-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmain.S
233 lines (205 loc) · 6.03 KB
/
main.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
;; ****************************************************************************
;; Instead of string numbers we could use offsets into GS data, byte+
;; half byte; nybble address
;;
;; Registers
;;
;; r0 = scratch used by interrupt processor, don't use!
;; r1 = SPI reading, used in interrupt
;; r2 = SPI counter
;; r3 = have new gs data
;; r4l:r5h = LED brightness
;; r6 = TLC SPI Byte type
;; r7 = scratch used in interrupt processing
;; r10 = channel # parameter to TLC_setChannelTargetIntensity
;; N r11: low byte of channel parameter
;; N r12: high byte of channel parameter
;; I r17 = minutes past hour
;; I r18 = hours (0-11)
;; N r19 = temp, can be overwritten by any function, but not overwritten
;; in interrupt handlers
;; r20 = scratch for interrupt handling
;; r21 = scratch for interrupt handling
;; r24:r25 = timer counter
;; r26:r27 X, used in TLC_setChannelTargetIntensity.
;; r30:r31 Z = SPI read pointer
;;
;; Pins:
;;
;; PB0 CLKO - TLC5940 GSCLK
;; PB1 - TLC5940 XLAT 0
;; PB2 - TLC5940 BLANK 1
;; PB3 MOSI - TLC5940 SIN
;; PB4 MISO - ArduinoISP
;; PB5 SCK - TLC5940 SCLK 0
;; PB6 XTAL1 - Crystal
;; PB7 XTAL2 - Crystal
;; PD4 - TLC5940 DCPRG 0
;; PD7 - TLC5940 VPRG 1
;;
;; Timers
;;
;; Timer0: Time handling. clock divider 1024
;; Timer2: TLC Handling. Clock divider 1024, max counter 3
;; ****************************************************************************
;; INCLUDES
.include "m168.h"
#include "reg_mnemonics.h"
.include "config.h"
;; CONSTANTS
;; TICKS_PER_STEP is the number of timer0 ticks per clock step.
;; For Erland's clock a clock step is five minutes, for Mac's it will be
;; one minute.
;; MINUTES_PER_STEP is defined in the relevant config.h file
;; 16000000 / (1024 * 255) timer ticks per second * 60 * 60
.equ TICKS_PER_STEP, (16000000 * 60 * MINUTES_PER_STEP) / (1024 * 255)
.equ STEPS_PER_HOUR, (60 / MINUTES_PER_STEP)
;; GSDATA is the grayscale data. It consists of 32 12 bit values, packed into
;; 48 bytes. Channel 15 MSB first.
.equ GSDATA, 0x0100
.text
;; INTERRUPT VECTORS, .org = advance location counter.
;; Since this code is the first to be excuted, the memory location is the
;; one for interrupts.
.org 0
rjmp init ;; boot & reset vector
.org OC2Aaddr * 2
rjmp TLC_spiTimerInterrupt
.org OVF0addr * 2
rjmp timerInterrupt ;; Timer 0 overflow
.org SPIaddr * 2
rjmp TLC_spiInterrupt
.org INT_VECTORS_SIZE * 2
init:
;; PORT SETUP
;; set outputs before port direction, so values will be correct on
;; switch
call TLC_init
;; Initialize the time to midnight
ldi MINS_PAST, 0 ; 5 minutes past hour
ldi HOURS, 0 ; hour
;; Initialize timer tick counter
ldi r24, 0
ldi r25, 0
;; Set up timer 0 with 1024 prescaler
clr r16
out TCCR0A, r16 ; TCCR = timer/counter control register
ldi r16, 5
out TCCR0B, r16 ; Select prescaler 1024, turn on
ldi r16, 1
sts TIMSK0, r16 ; Enable interrupt on overflow (TOIE0 bit)
;; Everything set up, enable interrupts
sei ; Enable interrupts
/* clr r16 */ /* Sets r16 to 0x00 */
/* out PORTB, r16 */ /* Sets portB outputs to 0? */
/* out PORTD, r16 */ /* Sets portD outputs to 0? */
loop:
; Mac: Idle Sleep ??? isn't it ADC noise reduction ???
; Erl: No. The lowest bit is SE (Sleep enable) the three bits above that
; are 0, which is idle sleep mode
ldi r16, 1
out SMCR, r16 ; SMCR = Sleep mode control register
sleep
doneSetting:
;; Increment time counter if required
;; Time counter is in r24, increased 62.5 times per second ==
;; 18750 == 0x493e times per 5 minutes
ldi r16, hi8( TICKS_PER_STEP )
cli ; make sure r24 doesn't change while comparing
cpi r24, lo8( TICKS_PER_STEP ) ; compare with immediate
cpc r25, r16 ; compare with carry
sei
brmi noNewTime ; branch if minus
inc MINS_PAST ; 5 minutes past the hour
cli
subi r24, lo8( TICKS_PER_STEP ) ; subtract immediate
sbci r25, hi8( TICKS_PER_STEP ) ; subtract immediate with carry
sei
cpi MINS_PAST, STEPS_PER_HOUR
brlo noNewHour ; branch if lower
inc HOURS ; increment hour count
cpi HOURS, HOURS_PER_DAY
brlo noNewHour
ldi HOURS, 0
noNewHour:
;; Change time words if time changed
;; If we get here, minutes changed, but not hours
cpi MINS_PAST, 0
brne isItTenPast
;;
;; call function to set all minute strings to intensity
;;
isItTenPast:
noNewTime:
/* Check buttons */
/* Check LDR, adjust PWM */
rjmp loop
timerInterrupt:
/* save status byte */
in r0, 0x3f
push r0
;; Incremement time counter (actual freq = 62.5Hz
adiw r24, 1
doneSetting2:
;; restore status register
pop r0
out 0x3f, r0
reti
;; 16 channels with 12 bits each = 24 bytes
initialGSValues:
.byte 0b11111111 ; 15
.byte 0b11111000
.byte 0b00000000
.byte 0b01000000 ; 13
.byte 0b00000010
.byte 0
.byte 0 ; 11
.byte 0
.byte 0
.byte 0 ; 9
.byte 0
.byte 0
.byte 0 ; 7
.byte 0
.byte 0
.byte 0 ; 5
.byte 0
.byte 0
.byte 0 ; 3
.byte 0
.byte 0
.byte 0 ; 1
.byte 0
.byte 0
;; There are 11 strings related to minutes
;; this table has one word (16 bits) to indicate which strings are on
;;
;; LSB in each word is for string 3, bit 10 for string d
minuteStringData:
.word 0x0000 ; on the hour
.word 0b0000000110000100 ; five past the hour
.word 0b0000000110001000 ; ten past the hour
.word 0b0000000110110000 ; quarter past the hour
.word 0b0000000110000011 ; twenty past the hour
.word 0b0000011001000100 ; twenty five past the hour
.word 0b0000011000000000 ; half past
.word 0b0000011110000100 ; 35 minutes past
.word 0b0000000001000011 ; 40 minutes past
.word 0b0000000111000000 ; 45 minutes past
.word 0b0000000001001000 ; 50 minutes past
.word 0b0000000001000100 ; 55 minutes past
;; There are 16 strings related to hours
hourStringData:
.word 0b0110000000000000 ; 12
.word 0b0000000000000010 ; 1
.word 0b0000000000000001 ; 2
.word 0b0000000010000000 ; 3
.word 0b0000000000001100 ; 4
.word 0b0000000000010000 ; 5
.word 0b0000001000000000 ; 6
.word 0b0001000000000000 ; 7
.word 0b0000000001100000 ; 8
.word 0b1000000000000000 ; 9
.word 0b0000000100000000 ; 10
.word 0b0000110000000000 ; 11
.end