1
- from picographics import PicoGraphics , DISPLAY_TUFTY_2040 , PEN_RGB332
2
- from os import listdir
3
- import time
1
+ # Tufty2040 boot menu/loader.
2
+
4
3
import gc
4
+ import time
5
+ from os import listdir
6
+ from picographics import PicoGraphics , DISPLAY_TUFTY_2040 , PEN_RGB332
5
7
from pimoroni import Button
6
8
7
- display = PicoGraphics (display = DISPLAY_TUFTY_2040 , pen_type = PEN_RGB332 , rotate = 180 )
8
-
9
9
10
- def hsv_to_rgb (h , s , v ) :
10
+ def hsv_to_rgb (h : float , s : float , v : float ) -> tuple [ float , float , float ] :
11
11
if s == 0.0 :
12
12
return v , v , v
13
13
i = int (h * 6.0 )
@@ -34,7 +34,7 @@ def hsv_to_rgb(h, s, v):
34
34
return v , p , q
35
35
36
36
37
- def get_applications ():
37
+ def get_applications () -> list [ dict [ str , str ]] :
38
38
# fetch a list of the applications that are stored in the filesystem
39
39
applications = []
40
40
for file in listdir ():
@@ -54,98 +54,102 @@ def get_applications():
54
54
return sorted (applications , key = lambda x : x ["title" ])
55
55
56
56
57
- def launch_application ( application ) :
57
+ def prepare_for_launch () -> None :
58
58
for k in locals ().keys ():
59
- if k not in ("gc" , "file" , "badger_os" ):
59
+ if k not in ("__name__" ,
60
+ "application_file_to_launch" ,
61
+ "gc" ):
60
62
del locals ()[k ]
61
-
62
63
gc .collect ()
63
64
64
- __import__ (application ["file" ])
65
-
66
-
67
- applications = get_applications ()
68
-
69
- button_up = Button (22 , invert = False )
70
- button_down = Button (6 , invert = False )
71
- button_a = Button (7 , invert = False )
72
65
73
- display .set_backlight (1.0 )
66
+ def menu () -> str :
67
+ applications = get_applications ()
74
68
75
- WHITE = display . create_pen ( 255 , 255 , 255 )
76
- BLACK = display . create_pen ( 0 , 0 , 0 )
77
- RED = display . create_pen ( 200 , 0 , 0 )
69
+ button_up = Button ( 22 , invert = False )
70
+ button_down = Button ( 6 , invert = False )
71
+ button_a = Button ( 7 , invert = False )
78
72
73
+ display = PicoGraphics (display = DISPLAY_TUFTY_2040 , pen_type = PEN_RGB332 )
74
+ display .set_backlight (1.0 )
79
75
80
- def text ( text , x , y , pen , s ):
81
- display . set_pen ( pen )
82
- display . text ( text , x , y , - 1 , s )
76
+ selected_item = 2
77
+ scroll_position = 2
78
+ target_scroll_position = 2
83
79
80
+ selected_pen = display .create_pen (255 , 255 , 255 )
81
+ unselected_pen = display .create_pen (80 , 80 , 100 )
82
+ background_pen = display .create_pen (50 , 50 , 70 )
83
+ shadow_pen = display .create_pen (0 , 0 , 0 )
84
84
85
- selected_item = 2
86
- scroll_position = 2
87
- target_scroll_position = 2
85
+ while True :
86
+ t = time .ticks_ms () / 1000.0
88
87
89
- selected_pen = display .create_pen (255 , 255 , 255 )
90
- unselected_pen = display .create_pen (80 , 80 , 100 )
91
- background_pen = display .create_pen (50 , 50 , 70 )
92
- shadow_pen = display .create_pen (0 , 0 , 0 )
88
+ if button_up .read ():
89
+ target_scroll_position -= 1
90
+ target_scroll_position = target_scroll_position if target_scroll_position >= 0 else len (applications ) - 1
93
91
94
- while True :
95
- t = time .ticks_ms () / 1000.0
92
+ if button_down .read ():
93
+ target_scroll_position += 1
94
+ target_scroll_position = target_scroll_position if target_scroll_position < len (applications ) else 0
96
95
97
- if button_up .read ():
98
- target_scroll_position -= 1
99
- target_scroll_position = target_scroll_position if target_scroll_position >= 0 else len (applications ) - 1
96
+ if button_a .read ():
97
+ # Wait for the button to be released.
98
+ while button_a .is_pressed :
99
+ time .sleep (0.01 )
100
100
101
- if button_down .read ():
102
- target_scroll_position += 1
103
- target_scroll_position = target_scroll_position if target_scroll_position < len (applications ) else 0
101
+ return applications [selected_item ]["file" ]
104
102
105
- if button_a . read ():
106
- launch_application ( applications [ selected_item ] )
103
+ display . set_pen ( background_pen )
104
+ display . clear ( )
107
105
108
- display .set_pen (background_pen )
109
- display .clear ()
106
+ scroll_position += (target_scroll_position - scroll_position ) / 5
110
107
111
- scroll_position += (target_scroll_position - scroll_position ) / 5
108
+ grid_size = 40
109
+ for y in range (0 , 240 // grid_size ):
110
+ for x in range (0 , 320 // grid_size ):
111
+ h = x + y + int (t * 5 )
112
+ h = h / 50.0
113
+ r , g , b = hsv_to_rgb (h , 0.5 , 1 )
112
114
113
- grid_size = 40
114
- for y in range (0 , 240 / grid_size ):
115
- for x in range (0 , 320 / grid_size ):
116
- h = x + y + int (t * 5 )
117
- h = h / 50.0
118
- r , g , b = hsv_to_rgb (h , .5 , 1 )
115
+ display .set_pen (display .create_pen (r , g , b ))
116
+ display .rectangle (x * grid_size , y * grid_size , grid_size , grid_size )
119
117
120
- display . set_pen ( display . create_pen ( r , g , b ) )
121
- display . rectangle ( x * grid_size , y * grid_size , grid_size , grid_size )
118
+ # work out which item is selected (closest to the current scroll position )
119
+ selected_item = round ( target_scroll_position )
122
120
123
- # work out which item is selected (closest to the current scroll position)
124
- selected_item = round ( target_scroll_position )
121
+ for list_index , application in enumerate ( applications ):
122
+ distance = list_index - scroll_position
125
123
126
- start = time . ticks_ms ()
124
+ text_size = 4 if selected_item == list_index else 3
127
125
128
- for list_index , application in enumerate (applications ):
129
- distance = list_index - scroll_position
126
+ # center text horixontally
127
+ title_width = display .measure_text (application ["title" ], text_size )
128
+ text_x = int (160 - title_width / 2 )
130
129
131
- text_size = 4 if selected_item == list_index else 3
130
+ row_height = text_size * 5 + 20
132
131
133
- # center text horixontally
134
- title_width = display .measure_text (application ["title" ], text_size )
135
- text_x = int (160 - title_width / 2 )
132
+ # center list items vertically
133
+ text_y = int (120 + distance * row_height - (row_height / 2 ))
136
134
137
- row_height = text_size * 5 + 20
135
+ # draw the text, selected item brightest and with shadow
136
+ if selected_item == list_index :
137
+ display .set_pen (shadow_pen )
138
+ display .text (application ["title" ], text_x + 1 , text_y + 1 , - 1 , text_size )
138
139
139
- # center list items vertically
140
- text_y = int (120 + distance * row_height - (row_height / 2 ))
140
+ text_pen = selected_pen if selected_item == list_index else unselected_pen
141
+ display .set_pen (text_pen )
142
+ display .text (application ["title" ], text_x , text_y , - 1 , text_size )
141
143
142
- # draw the text, selected item brightest and with shadow
143
- if selected_item == list_index :
144
- text (application ["title" ], text_x + 1 , text_y + 1 , shadow_pen , text_size )
144
+ display .update ()
145
145
146
- text_pen = selected_pen if selected_item == list_index else unselected_pen
147
- text (application ["title" ], text_x , text_y , text_pen , text_size )
148
146
149
- start = time .ticks_ms ()
147
+ # The application we will be launching. This should be ouronly global, so we can
148
+ # drop everything else.
149
+ application_file_to_launch = menu ()
150
150
151
- display .update ()
151
+ # Run whatever we've set up to.
152
+ # If this fails, we'll exit the script and drop to the REPL, which is
153
+ # fairly reasonable.
154
+ prepare_for_launch ()
155
+ __import__ (application_file_to_launch )
0 commit comments