6
6
import signal
7
7
import struct
8
8
from datetime import datetime
9
+ from enum import IntEnum
9
10
from time import sleep
10
11
11
12
import serial # Install pyserial : pip install pyserial
19
20
DISPLAY_HEIGHT = 480
20
21
21
22
22
- class Command :
23
+ class Orientation (IntEnum ):
24
+ PORTRAIT = 0
25
+ LANDSCAPE = 2
26
+ REVERSE_PORTRAIT = 1
27
+ REVERSE_LANDSCAPE = 3
28
+
29
+
30
+ CUR_ORIENTATION = Orientation .PORTRAIT
31
+
32
+
33
+ def getWidth ():
34
+ global CUR_ORIENTATION
35
+ if CUR_ORIENTATION == Orientation .PORTRAIT or CUR_ORIENTATION == Orientation .REVERSE_PORTRAIT :
36
+ return DISPLAY_WIDTH
37
+ else :
38
+ return DISPLAY_HEIGHT
39
+
40
+
41
+ def getHeight ():
42
+ global CUR_ORIENTATION
43
+ if CUR_ORIENTATION == Orientation .PORTRAIT or CUR_ORIENTATION == Orientation .REVERSE_PORTRAIT :
44
+ return DISPLAY_HEIGHT
45
+ else :
46
+ return DISPLAY_WIDTH
47
+
48
+
49
+ class Command (IntEnum ):
23
50
RESET = 101
24
51
CLEAR = 102
25
52
SCREEN_OFF = 108
26
53
SCREEN_ON = 109
27
54
SET_BRIGHTNESS = 110
28
55
DISPLAY_BITMAP = 197
56
+ SET_ORIENTATION = 121
29
57
30
58
31
- def SendReg (ser : serial .Serial , cmd : int , x : int , y : int , ex : int , ey : int ):
59
+ def SendReg (ser : serial .Serial , cmd : Command , x : int , y : int , ex : int , ey : int ):
32
60
byteBuffer = bytearray (6 )
33
61
byteBuffer [0 ] = (x >> 2 )
34
62
byteBuffer [1 ] = (((x & 3 ) << 6 ) + (y >> 4 ))
@@ -61,10 +89,36 @@ def SetBrightness(ser: serial.Serial, level: int):
61
89
SendReg (ser , Command .SET_BRIGHTNESS , level , 0 , 0 , 0 )
62
90
63
91
92
+ def SetOrientation (ser : serial .Serial , orientation : Orientation ):
93
+ global CUR_ORIENTATION
94
+ CUR_ORIENTATION = orientation
95
+ width = getWidth ()
96
+ height = getHeight ()
97
+ x = 0
98
+ y = 0
99
+ ex = 0
100
+ ey = 0
101
+ byteBuffer = bytearray (11 )
102
+ byteBuffer [0 ] = (x >> 2 )
103
+ byteBuffer [1 ] = (((x & 3 ) << 6 ) + (y >> 4 ))
104
+ byteBuffer [2 ] = (((y & 15 ) << 4 ) + (ex >> 6 ))
105
+ byteBuffer [3 ] = (((ex & 63 ) << 2 ) + (ey >> 8 ))
106
+ byteBuffer [4 ] = (ey & 255 )
107
+ byteBuffer [5 ] = Command .SET_ORIENTATION
108
+ byteBuffer [6 ] = (CUR_ORIENTATION + 100 )
109
+ byteBuffer [7 ] = (width >> 8 )
110
+ byteBuffer [8 ] = (width & 255 )
111
+ byteBuffer [9 ] = (height >> 8 )
112
+ byteBuffer [10 ] = (height & 255 )
113
+ ser .write (bytes (byteBuffer ))
114
+
115
+
64
116
def DisplayPILImage (ser : serial .Serial , image : Image , x : int , y : int ):
65
117
image_height = image .size [1 ]
66
118
image_width = image .size [0 ]
67
119
120
+ assert x <= getWidth (), 'Image X coordinate must be <= display width'
121
+ assert y <= getHeight (), 'Image Y coordinate must be <= display height'
68
122
assert image_height > 0 , 'Image width must be > 0'
69
123
assert image_width > 0 , 'Image height must be > 0'
70
124
@@ -82,7 +136,7 @@ def DisplayPILImage(ser: serial.Serial, image: Image, x: int, y: int):
82
136
line += struct .pack ('H' , rgb )
83
137
84
138
# Send image data by multiple of DISPLAY_WIDTH bytes
85
- if len (line ) >= DISPLAY_WIDTH * 8 :
139
+ if len (line ) >= getWidth () * 8 :
86
140
ser .write (line )
87
141
line = bytes ()
88
142
@@ -107,12 +161,14 @@ def DisplayText(ser: serial.Serial, text: str, x=0, y=0,
107
161
# Convert text to bitmap using PIL and display it
108
162
# Provide the background image path to display text with transparent background
109
163
164
+ assert x <= getWidth (), 'Text X coordinate must be <= display width'
165
+ assert y <= getHeight (), 'Text Y coordinate must be <= display height'
110
166
assert len (text ) > 0 , 'Text must not be empty'
111
167
assert font_size > 0 , "Font size must be > 0"
112
168
113
169
if background_image is None :
114
170
# A text bitmap is created with max width/height by default : text with solid background
115
- text_image = Image .new ('RGB' , (DISPLAY_WIDTH , DISPLAY_HEIGHT ), background_color )
171
+ text_image = Image .new ('RGB' , (getWidth (), getHeight () ), background_color )
116
172
else :
117
173
# The text bitmap is created from provided background image : text with transparent background
118
174
text_image = Image .open (background_image )
@@ -123,8 +179,8 @@ def DisplayText(ser: serial.Serial, text: str, x=0, y=0,
123
179
d .text ((x , y ), text , font = font , fill = font_color )
124
180
125
181
# Crop text bitmap to keep only the text
126
- left , top , text_width , text_height = d .textbbox ((0 ,0 ), text , font = font )
127
- text_image = text_image .crop (box = (x , y , min (x + text_width , DISPLAY_WIDTH ) , min (y + text_height , DISPLAY_HEIGHT )))
182
+ left , top , text_width , text_height = d .textbbox ((0 , 0 ), text , font = font )
183
+ text_image = text_image .crop (box = (x , y , min (x + text_width , getWidth ()) , min (y + text_height , getHeight () )))
128
184
129
185
DisplayPILImage (ser , text_image , x , y )
130
186
@@ -138,8 +194,10 @@ def DisplayProgressBar(ser: serial.Serial, x: int, y: int, width: int, height: i
138
194
# Generate a progress bar and display it
139
195
# Provide the background image path to display progress bar with transparent background
140
196
141
- assert x + width <= DISPLAY_WIDTH , 'Progress bar width exceeds display width'
142
- assert y + height <= DISPLAY_HEIGHT , 'Progress bar height exceeds display height'
197
+ assert x <= getWidth (), 'Progress bar X coordinate must be <= display width'
198
+ assert y <= getHeight (), 'Progress bar Y coordinate must be <= display height'
199
+ assert x + width <= getWidth (), 'Progress bar width exceeds display width'
200
+ assert y + height <= getHeight (), 'Progress bar height exceeds display height'
143
201
assert min_value <= value <= max_value , 'Progress bar value shall be between min and max'
144
202
145
203
if background_image is None :
@@ -155,11 +213,11 @@ def DisplayProgressBar(ser: serial.Serial, x: int, y: int, width: int, height: i
155
213
# Draw progress bar
156
214
bar_filled_width = value / (max_value - min_value ) * width
157
215
draw = ImageDraw .Draw (bar_image )
158
- draw .rectangle ([0 , 0 , bar_filled_width - 1 , height - 1 ], fill = bar_color , outline = bar_color )
216
+ draw .rectangle ([0 , 0 , bar_filled_width - 1 , height - 1 ], fill = bar_color , outline = bar_color )
159
217
160
218
if bar_outline :
161
219
# Draw outline
162
- draw .rectangle ([0 , 0 , width - 1 , height - 1 ], fill = None , outline = bar_color )
220
+ draw .rectangle ([0 , 0 , width - 1 , height - 1 ], fill = None , outline = bar_color )
163
221
164
222
DisplayPILImage (ser , bar_image , x , y )
165
223
@@ -184,13 +242,21 @@ def sighandler(signum, frame):
184
242
lcd_comm = serial .Serial (COM_PORT , 115200 , timeout = 1 , rtscts = 1 )
185
243
186
244
# Clear screen (blank)
245
+ SetOrientation (lcd_comm , Orientation .PORTRAIT ) # Bug: orientation needs to be PORTRAIT before clearing screen
187
246
Clear (lcd_comm )
188
247
189
248
# Set brightness to max value
190
249
SetBrightness (lcd_comm , 0 )
191
250
251
+ # Set screen orientation
252
+ # SetOrientation(lcd_comm, Orientation.LANDSCAPE)
253
+
254
+ # Define background picture
255
+ background = "res/example.png"
256
+ # background = "res/example_landscape.jpg"
257
+
192
258
# Display sample picture
193
- DisplayBitmap (lcd_comm , "res/example.png" )
259
+ DisplayBitmap (lcd_comm , background )
194
260
195
261
# Display sample text
196
262
DisplayText (lcd_comm , "Basic text" , 50 , 100 )
@@ -203,18 +269,11 @@ def sighandler(signum, frame):
203
269
background_color = (255 , 255 , 0 ))
204
270
205
271
# Display custom text with transparent background
206
- DisplayText (lcd_comm , "Transparent bold text" , 5 , 300 ,
272
+ DisplayText (lcd_comm , "Transparent bold text" , 5 , 250 ,
207
273
font = "geforce/GeForce-Bold.ttf" ,
208
274
font_size = 30 ,
209
275
font_color = (255 , 255 , 255 ),
210
- background_image = "res/example.png" )
211
-
212
- # Display text that overflows
213
- DisplayText (lcd_comm , "Text overflow!" , 5 , 430 ,
214
- font = "roboto/Roboto-Bold.ttf" ,
215
- font_size = 60 ,
216
- font_color = (255 , 255 , 255 ),
217
- background_image = "res/example.png" )
276
+ background_image = background )
218
277
219
278
# Display the current time and some progress bars as fast as possible
220
279
bar_value = 0
@@ -223,19 +282,19 @@ def sighandler(signum, frame):
223
282
font = "roboto/Roboto-Bold.ttf" ,
224
283
font_size = 20 ,
225
284
font_color = (255 , 0 , 0 ),
226
- background_image = "res/example.png" )
285
+ background_image = background )
227
286
228
287
DisplayProgressBar (lcd_comm , 10 , 40 ,
229
288
width = 140 , height = 30 ,
230
289
min_value = 0 , max_value = 100 , value = bar_value ,
231
290
bar_color = (255 , 255 , 0 ), bar_outline = True ,
232
- background_image = "res/example.png" )
291
+ background_image = background )
233
292
234
293
DisplayProgressBar (lcd_comm , 160 , 40 ,
235
294
width = 140 , height = 30 ,
236
295
min_value = 0 , max_value = 19 , value = bar_value % 20 ,
237
296
bar_color = (0 , 255 , 0 ), bar_outline = False ,
238
- background_image = "res/example.png" )
297
+ background_image = background )
239
298
240
299
bar_value = (bar_value + 2 ) % 101
241
300
0 commit comments