Skip to content

Commit 5df1321

Browse files
committed
Consolidate Function with ili9341 support
1 parent 8a2759d commit 5df1321

File tree

1 file changed

+341
-5
lines changed

1 file changed

+341
-5
lines changed

hardware/screen_runner.py

Lines changed: 341 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,357 @@
22
""" the all the app runner needs to do is import one variable: 'display' """
33

44
""" All Devices Need These """
5+
from bbapp.version import version
56
from .config import screen
7+
from .font_runner import sm_font, score_font, date_font
8+
from .ili9341 import color565
69

710
""" Break Down of Individual Personalities """
811
if 'ili' in screen:
912

1013
from .ili9341_runner import display
11-
14+
white=color565(255,255,255)
15+
drk_grn=color565(50,100,30)
16+
red=color565(255, 0, 0)
17+
black=color565(0, 0, 0)
18+
def check_upgrade():
19+
return False
20+
1221
elif screen == "lilygo_watch":
1322

1423
from .lilygo_watch_1_54_inch import display
24+
def check_upgrade():
25+
return False
26+
27+
if 'esp32-s3-box' in screen:
28+
29+
from machine import ADC, Pin
30+
adc = ADC(Pin(1))
31+
32+
if screen == 'esp32-s3-box-lite':
33+
34+
from .espboxlite import display
35+
36+
""" BOX-LITE specifics """
37+
#NOTE: S3-ESP32-BOX-LITE - INVERTED w/ili9341
38+
drk_grn=color565(255,222,255)
39+
white=color565(0, 0, 0)
40+
black=color565(255,255,255)
41+
yellow=color565(255, 0, 0)
42+
green=color565(0,0,255)
43+
pink=color565(0, 255, 0)
44+
45+
def check_upgrade():
46+
""" We only check Button 3 - It's on GPIO01
47+
#Unpushed
48+
>>> adc.read_u16()
49+
65535
50+
51+
#Pushed
52+
>>> adc.read_u16()
53+
55261
54+
"""
55+
if str(adc.read_u16()).startswith('55'):
56+
return True
57+
58+
if screen == 'esp32-s3-box':
59+
60+
from .espbox import display
61+
62+
drk_grn=color565(58, 124, 14) # esp full box
63+
black=color565(0, 0, 0)
64+
white=color565(255,255,255)
65+
yellow=color565(255, 0, 0)
66+
green=color565(0,0,255)
67+
pink=color565(0, 255, 0)
68+
red = color565(255, 0, 0)
69+
70+
def check_upgrade():
71+
""" We only check the Mute Button on the ESP BOX - It's on GPIO01
72+
#Unpushed:
73+
>>>adc.read_u16()
74+
65535
75+
76+
#Pushed
77+
>>> adc.read_u16()
78+
0
79+
"""
80+
if adc.read_u16() == 0:
81+
return True
82+
83+
""" How many chars per line before you hit the end """
84+
anum = {'r': '36', 'Y': '19', 'Z': '22', 'y': '27', 'x': '27', 'z': '27', 'E':'21',
85+
'D': '19', 'G': '18', 'F': '22', 'A': '21', 'C': '19', 'B': '21', 'M':'18',
86+
'L': '25', 'O': '17', 'N': '21', 'I': '65', 'H': '21', 'K': '19', 'J': '30',
87+
'U': '21', 'T': '22', 'W': '14', 'V': '21', 'Q': '17', 'P': '21', 'S': '21',
88+
'R': '19', 'e': '25', 'd': '25', 'g': '25', 'f': '41', 'a': '25', 'X': '21',
89+
'c': '27', 'b': '23', 'm': '17', 'l': '65', 'o': '25', 'n': '25', 'i': '65',
90+
'h': '25', 'k': '25', 'j': '65', 'u': '25', 't': '41', 'w': '18', 'v': '27',
91+
'q': '25', 'p': '23', 's': '27'}
92+
93+
""" How many pixels/char, rounded up (/320) """
94+
apnt3 = {'.':10, 0:13, 1:10, 2:13, 3:13, 4:13, 5:13, 6:13, 7:13, 8:13, 9:13, '-':12,
95+
"'":5, ' ': 19, 'r': 8, 'X': 15, 'Z': 14, 'y': 11, 'x': 11, 'z': 11,
96+
'E': 15, 'D': 16, 'G': 17, 'F': 14, 'A': 15, 'C': 16, 'B': 15, 'M': 17,
97+
'L': 12, 'O': 18, 'N': 15, 'I': 4, 'H': 15, 'K': 16, 'J': 10, 'U': 15,
98+
'T': 14, 'W': 22, 'V': 15, 'Q': 18, 'P': 15, 'S': 15, 'R': 16, 'e': 12,
99+
'd': 12, 'g': 12, 'f': 7, 'Y': 16, 'a': 12, 'c': 11, 'b': 13, 'm': 18,
100+
'l': 4, 'o': 12, 'n': 12, 'i': 4, 'h': 12, 'k': 12, 'j': 4, 'u': 12,
101+
't': 7, 'w': 17, 'v': 11, 'q': 12, 'p': 13, 's': 11}
102+
103+
""" How many pixels/char, rounded up (/240) """
104+
apnt2 = {'K': 18, 'J': 11, 'U': 15, 'T': 15, 'W': 22, 'V': 16, 'Q': 19, 'P': 15,
105+
'S': 15, 'R': 16, 'Z': 15, 'Y': 16, 'E': 15, 'D': 18, 'G': 18, 'F': 15,
106+
'A': 16, 'X': 16, 'C': 18, 'B': 15, 'M': 19, 'L': 14, 'O': 19, 'N': 15,
107+
'I': 6, 'H': 15, 't': 7, 'w': 18, 'v': 12, 'q': 12, 'p': 13, 's': 12,
108+
'r': 9, 'z': 11, 'y': 12, 'e': 13, 'd': 12, 'g': 12, 'f': 8, 'a': 13,
109+
'x': 11, 'c': 12, 'b': 13, 'm': 19, 'l': 5, 'o': 13, 'n': 13, 'i': 5,
110+
'h': 13, 'k': 13, 'j': 5, 'u': 13, 0: 14, 1: 10, 2: 13, 3: 14, 4: 14,
111+
5:14, 6: 14, 7: 14, 8: 14, 9: 14, "'": 4, '-': 8, ' ': 14, '.': 6}
112+
113+
def draw_outline_box():
114+
display.draw_vline(0, 0, 240, white)
115+
display.draw_vline(319, 0, 240, white)
116+
display.draw_hline(0, 0, 320, white)
117+
display.draw_hline(0, 40, 320, white)
118+
display.draw_hline(0, 239, 320, white)
119+
120+
def clear_fill():
121+
display.clear()
122+
display.fill_rectangle(0,0, 320, 240, drk_grn)
123+
124+
def fresh_box():
125+
display.clear_fill()
126+
display.draw_outline_box()
127+
128+
def print_setup(boot_stage):
129+
clear_fill()
130+
draw_outline_box()
131+
display.draw_text(5, 8, f"{boot_stage}" , date_font, white, drk_grn)
132+
display.draw_text(5, 65, 'BB Kiosk' , date_font, white, drk_grn)
133+
display.draw_text(5, 105, f"Version {version}" , date_font, white, drk_grn)
134+
135+
def crash_burn(err):
136+
display.fresh_box()
137+
print(f"=={err}")
138+
display.draw_text(5, 5, err, date_font, white, drk_grn)
139+
time.sleep(5)
140+
import machine
141+
machine.reset()
15142

16-
elif screen == 'esp32-s3-box-lite':
143+
def get_tb_text(err):
144+
"""
145+
Credit https://forums.openmv.io/t/how-can-i-get-the-line-number-of-error/6145
146+
"""
147+
import io
148+
import sys
149+
buf = io.StringIO()
150+
sys.print_exception(err, buf)
151+
#Remove the word Traceback/etc
152+
print(buf.getvalue()[35:])
153+
return buf.getvalue()[35:]
154+
155+
def scroll_print(text='NA',x_pos=5, y_pos=5, scr_len=30,
156+
Error=False, clear=True, font=sm_font,
157+
bg=drk_grn, fg=white, debug=False):
158+
""" Given a headline from a text string from mlb.com/news like:
17159
18-
from .espboxlite import display
160+
'Celebrate Aaron's birthday with 13 stats that show his greatness'
161+
162+
We need to break it into grouping like this:
163+
164+
["Celebrate Aaron's", 'birthday with 13', 'stats that show his', 'greatness']
165+
166+
...but do so in a way that does not step outside the character/pixel limits """
167+
168+
169+
""" We will pass in a 'text container' which will be either
170+
and instance of an error or a string """
171+
if clear:
172+
display.fresh_box()
19173

20-
elif screen == 'esp32-s3-box':
174+
""" 5 is already tight, 6 partly off the screen """
175+
max_rows = 6
176+
scr_len = scr_len
177+
178+
def proc_text(text):
179+
""" Here's where we do the processing of the 'text' """
180+
181+
def get_raw_parts(_text):
182+
""" Split 'text' to list[] in scr_len increments as a first pass
183+
return a list of 'raw' parts like this:
184+
["Celebrate Aaron's", "birthday with 13 s","tats that show his greatness"] """
185+
return [ _text[i : i + scr_len] for i in range(0, len(_text), scr_len)]
186+
187+
def mv_parts(text):
188+
""" Cycle through / Get the 'raw' 'parts' of 'text', convert each to a list.
189+
Then align() each item/push characters to the next part if needed.
190+
191+
Return a list of strings that do no 'run on', but still need to be processed for length.
192+
Ex. ["Celebrate Aaron's ", 'birthday with 13 ', 'stats that show his', ' greatness'] """
193+
194+
print(f"Text: {text}") if debug else None
195+
raw_parts = get_raw_parts(text)
196+
197+
if debug:
198+
for _each in raw_parts:
199+
print(f"Raw Part: {_each} - Raw tsum: {get_tsum(_each)}")
200+
201+
max_num_raw_parts = len(raw_parts)-2
202+
start=0
203+
while start <= max_num_raw_parts:
204+
"""Convert Text parts to lists to be able to pop easily """
205+
t1=list(raw_parts[start])
206+
t2=list(raw_parts[start+1])
207+
""" Move upstream through raw_parts align()ing to a new list as you go """
208+
raw_parts[start], raw_parts[start+1] = align(t1,t2)
209+
print(f"Parts after round {start} {raw_parts}") if debug else None
210+
start+=1
211+
return raw_parts
212+
213+
def align(_t1, _t2):
214+
""" Given the first 2 portions of the text converted to lists,
215+
see if the end of the 1st list and the start of the 2nd list are
216+
alphanumeric, if so push text to avoid a broken word on the screen
217+
218+
Ex.
219+
['W', 'h', 'i', 't', 'e', 'S']['o', 'x', ' ', 'a', 'c', 'q', 'u', 'i', 'r', 'e']
220+
to
221+
['W', 'h', 'i', 't', 'e']['S','o', 'x', ' ', 'a', 'c', 'q', 'u', 'i', 'r', 'e']
222+
223+
then return a tuple of strings:
224+
225+
226+
"""
227+
if run_on(_t1, _t2):
228+
_t2.insert(0,_t1.pop(-1))
229+
_t1, _t2 = align(_t1,_t2)
230+
return ''.join(_t1), ''.join(_t2)
231+
232+
233+
def run_on(_t1, _t2):
234+
""" check for align() """
235+
if _t1[-1] != ' ' and _t2[0] != ' ':
236+
return True
237+
return False
238+
239+
240+
def get_tsum(thing, def_size=15):
241+
""" Given the footprint of each character, return the sum(), "tsum" of it
242+
whether it's a string or a list, to determine how to postion the text """
243+
if isinstance(thing, list):
244+
return sum([ apnt2.get(x,def_size) for x in ' '.join(thing)])
245+
if isinstance(thing, str):
246+
return sum([ apnt2.get(x,def_size) for x in thing ])
247+
248+
def rm_space(_parts):
249+
""" rm final / inital spaces of each part of given list """
250+
[ x.pop() for x in _parts if x[-1] == ' ' ]
251+
[ x.pop(0) for x in _parts if x[0] == ' ' ]
252+
return _parts
253+
254+
def sw_parts(parts):
255+
""" Swap parts like
256+
from ['One series to ', "circle on each team's ", "schedule in '23" ]
257+
to
258+
['One series to ', "circle on each ", " team's schedule in '23"]
259+
if their pixel footprint (tsum) breaks past the screen's max """
260+
261+
def bump(each, tsum):
262+
""" Insert strategically into a list (push to a non existing 'part'/list to create it)
263+
for the last 'each', or into an (already existing 'each'/list) inside a list """
264+
if tsum > max_x:
265+
print(f"over {max_x}") if debug else None
266+
if len(_pparts) == each+1:
267+
_pparts.insert(each+1,[_pparts[each].pop(-1)])
268+
else:
269+
_pparts[each+1].insert(0,_pparts[each].pop(-1))
270+
tsum = get_tsum(_pparts[each])
271+
print(f"New _pparts each {_pparts[each]} new tsum {tsum}") if debug else None
272+
bump(each, tsum)
273+
274+
""" Given the aligned parts(strings), convert each to list to rm space easily """
275+
_parts = [ list(x) for x in parts ]
276+
print(f"_parts list comp {_parts}") if debug else None
277+
278+
""" There is no need for beg/end spaces at all right now, rm them """
279+
_parts = rm_space(_parts)
280+
print(f"_parts list rm_space {_parts}") if debug else None
281+
282+
""" join them all back to get words back """
283+
_parts = [ ''.join(x) for x in _parts ]
284+
print(f"_parts Current joined {_parts}") if debug else None
285+
286+
""" make each part a list in a new candidate list for easy bumping of a full word/string """
287+
_pparts = [ x.split(' ') for x in _parts ]
288+
print(f"_pparts Current list cand to bump {_pparts}") if debug else None
289+
print(f"lp {len(_parts)}") if debug else None
290+
291+
max_x=230
292+
293+
for each in range(0, len(_parts)):
294+
if debug:
295+
print(f"---- Each {each}")
296+
print(f"-- each _parts {each}: {_parts[each]} { get_tsum(_parts[each]) }")
297+
print(f"-- each _pparts {each}: {_pparts[each]} { get_tsum(_pparts[each]) }")
298+
bump(each, get_tsum(_pparts[each]))
299+
300+
print(f"Final swapped but unjoined _pparts {_pparts}") if debug else None
301+
if debug:
302+
for each in _pparts:
303+
print(get_tsum(each))
304+
305+
_parts = [ ' '.join(x) for x in _pparts ]
306+
print(f"Final joined _parts {_parts}") if debug else None
307+
if debug:
308+
for each in _parts:
309+
print(get_tsum(each)) if debug else None
310+
311+
return _parts
312+
313+
return sw_parts(mv_parts(text))
21314

22-
from .espbox import display
315+
""" If an error instance, pull out the text other process the beast ... """
316+
317+
if Error:
318+
319+
_text = get_tb_text(text)
320+
print(f"_text: {text} type: {type(_text)}, len: {len(_text)}") if debug else None
321+
procd_parts = [ _text[-150:-125], _text[-125:-100],
322+
_text[-100:-75], _text[-75:-50],
323+
_text[-50:-25], _text[-25:-1] ]
324+
else:
325+
326+
procd_parts = proc_text(text)
327+
328+
329+
print(f"Final procd_parts parts {procd_parts}") if debug else None
330+
331+
count=0
332+
for each_text in procd_parts:
333+
""" sm font = 25, date font =30 """
334+
if count > max_rows:
335+
break
336+
else:
337+
display.draw_text(x_pos, y_pos, each_text, font=font, color=fg, background=bg)
338+
print(f"{each_text}") #This will be each story or the error message
339+
count+=1
340+
y_pos+=30
341+
342+
343+
344+
345+
display.draw_outline_box = draw_outline_box
346+
display.clear_fill = clear_fill
347+
display.print_setup = print_setup
348+
display.white = white
349+
display.drk_grn = drk_grn
350+
display.black = black
351+
display.sm_font = sm_font
352+
display.score_font = score_font
353+
display.date_font = date_font
354+
display.get_tb_text = get_tb_text
355+
display.scroll_print = scroll_print
356+
display.check_upgrade = check_upgrade
357+
display.fresh_box = fresh_box
358+
display.crash_burn = crash_burn

0 commit comments

Comments
 (0)