static void RADIO_HandleStateMachine(void) { uint8_t status; for(;;) { /* will break/return */ switch (RADIO_AppStatus) { case RADIO_INITIAL_STATE: RF1_StopRxTx(); /* will send/receive data later */ RADIO_AppStatus = RADIO_RECEIVER_ALWAYS_ON; /* turn receive on */ break; /* process switch again */ case RADIO_RECEIVER_ALWAYS_ON: /* turn receive on */ RX_POWERUP(); RF1_StartRxTx(); /* Listening for packets */ RADIO_AppStatus = RADIO_READY_FOR_TX_RX_DATA; break; /* process switch again */ case RADIO_READY_FOR_TX_RX_DATA: /* we are ready to receive/send data data */ if (RADIO_isrFlag) { /* Rx interrupt? */ RADIO_isrFlag = FALSE; /* reset interrupt flag */ (void)CheckRx(); /* get message */ RADIO_AppStatus = RADIO_RECEIVER_ALWAYS_ON; /* continue listening */ break; /* process switch again */ } if (CheckTx()==ERR_OK) { /* there was data and it has been sent */ RADIO_AppStatus = RADIO_WAITING_DATA_SENT; break; /* process switch again */ } return; case RADIO_WAITING_DATA_SENT: if (RADIO_isrFlag) { /* check if we have received an interrupt: this is either timeout or low level ack */ RADIO_isrFlag = FALSE; /* reset interrupt flag */ status = RF1_GetStatus(); if (status&RF1_STATUS_RX_DR) { /* data received interrupt */ RF1_ResetStatusIRQ(RF1_STATUS_RX_DR); /* clear bit */ } if (status&RF1_STATUS_TX_DS) { /* data sent interrupt */ RF1_ResetStatusIRQ(RF1_STATUS_TX_DS); /* clear bit */ } if (status&RF1_STATUS_MAX_RT) { /* retry timeout interrupt */ RF1_ResetStatusIRQ(RF1_STATUS_MAX_RT); /* clear bit */ RF1_Write(RF1_FLUSH_TX); /* flush old data */ RADIO_AppStatus = RADIO_TIMEOUT; /* timeout */ } else { RADIO_AppStatus = RADIO_RECEIVER_ALWAYS_ON; /* turn receive on */ } break; /* process switch again */ } return; case RADIO_TIMEOUT: Err((unsigned char*)"ERR: Timeout\r\n"); RADIO_AppStatus = RADIO_RECEIVER_ALWAYS_ON; /* turn receive on */ break; /* process switch again */ default: /* should not happen! */ return; } /* switch */ } /* for */ }
void nrf_simplebyte(uint8_t cmd) { RF1_Write(cmd); #if 0 cbi(PORTB, PIN_nCS); spi_byte(cmd); sbi(PORTB, PIN_nCS); #endif }
/* called to check if we have something in the RX queue. If so, we queue it */ static uint8_t CheckRx(void) { uint8_t res = ERR_OK; uint8_t RxDataBuffer[RPHY_BUFFER_SIZE]; uint8_t status; RPHY_PacketDesc packet; bool hasRxData; hasRxData = FALSE; packet.flags = RPHY_PACKET_FLAGS_NONE; packet.phyData = &RxDataBuffer[0]; packet.phySize = sizeof(RxDataBuffer); #if NRF24_DYNAMIC_PAYLOAD packet.rxtx = RPHY_BUF_PAYLOAD_START(packet.phyData); #else packet.rxtx = &RPHY_BUF_SIZE(packet.phyData); /* we transmit the data size too */ #endif status = RF1_GetStatus(); if (status&RF1_STATUS_RX_DR) { /* data received interrupt */ hasRxData = TRUE; #if NRF24_DYNAMIC_PAYLOAD uint8_t payloadSize; (void)RF1_ReadNofRxPayload(&payloadSize); if (payloadSize>32) { /* packet with error? */ RF1_Write(RF1_FLUSH_RX); /* flush old data */ return ERR_FAILED; } else { RF1_RxPayload(packet.rxtx, payloadSize); /* get payload: note that we transmit <size> as payload! */ RPHY_BUF_SIZE(packet.phyData) = payloadSize; } #else RF1_RxPayload(packet.rxtx, RPHY_PAYLOAD_SIZE); /* get payload: note that we transmit <size> as payload! */ #endif RF1_ResetStatusIRQ(RF1_STATUS_RX_DR|RF1_STATUS_TX_DS|RF1_STATUS_MAX_RT); /* make sure we reset all flags. Need to have the pipe number too */ } if (status&RF1_STATUS_TX_DS) { /* data sent interrupt */ RF1_ResetStatusIRQ(RF1_STATUS_TX_DS); /* clear bit */ } if (status&RF1_STATUS_MAX_RT) { /* retry timeout interrupt */ RF1_ResetStatusIRQ(RF1_STATUS_MAX_RT); /* clear bit */ } if (hasRxData) { /* put message into Rx queue */ res = RMSG_QueueRxMsg(packet.phyData, packet.phySize, RPHY_BUF_SIZE(packet.phyData), packet.flags); if (res!=ERR_OK) { if (res==ERR_OVERFLOW) { Err((unsigned char*)"ERR: Rx queue overflow!\r\n"); } else { Err((unsigned char*)"ERR: Rx Queue full?\r\n"); } } } return res; }
void APP_Run(void) { static const uint8_t chRf[] = {2, 26,80}; static const uint8_t chLe[] = {37,38,39}; uint8_t i, L, ch = 0; uint8_t buf[32]; nrf_cmd(0x20, 0x12); //on, no crc, int on RX/TX done nrf_cmd(0x21, 0x00); //no auto-acknowledge nrf_cmd(0x22, 0x00); //no RX nrf_cmd(0x23, 0x02); //5-byte address nrf_cmd(0x24, 0x00); //no auto-retransmit nrf_cmd(0x26, 0x06); //1MBps at 0dBm nrf_cmd(0x27, 0x3E); //clear various flags nrf_cmd(0x3C, 0x00); //no dynamic payloads nrf_cmd(0x3D, 0x00); //no features nrf_cmd(0x31, 32); //always RX 32 bytes nrf_cmd(0x22, 0x01); //RX on pipe 0 buf[0] = 0x30; //set addresses buf[1] = swapbits(0x8E); buf[2] = swapbits(0x89); buf[3] = swapbits(0xBE); buf[4] = swapbits(0xD6); #if 0 nrf_manybytes(buf, 5); #else RF1_WriteRegisterData(RF1_TX_ADDR, &buf[1], 4); #endif buf[0] = 0x2A; #if 0 nrf_manybytes(buf, 5); #else RF1_WriteRegisterData(RF1_RX_ADDR_P0, &buf[1], 4); #endif while(1) { L = 0; buf[L++] = 0x40; //PDU type, given address is random buf[L++] = 11; //17 bytes of payload buf[L++] = MY_MAC_0; buf[L++] = MY_MAC_1; buf[L++] = MY_MAC_2; buf[L++] = MY_MAC_3; buf[L++] = MY_MAC_4; buf[L++] = MY_MAC_5; buf[L++] = 2; //flags (LE-only, limited discovery mode) buf[L++] = 0x01; buf[L++] = 0x05; buf[L++] = 7; buf[L++] = 0x08; buf[L++] = 'n'; buf[L++] = 'R'; buf[L++] = 'F'; buf[L++] = ' '; buf[L++] = 'L'; buf[L++] = 'E'; buf[L++] = 0x55; //CRC start value: 0x555555 buf[L++] = 0x55; buf[L++] = 0x55; if(++ch == sizeof(chRf)) { /* channel hopping */ ch = 0; } //nrf_cmd(0x25, chRf[ch]); (void)RF1_SetChannel(chRf[ch]); //nrf_cmd(0x27, 0x6E); //clear flags RF1_WriteRegister(RF1_STATUS, RF1_STATUS_RX_DR|RF1_STATUS_TX_DS|RF1_STATUS_RX_P_NO_RX_FIFO_EMPTY); /* clear flags */ btLePacketEncode(buf, L, chLe[ch]); //nrf_simplebyte(0xE2); //Clear RX Fifo RF1_Write(RF1_FLUSH_RX); /* flush old data */ //nrf_simplebyte(0xE1); //Clear TX Fifo //RF1_Write(RF1_FLUSH_TX); /* flush old data */ /* done in RF1_TxPayload() */ RF1_TxPayload(buf, L); #if 0 cbi(PORTB, PIN_nCS); spi_byte(0xA0); for(i = 0 ; i < L ; i++) { spi_byte(buf[i]); } sbi(PORTB, PIN_nCS); nrf_cmd(0x20, 0x12); //tx on sbi(PORTB, PIN_CE); //do tx delay_ms(10); cbi(PORTB, PIN_CE); (in preparation of switching to RX quickly); #endif LED1_Neg(); WAIT1_Waitms(10); } /* for */ }