diff --git a/df_datalink_sp/src/networking/phy_layer/phy_layer.c b/df_datalink_sp/src/networking/phy_layer/phy_layer.c index 97ceead..e1f4f62 100644 --- a/df_datalink_sp/src/networking/phy_layer/phy_layer.c +++ b/df_datalink_sp/src/networking/phy_layer/phy_layer.c @@ -759,6 +759,59 @@ uint32_t Phy_GetTimeComp(L1_FRAME_TYPE frameType) } } +/*****************************************************************************/ +/** + * @brief Get frequency estimation of last valid frame. + * + * @param instPtr a pointer to physical instance + * + * @return frequency estimation + * + ******************************************************************************/ +double Phy_GetFreqEst(PHY_INST *instPtr) +{ + ASSERT(instPtr != NULL); + uint32_t coarseReg, fineReg, estAbs; + uint8_t acqFreqIdx; + int8_t syncFreqIdx; + L1_FRAME_TYPE frameType; + double coarse, fine; + + + frameType = Phy_GetLastRecvFrameType(instPtr); + if (frameType > L1_1M2BPS_5MS_FRAME || frameType <= L1_NONE_FRAME) + { + return INFINITY; // FIXME + } + + coarseReg = PhyRead(instPtr, COASE_FREQEST); + acqFreqIdx = (coarseReg & COASE_FREQEST_ACQ_MASK) >> COASE_FREQEST_ACQ_SHIFT; + syncFreqIdx = (coarseReg & COASE_FREQEST_SYNC_MASK) >> COASE_FREQEST_SYNC_SHIFT; + fineReg = PhyRead(instPtr, FINE_FREQEST); + estAbs = fineReg & FINE_FREQEST_VAL_MASK; + if (frameType >= L1_200KBPS_5MS_FRAME) + { + // 1.5M Rc + coarse = (double)(80 - acqFreqIdx) * (31.25e3 / 4); + coarse += (double)syncFreqIdx * 1.5e6 / 64 / 128; + + fine = 12e6/2048*((double)estAbs)/8192.0; + } + else + { + // 12M Rc + coarse = (double)(8 - acqFreqIdx) * (250e3 / 4); + coarse += (double)syncFreqIdx * 12e6 / 64 / 128; + + fine = 48e6/2048*((double)estAbs)/8192.0; + } + + fine = ((fineReg & FINE_FREQEST_SIGN_MASK) == FINE_FREQEST_SIGN_NEG) ? + -fine : fine; + + return (coarse + fine); +} + /*****************************************************************************/ /** * @brief Get coarse frequency estimation of last valid frame. @@ -778,9 +831,9 @@ double Phy_GetCoarseFreqEst(PHY_INST *instPtr) double freqEst; frameType = Phy_GetLastRecvFrameType(instPtr); - if (frameType > L1_1M2BPS_5MS_FRAME || frameType == L1_NONE_FRAME) + if (frameType > L1_1M2BPS_5MS_FRAME || frameType <= L1_NONE_FRAME) { - return INFINITY; // FIXME: + return INFINITY; // FIXME } regValue = PhyRead(instPtr, COASE_FREQEST); acqFreqIdx = (regValue & COASE_FREQEST_ACQ_MASK) >> COASE_FREQEST_ACQ_SHIFT; @@ -801,6 +854,43 @@ double Phy_GetCoarseFreqEst(PHY_INST *instPtr) return freqEst; } +/*****************************************************************************/ +/** + * @brief Get fine frequency estimation of last valid frame. + * + * @param instPtr a pointer to physical instance + * + * @return frequency estimation + * + ******************************************************************************/ +double Phy_GetFineFreqEst(PHY_INST *instPtr) +{ + uint32_t regValue, estAbs; + double freqEst; + L1_FRAME_TYPE frameType; + frameType = Phy_GetLastRecvFrameType(instPtr); + if (frameType > L1_1M2BPS_5MS_FRAME || frameType <= L1_NONE_FRAME) + { + return INFINITY; // FIXME + } + + regValue = PhyRead(instPtr, FINE_FREQEST); + estAbs = regValue & FINE_FREQEST_VAL_MASK; + if (frameType >= L1_200KBPS_5MS_FRAME) + { + // 1.5M Rc + freqEst = 12e6/2048*((double)estAbs)/8192.0; + } + else + { + // 12M Rc + freqEst = 48e6/2048*((double)estAbs)/8192.0; + } + freqEst = ((regValue & FINE_FREQEST_SIGN_MASK) == FINE_FREQEST_SIGN_NEG) ? + -freqEst : freqEst; + return freqEst; +} + /*****************************************************************************/ /** * @brief Setup a frequency hopping pattern. diff --git a/df_datalink_sp/src/networking/phy_layer/phy_reg.h b/df_datalink_sp/src/networking/phy_layer/phy_reg.h index 2feb5a3..684f146 100644 --- a/df_datalink_sp/src/networking/phy_layer/phy_reg.h +++ b/df_datalink_sp/src/networking/phy_layer/phy_reg.h @@ -229,15 +229,31 @@ #define COASE_FREQEST_ACQ_MASK 0x000000FFU #define COASE_FREQEST_SYNC_SHIFT 8 #define COASE_FREQEST_SYNC_WIDTH 8 -#define COASE_FREQEST_SYNC_MASK 0x000FF00U +#define COASE_FREQEST_SYNC_MASK 0x0000FF00U +#define COASE_TYPE_SHIFT 16 +#define COASE_TYPE_WIDTH 8 +#define COASE_TYPE_MASK 0x00FF0000U +#define COASE_TYPE_2KBPS_20MS 0x00010000U +#define COASE_TYPE_2KBPS_100MS 0x00020000U +#define COASE_TYPE_10KBPS_10MS 0x00030000U +#define COASE_TYPE_10KBPS_20MS 0x00040000U +#define COASE_TYPE_40KBPS_20MS 0x00050000U +#define COASE_TYPE_40KBPS_10MS 0x00060000U +#define COASE_TYPE_200KBPS_5MS 0x00070000U +#define COASE_TYPE_1M2BPS_5MS 0x00080000U /** * Register: FINE_FREQEST */ #define FINE_FREQEST 0x00000040U -#define FINE_FREQEST_SHIFT 0 -#define FINE_FREQEST_WIDTH 32 -#define FINE_FREQEST_MASK 0xFFFFFFFFU +#define FINE_FREQEST_VAL_SHIFT 0 +#define FINE_FREQEST_VAL_WIDTH 24 +#define FINE_FREQEST_VAL_MASK 0x00FFFFFFU +#define FINE_FREQEST_SIGN_SHIFT 24 +#define FINE_FREQEST_SIGN_WIDTH 8 +#define FINE_FREQEST_SIGN_MASK 0xFF000000U +#define FINE_FREQEST_SIGN_POS 0x00000000U +#define FINE_FREQEST_SIGN_NEG 0x01000000U /** * Register: BEAM_SELECT