Beispiel #1
0
OT_WEAK void radio_init( ) {
/// Transceiver implementation dependent    
    //vlFILE* fp;
    
    /// Set SPIRIT1-dependent initialization defaults
    //rfctl.flags     = RADIO_FLAG_XOON;
    rfctl.flags     = 0;
    rfctl.nextcal   = 0;
    
    /// Set universal Radio module initialization defaults
    //radio.state     = RADIO_Idle;
    //radio.evtdone   = &otutils_sig2_null;
    
    /// Initialize the bus between SPIRIT1 and MCU, and load defaults.
    /// SPIRIT1 starts-up in Idle (READY), so we set the state and flags
    /// to match that.  Then, init the bus and send RADIO to sleep.
    /// SPIRIT1 can do SPI in Sleep.
    spirit1_init_bus();
    spirit1_load_defaults();
    
    /// Do this workaround (SPIRIT1 Errata DocID023165 R5, section 1.2) to fix
    /// the shutdown current issue for input voltages <= 2.6V.  For input
    /// voltages > 2.6V, it does not hurt anything.
    spirit1_write(RFREG(PM_TEST), 0xCA);
    spirit1_write(RFREG(TEST_SELECT), 0x04);
    spirit1_write(RFREG(TEST_SELECT), 0x00);
    
    /// Done with the radio init
    //spirit1drv_smart_standby();
    radio_sleep();
    
    /// Initialize RM2 elements such as channels, link-params, etc.
    rm2_init();
}
Beispiel #2
0
void spirit1_clockout_off() {
/// This is the reverse of spirit1_clockout_on(), described above.
#if (BOARD_FEATURE_RFXTALOUT)
    spirit1.clkreq = False;
    spirit1_write(RFREG(GPIO3_CONF), RFGPO(GND));
    spirit1_write(RFREG(MCU_CK_CONF), 0);
    spirit1drv_smart_standby();
#endif
}
Beispiel #3
0
/** Special Functions    <BR>
  * ========================================================================<BR>
  * Notably, these two control the clock-out feature of the SPIRIT1, which is 
  * handy if you have a 48MHz crystal and you want to drive an otherwise 
  * crystal-less MCU for USB.
  */
void spirit1_clockout_on(ot_u8 clk_param) {
/// Set the SPIRIT1 to idle, then configure the driver so it never goes into sleep 
/// or standby, and finally configure the SPIRIT1 to output the clock.
#if (BOARD_FEATURE_RFXTALOUT)
    spirit1drv_smart_ready();
    spirit1.clkreq = True;
    spirit1_write(RFREG(MCU_CK_CONF), clk_param);
    spirit1_write(RFREG(GPIO3_CONF), (_GPIO_SELECT(RFGPO_MCU_CLK) | _GPIO_MODE_HIDRIVE));
#endif
}
Beispiel #4
0
void spirit1_wfe_aes() {
    // Kill any interrupts and activate the WFE event source (always pin 2)
    EXTI->IMR  &= (RFI_SOURCE2 | RFI_SOURCE1 | RFI_SOURCE0);
    EXTI->EMR  |= RFI_SOURCE2;

    // read-out all IRQ_STATUS bits to clear
    {   ot_u8 cmd[2];
        cmd[0]  = 1;
        cmd[1]  = RFREG(IRQ_STATUS3);
        spirit1_spibus_io(2, 4, (ot_u8*)cmd);
    }

    // write AES to IRQ MASK
    spirit1_write(0x40, RFREG(IRQ_MASK3));
}
Beispiel #5
0
void spirit1_set_txpwr(ot_u8* pwr_code) {
/// Sets the tx output power.
/// "pwr_code" is a value, 0-127, that is: eirp_code/2 - 40 = TX dBm
/// i.e. eirp_code=0 => -40 dBm, eirp_code=80 => 0 dBm, etc
    static const ot_u8 pa_lut[84] = {
          87, 0x57, 0x56, 0x55, 0x54, 0x53, 0x53, 0x52, 0x52, 0x50,     //-30 to -25.5
        0x4F, 0x4E, 0x4D, 0x4C, 0x4B, 0x4B, 0x4A, 0x49, 0x48, 0x47,     //-25 to -20.5
        0x46, 0x45, 0x44, 0x43, 0x42, 0x41, 0x40, 0x3F, 0x3E, 0x3C,     //-20 to -15.5
        0x3B, 0x3A, 0x39, 0x38, 0x37, 0x36, 0x34, 0x33, 0x32, 0x31,     //-15 to -10.5
        0x30, 0x2F, 0x2D, 0x2C, 0x2B, 0x2A, 0x29, 0x27,   42, 0x25,     //-10 to -5.5
        0x24, 0x23, 0x22, 0x20, 0x1F, 0x1E, 0x1D, 0x1C, 0x1B, 0x19,     //-5 to -0.5
          30, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0F,     // 0 to 4.5
        0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x07, 0x06, 0x05,     // 5 to 9.5
        0x04, 0x03,    1, 0x01                                          // 10 to 11.5
    };

    ot_u8   pa_table[10];
    ot_u8*  cursor;
    ot_int  step;
    ot_int  eirp_val;

    ///@todo autoscaling algorithm, and refresh value in *pwr_code
    // Autoscaling: Try to make RSSI at receiver be -90 < RX_RSSI < -80
    // The simple algorithm uses the last_rssi and last_linkloss values
    //if (*pwr_code & 0x80) {
    //}
    //else {
    //}

    // Not autoscaling: extract TX power directly from pwr_code
    eirp_val = *pwr_code;

    // Offset SPIRIT1 PA CFG to match DASH7 PA CFG, plus antenna losses
    // SPIRIT1: 0 --> -30 dBm, 83 --> 11.5 dBm, half-dBm steps
    // DASH7: 0 --> -40 dBm, 127 --> 23.5 dBm, half-dBm steps
    eirp_val += (-10*2) + (RF_HDB_ATTEN);

    // Adjust base power code in case it is out-of-range:
    // SPIRIT1 PA starts at -30, DASH7 pwr_code starts at -40.
    if (eirp_val < 0)       eirp_val = 0;
    else if (eirp_val > 83) eirp_val = 83;

    // Build PA RAMP using 8 steps of variable size.
    pa_table[0] = 0;
    pa_table[1] = RFREG(PAPOWER8);
    cursor      = &pa_table[2];
    step        = eirp_val >> 3;
    do {
        *cursor++   = pa_lut[eirp_val];
        eirp_val   -= step;
    } while (cursor != &pa_table[9]);


    // Write new PA Table to device
    spirit1_spibus_io(10, 0, pa_table);
}
Beispiel #6
0
OT_WEAK void rm2_enter_channel(ot_u8 old_chan_id, ot_u8 old_tx_eirp) {
    static const ot_u8 dr_matrix[32] = { 
        0, RFREG(MOD1), DRF_MOD1_SS, DRF_MOD0_SS, DRF_FDEV0, DRF_CHFLT_SS, 0, 0, 
        0, RFREG(MOD1), DRF_MOD1_LS, DRF_MOD0_LS, DRF_FDEV0, DRF_CHFLT_LS, 0, 0, 
        0, RFREG(MOD1), DRF_MOD1_HS, DRF_MOD0_HS, DRF_FDEV0, DRF_CHFLT_HS, 0, 0,    /// @todo change HS to MS (mid speed)
        0, RFREG(MOD1), DRF_MOD1_HS, DRF_MOD0_HS, DRF_FDEV0, DRF_CHFLT_HS, 0, 0,
    };    
    ot_u8   fc_i;

    /// Flag PA table reprogram (done before TX): only flag if power is different
    if (old_tx_eirp != phymac[0].tx_eirp) {
        rfctl.flags |= RADIO_FLAG_SETPWR;
    }

    /// Configure data rate: only change registers if required
    if ((old_chan_id ^ phymac[0].channel) & 0x30) {
        ot_u8 offset;
        offset = (phymac[0].channel & 0x30) >> 1;
        spirit1_spibus_io(6, 0, (ot_u8*)&dr_matrix[offset]);
    }
Beispiel #7
0
void sx127x_wfe(ot_u16 ifg_sel) {
    do {
        __WFE();
    }
    while((EXTI->PR & ifg_sel) == 0);

    // clear IRQ value in SX127x by setting IRQFLAGS to 0xFF
    sx127x_write(RFREG(LR_IRQFLAGS), 0xFF);

    // clear pending register(s)
    EXTI->PR = ifg_sel;
}
Beispiel #8
0
void spirit1_wfe() {
    do {
        __WFE();
    }
    while((EXTI->PR & RFI_SOURCE2) == 0);

    // clear pending register
    EXTI->PR = RFI_SOURCE2;

    // clear IRQ value in SPIRIT by setting IRQMASK to 0
    {   ot_u8 cmd[8];
        *(ot_u32*)&cmd[0]   = 0;
        *(ot_u32*)&cmd[4]   = 0;
        cmd[1]              = RFREG(IRQ_MASK3);
        spirit1_burstwrite(6, 0, cmd);
    }
}
Beispiel #9
0
ot_u8   spirit1_rssi()          { return spirit1_read( RFREG(RSSI_LEVEL) ); }
Beispiel #10
0
ot_u8   spirit1_txbytes()       { return spirit1_read( RFREG(LINEAR_FIFO_STATUS1) ); }
Beispiel #11
0
ot_u8   spirit1_rxtime()        { return spirit1_read( RFREG(TIMERS4) ); }
Beispiel #12
0
ot_u8   spirit1_ldcrtime()      { return spirit1_read( RFREG(TIMERS0) ); }
Beispiel #13
0
ot_u16 spirit1_mcstate() {
    static const ot_u8 cmd[2] = { 1, RFREG(MC_STATE1) };
    spirit1_spibus_io(2, 2, (ot_u8*)cmd);
    return (ot_u16)*((ot_u16*)spirit1.busrx);
}
Beispiel #14
0
}

OT_WEAK void spirit1_int_on() {
    ot_u32 ie_sel;
    switch (spirit1.imode) {
        case MODE_Listen:   ie_sel = RFI_LISTEN;
        case MODE_RXData:   ie_sel = RFI_RXDATA;
        case MODE_CSMA:     ie_sel = RFI_CSMA;
        case MODE_TXData:   ie_sel = RFI_TXFIFO;
        default:            ie_sel = 0;
    }
    spirit1_int_config(ie_sel);
}

static const ot_u8 gpio_rx[5] = {
    0, RFREG(GPIO2_CONF),
    RFGPO(RX_FIFO_ALMOST_FULL),  //indicate buffer threshold condition (kept for RX)
    RFGPO(SYNC_WORD),            //indicate when sync word is qualified
    RFGPO(TRX_INDICATOR)             //indicate when RX is active (falling edge)
};

static const ot_u8 gpio_tx[5] = {
    0, RFREG(GPIO2_CONF),
    RFGPO(TX_FIFO_ALMOST_EMPTY), //indicate buffer threshold condition
    RFGPO(RSSI_ABOVE_THR),       //indicate if RSSI goes above/below CCA threshold
    RFGPO(TRX_INDICATOR)         //indicate when TX or RX is active
};

inline void spirit1_iocfg_rx()  {
    spirit1_int_clearall();
    spirit1_spibus_io(5, 0, (ot_u8*)gpio_rx);