/*****************************************************************************/ /** * Description: Time sync implementation file. * * Author: Author's name * Date: 2021-12-04 16:32 * LastEditors: FanHao * LastEditTime: 2022-07-10 20:43 * Revisions: Rev 0.0 * History: * [2022-07-10]: New branch for Dijian. * [2021-12-04]: Initial version. * * Copyright(c) 2021 Beijing Institute of Technology. * Lab of Communication and Networking * ******************************************************************************/ /***************************** Include Files *********************************/ #include #include #include "linklayer814.h" #include "rtt.h" #include "../time_ctrl/time_ctrl.h" #include "../error.h" #include "../common.h" /************************** Constant Definitions *****************************/ #define LIGHT_SPPED_AIR 299702547.0 // m/s #define LIGHT_SPPED_VAC 299792458.0 // m/s #define RTT_DOPPLER_NONE UINT32_MAX const TIME_WORD RTT_TIME_NONE = { .int_part = UINT32_MAX, .frac_part = UINT32_MAX }; /***************** Macros (Inline Functions) Definitions *********************/ /**************************** Type Definitions *******************************/ /************************** Variable Definitions *****************************/ /************************** Function Prototypes ******************************/ static void RTT_StageUpdate(L2_RTT_FSM* rttFsmPtr, L2_RTT_STGE newStage); static void RTT_GetFrameStart(L2_INST* instPtr, TIME_WORD *tmStamp, L2_TOR_TYPE torType); /*****************************************************************************/ /** * @brief a slot alignment, base on physical layer information. * * @param instPtr a pointer to linklayer layer instance * @param frameNum * @param slotNum * * @return SUCCESS Initialize successfully. * FAILURE Initialization failed, allocate memory fail or initial * bram controller fail. * ******************************************************************************/ // TODO: Check int32_t L2_TimeAlign(L2_INST* instPtr, uint32_t frameNum, uint32_t slotNum){ L1_FRAME_TYPE lastRecvdFrame; lastRecvdFrame = Phy_GetLastRecvFrameType(instPtr->config.phyInstPtr); if(lastRecvdFrame != L1_NONE_FRAME){ return EIGNORE; } // read nextSendTime from physical layer uint64_t currTime, expctTime; int64_t timeDiff; TIME_WORD timeStamp, slotTimerAdjmet; expctTime = ((uint64_t)(frameNum*L2_SLOTS_PER_FRAME + slotNum))*COUNTE_FRAC_MAX; expctTime += Phy_GetTimeComp(lastRecvdFrame); Phy_GetFrameSyncTimeStamp(instPtr->config.phyInstPtr, &timeStamp); currTime = (uint64_t)timeStamp.frac_part; currTime += ((uint64_t)timeStamp.int_part) * COUNTE_FRAC_MAX; timeDiff = (int64_t)(expctTime - currTime); slotTimerAdjmet.int_part = (uint32_t)(timeDiff / COUNTE_FRAC_MAX); slotTimerAdjmet.frac_part = (uint32_t)(timeDiff % COUNTE_FRAC_MAX); TimeCtrl_TimeAdjust(instPtr->config.tmcInstPtr, &slotTimerAdjmet, TM_ADJ_ADD); return SUCCESS; } /*****************************************************************************/ /** * @brief Update corrent time-sync for RTT stage * * @param scanFsmPtr A pointer to scan net fsm. * @param newSatge New state. * * @return NONE. * ******************************************************************************/ static void RTT_StageUpdate(L2_RTT_FSM* rttFsmPtr, L2_RTT_STGE newStage) { ASSERT(rttFsmPtr != NULL); ASSERT(newStage >= RTT_NONE_STAGE && newStage <= RTT_RSP2); DBG_INFO("RTT Stage Update: %d -> %d.\n", rttFsmPtr->rttStage, newStage); rttFsmPtr->rttStage = newStage; } /*****************************************************************************/ /** * @brief Reset RTT FSM * * @param rttFsmPtr a pointer to rtt FSM instance. * * @return NONE * ******************************************************************************/ void RTT_Reset(L2_RTT_FSM* rttFsmPtr){ ASSERT(rttFsmPtr != NULL); memset(&(rttFsmPtr->rttRecord), 0x00, sizeof(RTT_RECORD)); rttFsmPtr->rttStage = RTT_REQ1; rttFsmPtr->isR1Valid = false; rttFsmPtr->isR2Valid = false; rttFsmPtr->isR3Valid = false; rttFsmPtr->isR4Valid = false; rttFsmPtr->timeStamp.int_part = 0; rttFsmPtr->timeStamp.frac_part = 0; rttFsmPtr->doppler = 0; } /*****************************************************************************/ /** * @brief Destroy RTT FSM, free allocated memory. * * @param rttFsmPtr a pointer to rtt FSM instance. * * @return NONE * ******************************************************************************/ void RTT_Destroy(L2_RTT_FSM* rttFsmPtr){ free(rttFsmPtr); } /*****************************************************************************/ /** * @brief Get the frame start time. If torType == L2_TOR_TX, get the next * slot start time, if torType == L2_TOR_RX get last frame start * time. * * @param instPtr a pointer to linklayer layer instance * @param tmStamp a pointer to store frame start time * @param torType tx/rx mode * * @return NONE * ******************************************************************************/ void RTT_GetFrameStart(L2_INST* instPtr, TIME_WORD *tmStamp, L2_TOR_TYPE torType){ ASSERT(instPtr != NULL); ASSERT(tmStamp != NULL); // Get the next frame start time if(torType == L2_TOR_TX) { tmStamp->int_part = L2_GetNextFrameNum(instPtr)*L2_SLOTS_PER_FRAME + L2_GetNextSlotNum(instPtr); tmStamp->frac_part = 0 ; } // Get the last reiceive frame start time else if(torType == L2_TOR_RX) { PHY_INST* phyRef = instPtr->config.phyInstPtr; TIME_WORD timeStamp; int64_t timeDiff; Phy_GetFrameSyncTimeStamp(phyRef, &timeStamp); timeDiff = (uint64_t) timeStamp.frac_part; timeDiff += ((uint64_t)timeStamp.int_part) * COUNTE_FRAC_MAX; Phy_GetLastSlotStartTimeStamp(phyRef, tmStamp); timeDiff -= ((uint64_t) tmStamp->int_part) * COUNTE_FRAC_MAX; timeDiff -= (uint64_t) tmStamp->frac_part; timeDiff = (int64_t)Phy_GetTimeComp(L2_L2frame2L1frame(L2_GetLastFrameType(instPtr))) - timeDiff; if (timeDiff < 0) { timeDiff += COUNTE_FRAC_MAX; tmStamp->int_part--; _nop_(); } tmStamp->frac_part = (TIME_FRAC)timeDiff; } else { *tmStamp = RTT_TIME_NONE; DBG_ERROR("Unexpected tx/rx mode, setting dummy values.\n"); } } /*****************************************************************************/ /** * @brief Initialize RTT FSM, allocate memory for FSM instance. * * @param rttFsmPtr * * @return SUCCESS Initialization successful. * EMAC_MEMORY_ALLOC_ERROR Memory allocate error. * ******************************************************************************/ int32_t RTT_Init(L2_RTT_FSM** rttFsmPtr){ (*rttFsmPtr) = (L2_RTT_FSM*) malloc(sizeof(L2_RTT_FSM)); if (*rttFsmPtr == NULL) { free(*rttFsmPtr); return EALLOC; } RTT_Reset(*rttFsmPtr); return SUCCESS; } /*****************************************************************************/ /** * @brief Update RTT FSM accordingly. * * @param instPtr a pointer to linklayer layer instance * @param torType tx/rx mode type * * @return SUCCESS * error code * ******************************************************************************/ int32_t RTT_FsmUpdate(L2_INST* instPtr, L2_TOR_TYPE torType) { ASSERT(instPtr != NULL); L2_RTT_FSM* rttFsmPtr = L2_GetRttFsm(instPtr); RTT_RECORD* rttRecord = &(rttFsmPtr->rttRecord); PHY_INST *phyRef = instPtr->config.phyInstPtr; DBG_INFO("-------- RTT FSM Update --------\n"); // Stage trans // For Head Node: Tx->Rx->Tx->Rx if(L2_GetNodeType(instPtr) == L2_NODE_HEAD){ switch(rttFsmPtr->rttStage) { case RTT_REQ1 : if(torType == L2_TOR_TX){ DBG_INFO("Prepare data for RTT REQ-1\n"); // Update Tt1 RTT_GetFrameStart(instPtr, &(rttRecord->Tt1), torType); DBG_INFO("Tt1-timeL:%u.\n", rttRecord->Tt1.int_part); DBG_INFO("Tt1-timeH:%u.\n", rttRecord->Tt1.frac_part); // Prepare data for sending... rttFsmPtr->timeStamp = rttRecord->Tt1; rttFsmPtr->doppler = RTT_DOPPLER_NONE; RTT_StageUpdate(rttFsmPtr, RTT_RSP1); } else{ DBG_INFO("RTT FSM remain current state [%d].\n", rttFsmPtr->rttStage); } break; case RTT_RSP1 : if(torType == L2_TOR_RX){ if(L2_isDataAvail(instPtr) == true){ DBG_INFO("RTT RSP-1 have been received.\n"); DBG_INFO("Preparing data for RTT REQ-2.\n"); rttFsmPtr->isR2Valid = true; // Update doppler rttRecord->dopplerR2 = (int32_t)Phy_GetCoarseFreqEst(phyRef); // Update Tr2 RTT_GetFrameStart(instPtr, &(rttRecord->Tr2), torType); // Calculate TroundA TimeCtrl_CalculateTimeGap(&(rttRecord->Tt1), &(rttRecord->Tr2), &(rttRecord->TroundA)); } else{ DBG_WARNING("RTT RSP-1 had not been received [Stage: %d].\n", rttFsmPtr->rttStage); DBG_WARNING("Set Tr2 dopplerR2 and TroundA to dummy value.\n"); rttFsmPtr->isR2Valid = false; rttRecord->dopplerR2 = RTT_DOPPLER_NONE; rttRecord->Tr2 = RTT_TIME_NONE; rttRecord->TroundA = RTT_TIME_NONE; } DBG_INFO("dopplerR2:%d.\n", rttRecord->dopplerR2); DBG_INFO("Tr2-timeL:%u.\n", rttRecord->Tr2.frac_part); DBG_INFO("Tr2-timeH:%u.\n", rttRecord->Tr2.int_part); DBG_INFO("TroundA-timeL:%u.\n", rttRecord->TroundA.frac_part); DBG_INFO("TroundA-timeH:%u.\n", rttRecord->TroundA.int_part); RTT_StageUpdate(rttFsmPtr, RTT_REQ2); } else{ DBG_INFO("RTT FSM remain current state [%d].\n", rttFsmPtr->rttStage); } break; case RTT_REQ2 : if(torType == L2_TOR_TX){ DBG_INFO("Prepare data for RTT REQ-2\n"); // Update Tt3 RTT_GetFrameStart(instPtr, &(rttRecord->Tt3), torType); if ( rttFsmPtr->isR2Valid ) { // Calculate reply A TimeCtrl_CalculateTimeGap(&(rttRecord->Tt3), &(rttRecord->Tr2), &(rttRecord->TreplyA)); } else { DBG_WARNING("RTT RSP-1 have not been received [Stage: %d].\n", rttFsmPtr->rttStage); DBG_WARNING("Set TreplyA to dummy value.\n"); rttRecord->TreplyA = RTT_TIME_NONE; } DBG_INFO("Tt3-timeL:%u.\n", rttRecord->Tt3.frac_part); DBG_INFO("Tt3-timeH:%u.\n", rttRecord->Tt3.int_part); DBG_INFO("TreplyA-timeL:%u.\n", rttRecord->TreplyA.frac_part); DBG_INFO("TreplyA-timeH:%u.\n", rttRecord->TreplyA.int_part); // Prepare data for sending. rttFsmPtr->timeStamp = rttRecord->TroundA; rttFsmPtr->doppler = rttRecord->dopplerR2; RTT_StageUpdate(rttFsmPtr, RTT_RSP2); } else{ DBG_INFO("RTT FSM remain current state [%d].\n", rttFsmPtr->rttStage); } break; case RTT_RSP2 : if(torType == L2_TOR_RX){ if(L2_isDataAvail(instPtr) == true){ DBG_INFO("RTT RSP-2 have been received.\n"); rttFsmPtr->isR4Valid = true; // Update doppler double doppler = Phy_GetCoarseFreqEst(phyRef); rttRecord->dopplerR2 = (int32_t)doppler; // Update Tr4 RTT_GetFrameStart(instPtr, &(rttRecord->Tr4), torType); // Calculate TroundA TimeCtrl_CalculateTimeGap(&(rttRecord->Tt3), &(rttRecord->Tr4), &(rttRecord->TroundA)); } else{ DBG_WARNING("RTT RSP-1 have not been received [Stage: %d].\n", rttFsmPtr->rttStage); DBG_WARNING("Set Tr4 dopplerR4 and TroundA to dummy value.\n"); rttFsmPtr->isR4Valid = false; rttRecord->dopplerR4 = RTT_DOPPLER_NONE; rttRecord->Tr4 = RTT_TIME_NONE; rttRecord->TroundA = RTT_TIME_NONE; } DBG_INFO("dopplerR4:%d.\n", rttRecord->dopplerR4); DBG_INFO("Tr4-timeL:%u.\n", rttRecord->Tr4.frac_part); DBG_INFO("Tr4-timeH:%u.\n", rttRecord->Tr4.int_part); DBG_INFO("TroundA-timeL:%u.\n", rttRecord->TroundA.frac_part); DBG_INFO("TroundA-timeH:%u.\n", rttRecord->TroundA.int_part); RTT_StageUpdate(rttFsmPtr, RTT_REQ1); DBG_INFO("RTT procedure end...\n"); } else{ DBG_INFO("RTT FSM remain current state [%d].\n", rttFsmPtr->rttStage); } break; default : DBG_ERROR("Unexpected RTT FSM stage [%d].\n", rttFsmPtr->rttStage); break; } } // For Member Node: Rx->Tx->Rx->Tx else{ switch(rttFsmPtr->rttStage) { case RTT_REQ1 : if(torType == L2_TOR_RX){ if(L2_isDataAvail(instPtr) == true){ DBG_INFO("RTT REQ-1 have been received.\n"); DBG_INFO("Preparing data for RTT RSP-1.\n"); rttFsmPtr->isR2Valid = true; // Update doppler rttRecord->dopplerR2 = (int32_t)Phy_GetCoarseFreqEst(phyRef); // Update Tr1 RTT_GetFrameStart(instPtr, &(rttRecord->Tr1), torType); } else{ DBG_WARNING("RTT REQ-1 have not been received [Stage: %d].\n", rttFsmPtr->rttStage); DBG_WARNING("Set dopplerR1 and Tr1 to dummy value.\n"); rttFsmPtr->isR1Valid = false; rttRecord->dopplerR1 = RTT_DOPPLER_NONE; rttRecord->Tr1 = RTT_TIME_NONE; } DBG_INFO("dopplerR1:%d.\n", rttRecord->dopplerR1); DBG_INFO("Tr1-timeL:%u.\n", rttRecord->Tr1.frac_part); DBG_INFO("Tr1-timeH:%u.\n", rttRecord->Tr1.int_part); RTT_StageUpdate(rttFsmPtr, RTT_RSP1); } else{ DBG_INFO("RTT FSM remain current state [%d].\n", rttFsmPtr->rttStage); } break; case RTT_RSP1 : if(torType == L2_TOR_TX){ DBG_INFO("Prepare data for RTT RSP-1\n"); // Update Tt2 RTT_GetFrameStart(instPtr, &(rttRecord->Tt2), torType); if ( rttFsmPtr->isR1Valid ) { // Calculate reply B TimeCtrl_CalculateTimeGap(&(rttRecord->Tr1), &(rttRecord->Tt2), &(rttRecord->TreplyB)); } else { rttRecord->TreplyB = RTT_TIME_NONE; DBG_WARNING("RTT REQ-1 have not been received [Stage: %d].\n", rttFsmPtr->rttStage); DBG_WARNING("Set ReplayB to dummy value.\n"); } DBG_INFO("Tt2-timeL:%u.\n", rttRecord->Tt2.frac_part); DBG_INFO("Tt2-timeH:%u.\n", rttRecord->Tt2.int_part); DBG_INFO("TreplyB-timeL:%u.\n", rttRecord->TreplyB.frac_part); DBG_INFO("TreplyB-timeH:%u.\n", rttRecord->TreplyB.int_part); // Prepare data for sending. rttFsmPtr->timeStamp = rttRecord->TreplyB; rttFsmPtr->doppler = rttRecord->dopplerR1; RTT_StageUpdate(rttFsmPtr, RTT_REQ2); } else{ DBG_INFO("RTT FSM remain current state [%d].\n", rttFsmPtr->rttStage); } break; case RTT_REQ2 : if(torType == L2_TOR_RX){ if(L2_isDataAvail(instPtr) == true){ DBG_INFO("RTT REQ-2 have been received.\n"); DBG_INFO("Preparing data for RTT RSP-2.\n"); rttFsmPtr->isR3Valid = true; // Update doppler rttRecord->dopplerR2 = (int32_t)Phy_GetCoarseFreqEst(phyRef); // Update Tr3 RTT_GetFrameStart(instPtr, &(rttRecord->Tr3), torType); // Calculate TroundB TimeCtrl_CalculateTimeGap(&(rttRecord->Tt2), &(rttRecord->Tr3), &(rttRecord->TroundB)); } else{ DBG_WARNING("RTT REQ-2 have not been received [Stage: %d].\n", rttFsmPtr->rttStage); DBG_WARNING("Set dopplerR3 and ReplayB to dummy value.\n"); rttFsmPtr->isR3Valid = false; rttRecord->dopplerR3 = RTT_DOPPLER_NONE; rttRecord->TroundB = RTT_TIME_NONE; } DBG_INFO("dopplerR3:%d.\n", rttRecord->dopplerR3); DBG_INFO("Tr3-timeL:%u.\n", rttRecord->Tr3.frac_part); DBG_INFO("Tr3-timeH:%u.\n", rttRecord->Tr3.int_part); DBG_INFO("TroundB-timeL:%u.\n", rttRecord->TroundB.frac_part); DBG_INFO("TroundB-timeH:%u.\n", rttRecord->TroundB.int_part); RTT_StageUpdate(rttFsmPtr, RTT_RSP2); } else{ DBG_INFO("RTT FSM remain current state [%d].\n", rttFsmPtr->rttStage); } break; case RTT_RSP2 : if(torType == L2_TOR_TX){ DBG_INFO("Prepare data for RTT RSP-2\n"); // Update Tt4 RTT_GetFrameStart(instPtr, &(rttRecord->Tt4), torType); if ( rttFsmPtr->isR3Valid ) { // Calculate reply B TimeCtrl_CalculateTimeGap(&(rttRecord->Tr3), &(rttRecord->Tt4), &(rttRecord->TreplyB)); // TODO: implement a time adjustment. } else { DBG_WARNING("RTT REQ-2 have not been received [Stage: %d].\n", rttFsmPtr->rttStage); DBG_WARNING("Set ReplayB to dummy value.\n"); rttRecord->TreplyB = RTT_TIME_NONE; } DBG_INFO("Tt4-timeL:%u.\n", rttRecord->Tt4.frac_part); DBG_INFO("Tt4-timeH:%u.\n", rttRecord->Tt4.int_part); DBG_INFO("TreplyB-timeL:%u.\n", rttRecord->TreplyB.frac_part); DBG_INFO("TreplyB-timeH:%u.\n", rttRecord->TreplyB.int_part); // Prepare data for sending. rttFsmPtr->timeStamp = rttRecord->TreplyB; rttFsmPtr->doppler = rttRecord->dopplerR3; RTT_StageUpdate(rttFsmPtr, RTT_REQ1); DBG_INFO("RTT procedure end...\n"); } else{ DBG_INFO("RTT FSM remain current state [%d].\n", rttFsmPtr->rttStage); } break; default: DBG_ERROR("Unexpected RTT FSM stage [%d].\n", rttFsmPtr->rttStage); break; } } return SUCCESS; }