센서보드 RF IRQ 테스트 중 and bug fix?
Fork of EV-COG-AD3029LZ by
Diff: source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_Radio.c
- Revision:
- 67:93bec0baf1de
- Parent:
- 34:edda6a7238ec
- Child:
- 83:54b207156a91
--- a/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_Radio.c Wed Jul 05 14:02:16 2017 +0200 +++ b/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_Radio.c Thu Jul 06 11:13:31 2017 +0200 @@ -1,3144 +1,3144 @@ -/** - ****************************************************************************** - * @file SPIRIT_Radio.c - * @author VMA division - AMS - * @version 3.2.2 - * @date 08-July-2015 - * @brief This file provides all the low level API to manage Analog and Digital - * radio part of SPIRIT. - * @details - * - * @attention - * - * <h2><center>© COPYRIGHT(c) 2015 STMicroelectronics</center></h2> - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ - -/* Includes ------------------------------------------------------------------*/ -#include "SPIRIT_Radio.h" -#include "MCU_Interface.h" -#include <math.h> - -/** @addtogroup SPIRIT_Libraries -* @{ -*/ - - -/** @addtogroup SPIRIT_Radio -* @{ -*/ - - -/** @defgroup Radio_Private_TypesDefinitions Radio Private Types Definitions -* @{ -*/ - - -/** -* @} -*/ - - -/** @defgroup Radio_Private_Defines Radio Private Defines -* @{ -*/ - - - - -/** -* @} -*/ - - -/** @defgroup Radio_Private_Macros Radio Private Macros -* @{ -*/ -#define XTAL_FLAG(xtalFrequency) (xtalFrequency>=25e6) ? XTAL_FLAG_26_MHz:XTAL_FLAG_24_MHz - -#define ROUND(A) (((A-(uint32_t)A)> 0.5)? (uint32_t)A+1:(uint32_t)A) -/** -* @} -*/ - - -/** @defgroup Radio_Private_Variables Radio Private Variables -* @{ -*/ -/** -* @brief The Xtal frequency. To be set by the user (see SetXtalFreq() function) -*/ -static uint32_t s_lXtalFrequency; - -/** -* @brief Factor is: B/2 used in the formula for SYNTH word calculation -*/ -static const uint8_t s_vectcBHalfFactor[4]={(HIGH_BAND_FACTOR/2), (MIDDLE_BAND_FACTOR/2), (LOW_BAND_FACTOR/2), (VERY_LOW_BAND_FACTOR/2)}; - -/** -* @brief BS value to write in the SYNT0 register according to the selected band -*/ -static const uint8_t s_vectcBandRegValue[4]={SYNT0_BS_6, SYNT0_BS_12, SYNT0_BS_16, SYNT0_BS_32}; - - -/** -* @brief It represents the available channel bandwidth times 10 for 26 Mhz xtal. -* @note The channel bandwidth for others xtal frequencies can be computed since this table -* multiplying the current table by a factor xtal_frequency/26e6. -*/ -static const uint16_t s_vectnBandwidth26M[90]= -{ - 8001, 7951, 7684, 7368, 7051, 6709, 6423, 5867, 5414, \ - 4509, 4259, 4032, 3808, 3621, 3417, 3254, 2945, 2703, \ - 2247, 2124, 2015, 1900, 1807, 1706, 1624, 1471, 1350, \ - 1123, 1062, 1005, 950, 903, 853, 812, 735, 675, \ - 561, 530, 502, 474, 451, 426, 406, 367, 337, \ - 280, 265, 251, 237, 226, 213, 203, 184, 169, \ - 140, 133, 126, 119, 113, 106, 101, 92, 84, \ - 70, 66, 63, 59, 56, 53, 51, 46, 42, \ - 35, 33, 31, 30, 28, 27, 25, 23, 21, \ - 18, 17, 16, 15, 14, 13, 13, 12, 11 -}; - -/** -* @brief It represents the available VCO frequencies -*/ -static const uint16_t s_vectnVCOFreq[16]= -{ - 4644, 4708, 4772, 4836, 4902, 4966, 5030, 5095, \ - 5161, 5232, 5303, 5375, 5448, 5519, 5592, 5663 -}; - -/** -* @brief This variable is used to enable or disable -* the VCO calibration WA called at the end of the SpiritRadioSetFrequencyBase fcn. -* Default is enabled. -*/ -static SpiritFunctionalState xDoVcoCalibrationWA=S_ENABLE; - - -/** -* @brief These values are used to interpolate the power curves. -* Interpolation curves are linear in the following 3 regions: -* - reg value: 1 to 13 (up region) -* - reg value: 13 to 40 (mid region) -* - reg value: 41 to 90 (low region) -* power_reg = m*power_dBm + q -* For each band the order is: {m-up, q-up, m-mid, q-mid, m-low, q-low}. -* @note The power interpolation curves have been extracted -* by measurements done on the divisional evaluation boards. -*/ -static const float fPowerFactors[5][6]={ - {-2.11,25.66,-2.11,25.66,-2.00,31.28}, /* 915 */ - {-2.04,23.45,-2.04,23.45,-1.95,27.66}, /* 868 */ - {-3.48,38.45,-1.89,27.66,-1.92,30.23}, /* 433 */ - {-3.27,35.43,-1.80,26.31,-1.89,29.61}, /* 315 */ - {-4.18,50.66,-1.80,30.04,-1.86,32.22}, /* 169 */ -}; - -/** -* @} -*/ - - -/** @defgroup Radio_Private_FunctionPrototypes Radio Private Function Prototypes -* @{ -*/ - - -/** -* @} -*/ - - -/** @defgroup Radio_Private_Functions Radio Private Functions -* @{ -*/ - -/** -* @brief Initializes the SPIRIT analog and digital radio part according to the specified -* parameters in the pxSRadioInitStruct. -* @param pxSRadioInitStruct pointer to a SRadioInit structure that -* contains the configuration information for the analog radio part of SPIRIT. -* @retval Error code: 0=no error, 1=error during calibration of VCO. -*/ -uint8_t SpiritRadioInit(SRadioInit* pxSRadioInitStruct) -{ - int32_t FOffsetTmp; - uint8_t anaRadioRegArray[8], digRadioRegArray[4]; - int16_t xtalOffsetFactor; - uint8_t drM, drE, FdevM, FdevE, bwM, bwE; - - /* Workaround for Vtune */ - uint8_t value = 0xA0; SpiritSpiWriteRegisters(0x9F, 1, &value); - - /* Calculates the offset respect to RF frequency and according to xtal_ppm parameter: (xtal_ppm*FBase)/10^6 */ - FOffsetTmp = (int32_t)(((float)pxSRadioInitStruct->nXtalOffsetPpm*pxSRadioInitStruct->lFrequencyBase)/PPM_FACTOR); - - /* Check the parameters */ - s_assert_param(IS_FREQUENCY_BAND(pxSRadioInitStruct->lFrequencyBase)); - s_assert_param(IS_MODULATION_SELECTED(pxSRadioInitStruct->xModulationSelect)); - s_assert_param(IS_DATARATE(pxSRadioInitStruct->lDatarate)); - s_assert_param(IS_FREQUENCY_OFFSET(FOffsetTmp,s_lXtalFrequency)); - s_assert_param(IS_CHANNEL_SPACE(pxSRadioInitStruct->nChannelSpace,s_lXtalFrequency)); - s_assert_param(IS_F_DEV(pxSRadioInitStruct->lFreqDev,s_lXtalFrequency)); - - /* Disable the digital, ADC, SMPS reference clock divider if fXO>24MHz or fXO<26MHz */ - SpiritSpiCommandStrobes(COMMAND_STANDBY); - do{ - /* Delay for state transition */ - for(volatile uint8_t i=0; i!=0xFF; i++); - - /* Reads the MC_STATUS register */ - SpiritRefreshStatus(); - }while(g_xStatus.MC_STATE!=MC_STATE_STANDBY); - - if(s_lXtalFrequency<DOUBLE_XTAL_THR) - { - SpiritRadioSetDigDiv(S_DISABLE); - s_assert_param(IS_CH_BW(pxSRadioInitStruct->lBandwidth,s_lXtalFrequency)); - } - else - { - SpiritRadioSetDigDiv(S_ENABLE); - s_assert_param(IS_CH_BW(pxSRadioInitStruct->lBandwidth,(s_lXtalFrequency>>1))); - } - - /* Goes in READY state */ - SpiritSpiCommandStrobes(COMMAND_READY); - do{ - /* Delay for state transition */ - for(volatile uint8_t i=0; i!=0xFF; i++); - - /* Reads the MC_STATUS register */ - SpiritRefreshStatus(); - }while(g_xStatus.MC_STATE!=MC_STATE_READY); - - /* Calculates the FC_OFFSET parameter and cast as signed int: FOffsetTmp = (Fxtal/2^18)*FC_OFFSET */ - xtalOffsetFactor = (int16_t)(((float)FOffsetTmp*FBASE_DIVIDER)/s_lXtalFrequency); - anaRadioRegArray[2] = (uint8_t)((((uint16_t)xtalOffsetFactor)>>8)&0x0F); - anaRadioRegArray[3] = (uint8_t)(xtalOffsetFactor); - - /* Calculates the channel space factor */ - anaRadioRegArray[0] =((uint32_t)pxSRadioInitStruct->nChannelSpace<<9)/(s_lXtalFrequency>>6)+1; - - SpiritManagementWaTRxFcMem(pxSRadioInitStruct->lFrequencyBase); - - /* 2nd order DEM algorithm enabling */ - uint8_t tmpreg; SpiritSpiReadRegisters(0xA3, 1, &tmpreg); - tmpreg &= ~0x02; SpiritSpiWriteRegisters(0xA3, 1, &tmpreg); - - /* Check the channel center frequency is in one of the possible range */ - s_assert_param(IS_FREQUENCY_BAND((pxSRadioInitStruct->lFrequencyBase + ((xtalOffsetFactor*s_lXtalFrequency)/FBASE_DIVIDER) + pxSRadioInitStruct->nChannelSpace * pxSRadioInitStruct->cChannelNumber))); - - /* Calculates the datarate mantissa and exponent */ - SpiritRadioSearchDatarateME(pxSRadioInitStruct->lDatarate, &drM, &drE); - digRadioRegArray[0] = (uint8_t)(drM); - digRadioRegArray[1] = (uint8_t)(0x00 | pxSRadioInitStruct->xModulationSelect |drE); - - /* Read the fdev register to preserve the clock recovery algo bit */ - SpiritSpiReadRegisters(0x1C, 1, &tmpreg); - - /* Calculates the frequency deviation mantissa and exponent */ - SpiritRadioSearchFreqDevME(pxSRadioInitStruct->lFreqDev, &FdevM, &FdevE); - digRadioRegArray[2] = (uint8_t)((FdevE<<4) | (tmpreg&0x08) | FdevM); - - /* Calculates the channel filter mantissa and exponent */ - SpiritRadioSearchChannelBwME(pxSRadioInitStruct->lBandwidth, &bwM, &bwE); - - digRadioRegArray[3] = (uint8_t)((bwM<<4) | bwE); - - float if_off=(3.0*480140)/(s_lXtalFrequency>>12)-64; - - uint8_t ifOffsetAna = ROUND(if_off); - - if(s_lXtalFrequency<DOUBLE_XTAL_THR) - { - /* if offset digital is the same in case of single xtal */ - anaRadioRegArray[1] = ifOffsetAna; - } - else - { - if_off=(3.0*480140)/(s_lXtalFrequency>>13)-64; - - /* ... otherwise recompute it */ - anaRadioRegArray[1] = ROUND(if_off); - } -// if(s_lXtalFrequency==24000000) { -// ifOffsetAna = 0xB6; -// anaRadioRegArray[1] = 0xB6; -// } -// if(s_lXtalFrequency==25000000) { -// ifOffsetAna = 0xAC; -// anaRadioRegArray[1] = 0xAC; -// } -// if(s_lXtalFrequency==26000000) { -// ifOffsetAna = 0xA3; -// anaRadioRegArray[1] = 0xA3; -// } -// if(s_lXtalFrequency==48000000) { -// ifOffsetAna = 0x3B; -// anaRadioRegArray[1] = 0xB6; -// } -// if(s_lXtalFrequency==50000000) { -// ifOffsetAna = 0x36; -// anaRadioRegArray[1] = 0xAC; -// } -// if(s_lXtalFrequency==52000000) { -// ifOffsetAna = 0x31; -// anaRadioRegArray[1] = 0xA3; -// } - - g_xStatus = SpiritSpiWriteRegisters(IF_OFFSET_ANA_BASE, 1, &ifOffsetAna); - - - /* Sets Xtal configuration */ - if(s_lXtalFrequency>DOUBLE_XTAL_THR) - { - SpiritRadioSetXtalFlag(XTAL_FLAG((s_lXtalFrequency/2))); - } - else - { - SpiritRadioSetXtalFlag(XTAL_FLAG(s_lXtalFrequency)); - } - - /* Sets the channel number in the corresponding register */ - SpiritSpiWriteRegisters(CHNUM_BASE, 1, &pxSRadioInitStruct->cChannelNumber); - - /* Configures the Analog Radio registers */ - SpiritSpiWriteRegisters(CHSPACE_BASE, 4, anaRadioRegArray); - - /* Configures the Digital Radio registers */ - g_xStatus = SpiritSpiWriteRegisters(MOD1_BASE, 4, digRadioRegArray); - - /* Enable the freeze option of the AFC on the SYNC word */ - SpiritRadioAFCFreezeOnSync(S_ENABLE); - - /* Set the IQC correction optimal value */ - anaRadioRegArray[0]=0x80; - anaRadioRegArray[1]=0xE3; - g_xStatus = SpiritSpiWriteRegisters(0x99, 2, anaRadioRegArray); - - return SpiritRadioSetFrequencyBase(pxSRadioInitStruct->lFrequencyBase); - -} - - -/** -* @brief Returns the SPIRIT analog and digital radio structure according to the registers value. -* @param pxSRadioInitStruct pointer to a SRadioInit structure that -* contains the configuration information for the analog radio part of SPIRIT. -* @retval None. -*/ -void SpiritRadioGetInfo(SRadioInit* pxSRadioInitStruct) -{ - uint8_t anaRadioRegArray[8], digRadioRegArray[4]; - BandSelect band; - int16_t xtalOffsetFactor; - - /* Get the RF board version */ - //SpiritVersion xSpiritVersion = SpiritGeneralGetSpiritVersion(); - - /* Reads the Analog Radio registers */ - SpiritSpiReadRegisters(SYNT3_BASE, 8, anaRadioRegArray); - - /* Reads the Digital Radio registers */ - g_xStatus = SpiritSpiReadRegisters(MOD1_BASE, 4, digRadioRegArray); - - /* Reads the operating band masking the Band selected field */ - if((anaRadioRegArray[3] & 0x07) == SYNT0_BS_6) - { - band = HIGH_BAND; - } - else if ((anaRadioRegArray[3] & 0x07) == SYNT0_BS_12) - { - band = MIDDLE_BAND; - } - else if ((anaRadioRegArray[3] & 0x07) == SYNT0_BS_16) - { - band = LOW_BAND; - } - else if ((anaRadioRegArray[3] & 0x07) == SYNT0_BS_32) - { - band = VERY_LOW_BAND; - } - else - { - /* if it is another value, set it to a valid one in order to avoid access violation */ - uint8_t tmp=(anaRadioRegArray[3]&0xF8)|SYNT0_BS_6; - SpiritSpiWriteRegisters(SYNT0_BASE,1,&tmp); - band = HIGH_BAND; - } - - /* Computes the synth word */ - uint32_t synthWord = (uint32_t)((((uint32_t)(anaRadioRegArray[0]&0x1F))<<21)+(((uint32_t)(anaRadioRegArray[1]))<<13)+\ - (((uint32_t)(anaRadioRegArray[2]))<<5)+(((uint32_t)(anaRadioRegArray[3]))>>3)); - - /* Calculates the frequency base */ - uint8_t cRefDiv = (uint8_t)SpiritRadioGetRefDiv()+1; - pxSRadioInitStruct->lFrequencyBase = (uint32_t)round(synthWord*(((double)s_lXtalFrequency)/(FBASE_DIVIDER*cRefDiv*s_vectcBHalfFactor[band]))); - - /* Calculates the Offset Factor */ - uint16_t xtalOffTemp = ((((uint16_t)anaRadioRegArray[6])<<8)+((uint16_t)anaRadioRegArray[7])); - - /* If a negative number then convert the 12 bit 2-complement in a 16 bit number */ - if(xtalOffTemp & 0x0800) - { - xtalOffTemp = xtalOffTemp | 0xF000; - } - else - { - xtalOffTemp = xtalOffTemp & 0x0FFF; - } - - xtalOffsetFactor = *((int16_t*)(&xtalOffTemp)); - - /* Calculates the frequency offset in ppm */ - pxSRadioInitStruct->nXtalOffsetPpm =(int16_t)((uint32_t)xtalOffsetFactor*s_lXtalFrequency*PPM_FACTOR)/((uint32_t)FBASE_DIVIDER*pxSRadioInitStruct->lFrequencyBase); - - /* Channel space */ - pxSRadioInitStruct->nChannelSpace = anaRadioRegArray[4]*(s_lXtalFrequency>>15); - - /* Channel number */ - pxSRadioInitStruct->cChannelNumber = SpiritRadioGetChannel(); - - /* Modulation select */ - pxSRadioInitStruct->xModulationSelect = (ModulationSelect)(digRadioRegArray[1] & 0x70); - - /* Reads the frequency deviation for mantissa and exponent */ - uint8_t FDevM = digRadioRegArray[2]&0x07; - uint8_t FDevE = (digRadioRegArray[2]&0xF0)>>4; - - /* Reads the channel filter register for mantissa and exponent */ - uint8_t bwM = (digRadioRegArray[3]&0xF0)>>4; - uint8_t bwE = digRadioRegArray[3]&0x0F; - - uint8_t cDivider = 0; - cDivider = SpiritRadioGetDigDiv(); - - /* Calculates the datarate */ - pxSRadioInitStruct->lDatarate = ((s_lXtalFrequency>>(5+cDivider))*(256+digRadioRegArray[0]))>>(23-(digRadioRegArray[1]&0x0F)); - - /* Calculates the frequency deviation */ - // (((s_lXtalFrequency>>6)*(8+FDevM))>>(12-FDevE+cCorrection)); - pxSRadioInitStruct->lFreqDev =(uint32_t)((float)s_lXtalFrequency/(((uint32_t)1)<<18)*(uint32_t)((8.0+FDevM)/2*(1<<FDevE))); - - /* Reads the channel filter bandwidth from the look-up table and return it */ - pxSRadioInitStruct->lBandwidth = (uint32_t)(100.0*s_vectnBandwidth26M[bwM+(bwE*9)]*((s_lXtalFrequency>>cDivider)/26e6)); - -} - - -/** -* @brief Sets the Xtal configuration in the ANA_FUNC_CONF0 register. -* @param xXtal one of the possible value of the enum type XtalFrequency. -* @arg XTAL_FLAG_24_MHz: in case of 24 MHz crystal -* @arg XTAL_FLAG_26_MHz: in case of 26 MHz crystal -* @retval None. -*/ -void SpiritRadioSetXtalFlag(XtalFlag xXtal) -{ - uint8_t tempRegValue = 0x00; - - /* Check the parameters */ - s_assert_param(IS_XTAL_FLAG(xXtal)); - - /* Reads the ANA_FUNC_CONF_0 register */ - g_xStatus = SpiritSpiReadRegisters(ANA_FUNC_CONF0_BASE, 1, &tempRegValue); - if(xXtal == XTAL_FLAG_26_MHz) - { - tempRegValue|=SELECT_24_26_MHZ_MASK; - } - else - { - tempRegValue &= (~SELECT_24_26_MHZ_MASK); - } - - /* Sets the 24_26MHz_SELECT field in the ANA_FUNC_CONF_0 register */ - g_xStatus = SpiritSpiWriteRegisters(ANA_FUNC_CONF0_BASE, 1, &tempRegValue); - -} - - -/** -* @brief Returns the Xtal configuration in the ANA_FUNC_CONF0 register. -* @param None. -* @retval XtalFrequency Settled Xtal configuration. -*/ -XtalFlag SpiritRadioGetXtalFlag(void) -{ - uint8_t tempRegValue; - - /* Reads the Xtal configuration in the ANA_FUNC_CONF_0 register and return the value */ - g_xStatus = SpiritSpiReadRegisters(ANA_FUNC_CONF0_BASE, 1, &tempRegValue); - - return (XtalFlag)((tempRegValue & 0x40)>>6); - -} - - -/** -* @brief Returns the charge pump word for a given VCO frequency. -* @param lFc channel center frequency expressed in Hz. -* This parameter can be a value in one of the following ranges:<ul> -* <li> High_Band: from 779 MHz to 915 MHz </li> -* <li> Middle Band: from 387 MHz to 470 MHz </li> -* <li> Low Band: from 300 MHz to 348 MHz </li> -* <li> Very low Band: from 150 MHz to 174 MHz </li> </ul> -* @retval uint8_t Charge pump word. -*/ -uint8_t SpiritRadioSearchWCP(uint32_t lFc) -{ - int8_t i; - uint32_t vcofreq; - uint8_t BFactor; - - /* Check the channel center frequency is in one of the possible range */ - s_assert_param(IS_FREQUENCY_BAND(lFc)); - - /* Search the operating band */ - if(IS_FREQUENCY_BAND_HIGH(lFc)) - { - BFactor = HIGH_BAND_FACTOR; - } - else if(IS_FREQUENCY_BAND_MIDDLE(lFc)) - { - BFactor = MIDDLE_BAND_FACTOR; - } - else if(IS_FREQUENCY_BAND_LOW(lFc)) - { - BFactor = LOW_BAND_FACTOR; - } - else - { - BFactor = VERY_LOW_BAND_FACTOR; - } - - /* Calculates the VCO frequency VCOFreq = lFc*B */ - vcofreq = (lFc/1000000)*BFactor; - - /* Search in the vco frequency array the charge pump word */ - if(vcofreq>=s_vectnVCOFreq[15]) - { - i=15; - } - else - { - /* Search the value */ - for(i=0 ; i<15 && vcofreq>s_vectnVCOFreq[i] ; i++); - - /* Be sure that it is the best approssimation */ - if (i!=0 && s_vectnVCOFreq[i]-vcofreq>vcofreq-s_vectnVCOFreq[i-1]) - i--; - } - - /* Return index */ - return (i%8); - -} - -/** -* @brief Returns the synth word. -* @param None. -* @retval uint32_t Synth word. -*/ -uint32_t SpiritRadioGetSynthWord(void) -{ - uint8_t regArray[4]; - - /* Reads the SYNTH registers, build the synth word and return it */ - g_xStatus = SpiritSpiReadRegisters(SYNT3_BASE, 4, regArray); - return ((((uint32_t)(regArray[0]&0x1F))<<21)+(((uint32_t)(regArray[1]))<<13)+\ - (((uint32_t)(regArray[2]))<<5)+(((uint32_t)(regArray[3]))>>3)); - -} - - -/** -* @brief Sets the SYNTH registers. -* @param lSynthWord the synth word to write in the SYNTH[3:0] registers. -* @retval None. -*/ -void SpiritRadioSetSynthWord(uint32_t lSynthWord) -{ - uint8_t tempArray[4]; - uint8_t tempRegValue; - - /* Reads the SYNT0 register */ - g_xStatus = SpiritSpiReadRegisters(SYNT0_BASE, 1, &tempRegValue); - - /* Mask the Band selected field */ - tempRegValue &= 0x07; - - /* Build the array for SYNTH registers */ - tempArray[0] = (uint8_t)((lSynthWord>>21)&(0x0000001F)); - tempArray[1] = (uint8_t)((lSynthWord>>13)&(0x000000FF)); - tempArray[2] = (uint8_t)((lSynthWord>>5)&(0x000000FF)); - tempArray[3] = (uint8_t)(((lSynthWord&0x0000001F)<<3)| tempRegValue); - - /* Writes the synth word in the SYNTH registers */ - g_xStatus = SpiritSpiWriteRegisters(SYNT3_BASE, 4, tempArray); - -} - - -/** -* @brief Sets the operating band. -* @param xBand the band to set. -* This parameter can be one of following parameters: -* @arg HIGH_BAND High_Band selected: from 779 MHz to 915 MHz -* @arg MIDDLE_BAND: Middle Band selected: from 387 MHz to 470 MHz -* @arg LOW_BAND: Low Band selected: from 300 MHz to 348 MHz -* @arg VERY_LOW_BAND: Very low Band selected: from 150 MHz to 174 MHz -* @retval None. -*/ -void SpiritRadioSetBand(BandSelect xBand) -{ - uint8_t tempRegValue; - - /* Check the parameters */ - s_assert_param(IS_BAND_SELECTED(xBand)); - - /* Reads the SYNT0 register*/ - g_xStatus = SpiritSpiReadRegisters(SYNT0_BASE, 1, &tempRegValue); - - /* Mask the SYNTH[4;0] field and write the BS value */ - tempRegValue &= 0xF8; - tempRegValue |= s_vectcBandRegValue[xBand]; - - /* Configures the SYNT0 register setting the operating band */ - g_xStatus = SpiritSpiWriteRegisters(SYNT0_BASE, 1, &tempRegValue); - -} - - -/** -* @brief Returns the operating band. -* @param None. -* @retval BandSelect Settled band. -* This returned value can be one of the following parameters: -* @arg HIGH_BAND High_Band selected: from 779 MHz to 915 MHz -* @arg MIDDLE_BAND: Middle Band selected: from 387 MHz to 470 MHz -* @arg LOW_BAND: Low Band selected: from 300 MHz to 348 MHz -* @arg VERY_LOW_BAND: Very low Band selected: from 150 MHz to 174 MHz -*/ -BandSelect SpiritRadioGetBand(void) -{ - uint8_t tempRegValue; - - /* Reads the SYNT0 register */ - g_xStatus = SpiritSpiReadRegisters(SYNT0_BASE, 1, &tempRegValue); - - /* Mask the Band selected field */ - if((tempRegValue & 0x07) == SYNT0_BS_6) - { - return HIGH_BAND; - } - else if ((tempRegValue & 0x07) == SYNT0_BS_12) - { - return MIDDLE_BAND; - } - else if ((tempRegValue & 0x07) == SYNT0_BS_16) - { - return LOW_BAND; - } - else - { - return VERY_LOW_BAND; - } - -} - - -/** -* @brief Sets the channel number. -* @param cChannel the channel number. -* @retval None. -*/ -void SpiritRadioSetChannel(uint8_t cChannel) -{ - /* Writes the CHNUM register */ - g_xStatus = SpiritSpiWriteRegisters(CHNUM_BASE, 1, &cChannel); - -} - - -/** -* @brief Returns the actual channel number. -* @param None. -* @retval uint8_t Actual channel number. -*/ -uint8_t SpiritRadioGetChannel(void) -{ - uint8_t tempRegValue; - - /* Reads the CHNUM register and return the value */ - g_xStatus = SpiritSpiReadRegisters(CHNUM_BASE, 1, &tempRegValue); - - return tempRegValue; - -} - - -/** -* @brief Sets the channel space factor in channel space register. -* The channel spacing step is computed as F_Xo/32768. -* @param fChannelSpace the channel space expressed in Hz. -* @retval None. -*/ -void SpiritRadioSetChannelSpace(uint32_t fChannelSpace) -{ - uint8_t cChannelSpaceFactor; - - /* Round to the nearest integer */ - cChannelSpaceFactor = ((uint32_t)fChannelSpace*CHSPACE_DIVIDER)/s_lXtalFrequency; - - /* Write value into the register */ - g_xStatus = SpiritSpiWriteRegisters(CHSPACE_BASE, 1, &cChannelSpaceFactor); - -} - - -/** -* @brief Returns the channel space register. -* @param None. -* @retval uint32_t Channel space. The channel space is: CS = channel_space_factor x XtalFrequency/2^15 -* where channel_space_factor is the CHSPACE register value. -*/ -uint32_t SpiritRadioGetChannelSpace(void) -{ - uint8_t channelSpaceFactor; - - /* Reads the CHSPACE register, calculate the channel space and return it */ - g_xStatus = SpiritSpiReadRegisters(CHSPACE_BASE, 1, &channelSpaceFactor); - - /* Compute the Hertz value and return it */ - return ((channelSpaceFactor*s_lXtalFrequency)/CHSPACE_DIVIDER); - -} - - -/** -* @brief Sets the FC OFFSET register starting from xtal ppm value. -* @param nXtalPpm the xtal offset expressed in ppm. -* @retval None. -*/ -void SpiritRadioSetFrequencyOffsetPpm(int16_t nXtalPpm) -{ - uint8_t tempArray[2]; - int16_t xtalOffsetFactor; - uint32_t synthWord, fBase; - int32_t FOffsetTmp; - BandSelect band; - - /* Reads the synth word */ - synthWord = SpiritRadioGetSynthWord(); - - /* Reads the operating band */ - band = SpiritRadioGetBand(); - - /* Calculates the frequency base */ - uint8_t cRefDiv = (uint8_t)SpiritRadioGetRefDiv()+1; - fBase = synthWord*(s_lXtalFrequency/(s_vectcBHalfFactor[band]*cRefDiv)/FBASE_DIVIDER); - - /* Calculates the offset respect to RF frequency and according to xtal_ppm parameter */ - FOffsetTmp = (int32_t)(((float)nXtalPpm*fBase)/PPM_FACTOR); - - /* Check the Offset is in the correct range */ - s_assert_param(IS_FREQUENCY_OFFSET(FOffsetTmp,s_lXtalFrequency)); - - /* Calculates the FC_OFFSET value to write in the corresponding register */ - xtalOffsetFactor = (int16_t)(((float)FOffsetTmp*FBASE_DIVIDER)/s_lXtalFrequency); - - /* Build the array related to the FC_OFFSET_1 and FC_OFFSET_0 register */ - tempArray[0]=(uint8_t)((((uint16_t)xtalOffsetFactor)>>8)&0x0F); - tempArray[1]=(uint8_t)(xtalOffsetFactor); - - /* Writes the FC_OFFSET registers */ - g_xStatus = SpiritSpiWriteRegisters(FC_OFFSET1_BASE, 2, tempArray); - -} - - -/** -* @brief Sets the FC OFFSET register starting from frequency offset expressed in Hz. -* @param lFOffset frequency offset expressed in Hz as signed word. -* @retval None. -*/ -void SpiritRadioSetFrequencyOffset(int32_t lFOffset) -{ - uint8_t tempArray[2]; - int16_t offset; - - /* Check that the Offset is in the correct range */ - s_assert_param(IS_FREQUENCY_OFFSET(lFOffset,s_lXtalFrequency)); - - /* Calculates the offset value to write in the FC_OFFSET register */ - offset = (int16_t)(((float)lFOffset*FBASE_DIVIDER)/s_lXtalFrequency); - - /* Build the array related to the FC_OFFSET_1 and FC_OFFSET_0 register */ - tempArray[0]=(uint8_t)((((uint16_t)offset)>>8)&0x0F); - tempArray[1]=(uint8_t)(offset); - - /* Writes the FC_OFFSET registers */ - g_xStatus = SpiritSpiWriteRegisters(FC_OFFSET1_BASE, 2, tempArray); - -} - - -/** -* @brief Returns the actual frequency offset. -* @param None. -* @retval int32_t Frequency offset expressed in Hz as signed word. -*/ -int32_t SpiritRadioGetFrequencyOffset(void) -{ - uint8_t tempArray[2]; - int16_t xtalOffsetFactor; - - /* Reads the FC_OFFSET registers */ - g_xStatus = SpiritSpiReadRegisters(FC_OFFSET1_BASE, 2, tempArray); - - /* Calculates the Offset Factor */ - uint16_t xtalOffTemp = ((((uint16_t)tempArray[0])<<8)+((uint16_t)tempArray[1])); - - if(xtalOffTemp & 0x0800) - { - xtalOffTemp = xtalOffTemp | 0xF000; - } - else - { - xtalOffTemp = xtalOffTemp & 0x0FFF; - } - - xtalOffsetFactor = *((int16_t*)(&xtalOffTemp)); - - /* Calculates the frequency offset and return it */ - return ((int32_t)(xtalOffsetFactor*s_lXtalFrequency)/FBASE_DIVIDER); - -} - - - -/** -* @brief Sets the Synth word and the Band Select register according to desired base carrier frequency. -* In this API the Xtal configuration is read out from -* the corresponding register. The user shall fix it before call this API. -* @param lFBase the base carrier frequency expressed in Hz as unsigned word. -* @retval Error code: 0=no error, 1=error during calibration of VCO. -*/ -uint8_t SpiritRadioSetFrequencyBase(uint32_t lFBase) -{ - uint32_t synthWord, Fc; - uint8_t band, 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 - { - 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; - - /* Selects the VCO */ - 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*s_vectcBHalfFactor[band]*(((double)(FBASE_DIVIDER*cRefDiv))/s_lXtalFrequency)); - - /* 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); - - if(xDoVcoCalibrationWA==S_ENABLE) - return SpiritManagementWaVcoCalibration(); - - return 0; -} - -/** -* @brief To say to the set frequency base if do or not the VCO calibration WA. -* @param S_ENABLE or S_DISABLE the WA procedure. -* @retval None. -*/ -void SpiritRadioVcoCalibrationWAFB(SpiritFunctionalState xNewstate) -{ - xDoVcoCalibrationWA=xNewstate; -} - -/** -* @brief Returns the base carrier frequency. -* @param None. -* @retval uint32_t Base carrier frequency expressed in Hz as unsigned word. -*/ -uint32_t SpiritRadioGetFrequencyBase(void) -{ - uint32_t synthWord; - BandSelect band; - - /* Reads the synth word */ - synthWord = SpiritRadioGetSynthWord(); - - /* Reads the operating band */ - band = SpiritRadioGetBand(); - - uint8_t cRefDiv = (uint8_t)SpiritRadioGetRefDiv() + 1; - - /* Calculates the frequency base and return it */ - return (uint32_t)round(synthWord*(((double)s_lXtalFrequency)/(FBASE_DIVIDER*cRefDiv*s_vectcBHalfFactor[band]))); -} - - -/** -* @brief Returns the actual channel center frequency. -* @param None. -* @retval uint32_t Actual channel center frequency expressed in Hz. -*/ -uint32_t SpiritRadioGetCenterFrequency(void) -{ - int32_t offset; - uint8_t channel; - uint32_t fBase; - uint32_t channelSpace; - - /* Reads the frequency base */ - fBase = SpiritRadioGetFrequencyBase(); - - /* Reads the frequency offset */ - offset = SpiritRadioGetFrequencyOffset(); - - /* Reads the channel space */ - channelSpace = SpiritRadioGetChannelSpace(); - - /* Reads the channel number */ - channel = SpiritRadioGetChannel(); - - /* Calculates the channel center frequency and return it */ - return (uint32_t)(fBase + offset + (uint32_t)(channelSpace*channel)); - -} - - -/** -* @brief Returns the mantissa and exponent, whose value used in the datarate formula -* will give the datarate value closer to the given datarate. -* @param fDatarate datarate expressed in bps. This parameter ranging between 100 and 500000. -* @param pcM pointer to the returned mantissa value. -* @param pcE pointer to the returned exponent value. -* @retval None. -*/ -void SpiritRadioSearchDatarateME(uint32_t lDatarate, uint8_t* pcM, uint8_t* pcE) -{ - volatile SpiritBool find = S_FALSE; - int8_t i=15; - uint8_t cMantissaTmp; - uint8_t cDivider = 0; - - /* Check the parameters */ - s_assert_param(IS_DATARATE(lDatarate)); - - cDivider = (uint8_t)SpiritRadioGetDigDiv(); - - /* Search in the datarate array the exponent value */ - while(!find && i>=0) - { - if(lDatarate>=(s_lXtalFrequency>>(20-i+cDivider))) - { - find = S_TRUE; - } - else - { - i--; - } - } - i<0 ? i=0 : i; - *pcE = i; - - /* Calculates the mantissa value according to the datarate formula */ - cMantissaTmp = (lDatarate*((uint32_t)1<<(23-i)))/(s_lXtalFrequency>>(5+cDivider))-256; - - /* Finds the mantissa value with less approximation */ - int16_t mantissaCalculation[3]; - for(uint8_t j=0;j<3;j++) - { - if((cMantissaTmp+j-1)) - { - mantissaCalculation[j]=lDatarate-(((256+cMantissaTmp+j-1)*(s_lXtalFrequency>>(5+cDivider)))>>(23-i)); - } - else - { - mantissaCalculation[j]=0x7FFF; - } - } - uint16_t mantissaCalculationDelta = 0xFFFF; - for(uint8_t j=0;j<3;j++) - { - if(S_ABS(mantissaCalculation[j])<mantissaCalculationDelta) - { - mantissaCalculationDelta = S_ABS(mantissaCalculation[j]); - *pcM = cMantissaTmp+j-1; - } - } - -} - - -/** -* @brief Returns the mantissa and exponent for a given bandwidth. -* Even if it is possible to pass as parameter any value in the below mentioned range, -* the API will search the closer value according to a fixed table of channel -* bandwidth values (@ref s_vectnBandwidth), as defined in the datasheet, returning the corresponding mantissa -* and exponent value. -* @param lBandwidth bandwidth expressed in Hz. This parameter ranging between 1100 and 800100. -* @param pcM pointer to the returned mantissa value. -* @param pcE pointer to the returned exponent value. -* @retval None. -*/ -void SpiritRadioSearchChannelBwME(uint32_t lBandwidth, uint8_t* pcM, uint8_t* pcE) -{ - int8_t i, i_tmp; - uint8_t cDivider = 1; - - /* Search in the channel filter bandwidth table the exponent value */ - if(SpiritRadioGetDigDiv()) - { - cDivider = 2; - } - else - { - cDivider = 1; - } - - s_assert_param(IS_CH_BW(lBandwidth,s_lXtalFrequency/cDivider)); - - uint32_t lChfltFactor = (s_lXtalFrequency/cDivider)/100; - - for(i=0;i<90 && (lBandwidth<(uint32_t)((s_vectnBandwidth26M[i]*lChfltFactor)/2600));i++); - - if(i!=0) - { - /* Finds the mantissa value with less approximation */ - i_tmp=i; - int16_t chfltCalculation[3]; - for(uint8_t j=0;j<3;j++) - { - if(((i_tmp+j-1)>=0) || ((i_tmp+j-1)<=89)) - { - chfltCalculation[j] = lBandwidth - (uint32_t)((s_vectnBandwidth26M[i_tmp+j-1]*lChfltFactor)/2600); - } - else - { - chfltCalculation[j] = 0x7FFF; - } - } - uint16_t chfltDelta = 0xFFFF; - - for(uint8_t j=0;j<3;j++) - { - if(S_ABS(chfltCalculation[j])<chfltDelta) - { - chfltDelta = S_ABS(chfltCalculation[j]); - i=i_tmp+j-1; - } - } - } - (*pcE) = (uint8_t)(i/9); - (*pcM) = (uint8_t)(i%9); - -} - -/** -* @brief Returns the mantissa and exponent, whose value used in the frequency deviation formula -* will give a frequency deviation value most closer to the given frequency deviation. -* @param fFDev frequency deviation expressed in Hz. This parameter can be a value in the range [F_Xo*8/2^18, F_Xo*7680/2^18]. -* @param pcM pointer to the returned mantissa value. -* @param pcE pointer to the returned exponent value. -* @retval None. -*/ -void SpiritRadioSearchFreqDevME(uint32_t lFDev, uint8_t* pcM, uint8_t* pcE) -{ - uint8_t i; - uint32_t a,bp,b=0; - float xtalDivtmp=(float)s_lXtalFrequency/(((uint32_t)1)<<18); - - /* Check the parameters */ - s_assert_param(IS_F_DEV(lFDev,s_lXtalFrequency)); - - for(i=0;i<10;i++) - { - a=(uint32_t)(xtalDivtmp*(uint32_t)(7.5*(1<<i))); - if(lFDev<a) - break; - } - (*pcE) = i; - - for(i=0;i<8;i++) - { - bp=b; - b=(uint32_t)(xtalDivtmp*(uint32_t)((8.0+i)/2*(1<<(*pcE)))); - if(lFDev<b) - break; - } - - (*pcM)=i; - if((lFDev-bp)<(b-lFDev)) - (*pcM)--; - -} - - -/** -* @brief Sets the datarate. -* @param fDatarate datarate expressed in bps. This value shall be in the range -* [100 500000]. -* @retval None. -*/ -void SpiritRadioSetDatarate(uint32_t lDatarate) -{ - uint8_t drE, tempRegValue[2]; - - /* Check the parameters */ - s_assert_param(IS_DATARATE(lDatarate)); - - /* Calculates the datarate mantissa and exponent */ - SpiritRadioSearchDatarateME(lDatarate, &tempRegValue[0], &drE); - - /* Reads the MOD_O register*/ - SpiritSpiReadRegisters(MOD0_BASE, 1, &tempRegValue[1]); - - /* Mask the other fields and set the datarate exponent */ - tempRegValue[1] &= 0xF0; - tempRegValue[1] |= drE; - - /* Writes the Datarate registers */ - g_xStatus = SpiritSpiWriteRegisters(MOD1_BASE, 2, tempRegValue); - -} - - -/** -* @brief Returns the datarate. -* @param None. -* @retval uint32_t Settled datarate expressed in bps. -*/ -uint32_t SpiritRadioGetDatarate(void) -{ - uint8_t tempRegValue[2]; - uint8_t cDivider=0; - - /* Reads the datarate registers for mantissa and exponent */ - g_xStatus = SpiritSpiReadRegisters(MOD1_BASE, 2, tempRegValue); - - /* Calculates the datarate */ - cDivider = (uint8_t)SpiritRadioGetDigDiv(); - - return (((s_lXtalFrequency>>(5+cDivider))*(256+tempRegValue[0]))>>(23-(tempRegValue[1]&0x0F))); -} - - -/** -* @brief Sets the frequency deviation. -* @param fFDev frequency deviation expressed in Hz. Be sure that this value -* is in the correct range [F_Xo*8/2^18, F_Xo*7680/2^18] Hz. -* @retval None. -*/ -void SpiritRadioSetFrequencyDev(uint32_t lFDev) -{ - uint8_t FDevM, FDevE, tempRegValue; - - /* Check the parameters */ - s_assert_param(IS_F_DEV(lFDev, s_lXtalFrequency)); - - /* Calculates the frequency deviation mantissa and exponent */ - SpiritRadioSearchFreqDevME(lFDev, &FDevM, &FDevE); - - /* Reads the FDEV0 register */ - SpiritSpiReadRegisters(FDEV0_BASE, 1, &tempRegValue); - - /* Mask the other fields and set the frequency deviation mantissa and exponent */ - tempRegValue &= 0x08; - tempRegValue |= ((FDevE<<4)|(FDevM)); - - /* Writes the Frequency deviation register */ - g_xStatus = SpiritSpiWriteRegisters(FDEV0_BASE, 1, &tempRegValue); - -} - - -/** -* @brief Returns the frequency deviation. -* @param None. -* @retval uint32_t Frequency deviation value expressed in Hz. -* This value will be in the range [F_Xo*8/2^18, F_Xo*7680/2^18] Hz. -*/ -uint32_t SpiritRadioGetFrequencyDev(void) -{ - uint8_t tempRegValue, FDevM, FDevE; - - - /* Reads the frequency deviation register for mantissa and exponent */ - g_xStatus = SpiritSpiReadRegisters(FDEV0_BASE, 1, &tempRegValue); - FDevM = tempRegValue&0x07; - FDevE = (tempRegValue&0xF0)>>4; - - /* Calculates the frequency deviation and return it */ - //return (((s_lXtalFrequency>>6)*(8+FDevM))>>(13-FDevE)); - - return (uint32_t)((float)s_lXtalFrequency/(((uint32_t)1)<<18)*(uint32_t)((8.0+FDevM)/2*(1<<FDevE))); - -} - - -/** -* @brief Sets the channel filter bandwidth. -* @param lBandwidth channel filter bandwidth expressed in Hz. This parameter shall be in the range [1100 800100] -* Even if it is possible to pass as parameter any value in the above mentioned range, -* the API will search the most closer value according to a fixed table of channel -* bandwidth values (@ref s_vectnBandwidth), as defined in the datasheet. To verify the settled channel bandwidth -* it is possible to use the SpiritRadioGetChannelBW() API. -* @retval None. -*/ -void SpiritRadioSetChannelBW(uint32_t lBandwidth) -{ - uint8_t bwM, bwE, tempRegValue; - - /* Search in the channel filter bandwidth table the exponent value */ - if(SpiritRadioGetDigDiv()) - { - s_assert_param(IS_CH_BW(lBandwidth,(s_lXtalFrequency/2))); - } - else - { - s_assert_param(IS_CH_BW(lBandwidth,(s_lXtalFrequency))); - } - - /* Calculates the channel bandwidth mantissa and exponent */ - SpiritRadioSearchChannelBwME(lBandwidth, &bwM, &bwE); - tempRegValue = (bwM<<4)|(bwE); - - /* Writes the Channel filter register */ - g_xStatus = SpiritSpiWriteRegisters(CHFLT_BASE, 1, &tempRegValue); - -} - -/** -* @brief Returns the channel filter bandwidth. -* @param None. -* @retval uint32_t Channel filter bandwidth expressed in Hz. -*/ -uint32_t SpiritRadioGetChannelBW(void) -{ - uint8_t tempRegValue, bwM, bwE; - - /* Reads the channel filter register for mantissa and exponent */ - g_xStatus = SpiritSpiReadRegisters(CHFLT_BASE, 1, &tempRegValue); - bwM = (tempRegValue&0xF0)>>4; - bwE = tempRegValue&0x0F; - - /* Reads the channel filter bandwidth from the look-up table and return it */ - return (uint32_t)(100.0*s_vectnBandwidth26M[bwM+(bwE*9)]*s_lXtalFrequency/26e6); - -} - - -/** -* @brief Sets the modulation type. -* @param xModulation modulation to set. -* This parameter shall be of type @ref ModulationSelect . -* @retval None. -*/ -void SpiritRadioSetModulation(ModulationSelect xModulation) -{ - uint8_t tempRegValue; - - /* Check the parameters */ - s_assert_param(IS_MODULATION_SELECTED(xModulation)); - - /* Reads the modulation register */ - SpiritSpiReadRegisters(MOD0_BASE, 1, &tempRegValue); - - /* Mask the other fields and set the modulation type */ - tempRegValue &=0x8F; - tempRegValue |= xModulation; - - /* Writes the modulation register */ - g_xStatus = SpiritSpiWriteRegisters(MOD0_BASE, 1, &tempRegValue); - -} - - -/** -* @brief Returns the modulation type used. -* @param None. -* @retval ModulationSelect Settled modulation type. -*/ -ModulationSelect SpiritRadioGetModulation(void) -{ - uint8_t tempRegValue; - - /* Reads the modulation register MOD0*/ - g_xStatus = SpiritSpiReadRegisters(MOD0_BASE, 1, &tempRegValue); - - /* Return the modulation type */ - return (ModulationSelect)(tempRegValue&0x70); - -} - - -/** -* @brief Enables or Disables the Continuous Wave transmit mode. -* @param xNewState new state for power ramping. -* This parameter can be: S_ENABLE or S_DISABLE . -* @retval None. -*/ -void SpiritRadioCWTransmitMode(SpiritFunctionalState xNewState) -{ - uint8_t tempRegValue; - - /* Check the parameters */ - s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState)); - - /* Reads the modulation register MOD0 and mask the CW field */ - SpiritSpiReadRegisters(MOD0_BASE, 1, &tempRegValue); - if(xNewState == S_ENABLE) - { - tempRegValue |=MOD0_CW; - } - else - { - tempRegValue &= (~MOD0_CW); - } - - /* Writes the new value in the MOD0 register */ - g_xStatus = SpiritSpiWriteRegisters(MOD0_BASE, 1, &tempRegValue); - -} - - -/** -* @brief Sets the OOK Peak Decay. -* @param xOokDecay Peak decay control for OOK. -* This parameter shall be of type @ref OokPeakDecay . -* @retval None. -*/ -void SpiritRadioSetOokPeakDecay(OokPeakDecay xOokDecay) -{ - uint8_t tempRegValue; - - /* Check the parameters */ - s_assert_param(IS_OOK_PEAK_DECAY(xOokDecay)); - - /* Reads the RSSI_FLT register */ - SpiritSpiReadRegisters(RSSI_FLT_BASE, 1, &tempRegValue); - - /* Mask the other fields and set OOK Peak Decay */ - tempRegValue &= 0xFC; - tempRegValue |= xOokDecay; - - /* Writes the RSSI_FLT register to set the new OOK peak dacay value */ - g_xStatus = SpiritSpiWriteRegisters(RSSI_FLT_BASE, 1, &tempRegValue); - -} - - -/** -* @brief Returns the OOK Peak Decay. -* @param None -* @retval OokPeakDecay Ook peak decay value. -*/ -OokPeakDecay SpiritRadioGetOokPeakDecay(void) -{ - uint8_t tempRegValue; - - /* Reads the OOK peak decay register RSSI_FLT_BASE*/ - g_xStatus = SpiritSpiReadRegisters(RSSI_FLT_BASE, 1, &tempRegValue); - - /* Returns the OOK peak decay */ - return (OokPeakDecay) (tempRegValue & 0x03); - -} - -/** -* @brief Returns the PA register value that corresponds to the passed dBm power. -* @param lFbase Frequency base expressed in Hz. -* @param fPowerdBm Desired power in dBm. -* @retval Register value as byte. -* @note The power interpolation curves used by this function have been extracted -* by measurements done on the divisional evaluation boards. -*/ -uint8_t SpiritRadioGetdBm2Reg(uint32_t lFBase, float fPowerdBm) -{ - uint8_t i=0; - uint8_t j=0; - float fReg; - - if(IS_FREQUENCY_BAND_HIGH(lFBase)) - { - i=0; - if(lFBase<900000000) i=1;// 868 - } - else if(IS_FREQUENCY_BAND_MIDDLE(lFBase)) - { - i=2; - } - else if(IS_FREQUENCY_BAND_LOW(lFBase)) - { - i=3; - } - else if(IS_FREQUENCY_BAND_VERY_LOW(lFBase)) - { - i=4; - } - - j=1; - if(fPowerdBm>0 && 13.0/fPowerFactors[i][2]-fPowerFactors[i][3]/fPowerFactors[i][2]<fPowerdBm) - j=0; - else if(fPowerdBm<=0 && 40.0/fPowerFactors[i][2]-fPowerFactors[i][3]/fPowerFactors[i][2]>fPowerdBm) - j=2; - - fReg=fPowerFactors[i][2*j]*fPowerdBm+fPowerFactors[i][2*j+1]; - - if(fReg<1) - fReg=1; - else if(fReg>90) - fReg=90; - - return ((uint8_t)fReg); -} - - -/** -* @brief Returns the dBm power that corresponds to the value of PA register. -* @param lFbase Frequency base expressed in Hz. -* @param cPowerReg Register value of the PA. -* @retval Power in dBm as float. -* @note The power interpolation curves used by this function have been extracted -* by measurements done on the divisional evaluation boards. -*/ -float SpiritRadioGetReg2dBm(uint32_t lFBase, uint8_t cPowerReg) -{ - uint8_t i=0; - uint8_t j=0; - float fPower; - - if(cPowerReg==0 || cPowerReg>90) - return (-130.0); - - if(IS_FREQUENCY_BAND_HIGH(lFBase)) - { - i=0; - if(lFBase<900000000) i=1;// 868 - } - else if(IS_FREQUENCY_BAND_MIDDLE(lFBase)) - { - i=2; - } - else if(IS_FREQUENCY_BAND_LOW(lFBase)) - { - i=3; - } - else if(IS_FREQUENCY_BAND_VERY_LOW(lFBase)) - { - i=4; - } - - j=1; - if(cPowerReg<13) j=0; - else if(cPowerReg>40) j=2; - - fPower=(((float)cPowerReg)/fPowerFactors[i][2*j]-fPowerFactors[i][2*j+1]/fPowerFactors[i][2*j]); - - return fPower; -} - -/** -* @brief Configures the Power Amplifier Table and registers with value expressed in dBm. -* @param cPALevelMaxIndex number of levels to set. This parameter shall be in the range [0:7]. -* @param cWidth step width expressed in terms of bit period units Tb/8. -* This parameter shall be in the range [1:4]. -* @param xCLoad one of the possible value of the enum type PALoadCapacitor. -* @arg LOAD_0_PF No additional PA load capacitor -* @arg LOAD_1_2_PF 1.2pF additional PA load capacitor -* @arg LOAD_2_4_PF 2.4pF additional PA load capacitor -* @arg LOAD_3_6_PF 3.6pF additional PA load capacitor -* @param pfPAtabledBm pointer to an array of PA values in dbm between [-PA_LOWER_LIMIT: PA_UPPER_LIMIT] dbm. -* The first element shall be the lower level (PA_LEVEL[0]) value and the last element -* the higher level one (PA_LEVEL[paLevelMaxIndex]). -* @retval None. -*/ -void SpiritRadioSetPATabledBm(uint8_t cPALevelMaxIndex, uint8_t cWidth, PALoadCapacitor xCLoad, float* pfPAtabledBm) -{ - uint8_t palevel[9], address, paLevelValue; - uint32_t lFBase=SpiritRadioGetFrequencyBase(); - - /* Check the parameters */ - s_assert_param(IS_PA_MAX_INDEX(cPALevelMaxIndex)); - s_assert_param(IS_PA_STEP_WIDTH(cWidth)); - s_assert_param(IS_PA_LOAD_CAP(xCLoad)); - - /* Check the PA level in dBm is in the range and calculate the PA_LEVEL value - to write in the corresponding register using the linearization formula */ - for(int i=0; i<=cPALevelMaxIndex; i++) - { - s_assert_param(IS_PAPOWER_DBM(*pfPAtabledBm)); - paLevelValue=SpiritRadioGetdBm2Reg(lFBase,(*pfPAtabledBm)); - palevel[cPALevelMaxIndex-i]=paLevelValue; - pfPAtabledBm++; - } - - /* Sets the PA_POWER[0] register */ - palevel[cPALevelMaxIndex+1]=xCLoad|(cWidth-1)<<3|cPALevelMaxIndex; - - /* Sets the base address */ - address=PA_POWER8_BASE+7-cPALevelMaxIndex; - - /* Configures the PA_POWER registers */ - g_xStatus = SpiritSpiWriteRegisters(address, cPALevelMaxIndex+2, palevel); - -} - - -/** -* @brief Returns the Power Amplifier Table and registers, returning values in dBm. -* @param pcPALevelMaxIndex pointer to the number of levels settled. -* This parameter will be in the range [0:7]. -* @param pfPAtabledBm pointer to an array of 8 elements containing the PA value in dbm. -* The first element will be the PA_LEVEL_0 and the last element -* will be PA_LEVEL_7. Any value higher than PA_UPPER_LIMIT implies no output -* power (output stage is in high impedance). -* @retval None. -*/ -void SpiritRadioGetPATabledBm(uint8_t* pcPALevelMaxIndex, float* pfPAtabledBm) -{ - uint8_t palevelvect[9]; - uint32_t lFBase=SpiritRadioGetFrequencyBase(); - - /* Reads the PA_LEVEL_x registers and the PA_POWER_0 register */ - g_xStatus = SpiritSpiReadRegisters(PA_POWER8_BASE, 9, palevelvect); - - /* Fill the PAtable */ - for(int i=7; i>=0; i--) - { - (*pfPAtabledBm)=SpiritRadioGetReg2dBm(lFBase,palevelvect[i]); - pfPAtabledBm++; - } - - /* Return the settled index */ - *pcPALevelMaxIndex = palevelvect[8]&0x07; - -} - - - - - - -/** -* @brief Sets a specific PA_LEVEL register, with a value given in dBm. -* @param cIndex PA_LEVEL to set. This parameter shall be in the range [0:7]. -* @param fPowerdBm PA value to write expressed in dBm . Be sure that this values is in the -* correct range [-PA_LOWER_LIMIT: PA_UPPER_LIMIT] dBm. -* @retval None. -* @note This function makes use of the @ref SpiritRadioGetdBm2Reg fcn to interpolate the -* power value. -*/ -void SpiritRadioSetPALeveldBm(uint8_t cIndex, float fPowerdBm) -{ - uint8_t address, paLevelValue; - - /* Check the parameters */ - s_assert_param(IS_PA_MAX_INDEX(cIndex)); - s_assert_param(IS_PAPOWER_DBM(fPowerdBm)); - - /* interpolate the power level */ - paLevelValue=SpiritRadioGetdBm2Reg(SpiritRadioGetFrequencyBase(),fPowerdBm); - - /* Sets the base address */ - address=PA_POWER8_BASE+7-cIndex; - - /* Configures the PA_LEVEL register */ - g_xStatus = SpiritSpiWriteRegisters(address, 1, &paLevelValue); - -} - - -/** -* @brief Returns a specific PA_LEVEL register, returning a value in dBm. -* @param cIndex PA_LEVEL to read. This parameter shall be in the range [0:7] -* @retval float Settled power level expressed in dBm. A value -* higher than PA_UPPER_LIMIT dBm implies no output power -* (output stage is in high impedance). -* @note This function makes use of the @ref SpiritRadioGetReg2dBm fcn to interpolate the -* power value. -*/ -float SpiritRadioGetPALeveldBm(uint8_t cIndex) -{ - uint8_t address, paLevelValue; - - /* Check the parameters */ - s_assert_param(IS_PA_MAX_INDEX(cIndex)); - - /* Sets the base address */ - address=PA_POWER8_BASE+7-cIndex; - - /* Reads the PA_LEVEL[cIndex] register */ - g_xStatus = SpiritSpiReadRegisters(address, 1, &paLevelValue); - - return SpiritRadioGetReg2dBm(SpiritRadioGetFrequencyBase(),paLevelValue); -} - - -/** -* @brief Configures the Power Amplifier Table and registers. -* @param cPALevelMaxIndex number of levels to set. This parameter shall be in the range [0:7]. -* @param cWidth step width expressed in terms of bit period units Tb/8. -* This parameter shall be in the range [1:4]. -* @param xCLoad one of the possible value of the enum type PALoadCapacitor. -* @arg LOAD_0_PF No additional PA load capacitor -* @arg LOAD_1_2_PF 1.2pF additional PA load capacitor -* @arg LOAD_2_4_PF 2.4pF additional PA load capacitor -* @arg LOAD_3_6_PF 3.6pF additional PA load capacitor -* @param pcPAtable pointer to an array of PA values in the range [0: 90], where 0 implies no -* output power, 1 will be the maximum level and 90 the minimum one -* The first element shall be the lower level (PA_LEVEL[0]) value and the last element -* the higher level one (PA_LEVEL[paLevelMaxIndex]). -* @retval None. -*/ -void SpiritRadioSetPATable(uint8_t cPALevelMaxIndex, uint8_t cWidth, PALoadCapacitor xCLoad, uint8_t* pcPAtable) -{ - uint8_t palevel[9], address; - - /* Check the parameters */ - s_assert_param(IS_PA_MAX_INDEX(cPALevelMaxIndex)); - s_assert_param(IS_PA_STEP_WIDTH(cWidth)); - s_assert_param(IS_PA_LOAD_CAP(xCLoad)); - - /* Check the PA levels are in the range */ - for(int i=0; i<=cPALevelMaxIndex; i++) - { - s_assert_param(IS_PAPOWER(*pcPAtable)); - palevel[cPALevelMaxIndex-i]=*pcPAtable; - pcPAtable++; - } - - /* Sets the PA_POWER[0] register */ - palevel[cPALevelMaxIndex+1]=xCLoad|((cWidth-1)<<3)|cPALevelMaxIndex; - - /* Sets the base address */ - address=PA_POWER8_BASE+7-cPALevelMaxIndex; - - /* Configures the PA_POWER registers */ - g_xStatus = SpiritSpiWriteRegisters(address, cPALevelMaxIndex+2, palevel); - -} - - -/** -* @brief Returns the Power Amplifier Table and registers. -* @param pcPALevelMaxIndex pointer to the number of levels settled. -* This parameter shall be in the range [0:7]. -* @param pcPAtable pointer to an array of 8 elements containing the PA value. -* The first element will be the PA_LEVEL_0 and the last element -* will be PA_LEVEL_7. Any value equals to 0 implies that level has -* no output power (output stage is in high impedance). -* @retval None -*/ -void SpiritRadioGetPATable(uint8_t* pcPALevelMaxIndex, uint8_t* pcPAtable) -{ - uint8_t palevelvect[9]; - - /* Reads the PA_LEVEL_x registers and the PA_POWER_0 register */ - g_xStatus = SpiritSpiReadRegisters(PA_POWER8_BASE, 9, palevelvect); - - /* Fill the PAtable */ - for(int i=7; i>=0; i--) - { - *pcPAtable = palevelvect[i]; - pcPAtable++; - } - - /* Return the settled index */ - *pcPALevelMaxIndex = palevelvect[8]&0x07; - -} - - -/** -* @brief Sets a specific PA_LEVEL register. -* @param cIndex PA_LEVEL to set. This parameter shall be in the range [0:7]. -* @param cPower PA value to write in the register. Be sure that this values is in the -* correct range [0 : 90]. -* @retval None. -*/ -void SpiritRadioSetPALevel(uint8_t cIndex, uint8_t cPower) -{ - uint8_t address; - - /* Check the parameters */ - s_assert_param(IS_PA_MAX_INDEX(cIndex)); - s_assert_param(IS_PAPOWER(cPower)); - - /* Sets the base address */ - address=PA_POWER8_BASE+7-cIndex; - - /* Configures the PA_LEVEL register */ - g_xStatus = SpiritSpiWriteRegisters(address, 1, &cPower); - -} - - -/** -* @brief Returns a specific PA_LEVEL register. -* @param cIndex PA_LEVEL to read. This parameter shall be in the range [0:7]. -* @retval uint8_t PA_LEVEL value. A value equal to zero -* implies no output power (output stage is in high impedance). -*/ -uint8_t SpiritRadioGetPALevel(uint8_t cIndex) -{ - uint8_t address, tempRegValue; - - /* Check the parameters */ - s_assert_param(IS_PA_MAX_INDEX(cIndex)); - - /* Sets the base address */ - address=PA_POWER8_BASE+7-cIndex; - - /* Reads the PA_LEVEL[cIndex] register and return the value */ - g_xStatus = SpiritSpiReadRegisters(address, 1, &tempRegValue); - return tempRegValue; - -} - - -/** -* @brief Sets the output stage additional load capacitor bank. -* @param xCLoad one of the possible value of the enum type PALoadCapacitor. -* @arg LOAD_0_PF No additional PA load capacitor -* @arg LOAD_1_2_PF 1.2pF additional PA load capacitor -* @arg LOAD_2_4_PF 2.4pF additional PA load capacitor -* @arg LOAD_3_6_PF 3.6pF additional PA load capacitor -* @retval None. -*/ -void SpiritRadioSetPACwc(PALoadCapacitor xCLoad) -{ - uint8_t tempRegValue; - - /* Check the parameters */ - s_assert_param(IS_PA_LOAD_CAP(xCLoad)); - - /* Reads the PA_POWER_0 register */ - SpiritSpiReadRegisters(PA_POWER0_BASE, 1, &tempRegValue); - - /* Mask the CWC[1:0] field and write the new value */ - tempRegValue &= 0x3F; - tempRegValue |= xCLoad; - - /* Configures the PA_POWER_0 register */ - g_xStatus = SpiritSpiWriteRegisters(PA_POWER0_BASE, 1, &tempRegValue); - -} - - -/** -* @brief Returns the output stage additional load capacitor bank. -* @param None. -* @retval PALoadCapacitor Output stage additional load capacitor bank. -* This parameter can be: -* @arg LOAD_0_PF No additional PA load capacitor -* @arg LOAD_1_2_PF 1.2pF additional PA load capacitor -* @arg LOAD_2_4_PF 2.4pF additional PA load capacitor -* @arg LOAD_3_6_PF 3.6pF additional PA load capacitor -*/ -PALoadCapacitor SpiritRadioGetPACwc(void) -{ - uint8_t tempRegValue; - - /* Reads the PA_POWER_0 register */ - g_xStatus = SpiritSpiReadRegisters(PA_POWER0_BASE, 1, &tempRegValue); - - /* Mask the CWC[1:0] field and return the value*/ - return (PALoadCapacitor)(tempRegValue & 0xC0); - -} - - -/** -* @brief Sets a specific PA_LEVEL_MAX_INDEX. -* @param cIndex PA_LEVEL_MAX_INDEX to set. This parameter shall be in the range [0:7]. -* @retval None -*/ -void SpiritRadioSetPALevelMaxIndex(uint8_t cIndex) -{ - uint8_t tempRegValue; - - /* Check the parameters */ - s_assert_param(IS_PA_MAX_INDEX(cIndex)); - - /* Reads the PA_POWER_0 register */ - SpiritSpiReadRegisters(PA_POWER0_BASE, 1, &tempRegValue); - - /* Mask the PA_LEVEL_MAX_INDEX[1:0] field and write the new value */ - tempRegValue &= 0xF8; - tempRegValue |= cIndex; - - /* Configures the PA_POWER_0 register */ - g_xStatus = SpiritSpiWriteRegisters(PA_POWER0_BASE, 1, &tempRegValue); - -} - - -/** -* @brief Returns the actual PA_LEVEL_MAX_INDEX. -* @param None. -* @retval uint8_t Actual PA_LEVEL_MAX_INDEX. This parameter will be in the range [0:7]. -*/ -uint8_t SpiritRadioGetPALevelMaxIndex(void) -{ - uint8_t tempRegValue; - - /* Reads the PA_POWER_0 register */ - g_xStatus = SpiritSpiReadRegisters(PA_POWER0_BASE, 1, &tempRegValue); - - /* Mask the PA_LEVEL_MAX_INDEX[1:0] field and return the value */ - return (tempRegValue & 0x07); - -} - - -/** -* @brief Sets a specific PA_RAMP_STEP_WIDTH. -* @param cWidth step width expressed in terms of bit period units Tb/8. -* This parameter shall be in the range [1:4]. -* @retval None. -*/ -void SpiritRadioSetPAStepWidth(uint8_t cWidth) -{ - uint8_t tempRegValue; - - /* Check the parameters */ - s_assert_param(IS_PA_STEP_WIDTH(cWidth)); - - /* Reads the PA_POWER_0 register */ - SpiritSpiReadRegisters(PA_POWER0_BASE, 1, &tempRegValue); - - /* Mask the PA_RAMP_STEP_WIDTH[1:0] field and write the new value */ - tempRegValue &= 0xE7; - tempRegValue |= (cWidth-1)<<3; - - /* Configures the PA_POWER_0 register */ - g_xStatus = SpiritSpiWriteRegisters(PA_POWER0_BASE, 1, &tempRegValue); - -} - - -/** -* @brief Returns the actual PA_RAMP_STEP_WIDTH. -* @param None. -* @retval uint8_t Step width value expressed in terms of bit period units Tb/8. -* This parameter will be in the range [1:4]. -*/ -uint8_t SpiritRadioGetPAStepWidth(void) -{ - uint8_t tempRegValue; - - /* Reads the PA_POWER_0 register */ - g_xStatus = SpiritSpiReadRegisters(PA_POWER0_BASE, 1, &tempRegValue); - - /* Mask the PA_RAMP_STEP_WIDTH[1:0] field and return the value */ - tempRegValue &= 0x18; - return ((tempRegValue>>3)+1); - -} - - -/** -* @brief Enables or Disables the Power Ramping. -* @param xNewState new state for power ramping. -* This parameter can be: S_ENABLE or S_DISABLE. -* @retval None. -*/ -void SpiritRadioPARamping(SpiritFunctionalState xNewState) -{ - uint8_t tempRegValue = 0x00; - - /* Check the parameters */ - s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState)); - - /* Reads the PA_POWER_0 register and configure the PA_RAMP_ENABLE field */ - SpiritSpiReadRegisters(PA_POWER0_BASE, 1, &tempRegValue); - if(xNewState == S_ENABLE) - { - tempRegValue |= PA_POWER0_PA_RAMP_MASK; - } - else - { - tempRegValue &= (~PA_POWER0_PA_RAMP_MASK); - } - - /* Sets the PA_POWER_0 register */ - g_xStatus = SpiritSpiWriteRegisters(PA_POWER0_BASE, 1, &tempRegValue); - -} - -/** -* @brief Returns the Power Ramping enable bit. -* @param xNewState new state for power ramping. -* This parameter can be: S_ENABLE or S_DISABLE. -* @retval None. -*/ -SpiritFunctionalState SpiritRadioGetPARamping(void) -{ - uint8_t tempRegValue; - - /* Reads the PA_POWER_0 register and configure the PA_RAMP_ENABLE field */ - g_xStatus = SpiritSpiReadRegisters(PA_POWER0_BASE, 1, &tempRegValue); - - /* Mask and return data */ - return (SpiritFunctionalState)((tempRegValue>>5) & 0x01); - -} - - -/** -* @brief Enables or Disables the AFC. -* @param xNewState new state for AFC. -* This parameter can be: S_ENABLE or S_DISABLE. -* @retval None. -*/ -void SpiritRadioAFC(SpiritFunctionalState xNewState) -{ - uint8_t tempRegValue = 0x00; - - /* Check the parameters */ - s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState)); - - /* Reads the AFC_2 register and configure the AFC Enabled field */ - SpiritSpiReadRegisters(AFC2_BASE, 1, &tempRegValue); - if(xNewState == S_ENABLE) - { - tempRegValue |= AFC2_AFC_MASK; - } - else - { - tempRegValue &= (~AFC2_AFC_MASK); - } - - /* Sets the AFC_2 register */ - g_xStatus = SpiritSpiWriteRegisters(AFC2_BASE, 1, &tempRegValue); - -} - - -/** -* @brief Enables or Disables the AFC freeze on sync word detection. -* @param xNewState new state for AFC freeze on sync word detection. -* This parameter can be: S_ENABLE or S_DISABLE. -* @retval None. -*/ -void SpiritRadioAFCFreezeOnSync(SpiritFunctionalState xNewState) -{ - uint8_t tempRegValue = 0x00; - - /* Check the parameters */ - s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState)); - - /* Reads the AFC_2 register and configure the AFC Freeze on Sync field */ - SpiritSpiReadRegisters(AFC2_BASE, 1, &tempRegValue); - if(xNewState == S_ENABLE) - { - tempRegValue |= AFC2_AFC_FREEZE_ON_SYNC_MASK; - } - else - { - tempRegValue &= (~AFC2_AFC_FREEZE_ON_SYNC_MASK); - } - - /* Sets the AFC_2 register */ - g_xStatus = SpiritSpiWriteRegisters(AFC2_BASE, 1, &tempRegValue); - -} - - -/** -* @brief Sets the AFC working mode. -* @param xMode the AFC mode. This parameter can be one of the values defined in @ref AFCMode : -* @arg AFC_SLICER_CORRECTION AFC loop closed on slicer -* @arg AFC_2ND_IF_CORRECTION AFC loop closed on 2nd conversion stage -* @retval None. -*/ -void SpiritRadioSetAFCMode(AFCMode xMode) -{ - uint8_t tempRegValue = 0x00; - - /* Check the parameters */ - s_assert_param(IS_AFC_MODE(xMode)); - - /* Reads the AFC_2 register and configure the AFC Mode field */ - SpiritSpiReadRegisters(AFC2_BASE, 1, &tempRegValue); - if(xMode == AFC_2ND_IF_CORRECTION) - { - tempRegValue |= AFC_2ND_IF_CORRECTION; - } - else - { - tempRegValue &= (~AFC_2ND_IF_CORRECTION); - } - - /* Sets the AFC_2 register */ - g_xStatus = SpiritSpiWriteRegisters(AFC2_BASE, 1, &tempRegValue); - -} - - -/** -* @brief Returns the AFC working mode. -* @param None. -* @retval AFCMode Settled AFC mode. This parameter will be one of the values defined in @ref AFCMode : -* @arg AFC_SLICER_CORRECTION AFC loop closed on slicer -* @arg AFC_2ND_IF_CORRECTION AFC loop closed on 2nd conversion stage -*/ -AFCMode SpiritRadioGetAFCMode(void) -{ - uint8_t tempRegValue; - - /* Reads the AFC_2 register */ - g_xStatus = SpiritSpiReadRegisters(AFC2_BASE, 1, &tempRegValue); - - /* Mask the AFC Mode field and returns the value */ - return (AFCMode)(tempRegValue & 0x20); - -} - - -/** -* @brief Sets the AFC peak detector leakage. -* @param cLeakage the peak detector leakage. This parameter shall be in the range: -* [0:31]. -* @retval None. -*/ -void SpiritRadioSetAFCPDLeakage(uint8_t cLeakage) -{ - uint8_t tempRegValue = 0x00; - - /* Check the parameters */ - s_assert_param(IS_AFC_PD_LEAKAGE(cLeakage)); - - /* Reads the AFC_2 register and configure the AFC PD leakage field */ - SpiritSpiReadRegisters(AFC2_BASE, 1, &tempRegValue); - tempRegValue &= 0xE0; - tempRegValue |= cLeakage; - - /* Sets the AFC_2 register */ - g_xStatus = SpiritSpiWriteRegisters(AFC2_BASE, 1, &tempRegValue); - -} - - -/** -* @brief Returns the AFC peak detector leakage. -* @param None. -* @retval uint8_t Peak detector leakage value. This parameter will be in the range: -* [0:31]. -*/ -uint8_t SpiritRadioGetAFCPDLeakage(void) -{ - uint8_t tempRegValue; - - /* Reads the AFC_2 register */ - g_xStatus = SpiritSpiReadRegisters(AFC2_BASE, 1, &tempRegValue); - - /* Mask the AFC PD leakage field and return the value */ - return (tempRegValue & 0x1F); - -} - - -/** -* @brief Sets the length of the AFC fast period expressed as number of samples. -* @param cLength length of the fast period in number of samples. -* @retval None. -*/ -void SpiritRadioSetAFCFastPeriod(uint8_t cLength) -{ - /* Sets the AFC_1 register */ - g_xStatus = SpiritSpiWriteRegisters(AFC1_BASE, 1, &cLength); - -} - - -/** -* @brief Returns the AFC fast period expressed as number of samples. -* @param None. -* @retval uint8_t Length of the fast period in number of samples. -*/ -uint8_t SpiritRadioGetAFCFastPeriod(void) -{ - uint8_t tempRegValue; - - /* Reads the AFC 1 register and return the value */ - g_xStatus = SpiritSpiReadRegisters(AFC1_BASE, 1, &tempRegValue); - - return tempRegValue; - -} - - -/** -* @brief Sets the AFC loop gain in fast mode. -* @param cGain AFC loop gain in fast mode. This parameter shall be in the range: -* [0:15]. -* @retval None. -*/ -void SpiritRadioSetAFCFastGain(uint8_t cGain) -{ - uint8_t tempRegValue = 0x00; - - /* Check the parameters */ - s_assert_param(IS_AFC_FAST_GAIN(cGain)); - - /* Reads the AFC_0 register and configure the AFC Fast Gain field */ - SpiritSpiReadRegisters(AFC0_BASE, 1, &tempRegValue); - tempRegValue &= 0x0F; - tempRegValue |= cGain<<4; - - /* Sets the AFC_0 register */ - g_xStatus = SpiritSpiWriteRegisters(AFC0_BASE, 1, &tempRegValue); - -} - - -/** -* @brief Returns the AFC loop gain in fast mode. -* @param None. -* @retval uint8_t AFC loop gain in fast mode. This parameter will be in the range: -* [0:15]. -*/ -uint8_t SpiritRadioGetAFCFastGain(void) -{ - uint8_t tempRegValue; - - /* Reads the AFC_0 register, mask the AFC Fast Gain field and return the value */ - g_xStatus = SpiritSpiReadRegisters(AFC0_BASE, 1, &tempRegValue); - - return ((tempRegValue & 0xF0)>>4); - -} - - -/** -* @brief Sets the AFC loop gain in slow mode. -* @param cGain AFC loop gain in slow mode. This parameter shall be in the range: -* [0:15]. -* @retval None. -*/ -void SpiritRadioSetAFCSlowGain(uint8_t cGain) -{ - uint8_t tempRegValue = 0x00; - - /* Check the parameters */ - s_assert_param(IS_AFC_SLOW_GAIN(cGain)); - - /* Reads the AFC_0 register and configure the AFC Slow Gain field */ - SpiritSpiReadRegisters(AFC0_BASE, 1, &tempRegValue); - tempRegValue &= 0xF0; - tempRegValue |= cGain; - - /* Sets the AFC_0 register */ - g_xStatus = SpiritSpiWriteRegisters(AFC0_BASE, 1, &tempRegValue); - -} - - -/** -* @brief Returns the AFC loop gain in slow mode. -* @param None. -* @retval uint8_t AFC loop gain in slow mode. This parameter will be in the range: -* [0:15]. -*/ -uint8_t SpiritRadioGetAFCSlowGain(void) -{ - uint8_t tempRegValue; - - /* Reads the AFC_0 register, mask the AFC Slow Gain field and return the value */ - g_xStatus = SpiritSpiReadRegisters(AFC0_BASE, 1, &tempRegValue); - - return (tempRegValue & 0x0F); - -} - - -/** -* @brief Returns the AFC correction from the corresponding register. -* @param None. -* @retval int8_t AFC correction, read from the corresponding register. -* This parameter will be in the range [-128:127]. -*/ -int8_t SpiritRadioGetAFCCorrectionReg(void) -{ - uint8_t tempRegValue; - - /* Reads the AFC_CORR register, cast the read value as signed char and return it */ - g_xStatus = SpiritSpiReadRegisters(AFC_CORR_BASE, 1, &tempRegValue); - - return (int8_t)tempRegValue; - -} - - -/** -* @brief Returns the AFC correction expressed in Hz. -* @param None. -* @retval int32_t AFC correction expressed in Hz -* according to the following formula:<ul> -* <li> Fafc[Hz]= (Fdig/(12*2^10))*AFC_CORR where </li> -* <li> AFC_CORR is the value read in the AFC_CORR register </li> </ul> -*/ -int32_t SpiritRadioGetAFCCorrectionHz(void) -{ - int8_t correction; - uint32_t xtal = s_lXtalFrequency; - - /* Reads the AFC correction register */ - correction = SpiritRadioGetAFCCorrectionReg(); - - if(xtal>DOUBLE_XTAL_THR) - { - xtal /= 2; - } - - /* Calculates and return the Frequency Correction */ - return (int32_t)(xtal/(12*pow(2,10))*correction); - -} - - -/** -* @brief Enables or Disables the AGC. -* @param xNewState new state for AGC. -* This parameter can be: S_ENABLE or S_DISABLE -* @retval None. -*/ -void SpiritRadioAGC(SpiritFunctionalState xNewState) -{ - uint8_t tempRegValue = 0x00; - - /* Check the parameters */ - s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState)); - - /* Reads the AGCCTRL_0 register and configure the AGC Enabled field */ - SpiritSpiReadRegisters(AGCCTRL0_BASE, 1, &tempRegValue); - if(xNewState == S_ENABLE) - { - tempRegValue |= AGCCTRL0_AGC_MASK; - } - else - { - tempRegValue &= (~AGCCTRL0_AGC_MASK); - } - - /* Sets the AGCCTRL_0 register */ - g_xStatus = SpiritSpiWriteRegisters(AGCCTRL0_BASE, 1, &tempRegValue); - -} - - -/** -* @brief Sets the AGC working mode. -* @param xMode the AGC mode. This parameter can be one of the values defined in @ref AGCMode : -* @arg AGC_LINEAR_MODE AGC works in linear mode -* @arg AGC_BINARY_MODE AGC works in binary mode -* @retval None. -*/ -void SpiritRadioSetAGCMode(AGCMode xMode) -{ - uint8_t tempRegValue = 0x00; - - /* Check the parameters */ - s_assert_param(IS_AGC_MODE(xMode)); - - /* Reads the AGCCTRL_0 register and configure the AGC Mode field */ - SpiritSpiReadRegisters(AGCCTRL0_BASE, 1, &tempRegValue); - if(xMode == AGC_BINARY_MODE) - { - tempRegValue |= AGC_BINARY_MODE; - } - else - { - tempRegValue &= (~AGC_BINARY_MODE); - } - - /* Sets the AGCCTRL_0 register */ - g_xStatus = SpiritSpiWriteRegisters(AGCCTRL0_BASE, 1, &tempRegValue); - -} - - -/** -* @brief Returns the AGC working mode. -* @param None. -* @retval AGCMode Settled AGC mode. This parameter can be one of the values defined in @ref AGCMode : -* @arg AGC_LINEAR_MODE AGC works in linear mode -* @arg AGC_BINARY_MODE AGC works in binary mode -*/ -AGCMode SpiritRadioGetAGCMode(void) -{ - uint8_t tempRegValue; - - /* Reads the AGCCTRL_0 register, mask the AGC Mode field and return the value */ - g_xStatus = SpiritSpiReadRegisters(AGCCTRL0_BASE, 1, &tempRegValue); - - return (AGCMode)(tempRegValue & 0x40); - -} - - -/** -* @brief Enables or Disables the AGC freeze on steady state. -* @param xNewState new state for AGC freeze on steady state. -* This parameter can be: S_ENABLE or S_DISABLE. -* @retval None. -*/ -void SpiritRadioAGCFreezeOnSteady(SpiritFunctionalState xNewState) -{ - uint8_t tempRegValue = 0x00; - - /* Check the parameters */ - s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState)); - - /* Reads the AGCCTRL_2 register and configure the AGC Freeze On Steady field */ - SpiritSpiReadRegisters(AGCCTRL2_BASE, 1, &tempRegValue); - if(xNewState == S_ENABLE) - { - tempRegValue |= AGCCTRL2_FREEZE_ON_STEADY_MASK; - } - else - { - tempRegValue &= (~AGCCTRL2_FREEZE_ON_STEADY_MASK); - } - - /* Sets the AGCCTRL_2 register */ - g_xStatus = SpiritSpiWriteRegisters(AGCCTRL2_BASE, 1, &tempRegValue); - -} - - -/** -* @brief Enable or Disable the AGC freeze on sync detection. -* @param xNewState new state for AGC freeze on sync detection. -* This parameter can be: S_ENABLE or S_DISABLE. -* @retval None. -*/ -void SpiritRadioAGCFreezeOnSync(SpiritFunctionalState xNewState) -{ - uint8_t tempRegValue = 0x00; - - /* Check the parameters */ - s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState)); - - /* Reads the AGCCTRL_2 register and configure the AGC Freeze On Sync field */ - SpiritSpiReadRegisters(AGCCTRL2_BASE, 1, &tempRegValue); - if(xNewState == S_ENABLE) - { - tempRegValue |= AGCCTRL2_FREEZE_ON_SYNC_MASK; - } - else - { - tempRegValue &= (~AGCCTRL2_FREEZE_ON_SYNC_MASK); - } - - /* Sets the AGCCTRL_2 register */ - g_xStatus = SpiritSpiWriteRegisters(AGCCTRL2_BASE, 1, &tempRegValue); - -} - - -/** -* @brief Enable or Disable the AGC to start with max attenuation. -* @param xNewState new state for AGC start with max attenuation mode. -* This parameter can be: S_ENABLE or S_DISABLE. -* @retval None. -*/ -void SpiritRadioAGCStartMaxAttenuation(SpiritFunctionalState xNewState) -{ - uint8_t tempRegValue = 0x00; - - /* Check the parameters */ - s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState)); - - /* Reads the AGCCTRL_2 register and configure the AGC Start Max Attenuation field */ - SpiritSpiReadRegisters(AGCCTRL2_BASE, 1, &tempRegValue); - if(xNewState == S_ENABLE) - { - tempRegValue |= AGCCTRL2_START_MAX_ATTENUATION_MASK; - } - else - { - tempRegValue &= (~AGCCTRL2_START_MAX_ATTENUATION_MASK); - } - - /* Sets the AGCCTRL_2 register */ - g_xStatus = SpiritSpiWriteRegisters(AGCCTRL2_BASE, 1, &tempRegValue); - -} - - -/** -* @brief Sets the AGC measure time. -* @param nTime AGC measure time expressed in us. This parameter shall be in the range [0, 393216/F_Xo]. -* @retval None. -*/ -void SpiritRadioSetAGCMeasureTimeUs(uint16_t nTime) -{ - uint8_t tempRegValue, measure; - - /* Check the parameter */ - s_assert_param(IS_AGC_MEASURE_TIME_US(nTime,s_lXtalFrequency)); - - /* Reads the AGCCTRL_2 register */ - SpiritSpiReadRegisters(AGCCTRL2_BASE, 1, &tempRegValue); - - /* Calculates the measure time value to write in the register */ - measure = (uint8_t)lroundf(log2((float)nTime/1e6 * s_lXtalFrequency/12)); - (measure>15) ? (measure=15):(measure); - - /* Mask the MEAS_TIME field and write the new value */ - tempRegValue &= 0xF0; - tempRegValue |= measure; - - /* Sets the AGCCTRL_2 register */ - g_xStatus = SpiritSpiWriteRegisters(AGCCTRL2_BASE, 1, &tempRegValue); - -} - - -/** -* @brief Returns the AGC measure time. -* @param None. -* @retval uint16_t AGC measure time expressed in us. This parameter will be in the range [0, 393216/F_Xo]. -*/ -uint16_t SpiritRadioGetAGCMeasureTimeUs(void) -{ - uint8_t measure; - - /* Reads the AGCCTRL_2 register */ - g_xStatus = SpiritSpiReadRegisters(AGCCTRL2_BASE, 1, &measure); - - /* Mask the MEAS_TIME field */ - measure &= 0x0F; - - /* Calculates the measure time value to write in the register */ - return (uint16_t)((12.0/s_lXtalFrequency)*(float)pow(2,measure)*1e6); - -} - - -/** -* @brief Sets the AGC measure time. -* @param cTime AGC measure time to write in the MEAS_TIME field of AGCCTRL_2 register. -* This parameter shall be in the range [0:15]. -* @retval None. -*/ -void SpiritRadioSetAGCMeasureTime(uint8_t cTime) -{ - uint8_t tempRegValue; - - /* Check the parameter */ - s_assert_param(IS_AGC_MEASURE_TIME(cTime)); - - /* Reads the AGCCTRL_2 register */ - SpiritSpiReadRegisters(AGCCTRL2_BASE, 1, &tempRegValue); - - /* Mask the MEAS_TIME field and write the new value */ - tempRegValue &= 0xF0; - tempRegValue |= cTime; - - /* Sets the AGCCTRL_2 register */ - g_xStatus = SpiritSpiWriteRegisters(AGCCTRL2_BASE, 1, &tempRegValue); - -} - - -/** -* @brief Returns the AGC measure time. -* @param None. -* @retval uint8_t AGC measure time read from the MEAS_TIME field of AGCCTRL_2 register. -* This parameter will be in the range [0:15]. -*/ -uint8_t SpiritRadioGetAGCMeasureTime(void) -{ - uint8_t tempRegValue; - - /* Reads the AGCCTRL_2 register, mask the MEAS_TIME field and return the value */ - g_xStatus = SpiritSpiReadRegisters(AGCCTRL2_BASE, 1, &tempRegValue); - - return (tempRegValue & 0x0F); - -} - - -/** -* @brief Sets the AGC hold time. -* @param cTime AGC hold time expressed in us. This parameter shall be in the range[0, 756/F_Xo]. -* @retval None. -*/ -void SpiritRadioSetAGCHoldTimeUs(uint8_t cTime) -{ - uint8_t tempRegValue, hold; - - /* Check the parameter */ - s_assert_param(IS_AGC_HOLD_TIME_US(cTime,s_lXtalFrequency)); - - /* Reads the AGCCTRL_0 register */ - SpiritSpiReadRegisters(AGCCTRL0_BASE, 1, &tempRegValue); - - /* Calculates the hold time value to write in the register */ - hold = (uint8_t)lroundf(((float)cTime/1e6 * s_lXtalFrequency)/12); - (hold>63) ? (hold=63):(hold); - - /* Mask the HOLD_TIME field and write the new value */ - tempRegValue &= 0xC0; - tempRegValue |= hold; - - /* Sets the AGCCTRL_0 register */ - g_xStatus = SpiritSpiWriteRegisters(AGCCTRL0_BASE, 1, &tempRegValue); - -} - - -/** -* @brief Returns the AGC hold time. -* @param None. -* @retval uint8_t AGC hold time expressed in us. This parameter will be in the range: -* [0, 756/F_Xo]. -*/ -uint8_t SpiritRadioGetAGCHoldTimeUs(void) -{ - uint8_t tempRegValue; - - /* Reads the AGCCTRL_0 register */ - g_xStatus = SpiritSpiReadRegisters(AGCCTRL0_BASE, 1, &tempRegValue); - - /* Mask the HOLD_TIME field */ - tempRegValue &= 0x3F; - - /* Calculates the hold time value and return it */ - return (uint8_t)lroundf ((12.0/s_lXtalFrequency)*(tempRegValue*1e6)); - -} - - -/** -* @brief Sets the AGC hold time. -* @param cTime AGC hold time to write in the HOLD_TIME field of AGCCTRL_0 register. -* This parameter shall be in the range [0:63]. -* @retval None. -*/ -void SpiritRadioSetAGCHoldTime(uint8_t cTime) -{ - uint8_t tempRegValue; - - /* Check the parameter */ - s_assert_param(IS_AGC_HOLD_TIME(cTime)); - - /* Reads the AGCCTRL_0 register */ - SpiritSpiReadRegisters(AGCCTRL0_BASE, 1, &tempRegValue); - - /* Mask the HOLD_TIME field and write the new value */ - tempRegValue &= 0xC0; - tempRegValue |= cTime; - - /* Sets the AGCCTRL_0 register */ - g_xStatus = SpiritSpiWriteRegisters(AGCCTRL0_BASE, 1, &tempRegValue); - -} - - -/** -* @brief Returns the AGC hold time. -* @param None. -* @retval uint8_t AGC hold time read from the HOLD_TIME field of AGCCTRL_0 register. -* This parameter will be in the range [0:63]. -*/ -uint8_t SpiritRadioGetAGCHoldTime(void) -{ - uint8_t tempRegValue; - - /* Reads the AGCCTRL_0 register, mask the MEAS_TIME field and return the value */ - g_xStatus = SpiritSpiReadRegisters(AGCCTRL0_BASE, 1, &tempRegValue); - - return (tempRegValue & 0x3F); - -} - - -/** -* @brief Sets the AGC high threshold. -* @param cHighThreshold AGC high threshold to write in the THRESHOLD_HIGH field of AGCCTRL_1 register. -* This parameter shall be in the range [0:15]. -* @retval None. -*/ -void SpiritRadioSetAGCHighThreshold(uint8_t cHighThreshold) -{ - uint8_t tempRegValue; - - /* Check the parameter */ - s_assert_param(IS_AGC_THRESHOLD(cHighThreshold)); - - /* Reads the AGCCTRL_1 register */ - SpiritSpiReadRegisters(AGCCTRL1_BASE, 1, &tempRegValue); - - /* Mask the THRESHOLD_HIGH field and write the new value */ - tempRegValue &= 0x0F; - tempRegValue |= cHighThreshold<<4; - - /* Sets the AGCCTRL_1 register */ - g_xStatus = SpiritSpiWriteRegisters(AGCCTRL1_BASE, 1, &tempRegValue); - -} - - -/** -* @brief Returns the AGC high threshold. -* @param None. -* @retval uint8_t AGC high threshold read from the THRESHOLD_HIGH field of AGCCTRL_1 register. -* This parameter will be in the range [0:15]. -*/ -uint8_t SpiritRadioGetAGCHighThreshold(void) -{ - uint8_t tempRegValue; - - /* Reads the AGCCTRL_1 register, mask the THRESHOLD_HIGH field and return the value */ - g_xStatus = SpiritSpiReadRegisters(AGCCTRL1_BASE, 1, &tempRegValue); - - return ((tempRegValue & 0xF0)>>4); - -} - - -/** -* @brief Sets the AGC low threshold. -* @param cLowThreshold AGC low threshold to write in the THRESHOLD_LOW field of AGCCTRL_1 register. -* This parameter shall be in the range [0:15]. -* @retval None. -*/ -void SpiritRadioSetAGCLowThreshold(uint8_t cLowThreshold) -{ - uint8_t tempRegValue; - - /* Check the parameter */ - s_assert_param(IS_AGC_THRESHOLD(cLowThreshold)); - - /* Reads the AGCCTRL_1 register */ - SpiritSpiReadRegisters(AGCCTRL1_BASE, 1, &tempRegValue); - - /* Mask the THRESHOLD_LOW field and write the new value */ - tempRegValue &= 0xF0; - tempRegValue |= cLowThreshold; - - /* Sets the AGCCTRL_1 register */ - g_xStatus = SpiritSpiWriteRegisters(AGCCTRL1_BASE, 1, &tempRegValue); - -} - - -/** -* @brief Returns the AGC low threshold. -* @param None. -* @retval uint8_t AGC low threshold read from the THRESHOLD_LOW field of AGCCTRL_1 register. -* This parameter will be in the range [0:15]. -*/ -uint8_t SpiritRadioGetAGCLowThreshold(void) -{ - uint8_t tempRegValue; - - /* Reads the AGCCTRL_1 register, mask the THRESHOLD_LOW field and return the value */ - g_xStatus = SpiritSpiReadRegisters(AGCCTRL1_BASE, 1, &tempRegValue); - - return (tempRegValue & 0x0F); - -} - - -/** -* @brief Sets the clock recovery algorithm. -* @param xMode the Clock Recovery mode. This parameter can be one of the values defined in @ref ClkRecMode : -* @arg CLK_REC_PLL PLL alogrithm for clock recovery -* @arg CLK_REC_DLL DLL alogrithm for clock recovery -* @retval None. -*/ -void SpiritRadioSetClkRecMode(ClkRecMode xMode) -{ - uint8_t tempRegValue; - - /* Check the parameter */ - s_assert_param(IS_CLK_REC_MODE(xMode)); - - /* Reads the FDEV_0 register */ - SpiritSpiReadRegisters(FDEV0_BASE, 1, &tempRegValue); - - /* Mask the CLOCK_REC_ALGO_SEL field and write the new value */ - tempRegValue &= 0xF7; - tempRegValue |= (uint8_t)xMode; - - /* Sets the FDEV_0 register */ - g_xStatus = SpiritSpiWriteRegisters(FDEV0_BASE, 1, &tempRegValue); - -} - - -/** -* @brief Returns the Clock Recovery working mode. -* @param None. -* @retval ClkRecMode Clock Recovery mode. This parameter can be one of the values defined in @ref ClkRecMode : -* @arg CLK_REC_PLL PLL alogrithm for clock recovery -* @arg CLK_REC_DLL DLL alogrithm for clock recovery -*/ -ClkRecMode SpiritRadioGetClkRecMode(void) -{ - uint8_t tempRegValue; - - /* Reads the FDEV_0 register, mask the CLOCK_REC_ALGO_SEL field and return the value */ - g_xStatus = SpiritSpiReadRegisters(FDEV0_BASE, 1, &tempRegValue); - - return (ClkRecMode)(tempRegValue & 0x08); - -} - - -/** -* @brief Sets the clock recovery proportional gain. -* @param cPGain the Clock Recovery proportional gain to write in the CLK_REC_P_GAIN field of CLOCKREC register. -* It represents is log2 value of the clock recovery proportional gain. -* This parameter shall be in the range [0:7]. -* @retval None. -*/ -void SpiritRadioSetClkRecPGain(uint8_t cPGain) -{ - uint8_t tempRegValue; - - /* Check the parameter */ - s_assert_param(IS_CLK_REC_P_GAIN(cPGain)); - - /* Reads the CLOCKREC register */ - SpiritSpiReadRegisters(CLOCKREC_BASE, 1, &tempRegValue); - - /* Mask the CLK_REC_P_GAIN field and write the new value */ - tempRegValue &= 0x1F; - tempRegValue |= (cPGain<<5); - - /* Sets the CLOCKREC register */ - g_xStatus = SpiritSpiWriteRegisters(CLOCKREC_BASE, 1, &tempRegValue); - -} - - -/** -* @brief Returns the log2 of the clock recovery proportional gain. -* @param None. -* @retval uint8_t Clock Recovery proportional gain read from the CLK_REC_P_GAIN field of CLOCKREC register. -* This parameter will be in the range [0:7]. -*/ -uint8_t SpiritRadioGetClkRecPGain(void) -{ - uint8_t tempRegValue; - - /* Reads the CLOCKREC register, mask the CLK_REC_P_GAIN field and return the value */ - g_xStatus = SpiritSpiReadRegisters(CLOCKREC_BASE, 1, &tempRegValue); - - return ((tempRegValue & 0xEF)>>5); - -} - - -/** -* @brief Sets the clock recovery integral gain. -* @param cIGain the Clock Recovery integral gain to write in the CLK_REC_I_GAIN field of CLOCKREC register. -* This parameter shall be in the range [0:15]. -* @retval None. -*/ -void SpiritRadioSetClkRecIGain(uint8_t cIGain) -{ - uint8_t tempRegValue; - - /* Check the parameter */ - s_assert_param(IS_CLK_REC_I_GAIN(cIGain)); - - /* Reads the CLOCKREC register */ - SpiritSpiReadRegisters(CLOCKREC_BASE, 1, &tempRegValue); - - /* Mask the CLK_REC_P_GAIN field and write the new value */ - tempRegValue &= 0xF0; - tempRegValue |= cIGain; - - /* Sets the CLOCKREC register */ - g_xStatus = SpiritSpiWriteRegisters(CLOCKREC_BASE, 1, &tempRegValue); - -} - - -/** -* @brief Returns the clock recovery integral gain. -* @param None. -* @retval uint8_t Clock Recovery integral gain read from the -* CLK_REC_I_GAIN field of CLOCKREC register. -* This parameter will be in the range [0:15]. -*/ -uint8_t SpiritRadioGetClkRecIGain(void) -{ - uint8_t tempRegValue; - - /* Reads the CLOCKREC register, mask the CLK_REC_I_GAIN field and return the value */ - g_xStatus = SpiritSpiReadRegisters(CLOCKREC_BASE, 1, &tempRegValue); - - return (tempRegValue & 0x0F); - -} - - -/** -* @brief Sets the postfilter length for clock recovery algorithm. -* @param xLength the postfilter length in symbols. This parameter can be one of the values defined in @ref PstFltLength : -* @arg PSTFLT_LENGTH_8 Postfilter length is 8 symbols -* @arg PSTFLT_LENGTH_16 Postfilter length is 16 symbols -* @retval None. -*/ -void SpiritRadioSetClkRecPstFltLength(PstFltLength xLength) -{ - uint8_t tempRegValue; - - /* Check the parameter */ - s_assert_param(IS_PST_FLT_LENGTH(xLength)); - - /* Reads the CLOCKREC register */ - SpiritSpiReadRegisters(CLOCKREC_BASE, 1, &tempRegValue); - - /* Mask the PSTFLT_LEN field and write the new value */ - tempRegValue &= 0xEF; - tempRegValue |= (uint8_t)xLength; - - /* Sets the CLOCKREC register */ - g_xStatus = SpiritSpiWriteRegisters(CLOCKREC_BASE, 1, &tempRegValue); - -} - - -/** -* @brief Returns the postfilter length for clock recovery algorithm. -* @param None. -* @retval PstFltLength Postfilter length in symbols. This parameter can be one of the values defined in @ref PstFltLength : -* @arg PSTFLT_LENGTH_8 Postfilter length is 8 symbols -* @arg PSTFLT_LENGTH_16 Postfilter length is 16 symbols -*/ -PstFltLength SpiritRadioGetClkRecPstFltLength(void) -{ - uint8_t tempRegValue; - - /* Reads the CLOCKREC register, mask the PSTFLT_LEN field and return the value */ - g_xStatus = SpiritSpiReadRegisters(CLOCKREC_BASE, 1, &tempRegValue); - - return (PstFltLength)(tempRegValue & 0x10); - -} - - -/** -* @brief Enables or Disables the received data blanking when the CS is under the threshold. -* @param xNewState new state of this mode. -* This parameter can be: S_ENABLE or S_DISABLE . -* @retval None. -*/ -void SpiritRadioCsBlanking(SpiritFunctionalState xNewState) -{ - uint8_t tempRegValue; - - /* Check the parameters */ - s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState)); - - /* Reads the ANT_SELECT_CONF_BASE and mask the CS_BLANKING BIT field */ - SpiritSpiReadRegisters(ANT_SELECT_CONF_BASE, 1, &tempRegValue); - - if(xNewState == S_ENABLE) - { - tempRegValue |= ANT_SELECT_CS_BLANKING_MASK; - } - else - { - tempRegValue &= (~ANT_SELECT_CS_BLANKING_MASK); - } - - /* Writes the new value in the ANT_SELECT_CONF register */ - g_xStatus = SpiritSpiWriteRegisters(ANT_SELECT_CONF_BASE, 1, &tempRegValue); - - -} - -/** -* @brief Enables or Disables the persistent RX mode. -* @param xNewState new state of this mode. -* This parameter can be: S_ENABLE or S_DISABLE . -* @retval None. -*/ -void SpiritRadioPersistenRx(SpiritFunctionalState xNewState) -{ - uint8_t tempRegValue; - - /* Check the parameters */ - s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState)); - - /* Reads the PROTOCOL0_BASE and mask the PROTOCOL0_PERS_RX_MASK bitfield */ - SpiritSpiReadRegisters(PROTOCOL0_BASE, 1, &tempRegValue); - - if(xNewState == S_ENABLE) - { - tempRegValue |= PROTOCOL0_PERS_RX_MASK; - } - else - { - tempRegValue &= (~PROTOCOL0_PERS_RX_MASK); - } - - /* Writes the new value in the PROTOCOL0_BASE register */ - g_xStatus = SpiritSpiWriteRegisters(PROTOCOL0_BASE, 1, &tempRegValue); - -} - -/** -* @brief Enables or Disables the synthesizer reference divider. -* @param xNewState new state for synthesizer reference divider. -* This parameter can be: S_ENABLE or S_DISABLE . -* @retval None. -*/ -void SpiritRadioSetRefDiv(SpiritFunctionalState xNewState) -{ - uint8_t tempRegValue; - - /* Check the parameters */ - s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState)); - - /* Reads the SYNTH_CONFIG1_BASE and mask the REFDIV bit field */ - SpiritSpiReadRegisters(SYNTH_CONFIG1_BASE, 1, &tempRegValue); - - if(xNewState == S_ENABLE) - { - tempRegValue |= 0x80; - } - else - { - tempRegValue &= 0x7F; - } - - /* Writes the new value in the SYNTH_CONFIG1_BASE register */ - g_xStatus = SpiritSpiWriteRegisters(SYNTH_CONFIG1_BASE, 1, &tempRegValue); - -} - -/** -* @brief Get the the synthesizer reference divider state. -* @param void. -* @retval None. -*/ -SpiritFunctionalState SpiritRadioGetRefDiv(void) -{ - uint8_t tempRegValue; - - g_xStatus = SpiritSpiReadRegisters(SYNTH_CONFIG1_BASE, 1, &tempRegValue); - - if(((tempRegValue>>7)&0x1)) - { - return S_ENABLE; - } - else - { - return S_DISABLE; - } - -} - -/** -* @brief Enables or Disables the synthesizer reference divider. -* @param xNewState new state for synthesizer reference divider. -* This parameter can be: S_ENABLE or S_DISABLE . -* @retval None. -*/ -void SpiritRadioSetDigDiv(SpiritFunctionalState xNewState) -{ - uint8_t tempRegValue; - - /* Check the parameters */ - s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState)); - - /* Reads the XO_RCO_TEST_BASE and mask the PD_CLKDIV bit field */ - SpiritSpiReadRegisters(XO_RCO_TEST_BASE, 1, &tempRegValue); - - if(xNewState == S_ENABLE) - { - tempRegValue &= 0xf7; - } - else - { - - tempRegValue |= 0x08; - } - - /* Writes the new value in the XO_RCO_TEST_BASE register */ - g_xStatus = SpiritSpiWriteRegisters(XO_RCO_TEST_BASE, 1, &tempRegValue); - -} - -/** -* @brief Get the the synthesizer reference divider state. -* @param void. -* @retval None. -*/ -SpiritFunctionalState SpiritRadioGetDigDiv(void) -{ - uint8_t tempRegValue; - - g_xStatus = SpiritSpiReadRegisters(XO_RCO_TEST_BASE, 1, &tempRegValue); - - if(((tempRegValue>>3)&0x1)) - { - return S_DISABLE; - } - else - { - return S_ENABLE; - } - -} - -/** -* @brief Returns the XTAL frequency. -* @param void. -* @retval uint32_t XTAL frequency. -*/ -uint32_t SpiritRadioGetXtalFrequency(void) -{ - return s_lXtalFrequency; -} - -/** -* @brief Sets the XTAL frequency. -* @param uint32_t XTAL frequency. -* @retval void. -*/ -void SpiritRadioSetXtalFrequency(uint32_t lXtalFrequency) -{ - s_lXtalFrequency = lXtalFrequency; -} - -/** -* @} -*/ - - -/** -* @} -*/ - - -/** -* @} -*/ - - - -/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/ - +/** + ****************************************************************************** + * @file SPIRIT_Radio.c + * @author VMA division - AMS + * @version 3.2.2 + * @date 08-July-2015 + * @brief This file provides all the low level API to manage Analog and Digital + * radio part of SPIRIT. + * @details + * + * @attention + * + * <h2><center>© COPYRIGHT(c) 2015 STMicroelectronics</center></h2> + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "SPIRIT_Radio.h" +#include "MCU_Interface.h" +#include <math.h> + +/** @addtogroup SPIRIT_Libraries +* @{ +*/ + + +/** @addtogroup SPIRIT_Radio +* @{ +*/ + + +/** @defgroup Radio_Private_TypesDefinitions Radio Private Types Definitions +* @{ +*/ + + +/** +* @} +*/ + + +/** @defgroup Radio_Private_Defines Radio Private Defines +* @{ +*/ + + + + +/** +* @} +*/ + + +/** @defgroup Radio_Private_Macros Radio Private Macros +* @{ +*/ +#define XTAL_FLAG(xtalFrequency) (xtalFrequency>=25e6) ? XTAL_FLAG_26_MHz:XTAL_FLAG_24_MHz + +#define ROUND(A) (((A-(uint32_t)A)> 0.5)? (uint32_t)A+1:(uint32_t)A) +/** +* @} +*/ + + +/** @defgroup Radio_Private_Variables Radio Private Variables +* @{ +*/ +/** +* @brief The Xtal frequency. To be set by the user (see SetXtalFreq() function) +*/ +static uint32_t s_lXtalFrequency; + +/** +* @brief Factor is: B/2 used in the formula for SYNTH word calculation +*/ +static const uint8_t s_vectcBHalfFactor[4]={(HIGH_BAND_FACTOR/2), (MIDDLE_BAND_FACTOR/2), (LOW_BAND_FACTOR/2), (VERY_LOW_BAND_FACTOR/2)}; + +/** +* @brief BS value to write in the SYNT0 register according to the selected band +*/ +static const uint8_t s_vectcBandRegValue[4]={SYNT0_BS_6, SYNT0_BS_12, SYNT0_BS_16, SYNT0_BS_32}; + + +/** +* @brief It represents the available channel bandwidth times 10 for 26 Mhz xtal. +* @note The channel bandwidth for others xtal frequencies can be computed since this table +* multiplying the current table by a factor xtal_frequency/26e6. +*/ +static const uint16_t s_vectnBandwidth26M[90]= +{ + 8001, 7951, 7684, 7368, 7051, 6709, 6423, 5867, 5414, \ + 4509, 4259, 4032, 3808, 3621, 3417, 3254, 2945, 2703, \ + 2247, 2124, 2015, 1900, 1807, 1706, 1624, 1471, 1350, \ + 1123, 1062, 1005, 950, 903, 853, 812, 735, 675, \ + 561, 530, 502, 474, 451, 426, 406, 367, 337, \ + 280, 265, 251, 237, 226, 213, 203, 184, 169, \ + 140, 133, 126, 119, 113, 106, 101, 92, 84, \ + 70, 66, 63, 59, 56, 53, 51, 46, 42, \ + 35, 33, 31, 30, 28, 27, 25, 23, 21, \ + 18, 17, 16, 15, 14, 13, 13, 12, 11 +}; + +/** +* @brief It represents the available VCO frequencies +*/ +static const uint16_t s_vectnVCOFreq[16]= +{ + 4644, 4708, 4772, 4836, 4902, 4966, 5030, 5095, \ + 5161, 5232, 5303, 5375, 5448, 5519, 5592, 5663 +}; + +/** +* @brief This variable is used to enable or disable +* the VCO calibration WA called at the end of the SpiritRadioSetFrequencyBase fcn. +* Default is enabled. +*/ +static SpiritFunctionalState xDoVcoCalibrationWA=S_ENABLE; + + +/** +* @brief These values are used to interpolate the power curves. +* Interpolation curves are linear in the following 3 regions: +* - reg value: 1 to 13 (up region) +* - reg value: 13 to 40 (mid region) +* - reg value: 41 to 90 (low region) +* power_reg = m*power_dBm + q +* For each band the order is: {m-up, q-up, m-mid, q-mid, m-low, q-low}. +* @note The power interpolation curves have been extracted +* by measurements done on the divisional evaluation boards. +*/ +static const float fPowerFactors[5][6]={ + {-2.11,25.66,-2.11,25.66,-2.00,31.28}, /* 915 */ + {-2.04,23.45,-2.04,23.45,-1.95,27.66}, /* 868 */ + {-3.48,38.45,-1.89,27.66,-1.92,30.23}, /* 433 */ + {-3.27,35.43,-1.80,26.31,-1.89,29.61}, /* 315 */ + {-4.18,50.66,-1.80,30.04,-1.86,32.22}, /* 169 */ +}; + +/** +* @} +*/ + + +/** @defgroup Radio_Private_FunctionPrototypes Radio Private Function Prototypes +* @{ +*/ + + +/** +* @} +*/ + + +/** @defgroup Radio_Private_Functions Radio Private Functions +* @{ +*/ + +/** +* @brief Initializes the SPIRIT analog and digital radio part according to the specified +* parameters in the pxSRadioInitStruct. +* @param pxSRadioInitStruct pointer to a SRadioInit structure that +* contains the configuration information for the analog radio part of SPIRIT. +* @retval Error code: 0=no error, 1=error during calibration of VCO. +*/ +uint8_t SpiritRadioInit(SRadioInit* pxSRadioInitStruct) +{ + int32_t FOffsetTmp; + uint8_t anaRadioRegArray[8], digRadioRegArray[4]; + int16_t xtalOffsetFactor; + uint8_t drM, drE, FdevM, FdevE, bwM, bwE; + + /* Workaround for Vtune */ + uint8_t value = 0xA0; SpiritSpiWriteRegisters(0x9F, 1, &value); + + /* Calculates the offset respect to RF frequency and according to xtal_ppm parameter: (xtal_ppm*FBase)/10^6 */ + FOffsetTmp = (int32_t)(((float)pxSRadioInitStruct->nXtalOffsetPpm*pxSRadioInitStruct->lFrequencyBase)/PPM_FACTOR); + + /* Check the parameters */ + s_assert_param(IS_FREQUENCY_BAND(pxSRadioInitStruct->lFrequencyBase)); + s_assert_param(IS_MODULATION_SELECTED(pxSRadioInitStruct->xModulationSelect)); + s_assert_param(IS_DATARATE(pxSRadioInitStruct->lDatarate)); + s_assert_param(IS_FREQUENCY_OFFSET(FOffsetTmp,s_lXtalFrequency)); + s_assert_param(IS_CHANNEL_SPACE(pxSRadioInitStruct->nChannelSpace,s_lXtalFrequency)); + s_assert_param(IS_F_DEV(pxSRadioInitStruct->lFreqDev,s_lXtalFrequency)); + + /* Disable the digital, ADC, SMPS reference clock divider if fXO>24MHz or fXO<26MHz */ + SpiritSpiCommandStrobes(COMMAND_STANDBY); + do{ + /* Delay for state transition */ + for(volatile uint8_t i=0; i!=0xFF; i++); + + /* Reads the MC_STATUS register */ + SpiritRefreshStatus(); + }while(g_xStatus.MC_STATE!=MC_STATE_STANDBY); + + if(s_lXtalFrequency<DOUBLE_XTAL_THR) + { + SpiritRadioSetDigDiv(S_DISABLE); + s_assert_param(IS_CH_BW(pxSRadioInitStruct->lBandwidth,s_lXtalFrequency)); + } + else + { + SpiritRadioSetDigDiv(S_ENABLE); + s_assert_param(IS_CH_BW(pxSRadioInitStruct->lBandwidth,(s_lXtalFrequency>>1))); + } + + /* Goes in READY state */ + SpiritSpiCommandStrobes(COMMAND_READY); + do{ + /* Delay for state transition */ + for(volatile uint8_t i=0; i!=0xFF; i++); + + /* Reads the MC_STATUS register */ + SpiritRefreshStatus(); + }while(g_xStatus.MC_STATE!=MC_STATE_READY); + + /* Calculates the FC_OFFSET parameter and cast as signed int: FOffsetTmp = (Fxtal/2^18)*FC_OFFSET */ + xtalOffsetFactor = (int16_t)(((float)FOffsetTmp*FBASE_DIVIDER)/s_lXtalFrequency); + anaRadioRegArray[2] = (uint8_t)((((uint16_t)xtalOffsetFactor)>>8)&0x0F); + anaRadioRegArray[3] = (uint8_t)(xtalOffsetFactor); + + /* Calculates the channel space factor */ + anaRadioRegArray[0] =((uint32_t)pxSRadioInitStruct->nChannelSpace<<9)/(s_lXtalFrequency>>6)+1; + + SpiritManagementWaTRxFcMem(pxSRadioInitStruct->lFrequencyBase); + + /* 2nd order DEM algorithm enabling */ + uint8_t tmpreg; SpiritSpiReadRegisters(0xA3, 1, &tmpreg); + tmpreg &= ~0x02; SpiritSpiWriteRegisters(0xA3, 1, &tmpreg); + + /* Check the channel center frequency is in one of the possible range */ + s_assert_param(IS_FREQUENCY_BAND((pxSRadioInitStruct->lFrequencyBase + ((xtalOffsetFactor*s_lXtalFrequency)/FBASE_DIVIDER) + pxSRadioInitStruct->nChannelSpace * pxSRadioInitStruct->cChannelNumber))); + + /* Calculates the datarate mantissa and exponent */ + SpiritRadioSearchDatarateME(pxSRadioInitStruct->lDatarate, &drM, &drE); + digRadioRegArray[0] = (uint8_t)(drM); + digRadioRegArray[1] = (uint8_t)(0x00 | pxSRadioInitStruct->xModulationSelect |drE); + + /* Read the fdev register to preserve the clock recovery algo bit */ + SpiritSpiReadRegisters(0x1C, 1, &tmpreg); + + /* Calculates the frequency deviation mantissa and exponent */ + SpiritRadioSearchFreqDevME(pxSRadioInitStruct->lFreqDev, &FdevM, &FdevE); + digRadioRegArray[2] = (uint8_t)((FdevE<<4) | (tmpreg&0x08) | FdevM); + + /* Calculates the channel filter mantissa and exponent */ + SpiritRadioSearchChannelBwME(pxSRadioInitStruct->lBandwidth, &bwM, &bwE); + + digRadioRegArray[3] = (uint8_t)((bwM<<4) | bwE); + + float if_off=(3.0*480140)/(s_lXtalFrequency>>12)-64; + + uint8_t ifOffsetAna = ROUND(if_off); + + if(s_lXtalFrequency<DOUBLE_XTAL_THR) + { + /* if offset digital is the same in case of single xtal */ + anaRadioRegArray[1] = ifOffsetAna; + } + else + { + if_off=(3.0*480140)/(s_lXtalFrequency>>13)-64; + + /* ... otherwise recompute it */ + anaRadioRegArray[1] = ROUND(if_off); + } +// if(s_lXtalFrequency==24000000) { +// ifOffsetAna = 0xB6; +// anaRadioRegArray[1] = 0xB6; +// } +// if(s_lXtalFrequency==25000000) { +// ifOffsetAna = 0xAC; +// anaRadioRegArray[1] = 0xAC; +// } +// if(s_lXtalFrequency==26000000) { +// ifOffsetAna = 0xA3; +// anaRadioRegArray[1] = 0xA3; +// } +// if(s_lXtalFrequency==48000000) { +// ifOffsetAna = 0x3B; +// anaRadioRegArray[1] = 0xB6; +// } +// if(s_lXtalFrequency==50000000) { +// ifOffsetAna = 0x36; +// anaRadioRegArray[1] = 0xAC; +// } +// if(s_lXtalFrequency==52000000) { +// ifOffsetAna = 0x31; +// anaRadioRegArray[1] = 0xA3; +// } + + g_xStatus = SpiritSpiWriteRegisters(IF_OFFSET_ANA_BASE, 1, &ifOffsetAna); + + + /* Sets Xtal configuration */ + if(s_lXtalFrequency>DOUBLE_XTAL_THR) + { + SpiritRadioSetXtalFlag(XTAL_FLAG((s_lXtalFrequency/2))); + } + else + { + SpiritRadioSetXtalFlag(XTAL_FLAG(s_lXtalFrequency)); + } + + /* Sets the channel number in the corresponding register */ + SpiritSpiWriteRegisters(CHNUM_BASE, 1, &pxSRadioInitStruct->cChannelNumber); + + /* Configures the Analog Radio registers */ + SpiritSpiWriteRegisters(CHSPACE_BASE, 4, anaRadioRegArray); + + /* Configures the Digital Radio registers */ + g_xStatus = SpiritSpiWriteRegisters(MOD1_BASE, 4, digRadioRegArray); + + /* Enable the freeze option of the AFC on the SYNC word */ + SpiritRadioAFCFreezeOnSync(S_ENABLE); + + /* Set the IQC correction optimal value */ + anaRadioRegArray[0]=0x80; + anaRadioRegArray[1]=0xE3; + g_xStatus = SpiritSpiWriteRegisters(0x99, 2, anaRadioRegArray); + + return SpiritRadioSetFrequencyBase(pxSRadioInitStruct->lFrequencyBase); + +} + + +/** +* @brief Returns the SPIRIT analog and digital radio structure according to the registers value. +* @param pxSRadioInitStruct pointer to a SRadioInit structure that +* contains the configuration information for the analog radio part of SPIRIT. +* @retval None. +*/ +void SpiritRadioGetInfo(SRadioInit* pxSRadioInitStruct) +{ + uint8_t anaRadioRegArray[8], digRadioRegArray[4]; + BandSelect band; + int16_t xtalOffsetFactor; + + /* Get the RF board version */ + //SpiritVersion xSpiritVersion = SpiritGeneralGetSpiritVersion(); + + /* Reads the Analog Radio registers */ + SpiritSpiReadRegisters(SYNT3_BASE, 8, anaRadioRegArray); + + /* Reads the Digital Radio registers */ + g_xStatus = SpiritSpiReadRegisters(MOD1_BASE, 4, digRadioRegArray); + + /* Reads the operating band masking the Band selected field */ + if((anaRadioRegArray[3] & 0x07) == SYNT0_BS_6) + { + band = HIGH_BAND; + } + else if ((anaRadioRegArray[3] & 0x07) == SYNT0_BS_12) + { + band = MIDDLE_BAND; + } + else if ((anaRadioRegArray[3] & 0x07) == SYNT0_BS_16) + { + band = LOW_BAND; + } + else if ((anaRadioRegArray[3] & 0x07) == SYNT0_BS_32) + { + band = VERY_LOW_BAND; + } + else + { + /* if it is another value, set it to a valid one in order to avoid access violation */ + uint8_t tmp=(anaRadioRegArray[3]&0xF8)|SYNT0_BS_6; + SpiritSpiWriteRegisters(SYNT0_BASE,1,&tmp); + band = HIGH_BAND; + } + + /* Computes the synth word */ + uint32_t synthWord = (uint32_t)((((uint32_t)(anaRadioRegArray[0]&0x1F))<<21)+(((uint32_t)(anaRadioRegArray[1]))<<13)+\ + (((uint32_t)(anaRadioRegArray[2]))<<5)+(((uint32_t)(anaRadioRegArray[3]))>>3)); + + /* Calculates the frequency base */ + uint8_t cRefDiv = (uint8_t)SpiritRadioGetRefDiv()+1; + pxSRadioInitStruct->lFrequencyBase = (uint32_t)round(synthWord*(((double)s_lXtalFrequency)/(FBASE_DIVIDER*cRefDiv*s_vectcBHalfFactor[band]))); + + /* Calculates the Offset Factor */ + uint16_t xtalOffTemp = ((((uint16_t)anaRadioRegArray[6])<<8)+((uint16_t)anaRadioRegArray[7])); + + /* If a negative number then convert the 12 bit 2-complement in a 16 bit number */ + if(xtalOffTemp & 0x0800) + { + xtalOffTemp = xtalOffTemp | 0xF000; + } + else + { + xtalOffTemp = xtalOffTemp & 0x0FFF; + } + + xtalOffsetFactor = *((int16_t*)(&xtalOffTemp)); + + /* Calculates the frequency offset in ppm */ + pxSRadioInitStruct->nXtalOffsetPpm =(int16_t)((uint32_t)xtalOffsetFactor*s_lXtalFrequency*PPM_FACTOR)/((uint32_t)FBASE_DIVIDER*pxSRadioInitStruct->lFrequencyBase); + + /* Channel space */ + pxSRadioInitStruct->nChannelSpace = anaRadioRegArray[4]*(s_lXtalFrequency>>15); + + /* Channel number */ + pxSRadioInitStruct->cChannelNumber = SpiritRadioGetChannel(); + + /* Modulation select */ + pxSRadioInitStruct->xModulationSelect = (ModulationSelect)(digRadioRegArray[1] & 0x70); + + /* Reads the frequency deviation for mantissa and exponent */ + uint8_t FDevM = digRadioRegArray[2]&0x07; + uint8_t FDevE = (digRadioRegArray[2]&0xF0)>>4; + + /* Reads the channel filter register for mantissa and exponent */ + uint8_t bwM = (digRadioRegArray[3]&0xF0)>>4; + uint8_t bwE = digRadioRegArray[3]&0x0F; + + uint8_t cDivider = 0; + cDivider = SpiritRadioGetDigDiv(); + + /* Calculates the datarate */ + pxSRadioInitStruct->lDatarate = ((s_lXtalFrequency>>(5+cDivider))*(256+digRadioRegArray[0]))>>(23-(digRadioRegArray[1]&0x0F)); + + /* Calculates the frequency deviation */ + // (((s_lXtalFrequency>>6)*(8+FDevM))>>(12-FDevE+cCorrection)); + pxSRadioInitStruct->lFreqDev =(uint32_t)((float)s_lXtalFrequency/(((uint32_t)1)<<18)*(uint32_t)((8.0+FDevM)/2*(1<<FDevE))); + + /* Reads the channel filter bandwidth from the look-up table and return it */ + pxSRadioInitStruct->lBandwidth = (uint32_t)(100.0*s_vectnBandwidth26M[bwM+(bwE*9)]*((s_lXtalFrequency>>cDivider)/26e6)); + +} + + +/** +* @brief Sets the Xtal configuration in the ANA_FUNC_CONF0 register. +* @param xXtal one of the possible value of the enum type XtalFrequency. +* @arg XTAL_FLAG_24_MHz: in case of 24 MHz crystal +* @arg XTAL_FLAG_26_MHz: in case of 26 MHz crystal +* @retval None. +*/ +void SpiritRadioSetXtalFlag(XtalFlag xXtal) +{ + uint8_t tempRegValue = 0x00; + + /* Check the parameters */ + s_assert_param(IS_XTAL_FLAG(xXtal)); + + /* Reads the ANA_FUNC_CONF_0 register */ + g_xStatus = SpiritSpiReadRegisters(ANA_FUNC_CONF0_BASE, 1, &tempRegValue); + if(xXtal == XTAL_FLAG_26_MHz) + { + tempRegValue|=SELECT_24_26_MHZ_MASK; + } + else + { + tempRegValue &= (~SELECT_24_26_MHZ_MASK); + } + + /* Sets the 24_26MHz_SELECT field in the ANA_FUNC_CONF_0 register */ + g_xStatus = SpiritSpiWriteRegisters(ANA_FUNC_CONF0_BASE, 1, &tempRegValue); + +} + + +/** +* @brief Returns the Xtal configuration in the ANA_FUNC_CONF0 register. +* @param None. +* @retval XtalFrequency Settled Xtal configuration. +*/ +XtalFlag SpiritRadioGetXtalFlag(void) +{ + uint8_t tempRegValue; + + /* Reads the Xtal configuration in the ANA_FUNC_CONF_0 register and return the value */ + g_xStatus = SpiritSpiReadRegisters(ANA_FUNC_CONF0_BASE, 1, &tempRegValue); + + return (XtalFlag)((tempRegValue & 0x40)>>6); + +} + + +/** +* @brief Returns the charge pump word for a given VCO frequency. +* @param lFc channel center frequency expressed in Hz. +* This parameter can be a value in one of the following ranges:<ul> +* <li> High_Band: from 779 MHz to 915 MHz </li> +* <li> Middle Band: from 387 MHz to 470 MHz </li> +* <li> Low Band: from 300 MHz to 348 MHz </li> +* <li> Very low Band: from 150 MHz to 174 MHz </li> </ul> +* @retval uint8_t Charge pump word. +*/ +uint8_t SpiritRadioSearchWCP(uint32_t lFc) +{ + int8_t i; + uint32_t vcofreq; + uint8_t BFactor; + + /* Check the channel center frequency is in one of the possible range */ + s_assert_param(IS_FREQUENCY_BAND(lFc)); + + /* Search the operating band */ + if(IS_FREQUENCY_BAND_HIGH(lFc)) + { + BFactor = HIGH_BAND_FACTOR; + } + else if(IS_FREQUENCY_BAND_MIDDLE(lFc)) + { + BFactor = MIDDLE_BAND_FACTOR; + } + else if(IS_FREQUENCY_BAND_LOW(lFc)) + { + BFactor = LOW_BAND_FACTOR; + } + else + { + BFactor = VERY_LOW_BAND_FACTOR; + } + + /* Calculates the VCO frequency VCOFreq = lFc*B */ + vcofreq = (lFc/1000000)*BFactor; + + /* Search in the vco frequency array the charge pump word */ + if(vcofreq>=s_vectnVCOFreq[15]) + { + i=15; + } + else + { + /* Search the value */ + for(i=0 ; i<15 && vcofreq>s_vectnVCOFreq[i] ; i++); + + /* Be sure that it is the best approssimation */ + if (i!=0 && s_vectnVCOFreq[i]-vcofreq>vcofreq-s_vectnVCOFreq[i-1]) + i--; + } + + /* Return index */ + return (i%8); + +} + +/** +* @brief Returns the synth word. +* @param None. +* @retval uint32_t Synth word. +*/ +uint32_t SpiritRadioGetSynthWord(void) +{ + uint8_t regArray[4]; + + /* Reads the SYNTH registers, build the synth word and return it */ + g_xStatus = SpiritSpiReadRegisters(SYNT3_BASE, 4, regArray); + return ((((uint32_t)(regArray[0]&0x1F))<<21)+(((uint32_t)(regArray[1]))<<13)+\ + (((uint32_t)(regArray[2]))<<5)+(((uint32_t)(regArray[3]))>>3)); + +} + + +/** +* @brief Sets the SYNTH registers. +* @param lSynthWord the synth word to write in the SYNTH[3:0] registers. +* @retval None. +*/ +void SpiritRadioSetSynthWord(uint32_t lSynthWord) +{ + uint8_t tempArray[4]; + uint8_t tempRegValue; + + /* Reads the SYNT0 register */ + g_xStatus = SpiritSpiReadRegisters(SYNT0_BASE, 1, &tempRegValue); + + /* Mask the Band selected field */ + tempRegValue &= 0x07; + + /* Build the array for SYNTH registers */ + tempArray[0] = (uint8_t)((lSynthWord>>21)&(0x0000001F)); + tempArray[1] = (uint8_t)((lSynthWord>>13)&(0x000000FF)); + tempArray[2] = (uint8_t)((lSynthWord>>5)&(0x000000FF)); + tempArray[3] = (uint8_t)(((lSynthWord&0x0000001F)<<3)| tempRegValue); + + /* Writes the synth word in the SYNTH registers */ + g_xStatus = SpiritSpiWriteRegisters(SYNT3_BASE, 4, tempArray); + +} + + +/** +* @brief Sets the operating band. +* @param xBand the band to set. +* This parameter can be one of following parameters: +* @arg HIGH_BAND High_Band selected: from 779 MHz to 915 MHz +* @arg MIDDLE_BAND: Middle Band selected: from 387 MHz to 470 MHz +* @arg LOW_BAND: Low Band selected: from 300 MHz to 348 MHz +* @arg VERY_LOW_BAND: Very low Band selected: from 150 MHz to 174 MHz +* @retval None. +*/ +void SpiritRadioSetBand(BandSelect xBand) +{ + uint8_t tempRegValue; + + /* Check the parameters */ + s_assert_param(IS_BAND_SELECTED(xBand)); + + /* Reads the SYNT0 register*/ + g_xStatus = SpiritSpiReadRegisters(SYNT0_BASE, 1, &tempRegValue); + + /* Mask the SYNTH[4;0] field and write the BS value */ + tempRegValue &= 0xF8; + tempRegValue |= s_vectcBandRegValue[xBand]; + + /* Configures the SYNT0 register setting the operating band */ + g_xStatus = SpiritSpiWriteRegisters(SYNT0_BASE, 1, &tempRegValue); + +} + + +/** +* @brief Returns the operating band. +* @param None. +* @retval BandSelect Settled band. +* This returned value can be one of the following parameters: +* @arg HIGH_BAND High_Band selected: from 779 MHz to 915 MHz +* @arg MIDDLE_BAND: Middle Band selected: from 387 MHz to 470 MHz +* @arg LOW_BAND: Low Band selected: from 300 MHz to 348 MHz +* @arg VERY_LOW_BAND: Very low Band selected: from 150 MHz to 174 MHz +*/ +BandSelect SpiritRadioGetBand(void) +{ + uint8_t tempRegValue; + + /* Reads the SYNT0 register */ + g_xStatus = SpiritSpiReadRegisters(SYNT0_BASE, 1, &tempRegValue); + + /* Mask the Band selected field */ + if((tempRegValue & 0x07) == SYNT0_BS_6) + { + return HIGH_BAND; + } + else if ((tempRegValue & 0x07) == SYNT0_BS_12) + { + return MIDDLE_BAND; + } + else if ((tempRegValue & 0x07) == SYNT0_BS_16) + { + return LOW_BAND; + } + else + { + return VERY_LOW_BAND; + } + +} + + +/** +* @brief Sets the channel number. +* @param cChannel the channel number. +* @retval None. +*/ +void SpiritRadioSetChannel(uint8_t cChannel) +{ + /* Writes the CHNUM register */ + g_xStatus = SpiritSpiWriteRegisters(CHNUM_BASE, 1, &cChannel); + +} + + +/** +* @brief Returns the actual channel number. +* @param None. +* @retval uint8_t Actual channel number. +*/ +uint8_t SpiritRadioGetChannel(void) +{ + uint8_t tempRegValue; + + /* Reads the CHNUM register and return the value */ + g_xStatus = SpiritSpiReadRegisters(CHNUM_BASE, 1, &tempRegValue); + + return tempRegValue; + +} + + +/** +* @brief Sets the channel space factor in channel space register. +* The channel spacing step is computed as F_Xo/32768. +* @param fChannelSpace the channel space expressed in Hz. +* @retval None. +*/ +void SpiritRadioSetChannelSpace(uint32_t fChannelSpace) +{ + uint8_t cChannelSpaceFactor; + + /* Round to the nearest integer */ + cChannelSpaceFactor = ((uint32_t)fChannelSpace*CHSPACE_DIVIDER)/s_lXtalFrequency; + + /* Write value into the register */ + g_xStatus = SpiritSpiWriteRegisters(CHSPACE_BASE, 1, &cChannelSpaceFactor); + +} + + +/** +* @brief Returns the channel space register. +* @param None. +* @retval uint32_t Channel space. The channel space is: CS = channel_space_factor x XtalFrequency/2^15 +* where channel_space_factor is the CHSPACE register value. +*/ +uint32_t SpiritRadioGetChannelSpace(void) +{ + uint8_t channelSpaceFactor; + + /* Reads the CHSPACE register, calculate the channel space and return it */ + g_xStatus = SpiritSpiReadRegisters(CHSPACE_BASE, 1, &channelSpaceFactor); + + /* Compute the Hertz value and return it */ + return ((channelSpaceFactor*s_lXtalFrequency)/CHSPACE_DIVIDER); + +} + + +/** +* @brief Sets the FC OFFSET register starting from xtal ppm value. +* @param nXtalPpm the xtal offset expressed in ppm. +* @retval None. +*/ +void SpiritRadioSetFrequencyOffsetPpm(int16_t nXtalPpm) +{ + uint8_t tempArray[2]; + int16_t xtalOffsetFactor; + uint32_t synthWord, fBase; + int32_t FOffsetTmp; + BandSelect band; + + /* Reads the synth word */ + synthWord = SpiritRadioGetSynthWord(); + + /* Reads the operating band */ + band = SpiritRadioGetBand(); + + /* Calculates the frequency base */ + uint8_t cRefDiv = (uint8_t)SpiritRadioGetRefDiv()+1; + fBase = synthWord*(s_lXtalFrequency/(s_vectcBHalfFactor[band]*cRefDiv)/FBASE_DIVIDER); + + /* Calculates the offset respect to RF frequency and according to xtal_ppm parameter */ + FOffsetTmp = (int32_t)(((float)nXtalPpm*fBase)/PPM_FACTOR); + + /* Check the Offset is in the correct range */ + s_assert_param(IS_FREQUENCY_OFFSET(FOffsetTmp,s_lXtalFrequency)); + + /* Calculates the FC_OFFSET value to write in the corresponding register */ + xtalOffsetFactor = (int16_t)(((float)FOffsetTmp*FBASE_DIVIDER)/s_lXtalFrequency); + + /* Build the array related to the FC_OFFSET_1 and FC_OFFSET_0 register */ + tempArray[0]=(uint8_t)((((uint16_t)xtalOffsetFactor)>>8)&0x0F); + tempArray[1]=(uint8_t)(xtalOffsetFactor); + + /* Writes the FC_OFFSET registers */ + g_xStatus = SpiritSpiWriteRegisters(FC_OFFSET1_BASE, 2, tempArray); + +} + + +/** +* @brief Sets the FC OFFSET register starting from frequency offset expressed in Hz. +* @param lFOffset frequency offset expressed in Hz as signed word. +* @retval None. +*/ +void SpiritRadioSetFrequencyOffset(int32_t lFOffset) +{ + uint8_t tempArray[2]; + int16_t offset; + + /* Check that the Offset is in the correct range */ + s_assert_param(IS_FREQUENCY_OFFSET(lFOffset,s_lXtalFrequency)); + + /* Calculates the offset value to write in the FC_OFFSET register */ + offset = (int16_t)(((float)lFOffset*FBASE_DIVIDER)/s_lXtalFrequency); + + /* Build the array related to the FC_OFFSET_1 and FC_OFFSET_0 register */ + tempArray[0]=(uint8_t)((((uint16_t)offset)>>8)&0x0F); + tempArray[1]=(uint8_t)(offset); + + /* Writes the FC_OFFSET registers */ + g_xStatus = SpiritSpiWriteRegisters(FC_OFFSET1_BASE, 2, tempArray); + +} + + +/** +* @brief Returns the actual frequency offset. +* @param None. +* @retval int32_t Frequency offset expressed in Hz as signed word. +*/ +int32_t SpiritRadioGetFrequencyOffset(void) +{ + uint8_t tempArray[2]; + int16_t xtalOffsetFactor; + + /* Reads the FC_OFFSET registers */ + g_xStatus = SpiritSpiReadRegisters(FC_OFFSET1_BASE, 2, tempArray); + + /* Calculates the Offset Factor */ + uint16_t xtalOffTemp = ((((uint16_t)tempArray[0])<<8)+((uint16_t)tempArray[1])); + + if(xtalOffTemp & 0x0800) + { + xtalOffTemp = xtalOffTemp | 0xF000; + } + else + { + xtalOffTemp = xtalOffTemp & 0x0FFF; + } + + xtalOffsetFactor = *((int16_t*)(&xtalOffTemp)); + + /* Calculates the frequency offset and return it */ + return ((int32_t)(xtalOffsetFactor*s_lXtalFrequency)/FBASE_DIVIDER); + +} + + + +/** +* @brief Sets the Synth word and the Band Select register according to desired base carrier frequency. +* In this API the Xtal configuration is read out from +* the corresponding register. The user shall fix it before call this API. +* @param lFBase the base carrier frequency expressed in Hz as unsigned word. +* @retval Error code: 0=no error, 1=error during calibration of VCO. +*/ +uint8_t SpiritRadioSetFrequencyBase(uint32_t lFBase) +{ + uint32_t synthWord, Fc; + uint8_t band, 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 + { + 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; + + /* Selects the VCO */ + 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*s_vectcBHalfFactor[band]*(((double)(FBASE_DIVIDER*cRefDiv))/s_lXtalFrequency)); + + /* 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); + + if(xDoVcoCalibrationWA==S_ENABLE) + return SpiritManagementWaVcoCalibration(); + + return 0; +} + +/** +* @brief To say to the set frequency base if do or not the VCO calibration WA. +* @param S_ENABLE or S_DISABLE the WA procedure. +* @retval None. +*/ +void SpiritRadioVcoCalibrationWAFB(SpiritFunctionalState xNewstate) +{ + xDoVcoCalibrationWA=xNewstate; +} + +/** +* @brief Returns the base carrier frequency. +* @param None. +* @retval uint32_t Base carrier frequency expressed in Hz as unsigned word. +*/ +uint32_t SpiritRadioGetFrequencyBase(void) +{ + uint32_t synthWord; + BandSelect band; + + /* Reads the synth word */ + synthWord = SpiritRadioGetSynthWord(); + + /* Reads the operating band */ + band = SpiritRadioGetBand(); + + uint8_t cRefDiv = (uint8_t)SpiritRadioGetRefDiv() + 1; + + /* Calculates the frequency base and return it */ + return (uint32_t)round(synthWord*(((double)s_lXtalFrequency)/(FBASE_DIVIDER*cRefDiv*s_vectcBHalfFactor[band]))); +} + + +/** +* @brief Returns the actual channel center frequency. +* @param None. +* @retval uint32_t Actual channel center frequency expressed in Hz. +*/ +uint32_t SpiritRadioGetCenterFrequency(void) +{ + int32_t offset; + uint8_t channel; + uint32_t fBase; + uint32_t channelSpace; + + /* Reads the frequency base */ + fBase = SpiritRadioGetFrequencyBase(); + + /* Reads the frequency offset */ + offset = SpiritRadioGetFrequencyOffset(); + + /* Reads the channel space */ + channelSpace = SpiritRadioGetChannelSpace(); + + /* Reads the channel number */ + channel = SpiritRadioGetChannel(); + + /* Calculates the channel center frequency and return it */ + return (uint32_t)(fBase + offset + (uint32_t)(channelSpace*channel)); + +} + + +/** +* @brief Returns the mantissa and exponent, whose value used in the datarate formula +* will give the datarate value closer to the given datarate. +* @param fDatarate datarate expressed in bps. This parameter ranging between 100 and 500000. +* @param pcM pointer to the returned mantissa value. +* @param pcE pointer to the returned exponent value. +* @retval None. +*/ +void SpiritRadioSearchDatarateME(uint32_t lDatarate, uint8_t* pcM, uint8_t* pcE) +{ + volatile SpiritBool find = S_FALSE; + int8_t i=15; + uint8_t cMantissaTmp; + uint8_t cDivider = 0; + + /* Check the parameters */ + s_assert_param(IS_DATARATE(lDatarate)); + + cDivider = (uint8_t)SpiritRadioGetDigDiv(); + + /* Search in the datarate array the exponent value */ + while(!find && i>=0) + { + if(lDatarate>=(s_lXtalFrequency>>(20-i+cDivider))) + { + find = S_TRUE; + } + else + { + i--; + } + } + i<0 ? i=0 : i; + *pcE = i; + + /* Calculates the mantissa value according to the datarate formula */ + cMantissaTmp = (lDatarate*((uint32_t)1<<(23-i)))/(s_lXtalFrequency>>(5+cDivider))-256; + + /* Finds the mantissa value with less approximation */ + int16_t mantissaCalculation[3]; + for(uint8_t j=0;j<3;j++) + { + if((cMantissaTmp+j-1)) + { + mantissaCalculation[j]=lDatarate-(((256+cMantissaTmp+j-1)*(s_lXtalFrequency>>(5+cDivider)))>>(23-i)); + } + else + { + mantissaCalculation[j]=0x7FFF; + } + } + uint16_t mantissaCalculationDelta = 0xFFFF; + for(uint8_t j=0;j<3;j++) + { + if(S_ABS(mantissaCalculation[j])<mantissaCalculationDelta) + { + mantissaCalculationDelta = S_ABS(mantissaCalculation[j]); + *pcM = cMantissaTmp+j-1; + } + } + +} + + +/** +* @brief Returns the mantissa and exponent for a given bandwidth. +* Even if it is possible to pass as parameter any value in the below mentioned range, +* the API will search the closer value according to a fixed table of channel +* bandwidth values (@ref s_vectnBandwidth), as defined in the datasheet, returning the corresponding mantissa +* and exponent value. +* @param lBandwidth bandwidth expressed in Hz. This parameter ranging between 1100 and 800100. +* @param pcM pointer to the returned mantissa value. +* @param pcE pointer to the returned exponent value. +* @retval None. +*/ +void SpiritRadioSearchChannelBwME(uint32_t lBandwidth, uint8_t* pcM, uint8_t* pcE) +{ + int8_t i, i_tmp; + uint8_t cDivider = 1; + + /* Search in the channel filter bandwidth table the exponent value */ + if(SpiritRadioGetDigDiv()) + { + cDivider = 2; + } + else + { + cDivider = 1; + } + + s_assert_param(IS_CH_BW(lBandwidth,s_lXtalFrequency/cDivider)); + + uint32_t lChfltFactor = (s_lXtalFrequency/cDivider)/100; + + for(i=0;i<90 && (lBandwidth<(uint32_t)((s_vectnBandwidth26M[i]*lChfltFactor)/2600));i++); + + if(i!=0) + { + /* Finds the mantissa value with less approximation */ + i_tmp=i; + int16_t chfltCalculation[3]; + for(uint8_t j=0;j<3;j++) + { + if(((i_tmp+j-1)>=0) || ((i_tmp+j-1)<=89)) + { + chfltCalculation[j] = lBandwidth - (uint32_t)((s_vectnBandwidth26M[i_tmp+j-1]*lChfltFactor)/2600); + } + else + { + chfltCalculation[j] = 0x7FFF; + } + } + uint16_t chfltDelta = 0xFFFF; + + for(uint8_t j=0;j<3;j++) + { + if(S_ABS(chfltCalculation[j])<chfltDelta) + { + chfltDelta = S_ABS(chfltCalculation[j]); + i=i_tmp+j-1; + } + } + } + (*pcE) = (uint8_t)(i/9); + (*pcM) = (uint8_t)(i%9); + +} + +/** +* @brief Returns the mantissa and exponent, whose value used in the frequency deviation formula +* will give a frequency deviation value most closer to the given frequency deviation. +* @param fFDev frequency deviation expressed in Hz. This parameter can be a value in the range [F_Xo*8/2^18, F_Xo*7680/2^18]. +* @param pcM pointer to the returned mantissa value. +* @param pcE pointer to the returned exponent value. +* @retval None. +*/ +void SpiritRadioSearchFreqDevME(uint32_t lFDev, uint8_t* pcM, uint8_t* pcE) +{ + uint8_t i; + uint32_t a,bp,b=0; + float xtalDivtmp=(float)s_lXtalFrequency/(((uint32_t)1)<<18); + + /* Check the parameters */ + s_assert_param(IS_F_DEV(lFDev,s_lXtalFrequency)); + + for(i=0;i<10;i++) + { + a=(uint32_t)(xtalDivtmp*(uint32_t)(7.5*(1<<i))); + if(lFDev<a) + break; + } + (*pcE) = i; + + for(i=0;i<8;i++) + { + bp=b; + b=(uint32_t)(xtalDivtmp*(uint32_t)((8.0+i)/2*(1<<(*pcE)))); + if(lFDev<b) + break; + } + + (*pcM)=i; + if((lFDev-bp)<(b-lFDev)) + (*pcM)--; + +} + + +/** +* @brief Sets the datarate. +* @param fDatarate datarate expressed in bps. This value shall be in the range +* [100 500000]. +* @retval None. +*/ +void SpiritRadioSetDatarate(uint32_t lDatarate) +{ + uint8_t drE, tempRegValue[2]; + + /* Check the parameters */ + s_assert_param(IS_DATARATE(lDatarate)); + + /* Calculates the datarate mantissa and exponent */ + SpiritRadioSearchDatarateME(lDatarate, &tempRegValue[0], &drE); + + /* Reads the MOD_O register*/ + SpiritSpiReadRegisters(MOD0_BASE, 1, &tempRegValue[1]); + + /* Mask the other fields and set the datarate exponent */ + tempRegValue[1] &= 0xF0; + tempRegValue[1] |= drE; + + /* Writes the Datarate registers */ + g_xStatus = SpiritSpiWriteRegisters(MOD1_BASE, 2, tempRegValue); + +} + + +/** +* @brief Returns the datarate. +* @param None. +* @retval uint32_t Settled datarate expressed in bps. +*/ +uint32_t SpiritRadioGetDatarate(void) +{ + uint8_t tempRegValue[2]; + uint8_t cDivider=0; + + /* Reads the datarate registers for mantissa and exponent */ + g_xStatus = SpiritSpiReadRegisters(MOD1_BASE, 2, tempRegValue); + + /* Calculates the datarate */ + cDivider = (uint8_t)SpiritRadioGetDigDiv(); + + return (((s_lXtalFrequency>>(5+cDivider))*(256+tempRegValue[0]))>>(23-(tempRegValue[1]&0x0F))); +} + + +/** +* @brief Sets the frequency deviation. +* @param fFDev frequency deviation expressed in Hz. Be sure that this value +* is in the correct range [F_Xo*8/2^18, F_Xo*7680/2^18] Hz. +* @retval None. +*/ +void SpiritRadioSetFrequencyDev(uint32_t lFDev) +{ + uint8_t FDevM, FDevE, tempRegValue; + + /* Check the parameters */ + s_assert_param(IS_F_DEV(lFDev, s_lXtalFrequency)); + + /* Calculates the frequency deviation mantissa and exponent */ + SpiritRadioSearchFreqDevME(lFDev, &FDevM, &FDevE); + + /* Reads the FDEV0 register */ + SpiritSpiReadRegisters(FDEV0_BASE, 1, &tempRegValue); + + /* Mask the other fields and set the frequency deviation mantissa and exponent */ + tempRegValue &= 0x08; + tempRegValue |= ((FDevE<<4)|(FDevM)); + + /* Writes the Frequency deviation register */ + g_xStatus = SpiritSpiWriteRegisters(FDEV0_BASE, 1, &tempRegValue); + +} + + +/** +* @brief Returns the frequency deviation. +* @param None. +* @retval uint32_t Frequency deviation value expressed in Hz. +* This value will be in the range [F_Xo*8/2^18, F_Xo*7680/2^18] Hz. +*/ +uint32_t SpiritRadioGetFrequencyDev(void) +{ + uint8_t tempRegValue, FDevM, FDevE; + + + /* Reads the frequency deviation register for mantissa and exponent */ + g_xStatus = SpiritSpiReadRegisters(FDEV0_BASE, 1, &tempRegValue); + FDevM = tempRegValue&0x07; + FDevE = (tempRegValue&0xF0)>>4; + + /* Calculates the frequency deviation and return it */ + //return (((s_lXtalFrequency>>6)*(8+FDevM))>>(13-FDevE)); + + return (uint32_t)((float)s_lXtalFrequency/(((uint32_t)1)<<18)*(uint32_t)((8.0+FDevM)/2*(1<<FDevE))); + +} + + +/** +* @brief Sets the channel filter bandwidth. +* @param lBandwidth channel filter bandwidth expressed in Hz. This parameter shall be in the range [1100 800100] +* Even if it is possible to pass as parameter any value in the above mentioned range, +* the API will search the most closer value according to a fixed table of channel +* bandwidth values (@ref s_vectnBandwidth), as defined in the datasheet. To verify the settled channel bandwidth +* it is possible to use the SpiritRadioGetChannelBW() API. +* @retval None. +*/ +void SpiritRadioSetChannelBW(uint32_t lBandwidth) +{ + uint8_t bwM, bwE, tempRegValue; + + /* Search in the channel filter bandwidth table the exponent value */ + if(SpiritRadioGetDigDiv()) + { + s_assert_param(IS_CH_BW(lBandwidth,(s_lXtalFrequency/2))); + } + else + { + s_assert_param(IS_CH_BW(lBandwidth,(s_lXtalFrequency))); + } + + /* Calculates the channel bandwidth mantissa and exponent */ + SpiritRadioSearchChannelBwME(lBandwidth, &bwM, &bwE); + tempRegValue = (bwM<<4)|(bwE); + + /* Writes the Channel filter register */ + g_xStatus = SpiritSpiWriteRegisters(CHFLT_BASE, 1, &tempRegValue); + +} + +/** +* @brief Returns the channel filter bandwidth. +* @param None. +* @retval uint32_t Channel filter bandwidth expressed in Hz. +*/ +uint32_t SpiritRadioGetChannelBW(void) +{ + uint8_t tempRegValue, bwM, bwE; + + /* Reads the channel filter register for mantissa and exponent */ + g_xStatus = SpiritSpiReadRegisters(CHFLT_BASE, 1, &tempRegValue); + bwM = (tempRegValue&0xF0)>>4; + bwE = tempRegValue&0x0F; + + /* Reads the channel filter bandwidth from the look-up table and return it */ + return (uint32_t)(100.0*s_vectnBandwidth26M[bwM+(bwE*9)]*s_lXtalFrequency/26e6); + +} + + +/** +* @brief Sets the modulation type. +* @param xModulation modulation to set. +* This parameter shall be of type @ref ModulationSelect . +* @retval None. +*/ +void SpiritRadioSetModulation(ModulationSelect xModulation) +{ + uint8_t tempRegValue; + + /* Check the parameters */ + s_assert_param(IS_MODULATION_SELECTED(xModulation)); + + /* Reads the modulation register */ + SpiritSpiReadRegisters(MOD0_BASE, 1, &tempRegValue); + + /* Mask the other fields and set the modulation type */ + tempRegValue &=0x8F; + tempRegValue |= xModulation; + + /* Writes the modulation register */ + g_xStatus = SpiritSpiWriteRegisters(MOD0_BASE, 1, &tempRegValue); + +} + + +/** +* @brief Returns the modulation type used. +* @param None. +* @retval ModulationSelect Settled modulation type. +*/ +ModulationSelect SpiritRadioGetModulation(void) +{ + uint8_t tempRegValue; + + /* Reads the modulation register MOD0*/ + g_xStatus = SpiritSpiReadRegisters(MOD0_BASE, 1, &tempRegValue); + + /* Return the modulation type */ + return (ModulationSelect)(tempRegValue&0x70); + +} + + +/** +* @brief Enables or Disables the Continuous Wave transmit mode. +* @param xNewState new state for power ramping. +* This parameter can be: S_ENABLE or S_DISABLE . +* @retval None. +*/ +void SpiritRadioCWTransmitMode(SpiritFunctionalState xNewState) +{ + uint8_t tempRegValue; + + /* Check the parameters */ + s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState)); + + /* Reads the modulation register MOD0 and mask the CW field */ + SpiritSpiReadRegisters(MOD0_BASE, 1, &tempRegValue); + if(xNewState == S_ENABLE) + { + tempRegValue |=MOD0_CW; + } + else + { + tempRegValue &= (~MOD0_CW); + } + + /* Writes the new value in the MOD0 register */ + g_xStatus = SpiritSpiWriteRegisters(MOD0_BASE, 1, &tempRegValue); + +} + + +/** +* @brief Sets the OOK Peak Decay. +* @param xOokDecay Peak decay control for OOK. +* This parameter shall be of type @ref OokPeakDecay . +* @retval None. +*/ +void SpiritRadioSetOokPeakDecay(OokPeakDecay xOokDecay) +{ + uint8_t tempRegValue; + + /* Check the parameters */ + s_assert_param(IS_OOK_PEAK_DECAY(xOokDecay)); + + /* Reads the RSSI_FLT register */ + SpiritSpiReadRegisters(RSSI_FLT_BASE, 1, &tempRegValue); + + /* Mask the other fields and set OOK Peak Decay */ + tempRegValue &= 0xFC; + tempRegValue |= xOokDecay; + + /* Writes the RSSI_FLT register to set the new OOK peak dacay value */ + g_xStatus = SpiritSpiWriteRegisters(RSSI_FLT_BASE, 1, &tempRegValue); + +} + + +/** +* @brief Returns the OOK Peak Decay. +* @param None +* @retval OokPeakDecay Ook peak decay value. +*/ +OokPeakDecay SpiritRadioGetOokPeakDecay(void) +{ + uint8_t tempRegValue; + + /* Reads the OOK peak decay register RSSI_FLT_BASE*/ + g_xStatus = SpiritSpiReadRegisters(RSSI_FLT_BASE, 1, &tempRegValue); + + /* Returns the OOK peak decay */ + return (OokPeakDecay) (tempRegValue & 0x03); + +} + +/** +* @brief Returns the PA register value that corresponds to the passed dBm power. +* @param lFbase Frequency base expressed in Hz. +* @param fPowerdBm Desired power in dBm. +* @retval Register value as byte. +* @note The power interpolation curves used by this function have been extracted +* by measurements done on the divisional evaluation boards. +*/ +uint8_t SpiritRadioGetdBm2Reg(uint32_t lFBase, float fPowerdBm) +{ + uint8_t i=0; + uint8_t j=0; + float fReg; + + if(IS_FREQUENCY_BAND_HIGH(lFBase)) + { + i=0; + if(lFBase<900000000) i=1;// 868 + } + else if(IS_FREQUENCY_BAND_MIDDLE(lFBase)) + { + i=2; + } + else if(IS_FREQUENCY_BAND_LOW(lFBase)) + { + i=3; + } + else if(IS_FREQUENCY_BAND_VERY_LOW(lFBase)) + { + i=4; + } + + j=1; + if(fPowerdBm>0 && 13.0/fPowerFactors[i][2]-fPowerFactors[i][3]/fPowerFactors[i][2]<fPowerdBm) + j=0; + else if(fPowerdBm<=0 && 40.0/fPowerFactors[i][2]-fPowerFactors[i][3]/fPowerFactors[i][2]>fPowerdBm) + j=2; + + fReg=fPowerFactors[i][2*j]*fPowerdBm+fPowerFactors[i][2*j+1]; + + if(fReg<1) + fReg=1; + else if(fReg>90) + fReg=90; + + return ((uint8_t)fReg); +} + + +/** +* @brief Returns the dBm power that corresponds to the value of PA register. +* @param lFbase Frequency base expressed in Hz. +* @param cPowerReg Register value of the PA. +* @retval Power in dBm as float. +* @note The power interpolation curves used by this function have been extracted +* by measurements done on the divisional evaluation boards. +*/ +float SpiritRadioGetReg2dBm(uint32_t lFBase, uint8_t cPowerReg) +{ + uint8_t i=0; + uint8_t j=0; + float fPower; + + if(cPowerReg==0 || cPowerReg>90) + return (-130.0); + + if(IS_FREQUENCY_BAND_HIGH(lFBase)) + { + i=0; + if(lFBase<900000000) i=1;// 868 + } + else if(IS_FREQUENCY_BAND_MIDDLE(lFBase)) + { + i=2; + } + else if(IS_FREQUENCY_BAND_LOW(lFBase)) + { + i=3; + } + else if(IS_FREQUENCY_BAND_VERY_LOW(lFBase)) + { + i=4; + } + + j=1; + if(cPowerReg<13) j=0; + else if(cPowerReg>40) j=2; + + fPower=(((float)cPowerReg)/fPowerFactors[i][2*j]-fPowerFactors[i][2*j+1]/fPowerFactors[i][2*j]); + + return fPower; +} + +/** +* @brief Configures the Power Amplifier Table and registers with value expressed in dBm. +* @param cPALevelMaxIndex number of levels to set. This parameter shall be in the range [0:7]. +* @param cWidth step width expressed in terms of bit period units Tb/8. +* This parameter shall be in the range [1:4]. +* @param xCLoad one of the possible value of the enum type PALoadCapacitor. +* @arg LOAD_0_PF No additional PA load capacitor +* @arg LOAD_1_2_PF 1.2pF additional PA load capacitor +* @arg LOAD_2_4_PF 2.4pF additional PA load capacitor +* @arg LOAD_3_6_PF 3.6pF additional PA load capacitor +* @param pfPAtabledBm pointer to an array of PA values in dbm between [-PA_LOWER_LIMIT: PA_UPPER_LIMIT] dbm. +* The first element shall be the lower level (PA_LEVEL[0]) value and the last element +* the higher level one (PA_LEVEL[paLevelMaxIndex]). +* @retval None. +*/ +void SpiritRadioSetPATabledBm(uint8_t cPALevelMaxIndex, uint8_t cWidth, PALoadCapacitor xCLoad, float* pfPAtabledBm) +{ + uint8_t palevel[9], address, paLevelValue; + uint32_t lFBase=SpiritRadioGetFrequencyBase(); + + /* Check the parameters */ + s_assert_param(IS_PA_MAX_INDEX(cPALevelMaxIndex)); + s_assert_param(IS_PA_STEP_WIDTH(cWidth)); + s_assert_param(IS_PA_LOAD_CAP(xCLoad)); + + /* Check the PA level in dBm is in the range and calculate the PA_LEVEL value + to write in the corresponding register using the linearization formula */ + for(int i=0; i<=cPALevelMaxIndex; i++) + { + s_assert_param(IS_PAPOWER_DBM(*pfPAtabledBm)); + paLevelValue=SpiritRadioGetdBm2Reg(lFBase,(*pfPAtabledBm)); + palevel[cPALevelMaxIndex-i]=paLevelValue; + pfPAtabledBm++; + } + + /* Sets the PA_POWER[0] register */ + palevel[cPALevelMaxIndex+1]=xCLoad|(cWidth-1)<<3|cPALevelMaxIndex; + + /* Sets the base address */ + address=PA_POWER8_BASE+7-cPALevelMaxIndex; + + /* Configures the PA_POWER registers */ + g_xStatus = SpiritSpiWriteRegisters(address, cPALevelMaxIndex+2, palevel); + +} + + +/** +* @brief Returns the Power Amplifier Table and registers, returning values in dBm. +* @param pcPALevelMaxIndex pointer to the number of levels settled. +* This parameter will be in the range [0:7]. +* @param pfPAtabledBm pointer to an array of 8 elements containing the PA value in dbm. +* The first element will be the PA_LEVEL_0 and the last element +* will be PA_LEVEL_7. Any value higher than PA_UPPER_LIMIT implies no output +* power (output stage is in high impedance). +* @retval None. +*/ +void SpiritRadioGetPATabledBm(uint8_t* pcPALevelMaxIndex, float* pfPAtabledBm) +{ + uint8_t palevelvect[9]; + uint32_t lFBase=SpiritRadioGetFrequencyBase(); + + /* Reads the PA_LEVEL_x registers and the PA_POWER_0 register */ + g_xStatus = SpiritSpiReadRegisters(PA_POWER8_BASE, 9, palevelvect); + + /* Fill the PAtable */ + for(int i=7; i>=0; i--) + { + (*pfPAtabledBm)=SpiritRadioGetReg2dBm(lFBase,palevelvect[i]); + pfPAtabledBm++; + } + + /* Return the settled index */ + *pcPALevelMaxIndex = palevelvect[8]&0x07; + +} + + + + + + +/** +* @brief Sets a specific PA_LEVEL register, with a value given in dBm. +* @param cIndex PA_LEVEL to set. This parameter shall be in the range [0:7]. +* @param fPowerdBm PA value to write expressed in dBm . Be sure that this values is in the +* correct range [-PA_LOWER_LIMIT: PA_UPPER_LIMIT] dBm. +* @retval None. +* @note This function makes use of the @ref SpiritRadioGetdBm2Reg fcn to interpolate the +* power value. +*/ +void SpiritRadioSetPALeveldBm(uint8_t cIndex, float fPowerdBm) +{ + uint8_t address, paLevelValue; + + /* Check the parameters */ + s_assert_param(IS_PA_MAX_INDEX(cIndex)); + s_assert_param(IS_PAPOWER_DBM(fPowerdBm)); + + /* interpolate the power level */ + paLevelValue=SpiritRadioGetdBm2Reg(SpiritRadioGetFrequencyBase(),fPowerdBm); + + /* Sets the base address */ + address=PA_POWER8_BASE+7-cIndex; + + /* Configures the PA_LEVEL register */ + g_xStatus = SpiritSpiWriteRegisters(address, 1, &paLevelValue); + +} + + +/** +* @brief Returns a specific PA_LEVEL register, returning a value in dBm. +* @param cIndex PA_LEVEL to read. This parameter shall be in the range [0:7] +* @retval float Settled power level expressed in dBm. A value +* higher than PA_UPPER_LIMIT dBm implies no output power +* (output stage is in high impedance). +* @note This function makes use of the @ref SpiritRadioGetReg2dBm fcn to interpolate the +* power value. +*/ +float SpiritRadioGetPALeveldBm(uint8_t cIndex) +{ + uint8_t address, paLevelValue; + + /* Check the parameters */ + s_assert_param(IS_PA_MAX_INDEX(cIndex)); + + /* Sets the base address */ + address=PA_POWER8_BASE+7-cIndex; + + /* Reads the PA_LEVEL[cIndex] register */ + g_xStatus = SpiritSpiReadRegisters(address, 1, &paLevelValue); + + return SpiritRadioGetReg2dBm(SpiritRadioGetFrequencyBase(),paLevelValue); +} + + +/** +* @brief Configures the Power Amplifier Table and registers. +* @param cPALevelMaxIndex number of levels to set. This parameter shall be in the range [0:7]. +* @param cWidth step width expressed in terms of bit period units Tb/8. +* This parameter shall be in the range [1:4]. +* @param xCLoad one of the possible value of the enum type PALoadCapacitor. +* @arg LOAD_0_PF No additional PA load capacitor +* @arg LOAD_1_2_PF 1.2pF additional PA load capacitor +* @arg LOAD_2_4_PF 2.4pF additional PA load capacitor +* @arg LOAD_3_6_PF 3.6pF additional PA load capacitor +* @param pcPAtable pointer to an array of PA values in the range [0: 90], where 0 implies no +* output power, 1 will be the maximum level and 90 the minimum one +* The first element shall be the lower level (PA_LEVEL[0]) value and the last element +* the higher level one (PA_LEVEL[paLevelMaxIndex]). +* @retval None. +*/ +void SpiritRadioSetPATable(uint8_t cPALevelMaxIndex, uint8_t cWidth, PALoadCapacitor xCLoad, uint8_t* pcPAtable) +{ + uint8_t palevel[9], address; + + /* Check the parameters */ + s_assert_param(IS_PA_MAX_INDEX(cPALevelMaxIndex)); + s_assert_param(IS_PA_STEP_WIDTH(cWidth)); + s_assert_param(IS_PA_LOAD_CAP(xCLoad)); + + /* Check the PA levels are in the range */ + for(int i=0; i<=cPALevelMaxIndex; i++) + { + s_assert_param(IS_PAPOWER(*pcPAtable)); + palevel[cPALevelMaxIndex-i]=*pcPAtable; + pcPAtable++; + } + + /* Sets the PA_POWER[0] register */ + palevel[cPALevelMaxIndex+1]=xCLoad|((cWidth-1)<<3)|cPALevelMaxIndex; + + /* Sets the base address */ + address=PA_POWER8_BASE+7-cPALevelMaxIndex; + + /* Configures the PA_POWER registers */ + g_xStatus = SpiritSpiWriteRegisters(address, cPALevelMaxIndex+2, palevel); + +} + + +/** +* @brief Returns the Power Amplifier Table and registers. +* @param pcPALevelMaxIndex pointer to the number of levels settled. +* This parameter shall be in the range [0:7]. +* @param pcPAtable pointer to an array of 8 elements containing the PA value. +* The first element will be the PA_LEVEL_0 and the last element +* will be PA_LEVEL_7. Any value equals to 0 implies that level has +* no output power (output stage is in high impedance). +* @retval None +*/ +void SpiritRadioGetPATable(uint8_t* pcPALevelMaxIndex, uint8_t* pcPAtable) +{ + uint8_t palevelvect[9]; + + /* Reads the PA_LEVEL_x registers and the PA_POWER_0 register */ + g_xStatus = SpiritSpiReadRegisters(PA_POWER8_BASE, 9, palevelvect); + + /* Fill the PAtable */ + for(int i=7; i>=0; i--) + { + *pcPAtable = palevelvect[i]; + pcPAtable++; + } + + /* Return the settled index */ + *pcPALevelMaxIndex = palevelvect[8]&0x07; + +} + + +/** +* @brief Sets a specific PA_LEVEL register. +* @param cIndex PA_LEVEL to set. This parameter shall be in the range [0:7]. +* @param cPower PA value to write in the register. Be sure that this values is in the +* correct range [0 : 90]. +* @retval None. +*/ +void SpiritRadioSetPALevel(uint8_t cIndex, uint8_t cPower) +{ + uint8_t address; + + /* Check the parameters */ + s_assert_param(IS_PA_MAX_INDEX(cIndex)); + s_assert_param(IS_PAPOWER(cPower)); + + /* Sets the base address */ + address=PA_POWER8_BASE+7-cIndex; + + /* Configures the PA_LEVEL register */ + g_xStatus = SpiritSpiWriteRegisters(address, 1, &cPower); + +} + + +/** +* @brief Returns a specific PA_LEVEL register. +* @param cIndex PA_LEVEL to read. This parameter shall be in the range [0:7]. +* @retval uint8_t PA_LEVEL value. A value equal to zero +* implies no output power (output stage is in high impedance). +*/ +uint8_t SpiritRadioGetPALevel(uint8_t cIndex) +{ + uint8_t address, tempRegValue; + + /* Check the parameters */ + s_assert_param(IS_PA_MAX_INDEX(cIndex)); + + /* Sets the base address */ + address=PA_POWER8_BASE+7-cIndex; + + /* Reads the PA_LEVEL[cIndex] register and return the value */ + g_xStatus = SpiritSpiReadRegisters(address, 1, &tempRegValue); + return tempRegValue; + +} + + +/** +* @brief Sets the output stage additional load capacitor bank. +* @param xCLoad one of the possible value of the enum type PALoadCapacitor. +* @arg LOAD_0_PF No additional PA load capacitor +* @arg LOAD_1_2_PF 1.2pF additional PA load capacitor +* @arg LOAD_2_4_PF 2.4pF additional PA load capacitor +* @arg LOAD_3_6_PF 3.6pF additional PA load capacitor +* @retval None. +*/ +void SpiritRadioSetPACwc(PALoadCapacitor xCLoad) +{ + uint8_t tempRegValue; + + /* Check the parameters */ + s_assert_param(IS_PA_LOAD_CAP(xCLoad)); + + /* Reads the PA_POWER_0 register */ + SpiritSpiReadRegisters(PA_POWER0_BASE, 1, &tempRegValue); + + /* Mask the CWC[1:0] field and write the new value */ + tempRegValue &= 0x3F; + tempRegValue |= xCLoad; + + /* Configures the PA_POWER_0 register */ + g_xStatus = SpiritSpiWriteRegisters(PA_POWER0_BASE, 1, &tempRegValue); + +} + + +/** +* @brief Returns the output stage additional load capacitor bank. +* @param None. +* @retval PALoadCapacitor Output stage additional load capacitor bank. +* This parameter can be: +* @arg LOAD_0_PF No additional PA load capacitor +* @arg LOAD_1_2_PF 1.2pF additional PA load capacitor +* @arg LOAD_2_4_PF 2.4pF additional PA load capacitor +* @arg LOAD_3_6_PF 3.6pF additional PA load capacitor +*/ +PALoadCapacitor SpiritRadioGetPACwc(void) +{ + uint8_t tempRegValue; + + /* Reads the PA_POWER_0 register */ + g_xStatus = SpiritSpiReadRegisters(PA_POWER0_BASE, 1, &tempRegValue); + + /* Mask the CWC[1:0] field and return the value*/ + return (PALoadCapacitor)(tempRegValue & 0xC0); + +} + + +/** +* @brief Sets a specific PA_LEVEL_MAX_INDEX. +* @param cIndex PA_LEVEL_MAX_INDEX to set. This parameter shall be in the range [0:7]. +* @retval None +*/ +void SpiritRadioSetPALevelMaxIndex(uint8_t cIndex) +{ + uint8_t tempRegValue; + + /* Check the parameters */ + s_assert_param(IS_PA_MAX_INDEX(cIndex)); + + /* Reads the PA_POWER_0 register */ + SpiritSpiReadRegisters(PA_POWER0_BASE, 1, &tempRegValue); + + /* Mask the PA_LEVEL_MAX_INDEX[1:0] field and write the new value */ + tempRegValue &= 0xF8; + tempRegValue |= cIndex; + + /* Configures the PA_POWER_0 register */ + g_xStatus = SpiritSpiWriteRegisters(PA_POWER0_BASE, 1, &tempRegValue); + +} + + +/** +* @brief Returns the actual PA_LEVEL_MAX_INDEX. +* @param None. +* @retval uint8_t Actual PA_LEVEL_MAX_INDEX. This parameter will be in the range [0:7]. +*/ +uint8_t SpiritRadioGetPALevelMaxIndex(void) +{ + uint8_t tempRegValue; + + /* Reads the PA_POWER_0 register */ + g_xStatus = SpiritSpiReadRegisters(PA_POWER0_BASE, 1, &tempRegValue); + + /* Mask the PA_LEVEL_MAX_INDEX[1:0] field and return the value */ + return (tempRegValue & 0x07); + +} + + +/** +* @brief Sets a specific PA_RAMP_STEP_WIDTH. +* @param cWidth step width expressed in terms of bit period units Tb/8. +* This parameter shall be in the range [1:4]. +* @retval None. +*/ +void SpiritRadioSetPAStepWidth(uint8_t cWidth) +{ + uint8_t tempRegValue; + + /* Check the parameters */ + s_assert_param(IS_PA_STEP_WIDTH(cWidth)); + + /* Reads the PA_POWER_0 register */ + SpiritSpiReadRegisters(PA_POWER0_BASE, 1, &tempRegValue); + + /* Mask the PA_RAMP_STEP_WIDTH[1:0] field and write the new value */ + tempRegValue &= 0xE7; + tempRegValue |= (cWidth-1)<<3; + + /* Configures the PA_POWER_0 register */ + g_xStatus = SpiritSpiWriteRegisters(PA_POWER0_BASE, 1, &tempRegValue); + +} + + +/** +* @brief Returns the actual PA_RAMP_STEP_WIDTH. +* @param None. +* @retval uint8_t Step width value expressed in terms of bit period units Tb/8. +* This parameter will be in the range [1:4]. +*/ +uint8_t SpiritRadioGetPAStepWidth(void) +{ + uint8_t tempRegValue; + + /* Reads the PA_POWER_0 register */ + g_xStatus = SpiritSpiReadRegisters(PA_POWER0_BASE, 1, &tempRegValue); + + /* Mask the PA_RAMP_STEP_WIDTH[1:0] field and return the value */ + tempRegValue &= 0x18; + return ((tempRegValue>>3)+1); + +} + + +/** +* @brief Enables or Disables the Power Ramping. +* @param xNewState new state for power ramping. +* This parameter can be: S_ENABLE or S_DISABLE. +* @retval None. +*/ +void SpiritRadioPARamping(SpiritFunctionalState xNewState) +{ + uint8_t tempRegValue = 0x00; + + /* Check the parameters */ + s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState)); + + /* Reads the PA_POWER_0 register and configure the PA_RAMP_ENABLE field */ + SpiritSpiReadRegisters(PA_POWER0_BASE, 1, &tempRegValue); + if(xNewState == S_ENABLE) + { + tempRegValue |= PA_POWER0_PA_RAMP_MASK; + } + else + { + tempRegValue &= (~PA_POWER0_PA_RAMP_MASK); + } + + /* Sets the PA_POWER_0 register */ + g_xStatus = SpiritSpiWriteRegisters(PA_POWER0_BASE, 1, &tempRegValue); + +} + +/** +* @brief Returns the Power Ramping enable bit. +* @param xNewState new state for power ramping. +* This parameter can be: S_ENABLE or S_DISABLE. +* @retval None. +*/ +SpiritFunctionalState SpiritRadioGetPARamping(void) +{ + uint8_t tempRegValue; + + /* Reads the PA_POWER_0 register and configure the PA_RAMP_ENABLE field */ + g_xStatus = SpiritSpiReadRegisters(PA_POWER0_BASE, 1, &tempRegValue); + + /* Mask and return data */ + return (SpiritFunctionalState)((tempRegValue>>5) & 0x01); + +} + + +/** +* @brief Enables or Disables the AFC. +* @param xNewState new state for AFC. +* This parameter can be: S_ENABLE or S_DISABLE. +* @retval None. +*/ +void SpiritRadioAFC(SpiritFunctionalState xNewState) +{ + uint8_t tempRegValue = 0x00; + + /* Check the parameters */ + s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState)); + + /* Reads the AFC_2 register and configure the AFC Enabled field */ + SpiritSpiReadRegisters(AFC2_BASE, 1, &tempRegValue); + if(xNewState == S_ENABLE) + { + tempRegValue |= AFC2_AFC_MASK; + } + else + { + tempRegValue &= (~AFC2_AFC_MASK); + } + + /* Sets the AFC_2 register */ + g_xStatus = SpiritSpiWriteRegisters(AFC2_BASE, 1, &tempRegValue); + +} + + +/** +* @brief Enables or Disables the AFC freeze on sync word detection. +* @param xNewState new state for AFC freeze on sync word detection. +* This parameter can be: S_ENABLE or S_DISABLE. +* @retval None. +*/ +void SpiritRadioAFCFreezeOnSync(SpiritFunctionalState xNewState) +{ + uint8_t tempRegValue = 0x00; + + /* Check the parameters */ + s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState)); + + /* Reads the AFC_2 register and configure the AFC Freeze on Sync field */ + SpiritSpiReadRegisters(AFC2_BASE, 1, &tempRegValue); + if(xNewState == S_ENABLE) + { + tempRegValue |= AFC2_AFC_FREEZE_ON_SYNC_MASK; + } + else + { + tempRegValue &= (~AFC2_AFC_FREEZE_ON_SYNC_MASK); + } + + /* Sets the AFC_2 register */ + g_xStatus = SpiritSpiWriteRegisters(AFC2_BASE, 1, &tempRegValue); + +} + + +/** +* @brief Sets the AFC working mode. +* @param xMode the AFC mode. This parameter can be one of the values defined in @ref AFCMode : +* @arg AFC_SLICER_CORRECTION AFC loop closed on slicer +* @arg AFC_2ND_IF_CORRECTION AFC loop closed on 2nd conversion stage +* @retval None. +*/ +void SpiritRadioSetAFCMode(AFCMode xMode) +{ + uint8_t tempRegValue = 0x00; + + /* Check the parameters */ + s_assert_param(IS_AFC_MODE(xMode)); + + /* Reads the AFC_2 register and configure the AFC Mode field */ + SpiritSpiReadRegisters(AFC2_BASE, 1, &tempRegValue); + if(xMode == AFC_2ND_IF_CORRECTION) + { + tempRegValue |= AFC_2ND_IF_CORRECTION; + } + else + { + tempRegValue &= (~AFC_2ND_IF_CORRECTION); + } + + /* Sets the AFC_2 register */ + g_xStatus = SpiritSpiWriteRegisters(AFC2_BASE, 1, &tempRegValue); + +} + + +/** +* @brief Returns the AFC working mode. +* @param None. +* @retval AFCMode Settled AFC mode. This parameter will be one of the values defined in @ref AFCMode : +* @arg AFC_SLICER_CORRECTION AFC loop closed on slicer +* @arg AFC_2ND_IF_CORRECTION AFC loop closed on 2nd conversion stage +*/ +AFCMode SpiritRadioGetAFCMode(void) +{ + uint8_t tempRegValue; + + /* Reads the AFC_2 register */ + g_xStatus = SpiritSpiReadRegisters(AFC2_BASE, 1, &tempRegValue); + + /* Mask the AFC Mode field and returns the value */ + return (AFCMode)(tempRegValue & 0x20); + +} + + +/** +* @brief Sets the AFC peak detector leakage. +* @param cLeakage the peak detector leakage. This parameter shall be in the range: +* [0:31]. +* @retval None. +*/ +void SpiritRadioSetAFCPDLeakage(uint8_t cLeakage) +{ + uint8_t tempRegValue = 0x00; + + /* Check the parameters */ + s_assert_param(IS_AFC_PD_LEAKAGE(cLeakage)); + + /* Reads the AFC_2 register and configure the AFC PD leakage field */ + SpiritSpiReadRegisters(AFC2_BASE, 1, &tempRegValue); + tempRegValue &= 0xE0; + tempRegValue |= cLeakage; + + /* Sets the AFC_2 register */ + g_xStatus = SpiritSpiWriteRegisters(AFC2_BASE, 1, &tempRegValue); + +} + + +/** +* @brief Returns the AFC peak detector leakage. +* @param None. +* @retval uint8_t Peak detector leakage value. This parameter will be in the range: +* [0:31]. +*/ +uint8_t SpiritRadioGetAFCPDLeakage(void) +{ + uint8_t tempRegValue; + + /* Reads the AFC_2 register */ + g_xStatus = SpiritSpiReadRegisters(AFC2_BASE, 1, &tempRegValue); + + /* Mask the AFC PD leakage field and return the value */ + return (tempRegValue & 0x1F); + +} + + +/** +* @brief Sets the length of the AFC fast period expressed as number of samples. +* @param cLength length of the fast period in number of samples. +* @retval None. +*/ +void SpiritRadioSetAFCFastPeriod(uint8_t cLength) +{ + /* Sets the AFC_1 register */ + g_xStatus = SpiritSpiWriteRegisters(AFC1_BASE, 1, &cLength); + +} + + +/** +* @brief Returns the AFC fast period expressed as number of samples. +* @param None. +* @retval uint8_t Length of the fast period in number of samples. +*/ +uint8_t SpiritRadioGetAFCFastPeriod(void) +{ + uint8_t tempRegValue; + + /* Reads the AFC 1 register and return the value */ + g_xStatus = SpiritSpiReadRegisters(AFC1_BASE, 1, &tempRegValue); + + return tempRegValue; + +} + + +/** +* @brief Sets the AFC loop gain in fast mode. +* @param cGain AFC loop gain in fast mode. This parameter shall be in the range: +* [0:15]. +* @retval None. +*/ +void SpiritRadioSetAFCFastGain(uint8_t cGain) +{ + uint8_t tempRegValue = 0x00; + + /* Check the parameters */ + s_assert_param(IS_AFC_FAST_GAIN(cGain)); + + /* Reads the AFC_0 register and configure the AFC Fast Gain field */ + SpiritSpiReadRegisters(AFC0_BASE, 1, &tempRegValue); + tempRegValue &= 0x0F; + tempRegValue |= cGain<<4; + + /* Sets the AFC_0 register */ + g_xStatus = SpiritSpiWriteRegisters(AFC0_BASE, 1, &tempRegValue); + +} + + +/** +* @brief Returns the AFC loop gain in fast mode. +* @param None. +* @retval uint8_t AFC loop gain in fast mode. This parameter will be in the range: +* [0:15]. +*/ +uint8_t SpiritRadioGetAFCFastGain(void) +{ + uint8_t tempRegValue; + + /* Reads the AFC_0 register, mask the AFC Fast Gain field and return the value */ + g_xStatus = SpiritSpiReadRegisters(AFC0_BASE, 1, &tempRegValue); + + return ((tempRegValue & 0xF0)>>4); + +} + + +/** +* @brief Sets the AFC loop gain in slow mode. +* @param cGain AFC loop gain in slow mode. This parameter shall be in the range: +* [0:15]. +* @retval None. +*/ +void SpiritRadioSetAFCSlowGain(uint8_t cGain) +{ + uint8_t tempRegValue = 0x00; + + /* Check the parameters */ + s_assert_param(IS_AFC_SLOW_GAIN(cGain)); + + /* Reads the AFC_0 register and configure the AFC Slow Gain field */ + SpiritSpiReadRegisters(AFC0_BASE, 1, &tempRegValue); + tempRegValue &= 0xF0; + tempRegValue |= cGain; + + /* Sets the AFC_0 register */ + g_xStatus = SpiritSpiWriteRegisters(AFC0_BASE, 1, &tempRegValue); + +} + + +/** +* @brief Returns the AFC loop gain in slow mode. +* @param None. +* @retval uint8_t AFC loop gain in slow mode. This parameter will be in the range: +* [0:15]. +*/ +uint8_t SpiritRadioGetAFCSlowGain(void) +{ + uint8_t tempRegValue; + + /* Reads the AFC_0 register, mask the AFC Slow Gain field and return the value */ + g_xStatus = SpiritSpiReadRegisters(AFC0_BASE, 1, &tempRegValue); + + return (tempRegValue & 0x0F); + +} + + +/** +* @brief Returns the AFC correction from the corresponding register. +* @param None. +* @retval int8_t AFC correction, read from the corresponding register. +* This parameter will be in the range [-128:127]. +*/ +int8_t SpiritRadioGetAFCCorrectionReg(void) +{ + uint8_t tempRegValue; + + /* Reads the AFC_CORR register, cast the read value as signed char and return it */ + g_xStatus = SpiritSpiReadRegisters(AFC_CORR_BASE, 1, &tempRegValue); + + return (int8_t)tempRegValue; + +} + + +/** +* @brief Returns the AFC correction expressed in Hz. +* @param None. +* @retval int32_t AFC correction expressed in Hz +* according to the following formula:<ul> +* <li> Fafc[Hz]= (Fdig/(12*2^10))*AFC_CORR where </li> +* <li> AFC_CORR is the value read in the AFC_CORR register </li> </ul> +*/ +int32_t SpiritRadioGetAFCCorrectionHz(void) +{ + int8_t correction; + uint32_t xtal = s_lXtalFrequency; + + /* Reads the AFC correction register */ + correction = SpiritRadioGetAFCCorrectionReg(); + + if(xtal>DOUBLE_XTAL_THR) + { + xtal /= 2; + } + + /* Calculates and return the Frequency Correction */ + return (int32_t)(xtal/(12*pow(2,10))*correction); + +} + + +/** +* @brief Enables or Disables the AGC. +* @param xNewState new state for AGC. +* This parameter can be: S_ENABLE or S_DISABLE +* @retval None. +*/ +void SpiritRadioAGC(SpiritFunctionalState xNewState) +{ + uint8_t tempRegValue = 0x00; + + /* Check the parameters */ + s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState)); + + /* Reads the AGCCTRL_0 register and configure the AGC Enabled field */ + SpiritSpiReadRegisters(AGCCTRL0_BASE, 1, &tempRegValue); + if(xNewState == S_ENABLE) + { + tempRegValue |= AGCCTRL0_AGC_MASK; + } + else + { + tempRegValue &= (~AGCCTRL0_AGC_MASK); + } + + /* Sets the AGCCTRL_0 register */ + g_xStatus = SpiritSpiWriteRegisters(AGCCTRL0_BASE, 1, &tempRegValue); + +} + + +/** +* @brief Sets the AGC working mode. +* @param xMode the AGC mode. This parameter can be one of the values defined in @ref AGCMode : +* @arg AGC_LINEAR_MODE AGC works in linear mode +* @arg AGC_BINARY_MODE AGC works in binary mode +* @retval None. +*/ +void SpiritRadioSetAGCMode(AGCMode xMode) +{ + uint8_t tempRegValue = 0x00; + + /* Check the parameters */ + s_assert_param(IS_AGC_MODE(xMode)); + + /* Reads the AGCCTRL_0 register and configure the AGC Mode field */ + SpiritSpiReadRegisters(AGCCTRL0_BASE, 1, &tempRegValue); + if(xMode == AGC_BINARY_MODE) + { + tempRegValue |= AGC_BINARY_MODE; + } + else + { + tempRegValue &= (~AGC_BINARY_MODE); + } + + /* Sets the AGCCTRL_0 register */ + g_xStatus = SpiritSpiWriteRegisters(AGCCTRL0_BASE, 1, &tempRegValue); + +} + + +/** +* @brief Returns the AGC working mode. +* @param None. +* @retval AGCMode Settled AGC mode. This parameter can be one of the values defined in @ref AGCMode : +* @arg AGC_LINEAR_MODE AGC works in linear mode +* @arg AGC_BINARY_MODE AGC works in binary mode +*/ +AGCMode SpiritRadioGetAGCMode(void) +{ + uint8_t tempRegValue; + + /* Reads the AGCCTRL_0 register, mask the AGC Mode field and return the value */ + g_xStatus = SpiritSpiReadRegisters(AGCCTRL0_BASE, 1, &tempRegValue); + + return (AGCMode)(tempRegValue & 0x40); + +} + + +/** +* @brief Enables or Disables the AGC freeze on steady state. +* @param xNewState new state for AGC freeze on steady state. +* This parameter can be: S_ENABLE or S_DISABLE. +* @retval None. +*/ +void SpiritRadioAGCFreezeOnSteady(SpiritFunctionalState xNewState) +{ + uint8_t tempRegValue = 0x00; + + /* Check the parameters */ + s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState)); + + /* Reads the AGCCTRL_2 register and configure the AGC Freeze On Steady field */ + SpiritSpiReadRegisters(AGCCTRL2_BASE, 1, &tempRegValue); + if(xNewState == S_ENABLE) + { + tempRegValue |= AGCCTRL2_FREEZE_ON_STEADY_MASK; + } + else + { + tempRegValue &= (~AGCCTRL2_FREEZE_ON_STEADY_MASK); + } + + /* Sets the AGCCTRL_2 register */ + g_xStatus = SpiritSpiWriteRegisters(AGCCTRL2_BASE, 1, &tempRegValue); + +} + + +/** +* @brief Enable or Disable the AGC freeze on sync detection. +* @param xNewState new state for AGC freeze on sync detection. +* This parameter can be: S_ENABLE or S_DISABLE. +* @retval None. +*/ +void SpiritRadioAGCFreezeOnSync(SpiritFunctionalState xNewState) +{ + uint8_t tempRegValue = 0x00; + + /* Check the parameters */ + s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState)); + + /* Reads the AGCCTRL_2 register and configure the AGC Freeze On Sync field */ + SpiritSpiReadRegisters(AGCCTRL2_BASE, 1, &tempRegValue); + if(xNewState == S_ENABLE) + { + tempRegValue |= AGCCTRL2_FREEZE_ON_SYNC_MASK; + } + else + { + tempRegValue &= (~AGCCTRL2_FREEZE_ON_SYNC_MASK); + } + + /* Sets the AGCCTRL_2 register */ + g_xStatus = SpiritSpiWriteRegisters(AGCCTRL2_BASE, 1, &tempRegValue); + +} + + +/** +* @brief Enable or Disable the AGC to start with max attenuation. +* @param xNewState new state for AGC start with max attenuation mode. +* This parameter can be: S_ENABLE or S_DISABLE. +* @retval None. +*/ +void SpiritRadioAGCStartMaxAttenuation(SpiritFunctionalState xNewState) +{ + uint8_t tempRegValue = 0x00; + + /* Check the parameters */ + s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState)); + + /* Reads the AGCCTRL_2 register and configure the AGC Start Max Attenuation field */ + SpiritSpiReadRegisters(AGCCTRL2_BASE, 1, &tempRegValue); + if(xNewState == S_ENABLE) + { + tempRegValue |= AGCCTRL2_START_MAX_ATTENUATION_MASK; + } + else + { + tempRegValue &= (~AGCCTRL2_START_MAX_ATTENUATION_MASK); + } + + /* Sets the AGCCTRL_2 register */ + g_xStatus = SpiritSpiWriteRegisters(AGCCTRL2_BASE, 1, &tempRegValue); + +} + + +/** +* @brief Sets the AGC measure time. +* @param nTime AGC measure time expressed in us. This parameter shall be in the range [0, 393216/F_Xo]. +* @retval None. +*/ +void SpiritRadioSetAGCMeasureTimeUs(uint16_t nTime) +{ + uint8_t tempRegValue, measure; + + /* Check the parameter */ + s_assert_param(IS_AGC_MEASURE_TIME_US(nTime,s_lXtalFrequency)); + + /* Reads the AGCCTRL_2 register */ + SpiritSpiReadRegisters(AGCCTRL2_BASE, 1, &tempRegValue); + + /* Calculates the measure time value to write in the register */ + measure = (uint8_t)lroundf(log2((float)nTime/1e6 * s_lXtalFrequency/12)); + (measure>15) ? (measure=15):(measure); + + /* Mask the MEAS_TIME field and write the new value */ + tempRegValue &= 0xF0; + tempRegValue |= measure; + + /* Sets the AGCCTRL_2 register */ + g_xStatus = SpiritSpiWriteRegisters(AGCCTRL2_BASE, 1, &tempRegValue); + +} + + +/** +* @brief Returns the AGC measure time. +* @param None. +* @retval uint16_t AGC measure time expressed in us. This parameter will be in the range [0, 393216/F_Xo]. +*/ +uint16_t SpiritRadioGetAGCMeasureTimeUs(void) +{ + uint8_t measure; + + /* Reads the AGCCTRL_2 register */ + g_xStatus = SpiritSpiReadRegisters(AGCCTRL2_BASE, 1, &measure); + + /* Mask the MEAS_TIME field */ + measure &= 0x0F; + + /* Calculates the measure time value to write in the register */ + return (uint16_t)((12.0/s_lXtalFrequency)*(float)pow(2,measure)*1e6); + +} + + +/** +* @brief Sets the AGC measure time. +* @param cTime AGC measure time to write in the MEAS_TIME field of AGCCTRL_2 register. +* This parameter shall be in the range [0:15]. +* @retval None. +*/ +void SpiritRadioSetAGCMeasureTime(uint8_t cTime) +{ + uint8_t tempRegValue; + + /* Check the parameter */ + s_assert_param(IS_AGC_MEASURE_TIME(cTime)); + + /* Reads the AGCCTRL_2 register */ + SpiritSpiReadRegisters(AGCCTRL2_BASE, 1, &tempRegValue); + + /* Mask the MEAS_TIME field and write the new value */ + tempRegValue &= 0xF0; + tempRegValue |= cTime; + + /* Sets the AGCCTRL_2 register */ + g_xStatus = SpiritSpiWriteRegisters(AGCCTRL2_BASE, 1, &tempRegValue); + +} + + +/** +* @brief Returns the AGC measure time. +* @param None. +* @retval uint8_t AGC measure time read from the MEAS_TIME field of AGCCTRL_2 register. +* This parameter will be in the range [0:15]. +*/ +uint8_t SpiritRadioGetAGCMeasureTime(void) +{ + uint8_t tempRegValue; + + /* Reads the AGCCTRL_2 register, mask the MEAS_TIME field and return the value */ + g_xStatus = SpiritSpiReadRegisters(AGCCTRL2_BASE, 1, &tempRegValue); + + return (tempRegValue & 0x0F); + +} + + +/** +* @brief Sets the AGC hold time. +* @param cTime AGC hold time expressed in us. This parameter shall be in the range[0, 756/F_Xo]. +* @retval None. +*/ +void SpiritRadioSetAGCHoldTimeUs(uint8_t cTime) +{ + uint8_t tempRegValue, hold; + + /* Check the parameter */ + s_assert_param(IS_AGC_HOLD_TIME_US(cTime,s_lXtalFrequency)); + + /* Reads the AGCCTRL_0 register */ + SpiritSpiReadRegisters(AGCCTRL0_BASE, 1, &tempRegValue); + + /* Calculates the hold time value to write in the register */ + hold = (uint8_t)lroundf(((float)cTime/1e6 * s_lXtalFrequency)/12); + (hold>63) ? (hold=63):(hold); + + /* Mask the HOLD_TIME field and write the new value */ + tempRegValue &= 0xC0; + tempRegValue |= hold; + + /* Sets the AGCCTRL_0 register */ + g_xStatus = SpiritSpiWriteRegisters(AGCCTRL0_BASE, 1, &tempRegValue); + +} + + +/** +* @brief Returns the AGC hold time. +* @param None. +* @retval uint8_t AGC hold time expressed in us. This parameter will be in the range: +* [0, 756/F_Xo]. +*/ +uint8_t SpiritRadioGetAGCHoldTimeUs(void) +{ + uint8_t tempRegValue; + + /* Reads the AGCCTRL_0 register */ + g_xStatus = SpiritSpiReadRegisters(AGCCTRL0_BASE, 1, &tempRegValue); + + /* Mask the HOLD_TIME field */ + tempRegValue &= 0x3F; + + /* Calculates the hold time value and return it */ + return (uint8_t)lroundf ((12.0/s_lXtalFrequency)*(tempRegValue*1e6)); + +} + + +/** +* @brief Sets the AGC hold time. +* @param cTime AGC hold time to write in the HOLD_TIME field of AGCCTRL_0 register. +* This parameter shall be in the range [0:63]. +* @retval None. +*/ +void SpiritRadioSetAGCHoldTime(uint8_t cTime) +{ + uint8_t tempRegValue; + + /* Check the parameter */ + s_assert_param(IS_AGC_HOLD_TIME(cTime)); + + /* Reads the AGCCTRL_0 register */ + SpiritSpiReadRegisters(AGCCTRL0_BASE, 1, &tempRegValue); + + /* Mask the HOLD_TIME field and write the new value */ + tempRegValue &= 0xC0; + tempRegValue |= cTime; + + /* Sets the AGCCTRL_0 register */ + g_xStatus = SpiritSpiWriteRegisters(AGCCTRL0_BASE, 1, &tempRegValue); + +} + + +/** +* @brief Returns the AGC hold time. +* @param None. +* @retval uint8_t AGC hold time read from the HOLD_TIME field of AGCCTRL_0 register. +* This parameter will be in the range [0:63]. +*/ +uint8_t SpiritRadioGetAGCHoldTime(void) +{ + uint8_t tempRegValue; + + /* Reads the AGCCTRL_0 register, mask the MEAS_TIME field and return the value */ + g_xStatus = SpiritSpiReadRegisters(AGCCTRL0_BASE, 1, &tempRegValue); + + return (tempRegValue & 0x3F); + +} + + +/** +* @brief Sets the AGC high threshold. +* @param cHighThreshold AGC high threshold to write in the THRESHOLD_HIGH field of AGCCTRL_1 register. +* This parameter shall be in the range [0:15]. +* @retval None. +*/ +void SpiritRadioSetAGCHighThreshold(uint8_t cHighThreshold) +{ + uint8_t tempRegValue; + + /* Check the parameter */ + s_assert_param(IS_AGC_THRESHOLD(cHighThreshold)); + + /* Reads the AGCCTRL_1 register */ + SpiritSpiReadRegisters(AGCCTRL1_BASE, 1, &tempRegValue); + + /* Mask the THRESHOLD_HIGH field and write the new value */ + tempRegValue &= 0x0F; + tempRegValue |= cHighThreshold<<4; + + /* Sets the AGCCTRL_1 register */ + g_xStatus = SpiritSpiWriteRegisters(AGCCTRL1_BASE, 1, &tempRegValue); + +} + + +/** +* @brief Returns the AGC high threshold. +* @param None. +* @retval uint8_t AGC high threshold read from the THRESHOLD_HIGH field of AGCCTRL_1 register. +* This parameter will be in the range [0:15]. +*/ +uint8_t SpiritRadioGetAGCHighThreshold(void) +{ + uint8_t tempRegValue; + + /* Reads the AGCCTRL_1 register, mask the THRESHOLD_HIGH field and return the value */ + g_xStatus = SpiritSpiReadRegisters(AGCCTRL1_BASE, 1, &tempRegValue); + + return ((tempRegValue & 0xF0)>>4); + +} + + +/** +* @brief Sets the AGC low threshold. +* @param cLowThreshold AGC low threshold to write in the THRESHOLD_LOW field of AGCCTRL_1 register. +* This parameter shall be in the range [0:15]. +* @retval None. +*/ +void SpiritRadioSetAGCLowThreshold(uint8_t cLowThreshold) +{ + uint8_t tempRegValue; + + /* Check the parameter */ + s_assert_param(IS_AGC_THRESHOLD(cLowThreshold)); + + /* Reads the AGCCTRL_1 register */ + SpiritSpiReadRegisters(AGCCTRL1_BASE, 1, &tempRegValue); + + /* Mask the THRESHOLD_LOW field and write the new value */ + tempRegValue &= 0xF0; + tempRegValue |= cLowThreshold; + + /* Sets the AGCCTRL_1 register */ + g_xStatus = SpiritSpiWriteRegisters(AGCCTRL1_BASE, 1, &tempRegValue); + +} + + +/** +* @brief Returns the AGC low threshold. +* @param None. +* @retval uint8_t AGC low threshold read from the THRESHOLD_LOW field of AGCCTRL_1 register. +* This parameter will be in the range [0:15]. +*/ +uint8_t SpiritRadioGetAGCLowThreshold(void) +{ + uint8_t tempRegValue; + + /* Reads the AGCCTRL_1 register, mask the THRESHOLD_LOW field and return the value */ + g_xStatus = SpiritSpiReadRegisters(AGCCTRL1_BASE, 1, &tempRegValue); + + return (tempRegValue & 0x0F); + +} + + +/** +* @brief Sets the clock recovery algorithm. +* @param xMode the Clock Recovery mode. This parameter can be one of the values defined in @ref ClkRecMode : +* @arg CLK_REC_PLL PLL alogrithm for clock recovery +* @arg CLK_REC_DLL DLL alogrithm for clock recovery +* @retval None. +*/ +void SpiritRadioSetClkRecMode(ClkRecMode xMode) +{ + uint8_t tempRegValue; + + /* Check the parameter */ + s_assert_param(IS_CLK_REC_MODE(xMode)); + + /* Reads the FDEV_0 register */ + SpiritSpiReadRegisters(FDEV0_BASE, 1, &tempRegValue); + + /* Mask the CLOCK_REC_ALGO_SEL field and write the new value */ + tempRegValue &= 0xF7; + tempRegValue |= (uint8_t)xMode; + + /* Sets the FDEV_0 register */ + g_xStatus = SpiritSpiWriteRegisters(FDEV0_BASE, 1, &tempRegValue); + +} + + +/** +* @brief Returns the Clock Recovery working mode. +* @param None. +* @retval ClkRecMode Clock Recovery mode. This parameter can be one of the values defined in @ref ClkRecMode : +* @arg CLK_REC_PLL PLL alogrithm for clock recovery +* @arg CLK_REC_DLL DLL alogrithm for clock recovery +*/ +ClkRecMode SpiritRadioGetClkRecMode(void) +{ + uint8_t tempRegValue; + + /* Reads the FDEV_0 register, mask the CLOCK_REC_ALGO_SEL field and return the value */ + g_xStatus = SpiritSpiReadRegisters(FDEV0_BASE, 1, &tempRegValue); + + return (ClkRecMode)(tempRegValue & 0x08); + +} + + +/** +* @brief Sets the clock recovery proportional gain. +* @param cPGain the Clock Recovery proportional gain to write in the CLK_REC_P_GAIN field of CLOCKREC register. +* It represents is log2 value of the clock recovery proportional gain. +* This parameter shall be in the range [0:7]. +* @retval None. +*/ +void SpiritRadioSetClkRecPGain(uint8_t cPGain) +{ + uint8_t tempRegValue; + + /* Check the parameter */ + s_assert_param(IS_CLK_REC_P_GAIN(cPGain)); + + /* Reads the CLOCKREC register */ + SpiritSpiReadRegisters(CLOCKREC_BASE, 1, &tempRegValue); + + /* Mask the CLK_REC_P_GAIN field and write the new value */ + tempRegValue &= 0x1F; + tempRegValue |= (cPGain<<5); + + /* Sets the CLOCKREC register */ + g_xStatus = SpiritSpiWriteRegisters(CLOCKREC_BASE, 1, &tempRegValue); + +} + + +/** +* @brief Returns the log2 of the clock recovery proportional gain. +* @param None. +* @retval uint8_t Clock Recovery proportional gain read from the CLK_REC_P_GAIN field of CLOCKREC register. +* This parameter will be in the range [0:7]. +*/ +uint8_t SpiritRadioGetClkRecPGain(void) +{ + uint8_t tempRegValue; + + /* Reads the CLOCKREC register, mask the CLK_REC_P_GAIN field and return the value */ + g_xStatus = SpiritSpiReadRegisters(CLOCKREC_BASE, 1, &tempRegValue); + + return ((tempRegValue & 0xEF)>>5); + +} + + +/** +* @brief Sets the clock recovery integral gain. +* @param cIGain the Clock Recovery integral gain to write in the CLK_REC_I_GAIN field of CLOCKREC register. +* This parameter shall be in the range [0:15]. +* @retval None. +*/ +void SpiritRadioSetClkRecIGain(uint8_t cIGain) +{ + uint8_t tempRegValue; + + /* Check the parameter */ + s_assert_param(IS_CLK_REC_I_GAIN(cIGain)); + + /* Reads the CLOCKREC register */ + SpiritSpiReadRegisters(CLOCKREC_BASE, 1, &tempRegValue); + + /* Mask the CLK_REC_P_GAIN field and write the new value */ + tempRegValue &= 0xF0; + tempRegValue |= cIGain; + + /* Sets the CLOCKREC register */ + g_xStatus = SpiritSpiWriteRegisters(CLOCKREC_BASE, 1, &tempRegValue); + +} + + +/** +* @brief Returns the clock recovery integral gain. +* @param None. +* @retval uint8_t Clock Recovery integral gain read from the +* CLK_REC_I_GAIN field of CLOCKREC register. +* This parameter will be in the range [0:15]. +*/ +uint8_t SpiritRadioGetClkRecIGain(void) +{ + uint8_t tempRegValue; + + /* Reads the CLOCKREC register, mask the CLK_REC_I_GAIN field and return the value */ + g_xStatus = SpiritSpiReadRegisters(CLOCKREC_BASE, 1, &tempRegValue); + + return (tempRegValue & 0x0F); + +} + + +/** +* @brief Sets the postfilter length for clock recovery algorithm. +* @param xLength the postfilter length in symbols. This parameter can be one of the values defined in @ref PstFltLength : +* @arg PSTFLT_LENGTH_8 Postfilter length is 8 symbols +* @arg PSTFLT_LENGTH_16 Postfilter length is 16 symbols +* @retval None. +*/ +void SpiritRadioSetClkRecPstFltLength(PstFltLength xLength) +{ + uint8_t tempRegValue; + + /* Check the parameter */ + s_assert_param(IS_PST_FLT_LENGTH(xLength)); + + /* Reads the CLOCKREC register */ + SpiritSpiReadRegisters(CLOCKREC_BASE, 1, &tempRegValue); + + /* Mask the PSTFLT_LEN field and write the new value */ + tempRegValue &= 0xEF; + tempRegValue |= (uint8_t)xLength; + + /* Sets the CLOCKREC register */ + g_xStatus = SpiritSpiWriteRegisters(CLOCKREC_BASE, 1, &tempRegValue); + +} + + +/** +* @brief Returns the postfilter length for clock recovery algorithm. +* @param None. +* @retval PstFltLength Postfilter length in symbols. This parameter can be one of the values defined in @ref PstFltLength : +* @arg PSTFLT_LENGTH_8 Postfilter length is 8 symbols +* @arg PSTFLT_LENGTH_16 Postfilter length is 16 symbols +*/ +PstFltLength SpiritRadioGetClkRecPstFltLength(void) +{ + uint8_t tempRegValue; + + /* Reads the CLOCKREC register, mask the PSTFLT_LEN field and return the value */ + g_xStatus = SpiritSpiReadRegisters(CLOCKREC_BASE, 1, &tempRegValue); + + return (PstFltLength)(tempRegValue & 0x10); + +} + + +/** +* @brief Enables or Disables the received data blanking when the CS is under the threshold. +* @param xNewState new state of this mode. +* This parameter can be: S_ENABLE or S_DISABLE . +* @retval None. +*/ +void SpiritRadioCsBlanking(SpiritFunctionalState xNewState) +{ + uint8_t tempRegValue; + + /* Check the parameters */ + s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState)); + + /* Reads the ANT_SELECT_CONF_BASE and mask the CS_BLANKING BIT field */ + SpiritSpiReadRegisters(ANT_SELECT_CONF_BASE, 1, &tempRegValue); + + if(xNewState == S_ENABLE) + { + tempRegValue |= ANT_SELECT_CS_BLANKING_MASK; + } + else + { + tempRegValue &= (~ANT_SELECT_CS_BLANKING_MASK); + } + + /* Writes the new value in the ANT_SELECT_CONF register */ + g_xStatus = SpiritSpiWriteRegisters(ANT_SELECT_CONF_BASE, 1, &tempRegValue); + + +} + +/** +* @brief Enables or Disables the persistent RX mode. +* @param xNewState new state of this mode. +* This parameter can be: S_ENABLE or S_DISABLE . +* @retval None. +*/ +void SpiritRadioPersistenRx(SpiritFunctionalState xNewState) +{ + uint8_t tempRegValue; + + /* Check the parameters */ + s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState)); + + /* Reads the PROTOCOL0_BASE and mask the PROTOCOL0_PERS_RX_MASK bitfield */ + SpiritSpiReadRegisters(PROTOCOL0_BASE, 1, &tempRegValue); + + if(xNewState == S_ENABLE) + { + tempRegValue |= PROTOCOL0_PERS_RX_MASK; + } + else + { + tempRegValue &= (~PROTOCOL0_PERS_RX_MASK); + } + + /* Writes the new value in the PROTOCOL0_BASE register */ + g_xStatus = SpiritSpiWriteRegisters(PROTOCOL0_BASE, 1, &tempRegValue); + +} + +/** +* @brief Enables or Disables the synthesizer reference divider. +* @param xNewState new state for synthesizer reference divider. +* This parameter can be: S_ENABLE or S_DISABLE . +* @retval None. +*/ +void SpiritRadioSetRefDiv(SpiritFunctionalState xNewState) +{ + uint8_t tempRegValue; + + /* Check the parameters */ + s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState)); + + /* Reads the SYNTH_CONFIG1_BASE and mask the REFDIV bit field */ + SpiritSpiReadRegisters(SYNTH_CONFIG1_BASE, 1, &tempRegValue); + + if(xNewState == S_ENABLE) + { + tempRegValue |= 0x80; + } + else + { + tempRegValue &= 0x7F; + } + + /* Writes the new value in the SYNTH_CONFIG1_BASE register */ + g_xStatus = SpiritSpiWriteRegisters(SYNTH_CONFIG1_BASE, 1, &tempRegValue); + +} + +/** +* @brief Get the the synthesizer reference divider state. +* @param void. +* @retval None. +*/ +SpiritFunctionalState SpiritRadioGetRefDiv(void) +{ + uint8_t tempRegValue; + + g_xStatus = SpiritSpiReadRegisters(SYNTH_CONFIG1_BASE, 1, &tempRegValue); + + if(((tempRegValue>>7)&0x1)) + { + return S_ENABLE; + } + else + { + return S_DISABLE; + } + +} + +/** +* @brief Enables or Disables the synthesizer reference divider. +* @param xNewState new state for synthesizer reference divider. +* This parameter can be: S_ENABLE or S_DISABLE . +* @retval None. +*/ +void SpiritRadioSetDigDiv(SpiritFunctionalState xNewState) +{ + uint8_t tempRegValue; + + /* Check the parameters */ + s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState)); + + /* Reads the XO_RCO_TEST_BASE and mask the PD_CLKDIV bit field */ + SpiritSpiReadRegisters(XO_RCO_TEST_BASE, 1, &tempRegValue); + + if(xNewState == S_ENABLE) + { + tempRegValue &= 0xf7; + } + else + { + + tempRegValue |= 0x08; + } + + /* Writes the new value in the XO_RCO_TEST_BASE register */ + g_xStatus = SpiritSpiWriteRegisters(XO_RCO_TEST_BASE, 1, &tempRegValue); + +} + +/** +* @brief Get the the synthesizer reference divider state. +* @param void. +* @retval None. +*/ +SpiritFunctionalState SpiritRadioGetDigDiv(void) +{ + uint8_t tempRegValue; + + g_xStatus = SpiritSpiReadRegisters(XO_RCO_TEST_BASE, 1, &tempRegValue); + + if(((tempRegValue>>3)&0x1)) + { + return S_DISABLE; + } + else + { + return S_ENABLE; + } + +} + +/** +* @brief Returns the XTAL frequency. +* @param void. +* @retval uint32_t XTAL frequency. +*/ +uint32_t SpiritRadioGetXtalFrequency(void) +{ + return s_lXtalFrequency; +} + +/** +* @brief Sets the XTAL frequency. +* @param uint32_t XTAL frequency. +* @retval void. +*/ +void SpiritRadioSetXtalFrequency(uint32_t lXtalFrequency) +{ + s_lXtalFrequency = lXtalFrequency; +} + +/** +* @} +*/ + + +/** +* @} +*/ + + +/** +* @} +*/ + + + +/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/ +