-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdisplayText.py
153 lines (110 loc) · 4.21 KB
/
displayText.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# New version for CircuitPython on a microcontroller - (c)2024
# Now packaged as a class, with single-character mode
# based on
# displayText.py
# (c)2020 robcranfill@gmail.com
#
import board
import time
from adafruit_ht16k33.matrix import Matrix8x8
import led8x8Font
class LEDMatrixDisplay:
def __init__(self) -> None:
pass
# For the string, create the big list of bit values (columns), left to right.
#
def makeVRasters(self, string):
if len(string) == 0: # is there a better way to handle this null-input case? needed?
string = " "
else:
# duplicate the first char onto the end of the data for easier scrolling. TODO: needed?
string += string[0]
bits = []
for char in string:
# bl is the list of *horizontal* rasters for the char
bl = self.byteListForChar(char)
for bitIndex in range(7,-1,-1):
thisVR = 0
for hRasterIndex in range(7,-1,-1):
bitVal = ((1 << bitIndex) & bl[hRasterIndex])
if bitVal > 0:
thisVR += (1 << (7-hRasterIndex))
bits.append(thisVR)
# print(f"vraster (len {len(bits)}): {bits}")
return bits
# Rotate the list of vertical rasters thru the display, forever.
# The input data already has the first char duplicated at the end, for ease of rotation.
#
# display for 'main_timeout' seconds; if zero, forever
#
def display_for_a_while(self, matrix, vrs, raster_delay, main_timeout):
# display all 8 of the first char; after that,
# rotate old ones and repaint only the new, rightmost, raster.
self.display_raster(matrix, vrs[0:8])
end_sec = time.time() + main_timeout
print(f"display_for_a_while will time out in {main_timeout} seconds")
while True:
# this is dependent on the display rotation. FIXME
matrix.shift(0, -1)
# get the proper 8x8 bits to display
for i in range(len(vrs)-8):
self.display_raster(matrix, vrs[i:i+8])
time.sleep(raster_delay)
if main_timeout > 0:
if time.time() > end_sec:
print(f"display_for_a_while timeout!")
return
# Shift the existing pixels left 1, then paint the new rightmost raster.
# This is slightly funky because I have my 8x8 matrix mounted sideways - YMMV!
#
def display_raster(self, matrix, rasters):
matrix.shift(0, -1)
i = 7 # the rightmost scanline
for j in range(8):
matrix[j, i] = rasters[i] & (1<<j)
# Return a list of the bytes for the given character.
# TODO: catch missing chars?
#
def byteListForChar(self, char):
bits = led8x8Font.FontData[char]
return bits
# The money method.
# This method never returns.
# NOT SURE HOW DO MAKE THIS UPDATE-ABLE.
# FIXME TODO
#
def display_scrolling_text(self, string, raster_delay, display_timeout):
i2c = board.STEMMA_I2C()
matrix = Matrix8x8(i2c)
matrix.brightness = 1
# matrix.fill(1)
# time.sleep(1)
matrix.fill(0)
# time.sleep(1)
rasters = self.makeVRasters(string)
# print(f"vertical rasters: {rasters}")
self.display_for_a_while(matrix, rasters, raster_delay, display_timeout)
# Display a single character and return.
#
def display_single_char(self, char):
i2c = board.STEMMA_I2C()
matrix = Matrix8x8(i2c)
matrix.brightness = 1
rasters = self.makeVRasters(char)
# print(f"vertical rasters: {rasters}")
for i in range(8):
for j in range(8):
matrix[j, i] = rasters[i] & (1<<j)
# for command-line testing.
# for testing in CP, just do the following in code.py.
#
if __name__ == "__main__":
# scrolling
lmd = LEDMatrixDisplay()
lmd.display_scrolling_text(" Wind 8MPH; Temp 64F - ", 0.01, 0)
# single char at a time
import time, random
while True:
c = str(random.choice(range(10)))
lmd.display_single_char(c)
time.sleep(1)