/*------------------------------------------------------------------------------------*/ static void switch_to_rx(transceiver_type_t t) { switch (t) { #if (defined(MODULE_CC110X) || defined(MODULE_CC110X_LEGACY)) case TRANSCEIVER_CC1100: cc110x_switch_to_rx(); break; #endif #ifdef MODULE_CC2420 case TRANSCEIVER_CC2420: cc2420_switch_to_rx(); break; #endif #ifdef MODULE_NATIVENET case TRANSCEIVER_NATIVE: nativenet_switch_to_rx(); break; #endif #ifdef MODULE_AT86RF231 case TRANSCEIVER_AT86RF231: at86rf231_switch_to_rx(); #endif default: break; } }
static void write_register(uint8_t r, uint8_t value) { /* Save old radio state */ uint8_t old_state = radio_state; /* Wake up from WOR/RX (if in WOR/RX, else no effect) */ cc110x_wakeup_from_rx(); cc110x_write_reg(r, value); /* Have to put radio back to WOR/RX if old radio state * was WOR/RX, otherwise no action is necessary */ if((old_state == RADIO_WOR) || (old_state == RADIO_RX)) { cc110x_switch_to_rx(); } }
static void finish(void) { // back to idle cc110x_strobe(RF_SIDLE); radio_state = RADIO_IDLE; restore_conf(); /* Have to put radio back to WOR/RX if old radio state * was WOR/RX, otherwise no action is necessary */ if ((old_radio_state == RADIO_WOR) || (old_radio_state == RADIO_RX)) { cc110x_switch_to_rx(); } radio_release(); // restoreIRQ(cpsr); }
void cc110x_rx_handler(void) { uint8_t res = 0; // Possible packet received, RX -> IDLE (0.1 us) rflags.CAA = 0; rflags.MAN_WOR = 0; cc110x_statistic.packets_in++; res = receive_packet((uint8_t*)&(cc110x_rx_buffer[rx_buffer_next].packet), sizeof(cc110x_packet_t)); if (res) { // If we are sending a burst, don't accept packets. // Only ACKs are processed (for stopping the burst). // Same if state machine is in TX lock. if (radio_state == RADIO_SEND_BURST || rflags.TX) { cc110x_statistic.packets_in_while_tx++; return; } cc110x_rx_buffer[rx_buffer_next].rssi = rflags._RSSI; cc110x_rx_buffer[rx_buffer_next].lqi = rflags._LQI; cc110x_strobe(CC1100_SFRX); // ...for flushing the RX FIFO // Valid packet. After a wake-up, the radio should be in IDLE. // So put CC1100 to RX for WOR_TIMEOUT (have to manually put // the radio back to sleep/WOR). //cc110x_spi_write_reg(CC1100_MCSM0, 0x08); // Turn off FS-Autocal cc110x_write_reg(CC1100_MCSM2, 0x07); // Configure RX_TIME (until end of packet) cc110x_strobe(CC1100_SRX); hwtimer_wait(IDLE_TO_RX_TIME); radio_state = RADIO_RX; #ifdef DBG_IGNORE if (is_ignored(cc110x_rx_buffer[rx_buffer_next].packet.phy_src)) { LED_RED_TOGGLE; return; } #endif /* notify transceiver thread if any */ if (transceiver_pid) { msg_t m; m.type = (uint16_t) RCV_PKT_CC1100; m.content.value = rx_buffer_next; msg_send_int(&m, transceiver_pid); } /* shift to next buffer element */ if (++rx_buffer_next == RX_BUF_SIZE) { rx_buffer_next = 0; } return; } else { // No ACK received so TOF is unpredictable rflags.TOF = 0; // CRC false or RX buffer full -> clear RX FIFO in both cases cc110x_strobe(CC1100_SIDLE); // Switch to IDLE (should already be)... cc110x_strobe(CC1100_SFRX); // ...for flushing the RX FIFO // If packet interrupted this nodes send call, // don't change anything after this point. if (radio_state == RADIO_AIR_FREE_WAITING) { cc110x_strobe(CC1100_SRX); hwtimer_wait(IDLE_TO_RX_TIME); return; } // If currently sending, exit here (don't go to RX/WOR) if (radio_state == RADIO_SEND_BURST) { cc110x_statistic.packets_in_while_tx++; return; } // No valid packet, so go back to RX/WOR as soon as possible cc110x_switch_to_rx(); } }
char *cc110x_get_marc_state(void) { uint8_t state; /* Save old radio state */ uint8_t old_state = radio_state; /* Read content of status register */ state = cc110x_read_status(CC1100_MARCSTATE) & MARC_STATE; /* Make sure in IDLE state. * Only goes to IDLE if state was RX/WOR */ cc110x_wakeup_from_rx(); /* Have to put radio back to WOR/RX if old radio state * was WOR/RX, otherwise no action is necessary */ if(old_state == RADIO_WOR || old_state == RADIO_RX) { cc110x_switch_to_rx(); } switch(state) { /* Note: it is not possible to read back the SLEEP or XOFF state numbers * because setting CSn low will make the chip enter the IDLE mode from the * SLEEP (0) or XOFF (2) states. */ case 1: return "IDLE"; case 3: case 4: case 5: return "MANCAL"; case 6: case 7: return "FS_WAKEUP"; case 8: case 12: return "CALIBRATE"; case 9: case 10: case 11: return "SETTLING"; case 13: case 14: case 15: return "RX"; case 16: return "TXRX_SETTLING"; case 17: return "RXFIFO_OVERFLOW"; case 18: return "FSTXON"; case 19: case 20: return "TX"; case 21: return "RXTX_SETTLING"; case 22: return "TXFIFO_UNDERFLOW"; default: return "UNKNOWN"; } }
void cc110x_setup_rx_mode(void) { /* Stay in RX mode until end of packet */ cc110x_write_reg(CC1100_MCSM2, 0x07); cc110x_switch_to_rx(); }
void cc110x_rx_handler(void *args) { uint8_t res = 0; /* Possible packet received, RX -> IDLE (0.1 us) */ cc110x_statistic.packets_in++; res = receive_packet((uint8_t *)&(cc110x_rx_buffer[rx_buffer_next].packet), sizeof(cc110x_packet_t)); if (res) { /* If we are sending a burst, don't accept packets. * Only ACKs are processed (for stopping the burst). * Same if state machine is in TX lock. */ if (radio_state == RADIO_SEND_BURST) { cc110x_statistic.packets_in_while_tx++; return; } cc110x_rx_buffer[rx_buffer_next].rssi = rflags._RSSI; cc110x_rx_buffer[rx_buffer_next].lqi = rflags._LQI; cc110x_strobe(CC1100_SFRX); /* ...for flushing the RX FIFO */ /* Valid packet. After a wake-up, the radio should be in IDLE. * So put CC110x to RX for WOR_TIMEOUT (have to manually put * the radio back to sleep/WOR). */ cc110x_write_reg(CC1100_MCSM2, 0x07); /* Configure RX_TIME (until end of packet) */ cc110x_strobe(CC1100_SRX); hwtimer_wait(IDLE_TO_RX_TIME); radio_state = RADIO_RX; #ifdef MODULE_TRANSCEIVER /* notify transceiver thread if any */ if (transceiver_pid != KERNEL_PID_UNDEF) { msg_t m; m.type = (uint16_t) RCV_PKT_CC1100; m.content.value = rx_buffer_next; msg_send_int(&m, transceiver_pid); } #endif #ifdef MODULE_NETDEV_BASE if (cc110x_recv_cb != NULL) { cc110x_packet_t p = cc110x_rx_buffer[rx_buffer_next].packet; cc110x_recv_cb(&cc110x_dev, &p.phy_src, sizeof(uint8_t), &p.address, sizeof(uint8_t), p.data, p.length - CC1100_HEADER_LENGTH); } #endif /* shift to next buffer element */ if (++rx_buffer_next == RX_BUF_SIZE) { rx_buffer_next = 0; } return; } else { /* CRC false or RX buffer full -> clear RX FIFO in both cases */ cc110x_strobe(CC1100_SIDLE); /* Switch to IDLE (should already be)... */ cc110x_strobe(CC1100_SFRX); /* ...for flushing the RX FIFO */ /* If currently sending, exit here (don't go to RX/WOR) */ if (radio_state == RADIO_SEND_BURST) { cc110x_statistic.packets_in_while_tx++; return; } /* No valid packet, so go back to RX/WOR as soon as possible */ cc110x_switch_to_rx(); } }