1 | ; general device setup
|
2 | ; this is for the Arduino
|
3 | ;
|
4 | .NOLIST ; Disable listfile generation
|
5 | .include "m328def.inc"
|
6 | .LIST
|
7 | ; ******************************************************************
|
8 | ; todays project:
|
9 | ; control The RFM01 RX Module with an ATMega 48/168/328
|
10 | ; Receive an FSK data stream with it
|
11 | ; constants @ 16 Mhz clk
|
12 | ; ******************************************************************
|
13 | ; crystal osc. frequency
|
14 | .equ F_CPU = 16000000
|
15 | ; this is for the 868 Mhz Module
|
16 | ; PLL ref is 5 Khz
|
17 | ; frequency is f = 860Mhz + FREQUENCY * 5khz
|
18 | .equ FREQUENCY = 1024 ; 865.120 Mhz
|
19 | ;
|
20 | ; bitrate setting : BR = 10E6 / 29 / (BITRATE+1)
|
21 | .equ BITRATE = 71 ; 4800 baud
|
22 | ;
|
23 | ;
|
24 | .equ ROMSTART = 0x0100
|
25 | .equ RAMSTART = SRAM_START
|
26 | .equ cr = 0x0d
|
27 | .equ lf = 0x0a
|
28 | .equ spc = 0x20
|
29 | .equ MS10 = 0x34
|
30 | .equ MS30 = 0x60
|
31 | .equ MS100 = 0x91 ; roughly 100mS with wozwait @ 16Mhz
|
32 | .equ MS500 = 0xf9 ; roughly 500mS with wozwait @ 16Mhz
|
33 | .equ timeout = 0x14 ; 20 seconds for display timeout
|
34 |
|
35 | ; serial
|
36 | .equ baudrate = 19200
|
37 | .equ ubrvalue = (F_CPU /(16 * baudrate)) - 1
|
38 |
|
39 | ; DMX definitions
|
40 | .equ DMXSTART = SRAM_START
|
41 | .equ DMXCHANNELS = 16
|
42 | .equ DMXEND = DMXSTART+DMXCHANNELS
|
43 |
|
44 | ; hardware ports
|
45 | ; pinning for RFM recommends port D
|
46 | .equ RFMClk = 7 ; SPI Clock Out
|
47 | .equ RFMOut = 6 ; SPI Data Out
|
48 | .equ RFMIn = 5
|
49 | .equ RFMCs = 4 ; RFM Chip Select Out
|
50 | .equ RFMFfit = 3 ; Control for Fif0
|
51 | .equ RFMIrq = 2 ; Register/Data IRQ
|
52 |
|
53 | .equ RFMPort = PortD ; this is Port to the RFM module
|
54 | .equ RFMDir = DDRD ; DDR for RFM module
|
55 | .equ RFMPin = PinD ; and the input pins
|
56 | ;
|
57 | .equ LEDPort = PortB
|
58 | .equ LEDDir = DDRB
|
59 | .equ OVLed = 5
|
60 | .equ VID = 0 ; data valid wire
|
61 | ;
|
62 | ;
|
63 | ; general usage ; written by
|
64 | ; irq registers
|
65 | .def irqstor = r12 ; EXT IRQ routine SREG safe place
|
66 | ; general purpose non-immediate
|
67 | .def lowtemp = r13
|
68 | .def chksum = r14
|
69 | ; immediate registers
|
70 | .def temp = r16 ;misc usage, general purpose
|
71 | .def del = r17 ; delay counter
|
72 | .def counter = r18 ; bitbanger
|
73 | .def length = r19 ; stringlength
|
74 | .def spihi = r20 ; send to RFM
|
75 | .def spilo = r21 ;
|
76 | .def ticker = r22
|
77 | ; flags for operation
|
78 | ;7 6 5 4 3 2 1 0
|
79 | ;valid
|
80 | .def flags = r25 ; flags
|
81 | .equ valid = 0x80
|
82 | .equ validbit = 7
|
83 |
|
84 | ; ************** MAIN PROGRAM STARTS HERE *************************
|
85 | .CSEG
|
86 | .ORG 0x0 ; note that this table is 2-byte addresses
|
87 | jmp RESET ; Reset Handler
|
88 | jmp EXT_INT0 ; IRQ0 Handler
|
89 | jmp EXT_INT1 ; IRQ1 Handler
|
90 | jmp PC_INT0 ; PCINT0 Handler
|
91 | jmp PC_INT1 ; PCINT1 Handler
|
92 | jmp PC_INT2 ; PCINT2 Handler
|
93 | jmp WDT ; Watchdog Timer Handler
|
94 | jmp TIM2_COMPA ; Timer2 Compare A Handler
|
95 | jmp TIM2_COMPB ; Timer2 Compare B Handler
|
96 | jmp TIM2_OVF ; Timer2 Overflow Handler
|
97 | jmp TIM1_CAPT ; Timer1 Capture Handler
|
98 | jmp TIM1_COMPA ; Timer1 Compare A Handler
|
99 | jmp TIM1_COMPB ; Timer1 Compare B Handler
|
100 | jmp TIM1_OVF ; Timer1 Overflow Handler
|
101 | jmp TIM0_COMPA ; Timer0 Compare A Handler
|
102 | jmp TIM0_COMPB ; Timer0 Compare B Handler
|
103 | jmp TIM0_OVF ; Timer0 Overflow Handler
|
104 | jmp SPI_STC ; SPI Transfer Complete Handler
|
105 | jmp USART_RXC ; USART, RX Complete Handler
|
106 | jmp USART_UDRE ; USART, UDR Empty Handler
|
107 | jmp USART_TXC ; USART, TX Complete Handler
|
108 | jmp ADC_INT ; ADC Conversion Complete Handler
|
109 | jmp EE_RDY ; EEPROM Ready Handler
|
110 | jmp ANA_COMP ; Analog Comparator Handler
|
111 | jmp TWI ; 2-wire Serial Interface Handler
|
112 | jmp SPM_RDY ; Store Program Memory Ready Handler
|
113 | ;
|
114 | ; IRQ stubs
|
115 | EXT_INT0:
|
116 | EXT_INT1:
|
117 | PC_INT0:
|
118 | PC_INT1:
|
119 | PC_INT2:
|
120 | WDT:
|
121 | TIM2_COMPA:
|
122 | TIM2_COMPB:
|
123 | TIM2_OVF:
|
124 | TIM1_CAPT:
|
125 | TIM1_COMPA:
|
126 | TIM1_COMPB:
|
127 | TIM1_OVF:
|
128 | TIM0_COMPA:
|
129 | TIM0_COMPB:
|
130 | TIM0_OVF:
|
131 | SPI_STC:
|
132 | USART_RXC:
|
133 | USART_UDRE:
|
134 | USART_TXC:
|
135 | ADC_INT:
|
136 | EE_RDY:
|
137 | ANA_COMP:
|
138 | TWI:
|
139 | SPM_RDY: reti
|
140 | ;
|
141 | RESET: cli
|
142 | ldi temp,low(RAMEND) ; stackpointer
|
143 | sts SPL,temp
|
144 | ldi temp,high(RAMEND)
|
145 | sts SPH,temp
|
146 | ; variable init
|
147 | clr flags ; reset anything
|
148 | ; hardware init
|
149 | rcall init_ports ; initialize
|
150 | cbi LEDPort, OVLED
|
151 | ;*********************************************************
|
152 | ; main program
|
153 | main: ldi ticker,0xff ; periodical calls
|
154 | clr chksum
|
155 | ldi YH,High(DMXSTART)
|
156 | ldi YL,low(DMXSTART)
|
157 | rcall w30us
|
158 | ; reset the FIFO
|
159 | ldi spihi,0xce
|
160 | ldi spilo,0x84
|
161 | rcall spiout
|
162 | nop
|
163 | ; restart the FIFO
|
164 | ldi spihi,0xce
|
165 | ldi spilo,0x87
|
166 | rcall spiout
|
167 | nop
|
168 | main1:
|
169 | dec ticker ; timeouter
|
170 | rcall rfmread ; try to read something from the receiver
|
171 | sbrs flags, validbit ; if theres something valid throw it on the console
|
172 | rjmp main1
|
173 | ; received something
|
174 | mov spihi,temp ; status
|
175 | rcall usbout
|
176 | cpi YL,low(DMXEND)
|
177 | brcs main1
|
178 | sbi LEDPort,OVLED ; LED flashes on full buffer
|
179 | rcall w100ms
|
180 | cbi LEDPort,OVLED
|
181 | rjmp main
|
182 | ; subprograms
|
183 | ;
|
184 | ; write a word from program space to RFM module
|
185 | ; pointer is in Z and is incremented
|
186 | writedw: lpm spilo,Z+
|
187 | lpm spihi,Z+
|
188 | ; send a single word via SPI from spihi and spilo with chipselect
|
189 | spiout: cbi RFMPort,RFMCs ; select
|
190 | ldi counter,16 ; 16 bitbangs
|
191 | spio1: rol spilo ; data into carry
|
192 | rol spihi ; this carry we send
|
193 | brcc spiolo ; data is lo
|
194 | sbi RFMPort,RFMOut
|
195 | rjmp spio2
|
196 | spiolo: cbi RFMPort,RFMOut
|
197 | nop
|
198 | spio2: nop
|
199 | sbi RFMPort,RFMClk ; strobe pulse
|
200 | nop
|
201 | nop
|
202 | cbi RFMPort,RFMClk ; set clock low
|
203 | nop
|
204 | nop
|
205 | dec counter ; next bit
|
206 | brne spio1
|
207 | nop
|
208 | cbi RFMPort,RFMOut
|
209 | nop
|
210 | nop
|
211 | sbi RFMPort,RFMCs
|
212 | ret
|
213 | ; read RFM01 status byte into spihi, spilo and the next data byte from the fifo
|
214 | ; the read command starts and continues with a 0
|
215 | ; data will be stored at Y
|
216 | rfmread: ; read command
|
217 | cbi RFMPort,RFMOut ; set to lo for the rest of this run
|
218 | nop
|
219 | cbi RFMPort,RFMCs ; select rx
|
220 | ldi counter,16 ; 16, read in the statusword
|
221 | nop
|
222 | sbi RFMPort,RFMClk ; strobe in the next bit
|
223 | nop
|
224 | clc
|
225 | sbis RFMPin,RFMIn ; read
|
226 | rjmp rfmr2 ; no fifo there, skip this receiption
|
227 | sec
|
228 | rol spilo ; into 16 bit rollers
|
229 | rol spihi
|
230 | dec counter
|
231 | rfmr1: nop
|
232 | sbi RFMPort,RFMClk ; strobe in the next bit
|
233 | nop
|
234 | clc
|
235 | sbic RFMPin,RFMIn ; read
|
236 | sec
|
237 | rol spilo ; into 16 bit rollers
|
238 | rol spihi
|
239 | cbi RFMPort,RFMClk
|
240 | dec counter
|
241 | brne rfmr1
|
242 | ; now get the databyte
|
243 | ; read in 8 bits
|
244 | ldi counter,8
|
245 | rfmr6: nop
|
246 | nop
|
247 | nop
|
248 | sbi RFMPort,RFMClk ; strobe pulse
|
249 | clc
|
250 | nop
|
251 | nop
|
252 | sbic RFMPin, RFMIn ; is it high ?
|
253 | sec
|
254 | rol temp ; from carry into lowest
|
255 | rfmr5: nop
|
256 | nop
|
257 | cbi RFMPort,RFMClk ; clr the clock
|
258 | dec counter
|
259 | brne rfmr6
|
260 | nop
|
261 | sbi RFMPort,RFMCs ; deselect RFM
|
262 | st Y+,temp ; store in RAM
|
263 | add chksum,temp ; add to the checksum
|
264 | sbr flags,valid ; we have a valid reception
|
265 | ret
|
266 | rfmr2: cbr flags,valid ; no valid reception detected
|
267 | cbi RFMPort, RFMClk ; unclock
|
268 | sbi RFMPort,RFMCs ; deselect RFM
|
269 | ret
|
270 | ;
|
271 | ;send a single char from temp via uart
|
272 | usbout: push temp
|
273 | ;first wait for transmitter empty
|
274 | usbo1: lds temp,UCSR0A
|
275 | sbrs temp,UDRE0 ; test buffer empty
|
276 | rjmp usbo1
|
277 | ; send the byte
|
278 | pop temp ; get the byte back
|
279 | sts UDR0, temp ; and send it
|
280 | ret
|
281 | ; steve wozniak's wait routine - this time for AVR
|
282 | ; this is the routine with del^2
|
283 | ; this wait routine is ingenious and handles wide ranges of delay
|
284 | ; as a hommage to steve i port it to all my embedded systems.
|
285 | ; some presets
|
286 | w500ms: ldi del,MS500 ; half a second
|
287 | rjmp wozwait
|
288 | w100ms: ldi del,MS100 ; 1/10 second
|
289 | rjmp wozwait
|
290 | w10ms: ldi del,MS10
|
291 | rjmp wozwait
|
292 | w30ms: ldi del,MS30
|
293 | rjmp wozwait
|
294 | w30us: ldi del,0x05 ;
|
295 | ; here now the core wait routine
|
296 | wozwait: push del
|
297 | wwait2: push del
|
298 | wwait1: subi del,1
|
299 | brne wwait1
|
300 | pop del
|
301 | subi del,1
|
302 | brne wwait2
|
303 | pop del
|
304 | subi del,1
|
305 | brne wozwait
|
306 | ret
|
307 | ; initialize ports
|
308 | ; Port B
|
309 | ; RFM 7 6 5 4 3 2 1 0
|
310 | ; - - LED - - - Power VID
|
311 | ; Port D
|
312 | ; LED 7 6 5 4 3 2 1 0
|
313 | ; CLK Out In Sel FFIT Irq TXD RXD
|
314 | ;
|
315 | ;
|
316 | ; Port B - RFM Module
|
317 | init_ports:
|
318 | ; rcall w500ms
|
319 | ldi temp,0b00101100 ; enable pullups and preset RFM wires to low
|
320 | out RFMPort,temp ;
|
321 | ldi temp,0b11010010 ; RFMPort set outputs and clip LED
|
322 | out RFMDir,temp ; set outputs
|
323 | ldi temp,0b00100010
|
324 | out LEDDir, temp
|
325 | ldi temp,0b00100011 ; LED on , Power on, pullup on VID
|
326 | out LEDPort, temp ; illuminate clipping led
|
327 | rcall w100ms ; 100 mSec
|
328 | init_uart:
|
329 | ldi temp, (1<<TXEN0) ; must be enabled first
|
330 | sts UCSR0B, temp
|
331 | ldi temp, 0b00000110 ; async,8bit,no parity
|
332 | sts UCSR0C, temp
|
333 | ldi temp, 0b01000000
|
334 | sts UCSR0A, temp
|
335 | ldi temp,low(ubrvalue) ; write our fixed baudrate
|
336 | sts UBRR0L, temp
|
337 | ldi temp,high(ubrvalue)
|
338 | andi temp,0x0f ; mask forbidden bits
|
339 | sts UBRR0H, temp
|
340 | ; clear all pending
|
341 | ldi temp,0x03
|
342 | out EIFR, temp
|
343 | out TIFR0, temp
|
344 | ; initialize the radio RX module
|
345 | ldi spihi,0xda ; reset RFM module
|
346 | ldi spilo,0x01
|
347 | rcall spiout
|
348 | rcall w100ms
|
349 | init_rfm:
|
350 | ldi ZH,high(rfminit << 1) ; table start
|
351 | ldi ZL,low(rfminit << 1)
|
352 | ldi length,NUM_COMMANDS ; number of words
|
353 | init_rf1:
|
354 | rcall writedw ; stream to RFM
|
355 | rcall w30us ; wait a little
|
356 | dec length ; next word
|
357 | brne init_rf1
|
358 | rcall w100ms ; 100 mSec
|
359 | ; init uart
|
360 | ret
|
361 | ; init values for the RFM01 868 mhz rx
|
362 | .equ NUM_COMMANDS = 11
|
363 | rfminit:
|
364 | .dw 0x0000 ; dummy read
|
365 | .dw 0b1001000110001011 ; configuration, 868 mhz, 134 khz bandwidth
|
366 | .dw 0xa000 + FREQUENCY ; frequency
|
367 | .dw 0xc800 + BITRATE ; data rate
|
368 | .dw 0xc6f7 ; AFC setting
|
369 | .dw 0xc400 + 0b10101101 ; data filter
|
370 | .dw 0xc240 ; low battery & clk divider
|
371 | .dw 0xc084 ; receiver settings
|
372 | .dw 0xce00 + 0b10000101 ; Output and FIFO mode
|
373 | .dw 0xce00 + 0b10000111 ; toggle Output and FIFO mode
|
374 | .dw 0xc085 ; rx on , -91 db
|
375 | .db "Ende"
|