/** * @brief Computes and returns the RCO frequency. * This frequency depends on the xtal frequency and the XTAL bit in register 0x01. * @retval RCO frequency in Hz as an uint16_t. */ uint16_t SpiritTimerGetRcoFrequency(void) { uint16_t rco_freq=34700; uint32_t xtal=SpiritRadioGetXtalFrequency(); if(xtal>30000000) xtal/=2; if(xtal==25000000) { uint8_t xtal_flag; SpiritSpiReadRegisters(0x01, 1, &xtal_flag); xtal_flag=(xtal_flag&0x40); if(xtal_flag==0) { rco_freq=36100; } else { rco_freq=33300; } } return rco_freq; }
/** * @brief Computes the values of the rx_timeout timer counter and prescaler from the user time expressed in millisecond. * The prescaler and the counter values are computed maintaining the prescaler value as * small as possible in order to obtain the best resolution, and in the meantime minimizing the error. * @param fDesiredMsec desired rx_timeout in millisecs. * This parameter must be a float. Since the counter and prescaler are 8 bit registers the maximum * reachable value is maxTime = fTclk x 255 x 255. * @param pcCounter pointer to the variable in which the value for the rx_timeout counter has to be stored. * This parameter must be a uint8_t*. * @param pcPrescaler pointer to the variable in which the value for the rx_timeout prescaler has to be stored. * This parameter must be an uint8_t*. * @retval None */ void SpiritTimerComputeRxTimeoutValues(float fDesiredMsec , uint8_t* pcCounter , uint8_t* pcPrescaler) { uint32_t nXtalFrequency = SpiritRadioGetXtalFrequency(); uint32_t n; float err; /* if xtal is doubled divide it by 2 */ if(nXtalFrequency>DOUBLE_XTAL_THR) { nXtalFrequency >>= 1; }
/** * @brief Returns the RX timeout timer. * @param pfTimeoutMsec pointer to the variable in which the timeout expressed in milliseconds has to be stored. * If the returned value is 0, it means that the RX_Timeout is infinite. * This parameter must be a float*. * @param pcCounter pointer to the variable in which the timer counter has to be stored. * This parameter must be an uint8_t*. * @param pcPrescaler pointer to the variable in which the timer prescaler has to be stored. * This parameter must be an uint8_t*. * @retval None. */ void SpiritTimerGetRxTimeout(float* pfTimeoutMsec, uint8_t* pcCounter , uint8_t* pcPrescaler) { uint8_t tempRegValue[2]; /* Reads the RX timeout registers value */ g_xStatus = SpiritSpiReadRegisters(TIMERS5_RX_TIMEOUT_PRESCALER_BASE, 2, tempRegValue); /* Returns values */ (*pcPrescaler) = tempRegValue[0]; (*pcCounter) = tempRegValue[1]; float nXtalFrequency = (float)SpiritRadioGetXtalFrequency(); if(nXtalFrequency>DOUBLE_XTAL_THR) { nXtalFrequency /= 2.0f; /* #1035-D */ } nXtalFrequency /= 1000.0f; /* #1035-D */ *pfTimeoutMsec = (float)((tempRegValue[0]+1)*tempRegValue[1]*(1210.0f/nXtalFrequency)); /* #1035-D */ }
void SpiritManagementWaCmdStrobeTx(void) { if(s_cCommunicationState != COMMUNICATION_STATE_TX) { uint32_t xtal_frequency = SpiritRadioGetXtalFrequency(); /* To achive the max output power */ if(s_nDesiredFrequency>=150000000 && s_nDesiredFrequency<=470000000) { /* Optimal setting for Tx mode only */ SpiritRadioSetPACwc(LOAD_3_6_PF); } else { /* Optimal setting for Tx mode only */ SpiritRadioSetPACwc(LOAD_0_PF); } uint8_t tmp = 0x11; SpiritSpiWriteRegisters(0xa9, 1, &tmp); /* Enable VCO_L buffer */ tmp = 0x20; SpiritSpiWriteRegisters(PM_CONFIG1_BASE, 1, &tmp); /* Set SMPS switching frequency */ s_cCommunicationState = COMMUNICATION_STATE_TX; } }
/** * @brief Private SpiritRadioSetFrequencyBase function only used in SpiritManagementWaVcoCalibration. * @param lFBase the base carrier frequency expressed in Hz as unsigned word. * @retval None. */ void SpiritManagementSetFrequencyBase(uint32_t lFBase) { uint32_t synthWord, Fc; uint8_t band=0, anaRadioRegArray[4], wcp; /* Check the parameter */ s_assert_param(IS_FREQUENCY_BAND(lFBase)); /* Search the operating band */ if(IS_FREQUENCY_BAND_HIGH(lFBase)) { band = HIGH_BAND; } else if(IS_FREQUENCY_BAND_MIDDLE(lFBase)) { band = MIDDLE_BAND; } else if(IS_FREQUENCY_BAND_LOW(lFBase)) { band = LOW_BAND; } else if(IS_FREQUENCY_BAND_VERY_LOW(lFBase)) { band = VERY_LOW_BAND; } int32_t FOffset = SpiritRadioGetFrequencyOffset(); uint32_t lChannelSpace = SpiritRadioGetChannelSpace(); uint8_t cChannelNum = SpiritRadioGetChannel(); /* Calculates the channel center frequency */ Fc = lFBase + FOffset + lChannelSpace*cChannelNum; /* Reads the reference divider */ uint8_t cRefDiv = (uint8_t)SpiritRadioGetRefDiv()+1; switch(band) { case VERY_LOW_BAND: if(Fc<161281250) { SpiritCalibrationSelectVco(VCO_L); } else { SpiritCalibrationSelectVco(VCO_H); } break; case LOW_BAND: if(Fc<322562500) { SpiritCalibrationSelectVco(VCO_L); } else { SpiritCalibrationSelectVco(VCO_H); } break; case MIDDLE_BAND: if(Fc<430083334) { SpiritCalibrationSelectVco(VCO_L); } else { SpiritCalibrationSelectVco(VCO_H); } break; case HIGH_BAND: if(Fc<860166667) { SpiritCalibrationSelectVco(VCO_L); } else { SpiritCalibrationSelectVco(VCO_H); } } /* Search the VCO charge pump word and set the corresponding register */ wcp = SpiritRadioSearchWCP(Fc); synthWord = (uint32_t)(lFBase*(((double)(FBASE_DIVIDER*cRefDiv*s_vectcBHalfFactor[band]))/SpiritRadioGetXtalFrequency())); /* Build the array of registers values for the analog part */ anaRadioRegArray[0] = (uint8_t)(((synthWord>>21)&(0x0000001F))|(wcp<<5)); anaRadioRegArray[1] = (uint8_t)((synthWord>>13)&(0x000000FF)); anaRadioRegArray[2] = (uint8_t)((synthWord>>5)&(0x000000FF)); anaRadioRegArray[3] = (uint8_t)(((synthWord&0x0000001F)<<3)| s_vectcBandRegValue[band]); /* Configures the needed Analog Radio registers */ g_xStatus = SpiritSpiWriteRegisters(SYNT3_BASE, 4, anaRadioRegArray); }
uint8_t SpiritManagementWaVcoCalibration(void) { uint8_t s_cVcoWordRx; uint8_t s_cVcoWordTx; uint32_t nFreq; uint8_t cRestore = 0; uint8_t cStandby = 0; uint32_t xtal_frequency = SpiritRadioGetXtalFrequency(); /* Enable the reference divider if the XTAL is between 48 and 52 MHz */ if(xtal_frequency>26000000) { if(!SpiritRadioGetRefDiv()) { cRestore = 1; nFreq = SpiritRadioGetFrequencyBase(); SpiritRadioSetRefDiv(S_ENABLE); SpiritManagementSetFrequencyBase(nFreq); } } nFreq = SpiritRadioGetFrequencyBase(); /* Increase the VCO current */ uint8_t tmp = 0x19; SpiritSpiWriteRegisters(0xA1,1,&tmp); SpiritCalibrationVco(S_ENABLE); SpiritRefreshStatus(); if(g_xStatus.MC_STATE == MC_STATE_STANDBY) { cStandby = 1; SpiritCmdStrobeReady(); do{ SpiritRefreshStatus(); if(g_xStatus.MC_STATE == 0x13) { return 1; } }while(g_xStatus.MC_STATE != MC_STATE_READY); } SpiritCmdStrobeLockTx(); do{ SpiritRefreshStatus(); if(g_xStatus.MC_STATE == 0x13) { return 1; } }while(g_xStatus.MC_STATE != MC_STATE_LOCK); s_cVcoWordTx = SpiritCalibrationGetVcoCalData(); SpiritCmdStrobeReady(); do{ SpiritRefreshStatus(); }while(g_xStatus.MC_STATE != MC_STATE_READY); SpiritCmdStrobeLockRx(); do{ SpiritRefreshStatus(); if(g_xStatus.MC_STATE == 0x13) { return 1; } }while(g_xStatus.MC_STATE != MC_STATE_LOCK); s_cVcoWordRx = SpiritCalibrationGetVcoCalData(); SpiritCmdStrobeReady(); do{ SpiritRefreshStatus(); if(g_xStatus.MC_STATE == 0x13) { return 1; } }while(g_xStatus.MC_STATE != MC_STATE_READY); if(cStandby == 1) { SpiritCmdStrobeStandby(); } SpiritCalibrationVco(S_DISABLE); /* Disable the reference divider if the XTAL is between 48 and 52 MHz */ if(cRestore) { SpiritRadioSetRefDiv(S_DISABLE); SpiritManagementSetFrequencyBase(nFreq); } /* Restore the VCO current */ tmp = 0x11; SpiritSpiWriteRegisters(0xA1,1,&tmp); SpiritCalibrationSetVcoCalDataTx(s_cVcoWordTx); SpiritCalibrationSetVcoCalDataRx(s_cVcoWordRx); return 0; }