Advertisement  

Friday, 29 March 2024
     
 
Main Menu
Home Home
Shop Shop
News News
BASCOM-AVR BASCOM-AVR
BASCOM-8051 BASCOM-8051
Products Products
Application Notes Application Notes
Publications Publications
Links Links
Support Center Support Center
Downloads Downloads
Forum Forum
Resellers Resellers
Contact Us Contact Us
Updates Updates
MCS Wiki MCS Wiki
Online Help
BASCOM-AVR Help BASCOM-AVR Help
BASCOM-8051 Help BASCOM-8051 Help
Contents in Cart
Show Cart
Your Cart is currently empty.
Search the Shop

Products Search

User Login
Username

Password

If you have problem after log in with disappeared login data, please press F5 in your browser

RSS News
 
     
 

 
   
     
 
AN #151 - Nordic nRF24L01 with BASCOM-AVR Print

Nordic nRF24L01 with BASCOM-AVR
Written by Evert Dekker 2007.

Getting a Nordic nRF24L01 single chip 2.4GHZ radio transceiver up and running with Bascom-Avr.

Written by Evert Dekker 2007.

What’s an nRF24L01

The nRF24L01 is a single chip transceiver that’s operate in the 2.4Ghz band with a maximum data rate of 2Mbps. It has also 6 so-called data pipes that allow to connect 6 devices together. In Enhanced shockburst mode the nRF24L01 take’s care over the complete packet transmission, including the ACK and retry’s. No need for Manchester coding etc.

 

What do we need for testing

  • First of all the datasheet,  all significant information is there.
  • To understand the working and functions of the chip you must read the 4 tutorials that Brennen Ball has written ; www.diyembedded.com His sample codes are written in C for the PIC processor, but the rest of the tutorials explains clearly how this chip works.
  • We also need 2x the nRF24L01 chip. You can build your own circuit with the diagram below, but for most of us the chip is to small to solder, it’s much easer when we buy some modules that are complete with the external components. But keep always in mind that the nRF24L01 operates at 3.3V.
  • Then we need 2 test boards with an AVR that’s support hardware SPI, soft SPI is not working. The AVR needs for the test program at least 5K flash memory and Rs-232 connection with a pc.
  • And of course we need Bascom-avr (tested with 1.11.8.3) This application note is too large to use with the demo version, so you need the paid version www.mcselec.com . If you strip the program or split up the TX and RX part it will maybe fit, but I didn’t tried it.

It should also work with Bascom-8051 with some small modifications but that I did also not tried




This is the circuit that I used for testing and where the code is adapted to.

The code is the same for the RX and TX device, with R2 or R3 you choose witch device it need to be.

Keep in mind that the nRF24L01 runs at 3.3V and that the i/o is 5V tolerant.



The code

In the code is enough help to understand it, but here is some additional help.

You must use a chip with hardware spi, the software spi isn’t working. We need the control over the SS (CSN) line our self to get the nRF24L01 working properly.

The nRF24L01 can work in different mode’s. In this sample we choose to use Enhanced shockburst mode so we can demonstrate the benefits in comparing with “regular” transmitters.

In this sample we send a 5 bytes pload with auto ACK, 3x re-transmit, 2Mbps, 0dbm output trough pipe0 on channel 40.

The code is not optimised for speed so it will not reach the 2Mbps. For example, the Spi bus of the nRF24L01 can run max 8Mbps and we are using now 2Mbps, that’s 7372800 / 4 (Clock divided Spi Clockrate). Further there are some delay’s that can be removed if your not using serial communication with a pc that’s very slow in comparison with the air speed. Please read Brennen his tutorials how to calculate maximum air speed. 



 

'------------------------------------------------------------------
' Nordic nRF24L01 data link demo in Enhanced Shockburst mode
' By Evert Dekker 2007 nRF24L01@Evertdekker dotje com
' Created with Bascom-Avr: 1.11.8.3
'------------------------------------------------------------------

$regfile = "M8def.dat"
$crystal = 7372800
$baud = 19200
$hwstack = 40
$swstack = 20
$framesize = 40

'=== Declare sub routines
Declare Sub R_register(byval Command As Byte , Byval C_bytes As Byte)
Declare Sub W_register(byval C_bytes As Byte)

'=== Constante ===
'Define nRF24L01 interrupt flag's
Const Idle_int = &H00 'Idle, no interrupt pending
Const Max_rt = &H10 'Max #of Tx Retrans Interrupt
Const Tx_ds = &H20 'Tx Data Sent Interrupt
Const Rx_dr = &H40 'Rx Data Received
'SPI(nRF24L01) commands
Const Read_reg = &H00 'Define Read Command To Register
Const Write_reg = &H20 'Define Write Command To Register
Const Rd_rx_pload = &H61 'Define Rx Payload Register Address
Const Wr_tx_pload = &HA0  'Define Tx Payload Register Address
Const Flush_tx = &HE1 'Define Flush Tx Register Command
Const Flush_rx = &HE2 'Define Flush Rx Register Command
Const Reuse_tx_pl = &HE3 'Define Reuse Tx Payload Register Command
Const Nop_comm = &HFF 'Define No Operation , Might Be Used To Read Status Register
'SPI(nRF24L01) registers(addresses)
Const Config_nrf = &H00 'Config' register address
Const En_aa = &H01 'Enable Auto Acknowledgment' register address
Const En_rxaddr = &H02 'Enabled RX addresses' register address
Const Setup_aw = &H03 'Setup address width' register address
Const Setup_retr = &H04 'Setup Auto. Retrans' register address
Const Rf_ch = &H05  'RF channel' register address
Const Rf_setup = &H06 'RF setup' register address
Const Status = &H07 'Status' register address
Const Observe_tx = &H08 'Observe TX' register address
Const Cd = &H09 'Carrier Detect' register address
Const Rx_addr_p0 = &H0A 'RX address pipe0' register address
Const Rx_addr_p1 = &H0B 'RX address pipe1' register address
Const Rx_addr_p2 = &H0C 'RX address pipe2' register address
Const Rx_addr_p3 = &H0D  'RX address pipe3' register address
Const Rx_addr_p4 = &H0E 'RX address pipe4' register address
Const Rx_addr_p5 = &H0F 'RX address pipe5' register address
Const Tx_addr = &H10  'TX address' register address
Const Rx_pw_p0 = &H11 'RX payload width, pipe0' register address
Const Rx_pw_p1 = &H12 'RX payload width, pipe1' register address
Const Rx_pw_p2 = &H13 'RX payload width, pipe2' register address
Const Rx_pw_p3 = &H14 'RX payload width, pipe3' register address
Const Rx_pw_p4 = &H15  'RX payload width, pipe4' register address
Const Rx_pw_p5 = &H16 'RX payload width, pipe5' register address
Const Fifo_status = &H17 'FIFO Status Register' register address
'Various
Const True = 1
Const False = 0

'=== Config hardware ===
Config Spi = Hard , Interrupt = Off , Data Order = Msb , Master = Yes , Polarity = Low , Phase = 0 , Clockrate = 4 , Noss = 1
'Software SPI is NOT working with the nRF24L01, use hardware SPI only, but the SS pin must be controlled by our self
Config Pinc.5 = Output 'CE pin is output
Config Pinb.2 = Output 'SS pin is output
Config Pinc.4 = Input  'IRQ pin is input
Config Pinc.3 = Input 'TX/RX Device _select
Ce
Alias Portc.5
Ss
Alias Portb.2
Irq
Alias Pinc.4
Txrx_device
Alias Pinc.3
Spiinit  'init the spi pins
Set Ce
Waitms 10 'Wait a moment until all hardware is stable
Reset Ce 'Set CE pin low
Reset Ss  'Set SS pin low (CSN pin)
Dim D_bytes(33) As Byte , B_bytes(33) As Byte 'Dim the bytes use for SPI, D_bytes = outgoing B_bytes = Incoming
Dim Temp As Byte , W As Word
Dim Packet_count As Byte

If Txrx_device = True Then Goto Main_tx 'Is this the RX or TX device?
'===Main rx==========================================================================================================================

Main_rx
:
Call R_register(status , 1)  'Read STATUS register
Print "Rx_device" 'Send to terminal who i'm
Reset Ce 'Set CE low to access the registers
Gosub Setup_rx  'Setup the nRF24L01 for RX
Waitms 2 'Add a delay before going in RX
Set Ce 'Set nRF20L01 in RX mode
Do  'Main loop for RX
If Irq = 0 Then 'Wait until IRQ occurs, pin becomes low on interrupt
 
Reset Ce 'Receiver must be disabled before reading pload
 
Do 'Loop until all 3 fifo buffers are empty
 
Call R_register(rd_rx_pload , 5) 'Read 5 bytes RX pload register
 
Print "Pload : " ; Hex(b_bytes(1)) ; Hex(b_bytes(2)) ; Hex(b_bytes(3)) ; Hex(b_bytes(4)) ; Hex(b_bytes(5)) 'Print the pload
 
Call R_register(fifo_status , 1) 'Read FIFO_STATUS
 
Loop Until B_bytes(1).0 = True 'Test or RX_EMPTY bit is true, RX FIFO empty
 D_bytes
(1) = Write_reg + Status 'Reset the RX_DR status bit
 D_bytes
(2) = &B01000000 'Write 1 to RX_DR bit to reset IRQ
 
Call W_register(2)
 
Set Ce  'Enable receiver again
 
Waitms 2
End If
'Gosub Dump_registers 'Unremark me for debugging
Loop
Return

'===Main tx==========================================================================================================================
Main_tx
:
Print "TX_device" 'Send to terminal who i'm
D_bytes
(1) = Flush_tx 'Flush the TX_fifo buffer
Call W_register(1)
D_bytes
(1) = Write_reg + Status 'Reset the IRQ bits
D_bytes
(2) = &B00110000
Call W_register(2)
Do 'Main loop for TX
Incr Packet_count 'Increase the send packet counter, for test only
If Packet_count > 254 Then Packet_count = 0
Gosub Setup_tx 'Setup the nrf240l01 for TX
D_bytes
(1) = Wr_tx_pload 'Put 5 bytes in the TX pload buffer
D_bytes
(2) = &HAA 'Byte 1
D_bytes
(3) = &HBB 'Byte 2
D_bytes
(4) = &HCC 'Byte 3
D_bytes
(5) = &H11  'Byte 4
D_bytes
(6) = Packet_count 'Byte 5 will be increase every loop
Call W_register(6) 'Write 6 bytes to register
Waitms 2
Set Ce  'Set CE for a short moment to transmit the fifo buffer
Waitms 1 '
Reset Ce '
Waitms 100  'Some delay to read the output on the terminal, line can be removed for max. speed
W
= 0 'Counter for time out
Do
 
If Irq = 0 Then
 
Call R_register(status , 1)
 Temp
= B_bytes(1) And &B01110000 'Mask the IRQ bits out the status byte
 
Select Case Temp 'Which IRQ occurs
 
Case Max_rt 'MAX_RT
 
Print "Maximum number of TX retries, Flussing the TX buffer now !"
 D_bytes
(1) = Flush_tx 'Flush the TX buffer
 
Call W_register(1)
 D_bytes
(1) = Write_reg + Status
 D_bytes
(2) = &B00010000 'Clear the MAX_RT IRQ bit
 
Call W_register(2)
 
Exit Do
 
Case Tx_ds 'TX_DS
 
Print "Packet " ; Packet_count ; " send and ACK received."
 D_bytes
(1) = Write_reg + Status
 D_bytes
(2) = &B00100000 'Clear the TX_DS IRQ bit
 
Call W_register(2)
 
Exit Do
 
Case Else 'Other IRQ ??
 
Print "Other irq " ; Bin(temp)
  D_bytes
(1) = Flush_tx 'Flush the TX buffer
 
Call W_register(1)
 D_bytes
(1) = Write_reg + Status
 D_bytes
(2) = &B00110000 'Clear both MAX_RT, TX_DS bits
  
Call W_register(2)
 
End Select
 
End If
 
Waitms 1 'Time out waiting for IRQ 1ms * 100
 
Incr W 'Increment W
 
If W > 100 Then  'Waited for 100ms
 
Print "No irq response from RF20L01 within 100ms"
 
Exit Do 'Exit the wait loop
 
End If
Loop
Loop
Return


'=== Sub routines ===
Sub W_register(byval C_bytes As Byte) 'Write register with SPI
Reset Ss 'Manual control SS pin, set SS low before shifting out the bytes
 
Spiout D_bytes(1) , C_bytes 'Shiftout the data bytes trough SPI , C_bytes is the amount bytes to be written
Set Ss 'Set SS high
End Sub

Sub R_register(byval Command As Byte , Byval C_bytes As Byte) As Byte 'C_bytes = Count_bytes, number off bytes to be read
Reset Ss 'Manual controle SS pin, set low before shifting in/out the bytes
 
Spiout Command , 1 'First shiftout the register to be read
 
Spiin B_bytes(1) , C_bytes 'Read back the bytes from SPI sended by nRF20L01
Set Ss 'Set SS back to high level
End Sub


Setup_rx
: 'Setup for RX
D_bytes
(1) = Write_reg + Rx_addr_p0 'RX adress for pipe0
D_bytes
(2) = &H34
D_bytes
(3) = &H43
D_bytes
(4) = &H10
D_bytes
(5) = &H10
D_bytes
(6) = &H01
Call W_register(6) 'Send 6 bytes to SPI
D_bytes
(1) = Write_reg + En_aa 'Enable auto ACK for pipe0
D_bytes
(2) = &H01
Call W_register(2)
D_bytes
(1) = Write_reg + En_rxaddr 'Enable RX adress for pipe0
D_bytes
(2) = &H01
Call W_register(2)
D_bytes
(1) = Write_reg + Rf_ch 'Set RF channel
D_bytes
(2) = 40
Call W_register(2)
D_bytes
(1) = Write_reg + Rx_pw_p0 'Set RX pload width for pipe0
D_bytes
(2) = 5
Call W_register(2)
D_bytes
(1) = Write_reg + Rf_setup 'Setup RF-> Output power 0dbm, datarate 2Mbps and LNA gain on
D_bytes
(2) = &H0F
Call W_register(2)
D_bytes
(1) = Write_reg + Config_nrf 'Setup CONFIG-> PRX=1(RX_device), PWR_UP=1, CRC 2bytes, Enable CRC
D_bytes
(2) = &H0F
Call W_register(2)
Return

Setup_tx
: 'Setup for TX
D_bytes
(1) = Write_reg + Tx_addr 'TX adress
D_bytes
(2) = &H34
D_bytes
(3) = &H43
D_bytes
(4) = &H10
D_bytes
(5) = &H10
D_bytes
(6) = &H01
Call W_register(6)
D_bytes
(1) = Write_reg + Rx_addr_p0 'RX adress for pipe0
D_bytes
(2) = &H34
D_bytes
(3) = &H43
D_bytes
(4) = &H10
D_bytes
(5) = &H10
D_bytes
(6) = &H01
Call W_register(6)
D_bytes
(1) = Write_reg + En_aa 'Enable auto ACK for pipe0
D_bytes
(2) = &H01
Call W_register(2)
D_bytes
(1) = Write_reg + En_rxaddr 'Enable RX adress for pipe0
D_bytes
(2) = &H01
Call W_register(2)
D_bytes
(1) = Write_reg + Rf_ch 'Set RF channel
D_bytes
(2) = 40
Call W_register(2)
D_bytes
(1) = Write_reg + Rf_setup 'Setup RF-> Output power 0dbm, datarate 2Mbps and LNA gain on
D_bytes
(2) = &H0F
Call W_register(2)
D_bytes
(1) = Write_reg + Config_nrf 'Setup CONFIG-> PRX=0(TX_device), PWR_UP=1, CRC 2bytes, Enable CRC
D_bytes
(2) = &H0E
Call W_register(2)

Return

Dump_registers
: 'Dumps all nRF24L01 registers to the terminal, handy for debugging
Print "* Dump nRF24L01 Registers *"
Call R_register(config_nrf , 1)
Print "CONFIG : " ; Bin(b_bytes(1))
Call R_register(en_aa , 1)
Print "EN_AA : " ; Bin(b_bytes(1))
Call R_register(en_rxaddr , 1)
Print "EN_RXADDR : " ; Bin(b_bytes(1))
Call R_register(setup_aw , 1)
Print "SETUP_AW : " ; Bin(b_bytes(1))
Call R_register(setup_retr , 1)
Print "SETUP_RETR : " ; Bin(b_bytes(1))
Call R_register(rf_ch , 1)
Print "RF_CH : " ; B_bytes(1)
Call R_register(rf_setup , 1)
Print "RF_SETUP : " ; Bin(b_bytes(1))
Call R_register(status , 1)
Print "STATUS : " ; Bin(b_bytes(1))
Call R_register(observe_tx , 1)
Print "OBSERVE_TX : " ; Bin(b_bytes(1))
Call R_register(cd , 1)
Print "CD : " ; Bin(b_bytes(1))
Call R_register(rx_addr_p0 , 5)
Print "RX_ADDR_P0 : " ; Hex(b_bytes(1)) ; Hex(b_bytes(2)) ; Hex(b_bytes(3)) ; Hex(b_bytes(4)) ; Hex(b_bytes(5))
Call R_register(rx_addr_p1 , 5)
Print "RX_ADDR_P1 : " ; Hex(b_bytes(1)) ; Hex(b_bytes(2)) ; Hex(b_bytes(3)) ; Hex(b_bytes(4)) ; Hex(b_bytes(5))
Call R_register(rx_addr_p2 , 5)
Print "RX_ADDR_P2 : " ; Hex(b_bytes(1)) ; Hex(b_bytes(2)) ; Hex(b_bytes(3)) ; Hex(b_bytes(4)) ; Hex(b_bytes(5))
Call R_register(rx_addr_p3 , 5)
Print "RX_ADDR_P3 : " ; Hex(b_bytes(1)) ; Hex(b_bytes(2)) ; Hex(b_bytes(3)) ; Hex(b_bytes(4)) ; Hex(b_bytes(5))
Call R_register(rx_addr_p4 , 5)
Print "RX_ADDR_P4 : " ; Hex(b_bytes(1)) ; Hex(b_bytes(2)) ; Hex(b_bytes(3)) ; Hex(b_bytes(4)) ; Hex(b_bytes(5))
Call R_register(rx_addr_p5 , 5)
Print "RX_ADDR_P5 : " ; Hex(b_bytes(1)) ; Hex(b_bytes(2)) ; Hex(b_bytes(3)) ; Hex(b_bytes(4)) ; Hex(b_bytes(5))
Call R_register(tx_addr , 5)
Print "TX_ADDR : " ; Hex(b_bytes(1)) ; Hex(b_bytes(2)) ; Hex(b_bytes(3)) ; Hex(b_bytes(4)) ; Hex(b_bytes(5))
Call R_register(rx_pw_p0 , 5)
Print "RX_PW_P0 : " ; Hex(b_bytes(1)) ; Hex(b_bytes(2)) ; Hex(b_bytes(3)) ; Hex(b_bytes(4)) ; Hex(b_bytes(5))
Call R_register(rx_pw_p1 , 5)
Print "RX_PW_P1 : " ; Hex(b_bytes(1)) ; Hex(b_bytes(2)) ; Hex(b_bytes(3)) ; Hex(b_bytes(4)) ; Hex(b_bytes(5))
Call R_register(rx_pw_p2 , 5)
Print "RX_PW_P2 : " ; Hex(b_bytes(1)) ; Hex(b_bytes(2)) ; Hex(b_bytes(3)) ; Hex(b_bytes(4)) ; Hex(b_bytes(5))
Call R_register(rx_pw_p3 , 5)
Print "RX_PW_P3 : " ; Hex(b_bytes(1)) ; Hex(b_bytes(2)) ; Hex(b_bytes(3)) ; Hex(b_bytes(4)) ; Hex(b_bytes(5))
Call R_register(rx_pw_p4 , 5)
Print "RX_PW_P4 : " ; Hex(b_bytes(1)) ; Hex(b_bytes(2)) ; Hex(b_bytes(3)) ; Hex(b_bytes(4)) ; Hex(b_bytes(5))
Call R_register(rx_pw_p5 , 5)
Print "RX_PW_P5 : " ; Hex(b_bytes(1)) ; Hex(b_bytes(2)) ; Hex(b_bytes(3)) ; Hex(b_bytes(4)) ; Hex(b_bytes(5))
Call R_register(fifo_status , 1)
Print "FIFO_STATUS : " ; Bin(b_bytes(1))
Return


Updated code for using with Xmega32a4:

'in this sample you can send 2 byte numbrical and learn how send more byte of different data
'------------------------------------------------------------------
'   Nordic nRF24L01 data link demo in Enhanced Shockburst mode
'        By shobeir 2012 shobeir90@yahoo.co.uk
'                   Created with Bascom-Avr: 2.0.7.3
'------------------------------------------------------------------

'$regfile = "M8def.dat"
$regfile = "xm32a4def.dat"
'$crystal = 7372800
$crystal = 32000000
'$baud = 19200
$hwstack = 255
$swstack = 255
$framesize = 255
$lib "xmega.lib"
$external _xmegafix_clear
$external _xmegafix_rol_r1014
Config Osc = Enabled , 32mhzosc = Enabled                   'We use internal 32MHz
Config Sysclock = 32mhz , Prescalea = 1 , Prescalebc = 1_1  'Internal 32MHz, no prescaler
Config Priority = Static , Vector = Application , Lo = Enabled

'=== Declare sub routines
Declare Sub R_register(byval Command As Byte , Byval C_bytes As Byte)
Declare Sub W_register(byval C_bytes As Byte)

'=== Constante ===
'Define nRF24L01 interrupt flag's
Const Idle_int = &H00                                       'Idle, no interrupt pending
Const Max_rt = &H10                                         'Max #of Tx Retrans Interrupt
Const Tx_ds = &H20                                          'Tx Data Sent Interrupt
Const Rx_dr = &H40                                          'Rx Data Received
'SPI(nRF24L01) commands
Const Read_reg = &H00                                       'Define Read Command To Register
Const Write_reg = &H20                                      'Define Write Command To Register
Const Rd_rx_pload = &H61                                    'Define Rx Payload Register Address
Const Wr_tx_pload = &HA0                                    'Define Tx Payload Register Address
Const Flush_tx = &HE1                                       'Define Flush Tx Register Command
Const Flush_rx = &HE2                                       'Define Flush Rx Register Command
Const Reuse_tx_pl = &HE3                                    'Define Reuse Tx Payload Register Command
Const Nop_comm = &HFF                                       'Define No Operation , Might Be Used To Read Status Register
'SPI(nRF24L01) registers(addresses)
Const Config_nrf = &H00                                     'Config' register address
Const En_aa = &H01                                          'Enable Auto Acknowledgment' register address
Const En_rxaddr = &H02                                      'Enabled RX addresses' register address
Const Setup_aw = &H03                                       'Setup address width' register address
Const Setup_retr = &H04                                     'Setup Auto. Retrans' register address
Const Rf_ch = &H05                                          'RF channel' register address
Const Rf_setup = &H06                                       'RF setup' register address
Const Status = &H07                                         'Status' register address
Const Observe_tx = &H08                                     'Observe TX' register address
Const Cd = &H09                                             'Carrier Detect' register address
Const Rx_addr_p0 = &H0A                                     'RX address pipe0' register address
Const Rx_addr_p1 = &H0B                                     'RX address pipe1' register address
Const Rx_addr_p2 = &H0C                                     'RX address pipe2' register address
Const Rx_addr_p3 = &H0D                                     'RX address pipe3' register address
Const Rx_addr_p4 = &H0E                                     'RX address pipe4' register address
Const Rx_addr_p5 = &H0F                                     'RX address pipe5' register address
Const Tx_addr = &H10                                        'TX address' register address
Const Rx_pw_p0 = &H11                                       'RX payload width, pipe0' register address
Const Rx_pw_p1 = &H12                                       'RX payload width, pipe1' register address
Const Rx_pw_p2 = &H13                                       'RX payload width, pipe2' register address
Const Rx_pw_p3 = &H14                                       'RX payload width, pipe3' register address
Const Rx_pw_p4 = &H15                                       'RX payload width, pipe4' register address
Const Rx_pw_p5 = &H16                                       'RX payload width, pipe5' register address
Const Fifo_status = &H17                                    'FIFO Status Register' register address
'Various
Const True = 1
Const False = 0

'=== Config hardware ===
'Config Spi = Hard , Interrupt = Off , Data Order = Msb , Master = Yes , Polarity = Low , Phase = 0 , Clockrate = 4 , Noss = 1
'Config Spic = Hard , Master = Yes , Mode = 0 , Clockdiv = Clk16 , Data_order = Msb , Ss = Auto


'Software SPI is NOT working with the nRF24L01, use hardware SPI only, but the SS pin must be controlled by our self
Config Pinb.= Output 'test pin

Config Pinc.= Output 'CE pin is output
Config Pinc.= Output 'SS pin is output
Config Portc.= Output
Config Portc.= Output
Set Pinc.4
Config Pinc.= Input 'IRQ pin is input
Config Pinc.= Input 'TX/RX Device _select
Ddrc = &B1011_1010
Ce Alias Portc.1
Ss Alias Portc.4
Irq Alias Pinc.0
Txrx_device Alias Pinc.3
Config Spi = Soft , Din = Pinc., Dout = Portc., Ss = None , Clock = Portc., Spiin = 0 , Mode = 0
Spiinit 'init the spi pins
Set Ce
Waitms 10                                                   'Wait a moment until all hardware is stable
Reset Ce                                                    'Set CE pin low
Reset Ss                                                    'Set SS pin low (CSN pin)
Dim D_bytes(33) As Byte , B_bytes(33) As Byte 'Dim the bytes use for SPI, D_bytes = outgoing  B_bytes = Incoming
Dim Temp As Byte , W As Word
Dim Packet_count As Byte

Dim Lword As Word , L As Word

If Txrx_device = True Then Goto Main_tx                     'Is this the RX or TX device?
'**********************test
'Do
'Portb.0 = Not Portb.0
'Waitms 300
'Loop
'===Main rx==========================================================================================================================
Main_rx:
Set Portb.0
Waitms 200
Reset Portb.0
Call R_register(status , 1) 'Read STATUS register
Print "Rx_device" 'Send to terminal who i'm
Reset Ce                                                    'Set CE low to access the registers
Gosub Setup_rx                                              'Setup the nRF24L01 for RX
Waitms 2                                                    'Add a delay before going in RX
Set Ce                                                      'Set nRF20L01 in RX mode
Do 'Main loop for RX
'Portb.0 = 1
If Irq = 0 Then 'Wait until IRQ occurs, pin becomes low on interrupt
 Reset Ce                                                'Receiver must be disabled before reading pload
 Do 'Loop until all 3 fifo buffers are empty
 Call R_register(rd_rx_pload , 5) 'Read 5 bytes RX pload register
 Print "Pload  : " ; Hex(b_bytes(1)) ; Hex(b_bytes(2)) ; Hex(b_bytes(3)) ; Hex(b_bytes(4)) ; Hex(b_bytes(5)) 'Print the pload

 ' Lword = &H100 * B_bytes(1)
 ' Lword = Lword Or B_bytes(2)
       L = 0
       L = B_bytes(2)
 Swap L
       Lword = B_bytes(1) + L



 If Lword = 65535 Then 'Or B_bytes(2) = 12 Or B_bytes(3) = 12 Or B_bytes(4) = 12 Or B_bytes(5) = 12 Then
 Portb.= Not Portb.0
 Else
 Reset Portb.0
 End If


 Call R_register(fifo_status , 1) 'Read FIFO_STATUS
 Loop Until B_bytes(1).= True                          'Test or RX_EMPTY bit is true, RX FIFO empty
    D_bytes(1) = Write_reg + Status                         'Reset the RX_DR status bit
    D_bytes(2) = &B01000000                                 'Write 1 to RX_DR bit to reset IRQ
 Call W_register(2)
 Set Ce                                                  'Enable receiver again
 Waitms 2
End If
'Gosub Dump_registers                                        'Unremark me for debugging
Loop
Return

'===Main tx==========================================================================================================================
Main_tx:
Print "TX_device" 'Send to terminal who i'm
D_bytes(1) = Flush_tx                                       'Flush the TX_fifo buffer
Call W_register(1)
D_bytes(1) = Write_reg + Status                             'Reset the IRQ bits
D_bytes(2) = &B00110000
Call W_register(2)
Do 'Main loop for TX
Incr Packet_count                                           'Increase the send packet counter, for test only
If Packet_count > 254 Then Packet_count = 0
Gosub Setup_tx                                              'Setup the nrf240l01 for TX
D_bytes(1) = Wr_tx_pload                                    'Put 5 bytes in the TX pload buffer
D_bytes(2) = &HAA                                           'Byte 1
D_bytes(3) = &HBB                                           'Byte 2
D_bytes(4) = &HCC                                           'Byte 3
D_bytes(5) = &H11                                           'Byte 4
D_bytes(6) = Packet_count                                   'Byte 5 will be increase every loop
Call W_register(6) 'Write 6 bytes to register
Waitms 2
Set Ce                                                      'Set CE for a short moment to transmit the fifo buffer
Waitms 1                                                    '
Reset Ce                                                    '
'Waitms 100                                                  'Some delay to read the output on the terminal, line can be removed for max. speed
Waitms 10
= 0                                                       'Counter for time out

Do

'test
Do

Lword = 65535
 Portb.= Not Portb.0
 Gosub Setup_tx
  D_bytes(1) = Wr_tx_pload
  D_bytes(2) = Lword And &H00FF
  L = &HFF00 And Lword
 Swap L
  D_bytes(3) = L And &H00FF
 Call W_register(6)
 Waitms 2
 Set Ce                                                    'Set CE for a short moment to transmit the fifo buffer
 Waitms 1                                                 '
 Reset Ce
 Waitms 100
 If Irq = 0 Then
 Call R_register(status , 1)
            D_bytes(1) = Flush_tx                           'Flush the TX buffer
 Call W_register(1)
            D_bytes(1) = Write_reg + Status
            D_bytes(2) = &B00110000                         'Clear both MAX_RT, TX_DS bits
 Call W_register(2)
 End If

Loop
'tested

 If Irq = 0 Then
 Call R_register(status , 1)
       Temp = B_bytes(1) And &B01110000                     'Mask the IRQ bits out the status byte
 Select Case Temp                                      'Which IRQ occurs
 Case Max_rt                                         'MAX_RT
 Print "Maximum number of TX retries, Flushing the TX buffer now !"
            D_bytes(1) = Flush_tx                           'Flush the TX buffer
 Call W_register(1)
            D_bytes(1) = Write_reg + Status
            D_bytes(2) = &B00010000                         'Clear the MAX_RT IRQ bit
 Call W_register(2)
 Exit Do
 Case Tx_ds                                          'TX_DS
 Print "Packet " ; Packet_count ; " send and ACK received."

'            D_bytes(1) = 12
'           Call W_register(1)


            D_bytes(1) = Write_reg + Status
            D_bytes(2) = &B00100000                         'Clear the TX_DS IRQ bit
 Call W_register(2)
 Exit Do
 Case Else 'Other IRQ ??
 Print "Other irq " ; Bin(temp)
            D_bytes(1) = Flush_tx                           'Flush the TX buffer
 Call W_register(1)
            D_bytes(1) = Write_reg + Status
            D_bytes(2) = &B00110000                         'Clear both MAX_RT, TX_DS bits
 Call W_register(2)


 End Select
 End If
 Waitms 1                                                'Time out waiting for IRQ 1ms * 100
 Incr W                                                  'Increment W
 If W > 100 Then 'Waited for 100ms
 Print "No irq response from RF20L01 within 100ms"
 Exit Do 'Exit the wait loop
 End If
Loop
Loop
Return



'**********************************************************************************************w reg
'=== Sub routines ===
Sub W_register(byval C_bytes As Byte) 'Write register with SPI
Reset Ss                                                    'Manual control SS pin, set SS low before shifting out the bytes
 Spiout D_bytes(1) , C_bytes                             'Shiftout the data bytes trough SPI , C_bytes is the amount bytes to be written
Set Ss                                                      'Set SS high
End Sub

'**********************************************************************************************r reg
Sub R_register(byval Command As Byte , Byval C_bytes As Byte) As Byte 'C_bytes = Count_bytes, number off bytes to be read
Reset Ss                                                    'Manual controle SS pin, set low before shifting in/out the bytes
 Spiout Command , 1                                      'First shiftout the register to be read
 Spiin B_bytes(1) , C_bytes                              'Read back the bytes from SPI sended by nRF20L01
Set Ss                                                      'Set SS back to high level
End Sub


Setup_rx: 'Setup for RX
D_bytes(1) = Write_reg + Rx_addr_p0                         'RX adress for pipe0
D_bytes(2) = &H34
D_bytes(3) = &H43
D_bytes(4) = &H10
D_bytes(5) = &H10
D_bytes(6) = &H01
Call W_register(6) 'Send 6 bytes to SPI
D_bytes(1) = Write_reg + En_aa                              'Enable auto ACK for pipe0
D_bytes(2) = &H01
Call W_register(2)
D_bytes(1) = Write_reg + En_rxaddr                          'Enable RX adress for pipe0
D_bytes(2) = &H01
Call W_register(2)
D_bytes(1) = Write_reg + Rf_ch                              'Set RF channel
D_bytes(2) = 40
Call W_register(2)
D_bytes(1) = Write_reg + Rx_pw_p0                           'Set RX pload width for pipe0
D_bytes(2) = 5
Call W_register(2)
D_bytes(1) = Write_reg + Rf_setup                           'Setup RF-> Output power 0dbm, datarate 2Mbps and LNA gain on
D_bytes(2) = &H0F
Call W_register(2)
D_bytes(1) = Write_reg + Config_nrf                         'Setup CONFIG-> PRX=1(RX_device), PWR_UP=1, CRC 2bytes, Enable CRC
D_bytes(2) = &H0F
Call W_register(2)
Return

Setup_tx: 'Setup for TX
D_bytes(1) = Write_reg + Tx_addr                            'TX adress
D_bytes(2) = &H34
D_bytes(3) = &H43
D_bytes(4) = &H10
D_bytes(5) = &H10
D_bytes(6) = &H01
Call W_register(6)
D_bytes(1) = Write_reg + Rx_addr_p0                         'RX adress for pipe0
D_bytes(2) = &H34
D_bytes(3) = &H43
D_bytes(4) = &H10
D_bytes(5) = &H10
D_bytes(6) = &H01
Call W_register(6)
D_bytes(1) = Write_reg + En_aa                              'Enable auto ACK for pipe0
D_bytes(2) = &H01
Call W_register(2)
D_bytes(1) = Write_reg + En_rxaddr                          'Enable RX adress for pipe0
D_bytes(2) = &H01
Call W_register(2)
D_bytes(1) = Write_reg + Rf_ch                              'Set RF channel
D_bytes(2) = 40
Call W_register(2)
D_bytes(1) = Write_reg + Rf_setup                           'Setup RF-> Output power 0dbm, datarate 2Mbps and LNA gain on
D_bytes(2) = &H0F
Call W_register(2)
D_bytes(1) = Write_reg + Config_nrf                         'Setup CONFIG-> PRX=0(TX_device), PWR_UP=1, CRC 2bytes, Enable CRC
D_bytes(2) = &H0E
Call W_register(2)
Return

Dump_registers: 'Dumps all nRF24L01 registers to the terminal, handy for debugging
Print "* Dump nRF24L01 Registers *"
Call R_register(config_nrf , 1)
Print "CONFIG      : " ; Bin(b_bytes(1))
Call R_register(en_aa , 1)
Print "EN_AA       : " ; Bin(b_bytes(1))
Call R_register(en_rxaddr , 1)
Print "EN_RXADDR   : " ; Bin(b_bytes(1))
Call R_register(setup_aw , 1)
Print "SETUP_AW    : " ; Bin(b_bytes(1))
Call R_register(setup_retr , 1)
Print "SETUP_RETR  : " ; Bin(b_bytes(1))
Call R_register(rf_ch , 1)
Print "RF_CH       : " ; B_bytes(1)
Call R_register(rf_setup , 1)
Print "RF_SETUP    : " ; Bin(b_bytes(1))
Call R_register(status , 1)
Print "STATUS      : " ; Bin(b_bytes(1))
Call R_register(observe_tx , 1)
Print "OBSERVE_TX  : " ; Bin(b_bytes(1))
Call R_register(cd , 1)
Print "CD          : " ; Bin(b_bytes(1))
Call R_register(rx_addr_p0 , 5)
Print "RX_ADDR_P0  : " ; Hex(b_bytes(1)) ; Hex(b_bytes(2)) ; Hex(b_bytes(3)) ; Hex(b_bytes(4)) ; Hex(b_bytes(5))
Call R_register(rx_addr_p1 , 5)
Print "RX_ADDR_P1  : " ; Hex(b_bytes(1)) ; Hex(b_bytes(2)) ; Hex(b_bytes(3)) ; Hex(b_bytes(4)) ; Hex(b_bytes(5))
Call R_register(rx_addr_p2 , 5)
Print "RX_ADDR_P2  : " ; Hex(b_bytes(1)) ; Hex(b_bytes(2)) ; Hex(b_bytes(3)) ; Hex(b_bytes(4)) ; Hex(b_bytes(5))
Call R_register(rx_addr_p3 , 5)
Print "RX_ADDR_P3  : " ; Hex(b_bytes(1)) ; Hex(b_bytes(2)) ; Hex(b_bytes(3)) ; Hex(b_bytes(4)) ; Hex(b_bytes(5))
Call R_register(rx_addr_p4 , 5)
Print "RX_ADDR_P4  : " ; Hex(b_bytes(1)) ; Hex(b_bytes(2)) ; Hex(b_bytes(3)) ; Hex(b_bytes(4)) ; Hex(b_bytes(5))
Call R_register(rx_addr_p5 , 5)
Print "RX_ADDR_P5  : " ; Hex(b_bytes(1)) ; Hex(b_bytes(2)) ; Hex(b_bytes(3)) ; Hex(b_bytes(4)) ; Hex(b_bytes(5))
Call R_register(tx_addr , 5)
Print "TX_ADDR     : " ; Hex(b_bytes(1)) ; Hex(b_bytes(2)) ; Hex(b_bytes(3)) ; Hex(b_bytes(4)) ; Hex(b_bytes(5))
Call R_register(rx_pw_p0 , 5)
Print "RX_PW_P0    : " ; Hex(b_bytes(1)) ; Hex(b_bytes(2)) ; Hex(b_bytes(3)) ; Hex(b_bytes(4)) ; Hex(b_bytes(5))
Call R_register(rx_pw_p1 , 5)
Print "RX_PW_P1    : " ; Hex(b_bytes(1)) ; Hex(b_bytes(2)) ; Hex(b_bytes(3)) ; Hex(b_bytes(4)) ; Hex(b_bytes(5))
Call R_register(rx_pw_p2 , 5)
Print "RX_PW_P2    : " ; Hex(b_bytes(1)) ; Hex(b_bytes(2)) ; Hex(b_bytes(3)) ; Hex(b_bytes(4)) ; Hex(b_bytes(5))
Call R_register(rx_pw_p3 , 5)
Print "RX_PW_P3    : " ; Hex(b_bytes(1)) ; Hex(b_bytes(2)) ; Hex(b_bytes(3)) ; Hex(b_bytes(4)) ; Hex(b_bytes(5))
Call R_register(rx_pw_p4 , 5)
Print "RX_PW_P4    : " ; Hex(b_bytes(1)) ; Hex(b_bytes(2)) ; Hex(b_bytes(3)) ; Hex(b_bytes(4)) ; Hex(b_bytes(5))
Call R_register(rx_pw_p5 , 5)
Print "RX_PW_P5    : " ; Hex(b_bytes(1)) ; Hex(b_bytes(2)) ; Hex(b_bytes(3)) ; Hex(b_bytes(4)) ; Hex(b_bytes(5))
Call R_register(fifo_status , 1)
Print "FIFO_STATUS : " ; Bin(b_bytes(1))
Return