45
|
1 |
;;; vim: set ft=avr:
|
|
2 |
|
|
3 |
.nolist
|
|
4 |
.include "m168def.inc" ; Same family as 328P
|
|
5 |
.list
|
|
6 |
|
46
|
7 |
.include "macros.inc"
|
45
|
8 |
|
|
9 |
;; Interrupt Vector
|
|
10 |
.cseg
|
|
11 |
.org 0x0000
|
|
12 |
rjmp Main
|
|
13 |
|
|
14 |
|
|
15 |
;; CPU cycles / second: 16 Mhz
|
|
16 |
.set CPU_CYCLES = 16 * 1000 * 1000
|
|
17 |
|
46
|
18 |
;; Delays
|
|
19 |
.include "delay.inc"
|
|
20 |
|
45
|
21 |
;; DMX baud raite: 250k
|
|
22 |
.set DMX_BAUD = 250 * 1000
|
|
23 |
|
|
24 |
;; CPU cycles / bit: 64
|
|
25 |
.set DMX_CYCLES = CPU_CYCLES / DMX_BAUD
|
|
26 |
|
46
|
27 |
;; DMX output I/O
|
45
|
28 |
.set DMX_DDR = DDRB
|
|
29 |
.set DMX_PORT = PORTB
|
|
30 |
.equ DMX_DATA = PORTB3
|
|
31 |
|
46
|
32 |
;; DMX protocol timer
|
|
33 |
; Registers
|
|
34 |
.set DMX_TIMER_CRA = TCCR2A
|
|
35 |
.set DMX_TIMER_CRB = TCCR2B
|
|
36 |
.set DMX_TIMER_CNT = TCNT2
|
|
37 |
.set DMX_TIMER_OCRA = OCR2A
|
|
38 |
.set DMX_TIMER_OCRB = OCR2B
|
|
39 |
.set DMX_TIMER_IMSK = TIMSK2
|
|
40 |
.set DMX_TIMER_IFR = TIFR2
|
|
41 |
|
|
42 |
; Compare output match isn't used
|
|
43 |
.set DMX_TIMER_COMA = 0b00
|
|
44 |
.set DMX_TIMER_COMB = 0b00
|
|
45 |
|
|
46 |
; Control register, generation mode value
|
|
47 |
.set DMX_TIMER_WGM_10 = 0b10 ; CTC
|
|
48 |
.set DMX_TIMER_WGM_2 = 0b0
|
|
49 |
|
|
50 |
; Clock select
|
|
51 |
.set DMX_TIMER_CS_STOP = 0b000
|
|
52 |
;.set DMX_TIMER_CS = 0b001 ; 1/1
|
|
53 |
.set DMX_TIMER_CS = 0b111 ; 1/1024
|
|
54 |
|
|
55 |
; Counted value
|
|
56 |
.set DMX_TIMER_TOP = DMX_CYCLES ; number of cycles for baud
|
|
57 |
|
45
|
58 |
;; Debug LED
|
|
59 |
.set LED_DDR = DDRB
|
|
60 |
.set LED_PORT = PORTB
|
|
61 |
.set LED_PIN = PINB
|
|
62 |
.set LED_BIT = PORTB5
|
|
63 |
|
|
64 |
;; Set up DMX output
|
|
65 |
DMX_Init:
|
|
66 |
; Setup output port
|
|
67 |
; out
|
|
68 |
sbi DMX_DDR, DMX_DATA
|
|
69 |
|
|
70 |
; drive high
|
|
71 |
sbi DMX_PORT, DMX_DATA
|
|
72 |
|
46
|
73 |
; Setup timer
|
|
74 |
; setup CTC mode with no output pins
|
|
75 |
poke [DMX_TIMER_CRA, r16, (DMX_TIMER_COMA << COM2A0) | (DMX_TIMER_COMB << COM2B0) | (DMX_TIMER_WGM_10 << WGM20)]
|
|
76 |
poke [DMX_TIMER_CRB, r16, (DMX_TIMER_WGM_2 << WGM22) | (DMX_TIMER_CS_STOP << CS20)]
|
|
77 |
|
|
78 |
; trigger threshold for CTC
|
|
79 |
poke [DMX_TIMER_OCRA, r16, (DMX_TIMER_TOP)]
|
|
80 |
|
45
|
81 |
; OK
|
46
|
82 |
ret
|
|
83 |
|
|
84 |
;; Start Break signal
|
|
85 |
;;
|
|
86 |
;; 22 bits - 1s long; then DMX_Break_Mark
|
|
87 |
;;
|
|
88 |
DMX_Break_Start:
|
|
89 |
; Low
|
|
90 |
cbi DMX_PORT, DMX_DATA
|
|
91 |
|
|
92 |
ret
|
|
93 |
|
|
94 |
;; Start Mark-after-break signal
|
|
95 |
;;
|
|
96 |
;; 2 bits - 1s long; then DMX_Break_End
|
|
97 |
;;
|
|
98 |
DMX_Break_Mark:
|
|
99 |
; High
|
|
100 |
sbi DMX_PORT, DMX_DATA
|
|
101 |
|
|
102 |
ret
|
|
103 |
|
|
104 |
;; End break; prepare for DMX_Frame
|
|
105 |
DMX_Frame_Start:
|
|
106 |
; Start timer
|
|
107 |
poke [DMX_TIMER_CRB, r20, (DMX_TIMER_WGM_2 << WGM22) | (DMX_TIMER_CS << CS20)]
|
|
108 |
|
|
109 |
ret
|
|
110 |
|
|
111 |
;; Do a full DMX break, using some random length
|
|
112 |
;;
|
|
113 |
DMX_Break:
|
|
114 |
; Break
|
|
115 |
; start
|
|
116 |
rcall DMX_Break_Start
|
|
117 |
|
|
118 |
; wait; about 100ms?
|
|
119 |
ldi r20, 82 / 10
|
|
120 |
rcall VarDelay
|
|
121 |
|
|
122 |
; MAB
|
|
123 |
; mark
|
|
124 |
rcall DMX_Break_Mark
|
|
125 |
|
|
126 |
; short wait
|
|
127 |
ldi r20, 1
|
|
128 |
rcall VarDelay
|
|
129 |
|
|
130 |
; Timed frames
|
|
131 |
; start frame
|
|
132 |
rcall DMX_Frame_Start
|
|
133 |
|
|
134 |
; ok
|
|
135 |
ret
|
45
|
136 |
|
|
137 |
;; Bitbang one DMX bit out
|
|
138 |
;; uses SREG/C to send
|
46
|
139 |
;
|
|
140 |
; Uses Timer2 as a bit sync clock, sending out the next bit once we've hit 64 cycles on the timer
|
45
|
141 |
DMX_Bit:
|
46
|
142 |
; Wait for bit sync clock
|
|
143 |
_dmx_bit_wait:
|
|
144 |
; test OCA hit
|
|
145 |
sbic TIFR2, OCF2A
|
|
146 |
rjmp _dmx_bit_wait
|
|
147 |
|
|
148 |
sbi LED_PIN, LED_BIT
|
|
149 |
|
|
150 |
; Output bit
|
|
151 |
; XXX: ugly bit-testing, can't we do this using something more nifty?
|
45
|
152 |
brcs _dmx_bit_1
|
|
153 |
|
46
|
154 |
; bit 0
|
45
|
155 |
cbi DMX_PORT, DMX_DATA
|
46
|
156 |
rjmp _dmx_bit_done
|
45
|
157 |
|
|
158 |
_dmx_bit_1:
|
46
|
159 |
; bit 1
|
45
|
160 |
sbi DMX_PORT, DMX_DATA
|
|
161 |
nop
|
|
162 |
|
46
|
163 |
; Bit sent
|
|
164 |
_dmx_bit_done:
|
|
165 |
; reset OCA hit for next bit
|
|
166 |
cbi TIFR2, OCF2A
|
45
|
167 |
|
46
|
168 |
; OK, bit sync clock keeps running for next bit
|
|
169 |
ret
|
45
|
170 |
|
46
|
171 |
;; Bitbang one DMX byte out, using DMX_Bit
|
45
|
172 |
;; r16: byte value
|
46
|
173 |
;
|
|
174 |
; Uses Timer2 as a bit sync clock; must call DMX_Frame_Start before first DMX_Frame
|
45
|
175 |
DMX_Frame:
|
|
176 |
; Start bit
|
46
|
177 |
clc
|
45
|
178 |
rcall DMX_Bit
|
|
179 |
|
|
180 |
; Data bits: 8
|
|
181 |
ldi r21, 8
|
|
182 |
|
|
183 |
_dmx_frame_loop:
|
|
184 |
; shift + send bit
|
|
185 |
lsl r16
|
|
186 |
rcall DMX_Bit
|
|
187 |
|
|
188 |
; loop
|
|
189 |
dec r21
|
|
190 |
brne _dmx_frame_loop
|
|
191 |
|
|
192 |
; Stop bits
|
46
|
193 |
sec
|
45
|
194 |
rcall DMX_Bit
|
|
195 |
rcall DMX_Bit
|
|
196 |
|
|
197 |
; OK
|
46
|
198 |
ret
|
45
|
199 |
|
46
|
200 |
;; End of DMX frames
|
|
201 |
DMX_Frame_End:
|
|
202 |
; Keep mark from end of last frame; DMX_Break_Start starts the break
|
|
203 |
; Stop the timer
|
|
204 |
poke [DMX_TIMER_CRB, r20, (DMX_TIMER_WGM_2 << WGM22) | (DMX_TIMER_CS_STOP << CS20)]
|
|
205 |
|
|
206 |
; OK
|
|
207 |
ret
|
|
208 |
|
|
209 |
;; Send one value on all frames
|
45
|
210 |
;; r17: byte value
|
|
211 |
DMX_Flood:
|
|
212 |
; Break
|
|
213 |
rcall DMX_Break
|
|
214 |
|
|
215 |
; Start code
|
|
216 |
ldi r16, 0
|
|
217 |
rcall DMX_Frame
|
|
218 |
|
|
219 |
; Channels
|
|
220 |
; number of channels to send
|
|
221 |
ldi r22, 100
|
|
222 |
|
|
223 |
_dmx_flood_channels:
|
|
224 |
; restore channel value
|
|
225 |
mov r16, r17
|
|
226 |
|
|
227 |
; send channel value
|
|
228 |
rcall DMX_Frame
|
|
229 |
|
|
230 |
; loop
|
|
231 |
dec r22
|
|
232 |
brne _dmx_flood_channels
|
|
233 |
|
46
|
234 |
; End packet
|
|
235 |
rcall DMX_Frame_End
|
45
|
236 |
|
|
237 |
|
46
|
238 |
ret
|
|
239 |
|
45
|
240 |
;; Program main
|
|
241 |
Main:
|
|
242 |
; Initialization
|
|
243 |
; Debug
|
|
244 |
sbi LED_DDR, LED_BIT
|
46
|
245 |
sbi LED_PORT, LED_BIT
|
45
|
246 |
|
|
247 |
; Stack
|
46
|
248 |
poke [SPL, r16:r17, RAMEND]
|
45
|
249 |
|
|
250 |
; Init
|
|
251 |
rcall DMX_Init
|
|
252 |
|
|
253 |
sbi LED_PORT, LED_BIT
|
|
254 |
|
|
255 |
; Send; value
|
46
|
256 |
_main_loop:
|
45
|
257 |
ldi r17, 255
|
|
258 |
rcall DMX_Flood
|
|
259 |
|
46
|
260 |
;sbi LED_PORT, LED_BIT
|
|
261 |
|
45
|
262 |
; never returns..
|
|
263 |
rjmp _main_loop
|
|
264 |
|