Skip to content

Commit e9b24dc

Browse files
authored
Merge pull request #27 from gerph/different-protocol
Implementation of the protocol in the different model of smart screen.
2 parents c8ecaa8 + 6a4a586 commit e9b24dc

File tree

1 file changed

+115
-16
lines changed

1 file changed

+115
-16
lines changed

main.py

Lines changed: 115 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,39 @@
1414
# Set your COM port e.g. COM3 for Windows, /dev/ttyACM0 for Linux...
1515
COM_PORT = "/dev/ttyACM0"
1616
# COM_PORT = "COM5"
17+
# MacOS COM port:
18+
COM_PORT = '/dev/cu.usbmodem2017_2_251'
19+
20+
# The new device has a serial number of '2017-2-25'
1721

1822
DISPLAY_WIDTH = 320
1923
DISPLAY_HEIGHT = 480
2024

2125

26+
class TuringError(Exception):
27+
pass
28+
29+
2230
class Command:
23-
RESET = 101
24-
CLEAR = 102
25-
SCREEN_OFF = 108
26-
SCREEN_ON = 109
27-
SET_BRIGHTNESS = 110
28-
DISPLAY_BITMAP = 197
31+
# Old protocol (6 byte packets, command in final byte)
32+
#RESET = 101
33+
#CLEAR = 102
34+
#SCREEN_OFF = 108
35+
#SCREEN_ON = 109
36+
#SET_BRIGHTNESS = 110
37+
#DISPLAY_BITMAP = 197
38+
39+
# New protocol (10 byte packets, framed with the command, 8 data bytes inside)
40+
HELLO = 0xCA
41+
ORIENTATION = 0xCB
42+
ORIENTATION_PORTRAIT = 0
43+
ORIENTATION_LANDSCAPE = 1
44+
# The device seems to start in PORTRAIT, with the row ordering reversed from
45+
# the ORIENTATION_PORTRAIT setting. It is not clear how to restore the ordering
46+
# to the reset configuration.
47+
DISPLAY_BITMAP = 0xCC
48+
LIGHTING = 0xCD
49+
SET_BRIGHTNESS = 0xCE
2950

3051

3152
def SendReg(ser: serial.Serial, cmd: int, x: int, y: int, ex: int, ey: int):
@@ -39,26 +60,83 @@ def SendReg(ser: serial.Serial, cmd: int, x: int, y: int, ex: int, ey: int):
3960
ser.write(bytes(byteBuffer))
4061

4162

42-
def Reset(ser: serial.Serial):
43-
SendReg(ser, Command.RESET, 0, 0, 0, 0)
63+
def SendCommand(ser: serial.Serial, cmd: int, payload=None):
64+
if payload is None:
65+
payload = [0] * 8
66+
elif len(payload) < 8:
67+
payload = list(payload) + [0] * (8 - len(payload))
68+
69+
byteBuffer = bytearray(10)
70+
byteBuffer[0] = cmd
71+
byteBuffer[1] = payload[0]
72+
byteBuffer[2] = payload[1]
73+
byteBuffer[3] = payload[2]
74+
byteBuffer[4] = payload[3]
75+
byteBuffer[5] = payload[4]
76+
byteBuffer[6] = payload[5]
77+
byteBuffer[7] = payload[6]
78+
byteBuffer[8] = payload[7]
79+
byteBuffer[9] = cmd
80+
print("Sending %r" % (byteBuffer,))
81+
ser.write(bytes(byteBuffer))
82+
83+
84+
def Hello(ser: serial.Serial):
85+
hello = [ord('H'), ord('E'), ord('L'), ord('L'), ord('O')]
86+
SendCommand(ser, Command.HELLO, payload=hello)
87+
response = ser.read(10)
88+
if len(response) != 10:
89+
raise TuringError("Device not recognised (short response to HELLO)")
90+
if response[0] != Command.HELLO or response[-1] != Command.HELLO:
91+
raise TuringError("Device not recognised (bad framing)")
92+
if [x for x in response[1:6]] != hello:
93+
raise TuringError("Device not recognised (No HELLO; got %r)" % (response[1:6],))
94+
# The HELLO response here is followed by:
95+
# 0x0A, 0x12, 0x00
96+
# It is not clear what these might be.
97+
# It would be handy if these were a version number, or a set of capability
98+
# flags. The 0x0A=10 being version 10 or 0.10, and the 0x12 being the size or the
99+
# indication that a backlight is present, would be nice. But that's guessing
100+
# based on how I'd do it.
44101

45102

46103
def Clear(ser: serial.Serial):
47-
SendReg(ser, Command.CLEAR, 0, 0, 0, 0)
104+
# Unknown what command this is
105+
print("Clear unknown")
106+
# Cannot find a 'clear' command
107+
#SendReg(ser, Command.CLEAR, 0, 0, 0, 0)
108+
109+
110+
def Orientation(ser: serial.Serial, state: int):
111+
print("Orientation: %r" % (state,))
112+
SendCommand(ser, Command.ORIENTATION, payload=[state])
113+
114+
115+
def SetLighting(ser: serial.Serial, red: int, green: int, blue: int):
116+
print("Lighting: %i, %i, %i" % (red, green, blue))
117+
assert red < 256, 'Red lighting must be < 256'
118+
assert green < 256, 'Green lighting must be < 256'
119+
assert blue < 256, 'Blue lighting must be < 256'
120+
SendCommand(ser, Command.LIGHTING, payload=[red, green, blue])
48121

49122

50123
def ScreenOff(ser: serial.Serial):
51-
SendReg(ser, Command.SCREEN_OFF, 0, 0, 0, 0)
124+
print("Screen off unknown")
125+
# Cannot find a 'screen off' command
126+
#SendReg(ser, Command.SCREEN_OFF, 0, 0, 0, 0)
52127

53128

54129
def ScreenOn(ser: serial.Serial):
55-
SendReg(ser, Command.SCREEN_ON, 0, 0, 0, 0)
130+
print("Screen on unknown")
131+
# Cannot find a 'screen on' command
132+
#SendReg(ser, Command.SCREEN_ON, 0, 0, 0, 0)
56133

57134

58135
def SetBrightness(ser: serial.Serial, level: int):
59136
# Level : 0 (brightest) - 255 (darkest)
60137
assert 255 >= level >= 0, 'Brightness level must be [0-255]'
61-
SendReg(ser, Command.SET_BRIGHTNESS, level, 0, 0, 0)
138+
# New protocol has 255 as the brightest, and 0 as off.
139+
SendCommand(ser, Command.SET_BRIGHTNESS, payload=[255-level])
62140

63141

64142
def DisplayPILImage(ser: serial.Serial, image: Image, x: int, y: int):
@@ -68,7 +146,14 @@ def DisplayPILImage(ser: serial.Serial, image: Image, x: int, y: int):
68146
assert image_height > 0, 'Image width must be > 0'
69147
assert image_width > 0, 'Image height must be > 0'
70148

71-
SendReg(ser, Command.DISPLAY_BITMAP, x, y, x + image_width - 1, y + image_height - 1)
149+
(x0, y0) = (x, y)
150+
(x1, y1) = (x + image_width - 1, y + image_height - 1)
151+
152+
SendCommand(ser, Command.DISPLAY_BITMAP,
153+
payload=[(x0>>8) & 255, x0 & 255,
154+
(y0>>8) & 255, y0 & 255,
155+
(x1>>8) & 255, x1 & 255,
156+
(y1>>8) & 255, y1 & 255])
72157

73158
pix = image.load()
74159
line = bytes()
@@ -78,7 +163,15 @@ def DisplayPILImage(ser: serial.Serial, image: Image, x: int, y: int):
78163
G = pix[w, h][1] >> 2
79164
B = pix[w, h][2] >> 3
80165

81-
rgb = (R << 11) | (G << 5) | B
166+
# Original: 0bRRRRRGGGGGGBBBBB
167+
# fedcba9876543210
168+
# New: 0bgggBBBBBRRRRRGGG
169+
# That is...
170+
# High 3 bits of green in b0-b2
171+
# Low 3 bits of green in b13-b15
172+
# Red 5 bits in b3-b7
173+
# Blue 5 bits in b8-b12
174+
rgb = (B << 8) | (G>>3) | ((G&7)<<13) | (R<<3)
82175
line += struct.pack('H', rgb)
83176

84177
# Send image data by multiple of DISPLAY_WIDTH bytes
@@ -183,12 +276,18 @@ def sighandler(signum, frame):
183276
# Do not change COM port settings unless you know what you are doing
184277
lcd_comm = serial.Serial(COM_PORT, 115200, timeout=1, rtscts=1)
185278

186-
# Clear screen (blank)
187-
Clear(lcd_comm)
279+
# Hello! to check this is the right device
280+
Hello(lcd_comm)
281+
282+
# Data orientation
283+
Orientation(lcd_comm, Command.ORIENTATION_PORTRAIT)
188284

189285
# Set brightness to max value
190286
SetBrightness(lcd_comm, 0)
191287

288+
# Lighting (a purple)
289+
SetLighting(lcd_comm, 128, 50, 112)
290+
192291
# Display sample picture
193292
DisplayBitmap(lcd_comm, "res/example.png")
194293

0 commit comments

Comments
 (0)