int16_t at86rf2xx_get_txpower(at86rf2xx_t *dev) { #ifdef MODULE_AT86RF212B uint8_t txpower = at86rf2xx_reg_read(dev, AT86RF2XX_REG__PHY_TX_PWR); DEBUG("txpower value: %x\n", txpower); return _tx_pow_to_dbm_212b(dev->netdev.chan, dev->page, txpower); #else uint8_t txpower = at86rf2xx_reg_read(dev, AT86RF2XX_REG__PHY_TX_PWR) & AT86RF2XX_PHY_TX_PWR_MASK__TX_PWR; return tx_pow_to_dbm[txpower]; #endif }
int8_t at86rf2xx_get_cca_threshold(at86rf2xx_t *dev) { int8_t tmp = at86rf2xx_reg_read(dev, AT86RF2XX_REG__CCA_THRES); tmp &= AT86RF2XX_CCA_THRES_MASK__CCA_ED_THRES; tmp <<= 1; return (RSSI_BASE_VAL + tmp); }
static int _init(netdev2_t *netdev) { at86rf2xx_t *dev = (at86rf2xx_t *)netdev; /* initialise GPIOs */ gpio_init(dev->params.cs_pin, GPIO_OUT); gpio_set(dev->params.cs_pin); gpio_init(dev->params.sleep_pin, GPIO_OUT); gpio_clear(dev->params.sleep_pin); gpio_init(dev->params.reset_pin, GPIO_OUT); gpio_set(dev->params.reset_pin); gpio_init_int(dev->params.int_pin, GPIO_IN, GPIO_RISING, _irq_handler, dev); /* make sure device is not sleeping, so we can query part number */ at86rf2xx_assert_awake(dev); /* test if the SPI is set up correctly and the device is responding */ if (at86rf2xx_reg_read(dev, AT86RF2XX_REG__PART_NUM) != AT86RF2XX_PARTNUM) { DEBUG("[at86rf2xx] error: unable to read correct part number\n"); return -1; } #ifdef MODULE_NETSTATS_L2 memset(&netdev->stats, 0, sizeof(netstats_t)); #endif /* reset device to default values and put it into RX state */ at86rf2xx_reset(dev); return 0; }
uint8_t at86rf2xx_get_csma_max_retries(at86rf2xx_t *dev) { uint8_t tmp; tmp = at86rf2xx_reg_read(dev, AT86RF2XX_REG__XAH_CTRL_0); tmp &= AT86RF2XX_XAH_CTRL_0__MAX_CSMA_RETRIES; tmp >>= 1; return tmp; }
void at86rf2xx_set_max_retries(at86rf2xx_t *dev, uint8_t max) { max = (max > 7) ? 7 : max; uint8_t tmp = at86rf2xx_reg_read(dev, AT86RF2XX_REG__XAH_CTRL_0); tmp &= ~(AT86RF2XX_XAH_CTRL_0__MAX_FRAME_RETRIES); tmp |= (max << 4); at86rf2xx_reg_write(dev, AT86RF2XX_REG__XAH_CTRL_0, tmp); }
uint8_t at86rf2xx_get_status(const at86rf2xx_t *dev) { /* if sleeping immediately return state */ if(dev->state == AT86RF2XX_STATE_SLEEP) return dev->state; return at86rf2xx_reg_read(dev, AT86RF2XX_REG__TRX_STATUS) & AT86RF2XX_TRX_STATUS_MASK__TRX_STATUS; }
static int _recv(netdev2_t *netdev, void *buf, size_t len, void *info) { at86rf2xx_t *dev = (at86rf2xx_t *)netdev; uint8_t phr; size_t pkt_len; /* frame buffer protection will be unlocked as soon as at86rf2xx_fb_stop() * is called*/ at86rf2xx_fb_start(dev); /* get the size of the received packet */ at86rf2xx_fb_read(dev, &phr, 1); /* ignore MSB (refer p.80) and substract length of FCS field */ pkt_len = (phr & 0x7f) - 2; /* just return length when buf == NULL */ if (buf == NULL) { at86rf2xx_fb_stop(dev); return pkt_len; } /* not enough space in buf */ if (pkt_len > len) { at86rf2xx_fb_stop(dev); return -ENOBUFS; } #ifdef MODULE_NETSTATS_L2 netdev->stats.rx_count++; netdev->stats.rx_bytes += pkt_len; #endif /* copy payload */ at86rf2xx_fb_read(dev, (uint8_t *)buf, pkt_len); /* Ignore FCS but advance fb read - we must give a temporary buffer here, * as we are not allowed to issue SPI transfers without any buffer */ uint8_t tmp[2]; at86rf2xx_fb_read(dev, tmp, 2); (void)tmp; if (info != NULL) { netdev2_ieee802154_rx_info_t *radio_info = info; at86rf2xx_fb_read(dev, &(radio_info->lqi), 1); #ifndef MODULE_AT86RF231 at86rf2xx_fb_read(dev, &(radio_info->rssi), 1); at86rf2xx_fb_stop(dev); #else at86rf2xx_fb_stop(dev); radio_info->rssi = at86rf2xx_reg_read(dev, AT86RF2XX_REG__PHY_ED_LEVEL); #endif } else { at86rf2xx_fb_stop(dev); } return pkt_len; }
void at86rf2xx_set_csma_max_retries(at86rf2xx_t *dev, int8_t retries) { retries = (retries > 5) ? 5 : retries; /* valid values: 0-5 */ retries = (retries < 0) ? 7 : retries; /* max < 0 => disable CSMA (set to 7) */ DEBUG("[at86rf2xx] opt: Set CSMA retries to %u\n", retries); uint8_t tmp = at86rf2xx_reg_read(dev, AT86RF2XX_REG__XAH_CTRL_0); tmp &= ~(AT86RF2XX_XAH_CTRL_0__MAX_CSMA_RETRIES); tmp |= (retries << 1); at86rf2xx_reg_write(dev, AT86RF2XX_REG__XAH_CTRL_0, tmp); }
void at86rf2xx_assert_awake(at86rf2xx_t *dev) { if(at86rf2xx_get_status(dev) == AT86RF2XX_STATE_SLEEP) { /* wake up and wait for transition to TRX_OFF */ gpio_clear(dev->sleep_pin); xtimer_usleep(AT86RF2XX_WAKEUP_DELAY); /* update state */ dev->state = at86rf2xx_reg_read(dev, AT86RF2XX_REG__TRX_STATUS) & AT86RF2XX_TRX_STATUS_MASK__TRX_STATUS; } }
bool at86rf2xx_cca(at86rf2xx_t *dev) { uint8_t tmp; uint8_t status; at86rf2xx_assert_awake(dev); /* trigger CCA measurment */ tmp = at86rf2xx_reg_read(dev, AT86RF2XX_REG__PHY_CC_CCA); tmp &= AT86RF2XX_PHY_CC_CCA_MASK__CCA_REQUEST; at86rf2xx_reg_write(dev, AT86RF2XX_REG__PHY_CC_CCA, tmp); /* wait for result to be ready */ do { status = at86rf2xx_reg_read(dev, AT86RF2XX_REG__TRX_STATUS); } while (!(status & AT86RF2XX_TRX_STATUS_MASK__CCA_DONE)); /* return according to measurement */ if (status & AT86RF2XX_TRX_STATUS_MASK__CCA_STATUS) { return true; } else { return false; } }
void at86rf2xx_set_csma_seed(at86rf2xx_t *dev, uint8_t entropy[2]) { if(entropy == NULL) { DEBUG("[at86rf2xx] opt: CSMA seed entropy is nullpointer\n"); return; } DEBUG("[at86rf2xx] opt: Set CSMA seed to 0x%x 0x%x\n", entropy[0], entropy[1]); at86rf2xx_reg_write(dev, AT86RF2XX_REG__CSMA_SEED_0, entropy[0]); uint8_t tmp = at86rf2xx_reg_read(dev, AT86RF2XX_REG__CSMA_SEED_1); tmp &= ~(AT86RF2XX_CSMA_SEED_1__CSMA_SEED_1); tmp |= entropy[1] & AT86RF2XX_CSMA_SEED_1__CSMA_SEED_1; at86rf2xx_reg_write(dev, AT86RF2XX_REG__CSMA_SEED_1, tmp); }
int at86rf2xx_init(at86rf2xx_t *dev, spi_t spi, spi_speed_t spi_speed, gpio_t cs_pin, gpio_t int_pin, gpio_t sleep_pin, gpio_t reset_pin) { dev->driver = &at86rf2xx_driver; /* initialize device descriptor */ dev->spi = spi; dev->cs_pin = cs_pin; dev->int_pin = int_pin; dev->sleep_pin = sleep_pin; dev->reset_pin = reset_pin; dev->idle_state = AT86RF2XX_STATE_TRX_OFF; dev->state = AT86RF2XX_STATE_SLEEP; /* initialise SPI */ spi_init_master(dev->spi, SPI_CONF_FIRST_RISING, spi_speed); /* initialise GPIOs */ gpio_init(dev->cs_pin, GPIO_DIR_OUT, GPIO_NOPULL); gpio_set(dev->cs_pin); gpio_init(dev->sleep_pin, GPIO_DIR_OUT, GPIO_NOPULL); gpio_clear(dev->sleep_pin); gpio_init(dev->reset_pin, GPIO_DIR_OUT, GPIO_NOPULL); gpio_set(dev->reset_pin); gpio_init_int(dev->int_pin, GPIO_NOPULL, GPIO_RISING, _irq_handler, dev); /* make sure device is not sleeping, so we can query part number */ at86rf2xx_assert_awake(dev); /* test if the SPI is set up correctly and the device is responding */ if (at86rf2xx_reg_read(dev, AT86RF2XX_REG__PART_NUM) != AT86RF2XX_PARTNUM) { DEBUG("[at86rf2xx] error: unable to read correct part number\n"); return -1; } /* reset device to default values and put it into RX state */ at86rf2xx_reset(dev); return 0; }
void at86rf2xx_set_state(at86rf2xx_t *dev, uint8_t state) { uint8_t old_state = at86rf2xx_get_status(dev); /* make sure there is no ongoing transmission, or state transition already * in progress */ while (old_state == AT86RF2XX_STATE_BUSY_RX_AACK || old_state == AT86RF2XX_STATE_BUSY_TX_ARET || old_state == AT86RF2XX_STATE_IN_PROGRESS) { old_state = at86rf2xx_get_status(dev); } if (state == old_state) { return; } /* we need to go via PLL_ON if we are moving between RX_AACK_ON <-> TX_ARET_ON */ if ((old_state == AT86RF2XX_STATE_RX_AACK_ON && state == AT86RF2XX_STATE_TX_ARET_ON) || (old_state == AT86RF2XX_STATE_TX_ARET_ON && state == AT86RF2XX_STATE_RX_AACK_ON)) { _set_state(dev, AT86RF2XX_STATE_PLL_ON); } /* check if we need to wake up from sleep mode */ else if (old_state == AT86RF2XX_STATE_SLEEP) { DEBUG("at86rf2xx: waking up from sleep mode\n"); at86rf2xx_assert_awake(dev); } if (state == AT86RF2XX_STATE_SLEEP) { /* First go to TRX_OFF */ at86rf2xx_force_trx_off(dev); /* Discard all IRQ flags, framebuffer is lost anyway */ at86rf2xx_reg_read(dev, AT86RF2XX_REG__IRQ_STATUS); /* Go to SLEEP mode from TRX_OFF */ gpio_set(dev->params.sleep_pin); dev->state = state; } else { _set_state(dev, state); } }
static void _isr(netdev2_t *netdev) { at86rf2xx_t *dev = (at86rf2xx_t *) netdev; uint8_t irq_mask; uint8_t state; uint8_t trac_status; /* If transceiver is sleeping register access is impossible and frames are * lost anyway, so return immediately. */ state = at86rf2xx_get_status(dev); if (state == AT86RF2XX_STATE_SLEEP) { return; } /* read (consume) device status */ irq_mask = at86rf2xx_reg_read(dev, AT86RF2XX_REG__IRQ_STATUS); trac_status = at86rf2xx_reg_read(dev, AT86RF2XX_REG__TRX_STATE) & AT86RF2XX_TRX_STATE_MASK__TRAC; if (irq_mask & AT86RF2XX_IRQ_STATUS_MASK__RX_START) { netdev->event_callback(netdev, NETDEV2_EVENT_RX_STARTED, NULL); DEBUG("[at86rf2xx] EVT - RX_START\n"); } if (irq_mask & AT86RF2XX_IRQ_STATUS_MASK__TRX_END) { if (state == AT86RF2XX_STATE_RX_AACK_ON || state == AT86RF2XX_STATE_BUSY_RX_AACK) { DEBUG("[at86rf2xx] EVT - RX_END\n"); if (!(dev->netdev.flags & AT86RF2XX_OPT_TELL_RX_END)) { return; } netdev->event_callback(netdev, NETDEV2_EVENT_RX_COMPLETE, NULL); } else if (state == AT86RF2XX_STATE_TX_ARET_ON || state == AT86RF2XX_STATE_BUSY_TX_ARET) { /* check for more pending TX calls and return to idle state if * there are none */ assert(dev->pending_tx != 0); if ((--dev->pending_tx) == 0) { at86rf2xx_set_state(dev, dev->idle_state); DEBUG("[at86rf2xx] return to state 0x%x\n", dev->idle_state); } DEBUG("[at86rf2xx] EVT - TX_END\n"); if (netdev->event_callback && (dev->netdev.flags & AT86RF2XX_OPT_TELL_TX_END)) { switch (trac_status) { case AT86RF2XX_TRX_STATE__TRAC_SUCCESS: case AT86RF2XX_TRX_STATE__TRAC_SUCCESS_DATA_PENDING: netdev->event_callback(netdev, NETDEV2_EVENT_TX_COMPLETE, NULL); DEBUG("[at86rf2xx] TX SUCCESS\n"); break; case AT86RF2XX_TRX_STATE__TRAC_NO_ACK: netdev->event_callback(netdev, NETDEV2_EVENT_TX_NOACK, NULL); DEBUG("[at86rf2xx] TX NO_ACK\n"); break; case AT86RF2XX_TRX_STATE__TRAC_CHANNEL_ACCESS_FAILURE: netdev->event_callback(netdev, NETDEV2_EVENT_TX_MEDIUM_BUSY, NULL); DEBUG("[at86rf2xx] TX_CHANNEL_ACCESS_FAILURE\n"); break; default: DEBUG("[at86rf2xx] Unhandled TRAC_STATUS: %d\n", trac_status >> 5); } } } }
void at86rf2xx_set_option(at86rf2xx_t *dev, uint16_t option, bool state) { uint8_t tmp; DEBUG("set option %i to %i\n", option, state); /* set option field */ if (state) { dev->netdev.flags |= option; /* trigger option specific actions */ switch (option) { case AT86RF2XX_OPT_CSMA: DEBUG("[at86rf2xx] opt: enabling CSMA mode" \ "(4 retries, min BE: 3 max BE: 5)\n"); /* Initialize CSMA seed with hardware address */ at86rf2xx_set_csma_seed(dev, dev->netdev.long_addr); at86rf2xx_set_csma_max_retries(dev, 4); at86rf2xx_set_csma_backoff_exp(dev, 3, 5); break; case AT86RF2XX_OPT_PROMISCUOUS: DEBUG("[at86rf2xx] opt: enabling PROMISCUOUS mode\n"); /* disable auto ACKs in promiscuous mode */ tmp = at86rf2xx_reg_read(dev, AT86RF2XX_REG__CSMA_SEED_1); tmp |= AT86RF2XX_CSMA_SEED_1__AACK_DIS_ACK; at86rf2xx_reg_write(dev, AT86RF2XX_REG__CSMA_SEED_1, tmp); /* enable promiscuous mode */ tmp = at86rf2xx_reg_read(dev, AT86RF2XX_REG__XAH_CTRL_1); tmp |= AT86RF2XX_XAH_CTRL_1__AACK_PROM_MODE; at86rf2xx_reg_write(dev, AT86RF2XX_REG__XAH_CTRL_1, tmp); break; case AT86RF2XX_OPT_AUTOACK: DEBUG("[at86rf2xx] opt: enabling auto ACKs\n"); tmp = at86rf2xx_reg_read(dev, AT86RF2XX_REG__CSMA_SEED_1); tmp &= ~(AT86RF2XX_CSMA_SEED_1__AACK_DIS_ACK); at86rf2xx_reg_write(dev, AT86RF2XX_REG__CSMA_SEED_1, tmp); break; case AT86RF2XX_OPT_TELL_RX_START: DEBUG("[at86rf2xx] opt: enabling SFD IRQ\n"); tmp = at86rf2xx_reg_read(dev, AT86RF2XX_REG__IRQ_MASK); tmp |= AT86RF2XX_IRQ_STATUS_MASK__RX_START; at86rf2xx_reg_write(dev, AT86RF2XX_REG__IRQ_MASK, tmp); break; default: /* do nothing */ break; } } else { dev->netdev.flags &= ~(option); /* trigger option specific actions */ switch (option) { case AT86RF2XX_OPT_CSMA: DEBUG("[at86rf2xx] opt: disabling CSMA mode\n"); /* setting retries to -1 means CSMA disabled */ at86rf2xx_set_csma_max_retries(dev, -1); break; case AT86RF2XX_OPT_PROMISCUOUS: DEBUG("[at86rf2xx] opt: disabling PROMISCUOUS mode\n"); /* disable promiscuous mode */ tmp = at86rf2xx_reg_read(dev, AT86RF2XX_REG__XAH_CTRL_1); tmp &= ~(AT86RF2XX_XAH_CTRL_1__AACK_PROM_MODE); at86rf2xx_reg_write(dev, AT86RF2XX_REG__XAH_CTRL_1, tmp); /* re-enable AUTOACK only if the option is set */ if (dev->netdev.flags & AT86RF2XX_OPT_AUTOACK) { tmp = at86rf2xx_reg_read(dev, AT86RF2XX_REG__CSMA_SEED_1); tmp &= ~(AT86RF2XX_CSMA_SEED_1__AACK_DIS_ACK); at86rf2xx_reg_write(dev, AT86RF2XX_REG__CSMA_SEED_1, tmp); } break; case AT86RF2XX_OPT_AUTOACK: DEBUG("[at86rf2xx] opt: disabling auto ACKs\n"); tmp = at86rf2xx_reg_read(dev, AT86RF2XX_REG__CSMA_SEED_1); tmp |= AT86RF2XX_CSMA_SEED_1__AACK_DIS_ACK; at86rf2xx_reg_write(dev, AT86RF2XX_REG__CSMA_SEED_1, tmp); break; case AT86RF2XX_OPT_TELL_RX_START: DEBUG("[at86rf2xx] opt: disabling SFD IRQ\n"); tmp = at86rf2xx_reg_read(dev, AT86RF2XX_REG__IRQ_MASK); tmp &= ~AT86RF2XX_IRQ_STATUS_MASK__RX_START; at86rf2xx_reg_write(dev, AT86RF2XX_REG__IRQ_MASK, tmp); break; default: /* do nothing */ break; } } }
void at86rf2xx_configure_phy(at86rf2xx_t *dev) { /* make sure device is not sleeping */ at86rf2xx_assert_awake(dev); uint8_t state; /* make sure ongoing transmissions are finished */ do { state = at86rf2xx_get_status(dev); } while ((state == AT86RF2XX_STATE_BUSY_TX_ARET) || (state == AT86RF2XX_STATE_BUSY_RX_AACK)); /* we must be in TRX_OFF before changing the PHY configuration */ at86rf2xx_force_trx_off(dev); #ifdef MODULE_AT86RF212B /* The TX power register must be updated after changing the channel if * moving between bands. */ int16_t txpower = at86rf2xx_get_txpower(dev); uint8_t trx_ctrl2 = at86rf2xx_reg_read(dev, AT86RF2XX_REG__TRX_CTRL_2); uint8_t rf_ctrl0 = at86rf2xx_reg_read(dev, AT86RF2XX_REG__RF_CTRL_0); /* Clear previous configuration for PHY mode */ trx_ctrl2 &= ~(AT86RF2XX_TRX_CTRL_2_MASK__FREQ_MODE); /* Clear previous configuration for GC_TX_OFFS */ rf_ctrl0 &= ~AT86RF2XX_RF_CTRL_0_MASK__GC_TX_OFFS; if (dev->netdev.chan != 0) { /* Set sub mode bit on 915 MHz as recommended by the data sheet */ trx_ctrl2 |= AT86RF2XX_TRX_CTRL_2_MASK__SUB_MODE; } if (dev->page == 0) { /* BPSK coding */ /* Data sheet recommends using a +2 dB setting for BPSK */ rf_ctrl0 |= AT86RF2XX_RF_CTRL_0_GC_TX_OFFS__2DB; } else if (dev->page == 2) { /* O-QPSK coding */ trx_ctrl2 |= AT86RF2XX_TRX_CTRL_2_MASK__BPSK_OQPSK; /* Data sheet recommends using a +1 dB setting for O-QPSK */ rf_ctrl0 |= AT86RF2XX_RF_CTRL_0_GC_TX_OFFS__1DB; } at86rf2xx_reg_write(dev, AT86RF2XX_REG__TRX_CTRL_2, trx_ctrl2); at86rf2xx_reg_write(dev, AT86RF2XX_REG__RF_CTRL_0, rf_ctrl0); #endif uint8_t phy_cc_cca = at86rf2xx_reg_read(dev, AT86RF2XX_REG__PHY_CC_CCA); /* Clear previous configuration for channel number */ phy_cc_cca &= ~(AT86RF2XX_PHY_CC_CCA_MASK__CHANNEL); /* Update the channel register */ phy_cc_cca |= (dev->netdev.chan & AT86RF2XX_PHY_CC_CCA_MASK__CHANNEL); at86rf2xx_reg_write(dev, AT86RF2XX_REG__PHY_CC_CCA, phy_cc_cca); #ifdef MODULE_AT86RF212B /* Update the TX power register to achieve the same power (in dBm) */ at86rf2xx_set_txpower(dev, txpower); #endif /* Return to the state we had before reconfiguring */ at86rf2xx_set_state(dev, state); }
uint8_t at86rf2xx_get_status(const at86rf2xx_t *dev) { return (at86rf2xx_reg_read(dev, AT86RF2XX_REG__TRX_STATUS) & AT86RF2XX_TRX_STATUS_MASK__TRX_STATUS); }
void at86rf2xx_reset(at86rf2xx_t *dev) { #if CPUID_LEN uint8_t cpuid[CPUID_LEN]; eui64_t addr_long; #endif at86rf2xx_hardware_reset(dev); /* Reset state machine to ensure a known state */ at86rf2xx_reset_state_machine(dev); /* reset options and sequence number */ dev->seq_nr = 0; dev->options = 0; /* set short and long address */ #if CPUID_LEN cpuid_get(cpuid); #if CPUID_LEN < 8 /* in case CPUID_LEN < 8, fill missing bytes with zeros */ for (int i = CPUID_LEN; i < 8; i++) { cpuid[i] = 0; } #else for (int i = 8; i < CPUID_LEN; i++) { cpuid[i & 0x07] ^= cpuid[i]; } #endif /* make sure we mark the address as non-multicast and not globally unique */ cpuid[0] &= ~(0x01); cpuid[0] |= 0x02; /* copy and set long address */ memcpy(&addr_long, cpuid, 8); at86rf2xx_set_addr_long(dev, NTOHLL(addr_long.uint64.u64)); at86rf2xx_set_addr_short(dev, NTOHS(addr_long.uint16[0].u16)); #else at86rf2xx_set_addr_long(dev, AT86RF2XX_DEFAULT_ADDR_LONG); at86rf2xx_set_addr_short(dev, AT86RF2XX_DEFAULT_ADDR_SHORT); #endif /* set default PAN id */ at86rf2xx_set_pan(dev, AT86RF2XX_DEFAULT_PANID); /* set default channel */ at86rf2xx_set_chan(dev, AT86RF2XX_DEFAULT_CHANNEL); /* set default TX power */ at86rf2xx_set_txpower(dev, AT86RF2XX_DEFAULT_TXPOWER); /* set default options */ at86rf2xx_set_option(dev, AT86RF2XX_OPT_AUTOACK, true); at86rf2xx_set_option(dev, AT86RF2XX_OPT_CSMA, true); at86rf2xx_set_option(dev, AT86RF2XX_OPT_TELL_RX_START, false); at86rf2xx_set_option(dev, AT86RF2XX_OPT_TELL_RX_END, true); /* set default protocol */ #ifdef MODULE_GNRC_SIXLOWPAN dev->proto = GNRC_NETTYPE_SIXLOWPAN; #else dev->proto = GNRC_NETTYPE_UNDEF; #endif /* enable safe mode (protect RX FIFO until reading data starts) */ at86rf2xx_reg_write(dev, AT86RF2XX_REG__TRX_CTRL_2, AT86RF2XX_TRX_CTRL_2_MASK__RX_SAFE_MODE); #ifdef MODULE_AT86RF212B at86rf2xx_set_page(dev, 0); #endif /* don't populate masked interrupt flags to IRQ_STATUS register */ uint8_t tmp = at86rf2xx_reg_read(dev, AT86RF2XX_REG__TRX_CTRL_1); tmp &= ~(AT86RF2XX_TRX_CTRL_1_MASK__IRQ_MASK_MODE); at86rf2xx_reg_write(dev, AT86RF2XX_REG__TRX_CTRL_1, tmp); /* disable clock output to save power */ tmp = at86rf2xx_reg_read(dev, AT86RF2XX_REG__TRX_CTRL_0); tmp &= ~(AT86RF2XX_TRX_CTRL_0_MASK__CLKM_CTRL); tmp &= ~(AT86RF2XX_TRX_CTRL_0_MASK__CLKM_SHA_SEL); tmp |= (AT86RF2XX_TRX_CTRL_0_CLKM_CTRL__OFF); at86rf2xx_reg_write(dev, AT86RF2XX_REG__TRX_CTRL_0, tmp); /* enable interrupts */ at86rf2xx_reg_write(dev, AT86RF2XX_REG__IRQ_MASK, AT86RF2XX_IRQ_STATUS_MASK__TRX_END); /* clear interrupt flags */ at86rf2xx_reg_read(dev, AT86RF2XX_REG__IRQ_STATUS); /* go into RX state */ at86rf2xx_set_state(dev, AT86RF2XX_STATE_RX_AACK_ON); DEBUG("at86rf2xx_reset(): reset complete.\n"); }
void at86rf2xx_reset(at86rf2xx_t *dev) { eui64_t addr_long; at86rf2xx_hardware_reset(dev); /* Reset state machine to ensure a known state */ at86rf2xx_reset_state_machine(dev); /* reset options and sequence number */ dev->netdev.seq = 0; dev->netdev.flags = 0; /* get an 8-byte unique ID to use as hardware address */ luid_get(addr_long.uint8, IEEE802154_LONG_ADDRESS_LEN); /* make sure we mark the address as non-multicast and not globally unique */ addr_long.uint8[0] &= ~(0x01); addr_long.uint8[0] |= (0x02); /* set short and long address */ at86rf2xx_set_addr_long(dev, NTOHLL(addr_long.uint64.u64)); at86rf2xx_set_addr_short(dev, NTOHS(addr_long.uint16[0].u16)); /* set default PAN id */ at86rf2xx_set_pan(dev, AT86RF2XX_DEFAULT_PANID); /* set default channel */ at86rf2xx_set_chan(dev, AT86RF2XX_DEFAULT_CHANNEL); /* set default TX power */ at86rf2xx_set_txpower(dev, AT86RF2XX_DEFAULT_TXPOWER); /* set default options */ at86rf2xx_set_option(dev, AT86RF2XX_OPT_AUTOACK, true); at86rf2xx_set_option(dev, AT86RF2XX_OPT_CSMA, true); at86rf2xx_set_option(dev, AT86RF2XX_OPT_TELL_RX_START, false); at86rf2xx_set_option(dev, AT86RF2XX_OPT_TELL_RX_END, true); #ifdef MODULE_NETSTATS_L2 at86rf2xx_set_option(dev, AT86RF2XX_OPT_TELL_TX_END, true); #endif /* set default protocol */ #ifdef MODULE_GNRC_SIXLOWPAN dev->netdev.proto = GNRC_NETTYPE_SIXLOWPAN; #elif MODULE_GNRC dev->netdev.proto = GNRC_NETTYPE_UNDEF; #endif /* enable safe mode (protect RX FIFO until reading data starts) */ at86rf2xx_reg_write(dev, AT86RF2XX_REG__TRX_CTRL_2, AT86RF2XX_TRX_CTRL_2_MASK__RX_SAFE_MODE); #ifdef MODULE_AT86RF212B at86rf2xx_set_page(dev, 0); #endif /* don't populate masked interrupt flags to IRQ_STATUS register */ uint8_t tmp = at86rf2xx_reg_read(dev, AT86RF2XX_REG__TRX_CTRL_1); tmp &= ~(AT86RF2XX_TRX_CTRL_1_MASK__IRQ_MASK_MODE); at86rf2xx_reg_write(dev, AT86RF2XX_REG__TRX_CTRL_1, tmp); /* disable clock output to save power */ tmp = at86rf2xx_reg_read(dev, AT86RF2XX_REG__TRX_CTRL_0); tmp &= ~(AT86RF2XX_TRX_CTRL_0_MASK__CLKM_CTRL); tmp &= ~(AT86RF2XX_TRX_CTRL_0_MASK__CLKM_SHA_SEL); tmp |= (AT86RF2XX_TRX_CTRL_0_CLKM_CTRL__OFF); at86rf2xx_reg_write(dev, AT86RF2XX_REG__TRX_CTRL_0, tmp); /* enable interrupts */ at86rf2xx_reg_write(dev, AT86RF2XX_REG__IRQ_MASK, AT86RF2XX_IRQ_STATUS_MASK__TRX_END); /* clear interrupt flags */ at86rf2xx_reg_read(dev, AT86RF2XX_REG__IRQ_STATUS); /* go into RX state */ at86rf2xx_set_state(dev, AT86RF2XX_STATE_RX_AACK_ON); DEBUG("at86rf2xx_reset(): reset complete.\n"); }