/* switch the radio on */ int on(void) { /* Check whether radio is in sleep */ if (sleep_on) { /* Wake the radio. It'll move to TRX_OFF state */ gpio_clear(SLP_PIN); delay_ms(1); printf("RF233: Wake from sleep\n"); sleep_on = 0; } uint8_t state_now = rf233_status(); if (state_now != STATE_PLL_ON && state_now != STATE_TRX_OFF && state_now != STATE_TX_ARET_ON) { PRINTF("RF233: Failed to turn radio on, state is %s.\n", state_str(state_now)); return -1; } PRINTF("RF233: State is %s, transitioning to PLL_ON.\n", state_str(rf233_status())); radio_pll = false; RF233_COMMAND(TRXCMD_PLL_ON); wait_for(&radio_pll); delay_ms(1); PRINTF("RF233: State is %s, transitioning to RX_ON.\n", state_str(rf233_status())); /* go to RX_ON state */ RF233_COMMAND(TRXCMD_RX_ON); radio_is_on = 1; PRINTF("RF233: Radio is on, state is %s.\n", state_str(rf233_status())); return 0; }
/* switch the radio on */ int on(void) { /* Check whether radio is in sleep */ if(sleep_on) { /* Wake the radio. It'll move to TRX_OFF state */ wake_from_sleep(); delay_ms(1); //printf("\r\nWake from sleep %d",rf233_get_channel()); sleep_on = 0; } uint8_t state_now = rf233_status(); if(state_now != STATE_PLL_ON && state_now != STATE_TRX_OFF #if NULLRDC_CONF_802154_AUTOACK_HW && state_now != STATE_TX_ARET_ON #endif ) { /* fail, we need the radio transceiver to be in either of those states */ return -1; } /* go to RX_ON state */ ENERGEST_ON(ENERGEST_TYPE_LISTEN); #if NULLRDC_CONF_802154_AUTOACK_HW RF233_COMMAND(TRXCMD_RX_AACK_ON); #else RF233_COMMAND(TRXCMD_RX_ON); #endif radio_is_on = 1; return 0; }
/** * \brief Transmit a frame already put in the radio with 'prepare' * \param payload_len Length of the frame to send * \return Returns success/fail, refer to radio.h for explanation */ int rf233_transmit() { static uint8_t status_now; status_now = rf233_status(); PRINTF("RF233: attempting transmit, in state %s\n", state_str(status_now)); if (status_now == STATE_BUSY_RX_AACK || status_now == STATE_BUSY_TX_ARET) { PRINTF("RF233: collision, was in state %s\n", state_str(status_now)); /* NOTE: to avoid loops */ return RADIO_TX_ERR;; } if (status_now != STATE_PLL_ON) { trx_reg_write(RF233_REG_TRX_STATE, STATE_PLL_ON); do { // I think this code is broken, does nothing -pal status_now = trx_bit_read(RF233_REG_TRX_STATUS, 0x1F, 0); } while (status_now == 0x1f); } if (rf233_status() != STATE_PLL_ON) { /* failed moving into PLL_ON state, gracefully try to recover */ PRINTF("RF233: failed going to STATE_PLL_ON\n"); RF233_COMMAND(TRXCMD_PLL_ON); /* try again */ static uint8_t state; state = rf233_status(); if(state != STATE_PLL_ON) { PRINTF("RF233: graceful recovery (in tx) failed, giving up. State: 0x%02X\n", rf233_status()); return RADIO_TX_ERR; } } /* perform transmission */ flag_transmit = 1; radio_tx = false; RF233_COMMAND(TRXCMD_TX_ARET_ON); RF233_COMMAND(TRXCMD_TX_START); PRINTF("RF233:: Issued TX_START, wait for completion interrupt.\n"); wait_for(&radio_tx); PRINTF("RF233: tx ok\n\n"); return RADIO_TX_OK; }
/* switch the radio off */ int off(void) { if(rf233_status() != STATE_RX_ON ) { /* fail, we need the radio transceiver to be in this state */ return -1; } /* turn off the radio transceiver */ RF233_COMMAND(TRXCMD_TRX_OFF); radio_is_on = 0; return 0; }
/** * \brief perform a clear channel assessment * \retval >0 Channel is clear * \retval 0 Channel is not clear */ int rf233_channel_clear(void) { uint8_t regsave; int was_off = 0; if(rf233_status() != STATE_RX_ON) { /* CCA can only be performed in RX state */ was_off = 1; RF233_COMMAND(TRXCMD_RX_ON); } delay_us(200); /* request a CCA, storing the channel number (set with the same reg) */ regsave = trx_reg_read(RF233_REG_PHY_CC_CCA); regsave |= PHY_CC_CCA_DO_CCA | PHY_CC_CCA_MODE_CS_OR_ED; trx_reg_write(RF233_REG_PHY_CC_CCA, regsave); BUSYWAIT_UNTIL(trx_reg_read(RF233_REG_TRX_STATUS) & TRX_CCA_DONE, RTIMER_SECOND / 1000); //regsave = rf233_status(); regsave = trx_reg_read(RF233_REG_TRX_STATUS); /* return to previous state */ if(was_off) { RF233_COMMAND(TRXCMD_TRX_OFF); } #if NULLRDC_CONF_802154_AUTOACK_HW else{ RF233_COMMAND(TRXCMD_RX_AACK_ON); } #endif /* check CCA */ if((regsave & TRX_CCA_DONE) && (regsave & TRX_CCA_STATUS)) { PRINTF("RF233: CCA 1\r\n"); return 1; } PRINTF("RF233: CCA 0\r\n"); return 0; }
/* switch the radio off */ int off(void) { #if NULLRDC_CONF_802154_AUTOACK_HW if(rf233_status() != STATE_RX_AACK_ON ) { #else if(rf233_status() != STATE_RX_ON) { #endif /* fail, we need the radio transceiver to be in this state */ return -1; } /* turn off the radio transceiver */ ENERGEST_OFF(ENERGEST_TYPE_LISTEN); RF233_COMMAND(TRXCMD_TRX_OFF); radio_is_on = 0; return 0; } /*---------------------------------------------------------------------------*/ /* Put the Radio in sleep mode */ int rf233_sleep(void) { int status; /* Check whether we're already sleeping */ if (!sleep_on) { //printf("\r\n goto sleep %d",rf233_get_channel()); //delay_ms(1); sleep_on = 1; /* Turn off the Radio */ status = rf233_off(); /* Set the SLP_PIN to high */ if(status == 0) { goto_sleep(); } } return 0; }
void interrupt_callback() { volatile uint8_t irq_source; PRINTF("RF233: interrupt handler.\n"); /* handle IRQ source (for what IRQs are enabled, see rf233-config.h) */ irq_source = trx_reg_read(RF233_REG_IRQ_STATUS); PRINTF(" interrupt sources: 0x%x\n", (int)irq_source); if (irq_source & IRQ_PLL_LOCK) { PRINTF("RF233: PLL locked.\n"); radio_pll = true; return; } else if (irq_source == IRQ_RX_START) { PRINTF("RF233: Interrupt receive start.\n"); } else if (irq_source == IRQ_TRX_DONE) { PRINTF("RF233: TRX_DONE handler.\n"); // Completed a transmission if (flag_transmit != 0) { PRINTF("RF233: Interrupt transmit.\n"); flag_transmit = 0; if (!(trx_reg_read(RF233_REG_TRX_STATE) & TRX_STATE_TRAC_STATUS)) { flag_transmit = ack_status = 1; } RF233_COMMAND(TRXCMD_RX_ON); PRINTF("RF233: TX complete, go back to RX with acks on.\n"); radio_tx = true; return; } else { //PRINTF("RF233: Interrupt receive.\n"); packetbuf_clear(); pending_frame = 1; int len = rf233_read(packetbuf_dataptr(), MAX_PACKET_LEN); if (len > 0) { PRINTF("RF233: Received packet and read from device.\n\n"); } else { PRINTF("RF233: Read failed.\n\n"); } radio_rx = true; return; } } }
/** * \brief RF233 radio process poll function, to be called from the * interrupt handler to poll the radio process * \retval 0 success */ int rf233_interrupt_poll(void) { volatile uint8_t irq_source; /* handle IRQ source (for what IRQs are enabled, see rf233-config.h) */ irq_source = trx_reg_read(RF233_REG_IRQ_STATUS); if(irq_source & IRQ_TRX_DONE) { if(flag_transmit==1) { flag_transmit=0; interrupt_callback_in_progress = 0; #if NULLRDC_CONF_802154_AUTOACK_HW //printf("Status %x",trx_reg_read(RF233_REG_TRX_STATE) & TRX_STATE_TRAC_STATUS); if(!(trx_reg_read(RF233_REG_TRX_STATE) & TRX_STATE_TRAC_STATUS)) ack_status = 1; RF233_COMMAND(TRXCMD_RX_AACK_ON); #endif return 0; } if( interrupt_callback_in_progress) { /* we cannot read out info from radio now, return here later (through a poll) */ interrupt_callback_wants_poll = 1; process_poll(&rf233_radio_process); PRINTF("RF233: irq but busy, returns later.\r\n"); return 0; } interrupt_callback_wants_poll = 0; interrupt_callback_in_progress = 1; /* we have started receiving a frame, len can be read */ pending_frame = 1; //delay_cycles_ms(1); process_poll(&rf233_radio_process); } #if 0 /* Note, these are not currently in use but here for completeness. */ if(irq_source & IRQ_TRX_DONE) { /* End of transmitted or received frame. */ } if(irq_source & IRQ_TRXBUF_ACCESS_VIOLATION) { /* * Access violation on the shared TX/RX FIFO. Possible causes: * - buffer underrun while transmitting, ie not enough data in FIFO to tx * - reading too fast from FIFO during rx, ie not enough data received yet * - haven't read last rxed frame when next rx starts, but first is possible * to read out, with possible corruption - check FCS * - writing frames larger than 127 B to FIFO (len byte) */ PRINTF("RF233-arch: access violation.\n"); } if(irq_source & IRQ_BAT_LOW) { /* Battery low */ } if(irq_source & IRQ_RX_ADDRESS_MATCH) { /* receiving frame address match */ } if(irq_source & IRQ_CCA_ED_DONE) { /* CCA/ED done */ } if(irq_source & IRQ_PLL_UNLOCK) { /* PLL unlock */ } if(irq_source & IRQ_PLL_LOCK) { /* PLL lock */ } #endif interrupt_callback_in_progress = 0; return 0; }
/** * \brief prepare a frame and the radio for immediate transmission * \param payload Pointer to data to copy/send * \param payload_len length of data to copy * \return Returns success/fail, refer to radio.h for explanation */ int rf233_prepare(const void *payload, unsigned short payload_len) { #if DEBUG_PRINTDATA int i; #endif /* DEBUG_PRINTDATA */ uint8_t templen; uint8_t radio_status; uint8_t data[130]; #if USE_HW_FCS_CHECK /* Add length of the FCS (2 bytes) */ templen = payload_len + 2; #else /* USE_HW_FCS_CHECK */ /* FCS is assumed to already be included in the payload */ templen = payload_len; #endif /* USE_HW_FCS_CHECK */ //data = templen; /* for(i = 0; i < templen; i++) { data++; data =(uint8_t *)(payload + i); }*/ //memcpy(data,&templen,1); data[0] = templen; memcpy(&data[1],payload,templen); //data--; #if DEBUG_PRINTDATA PRINTF("RF233 prepare (%u/%u): 0x", payload_len, templen); for(i = 0; i < templen; i++) { PRINTF("%02x", *(uint8_t *)(payload + i)); } PRINTF("\r\n"); #endif /* DEBUG_PRINTDATA */ PRINTF("RF233: prepare %u\r\n", payload_len); if(payload_len > MAX_PACKET_LEN) { PRINTF("RF233: error, frame too large to tx\r\n"); return RADIO_TX_ERR; } /* check that the FIFO is clear to access */ radio_status=rf233_status(); #if NULLRDC_CONF_802154_AUTOACK_HW if(radio_status == STATE_BUSY_RX_AACK || radio_status == STATE_BUSY_TX_ARET) { PRINTF("RF233: TRX buffer unavailable: prep when %s\r\n", radio_status == STATE_BUSY_RX_AACK ? "rx" : "tx"); #else if(radio_status == STATE_BUSY_RX || radio_status == STATE_BUSY_TX) { PRINTF("RF233: TRX buffer unavailable: prep when %s\r\n", radio_status == STATE_BUSY_RX? "rx" : "tx"); #endif return RADIO_TX_ERR; } /* Write packet to TX FIFO. */ PRINTF("RF233 len = %u\r\n", payload_len); trx_frame_write((uint8_t *)data, templen+1); return RADIO_TX_OK; } /*---------------------------------------------------------------------------*/ /** * \brief Transmit a frame already put in the radio with 'prepare' * \param payload_len Length of the frame to send * \return Returns success/fail, refer to radio.h for explanation */ int rf233_transmit(unsigned short payload_len) { static uint8_t status_now; PRINTF("RF233: tx %u\r\n", payload_len); /* prepare for TX */ status_now = rf233_status(); //status_now = trx_reg_read(RF233_REG_TRX_RPC); #if NULLRDC_CONF_802154_AUTOACK_HW if(status_now == STATE_BUSY_RX_AACK || status_now == STATE_BUSY_TX_ARET) { #else if(status_now == STATE_BUSY_RX || status_now == STATE_BUSY_TX) { #endif PRINTF("RF233: collision, was receiving 0x%02X\r\n",status_now); /* NOTE: to avoid loops */ return RADIO_TX_ERR;; // return RADIO_TX_COLLISION; } if(status_now != STATE_PLL_ON) { /* prepare for going to state TX, should take max 80 us */ //RF233_COMMAND(TRXCMD_PLL_ON); trx_reg_write(RF233_REG_TRX_STATE,0x09); // BUSYWAIT_UNTIL(trx_reg_read(RF233_REG_TRX_STATUS) == STATE_PLL_ON, 1 * RTIMER_SECOND/1000); //delay_ms(10); //status_now = trx_reg_read(RF233_REG_TRX_STATE); do { status_now = trx_bit_read(0x01, 0x1F, 0); } while (status_now == 0x1f); } if(rf233_status() != STATE_PLL_ON) { /* failed moving into PLL_ON state, gracefully try to recover */ PRINTF("RF233: failed going to PLLON\r\n"); RF233_COMMAND(TRXCMD_PLL_ON); /* try again */ static uint8_t state; state = rf233_status(); if(state != STATE_PLL_ON) { /* give up and signal big fail (should perhaps reset radio core instead?) */ PRINTF("RF233: graceful recovery (in tx) failed, giving up. State: 0x%02X\r\n", rf233_status()); return RADIO_TX_ERR; } } /* perform transmission */ ENERGEST_OFF(ENERGEST_TYPE_LISTEN); ENERGEST_ON(ENERGEST_TYPE_TRANSMIT); #if NULLRDC_CONF_802154_AUTOACK_HW RF233_COMMAND(TRXCMD_TX_ARET_ON); #endif RF233_COMMAND(TRXCMD_TX_START); flag_transmit=1; //delay_ms(5); //printf("RTIMER value %d",RTIMER_NOW()); #if !NULLRDC_CONF_802154_AUTOACK_HW BUSYWAIT_UNTIL(rf233_status() == STATE_BUSY_TX, RTIMER_SECOND/2000); // printf("RTIMER value1 %d",RTIMER_NOW()); // printf("\r\nSTATE_BUSY_TX"); BUSYWAIT_UNTIL(rf233_status() != STATE_BUSY_TX, 10 * RTIMER_SECOND/1000); // printf("RTIMER value2 %d",RTIMER_NOW()); #endif ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT); ENERGEST_ON(ENERGEST_TYPE_LISTEN); #if !NULLRDC_CONF_802154_AUTOACK_HW if(rf233_status() != STATE_PLL_ON) { // something has failed PRINTF("RF233: radio fatal err after tx\r\n"); radiocore_hard_recovery(); return RADIO_TX_ERR; } RF233_COMMAND(TRXCMD_RX_ON); #else BUSYWAIT_UNTIL(ack_status == 1, 10 * RTIMER_SECOND/1000); if((ack_status)) { // printf("\r\nrf233 sent\r\n "); ack_status=0; // printf("\nACK received"); return RADIO_TX_OK; } else { // printf("\nNOACK received"); return RADIO_TX_NOACK; } #endif PRINTF("RF233: tx ok\r\n"); return RADIO_TX_OK; } /*---------------------------------------------------------------------------*/ /** * \brief Send data: first prepares, then transmits * \param payload Pointer to data to copy/send * \param payload_len length of data to copy * \return Returns success/fail, refer to radio.h for explanation */ int rf233_send(const void *payload, unsigned short payload_len) { PRINTF("RF233: send %u\r\n", payload_len); if(rf233_prepare(payload, payload_len) == RADIO_TX_ERR) { return RADIO_TX_ERR; } return rf233_transmit(payload_len); } /*---------------------------------------------------------------------------*/ /** * \brief read a received frame out of the radio buffer * \param buf pointer to where to copy received data * \param bufsize Maximum size we can copy into bufsize * \return Returns length of data read (> 0) if successful * \retval -1 Failed, was transmitting so FIFO is invalid * \retval -2 Failed, rx timed out (stuck in rx?) * \retval -3 Failed, too large frame for buffer * \retval -4 Failed, CRC/FCS failed (if USE_HW_FCS_CHECK is true) */ int rf233_read(void *buf, unsigned short bufsize) { // uint8_t radio_state; uint8_t ed; /* frame metadata */ uint8_t frame_len = 0; uint8_t len = 0; int rssi; #if DEBUG_PRINTDATA uint8_t tempreadlen; #endif /* DEBUG_PRINTDATA */ if(pending_frame == 0) { return 0; } pending_frame = 0; /* / * check that data in FIFO is valid * / radio_state = RF233_STATUS(); if(radio_state == STATE_BUSY_TX) { / * data is invalid, bail out * / PRINTF("RF233: read while in BUSY_TX ie invalid, dropping.\n"); return -1; } if(radio_state == STATE_BUSY_RX) { / * still receiving - data is invalid, wait for it to finish * / PRINTF("RF233: read while BUSY_RX, waiting.\n"); BUSYWAIT_UNTIL(RF233_STATUS() != STATE_BUSY_RX, 10 * RTIMER_SECOND/1000); if(RF233_STATUS() == STATE_BUSY_RX) { PRINTF("RF233: timed out, still BUSY_RX, dropping.\n"); return -2; } } */ /* get length of data in FIFO */ trx_frame_read(&frame_len, 1); #if DEBUG_PRINTDATA tempreadlen = frame_len; #endif /* DEBUG_PRINTDATA */ if(frame_len == 1) { frame_len = 0; } len = frame_len; #if USE_HW_FCS_CHECK /* FCS has already been stripped */ len = frame_len - 2; #endif /* USE_HW_FCS_CHECK */ if(frame_len == 0) { return 0; } if(len > bufsize) { /* too large frame for the buffer, drop */ PRINTF("RF233: too large frame for buffer, dropping (%u > %u).\r\n", frame_len, bufsize); flush_buffer(); return -3; } PRINTF("RF233 read %u B\r\n", frame_len); /* read out the data into the buffer, disregarding the length and metadata bytes */ trx_sram_read(1,(uint8_t *)buf, len); #if DEBUG_PRINTDATA { int k; PRINTF("RF233: Read frame (%u/%u): ", tempreadlen, frame_len); for(k = 0; k < frame_len; k++) { PRINTF("%02x", *((uint8_t *)buf + k)); } PRINTF("\r\n"); } #endif /* DEBUG_PRINTDATA */ /* * Energy level during reception, ranges from 0x00 to 0x53 (=83d) with a * resolution of 1dB and accuracy of +/- 5dB. 0xFF means invalid measurement. * 0x00 means <= RSSI(base_val), which is -91dBm (typ). See datasheet 12.7. * Ergo, real RSSI is (ed-91) dBm or less. */ #define RSSI_OFFSET (91) ed = trx_reg_read(RF233_REG_PHY_ED_LEVEL); rssi = (int) ed - RSSI_OFFSET; packetbuf_set_attr(PACKETBUF_ATTR_RSSI, rssi); flush_buffer(); /* #if USE_HW_FCS_CHECK { uint8_t crc_ok; / * frame metadata * / crc_ok = rf233_arch_read_reg(RF233_REG_PHY_RSSI) & PHY_RSSI_CRC_VALID; if(crc_ok == 0) { / * CRC/FCS fail, drop * / PRINTF("RF233: CRC/FCS fail, dropping.\n"); flush_buffer(); return -4; } } #endif / * USE_HW_FCS_CHECK * /*/ return len; }