Initial commit
This commit is contained in:
@@ -0,0 +1,189 @@
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @file framing.h
|
||||
* @author FanHao ([email protected])
|
||||
* @brief DF Linklayer framing functions.
|
||||
* @version 0.0
|
||||
* @date 2023-05-06
|
||||
*
|
||||
* @copyright Copyright(c) 2024 Beijing Institute of Technology.\n
|
||||
* Lab of Communication and Network
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* @addtogroup LinkLayer
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup LinkLayer_Framing
|
||||
* @{
|
||||
*/
|
||||
/***************************** Include Files *********************************/
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "error.h"
|
||||
#include "common.h"
|
||||
#include "msg_def.h"
|
||||
#include "link_layer.h"
|
||||
|
||||
/************************** Constant Definitions *****************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Insert a data chunk to a bit array.
|
||||
*
|
||||
* @param frame pointer to target bit array.
|
||||
* @param offset offset of insert start position.
|
||||
* @param bytes number of insert bytes
|
||||
* @param chunk pointer to data chunk
|
||||
*
|
||||
* @return NONE
|
||||
*
|
||||
******************************************************************************/
|
||||
void L2_FrameInsertChunk(uint8_t *frame, size_t offset, size_t bytes, const void *chunk)
|
||||
{
|
||||
ASSERT(frame != NULL);
|
||||
ASSERT(chunk != NULL);
|
||||
memcpy(frame + offset, chunk, bytes);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Get a data chunk to a frame buff.
|
||||
*
|
||||
* @param frame pointer to target bit array.
|
||||
* @param offset offset of data chunk start position.
|
||||
* @param bytes number of data bytes
|
||||
* @param chunk pointer to data chunk
|
||||
*
|
||||
* @return NONE
|
||||
*
|
||||
******************************************************************************/
|
||||
void L2_FrameGetChunk(uint8_t *frame, size_t offset, size_t bytes, void *chunk)
|
||||
{
|
||||
ASSERT(frame != NULL);
|
||||
ASSERT(chunk != NULL);
|
||||
memcpy(chunk, frame + offset, bytes);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Generate crc of specified data.
|
||||
*
|
||||
* @param dataBuff pointer to data buffer.
|
||||
* @param dataLen length of specified data.
|
||||
* @param crcType type of crc
|
||||
* @param crc a pointer to 32 bit crc container.
|
||||
*
|
||||
* @return FAILURE crc type not support.
|
||||
* SUCCESS
|
||||
*
|
||||
******************************************************************************/
|
||||
static int32_t L2_CrcGen(uint8_t *dataBuff, uint32_t dataLen, L2_CRC_TYPE crcType, uint32_t *crc)
|
||||
{
|
||||
ASSERT(dataBuff != NULL);
|
||||
int32_t Status;
|
||||
switch (crcType)
|
||||
{
|
||||
case L2_CRC16_1021:
|
||||
Status = crc16_gen(dataBuff, dataLen, 0x1021, (uint16_t *)crc);
|
||||
break;
|
||||
case L2_CRC16_8005:
|
||||
Status = crc16_gen(dataBuff, dataLen, 0x8005, (uint16_t *)crc);
|
||||
break;
|
||||
case L2_CRC8_31:
|
||||
Status = crc8_gen(dataBuff, dataLen, 0x31, (uint8_t *)crc);
|
||||
break;
|
||||
default:
|
||||
Status = EPARAM;
|
||||
break;
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Append a crc of specified data, to a specified position.
|
||||
*
|
||||
* @param dataBuff pointer to data buffer.
|
||||
* @param dataLen length of specified data.
|
||||
* @param crcPos position of crc insert position
|
||||
* @param crcType type of crc
|
||||
*
|
||||
* @return FAILURE crc type not support.
|
||||
* SUCCESS
|
||||
*
|
||||
******************************************************************************/
|
||||
int32_t L2_CrcAppend(uint8_t *dataBuff, uint32_t dataLen, uint32_t crcPos, L2_CRC_TYPE crcType)
|
||||
{
|
||||
ASSERT(dataBuff != NULL);
|
||||
int32_t Status;
|
||||
uint32_t crcVal;
|
||||
uint8_t *crcPtr;
|
||||
crcPtr = dataBuff + crcPos;
|
||||
Status = L2_CrcGen(dataBuff, dataLen, crcType, &crcVal);
|
||||
if (Status != SUCCESS)
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
switch (crcType)
|
||||
{
|
||||
case L2_CRC16_1021:
|
||||
*(crcPtr + 1) = (uint8_t)(crcVal >> 8);
|
||||
*crcPtr = (uint8_t)(crcVal);
|
||||
break;
|
||||
case L2_CRC16_8005:
|
||||
*(crcPtr + 1) = (uint8_t)(crcVal >> 8);
|
||||
*crcPtr = (uint8_t)(crcVal);
|
||||
break;
|
||||
case L2_CRC8_31:
|
||||
*crcPtr = (uint8_t)crcVal;
|
||||
break;
|
||||
default:
|
||||
Status = EPARAM;
|
||||
break;
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Check data validation by crc.
|
||||
*
|
||||
* @param dataBuff pointer to data buffer.
|
||||
* @param dataLen length of specified data.
|
||||
* @param crcType type of crc
|
||||
*
|
||||
* @return FAILURE crc type not support.
|
||||
* SUCCESS
|
||||
*
|
||||
******************************************************************************/
|
||||
bool L2_CrcCheck(uint8_t *dataBuff, uint32_t dataLen, L2_CRC_TYPE crcType)
|
||||
{
|
||||
ASSERT(dataBuff != NULL);
|
||||
int32_t Status;
|
||||
uint32_t crcVal;
|
||||
crcVal = 0;
|
||||
Status = L2_CrcGen(dataBuff, dataLen, crcType, &crcVal);
|
||||
if (Status == SUCCESS)
|
||||
{
|
||||
if (crcVal == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/** @} LinkLayer_Framing*/
|
||||
|
||||
/** @} LinkLayer*/
|
||||
@@ -0,0 +1,237 @@
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @file coord.c
|
||||
* @author FanHao ([email protected])
|
||||
* @version 0.0
|
||||
* @date 2023-05-06
|
||||
*
|
||||
* @copyright Copyright(c) 2024 Beijing Institute of Technology.\n
|
||||
* Lab of Communication and Network
|
||||
*
|
||||
******************************************************************************/
|
||||
/**
|
||||
* @addtogroup LinkLayer
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup LinkLayerGeometry
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup LinkLayerGeometry_Coord
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include "coord.h"
|
||||
|
||||
const COORD COORD_NIL = {NAN, NAN, NAN};
|
||||
const COORD COORD_ZERO = {0.0, 0.0, 0.0};
|
||||
const COORD COORD_ONE = {1.0, 1.0, 1.0};
|
||||
const COORD COORD_X_AXIS = {1.0, 0.0, 0.0};
|
||||
const COORD COORD_Y_AXIS = {0.0, 1.0, 0.0};
|
||||
const COORD COORD_Z_AXIS = {0.0, 0.0, 1.0};
|
||||
|
||||
/** @brief Subtracts two coordinate vectors. */
|
||||
COORD Coord_Sub(COORD a, COORD b)
|
||||
{
|
||||
COORD ret;
|
||||
ret.x = a.x - b.x;
|
||||
ret.y = a.y - b.y;
|
||||
ret.z = a.z - b.z;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** @brief Adds two coordinate vectors. */
|
||||
COORD Coord_Add(COORD a, COORD b)
|
||||
{
|
||||
COORD ret;
|
||||
ret.x = a.x + b.x;
|
||||
ret.y = a.y + b.y;
|
||||
ret.z = a.z + b.z;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** @brief Multiplies a coordinate vector by a real number. */
|
||||
void Coord_ScalarMult(COORD *a, double t)
|
||||
{
|
||||
a->x *= t;
|
||||
a->y *= t;
|
||||
a->z *= t;
|
||||
}
|
||||
|
||||
/** @brief Multiplies a coordinate vector by a real number. */
|
||||
COORD Coord_GetScalarMult(COORD a, double t)
|
||||
{
|
||||
COORD ret;
|
||||
ret.x = a.x * t;
|
||||
ret.y = a.y * t;
|
||||
ret.z = a.z * t;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** @brief Divides a coordinate vector by a real number. */
|
||||
void Coord_ScalarDiv(COORD *a, double t)
|
||||
{
|
||||
a->x /= t;
|
||||
a->y /= t;
|
||||
a->z /= t;
|
||||
}
|
||||
|
||||
/** @brief Divides a coordinate vector by a real number. */
|
||||
COORD Coord_GetScalarDiv(COORD a, double t)
|
||||
{
|
||||
COORD ret;
|
||||
ret.x = a.x / t;
|
||||
ret.y = a.y / t;
|
||||
ret.z = a.z / t;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** @brief Dot product. */
|
||||
inline double Coord_Dot(COORD a, COORD b)
|
||||
{
|
||||
return (a.x * b.x + a.y * b.y + a.z * b.z);
|
||||
}
|
||||
|
||||
/** @brief Cross product. */
|
||||
COORD Coord_Cross(COORD a, COORD b)
|
||||
{
|
||||
COORD ret;
|
||||
ret.x = a.y * b.z - a.z * b.y;
|
||||
ret.y = a.z * b.x - a.x * b.z;
|
||||
ret.z = a.x * b.y - a.y * b.x;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** @brief Multiplies two coordinate vector in elementwise. */
|
||||
COORD Coord_ElementwiseMult(COORD a, COORD b)
|
||||
{
|
||||
COORD ret;
|
||||
ret.x = a.x * b.x;
|
||||
ret.y = a.y * b.y;
|
||||
ret.z = a.z * b.z;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** @brief Divides two coordinate vector in elementwise. */
|
||||
COORD Coord_ElementwiseDiv(COORD a, COORD b)
|
||||
{
|
||||
COORD ret;
|
||||
ret.x = a.x / b.x;
|
||||
ret.y = a.y / b.y;
|
||||
ret.z = a.z / b.z;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** @brief Calculate a coordinate vector length^2 (omits calling square root). */
|
||||
double Coord_SquareLength(COORD a)
|
||||
{
|
||||
return (a.x * a.x + a.y * a.y + a.z * a.z);
|
||||
}
|
||||
|
||||
/** @brief Calculate a coordinate vector length. */
|
||||
double Coord_Length(COORD a)
|
||||
{
|
||||
return sqrt(Coord_SquareLength(a));
|
||||
}
|
||||
|
||||
/** @brief Calculate two coordinates' distance. */
|
||||
double Coord_Distance(COORD a, COORD b)
|
||||
{
|
||||
return Coord_Length(Coord_Sub(a, b));
|
||||
}
|
||||
|
||||
/** @brief Normalize coordinate vector. */
|
||||
void Coord_Normalize(COORD *a)
|
||||
{
|
||||
Coord_ScalarDiv(a, Coord_Length(*a));
|
||||
}
|
||||
|
||||
/** @brief Normalize coordinate vector. */
|
||||
COORD Coord_GetNormalized(COORD a)
|
||||
{
|
||||
Coord_Normalize(&a);
|
||||
return a;
|
||||
}
|
||||
|
||||
/** @brief Returns the angle between the two vectors. */
|
||||
double Coord_Angle(COORD a, COORD b)
|
||||
{
|
||||
Coord_Normalize(&a);
|
||||
Coord_Normalize(&b);
|
||||
return acos(Coord_Dot(a, b));
|
||||
}
|
||||
|
||||
// Additional Coordinates convert
|
||||
// TODO: Confirm correctness
|
||||
/** @brief Convert coordinate from Launch coordinate system to ECEF. */
|
||||
COORD Coord_Launch2Ecef(COORD o, COORD p, double A, double B, double lambda)
|
||||
{
|
||||
COORD ret;
|
||||
double sinA, cosA, sinB, cosB, sinL, cosL;
|
||||
double S11, S12, S13, S21, S22, S23, S31, S32, S33;
|
||||
sinA = sin(A);
|
||||
cosA = cos(A);
|
||||
sinB = sin(B);
|
||||
cosB = cos(B);
|
||||
sinL = sin(lambda);
|
||||
cosL = cos(lambda);
|
||||
|
||||
S11 = -sinA * sinL - cosA * sinB * cosL;
|
||||
S12 = cosB * cosL;
|
||||
S13 = -cosA * sinL + sinA * sinB * cosL;
|
||||
|
||||
S21 = sinA * cosL - cosA * sinB * sinL;
|
||||
S22 = cosB * sinL;
|
||||
S23 = cosA * cosL + sinA * sinB * sinL;
|
||||
|
||||
S31 = cosA * cosB;
|
||||
S32 = sinB;
|
||||
S33 = -sinA * cosB;
|
||||
|
||||
ret.x = p.x * (S11 + S21 + S31) + o.x;
|
||||
ret.y = p.y * (S12 + S22 + S32) + o.y;
|
||||
ret.z = p.z * (S13 + S23 + S33) + o.z;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** @brief Convert coordinate from launch coordinate system to Inertia coordinate system. */
|
||||
COORD Coord_Launch2Inertia(COORD o, COORD p, double A, double B, double we, double t)
|
||||
{
|
||||
COORD ret;
|
||||
double OmgX, OmgY, OmgZ, sinwet, coswet;
|
||||
double M11, M12, M13, M21, M22, M23, M31, M32, M33;
|
||||
OmgX = cos(A) * cos(B);
|
||||
OmgY = sin(B);
|
||||
OmgZ = -sin(A) * cos(B);
|
||||
sinwet = sin(we * t);
|
||||
coswet = cos(we * t);
|
||||
|
||||
M11 = 1 - (1 - OmgX * OmgX) * (1 - coswet);
|
||||
M12 = OmgX * OmgY * (1 - coswet) + OmgZ * sinwet;
|
||||
M13 = OmgX * OmgZ * (1 - coswet) - OmgY * sinwet;
|
||||
|
||||
M21 = OmgY * OmgX * (1 - coswet) - OmgZ * sinwet;
|
||||
M22 = 1 - (1 - OmgY * OmgY) * (1 - coswet);
|
||||
M23 = OmgY * OmgZ * (1 - coswet) + OmgX * sinwet;
|
||||
|
||||
M31 = OmgZ * OmgX * (1 - coswet) + OmgY * sinwet;
|
||||
M32 = OmgZ * OmgY * (1 - coswet) - OmgX * sinwet;
|
||||
M33 = 1 - (1 - OmgZ * OmgZ) * (1 - coswet);
|
||||
|
||||
ret.x = p.x * (M11 + M21 + M31) + o.x;
|
||||
ret.y = p.y * (M12 + M22 + M32) + o.y;
|
||||
ret.z = p.z * (M13 + M23 + M33) + o.z;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** @} LinkLayerGeometry_Coord */
|
||||
|
||||
/** @} LinkLayerGeometry */
|
||||
|
||||
/** @} LinkLayer */
|
||||
@@ -0,0 +1,102 @@
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @file coord.h
|
||||
* @author FanHao ([email protected])
|
||||
* @version 0.0
|
||||
* @date 2023-05-06
|
||||
*
|
||||
* @copyright Copyright(c) 2024 Beijing Institute of Technology.\n
|
||||
* Lab of Communication and Network
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef _COORD_H
|
||||
#define _COORD_H
|
||||
/**
|
||||
* @addtogroup LinkLayer
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup LinkLayerGeometry
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup LinkLayerGeometry_Coord
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @struct COORD
|
||||
* @brief Structure for storing 3D coordinates.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
} COORD;
|
||||
|
||||
extern const COORD COORD_NIL;
|
||||
extern const COORD COORD_ZERO;
|
||||
extern const COORD COORD_ONE;
|
||||
extern const COORD COORD_X_AXIS;
|
||||
extern const COORD COORD_Y_AXIS;
|
||||
extern const COORD COORD_Z_AXIS;
|
||||
|
||||
/** @brief Subtracts two coordinate vectors. */
|
||||
COORD Coord_Sub(COORD a, COORD b);
|
||||
|
||||
/** @brief Adds two coordinate vectors. */
|
||||
COORD Coord_Add(COORD a, COORD b);
|
||||
|
||||
/** @brief Multiplies a coordinate vector by a real number. */
|
||||
void Coord_ScalarMult(COORD *a, double t);
|
||||
|
||||
/** @brief Multiplies a coordinate vector by a real number. */
|
||||
COORD Coord_GetScalarMult(COORD a, double t);
|
||||
|
||||
/** @brief Divides a coordinate vector by a real number. */
|
||||
void Coord_ScalarDiv(COORD *a, double t);
|
||||
|
||||
/** @brief Divides a coordinate vector by a real number. */
|
||||
COORD Coord_GetScalarDiv(COORD a, double t);
|
||||
|
||||
/** @brief Dot product. */
|
||||
double Coord_Dot(COORD a, COORD b);
|
||||
|
||||
/** @brief Cross product. */
|
||||
COORD Coord_Cross(COORD a, COORD b);
|
||||
|
||||
/** @brief Multiplies two coordinate vector in elementwise. */
|
||||
COORD Coord_ElementwiseMult(COORD a, COORD b);
|
||||
|
||||
/** @brief Divides two coordinate vector in elementwise. */
|
||||
COORD Coord_ElementwiseDiv(COORD a, COORD b);
|
||||
|
||||
/** @brief Calculate a coordinate vector length^2 (omits calling square root). */
|
||||
double Coord_SquareLength(COORD a);
|
||||
|
||||
/** @brief Calculate a coordinate vector length. */
|
||||
double Coord_Length(COORD a);
|
||||
|
||||
/** @brief Calculate two coordinates' distance. */
|
||||
double Coord_Distance(COORD a, COORD b);
|
||||
|
||||
/** @brief Normalize coordinate vector. */
|
||||
void Coord_Normalize(COORD *a);
|
||||
|
||||
/** @brief Normalize coordinate vector. */
|
||||
COORD Coord_GetNormalized(COORD a);
|
||||
|
||||
/** @brief Returns the angle between the two vectors. */
|
||||
double Coord_Angle(COORD a, COORD b);
|
||||
|
||||
#endif
|
||||
|
||||
/** @} LinkLayerGeometry_Coord */
|
||||
|
||||
/** @} LinkLayerGeometry */
|
||||
|
||||
/** @} LinkLayer */
|
||||
@@ -0,0 +1,88 @@
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @file eulerangles.c
|
||||
* @author FanHao ([email protected])
|
||||
* @version 0.0
|
||||
* @date 2023-05-06
|
||||
*
|
||||
* @copyright Copyright(c) 2024 Beijing Institute of Technology.\n
|
||||
* Lab of Communication and Network
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* @addtogroup LinkLayer
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup LinkLayerGeometry
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup LinkLayerGeometry_EulerAngles
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include "eulerangles.h"
|
||||
|
||||
const EULERANGLES EULERANGLES_NIL = {NAN, NAN, NAN};
|
||||
const EULERANGLES EULERANGLES_ZERO = {0.0, 0.0, 0.0};
|
||||
|
||||
/** @brief Add two EulerAngles. */
|
||||
EULERANGLES EulerAngles_Add(EULERANGLES e1, EULERANGLES e2)
|
||||
{
|
||||
EULERANGLES ret;
|
||||
ret.alpha = e1.alpha + e2.alpha;
|
||||
ret.beta = e1.beta + e2.beta;
|
||||
ret.gamma = e1.gamma + e2.gamma;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** @brief Subtracts two EulerAngles. */
|
||||
EULERANGLES EulerAngles_Sub(EULERANGLES e1, EULERANGLES e2)
|
||||
{
|
||||
EULERANGLES ret;
|
||||
ret.alpha = e1.alpha - e2.alpha;
|
||||
ret.beta = e1.beta - e2.beta;
|
||||
ret.gamma = e1.gamma - e2.gamma;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** @brief Multiplies EulerAngles by a real number. */
|
||||
void EulerAngles_ScalarMult(EULERANGLES *e, double f)
|
||||
{
|
||||
e->alpha *= f;
|
||||
e->beta *= f;
|
||||
e->gamma *= f;
|
||||
}
|
||||
|
||||
/** @brief Multiplies EulerAngles by a real number. */
|
||||
EULERANGLES EulerAngles_GetScalarMult(EULERANGLES e, double f)
|
||||
{
|
||||
EulerAngles_ScalarMult(&e, f);
|
||||
return e;
|
||||
}
|
||||
|
||||
/** @brief Normalize EulerAngles. */
|
||||
void EulerAngles_Normalize(EULERANGLES *e)
|
||||
{
|
||||
e->alpha = fmod(e->alpha, 2 * EUL_PI);
|
||||
e->beta = fmod(e->beta, 2 * EUL_PI);
|
||||
e->gamma = fmod(e->gamma, 2 * EUL_PI);
|
||||
}
|
||||
|
||||
/** @brief Normalize EulerAngles. */
|
||||
EULERANGLES EulerAngles_GetNormalize(EULERANGLES e)
|
||||
{
|
||||
EulerAngles_Normalize(&e);
|
||||
return e;
|
||||
}
|
||||
|
||||
/** @} LinkLayerGeometry_EulerAngles */
|
||||
|
||||
/** @} LinkLayerGeometry */
|
||||
|
||||
/** @} LinkLayer */
|
||||
@@ -0,0 +1,93 @@
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @file eulerangles.h
|
||||
* @author FanHao ([email protected])
|
||||
* @version 0.0
|
||||
* @date 2023-05-06
|
||||
*
|
||||
* @copyright Copyright(c) 2024 Beijing Institute of Technology.\n
|
||||
* Lab of Communication and Network
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* @addtogroup LinkLayer
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup LinkLayerGeometry
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup LinkLayerGeometry_EulerAngles
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef __EULERANGLES_H
|
||||
#define __EULERANGLES_H
|
||||
|
||||
#define EUL_PI 3.14159265358979323846
|
||||
|
||||
#define DEG2RAD(d) ((EUL_PI / 180.0) * d)
|
||||
#define RAD2DEG(r) ((180.0 / EUL_PI) * r)
|
||||
|
||||
/**
|
||||
* Orientations are represented by 3D double precision Tait-Bryan (Euler) tuples
|
||||
* called EulerAngles. The angles are in Z, Y', X" order that is often called
|
||||
* intrinsic rotations, they are measured in radians. The default (unrotated)
|
||||
* orientation is along the X axis. Conceptually, the Z axis rotation is heading,
|
||||
* the Y' axis rotation is descending (negative elevation), the X" axis rotation is bank.
|
||||
* For example, positive rotation along the Z axis rotates X into Y (turns left), positive
|
||||
* rotation along the Y axis rotates Z into X (leans forward), positive rotation
|
||||
* along the X axis rotates Y into Z (leans right).
|
||||
*/
|
||||
|
||||
/**
|
||||
* @struct EULERANGLES
|
||||
* @brief Structure for standard quaternion
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
double alpha; // unit rad
|
||||
double beta; // unit rad
|
||||
double gamma; // unit rad
|
||||
} EULERANGLES;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
EULERANGLES_NONE = 0,
|
||||
EULERANGLES_ZYX = 1,
|
||||
EULERANGLES_ZYZ = 2,
|
||||
EULERANGLES_XYZ = 3,
|
||||
} EULERANGLES_TYPE;
|
||||
|
||||
extern const EULERANGLES EULERANGLES_ZERO;
|
||||
extern const EULERANGLES EULERANGLES_NIL;
|
||||
|
||||
/** @brief Add two EulerAngles. */
|
||||
EULERANGLES EulerAngles_Add(EULERANGLES e1, EULERANGLES e2);
|
||||
|
||||
/** @brief Subtracts two EulerAngles. */
|
||||
EULERANGLES EulerAngles_Sub(EULERANGLES e1, EULERANGLES e2);
|
||||
|
||||
/** @brief Multiplies EulerAngles by a real number. */
|
||||
void EulerAngles_ScalarMult(EULERANGLES *e, double f);
|
||||
|
||||
/** @brief Multiplies EulerAngles by a real number. */
|
||||
EULERANGLES EulerAngles_GetScalarMult(EULERANGLES e, double f);
|
||||
|
||||
/** @brief Normalize EulerAngles. */
|
||||
void EulerAngles_Normalize(EULERANGLES *e);
|
||||
|
||||
/** @brief Normalize EulerAngles. */
|
||||
EULERANGLES EulerAngles_GetNormalize(EULERANGLES e);
|
||||
|
||||
#endif
|
||||
|
||||
/** @} LinkLayerGeometry_EulerAngles */
|
||||
|
||||
/** @} LinkLayerGeometry */
|
||||
|
||||
/** @} LinkLayer */
|
||||
@@ -0,0 +1,480 @@
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @file quaternion.c
|
||||
* @author FanHao ([email protected])
|
||||
* @version 0.0
|
||||
* @date 2023-05-06
|
||||
*
|
||||
* @copyright Copyright(c) 2024 Beijing Institute of Technology.\n
|
||||
* Lab of Communication and Network
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* @addtogroup LinkLayer
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup LinkLayerGeometry
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup LinkLayerGeometry_Quaternion
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "coord.h"
|
||||
#include "eulerangles.h"
|
||||
#include "quaternion.h"
|
||||
|
||||
typedef union
|
||||
{
|
||||
float value;
|
||||
uint32_t raw;
|
||||
} SOFT_FLOAT;
|
||||
|
||||
typedef union
|
||||
{
|
||||
double value;
|
||||
uint64_t raw;
|
||||
} SOFT_DOUBLE;
|
||||
|
||||
const SOFT_FLOAT EPS_FLOAT = {.raw = 0x34000000};
|
||||
const SOFT_DOUBLE EPS_DOUBLE = {.raw = 0x3CB0000000000000};
|
||||
|
||||
const QUATERNION QUATERNION_IDENTITY = {1.0, 0.0, 0.0, 0.0};
|
||||
const QUATERNION QUATERNION_NIL = {NAN, NAN, NAN, NAN};
|
||||
|
||||
/** @brief Subtracts two quaternions. */
|
||||
QUATERNION Quaternion_Sub(QUATERNION q1, QUATERNION q2)
|
||||
{
|
||||
QUATERNION ret;
|
||||
ret.s = q1.s - q2.s;
|
||||
ret.i = q1.i - q2.i;
|
||||
ret.j = q1.j - q2.j;
|
||||
ret.k = q1.k - q2.k;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** @brief Adds two quaternions. */
|
||||
QUATERNION Quaternion_Add(QUATERNION q1, QUATERNION q2)
|
||||
{
|
||||
QUATERNION ret;
|
||||
ret.s = q1.s + q2.s;
|
||||
ret.i = q1.i + q2.i;
|
||||
ret.j = q1.j + q2.j;
|
||||
ret.k = q1.k + q2.k;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** @brief Multiplies a quaternion by a real number. */
|
||||
void Quaternion_ScalarMult(QUATERNION *q, double t)
|
||||
{
|
||||
q->s *= t;
|
||||
q->i *= t;
|
||||
q->j *= t;
|
||||
q->k *= t;
|
||||
}
|
||||
|
||||
/** @brief Multiplies a quaternion by a real number. */
|
||||
QUATERNION Quaternion_GetScalarMult(QUATERNION a, double t)
|
||||
{
|
||||
Quaternion_ScalarMult(&a, t);
|
||||
return a;
|
||||
}
|
||||
|
||||
/** @brief Divides a quaternion by a real number. */
|
||||
void Quaternion_ScalarDiv(QUATERNION *q, double t)
|
||||
{
|
||||
q->s /= t;
|
||||
q->i /= t;
|
||||
q->j /= t;
|
||||
q->k /= t;
|
||||
}
|
||||
|
||||
/** @brief Divides a quaternion by a real number. */
|
||||
QUATERNION Quaternion_GetScalarDiv(QUATERNION q, double t)
|
||||
{
|
||||
Quaternion_ScalarDiv(&q, t);
|
||||
return q;
|
||||
}
|
||||
|
||||
/** @brief Multiplies two quaternions. */
|
||||
QUATERNION Quaternion_Mult(QUATERNION q1, QUATERNION q2)
|
||||
{
|
||||
QUATERNION ret;
|
||||
ret.s = q1.s * q2.s - (q1.i * q2.i + q1.j * q2.j + q1.k * q2.k);
|
||||
ret.i = q1.j * q2.k - q1.k * q2.j + q1.s * q2.i + q1.i * q2.s;
|
||||
ret.j = q1.k * q2.i - q1.i * q2.k + q1.s * q2.j + q1.j * q2.s;
|
||||
ret.k = q1.i * q2.j - q1.j * q2.i + q1.s * q2.k + q1.k * q2.s;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** @brief Divides two quaternions. */
|
||||
QUATERNION Quaternion_Div(QUATERNION q1, QUATERNION q2)
|
||||
{
|
||||
Quaternion_Inverse(&q2);
|
||||
return Quaternion_Mult(q1, q2);
|
||||
}
|
||||
|
||||
/** @brief Dot product. */
|
||||
inline double Quaternion_Dot(QUATERNION q1, QUATERNION q2)
|
||||
{
|
||||
return (q1.s * q2.s + q1.i * q2.i + q1.j * q2.j + q1.k * q2.k);
|
||||
}
|
||||
|
||||
/** @brief Calculate a quaternion length^2 (omits calling square root). */
|
||||
inline double Quaternion_SquareLength(QUATERNION q)
|
||||
{
|
||||
return (q.s * q.s + q.i * q.i + q.j * q.j + q.k * q.k);
|
||||
}
|
||||
|
||||
/** @brief Calculate a quaternion length. */
|
||||
inline double Quaternion_Length(QUATERNION q)
|
||||
{
|
||||
return sqrt(Quaternion_SquareLength(q));
|
||||
}
|
||||
|
||||
/** @brief Normalize quaternion. */
|
||||
void Quaternion_Normalize(QUATERNION *q)
|
||||
{
|
||||
Quaternion_ScalarDiv(q, Quaternion_Length(*q));
|
||||
}
|
||||
|
||||
/** @brief Normalize quaternion. */
|
||||
QUATERNION Quaternion_GetNormalized(QUATERNION q)
|
||||
{
|
||||
Quaternion_Normalize(&q);
|
||||
return q;
|
||||
}
|
||||
|
||||
/** @brief Conjugated quaternion. */
|
||||
void Quaternion_Conjugated(QUATERNION *q)
|
||||
{
|
||||
q->i = -q->i;
|
||||
q->j = -q->j;
|
||||
q->k = -q->k;
|
||||
}
|
||||
|
||||
/** @brief Conjugated quaternion. */
|
||||
QUATERNION Quaternion_GetConjugated(QUATERNION q)
|
||||
{
|
||||
Quaternion_Conjugated(&q);
|
||||
return q;
|
||||
}
|
||||
|
||||
/** @brief Inverse quaternion. */
|
||||
void Quaternion_Inverse(QUATERNION *q)
|
||||
{
|
||||
Quaternion_Conjugated(q);
|
||||
Quaternion_ScalarDiv(q, Quaternion_SquareLength(*q));
|
||||
}
|
||||
|
||||
/** @brief Inverse quaternion. */
|
||||
QUATERNION Quaternion_GeInverse(QUATERNION q)
|
||||
{
|
||||
Quaternion_Inverse(&q);
|
||||
return q;
|
||||
}
|
||||
|
||||
inline double Quaternion_GetRotationAngle(QUATERNION q)
|
||||
{
|
||||
return (acos(q.s) * 2);
|
||||
}
|
||||
|
||||
/** @brief Get axis of quaternion. */
|
||||
COORD Quaternion_GetRotationAxis(QUATERNION q)
|
||||
{
|
||||
double sin_theta_inv;
|
||||
COORD ret;
|
||||
sin_theta_inv = 1.0 / sin(acos(q.s));
|
||||
ret.x = q.i * sin_theta_inv;
|
||||
ret.y = q.j * sin_theta_inv;
|
||||
ret.z = q.k * sin_theta_inv;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** @brief Get the axis and rotate angle of a unit Quaternion */
|
||||
void Quaternion_GetRotationAxisAndAngle(QUATERNION q, COORD *axis, double *angle)
|
||||
{
|
||||
double sin_theta_inv;
|
||||
*angle = acos(q.s);
|
||||
|
||||
// pre-compute to save time
|
||||
sin_theta_inv = 1.0 / sin(*angle);
|
||||
|
||||
// now the vector
|
||||
axis->x = q.i * sin_theta_inv;
|
||||
axis->y = q.j * sin_theta_inv;
|
||||
axis->z = q.k * sin_theta_inv;
|
||||
*angle = (*angle) * 2;
|
||||
}
|
||||
|
||||
/** @brief Decompose the rotation on to 2 parts. */
|
||||
void Quaternion_GetSwingAndTwist(QUATERNION q, COORD axis, QUATERNION *swing, QUATERNION *twist)
|
||||
{
|
||||
double p;
|
||||
COORD v;
|
||||
v.x = q.i;
|
||||
v.y = q.j;
|
||||
v.z = q.k;
|
||||
// return projection v1 on to v2 (parallel component)
|
||||
p = Coord_Dot(v, axis);
|
||||
v = Coord_GetScalarMult(axis, p);
|
||||
twist->s = q.s;
|
||||
twist->i = v.x;
|
||||
twist->j = v.y;
|
||||
twist->k = v.z;
|
||||
Quaternion_Normalize(twist);
|
||||
*swing = Quaternion_Mult(q, Quaternion_GetConjugated(*twist));
|
||||
}
|
||||
|
||||
/** @brief rotates v by this quaternion (quaternion must be unit) */
|
||||
COORD Quaternion_Rotate(QUATERNION q, COORD v)
|
||||
{
|
||||
QUATERNION temp;
|
||||
COORD ret;
|
||||
temp.s = 0;
|
||||
temp.i = v.x;
|
||||
temp.j = v.y;
|
||||
temp.k = v.z;
|
||||
temp = Quaternion_Mult(q, temp);
|
||||
Quaternion_Conjugated(&q);
|
||||
temp = Quaternion_Mult(temp, q);
|
||||
ret.x = temp.i;
|
||||
ret.y = temp.j;
|
||||
ret.z = temp.k;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** @brief returns the euler angles from a rotation Quaternion */
|
||||
EULERANGLES Quaternion_ToEulerAngles(QUATERNION q, EULERANGLES_TYPE type)
|
||||
{
|
||||
EULERANGLES ret;
|
||||
switch (type)
|
||||
{
|
||||
case EULERANGLES_ZYX:
|
||||
{
|
||||
/* Covert form matlab 2023a */
|
||||
// Cap all inputs to asin to 1, since values >1 produce complex
|
||||
// results
|
||||
// Since the quaternion is of unit length, this should never happen,
|
||||
// but some code generation configuration seem to hit this edge case
|
||||
// under some circumstances.
|
||||
|
||||
double asinValue;
|
||||
bool mask1, mask2;
|
||||
|
||||
asinValue = -2.0 * (q.i * q.k - q.s * q.j);
|
||||
mask1 = asinValue >= 1.0 - 10 * EPS_DOUBLE.value;
|
||||
mask2 = asinValue <= -1.0 + 10 * EPS_DOUBLE.value;
|
||||
if (mask1)
|
||||
asinValue = 1;
|
||||
if (mask2)
|
||||
asinValue = -1;
|
||||
|
||||
if (mask1 || mask2)
|
||||
{
|
||||
ret.alpha = (asinValue > 0) ? (-2.0 * atan2(q.i, q.s)) : (2.0 * atan2(q.i, q.s));
|
||||
ret.gamma = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret.alpha = atan2(2.0 * (q.i * q.j + q.s * q.k), q.s * q.s + q.i * q.i - q.j * q.j - q.k * q.k);
|
||||
ret.gamma = atan2(2.0 * (q.j * q.k + q.s * q.i), q.s * q.s - q.i * q.i - q.j * q.j + q.k * q.k);
|
||||
}
|
||||
ret.beta = asin(asinValue);
|
||||
break;
|
||||
}
|
||||
|
||||
case EULERANGLES_ZYZ:
|
||||
{
|
||||
// TODO;
|
||||
ret = EULERANGLES_NIL;
|
||||
break;
|
||||
}
|
||||
|
||||
case EULERANGLES_XYZ:
|
||||
{
|
||||
/* Covert form matlab 2023a */
|
||||
// Prevent singularities as done in ZYX case
|
||||
// Alternative to rotm2eul(quat2rotm(q), 'XYZ') with fewer
|
||||
// operations
|
||||
// sin(y) = R13 = 2 * (qx*qz + qy*qw)
|
||||
// tan(x) = sin(x) / cos(x) = -R23 / R33
|
||||
// = -2 * (qy*qz - qx*qw) / (1 - 2*(qx^2 + qy^2))
|
||||
// = -2 * (qy*qz - qx*qw) / (qw^2 - qx^2 - qy^2 + qz^2)
|
||||
// tan(z) = sin(z) / cos(z) = -R12 / R11
|
||||
// = -2 * (qx*qy - qz*qw) / (1 - 2*(qy^2 + qz^2))
|
||||
// = -2 * (qy*qz - qx*qw) / (qw^2 + qx^2 - qy^2 - qz^2)
|
||||
|
||||
double asinValue;
|
||||
bool mask1, mask2;
|
||||
|
||||
asinValue = 2.0 * (q.i * q.k + q.s * q.j);
|
||||
mask1 = asinValue >= 1.0 - 10 * EPS_DOUBLE.value;
|
||||
mask2 = asinValue <= -1.0 + 10 * EPS_DOUBLE.value;
|
||||
if (mask1)
|
||||
asinValue = 1;
|
||||
if (mask2)
|
||||
asinValue = -1;
|
||||
if (mask1 || mask2)
|
||||
{
|
||||
ret.alpha = 0;
|
||||
ret.gamma = (asinValue > 0) ? (2.0 * atan2(q.i, q.s)) : (-2.0 * atan2(q.i, q.s));
|
||||
}
|
||||
else
|
||||
{
|
||||
ret.alpha = atan2(-2.0 * (q.j * q.k - q.s * q.i), q.s * q.s - q.i * q.i - q.j * q.j + q.k * q.k);
|
||||
ret.gamma = atan2(-2.0 * (q.i * q.j - q.s * q.k), q.s * q.s + q.i * q.i - q.j * q.j - q.k * q.k);
|
||||
}
|
||||
ret.beta = asin(asinValue);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
ret = EULERANGLES_NIL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** @brief returns the rotation Quaternion from a euler angles */
|
||||
QUATERNION Quaternion_FromeEulerAngles(EULERANGLES e, EULERANGLES_TYPE type)
|
||||
{
|
||||
QUATERNION ret;
|
||||
double cosx, sinx, cosy, siny, cosz, sinz;
|
||||
cosx = cos(e.alpha * 0.5);
|
||||
sinx = sin(e.alpha * 0.5);
|
||||
cosy = cos(e.beta * 0.5);
|
||||
siny = sin(e.beta * 0.5);
|
||||
cosz = cos(e.gamma * 0.5);
|
||||
sinz = sin(e.gamma * 0.5);
|
||||
switch (type)
|
||||
{
|
||||
case EULERANGLES_ZYX:
|
||||
ret.s = cosx * cosy * cosz + sinx * siny * sinz;
|
||||
ret.i = cosx * cosy * sinz - sinx * siny * cosz;
|
||||
ret.j = cosx * siny * cosz + sinx * cosy * sinz;
|
||||
ret.k = sinx * cosy * cosz - cosx * siny * sinz;
|
||||
break;
|
||||
case EULERANGLES_ZYZ:
|
||||
ret.s = cosx * cosy * cosz - sinx * cosy * sinz;
|
||||
ret.i = cosx * siny * sinz - sinx * siny * cosz;
|
||||
ret.j = cosx * siny * cosz + sinx * siny * sinz;
|
||||
ret.k = sinx * cosy * cosz + cosx * cosy * sinz;
|
||||
break;
|
||||
case EULERANGLES_XYZ:
|
||||
ret.s = cosx * cosy * cosz - sinx * siny * sinz;
|
||||
ret.i = sinx * cosy * cosz + cosx * siny * sinz;
|
||||
ret.j = -sinx * cosy * sinz + cosx * siny * cosz;
|
||||
ret.k = cosx * cosy * sinz + sinx * siny * cosz;
|
||||
break;
|
||||
default:
|
||||
ret = QUATERNION_NIL;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** @brief adapted from https://svn.code.sf.net/p/irrlicht/code/trunk/include/quaternion.h */
|
||||
QUATERNION Quaternion_RotationFromTo(COORD from, COORD to)
|
||||
{
|
||||
// Based on Stan Melax's article in Game Programming Gems
|
||||
COORD axis;
|
||||
QUATERNION ret;
|
||||
double c, s;
|
||||
Coord_Normalize(&from);
|
||||
Coord_Normalize(&to);
|
||||
|
||||
c = Coord_Dot(from, to);
|
||||
|
||||
if (c >= 1.0)
|
||||
{ // If dot == 1, vectors are the same
|
||||
return QUATERNION_IDENTITY; // identity
|
||||
}
|
||||
else if (c <= -1.0)
|
||||
{ // exactly opposite
|
||||
axis = Coord_Cross(COORD_X_AXIS, from);
|
||||
|
||||
if (Coord_Length(axis) == 0)
|
||||
axis = Coord_Cross(COORD_Y_AXIS, from);
|
||||
|
||||
// same as fromAxisAngle(axis, PI).normalize();
|
||||
ret.s = 0;
|
||||
ret.i = axis.x;
|
||||
ret.j = axis.y;
|
||||
ret.k = axis.z;
|
||||
Quaternion_Normalize(&ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
s = sqrt((1 + c) * 2);
|
||||
axis = Coord_Cross(from, to);
|
||||
Coord_ScalarDiv(&axis, s);
|
||||
ret.s = s * 0.5;
|
||||
ret.i = axis.x;
|
||||
ret.j = axis.y;
|
||||
ret.k = axis.z;
|
||||
Quaternion_Normalize(&ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** @brief linear quaternion interpolation */
|
||||
QUATERNION Quaternion_Lerp(QUATERNION q1, QUATERNION q2, double t)
|
||||
{
|
||||
QUATERNION ret;
|
||||
Quaternion_ScalarMult(&q1, 1 - t);
|
||||
Quaternion_ScalarMult(&q1, t);
|
||||
ret = Quaternion_Add(q1, q2);
|
||||
Quaternion_Normalize(&ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** @brief spherical linear interpolation */
|
||||
QUATERNION Quaternion_Slerp(QUATERNION q1, QUATERNION q2, double t)
|
||||
{
|
||||
double dot;
|
||||
QUATERNION q3, ret;
|
||||
dot = Quaternion_Dot(q1, q2);
|
||||
/* dot = cos(theta)
|
||||
if (dot < 0), q1 and q2 are more than 90 degrees apart,
|
||||
so we can invert one to reduce spinning */
|
||||
if (dot < 0)
|
||||
{
|
||||
dot = -dot;
|
||||
q3.s = -q2.s;
|
||||
q3.i = -q2.i;
|
||||
q3.j = -q2.j;
|
||||
q3.k = -q2.k;
|
||||
}
|
||||
else
|
||||
{
|
||||
q3 = q2;
|
||||
}
|
||||
|
||||
if (dot < 0.95)
|
||||
{
|
||||
double angle = acos(dot);
|
||||
Quaternion_ScalarMult(&q1, sin(angle * (1 - t)));
|
||||
Quaternion_ScalarMult(&q3, sin(angle * t));
|
||||
ret = Quaternion_Add(q1, q3);
|
||||
Quaternion_ScalarDiv(&ret, sin(angle));
|
||||
return ret;
|
||||
}
|
||||
// if the angle is small, use linear interpolation
|
||||
else
|
||||
{
|
||||
return Quaternion_Lerp(q1, q3, t);
|
||||
}
|
||||
}
|
||||
|
||||
/** @} LinkLayerGeometry_Quaternion */
|
||||
|
||||
/** @} LinkLayerGeometry */
|
||||
|
||||
/** @} LinkLayer */
|
||||
@@ -0,0 +1,144 @@
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @file quaternion.h
|
||||
* @author FanHao ([email protected])
|
||||
* @version 0.0
|
||||
* @date 2023-05-06
|
||||
*
|
||||
* @copyright Copyright(c) 2024 Beijing Institute of Technology.\n
|
||||
* Lab of Communication and Network
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* @addtogroup LinkLayer
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup LinkLayerGeometry
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup LinkLayerGeometry_Quaternion
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef __QUATERNION_H
|
||||
#define __QUATERNION_H
|
||||
|
||||
#include "coord.h"
|
||||
#include "eulerangles.h"
|
||||
|
||||
/**
|
||||
* @struct QUATERNION
|
||||
* @brief Structure for standard quaternion
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
double s;
|
||||
double i;
|
||||
double j;
|
||||
double k;
|
||||
} QUATERNION;
|
||||
|
||||
extern const QUATERNION QUATERNION_IDENTITY;
|
||||
extern const QUATERNION QUATERNION_NIL;
|
||||
|
||||
/** @brief Subtracts two quaternions. */
|
||||
QUATERNION Quaternion_Sub(QUATERNION q1, QUATERNION q2);
|
||||
|
||||
/** @brief Adds two quaternions. */
|
||||
QUATERNION Quaternion_Add(QUATERNION q1, QUATERNION q2);
|
||||
|
||||
/** @brief Multiplies a quaternion by a real number. */
|
||||
void Quaternion_ScalarMult(QUATERNION *q, double t);
|
||||
|
||||
/** @brief Multiplies a quaternion by a real number. */
|
||||
QUATERNION Quaternion_GetScalarMult(QUATERNION a, double t);
|
||||
|
||||
/** @brief Divides a quaternion by a real number. */
|
||||
void Quaternion_ScalarDiv(QUATERNION *q, double t);
|
||||
|
||||
/** @brief Divides a quaternion by a real number. */
|
||||
QUATERNION Quaternion_GetScalarDiv(QUATERNION a, double t);
|
||||
|
||||
/** @brief Multiplies two quaternions. */
|
||||
QUATERNION Quaternion_Mult(QUATERNION q1, QUATERNION q2);
|
||||
|
||||
/** @brief Divides two quaternions. */
|
||||
QUATERNION Quaternion_Div(QUATERNION q1, QUATERNION q2);
|
||||
|
||||
/** @brief Dot product. */
|
||||
double Quaternion_Dot(QUATERNION q1, QUATERNION q2);
|
||||
|
||||
/** @brief Calculate a quaternion length^2 (omits calling square root). */
|
||||
double Quaternion_SquareLength(QUATERNION q);
|
||||
|
||||
/** @brief Calculate a quaternion length. */
|
||||
double Quaternion_Length(QUATERNION q);
|
||||
|
||||
/** @brief Normalize quaternion. */
|
||||
void Quaternion_Normalize(QUATERNION *q);
|
||||
|
||||
/** @brief Normalize quaternion. */
|
||||
QUATERNION Quaternion_GetNormalized(QUATERNION q);
|
||||
|
||||
/** @brief Conjugated quaternion. */
|
||||
void Quaternion_Conjugated(QUATERNION *q);
|
||||
|
||||
/** @brief Conjugated quaternion. */
|
||||
QUATERNION Quaternion_GetConjugated(QUATERNION q);
|
||||
|
||||
/** @brief Inverse quaternion. */
|
||||
void Quaternion_Inverse(QUATERNION *q);
|
||||
|
||||
/** @brief Inverse quaternion. */
|
||||
QUATERNION Quaternion_GeInverse(QUATERNION q);
|
||||
|
||||
/** @brief Get rotate angle of quaternion. */
|
||||
double Quaternion_GetRotationAngle(QUATERNION q);
|
||||
|
||||
/** @brief Get axis of quaternion. */
|
||||
COORD Quaternion_GetRotationAxis(QUATERNION q);
|
||||
|
||||
/** @brief Get the axis and rotate angle of a unit Quaternion */
|
||||
void Quaternion_GetRotationAxisAndAngle(QUATERNION q, COORD *axis, double *angle);
|
||||
|
||||
/** @brief Decompose the rotation on to 2 parts.
|
||||
1. Twist - rotation around the "direction" vector
|
||||
2. Swing - rotation around axis that is perpendicular to "direction" vector
|
||||
The rotation can be composed back by rotation = swing * twist
|
||||
|
||||
has singularity in case of swing_rotation close to 180 degrees rotation.
|
||||
if the input quaternion is of non-unit length, the outputs are non-unit as well
|
||||
otherwise, outputs are both unit
|
||||
*/
|
||||
void Quaternion_GetSwingAndTwist(QUATERNION q, COORD axis, QUATERNION *swing, QUATERNION *twist);
|
||||
|
||||
/** @brief rotates v by this quaternion (quaternion must be unit) */
|
||||
COORD Quaternion_Rotate(QUATERNION q, COORD v);
|
||||
|
||||
/** @brief returns the euler angles from a rotation Quaternion */
|
||||
EULERANGLES Quaternion_ToEulerAngles(QUATERNION q, EULERANGLES_TYPE type);
|
||||
|
||||
/** @brief returns the rotation Quaternion from a euler angles */
|
||||
QUATERNION Quaternion_FromeEulerAngles(EULERANGLES e, EULERANGLES_TYPE type);
|
||||
|
||||
/** @brief adapted from https://svn.code.sf.net/p/irrlicht/code/trunk/include/quaternion.h */
|
||||
QUATERNION Quaternion_RotationFromTo(COORD from, COORD to);
|
||||
|
||||
/** @brief linear quaternion interpolation */
|
||||
QUATERNION Quaternion_Lerp(QUATERNION q1, QUATERNION q2, double t);
|
||||
|
||||
/** @brief spherical linear interpolation */
|
||||
QUATERNION Quaternion_Slerp(QUATERNION q1, QUATERNION q2, double t);
|
||||
|
||||
#endif
|
||||
|
||||
/** @} LinkLayerGeometry_Quaternion */
|
||||
|
||||
/** @} LinkLayerGeometry */
|
||||
|
||||
/** @} LinkLayer */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,221 @@
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @file link_layer.h
|
||||
* @author FanHao ([email protected])
|
||||
* @brief DF Linklayer header file.
|
||||
* @version 0.1
|
||||
* @date 2023-05-06
|
||||
*
|
||||
* @copyright Copyright(c) 2024 Beijing Institute of Technology.\n
|
||||
* Lab of Communication and Network
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* @defgroup LinkLayer
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef __LINK_LAYER_H_
|
||||
#define __LINK_LAYER_H_
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
#include <stdint.h>
|
||||
#include "link_layer_types.h"
|
||||
#include "schdevent.h"
|
||||
#include "node_list.h"
|
||||
#include "circ_queue.h"
|
||||
#include "../phy_layer/phy_layer.h"
|
||||
#include "../../system_monitor.h"
|
||||
/************************** Constant Definitions *****************************/
|
||||
/***************** Macros (Inline Functions) Definitions *********************/
|
||||
#define AssertL2Event(instPtr, event) Linklayer_EventHandler(instPtr, event)
|
||||
/**************************** Type Definitions *******************************/
|
||||
|
||||
/**
|
||||
* @struct L2_CONFIG
|
||||
* @brief A struct holds all linklayer initialization parameters
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
L2_NODE_TYPE myType; ///< node type
|
||||
uint8_t clustId; ///< node cluster id
|
||||
uint8_t myId; ///< node id
|
||||
uint8_t headId; ///< head node id
|
||||
uint8_t netScale; ///< net scale
|
||||
PHY_INST *phyInstPtr; ///< pointer to system physical layer instance
|
||||
TMC_INST *tmcInstPtr; ///< pointer to system timer controller layer instance
|
||||
} L2_CONFIG;
|
||||
|
||||
/**
|
||||
* @struct L2_LOG
|
||||
* @brief A struct holds linklayer operating log
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t frameRx; ///< total rx frame count
|
||||
uint32_t frameTx; ///< total tx frame count
|
||||
uint32_t frameRecv; ///< total received frame count
|
||||
uint32_t frameCorrect; ///< total correctly received frame count
|
||||
|
||||
uint32_t advRxCnt; ///< advertise rx frame count
|
||||
uint32_t advTxCnt; ///< advertise tx frame count
|
||||
uint32_t advRecvCnt; ///< advertise received frame count
|
||||
uint32_t advCorrectCnt; ///< advertise correctly received frame count
|
||||
|
||||
uint32_t cfmRxCnt; ///< confirm rx frame count
|
||||
uint32_t cfmTxCnt; ///< confirm tx frame count
|
||||
uint32_t cfmRecvCnt; ///< confirm received frame count
|
||||
uint32_t cfmCorrectCnt; ///< confirm correctly received frame count
|
||||
|
||||
uint32_t svcRxCnt; ///< service rx frame count
|
||||
uint32_t svcTxCnt; ///< service tx frame count
|
||||
uint32_t svcRecvCnt; ///< service received frame count
|
||||
uint32_t svcCorrectCnt; ///< service correctly received frame count
|
||||
|
||||
int64_t timeDev; ///< last time deviation estimation result
|
||||
uint8_t lastBeamWidth; ///< last beam width
|
||||
uint32_t reconnectCnt; ///< reconnect trial count
|
||||
|
||||
PAYLOAD rxLog;
|
||||
PAYLOAD txLog;
|
||||
} L2_LOG;
|
||||
|
||||
/**
|
||||
* @struct L2_INST
|
||||
* @brief A linklayer instance
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
L2_CONFIG config; ///< linklayer configuration parameters
|
||||
L2_NODE_INFO myInfo; ///< current node info
|
||||
NODE_LIST *nodeList; ///< discovered node list
|
||||
L2_SCHD_POOL *schdEventPool; ///< event schedule pool
|
||||
uint32_t netStartTime; ///< network start time
|
||||
bool isEnable; ///< indicates if the node is connected to the network
|
||||
bool dataAvail; ///< indicates if there is a valid received frame data in rx buffer
|
||||
bool cxn2Net; ///< indicates if the node is connected to the network
|
||||
L2_RCD frameNum; ///< stores the last current and next frame number.
|
||||
L2_RCD slotNum; ///< stores the last current and next slot number.
|
||||
L2_RCD frame; ///< stores the last current and next link layer frame type.
|
||||
L2_RCD tor; ///< stores the last current and next link layer tx/rx state.
|
||||
L2_NODE_STATE mainState; ///< the main state of link layer state
|
||||
L2_NODE_STATE nextState; ///< next state of link layer state, which will be applied to mainState every second.
|
||||
L2_RTNE_CONFIG rtneConfig; ///< current routine table configuration and status.
|
||||
L2_SCAN_FSM *scanFSM; ///< FSM of scan net (link set up)
|
||||
L2_SVC_FSM *serviceFSM; ///< FSM of service net (data service)
|
||||
uint8_t *sendPktData; ///< send data buffer
|
||||
uint8_t *recvPktData; ///< received data buffer
|
||||
L2_LOG log; ///< Linklayer operating log
|
||||
// for system log
|
||||
SYSINFO sysInfo; ///< system info
|
||||
LINKLOG linkLog; ///< linklayer log for system monitor
|
||||
} L2_INST;
|
||||
|
||||
/************************** Variable Definitions *****************************/
|
||||
extern L2_RTNE_TABLE_ENTRY *initTable[L2_INIT_RTNE_PERIOD];
|
||||
extern L2_RTNE_TABLE_ENTRY *normalTable[L2_NORMAL_RTNE_PERIOD];
|
||||
/************************** Function Prototypes ******************************/
|
||||
/**
|
||||
* @defgroup LinkLayer_Main
|
||||
* @{
|
||||
*/
|
||||
int32_t Linklayer_Init(L2_INST **instPtr, const L2_CONFIG *config);
|
||||
int32_t Linklayer_Reconfig(L2_INST *instPtr, const L2_CONFIG *config);
|
||||
void Linklayer_Destroy(L2_INST *instPtr);
|
||||
int32_t Linklayer_Start(L2_INST *instPtr);
|
||||
int32_t Linklayer_Halt(L2_INST *instPtr);
|
||||
int32_t Linklayer_Proc(L2_INST *instPtr);
|
||||
int32_t Linklayer_EventHandler(L2_INST *instPtr, const L2_EVENT *l2Event);
|
||||
int32_t Linklayer_PktHandler(L2_INST *instPtr, L2_FRAME_TYPE frameType);
|
||||
int32_t L2_SteerBeam2Node(L2_INST *instPtr, uint8_t nodeId);
|
||||
int32_t L2_SetupNextSlot(L2_INST *instPtr, L2_TOR_TYPE txrxMode, L2_FRAME_TYPE frameType);
|
||||
/** @} LinkLayer_Main*/
|
||||
|
||||
/**
|
||||
* @defgroup LinkLayer_Framing
|
||||
* @{
|
||||
*/
|
||||
void L2_FrameInsertChunk(uint8_t *frame, size_t offset, size_t bytes, const void *chunk);
|
||||
void L2_FrameGetChunk(uint8_t *frame, size_t offset, size_t bytes, void *chunk);
|
||||
int32_t L2_CrcAppend(uint8_t *dataBuff, uint32_t dataLen, uint32_t crcPos, L2_CRC_TYPE crcType);
|
||||
bool L2_CrcCheck(uint8_t *dataBuff, uint32_t dataLen, L2_CRC_TYPE crcType);
|
||||
/** @} LinkLayer_Framing*/
|
||||
|
||||
/**
|
||||
* @defgroup LinkLayer_Scheduler
|
||||
* @{
|
||||
*/
|
||||
void L2_EventPoolHandler(L2_INST *instPtr);
|
||||
int32_t L2_ScheduleEventAt(L2_INST *instPtr, L2_SCHD_EVENT *schdEvent, uint32_t frameNo, uint32_t slotNo);
|
||||
int32_t L2_ScheduleEventAfter(L2_INST *instPtr, L2_SCHD_EVENT *schdEvent, uint32_t numSlots);
|
||||
int32_t L2_RescheduleEventAt(L2_INST *instPtr, L2_SCHD_EVENT *schdEvent, uint32_t frameNo, uint32_t slotNo);
|
||||
int32_t L2_RescheduleEventAfter(L2_INST *instPtr, L2_SCHD_EVENT *schdEvent, uint32_t numSlots);
|
||||
/** @} LinkLayer_Scheduler*/
|
||||
|
||||
/**
|
||||
* @defgroup LinkLayer_Scan
|
||||
* @{
|
||||
*/
|
||||
int32_t L2_Scan_Init(L2_SCAN_FSM **scanFSMPtr);
|
||||
void L2_Scan_RefreashScanTable(L2_INST *instPtr);
|
||||
void L2_Scan_Reset(L2_SCAN_FSM *scanFSMPtr);
|
||||
void L2_Scan_Destroy(L2_SCAN_FSM *scanFSMPtr);
|
||||
int32_t L2_Scan_Proc(L2_INST *instPtr);
|
||||
int32_t L2_Scan_PktHandler(L2_INST *instPtr, uint8_t *msg);
|
||||
int32_t L2_Scan_Routine(L2_INST *instPtr, const L2_RTNE_TABLE_ENTRY *schedEntry);
|
||||
/** @} LinkLayer_Scan*/
|
||||
|
||||
/**
|
||||
* @defgroup LinkLayer_Service
|
||||
* @{
|
||||
*/
|
||||
int32_t L2_Service_Init(L2_SVC_FSM **svcFSMPtr);
|
||||
void L2_Service_Reset(L2_SVC_FSM *svcFSMPtr);
|
||||
void L2_Service_Destroy(L2_SVC_FSM *svcFSMPtr);
|
||||
int32_t L2_Service_PktHandler(L2_INST *instPtr, uint8_t *msg);
|
||||
int32_t L2_Service_Proc(L2_INST *instPtr);
|
||||
int32_t L2_Service_Routine(L2_INST *instPtr, const L2_RTNE_TABLE_ENTRY *schedEntry);
|
||||
/** @} LinkLayer_Service*/
|
||||
|
||||
/**
|
||||
* @defgroup LinkLayer_TimeSync
|
||||
* @{
|
||||
*/
|
||||
int32_t L2_GetTimeDeviation(L2_INST *instPtr, uint32_t frameNum, uint32_t slotNum, bool relative, int64_t *timeDev);
|
||||
void L2_TimeAdjust(L2_INST *instPtr, const int64_t *timeDev);
|
||||
/** @} LinkLayer_TimeSync*/
|
||||
|
||||
/**
|
||||
* @defgroup LinkLayer_Utility
|
||||
* @{
|
||||
*/
|
||||
uint8_t L2_GetNodeId(L2_INST *instPtr);
|
||||
uint8_t L2_GetClusterId(L2_INST *instPtr);
|
||||
uint8_t L2_GetHeadId(L2_INST *instPtr);
|
||||
uint8_t L2_GetNetScale(L2_INST *instPtr);
|
||||
L2_NODE_TYPE L2_GetNodeType(L2_INST *instPtr);
|
||||
L2_NODE_STATE L2_GetMainState(L2_INST *instPtr);
|
||||
bool L2_isStarted(L2_INST *instPtr);
|
||||
bool L2_isDataAvail(L2_INST *instPtr);
|
||||
bool L2_isCxn2Net(L2_INST *instPtr);
|
||||
uint32_t L2_GetFrameLen(L2_FRAME_TYPE l2FrameType);
|
||||
uint32_t L2_GetLastFrameNum(L2_INST *instPtr);
|
||||
uint32_t L2_GetLastSlotNum(L2_INST *instPtr);
|
||||
L2_FRAME_TYPE L2_GetLastFrameType(L2_INST *instPtr);
|
||||
L2_TOR_TYPE L2_GetLastTor(L2_INST *instPtr);
|
||||
uint32_t L2_GetCurrentFrameNum(L2_INST *instPtr);
|
||||
uint32_t L2_GetCurrentSlotNum(L2_INST *instPtr);
|
||||
L2_FRAME_TYPE L2_GetCurrentFrameType(L2_INST *instPtr);
|
||||
L2_TOR_TYPE L2_GetCurrentTor(L2_INST *instPtr);
|
||||
uint32_t L2_GetNextFrameNum(L2_INST *instPtr);
|
||||
uint32_t L2_GetNextSlotNum(L2_INST *instPtr);
|
||||
L2_FRAME_TYPE L2_GetNextFrameType(L2_INST *instPtr);
|
||||
L2_TOR_TYPE L2_GetNextTor(L2_INST *instPtr);
|
||||
L2_FRAME_TYPE L2_GetLastOptFrameType(L2_INST *instPtr);
|
||||
L1_FRAME_TYPE L2_L2frame2L1frame(L2_FRAME_TYPE l2Frame);
|
||||
/** @} LinkLayer_Utility*/
|
||||
|
||||
#endif /* __LINK_LAYER_H_ */
|
||||
|
||||
/** @} LinkLayer*/
|
||||
@@ -0,0 +1,262 @@
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @file link_layer_types.h
|
||||
* @author FanHao ([email protected])
|
||||
* @brief DF Linklayer types definition.
|
||||
* @version 0.1
|
||||
* @date 2023-05-06
|
||||
*
|
||||
* @copyright Copyright(c) 2024 Beijing Institute of Technology.\n
|
||||
* Lab of Communication and Network
|
||||
*
|
||||
******************************************************************************/
|
||||
/**
|
||||
* @defgroup LinkLayer
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef __LINK_LAYER_DEF_H_
|
||||
#define __LINK_LAYER_DEF_H_
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "geometry/coord.h"
|
||||
#include "geometry/quaternion.h"
|
||||
#include "../phy_layer/phy_layer.h"
|
||||
#ifndef EMULATION
|
||||
#include "../config/app_config.h"
|
||||
#endif
|
||||
/************************** Constant Definitions *****************************/
|
||||
/**
|
||||
* @name Linklayer_Common_Constants
|
||||
* @{
|
||||
*/
|
||||
// Common node ID definition
|
||||
#define L2_BROADCAST_ID 0xFF
|
||||
#define L2_NONE_ID 0
|
||||
|
||||
// Routine configure
|
||||
#define L2_INIT_RTNE_PERIOD 1
|
||||
#define L2_NORMAL_RTNE_PERIOD 1
|
||||
|
||||
// Common slot number definition
|
||||
#define L2_SLOTNO_NONE 0
|
||||
#define L2_FRAMENO_NONE 0
|
||||
|
||||
// Common number of slots definition
|
||||
#define L2_SLOTS_PER_FRAME 100
|
||||
#define L2_SLOTS_PER_SUBFRAME 20
|
||||
|
||||
#define L2_NUM_SLOTS_NONE UINT32_MAX
|
||||
#define L2_NUM_SLOTS_100MS 20
|
||||
#define L2_NUM_SLOTS_20MS 4
|
||||
#define L2_NUM_SLOTS_10MS 2
|
||||
#define L2_NUM_SLOTS_5MS 1
|
||||
#define L2_NUM_SLOTS_SKIP 0
|
||||
/** @} Linklayer_Common_Constants*/
|
||||
|
||||
/**************************** Type Definitions *******************************/
|
||||
|
||||
/**
|
||||
* @struct L2_RCD
|
||||
* @brief Linklayer recode buffer
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t last;
|
||||
uint32_t curr;
|
||||
uint32_t next;
|
||||
} L2_RCD;
|
||||
|
||||
/**
|
||||
* @enum L2_TOR_TYPE
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
L2_TOR_SUSPEND = 0,
|
||||
L2_TOR_TX = 1,
|
||||
L2_TOR_RX = 2
|
||||
} L2_TOR_TYPE;
|
||||
|
||||
/**
|
||||
* @enum L2_NODE_TYPE
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
L2_NODE_NONE = 0,
|
||||
L2_NODE_HEAD = 1,
|
||||
L2_NODE_MEMBER = 2,
|
||||
L2_NODE_BACKUP = 3
|
||||
} L2_NODE_TYPE;
|
||||
|
||||
/**
|
||||
* @enum L2_NODE_STATE
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
L2_NONE_STATE = 0,
|
||||
L2_INIT_STATE = 1,
|
||||
L2_NORMAL_STATE = 2,
|
||||
L2_INTRA_SEEK_STATE = 3,
|
||||
L2_INTER_SEEK_STATE = 4,
|
||||
L2_SEEK_STATE = 5
|
||||
} L2_NODE_STATE;
|
||||
|
||||
/**
|
||||
* @struct L2_NODE_INFO
|
||||
* @brief Node information struct contains the detail node info which needed by the link layer.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t nodeId; ///< node ID
|
||||
uint8_t clustId; ///< node cluster ID
|
||||
uint8_t headId; ///< cluster head ID
|
||||
L2_NODE_TYPE nodeType; ///< node type
|
||||
uint8_t beamNo; ///< beam number to this node
|
||||
COORD pos; ///< node position
|
||||
COORD speed; ///< node speed
|
||||
QUATERNION attitude; ///< node attitude
|
||||
} L2_NODE_INFO;
|
||||
|
||||
/**
|
||||
* @enum L2_EVENT_TYPE
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
L2_EV_NONE = 0,
|
||||
L2_EV_SCAN_PROC_DONE = 1,
|
||||
L2_EV_NET_ADV_UPDATE = 2,
|
||||
L2_EV_NET_SETUP_DONE = 3,
|
||||
L2_EV_TIME_SYNC = 4,
|
||||
L2_EV_LOST_CXN = 5,
|
||||
L2_EV_LOST_NODE = 6,
|
||||
L2_EV_SET_FRAME_NUM = 7,
|
||||
L2_EV_SET_SLOT_NUM = 8,
|
||||
L2_EV_MAIN_STATE_UPDATE = 9,
|
||||
L2_ROUTINE_FINISH = 10,
|
||||
L2_ROUTINE_UPDATE = 11
|
||||
} L2_EVENT_TYPE;
|
||||
|
||||
/**
|
||||
* @struct L2_EVENT
|
||||
* @brief Linklayer event instance
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
L2_EVENT_TYPE event; ///< event type
|
||||
void *msg; ///< event message
|
||||
} L2_EVENT;
|
||||
|
||||
/**
|
||||
* @enum L2_SLOT_TYPE
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
L2_SLOT_NONE = 0,
|
||||
L2_SLOT_IDLE = 1,
|
||||
L2_SLOT_SCAN = 2,
|
||||
L2_SLOT_ADVERTISE = 3,
|
||||
L2_SLOT_CONFIRM = 4,
|
||||
L2_SLOT_SERVICE = 5,
|
||||
} L2_SLOT_TYPE;
|
||||
|
||||
/**
|
||||
* @enum L2_FRAME_TYPE
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
L2_NONE_FRAME = 0,
|
||||
L2_SCAN_FRAME = 1,
|
||||
L2_ADV_FRAME = 2,
|
||||
L2_CFM_FRAME = 3,
|
||||
L2_SVC_FRAME = 4
|
||||
} L2_FRAME_TYPE;
|
||||
|
||||
/**
|
||||
* @enum L2_CRC_TYPE
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
L2_CRC_NONE = 0,
|
||||
L2_CRC16_1021 = 1,
|
||||
L2_CRC16_8005 = 2,
|
||||
L2_CRC8_31 = 3
|
||||
} L2_CRC_TYPE;
|
||||
|
||||
/**
|
||||
* @struct L2_RTNE_TABLE_ENTRY
|
||||
* @brief Linklayer routine table entry
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
L2_SLOT_TYPE slotType : 8; ///< slot type
|
||||
uint8_t slotSeq; ///< slot sequence number
|
||||
uint8_t src; ///< source node ID
|
||||
uint8_t dst; ///< destination node ID
|
||||
} L2_RTNE_TABLE_ENTRY;
|
||||
|
||||
/**
|
||||
* @enum SCAN_STAGE
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
L2_SCAN_NONE_STAGE = 0,
|
||||
L2_SCAN_INIT_STAGE = 1,
|
||||
L2_SCAN_ADV_STAGE = 2,
|
||||
L2_SCAN_CFM_STAGE = 3
|
||||
} SCAN_STAGE;
|
||||
|
||||
/**
|
||||
* @struct L2_SCAN_FSM
|
||||
* @brief Linklayer scan process FSM instance
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
bool isLocked; ///< indicates if init acq done(beam locked).
|
||||
bool isAdvRecvd; ///< indicates if advertisement frame done(beam locked).
|
||||
bool isAckPending; ///< indicates if confirm message acked
|
||||
uint8_t scanCnt; ///< scan count
|
||||
uint8_t advTimeout; ///< adv receive try count
|
||||
uint8_t cfmTimeout; ///< cmf receive try count
|
||||
SCAN_STAGE scanStage; ///< scan stage \n
|
||||
/// only for member node
|
||||
uint8_t beamNo; ///< locked beam number
|
||||
uint8_t tableNo; ///< scan table index
|
||||
} L2_SCAN_FSM;
|
||||
|
||||
/**
|
||||
* @struct L2_SVC_FSM
|
||||
* @brief Linklayer service process FSM
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t txCnt; ///< tx frame count
|
||||
uint32_t rxCnt; ///< rx frame count
|
||||
uint32_t rxdCnt; ///< received frame count
|
||||
#ifdef DATALINK_ENABLE_BERTEST
|
||||
uint32_t bitTotal; ///< received bits count
|
||||
uint32_t bitError; ///< error bits count
|
||||
double lossRate; ///< packet loss rate
|
||||
double errorRate; ///< bit error rate
|
||||
#endif
|
||||
} L2_SVC_FSM;
|
||||
|
||||
/**
|
||||
* @struct L2_RTNE_CONFIG
|
||||
* @brief Linklayer routine table configuration
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
L2_RTNE_TABLE_ENTRY **rtneTable; ///< routine table
|
||||
uint32_t rtnePrd; ///< period of routine table
|
||||
L2_RTNE_TABLE_ENTRY *last; ///< last routine entry
|
||||
L2_RTNE_TABLE_ENTRY *curr; ///< curent routine entry
|
||||
L2_RTNE_TABLE_ENTRY *next; ///< next routine entry
|
||||
} L2_RTNE_CONFIG;
|
||||
|
||||
/************************** Variable Definitions *****************************/
|
||||
|
||||
#endif /* __LINK_LAYER_DEF_H_ */
|
||||
|
||||
/** @} LinkLayer*/
|
||||
@@ -0,0 +1,130 @@
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @file msg_def.c
|
||||
* @author FanHao ([email protected])
|
||||
* @brief DF Linklayer message definition constants.
|
||||
* @version 0.0
|
||||
* @date 2023-05-06
|
||||
*
|
||||
* @copyright Copyright(c) 2024 Beijing Institute of Technology.\n
|
||||
* Lab of Communication and Network
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* @addtogroup LinkLayer
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @name LinkLayer_MSG_Constants
|
||||
* @{
|
||||
*/
|
||||
#ifndef __L2_MSG_DEF_H_
|
||||
#define __L2_MSG_DEF_H_
|
||||
|
||||
#define L2_PACK_LEN_MAX 512 // bytes
|
||||
|
||||
#define L2_ADV_PACK_LEN 28 // bytes
|
||||
#define L2_CMF_PACK_LEN 268 // bytes
|
||||
#define L2_SVC_PACK_LEN 268 // bytes
|
||||
|
||||
// Common structure:
|
||||
// [bytes] [name]
|
||||
// 4 fame number
|
||||
// 1 slot number
|
||||
// 1 source id
|
||||
// 1 destination id
|
||||
// 1 message type
|
||||
#define L2_MSG_FRAME_NUM 0
|
||||
#define L2_MSG_FRAME_NUM_LEN 4
|
||||
#define L2_MSG_SLOT_NUM 4
|
||||
#define L2_MSG_SLOT_NUM_LEN 1
|
||||
#define L2_MSG_SRC_ID 5
|
||||
#define L2_MSG_SRC_ID_LEN 1
|
||||
#define L2_MSG_DST_ID 6
|
||||
#define L2_MSG_DST_ID_LEN 1
|
||||
#define L2_MSG_TYPE 7
|
||||
#define L2_MSG_TYPE_LEN 1
|
||||
#define L2_MSG_PAYLOAD 8
|
||||
|
||||
// advertisement payload structure:
|
||||
// [bytes] [name]
|
||||
// 4 position x
|
||||
// 4 position y
|
||||
// 4 position z
|
||||
// 4 net start time
|
||||
// 2 crc
|
||||
#define L2_MSG_ADV_SRC_POSX 8
|
||||
#define L2_MSG_ADV_SRC_POSX_LEN 4
|
||||
#define L2_MSG_ADV_SRC_POSY 12
|
||||
#define L2_MSG_ADV_SRC_POSY_LEN 4
|
||||
#define L2_MSG_ADV_SRC_POSZ 16
|
||||
#define L2_MSG_ADV_SRC_POSZ_LEN 4
|
||||
#define L2_MSG_ADV_SRC_NETSTART_TIME 20
|
||||
#define L2_MSG_ADV_SRC_NETSTART_TIME_LEN 4
|
||||
#define L2_MSG_ADV_SVC_CRC 26
|
||||
#define L2_MSG_ADV_SVC_CRC_LEN 2
|
||||
|
||||
// confirm payload structure:
|
||||
// [bytes] [name]
|
||||
// 4 position x
|
||||
// 4 position y
|
||||
// 4 position z
|
||||
// 4 speed x
|
||||
// 4 speed y
|
||||
// 4 speed z
|
||||
// 2 crc
|
||||
#define L2_MSG_CFM_SRC_POSX 8
|
||||
#define L2_MSG_CFM_SRC_POSX_LEN 4
|
||||
#define L2_MSG_CFM_SRC_POSY 12
|
||||
#define L2_MSG_CFM_SRC_POSY_LEN 4
|
||||
#define L2_MSG_CFM_SRC_POSZ 16
|
||||
#define L2_MSG_CFM_SRC_POSZ_LEN 4
|
||||
#define L2_MSG_CFM_SRC_SPEEDX 20
|
||||
#define L2_MSG_CFM_SRC_SPEEDX_LEN 4
|
||||
#define L2_MSG_CFM_SRC_SPEEDY 24
|
||||
#define L2_MSG_CFM_SRC_SPEEDY_LEN 4
|
||||
#define L2_MSG_CFM_SRC_SPEEDZ 28
|
||||
#define L2_MSG_CFM_SRC_SPEEDZ_LEN 4
|
||||
#define L2_MSG_CFM_PAYLOAD_ID 32
|
||||
#define L2_MSG_CFM_PAYLOAD_ID_LEN 4
|
||||
#define L2_MSG_CFM_PAYLOAD 36
|
||||
#define L2_MSG_CFM_PAYLOAD_LEN 230
|
||||
#define L2_MSG_CFM_CRC 266
|
||||
#define L2_MSG_CFM_CRC_LEN 2
|
||||
|
||||
// service payload structure:
|
||||
// [bytes] [name]
|
||||
// 4 position x
|
||||
// 4 position y
|
||||
// 4 position z
|
||||
// 4 speed x
|
||||
// 4 speed y
|
||||
// 4 speed z
|
||||
// 234 payload
|
||||
// 2 crc
|
||||
#define L2_MSG_SVC_SRC_POSX 8
|
||||
#define L2_MSG_SVC_SRC_POSX_LEN 4
|
||||
#define L2_MSG_SVC_SRC_POSY 12
|
||||
#define L2_MSG_SVC_SRC_POSY_LEN 4
|
||||
#define L2_MSG_SVC_SRC_POSZ 16
|
||||
#define L2_MSG_SVC_SRC_POSZ_LEN 4
|
||||
#define L2_MSG_SVC_SRC_SPEEDX 20
|
||||
#define L2_MSG_SVC_SRC_SPEEDX_LEN 4
|
||||
#define L2_MSG_SVC_SRC_SPEEDY 24
|
||||
#define L2_MSG_SVC_SRC_SPEEDY_LEN 4
|
||||
#define L2_MSG_SVC_SRC_SPEEDZ 28
|
||||
#define L2_MSG_SVC_SRC_SPEEDZ_LEN 4
|
||||
#define L2_MSG_SVC_PAYLOAD_ID 32
|
||||
#define L2_MSG_SVC_PAYLOAD_ID_LEN 4
|
||||
#define L2_MSG_SVC_PAYLOAD 36
|
||||
#define L2_MSG_SVC_PAYLOAD_LEN 230
|
||||
#define L2_MSG_SVC_CRC 266
|
||||
#define L2_MSG_SVC_CRC_LEN 2
|
||||
|
||||
#endif //__L2_MSG_DEF_H_
|
||||
|
||||
/** @} LinkLayer_MSG_Constants*/
|
||||
|
||||
/** @} LinkLayer*/
|
||||
@@ -0,0 +1,561 @@
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @file node_list.c
|
||||
* @author FanHao ([email protected])
|
||||
* @brief DF Linklayer node list implementation file
|
||||
* @version 0.0
|
||||
* @date 2023-05-06
|
||||
*
|
||||
* @copyright Copyright(c) 2024 Beijing Institute of Technology.\n
|
||||
* Lab of Communication and Network
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* @addtogroup LinkLayer
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup LinkLayer_NodeList
|
||||
* @{
|
||||
*/
|
||||
/***************************** Include Files *********************************/
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "link_layer_types.h"
|
||||
#include "node_list.h"
|
||||
#include "clist.h"
|
||||
#include "common.h"
|
||||
#include "error.h"
|
||||
|
||||
/***************** Macros (Inline Functions) Definitions *********************/
|
||||
/**
|
||||
* @brief Get the node list length
|
||||
* @param list pointer to node list
|
||||
*/
|
||||
inline uint32_t L2_GetNodeListLen(NODE_LIST *list)
|
||||
{
|
||||
ASSERT(list != NULL);
|
||||
return list->len;
|
||||
}
|
||||
/**************************** Type Definitions *******************************/
|
||||
|
||||
/************************** Variable Definitions *****************************/
|
||||
static NODE_ENTRY util_entry;
|
||||
/************************** Function Prototypes ******************************/
|
||||
/**
|
||||
* @brief helper function to free node entry.
|
||||
*/
|
||||
static void entry_free(void *val)
|
||||
{
|
||||
free(val);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief helper function to match node entries by nodeIds
|
||||
*/
|
||||
static int8_t entry_compare(void *a, void *b)
|
||||
{
|
||||
ASSERT(a != NULL);
|
||||
ASSERT(b != NULL);
|
||||
register uint8_t idA, idB;
|
||||
idA = ((NODE_ENTRY *)a)->nodeInfo.nodeId;
|
||||
idB = ((NODE_ENTRY *)b)->nodeInfo.nodeId;
|
||||
if (idA == idB)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (idA < idB)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Initialize node list
|
||||
*
|
||||
* @param list
|
||||
*
|
||||
* @return SUCCESS
|
||||
* ENOMEM - not enough memory.
|
||||
*
|
||||
******************************************************************************/
|
||||
int32_t L2_NodeList_Init(NODE_LIST **list)
|
||||
{
|
||||
(*list) = clist_new();
|
||||
if (*list == NULL)
|
||||
{
|
||||
return ENOMEM;
|
||||
}
|
||||
(*list)->free = entry_free;
|
||||
(*list)->compare = entry_compare;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Clear all nodes in the node list, free allocated memory.
|
||||
*
|
||||
* @param list
|
||||
* @return NONE
|
||||
*
|
||||
******************************************************************************/
|
||||
void L2_NodeList_Clear(NODE_LIST *list)
|
||||
{
|
||||
ASSERT(list != NULL);
|
||||
clist_clear(list);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Completely destroy node list.
|
||||
*
|
||||
* @param list
|
||||
*
|
||||
* @return NONE
|
||||
*
|
||||
******************************************************************************/
|
||||
void L2_NodeList_Destroy(NODE_LIST *list)
|
||||
{
|
||||
clist_destroy(list);
|
||||
}
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Get node entry from node list base on node id.
|
||||
*
|
||||
* @param list
|
||||
* @param nodeId
|
||||
*
|
||||
* @return Node entry \n
|
||||
* NULL if node dose not exist.
|
||||
*
|
||||
******************************************************************************/
|
||||
NODE_ENTRY *L2_GetNodeById(NODE_LIST *list, uint8_t nodeId)
|
||||
{
|
||||
ASSERT(list != NULL);
|
||||
if (nodeId == L2_BROADCAST_ID || nodeId == L2_NONE_ID)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
util_entry.nodeInfo.nodeId = nodeId;
|
||||
clist_node_t *node = clist_find(list, &util_entry);
|
||||
if (node == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ((NODE_ENTRY *)node->val);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Append a new node entry to the node list
|
||||
*
|
||||
* @param list
|
||||
* @param nodeId
|
||||
* @param nodeType
|
||||
*
|
||||
* @return SUCCESS Node was added successfully.\n
|
||||
* Other Error occurred.(Node already exist, memory alloc error ect.)
|
||||
*
|
||||
******************************************************************************/
|
||||
NODE_ENTRY *L2_AppendNode(NODE_LIST *list, uint8_t nodeId, L2_NODE_TYPE nodeType)
|
||||
{
|
||||
ASSERT(list != NULL);
|
||||
if (L2_isNodeInList(list, nodeId))
|
||||
{
|
||||
DBG_WARNING("Node [%" PRIu8 "] already exist.\n", nodeId);
|
||||
return NULL;
|
||||
}
|
||||
DBG_INFO("Link layer appending node [%" PRIu8 "] to node list.\n", nodeId);
|
||||
NODE_ENTRY *nodeEntry = (NODE_ENTRY *)malloc(sizeof(NODE_ENTRY));
|
||||
if (nodeEntry == NULL)
|
||||
{
|
||||
DBG_ERROR("Failed to allocated memory for nodeEntry.\n");
|
||||
return NULL;
|
||||
}
|
||||
clist_node_t *node = clist_node_new(nodeEntry);
|
||||
if (node == NULL)
|
||||
{
|
||||
DBG_ERROR("Failed to allocated memory for list node.\n");
|
||||
free(nodeEntry);
|
||||
return NULL;
|
||||
}
|
||||
nodeEntry->nodeInfo.nodeId = nodeId;
|
||||
nodeEntry->nodeInfo.nodeType = (uint8_t)nodeType;
|
||||
nodeEntry->nodeInfo.pos.x = 0;
|
||||
nodeEntry->nodeInfo.pos.y = 0;
|
||||
nodeEntry->nodeInfo.pos.z = 0;
|
||||
nodeEntry->nodeInfo.speed.x = 0;
|
||||
nodeEntry->nodeInfo.speed.y = 0;
|
||||
nodeEntry->nodeInfo.speed.z = 0;
|
||||
nodeEntry->nodeInfo.beamNo = 0;
|
||||
nodeEntry->ttlCnt = 0;
|
||||
clist_rpush(list, node);
|
||||
return nodeEntry;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Delete a node in list based on node id.
|
||||
*
|
||||
* @param list
|
||||
* @param nodeId
|
||||
*
|
||||
* @return SUCCESS Node has been successfully deleted.\n
|
||||
* Other Node not exist.
|
||||
*
|
||||
******************************************************************************/
|
||||
int32_t L2_DeleteNodeById(NODE_LIST *list, uint8_t nodeId)
|
||||
{
|
||||
ASSERT(list != NULL);
|
||||
util_entry.nodeInfo.nodeId = nodeId;
|
||||
clist_node_t *node = clist_find(list, &util_entry);
|
||||
if (node == NULL)
|
||||
{
|
||||
DBG_WARNING("Node [%" PRIu8 "] in not in node list, skip deleting process.\n", nodeId);
|
||||
return SUCCESS;
|
||||
}
|
||||
DBG_INFO("Deleting node [%" PRIu8 "].\n", nodeId);
|
||||
clist_remove(list, node);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Check whether the node is already in the node list.
|
||||
*
|
||||
* @param list
|
||||
* @param nodeId
|
||||
*
|
||||
* @return true node in the list\n
|
||||
* false node not in the list
|
||||
*
|
||||
******************************************************************************/
|
||||
bool L2_isNodeInList(NODE_LIST *list, uint8_t nodeId)
|
||||
{
|
||||
ASSERT(list != NULL);
|
||||
return (L2_GetNodeById(list, nodeId) != NULL);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Get the distance between me and the node.
|
||||
*
|
||||
* @param list
|
||||
* @param nodeId
|
||||
* @param dst A pointer to store distance.
|
||||
*
|
||||
* @return SUCCESS distance has been successfully store in dst\n
|
||||
* FAILURE Node dose not exit.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
int32_t L2_GetDistance(NODE_LIST *list, COORD myCoord, uint8_t nodeId, double *dst)
|
||||
{
|
||||
ASSERT(list != NULL);
|
||||
NODE_ENTRY *nodeEntry = L2_GetNodeById(list, nodeId);
|
||||
if (nodeEntry == NULL)
|
||||
{
|
||||
return FAILURE;
|
||||
}
|
||||
else
|
||||
{
|
||||
*dst = Coord_Distance(myCoord, nodeEntry->nodeInfo.pos);
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Update node positions information.
|
||||
*
|
||||
* @param list
|
||||
* @param nodeId
|
||||
* @param newPos A structure stores the corresponding node position info.
|
||||
*
|
||||
* @return SUCCESS update successfully.\n
|
||||
* FAILURE node not exist.
|
||||
*
|
||||
******************************************************************************/
|
||||
int32_t L2_UpdateNodePos(NODE_LIST *list, uint8_t nodeId, const COORD *newPos)
|
||||
{
|
||||
ASSERT(list != NULL);
|
||||
NODE_ENTRY *nodeEntry = L2_GetNodeById(list, nodeId);
|
||||
if (nodeEntry == NULL)
|
||||
{
|
||||
return FAILURE;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(&(nodeEntry->nodeInfo.pos), newPos, sizeof(COORD));
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Get node positions information.
|
||||
*
|
||||
* @param list
|
||||
* @param nodeId
|
||||
* @param newPos A structure stores the corresponding node position info.
|
||||
*
|
||||
* @return SUCCESS update successfully.\n
|
||||
* FAILURE node not exist.
|
||||
*
|
||||
******************************************************************************/
|
||||
int32_t L2_GetNodePos(NODE_LIST *list, uint8_t nodeId, COORD *pos)
|
||||
{
|
||||
ASSERT(list != NULL);
|
||||
NODE_ENTRY *nodeEntry = L2_GetNodeById(list, nodeId);
|
||||
if (nodeEntry == NULL)
|
||||
{
|
||||
return FAILURE;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(pos, &(nodeEntry->nodeInfo.pos), sizeof(COORD));
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Update node speed information.
|
||||
*
|
||||
* @param list
|
||||
* @param nodeId
|
||||
* @param newSpeed A structure stores the corresponding node speed info.
|
||||
*
|
||||
* @return SUCCESS update successfully.\n
|
||||
* FAILURE node not exist.
|
||||
*
|
||||
******************************************************************************/
|
||||
int32_t L2_UpdateNodeSpeed(NODE_LIST *list, uint8_t nodeId, const COORD *newSpeed)
|
||||
{
|
||||
ASSERT(list != NULL);
|
||||
NODE_ENTRY *nodeEntry = L2_GetNodeById(list, nodeId);
|
||||
if (nodeEntry == NULL)
|
||||
{
|
||||
return FAILURE;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(&(nodeEntry->nodeInfo.speed), newSpeed, sizeof(COORD));
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Get node speed information.
|
||||
*
|
||||
* @param list
|
||||
* @param nodeId
|
||||
* @param newSpeed A structure stores the corresponding node speed info.
|
||||
*
|
||||
* @return SUCCESS update successfully.\n
|
||||
* FAILURE node not exist.
|
||||
*
|
||||
******************************************************************************/
|
||||
int32_t L2_GetNodeSpeed(NODE_LIST *list, uint8_t nodeId, COORD *speed)
|
||||
{
|
||||
ASSERT(list != NULL);
|
||||
NODE_ENTRY *nodeEntry = L2_GetNodeById(list, nodeId);
|
||||
if (nodeEntry == NULL)
|
||||
{
|
||||
return FAILURE;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(speed, &(nodeEntry->nodeInfo.speed), sizeof(COORD));
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Update node ACK status.
|
||||
*
|
||||
* @param list
|
||||
* @param nodeId
|
||||
* @param devi
|
||||
*
|
||||
* @return SUCCESS update successfully.\n
|
||||
* FAILURE Node not exist.
|
||||
*
|
||||
******************************************************************************/
|
||||
int32_t L2_UpdateNodeTimeDeviation(NODE_LIST *list, uint8_t nodeId, int32_t devi)
|
||||
{
|
||||
ASSERT(list != NULL);
|
||||
NODE_ENTRY *nodeEntry = L2_GetNodeById(list, nodeId);
|
||||
if (nodeEntry == NULL)
|
||||
{
|
||||
return FAILURE;
|
||||
}
|
||||
else
|
||||
{
|
||||
nodeEntry->timeDevi = devi;
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Increase TTL of specified node in the list.
|
||||
*
|
||||
* @param list
|
||||
* @param inc cnt of slot to add
|
||||
* @param nodeId
|
||||
*
|
||||
* @return NONE
|
||||
*
|
||||
******************************************************************************/
|
||||
int32_t L2_IncNodeTTL(NODE_LIST *list, uint8_t nodeId, uint32_t inc)
|
||||
{
|
||||
ASSERT(list != NULL);
|
||||
NODE_ENTRY *nodeEntry = L2_GetNodeById(list, nodeId);
|
||||
if (nodeEntry == NULL)
|
||||
{
|
||||
return FAILURE;
|
||||
}
|
||||
else
|
||||
{
|
||||
nodeEntry->ttlCnt += inc;
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Reset node TTL based on node id.
|
||||
*
|
||||
* @param list
|
||||
* @param nodeId
|
||||
*
|
||||
* @return SUCCESS TTL has been successfully cleared.\n
|
||||
* FAILURE Node not exist.
|
||||
*
|
||||
******************************************************************************/
|
||||
int32_t L2_RstNodeTTL(NODE_LIST *list, uint8_t nodeId)
|
||||
{
|
||||
ASSERT(list != NULL);
|
||||
NODE_ENTRY *nodeEntry = L2_GetNodeById(list, nodeId);
|
||||
if (nodeEntry == NULL)
|
||||
{
|
||||
return FAILURE;
|
||||
}
|
||||
else
|
||||
{
|
||||
nodeEntry->ttlCnt = 0;
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Get TTL of specified node in the list.
|
||||
*
|
||||
* @param list
|
||||
* @param nodeId
|
||||
* @param ttl
|
||||
*
|
||||
* @return NONE
|
||||
*
|
||||
******************************************************************************/
|
||||
int32_t L2_GetNodeTTL(NODE_LIST *list, uint8_t nodeId, uint32_t *ttl)
|
||||
{
|
||||
ASSERT(list != NULL);
|
||||
NODE_ENTRY *nodeEntry = L2_GetNodeById(list, nodeId);
|
||||
if (nodeEntry == NULL)
|
||||
{
|
||||
return FAILURE;
|
||||
}
|
||||
else
|
||||
{
|
||||
*ttl = nodeEntry->ttlCnt;
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Implements a edit operations to each node.
|
||||
*
|
||||
* @param list
|
||||
* @param param
|
||||
* @param operation A pointer to a function handled "NODE_ENTRY*" as input
|
||||
* which defines the operations need to be apply.
|
||||
*
|
||||
* @return SUCCESS Operations has been applied successfully to all nodes.\n
|
||||
* Other Error occurred.
|
||||
*
|
||||
******************************************************************************/
|
||||
int32_t L2_IterEditNode(NODE_LIST *list, const void *param, int32_t (*operation)(NODE_ENTRY *, const void *))
|
||||
{
|
||||
ASSERT(list != NULL);
|
||||
int32_t Status;
|
||||
clist_node_t *node;
|
||||
clist_iterator_t *iter = clist_iterator_new(list, LIST_HEAD);
|
||||
if (iter == NULL)
|
||||
{
|
||||
DBG_ERROR("Failed to initialize list iteration process.\n");
|
||||
return ENOMEM;
|
||||
}
|
||||
while ((node = clist_iterator_next(iter)))
|
||||
{
|
||||
Status = operation((NODE_ENTRY *)node->val, param);
|
||||
if (Status != SUCCESS)
|
||||
{
|
||||
DBG_ERROR("Error occurred when iteratively edit node entry.\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
clist_iterator_destroy(iter);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Filter all node, delete all the node not satisfied the condition.
|
||||
*
|
||||
* @param list
|
||||
* @param condition A pointer to a function handled "NODE_ENTRY*" as input
|
||||
* which defines the condition need to be verify.
|
||||
*
|
||||
* @return SUCCESS
|
||||
*
|
||||
******************************************************************************/
|
||||
int32_t L2_IterDeleteNode(NODE_LIST *list, bool (*condition)(NODE_ENTRY *))
|
||||
{
|
||||
ASSERT(list != NULL);
|
||||
clist_node_t *node;
|
||||
clist_iterator_t *iter = clist_iterator_new(list, LIST_HEAD);
|
||||
if (iter == NULL)
|
||||
{
|
||||
DBG_ERROR("Failed to initialize list iteration process.\n");
|
||||
return ENOMEM;
|
||||
}
|
||||
while ((node = clist_iterator_next(iter)))
|
||||
{
|
||||
if (condition((NODE_ENTRY *)node->val) == false)
|
||||
{
|
||||
clist_remove(list, node);
|
||||
}
|
||||
}
|
||||
clist_iterator_destroy(iter);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/** @} LinkLayer_NodeList*/
|
||||
|
||||
/** @} LinkLayer*/
|
||||
@@ -0,0 +1,79 @@
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @file node_list.h
|
||||
* @author FanHao ([email protected])
|
||||
* @brief DF Linklayer node list header file
|
||||
* @version 0.0
|
||||
* @date 2023-05-06
|
||||
*
|
||||
* @copyright Copyright(c) 2024 Beijing Institute of Technology.\n
|
||||
* Lab of Communication and Network
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* @addtogroup LinkLayer
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup LinkLayer_NodeList
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
#ifndef NODE_LIST_H_
|
||||
#define NODE_LIST_H_
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <stdbool.h>
|
||||
#include "link_layer_types.h"
|
||||
#include "geometry/coord.h"
|
||||
#include "util.h"
|
||||
#include "clist.h"
|
||||
|
||||
/************************** Constant Definitions *****************************/
|
||||
/***************** Macros (Inline Functions) Definitions *********************/
|
||||
/**************************** Type Definitions *******************************/
|
||||
/**
|
||||
* @struct NODE_ENTRY
|
||||
* @brief Linklayer discovered node list node entry
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
L2_NODE_INFO nodeInfo;
|
||||
uint32_t ttlCnt;
|
||||
int32_t timeDevi;
|
||||
} NODE_ENTRY;
|
||||
|
||||
typedef clist_t NODE_LIST;
|
||||
|
||||
/************************** Variable Definitions *****************************/
|
||||
|
||||
/************************** Function Prototypes ******************************/
|
||||
int32_t L2_NodeList_Init(NODE_LIST **list);
|
||||
void L2_NodeList_Clear(NODE_LIST *list);
|
||||
void L2_NodeList_Destroy(NODE_LIST *list);
|
||||
uint32_t L2_GetNodeListLen(NODE_LIST *list);
|
||||
NODE_ENTRY *L2_GetNodeById(NODE_LIST *list, uint8_t nodeId);
|
||||
NODE_ENTRY *L2_AppendNode(NODE_LIST *list, uint8_t nodeId, L2_NODE_TYPE nodeType);
|
||||
int32_t L2_DeleteNodeById(NODE_LIST *list, uint8_t nodeId);
|
||||
int32_t L2_UpdateNodePos(NODE_LIST *list, uint8_t nodeId, const COORD *newPos);
|
||||
bool L2_isNodeInList(NODE_LIST *list, uint8_t nodeId);
|
||||
int32_t L2_GetNodePos(NODE_LIST *list, uint8_t nodeId, COORD *newPos);
|
||||
int32_t L2_UpdateNodeSpeed(NODE_LIST *list, uint8_t nodeId, const COORD *newSpeed);
|
||||
int32_t L2_GetNodeSpeed(NODE_LIST *list, uint8_t nodeId, COORD *speed);
|
||||
int32_t L2_UpdateNodeTimeDeviation(NODE_LIST *list, uint8_t nodeId, int32_t devi);
|
||||
int32_t L2_GetDistance(NODE_LIST *list, COORD myCoord, uint8_t nodeId, double *dst);
|
||||
int32_t L2_RstNodeTTL(NODE_LIST *list, uint8_t nodeId);
|
||||
int32_t L2_IncNodeTTL(NODE_LIST *list, uint8_t nodeId, uint32_t inc);
|
||||
int32_t L2_GetNodeTTL(NODE_LIST *list, uint8_t nodeId, uint32_t *ttl);
|
||||
int32_t L2_IterEditNode(NODE_LIST *list, const void *param, int32_t (*operation)(NODE_ENTRY *, const void *));
|
||||
int32_t L2_IterDeleteNode(NODE_LIST *list, bool (*condition)(NODE_ENTRY *));
|
||||
|
||||
#endif /* NODE_LIST_H_ */
|
||||
|
||||
/** @} LinkLayer_NodeList*/
|
||||
/** @} LinkLayer*/
|
||||
@@ -0,0 +1,263 @@
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @file routine_table.c
|
||||
* @author FanHao ([email protected])
|
||||
* @brief DF Linklayer node list implementation file
|
||||
* @version 0.0
|
||||
* @date 2023-05-06
|
||||
*
|
||||
* @copyright Copyright(c) 2024 Beijing Institute of Technology.\n
|
||||
* Lab of Communication and Network
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* @addtogroup LinkLayer
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @name RoutineTable
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "link_layer.h"
|
||||
#include "link_layer_types.h"
|
||||
|
||||
L2_RTNE_TABLE_ENTRY intraScanSubT[L2_SLOTS_PER_FRAME] = {
|
||||
// SubFrame 0
|
||||
{L2_SLOT_SCAN, 0x00, 0x01, 0xFF},
|
||||
{L2_SLOT_SCAN, 0x01, 0x01, 0xFF},
|
||||
{L2_SLOT_SCAN, 0x00, 0x01, 0xFF},
|
||||
{L2_SLOT_SCAN, 0x01, 0x01, 0xFF},
|
||||
{L2_SLOT_SCAN, 0x00, 0x01, 0xFF},
|
||||
{L2_SLOT_SCAN, 0x01, 0x01, 0xFF},
|
||||
{L2_SLOT_SCAN, 0x00, 0x01, 0xFF},
|
||||
{L2_SLOT_SCAN, 0x01, 0x01, 0xFF},
|
||||
{L2_SLOT_SCAN, 0x00, 0x01, 0xFF},
|
||||
{L2_SLOT_SCAN, 0x01, 0x01, 0xFF},
|
||||
{L2_SLOT_SCAN, 0x00, 0x01, 0xFF},
|
||||
{L2_SLOT_SCAN, 0x01, 0x01, 0xFF},
|
||||
{L2_SLOT_SCAN, 0x00, 0x01, 0xFF},
|
||||
{L2_SLOT_SCAN, 0x01, 0x01, 0xFF},
|
||||
{L2_SLOT_SCAN, 0x00, 0x01, 0xFF},
|
||||
{L2_SLOT_SCAN, 0x01, 0x01, 0xFF},
|
||||
{L2_SLOT_SCAN, 0x00, 0x01, 0xFF},
|
||||
{L2_SLOT_SCAN, 0x01, 0x01, 0xFF},
|
||||
{L2_SLOT_SCAN, 0x00, 0x01, 0xFF},
|
||||
{L2_SLOT_SCAN, 0x01, 0x01, 0xFF},
|
||||
|
||||
// SubFrame 1
|
||||
{L2_SLOT_SCAN, 0x00, 0x01, 0xFF},
|
||||
{L2_SLOT_SCAN, 0x01, 0x01, 0xFF},
|
||||
{L2_SLOT_SCAN, 0x00, 0x01, 0xFF},
|
||||
{L2_SLOT_SCAN, 0x01, 0x01, 0xFF},
|
||||
{L2_SLOT_SCAN, 0x00, 0x01, 0xFF},
|
||||
{L2_SLOT_SCAN, 0x01, 0x01, 0xFF},
|
||||
{L2_SLOT_SCAN, 0x00, 0x01, 0xFF},
|
||||
{L2_SLOT_SCAN, 0x01, 0x01, 0xFF},
|
||||
{L2_SLOT_SCAN, 0x00, 0x01, 0xFF},
|
||||
{L2_SLOT_SCAN, 0x01, 0x01, 0xFF},
|
||||
{L2_SLOT_SCAN, 0x00, 0x01, 0xFF},
|
||||
{L2_SLOT_SCAN, 0x01, 0x01, 0xFF},
|
||||
{L2_SLOT_SCAN, 0x00, 0x01, 0xFF},
|
||||
{L2_SLOT_SCAN, 0x01, 0x01, 0xFF},
|
||||
{L2_SLOT_SCAN, 0x00, 0x01, 0xFF},
|
||||
{L2_SLOT_SCAN, 0x01, 0x01, 0xFF},
|
||||
{L2_SLOT_SCAN, 0x00, 0x01, 0xFF},
|
||||
{L2_SLOT_SCAN, 0x01, 0x01, 0xFF},
|
||||
{L2_SLOT_SCAN, 0x00, 0x01, 0xFF},
|
||||
{L2_SLOT_SCAN, 0x01, 0x01, 0xFF},
|
||||
|
||||
// SubFrame 2
|
||||
{L2_SLOT_SCAN, 0x00, 0x01, 0xFF},
|
||||
{L2_SLOT_SCAN, 0x01, 0x01, 0xFF},
|
||||
{L2_SLOT_SCAN, 0x00, 0x01, 0xFF},
|
||||
{L2_SLOT_SCAN, 0x01, 0x01, 0xFF},
|
||||
{L2_SLOT_SCAN, 0x00, 0x01, 0xFF},
|
||||
{L2_SLOT_SCAN, 0x01, 0x01, 0xFF},
|
||||
{L2_SLOT_SCAN, 0x00, 0x01, 0xFF},
|
||||
{L2_SLOT_SCAN, 0x01, 0x01, 0xFF},
|
||||
{L2_SLOT_SCAN, 0x00, 0x01, 0xFF},
|
||||
{L2_SLOT_SCAN, 0x01, 0x01, 0xFF},
|
||||
{L2_SLOT_SCAN, 0x00, 0x01, 0xFF},
|
||||
{L2_SLOT_SCAN, 0x01, 0x01, 0xFF},
|
||||
{L2_SLOT_SCAN, 0x00, 0x01, 0xFF},
|
||||
{L2_SLOT_SCAN, 0x01, 0x01, 0xFF},
|
||||
{L2_SLOT_ADVERTISE, 0x00, 0x01, 0xFF},
|
||||
{L2_SLOT_ADVERTISE, 0x01, 0x01, 0xFF},
|
||||
{L2_SLOT_ADVERTISE, 0x02, 0x01, 0xFF},
|
||||
{L2_SLOT_ADVERTISE, 0x03, 0x01, 0xFF},
|
||||
{L2_SLOT_IDLE, 0x00, 0x00, 0x00},
|
||||
{L2_SLOT_IDLE, 0x00, 0x00, 0x00},
|
||||
|
||||
// SubFrame 3
|
||||
{L2_SLOT_CONFIRM, 0x00, 0x01, 0xFF},
|
||||
{L2_SLOT_CONFIRM, 0x01, 0x01, 0xFF},
|
||||
{L2_SLOT_CONFIRM, 0x02, 0x01, 0xFF},
|
||||
{L2_SLOT_CONFIRM, 0x03, 0x01, 0xFF},
|
||||
{L2_SLOT_IDLE, 0x00, 0x00, 0x00},
|
||||
{L2_SLOT_CONFIRM, 0x00, 0x01, 0xFF},
|
||||
{L2_SLOT_CONFIRM, 0x01, 0x01, 0xFF},
|
||||
{L2_SLOT_CONFIRM, 0x02, 0x01, 0xFF},
|
||||
{L2_SLOT_CONFIRM, 0x03, 0x01, 0xFF},
|
||||
{L2_SLOT_IDLE, 0x00, 0x00, 0x00},
|
||||
{L2_SLOT_CONFIRM, 0x00, 0x02, 0x01},
|
||||
{L2_SLOT_CONFIRM, 0x01, 0x02, 0x01},
|
||||
{L2_SLOT_CONFIRM, 0x02, 0x02, 0x01},
|
||||
{L2_SLOT_CONFIRM, 0x03, 0x02, 0x01},
|
||||
{L2_SLOT_IDLE, 0x00, 0x00, 0x00},
|
||||
{L2_SLOT_CONFIRM, 0x00, 0x03, 0x01},
|
||||
{L2_SLOT_CONFIRM, 0x01, 0x03, 0x01},
|
||||
{L2_SLOT_CONFIRM, 0x02, 0x03, 0x01},
|
||||
{L2_SLOT_CONFIRM, 0x03, 0x03, 0x01},
|
||||
{L2_SLOT_IDLE, 0x00, 0x00, 0x00},
|
||||
|
||||
// SubFrame 4
|
||||
{L2_SLOT_CONFIRM, 0x00, 0x02, 0x01},
|
||||
{L2_SLOT_CONFIRM, 0x01, 0x02, 0x01},
|
||||
{L2_SLOT_CONFIRM, 0x02, 0x02, 0x01},
|
||||
{L2_SLOT_CONFIRM, 0x03, 0x02, 0x01},
|
||||
{L2_SLOT_IDLE, 0x00, 0x00, 0x00},
|
||||
{L2_SLOT_CONFIRM, 0x00, 0x03, 0x01},
|
||||
{L2_SLOT_CONFIRM, 0x01, 0x03, 0x01},
|
||||
{L2_SLOT_CONFIRM, 0x02, 0x03, 0x01},
|
||||
{L2_SLOT_CONFIRM, 0x03, 0x03, 0x01},
|
||||
{L2_SLOT_IDLE, 0x00, 0x00, 0x00},
|
||||
{L2_SLOT_CONFIRM, 0x00, 0x02, 0x01},
|
||||
{L2_SLOT_CONFIRM, 0x01, 0x02, 0x01},
|
||||
{L2_SLOT_CONFIRM, 0x02, 0x02, 0x01},
|
||||
{L2_SLOT_CONFIRM, 0x03, 0x02, 0x01},
|
||||
{L2_SLOT_IDLE, 0x00, 0x00, 0x00},
|
||||
{L2_SLOT_CONFIRM, 0x00, 0x03, 0x01},
|
||||
{L2_SLOT_CONFIRM, 0x01, 0x03, 0x01},
|
||||
{L2_SLOT_CONFIRM, 0x02, 0x03, 0x01},
|
||||
{L2_SLOT_CONFIRM, 0x03, 0x03, 0x01},
|
||||
{L2_SLOT_IDLE, 0x00, 0x00, 0x00},
|
||||
};
|
||||
|
||||
L2_RTNE_TABLE_ENTRY normalSub[L2_SLOTS_PER_FRAME] = {
|
||||
// SubFrame 0
|
||||
{L2_SLOT_SERVICE, 0x00, 0x01, 0x02},
|
||||
{L2_SLOT_SERVICE, 0x01, 0x01, 0x02},
|
||||
{L2_SLOT_SERVICE, 0x02, 0x01, 0x02},
|
||||
{L2_SLOT_SERVICE, 0x03, 0x01, 0x02},
|
||||
{L2_SLOT_IDLE, 0x00, 0x00, 0x00},
|
||||
{L2_SLOT_SERVICE, 0x00, 0x02, 0x01},
|
||||
{L2_SLOT_SERVICE, 0x01, 0x02, 0x01},
|
||||
{L2_SLOT_SERVICE, 0x02, 0x02, 0x01},
|
||||
{L2_SLOT_SERVICE, 0x03, 0x02, 0x01},
|
||||
{L2_SLOT_IDLE, 0x00, 0x00, 0x00},
|
||||
{L2_SLOT_SERVICE, 0x00, 0x01, 0x03},
|
||||
{L2_SLOT_SERVICE, 0x01, 0x01, 0x03},
|
||||
{L2_SLOT_SERVICE, 0x02, 0x01, 0x03},
|
||||
{L2_SLOT_SERVICE, 0x03, 0x01, 0x03},
|
||||
{L2_SLOT_IDLE, 0x00, 0x00, 0x00},
|
||||
{L2_SLOT_SERVICE, 0x00, 0x03, 0x01},
|
||||
{L2_SLOT_SERVICE, 0x01, 0x03, 0x01},
|
||||
{L2_SLOT_SERVICE, 0x02, 0x03, 0x01},
|
||||
{L2_SLOT_SERVICE, 0x03, 0x03, 0x01},
|
||||
{L2_SLOT_IDLE, 0x00, 0x00, 0x00},
|
||||
|
||||
// SubFrame 1
|
||||
{L2_SLOT_SERVICE, 0x00, 0x01, 0x02},
|
||||
{L2_SLOT_SERVICE, 0x01, 0x01, 0x02},
|
||||
{L2_SLOT_SERVICE, 0x02, 0x01, 0x02},
|
||||
{L2_SLOT_SERVICE, 0x03, 0x01, 0x02},
|
||||
{L2_SLOT_IDLE, 0x00, 0x00, 0x00},
|
||||
{L2_SLOT_SERVICE, 0x00, 0x02, 0x01},
|
||||
{L2_SLOT_SERVICE, 0x01, 0x02, 0x01},
|
||||
{L2_SLOT_SERVICE, 0x02, 0x02, 0x01},
|
||||
{L2_SLOT_SERVICE, 0x03, 0x02, 0x01},
|
||||
{L2_SLOT_IDLE, 0x00, 0x00, 0x00},
|
||||
{L2_SLOT_SERVICE, 0x00, 0x01, 0x03},
|
||||
{L2_SLOT_SERVICE, 0x01, 0x01, 0x03},
|
||||
{L2_SLOT_SERVICE, 0x02, 0x01, 0x03},
|
||||
{L2_SLOT_SERVICE, 0x03, 0x01, 0x03},
|
||||
{L2_SLOT_IDLE, 0x00, 0x00, 0x00},
|
||||
{L2_SLOT_SERVICE, 0x00, 0x03, 0x01},
|
||||
{L2_SLOT_SERVICE, 0x01, 0x03, 0x01},
|
||||
{L2_SLOT_SERVICE, 0x02, 0x03, 0x01},
|
||||
{L2_SLOT_SERVICE, 0x03, 0x03, 0x01},
|
||||
{L2_SLOT_IDLE, 0x00, 0x00, 0x00},
|
||||
|
||||
// SubFrame 2
|
||||
{L2_SLOT_SERVICE, 0x00, 0x01, 0x02},
|
||||
{L2_SLOT_SERVICE, 0x01, 0x01, 0x02},
|
||||
{L2_SLOT_SERVICE, 0x02, 0x01, 0x02},
|
||||
{L2_SLOT_SERVICE, 0x03, 0x01, 0x02},
|
||||
{L2_SLOT_IDLE, 0x00, 0x00, 0x00},
|
||||
{L2_SLOT_SERVICE, 0x00, 0x02, 0x01},
|
||||
{L2_SLOT_SERVICE, 0x01, 0x02, 0x01},
|
||||
{L2_SLOT_SERVICE, 0x02, 0x02, 0x01},
|
||||
{L2_SLOT_SERVICE, 0x03, 0x02, 0x01},
|
||||
{L2_SLOT_IDLE, 0x00, 0x00, 0x00},
|
||||
{L2_SLOT_SERVICE, 0x00, 0x01, 0x03},
|
||||
{L2_SLOT_SERVICE, 0x01, 0x01, 0x03},
|
||||
{L2_SLOT_SERVICE, 0x02, 0x01, 0x03},
|
||||
{L2_SLOT_SERVICE, 0x03, 0x01, 0x03},
|
||||
{L2_SLOT_IDLE, 0x00, 0x00, 0x00},
|
||||
{L2_SLOT_SERVICE, 0x00, 0x03, 0x01},
|
||||
{L2_SLOT_SERVICE, 0x01, 0x03, 0x01},
|
||||
{L2_SLOT_SERVICE, 0x02, 0x03, 0x01},
|
||||
{L2_SLOT_SERVICE, 0x03, 0x03, 0x01},
|
||||
{L2_SLOT_IDLE, 0x00, 0x00, 0x00},
|
||||
|
||||
// SubFrame 3
|
||||
{L2_SLOT_SERVICE, 0x00, 0x01, 0x02},
|
||||
{L2_SLOT_SERVICE, 0x01, 0x01, 0x02},
|
||||
{L2_SLOT_SERVICE, 0x02, 0x01, 0x02},
|
||||
{L2_SLOT_SERVICE, 0x03, 0x01, 0x02},
|
||||
{L2_SLOT_IDLE, 0x00, 0x00, 0x00},
|
||||
{L2_SLOT_SERVICE, 0x00, 0x02, 0x01},
|
||||
{L2_SLOT_SERVICE, 0x01, 0x02, 0x01},
|
||||
{L2_SLOT_SERVICE, 0x02, 0x02, 0x01},
|
||||
{L2_SLOT_SERVICE, 0x03, 0x02, 0x01},
|
||||
{L2_SLOT_IDLE, 0x00, 0x00, 0x00},
|
||||
{L2_SLOT_SERVICE, 0x00, 0x01, 0x03},
|
||||
{L2_SLOT_SERVICE, 0x01, 0x01, 0x03},
|
||||
{L2_SLOT_SERVICE, 0x02, 0x01, 0x03},
|
||||
{L2_SLOT_SERVICE, 0x03, 0x01, 0x03},
|
||||
{L2_SLOT_IDLE, 0x00, 0x00, 0x00},
|
||||
{L2_SLOT_SERVICE, 0x00, 0x03, 0x01},
|
||||
{L2_SLOT_SERVICE, 0x01, 0x03, 0x01},
|
||||
{L2_SLOT_SERVICE, 0x02, 0x03, 0x01},
|
||||
{L2_SLOT_SERVICE, 0x03, 0x03, 0x01},
|
||||
{L2_SLOT_IDLE, 0x00, 0x00, 0x00},
|
||||
|
||||
// SubFrame 4
|
||||
{L2_SLOT_SERVICE, 0x00, 0x01, 0x02},
|
||||
{L2_SLOT_SERVICE, 0x01, 0x01, 0x02},
|
||||
{L2_SLOT_SERVICE, 0x02, 0x01, 0x02},
|
||||
{L2_SLOT_SERVICE, 0x03, 0x01, 0x02},
|
||||
{L2_SLOT_IDLE, 0x00, 0x00, 0x00},
|
||||
{L2_SLOT_SERVICE, 0x00, 0x02, 0x01},
|
||||
{L2_SLOT_SERVICE, 0x01, 0x02, 0x01},
|
||||
{L2_SLOT_SERVICE, 0x02, 0x02, 0x01},
|
||||
{L2_SLOT_SERVICE, 0x03, 0x02, 0x01},
|
||||
{L2_SLOT_IDLE, 0x00, 0x00, 0x00},
|
||||
{L2_SLOT_SERVICE, 0x00, 0x01, 0x03},
|
||||
{L2_SLOT_SERVICE, 0x01, 0x01, 0x03},
|
||||
{L2_SLOT_SERVICE, 0x02, 0x01, 0x03},
|
||||
{L2_SLOT_SERVICE, 0x03, 0x01, 0x03},
|
||||
{L2_SLOT_IDLE, 0x00, 0x00, 0x00},
|
||||
{L2_SLOT_SERVICE, 0x00, 0x03, 0x01},
|
||||
{L2_SLOT_SERVICE, 0x01, 0x03, 0x01},
|
||||
{L2_SLOT_SERVICE, 0x02, 0x03, 0x01},
|
||||
{L2_SLOT_SERVICE, 0x03, 0x03, 0x01},
|
||||
{L2_SLOT_IDLE, 0x00, 0x00, 0x00},
|
||||
};
|
||||
|
||||
L2_RTNE_TABLE_ENTRY *initTable[L2_INIT_RTNE_PERIOD] =
|
||||
{
|
||||
intraScanSubT
|
||||
};
|
||||
|
||||
L2_RTNE_TABLE_ENTRY *normalTable[L2_NORMAL_RTNE_PERIOD] =
|
||||
{
|
||||
normalSub
|
||||
};
|
||||
|
||||
/** @} RoutineTable*/
|
||||
/** @} LinkLayer*/
|
||||
@@ -0,0 +1,929 @@
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @file scan.c
|
||||
* @author FanHao ([email protected])
|
||||
* @brief DF Linklayer scan implementation file.
|
||||
* @version 0.1
|
||||
* @date 2023-05-06
|
||||
*
|
||||
* @copyright Copyright(c) 2024 Beijing Institute of Technology.\n
|
||||
* Lab of Communication and Network
|
||||
*
|
||||
******************************************************************************/
|
||||
/**
|
||||
* @addtogroup LinkLayer
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup LinkLayer_Scan
|
||||
* @{
|
||||
*/
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
#include <string.h>
|
||||
#include "link_layer.h"
|
||||
#include "link_layer_types.h"
|
||||
#include "msg_def.h"
|
||||
#include "node_list.h"
|
||||
#include "error.h"
|
||||
#include "common.h"
|
||||
#include "../phy_layer/phy_layer.h"
|
||||
|
||||
/************************** Constant Definitions *****************************/
|
||||
#define ADV_LISTEN_TIMEOUT 40
|
||||
#define CFM_LISTEN_TIMEOUT 5
|
||||
#define ADV_FRAME_SLOTS 4
|
||||
#define CFM_FRAME_SLOTS 5
|
||||
/***************** Macros (In-line Functions) Definitions *********************/
|
||||
|
||||
/**************************** Type Definitions *******************************/
|
||||
|
||||
/************************** Variable Definitions *****************************/
|
||||
// Pair by regex
|
||||
// Regex: ((\{\.oaxis = [0-9]+[ ,]+\.raxis = [0-9]+[ ]*\}, ){2})
|
||||
PHY_ANT_ANGLE antNrrwPattern_0[L1_NUM_ANT_NRRW_PATTERN] =
|
||||
{
|
||||
{.oaxis = 0 , .raxis = 0 },
|
||||
{.oaxis = 139, .raxis = 2225},
|
||||
{.oaxis = 152, .raxis = 850 },
|
||||
{.oaxis = 138, .raxis = 3155},
|
||||
{.oaxis = 159, .raxis = 1680},
|
||||
{.oaxis = 168, .raxis = 285 },
|
||||
{.oaxis = 195, .raxis = 2630},
|
||||
{.oaxis = 211, .raxis = 1204},
|
||||
{.oaxis = 225, .raxis = 3429},
|
||||
{.oaxis = 249, .raxis = 2022},
|
||||
{.oaxis = 272, .raxis = 629 },
|
||||
{.oaxis = 265, .raxis = 2934},
|
||||
{.oaxis = 277, .raxis = 1499},
|
||||
{.oaxis = 289, .raxis = 124 },
|
||||
{.oaxis = 300, .raxis = 2349},
|
||||
{.oaxis = 311, .raxis = 959 },
|
||||
{.oaxis = 321, .raxis = 3199},
|
||||
{.oaxis = 331, .raxis = 1824},
|
||||
{.oaxis = 341, .raxis = 389 },
|
||||
{.oaxis = 351, .raxis = 2674},
|
||||
{.oaxis = 360, .raxis = 1268},
|
||||
{.oaxis = 364, .raxis = 3483},
|
||||
{.oaxis = 378, .raxis = 2118},
|
||||
{.oaxis = 387, .raxis = 733 },
|
||||
{.oaxis = 416, .raxis = 3028},
|
||||
{.oaxis = 404, .raxis = 1623},
|
||||
{.oaxis = 433, .raxis = 248 },
|
||||
{.oaxis = 421, .raxis = 2473},
|
||||
{.oaxis = 429, .raxis = 1098},
|
||||
{.oaxis = 437, .raxis = 3303},
|
||||
{.oaxis = 445, .raxis = 1948},
|
||||
{.oaxis = 443, .raxis = 543 },
|
||||
{.oaxis = 450, .raxis = 2828},
|
||||
{.oaxis = 448, .raxis = 1422},
|
||||
{.oaxis = 455, .raxis = 47 },
|
||||
{.oaxis = 453, .raxis = 2272},
|
||||
{.oaxis = 450, .raxis = 897 }
|
||||
};
|
||||
|
||||
PHY_ANT_ANGLE antNrrwPattern_1[L1_NUM_ANT_NRRW_PATTERN] =
|
||||
{
|
||||
{.oaxis = 0 , .raxis = 0 },
|
||||
{.oaxis = 139, .raxis = 1155},
|
||||
{.oaxis = 152, .raxis = 3380},
|
||||
{.oaxis = 138, .raxis = 2085},
|
||||
{.oaxis = 159, .raxis = 610 },
|
||||
{.oaxis = 168, .raxis = 2815},
|
||||
{.oaxis = 195, .raxis = 1560},
|
||||
{.oaxis = 211, .raxis = 134 },
|
||||
{.oaxis = 225, .raxis = 2359},
|
||||
{.oaxis = 249, .raxis = 952 },
|
||||
{.oaxis = 272, .raxis = 3159},
|
||||
{.oaxis = 265, .raxis = 1864},
|
||||
{.oaxis = 277, .raxis = 429 },
|
||||
{.oaxis = 289, .raxis = 2654},
|
||||
{.oaxis = 300, .raxis = 1279},
|
||||
{.oaxis = 311, .raxis = 3489},
|
||||
{.oaxis = 321, .raxis = 2129},
|
||||
{.oaxis = 331, .raxis = 754 },
|
||||
{.oaxis = 341, .raxis = 2919},
|
||||
{.oaxis = 351, .raxis = 1604},
|
||||
{.oaxis = 360, .raxis = 198 },
|
||||
{.oaxis = 364, .raxis = 2413},
|
||||
{.oaxis = 378, .raxis = 1048},
|
||||
{.oaxis = 387, .raxis = 3263},
|
||||
{.oaxis = 416, .raxis = 1958},
|
||||
{.oaxis = 404, .raxis = 553 },
|
||||
{.oaxis = 433, .raxis = 2778},
|
||||
{.oaxis = 421, .raxis = 1403},
|
||||
{.oaxis = 429, .raxis = 28 },
|
||||
{.oaxis = 437, .raxis = 2233},
|
||||
{.oaxis = 445, .raxis = 878 },
|
||||
{.oaxis = 443, .raxis = 3073},
|
||||
{.oaxis = 450, .raxis = 1758},
|
||||
{.oaxis = 448, .raxis = 352 },
|
||||
{.oaxis = 455, .raxis = 2577},
|
||||
{.oaxis = 453, .raxis = 1202},
|
||||
{.oaxis = 450, .raxis = 3427},
|
||||
};
|
||||
/************************** Function Prototypes ******************************/
|
||||
static void LockStateUpdate(L2_SCAN_FSM *scanFsmPtr, bool state);
|
||||
static void AdvRecvStateUpdate(L2_SCAN_FSM *scanFsmPtr, bool state);
|
||||
static void StageUpdate(L2_SCAN_FSM *scanFsmPtr, SCAN_STAGE newStage);
|
||||
static void PendCfmAck(L2_SCAN_FSM *scanFsmPtr);
|
||||
|
||||
static int32_t Scan_InitScanHandler(L2_INST *instPtr);
|
||||
static int32_t Scan_AdvHandler(L2_INST *instPtr);
|
||||
static int32_t Scan_CfmHandler(L2_INST *instPtr);
|
||||
|
||||
static int32_t ScanMsg_Packing(L2_INST *instPtr, L2_FRAME_TYPE type, uint8_t dstId);
|
||||
|
||||
/**
|
||||
* @brief Update Init-Scan lock state.
|
||||
*/
|
||||
static inline void LockStateUpdate(L2_SCAN_FSM *scanFsmPtr, bool state)
|
||||
{
|
||||
ASSERT(scanFsmPtr != NULL);
|
||||
DBG_INFO("Update BeamLockState from [%" PRId8 "] to [%" PRId8 "].\n",
|
||||
scanFsmPtr->isLocked, state);
|
||||
scanFsmPtr->isLocked = state;
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update Base-info Advertisement state.
|
||||
*/
|
||||
static void AdvRecvStateUpdate(L2_SCAN_FSM *scanFsmPtr, bool state)
|
||||
{
|
||||
ASSERT(scanFsmPtr != NULL);
|
||||
DBG_INFO("Update AdvRecvState from [%" PRId8 "] to [%" PRId8 "].\n",
|
||||
scanFsmPtr->isAdvRecvd, state);
|
||||
scanFsmPtr->isAdvRecvd = state;
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update 2-Way Acquisition ack state.
|
||||
*/
|
||||
static void PendCfmAck(L2_SCAN_FSM *scanFsmPtr)
|
||||
{
|
||||
ASSERT(scanFsmPtr != NULL);
|
||||
DBG_INFO("Pending Cfm-Ack...\n");
|
||||
scanFsmPtr->isAckPending = true;
|
||||
return;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Update current Scan-Net stage
|
||||
*
|
||||
* @param scanFsmPtr A pointer to scan net fsm.
|
||||
* newStage New state.
|
||||
*
|
||||
* @return NONE.
|
||||
*
|
||||
******************************************************************************/
|
||||
static void StageUpdate(L2_SCAN_FSM *scanFsmPtr, SCAN_STAGE newStage)
|
||||
{
|
||||
ASSERT(newStage >= L2_SCAN_NONE_STAGE && newStage <= L2_SCAN_CFM_STAGE);
|
||||
DBG_INFO("ScanNet current stage: %" PRIu8 " -> ScanNet new stage: %" PRIu8 " \n",
|
||||
scanFsmPtr->scanStage, newStage);
|
||||
scanFsmPtr->scanStage = newStage;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Member node scan net InitScan stage handler.
|
||||
*
|
||||
* @param instPtr A pointer to l2 instance
|
||||
*
|
||||
* @return used slot (5ms slot).
|
||||
*
|
||||
******************************************************************************/
|
||||
static int32_t Scan_InitScanHandler(L2_INST *instPtr)
|
||||
{
|
||||
ASSERT(instPtr != NULL);
|
||||
PHY_INST *phyRef = instPtr->config.phyInstPtr;
|
||||
L2_SCAN_FSM *scanFsmPtr = instPtr->scanFSM;
|
||||
DBG_INFO("** Net-Setup - InitScan Procedure (Attempts: %" PRIu8 ")**\n", scanFsmPtr->scanCnt);
|
||||
|
||||
if (scanFsmPtr->scanCnt == 0)
|
||||
{
|
||||
// Update scan beam table
|
||||
L2_Scan_RefreashScanTable(instPtr);
|
||||
}
|
||||
else if (Phy_IsFrameDetected(phyRef))
|
||||
{
|
||||
// last scan beam number
|
||||
scanFsmPtr->beamNo = Phy_LastScanBeamNo(phyRef);
|
||||
// Update scan beam table
|
||||
L2_Scan_RefreashScanTable(instPtr);
|
||||
}
|
||||
|
||||
if (scanFsmPtr->isLocked == true)
|
||||
{
|
||||
scanFsmPtr->beamNo = Phy_LastScanBeamNo(phyRef);
|
||||
Phy_SetBeamNo(phyRef, scanFsmPtr->beamNo, PHY_ANT_BEAM_16);
|
||||
L2_SetupNextSlot(instPtr, L2_TOR_RX, L2_ADV_FRAME);
|
||||
StageUpdate(scanFsmPtr, L2_SCAN_ADV_STAGE);
|
||||
instPtr->log.lastBeamWidth = PHY_ANT_BEAM_16;
|
||||
} /* Otherwise remain L2_SCAN_INIT_STAGE */
|
||||
else
|
||||
{
|
||||
/* Antenna steering (reserved, automatically accomplished by physical layer) */
|
||||
Phy_SetBeamNo(phyRef, scanFsmPtr->beamNo, PHY_ANT_BEAM_16);
|
||||
L2_SetupNextSlot(instPtr, L2_TOR_RX, L2_SCAN_FRAME);
|
||||
scanFsmPtr->scanCnt++;
|
||||
instPtr->log.lastBeamWidth = PHY_ANT_BEAM_16;
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Member node scan net BmAdvt stage handler.
|
||||
*
|
||||
* @param scanFsmPtr A pointer to scan net fsm.
|
||||
* mainState A pointer to main node state.
|
||||
*
|
||||
* @return used slot (5ms slot).
|
||||
*
|
||||
******************************************************************************/
|
||||
static int32_t Scan_AdvHandler(L2_INST *instPtr)
|
||||
{
|
||||
ASSERT(instPtr != NULL);
|
||||
L2_SCAN_FSM *scanFsmPtr = instPtr->scanFSM;
|
||||
PHY_INST *phyRef = instPtr->config.phyInstPtr;
|
||||
TMC_INST *tmcRef = instPtr->config.tmcInstPtr;
|
||||
DBG_INFO("** Net-Setup - Advertisement Procedure (Timeout: %" PRIu8 ") **\n", scanFsmPtr->advTimeout);
|
||||
|
||||
// if received a valid bm frame.
|
||||
if (scanFsmPtr->isAdvRecvd == true)
|
||||
{
|
||||
// last scan beam number
|
||||
scanFsmPtr->beamNo = Phy_LastScanBeamNo(phyRef);
|
||||
// reset listen counter.
|
||||
scanFsmPtr->advTimeout = 0;
|
||||
|
||||
// Update scan stage
|
||||
StageUpdate(scanFsmPtr, L2_SCAN_CFM_STAGE);
|
||||
|
||||
// start a confirm frame reception if in the target slot
|
||||
if ((TimeCtrl_GetIntCnt(tmcRef) + 1) % CFM_FRAME_SLOTS == 0)
|
||||
{
|
||||
// using pull mode to receive confirm frame
|
||||
// since first time sync procedure is accomplished in ADV stage.
|
||||
Phy_SetBeamWidth(phyRef, PHY_ANT_BEAM_16);
|
||||
Phy_SetBeamNo(phyRef, scanFsmPtr->beamNo, PHY_ANT_BEAM_16);
|
||||
Phy_SetMode(phyRef, PHY_MODE_PULL);
|
||||
L2_SetupNextSlot(instPtr, L2_TOR_RX, L2_CFM_FRAME);
|
||||
scanFsmPtr->cfmTimeout++; // increase counter.
|
||||
instPtr->log.lastBeamWidth = PHY_ANT_BEAM_16;
|
||||
}
|
||||
// otherwise skip...
|
||||
return SUCCESS;
|
||||
}
|
||||
// no valid bm frame was received.
|
||||
else
|
||||
{
|
||||
/* if time out reached, go back to init scan stage. */
|
||||
if (scanFsmPtr->advTimeout > ADV_LISTEN_TIMEOUT)
|
||||
{
|
||||
/* Antenna steering (reserved, automatically accomplished by physical layer) */
|
||||
Phy_SetBeamNo(phyRef, scanFsmPtr->beamNo, PHY_ANT_BEAM_16);
|
||||
L2_SetupNextSlot(instPtr, L2_TOR_RX, L2_SCAN_FRAME);
|
||||
DBG_WARNING("Adv timeout, restart net scan from L2_SCAN_INIT_STAGE.\n");
|
||||
L2_Scan_Reset(scanFsmPtr);
|
||||
instPtr->log.lastBeamWidth = PHY_ANT_BEAM_16;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Antenna steering (reserved, automatically accomplished by physical layer) */
|
||||
Phy_SetBeamNo(phyRef, scanFsmPtr->beamNo, PHY_ANT_BEAM_16);
|
||||
L2_SetupNextSlot(instPtr, L2_TOR_RX, L2_ADV_FRAME);
|
||||
scanFsmPtr->advTimeout++;
|
||||
instPtr->log.lastBeamWidth = PHY_ANT_BEAM_16;
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Scan net 2Way-Acq stage handler.
|
||||
*
|
||||
* @param instPtr a pointer to linklayer layer instance
|
||||
*
|
||||
* @return used slot (5ms slot).
|
||||
*
|
||||
******************************************************************************/
|
||||
static int32_t Scan_CfmHandler(L2_INST *instPtr)
|
||||
{
|
||||
ASSERT(instPtr != NULL);
|
||||
L2_SCAN_FSM *scanFsmPtr = instPtr->scanFSM;
|
||||
PHY_INST *phyRef = instPtr->config.phyInstPtr;
|
||||
DBG_INFO("** Net-Setup - Confirm Procedure (Timeout: %" PRIu8 ") **\n", scanFsmPtr->cfmTimeout);
|
||||
|
||||
// 2 way acq failed, back to init stage.
|
||||
if (scanFsmPtr->cfmTimeout >= CFM_LISTEN_TIMEOUT)
|
||||
{
|
||||
DBG_WARNING("Cmf timeout, restart net scan from L2_SCAN_INIT_STAGE.\n");
|
||||
L2_Scan_Reset(scanFsmPtr);
|
||||
return SUCCESS;
|
||||
}
|
||||
if (L2_GetNextSlotNum(instPtr) % CFM_FRAME_SLOTS == 0)
|
||||
{
|
||||
// using pull mode to receive confirm frame
|
||||
// since first time sync procedure is accomplished in ADV stage.
|
||||
Phy_SetBeamWidth(phyRef, PHY_ANT_BEAM_16);
|
||||
Phy_SetBeamNo(phyRef, scanFsmPtr->beamNo, PHY_ANT_BEAM_16);
|
||||
Phy_SetMode(phyRef, PHY_MODE_PULL);
|
||||
L2_SetupNextSlot(instPtr, L2_TOR_RX, L2_CFM_FRAME);
|
||||
scanFsmPtr->cfmTimeout++; // increase counter.
|
||||
instPtr->log.lastBeamWidth = PHY_ANT_BEAM_16;
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Packing Scan message to a bit array.
|
||||
*
|
||||
* @param bitarr pointer to bit array buffer.
|
||||
* @param msgType message type.
|
||||
*
|
||||
* @return EPARAM
|
||||
* SUCCESS
|
||||
*
|
||||
******************************************************************************/
|
||||
static int32_t ScanMsg_Packing(L2_INST *instPtr, L2_FRAME_TYPE type, uint8_t dstId)
|
||||
{
|
||||
ASSERT(instPtr != NULL);
|
||||
int32_t Status;
|
||||
uint32_t dataChunk;
|
||||
uint8_t *buff = instPtr->sendPktData;
|
||||
if (type < L2_ADV_FRAME || type > L2_CFM_FRAME)
|
||||
{
|
||||
DBG_ERROR("Unexpected frame type: %" PRId8 ".\n", type);
|
||||
return EPARAM;
|
||||
}
|
||||
|
||||
// Common section of link layer package
|
||||
dataChunk = L2_GetNextFrameNum(instPtr);
|
||||
L2_FrameInsertChunk(buff, L2_MSG_FRAME_NUM, L2_MSG_FRAME_NUM_LEN, &dataChunk);
|
||||
dataChunk = L2_GetNextSlotNum(instPtr);
|
||||
L2_FrameInsertChunk(buff, L2_MSG_SLOT_NUM, L2_MSG_SLOT_NUM_LEN, &dataChunk);
|
||||
dataChunk = L2_GetNodeId(instPtr);
|
||||
L2_FrameInsertChunk(buff, L2_MSG_SRC_ID, L2_MSG_SRC_ID_LEN, &dataChunk);
|
||||
dataChunk = dstId;
|
||||
L2_FrameInsertChunk(buff, L2_MSG_DST_ID, L2_MSG_DST_ID_LEN, &dataChunk);
|
||||
switch (type)
|
||||
{
|
||||
case L2_ADV_FRAME:
|
||||
{
|
||||
dataChunk = L2_ADV_FRAME;
|
||||
L2_FrameInsertChunk(buff, L2_MSG_TYPE, L2_MSG_TYPE_LEN, &dataChunk);
|
||||
|
||||
SysMonitor_GetSysinfo(&(instPtr->sysInfo));
|
||||
// insert position and speed info
|
||||
L2_FrameInsertChunk(buff, L2_MSG_ADV_SRC_POSX, L2_MSG_ADV_SRC_POSX_LEN, &(instPtr->sysInfo.posX));
|
||||
L2_FrameInsertChunk(buff, L2_MSG_ADV_SRC_POSY, L2_MSG_ADV_SRC_POSY_LEN, &(instPtr->sysInfo.posY));
|
||||
L2_FrameInsertChunk(buff, L2_MSG_ADV_SRC_POSZ, L2_MSG_ADV_SRC_POSZ_LEN, &(instPtr->sysInfo.posZ));
|
||||
|
||||
// Insert net start time
|
||||
L2_FrameInsertChunk(buff, L2_MSG_ADV_SRC_NETSTART_TIME, L2_MSG_ADV_SRC_NETSTART_TIME_LEN, &(instPtr->netStartTime));
|
||||
|
||||
// Append CRC
|
||||
Status = L2_CrcAppend(buff, L2_ADV_PACK_LEN - L2_MSG_ADV_SVC_CRC_LEN, L2_MSG_ADV_SVC_CRC, L2_CRC16_1021);
|
||||
if (Status != SUCCESS)
|
||||
{
|
||||
DBG_ERROR("Fail to append CRC, error code: %" PRId32 ".\n", Status);
|
||||
return Status;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case L2_CFM_FRAME:
|
||||
{
|
||||
dataChunk = L2_CFM_FRAME;
|
||||
L2_FrameInsertChunk(buff, L2_MSG_TYPE, L2_MSG_TYPE_LEN, &dataChunk);
|
||||
|
||||
SysMonitor_GetSysinfo(&(instPtr->sysInfo));
|
||||
// insert position and speed info
|
||||
L2_FrameInsertChunk(buff, L2_MSG_CFM_SRC_POSX, L2_MSG_CFM_SRC_POSX_LEN, &(instPtr->sysInfo.posX));
|
||||
L2_FrameInsertChunk(buff, L2_MSG_CFM_SRC_POSY, L2_MSG_CFM_SRC_POSY_LEN, &(instPtr->sysInfo.posY));
|
||||
L2_FrameInsertChunk(buff, L2_MSG_CFM_SRC_POSZ, L2_MSG_CFM_SRC_POSZ_LEN, &(instPtr->sysInfo.posZ));
|
||||
L2_FrameInsertChunk(buff, L2_MSG_CFM_SRC_SPEEDX, L2_MSG_CFM_SRC_SPEEDX_LEN, &(instPtr->sysInfo.vX));
|
||||
L2_FrameInsertChunk(buff, L2_MSG_CFM_SRC_SPEEDY, L2_MSG_CFM_SRC_SPEEDY_LEN, &(instPtr->sysInfo.vY));
|
||||
L2_FrameInsertChunk(buff, L2_MSG_CFM_SRC_SPEEDZ, L2_MSG_CFM_SRC_SPEEDZ_LEN, &(instPtr->sysInfo.vZ));
|
||||
|
||||
// Packing extra payload
|
||||
uint32_t dataId;
|
||||
if (L2_GetNodeType(instPtr) == L2_NODE_HEAD)
|
||||
{
|
||||
SysMonitor_GetSendPayload(buff + L2_MSG_CFM_PAYLOAD, &dataId, PAYLOAD_LEN_FLJ_TX);
|
||||
}
|
||||
else
|
||||
{
|
||||
SysMonitor_GetSendPayload(buff + L2_MSG_CFM_PAYLOAD, &dataId, PAYLOAD_LEN_LJ_TX);
|
||||
}
|
||||
|
||||
L2_FrameInsertChunk(buff, L2_MSG_CFM_PAYLOAD_ID, L2_MSG_CFM_PAYLOAD_ID_LEN, &dataId);
|
||||
if (dataId == DATA_ID_NONE)
|
||||
{
|
||||
memset(buff + L2_MSG_CFM_PAYLOAD, 0xAA, L2_MSG_CFM_PAYLOAD_LEN);
|
||||
}
|
||||
|
||||
// Append CRC
|
||||
Status = L2_CrcAppend(buff, L2_CMF_PACK_LEN - L2_MSG_CFM_CRC_LEN, L2_MSG_CFM_CRC, L2_CRC16_1021);
|
||||
if (Status != SUCCESS)
|
||||
{
|
||||
DBG_ERROR("Fail to append CRC, error code: %" PRId32 ".\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
// Logging...
|
||||
memcpy(instPtr->log.txLog.data, buff, L2_CMF_PACK_LEN);
|
||||
instPtr->log.txLog.dataId = dataId;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
DBG_ERROR("Unexpected frame type: %" PRId8 ".\n", type);
|
||||
return EPARAM;
|
||||
}
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Scan net packet handler.
|
||||
*
|
||||
* @param instPtr a pointer to linklayer layer instance
|
||||
* @param msg A pointer to frame data buffer.
|
||||
*
|
||||
* @return
|
||||
*
|
||||
******************************************************************************/
|
||||
int32_t L2_Scan_PktHandler(L2_INST *instPtr, uint8_t *msg)
|
||||
{
|
||||
ASSERT(instPtr != NULL);
|
||||
ASSERT(msg != NULL);
|
||||
int32_t Status;
|
||||
uint8_t srcId = L2_NONE_ID;
|
||||
uint8_t dstId = L2_NONE_ID;
|
||||
L2_FRAME_TYPE frameType = L2_NONE_FRAME;
|
||||
L2_SCAN_FSM *scanFsmPtr = instPtr->scanFSM;
|
||||
L2_FrameGetChunk(msg, L2_MSG_TYPE, L2_MSG_TYPE_LEN, &frameType);
|
||||
L2_FrameGetChunk(msg, L2_MSG_SRC_ID, L2_MSG_SRC_ID_LEN, &srcId);
|
||||
L2_FrameGetChunk(msg, L2_MSG_DST_ID, L2_MSG_DST_ID_LEN, &dstId);
|
||||
if(dstId != L2_GetNodeId(instPtr) && L2_GetNodeType(instPtr) == L2_NODE_HEAD)
|
||||
{
|
||||
DBG_WARNING("Drop frame not addressed to me (%u)", nodeId);
|
||||
return SUCCESS;
|
||||
}
|
||||
else if(dstId != L2_GetNodeId(instPtr) && dstId == L2_NONE_ID)
|
||||
{
|
||||
DBG_WARNING("Drop frame not addressed to me (%u)", nodeId);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
switch (frameType)
|
||||
{
|
||||
case L2_SCAN_FRAME:
|
||||
case L2_ADV_FRAME:
|
||||
{
|
||||
if (L2_GetLastOptFrameType(instPtr) == L2_SCAN_FRAME)
|
||||
{
|
||||
LockStateUpdate(scanFsmPtr, true);
|
||||
StageUpdate(scanFsmPtr, L2_SCAN_ADV_STAGE);
|
||||
}
|
||||
if (L2_GetNodeType(instPtr) == L2_NODE_HEAD)
|
||||
{
|
||||
DBG_ERROR("Unexpected call from head node, only member Node can handle L2_SCAN_FRAME and L2_ADV_FRAME.\n");
|
||||
Status = EUNEXP;
|
||||
break;
|
||||
}
|
||||
|
||||
NODE_ENTRY *node;
|
||||
node = L2_GetNodeById(instPtr->nodeList, srcId);
|
||||
if (node == NULL)
|
||||
{
|
||||
node = L2_AppendNode(instPtr->nodeList, srcId, L2_NODE_MEMBER);
|
||||
if (node == NULL)
|
||||
{
|
||||
DBG_ERROR("Failed to append new node [id: %" PRId8 "]", srcId);
|
||||
Status = ENOMEM;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Update node info.
|
||||
float nodePos;
|
||||
L2_FrameGetChunk(msg, L2_MSG_ADV_SRC_POSX, L2_MSG_ADV_SRC_POSX_LEN, &nodePos);
|
||||
node->nodeInfo.pos.x = (double)nodePos;
|
||||
L2_FrameGetChunk(msg, L2_MSG_ADV_SRC_POSY, L2_MSG_ADV_SRC_POSY_LEN, &nodePos);
|
||||
node->nodeInfo.pos.y = (double)nodePos;
|
||||
L2_FrameGetChunk(msg, L2_MSG_ADV_SRC_POSZ, L2_MSG_ADV_SRC_POSZ_LEN, &nodePos);
|
||||
node->nodeInfo.pos.z = (double)nodePos;
|
||||
node->nodeInfo.beamNo = Phy_LastScanBeamNo(instPtr->config.phyInstPtr);
|
||||
|
||||
// Reset node ttl
|
||||
node->ttlCnt = 0;
|
||||
|
||||
uint32_t netstartTime;
|
||||
// Update net start time.
|
||||
L2_FrameGetChunk(msg, L2_MSG_ADV_SRC_NETSTART_TIME, L2_MSG_ADV_SRC_NETSTART_TIME_LEN, &netstartTime);
|
||||
L2_EVENT netSetupDoneEvent = {
|
||||
.event = L2_EV_NET_ADV_UPDATE,
|
||||
.msg = &netstartTime};
|
||||
AssertL2Event(instPtr, &netSetupDoneEvent);
|
||||
|
||||
// Calculate time deviation
|
||||
uint32_t frameNum, slotNum = 0;
|
||||
L2_FrameGetChunk(msg, L2_MSG_FRAME_NUM, L2_MSG_FRAME_NUM_LEN, &frameNum);
|
||||
L2_FrameGetChunk(msg, L2_MSG_SLOT_NUM, L2_MSG_SLOT_NUM_LEN, &slotNum);
|
||||
Status = L2_GetTimeDeviation(instPtr, frameNum, slotNum, true, &(instPtr->log.timeDev));
|
||||
if (Status != SUCCESS)
|
||||
{
|
||||
DBG_ERROR("Failed to compute time deviation.\n");
|
||||
break;
|
||||
}
|
||||
|
||||
// Time sync.
|
||||
L2_TimeAdjust(instPtr, &(instPtr->log.timeDev));
|
||||
|
||||
// trigger flag
|
||||
AdvRecvStateUpdate(scanFsmPtr, true);
|
||||
Status = SUCCESS;
|
||||
break;
|
||||
}
|
||||
case L2_CFM_FRAME:
|
||||
{
|
||||
NODE_ENTRY *node;
|
||||
node = L2_GetNodeById(instPtr->nodeList, srcId);
|
||||
if (node == NULL)
|
||||
{
|
||||
node = L2_AppendNode(instPtr->nodeList, srcId, L2_NODE_MEMBER);
|
||||
if (node == NULL)
|
||||
{
|
||||
DBG_ERROR("Failed to append new node [id: %" PRId8 "]", srcId);
|
||||
Status = ENOMEM;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Update node info.
|
||||
float nodePos;
|
||||
L2_FrameGetChunk(msg, L2_MSG_CFM_SRC_POSX, L2_MSG_CFM_SRC_POSX_LEN, &nodePos);
|
||||
node->nodeInfo.pos.x = (double)nodePos;
|
||||
L2_FrameGetChunk(msg, L2_MSG_CFM_SRC_POSY, L2_MSG_CFM_SRC_POSY_LEN, &nodePos);
|
||||
node->nodeInfo.pos.y = (double)nodePos;
|
||||
L2_FrameGetChunk(msg, L2_MSG_CFM_SRC_POSZ, L2_MSG_CFM_SRC_POSZ_LEN, &nodePos);
|
||||
node->nodeInfo.pos.z = (double)nodePos;
|
||||
float nodeSpeed;
|
||||
L2_FrameGetChunk(msg, L2_MSG_CFM_SRC_SPEEDX, L2_MSG_CFM_SRC_SPEEDX_LEN, &nodeSpeed);
|
||||
node->nodeInfo.speed.x = (double)nodePos;
|
||||
L2_FrameGetChunk(msg, L2_MSG_CFM_SRC_SPEEDY, L2_MSG_CFM_SRC_SPEEDY_LEN, &nodeSpeed);
|
||||
node->nodeInfo.speed.y = (double)nodePos;
|
||||
L2_FrameGetChunk(msg, L2_MSG_CFM_SRC_SPEEDZ, L2_MSG_CFM_SRC_SPEEDZ_LEN, &nodeSpeed);
|
||||
node->nodeInfo.speed.z = (double)nodePos;
|
||||
|
||||
// Reset node ttl
|
||||
node->ttlCnt = 0;
|
||||
|
||||
// Calculate time deviation
|
||||
uint32_t frameNum, slotNum = 0;
|
||||
L2_FrameGetChunk(msg, L2_MSG_FRAME_NUM, L2_MSG_FRAME_NUM_LEN, &frameNum);
|
||||
L2_FrameGetChunk(msg, L2_MSG_SLOT_NUM, L2_MSG_SLOT_NUM_LEN, &slotNum);
|
||||
Status = L2_GetTimeDeviation(instPtr, frameNum, slotNum, true, &(instPtr->log.timeDev));
|
||||
if (Status != SUCCESS)
|
||||
{
|
||||
DBG_ERROR("Failed to compute time deviation.\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (L2_GetNodeType(instPtr) != L2_NODE_HEAD)
|
||||
{
|
||||
// check if net setup finished.
|
||||
if (L2_isCxn2Net(instPtr) == false)
|
||||
{
|
||||
// Assert Net-Setup Done.
|
||||
L2_EVENT l2Event;
|
||||
l2Event.event = L2_EV_NET_SETUP_DONE;
|
||||
l2Event.msg = NULL;
|
||||
AssertL2Event(instPtr, &l2Event);
|
||||
|
||||
// Assert update routine event...
|
||||
L2_RTNE_CONFIG newRtneConfig = {0};
|
||||
L2_EVENT rtneUpEvent =
|
||||
{
|
||||
.event = L2_ROUTINE_UPDATE,
|
||||
.msg = &newRtneConfig
|
||||
};
|
||||
newRtneConfig.rtneTable = initTable;
|
||||
newRtneConfig.rtnePrd = ARRAY_SIZE(initTable);
|
||||
AssertL2Event(instPtr, &rtneUpEvent);
|
||||
}
|
||||
PendCfmAck(instPtr->scanFSM);
|
||||
// Time sync.
|
||||
L2_TimeAdjust(instPtr, &(instPtr->log.timeDev));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (L2_GetMainState(instPtr) == L2_INIT_STATE
|
||||
&& L2_GetNodeListLen(instPtr->nodeList) >= instPtr->config.netScale - 1)
|
||||
{
|
||||
// Assert Net-Setup Done.
|
||||
L2_EVENT l2Event;
|
||||
L2_NODE_STATE newState = L2_NORMAL_STATE;
|
||||
l2Event.event = L2_EV_MAIN_STATE_UPDATE;
|
||||
l2Event.msg = &newState;
|
||||
AssertL2Event(instPtr, &l2Event);
|
||||
}
|
||||
}
|
||||
|
||||
// Get data payload
|
||||
uint32_t dataId;
|
||||
L2_FrameGetChunk(msg, L2_MSG_CFM_PAYLOAD_ID, L2_MSG_CFM_PAYLOAD_ID_LEN, &dataId);
|
||||
|
||||
if (L2_GetNodeType(instPtr) == L2_NODE_HEAD)
|
||||
{
|
||||
SysMonitor_UpdateRecvPayload(msg + L2_MSG_CFM_PAYLOAD, dataId, PAYLOAD_LEN_FLJ_RX);
|
||||
}
|
||||
else
|
||||
{
|
||||
SysMonitor_UpdateRecvPayload(msg + L2_MSG_CFM_PAYLOAD, dataId, PAYLOAD_LEN_LJ_RX);
|
||||
}
|
||||
|
||||
// Logging...
|
||||
memcpy(instPtr->log.rxLog.data, msg, L2_CMF_PACK_LEN);
|
||||
instPtr->log.rxLog.dataId = dataId;
|
||||
|
||||
Status = SUCCESS;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
DBG_ERROR("Unsupported frame type: %" PRId8 ".\n", frameType);
|
||||
Status = EUNEXP;
|
||||
break;
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Initialize scan FSM.
|
||||
*
|
||||
* @param instPtr
|
||||
*
|
||||
* @return
|
||||
*
|
||||
******************************************************************************/
|
||||
int32_t L2_Scan_Init(L2_SCAN_FSM **scanFSMPtr)
|
||||
{
|
||||
ASSERT(scanFSMPtr != NULL);
|
||||
*scanFSMPtr = (L2_SCAN_FSM *)malloc(sizeof(L2_SCAN_FSM));
|
||||
if (*scanFSMPtr == NULL)
|
||||
{
|
||||
DBG_ERROR("Failed to allocate memory for scanFsmPtr.\n");
|
||||
return ENOMEM;
|
||||
}
|
||||
L2_Scan_Reset(*scanFSMPtr);
|
||||
(*scanFSMPtr)->beamNo = 0;
|
||||
(*scanFSMPtr)->tableNo = 0;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Reset ScanNet FSM
|
||||
*
|
||||
* @param scanFsmPtr a pointer to scan net finite state machine
|
||||
*
|
||||
* @return NONE
|
||||
*
|
||||
******************************************************************************/
|
||||
void L2_Scan_Reset(L2_SCAN_FSM *scanFSMPtr)
|
||||
{
|
||||
ASSERT(scanFSMPtr != NULL);
|
||||
scanFSMPtr->isLocked = false;
|
||||
scanFSMPtr->isAdvRecvd = false;
|
||||
scanFSMPtr->isAckPending = false;
|
||||
scanFSMPtr->scanCnt = 0;
|
||||
scanFSMPtr->advTimeout = 0;
|
||||
scanFSMPtr->cfmTimeout = 0;
|
||||
scanFSMPtr->scanStage = L2_SCAN_NONE_STAGE;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Destroy ScanNet FSM, free memory
|
||||
*
|
||||
* @param scanFsmPtr a pointer to scan net finite state machine
|
||||
*
|
||||
* @return NONE
|
||||
*
|
||||
******************************************************************************/
|
||||
void L2_Scan_Destroy(L2_SCAN_FSM *scanFSMPtr)
|
||||
{
|
||||
free(scanFSMPtr);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Refresh scan beam table.
|
||||
*
|
||||
* @param instPtr a pointer to linklayer layer instance
|
||||
*
|
||||
* @return NONE
|
||||
*
|
||||
******************************************************************************/
|
||||
void L2_Scan_RefreashScanTable(L2_INST *instPtr)
|
||||
{
|
||||
ASSERT(instPtr != NULL);
|
||||
L2_SCAN_FSM *scanFsmPtr = instPtr->scanFSM;
|
||||
PHY_INST *phyRef = instPtr->config.phyInstPtr;
|
||||
if (scanFsmPtr->tableNo == 0)
|
||||
{
|
||||
Phy_SetBeamTable(phyRef, antNrrwPattern_0, scanFsmPtr->beamNo);
|
||||
scanFsmPtr->tableNo = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
Phy_SetBeamTable(phyRef, antNrrwPattern_1, scanFsmPtr->beamNo);
|
||||
scanFsmPtr->tableNo = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Execute a member node scan net procedure.
|
||||
*
|
||||
* @param instPtr a pointer to linklayer layer instance
|
||||
*
|
||||
* @return used slot (5ms slot).
|
||||
*
|
||||
******************************************************************************/
|
||||
int32_t L2_Scan_Proc(L2_INST *instPtr)
|
||||
{
|
||||
L2_SCAN_FSM *scanFSM = instPtr->scanFSM;
|
||||
if (L2_GetNodeType(instPtr) == L2_NODE_HEAD)
|
||||
{
|
||||
DBG_ERROR("Only member node needs to execute L2_Scan_Proc. \n");
|
||||
return FAILURE;
|
||||
}
|
||||
int32_t Status;
|
||||
DBG_INFO("-------- ScanNet Process --------\n");
|
||||
switch (scanFSM->scanStage)
|
||||
{
|
||||
case L2_SCAN_NONE_STAGE:
|
||||
/* Start Scan. */
|
||||
StageUpdate(scanFSM, L2_SCAN_INIT_STAGE);
|
||||
Status = Scan_InitScanHandler(instPtr);
|
||||
break;
|
||||
case L2_SCAN_INIT_STAGE:
|
||||
Status = Scan_InitScanHandler(instPtr);
|
||||
break;
|
||||
case L2_SCAN_ADV_STAGE:
|
||||
Status = Scan_AdvHandler(instPtr);
|
||||
break;
|
||||
case L2_SCAN_CFM_STAGE:
|
||||
Status = Scan_CfmHandler(instPtr);
|
||||
break;
|
||||
default:
|
||||
DBG_ERROR("Unexpected scan net stage: %" PRId8 ".\n", scanFSM->scanStage);
|
||||
Status = FAILURE;
|
||||
break;
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief Execute a scan net Routine procedure.
|
||||
*
|
||||
* @param rtneEntry Routine configuration
|
||||
*
|
||||
* @return used slot (5ms slot).
|
||||
*
|
||||
******************************************************************************/
|
||||
int32_t L2_Scan_Routine(L2_INST *instPtr, const L2_RTNE_TABLE_ENTRY *rtneEntry)
|
||||
{
|
||||
ASSERT(instPtr != NULL);
|
||||
L2_TOR_TYPE torState;
|
||||
int32_t Status;
|
||||
const NODE_ENTRY *commNode;
|
||||
PHY_INST *phyRef = instPtr->config.phyInstPtr;
|
||||
DBG_INFO("-------- Scan Routine --------\n");
|
||||
|
||||
if (rtneEntry->slotSeq != 0)
|
||||
{
|
||||
return SUCCESS; // skip
|
||||
}
|
||||
|
||||
if (L2_GetNodeType(instPtr) != L2_NODE_HEAD)
|
||||
{
|
||||
if (rtneEntry->dst == L2_GetNodeId(instPtr) || rtneEntry->dst == L2_BROADCAST_ID)
|
||||
{
|
||||
torState = L2_TOR_RX;
|
||||
commNode = L2_GetNodeById(instPtr->nodeList, rtneEntry->src);
|
||||
}
|
||||
else if (rtneEntry->src == L2_GetNodeId(instPtr) || rtneEntry->src == L2_BROADCAST_ID)
|
||||
{
|
||||
torState = L2_TOR_TX;
|
||||
commNode = L2_GetNodeById(instPtr->nodeList, rtneEntry->dst);
|
||||
}
|
||||
else
|
||||
{
|
||||
torState = L2_TOR_SUSPEND;
|
||||
}
|
||||
|
||||
// Setup antenna beam
|
||||
Phy_SetBeamWidth(phyRef, PHY_ANT_BEAM_16);
|
||||
instPtr->log.lastBeamWidth = PHY_ANT_BEAM_16;
|
||||
if (commNode != NULL)
|
||||
{
|
||||
Phy_SetBeamNo(phyRef, commNode->nodeInfo.beamNo, PHY_ANT_BEAM_16);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rtneEntry->dst == L2_GetNodeId(instPtr))
|
||||
{
|
||||
torState = L2_TOR_RX;
|
||||
}
|
||||
else if (rtneEntry->src == L2_GetNodeId(instPtr))
|
||||
{
|
||||
torState = L2_TOR_TX;
|
||||
}
|
||||
else
|
||||
{
|
||||
torState = L2_TOR_SUSPEND;
|
||||
}
|
||||
// Setup antenna beam
|
||||
Phy_SetBeamWidth(phyRef, PHY_ANT_BEAM_120);
|
||||
instPtr->log.lastBeamWidth = PHY_ANT_BEAM_120;
|
||||
}
|
||||
|
||||
switch (rtneEntry->slotType)
|
||||
{
|
||||
case L2_SLOT_SCAN:
|
||||
if (L2_GetNodeType(instPtr) != L2_NODE_HEAD && torState == L2_TOR_TX)
|
||||
{
|
||||
DBG_ERROR("Only head node can send init-scan Frame.\n");
|
||||
Status = FAILURE;
|
||||
goto routine_err;
|
||||
}
|
||||
L2_SetupNextSlot(instPtr, torState, L2_SCAN_FRAME);
|
||||
break;
|
||||
|
||||
case L2_SLOT_ADVERTISE:
|
||||
if (torState == L2_TOR_TX)
|
||||
{
|
||||
if (L2_GetNodeType(instPtr) != L2_NODE_HEAD)
|
||||
{
|
||||
DBG_ERROR("Only head node can send ADV Frame.\n");
|
||||
Status = FAILURE;
|
||||
goto routine_err;
|
||||
}
|
||||
memset(instPtr->sendPktData, 0xAA, L2_PACK_LEN_MAX);
|
||||
if (ScanMsg_Packing(instPtr, L2_ADV_FRAME, rtneEntry->dst) != SUCCESS)
|
||||
{
|
||||
Status = FAILURE;
|
||||
goto routine_err;
|
||||
}
|
||||
}
|
||||
/* Antenna setting (reserved.) */
|
||||
L2_SetupNextSlot(instPtr, torState, L2_ADV_FRAME);
|
||||
break;
|
||||
|
||||
case L2_SLOT_CONFIRM:
|
||||
if (torState == L2_TOR_TX)
|
||||
{
|
||||
if (L2_GetNodeType(instPtr) != L2_NODE_HEAD)
|
||||
{
|
||||
if (instPtr->scanFSM->isAckPending == false)
|
||||
{
|
||||
DBG_INFO("Member node has no pending CFM-Ack frame.\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
memset(instPtr->sendPktData, 0xAA, L2_PACK_LEN_MAX);
|
||||
if (ScanMsg_Packing(instPtr, L2_CFM_FRAME, rtneEntry->dst) != SUCCESS)
|
||||
{
|
||||
Status = FAILURE;
|
||||
goto routine_err;
|
||||
}
|
||||
}
|
||||
/* Antenna setting (reserved.) */
|
||||
L2_SetupNextSlot(instPtr, torState, L2_CFM_FRAME);
|
||||
break;
|
||||
default:
|
||||
DBG_ERROR("Cannot start a routine for slot type [%" PRId8 "] properly.\n", rtneEntry->slotType);
|
||||
Status = FAILURE;
|
||||
goto routine_err;
|
||||
}
|
||||
return SUCCESS;
|
||||
routine_err:
|
||||
return Status;
|
||||
}
|
||||
|
||||
/** @} LinkLayer_Scan*/
|
||||
/** @} LinkLayer*/
|
||||
@@ -0,0 +1,438 @@
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @file schdevent.c
|
||||
* @author FanHao ([email protected])
|
||||
* @brief DF Linklayer Event scheduling implementation file.
|
||||
* @version 0.1
|
||||
* @date 2023-05-06
|
||||
*
|
||||
* @copyright Copyright(c) 2024 Beijing Institute of Technology.\n
|
||||
* Lab of Communication and Network
|
||||
*
|
||||
******************************************************************************/
|
||||
/**
|
||||
* @addtogroup LinkLayer
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup LinkLayer_Scheduler
|
||||
* @{
|
||||
*/
|
||||
/***************************** Include Files *********************************/
|
||||
#include <stdlib.h>
|
||||
#include "schdevent.h"
|
||||
#include "link_layer.h"
|
||||
#include "link_layer_types.h"
|
||||
#include "error.h"
|
||||
#include "clist.h"
|
||||
/***************** Macros (Inline Functions) Definitions *********************/
|
||||
/**************************** Type Definitions *******************************/
|
||||
/************************** Variable Definitions *****************************/
|
||||
static L2_SCHD_EVENT util_schdevent;
|
||||
/************************** Function Prototypes ******************************/
|
||||
/**
|
||||
* @brief helper function to free schedule events.
|
||||
*/
|
||||
static void schdevent_free(void *val)
|
||||
{
|
||||
if (val == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
free(((L2_SCHD_EVENT *)val)->l2Event.msg);
|
||||
free(val);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief helper function to match events by ids.
|
||||
*/
|
||||
static int8_t schdevent_compare(void *a, void *b)
|
||||
{
|
||||
ASSERT(a == NULL);
|
||||
ASSERT(b != NULL);
|
||||
register uint32_t idA, idB;
|
||||
idA = ((L2_SCHD_EVENT *)a)->eventId;
|
||||
idB = ((L2_SCHD_EVENT *)b)->eventId;
|
||||
if (idA == idB)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (idA < idB)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Creat a schedule event pool.
|
||||
*
|
||||
* @param schdPool a pointer to schedule pool instance.
|
||||
*
|
||||
* @return SUCCESS
|
||||
*
|
||||
******************************************************************************/
|
||||
int32_t L2_CreateSchedEventPool(L2_SCHD_POOL **schdPool)
|
||||
{
|
||||
(*schdPool) = malloc(sizeof(L2_SCHD_POOL));
|
||||
if (*schdPool == NULL)
|
||||
{
|
||||
DBG_ERROR("Failed to allocated memory for schdPool.\n");
|
||||
return ENOMEM;
|
||||
}
|
||||
(*schdPool)->schdList = clist_new();
|
||||
if ((*schdPool)->schdList == NULL)
|
||||
{
|
||||
DBG_ERROR("Failed to allocated memory for schdPool->schdList.\n");
|
||||
free(*schdPool);
|
||||
return ENOMEM;
|
||||
}
|
||||
(*schdPool)->schdList->free = schdevent_free;
|
||||
(*schdPool)->schdList->compare = schdevent_compare;
|
||||
(*schdPool)->envCnt = 0;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Clear schedule event pool, delete all events in pool and
|
||||
* free allocated memory.
|
||||
*
|
||||
* @param schdPool a pointer to schedule pool instance.
|
||||
*
|
||||
* @return SUCCESS
|
||||
*
|
||||
******************************************************************************/
|
||||
void L2_ClearSchedEventPool(L2_SCHD_POOL *schdPool)
|
||||
{
|
||||
ASSERT(schdPool != NULL);
|
||||
clist_clear(schdPool->schdList);
|
||||
schdPool->envCnt = 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Completely destroy schedule event pool.
|
||||
*
|
||||
* @param schdPool a pointer to schedule pool instance.
|
||||
*
|
||||
* @return SUCCESS
|
||||
*
|
||||
******************************************************************************/
|
||||
void L2_DestroySchedEventPool(L2_SCHD_POOL *schdPool)
|
||||
{
|
||||
if (schdPool == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
clist_destroy(schdPool->schdList);
|
||||
free(schdPool);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Creat a new schedule event, register event in schedule event pool.
|
||||
*
|
||||
* @param schdPool a pointer to schedule pool instance.
|
||||
* @param event event type of the new schedule event.
|
||||
* @param isVolatile event type of the new schedule event.
|
||||
*
|
||||
* @return NULL error occurred
|
||||
* Pointer to schedule event.
|
||||
*
|
||||
******************************************************************************/
|
||||
L2_SCHD_EVENT *L2_CreatNewSchdEvent(L2_SCHD_POOL *schdPool, L2_EVENT_TYPE event, bool isVolatile)
|
||||
{
|
||||
ASSERT(schdPool != NULL);
|
||||
if (event < L2_EV_SCAN_PROC_DONE || event > L2_ROUTINE_UPDATE)
|
||||
{
|
||||
DBG_ERROR("Unknown event type: %" PRId8 ".\n", event);
|
||||
return NULL;
|
||||
}
|
||||
L2_SCHD_EVENT *schdEvent = (L2_SCHD_EVENT *)malloc(sizeof(L2_SCHD_EVENT));
|
||||
if (schdEvent == NULL)
|
||||
{
|
||||
DBG_ERROR("Failed to allocate schedule event.\n");
|
||||
return NULL;
|
||||
}
|
||||
clist_node_t *node = clist_node_new(schdEvent);
|
||||
if (node == NULL)
|
||||
{
|
||||
DBG_ERROR("Failed to allocate schedule event list node.\n");
|
||||
free(schdEvent);
|
||||
return NULL;
|
||||
}
|
||||
schdEvent->eventId = schdPool->envCnt++;
|
||||
schdEvent->occurCnt = 0;
|
||||
schdEvent->l2Event.event = event;
|
||||
schdEvent->l2Event.msg = NULL;
|
||||
schdEvent->isSchd = false;
|
||||
schdEvent->isVolatile = isVolatile;
|
||||
schdEvent->schdSlot = L2_SLOTNO_NONE;
|
||||
schdEvent->schdFrame = L2_FRAMENO_NONE;
|
||||
clist_rpush(schdPool->schdList, node);
|
||||
return schdEvent;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Get a schedule event by its id.
|
||||
*
|
||||
* @param schdPool a pointer to schedule pool instance.
|
||||
* @param id ID of the event
|
||||
*
|
||||
* @return NULL
|
||||
* Pointer to the schedule event.
|
||||
*
|
||||
******************************************************************************/
|
||||
L2_SCHD_EVENT *L2_GetEventById(L2_SCHD_POOL *schdPool, uint32_t id)
|
||||
{
|
||||
ASSERT(schdPool != NULL);
|
||||
util_schdevent.eventId = id;
|
||||
clist_node_t *node = clist_find(schdPool->schdList, &util_schdevent);
|
||||
if (node != NULL)
|
||||
{
|
||||
DBG_WARNING("Event with id=%" PRIu32 ", dose not exist.\n", id);
|
||||
return NULL;
|
||||
}
|
||||
return ((L2_SCHD_EVENT *)node->val);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Delete a schedule event, remove the event from event pool,
|
||||
* release memory.
|
||||
*
|
||||
* @param schdPool a pointer to schedule pool instance.
|
||||
* @param id ID of the event
|
||||
*
|
||||
* @return SUCCESS
|
||||
* error code
|
||||
*
|
||||
******************************************************************************/
|
||||
int32_t L2_DeleteSchdEventById(L2_SCHD_POOL *schdPool, uint32_t id)
|
||||
{
|
||||
ASSERT(schdPool != NULL);
|
||||
util_schdevent.eventId = id;
|
||||
clist_node_t *node = clist_find(schdPool->schdList, &util_schdevent);
|
||||
if (node != NULL)
|
||||
{
|
||||
DBG_ERROR("Event with id=%" PRIu32 ", dose not exist.\n", id);
|
||||
return EIGNORE;
|
||||
}
|
||||
clist_remove(schdPool->schdList, node);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Schedule a event at a specific time(indexed by frame and slot number)
|
||||
*
|
||||
* @param instPtr a pointer to linklayer instance
|
||||
* @param schdEvent pointer to the schedule event.
|
||||
* @param frameNum schedule frame number
|
||||
* @param slotNum schedule slot number
|
||||
*
|
||||
* @return FAILURE, event has already been scheduled/schedule time not allowed.
|
||||
* SUCCESS
|
||||
*
|
||||
******************************************************************************/
|
||||
int32_t L2_ScheduleEventAt(L2_INST *instPtr, L2_SCHD_EVENT *schdEvent, uint32_t frameNum, uint32_t slotNum)
|
||||
{
|
||||
ASSERT(schdEvent != NULL);
|
||||
if (L2_isEventScheduled(schdEvent) == true)
|
||||
{
|
||||
DBG_ERROR("Event %" PRIu32 " has already been scheduled.\n", schdEvent->eventId);
|
||||
return FAILURE;
|
||||
}
|
||||
if (frameNum <= L2_GetCurrentFrameNum(instPtr) && slotNum < L2_GetCurrentSlotNum(instPtr))
|
||||
{
|
||||
DBG_ERROR("Cannot schedule event %" PRIu32 " to the past(current: [%" PRIu32 "-%" PRIu32 "], schedule: [%" PRIu32 "-%" PRIu32 "]).\n",
|
||||
schdEvent->eventId, L2_GetCurrentFrameNum(instPtr), L2_GetCurrentSlotNum(instPtr), frameNum, slotNum);
|
||||
return FAILURE;
|
||||
}
|
||||
DBG_INFO("Schedule event (type:%" PRIu8 ") [%" PRIu32 "] at %" PRIu32 "-%" PRIu32 ".\n",
|
||||
schdEvent->l2Event.event, schdEvent->eventId,
|
||||
frameNum, slotNum);
|
||||
schdEvent->isSchd = true;
|
||||
schdEvent->schdFrame = frameNum;
|
||||
schdEvent->schdSlot = slotNum;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Schedule a event after a specific time period.
|
||||
*
|
||||
* @param instPtr a pointer to linklayer instance
|
||||
* @param schdEvent pointer to the schedule event.
|
||||
* @param numSlots how many slot later the event should be scheduled
|
||||
*
|
||||
* @return FAILURE, event has already been scheduled/schedule time not allowed.
|
||||
* SUCCESS
|
||||
*
|
||||
******************************************************************************/
|
||||
int32_t L2_ScheduleEventAfter(L2_INST *instPtr, L2_SCHD_EVENT *schdEvent, uint32_t numSlots)
|
||||
{
|
||||
ASSERT(schdEvent != NULL);
|
||||
if (L2_isEventScheduled(schdEvent) == true)
|
||||
{
|
||||
DBG_ERROR("Event %" PRIu32 " has already been scheduled.\n", schdEvent->eventId);
|
||||
return FAILURE;
|
||||
}
|
||||
uint32_t frameNum = L2_GetCurrentFrameNum(instPtr) + (numSlots / L2_SLOTS_PER_FRAME);
|
||||
uint32_t slotNum = L2_GetCurrentSlotNum(instPtr) + (numSlots % L2_SLOTS_PER_FRAME);
|
||||
return L2_ScheduleEventAt(instPtr, schdEvent, frameNum, slotNum);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Reschedule a event at a specific time(indexed by frame and slot number)
|
||||
*
|
||||
* @param instPtr a pointer to linklayer instance
|
||||
* @param schdEvent pointer to the schedule event.
|
||||
* @param frameNum schedule frame number
|
||||
* @param slotNum schedule slot number
|
||||
*
|
||||
* @return FAILURE, event has already been scheduled/schedule time not allowed.
|
||||
* SUCCESS
|
||||
*
|
||||
******************************************************************************/
|
||||
int32_t L2_RescheduleEventAt(L2_INST *instPtr, L2_SCHD_EVENT *schdEvent, uint32_t frameNum, uint32_t slotNum)
|
||||
{
|
||||
ASSERT(schdEvent != NULL);
|
||||
if (schdEvent->isSchd == false)
|
||||
{
|
||||
DBG_WARNING("Event %" PRIu32 " has not been scheduled yet.\n", schdEvent->eventId);
|
||||
}
|
||||
schdEvent->isSchd = false;
|
||||
return L2_ScheduleEventAt(instPtr, schdEvent, frameNum, slotNum);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Reschedule a event after a specific time period.
|
||||
*
|
||||
* @param instPtr a pointer to linklayer instance
|
||||
* @param schdEvent pointer to the schedule event.
|
||||
* @param numSlots how many slot later the event should be scheduled
|
||||
*
|
||||
* @return FAILURE, event has already been scheduled/schedule time not allowed.
|
||||
* SUCCESS
|
||||
*
|
||||
******************************************************************************/
|
||||
int32_t L2_RescheduleEventAfter(L2_INST *instPtr, L2_SCHD_EVENT *schdEvent, uint32_t numSlots)
|
||||
{
|
||||
ASSERT(schdEvent != NULL);
|
||||
if (schdEvent->isSchd == false)
|
||||
{
|
||||
DBG_WARNING("Event %" PRIu32 " has not been scheduled yet.\n", schdEvent->eventId);
|
||||
}
|
||||
return L2_ScheduleEventAfter(instPtr, schdEvent, numSlots);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Check and excute schedule event in event pool illiterate.
|
||||
*
|
||||
* @param instPtr a pointer to linklayer instance
|
||||
*
|
||||
* @return NONE.
|
||||
*
|
||||
******************************************************************************/
|
||||
void L2_EventPoolHandler(L2_INST *instPtr)
|
||||
{
|
||||
ASSERT(instPtr != NULL);
|
||||
clist_node_t *node;
|
||||
L2_SCHD_EVENT *event;
|
||||
L2_SCHD_POOL *pool = instPtr->schdEventPool;
|
||||
clist_iterator_t *iter = clist_iterator_new(pool->schdList, LIST_HEAD);
|
||||
if (iter == NULL)
|
||||
{
|
||||
DBG_ERROR("Failed to initialize schedule event pool iteration.\n");
|
||||
return;
|
||||
}
|
||||
while ((node = clist_iterator_next(iter)))
|
||||
{
|
||||
event = (L2_SCHD_EVENT *)node->val;
|
||||
if (L2_isEventScheduled(event))
|
||||
{
|
||||
if (event->schdFrame == L2_GetCurrentFrameNum(instPtr) && event->schdSlot == L2_GetCurrentSlotNum(instPtr))
|
||||
{
|
||||
DBG_INFO("Asserting scheduled event [%" PRIu32 "].\n", event->eventId);
|
||||
AssertL2Event(instPtr, &(event->l2Event));
|
||||
if (event->isVolatile == true)
|
||||
{
|
||||
DBG_INFO("Deleting scheduled event [%" PRIu32 "], since it is volatile.\n", event->eventId);
|
||||
clist_remove(pool->schdList, node);
|
||||
}
|
||||
else
|
||||
{
|
||||
event->occurCnt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
clist_iterator_destroy(iter);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Append extra message content to specific schedule event.
|
||||
*
|
||||
* @param schdEvent pointer to the schedule event.
|
||||
* msg pointer to the append content.
|
||||
*
|
||||
* @return SUCCESS.
|
||||
* error code.
|
||||
*
|
||||
******************************************************************************/
|
||||
inline void L2_SchdEventAppendMsg(L2_SCHD_EVENT *schdEvent, void *msg)
|
||||
{
|
||||
ASSERT(schdEvent != NULL);
|
||||
schdEvent->l2Event.msg = msg;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Cancel a scheduled event.
|
||||
*
|
||||
* @param schdEvent pointer to the schedule event.
|
||||
*
|
||||
* @return SUCCESS.
|
||||
*
|
||||
******************************************************************************/
|
||||
inline int32_t L2_CancelEvent(L2_SCHD_EVENT *schdEvent)
|
||||
{
|
||||
ASSERT(schdEvent != NULL);
|
||||
if (schdEvent->isSchd == false)
|
||||
{
|
||||
DBG_WARNING("Event %" PRIu32 " has not been scheduled yet.\n", schdEvent->eventId);
|
||||
}
|
||||
schdEvent->isSchd = false;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Check if the event was scheduled.
|
||||
*
|
||||
* @param schdEvent pointer to the schedule event.
|
||||
*
|
||||
* @return true.
|
||||
* false.
|
||||
*
|
||||
******************************************************************************/
|
||||
inline bool L2_isEventScheduled(const L2_SCHD_EVENT *schdEvent)
|
||||
{
|
||||
ASSERT(schdEvent != NULL);
|
||||
return schdEvent->isSchd;
|
||||
}
|
||||
|
||||
/** @} LinkLayer_Scheduler*/
|
||||
/** @} LinkLayer*/
|
||||
@@ -0,0 +1,76 @@
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @file schdevent.c
|
||||
* @author FanHao ([email protected])
|
||||
* @brief DF Linklayer Event scheduling header file.
|
||||
* @version 0.1
|
||||
* @date 2023-05-06
|
||||
*
|
||||
* @copyright Copyright(c) 2024 Beijing Institute of Technology.\n
|
||||
* Lab of Communication and Network
|
||||
*
|
||||
******************************************************************************/
|
||||
/**
|
||||
* @addtogroup LinkLayer
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup LinkLayer_Scheduler
|
||||
* @{
|
||||
*/
|
||||
#ifndef SCHDEVENT_H_
|
||||
#define SCHDEVENT_H_
|
||||
|
||||
#define SCHDEVENT_ID_NONE UINT32_MAX
|
||||
/***************************** Include Files *********************************/
|
||||
#include <stdlib.h>
|
||||
#include "link_layer_types.h"
|
||||
#include "error.h"
|
||||
#include "clist.h"
|
||||
/***************** Macros (Inline Functions) Definitions *********************/
|
||||
/**************************** Type Definitions *******************************/
|
||||
/**
|
||||
* @struct L2_SCHD_EVENT
|
||||
* @brief Linklayer scheduled event descriptor
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
bool isSchd;
|
||||
bool isVolatile;
|
||||
L2_EVENT l2Event;
|
||||
uint32_t eventId;
|
||||
uint32_t occurCnt;
|
||||
uint32_t schdFrame;
|
||||
uint32_t schdSlot;
|
||||
} L2_SCHD_EVENT;
|
||||
|
||||
/**
|
||||
* @struct L2_SCHD_POOL
|
||||
* @brief Linklayer schedule event pool instance
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
clist_t *schdList;
|
||||
uint32_t envCnt;
|
||||
} L2_SCHD_POOL;
|
||||
|
||||
/************************** Variable Definitions *****************************/
|
||||
/************************** Function Prototypes ******************************/
|
||||
// Scheduling Event
|
||||
int32_t L2_CreateSchedEventPool(L2_SCHD_POOL **schdPool);
|
||||
void L2_ClearSchedEventPool(L2_SCHD_POOL *schdPool);
|
||||
void L2_DestroySchedEventPool(L2_SCHD_POOL *schdPool);
|
||||
|
||||
L2_SCHD_EVENT *L2_CreatNewSchdEvent(L2_SCHD_POOL *schdPool, L2_EVENT_TYPE event, bool isVolatile);
|
||||
L2_SCHD_EVENT *L2_GetEventById(L2_SCHD_POOL *schdPool, uint32_t id);
|
||||
int32_t L2_DeleteSchdEventById(L2_SCHD_POOL *schdPool, uint32_t id);
|
||||
|
||||
void L2_SchdEventAppendMsg(L2_SCHD_EVENT *schdEvent, void *msg);
|
||||
bool L2_isEventScheduled(const L2_SCHD_EVENT *schdEvent);
|
||||
int32_t L2_CancelEvent(L2_SCHD_EVENT *schdEvent);
|
||||
|
||||
#endif // SCHDEVENT_H_
|
||||
|
||||
/** @} LinkLayer_Scheduler*/
|
||||
/** @} LinkLayer*/
|
||||
@@ -0,0 +1,440 @@
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @file service.c
|
||||
* @author FanHao ([email protected])
|
||||
* @brief DF Linklayer service implementation file.
|
||||
* @version 0.0
|
||||
* @date 2023-05-06
|
||||
*
|
||||
* @copyright Copyright(c) 2024 Beijing Institute of Technology.\n
|
||||
* Lab of Communication and Network
|
||||
*
|
||||
******************************************************************************/
|
||||
/**
|
||||
* @addtogroup LinkLayer
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup LinkLayer_Service
|
||||
* @{
|
||||
*/
|
||||
/***************************** Include Files *********************************/
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include "link_layer.h"
|
||||
#include "link_layer_types.h"
|
||||
#include "msg_def.h"
|
||||
#include "error.h"
|
||||
#include "common.h"
|
||||
#include "circ_queue.h"
|
||||
#ifndef EMULATION
|
||||
#include "../config/app_config.h"
|
||||
#endif
|
||||
/************************** Constant Definitions *****************************/
|
||||
/***************** Macros (Inline Functions) Definitions *********************/
|
||||
/**************************** Type Definitions *******************************/
|
||||
/************************** Function Prototypes ******************************/
|
||||
static int32_t Service_Packing(L2_INST *instPtr, L2_FRAME_TYPE type, uint8_t dstId);
|
||||
/************************** Variable Definitions *****************************/
|
||||
|
||||
static uint8_t testData[L2_PACK_LEN_MAX] =
|
||||
{
|
||||
0x39, 0x85, 0x02, 0xF0, 0xC7, 0x6A, 0xE8, 0xB4, 0xE7, 0xAB, 0xC9, 0xDC, 0x0B, 0x41, 0x42, 0xE0,
|
||||
0xED, 0x21, 0x07, 0x62, 0x4E, 0x80, 0xA0, 0xE1, 0xAC, 0x77, 0x9B, 0x1F, 0x48, 0x0B, 0x58, 0xB9,
|
||||
0x45, 0xA5, 0x24, 0xEF, 0xF3, 0x71, 0x2E, 0x84, 0x6C, 0x22, 0xB3, 0x05, 0xEB, 0x75, 0xF2, 0x0B,
|
||||
0x45, 0x73, 0x01, 0xA8, 0x1E, 0x00, 0x21, 0x3E, 0x03, 0x86, 0x55, 0x59, 0x98, 0x5C, 0x61, 0xA2,
|
||||
0xE8, 0x20, 0x0E, 0x7A, 0xD5, 0x72, 0xAF, 0xF4, 0xBC, 0xB3, 0x6F, 0xFE, 0xB3, 0x78, 0x6A, 0x59,
|
||||
0x73, 0xBD, 0x97, 0xBE, 0x44, 0xA4, 0x9B, 0x71, 0x11, 0x45, 0x37, 0xFE, 0xB3, 0x71, 0xEF, 0x1E,
|
||||
0x3A, 0x2B, 0x58, 0x07, 0xF6, 0x01, 0x1C, 0x73, 0x28, 0x11, 0xA8, 0x15, 0xA2, 0x58, 0x32, 0x2E,
|
||||
0x7D, 0x35, 0x9C, 0xE4, 0x98, 0x7F, 0x9C, 0x81, 0x32, 0xAA, 0xC4, 0x87, 0x16, 0x26, 0x23, 0x95,
|
||||
0x57, 0xC9, 0xD4, 0x34, 0xCE, 0x63, 0x78, 0x7E, 0xD4, 0x3C, 0x16, 0x1D, 0x80, 0xC0, 0x55, 0xBF,
|
||||
0xB5, 0xD6, 0x0C, 0xA5, 0xB9, 0x0A, 0x14, 0x5B, 0x4D, 0x52, 0xF2, 0xA9, 0x7A, 0x08, 0x67, 0x8E,
|
||||
0xEB, 0x67, 0x34, 0x7F, 0x7A, 0x35, 0xAF, 0xD9, 0x07, 0x52, 0x30, 0x38, 0x70, 0xC9, 0x41, 0xF8,
|
||||
0x36, 0x61, 0x32, 0x72, 0xA4, 0x7A, 0xEA, 0x21, 0xB4, 0xBF, 0xAA, 0xCF, 0x93, 0x4F, 0xE1, 0x5C,
|
||||
0xA0, 0xFB, 0xD0, 0x2B, 0xA3, 0x82, 0x2E, 0x69, 0x7D, 0xB7, 0x76, 0x88, 0xF7, 0x5C, 0xF3, 0x82,
|
||||
0xC6, 0x6D, 0x49, 0x92, 0x64, 0x88, 0x9A, 0x43, 0xEE, 0xE9, 0x93, 0xC3, 0x70, 0x50, 0x22, 0xF1,
|
||||
0xD3, 0x2B, 0xCF, 0xA9, 0xE5, 0x69, 0x22, 0xF9, 0xBF, 0x78, 0x9A, 0xA4, 0x5A, 0x3D, 0x2E, 0x2A,
|
||||
0x23, 0xE3, 0x51, 0x8F, 0x1A, 0xC1, 0xAF, 0x47, 0x9C, 0x14, 0xCE, 0xB9, 0xCD, 0xD0, 0x02, 0xB7,
|
||||
0xB8, 0x81, 0xCC, 0x44, 0xE7, 0xA2, 0x6F, 0x32, 0x8C, 0x78, 0x79, 0x10, 0xF3, 0xE1, 0xB0, 0x7C,
|
||||
0xAB, 0x40, 0xDB, 0xF9, 0x99, 0xE7, 0x27, 0x30, 0x53, 0x67, 0x00, 0xE8, 0x33, 0x6D, 0xFC, 0x4D,
|
||||
0xDC, 0xB0, 0xFC, 0x3D, 0xEF, 0x8D, 0x43, 0xAF, 0x7E, 0x41, 0x69, 0xDA, 0xFD, 0xDF, 0x2F, 0xF8,
|
||||
0xEC, 0xFB, 0x6A, 0x65, 0xE7, 0xEC, 0xC7, 0x53, 0x1B, 0x14, 0xDF, 0xBD, 0x0C, 0x54, 0x57, 0xD2,
|
||||
0x56, 0x15, 0xF4, 0x34, 0xE2, 0xFB, 0x12, 0xA0, 0xA2, 0xDE, 0x82, 0xF5, 0x04, 0x81, 0x9B, 0x08,
|
||||
0xB6, 0x8C, 0x7B, 0xE0, 0xAA, 0xDF, 0xC9, 0x92, 0x9D, 0x5F, 0x2D, 0xF7, 0x4A, 0x0B, 0xFF, 0xA5,
|
||||
0xAA, 0xDC, 0xD6, 0x3F, 0x56, 0xB2, 0x6A, 0x3C, 0x6F, 0xAA, 0xAC, 0x84, 0xAC, 0x3F, 0x3D, 0x05,
|
||||
0x96, 0x12, 0x44, 0x39, 0x1C, 0xD1, 0xFA, 0xBE, 0x6B, 0x1A, 0xCD, 0x31, 0x29, 0x41, 0x31, 0xA3,
|
||||
0xA8, 0x0D, 0x87, 0xEB, 0x96, 0x21, 0x39, 0xD6, 0x3B, 0x11, 0x50, 0xB5, 0xFE, 0x44, 0x0E, 0x74,
|
||||
0x31, 0x12, 0xA1, 0x66, 0x49, 0xFD, 0x2D, 0x75, 0x72, 0xF9, 0xC8, 0xD9, 0x6C, 0xC9, 0x11, 0x74,
|
||||
0x2E, 0xEB, 0x20, 0x33, 0x3D, 0x2C, 0x5E, 0xEA, 0x39, 0x31, 0x88, 0xC7, 0xD1, 0x93, 0x95, 0xD8,
|
||||
0x9E, 0x87, 0x93, 0xBC, 0x09, 0x17, 0xC9, 0xA2, 0x59, 0x18, 0x51, 0x8F, 0xBF, 0x55, 0x45, 0x81,
|
||||
0x8D, 0xFD, 0xAF, 0xB2, 0x21, 0xB7, 0xD8, 0xA8, 0x00, 0x2E, 0x70, 0x73, 0x2F, 0x74, 0xBC, 0x61,
|
||||
0x0A, 0x8E, 0xE3, 0x0A, 0x92, 0x82, 0xD2, 0x82, 0xBA, 0xE4, 0x3E, 0x8E, 0xBB, 0xC7, 0xA2, 0x8F,
|
||||
0x68, 0xE1, 0x29, 0x34, 0x7C, 0xB4, 0x22, 0xCF, 0x36, 0x8F, 0x9D, 0x63, 0x9D, 0x04, 0x8F, 0x4A,
|
||||
0xFB, 0x84, 0xBB, 0x6B, 0x97, 0x2C, 0x15, 0xC9, 0x37, 0x4F, 0x40, 0xD7, 0x47, 0x50, 0x39, 0x97
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Packing Service message
|
||||
*
|
||||
* @param instPtr pointer to linklayer instance
|
||||
* type message type.
|
||||
* dstId destination node address.
|
||||
*
|
||||
* @return EPARAM
|
||||
* SUCCESS
|
||||
*
|
||||
******************************************************************************/
|
||||
static int32_t Service_Packing(L2_INST *instPtr, L2_FRAME_TYPE type, uint8_t dstId)
|
||||
{
|
||||
#ifndef DATALINK_ENABLE_BERTEST
|
||||
ASSERT(instPtr != NULL);
|
||||
int32_t Status;
|
||||
uint32_t dataChunk;
|
||||
uint8_t *buff = instPtr->sendPktData;
|
||||
|
||||
// Common section of link layer package
|
||||
dataChunk = L2_GetNextFrameNum(instPtr);
|
||||
L2_FrameInsertChunk(buff, L2_MSG_FRAME_NUM, L2_MSG_FRAME_NUM_LEN, &dataChunk);
|
||||
dataChunk = L2_GetNextSlotNum(instPtr);
|
||||
L2_FrameInsertChunk(buff, L2_MSG_SLOT_NUM, L2_MSG_SLOT_NUM_LEN, &dataChunk);
|
||||
dataChunk = L2_GetNodeId(instPtr);
|
||||
L2_FrameInsertChunk(buff, L2_MSG_SRC_ID, L2_MSG_SRC_ID_LEN, &dataChunk);
|
||||
dataChunk = dstId;
|
||||
L2_FrameInsertChunk(buff, L2_MSG_DST_ID, L2_MSG_DST_ID_LEN, &dataChunk);
|
||||
switch (type)
|
||||
{
|
||||
case L2_SVC_FRAME:
|
||||
{
|
||||
dataChunk = L2_SVC_FRAME;
|
||||
L2_FrameInsertChunk(buff, L2_MSG_TYPE, L2_MSG_TYPE_LEN, &dataChunk);
|
||||
|
||||
SysMonitor_GetSysinfo(&(instPtr->sysInfo));
|
||||
// insert position and speed info
|
||||
L2_FrameInsertChunk(buff, L2_MSG_SVC_SRC_POSX, L2_MSG_SVC_SRC_POSX_LEN, &(instPtr->sysInfo.posX));
|
||||
L2_FrameInsertChunk(buff, L2_MSG_SVC_SRC_POSY, L2_MSG_SVC_SRC_POSY_LEN, &(instPtr->sysInfo.posY));
|
||||
L2_FrameInsertChunk(buff, L2_MSG_SVC_SRC_POSZ, L2_MSG_SVC_SRC_POSZ_LEN, &(instPtr->sysInfo.posZ));
|
||||
L2_FrameInsertChunk(buff, L2_MSG_SVC_SRC_SPEEDX, L2_MSG_SVC_SRC_SPEEDX_LEN, &(instPtr->sysInfo.vX));
|
||||
L2_FrameInsertChunk(buff, L2_MSG_SVC_SRC_SPEEDY, L2_MSG_SVC_SRC_SPEEDY_LEN, &(instPtr->sysInfo.vY));
|
||||
L2_FrameInsertChunk(buff, L2_MSG_SVC_SRC_SPEEDZ, L2_MSG_SVC_SRC_SPEEDZ_LEN, &(instPtr->sysInfo.vZ));
|
||||
|
||||
uint32_t dataId;
|
||||
if (L2_GetNodeType(instPtr) == L2_NODE_HEAD)
|
||||
{
|
||||
SysMonitor_GetSendPayload(buff + L2_MSG_SVC_PAYLOAD, &dataId, PAYLOAD_LEN_FLJ_TX);
|
||||
}
|
||||
else
|
||||
{
|
||||
SysMonitor_GetSendPayload(buff + L2_MSG_SVC_PAYLOAD, &dataId, PAYLOAD_LEN_LJ_TX);
|
||||
}
|
||||
|
||||
L2_FrameInsertChunk(buff, L2_MSG_SVC_PAYLOAD_ID, L2_MSG_SVC_PAYLOAD_ID_LEN, &dataId);
|
||||
if (dataId == DATA_ID_NONE)
|
||||
{
|
||||
L2_FrameInsertChunk(buff, L2_MSG_SVC_PAYLOAD, L2_MSG_SVC_PAYLOAD_LEN, testData);
|
||||
}
|
||||
|
||||
Status = L2_CrcAppend(buff, L2_SVC_PACK_LEN - L2_MSG_SVC_CRC_LEN, L2_MSG_SVC_CRC, L2_CRC16_1021);
|
||||
if (Status != SUCCESS)
|
||||
{
|
||||
DBG_ERROR("Fail to append CRC...\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
memcpy(instPtr->log.txLog.data, buff, L2_SVC_PACK_LEN);
|
||||
instPtr->log.txLog.dataId = dataId;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
DBG_ERROR("Unexpected frame type: %" PRIu8 ".\n", type);
|
||||
return EPARAM;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return SUCCESS;
|
||||
#else
|
||||
DBG_ERROR("Unexpected call of Service_Packing in BER test mode.\n");
|
||||
return EUNEXP;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Handle service received packet. Send data up to MPC
|
||||
*
|
||||
* @param msg A point32_ter the the message frame.
|
||||
*
|
||||
* @return SUCCESS message has been successfully handled.
|
||||
* other error occurred.
|
||||
*
|
||||
******************************************************************************/
|
||||
int32_t L2_Service_PktHandler(L2_INST *instPtr, uint8_t *msg)
|
||||
{
|
||||
ASSERT(instPtr != NULL);
|
||||
ASSERT(msg != NULL);
|
||||
int32_t Status;
|
||||
#ifndef DATALINK_ENABLE_BERTEST
|
||||
uint8_t srcId = L2_NONE_ID;
|
||||
uint8_t dstId = L2_NONE_ID;
|
||||
L2_FRAME_TYPE frameType = L2_NONE_FRAME;
|
||||
L2_FrameGetChunk(msg, L2_MSG_SRC_ID, L2_MSG_SRC_ID_LEN, &srcId);
|
||||
L2_FrameGetChunk(msg, L2_MSG_DST_ID, L2_MSG_DST_ID_LEN, &dstId);
|
||||
if(dstId != L2_GetNodeId(instPtr)) {
|
||||
DBG_WARNING("Drop frame not addressed to me (%u->%u)", srcId, dstId);
|
||||
return SUCCESS;
|
||||
}
|
||||
L2_FrameGetChunk(msg, L2_MSG_TYPE, L2_MSG_TYPE_LEN, &frameType);
|
||||
switch (frameType)
|
||||
{
|
||||
case L2_SVC_FRAME:
|
||||
{
|
||||
NODE_ENTRY *node;
|
||||
node = L2_GetNodeById(instPtr->nodeList, srcId);
|
||||
if (node == NULL)
|
||||
{
|
||||
DBG_WARNING("Unrecognized node (%u).", srcId);
|
||||
Status = FAILURE;
|
||||
break;
|
||||
}
|
||||
|
||||
// Update node info.
|
||||
float nodePos;
|
||||
L2_FrameGetChunk(msg, L2_MSG_SVC_SRC_POSX, L2_MSG_SVC_SRC_POSX_LEN, &nodePos);
|
||||
node->nodeInfo.pos.x = (double)nodePos;
|
||||
L2_FrameGetChunk(msg, L2_MSG_SVC_SRC_POSY, L2_MSG_SVC_SRC_POSY_LEN, &nodePos);
|
||||
node->nodeInfo.pos.y = (double)nodePos;
|
||||
L2_FrameGetChunk(msg, L2_MSG_SVC_SRC_POSZ, L2_MSG_SVC_SRC_POSZ_LEN, &nodePos);
|
||||
node->nodeInfo.pos.z = (double)nodePos;
|
||||
float nodeSpeed;
|
||||
L2_FrameGetChunk(msg, L2_MSG_SVC_SRC_SPEEDX, L2_MSG_SVC_SRC_SPEEDX_LEN, &nodeSpeed);
|
||||
node->nodeInfo.speed.x = (double)nodePos;
|
||||
L2_FrameGetChunk(msg, L2_MSG_SVC_SRC_SPEEDY, L2_MSG_SVC_SRC_SPEEDY_LEN, &nodeSpeed);
|
||||
node->nodeInfo.speed.y = (double)nodePos;
|
||||
L2_FrameGetChunk(msg, L2_MSG_SVC_SRC_SPEEDZ, L2_MSG_SVC_SRC_SPEEDZ_LEN, &nodeSpeed);
|
||||
node->nodeInfo.speed.z = (double)nodePos;
|
||||
|
||||
// Reset node ttl
|
||||
node->ttlCnt = 0;
|
||||
|
||||
// Calculate time deviation
|
||||
uint32_t frameNum, slotNum = 0;
|
||||
L2_FrameGetChunk(msg, L2_MSG_FRAME_NUM, L2_MSG_FRAME_NUM_LEN, &frameNum);
|
||||
L2_FrameGetChunk(msg, L2_MSG_SLOT_NUM, L2_MSG_SLOT_NUM_LEN, &slotNum);
|
||||
Status = L2_GetTimeDeviation(instPtr, frameNum, slotNum, true, &(instPtr->log.timeDev));
|
||||
if (Status != SUCCESS)
|
||||
{
|
||||
DBG_ERROR("Failed to compute time deviation.\n");
|
||||
break;
|
||||
}
|
||||
|
||||
uint32_t dataId;
|
||||
L2_FrameGetChunk(msg, L2_MSG_SVC_PAYLOAD_ID, L2_MSG_SVC_PAYLOAD_ID_LEN, &dataId);
|
||||
|
||||
if (L2_GetNodeType(instPtr) == L2_NODE_HEAD)
|
||||
{
|
||||
SysMonitor_UpdateRecvPayload(msg + L2_MSG_SVC_PAYLOAD, dataId, PAYLOAD_LEN_FLJ_RX);
|
||||
}
|
||||
else
|
||||
{
|
||||
SysMonitor_UpdateRecvPayload(msg + L2_MSG_SVC_PAYLOAD, dataId, PAYLOAD_LEN_LJ_RX);
|
||||
}
|
||||
|
||||
// Logging
|
||||
memcpy(instPtr->log.rxLog.data, msg, L2_SVC_PACK_LEN);
|
||||
instPtr->log.rxLog.dataId = dataId;
|
||||
instPtr->serviceFSM->rxdCnt++;
|
||||
|
||||
#ifdef DATALINK_ENABLE_AUTOTIMESYNC
|
||||
// Implement a auto time sync.
|
||||
if (L2_GetNodeType(instPtr) != L2_NODE_HEAD)
|
||||
{
|
||||
// Time sync.
|
||||
L2_TimeAdjust(instPtr, &(instPtr->log.timeDev));
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
default:
|
||||
DBG_ERROR("Unsupported frame type: %" PRIu8 ".\n", frameType);
|
||||
break;
|
||||
}
|
||||
return Status;
|
||||
#else
|
||||
uint32_t errorBits = 0;
|
||||
for (int i = 0; i < L2_SVC_PACK_LEN; i++)
|
||||
{
|
||||
errorBits += count_ones(msg[i] ^ testData[i]);
|
||||
}
|
||||
|
||||
instPtr->serviceFSM->bitError += errorBits;
|
||||
instPtr->serviceFSM->bitTotal += L2_SVC_PACK_LEN * 8;
|
||||
|
||||
// Calculate time deviation
|
||||
uint32_t frameNum, slotNum = 0;
|
||||
L2_FrameGetChunk(msg, L2_MSG_FRAME_NUM, L2_MSG_FRAME_NUM_LEN, &frameNum);
|
||||
L2_FrameGetChunk(msg, L2_MSG_SLOT_NUM, L2_MSG_SLOT_NUM_LEN, &slotNum);
|
||||
Status = L2_GetTimeDeviation(instPtr, frameNum, slotNum, true, &(instPtr->log.timeDev));
|
||||
if (Status != SUCCESS)
|
||||
{
|
||||
DBG_ERROR("Failed to compute time deviation.\n")
|
||||
return Status;
|
||||
}
|
||||
// Implement a auto time sync.
|
||||
if (L2_GetNodeType(instPtr) != L2_NODE_HEAD)
|
||||
{
|
||||
// Time sync.
|
||||
L2_TimeAdjust(instPtr, &(instPtr->log.timeDev));
|
||||
}
|
||||
return SUCCESS;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Initialize service net FSM
|
||||
*
|
||||
* @param serviceFSM A pointer to service FSM instance.
|
||||
*
|
||||
* @return SUCCESS Initialize successfully.
|
||||
* Other Initialize failed.
|
||||
*
|
||||
******************************************************************************/
|
||||
int32_t L2_Service_Init(L2_SVC_FSM **svcFSMPtr)
|
||||
{
|
||||
ASSERT(svcFSMPtr != NULL);
|
||||
*svcFSMPtr = (L2_SVC_FSM *)malloc(sizeof(L2_SVC_FSM));
|
||||
if (*svcFSMPtr == NULL)
|
||||
{
|
||||
return ENOMEM;
|
||||
}
|
||||
L2_Service_Reset(*svcFSMPtr);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Reset ServiceNet FSM
|
||||
*
|
||||
* @param scanFsmPtr a pointer to service net finite state machine
|
||||
*
|
||||
* @return NONE
|
||||
*
|
||||
******************************************************************************/
|
||||
void L2_Service_Reset(L2_SVC_FSM *svcFSMPtr)
|
||||
{
|
||||
ASSERT(svcFSMPtr != NULL);
|
||||
svcFSMPtr->txCnt = 0;
|
||||
svcFSMPtr->rxCnt = 0;
|
||||
svcFSMPtr->rxdCnt = 0;
|
||||
#ifdef DATALINK_ENABLE_BERTEST
|
||||
svcFSMPtr->bitTotal = 0;
|
||||
svcFSMPtr->bitError = 0;
|
||||
svcFSMPtr->lossRate = 0;
|
||||
svcFSMPtr->errorRate = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Destroy ServiceNet FSM, free memory
|
||||
*
|
||||
* @param scanFsmPtr a pointer to service net finite state machine
|
||||
*
|
||||
* @return NONE
|
||||
*
|
||||
******************************************************************************/
|
||||
void L2_Service_Destroy(L2_SVC_FSM *serviceFSM)
|
||||
{
|
||||
free(serviceFSM);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Service FSM Routine.
|
||||
*
|
||||
* @param instPtr
|
||||
* @param schedEntry
|
||||
*
|
||||
* @return Slot has been used.
|
||||
*
|
||||
******************************************************************************/
|
||||
int32_t L2_Service_Routine(L2_INST *instPtr, const L2_RTNE_TABLE_ENTRY *rtneEntry)
|
||||
{
|
||||
ASSERT(instPtr != NULL);
|
||||
DBG_INFO("-------- ServiceNet Routine --------\n");
|
||||
|
||||
if (rtneEntry->slotSeq != 0)
|
||||
{
|
||||
return SUCCESS; // skip
|
||||
}
|
||||
|
||||
PHY_INST *phyRef = instPtr->config.phyInstPtr;
|
||||
L2_SVC_FSM *svcFSMPtr = instPtr->serviceFSM;
|
||||
L2_TOR_TYPE torState;
|
||||
const NODE_ENTRY *commNode;
|
||||
if (rtneEntry->src == L2_GetNodeId(instPtr))
|
||||
{
|
||||
torState = L2_TOR_TX;
|
||||
commNode = L2_GetNodeById(instPtr->nodeList, rtneEntry->dst);
|
||||
}
|
||||
else if (rtneEntry->dst == L2_GetNodeId(instPtr))
|
||||
{
|
||||
torState = L2_TOR_RX;
|
||||
commNode = L2_GetNodeById(instPtr->nodeList, rtneEntry->src);
|
||||
}
|
||||
else
|
||||
{
|
||||
torState = L2_TOR_SUSPEND;
|
||||
}
|
||||
|
||||
// Setup antenna beam
|
||||
if (L2_GetNodeType(instPtr) != L2_NODE_HEAD && commNode != NULL)
|
||||
{
|
||||
Phy_SetBeamWidth(phyRef, PHY_ANT_BEAM_16);
|
||||
Phy_SetBeamNo(phyRef, commNode->nodeInfo.beamNo, PHY_ANT_BEAM_16);
|
||||
instPtr->log.lastBeamWidth = PHY_ANT_BEAM_16;
|
||||
}
|
||||
else
|
||||
{
|
||||
Phy_SetBeamWidth(phyRef, PHY_ANT_BEAM_120);
|
||||
instPtr->log.lastBeamWidth = PHY_ANT_BEAM_120;
|
||||
}
|
||||
|
||||
switch (rtneEntry->slotType)
|
||||
{
|
||||
case L2_SLOT_SERVICE:
|
||||
if (torState == L2_TOR_TX)
|
||||
{
|
||||
svcFSMPtr->txCnt++;
|
||||
#ifndef DATALINK_ENABLE_BERTEST
|
||||
// Packing service data
|
||||
Service_Packing(instPtr, L2_SVC_FRAME, rtneEntry->dst);
|
||||
#else
|
||||
memcpy(instPtr->sendPktData, testData, L2_SVC_PACK_LEN);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
svcFSMPtr->rxCnt++;
|
||||
}
|
||||
L2_SetupNextSlot(instPtr, torState, L2_SVC_FRAME);
|
||||
break;
|
||||
default:
|
||||
DBG_ERROR("UNKNOWN slot type [%" PRIu8 "].\n", rtneEntry->slotType);
|
||||
return FAILURE;
|
||||
}
|
||||
#ifdef DATALINK_ENABLE_BERTEST
|
||||
uint32_t pktLoss;
|
||||
pktLoss = svcFSMPtr->rxCnt - svcFSMPtr->rxdCnt;
|
||||
svcFSMPtr->lossRate = (svcFSMPtr->rxCnt == 0) ? 0 : (double)pktLoss / (double)svcFSMPtr->rxCnt;
|
||||
svcFSMPtr->errorRate = (svcFSMPtr->bitTotal == 0) ? 0 : (double)svcFSMPtr->bitError / (double)svcFSMPtr->bitTotal;
|
||||
DBG_PRINT("Packet Loss Rate -- Total: %lu, Loss: %lu.\n", instPtr->log.svcRxCnt, pktLoss);
|
||||
DBG_PRINT("Bit Error Rate -- Total:%lu, Error:%lu.\n", svcFSMPtr->bitTotal, svcFSMPtr->bitError);
|
||||
#endif
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/** @} LinkLayer_Service*/
|
||||
/** @} LinkLayer*/
|
||||
@@ -0,0 +1,105 @@
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @file time_sync.c
|
||||
* @author FanHao ([email protected])
|
||||
* @brief DF Linklayer time sync implementation file.
|
||||
* @version 0.0
|
||||
* @date 2023-05-06
|
||||
*
|
||||
* @copyright Copyright(c) 2024 Beijing Institute of Technology.\n
|
||||
* Lab of Communication and Network
|
||||
*
|
||||
******************************************************************************/
|
||||
/**
|
||||
* @addtogroup LinkLayer
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup LinkLayer_TimeSync
|
||||
* @{
|
||||
*/
|
||||
/***************************** Include Files *********************************/
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "link_layer.h"
|
||||
#include "../phy_layer/phy_layer.h"
|
||||
#include "error.h"
|
||||
#include "common.h"
|
||||
|
||||
/************************** Constant Definitions *****************************/
|
||||
/***************** Macros (Inline Functions) Definitions *********************/
|
||||
/**************************** Type Definitions *******************************/
|
||||
/************************** Variable Definitions *****************************/
|
||||
/************************** Function Prototypes ******************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Get time deviation to the specified frame and slot number.
|
||||
*
|
||||
* @param instPtr a pointer to linklayer layer instance
|
||||
* @param frameNum
|
||||
* @param slotNum
|
||||
* @param relative
|
||||
* @param timeDev
|
||||
*
|
||||
* @return SUCCESS
|
||||
* EIGNORE there is no received frame
|
||||
*
|
||||
******************************************************************************/
|
||||
int32_t L2_GetTimeDeviation(L2_INST *instPtr, uint32_t frameNum, uint32_t slotNum, bool relative, int64_t *timeDev)
|
||||
{
|
||||
ASSERT(instPtr != NULL);
|
||||
ASSERT(timeDev != NULL);
|
||||
L1_FRAME_TYPE lastRecvdFrame;
|
||||
PHY_INST *phyRef = instPtr->config.phyInstPtr;
|
||||
lastRecvdFrame = Phy_GetLastRecvFrameType(phyRef);
|
||||
if (lastRecvdFrame == L1_NONE_FRAME)
|
||||
{
|
||||
DBG_ERROR("Invalid TimeAlign operation, no frame was received.");
|
||||
return EIGNORE;
|
||||
}
|
||||
|
||||
DBG_INFO("Starting TimeAlign operation...\n");
|
||||
// read nextSendTime from physical layer
|
||||
uint64_t currTime, expectTime;
|
||||
TIME_WORD timeStamp;
|
||||
expectTime = ((uint64_t)(frameNum * L2_SLOTS_PER_FRAME + slotNum)) * TIME_FRAC_MAX;
|
||||
expectTime += Phy_GetTimeComp(lastRecvdFrame);
|
||||
|
||||
if (relative)
|
||||
{
|
||||
expectTime += (uint64_t)instPtr->netStartTime * L2_SLOTS_PER_FRAME * TIME_FRAC_MAX;
|
||||
}
|
||||
|
||||
Phy_GetLastReceivedFrameSyncTimeStamp(phyRef, &timeStamp);
|
||||
currTime = (uint64_t)timeStamp.frac_part;
|
||||
currTime += ((uint64_t)timeStamp.int_part) * TIME_FRAC_MAX;
|
||||
|
||||
*timeDev = (int64_t)(expectTime - currTime);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Implement time adjustment by applying time deviation.
|
||||
*
|
||||
* @param instPtr a pointer to linklayer layer instance
|
||||
* @param timeDev
|
||||
*
|
||||
* @return NONE
|
||||
*
|
||||
******************************************************************************/
|
||||
void L2_TimeAdjust(L2_INST *instPtr, const int64_t *timeDev)
|
||||
{
|
||||
ASSERT(instPtr != NULL);
|
||||
ASSERT(timeDev != NULL);
|
||||
TIME_WORD slotTimerAdjmet;
|
||||
slotTimerAdjmet.int_part = (uint32_t)(*timeDev / TIME_FRAC_MAX);
|
||||
slotTimerAdjmet.frac_part = (uint32_t)(*timeDev % TIME_FRAC_MAX);
|
||||
TimeCtrl_TimeAdjust(instPtr->config.tmcInstPtr, &slotTimerAdjmet, TM_ADJ_ADD);
|
||||
}
|
||||
|
||||
/** @} LinkLayer_TimeSync*/
|
||||
|
||||
/** @} LinkLayer*/
|
||||
@@ -0,0 +1,428 @@
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @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] =
|
||||
{
|
||||
1084, 1097, 1110, 1123, 1136, 1149, 1162, 1175,
|
||||
1188, 1201, 1214, 1227, 1240, 1253, 1266, 1279,
|
||||
1292, 1305, 1318, 1331, 1344, 1357, 1370, 1383,
|
||||
1396, 1409, 1422, 1435, 1448, 1461, 1474, 1487,
|
||||
1500, 1513, 1526, 1539, 1552, 1565, 1578, 1591,
|
||||
1604, 1617, 1630, 1643, 1656, 1669, 1682, 1695,
|
||||
1708, 1721, 1734, 1747, 1760, 1773, 1786, 1799,
|
||||
1812, 1825, 1838, 1851, 1864, 1877, 1890, 1903,
|
||||
1916, 1929, 1942, 1955, 1968, 1981, 1994, 2007,
|
||||
2020, 2033, 2046, 2059, 2072, 2085, 2098, 2111,
|
||||
2124
|
||||
};
|
||||
|
||||
const uint16_t antCalTable[L1_FRAME_MAX_HOPS][L1_ANT_NUM_CH] =
|
||||
//Antenna-JG01
|
||||
{
|
||||
{ 0, 406, -10530, -8223}, { 0, 697, -9933, -7988},
|
||||
{ 0, 296, -10497, -8272}, { 0, 515, -10264, -8093},
|
||||
{ 0, 689, -10212, -8064}, { 0, 40, -10960, -8572},
|
||||
{ 0, 722, -10878, -8518}, { 0, 59, -10987, -8962},
|
||||
{ 0, 56, -11264, -8770}, { 0, -464, -11341, -9159},
|
||||
{ 0, 19, -10924, -8887}, { 0, -669, -10927, -8679},
|
||||
{ 0, -701, -11154, -8712}, { 0, -255, -10739, -8009},
|
||||
{ 0, -192, -10509, -8242}, { 0, -1057, -11183, -9007},
|
||||
{ 0, -57, -10606, -8350}, { 0, -719, -10949, -8880},
|
||||
{ 0, -760, -11084, -8660}, { 0, -457, -10735, -8833},
|
||||
{ 0, -188, -10623, -9119}, { 0, -628, -12609, -10119},
|
||||
{ 0, -434, -12714, -10225}, { 0, -727, -13074, -10685},
|
||||
{ 0, -12, -12408, -10190}, { 0, 33, -12790, -10624},
|
||||
{ 0, 93, -13235, -10819}, { 0, -363, -13301, -11183},
|
||||
{ 0, -514, -13955, -11557}, { 0, -458, -13878, -11722},
|
||||
{ 0, 93, -13086, -11726}, { 0, -663, -13597, -11868},
|
||||
{ 0, 174, -12814, -11295}, { 0, 121, -12278, -11150},
|
||||
{ 0, 425, -11255, -10363}, { 0, 430, -11645, -10189},
|
||||
{ 0, 277, -11844, -9499}, { 0, -132, -12241, -9420},
|
||||
{ 0, 448, -11934, -9612}, { 0, 200, -11778, -9582},
|
||||
{ 0, -40, -12069, -9336}, { 0, 1692, -11315, -9085},
|
||||
{ 0, -1753, -11445, -9482}, { 0, -2520, -12620, -10068},
|
||||
{ 0, -1976, -12674, -10218}, { 0, -1984, -12525, -10354},
|
||||
{ 0, -2272, -13476, -10932}, { 0, -2123, -13918, -11095},
|
||||
{ 0, -2883, -14447, -11659}, { 0, -2826, -13946, -11563},
|
||||
{ 0, -2697, -13680, -11328}, { 0, -3068, -13393, -11614},
|
||||
{ 0, -2935, -13074, -11882}, { 0, -3017, -13038, -11163},
|
||||
{ 0, -2490, -12379, -11288}, { 0, -2463, -12286, -10726},
|
||||
{ 0, -2686, -12167, -10673}, { 0, -2428, -12077, -10555},
|
||||
{ 0, -2282, -12564, -10388}, { 0, -2017, -12303, -10844},
|
||||
{ 0, -2329, -12637, -11250}, { 0, -2703, -13362, -11807},
|
||||
{ 0, -1820, -12605, -11733}, { 0, 596, -10833, -9852},
|
||||
{ 0, 9, -11140, -9776}, { 0, 41, -11168, -9478},
|
||||
{ 0, -261, -11368, -9752}, { 0, 226, -11282, -9879},
|
||||
{ 0, -68, -11454, -10148}, { 0, -314, -12278, -10716},
|
||||
{ 0, -66, -11998, -10762}, { 0, -58, -11469, -10664},
|
||||
{ 0, 319, -10759, -10212}, { 0, 122, -11041, -9901},
|
||||
{ 0, -269, -11085, -10008}, { 0, 637, -10569, -9674},
|
||||
{ 0, 1185, -10632, -9521}, { 0, 902, -11053, -9681},
|
||||
{ 0, 560, -11408, -9588}, { 0, 1162, -11079, -9371},
|
||||
{ 0, 1780, -10547, -9133},
|
||||
};
|
||||
|
||||
const uint8_t hopPattern_2KBPS_20MS[L1_FRAME_2KBPS_20MS_HOPS] =
|
||||
{
|
||||
0
|
||||
};
|
||||
|
||||
const uint8_t hopPattern_2KBPS_100MS[L1_FRAME_2KBPS_100MS_HOPS] =
|
||||
{
|
||||
0, 1, 2, 3, 4, 5, 6, 7,
|
||||
8, 9, 10, 11, 12, 13, 14, 15,
|
||||
16, 17, 18, 19, 20, 21, 22, 23,
|
||||
24, 25, 26, 27, 28, 29, 30, 31,
|
||||
32, 33, 34, 35, 36, 37, 38, 39,
|
||||
40, 41, 42, 43, 44, 45, 46, 47,
|
||||
48, 49, 50, 51, 52, 53, 54, 55,
|
||||
56, 57, 58, 59, 60, 61, 62, 63,
|
||||
64, 65, 66, 67, 68, 69, 70, 71,
|
||||
72, 73, 74, 75, 76, 77, 78, 79,
|
||||
80
|
||||
};
|
||||
|
||||
const uint8_t hopPattern_10KBPS_10MS[L1_FRAME_10KBPS_10MS_HOPS] =
|
||||
{
|
||||
80
|
||||
};
|
||||
|
||||
const uint8_t hopPattern_10KBPS_20MS[L1_FRAME_10KBPS_20MS_HOPS] =
|
||||
{
|
||||
80, 1, 2, 3, 4, 5, 6, 7,
|
||||
8, 9, 10
|
||||
};
|
||||
|
||||
const uint8_t hopPattern_40KBPS_10MS[L1_FRAME_40KBPS_10MS_HOPS] =
|
||||
{
|
||||
0, 1, 2, 3, 4, 5, 6, 7,
|
||||
8,
|
||||
};
|
||||
|
||||
const uint8_t hopPattern_40KBPS_20MS[L1_FRAME_40KBPS_20MS_HOPS] =
|
||||
{
|
||||
0, 1, 2, 3, 4, 5, 6, 7,
|
||||
8, 9, 10, 11, 12, 13, 14, 15,
|
||||
16, 17, 18
|
||||
};
|
||||
|
||||
const uint8_t hopPattern_200KBPS_5MS[L1_FRAME_200KBPS_5MS_HOPS] =
|
||||
{
|
||||
0, 1, 2, 3, 4, 5, 6, 7,
|
||||
8, 9, 10, 11, 12, 13, 14, 15,
|
||||
16, 17, 18, 19
|
||||
};
|
||||
|
||||
const uint8_t hopPattern_1M2BPS_5MS[L1_FRAME_1M2BPS_5MS_HOPS] =
|
||||
{
|
||||
0, 1, 2, 3, 4, 5, 6, 7,
|
||||
8, 9, 10, 11, 12, 13, 14, 15,
|
||||
16, 17, 18, 19
|
||||
};
|
||||
|
||||
/** @} 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,
|
||||
NORMALIZE_SIZE(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, int32_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 / ANT_PI)) % 360) : (((int32_t)(offAx * 180 / ANT_PI)) % 360 + 360);
|
||||
rndAxDeg = (rndAx >= 0) ? (((int32_t)(rndAx * 180 / ANT_PI)) % 360) : (((int32_t)(rndAx * 180 / 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*/
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,315 @@
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @file phy_layer.c
|
||||
* @author FanHao ([email protected])
|
||||
* @brief Physical layer control header file.
|
||||
* @version 0.0
|
||||
* @date 2023-04-24
|
||||
*
|
||||
* @copyright Copyright(c) 2024 Beijing Institute of Technology.\n
|
||||
* Lab of Communication and Network
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* @defgroup PhysicalLayer
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef PHY_CTRL_H_
|
||||
#define PHY_CTRL_H_
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
#include <stdint.h>
|
||||
#include "common.h"
|
||||
#ifndef EMULATION
|
||||
#include "xbram.h"
|
||||
#include "xsysmon.h"
|
||||
#include "../config/app_config.h"
|
||||
#endif
|
||||
#include "../../system_monitor.h"
|
||||
#include "../../time_ctrl/time_ctrl.h"
|
||||
/************************** Constant Definitions *****************************/
|
||||
/**
|
||||
* @name PhysicalLayer_Common_Constant
|
||||
* @{
|
||||
*/
|
||||
#define L1_NUM_ANT_NRRW_PATTERN 37
|
||||
#define L1_INIT_BEAM_NO 0
|
||||
#define L1_INIT_ANT_WD PHY_ANT_BEAM_120
|
||||
#define L1_ANT_NUM_CH 4
|
||||
|
||||
#define L1_FRAME_NONE_LEN UINT32_MAX // byte
|
||||
#define L1_FRAME_NONE_COMP UINT32_MAX // *10ns(Timer_L)
|
||||
#define L1_FRAME_NONE_HOPS UINT32_MAX
|
||||
#define L1_FRAME_MAX_HOPS 81
|
||||
#define L1_FRAME_2KBPS_20MS_HOPS 1
|
||||
#define L1_FRAME_2KBPS_100MS_HOPS 81
|
||||
#define L1_FRAME_10KBPS_10MS_HOPS 1
|
||||
#define L1_FRAME_10KBPS_20MS_HOPS 11
|
||||
#define L1_FRAME_40KBPS_20MS_HOPS 19
|
||||
#define L1_FRAME_40KBPS_10MS_HOPS 9
|
||||
#define L1_FRAME_200KBPS_5MS_HOPS 20
|
||||
#define L1_FRAME_1M2BPS_5MS_HOPS 20
|
||||
#define PHY_LOG_EXPIRE 40 // 50*5ms
|
||||
/** @} */
|
||||
/***************** Macros (Inline Functions) Definitions *********************/
|
||||
/**************************** Type Definitions *******************************/
|
||||
/**
|
||||
* @enum L1_FRAME_TYPE
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
L1_NONE_FRAME = 0,
|
||||
L1_2KBPS_20MS_FRAME = 1,
|
||||
L1_2KBPS_100MS_FRAME = 2,
|
||||
L1_10KBPS_10MS_FRAME = 3,
|
||||
L1_10KBPS_20MS_FRAME = 4,
|
||||
L1_40KBPS_20MS_FRAME = 5,
|
||||
L1_40KBPS_10MS_FRAME = 6,
|
||||
L1_200KBPS_5MS_FRAME = 7,
|
||||
L1_1M2BPS_5MS_FRAME = 8
|
||||
} L1_FRAME_TYPE;
|
||||
|
||||
/**
|
||||
* @struct PHY_ANT_CONFIG
|
||||
* @brief PhysicalLayer antenna config
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
/*** Ant Control ***/
|
||||
uint8_t ctrlWord; ///< Antenna control frame head 0xAA\n
|
||||
/// default 0, reserved for further use
|
||||
uint8_t antMode; ///< high 4 bits specified beam mode.\n
|
||||
/// low 4 bits specified power control
|
||||
uint8_t oaxis[2]; ///< off-axis angle range is 0~60 \n
|
||||
/// 0.1 degree each LSB
|
||||
uint8_t raxis[2]; ///< round-axis angle range is 0~360, \n
|
||||
/// 0.1 degree each LSB
|
||||
uint8_t antFreq[2]; ///< 0~3500Mhz, step 1MHz
|
||||
uint8_t trSlect; ///< in single tr mode, 0~63 specified tr channel \n
|
||||
/// in single subarray mode, 0~3 specified the subarray
|
||||
/// ! Only in debug mode!
|
||||
uint8_t antAtt; ///< Antenna attenuation 0~31, 0.5dB each LSB, Only in debug mode
|
||||
uint8_t phase; ///< 0~63, 5.625 degree each LSB, Only in debug mode
|
||||
uint8_t rxtxMode; ///< Only for debug \n
|
||||
/// default 0x00
|
||||
uint8_t calibrMode; ///< 0x00 Normal, 0x01 single tr calibration
|
||||
uint8_t antReserved; ///< reserved for further use
|
||||
|
||||
/*** RF Control ***/
|
||||
uint8_t rfCtrl; ///< [7:4]RF enable: 0-On, 1-Off(Default); [3:0]Work mode: 0(default)
|
||||
uint8_t rfFreq[2]; ///< 0~3500Mhz, step 1MHz
|
||||
uint8_t rfTxMgc; ///< RF MGC control: 0~31, 1dB each LSB
|
||||
uint8_t rf12CalMgc; ///< RF channel 1&2 calibration mgc\n
|
||||
/// [7:4] Channle1 - max 15db, 1dB each LSB \n
|
||||
/// [3:0] Channle2 - max 15db, 1dB each LSB
|
||||
uint8_t rf34CalMgc; ///< RF channel 3&4 calibration mgc\n
|
||||
/// [7:4] Channle3 - max 15db, 1dB each LSB
|
||||
/// [3:0] Channle4 - max 15db, 1dB each LSB
|
||||
uint8_t rcvMgc; ///< Receive channel 1-4 MGC: 0~31, 1dB each LSB
|
||||
uint8_t rfMonitor; ///< Receive monitor, 0-normal, 1-switch to monitor port
|
||||
uint8_t rfReserved0; ///< reserved for further use
|
||||
uint8_t rfReserved1; ///< reserved for further use
|
||||
uint8_t ch0Cal[2];
|
||||
uint8_t ch1Cal[2];
|
||||
uint8_t ch2Cal[2];
|
||||
uint8_t ch3Cal[2];
|
||||
} PHY_ANT_CONFIG;
|
||||
|
||||
/**
|
||||
* @struct PHY_ANT_ANGLE
|
||||
* @brief Describe the PhysicalLayer antenna angle
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint16_t oaxis; ///< off-axis angle range is 0~60
|
||||
/// 0.1 degree each LSB
|
||||
uint16_t raxis; ///< round-axis angle range is 0~360
|
||||
/// 0.1 degree each LSB
|
||||
} PHY_ANT_ANGLE;
|
||||
|
||||
/**
|
||||
* @enum PHY_TIME_WORD_TYPE
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
PHY_TIME_WORD_NONE = 0,
|
||||
PHY_TIME_WORD_POLL = 1,
|
||||
PHY_TIME_WORD_LISTEN_TIMEOUT = 2
|
||||
} PHY_TIME_WORD_TYPE;
|
||||
|
||||
/**
|
||||
* @enum PHY_ANT_BEAM_WIDTH
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
PHY_ANT_BEAM_NONE = 0,
|
||||
PHY_ANT_BEAM_120 = 1,
|
||||
PHY_ANT_BEAM_60 = 2,
|
||||
PHY_ANT_BEAM_25 = 3,
|
||||
PHY_ANT_BEAM_16 = 4
|
||||
} PHY_ANT_BEAM_WIDTH;
|
||||
|
||||
/**
|
||||
* @enum PHY_TOR_TYPE
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
PHY_TOR_SUSPEND = 0,
|
||||
PHY_TOR_TX = 1,
|
||||
PHY_TOR_RX = 2
|
||||
} PHY_TOR_TYPE;
|
||||
|
||||
/**
|
||||
* @enum PHY_MODE
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
PHY_MODE_NONE = 0,
|
||||
PHY_MODE_LISTEN = 1,
|
||||
PHY_MODE_SCHEDULE = 2,
|
||||
PHY_MODE_PULL = 3
|
||||
} PHY_MODE;
|
||||
|
||||
/**
|
||||
* @enum PHY_ANT_MODE
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
PHY_ANT_MODE_NONE = 0,
|
||||
PHY_ANT_MODE_STANDBY = 1,
|
||||
PHY_ANT_MODE_POWER_LOW = 2,
|
||||
PHY_ANT_MODE_POWER_FULL = 3,
|
||||
} PHY_ANT_MODE;
|
||||
|
||||
/**
|
||||
* @struct PHY_RCD
|
||||
* @brief Physical Layer recode buffer
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
int32_t last;
|
||||
int32_t curr;
|
||||
int32_t next;
|
||||
} PHY_RCD;
|
||||
|
||||
/**
|
||||
* @struct PHY_CONFIG
|
||||
* @brief struct holds all physical layer initialization parameters
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t devId; ///< device ID
|
||||
uint32_t txBramId; ///< tx bram ID
|
||||
uint32_t rxBramId; ///< rx bram ID
|
||||
uint32_t antBramId; ///< antenna config bram ID
|
||||
uint32_t antInfoBramId; ///< antenna beam info bram ID
|
||||
uint32_t hwSysmonId; ///< hardware xadc device ID
|
||||
uintptr_t baseAddr; ///< Physical layer controller base address
|
||||
#ifndef EMULATION
|
||||
uint8_t (*get_clk_state)(void); ///< function handle returns hardware clock state
|
||||
uint8_t (*get_ad_lock_state)(void); ///< function handle returns adc lock state
|
||||
int8_t (*get_ad0_temp)(void); ///< function handle returns adc0 temperature state
|
||||
int8_t (*get_ad1_temp)(void); ///< function handle returns adc1 temperature state
|
||||
#endif
|
||||
} PHY_CONFIG;
|
||||
|
||||
/**
|
||||
* @struct PHY_INST
|
||||
* @brief Physical Layer operating instance
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
PHY_CONFIG phyCofig; ///< physical layer configuration parameters
|
||||
uintptr_t recvDataAddr; ///< receive data bram address
|
||||
uintptr_t sendDataAddr; ///< send data bram address
|
||||
uintptr_t antConfigAddr; ///< antenna config data bram address
|
||||
uintptr_t antInfoAddr; ///< antenna beam info data bram address
|
||||
bool isPhyEn; ///< indicates if physical layer running
|
||||
bool isAcq; ///< indicates if last reception acquisition success
|
||||
bool isFrameSync; ///< indicates if last reception frame sync success
|
||||
bool isDecode; ///< indicates if last reception decode success
|
||||
bool isValid; ///< indicates if last reception frame data valid (crc check pass)
|
||||
TIME_WORD recvSlotTime; ///< last slot start time stamp
|
||||
TIME_WORD recvFsTime; ///< last frame sync time stamp
|
||||
PHY_RCD beamNo; ///< beam number record
|
||||
PHY_RCD beamWd; ///< beam width record
|
||||
PHY_RCD tor; ///< tx rx state record
|
||||
PHY_RCD frameType; ///< frame type record
|
||||
uint32_t sendDataOffset; ///< antenna configuration bram offset (to implement ping-pong data flow)
|
||||
uint32_t antConfigOffset; ///< antenna configuration bram offset (to implement ping-pong data flow)
|
||||
PHY_ANT_CONFIG antConfig; ///< antenna configuration pointer
|
||||
#ifndef EMULATION
|
||||
XSysMon sysMon; ///< System monitor
|
||||
#endif
|
||||
PHY_ANT_ANGLE antNrrwPattern[L1_NUM_ANT_NRRW_PATTERN]; ///< antenna beam scan pattern
|
||||
HWSTATE hwSate; ///< hardware state log
|
||||
PHYLOG phyLog; ///< physical state log
|
||||
uint32_t lastLogTime; /// physical state log time stamp
|
||||
} PHY_INST;
|
||||
|
||||
/************************** Function Prototypes ******************************/
|
||||
|
||||
/**
|
||||
* @defgroup PhysicalLayer_Main
|
||||
* @{
|
||||
*/
|
||||
int32_t Phy_Init(PHY_INST **instPtr, PHY_CONFIG *phyConfig);
|
||||
void Phy_Destroy(PHY_INST *instPtr);
|
||||
void Phy_Start(PHY_INST *instPtr);
|
||||
void Phy_Halt(PHY_INST *instPtr);
|
||||
|
||||
int32_t Phy_SetMode(PHY_INST *instPtr, PHY_MODE modeCod);
|
||||
int32_t Phy_SetTimeWord(PHY_INST *instPtr, const TIME_WORD *tmWord, PHY_TIME_WORD_TYPE tmType);
|
||||
int32_t Phy_SetupNextSlot(PHY_INST *instPtr, PHY_TOR_TYPE txrxMode, L1_FRAME_TYPE frameType, uint8_t *dataBuff);
|
||||
void Phy_UpdateState(PHY_INST *instPtr);
|
||||
void Phy_PeekRecvData(PHY_INST *instPtr, uint8_t *dataBuff);
|
||||
void Phy_RetrieveRecvData(PHY_INST *instPtr, uint8_t *dataBuff);
|
||||
void Phy_UpdateLogging(PHY_INST *instPtr);
|
||||
void Phy_RefreshHwSate(PHY_INST *instPtr);
|
||||
/** @} PhysicalLayer_Main*/
|
||||
|
||||
/**
|
||||
* @defgroup PhysicalLayer_Utility
|
||||
* @{
|
||||
*/
|
||||
bool Phy_IsFrameDetected(PHY_INST *instPtr);
|
||||
bool Phy_IsFrameReceived(PHY_INST *instPtr);
|
||||
bool Phy_IsFrameValid(PHY_INST *instPtr);
|
||||
uint32_t Phy_GetFrameLen(L1_FRAME_TYPE frameType);
|
||||
uint32_t Phy_GetHopLength(L1_FRAME_TYPE frameType);
|
||||
uint32_t Phy_GetTimeComp(L1_FRAME_TYPE frameType);
|
||||
L1_FRAME_TYPE Phy_GetLastRecvFrameType(PHY_INST *instPtr);
|
||||
L1_FRAME_TYPE Phy_GetLastSendFrameType(PHY_INST *instPtr);
|
||||
/** @} PhysicalLayer_Utility*/
|
||||
|
||||
/**
|
||||
* @defgroup PhysicalLayer_Receive_Estimations
|
||||
* @{
|
||||
*/
|
||||
uint8_t Phy_LastScanBeamNo(PHY_INST *instPtr);
|
||||
double Phy_GetFreqEst(PHY_INST *instPtr);
|
||||
double Phy_GetCoarseFreqEst(PHY_INST *instPtr);
|
||||
double Phy_GetFineFreqEst(PHY_INST *instPtr);
|
||||
void Phy_GetFrameSyncTimeStamp(PHY_INST *instPtr, TIME_WORD *frameSyncT);
|
||||
void Phy_GetLastReceivedFrameSyncTimeStamp(PHY_INST *instPtr, TIME_WORD *frameSyncT);
|
||||
void Phy_GetSlotStartTimeStamp(PHY_INST *instPtr, TIME_WORD *slotStart);
|
||||
void Phy_GetLastReceivedSlotStartTimeStamp(PHY_INST *instPtr, TIME_WORD *slotStart);
|
||||
/** @} PhysicalLayer_Receive_Estimations*/
|
||||
|
||||
/**
|
||||
* @defgroup PhysicalLayer_AntennaControl
|
||||
* @{
|
||||
*/
|
||||
void Phy_AntConfigInit(PHY_ANT_CONFIG *antConfig);
|
||||
void Phy_AntConfigMode(PHY_INST *instPtr, PHY_ANT_MODE mode);
|
||||
void Phy_SetBeamTable(PHY_INST *instPtr, PHY_ANT_ANGLE *table, uint32_t offset);
|
||||
int32_t Phy_SetBeamWidth(PHY_INST *instPtr, PHY_ANT_BEAM_WIDTH beamWidth);
|
||||
int32_t Phy_SetBeamNo(PHY_INST *instPtr, int32_t beamNo, PHY_ANT_BEAM_WIDTH beamWidth);
|
||||
int32_t Phy_SetBeamAngle(PHY_INST *phyInstPtr, double offAx, double rndAx);
|
||||
/** @} PhysicalLayer_AntennaControl*/
|
||||
|
||||
#endif // PHY_CTRL_H_
|
||||
|
||||
/** @} PhysicalLayer*/
|
||||
@@ -0,0 +1,497 @@
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @file phy_layer.h
|
||||
* @author FanHao ([email protected])
|
||||
* @brief Physical layer controller register definition
|
||||
* @version 0.0
|
||||
* @date 2023-04-24
|
||||
*
|
||||
* @copyright Copyright(c) 2024 Beijing Institute of Technology.\n
|
||||
* Lab of Communication and Network
|
||||
*
|
||||
******************************************************************************/
|
||||
/**
|
||||
* @defgroup PhysicalLayer
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @name PhysicalLayer_REG_Constants
|
||||
* @{
|
||||
*/
|
||||
#ifndef PHY_REG_H_
|
||||
#define PHY_REG_H_
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
#include "util.h"
|
||||
|
||||
/***************** Macros (Inline Functions) Definitions *********************/
|
||||
#define PhyRead(instPtr, addr) IO_In32((instPtr)->phyCofig.baseAddr + addr)
|
||||
#define PhyWrite(instPtr, addr, value) IO_Out32((instPtr)->phyCofig.baseAddr + addr, value)
|
||||
|
||||
/************************** Constant Definitions *****************************/
|
||||
/**
|
||||
* Register: PHY_MAIN_CTRL
|
||||
*/
|
||||
#define PHY_MAIN_CTRL 0x00000000U
|
||||
#define PHY_MAIN_CTRL_EN_SHIFT 0
|
||||
#define PHY_MAIN_CTRL_EN_WIDTH 1
|
||||
#define PHY_MAIN_CTRL_EN_MASK 0x00000001U
|
||||
#define PHY_MAIN_CTRL_MODE_SHIFT 8
|
||||
#define PHY_MAIN_CTRL_MODE_WIDTH 8
|
||||
#define PHY_MAIN_CTRL_MODE_MASK 0x0000FF00U
|
||||
#define PHY_MAIN_CTRL_NSCAN_SHIFT 16
|
||||
#define PHY_MAIN_CTRL_NSCAN_WIDTH 8
|
||||
#define PHY_MAIN_CTRL_NSCAN_MASK 0x00FF0000U
|
||||
|
||||
#define PHY_MAIN_CTRL_EN_EN 0x00000001U
|
||||
#define PHY_MAIN_CTRL_EN_DSBL 0x00000000U
|
||||
#define PHY_MAIN_CTRL_MODE_NONE 0x00000000U
|
||||
#define PHY_MAIN_CTRL_MODE_LISTEN 0x00000100U
|
||||
#define PHY_MAIN_CTRL_MODE_SCHEDULE 0x00000200U
|
||||
#define PHY_MAIN_CTRL_MODE_PULL 0x00000300U
|
||||
|
||||
/**
|
||||
* Register: TXRX_CTRL
|
||||
*/
|
||||
#define PHY_MODE_CTRL 0x00000004U
|
||||
#define PHY_MODE_CTRL_TOR_SHIFT 0
|
||||
#define PHY_MODE_CTRL_TOR_WIDTH 8
|
||||
#define PHY_MODE_CTRL_TOR_MASK 0x000000FFU
|
||||
#define PHY_MODE_CTRL_FRAME_SHIFT 8
|
||||
#define PHY_MODE_CTRL_FRAME_WIDTH 8
|
||||
#define PHY_MODE_CTRL_FRAME_MASK 0x0000FF00U
|
||||
#define PHY_MODE_CTRL_CRC_SHIFT 8
|
||||
#define PHY_MODE_CTRL_CRC_WIDTH 16
|
||||
#define PHY_MODE_CTRL_CRC_MASK 0x00FF0000U
|
||||
|
||||
#define PHY_MODE_CTRL_TOR_SUSPEND 0x00000000U
|
||||
#define PHY_MODE_CTRL_TOR_TX 0x00000001U
|
||||
#define PHY_MODE_CTRL_TOR_RX 0x00000002U
|
||||
|
||||
#define PHY_MODE_CTRL_FRAME_NONE 0x00000000U
|
||||
#define PHY_MODE_CTRL_FRAME_2KBPS_20MS 0x00000100U
|
||||
#define PHY_MODE_CTRL_FRAME_2KBPS_100MS 0x00000200U
|
||||
#define PHY_MODE_CTRL_FRAME_10KBPS_10MS 0x00000300U // Initial Scan Frame
|
||||
#define PHY_MODE_CTRL_FRAME_10KBPS_20MS 0x00000400U // Benchmark Frame
|
||||
#define PHY_MODE_CTRL_FRAME_40KBPS_20MS 0x00000500U
|
||||
#define PHY_MODE_CTRL_FRAME_40KBPS_10MS 0x00000600U
|
||||
#define PHY_MODE_CTRL_FRAME_200KBPS_5MS 0x00000700U // 2-Way ACQ Frame, Management Frame, Service Frame
|
||||
#define PHY_MODE_CTRL_FRAME_1M2BPS_5MS 0x00000800U // Bistatic Synthetic Aperture Radar Frame
|
||||
|
||||
#define PHY_MODE_CTRL_CRC_EN 0x00010000U
|
||||
#define PHY_MODE_CTRL_CRC_DSBL 0x00000000U
|
||||
/**
|
||||
* Register: POLLTIME_L
|
||||
*/
|
||||
#define POLLTIME_L 0x00000008U
|
||||
#define POLLTIME_L_SHIFT 0
|
||||
#define POLLTIME_L_WIDTH 32
|
||||
#define POLLTIME_L_MASK 0xFFFFFFFFU
|
||||
|
||||
/**
|
||||
* Register: POLLTIME_H
|
||||
*/
|
||||
#define POLLTIME_H 0x0000000CU
|
||||
#define POLLTIME_H_SHIFT 0
|
||||
#define POLLTIME_H_WIDTH 32
|
||||
#define POLLTIME_H_MASK 0xFFFFFFFFU
|
||||
|
||||
/**
|
||||
* Register: TIMEOUT_L
|
||||
*/
|
||||
#define LISTENTIMEOUT_L 0x00000010U
|
||||
#define LISTENTIMEOUT_L_SHIFT 0
|
||||
#define LISTENTIMEOUT_L_WIDTH 32
|
||||
#define LISTENTIMEOUT_L_MASK 0xFFFFFFFFU
|
||||
|
||||
/**
|
||||
* Register: TIMEOUT_H
|
||||
*/
|
||||
#define LISTENTIMEOUT_H 0x00000014U
|
||||
#define LISTENTIMEOUT_H_SHIFT 0
|
||||
#define LISTENTIMEOUT_H_WIDTH 32
|
||||
#define LISTENTIMEOUT_H_MASK 0xFFFFFFFFU
|
||||
|
||||
/**
|
||||
* Register: ANT_CTRL
|
||||
*/
|
||||
#define ANT_CONFIG 0x00000018U
|
||||
#define ANT_CONFIG_OFFSET_SHIFT 0
|
||||
#define ANT_CONFIG_OFFSET_WIDTH 16
|
||||
#define ANT_CONFIG_OFFSET_MASK 0x0000FFFFU
|
||||
#define ANT_CONFIG_LEN_SHIFT 16
|
||||
#define ANT_CONFIG_LEN_WIDTH 8
|
||||
#define ANT_CONFIG_LEN_MASK 0x00FF0000U
|
||||
#define ANT_CONFIG_NUM_SHIFT 24
|
||||
#define ANT_CONFIG_NUM_WIDTH 8
|
||||
#define ANT_CONFIG_NUM_MASK 0xFF000000U
|
||||
|
||||
/**
|
||||
* Register: SEND_DATA_CMD
|
||||
*/
|
||||
#define SEND_DATA_CMD 0x0000001CU
|
||||
#define SEND_DATA_CMD_SHIFT 0
|
||||
#define SEND_DATA_CMD_WIDTH 32
|
||||
#define SEND_DATA_CMD_MASK 0xFFFFFFFFU
|
||||
|
||||
#define SEND_DATA_CMD_LEN_SHIFT 0
|
||||
#define SEND_DATA_CMD_LEN_WIDTH 16
|
||||
#define SEND_DATA_CMD_LEN_MASK 0x0000FFFFU
|
||||
#define SEND_DATA_CMD_OFFSET_SHIFT 16
|
||||
#define SEND_DATA_CMD_OFFSET_WIDTH 16
|
||||
#define SEND_DATA_CMD_OFFSET_MASK 0xFFFF0000U
|
||||
|
||||
/**
|
||||
* Register: SLOT_CONFIG_CMD
|
||||
*/
|
||||
#define SLOT_CMD 0x00000020U
|
||||
#define SLOT_CMD_SHIFT 0
|
||||
#define SLOT_CMD_WIDTH 32
|
||||
#define SLOT_CMD_MASK 0xFFFFFFFFU
|
||||
#define SLOT_CMD_KEY 0x434D442EU
|
||||
|
||||
/**
|
||||
* Register: TXRX_STATE
|
||||
*/
|
||||
#define TXRX_STATE 0x00000024U
|
||||
#define TXRX_STATE_ACQ_SHIFT 0
|
||||
#define TXRX_STATE_ACQ_WIDTH 8
|
||||
#define TXRX_STATE_ACQ_MASK 0x000000FFU
|
||||
#define TXRX_STATE_ACQ_SUCCESS 0x00000001U
|
||||
#define TXRX_STATE_ACQ_FAIL 0x00000002U
|
||||
|
||||
#define TXRX_STATE_FSYNC_SHIFT 8
|
||||
#define TXRX_STATE_FSYNC_WIDTH 8
|
||||
#define TXRX_STATE_FSYNC_MASK 0x0000FF00U
|
||||
#define TXRX_STATE_FSYNC_SUCCESS 0x00000100U
|
||||
#define TXRX_STATE_FSYNC_FAIL 0x00000200U
|
||||
|
||||
#define TXRX_STATE_DECODE_SHIFT 16
|
||||
#define TXRX_STATE_DECODE_WIDTH 8
|
||||
#define TXRX_STATE_DECODE_MASK 0x00FF0000U
|
||||
#define TXRX_STATE_DECODE_SUCCESS 0x00010000U
|
||||
#define TXRX_STATE_DECODE_FAIL 0x00020000U
|
||||
|
||||
#define TXRX_STATE_CRC_SHIFT 24
|
||||
#define TXRX_STATE_CRC_WIDTH 8
|
||||
#define TXRX_STATE_CRC_MASK 0xFF000000U
|
||||
#define TXRX_STATE_CRC_OK 0x01000000U
|
||||
#define TXRX_STATE_CRC_ERROR 0x02000000U
|
||||
|
||||
/**
|
||||
* Register: RECVDATA_STATE
|
||||
*/
|
||||
#define RECVDATA_STATE 0x00000028U
|
||||
#define RECVDATA_STATE_LEN_SHIFT 0
|
||||
#define RECVDATA_STATE_LEN_WIDTH 16
|
||||
#define RECVDATA_STATE_LEN_MASK 0x0000FFFFU
|
||||
|
||||
#define RECVDATA_STATE_OFFSET_SHIFT 16
|
||||
#define RECVDATA_STATE_OFFSET_WIDTH 16
|
||||
#define RECVDATA_STATE_OFFSET_MASK 0xFFFF0000U
|
||||
|
||||
/**
|
||||
* Register: FSTIME_L
|
||||
*/
|
||||
#define FSTIME_L 0x0000002CU
|
||||
#define FSTIME_L_SHIFT 0
|
||||
#define FSTIME_L_WIDTH 32
|
||||
#define FSTIME_L_MASK 0xFFFFFFFFU
|
||||
|
||||
/**
|
||||
* Register: FSTIME_INT1
|
||||
*/
|
||||
#define FSTIME_H 0x00000030U
|
||||
#define FSTIME_H_SHIFT 0
|
||||
#define FSTIME_H_WIDTH 32
|
||||
#define FSTIME_H_MASK 0xFFFFFFFFU
|
||||
|
||||
/**
|
||||
* Register: TM_TARGET_L
|
||||
*/
|
||||
#define TM_TARGET_L 0x00000064U
|
||||
#define TM_TARGET_L_SHIFT 0
|
||||
#define TM_TARGET_L_WIDTH 32
|
||||
#define TM_TARGET_L_MASK 0xFFFFFFFFU
|
||||
|
||||
/**
|
||||
* Register: TM_TARGET_H
|
||||
*/
|
||||
#define TM_TARGET_H 0x00000038U
|
||||
#define TM_TARGET_H_SHIFT 0
|
||||
#define TM_TARGET_H_WIDTH 32
|
||||
#define TM_TARGET_H_MASK 0xFFFFFFFFU
|
||||
|
||||
/**
|
||||
* Register: COASEFREQEST
|
||||
*/
|
||||
#define COASE_FREQEST 0x0000003CU
|
||||
#define COASE_FREQEST_ACQ_SHIFT 0
|
||||
#define COASE_FREQEST_ACQ_WIDTH 8
|
||||
#define COASE_FREQEST_ACQ_MASK 0x000000FFU
|
||||
#define COASE_FREQEST_SYNC_SHIFT 8
|
||||
#define COASE_FREQEST_SYNC_WIDTH 8
|
||||
#define COASE_FREQEST_SYNC_MASK 0x0000FF00U
|
||||
#define COASE_TYPE_SHIFT 16
|
||||
#define COASE_TYPE_WIDTH 8
|
||||
#define COASE_TYPE_MASK 0x00FF0000U
|
||||
#define COASE_TYPE_2KBPS_20MS 0x00010000U
|
||||
#define COASE_TYPE_2KBPS_100MS 0x00020000U
|
||||
#define COASE_TYPE_10KBPS_10MS 0x00030000U
|
||||
#define COASE_TYPE_10KBPS_20MS 0x00040000U
|
||||
#define COASE_TYPE_40KBPS_20MS 0x00050000U
|
||||
#define COASE_TYPE_40KBPS_10MS 0x00060000U
|
||||
#define COASE_TYPE_200KBPS_5MS 0x00070000U
|
||||
#define COASE_TYPE_1M2BPS_5MS 0x00080000U
|
||||
|
||||
/**
|
||||
* Register: FINE_FREQEST
|
||||
*/
|
||||
#define FINE_FREQEST 0x00000040U
|
||||
#define FINE_FREQEST_VAL_SHIFT 0
|
||||
#define FINE_FREQEST_VAL_WIDTH 24
|
||||
#define FINE_FREQEST_VAL_MASK 0x00FFFFFFU
|
||||
#define FINE_FREQEST_SIGN_SHIFT 24
|
||||
#define FINE_FREQEST_SIGN_WIDTH 8
|
||||
#define FINE_FREQEST_SIGN_MASK 0xFF000000U
|
||||
#define FINE_FREQEST_SIGN_POS 0x00000000U
|
||||
#define FINE_FREQEST_SIGN_NEG 0x01000000U
|
||||
|
||||
/**
|
||||
* Register: BEAM_SELECT
|
||||
*/
|
||||
#define BEAM_SELECT_INDEX 0x00000044U
|
||||
#define BEAM_SELECT_INDEX_SHIFT 0
|
||||
#define BEAM_SELECT_INDEX_WIDTH 32
|
||||
#define BEAM_SELECT_INDEX_MASK 0xFFFFFFFFU
|
||||
|
||||
/**
|
||||
* Register: BEAM_AXIS
|
||||
*/
|
||||
#define BEAM_AXIS 0x00000044U
|
||||
#define BEAM_AXIS_EL_SHIFT 0
|
||||
#define BEAM_AXIS_EL_WIDTH 16
|
||||
#define BEAM_AXIS_EL_MASK 0x0000FFFFU
|
||||
#define BEAM_AXIS_AZ_SHIFT 16
|
||||
#define BEAM_AXIS_AZ_WIDTH 16
|
||||
#define BEAM_AXIS_AZ_MASK 0xFFFF0000U
|
||||
|
||||
/**
|
||||
* Register: ANT_STATUS
|
||||
*/
|
||||
#define ANT_STATUS 0x00000100U
|
||||
#define ANT_STATUS_ANT_VOLT_SHIFT 0
|
||||
#define ANT_STATUS_ANT_VOLT_WIDTH 8
|
||||
#define ANT_STATUS_ANT_VOLT_MASK 0x000000FFU
|
||||
#define ANT_STATUS_ANT_VOLT_OK 0x00000001U
|
||||
|
||||
#define ANT_STATUS_RF_VOLT_SHIFT 8
|
||||
#define ANT_STATUS_RF_VOLT_WIDTH 8
|
||||
#define ANT_STATUS_RF_VOLT_MASK 0x0000FF00U
|
||||
#define ANT_STATUS_RF_VOLT_OK 0x00000100U
|
||||
|
||||
#define ANT_STATUS_NIL_VOLT_SHIFT 16
|
||||
#define ANT_STATUS_NIL_VOLT_WIDTH 8
|
||||
#define ANT_STATUS_NIL_VOLT_MASK 0x00FF0000U
|
||||
#define ANT_STATUS_NIL_VOLT_OK 0x00010000U
|
||||
|
||||
#define ANT_STATUS_CODE_SHIFT 24
|
||||
#define ANT_STATUS_CODE_WIDTH 8
|
||||
#define ANT_STATUS_CODE_MASK 0xFF000000U
|
||||
#define ANT_STATUS_CODE_OK 0x00000000U
|
||||
|
||||
/**
|
||||
* Register: ANT_FRAME_CNT
|
||||
*/
|
||||
#define ANT_FRAME_CNT 0x00000104U
|
||||
#define ANT_FRAME_CNT_SHIFT 0
|
||||
#define ANT_FRAME_CNT_WIDTH 32
|
||||
#define ANT_FRAME_CNT_MASK 0xFFFFFFFFU
|
||||
|
||||
/**
|
||||
* Register: ANT_RF_STATUS
|
||||
*/
|
||||
#define ANT_RF_STATUS 0x00000108U
|
||||
#define ANT_RF_STATUS_TEMP_SHIFT 0
|
||||
#define ANT_RF_STATUS_TEMP_WIDTH 8
|
||||
#define ANT_RF_STATUS_TEMP_MASK 0x000000FFU
|
||||
|
||||
#define ANT_RF_STATUS_BBLOCK_SHIFT 8
|
||||
#define ANT_RF_STATUS_BBLOCK_WIDTH 8
|
||||
#define ANT_RF_STATUS_BBLOCK_MASK 0x0000FF00U
|
||||
#define ANT_RF_STATUS_BBLOCK_OK 0x00000100U
|
||||
|
||||
#define ANT_RF_STATUS_PLLA_SHIFT 16
|
||||
#define ANT_RF_STATUS_PLLA_WIDTH 8
|
||||
#define ANT_RF_STATUS_PLLA_MASK 0x00FF0000U
|
||||
#define ANT_RF_STATUS_PLLA_OK 0x00010000U
|
||||
|
||||
#define ANT_RF_STATUS_PLLB_SHIFT 24
|
||||
#define ANT_RF_STATUS_PLLB_WIDTH 8
|
||||
#define ANT_RF_STATUS_PLLB_MASK 0xFF000000U
|
||||
#define ANT_RF_STATUS_PLLB_OK 0x01000000U
|
||||
|
||||
/**
|
||||
* Register: ANT_RF_MGC
|
||||
*/
|
||||
#define ANT_RF_MGC 0x0000010CU
|
||||
#define ANT_RF_MGC_CH1_SHIFT 0
|
||||
#define ANT_RF_MGC_CH1_WIDTH 4
|
||||
#define ANT_RF_MGC_CH1_MASK 0x0000000FU
|
||||
#define ANT_RF_MGC_CH2_SHIFT 8
|
||||
#define ANT_RF_MGC_CH2_WIDTH 4
|
||||
#define ANT_RF_MGC_CH2_MASK 0x00000F00U
|
||||
#define ANT_RF_MGC_CH3_SHIFT 16
|
||||
#define ANT_RF_MGC_CH3_WIDTH 4
|
||||
#define ANT_RF_MGC_CH3_MASK 0x000F0000U
|
||||
#define ANT_RF_MGC_CH4_SHIFT 24
|
||||
#define ANT_RF_MGC_CH4_WIDTH 4
|
||||
#define ANT_RF_MGC_CH4_MASK 0x0F000000U
|
||||
|
||||
/**
|
||||
* Register: ANT_RF_FRAME_CNT
|
||||
*/
|
||||
#define ANT_RF_FRAME_CNT 0x00000110U
|
||||
#define ANT_RF_FRAME_CNT_SHIFT 0
|
||||
#define ANT_RF_FRAME_CNT_WIDTH 32
|
||||
#define ANT_RF_FRAME_CNT_MASK 0xFFFFFFFFU
|
||||
|
||||
/**
|
||||
* Register: PHY_ACQ_CNT
|
||||
*/
|
||||
#define PHY_ACQ_CNT 0x00000114U
|
||||
#define PHY_ACQ_CNT_SHIFT 0
|
||||
#define PHY_ACQ_CNT_WIDTH 32
|
||||
#define PHY_ACQ_CNT_MASK 0xFFFFFFFFU
|
||||
|
||||
/**
|
||||
* Register: PHY_FRAME_SYNC_CNT
|
||||
*/
|
||||
#define PHY_FRAME_SYNC_CNT 0x00000118U
|
||||
#define PHY_FRAME_SYNC_CNT_SHIFT 0
|
||||
#define PHY_FRAME_SYNC_CNT_WIDTH 32
|
||||
#define PHY_FRAME_SYNC_CNT_MASK 0xFFFFFFFFU
|
||||
|
||||
/**
|
||||
* Register: PHY_DECODE_CNT
|
||||
*/
|
||||
#define PHY_DECODE_CNT 0x0000011CU
|
||||
#define PHY_DECODE_CNT_SHIFT 0
|
||||
#define PHY_DECODE_CNT_WIDTH 32
|
||||
#define PHY_DECODE_CNT_MASK 0xFFFFFFFFU
|
||||
|
||||
/**
|
||||
* Register: PHY_CRC_OK_CNT
|
||||
*/
|
||||
#define PHY_CRC_OK_CNT 0x00000120U
|
||||
#define PHY_CRC_OK_CNT_SHIFT 0
|
||||
#define PHY_CRC_OK_CNT_WIDTH 32
|
||||
#define PHY_CRC_OK_CNT_MASK 0xFFFFFFFFU
|
||||
|
||||
/**
|
||||
* Register: PHY_ACQ_PEAK_H
|
||||
*/
|
||||
#define PHY_ACQ_PEAK_H 0x00000124U
|
||||
#define PHY_ACQ_PEAK_H_SHIFT 0
|
||||
#define PHY_ACQ_PEAK_H_WIDTH 32
|
||||
#define PHY_ACQ_PEAK_H_MASK 0xFFFFFFFFU
|
||||
|
||||
/**
|
||||
* Register: PHY_ACQ_PEAK_L
|
||||
*/
|
||||
#define PHY_ACQ_PEAK_L 0x00000128U
|
||||
#define PHY_ACQ_PEAK_L_SHIFT 0
|
||||
#define PHY_ACQ_PEAK_L_WIDTH 32
|
||||
#define PHY_ACQ_PEAK_L_MASK 0xFFFFFFFFU
|
||||
|
||||
|
||||
/**
|
||||
* Register: PHY_ACQ_MEAN_H
|
||||
*/
|
||||
#define PHY_ACQ_MEAN_H 0x0000012CU
|
||||
#define PHY_ACQ_MEAN_H_SHIFT 0
|
||||
#define PHY_ACQ_MEAN_H_WIDTH 32
|
||||
#define PHY_ACQ_MEAN_H_MASK 0xFFFFFFFFU
|
||||
|
||||
/**
|
||||
* Register: PHY_ACQ_MEAN_L
|
||||
*/
|
||||
#define PHY_ACQ_MEAN_L 0x00000130U
|
||||
#define PHY_ACQ_MEAN_L_SHIFT 0
|
||||
#define PHY_ACQ_MEAN_L_WIDTH 32
|
||||
#define PHY_ACQ_MEAN_L_MASK 0xFFFFFFFFU
|
||||
|
||||
/**
|
||||
* Register: PHY_ACQ_FREQEST
|
||||
*/
|
||||
#define PHY_ACQ_FREQEST 0x00000134U
|
||||
#define PHY_ACQ_FREQEST_SHIFT 0
|
||||
#define PHY_ACQ_FREQEST_WIDTH 32
|
||||
#define PHY_ACQ_FREQEST_MASK 0xFFFFFFFFU
|
||||
|
||||
#define PHY_ACQ_FREQEST_PHASE_SHIFT 0
|
||||
#define PHY_ACQ_FREQEST_PHASE_WIDTH 8
|
||||
#define PHY_ACQ_FREQEST_PHASE_MASK 0x000000FFU
|
||||
#define PHY_ACQ_FREQEST_CHANNEL_SHIFT 8
|
||||
#define PHY_ACQ_FREQEST_CHANNEL_WIDTH 8
|
||||
#define PHY_ACQ_FREQEST_CHANNEL_MASK 0x0000FF00U
|
||||
|
||||
/**
|
||||
* Register: PHY_FRAME_SYNC_PEAK_H
|
||||
*/
|
||||
#define PHY_FRAME_SYNC_PEAK_H 0x00000138U
|
||||
#define PHY_FRAME_SYNC_PEAK_H_SHIFT 0
|
||||
#define PHY_FRAME_SYNC_PEAK_H_WIDTH 32
|
||||
#define PHY_FRAME_SYNC_PEAK_H_MASK 0xFFFFFFFFU
|
||||
|
||||
/**
|
||||
* Register: PHY_FRAME_SYNC_PEAK_L
|
||||
*/
|
||||
#define PHY_FRAME_SYNC_PEAK_L 0x0000013CU
|
||||
#define PHY_FRAME_SYNC_PEAK_L_SHIFT 0
|
||||
#define PHY_FRAME_SYNC_PEAK_L_WIDTH 32
|
||||
#define PHY_FRAME_SYNC_PEAK_L_MASK 0xFFFFFFFFU
|
||||
|
||||
|
||||
/**
|
||||
* Register: PHY_FRAME_SYNC_MEAN_H
|
||||
*/
|
||||
#define PHY_FRAME_SYNC_MEAN_H 0x00000140U
|
||||
#define PHY_FRAME_SYNC_MEAN_H_SHIFT 0
|
||||
#define PHY_FRAME_SYNC_MEAN_H_WIDTH 32
|
||||
#define PHY_FRAME_SYNC_MEAN_H_MASK 0xFFFFFFFFU
|
||||
|
||||
/**
|
||||
* Register: PHY_FRAME_SYNC_MEAN_L
|
||||
*/
|
||||
#define PHY_FRAME_SYNC_MEAN_L 0x00000144U
|
||||
#define PHY_FRAME_SYNC_MEAN_L_SHIFT 0
|
||||
#define PHY_FRAME_SYNC_MEAN_L_WIDTH 32
|
||||
#define PHY_FRAME_SYNC_MEAN_L_MASK 0xFFFFFFFFU
|
||||
|
||||
/**
|
||||
* Register: PHY_FRAME_SYNC_FREQEST
|
||||
*/
|
||||
#define PHY_FRAME_SYNC_FREQEST 0x00000148U
|
||||
#define PHY_FRAME_SYNC_FREQEST_SHIFT 0
|
||||
#define PHY_FRAME_SYNC_FREQEST_WIDTH 32
|
||||
#define PHY_FRAME_SYNC_FREQEST_MASK 0xFFFFFFFFU
|
||||
|
||||
#define PHY_FRAME_SYNC_FREQEST_CHANNEL_SHIFT 0
|
||||
#define PHY_FRAME_SYNC_FREQEST_CHANNEL_WIDTH 8
|
||||
#define PHY_FRAME_SYNC_FREQEST_CHANNEL_MASK 0x000000FFU
|
||||
|
||||
/**
|
||||
* Register: PHY_DEINTLV_AMPEST
|
||||
*/
|
||||
#define PHY_DEINTLV_AMPEST 0x0000014CU
|
||||
#define PHY_DEINTLV_AMPEST_SHIFT 0
|
||||
#define PHY_DEINTLV_AMPEST_WIDTH 16
|
||||
#define PHY_DEINTLV_AMPEST_MASK 0x0000FFFFU
|
||||
|
||||
#endif /* PHY_REG_H_ */
|
||||
|
||||
/** @} PhysicalLayer_REG_Constants*/
|
||||
|
||||
/** @} PhysicalLayer*/
|
||||
Reference in New Issue
Block a user