error_t chb_reset() { CHB_RST_DISABLE(); CHB_SLPTR_DISABLE(); // wait a bit while transceiver wakes up chb_delay_us(TIME_P_ON_TO_CLKM_AVAIL); // reset the device CHB_RST_ENABLE(); chb_delay_us(TIME_RST_PULSE_WIDTH); CHB_RST_DISABLE(); // check that we have the part number that we're expecting // if you're stuck here, that means that you're not reading // the version and part number register correctly. possible that version number // changes. if so, update version num in header file if ((chb_reg_read(VERSION_NUM) == CHB_AT86RF212_VER_NUM) && (chb_reg_read(PART_NUM) == CHB_AT86RF212_PART_NUM)) { return ERROR_NONE; } else { return ERROR_DEVICENOTINITIALISED; } }
void chb_reset() { CHB_RST_DISABLE(); CHB_SLPTR_DISABLE(); // wait a bit while transceiver wakes up chb_delay_us(TIME_P_ON_TO_CLKM_AVAIL); // reset the device CHB_RST_ENABLE(); chb_delay_us(TIME_RST_PULSE_WIDTH); CHB_RST_DISABLE(); // check that we have the part number that we're expecting while (1) { // if you're stuck in this loop, that means that you're not reading // the version and part number register correctly. possible that version number // changes. if so, update version num in header file if ((chb_reg_read(VERSION_NUM) == CHB_AT86RF212_VER_NUM) && (chb_reg_read(PART_NUM) == CHB_AT86RF212_PART_NUM)) { break; } } }
U8 chb_get_rand() { if (radio_id == CHB_AT86RF230) { // part ID AT86RF230 does not support true random number generation char buf[50]; // nothing to be done here. print warning & return. strcpy_P(buf, chb_err_not_supported); Serial.print(buf); return 0; } else if ((radio_id == CHB_AT86RF212) || (radio_id == CHB_AT86RF231)) { U8 i, rnd, tmp; rnd = tmp = 0; for (i=0; i<4; i++) { tmp = chb_reg_read(PHY_RSSI); tmp >>= 5; tmp &= 0x03; rnd |= tmp << (i*2); chb_delay_us(5); } return rnd; }
void chb_sleep(U8 enb) { if (enb) { // first we need to go to TRX OFF state chb_set_state(TRX_OFF); // then we need to make SLP_TR pin an input. this enables the external // pullup on that pin. we do this so that we won't need to go through // a voltage divider which drains current. we want to avoid that when // we sleep CHB_SLPTR_DDIR &= ~(_BV(CHB_SLPTR_PIN)); } else { // make sure the SLPTR pin is low first CHB_SLPTR_PORT &= ~(_BV(CHB_SLPTR_PIN)); // make the SLPTR pin an output CHB_SLPTR_DDIR |= _BV(CHB_SLPTR_PIN); // we need to allow some time for the PLL to lock chb_delay_us(TIME_SLEEP_TO_TRX_OFF); // Turn the transceiver back on chb_set_state(RX_STATE); } }
U8 chb_set_channel(U8 channel) { U8 state; chb_reg_read_mod_write(PHY_CC_CCA, channel, 0x1f); // add a delay to allow the PLL to lock if in active mode. state = chb_get_state(); if ((state == RX_ON) || (state == PLL_ON)) { chb_delay_us(TIME_PLL_LOCK); } return ((chb_reg_read(PHY_CC_CCA) & 0x1f) == channel) ? RADIO_SUCCESS : RADIO_TIMED_OUT; }
void chb_sleep(U8 enb) { if (enb) { // first we need to go to TRX OFF state chb_set_state(TRX_OFF); // set the SLPTR pin CHB_SLPTR_ENABLE(); } else { // make sure the SLPTR pin is low first CHB_SLPTR_DISABLE(); // we need to allow some time for the PLL to lock chb_delay_us(TIME_SLEEP_TO_TRX_OFF); // Turn the transceiver back on chb_set_state(RX_STATE); } }
U8 chb_set_state(U8 state) { U8 curr_state, delay; // if we're sleeping then don't allow transition if (gpioGetValue(CHB_SLPTRPORT, CHB_SLPTRPIN)) { return RADIO_WRONG_STATE; } // if we're in a transition state, wait for the state to become stable curr_state = chb_get_state(); if ((curr_state == BUSY_TX_ARET) || (curr_state == BUSY_RX_AACK) || (curr_state == BUSY_RX) || (curr_state == BUSY_TX)) { while (chb_get_state() == curr_state); } // At this point it is clear that the requested new_state is: // TRX_OFF, RX_ON, PLL_ON, RX_AACK_ON or TX_ARET_ON. // we need to handle some special cases before we transition to the new state switch (state) { case TRX_OFF: /* Go to TRX_OFF from any state. */ CHB_SLPTR_DISABLE(); chb_reg_read_mod_write(TRX_STATE, CMD_FORCE_TRX_OFF, 0x1f); chb_delay_us(TIME_ALL_STATES_TRX_OFF); break; case TX_ARET_ON: if (curr_state == RX_AACK_ON) { /* First do intermediate state transition to PLL_ON, then to TX_ARET_ON. */ chb_reg_read_mod_write(TRX_STATE, CMD_PLL_ON, 0x1f); chb_delay_us(TIME_RX_ON_PLL_ON); } break; case RX_AACK_ON: if (curr_state == TX_ARET_ON) { /* First do intermediate state transition to RX_ON, then to RX_AACK_ON. */ chb_reg_read_mod_write(TRX_STATE, CMD_PLL_ON, 0x1f); chb_delay_us(TIME_RX_ON_PLL_ON); } break; } /* Now we're okay to transition to any new state. */ chb_reg_read_mod_write(TRX_STATE, state, 0x1f); /* When the PLL is active most states can be reached in 1us. However, from */ /* TRX_OFF the PLL needs time to activate. */ delay = (curr_state == TRX_OFF) ? TIME_TRX_OFF_PLL_ON : TIME_RX_ON_PLL_ON; chb_delay_us(delay); if (chb_get_state() == state) { return RADIO_SUCCESS; } return RADIO_TIMED_OUT; }
U8 chb_set_channel(U8 channel) { U8 state; #if (CHB_CHINA == 1) // this if for China only which uses a 780 MHz frequency band if ((chb_reg_read(TRX_CTRL2) & 0x3f) != 0x1c) { chb_reg_read_mod_write(TRX_CTRL2, 0x1c, 0x3f); } if (channel > 3) { channel = 0; } channel = (channel << 1) + 11; chb_reg_read_mod_write(CC_CTRL_1, 0x4, 0x7); // set 769 MHz base frequency for China chb_reg_write(CC_CTRL_0, channel); // set the center frequency for the channel #else //if (channel == 0) //{ // // Channel 0 is for European use only. make sure we are using channel page 2, // // channel 0 settings for 100 kbps // if ((chb_reg_read(TRX_CTRL_2) & 0x3f) != 0x08) // { // chb_reg_read_mod_write(TRX_CTRL_2, 0x08, 0x3f); // } //} //else if (channel > 10) //{ // // if the channel is out of bounds for page 2, then default to channel 1 and // // assume we're on the US frequency of 915 MHz // channel = 1; // if ((chb_reg_read(TRX_CTRL_2) & 0x3f) != 0x0c) // { // chb_reg_read_mod_write(TRX_CTRL_2, 0x0c, 0x3f); // } //} //else //{ // // Channels 1-10 are for US frequencies of 915 MHz // if ((chb_reg_read(TRX_CTRL_2) & 0x3f) != 0x0c) // { // chb_reg_read_mod_write(TRX_CTRL_2, 0x0c, 0x3f); // } //} chb_reg_read_mod_write(PHY_CC_CCA, channel, 0x1f); #endif // add a delay to allow the PLL to lock if in active mode. state = chb_get_state(); if ((state == RX_ON) || (state == PLL_ON)) { chb_delay_us(TIME_PLL_LOCK_TIME); } return ((chb_reg_read(PHY_CC_CCA) & 0x1f) == channel) ? RADIO_SUCCESS : RADIO_TIMED_OUT; }
static void chb_radio_init() { U8 ieee_addr[8]; U8 part_num; // disable intps while we config the radio chb_reg_write(IRQ_MASK, 0); // force transceiver off while we configure the intps chb_reg_read_mod_write(TRX_STATE, CMD_FORCE_TRX_OFF, 0x1F); chb_delay_us(TIME_P_ON_TO_TRX_OFF); // set radio cfg parameters // **note** uncomment if these will be set to something other than default //chb_reg_read_mod_write(XAH_CTRL_0, CHB_MAX_FRAME_RETRIES << CHB_MAX_FRAME_RETRIES_POS, 0xF << CHB_MAX_FRAME_RETRIES_POS); //chb_reg_read_mod_write(XAH_CTRL_0, CHB_MAX_CSMA_RETRIES << CHB_MAX_CSMA_RETIRES_POS, 0x7 << CHB_MAX_CSMA_RETIRES_POS); //chb_reg_read_mod_write(CSMA_SEED_1, CHB_MIN_BE << CHB_MIN_BE_POS, 0x3 << CHB_MIN_BE_POS); //chb_reg_read_mod_write(CSMA_SEED_1, CHB_CSMA_SEED1 << CHB_CSMA_SEED1_POS, 0x7 << CHB_CSMA_SEED1_POS); //chb_ret_write(CSMA_SEED0, CHB_CSMA_SEED0); //chb_reg_read_mod_write(PHY_CC_CCA, CHB_CCA_MODE << CHB_CCA_MODE_POS,0x3 << CHB_CCA_MODE_POS); //chb_reg_write(CCA_THRES, CHB_CCA_ED_THRES); //chb_reg_read_mod_write(PHY_TX_PWR, CHB_TX_PWR, 0xf); // identify device part_num = chb_reg_read(PART_NUM); switch (part_num) { case CHB_AT86RF230: // set default channel chb_set_channel(CHB_2_4GHZ_DEFAULT_CHANNEL); #if (CHIBI_PROMISCUOUS == 0) // set autocrc mode chb_reg_read_mod_write(PHY_TX_PWR, 1 << CHB_AUTO_CRC_POS, 1 << CHB_AUTO_CRC_POS); #endif break; case CHB_AT86RF231: // set default channel chb_set_channel(CHB_2_4GHZ_DEFAULT_CHANNEL); #if (CHIBI_PROMISCUOUS == 0) // set autocrc mode chb_reg_read_mod_write(PHY_TX_PWR, 1 << CHB_AUTO_CRC_POS, 1 << CHB_AUTO_CRC_POS); #endif break; case CHB_AT86RF212: // set mode to OQPSK or BPSK depending on setting chb_set_mode(CHB_INIT_MODE); // set default channel and tx power to max chb_set_channel(CHB_900MHZ_DEFAULT_CHANNEL); chb_reg_read_mod_write(PHY_TX_PWR, CHB_900MHZ_TX_PWR, 0xf); #if (CHIBI_PROMISCUOUS == 0) // set autocrc mode chb_reg_read_mod_write(TRX_CTRL1, 1 << CHB_AUTO_CRC_POS, 1 << CHB_AUTO_CRC_POS); #endif break; default: Serial.print("ERROR: Unknown radio detected.\n"); break; } // set transceiver's fsm state chb_set_state(RX_STATE); // set pan ID chb_reg_write16(PAN_ID_0, CHB_PAN_ID); // set short addr // NOTE: Possibly get this from EEPROM chb_reg_write16(SHORT_ADDR_0, chb_get_short_addr()); // set long addr // NOTE: Possibly get this from EEPROM chb_get_ieee_addr(ieee_addr); chb_reg_write64(IEEE_ADDR_0, ieee_addr); // do a read of the interrupt register to clear the interrupt bits chb_reg_read(IRQ_STATUS); // re-enable intps while we config the radio chb_reg_write(IRQ_MASK, 0x8); // enable mcu intp pin on INT6 for rising edge CFG_CHB_INTP(); if (chb_get_state() != RX_STATE) { // ERROR occurred initializing the radio. Print out error message. char buf[50]; // grab the error message from flash & print it out strcpy_P(buf, chb_err_init); Serial.print(buf); } }