/*****************************************************************************/ /** * @file phy_layer.h * @author FanHao (hao_fan_bit_ee@163.com) * @brief Physical layer control implementation file. * @version 0.0 * @date 2023-04-24 * * @copyright Copyright(c) 2024 Beijing Institute of Technology.\n * Lab of Communication and Network * ******************************************************************************/ /** * @addtogroup PhysicalLayer * @{ */ /***************************** Include Files *********************************/ #include #include #include #include "phy_layer.h" #include "phy_reg.h" #include "util.h" #include "error.h" #ifndef EMULATION #include "xbram.h" #endif /************************** Constant Definitions *****************************/ /** * @name PhysicalLayer_Private_Constants * @{ */ #define PHY_TIME_WORD_H_MAX UINT32_MAX #define PHY_TIME_WORD_L_MAX 200000U // 2 ms/10 ns #define L1_FRAME_LEN_MAX (16384 / 8) // byte #define L1_FRAME_ADV_24MS_LEN (520 / 8) // byte #define L1_FRAME_ACK_8MS_LEN (520 / 8) // byte #define L1_FRAME_128KBPS_4MS_LEN (784 / 8) // byte #define L1_FRAME_512KBPS_4MS_LEN (2584 / 8) // byte #define L1_FRAME_2MBPS_4MS_LEN (10224 / 8) // byte //#define L1_FRAME_ADV_24MS_COMP 1399800 // *10ns(Timer_L) #define L1_FRAME_ADV_24MS_COMP 1464362 // *10ns(Timer_L) #define L1_FRAME_ACK_8MS_COMP 598408 // *10ns(Timer_L) #define L1_FRAME_128KBPS_4MS_COMP 9950 // *10ns(Timer_L) #define L1_FRAME_512KBPS_4MS_COMP 9950 // *10ns(Timer_L) #define L1_FRAME_2MBPS_4MS_COMP 9950 // *10ns(Timer_L) #define L1_ANTCONFIG_MAX_LEN 8192 // byte #define L1_TXRXDATA_MAX_LEN 4096 // byte #define ANT_COINFO_LEN 40 // bytes, antenna configuration length of each hop #define ATTN_DEFAULT 0 #define ATTN_ADV_24MS ATTN_DEFAULT #define ATTN_ACK_8MS ATTN_DEFAULT #define ATTN_128KBPS_4MS ATTN_DEFAULT #define ATTN_512KBPS_4MS ATTN_DEFAULT #define ATTN_2MBPS_4MS ATTN_DEFAULT /** @} PhysicalLayer_Private_Constants*/ /************************** Variable Definitions *****************************/ extern const uint16_t freqTable[L1_FRAME_MAX_HOPS]; //extern const int16_t antCalTable[L1_ANT_NUM][L1_FRAME_MAX_HOPS][L1_ANT_CH_NUM]; extern const uint8_t hopPattern_ADV_24MS[L1_FRAME_ADV_24MS_HOPS]; extern const uint8_t hopPattern_ACK_8MS[L1_FRAME_ACK_8MS_HOPS]; extern const uint8_t hopPattern_128KBPS_4MS[L1_FRAME_128KBPS_4MS_HOPS]; extern const uint8_t hopPattern_512KBPS_4MS[L1_FRAME_512KBPS_4MS_HOPS]; extern const uint8_t hopPattern_2MBPS_4MS[L1_FRAME_2MBPS_4MS_HOPS]; /***************** Macros (Inline Functions) Definitions *********************/ /************************** Function Prototypes ******************************/ static void Phy_RcdShift(PHY_RCD *rcd, int32_t netxVal); static int32_t Phy_SetSendData(PHY_INST *instPtr, L1_FRAME_TYPE frameType, uint8_t *dataBuff); /**************************** Type Definitions *******************************/ /************************** Variable Definitions *****************************/ /*****************************************************************************/ /** * @brief Shift l1 status record.(newval->next->curr->last) * * @param instPtr A pointer to physical layer control instance. * * @return NONE. * ******************************************************************************/ static void Phy_RcdShift(PHY_RCD *rcd, int32_t netxVal) { ASSERT(rcd != NULL); rcd->last = rcd->curr; rcd->curr = rcd->next; rcd->next = netxVal; } /*****************************************************************************/ /** * @brief Setup data will be sent in next slot. * * @param instPtr A pointer to physical layer control instance. * * @return FAILURE Error occurred.\n * SUCCESS Setting data successful. * ******************************************************************************/ static int32_t Phy_SetSendData(PHY_INST *instPtr, L1_FRAME_TYPE frameType, uint8_t *dataBuff) { ASSERT(instPtr != NULL); ASSERT(dataBuff != NULL); uint32_t frameLen, sendCmd; frameLen = Phy_GetFrameLen(frameType); if (frameLen == L1_FRAME_NONE_LEN) { DBG_ERROR("Invalid frame length.\n"); return EPARAM; } instPtr->sendDataOffset = (L1_TXRXDATA_MAX_LEN >> 1) - instPtr->sendDataOffset; memcpy((uint8_t *)(instPtr->sendDataAddr + instPtr->sendDataOffset), dataBuff, NORMALIZE_SIZE(frameLen)); sendCmd = frameLen & SEND_DATA_CMD_LEN_MASK; sendCmd |= (instPtr->sendDataOffset << SEND_DATA_CMD_OFFSET_SHIFT) & SEND_DATA_CMD_OFFSET_MASK; // Physical layer start fetching data. PhyWrite(instPtr, SEND_DATA_CMD, sendCmd); return SUCCESS; } /** * @addtogroup PhysicalLayer_Utility * @{ */ /*****************************************************************************/ /** * @brief Check whether a frame was detected. (Do not check if the frame was * deoced.) * * @param instPtr A pointer to physical layer control instance. * * @return true * false * ******************************************************************************/ inline bool Phy_IsFrameDetected(PHY_INST *instPtr) { ASSERT(instPtr != NULL); if (instPtr->isAcq && instPtr->isFrameSync) { return true; } else { return false; } } /*****************************************************************************/ /** * @brief Check whether a frame was received. (Do not check if the frame was * crashed.) * * @param instPtr A pointer to physical layer control instance. * * @return true * false * ******************************************************************************/ inline bool Phy_IsFrameReceived(PHY_INST *instPtr) { ASSERT(instPtr != NULL); if (instPtr->isAcq && instPtr->isFrameSync && instPtr->isDecode) { return true; } else { return false; } } /*****************************************************************************/ /** * @brief Check whether a frame was valid. (if the frame was crashed, it will * be regarded as not valid. * * @param instPtr * * @return true * false * ******************************************************************************/ inline bool Phy_IsFrameValid(PHY_INST *instPtr) { ASSERT(instPtr != NULL); return instPtr->isValid; } /*****************************************************************************/ /** * @brief Get corresponding frame length in byte of L1 frame. * * @param frameType * * @return Corresponding frame length * L1_FRAME_NONE_LEN if the frame type code cannot be recognized. * ******************************************************************************/ uint32_t Phy_GetFrameLen(L1_FRAME_TYPE frameType) { switch (frameType) { case L1_FRAME_ADV_24MS: return L1_FRAME_ADV_24MS_LEN; case L1_FRAME_ACK_8MS: return L1_FRAME_ACK_8MS_LEN; case L1_FRAME_128KBPS_4MS: return L1_FRAME_128KBPS_4MS_LEN; case L1_FRAME_512KBPS_4MS: return L1_FRAME_512KBPS_4MS_LEN; case L1_FRAME_2MBPS_4MS: return L1_FRAME_2MBPS_4MS_LEN; default: return L1_FRAME_NONE_LEN; } } /*****************************************************************************/ /** * @brief Get the corresponding frequency hopping pattern length of a * specified L1 frame type. * * @param frameType a L1 frame type enumeration. * * @return SUCCESS * FAILURE frame type cannot be recognized * ******************************************************************************/ uint32_t Phy_GetHopLength(L1_FRAME_TYPE frameType) { switch (frameType) { case L1_FRAME_ADV_24MS: return L1_FRAME_ADV_24MS_HOPS; case L1_FRAME_ACK_8MS: return L1_FRAME_ACK_8MS_HOPS; case L1_FRAME_128KBPS_4MS: return L1_FRAME_128KBPS_4MS_HOPS; case L1_FRAME_512KBPS_4MS: return L1_FRAME_512KBPS_4MS_HOPS; case L1_FRAME_2MBPS_4MS: return L1_FRAME_2MBPS_4MS_HOPS; default: return L1_FRAME_NONE_HOPS; } } /*****************************************************************************/ /** * @brief Get the corresponding time compensation value (time interval from * frame start to frame sync) * * @param frameType a L1 frame type enumeration. * * @return 32bit unsigned integer (10ns) * ******************************************************************************/ uint32_t Phy_GetTimeComp(L1_FRAME_TYPE frameType) { switch (frameType) { case L1_FRAME_ADV_24MS: return L1_FRAME_ADV_24MS_COMP; case L1_FRAME_ACK_8MS: return L1_FRAME_ACK_8MS_COMP; case L1_FRAME_128KBPS_4MS: return L1_FRAME_128KBPS_4MS_COMP; case L1_FRAME_512KBPS_4MS: return L1_FRAME_512KBPS_4MS_COMP; case L1_FRAME_2MBPS_4MS: return L1_FRAME_2MBPS_4MS_COMP; default: return L1_FRAME_NONE_COMP; } } /*****************************************************************************/ /** * @brief Get frame type of the frame in receive data buffer (Base on PL Record). * * @param instPtr A pointer to physical layer control instance. * * @return Layer1 frame type. Refer "frame_def.h" * ******************************************************************************/ inline L1_FRAME_TYPE Phy_GetLastRecvFrameType(PHY_INST *instPtr) { ASSERT(instPtr != NULL); if (Phy_IsFrameReceived(instPtr) == false) { return L1_FRAME_NONE; } uint32_t frame_type = (PhyRead(instPtr, COASE_FREQEST) & COASE_TYPE_MASK); switch (frame_type) { case COASE_TYPE_ADV_24MS: return L1_FRAME_ADV_24MS; case COASE_TYPE_ACK_8MS: return L1_FRAME_ACK_8MS; case COASE_TYPE_128KBPS_4MS: return L1_FRAME_128KBPS_4MS; case COASE_TYPE_512KBPS_4MS: return L1_FRAME_512KBPS_4MS; case COASE_TYPE_2MBPS_4MS: return L1_FRAME_2MBPS_4MS; default: return L1_FRAME_NONE; } } /*****************************************************************************/ /** * @brief Get frame type of the frame was sent in last slot. * * @param instPtr A pointer to physical layer control instance. * * @return Layer1 frame type. Refer "frame_def.h" * ******************************************************************************/ inline L1_FRAME_TYPE Phy_GetLastSendFrameType(PHY_INST *instPtr) { ASSERT(instPtr != NULL); if (instPtr->tor.last != PHY_TOR_TX) { return L1_FRAME_NONE; } return instPtr->frameType.last; } /** @} PhysicalLayer_Utility*/ /** * @addtogroup PhysicalLayer_Main * @{ */ /*****************************************************************************/ /** * @brief Initialize Physical Layer instance, allocate memory for buffers, * apply a self test. * * @param instPtr a pointer to physical instance * @param phyConfig a pointer to configuration structure. * * @return SUCCESS * ******************************************************************************/ int32_t Phy_Init(PHY_INST **instPtr, PHY_CONFIG *phyConfig) { ASSERT(instPtr != NULL); ASSERT(phyConfig != NULL); int32_t Status; *instPtr = (PHY_INST *)malloc(sizeof(PHY_INST)); if ((*instPtr) == NULL) { return ENOMEM; } memset(*instPtr, 0x00, sizeof(PHY_INST)); memcpy(&((*instPtr)->phyCofig), phyConfig, sizeof(PHY_CONFIG)); (*instPtr)->isPhyEn = false; (*instPtr)->isAcq = false; (*instPtr)->isFrameSync = false; (*instPtr)->isDecode = false; (*instPtr)->isValid = false; (*instPtr)->recvFsTime.int_part = UINT32_MAX; (*instPtr)->recvFsTime.frac_part = UINT32_MAX; (*instPtr)->recvSlotTime.int_part = UINT32_MAX; (*instPtr)->recvSlotTime.frac_part = UINT32_MAX; (*instPtr)->antConfigOffset = 0; (*instPtr)->sendDataOffset = 0; (*instPtr)->lastLogTime = 0; Phy_AntConfigInit(&((*instPtr)->antConfig)); memset(&((*instPtr))->tor, PHY_TOR_SUSPEND, sizeof(PHY_RCD)); memset(&((*instPtr)->frameType), L1_FRAME_NONE, sizeof(PHY_RCD)); memset(&((*instPtr)->antIndex), (int32_t)L1_INIT_ANT_IDX, sizeof(PHY_RCD)); memset(&((*instPtr)->hwSate), 0x00, sizeof(HWSTATE)); memset(&((*instPtr)->phyLog), 0x00, sizeof(PHYLOG)); #ifndef EMULATION XBram_Config *bramConfigPtr; XBram antConfigBram; XBram txDataBram; XBram rxDataBram; bramConfigPtr = XBram_LookupConfig(phyConfig->antBramId); if (bramConfigPtr == NULL) { Phy_Destroy(*instPtr); return EDCONF; } Status = XBram_CfgInitialize(&antConfigBram, bramConfigPtr, bramConfigPtr->CtrlBaseAddress); if (Status != SUCCESS) { Phy_Destroy(*instPtr); return Status; } /* * Execute the BRAM driver selftest. */ Status = XBram_SelfTest(&antConfigBram, 0); if (Status != SUCCESS) { Phy_Destroy(*instPtr); return Status; } bramConfigPtr = XBram_LookupConfig(phyConfig->txBramId); if (bramConfigPtr == NULL) { Phy_Destroy(*instPtr); return EDCONF; } Status = XBram_CfgInitialize(&txDataBram, bramConfigPtr, bramConfigPtr->CtrlBaseAddress); if (Status != SUCCESS) { Phy_Destroy(*instPtr); return Status; } /* * Execute the BRAM driver selftest. */ Status = XBram_SelfTest(&txDataBram, 0); if (Status != SUCCESS) { Phy_Destroy(*instPtr); return Status; } bramConfigPtr = XBram_LookupConfig(phyConfig->rxBramId); if (bramConfigPtr == NULL) { Phy_Destroy(*instPtr); return EDCONF; } Status = XBram_CfgInitialize(&rxDataBram, bramConfigPtr, bramConfigPtr->CtrlBaseAddress); if (Status != SUCCESS) { Phy_Destroy(*instPtr); return Status; } /* * Execute the BRAM driver selftest. */ Status = XBram_SelfTest(&rxDataBram, 0); if (Status != SUCCESS) { Phy_Destroy(*instPtr); return Status; } (*instPtr)->antConfigAddr = antConfigBram.Config.MemBaseAddress; (*instPtr)->recvDataAddr = rxDataBram.Config.MemBaseAddress; (*instPtr)->sendDataAddr = txDataBram.Config.MemBaseAddress; #ifdef HSJL_GE // Zynq MPSoC (Zynq UltraScale+) /* Initialize the XAdc driver. */ XSysMon_Config *sysmonConfigPtr; XSysMon *sysmonPtr = &((*instPtr)->sysMon); /* * Initialize the SysMon driver. */ sysmonConfigPtr = XSysMon_LookupConfig(phyConfig->hwSysmonId); if (sysmonConfigPtr == NULL) { return FAILURE; } XSysMon_CfgInitialize(sysmonPtr, sysmonConfigPtr, sysmonConfigPtr->BaseAddress); /* * Self Test the System Monitor/ADC device */ Status = XSysMon_SelfTest(sysmonPtr); if (Status != XST_SUCCESS) { return FAILURE; } #else /* Initialize the XAdc driver. */ XAdcPs_Config *xadcConfigPtr; xadcConfigPtr = XAdcPs_LookupConfig(phyConfig->hwXadcId); if (xadcConfigPtr == NULL) { Phy_Destroy(*instPtr); return EDCONF; } XAdcPs_CfgInitialize(&((*instPtr)->hwXadc), xadcConfigPtr, xadcConfigPtr->BaseAddress); /* Self Test the XADC/ADC device */ Status = XAdcPs_SelfTest(&((*instPtr)->hwXadc)); if (Status != SUCCESS) { Phy_Destroy(*instPtr); return Status; } /* Disable the Channel Sequencer before configuring the Sequence registers. */ XAdcPs_SetSequencerMode(&((*instPtr)->hwXadc), XADCPS_SEQ_MODE_SAFE); #endif #else (*instPtr)->antConfigAddr = NULL; (*instPtr)->recvDataAddr = NULL; (*instPtr)->sendDataAddr = NULL; (*instPtr)->antConfigAddr = (uintptr_t)calloc(L1_ANTCONFIG_MAX_LEN / sizeof(uint64_t), sizeof(uint64_t)); if ((*instPtr)->antConfigAddr == (uintptr_t)NULL) { Phy_Destroy(*instPtr); return EDCONF; } (*instPtr)->recvDataAddr = (uintptr_t)calloc(L1_TXRXDATA_MAX_LEN / sizeof(uint64_t), sizeof(uint64_t)); if ((*instPtr)->recvDataAddr == (uintptr_t)NULL) { Phy_Destroy(*instPtr); return EDCONF; } (*instPtr)->sendDataAddr = (uintptr_t)calloc(L1_TXRXDATA_MAX_LEN / sizeof(uint64_t), sizeof(uint64_t)); if ((*instPtr)->sendDataAddr == (uintptr_t)NULL) { Phy_Destroy(*instPtr); return EDCONF; } #endif return SUCCESS; } /*****************************************************************************/ /** * @brief Destroy physical layer instance, free allocated memory. * * @param instPtr a pointer to physical instance * * @return NONE * ******************************************************************************/ void Phy_Destroy(PHY_INST *instPtr) { if (instPtr == NULL) { return; } #ifdef EMULATION free((void *)instPtr->antConfigAddr); free((void *)instPtr->recvDataAddr); free((void *)instPtr->sendDataAddr); #endif free(instPtr); } /*****************************************************************************/ /** * @brief Start physical layer * * @param instPtr a pointer to physical instance * * @return NONE * ******************************************************************************/ void Phy_Start(PHY_INST *instPtr) { ASSERT(instPtr != NULL); uint32_t phyMainCtrl = PhyRead(instPtr, PHY_MAIN_CTRL); if ((phyMainCtrl & PHY_MAIN_CTRL_EN_MASK) == PHY_MAIN_CTRL_EN_EN) { DBG_WARNING("Physical layer was already enabled.\n"); } instPtr->isPhyEn = true; // Enable CRC check automatically PhyWrite(instPtr, PHY_MAIN_CTRL, (phyMainCtrl | PHY_MAIN_CTRL_EN_EN)); } /*****************************************************************************/ /** * @brief Halt physical layer operation * * @param instPtr a pointer to physical instance * * @return NONE * ******************************************************************************/ void Phy_Halt(PHY_INST *instPtr) { ASSERT(instPtr != NULL); uint32_t phyMainCtrl = PhyRead(instPtr, PHY_MAIN_CTRL); if ((phyMainCtrl & PHY_MAIN_CTRL_EN_MASK) == PHY_MAIN_CTRL_EN_DSBL) { DBG_WARNING("Physical layer was already halted.\n"); } instPtr->isPhyEn = false; PhyWrite(instPtr, PHY_MAIN_CTRL, (phyMainCtrl & (~PHY_MAIN_CTRL_EN_MASK))); } /*****************************************************************************/ /** * @brief Set physical layer working mode. * * @param instPtr physical instance * @param modeCod intend mode code * * @return SUCCESS * other * ******************************************************************************/ int32_t Phy_SetMode(PHY_INST *instPtr, PHY_MODE modeCod) { ASSERT(instPtr != NULL); uint32_t phyMainCtrl = PhyRead(instPtr, PHY_MAIN_CTRL) & ~PHY_MAIN_CTRL_MODE_MASK; switch (modeCod) { case PHY_MODE_NONE: phyMainCtrl |= PHY_MAIN_CTRL_MODE_NONE; break; case PHY_MODE_LISTEN: phyMainCtrl |= PHY_MAIN_CTRL_MODE_LISTEN; break; case PHY_MODE_POLL: phyMainCtrl |= PHY_MAIN_CTRL_MODE_POLL; break; default: return FAILURE; break; } PhyWrite(instPtr, PHY_MAIN_CTRL, phyMainCtrl | PHY_MAIN_CTRL_EN_EN); return SUCCESS; } /*****************************************************************************/ /** * @brief Setup a specific timer word register in physical controller. * * @param instPtr physical instance * @param tmWord time word * @param tmType time word type * * @return SUCCESS * FAILURE * ******************************************************************************/ int32_t Phy_SetTimeWord(PHY_INST *instPtr, const TIME_WORD *tmWord, PHY_TIME_WORD_TYPE tmType) { ASSERT(instPtr != NULL); if (tmWord->frac_part >= PHY_TIME_WORD_L_MAX) { return EPARAM; } switch (tmType) { case PHY_TIME_WORD_POLL: PhyWrite(instPtr, POLLTIME_L, tmWord->frac_part); PhyWrite(instPtr, POLLTIME_H, tmWord->int_part); break; case PHY_TIME_WORD_LISTEN_TIMEOUT: PhyWrite(instPtr, LISTENTIMEOUT_L, tmWord->frac_part); PhyWrite(instPtr, LISTENTIMEOUT_H, tmWord->int_part); break; default: return EPARAM; } return SUCCESS; } /*****************************************************************************/ /** * @brief Setup next slot operation. * * @param instPtr a pointer to physical instance * @param txrxMode tor type of next slot * @param frameType frame type of next slot * * @return SUCCESS * other * ******************************************************************************/ int32_t Phy_SetupNextSlot(PHY_INST *instPtr, PHY_TOR_TYPE txrxMode, L1_FRAME_TYPE frameType, uint8_t *dataBuff) { ASSERT(instPtr != NULL); int32_t Status; uint32_t phyModeCtrl, hopNum; const uint8_t *hopPattern; // Implement a ping-pong flow, offset always is 0 or half of buffer depth. instPtr->antConfigOffset = (L1_ANTCONFIG_MAX_LEN >> 1) - instPtr->antConfigOffset; uintptr_t antConfigAddr = instPtr->antConfigAddr + instPtr->antConfigOffset; switch (txrxMode) { case PHY_TOR_SUSPEND: phyModeCtrl = PHY_MODE_CTRL_TOR_SUSPEND; break; case PHY_TOR_RX: phyModeCtrl = PHY_MODE_CTRL_TOR_RX; break; case PHY_TOR_TX: phyModeCtrl = PHY_MODE_CTRL_TOR_TX; break; default: return EPARAM; } switch (frameType) { case L1_FRAME_ADV_24MS: phyModeCtrl |= PHY_MODE_CTRL_FRAME_ADV_24MS; hopNum = L1_FRAME_ADV_24MS_HOPS; hopPattern = hopPattern_ADV_24MS; break; case L1_FRAME_ACK_8MS: phyModeCtrl |= PHY_MODE_CTRL_FRAME_ACK_8MS; hopNum = L1_FRAME_ACK_8MS_HOPS; hopPattern = hopPattern_ACK_8MS; break; case L1_FRAME_128KBPS_4MS: phyModeCtrl |= PHY_MODE_CTRL_FRAME_128KBPS_4MS; hopNum = L1_FRAME_128KBPS_4MS_HOPS; hopPattern = hopPattern_128KBPS_4MS; break; case L1_FRAME_512KBPS_4MS: phyModeCtrl |= PHY_MODE_CTRL_FRAME_512KBPS_4MS; hopNum = L1_FRAME_512KBPS_4MS_HOPS; hopPattern = hopPattern_512KBPS_4MS; break; case L1_FRAME_2MBPS_4MS: phyModeCtrl |= PHY_MODE_CTRL_FRAME_2MBPS_4MS; hopNum = L1_FRAME_2MBPS_4MS_HOPS; hopPattern = hopPattern_2MBPS_4MS; break; default: return EPARAM; break; } // Set frame configs PhyWrite(instPtr, PHY_MODE_CTRL, phyModeCtrl | PHY_MODE_CTRL_CRC_EN); // TODO: Set antenna stand by, when suspend. const uint8_t *dataSrcPtr = (uint8_t *)(&(instPtr->antConfig)); uint8_t freqIdx; uint16_t hopFreq; uint8_t hopCal; for (uint8_t hopIdx = 0; hopIdx < hopNum; hopIdx++) { // Frequency setting freqIdx = hopPattern[hopIdx]; hopFreq = freqTable[freqIdx]; for (uint8_t antIdx = 0; antIdx < L1_ANT_NUM; antIdx++) { instPtr->antConfig.rfFreq[antIdx][0] = (uint8_t)(hopFreq >> 8); instPtr->antConfig.rfFreq[antIdx][1] = (uint8_t)hopFreq; // FIXME: Calibration setting // for (uint8_t chIdx = 0; chIdx < L1_ANT_CH_NUM; chIdx ++) // { // hopCal = antCalTable[antIdx][freqIdx][chIdx]; // instPtr->antConfig.rfNormComp[antIdx][chIdx] = hopCal; // } } memcpy((uint8_t *)(antConfigAddr + hopIdx * ANT_COINFO_LEN), dataSrcPtr, NORMALIZE_SIZE(sizeof(PHY_ANT_CONFIG))); } uint32_t antCtrl = (instPtr->antConfigOffset & ANT_CONFIG_OFFSET_MASK) | ((hopNum << ANT_CONFIG_NUM_SHIFT) & ANT_CONFIG_NUM_MASK) | ((ANT_COINFO_LEN << ANT_CONFIG_LEN_SHIFT) & ANT_CONFIG_LEN_MASK); // Set antenna configs PhyWrite(instPtr, ANT_CONFIG, antCtrl); if (txrxMode == PHY_TOR_TX) { // Set data to be sent Status = Phy_SetSendData(instPtr, frameType, dataBuff); if (Status != SUCCESS) { DBG_ERROR("Failed to apply send data.\n"); return Status; } } // Trigger physical configuration. // Indicate physical layer that all the configurations were done. PhyWrite(instPtr, SLOT_CMD, SLOT_CMD_KEY); Phy_RcdShift(&(instPtr->tor), txrxMode); Phy_RcdShift(&(instPtr->frameType), frameType); return SUCCESS; } /*****************************************************************************/ /** * @brief Update physical layer status cache. * * @param instPtr physical layer control instance. * * @return NONE. * ******************************************************************************/ void Phy_UpdateState(PHY_INST *instPtr) { ASSERT(instPtr != NULL); /* Update Frame Sate. */ uint32_t txrxSate = PhyRead(instPtr, TXRX_STATE); // instPtr->isAcq = ((txrxSate & TXRX_STATE_ACQ_MASK) == TXRX_STATE_ACQ_SUCCESS) ? true : false; // instPtr->isFrameSync = ((txrxSate & TXRX_STATE_FSYNC_MASK) == TXRX_STATE_FSYNC_SUCCESS) ? true : false; // FIXME: using default value, since physical layer may provide unexpected error value. instPtr->isAcq = true; instPtr->isFrameSync = true; instPtr->isDecode = ((txrxSate & TXRX_STATE_DECODE_MASK) == TXRX_STATE_DECODE_SUCCESS) ? true : false; if (Phy_IsFrameReceived(instPtr)) { instPtr->isValid = ((txrxSate & TXRX_STATE_CRC_MASK) == TXRX_STATE_CRC_OK) ? true : false; } else { instPtr->isValid = false; } Phy_UpdateLogging(instPtr); } /*****************************************************************************/ /** * @brief Copy ans store the received data, if received data valid. * * @param instPtr to physical layer control instance. * @param dataBuff data buffer. * * @return NONE * ******************************************************************************/ void Phy_PeekRecvData(PHY_INST *instPtr, uint8_t *dataBuff) { ASSERT(instPtr != NULL); ASSERT(dataBuff != NULL); if (instPtr->isValid == false) { return; } uint32_t frameLen, offset; frameLen = (PhyRead(instPtr, RECVDATA_STATE) & RECVDATA_STATE_LEN_MASK) >> RECVDATA_STATE_LEN_SHIFT; offset = (PhyRead(instPtr, RECVDATA_STATE) & RECVDATA_STATE_OFFSET_MASK) >> RECVDATA_STATE_OFFSET_SHIFT; memcpy(dataBuff, (uint8_t *)(instPtr->recvDataAddr + offset), NORMALIZE_SIZE(frameLen)); } /*****************************************************************************/ /** * @brief Get the received data (if valid), store it to data buffer. * and clear data valid flag. * * @param instPtr to physical layer control instance. * @param dataBuff data buffer. * * @return NONE * ******************************************************************************/ void Phy_RetrieveRecvData(PHY_INST *instPtr, uint8_t *dataBuff) { ASSERT(instPtr != NULL); ASSERT(dataBuff != NULL); if (instPtr->isValid == false) { return; } Phy_PeekRecvData(instPtr, dataBuff); instPtr->isValid = false; } /*****************************************************************************/ /** * @brief Update physical layer logging. * * @param instPtr A pointer to physical layer control instance. * * @return NONE. * ******************************************************************************/ void Phy_UpdateLogging(PHY_INST *instPtr) { ASSERT(instPtr != NULL); uint64_t peak, avg; // Logging instPtr->recvSlotTime.int_part = PhyRead(instPtr, TM_TARGET_H); instPtr->recvSlotTime.frac_part = PhyRead(instPtr, TM_TARGET_L); instPtr->recvFsTime.int_part = PhyRead(instPtr, FSTIME_H); instPtr->recvFsTime.frac_part = PhyRead(instPtr, FSTIME_L); instPtr->phyLog.acqCnt = PhyRead(instPtr, PHY_ACQ_CNT); instPtr->phyLog.fsyncCnt = PhyRead(instPtr, PHY_FRAME_SYNC_CNT); instPtr->phyLog.decodeCnt = PhyRead(instPtr, PHY_DECODE_CNT); instPtr->phyLog.crcCnt = PhyRead(instPtr, PHY_CRC_OK_CNT); instPtr->phyLog.doppler = Phy_GetFreqEst(instPtr); instPtr->phyLog.recvStamp = (uint64_t)instPtr->recvFsTime.int_part * TIME_FRAC_MAX + instPtr->recvFsTime.frac_part; peak = PhyRead(instPtr, PHY_ACQ_PEAK_L); peak |= ((uint64_t)PhyRead(instPtr, PHY_ACQ_PEAK_H)) << 32; avg = PhyRead(instPtr, PHY_ACQ_MEAN_L); avg |= ((uint64_t)PhyRead(instPtr, PHY_ACQ_MEAN_H)) << 32; instPtr->phyLog.acqPAPR = ((double)peak) / ((double)avg); instPtr->phyLog.acqPhase = (PhyRead(instPtr, PHY_ACQ_FREQEST) & PHY_ACQ_FREQEST_PHASE_MASK) >> PHY_ACQ_FREQEST_PHASE_SHIFT; instPtr->phyLog.acqFreqCh = (PhyRead(instPtr, PHY_ACQ_FREQEST) & PHY_ACQ_FREQEST_CHANNEL_MASK) >> PHY_ACQ_FREQEST_CHANNEL_SHIFT; peak = PhyRead(instPtr, PHY_FRAME_SYNC_PEAK_L); peak |= ((uint64_t)PhyRead(instPtr, PHY_FRAME_SYNC_PEAK_H)) << 32; avg = PhyRead(instPtr, PHY_FRAME_SYNC_MEAN_L); avg |= ((uint64_t)PhyRead(instPtr, PHY_FRAME_SYNC_MEAN_H)) << 32; instPtr->phyLog.fsyncPAPR = ((double)peak) / ((double)avg); instPtr->phyLog.fsyncFreqCh = (PhyRead(instPtr, PHY_FRAME_SYNC_FREQEST) & PHY_FRAME_SYNC_FREQEST_CHANNEL_MASK) >> PHY_FRAME_SYNC_FREQEST_CHANNEL_SHIFT; instPtr->phyLog.deintlvAmpEst = PhyRead(instPtr, PHY_DEINTLV_AMPEST) & PHY_DEINTLV_AMPEST_MASK; memset(instPtr->phyLog.reserve, 0x00, sizeof(instPtr->phyLog.reserve)); // Sync logs to system monitor SysMonitor_UpdatePhysicalLayerLog(&(instPtr->phyLog)); instPtr->lastLogTime = PhyRead(instPtr, TM_TARGET_H); } /*****************************************************************************/ /** * @brief Refresh hardware status. * * @param instPtr a pointer to hopping pattern buffer * * @return NONE * ******************************************************************************/ void Phy_RefreshHwSate(PHY_INST *instPtr) { ASSERT(instPtr != NULL); uint16_t rawData; #ifndef EMULATION #ifdef HSJL_GE // Zynq MPSoC (Zynq UltraScale+) XSysMon *sysMonPtr = &(instPtr->sysMon); float evalData; instPtr->hwSate.isSpOk = true; // -- Update FPGA voltage status; instPtr->hwSate.spFpgaVolt = 0; rawData = XSysMon_GetAdcData(sysMonPtr, XSM_CH_VCCPINT); evalData = XSysMon_RawToVoltage(rawData); instPtr->hwSate.spFpgaVolt |= (IS_PS_VALID(evalData)) ? VOLT_PS_OK : 0; // -- -- Update Ps aux voltage rawData = XSysMon_GetAdcData(sysMonPtr, XSM_CH_VCCPAUX); evalData = XSysMon_RawToVoltage(rawData); instPtr->hwSate.spFpgaVolt |= (IS_PSAUX_VALID(evalData)) ? VOLT_PSAUX_OK : 0; // -- -- Update DDR voltage rawData = XSysMon_GetAdcData(sysMonPtr, XSM_CH_VCCPDRO); evalData = XSysMon_RawToVoltage(rawData); instPtr->hwSate.spFpgaVolt |= (IS_DDR_VALID(evalData)) ? VOLT_DDR_OK : 0; // -- -- Update PL voltage rawData = XSysMon_GetAdcData(sysMonPtr, XSM_CH_VCCINT); evalData = XSysMon_RawToVoltage(rawData); instPtr->hwSate.spFpgaVolt |= (IS_PL_VALID(evalData)) ? VOLT_PL_OK : 0; // -- -- Update PL aux voltage rawData = XSysMon_GetAdcData(sysMonPtr, XSM_CH_VCCAUX); evalData = XSysMon_RawToVoltage(rawData); instPtr->hwSate.spFpgaVolt |= (IS_PLAUX_VALID(evalData)) ? VOLT_PLAUX_OK : 0; // -- -- Update Bram voltage rawData = XSysMon_GetAdcData(sysMonPtr, XSM_CH_VBRAM); evalData = XSysMon_RawToVoltage(rawData); instPtr->hwSate.spFpgaVolt |= (IS_BRAM_VALID(evalData)) ? VOLT_BRAM_OK : 0; // -- Update clock lock state if (instPtr->phyCofig.get_clk_state != NULL) { instPtr->hwSate.spClkState = instPtr->phyCofig.get_clk_state(); } else { instPtr->hwSate.spClkState = 0; } // -- Update AD9361 pll lock state if (instPtr->phyCofig.get_ad_lock_state != NULL) { instPtr->hwSate.spAdLockState = instPtr->phyCofig.get_ad_lock_state(); } else { instPtr->hwSate.spAdLockState = 0; } // -- Update AD9361-0 temperature, unit 1 Celcius degree if (instPtr->phyCofig.get_ad0_temp != NULL) { instPtr->hwSate.spAdTemp_0 = instPtr->phyCofig.get_ad0_temp(); } else { instPtr->hwSate.spAdTemp_0 = 0; } // -- Update AD9361-1 temperature, unit 1 Celcius degree if (instPtr->phyCofig.get_ad1_temp != NULL) { instPtr->hwSate.spAdTemp_1 = instPtr->phyCofig.get_ad1_temp(); } else { instPtr->hwSate.spAdTemp_1 = 0; } // -- Update FPGA Chip temperature, unit 1 deg rawData = XSysMon_GetAdcData(sysMonPtr, XSM_CH_TEMP); evalData = XSysMon_RawToTemperature(rawData); instPtr->hwSate.spFpgaTemp = (evalData > TEMPERATURE_MAX) ? INT8_MAX : ((evalData < TEMPERATURE_MIN) ? INT8_MIN : (int8_t)round(evalData / TEMPERATURE_LSB)); instPtr->hwSate.isSpOk = (instPtr->hwSate.spFpgaVolt == (VOLT_PS_OK | VOLT_PSAUX_OK | VOLT_DDR_OK | VOLT_PL_OK | VOLT_PLAUX_OK | VOLT_BRAM_OK)) && (instPtr->hwSate.spClkState == (CLK_SP_PLL1_LOCK | CLK_SP_PLL2_LOCK)) && (instPtr->hwSate.spAdLockState == (CLK_AD0_BBPLL_LOCK | CLK_AD0_RFPLL_LOCK | CLK_AD1_BBPLL_LOCK | CLK_AD1_RFPLL_LOCK)); #else double evalData; instPtr->hwSate.isSpOk = true; // -- Update FPGA voltage status; instPtr->hwSate.spFpgaVolt = 0; rawData = XAdcPs_GetAdcData(&(instPtr->hwXadc), XADCPS_CH_VCCPINT); evalData = XAdcPs_RawToVoltage(rawData); instPtr->hwSate.spFpgaVolt |= (IS_PS_VALID(evalData)) ? VOLT_PS_OK : 0; // -- -- Update Ps aux voltage rawData = XAdcPs_GetAdcData(&(instPtr->hwXadc), XADCPS_CH_VCCPAUX); evalData = XAdcPs_RawToVoltage(rawData); instPtr->hwSate.spFpgaVolt |= (IS_PSAUX_VALID(evalData)) ? VOLT_PSAUX_OK : 0; // -- -- Update DDR voltage rawData = XAdcPs_GetAdcData(&(instPtr->hwXadc), XADCPS_CH_VCCPDRO); evalData = XAdcPs_RawToVoltage(rawData); instPtr->hwSate.spFpgaVolt |= (IS_DDR_VALID(evalData)) ? VOLT_DDR_OK : 0; // -- -- Update PL voltage rawData = XAdcPs_GetAdcData(&(instPtr->hwXadc), XADCPS_CH_VCCINT); evalData = XAdcPs_RawToVoltage(rawData); instPtr->hwSate.spFpgaVolt |= (IS_PL_VALID(evalData)) ? VOLT_PL_OK : 0; // -- -- Update PL aux voltage rawData = XAdcPs_GetAdcData(&(instPtr->hwXadc), XADCPS_CH_VCCAUX); evalData = XAdcPs_RawToVoltage(rawData); instPtr->hwSate.spFpgaVolt |= (IS_PLAUX_VALID(evalData)) ? VOLT_PLAUX_OK : 0; // -- -- Update Bram voltage rawData = XAdcPs_GetAdcData(&(instPtr->hwXadc), XADCPS_CH_VBRAM); evalData = XAdcPs_RawToVoltage(rawData); instPtr->hwSate.spFpgaVolt |= (IS_BRAM_VALID(evalData)) ? VOLT_BRAM_OK : 0; // -- Update clock lock state if (instPtr->phyCofig.get_clk_state != NULL) { instPtr->hwSate.spClkState = instPtr->phyCofig.get_clk_state(); } else { instPtr->hwSate.spClkState = 0; } // -- Update AD9361 pll lock state if (instPtr->phyCofig.get_ad_lock_state != NULL) { instPtr->hwSate.spAdLockState = instPtr->phyCofig.get_ad_lock_state(); } else { instPtr->hwSate.spAdLockState = 0; } // -- Update AD9361-0 temperature, unit 1 Celcius degree if (instPtr->phyCofig.get_ad0_temp != NULL) { instPtr->hwSate.spAdTemp_0 = instPtr->phyCofig.get_ad0_temp(); } else { instPtr->hwSate.spAdTemp_0 = 0; } // -- Update AD9361-1 temperature, unit 1 Celcius degree if (instPtr->phyCofig.get_ad1_temp != NULL) { instPtr->hwSate.spAdTemp_1 = instPtr->phyCofig.get_ad1_temp(); } else { instPtr->hwSate.spAdTemp_1 = 0; } // -- Update FPGA Chip temperature, unit 1 deg rawData = XAdcPs_GetAdcData(&(instPtr->hwXadc), XADCPS_CH_TEMP); evalData = XAdcPs_RawToTemperature(rawData); instPtr->hwSate.spFpgaTemp = (evalData > TEMPERATURE_MAX) ? INT8_MAX : ((evalData < TEMPERATURE_MIN) ? INT8_MIN : (int8_t)round(evalData / TEMPERATURE_LSB)); instPtr->hwSate.isSpOk = (instPtr->hwSate.spFpgaVolt == (VOLT_PS_OK | VOLT_PSAUX_OK | VOLT_DDR_OK | VOLT_PL_OK | VOLT_PLAUX_OK | VOLT_BRAM_OK)) && (instPtr->hwSate.spClkState == (CLK_SP_PLL1_LOCK | CLK_SP_PLL2_LOCK)) && (instPtr->hwSate.spAdLockState == (CLK_AD0_BBPLL_LOCK | CLK_AD0_RFPLL_LOCK | CLK_AD1_BBPLL_LOCK | CLK_AD1_RFPLL_LOCK)); #endif #else instPtr->hwSate.isSpOk = true; #endif /*** Antenna Status Chunk 1 ***/ rawData = PhyRead(instPtr, ANT_STATUS_1); // -- Update Antenna Frequency Status: // [15] - ANT1 PLL on-off status: 1 - PLL1 active, 0 - PLL2 active // [14:0] - ANT1 PLL frequency, base frequency is 3700 MHz // [31] - ANT2 PLL on-off status: 1 - PLL1 active, 0 - PLL2 active // [30:16] - ANT2 PLL frequency, base frequency is 3700 MHz instPtr->hwSate.ant1Freq = (rawData & ANT_STATUS_1_ANT1_STATUS_MASK) >> ANT_STATUS_1_ANT1_STATUS_SHIFT; instPtr->hwSate.ant2Freq = (rawData & ANT_STATUS_1_ANT2_STATUS_MASK) >> ANT_STATUS_1_ANT2_STATUS_SHIFT; /*** Antenna Status Chunk 2 ***/ rawData = PhyRead(instPtr, ANT_STATUS_2); // -- Update Antenna Frequency Status: // [15] - ANT 3 PLL on-off status: 1 - PLL1 active, 0 - PLL2 active // [14:0] - ANT 3 PLL frequency, base frequency is 3700 MHz // [16] - PLL1 of ANT1 lock status: 1 - lock, 2 - unlock // [17] - PLL2 of ANT1 lock status: 1 - lock, 2 - unlock // [18] - PLL1 of ANT2 lock status: 1 - lock, 2 - unlock // [19] - PLL2 of ANT2 lock status: 1 - lock, 2 - unlock // [20] - PLL1 of ANT3 lock status: 1 - lock, 2 - unlock // [21] - PLL2 of ANT3 lock status: 1 - lock, 2 - unlock // [24] - Working mode of ANT1: 0 - normal mode, 1 - anti-jamming mode // [25] - Working mode of ANT2: 0 - normal mode, 1 - anti-jamming mode // [26] - Working mode of ANT3: 0 - normal mode, 1 - anti-jamming mode instPtr->hwSate.ant3Freq = (rawData & ANT_STATUS_2_ANT3_STATUS_MASK) >> ANT_STATUS_2_ANT3_STATUS_SHIFT; instPtr->hwSate.antPll = (rawData & ANT_STATUS_2_PLL_LK_MASK) >> ANT_STATUS_2_PLL_LK_SHIFT; instPtr->hwSate.antMode = (rawData & ANT_STATUS_2_MODE_MASK) >> ANT_STATUS_2_MODE_SHIFT; /*** Temperature and Reserved Control ***/ rawData = PhyRead(instPtr, ANT_STATUS_TEMP); //-- Update Antenna Temperature (signed 8bit integer, 1 centigrade per LSB) instPtr->hwSate.antTemp = (int8_t)(rawData & ANT_STATUS_TEMP_MASK) >> ANT_STATUS_TEMP_SHIFT; instPtr->hwSate.antRsvd = (uint8_t)(rawData & ANT_STATUS_TEMP_RSVD_MASK) >> ANT_STATUS_TEMP_RSVD_SHIFT; // Determine if antenna is ok. instPtr->hwSate.isAntOk = 1U; // FIXME: proper condition is required instPtr->hwSate.phyId = instPtr->phyCofig.devId; memset(instPtr->hwSate.reserve, 0x00, sizeof(instPtr->hwSate.reserve)); SysMonitor_UpdateHardwareStatus(&(instPtr->hwSate)); } /** @} PhysicalLayer_Main*/ /** * @addtogroup PhysicalLayer_Receive_Estimations * @{ */ /*****************************************************************************/ /** * @brief Get the antenna number after physical receive. * * @param instPtr a pointer to physical instance * * @return antenna index * ******************************************************************************/ uint8_t Phy_ReceiveAntIndex(PHY_INST *instPtr) { ASSERT(instPtr != NULL); return (uint8_t)PhyRead(instPtr, ANT_SELECT_INDEX); } /*****************************************************************************/ /** * @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_FRAME_2MBPS_4MS || frameType <= L1_FRAME_NONE) { 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_FRAME_128KBPS_4MS) { // 12M Rc coarse = (double)(8 - acqFreqIdx) * (250e3 / 4); coarse += (double)syncFreqIdx * 12e6 / 64 / 128; fine = 48e6 / 2048 * ((double)estAbs) / 8192.0; } else { // 1.5M Rc coarse = (double)(80 - acqFreqIdx) * (31.25e3 / 4); coarse += (double)syncFreqIdx * 1.5e6 / 64 / 128; fine = 12e6 / 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. * * @param instPtr a pointer to physical instance * * @return frequency estimation * ******************************************************************************/ double Phy_GetCoarseFreqEst(PHY_INST *instPtr) { ASSERT(instPtr != NULL); uint32_t regValue; uint8_t acqFreqIdx; int8_t syncFreqIdx; L1_FRAME_TYPE frameType; double freqEst; frameType = Phy_GetLastRecvFrameType(instPtr); if ((frameType > L1_FRAME_2MBPS_4MS) || (frameType <= L1_FRAME_NONE)) { return INFINITY; // FIXME } regValue = PhyRead(instPtr, COASE_FREQEST); acqFreqIdx = (regValue & COASE_FREQEST_ACQ_MASK) >> COASE_FREQEST_ACQ_SHIFT; syncFreqIdx = (regValue & COASE_FREQEST_SYNC_MASK) >> COASE_FREQEST_SYNC_SHIFT; if (frameType >= L1_FRAME_128KBPS_4MS) { // 12M Rc freqEst = (double)(8 - acqFreqIdx) * (250e3 / 4); freqEst += (double)syncFreqIdx * 12e6 / 64 / 128; } else { // 1.5M Rc freqEst = (double)(80 - acqFreqIdx) * (31.25e3 / 4); freqEst += (double)syncFreqIdx * 1.5e6 / 64 / 128; } 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_FRAME_2MBPS_4MS) || (frameType <= L1_FRAME_NONE)) { return INFINITY; // FIXME } regValue = PhyRead(instPtr, FINE_FREQEST); estAbs = regValue & FINE_FREQEST_VAL_MASK; if ((frameType >= L1_FRAME_128KBPS_4MS)) { // 12M Rc freqEst = 48e6 / 2048 * ((double)estAbs) / 8192.0; } else { // 1.5M Rc freqEst = 12e6 / 2048 * ((double)estAbs) / 8192.0; } freqEst = ((regValue & FINE_FREQEST_SIGN_MASK) == FINE_FREQEST_SIGN_NEG) ? -freqEst : freqEst; return freqEst; } /*****************************************************************************/ /** * @brief Get the frame sync time of last frame. * * @param instPtr a pointer to physical instance * @param frameSycT a pointer to the frame sync time data buffer. * * @return NONE * ******************************************************************************/ void Phy_GetFrameSyncTimeStamp(PHY_INST *instPtr, TIME_WORD *frameSyncT) { ASSERT(instPtr != NULL); ASSERT(frameSyncT != NULL); frameSyncT->int_part = PhyRead(instPtr, FSTIME_H); frameSyncT->frac_part = PhyRead(instPtr, FSTIME_L); } /*****************************************************************************/ /** * @brief Get the frame sync time of last received frame. * * @param instPtr a pointer to physical instance * @param frameSycT a pointer to the frame sync time data buffer. * * @return NONE * ******************************************************************************/ void Phy_GetLastReceivedFrameSyncTimeStamp(PHY_INST *instPtr, TIME_WORD *frameSyncT) { ASSERT(instPtr != NULL); ASSERT(frameSyncT != NULL); memcpy(frameSyncT, &(instPtr->recvFsTime), sizeof(TIME_WORD)); } /*****************************************************************************/ /** * @brief Get the slot start time of last received frame. * * @param instPtr a pointer to physical instance * @param slotStart a pointer to the time data buffer. * * @return NONE * ******************************************************************************/ void Phy_GetSlotStartTimeStamp(PHY_INST *instPtr, TIME_WORD *slotStart) { ASSERT(instPtr != NULL); ASSERT(slotStart != NULL); slotStart->int_part = PhyRead(instPtr, TM_TARGET_H); slotStart->frac_part = PhyRead(instPtr, TM_TARGET_L); } /*****************************************************************************/ /** * @brief Get the slot start time of last frame. * * @param instPtr a pointer to physical instance * @param slotStart a pointer to the time data buffer. * * @return NONE * ******************************************************************************/ void Phy_GetLastReceivedSlotStartTimeStamp(PHY_INST *instPtr, TIME_WORD *slotStart) { ASSERT(instPtr != NULL); ASSERT(slotStart != NULL); memcpy(slotStart, &(instPtr->recvSlotTime), sizeof(TIME_WORD)); } /** @} PhysicalLayer_Receive_Estimations*/ /** @} PhysicalLayer*/