Code:
'****************************************************************
'* Name : Transceiver.pbp *
'* Author : Paul R. Steinmeyer *
'* Notice : Copyright (c) 2010 [select VIEW...EDITOR OPTIONS] *
'* : All Rights Reserved *
'* Date : 11/02/2010 *
'* Version : 1.0 *
'* Notes : Target uC: 16F88, using 18F1320 *
'* : Interface with RFM22 *
'* : Waits in RX Mode unless button is pressed, at *
'* : which point it transmits the packet and returns *
'* : to RX mode. *
'* : At any valid packet reception the LED blinks *
'* : *
'* : Un-rem lines with SEROUT2 for debugging serial *
'* : transmissions at 9600 baud *
'* : *
'* : *
'****************************************************************
'------------------------------------------------------------------------------------------------------------------------------------
' # Name |I/O| Alias | Var | Description
'------------------------------------------------------------------------------------------------------------------------------------
' 1 RA0/AN0 |D 1| nButton | | Goes low when button is pressed
' 2 RA1/AN1 |D 0| LED | | LED on when high
' 3 RA4/T0CKI |D 1| | | N/C
' 4 RA5/MCLR |D 1| | | N/C
' 5 Vss | | | | Ground
' 6 RA2/AN2 |D 1| | | N/C
' 7 RA3/AN3 |D 1| | | N/C
' 8 RB0/AN4 |D 1| nIRQ | | Goes low on interrupt from RFM
' 9 RB1/TX | 0| nSel | | Bring low to select RFM
'------------------------------------------------------------------------------------------------------------------------------------
'10 RB4/RX |D 1|SDO | | Input from RFM output
'11 RB5/SS |D 0|TX_ANT | | Selector for TX Mode
'12 RB6/T1CKI |D 0|RX_ANT | | Selector for RX Mode
'13 RB7 |D 0| | | N/C
'14 Vdd | | | | +3V
'15 RA6/OSC2 |D 1| | | N/C
'16 RA7/OSC1 |D 1| | | N/C
'17 RB2 |D 0|SCK | | Clock signal to RFM
'18 RB3 |D 0|SDI | | Output to RFM input
'------------------------------------------------------------------------------------------------------------------------------------
'Be sure to REM out the line "__CONFIG _CONFIG1H, _XT_OSC_1H" in the \PBP\18F1320.INC file!
'@ __CONFIG _CONFIG1H, _INTIO2_OSC_1H
'@ __CONFIG _CONFIG3H, _MCLRE_OFF_3H
'**********
' DEFINES
'**********
DEFINE OSC 4
'***********
' CONSTANTS
'***********
PacketSize CON 3
'****************
' Hardware Setup
'****************
'All Ports Digital
'un-rem this line for 18F1320...
ADCON1 = $7F
'...or un-rem these two for 16F88
'ANSEL = 0
'CMCON = 7
OSCCON = 100000 '4MHz
PORTA = 110111
TRISA = 000001
PORTB = 000010
TRISB = 010001
'*********
' ALIASES
'*********
nButton VAR PORTA.0
LED VAR PORTA.1
SDO VAR PORTB.4
SDI VAR PORTB.3
SCK VAR PORTB.2
nSEL VAR PORTB.1
nIRQ VAR PORTB.0
TX_ANT VAR PORTB.5
RX_ANT VAR PORTB.6
'***********
' VARIABLES
'***********
nAddress VAR BYTE
nOutData VAR BYTE
nInData VAR BYTE
nStatus1 VAR BYTE
nStatus2 VAR BYTE
i var byte
anRxBuf var byte[35] 'at least 2x the packet length
anTxBuf VAR BYTE[PacketSize]
nCheckSum var byte
'**********************
' Initialize Variables
'**********************
nSEL = 1
LED = 1
PAUSE 1000
LED = 0
for i = 0 to 34
anRxBuf[i] = $ff
next i
for i = 0 to PacketSize-1
anTxBuf[i] = $30+i
next i
'Initialize the RFM22 Registers
GOSUB InitRFM
'Set up to receive data
GOSUB To_RX_Mode
'Jump to the main program loop
GOTO MainLoop
'*******************************************************************************
' HELPER FUNCTIONS
'*******************************************************************************
'Write a single byte to the RFM22
SPI_Out:
nSel = 0 'Select the RFM22
PAUSEUS 50 'Give it a moment
nAddress.7 = 1 'Tell the RFM22 we're doing a WRITE transaction
SHIFTOUT SDI,SCK,1,[nAddress,nOutData] 'Stuff the datum into the RFM22
nSel = 1 'De-select the RFM22
PAUSEUS 100 'Unnecessary?
RETURN
'Read a single byte from the RFM22
SPI_In:
nSel = 0 'Select the RFM22
PAUSEUS 50 'Give it a moment
nAddress.7 = 0 'Tell the RFM22 we're doing a READ transaction
SHIFTOUT SDI,SCK,1,[nAddress] 'First, write the ADDRESS we want to read from
SHIFTIN SDO,SCK,0,[nInData] 'Second, take in the datum
nSel = 1 'De-select the RFM22
PAUSEUS 100 'Unnecessary?
RETURN
'Send the data contained in the anTXBuf array
To_TX_Mode:
'SEROUT2 PORTA.3,49236,["Entering RX Mode...",13,10]
NAddress = $07 : noutData = $01 : GOSUB SPI_Out 'Set READY mode in RFM22
RX_ANT = 0 'Configure for transmission
TX_ANT = 1 'Configure for transmission
Pause 50 'Give it a moment
nAddress = $08 : noutData = $03 : GOSUB SPI_Out 'Tell it we want to reset the FIFO
nAddress = $08 : noutData = $00 : GOSUB SPI_Out 'Reset the FIFO
nAddress = $34 : noutData = 64 : GOSUB SPI_Out 'Set the preamble = 64nibble
nAddress = $3E : noutData = PacketSize : GOSUB SPI_Out 'Set the packet length
nCheckSum = 0
for i = 0 to PacketSize-2
nAddress = $7F : noutData = anTXBuf[i] : GOSUB SPI_Out 'Write the data to the TX FIFO
nCheckSum = nChecksum + antxbuf[i] 'Calculate the checksum
next i
nAddress = $7F : noutData = nCheckSum : GOSUB SPI_Out 'Write the checksum as the last byte
nAddress = $05 : noutData = $04 : GOSUB SPI_Out 'Enable the packet sent interrupt
nAddress = $03 : GOSUB SPI_In : nStatus1 = nInData 'Clear interrupts part 1
nAddress = $04 : GOSUB SPI_In : nStatus2 = nInData 'Clear interrupts part 2
LED = 1 'Turn on LED immediatly prior to start of transmission
nAddress = $07 : noutData = 9 : GOSUB SPI_Out 'Tell the RFM22 to start the transmission
'wait for the interrupt to tell us the transmission is complete
TXWait:
if nirq = 1 then
goto TXWait
endif
pause 100 'This pause exists only to make the LED blink long enough to see
LED = 0 'turn off the LED
RETURN
'Set up RFM22 hardware to receive mode
To_RX_Mode:
'SEROUT2 PORTA.3,49236,["Entering RX Mode...",13,10]
RX_ANT = 0 'Turn off receiver
TX_ANT = 0 'Turn off transmitter
nAddress = $03 : GOSUB SPI_In : nStatus1 = nInData 'Clear interrupts part 1
nAddress = $04 : GOSUB SPI_In : nStatus2 = nInData 'Clear interrupts part 2
nAddress = $07 : noutData = $01 : GOSUB SPI_Out 'Set READY mode in RFM22
pause 50 'Give it a moment
RX_ANT = 1 'Configure for reception
TX_ANT = 0 'Configure for reception
pause 50 'Give it a moment
GOSUB RX_Reset 'Configure RFM22 registers for reception
PAUSEUS 10 'Give it a moment
RETURN
'Configure RFM22 registers for reception
RX_Reset:
'Set READY Mode (Xtal is ON)
nAddress = $07 : noutData = $01 : GOSUB SPI_Out
'Set the RX FIFO Almost Full interrupt level to 17 (same as the packet size)
nAddress = $7E : noutData = PacketSize : GOSUB SPI_Out
'Clear the RX FIFO and disable multi-packet
nAddress = $08 : noutData = $03 : GOSUB SPI_Out
'Second write to complete clearing FIFO buffers
nAddress = $08 : noutData = $00 : GOSUB SPI_Out
'READY mode set, RX on in Manual Receiver Mode
nAddress = $07 : noutData = $05 : GOSUB SPI_Out
'Disable extra/oddball interrupts
nAddress = $06 : noutData = 000000 : GOSUB SPI_Out
'Valid Packet Received interrupt is enabled
nAddress = $05 : noutData = $02 : GOSUB SPI_Out
'Read the interrupt registers (in order to clear them)
nAddress = $03 : GOSUB SPI_In : nStatus1 = nInData
nAddress = $04 : GOSUB SPI_In : nStatus2 = nInData
RETURN
'Initial configuration of RFM22 Registers
InitRFM:
'Disable Interrupts
nAddress = $06 : noutData = $00 : GOSUB SPI_Out
'Set READY mode
nAddress = $07 : nOutData = $01 : GOSUB SPI_Out
'cap = 12.5 pF
nAddress = $09 : nOutData = $7F : GOSUB SPI_Out
'Clk output is 2 MHz
nAddress = $0A : nOutData = $05 : GOSUB SPI_Out
'GPIO0 is RX data output
nAddress = $0B : nOutData = $F4 : GOSUB SPI_Out
'GPIO1 Tx/Rx data clk output
nAddress = $0C : nOutData = $EF : GOSUB SPI_Out
'GPIO2 for MCLK output
nAddress = $0D : nOutData = $00 : GOSUB SPI_Out
'GPIO port use default value
nAddress = $0E : nOutData = $00 : GOSUB SPI_Out
'no ADC used
nAddress = $0F : nOutData = $70 : GOSUB SPI_Out
nAddress = $10 : nOutData = $00 : GOSUB SPI_Out
'no temp sensor used
nAddress = $12 : nOutData = $00 : GOSUB SPI_Out
nAddress = $13 : nOutData = $00 : GOSUB SPI_Out
'no manchester code, no data whiting, data rate < 30Kbps
nAddress = $70 : nOutData = $20 : GOSUB SPI_Out
'IF filter bandwidth
nAddress = $1C : nOutData = $1D : GOSUB SPI_Out
'AFC loop
nAddress = $1D : nOutData = $40 : GOSUB SPI_Out
'Clock Recovery
nAddress = $20 : nOutData = $A1 : GOSUB SPI_Out
nAddress = $21 : nOutData = $20 : GOSUB SPI_Out
nAddress = $22 : nOutData = $4E : GOSUB SPI_Out
nAddress = $23 : nOutData = $A5 : GOSUB SPI_Out
'Clock Recovery timing
nAddress = $24 : nOutData = $00 : GOSUB SPI_Out
nAddress = $25 : nOutData = $0A : GOSUB SPI_Out
'zero OOK counter
nAddress = $2C : nOutData = $00 : GOSUB SPI_Out
nAddress = $2D : nOutData = $00 : GOSUB SPI_Out
'slicer peak hold
nAddress = $2E : nOutData = $00 : GOSUB SPI_Out
'TX data rate (4800 baud)
nAddress = $6E : nOutData = $27 : GOSUB SPI_Out
nAddress = $6F : nOutData = $52 : GOSUB SPI_Out
'Data Access Control
nAddress = $30 : nOutData = $8C : GOSUB SPI_Out
'Header Control
nAddress = $32 : nOutData = $FF : GOSUB SPI_Out
' header 3, 2, 1,0 used for head length, fixed packet length, synchronize word length 3, 2,
nAddress = $33 : nOutData = $42 : GOSUB SPI_Out
'64 nibble = 32byte preamble
nAddress = $34 : nOutData = 64 : GOSUB SPI_Out
'0x35 need to detect 20bit preamble
nAddress = $35 : nOutData = $20 : GOSUB SPI_Out
' synchronize word
nAddress = $36 : nOutData = $2D : GOSUB SPI_Out
nAddress = $37 : nOutData = $D4 : GOSUB SPI_Out
nAddress = $38 : nOutData = $00 : GOSUB SPI_Out
nAddress = $39 : nOutData = $00 : GOSUB SPI_Out
' set tx header
nAddress = $3A : nOutData = "h" : GOSUB SPI_Out
nAddress = $3B : nOutData = "o" : GOSUB SPI_Out
nAddress = $3C : nOutData = "p" : GOSUB SPI_Out
nAddress = $3D : nOutData = "e" : GOSUB SPI_Out
' total tx 17 byte
nAddress = $3E : nOutData = PacketSize : GOSUB SPI_Out
' set rx header
nAddress = $3F : nOutData = "h" : GOSUB SPI_Out
nAddress = $40 : nOutData = "o" : GOSUB SPI_Out
nAddress = $41 : nOutData = "p" : GOSUB SPI_Out
nAddress = $42 : nOutData = "e" : GOSUB SPI_Out
' all the bits to be checked
nAddress = $43 : nOutData = $FF : GOSUB SPI_Out
nAddress = $44 : nOutData = $FF : GOSUB SPI_Out
nAddress = $45 : nOutData = $FF : GOSUB SPI_Out
nAddress = $46 : nOutData = $FF : GOSUB SPI_Out
'Reserved
nAddress = $56 : nOutData = $01 : GOSUB SPI_Out
' tx power to Max
nAddress = $6D : nOutData = $07 : GOSUB SPI_Out
' no frequency hopping
nAddress = $79 : nOutData = $00 : GOSUB SPI_Out
nAddress = $7A : nOutData = $00 : GOSUB SPI_Out
' Gfsk, fd[8] =0, no invert for Tx/Rx data, fifo mode, txclk -->gpio
nAddress = $71 : nOutData = $22 : GOSUB SPI_Out
' frequency deviation setting to 35k = 56*625
nAddress = $72 : nOutData = $38 : GOSUB SPI_Out
' no frequency offset
nAddress = $73 : nOutData = $00 : GOSUB SPI_Out
nAddress = $74 : nOutData = $00 : GOSUB SPI_Out
' frequency set to 434MHz
nAddress = $75 : nOutData = $53 : GOSUB SPI_Out
nAddress = $76 : nOutData = $64 : GOSUB SPI_Out
nAddress = $77 : nOutData = $00 : GOSUB SPI_Out
'NOTE:
'The following 5 registers are listed as RESERVED in the RFM22B v1.1
'datasheet. Try remming them if problems are experienced
nAddress = $5A : nOutData = $7F : GOSUB SPI_Out
nAddress = $59 : nOutData = $40 : GOSUB SPI_Out
nAddress = $58 : nOutData = $80 : GOSUB SPI_Out
nAddress = $6A : nOutData = $0B : GOSUB SPI_Out
nAddress = $68 : nOutData = $04 : GOSUB SPI_Out
'Clock Recovery Gearshift Override
nAddress = $1F : nOutData = $03 : GOSUB SPI_Out
PAUSEUS 1000 'Let the settings settle
return
'*******************************************************************************
' END OF HELPER FUNCTIONS, BEGIN MAIN PROGRAM LOOP
'*******************************************************************************
MainLoop:
'nIRQ Pin Indicates that we have received a packet
if nIRQ = 0 then 'Packet received
'Clear the interrupt
nAddress = $03 : GOSUB SPI_In : nStatus1 = nInData
nAddress = $04 : GOSUB SPI_In : nStatus2 = nInData
'Read in the data
for i = 0 to PacketSize-1
nAddress = $7F : GOSUB SPI_In : anRxBuf[i] = nInData
next i
nSel = 1 'unncecessary?
'Calculate the checksum...
nCheckSum = 0
for i = 0 to PacketSize-2
nCheckSum = nCheckSum + anRxBuf[i]
'SEROUT2 PORTA.3,49236,[Ihex2 anRxBuf[i]," "]
anRxBuf[i] = 0
next i
'SEROUT2 PORTA.3,49236,[13,10,"ChkSum=",Ihex2 anRxBuf[i],13,10]
'Verify that the calculate checksum matches the last byte in the packet
if nChecksum = anRxBuf[PacketSize-1] then
LED = 1
'SEROUT2 PORTA.3,49236,["ChkSum MATCH!",13,10]
PAUSE 500
LED = 0;
ENDIF
GOSUB rx_reset; // rx reset
endif
'Check for button press
if nButton = 0 then 'the button is pressed...
'SEROUT2 PORTA.3,49236,["Xmitting",13,10]
'Here would be a good place to load the relevant data into anTxBuf
gosub To_TX_Mode
'and return back to RX_Mode
GOSUB To_RX_Mode
endif
GOTO MainLoop
Best Regards,
Bookmarks