NOTE: This is not a complete work. I believe an SPIreadWrite method needs to be used to shift in the bytes at the same time as it is shifting out. I’m new to the spin language. But this is what i came up with. Feel free to comment suggestions
CON
{
.:RF12B wireless tranciever driver V1.0:.
.:Written by Bill Heaster:.
.:TheCreator at ApexLogic D0t net
.:Adapted from JeeLabs Arduino RF12Driver;.
}
#0, TXIDLE, TXRECV, TXSEND, TXFULL
'Frequency Constants
F433 = 0
F868 = 1
F915 = 2
'RF12 Bits
RF_RECEIVER_ON = $82DD
RF_XMITTER_ON = $823D
RF_IDLE_MODE = $820D
RF_SLEEP_MODE = $8205
RF_WAKEUP_MODE = $8207
RF_TXREG_WRITE = $B800
RF_RX_FIFO_READ= $B000
RF_WAKEUP_TIMER= $E000
'max buffer size
MAXPACKET = 128
'Status Bits
RF_LBD_BIT = $0400
RF_RSSI_BIT = $0100
'Node ID stuff
NODE_BAND = $C0
NODE_ACKANY = $20
NODE_ID = $1F
OBJ
Debug : "SimpleDebug"
VAR
'Pins , state flags, stacks, and buffers
long SDI, SDO, CP, SS, nIRQ, ID, MHZ
long intStack[32]
long rxfill, rxstate, packetSize
byte rf12Buff[MAXPACKET]
long in , out, pos, temp, temp2
byte cog
byte hdr[3]
long count
byte tempCheck, checksum, low, high
PUB Start(DIpin, DOpin, Cpin, SSpin, nIRQpin, NodeIDarg, MHZarg)
Debug.start(115200)
Debug.str(STRING("Debug Started"))
Debug.newline
'Assign global variables with the methods argument
SDI :=DIpin
SDO := DOpin
CP := Cpin
SS := SSpin
nIRQ := nIRQpin
ID := NodeIDarg
MHZ := MHZarg
'Set pin direction of slave select pin, set it to high
dira[SS]~~
dira[SDI]~~
dira[SDO]~
dira[CP]~~
dira[nIRQ]~
outa[SS]~~
'When the interupt pin on the rf12 is pulled low clear it with a fake status read command
'repeat until(ina[nIRQ] == 1)
WriteCommand($0000)
'What is our Mhz
if(MHZ == F433)
WriteCommand($80D8) 'Set registers, 433mhz, 12.5pf
WriteCommand($A4B0) 'Set Frequency Center
if(MHZ == F868)
WriteCommand($80E8)
WriteCommand($A640)
if(MHZ == F915)
WriteCommand($80F8)
WriteCommand($A7D0)
WriteCommand(RF_IDLE_MODE) 'disable Clock , Enable LBD
WriteCommand($C606) '49.2kb/s data rate
WriteCommand($94A0) 'fast VDI, -103Dbm, !gain, 134khz BaseBand
WriteCommand($C2AC) 'DigitalFilter, clock auto lock
WriteCommand($CA8B) 'FIFO8, 1-sync, !ff, DR
WriteCommand($C483) 'AFC
WriteCommand($9850) '90khz, !MP, !OP
WriteCommand($CC77) 'PLL
WriteCommand($E000) 'not using low duty cycle
WriteCommand($C800) ' not using wakeup timer
WriteCommand($C000) '1.0mhz, 2.2v
rxState := TXIDLE
Debug.str(STRING("txidle"))
Debug.newline
'Setup a new COG to handle interrupts
cog := cognew(RX(nIRQ), @intStack)
return cog
PUB Stop
if(cog)
cogstop(cog~-1)
PRI WriteCommand(cmd) | ltemp
Debug.hex(cmd,4)
Debug.newline
outa[CP]~
outa[SS]~
repeat ltemp from 17 to 0
if(cmd & $8000)
write1
else
write0
cmd<=1
outa[CP]~
outa[SS]~~
PUB canSend
if(rxstate==TXRECV & rxfill ==0)
WriteCommand(RF_IDLE_MODE)
rxstate := TXIDLE
return 1
if(rxstate == TXIDLE)
return 1
PUB RX(iPin)
dira[iPin]~
repeat while(ina[iPin]==0 & rxstate == TXRECV)
rf12Buff[rxfill] := ReadFIFO
checksum += rf12Buff[rxfill]
rxfill++
if(rxfill>=MAXPACKET+5)
checksum &= $0FF
WriteCommand(RF_IDLE_MODE)
rxstate := TXFULL
PUB checkData
Debug.str(STRING("CheckData"))
Debug.newline
'If the buffer is full
if(rxstate == TXFULL)
if(packetSize > MAXPACKET)
checksum := -1 'Send bad crc if the packet length is invalid
if(rf12Buff[--rxfill] <> checksum)
checksum := -1
'if the packets destination was to this node, or a broadcast packet
if((rf12Buff[0] == ID | rf12Buff[0]==31)& checksum > -1)
'return 1 to let us know that we need to parse the buffer
return 1
if(rxstate == TXIDLE)
recvStart
return 0
PRI recvStart
rxfill := packetSize := 0
checksum := 0
rxstate := TXRECV
WriteCommand(RF_RECEIVER_ON)
PUB ReadPacket(myBuffer) | myCount
myCount:=0
repeat myCount from 0 to rxfill
myBuffer[myCount] := rf12Buff[myCount]
bytefill(@rf12Buff, 0, MAXPACKET)
WriteCommand(RF_IDLE_MODE)
rxstate := TXIDLE
return myCount
PUB WritePacket(dst, buffer, size, ack) | tempTime
bytefill(@rf12Buff, 0,MAXPACKET)
packetSize := size
checksum := 0
'Assemble the packet into a buffer then send it
'Assemble Header...Destination [0], this node ID[1], 1 for ack 0 for no ack [2]
rf12Buff[0] := dst
rf12Buff[1] := ID
if(ack)
rf12Buff[2] := 1
else
rf12Buff[2] := 0
count:= 0
repeat count from 0 to size
checksum := checksum + buffer[count]
rf12Buff[count+3] :=buffer[count]
checksum &= $0FF
rxstate := TXSEND
WriteCommand(RF_XMITTER_ON)
tempTime := cnt
waitcnt(100_000 + tempTime)
'send preamble
WriteByte($AA)
WriteByte($AA)
WriteByte($AA)
'send sync word
WriteByte($D4)
count:= 0
repeat count from 0 to size+3
WriteByte(rf12Buff[count])
WriteByte(checksum)
WriteByte($AA)
WriteCommand(RF_IDLE_MODE)
rxstate := TXIDLE
PRI Write1 | tempTime
tempTime := cnt
outa[CP]~
waitcnt(10_000 + tempTime)
outa[SDI]~~
tempTime := cnt
waitcnt(100_000 + tempTime)
outa[CP]~~
tempTime:= cnt
waitcnt(10_000 + tempTime)
PRI Write0 | tempTime
tempTime := cnt
outa[CP]~
waitcnt(10_000 + tempTime)
outa[SDI]~
tempTime := cnt
waitcnt(100_000 + tempTime)
outa[CP]~~
tempTime := cnt
waitcnt(10_000 + tempTime)
PRI WriteByte(outByte) | RGIT, tempOut
RGIT := 0
tempOut := RF_TXREG_WRITE | outByte
repeat while RGIT == 0
outa[CP]~
outa[SS]~
outa[SDI]~
outa[CP]~~
if(ina[SDO])
RGIT :=1
else
RGIT := 0
outa[CP]~
outa[SDI]~~
outa[SS]~~
if(RGIT)
WriteCommand(tempOut)
PRI ReadFIFO | myResult, tempTime
'set clock and chip select
outa[CP]~
outa[SS]~
'Skip status bytes
repeat 17
outa[CP]~~
tempTime := cnt
waitcnt(tempTime + 1_000_000)
outa[CP]~
tempTime := cnt
waitcnt(tempTime + 1_000_000)
myResult := 0
repeat 9
myResult <<= 1
if(ina[SDO])
myResult |= 1
outa[CP]~~
tempTime := cnt
waitcnt(tempTime + 1_000_000)
outa[CP]~
tempTime := cnt
waitcnt(tempTime + 1_000_000)
outa[SS]~~
return myResult
{~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
{Test stuff below here}
{~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
PUB getStatus | statByte, TempTime
statByte := 0
WriteCommand($0000)
repeat 17
outa[CP]~~
tempTime := cnt
waitcnt(tempTime + 1_000_000)
if(ina[SDO] == 1)
statByte |=1
outa[CP]~
tempTime := cnt
waitcnt(tempTime + 1_000_000)
statByte <<=1
CON
{
.:RF12B wireless tranciever driver V1.0:.
.:Written by Bill Heaster:.
.:TheCreator at ApexLogic D0t net
.:Adapted from JeeLabs Arduino RF12Driver;.
}
#0, TXIDLE, TXRECV, TXSEND, TXFULL
#0, PRE1, PRE2, PRE3, SYNC, HEADER1, HEADER2, HEADER3, SDATA, POST
'Frequency Constants
F433 = 0
F868 = 1
F915 = 2
'RF12 Bits
RF_RECEIVER_ON = $82DD
RF_XMITTER_ON = $823D
RF_IDLE_MODE = $820D
RF_TXREG_WRITE = $B800
RF_RX_FIFO_READ= $B000
RF_WAKEUP_TIMER= $E000
'max buffer size
MAXPACKET = 128
'Status Bits
RF_LBD_BIT = $0400
RF_RSSI_BIT = $0100
'Node ID stuff
NODE_BAND = $C0
NODE_ACKANY = $20
NODE_ID = $1F
OBJ
Debug : "SimpleDebug"
SPI : "SPI_ASM"
VAR
'Pins , state flags, stacks, and buffers
long SDI, SDO, CP, SS, nIRQ, ID, MHZ
long intStack[128]
long rxfill, rxstate, packetSize
byte rf12Buff[MAXPACKET]
byte rf12hdr[2]
long in , out, temp, temp2
byte cog, pos
long count
byte tempCheck, checksum, low, high
long packetState
PUB Start(DIpin, DOpin, Cpin, SSpin, nIRQpin, NodeIDarg, MHZarg)
SPI.start(1,0)
'Debug.start(115200)
'Debug.str(STRING("Debug Started"))
'Debug.newline
'Assign global variables with the methods argument
SDI :=DIpin
SDO := DOpin
CP := Cpin
SS := SSpin
nIRQ := nIRQpin
ID := NodeIDarg
MHZ := MHZarg
'Set pin direction of slave select pin, set it to high
dira[SS]~~
dira[SDI]~~
dira[SDO]~
dira[CP]~~
dira[nIRQ]~
outa[SS]~~
'When the interupt pin on the rf12 is pulled low clear it with a fake status read command
repeat while(ina[nIRQ] == 0)
WriteCommand($0000)
'What is our Mhz
if(MHZ == F433)
WriteCommand($80D8) 'Set registers, 433mhz, 12.5pf
WriteCommand($A4B0) 'Set Frequency Center
if(MHZ == F868)
WriteCommand($80E8)
WriteCommand($A640)
if(MHZ == F915)
WriteCommand($80F8)
WriteCommand($A7D0)
WriteCommand(RF_IDLE_MODE) 'disable Clock , Enable LBD
WriteCommand($C606) '49.2kb/s data rate
WriteCommand($94A0) 'fast VDI, -103Dbm, !gain, 134khz BaseBand
WriteCommand($C2AC) 'DigitalFilter, clock auto lock
WriteCommand($CA8B) 'FIFO8, 1-sync, !ff, DR
WriteCommand($C483) 'AFC
WriteCommand($9850) '90khz, !MP, !OP
WriteCommand($CC77) 'PLL
WriteCommand($E000) 'not using low duty cycle
WriteCommand($C800) ' not using wakeup timer
WriteCommand($C000) '1.0mhz, 2.2v
rxstate := TXIDLE
'Setup a new COG to handle interrupts
stop
cog := cognew(handleInt(nIRQ), @intStack)
return cog
PUB Stop
if(cog)
cogstop(cog~-1)
PRI WriteCommand(cmd) | myHigh, myLow
' Debug.hex(cmd,4)
' Debug.newline
outa[SS]~
myLow := cmd & $FF
myHigh := cmd >>8
SPI.SHIFTOUT(SDI, CP, SPI#MSBFIRST, 8, myHigh)
SPI.SHIFTOUT(SDI, CP, SPI#MSBFIRST, 8, myLow)
outa[SS]~~
PUB canSend
if(rxstate==TXRECV & rxfill ==0)
WriteCommand(RF_IDLE_MODE)
rxstate := TXIDLE
return 1
if(rxstate == TXIDLE)
return 1
else
return 0
PUB handleInt(iPin)
dira[iPin]~
if(rxstate == TXRECV)
SPI.SHIFTOUT(SDI,CP,SPI#MSBFIRST, 8, RF_RX_FIFO_READ)
SPI.SHIFTIN(SDO,CP,SPI#MSBPRE, 8)
rf12Buff[rxfill] := in
checksum += rf12Buff[rxfill]
rxfill++
if(rxfill>=MAXPACKET+5)
checksum &= $0FF
WriteCommand(RF_IDLE_MODE)
rxstate := TXFULL
if(rxstate==TXSEND & packetState==SDATA)
if(pos <= packetSize)
txByte(rf12Buff[pos++])
else
packetState++
if(rxstate == TXSEND)
case packetState
PRE1: txByte($AA)
packetState++
PRE2: txByte($AA)
packetState++
PRE3: txByte($AA)
packetState++
SYNC : txByte($D4)
pos := 0
packetState++
HEADER1: txByte(rf12hdr[0])
packetState++
HEADER2: txByte(rf12hdr[1])
packetState++
HEADER3: txByte(rf12hdr[2])
packetState++
POST : txByte(checksum)
txByte($AA)
WriteCommand(RF_IDLE_MODE)
rxstate := TXIDLE
OTHER : txByte($AA)
PUB checkData
'If the buffer is full
if(rxstate == TXFULL)
if(packetSize > MAXPACKET)
checksum := -1 'Send bad crc if the packet length is invalid
'if the packets destination was to this node, or a broadcast packet
'if(( rf12Buff[0] == ID | rf12Buff[0]==31)& checksum > -1)
'return 1 to let us know that we need to parse the buffer
return 1
if(rxstate == TXIDLE)
recvStart
return 0
PRI recvStart
rxfill := packetSize := 0
checksum := 0
rxstate := TXRECV
WriteCommand(RF_RECEIVER_ON)
PUB txByte(myByte) | RGIT
RGIT := 0
outa[SS]~
repeat while !RGIT
if(ina[SDO])
RGIT := 1
SPI.SHIFTOUT(SDI, CP, SPI#MSBFIRST, 8, RF_TXREG_WRITE)
SPI.SHIFTOUT(SDI, CP, SPI#MSBFIRST, 8, myByte)
else
RGIT := 0
outa[SS]~~
PUB ReadPacket(myBuffer) | myCount
bytemove(@myBuffer, @rf12Buff, MAXPACKET)
WriteCommand(RF_IDLE_MODE)
rxstate := TXIDLE
return myCount
PUB WritePacket(dst, buffer, size, ack) | tempTime
bytefill(@rf12Buff, 0,MAXPACKET)
packetSize := size
checksum := 0
'Assemble the packet into a buffer
'Assemble Header...Destination [0], this node ID[1], 1 for ack 0 for no ack [2]
rf12hdr[0] := dst
rf12hdr[1] := ID
if(ack)
rf12hdr[2] := 1
else
rf12hdr[2] := 0
bytemove(@rf12Buff, @buffer, size)
repeat count from 0 to size
checksum += rf12buff[count]
checksum &= $0FF
rxstate := TXSEND
packetState := PRE1
WriteCommand(RF_XMITTER_ON)
PUB checkStatus | outByte
outa[SS]~
outByte := SPI.SHIFTIN(SDO, CP, SPI#MSBPRE,8)
outa[SS]~~
return outByte
This is a different version using SPI_ASM object.