Files
KY-XTZ/src/networking/phy_layer/phy_antenna.c
T
2024-11-29 11:44:46 +08:00

428 lines
14 KiB
C

/*****************************************************************************/
/**
* @file phy_antenna.h
* @author FanHao ([email protected])
* @brief Physical layer control antenna configuration functions.
* @version 0.0
* @date 2023-04-24
*
* @copyright Copyright(c) 2024 Beijing Institute of Technology.\n
* Lab of Communication and Network
*
******************************************************************************/
/**
* @addtogroup PhysicalLayer
* @{
*/
/**
* @addtogroup PhysicalLayer_AntennaControl
* @{
*/
#include <string.h>
#include <stdint.h>
#include <math.h>
#include "error.h"
#include "phy_layer.h"
/**
* @name PhysicalLayer_AntennaConfig_Constants
* @{
*/
#define ANT_PI 3.14159265358979323846
#define ANT_COINFO_HEAD 0xAA
#define ANT_COINFO_TAIL 0xCC
#define CTRL_WORD_DEFAULT 0x00
#define ANT_MODE_BEAM_MASK 0xF0
#define ANT_BEAM_NARROR 0x00 // 8
#define ANT_BEAM_SUBNARROR_0 0x10 // 25
#define ANT_BEAM_SUBNARROR_1 0x20 // 60
#define ANT_BEAM_WIDE 0x30 // 120
#define ANT_MODE_POWER_MASK 0x0F
#define ANT_POWER_FULL 0x00
#define ANT_POWER_LOW 0x04
#define ANT_POWER_STANDBY 0x0F
#define ATN_MODE_SILENT (ANT_BEAM_SUBNARROR_0 | ANT_POWER_STANDBY)
#define ATN_MODE_LOWPOWER (ANT_BEAM_SUBNARROR_0 | ANT_POWER_LOW)
#define ATN_MODE_FULLPOWER (ANT_BEAM_SUBNARROR_0 | ANT_POWER_FULL)
#define ATN_MODE_DEFAULT ATN_MODE_SILENT
#define DEFAULT_CENTRTAL_FREQ 0x06D7 // 26.25GHz
#define RXTXMODE_RX 0x00
#define RXTXMODE_TX 0x01
#define RXTXMODE_DEFAULT 0x00
#define CALIBRMODE_NORMAL 0x00
#define CALIBRMODE_SINGLE_TR_CAL 0x01
#define RF_CTRL_DEFAULT 0x00
// Pair by regex
// Regex: (([0-9]+, ){8})
const uint16_t freqTable[L1_FRAME_MAX_HOPS] =
{
1084U, 1097U, 1110U, 1123U, 1136U, 1149U, 1162U, 1175U,
1188U, 1201U, 1214U, 1227U, 1240U, 1253U, 1266U, 1279U,
1292U, 1305U, 1318U, 1331U, 1344U, 1357U, 1370U, 1383U,
1396U, 1409U, 1422U, 1435U, 1448U, 1461U, 1474U, 1487U,
1500U, 1513U, 1526U, 1539U, 1552U, 1565U, 1578U, 1591U,
1604U, 1617U, 1630U, 1643U, 1656U, 1669U, 1682U, 1695U,
1708U, 1721U, 1734U, 1747U, 1760U, 1773U, 1786U, 1799U,
1812U, 1825U, 1838U, 1851U, 1864U, 1877U, 1890U, 1903U,
1916U, 1929U, 1942U, 1955U, 1968U, 1981U, 1994U, 2007U,
2020U, 2033U, 2046U, 2059U, 2072U, 2085U, 2098U, 2111U,
2124U
};
const int16_t antCalTable[L1_FRAME_MAX_HOPS][L1_ANT_NUM_CH] =
//Antenna-JG01
{
{ 0, 2525, -7533, -6846}, { 0, 12726, -7818, -6860},
{ 0, 2490, -7836, -6907}, { 0, 4479, -7716, -6837},
{ 0, 6409, -7770, -6776}, { 0, 14616, -7977, -6816},
{ 0, -22557, -8002, -6911}, { 0, -22587, -8121, -6918},
{ 0, -1124, -8123, -7030}, { 0, -152, -8219, -7042},
{ 0, 1823, -8209, -7130}, { 0, 1790, -8290, -7214},
{ 0, 1669, -8362, -7283}, { 0, 1634, -8459, -7276},
{ 0, 1615, -8315, -7415}, { 0, 1698, -8168, -7366},
{ 0, 1535, -8285, -7520}, { 0, 1619, -8285, -7532},
{ 0, 1609, -8201, -7693}, { 0, 1671, -8145, -7769},
{ 0, 1676, -8135, -7805}, { 0, 951, -10279, -8871},
{ 0, 976, -10235, -8978}, { 0, 1118, -10127, -9019},
{ 0, 1175, -10003, -9007}, { 0, 1386, -9847, -9039},
{ 0, 1535, -9572, -9058}, { 0, 1729, -9493, -9006},
{ 0, -1158, -9312, -9003}, { 0, 23771, -9147, -8928},
{ 0, 20733, -9074, -8924}, { 0, 2455, -8841, -8886},
{ 0, 2622, -8718, -8735}, { 0, 2791, -8615, -8705},
{ 0, 2861, -8168, -8331}, { 0, 3076, -8091, -8218},
{ 0, 3257, -8046, -8100}, { 0, 3331, -7923, -8073},
{ 0, 3396, -7826, -7994}, { 0, 3478, -7842, -8016},
{ 0, 3518, -7846, -7765}, { 0, 3585, -7753, -7715},
{ 0, 150, -8145, -8591}, { 0, 192, -8090, -8570},
{ 0, 207, -8150, -8597}, { 0, 178, -8142, -8656},
{ 0, 89, -8557, -8688}, { 0, 107, -8614, -8733},
{ 0, 194, -8605, -8782}, { 0, 153, -8655, -8881},
{ 0, 70, -8615, -8952}, { 0, 35, -8596, -9148},
{ 0, 49, -8636, -9286}, { 0, 6, -8587, -9435},
{ 0, -51, -8540, -9549}, { 0, -65, -8588, -9700},
{ 0, -55, -8503, -9820}, { 0, -20, -8414, -9907},
{ 0, -112, -8481, -10031}, { 0, -69, -8535, -10185},
{ 0, 2, -8550, -10052}, { 0, -1, -8493, -10291},
{ 0, -73, -8441, -10380}, { 0, 1958, -6930, -8295},
{ 0, -1148, -6939, -8396}, { 0, 1915, -6784, -8370},
{ 0, 1871, -6970, -8514}, { 0, 1821, -6974, -8387},
{ 0, 1781, -6906, -8431}, { 0, 1736, -6897, -8462},
{ 0, 1664, -7024, -8377}, { 0, 1629, -7127, -8436},
{ 0, 1603, -7148, -8528}, { 0, 1577, -7198, -8500},
{ 0, 1528, -7311, -8512}, { 0, 1577, -7390, -8570},
{ 0, 1616, -7436, -8572}, { 0, 1589, -7597, -8590},
{ 0, 1722, -7550, -8568}, { 0, 1741, -7691, -8449},
{ 0, 1767, -7775, -8328},
};
const uint8_t hopPattern_2KBPS_20MS[L1_FRAME_2KBPS_20MS_HOPS] =
{
0
};
const uint8_t hopPattern_2KBPS_100MS[L1_FRAME_2KBPS_100MS_HOPS] =
{
0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U,
8U, 9U, 10U, 11U, 12U, 13U, 14U, 15U,
16U, 17U, 18U, 19U, 20U, 21U, 22U, 23U,
24U, 25U, 26U, 27U, 28U, 29U, 30U, 31U,
32U, 33U, 34U, 35U, 36U, 37U, 38U, 39U,
40U, 41U, 42U, 43U, 44U, 45U, 46U, 47U,
48U, 49U, 50U, 51U, 52U, 53U, 54U, 55U,
56U, 57U, 58U, 59U, 60U, 61U, 62U, 63U,
64U, 65U, 66U, 67U, 68U, 69U, 70U, 71U,
72U, 73U, 74U, 75U, 76U, 77U, 78U, 79U,
80U
};
const uint8_t hopPattern_10KBPS_10MS[L1_FRAME_10KBPS_10MS_HOPS] =
{
80U
};
const uint8_t hopPattern_10KBPS_20MS[L1_FRAME_10KBPS_20MS_HOPS] =
{
80U, 1U, 2U, 3U, 4U, 5U, 6U, 7U,
8U, 9U, 10U
};
const uint8_t hopPattern_40KBPS_10MS[L1_FRAME_40KBPS_10MS_HOPS] =
{
0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U,
8U,
};
const uint8_t hopPattern_40KBPS_20MS[L1_FRAME_40KBPS_20MS_HOPS] =
{
0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U,
8U, 9U, 10U, 11U, 12U, 13U, 14U, 15U,
16U, 17U, 18U
};
const uint8_t hopPattern_200KBPS_5MS[L1_FRAME_200KBPS_5MS_HOPS] =
{
0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U,
8U, 9U, 10U, 11U, 12U, 13U, 14U, 15U,
16U, 17U, 18U, 19U
};
const uint8_t hopPattern_1M2BPS_5MS[L1_FRAME_1M2BPS_5MS_HOPS] =
{
0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U,
8U, 9U, 10U, 11U, 12U, 13U, 14U, 15U,
16U, 17U, 18U, 19U
};
/** @} PhysicalLayer_AntennaConfig_Constants*/
/*****************************************************************************/
/**
* @brief Initialize antenna configurations (load preset values)
*
* @param antConfig pointer to antenna configure
*
* @return None.
*
******************************************************************************/
void Phy_AntConfigInit(PHY_ANT_CONFIG *antConfig)
{
ASSERT(antConfig != NULL);
antConfig->ctrlWord = CTRL_WORD_DEFAULT;
antConfig->antMode = ATN_MODE_DEFAULT;
// FIXME: Dummy default value.
// off axis angle setting
antConfig->oaxis[0] = 0;
antConfig->oaxis[1] = 0;
// round axis angle setting
antConfig->raxis[0] = 0;
antConfig->raxis[1] = 0;
// ***********************
antConfig->antFreq[0] = (uint8_t)(DEFAULT_CENTRTAL_FREQ);
antConfig->antFreq[1] = (uint8_t)(DEFAULT_CENTRTAL_FREQ >> 8);
// FIXME: Dummy default value.
// trSelect
antConfig->trSlect = 0;
// Antenna attenuation setting
antConfig->antAtt = 0;
// phase setting
antConfig->phase = 0;
// ***********************
antConfig->rxtxMode = RXTXMODE_DEFAULT;
antConfig->calibrMode = CALIBRMODE_NORMAL;
antConfig->antReserved = 0x00;
// FIXME: Dummy default value.
// RF mode control
antConfig->rfCtrl = RF_CTRL_DEFAULT;
// RF frequency
antConfig->rfFreq[0] = (uint8_t)(DEFAULT_CENTRTAL_FREQ);
antConfig->rfFreq[1] = (uint8_t)(DEFAULT_CENTRTAL_FREQ >> 8);
// RF MGC control
antConfig->rfTxMgc = 0;
// RF channel 1&2 calibration mgc
antConfig->rf12CalMgc = 0;
// RF channel 2&3 calibration mgc
antConfig->rf34CalMgc = 0;
// Receive channel 1-4 MGC
antConfig->rcvMgc = 0;
antConfig->rfReserved0 = 0x00;
antConfig->rfReserved1 = 0x00;
// ***********************
}
/*****************************************************************************/
/**
* @brief Update antenna power mode setting
*
* @param instPtr pointer to physical layer instance
* @param mode new antenna mode
*
* @return None.
*
******************************************************************************/
void Phy_AntConfigMode(PHY_INST *instPtr, PHY_ANT_MODE mode)
{
ASSERT(instPtr != NULL);
uint8_t config = instPtr->antConfig.antMode & ANT_MODE_BEAM_MASK;
switch (mode)
{
case PHY_ANT_MODE_STANDBY:
config |= ANT_POWER_STANDBY;
break;
case PHY_ANT_MODE_POWER_LOW:
config |= ANT_POWER_LOW;
break;
case PHY_ANT_MODE_POWER_FULL:
config |= ANT_POWER_FULL;
break;
default:
DBG_ERROR("Unknown antenna mode: %" PRIu8 ", remain previous mode.\n", mode);
return;
}
instPtr->phyLog.antMode = mode;
instPtr->antConfig.antMode = config;
// Sync logs to system monitor
SysMonitor_UpdatePhysicalLayerLog(&(instPtr->phyLog));
}
/*****************************************************************************/
/**
* @brief Update antenna beam table
*
* @param instPtr pointer to physical layer instance
* @param table new beam table
* @param offset table offset
*
* @return None
*
******************************************************************************/
void Phy_SetBeamTable(PHY_INST *instPtr, PHY_ANT_ANGLE *table, uint32_t offset)
{
ASSERT(instPtr != NULL);
ASSERT(table != NULL);
for (int i = 0; i < L1_NUM_ANT_NRRW_PATTERN; i++)
{
instPtr->antNrrwPattern[i] = table[(i + offset) % L1_NUM_ANT_NRRW_PATTERN];
}
memcpy((uint32_t *)instPtr->antInfoAddr, instPtr->antNrrwPattern,
L1_NUM_ANT_NRRW_PATTERN * sizeof(PHY_ANT_ANGLE));
}
/*****************************************************************************/
/**
* @brief Update antenna point direction using predefined beam table
*
* @param instPtr pointer to physical layer instance
* @param beamNo new beam index
*
* @return SUCCESS.
* FAILURE beamNo exceeds the table size
*
******************************************************************************/
int32_t Phy_SetBeamNo(PHY_INST *instPtr, size_t beamNo, PHY_ANT_BEAM_WIDTH beamWidth)
{
ASSERT(instPtr != NULL);
if (beamWidth == PHY_ANT_BEAM_16)
{
if (beamNo >= L1_NUM_ANT_NRRW_PATTERN)
{
return FAILURE;
}
else
{
instPtr->beamNo.next = beamNo;
instPtr->antConfig.oaxis[0] = (uint8_t)(instPtr->antNrrwPattern[beamNo].oaxis >> 8);
instPtr->antConfig.oaxis[1] = (uint8_t)(instPtr->antNrrwPattern[beamNo].oaxis);
instPtr->antConfig.raxis[0] = (uint8_t)(instPtr->antNrrwPattern[beamNo].raxis >> 8);
instPtr->antConfig.raxis[1] = (uint8_t)(instPtr->antNrrwPattern[beamNo].raxis);
return SUCCESS;
}
}
else
{
// Beam number assign not support.
// Assign default angle (0,0)
instPtr->beamNo.next = 0;
instPtr->antConfig.oaxis[0] = 0;
instPtr->antConfig.oaxis[1] = 0;
instPtr->antConfig.raxis[0] = 0;
instPtr->antConfig.raxis[1] = 0;
DBG_WARNING("Using default beam number...\n");
return SUCCESS;
}
}
/*****************************************************************************/
/**
* @brief Update antenna beam width setting
*
* @param instPtr pointer to physical layer instance
* @param beamWidth new beam width
*
* @return SUCCESS.
* EPARAM
*
******************************************************************************/
int32_t Phy_SetBeamWidth(PHY_INST *instPtr, PHY_ANT_BEAM_WIDTH beamWidth)
{
ASSERT(instPtr != NULL);
uint8_t beamConfig = instPtr->antConfig.antMode & (~ANT_MODE_BEAM_MASK);
switch (beamWidth)
{
case PHY_ANT_BEAM_120:
beamConfig |= ANT_BEAM_WIDE;
break;
case PHY_ANT_BEAM_60:
beamConfig |= ANT_BEAM_SUBNARROR_1;
break;
case PHY_ANT_BEAM_25:
beamConfig |= ANT_BEAM_SUBNARROR_0;
break;
case PHY_ANT_BEAM_16:
beamConfig |= ANT_BEAM_NARROR;
break;
default:
DBG_ERROR("Beam width code: 0x%08X is illegal.\n\r", beamWidth);
return EPARAM;
}
instPtr->antConfig.antMode = beamConfig;
instPtr->beamWd.next = beamWidth;
return SUCCESS;
}
/*****************************************************************************/
/**
* @brief Set antenna to a specific direction
*
* @param instPtr pointer to physical layer instance
* @param offAx elevation angle
* @param rndAx azimuth angle
*
* @return SUCCESS.
* EPARAM - the direction is exceeds predefined range
*
******************************************************************************/
int32_t Phy_SetBeamAngle(PHY_INST *instPtr, double offAx, double rndAx)
{
ASSERT(instPtr != NULL);
uint16_t offAxDeg = 0;
uint16_t rndAxDeg = 0;
offAxDeg = (offAx >= 0) ? (((int32_t)(offAx * 180.0 / ANT_PI)) % 360) : (((int32_t)(offAx * 180.0 / ANT_PI)) % 360 + 360);
rndAxDeg = (rndAx >= 0) ? (((int32_t)(rndAx * 180.0 / ANT_PI)) % 360) : (((int32_t)(rndAx * 180.0 / ANT_PI)) % 360 + 360);
if (offAxDeg > 60)
{
DBG_ERROR("Angle out of range, off axis angle: %" PRIu16 " (should be 0~60), round axis angle: %" PRIu16 " (should be 0~360).\n",
offAxDeg, rndAxDeg);
return EPARAM;
}
offAxDeg = offAxDeg * 10;
rndAxDeg = rndAxDeg * 10;
instPtr->antConfig.oaxis[0] = (uint8_t)(offAxDeg >> 8);
instPtr->antConfig.oaxis[1] = (uint8_t)offAxDeg;
instPtr->antConfig.raxis[0] = (uint8_t)(rndAxDeg >> 8);
instPtr->antConfig.raxis[1] = (uint8_t)rndAxDeg;
return SUCCESS;
}
/** @} PhysicalLayer_AntennaControl*/
/** @} PhysicalLayer*/