void radio_getReceivedFrame(uint8_t* pBufRead, uint8_t* pLenRead, uint8_t maxBufLen, int8_t* pRssi, uint8_t* pLqi, uint8_t* pCrc) { uint8_t crc_corr,i; uint8_t len=0; /* Check the length */ len = HWREG(RFCORE_SFR_RFDATA); //first byte is len /* Check for validity */ if(len > CC2538_RF_MAX_PACKET_LEN) { /* wrong len */ CC2538_RF_CSP_ISFLUSHRX(); return; } if(len <= CC2538_RF_MIN_PACKET_LEN) { //too short CC2538_RF_CSP_ISFLUSHRX(); return; } //check if this fits to the buffer if(len > maxBufLen) { CC2538_RF_CSP_ISFLUSHRX(); return; } // when reading the packet from the RX buffer, you get the following: // - *[1B] length byte // - [0-125B] packet (excluding CRC) // - [1B] RSSI // - *[2B] CRC //skip first byte is len for(i = 1; i < len; i++) { pBufRead[i] = HWREG(RFCORE_SFR_RFDATA); } *pRssi = ((int8_t)(HWREG(RFCORE_SFR_RFDATA)) - RSSI_OFFSET); crc_corr = HWREG(RFCORE_SFR_RFDATA); *pCrc = crc_corr & CRC_BIT_MASK; *pLenRead = len; //flush it CC2538_RF_CSP_ISFLUSHRX(); }
port_INLINE void radio_off(){ /* Wait for ongoing TX to complete (e.g. this could be an outgoing ACK) */ while(HWREG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_TX_ACTIVE); CC2538_RF_CSP_ISFLUSHRX(); /* Don't turn off if we are off as this will trigger a Strobe Error */ if(HWREG(RFCORE_XREG_RXENABLE) != 0) { CC2538_RF_CSP_ISRFOFF(); //clear fifo isr flag HWREG(RFCORE_SFR_RFIRQF0) = ~(RFCORE_SFR_RFIRQF0_FIFOP|RFCORE_SFR_RFIRQF0_RXPKTDONE); } }
void radio_reset() { /* Wait for ongoing TX to complete (e.g. this could be an outgoing ACK) */ while(HWREG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_TX_ACTIVE); //flush fifos CC2538_RF_CSP_ISFLUSHRX(); CC2538_RF_CSP_ISFLUSHTX(); /* Don't turn off if we are off as this will trigger a Strobe Error */ if(HWREG(RFCORE_XREG_RXENABLE) != 0) { CC2538_RF_CSP_ISRFOFF(); } radio_init(); }
/*---------------------------------------------------------------------------*/ static int on(void) { PRINTF("RF: On\n"); if(!(rf_flags & RX_ACTIVE)) { CC2538_RF_CSP_ISFLUSHRX(); CC2538_RF_CSP_ISRXON(); rf_flags |= RX_ACTIVE; } ENERGEST_ON(ENERGEST_TYPE_LISTEN); return 1; }
/*---------------------------------------------------------------------------*/ static int off(void) { PRINTF("RF: Off\n"); /* Wait for ongoing TX to complete (e.g. this could be an outgoing ACK) */ while(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_TX_ACTIVE); CC2538_RF_CSP_ISFLUSHRX(); /* Don't turn off if we are off as this will trigger a Strobe Error */ if(REG(RFCORE_XREG_RXENABLE) != 0) { CC2538_RF_CSP_ISRFOFF(); } rf_flags &= ~RX_ACTIVE; ENERGEST_OFF(ENERGEST_TYPE_LISTEN); return 1; }
/*---------------------------------------------------------------------------*/ static int read(void *buf, unsigned short bufsize) { uint8_t i; uint8_t len; uint8_t crc_corr; int8_t rssi; PRINTF("RF: Read\n"); if((REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_FIFOP) == 0) { return 0; } /* Check the length */ len = REG(RFCORE_SFR_RFDATA); /* Check for validity */ if(len > CC2538_RF_MAX_PACKET_LEN) { /* Oops, we must be out of sync. */ PRINTF("RF: bad sync\n"); RIMESTATS_ADD(badsynch); CC2538_RF_CSP_ISFLUSHRX(); return 0; } if(len <= CC2538_RF_MIN_PACKET_LEN) { PRINTF("RF: too short\n"); RIMESTATS_ADD(tooshort); CC2538_RF_CSP_ISFLUSHRX(); return 0; } if(len - CHECKSUM_LEN > bufsize) { PRINTF("RF: too long\n"); RIMESTATS_ADD(toolong); CC2538_RF_CSP_ISFLUSHRX(); return 0; } /* If we reach here, chances are the FIFO is holding a valid frame */ PRINTF("RF: read (0x%02x bytes) = ", len); len -= CHECKSUM_LEN; /* Don't bother with uDMA for short frames (e.g. ACKs) */ if(CC2538_RF_CONF_RX_USE_DMA && len > UDMA_RX_SIZE_THRESHOLD) { PRINTF("<uDMA payload>"); /* Set the transfer destination's end address */ udma_set_channel_dst(CC2538_RF_CONF_RX_DMA_CHAN, (uint32_t)(buf) + len - 1); /* Configure the control word */ udma_set_channel_control_word(CC2538_RF_CONF_RX_DMA_CHAN, UDMA_RX_FLAGS | udma_xfer_size(len)); /* Enabled the RF RX uDMA channel */ udma_channel_enable(CC2538_RF_CONF_RX_DMA_CHAN); /* Trigger the uDMA transfer */ udma_channel_sw_request(CC2538_RF_CONF_RX_DMA_CHAN); /* Wait for the transfer to complete. */ while(udma_channel_get_mode(CC2538_RF_CONF_RX_DMA_CHAN)); } else { for(i = 0; i < len; ++i) { ((unsigned char *)(buf))[i] = REG(RFCORE_SFR_RFDATA); PRINTF("%02x", ((unsigned char *)(buf))[i]); } } /* Read the RSSI and CRC/Corr bytes */ rssi = ((int8_t)REG(RFCORE_SFR_RFDATA)) - RSSI_OFFSET; crc_corr = REG(RFCORE_SFR_RFDATA); PRINTF("%02x%02x\n", (uint8_t)rssi, crc_corr); /* MS bit CRC OK/Not OK, 7 LS Bits, Correlation value */ if(crc_corr & CRC_BIT_MASK) { packetbuf_set_attr(PACKETBUF_ATTR_RSSI, rssi); packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, crc_corr & LQI_BIT_MASK); RIMESTATS_ADD(llrx); } else { RIMESTATS_ADD(badcrc); PRINTF("RF: Bad CRC\n"); CC2538_RF_CSP_ISFLUSHRX(); return 0; } #if CC2538_RF_CONF_SNIFFER write_byte(magic[0]); write_byte(magic[1]); write_byte(magic[2]); write_byte(magic[3]); write_byte(len + 2); for(i = 0; i < len; ++i) { write_byte(((unsigned char *)(buf))[i]); } write_byte(rssi); write_byte(crc_corr); flush(); #endif /* If FIFOP==1 and FIFO==0 then we had a FIFO overflow at some point. */ if(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_FIFOP) { if(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_FIFO) { process_poll(&cc2538_rf_process); } else { CC2538_RF_CSP_ISFLUSHRX(); } } return (len); }
void radio_init() { // clear variables memset(&radio_vars,0,sizeof(radio_vars_t)); // change state radio_vars.state = RADIOSTATE_STOPPED; //flush fifos CC2538_RF_CSP_ISFLUSHRX(); CC2538_RF_CSP_ISFLUSHTX(); radio_off(); //disable radio interrupts disable_radio_interrupts(); /* This CORR_THR value should be changed to 0x14 before attempting RX. Testing has shown that * too many false frames are received if the reset value is used. Make it more likely to detect * sync by removing the requirement that both symbols in the SFD must have a correlation value * above the correlation threshold, and make sync word detection less likely by raising the * correlation threshold. */ HWREG(RFCORE_XREG_MDMCTRL1) = 0x14; /* tuning adjustments for optimal radio performance; details available in datasheet */ HWREG(RFCORE_XREG_RXCTRL) = 0x3F; /* Adjust current in synthesizer; details available in datasheet. */ HWREG(RFCORE_XREG_FSCTRL) = 0x55; /* Makes sync word detection less likely by requiring two zero symbols before the sync word. * details available in datasheet. */ HWREG(RFCORE_XREG_MDMCTRL0) = 0x85; /* Adjust current in VCO; details available in datasheet. */ HWREG(RFCORE_XREG_FSCAL1) = 0x01; /* Adjust target value for AGC control loop; details available in datasheet. */ HWREG(RFCORE_XREG_AGCCTRL1) = 0x15; /* Tune ADC performance, details available in datasheet. */ HWREG(RFCORE_XREG_ADCTEST0) = 0x10; HWREG(RFCORE_XREG_ADCTEST1) = 0x0E; HWREG(RFCORE_XREG_ADCTEST2) = 0x03; //update CCA register to -81db as indicated by manual.. won't be used.. HWREG(RFCORE_XREG_CCACTRL0) = 0xF8; /* * Changes from default values * See User Guide, section "Register Settings Update" */ HWREG(RFCORE_XREG_TXFILTCFG) = 0x09; /** TX anti-aliasing filter bandwidth */ HWREG(RFCORE_XREG_AGCCTRL1) = 0x15; /** AGC target value */ HWREG(ANA_REGS_O_IVCTRL) = 0x0B; /** Bias currents */ /* disable the CSPT register compare function */ HWREG(RFCORE_XREG_CSPT) = 0xFFUL; /* * Defaults: * Auto CRC; Append RSSI, CRC-OK and Corr. Val.; CRC calculation; * RX and TX modes with FIFOs */ HWREG(RFCORE_XREG_FRMCTRL0) = RFCORE_XREG_FRMCTRL0_AUTOCRC; //poipoi disable frame filtering by now.. sniffer mode. HWREG(RFCORE_XREG_FRMFILT0) &= ~RFCORE_XREG_FRMFILT0_FRAME_FILTER_EN; /* Disable source address matching and autopend */ HWREG(RFCORE_XREG_SRCMATCH) = 0; /* MAX FIFOP threshold */ HWREG(RFCORE_XREG_FIFOPCTRL) = CC2538_RF_MAX_PACKET_LEN; HWREG(RFCORE_XREG_TXPOWER) = CC2538_RF_TX_POWER; HWREG(RFCORE_XREG_FREQCTRL) = CC2538_RF_CHANNEL_MIN; /* Enable RF interrupts see page 751 */ // enable_radio_interrupts(); //register interrupt IntRegister(INT_RFCORERTX, radio_isr); IntRegister(INT_RFCOREERR, radio_error_isr); IntPrioritySet(INT_RFCORERTX, HAL_INT_PRIOR_MAC); IntPrioritySet(INT_RFCOREERR, HAL_INT_PRIOR_MAC); IntEnable(INT_RFCORERTX); /* Enable all RF Error interrupts */ HWREG(RFCORE_XREG_RFERRM) = RFCORE_XREG_RFERRM_RFERRM_M; //all errors IntEnable(INT_RFCOREERR); //radio_on(); // change state radio_vars.state = RADIOSTATE_RFOFF; }
port_INLINE void radio_on(){ CC2538_RF_CSP_ISFLUSHRX(); CC2538_RF_CSP_ISRXON(); }