'**************************************************************** '* Name : NRF24L01_18F13K22_RX.bas * '* Author : Barak Dar * '* Notice : Copyright (c) 2010 * '* : All Rights Reserved * '* Date : 8/11/2010 * '* Version : 1.0 * '* Notes : nRF24L01+ Primary RX test * '* : Receives segments of a String with a position * '* : pointer for the target array * '* : ShockBurst with ACK and Auto retransmit x 8 * '* : 250kbs * '* : Xtal not Shared (nRF module) * '* : All running from 3.3V incl. LCD * '**************************************************************** Device 18F13K22 Xtal = 16 Config_Start FOSC = IRC ;Internal RC oscillator PLLEN = OFF ; PLL is under software control PCLKEN = On ; Primary clock enabled FCMEN = On ; Fail-Safe Clock Monitor disabled IESO = OFF ; Oscillator Switchover mode disabled PWRTEN = OFF ; PWRT disabled BOREN = OFF ; Brown-out Reset disabled in hardware and software BORV = 22 ; VBOR set to 2.2 V nominal WDTEN = OFF ; WDT is controlled by SWDTEN bit of the WDTCON register WDTPS = 128 ; 1:128 MCLRE = OFF ; RE3 input pin enabled; MCLR disabled HFOFST = On ; The system clock is held off until the HFINTOSC is stable. STVREN = On ; Stack full/underflow will cause Reset LVP = OFF ; Single-Supply ICSP disabled BBSIZ = OFF ; 1KW boot block size XINST = OFF ; Instruction set extension and Indexed Addressing mode disabled Config_End '---[LCD Declares]------------------------ Declare LCD_Type 0 Declare LCD_DTPin PORTC.0 ' NOTICE: RC3 is disabled if config LVP = On Declare LCD_ENPin PORTA.1 Declare LCD_RSPin PORTA.0 Declare LCD_Interface 4 Declare LCD_Lines 2 '---[Port Setup]------------------------- PortSetUp: CM1CON0 = 0 ' disable compartor1 CM2CON0 = 0 ' disable compartor2 OSCCON = %01110010 ' IRCF<6:4> and SCS<1:0> => 16MHz internal osc ANSEL = 0 ' all digital ANSELH = 0 ' all digital TRISA = %00001100 ' RA2 input from IRQ, RA3 set for input from low count board switch TRISB = %00010000 ' portB RB6/SCL = 0 output ; RB4/SDI = 1 input TRISC = %00000000 ' portC '---[Weak Pullups Config]---------------- Pullup_Con: WPUA = %00000100 ' week pull-up on RA2 for IRQ WPUB = %00000000 ' no other week pull-up Symbol RABPU = INTCON2.7 ' PORTA/PORTB Pull-up Enable/disable RABPU = 0 ' allow weak pullup on portA/B '-----[NRF Interface setup]-------------- NRF_Interface: SSPCON1 = %00000001 ' configure SPI Master, FOSC/16 so SCL is 1MHz Symbol SSPEN = SSPCON1.5 ' SSP Enable bit Symbol CKP = SSPCON1.4 ' Clock Polarity Select Symbol SMP = SSPSTAT.7 ' Data input sample bit Symbol CKE = SSPSTAT.6 ' Clock Edge Select bit Symbol BF = SSPSTAT.0 ' buffer full status bit 1 = buffer full Symbol SSPIF = PIR1.3 ' interrupt flag - last bit set Symbol CSN = PORTC.6 ' "Chip Select Not" pin Symbol CE = PORTC.5 ' Controls Data transmit/receive Symbol IRQ = PORTA.2 ' IRQ can be used with INT2 on RA2 '---[Variables]-------------------------- Dim i As Byte ' loop index Dim j As Byte ' loop index Dim k As Byte ' loop index Dim DataIn[20] As Byte ' general array Dim spi_array[20] As Byte ' SPI transmit array '---[nRF command set]-------------------- Symbol W_REGISTER = 0x20 ' Address 0 Write Register command Symbol R_REGISTER = 0x00 ' Address 0 Read Register command Symbol R_RX_PAYLOAD = 0x61 ' Read RX payload Symbol W_TX_PAYLOAD = 0xA0 ' Write TX payload Symbol FLUSH_TX = 0xE1 ' Flush TX FIFO Symbol FLUSH_RX = 0xE2 ' Flush RX FIFO Symbol REUSE_TX_PL = 0xE3 ' Reuse last sent payload Symbol R_RX_PL_WID = 0x60 ' read RX payload width for the top Rx payload in the FIFO Symbol W_ACK_PAYLOAD = 0xA8 ' RX mode: write payload to be transmitted with ACK packet mask for last 3 bits in range 000 - 101 Symbol W_TX_PAYLOAD_NOACK = 0xB0 ' Disable auto ACK on the specific packet Symbol NRF_NOP = 0xFF ' Reuse last sent payload Symbol NRF_ADDR = 0xCFE7E7CF ' Pipe's address (4 Byte) - fixed in code for the demo, read from EEPROM in application '---[Start here]---------------------- RX_Boot: High CSN ' unselect NRF slave otherwise it will never work Low CE ' clear CE until we start working DelayMS 500 ' Wait to stabilize GoSub InitDOG162 ' intialize the 3.3V LCD '---[intilaize the SPI]--------------- SMP = 0 ' Data input sampled at middle of data output time CKE = 0 ' CPHA - transmit on rising edge idle to active CKP = 0 ' CPOL - idle state is low level SSPEN = 1 ' SSP Enable Main: ' intialize in test mode Print At 1,1, "PRX V.16" '***OFD*** DelayMS 1000 GoSub Init_PRX ' init the nRF as Receiver ' CE = 1 ' Active Rx mode k = 0 ' k is a pointer to position of data in receiver's array Clear DataIn Cls Print "PRX_PAYLOAD: " ' While 1 = 1 Clear spi_array ' clear the spi array While IRQ = 1 : Wend ' wait for RX_DR interrupt.In a real application we may do more stuff in the loop and have a way to abort DelayUS 500 ' delay for ACK CSN = 0 ' select the nRF spi_array[0] = R_RX_PAYLOAD ' Read Rx payload command j = 4 ' index of 5 bytes, (we have to send a byte to receive a byte) GoSub SPI_Global CSN = 1 k = spi_array[1] ' the first data byte containes the data position in the target array Print At 1, 15 , Dec2 k Cursor 2, k + 1 For i = 0 To 2 ' load to data array DataIn[k + i] = spi_array[i + 2] Print DataIn[k + i] ' show us the data Next ' just to make it display nice If k = 9 Then Clear DataIn DelayMS 400 Print At 2,1, " " DelayMS 100 EndIf ' Clear rx Interrupt CSN = 0 spi_array[0] = W_REGISTER | 0x07 ' W_REGISTER at address 0x07 => STATUS spi_array[1] = 0x40 ' Clear rx Interrupt j = 1 GoSub SPI_Global CSN = 1 ' optional, uncomment to flush ;CSN = 0 ;spi_array[0] = FLUSH_RX ' flush all 3 data buffers ;j = 0 ;GoSub SPI_Global ;CSN = 1 Wend '---[SPI using global vars]------------- SPI_Global: i = 0 Repeat SSPBUF = spi_array[i] ' put the output byte in the buffer While SSPIF = 0 : Wend ' wait for end of transaction SSPIF = 0 ' clear the SSP flag spi_array[i] = SSPBUF ' read the input buffer Inc i Until i > j Return '---[Initialize nRF as RX]--------------- Init_PRX: CE = 0 ' standby mode '---------------------------------------- 'REG 00 CONFIG CSN = 0 spi_array[0] = W_REGISTER ' W_REGISTER at address 0x00 => CONFIG spi_array[1] = 0x39 ' PRX, CRC enabled j = 1 GoSub SPI_Global CSN = 1 '---------------------------------------- 'REG 01 EN_AA CSN = 0 spi_array[0] = W_REGISTER | 0x01 ' W_REGISTER at address 0x01 => EN_AA spi_array[1] = 0x01 ' enable auto-ack only for pipe 0 j = 1 GoSub SPI_Global CSN = 1 '---------------------------------------- 'REG 02 EN_RXADDR CSN = 0 spi_array[0] = W_REGISTER | 0x02 ' W_REGISTER at address 0x02 => EN_RXADDR spi_array[1] = 0x01 ' enable only pipe 0 j = 1 GoSub SPI_Global CSN = 1 '---------------------------------------- 'REG 03 SETUP AW CSN = 0 spi_array[0] = W_REGISTER | 0x03 ' W_REGISTER at address 0x03 => SETUP AW spi_array[1] = 0x02 ' address width = 4 bytes j = 1 GoSub SPI_Global CSN = 1 '---------------------------------------- 'REG 05 RF_CH CSN = 0 spi_array[0] = W_REGISTER | 0x05 ' W_REGISTER at address 0x05 => RF_CH spi_array[1] = 0x02 ' set channel #2. For the application, make it selectable from E2PROM j = 1 GoSub SPI_Global CSN = 1 '---------------------------------------- 'REG 06 RF_SETUP CSN = 0 spi_array[0] = W_REGISTER | 0x06 ' W_REGISTER at address 0x06 => RF_SETUP spi_array[1] = 0x26 ' Reg_Data rate = 250kbps, RF_POWER 0dBm j = 1 GoSub SPI_Global CSN = 1 '---------------------------------------- 'REG 07 STATUS CSN = 0 spi_array[0] = W_REGISTER | 0x07 ' W_REGISTER at address 0x27 => STATUS spi_array[1] = 0x7E ' Clear Interrupts j = 1 GoSub SPI_Global CSN = 1 '---------------------------------------- 'REG 0A RX_ADDR_P0 CSN = 0 spi_array[0] = W_REGISTER | 0x0A ' W_REGISTER at address 0x0A => RX_ADDR_P0 spi_array[1] = NRF_ADDR.Byte0 ' RX address byte 0 LSByte spi_array[2] = NRF_ADDR.Byte1 ' RX address byte 1 spi_array[3] = NRF_ADDR.Byte2 ' RX address byte 2 spi_array[4] = NRF_ADDR.Byte3 ' RX address byte 3 j = 4 GoSub SPI_Global CSN = 1 '---------------------------------------- 'REG 11 RX_PW_PO CSN = 0 spi_array[0] = W_REGISTER | 0x11 ' W_REGISTER at address 0x11 => RX_PW_PO spi_array[1] = 0x04 ' 4 byte payload width on Pipe0 j = 1 GoSub SPI_Global CSN = 1 '---------------------------------------- 'REG 00 CONFIG CSN = 0 spi_array[0] = W_REGISTER ' W_REGISTER at address 0x00 => CONFIG spi_array[1] = 0x3B ' PRX, PWR_UP = 1,CRC = 1 byte, CRC enable, RX_DR INT j = 1 GoSub SPI_Global CSN = 1 Return ' this part relates to a specific type of LCD '---[DOG162-4bit-3.3V initialization]------ InitDOG162: Cls DelayMS 50 ' another delay For i = 0 To 8 j = CRead LCDInit + i ' load intialiazation command Print 0xFE, j ' send the command DelayUS 30 If i = 0x01 Then DelayMS 2 ' longer delay on Cls command Next DelayMS 100 Return '===[place at the end of the code]===================================== LCDInit: ' the command are per page 7 in the EADOGM162 @ 3.3V datasheet CData As Byte 0x29,_ ' Function set: 0x31 is for 1 line, 0x39 is for 2 lines, Instruction table 1 0x14,_ ' Bias set: 1/5, 2 line LCD 0x55,_ ' Power: booster On, contrast: clear C5, set C4 0x6D,_ ' Follower control 0x7C,_ ' Contrast 0x72 = 4 for FSTN, 0x7C is good for STN positive 0x28,_ ' Function Set: 0x28 for 2 lines 4bit 0x0F,_ ' display ON cursor ON, cursor blink 0x01,_ ' clear display cursor Home 0x06 ' cursor auto increment