static int _get(netdev2_t *netdev, netopt_t opt, void *val, size_t max_len) { at86rf2xx_t *dev = (at86rf2xx_t *) netdev; if (netdev == NULL) { return -ENODEV; } /* getting these options doesn't require the transceiver to be responsive */ switch (opt) { case NETOPT_CHANNEL_PAGE: if (max_len < sizeof(uint16_t)) { return -EOVERFLOW; } ((uint8_t *)val)[1] = 0; ((uint8_t *)val)[0] = at86rf2xx_get_page(dev); return sizeof(uint16_t); case NETOPT_MAX_PACKET_SIZE: if (max_len < sizeof(int16_t)) { return -EOVERFLOW; } *((uint16_t *)val) = AT86RF2XX_MAX_PKT_LENGTH - _MAX_MHR_OVERHEAD; return sizeof(uint16_t); case NETOPT_STATE: if (max_len < sizeof(netopt_state_t)) { return -EOVERFLOW; } *((netopt_state_t *)val) = _get_state(dev); return sizeof(netopt_state_t); case NETOPT_PRELOADING: if (dev->netdev.flags & AT86RF2XX_OPT_PRELOADING) { *((netopt_enable_t *)val) = NETOPT_ENABLE; } else { *((netopt_enable_t *)val) = NETOPT_DISABLE; } return sizeof(netopt_enable_t); case NETOPT_PROMISCUOUSMODE: if (dev->netdev.flags & AT86RF2XX_OPT_PROMISCUOUS) { *((netopt_enable_t *)val) = NETOPT_ENABLE; } else { *((netopt_enable_t *)val) = NETOPT_DISABLE; } return sizeof(netopt_enable_t); case NETOPT_RX_START_IRQ: *((netopt_enable_t *)val) = !!(dev->netdev.flags & AT86RF2XX_OPT_TELL_RX_START); return sizeof(netopt_enable_t); case NETOPT_RX_END_IRQ: *((netopt_enable_t *)val) = !!(dev->netdev.flags & AT86RF2XX_OPT_TELL_RX_END); return sizeof(netopt_enable_t); case NETOPT_TX_START_IRQ: *((netopt_enable_t *)val) = !!(dev->netdev.flags & AT86RF2XX_OPT_TELL_TX_START); return sizeof(netopt_enable_t); case NETOPT_TX_END_IRQ: *((netopt_enable_t *)val) = !!(dev->netdev.flags & AT86RF2XX_OPT_TELL_TX_END); return sizeof(netopt_enable_t); case NETOPT_CSMA: *((netopt_enable_t *)val) = !!(dev->netdev.flags & AT86RF2XX_OPT_CSMA); return sizeof(netopt_enable_t); default: /* Can still be handled in second switch */ break; } int res; if (((res = netdev2_ieee802154_get((netdev2_ieee802154_t *)netdev, opt, val, max_len)) >= 0) || (res != -ENOTSUP)) { return res; } uint8_t old_state = at86rf2xx_get_status(dev); res = 0; /* temporarily wake up if sleeping */ if (old_state == AT86RF2XX_STATE_SLEEP) { at86rf2xx_assert_awake(dev); } /* these options require the transceiver to be not sleeping*/ switch (opt) { case NETOPT_TX_POWER: if (max_len < sizeof(int16_t)) { res = -EOVERFLOW; } else { *((uint16_t *)val) = at86rf2xx_get_txpower(dev); res = sizeof(uint16_t); } break; case NETOPT_RETRANS: if (max_len < sizeof(uint8_t)) { res = -EOVERFLOW; } else { *((uint8_t *)val) = at86rf2xx_get_max_retries(dev); res = sizeof(uint8_t); } break; case NETOPT_IS_CHANNEL_CLR: if (at86rf2xx_cca(dev)) { *((netopt_enable_t *)val) = NETOPT_ENABLE; } else { *((netopt_enable_t *)val) = NETOPT_DISABLE; } res = sizeof(netopt_enable_t); break; case NETOPT_CSMA_RETRIES: if (max_len < sizeof(uint8_t)) { res = -EOVERFLOW; } else { *((uint8_t *)val) = at86rf2xx_get_csma_max_retries(dev); res = sizeof(uint8_t); } break; case NETOPT_CCA_THRESHOLD: if (max_len < sizeof(int8_t)) { res = -EOVERFLOW; } else { *((int8_t *)val) = at86rf2xx_get_cca_threshold(dev); res = sizeof(int8_t); } break; default: res = -ENOTSUP; } /* go back to sleep if were sleeping */ if (old_state == AT86RF2XX_STATE_SLEEP) { at86rf2xx_set_state(dev, AT86RF2XX_STATE_SLEEP); } return res; }
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); }