11 Commits
33 changed files with 3579 additions and 3179 deletions
+9 -8
View File
@@ -46,7 +46,7 @@
/************************** Function Prototypes ******************************/ /************************** Function Prototypes ******************************/
int32_t SetupInterruptSystem(struct irq_ctrl_desc *descPtr); int32_t SetupInterruptSystem(struct irq_ctrl_desc *descPtr);
void Phy_IntrHandler(void *context); void Phy_IntrHandler(void *context);
void PeriodicPull_Handler(void *callBackRef); void PeriodicPoll_Handler(void *callBackRef);
void ScuTimer_IntrHandler(void *context); void ScuTimer_IntrHandler(void *context);
void Mpc_RxIntrHandler(void *context); void Mpc_RxIntrHandler(void *context);
void Mpc_TxIntrHandler(void *context); void Mpc_TxIntrHandler(void *context);
@@ -57,9 +57,9 @@ struct callback_desc phy_callback_desc =
.ctx = NULL .ctx = NULL
}; };
struct callback_desc periodicpull_callback_desc = struct callback_desc periodicpoll_callback_desc =
{ {
.callback = PeriodicPull_Handler, .callback = PeriodicPoll_Handler,
.ctx = NULL .ctx = NULL
}; };
@@ -88,7 +88,8 @@ L2_CONFIG linkConfig =
.clustId = 1, .clustId = 1,
.myId = 1, .myId = 1,
.headId = 1, .headId = 1,
.netScale = 2, .netScale = 10,
.serviceRate = L2_SVC_128K,
.phyInstPtr = NULL, // physical layer reference .phyInstPtr = NULL, // physical layer reference
.tmcInstPtr = NULL .tmcInstPtr = NULL
}; };
@@ -246,7 +247,7 @@ int32_t SetupInterruptSystem(struct irq_ctrl_desc *descPtr)
return Status; return Status;
} }
// Connect the interrupt service routine isr1 to the interrupt controller // Connect the interrupt service routine isr1 to the interrupt controller
Status = irq_register_callback(descPtr, PERIODIC_5MS_INTR_ID, &periodicpull_callback_desc); Status = irq_register_callback(descPtr, PERIODIC_5MS_INTR_ID, &periodicpoll_callback_desc);
if (Status != SUCCESS) if (Status != SUCCESS)
{ {
DBG_ERROR("PHY_INTR register callback FAILED, ErrorCode: %" PRId32 ".\n", Status); DBG_ERROR("PHY_INTR register callback FAILED, ErrorCode: %" PRId32 ".\n", Status);
@@ -341,14 +342,14 @@ void Phy_IntrHandler(void *context)
/****************************************************************************/ /****************************************************************************/
/** /**
* Handler of periodic 5ms interrupt * Handler of periodic 2 ms interrupt
* *
* @param callBackRef is the linklayer instance pointer. * @param callBackRef is the linklayer instance pointer.
* *
* @return None. * @return None.
* *
*****************************************************************************/ *****************************************************************************/
void PeriodicPull_Handler(void *callBackRef) void PeriodicPoll_Handler(void *callBackRef)
{ {
int32_t Status; int32_t Status;
Status = Linklayer_Proc(linkInstPtr); Status = Linklayer_Proc(linkInstPtr);
@@ -357,7 +358,7 @@ void PeriodicPull_Handler(void *callBackRef)
DBG_ERROR("Link layer runs failed, with error code: %" PRId32 "\n", Status); DBG_ERROR("Link layer runs failed, with error code: %" PRId32 "\n", Status);
_nop_(); _nop_();
} }
} // PeriodicPull_Handler } // PeriodicPoll_Handler
/*****************************************************************************/ /*****************************************************************************/
/** /**
+62 -63
View File
@@ -23,7 +23,7 @@
#include "xparameters.h" #include "xparameters.h"
/******** Software Version ********/ /******** Software Version ********/
#define _APP_VER 0x00010008 #define _APP_VER 0x00010000
#define _APP_VER_MAIN ((_APP_VER & 0xFF000000) >> 24) #define _APP_VER_MAIN ((_APP_VER & 0xFF000000) >> 24)
#define _APP_VER_MINOR ((_APP_VER & 0x00FF0000) >> 16) #define _APP_VER_MINOR ((_APP_VER & 0x00FF0000) >> 16)
@@ -92,16 +92,6 @@
#define AD9363A_DEVICE 0 /* set it 1 if AD9363A device is used, 0 otherwise */ #define AD9363A_DEVICE 0 /* set it 1 if AD9363A device is used, 0 otherwise */
#define HAVE_VERBOSE_MESSAGES /* Recommended during development prints errors and warnings */ #define HAVE_VERBOSE_MESSAGES /* Recommended during development prints errors and warnings */
// #define HAVE_DEBUG_MESSAGES /* For Debug purposes only */ // #define HAVE_DEBUG_MESSAGES /* For Debug purposes only */
// -- AD9361 SPI Engine Configuration
#define AD9361_SPI_DEVICE_ID 0
#define AD9361_SPI_ENGINE_REF_CLK FCLK_CLK0_HZ
#define AD9361_SPI_ENGINE_MAX_SPEED 5000000
#define AD9361_SPI_ENGINE_BASEADDR XPAR_AXI_SPI_ENGINE_AXI_SPI_ENGINE_BASEADDR
#define AD9361_SPI_ENGINE_DATA_WIDTH 8
#define AD9361_SPI_ENGINE_CS_DELAY 3
#define AD9361_SPI_CS_AD9361_1 0x01
#define AD9361_SPI_CS_AD9361_2 0x02
#define AD9361_TIMEOUT_TH 2000
// AD9361 GPIO Configurations // AD9361 GPIO Configurations
#define AD9361_GPIO_DEVICE_ID 0 #define AD9361_GPIO_DEVICE_ID 0
#define AD9361_GPIO_OFFSET 54 #define AD9361_GPIO_OFFSET 54
@@ -109,57 +99,50 @@
#define AD9361_GPIO_OUTPUT 1 #define AD9361_GPIO_OUTPUT 1
#define AD9361_GPIO_DISABLE 0 #define AD9361_GPIO_DISABLE 0
#define AD9361_GPIO_ENABLE 1 #define AD9361_GPIO_ENABLE 1
// -- AD9361-1 // -- AD9361 SPI Engine Configuration
#define AD9361_1_TXNRX (AD9361_GPIO_OFFSET + 6) #define AD9361_SPI_DEVICE_ID 0
#define AD9361_1_ENABLE (AD9361_GPIO_OFFSET + 7) #define AD9361_SPI_ENGINE_REF_CLK FCLK_CLK0_HZ
#define AD9361_1_EN_AGC (AD9361_GPIO_OFFSET + 8) #define AD9361_SPI_ENGINE_MAX_SPEED 5000000
#define AD9361_1_RESET_B (AD9361_GPIO_OFFSET + 9) #define AD9361_SPI_ENGINE_BASEADDR XPAR_AXI_SPI_ENGINE_AXI_SPI_ENGINE_BASEADDR
#define AD9361_1_CTRL_OUT0 (AD9361_GPIO_OFFSET + 10) #define AD9361_SPI_ENGINE_DATA_WIDTH 8
#define AD9361_1_CTRL_OUT1 (AD9361_GPIO_OFFSET + 11) #define AD9361_SPI_ENGINE_CS_DELAY 3
#define AD9361_1_CTRL_OUT2 (AD9361_GPIO_OFFSET + 12) #define AD9361_TIMEOUT_TH 2000
#define AD9361_1_CTRL_OUT3 (AD9361_GPIO_OFFSET + 13) #define AD9361_1_SPI_CS 0x01
#define AD9361_1_CTRL_OUT4 (AD9361_GPIO_OFFSET + 14) #define AD9361_2_SPI_CS 0x02
#define AD9361_1_CTRL_OUT5 (AD9361_GPIO_OFFSET + 15) // -- AD9361-1 GPIO
#define AD9361_1_CTRL_OUT6 (AD9361_GPIO_OFFSET + 16) #define AD9361_1_TXNRX (AD9361_GPIO_OFFSET + 4)
#define AD9361_1_CTRL_OUT7 (AD9361_GPIO_OFFSET + 17) #define AD9361_1_ENABLE (AD9361_GPIO_OFFSET + 5)
#define AD9361_1_CTRL_IN0 (AD9361_GPIO_OFFSET + 18) #define AD9361_1_EN_AGC (AD9361_GPIO_OFFSET + 6)
#define AD9361_1_CTRL_IN1 (AD9361_GPIO_OFFSET + 19) #define AD9361_1_RESET_B (AD9361_GPIO_OFFSET + 7)
#define AD9361_1_CTRL_IN2 (AD9361_GPIO_OFFSET + 20) #define AD9361_1_CTRL_OUT0 (AD9361_GPIO_OFFSET + 8)
#define AD9361_1_CTRL_IN3 (AD9361_GPIO_OFFSET + 21) #define AD9361_1_CTRL_OUT1 (AD9361_GPIO_OFFSET + 9)
// AD9361-2 #define AD9361_1_CTRL_OUT2 (AD9361_GPIO_OFFSET + 10)
#define AD9361_2_TXNRX (AD9361_GPIO_OFFSET + 22) #define AD9361_1_CTRL_OUT3 (AD9361_GPIO_OFFSET + 11)
#define AD9361_2_ENABLE (AD9361_GPIO_OFFSET + 23) #define AD9361_1_CTRL_OUT4 (AD9361_GPIO_OFFSET + 12)
#define AD9361_2_EN_AGC (AD9361_GPIO_OFFSET + 24) #define AD9361_1_CTRL_OUT5 (AD9361_GPIO_OFFSET + 13)
#define AD9361_2_RESET_B (AD9361_GPIO_OFFSET + 25) #define AD9361_1_CTRL_OUT6 (AD9361_GPIO_OFFSET + 14)
#define AD9361_2_CTRL_OUT0 (AD9361_GPIO_OFFSET + 26) #define AD9361_1_CTRL_OUT7 (AD9361_GPIO_OFFSET + 15)
#define AD9361_2_CTRL_OUT1 (AD9361_GPIO_OFFSET + 27) #define AD9361_1_CTRL_IN0 (AD9361_GPIO_OFFSET + 16)
#define AD9361_2_CTRL_OUT2 (AD9361_GPIO_OFFSET + 28) #define AD9361_1_CTRL_IN1 (AD9361_GPIO_OFFSET + 17)
#define AD9361_2_CTRL_OUT3 (AD9361_GPIO_OFFSET + 29) #define AD9361_1_CTRL_IN2 (AD9361_GPIO_OFFSET + 18)
#define AD9361_2_CTRL_OUT4 (AD9361_GPIO_OFFSET + 30) #define AD9361_1_CTRL_IN3 (AD9361_GPIO_OFFSET + 19)
#define AD9361_2_CTRL_OUT5 (AD9361_GPIO_OFFSET + 31) // -- AD9361-2 GPIO
#define AD9361_2_CTRL_OUT6 (AD9361_GPIO_OFFSET + 32) #define AD9361_2_TXNRX (AD9361_GPIO_OFFSET + 20)
#define AD9361_2_CTRL_OUT7 (AD9361_GPIO_OFFSET + 33) #define AD9361_2_ENABLE (AD9361_GPIO_OFFSET + 21)
#define AD9361_2_CTRL_IN0 (AD9361_GPIO_OFFSET + 34) #define AD9361_2_EN_AGC (AD9361_GPIO_OFFSET + 22)
#define AD9361_2_CTRL_IN1 (AD9361_GPIO_OFFSET + 35) #define AD9361_2_RESET_B (AD9361_GPIO_OFFSET + 23)
#define AD9361_2_CTRL_IN2 (AD9361_GPIO_OFFSET + 36) #define AD9361_2_CTRL_OUT0 (AD9361_GPIO_OFFSET + 24)
#define AD9361_2_CTRL_IN3 (AD9361_GPIO_OFFSET + 37) #define AD9361_2_CTRL_OUT1 (AD9361_GPIO_OFFSET + 25)
// AD9361-Status Code #define AD9361_2_CTRL_OUT2 (AD9361_GPIO_OFFSET + 26)
#define AD9361_SYNC (AD9361_GPIO_OFFSET + 38) #define AD9361_2_CTRL_OUT3 (AD9361_GPIO_OFFSET + 27)
#define AD9361_RX_FIFO_RST (AD9361_GPIO_OFFSET + 39) #define AD9361_2_CTRL_OUT4 (AD9361_GPIO_OFFSET + 28)
#define AD9361_1_CAL_START (AD9361_GPIO_OFFSET + 40) #define AD9361_2_CTRL_OUT5 (AD9361_GPIO_OFFSET + 29)
#define AD9361_2_CAL_START (AD9361_GPIO_OFFSET + 41) #define AD9361_2_CTRL_OUT6 (AD9361_GPIO_OFFSET + 30)
#define AD9361_RECAL (AD9361_GPIO_OFFSET + 42) #define AD9361_2_CTRL_OUT7 (AD9361_GPIO_OFFSET + 31)
#define AD9361_TX_SWITCH (AD9361_GPIO_OFFSET + 43) #define AD9361_2_CTRL_IN0 (AD9361_GPIO_OFFSET + 32)
#define AD9361_1_CAL_DONE (AD9361_GPIO_OFFSET + 44) #define AD9361_2_CTRL_IN1 (AD9361_GPIO_OFFSET + 33)
#define AD9361_2_CAL_DONE (AD9361_GPIO_OFFSET + 45) #define AD9361_2_CTRL_IN2 (AD9361_GPIO_OFFSET + 34)
#define AD9361_CAL_RESULT (AD9361_GPIO_OFFSET + 46) #define AD9361_2_CTRL_IN3 (AD9361_GPIO_OFFSET + 35)
typedef enum
{
TX_FREQ_125,
TX_FREQ_126,
TX_FREQ_4125
} ad9361TxFreq;
// HMC7044 Configurations // HMC7044 Configurations
#define HMC7044_GPIO_DEVICE_ID 0 #define HMC7044_GPIO_DEVICE_ID 0
@@ -177,7 +160,23 @@ typedef enum
#define HMC7044_SPI_ENGINE_BASEADDR XPAR_AXI_SPI_ENGINE_AXI_SPI_ENGINE_BASEADDR #define HMC7044_SPI_ENGINE_BASEADDR XPAR_AXI_SPI_ENGINE_AXI_SPI_ENGINE_BASEADDR
#define HMC7044_SPI_ENGINE_DATA_WIDTH 8 #define HMC7044_SPI_ENGINE_DATA_WIDTH 8
#define HMC7044_SPI_ENGINE_CS_DELAY 3 #define HMC7044_SPI_ENGINE_CS_DELAY 3
#define HMC7044_SPI_CS_HMC7044 0x00 #define HMC7044_SPI_CS 0x00
// AD9528 Configurations
#define AD9528_GPIO_DEVICE_ID 0
#define AD9528_GPIO_OFFSET 54
#define AD9528_RESETB (AD9528_GPIO_OFFSET+0)
#define AD9528_SYSREF_REQ (AD9528_GPIO_OFFSET+1)
#define AD9528_STATUS_0 (AD9528_GPIO_OFFSET+2)
#define AD9528_STATUS_1 (AD9528_GPIO_OFFSET+3)
// -- AD9528 SPI Engine Configuration
#define AD9528_SPI_DEVICE_ID 0
#define AD9528_SPI_ENGINE_REF_CLK FCLK_CLK0_HZ
#define AD9528_SPI_ENGINE_MAX_SPEED 5000000
#define AD9528_SPI_ENGINE_BASEADDR XPAR_AXI_SPI_ENGINE_AXI_SPI_ENGINE_BASEADDR
#define AD9528_SPI_ENGINE_DATA_WIDTH 8
#define AD9528_SPI_ENGINE_CS_DELAY 3
#define AD9528_SPI_CS 0x00
// Configuration Check // Configuration Check
#if defined(PHY_BEAM_SET_PRESET) && !defined(PHY_BEAM_FORMING_ENABLE) #if defined(PHY_BEAM_SET_PRESET) && !defined(PHY_BEAM_FORMING_ENABLE)
@@ -273,7 +273,7 @@ AD9361_InitParam ad9361_default_init_param = {
{ {
.device_id = AD9361_SPI_DEVICE_ID, .device_id = AD9361_SPI_DEVICE_ID,
.mode = SPI_MODE_1, .mode = SPI_MODE_1,
.chip_select = AD9361_SPI_CS_AD9361_1, .chip_select = AD9361_1_SPI_CS,
.platform_ops = &spi_eng_platform_ops, .platform_ops = &spi_eng_platform_ops,
.extra = &spi_engine_param .extra = &spi_engine_param
}, },
@@ -25,7 +25,7 @@ static struct spi_init_param ad9361_1_reg_spi_init = {
.device_id = AD9361_SPI_DEVICE_ID, .device_id = AD9361_SPI_DEVICE_ID,
.max_speed_hz = AD9361_SPI_ENGINE_MAX_SPEED, .max_speed_hz = AD9361_SPI_ENGINE_MAX_SPEED,
.mode = SPI_MODE_1, .mode = SPI_MODE_1,
.chip_select = AD9361_SPI_CS_AD9361_1, .chip_select = AD9361_1_SPI_CS,
.platform_ops = &spi_eng_platform_ops, .platform_ops = &spi_eng_platform_ops,
.extra = &spi_engine_param .extra = &spi_engine_param
}; };
@@ -35,6 +35,7 @@ static struct gpio_init_param ad9361_1_reg_gpio_resetb_init = {
.platform_ops = &xil_gpio_ops, .platform_ops = &xil_gpio_ops,
.extra = &xil_gpio_param .extra = &xil_gpio_param
}; };
struct ad9361_reg_init_param ad9361_1_reg_default_init_param = { struct ad9361_reg_init_param ad9361_1_reg_default_init_param = {
/* SPI */ /* SPI */
.spi_init = &ad9361_1_reg_spi_init, .spi_init = &ad9361_1_reg_spi_init,
@@ -46,7 +47,7 @@ static struct spi_init_param ad9361_2_reg_spi_init = {
.device_id = AD9361_SPI_DEVICE_ID, .device_id = AD9361_SPI_DEVICE_ID,
.max_speed_hz = AD9361_SPI_ENGINE_MAX_SPEED, .max_speed_hz = AD9361_SPI_ENGINE_MAX_SPEED,
.mode = SPI_MODE_1, .mode = SPI_MODE_1,
.chip_select = AD9361_SPI_CS_AD9361_2, .chip_select = AD9361_2_SPI_CS,
.platform_ops = &spi_eng_platform_ops, .platform_ops = &spi_eng_platform_ops,
.extra = &spi_engine_param .extra = &spi_engine_param
}; };
@@ -56,6 +57,7 @@ static struct gpio_init_param ad9361_2_reg_gpio_resetb_init = {
.platform_ops = &xil_gpio_ops, .platform_ops = &xil_gpio_ops,
.extra = &xil_gpio_param .extra = &xil_gpio_param
}; };
struct ad9361_reg_init_param ad9361_2_reg_default_init_param = { struct ad9361_reg_init_param ad9361_2_reg_default_init_param = {
/* SPI */ /* SPI */
.spi_init = &ad9361_2_reg_spi_init, .spi_init = &ad9361_2_reg_spi_init,
@@ -72,7 +74,7 @@ uint32_t ad9361_reg_config(struct ad9361_reg_dev *dev){
// generated using the AD9361 Customer software Version 2.1.3 // generated using the AD9361 Customer software Version 2.1.3
//************************************************************ //************************************************************
// Profile: Custom // Profile: Custom
// REFCLK_IN: 25.000 MHz // REFCLK_IN: 40.000 MHz
status = ad9361_reg_write(dev, 0x03DF, 0x01); // Required for proper operation status = ad9361_reg_write(dev, 0x03DF, 0x01); // Required for proper operation
@@ -87,527 +89,40 @@ uint32_t ad9361_reg_config(struct ad9361_reg_dev *dev){
// Set BBPLL Frequency: 1152.000000 // Set BBPLL Frequency: 1152.000000
//************************************************************ //************************************************************
status = ad9361_reg_write(dev, 0x0045, 0x03); // Set BBPLL reflclk scale to REFCLK * 2 status = ad9361_reg_write(dev, 0x0045, 0x03); // Set BBPLL reflclk scale to REFCLK * 2
status = ad9361_reg_write(dev, 0x0046, 0x03); // Set BBPLL Loop Filter Charge Pump current status = ad9361_reg_write(dev, 0x0046, 0x02); // Set BBPLL Loop Filter Charge Pump current
status = ad9361_reg_write(dev, 0x0048, 0xE8); // Set BBPLL Loop Filter C1, R1 status = ad9361_reg_write(dev, 0x0048, 0xE8); // Set BBPLL Loop Filter C1, R1
status = ad9361_reg_write(dev, 0x0049, 0x5B); // Set BBPLL Loop Filter R2, C2, C1 status = ad9361_reg_write(dev, 0x0049, 0x5B); // Set BBPLL Loop Filter R2, C2, C1
status = ad9361_reg_write(dev, 0x004A, 0x35); // Set BBPLL Loop Filter C3,R2 status = ad9361_reg_write(dev, 0x004A, 0x35); // Set BBPLL Loop Filter C3,R2
status = ad9361_reg_write(dev, 0x004B, 0xE0); // Allow calibration to occur and set cal count to 1024 for max accuracy status = ad9361_reg_write(dev, 0x004B, 0xE0); // Allow calibration to occur and set cal count to 1024 for max accuracy
status = ad9361_reg_write(dev, 0x004E, 0x10); // Set calibration clock to REFCLK/4 for more accuracy status = ad9361_reg_write(dev, 0x004E, 0x10); // Set calibration clock to REFCLK/4 for more accuracy
status = ad9361_reg_write(dev, 0x0043, 0x66); // BBPLL Freq Word (Fractional[7:0]) status = ad9361_reg_write(dev, 0x0043, 0x00); // BBPLL Freq Word (Fractional[7:0])
status = ad9361_reg_write(dev, 0x0042, 0x46); // BBPLL Freq Word (Fractional[15:8]) status = ad9361_reg_write(dev, 0x0042, 0xC0); // BBPLL Freq Word (Fractional[15:8])
status = ad9361_reg_write(dev, 0x0041, 0x01); // BBPLL Freq Word (Fractional[23:16]) status = ad9361_reg_write(dev, 0x0041, 0x0C); // BBPLL Freq Word (Fractional[23:16])
status = ad9361_reg_write(dev, 0x0044, 0x17); // BBPLL Freq Word (Integer[7:0]) status = ad9361_reg_write(dev, 0x0044, 0x0E); // BBPLL Freq Word (Integer[7:0])
status = ad9361_reg_write(dev, 0x003F, 0x05); // Start BBPLL Calibration status = ad9361_reg_write(dev, 0x003F, 0x05); // Start BBPLL Calibration
status = ad9361_reg_write(dev, 0x003F, 0x01); // Clear BBPLL start calibration bit status = ad9361_reg_write(dev, 0x003F, 0x01); // Clear BBPLL start calibration bit
status = ad9361_reg_write(dev, 0x004C, 0x86); // Increase BBPLL KV and phase margin status = ad9361_reg_write(dev, 0x004C, 0x86); // Increase BBPLL KV and phase margin
status = ad9361_reg_write(dev, 0x004D, 0x01); // Increase BBPLL KV and phase margin status = ad9361_reg_write(dev, 0x004D, 0x01); // Increase BBPLL KV and phase margin
status = ad9361_reg_write(dev, 0x004D, 0x05); // Increase BBPLL KV and phase margin status = ad9361_reg_write(dev, 0x004D, 0x05); // Increase BBPLL KV and phase margin
// Wait for BBPLL to lock, Timeout 2sec, Max BBPLL VCO Cal Time: 276.480 us (Done when 0x05E[7]==1) // Wait for BBPLL to lock, Timeout 2sec, Max BBPLL VCO Cal Time: 172.800 us (Done when 0x05E[7]==1)
time_out_cnt = 0; time_out_cnt = 0;
do{ do{
status |= ad9361_reg_read(dev, 0x005E, &value); status |= ad9361_reg_read(dev, 0x005E, &value);
mdelay(1);// Wait 1ms mdelay(1);// Wait 1ms
time_out_cnt++; time_out_cnt++;
} while((value & 0x80) != 0x80 && time_out_cnt <= AD9361_TIMEOUT_TH); } while((value & 0x80) != 0x80 && time_out_cnt <= TIMEOUT_TH);
status = ad9361_reg_write(dev, 0x0002, 0xA4); // Setup Tx Digital Filters/ Channels status = ad9361_reg_write(dev, 0x0002, 0xA4); // Setup Tx Digital Filters/ Channels
status = ad9361_reg_write(dev, 0x0003, 0xE5); // Setup Rx Digital Filters/ Channels status = ad9361_reg_write(dev, 0x0003, 0xE4); // Setup Rx Digital Filters/ Channels
status = ad9361_reg_write(dev, 0x0004, 0x03); // Select Rx input pin(A,B,C)/ Tx out pin (A,B) status = ad9361_reg_write(dev, 0x0004, 0x03); // Select Rx input pin(A,B,C)/ Tx out pin (A,B)
status = ad9361_reg_write(dev, 0x000A, 0x12); // Set BBPLL post divide rate status = ad9361_reg_write(dev, 0x000A, 0x12); // Set BBPLL post divide rate
//************************************************************
// Program Rx FIR: C:\Users\josh\Desktop\Config\rx64.txt
//************************************************************
status = ad9361_reg_write(dev, 0x00F5, 0x9A); // Enable clock to Rx FIR Filter
status = ad9361_reg_write(dev, 0x00F6, 0x02); // Write Filter Gain setting
status = ad9361_reg_write(dev, 0x00F0, 0x00); // Write FIR coefficient address
status = ad9361_reg_write(dev, 0x00F1, 0x00); // Write FIR coefficient data[7:0]
status = ad9361_reg_write(dev, 0x00F2, 0x00); // Write FIR coefficient data[15:8]
status = ad9361_reg_write(dev, 0x00F5, 0x9E); // Set Write EN to push data into FIR filter register map
status = ad9361_reg_write(dev, 0x00F4, 0x00); // Dummy Write to Read only register to delay ~1us
status = ad9361_reg_write(dev, 0x00F4, 0x00); // Dummy Write to Read only register to delay ~1us
status = ad9361_reg_write(dev, 0x00F0, 0x01);
status = ad9361_reg_write(dev, 0x00F1, 0xB6);
status = ad9361_reg_write(dev, 0x00F2, 0xFF);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x02);
status = ad9361_reg_write(dev, 0x00F1, 0xA5);
status = ad9361_reg_write(dev, 0x00F2, 0xFF);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x03);
status = ad9361_reg_write(dev, 0x00F1, 0xEA);
status = ad9361_reg_write(dev, 0x00F2, 0xFF);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x04);
status = ad9361_reg_write(dev, 0x00F1, 0x61);
status = ad9361_reg_write(dev, 0x00F2, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x05);
status = ad9361_reg_write(dev, 0x00F1, 0xA3);
status = ad9361_reg_write(dev, 0x00F2, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x06);
status = ad9361_reg_write(dev, 0x00F1, 0x4D);
status = ad9361_reg_write(dev, 0x00F2, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x07);
status = ad9361_reg_write(dev, 0x00F1, 0x77);
status = ad9361_reg_write(dev, 0x00F2, 0xFF);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x08);
status = ad9361_reg_write(dev, 0x00F1, 0xD5);
status = ad9361_reg_write(dev, 0x00F2, 0xFE);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x09);
status = ad9361_reg_write(dev, 0x00F1, 0x38);
status = ad9361_reg_write(dev, 0x00F2, 0xFF);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x0A);
status = ad9361_reg_write(dev, 0x00F1, 0xA5);
status = ad9361_reg_write(dev, 0x00F2, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x0B);
status = ad9361_reg_write(dev, 0x00F1, 0xF8);
status = ad9361_reg_write(dev, 0x00F2, 0x01);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x0C);
status = ad9361_reg_write(dev, 0x00F1, 0xAD);
status = ad9361_reg_write(dev, 0x00F2, 0x01);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x0D);
status = ad9361_reg_write(dev, 0x00F1, 0x75);
status = ad9361_reg_write(dev, 0x00F2, 0xFF);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x0E);
status = ad9361_reg_write(dev, 0x00F1, 0xFD);
status = ad9361_reg_write(dev, 0x00F2, 0xFC);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x0F);
status = ad9361_reg_write(dev, 0x00F1, 0xD8);
status = ad9361_reg_write(dev, 0x00F2, 0xFC);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x10);
status = ad9361_reg_write(dev, 0x00F1, 0x00);
status = ad9361_reg_write(dev, 0x00F2, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x11);
status = ad9361_reg_write(dev, 0x00F1, 0x3A);
status = ad9361_reg_write(dev, 0x00F2, 0x04);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x12);
status = ad9361_reg_write(dev, 0x00F1, 0x6B);
status = ad9361_reg_write(dev, 0x00F2, 0x05);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x13);
status = ad9361_reg_write(dev, 0x00F1, 0x51);
status = ad9361_reg_write(dev, 0x00F2, 0x01);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x14);
status = ad9361_reg_write(dev, 0x00F1, 0x80);
status = ad9361_reg_write(dev, 0x00F2, 0xFA);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x15);
status = ad9361_reg_write(dev, 0x00F1, 0x34);
status = ad9361_reg_write(dev, 0x00F2, 0xF7);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x16);
status = ad9361_reg_write(dev, 0x00F1, 0x08);
status = ad9361_reg_write(dev, 0x00F2, 0xFC);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x17);
status = ad9361_reg_write(dev, 0x00F1, 0xB2);
status = ad9361_reg_write(dev, 0x00F2, 0x06);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x18);
status = ad9361_reg_write(dev, 0x00F1, 0x1A);
status = ad9361_reg_write(dev, 0x00F2, 0x0E);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x19);
status = ad9361_reg_write(dev, 0x00F1, 0x44);
status = ad9361_reg_write(dev, 0x00F2, 0x09);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x1A);
status = ad9361_reg_write(dev, 0x00F1, 0x54);
status = ad9361_reg_write(dev, 0x00F2, 0xF8);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x1B);
status = ad9361_reg_write(dev, 0x00F1, 0xD1);
status = ad9361_reg_write(dev, 0x00F2, 0xE7);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x1C);
status = ad9361_reg_write(dev, 0x00F1, 0xC2);
status = ad9361_reg_write(dev, 0x00F2, 0xE9);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x1D);
status = ad9361_reg_write(dev, 0x00F1, 0x4F);
status = ad9361_reg_write(dev, 0x00F2, 0x08);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x1E);
status = ad9361_reg_write(dev, 0x00F1, 0xB2);
status = ad9361_reg_write(dev, 0x00F2, 0x3B);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x1F);
status = ad9361_reg_write(dev, 0x00F1, 0x2A);
status = ad9361_reg_write(dev, 0x00F2, 0x6C);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x20);
status = ad9361_reg_write(dev, 0x00F1, 0xFF);
status = ad9361_reg_write(dev, 0x00F2, 0x7F);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x21);
status = ad9361_reg_write(dev, 0x00F1, 0x2A);
status = ad9361_reg_write(dev, 0x00F2, 0x6C);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x22);
status = ad9361_reg_write(dev, 0x00F1, 0xB2);
status = ad9361_reg_write(dev, 0x00F2, 0x3B);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x23);
status = ad9361_reg_write(dev, 0x00F1, 0x4F);
status = ad9361_reg_write(dev, 0x00F2, 0x08);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x24);
status = ad9361_reg_write(dev, 0x00F1, 0xC2);
status = ad9361_reg_write(dev, 0x00F2, 0xE9);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x25);
status = ad9361_reg_write(dev, 0x00F1, 0xD1);
status = ad9361_reg_write(dev, 0x00F2, 0xE7);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x26);
status = ad9361_reg_write(dev, 0x00F1, 0x54);
status = ad9361_reg_write(dev, 0x00F2, 0xF8);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x27);
status = ad9361_reg_write(dev, 0x00F1, 0x44);
status = ad9361_reg_write(dev, 0x00F2, 0x09);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x28);
status = ad9361_reg_write(dev, 0x00F1, 0x1A);
status = ad9361_reg_write(dev, 0x00F2, 0x0E);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x29);
status = ad9361_reg_write(dev, 0x00F1, 0xB2);
status = ad9361_reg_write(dev, 0x00F2, 0x06);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x2A);
status = ad9361_reg_write(dev, 0x00F1, 0x08);
status = ad9361_reg_write(dev, 0x00F2, 0xFC);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x2B);
status = ad9361_reg_write(dev, 0x00F1, 0x34);
status = ad9361_reg_write(dev, 0x00F2, 0xF7);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x2C);
status = ad9361_reg_write(dev, 0x00F1, 0x80);
status = ad9361_reg_write(dev, 0x00F2, 0xFA);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x2D);
status = ad9361_reg_write(dev, 0x00F1, 0x51);
status = ad9361_reg_write(dev, 0x00F2, 0x01);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x2E);
status = ad9361_reg_write(dev, 0x00F1, 0x6B);
status = ad9361_reg_write(dev, 0x00F2, 0x05);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x2F);
status = ad9361_reg_write(dev, 0x00F1, 0x3A);
status = ad9361_reg_write(dev, 0x00F2, 0x04);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x30);
status = ad9361_reg_write(dev, 0x00F1, 0x00);
status = ad9361_reg_write(dev, 0x00F2, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x31);
status = ad9361_reg_write(dev, 0x00F1, 0xD8);
status = ad9361_reg_write(dev, 0x00F2, 0xFC);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x32);
status = ad9361_reg_write(dev, 0x00F1, 0xFD);
status = ad9361_reg_write(dev, 0x00F2, 0xFC);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x33);
status = ad9361_reg_write(dev, 0x00F1, 0x75);
status = ad9361_reg_write(dev, 0x00F2, 0xFF);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x34);
status = ad9361_reg_write(dev, 0x00F1, 0xAD);
status = ad9361_reg_write(dev, 0x00F2, 0x01);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x35);
status = ad9361_reg_write(dev, 0x00F1, 0xF8);
status = ad9361_reg_write(dev, 0x00F2, 0x01);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x36);
status = ad9361_reg_write(dev, 0x00F1, 0xA5);
status = ad9361_reg_write(dev, 0x00F2, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x37);
status = ad9361_reg_write(dev, 0x00F1, 0x38);
status = ad9361_reg_write(dev, 0x00F2, 0xFF);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x38);
status = ad9361_reg_write(dev, 0x00F1, 0xD5);
status = ad9361_reg_write(dev, 0x00F2, 0xFE);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x39);
status = ad9361_reg_write(dev, 0x00F1, 0x77);
status = ad9361_reg_write(dev, 0x00F2, 0xFF);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x3A);
status = ad9361_reg_write(dev, 0x00F1, 0x4D);
status = ad9361_reg_write(dev, 0x00F2, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x3B);
status = ad9361_reg_write(dev, 0x00F1, 0xA3);
status = ad9361_reg_write(dev, 0x00F2, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x3C);
status = ad9361_reg_write(dev, 0x00F1, 0x61);
status = ad9361_reg_write(dev, 0x00F2, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x3D);
status = ad9361_reg_write(dev, 0x00F1, 0xEA);
status = ad9361_reg_write(dev, 0x00F2, 0xFF);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x3E);
status = ad9361_reg_write(dev, 0x00F1, 0xA5);
status = ad9361_reg_write(dev, 0x00F2, 0xFF);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x3F);
status = ad9361_reg_write(dev, 0x00F1, 0xB6);
status = ad9361_reg_write(dev, 0x00F2, 0xFF);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x40);
status = ad9361_reg_write(dev, 0x00F1, 0x00);
status = ad9361_reg_write(dev, 0x00F2, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x41);
status = ad9361_reg_write(dev, 0x00F1, 0x00);
status = ad9361_reg_write(dev, 0x00F2, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x42);
status = ad9361_reg_write(dev, 0x00F1, 0x00);
status = ad9361_reg_write(dev, 0x00F2, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x43);
status = ad9361_reg_write(dev, 0x00F1, 0x00);
status = ad9361_reg_write(dev, 0x00F2, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x44);
status = ad9361_reg_write(dev, 0x00F1, 0x00);
status = ad9361_reg_write(dev, 0x00F2, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x45);
status = ad9361_reg_write(dev, 0x00F1, 0x00);
status = ad9361_reg_write(dev, 0x00F2, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x46);
status = ad9361_reg_write(dev, 0x00F1, 0x00);
status = ad9361_reg_write(dev, 0x00F2, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x47);
status = ad9361_reg_write(dev, 0x00F1, 0x00);
status = ad9361_reg_write(dev, 0x00F2, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x48);
status = ad9361_reg_write(dev, 0x00F1, 0x00);
status = ad9361_reg_write(dev, 0x00F2, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x49);
status = ad9361_reg_write(dev, 0x00F1, 0x00);
status = ad9361_reg_write(dev, 0x00F2, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x4A);
status = ad9361_reg_write(dev, 0x00F1, 0x00);
status = ad9361_reg_write(dev, 0x00F2, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x4B);
status = ad9361_reg_write(dev, 0x00F1, 0x00);
status = ad9361_reg_write(dev, 0x00F2, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x4C);
status = ad9361_reg_write(dev, 0x00F1, 0x00);
status = ad9361_reg_write(dev, 0x00F2, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x4D);
status = ad9361_reg_write(dev, 0x00F1, 0x00);
status = ad9361_reg_write(dev, 0x00F2, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x4E);
status = ad9361_reg_write(dev, 0x00F1, 0x00);
status = ad9361_reg_write(dev, 0x00F2, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x4F);
status = ad9361_reg_write(dev, 0x00F1, 0x00);
status = ad9361_reg_write(dev, 0x00F2, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x98); // Disable clock to Rx Filter
//************************************************************ //************************************************************
// Setup the Parallel Port (Digital Data Interface) // Setup the Parallel Port (Digital Data Interface)
//************************************************************ //************************************************************
status = ad9361_reg_write(dev, 0x0010, 0xC8); // I/O Config. Tx Swap IQ; Rx Swap IQ; Tx CH Swap, Rx CH Swap; Rx Frame Mode; 2R2T bit; Invert data bus; Invert DATA_CLK status = ad9361_reg_write(dev, 0x0010, 0xCC); // I/O Config. Tx Swap IQ; Rx Swap IQ; Tx CH Swap, Rx CH Swap; Rx Frame Mode; 2R2T bit; Invert data bus; Invert DATA_CLK
status = ad9361_reg_write(dev, 0x0011, 0x00); // I/O Config. Alt Word Order; -Rx1; -Rx2; -Tx1; -Tx2; Invert Rx Frame; Delay Rx Data status = ad9361_reg_write(dev, 0x0011, 0x00); // I/O Config. Alt Word Order; -Rx1; -Rx2; -Tx1; -Tx2; Invert Rx Frame; Delay Rx Data
status = ad9361_reg_write(dev, 0x0012, 0x02); // I/O Config. Rx=2*Tx; Swap Ports; SDR; LVDS; Half Duplex; Single Port; Full Port; Swap Bits status = ad9361_reg_write(dev, 0x0012, 0x02); // I/O Config. Rx=2*Tx; Swap Ports; SDR; LVDS; Half Duplex; Single Port; Full Port; Swap Bits
status = ad9361_reg_write(dev, 0x0006, 0x00); // PPORT Rx Delay (adjusts Tco Dataclk->Data) status = ad9361_reg_write(dev, 0x0006, 0x00); // PPORT Rx Delay (adjusts Tco Dataclk->Data)
@@ -646,7 +161,7 @@ uint32_t ad9361_reg_config(struct ad9361_reg_dev *dev){
//************************************************************ //************************************************************
// Setup GPO // Setup GPO
//************************************************************ //************************************************************
status = ad9361_reg_write(dev, 0x003A, 0x18); // Set number of REFCLK cycles for 1us delay timer status = ad9361_reg_write(dev, 0x003A, 0x27); // Set number of REFCLK cycles for 1us delay timer
status = ad9361_reg_write(dev, 0x0020, 0x00); // GPO Auto Enable Setup in RX and TX status = ad9361_reg_write(dev, 0x0020, 0x00); // GPO Auto Enable Setup in RX and TX
status = ad9361_reg_write(dev, 0x0027, 0x00); // GPO Manual and GPO auto value in ALERT status = ad9361_reg_write(dev, 0x0027, 0x00); // GPO Manual and GPO auto value in ALERT
status = ad9361_reg_write(dev, 0x0028, 0x00); // GPO_0 RX Delay status = ad9361_reg_write(dev, 0x0028, 0x00); // GPO_0 RX Delay
@@ -683,74 +198,74 @@ uint32_t ad9361_reg_config(struct ad9361_reg_dev *dev){
status = ad9361_reg_write(dev, 0x023D, 0x04); // Start RX CP cal status = ad9361_reg_write(dev, 0x023D, 0x04); // Start RX CP cal
// Wait for CP cal to complete, Max RXCP Cal time: 737.280 (us)(Done when 0x244[7]==1) // Wait for CP cal to complete, Max RXCP Cal time: 460.800 (us)(Done when 0x244[7]==1)
time_out_cnt = 0; time_out_cnt = 0;
do{ do{
status |= ad9361_reg_read(dev, 0x0244, &value); status |= ad9361_reg_read(dev, 0x0244, &value);
mdelay(1);// Wait 1ms mdelay(1);// Wait 1ms
time_out_cnt++; time_out_cnt++;
} while((value & 0x80) != 0x80 && time_out_cnt <= AD9361_TIMEOUT_TH); } while((value & 0x80) != 0x80 && time_out_cnt <= TIMEOUT_TH);
status = ad9361_reg_write(dev, 0x027D, 0x04); // Start TX CP cal status = ad9361_reg_write(dev, 0x027D, 0x04); // Start TX CP cal
// Wait for CP cal to complete, Max TXCP Cal time: 737.280 (us)(Done when 0x284[7]==1) // Wait for CP cal to complete, Max TXCP Cal time: 460.800 (us)(Done when 0x284[7]==1)
time_out_cnt = 0; time_out_cnt = 0;
do{ do{
status |= ad9361_reg_read(dev, 0x0284, &value); status |= ad9361_reg_read(dev, 0x0284, &value);
mdelay(1);// Wait 1ms mdelay(1);// Wait 1ms
time_out_cnt++; time_out_cnt++;
} while((value & 0x80) != 0x80 && time_out_cnt <= AD9361_TIMEOUT_TH); } while((value & 0x80) != 0x80 && time_out_cnt <= TIMEOUT_TH);
status = ad9361_reg_write(dev, 0x023D, 0x00); // Disable RX CP Calibration since the CP Cal start bit is not self-clearing. Only important if the script is run again without restting the DUT status = ad9361_reg_write(dev, 0x023D, 0x00); // Disable RX CP Calibration since the CP Cal start bit is not self-clearing. Only important if the script is run again without restting the DUT
status = ad9361_reg_write(dev, 0x027D, 0x00); // Disable TX CP Calibration since the CP Cal start bit is not self-clearing. Only important if the script is run again without restting the DUT status = ad9361_reg_write(dev, 0x027D, 0x00); // Disable TX CP Calibration since the CP Cal start bit is not self-clearing. Only important if the script is run again without restting the DUT
//************************************************************ //************************************************************
// FDD RX,TX Synth Frequency: 125.000000,4125.000000 MHz // FDD RX,TX Synth Frequency: 1268.250000,1268.250000 MHz
//************************************************************ //************************************************************
//************************************************************ //************************************************************
// Setup Rx Frequency-Dependent Syntheisizer Registers // Setup Rx Frequency-Dependent Syntheisizer Registers
//************************************************************ //************************************************************
status = ad9361_reg_write(dev, 0x023A, 0x4A); // Set VCO Output level[3:0] status = ad9361_reg_write(dev, 0x023A, 0x4A); // Set VCO Output level[3:0]
status = ad9361_reg_write(dev, 0x0239, 0xC1); // Set Init ALC Value[3:0] and VCO Varactor[3:0] status = ad9361_reg_write(dev, 0x0239, 0xC0); // Set Init ALC Value[3:0] and VCO Varactor[3:0]
status = ad9361_reg_write(dev, 0x0242, 0x0E); // Set VCO Bias Tcf[1:0] and VCO Bias Ref[2:0] status = ad9361_reg_write(dev, 0x0242, 0x0D); // Set VCO Bias Tcf[1:0] and VCO Bias Ref[2:0]
status = ad9361_reg_write(dev, 0x0238, 0x78); // Set VCO Cal Offset[3:0] status = ad9361_reg_write(dev, 0x0238, 0x70); // Set VCO Cal Offset[3:0]
status = ad9361_reg_write(dev, 0x0245, 0x00); // Set VCO Cal Ref Tcf[2:0] status = ad9361_reg_write(dev, 0x0245, 0x00); // Set VCO Cal Ref Tcf[2:0]
status = ad9361_reg_write(dev, 0x0251, 0x0B); // Set VCO Varactor Reference[3:0] status = ad9361_reg_write(dev, 0x0251, 0x09); // Set VCO Varactor Reference[3:0]
status = ad9361_reg_write(dev, 0x0250, 0x70); // Set VCO Varactor Ref Tcf[2:0] and VCO Varactor Offset[3:0] status = ad9361_reg_write(dev, 0x0250, 0x70); // Set VCO Varactor Ref Tcf[2:0] and VCO Varactor Offset[3:0]
status = ad9361_reg_write(dev, 0x023B, 0x94); // Set Synth Loop Filter charge pump current (Icp) status = ad9361_reg_write(dev, 0x023B, 0x8F); // Set Synth Loop Filter charge pump current (Icp)
status = ad9361_reg_write(dev, 0x023E, 0xF4); // Set Synth Loop Filter C2 and C1 status = ad9361_reg_write(dev, 0x023E, 0xD4); // Set Synth Loop Filter C2 and C1
status = ad9361_reg_write(dev, 0x023F, 0xDF); // Set Synth Loop Filter R1 and C3 status = ad9361_reg_write(dev, 0x023F, 0xDF); // Set Synth Loop Filter R1 and C3
status = ad9361_reg_write(dev, 0x0240, 0x0A); // Set Synth Loop Filter R3 status = ad9361_reg_write(dev, 0x0240, 0x09); // Set Synth Loop Filter R3
//************************************************************ //************************************************************
// Setup Tx Frequency-Dependent Syntheisizer Registers // Setup Tx Frequency-Dependent Syntheisizer Registers
//************************************************************ //************************************************************
status = ad9361_reg_write(dev, 0x027A, 0x4A); // Set VCO Output level[3:0] status = ad9361_reg_write(dev, 0x027A, 0x4A); // Set VCO Output level[3:0]
status = ad9361_reg_write(dev, 0x0279, 0xC1); // Set Init ALC Value[3:0] and VCO Varactor[3:0] status = ad9361_reg_write(dev, 0x0279, 0xC0); // Set Init ALC Value[3:0] and VCO Varactor[3:0]
status = ad9361_reg_write(dev, 0x0282, 0x0E); // Set VCO Bias Tcf[1:0] and VCO Bias Ref[2:0] status = ad9361_reg_write(dev, 0x0282, 0x0D); // Set VCO Bias Tcf[1:0] and VCO Bias Ref[2:0]
status = ad9361_reg_write(dev, 0x0278, 0x78); // Set VCO Cal Offset[3:0] status = ad9361_reg_write(dev, 0x0278, 0x70); // Set VCO Cal Offset[3:0]
status = ad9361_reg_write(dev, 0x0285, 0x00); // Set VCO Cal Ref Tcf[2:0] status = ad9361_reg_write(dev, 0x0285, 0x00); // Set VCO Cal Ref Tcf[2:0]
status = ad9361_reg_write(dev, 0x0291, 0x0B); // Set VCO Varactor Reference[3:0] status = ad9361_reg_write(dev, 0x0291, 0x09); // Set VCO Varactor Reference[3:0]
status = ad9361_reg_write(dev, 0x0290, 0x70); // Set VCO Varactor Ref Tcf[2:0] and VCO Varactor Offset[3:0] status = ad9361_reg_write(dev, 0x0290, 0x70); // Set VCO Varactor Ref Tcf[2:0] and VCO Varactor Offset[3:0]
status = ad9361_reg_write(dev, 0x027B, 0x93); // Set Synth Loop Filter charge pump current (Icp) status = ad9361_reg_write(dev, 0x027B, 0x8F); // Set Synth Loop Filter charge pump current (Icp)
status = ad9361_reg_write(dev, 0x027E, 0xF4); // Set Synth Loop Filter C2 and C1 status = ad9361_reg_write(dev, 0x027E, 0xD4); // Set Synth Loop Filter C2 and C1
status = ad9361_reg_write(dev, 0x027F, 0xDF); // Set Synth Loop Filter R1 and C3 status = ad9361_reg_write(dev, 0x027F, 0xDF); // Set Synth Loop Filter R1 and C3
status = ad9361_reg_write(dev, 0x0280, 0x0A); // Set Synth Loop Filter R3 status = ad9361_reg_write(dev, 0x0280, 0x09); // Set Synth Loop Filter R3
//************************************************************ //************************************************************
// Write Rx and Tx Frequency Words // Write Rx and Tx Frequency Words
//************************************************************ //************************************************************
status = ad9361_reg_write(dev, 0x0233, 0x00); // Write Rx Synth Fractional Freq Word[7:0] status = ad9361_reg_write(dev, 0x0233, 0x8D); // Write Rx Synth Fractional Freq Word[7:0]
status = ad9361_reg_write(dev, 0x0234, 0x00); // Write Rx Synth Fractional Freq Word[15:8] status = ad9361_reg_write(dev, 0x0234, 0x99); // Write Rx Synth Fractional Freq Word[15:8]
status = ad9361_reg_write(dev, 0x0235, 0x00); // Write Rx Synth Fractional Freq Word[22:16] status = ad9361_reg_write(dev, 0x0235, 0x69); // Write Rx Synth Fractional Freq Word[22:16]
status = ad9361_reg_write(dev, 0x0232, 0x00); // Write Rx Synth Integer Freq Word[10:8] status = ad9361_reg_write(dev, 0x0232, 0x00); // Write Rx Synth Integer Freq Word[10:8]
status = ad9361_reg_write(dev, 0x0231, 0xA0); // Write Rx Synth Integer Freq Word[7:0] status = ad9361_reg_write(dev, 0x0231, 0x7E); // Write Rx Synth Integer Freq Word[7:0]
status = ad9361_reg_write(dev, 0x0005, 0x05); // Set LO divider setting status = ad9361_reg_write(dev, 0x0005, 0x22); // Set LO divider setting
status = ad9361_reg_write(dev, 0x0273, 0x00); // Write Tx Synth Fractional Freq Word[7:0] status = ad9361_reg_write(dev, 0x0273, 0x8D); // Write Tx Synth Fractional Freq Word[7:0]
status = ad9361_reg_write(dev, 0x0274, 0x00); // Write Tx Synth Fractional Freq Word[15:8] status = ad9361_reg_write(dev, 0x0274, 0x99); // Write Tx Synth Fractional Freq Word[15:8]
status = ad9361_reg_write(dev, 0x0275, 0x00); // Write Tx Synth Fractional Freq Word[22:16] status = ad9361_reg_write(dev, 0x0275, 0x69); // Write Tx Synth Fractional Freq Word[22:16]
status = ad9361_reg_write(dev, 0x0272, 0x00); // Write Tx Synth Integer Freq Word[10:8] status = ad9361_reg_write(dev, 0x0272, 0x00); // Write Tx Synth Integer Freq Word[10:8]
status = ad9361_reg_write(dev, 0x0271, 0xA5); // Write Tx Synth Integer Freq Word[7:0] (starts VCO cal) status = ad9361_reg_write(dev, 0x0271, 0x7E); // Write Tx Synth Integer Freq Word[7:0] (starts VCO cal)
status = ad9361_reg_write(dev, 0x0005, 0x05); // Set LO divider setting status = ad9361_reg_write(dev, 0x0005, 0x22); // Set LO divider setting
//************************************************************ //************************************************************
// Program Mixer GM Sub-table // Program Mixer GM Sub-table
@@ -1542,12 +1057,12 @@ uint32_t ad9361_reg_config(struct ad9361_reg_dev *dev){
status = ad9361_reg_write(dev, 0x011A, 0x27); // Initial LMT Gain Limit status = ad9361_reg_write(dev, 0x011A, 0x27); // Initial LMT Gain Limit
status = ad9361_reg_write(dev, 0x0081, 0x00); // Tx Symbol Gain Control status = ad9361_reg_write(dev, 0x0081, 0x00); // Tx Symbol Gain Control
//************************************************************ //************************************************************
// RX Baseband Filter Tuning (Real BW: 7.500000 MHz) 3dB Filter // RX Baseband Filter Tuning (Real BW: 20.000000 MHz) 3dB Filter
// Corner @ 10.500000 MHz) // Corner @ 28.000000 MHz)
//************************************************************ //************************************************************
status = ad9361_reg_write(dev, 0x01FB, 0x07); // RX Freq Corner (MHz) status = ad9361_reg_write(dev, 0x01FB, 0x14); // RX Freq Corner (MHz)
status = ad9361_reg_write(dev, 0x01FC, 0x40); // RX Freq Corner (Khz) status = ad9361_reg_write(dev, 0x01FC, 0x00); // RX Freq Corner (Khz)
status = ad9361_reg_write(dev, 0x01F8, 0x0D); // Rx BBF Tune Divider[7:0] status = ad9361_reg_write(dev, 0x01F8, 0x05); // Rx BBF Tune Divider[7:0]
status = ad9361_reg_write(dev, 0x01F9, 0x1E); // RX BBF Tune Divider[8] status = ad9361_reg_write(dev, 0x01F9, 0x1E); // RX BBF Tune Divider[8]
status = ad9361_reg_write(dev, 0x01D5, 0x3F); // Set Rx Mix LO CM status = ad9361_reg_write(dev, 0x01D5, 0x3F); // Set Rx Mix LO CM
@@ -1556,56 +1071,56 @@ uint32_t ad9361_reg_config(struct ad9361_reg_dev *dev){
status = ad9361_reg_write(dev, 0x01E3, 0x02); // Enable Rx2 Filter Tuner status = ad9361_reg_write(dev, 0x01E3, 0x02); // Enable Rx2 Filter Tuner
status = ad9361_reg_write(dev, 0x0016, 0x80); // Start RX Filter Tune status = ad9361_reg_write(dev, 0x0016, 0x80); // Start RX Filter Tune
// Wait for RX filter to tune, Max Cal Time: 6.884 us (Done when 0x016[7]==0) // Wait for RX filter to tune, Max Cal Time: 2.648 us (Done when 0x016[7]==0)
time_out_cnt = 0; time_out_cnt = 0;
do{ do{
status |= ad9361_reg_read(dev, 0x0016, &value); status |= ad9361_reg_read(dev, 0x0016, &value);
mdelay(1);// Wait 1ms mdelay(1);// Wait 1ms
time_out_cnt++; time_out_cnt++;
} while((value & 0x80) != 0x00 && time_out_cnt <= AD9361_TIMEOUT_TH); } while((value & 0x80) != 0x00 && time_out_cnt <= TIMEOUT_TH);
status = ad9361_reg_write(dev, 0x01E2, 0x03); // Disable Rx Filter Tuner (Rx1) status = ad9361_reg_write(dev, 0x01E2, 0x03); // Disable Rx Filter Tuner (Rx1)
status = ad9361_reg_write(dev, 0x01E3, 0x03); // Disable Rx Filter Tuner (Rx2) status = ad9361_reg_write(dev, 0x01E3, 0x03); // Disable Rx Filter Tuner (Rx2)
//************************************************************ //************************************************************
// TX Baseband Filter Tuning (Real BW: 7.500000 MHz) 3dB Filter // TX Baseband Filter Tuning (Real BW: 20.000000 MHz) 3dB Filter
// Corner @ 12.000000 MHz) // Corner @ 32.000000 MHz)
//************************************************************ //************************************************************
status = ad9361_reg_write(dev, 0x00D6, 0x0B); // TX BBF Tune Divider[7:0] status = ad9361_reg_write(dev, 0x00D6, 0x04); // TX BBF Tune Divider[7:0]
status = ad9361_reg_write(dev, 0x00D7, 0x1E); // TX BBF Tune Divider[8] status = ad9361_reg_write(dev, 0x00D7, 0x1E); // TX BBF Tune Divider[8]
status = ad9361_reg_write(dev, 0x00CA, 0x22); // Enable Tx Filter Tuner status = ad9361_reg_write(dev, 0x00CA, 0x22); // Enable Tx Filter Tuner
status = ad9361_reg_write(dev, 0x0016, 0x40); // Start Tx Filter Tune status = ad9361_reg_write(dev, 0x0016, 0x40); // Start Tx Filter Tune
// Wait for TX filter to tune, Max Cal Time: 3.390 us (Done when 0x016[6]==0) // Wait for TX filter to tune, Max Cal Time: 1.233 us (Done when 0x016[6]==0)
time_out_cnt = 0; time_out_cnt = 0;
do{ do{
status |= ad9361_reg_read(dev, 0x0016, &value); status |= ad9361_reg_read(dev, 0x0016, &value);
mdelay(1);// Wait 1ms mdelay(1);// Wait 1ms
time_out_cnt++; time_out_cnt++;
} while((value & 0x40) != 0x00 && time_out_cnt <= AD9361_TIMEOUT_TH); } while((value & 0x40) != 0x00 && time_out_cnt <= TIMEOUT_TH);
status = ad9361_reg_write(dev, 0x00CA, 0x26); // Disable Tx Filter Tuner (Both Channels) status = ad9361_reg_write(dev, 0x00CA, 0x26); // Disable Tx Filter Tuner (Both Channels)
//************************************************************ //************************************************************
// RX TIA Setup: Setup values scale based on RxBBF calibration // RX TIA Setup: Setup values scale based on RxBBF calibration
// results. See information in Calibration Guide. // results. See information in Calibration Guide.
//************************************************************ //************************************************************
status = ad9361_reg_write(dev, 0x01DB, 0x60); // Set TIA selcc[2:0] status = ad9361_reg_write(dev, 0x01DB, 0x20); // Set TIA selcc[2:0]
status = ad9361_reg_write(dev, 0x01DD, 0x00); // Set RX TIA1 C MSB[6:0] status = ad9361_reg_write(dev, 0x01DD, 0x00); // Set RX TIA1 C MSB[6:0]
status = ad9361_reg_write(dev, 0x01DF, 0x00); // Set RX TIA2 C MSB[6:0] status = ad9361_reg_write(dev, 0x01DF, 0x00); // Set RX TIA2 C MSB[6:0]
status = ad9361_reg_write(dev, 0x01DC, 0x72); // Set RX TIA1 C LSB[5:0] status = ad9361_reg_write(dev, 0x01DC, 0x47); // Set RX TIA1 C LSB[5:0]
status = ad9361_reg_write(dev, 0x01DE, 0x72); // Set RX TIA2 C LSB[5:0] status = ad9361_reg_write(dev, 0x01DE, 0x47); // Set RX TIA2 C LSB[5:0]
//************************************************************ //************************************************************
// TX Secondary Filter Calibration Setup: Real Bandwidth // TX Secondary Filter Calibration Setup: Real Bandwidth
// 7.500000MHz, 3dB Corner @ 37.500000MHz // 20.000000MHz, 3dB Corner @ 100.000000MHz
//************************************************************ //************************************************************
status = ad9361_reg_write(dev, 0x00D2, 0x1E); // TX Secondary Filter PDF Cap cal[5:0] status = ad9361_reg_write(dev, 0x00D2, 0x04); // TX Secondary Filter PDF Cap cal[5:0]
status = ad9361_reg_write(dev, 0x00D1, 0x0C); // TX Secondary Filter PDF Res cal[3:0] status = ad9361_reg_write(dev, 0x00D1, 0x0C); // TX Secondary Filter PDF Res cal[3:0]
status = ad9361_reg_write(dev, 0x00D0, 0x56); // Pdampbias status = ad9361_reg_write(dev, 0x00D0, 0x57); // Pdampbias
//************************************************************ //************************************************************
// ADC Setup: Tune ADC Performance based on RX analog filter tune // ADC Setup: Tune ADC Performance based on RX analog filter tune
// corner. Real Bandwidth: 6.982753 MHz, ADC Clock Frequency: // corner. Real Bandwidth: 18.155158 MHz, ADC Clock Frequency:
// 288.000000 MHz. The values in registers 0x200 - 0x227 need to be // 288.000000 MHz. The values in registers 0x200 - 0x227 need to be
// calculated using the equations in the Calibration Guide. // calculated using the equations in the Calibration Guide.
//************************************************************ //************************************************************
@@ -1617,23 +1132,23 @@ uint32_t ad9361_reg_config(struct ad9361_reg_dev *dev){
status = ad9361_reg_write(dev, 0x0204, 0x24); status = ad9361_reg_write(dev, 0x0204, 0x24);
status = ad9361_reg_write(dev, 0x0205, 0x00); status = ad9361_reg_write(dev, 0x0205, 0x00);
status = ad9361_reg_write(dev, 0x0206, 0x00); status = ad9361_reg_write(dev, 0x0206, 0x00);
status = ad9361_reg_write(dev, 0x0207, 0x7C); status = ad9361_reg_write(dev, 0x0207, 0x67);
status = ad9361_reg_write(dev, 0x0208, 0x46); status = ad9361_reg_write(dev, 0x0208, 0x55);
status = ad9361_reg_write(dev, 0x0209, 0x3C); status = ad9361_reg_write(dev, 0x0209, 0x31);
status = ad9361_reg_write(dev, 0x020A, 0x4C); status = ad9361_reg_write(dev, 0x020A, 0x3E);
status = ad9361_reg_write(dev, 0x020B, 0x2C); status = ad9361_reg_write(dev, 0x020B, 0x35);
status = ad9361_reg_write(dev, 0x020C, 0x4F); status = ad9361_reg_write(dev, 0x020C, 0x41);
status = ad9361_reg_write(dev, 0x020D, 0x2A); status = ad9361_reg_write(dev, 0x020D, 0x34);
status = ad9361_reg_write(dev, 0x020E, 0x00); status = ad9361_reg_write(dev, 0x020E, 0x00);
status = ad9361_reg_write(dev, 0x020F, 0x7F); status = ad9361_reg_write(dev, 0x020F, 0x6A);
status = ad9361_reg_write(dev, 0x0210, 0x7F); status = ad9361_reg_write(dev, 0x0210, 0x6A);
status = ad9361_reg_write(dev, 0x0211, 0x7F); status = ad9361_reg_write(dev, 0x0211, 0x6A);
status = ad9361_reg_write(dev, 0x0212, 0x4A); status = ad9361_reg_write(dev, 0x0212, 0x3C);
status = ad9361_reg_write(dev, 0x0213, 0x4A); status = ad9361_reg_write(dev, 0x0213, 0x3C);
status = ad9361_reg_write(dev, 0x0214, 0x4A); status = ad9361_reg_write(dev, 0x0214, 0x3C);
status = ad9361_reg_write(dev, 0x0215, 0x4D); status = ad9361_reg_write(dev, 0x0215, 0x3F);
status = ad9361_reg_write(dev, 0x0216, 0x4D); status = ad9361_reg_write(dev, 0x0216, 0x3F);
status = ad9361_reg_write(dev, 0x0217, 0x4D); status = ad9361_reg_write(dev, 0x0217, 0x3F);
status = ad9361_reg_write(dev, 0x0218, 0x2E); status = ad9361_reg_write(dev, 0x0218, 0x2E);
status = ad9361_reg_write(dev, 0x0219, 0x9C); status = ad9361_reg_write(dev, 0x0219, 0x9C);
status = ad9361_reg_write(dev, 0x021A, 0x1F); status = ad9361_reg_write(dev, 0x021A, 0x1F);
@@ -1664,7 +1179,7 @@ uint32_t ad9361_reg_config(struct ad9361_reg_dev *dev){
status |= ad9361_reg_read(dev, 0x0016, &value); status |= ad9361_reg_read(dev, 0x0016, &value);
mdelay(1);// Wait 1ms mdelay(1);// Wait 1ms
time_out_cnt++; time_out_cnt++;
} while((value & 0x01) != 0x00 && time_out_cnt <= AD9361_TIMEOUT_TH); } while((value & 0x01) != 0x00 && time_out_cnt <= TIMEOUT_TH);
status = ad9361_reg_write(dev, 0x0185, 0x20); // Set RF DC offset Wait Count status = ad9361_reg_write(dev, 0x0185, 0x20); // Set RF DC offset Wait Count
status = ad9361_reg_write(dev, 0x0186, 0x32); // Set RF DC Offset Count[7:0] status = ad9361_reg_write(dev, 0x0186, 0x32); // Set RF DC Offset Count[7:0]
@@ -1680,21 +1195,21 @@ uint32_t ad9361_reg_config(struct ad9361_reg_dev *dev){
status |= ad9361_reg_read(dev, 0x0016, &value); status |= ad9361_reg_read(dev, 0x0016, &value);
mdelay(1);// Wait 1ms mdelay(1);// Wait 1ms
time_out_cnt++; time_out_cnt++;
} while((value & 0x01) != 0x00 && time_out_cnt <= AD9361_TIMEOUT_TH); } while((value & 0x01) != 0x00 && time_out_cnt <= TIMEOUT_TH);
//************************************************************ //************************************************************
// Tx Quadrature Calibration Settings // Tx Quadrature Calibration Settings
//************************************************************ //************************************************************
status = ad9361_reg_write(dev, 0x00A0, 0x15); // Set TxQuadcal NCO frequency status = ad9361_reg_write(dev, 0x00A0, 0x5F); // Set TxQuadcal NCO frequency
status = ad9361_reg_write(dev, 0x00A3, 0x00); // Set TxQuadcal NCO frequency (Only update bits [7:6]) status = ad9361_reg_write(dev, 0x00A3, 0x80); // Set TxQuadcal NCO frequency (Only update bits [7:6])
status = ad9361_reg_write(dev, 0x00A1, 0x7B); // Tx Quad Cal Configuration, Phase and Gain Cal Enable status = ad9361_reg_write(dev, 0x00A1, 0x7B); // Tx Quad Cal Configuration, Phase and Gain Cal Enable
status = ad9361_reg_write(dev, 0x00A9, 0xFF); // Set Tx Quad Cal Count status = ad9361_reg_write(dev, 0x00A9, 0xFF); // Set Tx Quad Cal Count
status = ad9361_reg_write(dev, 0x00A2, 0x7F); // Set Tx Quad Cal Kexp status = ad9361_reg_write(dev, 0x00A2, 0x7F); // Set Tx Quad Cal Kexp
status = ad9361_reg_write(dev, 0x00A5, 0x01); // Set Tx Quad Cal Magnitude Threshhold status = ad9361_reg_write(dev, 0x00A5, 0x01); // Set Tx Quad Cal Magnitude Threshhold
status = ad9361_reg_write(dev, 0x00A6, 0x01); // Set Tx Quad Cal Magnitude Threshhold status = ad9361_reg_write(dev, 0x00A6, 0x01); // Set Tx Quad Cal Magnitude Threshhold
status = ad9361_reg_write(dev, 0x00AA, 0x28); // Set Tx Quad Cal Gain Table index status = ad9361_reg_write(dev, 0x00AA, 0x22); // Set Tx Quad Cal Gain Table index
status = ad9361_reg_write(dev, 0x00A4, 0xF0); // Set Tx Quad Cal Settle Count status = ad9361_reg_write(dev, 0x00A4, 0xF0); // Set Tx Quad Cal Settle Count
status = ad9361_reg_write(dev, 0x00AE, 0x04); // Set Tx Quad Cal LPF Gain index incase Split table mode used status = ad9361_reg_write(dev, 0x00AE, 0x00); // Set Tx Quad Cal LPF Gain index incase Split table mode used
status = ad9361_reg_write(dev, 0x0169, 0xC0); // Disable Rx Quadrature Calibration before Running Tx Quadrature Calibration status = ad9361_reg_write(dev, 0x0169, 0xC0); // Disable Rx Quadrature Calibration before Running Tx Quadrature Calibration
status = ad9361_reg_write(dev, 0x0016, 0x10); // Start Tx Quad cal status = ad9361_reg_write(dev, 0x0016, 0x10); // Start Tx Quad cal
@@ -1705,7 +1220,7 @@ uint32_t ad9361_reg_config(struct ad9361_reg_dev *dev){
status |= ad9361_reg_read(dev, 0x0016, &value); status |= ad9361_reg_read(dev, 0x0016, &value);
mdelay(1);// Wait 1ms mdelay(1);// Wait 1ms
time_out_cnt++; time_out_cnt++;
} while((value & 0x10) != 0x00 && time_out_cnt <= AD9361_TIMEOUT_TH); } while((value & 0x10) != 0x00 && time_out_cnt <= TIMEOUT_TH);
status = ad9361_reg_write(dev, 0x016A, 0x75); // Set Kexp Phase status = ad9361_reg_write(dev, 0x016A, 0x75); // Set Kexp Phase
status = ad9361_reg_write(dev, 0x016B, 0x95); // Set Kexp Amplitude & Prevent Positive Gain Bit status = ad9361_reg_write(dev, 0x016B, 0x95); // Set Kexp Amplitude & Prevent Positive Gain Bit
@@ -1736,11 +1251,5 @@ uint32_t ad9361_reg_config(struct ad9361_reg_dev *dev){
status = ad9361_reg_write(dev, 0x0158, 0x0D); // RSSI Mode Select status = ad9361_reg_write(dev, 0x0158, 0x0D); // RSSI Mode Select
status = ad9361_reg_write(dev, 0x015C, 0x67); // Power Measurement Duration status = ad9361_reg_write(dev, 0x015C, 0x67); // Power Measurement Duration
//************************************************************
// Enable External LO & External VCO Buffer
//************************************************************
status |= ad9361_reg_write(dev, 0x0005, 0x07);
status |= ad9361_reg_write(dev, 0x0057, 0x1C);
return status; return status;
} }
@@ -0,0 +1,134 @@
#include "dev_profile.h"
#include "../config/app_config.h"
#include "../drivers/platform/xilinx_gpio.h"
#include "../drivers/axi_core/spi_engine/spi_engine.h"
#include "../drivers/frequency/ad9528/ad9528.h"
static struct spi_engine_init_param spi_engine_param = {
.ref_clk_hz = AD9528_SPI_ENGINE_REF_CLK,
.type = SPI_ENGINE,
.spi_engine_baseaddr = AD9528_SPI_ENGINE_BASEADDR,
.cs_delay = AD9528_SPI_ENGINE_CS_DELAY,
.data_width = AD9528_SPI_ENGINE_DATA_WIDTH
};
static struct xil_gpio_init_param xil_gpio_param = {
.type = GPIO_PS,
.device_id = AD9528_GPIO_DEVICE_ID
};
static struct spi_init_param ad9528_spi_init = {
.device_id = AD9528_SPI_DEVICE_ID,
.max_speed_hz = AD9528_SPI_ENGINE_MAX_SPEED,
.mode = SPI_MODE_0,
.chip_select = AD9528_SPI_CS,
.platform_ops = &spi_eng_platform_ops,
.extra = &spi_engine_param
};
static struct gpio_init_param ad9528_gpio_resetb_init = {
.number = AD9528_RESETB,
.platform_ops = &xil_gpio_ops,
.extra = &xil_gpio_param
};
static struct gpio_init_param ad9528_gpio_sysref_req_init = {
.number = AD9528_SYSREF_REQ,
.platform_ops = &xil_gpio_ops,
.extra = &xil_gpio_param
};
static ad9528pll1Settings_t clockPll1Settings = {
.refA_Frequency_Hz = 50000000,
.refA_Divider = 1,
.refA_bufferCtrl = SINGLE_ENDED,
.refB_Frequency_Hz = 0,
.refB_Divider = 1,
.refB_bufferCtrl = DISABLED,
.vcxo_Frequency_Hz = 50000000,
.vcxoBufferCtrl = SINGLE_ENDED,
.nDivider = 1
};
static ad9528pll2Settings_t clockPll2Settings = {
.rfDivider = 4,
.n2Divider = 20,
.totalNdiv = 80
};
/*******************************************************************
* Output Distribution Settings
* 9369CE02A uses the following clock outputs
* OUT 1: FPGA REFCLK
* OUT 3: FPGA SYSREF
* OUT 12: DUT SYSREF
* OUT 13: DUT REFCLK
*******************************************************************
*/
static ad9528outputSettings_t clockOutputSettings = {
.outPowerDown = 0xE001,
.outSource = {
AD9528_CHANNEL_DIV, AD9528_CHANNEL_DIV, AD9528_CHANNEL_DIV, AD9528_CHANNEL_DIV, AD9528_CHANNEL_DIV,
AD9528_CHANNEL_DIV, AD9528_CHANNEL_DIV, AD9528_CHANNEL_DIV, AD9528_CHANNEL_DIV, AD9528_CHANNEL_DIV,
AD9528_CHANNEL_DIV, AD9528_CHANNEL_DIV, AD9528_CHANNEL_DIV, AD9528_CHANNEL_DIV
},
.outBufferCtrl = {
0,0,0,0,0,
0,0,0,0,0,
0,0,0,0
},
.outAnalogDelay = {
0,0,0,0,0,
0,0,0,0,0,
0,0,0,0
},
.outDigitalDelay = {
0,0,0,0,0,
0,0,0,0,0,
0,0,0,0
},
.outChannelDiv = {
5,25,25,5,5,
5,5,8,5,5,
5,5,10,5
},
.outFrequency_Hz = {
200e6, 40e6, 40e6, 200e6, 200e6,
200e6, 200e6, 125e6, 200e6, 200e6,
200e6, 200e6, 100e6, 200e6
}
};
static ad9528sysrefSettings_t clockSysrefSettings = {
.sysrefRequestMethod = PIN,
.sysrefSource = INTERNAL,
.sysrefPinEdgeMode = LEVEL_ACTIVE_HIGH,
.sysrefPinBufferMode = DISABLED,
.sysrefPatternMode = CONTINUOUS,
.sysrefNshotMode = FOUR_PULSES,
.sysrefDivide = 256
};
static ad9528spiSettings_t clockSpiSettings = {
.chipSelectIndex = AD9528_SPI_CS, //chip select Index, not used
.writeBitPolarity = 0, //Write bit polarity
.longInstructionWord = 1, //16bit instruction word
.MSBFirst = 1, //MSB first
.CPHA = 0, //Clock phase
.CPOL = 0, //Clock polarity
.enSpiStreaming = 0, //uint8_t enSpiStreaming;
.autoIncAddrUp = 1, //uint8_t autoIncAddrUp;
.fourWireMode = 1 //uint8_t fourWireMode;
};
ad9528Init_t ad9528_default_init_param = {
/* SPI */
.spi_init = &ad9528_spi_init,
.gpio_init_resetb = &ad9528_gpio_resetb_init,
.gpio_init_sysref_req = &ad9528_gpio_sysref_req_init,
.spiSettings = &clockSpiSettings,
.pll1Settings = &clockPll1Settings,
.pll2Settings = &clockPll2Settings,
.outputSettings = &clockOutputSettings,
.sysrefSettings = &clockSysrefSettings
};
@@ -6,6 +6,7 @@
#include "../drivers/rf-transceiver/ad9361/ad9361_api.h" #include "../drivers/rf-transceiver/ad9361/ad9361_api.h"
#include "../drivers/rf-transceiver/ad9361_reg/ad9361_reg.h" #include "../drivers/rf-transceiver/ad9361_reg/ad9361_reg.h"
#include "../drivers/frequency/hmc7044/hmc7044.h" #include "../drivers/frequency/hmc7044/hmc7044.h"
#include "../drivers/frequency/ad9528/ad9528.h"
#include "../drivers/adc/ad9694/ad9694.h" #include "../drivers/adc/ad9694/ad9694.h"
#include "../config/app_config.h" #include "../config/app_config.h"
@@ -17,6 +18,9 @@ extern struct global_timer_init_param globaltimer_init_param;
// HMC7044 // HMC7044
extern struct hmc7044_init_param hmc7044_default_init_param; extern struct hmc7044_init_param hmc7044_default_init_param;
// AD9528
extern ad9528Init_t ad9528_default_init_param;
// AD9361 // AD9361
extern AD9361_InitParam ad9361_default_init_param; extern AD9361_InitParam ad9361_default_init_param;
extern AD9361_RXFIRConfig rx_fir_config; extern AD9361_RXFIRConfig rx_fir_config;
@@ -23,7 +23,7 @@ static struct spi_init_param hmc7044_spi_init_param = {
.device_id = HMC7044_SPI_DEVICE_ID, .device_id = HMC7044_SPI_DEVICE_ID,
.max_speed_hz = HMC7044_SPI_ENGINE_MAX_SPEED, .max_speed_hz = HMC7044_SPI_ENGINE_MAX_SPEED,
.mode = SPI_MODE_4, .mode = SPI_MODE_4,
.chip_select = HMC7044_SPI_CS_HMC7044, .chip_select = HMC7044_SPI_CS,
.platform_ops = &spi_eng_platform_ops, .platform_ops = &spi_eng_platform_ops,
.extra = &spi_engine_param .extra = &spi_engine_param
}; };
@@ -42,9 +42,9 @@ struct hmc7044_chan_spec hmc7044_chan_spec[4] = {
.dynamic_driver_enable = false, .dynamic_driver_enable = false,
.output_control0_rb4_enable = true, .output_control0_rb4_enable = true,
.force_mute_enable = false, .force_mute_enable = false,
.driver_mode = CML, .driver_mode = HMC7044_CML,
.driver_impedance = INTERNAL_100OHM_PER_PIN, .driver_impedance = INTERNAL_100OHM_PER_PIN,
.out_mux_mode = CHANNEL_DIV .out_mux_mode = HMC7044_CHANNEL_DIV
}, },
/* FPGA_DAC_LOGIC_CLK */ /* FPGA_DAC_LOGIC_CLK */
{ {
@@ -58,9 +58,9 @@ struct hmc7044_chan_spec hmc7044_chan_spec[4] = {
.dynamic_driver_enable = false, .dynamic_driver_enable = false,
.output_control0_rb4_enable = true, .output_control0_rb4_enable = true,
.force_mute_enable = false, .force_mute_enable = false,
.driver_mode = CML, .driver_mode = HMC7044_CML,
.driver_impedance = INTERNAL_100OHM_PER_PIN, .driver_impedance = INTERNAL_100OHM_PER_PIN,
.out_mux_mode = CHANNEL_DIV .out_mux_mode = HMC7044_CHANNEL_DIV
}, },
/* B_AD9361_XTAL */ /* B_AD9361_XTAL */
{ {
@@ -74,9 +74,9 @@ struct hmc7044_chan_spec hmc7044_chan_spec[4] = {
.dynamic_driver_enable = false, .dynamic_driver_enable = false,
.output_control0_rb4_enable = true, .output_control0_rb4_enable = true,
.force_mute_enable = false, .force_mute_enable = false,
.driver_mode = CML, .driver_mode = HMC7044_CML,
.driver_impedance = INTERNAL_100OHM_PER_PIN, .driver_impedance = INTERNAL_100OHM_PER_PIN,
.out_mux_mode = CHANNEL_DIV .out_mux_mode = HMC7044_CHANNEL_DIV
}, },
/* AD9361_RX_EXT_LO */ /* AD9361_RX_EXT_LO */
{ {
@@ -90,9 +90,9 @@ struct hmc7044_chan_spec hmc7044_chan_spec[4] = {
.dynamic_driver_enable = false, .dynamic_driver_enable = false,
.output_control0_rb4_enable = true, .output_control0_rb4_enable = true,
.force_mute_enable = false, .force_mute_enable = false,
.driver_mode = CML, .driver_mode = HMC7044_CML,
.driver_impedance = INTERNAL_100OHM_PER_PIN, .driver_impedance = INTERNAL_100OHM_PER_PIN,
.out_mux_mode = CHANNEL_DIV .out_mux_mode = HMC7044_CHANNEL_DIV
}, },
}; };
@@ -0,0 +1,783 @@
/**
* \file ad9528.c
* \brief Contains source code for configuring and initializing AD9528 clock device
*/
/**
* \page Disclaimer Legal Disclaimer
* Copyright 2015-2017 Analog Devices Inc.
* Released under the AD9371 API license.
*
*/
#include <stdlib.h>
#include <stdio.h>
#include "ad9528.h"
#include "../../../include/error.h"
static uint32_t _desired_time_to_elapse_ms = 0;
/**
* \brief Write data to a register
*/
int32_t AD9528_spiWriteByte(ad9528Device_t *device, uint16_t addr,
uint8_t data)
{
uint8_t buf[3];
int32_t status;
buf[0] = (addr >> 8) & 0x7F;
buf[1] = addr & 0xFF;
buf[2] = data;
status = spi_write_and_read_3wire(device->spi_desc,
buf, NULL, 3, 0);
return status;
}
/**
* \brief Read data from a register
*/
int32_t AD9528_spiReadByte(ad9528Device_t *device, uint16_t addr,
uint8_t *readdata)
{
uint8_t tx_buf[2];
uint8_t rx_buf[1];
int32_t status;
tx_buf[0] = 0x80 | addr >> 8;
tx_buf[1] = addr & 0xFF;
status = spi_write_and_read_3wire(device->spi_desc,
tx_buf, rx_buf, 2, 1);
*readdata = rx_buf[0];
return status;
}
/**
* \brief Modify a field of bits from a register
*/
int32_t AD9528_spiWriteField(ad9528Device_t *device,
uint16_t addr, uint8_t fieldVal, uint8_t mask, uint8_t startBit)
{
int32_t errVal;
uint8_t readVal;
errVal = AD9528_spiReadByte(device, addr, &readVal);
if (errVal < 0)
return errVal;
readVal = (readVal & ~mask) | ((fieldVal << startBit) & mask);
return AD9528_spiWriteByte(device, addr, readVal);
}
/**
* \brief Set the desired timeout value
*/
int32_t AD9528_setTimeout_ms(uint32_t timeOut_ms)
{
_desired_time_to_elapse_ms = timeOut_ms;
return SUCCESS;
}
/**
* \brief Verify if the desired time has elapsed
*/
int32_t AD9528_hasTimeoutExpired()
{
udelay(1000);
_desired_time_to_elapse_ms--;
if (_desired_time_to_elapse_ms > 0)
return SUCCESS;
return FAILURE;
}
/**
* \brief Performs a hard reset on the AD9528 DUT
*
* <B>Dependencies</B>
* - device->spiSettings->chipSelectIndex
*
* \param device is structure pointer to the AD9528 data structure containing settings
* \return Returns enum ADI_ERR, ADIERR_OK=pass, !ADIERR_OK=fail
*/
int32_t AD9528_resetDevice(ad9528Device_t *device)
{
gpio_direction_output(device->gpio_resetb, 0);
mdelay(100);
gpio_direction_output(device->gpio_resetb, 1);
mdelay(100);
AD9528_spiWriteByte(device, AD9528_ADDR_ADI_SPI_CONFIG_A, 0x81);
mdelay(100);
AD9528_spiWriteByte(device, AD9528_ADDR_ADI_SPI_CONFIG_A, 0x00);
mdelay(100);
return SUCCESS;
}
/**
* \brief Sets the AD9528 device SPI settings (3wire/4wire, MSBFirst, etc).
*
* This function will use the settings in the device->spiSettings structure
* to set SPI stream mode, address auto increment direction, MSBFirst/LSBfirst,
* and 3wire/4wire mode. The AD9528 device always uses SPI MODE 0 (CPHA=0, CPOL=0).
* This function will update your device->spiSettings to set CHPA=0 and CPOL=0 and
* longInstructionWord =1 to use a 16bit instruction word.
*
* <B>Dependencies</B>
* - writes device->spiSettings->CPHA = 0
* - writes device->spiSettings->CPOL = 0
* - writes device->spiSettings->longInstructionWord = 1
*
* - device->spiSettings->MSBFirst
* - device->spiSettings->enSpiStreaming
* - device->spiSettings->autoIncAddrUp
* - device->spiSettings->fourWireMode
*
* \param device is structure pointer to the AD9528 data structure containing settings
*
* \return Returns enum ADI_ERR, ADIERR_OK=pass, !ADIERR_OK=fail
*/
int32_t AD9528_setSpiSettings(ad9528Device_t *device)
{
uint8_t spiReg = 0;
device->spiSettings->CPHA = 0;
device->spiSettings->CPOL = 0;
device->spiSettings->longInstructionWord = 1;
if (device->spiSettings->MSBFirst == 0) {
spiReg |= 0x42; /* SPI bit is 1=LSB first */
}
if (device->spiSettings->autoIncAddrUp > 0) {
spiReg |= 0x24;
}
if (device->spiSettings->fourWireMode > 0) {
spiReg |= 0x18;
}
AD9528_spiWriteByte(device, AD9528_ADDR_ADI_SPI_CONFIG_A, spiReg);
if (device->spiSettings->enSpiStreaming > 0) {
/* Allow SPI streaming mode: SPI message ends when chip select deasserts */
AD9528_spiWriteByte(device, AD9528_ADDR_ADI_SPI_CONFIG_B, 0x00);
} else {
/* Force single instruction mode */
AD9528_spiWriteByte(device, AD9528_ADDR_ADI_SPI_CONFIG_B, 0x80);
}
return SUCCESS;
}
/**
* \brief Helper function for ADI transceiver eval boards to init the AD9528 data structure
*
* This function inits the AD9528 device data structure with defaults that
* are known to work with the ADI AD9369 and AD9371 evaluation boards. NOTE: This function will
* modify the contents of the AD9528 device data structure.
*
* <B>Dependencies</B>
* - spi->chipSelectIndex
* - spi
*
* \param device Pointer to the AD9528 device data structure to initialize
* \param vcxoFrequency_Hz The VCXO frequency that is connected to the AD9528
* \param refAFrequency_Hz The reference clock frequency being input into the AD9528 REFCLK A input
* \param outputDeviceClock_Hz Desired output clock frequency to the FPGA and transceiver device
*
* \return Returns enum ADI_ERR, 0=pass, >0 = fail
*/
int32_t AD9528_initDeviceDataStruct(ad9528Device_t *device,
uint32_t vcxoFrequency_Hz, uint32_t refAFrequency_Hz,
uint32_t outputDeviceClock_Hz)
{
// uint16_t chDiv;
// uint8_t i = 0;
//
// uint32_t pll1PfdFreq_Hz = 0;
// uint8_t pll1Ndiv = 0;
// uint8_t validPll1DivSetting = 0;
// uint8_t refAdiv = 1;
//
//
// uint8_t pll2RfDiv = 3; /* Valid values 3,4,5 */
// uint16_t pll2Ndiv = 1; /* Valid values 1-256 */
// uint32_t pll2InputFreq_Hz = 0;
// uint64_t pll2VcoFreq_Hz = 0;
// uint16_t pll2NdivStart = 0;
// uint8_t validPll2DivSetting = 0;
// uint64_t chDivU64 = 0;
//
// static const uint64_t PLL2_MIN_VCO_FREQ_HZ = 3450000000ULL;
// static const uint64_t PLL2_MAX_VCO_FREQ_HZ = 4025000000ULL;
// struct spi_init_param spi_param;
// int32_t status;
//
// status = gpio_get(&device->gpio_resetb, CLK_RESETB);
// status |= gpio_get(&device->gpio_sysref_req, ADRV_SYSREF_REQ);
//
// spi_param.id = 0;
// spi_param.mode = SPI_MODE_0;
// spi_param.chip_select = CLK_CS;
// status |= spi_init(&device->spi_desc, &spi_param);
//
// if (status != SUCCESS)
// return FAILURE;
/*******************************************************************
* PLL1 Settings
*******************************************************************
*/
/* find valid PLL1 Ndiv and REFA div */
// for (pll1Ndiv = 1; pll1Ndiv < 20; pll1Ndiv++) {
// pll1PfdFreq_Hz = vcxoFrequency_Hz / pll1Ndiv;
//
// if ((pll1PfdFreq_Hz <= 110000000) && (pll1PfdFreq_Hz >= 1000000) &&
// (pll1PfdFreq_Hz <= refAFrequency_Hz) &&
// (refAFrequency_Hz % pll1PfdFreq_Hz == 0)
// ) {
// validPll1DivSetting = 1;
// refAdiv = refAFrequency_Hz / pll1PfdFreq_Hz ;
// break;
// }
// }
//
// if (validPll1DivSetting == 0) {
// return FAILURE;
// }
// device->pll1Settings->nDivider =
// pll1Ndiv; //This init function always runs PLL1 at 30.72MHz Pfd rate
// device->pll1Settings->refA_bufferCtrl =
// DIFFERENTIAL; //DISABLED = 0, SINGLE_ENDED, NEG_SINGLE_ENDED, DIFFERENTIAL
// device->pll1Settings->refA_Divider = refAdiv;
// device->pll1Settings->refA_Frequency_Hz = refAFrequency_Hz;
// device->pll1Settings->refB_bufferCtrl =
// DISABLED; //DISABLED = 0, SINGLE_ENDED, NEG_SINGLE_ENDED, DIFFERENTIAL
// device->pll1Settings->refB_Divider = 1;
// device->pll1Settings->refB_Frequency_Hz = 0;
// device->pll1Settings->vcxoBufferCtrl =
// NEG_SINGLE_ENDED; //DISABLED = 0, SINGLE_ENDED, NEG_SINGLE_ENDED, DIFFERENTIAL
// device->pll1Settings->vcxo_Frequency_Hz = vcxoFrequency_Hz;
/*******************************************************************
* PLL2 Settings
*******************************************************************
*/
/*******************************************************************
* Output Distribution Settings
* 9369CE02A uses the following clock outputs
* OUT 1: FPGA REFCLK
* OUT 3: FPGA SYSREF
* OUT 12: DUT SYSREF
* OUT 13: DUT REFCLK
*******************************************************************
*/
/* PLL 2 input clock can be several different things. Currently hard coded by this init funciton to use
* PLL 1 output (VCXO Frequency) with no scaling
*/
// pll2InputFreq_Hz = device->pll1Settings->vcxo_Frequency_Hz;
// validPll2DivSetting = 0;
/* Sweep PLL2 Divider settings to find something that has a valid integer divide (3,4,5)*/
// for (pll2RfDiv = 3; pll2RfDiv <= 5; pll2RfDiv++) {
//
// pll2NdivStart = (PLL2_MIN_VCO_FREQ_HZ / pll2RfDiv / pll2InputFreq_Hz);
// /* find valid PLL2 Ndiv (1-256) */
// for (pll2Ndiv = pll2NdivStart; pll2Ndiv <= 256; pll2Ndiv++) {
// pll2VcoFreq_Hz = (pll2InputFreq_Hz * pll2RfDiv * pll2Ndiv);
//
// if (pll2VcoFreq_Hz < PLL2_MIN_VCO_FREQ_HZ) {
// /* Continue to next PLL2 N div */
// continue;
// } else if (pll2VcoFreq_Hz > PLL2_MAX_VCO_FREQ_HZ) {
// /* Break to next PLL2 RF div */
// break;
// }
//
// if (((pll2VcoFreq_Hz / pll2RfDiv) % outputDeviceClock_Hz) == 0) {
//
// device->pll2Settings->rfDivider = pll2RfDiv;
// device->pll2Settings->n2Divider = pll2Ndiv;
// device->pll2Settings->totalNdiv = pll2RfDiv * pll2Ndiv;
// chDivU64 = ((pll2VcoFreq_Hz / pll2RfDiv) / outputDeviceClock_Hz);
//
// if ((chDivU64 < 1) || (chDivU64 > 256)) {
// return FAILURE;
// } else {
// chDiv = (uint16_t)(chDivU64);
// }
//
// validPll2DivSetting = 1;
// break;
// }
// }
//
// if (validPll2DivSetting == 1) {
// break;
// }
// }
//
// if (validPll2DivSetting == 0) {
// return FAILURE;
// }
//
// device->outputSettings->outPowerDown = (uint16_t)(
// ~0x318A); //enable outputs 13,12,8,7,3 and 1
//
// for (i=0; i<14; i++) {
// device->outputSettings->outSource[i] =
// CHANNEL_DIV; //CHANNEL_DIV , PLL1_OUTPUT, SYSREF, INV_PLL1_OUTPUT
// device->outputSettings->outBufferCtrl[i] = LVDS; //LVDS, LVDS_BOOST, HSTL
// device->outputSettings->outChannelDiv[i] = chDiv;
// device->outputSettings->outFrequency_Hz[i] = outputDeviceClock_Hz;
// device->outputSettings->outAnalogDelay[i] = 0;
// device->outputSettings->outDigitalDelay[i] = 0;
// }
//
//
// device->outputSettings->outSource[3] = SYSREF;
// device->outputSettings->outSource[7] = SYSREF;
// device->outputSettings->outSource[12] = SYSREF;
//
//
// device->sysrefSettings->sysrefDivide =
// 512; //SYSREF frequency = VCXO / 2 / sysrefDivde
// device->sysrefSettings->sysrefNshotMode =
// ONE_PULSE; //ONE_PULSE=0, TWO_PULSES=2, FOUR_PULSES=3, SIX_PULSES=4, EIGHT_PULSES=5
// device->sysrefSettings->sysrefPatternMode =
// CONTINUOUS; //NSHOT=0, CONTINUOUS=1, PRBS=2, STOP=3
// device->sysrefSettings->sysrefPinBufferMode =
// DISABLED; //DISABLED = 0, SINGLE_ENDED, NEG_SINGLE_ENDED, DIFFERENTIAL
// device->sysrefSettings->sysrefPinEdgeMode =
// LEVEL_ACTIVE_HIGH; //LEVEL_ACTIVE_HIGH=0, LEVEL_ACTIVE_LOW=1, RISING_EDGE=2, FALLING_EDGE=3
// device->sysrefSettings->sysrefRequestMethod = PIN; //SPI=0,PIN=1
// device->sysrefSettings->sysrefSource =
// INTERNAL; //EXTERNAL=0, EXT_RESAMPLED=1, INTERNAL=2
return SUCCESS;
}
int32_t AD9528_init(ad9528Device_t **device, const ad9528Init_t *init_device)
{
int ret = SUCCESS;
ad9528Device_t *dev;
dev = (ad9528Device_t *)malloc(sizeof(*dev));
if (!dev)
return FAILURE;
/* SPI */
ret = spi_init(&dev->spi_desc, init_device->spi_init);
ret |= gpio_get(&dev->gpio_resetb, init_device->gpio_init_resetb);
ret |= gpio_get(&dev->gpio_sysref_req, init_device->gpio_init_sysref_req);
gpio_direction_output(dev->gpio_resetb, 0);
gpio_direction_output(dev->gpio_sysref_req, 0);
AD9528_resetDevice(dev);
dev->spiSettings = init_device->spiSettings;
dev->pll1Settings = init_device->pll1Settings;
dev->pll2Settings = init_device->pll2Settings;
dev->outputSettings = init_device->outputSettings;
dev->sysrefSettings = init_device->sysrefSettings;
*device = dev;
return ret;
}
/**
* \brief Initializes the AD9528 by writing all SPI registers
*
* Initializes the AD9528 for use with the AD9369 transceiver. Designed to work with
* a reference clock of 122.88MHz. Reference clock is expected to be 30.72MHz.
* The output clocks from the AD9528 can run at 122.88M, 153.6M, 184.32M, 245.76M, or 307.2M.
* Typical setup: REFA frequency = 30.72, VCXO = 122.88MHz
* SYNC(SYSREF) pulses output at rate of 120kHz
*
* <B>Dependencies</B>
* - All parameters in device structure
*
* \param device is structure pointer to AD9528 clock device structure
*
* \return Returns enum ADI_ERR, 0=pass, >0 = fail
*/
int32_t AD9528_config(ad9528Device_t
*device) //writes all registers to desired values, leaves clock outputs off, SYSREF output disabled.
{
uint8_t pll2_Adiv=0;
uint8_t pll2_Bdiv=0;
uint8_t reg108=0;
uint8_t reg109=0x4;
uint8_t i = 0;
uint8_t j = 0;
uint8_t reg508;
int32_t retval = SUCCESS;
retval = AD9528_setSpiSettings(device);
if (retval != SUCCESS) {
return retval;
}
/**********************************************************************
* Configure PLL1
**********************************************************************
*/
AD9528_spiWriteByte(device, AD9528_ADDR_REF_A_DIVIDER_LSB,
device->pll1Settings->refA_Divider & 0xFF); //REF A div[7:0]
AD9528_spiWriteByte(device, AD9528_ADDR_REF_A_DIVIDER_MSB,
(device->pll1Settings->refA_Divider >> 8) & 0x03); //REF A div[9:8]
AD9528_spiWriteByte(device, AD9528_ADDR_REF_B_DIVIDER_LSB,
device->pll1Settings->refB_Divider & 0xFF); //REF B div[7:0]
AD9528_spiWriteByte(device, AD9528_ADDR_REF_B_DIVIDER_MSB,
(device->pll1Settings->refB_Divider >> 8) & 0x03); //REF B div[9:8]
AD9528_spiWriteByte(device, AD9528_ADDR_PLL1_N_DIV_LSB,
device->pll1Settings->nDivider & 0xFF); //PLL1 N div[7:0]
AD9528_spiWriteByte(device, AD9528_ADDR_PLL1_N_DIV_MSB,
(device->pll1Settings->nDivider >> 8) & 0x03); //PLL1 N div[9:8]
AD9528_spiWriteByte(device, AD9528_ADDR_PLL1_CHARGEPUMP,
0x0A); //PLL1 Charge Pump control 1
AD9528_spiWriteByte(device, AD9528_ADDR_PLL1_CP_CTRL2,
0x03); //PLL1 Charge Pump control 2
switch (device->pll1Settings->refA_bufferCtrl) {
case DISABLED:
reg108 &= ~0x28;
reg109 &= ~0x01;
break; //clear all REFA enable bits
case SINGLE_ENDED:
reg108 |= 0x08;
reg109 &= ~0x01;
break; //Set REFA receiver enable, clear REFA SE negative input enable
case NEG_SINGLE_ENDED:
reg108 |= 0x08;
reg108 &= ~0x10;
reg109 |= 0x01;
break; //Disable REFA diff receiver, enable REFA receiver and use negative REFA input
case DIFFERENTIAL:
reg108 |= 0x28;
reg109 &= ~0x01;
break;
default:
reg108 |= 0x08;
reg109 &= ~0x01;
break; //default to single ended case
}
switch (device->pll1Settings->refB_bufferCtrl) {
case DISABLED:
reg108 &= ~0x50;
reg109 &= ~0x02;
break; //clear all REFB enable bits
case SINGLE_ENDED:
reg108 |= 0x10;
reg109 &= ~0x02;
break; //Set REFB receiver enable, clear REFB SE negative input enable
case NEG_SINGLE_ENDED:
reg108 |= 0x10;
reg108 &= ~0x40;
reg109 |= 0x02;
break; //Disable REFB diff receiver, enable REFB receiver and use negative REFB input
case DIFFERENTIAL:
reg108 |= 0x50;
reg109 &= ~0x02;
break;
default:
reg108 |= 0x10;
reg109 &= ~0x02;
break; //default to single ended case
}
switch (device->pll1Settings->vcxoBufferCtrl) {
case DISABLED:
reg108 &= ~0x03;
reg108 |= 0x04;
break; //power down VCXO input
case SINGLE_ENDED:
reg108 &= ~0x07;
break; //Clear VCXO receiver power down, defaults to Single ended mode
case NEG_SINGLE_ENDED:
reg108 &= ~0x07;
reg108 |= 0x02;
break; //Clear VCXO power down, enable Negative single ended mode[1]
case DIFFERENTIAL:
reg108 &= ~0x07;
reg108 |= 0x01;
break; //Clear VCXO power down, enable differential input buffer[0]
default:
reg108 &= ~0x07;
break; //default to positive single ended case
}
AD9528_spiWriteByte(device, AD9528_ADDR_INPUT_RECEIVERS1,
reg108); //Input receiver settings (single ended or differential clock inputs)
AD9528_spiWriteByte(device, AD9528_ADDR_INPUT_RECEIVERS2,
reg109); //Input receiver settings
AD9528_spiWriteByte(device, AD9528_ADDR_INPUT_RECEIVERS3,
0x0A); //Reference selection mode
AD9528_spiWriteByte(device, AD9528_ADDR_PLL1_FASTLOCK,
0x00); //Disable Fast lock
/**********************************************************************
* Configure PLL2
**********************************************************************
*/
pll2_Bdiv = device->pll2Settings->totalNdiv / 4;
pll2_Adiv = device->pll2Settings->totalNdiv % 4;
if (pll2_Adiv > 3) { //A div valid range (0 to 3)
return FAILURE;
}
if (pll2_Bdiv < 3 || pll2_Bdiv > 63) {
return FAILURE;
}
AD9528_spiWriteByte(device, AD9528_ADDR_PLL2_CHARGEPUMP,
0xE6); //PLL2 Charge Pump[7:0]
AD9528_spiWriteByte(device, AD9528_ADDR_PLL2_N_DIV,
((pll2_Adiv & 0x3) << 6) | (pll2_Bdiv & 0x3F)); //PLL2 A and B divider
AD9528_spiWriteByte(device, AD9528_ADDR_PLL2_CTRL, 0x03); //PLL2 control
AD9528_spiWriteByte(device, AD9528_ADDR_PLL2_VCO_CTRL, 0x01); //Manual VCO CAL
if (device->pll2Settings->rfDivider < 3
|| device->pll2Settings->rfDivider > 5) {
return FAILURE;
}
AD9528_spiWriteByte(device, AD9528_ADDR_PLL2_VCO_DIV,
device->pll2Settings->rfDivider); //VCO divider
AD9528_spiWriteByte(device, AD9528_ADDR_PLL2_LF_CTRL1,
0x3A); //PLL2 Loop filter [7:0]
AD9528_spiWriteByte(device, AD9528_ADDR_PLL2_LF_CTRL2,
0x00); //PLL2 Loop filter [8]
AD9528_spiWriteByte(device, AD9528_ADDR_PLL2_RDIV, 0x01); //R divider
AD9528_spiWriteByte(device, AD9528_ADDR_PLL2_REPLICA_CHDIV,
(device->pll2Settings->totalNdiv / device->pll2Settings->rfDivider)
-1 ); //Replica channel divider: Ndivider = rfDivider * R divider
AD9528_spiWriteByte(device, AD9528_ADDR_PLL2_REPLICA_DIV_PHASE,
0x00); //Replica Channel Divider phase
/**********************************************************************
* Configure Output Distribution
**********************************************************************
*/
for (i=0; i<14; i=i+1) {
AD9528_spiWriteByte(device, AD9528_ADDR_CH_OUT0_CTRL1 + j,
((device->outputSettings->outSource[i] & 0x7) << 5) |
(device->outputSettings->outAnalogDelay[i] & 0x1F));
AD9528_spiWriteByte(device, AD9528_ADDR_CH_OUT0_CTRL2 + j,
((device->outputSettings->outBufferCtrl[i] & 0x3) << 6) |
(device->outputSettings->outDigitalDelay[i] & 0x3F));
AD9528_spiWriteByte(device, AD9528_ADDR_CH_OUT0_CHDIV + j,
device->outputSettings->outChannelDiv[i]-1);
j = j+3;
}
AD9528_spiWriteByte(device, AD9528_ADDR_OUTPUT_SYNC, 0x00); //Sync outputs
AD9528_spiWriteByte(device, AD9528_ADDR_MASK_SYNC1, 0x00); //Mask SYNC[7:0]
AD9528_spiWriteByte(device, AD9528_ADDR_MASK_SYNC2, 0x00); //Mask SYNC[13:8]
AD9528_spiWriteByte(device, AD9528_ADDR_EN_OUTPUT_PATH_SEL1,
0x00); //Bypass SYSREF resample [6:0], bit0:Enable VCXO to feed output distrubution
AD9528_spiWriteByte(device, AD9528_ADDR_EN_OUTPUT_PATH_SEL2,
0x00); //Bypass SYSREF resample [13:7]
/**********************************************************************
* Configure SYSREF operation
**********************************************************************
*/
AD9528_spiWriteByte(device, AD9528_ADDR_SYSERF_DIV_LSB,
device->sysrefSettings->sysrefDivide & 0xFF); //SYSREF divider [7:0]
AD9528_spiWriteByte(device, AD9528_ADDR_SYSERF_DIV_MSB,
(device->sysrefSettings->sysrefDivide >> 8) & 0xFF); //SYSREF divider [7:0]
AD9528_spiWriteByte(device, AD9528_ADDR_SYSREF_CTRL3,
((device->sysrefSettings->sysrefRequestMethod & 0x1) << 7) |
((device->sysrefSettings->sysrefPinEdgeMode & 0x3) << 5) );
AD9528_spiWriteByte(device, AD9528_ADDR_SYSREF_CTRL4,
((device->sysrefSettings->sysrefSource & 0x03) << 6) |
((device->sysrefSettings->sysrefPatternMode & 0x3) << 4 ) |
((device->sysrefSettings->sysrefNshotMode & 0x7) << 1) );
if(device->sysrefSettings->sysrefPinBufferMode == DISABLED) {
AD9528_spiWriteByte(device, AD9528_ADDR_SYSREF_CTRL5,
0x04); //power down input buffer for external SYSREF
} else if(device->sysrefSettings->sysrefPinBufferMode == SINGLE_ENDED) {
AD9528_spiWriteByte(device, AD9528_ADDR_SYSREF_CTRL5,
0x00); //enable positive singled ended input
} else if(device->sysrefSettings->sysrefPinBufferMode == NEG_SINGLE_ENDED) {
AD9528_spiWriteByte(device, AD9528_ADDR_SYSREF_CTRL5,
0x02); //enable negative singled ended input
} else if(device->sysrefSettings->sysrefPinBufferMode == DIFFERENTIAL) {
AD9528_spiWriteByte(device, AD9528_ADDR_SYSREF_CTRL5,
0x01); //enable differential input buffer
} else {
AD9528_spiWriteByte(device, AD9528_ADDR_SYSREF_CTRL5,
0x04); //power down input buffer for external SYSREF
}
/**********************************************************************
* Power down control
**********************************************************************
*/
if (device->pll1Settings->bypassPll1 > 0) {
AD9528_spiWriteByte(device, AD9528_ADDR_POWERDOWN_CTRL,
0x14);// power up PLL2 and output distribution, power down PLL1
} else {
AD9528_spiWriteByte(device, AD9528_ADDR_POWERDOWN_CTRL,
0x10);// power up PLL1, PLL2 and output distribution
}
AD9528_spiWriteByte(device, AD9528_ADDR_CH_POWERDOWN1,
device->outputSettings->outPowerDown & 0xFF); //power down out[7:0]
AD9528_spiWriteByte(device, AD9528_ADDR_CH_POWERDOWN2,
((device->outputSettings->outPowerDown >> 8) & 0x3F)); //power down out[13:8]
AD9528_spiWriteByte(device, AD9528_ADDR_LDO_ENABLES1,
0xFF); //LDO enable per output channel [7:0]
AD9528_spiWriteByte(device, AD9528_ADDR_LDO_ENABLES2,
0xFF); //LDO enable per output channel [15:8]
AD9528_spiWriteByte(device, AD9528_ADDR_STATUS0_CTRL,
0x07); //STATUS 0 outputs REFA present
AD9528_spiWriteByte(device, AD9528_ADDR_STATUS1_CTRL,
0x01); //STATUS 1 outputs PLL1 and PLL2 locked
AD9528_spiWriteByte(device, AD9528_ADDR_STATUS_OE,
0x0C);// Make Status0 and Status1 outputs after reset.
AD9528_spiWriteByte(device, AD9528_ADDR_IO_UPDATE,
0x01); //IO update to make all these settings valid in the 9528
AD9528_setTimeout_ms(1000);
do {
AD9528_spiReadByte(device, AD9528_ADDR_STATUS_READBACK0, &reg508);
if(AD9528_hasTimeoutExpired() > 0) {
return FAILURE;
}
} while((reg508 & 0x26) != 0x26);
return SUCCESS;
}
/// Send a SPI message to request a SYSREF pulse or continuous SYSREF from the AD9528.
/*******************************************************************************//**
* Requests a SYSREF from the AD9528. It will use whatever settings for SYSREF
* that are current configured in the AD9528. This could be a single pulse,
* multiple pulses, or continuous pulses.
* <B>Dependencies</B>
* - device->spiSettings
* - device->sysrefSettings->sysrefPatternMode
*
* \param device is structure pointer to AD9528 clock device structure
* \param enableSYSREF If NSHOT SYSREF mode, this parameter is ignored. If PRBS/CONTINUOUS SYSREF mode, 1= enable SYSREF, 0= disable SYSREF.
*
* \return Returns enum ADI_ERR, 0=pass, >0 = fail
***********************************************************************************/
int32_t AD9528_requestSysref(ad9528Device_t *device, uint8_t enableSYSREF)
{
uint8_t _enableSYSREF=0;
if (device->sysrefSettings->sysrefPatternMode == NSHOT || enableSYSREF > 0) {
_enableSYSREF = 1;
} else {
_enableSYSREF = 0;
}
AD9528_spiWriteField(device, AD9528_ADDR_SYSREF_CTRL4, _enableSYSREF, 0x01,
0x00); //Set SPI SYSREF request bit
AD9528_spiWriteByte(device, AD9528_ADDR_IO_UPDATE,
0x01); //IO update to make all these settings valid in the 9528
return SUCCESS;
}
/// Allow changing the 9528 SYSREF frequency and pattern mode(CONTINUOUS, PRBS vs NSHOT mode)
/*******************************************************************************//**
* NOTE: this function will update the device structure with the parameter values passed
* into this function. The device->sysrefSettings->sysrefPatternMode, device->sysrefSettings->sysrefNshotMode,
* and device->sysrefSettings->sysrefDivide values will be updated in the device structure.
*
* <B>Dependencies</B>
* - device->spiSettings
*
* \param device is structure pointer to AD9528 clock device structure
* \param divideFromPll1Out Sets the SYSREF pulse frequency. SYSREF frequency = PLL1_VCXO frequency/divideFromPll1Out
* \param sysrefPatternMode Valid settings: NSHOT, CONTINUOUS, PRBS, STOP
* \param nShotPulses Valid settings: ONE_PULSE=0, TWO_PULSES=2, FOUR_PULSES=3, SIX_PULSES=4, EIGHT_PULSES=5
*
* \return Returns enum ADI_ERR, 0=pass, >0 = fail
***********************************************************************************/
int32_t AD9528_setupSYSREF(ad9528Device_t *device,
uint16_t divideFromPll1Out, sysrefPatternMode_t sysrefPatternMode,
sysrefNshotMode_t nShotPulses)
{
uint8_t reg403=0;
device->sysrefSettings->sysrefPatternMode = sysrefPatternMode;
device->sysrefSettings->sysrefNshotMode = nShotPulses;
device->sysrefSettings->sysrefDivide = divideFromPll1Out >>
1; //SYSREF frequency is (PLL1)VCXO frequency / 2 / device->sysrefSettings->sysrefDivide
AD9528_spiReadByte(device, AD9528_ADDR_SYSREF_CTRL4, &reg403);
reg403 = reg403 & ~0x01; //clear bit 0 to stop a continuous sysref if it is on.
AD9528_spiWriteByte(device, AD9528_ADDR_SYSREF_CTRL4, reg403);
reg403 = reg403 & ~0x3E; //clear bits for pattern mode and Nshot mode bitfields
reg403 = reg403 | ((sysrefPatternMode & 0x3) << 4) | ((nShotPulses & 0x7) << 1);
AD9528_spiWriteByte(device, AD9528_ADDR_SYSREF_CTRL4,
reg403); //update internal sysref pattern mode and Nshot mode (number of pulses)
//SYSREF request bit x403[0] is left 0. The next call to AD9528_requestSysref will start the SYSREF
AD9528_spiWriteByte(device, AD9528_ADDR_IO_UPDATE,
0x01); //IO update to make all these settings valid in the 9528
return SUCCESS;
}
int32_t AD9528_sysrefReq(ad9528Device_t *device,
ad9528SysrefReqMode_t mode)
{
if (mode == SYSREF_CONT_ON)
gpio_direction_output(device->gpio_sysref_req, 1);
else if (mode == SYSREF_CONT_OFF)
gpio_direction_output(device->gpio_sysref_req, 0);
else if (mode == SYSREF_PULSE) {
gpio_direction_output(device->gpio_sysref_req, 1);
mdelay(1);
gpio_direction_output(device->gpio_sysref_req, 0);
} else
return FAILURE;
return SUCCESS;
}
/**
* \brief Free the allocated resources
*/
int32_t AD9528_remove(ad9528Device_t *device)
{
int32_t status;
status = gpio_remove(device->gpio_resetb);
status |= gpio_remove(device->gpio_sysref_req);
status |= spi_remove(device->spi_desc);
return SUCCESS;
}
@@ -0,0 +1,245 @@
/**
* \file ad9528.h
* \brief Contains function declarations and ad9528Device_t structure typedef for ad9528.c
*/
/**
* \page Disclaimer Legal Disclaimer
* Copyright 2015-2017 Analog Devices Inc.
* Released under the AD9371 API license.
*
*/
#ifndef _AD9528_H_
#define _AD9528_H_
/******************************************************************************/
/***************************** Include Files **********************************/
/******************************************************************************/
#include <stdint.h>
#include "delay.h"
#include "spi.h"
#include "gpio.h"
/******************************************************************************/
/********************** Macros and Constants Definitions **********************/
/******************************************************************************/
/* AD9528 SPI Address defines */
#define AD9528_ADDR_ADI_SPI_CONFIG_A 0x000
#define AD9528_ADDR_ADI_SPI_CONFIG_B 0x001
#define AD9528_ADDR_IO_UPDATE 0x00F
#define AD9528_ADDR_REF_A_DIVIDER_LSB 0x100
#define AD9528_ADDR_REF_A_DIVIDER_MSB 0x101
#define AD9528_ADDR_REF_B_DIVIDER_LSB 0x102
#define AD9528_ADDR_REF_B_DIVIDER_MSB 0x103
#define AD9528_ADDR_PLL1_N_DIV_LSB 0x104
#define AD9528_ADDR_PLL1_N_DIV_MSB 0x105
#define AD9528_ADDR_PLL1_CHARGEPUMP 0x106
#define AD9528_ADDR_PLL1_CP_CTRL2 0x107
#define AD9528_ADDR_INPUT_RECEIVERS1 0x108
#define AD9528_ADDR_INPUT_RECEIVERS2 0x109
#define AD9528_ADDR_INPUT_RECEIVERS3 0x10A
#define AD9528_ADDR_PLL1_FASTLOCK 0x10B
#define AD9528_ADDR_PLL2_CHARGEPUMP 0x200
#define AD9528_ADDR_PLL2_N_DIV 0x201
#define AD9528_ADDR_PLL2_CTRL 0x202
#define AD9528_ADDR_PLL2_VCO_CTRL 0x203
#define AD9528_ADDR_PLL2_VCO_DIV 0x204
#define AD9528_ADDR_PLL2_LF_CTRL1 0x205
#define AD9528_ADDR_PLL2_LF_CTRL2 0x206
#define AD9528_ADDR_PLL2_RDIV 0x207
#define AD9528_ADDR_PLL2_REPLICA_CHDIV 0x208
#define AD9528_ADDR_PLL2_REPLICA_DIV_PHASE 0x209
#define AD9528_ADDR_CH_OUT0_CTRL1 0x300
#define AD9528_ADDR_CH_OUT0_CTRL2 0x301
#define AD9528_ADDR_CH_OUT0_CHDIV 0x302
#define AD9528_ADDR_OUTPUT_SYNC 0x32A
#define AD9528_ADDR_MASK_SYNC1 0x32B
#define AD9528_ADDR_MASK_SYNC2 0x32C
#define AD9528_ADDR_EN_OUTPUT_PATH_SEL1 0x32D
#define AD9528_ADDR_EN_OUTPUT_PATH_SEL2 0x32E
#define AD9528_ADDR_SYSERF_DIV_LSB 0x400
#define AD9528_ADDR_SYSERF_DIV_MSB 0x401
#define AD9528_ADDR_SYSREF_CTRL3 0x402
#define AD9528_ADDR_SYSREF_CTRL4 0x403
#define AD9528_ADDR_SYSREF_CTRL5 0x404
#define AD9528_ADDR_POWERDOWN_CTRL 0x500
#define AD9528_ADDR_CH_POWERDOWN1 0x501
#define AD9528_ADDR_CH_POWERDOWN2 0x502
#define AD9528_ADDR_LDO_ENABLES1 0x503
#define AD9528_ADDR_LDO_ENABLES2 0x504
#define AD9528_ADDR_STATUS0_CTRL 0x505
#define AD9528_ADDR_STATUS1_CTRL 0x506
#define AD9528_ADDR_STATUS_OE 0x507
#define AD9528_ADDR_STATUS_READBACK0 0x508
#define AD9528_ADDR_STATUS_READBACK1 0x509
/******************************************************************************/
/*************************** Types Declarations *******************************/
/******************************************************************************/
///Enum to select what source outputs from each AD9528 output channel
typedef enum {
AD9528_CHANNEL_DIV = 0, PLL1_OUTPUT = 1, //VCXO frequency
SYSREF = 2,
INV_PLL1_OUTPUT = 5 //VCXO inverted
} ad9528outSourceSel_t;
///Enum to select what output buffer standard is used for the clock outputs
typedef enum {
AD9528_LVDS = 0, AD9528_LVDS_BOOST = 1, AD9528_HSTL = 2
} ad9528outBufferControl_t;
///Enum to select the clock input buffer mode.
typedef enum {
DISABLED = 0, SINGLE_ENDED, NEG_SINGLE_ENDED, DIFFERENTIAL
} ad9528RefBuffer_t;
/// Structure to hold AD9528 PLL1 settings
typedef struct {
uint32_t refA_Frequency_Hz;
uint16_t refA_Divider;
ad9528RefBuffer_t refA_bufferCtrl;
uint32_t refB_Frequency_Hz;
uint16_t refB_Divider;
ad9528RefBuffer_t refB_bufferCtrl;
uint32_t vcxo_Frequency_Hz;
ad9528RefBuffer_t vcxoBufferCtrl;
uint16_t nDivider;
uint8_t bypassPll1;
} ad9528pll1Settings_t;
/// Structure to hold AD9528 PLL2 settings
typedef struct {
uint8_t rfDivider; //VCO divider: Valid range (3,4,5)
uint8_t n2Divider; //PLL2 N2 Divider
uint8_t totalNdiv; //NDiv = 4*Bdiv + Adiv //Bdiv valid range (3 to 63), Adiv valid range (0-3)
} ad9528pll2Settings_t;
/// Structure to hold AD9528 Output Clock settings
typedef struct {
uint16_t outPowerDown; //bit per output, if 1 power down that output.
ad9528outSourceSel_t
outSource[14]; //CHANNEL_DIV, PLL1_OUTPUT, SYSREF, INV_PLL1_OUTPUT
ad9528outBufferControl_t outBufferCtrl[14]; //LVDS, LVDS_BOOST, HSTL
uint8_t outAnalogDelay[14]; //5 bits
uint8_t outDigitalDelay[14]; //6 bits, 1/2 clock resolution @ channel div input frequency
uint8_t outChannelDiv[14]; //8 bit channel divider
uint32_t outFrequency_Hz[14]; //output clock frequency per clock output
} ad9528outputSettings_t;
///Enum to select the SYSREF output source
typedef enum {
EXTERNAL = 0, EXT_RESAMPLED = 1, INTERNAL = 2
} sysrefSourceSelection_t;
///Enum to choose the SYSREF pattern mode.
typedef enum {
NSHOT = 0, CONTINUOUS = 1, PRBS = 2, STOP = 3
} sysrefPatternMode_t;
///Enum to select the SYSREF input pin mode.
typedef enum {
LEVEL_ACTIVE_HIGH = 0, LEVEL_ACTIVE_LOW = 1, RISING_EDGE = 2, FALLING_EDGE = 3
} sysrefPinEdgeMode_t;
///Enum to select the SYSREF output # of pulses for NSHOT mode.
typedef enum {
ONE_PULSE = 0, TWO_PULSES = 2, FOUR_PULSES = 3, SIX_PULSES = 4, EIGHT_PULSES = 5
} sysrefNshotMode_t;
//Enum to select how a SYSREF is requested.
typedef enum {
SPI = 0, PIN = 1
} sysrefRequestMethod_t;
/// Structure to hold AD9528 SYSREF output settings
typedef struct {
sysrefRequestMethod_t sysrefRequestMethod;
sysrefSourceSelection_t sysrefSource;
sysrefPinEdgeMode_t sysrefPinEdgeMode;
ad9528RefBuffer_t sysrefPinBufferMode;
sysrefPatternMode_t sysrefPatternMode;
sysrefNshotMode_t sysrefNshotMode;
uint16_t sysrefDivide;
} ad9528sysrefSettings_t;
/// Structure to hold AD9528 SPI settings
typedef struct {
uint8_t chipSelectIndex; ///< valid 1~8
uint8_t writeBitPolarity; ///< the level of the write bit of a SPI write instruction word, value is inverted for SPI read operation
uint8_t longInstructionWord; ///< 1 = 16bit instruction word, 0 = 8bit instruction word
uint8_t MSBFirst; ///< 1 = MSBFirst, 0 = LSBFirst
uint8_t CPHA; ///< clock phase, sets which clock edge the data updates (valid 0 or 1)
uint8_t CPOL; ///< clock polarity 0 = clock starts low, 1 = clock starts high
uint8_t enSpiStreaming; ///< Not implemented. SW feature to improve SPI throughput.
uint8_t autoIncAddrUp; ///< Not implemented. For SPI Streaming, set address increment direction. 1= next addr = addr+1, 0:addr = addr-1
uint8_t fourWireMode; ///< 1: Use 4-wire SPI, 0: 3-wire SPI (SDIO pin is bidirectional). NOTE: ADI's FPGA platform always uses 4-wire mode.
uint32_t spiClkFreq_Hz; ///< SPI Clk frequency in Hz (default 25000000), platform will use next lowest frequency that it's baud rate generator can create */
} ad9528spiSettings_t;
/// Structure to hold AD9528 settings
typedef struct {
struct gpio_desc *gpio_resetb;
struct gpio_desc *gpio_sysref_req;
struct spi_desc *spi_desc;
ad9528spiSettings_t *spiSettings;
ad9528pll1Settings_t *pll1Settings;
ad9528pll2Settings_t *pll2Settings;
ad9528outputSettings_t *outputSettings;
ad9528sysrefSettings_t *sysrefSettings;
} ad9528Device_t;
typedef struct {
struct gpio_init_param *gpio_init_resetb;
struct gpio_init_param *gpio_init_sysref_req;
struct spi_init_param *spi_init;
ad9528spiSettings_t *spiSettings;
ad9528pll1Settings_t *pll1Settings;
ad9528pll2Settings_t *pll2Settings;
ad9528outputSettings_t *outputSettings;
ad9528sysrefSettings_t *sysrefSettings;
} ad9528Init_t;
typedef enum {
SYSREF_CONT_ON,
SYSREF_CONT_OFF,
SYSREF_PULSE,
} ad9528SysrefReqMode_t;
/******************************************************************************/
/************************ Functions Declarations ******************************/
/******************************************************************************/
//Helper function to setup the 9528 device data structure specifically for the ADI transceiver evaluation cards
int32_t AD9528_initDeviceDataStruct(ad9528Device_t *device,
uint32_t vcxoFrequency_Hz, uint32_t refAFrequency_Hz,
uint32_t outputDeviceClock_Hz);
int32_t AD9528_spiReadByte(ad9528Device_t *device, uint16_t addr,
uint8_t *readdata);
//AD9528 API functions
int32_t AD9528_hasTimeoutExpired();
int32_t AD9528_resetDevice(ad9528Device_t *device);
int32_t AD9528_init(ad9528Device_t **device, const ad9528Init_t *init_device);
int32_t AD9528_config(ad9528Device_t
*device); //writes all registers to desired values, leaves clock outputs off.
int32_t AD9528_setupSYSREF(ad9528Device_t *device,
uint16_t divideFromPll1Out, sysrefPatternMode_t sysrefPatternMode,
sysrefNshotMode_t nShotPulses);
int32_t AD9528_requestSysref(ad9528Device_t *device, uint8_t enableSYSREF);
int32_t AD9528_sysrefReq(ad9528Device_t *device,
ad9528SysrefReqMode_t mode);
int32_t AD9528_remove(ad9528Device_t *device);
#endif
@@ -75,10 +75,10 @@ typedef enum
// 0x0148, 0x0152) // 0x0148, 0x0152)
typedef enum typedef enum
{ {
CML = 0, HMC7044_CML = 0,
LVPECL = 1, HMC7044_LVPECL = 1,
LVDS = 2, HMC7044_LVDS = 2,
CMOS = 3 HMC7044_CMOS = 3
} hmc7044DriverMode_t; } hmc7044DriverMode_t;
// Enum to select the GPIx functionality. (0x0046, 0x0047, 0x0048, 0x0049) // Enum to select the GPIx functionality. (0x0046, 0x0047, 0x0048, 0x0049)
@@ -154,7 +154,7 @@ typedef enum
// 0x0101, 0x010B, 0x0115, 0x011F, 0x0129, 0x0133, 0x013D, 0x0147, 0x0151 // 0x0101, 0x010B, 0x0115, 0x011F, 0x0129, 0x0133, 0x013D, 0x0147, 0x0151
typedef enum typedef enum
{ {
CHANNEL_DIV = 0, HMC7044_CHANNEL_DIV = 0,
ANALOG_DELAY = 1, ANALOG_DELAY = 1,
OTHER_CHANNEL = 2, OTHER_CHANNEL = 2,
VCO_CLOCK = 3 VCO_CLOCK = 3
+19 -288
View File
@@ -34,7 +34,7 @@
/************************** Function Prototypes ******************************/ /************************** Function Prototypes ******************************/
/*********************** Driver Instance Definitions **************************/ /*********************** Driver Instance Definitions **************************/
static struct hmc7044_dev *hmc7044_inst = NULL; ad9528Device_t *ad9528_inst = NULL;
static struct ad9361_reg_dev *ad9361_1_reg_inst = NULL; static struct ad9361_reg_dev *ad9361_1_reg_inst = NULL;
static struct ad9361_reg_dev *ad9361_2_reg_inst = NULL; static struct ad9361_reg_dev *ad9361_2_reg_inst = NULL;
// static struct ad9361_rf_phy *ad9361_phy; // static struct ad9361_rf_phy *ad9361_phy;
@@ -62,12 +62,17 @@ int32_t Hardware_Init(void)
} }
/**********************************************************/ /**********************************************************/
/****************** HMC7044 Configuration *****************/ /****************** AD9528 Configuration ******************/
/**********************************************************/ /**********************************************************/
Status = hmc7044_init(&hmc7044_inst, &hmc7044_default_init_param); Status = AD9528_init(&ad9528_inst, &ad9528_default_init_param);
if (Status != SUCCESS) if (Status != SUCCESS) {
{ DBG_ERROR("AD9528_init() error: %" PRId32 "\n", Status);
DBG_ERROR("hmc7044_init() error: %" PRId32 "\n", Status); return FAILURE;
}
Status = AD9528_config(ad9528_inst);
if (Status != SUCCESS) {
DBG_ERROR("AD9528_config() error: %" PRId32 "\n", Status);
return FAILURE; return FAILURE;
} }
@@ -110,110 +115,6 @@ int32_t Hardware_Init(void)
// Status = ad9361_reg_read(ad9361_1_reg_inst, 0x0002, &rd_back); // Status = ad9361_reg_read(ad9361_1_reg_inst, 0x0002, &rd_back);
// Status = ad9361_reg_read(ad9361_2_reg_inst, 0x0002, &rd_back); // Status = ad9361_reg_read(ad9361_2_reg_inst, 0x0002, &rd_back);
/**********************************************************/
/******* AD9361 Baseband Multichip Synchronization ********/
/**********************************************************/
XGpioPs_SetDirectionPin(&Gpio, AD9361_SYNC, AD9361_GPIO_OUTPUT);
XGpioPs_SetDirectionPin(&Gpio, AD9361_RX_FIFO_RST, AD9361_GPIO_OUTPUT);
// SYNC BBPLL and DIGITAL SAMPLING CLOCKS
ad9361_reg_write(ad9361_1_reg_inst, 0x0001, 0x0D); // MCS RF Enable; MCS BBPLL Enable; MCS BB Enable
ad9361_reg_write(ad9361_2_reg_inst, 0x0001, 0x0D);
ad9361_reg_write(ad9361_1_reg_inst, 0x0047, 0x80); // MCS refclk Scale Enable
ad9361_reg_write(ad9361_2_reg_inst, 0x0047, 0x80);
XGpioPs_WritePin(&Gpio, AD9361_SYNC, 0);
mdelay(20);
XGpioPs_WritePin(&Gpio, AD9361_SYNC, 1); // Input a rising-edge pulse to the SYNC_IN pin
mdelay(500);
XGpioPs_WritePin(&Gpio, AD9361_SYNC, 0);
mdelay(2000);
ad9361_reg_write(ad9361_1_reg_inst, 0x0001, 0x0B); // MCS RF Enable; MCS Digital CLK Enable ; MCS BB Enable
ad9361_reg_write(ad9361_2_reg_inst, 0x0001, 0x0B);
XGpioPs_WritePin(&Gpio, AD9361_SYNC, 1); // Input another rising-edge pulse to the SYNC_IN pin
mdelay(500);
XGpioPs_WritePin(&Gpio, AD9361_SYNC, 0);
ad9361_reg_write(ad9361_1_reg_inst, 0x0001, 0x08); // clear MCS bits
ad9361_reg_write(ad9361_2_reg_inst, 0x0001, 0x08);
XGpioPs_WritePin(&Gpio, AD9361_RX_FIFO_RST, 0);
mdelay(20);
XGpioPs_WritePin(&Gpio, AD9361_RX_FIFO_RST, 1);
mdelay(20);
XGpioPs_WritePin(&Gpio, AD9361_RX_FIFO_RST, 0);
/**********************************************************/
/********* AD9361 Multichip Rx Phase Calibration **********/
/**********************************************************/
XGpioPs_SetDirectionPin(&Gpio, AD9361_TX_SWITCH, AD9361_GPIO_OUTPUT);
XGpioPs_SetDirectionPin(&Gpio, AD9361_1_CAL_START, AD9361_GPIO_OUTPUT);
XGpioPs_SetDirectionPin(&Gpio, AD9361_1_CAL_DONE, AD9361_GPIO_INPUT);
XGpioPs_SetDirectionPin(&Gpio, AD9361_2_CAL_START, AD9361_GPIO_OUTPUT);
XGpioPs_SetDirectionPin(&Gpio, AD9361_2_CAL_DONE, AD9361_GPIO_INPUT);
// switch to lower frequency
Status = Hardware_SwitchFreq(ad9361_1_reg_inst, TX_FREQ_126);
XGpioPs_WritePin(&Gpio, AD9361_TX_SWITCH, 1);
mdelay(20);
// switch rx channel
Status = ad9361_reg_write(ad9361_1_reg_inst, 0x0004, 0x30);
Status = ad9361_reg_write(ad9361_2_reg_inst, 0x0004, 0x30);
// enable dual ad9361 tx channels
Status = ad9361_reg_write(ad9361_1_reg_inst, 0x0002, 0xE4); // Setup Tx Digital Filters/ Channels
// switch ad9361 tx channel
Status = ad9361_reg_write(ad9361_1_reg_inst, 0x0004, 0x70); // Select Rx input pin(A,B,C)/ Tx out pin (A,B)
mdelay(20);
// begin to calibrate the 1st ad9361
XGpioPs_WritePin(&Gpio, AD9361_1_CAL_START, 0);
XGpioPs_WritePin(&Gpio, AD9361_1_CAL_START, 1);
mdelay(1);
XGpioPs_WritePin(&Gpio, AD9361_1_CAL_START, 0);
// read calibration status
int32_t time_out_cnt = 0;
do
{
mdelay(1); // Wait 1ms
time_out_cnt++;
} while (((XGpioPs_ReadPin(&Gpio, AD9361_1_CAL_DONE) == 0) && time_out_cnt <= AD9361_TIMEOUT_TH));
if (time_out_cnt == AD9361_TIMEOUT_TH)
{
return FAILURE;
}
// begin to calibrate the 2nd ad9361
XGpioPs_WritePin(&Gpio, AD9361_2_CAL_START, 1);
mdelay(1);
XGpioPs_WritePin(&Gpio, AD9361_2_CAL_START, 0);
// read calibration status
time_out_cnt = 0;
do
{
mdelay(1); // Wait 1ms
time_out_cnt++;
} while (((XGpioPs_ReadPin(&Gpio, AD9361_2_CAL_DONE) == 0) && time_out_cnt <= AD9361_TIMEOUT_TH));
if (time_out_cnt == AD9361_TIMEOUT_TH)
{
return FAILURE;
}
// enable single ad9361 tx channels
Status = ad9361_reg_write(ad9361_1_reg_inst, 0x0002, 0xA4); // Setup Tx Digital Filters/ Channels
// switch ad9361 tx & rx channel
Status = ad9361_reg_write(ad9361_1_reg_inst, 0x0004, 0x03);
Status = ad9361_reg_write(ad9361_2_reg_inst, 0x0004, 0x03);
// switch to higher frequency
Status = Hardware_SwitchFreq(ad9361_1_reg_inst, TX_FREQ_4125);
XGpioPs_WritePin(&Gpio, AD9361_TX_SWITCH, 0);
Status = ad9361_reg_write(ad9361_1_reg_inst, 0x0109, 0x00); // Rx Gain Status = ad9361_reg_write(ad9361_1_reg_inst, 0x0109, 0x00); // Rx Gain
Status = ad9361_reg_write(ad9361_1_reg_inst, 0x010C, 0x00); // Rx Gain Status = ad9361_reg_write(ad9361_1_reg_inst, 0x010C, 0x00); // Rx Gain
Status = ad9361_reg_write(ad9361_2_reg_inst, 0x0109, 0x00); // Rx Gain Status = ad9361_reg_write(ad9361_2_reg_inst, 0x0109, 0x00); // Rx Gain
@@ -224,176 +125,6 @@ int32_t Hardware_Init(void)
return SUCCESS; return SUCCESS;
} }
/*****************************************************************************/
/**
* @brief Hardware_SwitchFreq
*
* @param devSysMonitor_UpdateHardwareStatus(newHwState);
* @param freq
*
* @return None.
*
******************************************************************************/
int32_t Hardware_SwitchFreq(struct ad9361_reg_dev *dev, ad9361TxFreq freq)
{
int32_t status = 0;
uint8_t value = 0;
int32_t time_out_cnt = 0;
switch (freq)
{
case TX_FREQ_125:
{
//************************************************************
// Setup Tx Frequency-Dependent Syntheisizer Registers
//************************************************************
status = ad9361_reg_write(dev, 0x027A, 0x4A); // Set VCO Output level[3:0]
status = ad9361_reg_write(dev, 0x0279, 0xC1); // Set Init ALC Value[3:0] and VCO Varactor[3:0]
status = ad9361_reg_write(dev, 0x0282, 0x0E); // Set VCO Bias Tcf[1:0] and VCO Bias Ref[2:0]
status = ad9361_reg_write(dev, 0x0278, 0x78); // Set VCO Cal Offset[3:0]
status = ad9361_reg_write(dev, 0x0285, 0x00); // Set VCO Cal Ref Tcf[2:0]
status = ad9361_reg_write(dev, 0x0291, 0x0B); // Set VCO Varactor Reference[3:0]
status = ad9361_reg_write(dev, 0x0290, 0x70); // Set VCO Varactor Ref Tcf[2:0] and VCO Varactor Offset[3:0]
status = ad9361_reg_write(dev, 0x027B, 0x94); // Set Synth Loop Filter charge pump current (Icp)
status = ad9361_reg_write(dev, 0x027E, 0xF4); // Set Synth Loop Filter C2 and C1
status = ad9361_reg_write(dev, 0x027F, 0xDF); // Set Synth Loop Filter R1 and C3
status = ad9361_reg_write(dev, 0x0280, 0x0A); // Set Synth Loop Filter R3
//************************************************************
// Write Tx Frequency Words
//************************************************************
status = ad9361_reg_write(dev, 0x0273, 0x00); // Write Tx Synth Fractional Freq Word[7:0]
status = ad9361_reg_write(dev, 0x0274, 0x00); // Write Tx Synth Fractional Freq Word[15:8]
status = ad9361_reg_write(dev, 0x0275, 0x00); // Write Tx Synth Fractional Freq Word[22:16]
status = ad9361_reg_write(dev, 0x0272, 0x00); // Write Tx Synth Integer Freq Word[10:8]
status = ad9361_reg_write(dev, 0x0271, 0xA0); // Write Tx Synth Integer Freq Word[7:0] (starts VCO cal)
status = ad9361_reg_write(dev, 0x0005, 0x57); // Set LO divider setting
//************************************************************
// Tx Quadrature Calibration Settings
//************************************************************
status = ad9361_reg_write(dev, 0x00A0, 0x75); // Set TxQuadcal NCO frequency
status = ad9361_reg_write(dev, 0x00A3, 0xC0); // Set TxQuadcal NCO frequency (Only update bits [7:6])
status = ad9361_reg_write(dev, 0x00A1, 0x7B); // Tx Quad Cal Configuration, Phase and Gain Cal Enable
status = ad9361_reg_write(dev, 0x00A9, 0xFF); // Set Tx Quad Cal Count
status = ad9361_reg_write(dev, 0x00A2, 0x7F); // Set Tx Quad Cal Kexp
status = ad9361_reg_write(dev, 0x00A5, 0x01); // Set Tx Quad Cal Magnitude Threshhold
status = ad9361_reg_write(dev, 0x00A6, 0x01); // Set Tx Quad Cal Magnitude Threshhold
status = ad9361_reg_write(dev, 0x00AA, 0x22); // Set Tx Quad Cal Gain Table index
status = ad9361_reg_write(dev, 0x00A4, 0xF0); // Set Tx Quad Cal Settle Count
status = ad9361_reg_write(dev, 0x00AE, 0x00); // Set Tx Quad Cal LPF Gain index incase Split table mode used
status = ad9361_reg_write(dev, 0x0169, 0xC0); // Disable Rx Quadrature Calibration before Running Tx Quadrature Calibration
status = ad9361_reg_write(dev, 0x0016, 0x10); // Start Tx Quad cal
break;
}
case TX_FREQ_126:
{
//************************************************************
// Setup Tx Frequency-Dependent Syntheisizer Registers
//************************************************************
status = ad9361_reg_write(dev, 0x027A, 0x4A); // Set VCO Output level[3:0]
status = ad9361_reg_write(dev, 0x0279, 0xC1); // Set Init ALC Value[3:0] and VCO Varactor[3:0]
status = ad9361_reg_write(dev, 0x0282, 0x0E); // Set VCO Bias Tcf[1:0] and VCO Bias Ref[2:0]
status = ad9361_reg_write(dev, 0x0278, 0x78); // Set VCO Cal Offset[3:0]
status = ad9361_reg_write(dev, 0x0285, 0x00); // Set VCO Cal Ref Tcf[2:0]
status = ad9361_reg_write(dev, 0x0291, 0x0B); // Set VCO Varactor Reference[3:0]
status = ad9361_reg_write(dev, 0x0290, 0x70); // Set VCO Varactor Ref Tcf[2:0] and VCO Varactor Offset[3:0]
status = ad9361_reg_write(dev, 0x027B, 0x93); // Set Synth Loop Filter charge pump current (Icp)
status = ad9361_reg_write(dev, 0x027E, 0xF4); // Set Synth Loop Filter C2 and C1
status = ad9361_reg_write(dev, 0x027F, 0xDF); // Set Synth Loop Filter R1 and C3
status = ad9361_reg_write(dev, 0x0280, 0x0A); // Set Synth Loop Filter R3
//************************************************************
// Write Tx Frequency Words
//************************************************************
status = ad9361_reg_write(dev, 0x0273, 0x06); // Write Tx Synth Fractional Freq Word[7:0]
status = ad9361_reg_write(dev, 0x0274, 0xD7); // Write Tx Synth Fractional Freq Word[15:8]
status = ad9361_reg_write(dev, 0x0275, 0x23); // Write Tx Synth Fractional Freq Word[22:16]
status = ad9361_reg_write(dev, 0x0272, 0x00); // Write Tx Synth Integer Freq Word[10:8]
status = ad9361_reg_write(dev, 0x0271, 0xA1); // Write Tx Synth Integer Freq Word[7:0] (starts VCO cal)
status = ad9361_reg_write(dev, 0x0005, 0x57); // Set LO divider setting
//************************************************************
// Tx Quadrature Calibration Settings
//************************************************************
status = ad9361_reg_write(dev, 0x00A0, 0x75); // Set TxQuadcal NCO frequency
status = ad9361_reg_write(dev, 0x00A3, 0xC0); // Set TxQuadcal NCO frequency (Only update bits [7:6])
status = ad9361_reg_write(dev, 0x00A1, 0x7B); // Tx Quad Cal Configuration, Phase and Gain Cal Enable
status = ad9361_reg_write(dev, 0x00A9, 0xFF); // Set Tx Quad Cal Count
status = ad9361_reg_write(dev, 0x00A2, 0x7F); // Set Tx Quad Cal Kexp
status = ad9361_reg_write(dev, 0x00A5, 0x01); // Set Tx Quad Cal Magnitude Threshhold
status = ad9361_reg_write(dev, 0x00A6, 0x01); // Set Tx Quad Cal Magnitude Threshhold
status = ad9361_reg_write(dev, 0x00AA, 0x22); // Set Tx Quad Cal Gain Table index
status = ad9361_reg_write(dev, 0x00A4, 0xF0); // Set Tx Quad Cal Settle Count
status = ad9361_reg_write(dev, 0x00AE, 0x00); // Set Tx Quad Cal LPF Gain index incase Split table mode used
status = ad9361_reg_write(dev, 0x0169, 0xC0); // Disable Rx Quadrature Calibration before Running Tx Quadrature Calibration
status = ad9361_reg_write(dev, 0x0016, 0x10); // Start Tx Quad cal
break;
}
case TX_FREQ_4125:
{
//************************************************************
// Setup Tx Frequency-Dependent Syntheisizer Registers
//************************************************************
status = ad9361_reg_write(dev, 0x027A, 0x4A); // Set VCO Output level[3:0]
status = ad9361_reg_write(dev, 0x0279, 0xC1); // Set Init ALC Value[3:0] and VCO Varactor[3:0]
status = ad9361_reg_write(dev, 0x0282, 0x0E); // Set VCO Bias Tcf[1:0] and VCO Bias Ref[2:0]
status = ad9361_reg_write(dev, 0x0278, 0x78); // Set VCO Cal Offset[3:0]
status = ad9361_reg_write(dev, 0x0285, 0x00); // Set VCO Cal Ref Tcf[2:0]
status = ad9361_reg_write(dev, 0x0291, 0x0B); // Set VCO Varactor Reference[3:0]
status = ad9361_reg_write(dev, 0x0290, 0x70); // Set VCO Varactor Ref Tcf[2:0] and VCO Varactor Offset[3:0]
status = ad9361_reg_write(dev, 0x027B, 0x93); // Set Synth Loop Filter charge pump current (Icp)
status = ad9361_reg_write(dev, 0x027E, 0xF4); // Set Synth Loop Filter C2 and C1
status = ad9361_reg_write(dev, 0x027F, 0xDF); // Set Synth Loop Filter R1 and C3
status = ad9361_reg_write(dev, 0x0280, 0x0A); // Set Synth Loop Filter R3
//************************************************************
// Write Rx Frequency Words
//************************************************************
status = ad9361_reg_write(dev, 0x0273, 0x00); // Write Tx Synth Fractional Freq Word[7:0]
status = ad9361_reg_write(dev, 0x0274, 0x00); // Write Tx Synth Fractional Freq Word[15:8]
status = ad9361_reg_write(dev, 0x0275, 0x00); // Write Tx Synth Fractional Freq Word[22:16]
status = ad9361_reg_write(dev, 0x0272, 0x00); // Write Tx Synth Integer Freq Word[10:8]
status = ad9361_reg_write(dev, 0x0271, 0xA5); // Write Tx Synth Integer Freq Word[7:0] (starts VCO cal)
status = ad9361_reg_write(dev, 0x0005, 0x07); // Set LO divider setting
//************************************************************
// Tx Quadrature Calibration Settings
//************************************************************
status = ad9361_reg_write(dev, 0x00A0, 0x75); // Set TxQuadcal NCO frequency
status = ad9361_reg_write(dev, 0x00A3, 0xC0); // Set TxQuadcal NCO frequency (Only update bits [7:6])
status = ad9361_reg_write(dev, 0x00A1, 0x7B); // Tx Quad Cal Configuration, Phase and Gain Cal Enable
status = ad9361_reg_write(dev, 0x00A9, 0xFF); // Set Tx Quad Cal Count
status = ad9361_reg_write(dev, 0x00A2, 0x7F); // Set Tx Quad Cal Kexp
status = ad9361_reg_write(dev, 0x00A5, 0x01); // Set Tx Quad Cal Magnitude Threshhold
status = ad9361_reg_write(dev, 0x00A6, 0x01); // Set Tx Quad Cal Magnitude Threshhold
status = ad9361_reg_write(dev, 0x00AA, 0x28); // Set Tx Quad Cal Gain Table index
status = ad9361_reg_write(dev, 0x00A4, 0xF0); // Set Tx Quad Cal Settle Count
status = ad9361_reg_write(dev, 0x00AE, 0x04); // Set Tx Quad Cal LPF Gain index incase Split table mode used
status = ad9361_reg_write(dev, 0x0169, 0xC0); // Disable Rx Quadrature Calibration before Running Tx Quadrature Calibration
status = ad9361_reg_write(dev, 0x0016, 0x10); // Start Tx Quad cal
break;
}
// Wait for cal to complete (Done when 0x016[4]==0)
time_out_cnt = 0;
do
{
status |= ad9361_reg_read(dev, 0x0016, &value);
mdelay(1); // Wait 1ms
time_out_cnt++;
} while ((value & 0x10) != 0x00 && time_out_cnt <= AD9361_TIMEOUT_TH);
}
return status;
}
// @ Get AD9361 - 1 temperature (Celsius Degree) // @ Get AD9361 - 1 temperature (Celsius Degree)
/** /**
* Read corresponding register to get AD9361 - 1 current temperature. * Read corresponding register to get AD9361 - 1 current temperature.
@@ -453,22 +184,22 @@ uint8_t Hardware_GetAD9361LockStatus(void)
return ret; return ret;
} }
// @ Determine HMC7044 lock state // @ Determine AD9528 lock state
/** /**
* Read corresponding register to determine clock lock state. * Read corresponding register to determine clock lock state.
*/ */
uint8_t Hardware_GetHMC7044LockStatus(void) uint8_t Hardware_GetAD9528LockStatus(void)
{ {
uint8_t ret = 0; uint8_t ret = 0;
uint8_t regVal; uint8_t regVal;
// pll1 // pll1
hmc7044_read(hmc7044_inst, 0x007C, &regVal); // [D5] is lock indicator AD9528_spiReadByte(ad9528_inst, AD9528_ADDR_STATUS_READBACK0, &regVal); // [D0] is lock indicator
ret |= ((regVal & 0xE0) != 0x00) ? CLK_SP_PLL0_LOCK : 0;
// pll2
hmc7044_read(hmc7044_inst, 0x007D, &regVal); // [D0] is lock indicator
ret |= ((regVal & 0x01) == 0x01) ? CLK_SP_PLL1_LOCK : 0; ret |= ((regVal & 0x01) == 0x01) ? CLK_SP_PLL1_LOCK : 0;
// pll2
AD9528_spiReadByte(ad9528_inst, AD9528_ADDR_STATUS_READBACK0, &regVal); // [D1] is lock indicator
ret |= ((regVal & 0x02) == 0x02) ? CLK_SP_PLL2_LOCK : 0;
return ret; return ret;
} }
+1 -2
View File
@@ -24,10 +24,9 @@
/************************** Function Prototypes ******************************/ /************************** Function Prototypes ******************************/
int32_t Hardware_Init(void); int32_t Hardware_Init(void);
int32_t Hardware_SwitchFreq(struct ad9361_reg_dev *dev, ad9361TxFreq freq);
int8_t Hardware_GetAD9361Temp_1(void); int8_t Hardware_GetAD9361Temp_1(void);
int8_t Hardware_GetAD9361Temp_2(void); int8_t Hardware_GetAD9361Temp_2(void);
uint8_t Hardware_GetAD9361LockStatus(void); uint8_t Hardware_GetAD9361LockStatus(void);
uint8_t Hardware_GetHMC7044LockStatus(void); uint8_t Hardware_GetAD9528LockStatus(void);
#endif // HWCONFIG_H_ #endif // HWCONFIG_H_
+8 -10
View File
@@ -38,7 +38,7 @@
/************************** Function Prototypes ******************************/ /************************** Function Prototypes ******************************/
int32_t SetupInterruptSystem(struct irq_ctrl_desc *descPtr); int32_t SetupInterruptSystem(struct irq_ctrl_desc *descPtr);
void Phy_IntrHandler(void *context); void Phy_IntrHandler(void *context);
void PeriodicPull_Handler(void *callBackRef); void PeriodicPoll_Handler(void *callBackRef);
void ScuTimer_IntrHandler(void *context); void ScuTimer_IntrHandler(void *context);
void Systembus_RxIntrHandler(void *context); void Systembus_RxIntrHandler(void *context);
void Systembus_TxIntrHandler(void *context); void Systembus_TxIntrHandler(void *context);
@@ -49,8 +49,8 @@ struct callback_desc phy_callback_desc = {
.ctx = NULL .ctx = NULL
}; };
struct callback_desc periodicpull_callback_desc = { struct callback_desc periodicpoll_callback_desc = {
.callback = PeriodicPull_Handler, .callback = PeriodicPoll_Handler,
.ctx = NULL .ctx = NULL
}; };
@@ -94,11 +94,10 @@ static PHY_CONFIG phyConfig = {
.devId = PHY_DEVICE_ID, .devId = PHY_DEVICE_ID,
.baseAddr = PHY_BASEADDR, .baseAddr = PHY_BASEADDR,
.antBramId = PHY_ANTCONFIG_BRAM_DEVICE_ID, .antBramId = PHY_ANTCONFIG_BRAM_DEVICE_ID,
.antInfoBramId = PHY_ANTINFO_BRAM_DEVICE_ID,
.txBramId = PHY_TXBUFF_BRAM_DEVICE_ID, .txBramId = PHY_TXBUFF_BRAM_DEVICE_ID,
.rxBramId = PHY_RXBUFF_BRAM_DEVICE_ID, .rxBramId = PHY_RXBUFF_BRAM_DEVICE_ID,
.hwXadcId = PHY_HW_XADC_DEVICE_ID, .hwXadcId = PHY_HW_XADC_DEVICE_ID,
.get_clk_state = Hardware_GetHMC7044LockStatus, .get_clk_state = Hardware_GetAD9528LockStatus,
.get_ad_lock_state = Hardware_GetAD9361LockStatus, .get_ad_lock_state = Hardware_GetAD9361LockStatus,
.get_ad0_temp = Hardware_GetAD9361Temp_1, .get_ad0_temp = Hardware_GetAD9361Temp_1,
.get_ad1_temp = Hardware_GetAD9361Temp_2 .get_ad1_temp = Hardware_GetAD9361Temp_2
@@ -190,7 +189,7 @@ int32_t SetupInterruptSystem(struct irq_ctrl_desc *descPtr)
return Status; return Status;
} }
// Connect the interrupt service routine isr1 to the interrupt controller // Connect the interrupt service routine isr1 to the interrupt controller
Status = irq_register_callback(descPtr, PERIODIC_5MS_INTR_ID, &periodicpull_callback_desc); Status = irq_register_callback(descPtr, PERIODIC_5MS_INTR_ID, &periodicpoll_callback_desc);
if (Status != SUCCESS) if (Status != SUCCESS)
{ {
DBG_ERROR("PHY_INTR register callback FAILED, ErrorCode: %" PRId32 ".\n", Status); DBG_ERROR("PHY_INTR register callback FAILED, ErrorCode: %" PRId32 ".\n", Status);
@@ -282,17 +281,16 @@ void Phy_IntrHandler(void *context)
Phy_UpdateState(phyInstPtr); Phy_UpdateState(phyInstPtr);
} // PhyIntr_Handler } // PhyIntr_Handler
/****************************************************************************/ /****************************************************************************/
/** /**
* Handler of periodic 5ms interrupt * Handler of periodic 2ms interrupt
* *
* @param callBackRef is the linklayer instance pointer. * @param callBackRef is the linklayer instance pointer.
* *
* @return None. * @return None.
* *
*****************************************************************************/ *****************************************************************************/
void PeriodicPull_Handler(void *callBackRef) void PeriodicPoll_Handler(void *callBackRef)
{ {
int32_t Status; int32_t Status;
Status = Linklayer_Proc(linkInstPtr); Status = Linklayer_Proc(linkInstPtr);
@@ -301,7 +299,7 @@ void PeriodicPull_Handler(void *callBackRef)
DBG_ERROR("Link layer runs failed, with error code: %" PRId32 "\n", Status); DBG_ERROR("Link layer runs failed, with error code: %" PRId32 "\n", Status);
_nop_(); _nop_();
} }
} // PeriodicPull_Handler } // PeriodicPoll_Handler
/*****************************************************************************/ /*****************************************************************************/
/** /**
@@ -81,7 +81,7 @@ void L2_FrameGetChunk(uint8_t *frame, size_t offset, size_t bytes, void *chunk)
* SUCCESS * SUCCESS
* *
******************************************************************************/ ******************************************************************************/
static int32_t L2_CrcGen(uint8_t *dataBuff, uint32_t dataLen, L2_CRC_TYPE crcType, uint32_t *crc) int32_t L2_CrcGen(uint8_t *dataBuff, uint32_t dataLen, L2_CRC_TYPE crcType, uint32_t *crc)
{ {
ASSERT(dataBuff != NULL); ASSERT(dataBuff != NULL);
int32_t Status; int32_t Status;
@@ -33,7 +33,7 @@
#endif #endif
/************************** Constant Definitions *****************************/ /************************** Constant Definitions *****************************/
#define NET_START_TIME_INFTY UINT32_MAX #define NET_START_TIME_INFTY UINT32_MAX
#define LINK_BROCK_THRESHOLD L2_SLOTS_PER_FRAME // 0.5 secods #define LINK_BROCK_THRESHOLD L2_SLOTS_PER_FRAME // 1 seconds
/************************** Variable Definitions *****************************/ /************************** Variable Definitions *****************************/
/***************** Macros (Inline Functions) Definitions *********************/ /***************** Macros (Inline Functions) Definitions *********************/
@@ -59,7 +59,7 @@ inline void L2_RcdShift(L2_RCD *rcd, uint32_t netxVal)
} }
/** /**
* @brief helper function to update linkelayer state * @brief helper function to update linklayer state
*/ */
static inline void UpdateMainSate(L2_INST *instPtr, L2_NODE_STATE newSate) static inline void UpdateMainSate(L2_INST *instPtr, L2_NODE_STATE newSate)
{ {
@@ -131,7 +131,7 @@ static void L2_FrameStateUpdate(L2_INST *instPtr)
ASSERT(instPtr != NULL); ASSERT(instPtr != NULL);
PHY_INST *phyRef = instPtr->config.phyInstPtr; PHY_INST *phyRef = instPtr->config.phyInstPtr;
bool isValid; bool isValid;
L2_FRAME_TYPE recvType = L2_GetLastOptFrameType(instPtr); L2_FRAME_TYPE recvType = L2_GetLastFrameType(instPtr);
isValid = false; isValid = false;
// Update frame state. // Update frame state.
if (Phy_IsFrameValid(phyRef) == false) if (Phy_IsFrameValid(phyRef) == false)
@@ -148,20 +148,34 @@ static void L2_FrameStateUpdate(L2_INST *instPtr)
// Update frame state. // Update frame state.
switch (recvType) switch (recvType)
{ {
case L2_SCAN_FRAME: case L2_FRAME_ADV:
case L2_ADV_FRAME: isValid = L2_CrcCheck(instPtr->recvPktData, L2_GetFrameLen(L2_FRAME_ADV, L2_SVC_NONE), L2_CRC8_31);
isValid = L2_CrcCheck(instPtr->recvPktData, L2_ADV_PACK_LEN, L2_CRC16_1021);
instPtr->log.advRecvCnt++; instPtr->log.advRecvCnt++;
instPtr->log.advCorrectCnt = isValid ? instPtr->log.advCorrectCnt + 1 : instPtr->log.advCorrectCnt; instPtr->log.advCorrectCnt = isValid ? instPtr->log.advCorrectCnt + 1 : instPtr->log.advCorrectCnt;
break; break;
case L2_CFM_FRAME: case L2_FRAME_ACK:
isValid = L2_CrcCheck(instPtr->recvPktData, L2_CMF_PACK_LEN, L2_CRC16_1021); isValid = L2_CrcCheck(instPtr->recvPktData, L2_GetFrameLen(L2_FRAME_ACK, L2_SVC_NONE), L2_CRC8_31);
instPtr->log.cfmRecvCnt++; instPtr->log.ackRecvCnt++;
instPtr->log.cfmCorrectCnt = isValid ? instPtr->log.cfmCorrectCnt + 1 : instPtr->log.cfmCorrectCnt; instPtr->log.ackCorrectCnt = isValid ? instPtr->log.ackCorrectCnt + 1 : instPtr->log.ackCorrectCnt;
break; break;
case L2_SVC_FRAME: case L2_FRAME_DIS:
isValid = L2_CrcCheck(instPtr->recvPktData, L2_GetFrameLen(L2_FRAME_DIS, L2_SVC_NONE), L2_CRC8_31);
instPtr->log.disRecvCnt++;
instPtr->log.disCorrectCnt = isValid ? instPtr->log.disCorrectCnt + 1 : instPtr->log.disCorrectCnt;
break;
case L2_FRAME_MNG:
isValid = L2_CrcCheck(instPtr->recvPktData, L2_GetFrameLen(L2_FRAME_MNG, L2_SVC_NONE), L2_CRC8_31);
instPtr->log.mngRecvCnt++;
instPtr->log.mngCorrectCnt = isValid ? instPtr->log.mngCorrectCnt + 1 : instPtr->log.mngCorrectCnt;
break;
case L2_FRAME_RTT:
isValid = L2_CrcCheck(instPtr->recvPktData, L2_GetFrameLen(L2_FRAME_RTT, L2_SVC_NONE), L2_CRC8_31);
instPtr->log.rttRecvCnt++;
instPtr->log.rttCorrectCnt = isValid ? instPtr->log.rttCorrectCnt + 1 : instPtr->log.rttCorrectCnt;
break;
case L2_FRAME_SVC:
#ifndef DATALINK_ENABLE_BERTEST #ifndef DATALINK_ENABLE_BERTEST
isValid = L2_CrcCheck(instPtr->recvPktData, L2_SVC_PACK_LEN, L2_CRC16_1021); isValid = L2_CrcCheck(instPtr->recvPktData, L2_GetFrameLen(L2_FRAME_SVC, instPtr->config.serviceRate), L2_CRC8_31);
#else #else
isValid = true; isValid = true;
#endif #endif
@@ -265,9 +279,9 @@ inline bool L2_isCxn2Net(L2_INST *instPtr)
/** /**
* @brief Get corresponding frame length in byte of L2 frame. * @brief Get corresponding frame length in byte of L2 frame.
*/ */
inline uint32_t L2_GetFrameLen(L2_FRAME_TYPE l2FrameType) inline uint32_t L2_GetFrameLen(L2_FRAME_TYPE l2FrameType, L2_SVC_RATE l2SvcRate)
{ {
return Phy_GetFrameLen(L2_L2frame2L1frame(l2FrameType)); return Phy_GetFrameLen(L2_L2frame2L1frame(l2FrameType, l2SvcRate));
} }
/** /**
@@ -377,57 +391,128 @@ inline L2_TOR_TYPE L2_GetNextTor(L2_INST *instPtr)
return instPtr->tor.next; return instPtr->tor.next;
} }
/*****************************************************************************/
/** /**
* @brief Infer last received frame type. * @brief Get service rate of the node.
* */
* @param instPtr A pointer to physical layer control instance. inline L2_SVC_RATE L2_GetServiceRate(L2_INST *instPtr)
*
* @return L2_FRAME_TYPE.
*
******************************************************************************/
L2_FRAME_TYPE L2_GetLastOptFrameType(L2_INST *instPtr)
{ {
if (instPtr->myInfo.nodeType == L2_NODE_HEAD || L2_isCxn2Net(instPtr)) ASSERT(instPtr != NULL);
{ return instPtr->config.serviceRate;
return instPtr->frame.curr;
}
switch (instPtr->scanFSM->scanStage)
{
case L2_SCAN_INIT_STAGE:
return L2_SCAN_FRAME;
case L2_SCAN_ADV_STAGE:
return L2_ADV_FRAME;
case L2_SCAN_CFM_STAGE:
return L2_CFM_FRAME;
default:
return L2_NONE_FRAME;
}
} }
/*****************************************************************************/ /*****************************************************************************/
/** /**
* @brief Convert L2 frame type to L1 frame type * @brief Convert L2 frame type to L1 frame type
* *
* @param l2Frame * @param l2Frame
* @param l2SvcRate
* *
* @return L1 frame type. * @return L1 frame type.
* *
******************************************************************************/ ******************************************************************************/
L1_FRAME_TYPE L2_L2frame2L1frame(L2_FRAME_TYPE l2Frame) L1_FRAME_TYPE L2_L2frame2L1frame(L2_FRAME_TYPE l2Frame, L2_SVC_RATE l2SvcRate)
{ {
switch (l2Frame) switch (l2Frame)
{ {
case L2_SCAN_FRAME: case L2_FRAME_ADV:
return L1_10KBPS_10MS_FRAME; return L1_FRAME_ADV_24MS;
case L2_ADV_FRAME: case L2_FRAME_ACK:
return L1_10KBPS_20MS_FRAME; return L1_FRAME_ACK_8MS;
case L2_CFM_FRAME: case L2_FRAME_DIS:
case L2_SVC_FRAME: case L2_FRAME_MNG:
return L1_40KBPS_20MS_FRAME; case L2_FRAME_RTT:
return L1_FRAME_128KBPS_4MS;
case L2_FRAME_SVC:
switch (l2SvcRate)
{
case L2_SVC_128K:
return L1_FRAME_128KBPS_4MS;
case L2_SVC_512K:
return L1_FRAME_512KBPS_4MS;
case L2_SVC_2M:
return L1_FRAME_2MBPS_4MS;
default:
return L1_FRAME_NONE;
}
default: default:
return L1_NONE_FRAME; return L1_FRAME_NONE;
} }
} }
/*****************************************************************************/
/**
* @brief Get L2 service packet length based on service rate
*
* @param l2SvcRate
*
* @return Packet length.
*
******************************************************************************/
size_t L2_GetSvcPacketLen(L2_SVC_RATE l2SvcRate)
{
switch (l2SvcRate)
{
case L2_SVC_128K:
return sizeof(L2_MSG_SVC_128K);
case L2_SVC_512K:
return sizeof(L2_MSG_SVC_512K);
case L2_SVC_2M:
return sizeof(L2_MSG_SVC_2M);
default:
DBG_ERROR("Unsupported service rate: %" PRId8 ".\n", instPtr->config.serviceRate);
return EPARAM;
}
}
/*****************************************************************************/
/**
* @brief Get L2 service payload length based on service rate
*
* @param l2SvcRate
*
* @return Payload length.
*
******************************************************************************/
size_t L2_GetSvcPayloadLen(L2_SVC_RATE l2SvcRate)
{
switch (l2SvcRate)
{
case L2_SVC_128K:
return L2_PAYLOAD_LEN_SVC_128K;
case L2_SVC_512K:
return L2_PAYLOAD_LEN_SVC_512K;
case L2_SVC_2M:
return L2_PAYLOAD_LEN_SVC_2M;
default:
DBG_ERROR("Unsupported service rate: %" PRId8 ".\n", instPtr->config.serviceRate);
return EPARAM;
}
}
/*****************************************************************************/
/**
* @brief Convert antenna broadcast id to antenna index
*
* @param antId
*
* @return Physical antenna index.
*
******************************************************************************/
PHY_ANT_INDEX L2_AntId2AntIndex(uint8_t antId)
{
switch (antId)
{
case L2_BROADCAST_ID1:
return PHY_ANT_INDEX_1;
case L2_BROADCAST_ID2:
return PHY_ANT_INDEX_2;
case L2_BROADCAST_ID3:
return PHY_ANT_INDEX_3;
default:
return PHY_ANT_INDEX_NONE;
}
}
/** @} LinkLayer_Utility*/ /** @} LinkLayer_Utility*/
/** /**
@@ -475,7 +560,6 @@ int32_t Linklayer_Init(L2_INST **instPtr, const L2_CONFIG *config)
(*instPtr)->recvPktData = NULL; (*instPtr)->recvPktData = NULL;
(*instPtr)->schdEventPool = NULL; (*instPtr)->schdEventPool = NULL;
(*instPtr)->nodeList = NULL; (*instPtr)->nodeList = NULL;
(*instPtr)->scanFSM = NULL;
(*instPtr)->serviceFSM = NULL; (*instPtr)->serviceFSM = NULL;
memcpy(&((*instPtr)->config), config, sizeof(L2_CONFIG)); memcpy(&((*instPtr)->config), config, sizeof(L2_CONFIG));
@@ -508,9 +592,9 @@ int32_t Linklayer_Init(L2_INST **instPtr, const L2_CONFIG *config)
(*instPtr)->slotNum.last = 0; (*instPtr)->slotNum.last = 0;
(*instPtr)->slotNum.curr = 0; (*instPtr)->slotNum.curr = 0;
(*instPtr)->slotNum.next = 0; (*instPtr)->slotNum.next = 0;
(*instPtr)->frame.last = L2_NONE_FRAME; (*instPtr)->frame.last = L2_FRAME_NONE;
(*instPtr)->frame.curr = L2_NONE_FRAME; (*instPtr)->frame.curr = L2_FRAME_NONE;
(*instPtr)->frame.next = L2_NONE_FRAME; (*instPtr)->frame.next = L2_FRAME_NONE;
(*instPtr)->tor.last = L2_TOR_SUSPEND; (*instPtr)->tor.last = L2_TOR_SUSPEND;
(*instPtr)->tor.curr = L2_TOR_SUSPEND; (*instPtr)->tor.curr = L2_TOR_SUSPEND;
(*instPtr)->tor.next = L2_TOR_SUSPEND; (*instPtr)->tor.next = L2_TOR_SUSPEND;
@@ -547,13 +631,6 @@ int32_t Linklayer_Init(L2_INST **instPtr, const L2_CONFIG *config)
return Status; return Status;
} }
Status = L2_Scan_Init(&((*instPtr)->scanFSM));
if (Status != SUCCESS)
{
Linklayer_Destroy(*instPtr);
return Status;
}
Status = L2_Service_Init(&((*instPtr)->serviceFSM)); Status = L2_Service_Init(&((*instPtr)->serviceFSM));
if (Status != SUCCESS) if (Status != SUCCESS)
{ {
@@ -605,9 +682,9 @@ int32_t Linklayer_Reconfig(L2_INST *instPtr, const L2_CONFIG *config)
instPtr->slotNum.last = 0; instPtr->slotNum.last = 0;
instPtr->slotNum.curr = 0; instPtr->slotNum.curr = 0;
instPtr->slotNum.next = 0; instPtr->slotNum.next = 0;
instPtr->frame.last = L2_NONE_FRAME; instPtr->frame.last = L2_FRAME_NONE;
instPtr->frame.curr = L2_NONE_FRAME; instPtr->frame.curr = L2_FRAME_NONE;
instPtr->frame.next = L2_NONE_FRAME; instPtr->frame.next = L2_FRAME_NONE;
instPtr->tor.last = L2_TOR_SUSPEND; instPtr->tor.last = L2_TOR_SUSPEND;
instPtr->tor.curr = L2_TOR_SUSPEND; instPtr->tor.curr = L2_TOR_SUSPEND;
instPtr->tor.next = L2_TOR_SUSPEND; instPtr->tor.next = L2_TOR_SUSPEND;
@@ -629,7 +706,6 @@ int32_t Linklayer_Reconfig(L2_INST *instPtr, const L2_CONFIG *config)
// Reset according instance // Reset according instance
L2_ClearSchedEventPool(instPtr->schdEventPool); L2_ClearSchedEventPool(instPtr->schdEventPool);
L2_NodeList_Clear(instPtr->nodeList); L2_NodeList_Clear(instPtr->nodeList);
L2_Scan_Reset(instPtr->scanFSM);
L2_Service_Reset(instPtr->serviceFSM); L2_Service_Reset(instPtr->serviceFSM);
return SUCCESS; return SUCCESS;
} }
@@ -654,7 +730,6 @@ void Linklayer_Destroy(L2_INST *instPtr)
// Destroy FSMs and nodeList // Destroy FSMs and nodeList
L2_DestroySchedEventPool(instPtr->schdEventPool); L2_DestroySchedEventPool(instPtr->schdEventPool);
L2_NodeList_Destroy(instPtr->nodeList); L2_NodeList_Destroy(instPtr->nodeList);
L2_Scan_Destroy(instPtr->scanFSM);
L2_Service_Destroy(instPtr->serviceFSM); L2_Service_Destroy(instPtr->serviceFSM);
free(instPtr); free(instPtr);
} }
@@ -671,7 +746,7 @@ void Linklayer_Destroy(L2_INST *instPtr)
int32_t Linklayer_Start(L2_INST *instPtr) int32_t Linklayer_Start(L2_INST *instPtr)
{ {
ASSERT(instPtr != NULL); ASSERT(instPtr != NULL);
// Set netStartTime at first call. // Set netStartTime at first call, i.e. at the beginning of next time unit.
if (instPtr->netStartTime == NET_START_TIME_INFTY) if (instPtr->netStartTime == NET_START_TIME_INFTY)
{ {
instPtr->netStartTime = TimeCtrl_GetIntCnt(instPtr->config.tmcInstPtr) / L2_SLOTS_PER_FRAME + 1; instPtr->netStartTime = TimeCtrl_GetIntCnt(instPtr->config.tmcInstPtr) / L2_SLOTS_PER_FRAME + 1;
@@ -771,7 +846,6 @@ int32_t Linklayer_EventHandler(L2_INST *instPtr, const L2_EVENT *l2Event)
break; break;
} }
DBG_WARNING("Lost connection with head node [%" PRId8 "].\n", L2_GetHeadId(instPtr)); DBG_WARNING("Lost connection with head node [%" PRId8 "].\n", L2_GetHeadId(instPtr));
L2_Scan_Reset(instPtr->scanFSM);
L2_Service_Reset(instPtr->serviceFSM); L2_Service_Reset(instPtr->serviceFSM);
instPtr->cxn2Net = false; instPtr->cxn2Net = false;
UpdateMainSate(instPtr, L2_INIT_STATE); UpdateMainSate(instPtr, L2_INIT_STATE);
@@ -781,7 +855,6 @@ int32_t Linklayer_EventHandler(L2_INST *instPtr, const L2_EVENT *l2Event)
case L2_EV_LOST_NODE: case L2_EV_LOST_NODE:
{ {
DBG_INFO("Event L2_EV_LOST_NODE asserted....\n"); DBG_INFO("Event L2_EV_LOST_NODE asserted....\n");
L2_Scan_Reset(instPtr->scanFSM);
L2_Service_Reset(instPtr->serviceFSM); L2_Service_Reset(instPtr->serviceFSM);
UpdateMainSate(instPtr, L2_INIT_STATE); UpdateMainSate(instPtr, L2_INIT_STATE);
// Log reconnect // Log reconnect
@@ -794,7 +867,6 @@ int32_t Linklayer_EventHandler(L2_INST *instPtr, const L2_EVENT *l2Event)
if (instPtr->nextState == L2_INIT_STATE) if (instPtr->nextState == L2_INIT_STATE)
{ {
// Reset scan net FMS for next scan process. // Reset scan net FMS for next scan process.
L2_Scan_Reset(instPtr->scanFSM);
UpdateMainSate(instPtr, L2_INIT_STATE); UpdateMainSate(instPtr, L2_INIT_STATE);
instPtr->rtneConfig.rtneTable = initTable; instPtr->rtneConfig.rtneTable = initTable;
instPtr->rtneConfig.rtnePrd = ARRAY_SIZE(initTable); instPtr->rtneConfig.rtnePrd = ARRAY_SIZE(initTable);
@@ -851,12 +923,14 @@ int32_t Linklayer_PktHandler(L2_INST *instPtr, L2_FRAME_TYPE frameType)
switch (frameType) switch (frameType)
{ {
case L2_SCAN_FRAME: case L2_FRAME_ADV:
case L2_ADV_FRAME: case L2_FRAME_ACK:
case L2_CFM_FRAME:
Status = L2_Scan_PktHandler(instPtr, instPtr->recvPktData); Status = L2_Scan_PktHandler(instPtr, instPtr->recvPktData);
break; break;
case L2_SVC_FRAME: case L2_FRAME_DIS:
case L2_FRAME_MNG:
case L2_FRAME_RTT:
case L2_FRAME_SVC:
Status = L2_Service_PktHandler(instPtr, instPtr->recvPktData); Status = L2_Service_PktHandler(instPtr, instPtr->recvPktData);
break; break;
default: default:
@@ -923,20 +997,23 @@ static int32_t Linklayer_Routine(L2_INST *instPtr)
instPtr->rtneConfig.curr = instPtr->rtneConfig.next; instPtr->rtneConfig.curr = instPtr->rtneConfig.next;
instPtr->rtneConfig.next = &(instPtr->rtneConfig.rtneTable[tableIndx][entryIndx]); instPtr->rtneConfig.next = &(instPtr->rtneConfig.rtneTable[tableIndx][entryIndx]);
rtneEntry = instPtr->rtneConfig.rtneTable[tableIndx][entryIndx]; rtneEntry = instPtr->rtneConfig.rtneTable[tableIndx][entryIndx];
DBG_INFO("## Routine: %" PRIu32 "-%" PRIu32 ", Routine period: %" PRIu32 ".\n", tableIndx, entryIndx, instPtr->rtneConfig.rtnePrd); DBG_INFO("## Routine: %" PRIu32 "-%" PRIu32 ", Routine period: %" PRIu32 ".\n", tableIndx, entryIndx,
instPtr->rtneConfig.rtnePrd);
switch (rtneEntry.slotType) switch (rtneEntry.slotType)
{ {
case L2_SLOT_IDLE: case L2_SLOT_IDLE:
// Skip a 5ms slot. // Skip a 2 ms slot.
DBG_INFO("Skipping idle slot (5ms)...\n"); DBG_INFO("Skipping idle slot (2 ms)...\n");
Status = SUCCESS; Status = SUCCESS;
break; break;
case L2_SLOT_SCAN:
case L2_SLOT_ADVERTISE: case L2_SLOT_ADVERTISE:
case L2_SLOT_CONFIRM: case L2_SLOT_ACKNOWLEDGE:
Status = L2_Scan_Routine(instPtr, &rtneEntry); Status = L2_Scan_Routine(instPtr, &rtneEntry);
break; break;
case L2_SLOT_DISTRIBUTE:
case L2_SLOT_MANAGE:
case L2_SLOT_RTT:
case L2_SLOT_SERVICE: case L2_SLOT_SERVICE:
Status = L2_Service_Routine(instPtr, &rtneEntry); Status = L2_Service_Routine(instPtr, &rtneEntry);
break; break;
@@ -1021,29 +1098,28 @@ int32_t Linklayer_Proc(L2_INST *instPtr)
// Handle frame received in last slot. // Handle frame received in last slot.
if (L2_isDataAvail(instPtr) == true) if (L2_isDataAvail(instPtr) == true)
{ {
if (Linklayer_PktHandler(instPtr, L2_GetLastOptFrameType(instPtr)) != SUCCESS) if (Linklayer_PktHandler(instPtr, L2_GetLastFrameType(instPtr)) != SUCCESS)
{ {
DBG_ERROR("Failed to handle last received frame: %" PRId8 ".\n", L2_GetLastOptFrameType(instPtr)); DBG_ERROR("Failed to handle last received frame: %" PRId8 ".\n", L2_GetLastFrameType(instPtr));
} }
} }
// Run Link layer routine, setup next slot procedure. // Run Link layer routine, setup next slot procedure.
if (L2_GetNodeType(instPtr) == L2_NODE_HEAD) if (L2_GetNodeType(instPtr) == L2_NODE_HEAD)
{ {
Phy_SetMode(phyRef, PHY_MODE_PULL); Phy_SetMode(phyRef, PHY_MODE_POLL);
Status = Linklayer_Routine(instPtr); Status = Linklayer_Routine(instPtr);
} }
else else
{ // L2_NODE_MEMBER { // L2_NODE_MEMBER
if (L2_isCxn2Net(instPtr)) if (L2_isCxn2Net(instPtr))
{ {
Phy_SetMode(phyRef, PHY_MODE_PULL); Phy_SetMode(phyRef, PHY_MODE_POLL);
Status = Linklayer_Routine(instPtr); Status = Linklayer_Routine(instPtr);
} }
else else
{ {
Phy_SetMode(phyRef, PHY_MODE_LISTEN); Phy_SetMode(phyRef, PHY_MODE_LISTEN);
Status = L2_Scan_Proc(instPtr);
} }
} }
@@ -1064,16 +1140,21 @@ int32_t Linklayer_Proc(L2_INST *instPtr)
instPtr->linkLog.cxnStatus = (L2_isCxn2Net(instPtr)) ? 0x11 : 0x00; instPtr->linkLog.cxnStatus = (L2_isCxn2Net(instPtr)) ? 0x11 : 0x00;
instPtr->linkLog.linkStage = (instPtr->mainState == L2_INIT_STATE) ? 0x11 : 0x22; instPtr->linkLog.linkStage = (instPtr->mainState == L2_INIT_STATE) ? 0x11 : 0x22;
instPtr->linkLog.recxnCnt = instPtr->log.reconnectCnt; instPtr->linkLog.recxnCnt = instPtr->log.reconnectCnt;
instPtr->linkLog.beamNo = instPtr->scanFSM->beamNo;
instPtr->linkLog.beamWidth = instPtr->log.lastBeamWidth;
instPtr->linkLog.beamAz = phyRef->antNrrwPattern[instPtr->scanFSM->beamNo].oaxis;
instPtr->linkLog.beamEl = phyRef->antNrrwPattern[instPtr->scanFSM->beamNo].raxis;
instPtr->linkLog.advTxCnt = (uint16_t)instPtr->log.advTxCnt; instPtr->linkLog.advTxCnt = (uint16_t)instPtr->log.advTxCnt;
instPtr->linkLog.advRecvCnt = (uint16_t)instPtr->log.advRecvCnt; instPtr->linkLog.advRecvCnt = (uint16_t)instPtr->log.advRecvCnt;
instPtr->linkLog.advCorrectCnt = (uint16_t)instPtr->log.advCorrectCnt; instPtr->linkLog.advCorrectCnt = (uint16_t)instPtr->log.advCorrectCnt;
instPtr->linkLog.cfmTxCnt = instPtr->log.cfmTxCnt; instPtr->linkLog.ackTxCnt = instPtr->log.ackTxCnt;
instPtr->linkLog.cfmRecvCnt = instPtr->log.cfmRecvCnt; instPtr->linkLog.ackRecvCnt = instPtr->log.ackRecvCnt;
instPtr->linkLog.cfmCorrectCnt = instPtr->log.cfmCorrectCnt; instPtr->linkLog.ackCorrectCnt = instPtr->log.ackCorrectCnt;
instPtr->linkLog.disTxCnt = instPtr->log.disTxCnt;
instPtr->linkLog.disRecvCnt = instPtr->log.disRecvCnt;
instPtr->linkLog.disCorrectCnt = instPtr->log.disCorrectCnt;
instPtr->linkLog.mngTxCnt = instPtr->log.mngTxCnt;
instPtr->linkLog.mngRecvCnt = instPtr->log.mngRecvCnt;
instPtr->linkLog.mngCorrectCnt = instPtr->log.mngCorrectCnt;
instPtr->linkLog.rttTxCnt = instPtr->log.rttTxCnt;
instPtr->linkLog.rttRecvCnt = instPtr->log.rttRecvCnt;
instPtr->linkLog.rttCorrectCnt = instPtr->log.rttCorrectCnt;
instPtr->linkLog.svcTxCnt = instPtr->log.svcTxCnt; instPtr->linkLog.svcTxCnt = instPtr->log.svcTxCnt;
instPtr->linkLog.svcRecvCnt = instPtr->log.svcRecvCnt; instPtr->linkLog.svcRecvCnt = instPtr->log.svcRecvCnt;
instPtr->linkLog.svcCorrectCnt = instPtr->log.svcCorrectCnt; instPtr->linkLog.svcCorrectCnt = instPtr->log.svcCorrectCnt;
@@ -1086,69 +1167,6 @@ int32_t Linklayer_Proc(L2_INST *instPtr)
return SUCCESS; return SUCCESS;
} }
/*****************************************************************************/
/**
* @brief Steer antenna beam to specified node.
*
* @param instPtr a pointer to link layer descriptor instance
* @param nodeId destination node
*
* @return Corresponding frame length
* L2_FRAME_NONE_LEN if the frame type code cannot be recognized.
*
******************************************************************************/
int32_t L2_SteerBeam2Node(L2_INST *instPtr, uint8_t nodeId)
{
ASSERT(instPtr != NULL);
int32_t Status;
COORD myPos, dstPos, beamDir;
Status = L2_GetNodePos(instPtr->nodeList, nodeId, &dstPos);
if (Status != SUCCESS)
{
DBG_ERROR("Failed to retrieve position info of node %" PRIu8 ", remain last configuration.\n", nodeId);
return EPARAM;
}
myPos.x = instPtr->sysInfo.posX;
myPos.y = instPtr->sysInfo.posY;
myPos.z = instPtr->sysInfo.posZ;
// TODO Check data format
EULERANGLES attitudeEuler, antAttitudeEuler;
attitudeEuler.alpha = DEG2RAD(instPtr->sysInfo.pitch);
attitudeEuler.beta = DEG2RAD(instPtr->sysInfo.yaw);
attitudeEuler.gamma = DEG2RAD(instPtr->sysInfo.roll);
// FIXME: confirm date source.
antAttitudeEuler.alpha = DEG2RAD(0);
antAttitudeEuler.beta = DEG2RAD(0);
antAttitudeEuler.gamma = DEG2RAD(0);
// TODO Check data format
QUATERNION attitude, antAttitude;
attitude = Quaternion_FromeEulerAngles(attitudeEuler, EULERANGLES_XYZ);
antAttitude = Quaternion_FromeEulerAngles(antAttitudeEuler, EULERANGLES_XYZ);
// --- --- Algorithm --- ---
// TODO Check result validation
// Compute beam direction vector
beamDir = Coord_Sub(dstPos, myPos);
// Compute antenna attitude respect to ECEF
antAttitude = Quaternion_Mult(attitude, antAttitude);
// Convert beam direction vector to antenna coordinate
beamDir = Quaternion_Rotate(Quaternion_GeInverse(antAttitude), beamDir);
// Normalize
Coord_Normalize(&beamDir);
double oAxis, rAxis;
oAxis = RAD2DEG(atan2(beamDir.z, beamDir.y));
rAxis = RAD2DEG(acos(Coord_Dot(beamDir, COORD_X_AXIS)));
Status = Phy_SetBeamAngle(instPtr->config.phyInstPtr, oAxis, rAxis);
return Status;
}
/*****************************************************************************/ /*****************************************************************************/
/** /**
* @brief Layer 2 setup next slot operation, update current operating frame. * @brief Layer 2 setup next slot operation, update current operating frame.
@@ -1165,8 +1183,9 @@ int32_t L2_SetupNextSlot(L2_INST *instPtr, L2_TOR_TYPE txrxMode, L2_FRAME_TYPE f
ASSERT(instPtr != NULL); ASSERT(instPtr != NULL);
PHY_INST *phyRef = instPtr->config.phyInstPtr; PHY_INST *phyRef = instPtr->config.phyInstPtr;
int32_t Status; int32_t Status;
if (frameType < L2_SCAN_FRAME || frameType > L2_SVC_FRAME) if (frameType < L2_FRAME_ADV || frameType > L2_FRAME_SVC)
{ {
DBG_WARNING("L2_SetupNextSlot(): UNKNOWN L2-FrameType %" PRId8 "\n", frameType);
return FAILURE; return FAILURE;
} }
@@ -1176,13 +1195,22 @@ int32_t L2_SetupNextSlot(L2_INST *instPtr, L2_TOR_TYPE txrxMode, L2_FRAME_TYPE f
instPtr->log.frameTx++; instPtr->log.frameTx++;
switch (frameType) switch (frameType)
{ {
case L2_ADV_FRAME: case L2_FRAME_ADV:
instPtr->log.advTxCnt++; instPtr->log.advTxCnt++;
break; break;
case L2_CFM_FRAME: case L2_FRAME_ACK:
instPtr->log.cfmTxCnt++; instPtr->log.ackTxCnt++;
break; break;
case L2_SVC_FRAME: case L2_FRAME_DIS:
instPtr->log.disTxCnt++;
break;
case L2_FRAME_MNG:
instPtr->log.mngTxCnt++;
break;
case L2_FRAME_RTT:
instPtr->log.rttTxCnt++;
break;
case L2_FRAME_SVC:
instPtr->log.svcTxCnt++; instPtr->log.svcTxCnt++;
break; break;
default: default:
@@ -1194,13 +1222,22 @@ int32_t L2_SetupNextSlot(L2_INST *instPtr, L2_TOR_TYPE txrxMode, L2_FRAME_TYPE f
instPtr->log.frameRx++; instPtr->log.frameRx++;
switch (frameType) switch (frameType)
{ {
case L2_ADV_FRAME: case L2_FRAME_ADV:
instPtr->log.advRxCnt++; instPtr->log.advRxCnt++;
break; break;
case L2_CFM_FRAME: case L2_FRAME_ACK:
instPtr->log.cfmRxCnt++; instPtr->log.ackRxCnt++;
break; break;
case L2_SVC_FRAME: case L2_FRAME_DIS:
instPtr->log.disRxCnt++;
break;
case L2_FRAME_MNG:
instPtr->log.mngRxCnt++;
break;
case L2_FRAME_RTT:
instPtr->log.rttRxCnt++;
break;
case L2_FRAME_SVC:
instPtr->log.svcRxCnt++; instPtr->log.svcRxCnt++;
break; break;
default: default:
@@ -1225,16 +1262,22 @@ int32_t L2_SetupNextSlot(L2_INST *instPtr, L2_TOR_TYPE txrxMode, L2_FRAME_TYPE f
} }
switch (frameType) switch (frameType)
{ {
case L2_SCAN_FRAME: case L2_FRAME_ADV:
frameStr = "Scan";
break;
case L2_ADV_FRAME:
frameStr = "Advertisement"; frameStr = "Advertisement";
break; break;
case L2_CFM_FRAME: case L2_FRAME_ACK:
frameStr = "Confirm"; frameStr = "Acknowledgement";
break; break;
case L2_SVC_FRAME: case L2_FRAME_DIS:
frameStr = "Distribution";
break;
case L2_FRAME_MNG:
frameStr = "Management";
break;
case L2_FRAME_RTT:
frameStr = "Round Trip Time";
break;
case L2_FRAME_SVC:
frameStr = "Service"; frameStr = "Service";
break; break;
default: default:
@@ -1277,7 +1320,8 @@ int32_t L2_SetupNextSlot(L2_INST *instPtr, L2_TOR_TYPE txrxMode, L2_FRAME_TYPE f
return EPARAM; return EPARAM;
} }
Status = Phy_SetupNextSlot(phyRef, tor, L2_L2frame2L1frame(frameType), instPtr->sendPktData); Status = Phy_SetupNextSlot(phyRef, tor, L2_L2frame2L1frame(frameType,
instPtr->config.serviceRate), instPtr->sendPktData);
if (Status != SUCCESS) if (Status != SUCCESS)
{ {
DBG_ERROR("Physical setup failed, with error code: %" PRId32 "\n", Status); DBG_ERROR("Physical setup failed, with error code: %" PRId32 "\n", Status);
@@ -38,13 +38,14 @@
*/ */
typedef struct typedef struct
{ {
L2_NODE_TYPE myType; ///< node type L2_NODE_TYPE myType; ///< node type
uint8_t clustId; ///< node cluster id uint8_t clustId; ///< node cluster id
uint8_t myId; ///< node id uint8_t myId; ///< node id
uint8_t headId; ///< head node id uint8_t headId; ///< head node id
uint8_t netScale; ///< net scale uint8_t netScale; ///< net scale
PHY_INST *phyInstPtr; ///< pointer to system physical layer instance L2_SVC_RATE serviceRate; ///< service data rate
TMC_INST *tmcInstPtr; ///< pointer to system timer controller layer instance PHY_INST *phyInstPtr; ///< pointer to system physical layer instance
TMC_INST *tmcInstPtr; ///< pointer to system timer controller layer instance
} L2_CONFIG; } L2_CONFIG;
/** /**
@@ -63,10 +64,25 @@ typedef struct
uint32_t advRecvCnt; ///< advertise received frame count uint32_t advRecvCnt; ///< advertise received frame count
uint32_t advCorrectCnt; ///< advertise correctly received frame count uint32_t advCorrectCnt; ///< advertise correctly received frame count
uint32_t cfmRxCnt; ///< confirm rx frame count uint32_t ackRxCnt; ///< acknowledgement rx frame count
uint32_t cfmTxCnt; ///< confirm tx frame count uint32_t ackTxCnt; ///< acknowledgement tx frame count
uint32_t cfmRecvCnt; ///< confirm received frame count uint32_t ackRecvCnt; ///< acknowledgement received frame count
uint32_t cfmCorrectCnt; ///< confirm correctly received frame count uint32_t ackCorrectCnt; ///< acknowledgement correctly received frame count
uint32_t disRxCnt; ///< distribution rx frame count
uint32_t disTxCnt; ///< distribution tx frame count
uint32_t disRecvCnt; ///< distribution received frame count
uint32_t disCorrectCnt;///< distribution correctly received frame count
uint32_t mngRxCnt; ///< management rx frame count
uint32_t mngTxCnt; ///< management tx frame count
uint32_t mngRecvCnt; ///< management received frame count
uint32_t mngCorrectCnt; ///< management correctly received frame count
uint32_t rttRxCnt; ///< rtt rx frame count
uint32_t rttTxCnt; ///< rtt tx frame count
uint32_t rttRecvCnt; ///< rtt received frame count
uint32_t rttCorrectCnt; ///< rtt correctly received frame count
uint32_t svcRxCnt; ///< service rx frame count uint32_t svcRxCnt; ///< service rx frame count
uint32_t svcTxCnt; ///< service tx frame count uint32_t svcTxCnt; ///< service tx frame count
@@ -74,7 +90,6 @@ typedef struct
uint32_t svcCorrectCnt; ///< service correctly received frame count uint32_t svcCorrectCnt; ///< service correctly received frame count
int64_t timeDev; ///< last time deviation estimation result int64_t timeDev; ///< last time deviation estimation result
uint8_t lastBeamWidth; ///< last beam width
uint32_t reconnectCnt; ///< reconnect trial count uint32_t reconnectCnt; ///< reconnect trial count
PAYLOAD rxLog; PAYLOAD rxLog;
@@ -102,7 +117,6 @@ typedef struct
L2_NODE_STATE mainState; ///< the main state of link layer 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_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_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) L2_SVC_FSM *serviceFSM; ///< FSM of service net (data service)
uint8_t *sendPktData; ///< send data buffer uint8_t *sendPktData; ///< send data buffer
uint8_t *recvPktData; ///< received data buffer uint8_t *recvPktData; ///< received data buffer
@@ -128,7 +142,6 @@ int32_t Linklayer_Halt(L2_INST *instPtr);
int32_t Linklayer_Proc(L2_INST *instPtr); int32_t Linklayer_Proc(L2_INST *instPtr);
int32_t Linklayer_EventHandler(L2_INST *instPtr, const L2_EVENT *l2Event); int32_t Linklayer_EventHandler(L2_INST *instPtr, const L2_EVENT *l2Event);
int32_t Linklayer_PktHandler(L2_INST *instPtr, L2_FRAME_TYPE frameType); 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); int32_t L2_SetupNextSlot(L2_INST *instPtr, L2_TOR_TYPE txrxMode, L2_FRAME_TYPE frameType);
/** @} LinkLayer_Main*/ /** @} LinkLayer_Main*/
@@ -139,6 +152,7 @@ int32_t L2_SetupNextSlot(L2_INST *instPtr, L2_TOR_TYPE txrxMode, L2_FRAME_TYPE f
void L2_FrameInsertChunk(uint8_t *frame, size_t offset, size_t bytes, const void *chunk); 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); 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); int32_t L2_CrcAppend(uint8_t *dataBuff, uint32_t dataLen, uint32_t crcPos, L2_CRC_TYPE crcType);
int32_t L2_CrcGen(uint8_t *dataBuff, uint32_t dataLen, L2_CRC_TYPE crcType, uint32_t *crc);
bool L2_CrcCheck(uint8_t *dataBuff, uint32_t dataLen, L2_CRC_TYPE crcType); bool L2_CrcCheck(uint8_t *dataBuff, uint32_t dataLen, L2_CRC_TYPE crcType);
/** @} LinkLayer_Framing*/ /** @} LinkLayer_Framing*/
@@ -157,11 +171,6 @@ int32_t L2_RescheduleEventAfter(L2_INST *instPtr, L2_SCHD_EVENT *schdEvent, uint
* @defgroup LinkLayer_Scan * @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_PktHandler(L2_INST *instPtr, uint8_t *msg);
int32_t L2_Scan_Routine(L2_INST *instPtr, const L2_RTNE_TABLE_ENTRY *schedEntry); int32_t L2_Scan_Routine(L2_INST *instPtr, const L2_RTNE_TABLE_ENTRY *schedEntry);
/** @} LinkLayer_Scan*/ /** @} LinkLayer_Scan*/
@@ -198,7 +207,7 @@ L2_NODE_STATE L2_GetMainState(L2_INST *instPtr);
bool L2_isStarted(L2_INST *instPtr); bool L2_isStarted(L2_INST *instPtr);
bool L2_isDataAvail(L2_INST *instPtr); bool L2_isDataAvail(L2_INST *instPtr);
bool L2_isCxn2Net(L2_INST *instPtr); bool L2_isCxn2Net(L2_INST *instPtr);
uint32_t L2_GetFrameLen(L2_FRAME_TYPE l2FrameType); uint32_t L2_GetFrameLen(L2_FRAME_TYPE l2FrameType, L2_SVC_RATE l2SvcRate);
uint32_t L2_GetLastFrameNum(L2_INST *instPtr); uint32_t L2_GetLastFrameNum(L2_INST *instPtr);
uint32_t L2_GetLastSlotNum(L2_INST *instPtr); uint32_t L2_GetLastSlotNum(L2_INST *instPtr);
L2_FRAME_TYPE L2_GetLastFrameType(L2_INST *instPtr); L2_FRAME_TYPE L2_GetLastFrameType(L2_INST *instPtr);
@@ -211,10 +220,12 @@ uint32_t L2_GetNextFrameNum(L2_INST *instPtr);
uint32_t L2_GetNextSlotNum(L2_INST *instPtr); uint32_t L2_GetNextSlotNum(L2_INST *instPtr);
L2_FRAME_TYPE L2_GetNextFrameType(L2_INST *instPtr); L2_FRAME_TYPE L2_GetNextFrameType(L2_INST *instPtr);
L2_TOR_TYPE L2_GetNextTor(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, L2_SVC_RATE l2SvcRate);
L1_FRAME_TYPE L2_L2frame2L1frame(L2_FRAME_TYPE l2Frame); size_t L2_GetSvcPacketLen(L2_SVC_RATE l2SvcRate);
size_t L2_GetSvcPayloadLen(L2_SVC_RATE l2SvcRate);
PHY_ANT_INDEX L2_AntId2AntIndex(uint8_t antId);
/** @} LinkLayer_Utility*/ /** @} LinkLayer_Utility*/
#endif /* __LINK_LAYER_H_ */ #endif /* __LINK_LAYER_H_ */
/** @} LinkLayer*/ /** @} LinkLayer*/
@@ -33,7 +33,9 @@
* @{ * @{
*/ */
// Common node ID definition // Common node ID definition
#define L2_BROADCAST_ID 0xFF #define L2_BROADCAST_ID1 0xF1 // broadcast
#define L2_BROADCAST_ID2 0xF2
#define L2_BROADCAST_ID3 0xF4
#define L2_NONE_ID 0 #define L2_NONE_ID 0
// Routine configure // Routine configure
@@ -45,15 +47,8 @@
#define L2_FRAMENO_NONE 0 #define L2_FRAMENO_NONE 0
// Common number of slots definition // Common number of slots definition
#define L2_SLOTS_PER_FRAME 100 #define L2_SLOTS_PER_FRAME 250 // 2 ms per slot, 250 slots per time unit
#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*/ /** @} Linklayer_Common_Constants*/
/**************************** Type Definitions *******************************/ /**************************** Type Definitions *******************************/
@@ -113,7 +108,7 @@ typedef struct
uint8_t clustId; ///< node cluster ID uint8_t clustId; ///< node cluster ID
uint8_t headId; ///< cluster head ID uint8_t headId; ///< cluster head ID
L2_NODE_TYPE nodeType; ///< node type L2_NODE_TYPE nodeType; ///< node type
uint8_t beamNo; ///< beam number to this node uint8_t antIndex; ///< antenna number to this node
COORD pos; ///< node position COORD pos; ///< node position
COORD speed; ///< node speed COORD speed; ///< node speed
QUATERNION attitude; ///< node attitude QUATERNION attitude; ///< node attitude
@@ -153,12 +148,14 @@ typedef struct
*/ */
typedef enum typedef enum
{ {
L2_SLOT_NONE = 0, L2_SLOT_NONE = 0,
L2_SLOT_IDLE = 1, L2_SLOT_IDLE = 1,
L2_SLOT_SCAN = 2, L2_SLOT_ADVERTISE = 2,
L2_SLOT_ADVERTISE = 3, L2_SLOT_ACKNOWLEDGE = 3,
L2_SLOT_CONFIRM = 4, L2_SLOT_DISTRIBUTE = 4,
L2_SLOT_SERVICE = 5, L2_SLOT_MANAGE = 5,
L2_SLOT_RTT = 6,
L2_SLOT_SERVICE = 7
} L2_SLOT_TYPE; } L2_SLOT_TYPE;
/** /**
@@ -166,13 +163,26 @@ typedef enum
*/ */
typedef enum typedef enum
{ {
L2_NONE_FRAME = 0, L2_FRAME_NONE = 0,
L2_SCAN_FRAME = 1, L2_FRAME_ADV = 1,
L2_ADV_FRAME = 2, L2_FRAME_ACK = 2,
L2_CFM_FRAME = 3, L2_FRAME_DIS = 3,
L2_SVC_FRAME = 4 L2_FRAME_MNG = 4,
L2_FRAME_RTT = 5,
L2_FRAME_SVC = 6
} L2_FRAME_TYPE; } L2_FRAME_TYPE;
/**
* @enum L2_SVC_RATE
*/
typedef enum
{
L2_SVC_NONE = 0,
L2_SVC_128K = 1, // 128 kbps
L2_SVC_512K = 2, // 512 kbps
L2_SVC_2M = 3 // 2 Mbps
} L2_SVC_RATE;
/** /**
* @enum L2_CRC_TYPE * @enum L2_CRC_TYPE
*/ */
@@ -201,30 +211,10 @@ typedef struct
*/ */
typedef enum typedef enum
{ {
L2_SCAN_NONE_STAGE = 0, L2_SCAN_STAGE_NONE = 0,
L2_SCAN_INIT_STAGE = 1, L2_SCAN_STAGE_ADV = 1
L2_SCAN_ADV_STAGE = 2,
L2_SCAN_CFM_STAGE = 3
} SCAN_STAGE; } 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 * @struct L2_SVC_FSM
* @brief Linklayer service process FSM * @brief Linklayer service process FSM
@@ -23,108 +23,157 @@
#ifndef __L2_MSG_DEF_H_ #ifndef __L2_MSG_DEF_H_
#define __L2_MSG_DEF_H_ #define __L2_MSG_DEF_H_
#define L2_PACK_LEN_MAX 512 // bytes #define L2_PACK_LEN_MAX 2048 // bytes
#define L2_PAYLOAD_LEN_ADV 17
#define L2_PAYLOAD_LEN_ACK 9
#define L2_PAYLOAD_LEN_SVC_128K 42
#define L2_PAYLOAD_LEN_SVC_512K 267
#define L2_PAYLOAD_LEN_SVC_2M 1222
#define L2_MSG_CRC_LEN 1
#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] // [bytes] [name]
// 4 fame number // 1 udu number
// 10 crypto sync word
// 8 message authentication code
// 4 frame number
// 1 slot number // 1 slot number
// 1 source id // 1 source id
// 1 destination id // 1 destination id
// 1 message type // 1 message type
#define L2_MSG_FRAME_NUM 0 #define L2_MSG_UDU_NUM 0
#define L2_MSG_UDU_NUM_LEN 1
#define L2_MSG_SYNC_WORD 1
#define L2_MSG_SYNC_WORD_LEN 10
#define L2_MSG_AUTH_CODE 11
#define L2_MSG_AUTH_CODE_LEN 8
#define L2_MSG_FRAME_NUM 19
#define L2_MSG_FRAME_NUM_LEN 4 #define L2_MSG_FRAME_NUM_LEN 4
#define L2_MSG_SLOT_NUM 4 #define L2_MSG_SLOT_NUM 23
#define L2_MSG_SLOT_NUM_LEN 1 #define L2_MSG_SLOT_NUM_LEN 1
#define L2_MSG_SRC_ID 5 #define L2_MSG_SRC_ID 24
#define L2_MSG_SRC_ID_LEN 1 #define L2_MSG_SRC_ID_LEN 1
#define L2_MSG_DST_ID 6 #define L2_MSG_DST_ID 25
#define L2_MSG_DST_ID_LEN 1 #define L2_MSG_DST_ID_LEN 1
#define L2_MSG_TYPE 7 #define L2_MSG_TYPE 26
#define L2_MSG_TYPE_LEN 1 #define L2_MSG_TYPE_LEN 1
#define L2_MSG_PAYLOAD 8 #define L2_MSG_PAYLOAD 27
// advertisement payload structure: #pragma pack(push, 1) // Force 1-byte alignment
// [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] * @struct L2_MSG_COMMON
// 4 position x * @brief Link layer common message header, 27 byte / 216 bit in total.
// 4 position y */
// 4 position z typedef struct
// 4 speed x {
// 4 speed y uint8_t uduNum; ///< udu (user data unit) number per pdu (packet data unit)
// 4 speed z struct
// 2 crc {
#define L2_MSG_CFM_SRC_POSX 8 uint8_t cryptoSyncWord[10];
#define L2_MSG_CFM_SRC_POSX_LEN 4 uint8_t msgAuthCode[8];
#define L2_MSG_CFM_SRC_POSY 12 } MSG_KEY;
#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: uint32_t frameNum; ///< frame number
// [bytes] [name] uint8_t slotNum; ///< slot number
// 4 position x uint8_t src; ///< source id
// 4 position y uint8_t dst; ///< destination id
// 4 position z uint8_t msgType; ///< message type
// 4 speed x } L2_MSG_COMMON;
// 4 speed y
// 4 speed z /**
// 234 payload * @struct L2_MSG_ADV
// 2 crc * @brief Link layer advertise message definition, 65 byte / 520 bit in total.
#define L2_MSG_SVC_SRC_POSX 8 */
#define L2_MSG_SVC_SRC_POSX_LEN 4 typedef struct
#define L2_MSG_SVC_SRC_POSY 12 {
#define L2_MSG_SVC_SRC_POSY_LEN 4 L2_MSG_COMMON common; ///< common message header
#define L2_MSG_SVC_SRC_POSZ 16 double srcPosX; ///< position x
#define L2_MSG_SVC_SRC_POSZ_LEN 4 double srcPosY; ///< position y
#define L2_MSG_SVC_SRC_SPEEDX 20 double srcPosZ; ///< position z
#define L2_MSG_SVC_SRC_SPEEDX_LEN 4 uint32_t srcNetStatTime;///< net start time
#define L2_MSG_SVC_SRC_SPEEDY 24 uint32_t advDataId; ///< advertise payload id
#define L2_MSG_SVC_SRC_SPEEDY_LEN 4 uint8_t advData[17]; ///< advertise payload data
#define L2_MSG_SVC_SRC_SPEEDZ 28 uint8_t crc; ///< crc
#define L2_MSG_SVC_SRC_SPEEDZ_LEN 4 } L2_MSG_ADV;
#define L2_MSG_SVC_PAYLOAD_ID 32
#define L2_MSG_SVC_PAYLOAD_ID_LEN 4 /**
#define L2_MSG_SVC_PAYLOAD 36 * @struct L2_MSG_ACK
#define L2_MSG_SVC_PAYLOAD_LEN 230 * @brief Link layer acknowledge message definition, 65 byte / 520 bit in total.
#define L2_MSG_SVC_CRC 266 */
#define L2_MSG_SVC_CRC_LEN 2 typedef struct
{
L2_MSG_COMMON common; ///< common message header
double srcPosX; ///< position x
double srcPosY; ///< position y
double srcPosZ; ///< position z
double srcSpeedX; ///< speed x
double srcSpeedY; ///< speed y
double srcSpeedZ; ///< speed z
uint32_t ackDataId; ///< acknowledge payload id
uint8_t ackData[9]; ///< acknowledge payload data
uint8_t crc; ///< crc
} L2_MSG_ACK;
/**
* @struct L2_MSG_SVC_128K
* @brief Link layer 128 kbps service message definition, 98 byte / 784 bit in total.
*/
typedef struct
{
L2_MSG_COMMON common; ///< common message header
double srcPosX; ///< position x
double srcPosY; ///< position y
double srcPosZ; ///< position z
double srcSpeedX; ///< speed x
double srcSpeedY; ///< speed y
double srcSpeedZ; ///< speed z
uint32_t svcDataId; ///< service payload id
uint8_t svcData[42]; ///< service payload data
uint8_t crc; ///< crc
} L2_MSG_SVC_128K;
/**
* @struct L2_MSG_SVC_512K
* @brief Link layer 512 kbps service message definition, 323 byte / 2584 bit in total.
*/
typedef struct
{
L2_MSG_COMMON common; ///< common message header
double srcPosX; ///< position x
double srcPosY; ///< position y
double srcPosZ; ///< position z
double srcSpeedX; ///< speed x
double srcSpeedY; ///< speed y
double srcSpeedZ; ///< speed z
uint32_t svcDataId; ///< service payload id
uint8_t svcData[267]; ///< service payload data
uint8_t crc; ///< crc
} L2_MSG_SVC_512K;
/**
* @struct L2_MSG_SVC_2M
* @brief Link layer 2 Mbps service message definition, 1278 byte / 10224 bit in total.
*/
typedef struct
{
L2_MSG_COMMON common; ///< common message header
double srcPosX; ///< position x
double srcPosY; ///< position y
double srcPosZ; ///< position z
double srcSpeedX; ///< speed x
double srcSpeedY; ///< speed y
double srcSpeedZ; ///< speed z
uint32_t svcDataId; ///< service payload id
uint8_t svcData[1222]; ///< service payload data
uint8_t crc; ///< crc
} L2_MSG_SVC_2M;
#pragma pack(pop) // Restore original packing
#endif //__L2_MSG_DEF_H_ #endif //__L2_MSG_DEF_H_
/** @} LinkLayer_MSG_Constants*/ /** @} LinkLayer_MSG_Constants*/
/** @} LinkLayer*/ /** @} LinkLayer*/
@@ -140,7 +140,8 @@ void L2_NodeList_Destroy(NODE_LIST *list)
NODE_ENTRY *L2_GetNodeById(NODE_LIST *list, uint8_t nodeId) NODE_ENTRY *L2_GetNodeById(NODE_LIST *list, uint8_t nodeId)
{ {
ASSERT(list != NULL); ASSERT(list != NULL);
if (nodeId == L2_BROADCAST_ID || nodeId == L2_NONE_ID) if (nodeId == L2_BROADCAST_ID1 || nodeId == L2_BROADCAST_ID2 ||
nodeId == L2_BROADCAST_ID3 || nodeId == L2_NONE_ID)
{ {
return NULL; return NULL;
} }
@@ -198,7 +199,7 @@ NODE_ENTRY *L2_AppendNode(NODE_LIST *list, uint8_t nodeId, L2_NODE_TYPE nodeType
nodeEntry->nodeInfo.speed.x = 0; nodeEntry->nodeInfo.speed.x = 0;
nodeEntry->nodeInfo.speed.y = 0; nodeEntry->nodeInfo.speed.y = 0;
nodeEntry->nodeInfo.speed.z = 0; nodeEntry->nodeInfo.speed.z = 0;
nodeEntry->nodeInfo.beamNo = 0; nodeEntry->nodeInfo.antIndex = 0;
nodeEntry->ttlCnt = 0; nodeEntry->ttlCnt = 0;
clist_rpush(list, node); clist_rpush(list, node);
return nodeEntry; return nodeEntry;
@@ -558,4 +559,4 @@ int32_t L2_IterDeleteNode(NODE_LIST *list, bool (*condition)(NODE_ENTRY *))
/** @} LinkLayer_NodeList*/ /** @} LinkLayer_NodeList*/
/** @} LinkLayer*/ /** @} LinkLayer*/
@@ -25,238 +25,289 @@
#include "link_layer.h" #include "link_layer.h"
#include "link_layer_types.h" #include "link_layer_types.h"
L2_RTNE_TABLE_ENTRY intraScanSubT[L2_SLOTS_PER_FRAME] = { L2_RTNE_TABLE_ENTRY innerScanSubT[L2_SLOTS_PER_FRAME] =
// SubFrame 0 {
{L2_SLOT_SCAN, 0x00, 0x01, 0xFF}, // 36 slots: advertise of antenna-1 ~ antenna-3
{L2_SLOT_SCAN, 0x01, 0x01, 0xFF}, // 12 slots: idle for no antenna-4
{L2_SLOT_SCAN, 0x00, 0x01, 0xFF}, // 2 slots: service slot, set to idle
{L2_SLOT_SCAN, 0x01, 0x01, 0xFF}, {L2_SLOT_ADVERTISE, 0x00, 0x01, L2_BROADCAST_ID1},
{L2_SLOT_SCAN, 0x00, 0x01, 0xFF}, {L2_SLOT_ADVERTISE, 0x01, 0x01, L2_BROADCAST_ID1},
{L2_SLOT_SCAN, 0x01, 0x01, 0xFF}, {L2_SLOT_ADVERTISE, 0x02, 0x01, L2_BROADCAST_ID1},
{L2_SLOT_SCAN, 0x00, 0x01, 0xFF}, {L2_SLOT_ADVERTISE, 0x03, 0x01, L2_BROADCAST_ID1},
{L2_SLOT_SCAN, 0x01, 0x01, 0xFF}, {L2_SLOT_ADVERTISE, 0x04, 0x01, L2_BROADCAST_ID1},
{L2_SLOT_SCAN, 0x00, 0x01, 0xFF}, {L2_SLOT_ADVERTISE, 0x05, 0x01, L2_BROADCAST_ID1},
{L2_SLOT_SCAN, 0x01, 0x01, 0xFF}, {L2_SLOT_ADVERTISE, 0x06, 0x01, L2_BROADCAST_ID1},
{L2_SLOT_SCAN, 0x00, 0x01, 0xFF}, {L2_SLOT_ADVERTISE, 0x07, 0x01, L2_BROADCAST_ID1},
{L2_SLOT_SCAN, 0x01, 0x01, 0xFF}, {L2_SLOT_ADVERTISE, 0x08, 0x01, L2_BROADCAST_ID1},
{L2_SLOT_SCAN, 0x00, 0x01, 0xFF}, {L2_SLOT_ADVERTISE, 0x09, 0x01, L2_BROADCAST_ID1},
{L2_SLOT_SCAN, 0x01, 0x01, 0xFF}, {L2_SLOT_ADVERTISE, 0x0A, 0x01, L2_BROADCAST_ID1},
{L2_SLOT_SCAN, 0x00, 0x01, 0xFF}, {L2_SLOT_ADVERTISE, 0x0B, 0x01, L2_BROADCAST_ID1},
{L2_SLOT_SCAN, 0x01, 0x01, 0xFF}, {L2_SLOT_ADVERTISE, 0x00, 0x01, L2_BROADCAST_ID2},
{L2_SLOT_SCAN, 0x00, 0x01, 0xFF}, {L2_SLOT_ADVERTISE, 0x01, 0x01, L2_BROADCAST_ID2},
{L2_SLOT_SCAN, 0x01, 0x01, 0xFF}, {L2_SLOT_ADVERTISE, 0x02, 0x01, L2_BROADCAST_ID2},
{L2_SLOT_SCAN, 0x00, 0x01, 0xFF}, {L2_SLOT_ADVERTISE, 0x03, 0x01, L2_BROADCAST_ID2},
{L2_SLOT_SCAN, 0x01, 0x01, 0xFF}, {L2_SLOT_ADVERTISE, 0x04, 0x01, L2_BROADCAST_ID2},
{L2_SLOT_ADVERTISE, 0x05, 0x01, L2_BROADCAST_ID2},
// SubFrame 1 {L2_SLOT_ADVERTISE, 0x06, 0x01, L2_BROADCAST_ID2},
{L2_SLOT_SCAN, 0x00, 0x01, 0xFF}, {L2_SLOT_ADVERTISE, 0x07, 0x01, L2_BROADCAST_ID2},
{L2_SLOT_SCAN, 0x01, 0x01, 0xFF}, {L2_SLOT_ADVERTISE, 0x08, 0x01, L2_BROADCAST_ID2},
{L2_SLOT_SCAN, 0x00, 0x01, 0xFF}, {L2_SLOT_ADVERTISE, 0x09, 0x01, L2_BROADCAST_ID2},
{L2_SLOT_SCAN, 0x01, 0x01, 0xFF}, {L2_SLOT_ADVERTISE, 0x0A, 0x01, L2_BROADCAST_ID2},
{L2_SLOT_SCAN, 0x00, 0x01, 0xFF}, {L2_SLOT_ADVERTISE, 0x0B, 0x01, L2_BROADCAST_ID2},
{L2_SLOT_SCAN, 0x01, 0x01, 0xFF}, {L2_SLOT_ADVERTISE, 0x00, 0x01, L2_BROADCAST_ID3},
{L2_SLOT_SCAN, 0x00, 0x01, 0xFF}, {L2_SLOT_ADVERTISE, 0x01, 0x01, L2_BROADCAST_ID3},
{L2_SLOT_SCAN, 0x01, 0x01, 0xFF}, {L2_SLOT_ADVERTISE, 0x02, 0x01, L2_BROADCAST_ID3},
{L2_SLOT_SCAN, 0x00, 0x01, 0xFF}, {L2_SLOT_ADVERTISE, 0x03, 0x01, L2_BROADCAST_ID3},
{L2_SLOT_SCAN, 0x01, 0x01, 0xFF}, {L2_SLOT_ADVERTISE, 0x04, 0x01, L2_BROADCAST_ID3},
{L2_SLOT_SCAN, 0x00, 0x01, 0xFF}, {L2_SLOT_ADVERTISE, 0x05, 0x01, L2_BROADCAST_ID3},
{L2_SLOT_SCAN, 0x01, 0x01, 0xFF}, {L2_SLOT_ADVERTISE, 0x06, 0x01, L2_BROADCAST_ID3},
{L2_SLOT_SCAN, 0x00, 0x01, 0xFF}, {L2_SLOT_ADVERTISE, 0x07, 0x01, L2_BROADCAST_ID3},
{L2_SLOT_SCAN, 0x01, 0x01, 0xFF}, {L2_SLOT_ADVERTISE, 0x08, 0x01, L2_BROADCAST_ID3},
{L2_SLOT_SCAN, 0x00, 0x01, 0xFF}, {L2_SLOT_ADVERTISE, 0x09, 0x01, L2_BROADCAST_ID3},
{L2_SLOT_SCAN, 0x01, 0x01, 0xFF}, {L2_SLOT_ADVERTISE, 0x0A, 0x01, L2_BROADCAST_ID3},
{L2_SLOT_SCAN, 0x00, 0x01, 0xFF}, {L2_SLOT_ADVERTISE, 0x0B, 0x01, L2_BROADCAST_ID3},
{L2_SLOT_SCAN, 0x01, 0x01, 0xFF}, {L2_SLOT_IDLE, 0x00, 0x00, 0x00},
{L2_SLOT_SCAN, 0x00, 0x01, 0xFF}, {L2_SLOT_IDLE, 0x00, 0x00, 0x00},
{L2_SLOT_SCAN, 0x01, 0x01, 0xFF}, {L2_SLOT_IDLE, 0x00, 0x00, 0x00},
{L2_SLOT_IDLE, 0x00, 0x00, 0x00},
// SubFrame 2 {L2_SLOT_IDLE, 0x00, 0x00, 0x00},
{L2_SLOT_SCAN, 0x00, 0x01, 0xFF}, {L2_SLOT_IDLE, 0x00, 0x00, 0x00},
{L2_SLOT_SCAN, 0x01, 0x01, 0xFF}, {L2_SLOT_IDLE, 0x00, 0x00, 0x00},
{L2_SLOT_SCAN, 0x00, 0x01, 0xFF}, {L2_SLOT_IDLE, 0x00, 0x00, 0x00},
{L2_SLOT_SCAN, 0x01, 0x01, 0xFF}, {L2_SLOT_IDLE, 0x00, 0x00, 0x00},
{L2_SLOT_SCAN, 0x00, 0x01, 0xFF}, {L2_SLOT_IDLE, 0x00, 0x00, 0x00},
{L2_SLOT_SCAN, 0x01, 0x01, 0xFF}, {L2_SLOT_IDLE, 0x00, 0x00, 0x00},
{L2_SLOT_SCAN, 0x00, 0x01, 0xFF}, {L2_SLOT_IDLE, 0x00, 0x00, 0x00},
{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 3
{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},
{L2_SLOT_IDLE, 0x00, 0x00, 0x00}, {L2_SLOT_IDLE, 0x00, 0x00, 0x00},
// SubFrame 4 // 36 slots: acknowledge of member nodes
{L2_SLOT_CONFIRM, 0x00, 0x01, 0xFF}, // 14 slots: service
{L2_SLOT_CONFIRM, 0x01, 0x01, 0xFF}, {L2_SLOT_ACKNOWLEDGE, 0x00, 0x02, 0x01},
{L2_SLOT_CONFIRM, 0x02, 0x01, 0xFF}, {L2_SLOT_ACKNOWLEDGE, 0x01, 0x02, 0x01},
{L2_SLOT_CONFIRM, 0x03, 0x01, 0xFF}, {L2_SLOT_ACKNOWLEDGE, 0x02, 0x02, 0x01},
{L2_SLOT_IDLE, 0x00, 0x00, 0x00}, {L2_SLOT_ACKNOWLEDGE, 0x03, 0x02, 0x01},
{L2_SLOT_CONFIRM, 0x00, 0x01, 0xFF}, {L2_SLOT_ACKNOWLEDGE, 0x00, 0x03, 0x01},
{L2_SLOT_CONFIRM, 0x01, 0x01, 0xFF}, {L2_SLOT_ACKNOWLEDGE, 0x01, 0x03, 0x01},
{L2_SLOT_CONFIRM, 0x02, 0x01, 0xFF}, {L2_SLOT_ACKNOWLEDGE, 0x02, 0x03, 0x01},
{L2_SLOT_CONFIRM, 0x03, 0x01, 0xFF}, {L2_SLOT_ACKNOWLEDGE, 0x03, 0x03, 0x01},
{L2_SLOT_IDLE, 0x00, 0x00, 0x00}, {L2_SLOT_ACKNOWLEDGE, 0x00, 0x04, 0x01},
{L2_SLOT_CONFIRM, 0x00, 0xFF, 0x01}, {L2_SLOT_ACKNOWLEDGE, 0x01, 0x04, 0x01},
{L2_SLOT_CONFIRM, 0x01, 0xFF, 0x01}, {L2_SLOT_ACKNOWLEDGE, 0x02, 0x04, 0x01},
{L2_SLOT_CONFIRM, 0x02, 0xFF, 0x01}, {L2_SLOT_ACKNOWLEDGE, 0x03, 0x04, 0x01},
{L2_SLOT_CONFIRM, 0x03, 0xFF, 0x01}, {L2_SLOT_ACKNOWLEDGE, 0x00, 0x05, 0x01},
{L2_SLOT_IDLE, 0x00, 0x00, 0x00}, {L2_SLOT_ACKNOWLEDGE, 0x01, 0x05, 0x01},
{L2_SLOT_CONFIRM, 0x00, 0xFF, 0x01}, {L2_SLOT_ACKNOWLEDGE, 0x02, 0x05, 0x01},
{L2_SLOT_CONFIRM, 0x01, 0xFF, 0x01}, {L2_SLOT_ACKNOWLEDGE, 0x03, 0x05, 0x01},
{L2_SLOT_CONFIRM, 0x02, 0xFF, 0x01}, {L2_SLOT_ACKNOWLEDGE, 0x00, 0x06, 0x01},
{L2_SLOT_CONFIRM, 0x03, 0xFF, 0x01}, {L2_SLOT_ACKNOWLEDGE, 0x01, 0x06, 0x01},
{L2_SLOT_IDLE, 0x00, 0x00, 0x00}, {L2_SLOT_ACKNOWLEDGE, 0x02, 0x06, 0x01},
}; {L2_SLOT_ACKNOWLEDGE, 0x03, 0x06, 0x01},
{L2_SLOT_ACKNOWLEDGE, 0x00, 0x07, 0x01},
{L2_SLOT_ACKNOWLEDGE, 0x01, 0x07, 0x01},
{L2_SLOT_ACKNOWLEDGE, 0x02, 0x07, 0x01},
{L2_SLOT_ACKNOWLEDGE, 0x03, 0x07, 0x01},
{L2_SLOT_ACKNOWLEDGE, 0x00, 0x08, 0x01},
{L2_SLOT_ACKNOWLEDGE, 0x01, 0x08, 0x01},
{L2_SLOT_ACKNOWLEDGE, 0x02, 0x08, 0x01},
{L2_SLOT_ACKNOWLEDGE, 0x03, 0x08, 0x01},
{L2_SLOT_ACKNOWLEDGE, 0x00, 0x09, 0x01},
{L2_SLOT_ACKNOWLEDGE, 0x01, 0x09, 0x01},
{L2_SLOT_ACKNOWLEDGE, 0x02, 0x09, 0x01},
{L2_SLOT_ACKNOWLEDGE, 0x03, 0x09, 0x01},
{L2_SLOT_ACKNOWLEDGE, 0x00, 0x0A, 0x01},
{L2_SLOT_ACKNOWLEDGE, 0x01, 0x0A, 0x01},
{L2_SLOT_ACKNOWLEDGE, 0x02, 0x0A, 0x01},
{L2_SLOT_ACKNOWLEDGE, 0x03, 0x0A, 0x01},
{L2_SLOT_SERVICE, 0x00, 0x01, 0x02},
{L2_SLOT_SERVICE, 0x01, 0x01, 0x02},
{L2_SLOT_SERVICE, 0x00, 0x01, 0x03},
{L2_SLOT_SERVICE, 0x01, 0x01, 0x03},
{L2_SLOT_SERVICE, 0x00, 0x01, 0x04},
{L2_SLOT_SERVICE, 0x01, 0x01, 0x04},
{L2_SLOT_SERVICE, 0x00, 0x01, 0x05},
{L2_SLOT_SERVICE, 0x01, 0x01, 0x05},
{L2_SLOT_SERVICE, 0x00, 0x01, 0x06},
{L2_SLOT_SERVICE, 0x01, 0x01, 0x06},
{L2_SLOT_SERVICE, 0x00, 0x01, 0x07},
{L2_SLOT_SERVICE, 0x01, 0x01, 0x07},
{L2_SLOT_SERVICE, 0x00, 0x01, 0x08},
{L2_SLOT_SERVICE, 0x01, 0x01, 0x08},
L2_RTNE_TABLE_ENTRY normalSub[L2_SLOTS_PER_FRAME] = { // 12 slots: network management, head <--> node
// SubFrame 0 // 18 slots: message distribution, head ---> node
{L2_SLOT_SERVICE, 0x00, 0x01, 0x02}, // 12 slots: rtt, head <--> node
{L2_SLOT_SERVICE, 0x01, 0x01, 0x02}, // 8 slots: service
{L2_SLOT_SERVICE, 0x02, 0x01, 0x02}, {L2_SLOT_MANAGE, 0x00, 0x01, 0x02},
{L2_SLOT_SERVICE, 0x03, 0x01, 0x02}, {L2_SLOT_MANAGE, 0x01, 0x01, 0x02},
{L2_SLOT_IDLE, 0x00, 0x00, 0x00}, {L2_SLOT_MANAGE, 0x00, 0x01, 0x03},
{L2_SLOT_MANAGE, 0x01, 0x01, 0x03},
{L2_SLOT_MANAGE, 0x00, 0x01, 0x04},
{L2_SLOT_MANAGE, 0x01, 0x01, 0x04},
{L2_SLOT_MANAGE, 0x00, 0x02, 0x01},
{L2_SLOT_MANAGE, 0x01, 0x02, 0x01},
{L2_SLOT_MANAGE, 0x00, 0x03, 0x01},
{L2_SLOT_MANAGE, 0x01, 0x03, 0x01},
{L2_SLOT_MANAGE, 0x00, 0x04, 0x01},
{L2_SLOT_MANAGE, 0x01, 0x04, 0x01},
{L2_SLOT_DISTRIBUTE, 0x00, 0x01, 0x02},
{L2_SLOT_DISTRIBUTE, 0x01, 0x01, 0x02},
{L2_SLOT_DISTRIBUTE, 0x00, 0x01, 0x03},
{L2_SLOT_DISTRIBUTE, 0x01, 0x01, 0x03},
{L2_SLOT_DISTRIBUTE, 0x00, 0x01, 0x04},
{L2_SLOT_DISTRIBUTE, 0x01, 0x01, 0x04},
{L2_SLOT_DISTRIBUTE, 0x00, 0x01, 0x05},
{L2_SLOT_DISTRIBUTE, 0x01, 0x01, 0x05},
{L2_SLOT_DISTRIBUTE, 0x00, 0x01, 0x06},
{L2_SLOT_DISTRIBUTE, 0x01, 0x01, 0x06},
{L2_SLOT_DISTRIBUTE, 0x00, 0x01, 0x07},
{L2_SLOT_DISTRIBUTE, 0x01, 0x01, 0x07},
{L2_SLOT_DISTRIBUTE, 0x00, 0x01, 0x08},
{L2_SLOT_DISTRIBUTE, 0x01, 0x01, 0x08},
{L2_SLOT_DISTRIBUTE, 0x00, 0x01, 0x09},
{L2_SLOT_DISTRIBUTE, 0x01, 0x01, 0x09},
{L2_SLOT_DISTRIBUTE, 0x00, 0x01, 0x0A},
{L2_SLOT_DISTRIBUTE, 0x01, 0x01, 0x0A},
{L2_SLOT_RTT, 0x00, 0x01, 0x02},
{L2_SLOT_RTT, 0x01, 0x01, 0x02},
{L2_SLOT_RTT, 0x00, 0x01, 0x03},
{L2_SLOT_RTT, 0x01, 0x01, 0x03},
{L2_SLOT_RTT, 0x00, 0x01, 0x04},
{L2_SLOT_RTT, 0x01, 0x01, 0x04},
{L2_SLOT_RTT, 0x00, 0x02, 0x01},
{L2_SLOT_RTT, 0x01, 0x02, 0x01},
{L2_SLOT_RTT, 0x00, 0x03, 0x01},
{L2_SLOT_RTT, 0x01, 0x03, 0x01},
{L2_SLOT_RTT, 0x00, 0x04, 0x01},
{L2_SLOT_RTT, 0x01, 0x04, 0x01},
{L2_SLOT_SERVICE, 0x00, 0x01, 0x09},
{L2_SLOT_SERVICE, 0x01, 0x01, 0x09},
{L2_SLOT_SERVICE, 0x00, 0x01, 0x0A},
{L2_SLOT_SERVICE, 0x01, 0x01, 0x0A},
{L2_SLOT_SERVICE, 0x00, 0x01, 0x0B},
{L2_SLOT_SERVICE, 0x01, 0x01, 0x0B},
{L2_SLOT_SERVICE, 0x00, 0x02, 0x01}, {L2_SLOT_SERVICE, 0x00, 0x02, 0x01},
{L2_SLOT_SERVICE, 0x01, 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, 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},
// SubFrame 1 // 12 slots: network management, head <--> node
{L2_SLOT_SERVICE, 0x00, 0x01, 0x02}, // 18 slots: message distribution, head ---> node
{L2_SLOT_SERVICE, 0x01, 0x01, 0x02}, // 12 slots: rtt, head <--> node
{L2_SLOT_SERVICE, 0x02, 0x01, 0x02}, // 8 slots: service
{L2_SLOT_SERVICE, 0x03, 0x01, 0x02}, {L2_SLOT_MANAGE, 0x00, 0x01, 0x05},
{L2_SLOT_IDLE, 0x00, 0x00, 0x00}, {L2_SLOT_MANAGE, 0x01, 0x01, 0x05},
{L2_SLOT_SERVICE, 0x00, 0x02, 0x01}, {L2_SLOT_MANAGE, 0x00, 0x01, 0x06},
{L2_SLOT_SERVICE, 0x01, 0x02, 0x01}, {L2_SLOT_MANAGE, 0x01, 0x01, 0x06},
{L2_SLOT_SERVICE, 0x02, 0x02, 0x01}, {L2_SLOT_MANAGE, 0x00, 0x01, 0x07},
{L2_SLOT_SERVICE, 0x03, 0x02, 0x01}, {L2_SLOT_MANAGE, 0x01, 0x01, 0x07},
{L2_SLOT_IDLE, 0x00, 0x00, 0x00}, {L2_SLOT_MANAGE, 0x00, 0x05, 0x01},
{L2_SLOT_SERVICE, 0x00, 0x01, 0x02}, {L2_SLOT_MANAGE, 0x01, 0x05, 0x01},
{L2_SLOT_SERVICE, 0x01, 0x01, 0x02}, {L2_SLOT_MANAGE, 0x00, 0x06, 0x01},
{L2_SLOT_SERVICE, 0x02, 0x01, 0x02}, {L2_SLOT_MANAGE, 0x01, 0x06, 0x01},
{L2_SLOT_SERVICE, 0x03, 0x01, 0x02}, {L2_SLOT_MANAGE, 0x00, 0x07, 0x01},
{L2_SLOT_IDLE, 0x00, 0x00, 0x00}, {L2_SLOT_MANAGE, 0x01, 0x07, 0x01},
{L2_SLOT_SERVICE, 0x00, 0x02, 0x01}, {L2_SLOT_DISTRIBUTE, 0x00, 0x01, 0x02},
{L2_SLOT_SERVICE, 0x01, 0x02, 0x01}, {L2_SLOT_DISTRIBUTE, 0x01, 0x01, 0x02},
{L2_SLOT_SERVICE, 0x02, 0x02, 0x01}, {L2_SLOT_DISTRIBUTE, 0x00, 0x01, 0x03},
{L2_SLOT_SERVICE, 0x03, 0x02, 0x01}, {L2_SLOT_DISTRIBUTE, 0x01, 0x01, 0x03},
{L2_SLOT_IDLE, 0x00, 0x00, 0x00}, {L2_SLOT_DISTRIBUTE, 0x00, 0x01, 0x04},
{L2_SLOT_DISTRIBUTE, 0x01, 0x01, 0x04},
{L2_SLOT_DISTRIBUTE, 0x00, 0x01, 0x05},
{L2_SLOT_DISTRIBUTE, 0x01, 0x01, 0x05},
{L2_SLOT_DISTRIBUTE, 0x00, 0x01, 0x06},
{L2_SLOT_DISTRIBUTE, 0x01, 0x01, 0x06},
{L2_SLOT_DISTRIBUTE, 0x00, 0x01, 0x07},
{L2_SLOT_DISTRIBUTE, 0x01, 0x01, 0x07},
{L2_SLOT_DISTRIBUTE, 0x00, 0x01, 0x08},
{L2_SLOT_DISTRIBUTE, 0x01, 0x01, 0x08},
{L2_SLOT_DISTRIBUTE, 0x00, 0x01, 0x09},
{L2_SLOT_DISTRIBUTE, 0x01, 0x01, 0x09},
{L2_SLOT_DISTRIBUTE, 0x00, 0x01, 0x0A},
{L2_SLOT_DISTRIBUTE, 0x01, 0x01, 0x0A},
{L2_SLOT_RTT, 0x00, 0x01, 0x05},
{L2_SLOT_RTT, 0x01, 0x01, 0x05},
{L2_SLOT_RTT, 0x00, 0x01, 0x06},
{L2_SLOT_RTT, 0x01, 0x01, 0x06},
{L2_SLOT_RTT, 0x00, 0x01, 0x07},
{L2_SLOT_RTT, 0x01, 0x01, 0x07},
{L2_SLOT_RTT, 0x00, 0x05, 0x01},
{L2_SLOT_RTT, 0x01, 0x05, 0x01},
{L2_SLOT_RTT, 0x00, 0x06, 0x01},
{L2_SLOT_RTT, 0x01, 0x06, 0x01},
{L2_SLOT_RTT, 0x00, 0x07, 0x01},
{L2_SLOT_RTT, 0x01, 0x07, 0x01},
{L2_SLOT_SERVICE, 0x00, 0x03, 0x01},
{L2_SLOT_SERVICE, 0x01, 0x03, 0x01},
{L2_SLOT_SERVICE, 0x00, 0x04, 0x01},
{L2_SLOT_SERVICE, 0x01, 0x04, 0x01},
{L2_SLOT_SERVICE, 0x00, 0x05, 0x01},
{L2_SLOT_SERVICE, 0x01, 0x05, 0x01},
{L2_SLOT_SERVICE, 0x00, 0x06, 0x01},
{L2_SLOT_SERVICE, 0x01, 0x06, 0x01},
// SubFrame 2 // 12 slots: network management, head <--> node
{L2_SLOT_SERVICE, 0x00, 0x01, 0x02}, // 18 slots: message distribution, head ---> node
{L2_SLOT_SERVICE, 0x01, 0x01, 0x02}, // 12 slots: rtt, head <--> node
{L2_SLOT_SERVICE, 0x02, 0x01, 0x02}, // 8 slots: service, with one slot idle
{L2_SLOT_SERVICE, 0x03, 0x01, 0x02}, {L2_SLOT_MANAGE, 0x00, 0x01, 0x08},
{L2_SLOT_IDLE, 0x00, 0x00, 0x00}, {L2_SLOT_MANAGE, 0x01, 0x01, 0x08},
{L2_SLOT_SERVICE, 0x00, 0x02, 0x01}, {L2_SLOT_MANAGE, 0x00, 0x01, 0x09},
{L2_SLOT_SERVICE, 0x01, 0x02, 0x01}, {L2_SLOT_MANAGE, 0x01, 0x01, 0x09},
{L2_SLOT_SERVICE, 0x02, 0x02, 0x01}, {L2_SLOT_MANAGE, 0x00, 0x01, 0x0A},
{L2_SLOT_SERVICE, 0x03, 0x02, 0x01}, {L2_SLOT_MANAGE, 0x01, 0x01, 0x0A},
{L2_SLOT_IDLE, 0x00, 0x00, 0x00}, {L2_SLOT_MANAGE, 0x00, 0x08, 0x01},
{L2_SLOT_SERVICE, 0x00, 0x01, 0x02}, {L2_SLOT_MANAGE, 0x01, 0x08, 0x01},
{L2_SLOT_SERVICE, 0x01, 0x01, 0x02}, {L2_SLOT_MANAGE, 0x00, 0x09, 0x01},
{L2_SLOT_SERVICE, 0x02, 0x01, 0x02}, {L2_SLOT_MANAGE, 0x01, 0x09, 0x01},
{L2_SLOT_SERVICE, 0x03, 0x01, 0x02}, {L2_SLOT_MANAGE, 0x00, 0x0A, 0x01},
{L2_SLOT_IDLE, 0x00, 0x00, 0x00}, {L2_SLOT_MANAGE, 0x01, 0x0A, 0x01},
{L2_SLOT_SERVICE, 0x00, 0x02, 0x01}, {L2_SLOT_DISTRIBUTE, 0x00, 0x01, 0x02},
{L2_SLOT_SERVICE, 0x01, 0x02, 0x01}, {L2_SLOT_DISTRIBUTE, 0x01, 0x01, 0x02},
{L2_SLOT_SERVICE, 0x02, 0x02, 0x01}, {L2_SLOT_DISTRIBUTE, 0x00, 0x01, 0x03},
{L2_SLOT_SERVICE, 0x03, 0x02, 0x01}, {L2_SLOT_DISTRIBUTE, 0x01, 0x01, 0x03},
{L2_SLOT_IDLE, 0x00, 0x00, 0x00}, {L2_SLOT_DISTRIBUTE, 0x00, 0x01, 0x04},
{L2_SLOT_DISTRIBUTE, 0x01, 0x01, 0x04},
// SubFrame 3 {L2_SLOT_DISTRIBUTE, 0x00, 0x01, 0x05},
{L2_SLOT_SERVICE, 0x00, 0x01, 0x02}, {L2_SLOT_DISTRIBUTE, 0x01, 0x01, 0x05},
{L2_SLOT_SERVICE, 0x01, 0x01, 0x02}, {L2_SLOT_DISTRIBUTE, 0x00, 0x01, 0x06},
{L2_SLOT_SERVICE, 0x02, 0x01, 0x02}, {L2_SLOT_DISTRIBUTE, 0x01, 0x01, 0x06},
{L2_SLOT_SERVICE, 0x03, 0x01, 0x02}, {L2_SLOT_DISTRIBUTE, 0x00, 0x01, 0x07},
{L2_SLOT_IDLE, 0x00, 0x00, 0x00}, {L2_SLOT_DISTRIBUTE, 0x01, 0x01, 0x07},
{L2_SLOT_SERVICE, 0x00, 0x02, 0x01}, {L2_SLOT_DISTRIBUTE, 0x00, 0x01, 0x08},
{L2_SLOT_SERVICE, 0x01, 0x02, 0x01}, {L2_SLOT_DISTRIBUTE, 0x01, 0x01, 0x08},
{L2_SLOT_SERVICE, 0x02, 0x02, 0x01}, {L2_SLOT_DISTRIBUTE, 0x00, 0x01, 0x09},
{L2_SLOT_SERVICE, 0x03, 0x02, 0x01}, {L2_SLOT_DISTRIBUTE, 0x01, 0x01, 0x09},
{L2_SLOT_IDLE, 0x00, 0x00, 0x00}, {L2_SLOT_DISTRIBUTE, 0x00, 0x01, 0x0A},
{L2_SLOT_SERVICE, 0x00, 0x01, 0x02}, {L2_SLOT_DISTRIBUTE, 0x01, 0x01, 0x0A},
{L2_SLOT_SERVICE, 0x01, 0x01, 0x02}, {L2_SLOT_RTT, 0x00, 0x01, 0x08},
{L2_SLOT_SERVICE, 0x02, 0x01, 0x02}, {L2_SLOT_RTT, 0x01, 0x01, 0x08},
{L2_SLOT_SERVICE, 0x03, 0x01, 0x02}, {L2_SLOT_RTT, 0x00, 0x01, 0x09},
{L2_SLOT_IDLE, 0x00, 0x00, 0x00}, {L2_SLOT_RTT, 0x01, 0x01, 0x09},
{L2_SLOT_SERVICE, 0x00, 0x02, 0x01}, {L2_SLOT_RTT, 0x00, 0x01, 0x0A},
{L2_SLOT_SERVICE, 0x01, 0x02, 0x01}, {L2_SLOT_RTT, 0x01, 0x01, 0x0A},
{L2_SLOT_SERVICE, 0x02, 0x02, 0x01}, {L2_SLOT_RTT, 0x00, 0x08, 0x01},
{L2_SLOT_SERVICE, 0x03, 0x02, 0x01}, {L2_SLOT_RTT, 0x01, 0x08, 0x01},
{L2_SLOT_IDLE, 0x00, 0x00, 0x00}, {L2_SLOT_RTT, 0x00, 0x09, 0x01},
{L2_SLOT_RTT, 0x01, 0x09, 0x01},
// SubFrame 4 {L2_SLOT_RTT, 0x00, 0x0A, 0x01},
{L2_SLOT_SERVICE, 0x00, 0x01, 0x02}, {L2_SLOT_RTT, 0x01, 0x0A, 0x01},
{L2_SLOT_SERVICE, 0x01, 0x01, 0x02}, {L2_SLOT_SERVICE, 0x00, 0x08, 0x01},
{L2_SLOT_SERVICE, 0x02, 0x01, 0x02}, {L2_SLOT_SERVICE, 0x01, 0x08, 0x01},
{L2_SLOT_SERVICE, 0x03, 0x01, 0x02}, {L2_SLOT_SERVICE, 0x00, 0x09, 0x01},
{L2_SLOT_IDLE, 0x00, 0x00, 0x00}, {L2_SLOT_SERVICE, 0x01, 0x09, 0x01},
{L2_SLOT_SERVICE, 0x00, 0x02, 0x01}, {L2_SLOT_SERVICE, 0x00, 0x0A, 0x01},
{L2_SLOT_SERVICE, 0x01, 0x02, 0x01}, {L2_SLOT_SERVICE, 0x01, 0x0A, 0x01},
{L2_SLOT_SERVICE, 0x02, 0x02, 0x01},
{L2_SLOT_SERVICE, 0x03, 0x02, 0x01},
{L2_SLOT_IDLE, 0x00, 0x00, 0x00},
{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_IDLE, 0x00, 0x00, 0x00},
{L2_SLOT_IDLE, 0x00, 0x00, 0x00}
}; };
L2_RTNE_TABLE_ENTRY *initTable[L2_INIT_RTNE_PERIOD] = L2_RTNE_TABLE_ENTRY *initTable[L2_INIT_RTNE_PERIOD] =
{ {
intraScanSubT innerScanSubT
}; };
L2_RTNE_TABLE_ENTRY *normalTable[L2_NORMAL_RTNE_PERIOD] = L2_RTNE_TABLE_ENTRY *normalTable[L2_NORMAL_RTNE_PERIOD] =
{ {
normalSub innerScanSubT
}; };
/** @} RoutineTable*/ /** @} RoutineTable*/
File diff suppressed because it is too large Load Diff
+625 -167
View File
@@ -36,6 +36,13 @@
/**************************** Type Definitions *******************************/ /**************************** Type Definitions *******************************/
/************************** Function Prototypes ******************************/ /************************** Function Prototypes ******************************/
static int32_t Service_Packing(L2_INST *instPtr, L2_FRAME_TYPE type, uint8_t dstId); static int32_t Service_Packing(L2_INST *instPtr, L2_FRAME_TYPE type, uint8_t dstId);
static void Service_PackingCommon(L2_INST *instPtr, L2_FRAME_TYPE type, uint8_t dstId);
static int32_t Service_Packing128K(L2_INST *instPtr, L2_FRAME_TYPE type, uint8_t dstId);
static int32_t Service_Packing512K(L2_INST *instPtr, L2_FRAME_TYPE type, uint8_t dstId);
static int32_t Service_Packing2M(L2_INST *instPtr, L2_FRAME_TYPE type, uint8_t dstId);
static int32_t Service_PktHandler128K(L2_INST *instPtr, uint8_t *msg);
static int32_t Service_PktHandler512K(L2_INST *instPtr, uint8_t *msg);
static int32_t Service_PktHandler2M(L2_INST *instPtr, uint8_t *msg);
/************************** Variable Definitions *****************************/ /************************** Variable Definitions *****************************/
static uint8_t testData[L2_PACK_LEN_MAX] = static uint8_t testData[L2_PACK_LEN_MAX] =
@@ -91,75 +98,242 @@ static int32_t Service_Packing(L2_INST *instPtr, L2_FRAME_TYPE type, uint8_t dst
#ifndef DATALINK_ENABLE_BERTEST #ifndef DATALINK_ENABLE_BERTEST
ASSERT(instPtr != NULL); ASSERT(instPtr != NULL);
int32_t Status; 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) switch (type)
{ {
case L2_SVC_FRAME: case L2_FRAME_DIS:
case L2_FRAME_MNG:
case L2_FRAME_RTT:
{ {
dataChunk = L2_SVC_FRAME; Status = Service_Packing128K(instPtr, type, dstId);
L2_FrameInsertChunk(buff, L2_MSG_TYPE, L2_MSG_TYPE_LEN, &dataChunk); break;
}
SysMonitor_GetSysinfo(&(instPtr->sysInfo)); case L2_FRAME_SVC:
// insert position and speed info {
L2_FrameInsertChunk(buff, L2_MSG_SVC_SRC_POSX, L2_MSG_SVC_SRC_POSX_LEN, &(instPtr->sysInfo.posX)); switch (instPtr->config.serviceRate)
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); case L2_SVC_128K:
Status = Service_Packing128K(instPtr, type, dstId);
break;
case L2_SVC_512K:
Status = Service_Packing512K(instPtr, type, dstId);
break;
case L2_SVC_2M:
Status = Service_Packing2M(instPtr, type, dstId);
break;
default:
DBG_ERROR("Unexpected service rate: %" PRIu8 ".\n", instPtr->config.serviceRate);
return EPARAM;
} }
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; break;
} }
default: default:
{
DBG_ERROR("Unexpected frame type: %" PRIu8 ".\n", type); DBG_ERROR("Unexpected frame type: %" PRIu8 ".\n", type);
return EPARAM; return EPARAM;
break;
} }
} return Status;
return SUCCESS;
#else #else
DBG_ERROR("Unexpected call of Service_Packing in BER test mode.\n"); DBG_ERROR("Unexpected call of Service_Packing in BER test mode.\n");
return EUNEXP; return EUNEXP;
#endif #endif
} }
/*****************************************************************************/
/**
* @brief Packing Service message (common part)
*
* @param instPtr pointer to linklayer instance
* type message type.
* dstId destination node address.
*
* @return EPARAM
* SUCCESS
*
******************************************************************************/
static void Service_PackingCommon(L2_INST *instPtr, L2_FRAME_TYPE type, uint8_t dstId)
{
ASSERT(instPtr != NULL);
L2_MSG_COMMON *message = (L2_MSG_COMMON *)(instPtr->sendPktData);
// Common section of link layer package
message->frameNum = L2_GetNextFrameNum(instPtr);
message->slotNum = L2_GetNextSlotNum(instPtr);
message->src = L2_GetNodeId(instPtr);
message->dst = dstId;
message->msgType = type;
}
/*****************************************************************************/
/**
* @brief Packing Service message (128 kbps)
*
* @param instPtr pointer to linklayer instance
* type message type.
* dstId destination node address.
*
* @return EPARAM
* SUCCESS
*
******************************************************************************/
static int32_t Service_Packing128K(L2_INST *instPtr, L2_FRAME_TYPE type, uint8_t dstId)
{
ASSERT(instPtr != NULL);
int32_t Status;
Service_PackingCommon(instPtr, type, dstId);
L2_MSG_SVC_128K *message = (L2_MSG_SVC_128K *)(instPtr->sendPktData);
size_t msgLen = sizeof(L2_MSG_SVC_128K);
size_t dataLen = L2_PAYLOAD_LEN_SVC_128K;
// insert position and speed info
SysMonitor_GetSysinfo(&(instPtr->sysInfo));
message->srcPosX = instPtr->sysInfo.posX;
message->srcPosY = instPtr->sysInfo.posY;
message->srcPosZ = instPtr->sysInfo.posZ;
message->srcSpeedX = instPtr->sysInfo.vX;
message->srcSpeedY = instPtr->sysInfo.vY;
message->srcSpeedZ = instPtr->sysInfo.vZ;
// Packing extra payload
SysMonitor_GetSendPayload(message->svcData, &(message->svcDataId), dataLen);
if (message->svcDataId == DATA_ID_NONE)
{
memset(message->svcData, 0xAA, dataLen);
}
// Append CRC
uint32_t crcVal;
Status = L2_CrcGen((uint8_t *)message, msgLen - L2_MSG_CRC_LEN, L2_CRC8_31, &crcVal);
if (Status != SUCCESS)
{
DBG_ERROR("Fail to generate CRC, error code: %" PRId32 ".\n", Status);
return Status;
}
message->crc = crcVal;
// Logging...
memcpy(instPtr->log.txLog.data, message, msgLen);
instPtr->log.txLog.dataId = message->svcDataId;
return SUCCESS;
}
/*****************************************************************************/
/**
* @brief Packing Service message (512 kbps)
*
* @param instPtr pointer to linklayer instance
* type message type.
* dstId destination node address.
*
* @return EPARAM
* SUCCESS
*
******************************************************************************/
static int32_t Service_Packing512K(L2_INST *instPtr, L2_FRAME_TYPE type, uint8_t dstId)
{
ASSERT(instPtr != NULL);
int32_t Status;
Service_PackingCommon(instPtr, type, dstId);
L2_MSG_SVC_512K *message = (L2_MSG_SVC_512K *)(instPtr->sendPktData);
size_t msgLen = sizeof(L2_MSG_SVC_512K);
size_t dataLen = L2_PAYLOAD_LEN_SVC_512K;
// insert position and speed info
SysMonitor_GetSysinfo(&(instPtr->sysInfo));
message->srcPosX = instPtr->sysInfo.posX;
message->srcPosY = instPtr->sysInfo.posY;
message->srcPosZ = instPtr->sysInfo.posZ;
message->srcSpeedX = instPtr->sysInfo.vX;
message->srcSpeedY = instPtr->sysInfo.vY;
message->srcSpeedZ = instPtr->sysInfo.vZ;
// Packing extra payload
SysMonitor_GetSendPayload(message->svcData, &(message->svcDataId), dataLen);
if (message->svcDataId == DATA_ID_NONE)
{
memset(message->svcData, 0xAA, dataLen);
}
// Append CRC
uint32_t crcVal;
Status = L2_CrcGen((uint8_t *)message, msgLen - L2_MSG_CRC_LEN, L2_CRC8_31, &crcVal);
if (Status != SUCCESS)
{
DBG_ERROR("Fail to generate CRC, error code: %" PRId32 ".\n", Status);
return Status;
}
message->crc = crcVal;
// Logging...
memcpy(instPtr->log.txLog.data, message, msgLen);
instPtr->log.txLog.dataId = message->svcDataId;
return SUCCESS;
}
/*****************************************************************************/
/**
* @brief Packing Service message (2 Mbps)
*
* @param instPtr pointer to linklayer instance
* type message type.
* dstId destination node address.
*
* @return EPARAM
* SUCCESS
*
******************************************************************************/
static int32_t Service_Packing2M(L2_INST *instPtr, L2_FRAME_TYPE type, uint8_t dstId)
{
ASSERT(instPtr != NULL);
int32_t Status;
Service_PackingCommon(instPtr, type, dstId);
L2_MSG_SVC_2M *message = (L2_MSG_SVC_2M *)(instPtr->sendPktData);
size_t msgLen = sizeof(L2_MSG_SVC_2M);
size_t dataLen = L2_PAYLOAD_LEN_SVC_2M;
// insert position and speed info
SysMonitor_GetSysinfo(&(instPtr->sysInfo));
message->srcPosX = instPtr->sysInfo.posX;
message->srcPosY = instPtr->sysInfo.posY;
message->srcPosZ = instPtr->sysInfo.posZ;
message->srcSpeedX = instPtr->sysInfo.vX;
message->srcSpeedY = instPtr->sysInfo.vY;
message->srcSpeedZ = instPtr->sysInfo.vZ;
// Packing extra payload
SysMonitor_GetSendPayload(message->svcData, &(message->svcDataId), dataLen);
if (message->svcDataId == DATA_ID_NONE)
{
memset(message->svcData, 0xAA, dataLen);
}
// Append CRC
uint32_t crcVal;
Status = L2_CrcGen((uint8_t *)message, msgLen - L2_MSG_CRC_LEN, L2_CRC8_31, &crcVal);
if (Status != SUCCESS)
{
DBG_ERROR("Fail to generate CRC, error code: %" PRId32 ".\n", Status);
return Status;
}
message->crc = crcVal;
// Logging...
memcpy(instPtr->log.txLog.data, message, msgLen);
instPtr->log.txLog.dataId = message->svcDataId;
return SUCCESS;
}
/*****************************************************************************/ /*****************************************************************************/
/** /**
* @brief Handle service received packet. Send data up to MPC * @brief Handle service received packet. Send data up to MPC
@@ -176,103 +350,60 @@ int32_t L2_Service_PktHandler(L2_INST *instPtr, uint8_t *msg)
ASSERT(msg != NULL); ASSERT(msg != NULL);
int32_t Status; int32_t Status;
#ifndef DATALINK_ENABLE_BERTEST #ifndef DATALINK_ENABLE_BERTEST
L2_FRAME_TYPE frameType = L2_NONE_FRAME; L2_FRAME_TYPE frameType = L2_FRAME_NONE;
L2_FrameGetChunk(msg, L2_MSG_TYPE, L2_MSG_TYPE_LEN, &frameType); L2_FrameGetChunk(msg, L2_MSG_TYPE, L2_MSG_TYPE_LEN, &frameType);
// retrieve basic info
switch (frameType) switch (frameType)
{ {
case L2_SVC_FRAME: case L2_FRAME_DIS:
{
uint8_t nodeId;
L2_FrameGetChunk(msg, L2_MSG_SRC_ID, L2_MSG_SRC_ID_LEN, &nodeId);
NODE_ENTRY *node;
node = L2_GetNodeById(instPtr->nodeList, nodeId);
if (node == NULL)
{
node = L2_AppendNode(instPtr->nodeList, nodeId, L2_NODE_MEMBER);
if (node == NULL)
{
DBG_ERROR("Failed to append new node [id: %" PRIu8 "]", nodeId);
Status = ENOMEM;
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) if (L2_GetNodeType(instPtr) == L2_NODE_HEAD)
{ {
SysMonitor_UpdateRecvPayload(msg + L2_MSG_SVC_PAYLOAD, dataId, PAYLOAD_LEN_FLJ_RX); DBG_ERROR("Unexpected call from head node, only member Node can handle L2_FRAME_DIS.\n");
return EUNEXP;
}
case L2_FRAME_MNG:
case L2_FRAME_RTT:
Status = Service_PktHandler128K(instPtr, msg);
break;
case L2_FRAME_SVC:
switch (instPtr->config.serviceRate)
{
case L2_SVC_128K:
Status = Service_PktHandler128K(instPtr, msg);
break;
case L2_SVC_512K:
Status = Service_PktHandler512K(instPtr, msg);
break;
case L2_SVC_2M:
Status = Service_PktHandler2M(instPtr, msg);
break;
default:
DBG_ERROR("Unexpected service rate: %" PRIu8 ".\n", instPtr->config.serviceRate);
return EPARAM;
} }
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; break;
}
default: default:
DBG_ERROR("Unsupported frame type: %" PRIu8 ".\n", frameType); DBG_ERROR("Unsupported frame type: %" PRIu8 ".\n", frameType);
break; return EPARAM;
} }
return Status; return Status;
#else #else
uint32_t errorBits = 0; uint32_t errorBits = 0;
for (int i = 0; i < L2_SVC_PACK_LEN; i++) uint32_t pktLen = L2_GetSvcPacketLen(instPtr->config.serviceRate);
for (int i = 0; i < pktLen; i++)
{ {
errorBits += count_ones(msg[i] ^ testData[i]); errorBits += count_ones(msg[i] ^ testData[i]);
} }
instPtr->serviceFSM->bitError += errorBits; instPtr->serviceFSM->bitError += errorBits;
instPtr->serviceFSM->bitTotal += L2_SVC_PACK_LEN * 8; instPtr->serviceFSM->bitTotal += pktLen * 8;
// Calculate time deviation // Calculate time deviation
uint32_t frameNum, slotNum = 0; uint32_t frameNum = message->common.frameNum;
L2_FrameGetChunk(msg, L2_MSG_FRAME_NUM, L2_MSG_FRAME_NUM_LEN, &frameNum); uint32_t slotNum = (uint32_t)message->common.slotNum;
L2_FrameGetChunk(msg, L2_MSG_SLOT_NUM, L2_MSG_SLOT_NUM_LEN, &slotNum);
Status = L2_GetTimeDeviation(instPtr, frameNum, slotNum, true, &(instPtr->log.timeDev)); Status = L2_GetTimeDeviation(instPtr, frameNum, slotNum, true, &(instPtr->log.timeDev));
if (Status != SUCCESS) if (Status != SUCCESS)
{ {
@@ -289,6 +420,231 @@ int32_t L2_Service_PktHandler(L2_INST *instPtr, uint8_t *msg)
#endif #endif
} }
/*****************************************************************************/
/**
* @brief Handle service received packet. Send data up to MPC. (128 kbps)
*
* @param msg A point32_ter the the message frame.
*
* @return SUCCESS message has been successfully handled.
* other error occurred.
*
******************************************************************************/
static int32_t Service_PktHandler128K(L2_INST *instPtr, uint8_t *msg)
{
ASSERT(instPtr != NULL);
ASSERT(msg != NULL);
int32_t Status;
L2_MSG_SVC_128K *message = (L2_MSG_SVC_128K *)msg;
size_t msgLen = sizeof(L2_MSG_SVC_128K);
size_t dataLen = L2_PAYLOAD_LEN_SVC_128K;
// Update node status.
uint8_t nodeId = message->common.src;
NODE_ENTRY *node;
node = L2_GetNodeById(instPtr->nodeList, nodeId);
if (node == NULL)
{
node = L2_AppendNode(instPtr->nodeList, nodeId, L2_NODE_MEMBER);
if (node == NULL)
{
DBG_ERROR("Failed to append new node [id: %" PRId8 "]", nodeId);
return ENOMEM;
}
}
// Update node info.
node->nodeInfo.pos.x = message->srcPosX;
node->nodeInfo.pos.y = message->srcPosY;
node->nodeInfo.pos.z = message->srcPosZ;
node->nodeInfo.speed.x = message->srcSpeedX;
node->nodeInfo.speed.y = message->srcSpeedY;
node->nodeInfo.speed.z = message->srcSpeedZ;
node->nodeInfo.antIndex = Phy_ReceiveAntIndex(instPtr->config.phyInstPtr);
// Reset node ttl
node->ttlCnt = 0;
// Calculate time deviation
uint32_t frameNum = message->common.frameNum;
uint32_t slotNum = (uint32_t)message->common.slotNum;
Status = L2_GetTimeDeviation(instPtr, frameNum, slotNum, true, &(instPtr->log.timeDev));
if (Status != SUCCESS)
{
DBG_ERROR("Failed to compute time deviation.\n")
return Status;
}
// Get data payload
SysMonitor_UpdateRecvPayload(message->svcData, message->svcDataId, dataLen);
// Logging...
memcpy(instPtr->log.rxLog.data, msg, msgLen);
instPtr->log.rxLog.dataId = message->svcDataId;
#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
return Status;
}
/*****************************************************************************/
/**
* @brief Handle service received packet. Send data up to MPC. (512 kbps)
*
* @param msg A point32_ter the the message frame.
*
* @return SUCCESS message has been successfully handled.
* other error occurred.
*
******************************************************************************/
static int32_t Service_PktHandler512K(L2_INST *instPtr, uint8_t *msg)
{
ASSERT(instPtr != NULL);
ASSERT(msg != NULL);
int32_t Status;
L2_MSG_SVC_512K *message = (L2_MSG_SVC_512K *)msg;
size_t msgLen = sizeof(L2_MSG_SVC_512K);
size_t dataLen = L2_PAYLOAD_LEN_SVC_512K;
// Update node status.
uint8_t nodeId = message->common.src;
NODE_ENTRY *node;
node = L2_GetNodeById(instPtr->nodeList, nodeId);
if (node == NULL)
{
node = L2_AppendNode(instPtr->nodeList, nodeId, L2_NODE_MEMBER);
if (node == NULL)
{
DBG_ERROR("Failed to append new node [id: %" PRId8 "]", nodeId);
return ENOMEM;
}
}
// Update node info.
node->nodeInfo.pos.x = message->srcPosX;
node->nodeInfo.pos.y = message->srcPosY;
node->nodeInfo.pos.z = message->srcPosZ;
node->nodeInfo.speed.x = message->srcSpeedX;
node->nodeInfo.speed.y = message->srcSpeedY;
node->nodeInfo.speed.z = message->srcSpeedZ;
node->nodeInfo.antIndex = Phy_ReceiveAntIndex(instPtr->config.phyInstPtr);
// Reset node ttl
node->ttlCnt = 0;
// Calculate time deviation
uint32_t frameNum = message->common.frameNum;
uint32_t slotNum = (uint32_t)message->common.slotNum;
Status = L2_GetTimeDeviation(instPtr, frameNum, slotNum, true, &(instPtr->log.timeDev));
if (Status != SUCCESS)
{
DBG_ERROR("Failed to compute time deviation.\n")
return Status;
}
// Get data payload
SysMonitor_UpdateRecvPayload(message->svcData, message->svcDataId, dataLen);
// Logging...
memcpy(instPtr->log.rxLog.data, msg, msgLen);
instPtr->log.rxLog.dataId = message->svcDataId;
#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
return Status;
}
/*****************************************************************************/
/**
* @brief Handle service received packet. Send data up to MPC. (2 Mbps)
*
* @param msg A point32_ter the the message frame.
*
* @return SUCCESS message has been successfully handled.
* other error occurred.
*
******************************************************************************/
static int32_t Service_PktHandler2M(L2_INST *instPtr, uint8_t *msg)
{
ASSERT(instPtr != NULL);
ASSERT(msg != NULL);
int32_t Status;
L2_MSG_SVC_2M *message = (L2_MSG_SVC_2M *)msg;
size_t msgLen = sizeof(L2_MSG_SVC_2M);
size_t dataLen = L2_PAYLOAD_LEN_SVC_2M;
// Update node status.
uint8_t nodeId = message->common.src;
NODE_ENTRY *node;
node = L2_GetNodeById(instPtr->nodeList, nodeId);
if (node == NULL)
{
node = L2_AppendNode(instPtr->nodeList, nodeId, L2_NODE_MEMBER);
if (node == NULL)
{
DBG_ERROR("Failed to append new node [id: %" PRId8 "]", nodeId);
return ENOMEM;
}
}
// Update node info.
node->nodeInfo.pos.x = message->srcPosX;
node->nodeInfo.pos.y = message->srcPosY;
node->nodeInfo.pos.z = message->srcPosZ;
node->nodeInfo.speed.x = message->srcSpeedX;
node->nodeInfo.speed.y = message->srcSpeedY;
node->nodeInfo.speed.z = message->srcSpeedZ;
node->nodeInfo.antIndex = Phy_ReceiveAntIndex(instPtr->config.phyInstPtr);
// Reset node ttl
node->ttlCnt = 0;
// Calculate time deviation
uint32_t frameNum = message->common.frameNum;
uint32_t slotNum = (uint32_t)message->common.slotNum;
Status = L2_GetTimeDeviation(instPtr, frameNum, slotNum, true, &(instPtr->log.timeDev));
if (Status != SUCCESS)
{
DBG_ERROR("Failed to compute time deviation.\n")
return Status;
}
// Get data payload
SysMonitor_UpdateRecvPayload(message->svcData, message->svcDataId, dataLen);
// Logging...
memcpy(instPtr->log.rxLog.data, msg, msgLen);
instPtr->log.rxLog.dataId = message->svcDataId;
#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
return Status;
}
/*****************************************************************************/ /*****************************************************************************/
/** /**
* @brief Initialize service net FSM * @brief Initialize service net FSM
@@ -338,7 +694,7 @@ void L2_Service_Reset(L2_SVC_FSM *svcFSMPtr)
/** /**
* @brief Destroy ServiceNet FSM, free memory * @brief Destroy ServiceNet FSM, free memory
* *
* @param scanFsmPtr a pointer to service net finite state machine * @param serviceFSM a pointer to service net finite state machine
* *
* @return NONE * @return NONE
* *
@@ -369,55 +725,157 @@ int32_t L2_Service_Routine(L2_INST *instPtr, const L2_RTNE_TABLE_ENTRY *rtneEntr
} }
PHY_INST *phyRef = instPtr->config.phyInstPtr; PHY_INST *phyRef = instPtr->config.phyInstPtr;
PHY_ANT_INDEX antIndex;
L2_SVC_FSM *svcFSMPtr = instPtr->serviceFSM; L2_SVC_FSM *svcFSMPtr = instPtr->serviceFSM;
L2_TOR_TYPE torState; L2_TOR_TYPE torState;
const NODE_ENTRY *commNode; 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) switch (rtneEntry->slotType)
{ {
case L2_SLOT_SERVICE: case L2_SLOT_DISTRIBUTE:
if (torState == L2_TOR_TX) if (L2_GetNodeType(instPtr) == L2_NODE_HEAD && rtneEntry->src == L2_GetNodeId(instPtr))
{ {
svcFSMPtr->txCnt++; commNode = L2_GetNodeById(instPtr->nodeList, rtneEntry->dst);
#ifndef DATALINK_ENABLE_BERTEST // antenna selection based on destination id in routing table
// Packing service data antIndex = commNode->nodeInfo.antIndex;
Service_Packing(instPtr, L2_SVC_FRAME, rtneEntry->dst); // head node transmits messages in distribute slot
#else torState = L2_TOR_TX;
memcpy(instPtr->sendPktData, testData, L2_SVC_PACK_LEN);
#endif // reset memory
memset(instPtr->sendPktData, 0xAA, L2_PACK_LEN_MAX);
// pack message
if (Service_Packing(instPtr, L2_FRAME_DIS, rtneEntry->dst) != SUCCESS)
{
return FAILURE;
}
}
else if (L2_GetNodeType(instPtr) == L2_NODE_MEMBER && rtneEntry->dst == L2_GetNodeId(instPtr))
{
commNode = L2_GetNodeById(instPtr->nodeList, rtneEntry->src);
// antenna selection based on node list
antIndex = commNode->nodeInfo.antIndex;
// member node receives message in advertise slot
torState = L2_TOR_RX;
} }
else else
{ {
// otherwise suspend
antIndex = PHY_ANT_INDEX_NONE;
torState = L2_TOR_SUSPEND;
}
(void)Phy_SetAntIndex(instPtr->config.phyInstPtr, antIndex);
(void)L2_SetupNextSlot(instPtr, torState, L2_FRAME_DIS);
break;
case L2_SLOT_MANAGE:
if (rtneEntry->src == L2_GetNodeId(instPtr))
{
commNode = L2_GetNodeById(instPtr->nodeList, rtneEntry->dst);
// antenna selection based on destination id in routing table
antIndex = commNode->nodeInfo.antIndex;
// head node transmits messages in distribute slot
torState = L2_TOR_TX;
// reset memory
memset(instPtr->sendPktData, 0xAA, L2_PACK_LEN_MAX);
// pack message
if (Service_Packing(instPtr, L2_FRAME_MNG, rtneEntry->dst) != SUCCESS)
{
return FAILURE;
}
}
else if (rtneEntry->dst == L2_GetNodeId(instPtr))
{
commNode = L2_GetNodeById(instPtr->nodeList, rtneEntry->src);
// antenna selection based on node list
antIndex = commNode->nodeInfo.antIndex;
// member node receives message in advertise slot
torState = L2_TOR_RX;
}
else
{
// otherwise suspend
antIndex = PHY_ANT_INDEX_NONE;
torState = L2_TOR_SUSPEND;
}
(void)Phy_SetAntIndex(instPtr->config.phyInstPtr, antIndex);
(void)L2_SetupNextSlot(instPtr, torState, L2_FRAME_MNG);
break;
case L2_SLOT_RTT:
if (rtneEntry->src == L2_GetNodeId(instPtr))
{
commNode = L2_GetNodeById(instPtr->nodeList, rtneEntry->dst);
// antenna selection based on destination id in routing table
antIndex = commNode->nodeInfo.antIndex;
// head node transmits messages in distribute slot
torState = L2_TOR_TX;
// reset memory
memset(instPtr->sendPktData, 0xAA, L2_PACK_LEN_MAX);
// pack message
if (Service_Packing(instPtr, L2_FRAME_RTT, rtneEntry->dst) != SUCCESS)
{
return FAILURE;
}
}
else if (rtneEntry->dst == L2_GetNodeId(instPtr))
{
commNode = L2_GetNodeById(instPtr->nodeList, rtneEntry->src);
// antenna selection based on node list
antIndex = commNode->nodeInfo.antIndex;
// member node receives message in advertise slot
torState = L2_TOR_RX;
}
else
{
// otherwise suspend
antIndex = PHY_ANT_INDEX_NONE;
torState = L2_TOR_SUSPEND;
}
(void)Phy_SetAntIndex(instPtr->config.phyInstPtr, antIndex);
(void)L2_SetupNextSlot(instPtr, torState, L2_FRAME_RTT);
break;
case L2_SLOT_SERVICE:
if (rtneEntry->src == L2_GetNodeId(instPtr))
{
commNode = L2_GetNodeById(instPtr->nodeList, rtneEntry->dst);
// antenna selection based on destination id in routing table
antIndex = commNode->nodeInfo.antIndex;
// head node transmits messages in distribute slot
torState = L2_TOR_TX;
svcFSMPtr->txCnt++;
// reset memory
memset(instPtr->sendPktData, 0xAA, L2_PACK_LEN_MAX);
#ifndef DATALINK_ENABLE_BERTEST
// pack message
if (Service_Packing(instPtr, L2_FRAME_SVC, rtneEntry->dst) != SUCCESS)
{
return FAILURE;
}
#else
size_t msgLen = L2_GetSvcPacketLen(instPtr->config.serviceRate);
memcpy(instPtr->sendPktData, testData, msgLen);
#endif
}
else if (rtneEntry->dst == L2_GetNodeId(instPtr))
{
commNode = L2_GetNodeById(instPtr->nodeList, rtneEntry->src);
// antenna selection based on node list
antIndex = commNode->nodeInfo.antIndex;
// member node receives message in advertise slot
torState = L2_TOR_RX;
svcFSMPtr->rxCnt++; svcFSMPtr->rxCnt++;
} }
L2_SetupNextSlot(instPtr, torState, L2_SVC_FRAME); else
{
// otherwise suspend
antIndex = PHY_ANT_INDEX_NONE;
torState = L2_TOR_SUSPEND;
}
(void)Phy_SetAntIndex(instPtr->config.phyInstPtr, antIndex);
(void)L2_SetupNextSlot(instPtr, torState, L2_FRAME_SVC);
break; break;
default: default:
DBG_ERROR("UNKNOWN slot type [%" PRIu8 "].\n", rtneEntry->slotType); DBG_ERROR("UNKNOWN slot type [%" PRIu8 "].\n", rtneEntry->slotType);
@@ -435,4 +893,4 @@ int32_t L2_Service_Routine(L2_INST *instPtr, const L2_RTNE_TABLE_ENTRY *rtneEntr
} }
/** @} LinkLayer_Service*/ /** @} LinkLayer_Service*/
/** @} LinkLayer*/ /** @} LinkLayer*/
@@ -54,7 +54,7 @@ int32_t L2_GetTimeDeviation(L2_INST *instPtr, uint32_t frameNum, uint32_t slotNu
L1_FRAME_TYPE lastRecvdFrame; L1_FRAME_TYPE lastRecvdFrame;
PHY_INST *phyRef = instPtr->config.phyInstPtr; PHY_INST *phyRef = instPtr->config.phyInstPtr;
lastRecvdFrame = Phy_GetLastRecvFrameType(phyRef); lastRecvdFrame = Phy_GetLastRecvFrameType(phyRef);
if (lastRecvdFrame == L1_NONE_FRAME) if (lastRecvdFrame == L1_FRAME_NONE)
{ {
DBG_ERROR("Invalid TimeAlign operation, no frame was received."); DBG_ERROR("Invalid TimeAlign operation, no frame was received.");
return EIGNORE; return EIGNORE;
@@ -38,152 +38,204 @@
#define CTRL_WORD_DEFAULT 0x00 #define CTRL_WORD_DEFAULT 0x00
#define ANT_MODE_BEAM_MASK 0xF0 #define ANT_ENABLE 0x01
#define ANT_BEAM_NARROR 0x00 // 8 #define ANT_DISABLE 0x00
#define ANT_BEAM_SUBNARROR_0 0x10 // 25 #define ANT_MODE_RX_NORMAL 0x00
#define ANT_BEAM_SUBNARROR_1 0x20 // 60 #define ANT_MODE_RX_AJ 0x01
#define ANT_BEAM_WIDE 0x30 // 120
#define ANT_MODE_POWER_MASK 0x0F #define DEFAULT_CENTRTAL_FREQ 300U // 4 GHz
#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 // Pair by regex
// Regex: (([0-9]+, ){8}) // Regex: (([0-9]+, ){8})
const uint16_t freqTable[L1_FRAME_MAX_HOPS] = const uint16_t freqTable[L1_FRAME_MAX_HOPS] =
{ {
1084U, 1097U, 1110U, 1123U, 1136U, 1149U, 1162U, 1175U, 0U, 7U, 15U, 22U, 30U, 37U, 45U, 52U,
1188U, 1201U, 1214U, 1227U, 1240U, 1253U, 1266U, 1279U, 60U, 67U, 75U, 82U, 90U, 97U, 105U, 112U,
1292U, 1305U, 1318U, 1331U, 1344U, 1357U, 1370U, 1383U, 120U, 127U, 135U, 142U, 150U, 157U, 165U, 172U,
1396U, 1409U, 1422U, 1435U, 1448U, 1461U, 1474U, 1487U, 180U, 187U, 195U, 202U, 210U, 217U, 225U, 232U,
1500U, 1513U, 1526U, 1539U, 1552U, 1565U, 1578U, 1591U, 240U, 247U, 255U, 262U, 270U, 277U, 285U, 292U,
1604U, 1617U, 1630U, 1643U, 1656U, 1669U, 1682U, 1695U, 300U, 307U, 315U, 322U, 330U, 337U, 345U, 352U,
1708U, 1721U, 1734U, 1747U, 1760U, 1773U, 1786U, 1799U, 360U, 367U, 375U, 382U, 390U, 397U, 405U, 412U,
1812U, 1825U, 1838U, 1851U, 1864U, 1877U, 1890U, 1903U, 420U, 427U, 435U, 442U, 450U, 457U, 465U, 472U,
1916U, 1929U, 1942U, 1955U, 1968U, 1981U, 1994U, 2007U, 480U, 487U, 495U, 502U, 510U, 517U, 525U, 532U,
2020U, 2033U, 2046U, 2059U, 2072U, 2085U, 2098U, 2111U, 540U, 547U, 555U, 562U, 570U, 577U, 585U, 592U,
2124U 600U,
}; };
const int16_t antCalTable[L1_FRAME_MAX_HOPS][L1_ANT_NUM_CH] =
const uint8_t antCalTable[L1_ANT_NUM][L1_FRAME_MAX_HOPS][L1_ANT_CH_NUM] =
//Antenna-JG01 //Antenna-JG01
{ {
{ 0, 2525, -7533, -6846}, { 0, 12726, -7818, -6860}, // Antenna-1
{ 0, 2490, -7836, -6907}, { 0, 4479, -7716, -6837}, {
{ 0, 6409, -7770, -6776}, { 0, 14616, -7977, -6816}, { 0, 2525, -7533, -6846}, { 0, 12726, -7818, -6860},
{ 0, -22557, -8002, -6911}, { 0, -22587, -8121, -6918}, { 0, 2490, -7836, -6907}, { 0, 4479, -7716, -6837},
{ 0, -1124, -8123, -7030}, { 0, -152, -8219, -7042}, { 0, 6409, -7770, -6776}, { 0, 14616, -7977, -6816},
{ 0, 1823, -8209, -7130}, { 0, 1790, -8290, -7214}, { 0, -22557, -8002, -6911}, { 0, -22587, -8121, -6918},
{ 0, 1669, -8362, -7283}, { 0, 1634, -8459, -7276}, { 0, -1124, -8123, -7030}, { 0, -152, -8219, -7042},
{ 0, 1615, -8315, -7415}, { 0, 1698, -8168, -7366}, { 0, 1823, -8209, -7130}, { 0, 1790, -8290, -7214},
{ 0, 1535, -8285, -7520}, { 0, 1619, -8285, -7532}, { 0, 1669, -8362, -7283}, { 0, 1634, -8459, -7276},
{ 0, 1609, -8201, -7693}, { 0, 1671, -8145, -7769}, { 0, 1615, -8315, -7415}, { 0, 1698, -8168, -7366},
{ 0, 1676, -8135, -7805}, { 0, 951, -10279, -8871}, { 0, 1535, -8285, -7520}, { 0, 1619, -8285, -7532},
{ 0, 976, -10235, -8978}, { 0, 1118, -10127, -9019}, { 0, 1609, -8201, -7693}, { 0, 1671, -8145, -7769},
{ 0, 1175, -10003, -9007}, { 0, 1386, -9847, -9039}, { 0, 1676, -8135, -7805}, { 0, 951, -10279, -8871},
{ 0, 1535, -9572, -9058}, { 0, 1729, -9493, -9006}, { 0, 976, -10235, -8978}, { 0, 1118, -10127, -9019},
{ 0, -1158, -9312, -9003}, { 0, 23771, -9147, -8928}, { 0, 1175, -10003, -9007}, { 0, 1386, -9847, -9039},
{ 0, 20733, -9074, -8924}, { 0, 2455, -8841, -8886}, { 0, 1535, -9572, -9058}, { 0, 1729, -9493, -9006},
{ 0, 2622, -8718, -8735}, { 0, 2791, -8615, -8705}, { 0, -1158, -9312, -9003}, { 0, 23771, -9147, -8928},
{ 0, 2861, -8168, -8331}, { 0, 3076, -8091, -8218}, { 0, 20733, -9074, -8924}, { 0, 2455, -8841, -8886},
{ 0, 3257, -8046, -8100}, { 0, 3331, -7923, -8073}, { 0, 2622, -8718, -8735}, { 0, 2791, -8615, -8705},
{ 0, 3396, -7826, -7994}, { 0, 3478, -7842, -8016}, { 0, 2861, -8168, -8331}, { 0, 3076, -8091, -8218},
{ 0, 3518, -7846, -7765}, { 0, 3585, -7753, -7715}, { 0, 3257, -8046, -8100}, { 0, 3331, -7923, -8073},
{ 0, 150, -8145, -8591}, { 0, 192, -8090, -8570}, { 0, 3396, -7826, -7994}, { 0, 3478, -7842, -8016},
{ 0, 207, -8150, -8597}, { 0, 178, -8142, -8656}, { 0, 3518, -7846, -7765}, { 0, 3585, -7753, -7715},
{ 0, 89, -8557, -8688}, { 0, 107, -8614, -8733}, { 0, 150, -8145, -8591}, { 0, 192, -8090, -8570},
{ 0, 194, -8605, -8782}, { 0, 153, -8655, -8881}, { 0, 207, -8150, -8597}, { 0, 178, -8142, -8656},
{ 0, 70, -8615, -8952}, { 0, 35, -8596, -9148}, { 0, 89, -8557, -8688}, { 0, 107, -8614, -8733},
{ 0, 49, -8636, -9286}, { 0, 6, -8587, -9435}, { 0, 194, -8605, -8782}, { 0, 153, -8655, -8881},
{ 0, -51, -8540, -9549}, { 0, -65, -8588, -9700}, { 0, 70, -8615, -8952}, { 0, 35, -8596, -9148},
{ 0, -55, -8503, -9820}, { 0, -20, -8414, -9907}, { 0, 49, -8636, -9286}, { 0, 6, -8587, -9435},
{ 0, -112, -8481, -10031}, { 0, -69, -8535, -10185}, { 0, -51, -8540, -9549}, { 0, -65, -8588, -9700},
{ 0, 2, -8550, -10052}, { 0, -1, -8493, -10291}, { 0, -55, -8503, -9820}, { 0, -20, -8414, -9907},
{ 0, -73, -8441, -10380}, { 0, 1958, -6930, -8295}, { 0, -112, -8481, -10031}, { 0, -69, -8535, -10185},
{ 0, -1148, -6939, -8396}, { 0, 1915, -6784, -8370}, { 0, 2, -8550, -10052}, { 0, -1, -8493, -10291},
{ 0, 1871, -6970, -8514}, { 0, 1821, -6974, -8387}, { 0, -73, -8441, -10380}, { 0, 1958, -6930, -8295},
{ 0, 1781, -6906, -8431}, { 0, 1736, -6897, -8462}, { 0, -1148, -6939, -8396}, { 0, 1915, -6784, -8370},
{ 0, 1664, -7024, -8377}, { 0, 1629, -7127, -8436}, { 0, 1871, -6970, -8514}, { 0, 1821, -6974, -8387},
{ 0, 1603, -7148, -8528}, { 0, 1577, -7198, -8500}, { 0, 1781, -6906, -8431}, { 0, 1736, -6897, -8462},
{ 0, 1528, -7311, -8512}, { 0, 1577, -7390, -8570}, { 0, 1664, -7024, -8377}, { 0, 1629, -7127, -8436},
{ 0, 1616, -7436, -8572}, { 0, 1589, -7597, -8590}, { 0, 1603, -7148, -8528}, { 0, 1577, -7198, -8500},
{ 0, 1722, -7550, -8568}, { 0, 1741, -7691, -8449}, { 0, 1528, -7311, -8512}, { 0, 1577, -7390, -8570},
{ 0, 1767, -7775, -8328}, { 0, 1616, -7436, -8572}, { 0, 1589, -7597, -8590},
{ 0, 1722, -7550, -8568}, { 0, 1741, -7691, -8449},
{ 0, 1767, -7775, -8328},
},
// Antenna-2
{
{ 0, 2525, -7533, -6846}, { 0, 12726, -7818, -6860},
{ 0, 2490, -7836, -6907}, { 0, 4479, -7716, -6837},
{ 0, 6409, -7770, -6776}, { 0, 14616, -7977, -6816},
{ 0, -22557, -8002, -6911}, { 0, -22587, -8121, -6918},
{ 0, -1124, -8123, -7030}, { 0, -152, -8219, -7042},
{ 0, 1823, -8209, -7130}, { 0, 1790, -8290, -7214},
{ 0, 1669, -8362, -7283}, { 0, 1634, -8459, -7276},
{ 0, 1615, -8315, -7415}, { 0, 1698, -8168, -7366},
{ 0, 1535, -8285, -7520}, { 0, 1619, -8285, -7532},
{ 0, 1609, -8201, -7693}, { 0, 1671, -8145, -7769},
{ 0, 1676, -8135, -7805}, { 0, 951, -10279, -8871},
{ 0, 976, -10235, -8978}, { 0, 1118, -10127, -9019},
{ 0, 1175, -10003, -9007}, { 0, 1386, -9847, -9039},
{ 0, 1535, -9572, -9058}, { 0, 1729, -9493, -9006},
{ 0, -1158, -9312, -9003}, { 0, 23771, -9147, -8928},
{ 0, 20733, -9074, -8924}, { 0, 2455, -8841, -8886},
{ 0, 2622, -8718, -8735}, { 0, 2791, -8615, -8705},
{ 0, 2861, -8168, -8331}, { 0, 3076, -8091, -8218},
{ 0, 3257, -8046, -8100}, { 0, 3331, -7923, -8073},
{ 0, 3396, -7826, -7994}, { 0, 3478, -7842, -8016},
{ 0, 3518, -7846, -7765}, { 0, 3585, -7753, -7715},
{ 0, 150, -8145, -8591}, { 0, 192, -8090, -8570},
{ 0, 207, -8150, -8597}, { 0, 178, -8142, -8656},
{ 0, 89, -8557, -8688}, { 0, 107, -8614, -8733},
{ 0, 194, -8605, -8782}, { 0, 153, -8655, -8881},
{ 0, 70, -8615, -8952}, { 0, 35, -8596, -9148},
{ 0, 49, -8636, -9286}, { 0, 6, -8587, -9435},
{ 0, -51, -8540, -9549}, { 0, -65, -8588, -9700},
{ 0, -55, -8503, -9820}, { 0, -20, -8414, -9907},
{ 0, -112, -8481, -10031}, { 0, -69, -8535, -10185},
{ 0, 2, -8550, -10052}, { 0, -1, -8493, -10291},
{ 0, -73, -8441, -10380}, { 0, 1958, -6930, -8295},
{ 0, -1148, -6939, -8396}, { 0, 1915, -6784, -8370},
{ 0, 1871, -6970, -8514}, { 0, 1821, -6974, -8387},
{ 0, 1781, -6906, -8431}, { 0, 1736, -6897, -8462},
{ 0, 1664, -7024, -8377}, { 0, 1629, -7127, -8436},
{ 0, 1603, -7148, -8528}, { 0, 1577, -7198, -8500},
{ 0, 1528, -7311, -8512}, { 0, 1577, -7390, -8570},
{ 0, 1616, -7436, -8572}, { 0, 1589, -7597, -8590},
{ 0, 1722, -7550, -8568}, { 0, 1741, -7691, -8449},
{ 0, 1767, -7775, -8328},
},
// Antenna-3
{
{ 0, 2525, -7533, -6846}, { 0, 12726, -7818, -6860},
{ 0, 2490, -7836, -6907}, { 0, 4479, -7716, -6837},
{ 0, 6409, -7770, -6776}, { 0, 14616, -7977, -6816},
{ 0, -22557, -8002, -6911}, { 0, -22587, -8121, -6918},
{ 0, -1124, -8123, -7030}, { 0, -152, -8219, -7042},
{ 0, 1823, -8209, -7130}, { 0, 1790, -8290, -7214},
{ 0, 1669, -8362, -7283}, { 0, 1634, -8459, -7276},
{ 0, 1615, -8315, -7415}, { 0, 1698, -8168, -7366},
{ 0, 1535, -8285, -7520}, { 0, 1619, -8285, -7532},
{ 0, 1609, -8201, -7693}, { 0, 1671, -8145, -7769},
{ 0, 1676, -8135, -7805}, { 0, 951, -10279, -8871},
{ 0, 976, -10235, -8978}, { 0, 1118, -10127, -9019},
{ 0, 1175, -10003, -9007}, { 0, 1386, -9847, -9039},
{ 0, 1535, -9572, -9058}, { 0, 1729, -9493, -9006},
{ 0, -1158, -9312, -9003}, { 0, 23771, -9147, -8928},
{ 0, 20733, -9074, -8924}, { 0, 2455, -8841, -8886},
{ 0, 2622, -8718, -8735}, { 0, 2791, -8615, -8705},
{ 0, 2861, -8168, -8331}, { 0, 3076, -8091, -8218},
{ 0, 3257, -8046, -8100}, { 0, 3331, -7923, -8073},
{ 0, 3396, -7826, -7994}, { 0, 3478, -7842, -8016},
{ 0, 3518, -7846, -7765}, { 0, 3585, -7753, -7715},
{ 0, 150, -8145, -8591}, { 0, 192, -8090, -8570},
{ 0, 207, -8150, -8597}, { 0, 178, -8142, -8656},
{ 0, 89, -8557, -8688}, { 0, 107, -8614, -8733},
{ 0, 194, -8605, -8782}, { 0, 153, -8655, -8881},
{ 0, 70, -8615, -8952}, { 0, 35, -8596, -9148},
{ 0, 49, -8636, -9286}, { 0, 6, -8587, -9435},
{ 0, -51, -8540, -9549}, { 0, -65, -8588, -9700},
{ 0, -55, -8503, -9820}, { 0, -20, -8414, -9907},
{ 0, -112, -8481, -10031}, { 0, -69, -8535, -10185},
{ 0, 2, -8550, -10052}, { 0, -1, -8493, -10291},
{ 0, -73, -8441, -10380}, { 0, 1958, -6930, -8295},
{ 0, -1148, -6939, -8396}, { 0, 1915, -6784, -8370},
{ 0, 1871, -6970, -8514}, { 0, 1821, -6974, -8387},
{ 0, 1781, -6906, -8431}, { 0, 1736, -6897, -8462},
{ 0, 1664, -7024, -8377}, { 0, 1629, -7127, -8436},
{ 0, 1603, -7148, -8528}, { 0, 1577, -7198, -8500},
{ 0, 1528, -7311, -8512}, { 0, 1577, -7390, -8570},
{ 0, 1616, -7436, -8572}, { 0, 1589, -7597, -8590},
{ 0, 1722, -7550, -8568}, { 0, 1741, -7691, -8449},
{ 0, 1767, -7775, -8328},
},
}; };
const uint8_t hopPattern_2KBPS_20MS[L1_FRAME_2KBPS_20MS_HOPS] = const uint8_t hopPattern_ADV_24MS[L1_FRAME_ADV_24MS_HOPS] =
{ {
0 0U, 35U, 66U, 47U, 40U, 16U, 30U, 65U,
43U, 7U, 70U, 63U, 7U, 65U, 42U, 28U,
}; };
const uint8_t hopPattern_2KBPS_100MS[L1_FRAME_2KBPS_100MS_HOPS] = const uint8_t hopPattern_ACK_8MS[L1_FRAME_ACK_8MS_HOPS] =
{ {
0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, 0U, 5U, 49U, 25U,
8U, 9U, 10U, 11U, 12U, 13U, 14U, 15U,
16U, 17U, 18U, 19U, 20U, 21U, 22U, 23U,
24U, 25U, 26U, 27U, 28U, 29U, 30U, 31U,
32U, 33U, 34U, 35U, 36U, 37U, 38U, 39U,
40U, 41U, 42U, 43U, 44U, 45U, 46U, 47U,
48U, 49U, 50U, 51U, 52U, 53U, 54U, 55U,
56U, 57U, 58U, 59U, 60U, 61U, 62U, 63U,
64U, 65U, 66U, 67U, 68U, 69U, 70U, 71U,
72U, 73U, 74U, 75U, 76U, 77U, 78U, 79U,
80U
}; };
const uint8_t hopPattern_10KBPS_10MS[L1_FRAME_10KBPS_10MS_HOPS] = const uint8_t hopPattern_128KBPS_4MS[L1_FRAME_128KBPS_4MS_HOPS] =
{ {
80U 80U, 16U, 17U, 65U, 60U, 54U, 31U, 15U,
6U, 19U, 79U, 52U, 29U, 42U, 23U, 59U,
60U, 58U, 76U, 67U, 31U, 76U, 77U, 79U,
79U, 14U, 61U, 5U, 71U, 50U, 32U, 77U,
60U,
}; };
const uint8_t hopPattern_10KBPS_20MS[L1_FRAME_10KBPS_20MS_HOPS] = const uint8_t hopPattern_512KBPS_4MS[L1_FRAME_512KBPS_4MS_HOPS] =
{ {
80U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, 80U, 62U, 40U, 66U, 65U, 33U, 55U, 33U,
8U, 9U, 10U 57U, 11U, 37U, 45U, 5U, 69U, 77U, 54U,
37U, 63U, 14U, 64U, 76U, 31U, 45U, 52U,
40U, 20U, 20U, 32U, 0U, 60U, 23U, 19U,
15U, 38U, 62U, 18U,
}; };
const uint8_t hopPattern_40KBPS_10MS[L1_FRAME_40KBPS_10MS_HOPS] = const uint8_t hopPattern_2MBPS_4MS[L1_FRAME_2MBPS_4MS_HOPS] =
{ {
0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, 0U, 13U, 37U, 44U, 16U, 0U, 59U, 50U,
8U, 69U, 70U, 58U, 14U, 9U, 72U, 27U, 25U,
}; 21U, 76U, 20U, 35U, 30U, 58U, 22U, 59U,
48U, 33U, 8U, 7U, 41U, 12U, 44U, 79U,
const uint8_t hopPattern_40KBPS_20MS[L1_FRAME_40KBPS_20MS_HOPS] = 77U, 38U, 76U, 75U, 48U, 56U,
{
0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U,
8U, 9U, 10U, 11U, 12U, 13U, 14U, 15U,
16U, 17U, 18U
};
const uint8_t hopPattern_200KBPS_5MS[L1_FRAME_200KBPS_5MS_HOPS] =
{
0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U,
8U, 9U, 10U, 11U, 12U, 13U, 14U, 15U,
16U, 17U, 18U, 19U
};
const uint8_t hopPattern_1M2BPS_5MS[L1_FRAME_1M2BPS_5MS_HOPS] =
{
0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U,
8U, 9U, 10U, 11U, 12U, 13U, 14U, 15U,
16U, 17U, 18U, 19U
}; };
/** @} PhysicalLayer_AntennaConfig_Constants*/ /** @} PhysicalLayer_AntennaConfig_Constants*/
@@ -201,226 +253,173 @@ void Phy_AntConfigInit(PHY_ANT_CONFIG *antConfig)
{ {
ASSERT(antConfig != NULL); ASSERT(antConfig != NULL);
antConfig->ctrlWord = CTRL_WORD_DEFAULT;
antConfig->antMode = ATN_MODE_DEFAULT;
// FIXME: Dummy default value. // FIXME: Dummy default value.
// off axis angle setting for (uint8_t ii = 0; ii < L1_ANT_NUM; ii ++)
antConfig->oaxis[0] = 0; {
antConfig->oaxis[1] = 0; for (uint8_t jj = 0; jj < L1_ANT_CH_NUM; jj ++)
// round axis angle setting {
antConfig->raxis[0] = 0; antConfig->rfNormComp[ii][jj] = 0;
antConfig->raxis[1] = 0; antConfig->rfNormIdpAttn[ii][jj] = 0;
// *********************** }
antConfig->rfNormComAttn[ii] = 0;
antConfig->rfFreq[ii][0] = (uint8_t)(DEFAULT_CENTRTAL_FREQ);
antConfig->rfFreq[ii][1] = (uint8_t)(DEFAULT_CENTRTAL_FREQ >> 8);
}
antConfig->antFreq[0] = (uint8_t)(DEFAULT_CENTRTAL_FREQ); for (uint8_t ii = 0; ii < L1_ANT_CH_NUM; ii ++)
antConfig->antFreq[1] = (uint8_t)(DEFAULT_CENTRTAL_FREQ >> 8); {
antConfig->rfAntiAttn[ii] = 0;
}
// FIXME: Dummy default value. antConfig->antControl.antMode = ANT_MODE_RX_NORMAL;
// trSelect antConfig->antControl.antRx1En = ANT_DISABLE;
antConfig->trSlect = 0; antConfig->antControl.antRx2En = ANT_DISABLE;
// Antenna attenuation setting antConfig->antControl.antRx3En = ANT_DISABLE;
antConfig->antAtt = 0; antConfig->antControl.antTx1En = ANT_DISABLE;
// phase setting antConfig->antControl.antTx2En = ANT_DISABLE;
antConfig->phase = 0; antConfig->antControl.antTx3En = ANT_DISABLE;
// ***********************
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 * @brief Set tx antenna index
* *
* @param instPtr pointer to physical layer instance * @param instPtr pointer to physical layer instance
* @param mode new antenna mode * @param antTxIndex target tx antenna index
* *
* @return None. * @return None.
* *
******************************************************************************/ ******************************************************************************/
void Phy_AntConfigMode(PHY_INST *instPtr, PHY_ANT_MODE mode) void Phy_SetTxAntIndex(PHY_INST *instPtr, PHY_ANT_INDEX antIndex)
{ {
ASSERT(instPtr != NULL); ASSERT(instPtr != NULL);
uint8_t config = instPtr->antConfig.antMode & ANT_MODE_BEAM_MASK;
switch (mode) switch (antIndex)
{ {
case PHY_ANT_MODE_STANDBY: case PHY_ANT_INDEX_1:
config |= ANT_POWER_STANDBY; instPtr->antConfig.antControl.antTx1En = ANT_ENABLE;
instPtr->antConfig.antControl.antTx2En = ANT_DISABLE;
instPtr->antConfig.antControl.antTx3En = ANT_DISABLE;
break; break;
case PHY_ANT_MODE_POWER_LOW: case PHY_ANT_INDEX_2:
config |= ANT_POWER_LOW; instPtr->antConfig.antControl.antTx1En = ANT_DISABLE;
instPtr->antConfig.antControl.antTx2En = ANT_ENABLE;
instPtr->antConfig.antControl.antTx3En = ANT_DISABLE;
break; break;
case PHY_ANT_MODE_POWER_FULL: case PHY_ANT_INDEX_3:
config |= ANT_POWER_FULL; instPtr->antConfig.antControl.antTx1En = ANT_DISABLE;
instPtr->antConfig.antControl.antTx2En = ANT_DISABLE;
instPtr->antConfig.antControl.antTx3En = ANT_ENABLE;
break; break;
default: default:
DBG_ERROR("Unknown antenna mode: %" PRIu8 ", remain previous mode.\n", mode); instPtr->antConfig.antControl.antTx1En = ANT_DISABLE;
return; instPtr->antConfig.antControl.antTx2En = ANT_DISABLE;
instPtr->antConfig.antControl.antTx3En = ANT_DISABLE;
break;
} }
instPtr->phyLog.antMode = mode; }
instPtr->antConfig.antMode = config;
/*****************************************************************************/
/**
* @brief Set rx antenna index
*
* @param instPtr pointer to physical layer instance
* @param antRxIndex target rx antenna index
*
* @return None.
*
******************************************************************************/
void Phy_SetRxAntIndex(PHY_INST *instPtr, PHY_ANT_INDEX antRxIndex)
{
ASSERT(instPtr != NULL);
if (instPtr->antConfig.antControl.antMode == ANT_MODE_RX_AJ)
{
switch (antRxIndex)
{
case PHY_ANT_INDEX_1:
instPtr->antConfig.antControl.antRx1En = ANT_ENABLE;
instPtr->antConfig.antControl.antRx2En = ANT_DISABLE;
instPtr->antConfig.antControl.antRx3En = ANT_DISABLE;
break;
case PHY_ANT_INDEX_2:
instPtr->antConfig.antControl.antRx1En = ANT_DISABLE;
instPtr->antConfig.antControl.antRx2En = ANT_ENABLE;
instPtr->antConfig.antControl.antRx3En = ANT_DISABLE;
break;
case PHY_ANT_INDEX_3:
instPtr->antConfig.antControl.antRx1En = ANT_DISABLE;
instPtr->antConfig.antControl.antRx2En = ANT_DISABLE;
instPtr->antConfig.antControl.antRx3En = ANT_ENABLE;
break;
default:
instPtr->antConfig.antControl.antRx1En = ANT_DISABLE;
instPtr->antConfig.antControl.antRx2En = ANT_DISABLE;
instPtr->antConfig.antControl.antRx3En = ANT_DISABLE;
break;
}
}
else
{
instPtr->antConfig.antControl.antRx1En = ANT_DISABLE;
instPtr->antConfig.antControl.antRx2En = ANT_DISABLE;
instPtr->antConfig.antControl.antRx3En = ANT_DISABLE;
}
}
/*****************************************************************************/
/**
* @brief Set rx mode to normal or anti-jamming.
*
* @param instPtr pointer to physical layer instance
* @param antRxMode target rx mode
*
* @return None.
*
******************************************************************************/
void Phy_SetRxMode(PHY_INST *instPtr, PHY_ANT_RX_MODE antRxMode)
{
ASSERT(instPtr != NULL);
instPtr->antConfig.antControl.antMode = antRxMode;
// Sync logs to system monitor // Sync logs to system monitor
SysMonitor_UpdatePhysicalLayerLog(&(instPtr->phyLog)); SysMonitor_UpdatePhysicalLayerLog(&(instPtr->phyLog));
} }
/*****************************************************************************/ /*****************************************************************************/
/** /**
* @brief Update antenna beam table * @brief Update antenna index of the next slot.
*
* @param instPtr pointer to physical layer instance
* @param table new beam table
* @param offset table offset
*
* @return None
*
******************************************************************************/
void Phy_SetBeamTable(PHY_INST *instPtr, PHY_ANT_ANGLE *table, uint32_t offset)
{
ASSERT(instPtr != NULL);
ASSERT(table != NULL);
for (int i = 0; i < L1_NUM_ANT_NRRW_PATTERN; i++)
{
instPtr->antNrrwPattern[i] = table[(i + offset) % L1_NUM_ANT_NRRW_PATTERN];
}
memcpy((uint32_t *)instPtr->antInfoAddr, instPtr->antNrrwPattern,
L1_NUM_ANT_NRRW_PATTERN * sizeof(PHY_ANT_ANGLE));
}
/*****************************************************************************/
/**
* @brief Update antenna point direction using predefined beam table
*
* @param instPtr pointer to physical layer instance
* @param beamNo new beam index
*
* @return SUCCESS.
* FAILURE beamNo exceeds the table size
*
******************************************************************************/
int32_t Phy_SetBeamNo(PHY_INST *instPtr, size_t beamNo, PHY_ANT_BEAM_WIDTH beamWidth)
{
ASSERT(instPtr != NULL);
if (beamWidth == PHY_ANT_BEAM_16)
{
if (beamNo >= L1_NUM_ANT_NRRW_PATTERN)
{
return FAILURE;
}
else
{
instPtr->beamNo.next = beamNo;
instPtr->antConfig.oaxis[0] = (uint8_t)(instPtr->antNrrwPattern[beamNo].oaxis >> 8);
instPtr->antConfig.oaxis[1] = (uint8_t)(instPtr->antNrrwPattern[beamNo].oaxis);
instPtr->antConfig.raxis[0] = (uint8_t)(instPtr->antNrrwPattern[beamNo].raxis >> 8);
instPtr->antConfig.raxis[1] = (uint8_t)(instPtr->antNrrwPattern[beamNo].raxis);
return SUCCESS;
}
}
else
{
// Beam number assign not support.
// Assign default angle (0,0)
instPtr->beamNo.next = 0;
instPtr->antConfig.oaxis[0] = 0;
instPtr->antConfig.oaxis[1] = 0;
instPtr->antConfig.raxis[0] = 0;
instPtr->antConfig.raxis[1] = 0;
DBG_WARNING("Using default beam number...\n");
return SUCCESS;
}
}
/*****************************************************************************/
/**
* @brief Update antenna beam width setting
* *
* @param instPtr pointer to physical layer instance * @param instPtr pointer to physical layer instance
* @param beamWidth new beam width * @param AntIndex antenna index
* *
* @return SUCCESS. * @return SUCCESS.
* EPARAM * EPARAM - antenna index exceeds predefined range
* *
******************************************************************************/ ******************************************************************************/
int32_t Phy_SetBeamWidth(PHY_INST *instPtr, PHY_ANT_BEAM_WIDTH beamWidth) int32_t Phy_SetAntIndex(PHY_INST *instPtr, PHY_ANT_INDEX antIndex)
{ {
ASSERT(instPtr != NULL); ASSERT(instPtr != NULL);
uint8_t beamConfig = instPtr->antConfig.antMode & (~ANT_MODE_BEAM_MASK);
switch (beamWidth) if (antIndex < 0 || antIndex >= L1_ANT_NUM)
{ {
case PHY_ANT_BEAM_120: DBG_ERROR("Antenna index out of range: %" PRIu8 ". \n", antIndex);
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; return EPARAM;
} }
instPtr->antConfig.antMode = beamConfig; DBG_INFO("Set new antenna index: %" PRId8 "\n", antIndex);
instPtr->beamWd.next = beamWidth; instPtr->antIndex.next = antIndex;
Phy_SetTxAntIndex(instPtr, antIndex);
Phy_SetRxAntIndex(instPtr, antIndex);
return SUCCESS; return SUCCESS;
} }
/*****************************************************************************/
/** /**
* @brief Set antenna to a specific direction * @brief Get antenna index of the next slot.
* */
* @param instPtr pointer to physical layer instance inline size_t Phy_GetNextAntIndex(PHY_INST *instPtr)
* @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); ASSERT(instPtr != NULL);
uint16_t offAxDeg = 0; return instPtr->antIndex.next;
uint16_t rndAxDeg = 0;
offAxDeg = (offAx >= 0) ? (((int32_t)(offAx * 180.0 / ANT_PI)) % 360) : (((int32_t)(offAx * 180.0 / ANT_PI)) % 360 + 360);
rndAxDeg = (rndAx >= 0) ? (((int32_t)(rndAx * 180.0 / ANT_PI)) % 360) : (((int32_t)(rndAx * 180.0 / ANT_PI)) % 360 + 360);
if (offAxDeg > 60)
{
DBG_ERROR("Angle out of range, off axis angle: %" PRIu16 " (should be 0~60), round axis angle: %" PRIu16 " (should be 0~360).\n",
offAxDeg, rndAxDeg);
return EPARAM;
}
offAxDeg = offAxDeg * 10;
rndAxDeg = rndAxDeg * 10;
instPtr->antConfig.oaxis[0] = (uint8_t)(offAxDeg >> 8);
instPtr->antConfig.oaxis[1] = (uint8_t)offAxDeg;
instPtr->antConfig.raxis[0] = (uint8_t)(rndAxDeg >> 8);
instPtr->antConfig.raxis[1] = (uint8_t)rndAxDeg;
return SUCCESS;
} }
/** @} PhysicalLayer_AntennaControl*/ /** @} PhysicalLayer_AntennaControl*/
@@ -34,54 +34,42 @@
* @{ * @{
*/ */
#define PHY_TIME_WORD_H_MAX UINT32_MAX #define PHY_TIME_WORD_H_MAX UINT32_MAX
#define PHY_TIME_WORD_L_MAX 0x0007A120 // 5ms/10ns #define PHY_TIME_WORD_L_MAX 200000U // 2 ms/10 ns
#define L1_FRAME_LEN_MAX (8192 / 8) // byte #define L1_FRAME_LEN_MAX (16384 / 8) // byte
#define L1_FRAME_2KBPS_20MS_LEN 0 // byte #define L1_FRAME_ADV_24MS_LEN (520 / 8) // byte
#define L1_FRAME_2KBPS_100MS_LEN (312 / 8) // byte #define L1_FRAME_ACK_8MS_LEN (520 / 8) // byte
#define L1_FRAME_10KBPS_10MS_LEN 0 // byte #define L1_FRAME_128KBPS_4MS_LEN (784 / 8) // byte
#define L1_FRAME_10KBPS_20MS_LEN (232 / 8) // byte #define L1_FRAME_512KBPS_4MS_LEN (2584 / 8) // byte
#define L1_FRAME_40KBPS_20MS_LEN (2152 / 8) // byte #define L1_FRAME_2MBPS_4MS_LEN (10224 / 8) // byte
#define L1_FRAME_40KBPS_10MS_LEN (712 / 8) // byte
#define L1_FRAME_200KBPS_5MS_LEN (2040 / 8) // byte
#define L1_FRAME_1M2BPS_5MS_LEN (8176 / 8) // byte
#define L1_FRAME_2KBPS_20MS_COMP 1841158 // *10ns(Timer_L) #define L1_FRAME_ADV_24MS_COMP 1841158 // FIXME: need update, *10ns(Timer_L)
#define L1_FRAME_2KBPS_100MS_COMP 1841158 // *10ns(Timer_L) #define L1_FRAME_ACK_8MS_COMP 1841158 // FIXME: need update, *10ns(Timer_L)
#define L1_FRAME_10KBPS_10MS_COMP 850950 // *10ns(Timer_L) #define L1_FRAME_128KBPS_4MS_COMP 850950 // FIXME: need update, *10ns(Timer_L)
#define L1_FRAME_10KBPS_20MS_COMP 850950 // *10ns(Timer_L) #define L1_FRAME_512KBPS_4MS_COMP 850950 // FIXME: need update, *10ns(Timer_L)
#define L1_FRAME_40KBPS_20MS_COMP 111485 // *10ns(Timer_L) #define L1_FRAME_2MBPS_4MS_COMP 111485 // FIXME: need update, *10ns(Timer_L)
#define L1_FRAME_40KBPS_10MS_COMP 111485 // *10ns(Timer_L)
#define L1_FRAME_200KBPS_5MS_COMP 22493 // *10ns(Timer_L)
#define L1_FRAME_1M2BPS_5MS_COMP 22493 // *10ns(Timer_L)
#define L1_ANTCONFIG_MAX_LEN 8192 #define L1_ANTCONFIG_MAX_LEN 8192
#define L1_TXRXDATA_MAX_LEN 2048 #define L1_TXRXDATA_MAX_LEN 16384
#define ANT_COINFO_LEN 32 // bytes #define ANT_COINFO_LEN 32 // bytes, antenna configuration length of each hop
#define ATTN_DEFAULT 0 #define ATTN_DEFAULT 0
#define ATTN_2KBPS_100MS ATTN_DEFAULT #define ATTN_ADV_24MS ATTN_DEFAULT
#define ATTN_2KBPS_20MS ATTN_DEFAULT #define ATTN_ACK_8MS ATTN_DEFAULT
#define ATTN_10KBPS_10MS 12 #define ATTN_128KBPS_4MS ATTN_DEFAULT
#define ATTN_10KBPS_20MS 12 #define ATTN_512KBPS_4MS ATTN_DEFAULT
#define ATTN_40KBPS_10MS 0 #define ATTN_2MBPS_4MS ATTN_DEFAULT
#define ATTN_40KBPS_20MS 0
#define ATTN_200KBPS_5MS ATTN_DEFAULT
#define ATTN_1M2BPS_5MS ATTN_DEFAULT
/** @} PhysicalLayer_Private_Constants*/ /** @} PhysicalLayer_Private_Constants*/
/************************** Variable Definitions *****************************/ /************************** Variable Definitions *****************************/
extern const uint16_t freqTable[L1_FRAME_MAX_HOPS]; extern const uint16_t freqTable[L1_FRAME_MAX_HOPS];
extern const int16_t antCalTable[L1_FRAME_MAX_HOPS][L1_ANT_NUM_CH]; extern const int16_t antCalTable[L1_ANT_NUM][L1_FRAME_MAX_HOPS][L1_ANT_CH_NUM];
extern const uint8_t hopPattern_2KBPS_20MS[L1_FRAME_2KBPS_20MS_HOPS]; extern const uint8_t hopPattern_ADV_24MS[L1_FRAME_ADV_24MS_HOPS];
extern const uint8_t hopPattern_2KBPS_100MS[L1_FRAME_2KBPS_100MS_HOPS]; extern const uint8_t hopPattern_ACK_8MS[L1_FRAME_ACK_8MS_HOPS];
extern const uint8_t hopPattern_10KBPS_10MS[L1_FRAME_10KBPS_10MS_HOPS]; extern const uint8_t hopPattern_128KBPS_4MS[L1_FRAME_128KBPS_4MS_HOPS];
extern const uint8_t hopPattern_10KBPS_20MS[L1_FRAME_10KBPS_20MS_HOPS]; extern const uint8_t hopPattern_512KBPS_4MS[L1_FRAME_512KBPS_4MS_HOPS];
extern const uint8_t hopPattern_40KBPS_10MS[L1_FRAME_40KBPS_10MS_HOPS]; extern const uint8_t hopPattern_2MBPS_4MS[L1_FRAME_2MBPS_4MS_HOPS];
extern const uint8_t hopPattern_40KBPS_20MS[L1_FRAME_40KBPS_20MS_HOPS];
extern const uint8_t hopPattern_200KBPS_5MS[L1_FRAME_200KBPS_5MS_HOPS];
extern const uint8_t hopPattern_1M2BPS_5MS[L1_FRAME_1M2BPS_5MS_HOPS];
/***************** Macros (Inline Functions) Definitions *********************/ /***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/ /************************** Function Prototypes ******************************/
@@ -227,22 +215,16 @@ uint32_t Phy_GetFrameLen(L1_FRAME_TYPE frameType)
{ {
switch (frameType) switch (frameType)
{ {
case L1_2KBPS_20MS_FRAME: case L1_FRAME_ADV_24MS:
return L1_FRAME_2KBPS_20MS_LEN; return L1_FRAME_ADV_24MS_LEN;
case L1_2KBPS_100MS_FRAME: case L1_FRAME_ACK_8MS:
return L1_FRAME_2KBPS_100MS_LEN; return L1_FRAME_ACK_8MS_LEN;
case L1_10KBPS_10MS_FRAME: case L1_FRAME_128KBPS_4MS:
return L1_FRAME_10KBPS_10MS_LEN; return L1_FRAME_128KBPS_4MS_LEN;
case L1_10KBPS_20MS_FRAME: case L1_FRAME_512KBPS_4MS:
return L1_FRAME_10KBPS_20MS_LEN; return L1_FRAME_512KBPS_4MS_LEN;
case L1_40KBPS_20MS_FRAME: case L1_FRAME_2MBPS_4MS:
return L1_FRAME_40KBPS_20MS_LEN; return L1_FRAME_2MBPS_4MS_LEN;
case L1_40KBPS_10MS_FRAME:
return L1_FRAME_40KBPS_10MS_LEN;
case L1_200KBPS_5MS_FRAME:
return L1_FRAME_200KBPS_5MS_LEN;
case L1_1M2BPS_5MS_FRAME:
return L1_FRAME_1M2BPS_5MS_LEN;
default: default:
return L1_FRAME_NONE_LEN; return L1_FRAME_NONE_LEN;
} }
@@ -263,24 +245,18 @@ uint32_t Phy_GetHopLength(L1_FRAME_TYPE frameType)
{ {
switch (frameType) switch (frameType)
{ {
case L1_2KBPS_20MS_FRAME: case L1_FRAME_ADV_24MS:
return L1_FRAME_2KBPS_20MS_HOPS; return L1_FRAME_ADV_24MS_HOPS;
case L1_2KBPS_100MS_FRAME: case L1_FRAME_ACK_8MS:
return L1_FRAME_2KBPS_100MS_HOPS; return L1_FRAME_ACK_8MS_HOPS;
case L1_10KBPS_10MS_FRAME: case L1_FRAME_128KBPS_4MS:
return L1_FRAME_10KBPS_10MS_HOPS; return L1_FRAME_128KBPS_4MS_HOPS;
case L1_10KBPS_20MS_FRAME: case L1_FRAME_512KBPS_4MS:
return L1_FRAME_10KBPS_20MS_HOPS; return L1_FRAME_512KBPS_4MS_HOPS;
case L1_40KBPS_20MS_FRAME: case L1_FRAME_2MBPS_4MS:
return L1_FRAME_40KBPS_20MS_HOPS; return L1_FRAME_2MBPS_4MS_HOPS;
case L1_40KBPS_10MS_FRAME:
return L1_FRAME_40KBPS_10MS_HOPS;
case L1_200KBPS_5MS_FRAME:
return L1_FRAME_200KBPS_5MS_HOPS;
case L1_1M2BPS_5MS_FRAME:
return L1_FRAME_1M2BPS_5MS_HOPS;
default: default:
return L1_FRAME_NONE_LEN; return L1_FRAME_NONE_HOPS;
} }
} }
@@ -298,24 +274,18 @@ uint32_t Phy_GetTimeComp(L1_FRAME_TYPE frameType)
{ {
switch (frameType) switch (frameType)
{ {
case L1_2KBPS_20MS_FRAME: case L1_FRAME_ADV_24MS:
return L1_FRAME_2KBPS_20MS_COMP; return L1_FRAME_ADV_24MS_COMP;
case L1_2KBPS_100MS_FRAME: case L1_FRAME_ACK_8MS:
return L1_FRAME_2KBPS_100MS_COMP; return L1_FRAME_ACK_8MS_COMP;
case L1_10KBPS_10MS_FRAME: case L1_FRAME_128KBPS_4MS:
return L1_FRAME_10KBPS_10MS_COMP; return L1_FRAME_128KBPS_4MS_COMP;
case L1_10KBPS_20MS_FRAME: case L1_FRAME_512KBPS_4MS:
return L1_FRAME_10KBPS_20MS_COMP; return L1_FRAME_512KBPS_4MS_COMP;
case L1_40KBPS_20MS_FRAME: case L1_FRAME_2MBPS_4MS:
return L1_FRAME_40KBPS_20MS_COMP; return L1_FRAME_2MBPS_4MS_COMP;
case L1_40KBPS_10MS_FRAME:
return L1_FRAME_40KBPS_10MS_COMP;
case L1_200KBPS_5MS_FRAME:
return L1_FRAME_200KBPS_5MS_COMP;
case L1_1M2BPS_5MS_FRAME:
return L1_FRAME_1M2BPS_5MS_COMP;
default: default:
return L1_FRAME_NONE_LEN; return L1_FRAME_NONE_COMP;
} }
} }
@@ -325,7 +295,7 @@ uint32_t Phy_GetTimeComp(L1_FRAME_TYPE frameType)
* *
* @param instPtr A pointer to physical layer control instance. * @param instPtr A pointer to physical layer control instance.
* *
* @return Layer2 frame type. Refer "frame_def.h" * @return Layer1 frame type. Refer "frame_def.h"
* *
******************************************************************************/ ******************************************************************************/
inline L1_FRAME_TYPE Phy_GetLastRecvFrameType(PHY_INST *instPtr) inline L1_FRAME_TYPE Phy_GetLastRecvFrameType(PHY_INST *instPtr)
@@ -333,29 +303,23 @@ inline L1_FRAME_TYPE Phy_GetLastRecvFrameType(PHY_INST *instPtr)
ASSERT(instPtr != NULL); ASSERT(instPtr != NULL);
if (Phy_IsFrameReceived(instPtr) == false) if (Phy_IsFrameReceived(instPtr) == false)
{ {
return L1_NONE_FRAME; return L1_FRAME_NONE;
} }
uint32_t frame_type = (PhyRead(instPtr, COASE_FREQEST) & COASE_TYPE_MASK); uint32_t frame_type = (PhyRead(instPtr, COASE_FREQEST) & COASE_TYPE_MASK);
switch (frame_type) switch (frame_type)
{ {
case COASE_TYPE_2KBPS_20MS: case COASE_TYPE_ADV_24MS:
return L1_2KBPS_20MS_FRAME; return L1_FRAME_ADV_24MS;
case COASE_TYPE_2KBPS_100MS: case COASE_TYPE_ACK_8MS:
return L1_2KBPS_100MS_FRAME; return L1_FRAME_ACK_8MS;
case COASE_TYPE_10KBPS_10MS: case COASE_TYPE_128KBPS_4MS:
return L1_10KBPS_10MS_FRAME; return L1_FRAME_128KBPS_4MS;
case COASE_TYPE_10KBPS_20MS: case COASE_TYPE_512KBPS_4MS:
return L1_10KBPS_20MS_FRAME; return L1_FRAME_512KBPS_4MS;
case COASE_TYPE_40KBPS_20MS: case COASE_TYPE_2MBPS_4MS:
return L1_40KBPS_20MS_FRAME; return L1_FRAME_2MBPS_4MS;
case COASE_TYPE_40KBPS_10MS:
return L1_40KBPS_10MS_FRAME;
case COASE_TYPE_200KBPS_5MS:
return L1_200KBPS_5MS_FRAME;
case COASE_TYPE_1M2BPS_5MS:
return L1_1M2BPS_5MS_FRAME;
default: default:
return L1_NONE_FRAME; return L1_FRAME_NONE;
} }
} }
@@ -365,7 +329,7 @@ inline L1_FRAME_TYPE Phy_GetLastRecvFrameType(PHY_INST *instPtr)
* *
* @param instPtr A pointer to physical layer control instance. * @param instPtr A pointer to physical layer control instance.
* *
* @return Layer2 frame type. Refer "frame_def.h" * @return Layer1 frame type. Refer "frame_def.h"
* *
******************************************************************************/ ******************************************************************************/
inline L1_FRAME_TYPE Phy_GetLastSendFrameType(PHY_INST *instPtr) inline L1_FRAME_TYPE Phy_GetLastSendFrameType(PHY_INST *instPtr)
@@ -373,7 +337,7 @@ inline L1_FRAME_TYPE Phy_GetLastSendFrameType(PHY_INST *instPtr)
ASSERT(instPtr != NULL); ASSERT(instPtr != NULL);
if (instPtr->tor.last != PHY_TOR_TX) if (instPtr->tor.last != PHY_TOR_TX)
{ {
return L1_NONE_FRAME; return L1_FRAME_NONE;
} }
return instPtr->frameType.last; return instPtr->frameType.last;
} }
@@ -424,9 +388,8 @@ int32_t Phy_Init(PHY_INST **instPtr, PHY_CONFIG *phyConfig)
Phy_AntConfigInit(&((*instPtr)->antConfig)); Phy_AntConfigInit(&((*instPtr)->antConfig));
memset(&((*instPtr))->tor, PHY_TOR_SUSPEND, sizeof(PHY_RCD)); memset(&((*instPtr))->tor, PHY_TOR_SUSPEND, sizeof(PHY_RCD));
memset(&((*instPtr)->frameType), L1_NONE_FRAME, sizeof(PHY_RCD)); memset(&((*instPtr)->frameType), L1_FRAME_NONE, sizeof(PHY_RCD));
memset(&((*instPtr)->beamNo), (int32_t)L1_INIT_BEAM_NO, sizeof(PHY_RCD)); memset(&((*instPtr)->antIndex), (int32_t)L1_INIT_ANT_IDX, sizeof(PHY_RCD));
memset(&((*instPtr)->beamWd), (int32_t)L1_INIT_ANT_WD, sizeof(PHY_RCD));
memset(&((*instPtr)->hwSate), 0x00, sizeof(HWSTATE)); memset(&((*instPtr)->hwSate), 0x00, sizeof(HWSTATE));
memset(&((*instPtr)->phyLog), 0x00, sizeof(PHYLOG)); memset(&((*instPtr)->phyLog), 0x00, sizeof(PHYLOG));
@@ -509,44 +472,6 @@ int32_t Phy_Init(PHY_INST **instPtr, PHY_CONFIG *phyConfig)
(*instPtr)->recvDataAddr = rxDataBram.Config.MemBaseAddress; (*instPtr)->recvDataAddr = rxDataBram.Config.MemBaseAddress;
(*instPtr)->sendDataAddr = txDataBram.Config.MemBaseAddress; (*instPtr)->sendDataAddr = txDataBram.Config.MemBaseAddress;
// Setup antenna presets
XBram antInfoBram;
if (phyConfig->antInfoBramId != -1)
{
bramConfigPtr = XBram_LookupConfig(phyConfig->antInfoBramId);
if (bramConfigPtr == NULL)
{
Phy_Destroy(*instPtr);
return EDCONF;
}
Status = XBram_CfgInitialize(&antInfoBram, bramConfigPtr,
bramConfigPtr->CtrlBaseAddress);
if (Status != SUCCESS)
{
Phy_Destroy(*instPtr);
return Status;
}
/*
* Execute the BRAM driver self test.
*/
Status = XBram_SelfTest(&antInfoBram, 0);
if (Status != SUCCESS)
{
Phy_Destroy(*instPtr);
return Status;
}
(*instPtr)->antInfoAddr = antInfoBram.Config.MemBaseAddress;
uint32_t phyMainCtrl = PhyRead(*instPtr, PHY_MAIN_CTRL);
phyMainCtrl &= ~PHY_MAIN_CTRL_NSCAN_MASK;
phyMainCtrl |= PHY_MAIN_CTRL_NSCAN_MASK &
(L1_NUM_ANT_NRRW_PATTERN << PHY_MAIN_CTRL_NSCAN_SHIFT);
PhyWrite(*instPtr, PHY_MAIN_CTRL, phyMainCtrl);
}
else
{
(*instPtr)->antInfoAddr = (uintptr_t)NULL;
}
/* Initialize the XAdc driver. */ /* Initialize the XAdc driver. */
XAdcPs_Config *xadcConfigPtr; XAdcPs_Config *xadcConfigPtr;
@@ -597,7 +522,7 @@ int32_t Phy_Init(PHY_INST **instPtr, PHY_CONFIG *phyConfig)
/*****************************************************************************/ /*****************************************************************************/
/** /**
* @brief Destroy physical layer inctance, free allocated memory. * @brief Destroy physical layer instance, free allocated memory.
* *
* @param instPtr a pointer to physical instance * @param instPtr a pointer to physical instance
* *
@@ -685,11 +610,8 @@ int32_t Phy_SetMode(PHY_INST *instPtr, PHY_MODE modeCod)
case PHY_MODE_LISTEN: case PHY_MODE_LISTEN:
phyMainCtrl |= PHY_MAIN_CTRL_MODE_LISTEN; phyMainCtrl |= PHY_MAIN_CTRL_MODE_LISTEN;
break; break;
case PHY_MODE_SCHEDULE: case PHY_MODE_POLL:
phyMainCtrl |= PHY_MAIN_CTRL_MODE_SCHEDULE; phyMainCtrl |= PHY_MAIN_CTRL_MODE_POLL;
break;
case PHY_MODE_PULL:
phyMainCtrl |= PHY_MAIN_CTRL_MODE_PULL;
break; break;
default: default:
return FAILURE; return FAILURE;
@@ -773,53 +695,30 @@ int32_t Phy_SetupNextSlot(PHY_INST *instPtr, PHY_TOR_TYPE txrxMode,
} }
switch (frameType) switch (frameType)
{ {
case L1_2KBPS_20MS_FRAME: case L1_FRAME_ADV_24MS:
phyModeCtrl |= PHY_MODE_CTRL_FRAME_2KBPS_20MS; phyModeCtrl |= PHY_MODE_CTRL_FRAME_ADV_24MS;
hopNum = L1_FRAME_2KBPS_20MS_HOPS; hopNum = L1_FRAME_ADV_24MS_HOPS;
hopPattern = hopPattern_2KBPS_20MS; hopPattern = hopPattern_ADV_24MS;
instPtr->antConfig.rfTxMgc = ATTN_2KBPS_20MS;
break; break;
case L1_2KBPS_100MS_FRAME: case L1_FRAME_ACK_8MS:
phyModeCtrl |= PHY_MODE_CTRL_FRAME_2KBPS_100MS; phyModeCtrl |= PHY_MODE_CTRL_FRAME_ACK_8MS;
hopNum = L1_FRAME_2KBPS_100MS_HOPS; hopNum = L1_FRAME_ACK_8MS_HOPS;
hopPattern = hopPattern_2KBPS_100MS; hopPattern = hopPattern_ACK_8MS;
instPtr->antConfig.rfTxMgc = ATTN_2KBPS_100MS;
break; break;
case L1_10KBPS_10MS_FRAME: case L1_FRAME_128KBPS_4MS:
phyModeCtrl |= PHY_MODE_CTRL_FRAME_10KBPS_10MS; phyModeCtrl |= PHY_MODE_CTRL_FRAME_128KBPS_4MS;
hopNum = L1_FRAME_10KBPS_20MS_HOPS; hopNum = L1_FRAME_128KBPS_4MS_HOPS;
hopPattern = hopPattern_10KBPS_20MS; hopPattern = hopPattern_128KBPS_4MS;
instPtr->antConfig.rfTxMgc = ATTN_10KBPS_10MS;
break; break;
case L1_10KBPS_20MS_FRAME: case L1_FRAME_512KBPS_4MS:
phyModeCtrl |= PHY_MODE_CTRL_FRAME_10KBPS_20MS; phyModeCtrl |= PHY_MODE_CTRL_FRAME_512KBPS_4MS;
hopNum = L1_FRAME_10KBPS_20MS_HOPS; hopNum = L1_FRAME_512KBPS_4MS_HOPS;
hopPattern = hopPattern_10KBPS_20MS; hopPattern = hopPattern_512KBPS_4MS;
instPtr->antConfig.rfTxMgc = ATTN_10KBPS_20MS;
break; break;
case L1_40KBPS_20MS_FRAME: case L1_FRAME_2MBPS_4MS:
phyModeCtrl |= PHY_MODE_CTRL_FRAME_40KBPS_20MS; phyModeCtrl |= PHY_MODE_CTRL_FRAME_2MBPS_4MS;
hopNum = L1_FRAME_40KBPS_20MS_HOPS; hopNum = L1_FRAME_2MBPS_4MS_HOPS;
hopPattern = hopPattern_40KBPS_20MS; hopPattern = hopPattern_2MBPS_4MS;
instPtr->antConfig.rfTxMgc = ATTN_40KBPS_20MS;
break;
case L1_40KBPS_10MS_FRAME:
phyModeCtrl |= PHY_MODE_CTRL_FRAME_40KBPS_10MS;
hopNum = L1_FRAME_40KBPS_10MS_HOPS;
hopPattern = hopPattern_40KBPS_10MS;
instPtr->antConfig.rfTxMgc = ATTN_40KBPS_10MS;
break;
case L1_200KBPS_5MS_FRAME:
phyModeCtrl |= PHY_MODE_CTRL_FRAME_200KBPS_5MS;
hopNum = L1_FRAME_200KBPS_5MS_HOPS;
hopPattern = hopPattern_200KBPS_5MS;
instPtr->antConfig.rfTxMgc = ATTN_200KBPS_5MS;
break;
case L1_1M2BPS_5MS_FRAME:
phyModeCtrl |= PHY_MODE_CTRL_FRAME_1M2BPS_5MS;
hopNum = L1_FRAME_1M2BPS_5MS_HOPS;
hopPattern = hopPattern_1M2BPS_5MS;
instPtr->antConfig.rfTxMgc = ATTN_1M2BPS_5MS;
break; break;
default: default:
return EPARAM; return EPARAM;
@@ -831,36 +730,24 @@ int32_t Phy_SetupNextSlot(PHY_INST *instPtr, PHY_TOR_TYPE txrxMode,
// TODO: Set antenna stand by, when suspend. // TODO: Set antenna stand by, when suspend.
const uint8_t *dataSrcPtr = (uint8_t *)(&(instPtr->antConfig)); const uint8_t *dataSrcPtr = (uint8_t *)(&(instPtr->antConfig));
const size_t antIndexNext = Phy_GetNextAntIndex(instPtr);
size_t hopIdx; size_t hopIdx;
uint16_t hopFreq; uint16_t hopFreq;
int16_t hopCal; uint8_t hopCal;
for (int32_t i = 0; i < hopNum; i++) for (int32_t i = 0; i < hopNum; i++)
{ {
hopIdx = hopPattern[i]; hopIdx = hopPattern[i];
// Frequency setting // Frequency setting
hopFreq = freqTable[hopIdx]; hopFreq = freqTable[hopIdx];
instPtr->antConfig.antFreq[0] = (uint8_t)(hopFreq >> 8); instPtr->antConfig.rfFreq[antIndexNext][0] = (uint8_t)(hopFreq >> 8);
instPtr->antConfig.antFreq[1] = (uint8_t)hopFreq; instPtr->antConfig.rfFreq[antIndexNext][1] = (uint8_t)hopFreq;
instPtr->antConfig.rfFreq[0] = (uint8_t)(hopFreq >> 8);
instPtr->antConfig.rfFreq[1] = (uint8_t)hopFreq;
// Calibration setting // Calibration setting
// -- CH0 for (uint8_t ii = 0; ii < L1_ANT_CH_NUM; ii ++)
hopCal = antCalTable[hopIdx][0]; {
instPtr->antConfig.ch0Cal[0] = (uint8_t)(hopCal >> 8); hopCal = antCalTable[antIndexNext][hopIdx][ii];
instPtr->antConfig.ch0Cal[1] = (uint8_t)hopCal; instPtr->antConfig.rfNormComp[antIndexNext][ii] = hopCal;
// -- CH1 }
hopCal = antCalTable[hopIdx][1];
instPtr->antConfig.ch1Cal[0] = (uint8_t)(hopCal >> 8);
instPtr->antConfig.ch1Cal[1] = (uint8_t)hopCal;
// -- CH2
hopCal = antCalTable[hopIdx][2];
instPtr->antConfig.ch2Cal[0] = (uint8_t)(hopCal >> 8);
instPtr->antConfig.ch2Cal[1] = (uint8_t)hopCal;
// -- CH3
hopCal = antCalTable[hopIdx][3];
instPtr->antConfig.ch3Cal[0] = (uint8_t)(hopCal >> 8);
instPtr->antConfig.ch3Cal[1] = (uint8_t)hopCal;
memcpy((uint8_t *)(antConfigAddr + i * ANT_COINFO_LEN), memcpy((uint8_t *)(antConfigAddr + i * ANT_COINFO_LEN),
dataSrcPtr, sizeof(PHY_ANT_CONFIG)); dataSrcPtr, sizeof(PHY_ANT_CONFIG));
@@ -889,9 +776,7 @@ int32_t Phy_SetupNextSlot(PHY_INST *instPtr, PHY_TOR_TYPE txrxMode,
Phy_RcdShift(&(instPtr->tor), txrxMode); Phy_RcdShift(&(instPtr->tor), txrxMode);
Phy_RcdShift(&(instPtr->frameType), frameType); Phy_RcdShift(&(instPtr->frameType), frameType);
// TODO:
Phy_RcdShift(&(instPtr->beamNo), L1_INIT_BEAM_NO);
Phy_RcdShift(&(instPtr->beamWd), L1_INIT_ANT_WD);
return SUCCESS; return SUCCESS;
} }
@@ -1116,50 +1001,47 @@ void Phy_RefreshHwSate(PHY_INST *instPtr)
? INT8_MAX ? INT8_MAX
: ((evalData < TEMPERATURE_MIN) ? INT8_MIN : (int8_t)round(evalData / TEMPERATURE_LSB)); : ((evalData < TEMPERATURE_MIN) ? INT8_MIN : (int8_t)round(evalData / TEMPERATURE_LSB));
instPtr->hwSate.isSpOk = (instPtr->hwSate.spFpgaVolt == (VOLT_PS_OK | VOLT_PSAUX_OK | VOLT_DDR_OK | VOLT_PL_OK | VOLT_PLAUX_OK | VOLT_BRAM_OK)) instPtr->hwSate.isSpOk = (instPtr->hwSate.spFpgaVolt == (VOLT_PS_OK | VOLT_PSAUX_OK | VOLT_DDR_OK | VOLT_PL_OK | VOLT_PLAUX_OK | VOLT_BRAM_OK))
&& (instPtr->hwSate.spClkState == (CLK_SP_PLL0_LOCK | CLK_SP_PLL1_LOCK)) && (instPtr->hwSate.spClkState == (CLK_SP_PLL1_LOCK | CLK_SP_PLL2_LOCK))
&& (instPtr->hwSate.spAdLockState == (CLK_AD0_BBPLL_LOCK | CLK_AD0_RFPLL_LOCK | CLK_AD1_BBPLL_LOCK | CLK_AD1_RFPLL_LOCK)); && (instPtr->hwSate.spAdLockState == (CLK_AD0_BBPLL_LOCK | CLK_AD0_RFPLL_LOCK | CLK_AD1_BBPLL_LOCK | CLK_AD1_RFPLL_LOCK));
#else #else
instPtr->hwSate.isSpOk = true; instPtr->hwSate.isSpOk = true;
#endif #endif
/*** Voltage and Status ***/ /*** Antenna Status Chunk 1 ***/
rawData = PhyRead(instPtr, ANT_STATUS); rawData = PhyRead(instPtr, ANT_STATUS_1);
// -- Update Antenna Voltage Status: 1 - normal, 0 - error // -- Update Antenna Frequency Status:
// [0] - ANT voltage status // [15] - ANT1 PLL on-off status: 1 - PLL1 active, 0 - PLL2 active
// [2] - RF voltage status // [14:0] - ANT1 PLL frequency, base frequency is 3700 MHz
// [4] - NIL voltage status // [31] - ANT2 PLL on-off status: 1 - PLL1 active, 0 - PLL2 active
// [6] - Antenna status // [30:16] - ANT2 PLL frequency, base frequency is 3700 MHz
instPtr->hwSate.antVolt = ((rawData & ANT_STATUS_ANT_VOLT_MASK) == ANT_STATUS_ANT_VOLT_OK) ? VOLT_ANT_PROC_OK : 0x00; instPtr->hwSate.ant1Freq = (rawData & ANT_STATUS_1_ANT1_STATUS_MASK) >> ANT_STATUS_1_ANT1_STATUS_SHIFT;
instPtr->hwSate.antVolt |= ((rawData & ANT_STATUS_RF_VOLT_MASK) == ANT_STATUS_RF_VOLT_OK) ? VOLT_ANT_RF_OK : 0x00; instPtr->hwSate.ant2Freq = (rawData & ANT_STATUS_1_ANT2_STATUS_MASK) >> ANT_STATUS_1_ANT2_STATUS_SHIFT;
instPtr->hwSate.antVolt |= ((rawData & ANT_STATUS_NIL_VOLT_MASK) == ANT_STATUS_NIL_VOLT_OK) ? VOLT_ANT_NIL_OK : 0x00;
instPtr->hwSate.antVolt |= ((rawData & ANT_STATUS_CODE_MASK) == ANT_STATUS_CODE_OK) ? ANT_STATE_OK : 0x00;
/*** Temperature and Lock Status ***/ /*** Antenna Status Chunk 2 ***/
rawData = PhyRead(instPtr, ANT_RF_STATUS); rawData = PhyRead(instPtr, ANT_STATUS_2);
// -- Update Antenna Frequency Status:
// [15] - ANT 3 PLL on-off status: 1 - PLL1 active, 0 - PLL2 active
// [14:0] - ANT 3 PLL frequency, base frequency is 3700 MHz
// [16] - PLL1 of ANT1 lock status: 1 - lock, 2 - unlock
// [17] - PLL2 of ANT1 lock status: 1 - lock, 2 - unlock
// [18] - PLL1 of ANT2 lock status: 1 - lock, 2 - unlock
// [19] - PLL2 of ANT2 lock status: 1 - lock, 2 - unlock
// [20] - PLL1 of ANT3 lock status: 1 - lock, 2 - unlock
// [21] - PLL2 of ANT3 lock status: 1 - lock, 2 - unlock
// [24] - Working mode of ANT1: 0 - normal mode, 1 - anti-jamming mode
// [25] - Working mode of ANT2: 0 - normal mode, 1 - anti-jamming mode
// [26] - Working mode of ANT3: 0 - normal mode, 1 - anti-jamming mode
instPtr->hwSate.ant3Freq = (rawData & ANT_STATUS_2_ANT3_STATUS_MASK) >> ANT_STATUS_2_ANT3_STATUS_SHIFT;
instPtr->hwSate.antPll = (rawData & ANT_STATUS_2_PLL_LK_MASK) >> ANT_STATUS_2_PLL_LK_SHIFT;
instPtr->hwSate.antMode = (rawData & ANT_STATUS_2_MODE_MASK) >> ANT_STATUS_2_MODE_SHIFT;
/*** Temperature and Reserved Control ***/
rawData = PhyRead(instPtr, ANT_STATUS_TEMP);
//-- Update Antenna Temperature (signed 8bit integer, 1 centigrade per LSB) //-- Update Antenna Temperature (signed 8bit integer, 1 centigrade per LSB)
instPtr->hwSate.antTemp = (uint8_t)(rawData & ANT_RF_STATUS_TEMP_MASK); instPtr->hwSate.antTemp = (uint8_t)(rawData & ANT_STATUS_TEMP_MASK) >> ANT_STATUS_TEMP_SHIFT;
// -- Update Antenna PLL Lock Status: 1 - normal, 0 - error instPtr->hwSate.antRsvd = (uint8_t)(rawData & ANT_STATUS_TEMP_RSVD_MASK) >> ANT_STATUS_TEMP_RSVD_SHIFT;
// [0] - BASEBAND lock status
// [2] - PLLA lock status
// [4] - PLLB lock status
instPtr->hwSate.antPll = ((rawData & ANT_RF_STATUS_BBLOCK_MASK) == ANT_RF_STATUS_BBLOCK_OK) ? CLK_ANT_BBPLL_LOCK : 0x00;
instPtr->hwSate.antPll |= ((rawData & ANT_RF_STATUS_PLLA_MASK) == ANT_RF_STATUS_PLLA_OK) ? CLK_ANT_RFPLL0_LOCK : 0x00;
instPtr->hwSate.antPll |= ((rawData & ANT_RF_STATUS_PLLB_MASK) == ANT_RF_STATUS_PLLB_OK) ? CLK_ANT_RFPLL1_LOCK : 0x00;
/*** MGCs ***/ // Determine if antenna is ok.
rawData = PhyRead(instPtr, ANT_RF_MGC); instPtr->hwSate.isAntOk = 1U; // FIXME: proper condition is required
// -- Update Antenna MGC (0~15 dB)
// [3:0] - Channel 1 MGC
// [7:4] - Channel 2 MGC
// [11:8] - Channel 3 MGC
// [15:12] - Channel 4 MGC
instPtr->hwSate.antMgc0 = (rawData & ANT_RF_MGC_CH1_MASK);
instPtr->hwSate.antMgc0 |= (rawData & ANT_RF_MGC_CH2_MASK) >> 4;
instPtr->hwSate.antMgc1 = (rawData & ANT_RF_MGC_CH3_MASK) >> 16;
instPtr->hwSate.antMgc1 |= (rawData & ANT_RF_MGC_CH4_MASK) >> 24;
// Determin if antenna is ok.
instPtr->hwSate.isAntOk = (instPtr->hwSate.antVolt == (VOLT_ANT_PROC_OK | VOLT_ANT_RF_OK | VOLT_ANT_NIL_OK | ANT_STATE_OK))
&& (instPtr->hwSate.antPll == (CLK_ANT_BBPLL_LOCK | CLK_ANT_RFPLL0_LOCK | CLK_ANT_RFPLL1_LOCK));
instPtr->hwSate.phyId = instPtr->phyCofig.devId; instPtr->hwSate.phyId = instPtr->phyCofig.devId;
@@ -1176,17 +1058,17 @@ void Phy_RefreshHwSate(PHY_INST *instPtr)
*/ */
/*****************************************************************************/ /*****************************************************************************/
/** /**
* @brief Get the last scan beam number after autoscan. * @brief Get the antenna number after physical receive.
* *
* @param instPtr a pointer to physical instance * @param instPtr a pointer to physical instance
* *
* @return beam number * @return antenna index
* *
******************************************************************************/ ******************************************************************************/
uint8_t Phy_LastScanBeamNo(PHY_INST *instPtr) uint8_t Phy_ReceiveAntIndex(PHY_INST *instPtr)
{ {
ASSERT(instPtr != NULL); ASSERT(instPtr != NULL);
return (uint8_t)PhyRead(instPtr, BEAM_SELECT_INDEX); return (uint8_t)PhyRead(instPtr, ANT_SELECT_INDEX);
} }
/*****************************************************************************/ /*****************************************************************************/
@@ -1208,7 +1090,7 @@ double Phy_GetFreqEst(PHY_INST *instPtr)
double coarse, fine; double coarse, fine;
frameType = Phy_GetLastRecvFrameType(instPtr); frameType = Phy_GetLastRecvFrameType(instPtr);
if (frameType > L1_1M2BPS_5MS_FRAME || frameType <= L1_NONE_FRAME) if (frameType > L1_FRAME_2MBPS_4MS || frameType <= L1_FRAME_NONE)
{ {
return INFINITY; // FIXME return INFINITY; // FIXME
} }
@@ -1218,7 +1100,7 @@ double Phy_GetFreqEst(PHY_INST *instPtr)
syncFreqIdx = (coarseReg & COASE_FREQEST_SYNC_MASK) >> COASE_FREQEST_SYNC_SHIFT; syncFreqIdx = (coarseReg & COASE_FREQEST_SYNC_MASK) >> COASE_FREQEST_SYNC_SHIFT;
fineReg = PhyRead(instPtr, FINE_FREQEST); fineReg = PhyRead(instPtr, FINE_FREQEST);
estAbs = fineReg & FINE_FREQEST_VAL_MASK; estAbs = fineReg & FINE_FREQEST_VAL_MASK;
if (frameType >= L1_200KBPS_5MS_FRAME) if (frameType >= L1_FRAME_128KBPS_4MS)
{ {
// 12M Rc // 12M Rc
coarse = (double)(8 - acqFreqIdx) * (250e3 / 4); coarse = (double)(8 - acqFreqIdx) * (250e3 / 4);
@@ -1259,14 +1141,14 @@ double Phy_GetCoarseFreqEst(PHY_INST *instPtr)
double freqEst; double freqEst;
frameType = Phy_GetLastRecvFrameType(instPtr); frameType = Phy_GetLastRecvFrameType(instPtr);
if ((frameType > L1_1M2BPS_5MS_FRAME) || (frameType <= L1_NONE_FRAME)) if ((frameType > L1_FRAME_2MBPS_4MS) || (frameType <= L1_FRAME_NONE))
{ {
return INFINITY; // FIXME return INFINITY; // FIXME
} }
regValue = PhyRead(instPtr, COASE_FREQEST); regValue = PhyRead(instPtr, COASE_FREQEST);
acqFreqIdx = (regValue & COASE_FREQEST_ACQ_MASK) >> COASE_FREQEST_ACQ_SHIFT; acqFreqIdx = (regValue & COASE_FREQEST_ACQ_MASK) >> COASE_FREQEST_ACQ_SHIFT;
syncFreqIdx = (regValue & COASE_FREQEST_SYNC_MASK) >> COASE_FREQEST_SYNC_SHIFT; syncFreqIdx = (regValue & COASE_FREQEST_SYNC_MASK) >> COASE_FREQEST_SYNC_SHIFT;
if (frameType >= L1_200KBPS_5MS_FRAME) if (frameType >= L1_FRAME_128KBPS_4MS)
{ {
// 12M Rc // 12M Rc
freqEst = (double)(8 - acqFreqIdx) * (250e3 / 4); freqEst = (double)(8 - acqFreqIdx) * (250e3 / 4);
@@ -1297,14 +1179,14 @@ double Phy_GetFineFreqEst(PHY_INST *instPtr)
double freqEst; double freqEst;
L1_FRAME_TYPE frameType; L1_FRAME_TYPE frameType;
frameType = Phy_GetLastRecvFrameType(instPtr); frameType = Phy_GetLastRecvFrameType(instPtr);
if ((frameType > L1_1M2BPS_5MS_FRAME) || (frameType <= L1_NONE_FRAME)) if ((frameType > L1_FRAME_2MBPS_4MS) || (frameType <= L1_FRAME_NONE))
{ {
return INFINITY; // FIXME return INFINITY; // FIXME
} }
regValue = PhyRead(instPtr, FINE_FREQEST); regValue = PhyRead(instPtr, FINE_FREQEST);
estAbs = regValue & FINE_FREQEST_VAL_MASK; estAbs = regValue & FINE_FREQEST_VAL_MASK;
if ((frameType >= L1_200KBPS_5MS_FRAME)) if ((frameType >= L1_FRAME_128KBPS_4MS))
{ {
// 12M Rc // 12M Rc
freqEst = 48e6 / 2048 * ((double)estAbs) / 8192.0; freqEst = 48e6 / 2048 * ((double)estAbs) / 8192.0;
@@ -1390,4 +1272,4 @@ void Phy_GetLastReceivedSlotStartTimeStamp(PHY_INST *instPtr, TIME_WORD *slotSta
/** @} PhysicalLayer_Receive_Estimations*/ /** @} PhysicalLayer_Receive_Estimations*/
/** @} PhysicalLayer*/ /** @} PhysicalLayer*/
@@ -34,24 +34,20 @@
* @name PhysicalLayer_Common_Constant * @name PhysicalLayer_Common_Constant
* @{ * @{
*/ */
#define L1_NUM_ANT_NRRW_PATTERN 37U #define L1_ANT_NUM 3U // 1 beam per antenna, and 3 antennas in total
#define L1_INIT_BEAM_NO 0U #define L1_ANT_CH_NUM 4U // channel number per antenna
#define L1_INIT_ANT_WD PHY_ANT_BEAM_120 #define L1_INIT_ANT_IDX 0U
#define L1_ANT_NUM_CH 4U
#define L1_FRAME_NONE_LEN UINT32_MAX // byte #define L1_FRAME_NONE_LEN UINT32_MAX // byte
#define L1_FRAME_NONE_COMP UINT32_MAX // *10ns(Timer_L) #define L1_FRAME_NONE_COMP UINT32_MAX // *10ns(Timer_L)
#define L1_FRAME_NONE_HOPS UINT32_MAX #define L1_FRAME_NONE_HOPS UINT32_MAX
#define L1_FRAME_MAX_HOPS 81U #define L1_FRAME_MAX_HOPS 81
#define L1_FRAME_2KBPS_20MS_HOPS 1U #define L1_FRAME_ADV_24MS_HOPS 16U // sync 16 ms + data 8 ms, 2000 hops/s
#define L1_FRAME_2KBPS_100MS_HOPS 81U #define L1_FRAME_ACK_8MS_HOPS 4U // sync 6 ms + data 2 ms, 2000 hops/s
#define L1_FRAME_10KBPS_10MS_HOPS 1U #define L1_FRAME_128KBPS_4MS_HOPS 33U
#define L1_FRAME_10KBPS_20MS_HOPS 11U #define L1_FRAME_512KBPS_4MS_HOPS 36U
#define L1_FRAME_40KBPS_20MS_HOPS 19U #define L1_FRAME_2MBPS_4MS_HOPS 38U
#define L1_FRAME_40KBPS_10MS_HOPS 9U #define PHY_LOG_EXPIRE 50U // number of 2 ms slot
#define L1_FRAME_200KBPS_5MS_HOPS 20U
#define L1_FRAME_1M2BPS_5MS_HOPS 20U
#define PHY_LOG_EXPIRE 40U // 50*5ms
/** @} */ /** @} */
/***************** Macros (Inline Functions) Definitions *********************/ /***************** Macros (Inline Functions) Definitions *********************/
/**************************** Type Definitions *******************************/ /**************************** Type Definitions *******************************/
@@ -60,15 +56,12 @@
*/ */
typedef enum typedef enum
{ {
L1_NONE_FRAME = 0, L1_FRAME_NONE = 0,
L1_2KBPS_20MS_FRAME = 1, L1_FRAME_ADV_24MS = 1,
L1_2KBPS_100MS_FRAME = 2, L1_FRAME_ACK_8MS = 2,
L1_10KBPS_10MS_FRAME = 3, L1_FRAME_128KBPS_4MS = 3, // 128kbps
L1_10KBPS_20MS_FRAME = 4, L1_FRAME_512KBPS_4MS = 4, // 512kbps
L1_40KBPS_20MS_FRAME = 5, L1_FRAME_2MBPS_4MS = 5 // 2 Mbps
L1_40KBPS_10MS_FRAME = 6,
L1_200KBPS_5MS_FRAME = 7,
L1_1M2BPS_5MS_FRAME = 8
} L1_FRAME_TYPE; } L1_FRAME_TYPE;
/** /**
@@ -77,58 +70,39 @@ typedef enum
*/ */
typedef struct typedef struct
{ {
/*** Ant Control ***/ /*** Antenna & RF Control ***/
uint8_t ctrlWord; ///< Antenna control frame head 0xAA\n uint8_t rfNormComp[L1_ANT_NUM][L1_ANT_CH_NUM];
/// default 0, reserved for further use ///< Normal mode RF phase compensation, 3 antennas
uint8_t antMode; ///< high 4 bits specified beam mode.\n /// and 4 channels each: 0~63, 5.625° step
/// low 4 bits specified power control uint8_t rfNormIdpAttn[L1_ANT_NUM][L1_ANT_CH_NUM];
uint8_t oaxis[2]; ///< off-axis angle range is 0~60 \n ///< Normal mode RF attenuation for independent channel:
/// 0.1 degree each LSB /// 0~30 dB, 1dB step
uint8_t raxis[2]; ///< round-axis angle range is 0~360, \n uint8_t rfNormComAttn[L1_ANT_NUM];
/// 0.1 degree each LSB ///< Normal mode RF attenuation for combined channel:
uint8_t antFreq[2]; ///< 0~3500Mhz, step 1MHz /// 0~30 dB, 1dB step
uint8_t trSlect; ///< in single tr mode, 0~63 specified tr channel \n struct
/// in single subarray mode, 0~3 specified the subarray {
/// ! Only in debug mode! uint8_t antMode : 1; /// [0]: Anti-jamming mode control, 1 - enable, 0 - disable
uint8_t antAtt; ///< Antenna attenuation 0~31, 0.5dB each LSB, Only in debug mode /// only one antenna can be selected in anti-jamming mode
uint8_t phase; ///< 0~63, 5.625 degree each LSB, Only in debug mode uint8_t antRx1En : 1; /// [1]: Anti-jamming antenna 1 select, 1 - enable, 0 - disable
uint8_t rxtxMode; ///< Only for debug \n uint8_t antRx2En : 1; /// [2]: Anti-jamming antenna 2 select, 1 - enable, 0 - disable
/// default 0x00 uint8_t antRx3En : 1; /// [3]: Anti-jamming antenna 3 select, 1 - enable, 0 - disable
uint8_t calibrMode; ///< 0x00 Normal, 0x01 single tr calibration uint8_t antTx1En : 1; /// [4]: Antenna 1 tx control, 1 - enable, 0 - disable
uint8_t antReserved; ///< reserved for further use uint8_t antTx2En : 1; /// [5]: Antenna 2 tx control, 1 - enable, 0 - disable
uint8_t antTx3En : 1; /// [6]: Antenna 3 tx control, 1 - enable, 0 - disable
uint8_t antRsvd : 1; /// [7]: reserved
} antControl;
/*** RF Control ***/ uint8_t rfAntiAttn[L1_ANT_CH_NUM];
uint8_t rfCtrl; ///< [7:4]RF enable: 0-On, 1-Off(Default); [3:0]Work mode: 0(default) ///< Anti-jamming mode RF attenuation, 4 channels:
uint8_t rfFreq[2]; ///< 0~3500Mhz, step 1MHz /// 0~60 dB, 1dB step
uint8_t rfTxMgc; ///< RF MGC control: 0~31, 1dB each LSB uint8_t rfFreq[L1_ANT_NUM][2];
uint8_t rf12CalMgc; ///< RF channel 1&2 calibration mgc\n ///< RF synthesizer ping-pong frequency, 3 antennas
/// [7:4] Channle1 - max 15db, 1dB each LSB \n /// and 2 byte each: 0~600 MHz, step 1MHz, with base
/// [3:0] Channle2 - max 15db, 1dB each LSB /// frequency of 3700 MHz
uint8_t rf34CalMgc; ///< RF channel 3&4 calibration mgc\n uint8_t rfRsvd; ///< reserved for further use
/// [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; } 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 * @enum PHY_TIME_WORD_TYPE
*/ */
@@ -139,18 +113,6 @@ typedef enum
PHY_TIME_WORD_LISTEN_TIMEOUT = 2 PHY_TIME_WORD_LISTEN_TIMEOUT = 2
} PHY_TIME_WORD_TYPE; } 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 * @enum PHY_TOR_TYPE
*/ */
@@ -168,8 +130,7 @@ typedef enum
{ {
PHY_MODE_NONE = 0, PHY_MODE_NONE = 0,
PHY_MODE_LISTEN = 1, PHY_MODE_LISTEN = 1,
PHY_MODE_SCHEDULE = 2, PHY_MODE_POLL = 2
PHY_MODE_PULL = 3
} PHY_MODE; } PHY_MODE;
/** /**
@@ -179,10 +140,30 @@ typedef enum
{ {
PHY_ANT_MODE_NONE = 0, PHY_ANT_MODE_NONE = 0,
PHY_ANT_MODE_STANDBY = 1, PHY_ANT_MODE_STANDBY = 1,
PHY_ANT_MODE_POWER_LOW = 2, PHY_ANT_MODE_NORMAL = 2,
PHY_ANT_MODE_POWER_FULL = 3, PHY_ANT_MODE_ANTI_JAM = 3
} PHY_ANT_MODE; } PHY_ANT_MODE;
/**
* @enum PHY_ANT_RX_MODE
*/
typedef enum
{
PHY_ANT_RX_MODE_NORMAL = 0,
PHY_ANT_RX_MODE_AJ = 1
} PHY_ANT_RX_MODE;
/**
* @enum PHY_ANT_INDEX
*/
typedef enum
{
PHY_ANT_INDEX_NONE = 0,
PHY_ANT_INDEX_1 = 1,
PHY_ANT_INDEX_2 = 2,
PHY_ANT_INDEX_3 = 3
} PHY_ANT_INDEX;
/** /**
* @struct PHY_RCD * @struct PHY_RCD
* @brief Physical Layer recode buffer * @brief Physical Layer recode buffer
@@ -204,7 +185,6 @@ typedef struct
uint32_t txBramId; ///< tx bram ID uint32_t txBramId; ///< tx bram ID
uint32_t rxBramId; ///< rx bram ID uint32_t rxBramId; ///< rx bram ID
uint32_t antBramId; ///< antenna config bram ID uint32_t antBramId; ///< antenna config bram ID
uint32_t antInfoBramId; ///< antenna beam info bram ID
uint32_t hwXadcId; ///< hardware xadc device ID uint32_t hwXadcId; ///< hardware xadc device ID
uintptr_t baseAddr; ///< Physical layer controller base address uintptr_t baseAddr; ///< Physical layer controller base address
#ifndef EMULATION #ifndef EMULATION
@@ -225,7 +205,6 @@ typedef struct
uintptr_t recvDataAddr; ///< receive data bram address uintptr_t recvDataAddr; ///< receive data bram address
uintptr_t sendDataAddr; ///< send data bram address uintptr_t sendDataAddr; ///< send data bram address
uintptr_t antConfigAddr; ///< antenna config 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 isPhyEn; ///< indicates if physical layer running
bool isAcq; ///< indicates if last reception acquisition success bool isAcq; ///< indicates if last reception acquisition success
bool isFrameSync; ///< indicates if last reception frame sync success bool isFrameSync; ///< indicates if last reception frame sync success
@@ -233,8 +212,7 @@ typedef struct
bool isValid; ///< indicates if last reception frame data valid (crc check pass) bool isValid; ///< indicates if last reception frame data valid (crc check pass)
TIME_WORD recvSlotTime; ///< last slot start time stamp TIME_WORD recvSlotTime; ///< last slot start time stamp
TIME_WORD recvFsTime; ///< last frame sync time stamp TIME_WORD recvFsTime; ///< last frame sync time stamp
PHY_RCD beamNo; ///< beam number record PHY_RCD antIndex; ///< antenna number record
PHY_RCD beamWd; ///< beam width record
PHY_RCD tor; ///< tx rx state record PHY_RCD tor; ///< tx rx state record
PHY_RCD frameType; ///< frame type record PHY_RCD frameType; ///< frame type record
uint32_t sendDataOffset; ///< antenna configuration bram offset (to implement ping-pong data flow) uint32_t sendDataOffset; ///< antenna configuration bram offset (to implement ping-pong data flow)
@@ -243,10 +221,9 @@ typedef struct
#ifndef EMULATION #ifndef EMULATION
XAdcPs hwXadc; ///< hardware Xadc instance XAdcPs hwXadc; ///< hardware Xadc instance
#endif #endif
PHY_ANT_ANGLE antNrrwPattern[L1_NUM_ANT_NRRW_PATTERN]; ///< antenna beam scan pattern HWSTATE hwSate; ///< hardware state log
HWSTATE hwSate; ///< hardware state log PHYLOG phyLog; ///< physical state log
PHYLOG phyLog; ///< physical state log uint32_t lastLogTime; /// physical state log time stamp
uint32_t lastLogTime; /// physical state log time stamp
} PHY_INST; } PHY_INST;
/************************** Function Prototypes ******************************/ /************************** Function Prototypes ******************************/
@@ -288,7 +265,7 @@ L1_FRAME_TYPE Phy_GetLastSendFrameType(PHY_INST *instPtr);
* @defgroup PhysicalLayer_Receive_Estimations * @defgroup PhysicalLayer_Receive_Estimations
* @{ * @{
*/ */
uint8_t Phy_LastScanBeamNo(PHY_INST *instPtr); uint8_t Phy_ReceiveAntIndex(PHY_INST *instPtr);
double Phy_GetFreqEst(PHY_INST *instPtr); double Phy_GetFreqEst(PHY_INST *instPtr);
double Phy_GetCoarseFreqEst(PHY_INST *instPtr); double Phy_GetCoarseFreqEst(PHY_INST *instPtr);
double Phy_GetFineFreqEst(PHY_INST *instPtr); double Phy_GetFineFreqEst(PHY_INST *instPtr);
@@ -303,11 +280,11 @@ void Phy_GetLastReceivedSlotStartTimeStamp(PHY_INST *instPtr, TIME_WORD *slotSta
* @{ * @{
*/ */
void Phy_AntConfigInit(PHY_ANT_CONFIG *antConfig); void Phy_AntConfigInit(PHY_ANT_CONFIG *antConfig);
void Phy_AntConfigMode(PHY_INST *instPtr, PHY_ANT_MODE mode); void Phy_SetTxAntIndex(PHY_INST *instPtr, PHY_ANT_INDEX antIndex);
void Phy_SetBeamTable(PHY_INST *instPtr, PHY_ANT_ANGLE *table, uint32_t offset); void Phy_SetRxAntIndex(PHY_INST *instPtr, PHY_ANT_INDEX antRxIndex);
int32_t Phy_SetBeamWidth(PHY_INST *instPtr, PHY_ANT_BEAM_WIDTH beamWidth); void Phy_SetRxMode(PHY_INST *instPtr, PHY_ANT_RX_MODE antRxMode);
int32_t Phy_SetBeamNo(PHY_INST *instPtr, size_t beamNo, PHY_ANT_BEAM_WIDTH beamWidth); int32_t Phy_SetAntIndex(PHY_INST *instPtr, PHY_ANT_INDEX antIndex);
int32_t Phy_SetBeamAngle(PHY_INST *phyInstPtr, double offAx, double rndAx); size_t Phy_GetNextAntIndex(PHY_INST *instPtr);
/** @} PhysicalLayer_AntennaControl*/ /** @} PhysicalLayer_AntennaControl*/
#endif // PHY_CTRL_H_ #endif // PHY_CTRL_H_
+105 -100
View File
@@ -48,8 +48,7 @@
#define PHY_MAIN_CTRL_EN_DSBL 0x00000000U #define PHY_MAIN_CTRL_EN_DSBL 0x00000000U
#define PHY_MAIN_CTRL_MODE_NONE 0x00000000U #define PHY_MAIN_CTRL_MODE_NONE 0x00000000U
#define PHY_MAIN_CTRL_MODE_LISTEN 0x00000100U #define PHY_MAIN_CTRL_MODE_LISTEN 0x00000100U
#define PHY_MAIN_CTRL_MODE_SCHEDULE 0x00000200U #define PHY_MAIN_CTRL_MODE_POLL 0x00000200U
#define PHY_MAIN_CTRL_MODE_PULL 0x00000300U
/** /**
* Register: TXRX_CTRL * Register: TXRX_CTRL
@@ -70,14 +69,11 @@
#define PHY_MODE_CTRL_TOR_RX 0x00000002U #define PHY_MODE_CTRL_TOR_RX 0x00000002U
#define PHY_MODE_CTRL_FRAME_NONE 0x00000000U #define PHY_MODE_CTRL_FRAME_NONE 0x00000000U
#define PHY_MODE_CTRL_FRAME_2KBPS_20MS 0x00000100U #define PHY_MODE_CTRL_FRAME_ADV_24MS 0x00000100U
#define PHY_MODE_CTRL_FRAME_2KBPS_100MS 0x00000200U #define PHY_MODE_CTRL_FRAME_ACK_8MS 0x00000200U
#define PHY_MODE_CTRL_FRAME_10KBPS_10MS 0x00000300U // Initial Scan Frame #define PHY_MODE_CTRL_FRAME_128KBPS_4MS 0x00000300U
#define PHY_MODE_CTRL_FRAME_10KBPS_20MS 0x00000400U // Benchmark Frame #define PHY_MODE_CTRL_FRAME_512KBPS_4MS 0x00000400U
#define PHY_MODE_CTRL_FRAME_40KBPS_20MS 0x00000500U #define PHY_MODE_CTRL_FRAME_2MBPS_4MS 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_EN 0x00010000U
#define PHY_MODE_CTRL_CRC_DSBL 0x00000000U #define PHY_MODE_CTRL_CRC_DSBL 0x00000000U
@@ -236,14 +232,11 @@
#define COASE_TYPE_SHIFT 16 #define COASE_TYPE_SHIFT 16
#define COASE_TYPE_WIDTH 8 #define COASE_TYPE_WIDTH 8
#define COASE_TYPE_MASK 0x00FF0000U #define COASE_TYPE_MASK 0x00FF0000U
#define COASE_TYPE_2KBPS_20MS 0x00010000U #define COASE_TYPE_ADV_24MS 0x00010000U
#define COASE_TYPE_2KBPS_100MS 0x00020000U #define COASE_TYPE_ACK_8MS 0x00020000U
#define COASE_TYPE_10KBPS_10MS 0x00030000U #define COASE_TYPE_128KBPS_4MS 0x00030000U
#define COASE_TYPE_10KBPS_20MS 0x00040000U #define COASE_TYPE_512KBPS_4MS 0x00040000U
#define COASE_TYPE_40KBPS_20MS 0x00050000U #define COASE_TYPE_2MBPS_4MS 0x00050000U
#define COASE_TYPE_40KBPS_10MS 0x00060000U
#define COASE_TYPE_200KBPS_5MS 0x00070000U
#define COASE_TYPE_1M2BPS_5MS 0x00080000U
/** /**
* Register: FINE_FREQEST * Register: FINE_FREQEST
@@ -259,103 +252,115 @@
#define FINE_FREQEST_SIGN_NEG 0x01000000U #define FINE_FREQEST_SIGN_NEG 0x01000000U
/** /**
* Register: BEAM_SELECT * Register: ANT_SELECT
*/ */
#define BEAM_SELECT_INDEX 0x00000044U #define ANT_SELECT_INDEX 0x00000044U
#define BEAM_SELECT_INDEX_SHIFT 0 #define ANT_SELECT_INDEX_SHIFT 0
#define BEAM_SELECT_INDEX_WIDTH 32 #define ANT_SELECT_INDEX_WIDTH 32
#define BEAM_SELECT_INDEX_MASK 0xFFFFFFFFU #define ANT_SELECT_INDEX_MASK 0xFFFFFFFFU
/** /**
* Register: BEAM_AXIS * Register: ANT_STATUS_1
*/ */
#define BEAM_AXIS 0x00000044U #define ANT_STATUS_1 0x00000100U
#define BEAM_AXIS_EL_SHIFT 0
#define BEAM_AXIS_EL_WIDTH 16 #define ANT_STATUS_1_ANT1_STATUS_SHIFT 0
#define BEAM_AXIS_EL_MASK 0x0000FFFFU #define ANT_STATUS_1_ANT1_STATUS_WIDTH 16
#define BEAM_AXIS_AZ_SHIFT 16 #define ANT_STATUS_1_ANT1_STATUS_MASK 0x0000FFFFU
#define BEAM_AXIS_AZ_WIDTH 16
#define BEAM_AXIS_AZ_MASK 0xFFFF0000U #define ANT_STATUS_1_ANT1_FREQ_SHIFT 0
#define ANT_STATUS_1_ANT1_FREQ_WIDTH 15
#define ANT_STATUS_1_ANT1_FREQ_MASK 0x00003FFFU
#define ANT_STATUS_1_ANT1_PLL_SHIFT 15
#define ANT_STATUS_1_ANT1_PLL_WIDTH 1
#define ANT_STATUS_1_ANT1_PLL_MASK 0x00008000U
#define ANT_STATUS_1_ANT2_STATUS_SHIFT 16
#define ANT_STATUS_1_ANT2_STATUS_WIDTH 16
#define ANT_STATUS_1_ANT2_STATUS_MASK 0x0000FFFFU
#define ANT_STATUS_1_ANT2_FREQ_SHIFT 16
#define ANT_STATUS_1_ANT2_FREQ_WIDTH 15
#define ANT_STATUS_1_ANT2_FREQ_MASK 0x3FFF0000U
#define ANT_STATUS_1_ANT2_PLL_SHIFT 31
#define ANT_STATUS_1_ANT2_PLL_WIDTH 1
#define ANT_STATUS_1_ANT2_PLL_MASK 0x80000000U
/** /**
* Register: ANT_STATUS * Register: ANT_STATUS_2
*/ */
#define ANT_STATUS 0x00000100U #define ANT_STATUS_2 0x00000104U
#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_2_ANT3_STATUS_SHIFT 0
#define ANT_STATUS_RF_VOLT_WIDTH 8 #define ANT_STATUS_2_ANT3_STATUS_WIDTH 16
#define ANT_STATUS_RF_VOLT_MASK 0x0000FF00U #define ANT_STATUS_2_ANT3_STATUS_MASK 0x0000FFFFU
#define ANT_STATUS_RF_VOLT_OK 0x00000100U
#define ANT_STATUS_NIL_VOLT_SHIFT 16 #define ANT_STATUS_2_ANT3_FREQ_SHIFT 0
#define ANT_STATUS_NIL_VOLT_WIDTH 8 #define ANT_STATUS_2_ANT3_FREQ_WIDTH 15
#define ANT_STATUS_NIL_VOLT_MASK 0x00FF0000U #define ANT_STATUS_2_ANT3_FREQ_MASK 0x00003FFFU
#define ANT_STATUS_NIL_VOLT_OK 0x00010000U
#define ANT_STATUS_CODE_SHIFT 24 #define ANT_STATUS_2_ANT3_PLL_SHIFT 15
#define ANT_STATUS_CODE_WIDTH 8 #define ANT_STATUS_2_ANT3_PLL_WIDTH 1
#define ANT_STATUS_CODE_MASK 0xFF000000U #define ANT_STATUS_2_ANT3_PLL_MASK 0x00008000U
#define ANT_STATUS_CODE_OK 0x00000000U
#define ANT_STATUS_2_PLL_LK_SHIFT 16
#define ANT_STATUS_2_PLL_LK_WIDTH 8
#define ANT_STATUS_2_PLL_LK_MASK 0x00FF0000U
#define ANT_STATUS_2_ANT3_PLL2_LK_SHIFT 16
#define ANT_STATUS_2_ANT3_PLL2_LK_WIDTH 1
#define ANT_STATUS_2_ANT3_PLL2_LK_MASK 0x00010000U
#define ANT_STATUS_2_ANT3_PLL1_LK_SHIFT 17
#define ANT_STATUS_2_ANT3_PLL1_LK_WIDTH 1
#define ANT_STATUS_2_ANT3_PLL1_LK_MASK 0x00020000U
#define ANT_STATUS_2_ANT2_PLL2_LK_SHIFT 18
#define ANT_STATUS_2_ANT2_PLL2_LK_WIDTH 1
#define ANT_STATUS_2_ANT2_PLL2_LK_MASK 0x00040000U
#define ANT_STATUS_2_ANT2_PLL1_LK_SHIFT 19
#define ANT_STATUS_2_ANT2_PLL1_LK_WIDTH 1
#define ANT_STATUS_2_ANT2_PLL1_LK_MASK 0x00080000U
#define ANT_STATUS_2_ANT1_PLL2_LK_SHIFT 20
#define ANT_STATUS_2_ANT1_PLL2_LK_WIDTH 1
#define ANT_STATUS_2_ANT1_PLL2_LK_MASK 0x00100000U
#define ANT_STATUS_2_ANT1_PLL1_LK_SHIFT 21
#define ANT_STATUS_2_ANT1_PLL1_LK_WIDTH 1
#define ANT_STATUS_2_ANT1_PLL1_LK_MASK 0x00200000U
#define ANT_STATUS_2_MODE_SHIFT 24
#define ANT_STATUS_2_MODE_WIDTH 8
#define ANT_STATUS_2_MODE_MASK 0xFF000000U
#define ANT_STATUS_2_ANT1_MODE_SHIFT 24
#define ANT_STATUS_2_ANT1_MODE_WIDTH 1
#define ANT_STATUS_2_ANT1_MODE_MASK 0x01000000U
#define ANT_STATUS_2_ANT2_MODE_SHIFT 25
#define ANT_STATUS_2_ANT2_MODE_WIDTH 1
#define ANT_STATUS_2_ANT2_MODE_MASK 0x02000000U
#define ANT_STATUS_2_ANT3_MODE_SHIFT 26
#define ANT_STATUS_2_ANT3_MODE_WIDTH 1
#define ANT_STATUS_2_ANT3_MODE_MASK 0x04000000U
/** /**
* Register: ANT_FRAME_CNT * Register: ANT_STATUS_TEMP
*/ */
#define ANT_FRAME_CNT 0x00000104U #define ANT_STATUS_TEMP 0x00000108U
#define ANT_FRAME_CNT_SHIFT 0
#define ANT_FRAME_CNT_WIDTH 32
#define ANT_FRAME_CNT_MASK 0xFFFFFFFFU
/** #define ANT_STATUS_TEMP_SHIFT 0
* Register: ANT_RF_STATUS #define ANT_STATUS_TEMP_WIDTH 8
*/ #define ANT_STATUS_TEMP_MASK 0x000000FFU
#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_STATUS_TEMP_RSVD_SHIFT 8
#define ANT_RF_STATUS_BBLOCK_WIDTH 8 #define ANT_STATUS_TEMP_RSVD_WIDTH 8
#define ANT_RF_STATUS_BBLOCK_MASK 0x0000FF00U #define ANT_STATUS_TEMP_RSVD_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 * Register: PHY_ACQ_CNT
+26 -18
View File
@@ -61,8 +61,8 @@
#define IS_PLAUX_VALID(x) ((x) <= 2.0 && (x) >= 1.6) #define IS_PLAUX_VALID(x) ((x) <= 2.0 && (x) >= 1.6)
#define IS_BRAM_VALID(x) ((x) <= 1.1 && (x) >= 0.9) #define IS_BRAM_VALID(x) ((x) <= 1.1 && (x) >= 0.9)
#define CLK_SP_PLL0_LOCK BIT(0) #define CLK_SP_PLL1_LOCK BIT(0)
#define CLK_SP_PLL1_LOCK BIT(2) #define CLK_SP_PLL2_LOCK BIT(2)
#define CLK_AD0_BBPLL_LOCK BIT(0) #define CLK_AD0_BBPLL_LOCK BIT(0)
#define CLK_AD0_RFPLL_LOCK BIT(2) #define CLK_AD0_RFPLL_LOCK BIT(2)
@@ -70,8 +70,8 @@
#define CLK_AD1_RFPLL_LOCK BIT(6) #define CLK_AD1_RFPLL_LOCK BIT(6)
#define CLK_ANT_BBPLL_LOCK BIT(0) #define CLK_ANT_BBPLL_LOCK BIT(0)
#define CLK_ANT_RFPLL0_LOCK BIT(2) #define CLK_ANT_RFPLL1_LOCK BIT(2)
#define CLK_ANT_RFPLL1_LOCK BIT(4) #define CLK_ANT_RFPLL2_LOCK BIT(4)
#define TEMPERATURE_LSB 1.0 // Celsius degree #define TEMPERATURE_LSB 1.0 // Celsius degree
#define TEMPERATURE_MAX 127.0 // Celsius degree #define TEMPERATURE_MAX 127.0 // Celsius degree
@@ -141,16 +141,22 @@ typedef struct __attribute__((packed))
uint8_t cxnStatus; ///< current connection status uint8_t cxnStatus; ///< current connection status
uint8_t linkStage; ///< current linklayer working stage uint8_t linkStage; ///< current linklayer working stage
uint32_t recxnCnt; ///< reconnect trial count uint32_t recxnCnt; ///< reconnect trial count
uint8_t beamNo; ///< current working beam number uint8_t antIndex; ///< current working antenna index
uint8_t beamWidth; ///< current working beam width
uint16_t beamAz; ///< current working beam angle Az
uint16_t beamEl; ///< current working beam angle Ez
uint16_t advTxCnt; ///< adv frame send count uint16_t advTxCnt; ///< adv frame send count
uint16_t advRecvCnt; ///< adv frame received count uint16_t advRecvCnt; ///< adv frame received count
uint16_t advCorrectCnt; ///< adv frame received correctly count uint16_t advCorrectCnt; ///< adv frame received correctly count
uint32_t cfmTxCnt; ///< cfm frame send count uint32_t ackTxCnt; ///< ack frame send count
uint32_t cfmRecvCnt; ///< cfm frame received count uint32_t ackRecvCnt; ///< ack frame received count
uint32_t cfmCorrectCnt; ///< adv frame received correctly count uint32_t ackCorrectCnt; ///< ack frame received correctly count
uint32_t disTxCnt; ///< dist frame send count
uint32_t disRecvCnt; ///< dist frame received count
uint32_t disCorrectCnt;///< dist frame received correctly count
uint32_t mngTxCnt; ///< mng frame send count
uint32_t mngRecvCnt; ///< mng frame received count
uint32_t mngCorrectCnt; ///< mng frame received correctly count
uint32_t rttTxCnt; ///< rtt frame send count
uint32_t rttRecvCnt; ///< rtt frame received count
uint32_t rttCorrectCnt; ///< rtt frame received correctly count
uint32_t svcTxCnt; ///< svc frame send count uint32_t svcTxCnt; ///< svc frame send count
uint32_t svcRecvCnt; ///< svc frame received count uint32_t svcRecvCnt; ///< svc frame received count
uint32_t svcCorrectCnt; ///< svc frame received correctly count uint32_t svcCorrectCnt; ///< svc frame received correctly count
@@ -178,7 +184,7 @@ typedef struct __attribute__((packed))
double fsyncPAPR; ///< last frame sync peak-average ration double fsyncPAPR; ///< last frame sync peak-average ration
uint8_t fsyncFreqCh; ///< last frame sync frequency estimation uint8_t fsyncFreqCh; ///< last frame sync frequency estimation
uint16_t deintlvAmpEst; ///< de-interleave amplitude estimation uint16_t deintlvAmpEst; ///< de-interleave amplitude estimation
uint8_t antMode; ///< current antenna working mode uint8_t antControl; ///< current antenna rf mode
uint8_t reserve[3]; ///< reserved data uint8_t reserve[3]; ///< reserved data
} PHYLOG; } PHYLOG;
@@ -198,11 +204,13 @@ typedef struct __attribute__((packed))
int8_t spAdTemp_1; ///< Signal processor adc1 temperature int8_t spAdTemp_1; ///< Signal processor adc1 temperature
int8_t spFpgaTemp; ///< Signal processor FPGA temperature int8_t spFpgaTemp; ///< Signal processor FPGA temperature
// -- Antenna status // -- Antenna status
uint8_t antVolt; ///< Antenna voltage state indicator uint16_t ant1Freq; ///< Antenna 1 frequency
int8_t antTemp; ///< Antenna rf temperature uint16_t ant2Freq; ///< Antenna 2 frequency
uint8_t antPll; ///< Antenna rf lock state indicator uint16_t ant3Freq; ///< Antenna 3 frequency
uint8_t antMgc0; ///< Antenna rf mgc0~1 indicator uint8_t antPll; ///< Antenna pll lock state indicator
uint8_t antMgc1; ///< Antenna rf mgc2~3 indicator uint8_t antMode; ///< Antenna mode indicator
int8_t antTemp; ///< Antenna rf temperature
uint8_t antRsvd; ///< Antenna reserved status register
uint8_t phyId; uint8_t phyId;
uint8_t reserve[1]; uint8_t reserve[1];
} HWSTATE; } HWSTATE;
@@ -238,4 +246,4 @@ void SysMonitor_GetHardwareStatus(HWSTATE *state);
#endif //__SYSTEM_MONITOR_H_ #endif //__SYSTEM_MONITOR_H_
/** @} */ /** @} */
+35 -35
View File
@@ -310,40 +310,40 @@ static int32_t SystemBus_SystemConfig(SYSBUS *instPtr, uint8_t *msg)
return EPARAM; return EPARAM;
} }
if (msg[WD_EN_CMD] == EN_CMD_ON_HIGH_POWER) // if (msg[WD_EN_CMD] == EN_CMD_ON_HIGH_POWER)
{ // {
// full power config // // full power config
Phy_AntConfigMode(phyRef, PHY_ANT_MODE_POWER_FULL); // Phy_AntConfigMode(phyRef, PHY_ANT_MODE_POWER_FULL);
if (reconfig || !L2_isStarted(linkInstPtr)) // if (reconfig || !L2_isStarted(linkInstPtr))
{ // {
Linklayer_Reconfig(linkInstPtr, &linkConfig); // Linklayer_Reconfig(linkInstPtr, &linkConfig);
} // }
Linklayer_Start(linkInstPtr); // Linklayer_Start(linkInstPtr);
} // }
else if (msg[WD_EN_CMD] == EN_CMD_ON_LOW_POWER) // else if (msg[WD_EN_CMD] == EN_CMD_ON_LOW_POWER)
{ // {
// low power config // // low power config
Phy_AntConfigMode(phyRef, PHY_ANT_MODE_POWER_LOW); // Phy_AntConfigMode(phyRef, PHY_ANT_MODE_POWER_LOW);
if (reconfig || !L2_isStarted(linkInstPtr)) // if (reconfig || !L2_isStarted(linkInstPtr))
{ // {
Linklayer_Reconfig(linkInstPtr, &linkConfig); // Linklayer_Reconfig(linkInstPtr, &linkConfig);
} // }
Linklayer_Start(linkInstPtr); // Linklayer_Start(linkInstPtr);
} // }
else if (msg[WD_EN_CMD] == EN_CMD_SILENT) // else if (msg[WD_EN_CMD] == EN_CMD_SILENT)
{ // {
// silence config // // silence config
// TODO: better approach? // // TODO: better approach?
Linklayer_Halt(linkInstPtr); // Linklayer_Halt(linkInstPtr);
Phy_AntConfigMode(phyRef, PHY_ANT_MODE_STANDBY); // Phy_AntConfigMode(phyRef, PHY_ANT_MODE_STANDBY);
TIME_WORD pullTime = {0, 0}; // TIME_WORD pullTime = {0, 0};
pullTime.int_part = TimeCtrl_GetIntCnt(tmcRef) + 1; // pullTime.int_part = TimeCtrl_GetIntCnt(tmcRef) + 1;
if (Phy_SetTimeWord(phyRef, &pullTime, PHY_TIME_WORD_POLL) != SUCCESS) // if (Phy_SetTimeWord(phyRef, &pullTime, PHY_TIME_WORD_POLL) != SUCCESS)
{ // {
DBG_ERROR("Physical set pull time failed.\n"); // DBG_ERROR("Physical set pull time failed.\n");
} // }
Phy_SetupNextSlot(phyRef, PHY_TOR_RX, L1_10KBPS_10MS_FRAME, NULL); // Phy_SetupNextSlot(phyRef, PHY_TOR_RX, L1_10KBPS_10MS_FRAME, NULL);
} // }
else else
{ {
// Ignore current command // Ignore current command
@@ -777,4 +777,4 @@ int32_t SystemBus_RxIntrHandler(SYSBUS *instPtr)
return SUCCESS; return SUCCESS;
} }
/** @} SystemBus*/ /** @} SystemBus*/
+1 -1
View File
@@ -146,7 +146,7 @@ void TimeCtrl_ResetLow(TMC_INST *instPtr)
/*****************************************************************************/ /*****************************************************************************/
/** /**
* @brief Get current time integer value. * @brief Get current time integer value (2 ms counter).
* *
* @param instPtr a pointer to time controller instance * @param instPtr a pointer to time controller instance
* *
+3 -3
View File
@@ -21,7 +21,7 @@
/***************************** Include Files *********************************/ /***************************** Include Files *********************************/
#include <stdint.h> #include <stdint.h>
/************************** Constant Definitions *****************************/ /************************** Constant Definitions *****************************/
#define TIME_FRAC_MAX 500000 // how many 10ns in a 5ms #define TIME_FRAC_MAX 200000 // how many 10ns in a 2 ms
/***************** Macros (Inline Functions) Definitions *********************/ /***************** Macros (Inline Functions) Definitions *********************/
/**************************** Type Definitions *******************************/ /**************************** Type Definitions *******************************/
/** /**
@@ -44,8 +44,8 @@ typedef uint32_t TIME_INT;
*/ */
typedef struct typedef struct
{ {
TIME_INT int_part; ///< 5ms each LSB TIME_INT int_part; ///< 2 ms each LSB
TIME_FRAC frac_part; ///< 10ns each LSB TIME_FRAC frac_part; ///< 10 ns each LSB
} TIME_WORD; } TIME_WORD;
/** /**
@@ -228,7 +228,7 @@ TEST(linklayer_master_routine)
if (L2_isDataAvail(linkInstPtr)) if (L2_isDataAvail(linkInstPtr))
{ {
if (L2_GetLastOptFrameType(linkInstPtr) == L2_CFM_FRAME) if (L2_GetLastFrameType(linkInstPtr) == L2_CFM_FRAME)
{ {
ASSERT_EQUAL(1, L2_GetNodeListLen(linkInstPtr->nodeList)); ASSERT_EQUAL(1, L2_GetNodeListLen(linkInstPtr->nodeList));
ASSERT_TRUE(L2_isNodeInList(linkInstPtr->nodeList, 2)); ASSERT_TRUE(L2_isNodeInList(linkInstPtr->nodeList, 2));
+1 -1
View File
@@ -32,7 +32,7 @@ for key in ${!calMap[*]};do
exit 1 exit 1
fi fi
# substitute table # substitute table
sed -i'' "/^const uint16_t antCalTable\[L1_FRAME_MAX_HOPS\]\[L1_ANT_NUM_CH\] =/{ sed -i'' "/^const uint16_t antCalTable\[L1_FRAME_MAX_HOPS\]\[L1_ANT_CH_NUM\] =/{
:table :table
N N
/\};/!b table /\};/!b table