-
Notifications
You must be signed in to change notification settings - Fork 0
/
clock.asm
337 lines (272 loc) · 8.08 KB
/
clock.asm
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
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
; Subprogram for a 12-hour clock
; Can be configured using key presses.
;
; Up/Down keys are used to increment/decrement
; while Left/Right keys loop over the following position:
; - Tens of hours: +/- 4 hours
; - Hours: +/- 1 hour
; - Tens of minutes: +/- 10 minutes
; - Minutes: +/- 1 minute
; - Tens of seconds: +/- 10 seconds
; - Seconds: +/- 1 second
; - Hidden cursor
;
; On hidden cursor position:
; - Up key: toggle between 12-hour and 24-hour mode
; - Down key: synchronize the ticking
#include "layouts/subeater.asm"
; Allocate a string buffer
#bank ram
time_mode: #res 1
MODE_24 = 0
MODE_12 = 1
; Main program
#bank program
reset:
jsr lcd_init ; Init LCD display
jsr event_init ; Init event module
wrb #MODE_24 time_mode ; Use 24-hour mode by default
jsr update_display ; Show time on the LCD
lda #4 ; Move cursor
jsr lcd_seek ; To postion 4
jsr lcd_blink_on ; Blink cursor
.main: ; Event loop
jsr event_pop ; Pop events
sta r0 ; Store in r0
lda r0 ; Load events
and #EVENT_LEFT ; Keep left event
beq .end_left ; No left event
jsr on_left ; Call left event handler
.end_left:
lda r0 ; Load events
and #EVENT_RIGHT ; Keep right event
beq .end_right ; No right event
jsr on_right ; Call right event handler
.end_right:
lda r0 ; Load events
and #EVENT_UP ; Keep up event
beq .end_up ; No up event
jsr on_up ; Call up event handler
.end_up:
lda r0 ; Load events
and #EVENT_DOWN ; Keep down event
beq .end_down ; No down event
jsr on_down ; Call down event handler
.end_down:
lda r0 ; Load events
and #EVENT_SECOND ; Keep second event
beq .end_second ; No second event
jsr update_display ; Update display
.end_second:
jmp .main ; Loop over
; Up handler
on_up:
jsr lcd_tell ; Get cursor position
beq .no_edit ; Go to no edit handler
cmp #4 ; Position 4
beq .ten_hours ; Go to ten hours handler
cmp #5 ; Position 5
beq .hours ; Go to hours handler
cmp #7 ; Position 7
beq .ten_minutes ; Go to ten minutes hander
cmp #8 ; Position 8
beq .minutes ; Go to minutes handler
cmp #10 ; Position 10
beq .ten_seconds ; Go to ten seconds handler
cmp #11 ; Position 11
beq .seconds ; Go to seconds handler
jmp .done ; Otherwise we're done
.no_edit:
lda time_mode ; Load time mode
eor #1 ; Toggle time mode
sta time_mode ; Write back
jmp .done ; We're done
.ten_hours:
wrw #4*3600 a0 ; Add 4 hours
jsr time_add_seconds ; to current time
jmp .done ; We're done
.hours:
wrw #60*60 a0 ; Add 1 hour
jsr time_add_seconds ; to current time
jmp .done ; We're done
.ten_minutes:
wrw #10*60 a0 ; Add 10 minutes
jsr time_add_seconds ; to current time
jmp .done ; We're done
.minutes:
wrw #60 a0 ; Add 1 minute
jsr time_add_seconds ; to current time
jmp .done ; We're done
.ten_seconds:
wrw #10 a0 ; Add 10 seconds
jsr time_add_seconds ; to current time
jmp .done ; We're done
.seconds:
wrw #1 a0 ; Add 1 second
jsr time_add_seconds ; to current time
jmp .done ; We're done
.done:
jsr update_display ; Update the display
rts ; Return from subroutine
; Down handler
on_down:
jsr lcd_tell ; Get cursor position
beq .no_edit ; Go to no edit handler
cmp #4 ; Position 4
beq .ten_hours ; Go to ten hours handler
cmp #5 ; Position 5
beq .hours ; Go to hours handler
cmp #7 ; Position 7
beq .ten_minutes ; Go to ten minutes hander
cmp #8 ; Position 8
beq .minutes ; Go to minutes handler
cmp #10 ; Position 10
beq .ten_seconds ; Go to ten seconds handler
cmp #11 ; Position 11
beq .seconds ; Go to seconds handler
jmp .done ; Otherwise we're done
.no_edit:
jsr time_sync ; Synchronize seconds
jmp .done ; We're done
.ten_hours:
wrw #4*3600 a0 ; Subtract 4 hours
jsr time_sub_seconds ; to current time
jmp .done ; We're done
.hours:
wrw #60*60 a0 ; Subtract 1 hour
jsr time_sub_seconds ; to current time
jmp .done ; We're done
.ten_minutes:
wrw #10*60 a0 ; Subtract 10 minutes
jsr time_sub_seconds ; to current time
jmp .done ; We're done
.minutes:
wrw #60 a0 ; Subtract 1 minute
jsr time_sub_seconds ; to current time
jmp .done ; We're done
.ten_seconds:
wrw #10 a0 ; Subtract 10 seconds
jsr time_sub_seconds ; to current time
jmp .done ; We're done
.seconds:
wrw #1 a0 ; Subtract 1 second
jsr time_sub_seconds ; to current time
jmp .done ; We're done
.done:
jsr update_display ; Update the display
rts ; Return from subroutine
; Left handler
on_left:
jsr lcd_tell
beq .start_edit
cmp #11
beq .move_once
cmp #10
beq .move_twice
cmp #8
beq .move_once
cmp #7
beq .move_twice
cmp #5
beq .move_once
cmp #4
beq .stop_edit
jmp .done
.start_edit:
lda #11
jsr lcd_seek
jsr lcd_blink_on
jmp .done
.stop_edit:
lda #0
jsr lcd_seek
jsr lcd_blink_off
jmp .done
.move_twice:
jsr lcd_move_left
.move_once:
jsr lcd_move_left
.done:
rts
; Right handler
on_right:
jsr lcd_tell
beq .start_edit
cmp #4
beq .move_once
cmp #5
beq .move_twice
cmp #7
beq .move_once
cmp #8
beq .move_twice
cmp #10
beq .move_once
cmp #11
beq .stop_edit
jmp .done
.start_edit:
lda #4
jsr lcd_seek
jsr lcd_blink_on
jmp .done
.stop_edit:
lda #0
jsr lcd_seek
jsr lcd_blink_off
jmp .done
.move_twice:
jsr lcd_move_right
.move_once:
jsr lcd_move_right
.done:
rts
; Update display
update_display:
lda r0 ; Push r0
pha ; Onto the stack
lda r1 ; Push r1
pha ; Onto the stack
lda r2 ; Push r2
pha ; Onto the stack
jsr lcd_tell ; Get cursor position
sta r2 ; Save in r2
jsr lcd_clear ; Clear the screen
lda #4 ; Load position 4
jsr lcd_seek ; Move curosor
lda time_mode ; Load time mode
cmp #MODE_12 ; Test 12-hour mode
bne .mode_24 ; Go to the right mode
.mode_12:
jsr time_12_hour_str ; Get time as text
wrw a2 r0 ; Save a2 in r0
jsr lcd_print_str ; Print to LCD display
lda #64 + 7 ; Load position 7 on second row
jsr lcd_seek ; Move cursor
wrw r0 a0 ; Write second string address to a0
jsr lcd_print_str ; Print AM/PM
jmp .time_mode_done
.mode_24:
jsr time_24_hour_str ; Get time as text
jsr lcd_print_str ; Print to LCD display
.time_mode_done:
lda r2 ; Load r2
jsr lcd_seek ; Restore cursor position
pla ; Pop r0 from the stack
sta r2 ; And write it back
pla ; Pop r0 from the stack
sta r1 ; And write it back
pla ; Pop r0 from the stack
sta r0 ; And write it back
rts ; Return from subroutine
; Interrupt
nmi:
rti
irq:
jsr event_irq
rti
; Libraries
#include "libraries/lcd.asm"
#include "libraries/rom.asm"
#include "libraries/time.asm"
#include "libraries/event.asm"