RFM01_RX.asm


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"