-
Notifications
You must be signed in to change notification settings - Fork 1
/
ui.s
302 lines (261 loc) · 12.9 KB
/
ui.s
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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
;------------------------------------------------------------------------------
; UI module
; Ted John
; Version 1.0
; 23 April 2013
;
; Functions for interfacing with the LCD.
;
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
; MODULE_UI - structure for storing the UI variables
;------------------------------------------------------------------------------
RECORD
MODULE_UI_PROJECT WORD
MODULE_UI_SCROLL_SAVETICK WORD
MODULE_UI_TIME_SAVETICK WORD
MODULE_UI_LCD_SCROLLERS BYTE (LCD_SCROLLER_SIZE * 2)
MODULE_UI_BUFFER BYTE 256
MODULE_UI_LAST_KEYPAD_SCAN WORD
MODULE_UI_SIZE ALIAS
;------------------------------------------------------------------------------
; ui_init() - initialises the ui module
;
; I R0 - ui module address
; I R1 - project module address
;------------------------------------------------------------------------------
ui_init
PUSH {R0, R1, R2, R3, LR}
STR R1, [R0, #MODULE_UI_PROJECT]
MOV R2, #0
STR R2, [R0, #MODULE_UI_SCROLL_SAVETICK]
STR R2, [R0, #MODULE_UI_TIME_SAVETICK]
SVC SVC_LCD_CLEAR
SVC SVC_LCD_LIGHT
ADD R0, R0, #MODULE_UI_LCD_SCROLLERS
MOV R1, #0
BL lcd_scroller_init
ADD R0, R0, #LCD_SCROLLER_SIZE
MOV R1, #1
BL lcd_scroller_init
POP {R0, R1, R2, R3, PC}
;------------------------------------------------------------------------------
; ui_show_about() - shows the about screen / credits
;
; I R0 - ui module address
;------------------------------------------------------------------------------
ui_show_about_sz_top
DEFB "Music Player",0
ALIGN
ui_show_about_sz_bottom
DEFB "Ted John, 2013",0
ALIGN
ui_show_about
PUSH {R0, R1, LR}
ADD R0, R0, #MODULE_UI_LCD_SCROLLERS ; get top scroller
ADR R1, ui_show_about_sz_top ; set the top scroller text
BL lcd_scroller_set_text
ADD R0, R0, #LCD_SCROLLER_SIZE ; get bottom scroller
ADR R1, ui_show_about_sz_bottom ; set the bottom scroller text
BL lcd_scroller_set_text
POP {R0, R1, PC}
;------------------------------------------------------------------------------
; ui_track_changed() - called when the track has changed
;
; I R0 - ui_module address
;------------------------------------------------------------------------------
ui_track_changed
PUSH {R1, R2, R3, LR}
LDR R1, [R0, #MODULE_UI_PROJECT] ; get project module address
LDR R1, [R1, #MODULE_PROJECT_PLAYER] ; get player module address
PUSH {R0, R1, R2}
LDR R3, [R1, #MODULE_PLAYER_TRACK_NAME] ; get track name address
ADD R0, R0, #MODULE_UI_BUFFER ; get buffer address
LDR R1, [R1, #MODULE_PLAYER_TRACK_INDEX] ; get track index
ADD R1, R1, #1 ; make it base from 1
MOV R2, #0
BL int2str
MOV R1, #':' ; append colon
BL appendchar
ADD R0, R0, #1
MOV R1, #' ' ; append space
BL appendchar
ADD R0, R0, #1
MOV R1, R3 ; write track name
BL strcpy
POP {R0, R1, R2}
MOV R2, R0 ; preserve R0
ADD R0, R0, #MODULE_UI_LCD_SCROLLERS ; get top scroller
ADD R1, R2, #MODULE_UI_BUFFER
BL lcd_scroller_set_text ; set the top scroller text
MOV R0, R2 ; restore R0
BL ui_refresh_time ; update track info
POP {R1, R2, R3, PC}
;------------------------------------------------------------------------------
; ui_track_updated() - called when the track has updated, state or time
;
; I R0 - ui_module address
;------------------------------------------------------------------------------
ui_track_updated
PUSH {R1, R2, LR}
MOV R2, R0 ; preserve R0
ADD R0, R2, #MODULE_UI_TIME_SAVETICK
MOV R1, #250
BL has_elapsed_by
CMP R0, #FALSE
MOVNE R0, R2
BLNE ui_refresh_time ; refresh time and state
ADD R0, R2, #MODULE_UI_SCROLL_SAVETICK
MOV R1, #500
BL has_elapsed_by
CMP R0, #FALSE
BEQ ui_track_updated_return ; refresh time and state
ADD R0, R2, #MODULE_UI_LCD_SCROLLERS
BL lcd_scroller_update
ui_track_updated_return
MOV R0, R2 ; restore R0
POP {R1, R2, PC}
;------------------------------------------------------------------------------
; ui_refresh_time() - refresh the track time and state
;
; I R0 - ui_module address
;------------------------------------------------------------------------------
ui_refresh_time
PUSH {R0, R1, R2, R3, R4, LR}
LDR R1, [R0, #MODULE_UI_PROJECT] ; get project module address
LDR R1, [R1, #MODULE_PROJECT_PLAYER] ; get player module address
LDR R2, [R1, #MODULE_PLAYER_ELAPSED_TICKS]
ADD R3, R0, #MODULE_UI_BUFFER
PUSH {R0, R1}
MOV R4, R0 ; put ui module address in R4
MOV R0, R3 ; write the time
LDR R1, [R1, #MODULE_PLAYER_ELAPSED_TICKS]
BL ui_write_time
LDR R1, [R4, #MODULE_UI_PROJECT] ; write the current state
LDR R1, [R1, #MODULE_PROJECT_STATE]
BL ui_write_state
POP {R0, R1}
ADD R2, R0, #MODULE_UI_LCD_SCROLLERS ; get bottom scroller
ADD R2, R2, #LCD_SCROLLER_SIZE
MOV R0, R2 ; scroller
MOV R1, R3 ; string
BL lcd_scroller_set_text
POP {R0, R1, R2, R3, R4, PC}
;------------------------------------------------------------------------------
; ui_write_time() - write a time to a string
;
; IO R0 - destination string address (updated to end)
; I R1 - total milliseconds
;
; R1 - minutes
; R3 - seconds
;------------------------------------------------------------------------------
ui_write_time
PUSH {R1, R2, R3, LR}
MOV R3, R0 ; preserve R0
MOV R0, R1 ; get total seconds
MOV R1, #1000
BL udivision
MOV R1, #60 ; get minutes and seconds
BL udivision
MOV R1, R0
MOV R0, R3 ; restore R0
MOV R3, R2
MOV R2, #2 ; write minutes
BL int2str
MOV R1, #':' ; write colon
BL appendchar
ADD R0, R0, #1
MOV R1, R3 ; write seconds
BL int2str
POP {R1, R2, R3, PC}
;------------------------------------------------------------------------------
; ui_write_state() - write a state to a string
;
; IO R0 - destination string address (updated to end)
; I R1 - state
;------------------------------------------------------------------------------
ui_write_state_sz_stopped
DEFB " - stopped",0
ALIGN
ui_write_state_sz_playing
DEFB " - playing",0
ALIGN
ui_write_state
PUSH {R1, LR}
CMP R1, #STATE_PLAYING
ADREQ R1, ui_write_state_sz_playing
ADRNE R1, ui_write_state_sz_stopped
BL strcpy
BL strend
POP {R1, PC}
;------------------------------------------------------------------------------
; ui_handle_input()
;
; I R0 - ui_module address
;------------------------------------------------------------------------------
ui_handle_input
PUSH {R1, R2, R3, LR}
MOV R2, R0
SVC SVC_KEYPAD_SCAN ; scan the keyboard
MOV R1, R0
LDR R0, [R2, #MODULE_UI_LAST_KEYPAD_SCAN] ; get last scan
STR R1, [R2, #MODULE_UI_LAST_KEYPAD_SCAN] ; set last scan to new scan
BL keypad_get_new_presses ; get new presses
BL keypad_scan_read_index
CMP R1, #KEYPAD_NOBUTTON
BEQ ui_handle_input_return
CMP R1, #8
BLE ui_handle_input_track
CMP R1, #KEYPAD_IDX_ASTERISK
BEQ ui_handle_input_stop
CMP R1, #KEYPAD_IDX_0
BEQ ui_handle_input_about
CMP R1, #KEYPAD_IDX_HASH
BEQ ui_handle_input_play
B ui_handle_input_return
ui_handle_input_about
LDR R3, [R2, #MODULE_UI_PROJECT] ; get project module address
MOV R1, #STATE_ABOUT ; set about state
STR R1, [R3, #MODULE_PROJECT_STATE]
MOV R0, R2 ; show about page
BL ui_show_about
BL player_stop_all_channels ; stop any notes currently playing
B ui_handle_input_return
ui_handle_input_track
LDR R3, [R2, #MODULE_UI_PROJECT] ; get project module address
LDR R0, [R3, #MODULE_PROJECT_MUSIC] ; get music data address
LDR R0, [R0, #(tl_track_count-music_data)] ; get number of tracks
CMP R1, R0 ; check if track is out of range
BGE ui_handle_input_return
LDR R0, [R3, #MODULE_PROJECT_PLAYER] ; get player module address
BL player_load_track ; load the track
MOV R0, R2
BL ui_track_changed
LDR R1, [R3, #MODULE_PROJECT_STATE] ; check if in about state
CMP R1, #STATE_ABOUT
MOVEQ R1, #STATE_PLAYING ; set to playing state
STREQ R1, [R3, #MODULE_PROJECT_STATE]
B ui_handle_input_return
ui_handle_input_stop
LDR R3, [R2, #MODULE_UI_PROJECT] ; get project module address
LDR R1, [R3, #MODULE_PROJECT_STATE] ; check if in about state
CMP R1, #STATE_ABOUT
BEQ ui_handle_input_return
MOV R1, #STATE_STOPPED ; set to stopped state
STR R1, [R3, #MODULE_PROJECT_STATE]
BL player_stop_all_channels ; stop any notes currently playing
B ui_handle_input_return
ui_handle_input_play
LDR R3, [R2, #MODULE_UI_PROJECT] ; get project module address
LDR R1, [R3, #MODULE_PROJECT_STATE] ; check if in about state
CMP R1, #STATE_ABOUT
BEQ ui_handle_input_return
CMP R1, #STATE_FINISHED ; check if in finished state
BEQ ui_handle_input_return
MOV R1, #STATE_PLAYING ; set to playing state
STR R1, [R3, #MODULE_PROJECT_STATE]
B ui_handle_input_return
ui_handle_input_return
MOV R0, R2
POP {R1, R2, R3, PC}