// Configures RF parameters before Enhanced Shockburst can be used. void configureRF() { packet_received = false; send_success = false; // Enable the radio clock RFCKEN = 1; // Set payload width to 32 bytes hal_nrf_set_rx_payload_width((int)HAL_NRF_PIPE0, PAYLOAD_SIZE); // Set auto-retries to 5 with 500 us intervals hal_nrf_set_auto_retr(5, 500); // Set pipe address hal_nrf_set_address(HAL_NRF_PIPE0, default_pipe_address); hal_nrf_set_address(HAL_NRF_TX, default_pipe_address); // Set initial channel hal_nrf_set_rf_channel(default_channels[1]); // Configure radio as primary receiver (PTX) hal_nrf_set_operation_mode(HAL_NRF_PRX); // Wait for the xtal to power up while (hal_clk_get_16m_source() != HAL_CLK_XOSC16M) ; // Power up radio hal_nrf_set_power_mode(HAL_NRF_PWR_UP); // Enable receiver CE_HIGH(); return; }
char nrf_snd_pkt_crc_encr(int size, uint8_t * pkt, uint32_t const key[4]){ if(size > MAX_PKT) size=MAX_PKT; nrf_write_reg(R_CONFIG, R_CONFIG_PWR_UP| // Power on R_CONFIG_EN_CRC // CRC on, single byte ); // nrf_write_long(C_W_TX_PAYLOAD,size,pkt); uint16_t crc=crc16(pkt,size-2); pkt[size-2]=(crc >>8) & 0xff; pkt[size-1]=crc & 0xff; if(key !=NULL) xxtea_encode_words((uint32_t*)pkt,size/4,key); CS_LOW(); xmit_spi(C_W_TX_PAYLOAD); sspSend(0,pkt,size); CS_HIGH(); CE_HIGH(); delayms(1); // Send it. (only needs >10ys, i think) CE_LOW(); return nrf_cmd_status(C_NOP); };
/* Send function. * Write to send_buf[1] - send_buf[31] before calling this function. * command will be placed in send_buf[0].*/ void send(command_t command) { uint8_t i; // Set operation mode to transmit. CE_LOW(); hal_nrf_set_operation_mode(HAL_NRF_PTX); // Copy command to send buffer. send_buf[0] = command; hal_nrf_write_tx_payload(send_buf, PAYLOAD_SIZE); // Activate sender CE_PULSE(); send_success = false; // Wait for radio to transmit while (RFF != 1) ; RFF = 0; nrf_irq(); // Clear send buffer. for (i = 0; i < PAYLOAD_SIZE; i++) { send_buf[i] = 0x00; } // Reset operation mode to receive. hal_nrf_set_operation_mode(HAL_NRF_PRX); CE_HIGH(); }
app_states_t app_init(void) { if(usb_get_state() == USB_REM_WU_ENABLE) { return APP_SUSP_WE; } if(usb_get_state() == USB_REM_WU_DISABLE) { return APP_SUSP_WD; } /* I3FR = 1; // rising edge SPI ready detect INTEXP = 0x01; //Slave SPI Interrupt SPI = 1; // Enable SPI Interrupt */ hal_nrf_enable_ack_payload(1); hal_nrf_enable_dynamic_payload(1); hal_nrf_setup_dynamic_payload(1 << 0); // Set up PIPE 0 to handle dynamic lengths hal_nrf_set_operation_mode(HAL_NRF_PRX); // Configure radio as primary receiver (PTX) //hal_nrf_set_rx_payload_width(HAL_NRF_PIPE0, 30); // Set payload width to 30 bytes hal_nrf_set_power_mode(HAL_NRF_PWR_UP); // Power up radio CE_HIGH(); // Enable receiver return APP_NORMAL; }
// High-Level: void nrf_rcv_pkt_start(void){ nrf_write_reg(R_CONFIG, R_CONFIG_PRIM_RX| // Receive mode R_CONFIG_PWR_UP| // Power on R_CONFIG_EN_CRC // CRC on, single byte ); nrf_cmd(C_FLUSH_RX); nrf_write_reg(R_STATUS,0); CE_HIGH(); };
T2_ISR() { T2_STOP(); TF2 = 0; if(t2_sta==1){ CE_HIGH(); t2_sta = 2; T2 = (65536-16*TIME/12); T2_START(); }else if(t2_sta == 2){ CE_LOW(); T2_STOP(); } }
__interrupt void t2_irq(void) { if(t2_sta == 1){ t2_sta = 2; CE_HIGH(); TCCR2B = 0; TCNT2 = 0; OCR2A = 240; TCCR2B = 0x01; }else if(t2_sta == 2){ T2_STOP(); TCNT2 = 0; CE_LOW(); } }
char snd_pkt_no_crc(int size, uint8_t * pkt) { if(size > MAX_PKT) size=MAX_PKT; nrf_write_reg(R_CONFIG, R_CONFIG_PWR_UP| // Power on R_CONFIG_EN_CRC // CRC on, single byte ); CS_LOW(); xmit_spi(C_W_TX_PAYLOAD); sspSend(0,pkt,size); CS_HIGH(); CE_HIGH(); delayms(1); // Send it. (only needs >10ys, i think) CE_LOW(); return nrf_cmd_status(C_NOP); }
void main() { #ifdef MCU_NRF24LE1 while(hal_clk_get_16m_source() != HAL_CLK_XOSC16M) { // Wait until 16 MHz crystal oscillator is running } #endif #ifdef MCU_NRF24LU1P // Enable radio SPI RFCTL = 0x10; #endif // Set P0 as output P0DIR = 0; // Enable the radio clock RFCKEN = 1; // Enable RF interrupt RF = 1; // Enable global interrupt EA = 1; // Configure radio as primary receiver (PTX) hal_nrf_set_operation_mode(HAL_NRF_PRX); // Set payload width to 3 bytes hal_nrf_set_rx_payload_width((int)HAL_NRF_PIPE0, 3); // Power up radio hal_nrf_set_power_mode(HAL_NRF_PWR_UP); // Enable receiver CE_HIGH(); for(;;){} }
void device_prx_mode_esb(void) { CE_HIGH(); // Set Chip Enable (CE) pin high to enable reciever while(true) { start_timer(110); // Run until either 110ms has lapsed // OR there is data on the radio do { radio_irq (); } while ((radio_get_status () == RF_IDLE) && !timer_done()); if ((radio_get_status ()) == RF_RX_DR) { // Get the payload from the PTX and set LED1 if (radio_get_pload_byte (0) == 1) { LED1_ON(); } else { LED1_OFF(); } } else { LED1_OFF(); } // Set radio status to idle radio_set_status (RF_IDLE); } }
__interrupt void HAL_NRF_ISR(void) { u8 status, len, i; if(!IRQ) { /** */ // Read and clear IRQ flags from radio status = hal_nrf_nop(); // if(hal_nrf_ack_flag){ // if((status&0x60) == 0x60){ // hal_nrf_ack_flag = 0; // }else{ // read_flash_buf(slave_cmd, slave_cmd_request, CMD_LENGTH); // hal_nrf_write_ack_payload(0, slave_cmd, CMD_LENGTH); // } // } #ifdef SLAVE_DEBUG hal_nrf_irq_flag = status; #endif if(status & (1<< (uint8_t)HAL_NRF_RX_DR)){ do{ len = hal_nrf_read_rx_payload_width(); if(len > 32){ hal_nrf_write_reg (STATUS, (1<< (uint8_t)HAL_NRF_RX_DR)); hal_nrf_rx_sta = HAL_NRF_RX_STA_COM_ERROR; return; } if((hal_nrf_rx_cnt + len + 1) < HAL_NRF_RX_BUF_LEN){ hal_nrf_rx_buf[hal_nrf_rx_wr_index] = len; hal_nrf_rx_wr_index++; if(hal_nrf_rx_wr_index == HAL_NRF_RX_BUF_LEN){ hal_nrf_rx_wr_index=0; } // hal_nrf_read_payload((u8*)hal_nrf_rx_buf[hal_nrf_rx_wr_index].buf, len); CSN_LOW(); HAL_NRF_HW_SPI_WRITE(R_RX_PAYLOAD); while(HAL_NRF_HW_SPI_BUSY) {} HAL_NRF_HW_SPI_READ(); for(i=0; i<len; i++){ HAL_NRF_HW_SPI_WRITE(0U); while(HAL_NRF_HW_SPI_BUSY){} hal_nrf_rx_buf[hal_nrf_rx_wr_index] = HAL_NRF_HW_SPI_READ(); hal_nrf_rx_wr_index++; if(hal_nrf_rx_wr_index == HAL_NRF_RX_BUF_LEN){ hal_nrf_rx_wr_index=0; } } CSN_HIGH(); hal_nrf_rx_cnt = hal_nrf_rx_cnt+len+1; }else{ hal_nrf_flush_rx(); hal_nrf_rx_sta = HAL_NRF_RX_STA_BUF_OVF; /** clear RX_DR */ hal_nrf_write_reg (STATUS, (1<< (uint8_t)HAL_NRF_RX_DR)); break; } /** clear RX_DR */ hal_nrf_write_reg (STATUS, (1<< (uint8_t)HAL_NRF_RX_DR)); }while(!hal_nrf_rx_fifo_empty()); } if(status & (1 << (uint8_t)HAL_NRF_TX_DS)){ hal_nrf_write_reg (STATUS, (1<< (uint8_t)HAL_NRF_TX_DS)); switch(hal_nrf_sta){ case HAL_NRF_STA_TX: hal_nrf_tx_cmd_flag = 0; if(hal_nrf_tx_cnt){ hal_nrf_tx_busy = 1; len = hal_nrf_tx_buf[hal_nrf_tx_rd_index]; hal_nrf_tx_rd_index++; if(hal_nrf_tx_rd_index == HAL_NRF_TX_BUF_LEN){ hal_nrf_tx_rd_index = 0; } hal_nrf_tx_cnt = hal_nrf_tx_cnt-len-1; // hal_nrf_write_tx_payload(hal_nrf_tx_buf_tmp, len); CSN_LOW(); HAL_NRF_HW_SPI_WRITE(W_TX_PAYLOAD); while(HAL_NRF_HW_SPI_BUSY) {} HAL_NRF_HW_SPI_READ(); for(i=0; i<len; i++){ HAL_NRF_HW_SPI_WRITE(hal_nrf_tx_buf[hal_nrf_tx_rd_index]); hal_nrf_tx_rd_index++; if(hal_nrf_tx_rd_index == HAL_NRF_TX_BUF_LEN){ hal_nrf_tx_rd_index = 0; } while(HAL_NRF_HW_SPI_BUSY) {} /* wait for byte transfer finished */ HAL_NRF_HW_SPI_READ(); } CSN_HIGH(); // CE_HIGH(); // T2_START(); t2_start_delay(); }else{ if(hal_nrf_tx_sta == HAL_NRF_TX_STA_IDLE){ /** send end pkt */ hal_nrf_tx_sta = HAL_NRF_TX_STA_DONE; read_flash_buf(slave_cmd, slave_cmd_end, CMD_LENGTH); hal_nrf_write_tx_payload(slave_cmd, CMD_LENGTH); hal_nrf_tx_cmd_flag = 2; // CE_HIGH(); // T2_START(); t2_start_delay(); }else{ hal_nrf_tx_sta = HAL_NRF_TX_STA_IDLE; hal_nrf_sta = HAL_NRF_STA_RX; CE_LOW(); hal_nrf_flush_tx(); hal_nrf_flush_rx(); /** return to RX mode */ hal_nrf_set_operation_mode(HAL_NRF_PRX); CE_HIGH(); hal_nrf_tx_busy = 0; } } break; case HAL_NRF_STA_RX: /** ack payload send */ break; case HAL_NRF_STA_TX_CMD: hal_nrf_sta = HAL_NRF_STA_RX; CE_LOW(); hal_nrf_flush_tx(); hal_nrf_flush_rx(); /** return to RX mode */ hal_nrf_set_operation_mode(HAL_NRF_PRX); CE_HIGH(); hal_nrf_tx_busy = 0; hal_nrf_tx_cmd_flag = 0; break; } } if(status & (1 << (uint8_t)HAL_NRF_MAX_RT)){ #if 0 // When a MAX_RT interrupt occurs the TX payload will not be removed from the TX FIFO. // If the packet is to be discarded this must be done manually by flushing the TX FIFO. // Alternatively, CE_PULSE() can be called re-starting transmission of the payload. // (Will only be possible after the radio irq flags are cleared) hal_nrf_flush_tx(); hal_nrf_flush_rx(); hal_nrf_set_operation_mode(HAL_NRF_PRX); CE_HIGH(); hal_nrf_sta=HAL_NRF_STA_RX; /** discard all data in buffer */ hal_nrf_tx_busy = 0; hal_nrf_tx_cnt = 0; hal_nrf_tx_rd_index =0; hal_nrf_tx_wr_index = 0; // hal_nrf_flush_rx(); // hal_nrf_rx_cnt = 0; // hal_nrf_rx_rd_index =0; // hal_nrf_rx_wr_index = 0; /** set timeout flag */ hal_nrf_timeout = 1; hal_nrf_write_reg (STATUS, (1<< (uint8_t)HAL_NRF_MAX_RT)); #else hal_nrf_write_reg (STATUS, (1<< (uint8_t)HAL_NRF_MAX_RT)); switch(hal_nrf_sta){ case HAL_NRF_STA_TX: hal_nrf_tx_cmd_flag = 0; if(hal_nrf_tx_cnt){ hal_nrf_tx_busy = 1; len = hal_nrf_tx_buf[hal_nrf_tx_rd_index]; hal_nrf_tx_rd_index++; if(hal_nrf_tx_rd_index == HAL_NRF_TX_BUF_LEN){ hal_nrf_tx_rd_index = 0; } hal_nrf_tx_cnt = hal_nrf_tx_cnt-len-1; // hal_nrf_write_tx_payload(hal_nrf_tx_buf_tmp, len); CSN_LOW(); HAL_NRF_HW_SPI_WRITE(W_TX_PAYLOAD); while(HAL_NRF_HW_SPI_BUSY) {} HAL_NRF_HW_SPI_READ(); for(i=0; i<len; i++){ HAL_NRF_HW_SPI_WRITE(hal_nrf_tx_buf[hal_nrf_tx_rd_index]); hal_nrf_tx_rd_index++; if(hal_nrf_tx_rd_index == HAL_NRF_TX_BUF_LEN){ hal_nrf_tx_rd_index = 0; } while(HAL_NRF_HW_SPI_BUSY) {} /* wait for byte transfer finished */ HAL_NRF_HW_SPI_READ(); } CSN_HIGH(); // CE_HIGH(); // T2_START(); t2_start_delay(); }else{ if(hal_nrf_tx_sta == HAL_NRF_TX_STA_IDLE){ /** send end pkt */ hal_nrf_tx_sta = HAL_NRF_TX_STA_DONE; read_flash_buf(slave_cmd, slave_cmd_end, CMD_LENGTH); hal_nrf_write_tx_payload(slave_cmd, CMD_LENGTH); hal_nrf_tx_cmd_flag = 2; // CE_HIGH(); // T2_START(); t2_start_delay(); }else{ hal_nrf_tx_sta = HAL_NRF_TX_STA_IDLE; hal_nrf_sta = HAL_NRF_STA_RX; CE_LOW(); hal_nrf_flush_tx(); hal_nrf_flush_rx(); /** return to RX mode */ hal_nrf_set_operation_mode(HAL_NRF_PRX); CE_HIGH(); hal_nrf_tx_busy = 0; } } break; case HAL_NRF_STA_RX: /** ack payload send */ break; case HAL_NRF_STA_TX_CMD: hal_nrf_sta = HAL_NRF_STA_RX; CE_LOW(); hal_nrf_flush_tx(); hal_nrf_flush_rx(); /** return to RX mode */ hal_nrf_set_operation_mode(HAL_NRF_PRX); CE_HIGH(); hal_nrf_tx_busy = 0; hal_nrf_tx_cmd_flag = 0; break; } #endif } } }
void CE_PULSE(){ CE_HIGH(); i_delay = 300; while(i_delay--); CE_LOW(); }
// High-Level: int nrf_rcv_pkt_time_encr(int maxtime, int maxsize, uint8_t * pkt, uint32_t const key[4]){ uint8_t len; uint8_t status=0; uint16_t cmpcrc; nrf_write_reg(R_CONFIG, R_CONFIG_PRIM_RX| // Receive mode R_CONFIG_PWR_UP| // Power on R_CONFIG_EN_CRC // CRC on, single byte ); nrf_cmd(C_FLUSH_RX); nrf_write_reg(R_STATUS,0); CE_HIGH(); for(int i=0;i<maxsize;i++) pkt[i] = 0x00; // Sanity: clear packet buffer #define LOOPY 10 for (;maxtime >= LOOPY;maxtime-=LOOPY){ delayms(LOOPY); status =nrf_cmd_status(C_NOP); if( (status & R_STATUS_RX_DR) == R_STATUS_RX_DR){ if( (status & R_STATUS_RX_P_NO) == R_STATUS_RX_FIFO_EMPTY){ nrf_cmd(C_FLUSH_RX); delayms(1); nrf_write_reg(R_STATUS,0); continue; }else{ // Get/Check packet... nrf_read_long(C_R_RX_PL_WID,1,&len); if(len>32 || len==0){ continue; return -2; // no packet error }; if(len>maxsize){ continue; return -1; // packet too large }; nrf_read_pkt(len,pkt); if(key != NULL) xxtea_decode_words((uint32_t*)pkt,len/4,key); cmpcrc=crc16(pkt,len-2); if(cmpcrc != (pkt[len-2] <<8 | pkt[len-1])) { continue; return -3; // CRC failed }; break; }; }; }; CE_LOW(); CS_HIGH(); if(maxtime<LOOPY) return 0; // timeout return len; };