Răsfoiți Sursa

回退radio

dropLin 11 luni în urmă
părinte
comite
36f64c4263
11 a modificat fișierele cu 5930 adăugiri și 6 ștergeri
  1. 0 6
      .gitmodules
  2. 450 0
      radio/myRadio.c
  3. 138 0
      radio/myRadio.h
  4. 322 0
      radio/myRadio_gpio.c
  5. 89 0
      radio/myRadio_gpio.h
  6. 3337 0
      radio/pan3029.c
  7. 279 0
      radio/pan3029.h
  8. 158 0
      radio/pan3029_port.c
  9. 57 0
      radio/pan3029_port.h
  10. 972 0
      radio/radio.c
  11. 128 0
      radio/radio.h

+ 0 - 6
.gitmodules

@@ -1,6 +0,0 @@
-[submodule "lib-pan3029"]
-	path = lib-pan3029
-	url = http://git.cloudpeaks.cn/vg-module-lib/lib-pan3029.git
-[submodule "radio"]
-	path = radio
-	url = http://git.cloudpeaks.cn/vg-module-lib/lib-pan3029.git

+ 450 - 0
radio/myRadio.c

@@ -0,0 +1,450 @@
+#include "board.h"
+#include "myRadio.h"
+#include "myRadio_gpio.h"
+
+/**-------------------------radio include----------------------------------**/
+#include "radio.h"
+#include "pan3029.h"
+/**-------------------------radio include end----------------------------------**/
+
+static int8_t rfTxPower;
+static uint32_t rfFrequence;
+static uint32_t rfBaudrate;
+static uint8_t rf_sf;
+static uint8_t rf_bw;
+static uint8_t rf_cr;
+static rfRxCallBack rxCb;
+static uint8_t rfRxBuffer[255];
+static uint32_t rf_handle;
+static uint8_t rf_workProcess = RF_PRC_IDLE;
+static uint8_t chipType;
+/**-------------------------radio params----------------------------------**/
+
+typedef struct 
+{
+    int8_t power;
+    uint8_t regValue;
+}rfPowerReg_ts;
+
+const loraBaudrateFrame_ts loraBaudrateFrame[MAX_RF_BAUDRATE_COUNT] = 
+{
+    {//244.14bps,SF=12,BW=62.5kHz(6),CR=2
+    .SpreadingFactor = 12,        
+    .SignalBw = 6,               
+    .ErrorCoding = 2,            
+    },
+    {//627.79 bps,SF=9,BW=62.5kHz(6),CR=3
+    .SpreadingFactor = 9,        
+    .SignalBw = 6,               
+    .ErrorCoding = 4,            
+    },
+    {//1,255.58 bps,SF=9,BW=125kHz(7),CR=2
+    .SpreadingFactor = 9, 
+    .SignalBw = 7, 
+    .ErrorCoding = 2,            
+    },
+    {//2,511.16 bps,SF=9,BW=250kHz(8),CR=3
+    .SpreadingFactor = 9,        
+    .SignalBw = 8,               
+    .ErrorCoding = 3,            
+    },
+    {//5022.32bps,SF=8,BW=250kHz(8),CR=2
+    .SpreadingFactor = 8,        
+    .SignalBw = 8,               
+    .ErrorCoding = 2,            
+    },
+    {//12500bps,SF=8,BW=500kHz(9),CR=1
+    .SpreadingFactor = 8,                                                                                
+    .SignalBw = 9,               
+    .ErrorCoding = 1,            
+    },
+    {//20400bps,SF=8,BW=500kHz(9),CR=1
+    .SpreadingFactor = 7,        
+    .SignalBw = 9,               
+    .ErrorCoding = 1,            
+    },
+    {//62500bps,SF=5,BW=500kHz(9),CR=1
+    .SpreadingFactor = 7,        
+    .SignalBw = 9,               
+    .ErrorCoding = 1,            
+    },
+};
+bool rf_ifq;
+
+uint8_t regulatorMode = DCDC_ON;
+extern struct RxDoneMsg RxDoneParams;
+uint8_t getRfPowerTabIndex(int8_t power);
+/**-------------------------radio params end----------------------------------**/
+void myRadio_delay(uint32_t time_ms)
+{
+    delay1ms(time_ms);
+}
+/**
+ * @brief IO口中断回调
+ *      IO口产生中断后会执行该函数
+ *      用于接收射频工作的中断响应
+ * 
+ * @param index 
+ */
+void myRadio_gpioCallback(uint8_t index)
+{
+    rf_ifq = true;
+}
+/**
+ * @brief 射频初始化
+ * 
+ * @param agr0 
+ * @param agr1_ptr 无线工作状态响应回调
+ *          产生回调给外部使用,@rfRxCallBack
+ */
+void myRadio_init(int agr0, void *agr1_ptr)
+{
+    myRadio_gpio_init(myRadio_gpioCallback);
+    
+/**-------------------------radio init----------------------------------**/
+    uint32_t ret = 0;
+#ifdef SPI_SOFT_3LINE
+    PAN3029_write_reg(REG_SYS_CTL, 0x03);
+    PAN3029_write_reg(0x1A, 0x83);
+#endif
+
+	ret = rf_init();
+	if(ret != OK)
+	{
+		// printf("  RF Init Fail");
+		while(1);
+	}
+
+	rf_set_default_para();
+
+    rf_set_dcdc_mode(regulatorMode);
+/**-------------------------radio init end----------------------------------**/
+    myRadio_delay(10);
+    RF_EXT_PA_TO_IDLE();
+    if ((rfRxCallBack )agr1_ptr)
+    {
+        rxCb = (rfRxCallBack )agr1_ptr;
+    }
+    rf_handle = 0xe5;
+}
+void RadioSetregulatorMode(uint8_t mode)
+{
+    regulatorMode = mode;
+}
+/**
+ * @brief 射频底层执行程序
+ *      要放在主循环中执行
+ * 
+ */
+void myRadio_process(void)
+{
+    rfRxPacket_ts rfRxPacket;
+    if (rf_handle == 0)
+    {
+        return;
+    }
+    if (rf_ifq == false)
+    {
+        return;
+    }
+    rf_ifq = false;
+    if (!((rf_workProcess == RF_PRC_TX) || (rf_workProcess == RF_PRC_RX)))
+    {
+        return;
+    }
+
+    uint8_t plhd_len;
+    uint8_t irq = rf_get_irq();
+
+    if(irq & REG_IRQ_RX_PLHD_DONE)
+    {
+        plhd_len = rf_get_plhd_len();
+        rf_set_recv_flag(RADIO_FLAG_PLHDRXDONE);
+        RxDoneParams.PlhdSize = rf_plhd_receive(RxDoneParams.PlhdPayload,plhd_len);
+        //PAN3029_rst();//stop it
+
+    }
+    if(irq & REG_IRQ_RX_DONE)
+    {
+        RxDoneParams.Snr = rf_get_snr();
+        RxDoneParams.Rssi = rf_get_rssi();
+        rf_set_recv_flag(RADIO_FLAG_RXDONE);
+        RxDoneParams.Size = rf_receive(RxDoneParams.Payload);
+        rf_set_recv_flag(RADIO_FLAG_IDLE); 
+        if (rxCb)
+        {
+            rfRxPacket.rssi = RxDoneParams.Rssi;
+            rfRxPacket.len = RxDoneParams.Size;
+            memcpy(rfRxPacket.payload, RxDoneParams.Payload, RxDoneParams.Size);
+            rxCb(RX_STA_SECCESS, rfRxPacket);
+        }
+        
+    }
+    if(irq & REG_IRQ_CRC_ERR)
+    {
+        rf_set_recv_flag(RADIO_FLAG_RXERR);
+        rf_clr_irq();
+
+    }
+    if(irq & REG_IRQ_RX_TIMEOUT)
+    {
+        rf_set_refresh();
+        rf_set_recv_flag(RADIO_FLAG_RXTIMEOUT);
+        rf_clr_irq();
+        rf_set_recv_flag(RADIO_FLAG_IDLE); 
+        RF_EXT_PA_TO_IDLE();
+        if (rxCb)
+        {
+            rxCb(RX_STA_TIMEOUT, rfRxPacket);
+        }
+    }
+    if(irq & REG_IRQ_TX_DONE)
+    {
+        rf_set_transmit_flag(RADIO_FLAG_TXDONE);
+        rf_clr_irq();
+
+        RF_EXT_PA_TO_IDLE();
+        if (rxCb)
+        {
+            rxCb(TX_STA_SECCESS, rfRxPacket);
+        }
+    }
+}
+/**
+ * @brief 退出射频进入休眠
+ * 
+ */
+void myRadio_abort(void)
+{
+    if (rf_handle == 0)
+    {
+        return;
+    }
+    RF_EXT_PA_TO_IDLE();
+    // rf_deepsleep();
+    rf_sleep();
+}
+/**
+ * @brief 获取射频工作中心频率
+ * 
+ * @return uint32_t 
+ */
+uint32_t myRadio_getFrequency(void)
+{
+    if (rf_handle == 0)
+    {
+        return 0;
+    }
+    return rfFrequence;
+}
+/**
+ * @brief 设置射频工作中心频率
+ * 
+ * @param freq 
+ *      具体频点,单位:Hz
+ */
+void myRadio_setFrequency(uint32_t freq)
+{
+    if (rf_handle == 0)
+    {
+        return;
+    }
+    rfFrequence = freq;
+    rf_set_para(RF_PARA_TYPE_FREQ, rfFrequence);
+}
+/**
+ * @brief 获取发射功率
+ * 
+ * @return int8_t 
+ */
+int8_t myRadio_getTxPower(void)
+{
+    if (rf_handle == 0)
+    {
+        return 0;
+    }
+    return rfTxPower;
+}
+/**
+ * @brief 设置发射功率
+ * 
+ * @param power 
+ *          单位:dbm
+ */
+void myRadio_setTxPower(int8_t power)
+{
+    if (rf_handle == 0)
+    {
+        return;
+    }
+    rfTxPower = power;
+    rf_set_para(RF_PARA_TYPE_TXPOWER, rfTxPower);
+}
+/**
+ * 获取射频波特率
+ * @param : br->
+*/
+uint32_t myRadio_getBaudrate(void)
+{
+    if (rf_handle == 0)
+    {
+        return 0;
+    }
+    return rfBaudrate;
+}
+/**
+ * 设置射频波特率
+ * @param : br->
+*/
+void myRadio_setBaudrate(uint32_t br)
+{
+    if (rf_handle == 0)
+    {
+        return;
+    }
+    rfBaudrate = br;
+    rf_set_para(RF_PARA_TYPE_CR, loraBaudrateFrame[br].ErrorCoding);
+    rf_set_para(RF_PARA_TYPE_BW, loraBaudrateFrame[br].SignalBw);
+    rf_set_para(RF_PARA_TYPE_SF, loraBaudrateFrame[br].SpreadingFactor);
+    rf_set_ldr(LDR_OFF);
+}
+void myRadio_setRfParams(uint8_t sf, uint8_t bw, uint8_t cr)
+{
+    if (rf_handle == 0)
+    {
+        return;
+    }
+    rf_sf = sf;
+    rf_bw = bw;
+    rf_cr = cr;
+    rf_set_para(RF_PARA_TYPE_CR, cr);
+    rf_set_para(RF_PARA_TYPE_BW, bw);
+    rf_set_para(RF_PARA_TYPE_SF, sf);
+    rf_set_ldr(LDR_OFF);
+}
+/**
+ * @brief 设置模组型号
+ * 
+ * @param type 
+ */
+void myRadio_setChipType(uint8_t type)
+{
+    chipType = type;
+}
+/**
+ * @brief 获取模组型号
+ * 
+ * @return uint8_t 
+ */
+uint8_t myRadio_getChipType(void)
+{
+    return chipType;
+}
+int16_t myRadio_getRssi(void)
+{
+    return (int16_t)PAN3029_get_rssi();
+}
+/**
+ * @brief 无线发送数据包
+ * 
+ * @param packet 
+ */
+void myRadio_transmit(rfTxPacket_ts *packet)
+{
+    if (rf_handle == 0)
+    {
+        return;
+    }
+    RF_EXT_PA_TO_TX();
+    uint32_t getTxtime;
+    if (rf_get_mode() == PAN3029_MODE_DEEP_SLEEP)
+    {
+        rf_deepsleep_wakeup();
+        myRadio_setFrequency(rfFrequence);
+        myRadio_setTxPower(rfTxPower);
+        myRadio_setRfParams(rf_sf, rf_bw, rf_cr);
+        myRadio_delay(10);
+    }
+    if (rf_get_mode() == PAN3029_MODE_SLEEP)
+    {
+        rf_sleep_wakeup();
+        myRadio_delay(10);
+    }
+    
+    if(rf_single_tx_data(packet->payload, packet->len, &packet->absTime) != OK)	
+    {
+    }
+    else
+    {
+    }
+    rf_workProcess = RF_PRC_TX;
+}
+/**
+ * @brief 进入无线接收
+ * 
+ */
+void myRadio_receiver(void)
+{ 
+    if (rf_handle == 0)
+    {
+        return;
+    }
+    RF_EXT_PA_TO_RX();
+    if (rf_get_mode() == PAN3029_MODE_DEEP_SLEEP)
+    {
+        rf_deepsleep_wakeup();
+        myRadio_setFrequency(rfFrequence);
+        myRadio_setTxPower(rfTxPower);
+        myRadio_setRfParams(rf_sf, rf_bw, rf_cr);
+        myRadio_delay(10);
+    }
+    if (rf_get_mode() == PAN3029_MODE_SLEEP)
+    {
+        rf_sleep_wakeup();
+        myRadio_delay(10);
+    }
+    rf_enter_continous_rx();
+    rf_workProcess = RF_PRC_RX;
+}
+void myRadio_setCtrl(controlMode_te mode, uint32_t value)
+{
+    if (rf_handle == 0)
+    {
+        return;
+    }
+    rf_workProcess = RF_PRC_TEST_TX;
+    myRadio_init(0, 0);
+    switch (mode)
+    {
+    case RADIO_EXT_CONTROL_TX_UNMODULATED:
+    {
+        rf_workProcess = RF_PRC_TEST_TX;
+        RF_EXT_PA_TO_TX();
+        PAN3029_set_carrier_wave_on();
+        myRadio_setTxPower(rfTxPower);
+        PAN3029_set_carrier_wave_freq(rfFrequence);
+    }
+        break;
+    case RADIO_EXT_CONTROL_TX_MODULATED:
+    {
+        RF_EXT_PA_TO_TX();
+        PAN3029_set_carrier_wave_on();
+        myRadio_setTxPower(rfTxPower);
+        PAN3029_set_carrier_wave_freq(rfFrequence);
+        rf_workProcess = RF_PRC_TEST_TX;
+    }
+        break;
+    case RADIO_EXT_CONTROL_RX_SENSITIVITY:
+    {
+        RF_EXT_PA_TO_RX();
+        myRadio_receiver();
+        rf_workProcess = RF_PRC_RX;
+    }
+        break;
+    
+    default:
+        break;
+    }
+}
+
+/**-------------------------radio funtion end----------------------------------**/

+ 138 - 0
radio/myRadio.h

@@ -0,0 +1,138 @@
+#ifndef __MY_RADIO_H
+#define __MY_RADIO_H
+/* Includes ------------------------------------------------------------------*/
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+
+#define MAX_RF_PACKET_LEN 255
+
+
+typedef enum
+{
+    RF_TX_PWR_NULL,
+    RF_TX_PWR_N_26,
+    RF_TX_PWR_N_17,
+    RF_TX_PWR_N_5,
+    RF_TX_PWR_N_3,
+    RF_TX_PWR_N_2,
+    RF_TX_PWR_N_1,
+    RF_TX_PWR_P_2,
+    RF_TX_PWR_P_4,
+    RF_TX_PWR_P_5,
+    RF_TX_PWR_P_7,
+    RF_TX_PWR_P_8,
+    RF_TX_PWR_P_9,
+    RF_TX_PWR_P_10,
+    RF_TX_PWR_P_11,
+    RF_TX_PWR_P_12,
+    RF_TX_PWR_P_13,
+    RF_TX_PWR_P_14,
+    RF_TX_PWR_P_15,
+    RF_TX_PWR_P_16,
+    RF_TX_PWR_P_17,
+    RF_TX_PWR_P_18,
+    RF_TX_PWR_P_19,
+    RF_TX_PWR_P_20,
+    RF_TX_PWR_MAX_COUNT,
+}rf_txPwr_te;
+typedef enum
+{
+    DVTP_VG4130S433N0S1,
+    DVTP_VG4130S490N0S1,
+    DVTP_VG4130S868N0S1,
+    DVTP_VG4130S915N0S1,
+    DVTP_MAX_COUNT,
+}deviceType_te;
+
+typedef enum
+{
+    RF_BAUDRATE_RESV1,  
+    RF_BAUDRATE_RESV2,  
+    RF_BAUDRATE_1220,   
+    RF_BAUDRATE_2440,   
+    RF_BAUDRATE_5000,   
+    RF_BAUDRATE_12500,  
+    RF_BAUDRATE_20400,  
+    RF_BAUDRATE_62500,  
+    MAX_RF_BAUDRATE_COUNT,    //
+}rfBaudrate_te;
+typedef enum
+{
+    FREQ_BAND_315,
+    FREQ_BAND_433,
+    FREQ_BAND_490,
+    FREQ_BAND_868,
+    FREQ_BAND_915,
+    MAX_FREQ_BAND_COUNT,
+}freqBand_te;
+//! \brief Structure for the TX Packet
+typedef struct
+{
+    uint8_t rmvAddr[8];              //
+    uint32_t absTime;                //
+    uint8_t len;                     //
+    uint8_t payload[MAX_RF_PACKET_LEN];       //
+} rfTxPacket_ts;
+
+typedef struct
+{
+    uint8_t rmvAddr[8];              //
+    int16_t rssi;                     //
+    uint32_t absTime;                //
+    uint32_t rxTimeout;              //
+    uint8_t len;                     //
+    uint8_t payload[MAX_RF_PACKET_LEN];
+} rfRxPacket_ts;
+typedef struct
+{
+    uint8_t SignalBw;                   // LORA [0: 7.8 kHz, 1: 10.4 kHz, 2: 15.6 kHz, 3: 20.8 kHz, 4: 31.2 kHz,
+                                        // 5: 41.6 kHz, 6: 62.5 kHz, 7: 125 kHz, 8: 250 kHz, 9: 500 kHz, other: Reserved]  
+    uint8_t SpreadingFactor;            // LORA [6: 64, 7: 128, 8: 256, 9: 512, 10: 1024, 11: 2048, 12: 4096  chips]
+    uint8_t ErrorCoding;                // LORA [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8]
+}loraBaudrateFrame_ts;
+typedef enum 
+{
+    RADIO_EXT_CONTROL_TX_UNMODULATED,   //等婥疏髡薹聆彸
+    RADIO_EXT_CONTROL_RX_SENSITIVITY,   //諉彶鍾鏗僅聆彸
+    RADIO_EXT_CONTROL_TX_MODULATED,   //蟀哿覃秶聆彸
+}controlMode_te;
+typedef enum
+{
+    RX_STA_SECCESS,
+    RX_STA_TIMEOUT,
+    RX_STA_PAYLOAD_ERROR,
+    TX_STA_SECCESS,
+    TX_STA_ERROR,
+}rxStatus_te;
+typedef enum
+{
+    RF_PRC_IDLE,
+    RF_PRC_SLEEP,
+    RF_PRC_TX,
+    RF_PRC_RX,
+    RF_PRC_TEST_TX,
+    RF_PRC_TEST_RX,
+}rfProccess_te;
+typedef void (*rfRxCallBack)(uint8_t status, rfRxPacket_ts packet);
+extern const loraBaudrateFrame_ts loraBaudrateFrame[MAX_RF_BAUDRATE_COUNT];
+
+void myRadio_init(int agr0, void *agr1_ptr);
+void myRadio_abort(void);
+uint32_t myRadio_getFrequency(void);
+void myRadio_setFrequency(uint32_t freq);
+int8_t myRadio_getTxPower(void);
+void myRadio_setTxPower(int8_t power);
+uint32_t myRadio_getBaudrate(void);
+void myRadio_setBaudrate(uint32_t br);
+void myRadio_setRfParams(uint8_t sf, uint8_t bw, uint8_t cr);
+void myRadio_setChipType(uint8_t type);
+uint8_t myRadio_getChipType(void);
+int16_t myRadio_getRssi(void);
+void myRadio_transmit(rfTxPacket_ts *packet);
+void myRadio_receiver(void);
+void myRadio_setCtrl(controlMode_te mode, uint32_t value);
+
+#endif
+

+ 322 - 0
radio/myRadio_gpio.c

@@ -0,0 +1,322 @@
+#include "myRadio_gpio.h"
+#include "stm32f10x.h"
+#include "stm32f10x_exti.h"
+
+RADIO_GPIO_CALLBACK gpioCallback;
+int spiMosiMode = 0;
+//---------------------------射频SPI驱动部分---------------------
+void BOARD_SPI_NSS_H(void)
+{
+    GPIO_WriteBit(BOARD_GPIO_SPI_CSN, BOARD_PIN_H);
+}
+void BOARD_SPI_NSS_L(void)
+{
+    GPIO_WriteBit(BOARD_GPIO_SPI_CSN, BOARD_PIN_L);
+}
+void BOARD_SPI_SCK_H(void)
+{
+    GPIO_WriteBit(BOARD_GPIO_SPI_CLK, BOARD_PIN_H);
+}
+void BOARD_SPI_SCK_L(void)
+{
+    GPIO_WriteBit(BOARD_GPIO_SPI_CLK, BOARD_PIN_L);
+}
+void BOARD_SPI_MISO_H(void)
+{
+    GPIO_WriteBit(BOARD_GPIO_SPI_MISO, BOARD_PIN_H);
+}
+void BOARD_SPI_MISO_L(void)
+{
+    GPIO_WriteBit(BOARD_GPIO_SPI_MISO, BOARD_PIN_L);
+}
+void BOARD_SPI_MOSI_H(void)
+{
+#ifdef SPI_SOFT_3LINE
+    int ret;
+    if (spiMosiMode == 0)
+    {
+        GPIO_InitTypeDef GPIO_InitStructure;
+        GPIO_InitStructure.GPIO_Pin = BOARD_PIN_SPI_MOSI;           
+        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;     
+        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;      
+        GPIO_Init(BOARD_PORT_SPI_MOSI, &GPIO_InitStructure);
+    }
+    spiMosiMode = 1;
+#endif
+    GPIO_WriteBit(BOARD_GPIO_SPI_MOSI, BOARD_PIN_H);
+}
+void BOARD_SPI_MOSI_L(void)
+{
+#ifdef SPI_SOFT_3LINE
+    int ret;
+    if (spiMosiMode == 0)
+    {
+        GPIO_InitTypeDef GPIO_InitStructure;
+        GPIO_InitStructure.GPIO_Pin = BOARD_PIN_SPI_MOSI;           
+        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;     
+        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;      
+        GPIO_Init(BOARD_PORT_SPI_MOSI, &GPIO_InitStructure);
+    }
+    spiMosiMode = 1;
+#endif
+    GPIO_WriteBit(BOARD_GPIO_SPI_MOSI, BOARD_PIN_L);
+}
+uint8_t READ_BOARD_SPI_MISO(void)
+{
+#ifndef SPI_SOFT_3LINE
+    return GPIO_ReadInputDataBit(BOARD_GPIO_SPI_MISO);
+#else
+    int ret;
+    if (spiMosiMode == 1)
+    {
+        GPIO_InitTypeDef GPIO_InitStructure;
+        GPIO_InitStructure.GPIO_Pin = BOARD_PIN_SPI_MOSI;           
+        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;     
+        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;      
+        GPIO_Init(BOARD_PORT_SPI_MOSI, &GPIO_InitStructure);
+    }
+    spiMosiMode = 0;
+    ret = GPIO_ReadInputDataBit(BOARD_GPIO_SPI_MOSI);
+    return ret;
+#endif
+}
+
+//---------------------------射频驱动IO部分---------------------
+void RF_PAN3029_IRQ_H(void)
+{
+    GPIO_WriteBit(RF_PAN3029_IRQ, BOARD_PIN_H);
+}
+void RF_PAN3029_IRQ_L(void)
+{
+    GPIO_WriteBit(RF_PAN3029_IRQ, BOARD_PIN_L);
+}
+void RF_PAN3029_NRST_H(void)
+{
+    GPIO_WriteBit(RF_PAN3029_NRST, BOARD_PIN_H);
+}
+void RF_PAN3029_NRST_L(void)
+{
+    GPIO_WriteBit(RF_PAN3029_NRST, BOARD_PIN_L);
+}
+void RF_PAN3029_IO3_H(void)
+{
+    GPIO_WriteBit(RF_PAN3029_IO3, BOARD_PIN_H);
+}
+void RF_PAN3029_IO3_L(void)
+{
+    GPIO_WriteBit(RF_PAN3029_IO3, BOARD_PIN_L);
+}
+void RF_EXT_PA_RE_H(void)
+{
+    GPIO_WriteBit(RF_EXTPA_RE, BOARD_PIN_H);
+}
+void RF_EXT_PA_RE_L(void)
+{
+    GPIO_WriteBit(RF_EXTPA_RE, BOARD_PIN_L);
+}
+void RF_EXT_PA_TE_H(void)
+{
+    GPIO_WriteBit(RF_EXTPA_TE, BOARD_PIN_H);
+}
+void RF_EXT_PA_TE_L(void)
+{
+    GPIO_WriteBit(RF_EXTPA_TE, BOARD_PIN_L);
+}
+uint8_t READ_RF_PAN3029_IRQ(void)
+{
+    return GPIO_ReadInputDataBit(RF_PAN3029_IRQ);
+}
+void EXTI0_IRQHandler(void)
+{
+    if(EXTI_GetITStatus(EXTI_Line0) != RESET)
+    {
+        /* Clear the EXTI line 1 pending bit */
+        EXTI_ClearITPendingBit(EXTI_Line0);
+        if (READ_RF_PAN3029_IRQ())
+        {
+            gpioCallback(1);
+        }
+        
+    }
+}
+// BOARD_GPIOB
+void myRadio_gpio_irq_init()
+{
+    NVIC_InitTypeDef  NVIC_InitStructure;
+    EXTI_InitTypeDef  EXTI_InitStructure;
+    GPIO_InitTypeDef  GPIO_InitStructure;
+
+    GPIO_InitStructure.GPIO_Pin = RF_PAN3029_IRQ_PIN;         
+    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  
+    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;      
+    GPIO_Init(RF_PAN3029_IRQ_PORT, &GPIO_InitStructure);
+
+    EXTI_ClearITPendingBit(EXTI_Line0);
+    EXTI_InitStructure.EXTI_Line = EXTI_Line0;
+    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
+    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
+    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
+    EXTI_Init(&EXTI_InitStructure);
+    GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource0);
+    /* Enable and set EXTI1 Interrupt */
+    NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
+    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;
+    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;
+    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
+    NVIC_Init(&NVIC_InitStructure);
+}
+void myRadio_gpio_init(RADIO_GPIO_CALLBACK cb)
+{
+    GPIO_InitTypeDef  GPIO_InitStructure;
+	SPI_InitTypeDef  SPI_InitStructure;
+    
+#if defined(SPI_HARD)    
+    //----------SPI1时钟使能
+    RCC_APB2PeriphClockCmd(	RCC_APB2Periph_SPI1, ENABLE );
+
+	GPIO_InitStructure.GPIO_Pin = BOARD_PIN_SPI_CLK | BOARD_PIN_SPI_MISO | BOARD_PIN_SPI_MOSI;
+	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出
+	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
+	GPIO_Init(BOARD_PORT_SPI_CLK, &GPIO_InitStructure);
+
+    GPIO_SetBits(BOARD_GPIO_SPI_CLK | BOARD_PIN_SPI_MISO | BOARD_PIN_SPI_MOSI);
+    /*!< SPI configuration */
+    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
+    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
+    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
+    SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
+    SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
+    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
+    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;
+
+    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
+    SPI_InitStructure.SPI_CRCPolynomial = 7;
+    SPI_Init(SPI1, &SPI_InitStructure);
+
+    /*!< Enable the SPI1  */
+    SPI_Cmd(SPI1, ENABLE);
+#else
+
+    GPIO_InitStructure.GPIO_Pin = BOARD_PIN_SPI_MOSI;           
+    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;      
+    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;      
+    GPIO_Init(BOARD_PORT_SPI_MOSI, &GPIO_InitStructure);
+#ifndef SPI_SOFT_3LINE
+    GPIO_InitStructure.GPIO_Pin = BOARD_PIN_SPI_MISO;           
+    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;     
+    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;      
+    GPIO_Init(BOARD_PORT_SPI_MISO, &GPIO_InitStructure);
+#endif
+    GPIO_InitStructure.GPIO_Pin = BOARD_PIN_SPI_CLK;            
+    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;      
+    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;      
+    GPIO_Init(BOARD_PORT_SPI_CLK, &GPIO_InitStructure);
+    BOARD_SPI_SCK_L();
+
+#endif
+    GPIO_InitStructure.GPIO_Pin = BOARD_PIN_SPI_CSN;            
+    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;      
+    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;      
+    GPIO_Init(BOARD_PORT_SPI_CSN, &GPIO_InitStructure);
+
+    GPIO_InitStructure.GPIO_Pin = RF_PAN3029_IRQ_PIN;            
+    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;      
+    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;      
+    GPIO_Init(RF_PAN3029_IRQ_PORT, &GPIO_InitStructure);
+    GPIO_InitStructure.GPIO_Pin = RF_PAN3029_NRST_PIN;            
+    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;      
+    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;      
+    GPIO_Init(RF_PAN3029_NRST_PORT, &GPIO_InitStructure);
+    GPIO_InitStructure.GPIO_Pin = RF_PAN3029_IO3_PIN;            
+    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;      
+    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;      
+    GPIO_Init(RF_PAN3029_IO3_PORT, &GPIO_InitStructure);
+    GPIO_InitStructure.GPIO_Pin = RF_PAN3029_IO11_PIN;            
+    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;      
+    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;      
+    GPIO_Init(RF_PAN3029_IO11_PORT, &GPIO_InitStructure);
+
+    GPIO_InitStructure.GPIO_Pin = RF_EXTPA_RE_PIN;            
+    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;      
+    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;      
+    GPIO_Init(RF_EXTPA_RE_PORT, &GPIO_InitStructure);
+    GPIO_InitStructure.GPIO_Pin = RF_EXTPA_TE_PIN;            
+    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;      
+    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;      
+    GPIO_Init(RF_EXTPA_TE_PORT, &GPIO_InitStructure);
+
+    BOARD_SPI_NSS_H();
+    RF_PAN3029_NRST_H();
+    myRadio_gpio_irq_init();
+    gpioCallback = cb;
+}
+uint8_t myRadioSpi_rwByte(uint8_t byteToWrite)
+{
+    uint16_t i;
+    uint8_t temp;
+    temp = 0;   
+#if defined(SPI_HARD)
+	while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET) //检查指定的SPI标志位设置与否:发送缓存空标志位
+    {
+        i++;
+        if(i > 2000)return 0;
+    }			  
+	SPI_I2S_SendData(SPI1, byteToWrite); //通过外设SPIx发送一个数据
+	i=0;
+
+	while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET)//检查指定的SPI标志位设置与否:接受缓存非空标志位
+    {
+        i++;
+        if(i > 2000)return 0;
+    }
+    /*!< Return the byte read from the SPI bus */
+    temp = SPI_I2S_ReceiveData(SPI1);
+#else
+    BOARD_SPI_SCK_L();
+    for(i = 0; i < 8; i ++)
+    {
+        if(byteToWrite & 0x80)
+        {
+            BOARD_SPI_MOSI_H();
+        }
+        else
+        {
+            BOARD_SPI_MOSI_L();
+        } 
+
+        byteToWrite <<= 1;
+
+        BOARD_SPI_SCK_H();
+        temp <<= 1;
+        if(READ_BOARD_SPI_MISO())
+        {
+            temp ++; 
+        }
+        BOARD_SPI_SCK_L();
+    }
+#endif
+	return temp;
+}
+
+void myRadioSpi_wBuffer(uint8_t* pData, uint8_t len)
+{
+    uint8_t i;
+    
+    for(i = 0; i < len; i++)
+    {
+        myRadioSpi_rwByte(*pData);
+        pData ++;
+    }
+}
+
+void myRadioSpi_rBuffer(uint8_t* pData, uint8_t len)
+{
+    uint8_t i;
+    
+    for(i = 0; i < len; i++)
+    {
+        *pData = myRadioSpi_rwByte(0xFF);
+        pData ++;
+    }
+}
+

+ 89 - 0
radio/myRadio_gpio.h

@@ -0,0 +1,89 @@
+
+#ifndef __MYRADIO_GPIO_H_
+#define __MYRADIO_GPIO_H_
+
+#include <stdint.h>
+
+#include "stm32f10x.h"
+#include "stm32f10x_gpio.h"
+#include "stm32f10x_spi.h"
+#include "board.h"
+
+#ifndef SPI_SOFT_3LINE
+    #define SPI_HARD
+#endif
+// #define SPI_SOFT_3LINE
+
+typedef void (*RADIO_GPIO_CALLBACK)(uint8_t index);
+
+//-------------射频模块引脚映射到转接板排针---------------
+#define BOARD_PIN_SPI_CLK       GPIO_Pin_5     //SPI1_SCK(8)
+#define BOARD_PORT_SPI_CLK      GPIOA          //DAC_OUT2 ADC12_IN5
+#define BOARD_GPIO_SPI_CLK      BOARD_PORT_SPI_CLK, BOARD_PIN_SPI_CLK          //
+
+#define BOARD_PIN_SPI_MISO      GPIO_Pin_6    //SPI1_MISO(8)
+#define BOARD_PORT_SPI_MISO     GPIOA         // TIM8_BKIN/ADC12_IN6
+                                              // TIM3_CH1(8)
+#define BOARD_GPIO_SPI_MISO     BOARD_PORT_SPI_MISO, BOARD_PIN_SPI_MISO         //
+
+#define BOARD_PIN_SPI_MOSI      GPIO_Pin_7    //SPI1_MOSI(8)/
+#define BOARD_PORT_SPI_MOSI     GPIOA         // TIM8_CH1N/ADC12_IN7
+                                            // TIM3_CH2(8)
+#define BOARD_GPIO_SPI_MOSI     BOARD_PORT_SPI_MOSI, BOARD_PIN_SPI_MOSI         //
+
+#define BOARD_PIN_SPI_CSN       GPIO_Pin_4     //SPI1_NSS(8)/
+#define BOARD_PORT_SPI_CSN      GPIOA          // USART2_CK(8)
+                                               // DAC_OUT1/ADC12_IN4
+#define BOARD_GPIO_SPI_CSN      BOARD_PORT_SPI_CSN, BOARD_PIN_SPI_CSN          //
+//用于射频中断响应
+#define RF_PAN3029_IRQ_PIN      GPIO_Pin_0  //
+#define RF_PAN3029_IRQ_PORT     GPIOB
+#define RF_PAN3029_IRQ          RF_PAN3029_IRQ_PORT, RF_PAN3029_IRQ_PIN          //
+//
+#define RF_PAN3029_NRST_PIN     GPIO_Pin_1  //
+#define RF_PAN3029_NRST_PORT    GPIOB
+#define RF_PAN3029_NRST         RF_PAN3029_NRST_PORT, RF_PAN3029_NRST_PIN          //
+//
+#define RF_PAN3029_IO3_PIN      GPIO_Pin_5  //
+#define RF_PAN3029_IO3_PORT     GPIOC
+#define RF_PAN3029_IO3          RF_PAN3029_IO3_PORT, RF_PAN3029_IO3_PIN          //
+//
+#define RF_PAN3029_IO11_PIN     GPIO_Pin_2  //
+#define RF_PAN3029_IO11_PORT    GPIOA
+#define RF_PAN3029_IO11         RF_PAN3029_IO11_PORT, RF_PAN3029_IO11_PIN          //
+//用于大功率模块的PA和LNA控制脚
+#define RF_EXTPA_RE_PIN         GPIO_Pin_10  //
+#define RF_EXTPA_RE_PORT        GPIOB
+#define RF_EXTPA_RE             RF_EXTPA_RE_PORT, RF_EXTPA_RE_PIN          //
+#define RF_EXTPA_TE_PIN         GPIO_Pin_11  //
+#define RF_EXTPA_TE_PORT        GPIOB
+#define RF_EXTPA_TE             RF_EXTPA_TE_PORT, RF_EXTPA_TE_PIN          //
+//-------------射频模块引脚映射到转接板排针---------------END
+
+uint8_t READ_RF_PAN3029_IRQ(void);
+void RF_PAN3029_IRQ_H(void);
+void RF_PAN3029_IRQ_L(void);
+
+void RF_EXT_PA_RE_H(void);
+void RF_EXT_PA_RE_L(void);
+void RF_EXT_PA_TE_H(void);
+void RF_EXT_PA_TE_L(void);
+
+#define RF_EXT_PA_TO_TX() RF_EXT_PA_TE_H();RF_EXT_PA_RE_L()
+#define RF_EXT_PA_TO_RX() RF_EXT_PA_TE_L();RF_EXT_PA_RE_H()
+#define RF_EXT_PA_TO_IDLE() RF_EXT_PA_TE_L();RF_EXT_PA_RE_L()
+
+void BOARD_SPI_NSS_H(void);
+void BOARD_SPI_NSS_L(void);
+
+//-------------将封装的API映射到射频模块硬件层---------------
+void myRadio_gpio_init(RADIO_GPIO_CALLBACK cb);
+uint8_t myRadioSpi_rwByte(uint8_t byteToWrite);
+void myRadioSpi_wBuffer(uint8_t* pData, uint8_t len);
+void myRadioSpi_rBuffer(uint8_t* pData, uint8_t len);
+
+#define SpiReadWrite(p)         myRadioSpi_rwByte(p)
+#define SpiWriteData(p1, p2)    myRadioSpi_wBuffer(p2, p1)
+#define SpiReadData(p1, p2)     myRadioSpi_rBuffer(p2, p1)
+//-------------将封装的API映射到射频模块硬件层---------------END
+#endif

+ 3337 - 0
radio/pan3029.c

@@ -0,0 +1,3337 @@
+/*******************************************************************************
+ * @note Copyright (C) 2023 Shanghai Panchip Microelectronics Co., Ltd. All rights reserved.
+ *
+ * @file pan3029.c
+ * @brief
+ *
+ * @history - V0.7, 2024-3
+*******************************************************************************/
+#include "pan3029_port.h"
+
+uint8_t RadioRxPayload[255];
+uint8_t plhd_buf[16];
+bool pan3029_irq_trigged_flag = false;
+uint8_t reg_agc_value[40] = {0x06,0x00,0xf8,0x06,0x06,0x00,\
+                             0xf8,0x06,0x06,0x00,0xf8,0x06,0x06,0x00,0xf8,0x06,0x14,0xc0,0xf9,0x14,0x22,0xd4,\
+                             0xf9,0x22,0x30,0xd8,0xf9,0x30,0x3e,0xde,0xf9,0x3e,0x0e,0xff,0x80,0x4f,0x12,0x80,\
+                             0x38,0x01
+                            };
+
+uint8_t reg_agc_freq400[40] = {0x06,0x00,0xf8,0x06,0x06,0x00,\
+                               0xf8,0x06,0x06,0x00,0xf8,0x06,0x06,0x00,0xf8,0x06,0x14,0xc0,0xf9,0x14,0x22,0xd4,\
+                               0xf9,0x22,0x30,0xd8,0xf9,0x30,0x3e,0xde,0xf9,0x3e,0x0e,0xff,0x80,0x4f,0x12,0x80,\
+                               0x38,0x01
+                              };
+uint8_t reg_agc_freq800[40] = {0x09,0x80,0xf3,0x09,0x09,0x80,\
+                               0xf3,0x09,0x09,0x80,0xf3,0x09,0x09,0x80,0xf3,0x09,0x14,0x06,0xf0,0x14,0x22,0xc6,\
+                               0xf1,0x22,0x31,0x73,0xf0,0x31,0x3f,0xde,0xf1,0x3f,0x0e,0xff,0xe0,0x32,0x29,0x80,\
+                               0x38,0x01
+                              };
+
+const power_ramp_t power_ramp[PAN3029_MAX_RAMP][4]=
+{
+    {{0x01, 0x0b, 0x01, 0xff}, {0x01, 0x06, 0x00, 0xff}, {0x01, 0x07, 0x01, 0xff}, {0x01, 0x06, 0x01, 0xff}},
+    {{0x01, 0x0b, 0x00, 0xff}, {0x01, 0x06, 0x00, 0x00}, {0x01, 0x0b, 0x00, 0xff}, {0x01, 0x0b, 0x01, 0xff}},
+    {{0x03, 0x02, 0x01, 0xff}, {0x03, 0x04, 0x01, 0x00}, {0x03, 0x00, 0x01, 0xff}, {0x01, 0x0b, 0x00, 0xff}},
+    {{0x03, 0x08, 0x01, 0xff}, {0x03, 0x00, 0x01, 0x01}, {0x03, 0x06, 0x01, 0xff}, {0x03, 0x01, 0x01, 0xff}},
+    {{0x03, 0x0b, 0x00, 0xff}, {0x03, 0x00, 0x01, 0xff}, {0x03, 0x0b, 0x00, 0xff}, {0x03, 0x07, 0x01, 0xff}},
+    {{0x05, 0x00, 0x01, 0xff}, {0x03, 0x0b, 0x01, 0xff}, {0x05, 0x00, 0x01, 0xff}, {0x03, 0x0b, 0x00, 0xff}},
+    {{0x05, 0x03, 0x01, 0xff}, {0x05, 0x01, 0x01, 0x00}, {0x05, 0x03, 0x01, 0xff}, {0x05, 0x00, 0x01, 0xff}},
+    {{0x05, 0x08, 0x01, 0xff}, {0x07, 0x00, 0x01, 0x00}, {0x05, 0x0b, 0x01, 0xff}, {0x05, 0x05, 0x01, 0xff}},
+    {{0x05, 0x09, 0x00, 0xff}, {0x07, 0x02, 0x01, 0x00}, {0x07, 0x00, 0x01, 0xff}, {0x07, 0x00, 0x01, 0xff}},
+    {{0x07, 0x02, 0x01, 0xff}, {0x0d, 0x01, 0x01, 0x00}, {0x07, 0x02, 0x01, 0xff}, {0x07, 0x04, 0x01, 0xff}},
+    {{0x07, 0x05, 0x01, 0xff}, {0x0d, 0x02, 0x01, 0x00}, {0x09, 0x00, 0x01, 0xff}, {0x07, 0x0b, 0x01, 0xff}},
+    {{0x07, 0x0b, 0x01, 0xff}, {0x0d, 0x04, 0x01, 0x00}, {0x09, 0x02, 0x01, 0xff}, {0x09, 0x03, 0x01, 0xff}},
+    {{0x07, 0x0b, 0x00, 0xff}, {0x0d, 0x06, 0x01, 0x00}, {0x09, 0x05, 0x01, 0xff}, {0x0b, 0x02, 0x01, 0xff}},
+    {{0x0b, 0x03, 0x01, 0xff}, {0x0d, 0x09, 0x01, 0x00}, {0x0b, 0x03, 0x01, 0xff}, {0x0b, 0x04, 0x01, 0xff}},
+    {{0x0b, 0x05, 0x01, 0xff}, {0x15, 0x04, 0x01, 0x01}, {0x0b, 0x06, 0x01, 0xff}, {0x0d, 0x04, 0x01, 0xff}},
+    {{0x15, 0x04, 0x01, 0xff}, {0x15, 0x05, 0x01, 0x01}, {0x0b, 0x0b, 0x01, 0xff}, {0x0d, 0x07, 0x01, 0xff}},
+    {{0x15, 0x05, 0x01, 0xff}, {0x15, 0x07, 0x01, 0x01}, {0x0d, 0x08, 0x01, 0xff}, {0x15, 0x05, 0x01, 0xff}},
+    {{0x15, 0x07, 0x01, 0xff}, {0x15, 0x08, 0x01, 0x01}, {0x15, 0x06, 0x01, 0xff}, {0x15, 0x07, 0x01, 0xff}},
+    {{0x15, 0x01, 0x00, 0xff}, {0x15, 0x01, 0x00, 0x02}, {0x15, 0x08, 0x01, 0xff}, {0x15, 0x09, 0x01, 0xff}},
+    {{0x15, 0x03, 0x00, 0xff}, {0x15, 0x03, 0x00, 0x02}, {0x15, 0x02, 0x00, 0xff}, {0x15, 0x03, 0x00, 0xff}},
+    {{0x15, 0x05, 0x00, 0xff}, {0x15, 0x05, 0x00, 0xff}, {0x15, 0x05, 0x00, 0xff}, {0x15, 0x05, 0x00, 0xff}},
+    {{0x15, 0x06, 0x00, 0xff}, {0x15, 0x06, 0x00, 0xff}, {0x15, 0x06, 0x00, 0xff}, {0x15, 0x06, 0x00, 0xff}},
+};
+
+
+const power_ramp_cfg_t power_ramp_cfg[PAN3029_MAX_RAMP+1]=
+{
+    /*ramp, trim+ldo, bandsel+duty+PAbias(0/1)*/
+    {0x01, 0x01, 0x00},
+    {0x03, 0x01, 0x01},
+    {0x03, 0xf0, 0x30},
+    {0x05, 0x01, 0x81},
+    {0x05, 0xa1, 0x81},
+    {0x05, 0xf0, 0x81},
+    {0x07, 0x01, 0x81},
+    {0x05, 0x01, 0x80},
+    {0x05, 0x31, 0x80},
+    {0x07, 0x01, 0x80},
+    {0x07, 0x21, 0x80},
+    {0x0b, 0x11, 0x80},
+    {0x0b, 0x21, 0x80},
+    {0x0b, 0x41, 0x80},
+    {0x0b, 0x61, 0x80},
+    {0x0b, 0x91, 0x80},
+    {0x0b, 0xb1, 0x80},
+    {0x0d, 0xb1, 0x80},
+    {0x0f, 0xb1, 0x80},
+    {0x11, 0x50, 0x80},
+    {0x15, 0x30, 0x20},
+    {0x15, 0x50, 0x70},
+    {0x15, 0x60, 0x70},
+};
+
+
+/**
+ * @brief read one byte from register in current page
+ * @param[in] <addr> register address to write
+ * @return value read from register
+ */
+uint8_t PAN3029_read_reg(uint8_t addr)
+{
+    uint8_t temreg = 0x00;
+
+    rf_port.spi_cs_low();
+    rf_port.spi_readwrite(0x00 | (addr<<1));
+    temreg=rf_port.spi_readwrite(0x00);
+    rf_port.spi_cs_high();
+    return temreg;
+}
+
+/**
+ * @brief write global register in current page and chick
+ * @param[in] <addr> register address to write
+ * @param[in] <value> address value to write to rgister
+ * @return result
+ */
+uint8_t PAN3029_write_reg(uint8_t addr,uint8_t value)
+{
+    uint8_t tmpreg = 0;
+    uint8_t addr_w = (0x01 | (addr << 1));
+
+    rf_port.spi_cs_low();
+    rf_port.spi_readwrite(addr_w);
+    rf_port.spi_readwrite(value);
+    rf_port.spi_cs_high();
+    if(SPI_WRITE_CHECK)
+    {
+        tmpreg = PAN3029_read_reg(addr);
+        if(tmpreg == value)
+        {
+            return OK;
+        }
+        else
+        {
+            return FAIL;
+        }
+    } else
+    {
+        return OK;
+    }
+
+}
+
+/**
+ * @brief rf send data fifo,send bytes register
+ * @param[in] <addr> register address to write
+ * @param[in] <buffer> send data buffer
+ * @param[in] <size> send data size
+ * @return none
+ */
+void PAN3029_write_fifo(uint8_t addr,uint8_t *buffer,int size)
+{
+    int i;
+    uint8_t addr_w = (0x01 | (addr << 1));
+
+    rf_port.spi_cs_low();
+    rf_port.spi_readwrite(addr_w);
+    for(i =0; i<size; i++)
+    {
+        rf_port.spi_readwrite(buffer[i]);
+    }
+    rf_port.spi_cs_high();
+}
+
+/**
+ * @brief rf receive data fifo,read bytes from register
+ * @param[in] <addr> register address to write
+ * @param[in] <buffer> receive data buffer
+ * @param[in] <size> receive data size
+ * @return none
+ */
+void PAN3029_read_fifo(uint8_t addr,uint8_t *buffer,int size)
+{
+    int i;
+    uint8_t addr_w = (0x00 | (addr<<1));
+
+    rf_port.spi_cs_low();
+    rf_port.spi_readwrite(addr_w);
+    for(i =0; i<size; i++)
+    {
+        buffer[i] = rf_port.spi_readwrite(0x00);
+    }
+    rf_port.spi_cs_high();
+}
+
+/**
+ * @brief switch page
+ * @param[in] <page> page to switch
+ * @return result
+ */
+uint32_t PAN3029_switch_page(enum PAGE_SEL page)
+{
+    uint8_t page_sel = 0x00;
+    uint8_t tmpreg = 0x00;
+
+    tmpreg = PAN3029_read_reg(REG_SYS_CTL);
+    page_sel  = (tmpreg & 0xfc )| page;
+    PAN3029_write_reg(REG_SYS_CTL,page_sel);
+    if((PAN3029_read_reg(REG_SYS_CTL) &0x03) == page)
+    {
+        return OK;
+    } else
+    {
+        return FAIL;
+    }
+}
+
+/**
+ * @brief This function write a value to register in specific page
+ * @param[in] <page> the page of register
+ * @param[in] <addr> register address
+ * @param[in] <value> value to write
+ * @return result
+ */
+uint32_t PAN3029_write_spec_page_reg(enum PAGE_SEL page,uint8_t addr,uint8_t value)
+{
+    if(PAN3029_switch_page(page) != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_write_reg(addr, value) != OK)
+    {
+        return FAIL;
+    }
+    else
+    {
+        return OK;
+    }
+}
+
+/**
+ * @brief read a value to register in specific page
+ * @param[in] <page> the page of register
+ * @param[in] <addr> register address
+ * @return success(register value) or failure
+ */
+uint8_t PAN3029_read_spec_page_reg(enum PAGE_SEL page,uint8_t addr)
+{
+    if(PAN3029_switch_page(page) != OK)
+    {
+        return FAIL;
+    }
+    return PAN3029_read_reg(addr);
+}
+
+/**
+ * @brief write continue register valuies(buffer) in specific addr page
+ * @param[in] <page> the page of register
+ * @param[in] <addr> register start address
+ * @param[in] <buffer> values to write
+ * @param[in] <len> buffer len
+ * @return result
+ */
+uint32_t PAN3029_write_read_continue_regs(enum PAGE_SEL page,uint8_t addr,uint8_t *buffer,uint8_t len)
+{
+    uint8_t i,temreg[256];
+    uint16_t addr_w;
+    if(PAN3029_switch_page(page) != OK)
+    {
+        return FAIL;
+    }
+
+    addr_w = (0x01 | (addr << 1));
+    rf_port.spi_cs_low();
+    rf_port.spi_readwrite(addr_w);
+    for(i=0; i<len; i++)
+    {
+        rf_port.spi_readwrite(buffer[i]);
+    }
+    rf_port.spi_cs_high();
+
+    rf_port.spi_cs_low();
+    rf_port.spi_readwrite(0x00 | (addr<<1));
+    for(i=0; i<len; i++)
+    {
+        temreg[i] =rf_port.spi_readwrite(0x00);
+    }
+    rf_port.spi_cs_high();
+
+    for(i=0; i<len; i++)
+    {
+        if(temreg[i] != buffer[i])
+        {
+            return FAIL;
+        }
+    }
+    return OK;
+}
+
+/**
+ * @brief PAN3029 clear all irq
+ * @param[in] <none>
+ * @return result
+ */
+uint8_t PAN3029_clr_irq(void)
+{
+    uint8_t clr_cnt = 0, reg_value;
+    uint16_t a = 0, b = 0;
+    while(clr_cnt < 3)
+    {
+        PAN3029_write_spec_page_reg(PAGE0_SEL, 0x6C, 0x3f);//clr irq
+        reg_value = PAN3029_read_spec_page_reg(PAGE0_SEL, 0x6C);
+        if((reg_value & 0x7f)==0)
+        {
+            return OK;
+        } else {
+            clr_cnt++;
+            for(a=0; a<1200; a++)
+                for(b=0; b<100; b++);
+            continue;
+        }
+    }
+    return FAIL;
+}
+
+/**
+ * @brief get irq status
+ * @param[in] <none>
+ * @return ira status
+ */
+uint8_t PAN3029_get_irq(void)
+{
+    uint8_t tmpreg;
+
+    tmpreg = PAN3029_read_spec_page_reg(PAGE0_SEL, 0x6C);
+
+    return (tmpreg & 0x7f);
+}
+
+/**
+ * @brief RF 1.2V register refresh,Will not change register values
+ * @param[in] <none>
+ * @return result
+ */
+uint32_t PAN3029_refresh(void)
+{
+    uint8_t tmpreg = 0;
+
+    tmpreg = PAN3029_read_reg(REG_SYS_CTL);
+    tmpreg |= 0x80;
+    PAN3029_write_reg(REG_SYS_CTL,tmpreg);
+
+    tmpreg = PAN3029_read_reg(REG_SYS_CTL);
+    tmpreg &= 0x7F;
+
+    PAN3029_write_reg(REG_SYS_CTL,tmpreg);
+    PAN3029_read_reg(REG_SYS_CTL);
+    return OK;
+}
+
+/**
+ * @brief read packet count register
+ * @param[in] <none>
+ * @return packet count
+ */
+uint16_t PAN3029_read_pkt_cnt(void)
+{
+    uint8_t reg_low, reg_high;
+    uint32_t pkt_cnt = 0x00;
+
+    reg_low = PAN3029_read_spec_page_reg(PAGE1_SEL, 0x6c);
+    reg_high = PAN3029_read_spec_page_reg(PAGE1_SEL, 0x6d);
+
+    pkt_cnt = (reg_high << 8) | reg_low;
+    return pkt_cnt;
+}
+
+/**
+ * @brief clear packet count register
+ * @param[in] <none>
+ * @return none
+ */
+void PAN3029_clr_pkt_cnt(void)
+{
+    uint8_t tmpreg;
+
+    tmpreg = PAN3029_read_reg(REG_SYS_CTL);
+    tmpreg = (tmpreg & 0xbf) | 0x40 ;
+    PAN3029_write_reg(REG_SYS_CTL,tmpreg);
+
+    tmpreg = PAN3029_read_reg(REG_SYS_CTL);
+    tmpreg = (tmpreg & 0xbf);
+    PAN3029_write_reg(REG_SYS_CTL,tmpreg);
+}
+
+/**
+ * @brief enable AGC function
+ * @param[in] <state>
+ *			  AGC_OFF/AGC_ON
+ * @return result
+ */
+uint32_t PAN3029_agc_enable(uint32_t state)
+{
+    uint8_t temp_val_1;
+    uint8_t temp_val_2;
+
+    temp_val_1 = PAN3029_read_spec_page_reg(PAGE2_SEL, 0x06);
+
+    if(state == AGC_OFF)
+    {
+        temp_val_2 = (temp_val_1 & 0xfe) | 0x01;
+    }
+    else
+    {
+        temp_val_2 = (temp_val_1 & 0xfe) | 0x00;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE2_SEL, 0x06, temp_val_2)  != OK)
+    {
+        return FAIL;
+    }
+
+    return OK;
+}
+
+/**
+ * @brief configure AGC function
+ * @param[in] <none>
+ * @return result
+ */
+uint32_t PAN3029_agc_config(void)
+{
+    if(PAN3029_write_read_continue_regs(PAGE2_SEL, 0x0a, reg_agc_value, 40)  != OK)
+    {
+        return FAIL;
+    }
+    if(PAN3029_write_spec_page_reg(PAGE2_SEL, 0x34, 0xef)  != OK)
+    {
+        return FAIL;
+    }
+    return OK;
+}
+
+/**
+ * @brief do basic configuration to initialize
+ * @param[in] <none>
+ * @return result
+ */
+uint32_t PAN3029_ft_calibr(void)
+{
+    uint8_t i,tmpreg,cal[0x26]= {0};
+
+    PAN3029_efuse_on();
+
+    for(i = 17; i<20; i++)
+    {
+        cal[0x0d+i] = PAN3029_efuse_read_encry_byte(0x3b,0x5aa5,0x0d+i);
+    }
+
+    if(PAN3029_efuse_read_encry_byte(0x3b,0x5aa5,0x1c) == 0x5a)
+    {
+        PAN3029_write_spec_page_reg(PAGE2_SEL,0x3d,0xfd);
+        if(cal[0x0d+19]!=0)
+            PAN3029_write_spec_page_reg(PAGE0_SEL, 0x45, cal[0x0d+19]);
+
+        if(PAN3029_efuse_read_encry_byte(0x3b,0x5aa5,0x0d) == MODEM_MPA)
+        {
+            tmpreg = PAN3029_read_spec_page_reg(PAGE3_SEL,0x1c);
+            tmpreg &= 0xe0;
+            tmpreg |= (cal[0x1e]&0x1f);
+            PAN3029_write_spec_page_reg(PAGE3_SEL, 0x1c, tmpreg);
+        } else if(PAN3029_efuse_read_encry_byte(0x3b,0x5aa5,0x0d) == MODEM_MPB)
+        {
+            tmpreg = (0xc0 | (cal[0x1e]&0x1f));
+            PAN3029_write_spec_page_reg(PAGE3_SEL, 0x1c, tmpreg);
+        }
+
+        PAN3029_write_spec_page_reg(PAGE3_SEL, 0x1d, cal[0x1f]);
+    }
+    PAN3029_efuse_off();
+
+    return OK;
+}
+
+/**
+ * @brief do basic configuration to initialize
+ * @param[in] <none>
+ * @return result
+ */
+uint32_t PAN3029_init(void)
+{
+    if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x03, 0x1b)  != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x04, 0x76)  != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x06, 0x01)  != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x15, 0x21)  != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x31, 0xd0)  != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x36, 0x66)  != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x37, 0x6b)  != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x38, 0xcc)  != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x39, 0x09)  != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x3c, 0xb4)  != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x3e, 0x42)  != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x40, 0x6a)  != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x41, 0x06)  != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x42, 0xaa)  != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x48, 0x77)  != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x49, 0x77)  != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x4a, 0x77)  != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x4b, 0x05)  != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x4f, 0x04)  != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x50, 0xd2)  != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x5e, 0x80)  != OK)
+    {
+
+        return FAIL;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE1_SEL, 0x03, 0x1b)  != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE1_SEL, 0x04, 0x76)  != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE1_SEL, 0x0b, 0x08)  != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE1_SEL, 0x0f, 0x0a)  != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE1_SEL, 0x19, 0x00)  != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE1_SEL, 0x2f, 0xd0)  != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE1_SEL, 0x43, 0xda)  != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE2_SEL, 0x03, 0x1b)  != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE2_SEL, 0x04, 0x76)  != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE2_SEL, 0x2c, 0xc0)  != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE2_SEL, 0x2d, 0x27)  != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE2_SEL, 0x2e, 0x09)  != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE2_SEL, 0x2f, 0x00)  != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE2_SEL, 0x30, 0x10)  != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE3_SEL, 0x03, 0x1b)  != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE3_SEL, 0x04, 0x76)  != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE3_SEL, 0x0a, 0x0e)  != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE3_SEL, 0x0b, 0xcf) != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE3_SEL, 0x0c, 0x19)  != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE3_SEL, 0x0d, 0x98)  != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE3_SEL, 0x12, 0x16) != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE3_SEL, 0x13, 0x14) != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE3_SEL, 0x16, 0xf4) != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE3_SEL, 0x17, 0x01) != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE3_SEL, 0x1A, 0x83) != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE3_SEL, 0x1f, 0xd9) != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE3_SEL, 0x26, 0x20) != OK)
+    {
+        return FAIL;
+    }
+
+    return OK;
+}
+
+/**
+ * @brief change PAN3029 mode from deep sleep to standby3(STB3)
+ * @param[in] <none>
+ * @return result
+ */
+uint32_t PAN3029_deepsleep_wakeup(void)
+{
+    uint8_t tmpreg;
+    uint8_t rstreg = 0,porreg = 0;
+
+    porreg = PAN3029_read_reg(0x04);
+    porreg |= 0x10;
+    PAN3029_write_reg(0x04, porreg);
+    rf_port.delayus(10);
+    porreg &= 0xEF;
+    PAN3029_write_reg(0x04, porreg);
+    rstreg = PAN3029_read_reg(REG_SYS_CTL);
+    rstreg &= 0x7F;
+    PAN3029_write_reg(REG_SYS_CTL, rstreg);
+    rf_port.delayus(10);
+    rstreg |= 0x80;
+    PAN3029_write_reg(REG_SYS_CTL, rstreg);
+    rf_port.delayus(10);
+    rstreg &= 0x7F;
+    PAN3029_write_reg(REG_SYS_CTL, rstreg);
+    rf_port.delayus(10);
+
+    if(PAN3029_write_reg(REG_OP_MODE, PAN3029_MODE_DEEP_SLEEP) != OK)
+    {
+        return FAIL;
+    }
+    rf_port.delayus(10);
+
+    if(PAN3029_write_reg(REG_OP_MODE, PAN3029_MODE_SLEEP) != OK)
+    {
+        return FAIL;
+    }
+    rf_port.delayus(10);
+
+    tmpreg = PAN3029_read_spec_page_reg(PAGE3_SEL, 0x06);
+    tmpreg |= (1<<5);
+    if(PAN3029_write_spec_page_reg(PAGE3_SEL, 0x06, tmpreg)  != OK)
+    {
+        return FAIL;
+    }
+    rf_port.delayus(10);
+
+    if(PAN3029_write_reg(REG_OP_MODE, PAN3029_MODE_STB1) != OK)
+    {
+        return FAIL;
+    }
+    rf_port.delayus(10);
+
+    if(PAN3029_write_spec_page_reg(PAGE3_SEL, 0x26, 0x2f)  != OK)
+    {
+        return FAIL;
+    }
+    rf_port.delayus(10);
+
+    if(PAN3029_write_reg(0x04, 0x36) != OK)
+    {
+        return FAIL;
+    }
+    rf_port.delayus(10);
+
+    rf_port.tcxo_init();
+
+    if(PAN3029_write_reg(REG_OP_MODE, PAN3029_MODE_STB2) != OK)
+    {
+        return FAIL;
+    }
+    rf_port.delayms(2);
+
+    if(PAN3029_write_reg(REG_OP_MODE, PAN3029_MODE_STB3) != OK)
+    {
+        return FAIL;
+    }
+    else
+    {
+        rf_port.delayus(10);
+        return OK;
+    }
+}
+
+
+/**
+ * @brief change PAN3029 mode from sleep to standby3(STB3)
+ * @param[in] <none>
+ * @return result
+ */
+uint32_t PAN3029_sleep_wakeup(void)
+{
+    uint8_t tmpreg;
+
+    if(PAN3029_write_reg(REG_OP_MODE, PAN3029_MODE_SLEEP) != OK)
+    {
+        return FAIL;
+    }
+    rf_port.delayus(10);
+
+    tmpreg = PAN3029_read_spec_page_reg(PAGE3_SEL, 0x06);
+    tmpreg |= (1<<5);
+    if(PAN3029_write_spec_page_reg(PAGE3_SEL, 0x06, tmpreg)  != OK)
+    {
+        return FAIL;
+    }
+    rf_port.delayus(10);
+
+    if(PAN3029_write_reg(REG_OP_MODE, PAN3029_MODE_STB1) != OK)
+    {
+        return FAIL;
+    }
+    rf_port.delayus(10);
+
+    if(PAN3029_write_spec_page_reg(PAGE3_SEL, 0x26, 0x2f)  != OK)
+    {
+        return FAIL;
+    }
+    rf_port.delayus(10);
+
+    if(PAN3029_write_reg(0x04, 0x36) != OK)
+    {
+        return FAIL;
+    }
+    rf_port.delayus(10);
+
+    rf_port.tcxo_init();
+
+    if(PAN3029_write_reg(REG_OP_MODE, PAN3029_MODE_STB2) != OK)
+    {
+        return FAIL;
+    }
+    rf_port.delayms(2);
+
+    if(PAN3029_write_reg(REG_OP_MODE, PAN3029_MODE_STB3) != OK)
+    {
+        return FAIL;
+    }
+    else
+    {
+        rf_port.delayus(10);
+        return OK;
+    }
+}
+
+/**
+ * @brief change PAN3029 mode from standby3(STB3) to deep sleep, PAN3029 should set DCDC_OFF before enter deepsleep
+ * @param[in] <none>
+ * @return result
+ */
+uint32_t PAN3029_deepsleep(void)
+{
+    uint8_t tmpreg;
+
+    rf_port.delayus(10);
+    if(PAN3029_write_reg(REG_OP_MODE, PAN3029_MODE_STB3) != OK)
+    {
+        return FAIL;
+    }
+    rf_port.delayms(2);
+
+    if(PAN3029_write_reg(REG_OP_MODE, PAN3029_MODE_STB2) != OK)
+    {
+        return FAIL;
+    }
+    rf_port.delayus(10);
+
+    if(PAN3029_write_reg(REG_OP_MODE, PAN3029_MODE_STB1) != OK)
+    {
+        return FAIL;
+    }
+    rf_port.delayus(10);
+
+    rf_port.tcxo_close();
+
+    if(PAN3029_write_reg(0x04, 0x06) != OK)
+    {
+        return FAIL;
+    }
+    rf_port.delayus(10);
+
+    if(PAN3029_write_reg(REG_OP_MODE, PAN3029_MODE_SLEEP) != OK)
+    {
+        return FAIL;
+    }
+    rf_port.delayus(10);
+
+    tmpreg = PAN3029_read_spec_page_reg(PAGE3_SEL, 0x06);
+    tmpreg &= (~(1<<5));
+    if(PAN3029_write_spec_page_reg(PAGE3_SEL, 0x06, tmpreg)  != OK)
+    {
+        return FAIL;
+    }
+    rf_port.delayus(10);
+
+    if(PAN3029_write_spec_page_reg(PAGE3_SEL, 0x26, 0x0f)  != OK)
+    {
+        return FAIL;
+    }
+    rf_port.delayus(10);
+
+    if(PAN3029_write_reg(REG_OP_MODE, PAN3029_MODE_DEEP_SLEEP) != OK)
+    {
+        return FAIL;
+    }
+    else
+    {
+        return OK;
+    }
+}
+
+
+/**
+ * @brief change PAN3029 mode from standby3(STB3) to sleep, PAN3029 should set DCDC_OFF before enter sleep
+ * @param[in] <none>
+ * @return result
+ */
+uint32_t PAN3029_sleep(void)
+{
+    uint8_t tmpreg;
+
+    if(PAN3029_write_reg(REG_OP_MODE, PAN3029_MODE_STB3) != OK)
+    {
+        return FAIL;
+    }
+    rf_port.delayms(2);
+
+    if(PAN3029_write_reg(REG_OP_MODE, PAN3029_MODE_STB2) != OK)
+    {
+        return FAIL;
+    }
+    rf_port.delayus(10);
+
+    if(PAN3029_write_reg(REG_OP_MODE, PAN3029_MODE_STB1) != OK)
+    {
+        return FAIL;
+    }
+
+    rf_port.delayus(10);
+    rf_port.tcxo_close();
+
+    if(PAN3029_write_reg(0x04, 0x16) != OK)
+    {
+        return FAIL;
+    }
+    rf_port.delayus(10);
+
+    if(PAN3029_write_reg(REG_OP_MODE, PAN3029_MODE_SLEEP) != OK)
+    {
+        return FAIL;
+    }
+
+    tmpreg = PAN3029_read_spec_page_reg(PAGE3_SEL, 0x06);
+    tmpreg &= (~(1<<5));
+    if(PAN3029_write_spec_page_reg(PAGE3_SEL, 0x06, tmpreg)  != OK)
+    {
+        return FAIL;
+    }
+    rf_port.delayus(10);
+
+    if(PAN3029_write_spec_page_reg(PAGE3_SEL, 0x26, 0x0f)  != OK)
+    {
+        return FAIL;
+    }
+
+    return OK;
+}
+
+/**
+ * @brief set LO frequency
+ * @param[in] <lo> LO frequency
+ *			  LO_400M / LO_800M
+ * @return result
+ */
+uint32_t PAN3029_set_lo_freq(uint32_t lo)
+{
+    uint32_t reg_val = 0;
+    reg_val = PAN3029_read_spec_page_reg(PAGE0_SEL, 0x3d);
+    reg_val &= ~(0x70);
+
+    if(lo == LO_400M)
+    {
+        reg_val |= 0x10;
+    }
+    else if(lo == LO_800M)
+    {
+        reg_val |= 0x00;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x3d, reg_val)  != OK)
+    {
+        return FAIL;
+    }
+    return OK;
+}
+
+/**
+ * @brief set frequence
+ * @param[in] <freq>  RF frequency(in Hz) to set
+ * @return result
+ */
+uint32_t PAN3029_set_freq(uint32_t freq)
+{
+    uint8_t reg_freq;
+    float tmp_var = 0.0;
+    int integer_part = 0;
+    float fractional_part = 0.0;
+    uint8_t lowband_sel = 0;
+    int fb,fc;
+
+    if(freq < 800000000)
+    {
+        PAN3029_write_read_continue_regs(PAGE2_SEL, 0x0a, reg_agc_freq400, 40);
+    }
+    else
+    {
+        PAN3029_write_read_continue_regs(PAGE2_SEL, 0x0a, reg_agc_freq800, 40);
+    }
+
+    if ( (freq >= freq_405000000) && (freq <= freq_415000000))
+    {
+        if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x40, 0x1a)  != OK)
+        {
+            return FAIL;
+        }
+        lowband_sel = 0;
+        tmp_var = freq * 4 * 1.0 / 32000000;
+        PAN3029_set_lo_freq(LO_400M);
+    }
+    else if ( (freq > freq_415000000) && (freq <= freq_430000000))
+    {
+        if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x40, 0x2a)  != OK)
+        {
+            return FAIL;
+        }
+        lowband_sel = 0;
+        tmp_var = freq * 4 * 1.0 / 32000000;
+        PAN3029_set_lo_freq(LO_400M);
+    }
+    else if ( (freq > freq_430000000) && (freq <= freq_445000000))
+    {
+        if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x40, 0x3a)  != OK)
+        {
+            return FAIL;
+        }
+        lowband_sel = 0;
+        tmp_var = freq * 4 * 1.0 / 32000000;
+        PAN3029_set_lo_freq(LO_400M);
+    }
+    else if ( (freq > freq_445000000) && (freq <= freq_465000000))
+    {
+        if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x40, 0x4a)  != OK)
+        {
+            return FAIL;
+        }
+        lowband_sel = 0;
+        tmp_var = freq * 4 * 1.0 / 32000000;
+        PAN3029_set_lo_freq(LO_400M);
+    }
+    else if ( (freq > freq_465000000) && (freq <= freq_485000000))
+    {
+        if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x40, 0x5a)  != OK)
+        {
+            return FAIL;
+        }
+        lowband_sel = 0;
+        tmp_var = freq * 4 * 1.0 / 32000000;
+        PAN3029_set_lo_freq(LO_400M);
+    }
+    else if ( (freq > freq_485000000) && (freq <= freq_505000000))
+    {
+        if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x40, 0x6a)  != OK)
+        {
+            return FAIL;
+        }
+        lowband_sel = 0;
+        tmp_var = freq * 4 * 1.0 / 32000000;
+        PAN3029_set_lo_freq(LO_400M);
+    }
+    else if ( (freq > freq_505000000) && (freq <= freq_530000000))
+    {
+        if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x40, 0x7a)  != OK)
+        {
+            return FAIL;
+        }
+        lowband_sel = 0;
+        tmp_var = freq * 4 * 1.0 / 32000000;
+        PAN3029_set_lo_freq(LO_400M);
+    }
+    else if ( (freq > freq_530000000) && (freq <= freq_565000000))
+    {
+        if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x40, 0x7a)  != OK)
+        {
+            return FAIL;
+        }
+        lowband_sel = 0;
+        tmp_var = freq * 4 * 1.0 / 32000000;
+        PAN3029_set_lo_freq(LO_400M);
+    }
+    /****************************800M****************************/
+    else if ( (freq >= freq_810000000) && (freq <= freq_830000000))
+    {
+        if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x40, 0x1a)  != OK)
+        {
+            return FAIL;
+        }
+        lowband_sel = 0;
+        tmp_var = freq * 2 * 1.0 / 32000000;
+        PAN3029_set_lo_freq(LO_800M);
+    }
+    else if ( (freq > freq_830000000) && (freq <= freq_860000000))
+    {
+        if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x40, 0x2a)  != OK)
+        {
+            return FAIL;
+        }
+        lowband_sel = 0;
+        tmp_var = freq * 2 * 1.0 / 32000000;
+        PAN3029_set_lo_freq(LO_800M);
+    }
+    else if ( (freq > freq_860000000) && (freq <= freq_890000000))
+    {
+        if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x40, 0x3a)  != OK)
+        {
+            return FAIL;
+        }
+        lowband_sel = 0;
+        tmp_var = freq * 2 * 1.0 / 32000000;
+        PAN3029_set_lo_freq(LO_800M);
+    }
+    else if ( (freq > freq_890000000) && (freq <= freq_930000000))
+    {
+        if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x40, 0x4a)  != OK)
+        {
+            return FAIL;
+        }
+        lowband_sel = 0;
+        tmp_var = freq * 2 * 1.0 / 32000000;
+        PAN3029_set_lo_freq(LO_800M);
+    }
+    else if ( (freq > freq_930000000) && (freq <= freq_970000000))
+    {
+        if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x40, 0x5a)  != OK)
+        {
+            return FAIL;
+        }
+        lowband_sel = 0;
+        tmp_var = freq * 2 * 1.0 / 32000000;
+        PAN3029_set_lo_freq(LO_800M);
+    }
+    else if ( (freq > freq_970000000) && (freq <= freq_1010000000))
+    {
+        if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x40, 0x6a)  != OK)
+        {
+            return FAIL;
+        }
+        lowband_sel = 0;
+        tmp_var = freq * 2 * 1.0 / 32000000;
+        PAN3029_set_lo_freq(LO_800M);
+    }
+    else if ( (freq > freq_1010000000) && (freq <= freq_1060000000))
+    {
+        if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x40, 0x7a)  != OK)
+        {
+            return FAIL;
+        }
+        lowband_sel = 0;
+        tmp_var = freq * 2 * 1.0 / 32000000;
+        PAN3029_set_lo_freq(LO_800M);
+    }
+    else if ( (freq > freq_1060000000) && (freq <= freq_1080000000))
+    {
+        if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x40, 0x7a)  != OK)
+        {
+            return FAIL;
+        }
+        lowband_sel = 0;
+        tmp_var = freq * 2 * 1.0 / 32000000;
+        PAN3029_set_lo_freq(LO_800M);
+    }
+    else
+    {
+        return FAIL;
+    }
+
+    integer_part = (int)tmp_var;
+    fb = integer_part - 20;
+    fractional_part = tmp_var - integer_part;
+    fc = (int)(fractional_part * 1600 / (2 * (1 + lowband_sel)));
+
+    if(PAN3029_write_spec_page_reg(PAGE3_SEL, 0x15, (fb & 0xff)) != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE3_SEL, 0x16, (fc & 0xff)) != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE3_SEL, 0x17, ((fc >> 8) & 0x0f)) != OK)
+    {
+        return FAIL;
+    }
+
+    reg_freq = freq & 0xff;
+    if(PAN3029_write_spec_page_reg(PAGE3_SEL, 0x09, reg_freq) != OK)
+    {
+        return FAIL;
+    }
+
+    reg_freq = (freq >> 8) & 0xff;
+    if(PAN3029_write_spec_page_reg(PAGE3_SEL, 0x0a, reg_freq) != OK)
+    {
+        return FAIL;
+    }
+
+    reg_freq = (freq >> 16) & 0xff;
+    if(PAN3029_write_spec_page_reg(PAGE3_SEL, 0x0b, reg_freq) != OK)
+    {
+        return FAIL;
+    }
+
+    reg_freq = (freq >> 24) & 0xff;
+    if(PAN3029_write_spec_page_reg(PAGE3_SEL, 0x0c, reg_freq) != OK)
+    {
+        return FAIL;
+    }
+
+    return OK;
+}
+
+/**
+ * @brief read frequency(in Hz)
+ * @param[in] <none>
+ * @return frequency(in Hz)
+ */
+uint32_t PAN3029_read_freq(void)
+{
+    uint8_t reg1, reg2, reg3, reg4;
+    uint32_t freq = 0x00;
+
+    reg1 = PAN3029_read_spec_page_reg(PAGE3_SEL, 0x09);
+    reg2 = PAN3029_read_spec_page_reg(PAGE3_SEL, 0x0a);
+    reg3 = PAN3029_read_spec_page_reg(PAGE3_SEL, 0x0b);
+    reg4 = PAN3029_read_spec_page_reg(PAGE3_SEL, 0x0c);
+    freq = (reg4 << 24) | (reg3 << 16) | (reg2 << 8) | reg1;
+    return freq;
+}
+
+/**
+ * @brief calculate tx time
+ * @param[in] <size> tx len
+ * @return tx time(us)
+ */
+uint32_t PAN3029_calculate_tx_time(uint8_t size)
+{
+    uint8_t sf = PAN3029_get_sf();
+    uint8_t cr = PAN3029_get_code_rate();
+    uint8_t bw = PAN3029_get_bw();
+    uint32_t preamble = PAN3029_get_preamble();
+    uint32_t ldr = PAN3029_get_ldr();
+
+    const float bw_table[10] = {0,0,0,0,0,0,62.5,125,250,500};
+
+    if(bw < 6 ||bw > 9)
+    {
+        return 0;
+    }
+
+    float symbol_len = (float)(1<<sf)/bw_table[bw]; //symbol length
+    float preamble_time;                //preamble time:ms
+    float payload_time = 0;             //payload time:ms
+    float total_time;                   //total time:ms
+
+    if (sf < 7)
+    {
+        preamble_time = (preamble+6.25f)*symbol_len;
+        payload_time = ceil((float)(size*8-sf*4+36)/((sf-ldr*2)*4));
+    }
+    else
+    {
+        preamble_time = (preamble+4.25f)*symbol_len;
+        payload_time = ceil((float)(size*8-sf*4+44)/((sf-ldr*2)*4));
+    }
+
+    payload_time = payload_time*(cr+4);
+    payload_time = payload_time+8;
+    payload_time = payload_time*symbol_len;
+    total_time = (preamble_time+payload_time)*1000;
+
+    return (int)total_time;
+}
+
+/**
+ * @brief set bandwidth
+ * @param[in] <bw_val> value relate to bandwidth
+ *			  BW_62_5K / BW_125K / BW_250K / BW_500K
+ * @return result
+ */
+uint32_t PAN3029_set_bw(uint32_t bw_val)
+{
+    uint8_t temp_val_1;
+    uint8_t temp_val_2;
+    uint8_t sf_val, ldr_val;
+
+    temp_val_1 = PAN3029_read_spec_page_reg(PAGE3_SEL, 0x0d);
+    temp_val_2 = ((temp_val_1 & 0x0F) | (bw_val << 4)) ;
+    if(PAN3029_write_spec_page_reg(PAGE3_SEL, 0x0d, temp_val_2) != OK)
+    {
+        return FAIL;
+    }
+    sf_val = PAN3029_get_sf();
+    if(sf_val == SF_11)
+    {
+        if(bw_val == BW_62_5K || bw_val == BW_125K)
+        {
+            ldr_val = LDR_ON;
+        }
+        else
+        {
+            ldr_val = LDR_OFF;
+        }
+    }
+    else if(sf_val == SF_12)
+    {
+        if(bw_val == BW_62_5K || bw_val == BW_125K || bw_val == BW_250K)
+        {
+            ldr_val = LDR_ON;
+        }
+        else
+        {
+            ldr_val = LDR_OFF;
+        }
+    }
+    else
+    {
+        ldr_val = LDR_OFF;
+    }
+    rf_set_ldr(ldr_val);
+
+    if(bw_val == BW_62_5K || bw_val == BW_125K || bw_val == BW_250K)
+    {
+        temp_val_1 = PAN3029_read_spec_page_reg(PAGE2_SEL, 0x3f);
+        temp_val_1 =  temp_val_1 | 0x02;
+        if(PAN3029_write_spec_page_reg(PAGE2_SEL, 0x3f, temp_val_1) != OK)
+        {
+            return FAIL;
+        }
+        else
+        {
+            return OK;
+        }
+    } else
+    {
+        temp_val_1 = PAN3029_read_spec_page_reg(PAGE2_SEL, 0x3f);
+        temp_val_1 =  temp_val_1 & 0xfd;
+        if(PAN3029_write_spec_page_reg(PAGE2_SEL, 0x3f, temp_val_1) != OK)
+        {
+            return FAIL;
+        }
+        else
+        {
+            return OK;
+        }
+    }
+}
+
+/**
+ * @brief read bandwidth
+ * @param[in] <none>
+ * @return bandwidth
+ */
+uint8_t PAN3029_get_bw(void)
+{
+    uint8_t tmpreg;
+
+    tmpreg = PAN3029_read_spec_page_reg(PAGE3_SEL, 0x0d);
+
+    return (tmpreg & 0xff) >> 4;
+}
+
+/**
+ * @brief set spread factor
+ * @param[in] <sf> spread factor to set
+ *			 SF_5 / SF_6 /SF_7 / SF_8 / SF_9 / SF_10 / SF_11 / SF_12
+ * @return result
+ */
+uint32_t PAN3029_set_sf(uint32_t sf_val)
+{
+    uint8_t temp_val_1;
+    uint8_t temp_val_2;
+    uint8_t bw_val, ldr_val;
+
+    if(sf_val < 5 || sf_val > 12)
+    {
+        return FAIL;
+    }
+    else
+    {
+        temp_val_1 = PAN3029_read_spec_page_reg(PAGE3_SEL, 0x0e);
+        temp_val_2 = ((temp_val_1 & 0x0F) | (sf_val << 4)) ;
+        if(PAN3029_write_spec_page_reg(PAGE3_SEL, 0x0e, temp_val_2) != OK)
+        {
+            return FAIL;
+        }
+        else
+        {
+            bw_val = PAN3029_get_bw();
+            if(sf_val == SF_11)
+            {
+                if(bw_val == BW_62_5K || bw_val == BW_125K)
+                {
+                    ldr_val = LDR_ON;
+                }
+                else
+                {
+                    ldr_val = LDR_OFF;
+                }
+            }
+            else if(sf_val == SF_12)
+            {
+                if(bw_val == BW_62_5K || bw_val == BW_125K || bw_val == BW_250K)
+                {
+                    ldr_val = LDR_ON;
+                }
+                else
+                {
+                    ldr_val = LDR_OFF;
+                }
+            }
+            else
+            {
+                ldr_val = LDR_OFF;
+            }
+            rf_set_ldr(ldr_val);
+
+            return OK;
+        }
+    }
+}
+
+/**
+ * @brief read Spreading Factor
+ * @param[in] <none>
+ * @return Spreading Factor
+ */
+uint8_t PAN3029_get_sf(void)
+{
+    uint8_t tmpreg;
+
+    tmpreg = PAN3029_read_spec_page_reg(PAGE3_SEL, 0x0e);
+
+    return (tmpreg & 0xff) >> 4;
+}
+
+/**
+ * @brief set payload CRC
+ * @param[in] <crc_val> CRC to set
+ *			  CRC_ON / CRC_OFF
+ * @return result
+ */
+uint32_t PAN3029_set_crc(uint32_t crc_val)
+{
+    uint8_t temp_val_1;
+    uint8_t temp_val_2;
+
+    temp_val_1 = PAN3029_read_spec_page_reg(PAGE3_SEL, 0x0e);
+    temp_val_2 = ((temp_val_1 & 0xF7) | (crc_val << 3)) ;
+    if(PAN3029_write_spec_page_reg(PAGE3_SEL, 0x0e, temp_val_2) != OK)
+    {
+        return FAIL;
+    }
+    else
+    {
+        return OK;
+    }
+}
+
+/**
+ * @brief read payload CRC
+ * @param[in] <none>
+ * @return CRC status
+ */
+uint8_t PAN3029_get_crc(void)
+{
+    uint8_t tmpreg;
+
+    tmpreg = PAN3029_read_spec_page_reg(PAGE3_SEL, 0x0e);
+
+    return (tmpreg & 0x08) >> 3;
+}
+
+/**
+ * @brief set code rate
+ * @param[in] <code_rate> code rate to set
+ *			  CODE_RATE_45 / CODE_RATE_46 / CODE_RATE_47 / CODE_RATE_48
+ * @return result
+ */
+uint32_t PAN3029_set_code_rate(uint8_t code_rate)
+{
+    uint8_t tmpreg = 0;
+
+    tmpreg = PAN3029_read_spec_page_reg(PAGE3_SEL, 0x0d);
+    tmpreg &= ~(0x7 << 1);
+    tmpreg |= (code_rate << 1);
+    if(PAN3029_write_spec_page_reg(PAGE3_SEL, 0x0d, tmpreg) != OK)
+    {
+        return FAIL;
+    }
+    else
+    {
+        return OK;
+    }
+}
+
+/**
+ * @brief get code rate
+ * @param[in] <none>
+ * @return code rate
+ */
+uint8_t PAN3029_get_code_rate(void)
+{
+    uint8_t code_rate = 0;
+    uint8_t tmpreg = 0;
+
+    tmpreg = PAN3029_read_spec_page_reg(PAGE3_SEL, 0x0d);
+    code_rate = ((tmpreg & 0x0e) >> 1);
+
+    return code_rate;
+}
+
+/**
+ * @brief set rf mode
+ * @param[in] <mode>
+ *			  PAN3029_MODE_DEEP_SLEEP / PAN3029_MODE_SLEEP
+ *			PAN3029_MODE_STB1 / PAN3029_MODE_STB2
+ *			PAN3029_MODE_STB3 / PAN3029_MODE_TX / PAN3029_MODE_RX
+ * @return result
+ */
+uint32_t PAN3029_set_mode(uint8_t mode)
+{
+    if(PAN3029_write_reg(REG_OP_MODE,mode) != OK)
+    {
+        return FAIL;
+    }
+    else
+    {
+        return OK;
+    }
+}
+
+/**
+ * @brief get rf mode
+ * @param[in] <none>
+ * @return mode
+ *		   PAN3029_MODE_DEEP_SLEEP / PAN3029_MODE_SLEEP
+ *		 PAN3029_MODE_STB1 / PAN3029_MODE_STB2
+ *		 PAN3029_MODE_STB3 / PAN3029_MODE_TX / PAN3029_MODE_RX
+ */
+uint8_t PAN3029_get_mode(void)
+{
+    return PAN3029_read_reg(REG_OP_MODE);
+}
+
+/**
+ * @brief set rf Tx mode
+ * @param[in] <mode>
+ *			  PAN3029_TX_SINGLE/PAN3029_TX_CONTINOUS
+ * @return result
+ */
+uint32_t PAN3029_set_tx_mode(uint8_t mode)
+{
+    uint8_t tmp;
+    tmp = PAN3029_read_spec_page_reg(PAGE3_SEL, 0x06);
+    tmp = tmp & (~(1 << 2));
+    tmp = tmp | (mode << 2);
+
+    if(PAN3029_write_spec_page_reg(PAGE3_SEL, 0x06, tmp) != OK)
+    {
+        return FAIL;
+    }
+    else
+    {
+        return OK;
+    }
+}
+
+/**
+ * @brief set rf Rx mode
+ * @param[in] <mode>
+ *			  PAN3029_RX_SINGLE/PAN3029_RX_SINGLE_TIMEOUT/PAN3029_RX_CONTINOUS
+ * @return result
+ */
+uint32_t PAN3029_set_rx_mode(uint8_t mode)
+{
+    uint8_t tmp;
+    tmp = PAN3029_read_spec_page_reg(PAGE3_SEL, 0x06);
+    tmp = tmp & (~(3 << 0));
+    tmp = tmp | (mode << 0);
+
+    if(PAN3029_write_spec_page_reg(PAGE3_SEL, 0x06, tmp) != OK)
+    {
+        return FAIL;
+    }
+    else
+    {
+        return OK;
+    }
+}
+
+uint32_t PAN3029_set_modem_mode(uint8_t mode)
+{
+    if(mode == MODEM_MODE_NORMAL)
+    {
+        if(PAN3029_write_spec_page_reg(PAGE1_SEL, 0x0b, 0x08) != OK)
+        {
+            return FAIL;
+        }
+        else
+        {
+            return OK;
+        }
+    }
+    else if(mode == MODEM_MODE_MULTI_SECTOR)
+    {
+        if(PAN3029_write_spec_page_reg(PAGE1_SEL, 0x0b, 0x18) != OK)
+        {
+            return FAIL;
+        }
+        if(PAN3029_write_spec_page_reg(PAGE1_SEL, 0x2f, 0x54) != OK)
+        {
+            return FAIL;
+        }
+        if(PAN3029_write_spec_page_reg(PAGE1_SEL, 0x30, 0x40) != OK)
+        {
+            return FAIL;
+        }
+        return OK;
+    }
+    return FAIL;
+}
+
+/**
+ * @brief set timeout for Rx. It is useful in PAN3029_RX_SINGLE_TIMEOUT mode
+ * @param[in] <timeout> rx single timeout time(in ms)
+ * @return result
+ */
+uint32_t PAN3029_set_timeout(uint32_t timeout)
+{
+    uint8_t timeout_lsb = 0;
+    uint8_t timeout_msb = 0;
+
+    if(timeout > 0xffff)
+    {
+        timeout = 0xffff;
+    }
+
+    timeout_lsb = timeout & 0xff;
+    timeout_msb = (timeout >> 8) & 0xff;
+
+    if(PAN3029_write_spec_page_reg(PAGE3_SEL, 0x07, timeout_lsb) != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE3_SEL, 0x08, timeout_msb) != OK)
+    {
+        return FAIL;
+    }
+    else
+    {
+        return OK;
+    }
+}
+
+/**
+ * @brief get snr value
+ * @param[in] <none>
+ * @return snr
+ */
+float PAN3029_get_snr(void)
+{
+    float snr_val=0.0;
+    uint8_t sig_pow_l, sig_pow_m, sig_pow_h;
+    uint8_t noise_pow_l, noise_pow_m, noise_pow_h;
+    uint32_t sig_pow_val;
+    uint32_t noise_pow_val;
+    uint32_t sf_val;
+
+    sig_pow_l = PAN3029_read_spec_page_reg(PAGE1_SEL, 0x74);
+    sig_pow_m = PAN3029_read_spec_page_reg(PAGE1_SEL, 0x75);
+    sig_pow_h = PAN3029_read_spec_page_reg(PAGE1_SEL, 0x76);
+    sig_pow_val = ((sig_pow_h << 16) | (sig_pow_m << 8) | sig_pow_l );
+
+    noise_pow_l = PAN3029_read_spec_page_reg(PAGE2_SEL, 0x71);
+    noise_pow_m = PAN3029_read_spec_page_reg(PAGE2_SEL, 0x72);
+    noise_pow_h = PAN3029_read_spec_page_reg(PAGE2_SEL, 0x73);
+    noise_pow_val = ((noise_pow_h << 16) | (noise_pow_m << 8) | noise_pow_l );
+
+    sf_val = (PAN3029_read_spec_page_reg(PAGE1_SEL, 0x7c) & 0xf0) >> 4;
+
+    if(noise_pow_val == 0)
+    {
+        noise_pow_val = 1;
+    }
+    snr_val = (float)(10 * log10((sig_pow_val / pow(2,sf_val)) / noise_pow_val));
+
+    return snr_val;
+}
+
+/**
+ * @brief get rssi value
+ * @param[in] <none>
+ * @return rssi
+ */
+int8_t PAN3029_get_rssi(void)
+{
+    int8_t rssi_val = 0;
+
+    rssi_val = PAN3029_read_spec_page_reg(PAGE1_SEL, 0x7F);
+
+    return rssi_val;
+}
+
+
+/**
+ * @brief current channel energy detection
+ * @param[in] <none>
+ * @return rssi
+ */
+int8_t PAN3029_get_channel_rssi(void)
+{
+    int8_t rssi_pre_read = 0;
+    int8_t rssi_energy = 0;
+
+    rssi_pre_read = PAN3029_read_spec_page_reg(PAGE2_SEL, 0x06);
+    rssi_pre_read &= ~(1<<2);
+    PAN3029_write_spec_page_reg(PAGE2_SEL, 0x06, rssi_pre_read);
+    rssi_pre_read = PAN3029_read_spec_page_reg(PAGE2_SEL, 0x06);
+    rssi_pre_read |= (1<<2);
+    PAN3029_write_spec_page_reg(PAGE2_SEL, 0x06, rssi_pre_read);
+    rssi_energy = PAN3029_read_spec_page_reg(PAGE1_SEL, 0x7e);
+
+    return rssi_energy;
+}
+
+/**
+ * @brief set tx_power
+ * @param[in] <tx_power> open gears (range in 1--23(405MHz-565MHz)1-22(868/915MHz))
+ * @return result
+ */
+uint32_t PAN3029_set_tx_power(uint8_t tx_power)
+{
+    uint8_t tmp_value1, tmp_value2,pa_bias;
+    uint32_t freq, pwr_table;
+
+    if(tx_power < PAN3029_MIN_RAMP)
+    {
+        tx_power = PAN3029_MIN_RAMP;
+    }
+
+    freq = PAN3029_read_freq();
+
+    if ( (freq >= freq_405000000) && (freq <= freq_565000000))
+    {
+        if(tx_power > PAN3029_MAX_RAMP+1)
+        {
+            tx_power = PAN3029_MAX_RAMP;
+        }
+        tmp_value1 = PAN3029_read_spec_page_reg(PAGE0_SEL, 0x1e);
+        tmp_value2 = (tmp_value1 & 0xc0) | power_ramp_cfg[tx_power-1].ramp;
+        if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x1e, tmp_value2)  != OK)//modulate wave ramp mode
+        {
+            return FAIL;
+        }
+
+        tmp_value1 = PAN3029_read_spec_page_reg(PAGE0_SEL, 0x4b);
+        tmp_value2 = (tmp_value1 & 0xf0) | (power_ramp_cfg[tx_power-1].pa_ldo >> 4);
+        if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x4b, tmp_value2)  != OK)
+        {
+            return FAIL;
+        }
+
+        tmp_value1 = PAN3029_read_spec_page_reg(PAGE3_SEL, 0x22);
+        tmp_value2 = (tmp_value1 & 0xfe) | (power_ramp_cfg[tx_power-1].pa_ldo & 0x01);
+        if(PAN3029_write_spec_page_reg(PAGE3_SEL, 0x22, tmp_value2)  != OK)
+        {
+            return FAIL;
+        }
+
+        if(power_ramp_cfg[tx_power-1].pa_duty != 0x70)
+        {
+            tmp_value1 = PAN3029_read_spec_page_reg(PAGE0_SEL, 0x46);
+            tmp_value2 = tmp_value1 | 0x04;
+            if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x46, tmp_value2)  != OK)
+            {
+                return FAIL;
+            }
+        } else {
+            tmp_value1 = PAN3029_read_spec_page_reg(PAGE0_SEL, 0x46);
+            tmp_value2 = tmp_value1 & 0xfb;
+            if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x46, tmp_value2)  != OK)
+            {
+                return FAIL;
+            }
+        }
+        PAN3029_efuse_on();
+        pa_bias = PAN3029_efuse_read_encry_byte(0x3b,0x5aa5,0x0d+19);
+        PAN3029_efuse_off();
+        if(pa_bias == 0)
+        {
+            pa_bias = 8;
+        }
+        tmp_value1 = pa_bias - (power_ramp_cfg[tx_power-1].pa_duty & 0x0f);
+        tmp_value2 = (power_ramp_cfg[tx_power-1].pa_duty & 0xf0) | tmp_value1;
+        if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x45, tmp_value2)  != OK)
+        {
+            return FAIL;
+        }
+
+        return OK;
+    } else if ( (freq >= freq_810000000) && (freq <= freq_890000000))
+    {
+        pwr_table = 2;
+    } else if ( (freq >= freq_890000000) && (freq <= freq_1080000000))
+    {
+        pwr_table = 3;
+    } else
+    {
+        return FAIL;
+    }
+
+    if(tx_power > PAN3029_MAX_RAMP)
+    {
+        tx_power = PAN3029_MAX_RAMP;
+    }
+
+    tmp_value1 = PAN3029_read_spec_page_reg(PAGE0_SEL, 0x1e);
+    tmp_value2 = (tmp_value1 & 0xc0) | power_ramp[tx_power-1][pwr_table].ramp;
+    if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x1e, tmp_value2)  != OK)//modulate wave ramp mode
+    {
+        return FAIL;
+    }
+
+    tmp_value1 = PAN3029_read_spec_page_reg(PAGE0_SEL, 0x4b);
+    tmp_value2 = (tmp_value1 & 0xf0) | power_ramp[tx_power-1][pwr_table].pa_trim;
+
+    if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x4b, tmp_value2)  != OK)
+    {
+        return FAIL;
+    }
+
+    tmp_value1 = PAN3029_read_spec_page_reg(PAGE3_SEL, 0x22);
+    tmp_value2 = (tmp_value1 & 0xfe) | power_ramp[tx_power-1][pwr_table].pa_ldo;
+    if(PAN3029_write_spec_page_reg(PAGE3_SEL, 0x22, tmp_value2)  != OK)
+    {
+        return FAIL;
+    }
+
+    if(power_ramp[tx_power-1][pwr_table].pa_duty != 0xff)
+    {
+        tmp_value1 = PAN3029_read_spec_page_reg(PAGE0_SEL, 0x46);
+        tmp_value2 = tmp_value1 | 0x04;
+        if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x46, tmp_value2)  != OK)
+        {
+            return FAIL;
+        }
+
+        tmp_value1 = PAN3029_read_spec_page_reg(PAGE0_SEL, 0x45);
+        tmp_value2 = (tmp_value1 & 0x8f) | (power_ramp[tx_power-1][pwr_table].pa_duty << 4);
+        if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x45, tmp_value2)  != OK)
+        {
+            return FAIL;
+        }
+    } else {
+        tmp_value1 = PAN3029_read_spec_page_reg(PAGE0_SEL, 0x46);
+        tmp_value2 = tmp_value1 & 0xfb;
+        if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x46, tmp_value2)  != OK)
+        {
+            return FAIL;
+        }
+    }
+    return OK;
+}
+
+/**
+ * @brief get tx_power
+ * @param[in] <none>
+ * @return tx_power if return value is 0,means get tx_power fail
+ */
+uint32_t PAN3029_get_tx_power(void)
+{
+    uint8_t open_ramp, pa_trim, pa_ldo, pa_duty, pa_duty_en;
+    uint8_t i,pa_bias;
+    uint32_t freq, pwr_table;
+    open_ramp = PAN3029_read_spec_page_reg(PAGE0_SEL, 0x1e) & 0x3f;
+    pa_trim = PAN3029_read_spec_page_reg(PAGE0_SEL, 0x4b) & 0x0f;
+    pa_ldo = PAN3029_read_spec_page_reg(PAGE3_SEL, 0x22) & 0x01;
+    pa_duty = ((PAN3029_read_spec_page_reg(PAGE0_SEL, 0x45) & 0x70) >> 4);
+    pa_duty_en = ((PAN3029_read_spec_page_reg(PAGE0_SEL, 0x46) & 0x04) >> 2);
+
+    freq = PAN3029_read_freq();
+
+    if ( (freq >= freq_405000000) && (freq <= freq_565000000))
+    {
+        PAN3029_efuse_on();
+        pa_bias = PAN3029_efuse_read_encry_byte(0x3b,0x5aa5,0x0d+19);
+        PAN3029_efuse_off();
+        if(pa_bias == 0)
+        {
+            pa_bias = 8;
+        }
+        pa_duty = PAN3029_read_spec_page_reg(PAGE0_SEL, 0x45);
+        for(i=0; i<PAN3029_MAX_RAMP+1; i++)
+        {
+            if(open_ramp == power_ramp_cfg[i].ramp)
+            {
+                if(((pa_trim << 4) | pa_ldo) == power_ramp_cfg[i].pa_ldo)
+                {
+                    if((pa_duty_en == true)&&((pa_duty + (power_ramp_cfg[i].pa_duty & 0x0f)) == ((power_ramp_cfg[i].pa_duty & 0xf0) + pa_bias)))
+                    {
+                        return i+1;
+                    } else if((pa_duty_en == false)&&((pa_duty | 0x70) == ((power_ramp_cfg[i].pa_duty & 0xf0) + pa_bias)))
+                    {
+                        return i+1;
+                    }
+                }
+            }
+        }
+        return 0;
+    } else if ( (freq >= freq_810000000) && (freq <= freq_890000000))
+    {
+        pwr_table = 2;
+    } else if ( (freq >= freq_890000000) && (freq <= freq_1080000000))
+    {
+        pwr_table = 3;
+    } else
+    {
+        return FAIL;
+    }
+
+    for(i=0; i<PAN3029_MAX_RAMP; i++)
+    {
+        if(open_ramp == power_ramp[i][pwr_table].ramp)
+        {
+            if((pa_trim == power_ramp[i][pwr_table].pa_trim)&&(pa_ldo == power_ramp[i][pwr_table].pa_ldo))
+            {
+                if((pa_duty_en == true)&&(pa_duty == power_ramp[i][pwr_table].pa_duty))
+                {
+                    return i+1;
+                } else if((pa_duty_en == false)&&(0xff == power_ramp[i][pwr_table].pa_duty))
+                {
+                    return i+1;
+                }
+            }
+        }
+    }
+    return 0;
+}
+
+/**
+ * @brief set preamble
+ * @param[in] <reg> preamble
+ * @return result
+ */
+uint32_t PAN3029_set_preamble(uint16_t reg)
+{
+    uint8_t tmp_value;
+    tmp_value = reg & 0xff;
+
+    if(PAN3029_write_spec_page_reg(PAGE3_SEL, 0x13, tmp_value)  != OK)
+    {
+        return FAIL;
+    }
+
+    tmp_value = (reg >> 8) & 0xff;
+    if(PAN3029_write_spec_page_reg(PAGE3_SEL, 0x14, tmp_value)  != OK)
+    {
+        return FAIL;
+    }
+    return OK;
+}
+
+/**
+ * @brief get preamble
+ * @param[in] <none>
+ * @return preamble
+ */
+uint32_t PAN3029_get_preamble(void)
+{
+    uint8_t reg1, reg2;
+
+    reg1 = PAN3029_read_spec_page_reg(PAGE3_SEL, 0x13);
+    reg2 = PAN3029_read_spec_page_reg(PAGE3_SEL, 0x14);
+
+    return (reg2 << 8) | reg1;
+}
+
+/**
+ * @brief set RF GPIO as input
+ * @param[in] <gpio_pin>  pin number of GPIO to be enable
+ * @return result
+ */
+uint32_t PAN3029_set_gpio_input(uint8_t gpio_pin)
+{
+    uint8_t tmpreg = 0;
+
+    if(gpio_pin < 8)
+    {
+        tmpreg = PAN3029_read_spec_page_reg(PAGE0_SEL, 0x63);
+        tmpreg |= (1 << gpio_pin);
+        if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x63, tmpreg) != OK)
+        {
+            return FAIL;
+        }
+        else
+        {
+            return OK;
+        }
+    }
+    else
+    {
+        tmpreg = PAN3029_read_spec_page_reg(PAGE0_SEL, 0x64);
+        tmpreg |= (1 << (gpio_pin - 8));
+        if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x64, tmpreg) != OK)
+        {
+            return FAIL;
+        }
+        else
+        {
+            return OK;
+        }
+    }
+}
+
+/**
+ * @brief set RF GPIO as output
+ * @param[in] <gpio_pin>  pin number of GPIO to be enable
+ * @return result
+ */
+uint32_t PAN3029_set_gpio_output(uint8_t gpio_pin)
+{
+    uint8_t tmpreg = 0;
+
+    if(gpio_pin < 8)
+    {
+        tmpreg = PAN3029_read_spec_page_reg(PAGE0_SEL, 0x65);
+        tmpreg |= (1 << gpio_pin);
+        if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x65, tmpreg) != OK)
+        {
+            return FAIL;
+        }
+        else
+        {
+            return OK;
+        }
+    }
+    else
+    {
+        tmpreg = PAN3029_read_spec_page_reg(PAGE0_SEL, 0x66);
+        tmpreg |= (1 << (gpio_pin - 8));
+        if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x66, tmpreg) != OK)
+        {
+            return FAIL;
+        }
+        else
+        {
+            return OK;
+        }
+    }
+}
+
+/**
+ * @brief set GPIO output state, SET or RESET
+ * @param[in] <gpio_pin>  pin number of GPIO to be opearted
+ *			<state>   0  -  reset,
+ *					  1  -  set
+ * @return result
+ */
+uint32_t PAN3029_set_gpio_state(uint8_t gpio_pin, uint8_t state)
+{
+    uint8_t tmpreg = 0;
+
+    if(gpio_pin < 8)
+    {
+        tmpreg = PAN3029_read_spec_page_reg(PAGE0_SEL, 0x67);
+
+        if(state == 0)
+        {
+            tmpreg &= ~(1 << gpio_pin);
+        }
+        else
+        {
+            tmpreg |= (1 << gpio_pin);
+        }
+
+        if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x67, tmpreg) != OK)
+        {
+            return FAIL;
+        }
+        else
+        {
+            return OK;
+        }
+    }
+    else
+    {
+        tmpreg = PAN3029_read_spec_page_reg(PAGE0_SEL, 0x68);
+
+        if(state == 0)
+        {
+            tmpreg &= ~(1 << (gpio_pin - 8));
+        }
+        else
+        {
+            tmpreg |= (1 << (gpio_pin - 8));
+        }
+
+        if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x68, tmpreg) != OK)
+        {
+            return FAIL;
+        }
+        else
+        {
+            return OK;
+        }
+    }
+}
+
+/**
+ * @brief get GPIO input state
+ * @param[in] <gpio_pin>  pin number of GPIO to be opearted
+ *			<state>   0  -  low,
+ *					  1  -  high
+ * @return result
+ */
+uint8_t PAN3029_get_gpio_state(uint8_t gpio_pin)
+{
+    uint8_t tmpreg = 0;
+
+    if(gpio_pin < 6)
+    {
+        tmpreg = PAN3029_read_spec_page_reg(PAGE0_SEL, 0x74);
+    }
+    else
+    {
+        tmpreg = PAN3029_read_spec_page_reg(PAGE0_SEL, 0x75);
+        gpio_pin -= 6;
+    }
+
+    return (tmpreg >> gpio_pin) & 0x01;
+}
+
+/**
+ * @brief CAD function enable
+ * @param[in] <none>
+ * @return  result
+ */
+uint32_t PAN3029_cad_en(uint8_t threshold, uint8_t chirps)
+{
+    uint8_t temp_val_1;
+    uint8_t temp_val_2;
+
+    PAN3029_set_gpio_output(11);
+    temp_val_1 = PAN3029_read_spec_page_reg(PAGE0_SEL, 0x5e);
+    temp_val_2 = temp_val_1 & 0xbf;
+    if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x5e, temp_val_2) != OK)
+    {
+        return FAIL;
+    }
+
+    temp_val_1 = PAN3029_read_spec_page_reg(PAGE1_SEL, 0x25);
+    temp_val_2 = (temp_val_1 & 0xfc) | chirps;
+    if(PAN3029_write_spec_page_reg(PAGE1_SEL, 0x25, temp_val_2) != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE1_SEL, 0x0f, threshold) != OK)
+    {
+        return FAIL;
+    }
+
+    return OK;
+}
+
+/* @brief CAD function disable
+* @param[in] <none>
+* @return  result
+*/
+uint32_t PAN3029_cad_off(void)
+{
+    uint8_t temp_val_1;
+    uint8_t temp_val_2;
+
+    temp_val_1 = PAN3029_read_spec_page_reg(PAGE0_SEL, 0x5e);
+    temp_val_2 = temp_val_1 | 0x40;
+    PAN3029_write_spec_page_reg(PAGE0_SEL, 0x5e, temp_val_2);
+
+    if(PAN3029_write_spec_page_reg(PAGE1_SEL, 0x0f, 0x0a) != OK)
+    {
+        return FAIL;
+    }
+
+    return OK;
+}
+
+/**
+ * @brief set rf syncword
+ * @param[in] <sync> syncword
+ * @return result
+ */
+uint32_t PAN3029_set_syncword(uint32_t sync)
+{
+    if(PAN3029_write_spec_page_reg(PAGE3_SEL, 0x0f, sync) != OK)
+    {
+        return FAIL;
+    }
+    else
+    {
+        return OK;
+    }
+}
+
+/**
+ * @brief read rf syncword
+ * @param[in] <none>
+ * @return syncword
+ */
+uint8_t PAN3029_get_syncword(void)
+{
+    uint8_t tmpreg;
+
+    tmpreg = PAN3029_read_spec_page_reg(PAGE3_SEL, 0x0f);
+
+    return tmpreg;
+}
+
+/**
+ * @brief send one packet
+ * @param[in] <buff> buffer contain data to send
+ * @param[in] <len> the length of data to send
+ * @return result
+ */
+uint32_t PAN3029_send_packet(uint8_t *buff, uint32_t len)
+{
+    if(PAN3029_write_spec_page_reg(PAGE1_SEL, REG_PAYLOAD_LEN, len) != OK)
+    {
+        return FAIL;
+    }
+    if(PAN3029_write_reg(REG_OP_MODE, PAN3029_MODE_TX) != OK)
+    {
+        return FAIL;
+    }
+    else
+    {
+        PAN3029_write_fifo(REG_FIFO_ACC_ADDR, buff, len);
+        return OK;
+    }
+}
+
+/**
+ * @brief receive a packet in non-block method, it will return 0 when no data got
+ * @param[in] <buff> buffer provide for data to receive
+ * @return length, it will return 0 when no data got
+ */
+uint8_t PAN3029_recv_packet(uint8_t *buff)
+{
+    uint32_t len = 0;
+
+    len = PAN3029_read_spec_page_reg(PAGE1_SEL, 0x7D);
+    PAN3029_read_fifo(REG_FIFO_ACC_ADDR, buff, len);
+
+    /* clear rx done irq */
+    PAN3029_clr_irq();
+
+    return len;
+}
+
+/**
+ * @brief set early interruption
+ * @param[in] <earlyirq_val> PLHD IRQ to set
+ *			  PLHD_IRQ_ON / PLHD_IRQ_OFF
+ * @return result
+ */
+uint32_t PAN3029_set_early_irq(uint32_t earlyirq_val)
+{
+    uint8_t temp_val_1;
+    uint8_t temp_val_2;
+
+    temp_val_1 = PAN3029_read_spec_page_reg(PAGE1_SEL, 0x2b);
+    temp_val_2 = ((temp_val_1 & 0xbf) | (earlyirq_val << 6)) ;
+
+    if(PAN3029_write_spec_page_reg(PAGE1_SEL, 0x2b, temp_val_2) != OK)
+    {
+        return FAIL;
+    }
+    else
+    {
+        return OK;
+    }
+}
+
+/**
+ * @brief read plhd irq status
+ * @param[in] <none>
+ * @return plhd irq status
+ */
+uint8_t PAN3029_get_early_irq(void)
+{
+    uint8_t tmpreg;
+
+    tmpreg = PAN3029_read_spec_page_reg(PAGE1_SEL, 0x2b);
+    return (tmpreg >>6 ) & 0x01;
+}
+
+/**
+ * @brief set plhd
+ * @param[in] <addr> PLHD start addr,Range:0..7f
+ *			  <len> PLHD len
+ *			  PLHD_LEN8 / PLHD_LEN16
+ * @return result
+ */
+uint32_t PAN3029_set_plhd(uint8_t addr,uint8_t len)
+{
+    uint8_t temp_val_2;
+
+    temp_val_2 = ((addr & 0x7f) | (len << 7)) ;
+
+    if(PAN3029_write_spec_page_reg(PAGE1_SEL, 0x2e, temp_val_2) != OK)
+    {
+        return FAIL;
+    }
+    else
+    {
+        return OK;
+    }
+}
+
+/**
+ * @brief get plhd len reg value
+ * @param[in] <none>
+ * @return <len> PLHD_LEN8 / PLHD_LEN16
+ */
+uint8_t PAN3029_get_plhd_len(void)
+{
+    uint8_t tmpreg;
+
+    tmpreg = PAN3029_read_spec_page_reg(PAGE1_SEL, 0x2e);
+
+    return ((tmpreg & 0x80) >> 7);
+}
+
+/**
+ * @brief set plhd mask
+ * @param[in] <plhd_val> plhd mask to set
+ *			  PLHD_ON / PLHD_OFF
+ * @return result
+ */
+uint32_t PAN3029_set_plhd_mask(uint32_t plhd_val)
+{
+    uint8_t temp_val_1;
+    uint8_t temp_val_2;
+
+    temp_val_1 = PAN3029_read_spec_page_reg(PAGE0_SEL, 0x58);
+    temp_val_2 = ((temp_val_1 & 0xef) | (plhd_val << 4)) ;
+
+    if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x58, temp_val_2) != OK)
+    {
+        return FAIL;
+    }
+    else
+    {
+        return OK;
+    }
+}
+
+/**
+ * @brief read plhd mask
+ * @param[in] <none>
+ * @return plhd mask
+ */
+uint8_t PAN3029_get_plhd_mask(void)
+{
+    uint8_t tmpreg;
+
+    tmpreg = PAN3029_read_spec_page_reg(PAGE0_SEL, 0x58);
+
+    return tmpreg;
+}
+
+/**
+ * @brief receive 8 bytes plhd data
+ * @param[in] <buff> buffer provide for data to receive
+ * @return result
+ */
+uint8_t PAN3029_recv_plhd8(uint8_t *buff)
+{
+    uint32_t i,len = 8;
+    for(i = 0; i < len; i++)
+    {
+        buff[i] = PAN3029_read_spec_page_reg(PAGE2_SEL, 0x76 + i);
+    }
+
+    PAN3029_clr_irq();
+    return len;
+}
+
+/**
+ * @brief receive 16 bytes plhd data
+ * @param[in] <buff> buffer provide for data to receive
+ * @return result
+ */
+uint8_t PAN3029_recv_plhd16(uint8_t *buff)
+{
+    uint32_t i,len = 16;
+    for(i = 0; i < len; i++)
+    {
+        if(i<10)
+        {
+            buff[i] = PAN3029_read_spec_page_reg(PAGE2_SEL, 0x76 + i);
+        } else {
+            buff[i] = PAN3029_read_spec_page_reg(PAGE0_SEL, 0x76 + i - 10);
+        }
+    }
+
+    PAN3029_clr_irq();
+    return len;
+}
+
+/**
+ * @brief receive a packet in non-block method, it will return 0 when no data got
+ * @param[in] <buff> buffer provide for data to receive
+ *			  <len> PLHD_LEN8 / PLHD_LEN16
+ * @return result
+ */
+uint32_t PAN3029_plhd_receive(uint8_t *buf,uint8_t len)
+{
+    if(len == PLHD_LEN8)
+    {
+        return PAN3029_recv_plhd8(buf);
+    } else if (len == PLHD_LEN16)
+    {
+        return PAN3029_recv_plhd16(buf);
+    }
+    return FAIL;
+}
+
+/**
+ * @brief set dcdc mode, The default configuration is DCDC_OFF, PAN3029 should set DCDC_OFF before enter sleep/deepsleep
+ * @param[in] <dcdc_val> dcdc switch
+ *			  DCDC_ON / DCDC_OFF
+ * @return result
+ */
+uint32_t PAN3029_set_dcdc_mode(uint32_t dcdc_val)
+{
+    uint8_t temp_val_1;
+    uint8_t temp_val_2;
+
+    temp_val_1 = PAN3029_read_spec_page_reg(PAGE3_SEL, 0x24);
+    temp_val_2 = ((temp_val_1 & 0xf7) | (dcdc_val << 3)) ;
+
+    if(PAN3029_write_spec_page_reg(PAGE3_SEL, 0x24, temp_val_2) != OK)
+    {
+        return FAIL;
+    }
+    else
+    {
+        return OK;
+    }
+}
+
+/**
+ * @brief set LDR mode
+ * @param[in] <mode> LDR switch
+ *			  LDR_ON / LDR_OFF
+ * @return result
+ */
+uint32_t PAN3029_set_ldr(uint32_t mode)
+{
+    uint8_t temp_val_1;
+    uint8_t temp_val_2;
+
+    temp_val_1 = PAN3029_read_spec_page_reg(PAGE3_SEL, 0x12);
+    temp_val_2 = ((temp_val_1 & 0xF7) | (mode << 3)) ;
+    if(PAN3029_write_spec_page_reg(PAGE3_SEL, 0x12, temp_val_2) != OK)
+    {
+        return FAIL;
+    }
+    else
+    {
+        return OK;
+    }
+}
+
+/**
+ * @brief get LDR mode
+ * @param[in] <none>
+ * @return result LDR_ON / LDR_OFF
+ */
+uint32_t PAN3029_get_ldr(void)
+{
+    uint8_t tmpreg;
+
+    tmpreg = PAN3029_read_spec_page_reg(PAGE3_SEL, 0x12);
+
+    return (tmpreg >> 3) & 0x01;
+}
+
+/**
+ * @brief set preamble by Spreading Factor,It is useful in all_sf_search mode
+ * @param[in] <sf> Spreading Factor
+ * @return result
+ */
+uint32_t PAN3029_set_all_sf_preamble(uint32_t sf)
+{
+    switch(sf)
+    {
+    case 5:
+        if (PAN3029_write_spec_page_reg(PAGE3_SEL, 0x14, 2) != OK)
+        {
+            return FAIL;
+        }
+
+        if (PAN3029_write_spec_page_reg(PAGE3_SEL, 0x13, 0x6d) != OK)
+        {
+            return FAIL;
+        } else
+        {
+            return OK;
+        }
+
+    case 6:
+        if (PAN3029_write_spec_page_reg(PAGE3_SEL, 0x14, 1) != OK)
+        {
+            return FAIL;
+        }
+
+        if (PAN3029_write_spec_page_reg(PAGE3_SEL, 0x13, 0x2e) != OK)
+        {
+            return FAIL;
+        } else
+        {
+            return OK;
+        }
+
+    case 7:
+        if (PAN3029_write_spec_page_reg(PAGE3_SEL, 0x14, 0) != OK)
+        {
+            return FAIL;
+        }
+
+        if (PAN3029_write_spec_page_reg(PAGE3_SEL, 0x13, 130) != OK)
+        {
+            return FAIL;
+        } else
+        {
+            return OK;
+        }
+
+    case 8:
+        if (PAN3029_write_spec_page_reg(PAGE3_SEL, 0x14, 0) != OK)
+        {
+            return FAIL;
+        }
+
+        if (PAN3029_write_spec_page_reg(PAGE3_SEL, 0x13, 82) != OK)
+        {
+            return FAIL;
+        } else
+        {
+            return OK;
+        }
+
+    case 9:
+        if (PAN3029_write_spec_page_reg(PAGE3_SEL, 0x14, 0) != OK)
+        {
+            return FAIL;
+        }
+
+        if (PAN3029_write_spec_page_reg(PAGE3_SEL, 0x13, 48) != OK)
+        {
+            return FAIL;
+        } else
+        {
+            return OK;
+        }
+
+    case 10:
+        if (PAN3029_write_spec_page_reg(PAGE3_SEL, 0x14, 0) != OK)
+        {
+            return FAIL;
+        }
+
+        if (PAN3029_write_spec_page_reg(PAGE3_SEL, 0x13, 24) != OK)
+        {
+            return FAIL;
+        } else
+        {
+            return OK;
+        }
+
+    case 11:
+        if (PAN3029_write_spec_page_reg(PAGE3_SEL, 0x14, 0) != OK)
+        {
+            return FAIL;
+        }
+
+        if (PAN3029_write_spec_page_reg(PAGE3_SEL, 0x13, 16) != OK)
+        {
+            return FAIL;
+        } else
+        {
+            return OK;
+        }
+
+    case 12:
+        if (PAN3029_write_spec_page_reg(PAGE3_SEL, 0x14, 0) != OK)
+        {
+            return FAIL;
+        }
+
+        if (PAN3029_write_spec_page_reg(PAGE3_SEL, 0x13, 12) != OK)
+        {
+            return FAIL;
+        } else
+        {
+            return OK;
+        }
+
+    default:
+        return FAIL;
+    }
+}
+
+/**
+ * @brief open all sf auto-search mode
+ * @param[in] <none>
+ * @return result
+ */
+uint32_t PAN3029_set_all_sf_search(void)
+{
+    uint8_t tmp_val;
+
+    tmp_val = (PAN3029_read_spec_page_reg(PAGE3_SEL, 0x12) | 0x01);
+
+    if(PAN3029_write_spec_page_reg(PAGE3_SEL, 0x12, tmp_val) != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE1_SEL, 0x25, 0x04) != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_write_spec_page_reg(PAGE1_SEL, 0x2d, 0xff) != OK)
+    {
+        return FAIL;
+    }
+
+    return OK;
+}
+
+/**
+ * @brief close all sf auto-search mode
+ * @param[in] <none>
+ * @return result
+ */
+uint32_t PAN3029_set_all_sf_search_off(void)
+{
+    uint8_t tmp_val;
+
+    tmp_val = (PAN3029_read_spec_page_reg(PAGE3_SEL, 0x12) & 0xFE);
+
+    if(PAN3029_write_spec_page_reg(PAGE3_SEL, 0x12, tmp_val) != OK)
+    {
+        return FAIL;
+    }
+
+    if (PAN3029_write_spec_page_reg(PAGE3_SEL, 0x14, 0) != OK)
+    {
+        return FAIL;
+    }
+
+    if (PAN3029_write_spec_page_reg(PAGE3_SEL, 0x13, 8) != OK)
+    {
+        return FAIL;
+    } else
+    {
+        return OK;
+    }
+}
+
+/**
+ * @brief RF IRQ server routine, it should be call at ISR of IRQ pin
+ * @param[in] <none>
+ * @return <none>
+ */
+void PAN3029_irq_handler(void)
+{
+    pan3029_irq_trigged_flag = true;
+}
+
+/**
+ * @brief set carrier_wave mode on,Set BW and SF before calling this function
+ * @param[in] <none>
+ * @return result
+ */
+uint32_t PAN3029_set_carrier_wave_on(void)
+{
+    uint8_t temp_val_1;
+    uint8_t temp_val_2;
+
+    if(PAN3029_write_reg(REG_OP_MODE,PAN3029_MODE_STB3) != OK)
+    {
+        return FAIL;
+    }
+
+    PAN3029_set_tx_mode(PAN3029_TX_CONTINOUS);
+    PAN3029_set_tx_power(PAN3029_MAX_RAMP);
+
+    temp_val_1 = PAN3029_read_spec_page_reg(PAGE1_SEL, 0x1e);
+    temp_val_2 = ((temp_val_1 & 0xFE) | (1 << 0)) ;
+    if(PAN3029_write_spec_page_reg(PAGE1_SEL, 0x1e, temp_val_2) != OK)
+    {
+        return FAIL;
+    }
+    return OK;
+}
+
+/**
+ * @brief set carrier_wave mode frequence and send carrier_wave
+ * @param[in] <freq> RF frequency(in Hz) to set
+ * @return result
+ */
+uint32_t PAN3029_set_carrier_wave_freq(uint32_t freq)
+{
+    uint8_t buf[1]= {0};
+
+    if(PAN3029_write_reg(REG_OP_MODE,PAN3029_MODE_STB3) != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_set_tx_mode(PAN3029_TX_CONTINOUS) != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_set_freq(freq) != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_set_ldo_pa_on() != OK)
+    {
+        return FAIL;
+    }
+
+    rf_port.set_tx();
+
+    if(PAN3029_send_packet(buf, 1) != OK)
+    {
+        return FAIL;
+    }
+    return OK;
+}
+
+/**
+ * @brief set carrier_wave mode off
+ * @param[in] <none>
+ * @return result
+ */
+uint32_t PAN3029_set_carrier_wave_off(void)
+{
+    uint8_t temp_val_1;
+    uint8_t temp_val_2;
+
+    if(PAN3029_write_reg(REG_OP_MODE, PAN3029_MODE_STB3) != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_set_ldo_pa_off() != OK)
+    {
+        return FAIL;
+    }
+
+    temp_val_1 = PAN3029_read_spec_page_reg(PAGE1_SEL, 0x1e);
+    temp_val_2 = ((temp_val_1 & 0xFE) | (0 << 0)) ;
+    if(PAN3029_write_spec_page_reg(PAGE1_SEL, 0x1e, temp_val_2) != OK)
+    {
+        return FAIL;
+    }
+    return OK;
+}
+
+
+/**
+ * @brief set mapm mode enable
+ * @param[in] <none>
+ * @return result
+ */
+uint32_t PAN3029_mapm_en(void)
+{
+    uint8_t tmp_val;
+
+    tmp_val = PAN3029_read_spec_page_reg(PAGE1_SEL, 0x38);
+    tmp_val |= 0x01;
+    if(PAN3029_write_spec_page_reg(PAGE1_SEL, 0x38, tmp_val) != OK)
+    {
+        return FAIL;
+    }
+
+    return OK;
+}
+
+/**
+ * @brief set mapm mode disable
+ * @param[in] <none>
+ * @return result
+ */
+uint32_t PAN3029_mapm_dis(void)
+{
+    uint8_t tmp_val;
+
+    tmp_val = PAN3029_read_spec_page_reg(PAGE1_SEL, 0x38);
+    tmp_val &= ~0x01;
+    if(PAN3029_write_spec_page_reg(PAGE1_SEL, 0x38, tmp_val) != OK)
+    {
+        return FAIL;
+    }
+
+    return OK;
+}
+
+/**
+ * @brief set mapm mask
+ * @param[in] <mapm_val> mapm mask to set
+ *			  MAPM_ON / MAPM_OFF
+ * @return result
+ */
+uint32_t PAN3029_set_mapm_mask(uint32_t mapm_val)
+{
+    uint8_t temp_val_1;
+    uint8_t temp_val_2;
+
+    temp_val_1 = PAN3029_read_spec_page_reg(PAGE0_SEL, 0x58);
+    temp_val_2 = ((temp_val_1 & 0xbf) | (mapm_val << 6)) ;
+
+    if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x58, temp_val_2) != OK)
+    {
+        return FAIL;
+    }
+    else
+    {
+        return OK;
+    }
+}
+
+/**
+ * @brief get the number of fields
+ * @param[in] <none>
+
+ * @return <fn>
+ */
+uint32_t PAN3029_get_mapm_field_num(void)
+{
+    uint8_t reg_fn, fn_h, fn_l, fn;
+
+    reg_fn = PAN3029_read_spec_page_reg(PAGE1_SEL, 0x3d);
+    fn_h = ((reg_fn>>4) -1) * 15;
+    fn_l = (reg_fn & 0x0f) -1;
+    fn = fn_h + fn_l;
+
+    return fn;
+}
+
+/**
+ * @brief set the number of fields(range in 0x01~0xe0)
+ * @param[in] <fn> the number of fields you want to set
+
+ * @return result
+ */
+uint32_t PAN3029_set_mapm_field_num(uint8_t fn)
+{
+    uint8_t reg_fn, fn_h, fn_l;
+
+    fn_h = fn/15 + 1;
+    fn_l = fn%15 + 1;
+    reg_fn = (fn_h << 4) + fn_l;
+    if(PAN3029_write_spec_page_reg(PAGE1_SEL, 0x3d, reg_fn) != OK)
+    {
+        return FAIL;
+    }
+
+
+    return OK;
+}
+
+/**
+ * @brief set the unit code word of the field counter represents several fields
+ * @param[in] <fnm> the represents number you want to set
+              0--1
+              1--2
+              2--4
+              3--8
+ * @return result
+ */
+uint32_t PAN3029_set_mapm_field_num_mux(uint8_t fnm)
+{
+    uint8_t tmp_val;
+
+    tmp_val = PAN3029_read_spec_page_reg(PAGE1_SEL, 0x37);
+    tmp_val &= 0x3f;
+    tmp_val |= (fnm << 6);
+    if(PAN3029_write_spec_page_reg(PAGE1_SEL, 0x37, tmp_val) != OK)
+    {
+        return FAIL;
+    }
+
+    return OK;
+}
+
+/**
+ * @brief set the last group function selection
+ * @param[in] <group_fun_sel> The last group in the Field, its ADDR position function selection
+              0:ordinary address      1:Field counter
+
+ * @return result
+ */
+uint32_t PAN3029_set_mapm_group_fun_sel(uint8_t gfs)
+{
+    uint8_t tmp_val;
+
+    tmp_val = PAN3029_read_spec_page_reg(PAGE1_SEL, 0x38);
+    tmp_val &= 0xfd;
+    tmp_val |= (gfs << 1);
+    if(PAN3029_write_spec_page_reg(PAGE1_SEL, 0x38, tmp_val) != OK)
+    {
+        return FAIL;
+    }
+
+    return OK;
+}
+
+/**
+ * @brief set the number of groups in Field
+ * @param[in] <gn> the number of groups
+
+ * @return result
+ */
+uint32_t PAN3029_set_mapm_group_num(uint8_t gn)
+{
+    uint8_t tmp_val;
+
+    tmp_val = PAN3029_read_spec_page_reg(PAGE1_SEL, 0x38);
+    tmp_val &= 0xf3;
+    tmp_val |= (gn << 2);
+    if(PAN3029_write_spec_page_reg(PAGE1_SEL, 0x38, tmp_val) != OK)
+    {
+        return FAIL;
+    }
+
+    return OK;
+}
+
+
+/**
+ * @brief set the number of Preambles in first groups
+ * @param[in] <pgl> The numbers want set to Preambles in first groups(at least 10)
+
+ * @return result
+ */
+uint32_t PAN3029_set_mapm_firgroup_preamble_num(uint8_t pgl)
+{
+    if(PAN3029_write_spec_page_reg(PAGE1_SEL, 0x3b, pgl) != OK)
+    {
+        return FAIL;
+    }
+
+    return OK;
+}
+
+/**
+ * @brief set the number of preambles for groups other than the first group
+ * @param[in] <pgn>  the number of Preambles in other groups
+
+
+ * @return result
+ */
+uint32_t PAN3029_set_mapm_group_preamble_num(uint8_t pgn)
+{
+    if(PAN3029_write_spec_page_reg(PAGE1_SEL, 0x3c, pgn) != OK)
+    {
+        return FAIL;
+    }
+
+    return OK;
+}
+
+/**
+ * @brief set group address1 of mapm mode
+ * @param[in] <addr> The value of group address1 you want to set
+
+ * @return result
+ */
+uint32_t PAN3029_set_mapm_neces_preamble_num(uint16_t pn)
+{
+    uint8_t tmp_val_1, tmp_val_2, tmp_val_3;
+
+    tmp_val_1 = PAN3029_read_spec_page_reg(PAGE1_SEL, 0x39);
+    tmp_val_2 = (tmp_val_1&0xf0) | (pn>>8);
+
+    if(PAN3029_write_spec_page_reg(PAGE1_SEL, 0x39, tmp_val_2) != OK)
+    {
+        return FAIL;
+    }
+
+    tmp_val_3 = pn & 0xff;
+
+    if(PAN3029_write_spec_page_reg(PAGE1_SEL, 0x3a, tmp_val_3) != OK)
+    {
+        return FAIL;
+    }
+
+    return OK;
+}
+
+/**
+ * @brief set group address4 of mapm mode
+ * @param[in] <addr> The value of group address4 you want to set
+
+ * @return result
+ */
+uint32_t PAN3029_set_mapm_addr(uint8_t addr_no, uint8_t addr)
+{
+    if(PAN3029_write_spec_page_reg(PAGE1_SEL, 0x3e + addr_no, addr) != OK)
+    {
+        return FAIL;
+    }
+
+    return OK;
+}
+
+/**
+ * @brief calculate mapm preamble can sleep time
+ * @param[in] <none>
+ * @return sleeptime(ms)
+ */
+uint32_t PAN3029_calculate_mapm_preambletime(stc_mapm_cfg_t *mapm_cfg, uint32_t one_chirp_time)
+{
+    uint8_t fnm, gn, pgn, pg1, fn, pn;
+    uint16_t one_field_chirp, chirp_num;
+    uint32_t preamble_time;
+
+    pn = mapm_cfg->pn;
+    pgn = mapm_cfg->pgn;
+    pg1 = mapm_cfg->pg1;
+    gn = mapm_cfg->gn;
+    fnm = mapm_cfg->fnm;
+    fn = mapm_cfg->fn;
+    one_field_chirp = pg1+2 + (pgn+2) * gn;
+    chirp_num = (1 << fnm) * fn * one_field_chirp + pn - one_field_chirp;
+    preamble_time = one_chirp_time * chirp_num;
+
+    return preamble_time/1000;
+}
+
+/**
+ * @brief efuse function enable
+ * @param[in] <none>
+ * @return  result
+ */
+uint32_t PAN3029_efuse_on(void)
+{
+    uint8_t temp_val;
+
+    temp_val = PAN3029_read_spec_page_reg(PAGE2_SEL, 0x3e);
+    temp_val &= ~(1<<3);
+    if(PAN3029_write_spec_page_reg(PAGE2_SEL, 0x3e, temp_val) !=OK)
+    {
+        return FAIL;
+    }
+
+    return OK;
+}
+
+/**
+ * @brief efuse function disable
+ * @param[in] <none>
+ * @return  result
+ */
+uint32_t PAN3029_efuse_off(void)
+{
+    uint8_t temp_val;
+
+    temp_val = PAN3029_read_spec_page_reg(PAGE2_SEL, 0x3e);
+    temp_val |= (1<<3);
+    if(PAN3029_write_spec_page_reg(PAGE2_SEL, 0x3e, temp_val) !=OK)
+    {
+        return FAIL;
+    }
+
+    return OK;
+
+}
+
+/**
+ * @brief read efuse area data in unencrypted mode
+ * @param[in] <reg_addr> Efuse Register address, customer uses a fixed setting of 0x3c
+              <efuse_addr> aaddress want to read data in efuse, customer's usage range is 0x2d~0x7f
+ * @return data
+ */
+uint8_t PAN3029_efuse_read_byte(uint8_t reg_addr, uint8_t efuse_addr)
+{
+    uint8_t value = 0;
+    uint16_t timeout = 100;
+
+    efuse_addr <<= 1;
+    PAN3029_switch_page(PAGE2_SEL);
+    PAN3029_write_fifo(reg_addr, &efuse_addr, 1);
+    do {
+        if(PAN3029_read_spec_page_reg(PAGE0_SEL, 0x6c) & 0x80)
+        {
+            break;
+        }
+    } while(timeout--);
+    PAN3029_switch_page(PAGE2_SEL);
+    PAN3029_read_fifo(reg_addr, &value, 1);
+    return value;
+}
+
+/**
+ * @brief write efuse area data in unencrypted mode
+ * @param[in] <reg_addr> Efuse Register address, customer uses a fixed setting of 0x3c
+              <efuse_addr> address want to write data in efuse, customer's usage range is 0x2d~0x7f
+              <value> data want to write in efuse
+ * @return <none>
+ */
+void PAN3029_efuse_write_byte(uint8_t reg_addr, uint8_t efuse_addr, uint8_t value)
+{
+    uint8_t data_buf[5];
+    uint16_t timeout = 100;
+
+    memset(data_buf, 0, sizeof(data_buf));
+    data_buf[0] = (efuse_addr << 1) | 0x01;
+    data_buf[1] = value;
+
+    PAN3029_switch_page(PAGE2_SEL);
+    PAN3029_write_fifo(reg_addr, data_buf, 2);
+    do {
+        if(PAN3029_read_spec_page_reg(PAGE0_SEL, 0x6c) & 0x80)
+        {
+            break;
+        }
+    } while(timeout--);
+}
+
+/**
+ * @brief read efuse data for initialize
+ * @return data
+ */
+uint8_t PAN3029_efuse_read_encry_byte(uint8_t reg_addr, uint16_t pattern, uint8_t efuse_addr)
+{
+    uint8_t data_buf[5];
+    uint8_t value = 0;
+    uint16_t timeout = 100;
+
+    memset(data_buf, 0, sizeof(data_buf));
+    data_buf[0] = pattern >> 8;
+    data_buf[1] = pattern & 0xff;
+    data_buf[2] = efuse_addr << 1;
+
+    PAN3029_switch_page(PAGE2_SEL);
+    PAN3029_write_fifo(reg_addr, data_buf, 3);
+    do {
+        if(PAN3029_read_spec_page_reg(PAGE0_SEL, 0x6c) & 0x80)
+        {
+            break;
+        }
+        else
+        {
+        }
+    } while(timeout--);
+    PAN3029_switch_page(PAGE2_SEL);
+    PAN3029_read_fifo(reg_addr, &value, 1);
+
+    return value;
+}
+/**
+ * @brief enable DCDC calibration
+ * @param[in] <calibr_type> calibrated point
+              1--ref calibration
+              2--zero calibration
+              3--imax calibration
+ * @return result
+ */
+uint32_t PAN3029_set_dcdc_calibr_on(uint8_t calibr_type)
+{
+    if((calibr_type<CALIBR_REF_CMP)||(calibr_type>CALIBR_IMAX_CMP))
+    {
+        return FAIL;
+    }
+
+    uint8_t loop_time = 5;
+    uint8_t dcdc_cal = 0;
+    uint8_t temp_val_1, temp_val_2;
+    uint8_t rd_data, wr_data;
+    uint8_t offset_reg_addr;
+
+
+    if(calibr_type == CALIBR_ZERO_CMP)
+    {
+        offset_reg_addr = 0x1e;
+    }
+    else if(calibr_type == CALIBR_REF_CMP)
+    {
+        offset_reg_addr = 0x1d;
+    }
+    else if(calibr_type == CALIBR_IMAX_CMP)
+    {
+        offset_reg_addr = 0x1c;
+    }
+
+    temp_val_1 = PAN3029_read_spec_page_reg(PAGE3_SEL, 0x20);
+    temp_val_2 = (temp_val_1 & 0x9f) | (calibr_type << 5);
+
+    if(PAN3029_write_spec_page_reg(PAGE3_SEL, 0x20, temp_val_2) != OK)//calibration on
+    {
+        return FAIL;
+    }
+
+    for(; loop_time>0; loop_time--)
+    {
+        dcdc_cal |= (0x01 << (loop_time - 1));
+        wr_data = 0x80 | dcdc_cal;
+        if(PAN3029_write_spec_page_reg(PAGE3_SEL, offset_reg_addr, wr_data) != OK)
+        {
+            return FAIL;
+        }
+        rd_data = PAN3029_read_spec_page_reg(PAGE3_SEL, 0x27);
+        if (rd_data & 0x01)
+        {
+            dcdc_cal &= ~(0x01 << (loop_time - 1));
+        }
+        else
+        {
+            dcdc_cal |= (0x01 << (loop_time - 1));
+        }
+        wr_data = 0x80 | dcdc_cal;
+        if(PAN3029_write_spec_page_reg(PAGE3_SEL, offset_reg_addr, wr_data) != OK)
+        {
+            return FAIL;
+        }
+    }
+
+    return OK;
+}
+
+/**
+ * @brief disable DCDC calibration
+ * @param[in] <none>
+ * @return result
+ */
+uint32_t PAN3029_set_dcdc_calibr_off(void)
+{
+    uint8_t temp_val_1, temp_val_2;
+
+    temp_val_1 = PAN3029_read_spec_page_reg(PAGE3_SEL, 0x20);
+    temp_val_2 = temp_val_1 & 0x9f;
+    if(PAN3029_write_spec_page_reg(PAGE3_SEL, 0x20, temp_val_2) != OK)
+    {
+        return FAIL;
+    }
+
+    return OK;
+}
+
+/**
+ * @brief enable LDO PA
+ * @param[in] <none>
+ * @return result
+ */
+uint32_t PAN3029_set_ldo_pa_on(void)
+{
+    uint8_t temp_val;
+
+    temp_val = PAN3029_read_spec_page_reg(PAGE0_SEL, 0x4f);
+    temp_val |= 0x08;
+    if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x4f, temp_val) != OK)
+    {
+        return FAIL;
+    }
+
+    return OK;
+}
+
+/**
+ * @brief disable LDO PA
+ * @param[in] <none>
+ * @return result
+ */
+uint32_t PAN3029_set_ldo_pa_off(void)
+{
+    uint8_t temp_val;
+
+    temp_val = PAN3029_read_spec_page_reg(PAGE0_SEL, 0x4f);
+    temp_val &= 0xf7;
+    if(PAN3029_write_spec_page_reg(PAGE0_SEL, 0x4f, temp_val) != OK)
+    {
+        return FAIL;
+    }
+
+    return OK;
+}
+

+ 279 - 0
radio/pan3029.h

@@ -0,0 +1,279 @@
+/*******************************************************************************
+ * @note Copyright (C) 2023 Shanghai Panchip Microelectronics Co., Ltd. All rights reserved.
+ *
+ * @file pan3029.h
+ * @brief
+ *
+ * @history - V0.7, 2024-3
+*******************************************************************************/
+#ifndef __PAN_3029_H
+#define __PAN_3029_H
+
+#include "pan3029_port.h"
+
+/* result */
+#define OK                              0
+#define FAIL                            1
+/* 3029 mode define*/
+#define PAN3029_MODE_DEEP_SLEEP         0
+#define PAN3029_MODE_SLEEP              1
+#define PAN3029_MODE_STB1               2
+#define PAN3029_MODE_STB2               3
+#define PAN3029_MODE_STB3               4
+#define PAN3029_MODE_TX                 5
+#define PAN3029_MODE_RX                 6
+/* 3029 Tx mode */
+#define PAN3029_TX_SINGLE               0
+#define PAN3029_TX_CONTINOUS            1
+/* 3029 Rx mode */
+#define PAN3029_RX_SINGLE               0
+#define PAN3029_RX_SINGLE_TIMEOUT       1
+#define PAN3029_RX_CONTINOUS            2
+/* 3029 power maximum ramp */
+#define PAN3029_MAX_RAMP                22
+#define PAN3029_MIN_RAMP                1
+/* System control register */
+#define REG_SYS_CTL                     0x00
+#define REG_FIFO_ACC_ADDR               0x01
+/* 3V Logical area register */
+#define REG_OP_MODE                     0x02
+/* dcdc calibration select */
+#define CALIBR_REF_CMP  0x01
+#define CALIBR_ZERO_CMP 0x02
+#define CALIBR_IMAX_CMP 0x03
+
+#define MODEM_MODE_NORMAL               0x01
+#define MODEM_MODE_MULTI_SECTOR         0x02
+
+#define MODEM_MPA                       0x01
+#define MODEM_MPB                       0x02
+
+#define freq_360000000                  (360000000)
+#define freq_370000000                  (370000000)
+#define freq_385000000                  (385000000)
+#define freq_405000000                  (405000000)
+#define freq_415000000                  (415000000)
+#define freq_430000000                  (430000000)
+#define freq_445000000                  (445000000)
+#define freq_465000000                  (465000000)
+#define freq_485000000                  (485000000)
+#define freq_495000000                  (495000000)
+#define freq_505000000                  (505000000)
+#define freq_530000000                  (530000000)
+#define freq_565000000                  (565000000)
+#define freq_600000000                  (600000000)
+
+#define freq_720000000                  (720000000)
+#define freq_740000000                  (740000000)
+#define freq_770000000                  (770000000)
+#define freq_810000000                  (810000000)
+#define freq_830000000                  (830000000)
+#define freq_860000000                  (860000000)
+#define freq_890000000                  (890000000)
+#define freq_930000000                  (930000000)
+#define freq_970000000                  (970000000)
+#define freq_1010000000                 (1010000000)
+#define freq_1060000000                 (1060000000)
+#define freq_1080000000                 (1080000000)
+
+#define CODE_RATE_45                     0x01
+#define CODE_RATE_46                     0x02
+#define CODE_RATE_47                     0x03
+#define CODE_RATE_48                     0x04
+
+#define SF_5                            5
+#define SF_6                            6
+#define SF_7                            7
+#define SF_8                            8
+#define SF_9                            9
+#define SF_10                           10
+#define SF_11                           11
+#define SF_12                           12
+
+#define BW_62_5K                        6
+#define BW_125K                         7
+#define BW_250K                         8
+#define BW_500K                         9
+
+#define CRC_OFF                         0
+#define CRC_ON                          1
+
+#define PLHD_IRQ_OFF                    0
+#define PLHD_IRQ_ON                     1
+
+#define PLHD_OFF                        0
+#define PLHD_ON                         1
+
+#define PLHD_LEN8                       0
+#define PLHD_LEN16                      1
+
+#define AGC_ON                          1
+#define AGC_OFF                         0
+
+#define LO_400M                         0
+#define LO_800M                         1
+
+#define DCDC_OFF                        0
+#define DCDC_ON                         1
+
+#define LDR_OFF                         0
+#define LDR_ON                          1
+
+#define MAPM_OFF                        1
+#define MAPM_ON                         0
+
+#define CAD_DETECT_THRESHOLD_0A         0x0A
+#define CAD_DETECT_THRESHOLD_10         0x10
+#define CAD_DETECT_THRESHOLD_15         0x15
+#define CAD_DETECT_THRESHOLD_20         0x20
+
+#define CAD_DETECT_NUMBER_1             0x01
+#define CAD_DETECT_NUMBER_2             0x02
+#define CAD_DETECT_NUMBER_3             0x03
+
+#define REG_PAYLOAD_LEN                 0x0C
+
+/*IRQ BIT MASK*/
+#define REG_IRQ_MAPM_DONE               0x40
+#define REG_IRQ_RX_PLHD_DONE            0x10
+#define REG_IRQ_RX_DONE                 0x8
+#define REG_IRQ_CRC_ERR                 0x4
+#define REG_IRQ_RX_TIMEOUT              0x2
+#define REG_IRQ_TX_DONE                 0x1
+
+enum REF_CLK_SEL {REF_CLK_32M,REF_CLK_16M};
+enum PAGE_SEL {PAGE0_SEL,PAGE1_SEL,PAGE2_SEL, PAGE3_SEL};
+enum MAPM_LASTADDR_FUNC {ORDINARY_ADDR,FIELD_COUNTER};
+
+typedef struct
+{
+    uint8_t mapm_addr[4];
+    uint8_t fn;
+    uint8_t fnm;
+    uint8_t gfs;
+    uint8_t gn;
+    uint8_t pg1;
+    uint8_t pgn;
+    uint16_t pn;
+} stc_mapm_cfg_t;
+
+#pragma pack(1)
+typedef struct
+{
+    uint8_t  ramp;
+    uint8_t  pa_trim;
+    uint8_t  pa_ldo;
+    uint8_t  pa_duty;
+} power_ramp_t;
+#pragma pack ()
+
+#pragma pack(1)
+typedef struct
+{
+    uint8_t  ramp;
+    uint8_t  pa_ldo;
+    uint8_t  pa_duty;
+} power_ramp_cfg_t;
+#pragma pack ()
+
+uint8_t PAN3029_read_reg(uint8_t addr);
+uint8_t PAN3029_write_reg(uint8_t addr,uint8_t value);
+void PAN3029_write_fifo(uint8_t addr,uint8_t *buffer,int size);
+void PAN3029_read_fifo(uint8_t addr,uint8_t *buffer,int size);
+uint32_t PAN3029_switch_page(enum PAGE_SEL page);
+uint32_t PAN3029_write_spec_page_reg(enum PAGE_SEL page,uint8_t addr,uint8_t value);
+uint8_t PAN3029_read_spec_page_reg(enum PAGE_SEL page,uint8_t addr);
+uint32_t PAN3029_write_read_continue_regs(enum PAGE_SEL page,uint8_t addr,uint8_t *buffer,uint8_t len);
+uint8_t PAN3029_clr_irq(void);
+uint8_t PAN3029_get_irq(void);
+uint32_t PAN3029_refresh(void);
+uint16_t PAN3029_read_pkt_cnt(void);
+void PAN3029_clr_pkt_cnt(void);
+uint32_t PAN3029_agc_enable(uint32_t state);
+uint32_t PAN3029_agc_config(void);
+uint32_t PAN3029_ft_calibr(void);
+uint32_t PAN3029_init(void);
+uint32_t PAN3029_deepsleep_wakeup(void);
+uint32_t PAN3029_sleep_wakeup(void);
+uint32_t PAN3029_deepsleep(void);
+uint32_t PAN3029_sleep(void);
+uint32_t PAN3029_set_lo_freq(uint32_t lo);
+uint32_t PAN3029_set_freq(uint32_t freq);
+uint32_t PAN3029_read_freq(void);
+uint32_t PAN3029_calculate_tx_time(uint8_t size);
+uint32_t PAN3029_set_bw(uint32_t bw_val);
+uint8_t PAN3029_get_bw(void);
+uint32_t PAN3029_set_sf(uint32_t sf_val);
+uint8_t PAN3029_get_sf(void);
+uint32_t PAN3029_set_crc(uint32_t crc_val);
+uint8_t PAN3029_get_crc(void);
+uint32_t PAN3029_set_code_rate(uint8_t code_rate);
+uint8_t PAN3029_get_code_rate(void);
+uint32_t PAN3029_set_mode(uint8_t mode);
+uint8_t PAN3029_get_mode(void);
+uint32_t PAN3029_set_tx_mode(uint8_t mode);
+uint32_t PAN3029_set_rx_mode(uint8_t mode);
+uint32_t PAN3029_set_modem_mode(uint8_t mode);
+uint32_t PAN3029_set_timeout(uint32_t timeout);
+float PAN3029_get_snr(void);
+int8_t PAN3029_get_rssi(void);
+int8_t PAN3029_get_channel_rssi(void);
+uint32_t PAN3029_set_tx_power(uint8_t tx_power);
+uint32_t PAN3029_get_tx_power(void);
+uint32_t PAN3029_set_preamble(uint16_t reg);
+uint32_t PAN3029_get_preamble(void);
+uint32_t PAN3029_set_gpio_input(uint8_t gpio_pin);
+uint32_t PAN3029_set_gpio_output(uint8_t gpio_pin);
+uint32_t PAN3029_set_gpio_state(uint8_t gpio_pin, uint8_t state);
+uint8_t PAN3029_get_gpio_state(uint8_t gpio_pin);
+uint32_t PAN3029_cad_en(uint8_t threshold, uint8_t chirps);
+uint32_t PAN3029_cad_off(void);
+uint32_t PAN3029_set_syncword(uint32_t sync);
+uint8_t PAN3029_get_syncword(void);
+uint32_t PAN3029_send_packet(uint8_t *buff, uint32_t len);
+uint8_t PAN3029_recv_packet(uint8_t *buff);
+uint32_t PAN3029_set_early_irq(uint32_t earlyirq_val);
+uint8_t PAN3029_get_early_irq(void);
+uint32_t PAN3029_set_plhd(uint8_t addr,uint8_t len);
+uint8_t PAN3029_get_plhd_len(void);
+uint32_t PAN3029_set_plhd_mask(uint32_t plhd_val);
+uint8_t PAN3029_get_plhd_mask(void);
+uint8_t PAN3029_recv_plhd8(uint8_t *buff);
+uint8_t PAN3029_recv_plhd16(uint8_t *buff);
+uint32_t PAN3029_plhd_receive(uint8_t *buf,uint8_t len);
+uint32_t PAN3029_set_dcdc_mode(uint32_t dcdc_val);
+uint32_t PAN3029_set_ldr(uint32_t mode);
+uint32_t PAN3029_get_ldr(void);
+uint32_t PAN3029_set_all_sf_preamble(uint32_t sf);
+uint32_t PAN3029_set_all_sf_search(void);
+uint32_t PAN3029_set_all_sf_search_off(void);
+void PAN3029_irq_handler(void);
+uint32_t PAN3029_set_carrier_wave_on(void);
+uint32_t PAN3029_set_carrier_wave_freq(uint32_t freq);
+uint32_t PAN3029_set_carrier_wave_off(void);
+uint32_t carrier_wave_test_mode(void);
+uint32_t PAN3029_mapm_en(void);
+uint32_t PAN3029_mapm_dis(void);
+uint32_t PAN3029_set_mapm_mask(uint32_t mapm_val);
+uint32_t PAN3029_set_mapm_para(uint8_t field_num_mux, uint8_t group_fun_sel, uint8_t gn, uint8_t pgn);
+uint32_t PAN3029_set_mapm_addr(uint8_t addr_no, uint8_t addr);
+uint32_t PAN3029_calculate_mapm_preambletime(stc_mapm_cfg_t *mapm_cfg, uint32_t one_chirp_time);
+uint32_t PAN3029_get_mapm_field_num(void);
+uint32_t PAN3029_set_mapm_field_num(uint8_t);
+uint32_t PAN3029_set_mapm_field_num_mux(uint8_t fnm);
+uint32_t PAN3029_set_mapm_group_fun_sel(uint8_t gfs);
+uint32_t PAN3029_set_mapm_group_num(uint8_t gn);
+uint32_t PAN3029_set_mapm_firgroup_preamble_num(uint8_t pgl);
+uint32_t PAN3029_set_mapm_group_preamble_num(uint8_t pgn);
+uint32_t PAN3029_set_mapm_neces_preamble_num(uint16_t pn);
+uint32_t PAN3029_efuse_on(void);
+uint32_t PAN3029_efuse_off(void);
+uint8_t PAN3029_efuse_read_encry_byte(uint8_t reg_addr, uint16_t pattern, uint8_t efuse_addr);
+uint8_t PAN3029_efuse_read_byte(uint8_t reg_addr, uint8_t efuse_addr);
+void PAN3029_efuse_write_encry_byte(uint8_t reg_addr, uint16_t pattern, uint8_t efuse_addr, uint8_t value);
+void PAN3029_efuse_write_byte(uint8_t reg_addr, uint8_t efuse_addr, uint8_t value);
+uint32_t PAN3029_set_dcdc_calibr_on(uint8_t calibr_type);
+uint32_t PAN3029_set_dcdc_calibr_off(void);
+uint32_t PAN3029_set_ldo_pa_on(void);
+uint32_t PAN3029_set_ldo_pa_off(void);
+#endif

+ 158 - 0
radio/pan3029_port.c

@@ -0,0 +1,158 @@
+/*******************************************************************************
+ * @note Copyright (C) 2023 Shanghai Panchip Microelectronics Co., Ltd. All rights reserved.
+ *
+ * @file pan3029.c
+ * @brief
+ *
+ * @history - V0.2, 2023-08-04
+*******************************************************************************/
+#include "pan3029_port.h"
+
+extern uint8_t spi_tx_rx(uint8_t tx_data);
+
+rf_port_t rf_port= 
+{
+	.antenna_init = rf_antenna_init,
+	.tcxo_init = rf_tcxo_init,
+	.set_tx = rf_antenna_tx,
+	.set_rx = rf_antenna_rx,
+	.antenna_close = rf_antenna_close,
+	.tcxo_close = rf_tcxo_close,
+	.spi_readwrite = spi_readwritebyte,
+	.spi_cs_high = spi_cs_set_high,
+	.spi_cs_low = spi_cs_set_low,
+	.delayms = rf_delay_ms, 
+	.delayus = rf_delay_us,
+};
+
+/**
+ * @brief spi_readwritebyte
+ * @param[in] <tx_data> spi readwritebyte value
+ * @return result
+ */
+uint8_t spi_readwritebyte(uint8_t tx_data)
+{
+	return myRadioSpi_rwByte(tx_data);
+}
+
+/**
+ * @brief spi_cs_set_high
+ * @param[in] <none>
+ * @return none
+ */
+void spi_cs_set_high(void)
+{
+	BOARD_SPI_NSS_H();
+}
+
+/**
+ * @brief spi_cs_set_low
+ * @param[in] <none>
+ * @return none
+ */
+void spi_cs_set_low(void)
+{
+	BOARD_SPI_NSS_L();
+}
+void _delay(uint32_t time_ms)
+{
+    uint32_t i, j;
+    i = time_ms;
+    while (i --)
+    {
+        for ( j = 0; j < 10; j++)
+        {
+            ;
+        }
+    }
+}
+/**
+ * @brief rf_delay_ms
+ * @param[in] <time> ms
+ * @return none
+ */
+void rf_delay_ms(uint32_t time)
+{
+	delay1ms(time);
+}
+
+/**
+ * @brief rf_delay_us
+ * @param[in] <time> us
+ * @return none
+ */
+void rf_delay_us(uint32_t time)
+{
+	delay10us(time/10);
+}
+
+/**
+ * @brief do PAN3029 TX/RX IO to initialize
+ * @param[in] <none>
+ * @return none
+ */
+void rf_antenna_init(void)
+{
+	PAN3029_set_gpio_output(MODULE_GPIO_RX);
+	PAN3029_set_gpio_output(MODULE_GPIO_TX);
+	PAN3029_set_gpio_input(MODULE_GPIO_CAD_IRQ);
+
+	PAN3029_set_gpio_state(MODULE_GPIO_RX, 0);
+	PAN3029_set_gpio_state(MODULE_GPIO_TX, 0);
+	PAN3029_set_gpio_state(MODULE_GPIO_CAD_IRQ, 0);
+}
+
+/**
+ * @brief do PAN3029 XTAL IO to initialize
+ * @param[in] <none>
+ * @return none
+ */
+void rf_tcxo_init(void)
+{
+//	PAN3029_set_gpio_output(MODULE_GPIO_TCXO);
+//	PAN3029_set_gpio_state(MODULE_GPIO_TCXO, 1);
+}
+
+/**
+ * @brief close PAN3029 XTAL IO 
+ * @param[in] <none>
+ * @return none
+ */
+void rf_tcxo_close(void)
+{
+//	PAN3029_set_gpio_output(MODULE_GPIO_TCXO);
+//	PAN3029_set_gpio_state(MODULE_GPIO_TCXO, 0);
+}
+/**
+ * @brief change PAN3029 IO to rx
+ * @param[in] <none>
+ * @return none
+ */
+void rf_antenna_rx(void)
+{ 
+	PAN3029_set_gpio_state(MODULE_GPIO_TX, 0);
+	PAN3029_set_gpio_state(MODULE_GPIO_RX, 1);
+}
+
+/**
+ * @brief change PAN3029 IO to tx
+ * @param[in] <none>
+ * @return none
+ */
+void rf_antenna_tx(void)
+{
+	PAN3029_set_gpio_state(MODULE_GPIO_RX, 0);      
+	PAN3029_set_gpio_state(MODULE_GPIO_TX, 1);
+}
+
+/**
+ * @brief change PAN3029 IO to close
+ * @param[in] <none>
+ * @return none
+ */
+void rf_antenna_close(void)
+{
+	PAN3029_set_gpio_state(MODULE_GPIO_TX, 0);
+	PAN3029_set_gpio_state(MODULE_GPIO_RX, 0);
+}
+

+ 57 - 0
radio/pan3029_port.h

@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * @note Copyright (C) 2023 Shanghai Panchip Microelectronics Co., Ltd. All rights reserved.
+ *
+ * @file radio.c
+ * @brief
+ *
+ * @history - V1.0, 2023-05-21
+*******************************************************************************/
+#ifndef __pan3029_PORT_H_
+#define __pan3029_PORT_H_
+#include "stdio.h"
+#include "stdint.h"
+#include "stdlib.h"
+#include "stdbool.h"
+#include "math.h"
+#include "pan3029.h"
+#include "radio.h"
+#include "myRadio_gpio.h"
+
+#define SPI_WRITE_CHECK         1
+
+#define MODULE_GPIO_TX          0
+#define MODULE_GPIO_RX          10
+#define MODULE_GPIO_TCXO        3
+#define MODULE_GPIO_CAD_IRQ     11
+
+typedef struct {
+	void (*antenna_init)(void);
+	void (*tcxo_init)(void);
+	void (*set_tx)(void);
+	void (*set_rx)(void);
+	void (*antenna_close)(void);
+	void (*tcxo_close)(void);
+	uint8_t (*spi_readwrite)(uint8_t tx_data);
+	void (*spi_cs_high)(void);
+	void (*spi_cs_low)(void);
+	void (*delayms)(uint32_t time);
+	void (*delayus)(uint32_t time);
+}rf_port_t;
+
+extern rf_port_t rf_port;
+
+uint8_t spi_readwritebyte(uint8_t tx_data);
+void spi_cs_set_high(void);
+void spi_cs_set_low(void);
+void rf_delay_ms(uint32_t time);
+void rf_delay_us(uint32_t time);
+void rf_antenna_init(void);
+void rf_tcxo_init(void);
+void rf_tcxo_close(void);
+void rf_antenna_rx(void);
+void rf_antenna_tx(void);
+void rf_antenna_close(void);
+
+#endif
+
+

+ 972 - 0
radio/radio.c

@@ -0,0 +1,972 @@
+/*******************************************************************************
+ * @note Copyright (C) 2023 Shanghai Panchip Microelectronics Co., Ltd. All rights reserved.
+ *
+ * @file radio.c
+ * @brief
+ *
+ * @history - V0.7, 2024-3
+*******************************************************************************/
+#include "pan3029_port.h"
+#include "pan3029.h"
+
+extern bool pan3029_irq_trigged_flag;
+/*
+ * flag that indicate if a new packet is received.
+*/
+static int packet_received = RADIO_FLAG_IDLE;
+
+/*
+ * flag that indicate if transmision is finished.
+*/
+static int packet_transmit = RADIO_FLAG_IDLE;
+
+struct RxDoneMsg RxDoneParams;
+
+uint32_t cad_tx_timeout_flag = MAC_EVT_TX_CAD_NONE;
+/**
+ * @brief get receive flag
+ * @param[in] <none>
+ * @return receive state
+ */
+uint32_t rf_get_recv_flag(void)
+{
+    return packet_received;
+}
+
+/**
+ * @brief set receive flag
+ * @param[in] <status> receive flag state to set
+ * @return none
+ */
+void rf_set_recv_flag(int status)
+{
+    packet_received = status;
+}
+
+/**
+ * @brief get transmit flag
+ * @param[in] <none>
+ * @return reansmit state
+ */
+uint32_t rf_get_transmit_flag(void)
+{
+    return packet_transmit;
+}
+
+/**
+ * @brief set transmit flag
+ * @param[in] <status> transmit flag state to set
+ * @return none
+ */
+void rf_set_transmit_flag(int status)
+{
+    packet_transmit = status;
+}
+
+/**
+ * @brief do basic configuration to initialize
+ * @param[in] <none>
+ * @return result
+ */
+uint32_t rf_init(void)
+{
+    if(PAN3029_deepsleep_wakeup() != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_ft_calibr() != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_init() != OK)
+    {
+        return FAIL;
+    }
+
+    if(rf_set_agc(AGC_ON) != OK)
+    {
+        return FAIL;
+    }
+
+    rf_port.antenna_init();
+
+    return OK;
+}
+
+/**
+ * @brief change PAN3029 mode from deep sleep to wakeup(STB3)
+ * @param[in] <none>
+ * @return result
+ */
+uint32_t rf_deepsleep_wakeup(void)
+{
+    if(PAN3029_deepsleep_wakeup() != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_init() != OK)
+    {
+        return FAIL;
+    }
+
+    if(rf_set_agc(AGC_ON) != OK)
+    {
+        return FAIL;
+    }
+
+    rf_port.antenna_init();
+
+    return OK;
+}
+
+/**
+ * @brief change PAN3029 mode from sleep to wakeup(STB3)
+ * @param[in] <none>
+ * @return result
+ */
+uint32_t rf_sleep_wakeup(void)
+{
+    if(PAN3029_sleep_wakeup() != OK)
+    {
+        return FAIL;
+    }
+    rf_port.antenna_init();
+    return OK;
+}
+
+/**
+ * @brief change PAN3029 mode from standby3(STB3) to deep sleep, PAN3029 should set DCDC_OFF before enter deepsleep
+ * @param[in] <none>
+ * @return result
+ */
+uint32_t rf_deepsleep(void)
+{
+    rf_port.antenna_close();
+    return PAN3029_deepsleep();
+}
+
+/**
+ * @brief change PAN3029 mode from standby3(STB3) to deep sleep, PAN3029 should set DCDC_OFF before enter sleep
+ * @param[in] <none>
+ * @return result
+ */
+uint32_t rf_sleep(void)
+{
+    rf_port.antenna_close();
+    return PAN3029_sleep();
+}
+
+/**
+ * @brief calculate tx time
+ * @param[in] <size> tx len
+ * @return tx time(us)
+ */
+uint32_t rf_get_tx_time(uint8_t size)
+{
+    return PAN3029_calculate_tx_time(size);
+}
+
+/**
+ * @brief set rf mode
+ * @param[in] <mode>
+ *			  PAN3029_MODE_DEEP_SLEEP / PAN3029_MODE_SLEEP
+ *            PAN3029_MODE_STB1 / PAN3029_MODE_STB2
+ *            PAN3029_MODE_STB3 / PAN3029_MODE_TX / PAN3029_MODE_RX
+ * @return result
+ */
+uint32_t rf_set_mode(uint8_t mode)
+{
+    return PAN3029_set_mode(mode);
+}
+
+/**
+ * @brief get rf mode
+ * @param[in] <none>
+ * @return mode
+ *		   PAN3029_MODE_DEEP_SLEEP / PAN3029_MODE_SLEEP
+ *         PAN3029_MODE_STB1 / PAN3029_MODE_STB2
+ *         PAN3029_MODE_STB3 / PAN3029_MODE_TX / PAN3029_MODE_RX
+ */
+uint8_t rf_get_mode(void)
+{
+    return PAN3029_get_mode();
+}
+
+/**
+ * @brief set rf Tx mode
+ * @param[in] <mode>
+ *			  PAN3029_TX_SINGLE/PAN3029_TX_CONTINOUS
+ * @return result
+ */
+uint32_t rf_set_tx_mode(uint8_t mode)
+{
+    return PAN3029_set_tx_mode(mode);
+}
+
+/**
+ * @brief set rf Rx mode
+ * @param[in] <mode>
+ *			  PAN3029_RX_SINGLE/PAN3029_RX_SINGLE_TIMEOUT/PAN3029_RX_CONTINOUS
+ * @return result
+ */
+uint32_t rf_set_rx_mode(uint8_t mode)
+{
+    return PAN3029_set_rx_mode(mode);
+}
+
+/**
+ * @brief set timeout for Rx. It is useful in PAN3029_RX_SINGLE_TIMEOUT mode
+ * @param[in] <timeout> rx single timeout time(in ms)
+ * @return result
+ */
+uint32_t rf_set_rx_single_timeout(uint32_t timeout)
+{
+    return PAN3029_set_timeout(timeout);
+}
+
+/**
+ * @brief get snr value
+ * @param[in] <none>
+ * @return snr
+ */
+float rf_get_snr(void)
+{
+    return PAN3029_get_snr();
+}
+
+/**
+ * @brief get rssi value
+ * @param[in] <none>
+ * @return rssi
+ */
+int8_t rf_get_rssi(void)
+{
+    return PAN3029_get_rssi();
+}
+
+/**
+ * @brief current channel energy detection
+ * @param[in] <none>
+ * @return rssi
+ */
+int8_t rf_get_channel_rssi(void)
+{
+    return PAN3029_get_channel_rssi();
+}
+/**
+ * @brief get irq
+ * @param[in] <none>
+ * @return irq
+ */
+uint8_t rf_get_irq(void)
+{
+    return PAN3029_get_irq();
+}
+
+/**
+ * @brief clr irq
+ * @param[in] <none>
+ * @return result
+ */
+uint8_t rf_clr_irq(void)
+{
+    return PAN3029_clr_irq();
+}
+
+/**
+ * @brief set refresh
+ * @param[in] <none>
+ * @return result
+ */
+uint32_t rf_set_refresh(void)
+{
+    return PAN3029_refresh();
+}
+
+/**
+ * @brief set preamble
+ * @param[in] <reg> preamble
+ * @return result
+ */
+uint32_t rf_set_preamble(uint16_t pream)
+{
+    return PAN3029_set_preamble(pream);
+}
+
+/**
+ * @brief get preamble
+ * @param[in] <none>
+ * @return preamble
+ */
+uint32_t rf_get_preamble(void)
+{
+    return PAN3029_get_preamble();
+}
+
+/**
+ * @brief CAD function enable
+ * @param[in] <threshold>
+			  CAD_DETECT_THRESHOLD_0A / CAD_DETECT_THRESHOLD_10 / CAD_DETECT_THRESHOLD_15 / CAD_DETECT_THRESHOLD_20
+			<chirps>
+			  CAD_DETECT_NUMBER_1 / CAD_DETECT_NUMBER_2 / CAD_DETECT_NUMBER_3 /
+ * @return  result
+ */
+uint32_t rf_set_cad(uint8_t threshold, uint8_t chirps)
+{
+    return PAN3029_cad_en(threshold, chirps);
+}
+
+/**
+ * @brief CAD function disable
+ * @param[in] <none>
+ * @return  result
+ */
+uint32_t rf_set_cad_off(void)
+{
+    return PAN3029_cad_off();
+}
+
+/**
+ * @brief set rf syncword
+ * @param[in] <sync> syncword
+ * @return result
+ */
+uint32_t rf_set_syncword(uint8_t sync)
+{
+    return PAN3029_set_syncword(sync);
+}
+
+/**
+ * @brief read rf syncword
+ * @param[in] <none>
+ * @return syncword
+ */
+uint8_t rf_get_syncword(void)
+{
+    return PAN3029_get_syncword();
+}
+
+/**
+ * @brief RF IRQ server routine, it should be call at ISR of IRQ pin
+ * @param[in] <none>
+ * @return result
+ */
+void rf_irq_handler(void)
+{
+    PAN3029_irq_handler();
+}
+
+/**
+ * @brief set rf plhd mode on , rf will use early interruption
+ * @param[in] <addr> PLHD start addr,Range:0..7f
+		      <len> PLHD len
+			  PLHD_LEN8 / PLHD_LEN16
+ * @return result
+ */
+void rf_set_plhd_rx_on(uint8_t addr,uint8_t len)
+{
+    PAN3029_set_early_irq(PLHD_IRQ_ON);
+    PAN3029_set_plhd(addr, len);
+    PAN3029_set_plhd_mask(PLHD_ON);
+}
+
+/**
+ * @brief set rf plhd mode off
+ * @param[in] <none>
+ * @return result
+ */
+void rf_set_plhd_rx_off(void)
+{
+    PAN3029_set_early_irq(PLHD_IRQ_OFF);
+    PAN3029_set_plhd_mask(PLHD_OFF);
+}
+
+/**
+ * @brief get plhd len reg value
+ * @param[in] <none>
+ * @return <len> PLHD_LEN8 / PLHD_LEN16
+ */
+
+uint8_t rf_get_plhd_len(void)
+{
+    return PAN3029_get_plhd_len();
+}
+
+/**
+ * @brief receive a packet in non-block method, it will return 0 when no data got
+ * @param[in] <buff> buffer provide for data to receive
+			   <len> PLHD_LEN8 / PLHD_LEN16
+ * @return result
+ */
+uint32_t rf_plhd_receive(uint8_t *buf,uint8_t len)
+{
+    return PAN3029_plhd_receive(buf, len);
+}
+
+/**
+ * @brief set rf mapm mode on , rf will use mapm interruption
+ * @param[in] <none>
+ * @return result
+ */
+void rf_set_mapm_on(void)
+{
+    PAN3029_mapm_en();
+    PAN3029_set_mapm_mask(MAPM_ON);
+}
+
+/**
+ * @brief set mapm mode off
+ * @param[in] <none>
+ * @return result
+ */
+void rf_set_mapm_off(void)
+{
+    PAN3029_mapm_dis();
+    PAN3029_set_mapm_mask(MAPM_OFF);
+}
+
+/**
+ * @brief configure relevant parameters used in mapm mode
+ * @param[in] <p_mapm_cfg>
+              <fn>set the number of fields(range in 0x01~0xe0)
+              <field_num_mux> The unit code word of the Field counter represents several Fields
+              <group_fun_sel> The last group in the Field, its ADDR position function selection
+              0:ordinary address      1:Field counter
+              <gn> register for configuring the number of groups in a Field
+              0 1group\1 2group\2 3group\3 4group
+              <pgl>set the number of Preambles in first groups>
+              <pgn> the number of Preambles in other groups
+              <pn> the number of chirps before syncword after all fields have been sent
+ * @return result
+ */
+void rf_set_mapm_para(stc_mapm_cfg_t *p_mapm_cfg)
+{
+    PAN3029_set_mapm_field_num(p_mapm_cfg->fn);
+    PAN3029_set_mapm_field_num_mux(p_mapm_cfg->fnm);
+    PAN3029_set_mapm_group_fun_sel(p_mapm_cfg->gfs);
+    PAN3029_set_mapm_group_num(p_mapm_cfg->gn);
+    PAN3029_set_mapm_firgroup_preamble_num(p_mapm_cfg->pg1);
+    PAN3029_set_mapm_group_preamble_num(p_mapm_cfg->pgn);
+    PAN3029_set_mapm_neces_preamble_num(p_mapm_cfg->pn);
+}
+
+/**
+ * @brief receive a packet in non-block method, it will return 0 when no data got
+ * @param[in] <buff> buffer provide for data to receive
+ * @return length, it will return 0 when no data got
+ */
+uint32_t rf_receive(uint8_t *buf)
+{
+    return PAN3029_recv_packet(buf);
+}
+
+/**
+ * @brief rf enter rx continous mode to receive packet
+ * @param[in] <none>
+ * @return result
+ */
+uint32_t rf_enter_continous_rx(void)
+{
+    if(PAN3029_set_mode(PAN3029_MODE_STB3) != OK)
+    {
+        return FAIL;
+    }
+
+    rf_port.set_rx();
+
+    if(PAN3029_set_rx_mode(PAN3029_RX_CONTINOUS) != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_set_mode(PAN3029_MODE_RX) != OK)
+    {
+        return FAIL;
+    }
+    return OK;
+}
+
+/**
+ * @brief rf enter rx single timeout mode to receive packet
+ * @param[in] <timeout> rx single timeout time(in ms)
+ * @return result
+ */
+uint32_t rf_enter_single_timeout_rx(uint32_t timeout)
+{
+    if(PAN3029_set_mode(PAN3029_MODE_STB3) != OK)
+    {
+        return FAIL;
+    }
+
+    rf_port.set_rx();
+
+    if(PAN3029_set_rx_mode(PAN3029_RX_SINGLE_TIMEOUT) != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_set_timeout(timeout) != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_set_mode(PAN3029_MODE_RX) != OK)
+    {
+        return FAIL;
+    }
+    return OK;
+}
+
+/**
+ * @brief rf enter rx single mode to receive packet
+ * @param[in] <none>
+ * @return result
+ */
+uint32_t rf_enter_single_rx(void)
+{
+    if(PAN3029_set_mode(PAN3029_MODE_STB3) != OK)
+    {
+        return FAIL;
+    }
+
+    rf_port.set_rx();
+
+    if(PAN3029_set_rx_mode(PAN3029_RX_SINGLE) != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_set_mode(PAN3029_MODE_RX) != OK)
+    {
+        return FAIL;
+    }
+    return OK;
+}
+
+/**
+ * @brief rf enter single tx mode and send packet
+ * @param[in] <buf> buffer contain data to send
+ * @param[in] <size> the length of data to send
+ * @param[in] <tx_time> the packet tx time(us)
+ * @return result
+ */
+uint32_t rf_single_tx_data(uint8_t *buf, uint8_t size, uint32_t *tx_time)
+{
+    if(PAN3029_set_mode(PAN3029_MODE_STB3) != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_set_ldo_pa_on() != OK)
+    {
+        return FAIL;
+    }
+
+    rf_port.set_tx();
+
+    if(PAN3029_set_tx_mode(PAN3029_TX_SINGLE) != OK)
+    {
+        return FAIL;
+    }
+    *tx_time = rf_get_tx_time(size);
+
+    if(PAN3029_send_packet(buf, size) != OK)
+    {
+        return FAIL;
+    }
+
+    return OK;
+}
+
+/**
+ * @brief rf enter continous tx mode to ready send packet
+ * @param[in] <none>
+ * @return result
+ */
+uint32_t rf_enter_continous_tx(void)
+{
+    if(PAN3029_set_mode(PAN3029_MODE_STB3) != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_set_tx_mode(PAN3029_TX_CONTINOUS) != OK)
+    {
+        return FAIL;
+    }
+
+    return OK;
+}
+
+/**
+ * @brief rf continous mode send packet
+ * @param[in] <buf> buffer contain data to send
+ * @param[in] <size> the length of data to send
+ * @return result
+ */
+uint32_t rf_continous_tx_send_data(uint8_t *buf, uint8_t size)
+{
+    if(PAN3029_set_ldo_pa_on() != OK)
+    {
+        return FAIL;
+    }
+
+    rf_port.set_tx();
+
+    if(PAN3029_send_packet(buf, size) != OK)
+    {
+        return FAIL;
+    }
+
+    return OK;
+}
+
+/**
+ * @brief enable AGC function
+ * @param[in] <state>
+ *			  AGC_OFF/AGC_ON
+ * @return result
+ */
+uint32_t rf_set_agc(uint32_t state)
+{
+    if(PAN3029_agc_enable(state) != OK)
+    {
+        return FAIL;
+    }
+    if(PAN3029_agc_config() != OK)
+    {
+        return FAIL;
+    }
+
+    return OK;
+}
+
+/**
+ * @brief set rf para
+ * @param[in] <para_type> set type, rf_para_type_t para_type
+ * @param[in] <para_val> set value
+ * @return result
+ */
+uint32_t rf_set_para(rf_para_type_t para_type, uint32_t para_val)
+{
+    PAN3029_set_mode(PAN3029_MODE_STB3);
+    switch(para_type)
+    {
+    case RF_PARA_TYPE_FREQ:
+        PAN3029_set_freq(para_val);
+        rf_set_refresh();
+        break;
+    case RF_PARA_TYPE_CR:
+        PAN3029_set_code_rate(para_val);
+        rf_set_refresh();
+        break;
+    case RF_PARA_TYPE_BW:
+        PAN3029_set_bw(para_val);
+        rf_set_refresh();
+        break;
+    case RF_PARA_TYPE_SF:
+        PAN3029_set_sf(para_val);
+        rf_set_refresh();
+        break;
+    case RF_PARA_TYPE_TXPOWER:
+        PAN3029_set_tx_power(para_val);
+        rf_set_refresh();
+        break;
+    case RF_PARA_TYPE_CRC:
+        PAN3029_set_crc(para_val);
+        rf_set_refresh();
+        break;
+    default:
+        break;
+    }
+    return OK;
+}
+
+/**
+ * @brief get rf para
+ * @param[in] <para_type> get typ, rf_para_type_t para_type
+ * @param[in] <para_val> get value
+ * @return result
+ */
+uint32_t rf_get_para(rf_para_type_t para_type, uint32_t *para_val)
+{
+    PAN3029_set_mode(PAN3029_MODE_STB3);
+    switch(para_type)
+    {
+    case RF_PARA_TYPE_FREQ:
+        *para_val = PAN3029_read_freq();
+        return OK;
+    case RF_PARA_TYPE_CR:
+        *para_val = PAN3029_get_code_rate();
+        return OK;
+    case RF_PARA_TYPE_BW:
+        *para_val = PAN3029_get_bw();
+        return OK;
+    case RF_PARA_TYPE_SF:
+        *para_val = PAN3029_get_sf();
+        return OK;
+    case RF_PARA_TYPE_TXPOWER:
+        *para_val = PAN3029_get_tx_power();
+        return OK;
+    case RF_PARA_TYPE_CRC:
+        *para_val = PAN3029_get_crc();
+        return OK;
+    default:
+        return FAIL;
+    }
+}
+
+/**
+ * @brief set rf default para
+ * @param[in] <none>
+ * @return result
+ */
+void rf_set_default_para(void)
+{
+    PAN3029_set_mode(PAN3029_MODE_STB3);
+    rf_set_para(RF_PARA_TYPE_FREQ, DEFAULT_FREQ);
+    rf_set_para(RF_PARA_TYPE_CR, DEFAULT_CR);
+    rf_set_para(RF_PARA_TYPE_BW, DEFAULT_BW);
+    rf_set_para(RF_PARA_TYPE_SF, DEFAULT_SF);
+    rf_set_para(RF_PARA_TYPE_CRC, CRC_ON);
+    rf_set_para(RF_PARA_TYPE_TXPOWER, DEFAULT_PWR);
+}
+
+/**
+ * @brief set dcdc mode, The default configuration is DCDC_OFF, PAN3029 should set DCDC_OFF before enter sleep/deepsleep
+ * @param[in] <dcdc_val> dcdc switch
+ *		      DCDC_ON / DCDC_OFF
+ * @return result
+ */
+uint32_t rf_set_dcdc_mode(uint32_t dcdc_val)
+{
+    return PAN3029_set_dcdc_mode(dcdc_val);
+}
+
+/**
+ * @brief set LDR mode
+ * @param[in] <mode> LDR switch
+ *		      LDR_ON / LDR_OFF
+ * @return result
+ */
+uint32_t rf_set_ldr(uint32_t mode)
+{
+    return PAN3029_set_ldr(mode);
+}
+
+/**
+ * @brief get LDR mode
+ * @param[in] <none>
+ * @return result
+ */
+uint32_t rf_get_ldr(void)
+{
+    return PAN3029_get_ldr();
+}
+
+/**
+ * @brief set preamble by Spreading Factor,It is useful in all_sf_search mode
+ * @param[in] <sf> Spreading Factor
+ * @return result
+ */
+uint32_t rf_set_all_sf_preamble(uint32_t sf)
+{
+    return PAN3029_set_all_sf_preamble(sf);
+}
+
+/**
+ * @brief open all sf auto-search mode
+ * @param[in] <none>
+ * @return result
+ */
+uint32_t rf_set_all_sf_search(void)
+{
+    return PAN3029_set_all_sf_search();
+}
+
+/**
+ * @brief close all sf auto-search mode
+ * @param[in] <none>
+ * @return result
+ */
+uint32_t rf_set_all_sf_search_off(void)
+{
+    return PAN3029_set_all_sf_search_off();
+}
+
+/**
+ * @brief set mode
+ * @param[in] <mode> MODEM_MODE_NORMAL/MODEM_MODE_MULTI_SECTOR
+ * @return result
+ */
+uint32_t rf_set_modem_mode(uint8_t mode)
+{
+    return PAN3029_set_modem_mode(mode);
+}
+
+/**
+ * @brief RF IRQ server routine, it should be call at ISR of IRQ pin
+ * @param[in] <none>
+ * @return result
+ */
+void rf_irq_process(void)
+{
+    if(pan3029_irq_trigged_flag == true)
+    {
+        pan3029_irq_trigged_flag = false;
+
+        uint8_t irq = rf_get_irq();
+        if(irq & REG_IRQ_RX_PLHD_DONE)
+        {
+            RxDoneParams.PlhdSize = rf_get_plhd_len();
+            rf_set_recv_flag(RADIO_FLAG_PLHDRXDONE);
+            RxDoneParams.PlhdSize = rf_plhd_receive(RxDoneParams.PlhdPayload, RxDoneParams.PlhdSize);
+        }
+        if(irq & REG_IRQ_MAPM_DONE)
+        {
+            uint8_t addr_val = PAN3029_read_spec_page_reg(PAGE0_SEL, 0x6e);
+            RxDoneParams.mpam_recv_buf[RxDoneParams.mpam_recv_index++] = addr_val;
+            rf_set_recv_flag(RADIO_FLAG_MAPM);
+        }
+        if(irq & REG_IRQ_RX_DONE)
+        {
+            RxDoneParams.Snr = rf_get_snr();
+            RxDoneParams.Rssi = rf_get_rssi();
+            rf_set_recv_flag(RADIO_FLAG_RXDONE);
+            RxDoneParams.Size = rf_receive(RxDoneParams.Payload);
+        }
+        if(irq & REG_IRQ_CRC_ERR)
+        {
+            PAN3029_read_fifo(REG_FIFO_ACC_ADDR, RxDoneParams.TestModePayload, 10);
+            rf_set_recv_flag(RADIO_FLAG_RXERR);
+        }
+        if(irq & REG_IRQ_RX_TIMEOUT)
+        {
+            rf_set_refresh();
+            rf_set_recv_flag(RADIO_FLAG_RXTIMEOUT);
+        }
+        if(irq & REG_IRQ_TX_DONE)
+        {
+            PAN3029_set_ldo_pa_off();
+            rf_set_transmit_flag(RADIO_FLAG_TXDONE);
+        }
+        rf_clr_irq();
+    }
+}
+
+/**
+ * @brief get one chirp time
+ * @param[in] <bw>,<sf>
+ * @return <time> us
+ */
+uint32_t get_chirp_time(uint32_t bw,uint32_t sf)
+{
+    switch(bw)
+    {
+    case 6:
+        bw = 62500;
+        break;
+    case 7:
+        bw = 125000;
+        break;
+    case 8:
+        bw = 250000;
+        break;
+    case 9:
+        bw = 500000;
+        break;
+    default:
+        return FAIL;
+    }
+    return (1000000/bw)*(1<<sf);
+}
+
+/**
+ * @brief check cad rx inactive
+ * @param[in] <one_chirp_time>
+ * @return <result> LEVEL_ACTIVE/LEVEL_INACTIVE
+ */
+uint32_t check_cad_rx_inactive(uint32_t one_chirp_time)
+{
+    rf_delay_us(one_chirp_time*7);
+    rf_delay_us(360);
+
+    if(CHECK_CAD() != 1)
+    {
+        rf_set_mode(PAN3029_MODE_STB3);
+        return LEVEL_INACTIVE;
+    }
+
+    return LEVEL_ACTIVE;
+}
+
+/**
+ * @brief check cad tx inactive
+ * @param[in] <none>
+ * @return <result> OK/FAIL
+ */
+uint32_t check_cad_tx_inactive(void)
+{
+    uint32_t bw,sf;
+
+    rf_get_para(RF_PARA_TYPE_BW, &bw);
+    rf_get_para(RF_PARA_TYPE_SF, &sf);
+    uint32_t one_chirp_time = get_chirp_time(bw,sf);//us
+
+    if(rf_set_cad(CAD_DETECT_THRESHOLD_10, CAD_DETECT_NUMBER_3) != OK)
+    {
+        return FAIL;
+    }
+
+    cad_tx_timeout_flag = MAC_EVT_TX_CAD_NONE;
+
+    if(rf_enter_continous_rx() != OK)
+    {
+        return FAIL;
+    }
+
+    SET_TIMER_MS(one_chirp_time*7/1000 + 1);
+
+    return OK;
+}
+
+/**
+ * @brief dcdc calibration
+ * @param[in] <none>
+ * @return <result> OK/FAIL
+ */
+uint32_t rf_set_dcdc_calibr_on(void)
+{
+    if(PAN3029_set_dcdc_mode(DCDC_OFF) != OK)
+    {
+        return FAIL;
+    }
+
+    if(PAN3029_set_dcdc_calibr_on(CALIBR_REF_CMP) != OK)
+    {
+        return FAIL;
+    }
+    rf_port.delayus(100);
+
+    if(PAN3029_set_dcdc_calibr_on(CALIBR_ZERO_CMP) != OK)
+    {
+        return FAIL;
+    }
+    rf_port.delayus(100);
+
+    if(PAN3029_set_dcdc_calibr_on(CALIBR_IMAX_CMP) != OK)
+    {
+        return FAIL;
+    }
+    rf_port.delayus(100);
+
+    if(PAN3029_set_dcdc_calibr_off() != OK)
+    {
+        return FAIL;
+    }
+
+    return OK;
+}

+ 128 - 0
radio/radio.h

@@ -0,0 +1,128 @@
+/*******************************************************************************
+ * @note Copyright (C) 2023 Shanghai Panchip Microelectronics Co., Ltd. All rights reserved.
+ *
+ * @file radio.h
+ * @brief
+ *
+ * @history - V0.7, 2024-3
+*******************************************************************************/
+#ifndef __RADIO_H_
+#define __RADIO_H_
+
+#include "pan3029_port.h"
+#include "pan3029.h"
+#define DEFAULT_PWR            22
+#define DEFAULT_FREQ           (433920000)
+#define DEFAULT_SF             SF_9
+#define DEFAULT_BW             BW_125K
+#define DEFAULT_CR             CODE_RATE_47
+
+#define RADIO_FLAG_IDLE         0
+#define RADIO_FLAG_TXDONE       1
+#define RADIO_FLAG_RXDONE       2
+#define RADIO_FLAG_RXTIMEOUT    3
+#define RADIO_FLAG_RXERR        4
+#define RADIO_FLAG_PLHDRXDONE   5
+#define RADIO_FLAG_MAPM         6
+
+
+#define LEVEL_INACTIVE          6
+#define LEVEL_ACTIVE            7
+
+#define	GPIO_PIN_CAD            Pin09
+#define	GPIO_PORT_CAD           PortA
+
+#define  CHECK_CAD()            0//PORT_GetBit(GPIO_PORT_CAD, GPIO_PIN_CAD)
+#define  SET_TIMER_MS(time)     //timer6_open_ms(time)
+
+#define MAC_EVT_TX_CAD_NONE     0x00
+#define MAC_EVT_TX_CAD_TIMEOUT  0x01
+#define MAC_EVT_TX_CAD_ACTIVE   0x02
+
+#define TEST_MODE_BUFFER_LEN   10
+
+#pragma pack(1)
+struct RxDoneMsg
+{
+    uint8_t Payload[255];
+    uint8_t PlhdPayload[16];
+	uint8_t TestModePayload[TEST_MODE_BUFFER_LEN];
+    uint16_t PlhdSize;
+    uint16_t Size;
+    uint16_t mpam_recv_index;
+    uint8_t mpam_recv_buf[1024];  //set buf size based on actual application
+    int8_t Rssi;
+    float Snr;
+};
+#pragma pack ()
+
+typedef enum {
+    RF_PARA_TYPE_FREQ,
+    RF_PARA_TYPE_CR,
+    RF_PARA_TYPE_BW,
+    RF_PARA_TYPE_SF,
+    RF_PARA_TYPE_TXPOWER,
+    RF_PARA_TYPE_LDRO,
+    RF_PARA_TYPE_CRC,
+} rf_para_type_t;
+
+uint32_t rf_get_recv_flag(void);
+void rf_set_recv_flag(int status);
+uint32_t rf_get_transmit_flag(void);
+void rf_set_transmit_flag(int status);
+uint32_t rf_init(void);
+uint32_t rf_deepsleep_wakeup(void);
+uint32_t rf_deepsleep(void);
+uint32_t rf_sleep_wakeup(void);
+uint32_t rf_sleep(void);
+uint32_t rf_get_tx_time(uint8_t size);
+uint32_t rf_set_mode(uint8_t mode);
+uint8_t rf_get_mode(void);
+uint32_t rf_set_tx_mode(uint8_t mode);
+uint32_t rf_set_rx_mode(uint8_t mode);
+uint32_t rf_set_rx_single_timeout(uint32_t timeout);
+float rf_get_snr(void);
+int8_t rf_get_rssi(void);
+int8_t rf_get_channel_rssi(void);
+uint8_t rf_get_irq(void);
+uint8_t rf_clr_irq(void);
+uint32_t rf_set_refresh(void);
+uint32_t rf_set_preamble(uint16_t pream);
+uint32_t rf_get_preamble(void);
+uint32_t rf_set_cad(uint8_t threshold, uint8_t chirps);
+uint32_t rf_set_cad_off(void);
+uint32_t rf_set_syncword(uint8_t sync);
+uint8_t rf_get_syncword(void);
+void rf_irq_handler(void);
+void rf_set_plhd_rx_on(uint8_t addr,uint8_t len);
+void rf_set_plhd_rx_off(void);
+uint8_t rf_get_plhd_len(void);
+uint32_t rf_receive(uint8_t *buf);
+uint32_t rf_plhd_receive(uint8_t *buf,uint8_t len);
+uint32_t rf_enter_continous_rx(void);
+uint32_t rf_enter_single_timeout_rx(uint32_t timeout);
+uint32_t rf_enter_single_rx(void);
+uint32_t rf_single_tx_data(uint8_t *buf, uint8_t size, uint32_t *tx_time);
+uint32_t rf_enter_continous_tx(void);
+uint32_t rf_continous_tx_send_data(uint8_t *buf, uint8_t size);
+uint32_t rf_set_agc(uint32_t state);
+uint32_t rf_set_para(rf_para_type_t para_type, uint32_t para_val);
+uint32_t rf_get_para(rf_para_type_t para_type, uint32_t *para_val);
+void rf_set_default_para(void);
+uint32_t rf_set_modem_mode(uint8_t mode);
+uint32_t rf_set_dcdc_mode(uint32_t dcdc_val);
+uint32_t rf_set_ldr(uint32_t mode);
+uint32_t rf_get_ldr(void);
+uint32_t rf_set_all_sf_preamble(uint32_t sf);
+uint32_t rf_set_all_sf_search(void);
+uint32_t rf_set_all_sf_search_off(void);
+void rf_irq_process(void);
+uint32_t get_chirp_time(uint32_t bw,uint32_t sf);
+uint32_t check_cad_rx_inactive(uint32_t one_chirp_time);
+uint32_t check_cad_tx_inactive(void);
+void rf_set_mapm_on(void);
+void rf_set_mapm_off(void);
+void rf_set_mapm_para(stc_mapm_cfg_t *p_mapm_cfg);
+uint32_t rf_set_dcdc_calibr_on(void);
+#endif
+