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;
    }
}
Beispiel #2
0
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;
        }
    }
}
Beispiel #3
0
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;
    }
Beispiel #4
0
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);

    }
}
Beispiel #5
0
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);
  }
}
Beispiel #7
0
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;
}
Beispiel #8
0
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;
}
Beispiel #9
0
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);
    }
}