Doug
Code:
'****************************************************************
'* Name : MRF24J40_xmit.BAS *
'* Author : Douglas McDonald *
'* Notice : Copyright (c) 2010 [Douglas McDonald] *
'* : All Rights Reserved *
'* Date : 6/10/2010 *
'* Version : 1.0 *
'* Notes : Setup & test MiWi (not using MiWi Stack) *
'* : Transmit side *
'* THIS IS FOR 18F4550 & OLIMX BOARD ONLY
'* Special thanks to Clark Leach for his great help
'* and sample code
'* READ!!!!!!!!!!!!!!!!!!!!!!
'* I left in the MSSP SPI but commented out sincr I'm using
'* the PDS MSSP macros
'****************************************************************
'* THIS IS FOR 18F4550 & OLIMX BOARD ONLY you must change port for your board
Device = 18F4550
Xtal = 20
Stack_Size = 20
Clear
'Optimiser_level = 3
Config_Start
PLLDIV = 5 ; Divide by 5 (20 MHz oscillator input)
FOSC = HS ; HS oscillator, HS used by USB
WDT = OFF ; HW Disabled - SW Controlled
Config_End
DelayMS 200 'setteling
Include "SPI.inc"
Include "MRF24J40def.inc" 'from Clark
All_Digital = TRUE
TRISB = %00000100 'RB2 is interrupt from MRF24
TRISC = 0x00
TRISD = 0x00
TRISA = 0x00
'*****************vars **********************
Dim Byte_temp As Byte
Dim wrd_temp As Word
Dim B_retval As Byte
Dim cnt As Byte
Dim i As Word
'Dim xaddress As Word
Dim rxRadioBuffer[128] As Byte
Dim txRadioBuffer[128] As Byte
Dim HeaderLength As Byte
Dim FrameLength As Byte
Dim txHeader As Byte
Dim txPayLoad As Byte
Dim bRetVal As Byte
'Dim wRetVal As Word
'Dim fifo As Byte
Dim channel As Byte
Dim IEEEseqNumber As Byte
Dim txStatus As Byte
Dim StringTemp As String * 8
Dim txDestination As Word
Dim MRFaddr As Word
Dim MRFdata As Byte
'
'***radio status ***** These are for future use when adding State machine
'Dim radioStatus_error As Byte
Dim radioStatus_rxFifoHasData As Byte
'Dim radioStatus_txFifoHasData As Byte
'Dim radioStatus_rxHasDataPayload As Byte
'Dim radioStatus_txHasDataPayload As Byte
'Dim radioStatus_txUsesAckReq As Byte
'Dim radioStatus_txsecurity As Byte
'Dim radioStatus_Sleeping As Byte
''******************
'*******************************************************************
'* since there are no type structers in PDS I'm using arrays
'* in the end it would save space for falgs if I used byte vars and
'* mask to flags but that can come later
Dim FrameControl As Word
'FrameControl = %0010001000100110
FrameControl = %1001100001000001
'index Value
' frametype 3 bits 001
' securityEnabled 1 0
' framepending 1 0
' ackRequest 1 0
' intraPAN 1 1
' don't care 1 0
' don't care 2 00
' destAddressMode 2 10 0x02
' frameVersion 2 01 datasheet says this is reserved
' sourceAddressMode 2 10
Dim RadioState As Byte
' 0 Radio_Idle 0 waiting for incoming or outgoing
' 1 rx_Busy waiting for upperlayers to process frame
' 2 tx_pending waiting for transmit status from interrupt
' 3 radio_error oops
Dim RadioConfig[4] As Byte
' 0 shortAddL myShortAddress lo byte
' 1 shortAddH myShortAddress hi Byte
' 2 PanIDL my PANID lo byte
' 3 PanIDH my PANID Hi Byte
' 4 currentChannel
RadioConfig[0] = 0xcd 'need to change for each node
RadioConfig[1] = 0xab
RadioConfig[2] = 0x01
RadioConfig[3] = 0x02
'Dim MACframeCntl[3] As Word
' 0 dataSeq 'just need one byte
' 1 destPAN
' 2 dest
' 3 source
'************************************
'******** Setup interrupt 18F4550**********
Symbol GIE = INTCON.7 'global interrupt enable
Symbol INT2IE = INTCON3.4 'enable int2, portb.2
Symbol INT2IF = INTCON3.1 'interrupt flag
Symbol INTEDG2 = INTCON2.4 ' Interrupt Edge Select
Symbol INT2IP = INTCON3.7
Symbol IPEN = RCON.7
GIE = 0
INT2IE = 0
'**********************************
'******SPI CS & Reset**************
'Symbol sck = PORTB.1
'Symbol si = PORTB.0
'Symbol so = PORTC.7
Symbol cs = PORTB.3
Symbol Resetn = PORTB.4
'*************************
Symbol TX_BUFFER_SIZE = 127 'same as #define
Symbol RX_BUFFER_SIZE = 127
Resetn = 1 'Hold Hi MRF24J40 reset pin high = not in reset
cs = 1 'Hold Hi chip select high = not selected
'Cls 'for debug with easypic4
'Print At 1,1, "Startup"
'DelayMS 2000
'**************************************************************************
'**SPI Setup I'm using MSSP macros supplied from PDS
'**You can use the MSSP module directly. uncomment D0_SPI & Read_SPI
'**comment out SPI macro calls
'----------------------------------------------------------------------
OpenSPI(SPI_FOSC_64 , MODE_00 , SMPMID) 'open SPI_V1 set of pic's
'MSSP = MASTER SYNCHROUS SERIAL PORT MODULE ' SPI Port Setup
'SSPSTAT = %01000000 ' %X1XXXXXX ' 1 = transmitted On falling Clock Edge
'SSPCON1 = %00100000 ' %xx1xxxxx ' 1 = ENABLES SCK SDO & SDI
'**************************************************************************
'
'******configure interrupts ***********************************************
'On_Hardware_Interrupt GoTo Radio_ISR 'tell pds to use interrupt
GIE = 0 'disable global int
IPEN = 0 'disable high pri interupts
INT2IP =0 'disable int2 high pri not using priorty
INT2IE = 0 'disable int2 portb.2
INTEDG2 = 0 'rising
'*************************************************************************
GoSub Initialize ' setup & Initialize MRF24J40
main:
High PORTD.3
DelayMS 500
'GoSub SendMACframe
GoSub LoadMessage
' GoSub Initialize
Low PORTD.3
DelayMS 500
'INT2IE = 1
GoTo main
'***Not done yet but will be used!!!!!!!!!!!!!!!!!!!!!!
'*********************Do tasks****************************
'radioTasks: 'needs work
' Select RadioState
' Case 0 'radio idle
' 'if xcvr is holding incoming grab it or if upper layer
' 'has payload then send it
' If RadioStatus[4] = 1 Then 'txHasPayLoad
' GoSub sendndMACframe
' startTxTimer ??
' RadioState = 2 'tx pending
' ElseIf RadioStatus[1] = 1 'rxfifoHasData
' gosub getMACframe
' RadioState = 1 'rxBusy
' else
' gosub releaseRXbuffer
' endif
' case 2 'tx pending
' 'if transmission complete indicate completion
' 'and pass transmission status upstream
' case 1' rx_busy
' ' if upperlayer(s) are done with incoming frame
' ' then renable reception and Ack request response
' endselect
'return
'***Not done yet but will be used!!!!!!!!!!!!!!!!!!!!!!
'**************ISR *************************
'High_Int_Sub_Start
'Radio_ISR:
'INT2IE = 0 'disable interrupt
'INT2IF = 0 'clear int flag
'Context Save
' High PORTD.3
' DelayMS 5
' GoSub ReadShortRamAddress [INTSTAT],bRetVal 'what caused the interrupt
' IntFlag = bRetVal
' Select Case IntFlag
' Case 0 'false interrupt ??
' INT2IE = 1 'enable interrupt
' Low PORTD.3
' Context Restore
' High_Int_Sub_End 'get out of here
' Case 0x01 '000000001 'TXNIF bit
' radioStatus_txFifoHasData = 0 'txFifoHasData signal transmission complete
' GoSub ReadShortRamAddress [TXSTAT],bRetVal 'read transmission status
' txStatus = bRetVal 'ok what now????
' GoSub WriteShortRamAddress [RXFLUSH,0x01] 'flush receive buffer
' Case 0x08 'IntFlag.3 %00001000 rxif
' If radioStatus_rxFifoHasData = 0 Then 'if not busy
' radioStatus_rxFifoHasData = 1 'make busy
' Else
' GoSub WriteShortRamAddress [RXFLUSH,0x01] 'Ignor this frame
' EndIf
' Case Else
' GoSub WriteShortRamAddress [RXFLUSH,0x01] 'Ignor this frame
' EndSelect
' Low PORTD.3
' GoSub DisplayDebug "ISR ",bin intflag
'INT2IE = 1 'enable interrupt
'Context Restore
'High_Int_Sub_End
''Return
'**************** releaseRXbuffer *************
releaseRXbuffer:
INT2IE = 0 'disable interrupt
GoSub WriteShortRamAddress [RXFLUSH,0x01] 'flush buffer
GoSub WriteShortRamAddress [RXMCR,0x00] 're-enable Ack response
radioStatus_rxFifoHasData = 0 'reset
'rxsize = 0 don't have yet
INT2IE = 1 'enable interrupt
Return
'************LoadMessage***********************
LoadMessage:
For i = 0 To 127 'make sure there is valid data in array
txRadioBuffer[i] = i
Next
txDestination = 0xFFFF ' Set the destination address
txPayLoad = 16 ' set amount of data to xmitt from array(payload)
're-write first 11 bytes with hdrLen, frm Len and Header
'// Compute and send header and frame length
HeaderLength = 9 '(index 2 to 10, 9 bytes)
FrameLength = HeaderLength + txPayLoad '9 (0-8)+ 16 (0-15) = 25
'address 0-1 '2 bytes
txRadioBuffer[0] = HeaderLength
txRadioBuffer[1] = FrameLength
'address 2-10 '8 bytes
txRadioBuffer[2] = FrameControl.LowByte 'framecontrol[0] 0x26
txRadioBuffer[3] = FrameControl.HighByte 'framecontrol[1] 0x22
txRadioBuffer[4] = IEEEseqNumber 'IEEEseqNumber++
txRadioBuffer[5] = 0x01 'myPANID[0]
txRadioBuffer[6] = 0x02 'myPANID[1]
'txRadioBuffer[7] = 0xcd '& 0x00FF 'networkTX.dest & 0x00FF
'txRadioBuffer[8] = 0xef '>> 8 'networkTX.dest >> 8
txRadioBuffer[7] = txDestination.LowByte 'networkTX.dest & 0x00FF
txRadioBuffer[8] = txDestination.HighByte 'networkTX.dest >> 8
txRadioBuffer[9] = 0xcd 'myShortAddress[0]
txRadioBuffer[10] = 0xab 'myShortAddress[1]
Inc IEEEseqNumber 'IEEEseqNumber = IEEEseqNumber +1
'fifo = 0 = i
For i = 0 To FrameLength +1
GoSub WriteLongRamAddress [i,txRadioBuffer[i]] 'send header + payload
Next
'// Transmission acknowledgement request
'writeSAR(TXNCON,0x01);
GoSub WriteShortRamAddress [TXNCON, 0x01]
Return
'***Not done yet but will be used!!!!!!!!!!!!!!!!!!!!!!
''*************receive packet**********************
getMACframe:
'// Disable interrupts, disable reception
'RFIE = 0;
GoSub WriteShortRamAddress [BBREG1, 0x04]
bRetVal = 0
'// Read frame size (add 2 for LQI, RSSI appended by RXMAC)
'// If not too big, copy from transceiver FIFO to rxRadioBuffer
'rxRadioBuffer[0] = readLAR(RX_FIFO) + 2;
GoSub ReadLongRamAddress [RX_FIFO],bRetVal
rxRadioBuffer[0] = bRetVal + 2
If rxRadioBuffer[0] < RX_BUFFER_SIZE Then
GoSub WriteShortRamAddress [RXMCR, 0x20] '// Disable automatic Ack response
For i = 1 To rxRadioBuffer[0]
GoSub ReadLongRamAddress [RX_FIFO + i],bRetVal
rxRadioBuffer[i] = bRetVal
Next
Else
GoSub WriteShortRamAddress [RXFLUSH, 0x01]
'RFIE = 1
GoSub WriteShortRamAddress [BBREG1, 0x00]
End If
Return
'******************* Write Short Adress ****************************
WriteShortRamAddress:
'*******************************************************************
Pop MRFdata 'pop data argument passed
Pop MRFaddr.LowByte 'pop address argument passed
MRFaddr.LowByte = MRFaddr.LowByte << 1 'put address bits in position
MRFaddr.LowByte = MRFaddr.LowByte & 0x7F 'clear bit 7 to indicate short address
MRFaddr.LowByte = MRFaddr.LowByte | 1 'set bit 0 to indicate write operation
bcf cs
nop '18F4550 seems to need this
'send short address
WriteSPI(MRFaddr.LowByte)
' GoSub Do_SPI1 [ MRFaddr.LowByte] 'if using MSSP
nop '18F4550 seems to need this
'send data
WriteSPI(MRFdata)
' GoSub Do_SPI1 [MRFdata] 'if using MSSP
nop
nop
bsf cs
Return
'******************* Write Long Adress ****************************
WriteLongRamAddress:
'**********************************************************************
Pop MRFdata 'pop data argument
Pop MRFaddr 'pop address argument
MRFaddr = MRFaddr << 5 'shift to bits 5-14
MRFaddr = MRFaddr | 0x8010 'set bit 15 to indicate long addr
'and bit 4 to indicate a write
bcf cs
nop
'send long address
WriteSPI(MRFaddr.HighByte)
' GoSub Do_SPI1 [MRFaddr.HighByte]
nop '18F4550 seems to need this
WriteSPI(MRFaddr.LowByte)
' GoSub Do_SPI1 [MRFaddr.LowByte]
nop
'send data
WriteSPI(MRFdata)
' GoSub Do_SPI1 [MRFdata]
nop
bsf cs
Return
'*******************Read Short Adress ****************************
ReadShortRamAddress:
' Dim RSAD As Byte 'short address
' Pop RSAD 'this pops what was pushed in the call to here
' bcf cs
' nop
' 'brd_temp = (RSAD << 1) & %01111110
' Byte_temp = (RSAD << 1)
' WriteSPI(Byte_temp)
' nop '18F4550 seems to need this
' While DataReadySPI = 1 'get return value byte
' B_retval = ReadSPI()
' Wend
' nop
' bsf cs
'**********************************************************************
Pop MRFaddr.LowByte 'pop address argument
MRFaddr.LowByte = MRFaddr.LowByte << 1 'shift address bits into position
MRFaddr.LowByte = MRFaddr.LowByte & 0x7F 'just to make sure bit 7 is 0
bcf cs
nop
'send short address
WriteSPI(MRFaddr.LowByte)
' GoSub Do_SPI1 [MRFaddr.LowByte]
nop '18F4550 seems to need this
'get return value
While DataReadySPI = 1
MRFdata = ReadSPI()
' GoSub Read_SPI[],bRetVal
Wend
nop
bsf cs
Return MRFdata
'Return B_retval
'*******************Read Long Adress ****************************
ReadLongRamAddress:
'*****************************************************************************
Pop MRFaddr 'pop address argument
MRFaddr = MRFaddr << 5 'shift to bits 5-14
MRFaddr = MRFaddr | 0x8000 'set bit 15 to indicate long addr
bcf cs
nop
'send long address
WriteSPI(MRFaddr.HighByte)
' GoSub Do_SPI1 [MRFaddr.HighByte]
nop '18F4550 seems to need this
WriteSPI(MRFaddr.LowByte)
' GoSub Do_SPI1 [MRFaddr.LowByte]
nop '18F4550 seems to need this
' GoSub Read_SPI[],bRetVal
'get data
While DataReadySPI = 1 'read byte
MRFdata= ReadSPI()
Wend
nop
bsf cs
Return MRFdata
'****************************Initialize*****************************
Initialize:
'do hardware reset
Resetn = 0 'set reset low
DelayMS 3
Resetn = 1 'set reset high
DelayMS 3
'soft reset RF Module software
GoSub WriteShortRamAddress [SOFTRST, 0x07]
'take out of reset RF Module
bRetVal = 255
While (bRetVal & 0x07) != 0x00
GoSub ReadShortRamAddress [SOFTRST],bRetVal 'call read routine & return value
' 'whats returned ??? RS232 for debug
GoSub DisplayDebug [ "Reset",bRetVal]
Inc cnt
If cnt = 5 Then Break
Wend
'Flush RX FIFO
GoSub WriteShortRamAddress [RXFLUSH, 0x01]
'Program short mac address, 0xffff
GoSub WriteShortRamAddress [SADRL,0xcd]
GoSub WriteShortRamAddress [SADRH,0xab]
GoSub WriteShortRamAddress [PANIDL,0x01]
GoSub WriteShortRamAddress [PANIDH,0x02]
' /* Program Long MAC Address*/
GoSub WriteShortRamAddress [EADR0,0x4e] 'N
GoSub WriteShortRamAddress [EADR1,0x4f] 'O
GoSub WriteShortRamAddress [EADR2,0x54] 'T
GoSub WriteShortRamAddress [EADR3,0x42] 'B
GoSub WriteShortRamAddress [EADR4,0x55] 'U
GoSub WriteShortRamAddress [EADR5,0x53] 'S
GoSub WriteShortRamAddress [EADR6,0x54] 'T
GoSub WriteShortRamAddress [EADR7,0x4d] 'M *****Need To change To slave S
GoSub WriteLongRamAddress [RFCON2,0x80] ' PLL enabled
GoSub WriteLongRamAddress [RFCON3,0x20] ' -5 db power
GoSub WriteLongRamAddress [RFCON6,0x90] 'Program RSSI ADC with 2.5mhz clock
GoSub WriteLongRamAddress [RFCON7,0x80] 'sleep clock = 100khz internal
GoSub WriteLongRamAddress [RFCON8,0x10] ' enhanced VCO set
GoSub WriteLongRamAddress [SLPCON0,0x01] 'disable sleep clock, int falling edge
GoSub WriteLongRamAddress [SLPCON1,0x20] 'disable clock oout, divisor = 1
'***added 4-21*****
' GoSub WriteShortRamAddress [RXMCR, 0xa3] 'CRC Disable, ACK disable,no pan,no coordinator Error bit,no pkt discard*
'***************
'/* Program CCA mode using RSSI */
GoSub WriteShortRamAddress [BBREG2,0x80] 'CCa mode using RSSI
'/* Program CCA mode using RSSI */
GoSub WriteShortRamAddress [BBREG6,0x40] 'Enable the packet RSSI
'/* Program CCA, RSSI threshold values */
GoSub WriteShortRamAddress [CCAEDTH,0x60] 'set CCA, RSSI threshold values
'?????????GoSub WriteLongRamAddress '[RFCTRL0,0x00] 'set channel 11
GoSub WriteShortRamAddress [PACON2,0x98] 'enable FIFO, Set TXONTS = 6 (96uS)
GoSub WriteShortRamAddress [TXSTBL,0x95] 'TX stabilixation book recommends 0x93
bRetVal = 0xff 'clr return value
cnt = 0
While (bRetVal & 0xE0) != 0xA0
GoSub ReadLongRamAddress [RFSTATE],bRetVal 'read long address
'whats returned ???
GoSub DisplayDebug ["RF State",bRetVal]
Inc cnt
If cnt = 5 Then Break
Wend
' '*****configure transceiver interrupt control
GoSub WriteShortRamAddress [INTCONT,0xF6] 'enable RX,TXN
GoSub WriteLongRamAddress [RFCON1,0x01]
'set channel numbernot sure this is correct
' (((channel-11 << 4 ) | 0x02))
channel = ((6 << 4) | 0x02)
GoSub WriteLongRamAddress [RFCON0,channel] 'set channel 17
'reset RF Module
GoSub WriteShortRamAddress [RFCTL, 0x04] 'reset
DelayMS 1
'take out of reset RF Module
GoSub WriteShortRamAddress [RFCTL, 0x00] 'release reset
DelayUS 200 'as per datasheet wait at least 192uS
'*** some var & array config ***************
For i = 0 To TX_BUFFER_SIZE
txRadioBuffer[i] = i '0x00 put dummy data in
Next
For i = 0 To RX_BUFFER_SIZE 'clear rx buffer
rxRadioBuffer[i] = 0x00
Next
txPayLoad = 0
IEEEseqNumber = 0
'***Not done yet but will be used!!!!!!!!!!!!!!!!!!!!!!
' // Enable RF Interrupt
' RFIF = 0;
' RFIE = 1;
'GIE = 1 'enable global int
'IPEN = 0 'disable high pri interupts
'INT2IP =0 'disable int2 high pri not using priorty
'INT2IE = 1 'enable int2 portb.2
'INTEDG2 = 0 'rising
'******************************************************
Return
'*************** for debug, display to serial or paralle LCD ****************
DisplayDebug:
Dim msg As String * 8
Dim xVal As Byte
'Dim yVal As byte
Pop xVal 'pop byte
'Pop yVal
Pop msg 'pop message string
'for serial LCD
SerOut PORTE.0,84,[0x0c] 'clr display
DelayMS 100
SerOut PORTE.0,84,[msg, " " ,Hex xVal]
DelayMS 1000 'allow time to see LCD
'***for easypic4
' Cls
' Print At 1,1, msg, " " ,Hex xVal
' DelayMS 1000
Return
'******** uncommint if using MSSP SPI directly ************************
'Do_SPI1: 'SPI read / Write
' Dim bdat As Byte
' Pop bdat
' SSPBUF = bdat
' While PIR1.3 = 0
' Wend
' bRetVal = SSPBUF
' PIR1.3 = 0
' 'GoSub DisplayDebug ["Do_SPI ",bRetVal]
'Return
'Read_SPI:
'LOOP: btfss SSPSTAT, BF ;Has data been received (transmit complete)?
'bra LOOP ;No
'movf SSPBUF, W ;WREG reg = contents of SSPBUF
'movwf retval ;Save in user RAM, if data is meaningful
'GoSub DisplayDebug ["RD_SPI ",retval]
'Return retval
' Do_SPI2: 'SPI read / Write
' SSPBUF = 0'SPI_H 'highbyte
' While PIR1.3 = 0: Wend ' TX/RX COMPLETE?
' muxData.HighByte = SSPBUF
' PIR1.3 = 0
' SSPBUF = 0 'SPI_L 'lowbyte
' While PIR1.3 = 0 :Wend
' muxData.LowByte = SSPBUF
' PIR1.3 = 0
'Return


Menu
Recent Articles


Using PDS with SPI GLCD based on ST7565R Controller
Graphic LCDs based on the ST7565 are cheaper then GLCDs with other controllers. SPI requires only four pins. If the circuit