/*---------------------------------------------------------------------------*/ static int prepare(const void *payload, unsigned short payload_len) { uint8_t i; PRINTF("RF: Prepare 0x%02x bytes\n", payload_len + CHECKSUM_LEN); /* * When we transmit in very quick bursts, make sure previous transmission * is not still in progress before re-writing to the TX FIFO */ while(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_TX_ACTIVE); if((rf_flags & RX_ACTIVE) == 0) { on(); } CC2538_RF_CSP_ISFLUSHTX(); PRINTF("RF: data = "); /* Send the phy length byte first */ REG(RFCORE_SFR_RFDATA) = payload_len + CHECKSUM_LEN; if(CC2538_RF_CONF_TX_USE_DMA) { PRINTF("<uDMA payload>"); /* Set the transfer source's end address */ udma_set_channel_src(CC2538_RF_CONF_TX_DMA_CHAN, (uint32_t)(payload) + payload_len - 1); /* Configure the control word */ udma_set_channel_control_word(CC2538_RF_CONF_TX_DMA_CHAN, UDMA_TX_FLAGS | udma_xfer_size(payload_len)); /* Enabled the RF TX uDMA channel */ udma_channel_enable(CC2538_RF_CONF_TX_DMA_CHAN); /* Trigger the uDMA transfer */ udma_channel_sw_request(CC2538_RF_CONF_TX_DMA_CHAN); /* * No need to wait for this to end. Even if transmit() gets called * immediately, the uDMA controller will stream the frame to the TX FIFO * faster than transmit() can empty it */ } else { for(i = 0; i < payload_len; i++) { REG(RFCORE_SFR_RFDATA) = ((unsigned char *)(payload))[i]; PRINTF("%02x", ((unsigned char *)(payload))[i]); } } PRINTF("\n"); return 0; }
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(); }
void radio_loadPacket(uint8_t* packet, uint8_t len) { uint8_t i=0; // change state radio_vars.state = RADIOSTATE_LOADING_PACKET; // load packet in TXFIFO /* * When we transmit in very quick bursts, make sure previous transmission * is not still in progress before re-writing to the TX FIFO */ while(HWREG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_TX_ACTIVE); CC2538_RF_CSP_ISFLUSHTX(); /* Send the phy length byte first -- */ HWREG(RFCORE_SFR_RFDATA) = len; //crc len is included for(i = 0; i < len; i++) { HWREG(RFCORE_SFR_RFDATA) = packet[i]; } // change state radio_vars.state = RADIOSTATE_PACKET_LOADED; }
/*---------------------------------------------------------------------------*/ static int transmit(unsigned short transmit_len) { uint8_t counter; int ret = RADIO_TX_ERR; rtimer_clock_t t0; uint8_t was_off = 0; PRINTF("RF: Transmit\n"); if(!(rf_flags & RX_ACTIVE)) { t0 = RTIMER_NOW(); on(); was_off = 1; while(RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + ONOFF_TIME)); } if(channel_clear() == CC2538_RF_CCA_BUSY) { RIMESTATS_ADD(contentiondrop); return RADIO_TX_COLLISION; } /* * prepare() double checked that TX_ACTIVE is low. If SFD is high we are * receiving. Abort transmission and bail out with RADIO_TX_COLLISION */ if(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_SFD) { RIMESTATS_ADD(contentiondrop); return RADIO_TX_COLLISION; } /* Start the transmission */ ENERGEST_OFF(ENERGEST_TYPE_LISTEN); ENERGEST_ON(ENERGEST_TYPE_TRANSMIT); CC2538_RF_CSP_ISTXON(); counter = 0; while(!((REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_TX_ACTIVE)) && (counter++ < 3)) { clock_delay_usec(6); } if(!(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_TX_ACTIVE)) { PRINTF("RF: TX never active.\n"); CC2538_RF_CSP_ISFLUSHTX(); ret = RADIO_TX_ERR; } else { /* Wait for the transmission to finish */ while(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_TX_ACTIVE); ret = RADIO_TX_OK; } ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT); ENERGEST_ON(ENERGEST_TYPE_LISTEN); if(was_off) { off(); } RIMESTATS_ADD(lltx); return ret; }
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; }