Quantcast
Channel: MCS Electronics Forum
Viewing all articles
Browse latest Browse all 20606

Share your working BASCOM-AVR code here : Wireless Bootloader Using Nordic nRF24L01 Module : NEWTOPIC

$
0
0
Hello Forum, I have developed a system to program microcontrollers wirelessly using the nRF24L01 module. I include the Bascom files below. The way it works: Micro #1 - Base - mega328 with LCD and nRF24L01 module - file UART.nrf24l01.BL.Base.1.bas is compiled and loaded into mega328 using ISP programmer (or for the sophisticated user use the Bascom UART Bootloader). - UART connected to computer with Bascom - Bascom configured with Programmer as MCS Loader with COM Port pointing to UART on mega328. Micro #2 - Remote - mega644p (in my case) with UART to second computer (or second COM Port) with nRF24L01 module - file BL.Remote.M644P.nRF24L01.UART.1.bas is compiled and loaded into Bootloader area with ISP Programmer - FuseBits: BOOTSZ=7800 and BOOTRST set. Usage: 1. Micro #2 should be showing title and countdown on UART. 2. Micro #1 should be displaying "WaitPC?" on LCD. 3. From Bascom, select and compile the target *.bas file to transfer to Micro #2. 4. Push F4. File should be transferred from the Bascom PC to Micro #1, then wirelessly transmitted to micro#2 and finally be programmed into micro#2 by the wireless bootloader receiver. Enjoy. Please post any improvements Ennio M [PS: special thanks to Evert Dekker for the inspiration and for preparing AN#151.] [PS1: I had previously developed a similar system using the Microchip MRF24J40MA module. It is IEEE 802.15 compliant with AES-128 security-enabled communication with 64-bit addressing. If anyone is interested in this for commercial, industrial or military applications, please let me know.] [code:1:36deabc27d]'===UART.nrf24l01.BL.Base.1.bas========================================== 'Bootloader Base - Ver 1.0 '328 Board w/nRF24L01 'Nov 15/13 ' 'Thanks to Evert Dekker for the inspiration and BASCOM AN#151 '============================================= $regfile = "m328def.dat" $crystal = 8000000 $baud = 38400 $hwstack = 80 ' default use 32 for the hardware stack $swstack = 40 ' default use 10 for the SW stack $framesize = 80 ' default use 40 for the frame space $loadersize = $1000 '========================================== 'Overall AtMega Config '========================================== Config Portb.2 = Output Set Portb.2 Config Spi = Hard , Interrupt = Off , Data Order = Msb , Master = Yes , Polarity = Low , Phase = 0 , Clockrate = 4 , Noss = 1 Spiinit '============================================ 'nRF24L01+ Nordic Semiconductor '============================================ Const Dev_id = 1 'Address LSB of BASE device Nrfce Alias Portc.0 Config Nrfce = Output Nrfce = 1 Nrfcs Alias Portc.1 Config Nrfcs = Output Nrfcs = 1 nrfint Alias Pinc.2 Config Nrfint = Input Declare Sub R_register(byval Command As Byte , Byval Start_b As Byte , Byval Num_b As Byte) Declare Sub W_register(byval Start_b As Byte , Byval Num_b As Byte) Declare Sub Nrf24l01init() Declare Function Transmit(byval Tx As Byte , Byval Pl_w As Byte) As Byte Declare Function Receive() As Byte 'SPI(nRF24L01) commands 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 'Registers Const Config_nrf = &H00 Const Status = &H07 Const Fifo_stat = &H17 Const Tx_addr = &H10 Const Rx_addr_p0 = &H0A Const R_rx_pl_wid = &B01100000 'VALUES Const Nrfwait = 5 'This can be optimized. 'CAUTION: 'The nRF24L01 module has a 3-level Receive FIFO 'and a 3-level Transmit FIFO. If TX is too fast, the data 'may go into a level other than the first and this Bootloader 'will not work. Const V_irq_reset = &B01110000 Const V_set_tx = &B00001010 'PRX=1(RX_device), PWR_UP=1, CRC 2bytes, Enable CRC Const V_set_rx = &B00001011 'Make sure this matches DATA lines '&B00001111 ' ^ Module function as 0=TX, 1=RX ' ^ 0=Power Down, 1=Up ' ^ CRC type 0=1 byte, 1=2 byte ' ^ Enable CRC ' x^^^ Three sources of interrupts 0=enabled '==================================================== 'RAM dBase Array '==================================================== 'This RAM array assumes a 4-byte address for each nRF24L01 'The indeces (IDX) below need to be changed if using 3 or 5 byte address 'and the array will need re-mapping ' ' 2 1 4 1 4 1 1 1 32 '1 2 34567 89012 3 4 5 6789012345 6789012345 6789012345 67 8 'T R TAd RAd PW IrCm|-------- Payload ----------------| Const Payload_idx = 32 + 16 Const T_idx = 1 Const Tadr_idx = 3 Const Radr_idx = 8 Const Pw_idx = 13 Const Irq_idx = 14 Const Pl_cmd_idx = 15 Const Pl_idx = 16 Dim Payload(payload_idx) As Byte 'Main RAM space where Vars and Payload are OVERLAYED Dim Tb As Byte At Payload(t_idx) Overlay , Rb As Byte At Payload(t_idx) + 1 Overlay Dim Tx_addr_lsb As Byte At Payload(tadr_idx) + 1 Overlay , P0_addr_lsb As Byte At Payload(radr_idx) + 1 Overlay Dim Pw As Byte At Payload(pw_idx) Overlay , Irq_stat As Byte At Payload(irq_idx) Overlay Dim Reg_name As String * 12 , Reg_addr As Byte Tb = Tadr_idx Payload(tb + 4) = &H12 Payload(tb + 3) = &H34 Payload(tb + 2) = &H00 Payload(tadr_idx) = Write_reg + Tx_addr Rb = Radr_idx Payload(rb + 4) = &H12 Payload(rb + 3) = &H34 Payload(rb + 2) = &H00 Payload(radr_idx ) = Write_reg + Rx_addr_p0 '============================================ 'Scratchpad '============================================ Dim I As Byte , J As Byte , K As Byte , W As Word '========================================== 'MCS Bootloader Interface '========================================== Const Nak = &H15 Const Ack = &H06 Const Can = &H18 Const Eeprom_transfer = $3ff Dim Bstatus As Byte , Bblock As Byte , Bblocklocal As Byte Dim Bcsum1 As Byte , Bcsum2 As Byte , Buf(128) As Byte , Csum As Byte Dim Bkind As Byte , Bstarted As Byte , Nrfdevid As Byte Dim I1 As Byte Dim Ss As String * 20 '========================================= 'LCD Interface '========================================= Config Lcdpin = Pin , Rs = Portb.1 , E = Portb.2 , Db4 = Portd.4 , Db5 = Portd.5 , Db6 = Portd.6 , Db7 = Portd.7 Config Lcd = 16 * 2 Cls Cursor Off '============================================ 'Config Interrupts '============================================ Config Int0 = Falling On Int0 Do0 Enable Int0 Portd.2 = 1 Config Int1 = Falling On Int1 Do1 Enable Int1 Portd.3 = 1 Dim Pbs As Byte '============================================ 'Base '============================================ Dim Page As Word , Kk As Byte Dim Blockidx As Byte , Spmsize As Byte Dim Mv(32) As Byte At Payload(pl_idx) Overlay '============================================ 'Initialize components '============================================ Lcd "Base 328" Spmsize = 32 Call Nrf24l01init() '============================================ ' Main '============================================ $timeout = 800000 Enable Interrupts Readeeprom Nrfdevid , Eeprom_transfer I = Nrfdevid 'Changed by PushButtons 'Default I = 15 'Forced in this DEMO Kk = 0 Do Pbs = 0 Waitms 200 Select Case Pbs Case 1 If I > 1 Then Decr I Kk = 0 Case 2 If I < 50 Then Incr I Kk = 0 End Select Locate 2 , 1 : Lcd "DevID " ; I ; " " Incr Kk Loop Until Pbs = 3 Or Kk = 30 If Nrfdevid <> I Then Writeeeprom I , Eeprom_transfer Nrfdevid = I End If Do 'complete program loop Locate 1 , 1 : Lcd "DevID " ; Nrfdevid ; " " Locate 2 , 1 : Lcd "WaitPC? " Do Bkind = Waitkey() 'wait for the loader to send a byte If Pbs = 1 Then Goto _reset If Pbs = 3 Then Goto $3c00 Loop Until Bkind = 123 Or Bkind = 124 'Flash Or Eeprom Print Chr(bkind); If Bkind = 123 Then Ss = "Flash " Else Ss = "EEPROM " Locate 1 , 1 : Lcd Ss Do Bstatus = Waitkey() Loop Until Bstatus = 0 Locate 2 , 1 : Lcd "Wait " ; Nrfdevid ; " " Page = 0 Disable Interrupts If Nrfdevid <> 15 Then 'prepare and reset remote mrf Mv(1) = 15 Do Kk = Transmit(nrfdevid , 2) Loop Until Kk = 1 '================================================================================================= Wait 2 'this allows running main program to exit and start bootloader End If Config Watchdog = 8192 Start Watchdog Mv(1) = Bkind : Kk = Transmit(nrfdevid , 2) Reset Watchdog Bitwait Nrfint , Reset Kk = Receive() Stop Watchdog Blockidx = Mv(1) If Blockidx <> Bkind Then Locate 2 , 1 : Lcd "nRFTxErr" Wait 8 Goto _reset End If Locate 1 , 1 : Lcd "Send " ; Nrfdevid ; " " Do Bstarted = 0 'not started yet Csum = 0 'checksum is 0 when we start Print Chr(nak); 'first time send a nack Do Bstatus = Waitkey() 'wait for status byte Select Case Bstatus Case 0 : Bkind = 255 : Exit Do 'normal exit Case 1: 'start of heading, PC is ready to send Incr Bblocklocal 'increase local block count Csum = 1 'checksum is 1 Bblock = Waitkey() : Csum = Csum + Bblock 'get block Bcsum1 = Waitkey() : Csum = Csum + Bcsum1 'get checksum first byte For J = 1 To 128 'get 128 bytes Buf(j) = Waitkey() : Csum = Csum + Buf(j) Next Bcsum2 = Waitkey() 'get second checksum byte If Bblocklocal = Bblock Then 'are the blocks the same? If Bcsum2 = Csum Then 'is the checksum the same? For J = 0 To 3 'yes send data K = Spmsize * J : For I1 = 1 To Spmsize : I = K + I1 : Mv(i1) = Buf(i) : Next Kk = Transmit(nrfdevid , 33) Next J Mv(1) = 1 : Kk = Transmit(nrfdevid , 2) Incr Page : W = Page / 2 Locate 2 , 1 : Lcd "Page " ; W ; " " Print Chr(ack); 'acknowledge Else 'no match so send nak Print Chr(nak); End If Else Print Chr(nak); 'blocks do not match End If Case 4: Mv(1) = 255 : Kk = Transmit(nrfdevid , 2) 'end of transmission , file is transmitted Print Chr(ack); 'send ack and ready Bkind = 255 Case &H18: 'PC aborts transmission Locate 2 , 1 : Lcd "PC ABORT" Wait 8 Goto _reset 'Exit Do no valid data Case Else Locate 2 , 1 : Lcd "Unknown?" Wait 8 Goto _reset 'Exit Do no valid data End Select Loop Loop Until Bkind = 255 Locate 1 , 1 : Lcd "Complete" Locate 2 , 1 : Lcd "DevID " ; Nrfdevid Wait 8 Goto _reset Loop End '========================================= 'Subroutines '========================================= Sub Nrf24l01init() Nrfce = 0 Restore Nrf_registers_init Do Read Reg_name : Read Reg_addr : Read Rb If Reg_addr = 255 Then Exit Do Tb = Write_reg + Reg_addr Call W_register(t_idx , 2) Loop P0_addr_lsb = Dev_id : Call W_register(radr_idx , 5) 'Put this device 4-byte address in Pipe 0 for RX Tb = Flush_tx : Call W_register(t_idx , 1) 'Flush TX_fifo buffer Tb = Flush_rx : Call W_register(t_idx , 1) 'Flush RX_fifo buffer Nrfce = 1 End Sub Function Transmit(byval Tx As Byte , Byval Pl_w As Byte) As Byte Nrfce = 0 'set CE LO to set up registers Tb = Write_reg + Config_nrf : Rb = V_set_tx 'Set to TX Call W_register(t_idx , 2) Tb = Flush_tx 'Flush the TX_fifo buffer Call W_register(t_idx , 1) Tb = Write_reg + Status : Rb = V_irq_reset 'Reset the IRQ bits Call W_register(t_idx , 2) Tx_addr_lsb = Tx : Call W_register(tadr_idx , 5) 'LSB of Target Put 4-bytes TARGET address in TX P0_addr_lsb = Tx : Call W_register(radr_idx , 5) 'LSB of Target Put same 4-byte address in Pipe 0 for ACK Payload(pl_cmd_idx) = Wr_tx_pload 'Put bytes in the TX pload buffer Call W_register(pl_cmd_idx , Pl_w) Nrfce = 1 : Waitus 100 : Nrfce = 0 : W = 0 'Set CE for a short time to transmit the fifo buffer Bitwait Nrfint , Reset Call R_register(status , Irq_idx , 1) 'save TX status bit overlayed into IRQ_Stat Tb = Write_reg + Status : Rb = V_irq_reset 'Reset the IRQ bits Call W_register(t_idx , 2) P0_addr_lsb = Dev_id 'LSB of this device Call W_register(radr_idx , 5) 'Put this device 4-byte address BACK in Pipe 0 for RX Tb = Write_reg + Config_nrf : Rb = V_set_rx 'Set to RX Call W_register(t_idx , 2) Nrfce = 1 'set to RX Waitms Nrfwait Transmit = Irq_stat.5 End Function 'set CE HIGH to turn on Device Receive Function Receive() As Byte Call R_register(r_rx_pl_wid , Pw_idx , 1) Call R_register(status , Irq_idx , 1) 'save Receive interrupt overlayed into IRQ_Stat If Pw <= 32 And Pw > 0 And Irq_stat.6 = 1 Then Call R_register(rd_rx_pload , Pl_idx , Pw) Else Irq_stat = 0 'Read bytes RX to buffer overlayed in MV array Nrfce = 0 'set CE Low to read registers Tb = Flush_rx 'Flush the rX_fifo buffer Call W_register(t_idx , 1) Tb = Write_reg + Status : Rb = V_irq_reset 'Reset interrupts Call W_register(t_idx , 2) Nrfce = 1 'set CE HIGH for Receive Receive = Irq_stat.6 End Function Sub W_register(byval Start_b As Byte , Byval Num_b As Byte) Reset Nrfcs Spiout Payload(start_b) , Num_b Set Nrfcs End Sub Sub R_register(byval Command As Byte , Byval Start_b As Byte , Byval Num_b As Byte) Reset Nrfcs Spiout Command , 1 Spiin payload(start_b) , Num_b Set Nrfcs End Sub '============================= 'nRF24L01+ Register addresses '============================= 'Registers: 'Data "CONFIG_nRF " , &H00 , 1 'Data "EN_AA " , &H01 , 1 'Data "EN_RXADDR " , &H02 , 1 'Data "SETUP_AW " , &H03 , 1 'Data "SETUP_RETR " , &H04 , 1 'Data "RF_CH " , &H05 , 1 'Data "RF_SETUP " , &H06 , 1 'Data "STATUS " , &H07 , 1 'Data "OBSERVE_TX " , &H08 , 1 'Data "RcdPowerD " , &H09 , 1 'Data "RX_ADDR_P0 " , &H0A , 4 'Data "RX_ADDR_P1 " , &H0B , 4 'Data "RX_ADDR_P2 " , &H0C , 1 'Data "RX_ADDR_P3 " , &H0D , 1 'Data "RX_ADDR_P4 " , &H0E , 1 'Data "RX_ADDR_P5 " , &H0F , 1 'Data "TX_ADDR " , &H10 , 4 'Data "RX_PW_P0 " , &H11 , 1 'Data "RX_PW_P1 " , &H12 , 1 'Data "RX_PW_P2 " , &H13 , 1 'Data "RX_PW_P3 " , &H14 , 1 'Data "RX_PW_P4 " , &H15 , 1 'Data "RX_PW_P5 " , &H16 , 1 'Data "FIFO_STAT " , &H17 , 1 'Data "DYN_PD " , &H1C , 1 'Data "Features " , &H1D , 1 'Data "End " , &HFF , 0 Nrf_registers_init: Data "CONFIG_nRF " , &H00 , &B00001011 'PRX=1(RX_device), PWR_UP=1, CRC 2bytes, Enable CRC '&B00001111 ' ^ Module function as 0=TX, 1=RX ' ^ 0=Power Down, 1=Up ' ^ CRC type 0=1 byte, 1=2 byte ' ^ Enable CRC ' x^^^ Three sources of interrupts 0=enabled Data "EN_AA " , &H01 , &B00000001 'Enable auto ACK for pipe0 Data "EN_RXADDR " , &H02 , &B00111111 'Enable RX address for pipe0 Data "SETUP_AW " , &H03 , &B00000010 'number of address bytes '&B00000010 ' ^^ 01=3, 10=4, 11=5 Data "SETUP_RETR " , &H04 , &B11111111 'TX Retry wait; Num Retries '&B00110011 ' ^^ Num retries=3 ' ^^ TX retry wait=1000 uS Data "RF_CH " , &H05 , 27 'Set RF channel; range is 0-125 '2.400 - 2.525 GHz in 1 MHz increments 'FIND A FREQUENCY WITH THE LEAST INTERFERENCE Data "RF_SETUP " , &H06 , &B00100111 'Output power 0dbm, datarate 2Mbps and LNA gain on '&B00000000 ' ^ LNA Gain on=1 ' ^^ Power in TX 00=-18 dBm, -> 11=0 dBm ' ^ ^ Speed 00=1 MBPS, 01=2 MBPS, 10=250KBPS Data "STATUS " , &H07 , &B01110000 'Reset IRQ vector Data "DYN_Payld " , &H1C , &B00000001 'Dynamic payload pipe 0 &B00000001 Data "Features " , &H1D , &B00000100 'Enable Dynamic Payload length &B00000100 Data "End " , &HFF , 0 '========================================= 'PushButton Interrupts '========================================= Do0: Pbs.0 = 1 Return Do1: Pbs.1 = 1 Return [/code:1:36deabc27d] And ........... [code:1:36deabc27d] '=====BL.Remote.M644P.nRF24L01.UART.1.bas==================================== 'Bootloader Remote 644p 'Nov 15, 2013 'Revised: ' 'Thanks to Evert Dekker for the inspiration and BASCOM AN#151 '============================================= $regfile = "m644pdef.dat" $crystal = 8000000 $baud = 38400 $hwstack = 80 ' default use 32 for the hardware stack $swstack = 64 ' default use 10 for the SW stack $framesize = 64 ' default use 40 for the frame space $version 1 , 0 , 2 '========================================== 'Bootloader Config '========================================== Disable Interrupts 'we do not use ints $loader = $7800 Const Bootloader_start = $7800 ' Bootloader Hex $LOADERSIZE ' 8000 none 10000 ' 7E00 FC00 $400 ' 7C00 F800 $800 ' 7800 F000 $1000 ' 7000 E000 $2000 Const Maxwordbit = 7 'Z7 is maximum bit ' Const Maxword =(2 ^ Maxwordbit) * 2 '128 Const Maxwordshift = Maxwordbit + 1 '========================================== 'AtMega SPI Config '========================================== Config Portb.4 = Output Set Portb.4 Config Spi = Hard , Interrupt = Off , Data Order = Msb , Master = Yes , Polarity = Low , Phase = 0 , Clockrate = 4 , Noss = 1 Spiinit '============================================ 'nRF24L01+ Nordic Semiconductor '============================================ Const Dev_id = 15 'Address LSB of this TARGET device Nrfce Alias Portb.3 Config Nrfce = Output Nrfce = 1 Nrfcs Alias Portb.0 Config Nrfcs = Output Nrfcs = 1 Nrfint Alias Pinb.1 Config Nrfint = Input Declare Sub R_register(byval Command As Byte , Byval Start_b As Byte , Byval Num_b As Byte) Declare Sub W_register(byval Start_b As Byte , Byval Num_b As Byte) Declare Sub Nrf24l01init() Declare Function Transmit(byval Tx As Byte , Byval Pl_w As Byte) As Byte Declare Function Receive() As Byte 'SPI(nRF24L01) commands Const Write_reg = &H20 Const Rd_rx_pload = &H61 Const Wr_tx_pload = &HA0 Const Flush_tx = &HE1 Const Flush_rx = &HE2 'Registers Const Config_nrf = &H00 Const Status = &H07 Const Fifo_stat = &H17 Const Tx_addr = &H10 Const Rx_addr_p0 = &H0A Const R_rx_pl_wid = &B01100000 'VALUES Const Nrfwait = 5 'Not Optimized 'CAUTION: 'The nRF24L01 module has a 3-level Receive FIFO 'and a 3-level Transmit FIFO. If TX is too fast, the data 'may go into a level other than the first and this Bootloader 'will not work. Const V_irq_reset = &B01110000 Const V_set_tx = &B00001010 Const V_set_rx = &B00001011 'PRX=1(RX_device), PWR_UP=1, CRC 2bytes, Enable CRC '&B00001111 ' ^ Module function as 0=TX, 1=RX ' ^ 0=Power Down, 1=Up ' ^ CRC type 0=1 byte, 1=2 byte ' ^ Enable CRC ' x^^^ Three sources of interrupts 0=enabled '==================================================== 'RAM dBase Array '==================================================== 'This RAM array assumes a 4-byte address for each nRF24L01 'The indeces (IDX) below need to be changed if using 3 or 5 byte address 'and the array will need re-mapping ' ' 2 1 4 1 4 1 1 1 32 '1 2 34567 89012 3 4 5 6789012345 6789012345 6789012345 67 8 'T R TAd RAd PW IrCm|-------- Payload ----------------| Const Payload_idx = 32 + 16 Const T_idx = 1 Const Tadr_idx = 3 Const Radr_idx = 8 Const Pw_idx = 13 Const Irq_idx = 14 Const Pl_cmd_idx = 15 Const Pl_idx = 16 Dim Payload(payload_idx) As Byte 'Main RAM space where Vars and Payload are OVERLAYED Dim Tb As Byte At Payload(t_idx) Overlay , Rb As Byte At Payload(t_idx) + 1 Overlay Dim Tx_addr_lsb As Byte At Payload(tadr_idx) + 1 Overlay , P0_addr_lsb As Byte At Payload(radr_idx) + 1 Overlay Dim Pw As Byte At Payload(pw_idx) Overlay , Irq_stat As Byte At Payload(irq_idx) Overlay Dim Reg_name As String * 12 , Reg_addr As Byte , Reg_vals As Byte Tb = Tadr_idx Payload(tb + 4) = &H12 ') Payload(tb + 3) = &H34 ') Same MSB bytes Payload(tb + 2) = &H00 ') Payload(tadr_idx) = Write_reg + Tx_addr Rb = Radr_idx Payload(rb + 4) = &H12 ') Payload(rb + 3) = &H34 ') Same MSB bytes Payload(rb + 2) = &H00 ') Payload(radr_idx ) = Write_reg + Rx_addr_p0 '============================================ 'Scratchpad '============================================ Dim I As Byte , J As Byte , K As Byte , Jj As Byte , W As Word , Kk As Byte '============================================ 'User defined '============================================ Dim Mv(32) As Byte At Payload(pl_idx) Overlay Dim Blockidx As Byte , Spmsize As Byte , Buf(128) As Byte Dim Z As Long 'this is the Z pointer word Dim Vl As Byte , Vh As Byte ' these bytes are used for the data values Dim Wrd As Word , Page As Word 'these vars contain the page and word address Dim Bkind As Byte , Spmcrval As Byte '============================================ 'Initialize components '============================================ Call Nrf24l01init() '============================================ ' Main '============================================ Spmsize = 32 Print : Print : Print "BL M644p Addr LSB:15 Ver:" ; Version(2) Print "BL Start-" ; I = 9 Do J = 250 Print I; Do Decr J Waitms 4 Loop Until Nrfint = 0 Or J = 0 If Nrfint = 0 Then Kk = Receive() Blockidx = Mv(1) End If If I = 0 Then Goto _reset 'goto the normal reset vector at address 0 Decr I Loop Until Blockidx = 123 Or Blockidx = 124 Waitms Nrfwait Bkind = Mv(1) : Kk = Transmit(1 , 2) 'send back mv(1) = 123 or 124 Page = 0 : Wrd = 0 Print : Print "Page:" ; Page ; "."; Do For I = 0 To 3 Bitwait Nrfint , Reset Kk = Receive() If I = 0 And Mv(1) = 255 Then Blockidx = 255 : Exit Do End If J = Spmsize * I : For Jj = 1 To Spmsize : K = J + Jj : Buf(k) = Mv(jj) : Next Next Bitwait Nrfint , Reset Kk = Receive() : Blockidx = Mv(1) If Blockidx = 1 Then Gosub Writepage If Blockidx = 255 Then Exit Do Loop Print : Print "Exit" If Bkind = 123 Then If Blockidx = 255 Or Wrd > 0 Then 'if there was something left in the page Wrd = 0 'Z pointer needs wrd to be 0 Spmcrval = 5 : Gosub Do_spm 'write page Spmcrval = 17 : Gosub Do_spm ' re-enable page End If End If Goto _reset End '============================================= 'nRF24L01+ Subroutines '============================================= Sub Nrf24l01init() Nrfce = 0 'Low to Write Restore Nrf_registers_init Do Read Reg_name : Read Reg_addr : Read Rb If Reg_addr = 255 Then Exit Do Tb = Write_reg + Reg_addr : Call W_register(t_idx , 2) Loop P0_addr_lsb = Dev_id : Call W_register(radr_idx , 5) 'Put this device 4-byte address in Pipe 0 for RX Tb = Flush_tx : Call W_register(t_idx , 1) 'Flush TX_fifo buffer Tb = Flush_rx : Call W_register(t_idx , 1) 'Flush RX_fifo buffer Nrfce = 1 End Sub Function Transmit(byval Tx As Byte , Byval Pl_w As Byte) As Byte Nrfce = 0 'set CE LO to write registers Tb = Write_reg + Config_nrf : Rb = V_set_tx 'Set to TX Call W_register(t_idx , 2) Tb = Flush_tx : Call W_register(t_idx , 1) 'Flush the TX_fifo buffer Tb = Write_reg + Status : Rb = V_irq_reset 'Reset the IRQ bits Call W_register(t_idx , 2) Tx_addr_lsb = Tx : Call W_register(tadr_idx , 5) 'LSB of Target Put 4-bytes TARGET address in TX P0_addr_lsb = Tx : Call W_register(radr_idx , 5) 'LSB of Target Put same 4-byte address in Pipe 0 for ACK Payload(pl_cmd_idx) = Wr_tx_pload 'Put bytes in the TX pload buffer Call W_register(Pl_cmd_idx , Pl_w) Nrfce = 1 : Waitus 200 : Nrfce = 0 : W = 0 'Set CE for a short moment to transmit the fifo buffer Bitwait Nrfint , Reset Call R_register(status , Irq_idx , 1) 'save TX status bit overlayed into IRQ_Stat Tb = Write_reg + Status : Rb = V_irq_reset 'Reset the IRQ bits Call W_register(t_idx , 2) P0_addr_lsb = Dev_id : Call W_register(radr_idx , 5) 'LSB of this device Put this device 4-byte address BACK in RX Pipe 0 Tb = Write_reg + Config_nrf : Rb = V_set_rx 'Set to RX Call W_register(t_idx , 2) Nrfce = 1 Transmit = Irq_stat.5 End Function 'set CE HIGH to turn on Device Receive Function Receive() As Byte Call R_register(r_rx_pl_wid , Pw_idx , 1) Call R_register(status , Irq_idx , 1) 'save Receive interrupt overlayed into IRQ_Stat If Pw <= 32 And Pw > 0 And Irq_stat.6 = 1 Then Call R_register(rd_rx_pload , Pl_idx , Pw) Else Irq_stat = 0 'Read bytes RX to buffer overlayed in MV array Nrfce = 0 'set CE Low to read registers Tb = Flush_rx : Call W_register(t_idx , 1) 'Flush the rX_fifo buffer Tb = Write_reg + Status : Rb = V_irq_reset 'Reset interrupts Call W_register(t_idx , 2) Nrfce = 1 'set CE HIGH for Receive Receive = Irq_stat.6 End Function Sub W_register(byval Start_b As Byte , Byval Num_b As Byte) Reset Nrfcs Spiout Payload(start_b) , Num_b Set Nrfcs End Sub Sub R_register(byval Command As Byte , Byval Start_b As Byte , Byval Num_b As Byte) Reset Nrfcs Spiout Command , 1 Spiin payload(start_b) , Num_b Set Nrfcs End Sub '============================= 'nRF24L01+ Register addresses '============================= 'Registers: 'Data "CONFIG_nRF " , &H00 , 1 'Data "EN_AA " , &H01 , 1 'Data "EN_RXADDR " , &H02 , 1 'Data "SETUP_AW " , &H03 , 1 'Data "SETUP_RETR " , &H04 , 1 'Data "RF_CH " , &H05 , 1 'Data "RF_SETUP " , &H06 , 1 'Data "STATUS " , &H07 , 1 'Data "OBSERVE_TX " , &H08 , 1 'Data "RcdPowerD " , &H09 , 1 'Data "RX_ADDR_P0 " , &H0A , 4 'Data "RX_ADDR_P1 " , &H0B , 4 'Data "RX_ADDR_P2 " , &H0C , 1 'Data "RX_ADDR_P3 " , &H0D , 1 'Data "RX_ADDR_P4 " , &H0E , 1 'Data "RX_ADDR_P5 " , &H0F , 1 'Data "TX_ADDR " , &H10 , 4 'Data "RX_PW_P0 " , &H11 , 1 'Data "RX_PW_P1 " , &H12 , 1 'Data "RX_PW_P2 " , &H13 , 1 'Data "RX_PW_P3 " , &H14 , 1 'Data "RX_PW_P4 " , &H15 , 1 'Data "RX_PW_P5 " , &H16 , 1 'Data "FIFO_STAT " , &H17 , 1 'Data "DYN_PD " , &H1C , 1 'Data "Features " , &H1D , 1 'Data "End " , &HFF , 0 Nrf_registers_init: Data "CONFIG_nRF " , &H00 , &B00001011 'PRX=1(RX_device), PWR_UP=1, CRC 2bytes, Enable CRC '&B00001111 ' ^ Module function as 0=TX, 1=RX ' ^ 0=Power Down, 1=Up ' ^ CRC type 0=1 byte, 1=2 byte ' ^ Enable CRC ' x^^^ Three sources of interrupts 0=enabled Data "EN_AA " , &H01 , &B00000001 'Enable auto ACK for pipe0 Data "EN_RXADDR " , &H02 , &B00111111 'Enable RX address for pipe0 Data "SETUP_AW " , &H03 , &B00000010 'number of address bytes '&B00000010 ' ^^ 01=3, 10=4, 11=5 Data "SETUP_RETR " , &H04 , &B11111111 'TX Retry wait; Num Retries '&B00110011 ' ^^ Num retries=3 ' ^^ TX retry wait=1000 uS Data "RF_CH " , &H05 , 27 'Set RF channel; range is 0-125 '2.400 - 2.525 GHz in 1 MHz increments 'FIND A FREQUENCY WITH THE LEAST INTERFERENCE Data "RF_SETUP " , &H06 , &B00100111 'Output power 0dbm, datarate 2Mbps and LNA gain on '&B00000000 ' ^ LNA Gain on=1 ' ^^ Power in TX 00=-18 dBm, -> 11=0 dBm ' ^ ^ Speed 00=1 MBPS, 01=2 MBPS, 10=250KBPS ' 76543210 Data "STATUS " , &H07 , &B01110000 'Reset IRQ vector Data "DYN_Payld " , &H1C , &B00000001 'Dynamic payload pipe 0 &B00000001 Data "Features " , &H1D , &B00000100 'Enable Dynamic Payload length &B00000100 Data "End " , &HFF , 0 Writepage: If Bkind = 123 Then If Wrd = 0 Then Spmcrval = 3 : Gosub Do_spm ' erase the first page Spmcrval = 17 : Gosub Do_spm ' re-enable page End If For J = 1 To 128 Step 2 'we write 2 bytes into a page Vl = Buf(j) : Vh = Buf(j + 1) 'get Low and High bytes lds r0, {vl} 'store them into r0 and r1 registers lds r1, {vh} Spmcrval = 1 : Gosub Do_spm 'write value into page at word address Wrd = Wrd + 2 ' word address increases with 2 because LS bit of Z is not used If Wrd = Maxword Then ' page is full Wrd = 0 'Z pointer needs wrd to be 0 Spmcrval = 5 : Gosub Do_spm 'write page Spmcrval = 17 : Gosub Do_spm ' re-enable page Page = Page + 1 : Print Page ; "."; 'next page End If Next Else 'eeprom For J = 1 To 128 Writeeeprom Buf(j) , Wrd Wrd = Wrd + 1 Next End If Return Do_spm: Bitwait Spmcsr.0 , Reset ' check for previous SPM complete Bitwait Eecr.1 , Reset 'wait for eeprom Z = Page 'make equal to page Shift Z , Left , Maxwordshift 'shift to proper place Z = Z + Wrd 'add word lds r30,{Z} lds r31,{Z+1} #if _romsize > 65536 lds r24,{Z+2} sts rampz,r24 ' we need to set rampz also for the M128 #endif Spmcsr = Spmcrval 'assign register spm 'this is an asm instruction nop nop Return[/code:1:36deabc27d][code:1:36deabc27d][/code:1:36deabc27d]

Viewing all articles
Browse latest Browse all 20606

Trending Articles