1386 lines
42 KiB
C
1386 lines
42 KiB
C
/*****************************************************************************/
|
|
/**
|
|
* @file phy_layer.h
|
|
* @author FanHao ([email protected])
|
|
* @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 <string.h>
|
|
#include <stdlib.h>
|
|
#include <math.h>
|
|
#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*/
|