66import signal
77import struct
88from datetime import datetime
9+ from enum import IntEnum
910from time import sleep
1011
1112import serial # Install pyserial : pip install pyserial
1920DISPLAY_HEIGHT = 480
2021
2122
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 ):
2350 RESET = 101
2451 CLEAR = 102
2552 SCREEN_OFF = 108
2653 SCREEN_ON = 109
2754 SET_BRIGHTNESS = 110
2855 DISPLAY_BITMAP = 197
56+ SET_ORIENTATION = 121
2957
3058
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 ):
3260 byteBuffer = bytearray (6 )
3361 byteBuffer [0 ] = (x >> 2 )
3462 byteBuffer [1 ] = (((x & 3 ) << 6 ) + (y >> 4 ))
@@ -61,10 +89,36 @@ def SetBrightness(ser: serial.Serial, level: int):
6189 SendReg (ser , Command .SET_BRIGHTNESS , level , 0 , 0 , 0 )
6290
6391
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+
64116def DisplayPILImage (ser : serial .Serial , image : Image , x : int , y : int ):
65117 image_height = image .size [1 ]
66118 image_width = image .size [0 ]
67119
120+ assert x <= getWidth (), 'Image X coordinate must be <= display width'
121+ assert y <= getHeight (), 'Image Y coordinate must be <= display height'
68122 assert image_height > 0 , 'Image width must be > 0'
69123 assert image_width > 0 , 'Image height must be > 0'
70124
@@ -82,7 +136,7 @@ def DisplayPILImage(ser: serial.Serial, image: Image, x: int, y: int):
82136 line += struct .pack ('H' , rgb )
83137
84138 # Send image data by multiple of DISPLAY_WIDTH bytes
85- if len (line ) >= DISPLAY_WIDTH * 8 :
139+ if len (line ) >= getWidth () * 8 :
86140 ser .write (line )
87141 line = bytes ()
88142
@@ -107,12 +161,14 @@ def DisplayText(ser: serial.Serial, text: str, x=0, y=0,
107161 # Convert text to bitmap using PIL and display it
108162 # Provide the background image path to display text with transparent background
109163
164+ assert x <= getWidth (), 'Text X coordinate must be <= display width'
165+ assert y <= getHeight (), 'Text Y coordinate must be <= display height'
110166 assert len (text ) > 0 , 'Text must not be empty'
111167 assert font_size > 0 , "Font size must be > 0"
112168
113169 if background_image is None :
114170 # 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 )
116172 else :
117173 # The text bitmap is created from provided background image : text with transparent background
118174 text_image = Image .open (background_image )
@@ -123,8 +179,8 @@ def DisplayText(ser: serial.Serial, text: str, x=0, y=0,
123179 d .text ((x , y ), text , font = font , fill = font_color )
124180
125181 # 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 () )))
128184
129185 DisplayPILImage (ser , text_image , x , y )
130186
@@ -138,8 +194,10 @@ def DisplayProgressBar(ser: serial.Serial, x: int, y: int, width: int, height: i
138194 # Generate a progress bar and display it
139195 # Provide the background image path to display progress bar with transparent background
140196
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'
143201 assert min_value <= value <= max_value , 'Progress bar value shall be between min and max'
144202
145203 if background_image is None :
@@ -155,11 +213,11 @@ def DisplayProgressBar(ser: serial.Serial, x: int, y: int, width: int, height: i
155213 # Draw progress bar
156214 bar_filled_width = value / (max_value - min_value ) * width
157215 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 )
159217
160218 if bar_outline :
161219 # 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 )
163221
164222 DisplayPILImage (ser , bar_image , x , y )
165223
@@ -184,13 +242,21 @@ def sighandler(signum, frame):
184242 lcd_comm = serial .Serial (COM_PORT , 115200 , timeout = 1 , rtscts = 1 )
185243
186244 # Clear screen (blank)
245+ SetOrientation (lcd_comm , Orientation .PORTRAIT ) # Bug: orientation needs to be PORTRAIT before clearing screen
187246 Clear (lcd_comm )
188247
189248 # Set brightness to max value
190249 SetBrightness (lcd_comm , 0 )
191250
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+
192258 # Display sample picture
193- DisplayBitmap (lcd_comm , "res/example.png" )
259+ DisplayBitmap (lcd_comm , background )
194260
195261 # Display sample text
196262 DisplayText (lcd_comm , "Basic text" , 50 , 100 )
@@ -203,18 +269,11 @@ def sighandler(signum, frame):
203269 background_color = (255 , 255 , 0 ))
204270
205271 # Display custom text with transparent background
206- DisplayText (lcd_comm , "Transparent bold text" , 5 , 300 ,
272+ DisplayText (lcd_comm , "Transparent bold text" , 5 , 250 ,
207273 font = "geforce/GeForce-Bold.ttf" ,
208274 font_size = 30 ,
209275 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 )
218277
219278 # Display the current time and some progress bars as fast as possible
220279 bar_value = 0
@@ -223,19 +282,19 @@ def sighandler(signum, frame):
223282 font = "roboto/Roboto-Bold.ttf" ,
224283 font_size = 20 ,
225284 font_color = (255 , 0 , 0 ),
226- background_image = "res/example.png" )
285+ background_image = background )
227286
228287 DisplayProgressBar (lcd_comm , 10 , 40 ,
229288 width = 140 , height = 30 ,
230289 min_value = 0 , max_value = 100 , value = bar_value ,
231290 bar_color = (255 , 255 , 0 ), bar_outline = True ,
232- background_image = "res/example.png" )
291+ background_image = background )
233292
234293 DisplayProgressBar (lcd_comm , 160 , 40 ,
235294 width = 140 , height = 30 ,
236295 min_value = 0 , max_value = 19 , value = bar_value % 20 ,
237296 bar_color = (0 , 255 , 0 ), bar_outline = False ,
238- background_image = "res/example.png" )
297+ background_image = background )
239298
240299 bar_value = (bar_value + 2 ) % 101
241300
0 commit comments