diff --git a/bee/drivers/ppt/CMakeLists.txt b/bee/drivers/ppt/CMakeLists.txt index c05cb37b..7dd2f50c 100644 --- a/bee/drivers/ppt/CMakeLists.txt +++ b/bee/drivers/ppt/CMakeLists.txt @@ -1,4 +1,6 @@ # Copyright (c) 2024 Realtek Semiconductor Corp. # SPDX-License-Identifier: Apache-2.0 -add_subdirectory_ifdef(CONFIG_REALTEK_USING_PPT_SYNC_MASTER sync) +if(CONFIG_REALTEK_USING_PPT_SYNC_MASTER OR CONFIG_REALTEK_USING_PPT_SYNC_SLAVE) + add_subdirectory(sync) +endif() diff --git a/bee/drivers/ppt/Kconfig b/bee/drivers/ppt/Kconfig index e8d43944..14a54cde 100644 --- a/bee/drivers/ppt/Kconfig +++ b/bee/drivers/ppt/Kconfig @@ -7,6 +7,25 @@ config REALTEK_PPT config REALTEK_USING_PPT_SYNC_MASTER bool "RealTek ppt master library" - default y if REALTEK_PPT + default y if REALTEK_PPT && !REALTEK_USING_PPT_SYNC_SLAVE + select USE_HAL_REALTEK_ENHTIM help This option enables the ppt master library for REALTEK MCU. + +config REALTEK_USING_PPT_SYNC_SLAVE + bool "RealTek ppt slave library" + default n + select USE_HAL_REALTEK_ENHTIM + help + This option enables the ppt slave library for REALTEK MCU. + Requires libppt_sync_slave.a placed in + modules/hal/realtek/bee/drivers/ppt/sync/lib/rtl87x2g/. + +config PPT_DRIVER_LOG_LEVEL + int "PPT 2.4G driver log level" + range 0 4 + default 0 + depends on REALTEK_PPT + help + Compile-time log level for PPT 2.4G driver modules. + 0=none 1=err 2=wrn 3=inf 4=dbg. Set in prj.conf. diff --git a/bee/drivers/ppt/driver/common/DataType.h b/bee/drivers/ppt/driver/common/DataType.h new file mode 100644 index 00000000..f5d4d33a --- /dev/null +++ b/bee/drivers/ppt/driver/common/DataType.h @@ -0,0 +1,172 @@ +//DataType.h + +#ifndef _DATATYPE_H_ +#define _DATATYPE_H_ + +#include + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +typedef unsigned char BOOLEAN; +typedef void VOID; +typedef unsigned char UCHAR; +typedef unsigned char UINT8; +typedef unsigned short UINT16; +typedef unsigned int UINT32; +typedef unsigned long long UINT64; +typedef signed char CHAR; +typedef signed char INT8; +typedef signed short INT16; +typedef signed int INT32; +typedef signed long long INT64; + +/** @brief The upper 8 bits of a 16 bit value */ +#ifndef MSB +#define MSB(a) (((a) & 0xFF00) >> 8) +#endif + +/** @brief The lower 8 bits of a 16 bit value */ +#ifndef LSB +#define LSB(a) ((a) & 0xFF) +#endif + +#ifndef MAX +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#endif + +#ifndef MIN +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +#ifndef CEIL +#define CEIL(a,b) (((a)+(b)-1)/(b)) +#endif + +#define KSEG1 0 +#define NON_DCATCH(ptr) ((UINT32)((UINT32)(ptr) | KSEG1 | BUFFER_RAM_START_ADDR)) +#define NON_DCATCH_PTR(ptr) ((UINT8*)NON_DCATCH(ptr)) + +#define RD_32BIT_IO(base, offset) \ + (*(volatile UINT32*)((base) + (offset))) +#define RD_16BIT_IO(base, offset) \ + (*((volatile UINT16*)((base) + (offset)))) +#define RD_8BIT_IO(base, offset) \ + (*((volatile UINT8*)((base) + (offset)))) +#define WR_32BIT_IO(base, offset, val) \ + (*((volatile UINT32*)((base) + (offset))) = (val)) +#define WR_16BIT_IO(base, offset, val) \ + (*((volatile UINT16*)((base) + (offset))) = (val)) +#define WR_8BIT_IO(base, offset, val) \ + (*((volatile UINT8*)((base) + (offset))) = (val)) + +#define RD_REG_MMIO(type, addr) \ + (*((volatile type*) (addr))) +#define WR_REG_MMIO(type, addr, val) \ + (*((volatile type*) (addr)) = (val)) + + +typedef union UINT32_S_ +{ + UINT32 u4Byte; + UINT16 u2Byte[2]; + UINT8 u1Byte[4]; +} UINT32_S; + +typedef union INT32_S_ +{ + INT32 s4Byte; + INT16 s2Byte[2]; + INT8 s1Byte[4]; +} INT32_S; + +typedef struct UINT32_BM_S_ +{ + UINT32 bit0: 1; + UINT32 bit1: 1; + UINT32 bit2: 1; + UINT32 bit3: 1; + UINT32 bit4: 1; + UINT32 bit5: 1; + UINT32 bit6: 1; + UINT32 bit7: 1; + UINT32 bit8: 1; + UINT32 bit9: 1; + UINT32 bit10: 1; + UINT32 bit11: 1; + UINT32 bit12: 1; + UINT32 bit13: 1; + UINT32 bit14: 1; + UINT32 bit15: 1; + UINT32 bit16: 1; + UINT32 bit17: 1; + UINT32 bit18: 1; + UINT32 bit19: 1; + UINT32 bit20: 1; + UINT32 bit21: 1; + UINT32 bit22: 1; + UINT32 bit23: 1; + UINT32 bit24: 1; + UINT32 bit25: 1; + UINT32 bit26: 1; + UINT32 bit27: 1; + UINT32 bit28: 1; + UINT32 bit29: 1; + UINT32 bit30: 1; + UINT32 bit31: 1; +} UINT32_BM_S; + +typedef struct UINT16_BM_S_ +{ + UINT16 bit0: 1; + UINT16 bit1: 1; + UINT16 bit2: 1; + UINT16 bit3: 1; + UINT16 bit4: 1; + UINT16 bit5: 1; + UINT16 bit6: 1; + UINT16 bit7: 1; + UINT16 bit8: 1; + UINT16 bit9: 1; + UINT16 bit10: 1; + UINT16 bit11: 1; + UINT16 bit12: 1; + UINT16 bit13: 1; + UINT16 bit14: 1; + UINT16 bit15: 1; +} UINT16_BM_S; + +typedef struct UINT8_BM_S_ +{ + UINT8 bit0: 1; + UINT8 bit1: 1; + UINT8 bit2: 1; + UINT8 bit3: 1; + UINT8 bit4: 1; + UINT8 bit5: 1; + UINT8 bit6: 1; + UINT8 bit7: 1; +} UINT8_BM_S; + +#define PLATFORM_WAKEUP_TIME_INFINITE 0xffffffff + +typedef enum +{ + ROUND = 0, + ROUNDUP = 1, + ROUNDDOWN = 2, +} RoundType; + +uint32_t us_to_rtc_clk(uint32_t us, RoundType round_type); + +uint32_t rtc_clk_to_us(uint32_t rtc_clk, RoundType round_type); + +uint64_t clk_cnt_diff(uint64_t clk_begin, uint64_t clk_end, uint64_t bit_mask); + +#endif // _DATATYPE_H_ + diff --git a/bee/drivers/ppt/driver/common/bzdma.h b/bee/drivers/ppt/driver/common/bzdma.h new file mode 100644 index 00000000..92b8733a --- /dev/null +++ b/bee/drivers/ppt/driver/common/bzdma.h @@ -0,0 +1,223 @@ +/*************************************************************************** + Copyright (C) Realtek + This module is a confidential and proprietary property of Realtek and + a possession or use of this module requires written permission of Realtek. + ***************************************************************************/ + +/** + * \file + * BZDMA interface. + * + * \author + * austin , (C) 2010 + */ + +/** \addtogroup bb_driver_bzdma Baseband Driver Module + * @{ */ +#ifndef __BB_BZDMA_H__ +#define __BB_BZDMA_H__ + +#include +#include +#include "utils.h" + +#ifndef FALSE +#define FALSE false +#endif + +#ifndef TRUE +#define TRUE true +#endif + +typedef bool BOOLEAN; +typedef unsigned char UCHAR; +typedef uint8_t UINT8; +typedef uint16_t UINT16; +typedef uint32_t UINT32; +typedef uint64_t UINT64; +typedef signed char CHAR; +typedef int8_t INT8; +typedef int16_t INT16; +typedef int32_t INT32; +typedef int64_t INT64; + +//#include "DataType.h" +//#include "bt_fw_os.h" +//#include "platform.h" + +#define BZDMA_TX_DESC_ENTRY_NUM 13 +#define BZDMA_LEONLY_TX_MAX_ENTRY_NUM 11 + +/* ============= BZ DMA Register Structure (End) =================== */ +/* The structure of one segment of TX Descriptor */ +typedef struct BZDMA_TX_DESC_SEGMENT_ +{ + union + { + struct + { +#ifdef _NEW_BZDMA_FROM_V10_FROM_160223_ + UINT32 start_addr: 18; /* bit[17:0], the start address of SRAM */ +#else + UINT32 start_addr: 16; /* bit[15:0], the start address of SRAM */ + UINT32 rsvd0: 2; /* bit[17:16], reserved */ +#endif + UINT32 len: 11; /* bit[28:18], the copied length*/ + UINT32 rsvd1: 3; /* bit[31:29], reserved */ + }; + UINT32 DWord0; + }; + union + { + struct + { + UINT32 rsvd2: 29; /* bit[60:32], reserved */ + UINT32 llid: 2; /* bit[62:61], the link layer id */ + UINT32 isLast: 1; /* bit[63], is last segment */ + }; + UINT32 DWord1; + }; +} BZDMA_TX_DESC_SEGMENT, *PBZDMA_TX_DESC_SEGMENT; + + +typedef union BZDMA_BLEONLY_TX_DESC_SEGMENT_ +{ + struct + { + UINT32 start_addr: 16; /* bit[15:0], the start address of buffer SRAM + (note: it's 8 byte units in 18 bits mode) */ + UINT32 len: 11; /* bit[26:16], the copied length*/ +#if defined (_NEW_BZDMA_FROM_V10_) || defined (_BT5_0_LE_LONG_RANGE_SUPPORT_) + UINT32 le_ci: 2; /* bit[28:27], code indicator for LE LR */ +#else + UINT32 rsvd: 2; /* bit[28:27], reserved */ +#endif + UINT32 llid: 2; /* bit[30:29], the link layer id (only valid for data) */ + UINT32 isLast: 1; /* bit[31], is last segment (only valid for adv) + (170524) after _BT5_1_LE_CONNECTION_CTE_RECEIVE_TRANSMIT_PROCEDURE_ + this bit is used to indicate the sp flag in the header of + data channel pkt. */ + }; + UINT32 DWord; +} BZDMA_BLEONLY_TX_DESC_SEGMENT, *PBZDMA_BLEONLY_TX_DESC_SEGMENT; + +/* The structure of one fragment of TX Descriptor for BLE only */ +typedef union BZDMA_BLEONLY_TX_DESC_FRAGMENT_ +{ + struct + { + UINT32 start_addr: 16; /* bit[15:0], the start address of buffer SRAM */ + UINT32 len: 11; /* bit[26:16], the copied length*/ + UINT32 rsvd: 4; /* bit[30:27], reserved */ + UINT32 isLast: 1; /* bit[31], is last segment */ + }; + struct + { + UINT32 start_addr_ex: 18; /* bit[17:0], the start address of buffer SRAM */ + UINT32 len_ex: 11; /* bit[28:18], the copied length*/ + UINT32 rsvd_ex: 2; /* bit[30:29], reserved */ + UINT32 isLast_ex: 1; /* bit[31], is last segment */ + }; + UINT32 DWord; +} BZDMA_BLEONLY_TX_DESC_FRAGMENT, *PBZDMA_BLEONLY_TX_DESC_FRAGMENT; + +/* The structure of TX descriptor entry status of BZDMA */ +typedef struct BZDMA_TX_DESC_ENTRY_STATUS_ +{ + BZDMA_TX_DESC_SEGMENT *pTxDesc; /* The pointer of multiple segments */ + UINT32 entry_idx: 4; /* my entry index*/ + UINT32 pkt_id: 2; /* current packet Id */ + UINT32 ch_id: 2; /* current channel Id */ + UINT32 used: 1; /* the entry is used ? */ + UINT32 piconet_id: 2; /* current piconet id */ + UINT32 total_len: 11; /* the total data length of all segments */ + UINT32 total_segs: 4; /* the total segements */ + UINT32 is_sco_lt: 1; /* the logic link is sco ? */ +#ifndef _NEW_HCI_DMA_DESIGN_FOR_ACL_SNIFF_SCHEDULE_ + UINT32 rsvd1: 5; /* reserved */ +#else + UINT32 is_in_sniff: 1; /* the command is used in sniff ? */ + UINT32 rsvd1: 4; /* reserved */ +#endif + + UINT32 le_mode_en: 1; /* Enable Txdma in LE mode */ + UINT32 le_pdu_cmd: 2; /* The Txdma PDU Command Type in LE */ + UINT32 le_conn_entry: 6; /* Connection Entry in LE */ + UINT32 lt_addr: 3; /* my lt_addr */ + UINT32 rsvd2: 20; /* reserved */ +} BZDMA_TX_DESC_ENTRY_STATUS, *PBZDMA_TX_DESC_ENTRY_STATUS; + +/* Fragment memory layout: + * adv_id=0 adv_id=1 adv_id=2 + * +----------------+----------------+----------------+ + * seg_id=0 | MAX_FRAGS_ADV0 | MAX_FRAGS_ADV1 | MAX_FRAGS_ADV2 | + * +----------------+----------------+----------------+ + * seg_id=1 | MAX_FRAGS_ADV0 | MAX_FRAGS_ADV1 | MAX_FRAGS_ADV2 | + * +----------------+----------------+----------------+ + */ +/* The structure of Ble Advertising TX descriptor entry status of BZDMA */ +typedef struct BZDMA_BLEONLY_ADV_TX_DESC_ENTRY_STATUS_ +{ + BZDMA_BLEONLY_TX_DESC_SEGMENT *pTxSegDesc; /* The start pointer of multiple segments */ + BZDMA_BLEONLY_TX_DESC_FRAGMENT *pTxFragDesc; /* The start pointer of multiple fragments */ + UINT32 max_segs: 2; /* maximum segments in the tx descriptor */ + UINT32 max_frags: 4; /* maximum fragments in one segment */ + UINT32 le_pdu_cmd: 2; /* The Txdma PDU Command Type in LE */ +#ifdef BT5_0_LE_ADV_EXT_SUPPORT_NEW_BZDMA_FOR_LR_AUX_SCAN_RSP + UINT32 frag_row_num: 8; /* Number of fragments in a row */ + UINT32 rsvd1: 16; /* reserved */ +#else + UINT32 rsvd1: 24; /* reserved */ +#endif + UINT8 TxSegDescOffset[3]; /* the start offset array of Tx segment descriptor for every advertising channels */ + UINT8 TxFragDescOffset[3]; /* the start offset array of Tx fragment descriptor for every advertising channels */ +} BZDMA_BLEONLY_ADV_TX_DESC_ENTRY_STATUS, *PBZDMA_BLEONLY_ADV_TX_DESC_ENTRY_STATUS; + +/* The structure of Ble Data TX descriptor entry status of BZDMA */ +typedef struct BZDMA_BLEONLY_DATA_TX_DESC_ENTRY_STATUS_ +{ + BZDMA_BLEONLY_TX_DESC_SEGMENT *pTxSegDesc; /* The pointer of multiple segments */ + BZDMA_BLEONLY_TX_DESC_FRAGMENT *pTxFragDesc; /* The pointer of multiple fragment */ + UINT32 seg_wptr: 4; /* write pointer of segment table */ + UINT32 seg_rptr: 4; /* read pointer of segment table */ + UINT32 free_segs: 5; /* free packet counts of segment table */ + UINT32 rsvd1: 3; /* reserved */ + UINT32 bm_used_segs: 16; /* index bitmap of used segments */ +} BZDMA_BLEONLY_DATA_TX_DESC_ENTRY_STATUS, *PBZDMA_BLEONLY_DATA_TX_DESC_ENTRY_STATUS; + +#ifdef _NEW_BZDMA_FROM_V20_200512_ +#ifdef _BT5_0_LE_ADV_EXT_PA_HW_ +/* The structure of Ble PA Data TX descriptor entry status of BZDMA */ +typedef struct BZDMA_PA_TX_DESC_ENTRY_STATUS_ +{ + BZDMA_BLEPA_TX_DESC_SEGMENT *pTxSegDesc; /* The pointer of multiple segments */ + BZDMA_BLEPA_TX_DESC_FRAGMENT *pTxFragDesc; /* The pointer of multiple fragment */ + UINT32 seg_wptr: 4; /* write pointer of segment table (0~15) */ + UINT32 seg_rptr: 4; /* read pointer of segment table (0~15) */ + UINT32 free_segs: 5; /* free packet counts of segment table (max ?) */ + UINT32 rsvd1: 19; /* reserved */ +} BZDMA_PA_TX_DESC_ENTRY_STATUS, *PBZDMA_PA_TX_DESC_ENTRY_STATUS; +#endif +#endif /* end of _NEW_BZDMA_FROM_V20_200512_ */ + +/* The structure of management of BZDMA */ +typedef struct BZDMA_MANAGE_ +{ + BZDMA_TX_DESC_ENTRY_STATUS TxEntSta[BZDMA_TX_DESC_ENTRY_NUM]; + UINT16 bmFreeTxEnt; /* free Tx command entry bitmap */ + + + BZDMA_BLEONLY_ADV_TX_DESC_ENTRY_STATUS BleAdvTxEntSta; + BZDMA_BLEONLY_DATA_TX_DESC_ENTRY_STATUS BleTxEntSta[BZDMA_LEONLY_TX_MAX_ENTRY_NUM]; + UINT16 bmFreeBleTxEnt; /* free Tx command entry bitmap */ + +#ifdef _BT5_0_LE_ADV_EXT_PA_HW_ + BZDMA_PA_TX_DESC_ENTRY_STATUS BlePATxEntSta[BZDMA_LEONLY_PA_TX_MAX_ENTRY_NUM]; +#endif +} BZDMA_MANAGE, *PBZDMA_MANAGE; + + +extern BZDMA_MANAGE Bzdma_Manager; + +#endif /* __BB_BZDMA_H__ */ + diff --git a/bee/drivers/ppt/driver/common/ll_common.h b/bee/drivers/ppt/driver/common/ll_common.h new file mode 100644 index 00000000..d0bcd47c --- /dev/null +++ b/bee/drivers/ppt/driver/common/ll_common.h @@ -0,0 +1,501 @@ +#ifndef __LL_COMMON_H__ +#define __LL_COMMON_H__ + +//#include "DataType.h" +#include "rtl876x.h" +#include "bzdma.h" + +#define _NEW_BZDMA_FROM_V7_ +#define _NEW_BZDMA_FROM_V8_ +#define _NEW_BZDMA_FROM_V10_FROM_160223_ +#define _NEW_BZDMA_FROM_V10_ +#define _BT5_0_LE_LONG_RANGE_SUPPORT_ +#define _VENDOR_REG_MUST_UPDATE_FROM_RTL_SVN_VER_17316_ +#define _RTL8821A_ +#define _NEW_MODEM_PI_ACCESS_ +#define _NEW_MODEM_PI_ACCESS_BY_VENDOR_REG_ + +#define BT_SOC_VENDOR_BASE_ADDR VENDOR_REG_BASE//0x40006000 +#define BT_SOC_VENDOR_ADDR(offs) (BT_SOC_VENDOR_BASE_ADDR + (offs)) +#define BTMAC_ISR_STATUS_REG_ADDR BT_SOC_VENDOR_ADDR(0x10) + +/* The Base of LE Register */ +#define LE_REG_BASE 0x40051000 +#define PPT_REG_ADDR_BASE (BLUEWIZ_REG_BASE + 0x1c00) + +/* =========================== vendor section ===========================*/ +/* note: vender reg can be access by 1, 2, 4 byte */ +/* note: should be 1-byte aligned, 2-byte aligned, 4-byte aligned */ +#define VENDOR_BASE_ADDRESS 0x40058000 +#define BT_SYS_CTRL_REG 0x00 + +#define VENDOR_REG_ADDR(offset) (VENDOR_BASE_ADDRESS + (offset)) +#define VENDOR_READ(Vendor_offset) \ + ((uint32_t)*((volatile uint32_t*)(VENDOR_BASE_ADDRESS+(Vendor_offset)))) +#define VENDOR_WRITE(Vendor_offset, Value) \ + ((*((volatile uint32_t*)(VENDOR_BASE_ADDRESS + (Vendor_offset)))) = (Value)) +#define VENDOR_U16_READ(Vendor_offset) \ + ((uint16_t)*((volatile uint16_t*)(VENDOR_BASE_ADDRESS+(Vendor_offset)))) +#define VENDOR_U16_WRITE(Vendor_offset, Value) \ + ((*((volatile uint16_t*)(VENDOR_BASE_ADDRESS + (Vendor_offset)))) = (Value)) +#define VENDOR_BYTE_READ(Vendor_offset) \ + (*((volatile uint8_t*)(VENDOR_BASE_ADDRESS+(Vendor_offset)))) +#define VENDOR_BYTE_WRITE(Vendor_offset, Value) \ + ((*((volatile uint8_t*)(VENDOR_BASE_ADDRESS + (Vendor_offset)))) = (Value)) +#define VENDOR_U32_REG_UPDATE(Vendor_offset, Mask, Value) \ + {uint32_t temp; \ + temp = VENDOR_READ(Vendor_offset) & ~(Mask);\ + VENDOR_WRITE(Vendor_offset, (temp | ((Value) & (Mask))));} +#define VENDOR_U16_REG_UPDATE(Vendor_offset, Mask, Value) \ + {uint16_t temp; \ + temp = VENDOR_U16_READ(Vendor_offset) & ~(Mask);\ + VENDOR_U16_WRITE(Vendor_offset, (temp | ((Value) & (Mask))));} +#define VENDOR_U8_REG_UPDATE(Vendor_offset, Mask, Value) \ + {uint8_t temp; \ + temp = VENDOR_BYTE_READ(Vendor_offset) & ~(Mask);\ + VENDOR_BYTE_WRITE(Vendor_offset, (temp | ((Value) & (Mask))));} + +#define RD_32BIT_IO(base, offset) \ + (*(volatile UINT32*)((base) + (offset))) +#define RD_16BIT_IO(base, offset) \ + (*((volatile UINT16*)((base) + (offset)))) +#define RD_8BIT_IO(base, offset) \ + (*((volatile UINT8*)((base) + (offset)))) +#define WR_32BIT_IO(base, offset, val) \ + (*((volatile UINT32*)((base) + (offset))) = (val)) +#define WR_16BIT_IO(base, offset, val) \ + (*((volatile UINT16*)((base) + (offset))) = (val)) +#define WR_8BIT_IO(base, offset, val) \ + (*((volatile UINT8*)((base) + (offset))) = (val)) + +#define RD_U32_BZDMA_REG(offset) HAL_READ32(BZDMA_REG_BASE, offset)//RD_32BIT_IO(BZDMA_REG_BASE, offset) +#define RD_U16_BZDMA_REG(offset) HAL_READ16(BZDMA_REG_BASE, offset)//RD_16BIT_IO(BZDMA_REG_BASE, offset) +#define RD_U8_BZDMA_REG(offset) HAL_READ8(BZDMA_REG_BASE, offset)//RD_8BIT_IO(BZDMA_REG_BASE, offset) +#define WR_U32_BZDMA_REG(offset, val) HAL_WRITE32(BZDMA_REG_BASE, offset, val)//WR_32BIT_IO(BZDMA_REG_BASE, offset, val) +#define WR_U16_BZDMA_REG(offset, val) HAL_WRITE16(BZDMA_REG_BASE, offset, val)//WR_16BIT_IO(BZDMA_REG_BASE, offset, val) +#define WR_U8_BZDMA_REG(offset, val) HAL_WRITE8(BZDMA_REG_BASE, offset, val)//WR_8BIT_IO(BZDMA_REG_BASE, offset, val) + +#ifdef _NEW_BZDMA_FROM_V10_ +#define BZDMA_REG_BLEONLY_ENTRY_SEGMENT_VALID(num) ((((num)&BIT3)?0x464:0x440)+(((num)&0x7) << 2)) +#else +#define BZDMA_REG_BLEONLY_ENTRY_SEGMENT_VALID(num) (0x440 + ((num) << 2)) +#endif + +/* BZ DMA register list */ +#define BZDMA_REG_BASE 0x40058000 +#define BZDMA_REG_ACL_RXFIFO_PTR 0x33C + +#define BZDMA_ACL_RXFIFO_PTR_LEN 11 +#define BZDMA_ACL_RXFIFO_PTR_MASK 0x7FF +#define BZDMA_ACL_RXFIFO_WPTR(reg_value) ((reg_value) & BZDMA_ACL_RXFIFO_PTR_MASK) +#define BZDMA_ACL_RXFIFO_RPTR(reg_value) (((reg_value) >> 16) & BZDMA_ACL_RXFIFO_PTR_MASK) +#define BZDMA_ACL_RXFIFO_GET_LEFT(reg) (((reg.wr_ptr >= reg.rd_ptr ? reg.wr_ptr - reg.rd_ptr : reg.wr_ptr + (1 << BZDMA_ACL_RXFIFO_PTR_LEN) - reg.rd_ptr) + reg.rdbuffer_cnt) << 1) + +/* Structure of Vendor Register 0x33C(BZDMA_REG_ACL_RXFIFO_PTR)*/ +typedef union ACL_RX_FIFO_S_ +{ + uint32_t d32; + struct + { + UINT32 wr_ptr: 11; /* [10:0] write pointer (unit: word)*/ + UINT32 rsvd1: 5; /* [15:11] reserved */ + UINT32 rd_ptr: 11; /* [26:16] read pointer (unit: word) */ + UINT32 rdbuffer_cnt: 2; /* [28:27] read_buffer_cnt (unit: word)(Range:0~2)*/ +UINT32 rxfifo_busy: + 1; /* [29] Rx fifo busy indicator. 1: HW is pushing data into acl rx fifo or sco fifo. */ + UINT32 rsvd2: 2; /* [31:30] reserved 2 */ + }; +} ACL_RX_FIFO_S, *PACL_RX_FIFO_S; + +/* Baseband Control */ +#define INSTRUCTION_REGISTER 0x00 +#define CONNECTOR_REGISTER 0x02 + +#define BB_BASE_ADDR 0x40050000 +#define BB_REG_ADDR(offset) (BB_BASE_ADDR + (offset)) + +/* BASEBAND CONTROLLER OPCODES (Please Sort the OpCode) */ +#define BB_NOP 0X00 +#define BB_INQUIRY 0X01 +#define BB_INQUIRY_SCAN_FIRST_ID 0X02 +#define BB_PAGE 0X03 +#define BB_PAGE_SCAN 0X04 +#define BB_EXECUTE 0X05 +#define BB_HOLD 0X06 +#define BB_SNIFF 0X07 +#define BB_START_BEACON 0X08 +#define BB_UNPARK_REQUEST 0X09 +#define BB_INQUIRY_SCAN_SECOND_ID 0X0A +#define BB_START_SLEEP 0X0B +#ifdef _RTL8821A_ +#define BB_INQUIRY_SCAN_3DD 0X0B +#endif +#define BB_FLUSH 0X0C +#define BB_SEND_PACKET 0X0D +#define BB_MASTER_SLAVE_SWITCH 0X0E +#define BB_LOAD_OFFSET 0X0F + +#define BB_SWITCH_MASTER_PICONET 0X10 +#define BB_PRIORITY_SEND_PACKET 0x12 +#define BB_KILL_SEND_PACKET 0x13 +#ifdef _RTL8821A_ +#define BB_START_SYNC_3DD 0x14 +#define BB_START_BEACON_3DD 0x15 +#endif +#ifdef _SUPPORT_CSB_RECEIVER_ +#define BB_START_SYNC_SCAN_3DD 0x16 +#define BB_START_CSB_SCAN_3DD 0x17 +#endif +#define BB_SWITCH_SLAVE_PICONET 0x18 + +#define BB_SEQN_INIT 0x21 +#define BB_SEND_FLOW_ZERO 0x23 +#define BB_SEND_FLOW_GO 0x24 + +#define BB_START_TPOLL 0x30 +#define BB_STOP_TPOLL 0x31 +#ifdef _NEW_MODEM_PSD_SCAN_ +#define BB_SET_PSD_EN 0x40 +#define BB_CLR_PSD_EN 0x41 +#endif + +#define BB_RESET 0X80 +#define BB_KILL_INQUIRY 0X81 +#define BB_KILL_PAGE 0X82 +#define BB_KILL_HOLD 0X83 +#define BB_KILL_SNIFF 0x84 +#define BB_KILL_SLEEP 0x85 +#define BB_EXIT_BEACON 0x86 +#define BB_KILL_BEACON 0x87 +#define BB_ENTER_SNIFF_TRAN_MODE_DURING_EXIT_SNIFF_MASTER 0x89 +#define BB_ENTER_SNIFF_TRAN_MODE 0x89 +#define BB_EXIT_SNIFF_TRAN_MODE 0x8c +#ifdef _RTL8821A_ +#ifdef _DAPE_TEST_NEW_HW_INSTRUCTION +#define BB_KILL_INQUIRY_SCAN 0X8E +#define BB_KILL_PAGE_SCAN 0X8F +#endif +#define BB_KILL_SYNC_3DD 0x90 +#define BB_KILL_BEACON_3DD 0x91 +#endif +#ifdef _SUPPORT_CSB_RECEIVER_ +#define BB_KILL_SYNC_SCAN_3DD 0x92 +#define BB_KILL_CSB_SCAN_3DD 0x93 +#endif + +extern uint16_t (*rfc_reg_read)(uint8_t addr); +extern void (*rfc_reg_write)(uint8_t addr, uint16_t wdata); +extern void (*rfc_reg_update)(uint8_t addr, uint16_t mask, uint16_t wdata); + +#define RTK_READ_RFC_REG_PI(addr) rfc_reg_read(addr) +#define RTK_WRITE_RFC_REG_PI(addr, wdata) rfc_reg_write(addr, wdata) +#define RTK_UPDATE_RFC_REG_PI(addr, mask, wdata) rfc_reg_update(addr, mask, wdata) + +#ifdef _NEW_MODEM_PI_ACCESS_ +extern uint16_t (*modem_pi_read)(uint8_t, uint8_t); +extern void (*modem_pi_write)(uint8_t, uint8_t, uint16_t); +extern void (*modem_pi_update)(uint8_t, uint8_t, uint16_t, uint16_t); + +#define RTK_READ_MODEM_REG_PI(modem_page, waddr) modem_pi_read(modem_page, waddr) +#define RTK_WRITE_MODEM_REG_PI(modem_page, waddr, value) modem_pi_write(modem_page, waddr, value) +#define RTK_UPDATE_MODEM_REG_PI(modem_page, waddr, bm_mask, value) modem_pi_update(modem_page, waddr, bm_mask, value) +#endif + +#ifdef _NEW_MODEM_PI_ACCESS_ +#ifdef _NEW_MODEM_PI_ACCESS_BY_VENDOR_REG_ +#define REG_BTPHY_FPI_IF 0x354 +#define PI_READ_MODEM_REG 0 +#define PI_WRITE_MODEM_REG 1 +/* Read wiki page for more information about modem PI access: * + * https://wiki.realtek.com/pages/viewpage.action?pageId=20234492 */ +typedef union +{ + struct + { + UINT32 pi_wrdata : 16; //[15: 0] rw + UINT32 pi_modem_addr : 6; //[21:16] rw + UINT32 pi_modem_page : 6; //[27:22] rw + UINT32 pi_wr : 1; //[28] w, 0: read modem, 1: write modem + UINT32 bt_phy_pi_en : 1; //[29] r + UINT32 pi_rising_edge_time: 2; //[31:30] rw, 4*(1 + pi_rising_edge_time)T must >= 100ns + }; + UINT32 u32; +} MODEM_PI_VENDOR_REG_S; +#else +extern UINT8 g_efuse_modem_pi_enable; +#endif +extern UINT8 g_modem_init_completed; +#define MODEM_PI_PAGE_0 0 +#define MODEM_PI_PAGE_1 1 +#define MODEM_PI_PAGE_2 2 +#define MODEM_PI_PAGE_3 3 +#define MODEM_PI_PAGE_4 4 +#define MODEM_PI_PAGE_5 5 +#define MODEM_PI_PAGE_6 6 +#define MODEM_PI_PAGE_7 7 +#define MODEM_PI_PAGE_NEW_AGC_TAB0 8 +#define MODEM_PI_PAGE_NEW_AGC_TAB1 9 +#define MODEM_PI_PAGE_NEW_AGC_TAB2 10 +#define MODEM_PI_PAGE_NEW_AGC_TAB3 11 +#define MODEM_PI_PAGE_OLD_AGC_TAB0 12 +#define MODEM_PI_PAGE_W_ADDR0_START MODEM_PI_PAGE_NEW_AGC_TAB0 +#define MODEM_PI_PAGE_W_ADDR0_END MODEM_PI_PAGE_OLD_AGC_TAB0 +#endif +#define TRANS_MODEM_REG(x) (x) /* this is used to translate byte address to word address*/ + +typedef union BTMAC_ISR_STATUS_REG_ +{ + struct + { + __I uint32_t timer_intr1_intr0_r: 1; + __I uint32_t bluewiz_intr_r: 1; + __I uint32_t RESERVED_1: 1; + __I uint32_t bluewiz_dma_intr_r: 1; + __I uint32_t pro_intr_r: 1; + __I uint32_t RESERVED_0: 27; + }; + UINT32 d32; +} BTMAC_ISR_STATUS_REG; + +///* The structure of one fragment of TX Descriptor for BLE only */ +//typedef union BZDMA_BLEONLY_TX_DESC_FRAGMENT_ +//{ +// struct +// { +// UINT32 start_addr: 16; /* bit[15:0], the start address of buffer SRAM */ +// UINT32 len: 11; /* bit[26:16], the copied length*/ +// UINT32 rsvd: 4; /* bit[30:27], reserved */ +// UINT32 isLast: 1; /* bit[31], is last segment */ +// }; +//#ifdef _NEW_BZDMA_FROM_V10_FROM_160223_ +// struct +// { +// UINT32 start_addr_ex: 18; /* bit[17:0], the start address of buffer SRAM */ +// UINT32 len_ex: 11; /* bit[28:18], the copied length*/ +// UINT32 rsvd_ex: 2; /* bit[30:29], reserved */ +// UINT32 isLast_ex: 1; /* bit[31], is last segment */ +// }; +//#endif +// UINT32 DWord; +//} BZDMA_BLEONLY_TX_DESC_FRAGMENT, *PBZDMA_BLEONLY_TX_DESC_FRAGMENT; + +/* The structure of one segment of RX Descriptor (only use for FW) */ +typedef union BZDMA_RX_DESC_SEGMENT_ +{ + struct + { +#ifdef _NEW_BZDMA_FROM_V10_FROM_160223_ + UINT32 addr: 18; /* the address of destination address */ +#else + UINT32 addr: 16; /* the address of destination address */ +#endif + UINT32 len: 11; /* the copied byte length */ + UINT32 flush: 1; /* flush data from rx fifo */ +#ifdef _NEW_BZDMA_FROM_V10_FROM_160223_ + UINT32 rsvd: 2; /* reserved */ +#else + UINT32 rsvd: 4; /* reserved */ +#endif + }; + UINT32 DWord; +} BZDMA_RX_DESC_SEGMENT, *PBZDMA_RX_DESC_SEGMENT; + +/*====================================================================*/ +/* Table 2.3 LLID Defination */ +/*====================================================================*/ +enum LL_LLID_SET +{ + LL_LLID_RSVD = 0, + LL_LLID_DATA_PDU_CONT = 1, + LL_LLID_EMPTY_PDU = 1, + LL_LLID_DATA_PDU_START = 2, + LL_LLID_CTRL_PDU = 3 +}; + +/* The HW Definition of Tx/Rx PID */ +enum BZDMA_PID_ +{ + BZDMA_TX_PID_ACL = 0, +#ifdef _SUPPORT_CSB_TRANSMITTER_ + BZDMA_TX_PID_CSB = 1, +#endif + BZDMA_TX_PID_BCST = 2, + BZDMA_TX_PID_SCO = 3, +#ifdef _NEW_BZDMA_FROM_V7_ + BZDMA_TX_PID_NEW_SCO = 4, +#endif + BZDMA_TX_PID_TOTAL = 3, + BZDMA_RX_PID_ACL = 0, + BZDMA_RX_PID_SCO = 1, + BZDMA_RX_PID_TOTAL = (BZDMA_RX_PID_SCO + 1), +}; + +/* + * bit + * 0:1: System clock: + * 00b: 5MHz; 01b:10MHz; 10b:20MHz; 11b:40MHz + * 2: Bluewiz reset: + * defaut: 0,reset state + * 1: disable reset + * 3:4: + * 5: Modem reset: + * defaut: 0,reset state + * 1: disable reset + * 6:7: + * 8: The extern clock gat of bluewiz: + * defaut: 0,gating state + * 1: disable gating + * 9: CPU clock 40MHz switch: + * defaut: 0, 32K mode + * 1: enable 40MHz mode + * 10: Exist bluewiz seep sleep mode: + * defaut: 0 + * 1: force leaving deep sleep mode + * 11:31: +**/ +typedef union BT_SYS_CTRL_REG_S +{ + UINT32 d32; + struct + { + UINT32 sys_clk : 2; //bit0~1 + UINT32 bluewiz_rst : 1; //bit2 + UINT32 reserved_3_4 : 2; //bit3~4 + UINT32 modem_rst : 1; //bit5 + UINT32 pon_rst_n : 1; //bit6 + UINT32 pro_rst_n : 1; //bit7 + UINT32 external_bluewiz_clk_gat : 1; //bit8 + UINT32 cpu_40mhz_en : 1; //bit9 + UINT32 exist_deep_sleep_mode : 1; //bit10 +#ifdef _VENDOR_REG_MUST_UPDATE_FROM_RTL_SVN_VER_17316_ + UINT32 reserved_11_15 : 5; //bit 11~15 + UINT32 rfc_ret_rst_n : 1; //bit16, RFC retention register reset + UINT32 rfc_rst_n : 1; //bit17, RFC off domain register reset + UINT32 bb_ret_rst_n : 1; //bit18, modem retention FF reset + UINT32 modem_clk_force_on : 1; //bit19, force modem clock always on + UINT32 dp_bb_ret_rst_n : 1; //bit20 + UINT32 reserved_21_24 : 5; //bit21~24 + UINT32 zb_ret_rst_n : 1; //bit25 + UINT32 pro_clk_en : 1; //bit26 + UINT32 rfc_clk_force_on : 1; //bit27 + UINT32 bt_le_clk_en : 1; //bit28, le clock enable + UINT32 bt_br_edr_clk_en : 1; //bit29, BR EDR clock enable + UINT32 force_adda_iso_off : 1; //bit30, force ADDA isolation release. + UINT32 force_adda_pwron : 1; //bit31, force ADDA LDO on +#else + UINT32 reserved_11_31 : 21; //bit 11~31 +#endif + } b; +} BT_SYS_CTRL_REG_S_TYPE; + +typedef union MODEM_PSD_REPORT_ELEMENT_S +{ + UINT32 d32_array[4]; + struct // RTL8703B, RTL8822B, RTL8821B-MP + { + UINT32 psd_avg_dc: 16; //[15:0] + UINT32 psd_avg_pos: 16; ///[31:16] + UINT32 psd_avg_neg: 16; //[47:32] + UINT32 mp_gain_idx: 6; //[53:48] + UINT32 gnt_bt_hold: 1; //[54] + UINT32 gnt_bt_final: 1; //[55] + + UINT32 psd_u28_scale: 3; //[58:56] + UINT32 gnt_wl_hold: 1; //[59] + UINT32 gnt_wl_final: 1; //[60] + UINT32 wifi_txon_hold: 1; //[61] + UINT32 wifi_txon_final: 1; //[62] + UINT32 rsvd1: 1; //[63] + + UINT32 psd_avg_dfir_lsb: 16; //[79:64] + UINT32 psd_avg_dfir_msb: 4; //[83:80] + UINT32 psd_clip_ratio_start: 6; //[89:84] + UINT32 psd_clip_ratio_end: 6; //[95:90] + + UINT32 agc_ste: 4; //[99:96] + UINT32 lna_idx_use: 3; //[102:100] + UINT32 bpf_mode_use: 1; //[103] + UINT32 gain_idx_use: 5; //[108:104] + UINT32 rf_pd_en_use: 1; //[109] + UINT32 signature_bit: 2; //[111:110] //default 2'b0 + UINT32 rsvd3: 16; //[127:112] + }; +} MODEM_PSD_REPORT_ELEMENT_S_TYPE; + +typedef UINT8(*PF_ROM_CODE_PATCH_FUNC)(void *buf, ...); +extern PF_ROM_CODE_PATCH_FUNC rcp_BTMAC_Handler; +extern PF_ROM_CODE_PATCH_FUNC rcp_BB_handle_psd_end_intr_func; + +extern UINT8 bzdma_supported_le_max_seg_num; +extern MODEM_PSD_REPORT_ELEMENT_S_TYPE *g_modem_psd_report_array; +extern UINT16 g_modem_psd_report_entry_num; +extern uint16_t g_efuse_modem_psd_setting_1; +#define PSD_CHANN_NUM 128 +#define PSD_TIMEOUT_DEFAULT 0x3ff +#define PPT_RF_MODE 0 +extern int8_t (*calculate_log_from_rssi)(uint16_t, uint8_t, uint8_t); + +#define RD_REG_MMIO(type, addr) \ + (*((volatile type*) (addr))) +#define WR_REG_MMIO(type, addr, val) \ + (*((volatile type*) (addr)) = (val)) + +__STATIC_INLINE BTMAC_ISR_STATUS_REG btmac_isr_status_reg_read(void) +{ + return RD_REG_MMIO(BTMAC_ISR_STATUS_REG, BTMAC_ISR_STATUS_REG_ADDR); +} + +#if defined (_NEW_BZDMA_FROM_V10_) || defined (_BT5_0_LE_LONG_RANGE_SUPPORT_) +extern UINT8(*bzdma_send_packet_to_ble_data_ring_fifo)(UINT8 conn_entry, UINT8 llid, + BZDMA_BLEONLY_TX_DESC_FRAGMENT *pfrag, UINT8 Nfrag, + UINT8 codeind); +#else +UINT8 bzdma_send_packet_to_ble_data_ring_fifo(UINT8 conn_entry, UINT8 llid, + BZDMA_BLEONLY_TX_DESC_FRAGMENT *pfrag, UINT8 Nfrag); + +#endif +UINT8 bzdma_update_fw_rptr_of_ble_data_ring_fifo(UINT8 conn_entry, + UINT8 free_cnts, UINT8 check_cam); + + +void bzdma_send_burst_rxcmd_and_wait_complete(BZDMA_RX_DESC_SEGMENT *pRxDesc, + UINT8 cmd_count, UINT8 fifo_type, UINT8 sco_ch_id, UINT8 wait_complete); +void bzdma_flush_ble_data_ring_fifo(UINT8 conn_entry); +void bzdma_reset_ble_data_ring_fifo(UINT8 conn_entry); +void bzdma_ble_set_segment_valid_bitmap(UINT8 entry, UINT16 bitmap); +void bzdma_generic_ble_seg_cmd_clear(UINT8 entry, BOOLEAN clear_all); + +/* Prototypes of Baseband Driver Functions exported to other modules */ +UINT16 BB_read_baseband_register(UINT16 bb_reg_offset); +void BB_write_baseband_register(UINT16 bb_reg_offset, UINT16 val); +uint16_t BB_read_native_counter(void); +uint32_t BB_read_native_clock(void); + +#ifdef _NEW_MODEM_PI_ACCESS_ +UCHAR lc_read_modem_pi_page(void); +void lc_write_modem_pi_page(UCHAR modem_page); +extern UINT32(*rtk_read_modem_radio_reg_pi)(UCHAR modem_page, UCHAR addr, UCHAR type); +extern void (*rtk_write_modem_radio_reg_pi)(UCHAR modem_page, UCHAR addr, UCHAR type, UINT16 val); +#endif + +void phy_init(UINT8 dlps_flow); +extern void (*ll_hw_init)(UINT8); + +extern uint32_t (*platform_rtc_get_counter)(void); + +extern uint32_t (*lowerstack_SystemCall)(uint32_t, uint32_t, uint32_t, + uint32_t); + +#ifndef COUNT_ARG +#define ARG_T(t) t +#define ARG_N(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20,a21,N,...) N +#define ARG_N_HELPER(...) ARG_T(ARG_N(__VA_ARGS__)) +#define COUNT_ARG1(...) ARG_N_HELPER(__VA_ARGS__,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0) +#define COUNT_ARG(...) ((COUNT_ARG1(1, ##__VA_ARGS__) - 1)%21) +#endif + +#ifndef UNUSED +#define UNUSED(expr) do { (void)(expr); } while (0) +#endif + +#endif diff --git a/bee/drivers/ppt/driver/common/ppt_driver.c b/bee/drivers/ppt/driver/common/ppt_driver.c new file mode 100644 index 00000000..c8cc2a33 --- /dev/null +++ b/bee/drivers/ppt/driver/common/ppt_driver.c @@ -0,0 +1,1877 @@ +/** +***************************************************************************************** +* Copyright(c) 2020, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file ppt_driver.c + * @brief Source file for 2.4G module common driver. + * @details + * @author bill + * @date 2022-09-21 + * @version v0.1 + * ************************************************************************************* + */ + +#include +#include +#include +//#include "trace.h" +#include "rtl876x.h" +#include "rtl_pinmux.h" +#include "utils.h" +#include "os_sync.h" +#include "os_mem.h" +#include "ppt_driver.h" +#include "ppt_pm.h" +#include "ppt_pf.h" + +LOG_MODULE_REGISTER(ppt_driver, PPT_DRIVER_LOG_LEVEL); + +#define PPT_LOG_METHOD 0 //!< 0: no log, 1: buffer log, 2: direct log +#define PPT_REG_ACCESS_TIM_DBG (TIME_DEBUG && 0) +#define PPT_WR_WI_RD_BACK 0 + +#define PPT_IS_ASIC 1 +#define PATCH_BTMAC_ISR 1 + +void bt_retention_domain_reset(void); + +bool ppt_enable = false; +volatile bool ppt_dlps_mac_idle = true; +bool (*ppt_dlps_mac_check_cb)(uint32_t *wakeup_time_diff); +void (*ppt_dlps_mac_enter_cb)(void); +void (*ppt_dlps_mac_exit_cb)(void); +void (*ppt_dlps_pf_enter_cb)(void); +void (*ppt_dlps_pf_exit_cb)(void); +bool ppt_tx_fixed_rptr[PPT_ENTRY_NUM]; + +struct +{ + uint32_t modem_acc[PPT_ENTRY_RX_NUM]; + uint8_t modem_acc_enable; + uint8_t acc_byte3_flag; //!< 0: not set, 1: set for 1M, 2: set for 2M + bool acc_similar_flag; + bool mod_index_2m_flag; +} ppt_fw_ret; + +#if PATCH_BTMAC_ISR +void *btmac_handler_temp; +#endif +void *bb_psd_handler_temp; + +static void (*ppt_isr_handler)(void); +static void (*ppt_psd_isr_handler)(void); + +#if TIME_DEBUG +uint8_t test_pin[] = {TEST_PIN}; +uint32_t gpio_test_pin[sizeof(test_pin)]; +bool level_test_pin[sizeof(test_pin)]; +#endif + +static PPT_DAT_SECTION ppt_reg_field_t ppt_lut_prefix[PPT_ENTRY_RX_NUM] = +{ + {PRO_PREFIX0_1, 0}, {PRO_PREFIX0_1, 8}, + {PRO_PREFIX2_3, 0}, {PRO_PREFIX2_3, 8}, + {PRO_PREFIX4_5, 0}, {PRO_PREFIX4_5, 8}, + {PRO_PREFIX6_7, 0}, {PRO_TX_ADDRESS_UPPER, 8} +}; + +static PPT_DAT_SECTION uint16_t ppt_lut_tx_addr[PPT_ENTRY_RX_NUM] = +{ + PRO_TX_ADDRESS_LOWER, PRO_TX_ADDRESS1_LOWER, + PRO_TX_ADDRESS2_LOWER, PRO_TX_ADDRESS3_LOWER, + PRO_TX_ADDRESS4_LOWER, PRO_TX_ADDRESS5_LOWER, + PRO_TX_ADDRESS6_LOWER, PRO_TX_ADDRESS7_LOWER, +}; + +PPT_API_SECTION uint8_t ppt_swap_bits8(uint8_t inp) +{ + uint8_t retval = 0; + for (uint8_t i = 0; i < 8; i++) + { + retval |= ((inp >> i) & 0x01) << (7 - i); + } + return retval; +} + +PPT_API_SECTION uint16_t ppt_swap_bits16(uint16_t inp) +{ + uint16_t retval = 0; + for (uint8_t i = 0; i < 16; i++) + { + retval |= ((inp >> i) & 0x01) << (15 - i); + } + return retval; +} + +PPT_API_SECTION uint32_t ppt_swap_bits24(uint32_t inp) +{ + uint32_t retval = 0; + for (uint8_t i = 0; i < 24; i++) + { + retval |= ((inp >> i) & 0x01) << (23 - i); + } + return retval; +} + +PPT_API_SECTION uint32_t ppt_swap_bits32(uint32_t inp) +{ + uint32_t retval = 0; + for (uint8_t i = 0; i < 32; i++) + { + retval |= ((inp >> i) & 0x01) << (31 - i); + } + return retval; +} + +bool btmac_pm_check_inactive(void); +bool btmac_pm_check_active(void); +void btmac_pm_initiate_wakeup(void); +bool ppt_dlps_check_active(void); +bool ppt_dlps_check_inactive(void); +void ppt_dlps_initiate_wakeup(void); + +PPT_API_SECTION uint16_t ppt_read_reg_dlps(uint16_t offset) +{ + uint16_t reg; + + /* wake up btmac */ + if (btmac_pm_check_inactive()) + { + btmac_pm_initiate_wakeup(); + } + /* wake up ppt */ + if (ppt_dlps_check_inactive()) + { + ppt_dlps_initiate_wakeup(); + } + +#if PPT_REG_ACCESS_TIM_DBG + time_debug_level_high(TIME_DEBUG_CHAN_THREAD); +#endif + reg = HAL_READ16(PPT_REG_ADDR_BASE, offset); +#if PPT_REG_ACCESS_TIM_DBG + time_debug_level_low(TIME_DEBUG_CHAN_THREAD); +#endif + +#if PPT_LOG_METHOD == 2 + DBG_DIRECT("PPTR %04x=%04x", offset, reg); +#elif PPT_LOG_METHOD == 1 + APP_PRINT_INFO2("ppt_read_reg: offset 0x%04x, value 0x%04x", offset, reg); +#endif + return reg; +} + +PPT_API_SECTION uint16_t ppt_read_reg_active(uint16_t offset) +{ + return HAL_READ16(PPT_REG_ADDR_BASE, offset); +} + +PPT_API_SECTION void ppt_write_reg_dlps(uint16_t offset, uint16_t data) +{ + /* wake up btmac */ + if (btmac_pm_check_inactive()) + { + btmac_pm_initiate_wakeup(); + } + /* wake up ppt */ + if (ppt_dlps_check_inactive()) + { + ppt_dlps_initiate_wakeup(); + } + +#if PPT_REG_ACCESS_TIM_DBG + time_debug_level_high(TIME_DEBUG_CHAN_THREAD); +#endif + HAL_WRITE16(PPT_REG_ADDR_BASE, offset, data); +#if PPT_REG_ACCESS_TIM_DBG + time_debug_level_low(TIME_DEBUG_CHAN_THREAD); +#endif + +#if PPT_LOG_METHOD + uint16_t read_data = 0; +#if PPT_WR_WI_RD_BACK + read_data = ppt_read_reg(offset); +#endif +#endif +#if PPT_LOG_METHOD == 2 + DBG_DIRECT("PPTW %04x=%04x(r%04x)", offset, data, read_data); +#elif PPT_LOG_METHOD == 1 + APP_PRINT_INFO3("ppt_write_reg: offset 0x%04x, value 0x%04x(r%04x)", offset, data, read_data); +#endif +} + +PPT_API_SECTION void ppt_write_reg_active(uint16_t offset, uint16_t data) +{ + HAL_WRITE16(PPT_REG_ADDR_BASE, offset, data); +} + +uint16_t ppt_read_reg_def(uint16_t offset) +{ + ppt_read_reg = ppt_read_reg_active; + ppt_write_reg = ppt_write_reg_active; + return ppt_read_reg_dlps(offset); +} + +void ppt_write_reg_def(uint16_t offset, uint16_t data) +{ + ppt_read_reg = ppt_read_reg_active; + ppt_write_reg = ppt_write_reg_active; + ppt_write_reg_dlps(offset, data); +} + +uint16_t (*ppt_read_reg)(uint16_t offset) = ppt_read_reg_def; +void (*ppt_write_reg)(uint16_t offset, uint16_t data) = ppt_write_reg_def; + +PPT_API_SECTION void ppt_reset_core_domain(bool ppt_mode) +{ + { + /* proprietary reset */ + BT_SYS_CTRL_REG_S_TYPE bt_sys_reg; + bt_sys_reg.d32 = VENDOR_READ(BT_SYS_CTRL_REG); + bt_sys_reg.b.pro_rst_n = 0; + VENDOR_WRITE(BT_SYS_CTRL_REG, bt_sys_reg.d32); + + bt_sys_reg.b.pro_rst_n = 1; + VENDOR_WRITE(BT_SYS_CTRL_REG, bt_sys_reg.d32); + } + + { + /* clock enable */ + BT_SYS_CTRL_REG_S_TYPE bt_sys_reg; + bt_sys_reg.d32 = VENDOR_READ(BT_SYS_CTRL_REG); + bt_sys_reg.b.pro_clk_en = ppt_mode; + VENDOR_WRITE(BT_SYS_CTRL_REG, bt_sys_reg.d32); + platform_delay_us(2); + } + ppt_enable = ppt_mode; +} + +PPT_API_SECTION void ppt_lock(uint8_t entry, bool lock) +{ + assert_param(entry < PPT_ENTRY_NUM); + + if (entry <= 1) + { + PRO_TX_CONTROL_TYPE tx_ctrl = {.d16 = RD_PPT_REG(PRO_TX_CONTROL)}; + if (entry == 0) + { + tx_ctrl.lock0 = lock; + } + else if (entry == 1) + { + tx_ctrl.lock1 = lock; + } + WR_PPT_REG(PRO_TX_CONTROL, tx_ctrl.d16); + } + else if (entry == 2) + { + PRO_GPIO_CONTROL_TYPE gpio_ctrl = {.d16 = RD_PPT_REG(PRO_GPIO_CONTROL)}; + gpio_ctrl.lock2 = lock; + WR_PPT_REG(PRO_GPIO_CONTROL, gpio_ctrl.d16); + } + else + { + uint16_t offset = PRO_WHITE_FIELD_LENGTH_0 + ((entry - PPT_ENTRY_NUM_ORI) << 1); + PRO_WHITE_FIELD_LENGTH_0_TYPE len0 = {.d16 = RD_PPT_REG(offset)}; + len0.lock3 = lock; + WR_PPT_REG(offset, len0.d16); + } +} + +void ppt_set_auto_no_tx(uint8_t entry, bool enable) +{ + assert_param(entry < PPT_ENTRY_NUM); + uint16_t pro_reg; + if (entry == 0) + { + pro_reg = RD_PPT_REG(PRO_TX_CONTROL); + ((PRO_TX_CONTROL_TYPE *)(&pro_reg))->auto_no_tx_option0 = enable; + WR_PPT_REG(PRO_TX_CONTROL, pro_reg); + } + else if (entry == 1) + { + pro_reg = RD_PPT_REG(PRO_TRX_CONTROL); + ((PRO_TRX_CONTROL_TYPE *)(&pro_reg))->auto_no_tx_option1 = enable; + WR_PPT_REG(PRO_TRX_CONTROL, pro_reg); + } + else if (entry == 2) + { + pro_reg = RD_PPT_REG(PRO_GPIO_CONTROL); + ((PRO_GPIO_CONTROL_TYPE *)(&pro_reg))->auto_no_tx_option2 = enable; + WR_PPT_REG(PRO_GPIO_CONTROL, pro_reg); + } + else + { + uint16_t offset = PRO_WHITE_FIELD_LENGTH_0 + ((entry - PPT_ENTRY_NUM_ORI) << 1); + PRO_WHITE_FIELD_LENGTH_0_TYPE len0 = {.d16 = RD_PPT_REG(offset)}; + len0.auto_no_tx_option3 = enable; + WR_PPT_REG(offset, len0.d16); + } +} + +void ppt_clear_hw_no_tx(uint8_t entry) +{ + assert_param(entry < PPT_ENTRY_NUM); + if (entry <= 1) + { + PRO_TX_CONTROL_TYPE tx_ctrl = {.d16 = RD_PPT_REG(PRO_TX_CONTROL)}; + if (entry == 0) + { + tx_ctrl.clear_hw_no_tx0 = 1; + } + else if (entry == 1) + { + tx_ctrl.clear_hw_no_tx1 = 1; + } + WR_PPT_REG(PRO_TX_CONTROL, tx_ctrl.d16); + } + else if (entry == 2) + { + PRO_GPIO_CONTROL_TYPE gpio_ctrl = {.d16 = RD_PPT_REG(PRO_GPIO_CONTROL)}; + gpio_ctrl.clear_hw_no_tx2 = 1; + WR_PPT_REG(PRO_GPIO_CONTROL, gpio_ctrl.d16); + } + else + { + uint16_t offset = PRO_WHITE_FIELD_LENGTH_0 + ((entry - PPT_ENTRY_NUM_ORI) << 1); + PRO_WHITE_FIELD_LENGTH_0_TYPE len0 = {.d16 = RD_PPT_REG(offset)}; + len0.clear_hw_no_tx3 = 1; + WR_PPT_REG(offset, len0.d16); + } +} + +void ppt_set_auto_ack(uint8_t entry, bool enable) +{ + assert_param(entry < PPT_ENTRY_NUM); + if (entry == 0) + { + WR_PPT_REG_FIELD(PRO_FIELD_LENGTH, auto_no_rdptr_option0, enable); + } + else if (entry == 1) + { + WR_PPT_REG_FIELD(PRO_TRX_CONTROL, auto_no_rdptr_option1, enable); + } + else if (entry == 2) + { + WR_PPT_REG_FIELD(PRO_GPIO_CONTROL, auto_no_rdptr_option2, enable); + } + else + { + uint16_t offset = PRO_FIELD_LENGTH3 + ((entry - PPT_ENTRY_NUM_ORI) << 1); + PRO_FIELD_LENGTH3_TYPE len3 = {.d16 = RD_PPT_REG(offset)}; + len3.auto_no_rdptr_option3 = enable; + WR_PPT_REG(offset, len3.d16); + } +} + +PPT_API_SECTION uint8_t ppt_trigger_fw_ack_lock(uint8_t entry, bool lock) +{ + assert_param(entry < PPT_ENTRY_NUM); + if (ppt_tx_fixed_rptr[entry]) + { + ppt_tx_fixed_rptr[entry] = false; + if (entry < PPT_ENTRY_NUM_ORI) + { + PRO_PACKET_RELATED_CONTROL0_TYPE pkt_related_ctrl = {.d16 = RD_PPT_REG(PRO_ENTRY_FIELD_BASE(entry) + PRO_PACKET_RELATED_CONTROL0)}; + pkt_related_ctrl.auto_add_rptr_option0 = 0; + WR_PPT_REG(PRO_ENTRY_FIELD_BASE(entry) + PRO_PACKET_RELATED_CONTROL0, + pkt_related_ctrl.d16); + } + else + { + uint16_t offset = ((entry - PPT_ENTRY_NUM_ORI) << 1) + PRO_FIELD_LENGTH3; + PRO_FIELD_LENGTH3_TYPE field_len = {.d16 = RD_PPT_REG(offset)}; + field_len.auto_add_rptr_option3 = 0; + WR_PPT_REG(offset, field_len.d16); + } + } + /* Fw trigger rptr ++ */ +#if PPT_LOG_METHOD == 1 + UINT32 cur_bm = RD_U32_BZDMA_REG(BZDMA_REG_BLEONLY_ENTRY_SEGMENT_VALID(entry)); +#endif + if (lock) + { + ppt_lock(entry, true); + } + if (entry < PPT_ENTRY_NUM_ORI) + { + PRO_PACKET_RELATED_CONTROL0_TYPE pkt_related_ctrl = {.d16 = RD_PPT_REG(PRO_ENTRY_FIELD_BASE(entry) + PRO_PACKET_RELATED_CONTROL0)}; + pkt_related_ctrl.fw_ack0 = TRUE; // w1 ack, hw auto pull down in next T + WR_PPT_REG(PRO_ENTRY_FIELD_BASE(entry) + PRO_PACKET_RELATED_CONTROL0, pkt_related_ctrl.d16); + } + else + { + uint16_t offset = ((entry - PPT_ENTRY_NUM_ORI) << 1) + PRO_WHITE_FIELD_LENGTH_0; + PRO_WHITE_FIELD_LENGTH_0_TYPE white_field_len = {.d16 = RD_PPT_REG(offset)}; + white_field_len.fw_ack3 = 0; + WR_PPT_REG(offset, white_field_len.d16); + } + //bzdma_update_fw_rptr_of_ble_data_ring_fifo(entry, 1, FALSE); + uint8_t rd_ptr = Bzdma_Manager.BleTxEntSta[entry].seg_rptr; + rd_ptr = (rd_ptr + 1) & (bzdma_supported_le_max_seg_num - 1); + Bzdma_Manager.BleTxEntSta[entry].seg_rptr = rd_ptr; + Bzdma_Manager.BleTxEntSta[entry].free_segs += 1; + if (lock) + { + ppt_lock(entry, false); + } +#if PPT_LOG_METHOD == 1 + APP_PRINT_INFO4("ppt_trigger_fw_ack: BZDMA bitmap 0x%x -> 0x%x, entry %d, rd ptr %d", cur_bm, + RD_U32_BZDMA_REG(BZDMA_REG_BLEONLY_ENTRY_SEGMENT_VALID(entry)), entry, + rd_ptr); +#endif + return rd_ptr; +} + +PPT_API_SECTION uint8_t ppt_force_fw_ack(uint8_t entry) +{ + assert_param(entry < PPT_ENTRY_NUM); + uint8_t rd_ptr = Bzdma_Manager.BleTxEntSta[entry].seg_rptr; + uint32_t cur_bm = RD_U32_BZDMA_REG(BZDMA_REG_BLEONLY_ENTRY_SEGMENT_VALID(entry)); + uint32_t cur_bm_n = cur_bm & (~(1 << rd_ptr)); + WR_U32_BZDMA_REG(BZDMA_REG_BLEONLY_ENTRY_SEGMENT_VALID(entry), cur_bm_n); + + rd_ptr = (rd_ptr + 1) & (bzdma_supported_le_max_seg_num - 1); + if (entry < PPT_ENTRY_NUM_ORI) + { + PRO_PACKET_RELATED_CONTROL0_TYPE pkt_related_ctrl = {.d16 = RD_PPT_REG(PRO_ENTRY_FIELD_BASE(entry) + PRO_PACKET_RELATED_CONTROL0)}; + pkt_related_ctrl.auto_add_rptr_option0 = 1; + pkt_related_ctrl.fw_rd_ptr0 = rd_ptr; + WR_PPT_REG(PRO_ENTRY_FIELD_BASE(entry) + PRO_PACKET_RELATED_CONTROL0, pkt_related_ctrl.d16); + } + else + { + uint16_t offset = ((entry - PPT_ENTRY_NUM_ORI) << 1) + PRO_FIELD_LENGTH3; + PRO_FIELD_LENGTH3_TYPE field_len = {.d16 = RD_PPT_REG(offset)}; + field_len.auto_add_rptr_option3 = 1; + field_len.fw_rd_ptr3 = rd_ptr; + WR_PPT_REG(offset, field_len.d16); + } + + Bzdma_Manager.BleTxEntSta[entry].seg_rptr = rd_ptr; + Bzdma_Manager.BleTxEntSta[entry].free_segs += 1; + + ppt_tx_fixed_rptr[entry] = true; +#if PPT_LOG_METHOD == 1 + APP_PRINT_INFO4("ppt_force_fw_ack: BZDMA bitmap 0x%x -> 0x%x, entry %d, rd ptr %d", cur_bm, + RD_U32_BZDMA_REG(BZDMA_REG_BLEONLY_ENTRY_SEGMENT_VALID(entry)), entry, + rd_ptr); +#endif + //pkt_related_ctrl.auto_add_rptr_option0 = 0; + //WR_PPT_REG(PRO_PACKET_RELATED_CONTROL0, pkt_related_ctrl.d16); + //bzdma_update_fw_rptr_of_ble_data_ring_fifo(entry, 1, FALSE); + return rd_ptr; +} + +void ppt_flush_rx_fifo(void) +{ + BT_SYS_CTRL_REG_S_TYPE bt_sys_reg; + bt_sys_reg.d32 = VENDOR_READ(BT_SYS_CTRL_REG); + bt_sys_reg.b.bt_br_edr_clk_en = 1; + VENDOR_WRITE(BT_SYS_CTRL_REG, bt_sys_reg.d32); + BB_write_baseband_register(INSTRUCTION_REGISTER, BB_FLUSH); + bt_sys_reg.b.bt_br_edr_clk_en = 0; + VENDOR_WRITE(BT_SYS_CTRL_REG, bt_sys_reg.d32); +} + +void ppt_flush_trx_int(void) +{ + while (1) + { + PRO_MISR_TYPE reg_misr; + reg_misr.d16 = RD_PPT_REG(PRO_MISR); + if (reg_misr.tx_int) + { + PRO_TX_LENGTH_TYPE length = {.d16 = RD_PPT_REG(PRO_TX_LENGTH)}; // Read 0x6a to pop stack + } + else if (reg_misr.rx_int) + { + PRO_RX_HS_UPPER_TYPE rx_hs_upper = {.d16 = RD_PPT_REG(PRO_RX_HS_UPPER)}; //read 0x62 to pop rx stack + } + else + { + break; + } + } +} + +void ppt_reset_trx_pkt_num(void) +{ + PRO_CBK_CTRL_TYPE cbk_ctrl = {.d16 = RD_PPT_REG(PRO_CBK_CTRL)}; + cbk_ctrl.reset_rx_pktnum0 = 1; + cbk_ctrl.reset_rx_pktnum1 = 1; + cbk_ctrl.reset_tx_pktnum0 = 1; + cbk_ctrl.reset_tx_pktnum1 = 1; + WR_PPT_REG(PRO_CBK_CTRL, cbk_ctrl.d16); + cbk_ctrl.reset_rx_pktnum0 = 0; + cbk_ctrl.reset_rx_pktnum1 = 0; + cbk_ctrl.reset_tx_pktnum0 = 0; + cbk_ctrl.reset_tx_pktnum1 = 0; + WR_PPT_REG(PRO_CBK_CTRL, cbk_ctrl.d16); + + PRO_WHITE_FIELD_LENGTH_0_TYPE white0 = {.d16 = RD_PPT_REG(PRO_WHITE_FIELD_LENGTH_0)}; + white0.reset_rx_pktnum2 = 1; + WR_PPT_REG(PRO_WHITE_FIELD_LENGTH_0, white0.d16); + white0.reset_rx_pktnum2 = 0; + WR_PPT_REG(PRO_WHITE_FIELD_LENGTH_0, white0.d16); + + for (uint8_t entry = PPT_ENTRY_NUM_ORI; entry < PPT_ENTRY_NUM; entry++) + { + uint8_t offset = PRO_WHITE_FIELD_LENGTH_0 + ((entry - PPT_ENTRY_NUM_ORI) << 1); + PRO_WHITE_FIELD_LENGTH_0_TYPE white0 = {.d16 = RD_PPT_REG(offset)}; + white0.reset_rx_pktnum3 = 1; + WR_PPT_REG(offset, white0.d16); + white0.reset_rx_pktnum3 = 0; + WR_PPT_REG(offset, white0.d16); + } + + PRO_GPIO_CONTROL_TYPE gpio_ctrl = {.d16 = RD_PPT_REG(PRO_GPIO_CONTROL)}; + gpio_ctrl.reset_tx_pktnum2 = 1; + WR_PPT_REG(PRO_GPIO_CONTROL, gpio_ctrl.d16); + gpio_ctrl.reset_tx_pktnum2 = 0; + WR_PPT_REG(PRO_GPIO_CONTROL, gpio_ctrl.d16); + + for (uint8_t entry = PPT_ENTRY_NUM_ORI; entry < PPT_ENTRY_NUM; entry++) + { + uint8_t offset = PRO_FIELD_LENGTH3 + ((entry - PPT_ENTRY_NUM_ORI) << 1); + PRO_FIELD_LENGTH3_TYPE len3 = {.d16 = RD_PPT_REG(offset)}; + len3.reset_tx_pktnum3 = 1; + WR_PPT_REG(offset, len3.d16); + len3.reset_tx_pktnum3 = 0; + WR_PPT_REG(offset, len3.d16); + } +} + +PPT_API_SECTION void ppt_execute_instruction(uint8_t instruction_code) +{ + if (instruction_code >= PPT_HW_INSTRUCTION_MAX) + { +#if PPT_LOG_METHOD == 1 + APP_PRINT_ERROR1("ppt_execute_instruction: unknown instruction %d", instruction_code); +#endif + return; + } + +#if PPT_LOG_METHOD == 1 + APP_PRINT_INFO1("ppt_execute_instruction: execute %d", instruction_code); +#endif + PRO_INSTRUCTION_TYPE inst;// = {.d16 = RD_PPT_REG(PRO_INSTRUCTION)}; + inst.instruction = instruction_code; + WR_PPT_REG(PRO_INSTRUCTION, inst.d16); +} + +void ppt_set_crc_param(ppt_crc_param_t *param) +{ + PRO_PACKET_CONTROL_TYPE pkt_ctrl = {.d16 = RD_PPT_REG(PRO_PACKET_CONTROL)}; + pkt_ctrl.crc_field_length_2_0 = param->len; + /* not support feature, shall not be set to true */ + //pkt_ctrl.crc_include_addr_enable = param->include_addr; + WR_PPT_REG(PRO_PACKET_CONTROL, pkt_ctrl.d16); +} + +void ppt_set_crc_entry_param(uint8_t entry, ppt_crc_entry_param_t *param) +{ + assert_param(entry < PPT_ENTRY_NUM); + + /* poly */ + uint16_t crc_poly_lower = param->value.poly & 0xffff; + uint16_t crc_poly_upper = (param->value.poly >> 16) & 0xffff; + uint16_t reg_offset_poly = PPT_REG_OFFSET(entry, PRO_CRC_POLYNOMIAL_REG0_LOWER, + PRO_ONE_ENTRY_DW_SIZE, PRO_CRC_POLYNOMIAL_REG3_LOWER, 4); + WR_PPT_REG(reg_offset_poly, crc_poly_lower); + WR_PPT_REG(reg_offset_poly + 2, crc_poly_upper); + + /* init tx */ + uint16_t crc_init_lower = param->value.init & 0xffff; + uint16_t crc_init_upper = (param->value.init >> 16) & 0xffff; + uint16_t reg_offset_init = PPT_REG_OFFSET(entry, PRO_CRC_INIT0_LOWER, PRO_ONE_ENTRY_DW_SIZE, + PRO_CRC_INIT3_LOWER, 4); + WR_PPT_REG(reg_offset_init, crc_init_lower); + WR_PPT_REG(reg_offset_init + 2, crc_init_upper); + + /* init rx */ + uint16_t reg_offset_init_rx = PPT_REG_OFFSET(entry, PRO_RX_CRC_INIT0_LOWER, 4, + PRO_RX_CRC_INIT3_LOWER, 4); + WR_PPT_REG(reg_offset_init_rx, crc_init_lower); + WR_PPT_REG(reg_offset_init_rx + 2, crc_init_upper); +} + +void ppt_set_white_param(ppt_white_param_t *param) +{ + PRO_PACKET_CONTROL_TYPE packet_ctrl = {.d16 = RD_PPT_REG(PRO_PACKET_CONTROL)}; + packet_ctrl.white_dis = !param->enable; + WR_PPT_REG(PRO_PACKET_CONTROL, packet_ctrl.d16); +} + +void ppt_set_white_entry_param(uint8_t entry, ppt_white_entry_param_t *param) +{ + assert_param(entry < PPT_ENTRY_NUM); + + if (entry < PPT_ENTRY_NUM_ORI) + { + PRO_PACKET_RELATED_CONTROL0_TYPE pkt_related_ctrl = {.d16 = RD_PPT_REG(PRO_ENTRY_FIELD_BASE(entry) + PRO_PACKET_RELATED_CONTROL0)}; + pkt_related_ctrl.white_field_length0 = param->len; + WR_PPT_REG(PRO_ENTRY_FIELD_BASE(entry) + PRO_PACKET_RELATED_CONTROL0, pkt_related_ctrl.d16); + } + else + { + uint16_t offset = ((entry - PPT_ENTRY_NUM_ORI) << 1) + PRO_WHITE_FIELD_LENGTH_0; + PRO_WHITE_FIELD_LENGTH_0_TYPE white0 = {.d16 = RD_PPT_REG(offset)}; + white0.white_field_length3 = param->len; + WR_PPT_REG(offset, white0.d16); + } + + uint16_t white_poly_l = param->value.poly & 0xffff; + uint16_t white_poly_u = (param->value.poly >> 16) & 0xffff; + uint16_t reg_offset_poly = PPT_REG_OFFSET(entry, PRO_WHITE_POLYNOMIAL_REG0_LOWER, + PRO_ONE_ENTRY_DW_SIZE, PRO_WHITE_POLYNOMIAL_REG3_LOWER, 4); + WR_PPT_REG(reg_offset_poly, white_poly_l); + WR_PPT_REG(reg_offset_poly + 2, white_poly_u); + + uint16_t white_ini_l = param->value.init & 0xffff; + uint16_t white_ini_u = (param->value.init >> 16) & 0xffff; + uint16_t reg_offset_init = PPT_REG_OFFSET(entry, PRO_WHITE_INIT0_LOWER, PRO_ONE_ENTRY_DW_SIZE, + PRO_WHITE_INIT3_LOWER, 4); + WR_PPT_REG(reg_offset_init, white_ini_l); + WR_PPT_REG(reg_offset_init + 2, white_ini_u); +} + +void ppt_set_phy_rx_type(ppt_phy_type_t rx_phy) +{ + PRO_RX_CONTROL_TYPE rx_ctrl = {.d16 = RD_PPT_REG(PRO_RX_CONTROL)}; + rx_ctrl.rx_phy = rx_phy; + WR_PPT_REG(PRO_RX_CONTROL, rx_ctrl.d16); +} + +void ppt_set_phy_tx_type(uint8_t entry, ppt_phy_type_t tx_phy) +{ + assert_param(entry < PPT_ENTRY_NUM); + + if (entry < PPT_ENTRY_NUM_ORI) + { + PRO_PACKET_RELATED_CONTROL0_TYPE pkt_related_ctrl = {.d16 = RD_PPT_REG(PRO_ENTRY_FIELD_BASE(entry) + PRO_PACKET_RELATED_CONTROL0)}; + pkt_related_ctrl.tx_phy0 = tx_phy; + WR_PPT_REG(PRO_ENTRY_FIELD_BASE(entry) + PRO_PACKET_RELATED_CONTROL0, pkt_related_ctrl.d16); + } + else + { + PRO_WHITE_FIELD_LENGTH_0_TYPE white_field_len = {.d16 = RD_PPT_REG(2 * (entry - PPT_ENTRY_NUM_ORI) + PRO_WHITE_FIELD_LENGTH_0)}; + white_field_len.tx_phy3 = tx_phy; + WR_PPT_REG(2 * (entry - PPT_ENTRY_NUM_ORI) + PRO_WHITE_FIELD_LENGTH_0, white_field_len.d16); + } +} + +void ppt_set_phy_mod_index_2m(bool change) +{ + if (ppt_fw_ret.mod_index_2m_flag != change) + { + if (change) + { + RTK_WRITE_MODEM_REG_PI(MODEM_PI_PAGE_7, TRANS_MODEM_REG(0x14), 0xfb34); + RTK_UPDATE_MODEM_REG_PI(MODEM_PI_PAGE_7, TRANS_MODEM_REG(0x16), 0x3, 0x1); + RTK_UPDATE_MODEM_REG_PI(MODEM_PI_PAGE_2, TRANS_MODEM_REG(0x14), 0x3f, 0x28); + RTK_UPDATE_MODEM_REG_PI(MODEM_PI_PAGE_6, TRANS_MODEM_REG(0x2c), 0x3fe, 0x50); + } + else + { + RTK_WRITE_MODEM_REG_PI(MODEM_PI_PAGE_7, TRANS_MODEM_REG(0x14), 0xffd3); + RTK_UPDATE_MODEM_REG_PI(MODEM_PI_PAGE_7, TRANS_MODEM_REG(0x16), 0x3, 0x2); + RTK_UPDATE_MODEM_REG_PI(MODEM_PI_PAGE_2, TRANS_MODEM_REG(0x14), 0x3f, 0x1a); + RTK_UPDATE_MODEM_REG_PI(MODEM_PI_PAGE_6, TRANS_MODEM_REG(0x2c), 0x3fe, 0x84); + } + ppt_fw_ret.mod_index_2m_flag = change; + } +} + +PPT_API_SECTION void ppt_set_phy_bank(uint8_t bank_idx) +{ + /* deprecated */ +} + +PPT_API_SECTION bool ppt_set_phy_channel(uint16_t freq_mhz) +{ + uint8_t bank = 0, channel = 0; + if (false == ppt_get_bank_channel(freq_mhz, &bank, &channel)) + { + return false; + } + PRO_CHANNEL_BANK_TYPE ch_bank; + ch_bank.bank = bank; + ch_bank.pro_channel = channel; + WR_PPT_REG(PRO_CHANNEL_BANK, ch_bank.d16); + /* update phy parameters along with rf bank */ + ppt_set_phy_bank(bank); + return true; +} + +void ppt_set_phy_param(ppt_phy_param_t *param) +{ + PRO_CHANNEL_BANK_TYPE ch_bank = {.d16 = RD_PPT_REG(PRO_CHANNEL_BANK)}; + ch_bank.bank = param->bank; + ch_bank.pro_channel = param->channel; + WR_PPT_REG(PRO_CHANNEL_BANK, ch_bank.d16); + /* update phy parameters along with rf bank */ + ppt_set_phy_bank(param->bank); + + ppt_set_phy_rx_type(param->rx_phy); +} + +void ppt_set_phy_entry_param(uint8_t entry, ppt_phy_entry_param_t *param) +{ + assert_param(entry < PPT_ENTRY_NUM); + + ppt_set_phy_tx_type(entry, param->tx_phy); + ppt_set_preamble_len(entry, param->preamble_len); +} + +void ppt_set_preamble_len(uint8_t entry, uint8_t preamble_len) +{ + assert_param(entry < PPT_ENTRY_NUM); + + if (entry == 0) + { + PRO_FIELD_LENGTH_TYPE field_len = {.d16 = RD_PPT_REG(PRO_FIELD_LENGTH)}; + field_len.preamble_field_length0_2_0 = preamble_len; + WR_PPT_REG(PRO_FIELD_LENGTH, field_len.d16); + } + else if (entry == 1) + { + PRO_FIELD_LENGTH2_TYPE field_len2 = {.d16 = RD_PPT_REG(PRO_FIELD_LENGTH2)}; + field_len2.preamble_field_length1_2_0 = preamble_len; + WR_PPT_REG(PRO_FIELD_LENGTH2, field_len2.d16); + } + else if (entry == 2) + { + PRO_GPIO_CONTROL_TYPE gpio_ctrl = {.d16 = RD_PPT_REG(PRO_GPIO_CONTROL)}; + gpio_ctrl.preamble_field_length2 = preamble_len; + WR_PPT_REG(PRO_GPIO_CONTROL, gpio_ctrl.d16); + } + else + { + PRO_FIELD_LENGTH3_TYPE field_len = {.d16 = RD_PPT_REG(2 * (entry - PPT_ENTRY_NUM_ORI) + PRO_FIELD_LENGTH3)}; + field_len.preamble_field_length3_2_0 = preamble_len; + WR_PPT_REG(2 * (entry - PPT_ENTRY_NUM_ORI) + PRO_FIELD_LENGTH3, field_len.d16); + } +} + +void ppt_set_pkt_format(ppt_pkt_format_t *param) +{ + PRO_RX_MATCH_CONTROL_TYPE rx_match_ctrl = {.d16 = RD_PPT_REG(PRO_RX_MATCH_CONTROL)}; + rx_match_ctrl.compare_prefix_option = param->addr_len == 5; + WR_PPT_REG(PRO_RX_MATCH_CONTROL, rx_match_ctrl.d16); + + PRO_FIELD_LENGTH_TYPE field_len = {.d16 = RD_PPT_REG(PRO_FIELD_LENGTH)}; + field_len.address_field_length_2_0 = param->addr_len; + field_len.hp_field_length_3_0 = param->hp_len; + field_len.length_field_length_3_0 = param->length_len; + WR_PPT_REG(PRO_FIELD_LENGTH, field_len.d16); + + PRO_HS_LENGTH_TYPE hs_len = {.d16 = RD_PPT_REG(PRO_HS_LENGTH)}; + hs_len.hs_field_length_4_0 = param->hs_len; + WR_PPT_REG(PRO_HS_LENGTH, hs_len.d16); + + PRO_ORDER_CONTROL_TYPE order_ctrl = {.d16 = RD_PPT_REG(PRO_ORDER_CONTROL)}; + order_ctrl.hp_order = param->header_order; + order_ctrl.hp_order_first = param->header_order; + order_ctrl.length_order = param->header_order; + order_ctrl.length_order_first = param->header_order; + order_ctrl.hs_order = param->header_order; + order_ctrl.hs_order_first = param->header_order; + WR_PPT_REG(PRO_ORDER_CONTROL, order_ctrl.d16); + WR_PPT_REG_FIELD(PRO_MAX_LENGTH, txfifo_out_split, + param->payload_order == PPT_FIELD_BIT_ORDER_MSB ? 1 : 0); + WR_PPT_REG_FIELD(PRO_MAX_LENGTH, rxfifo_in_split, + param->payload_order == PPT_FIELD_BIT_ORDER_MSB ? 1 : 0); + + PRO_PREFIX6_7_TYPE prefix6_7 = {.d16 = RD_PPT_REG(PRO_PREFIX6_7)}; + prefix6_7.hp_order_first_rx = param->header_order; + prefix6_7.length_order_first_rx = param->header_order; + prefix6_7.hs_order_first_rx = param->header_order; + WR_PPT_REG(PRO_PREFIX6_7, prefix6_7.d16); +} + +void ppt_set_addon_len(uint8_t entry, ppt_addon_length_t *param) +{ + assert_param(entry < PPT_ENTRY_NUM); + + if (entry < PPT_ENTRY_NUM_ORI) + { + PRO_ADD_ON_LENGTH0_TYPE add_on_length = {.d16 = RD_PPT_REG(PRO_ENTRY_FIELD_BASE(entry) + PRO_ADD_ON_LENGTH0)}; + add_on_length.add_on_length0_7_0 = param->len; + WR_PPT_REG(PRO_ENTRY_FIELD_BASE(entry) + PRO_ADD_ON_LENGTH0, add_on_length.d16); + } + else + { + uint16_t offset = ((entry - PPT_ENTRY_NUM_ORI) & (~BIT0)) + PRO_ADD_ON_LENGTH3; + uint8_t field_offset = ((entry - PPT_ENTRY_NUM_ORI) & BIT0) << 3; + OV_PPT_REG_FIELD(offset, field_offset, 8, param->len); + } +} + +void ppt_set_tx_power(uint8_t tx_gain) +{ + PRO_GAIN_TYPE gain = {.d16 = RD_PPT_REG(PRO_GAIN)}; + gain.rif_tx_gain = tx_gain; + WR_PPT_REG(PRO_GAIN, gain.d16); +} + +extern bool (*get_valid_txgain_index_from_tx_power)(int8_t, uint8_t, uint8_t, bool, uint8_t *, + int8_t *); +#define TXGAIN_LE_1M 0 +#define TPM_MODE 0 +void ppt_set_tx_power_dbm(float tx_power_dbm) +{ + uint8_t tx_gain; + int8_t tx_power = tx_power_dbm; + int8_t tx_power_act; + //todo: set according to phy + get_valid_txgain_index_from_tx_power(tx_power * 2, TXGAIN_LE_1M, TPM_MODE, TRUE, &tx_gain, + &tx_power_act); + ppt_set_tx_power(tx_gain); +} + +void ppt_set_tx_addr(uint8_t entry, ppt_tx_addr_t *param) +{ + assert_param(entry < PPT_ENTRY_NUM); + + uint16_t tx_addr; + tx_addr = param->tx_addr[0] | (param->tx_addr[1] << 8); + WR_PPT_REG(ppt_lut_tx_addr[entry], tx_addr); + + tx_addr = param->tx_addr[2] | (param->tx_addr[3] << 8); + WR_PPT_REG(ppt_lut_tx_addr[entry] + 2, tx_addr); + + OV_PPT_REG_FIELD(ppt_lut_tx_addr[entry] + 4, 0, 8, param->tx_addr[4]); +} + +void ppt_check_rx_addr(uint8_t bit_th) +{ + PRO_RX_CONTROL_TYPE rx_ctrl = {.d16 = RD_PPT_REG(PRO_RX_CONTROL)}; + PRO_RX_MATCH_CONTROL_TYPE rx_match_ctrl = {.d16 = RD_PPT_REG(PRO_RX_MATCH_CONTROL)}; + uint32_t rx_addr0, rx_addr1; + bool byte3_flag = false; + bool similar_flag = false; + if ((rx_match_ctrl.rx_match_enable_bit_7_0 & 0x1) == 0x1) + { + rx_addr0 = RD_PPT_REG(PRO_BASE0_LOWER) + (RD_PPT_REG(PRO_BASE0_UPPER) << 16); + if ((rx_addr0 >> 24) == 0xff) + { + byte3_flag = true; + } + } + if ((rx_match_ctrl.rx_match_enable_bit_7_0 & 0x2) == 0x2) + { + rx_addr1 = RD_PPT_REG(PRO_BASE1_LOWER) + (RD_PPT_REG(PRO_BASE1_UPPER) << 16); + if ((rx_addr1 >> 24) == 0xff) + { + byte3_flag = true; + } + } + + uint8_t acc_byte3_flag = byte3_flag ? (rx_ctrl.rx_phy == PPT_PHY_TYPE_BLE_2M ? 2 : 1) : 0; + if (acc_byte3_flag != ppt_fw_ret.acc_byte3_flag) + { + /* default value */ + if (ppt_fw_ret.acc_byte3_flag == 2) /* 2M PHY */ + { + RTK_UPDATE_MODEM_REG_PI(MODEM_PI_PAGE_0, TRANS_MODEM_REG(0x10), 0x1 << 3, 0x1 << 3); + } + else if (ppt_fw_ret.acc_byte3_flag == 1)/* 1M PHY */ + { + RTK_UPDATE_MODEM_REG_PI(MODEM_PI_PAGE_2, TRANS_MODEM_REG(0x68), 0x7 << 9, 0x4 << 9); + } + + /* modified value */ + if (acc_byte3_flag == 2)/* 2M PHY */ + { + /* need restore after dlps */ + RTK_UPDATE_MODEM_REG_PI(MODEM_PI_PAGE_0, TRANS_MODEM_REG(0x10), 0x1 << 3, 0x0 << 3); + } + else if (acc_byte3_flag == 1)/* 1M PHY */ + { + /* need restore after dlps */ + RTK_UPDATE_MODEM_REG_PI(MODEM_PI_PAGE_2, TRANS_MODEM_REG(0x68), 0x7 << 9, 0x1 << 9); + } + + ppt_fw_ret.acc_byte3_flag = acc_byte3_flag; + } + + if ((rx_match_ctrl.rx_match_enable_bit_7_0 & 0x3) == 0x3) + { + uint32_t addr_diff = rx_addr0 ^ rx_addr1; + uint8_t diff_count = 0; + while (addr_diff) + { + diff_count += 1; + addr_diff &= addr_diff - 1; + } + if (diff_count <= bit_th) + { + similar_flag = true; + } + } + + if (similar_flag != ppt_fw_ret.acc_similar_flag) + { + ppt_fw_ret.acc_similar_flag = similar_flag; + if (similar_flag) /* modified value */ + { + /* need restore after dlps */ + RTK_UPDATE_MODEM_REG_PI(MODEM_PI_PAGE_6, TRANS_MODEM_REG(0x4a), 0xff << 0, 0x33 << 0); + /* 1M PHY */ + { + RTK_UPDATE_MODEM_REG_PI(MODEM_PI_PAGE_0, TRANS_MODEM_REG(0x3C), 0x1 << 11, 0x1 << 11); + /* need restore after dlps */ + RTK_UPDATE_MODEM_REG_PI(MODEM_PI_PAGE_0, TRANS_MODEM_REG(0x2C), 0x7 << 13, 0x0 << 13); + } + /* 2M PHY */ + { + RTK_UPDATE_MODEM_REG_PI(MODEM_PI_PAGE_6, TRANS_MODEM_REG(0x2a), 0x1 << 3, 0x1 << 3); + RTK_UPDATE_MODEM_REG_PI(MODEM_PI_PAGE_6, TRANS_MODEM_REG(0x2a), 0x7 << 4, 0x0 << 4); + } + } + else /* default value */ + { + RTK_UPDATE_MODEM_REG_PI(MODEM_PI_PAGE_6, TRANS_MODEM_REG(0x4a), 0xff << 0, 0xcc << 0); + /* 1M PHY */ + { + RTK_UPDATE_MODEM_REG_PI(MODEM_PI_PAGE_0, TRANS_MODEM_REG(0x3C), 0x1 << 11, 0x0 << 11); + RTK_UPDATE_MODEM_REG_PI(MODEM_PI_PAGE_0, TRANS_MODEM_REG(0x2C), 0x7 << 13, 0x2 << 13); + } + /* 2M PHY */ + { + RTK_UPDATE_MODEM_REG_PI(MODEM_PI_PAGE_6, TRANS_MODEM_REG(0x2a), 0x1 << 3, 0x0 << 3); + RTK_UPDATE_MODEM_REG_PI(MODEM_PI_PAGE_6, TRANS_MODEM_REG(0x2a), 0x7 << 4, 0x6 << 4); + } + } + } +} + +#define ppt_set_prefix(entry, prefix) OV_PPT_REG_FIELD(ppt_lut_prefix[entry].reg_offset, ppt_lut_prefix[entry].field_offset, 8, prefix) + +void ppt_set_rx_addr(uint8_t entry, ppt_rx_addr_t *param) +{ + assert_param(entry < PPT_ENTRY_RX_NUM); + PRO_RX_MATCH_CONTROL_TYPE rx_match_ctrl = {.d16 = RD_PPT_REG(PRO_RX_MATCH_CONTROL)}; + if (param->enable) + { + rx_match_ctrl.rx_match_enable_bit_7_0 |= BIT(entry); + ppt_fw_ret.modem_acc_enable |= BIT(entry); + uint16_t addr = param->rx_addr[0] + (param->rx_addr[1] << 8); + uint16_t addr1 = param->rx_addr[2] + (param->rx_addr[3] << 8); + uint8_t prefix = param->rx_addr[4]; + uint32_t base_for_modem = ppt_swap_bits32(addr + (addr1 << 16)); + ppt_fw_ret.modem_acc[entry] = base_for_modem; + if (entry == 0) + { + WR_PPT_REG(PRO_BASE0_LOWER, addr); + WR_PPT_REG(PRO_BASE0_UPPER, addr1); + RTK_WRITE_MODEM_REG_PI(MODEM_PI_PAGE_0, TRANS_MODEM_REG(0x1c), base_for_modem); + RTK_WRITE_MODEM_REG_PI(MODEM_PI_PAGE_0, TRANS_MODEM_REG(0x1e), base_for_modem >> 16); + } + else + { + WR_PPT_REG(PRO_BASE1_LOWER, addr); + WR_PPT_REG(PRO_BASE1_UPPER, addr1); + RTK_WRITE_MODEM_REG_PI(MODEM_PI_PAGE_0, TRANS_MODEM_REG(0x24), base_for_modem); + RTK_WRITE_MODEM_REG_PI(MODEM_PI_PAGE_0, TRANS_MODEM_REG(0x26), base_for_modem >> 16); + // Set Bit0 to 1 if use 2 rx match filter + RTK_UPDATE_MODEM_REG_PI(MODEM_PI_PAGE_0, TRANS_MODEM_REG(0x14), BIT0, 1); + WR_PPT_REG_FIELD(PRO_TX_PKT_NUM2, modem_compare2_addr, 1); + // disable acc false alarm protect scheme + RTK_UPDATE_MODEM_REG_PI(MODEM_PI_PAGE_6, TRANS_MODEM_REG(0x56), 0x3, 0); + } + ppt_set_prefix(entry, prefix); + } + else + { + rx_match_ctrl.rx_match_enable_bit_7_0 &= ~BIT(entry); + ppt_fw_ret.modem_acc_enable &= ~BIT(entry); + if (entry >= 1 && (ppt_fw_ret.modem_acc_enable & 0xfe) == 0) + { + RTK_UPDATE_MODEM_REG_PI(MODEM_PI_PAGE_0, TRANS_MODEM_REG(0x14), BIT0, 0); + WR_PPT_REG_FIELD(PRO_TX_PKT_NUM2, modem_compare2_addr, 0); + RTK_UPDATE_MODEM_REG_PI(MODEM_PI_PAGE_6, TRANS_MODEM_REG(0x56), 0x3, 0x3); + } + } + WR_PPT_REG(PRO_RX_MATCH_CONTROL, rx_match_ctrl.d16); +} + +PPT_API_SECTION void ppt_set_hp(uint8_t entry, uint8_t hp) +{ + assert_param(entry < PPT_ENTRY_NUM); + + if (entry < PPT_ENTRY_NUM_ORI) + { + PRO_HP_0_TYPE hp0 = {.d16 = RD_PPT_REG(PRO_HP_0 + PRO_ENTRY_FIELD_BASE(entry))}; + hp0.hp_0_7_0 = hp; + WR_PPT_REG(PRO_HP_0 + PRO_ENTRY_FIELD_BASE(entry), hp0.d16); + } + else + { + uint16_t reg_offet = PRO_HP_3 + (((entry - PPT_ENTRY_NUM_ORI) >> 1) << 1); + uint8_t field_offset = ((entry - PPT_ENTRY_NUM_ORI) & 0x1) << 3; + OV_PPT_REG_FIELD(reg_offet, field_offset, 8, hp); + } +} + +PPT_API_SECTION void ppt_set_length(uint8_t entry, uint16_t length) +{ + assert_param(entry < PPT_ENTRY_NUM); + + if (entry < PPT_ENTRY_NUM_ORI) + { + PRO_LENGTH_0_TYPE len = {.d16 = RD_PPT_REG(PRO_LENGTH_0 + PRO_ENTRY_FIELD_BASE(entry))}; + len.length_0_14_0 = length; + WR_PPT_REG(PRO_LENGTH_0 + PRO_ENTRY_FIELD_BASE(entry), len.d16); + } + else + { + uint16_t offset = ((entry - PPT_ENTRY_NUM_ORI) << 1) + PRO_LENGTH_3; + PRO_LENGTH_3_TYPE len = {.d16 = RD_PPT_REG(offset)}; + len.length_3_14_0 = length; + WR_PPT_REG(offset, len.d16); + } +} + +PPT_API_SECTION void ppt_set_hs(uint8_t entry, uint32_t hs) +{ + assert_param(entry < PPT_ENTRY_NUM); + + uint16_t reg_offet_l = PPT_REG_OFFSET(entry, PRO_HS_0_LOWER, PRO_ONE_ENTRY_DW_SIZE, PRO_HS_3_LOWER, + 4); + WR_PPT_REG(reg_offet_l, hs & 0xffff); + OV_PPT_REG_FIELD(reg_offet_l + 2, 1, 15, (hs >> 16) & 0xffff); +} + +void ppt_set_tx_header(uint8_t entry, ppt_header_t *param) +{ + assert_param(entry < PPT_ENTRY_NUM); + + ppt_set_hp(entry, param->hp); + /* length not used if dma_length_mode is enabled */ + ppt_set_length(entry, param->length); + ppt_set_hs(entry, param->hs); +} + +void ppt_set_tifs(uint8_t tifs_us) +{ + PRO_TX_TURN_AROUND_DELAY_TYPE tx_delay = {.d16 = RD_PPT_REG(PRO_TX_TURN_AROUND_DELAY)}; + tx_delay.pro_tx2rx_delay_base = tifs_us - 22; + WR_PPT_REG(PRO_TX_TURN_AROUND_DELAY, tx_delay.d16); + PRO_RX_TURN_AROUND_DELAY_TYPE rx_delay = {.d16 = RD_PPT_REG(PRO_RX_TURN_AROUND_DELAY)}; + rx_delay.pro_rx2tx_delay_base = tifs_us - 20; + WR_PPT_REG(PRO_RX_TURN_AROUND_DELAY, rx_delay.d16); +} + +void ppt_set_timing_latch(ppt_timing_latch_t *param) +{ + PRO_CBK_CTRL_TYPE cbk_ctrl = {.d16 = RD_PPT_REG(PRO_CBK_CTRL)}; + cbk_ctrl.tx_time_enable = param->tx_on; + WR_PPT_REG(PRO_CBK_CTRL, cbk_ctrl.d16); + + PRO_RX_CONTROL_TYPE rx_ctrl = {.d16 = RD_PPT_REG(PRO_RX_CONTROL)}; + rx_ctrl.acchit_time_enable = param->acc_hit; + WR_PPT_REG(PRO_RX_CONTROL, rx_ctrl.d16); +} + +void ppt_set_gpio_param(ppt_gpio_param_t *param) +{ + PRO_RESET_CTRL_REG_TYPE reset_ctrl = {.d16 = RD_PPT_REG(PRO_RESET_CTRL_REG)}; + reset_ctrl.gpio_tx_enable = param->enable; + reset_ctrl.gpio_in_enable = param->int_enable; + WR_PPT_REG(PRO_RESET_CTRL_REG, reset_ctrl.d16); +} + +void ppt_set_gpio_entry_param(uint8_t entry, ppt_gpio_entry_param_t *param) +{ + assert_param(entry < PPT_ENTRY_NUM); + + if (entry == 0) + { + PRO_GPIO_TX_DELAY_TYPE gpio_tx_delay = {.d16 = RD_PPT_REG(PRO_GPIO_TX_DELAY)}; + gpio_tx_delay.gpio_tx_delay_15_0 = param->gpio_delay; + WR_PPT_REG(PRO_GPIO_TX_DELAY, gpio_tx_delay.d16); + } + else if (entry == 1) + { + PRO_GPIO_TX_DELAY1_TYPE gpio_tx_delay1 = {.d16 = RD_PPT_REG(PRO_GPIO_TX_DELAY1)}; + gpio_tx_delay1.gpio_tx_delay1_15_0 = param->gpio_delay; + WR_PPT_REG(PRO_GPIO_TX_DELAY1, gpio_tx_delay1.d16); + } + else if (entry == 2) + { + PRO_GPIO_TX_DELAY2_TYPE gpio_tx_delay2 = {.d16 = RD_PPT_REG(PRO_GPIO_TX_DELAY2)}; + gpio_tx_delay2.gpio_tx_delay2_15_0 = param->gpio_delay; + WR_PPT_REG(PRO_GPIO_TX_DELAY2, gpio_tx_delay2.d16); + } + else + { + /* no setting here */ + } +} + +void ppt_set_ptx_mode(ppt_ptx_mode_t *param) +{ + PRO_TX_CONTROL_TYPE tx_ctrl = {.d16 = RD_PPT_REG(PRO_TX_CONTROL)}; + tx_ctrl.periodic_enable = param->periodic_mode; + WR_PPT_REG(PRO_TX_CONTROL, tx_ctrl.d16); + + PRO_TRX_CONTROL_TYPE trx_ctrl = {.d16 = RD_PPT_REG(PRO_TRX_CONTROL)}; + trx_ctrl.ack_enable = param->ack_mode; + WR_PPT_REG(PRO_TRX_CONTROL, trx_ctrl.d16); + + if (param->periodic_mode) + { + PRO_PERIODIC_INTERVAL_TYPE periodic_interval; + periodic_interval.d16 = param->periodic_interval; + WR_PPT_REG(PRO_PERIODIC_INTERVAL, periodic_interval.d16); + PRO_TRX_CONTROL_TYPE trx_ctrl = {.d16 = RD_PPT_REG(PRO_TRX_CONTROL)}; + trx_ctrl.periodic_interval_19_16 = param->periodic_interval >> 16; + WR_PPT_REG(PRO_TRX_CONTROL, trx_ctrl.d16); + } +} + +void ppt_set_prx_mode(ppt_prx_mode_t *param) +{ + PRO_RX_CONTROL_TYPE rx_ctrl = {.d16 = RD_PPT_REG(PRO_RX_CONTROL)}; + rx_ctrl.continuous_rx = param->continuous_mode; + WR_PPT_REG(PRO_RX_CONTROL, rx_ctrl.d16); + + PRO_TRX_CONTROL_TYPE trx_ctrl = {.d16 = RD_PPT_REG(PRO_TRX_CONTROL)}; + trx_ctrl.ack_enable = param->ack_mode; + WR_PPT_REG(PRO_TRX_CONTROL, trx_ctrl.d16); +} + +void ppt_set_psd_mode(ppt_psd_mode_t *param) +{ + assert_param(param->chann_start <= param->chann_stop); + assert_param(param->chann_stop < PSD_CHANN_NUM); + assert_param(param->chann_step < PSD_CHANN_NUM); + + PRO_PSD_RANGE0_TYPE psd_range0 = {.d16 = RD_PPT_REG(PRO_PSD_RANGE0)}; + psd_range0.pro_psd_start = param->chann_start; + psd_range0.pro_psd_end = param->chann_stop; + WR_PPT_REG(PRO_PSD_RANGE0, psd_range0.d16); + + PRO_PSD_RANGE1_TYPE psd_range1 = {.d16 = RD_PPT_REG(PRO_PSD_RANGE1)}; + psd_range1.pro_psd_step = param->chann_step; + psd_range1.pro_psd_mode = param->mode; + WR_PPT_REG(PRO_PSD_RANGE1, psd_range1.d16); + + PRO_PSD_TIMEOUT_TYPE psd_timeout = {.d16 = RD_PPT_REG(PRO_PSD_TIMEOUT)}; + psd_timeout.pro_psd_timeout = param->timeout; + WR_PPT_REG(PRO_PSD_TIMEOUT, psd_timeout.d16); +} + +void ppt_dbg_port_open(uint16_t bt_port, uint16_t ppt_port, uint16_t ppt_port2) +{ + /* baseband port */ + VENDOR_WRITE(0x30, (VENDOR_READ(0x30)&BIT31) | 0x40); + WR_16BIT_IO(BB_BASE_ADDR, 0x1FE, bt_port); + + /* 2.4g port */ + WR_PPT_REG(PRO_DEBUG_SEL, ppt_port); + WR_PPT_REG(PRO_DEBUG_SEL2, ppt_port2); + + /* sys */ + debug_port_open(DIGI_DBG_BT); +} + +void ppt_dbg_port_set_pin(uint8_t pin_group, uint32_t dbg_bitmap) +{ +#if PPT_IS_ASIC + debug_port_set_pin_bit_map(pin_group, dbg_bitmap); +#endif +} + +void ppt_dbg_port(uint16_t bt_port, uint16_t ppt_port, uint16_t ppt_port2, uint32_t dbg_bitmap) +{ + ppt_dbg_port_set_pin(DBG_PIN_GROUP_A, dbg_bitmap); + ppt_dbg_port_open(bt_port, ppt_port, ppt_port2); +} + +void ppt_dump_nonzero_reg(void) +{ + DBG_DIRECT("ppt_dump_nonzero_reg: start"); + uint16_t offset = 0; + while (offset < PRO_REG_TOTAL_SIZE) + { + uint16_t value = RD_PPT_REG(offset); + if (value != 0) + { + DBG_DIRECT("ppt_dump_nonzero_reg: 0x%04x = 0x%04x", offset, value); + } + offset += 2; + } + DBG_DIRECT("ppt_dump_nonzero_reg: end"); +} + +bool ppt_get_bank_channel(uint16_t frequency, uint8_t *bank, uint8_t *channel) +{ + if (frequency > 2530) + { + return false; + } + else if (frequency > 2500) + { + *bank = 2; + *channel = frequency - 2452; + } + else if (frequency >= 2402) + { + *bank = 0; + *channel = frequency - 2402; + } + else if (frequency >= 2348) + { + *bank = 1; + *channel = frequency - 2348; + } + else + { + return false; + } + return true; +} + +static const uint8_t le_logic_chan[40] = +{ + 37, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 38, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 39 +}; + +int8_t ppt_get_ble_logic_chan(uint8_t bank, uint8_t channel) +{ + if (bank == 0 && (channel & 0x1) == 0 && channel <= 78) + { + return le_logic_chan[channel / 2]; + } + else + { + return -1; + } +} + +int8_t ppt_get_ble_logic_chan_via_freq(uint16_t frequency) +{ + if (frequency >= 2402 && frequency <= 2480 && ((frequency & 0x1) == 0)) + { + return le_logic_chan[(frequency - 2402) / 2]; + } + else + { + return -1; + } +} + +uint32_t ppt_get_ble_white_init(uint8_t le_logic_chan) +{ + uint32_t white_init = 1; + le_logic_chan = ppt_swap_bits8(le_logic_chan); + white_init |= le_logic_chan >> 1; + return white_init; +} + +#if PATCH_BTMAC_ISR +PPT_ISR_SECTION static uint8_t btmac_isr_handler(void *pbuf) +#else +PPT_ISR_SECTION static void btmac_isr_handler(void) +#endif +{ + BTMAC_ISR_STATUS_REG reg = btmac_isr_status_reg_read(); + //APP_PRINT_INFO1("btmac_isr_handler 0x%08x!", reg.d32); + if (reg.pro_intr_r) + { + if (ppt_isr_handler) + { + ppt_isr_handler(); + } + else + { + DBG_DIRECT("ppt: fail, ISR isn't registered!"); + } + } +#if PATCH_BTMAC_ISR + return false; +#endif +} + +PPT_ISR_SECTION static uint8_t btmac_psd_isr_handler(void *buf) +{ + ppt_clear_radio(); + if (ppt_psd_isr_handler) + { + ppt_psd_isr_handler(); + } + + return true; +} + +PPT_API_SECTION bool ppt_push_tx_fifo(uint8_t entry, uint8_t *payload, uint16_t payload_len) +{ + bool ret; + assert_param(entry < PPT_ENTRY_NUM); + uint32_t s = os_lock(); +#if PPT_LOG_METHOD == 1 + UINT32 cur_bm = RD_U32_BZDMA_REG(BZDMA_REG_BLEONLY_ENTRY_SEGMENT_VALID(entry)); +#endif + /* config bzdma */ + BZDMA_BLEONLY_TX_DESC_FRAGMENT TxFragCache = { .DWord = 0 }; + TxFragCache.start_addr_ex = (UINT32)payload; + TxFragCache.len_ex = payload_len; + TxFragCache.isLast = TRUE; + // Pad_Config(P3_0, PAD_SW_MODE, PAD_IS_PWRON, PAD_PULL_DOWN, PAD_OUT_ENABLE, + // PAD_OUT_LOW); + + ret = bzdma_send_packet_to_ble_data_ring_fifo(entry, LL_LLID_DATA_PDU_START, + &TxFragCache, 1, 0); + // Pad_Config(P3_0, PAD_SW_MODE, PAD_IS_PWRON, PAD_PULL_DOWN, PAD_OUT_ENABLE, + // PAD_OUT_LOW); + + ret = true; +#if PPT_LOG_METHOD == 1 + APP_PRINT_INFO5("ppt_push_tx_fifo: BZDMA bitmap 0x%x -> 0x%x, entry %d, wr ptr %d, len %d", cur_bm, + RD_U32_BZDMA_REG(BZDMA_REG_BLEONLY_ENTRY_SEGMENT_VALID(entry)), entry, + Bzdma_Manager.BleTxEntSta[entry].seg_wptr, payload_len); +#endif + os_unlock(s); + return ret; +} + +PPT_API_SECTION static UINT8 bzdma_update_packet_to_ble_data_ring_fifo(UINT8 conn_entry, UINT8 llid, + BZDMA_BLEONLY_TX_DESC_FRAGMENT *pfrag, UINT8 Nfrag, + UINT8 codeind) +{ + BZDMA_BLEONLY_DATA_TX_DESC_ENTRY_STATUS *pTxEnt; + BZDMA_BLEONLY_TX_DESC_SEGMENT *pTxSeg; + BZDMA_BLEONLY_TX_DESC_FRAGMENT *pTxFrag; + UINT8 cur_wptr; + UINT8 i; + UINT8 PktSize = 0; + + pTxEnt = &Bzdma_Manager.BleTxEntSta[conn_entry]; + if (pTxEnt->free_segs == bzdma_supported_le_max_seg_num) + { + /* fifo is empty */ + return FALSE; + } + + cur_wptr = (pTxEnt->seg_wptr + bzdma_supported_le_max_seg_num - 1) & (bzdma_supported_le_max_seg_num + - 1); + pTxSeg = &pTxEnt->pTxSegDesc[cur_wptr]; + pTxFrag = &pTxEnt->pTxFragDesc[cur_wptr * 2]; + + /* fill all fragments */ + for (i = 0; i < Nfrag; i++) + { + pTxFrag[i].DWord = pfrag[i].DWord; + UINT16 local_len; + local_len = pfrag[i].len_ex; + PktSize += local_len; + if (local_len == 0) + { + /* hw can not handle zero length !! */ + return FALSE; + } + } + + /* fill full packet sie to tx segment */ + pTxSeg->len = PktSize; + pTxSeg->llid = llid; + return TRUE; +} + +PPT_API_SECTION bool ppt_update_tx_fifo(uint8_t entry, uint8_t *payload, uint16_t payload_len) +{ + bool ret; + assert_param(entry < PPT_ENTRY_NUM); + uint32_t s = os_lock(); +#if PPT_LOG_METHOD == 1 + UINT32 cur_bm = RD_U32_BZDMA_REG(BZDMA_REG_BLEONLY_ENTRY_SEGMENT_VALID(entry)); +#endif + /* config bzdma */ + BZDMA_BLEONLY_TX_DESC_FRAGMENT TxFragCache = { .DWord = 0 }; + TxFragCache.start_addr_ex = (UINT32)payload; + TxFragCache.len_ex = payload_len; + TxFragCache.isLast = TRUE; + ret = bzdma_update_packet_to_ble_data_ring_fifo(entry, LL_LLID_DATA_PDU_START, + &TxFragCache, 1, 0); + ret = true; +#if PPT_LOG_METHOD == 1 + APP_PRINT_INFO5("ppt_update_tx_fifo: BZDMA bitmap 0x%x -> 0x%x, entry %d, wr ptr %d, len %d", + cur_bm, + RD_U32_BZDMA_REG(BZDMA_REG_BLEONLY_ENTRY_SEGMENT_VALID(entry)), entry, + Bzdma_Manager.BleTxEntSta[entry].seg_wptr, payload_len); +#endif + os_unlock(s); + return ret; +} + +PPT_API_SECTION bool ppt_pop_rx_fifo(uint8_t entry, uint8_t *pdu, uint16_t pdu_len) +{ + assert_param(entry < PPT_ENTRY_NUM); + + /* config bzdma */ + BZDMA_RX_DESC_SEGMENT rxdesc = { .DWord = 0 }; + rxdesc.addr = (uint32_t)pdu; + rxdesc.len = pdu_len; + rxdesc.flush = FALSE; + bzdma_send_burst_rxcmd_and_wait_complete(&rxdesc, 1, + BZDMA_RX_PID_ACL, entry, TRUE); + return true; +} + +uint8_t ppt_flush_tx_fifo(uint8_t entry) +{ + assert_param(entry < PPT_ENTRY_NUM); + + Bzdma_Manager.BleTxEntSta[entry].seg_wptr = Bzdma_Manager.BleTxEntSta[entry].seg_rptr; + Bzdma_Manager.BleTxEntSta[entry].free_segs = bzdma_supported_le_max_seg_num; + bzdma_ble_set_segment_valid_bitmap(entry, 0); + return Bzdma_Manager.BleTxEntSta[entry].seg_rptr; +} + +PPT_API_SECTION uint8_t ppt_get_tx_fifo_rdptr(uint8_t entry) +{ + assert_param(entry < PPT_ENTRY_NUM); + return Bzdma_Manager.BleTxEntSta[entry].seg_rptr; +} + +PPT_API_SECTION void ppt_set_tx_fifo_rdptr(uint8_t entry, uint8_t ptr) +{ + assert_param(entry < PPT_ENTRY_NUM); + Bzdma_Manager.BleTxEntSta[entry].seg_rptr = ptr; +} + +PPT_API_SECTION uint8_t ppt_get_tx_fifo_wrptr(uint8_t entry) +{ + assert_param(entry < PPT_ENTRY_NUM); + return Bzdma_Manager.BleTxEntSta[entry].seg_wptr; +} + +PPT_API_SECTION void ppt_reset_tx_fifo(uint8_t entry) +{ + ppt_set_tx_fifo_rdptr(entry, PPT_TX_FIFO_SIZE - 1); + ppt_force_fw_ack(entry); + ppt_flush_tx_fifo(entry); +} + +PPT_API_SECTION int8_t ppt_get_rssi(uint16_t rssi_raw) +{ + return calculate_log_from_rssi(rssi_raw, 0xff, PPT_RF_MODE); +} + +void ppt_clear_dma_tx_done(void) +{ + /* This is a workaround for reset when bzdma start which results in dma carry error later. */ + /* BIT17: dma clock gating disable flag */ + VENDOR_WRITE(0x328, (VENDOR_READ(0x328) & (~BIT17)) | BIT17); + platform_delay_us(1); + VENDOR_WRITE(0x328, VENDOR_READ(0x328) & (~BIT17)); +} + +void ppt_init_dma(void) +{ + bzdma_supported_le_max_seg_num = PPT_TX_FIFO_SIZE; + for (uint8_t loop = 0; loop < PPT_ENTRY_NUM; loop++) + { + Bzdma_Manager.BleTxEntSta[loop].seg_rptr = 0; + Bzdma_Manager.BleTxEntSta[loop].seg_wptr = 0; + Bzdma_Manager.BleTxEntSta[loop].free_segs = bzdma_supported_le_max_seg_num; + bzdma_ble_set_segment_valid_bitmap(loop, 0); + } +} + +void ppt_deinit_dma(void) +{ + bzdma_supported_le_max_seg_num = 16; + for (uint8_t loop = 0; loop < PPT_ENTRY_NUM; loop++) + { + Bzdma_Manager.BleTxEntSta[loop].seg_rptr = 0; + Bzdma_Manager.BleTxEntSta[loop].seg_wptr = 0; + Bzdma_Manager.BleTxEntSta[loop].free_segs = bzdma_supported_le_max_seg_num; + bzdma_ble_set_segment_valid_bitmap(loop, 0); + } +} + +void ppt_notify_btmac(bool ppt_mode) +{ + /* notify 2.4g state to btmac */ + lowerstack_SystemCall(6, ppt_mode, 0, 0); +} + +void ppt_init_misc(void) +{ +#if PATCH_BTMAC_ISR + btmac_handler_temp = rcp_BTMAC_Handler; + rcp_BTMAC_Handler = (PF_ROM_CODE_PATCH_FUNC)btmac_isr_handler; +#else + RamVectorTableUpdate(BTMAC_VECTORn, btmac_isr_handler); +#endif + bb_psd_handler_temp = rcp_BB_handle_psd_end_intr_func; + rcp_BB_handle_psd_end_intr_func = (PF_ROM_CODE_PATCH_FUNC)btmac_psd_isr_handler; + + /* modem init 1: proprietary mode, 0: normal mode */ + RTK_UPDATE_MODEM_REG_PI(MODEM_PI_PAGE_0, TRANS_MODEM_REG(0x66), BIT15, BIT15); + /* force tx gain */ + //RTK_WRITE_MODEM_REG_PI(MODEM_PI_PAGE_3, TRANS_MODEM_REG(0x5c), 0x7840); + + /* workaround for rx empty pkt */ + //uint16_t reg = ((uint16_t) * ((volatile uint16_t *)(0x40050000 + 0x18e))); + //TODO: BB_write_baseband_register(0x18e, reg | BIT15); +} + +void ppt_deinit_misc(void) +{ + //uint16_t reg = ((uint16_t) * ((volatile uint16_t *)(0x40050000 + 0x18e))); + //TODO: BB_write_baseband_register(0x18e, reg & (~BIT15)); + + RTK_UPDATE_MODEM_REG_PI(MODEM_PI_PAGE_0, TRANS_MODEM_REG(0x66), BIT15, 0); + //TODO:ll_hw_init(false); + +#if PATCH_BTMAC_ISR + rcp_BTMAC_Handler = (PF_ROM_CODE_PATCH_FUNC)btmac_handler_temp; +#else + RamVectorTableUpdate(BTMAC_VECTORn, BTMAC_Handler); +#endif + rcp_BB_handle_psd_end_intr_func = (PF_ROM_CODE_PATCH_FUNC)bb_psd_handler_temp; +} + +PPT_API_SECTION uint32_t ppt_crc_eng_cal(ppt_crc_eng_param_t *param, uint8_t *data, + uint32_t data_len) +{ + uint32_t crc_hw = 0; + uint32_t init = param->init; + + WR_PPT_REG(PRO_CRC_ENGINE_POLY, param->poly & 0xffff); + WR_PPT_REG(PRO_CRC_ENGINE_POLY1, (param->poly >> 16) & 0xffff); + WR_PPT_REG_FIELD(PRO_CRC_ENGINE_EN, crc_engine_field_length, param->length >> 3); + WR_PPT_REG_FIELD(PRO_CRC_ENGINE_EN, crc_engine_data_length_in_bit, param->bit_mode); + WR_PPT_REG_FIELD(PRO_CRC_ENGINE_EN, crc_engine_input_endian, param->input_endian); + WR_PPT_REG_FIELD(PRO_CRC_ENGINE_EN, crc_engine_output_endian, 0); + + uint8_t step_len = param->bit_mode ? 40 : 5; + for (uint32_t loop = 0; loop < data_len; loop += step_len) + { + if (param->output_endian && loop + step_len >= data_len) + { + WR_PPT_REG_FIELD(PRO_CRC_ENGINE_EN, crc_engine_output_endian, 1); + } + + WR_PPT_REG(PRO_CRC_ENGINE_INIT, init & 0xffff); + WR_PPT_REG(PRO_CRC_ENGINE_INIT1, (init >> 16) & 0xffff); + + uint32_t data_idx = param->bit_mode ? (loop >> 3) : loop; + WR_PPT_REG(PRO_CRC_ENGINE_IN, data[data_idx + 0] + (data[data_idx + 1] << 8)); + WR_PPT_REG(PRO_CRC_ENGINE_IN1, data[data_idx + 2] + (data[data_idx + 3] << 8)); + WR_PPT_REG_FIELD(PRO_CRC_ENGINE_IN2, crc_engine_input_data_39_32, data[data_idx + 4]); + + uint8_t len = data_len - loop; + if (len > step_len) + { + len = step_len; + } + WR_PPT_REG_FIELD(PRO_CRC_ENGINE_EN, crc_engine_data_length, param->bit_mode ? len : len - 1); + + WR_PPT_REG_FIELD(PRO_CRC_ENGINE_EN, crc_engine_en, 1); + while (1) + { + bool run = RD_PPT_REG_FIELD(PRO_CRC_ENGINE_EN, crc_engine_en); + if (run == false) + { + break; + } + } + + uint16_t crc_l = RD_PPT_REG(PRO_CRC_ENGINE_OUT); + uint16_t crc_h = RD_PPT_REG(PRO_CRC_ENGINE_OUT1); + crc_hw = (crc_h << 16) + crc_l; + init = crc_hw; + } + + if (param->output_endian == 1) + { + crc_hw >>= 32 - param->length; + } + return crc_hw; +} + +void ppt_reg_handler(void (*handler)(void)) +{ + ppt_isr_handler = handler; +} + +void ppt_reg_psd_handler(void (*handler)(void)) +{ + ppt_psd_isr_handler = handler; +} + +#if TIME_DEBUG +void ppt_init_time_debug(void) +{ + RCC_PeriphClockCmd(APBPeriph_GPIOA, APBPeriph_GPIOA_CLOCK, (FunctionalState)ENABLE); + for (uint8_t loop = 0; loop < sizeof(test_pin) / sizeof(test_pin[0]); loop++) + { + Pad_Config(test_pin[loop], PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_DISABLE, + PAD_OUT_HIGH); + Pinmux_Config(test_pin[loop], DWGPIO); + gpio_test_pin[loop] = GPIO_GetPin(test_pin[loop]); + GPIO_InitTypeDef GPIO_InitStruct; + GPIO_StructInit(&GPIO_InitStruct); + GPIO_InitStruct.GPIO_Pin = gpio_test_pin[loop]; + GPIO_InitStruct.GPIO_Mode = GPIO_MODE_OUT; + GPIO_Init(GPIOA, &GPIO_InitStruct); + GPIOA->GPIO_DR |= gpio_test_pin[loop]; + GPIOA->GPIO_DR &= ~gpio_test_pin[loop]; + } +} + +PPT_API_SECTION void ppt_store_time_debug(void) +{ + for (uint8_t loop = 0; loop < sizeof(test_pin) / sizeof(test_pin[0]); loop++) + { + Pad_Config(test_pin[loop], PAD_SW_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_ENABLE, + level_test_pin[loop] ? PAD_OUT_HIGH : PAD_OUT_LOW); + } +} + +PPT_API_SECTION void ppt_restore_time_debug(void) +{ + for (uint8_t loop = 0; loop < sizeof(test_pin) / sizeof(test_pin[0]); loop++) + { + Pad_Config(test_pin[loop], PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_DISABLE, + PAD_OUT_HIGH); + } +} +#endif + +PPT_API_SECTION static PMCheckResult ppt_dlps_mac_check(uint32_t cur_clk, + uint32_t pre_sys_lv_wakeup_time_diff, + uint32_t *unit_wakeup_time_diff) +{ + if (ppt_enable == false) + { + return PM_CHECK_PASS; + } + //DBG_DIRECT("ppt mac check"); + //DBG_DIRECT("ppt mac check %04x, %04x", RD_PPT_REG(PRO_DSM_READ), RD_PPT_REG(PRO_DSM_READ1)); + + BT_SYS_CTRL_REG_S_TYPE bt_sys_reg; + bt_sys_reg.d32 = VENDOR_READ(BT_SYS_CTRL_REG); + if (bt_sys_reg.b.pro_rst_n != 0) + { + uint16_t pro_dsm = RD_PPT_REG(PRO_DSM_READ); + if ((pro_dsm & (BIT6 + BIT11 + BIT12)) != (BIT6 + BIT11 + BIT12)) + { + return PM_CHECK_FAIL; + } + uint16_t pro_dsm1 = RD_PPT_REG(PRO_DSM_READ1); + if ((pro_dsm1 & (BIT0 + BIT7 + BIT13)) != (BIT0 + BIT7 + BIT13)) + { + return PM_CHECK_FAIL; + } + if ((pro_dsm1 & (BIT1 + BIT2)) != 0) + { + return PM_CHECK_FAIL; + } + uint16_t isr_sta = RD_PPT_REG(PRO_MISR) & PPT_ISR_VALID_BITS_MASK; + uint16_t isr_msk = RD_PPT_REG(PRO_IMR) & PPT_ISR_VALID_BITS_MASK; + if (isr_sta & (~isr_msk)) + { + return PM_CHECK_FAIL; + } + } + + if (ppt_dlps_mac_idle == false) + { + return PM_CHECK_FAIL; + } + if (ppt_dlps_mac_check_cb != NULL) + { + if (ppt_dlps_mac_check_cb(unit_wakeup_time_diff) == false) + { + return PM_CHECK_FAIL; + } + } + return PM_CHECK_PASS; +} + +PPT_API_SECTION static void ppt_dlps_mac_store(void) +{ + if (ppt_enable == false) + { + return; + } + + if (ppt_dlps_mac_enter_cb) + { + ppt_dlps_mac_enter_cb(); + } + + ppt_read_reg = ppt_read_reg_dlps; + ppt_write_reg = ppt_write_reg_dlps; +} + +PPT_API_SECTION static void ppt_dlps_mac_restore(void) +{ + if (ppt_enable == false) + { + return; + } + //DBG_DIRECT("ppt mac restore"); + + ppt_reset_core_domain(true); + ppt_read_reg = ppt_read_reg_active; + ppt_write_reg = ppt_write_reg_active; + + for (uint8_t loop = 0; loop < PPT_ENTRY_RX_NUM; loop++) + { + if (ppt_fw_ret.modem_acc_enable & BIT(loop)) + { + uint32_t base_for_modem = ppt_fw_ret.modem_acc[loop]; + if (loop == 0) + { + RTK_WRITE_MODEM_REG_PI(MODEM_PI_PAGE_0, TRANS_MODEM_REG(0x1c), base_for_modem); + RTK_WRITE_MODEM_REG_PI(MODEM_PI_PAGE_0, TRANS_MODEM_REG(0x1e), base_for_modem >> 16); + } + else if (loop == 1) + { + RTK_WRITE_MODEM_REG_PI(MODEM_PI_PAGE_0, TRANS_MODEM_REG(0x24), base_for_modem); + RTK_WRITE_MODEM_REG_PI(MODEM_PI_PAGE_0, TRANS_MODEM_REG(0x26), base_for_modem >> 16); + } + } + } + + if (ppt_fw_ret.acc_byte3_flag == 2)/* 2M PHY */ + { + /* need restore after dlps */ + RTK_UPDATE_MODEM_REG_PI(MODEM_PI_PAGE_0, TRANS_MODEM_REG(0x10), 0x1 << 3, 0x0 << 3); + } + else if (ppt_fw_ret.acc_byte3_flag == 1)/* 1M PHY */ + { + /* need restore after dlps */ + RTK_UPDATE_MODEM_REG_PI(MODEM_PI_PAGE_2, TRANS_MODEM_REG(0x68), 0x7 << 9, 0x1 << 9); + } + + if (ppt_fw_ret.acc_similar_flag) + { + RTK_UPDATE_MODEM_REG_PI(MODEM_PI_PAGE_6, TRANS_MODEM_REG(0x4a), 0xff << 0, 0x33 << 0); + /* 1M PHY */ + { + RTK_UPDATE_MODEM_REG_PI(MODEM_PI_PAGE_0, TRANS_MODEM_REG(0x2C), 0x7 << 13, 0x0 << 13); + } + } + + if (ppt_fw_ret.mod_index_2m_flag) + { + RTK_UPDATE_MODEM_REG_PI(MODEM_PI_PAGE_2, TRANS_MODEM_REG(0x14), 0x3f, 0x28); + RTK_UPDATE_MODEM_REG_PI(MODEM_PI_PAGE_6, TRANS_MODEM_REG(0x2c), 0x3fe, 0x50); + } + + if (ppt_dlps_mac_exit_cb) + { + ppt_dlps_mac_exit_cb(); + } +} + +PPT_API_SECTION static void ppt_dlps_pf_enter(void) +{ + if (ppt_enable == false) + { + return; + } + //DBG_DIRECT("ppt pf enter"); + if (ppt_dlps_pf_enter_cb) + { + ppt_dlps_pf_enter_cb(); + } +#if TIME_DEBUG + ppt_store_time_debug(); +#endif +} + +PPT_API_SECTION static void ppt_dlps_pf_exit(void) +{ + if (ppt_enable == false) + { + return; + } + //DBG_DIRECT("ppt pf exit"); +#if TIME_DEBUG + ppt_restore_time_debug(); +#endif + if (ppt_dlps_pf_exit_cb) + { + ppt_dlps_pf_exit_cb(); + } +} + +void ppt_dlps_init(void) +{ + /* no way to unregister callback, so only register once */ + static bool ppt_dlps_pf_cb_reg = false; + if (ppt_dlps_pf_cb_reg == false) + { + ppt_dlps_pf_cb_reg = true; + platform_pm_register_callback_func(ppt_dlps_pf_enter, PLATFORM_PM_STORE); + platform_pm_register_callback_func(ppt_dlps_pf_exit, PLATFORM_PM_PEND); + + PowerManagerSlaveUnit *ppt_pm = (PowerManagerSlaveUnit *)os_mem_zalloc(RAM_TYPE_DATA_ON, + sizeof(PowerManagerSlaveUnit)); + ppt_pm->check_func = ppt_dlps_mac_check; + ppt_pm->enter_func = ppt_dlps_mac_store; + ppt_pm->exit_func = ppt_dlps_mac_restore; + ppt_pm->unit_id = PM_UNIT_PROPRIETARY; + power_manager_slave_register_unit(PM_UNIT_PROPRIETARY, ppt_pm); + } +} + +void ppt_dlps_deinit(void) +{ + +} + +PPT_API_SECTION bool ppt_dlps_check_active(void) +{ + return (power_manager_interface_get_unit_status(PM_SLAVE_PROPRIETARY, + PM_UNIT_PROPRIETARY) == PM_UNIT_ACTIVE); +} + +PPT_API_SECTION bool ppt_dlps_check_inactive(void) +{ + return (power_manager_interface_get_unit_status(PM_SLAVE_PROPRIETARY, + PM_UNIT_PROPRIETARY) == PM_UNIT_INACTIVE); +} + +PPT_API_SECTION void ppt_dlps_initiate_wakeup(void) +{ + power_manager_master_initiate_wakeup(PM_SLAVE_PROPRIETARY, ((PM_UNIT_PROPRIETARY >> 2) & 0x3), + PM_UNIT_PROPRIETARY); + while (ppt_dlps_check_inactive()); +} + +void ppt_dlps_reg_mac_check_cb(bool (*check_cb)(uint32_t *wakeup_time_diff)) +{ + ppt_dlps_mac_check_cb = check_cb; +} + +void ppt_dlps_reg_mac_enter_cb(void (*enter_cb)(void)) +{ + ppt_dlps_mac_enter_cb = enter_cb; +} + +void ppt_dlps_reg_mac_exit_cb(void (*exit_cb)(void)) +{ + ppt_dlps_mac_exit_cb = exit_cb; +} + +void ppt_dlps_reg_pf_enter_cb(void (*enter_cb)(void)) +{ + ppt_dlps_pf_enter_cb = enter_cb; +} + +void ppt_dlps_reg_pf_exit_cb(void (*exit_cb)(void)) +{ + ppt_dlps_pf_exit_cb = exit_cb; +} diff --git a/bee/drivers/ppt/driver/common/ppt_driver.h b/bee/drivers/ppt/driver/common/ppt_driver.h new file mode 100644 index 00000000..7ecd1737 --- /dev/null +++ b/bee/drivers/ppt/driver/common/ppt_driver.h @@ -0,0 +1,1215 @@ +/** +***************************************************************************************** +* Copyright(c) 2020, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file ppt_driver.h + * @brief Head file for 2.4G module common driver. + * @details data structs and external functions declaration. + * @author bill + * @date 2020-12-03 + * @version v0.1 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _PPT_DRIVER_H_ +#define _PPT_DRIVER_H_ + +/* Add Includes here */ +#include +#include +//#include "app_section.h" +//#include "DataType.h" +#include "ppt_hw_reg.h" +#include "ll_common.h" + +/* Undefine RTK SDK macros that conflict with Zephyr sys/util.h */ +#ifdef hex2char +#undef hex2char +#endif +#ifdef ARRAY_SIZE +#undef ARRAY_SIZE +#endif +#ifdef SAME_TYPE +#undef SAME_TYPE +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** @addtogroup PPT_Driver + * @{ + */ + +/** @defgroup PPT_Driver_Exported_Macros Exported Macros + * @brief + * @{ + */ +#include "zephyr/logging/log.h" + +#if 1 +#define PPT_DRIVER_LOG_LEVEL CONFIG_PPT_DRIVER_LOG_LEVEL + +#define APP_PRINT_INFO0(...) LOG_INF(__VA_ARGS__) +#define APP_PRINT_INFO1(...) LOG_INF(__VA_ARGS__) +#define APP_PRINT_INFO2(...) LOG_INF(__VA_ARGS__) +#define APP_PRINT_INFO3(...) LOG_INF(__VA_ARGS__) +#define APP_PRINT_INFO4(...) LOG_INF(__VA_ARGS__) +#define APP_PRINT_INFO5(...) LOG_INF(__VA_ARGS__) +#define APP_PRINT_INFO6(...) LOG_INF(__VA_ARGS__) +#define APP_PRINT_INFO7(...) LOG_INF(__VA_ARGS__) +#define APP_PRINT_INFO8(...) LOG_INF(__VA_ARGS__) +#define APP_PRINT_WARN0(...) LOG_WRN(__VA_ARGS__) +#define APP_PRINT_WARN1(...) LOG_WRN(__VA_ARGS__) +#define APP_PRINT_WARN2(...) LOG_WRN(__VA_ARGS__) +#define APP_PRINT_WARN3(...) LOG_WRN(__VA_ARGS__) +#define APP_PRINT_WARN4(...) LOG_WRN(__VA_ARGS__) +#define APP_PRINT_WARN5(...) LOG_WRN(__VA_ARGS__) +#define APP_PRINT_WARN6(...) LOG_WRN(__VA_ARGS__) +#define APP_PRINT_WARN7(...) LOG_WRN(__VA_ARGS__) +#define APP_PRINT_WARN8(...) LOG_WRN(__VA_ARGS__) +#define APP_PRINT_ERROR0(...) LOG_ERR(__VA_ARGS__) +#define APP_PRINT_ERROR1(...) LOG_ERR(__VA_ARGS__) +#define APP_PRINT_ERROR2(...) LOG_ERR(__VA_ARGS__) +#define APP_PRINT_ERROR3(...) LOG_ERR(__VA_ARGS__) +#define APP_PRINT_ERROR4(...) LOG_ERR(__VA_ARGS__) +#define APP_PRINT_ERROR5(...) LOG_ERR(__VA_ARGS__) +#define APP_PRINT_ERROR6(...) LOG_ERR(__VA_ARGS__) +#define APP_PRINT_ERROR7(...) LOG_ERR(__VA_ARGS__) +#define APP_PRINT_ERROR8(...) LOG_ERR(__VA_ARGS__) +#define DBG_DIRECT(...) LOG_INF(__VA_ARGS__) +#define TRACE_BINARY(len, pointer) (len) +#else +#define APP_PRINT_INFO0 LOG_INF +#define APP_PRINT_INFO1 LOG_INF +#define APP_PRINT_INFO2 LOG_INF +#define APP_PRINT_INFO3 LOG_INF +#define APP_PRINT_INFO4 LOG_INF +#define APP_PRINT_INFO5 LOG_INF +#define APP_PRINT_INFO6 LOG_INF +#define APP_PRINT_INFO7 LOG_INF +#define APP_PRINT_INFO8 LOG_INF +#define APP_PRINT_WARN0 LOG_INF +#define APP_PRINT_WARN1 LOG_INF +#define APP_PRINT_WARN2 LOG_INF +#define APP_PRINT_WARN3 LOG_INF +#define APP_PRINT_WARN4 LOG_INF +#define APP_PRINT_WARN5 LOG_INF +#define APP_PRINT_WARN6 LOG_INF +#define APP_PRINT_WARN7 LOG_INF +#define APP_PRINT_WARN8 LOG_INF +#define APP_PRINT_ERROR0 LOG_INF +#define APP_PRINT_ERROR1 LOG_INF +#define APP_PRINT_ERROR2 LOG_INF +#define APP_PRINT_ERROR3 LOG_INF +#define APP_PRINT_ERROR4 LOG_INF +#define APP_PRINT_ERROR5 LOG_INF +#define APP_PRINT_ERROR6 LOG_INF +#define APP_PRINT_ERROR7 LOG_INF +#define APP_PRINT_ERROR8 LOG_INF +#define DBG_DIRECT LOG_INF +#define TRACE_BINARY(len, pointer) (len) +#endif + +/** @brief Control the memory location of the function. + * The processing can speed up if the code is in RAM region. + * @{ + */ +#define PPT_ISR_SECTION //RAM_FUNCTION +#define PPT_API_SECTION //RAM_FUNCTION +#define PPT_DAT_SECTION //const +/** @} */ + +/** @brief Hardware trx channel related macros. + * @{ + */ +/* Total channels number */ +#define PPT_ENTRY_NUM 8 +#define PPT_ENTRY_NUM_ORI 3 +/* The maximum rx channels */ +#define PPT_ENTRY_RX_NUM 8 +#define PPT_ENTRY_RX_NUM_ORI 2 +/** @} */ + +/** @brief Hardware feature definition. + * @{ + */ +#define PPT_ADDR_LEN_MAX 5 +#define PPT_TX_FIFO_SIZE 8 + +#define PRO_ONE_ENTRY_DW_SIZE 0x20 +#define PRO_ENTRY_FIELD_BASE(entry) ((entry) * PRO_ONE_ENTRY_DW_SIZE) +#define PRO_ONE_PREFIX_DW_SIZE 0x2 +#define PRO_PREFIX_BASE(entry) ((entry) * PRO_ONE_PREFIX_DW_SIZE) + +#define PPT_ISR_NUMBER 7 +#define PPT_ISR_VALID_BITS_MASK 0x7F +/** @} */ + +/** @} End of PPT_Driver_Exported_Macros */ + +/** @defgroup PPT_Driver_Exported_Types Exported Types + * @brief + * @{ + */ + +/** @brief hw register field descriptor */ +typedef struct +{ + uint16_t reg_offset; + uint8_t field_offset; +} ppt_reg_field_t; + +/** @brief hw supported instructions */ +typedef enum +{ + PPT_HW_INSTRUCTION_PTX_ENABLE = 0, + PPT_HW_INSTRUCTION_PRX_ENABLE = 1, + PPT_HW_INSTRUCTION_PTX_DISABLE = 2, + PPT_HW_INSTRUCTION_PRX_DISABLE = 3, + PPT_HW_INSTRUCTION_PSD_ENABLE = 4, + PPT_HW_INSTRUCTION_PSD_DISABLE = 5, + PPT_HW_INSTRUCTION_MAX +} ppt_hw_instruction_t; + +/** @brief hw supported states */ +typedef enum +{ + PPT_FSM_STANDBY, + PPT_FSM_PTX, + PPT_FSM_PRX, + PPT_FSM_PSD +} ppt_fsm_t; + +/** @brief the bit endianess */ +typedef enum +{ + PPT_FIELD_BIT_ORDER_LSB, + PPT_FIELD_BIT_ORDER_MSB +} ppt_field_bit_order_t; + +/** @brief the packet format control parameters */ +typedef struct +{ + uint8_t addr_len; //!< byte + uint8_t hp_len; //!< bit + uint8_t length_len; //!< bit + uint8_t hs_len; //!< bit + ppt_field_bit_order_t header_order; + ppt_field_bit_order_t payload_order; +} ppt_pkt_format_t; + +/** @brief the addon field length parameters */ +typedef struct +{ + uint8_t len; +} ppt_addon_length_t; + +/** @brief the crc formula parameters */ +typedef struct +{ + uint32_t poly; + uint32_t init; +} ppt_crc_value_t; + +/** @brief the crc length parameters */ +typedef struct +{ + uint8_t len; //!< byte + bool include_addr; //!< not support feature +} ppt_crc_param_t; + +/** @brief crc parameters of each channel */ +typedef struct +{ + ppt_crc_value_t value; +} ppt_crc_entry_param_t; + +/** @brief the whitening formula parameters */ +typedef struct +{ + uint32_t poly; + uint32_t init; +} ppt_white_value_t; + +/** @brief the whitening switch */ +typedef struct +{ + bool enable; +} ppt_white_param_t; + +/** @brief the whitening parameters of each channel */ +typedef struct +{ + uint8_t len; //!< bit + ppt_white_value_t value; +} ppt_white_entry_param_t; + +/** @brief the supported PHY */ +typedef enum +{ + PPT_PHY_TYPE_BLE_1M, + PPT_PHY_TYPE_BLE_2M +} ppt_phy_type_t; + +/** @brief the PHY common parameters */ +typedef struct +{ + uint8_t bank; + uint8_t channel; + ppt_phy_type_t rx_phy; +} ppt_phy_param_t; + +/** @brief the PHY special parameters of each channel */ +typedef struct +{ + uint8_t preamble_len; + ppt_phy_type_t tx_phy; +} ppt_phy_entry_param_t; + +/** @brief rf tx gain */ +typedef enum +{ + PPT_TX_GAIN_8DBM = 0xe0, + PPT_TX_GAIN_7P5DBM = 0xe0, + PPT_TX_GAIN_4DBM = 0xb0, + PPT_TX_GAIN_3DBM = 0xa0, + PPT_TX_GAIN_0DBM = 0x70, + PPT_TX_GAIN_N4DBM = 0x50, + PPT_TX_GAIN_N8DBM = 0x40, + PPT_TX_GAIN_N10DBM = 0x30, + PPT_TX_GAIN_N20DBM = 0x10 +} ppt_tx_gain_t; + +/** @brief the tx access address of each channel */ +typedef struct +{ + uint8_t tx_addr[PPT_ADDR_LEN_MAX]; +} ppt_tx_addr_t; + +/** @brief the rx access address of each channel */ +typedef struct +{ + bool enable; + uint8_t rx_addr[PPT_ADDR_LEN_MAX]; +} ppt_rx_addr_t; + +/** @brief the header fields of frame of each channel*/ +typedef struct +{ + uint8_t hp; + uint16_t length; //!< this field set by DMA automatically + uint32_t hs; +} ppt_header_t; + +/** @brief the ptx mode parameters */ +typedef struct +{ + bool ack_mode; + bool periodic_mode; + uint32_t periodic_interval; //!< 20 valid bits, units of 125us, (n+1)*125us +} ppt_ptx_mode_t; + +/** @brief the prx mode parameters */ +typedef struct +{ + bool ack_mode; + bool continuous_mode; +} ppt_prx_mode_t; + +/** @brief the psd mode parameters */ +typedef struct +{ + uint8_t chann_start; + uint8_t chann_stop; + uint8_t chann_step; + uint8_t mode; //!< useless + uint16_t timeout; //!< value @ref PSD_TIMEOUT_DEFAULT is recommended +} ppt_psd_mode_t; + +/** @brief the timing latch parameters */ +typedef struct +{ + bool tx_on; + bool acc_hit; +} ppt_timing_latch_t; + +/** @brief the GPIO trigger parameters of each channel */ +typedef struct +{ + uint16_t gpio_delay; +} ppt_gpio_entry_param_t; + +/** @brief the GPIO trigger common parameters */ +typedef struct +{ + bool enable; + bool int_enable; +} ppt_gpio_param_t; + +/** @brief the crc engine common parameters */ +typedef struct +{ + uint32_t poly; + uint32_t init; + uint8_t length; //!< length in bits + uint8_t input_endian : 1; //!< 0: lsb, 1: msb + uint8_t output_endian : 1; //!< 0: lsb, 1: msb + uint8_t bit_mode : 1; //!< 0: byte, 1: bit +} ppt_crc_eng_param_t; + +/** @brief flag to tell driver whether it can sleep */ +extern volatile bool ppt_dlps_mac_idle; + +/** @} End of PPT_Driver_Exported_Types */ + +/** @defgroup PPT_Driver_Exported_Functions Exported Functions + * @brief + * @{ + */ + +/** + * @brief swap bit order of one byte data + * @param[in] inp: the data to be swapped + * @return the new value after swapped bit order + */ +uint8_t ppt_swap_bits8(uint8_t inp); + +/** + * @brief swap bit order of two bytes data + * @param[in] inp: the data to be swapped + * @return the new value after swapped bit order + */ +uint16_t ppt_swap_bits16(uint16_t inp); + +/** + * @brief swap bit order of three bytes data + * @param[in] inp: the data to be swapped + * @return the new value after swapped bit order + */ +uint32_t ppt_swap_bits24(uint32_t inp); + +/** + * @brief swap bit order of four bytes data + * @param[in] inp: the data to be swapped + * @return the new value after swapped bit order + */ +uint32_t ppt_swap_bits32(uint32_t inp); + +/** + * @brief read radio register + * @param[in] offset: the register address + * @return the register value + */ +extern uint16_t (*ppt_read_reg)(uint16_t offset); +#define RD_PPT_REG(offset) ppt_read_reg(offset) + +/** + * @brief write radio register + * @param[in] offset: the register address + * @param[in] data: the register value + * @return none + */ +extern void (*ppt_write_reg)(uint16_t offset, uint16_t data); +#define WR_PPT_REG(offset, data) ppt_write_reg(offset, data) + +/** + * @brief update radio register + * @param[in] offset: the register address + * @param[in] mask: the register mask + * @param[in] data: the register value + * @return none + */ +#define UP_PPT_REG(offset, mask, data) do\ + {\ + uint16_t reg = RD_PPT_REG(offset);\ + reg &= ~(mask);\ + reg |= (data) & (mask);\ + WR_PPT_REG(offset, reg);\ + } while(0) + +/** + * @brief read radio register by specific field + * @param[in] name: the register name + * @param[in] field: the specific field + * @return the field value + */ +#define RD_PPT_REG_FIELD(name, field) ({name##_TYPE reg = {.d16 = RD_PPT_REG(name)}; reg.field;}) + +/** + * @brief write radio register by specific field + * @param[in] name: the register name + * @param[in] field: the specific field + * @param[in] data: the field value + * @return the field value + */ +#define WR_PPT_REG_FIELD(name, field, data) do\ + {\ + name##_TYPE reg = {.d16 = RD_PPT_REG(name)};\ + reg.field = data;\ + WR_PPT_REG(name, reg.d16);\ + } while (0) + +/** + * @brief update radio register by specific field + * @param[in] name: the register address + * @param[in] field: the specific field + * @param[in] mask: the field mask + * @param[in] data: the field value + * @return none + */ +#define UP_PPT_REG_FIELD(name, field, mask, data) do\ + {\ + name##_TYPE reg = {.d16 = RD_PPT_REG(name)};\ + reg.field &= ~(mask);\ + reg.field |= (data) & (mask);\ + WR_PPT_REG(name, reg.d16);\ + } while(0) + +/** + * @brief overwrite radio field value + * @param[in] offset: the register address + * @param[in] field_offset: the field bit offset + * @param[in] field_len: the field bit length + * @param[in] data: the field value + * @return none + */ +#define OV_PPT_REG_FIELD(offset, field_offset, field_len, data) do\ + {\ + uint16_t reg = RD_PPT_REG(offset);\ + reg &= ~(((0xffff >> (16 - (field_len)))) << (field_offset));\ + reg |= (data) << (field_offset);\ + WR_PPT_REG(offset, reg);\ + } while(0) + +/** + * @brief obtain the register offset of the specific entry + * @param[in] entry: the entry of parameter + * @param[in] offset0: the register offset0 + * @param[in] size0: the entry step size0 + * @param[in] offset1: the register offset1 + * @param[in] size0: the entry step size1 + * @return register offset + */ +#define PPT_REG_OFFSET(entry, offset0, size0, offset1, size1) (((entry) < PPT_ENTRY_NUM_ORI) ? ((size0)*(entry) + (offset0)) : ((size1) * ((entry) - PPT_ENTRY_NUM_ORI) + (offset1))) + +/** + * @brief obtain the tx entry in the tx stack information + * @param[in] tx_stack: the @ref PRO_TX_STACK_TYPE register + * @param[in] tx_len: the @ref PRO_TX_LENGTH_TYPE register + */ +#define PPT_TX_STACK_ENTRY(tx_stack, tx_len) (tx_stack.tx_entry_1_0 + (tx_len.tx_entry_2 << 2)) + +/** + * @brief obtain the rx entry in the rx stack information + * @param[in] rx_stack: the @ref PRO_RX_STACK_TYPE register + */ +#define PPT_RX_STACK_ENTRY(rx_stack) (rx_stack.entry_0 + (rx_stack.entry_2_1 << 1)) + +/** + * @brief obtain the header size pushed to the Rx FIFO + * + * The Rx FIFO is filled with the header and the payload of a packet. + * The header contains the header prefix, length and header suffix. + * The total size will be aligned to 16 bits when filling to the Rx FIFO. + * @param[in] hp_size: header prefix size in unit of bit + * @param[in] length_size: length size in unit of bit + * @param[in] hp_size: header suffix size in unit of bit + * @return header size in unit of byte + */ +#define PPT_RX_FIFO_HEADER_SIZE(hp_size, length_size, hs_size) ((((hp_size) + (length_size) + (hs_size) + 15) >> 4) << 1) + +/** + * @brief obtain the header size pushed to the Rx FIFO + * + * The Rx FIFO is filled with the header and the payload of a packet. + * The header contains the header prefix, length and header suffix. + * The total size will be aligned to 16 bits when filling to the Rx FIFO. + * @param[in] hp_size: header prefix size in unit of byte + * @param[in] length_size: length size in unit of byte + * @param[in] hp_size: header suffix size in unit of byte + * @return header size in unit of byte + */ +#define PPT_RX_FIFO_HEADER_SIZE_BYTE(hp_size, length_size, hs_size) PPT_RX_FIFO_HEADER_SIZE(hp_size << 3, length_size << 3, hs_size << 3) + +/** + * @brief enable radio interrupt + * @return none + */ +#define PPT_ISR_ENABLE() NVIC_EnableIRQ(BTMAC_IRQn) + +/** + * @brief disable radio interrupt + * @return none + */ +#define PPT_ISR_DISABLE() NVIC_DisableIRQ(BTMAC_IRQn) + +/** + * @brief initialize the DMA of radio + * @return none + */ +void ppt_init_dma(void); + +/** + * @brief workaround for reset when bzdma start which results in dma carry error later. + * @return none + */ +void ppt_clear_dma_tx_done(void); + +/** + * @brief deinitialize the DMA of radio + * @return none + */ +void ppt_deinit_dma(void); + +/** + * @brief initial the miscellaneous functions + * @return none + */ +void ppt_init_misc(void); + +/** + * @brief deinitial the miscellaneous functions + * @return none + */ +void ppt_deinit_misc(void); + +/** + * @brief reset trx packet number counter of hardware + * @return none + */ +void ppt_reset_trx_pkt_num(void); + +/** + * @brief enable the clock of radio + * @param[in] ppt_mode: true for 2.4G, false for ble + * @return none + */ +void ppt_reset_core_domain(bool ppt_mode); + +/** + * @brief notify 2.4G state to the btmac which may optimize the performance + * @param[in] ppt_mode: true for 2.4G enable, false for 2.4G disable + * @return none + */ +void ppt_notify_btmac(bool ppt_mode); + +/** + * @brief execute instruction to switch the radio state + * @param[in] instruction_code: instruction opcode @ref ppt_hw_instruction_t + * @return none + */ +void ppt_execute_instruction(uint8_t instruction_code); + +/** + * @brief clear radio state + * @deprecated no used + * @return none + */ +#define ppt_clear_radio() +#define ppt_clear_radio_quick(...) + +/** + * @brief lock/unlock the header fields value + * + * Since the the header has multiple fields, they can be written in the atomic way after lock. + * @param[in] entry: channel index + * @param[in] lock: true for lock, false for unlock + * @return none + */ +void ppt_lock(uint8_t entry, bool lock); + +/** + * @brief set whether to holding tx automatically + * @param[in] entry: channel index + * @param[in] enable: feature value + * @return none + */ +void ppt_set_auto_no_tx(uint8_t entry, bool enable); + +/** + * @brief clear hardware holding tx once + * @param[in] entry: channel index + * @return none + */ +void ppt_clear_hw_no_tx(uint8_t entry); + +/** + * @brief set the feature of hardware auto ack the transmitted packet + * @param[in] entry: channel index + * @param[in] enable: feature value + * @return none + */ +void ppt_set_auto_ack(uint8_t entry, bool enable); + +/** + * @brief firmware ack the transmitted packet once with lock flag + * @param[in] entry: channel index + * @param[in] lock: lock the header and tx fifo + * @return tx fifo read pointer + */ +uint8_t ppt_trigger_fw_ack_lock(uint8_t entry, bool lock); + +/** + * @brief firmware ack the transmitted packet once + * @param[in] entry: channel index + * @return tx fifo read pointer + */ +#define ppt_trigger_fw_ack(entry) ppt_trigger_fw_ack_lock(entry, true) + +/** + * @brief firmware force ack the first packet + * + * PRX role may use this api to quit data pushed previously. + * @param[in] entry: channel index + * @return tx fifo read pointer + */ +uint8_t ppt_force_fw_ack(uint8_t entry); + +/** + * @brief register the interrupt handler + * @param[in] handler: the function pointer of ISR + * @return none + */ +void ppt_reg_handler(void (*handler)(void)); + +/** + * @brief register the psd interrupt handler + * @param[in] handler: the function pointer of ISR + * @return none + */ +void ppt_reg_psd_handler(void (*handler)(void)); + +/** + * @brief set crc common parameters + * + * @attention crc including address field is not supported. + * It can be as a workaround to replace the crc init by a new value which is calculated by crc check the address with the crc init. + * @param[in] param: parameters + * @return none + */ +void ppt_set_crc_param(ppt_crc_param_t *param); + +/** + * @brief set crc channel specific parameters + * @param[in] entry: channel index + * @param[in] param: parameters + * @return none + */ +void ppt_set_crc_entry_param(uint8_t entry, ppt_crc_entry_param_t *param); + +/** + * @brief set whitening common parameters + * @param[in] param: parameters + * @return none + */ +void ppt_set_white_param(ppt_white_param_t *param); + +/** + * @brief set whitening channel specific parameters + * @param[in] entry: channel index + * @param[in] param: parameters + * @return none + */ +void ppt_set_white_entry_param(uint8_t entry, ppt_white_entry_param_t *param); + +/** + * @brief set rx phy + * @param[in] rx_phy: phy type + * @return none + */ +void ppt_set_phy_rx_type(ppt_phy_type_t rx_phy); + +/** + * @brief set tx phy + * @param[in] entry: channel index + * @param[in] tx_phy: phy type + * @return none + */ +void ppt_set_phy_tx_type(uint8_t entry, ppt_phy_type_t tx_phy); + +/** + * @brief set phy common parameters + * @param[in] param: parameters + * @return none + */ +void ppt_set_phy_param(ppt_phy_param_t *param); + +/** + * @brief set modulation index of 2M phy + * @param[in] change: change default value + * @return none + */ +void ppt_set_phy_mod_index_2m(bool change); + +/** + * @brief set phy parameters for different rf bank + * + * Currently modulation tx parameters are updated by this function, so only tx needs these settings. + * + * @param[in] bank_idx: 0 for 2402~2480MHz, 1 for 2348~2426MHz, 2 for 2452~2530MHz + * @return none + */ +void ppt_set_phy_bank(uint8_t bank_idx); + +/** + * @brief set phy channel + * + * It will call ppt_set_phy_bank to update phy parameters at the same time. + * + * @param[in] freq_mhz: 2348~2530MHz + * @return set result + */ +bool ppt_set_phy_channel(uint16_t freq_mhz); + +/** + * @brief set phy channel specific parameters + * @param[in] entry: channel index + * @param[in] param: parameters + * @return none + */ +void ppt_set_phy_entry_param(uint8_t entry, ppt_phy_entry_param_t *param); + +/** + * @brief set packet format parameters + * @param[in] param: parameters + * @return none + */ +void ppt_set_pkt_format(ppt_pkt_format_t *param); + +/** + * @brief set preamble length + * @param[in] entry: channel index + * @param[in] preamble_len: length in unit of byte + * @return none + */ +void ppt_set_preamble_len(uint8_t entry, uint8_t preamble_len); + +/** + * @brief set addon field parameters + * @param[in] entry: channel index + * @param[in] param: parameters + * @return none + */ +void ppt_set_addon_len(uint8_t entry, ppt_addon_length_t *param); + +/** + * @brief set rf tx power + * @param[in] tx_gain: tx gain value @ref ppt_tx_gain_t + * @return none + */ +void ppt_set_tx_power(uint8_t tx_gain); + +/** + * @brief set rf tx power + * @param[in] tx_power_dbm: tx power in unit of dbm + * @return none + */ +void ppt_set_tx_power_dbm(float tx_power_dbm); + +/** + * @brief set tx access address + * @param[in] entry: channel index + * @param[in] param: parameters + * @return none + */ +void ppt_set_tx_addr(uint8_t entry, ppt_tx_addr_t *param); + +/** + * @brief set rx access address + * + * The caller shall check whether any address value is 0xff or two rx addresses values are similar. + * The access address shall be chotic as the definition in BT specification. + * If not, the radio parameter need be changed to receive the packets successfully. + * But this will decrease the rx sensitivity. + * + * The radio parameter can be updated by @ref ppt_check_rx_addr. + * @param[in] entry: channel index + * @param[in] param: parameters + * @return none + */ +void ppt_set_rx_addr(uint8_t entry, ppt_rx_addr_t *param); + +/** + * @brief check rx access address and set radio paramters + * + * If any address value is 0xff or two rx addresses values are similar, this function will set the radio parameters. + * Since the parameters are set according to the choosen rx PHY, this function shall be called + * after both the address and rx PHY are set. + * @param[in] bit_th: bit difference threshold, recommend to use 5 + * @return none + */ +void ppt_check_rx_addr(uint8_t bit_th); + +/** + * @brief set ptx modes + * @param[in] param: parameters + * @return none + */ +void ppt_set_ptx_mode(ppt_ptx_mode_t *param); + +/** + * @brief set prx modes + * @param[in] param: parameters + * @return none + */ +void ppt_set_prx_mode(ppt_prx_mode_t *param); + +/** + * @brief set psd modes + * @param[in] param: psd parameters + * @return none + */ +void ppt_set_psd_mode(ppt_psd_mode_t *param); + +/** + * @brief set tx header prefix field + * @param[in] entry: channel index + * @param[in] hp: header prefix + * @return none + */ +void ppt_set_hp(uint8_t entry, uint8_t hp); + +/** + * @brief set tx header length field + * + * The value of the length field indicates the octet length of the payload. + * But this value is useless if dma_length_mode is enabled (which is default on) which use dma length instead. + * @param[in] entry: channel index + * @param[in] length: payload length + * @return none + */ +void ppt_set_length(uint8_t entry, uint16_t length); + +/** + * @brief set tx header suffix field + * @param[in] entry: channel index + * @param[in] hs: header suffix + * @return none + */ +void ppt_set_hs(uint8_t entry, uint32_t hs); + +/** + * @brief set tx header field value + * @param[in] entry: channel index + * @param[in] param: parameters + * @return none + */ +void ppt_set_tx_header(uint8_t entry, ppt_header_t *param); + +/** + * @brief set rf turn around time + * + * If not set, the default value is 150us. + * @param[in] tifs_us: tifs value in microsecond + * @return none + */ +void ppt_set_tifs(uint8_t tifs_us); + +/** + * @brief set timing latch parameters + * @param[in] param: parameters + * @return none + */ +void ppt_set_timing_latch(ppt_timing_latch_t *param); + +/** + * @brief set gpio trigger common parameters + * @param[in] param: parameters + * @return none + */ +void ppt_set_gpio_param(ppt_gpio_param_t *param); + +/** + * @brief set gpio trigger channel specific parameters + * @param[in] entry: channel index + * @param[in] param: parameters + * @return none + */ +void ppt_set_gpio_entry_param(uint8_t entry, ppt_gpio_entry_param_t *param); + +/** + * @brief push the payload field to the tx fifo + * + * The hardware won't copy the data, so the data need be valid until it is acknoledged. + * The other fields will be filled to the transmitted frame automatically by the hardware. + * @param[in] entry: channel index + * @param[in] payload: data pointer + * @param[in] payload_len: length of payload + * @return none + */ +bool ppt_push_tx_fifo(uint8_t entry, uint8_t *payload, uint16_t payload_len); + +/** + * @brief update the payload field to the tx fifo + * + * The hardware won't copy the data, so the data need be valid until it is acknoledged. + * The other fields will be filled to the transmitted frame automatically by the hardware. + * @param[in] entry: channel index + * @param[in] payload: data pointer + * @param[in] payload_len: length of payload + * @return none + */ +bool ppt_update_tx_fifo(uint8_t entry, uint8_t *payload, uint16_t payload_len); + +/** + * @brief flush the tx fifo + * @param[in] entry: channel index + * @return read pointer + */ +uint8_t ppt_flush_tx_fifo(uint8_t entry); + +/** + * @brief get the tx fifo read pointer + * @param[in] entry: channel index + * @return read pointer + */ +uint8_t ppt_get_tx_fifo_rdptr(uint8_t entry); + +/** + * @brief set the tx fifo read pointer + * @param[in] entry: channel index + * @param[in] ptr: where to start tx next time + * @return none + */ +void ppt_set_tx_fifo_rdptr(uint8_t entry, uint8_t ptr); + +/** + * @brief get the tx fifo write pointer + * @param[in] entry: channel index + * @return write pointer + */ +uint8_t ppt_get_tx_fifo_wrptr(uint8_t entry); + +/** + * @brief reset the tx fifo sw & hw state + * + * The read and write pointer will be set to zero, and the fifo will be empty. + * @param[in] entry: channel index + * @return none + */ +void ppt_reset_tx_fifo(uint8_t entry); + +/** + * @brief pop the received pdu from the rx fifo + * + * The rx fifo contains the PDU data including the header fields and payload field. + * @param[in] entry: channel index + * @param[out] pdu: data pointer + * @param[in] pdu_len: length of pdu, attained from the rx stack information + * @return none + */ +bool ppt_pop_rx_fifo(uint8_t entry, uint8_t *pdu, uint16_t pdu_len); + +/** + * @brief flush the rx fifo + * + * Since the receiving state may be disrupted, some residual data needs be flushed from the rx fifo. + * @return none + */ +void ppt_flush_rx_fifo(void); + +/** + * @brief flush the pending tx & rx interrupt + * + * The tx & rx interrupt isn't cared about, so flush them. + * @return none + */ +void ppt_flush_trx_int(void); + +/** + * @brief get rssi dbm value + * @param[in] rssi_raw: rssi register value + * @return the value + */ +int8_t ppt_get_rssi(uint16_t rssi_raw); + +/** + * @brief get channel setting from radio frequncy + * @param[in] frequency: radio frequency in MHz + * @param[out] bank: frequency band index + * @param[out] channel: frequency offset + * @return get result + * @retval true: the input radio frequency is supported by the module + * @retval false: the input raido frequency isn't supported by the module + */ +bool ppt_get_bank_channel(uint16_t frequency, uint8_t *bank, uint8_t *channel); + +/** + * @brief get ble logic channel + * @param[in] bank: frequency band index + * @param[in] channel: frequency offset + * @return logic channel index + * @retval >= 0: the input channel is supported by ble + * @retval < 0: the input channel isn't supported by ble + */ +int8_t ppt_get_ble_logic_chan(uint8_t bank, uint8_t channel); + +/** + * @brief get ble logic channel + * @param[in] frequency: frequency in MHz + * @return logic channel index + * @retval >= 0: the input channel is supported by ble + * @retval < 0: the input channel isn't supported by ble + */ +int8_t ppt_get_ble_logic_chan_via_freq(uint16_t frequency); + +/** + * @brief get whitening init value from ble logic channel + * @param[in] le_logic_chan: ble logic channel + * @return whitening init value + */ +uint32_t ppt_get_ble_white_init(uint8_t le_logic_chan); + +/** + * @brief format diagnose output with raw data + * @param[in] data: raw data + * @param[in] data_len: raw data length + * @param[in] fmt: format string + * @return none + */ +void ppt_dump_log(uint8_t *data, uint32_t data_len, char *fmt, ...); + +/** + * @brief dump all non-zero register + * @return none + */ +void ppt_dump_nonzero_reg(void); + +/** + * @brief calculate the crc of the designated data + * @param[in] param: the crc paramters + * @param[in] data: raw data + * @param[in] data_len: the data length in bytes for byte mode and in bits for bit mode + * @return the CRC result + */ +uint32_t ppt_crc_eng_cal(ppt_crc_eng_param_t *param, uint8_t *data, uint32_t data_len); + +/** + * @brief initialize the dlps setting + * + * This api shall be called early before enter dlps, for example in the pwr_mgr_init. + * @return none + */ +void ppt_dlps_init(void); + +/** + * @brief deinitialize the dlps setting when disable 2.4g module + * @return none + */ +void ppt_dlps_deinit(void); + +/** + * @brief register function that check wheather the 2.4g module can enter sleep mode + * @param[in] check_cb: dlps enter check callback function pointer + * @return none + */ +void ppt_dlps_reg_mac_check_cb(bool (*check_cb)(uint32_t *wakeup_time_diff)); + +/** + * @brief register function that store some setting when mac enter dlps + * @param[in] enter_cb: dlps enter store function pointer + * @return none + */ +void ppt_dlps_reg_mac_enter_cb(void (*enter_cb)(void)); + +/** + * @brief register function that restore some setting when mac exit dlps + * @param[in] exit_cb: dlps exit restore function pointer + * @return none + */ +void ppt_dlps_reg_mac_exit_cb(void (*exit_cb)(void)); + +/** + * @brief register function that store some setting when enter dlps + * @param[in] enter_cb: dlps enter store function pointer + * @return none + */ +void ppt_dlps_reg_pf_enter_cb(void (*enter_cb)(void)); + +/** + * @brief register function that restore some setting when exit dlps + * @param[in] exit_cb: dlps exit restore function pointer + * @return none + */ +void ppt_dlps_reg_pf_exit_cb(void (*exit_cb)(void)); + +/** @} End of PPT_Driver_Exported_Functions */ + +///@cond +#define TIME_DEBUG 0 + +#if TIME_DEBUG +#include "rtl_rcc.h" +#include "rtl_pinmux.h" +#include "rtl_gpio.h" + +#define TEST_PIN P2_2, P2_3, P2_4, P2_5 +#define TIME_DEBUG_CHAN_INVALID -1 +#define TIME_DEBUG_CHAN_THREAD 0 +#define TIME_DEBUG_CHAN_ISR 1 +#define TIME_DEBUG_CHAN_ISR_TX 1 +#define TIME_DEBUG_CHAN_ISR_RX 1 +#define TIME_DEBUG_CHAN_ISR_GPIO 2 +#define TIME_DEBUG_CHAN_TIMING 3 +#define TIME_DEBUG_CHAN_DLPS -1 + +extern uint8_t test_pin[]; +extern uint32_t gpio_test_pin[]; +extern bool level_test_pin[]; +#define TIME_DEBUG_CHAN_NUMBER COUNT_ARG(TEST_PIN) +void ppt_init_time_debug(void); + +#define time_debug_level_high(ch) do \ + { \ + if(ch >= 0 && ch < TIME_DEBUG_CHAN_NUMBER) \ + {\ + GPIOA->GPIO_DR |= gpio_test_pin[ch]; \ + level_test_pin[ch] = TRUE; \ + }\ + }while(0) +#define time_debug_level_low(ch) do \ + { \ + if(ch >= 0 && ch < TIME_DEBUG_CHAN_NUMBER) \ + {\ + GPIOA->GPIO_DR &= ~gpio_test_pin[ch]; \ + level_test_pin[ch] = FALSE; \ + }\ + }while(0) +#define time_debug_edge_up(ch) do \ + { \ + if(ch >= 0 && ch < TIME_DEBUG_CHAN_NUMBER) \ + {\ + GPIOA->GPIO_DR &= ~gpio_test_pin[ch]; \ + GPIOA->GPIO_DR |= gpio_test_pin[ch]; \ + level_test_pin[ch] = TRUE; \ + }\ + }while(0) +#define time_debug_edge_down(ch) do \ + { \ + if(ch >= 0 && ch < TIME_DEBUG_CHAN_NUMBER) \ + {\ + GPIOA->GPIO_DR |= gpio_test_pin[ch]; \ + GPIOA->GPIO_DR &= ~gpio_test_pin[ch]; \ + level_test_pin[ch] = FALSE; \ + }\ + }while(0) +#else +#define time_debug_level_high(...) +#define time_debug_level_low(...) +#define time_debug_edge_up(...) +#define time_debug_edge_down(...) +#endif +void ppt_dbg_port_open(uint16_t bt_port, uint16_t ppt_port, uint16_t ppt_port2); +void ppt_dbg_port_set_pin(uint8_t pin_group, uint32_t dbg_bitmap); +void ppt_dbg_port(uint16_t bt_port, uint16_t ppt_port, uint16_t ppt_port2, uint32_t dbg_bitmap); +///@endcond + +/** @} End of PPT_Driver */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/bee/drivers/ppt/driver/common/ppt_hw_reg.h b/bee/drivers/ppt/driver/common/ppt_hw_reg.h new file mode 100644 index 00000000..4fafe0c7 --- /dev/null +++ b/bee/drivers/ppt/driver/common/ppt_hw_reg.h @@ -0,0 +1,3896 @@ +/* based on formal_reg_230606.xlsx */ + +#define PRO_INSTRUCTION 0x0 +#define PRO_BASE0_LOWER 0x4 +#define PRO_BASE0_UPPER 0x6 +#define PRO_BASE1_LOWER 0x8 +#define PRO_BASE1_UPPER 0xa +#define PRO_PREFIX0_1 0xc +#define PRO_PREFIX2_3 0xe +#define PRO_PREFIX4_5 0x10 +#define PRO_PREFIX6_7 0x12 +#define PRO_TX_ADDRESS_LOWER 0x14 +#define PRO_TX_ADDRESS_MIDDLE 0x16 +#define PRO_TX_ADDRESS_UPPER 0x18 +#define PRO_TX_CONTROL 0x20 +#define PRO_PERIODIC_INTERVAL 0x22 +#define PRO_GPIO_TX_DELAY 0x24 +#define PRO_RX_CONTROL 0x26 +#define PRO_RX_MATCH_CONTROL 0x28 +#define PRO_TRX_CONTROL 0x2a +#define PRO_FIELD_LENGTH2 0x2c +#define PRO_FIELD_LENGTH 0x30 +#define PRO_PACKET_CONTROL 0x32 +#define PRO_GAIN 0x34 +#define PRO_TX_PKT_NUM 0x36 +#define PRO_TX_PKT_NUM2 0x38 +#define PRO_HS_LENGTH 0x3a +#define PRO_CHANNEL_BANK 0x3c +#define PRO_GPIO_CONTROL 0x3e +#define PRO_MISR 0x40 +#define PRO_IMR 0x42 +#define PRO_RSSI 0x4e +#define PRO_LENGTH_INCLUDE_ADDON 0x50 +#define PRO_LENGTH 0x52 +#define PRO_RX_STACK 0x54 +#define PRO_RX_HP 0x56 +#define PRO_RX_CRC_LOWER 0x58 +#define PRO_RX_CRC_UPPER 0x5a +#define PRO_ACCHIT_CLK_LOWER 0x5c +#define PRO_ACCHIT_CLK_UPPER 0x5e +#define PRO_RX_HS_LOWER 0x60 +#define PRO_RX_HS_UPPER 0x62 +#define PRO_TX_STACK 0x64 +#define PRO_TX_HS_LOWER 0x66 +#define PRO_TX_HS_UPPER 0x68 +#define PRO_TX_LENGTH 0x6a +#define PRO_TX_CLK_LOWER 0x6c +#define PRO_TX_CLK_UPPER 0x6e +#define PRO_HP_0 0x80 +#define PRO_HS_0_LOWER 0x82 +#define PRO_HS_0_UPPER 0x84 +#define PRO_LENGTH_0 0x86 +#define PRO_CRC_INIT0_LOWER 0x88 +#define PRO_CRC_INIT0_UPPER 0x8a +#define PRO_CRC_POLYNOMIAL_REG0_LOWER 0x8c +#define PRO_CRC_POLYNOMIAL_REG0_UPPER 0x8e +#define PRO_PACKET_RELATED_CONTROL0 0x90 +#define PRO_ADD_ON_LENGTH0 0x92 +#define PRO_WHITE_INIT0_LOWER 0x94 +#define PRO_WHITE_INIT0_UPPER 0x96 +#define PRO_WHITE_POLYNOMIAL_REG0_LOWER 0x98 +#define PRO_WHITE_POLYNOMIAL_REG0_UPPER 0x9a +#define PRO_HP_1 0xa0 +#define PRO_HS_1_LOWER 0xa2 +#define PRO_HS_1_UPPER 0xa4 +#define PRO_LENGTH_1 0xa6 +#define PRO_CRC_INIT1_LOWER 0xa8 +#define PRO_CRC_INIT1_UPPER 0xaa +#define PRO_CRC_POLYNOMIAL_REG1_LOWER 0xac +#define PRO_CRC_POLYNOMIAL_REG1_UPPER 0xae +#define PRO_PACKET_RELATED_CONTROL1 0xb0 +#define PRO_ADD_ON_LENGTH1 0xb2 +#define PRO_WHITE_INIT1_LOWER 0xb4 +#define PRO_WHITE_INIT1_UPPER 0xb6 +#define PRO_WHITE_POLYNOMIAL_REG1_LOWER 0xb8 +#define PRO_WHITE_POLYNOMIAL_REG1_UPPER 0xba +#define PRO_HP_2 0xc0 +#define PRO_HS_2_LOWER 0xc2 +#define PRO_HS_2_UPPER 0xc4 +#define PRO_LENGTH_2 0xc6 +#define PRO_CRC_INIT2_LOWER 0xc8 +#define PRO_CRC_INIT2_UPPER 0xca +#define PRO_CRC_POLYNOMIAL_REG2_LOWER 0xcc +#define PRO_CRC_POLYNOMIAL_REG2_UPPER 0xce +#define PRO_PACKET_RELATED_CONTROL2 0xd0 +#define PRO_ADD_ON_LENGTH2 0xd2 +#define PRO_WHITE_INIT2_LOWER 0xd4 +#define PRO_WHITE_INIT2_UPPER 0xd6 +#define PRO_WHITE_POLYNOMIAL_REG2_LOWER 0xd8 +#define PRO_WHITE_POLYNOMIAL_REG2_UPPER 0xda +#define PRO_RESET_CTRL_REG 0xdc +#define PRO_GPIO_CTRL_REG 0xde +#define PRO_TX_ADDRESS2_LOWER 0xe0 +#define PRO_TX_ADDRESS2_MIDDLE 0xe2 +#define PRO_TX_ADDRESS2_UPPER 0xe4 +#define PRO_ORDER_CONTROL 0xe6 +#define PRO_GPIO_CTRL1_REG 0xe8 +#define PRO_GPIO_CTRL2_REG 0xea +#define PRO_GPIO_NATIVE_CNT 0xec +#define PRO_MAX_LENGTH 0xee +#define PRO_RX_TURN_AROUND_DELAY 0x100 +#define PRO_2M_TRX_TURN_AROUND_DELAY 0x102 +#define PRO_1M_2M_TRX_TURN_AROUND_DELAY 0x104 +#define PRO_TX_TURN_AROUND_DELAY 0x106 +#define PRO_RX_TIMEOUT_DELAY 0x108 +#define PRO_TRX_ON_DELAY 0x10a +#define PRO_2M_TRX_ON_DELAY 0x10c +#define PRO_TRX_DEALY_MISC 0x10e +#define PRO_PSD_RANGE0 0x110 +#define PRO_PSD_RANGE1 0x112 +#define PRO_PSD_TIMEOUT 0x114 +#define PRO_INT_CTRL 0x118 +#define PRO_GPIO_TX_DELAY1 0x11a +#define PRO_INT_CTRL_TX 0x11c +#define PRO_GPIO_TX_DELAY2 0x11e +#define PRO_CBK_CTRL 0x120 +#define PRO_TRX_AFE 0x122 +#define PRO_DEBUG_SEL 0x124 +#define PRO_DEBUG_SEL2 0x126 +#define PRO_DSM_READ 0x128 +#define PRO_DSM_READ1 0x12a +#define PRO_CRC_ENGINE_INIT 0x12c +#define PRO_CRC_ENGINE_INIT1 0x12e +#define PRO_CRC_ENGINE_POLY 0x130 +#define PRO_CRC_ENGINE_POLY1 0x132 +#define PRO_CRC_ENGINE_IN 0x134 +#define PRO_CRC_ENGINE_IN1 0x136 +#define PRO_CRC_ENGINE_IN2 0x138 +#define PRO_CRC_ENGINE_OUT 0x13a +#define PRO_CRC_ENGINE_OUT1 0x13c +#define PRO_CRC_ENGINE_EN 0x13e +#define PRO_RX_CRC_INIT0_LOWER 0x140 +#define PRO_RX_CRC_INIT0_UPPER 0x142 +#define PRO_RX_CRC_INIT1_LOWER 0x144 +#define PRO_RX_CRC_INIT1_UPPER 0x146 +#define PRO_RX_CRC_INIT2_LOWER 0x148 +#define PRO_RX_CRC_INIT2_UPPER 0x14a +#define PRO_HP_3 0x14c +#define PRO_HP_4 0x14e +#define PRO_HP_5 0x150 +#define PRO_HS_3_LOWER 0x152 +#define PRO_HS_3_UPPER 0x154 +#define PRO_HS_4_LOWER 0x156 +#define PRO_HS_4_UPPER 0x158 +#define PRO_HS_5_LOWER 0x15a +#define PRO_HS_5_UPPER 0x15c +#define PRO_HS_6_LOWER 0x15e +#define PRO_HS_6_UPPER 0x160 +#define PRO_HS_7_LOWER 0x162 +#define PRO_HS_7_UPPER 0x164 +#define PRO_LENGTH_3 0x166 +#define PRO_LENGTH_4 0x168 +#define PRO_LENGTH_5 0x16a +#define PRO_LENGTH_6 0x16c +#define PRO_LENGTH_7 0x16e +#define PRO_ADD_ON_LENGTH3 0x170 +#define PRO_ADD_ON_LENGTH4 0x172 +#define PRO_ADD_ON_LENGTH5 0x174 +#define PRO_CRC_INIT3_LOWER 0x176 +#define PRO_CRC_INIT3_UPPER 0x178 +#define PRO_CRC_INIT4_LOWER 0x17a +#define PRO_CRC_INIT4_UPPER 0x17c +#define PRO_CRC_INIT5_LOWER 0x17e +#define PRO_CRC_INIT5_UPPER 0x180 +#define PRO_CRC_INIT6_LOWER 0x182 +#define PRO_CRC_INIT6_UPPER 0x184 +#define PRO_CRC_INIT7_LOWER 0x186 +#define PRO_CRC_INIT7_UPPER 0x188 +#define PRO_RX_CRC_INIT3_LOWER 0x18a +#define PRO_RX_CRC_INIT3_UPPER 0x18c +#define PRO_RX_CRC_INIT4_LOWER 0x18e +#define PRO_RX_CRC_INIT4_UPPER 0x190 +#define PRO_RX_CRC_INIT5_LOWER 0x192 +#define PRO_RX_CRC_INIT5_UPPER 0x194 +#define PRO_RX_CRC_INIT6_LOWER 0x196 +#define PRO_RX_CRC_INIT6_UPPER 0x198 +#define PRO_RX_CRC_INIT7_LOWER 0x19a +#define PRO_RX_CRC_INIT7_UPPER 0x19c +#define PRO_WHITE_INIT3_LOWER 0x19e +#define PRO_WHITE_INIT3_UPPER 0x1a0 +#define PRO_WHITE_INIT4_LOWER 0x1a2 +#define PRO_WHITE_INIT4_UPPER 0x1a4 +#define PRO_WHITE_INIT5_LOWER 0x1a6 +#define PRO_WHITE_INIT5_UPPER 0x1a8 +#define PRO_WHITE_INIT6_LOWER 0x1aa +#define PRO_WHITE_INIT6_UPPER 0x1ac +#define PRO_WHITE_INIT7_LOWER 0x1ae +#define PRO_WHITE_INIT7_UPPER 0x1b0 +#define PRO_WHITE_POLYNOMIAL_REG3_LOWER 0x1b2 +#define PRO_WHITE_POLYNOMIAL_REG3_UPPER 0x1b4 +#define PRO_WHITE_POLYNOMIAL_REG4_LOWER 0x1b6 +#define PRO_WHITE_POLYNOMIAL_REG4_UPPER 0x1b8 +#define PRO_WHITE_POLYNOMIAL_REG5_LOWER 0x1ba +#define PRO_WHITE_POLYNOMIAL_REG5_UPPER 0x1bc +#define PRO_WHITE_POLYNOMIAL_REG6_LOWER 0x1be +#define PRO_WHITE_POLYNOMIAL_REG6_UPPER 0x1c0 +#define PRO_WHITE_POLYNOMIAL_REG7_LOWER 0x1c2 +#define PRO_WHITE_POLYNOMIAL_REG7_UPPER 0x1c4 +#define PRO_CRC_POLYNOMIAL_REG3_LOWER 0x1c6 +#define PRO_CRC_POLYNOMIAL_REG3_UPPER 0x1c8 +#define PRO_CRC_POLYNOMIAL_REG4_LOWER 0x1ca +#define PRO_CRC_POLYNOMIAL_REG4_UPPER 0x1cc +#define PRO_CRC_POLYNOMIAL_REG5_LOWER 0x1ce +#define PRO_CRC_POLYNOMIAL_REG5_UPPER 0x1d0 +#define PRO_CRC_POLYNOMIAL_REG6_LOWER 0x1d2 +#define PRO_CRC_POLYNOMIAL_REG6_UPPER 0x1d4 +#define PRO_CRC_POLYNOMIAL_REG7_LOWER 0x1d6 +#define PRO_CRC_POLYNOMIAL_REG7_UPPER 0x1d8 +#define PRO_RX_PKT_NUM0 0x1da +#define PRO_RX_PKT_NUM1 0x1dc +#define PRO_RX_PKT_NUM2 0x1de +#define PRO_TX_PKT_NUM3 0x1e0 +#define PRO_TX_PKT_NUM4 0x1e2 +#define PRO_TX_PKT_NUM5 0x1e4 +#define PRO_WHITE_FIELD_LENGTH_0 0x1e6 +#define PRO_WHITE_FIELD_LENGTH_1 0x1e8 +#define PRO_WHITE_FIELD_LENGTH_2 0x1ea +#define PRO_WHITE_FIELD_LENGTH_3 0x1ec +#define PRO_WHITE_FIELD_LENGTH_4 0x1ee +#define PRO_FIELD_LENGTH3 0x1f0 +#define PRO_FIELD_LENGTH4 0x1f2 +#define PRO_FIELD_LENGTH5 0x1f4 +#define PRO_FIELD_LENGTH6 0x1f6 +#define PRO_FIELD_LENGTH7 0x1f8 +#define PRO_TX_ADDRESS1_LOWER 0x1fa +#define PRO_TX_ADDRESS1_MIDDLE 0x1fc +#define PRO_TX_ADDRESS1_UPPER 0x1fe +#define PRO_TX_ADDRESS3_LOWER 0x200 +#define PRO_TX_ADDRESS3_MIDDLE 0x202 +#define PRO_TX_ADDRESS3_UPPER 0x204 +#define PRO_TX_ADDRESS4_LOWER 0x206 +#define PRO_TX_ADDRESS4_MIDDLE 0x208 +#define PRO_TX_ADDRESS4_UPPER 0x20a +#define PRO_TX_ADDRESS5_LOWER 0x20c +#define PRO_TX_ADDRESS5_MIDDLE 0x20e +#define PRO_TX_ADDRESS5_UPPER 0x210 +#define PRO_TX_ADDRESS6_LOWER 0x212 +#define PRO_TX_ADDRESS6_MIDDLE 0x214 +#define PRO_TX_ADDRESS6_UPPER 0x216 +#define PRO_TX_ADDRESS7_LOWER 0x218 +#define PRO_TX_ADDRESS7_MIDDLE 0x21a +#define PRO_TX_ADDRESS7_UPPER 0x21c +#define PRO_RD_PTR_0 0x21e +#define PRO_RD_PTR_1 0x220 +#define PRO_REG_TOTAL_SIZE (PRO_RD_PTR_1 + 2) + +/* 0x0 + 7:0 RW instruction 0x0 + 15:8 RO rsvd 0x0 + */ +typedef union _PRO_INSTRUCTION_TYPE +{ + uint16_t d16; + struct + { + uint16_t instruction: 8; + uint16_t rsvd: 8; + }; +} PRO_INSTRUCTION_TYPE; + +/* 0x4 + 15:0 RW base0[15:0] 0x0 + */ +typedef union _PRO_BASE0_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t base0_15_0; + }; +} PRO_BASE0_LOWER_TYPE; + +/* 0x6 + 15:0 RW base0[31:16] 0x0 + */ +typedef union _PRO_BASE0_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t base0_31_16; + }; +} PRO_BASE0_UPPER_TYPE; + +/* 0x8 + 15:0 RW base1[15:0] 0x0 + */ +typedef union _PRO_BASE1_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t base1_15_0; + }; +} PRO_BASE1_LOWER_TYPE; + +/* 0xa + 15:0 RW base1[31:16] 0x0 + */ +typedef union _PRO_BASE1_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t base1_31_16; + }; +} PRO_BASE1_UPPER_TYPE; + +/* 0xc + 7:0 RW prefix0[7:0] 0x0 + 15:8 RW prefix1[7:0] 0x0 + */ +typedef union _PRO_PREFIX0_1_TYPE +{ + uint16_t d16; + struct + { + uint16_t prefix0_7_0: 8; + uint16_t prefix1_7_0: 8; + }; +} PRO_PREFIX0_1_TYPE; + +/* 0xe + 7:0 RW prefix2[7:0] 0x0 + 15:8 RW prefix3[7:0] 0x0 + */ +typedef union _PRO_PREFIX2_3_TYPE +{ + uint16_t d16; + struct + { + uint16_t prefix2_7_0: 8; + uint16_t prefix3_7_0: 8; + }; +} PRO_PREFIX2_3_TYPE; + +/* 0x10 + 7:0 RW prefix4[7:0] 0x0 + 15:8 RW prefix5[7:0] 0x0 + */ +typedef union _PRO_PREFIX4_5_TYPE +{ + uint16_t d16; + struct + { + uint16_t prefix4_7_0: 8; + uint16_t prefix5_7_0: 8; + }; +} PRO_PREFIX4_5_TYPE; + +/* 0x12 + 7:0 RW prefix6[7:0] 0x0 + 8 RW length_order_first_rx 0x0 + 9 RW length_split_first_rx 0x0 + 10 RW hp_order_first_rx 0x0 + 11 RW hp_split_first_rx 0x0 + 12 RW hs_order_first_rx 0x0 + 13 RW hs_split_first_rx 0x0 + 15:14 RO rsvd 0x0 + */ +typedef union _PRO_PREFIX6_7_TYPE +{ + uint16_t d16; + struct + { + uint16_t prefix6_7_0: 8; + uint16_t length_order_first_rx: 1; + uint16_t length_split_first_rx: 1; + uint16_t hp_order_first_rx: 1; + uint16_t hp_split_first_rx: 1; + uint16_t hs_order_first_rx: 1; + uint16_t hs_split_first_rx: 1; + uint16_t rsvd: 2; + }; +} PRO_PREFIX6_7_TYPE; + +/* 0x14 + 15:0 RW tx_address[15:0] 0x0 + */ +typedef union _PRO_TX_ADDRESS_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t tx_address_15_0; + }; +} PRO_TX_ADDRESS_LOWER_TYPE; + +/* 0x16 + 15:0 RW tx_address[31:16] 0x0 + */ +typedef union _PRO_TX_ADDRESS_MIDDLE_TYPE +{ + uint16_t d16; + struct + { + uint16_t tx_address_31_16; + }; +} PRO_TX_ADDRESS_MIDDLE_TYPE; + +/* 0x18 + 7:0 RW tx_address[39:32] 0x0 + 15:8 RW prefix7[7:0] 0x0 + */ +typedef union _PRO_TX_ADDRESS_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t tx_address_39_32: 8; + uint16_t prefix7_7_0: 8; + }; +} PRO_TX_ADDRESS_UPPER_TYPE; + +/* 0x20 + 0 RW periodic_enable 0x0 + 1 RW no_tx0 0x0 + 2 RW auto_no_tx_option0 0x0 + 3 RW lock0 0x0 + 4 RW fix_tx_address_option 0x0 + 5 RW empty_flag1 0x0 + 6 RW clear_hw_no_tx1 0x0 + 7 RW clear_hw_rd_ptr0 0x0 + 8 RW clear_hw_rd_ptr1 0x0 + 9 RW clear_hw_no_tx0 0x0 + 10 RO read_clear_hw_rd_ptr0 0x0 + 11 RO read_clear_hw_rd_ptr1 0x0 + 12 RO read_clear_hw_no_tx0 0x0 + 13 RO read_clear_hw_no_tx1 0x0 + 14 RW empty_flag0 0x0 + 15 RW lock1 0x0 + */ +typedef union _PRO_TX_CONTROL_TYPE +{ + uint16_t d16; + struct + { + uint16_t periodic_enable: 1; + uint16_t no_tx0: 1; + uint16_t auto_no_tx_option0: 1; + uint16_t lock0: 1; + uint16_t fix_tx_address_option: 1; + uint16_t empty_flag1: 1; + uint16_t clear_hw_no_tx1: 1; + uint16_t clear_hw_rd_ptr0: 1; + uint16_t clear_hw_rd_ptr1: 1; + uint16_t clear_hw_no_tx0: 1; + uint16_t read_clear_hw_rd_ptr0: 1; + uint16_t read_clear_hw_rd_ptr1: 1; + uint16_t read_clear_hw_no_tx0: 1; + uint16_t read_clear_hw_no_tx1: 1; + uint16_t empty_flag0: 1; + uint16_t lock1: 1; + }; +} PRO_TX_CONTROL_TYPE; + +/* 0x22 + 15:0 RW periodic_interval[15:0] 0x0 + */ +typedef union _PRO_PERIODIC_INTERVAL_TYPE +{ + uint16_t d16; + struct + { + uint16_t periodic_interval_15_0; + }; +} PRO_PERIODIC_INTERVAL_TYPE; + +/* 0x24 + 15:0 RW gpio_tx_delay[15:0] 0x0 + */ +typedef union _PRO_GPIO_TX_DELAY_TYPE +{ + uint16_t d16; + struct + { + uint16_t gpio_tx_delay_15_0; + }; +} PRO_GPIO_TX_DELAY_TYPE; + +/* 0x26 + 6:0 RO rsvd 0x0 + 7 RW lna_en 0x0 + 8 RW max_length_kept 0x0 + 9 RW rx_phy 0x0 + 10 RW continuous_rx 0x1 + 11 RW rx2rx_option 0x0 + 12 RW fix_entry0_option 0x0 + 13 RW fix_entry1_option 0x0 + 14 RW error_address_kept 0x0 + 15 RW acchit_time_enable 0x0 + */ +typedef union _PRO_RX_CONTROL_TYPE +{ + uint16_t d16; + struct + { + uint16_t rsvd: 7; + uint16_t lna_en: 1; + uint16_t max_length_kept: 1; + uint16_t rx_phy: 1; + uint16_t continuous_rx: 1; + uint16_t rx2rx_option: 1; + uint16_t fix_entry0_option: 1; + uint16_t fix_entry1_option: 1; + uint16_t error_address_kept: 1; + uint16_t acchit_time_enable: 1; + }; +} PRO_RX_CONTROL_TYPE; + +/* 0x28 + 7:0 RW rx_match_enable_bit[7:0] 0x0 + 8 RW compare_prefix_option 0x0 + 9 RW tx_sdcnt_enable 0x0 + 10 RW rx_sdcnt_enable 0x0 + 11 RW use_maxlength_compare 0x0 + 12 RW opt_crc_err_no_ack 0x0 + 15:13 RO rsvd 0x0 + */ +typedef union _PRO_RX_MATCH_CONTROL_TYPE +{ + uint16_t d16; + struct + { + uint16_t rx_match_enable_bit_7_0: 8; + uint16_t compare_prefix_option: 1; + uint16_t tx_sdcnt_enable: 1; + uint16_t rx_sdcnt_enable: 1; + uint16_t use_maxlength_compare: 1; + uint16_t opt_crc_err_no_ack: 1; + uint16_t rsvd: 3; + }; +} PRO_RX_MATCH_CONTROL_TYPE; + +/* 0x2a + 0 RW ack_enable 0x0 + 4:1 RW periodic_interval[19:16] 0x0 + 5 RW auto_no_tx_option1 0x0 + 6 RW empty_flag2 0x0 + 7 RW auto_no_rdptr_option1 0x0 + 15:8 RW tifs_reg[7:0] 0x0 + */ +typedef union _PRO_TRX_CONTROL_TYPE +{ + uint16_t d16; + struct + { + uint16_t ack_enable: 1; + uint16_t periodic_interval_19_16: 4; + uint16_t auto_no_tx_option1: 1; + uint16_t empty_flag2: 1; + uint16_t auto_no_rdptr_option1: 1; + uint16_t tifs_reg_7_0: 8; + }; +} PRO_TRX_CONTROL_TYPE; + +/* 0x2c + 2:0 RW preamble_field_length1[2:0] 0x0 + 7:3 RW ramp_time_minus 0x18 + 15:8 RW early_interrupt_time 0xa + */ +typedef union _PRO_FIELD_LENGTH2_TYPE +{ + uint16_t d16; + struct + { + uint16_t preamble_field_length1_2_0: 3; + uint16_t ramp_time_minus: 5; + uint16_t early_interrupt_time: 8; + }; +} PRO_FIELD_LENGTH2_TYPE; + +/* 0x30 + 2:0 RW preamble_field_length0[2:0] 0x0 + 5:3 RW address_field_length[2:0] 0x0 + 9:6 RW hp_field_length[3:0] 0x0 + 13:10 RW length_field_length[3:0] 0x0 + 14 RW auto_no_rdptr_option0 0x0 + 15 RW dma_length_mode 0x1 + */ +typedef union _PRO_FIELD_LENGTH_TYPE +{ + uint16_t d16; + struct + { + uint16_t preamble_field_length0_2_0: 3; + uint16_t address_field_length_2_0: 3; + uint16_t hp_field_length_3_0: 4; + uint16_t length_field_length_3_0: 4; + uint16_t auto_no_rdptr_option0: 1; + uint16_t dma_length_mode: 1; + }; +} PRO_FIELD_LENGTH_TYPE; + +/* 0x32 + 0 RW crc_kept 0x0 + 1 RW crc_include_addr_enable 0x0 + 4:2 RW crc_field_length[2:0] 0x0 + 6:5 WO periodic_interval_opt[1:0] 0x0 + 7 RW force_null_packet 0x0 + 8 RW inval_crc 0x0 + 9 RW empty_kept 0x0 + 10 RW white_dis 0x0 + 11 RW hp_split 0x0 + 12 RW length_split 0x0 + 13 RW hs_split 0x0 + 14 RW white_include_addr_enable 0x0 + 15 RW rif_lbt_en_pro 0x0 + */ +typedef union _PRO_PACKET_CONTROL_TYPE +{ + uint16_t d16; + struct + { + uint16_t crc_kept: 1; + uint16_t crc_include_addr_enable: 1; + uint16_t crc_field_length_2_0: 3; + uint16_t periodic_interval_opt_1_0: 2; + uint16_t force_null_packet: 1; + uint16_t inval_crc: 1; + uint16_t empty_kept: 1; + uint16_t white_dis: 1; + uint16_t hp_split: 1; + uint16_t length_split: 1; + uint16_t hs_split: 1; + uint16_t white_include_addr_enable: 1; + uint16_t rif_lbt_en_pro: 1; + }; +} PRO_PACKET_CONTROL_TYPE; + +/* 0x34 + 7:0 RW rif_tx_gain 0x0 + 8 RW en_afc_opt0 0x1 + 9 RW en_afc_opt1 0x1 + 10 RW en_afc_opt2 0x0 + 11 RW en_afc_opt3 0x0 + 15:12 RO rsvd 0x0 + */ +typedef union _PRO_GAIN_TYPE +{ + uint16_t d16; + struct + { + uint16_t rif_tx_gain: 8; + uint16_t en_afc_opt0: 1; + uint16_t en_afc_opt1: 1; + uint16_t en_afc_opt2: 1; + uint16_t en_afc_opt3: 1; + uint16_t rsvd: 4; + }; +} PRO_GAIN_TYPE; + +/* 0x36 + 7:0 RO tx_pkt_num0 0x0 + 15:8 RO tx_pkt_num1 0x0 + */ +typedef union _PRO_TX_PKT_NUM_TYPE +{ + uint16_t d16; + struct + { + uint16_t tx_pkt_num0: 8; + uint16_t tx_pkt_num1: 8; + }; +} PRO_TX_PKT_NUM_TYPE; + +/* 0x38 + 7:0 RO tx_pkt_num2 0x0 + 8 RW modem_compare2_addr 0x0 + 15:9 RO rsvd 0x0 + */ +typedef union _PRO_TX_PKT_NUM2_TYPE +{ + uint16_t d16; + struct + { + uint16_t tx_pkt_num2: 8; + uint16_t modem_compare2_addr: 1; + uint16_t rsvd: 7; + }; +} PRO_TX_PKT_NUM2_TYPE; + +/* 0x3a + 4:0 RW hs_field_length[4:0] 0x0 + 15:5 RO rsvd 0x0 + */ +typedef union _PRO_HS_LENGTH_TYPE +{ + uint16_t d16; + struct + { + uint16_t hs_field_length_4_0: 5; + uint16_t rsvd: 11; + }; +} PRO_HS_LENGTH_TYPE; + +/* 0x3c + 6:0 RW pro_channel 0x0 + 12:7 RO rsvd2 0x0 + 15:13 RW bank 0x0 + */ +typedef union _PRO_CHANNEL_BANK_TYPE +{ + uint16_t d16; + struct + { + uint16_t pro_channel: 7; + uint16_t rsvd2: 6; + uint16_t bank: 3; + }; +} PRO_CHANNEL_BANK_TYPE; + +/* 0x3e + 0 RW fix_entry2_option 0x0 + 1 RW lock2 0x0 + 2 RO rsvd1 0x0 + 3 RW clear_hw_no_tx2 0x0 + 4 RW auto_no_tx_option2 0x0 + 5 RW no_tx2 0x0 + 8:6 RW preamble_field_length2 0x0 + 9 RW clear_hw_rd_ptr2 0x0 + 10 RW auto_no_rdptr_option2 0x0 + 11 RW reset_tx_pktnum2 0x0 + 12 RO read_clear_hw_no_tx2 0x0 + 13 RO read_clear_hw_rd_ptr2 0x0 + 15:14 RO rsvd 0x0 + */ +typedef union _PRO_GPIO_CONTROL_TYPE +{ + uint16_t d16; + struct + { + uint16_t fix_entry2_option: 1; + uint16_t lock2: 1; + uint16_t rsvd1: 1; + uint16_t clear_hw_no_tx2: 1; + uint16_t auto_no_tx_option2: 1; + uint16_t no_tx2: 1; + uint16_t preamble_field_length2: 3; + uint16_t clear_hw_rd_ptr2: 1; + uint16_t auto_no_rdptr_option2: 1; + uint16_t reset_tx_pktnum2: 1; + uint16_t read_clear_hw_no_tx2: 1; + uint16_t read_clear_hw_rd_ptr2: 1; + uint16_t rsvd: 2; + }; +} PRO_GPIO_CONTROL_TYPE; + +/* 0x40 + 0 RO tx_int 0x0 + 1 RO rx_int 0x0 + 2 RO tx_early_int 0x0 + 3 RO gpio_int 0x0 + 4 RO kill_ptx_int 0x0 + 5 RO kill_prx_int 0x0 + 6 RO reset_trig_int 0x0 + 15:7 RO rsvd 0x0 + */ +typedef union _PRO_MISR_TYPE +{ + uint16_t d16; + struct + { + uint16_t tx_int: 1; + uint16_t rx_int: 1; + uint16_t tx_early_int: 1; + uint16_t gpio_int: 1; + uint16_t kill_ptx_int: 1; + uint16_t kill_prx_int: 1; + uint16_t reset_trig_int: 1; + uint16_t rsvd: 9; + }; +} PRO_MISR_TYPE; + +/* 0x42 + 0 RW tx_int 0x0 + 1 RW rx_int 0x0 + 2 RW tx_early_int 0x0 + 3 RW gpio_int 0x0 + 4 RW kill_ptx_int 0x0 + 5 RW kill_prx_int 0x0 + 6 RW reset_trig_int 0x0 + 15:7 RW imr[15:7](rsvd) 0x0 + */ +typedef union _PRO_IMR_TYPE +{ + uint16_t d16; + struct + { + uint16_t tx_int: 1; + uint16_t rx_int: 1; + uint16_t tx_early_int: 1; + uint16_t gpio_int: 1; + uint16_t kill_ptx_int: 1; + uint16_t kill_prx_int: 1; + uint16_t reset_trig_int: 1; + uint16_t imr_15_7rsvd: 9; + }; +} PRO_IMR_TYPE; + +/* 0x4e + 15:0 RO rssi 0x0 + */ +typedef union _PRO_RSSI_TYPE +{ + uint16_t d16; + struct + { + uint16_t rssi; + }; +} PRO_RSSI_TYPE; + +/* 0x50 + 15:0 RO length_include_addon 0x0 + */ +typedef union _PRO_LENGTH_INCLUDE_ADDON_TYPE +{ + uint16_t d16; + struct + { + uint16_t length_include_addon; + }; +} PRO_LENGTH_INCLUDE_ADDON_TYPE; + +/* 0x52 + 14:0 RO rx_length 0x0 + 15 RO rsvd 0x0 + */ +typedef union _PRO_LENGTH_TYPE +{ + uint16_t d16; + struct + { + uint16_t rx_length: 15; + uint16_t rsvd: 1; + }; +} PRO_LENGTH_TYPE; + +/* 0x54 + 0 RO is_max_length 0x0 + 1 RO is_crc_error 0x0 + 2 RO entry[0] 0x0 + 3 RO rx_hit 0x0 + 4 RO gpio_flag 0x0 + 5 RO rx_time_out 0x0 + 6 RO rx_abort_rd 0x0 + 8:7 RO entry[2:1] 0x0 + 15:9 RO rsvd 0x0 + */ +typedef union _PRO_RX_STACK_TYPE +{ + uint16_t d16; + struct + { + uint16_t is_max_length: 1; + uint16_t is_crc_error: 1; + uint16_t entry_0: 1; + uint16_t rx_hit: 1; + uint16_t gpio_flag: 1; + uint16_t rx_time_out: 1; + uint16_t rx_abort_rd: 1; + uint16_t entry_2_1: 2; + uint16_t rsvd: 7; + }; +} PRO_RX_STACK_TYPE; + +/* 0x56 + 7:0 RO hp 0x0 + 15:8 RO rsvd 0x0 + */ +typedef union _PRO_RX_HP_TYPE +{ + uint16_t d16; + struct + { + uint16_t hp: 8; + uint16_t rsvd: 8; + }; +} PRO_RX_HP_TYPE; + +/* 0x58 + 15:0 RO rx_crc[15:0] 0x0 + */ +typedef union _PRO_RX_CRC_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t rx_crc_15_0; + }; +} PRO_RX_CRC_LOWER_TYPE; + +/* 0x5a + 15:0 RO rx_crc[31:16] 0x0 + */ +typedef union _PRO_RX_CRC_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t rx_crc_31_16; + }; +} PRO_RX_CRC_UPPER_TYPE; + +/* 0x5c + 15:0 RO acchit_clk[15:0] 0x0 + */ +typedef union _PRO_ACCHIT_CLK_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t acchit_clk_15_0; + }; +} PRO_ACCHIT_CLK_LOWER_TYPE; + +/* 0x5e + 15:0 RO acchit_clk[31:16] 0x0 + */ +typedef union _PRO_ACCHIT_CLK_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t acchit_clk_31_16; + }; +} PRO_ACCHIT_CLK_UPPER_TYPE; + +/* 0x60 + 15:0 RO hs[15:0] 0x0 + */ +typedef union _PRO_RX_HS_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t hs_15_0; + }; +} PRO_RX_HS_LOWER_TYPE; + +/* 0x62 + 14:0 RO hs[30:16] 0x0 + 15 RO rsvd 0x0 + */ +typedef union _PRO_RX_HS_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t hs_30_16: 15; + uint16_t rsvd: 1; + }; +} PRO_RX_HS_UPPER_TYPE; + +/* 0x64 + 0 RO is_no_tx 0x0 + 1 RO is_empty 0x0 + 5:2 RO tx_ptr 0x0 + 7:6 RO tx_entry[1:0] 0x0 + 15:8 RO tx_hp 0x0 + */ +typedef union _PRO_TX_STACK_TYPE +{ + uint16_t d16; + struct + { + uint16_t is_no_tx: 1; + uint16_t is_empty: 1; + uint16_t tx_ptr: 4; + uint16_t tx_entry_1_0: 2; + uint16_t tx_hp: 8; + }; +} PRO_TX_STACK_TYPE; + +/* 0x66 + 15:0 RO tx_hs[15:0] 0x0 + */ +typedef union _PRO_TX_HS_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t tx_hs_15_0; + }; +} PRO_TX_HS_LOWER_TYPE; + +/* 0x68 + 14:0 RO tx_hs[30:16] 0x0 + 15 RO rsvd 0x0 + */ +typedef union _PRO_TX_HS_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t tx_hs_30_16: 15; + uint16_t rsvd: 1; + }; +} PRO_TX_HS_UPPER_TYPE; + +/* 0x6a + 10:0 RO tx_length 0x0 + 11 RO tx_entry[2] 0x0 + 15:12 RO rsvd 0x0 + */ +typedef union _PRO_TX_LENGTH_TYPE +{ + uint16_t d16; + struct + { + uint16_t tx_length: 11; + uint16_t tx_entry_2: 1; + uint16_t rsvd: 4; + }; +} PRO_TX_LENGTH_TYPE; + +/* 0x6c + 15:0 RO tx_clk[15:0] 0x0 + */ +typedef union _PRO_TX_CLK_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t tx_clk_15_0; + }; +} PRO_TX_CLK_LOWER_TYPE; + +/* 0x6e + 15:0 RO tx_clk[31:16] 0x0 + */ +typedef union _PRO_TX_CLK_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t tx_clk_31_16; + }; +} PRO_TX_CLK_UPPER_TYPE; + +/* 0x80 + 7:0 RW hp_0[7:0] 0x0 + 15:8 RO rsvd 0x0 + */ +typedef union _PRO_HP_0_TYPE +{ + uint16_t d16; + struct + { + uint16_t hp_0_7_0: 8; + uint16_t rsvd: 8; + }; +} PRO_HP_0_TYPE; + +/* 0x82 + 15:0 RW hs_0[15:0] 0x0 + */ +typedef union _PRO_HS_0_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t hs_0_15_0; + }; +} PRO_HS_0_LOWER_TYPE; + +/* 0x84 + 14:0 RW hs_0[30:16] 0x0 + 15 RO rsvd 0x0 + */ +typedef union _PRO_HS_0_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t hs_0_30_16: 15; + uint16_t rsvd: 1; + }; +} PRO_HS_0_UPPER_TYPE; + +/* 0x86 + 14:0 RW length_0[14:0] 0x0 + 15 RO rsvd 0x0 + */ +typedef union _PRO_LENGTH_0_TYPE +{ + uint16_t d16; + struct + { + uint16_t length_0_14_0: 15; + uint16_t rsvd: 1; + }; +} PRO_LENGTH_0_TYPE; + +/* 0x88 + 15:0 RW crc_init0[15:0] 0x0 + */ +typedef union _PRO_CRC_INIT0_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t crc_init0_15_0; + }; +} PRO_CRC_INIT0_LOWER_TYPE; + +/* 0x8a + 15:0 RW crc_init0[31:16] 0x0 + */ +typedef union _PRO_CRC_INIT0_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t crc_init0_31_16; + }; +} PRO_CRC_INIT0_UPPER_TYPE; + +/* 0x8c + 15:0 RW crc_polynomial_reg0[15:0] 0x0 + */ +typedef union _PRO_CRC_POLYNOMIAL_REG0_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t crc_polynomial_reg0_15_0; + }; +} PRO_CRC_POLYNOMIAL_REG0_LOWER_TYPE; + +/* 0x8e + 15:0 RW crc_polynomial_reg0[31:16] 0x0 + */ +typedef union _PRO_CRC_POLYNOMIAL_REG0_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t crc_polynomial_reg0_31_16; + }; +} PRO_CRC_POLYNOMIAL_REG0_UPPER_TYPE; + +/* 0x90 + 0 RW tx_phy0 0x0 + 1 RW auto_add_rptr_option0 0x0 + 4:2 RW fw_rd_ptr0 0x0 + 5 RW fw_ack0 0x0 + 11:6 RW white_field_length0 0x0 + 15:12 RO rsvd 0x0 + */ +typedef union _PRO_PACKET_RELATED_CONTROL0_TYPE +{ + uint16_t d16; + struct + { + uint16_t tx_phy0: 1; + uint16_t auto_add_rptr_option0: 1; + uint16_t fw_rd_ptr0: 3; + uint16_t fw_ack0: 1; + uint16_t white_field_length0: 6; + uint16_t rsvd: 4; + }; +} PRO_PACKET_RELATED_CONTROL0_TYPE; + +/* 0x92 + 7:0 RW add_on_length0[7:0] 0x0 + 15:8 RO rx_pkt_num0 0x0 + */ +typedef union _PRO_ADD_ON_LENGTH0_TYPE +{ + uint16_t d16; + struct + { + uint16_t add_on_length0_7_0: 8; + uint16_t rx_pkt_num0: 8; + }; +} PRO_ADD_ON_LENGTH0_TYPE; + +/* 0x94 + 15:0 RW white_init0[15:0] 0x0 + */ +typedef union _PRO_WHITE_INIT0_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t white_init0_15_0; + }; +} PRO_WHITE_INIT0_LOWER_TYPE; + +/* 0x96 + 15:0 RW white_init0[31:16] 0x0 + */ +typedef union _PRO_WHITE_INIT0_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t white_init0_31_16; + }; +} PRO_WHITE_INIT0_UPPER_TYPE; + +/* 0x98 + 15:0 RW white_polynomial_reg0[15:0] 0x0 + */ +typedef union _PRO_WHITE_POLYNOMIAL_REG0_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t white_polynomial_reg0_15_0; + }; +} PRO_WHITE_POLYNOMIAL_REG0_LOWER_TYPE; + +/* 0x9a + 15:0 RW white_polynomial_reg0[31:16] 0x0 + */ +typedef union _PRO_WHITE_POLYNOMIAL_REG0_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t white_polynomial_reg0_31_16; + }; +} PRO_WHITE_POLYNOMIAL_REG0_UPPER_TYPE; + +/* 0xa0 + 7:0 RW hp_1[7:0] 0x0 + 15:8 RO rsvd 0x0 + */ +typedef union _PRO_HP_1_TYPE +{ + uint16_t d16; + struct + { + uint16_t hp_1_7_0: 8; + uint16_t rsvd: 8; + }; +} PRO_HP_1_TYPE; + +/* 0xa2 + 15:0 RW hs_1[15:0] 0x0 + */ +typedef union _PRO_HS_1_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t hs_1_15_0; + }; +} PRO_HS_1_LOWER_TYPE; + +/* 0xa4 + 14:0 RW hs_1[30:16] 0x0 + 15 RO rsvd 0x0 + */ +typedef union _PRO_HS_1_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t hs_1_30_16: 15; + uint16_t rsvd: 1; + }; +} PRO_HS_1_UPPER_TYPE; + +/* 0xa6 + 14:0 RW length_1[14:0] 0x0 + 15 RO rsvd 0x0 + */ +typedef union _PRO_LENGTH_1_TYPE +{ + uint16_t d16; + struct + { + uint16_t length_1_14_0: 15; + uint16_t rsvd: 1; + }; +} PRO_LENGTH_1_TYPE; + +/* 0xa8 + 15:0 RW crc_init1[15:0] 0x0 + */ +typedef union _PRO_CRC_INIT1_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t crc_init1_15_0; + }; +} PRO_CRC_INIT1_LOWER_TYPE; + +/* 0xaa + 15:0 RW crc_init1[31:16] 0x0 + */ +typedef union _PRO_CRC_INIT1_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t crc_init1_31_16; + }; +} PRO_CRC_INIT1_UPPER_TYPE; + +/* 0xac + 15:0 RW crc_polynomial_reg1[15:0] 0x0 + */ +typedef union _PRO_CRC_POLYNOMIAL_REG1_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t crc_polynomial_reg1_15_0; + }; +} PRO_CRC_POLYNOMIAL_REG1_LOWER_TYPE; + +/* 0xae + 15:0 RW crc_polynomial_reg1[31:16] 0x0 + */ +typedef union _PRO_CRC_POLYNOMIAL_REG1_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t crc_polynomial_reg1_31_16; + }; +} PRO_CRC_POLYNOMIAL_REG1_UPPER_TYPE; + +/* 0xb0 + 0 RW tx_phy1 0x0 + 1 RW auto_add_rptr_option1 0x0 + 4:2 RW fw_rd_ptr1 0x0 + 5 RW fw_ack1 0x0 + 11:6 RW white_field_length1 0x0 + 15:12 RO rsvd 0x0 + */ +typedef union _PRO_PACKET_RELATED_CONTROL1_TYPE +{ + uint16_t d16; + struct + { + uint16_t tx_phy1: 1; + uint16_t auto_add_rptr_option1: 1; + uint16_t fw_rd_ptr1: 3; + uint16_t fw_ack1: 1; + uint16_t white_field_length1: 6; + uint16_t rsvd: 4; + }; +} PRO_PACKET_RELATED_CONTROL1_TYPE; + +/* 0xb2 + 7:0 RW add_on_length1[7:0] 0x0 + 15:8 RO rx_pkt_num1 0x0 + */ +typedef union _PRO_ADD_ON_LENGTH1_TYPE +{ + uint16_t d16; + struct + { + uint16_t add_on_length1_7_0: 8; + uint16_t rx_pkt_num1: 8; + }; +} PRO_ADD_ON_LENGTH1_TYPE; + +/* 0xb4 + 15:0 RW white_init1[15:0] 0x0 + */ +typedef union _PRO_WHITE_INIT1_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t white_init1_15_0; + }; +} PRO_WHITE_INIT1_LOWER_TYPE; + +/* 0xb6 + 15:0 RW white_init1[31:16] 0x0 + */ +typedef union _PRO_WHITE_INIT1_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t white_init1_31_16; + }; +} PRO_WHITE_INIT1_UPPER_TYPE; + +/* 0xb8 + 15:0 RW white_polynomial_reg1[15:0] 0x0 + */ +typedef union _PRO_WHITE_POLYNOMIAL_REG1_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t white_polynomial_reg1_15_0; + }; +} PRO_WHITE_POLYNOMIAL_REG1_LOWER_TYPE; + +/* 0xba + 15:0 RW white_polynomial_reg1[31:16] 0x0 + */ +typedef union _PRO_WHITE_POLYNOMIAL_REG1_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t white_polynomial_reg1_31_16; + }; +} PRO_WHITE_POLYNOMIAL_REG1_UPPER_TYPE; + +/* 0xc0 + 7:0 RW hp_2[7:0] 0x0 + 15:8 RO rsvd 0x0 + */ +typedef union _PRO_HP_2_TYPE +{ + uint16_t d16; + struct + { + uint16_t hp_2_7_0: 8; + uint16_t rsvd: 8; + }; +} PRO_HP_2_TYPE; + +/* 0xc2 + 15:0 RW hs_2[15:0] 0x0 + */ +typedef union _PRO_HS_2_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t hs_2_15_0; + }; +} PRO_HS_2_LOWER_TYPE; + +/* 0xc4 + 14:0 RW hs_2[30:16] 0x0 + 15 RO rsvd 0x0 + */ +typedef union _PRO_HS_2_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t hs_2_30_16: 15; + uint16_t rsvd: 1; + }; +} PRO_HS_2_UPPER_TYPE; + +/* 0xc6 + 14:0 RW length_2[14:0] 0x0 + 15 RO rsvd 0x0 + */ +typedef union _PRO_LENGTH_2_TYPE +{ + uint16_t d16; + struct + { + uint16_t length_2_14_0: 15; + uint16_t rsvd: 1; + }; +} PRO_LENGTH_2_TYPE; + +/* 0xc8 + 15:0 RW crc_init2[15:0] 0x0 + */ +typedef union _PRO_CRC_INIT2_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t crc_init2_15_0; + }; +} PRO_CRC_INIT2_LOWER_TYPE; + +/* 0xca + 15:0 RW crc_init2[31:16] 0x0 + */ +typedef union _PRO_CRC_INIT2_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t crc_init2_31_16; + }; +} PRO_CRC_INIT2_UPPER_TYPE; + +/* 0xcc + 15:0 RW crc_polynomial_reg2[15:0] 0x0 + */ +typedef union _PRO_CRC_POLYNOMIAL_REG2_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t crc_polynomial_reg2_15_0; + }; +} PRO_CRC_POLYNOMIAL_REG2_LOWER_TYPE; + +/* 0xce + 15:0 RW crc_polynomial_reg2[31:16] 0x0 + */ +typedef union _PRO_CRC_POLYNOMIAL_REG2_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t crc_polynomial_reg2_31_16; + }; +} PRO_CRC_POLYNOMIAL_REG2_UPPER_TYPE; + +/* 0xd0 + 0 RW tx_phy2 0x0 + 1 RW auto_add_rptr_option2 0x0 + 4:2 RW fw_rd_ptr2 0x0 + 5 RW fw_ack2 0x0 + 11:6 RW white_field_length2 0x0 + 15:12 RO rsvd 0x0 + */ +typedef union _PRO_PACKET_RELATED_CONTROL2_TYPE +{ + uint16_t d16; + struct + { + uint16_t tx_phy2: 1; + uint16_t auto_add_rptr_option2: 1; + uint16_t fw_rd_ptr2: 3; + uint16_t fw_ack2: 1; + uint16_t white_field_length2: 6; + uint16_t rsvd: 4; + }; +} PRO_PACKET_RELATED_CONTROL2_TYPE; + +/* 0xd2 + 7:0 RW add_on_length2[7:0] 0x0 + 15:8 RW pro_rx_timeout_delay_ms 0x0 + */ +typedef union _PRO_ADD_ON_LENGTH2_TYPE +{ + uint16_t d16; + struct + { + uint16_t add_on_length2_7_0: 8; + uint16_t pro_rx_timeout_delay_ms: 8; + }; +} PRO_ADD_ON_LENGTH2_TYPE; + +/* 0xd4 + 15:0 RW white_init2[15:0] 0x0 + */ +typedef union _PRO_WHITE_INIT2_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t white_init2_15_0; + }; +} PRO_WHITE_INIT2_LOWER_TYPE; + +/* 0xd6 + 15:0 RW white_init2[31:16] 0x0 + */ +typedef union _PRO_WHITE_INIT2_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t white_init2_31_16; + }; +} PRO_WHITE_INIT2_UPPER_TYPE; + +/* 0xd8 + 15:0 RW white_polynomial_reg2[15:0] 0x0 + */ +typedef union _PRO_WHITE_POLYNOMIAL_REG2_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t white_polynomial_reg2_15_0; + }; +} PRO_WHITE_POLYNOMIAL_REG2_LOWER_TYPE; + +/* 0xda + 15:0 RW white_polynomial_reg2[31:16] 0x0 + */ +typedef union _PRO_WHITE_POLYNOMIAL_REG2_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t white_polynomial_reg2_31_16; + }; +} PRO_WHITE_POLYNOMIAL_REG2_UPPER_TYPE; + +/* 0xdc + 4:0 RW pro_gpio_native_counter_reg 0x18 + 5 RW gpio_tx_enable 0x0 + 6 RW gpio_tx_enable1 0x0 + 7 RW gpio_tx_enable2 0x0 + 8 RW fw_rst_trigger 0x0 + 9 RW fw_rst_enable 0x0 + 10 RW hw_rst_enable 0x0 + 11 RW gpio_in_enable 0x0 + 12 RW reset_trig_int_enable 0x1 + 15:13 RW dma_early_delay 0x0 + */ +typedef union _PRO_RESET_CTRL_REG_TYPE +{ + uint16_t d16; + struct + { + uint16_t pro_gpio_native_counter_reg: 5; + uint16_t gpio_tx_enable: 1; + uint16_t gpio_tx_enable1: 1; + uint16_t gpio_tx_enable2: 1; + uint16_t fw_rst_trigger: 1; + uint16_t fw_rst_enable: 1; + uint16_t hw_rst_enable: 1; + uint16_t gpio_in_enable: 1; + uint16_t reset_trig_int_enable: 1; + uint16_t dma_early_delay: 3; + }; +} PRO_RESET_CTRL_REG_TYPE; + +/* 0xde + 15:0 RW gpio_cnt_reg 0x1 + */ +typedef union _PRO_GPIO_CTRL_REG_TYPE +{ + uint16_t d16; + struct + { + uint16_t gpio_cnt_reg; + }; +} PRO_GPIO_CTRL_REG_TYPE; + +/* 0xe0 + 15:0 RW tx_address2[15:0] 0x0 + */ +typedef union _PRO_TX_ADDRESS2_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t tx_address2_15_0; + }; +} PRO_TX_ADDRESS2_LOWER_TYPE; + +/* 0xe2 + 15:0 RW tx_address2[31:16] 0x0 + */ +typedef union _PRO_TX_ADDRESS2_MIDDLE_TYPE +{ + uint16_t d16; + struct + { + uint16_t tx_address2_31_16; + }; +} PRO_TX_ADDRESS2_MIDDLE_TYPE; + +/* 0xe4 + 7:0 RW tx_address2[39:32] 0x0 + 15:8 RO rsvd 0x0 + */ +typedef union _PRO_TX_ADDRESS2_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t tx_address2_39_32: 8; + uint16_t rsvd: 8; + }; +} PRO_TX_ADDRESS2_UPPER_TYPE; + +/* 0xe6 + 0 RW preamble_order 0x0 + 1 RW txfifo_out_order 0x0 + 2 RW txclk_order 0x0 + 3 RW rxfifo_in_order 0x0 + 4 RW tx_address_order 0x0 + 5 RW length_order 0x0 + 6 RW hp_order 0x0 + 7 RW hs_order 0x0 + 8 RW length_order_first 0x0 + 9 RW length_split_first 0x0 + 10 RW hp_order_first 0x0 + 11 RW hp_split_first 0x0 + 12 RW hs_order_first 0x0 + 13 RW hs_split_first 0x0 + 15:14 RO rsvd 0x0 + */ +typedef union _PRO_ORDER_CONTROL_TYPE +{ + uint16_t d16; + struct + { + uint16_t preamble_order: 1; + uint16_t txfifo_out_order: 1; + uint16_t txclk_order: 1; + uint16_t rxfifo_in_order: 1; + uint16_t tx_address_order: 1; + uint16_t length_order: 1; + uint16_t hp_order: 1; + uint16_t hs_order: 1; + uint16_t length_order_first: 1; + uint16_t length_split_first: 1; + uint16_t hp_order_first: 1; + uint16_t hp_split_first: 1; + uint16_t hs_order_first: 1; + uint16_t hs_split_first: 1; + uint16_t rsvd: 2; + }; +} PRO_ORDER_CONTROL_TYPE; + +/* 0xe8 + 15:0 RW gpio_cnt1_reg 0x1 + */ +typedef union _PRO_GPIO_CTRL1_REG_TYPE +{ + uint16_t d16; + struct + { + uint16_t gpio_cnt1_reg; + }; +} PRO_GPIO_CTRL1_REG_TYPE; + +/* 0xea + 15:0 RW gpio_cnt2_reg 0x1 + */ +typedef union _PRO_GPIO_CTRL2_REG_TYPE +{ + uint16_t d16; + struct + { + uint16_t gpio_cnt2_reg; + }; +} PRO_GPIO_CTRL2_REG_TYPE; + +/* 0xec + 4:0 RW pro_gpio_native_counter1_reg 0x18 + 5 RW gpio_rst_enable1 0x0 + 7:6 RO rsvd1 0x0 + 12:8 RW pro_gpio_native_counter2_reg 0x18 + 13 RW gpio_rst_enable2 0x0 + 15:14 RO rsvd2 0x0 + */ +typedef union _PRO_GPIO_NATIVE_CNT_TYPE +{ + uint16_t d16; + struct + { + uint16_t pro_gpio_native_counter1_reg: 5; + uint16_t gpio_rst_enable1: 1; + uint16_t rsvd1: 2; + uint16_t pro_gpio_native_counter2_reg: 5; + uint16_t gpio_rst_enable2: 1; + uint16_t rsvd2: 2; + }; +} PRO_GPIO_NATIVE_CNT_TYPE; + +/* 0xee + 9:0 RW max_length 0xff + 10 RW txclk_split 0x0 + 11 RW txfifo_out_split 0x0 + 12 RW rxfifo_in_split 0x0 + 15:13 RO rsvd 0x0 + */ +typedef union _PRO_MAX_LENGTH_TYPE +{ + uint16_t d16; + struct + { + uint16_t max_length: 10; + uint16_t txclk_split: 1; + uint16_t txfifo_out_split: 1; + uint16_t rxfifo_in_split: 1; + uint16_t rsvd: 3; + }; +} PRO_MAX_LENGTH_TYPE; + +/* 0x100 + 7:0 RW pro_rx2tx_delay_base 0x83 + 15:8 RW pro_rx2rx_delay 0x32 + */ +typedef union _PRO_RX_TURN_AROUND_DELAY_TYPE +{ + uint16_t d16; + struct + { + uint16_t pro_rx2tx_delay_base: 8; + uint16_t pro_rx2rx_delay: 8; + }; +} PRO_RX_TURN_AROUND_DELAY_TYPE; + +/* 0x102 + 3:0 RW pro_rx2tx_delay_1m 0x3 + 7:4 RW pro_tx2rx_delay_1m 0x0 + 11:8 RW pro_rx2tx_delay_2m 0x8 + 15:12 RW pro_tx2rx_delay_2m 0x0 + */ +typedef union _PRO_2M_TRX_TURN_AROUND_DELAY_TYPE +{ + uint16_t d16; + struct + { + uint16_t pro_rx2tx_delay_1m: 4; + uint16_t pro_tx2rx_delay_1m: 4; + uint16_t pro_rx2tx_delay_2m: 4; + uint16_t pro_tx2rx_delay_2m: 4; + }; +} PRO_2M_TRX_TURN_AROUND_DELAY_TYPE; + +/* 0x104 + 3:0 RW pro_rx2tx_delay_1m_2m 0x3 + 7:4 RW pro_tx2rx_delay_1m_2m 0x0 + 11:8 RW pro_rx2tx_delay_2m_1m 0x7 + 15:12 RW pro_tx2rx_delay_2m_1m 0x0 + */ +typedef union _PRO_1M_2M_TRX_TURN_AROUND_DELAY_TYPE +{ + uint16_t d16; + struct + { + uint16_t pro_rx2tx_delay_1m_2m: 4; + uint16_t pro_tx2rx_delay_1m_2m: 4; + uint16_t pro_rx2tx_delay_2m_1m: 4; + uint16_t pro_tx2rx_delay_2m_1m: 4; + }; +} PRO_1M_2M_TRX_TURN_AROUND_DELAY_TYPE; + +/* 0x106 + 7:0 RW pro_tx2rx_delay_base 0x83 + 13:8 RW pro_txon_early_1m 0x10 + 15:14 RO rsvd 0x0 + */ +typedef union _PRO_TX_TURN_AROUND_DELAY_TYPE +{ + uint16_t d16; + struct + { + uint16_t pro_tx2rx_delay_base: 8; + uint16_t pro_txon_early_1m: 6; + uint16_t rsvd: 2; + }; +} PRO_TX_TURN_AROUND_DELAY_TYPE; + +/* 0x108 + 7:0 RW pro_rx_timeout_delay_us 0x64 + 11:8 RW no_tx_early[3:0] 0x2 + 15:12 RW pro_txon_early_2m 0x0 + */ +typedef union _PRO_RX_TIMEOUT_DELAY_TYPE +{ + uint16_t d16; + struct + { + uint16_t pro_rx_timeout_delay_us: 8; + uint16_t no_tx_early_3_0: 4; + uint16_t pro_txon_early_2m: 4; + }; +} PRO_RX_TIMEOUT_DELAY_TYPE; + +/* 0x10a + 7:0 RW pro_txon_delay 0xdc + 15:8 RW pro_rxon_delay 0xdc + */ +typedef union _PRO_TRX_ON_DELAY_TYPE +{ + uint16_t d16; + struct + { + uint16_t pro_txon_delay: 8; + uint16_t pro_rxon_delay: 8; + }; +} PRO_TRX_ON_DELAY_TYPE; + +/* 0x10c + 7:0 RW pro_txon_delay_2m 0xdc + 15:8 RW pro_rxon_delay_2m 0xdc + */ +typedef union _PRO_2M_TRX_ON_DELAY_TYPE +{ + uint16_t d16; + struct + { + uint16_t pro_txon_delay_2m: 8; + uint16_t pro_rxon_delay_2m: 8; + }; +} PRO_2M_TRX_ON_DELAY_TYPE; + +/* 0x10e + 3:0 RW txon_ext 0x4 + 4 RW en_early_txon_tgl 0x1 + 7:5 RW no_tx_early[6:4] 0x0 + 15:8 RW get_ack_before_send 0x1 + */ +typedef union _PRO_TRX_DEALY_MISC_TYPE +{ + uint16_t d16; + struct + { + uint16_t txon_ext: 4; + uint16_t en_early_txon_tgl: 1; + uint16_t no_tx_early_6_4: 3; + uint16_t get_ack_before_send: 8; + }; +} PRO_TRX_DEALY_MISC_TYPE; + +/* 0x110 + 6:0 RW pro_psd_start 0x0 + 7 RO rsvd0 0x0 + 14:8 RW pro_psd_end 0x0 + 15 RO rsvd1 0x0 + */ +typedef union _PRO_PSD_RANGE0_TYPE +{ + uint16_t d16; + struct + { + uint16_t pro_psd_start: 7; + uint16_t rsvd0: 1; + uint16_t pro_psd_end: 7; + uint16_t rsvd1: 1; + }; +} PRO_PSD_RANGE0_TYPE; + +/* 0x112 + 6:0 RW pro_psd_step 0x0 + 7 RW pro_psd_mode 0x0 + 8 RW psd_rst_enable 0x0 + 13:9 RW psd_rst_cnt_reg 0x2 + 15:14 RO rsvd 0x0 + */ +typedef union _PRO_PSD_RANGE1_TYPE +{ + uint16_t d16; + struct + { + uint16_t pro_psd_step: 7; + uint16_t pro_psd_mode: 1; + uint16_t psd_rst_enable: 1; + uint16_t psd_rst_cnt_reg: 5; + uint16_t rsvd: 2; + }; +} PRO_PSD_RANGE1_TYPE; + +/* 0x114 + 9:0 RW pro_psd_timeout 0x114 + 15:10 RO rsvd 0x0 + */ +typedef union _PRO_PSD_TIMEOUT_TYPE +{ + uint16_t d16; + struct + { + uint16_t pro_psd_timeout: 10; + uint16_t rsvd: 6; + }; +} PRO_PSD_TIMEOUT_TYPE; + +/* 0x118 + 14:0 RO rsvd 0x0 + 15 RW rx_int_stack_ovf 0x0 + */ +typedef union _PRO_INT_CTRL_TYPE +{ + uint16_t d16; + struct + { + uint16_t rsvd: 15; + uint16_t rx_int_stack_ovf: 1; + }; +} PRO_INT_CTRL_TYPE; + +/* 0x11a + 15:0 RW gpio_tx_delay1[15:0] 0x0 + */ +typedef union _PRO_GPIO_TX_DELAY1_TYPE +{ + uint16_t d16; + struct + { + uint16_t gpio_tx_delay1_15_0; + }; +} PRO_GPIO_TX_DELAY1_TYPE; + +/* 0x11c + 14:0 RO rsvd 0x0 + 15 RW tx_int_stack_ovf 0x0 + */ +typedef union _PRO_INT_CTRL_TX_TYPE +{ + uint16_t d16; + struct + { + uint16_t rsvd: 15; + uint16_t tx_int_stack_ovf: 1; + }; +} PRO_INT_CTRL_TX_TYPE; + +/* 0x11e + 15:0 RW gpio_tx_delay2[15:0] 0x0 + */ +typedef union _PRO_GPIO_TX_DELAY2_TYPE +{ + uint16_t d16; + struct + { + uint16_t gpio_tx_delay2_15_0; + }; +} PRO_GPIO_TX_DELAY2_TYPE; + +/* 0x120 + 0 RW opt_pro_ce_end 0x0 + 1 RW reset_tx_pktnum0 0x0 + 2 RW reset_tx_pktnum1 0x0 + 3 RW reset_rx_pktnum0 0x0 + 4 RW reset_rx_pktnum1 0x0 + 5 RW tx_time_enable 0x0 + 6 RW no_tx1 0x0 + 7 RW cbk_pcd_cg 0x1 + 8 RW cbk_radio_cg 0x1 + 9 RW cbk_txrx_time_cg 0x1 + 10 RW sd_cnt_enable 0x0 + 11 RW no_tx_trig_stack_enable 0x0 + 15:12 RW dma_cnt_reg 0x7 + */ +typedef union _PRO_CBK_CTRL_TYPE +{ + uint16_t d16; + struct + { + uint16_t opt_pro_ce_end: 1; + uint16_t reset_tx_pktnum0: 1; + uint16_t reset_tx_pktnum1: 1; + uint16_t reset_rx_pktnum0: 1; + uint16_t reset_rx_pktnum1: 1; + uint16_t tx_time_enable: 1; + uint16_t no_tx1: 1; + uint16_t cbk_pcd_cg: 1; + uint16_t cbk_radio_cg: 1; + uint16_t cbk_txrx_time_cg: 1; + uint16_t sd_cnt_enable: 1; + uint16_t no_tx_trig_stack_enable: 1; + uint16_t dma_cnt_reg: 4; + }; +} PRO_CBK_CTRL_TYPE; + +/* 0x122 + 7:0 RW txon_early_afe 0x6 + 15:8 RW rxon_early_afe 0x6 + */ +typedef union _PRO_TRX_AFE_TYPE +{ + uint16_t d16; + struct + { + uint16_t txon_early_afe: 8; + uint16_t rxon_early_afe: 8; + }; +} PRO_TRX_AFE_TYPE; + +/* 0x124 + 3:0 RW ptx_dbg_sel 0x0 + 5:4 RW control_dbg_sel 0x0 + 8:6 RW trx_dbg_sel 0x0 + 11:9 RW radio_dbg_sel 0x0 + 15:12 RW dma_dbg_sel[3:0] 0x0 + */ +typedef union _PRO_DEBUG_SEL_TYPE +{ + uint16_t d16; + struct + { + uint16_t ptx_dbg_sel: 4; + uint16_t control_dbg_sel: 2; + uint16_t trx_dbg_sel: 3; + uint16_t radio_dbg_sel: 3; + uint16_t dma_dbg_sel_3_0: 4; + }; +} PRO_DEBUG_SEL_TYPE; + +/* 0x126 + 3:0 RW pcd_dbg_sel 0x0 + 5:4 RW stack_dbg_sel 0x0 + 8:6 RW top_dbg_sel 0x0 + 9 RW dma_dbg_sel[4] 0x0 + 15:10 RO rsvd 0x0 + */ +typedef union _PRO_DEBUG_SEL2_TYPE +{ + uint16_t d16; + struct + { + uint16_t pcd_dbg_sel: 4; + uint16_t stack_dbg_sel: 2; + uint16_t top_dbg_sel: 3; + uint16_t dma_dbg_sel_4: 1; + uint16_t rsvd: 6; + }; +} PRO_DEBUG_SEL2_TYPE; + +/* 0x128 + 5:0 RO radio_cst 0x0 + 6 RO radio_idle 0x1 + 10:7 RO timing_cst 0x0 + 11 RO timing_idle 0x1 + 12 RO prx_fsm_idle 0x1 + 14:13 RO prx_cst 0x0 + 15 RO rsvd 0x0 + */ +typedef union _PRO_DSM_READ_TYPE +{ + uint16_t d16; + struct + { + uint16_t radio_cst: 6; + uint16_t radio_idle: 1; + uint16_t timing_cst: 4; + uint16_t timing_idle: 1; + uint16_t prx_fsm_idle: 1; + uint16_t prx_cst: 2; + uint16_t rsvd: 1; + }; +} PRO_DSM_READ_TYPE; + +/* 0x12a + 0 RO ptx_fsm_idle 0x1 + 2:1 RO ptx_cst 0x0 + 6:3 RO p2s_cst 0x0 + 7 RO pcd_p2s_idle 0x1 + 12:8 RO pcd_ctrl_cst 0x0 + 13 RO pcd_idle 0x1 + 15:14 RO rsvd 0x0 + */ +typedef union _PRO_DSM_READ1_TYPE +{ + uint16_t d16; + struct + { + uint16_t ptx_fsm_idle: 1; + uint16_t ptx_cst: 2; + uint16_t p2s_cst: 4; + uint16_t pcd_p2s_idle: 1; + uint16_t pcd_ctrl_cst: 5; + uint16_t pcd_idle: 1; + uint16_t rsvd: 2; + }; +} PRO_DSM_READ1_TYPE; + +/* 0x12c + 15:0 RW crc_engine_init[15:0] 0x0 + */ +typedef union _PRO_CRC_ENGINE_INIT_TYPE +{ + uint16_t d16; + struct + { + uint16_t crc_engine_init_15_0; + }; +} PRO_CRC_ENGINE_INIT_TYPE; + +/* 0x12e + 15:0 RW crc_engine_init[31:16] 0x0 + */ +typedef union _PRO_CRC_ENGINE_INIT1_TYPE +{ + uint16_t d16; + struct + { + uint16_t crc_engine_init_31_16; + }; +} PRO_CRC_ENGINE_INIT1_TYPE; + +/* 0x130 + 15:0 RW crc_engine_polynomial[15:0] 0x0 + */ +typedef union _PRO_CRC_ENGINE_POLY_TYPE +{ + uint16_t d16; + struct + { + uint16_t crc_engine_polynomial_15_0; + }; +} PRO_CRC_ENGINE_POLY_TYPE; + +/* 0x132 + 15:0 RW crc_engine_polynomial[31:16] 0x0 + */ +typedef union _PRO_CRC_ENGINE_POLY1_TYPE +{ + uint16_t d16; + struct + { + uint16_t crc_engine_polynomial_31_16; + }; +} PRO_CRC_ENGINE_POLY1_TYPE; + +/* 0x134 + 15:0 RW crc_engine_input_data[15:0] 0x0 + */ +typedef union _PRO_CRC_ENGINE_IN_TYPE +{ + uint16_t d16; + struct + { + uint16_t crc_engine_input_data_15_0; + }; +} PRO_CRC_ENGINE_IN_TYPE; + +/* 0x136 + 15:0 RW crc_engine_input_data[31:16] 0x0 + */ +typedef union _PRO_CRC_ENGINE_IN1_TYPE +{ + uint16_t d16; + struct + { + uint16_t crc_engine_input_data_31_16; + }; +} PRO_CRC_ENGINE_IN1_TYPE; + +/* 0x138 + 7:0 RW crc_engine_input_data[39:32] 0x0 + 15:8 RO rsvd 0x0 + */ +typedef union _PRO_CRC_ENGINE_IN2_TYPE +{ + uint16_t d16; + struct + { + uint16_t crc_engine_input_data_39_32: 8; + uint16_t rsvd: 8; + }; +} PRO_CRC_ENGINE_IN2_TYPE; + +/* 0x13a + 15:0 RO crc_engine_output[15:0] 0x0 + */ +typedef union _PRO_CRC_ENGINE_OUT_TYPE +{ + uint16_t d16; + struct + { + uint16_t crc_engine_output_15_0; + }; +} PRO_CRC_ENGINE_OUT_TYPE; + +/* 0x13c + 15:0 RO crc_engine_output[31:16] 0x0 + */ +typedef union _PRO_CRC_ENGINE_OUT1_TYPE +{ + uint16_t d16; + struct + { + uint16_t crc_engine_output_31_16; + }; +} PRO_CRC_ENGINE_OUT1_TYPE; + +/* 0x13e + 0 RW crc_engine_en 0x0 + 1 RW crc_engine_rst 0x0 + 4:2 RW crc_engine_field_length 0x0 + 10:5 RW crc_engine_data_length 0x0 + 11 RW crc_engine_cg 0x1 + 12 RW crc_engine_input_endian 0x0 + 13 RW crc_engine_output_endian 0x0 + 14 RW crc_engine_data_length_in_bit 0x1 + 15 RO rsvd 0x0 + */ +typedef union _PRO_CRC_ENGINE_EN_TYPE +{ + uint16_t d16; + struct + { + uint16_t crc_engine_en: 1; + uint16_t crc_engine_rst: 1; + uint16_t crc_engine_field_length: 3; + uint16_t crc_engine_data_length: 6; + uint16_t crc_engine_cg: 1; + uint16_t crc_engine_input_endian: 1; + uint16_t crc_engine_output_endian: 1; + uint16_t crc_engine_data_length_in_bit: 1; + uint16_t rsvd: 1; + }; +} PRO_CRC_ENGINE_EN_TYPE; + +/* 0x140 + 15:0 RW rx_crc_init0[15:0] 0x0 + */ +typedef union _PRO_RX_CRC_INIT0_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t rx_crc_init0_15_0; + }; +} PRO_RX_CRC_INIT0_LOWER_TYPE; + +/* 0x142 + 15:0 RW rx_crc_init0[31:16] 0x0 + */ +typedef union _PRO_RX_CRC_INIT0_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t rx_crc_init0_31_16; + }; +} PRO_RX_CRC_INIT0_UPPER_TYPE; + +/* 0x144 + 15:0 RW rx_crc_init1[15:0] 0x0 + */ +typedef union _PRO_RX_CRC_INIT1_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t rx_crc_init1_15_0; + }; +} PRO_RX_CRC_INIT1_LOWER_TYPE; + +/* 0x146 + 15:0 RW rx_crc_init1[31:16] 0x0 + */ +typedef union _PRO_RX_CRC_INIT1_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t rx_crc_init1_31_16; + }; +} PRO_RX_CRC_INIT1_UPPER_TYPE; + +/* 0x148 + 15:0 RW rx_crc_init2[15:0] 0x0 + */ +typedef union _PRO_RX_CRC_INIT2_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t rx_crc_init2_15_0; + }; +} PRO_RX_CRC_INIT2_LOWER_TYPE; + +/* 0x14a + 15:0 RW rx_crc_init2[31:16] 0x0 + */ +typedef union _PRO_RX_CRC_INIT2_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t rx_crc_init2_31_16; + }; +} PRO_RX_CRC_INIT2_UPPER_TYPE; + +/* 0x14c + 7:0 RW hp_3[7:0] 0x0 + 15:8 RW hp_4[7:0] 0x0 + */ +typedef union _PRO_HP_3_TYPE +{ + uint16_t d16; + struct + { + uint16_t hp_3_7_0: 8; + uint16_t hp_4_7_0: 8; + }; +} PRO_HP_3_TYPE; + +/* 0x14e + 7:0 RW hp_5[7:0] 0x0 + 15:8 RW hp_6[7:0] 0x0 + */ +typedef union _PRO_HP_4_TYPE +{ + uint16_t d16; + struct + { + uint16_t hp_5_7_0: 8; + uint16_t hp_6_7_0: 8; + }; +} PRO_HP_4_TYPE; + +/* 0x150 + 7:0 RW hp_7[7:0] 0x0 + 8 RW fix_entry_option 0x0 + 11:9 RW fix_ptx_entry[2:0] 0x0 + 12 RW fix_entry_rx_option 0x0 + 15:13 RW fix_prx_tx_entry[2:0] 0x0 + */ +typedef union _PRO_HP_5_TYPE +{ + uint16_t d16; + struct + { + uint16_t hp_7_7_0: 8; + uint16_t fix_entry_option: 1; + uint16_t fix_ptx_entry_2_0: 3; + uint16_t fix_entry_rx_option: 1; + uint16_t fix_prx_tx_entry_2_0: 3; + }; +} PRO_HP_5_TYPE; + +/* 0x152 + 15:0 RW hs_3[15:0] 0x0 + */ +typedef union _PRO_HS_3_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t hs_3_15_0; + }; +} PRO_HS_3_LOWER_TYPE; + +/* 0x154 + 14:0 RW hs_3[30:16] 0x0 + 15 RO rsvd 0x0 + */ +typedef union _PRO_HS_3_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t hs_3_30_16: 15; + uint16_t rsvd: 1; + }; +} PRO_HS_3_UPPER_TYPE; + +/* 0x156 + 15:0 RW hs_4[15:0] 0x0 + */ +typedef union _PRO_HS_4_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t hs_4_15_0; + }; +} PRO_HS_4_LOWER_TYPE; + +/* 0x158 + 14:0 RW hs_4[30:16] 0x0 + 15 RO rsvd 0x0 + */ +typedef union _PRO_HS_4_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t hs_4_30_16: 15; + uint16_t rsvd: 1; + }; +} PRO_HS_4_UPPER_TYPE; + +/* 0x15a + 15:0 RW hs_5[15:0] 0x0 + */ +typedef union _PRO_HS_5_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t hs_5_15_0; + }; +} PRO_HS_5_LOWER_TYPE; + +/* 0x15c + 14:0 RW hs_5[30:16] 0x0 + 15 RO rsvd 0x0 + */ +typedef union _PRO_HS_5_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t hs_5_30_16: 15; + uint16_t rsvd: 1; + }; +} PRO_HS_5_UPPER_TYPE; + +/* 0x15e + 15:0 RW hs_6[15:0] 0x0 + */ +typedef union _PRO_HS_6_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t hs_6_15_0; + }; +} PRO_HS_6_LOWER_TYPE; + +/* 0x160 + 14:0 RW hs_6[30:16] 0x0 + 15 RO rsvd 0x0 + */ +typedef union _PRO_HS_6_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t hs_6_30_16: 15; + uint16_t rsvd: 1; + }; +} PRO_HS_6_UPPER_TYPE; + +/* 0x162 + 15:0 RW hs_7[15:0] 0x0 + */ +typedef union _PRO_HS_7_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t hs_7_15_0; + }; +} PRO_HS_7_LOWER_TYPE; + +/* 0x164 + 14:0 RW hs_7[30:16] 0x0 + 15 RO rsvd 0x0 + */ +typedef union _PRO_HS_7_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t hs_7_30_16: 15; + uint16_t rsvd: 1; + }; +} PRO_HS_7_UPPER_TYPE; + +/* 0x166 + 14:0 RW length_3[14:0] 0x0 + 15 RO rsvd 0x0 + */ +typedef union _PRO_LENGTH_3_TYPE +{ + uint16_t d16; + struct + { + uint16_t length_3_14_0: 15; + uint16_t rsvd: 1; + }; +} PRO_LENGTH_3_TYPE; + +/* 0x168 + 14:0 RW length_4[14:0] 0x0 + 15 RO rsvd 0x0 + */ +typedef union _PRO_LENGTH_4_TYPE +{ + uint16_t d16; + struct + { + uint16_t length_4_14_0: 15; + uint16_t rsvd: 1; + }; +} PRO_LENGTH_4_TYPE; + +/* 0x16a + 14:0 RW length_5[14:0] 0x0 + 15 RO rsvd 0x0 + */ +typedef union _PRO_LENGTH_5_TYPE +{ + uint16_t d16; + struct + { + uint16_t length_5_14_0: 15; + uint16_t rsvd: 1; + }; +} PRO_LENGTH_5_TYPE; + +/* 0x16c + 14:0 RW length_6[14:0] 0x0 + 15 RO rsvd 0x0 + */ +typedef union _PRO_LENGTH_6_TYPE +{ + uint16_t d16; + struct + { + uint16_t length_6_14_0: 15; + uint16_t rsvd: 1; + }; +} PRO_LENGTH_6_TYPE; + +/* 0x16e + 14:0 RW length_7[14:0] 0x0 + 15 RO rsvd 0x0 + */ +typedef union _PRO_LENGTH_7_TYPE +{ + uint16_t d16; + struct + { + uint16_t length_7_14_0: 15; + uint16_t rsvd: 1; + }; +} PRO_LENGTH_7_TYPE; + +/* 0x170 + 7:0 RW add_on_length3[7:0] 0x0 + 15:8 RW add_on_length4[7:0] 0x0 + */ +typedef union _PRO_ADD_ON_LENGTH3_TYPE +{ + uint16_t d16; + struct + { + uint16_t add_on_length3_7_0: 8; + uint16_t add_on_length4_7_0: 8; + }; +} PRO_ADD_ON_LENGTH3_TYPE; + +/* 0x172 + 7:0 RW add_on_length5[7:0] 0x0 + 15:8 RW add_on_length6[7:0] 0x0 + */ +typedef union _PRO_ADD_ON_LENGTH4_TYPE +{ + uint16_t d16; + struct + { + uint16_t add_on_length5_7_0: 8; + uint16_t add_on_length6_7_0: 8; + }; +} PRO_ADD_ON_LENGTH4_TYPE; + +/* 0x174 + 7:0 RW add_on_length7[7:0] 0x0 + 15:8 RO rsvd 0x0 + */ +typedef union _PRO_ADD_ON_LENGTH5_TYPE +{ + uint16_t d16; + struct + { + uint16_t add_on_length7_7_0: 8; + uint16_t rsvd: 8; + }; +} PRO_ADD_ON_LENGTH5_TYPE; + +/* 0x176 + 15:0 RW crc_init3[15:0] 0x0 + */ +typedef union _PRO_CRC_INIT3_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t crc_init3_15_0; + }; +} PRO_CRC_INIT3_LOWER_TYPE; + +/* 0x178 + 15:0 RW crc_init3[31:16] 0x0 + */ +typedef union _PRO_CRC_INIT3_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t crc_init3_31_16; + }; +} PRO_CRC_INIT3_UPPER_TYPE; + +/* 0x17a + 15:0 RW crc_init4[15:0] 0x0 + */ +typedef union _PRO_CRC_INIT4_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t crc_init4_15_0; + }; +} PRO_CRC_INIT4_LOWER_TYPE; + +/* 0x17c + 15:0 RW crc_init4[31:16] 0x0 + */ +typedef union _PRO_CRC_INIT4_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t crc_init4_31_16; + }; +} PRO_CRC_INIT4_UPPER_TYPE; + +/* 0x17e + 15:0 RW crc_init5[15:0] 0x0 + */ +typedef union _PRO_CRC_INIT5_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t crc_init5_15_0; + }; +} PRO_CRC_INIT5_LOWER_TYPE; + +/* 0x180 + 15:0 RW crc_init5[31:16] 0x0 + */ +typedef union _PRO_CRC_INIT5_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t crc_init5_31_16; + }; +} PRO_CRC_INIT5_UPPER_TYPE; + +/* 0x182 + 15:0 RW crc_init6[15:0] 0x0 + */ +typedef union _PRO_CRC_INIT6_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t crc_init6_15_0; + }; +} PRO_CRC_INIT6_LOWER_TYPE; + +/* 0x184 + 15:0 RW crc_init6[31:16] 0x0 + */ +typedef union _PRO_CRC_INIT6_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t crc_init6_31_16; + }; +} PRO_CRC_INIT6_UPPER_TYPE; + +/* 0x186 + 15:0 RW crc_init7[15:0] 0x0 + */ +typedef union _PRO_CRC_INIT7_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t crc_init7_15_0; + }; +} PRO_CRC_INIT7_LOWER_TYPE; + +/* 0x188 + 15:0 RW crc_init7[31:16] 0x0 + */ +typedef union _PRO_CRC_INIT7_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t crc_init7_31_16; + }; +} PRO_CRC_INIT7_UPPER_TYPE; + +/* 0x18a + 15:0 RW rx_crc_init3[15:0] 0x0 + */ +typedef union _PRO_RX_CRC_INIT3_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t rx_crc_init3_15_0; + }; +} PRO_RX_CRC_INIT3_LOWER_TYPE; + +/* 0x18c + 15:0 RW rx_crc_init3[31:16] 0x0 + */ +typedef union _PRO_RX_CRC_INIT3_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t rx_crc_init3_31_16; + }; +} PRO_RX_CRC_INIT3_UPPER_TYPE; + +/* 0x18e + 15:0 RW rx_crc_init4[15:0] 0x0 + */ +typedef union _PRO_RX_CRC_INIT4_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t rx_crc_init4_15_0; + }; +} PRO_RX_CRC_INIT4_LOWER_TYPE; + +/* 0x190 + 15:0 RW rx_crc_init4[31:16] 0x0 + */ +typedef union _PRO_RX_CRC_INIT4_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t rx_crc_init4_31_16; + }; +} PRO_RX_CRC_INIT4_UPPER_TYPE; + +/* 0x192 + 15:0 RW rx_crc_init5[15:0] 0x0 + */ +typedef union _PRO_RX_CRC_INIT5_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t rx_crc_init5_15_0; + }; +} PRO_RX_CRC_INIT5_LOWER_TYPE; + +/* 0x194 + 15:0 RW rx_crc_init5[31:16] 0x0 + */ +typedef union _PRO_RX_CRC_INIT5_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t rx_crc_init5_31_16; + }; +} PRO_RX_CRC_INIT5_UPPER_TYPE; + +/* 0x196 + 15:0 RW rx_crc_init6[15:0] 0x0 + */ +typedef union _PRO_RX_CRC_INIT6_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t rx_crc_init6_15_0; + }; +} PRO_RX_CRC_INIT6_LOWER_TYPE; + +/* 0x198 + 15:0 RW rx_crc_init6[31:16] 0x0 + */ +typedef union _PRO_RX_CRC_INIT6_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t rx_crc_init6_31_16; + }; +} PRO_RX_CRC_INIT6_UPPER_TYPE; + +/* 0x19a + 15:0 RW rx_crc_init7[15:0] 0x0 + */ +typedef union _PRO_RX_CRC_INIT7_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t rx_crc_init7_15_0; + }; +} PRO_RX_CRC_INIT7_LOWER_TYPE; + +/* 0x19c + 15:0 RW rx_crc_init7[31:16] 0x0 + */ +typedef union _PRO_RX_CRC_INIT7_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t rx_crc_init7_31_16; + }; +} PRO_RX_CRC_INIT7_UPPER_TYPE; + +/* 0x19e + 15:0 RW white_init3[15:0] 0x0 + */ +typedef union _PRO_WHITE_INIT3_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t white_init3_15_0; + }; +} PRO_WHITE_INIT3_LOWER_TYPE; + +/* 0x1a0 + 15:0 RW white_init3[31:16] 0x0 + */ +typedef union _PRO_WHITE_INIT3_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t white_init3_31_16; + }; +} PRO_WHITE_INIT3_UPPER_TYPE; + +/* 0x1a2 + 15:0 RW white_init4[15:0] 0x0 + */ +typedef union _PRO_WHITE_INIT4_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t white_init4_15_0; + }; +} PRO_WHITE_INIT4_LOWER_TYPE; + +/* 0x1a4 + 15:0 RW white_init4[31:16] 0x0 + */ +typedef union _PRO_WHITE_INIT4_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t white_init4_31_16; + }; +} PRO_WHITE_INIT4_UPPER_TYPE; + +/* 0x1a6 + 15:0 RW white_init5[15:0] 0x0 + */ +typedef union _PRO_WHITE_INIT5_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t white_init5_15_0; + }; +} PRO_WHITE_INIT5_LOWER_TYPE; + +/* 0x1a8 + 15:0 RW white_init5[31:16] 0x0 + */ +typedef union _PRO_WHITE_INIT5_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t white_init5_31_16; + }; +} PRO_WHITE_INIT5_UPPER_TYPE; + +/* 0x1aa + 15:0 RW white_init6[15:0] 0x0 + */ +typedef union _PRO_WHITE_INIT6_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t white_init6_15_0; + }; +} PRO_WHITE_INIT6_LOWER_TYPE; + +/* 0x1ac + 15:0 RW white_init6[31:16] 0x0 + */ +typedef union _PRO_WHITE_INIT6_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t white_init6_31_16; + }; +} PRO_WHITE_INIT6_UPPER_TYPE; + +/* 0x1ae + 15:0 RW white_init7[15:0] 0x0 + */ +typedef union _PRO_WHITE_INIT7_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t white_init7_15_0; + }; +} PRO_WHITE_INIT7_LOWER_TYPE; + +/* 0x1b0 + 15:0 RW white_init7[31:16] 0x0 + */ +typedef union _PRO_WHITE_INIT7_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t white_init7_31_16; + }; +} PRO_WHITE_INIT7_UPPER_TYPE; + +/* 0x1b2 + 15:0 RW white_polynomial_reg3[15:0] 0x0 + */ +typedef union _PRO_WHITE_POLYNOMIAL_REG3_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t white_polynomial_reg3_15_0; + }; +} PRO_WHITE_POLYNOMIAL_REG3_LOWER_TYPE; + +/* 0x1b4 + 15:0 RW white_polynomial_reg3[31:16] 0x0 + */ +typedef union _PRO_WHITE_POLYNOMIAL_REG3_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t white_polynomial_reg3_31_16; + }; +} PRO_WHITE_POLYNOMIAL_REG3_UPPER_TYPE; + +/* 0x1b6 + 15:0 RW white_polynomial_reg4[15:0] 0x0 + */ +typedef union _PRO_WHITE_POLYNOMIAL_REG4_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t white_polynomial_reg4_15_0; + }; +} PRO_WHITE_POLYNOMIAL_REG4_LOWER_TYPE; + +/* 0x1b8 + 15:0 RW white_polynomial_reg4[31:16] 0x0 + */ +typedef union _PRO_WHITE_POLYNOMIAL_REG4_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t white_polynomial_reg4_31_16; + }; +} PRO_WHITE_POLYNOMIAL_REG4_UPPER_TYPE; + +/* 0x1ba + 15:0 RW white_polynomial_reg5[15:0] 0x0 + */ +typedef union _PRO_WHITE_POLYNOMIAL_REG5_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t white_polynomial_reg5_15_0; + }; +} PRO_WHITE_POLYNOMIAL_REG5_LOWER_TYPE; + +/* 0x1bc + 15:0 RW white_polynomial_reg5[31:16] 0x0 + */ +typedef union _PRO_WHITE_POLYNOMIAL_REG5_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t white_polynomial_reg5_31_16; + }; +} PRO_WHITE_POLYNOMIAL_REG5_UPPER_TYPE; + +/* 0x1be + 15:0 RW white_polynomial_reg6[15:0] 0x0 + */ +typedef union _PRO_WHITE_POLYNOMIAL_REG6_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t white_polynomial_reg6_15_0; + }; +} PRO_WHITE_POLYNOMIAL_REG6_LOWER_TYPE; + +/* 0x1c0 + 15:0 RW white_polynomial_reg6[31:16] 0x0 + */ +typedef union _PRO_WHITE_POLYNOMIAL_REG6_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t white_polynomial_reg6_31_16; + }; +} PRO_WHITE_POLYNOMIAL_REG6_UPPER_TYPE; + +/* 0x1c2 + 15:0 RW white_polynomial_reg7[15:0] 0x0 + */ +typedef union _PRO_WHITE_POLYNOMIAL_REG7_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t white_polynomial_reg7_15_0; + }; +} PRO_WHITE_POLYNOMIAL_REG7_LOWER_TYPE; + +/* 0x1c4 + 15:0 RW white_polynomial_reg7[31:16] 0x0 + */ +typedef union _PRO_WHITE_POLYNOMIAL_REG7_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t white_polynomial_reg7_31_16; + }; +} PRO_WHITE_POLYNOMIAL_REG7_UPPER_TYPE; + +/* 0x1c6 + 15:0 RW crc_polynomial_reg3[15:0] 0x0 + */ +typedef union _PRO_CRC_POLYNOMIAL_REG3_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t crc_polynomial_reg3_15_0; + }; +} PRO_CRC_POLYNOMIAL_REG3_LOWER_TYPE; + +/* 0x1c8 + 15:0 RW crc_polynomial_reg3[31:16] 0x0 + */ +typedef union _PRO_CRC_POLYNOMIAL_REG3_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t crc_polynomial_reg3_31_16; + }; +} PRO_CRC_POLYNOMIAL_REG3_UPPER_TYPE; + +/* 0x1ca + 15:0 RW crc_polynomial_reg4[15:0] 0x0 + */ +typedef union _PRO_CRC_POLYNOMIAL_REG4_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t crc_polynomial_reg4_15_0; + }; +} PRO_CRC_POLYNOMIAL_REG4_LOWER_TYPE; + +/* 0x1cc + 15:0 RW crc_polynomial_reg4[31:16] 0x0 + */ +typedef union _PRO_CRC_POLYNOMIAL_REG4_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t crc_polynomial_reg4_31_16; + }; +} PRO_CRC_POLYNOMIAL_REG4_UPPER_TYPE; + +/* 0x1ce + 15:0 RW crc_polynomial_reg5[15:0] 0x0 + */ +typedef union _PRO_CRC_POLYNOMIAL_REG5_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t crc_polynomial_reg5_15_0; + }; +} PRO_CRC_POLYNOMIAL_REG5_LOWER_TYPE; + +/* 0x1d0 + 15:0 RW crc_polynomial_reg5[31:16] 0x0 + */ +typedef union _PRO_CRC_POLYNOMIAL_REG5_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t crc_polynomial_reg5_31_16; + }; +} PRO_CRC_POLYNOMIAL_REG5_UPPER_TYPE; + +/* 0x1d2 + 15:0 RW crc_polynomial_reg6[15:0] 0x0 + */ +typedef union _PRO_CRC_POLYNOMIAL_REG6_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t crc_polynomial_reg6_15_0; + }; +} PRO_CRC_POLYNOMIAL_REG6_LOWER_TYPE; + +/* 0x1d4 + 15:0 RW crc_polynomial_reg6[31:16] 0x0 + */ +typedef union _PRO_CRC_POLYNOMIAL_REG6_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t crc_polynomial_reg6_31_16; + }; +} PRO_CRC_POLYNOMIAL_REG6_UPPER_TYPE; + +/* 0x1d6 + 15:0 RW crc_polynomial_reg7[15:0] 0x0 + */ +typedef union _PRO_CRC_POLYNOMIAL_REG7_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t crc_polynomial_reg7_15_0; + }; +} PRO_CRC_POLYNOMIAL_REG7_LOWER_TYPE; + +/* 0x1d8 + 15:0 RW crc_polynomial_reg7[31:16] 0x0 + */ +typedef union _PRO_CRC_POLYNOMIAL_REG7_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t crc_polynomial_reg7_31_16; + }; +} PRO_CRC_POLYNOMIAL_REG7_UPPER_TYPE; + +/* 0x1da + 7:0 RO rx_pkt_num2 0x0 + 15:8 RO rx_pkt_num3 0x0 + */ +typedef union _PRO_RX_PKT_NUM0_TYPE +{ + uint16_t d16; + struct + { + uint16_t rx_pkt_num2: 8; + uint16_t rx_pkt_num3: 8; + }; +} PRO_RX_PKT_NUM0_TYPE; + +/* 0x1dc + 7:0 RO rx_pkt_num4 0x0 + 15:8 RO rx_pkt_num5 0x0 + */ +typedef union _PRO_RX_PKT_NUM1_TYPE +{ + uint16_t d16; + struct + { + uint16_t rx_pkt_num4: 8; + uint16_t rx_pkt_num5: 8; + }; +} PRO_RX_PKT_NUM1_TYPE; + +/* 0x1de + 7:0 RO rx_pkt_num6 0x0 + 15:8 RO rx_pkt_num7 0x0 + */ +typedef union _PRO_RX_PKT_NUM2_TYPE +{ + uint16_t d16; + struct + { + uint16_t rx_pkt_num6: 8; + uint16_t rx_pkt_num7: 8; + }; +} PRO_RX_PKT_NUM2_TYPE; + +/* 0x1e0 + 7:0 RO tx_pkt_num3 0x0 + 15:8 RO tx_pkt_num4 0x0 + */ +typedef union _PRO_TX_PKT_NUM3_TYPE +{ + uint16_t d16; + struct + { + uint16_t tx_pkt_num3: 8; + uint16_t tx_pkt_num4: 8; + }; +} PRO_TX_PKT_NUM3_TYPE; + +/* 0x1e2 + 7:0 RO tx_pkt_num5 0x0 + 15:8 RO tx_pkt_num6 0x0 + */ +typedef union _PRO_TX_PKT_NUM4_TYPE +{ + uint16_t d16; + struct + { + uint16_t tx_pkt_num5: 8; + uint16_t tx_pkt_num6: 8; + }; +} PRO_TX_PKT_NUM4_TYPE; + +/* 0x1e4 + 7:0 RO tx_pkt_num7 0x0 + 15:8 RO rsvd 0x0 + */ +typedef union _PRO_TX_PKT_NUM5_TYPE +{ + uint16_t d16; + struct + { + uint16_t tx_pkt_num7: 8; + uint16_t rsvd: 8; + }; +} PRO_TX_PKT_NUM5_TYPE; + +/* 0x1e6 + 5:0 RW white_field_length3 0x0 + 6 RW reset_rx_pktnum2 0x0 + 7 RW lock3 0x0 + 8 RW no_tx3 0x0 + 9 RW auto_no_tx_option3 0x0 + 10 RW clear_hw_no_tx3 0x0 + 11 RO read_clear_hw_no_tx3 0x0 + 12 RW empty_flag3 0x0 + 13 RW fw_ack3 0x0 + 14 RW tx_phy3 0x0 + 15 RW reset_rx_pktnum3 0x0 + */ +typedef union _PRO_WHITE_FIELD_LENGTH_0_TYPE +{ + uint16_t d16; + struct + { + uint16_t white_field_length3: 6; + uint16_t reset_rx_pktnum2: 1; + uint16_t lock3: 1; + uint16_t no_tx3: 1; + uint16_t auto_no_tx_option3: 1; + uint16_t clear_hw_no_tx3: 1; + uint16_t read_clear_hw_no_tx3: 1; + uint16_t empty_flag3: 1; + uint16_t fw_ack3: 1; + uint16_t tx_phy3: 1; + uint16_t reset_rx_pktnum3: 1; + }; +} PRO_WHITE_FIELD_LENGTH_0_TYPE; + +/* 0x1e8 + 5:0 RW white_field_length4 0x0 + 6 RO rsvd 0x0 + 7 RW lock4 0x0 + 8 RW no_tx4 0x0 + 9 RW auto_no_tx_option4 0x0 + 10 RW clear_hw_no_tx4 0x0 + 11 RO read_clear_hw_no_tx4 0x0 + 12 RW empty_flag4 0x0 + 13 RW fw_ack4 0x0 + 14 RW tx_phy4 0x0 + 15 RW reset_rx_pktnum4 0x0 + */ +typedef union _PRO_WHITE_FIELD_LENGTH_1_TYPE +{ + uint16_t d16; + struct + { + uint16_t white_field_length4: 6; + uint16_t rsvd: 1; + uint16_t lock4: 1; + uint16_t no_tx4: 1; + uint16_t auto_no_tx_option4: 1; + uint16_t clear_hw_no_tx4: 1; + uint16_t read_clear_hw_no_tx4: 1; + uint16_t empty_flag4: 1; + uint16_t fw_ack4: 1; + uint16_t tx_phy4: 1; + uint16_t reset_rx_pktnum4: 1; + }; +} PRO_WHITE_FIELD_LENGTH_1_TYPE; + +/* 0x1ea + 5:0 RW white_field_length5 0x0 + 6 RO rsvd 0x0 + 7 RW lock5 0x0 + 8 RW no_tx5 0x0 + 9 RW auto_no_tx_option5 0x0 + 10 RW clear_hw_no_tx5 0x0 + 11 RO read_clear_hw_no_tx5 0x0 + 12 RW empty_flag5 0x0 + 13 RW fw_ack5 0x0 + 14 RW tx_phy5 0x0 + 15 RW reset_rx_pktnum5 0x0 + */ +typedef union _PRO_WHITE_FIELD_LENGTH_2_TYPE +{ + uint16_t d16; + struct + { + uint16_t white_field_length5: 6; + uint16_t rsvd: 1; + uint16_t lock5: 1; + uint16_t no_tx5: 1; + uint16_t auto_no_tx_option5: 1; + uint16_t clear_hw_no_tx5: 1; + uint16_t read_clear_hw_no_tx5: 1; + uint16_t empty_flag5: 1; + uint16_t fw_ack5: 1; + uint16_t tx_phy5: 1; + uint16_t reset_rx_pktnum5: 1; + }; +} PRO_WHITE_FIELD_LENGTH_2_TYPE; + +/* 0x1ec + 5:0 RW white_field_length6 0x0 + 6 RO rsvd 0x0 + 7 RW lock6 0x0 + 8 RW no_tx6 0x0 + 9 RW auto_no_tx_option6 0x0 + 10 RW clear_hw_no_tx6 0x0 + 11 RO read_clear_hw_no_tx6 0x0 + 12 RW empty_flag6 0x0 + 13 RW fw_ack6 0x0 + 14 RW tx_phy6 0x0 + 15 RW reset_rx_pktnum6 0x0 + */ +typedef union _PRO_WHITE_FIELD_LENGTH_3_TYPE +{ + uint16_t d16; + struct + { + uint16_t white_field_length6: 6; + uint16_t rsvd: 1; + uint16_t lock6: 1; + uint16_t no_tx6: 1; + uint16_t auto_no_tx_option6: 1; + uint16_t clear_hw_no_tx6: 1; + uint16_t read_clear_hw_no_tx6: 1; + uint16_t empty_flag6: 1; + uint16_t fw_ack6: 1; + uint16_t tx_phy6: 1; + uint16_t reset_rx_pktnum6: 1; + }; +} PRO_WHITE_FIELD_LENGTH_3_TYPE; + +/* 0x1ee + 5:0 RW white_field_length7 0x0 + 6 RO rsvd 0x0 + 7 RW lock7 0x0 + 8 RW no_tx7 0x0 + 9 RW auto_no_tx_option7 0x0 + 10 RW clear_hw_no_tx7 0x0 + 11 RO read_clear_hw_no_tx7 0x0 + 12 RW empty_flag7 0x0 + 13 RW fw_ack7 0x0 + 14 RW tx_phy7 0x0 + 15 RW reset_rx_pktnum7 0x0 + */ +typedef union _PRO_WHITE_FIELD_LENGTH_4_TYPE +{ + uint16_t d16; + struct + { + uint16_t white_field_length7: 6; + uint16_t rsvd: 1; + uint16_t lock7: 1; + uint16_t no_tx7: 1; + uint16_t auto_no_tx_option7: 1; + uint16_t clear_hw_no_tx7: 1; + uint16_t read_clear_hw_no_tx7: 1; + uint16_t empty_flag7: 1; + uint16_t fw_ack7: 1; + uint16_t tx_phy7: 1; + uint16_t reset_rx_pktnum7: 1; + }; +} PRO_WHITE_FIELD_LENGTH_4_TYPE; + +/* 0x1f0 + 2:0 RW preamble_field_length3[2:0] 0x0 + 3 RW clear_hw_rd_ptr3 0x0 + 4 RO read_clear_hw_rd_ptr3 0x0 + 5 RW auto_add_rptr_option3 0x0 + 8:6 RW fw_rd_ptr3 0x0 + 9 RW auto_no_rdptr_option3 0x0 + 10 RW reset_tx_pktnum3 0x0 + 15:11 RO rsvd 0x0 + */ +typedef union _PRO_FIELD_LENGTH3_TYPE +{ + uint16_t d16; + struct + { + uint16_t preamble_field_length3_2_0: 3; + uint16_t clear_hw_rd_ptr3: 1; + uint16_t read_clear_hw_rd_ptr3: 1; + uint16_t auto_add_rptr_option3: 1; + uint16_t fw_rd_ptr3: 3; + uint16_t auto_no_rdptr_option3: 1; + uint16_t reset_tx_pktnum3: 1; + uint16_t rsvd: 5; + }; +} PRO_FIELD_LENGTH3_TYPE; + +/* 0x1f2 + 2:0 RW preamble_field_length4[2:0] 0x0 + 3 RW clear_hw_rd_ptr4 0x0 + 4 RO read_clear_hw_rd_ptr4 0x0 + 5 RW auto_add_rptr_option4 0x0 + 8:6 RW fw_rd_ptr4 0x0 + 9 RW auto_no_rdptr_option4 0x0 + 10 RW reset_tx_pktnum4 0x0 + 15:11 RO rsvd 0x0 + */ +typedef union _PRO_FIELD_LENGTH4_TYPE +{ + uint16_t d16; + struct + { + uint16_t preamble_field_length4_2_0: 3; + uint16_t clear_hw_rd_ptr4: 1; + uint16_t read_clear_hw_rd_ptr4: 1; + uint16_t auto_add_rptr_option4: 1; + uint16_t fw_rd_ptr4: 3; + uint16_t auto_no_rdptr_option4: 1; + uint16_t reset_tx_pktnum4: 1; + uint16_t rsvd: 5; + }; +} PRO_FIELD_LENGTH4_TYPE; + +/* 0x1f4 + 2:0 RW preamble_field_length5[2:0] 0x0 + 3 RW clear_hw_rd_ptr5 0x0 + 4 RO read_clear_hw_rd_ptr5 0x0 + 5 RW auto_add_rptr_option5 0x0 + 8:6 RW fw_rd_ptr5 0x0 + 9 RW auto_no_rdptr_option5 0x0 + 10 RW reset_tx_pktnum5 0x0 + 15:11 RO rsvd 0x0 + */ +typedef union _PRO_FIELD_LENGTH5_TYPE +{ + uint16_t d16; + struct + { + uint16_t preamble_field_length5_2_0: 3; + uint16_t clear_hw_rd_ptr5: 1; + uint16_t read_clear_hw_rd_ptr5: 1; + uint16_t auto_add_rptr_option5: 1; + uint16_t fw_rd_ptr5: 3; + uint16_t auto_no_rdptr_option5: 1; + uint16_t reset_tx_pktnum5: 1; + uint16_t rsvd: 5; + }; +} PRO_FIELD_LENGTH5_TYPE; + +/* 0x1f6 + 2:0 RW preamble_field_length6[2:0] 0x0 + 3 RW clear_hw_rd_ptr6 0x0 + 4 RO read_clear_hw_rd_ptr6 0x0 + 5 RW auto_add_rptr_option6 0x0 + 8:6 RW fw_rd_ptr6 0x0 + 9 RW auto_no_rdptr_option6 0x0 + 10 RW reset_tx_pktnum6 0x0 + 15:11 RO rsvd 0x0 + */ +typedef union _PRO_FIELD_LENGTH6_TYPE +{ + uint16_t d16; + struct + { + uint16_t preamble_field_length6_2_0: 3; + uint16_t clear_hw_rd_ptr6: 1; + uint16_t read_clear_hw_rd_ptr6: 1; + uint16_t auto_add_rptr_option6: 1; + uint16_t fw_rd_ptr6: 3; + uint16_t auto_no_rdptr_option6: 1; + uint16_t reset_tx_pktnum6: 1; + uint16_t rsvd: 5; + }; +} PRO_FIELD_LENGTH6_TYPE; + +/* 0x1f8 + 2:0 RW preamble_field_length7[2:0] 0x0 + 3 RW clear_hw_rd_ptr7 0x0 + 4 RO read_clear_hw_rd_ptr7 0x0 + 5 RW auto_add_rptr_option7 0x0 + 8:6 RW fw_rd_ptr7 0x0 + 9 RW auto_no_rdptr_option7 0x0 + 10 RW reset_tx_pktnum7 0x0 + 15:11 RO rsvd 0x0 + */ +typedef union _PRO_FIELD_LENGTH7_TYPE +{ + uint16_t d16; + struct + { + uint16_t preamble_field_length7_2_0: 3; + uint16_t clear_hw_rd_ptr7: 1; + uint16_t read_clear_hw_rd_ptr7: 1; + uint16_t auto_add_rptr_option7: 1; + uint16_t fw_rd_ptr7: 3; + uint16_t auto_no_rdptr_option7: 1; + uint16_t reset_tx_pktnum7: 1; + uint16_t rsvd: 5; + }; +} PRO_FIELD_LENGTH7_TYPE; + +/* 0x1fa + 15:0 RW tx_address1[15:0] 0x0 + */ +typedef union _PRO_TX_ADDRESS1_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t tx_address1_15_0; + }; +} PRO_TX_ADDRESS1_LOWER_TYPE; + +/* 0x1fc + 15:0 RW tx_address1[31:16] 0x0 + */ +typedef union _PRO_TX_ADDRESS1_MIDDLE_TYPE +{ + uint16_t d16; + struct + { + uint16_t tx_address1_31_16; + }; +} PRO_TX_ADDRESS1_MIDDLE_TYPE; + +/* 0x1fe + 7:0 RW tx_address1[39:32] 0x0 + 15:8 RO rsvd 0x0 + */ +typedef union _PRO_TX_ADDRESS1_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t tx_address1_39_32: 8; + uint16_t rsvd: 8; + }; +} PRO_TX_ADDRESS1_UPPER_TYPE; + +/* 0x200 + 15:0 RW tx_address3[15:0] 0x0 + */ +typedef union _PRO_TX_ADDRESS3_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t tx_address3_15_0; + }; +} PRO_TX_ADDRESS3_LOWER_TYPE; + +/* 0x202 + 15:0 RW tx_address3[31:16] 0x0 + */ +typedef union _PRO_TX_ADDRESS3_MIDDLE_TYPE +{ + uint16_t d16; + struct + { + uint16_t tx_address3_31_16; + }; +} PRO_TX_ADDRESS3_MIDDLE_TYPE; + +/* 0x204 + 7:0 RW tx_address3[39:32] 0x0 + 15:8 RO rsvd 0x0 + */ +typedef union _PRO_TX_ADDRESS3_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t tx_address3_39_32: 8; + uint16_t rsvd: 8; + }; +} PRO_TX_ADDRESS3_UPPER_TYPE; + +/* 0x206 + 15:0 RW tx_address4[15:0] 0x0 + */ +typedef union _PRO_TX_ADDRESS4_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t tx_address4_15_0; + }; +} PRO_TX_ADDRESS4_LOWER_TYPE; + +/* 0x208 + 15:0 RW tx_address4[31:16] 0x0 + */ +typedef union _PRO_TX_ADDRESS4_MIDDLE_TYPE +{ + uint16_t d16; + struct + { + uint16_t tx_address4_31_16; + }; +} PRO_TX_ADDRESS4_MIDDLE_TYPE; + +/* 0x20a + 7:0 RW tx_address4[39:32] 0x0 + 15:8 RO rsvd 0x0 + */ +typedef union _PRO_TX_ADDRESS4_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t tx_address4_39_32: 8; + uint16_t rsvd: 8; + }; +} PRO_TX_ADDRESS4_UPPER_TYPE; + +/* 0x20c + 15:0 RW tx_address5[15:0] 0x0 + */ +typedef union _PRO_TX_ADDRESS5_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t tx_address5_15_0; + }; +} PRO_TX_ADDRESS5_LOWER_TYPE; + +/* 0x20e + 15:0 RW tx_address5[31:16] 0x0 + */ +typedef union _PRO_TX_ADDRESS5_MIDDLE_TYPE +{ + uint16_t d16; + struct + { + uint16_t tx_address5_31_16; + }; +} PRO_TX_ADDRESS5_MIDDLE_TYPE; + +/* 0x210 + 7:0 RW tx_address5[39:32] 0x0 + 15:8 RO rsvd 0x0 + */ +typedef union _PRO_TX_ADDRESS5_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t tx_address5_39_32: 8; + uint16_t rsvd: 8; + }; +} PRO_TX_ADDRESS5_UPPER_TYPE; + +/* 0x212 + 15:0 RW tx_address6[15:0] 0x0 + */ +typedef union _PRO_TX_ADDRESS6_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t tx_address6_15_0; + }; +} PRO_TX_ADDRESS6_LOWER_TYPE; + +/* 0x214 + 15:0 RW tx_address6[31:16] 0x0 + */ +typedef union _PRO_TX_ADDRESS6_MIDDLE_TYPE +{ + uint16_t d16; + struct + { + uint16_t tx_address6_31_16; + }; +} PRO_TX_ADDRESS6_MIDDLE_TYPE; + +/* 0x216 + 7:0 RW tx_address6[39:32] 0x0 + 15:8 RO rsvd 0x0 + */ +typedef union _PRO_TX_ADDRESS6_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t tx_address6_39_32: 8; + uint16_t rsvd: 8; + }; +} PRO_TX_ADDRESS6_UPPER_TYPE; + +/* 0x218 + 15:0 RW tx_address7[15:0] 0x0 + */ +typedef union _PRO_TX_ADDRESS7_LOWER_TYPE +{ + uint16_t d16; + struct + { + uint16_t tx_address7_15_0; + }; +} PRO_TX_ADDRESS7_LOWER_TYPE; + +/* 0x21a + 15:0 RW tx_address7[31:16] 0x0 + */ +typedef union _PRO_TX_ADDRESS7_MIDDLE_TYPE +{ + uint16_t d16; + struct + { + uint16_t tx_address7_31_16; + }; +} PRO_TX_ADDRESS7_MIDDLE_TYPE; + +/* 0x21c + 7:0 RW tx_address7[39:32] 0x0 + 15:8 RO rsvd 0x0 + */ +typedef union _PRO_TX_ADDRESS7_UPPER_TYPE +{ + uint16_t d16; + struct + { + uint16_t tx_address7_39_32: 8; + uint16_t rsvd: 8; + }; +} PRO_TX_ADDRESS7_UPPER_TYPE; + +/* 0x21e + 2:0 RO rd_ptr0[2:0] 0x0 + 5:3 RO rd_ptr1[2:0] 0x0 + 8:6 RO rd_ptr2[2:0] 0x0 + 11:9 RO rd_ptr3[2:0] 0x0 + 14:12 RO rd_ptr4[2:0] 0x0 + 15 RO rsvd 0x0 + */ +typedef union _PRO_RD_PTR_0_TYPE +{ + uint16_t d16; + struct + { + uint16_t rd_ptr0_2_0: 3; + uint16_t rd_ptr1_2_0: 3; + uint16_t rd_ptr2_2_0: 3; + uint16_t rd_ptr3_2_0: 3; + uint16_t rd_ptr4_2_0: 3; + uint16_t rsvd: 1; + }; +} PRO_RD_PTR_0_TYPE; + +/* 0x220 + 2:0 RO rd_ptr5[2:0] 0x0 + 5:3 RO rd_ptr6[2:0] 0x0 + 8:6 RO rd_ptr7[2:0] 0x0 + 15:9 RO rsvd 0x0 + */ +typedef union _PRO_RD_PTR_1_TYPE +{ + uint16_t d16; + struct + { + uint16_t rd_ptr5_2_0: 3; + uint16_t rd_ptr6_2_0: 3; + uint16_t rd_ptr7_2_0: 3; + uint16_t rsvd: 7; + }; +} PRO_RD_PTR_1_TYPE; + diff --git a/bee/drivers/ppt/driver/common/rtl87x2g/ppt_pf.h b/bee/drivers/ppt/driver/common/rtl87x2g/ppt_pf.h new file mode 100644 index 00000000..b35fb926 --- /dev/null +++ b/bee/drivers/ppt/driver/common/rtl87x2g/ppt_pf.h @@ -0,0 +1,57 @@ +/** +***************************************************************************************** +* Copyright(c) 2020, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file ppt_pf.h + * @brief Head file for 2.4G module platform related driver. + * @details data structs and external functions declaration. + * @author bill + * @date 2023-10-27 + * @version v0.1 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _PPT_PF_H_ +#define _PPT_PF_H_ + +/* Add Includes here */ +#include "debug_port.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** @addtogroup PPT_PF + * @{ + */ + +/** @defgroup PPT_PF_Exported_Macros Exported Macros + * @brief + * @{ + */ + +/** @} End of PPT_PF_Exported_Macros */ + +/** @defgroup PPT_PF_Exported_Types Exported Types + * @brief + * @{ + */ + +/** @} End of PPT_PF_Exported_Types */ + +/** @defgroup PPT_PF_Exported_Functions Exported Functions + * @brief + * @{ + */ + + +/** @} End of PPT_PF_Exported_Functions */ + +/** @} End of PPT_PF */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/bee/drivers/ppt/driver/common/rtl87x2g/ppt_pm.h b/bee/drivers/ppt/driver/common/rtl87x2g/ppt_pm.h new file mode 100644 index 00000000..50fc3806 --- /dev/null +++ b/bee/drivers/ppt/driver/common/rtl87x2g/ppt_pm.h @@ -0,0 +1,59 @@ +/** +***************************************************************************************** +* Copyright(c) 2020, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file ppt_pm.h + * @brief Head file for 2.4G module power driver. + * @details data structs and external functions declaration. + * @author bill + * @date 2023-10-27 + * @version v0.1 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _PPT_PM_H_ +#define _PPT_PM_H_ + +/* Add Includes here */ +#include "power_manager_interface.h" +#include "power_manager_slave.h" +#include "power_manager_unit_platform.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** @addtogroup PPT_PM + * @{ + */ + +/** @defgroup PPT_PM_Exported_Macros Exported Macros + * @brief + * @{ + */ + +/** @} End of PPT_PM_Exported_Macros */ + +/** @defgroup PPT_PM_Exported_Types Exported Types + * @brief + * @{ + */ + +/** @} End of PPT_PM_Exported_Types */ + +/** @defgroup PPT_PM_Exported_Functions Exported Functions + * @brief + * @{ + */ + + +/** @} End of PPT_PM_Exported_Functions */ + +/** @} End of PPT_PM */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/bee/drivers/ppt/driver/simple/ppt_simple.c b/bee/drivers/ppt/driver/simple/ppt_simple.c new file mode 100644 index 00000000..fc35025e --- /dev/null +++ b/bee/drivers/ppt/driver/simple/ppt_simple.c @@ -0,0 +1,504 @@ +/** +***************************************************************************************** +* Copyright(c) 2021, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file ppt_simple.c + * @brief Source file for simple wrapper of 2.4G module common driver. + * @details + * @author bill + * @date 2021-11-26 + * @version v0.1 + * ************************************************************************************* + */ + +#include +//#include "trace.h" +#include "ppt_simple.h" +#include "os_mem.h" + +LOG_MODULE_REGISTER(ppt_simple, PPT_DRIVER_LOG_LEVEL); + +extern uint8_t (*modem_psd_get_entry_num)(void); +extern int8_t (*get_phy_rssi0_dbm)(uint8_t); +extern uint8_t(*modem_psd_get_rf_mode)(void); +uint8_t modem_psd_get_scan_mode(void); + +ppt_ctx_t ppt_ctx_imp; +ppt_ctx_t *ppt_ctx = &ppt_ctx_imp; + +void ppt_set_ptx_mode_ext(ppt_ptx_mode_ext_t *param) +{ + ppt_ptx_mode_t *base = ¶m->base; + ppt_ctx->ack = base->ack_mode; + ppt_ctx->oneshot = !base->periodic_mode; + ppt_ctx->retransmit_times = ppt_ctx->oneshot ? 0 : param->retransmit_times; + ppt_set_ptx_mode(base); +} + +void ppt_set_prx_mode_ext(ppt_prx_mode_ext_t *param) +{ + ppt_prx_mode_t *base = ¶m->base; + ppt_ctx->ack = base->ack_mode; + ppt_ctx->oneshot = !base->continuous_mode; + ppt_set_prx_mode(base); +} + +bool ppt_set_psd_mode_ext(ppt_psd_mode_ext_t *param) +{ + ppt_psd_mode_t *base = ¶m->base; + if (base->chann_stop >= PSD_CHANN_NUM || base->chann_step >= PSD_CHANN_NUM) + { + return false; + } + if (base->chann_start > base->chann_stop) + { + return false; + } + else if (base->chann_start < base->chann_stop) + { + if (base->chann_step == 0) + { + return false; + } + uint8_t chann_num = base->chann_stop - base->chann_start + 1; + chann_num = (chann_num + base->chann_step - 1) / base->chann_step; + if (chann_num > modem_psd_get_entry_num()) + { + return false; + } + } + ppt_ctx->psd_mode = *base; + ppt_set_psd_mode(base); + return true; +} + +PPT_API_SECTION uint8_t *ppt_get_tx_buffer(uint16_t payload_len) +{ + if (payload_len > PPT_TX_BUFFER_SIZE) + { + APP_PRINT_ERROR1("ppt_get_tx_buffer: fail, payload size %d exceed limit", payload_len); + return NULL; + } + + return ppt_ctx->tx_buffer[0]; +} + +uint8_t *ppt_get_tx_buffer_by_entry(uint8_t entry, uint16_t payload_len) +{ + if (payload_len > PPT_TX_BUFFER_SIZE) + { + APP_PRINT_ERROR1("ppt_get_tx_buffer_entry: fail, payload size %d exceed limit", payload_len); + return NULL; + } + + if (entry >= PPT_TX_BUFFER_NUM) + { + APP_PRINT_ERROR1("ppt_get_tx_buffer_entry: fail, entry %d exceed limit", entry); + return NULL; + } + + return ppt_ctx->tx_buffer[entry]; +} + +PPT_API_SECTION uint8_t *ppt_get_rx_buffer(uint16_t pdu_len) +{ + if (pdu_len > PPT_RX_BUFFER_SIZE) + { + APP_PRINT_ERROR1("ppt_get_rx_buffer: fail, pdu size %d exceed limit", pdu_len); + return NULL; + } + + return ppt_ctx->rx_buffer; +} + +PPT_API_SECTION void ppt_push_tx_data(uint16_t len, uint8_t *data) +{ + uint8_t *tx_buffer = ppt_get_tx_buffer(len); + memcpy(tx_buffer, data, len); + ppt_push_tx_fifo(0, tx_buffer, len); +} + +void ppt_update_tx_data(uint16_t len, uint8_t *data) +{ + uint8_t *tx_buffer = ppt_get_tx_buffer(len); + memcpy(tx_buffer, data, len); + ppt_update_tx_fifo(0, tx_buffer, len); +} + +PPT_API_SECTION void ppt_push_tx_data_by_entry(uint8_t entry, uint16_t len, uint8_t *data) +{ + uint8_t *tx_buffer = ppt_get_tx_buffer_by_entry(entry, len); + memcpy(tx_buffer, data, len); + ppt_push_tx_fifo(entry, tx_buffer, len); +} + +PPT_API_SECTION uint8_t *ppt_pop_rx_data(uint16_t len) +{ + uint8_t *rx_buffer = ppt_get_rx_buffer(len); + ppt_pop_rx_fifo(0, rx_buffer, len); + return rx_buffer; +} + +PPT_API_SECTION uint8_t *ppt_pop_rx_data_by_entry(uint8_t entry, uint16_t len) +{ + uint8_t *rx_buffer = ppt_get_rx_buffer(len); + ppt_pop_rx_fifo(entry, rx_buffer, len); + return rx_buffer; +} + +void ppt_async_cb_template(void) +{ + /* make the async way easy to use */ +} + +void ppt_enable_ptx(void (*async_cb)(void)) +{ + if (ppt_ctx->fsm != PPT_FSM_STANDBY) + { + return; + } + + ppt_ctx->fsm = PPT_FSM_PTX; + ppt_ctx->retransmit_counter = ppt_ctx->retransmit_times; + ppt_ctx->async_cb = async_cb; + ppt_ctx->sync_flag = true; + ppt_execute_instruction(PPT_HW_INSTRUCTION_PTX_ENABLE); + if (ppt_ctx->async_cb == NULL) + { + while (ppt_ctx->sync_flag); + ppt_ctx->fsm = PPT_FSM_STANDBY; + } +} + +void ppt_disable_ptx(void (*async_cb)(void)) +{ + if (ppt_ctx->fsm != PPT_FSM_PTX) + { + return; + } + + ppt_ctx->async_cb = async_cb; + ppt_ctx->sync_flag = true; + ppt_execute_instruction(PPT_HW_INSTRUCTION_PTX_DISABLE); + if (ppt_ctx->async_cb == NULL) + { + while (ppt_ctx->sync_flag); + ppt_ctx->fsm = PPT_FSM_STANDBY; + } +} + +void ppt_enable_prx(void (*async_cb)(void)) +{ + if (ppt_ctx->fsm != PPT_FSM_STANDBY) + { + return; + } + + ppt_ctx->fsm = PPT_FSM_PRX; + ppt_ctx->async_cb = async_cb; + ppt_ctx->sync_flag = true; + ppt_execute_instruction(PPT_HW_INSTRUCTION_PRX_ENABLE); + if (ppt_ctx->async_cb == NULL) + { + while (ppt_ctx->sync_flag); + ppt_ctx->fsm = PPT_FSM_STANDBY; + } +} + +void ppt_disable_prx(void (*async_cb)(void)) +{ + if (ppt_ctx->fsm != PPT_FSM_PRX) + { + return; + } + + ppt_ctx->async_cb = async_cb; + ppt_ctx->sync_flag = true; + ppt_execute_instruction(PPT_HW_INSTRUCTION_PRX_DISABLE); + if (ppt_ctx->async_cb == NULL) + { + while (ppt_ctx->sync_flag); + ppt_ctx->fsm = PPT_FSM_STANDBY; + } +} + +PPT_API_SECTION void ppt_reset_hw_fsm(void) +{ + WR_PPT_REG_FIELD(PRO_RESET_CTRL_REG, fw_rst_trigger, 1); + ppt_clear_radio(); + PRO_MISR_TYPE reg_misr; + do + { + reg_misr.d16 = RD_PPT_REG(PRO_MISR); + } + while (reg_misr.reset_trig_int == 0); + WR_PPT_REG(PRO_MISR, BIT6); + /* workaround for dma error if reset when dma start */ + ppt_clear_dma_tx_done(); + /* trx interrupts may be already pended before reset */ + ppt_flush_trx_int(); + /* the hw rx fifo shall be cleared here after reset */ + ppt_flush_rx_fifo(); +} + +PPT_API_SECTION bool ppt_kill_hw_fsm(ppt_fsm_t fsm) +{ + if (fsm == PPT_FSM_PTX) + { + ppt_execute_instruction(PPT_HW_INSTRUCTION_PTX_DISABLE); + ppt_clear_radio(); + PRO_MISR_TYPE reg_misr; + do + { + reg_misr.d16 = RD_PPT_REG(PRO_MISR); + } + while (reg_misr.kill_ptx_int == 0); + WR_PPT_REG(PRO_MISR, BIT4); + } + else if (fsm == PPT_FSM_PRX) + { + ppt_execute_instruction(PPT_HW_INSTRUCTION_PRX_DISABLE); + ppt_clear_radio(); + PRO_MISR_TYPE reg_misr; + do + { + reg_misr.d16 = RD_PPT_REG(PRO_MISR); + } + while (reg_misr.kill_prx_int == 0); + WR_PPT_REG(PRO_MISR, BIT5); + } + else + { + return false; + } + + /* clear all trx interrupts */ + ppt_flush_trx_int(); + /* the hw rx fifo shall be cleared here after kill */ + ppt_flush_rx_fifo(); + return true; +} + +PPT_API_SECTION void ppt_psd_isr_handler_imp(void) +{ + for (uint8_t loop = 0; loop < modem_psd_get_entry_num(); loop++) + { + //DBG_DIRECT("psd: 0x%08x 0x%08x 0x%08x 0x%08x", g_modem_psd_report_array[loop].d32_array[0], + //g_modem_psd_report_array[loop].d32_array[1], g_modem_psd_report_array[loop].d32_array[2], + //g_modem_psd_report_array[loop].d32_array[3]); + if (g_modem_psd_report_array[loop].signature_bit == 0) + { + int16_t mp_gain, psd_db, base_tmp; + base_tmp = (get_phy_rssi0_dbm(modem_psd_get_rf_mode()) << 4); + uint8_t chann = ppt_ctx->psd_mode.chann_start + ppt_ctx->psd_mode.chann_step * loop; + mp_gain = g_modem_psd_report_array[loop].mp_gain_idx; + if (modem_psd_get_scan_mode() == 2) + { + psd_db = g_modem_psd_report_array[loop].psd_avg_neg; + psd_db = (psd_db >= 1024) ? ((psd_db - 2048)) : psd_db; + ppt_ctx->psd_result[chann] = (psd_db + base_tmp + (mp_gain << (1 + 4))) << 3; + if (chann <= PSD_CHANN_NUM - 2) + { + psd_db = g_modem_psd_report_array[loop].psd_avg_dc; + psd_db = (psd_db >= 1024) ? ((psd_db - 2048)) : psd_db; + ppt_ctx->psd_result[chann + 1] = (psd_db + base_tmp + (mp_gain << (1 + 4))) << 3; + } + if (chann <= PSD_CHANN_NUM - 3) + { + psd_db = g_modem_psd_report_array[loop].psd_avg_pos; + psd_db = (psd_db >= 1024) ? ((psd_db - 2048)) : psd_db; + ppt_ctx->psd_result[chann + 2] = (psd_db + base_tmp + (mp_gain << (1 + 4))) << 3; + } + //APP_PRINT_INFO4("ppt: psd chan %d, rssi %d %d %d", chann, ppt_ctx->psd_result[chann], ppt_ctx->psd_result[chann + 1], ppt_ctx->psd_result[chann + 2]); + } + else + { + psd_db = g_modem_psd_report_array[loop].psd_avg_dc; + psd_db = (psd_db >= 1024) ? ((psd_db - 2048)) : psd_db; + ppt_ctx->psd_result[chann] = (psd_db + base_tmp + (mp_gain << (1 + 4))) << 3; + //APP_PRINT_INFO2("ppt: psd chan %d, rssi %d %d %d",chann, ppt_ctx->psd_result[chann]); + } + } + else + { + break; + } + } + + RTK_WRITE_MODEM_REG_PI(MODEM_PI_PAGE_0, TRANS_MODEM_REG(0x14), ppt_ctx->psd_tmp_flag); + + ppt_ctx->fsm = PPT_FSM_STANDBY; + APP_PRINT_INFO0("[ppt psd isr] set sync flag false here"); + ppt_ctx->sync_flag = false; + ppt_dlps_mac_idle = true; + if (ppt_ctx->async_cb) + { + ppt_ctx->async_cb(); + } +} +uint8_t test_array[4] = {0}; +uint32_t *test_ptr = test_array; +#include "trace.h" +void ppt_enable_psd(void (*async_cb)(void)) +{ + if (ppt_ctx->fsm != PPT_FSM_STANDBY) + { + return; + } + + /* save modem param */ + ppt_ctx->psd_tmp_flag = RTK_READ_MODEM_REG_PI(MODEM_PI_PAGE_0, TRANS_MODEM_REG(0x14)); + + for (uint8_t loop = 0; loop < modem_psd_get_entry_num(); loop++) + { + g_modem_psd_report_array[loop].signature_bit = 3; + }; + ppt_reg_psd_handler(ppt_psd_isr_handler_imp); + ppt_ctx->fsm = PPT_FSM_PSD; + ppt_ctx->sync_flag = true; + ppt_ctx->async_cb = async_cb; + ppt_dlps_mac_idle = false; + ppt_execute_instruction(PPT_HW_INSTRUCTION_PSD_ENABLE); + if (ppt_ctx->async_cb == NULL) + { + while (ppt_ctx->sync_flag); + } +} + +void ppt_disable_psd(void (*async_cb)(void)) +{ + if (ppt_ctx->fsm != PPT_FSM_PSD) + { + return; + } + + ppt_ctx->async_cb = async_cb; + ppt_ctx->sync_flag = true; + ppt_execute_instruction(PPT_HW_INSTRUCTION_PSD_DISABLE); + if (ppt_ctx->async_cb == NULL) + { + while (ppt_ctx->sync_flag); + ppt_ctx->fsm = PPT_FSM_STANDBY; + } +} + +void ppt_clear_psd_result(void) +{ + memset(ppt_ctx->psd_result, 0, sizeof(ppt_ctx->psd_result)); +} + +int16_t ppt_get_psd_result(uint8_t chann) +{ + if (chann >= PSD_CHANN_NUM) + { + return 0x7fff; + } + + return ppt_ctx->psd_result[chann] / 128; +} + + void ppt_init_sw(void) +{ + for (uint8_t loop = 0; loop < PPT_TX_BUFFER_NUM; loop++) + { + if (ppt_ctx->tx_buffer[loop] == NULL) + { + ppt_ctx->tx_buffer[loop] = os_mem_alloc(RAM_TYPE_BUFFER_ON, PPT_TX_BUFFER_SIZE); + } + } + + if (ppt_ctx->rx_buffer == NULL) + { + ppt_ctx->rx_buffer = os_mem_alloc(RAM_TYPE_BUFFER_ON, PPT_RX_BUFFER_SIZE); + } +} + +static void ppt_deinit_sw(void) +{ + for (uint8_t loop = 0; loop < PPT_TX_BUFFER_NUM; loop++) + { + if (ppt_ctx->tx_buffer[loop]) + { + os_mem_free(ppt_ctx->tx_buffer[loop]); + } + } + + if (ppt_ctx->rx_buffer) + { + os_mem_free(ppt_ctx->rx_buffer); + } + memset(ppt_ctx, 0, sizeof(ppt_ctx_t)); +} + +static void ppt_init_hw(void) +{ + uint16_t pro_reg; + WR_PPT_REG(PRO_IMR, 0xFFFF); + + pro_reg = RD_PPT_REG(PRO_PACKET_CONTROL); + ((PRO_PACKET_CONTROL_TYPE *)(&pro_reg))->crc_kept = 0; + WR_PPT_REG(PRO_PACKET_CONTROL, pro_reg); + + pro_reg = RD_PPT_REG(PRO_RX_CONTROL); + ((PRO_RX_CONTROL_TYPE *)(&pro_reg))->max_length_kept = 0; + WR_PPT_REG(PRO_RX_CONTROL, pro_reg); + + pro_reg = RD_PPT_REG(PRO_MAX_LENGTH); + ((PRO_MAX_LENGTH_TYPE *)(&pro_reg))->max_length = PPT_TX_BUFFER_SIZE; + WR_PPT_REG(PRO_MAX_LENGTH, pro_reg); + + for (uint8_t entry = 0; entry < PPT_ENTRY_NUM; entry++) + { + ppt_set_auto_no_tx(entry, false); + ppt_set_auto_ack(entry, false); + } + + ppt_reset_trx_pkt_num(); + + pro_reg = RD_PPT_REG(PRO_TX_TURN_AROUND_DELAY); + ((PRO_TX_TURN_AROUND_DELAY_TYPE *)(&pro_reg))->pro_txon_early_1m = 0x8; + WR_PPT_REG(PRO_TX_TURN_AROUND_DELAY, pro_reg); + + PRO_TRX_ON_DELAY_TYPE trx_on_delay = {.d16 = RD_PPT_REG(PRO_TRX_ON_DELAY)}; + trx_on_delay.pro_txon_delay = 58; + trx_on_delay.pro_rxon_delay = 58; + WR_PPT_REG(PRO_TRX_ON_DELAY, trx_on_delay.d16); + + pro_reg = RD_PPT_REG(PRO_RX_TIMEOUT_DELAY); + ((PRO_RX_TIMEOUT_DELAY_TYPE *)(&pro_reg))->pro_txon_early_2m = 0x2; + WR_PPT_REG(PRO_RX_TIMEOUT_DELAY, pro_reg); + + PRO_2M_TRX_ON_DELAY_TYPE trx_on_delay_2m = {.d16 = RD_PPT_REG(PRO_2M_TRX_ON_DELAY)}; + trx_on_delay_2m.pro_txon_delay_2m = 58; + trx_on_delay_2m.pro_rxon_delay_2m = 58; + WR_PPT_REG(PRO_2M_TRX_ON_DELAY, trx_on_delay_2m.d16); + + WR_PPT_REG(PRO_IMR, 0); +} + +void ppt_init(void) +{ + ppt_init_sw(); + ppt_notify_btmac(true); + ppt_reset_core_domain(true); +#if 0 + bt_retention_domain_reset(); + phy_init(false); +#endif +#if TIME_DEBUG + ppt_init_time_debug(); +#endif + ppt_init_hw(); + ppt_init_dma(); + ppt_init_misc(); +} + +void ppt_deinit(void) +{ + ppt_reset_core_domain(false); + ppt_deinit_misc(); + ppt_deinit_dma(); + ppt_notify_btmac(false); + + ppt_deinit_sw(); +} diff --git a/bee/drivers/ppt/driver/simple/ppt_simple.h b/bee/drivers/ppt/driver/simple/ppt_simple.h new file mode 100644 index 00000000..358557b8 --- /dev/null +++ b/bee/drivers/ppt/driver/simple/ppt_simple.h @@ -0,0 +1,330 @@ +/** +***************************************************************************************** +* Copyright(c) 2021, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file ppt_simple.h + * @brief Head file for simple wrapper of 2.4G module common driver. + * @details data structs and external functions declaration. + * @author bill + * @date 2021-11-26 + * @version v0.1 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _PPT_SIMPLE_H_ +#define _PPT_SIMPLE_H_ + +/* Add Includes here */ +#include +#include +#include "ppt_driver.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** @addtogroup PPT_Simple + * @{ + */ + +/** @defgroup PPT_Simple_Exported_Macros Exported Macros + * @brief + * @{ + */ + +/* payload length */ +#ifndef PPT_TX_BUFFER_NUM +#define PPT_TX_BUFFER_NUM 2 +#endif +#define PPT_TX_BUFFER_SIZE 255 +/* header + payload length */ +#define PPT_RX_BUFFER_SIZE (PPT_TX_BUFFER_SIZE + 8) + +/** @} End of PPT_Simple_Exported_Macros */ + +/** @defgroup PPT_Simple_Exported_Types Exported Types + * @brief + * @{ + */ + +typedef struct +{ + ppt_ptx_mode_t base; + uint16_t retransmit_times; +} ppt_ptx_mode_ext_t; + +typedef struct +{ + ppt_prx_mode_t base; +} ppt_prx_mode_ext_t; + +typedef struct +{ + ppt_psd_mode_t base; +} ppt_psd_mode_ext_t; + +typedef struct +{ + volatile ppt_fsm_t fsm; + bool ack; + bool oneshot; + uint16_t retransmit_times; + volatile uint16_t retransmit_counter; + uint8_t *tx_buffer[PPT_TX_BUFFER_NUM]; + uint8_t *rx_buffer; + volatile bool sync_flag; + void (*async_cb)(void); + struct + { + ppt_psd_mode_t psd_mode; + int16_t psd_result[PSD_CHANN_NUM]; + uint16_t psd_tmp_flag; + }; +} ppt_ctx_t; + +extern ppt_ctx_t *ppt_ctx; +/** @} End of PPT_Simple_Exported_Types */ + +/** @defgroup PPT_Simple_Exported_Functions Exported Functions + * @brief + * @{ + */ + +/** + * @brief initialize the radio + * @return none + */ +void ppt_init(void); + +/** + * @brief deinitialize the radio + * @return none + */ +void ppt_deinit(void); + +/** + * @brief set the ptx modes + * @param[in] param: parameters + * @return none + */ +void ppt_set_ptx_mode_ext(ppt_ptx_mode_ext_t *param); + +/** + * @brief set the prx modes + * @param[in] param: parameters + * @return none + */ +void ppt_set_prx_mode_ext(ppt_prx_mode_ext_t *param); + +/** + * @brief set the psd modes + * @param[in] param: parameters + * @return parameters set result + */ +bool ppt_set_psd_mode_ext(ppt_psd_mode_ext_t *param); + +/** + * @brief get tx buffer used by DMA for sending data + * + * The RAM type used by DMA is limited to a specific RAM type. + * This driver manages the memory for easy to use at the application. + * @param[in] payload_len: length of payload + * @return buffer address + */ +uint8_t *ppt_get_tx_buffer(uint16_t payload_len); + +/** + * @brief get tx buffer used by DMA for sending data + * + * The RAM type used by DMA is limited to a specific RAM type. + * This driver manages the memory for easy to use at the application. + * @param[in] entry: channel index + * @param[in] payload_len: length of payload + * @return buffer address + */ +uint8_t *ppt_get_tx_buffer_by_entry(uint8_t entry, uint16_t payload_len); + +/** + * @brief get rx buffer used by DMA for receiving data + * + * The RAM type used by DMA is limited to a specific RAM type. + * This driver manages the memory for easy to use at the application. + * @param[in] pdu_len: length of PDU + * @return buffer address + */ +uint8_t *ppt_get_rx_buffer(uint16_t pdu_len); + +/** + * @brief copy and push the data to the hw fifo + * + * The data will be copied, so the RAM type of data can be any type. + * @param[in] len: length of data + * @param[in] data: data to send + * @return none + */ +void ppt_push_tx_data(uint16_t len, uint8_t *data); + +/** + * @brief copy and update the data to the hw fifo + * + * The last pushed data can be updated by this function. + * @param[in] len: length of data + * @param[in] data: data to send + * @return none + */ +void ppt_update_tx_data(uint16_t len, uint8_t *data); + +/** + * @brief copy and push the data to the hw fifo of the specific channel + * + * The data will be copied, so the RAM type of data can be any type. + * @param[in] entry: channel index + * @param[in] len: length of data + * @param[in] data: data to send + * @return none + */ +void ppt_push_tx_data_by_entry(uint8_t entry, uint16_t len, uint8_t *data); + +/** + * @brief pop and copy the data from the hw fifo + * + * The data will be copied to the buffer RAM, its pointer will be returned. + * @param[in] len: length of data + * @return received data pointer + */ +uint8_t *ppt_pop_rx_data(uint16_t len); + +/** + * @brief pop and copy the data from the hw fifo of the specific channel + * + * The data will be copied to the buffer RAM, its pointer will be returned. + * @param[in] entry: channel index + * @param[in] len: length of data + * @return received data pointer + */ +uint8_t *ppt_pop_rx_data_by_entry(uint8_t entry, uint16_t len); + +/** + * @brief async callback template + * @return none + */ +void ppt_async_cb_template(void); + +/** + * @brief enable ptx state + * + * If the callback is null, then the api returns after the procedure is done in a sync way. + * Otherwise, the caller will be notified via the callback when the procedure is done in an async way. + * @param[in] async_cb: the callback function pointer + * @return none + */ +void ppt_enable_ptx(void (*async_cb)(void)); + +/** + * @brief disable ptx state + * + * If the callback is null, then the api returns after the procedure is done in a sync way. + * Otherwise, the caller will be notified via the callback when the procedure is done in an async way. + * @param[in] async_cb: the callback function pointer + * @return none + */ +void ppt_disable_ptx(void (*async_cb)(void)); + +/** + * @brief enable prx state + * + * If the callback is null, then the api returns after the procedure is done in a sync way. + * Otherwise, the caller will be notified via the callback when the procedure is done in an async way. + * @param[in] async_cb: the callback function pointer + * @return none + */ +void ppt_enable_prx(void (*async_cb)(void)); + +/** + * @brief disable prx state + * + * If the callback is null, then the api returns after the procedure is done in a sync way. + * Otherwise, the caller will be notified via the callback when the procedure is done in an async way. + * @param[in] async_cb: the callback function pointer + * @return none + */ +void ppt_disable_prx(void (*async_cb)(void)); + +/** + * @brief reset the finite state machine of the hardware module + * + * The reset feature shall be enabled previously by fw_rst_enable flag in @ref PRO_RESET_CTRL_REG. + * This API will generate mac interrupt, so it shall be called in critical section if at lower priority. + * All the internal states will be reset except for the interface registers in ppt_hw_reg.h. + * @return none + */ +void ppt_reset_hw_fsm(void); + +/** + * @brief kill the finite state machine of the hardware module + * + * This API will generate mac interrupt, so it shall be called in critical section if at lower priority. + * @return the result + */ +bool ppt_kill_hw_fsm(ppt_fsm_t fsm); + +/** + * @brief enable psd procedure + * + * If the callback is null, then the api returns after the procedure is done in a sync way. + * Otherwise, the caller will be notified via the callback when the procedure is done in an async way. + * @param[in] async_cb: the callback function pointer + * @return none + * + * Example usage + * \code{.c} + ppt_psd_mode_ext_t param = + { + { + .chann_start = 0, + .chann_stop = 0, + .chann_step = 1, + .mode = 0, + .timeout = PSD_TIMEOUT_DEFAULT + } + }; + ppt_set_psd_mode_ext(¶m); + ppt_enable_psd(NULL); + int16_t rssi = ppt_get_psd_result(0); + * \endcode + */ +void ppt_enable_psd(void (*async_cb)(void)); + +/** + * @brief disable psd procedure + * + * If the callback is null, then the api returns after the procedure is done in a sync way. + * Otherwise, the caller will be notified via the callback when the procedure is done in an async way. + * @param[in] async_cb: the callback function pointer + * @return none + */ +void ppt_disable_psd(void (*async_cb)(void)); + +/** + * @brief get the stored psd result + * @param[in] chann: the channel index, shall be less than @ref PSD_CHANN_NUM + * @return dbm value + */ +int16_t ppt_get_psd_result(uint8_t chann); + +/** + * @brief clear the stored psd result + * @return none + */ +void ppt_clear_psd_result(void); + +/** @} End of PPT_Simple_Exported_Functions */ + +/** @} End of PPT_Simple */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/bee/drivers/ppt/sync/CMakeLists.txt b/bee/drivers/ppt/sync/CMakeLists.txt index 9dd82302..941cef16 100644 --- a/bee/drivers/ppt/sync/CMakeLists.txt +++ b/bee/drivers/ppt/sync/CMakeLists.txt @@ -1,4 +1,23 @@ # Copyright (c) 2024 Realtek Semiconductor Corp. # SPDX-License-Identifier: Apache-2.0 -add_subdirectory(lib) + +# add_subdirectory(lib) +# Compile from source so CONFIG_PPT_DRIVER_LOG_LEVEL takes effect at build time. +set(PPT_SYNC_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src) +set(PPT_DRV_SRC ${CMAKE_CURRENT_SOURCE_DIR}/../driver) + +zephyr_library_named(ppt_sync) + +zephyr_library_sources(${PPT_DRV_SRC}/common/ppt_driver.c) +zephyr_library_sources(${PPT_DRV_SRC}/simple/ppt_simple.c) +zephyr_library_sources(${PPT_SYNC_SRC}/platform_list.c) +zephyr_library_sources(${PPT_SYNC_SRC}/ppt_sync.c) +zephyr_library_sources(${PPT_SYNC_SRC}/ppt_sync_pendcall.c) +zephyr_library_sources(${PPT_SYNC_SRC}/ppt_sync_master.c) +zephyr_library_sources(${PPT_SYNC_SRC}/ppt_sync_slave.c) + zephyr_include_directories(inc) +zephyr_include_directories(${PPT_SYNC_SRC}) +zephyr_include_directories(${PPT_DRV_SRC}/common) +zephyr_include_directories(${PPT_DRV_SRC}/common/rtl87x2g) +zephyr_include_directories(${PPT_DRV_SRC}/simple) diff --git a/bee/drivers/ppt/sync/lib/rtl87x2g/CMakeLists.txt b/bee/drivers/ppt/sync/lib/rtl87x2g/CMakeLists.txt index 3780c673..a9a2abea 100644 --- a/bee/drivers/ppt/sync/lib/rtl87x2g/CMakeLists.txt +++ b/bee/drivers/ppt/sync/lib/rtl87x2g/CMakeLists.txt @@ -1,4 +1,10 @@ # Copyright (c) 2024 Realtek Semiconductor Corp. # SPDX-License-Identifier: Apache-2.0 -zephyr_link_libraries(${CMAKE_CURRENT_SOURCE_DIR}/libppt_sync_master.a) +if(CONFIG_REALTEK_USING_PPT_SYNC_MASTER) + zephyr_link_libraries(${CMAKE_CURRENT_SOURCE_DIR}/libppt_sync_master.a) +endif() + +if(CONFIG_REALTEK_USING_PPT_SYNC_SLAVE) + zephyr_link_libraries(${CMAKE_CURRENT_SOURCE_DIR}/libppt_sync_slave.a) +endif() diff --git a/bee/drivers/ppt/sync/lib/rtl87x2g/libppt_sync_slave.a b/bee/drivers/ppt/sync/lib/rtl87x2g/libppt_sync_slave.a new file mode 100644 index 00000000..fb8b45aa Binary files /dev/null and b/bee/drivers/ppt/sync/lib/rtl87x2g/libppt_sync_slave.a differ diff --git a/bee/drivers/ppt/sync/src/platform_list.c b/bee/drivers/ppt/sync/src/platform_list.c new file mode 100644 index 00000000..e14709ef --- /dev/null +++ b/bee/drivers/ppt/sync/src/platform_list.c @@ -0,0 +1,105 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file platform_list.c + * @brief Source file for link list structures. + * @details Data types and external functions declaration. + * @author bill + * @date 2017-3-3 + * @version v1.0 + * ************************************************************************************* + */ + +/* Add Includes here */ +#include "platform_types.h" +#include "platform_list.h" +//#include "app_section.h" +#define RAM_FUNCTION + +RAM_FUNCTION void plt_list_push(plt_list_t *plist, void *plist_e) +{ + plt_list_e_t *pelement = (plt_list_e_t *)plist_e; + pelement->pnext = NULL; + if (plist->count == 0) + { + plist->pfirst = pelement; + } + else + { + plist->plast->pnext = pelement; + } + plist->plast = pelement; + plist->count++; +} + +RAM_FUNCTION void *plt_list_pop(plt_list_t *plist) +{ + plt_list_e_t *pelement = NULL; + if (plist->count > 0) + { + if (plist->count == 1) + { + plist->plast = NULL; + } + plist->count--; + pelement = plist->pfirst; + plist->pfirst = pelement->pnext; + } + return pelement; +} + +void plt_list_insert(plt_list_t *plist, void *plist_e, void *plist_e_new) +{ + plt_list_e_t *pelement = (plt_list_e_t *)plist_e; + plt_list_e_t *pelement_new = (plt_list_e_t *)plist_e_new; + + if (pelement == NULL) + { + pelement_new->pnext = plist->pfirst; + plist->pfirst = pelement_new; + if (plist->count == 0) + { + plist->plast = pelement_new; + } + } + else + { + pelement_new->pnext = pelement->pnext; + pelement->pnext = pelement_new; + if (pelement_new->pnext == NULL) + { + plist->plast = pelement_new; + } + } + plist->count++; +} + +void plt_list_delete(plt_list_t *plist, void *plist_e_previous, void *plist_e) +{ + plt_list_e_t *pelement = (plt_list_e_t *)plist_e; + if (plist_e_previous == NULL)//(plist->pfirst == pelement) + { + plist->pfirst = pelement->pnext; + if (pelement->pnext == NULL) + { + plist->plast = NULL; + } + } + else + { + /* + plt_list_e_t * pprevious = plist->pfirst; + while(pprevious->pnext != pelement) + pprevious = pprevious->pnext; + */ + plt_list_e_t *pprevious = (plt_list_e_t *)plist_e_previous; + pprevious->pnext = pelement->pnext; + if (pelement->pnext == NULL) + { + plist->plast = pprevious; + } + } + plist->count--; +} + diff --git a/bee/drivers/ppt/sync/src/platform_list.h b/bee/drivers/ppt/sync/src/platform_list.h new file mode 100644 index 00000000..0a9d2e6a --- /dev/null +++ b/bee/drivers/ppt/sync/src/platform_list.h @@ -0,0 +1,90 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file platform_list.h + * @brief Head file for list structure related. + * @details Data types and external functions declaration. + * @author bill + * @date 2017-9-28 + * @version v1.0 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _PLATFORM_LIST_ +#define _PLATFORM_LIST_ + +#include "platform_types.h" + +BEGIN_DECLS + +/** @addtogroup Platform_List + * @{ + */ + +/** @defgroup Platform_List_Exported_Types Exported Types + * @{ + */ + +/** @brief general element type of link list */ +typedef struct _plt_list_e_t +{ + struct _plt_list_e_t *pnext; + uint8_t data[4]; +} plt_list_e_t; + +/** @brief general list type of link list */ +typedef struct +{ + plt_list_e_t *pfirst; + plt_list_e_t *plast; + uint32_t count; +} plt_list_t; + +/** @} */ + +/** @defgroup Platform_List_Exported_Functions Exported Functions + * @brief + * @{ + */ + +/** + * @brief push in the element to the end of the list + * @param[in] plist: the list pointer + * @param[in] plist_e: the element pointer + * @return none + */ +void plt_list_push(plt_list_t *plist, void *plist_e); + +/** + * @brief pop out the first element of the list + * @param[in] plist: the list pointer + * @return the list element + */ +void *plt_list_pop(plt_list_t *plist); + +/** + * @brief insert the element to any position of the list + * @param[in] plist: the list pointer + * @param[in] plist_e: the ahead element pointer + * @param[in] plist_e_new: the new element pointer + * @return none + */ +void plt_list_insert(plt_list_t *plist, void *plist_e, void *plist_e_new); + +/** + * @brief delete the element at any position of the list + * @param[in] plist: the list pointer + * @param[in] plist_e_previous: the ahead element pointer + * @param[in] plist_e: the deleted element pointer + * @return none + */ +void plt_list_delete(plt_list_t *plist, void *plist_e_previous, void *plist_e); + +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _PLATFORM_LIST_ */ diff --git a/bee/drivers/ppt/sync/src/platform_macros.h b/bee/drivers/ppt/sync/src/platform_macros.h new file mode 100644 index 00000000..10315259 --- /dev/null +++ b/bee/drivers/ppt/sync/src/platform_macros.h @@ -0,0 +1,165 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file platform_macros.h + * @brief Head file for platform macros. + * @details Compile, mathematic etc related + * @author bill + * @date 2017-3-3 + * @version v1.0 + * ************************************************************************************* + */ + +#ifndef _PLATFORM_MACROS_H_ +#define _PLATFORM_MACROS_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** @addtogroup Platform_Macros + * @{ + */ + +/** @defgroup Platform_Macros_Exported_Macros Exported Macros + * @{ + */ + +#ifndef _PACKED_ +#define _PACKED_ __attribute__ ((packed)) +#endif + +#ifndef _SHORT_ENUM_ +#define _SHORT_ENUM_ __attribute__ ((packed)) +#endif + +#ifndef __INLINE +#define __INLINE __inline +#endif + +#undef MAX +#define MAX(a, b) ((a) > (b) ? (a) : (b)) + +#undef MIN +#define MIN(a, b) ((a) > (b) ? (b) : (a)) + +#undef ABS +#define ABS(a) ((a < 0) ? -(a) : (a)) + +#undef CLAMP +#define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x))) + +#undef MEMBER_OFFSET +#define MEMBER_OFFSET(struct_type, member) ((uint32_t)&((struct_type *)0)->member) + +#undef CONTAINER_OF +#define CONTAINER_OF(member_ptr, struct_type, member) \ + ({ \ + (struct_type *)((char *)member_ptr - MEMBER_OFFSET(struct_type, member)); \ + }) + +#undef ARRAY_LEN +#define ARRAY_LEN(arr) (sizeof(arr) / sizeof((arr)[0])) + +#define BIT0 0x00000001 +#define BIT1 0x00000002 +#define BIT2 0x00000004 +#define BIT3 0x00000008 +#define BIT4 0x00000010 +#define BIT5 0x00000020 +#define BIT6 0x00000040 +#define BIT7 0x00000080 +#define BIT8 0x00000100 +#define BIT9 0x00000200 +#define BIT10 0x00000400 +#define BIT11 0x00000800 +#define BIT12 0x00001000 +#define BIT13 0x00002000 +#define BIT14 0x00004000 +#define BIT15 0x00008000 +#define BIT16 0x00010000 +#define BIT17 0x00020000 +#define BIT18 0x00040000 +#define BIT19 0x00080000 +#define BIT20 0x00100000 +#define BIT21 0x00200000 +#define BIT22 0x00400000 +#define BIT23 0x00800000 +#define BIT24 0x01000000 +#define BIT25 0x02000000 +#define BIT26 0x04000000 +#define BIT27 0x08000000 +#define BIT28 0x10000000 +#define BIT29 0x20000000 +#define BIT30 0x40000000 +#define BIT31 0x80000000 + +#define BIT(_n) (uint32_t)(1U << (_n)) + +#define BYTE0(data) ((uint8_t)data) +#define BYTE1(data) ((uint8_t)(data >> 8)) +#define BYTE2(data) ((uint8_t)(data >> 16)) +#define BYTE3(data) ((uint8_t)(data >> 24)) +#define BYTE(data, n) ((uint8_t)(data >> 8*n)) +#define BYTES2(data) BYTE0(data), BYTE1(data) +#define BYTES4(data) BYTE0(data), BYTE1(data), BYTE2(data), BYTE3(data) + +/* Get local WORD from external 2 BYTE, Big-Endian format STANDARD NETWORK BYTE ORDER */ +#define BE_EXTRN2WORD(p) ((*((p)+1)) & 0xff) + ((*(p)) << 8) + +/* Get local DWORD from external 4 BYTE, Big-Endian format STANDARD NETWORK BYTE ORDER */ +#define BE_EXTRN2DWORD(p) ((unsigned long)(*((p)+3)) & 0xff) + ((unsigned long)(*((p)+2)) << 8) \ + + ((unsigned long)(*((p)+1)) << 16) + ((unsigned long)(*((p)+0)) << 24) + +/* PUT external 2 CHARS from local SHORT, Big-Endian format STANDARD NETWORK BYTE ORDER */ +#define BE_WORD2EXTRN(p,w) \ + {*((p)+1) = (unsigned char)((w) & 0xff); \ + *(p) = /*lint -e(572,778)*/ (unsigned char)(((w)>>8) & 0xff);} + +/* PUT external 4 BYTE from local DWORD, Big-Endian format STANDARD NETWORK BYTE ORDER */ +#define BE_DWORD2EXTRN(p,w) \ + {*((p)+3) = (unsigned char)((w) & 0xff); \ + *((p)+2) = /*lint -e(572,778)*/ (unsigned char)(((w)>>8) & 0xff); \ + *((p)+1) = /*lint -e(572,778)*/ (unsigned char)(((w)>>16) & 0xff); \ + *((p)+0) = /*lint -e(572,778)*/ (unsigned char)(((w)>>24) & 0xff);} + +/* Get local WORD from external 2 BYTE, Little-Endian format */ +#define LE_EXTRN2WORD(p) (((*(p)) & 0xff) + ((*((p)+1)) << 8)) + +/* Get local DWORD from external 4 BYTE, Little-Endian format */ +#define LE_EXTRN2DWORD(p) (((unsigned long)(*((p)+0)) & 0xff) + ((unsigned long)(*((p)+1)) << 8) \ + + ((unsigned long)(*((p)+2)) << 16) + ((unsigned long)(*((p)+3)) << 24)) + +/* PUT external 2 BYTE from local WORD, Little-Endian Format */ +#define LE_WORD2EXTRN(p,w) \ + {*((unsigned char*)p) = (unsigned char)((unsigned short)(w) & 0xff); \ + *(((unsigned char*)p)+1) = /*lint -e(572,778)*/ (unsigned char)(((unsigned short)(w)>>8) & 0xff);} + +/* PUT external 4 BYTE from local DWORD, Little endian Format */ +#define LE_DWORD2EXTRN(p,w) \ + {*((unsigned char*)p) = (unsigned char)((unsigned long)(w) & 0xff); \ + *(((unsigned char*)p)+1) = (unsigned char)(((unsigned long)(w)>>8) & 0xff); \ + *(((unsigned char*)p)+2) = (unsigned char)(((unsigned long)(w)>>16) & 0xff); \ + *(((unsigned char*)p)+3) = (unsigned char)(((unsigned long)(w)>>24) & 0xff);} + +#ifdef __cplusplus +#define BEGIN_DECLS extern "C" { +#define END_DECLS } +#else +#define BEGIN_DECLS +#define END_DECLS +#endif + +#ifndef UNUSED +#define UNUSED(x) ((void)(x)) +#endif + +/** @} */ +/** @} */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _PLATFORM_MACROS_H_ */ diff --git a/bee/drivers/ppt/sync/src/platform_types.h b/bee/drivers/ppt/sync/src/platform_types.h new file mode 100644 index 00000000..74f2a80d --- /dev/null +++ b/bee/drivers/ppt/sync/src/platform_types.h @@ -0,0 +1,55 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file platform_types.h + * @brief Head file for platform types. + * @details Basic types related. + * @author bill + * @date 2017-3-3 + * @version v1.0 + * ************************************************************************************* + */ + +#ifndef _PLATFORM_TYPES_H_ +#define _PLATFORM_TYPES_H_ + +#include +#include +#include +#include "platform_macros.h" + +BEGIN_DECLS + +/** @addtogroup Platform_Types + * @{ + */ + +/** @defgroup Platform_Types_Exported_Macros Exported Macros + * @brief + * @{ + */ + +/* boolean definition */ +#ifndef FALSE +#define FALSE (0) +#endif + +#ifndef TRUE +#define TRUE (!FALSE) +#endif + +#ifndef NULL +#ifdef __cplusplus +#define NULL (0L) +#else +#define NULL ((void *)0) +#endif +#endif + +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _PLATFORM_TYPES_H_ */ diff --git a/bee/drivers/ppt/sync/src/ppt_sync.c b/bee/drivers/ppt/sync/src/ppt_sync.c new file mode 100644 index 00000000..352ea974 --- /dev/null +++ b/bee/drivers/ppt/sync/src/ppt_sync.c @@ -0,0 +1,1643 @@ +/** +***************************************************************************************** +* Copyright(c) 2020, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file ppt_sync.c + * @brief Source file for sync protocol. + * @details + * @author bill + * @date 2022-03-15 + * @version v0.1 + * ************************************************************************************* + */ + +/* Add Includes here */ +#include +#include "ppt_simple.h" +#include "ppt_sync_int.h" +#include "ppt_sync_master.h" +#include "ppt_sync_slave.h" +//#include "trace.h" +#include "os_mem.h" +#include "os_sync.h" +#include "rtl876x.h" +#include "rtl_rcc.h" +#include "rtl_nvic.h" +#include "rtl_enh_tim.h" +#include +#include +#include "vector_table.h" + +LOG_MODULE_REGISTER(ppt_sync, PPT_SYNC_LOG_LEVEL); + +#define SYNC_VERSION "v1.17.1" +#define SYNC_FTL_OFFSET 0 +#define SYNC_HW_TIMER ENH_TIM1 +#define SYNC_HW_TIMER_IRQN Enhanced_Timer1_IRQn +#define SYNC_HW_TIMER_VECTORN Enhanced_Timer1_VECTORn //Enhanced_Timer1_Handler +#define SYNC_HW_TIMER1 ENH_TIM2 +#define SYNC_HW_TIMER1_IRQN Enhanced_Timer2_IRQn +#define SYNC_HW_TIMER1_VECTORN Enhanced_Timer2_VECTORn +#define SYNC_HW_TIMER_IP NVIC_GetPriority(BTMAC_IRQn) +#define SYNC_HW_TIMER_CLOCK 40 +#define SYNC_HW_TIMER_SHIFT_COMPENSATE 2 +#define SYNC_HW_TIMER_SHIFT_TOLERANCE 5 +#define SYNC_HW_FRTIMER ENH_TIM0 +#define SYNC_HW_FRTIMER_IRQN Enhanced_Timer0_IRQn +#define SYNC_HW_FRTIMER_VECTORN Enhanced_Timer0_VECTORn + +#define SYNC_TIME_DEBUG_TIMER1 -1 + +sync_ctx_t sync_ctx = +{ + .conn_interval = SYNC_SYNC_SPEED_DV, + .conn_interval_high = SYNC_SYNC_SPEED_HIGH_DV, + .acc_br.addr = SYNC_ACC_ADDR_BR_DV, + .tifs = {SYNC_TIFS0_DV, SYNC_TIFS1_DV}, +}; + +typedef struct +{ + sync_bond_info_t bond_info; +} sync_nvm_bond_info_t; + +typedef struct +{ + sync_nvm_bond_info_t nvm_bond_info; +} sync_nvm_t; + +#define FAIL_MSG "fail (err %d)\n" +#define SYNC_NVM_BOND_INFO_F "pptsync/bondinfo" + +struct direct_immediate_value { + size_t len; + void *dest; + uint8_t fetched; +}; + +static int sync_direct_loader_immediate_value(const char *name, size_t len, + settings_read_cb read_cb, void *cb_arg, + void *param) +{ + const char *next; + size_t name_len; + int rc; + struct direct_immediate_value *one_value = + (struct direct_immediate_value *)param; + + name_len = settings_name_next(name, &next); + + if (name_len == 0) { + if (len == one_value->len) { + rc = read_cb(cb_arg, one_value->dest, len); + if (rc >= 0) { + one_value->fetched = 1; + //printk("immediate load: OK.\n"); + return 0; + } + + printk(FAIL_MSG, rc); + return rc; + } + return -EINVAL; + } + + /* other keys aren't served by the callback + * Return success in order to skip them + * and keep storage processing. + */ + return 0; +} + +int sync_load_immediate_value(const char *name, void *dest, size_t len) +{ + int rc; + struct direct_immediate_value dov; + + dov.fetched = 0; + dov.len = len; + dov.dest = dest; + + rc = settings_load_subtree_direct(name, sync_direct_loader_immediate_value, + (void *)&dov); + if (rc == 0) { + if (!dov.fetched) { + rc = -ENOENT; + } + } + + return rc; +} + +sync_err_code_t sync_nvm_get_bond_info(sync_bond_info_t *bond_info) +{ + sync_nvm_bond_info_t nvm_bond_info; + if (0 != sync_load_immediate_value(SYNC_NVM_BOND_INFO_F, &nvm_bond_info, sizeof(sync_nvm_bond_info_t))) + { + return SYNC_ERR_CODE_NOT_FOUND; + } + + *bond_info = nvm_bond_info.bond_info; + return SYNC_ERR_CODE_SUCCESS; +} + +sync_err_code_t sync_nvm_set_bond_info(sync_bond_info_t *bond_info) +{ + sync_nvm_bond_info_t nvm_bond_info = {}; + nvm_bond_info.bond_info = *bond_info; + if (0 != settings_save_one(SYNC_NVM_BOND_INFO_F, &nvm_bond_info, sizeof(sync_nvm_bond_info_t))) + { + return SYNC_ERR_CODE_UNKNOWN; + } + return SYNC_ERR_CODE_SUCCESS; +} + +sync_err_code_t sync_nvm_clear_bond_info(void) +{ + if(0 != settings_delete(SYNC_NVM_BOND_INFO_F)) + { + return SYNC_ERR_CODE_UNKNOWN; + } + + return SYNC_ERR_CODE_SUCCESS; +} + +void sync_ppt_init(void) +{ + ppt_init(); + + { + ppt_phy_param_t param = + { + .bank = 0, + .channel = 0, + .rx_phy = PPT_PHY_TYPE_BLE_2M + }; + ppt_set_phy_param(¶m); + } + + { + ppt_phy_entry_param_t param = + { + .preamble_len = 1, + .tx_phy = PPT_PHY_TYPE_BLE_2M + }; + ppt_set_phy_entry_param(0, ¶m); + } + + { + ppt_white_entry_param_t param = + { + .len = 7, + .value = {0x91, 0x53} + }; + ppt_set_white_entry_param(0, ¶m); + } + + { + ppt_pkt_format_t param = + { + .addr_len = 4, + .hp_len = SYNC_HEADER_LEN, + .length_len = SYNC_LENGTH_LEN, + .hs_len = 0, + .header_order = PPT_FIELD_BIT_ORDER_LSB, + .payload_order = PPT_FIELD_BIT_ORDER_LSB + }; + ppt_set_pkt_format(¶m); + } + + { + ppt_crc_param_t param = + { + .len = SYNC_CRC_LEN >> 3, + .include_addr = false + }; + ppt_set_crc_param(¶m); + } + + { + ppt_crc_entry_param_t param = + { + .value = {SYNC_CRC_POLY, SYNC_CRC_INIT} + }; + ppt_set_crc_entry_param(0, ¶m); + } + + PRO_RESET_CTRL_REG_TYPE reset_ctrl = {.d16 = RD_PPT_REG(PRO_RESET_CTRL_REG)}; + reset_ctrl.fw_rst_enable = 1; + WR_PPT_REG(PRO_RESET_CTRL_REG, reset_ctrl.d16); + + /* enable length check */ + WR_PPT_REG_FIELD(PRO_RX_MATCH_CONTROL, use_maxlength_compare, 1); + WR_PPT_REG_FIELD(PRO_MAX_LENGTH, max_length, SYNC_MSG_MAX_LEN); + + /* set rf time parameters */ + sync_ppt_set_rf_time(); + +#if SYNC_SUPPORT_MT1R + { + ppt_timing_latch_t param = + { + .tx_on = true, + .acc_hit = true + }; + ppt_set_timing_latch(¶m); + } +#endif +} + +void sync_ppt_set_tifs(bool init) +{ + uint8_t sync_tifs = 0; + if (sync_ctx.tifs[0] != sync_ctx.tifs[1]) + { + sync_tifs = init ? sync_ctx.tifs[0] : (SYNC_SYNC_SPEED >= 500 ? sync_ctx.tifs[0] : + sync_ctx.tifs[1]); + } + else + { + sync_tifs = sync_ctx.tifs[0]; + } + + ppt_set_tifs(sync_tifs); +} + +void sync_ppt_set_rf_time(void) +{ + PRO_2M_TRX_ON_DELAY_TYPE trx_on_delay = {.d16 = RD_PPT_REG(PRO_2M_TRX_ON_DELAY)}; + trx_on_delay.pro_txon_delay_2m = 54; + trx_on_delay.pro_rxon_delay_2m = 40; + WR_PPT_REG(PRO_2M_TRX_ON_DELAY, trx_on_delay.d16); + PRO_RX_TIMEOUT_DELAY_TYPE rx_to = {.d16 = RD_PPT_REG(PRO_RX_TIMEOUT_DELAY)}; + rx_to.pro_txon_early_2m = 1; + rx_to.pro_rx_timeout_delay_us = 55; + WR_PPT_REG(PRO_RX_TIMEOUT_DELAY, rx_to.d16); +} + +#if SYNC_SUPPORT_MT1R +void sync_ppt_set_rf_time_mt1r(void) +{ + PRO_2M_TRX_ON_DELAY_TYPE trx_on_delay = {.d16 = RD_PPT_REG(PRO_2M_TRX_ON_DELAY)}; + trx_on_delay.pro_rxon_delay_2m = 40; + trx_on_delay.pro_txon_delay_2m = 40; + WR_PPT_REG(PRO_2M_TRX_ON_DELAY, trx_on_delay.d16); + + PRO_RX_TIMEOUT_DELAY_TYPE rx_to = {.d16 = RD_PPT_REG(PRO_RX_TIMEOUT_DELAY)}; + rx_to.pro_txon_early_2m = 0; + rx_to.pro_rx_timeout_delay_us = 90; + WR_PPT_REG(PRO_RX_TIMEOUT_DELAY, rx_to.d16); +} +#endif + +bool sync_channel_set(uint8_t chan_num, uint8_t group_num, uint16_t freq[]) +{ + if (chan_num % group_num != 0) + { + return false; + } + sync_ctx.chan_num = chan_num; + sync_ctx.chan_group_num = group_num; + if (sync_ctx.chan_cfg) + { + os_mem_free(sync_ctx.chan_cfg); + } + sync_ctx.chan_cfg = (sync_channel_cfg_t *)os_mem_alloc(RAM_TYPE_DATA_ON, + sizeof(sync_channel_cfg_t) * sync_ctx.chan_num); + if (sync_ctx.chan_cfg == NULL) + { + return false; + } + for (uint8_t loop = 0; loop < sync_ctx.chan_num; loop++) + { + sync_ctx.chan_cfg[loop].freq = freq[loop]; + ppt_get_bank_channel(freq[loop], &sync_ctx.chan_cfg[loop].bank, + &sync_ctx.chan_cfg[loop].channel); + } + sync_ctx.chan_cur = 0; + return true; +} + +void sync_channel_change(uint8_t idx) +{ + if (idx >= sync_ctx.chan_num) + { + APP_PRINT_ERROR2("sync_channel_change: fail set to %d, total %d", idx, sync_ctx.chan_num); + return; + } + uint8_t old_idx = sync_ctx.chan_cur; + sync_ctx.chan_cur = idx; + PRO_CHANNEL_BANK_TYPE ch_bank; + ch_bank.bank = sync_ctx.chan_cfg[idx].bank; + ch_bank.pro_channel = sync_ctx.chan_cfg[idx].channel; + WR_PPT_REG(PRO_CHANNEL_BANK, ch_bank.d16); + +#if SYNC_FRAME_BLE_COMPATIBLE + uint32_t white_init = ppt_get_ble_white_init(ppt_get_ble_logic_chan_via_freq( + sync_ctx.chan_cfg[idx].freq)); +#else + uint32_t white_init = ppt_get_ble_white_init(idx); +#endif + WR_PPT_REG(PRO_WHITE_INIT0_LOWER, white_init & 0xffff); + WR_PPT_REG(PRO_WHITE_INIT0_UPPER, (white_init >> 16) & 0xffff); + sync_ctx.chan_used_count = 0; + sync_ctx.chan_miss_count = 0; + +#ifdef SYNC_DEBUG + sync_ctx.chan_cfg[idx].choose_times += 1; + if (sync_ctx.chan_cfg[old_idx].fail_burst_count) + { + if (sync_ctx.chan_cfg[old_idx].fail_burst_count > sync_ctx.chan_cfg[old_idx].fail_burst_max) + { + sync_ctx.chan_cfg[old_idx].fail_burst_max = sync_ctx.chan_cfg[old_idx].fail_burst_count; + } + } + sync_ctx.chan_cfg[old_idx].fail_burst_count = 0; +#endif +} + +void sync_channel_change_next(void) +{ + sync_channel_change((sync_ctx.chan_cur + 1) % sync_ctx.chan_num); +} + +void sync_channel_change_next_in_group(void) +{ + uint8_t chan_min, chan_max, chan_num, chan_next; + chan_num = sync_ctx.chan_num / sync_ctx.chan_group_num; + chan_min = (sync_ctx.chan_cur / chan_num) * chan_num; + chan_max = chan_min + chan_num - 1; + chan_next = sync_ctx.chan_cur >= chan_max ? chan_min : sync_ctx.chan_cur + 1; + sync_channel_change(chan_next); +} + +#ifdef SYNC_DEBUG +void sync_channel_statistic(bool ok) +{ + uint8_t idx = sync_ctx.chan_cur; + if (sync_ctx.chan_cfg[idx].choose_times == 0) + { + sync_ctx.chan_cfg[idx].choose_times += 1; + } + sync_ctx.chan_cfg[idx].used_count += 1; + if (ok == false) + { + sync_ctx.chan_cfg[idx].fail_count += 1; + sync_ctx.chan_cfg[idx].fail_burst_count += 1; + } + else + { + if (sync_ctx.chan_cfg[idx].fail_burst_count) + { + if (sync_ctx.chan_cfg[idx].fail_burst_count > sync_ctx.chan_cfg[idx].fail_burst_max) + { + sync_ctx.chan_cfg[idx].fail_burst_max = sync_ctx.chan_cfg[idx].fail_burst_count; + } + } + sync_ctx.chan_cfg[idx].fail_burst_count = 0; + } +} + +void sync_channel_clear_statistic(void) +{ + for (uint8_t idx = 0; idx < sync_ctx.chan_num; idx++) + { + sync_ctx.chan_cfg[idx].choose_times = 0; + sync_ctx.chan_cfg[idx].used_count = 0; + sync_ctx.chan_cfg[idx].fail_count = 0; + sync_ctx.chan_cfg[idx].fail_burst_count = 0; + sync_ctx.chan_cfg[idx].fail_burst_max = 0; + } +} + +void sync_channel_print_statistic(void) +{ + for (uint8_t idx = 0; idx < sync_ctx.chan_num; idx++) + { + APP_PRINT_INFO5("sync: channel statistic %d, choose %d, used %d, miss %d, burst max %d", idx, + sync_ctx.chan_cfg[idx].choose_times, + sync_ctx.chan_cfg[idx].used_count, sync_ctx.chan_cfg[idx].fail_count, + sync_ctx.chan_cfg[idx].fail_burst_max); + } +} +#endif + +void sync_acc_set(sync_acc_t acc) +{ + { + ppt_tx_addr_t param; + LE_DWORD2EXTRN(param.tx_addr, acc.addr); + ppt_set_tx_addr(0, ¶m); + } + + { + ppt_rx_addr_t param = + { + .enable = true + }; + LE_DWORD2EXTRN(param.rx_addr, acc.addr); + ppt_set_rx_addr(0, ¶m); + } + +#if SYNC_FRAME_BLE_COMPATIBLE == 0 + uint8_t rx_addr[4]; + LE_DWORD2EXTRN(rx_addr, acc.addr); + ppt_crc_eng_param_t crc_param = + { + .poly = SYNC_CRC_POLY, + .init = SYNC_CRC_INIT, + .length = SYNC_CRC_LEN, + .bit_mode = 0, + .input_endian = 0, + .output_endian = 0 + }; + uint32_t init = ppt_crc_eng_cal(&crc_param, rx_addr, 4); + { + ppt_crc_entry_param_t param = + { + .value = {SYNC_CRC_POLY, SYNC_CRC_INIT} + }; + param.value.init = init; + ppt_set_crc_entry_param(0, ¶m); + } +#endif +} + +int sync_acc_check(sync_acc_t acc) +{ + uint32_t acc_addr = acc.addr; + uint8_t count = 0; + uint8_t transition = 0; + bool last_bit = false; + + uint8_t addr0 = acc_addr & 0xff; + if (addr0 == 0x55 || addr0 == 0xaa) + { + return __LINE__; + } + + uint8_t addr1 = (acc_addr >> 8) & 0xff; + if (addr1 == 0x55 || addr1 == 0xaa) + { + return __LINE__; + } + + uint8_t loop = 1; + for (; loop < 4; loop++) + { + uint8_t value = (acc_addr >> (8 * loop)) & 0xff; + if (value != (acc_addr & 0xff)) + { + break; + } + } + if (loop >= 4) + { + return __LINE__; + } + + for (loop = 0; loop < 32; loop++) + { + bool curr_bit = acc_addr & BIT(31 - loop); + if (loop != 0) + { + if (curr_bit != last_bit) + { + transition += 1; + count = 0; + } + else + { + count += 1; + if (count >= 6) + { + return __LINE__; + } + } + + if (loop == 5 && transition < 2) + { + return __LINE__; + } + } + last_bit = curr_bit; + } + + if (transition > 24) + { + return __LINE__; + } + + return 0; +} + +sync_acc_t sync_acc_gen_data(void) +{ + sync_acc_t acc; +#if SYNC_FRAME_BLE_COMPATIBLE + acc.addr = SYNC_ACC_ADDR_BR + 1 + return acc; +#else + while (1) + { + acc.addr = sync_rand(); + if (acc.addr != SYNC_ACC_ADDR_BR && 0 == sync_acc_check(acc)) + { + APP_PRINT_INFO1("sync: acc gen 0x%08x", acc.addr); + return acc; + } + } +#endif +} + +void sync_acc_set_br(sync_acc_t acc_br) +{ + sync_ctx.acc_br = acc_br; + APP_PRINT_INFO2("sync: acc set br 0x%08x (%d)", acc_br.addr, sync_acc_check(acc_br)); +} + +void sync_hw_timer_handler(void); +void sync_hw_timer_init(void) +{ + RCC_PeriphClockCmd(APBPeriph_ENHTIMER, APBPeriph_ENHTIMER_CLOCK, ENABLE); + + ENHTIM_InitTypeDef TIM_InitStruct; + ENHTIM_StructInit(&TIM_InitStruct); + TIM_InitStruct.ENHTIM_Mode = ENHTIM_MODE_PWM_MANUAL; + ENHTIM_Init(SYNC_HW_TIMER, &TIM_InitStruct); + + NVIC_InitTypeDef NVIC_InitStruct; + NVIC_InitStruct.NVIC_IRQChannel = SYNC_HW_TIMER_IRQN; + NVIC_InitStruct.NVIC_IRQChannelPriority = SYNC_HW_TIMER_IP; + NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&NVIC_InitStruct); + RamVectorTableUpdate(SYNC_HW_TIMER_VECTORN, sync_hw_timer_handler); + + ENHTIM_ClearINTPendingBit(SYNC_HW_TIMER, ENHTIM_INT_TIM); + ENHTIM_INTConfig(SYNC_HW_TIMER, ENHTIM_INT_TIM, ENABLE); +} + +static PPT_ISR_SECTION void sync_hw_timer_disable(void) +{ + uint32_t lock = sync_enter_critical(); + ENHTIM_Cmd(SYNC_HW_TIMER, DISABLE); + ENHTIM_ClearINTPendingBit(SYNC_HW_TIMER, ENHTIM_INT_TIM); + NVIC_ClearPendingIRQ(SYNC_HW_TIMER_IRQN); + sync_exit_critical(lock); + sync_ctx.hw_timer_periodic = false; + sync_hw_timer_impr_ip(false); +} + +PPT_ISR_SECTION void sync_hw_timer_start(uint32_t period_us, sync_hw_timer_cb_t cb) +{ + sync_hw_timer_disable(); + sync_ctx.hw_timer_cb = cb; +#if SYNC_SUPPORT_MT1R + sync_ctx.hw_timer_period = period_us; + sync_ctx.hw_timer_shift_state = SYNC_HW_TIMER_SHIFT_STATE_IDLE; +#endif + SYNC_HW_TIMER->ENHTIM_MAX_CNT = period_us * SYNC_HW_TIMER_CLOCK; + ENHTIM_Cmd(SYNC_HW_TIMER, ENABLE); + time_debug_level_low(TIME_DEBUG_CHAN_ISR_GPIO); + time_debug_level_high(TIME_DEBUG_CHAN_ISR_GPIO); +} + +PPT_ISR_SECTION void sync_hw_timer_restart(void) +{ + time_debug_level_low(TIME_DEBUG_CHAN_ISR_GPIO); + time_debug_level_high(TIME_DEBUG_CHAN_ISR_GPIO); + sync_hw_timer_disable(); + ENHTIM_Cmd(SYNC_HW_TIMER, ENABLE); +} + +PPT_ISR_SECTION void sync_hw_timer_stop(void) +{ + time_debug_level_low(TIME_DEBUG_CHAN_ISR_GPIO); + sync_hw_timer_disable(); + sync_ctx.hw_timer_cb = NULL; +#if SYNC_SUPPORT_MT1R + sync_ctx.hw_timer_shift_state = SYNC_HW_TIMER_SHIFT_STATE_IDLE; +#endif +} + +PPT_ISR_SECTION uint32_t sync_hw_timer_get_left(void) +{ + uint32_t curr = SYNC_HW_TIMER->ENHTIM_CUR_CNT / SYNC_HW_TIMER_CLOCK; + return curr; +} + +PPT_ISR_SECTION bool sync_hw_timer_check_pending(void) +{ + return NVIC_GetPendingIRQ(SYNC_HW_TIMER_IRQN); +} + +PPT_ISR_SECTION void sync_hw_timer_set_periodic(bool enable) +{ + sync_ctx.hw_timer_periodic = enable; +} + +PPT_ISR_SECTION void sync_hw_timer_impr_ip(bool enable) +{ + NVIC_SetPriority(SYNC_HW_TIMER_IRQN, SYNC_HW_TIMER_IP - enable); +} + +PPT_ISR_SECTION void sync_hw_timer_handler(void) +{ + time_debug_level_low(TIME_DEBUG_CHAN_ISR_GPIO); + time_debug_level_high(TIME_DEBUG_CHAN_TIMING); + sync_hw_timer_cb_t tmp_cb = sync_ctx.hw_timer_cb; + +#if SYNC_SUPPORT_MT1R + uint32_t period = (sync_ctx.hw_timer_periodic && + (sync_ctx.hw_timer_shift_state == SYNC_HW_TIMER_SHIFT_STATE_SHIFTING)) ? + sync_ctx.hw_timer_shift_period - SYNC_HW_TIMER_SHIFT_COMPENSATE : sync_ctx.hw_timer_period; + uint32_t left = sync_hw_timer_get_left(); + sync_ctx.hw_timer_pend_time = left == 0 ? 0 : period - left; +#if SYNC_TRACE + if (sync_ctx.hw_timer_pend_time > sync_ctx.hw_timer_pend_time_max) + { + sync_ctx.hw_timer_pend_time_max = sync_ctx.hw_timer_pend_time; + } +#endif +#endif + + if (sync_ctx.hw_timer_periodic == false) + { + sync_ctx.hw_timer_cb = NULL; + /* Disable */ + ENHTIM_Cmd(SYNC_HW_TIMER, DISABLE); + } + else + { +#if SYNC_SUPPORT_MT1R + if (sync_ctx.hw_timer_shift_state == SYNC_HW_TIMER_SHIFT_STATE_PENDING) + { + /* in case already pend too long, shift next time */ + if (sync_ctx.hw_timer_pend_time < SYNC_HW_TIMER_SHIFT_TOLERANCE) + { + sync_ctx.hw_timer_shift_state = SYNC_HW_TIMER_SHIFT_STATE_SHIFTING; + sync_ctx.hw_timer_shift_period = sync_ctx.hw_timer_period + sync_ctx.hw_timer_shift_time; + ENHTIM_Cmd(SYNC_HW_TIMER, DISABLE); + SYNC_HW_TIMER->ENHTIM_MAX_CNT = (sync_ctx.hw_timer_shift_period - SYNC_HW_TIMER_SHIFT_COMPENSATE) * + SYNC_HW_TIMER_CLOCK; + ENHTIM_Cmd(SYNC_HW_TIMER, ENABLE); + time_debug_level_high(TIME_DEBUG_CHAN_ISR_GPIO); + time_debug_level_low(TIME_DEBUG_CHAN_ISR_GPIO); + } + } + else if (sync_ctx.hw_timer_shift_state == SYNC_HW_TIMER_SHIFT_STATE_SHIFTING) + { + uint32_t new_period = sync_ctx.hw_timer_period; + if (sync_ctx.hw_timer_pend_time < SYNC_HW_TIMER_SHIFT_TOLERANCE) + { + sync_ctx.hw_timer_shift_state = SYNC_HW_TIMER_SHIFT_STATE_IDLE; + } + else + { + if (sync_ctx.hw_timer_pend_time + 20 < sync_ctx.hw_timer_period) + { + /* re-enter shift state */ + new_period = sync_ctx.hw_timer_period - sync_ctx.hw_timer_pend_time; + sync_ctx.hw_timer_shift_time = sync_ctx.hw_timer_pend_time; + sync_ctx.hw_timer_shift_period = new_period; + new_period -= SYNC_HW_TIMER_SHIFT_COMPENSATE; + time_debug_level_high(TIME_DEBUG_CHAN_ISR_GPIO); + time_debug_level_low(TIME_DEBUG_CHAN_ISR_GPIO); + } + else + { + /* can't handle this case */ + sync_ctx.hw_timer_shift_state = SYNC_HW_TIMER_SHIFT_STATE_IDLE; + } + } + ENHTIM_Cmd(SYNC_HW_TIMER, DISABLE); + SYNC_HW_TIMER->ENHTIM_MAX_CNT = new_period * SYNC_HW_TIMER_CLOCK; + ENHTIM_Cmd(SYNC_HW_TIMER, ENABLE); + } +#endif + time_debug_level_high(TIME_DEBUG_CHAN_ISR_GPIO); + } + /* Clear interrupt */ + ENHTIM_ClearINTPendingBit(SYNC_HW_TIMER, ENHTIM_INT_TIM); + NVIC_ClearPendingIRQ(SYNC_HW_TIMER_IRQN); + if (tmp_cb) + { + //APP_PRINT_INFO1("sync_hw_timer_handler: callback 0x%x", tmp_cb); + tmp_cb(); + } + time_debug_level_low(TIME_DEBUG_CHAN_TIMING); +} + +#if SYNC_SUPPORT_MT1R +PPT_ISR_SECTION void sync_hw_timer_shift(int32_t time) +{ + bool shift_pend = false; + bool timer_pend = false; + uint32_t left = 0; + int32_t new_period = 0; + if (sync_ctx.hw_timer_shift_state != SYNC_HW_TIMER_SHIFT_STATE_IDLE) + { + if (SYNC_ISR_DEBUG) + { + APP_PRINT_WARN1("sync_isr: timer shift state error %d", sync_ctx.hw_timer_shift_state); + } + return; + } + if (time == 0 || (time < 0 && sync_ctx.hw_timer_period <= -time)) + { + if (SYNC_ISR_DEBUG) + { + APP_PRINT_WARN2("sync_isr: timer shift time error, period %d, shift %d", sync_ctx.hw_timer_period, + time); + } + return; + } + + left = sync_hw_timer_get_left(); + timer_pend = sync_hw_timer_check_pending(); + if (timer_pend) + { + shift_pend = true; + } + else + { + new_period = left + time; + if (left < 10 || (left + 2) >= sync_ctx.hw_timer_period || new_period < 20) + { + shift_pend = true; + } + } + + if (shift_pend) + { + sync_ctx.hw_timer_shift_state = SYNC_HW_TIMER_SHIFT_STATE_PENDING; + sync_ctx.hw_timer_shift_time = time; + } + else + { + time_debug_level_low(TIME_DEBUG_CHAN_ISR_GPIO); + sync_ctx.hw_timer_shift_state = SYNC_HW_TIMER_SHIFT_STATE_SHIFTING; + sync_ctx.hw_timer_shift_period = new_period; + sync_ctx.hw_timer_shift_time = time; + ENHTIM_Cmd(SYNC_HW_TIMER, DISABLE); + ENHTIM_ClearINTPendingBit(SYNC_HW_TIMER, ENHTIM_INT_TIM); + NVIC_ClearPendingIRQ(SYNC_HW_TIMER_IRQN); + SYNC_HW_TIMER->ENHTIM_MAX_CNT = (new_period - SYNC_HW_TIMER_SHIFT_COMPENSATE) * SYNC_HW_TIMER_CLOCK; + ENHTIM_Cmd(SYNC_HW_TIMER, ENABLE); + time_debug_level_high(TIME_DEBUG_CHAN_ISR_GPIO); + time_debug_level_low(TIME_DEBUG_CHAN_ISR_GPIO); + time_debug_level_high(TIME_DEBUG_CHAN_ISR_GPIO); + } + //APP_PRINT_INFO4("sync_isr: shift %d, left %d, pending %d, after state %d", time, left, timer_pend, sync_ctx.hw_timer_shift_state); +} + +void sync_hw_timer1_handler(void); +void sync_hw_timer1_init(void) +{ + RCC_PeriphClockCmd(APBPeriph_ENHTIMER, APBPeriph_ENHTIMER_CLOCK, ENABLE); + ENHTIM_InitTypeDef TIM_InitStruct; + ENHTIM_StructInit(&TIM_InitStruct); + TIM_InitStruct.ENHTIM_Mode = ENHTIM_MODE_PWM_MANUAL; + ENHTIM_Init(SYNC_HW_TIMER1, &TIM_InitStruct); + + NVIC_InitTypeDef NVIC_InitStruct; + NVIC_InitStruct.NVIC_IRQChannel = SYNC_HW_TIMER1_IRQN; + NVIC_InitStruct.NVIC_IRQChannelPriority = SYNC_HW_TIMER_IP; + NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&NVIC_InitStruct); + + ENHTIM_ClearINTPendingBit(SYNC_HW_TIMER1, ENHTIM_INT_TIM); + ENHTIM_INTConfig(SYNC_HW_TIMER1, ENHTIM_INT_TIM, ENABLE); + RamVectorTableUpdate(SYNC_HW_TIMER1_VECTORN, sync_hw_timer1_handler); +} + +static PPT_ISR_SECTION void sync_hw_timer1_disable(void) +{ + uint32_t lock = sync_enter_critical(); + ENHTIM_Cmd(SYNC_HW_TIMER1, DISABLE); + ENHTIM_ClearINTPendingBit(SYNC_HW_TIMER1, ENHTIM_INT_TIM); + NVIC_ClearPendingIRQ(SYNC_HW_TIMER1_IRQN); + sync_exit_critical(lock); +} + +PPT_ISR_SECTION void sync_hw_timer1_start(uint32_t period_us, sync_hw_timer_cb_t cb) +{ + sync_hw_timer1_disable(); + sync_ctx.hw_timer1_cb = cb; + SYNC_HW_TIMER1->ENHTIM_MAX_CNT = period_us * SYNC_HW_TIMER_CLOCK; + ENHTIM_Cmd(SYNC_HW_TIMER1, ENABLE); + time_debug_level_low(SYNC_TIME_DEBUG_TIMER1); + time_debug_level_high(SYNC_TIME_DEBUG_TIMER1); +} + +PPT_ISR_SECTION void sync_hw_timer1_stop(void) +{ + if (sync_ctx.hw_timer1_cb) + { + time_debug_level_low(SYNC_TIME_DEBUG_TIMER1); + sync_hw_timer1_disable(); + sync_ctx.hw_timer1_cb = NULL; + } +} + +PPT_ISR_SECTION void sync_hw_timer1_handler(void) +{ + time_debug_level_low(SYNC_TIME_DEBUG_TIMER1); + sync_hw_timer_cb_t tmp_cb = sync_ctx.hw_timer1_cb; + sync_ctx.hw_timer1_cb = NULL; + ENHTIM_Cmd(SYNC_HW_TIMER1, DISABLE); + + ENHTIM_ClearINTPendingBit(SYNC_HW_TIMER1, ENHTIM_INT_TIM); + NVIC_ClearPendingIRQ(SYNC_HW_TIMER1_IRQN); + + if (tmp_cb) + { + //APP_PRINT_INFO1("sync_hw_timer1_handler: callback 0x%x", tmp_cb); + tmp_cb(); + } +} +#endif + +void sync_hw_frtimer_init(void) +{ + RCC_PeriphClockCmd(APBPeriph_ENHTIMER, APBPeriph_ENHTIMER_CLOCK, ENABLE); + ENHTIM_InitTypeDef TIM_InitStruct; + ENHTIM_StructInit(&TIM_InitStruct); + TIM_InitStruct.ENHTIM_ClockDiv = ENHTIM_CLOCK_DIVIDER_1; + TIM_InitStruct.ENHTIM_Mode = ENHTIM_MODE_FreeRun; + TIM_InitStruct.ENHTIM_LatchCountEn[1] = ENABLE; + TIM_InitStruct.ENHTIM_LatchCountEn[2] = ENABLE; + ENHTIM_Init(SYNC_HW_FRTIMER, &TIM_InitStruct); + sync_hw_frtimer_start(); +} + +void sync_hw_frtimer_start(void) +{ + ENHTIM_Cmd(SYNC_HW_FRTIMER, ENABLE); +} + +void sync_hw_frtimer_stop(void) +{ + ENHTIM_Cmd(SYNC_HW_FRTIMER, DISABLE); +} + +PPT_API_SECTION uint32_t sync_hw_frtimer_get_count(void) +{ + return ENHTIM_GetCurrentCount(SYNC_HW_FRTIMER); +} + +PPT_API_SECTION int32_t sync_hw_frtimer_time_diff(uint32_t time1, uint32_t time2) +{ + int32_t diff_us; + uint32_t abs = time1 >= time2 ? time1 - time2 : time2 - time1; + if (abs > (SYNC_HW_FRTIMER_MAX_VALUE >> 1)) + { + if (time1 >= time2) + { + diff_us = time1 - time2 - SYNC_HW_FRTIMER_MAX_VALUE - 1; + } + else + { + diff_us = SYNC_HW_FRTIMER_MAX_VALUE + 1 - time2 + time1; + } + } + else + { + diff_us = time1 - time2; + } + + return diff_us / SYNC_HW_FRTIMER_CLOCK; +} + +static void sync_sw_timer_cb(void *timer) +{ + uint32_t timer_id = 0; + os_timer_id_get(&timer, &timer_id); + if (timer_id) + { + sync_sw_timer_t *sync_timer = (sync_sw_timer_t *)timer_id; + //uint32_t lock = sync_enter_critical(); + sync_sw_timer_cb_t cb = sync_timer->cb; + if (cb) + { + cb(sync_timer); + } + //sync_exit_critical(lock); + } +} + +void sync_sw_timer_start(sync_sw_timer_t *sync_timer, uint32_t interval_ms, sync_sw_timer_cb_t cb) +{ + sync_timer->cb = cb; + if (sync_timer->timer == NULL) + { + os_timer_create(&sync_timer->timer, "sync", (uint32_t)sync_timer, interval_ms, true, + sync_sw_timer_cb); + os_timer_start(&sync_timer->timer); + } + else + { + os_timer_restart(&sync_timer->timer, interval_ms); + } +} + +void sync_sw_timer_stop(sync_sw_timer_t *sync_timer) +{ + if (sync_timer->timer) + { + os_timer_delete(&sync_timer->timer); + sync_timer->timer = NULL; + } + sync_timer->cb = NULL; +} + +PPT_API_SECTION uint64_t sync_native_time_read(void) +{ + uint32_t clk; + uint16_t cnt; + do + { + clk = BB_read_native_clock(); + cnt = BB_read_native_counter(); + } + while (clk != BB_read_native_clock()); + uint64_t time = (((uint64_t)(clk & 0xfffffffe) * 625) >> 1) + 624 - cnt; + return time; +} + +void sync_event_cb_reg(sync_event_cb_t cb) +{ + sync_ctx.event_cb = cb; +} + +void sync_msg_reg_receive_cb(sync_msg_receive_cb_t cb) +{ + sync_ctx.msg_receive_cb = cb; +} + +void sync_msg_set_quota(uint8_t msg_quota[SYNC_MSG_TYPE_NUM]) +{ + memcpy(sync_ctx.msg_quota, msg_quota, SYNC_MSG_TYPE_NUM); +} + +bool sync_msg_set_quota_by_type(sync_msg_type_t type, uint8_t quota) +{ + if (type >= SYNC_MSG_TYPE_NUM) + { + return false; + } + + sync_ctx.msg_quota[type] = quota; + return true; +} + +void sync_msg_set_finite_retrans(uint8_t msg_retrans_num) +{ + sync_ctx.msg_finite_retrans_num = msg_retrans_num; +} + +void sync_msg_set_dynamic_retrans(uint8_t msg_retrans_num_lower, uint8_t msg_retrans_num_upper) +{ + if (msg_retrans_num_lower <= msg_retrans_num_upper) + { + sync_ctx.msg_dynamic_retrans_num_lower = msg_retrans_num_lower; + sync_ctx.msg_dynamic_retrans_num_upper = msg_retrans_num_upper; + } +} + +void sync_msg_init(void) +{ + sync_ctx.msg_quota_total = 0; + for (uint8_t loop = 0; loop < SYNC_MSG_TYPE_NUM; loop++) + { + sync_ctx.msg_quota_total += sync_ctx.msg_quota[loop]; + } + + if (sync_ctx.msg_quota_total) + { + sync_ctx.msg_quota_total += 1; + if (sync_ctx.pmsg_buff == NULL) + { + sync_msg_t *pmsg = (sync_msg_t *)os_mem_alloc(RAM_TYPE_BUFFER_ON, + sync_ctx.msg_quota_total * sizeof(sync_msg_t)); + for (uint8_t loop = 0; loop < sync_ctx.msg_quota_total; loop++) + { + plt_list_push(&sync_ctx.msg_free, &pmsg[loop]); + } + sync_ctx.pmsg_buff = pmsg; + } + } +} + +void sync_msg_reset(void) +{ +#if 1 + /* print message queue state for debug */ + APP_PRINT_INFO4("sync: msg reset, total %d free %d sending %d, buff addr 0x%x", + sync_ctx.msg_quota_total, + sync_ctx.msg_free.count, sync_ctx.msg_send.count, sync_ctx.pmsg_buff); + for (uint8_t loop = 0; loop < SYNC_MSG_TYPE_NUM; loop++) + { + APP_PRINT_INFO3("sync: msg reset, type %d quota %d count %d", loop, sync_ctx.msg_quota[loop], + sync_ctx.msg_count[loop]); + } + + { + uint8_t msg_count = 0; + sync_msg_t *pmsg = (sync_msg_t *)sync_ctx.msg_send.pfirst; + while (pmsg) + { + msg_count += 1; + APP_PRINT_INFO3("sync: msg reset, send queue count %d ptr 0x%x next 0x%x", msg_count, pmsg, + pmsg->pnext); + pmsg = (sync_msg_t *)pmsg->pnext; + } + } + + { + uint8_t msg_count = 0; + sync_msg_t *pmsg = (sync_msg_t *)sync_ctx.msg_free.pfirst; + while (pmsg) + { + msg_count += 1; + APP_PRINT_INFO3("sync: msg reset, free queue count %d ptr 0x%x next 0x%x", msg_count, pmsg, + pmsg->pnext); + pmsg = (sync_msg_t *)pmsg->pnext; + } + } +#endif + + for (uint8_t loop = 0; loop < SYNC_MSG_TYPE_NUM; loop++) + { + sync_ctx.msg_count[loop] = 0; + } + sync_ctx.msg_send.pfirst = NULL; + sync_ctx.msg_send.plast = NULL; + sync_ctx.msg_send.count = 0; + sync_ctx.msg_free.pfirst = NULL; + sync_ctx.msg_free.plast = NULL; + sync_ctx.msg_free.count = 0; + sync_msg_t *pmsg = sync_ctx.pmsg_buff; + for (uint8_t loop = 0; loop < sync_ctx.msg_quota_total; loop++) + { + plt_list_push(&sync_ctx.msg_free, &pmsg[loop]); + } +} + +PPT_ISR_SECTION void sync_msg_handle_tx_done(void *para1, uint32_t para2) +{ + sync_msg_t *pmsg = (sync_msg_t *)para1; + uint32_t lock = sync_enter_critical(); + sync_ctx.msg_count[pmsg->type] -= 1; + sync_exit_critical(lock); + if (pmsg->send_cb) + { + pmsg->send_cb(pmsg->type, pmsg->data, pmsg->len, &pmsg->send_info); + } + lock = sync_enter_critical(); + plt_list_push(&sync_ctx.msg_free, pmsg); + sync_exit_critical(lock); +} + +PPT_API_SECTION sync_err_code_t sync_msg_send(sync_msg_type_t type, uint8_t *data, uint16_t len, + sync_msg_send_cb_t send_cb) +{ + if (type >= SYNC_MSG_TYPE_NUM || data == NULL) + { + return SYNC_ERR_CODE_INVALID_PARAM; + } + + if (len == 0 || len > SYNC_MSG_MAX_LEN) + { + return SYNC_ERR_CODE_INVALID_LENGTH; + } + + if (sync_ctx.msg_count[type] >= sync_ctx.msg_quota[type]) + { + return SYNC_ERR_CODE_FULL_QUEUE; + } + + uint32_t lock = sync_enter_critical(); + sync_msg_t *pmsg = (sync_msg_t *)plt_list_pop(&sync_ctx.msg_free); + sync_exit_critical(lock); + if (pmsg == NULL) + { + return SYNC_ERR_CODE_UNKNOWN; + } + + pmsg->type = type; + memcpy(pmsg->data, data, len); + pmsg->len = len; + pmsg->send_cb = send_cb; + + lock = sync_enter_critical(); + plt_list_push(&sync_ctx.msg_send, (void *)pmsg); + sync_ctx.msg_count[type] += 1; + uint32_t list_size = sync_ctx.msg_send.count; + if (list_size == 1) + { +#if SYNC_ROLE_MASTER_SUPPORT + if (sync_ctx.role == SYNC_ROLE_MASTER) + { + sync_master_handle_tx_trigger(); + } +#endif +#if SYNC_ROLE_SLAVE_SUPPORT + if (sync_ctx.role == SYNC_ROLE_SLAVE) + { + sync_slave_handle_tx_trigger(); + } +#endif + } + sync_exit_critical(lock); + + return SYNC_ERR_CODE_SUCCESS; +} + +uint8_t sync_msg_get_available_number(sync_msg_type_t type) +{ + if (type >= SYNC_MSG_TYPE_NUM && type != SYNC_MSG_TYPE_ALL) + { + return 0; + } + uint8_t count = 0; + if (type == SYNC_MSG_TYPE_ALL) + { + for (uint8_t loop = 0; loop < SYNC_MSG_TYPE_NUM; loop++) + { + count += sync_ctx.msg_quota[loop] - sync_ctx.msg_count[loop]; + } + } + else + { + count = sync_ctx.msg_quota[type] - sync_ctx.msg_count[type]; + } + return count; +} + +uint8_t sync_msg_flush(sync_msg_type_t type) +{ + uint8_t count = 0; + if (type >= SYNC_MSG_TYPE_NUM && type != SYNC_MSG_TYPE_ALL) + { + return 0; + } + uint32_t lock = sync_enter_critical(); + sync_msg_t *pmsg_prev = NULL; + sync_msg_t *pmsg = (sync_msg_t *)sync_ctx.msg_send.pfirst; + while (pmsg) + { + if (type == SYNC_MSG_TYPE_ALL || type == pmsg->type) + { + plt_list_delete(&sync_ctx.msg_send, pmsg_prev, pmsg); + sync_msg_t *pmsg_next = (sync_msg_t *)pmsg->pnext; + if (pmsg->send_cb) + { + pmsg->send_info.res = SYNC_SEND_RESULT_FLUSHED; + sync_pendcall(sync_msg_handle_tx_done, pmsg, 0); + } + else + { + sync_ctx.msg_count[pmsg->type] -= 1; + plt_list_push(&sync_ctx.msg_free, pmsg); + } + pmsg = pmsg_next; + count += 1; + } + else + { + pmsg_prev = pmsg; + pmsg = (sync_msg_t *)pmsg->pnext; + } + } +#if SYNC_ROLE_MASTER_SUPPORT + if (sync_ctx.role == SYNC_ROLE_MASTER) + { + sync_master_msg_flush(type); + } +#endif + sync_exit_critical(lock); + return count; +} + +PPT_API_SECTION uint32_t sync_rand(void) +{ + return ((uint32_t)rand() & 0xffffff) + ((uint32_t)rand() << 24); +} + +PPT_API_SECTION uint32_t sync_enter_critical(void) +{ + uint32_t flag = __get_PRIMASK(); + __disable_irq(); + return flag; +} + +PPT_API_SECTION void sync_exit_critical(uint32_t flag) +{ + if (flag == 0) + { + __enable_irq(); + } +} + +void sync_init(sync_role_t role) +{ + APP_PRINT_INFO1("sync: version "SYNC_VERSION", role %d", role); + + uint32_t random_seed_value = platform_random(0xffffffff); + srand(random_seed_value); + + uint16_t freq[] = SYNC_CHANNEL_FREQUENCY; + if (SYNC_CHANNEL_NUM_DV != sizeof(freq) / sizeof(freq[0])) + { + APP_PRINT_ERROR2("sync: channel wrong %d %d", SYNC_CHANNEL_NUM_DV, sizeof(freq) / sizeof(freq[0])); + return; + } + sync_channel_set(SYNC_CHANNEL_NUM_DV, SYNC_CHANNEL_GROUP_NUM_DV, freq); + + sync_ctx.crc_len = SYNC_CRC_LEN_DV; + sync_ctx.crc_poly = SYNC_CRC_POLY_DV; + sync_ctx.crc_init = SYNC_CRC_INIT_DV; + + sync_ctx.conn_interval = SYNC_SYNC_SPEED_DV; + sync_ctx.slave_hopping_speed = SYNC_SLAVE_HOPPING_SPEED_DV; + + sync_ctx.tx_power_adaptive = false; + sync_ctx.tx_power_dbm_max = 8; + sync_ctx.tx_power_dbm_min = 8; + + sync_ctx.msg_quota[SYNC_MSG_TYPE_ONESHOT] = 2; + sync_ctx.msg_quota[SYNC_MSG_TYPE_FINITE_RETRANS] = 2; + sync_ctx.msg_quota[SYNC_MSG_TYPE_DYNAMIC_RETRANS] = 2; + sync_ctx.msg_quota[SYNC_MSG_TYPE_INFINITE_RETRANS] = 4; + sync_ctx.msg_finite_retrans_num = 2; + sync_ctx.msg_dynamic_retrans_num_lower = 0; + sync_ctx.msg_dynamic_retrans_num_upper = SYNC_MSG_RETRANS_NUM_INFINITE; + + sync_ctx.log_isr = 0; + sync_ctx.pair_rssi_th = -128; + sync_ctx.hb_to_times = SYNC_HB_TO_TIMES_DV; + sync_ctx.cca_times = SYNC_CCA_TIMES_DV; + + sync_ctx.role = role; + +#if SYNC_ROLE_MASTER_SUPPORT + if (sync_ctx.role == SYNC_ROLE_MASTER) + { + sync_master_init(); + } +#endif +#if SYNC_ROLE_SLAVE_SUPPORT + if (sync_ctx.role == SYNC_ROLE_SLAVE) + { + sync_slave_init(); + } +#endif +} + +void sync_enable(void) +{ + sync_msg_init(); + +#if SYNC_ROLE_MASTER_SUPPORT + if (sync_ctx.role == SYNC_ROLE_MASTER) + { + sync_master_enable(); + } +#endif +#if SYNC_ROLE_SLAVE_SUPPORT + if (sync_ctx.role == SYNC_ROLE_SLAVE) + { + sync_slave_enable(); + } +#endif +} + +sync_err_code_t sync_pair(void) +{ +#ifdef SYNC_ROLE_MASTER_SUPPORT + if (sync_ctx.role == SYNC_ROLE_MASTER) + { + return sync_master_pair(); + } +#endif +#ifdef SYNC_ROLE_SLAVE_SUPPORT + if (sync_ctx.role == SYNC_ROLE_SLAVE) + { + return sync_slave_pair(); + } +#endif + return SYNC_ERR_CODE_UNKNOWN; +} + +sync_err_code_t sync_connect(sync_bond_info_t *bond_info) +{ +#if SYNC_ROLE_MASTER_SUPPORT + if (sync_ctx.role == SYNC_ROLE_MASTER) + { + return sync_master_connect(bond_info); + } +#endif +#if SYNC_ROLE_SLAVE_SUPPORT + if (sync_ctx.role == SYNC_ROLE_SLAVE) + { + return sync_slave_connect(bond_info); + } +#endif + return SYNC_ERR_CODE_UNKNOWN; +} + +void sync_stop(void) +{ +#if SYNC_ROLE_MASTER_SUPPORT + if (sync_ctx.role == SYNC_ROLE_MASTER) + { + sync_master_stop(); + } +#endif +#if SYNC_ROLE_SLAVE_SUPPORT + if (sync_ctx.role == SYNC_ROLE_SLAVE) + { + sync_slave_stop(); + } +#endif +} + +void sync_deinit(void) +{ + if (sync_ctx.chan_cfg) + { + os_mem_free(sync_ctx.chan_cfg); + sync_ctx.chan_cfg = NULL; + } + +#if SYNC_ROLE_MASTER_SUPPORT + if (sync_ctx.role == SYNC_ROLE_MASTER) + { + sync_master_deinit(); + } +#endif +#if SYNC_ROLE_SLAVE_SUPPORT + if (sync_ctx.role == SYNC_ROLE_SLAVE) + { + sync_slave_deinit(); + } +#endif +} + +void sync_dlps_init(void) +{ +#if SYNC_ROLE_MASTER_SUPPORT + if (sync_ctx.role == SYNC_ROLE_MASTER) + { + return sync_master_dlps_init(); + } +#endif +#if SYNC_ROLE_SLAVE_SUPPORT + if (sync_ctx.role == SYNC_ROLE_SLAVE) + { + return sync_slave_dlps_init(); + } +#endif +} + +void sync_crc_set(uint8_t crc_len, uint32_t crc_poly, uint32_t crc_init) +{ + sync_ctx.crc_len = crc_len; + sync_ctx.crc_poly = crc_poly; + sync_ctx.crc_init = crc_init; + WR_PPT_REG_FIELD(PRO_PACKET_CONTROL, crc_field_length_2_0, sync_ctx.crc_len >> 3); +} + +bool sync_time_set(sync_time_param_t type, uint32_t time) +{ + bool ret = true; + switch (type) + { + case SYNC_TIME_PARAM_CONNECT_INTERVAL: +#if SYNC_SUPPORT_MT1R + sync_ctx.mt1r.flag = time == 125; + sync_ctx.conn_interval = sync_ctx.mt1r.flag ? 250 : time; +#else + sync_ctx.conn_interval = time; +#endif + break; + case SYNC_TIME_PARAM_CONNECT_INTERVAL_HIGH: + sync_ctx.conn_interval_high = time; + break; + case SYNC_TIME_PARAM_SYNC_LOST_PERIOD: + sync_ctx.sync_lost_period = time; + break; + case SYNC_TIME_PARAM_SYNC_FAST_PERIOD: + sync_ctx.sync_fast_period = time; + break; + case SYNC_TIME_PARAM_HB_TO_TIMES: + sync_ctx.hb_to_times = time; + break; + case SYNC_TIME_PARAM_CHANNEL_ASSESS_TIMES: + sync_ctx.cca_times = time; + break; + case SYNC_TIME_PARAM_SLAVE_HOPPING_SPEED: + sync_ctx.slave_hopping_speed = time; + break; + default: + ret = false; + break; + } + return ret; +} + +bool sync_time_get(sync_time_param_t type, uint32_t *time) +{ + bool ret = true; + switch (type) + { + case SYNC_TIME_PARAM_CONNECT_INTERVAL: +#if SYNC_SUPPORT_MT1R + *time = sync_ctx.mt1r.flag ? 125 : sync_ctx.conn_interval; +#else + *time = sync_ctx.conn_interval; +#endif + break; + case SYNC_TIME_PARAM_CONNECT_INTERVAL_HIGH: + *time = sync_ctx.conn_interval_high; + break; + default: + ret = false; + break; + } + return ret; +} + +bool sync_log_set(uint8_t level, bool on) +{ + sync_ctx.log_isr = on; + return true; +} + +#if SYNC_SUPPORT_POWER_CONTROL +static const int8_t sync_power_level[] = {-40, -20, -10, 0, 4, 8, 10, 14, 18, 20}; +static uint8_t sync_power_ctrl_get_idx(int8_t power_dbm) +{ + uint8_t table_size = sizeof(sync_power_level) / sizeof(sync_power_level[0]); + if (sync_power_level[table_size - 1] < power_dbm) + { + return table_size - 1; + } + for (int loop = table_size - 1; loop >= 0; loop--) + { + if (sync_power_level[loop] >= power_dbm && (loop == 0 || sync_power_level[loop - 1] < power_dbm)) + { + return loop; + } + } + return table_size - 1; +} + +static void sync_power_ctrl_adjust(sync_sw_timer_t *sync_timer) +{ + if (sync_ctx.tx_power_levels <= 1) + { + return; + } + + uint8_t adjust = 0; + + uint32_t count_fail = sync_ctx.power_ctrl_count_fail; + uint32_t count = sync_ctx.power_ctrl_count; + uint16_t old_per = sync_ctx.power_ctrl_per; + if (count && count_fail < count) + { + uint16_t per = count_fail * 1000 / count; + sync_ctx.power_ctrl_per = (old_per * 8 + per * 2) / 10; + if (sync_ctx.power_ctrl_per > 100) + { + adjust = 2; + } + else if (sync_ctx.power_ctrl_per < 10) + { + adjust = 1; + } + } + //APP_PRINT_INFO5("sync: power ctrl count %d, count_fail %d, per %d -> %d, adjust %d", count, count_fail, old_per, sync_ctx.power_ctrl_per, adjust); + sync_ctx.power_ctrl_count = 0; + sync_ctx.power_ctrl_count_fail = 0; + + if (adjust == 1) + { + if (sync_ctx.tx_power_idx_cur > sync_ctx.tx_power_idx_min) + { + sync_ctx.tx_power_idx_cur -= 1; + ppt_set_tx_power_dbm(sync_power_level[sync_ctx.tx_power_idx_cur]); + APP_PRINT_INFO3("sync: power ctrl %d decrease from %d to %d", sync_ctx.power_ctrl_per, + sync_power_level[sync_ctx.tx_power_idx_cur + 1], sync_power_level[sync_ctx.tx_power_idx_cur]); + sync_ctx.power_ctrl_per = 0; + } + + } + else if (adjust == 2) + { + if (sync_ctx.tx_power_idx_cur < sync_ctx.tx_power_idx_max) + { + sync_ctx.tx_power_idx_cur += 1; + ppt_set_tx_power_dbm(sync_power_level[sync_ctx.tx_power_idx_cur]); + APP_PRINT_INFO3("sync: power ctrl %d increase from %d to %d", sync_ctx.power_ctrl_per, + sync_power_level[sync_ctx.tx_power_idx_cur - 1], sync_power_level[sync_ctx.tx_power_idx_cur]); + sync_ctx.power_ctrl_per = 0; + } + } +} + +void sync_power_ctrl_init(void) +{ + sync_ctx.tx_power_idx_max = sync_power_ctrl_get_idx(sync_ctx.tx_power_dbm_max); + sync_ctx.tx_power_idx_min = sync_power_ctrl_get_idx(sync_ctx.tx_power_dbm_min); + sync_ctx.tx_power_levels = sync_ctx.tx_power_idx_min - sync_ctx.tx_power_idx_max + 1; + if (sync_ctx.tx_power_levels > 1) + { + sync_ctx.tx_power_idx_cur = sync_ctx.tx_power_idx_max; + ppt_set_tx_power_dbm(sync_power_level[sync_ctx.tx_power_idx_cur]); + } + else + { + ppt_set_tx_power_dbm(sync_ctx.tx_power_dbm_max); + } +} + +void sync_power_ctrl_start(void) +{ + if (sync_ctx.tx_power_levels <= 1) + { + return; + } + + sync_ctx.power_ctrl_count = 0; + sync_ctx.power_ctrl_count_fail = 0; + sync_ctx.power_ctrl_per = 0; + sync_sw_timer_start(&sync_ctx.power_ctrl_timer, SYNC_SUPPORT_POWER_CONTROL_PERIOD, + sync_power_ctrl_adjust); +} + +void sync_power_ctrl_stop(void) +{ + if (sync_ctx.tx_power_levels <= 1) + { + return; + } + + sync_sw_timer_stop(&sync_ctx.power_ctrl_timer); +} +#endif + +bool sync_tx_power_set(bool dynamic, int8_t tx_power_dbm_max, int8_t tx_power_dbm_min) +{ + if (tx_power_dbm_max < tx_power_dbm_min) + { + return false; + } + + sync_ctx.tx_power_adaptive = dynamic; + sync_ctx.tx_power_dbm_max = tx_power_dbm_max; + sync_ctx.tx_power_dbm_min = tx_power_dbm_min; + return true; +} + +bool sync_pair_rssi_set(int8_t rssi) +{ + sync_ctx.pair_rssi_th = rssi; + return true; +} + +bool sync_tifs_set(uint8_t level, uint8_t tifs) +{ + if (level >= sizeof(sync_ctx.tifs) / sizeof(sync_ctx.tifs[0])) + { + return false; + } + sync_ctx.tifs[level] = tifs; + return true; +} + +void sync_check_feature(void) +{ +#if SYNC_SUPPORT_POWER_CONTROL + if (sync_ctx.tx_power_adaptive) + { + sync_power_ctrl_init(); + } + else +#endif + { + ppt_set_tx_power_dbm(sync_ctx.tx_power_dbm_max); + } +} + +void sync_hb_reg_cb(sync_hb_cb_t cb) +{ + sync_ctx.hb_cb = cb; +} + +void sync_rte_req_reg_cb(sync_rte_req_cb_t cb) +{ + sync_ctx.rte_req_cb = cb; +} diff --git a/bee/drivers/ppt/sync/src/ppt_sync_int.h b/bee/drivers/ppt/sync/src/ppt_sync_int.h new file mode 100644 index 00000000..7fdd6561 --- /dev/null +++ b/bee/drivers/ppt/sync/src/ppt_sync_int.h @@ -0,0 +1,471 @@ +/** +***************************************************************************************** +* Copyright(c) 2020, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file ppt_sync_int.h +* @brief Head file for sync protocol. +* @details data structs and external functions declaration. +* @author bill +* @date 2022-03-15 +* @version v0.1 +* ************************************************************************************* +*/ + +/* Define to prevent recursive inclusion */ +#ifndef _PPT_SYNC_INT_H_ +#define _PPT_SYNC_INT_H_ + +/* Add Includes here */ +#include +#include +#include "platform_macros.h" +#include "platform_list.h" +#include "ppt_sync.h" +#include "ppt_sync_pendcall.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** @addtogroup PPT_SYNC_Driver + * @{ + */ +#define PPT_SYNC_LOG_LEVEL CONFIG_PPT_DRIVER_LOG_LEVEL + +/** @defgroup PPT_SYNC_Driver_Exported_Macros Exported Macros + * @brief + * @{ + */ +#ifdef CONFIG_REALTEK_USING_PPT_SYNC_MASTER +#define SYNC_ROLE_MASTER_SUPPORT 1 +#else +#define SYNC_ROLE_MASTER_SUPPORT 0 +#endif + +#ifdef CONFIG_REALTEK_USING_PPT_SYNC_SLAVE +#define SYNC_ROLE_SLAVE_SUPPORT 1 +#else +#define SYNC_ROLE_SLAVE_SUPPORT 0 +#endif +#define SYNC_CHANNEL_FREQUENCY \ + {2432, 2447, 2462, 2477, 2407, 2422, 2437, 2452, 2442, 2457, 2472, 2413} +#define SYNC_CHANNEL_NUM_DV 12 +#define SYNC_CHANNEL_GROUP_NUM_DV 3 +#define SYNC_HEADER_LEN 8 // bit +#define SYNC_HEADER_SEQ_LEN 7 // bit +#define SYNC_LENGTH_LEN 7 // bit +#define SYNC_MSG_MAX_LEN 127 // byte +#define SYNC_CRC_LEN_DV 8 // bit +#define SYNC_CRC_POLY_DV 0x07 +#define SYNC_CRC_INIT_DV 0xff +#define SYNC_OVERHEAD_LEN 2 // byte +#define SYNC_ACC_ADDR_BR_DV 0x8EBE89D6 +#define SYNC_TIFS0_DV 40 // us +#define SYNC_TIFS1_DV 40 // us +#define SYNC_PAIR_SPEED_DV 1000 // us +#define SYNC_PAIR_PERIOD 1000000 // us +#define SYNC_PAIR_CFM_PERIOD_DV 8 // times +#define SYNC_SYNC_SLOW_SPEED_DV 1000 // us +#define SYNC_SYNC_SLOW_PERIOD 1000000 // us +#define SYNC_SYNC_SPEED_DV 1000 // us +#define SYNC_SYNC_SPEED_HIGH_DV 250 // us +#define SYNC_SYNC_SPEED_HIGH_MIN 250 // us +#define SYNC_SYNC_LOST_PERIOD_DV 8 // times +#define SYNC_SYNC_FAST_SPEED_DV 1000 // us +#define SYNC_SYNC_FAST_PERIOD_DV 3 // times +#define SYNC_HB_TO_TIMES_DV 3 // times +#define SYNC_CCA_TIMES_DV 3 // times +#define SYNC_SLAVE_HOPPING_SPEED_DV 200000 // us + +#define SYNC_PARAM_CONFIG 1 +#if SYNC_PARAM_CONFIG +#define SYNC_CRC_LEN sync_ctx.crc_len +#define SYNC_CRC_POLY sync_ctx.crc_poly +#define SYNC_CRC_INIT sync_ctx.crc_init +#define SYNC_PAIR_SPEED sync_ctx.conn_interval +#define SYNC_SYNC_SLOW_SPEED sync_ctx.conn_interval +#define SYNC_SYNC_SPEED sync_ctx.conn_interval +#define SYNC_SYNC_SPEED_HIGH \ + (sync_ctx.conn_interval_high <= sync_ctx.conn_interval ? sync_ctx.conn_interval_high \ + : sync_ctx.conn_interval) +#define SYNC_SYNC_FAST_SPEED sync_ctx.conn_interval +#define SYNC_CHANNEL_NUM sync_ctx.chan_num +#define SYNC_CHANNEL_GROUP_NUM sync_ctx.chan_group_num +#define SYNC_ACC_ADDR_BR sync_ctx.acc_br.addr +#define SYNC_HB_TO_TIMES sync_ctx.hb_to_times +#define SYNC_CCA_TIMES sync_ctx.cca_times +#define SYNC_SLAVE_HOPPING_SPEED sync_ctx.slave_hopping_speed +#define SYNC_ISR_DEBUG sync_ctx.log_isr +#else +#define SYNC_CRC_LEN SYNC_CRC_LEN_DV +#define SYNC_CRC_POLY SYNC_CRC_POLY_DV +#define SYNC_CRC_INIT SYNC_CRC_INIT_DV +#define SYNC_PAIR_SPEED SYNC_PAIR_SPEED_DV +#define SYNC_SYNC_SLOW_SPEED SYNC_SYNC_SLOW_SPEED_DV +#define SYNC_SYNC_SPEED SYNC_SYNC_SPEED_DV +#define SYNC_SYNC_SPEED_HIGH SYNC_SYNC_SPEED_DV +#define SYNC_SYNC_FAST_SPEED SYNC_SYNC_FAST_SPEED_DV +#define SYNC_CHANNEL_NUM SYNC_CHANNEL_NUM_DV +#define SYNC_CHANNEL_GROUP_NUM SYNC_CHANNEL_GROUP_NUM_DV +#define SYNC_ACC_ADDR_BR SYNC_ACC_ADDR_BR_DV +#define SYNC_HB_TO_TIMES SYNC_HB_TO_TIMES_DV +#define SYNC_CCA_TIMES SYNC_CCA_TIMES_DV +#define SYNC_SLAVE_HOPPING_SPEED SYNC_SLAVE_HOPPING_SPEED_DV +#define SYNC_ISR_DEBUG 0 +#endif + +#define SYNC_PAIR_CFM_PERIOD (SYNC_SYNC_SPEED * SYNC_PAIR_CFM_PERIOD_DV) +#define SYNC_SYNC_LOST_PERIOD \ + (sync_ctx.sync_lost_period ? sync_ctx.sync_lost_period \ + : SYNC_SYNC_SPEED * SYNC_SYNC_LOST_PERIOD_DV) +#define SYNC_SYNC_FAST_PERIOD \ + (sync_ctx.sync_fast_period \ + ? sync_ctx.sync_fast_period \ + : (SYNC_SYNC_LOST_PERIOD + SYNC_SYNC_FAST_PERIOD_DV * SYNC_SYNC_FAST_SPEED * \ + SYNC_CHANNEL_NUM / SYNC_CHANNEL_GROUP_NUM)) + +#define SYNC_SUPPORT_POWER_CONTROL 1 +#define SYNC_SUPPORT_POWER_CONTROL_PERIOD 1000 // ms + +#define SYNC_SUPPORT_MT1R 1 +#define SYNC_SUFFIX_LEN 7 // bit +#define SYNC_CONNECT_DELAY 300 +#define SYNC_HEADER_LEN_MT1R 6 // bit + +#define SYNC_SUPPORT_SYNC_FAST_DISABLE 1 + +#define SYNC_FRAME_BLE_COMPATIBLE 0 +#if SYNC_FRAME_BLE_COMPATIBLE +#undef SYNC_CHANNEL_FREQUENCY +#define SYNC_CHANNEL_FREQUENCY \ + {2402, 2406, 2410, 2414, 2418, 2422, 2426, 2430, 2434, 2438, 2442, 2446} +#undef SYNC_HEADER_LEN +#define SYNC_HEADER_LEN 8 // bit +#undef SYNC_LENGTH_LEN +#define SYNC_LENGTH_LEN 8 // bit +#undef SYNC_CRC_LEN +#define SYNC_CRC_LEN 24 +#undef SYNC_CRC_POLY +#define SYNC_CRC_POLY 0x00065b +#undef SYNC_CRC_INIT +#define SYNC_CRC_INIT 0x555555 +#undef SYNC_ACC_ADDR_BR_DV +#define SYNC_ACC_ADDR_BR_DV 0x8E89BED6 +#endif +/** @} End of PPT_SYNC_Driver_Exported_Macros */ + +/** @defgroup PPT_SYNC_Driver_Exported_Types Exported Types + * @brief + * @{ + */ + +#pragma pack(1) + +typedef union { + uint8_t value; + struct { + uint8_t ack : 1; + uint8_t seq : SYNC_HEADER_SEQ_LEN; + }; +#if SYNC_SUPPORT_MT1R + struct { + uint8_t ack : 1; + uint8_t seq : 4; + uint8_t req_ack : 1; + } m; + struct { + uint8_t ack : 1; + uint8_t seq : 4; + uint8_t rfu : 1; + } s; +#endif +} sync_header_t; + +typedef enum { + SYNC_OPCODE_EMPTY, + SYNC_OPCODE_PAIR_REQ, + SYNC_OPCODE_PAIR_RSP, + SYNC_OPCODE_PAIR_CONF, + SYNC_OPCODE_CONN_REQ, + SYNC_OPCODE_CONN_RSP, + SYNC_OPCODE_HEARTBEAT, + SYNC_OPCODE_APP_START = SYNC_OPCODE_APP_START_VALUE, +} sync_opcode_t; + +typedef struct { + uint16_t interval; +} sync_pair_req_t; + +typedef struct { + sync_acc_t acc; +} sync_pair_rsp_t; + +typedef struct { + uint16_t interval; +} sync_conn_req_t; + +typedef struct { + uint16_t interval; +} sync_heartbeat_t; + +typedef struct { +#if SYNC_FRAME_BLE_COMPATIBLE + uint8_t addr[5]; +#endif + uint32_t seq; + // uint8_t padding[10]; +} sync_app_test_t; + +typedef struct { +#if SYNC_FRAME_BLE_COMPATIBLE + uint8_t addr[5]; +#endif + uint32_t seq; + // uint8_t padding[22]; +} sync_app_test1_t; + +typedef struct { + sync_opcode_t opcode; + union { + sync_pair_req_t pair_req; + sync_pair_rsp_t pair_rsp; + sync_conn_req_t conn_req; + sync_heartbeat_t heartbeat; + sync_app_test_t app_test; + }; +} sync_pdu_t; + +#pragma pack() + +typedef struct { + void *pnext; + sync_msg_send_cb_t send_cb; + sync_msg_type_t type; + uint16_t len; + uint8_t data[SYNC_MSG_MAX_LEN]; + sync_send_info_t send_info; +} sync_msg_t; + +typedef struct { + uint16_t freq; + uint8_t bank; + uint8_t channel; + int16_t rssi; +#ifdef SYNC_DEBUG + uint32_t choose_times; + uint32_t used_count; + uint32_t fail_count; + uint32_t fail_burst_count; + uint32_t fail_burst_max; +#endif +} sync_channel_cfg_t; + +struct _sync_sw_timer_t; +typedef void (*sync_sw_timer_cb_t)(struct _sync_sw_timer_t *p_timer); +typedef struct _sync_sw_timer_t { + void *timer; + sync_sw_timer_cb_t cb; +} sync_sw_timer_t; + +typedef void (*sync_hw_timer_cb_t)(void); + +#if SYNC_SUPPORT_MT1R +typedef enum { + SYNC_HW_TIMER_SHIFT_STATE_IDLE, + SYNC_HW_TIMER_SHIFT_STATE_PENDING, + SYNC_HW_TIMER_SHIFT_STATE_SHIFTING +} sync_hw_timer_shift_state_t; +#endif + +typedef struct { + sync_role_t role; + uint8_t crc_len; // bit + uint32_t crc_poly; + uint32_t crc_init; + uint8_t chan_num; + uint8_t chan_group_num; + uint8_t chan_cur; + sync_channel_cfg_t *chan_cfg; + uint32_t chan_used_count; + uint32_t chan_miss_count; + sync_hw_timer_cb_t hw_timer_cb; + bool hw_timer_periodic; + sync_event_cb_t event_cb; + uint8_t msg_quota[SYNC_MSG_TYPE_NUM]; + uint8_t msg_finite_retrans_num; + uint8_t msg_dynamic_retrans_num_lower; + uint8_t msg_dynamic_retrans_num_upper; + uint8_t msg_retrans_count; + sync_msg_receive_cb_t msg_receive_cb; + uint8_t msg_quota_total; + uint8_t msg_count[SYNC_MSG_TYPE_NUM]; + plt_list_t msg_free; + plt_list_t msg_send; + sync_msg_t *pmsg_buff; + uint32_t conn_interval; //!< us + uint32_t conn_interval_high; //!< us + uint32_t sync_lost_period; //!< us + uint32_t sync_fast_period; //!< us + bool log_isr; + bool tx_power_adaptive; + int8_t tx_power_dbm_max; + int8_t tx_power_dbm_min; +#if SYNC_SUPPORT_POWER_CONTROL + int8_t tx_power_idx_cur; + int8_t tx_power_idx_max; + int8_t tx_power_idx_min; + uint8_t tx_power_levels; + sync_sw_timer_t power_ctrl_timer; + uint32_t power_ctrl_count; + uint32_t power_ctrl_count_fail; + uint16_t power_ctrl_per; +#endif + int8_t pair_rssi_th; + sync_acc_t acc_br; + uint8_t tifs[2]; + sync_hb_cb_t hb_cb; + uint8_t hb_to_times; + uint8_t cca_times; + uint32_t slave_hopping_speed; + sync_rte_req_cb_t rte_req_cb; +#if SYNC_SUPPORT_MT1R + struct { + bool flag; + } mt1r; + uint32_t hw_timer_period; + int32_t hw_timer_shift_time; + uint32_t hw_timer_shift_period; + uint32_t hw_timer_pend_time; + sync_hw_timer_shift_state_t hw_timer_shift_state; + sync_hw_timer_cb_t hw_timer1_cb; +#endif +} sync_ctx_t; + +extern sync_ctx_t sync_ctx; + +/** @} End of PPT_SYNC_Driver_Exported_Types */ + +/** @defgroup PPT_SYNC_Driver_Exported_Functions Exported Functions + * @brief + * @{ + */ + +/** + * @brief format diagnose output with raw data + * @param[in] data: raw data + * @param[in] data_len: raw data length + * @param[in] fmt: format string + * @return none + */ +void sync_ppt_init(void); +void sync_ppt_set_rf_time(void); +void sync_ppt_set_tifs(bool init); +void sync_channel_init(void); +void sync_channel_change(uint8_t idx); +void sync_channel_change_next(void); +void sync_channel_change_next_in_group(void); +#ifdef SYNC_DEBUG +void sync_channel_statistic(bool ok); +void sync_channel_clear_statistic(void); +void sync_channel_print_statistic(void); +#else +#define sync_channel_statistic(...) +#define sync_channel_clear_statistic(...) +#define sync_channel_print_statistic(...) +#endif +void sync_acc_set(sync_acc_t acc); +sync_acc_t sync_acc_gen_data(void); + +void sync_hw_timer_init(void); +void sync_hw_timer_start(uint32_t period_us, sync_hw_timer_cb_t cb); +void sync_hw_timer_restart(void); +void sync_hw_timer_stop(void); +uint32_t sync_hw_timer_get_left(void); +bool sync_hw_timer_check_pending(void); +void sync_hw_timer_set_periodic(bool enable); +void sync_hw_timer_impr_ip(bool enable); + +void sync_hw_timer_shift(int32_t time); +void sync_hw_timer1_init(void); +void sync_hw_timer1_start(uint32_t period_us, sync_hw_timer_cb_t cb); +void sync_hw_timer1_stop(void); + +void sync_hw_frtimer_init(void); +void sync_hw_frtimer_start(void); +void sync_hw_frtimer_stop(void); +uint32_t sync_hw_frtimer_get_count(void); +int32_t sync_hw_frtimer_time_diff(uint32_t time1, uint32_t time2); +#define SYNC_HW_FRTIMER_MAX_VALUE 0xFFFFFFFE +#define SYNC_HW_FRTIMER_CLOCK 40 +#define sync_hw_frtimer_time_elapse(late, early) \ + (((late) >= (early) ? (late) - (early) : (SYNC_HW_FRTIMER_MAX_VALUE - (early) + (late) + 1)) / \ + SYNC_HW_FRTIMER_CLOCK) + +void sync_sw_timer_start(sync_sw_timer_t *sync_timer, uint32_t interval_ms, sync_sw_timer_cb_t cb); +void sync_sw_timer_stop(sync_sw_timer_t *sync_timer); + +uint64_t sync_native_time_read(void); + +void sync_msg_init(void); +void sync_msg_handle_tx_done(void *para1, uint32_t para2); + +void sync_check_feature(void); + +void sync_master_handle_tx_trigger(void); +void sync_master_msg_flush(sync_msg_type_t type); + +void sync_slave_handle_tx_trigger(void); + +#if SYNC_SUPPORT_POWER_CONTROL +void sync_power_ctrl_init(void); +void sync_power_ctrl_start(void); +void sync_power_ctrl_stop(void); +#endif + +#define sync_set_header(ack_tmp, seq_tmp) \ + do { \ + sync_header_t header = {0}; \ + header.ack = ack_tmp; \ + header.seq = seq_tmp; \ + PRO_HP_0_TYPE hp = {0}; \ + hp.hp_0_7_0 = header.value; \ + WR_PPT_REG(PRO_HP_0 + PRO_ENTRY_FIELD_BASE(0), hp.d16); \ + } while (0) + +#if SYNC_SUPPORT_MT1R +#define sync_master_set_header(ack_tmp, seq_tmp, req_ack_tmp) \ + do { \ + sync_header_t header = {0}; \ + header.m.ack = ack_tmp; \ + header.m.seq = seq_tmp; \ + header.m.req_ack = req_ack_tmp; \ + PRO_HP_0_TYPE hp = {0}; \ + hp.hp_0_7_0 = header.value; \ + WR_PPT_REG(PRO_HP_0 + PRO_ENTRY_FIELD_BASE(0), hp.d16); \ + } while (0) +#define sync_slave_set_header(ack_tmp, seq_tmp) \ + do { \ + sync_header_t header = {0}; \ + header.s.ack = ack_tmp; \ + header.s.seq = seq_tmp; \ + header.s.rfu = 0; \ + PRO_HP_0_TYPE hp = {0}; \ + hp.hp_0_7_0 = header.value; \ + WR_PPT_REG(PRO_HP_0 + PRO_ENTRY_FIELD_BASE(0), hp.d16); \ + } while (0) +void sync_ppt_set_rf_time_mt1r(void); +#endif + +uint32_t sync_rand(void); + +#include "os_timer.h" +#define os_timer_pendcall(func, para1, para2, wait) os_timer_pend_function_call(func, para1, para2) +/** @} End of PPT_SYNC_Driver_Exported_Functions */ + +/** @} End of PPT_SYNC_Driver */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/bee/drivers/ppt/sync/src/ppt_sync_master.c b/bee/drivers/ppt/sync/src/ppt_sync_master.c new file mode 100644 index 00000000..6c134820 --- /dev/null +++ b/bee/drivers/ppt/sync/src/ppt_sync_master.c @@ -0,0 +1,2886 @@ +/** +***************************************************************************************** +* Copyright(c) 2020, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file ppt_sync_master.c + * @brief Source file for sync protocol. + * @details + * @author bill + * @date 2022-03-15 + * @version v0.1 + * ************************************************************************************* + */ + +/* Add Includes here */ +#include +#include "ppt_simple.h" +#include "ppt_sync_int.h" +#include "ppt_sync_master.h" +#include "os_sync.h" +#include "os_timer.h" +//#include "trace.h" + +LOG_MODULE_REGISTER(ppt_sync_master, PPT_SYNC_LOG_LEVEL); + +#define SYNC_MASTER_PAIR_TIMES (SYNC_PAIR_PERIOD/SYNC_PAIR_SPEED) +#define SYNC_MASTER_PAIR_CFM_TIMES (SYNC_PAIR_CFM_PERIOD/SYNC_SYNC_SPEED) +#define SYNC_MASTER_SYNC_SLOW_TIMES (SYNC_SYNC_SLOW_PERIOD/SYNC_SYNC_SLOW_SPEED) +#define SYNC_MASTER_SYNC_LOST_TIMES (SYNC_SYNC_LOST_PERIOD/SYNC_SYNC_SPEED) +#define SYNC_MASTER_SYNC_FAST_TIMES (SYNC_SYNC_FAST_PERIOD/SYNC_SYNC_FAST_SPEED) +#define SYNC_MASTER_HB_SLEEP_MIN_PERIOD 3000 // us +#define SYNC_MASTER_HB_SLEEP_MIN_PERIOD_MT1R 10000 // us +#define SYNC_MASTER_HB_SLEEP_OH 1500 // us + +#define SYNC_MASTER_TIME_DEBUG_TX -1 +#define SYNC_MASTER_TIME_DEBUG_ACK -2 +#define SYNC_MASTER_TIME_DEBUG_NACK -2 +#define SYNC_MASTER_TIME_DEBUG_CB -1 +#define SYNC_MASTER_TIME_DEBUG_SEQ_ACK -3 + +typedef enum +{ + SYNC_MASTER_PAIR_PHASE_SEND_REQ, + SYNC_MASTER_PAIR_PHASE_SEND_CFM +} sync_master_pair_phase_t; + +typedef enum +{ + SYNC_MASTER_HB_STATE_IDLE, + SYNC_MASTER_HB_STATE_EMPTY_SEND, + SYNC_MASTER_HB_STATE_HB_SEND +} sync_master_hb_state_t; + +typedef struct +{ + uint32_t speed; // us + uint32_t period; // counter +} sync_master_hb_rhy_t; + +sync_master_hb_rhy_t sync_master_hb_rhy[] = +{ + {0, 20}, //SYNC_SYNC_SPEED + {8000, 10}, + {30000, SYNC_MASTER_HB_RHY_PERIOD_MAX} +}; +#define SYNC_MASTER_HB_RHY_NUMBER (sizeof(sync_master_hb_rhy)/sizeof(sync_master_hb_rhy_t)) + +#define SYNC_MASTER_MSG_SENDING_NUM 3 + +typedef struct +{ + sync_msg_t *pmsg; + uint8_t tx_count; + bool flush; +} sync_master_msg_sending_info_t; + +typedef struct +{ + sync_master_msg_sending_info_t info[SYNC_MASTER_MSG_SENDING_NUM]; + volatile uint8_t head; + volatile uint8_t tail; +} sync_master_msg_sending_list_t; + +struct +{ + sync_state_t state; + sync_pair_state_t pair_state; + uint8_t phase; + uint16_t count; + uint16_t count1; + sync_acc_t acc_data; + bool ack; + uint8_t seq_tx; + uint8_t seq_rx; + uint32_t crc_rx; + struct + { + uint16_t interval; + sync_master_hb_state_t state; + bool slow; + uint8_t rhy_idx; + bool rhy_changing; + uint8_t rhy_changing_idx; + uint32_t rhy_counter; + uint32_t time_left; + uint32_t sleep_clk; + uint8_t unack_count; + uint8_t rhy_idx_old; +#if SYNC_SUPPORT_MT1R + uint32_t time_left1; + uint32_t speed; + uint16_t ce_cnt; + uint64_t sleep_time; + bool sleep; + bool sleep_mac; + bool sleep_cal; + bool oversleep; +#endif + } hb; + volatile bool busy; //!< tx or rx ongoing + bool rx; + uint8_t tx_ptr; + uint8_t tx_ptr_hw; + bool tx_null; + bool tx_old; + uint8_t tx_fail_count; + volatile bool handling_ack; + sync_master_msg_sending_list_t msg_sending_list; + sync_msg_t *volatile pmsg_pend_free; + bool tx_align; + volatile uint32_t curr_time_in_ce; //!< us + bool new_event; //!< use a flag to indicate new while the curr_time_in_ce is changing +#if SYNC_SUPPORT_MT1R + struct + { + bool enable; + uint16_t ce_cnt; + uint8_t count; + uint8_t tx_count; + sync_msg_t *msg_txed[7]; + uint8_t msg_ack; + bool skip; + bool req_ack; + uint8_t seq_ack; + uint32_t ce_clk; + } quick; + uint8_t tx_fifo_bitmap; +#endif +} sync_master_ctx; + +struct +{ + sync_master_tx_scheme_t tx_scheme; + bool tx_align_enable; + bool early_high_prio_enable; + bool retrans_at_ack_enable; + bool tx_new_at_retrans_int_enable; + sync_tx_prepare_cb_t tx_prepare_cb; +} sync_master_param; + +#define sync_master_last_tx_is_valid() (sync_master_ctx.tx_null == false && sync_master_ctx.tx_old == false) +#define sync_master_tx_fifo_is_empty(entry) (ppt_get_tx_fifo_rdptr(entry) == ppt_get_tx_fifo_wrptr(entry)) + +void sync_master_start_sync_timer(void); +static void sync_master_ppt_isr_handler(void); + +static void sync_master_init_tx_fifo(void) +{ + ppt_set_tx_fifo_rdptr(0, PPT_TX_FIFO_SIZE - 1); + ppt_force_fw_ack(0); + sync_master_ctx.tx_ptr = ppt_flush_tx_fifo(0); +} + +static void sync_master_close(void) +{ + ppt_reset_hw_fsm(); + sync_master_ctx.tx_ptr = ppt_force_fw_ack(0); +} + +void sync_master_msg_flush(sync_msg_type_t type) +{ + uint8_t head = sync_master_ctx.msg_sending_list.head; + uint8_t tail = sync_master_ctx.msg_sending_list.tail; + while (head != tail) + { + sync_msg_t *pmsg = sync_master_ctx.msg_sending_list.info[head].pmsg; + if (pmsg) + { + if (type == SYNC_MSG_TYPE_ALL || type == pmsg->type) + { + sync_master_ctx.msg_sending_list.info[head].flush = true; + } + } + head = (head + 1) % SYNC_MASTER_MSG_SENDING_NUM; + } +} + +static void sync_master_msg_sending_free(void) +{ +#if SYNC_SUPPORT_MT1R + if (sync_ctx.mt1r.flag) + { + for (uint8_t loop = 0; loop < 7; loop++) + { + sync_msg_t *pmsg = sync_master_ctx.quick.msg_txed[loop]; + if (pmsg == NULL) + { + continue; + } + sync_master_ctx.quick.msg_txed[loop] = NULL; + if (pmsg->send_cb) + { + pmsg->send_info.res = SYNC_SEND_RESULT_UNKNOWN; + sync_pendcall(sync_msg_handle_tx_done, pmsg, 0); + } + else + { + sync_ctx.msg_count[pmsg->type] -= 1; + plt_list_push(&sync_ctx.msg_free, pmsg); + } + } + } +#endif + uint8_t head = sync_master_ctx.msg_sending_list.head; + uint8_t tail = sync_master_ctx.msg_sending_list.tail; + while (head != tail) + { + sync_msg_t *pmsg = sync_master_ctx.msg_sending_list.info[head].pmsg; + if (pmsg) + { + if (pmsg->send_cb) + { + pmsg->send_info.res = SYNC_SEND_RESULT_UNKNOWN; + sync_pendcall(sync_msg_handle_tx_done, pmsg, 0); + } + else + { + sync_ctx.msg_count[pmsg->type] -= 1; + plt_list_push(&sync_ctx.msg_free, pmsg); + } + } + head = (head + 1) % SYNC_MASTER_MSG_SENDING_NUM; + } + sync_master_ctx.msg_sending_list.head = 0; + sync_master_ctx.msg_sending_list.tail = 0; + + /* free the pend msg at the early handler */ + if (sync_master_ctx.pmsg_pend_free) + { + sync_pendcall(sync_msg_handle_tx_done, sync_master_ctx.pmsg_pend_free, 0); + sync_master_ctx.pmsg_pend_free = NULL; + } +} + +PPT_API_SECTION bool sync_master_msg_sending_is_full(void) +{ + uint8_t head = sync_master_ctx.msg_sending_list.head; + uint8_t tail = sync_master_ctx.msg_sending_list.tail; + uint8_t tail_next = (tail + 1) % SYNC_MASTER_MSG_SENDING_NUM; + return tail_next == head; +} + +PPT_API_SECTION bool sync_master_msg_sending_is_empty(void) +{ + uint8_t head = sync_master_ctx.msg_sending_list.head; + uint8_t tail = sync_master_ctx.msg_sending_list.tail; + return head == tail; +} + +PPT_API_SECTION uint8_t sync_master_msg_sending_get_num(void) +{ + uint8_t head = sync_master_ctx.msg_sending_list.head; + uint8_t tail = sync_master_ctx.msg_sending_list.tail; + return tail >= head ? tail - head : tail + SYNC_MASTER_MSG_SENDING_NUM - head; +} + +PPT_API_SECTION uint8_t sync_master_msg_sending_get_data_num(void) +{ + uint8_t head = sync_master_ctx.msg_sending_list.head; + uint8_t tail = sync_master_ctx.msg_sending_list.tail; + uint8_t count = 0; + while (head != tail) + { + if (sync_master_ctx.msg_sending_list.info[head].pmsg) + { + count += 1; + } + head = (head + 1) % SYNC_MASTER_MSG_SENDING_NUM; + } + + return count; +} + +PPT_API_SECTION bool sync_master_msg_sending_push(sync_msg_t *pmsg) +{ + uint8_t head = sync_master_ctx.msg_sending_list.head; + uint8_t tail = sync_master_ctx.msg_sending_list.tail; + uint8_t tail_next = (tail + 1) % SYNC_MASTER_MSG_SENDING_NUM; + if (tail_next == head) + { + APP_PRINT_WARN0("sync: fail push, sending fifo is full"); + return false; + } + memset(&sync_master_ctx.msg_sending_list.info[tail], 0, sizeof(sync_master_msg_sending_info_t)); + sync_master_ctx.msg_sending_list.info[tail].pmsg = pmsg; + sync_master_ctx.msg_sending_list.tail = tail_next; + return true; +} + +PPT_API_SECTION sync_master_msg_sending_info_t *sync_master_msg_sending_peak(void) +{ + uint8_t head = sync_master_ctx.msg_sending_list.head; + uint8_t tail = sync_master_ctx.msg_sending_list.tail; + if (head == tail) + { + return NULL; + } + + return &sync_master_ctx.msg_sending_list.info[head]; +} + +PPT_API_SECTION sync_master_msg_sending_info_t *sync_master_msg_sending_pop(void) +{ + sync_master_msg_sending_info_t *ret = NULL; + uint8_t head = sync_master_ctx.msg_sending_list.head; + uint8_t tail = sync_master_ctx.msg_sending_list.tail; + if (head == tail) + { + APP_PRINT_WARN0("sync: fail pop, sending fifo is empty"); + return ret; + } + ret = &sync_master_ctx.msg_sending_list.info[head]; + sync_master_ctx.msg_sending_list.head = (head + 1) % SYNC_MASTER_MSG_SENDING_NUM; + return ret; +} + +static void sync_master_handle_pair_to(void *para1, uint32_t para2) +{ + if (sync_ctx.event_cb) + { + sync_ctx.event_cb(SYNC_EVENT_PAIR_TIMEOUT); + } +} + +static void sync_master_handle_paired(void *para1, uint32_t para2) +{ + sync_bond_info_t bond_info; + bond_info.acc = sync_master_ctx.acc_data; + sync_nvm_set_bond_info(&bond_info); + + if (sync_ctx.event_cb) + { + sync_ctx.event_cb(SYNC_EVENT_PAIRED); + } + if (sync_ctx.event_cb) + { + sync_ctx.event_cb(SYNC_EVENT_CONNECTED); + } +} + +static void sync_master_handle_connect_to(void *para1, uint32_t para2) +{ + if (sync_ctx.event_cb) + { + sync_ctx.event_cb(SYNC_EVENT_CONNECT_TIMEOUT); + } +} + +static void sync_master_handle_connected(void *para1, uint32_t para2) +{ + if (sync_ctx.event_cb) + { + sync_ctx.event_cb(SYNC_EVENT_CONNECTED); + } +} + +static void sync_master_handle_disconnected(void *para1, uint32_t para2) +{ + if (sync_ctx.event_cb) + { + sync_ctx.event_cb(SYNC_EVENT_CONNECT_LOST); + } +} + +#ifdef SYNC_DEBUG +static void sync_master_handle_sync_lost(void *para1, uint32_t para2) +{ + if (sync_ctx.event_cb) + { + sync_ctx.event_cb(SYNC_EVENT_SYNC_LOST); + } +} + +static void sync_master_handle_sync_reconnected(void *para1, uint32_t para2) +{ + if (sync_ctx.event_cb) + { + sync_ctx.event_cb(SYNC_EVENT_SYNC_RECONNECTED); + } +} +#endif + +static void sync_master_handle_exception(void) +{ + sync_master_stop(); + sync_pendcall(sync_master_handle_disconnected, 0, 0); +} + +PPT_ISR_SECTION void sync_master_handle_hb_to(void) +{ + if (sync_master_hb_rhy[sync_master_ctx.hb.rhy_idx].period != SYNC_MASTER_HB_RHY_PERIOD_MAX + && sync_master_ctx.hb.rhy_changing == false) + { + sync_master_ctx.hb.rhy_counter += 1; + if (sync_master_ctx.hb.rhy_counter >= sync_master_hb_rhy[sync_master_ctx.hb.rhy_idx].period) + { + sync_master_ctx.hb.rhy_changing_idx = sync_master_ctx.hb.rhy_idx; + sync_master_ctx.hb.rhy_idx += 1; + sync_master_ctx.hb.rhy_changing = true; + APP_PRINT_INFO1("sync: hb changing %dus", sync_master_hb_rhy[sync_master_ctx.hb.rhy_idx].speed); + } + } + + sync_set_header(true, sync_master_ctx.seq_tx); + sync_pdu_t pdu; + pdu.opcode = SYNC_OPCODE_HEARTBEAT; + pdu.heartbeat.interval = sync_master_hb_rhy[sync_master_ctx.hb.rhy_idx].speed / 1000; + ppt_push_tx_data(sizeof(sync_opcode_t) + sizeof(sync_heartbeat_t), (uint8_t *)&pdu); + sync_master_msg_sending_push(NULL); + sync_master_ctx.busy = true; + ppt_execute_instruction(PPT_HW_INSTRUCTION_PTX_ENABLE); +} + +PPT_ISR_SECTION void sync_master_hb_exit(bool real) +{ + if (sync_master_ctx.hb.slow) + { + sync_master_ctx.hb.slow = false; + APP_PRINT_INFO0("sync: hb exit"); + if (sync_ctx.hb_cb) + { + sync_hb_cb_param_t param = {}; + param.enter = false; + sync_ctx.hb_cb(¶m); + } +#if SYNC_SUPPORT_MT1R + if (sync_master_ctx.quick.enable) + { + if (sync_ctx.rte_req_cb) + { + sync_ctx.rte_req_cb(true); + } + } + else +#endif + { + sync_master_ctx.curr_time_in_ce = 0; + sync_master_start_sync_timer(); + if (SYNC_SYNC_SPEED_HIGH <= SYNC_SYNC_SPEED_HIGH_MIN) + { + if (sync_ctx.rte_req_cb) + { + sync_ctx.rte_req_cb(true); + } + } + } + } + sync_master_ctx.hb.rhy_idx_old = real ? 0 : sync_master_ctx.hb.rhy_idx; + sync_master_ctx.hb.state = SYNC_MASTER_HB_STATE_IDLE; + sync_master_ctx.hb.rhy_changing = false; + sync_master_ctx.hb.rhy_idx = 0; + sync_master_ctx.hb.rhy_counter = 0; + sync_master_ctx.hb.unack_count = 0; +} +#include "rtl_pinmux.h" +PPT_ISR_SECTION void sync_master_push_data(void) +{ + uint32_t lock = sync_enter_critical(); + time_debug_level_high(TIME_DEBUG_CHAN_THREAD); + time_debug_level_low(TIME_DEBUG_CHAN_THREAD); + if (sync_master_msg_sending_is_full()) + { + sync_exit_critical(lock); + return; + } + sync_msg_t *pmsg = NULL; + if (sync_ctx.msg_send.count == 0 +#if SYNC_SUPPORT_MT1R + || sync_master_ctx.quick.req_ack +#endif + ) + { + sync_master_ctx.hb.state = SYNC_MASTER_HB_STATE_EMPTY_SEND; + sync_pdu_t pdu; + pdu.opcode = SYNC_OPCODE_EMPTY; + ppt_push_tx_data(sizeof(sync_opcode_t), (uint8_t *)&pdu); + } + else + { + /* clear hb state & counter in case of tx empty ahead of this */ + sync_master_ctx.hb.state = SYNC_MASTER_HB_STATE_IDLE; + sync_master_ctx.hb.rhy_counter = 0; + pmsg = (sync_msg_t *)plt_list_pop(&sync_ctx.msg_send); + Pad_Config(P3_0, PAD_SW_MODE, PAD_IS_PWRON, PAD_PULL_DOWN, PAD_OUT_ENABLE, + PAD_OUT_LOW); + Pad_Config(P3_0, PAD_SW_MODE, PAD_IS_PWRON, PAD_PULL_DOWN, PAD_OUT_ENABLE, + PAD_OUT_HIGH); + ppt_push_tx_fifo(0, pmsg->data, pmsg->len); + Pad_Config(P3_0, PAD_SW_MODE, PAD_IS_PWRON, PAD_PULL_DOWN, PAD_OUT_ENABLE, + PAD_OUT_LOW); + } + sync_master_msg_sending_push(pmsg); + + /* update at last in case of tx fail */ +#if SYNC_SUPPORT_MT1R + if (sync_master_ctx.quick.enable) + { + sync_master_set_header(sync_master_ctx.quick.seq_ack, sync_master_ctx.seq_tx, + sync_master_ctx.quick.req_ack); + } + else +#endif + { + sync_set_header(sync_master_ctx.rx, sync_master_ctx.seq_tx); + } + time_debug_level_high(TIME_DEBUG_CHAN_THREAD); + time_debug_level_low(TIME_DEBUG_CHAN_THREAD); + sync_exit_critical(lock); +} + +PPT_API_SECTION static void sync_master_tx_restart(void) +{ + sync_master_push_data(); + sync_master_ctx.busy = true; + ppt_execute_instruction(PPT_HW_INSTRUCTION_PTX_ENABLE); + sync_master_ctx.curr_time_in_ce = 0; + sync_master_start_sync_timer(); +} + +PPT_ISR_SECTION void sync_master_handle_tx_trigger(void) +{ + if (sync_master_ctx.pair_state != SYNC_PAIR_STATE_PAIRED + || sync_master_ctx.state != SYNC_STATE_SYNC) + { + return; + } + +#if SYNC_SUPPORT_MT1R + if (sync_master_ctx.quick.enable) + { + if (sync_master_ctx.busy == false) + { + if (sync_master_ctx.hb.slow) + { + void sync_master_hb_sleep_resume(void); + sync_master_hb_sleep_resume(); + sync_master_push_data(); + sync_master_hb_exit(true); + } + } + } + else +#endif + { + if (sync_master_ctx.busy == false) + { + if (sync_master_ctx.hb.slow) + { + /* quit hb to send msg */ + sync_master_push_data(); + sync_master_ctx.busy = true; + ppt_execute_instruction(PPT_HW_INSTRUCTION_PTX_ENABLE); + sync_master_hb_exit(true); + APP_PRINT_INFO0("sync: hb exit by tx trigger"); + return; + } + + if (sync_master_param.tx_align_enable) + { + /* in case of retrans ongoing */ + if (sync_master_msg_sending_get_num() == 0) + { + sync_master_tx_restart(); + } + } + } + else + { + if (sync_master_param.tx_align_enable) + { + if (sync_master_msg_sending_get_data_num() == 0) + { + sync_master_ctx.tx_align = true; + } + } + } + } +} + +PPT_ISR_SECTION void sync_master_handle_ack(bool rx, sync_header_t rx_header) +{ + bool enter_critical = false; + uint32_t lock = 0; + /* update ack field first in case tx fail next time */ + sync_set_header(rx, sync_master_ctx.seq_tx); + /* rx ack handling */ + sync_master_ctx.rx = rx; + + if (sync_master_ctx.tx_null) + { + /* empty msg send since no data pushed timely */ + uint8_t seg_vld = RD_U32_BZDMA_REG(BZDMA_REG_BLEONLY_ENTRY_SEGMENT_VALID(0)); + if (sync_master_ctx.tx_fail_count >= 3)//seg_vld == 0 || + { + APP_PRINT_WARN2("sync: fail, tx null ptr %d data 0x%02x, stop here", + sync_master_ctx.tx_ptr_hw, seg_vld); + sync_master_handle_exception(); + return; + } + else + { + /* the null pkt may exhaust one seq, so use new to make sure of normal pkt being handled */ + sync_master_ctx.seq_tx += 1; + sync_set_header(rx, sync_master_ctx.seq_tx); + } + } + else if (sync_master_ctx.tx_old) + { + /* this msg should have already been handled before, so no need handle again */ + uint8_t seg_vld = RD_U32_BZDMA_REG(BZDMA_REG_BLEONLY_ENTRY_SEGMENT_VALID(0)); + /* next pkt may be late */ + //if(seg_vld | (~(1 << sync_master_ctx.tx_ptr_hw))) + /* tx_ptr_hw maybe wrong */ + //if(seg_vld & (1 << sync_master_ctx.tx_ptr_hw)) + if (sync_master_ctx.tx_fail_count >= 3) + { + APP_PRINT_WARN2("sync: fail, tx %d old due to valid data 0x%02x, stop here", + sync_master_ctx.tx_ptr_hw, seg_vld); + sync_master_handle_exception(); + return; + } + } + else + { + bool retrans = false; + sync_master_msg_sending_info_t *pmsg_info = sync_master_msg_sending_peak(); + sync_msg_t *pmsg = pmsg_info ? pmsg_info->pmsg : NULL; + if (pmsg_info && pmsg_info->flush) + { + + } + else if (pmsg && (rx == false || rx_header.ack == false)) + { + switch (pmsg->type) + { + case SYNC_MSG_TYPE_FINITE_RETRANS: + if (sync_ctx.msg_retrans_count < sync_ctx.msg_finite_retrans_num) + { + retrans = true; + } + break; + case SYNC_MSG_TYPE_INFINITE_RETRANS: + retrans = true; + break; + case SYNC_MSG_TYPE_DYNAMIC_RETRANS: + if (sync_ctx.msg_retrans_count < sync_ctx.msg_dynamic_retrans_num_lower || + (sync_ctx.msg_send.count == 0 && + (sync_ctx.msg_dynamic_retrans_num_upper == SYNC_MSG_RETRANS_NUM_INFINITE || + sync_ctx.msg_retrans_count < sync_ctx.msg_dynamic_retrans_num_upper))) + { + retrans = true; + } + break; + default: + break; + } + } + + if (retrans) + { + sync_ctx.msg_retrans_count += 1; + /* header already updated above */ + } + else + { + sync_master_ctx.tx_ptr = ppt_trigger_fw_ack(0); + sync_master_ctx.seq_tx += 1; + sync_master_msg_sending_pop(); + if (pmsg) + { + if (pmsg->send_cb) + { + pmsg->send_info.res = rx ? (rx_header.ack ? SYNC_SEND_RESULT_ACKED : SYNC_SEND_RESULT_NACKED) : + SYNC_SEND_RESULT_UNKNOWN; + pmsg->send_info.retrans_count = sync_ctx.msg_retrans_count; + sync_pendcall(sync_msg_handle_tx_done, pmsg, 0); + } + else + { + sync_ctx.msg_count[pmsg->type] -= 1; + plt_list_push(&sync_ctx.msg_free, pmsg); + } + } + sync_ctx.msg_retrans_count = 0; + } + } + + if (sync_master_param.retrans_at_ack_enable) + { + if (sync_master_tx_fifo_is_empty(0) == false) + { + if (enter_critical == false) + { + lock = sync_enter_critical(); + enter_critical = true; + time_debug_level_low(TIME_DEBUG_CHAN_ISR); + time_debug_level_high(TIME_DEBUG_CHAN_ISR); + } + if (sync_master_ctx.busy == false) + { + /* re-trigger right now */ + sync_master_ctx.busy = true; + ppt_execute_instruction(PPT_HW_INSTRUCTION_PTX_ENABLE); + /* mark as retransmit tx */ + sync_master_ctx.curr_time_in_ce += 1; + sync_master_ctx.new_event = false; + } + } + } + + if (sync_master_param.early_high_prio_enable) + { + if (sync_master_tx_fifo_is_empty(0)) + { + if (enter_critical == false) + { + lock = sync_enter_critical(); + enter_critical = true; + time_debug_level_low(TIME_DEBUG_CHAN_ISR); + time_debug_level_high(TIME_DEBUG_CHAN_ISR); + } + + if (sync_master_ctx.busy) + { + if (sync_master_ctx.curr_time_in_ce != 0) + { + if (sync_master_param.tx_new_at_retrans_int_enable && sync_ctx.msg_send.count != 0) + { + sync_master_push_data(); + } + else + { + /* cancel before rx handler */ + ppt_execute_instruction(PPT_HW_INSTRUCTION_PTX_DISABLE); + sync_master_ctx.busy = false; + } + } + else + { + sync_master_push_data(); + } + } + } + } + + if (sync_master_param.tx_align_enable && sync_master_ctx.tx_align) + { + sync_master_ctx.tx_align = false; + if (sync_master_tx_fifo_is_empty(0)) + { + if (enter_critical == false) + { + lock = sync_enter_critical(); + enter_critical = true; + time_debug_level_low(TIME_DEBUG_CHAN_ISR); + time_debug_level_high(TIME_DEBUG_CHAN_ISR); + } + if (sync_master_ctx.busy == false) + { + sync_master_tx_restart(); + } + } + } + + /* update header in case tx at early */ + sync_set_header(rx, sync_master_ctx.seq_tx); + time_debug_level_low(TIME_DEBUG_CHAN_ISR); + time_debug_level_high(TIME_DEBUG_CHAN_ISR); + sync_master_ctx.handling_ack = false; + if (enter_critical) + { + sync_exit_critical(lock); + } +#if SYNC_SUPPORT_POWER_CONTROL + if (sync_ctx.tx_power_adaptive) + { + sync_ctx.power_ctrl_count_fail += !(rx && rx_header.ack); + } +#endif +} + +PPT_ISR_SECTION void sync_master_handle_rx(bool rx, sync_header_t rx_header, sync_pdu_t *rx_pdu, + uint16_t rx_len, uint16_t rssi, uint32_t rx_crc) +{ + uint32_t lock = sync_enter_critical(); + time_debug_level_low(TIME_DEBUG_CHAN_ISR); + if (sync_master_tx_fifo_is_empty(0)) + { + /* hb handling */ + bool rx_empty = false; + bool rx_ack = false; + if (rx) + { + if (rx_len == sizeof(sync_opcode_t) && rx_pdu->opcode == SYNC_OPCODE_EMPTY) + { + rx_empty = true; + } + if (rx_header.ack) + { + rx_ack = true; + } + } + //APP_PRINT_INFO4("sync: hb rhy idx %d counter %d, state %d, rx emtpy %d", + // sync_master_ctx.hb.rhy_idx, + // sync_master_ctx.hb.rhy_counter, sync_master_ctx.hb.state, rx_empty); + if (SYNC_MASTER_HB_RHY_NUMBER <= 1 || sync_master_ctx.hb.state == SYNC_MASTER_HB_STATE_IDLE) + { + + } + else if (sync_master_ctx.hb.state == SYNC_MASTER_HB_STATE_EMPTY_SEND) + { + bool tx_hb = false; + /* tx pend message */ + if (sync_ctx.msg_send.count != 0) + { + sync_master_hb_exit(true); + } + else if (rx_empty && rx_ack) + { + if (sync_master_hb_rhy[0].period != SYNC_MASTER_HB_RHY_PERIOD_MAX) + { + if (sync_master_ctx.hb.rhy_idx_old != 0) + { + tx_hb = true; + sync_master_ctx.hb.rhy_idx = sync_master_ctx.hb.rhy_idx_old; + sync_master_ctx.hb.rhy_changing = true; + sync_master_ctx.hb.rhy_changing_idx = 0; + } + else + { + sync_master_ctx.hb.rhy_counter += 1; + if (sync_master_ctx.hb.rhy_counter >= sync_master_hb_rhy[0].period) + { + tx_hb = true; + sync_master_ctx.hb.rhy_idx = 1; + sync_master_ctx.hb.rhy_changing = true; + sync_master_ctx.hb.rhy_changing_idx = 0; + } + } + } + } + else + { + /* ignore if be disturbed */ + if (sync_master_ctx.rx) + { + sync_master_ctx.hb.rhy_counter = 0; + } + } + if (sync_master_ctx.hb.rhy_changing) + { + uint32_t speed = sync_master_ctx.hb.rhy_changing_idx == 0 ? SYNC_SYNC_SPEED : + sync_master_hb_rhy[sync_master_ctx.hb.rhy_changing_idx].speed; + sync_hw_timer_start(speed, sync_master_handle_hb_to); + if (sync_master_param.early_high_prio_enable) + { + /* cancel if already triggered */ + if (sync_master_ctx.busy) + { + ppt_kill_hw_fsm(PPT_FSM_PTX); + sync_master_ctx.busy = false; + } + } + sync_master_ctx.hb.state = SYNC_MASTER_HB_STATE_HB_SEND; + sync_master_ctx.hb.slow = true; + APP_PRINT_INFO1("sync: hb changing %dus", sync_master_hb_rhy[sync_master_ctx.hb.rhy_idx].speed); + } + } + else if (sync_master_ctx.hb.state == SYNC_MASTER_HB_STATE_HB_SEND) + { + bool hb_enter = false; + bool hb_continue = false; + /* tx pend message */ + if (sync_ctx.msg_send.count != 0) + { + sync_master_hb_exit(true); + } + /* rx empty ack message */ + else if (rx_ack && rx_empty) + { + sync_master_ctx.hb.unack_count = 0; + hb_enter = true; + } + else + { + /* rx non-empty message */ + if (sync_master_ctx.rx && rx_empty == false) + { + sync_master_hb_exit(true); + } + /* no rx or rx non-ack */ + else if (rx_ack == false) + { + /* skip wakeup only when already in the hb state */ + if (sync_master_ctx.hb.slow) + { + sync_master_ctx.hb.unack_count += 1; + if (sync_master_ctx.hb.unack_count >= SYNC_HB_TO_TIMES) + { + sync_master_hb_exit(false); + } + else + { + hb_continue = true; + sync_master_ctx.hb.rhy_counter -= 1; + } + } + } + } + + if (hb_enter || hb_continue) + { + if (hb_enter && sync_master_ctx.hb.rhy_changing) + { + sync_master_ctx.hb.rhy_changing = false; + sync_master_ctx.hb.rhy_counter = 0; + APP_PRINT_INFO1("sync: hb enter %dus", + sync_master_hb_rhy[sync_master_ctx.hb.rhy_idx].speed); + if (sync_ctx.hb_cb) + { + sync_hb_cb_param_t param = {}; + param.enter = true; + param.interval = sync_master_hb_rhy[sync_master_ctx.hb.rhy_idx].speed; + sync_ctx.hb_cb(¶m); + } + } + uint32_t speed = 0; + if (sync_master_ctx.hb.rhy_changing) + { + speed = sync_master_ctx.hb.rhy_changing_idx == 0 ? SYNC_SYNC_SPEED : + sync_master_hb_rhy[sync_master_ctx.hb.rhy_changing_idx].speed; + } + else + { + speed = sync_master_hb_rhy[sync_master_ctx.hb.rhy_idx].speed; + } + sync_hw_timer_start(speed, sync_master_handle_hb_to); + sync_master_ctx.hb.slow = true; + if (speed > SYNC_SYNC_SPEED) + { + if (sync_ctx.rte_req_cb) + { + sync_ctx.rte_req_cb(false); + } + } + } + } + } + time_debug_level_high(TIME_DEBUG_CHAN_ISR); + sync_exit_critical(lock); + + if (rx) + { + if (rx_header.seq != sync_master_ctx.seq_rx)// || rx_crc != sync_master_ctx.crc_rx + { + sync_master_ctx.seq_rx = rx_header.seq; + sync_master_ctx.crc_rx = rx_crc; + if (rx_len > 0) + { + if (rx_pdu->opcode >= SYNC_OPCODE_APP_START) + { + if (sync_ctx.msg_receive_cb) + { + sync_receive_info_t info = {}; + info.rssi = ppt_get_rssi(rssi); + sync_ctx.msg_receive_cb((uint8_t *)rx_pdu, rx_len, &info); + } + } + else + { + bool handle = false; + switch (rx_pdu->opcode) + { + case SYNC_OPCODE_EMPTY: + if (rx_len == 1) + { + handle = true; + } + break; + default: + break; + } + if (handle == false) + { + APP_PRINT_WARN3("sync: rx unknown opcode %d, len %d, data %b", rx_pdu->opcode, rx_len, + TRACE_BINARY(rx_len, rx_pdu)); + } + } + } + } + } +} + +PPT_ISR_SECTION void sync_master_handle_sync_fast_early(void) +{ + sync_hw_timer_start(SYNC_SYNC_FAST_SPEED, sync_master_handle_sync_fast_early); + if (sync_master_ctx.busy) + { + return; + } + sync_master_ctx.busy = true; + ppt_execute_instruction(PPT_HW_INSTRUCTION_PTX_ENABLE); +} + +PPT_ISR_SECTION void sync_master_handle_sync_slow_early(void) +{ + uint32_t speed = sync_master_ctx.pair_state == SYNC_PAIR_STATE_PAIRED ? SYNC_SYNC_SLOW_SPEED : + sync_master_ctx.phase == SYNC_MASTER_PAIR_PHASE_SEND_CFM ? SYNC_SYNC_SPEED : SYNC_PAIR_SPEED; + sync_hw_timer_start(speed, sync_master_handle_sync_slow_early); + if (sync_master_ctx.busy) + { + return; + } + sync_master_ctx.busy = true; + ppt_execute_instruction(PPT_HW_INSTRUCTION_PTX_ENABLE); +} + +PPT_ISR_SECTION void sync_master_handle_sync_early(void) +{ + sync_master_ctx.curr_time_in_ce += SYNC_SYNC_SPEED_HIGH; + if (sync_master_ctx.busy) + { + APP_PRINT_WARN1("sync: busy at %d", sync_master_ctx.curr_time_in_ce); + return; + } + + if (sync_master_ctx.curr_time_in_ce >= SYNC_SYNC_SPEED) + { + sync_master_ctx.curr_time_in_ce = 0; + time_debug_level_low(TIME_DEBUG_CHAN_TIMING); + time_debug_level_high(TIME_DEBUG_CHAN_TIMING); + } + + /* tx if necessary */ + sync_master_msg_sending_info_t *pmsg_info = sync_master_msg_sending_peak(); + bool tx_new = sync_master_ctx.curr_time_in_ce == 0 + || (sync_master_param.tx_new_at_retrans_int_enable && sync_ctx.msg_send.count != 0); + if (tx_new || (false == sync_master_tx_fifo_is_empty(0) && pmsg_info && pmsg_info->pmsg && + pmsg_info->tx_count)) + { + sync_master_ctx.busy = true; + ppt_execute_instruction(PPT_HW_INSTRUCTION_PTX_ENABLE); + sync_master_ctx.new_event = sync_master_ctx.curr_time_in_ce == 0; + time_debug_level_low(TIME_DEBUG_CHAN_TIMING); + + if (sync_master_ctx.curr_time_in_ce == 0) + { + if (sync_master_param.early_high_prio_enable == false) + { + if (sync_master_param.tx_prepare_cb != NULL) + { + time_debug_level_high(TIME_DEBUG_CHAN_TIMING); + /* in case of calling tx trigger */ + sync_master_param.tx_prepare_cb(); + time_debug_level_low(TIME_DEBUG_CHAN_TIMING); + } + } + } + + if (tx_new) + { + if (sync_master_ctx.handling_ack == false) + { + /* quit dynamic msg if necessary */ + if (pmsg_info) + { + time_debug_level_high(TIME_DEBUG_CHAN_TIMING); + time_debug_level_low(TIME_DEBUG_CHAN_TIMING); + sync_msg_t *pmsg = pmsg_info->pmsg; + if (pmsg && pmsg->type == SYNC_MSG_TYPE_DYNAMIC_RETRANS + && sync_ctx.msg_retrans_count > sync_ctx.msg_dynamic_retrans_num_lower + && sync_ctx.msg_send.count != 0) + { + sync_master_ctx.tx_ptr = ppt_trigger_fw_ack(0); + sync_master_ctx.seq_tx += 1; + pmsg->send_info.retrans_count = sync_ctx.msg_retrans_count; + sync_master_msg_sending_pop(); + sync_master_push_data(); + if (pmsg->send_cb) + { + pmsg->send_info.res = SYNC_SEND_RESULT_UNKNOWN; + /* the early handler can't call os api when at high priority */ + if (sync_master_param.early_high_prio_enable) + { + if (sync_master_ctx.pmsg_pend_free) + { + APP_PRINT_ERROR0("sync: pmsg_pend_free error"); + while (1); + } + sync_master_ctx.pmsg_pend_free = pmsg; + } + else + { + sync_pendcall(sync_msg_handle_tx_done, pmsg, 0); + } + } + else + { + sync_ctx.msg_count[pmsg->type] -= 1; + plt_list_push(&sync_ctx.msg_free, pmsg); + } + } + } + else + { + if (sync_master_msg_sending_get_num() <= 1) + { + sync_master_push_data(); + } + } + } + } + + time_debug_level_high(TIME_DEBUG_CHAN_TIMING); + //APP_PRINT_TRACE1("sync: early curr_time_in_ce %d", sync_master_ctx.curr_time_in_ce); + } +} + +PPT_ISR_SECTION void sync_master_handle_sync_fast_to(void) +{ + sync_master_ctx.count += 1; + if ( +#if SYNC_SUPPORT_SYNC_FAST_DISABLE + SYNC_SYNC_FAST_PERIOD == SYNC_SYNC_FAST_PERIOD_DISABLE || +#endif + sync_master_ctx.count >= SYNC_MASTER_SYNC_FAST_TIMES) + { + sync_hw_timer_stop(); + sync_master_close(); + sync_master_msg_sending_free(); +#if SYNC_SUPPORT_POWER_CONTROL + if (sync_ctx.tx_power_adaptive) + { + sync_power_ctrl_stop(); + } +#endif +#if SYNC_SUPPORT_MT1R + ppt_reg_handler(sync_master_ppt_isr_handler); +#endif + sync_master_ctx.pair_state = SYNC_PAIR_STATE_IDLE; + sync_master_ctx.state = SYNC_STATE_IDLE; + APP_PRINT_INFO0("sync: disconnected!"); + sync_channel_print_statistic(); + sync_pendcall(sync_master_handle_disconnected, 0, 0); + if (sync_ctx.rte_req_cb) + { + sync_ctx.rte_req_cb(false); + } + } + else + { + sync_channel_change_next_in_group(); + if (sync_master_msg_sending_is_empty()) + { + sync_master_push_data(); + } + } +} + +PPT_ISR_SECTION void sync_master_handle_sync_lost_to(void) +{ + sync_header_t rx_header = {}; + sync_master_handle_rx(false, rx_header, NULL, 0, 0, 0); + + sync_ctx.chan_miss_count += 1; + if (sync_master_ctx.curr_time_in_ce == 0 || sync_master_ctx.new_event) + { + sync_master_ctx.count += 1; + } + if (sync_master_ctx.count >= SYNC_MASTER_SYNC_LOST_TIMES) + { + sync_hw_timer_stop(); + if (sync_master_param.early_high_prio_enable) + { + if (sync_master_ctx.busy) + { + ppt_kill_hw_fsm(PPT_FSM_PTX); + sync_master_ctx.busy = false; + } + } + APP_PRINT_INFO4("sync: lost at %d[%d], miss %d/%d!", sync_ctx.chan_cur, + sync_ctx.chan_cfg[sync_ctx.chan_cur].freq, + sync_ctx.chan_miss_count, sync_ctx.chan_used_count); +#ifdef SYNC_DEBUG + sync_pendcall(sync_master_handle_sync_lost, 0, 0); +#endif +#if SYNC_SUPPORT_SYNC_FAST_DISABLE + if (SYNC_SYNC_FAST_PERIOD == SYNC_SYNC_FAST_PERIOD_DISABLE) + { + sync_master_handle_sync_fast_to(); + } + else +#endif + { + sync_master_ctx.state = SYNC_STATE_SYNC_FAST; + sync_master_ctx.count = 0; + sync_channel_change_next_in_group(); + if (sync_master_msg_sending_is_empty()) + { + sync_master_push_data(); + } + sync_master_ctx.busy = true; + ppt_execute_instruction(PPT_HW_INSTRUCTION_PTX_ENABLE); + sync_hw_timer_start(SYNC_SYNC_FAST_SPEED, sync_master_handle_sync_fast_early); + } + } +} + +PPT_ISR_SECTION void sync_master_handle_sync_slow_to(void) +{ + sync_master_ctx.count += 1; + if (sync_master_ctx.count < SYNC_MASTER_SYNC_SLOW_TIMES) + { + sync_channel_change_next(); + } + else + { + sync_hw_timer_stop(); + sync_master_close(); + sync_master_ctx.pair_state = SYNC_PAIR_STATE_IDLE; + sync_master_ctx.state = SYNC_STATE_IDLE; + APP_PRINT_INFO0("sync: connect failed!"); + sync_pendcall(sync_master_handle_connect_to, 0, 0); + } +} + +PPT_ISR_SECTION void sync_master_handle_pair_req_to(void) +{ + sync_master_ctx.count += 1; + if (sync_master_ctx.count < SYNC_MASTER_PAIR_TIMES) + { + sync_channel_change_next(); + } + else + { + sync_hw_timer_stop(); + sync_master_close(); + sync_master_ctx.pair_state = SYNC_PAIR_STATE_IDLE; + sync_master_ctx.state = SYNC_STATE_IDLE; + APP_PRINT_INFO0("sync: pair failed!"); + sync_pendcall(sync_master_handle_pair_to, 0, 0); + } +} + +PPT_ISR_SECTION void sync_master_handle_pair_cfm_to(void) +{ + sync_master_ctx.count1 += 1; + if (sync_master_ctx.count1 >= SYNC_MASTER_PAIR_CFM_TIMES) + { + sync_master_ctx.phase = SYNC_MASTER_PAIR_PHASE_SEND_REQ; + APP_PRINT_ERROR0("sync: back to pair!"); + + sync_master_ctx.tx_ptr = ppt_trigger_fw_ack(0); + sync_ppt_set_tifs(true); + sync_hw_timer_start(SYNC_PAIR_SPEED, sync_master_handle_sync_slow_early); + sync_acc_t acc = {.addr = SYNC_ACC_ADDR_BR}; + sync_acc_set(acc); + + uint16_t interval = SYNC_SYNC_SPEED; +#if SYNC_SUPPORT_MT1R + if (sync_ctx.mt1r.flag) + { + interval = 125; + sync_ctx.conn_interval = 250; + } +#endif + sync_set_header(0, 0); + sync_pdu_t pdu; + pdu.opcode = SYNC_OPCODE_PAIR_REQ; + pdu.pair_req.interval = interval; + ppt_push_tx_data(sizeof(sync_opcode_t) + sizeof(sync_pair_req_t), (uint8_t *)&pdu); + + sync_master_handle_pair_req_to(); + } +} + +PPT_API_SECTION void sync_master_start_sync_timer(void) +{ + sync_hw_timer_start(SYNC_SYNC_SPEED_HIGH, sync_master_handle_sync_early); + sync_hw_timer_set_periodic(true); + if (sync_master_param.early_high_prio_enable) + { + sync_hw_timer_impr_ip(true); + } +} + +#if SYNC_SUPPORT_MT1R +PPT_ISR_SECTION void sync_master_pop_data(void) +{ + sync_master_ctx.tx_ptr = ppt_trigger_fw_ack(0); + sync_master_ctx.seq_tx += 1; + sync_master_msg_sending_info_t *pmsg_info = sync_master_msg_sending_pop(); + sync_msg_t *pmsg = pmsg_info ? pmsg_info->pmsg : NULL; + if (pmsg) + { + if (sync_master_ctx.quick.msg_txed[sync_master_ctx.quick.tx_count] != NULL) + { + APP_PRINT_ERROR2("sync: fail to free msg, slot %d, ptr 0x%0x", sync_master_ctx.quick.tx_count, + sync_master_ctx.quick.msg_txed[sync_master_ctx.quick.tx_count]); + sync_pendcall(sync_msg_handle_tx_done, + sync_master_ctx.quick.msg_txed[sync_master_ctx.quick.tx_count], 0); + } + sync_master_ctx.quick.msg_txed[sync_master_ctx.quick.tx_count] = pmsg; + } +} + +PPT_ISR_SECTION void sync_master_handle_rx_quick(bool rx, sync_header_t rx_header, + sync_pdu_t *rx_pdu, + uint16_t rx_len, uint16_t rssi, uint32_t rx_crc) +{ + if (rx && rx_header.s.seq == sync_master_ctx.seq_rx) + { + if (SYNC_ISR_DEBUG) + { + APP_PRINT_WARN0("sync_isr: ptx rx old pkt"); + } + rx = false; + } + + sync_master_ctx.quick.req_ack = rx == false; + sync_master_ctx.quick.seq_ack += rx; + sync_master_ctx.rx = rx; +#if TIME_DEBUG + if (sync_master_ctx.quick.seq_ack & 0x1) + { + time_debug_level_high(SYNC_MASTER_TIME_DEBUG_SEQ_ACK); + } + else + { + time_debug_level_low(SYNC_MASTER_TIME_DEBUG_SEQ_ACK); + } +#endif + sync_master_set_header(sync_master_ctx.quick.seq_ack, sync_master_ctx.seq_tx, + sync_master_ctx.quick.req_ack); + WR_PPT_REG_FIELD(PRO_TRX_CONTROL, ack_enable, sync_master_ctx.quick.req_ack); + if (sync_master_ctx.quick.req_ack) + { + time_debug_level_high(TIME_DEBUG_CHAN_THREAD); + time_debug_level_low(TIME_DEBUG_CHAN_THREAD); + } + + sync_master_pop_data(); + + /* hb handling */ + if (sync_master_ctx.quick.tx_count == 6) + { + bool rx_empty = false; + bool rx_ack = false; + if (rx) + { + if (rx_len == sizeof(sync_opcode_t) && rx_pdu->opcode == SYNC_OPCODE_EMPTY) + { + rx_empty = true; + } + if (rx_header.ack) + { + rx_ack = true; + } + } + //APP_PRINT_INFO4("sync: hb rhy idx %d counter %d, state %d, rx emtpy %d", + // sync_master_ctx.hb.rhy_idx, + // sync_master_ctx.hb.rhy_counter, sync_master_ctx.hb.state, rx_empty); + if (SYNC_MASTER_HB_RHY_NUMBER <= 1 || sync_master_ctx.hb.state == SYNC_MASTER_HB_STATE_IDLE) + { + + } + else if (sync_master_ctx.hb.state == SYNC_MASTER_HB_STATE_EMPTY_SEND) + { + bool tx_hb = false; + /* tx pend message */ + if (sync_ctx.msg_send.count != 0) + { + sync_master_ctx.hb.rhy_counter = 0; + } + else if (rx_empty && rx_ack) + { + if (sync_master_hb_rhy[0].period != SYNC_MASTER_HB_RHY_PERIOD_MAX) + { + if (sync_master_ctx.hb.rhy_idx_old != 0) + { + tx_hb = true; + sync_master_ctx.hb.rhy_idx = sync_master_ctx.hb.rhy_idx_old; + sync_master_ctx.hb.rhy_changing = true; + sync_master_ctx.hb.rhy_changing_idx = 0; + } + else + { + sync_master_ctx.hb.rhy_counter += 1; + if (sync_master_ctx.hb.rhy_counter >= sync_master_hb_rhy[0].period) + { + tx_hb = true; + sync_master_ctx.hb.rhy_idx = 1; + sync_master_ctx.hb.rhy_changing = true; + sync_master_ctx.hb.rhy_changing_idx = 0; + } + } + } + } + else + { + /* ignore if be disturbed */ + if (sync_master_ctx.rx) + { + sync_master_ctx.hb.rhy_counter = 0; + } + } + if (sync_master_ctx.hb.rhy_changing) + { + sync_master_ctx.hb.speed = sync_master_ctx.hb.rhy_changing_idx == 0 ? SYNC_SYNC_SPEED : + sync_master_hb_rhy[sync_master_ctx.hb.rhy_changing_idx].speed; + sync_master_ctx.hb.ce_cnt = sync_master_ctx.quick.ce_cnt + sync_master_ctx.hb.speed / + SYNC_SYNC_SPEED; + if (sync_master_param.early_high_prio_enable) + { + /* cancel if already triggered */ + if (sync_master_ctx.busy) + { + ppt_kill_hw_fsm(PPT_FSM_PTX); + sync_master_ctx.busy = false; + } + } + sync_master_ctx.hb.state = SYNC_MASTER_HB_STATE_HB_SEND; + sync_master_ctx.hb.slow = true; + } + } + else if (sync_master_ctx.hb.state == SYNC_MASTER_HB_STATE_HB_SEND) + { + bool hb_enter = false; + bool hb_continue = false; + /* tx pend message */ + if (sync_ctx.msg_send.count != 0) + { + sync_master_ctx.hb.slow = false; + sync_master_hb_exit(true); + } + /* rx empty ack message */ + else if (rx_ack && rx_empty) + { + sync_master_ctx.hb.unack_count = 0; + hb_enter = true; + } + else + { + /* rx non-empty message */ + if (sync_master_ctx.rx && rx_empty == false) + { + sync_master_ctx.hb.slow = false; + sync_master_hb_exit(true); + } + /* no rx or rx non-ack */ + else if (rx_ack == false) + { + /* skip wakeup only when already in the hb state */ + if (sync_master_ctx.hb.slow) + { + sync_master_ctx.hb.unack_count += 1; + if (sync_master_ctx.hb.unack_count >= SYNC_HB_TO_TIMES) + { + sync_master_ctx.hb.slow = false; + sync_master_ctx.count = 0; + sync_master_hb_exit(false); + } + else + { + hb_continue = true; + sync_master_ctx.hb.rhy_counter -= 1; + } + } + } + } + + if (hb_enter || hb_continue) + { + if (hb_enter && sync_master_ctx.hb.rhy_changing) + { + sync_master_ctx.hb.rhy_changing = false; + sync_master_ctx.hb.rhy_counter = 0; + APP_PRINT_INFO1("sync: hb enter %dus", + sync_master_hb_rhy[sync_master_ctx.hb.rhy_idx].speed); + if (sync_ctx.hb_cb) + { + sync_hb_cb_param_t param = {}; + param.enter = true; + param.interval = sync_master_hb_rhy[sync_master_ctx.hb.rhy_idx].speed; + sync_ctx.hb_cb(¶m); + } + } + if (sync_master_ctx.hb.rhy_changing) + { + sync_master_ctx.hb.speed = sync_master_ctx.hb.rhy_changing_idx == 0 ? SYNC_SYNC_SPEED : + sync_master_hb_rhy[sync_master_ctx.hb.rhy_changing_idx].speed; + } + else + { + sync_master_ctx.hb.speed = sync_master_hb_rhy[sync_master_ctx.hb.rhy_idx].speed; + } + sync_master_ctx.hb.ce_cnt = sync_master_ctx.quick.ce_cnt + sync_master_ctx.hb.speed / + SYNC_SYNC_SPEED; + sync_master_ctx.hb.slow = true; + if (sync_ctx.rte_req_cb) + { + sync_ctx.rte_req_cb(false); + } + } + } + } + + if (sync_master_ctx.hb.slow == false) + { + sync_master_push_data(); + } + + if (sync_master_ctx.quick.req_ack == false) + { + for (uint8_t loop = 0; loop < 7; loop++) + { + bool ack = rx && (sync_master_ctx.quick.msg_ack & BIT(loop)); +#if TIME_DEBUG + if (ack) + { + time_debug_level_high(SYNC_MASTER_TIME_DEBUG_ACK); + time_debug_level_low(SYNC_MASTER_TIME_DEBUG_ACK); + } + else + { + time_debug_level_high(SYNC_MASTER_TIME_DEBUG_NACK); + time_debug_level_low(SYNC_MASTER_TIME_DEBUG_NACK); + time_debug_level_high(SYNC_MASTER_TIME_DEBUG_NACK); + time_debug_level_low(SYNC_MASTER_TIME_DEBUG_NACK); + } +#endif + sync_msg_t *pmsg = sync_master_ctx.quick.msg_txed[loop]; + if (pmsg) + { + sync_master_ctx.quick.msg_txed[loop] = NULL; + pmsg->send_info.res = ack ? SYNC_SEND_RESULT_ACKED : SYNC_SEND_RESULT_NACKED; + sync_pendcall(sync_msg_handle_tx_done, pmsg, 0); + } + } + } + + if (rx) + { + if (rx_header.s.seq != sync_master_ctx.seq_rx)// || rx_crc != sync_master_ctx.crc_rx + { + sync_master_ctx.seq_rx = rx_header.s.seq; + sync_master_ctx.crc_rx = rx_crc; + if (rx_len > 0) + { + if (rx_pdu->opcode >= SYNC_OPCODE_APP_START) + { + if (sync_ctx.msg_receive_cb) + { + sync_receive_info_t info = {}; + info.rssi = ppt_get_rssi(rssi); + sync_ctx.msg_receive_cb((uint8_t *)rx_pdu, rx_len, &info); + } + } + else + { + bool handle = false; + switch (rx_pdu->opcode) + { + case SYNC_OPCODE_EMPTY: + if (rx_len == 1) + { + handle = true; + } + break; + default: + break; + } + if (handle == false) + { + APP_PRINT_WARN3("sync: rx unknown opcode %d, len %d, data %b", rx_pdu->opcode, rx_len, + TRACE_BINARY(rx_len, rx_pdu)); + } + } + } + } + } +} + +PPT_ISR_SECTION void sync_master_handle_sync_fast_to_quick(void) +{ + sync_header_t rx_header = {}; + sync_master_handle_rx_quick(false, rx_header, NULL, 0, 0, 0); + + if (sync_master_ctx.quick.tx_count < 6) + { + return; + } + + sync_master_ctx.count += 1; + if ( +#if SYNC_SUPPORT_SYNC_FAST_DISABLE + SYNC_SYNC_FAST_PERIOD == SYNC_SYNC_FAST_PERIOD_DISABLE || +#endif + sync_master_ctx.count >= SYNC_MASTER_SYNC_FAST_TIMES) + { + sync_hw_timer_stop(); + sync_master_close(); + sync_master_msg_sending_free(); +#if SYNC_SUPPORT_POWER_CONTROL + if (sync_ctx.tx_power_adaptive) + { + sync_power_ctrl_stop(); + } +#endif + ppt_reg_handler(sync_master_ppt_isr_handler); + sync_master_ctx.pair_state = SYNC_PAIR_STATE_IDLE; + sync_master_ctx.state = SYNC_STATE_IDLE; + APP_PRINT_INFO0("sync: disconnected!"); + sync_channel_print_statistic(); + sync_pendcall(sync_master_handle_disconnected, 0, 0); + if (sync_ctx.rte_req_cb) + { + sync_ctx.rte_req_cb(false); + } + } + else + { + sync_channel_change_next_in_group(); + if (sync_master_msg_sending_is_empty()) + { + sync_master_push_data(); + } + } +} + +PPT_ISR_SECTION void sync_master_handle_sync_lost_to_quick(void) +{ + sync_header_t rx_header = {}; + sync_master_handle_rx_quick(false, rx_header, NULL, 0, 0, 0); + + if (sync_master_ctx.quick.tx_count < 6) + { + return; + } + + sync_master_ctx.count += 1; + if (sync_master_ctx.count >= SYNC_MASTER_SYNC_LOST_TIMES) + { + APP_PRINT_INFO0("sync: lost!"); +#ifdef SYNC_DEBUG + sync_pendcall(sync_master_handle_sync_lost, 0, 0); +#endif +#if SYNC_SUPPORT_SYNC_FAST_DISABLE + if (SYNC_SYNC_FAST_PERIOD == SYNC_SYNC_FAST_PERIOD_DISABLE) + { + sync_master_handle_sync_fast_to_quick(); + } + else +#endif + { + sync_master_ctx.state = SYNC_STATE_SYNC_FAST; + sync_master_ctx.count = 0; + sync_channel_change_next_in_group(); + } + } +} + +PPT_ISR_SECTION void sync_master_handle_sync_early_quick(void) +{ + sync_master_ctx.quick.count = (sync_master_ctx.quick.count + 1) & 0x7; + if (sync_master_ctx.quick.skip) + { + sync_master_ctx.quick.skip = false; + /* no need protect since it shall be idle currently */ + if (sync_master_ctx.quick.tx_count == 6) + { + sync_master_ctx.quick.tx_count = 0; + } + else + { + if (sync_master_ctx.quick.req_ack && (sync_master_ctx.quick.count & 0x1)) + { + /* in case skip even slot */ + sync_master_ctx.quick.tx_count += 2; + } + else + { + sync_master_ctx.quick.tx_count += 1; + } + } + } + if (sync_master_ctx.quick.count == 0) + { + time_debug_level_low(TIME_DEBUG_CHAN_TIMING); + sync_master_ctx.quick.ce_cnt += 1; + WR_PPT_REG_FIELD(PRO_TRX_CONTROL, ack_enable, 0); + WR_PPT_REG_FIELD(PRO_HS_LENGTH, hs_field_length_4_0, 0); + sync_master_ctx.quick.ce_clk = sync_hw_frtimer_get_count(); + } + else if (sync_master_ctx.quick.count == 7) + { + return; + } + else + { + if (sync_master_ctx.quick.count == 6) + { + WR_PPT_REG_FIELD(PRO_TRX_CONTROL, ack_enable, 1); + } + } + + if (sync_master_ctx.quick.req_ack) + { + if (sync_master_ctx.quick.count & 0x1) + { + return; + } + WR_PPT_REG_FIELD(PRO_TRX_CONTROL, ack_enable, 1); + } + + if (sync_master_ctx.hb.slow) + { + sync_master_ctx.quick.tx_count = sync_master_ctx.quick.count; + if (sync_master_ctx.hb.ce_cnt == sync_master_ctx.quick.ce_cnt || sync_master_ctx.hb.oversleep) + { + if (sync_master_ctx.quick.count == 6) + { + sync_master_handle_hb_to(); + sync_master_ctx.hb.ce_cnt += sync_master_ctx.hb.speed / SYNC_SYNC_SPEED; + sync_master_ctx.hb.oversleep = false; + } + else if (sync_master_ctx.quick.count == 5) + { + if (sync_ctx.rte_req_cb) + { + sync_ctx.rte_req_cb(true); + } + } + } + } + else if (sync_ctx.hw_timer_pend_time <= 12 || sync_master_ctx.quick.count == 6) + { + sync_master_ctx.busy = true; + ppt_execute_instruction(PPT_HW_INSTRUCTION_PTX_ENABLE); + } + else + { + sync_master_ctx.quick.skip = true; + if (SYNC_ISR_DEBUG) + { + APP_PRINT_WARN2("sync_isr: skip count %d, timer pend %dus", sync_master_ctx.quick.count, + sync_ctx.hw_timer_pend_time); + } + } + if (sync_master_ctx.quick.count == 0) + { + time_debug_level_high(TIME_DEBUG_CHAN_TIMING); + } +} + +PPT_ISR_SECTION static void sync_master_ppt_isr_handler_quick(void) +{ + time_debug_level_high(TIME_DEBUG_CHAN_ISR); + PRO_MISR_TYPE reg_misr; + reg_misr.d16 = RD_PPT_REG(PRO_MISR); + //APP_PRINT_INFO1("sync_isr: ptx isr 0x%04x", reg_misr.d16); + + if (reg_misr.tx_int) + { + sync_master_ctx.busy = false; + /* pop tx stack */ + PRO_TX_STACK_TYPE tx_stack = {.d16 = RD_PPT_REG(PRO_TX_STACK)}; + //PRO_TX_HS_LOWER_TYPE hs_lower = {.d16 = RD_PPT_REG(PRO_TX_HS_LOWER)}; + //PRO_TX_HS_UPPER_TYPE hs_upper = {.d16 = RD_PPT_REG(PRO_TX_HS_UPPER)}; + int32_t clk_diff = 0; + if (sync_master_ctx.hb.slow == false) + { + PRO_TX_CLK_LOWER_TYPE tx_clk_lower = {.d16 = RD_PPT_REG(PRO_TX_CLK_LOWER)}; + PRO_TX_CLK_UPPER_TYPE tx_clk_upper = {.d16 = RD_PPT_REG(PRO_TX_CLK_UPPER)}; + uint32_t tx_clk = (tx_clk_upper.tx_clk_31_16 << 16) + tx_clk_lower.tx_clk_15_0; + clk_diff = sync_hw_frtimer_time_diff(tx_clk, sync_master_ctx.quick.ce_clk); + if (clk_diff >= 0) + { + uint8_t tx_count = clk_diff / 125; + if (sync_master_ctx.quick.tx_count != tx_count) + { + APP_PRINT_WARN2("sync_isr: ptx tx count fail, add %d cal %d", sync_master_ctx.quick.tx_count, + tx_count); + sync_master_ctx.quick.tx_count = tx_count; + } + } + } + PRO_TX_LENGTH_TYPE length = {.d16 = RD_PPT_REG(PRO_TX_LENGTH)}; // Read 0x6a to pop stack + sync_master_ctx.tx_fifo_bitmap = RD_U32_BZDMA_REG(BZDMA_REG_BLEONLY_ENTRY_SEGMENT_VALID(( + uint8_t)tx_stack.tx_entry_1_0)); + if (SYNC_ISR_DEBUG) + { + APP_PRINT_INFO8("sync_isr: ptx tx stack 0x%04x, bitmap 0x%02x, rd ptr hw %d sw %d, len %d, ce %d, clk %d, tx %d", + tx_stack.d16, sync_master_ctx.tx_fifo_bitmap, + tx_stack.tx_ptr, sync_master_ctx.tx_ptr, length.tx_length, sync_master_ctx.quick.ce_cnt, clk_diff, + sync_master_ctx.quick.tx_count); + } + sync_master_ctx.tx_ptr_hw = tx_stack.tx_ptr; + sync_master_ctx.tx_null = length.tx_length == 0; + sync_master_ctx.tx_old = (sync_master_ctx.tx_null == false) && + (tx_stack.tx_ptr != sync_master_ctx.tx_ptr); + + /* workaround when only tx empty pkt */ + if (sync_master_ctx.tx_null + && 0 == RD_U32_BZDMA_REG(BZDMA_REG_BLEONLY_ENTRY_SEGMENT_VALID((uint8_t)tx_stack.tx_entry_1_0)) + && tx_stack.tx_ptr != sync_master_ctx.tx_ptr + ) + { + APP_PRINT_WARN0("sync: fail, fifo error"); + sync_master_init_tx_fifo(); + } + + if (sync_master_ctx.tx_null || sync_master_ctx.tx_old) + { + APP_PRINT_WARN2("sync_isr: tx fail, null %d, old %d", sync_master_ctx.tx_null, + sync_master_ctx.tx_old); + sync_master_ctx.tx_fail_count += 1; + } + else + { + sync_master_ctx.tx_fail_count = 0; + } + + if (sync_master_ctx.quick.tx_count <= 5) + { + if (sync_master_ctx.quick.req_ack) + { + WR_PPT_REG_FIELD(PRO_HS_LENGTH, hs_field_length_4_0, SYNC_SUFFIX_LEN); + sync_master_ctx.busy = true; + } + else + { + /* don't switch pkt when tx fail */ + if (false == sync_master_ctx.tx_null && false == sync_master_ctx.tx_old && + sync_master_ctx.tx_fifo_bitmap) + { + sync_master_pop_data(); + sync_master_push_data(); + } + /* tx_count is used for determine ack timing, so update at last */ + sync_master_ctx.quick.tx_count += 1; + } + } + else + { + WR_PPT_REG_FIELD(PRO_HS_LENGTH, hs_field_length_4_0, SYNC_SUFFIX_LEN); + sync_master_ctx.busy = true; + } + } + + if (reg_misr.rx_int) + { + sync_master_ctx.busy = false; + ppt_clear_radio(); + WR_PPT_REG_FIELD(PRO_HS_LENGTH, hs_field_length_4_0, 0); + /* pop rx stack */ + //PRO_LENGTH_INCLUDE_ADDON_TYPE len_inc_addon = {.d16 = RD_PPT_REG(PRO_LENGTH_INCLUDE_ADDON)}; + PRO_RX_STACK_TYPE rx_stack = {.d16 = RD_PPT_REG(PRO_RX_STACK)}; + PRO_RX_HP_TYPE hp = {.d16 = RD_PPT_REG(PRO_RX_HP)}; + if (rx_stack.is_max_length) + { + APP_PRINT_WARN0("sync_isr: ptx rx max length"); + rx_stack.rx_time_out = 1; + } + bool rx = !(rx_stack.rx_time_out || rx_stack.rx_hit == false || rx_stack.is_crc_error); + //PRO_ACCHIT_CLK_LOWER_TYPE acchit_clk_lower = {.d16 = RD_PPT_REG(PRO_ACCHIT_CLK_LOWER)}; + //PRO_ACCHIT_CLK_UPPER_TYPE acchit_clk_upper = {.d16 = RD_PPT_REG(PRO_ACCHIT_CLK_UPPER)}; + PRO_LENGTH_TYPE length = {.d16 = RD_PPT_REG(PRO_LENGTH)}; + PRO_RSSI_TYPE rssi = {.d16 = RD_PPT_REG(PRO_RSSI)}; + PRO_RX_CRC_LOWER_TYPE rx_crc_lower = {.d16 = RD_PPT_REG(PRO_RX_CRC_LOWER)}; + PRO_RX_CRC_UPPER_TYPE rx_crc_upper = {.d16 = RD_PPT_REG(PRO_RX_CRC_UPPER)}; + uint32_t rx_crc = (rx_crc_upper.d16 << 16) + rx_crc_lower.d16; + rx_crc >>= 32 - SYNC_CRC_LEN; + PRO_ACCHIT_CLK_LOWER_TYPE acchit_clk_lower = {.d16 = RD_PPT_REG(PRO_ACCHIT_CLK_LOWER)}; + PRO_ACCHIT_CLK_UPPER_TYPE acchit_clk_upper = {.d16 = RD_PPT_REG(PRO_ACCHIT_CLK_UPPER)}; + uint32_t acchit_clk = (acchit_clk_upper.acchit_clk_31_16 << 16) + acchit_clk_lower.acchit_clk_15_0; + PRO_RX_HS_LOWER_TYPE rx_hs_lower = {.d16 = RD_PPT_REG(PRO_RX_HS_LOWER)}; + PRO_RX_HS_UPPER_TYPE rx_hs_upper = {.d16 = RD_PPT_REG(PRO_RX_HS_UPPER)}; //read 0x62 to pop rx stack + uint32_t hs = (rx_hs_upper.d16 << 16) + rx_hs_lower.d16; + sync_master_ctx.quick.msg_ack = hs; + //PRO_INT_CTRL_TYPE int_ctrl = {.d16 = RD_PPT_REG(PRO_INT_CTRL)}; + bool req_ack = sync_master_ctx.quick.req_ack; + if (SYNC_ISR_DEBUG) + { + int32_t clk_diff = 0; + clk_diff = sync_hw_frtimer_time_diff(acchit_clk, sync_master_ctx.quick.ce_clk); + APP_PRINT_INFO6("sync_isr: ptx rx stack 0x%04x, ce %d, clk %d, hp 0x%02x, hs 0x%x, len %d", + rx_stack.d16, + sync_master_ctx.quick.ce_cnt, clk_diff, hp.hp, hs, length.d16); + } + + if (rx) + { + uint16_t rx_len = length.d16 + SYNC_OVERHEAD_LEN + 2; + uint8_t *rx_buffer = ppt_get_rx_buffer(rx_len); + ppt_pop_rx_fifo(0, rx_buffer, rx_len); + sync_pdu_t *pdu = (sync_pdu_t *)(rx_buffer + SYNC_OVERHEAD_LEN + 2); + sync_header_t rx_header; + rx_header.value = hp.hp; + + //APP_PRINT_INFO2("sync_isr: ptx rx len %d, %b", rx_len, TRACE_BINARY(rx_len, rx_buffer)); + + if (sync_master_ctx.count != 0) + { + sync_master_ctx.count = 0; + } + sync_master_handle_rx_quick(true, rx_header, pdu, length.d16, + rssi.rssi, rx_crc); + if (sync_master_ctx.state == SYNC_STATE_SYNC_FAST) + { + sync_master_ctx.state = SYNC_STATE_SYNC; + sync_master_ctx.count = 0; + APP_PRINT_INFO2("sync: reconnected on %d[%d]!", sync_ctx.chan_cur, + sync_ctx.chan_cfg[sync_ctx.chan_cur].freq); +#ifdef SYNC_DEBUG + sync_pendcall(sync_master_handle_sync_reconnected, 0, 0); +#endif + } + } + else + { + if (sync_master_ctx.state == SYNC_STATE_SYNC) + { + sync_master_handle_sync_lost_to_quick(); + } + else if (sync_master_ctx.state == SYNC_STATE_SYNC_FAST) + { + sync_master_handle_sync_fast_to_quick(); + } + } + /* tx_count is used for determine ack timing, so update at last */ + if (req_ack) + { + sync_master_ctx.quick.tx_count += 2; + if (sync_master_ctx.quick.tx_count > 6) + { + sync_master_ctx.quick.tx_count = 0; + } + } + else + { + sync_master_ctx.quick.tx_count = 0; + } + } + + time_debug_level_low(TIME_DEBUG_CHAN_ISR); +} + +PPT_ISR_SECTION void sync_master_handle_sync_early_first_quick(void) +{ + sync_hw_timer_start(125, sync_master_handle_sync_early_quick); + sync_hw_timer_set_periodic(true); + sync_hw_timer_impr_ip(true); + ppt_reg_handler(sync_master_ppt_isr_handler_quick); + sync_master_ctx.quick.enable = true; + sync_master_ctx.quick.count = 7; + sync_master_ctx.quick.tx_count = 0; + sync_master_ctx.quick.ce_cnt -= 1; + WR_PPT_REG_FIELD(PRO_FIELD_LENGTH, hp_field_length_3_0, SYNC_HEADER_LEN_MT1R); + sync_master_set_header(sync_master_ctx.quick.seq_ack, sync_master_ctx.seq_tx, + sync_master_ctx.quick.req_ack); + sync_master_handle_sync_early_quick(); + sync_master_push_data(); +} + +PPT_ISR_SECTION void sync_master_handle_sync_early_hb_quick(void) +{ + time_debug_level_high(TIME_DEBUG_CHAN_DLPS); + sync_hw_timer_start(125, sync_master_handle_sync_early_quick); + sync_hw_timer_set_periodic(true); + sync_hw_timer_impr_ip(true); + time_debug_level_low(TIME_DEBUG_CHAN_DLPS); + sync_master_ctx.hb.sleep_cal = false; + uint8_t count = (sync_master_ctx.quick.count + 1) & 0x7; + if (count != 0) + { + sync_master_ctx.quick.ce_clk = sync_hw_frtimer_get_count() - count * 125 * SYNC_HW_FRTIMER_CLOCK; + } + sync_master_handle_sync_early_quick(); + //APP_PRINT_INFO4("sync: dlps mac exit, sleep %d hw %d, ce %d, count %d!", + // sync_master_ctx.hb.time_left, sync_master_ctx.hb.time_left1, sync_master_ctx.quick.ce_cnt, + // sync_master_ctx.quick.count); +} + +static void sync_master_dlps_mac_exit(void); +PPT_ISR_SECTION void sync_master_hb_sleep_resume(void) +{ + if (sync_master_ctx.hb.sleep) + { + if (sync_master_ctx.hb.sleep_mac) + { + RD_PPT_REG(PRO_MISR); + } + else + { + sync_master_dlps_mac_exit(); + } + } +} +#endif + +PPT_ISR_SECTION static void sync_master_ppt_isr_handler(void) +{ + time_debug_level_high(TIME_DEBUG_CHAN_ISR); + PRO_MISR_TYPE reg_misr; + reg_misr.d16 = RD_PPT_REG(PRO_MISR); + //APP_PRINT_INFO1("sync_isr: ptx isr 0x%04x\r\n", reg_misr.d16); + + /* free the pend msg at the early handler */ + if (sync_master_ctx.pmsg_pend_free) + { + sync_pendcall(sync_msg_handle_tx_done, sync_master_ctx.pmsg_pend_free, 0); + sync_master_ctx.pmsg_pend_free = NULL; + } + + if (reg_misr.tx_int) + { + Pad_Config(P2_3, PAD_SW_MODE, PAD_IS_PWRON, PAD_PULL_DOWN, PAD_OUT_ENABLE, + PAD_OUT_HIGH); + Pad_Config(P2_3, PAD_SW_MODE, PAD_IS_PWRON, PAD_PULL_DOWN, PAD_OUT_ENABLE, + PAD_OUT_LOW); + /* pop tx stack */ + PRO_TX_STACK_TYPE tx_stack = {.d16 = RD_PPT_REG(PRO_TX_STACK)}; + //PRO_TX_HS_LOWER_TYPE hs_lower = {.d16 = RD_PPT_REG(PRO_TX_HS_LOWER)}; + //PRO_TX_HS_UPPER_TYPE hs_upper = {.d16 = RD_PPT_REG(PRO_TX_HS_UPPER)}; +#if SYNC_SUPPORT_MT1R + if (sync_ctx.mt1r.flag) + { + if ((sync_master_ctx.pair_state == SYNC_PAIR_STATE_PAIRING && + sync_master_ctx.phase == SYNC_MASTER_PAIR_PHASE_SEND_REQ) + || (sync_master_ctx.pair_state == SYNC_PAIR_STATE_PAIRED && + sync_master_ctx.state == SYNC_STATE_SYNC_SLOW)) + { + PRO_TX_CLK_LOWER_TYPE tx_clk_lower = {.d16 = RD_PPT_REG(PRO_TX_CLK_LOWER)}; + PRO_TX_CLK_UPPER_TYPE tx_clk_upper = {.d16 = RD_PPT_REG(PRO_TX_CLK_UPPER)}; + sync_master_ctx.quick.ce_clk = (tx_clk_upper.tx_clk_31_16 << 16) + tx_clk_lower.tx_clk_15_0; + } + } +#endif + PRO_TX_LENGTH_TYPE length = {.d16 = RD_PPT_REG(PRO_TX_LENGTH)}; // Read 0x6a to pop stack + if (SYNC_ISR_DEBUG) + { + APP_PRINT_INFO6("sync_isr: ptx tx stack 0x%04x, seq 0x%02x, bitmap 0x%02x, rd ptr hw %d sw %d, len %d", + tx_stack.d16, sync_master_ctx.seq_tx, + RD_U32_BZDMA_REG(BZDMA_REG_BLEONLY_ENTRY_SEGMENT_VALID((uint8_t)tx_stack.tx_entry_1_0)), + tx_stack.tx_ptr, sync_master_ctx.tx_ptr, length.tx_length); + } + sync_master_ctx.tx_ptr_hw = tx_stack.tx_ptr; + sync_master_ctx.tx_null = length.tx_length == 0; + sync_master_ctx.tx_old = tx_stack.tx_ptr != sync_master_ctx.tx_ptr; + sync_header_t header; + header.value = tx_stack.tx_hp; + if (header.seq != (sync_master_ctx.seq_tx & ((1 << SYNC_HEADER_SEQ_LEN) - 1))) + { + sync_master_ctx.tx_old = true; + } + if (sync_master_ctx.tx_null || sync_master_ctx.tx_old) + { + APP_PRINT_WARN2("sync_isr: tx fail, null %d, old %d", sync_master_ctx.tx_null, + sync_master_ctx.tx_old); + sync_master_ctx.tx_fail_count += 1; + } + else + { + sync_master_ctx.tx_fail_count = 0; + } + +#if SYNC_SUPPORT_POWER_CONTROL + if (sync_ctx.tx_power_adaptive) + { + sync_ctx.power_ctrl_count += 1; + } +#endif + + if (sync_master_ctx.state == SYNC_STATE_SYNC && + sync_master_ctx.pair_state == SYNC_PAIR_STATE_PAIRED + ) + { + sync_master_msg_sending_info_t *pmsg_info = sync_master_msg_sending_peak(); + if (pmsg_info) + { + pmsg_info->tx_count += 1; + if (SYNC_ISR_DEBUG) + { + sync_msg_type_t type = SYNC_MSG_TYPE_ALL; + uint8_t opcode = 0; + if (pmsg_info->pmsg) + { + type = pmsg_info->pmsg->type; + opcode = pmsg_info->pmsg->data[0]; + } + else + { + uint8_t *tx_buffer = ppt_get_tx_buffer(1); + opcode = tx_buffer[0]; + } + + APP_PRINT_INFO2("sync_isr: tx msg type %d, op 0x%02x", type, opcode); + } + } + + if (sync_master_ctx.hb.slow == false) + { + if (sync_master_param.early_high_prio_enable) + { + if (sync_master_ctx.curr_time_in_ce == 0) + { + if (sync_master_param.tx_prepare_cb != NULL) + { + sync_master_param.tx_prepare_cb(); + } + } + } + } + } + } + + if (reg_misr.rx_int) + { + sync_master_ctx.handling_ack = true; + sync_master_ctx.busy = false; + + /* pop rx stack */ + //PRO_LENGTH_INCLUDE_ADDON_TYPE len_inc_addon = {.d16 = RD_PPT_REG(PRO_LENGTH_INCLUDE_ADDON)}; + PRO_RX_STACK_TYPE rx_stack = {.d16 = RD_PPT_REG(PRO_RX_STACK)}; + PRO_RX_HP_TYPE hp = {.d16 = RD_PPT_REG(PRO_RX_HP)}; + if (rx_stack.is_max_length) + { + APP_PRINT_WARN0("sync_isr: ptx rx max length"); + rx_stack.rx_time_out = 1; + } + bool rx = !(rx_stack.rx_time_out || rx_stack.rx_hit == false || rx_stack.is_crc_error); + if (sync_master_ctx.pair_state == SYNC_PAIR_STATE_PAIRED && + sync_master_ctx.state != SYNC_STATE_SYNC_SLOW) + { + sync_header_t rx_header; + rx_header.value = hp.hp; + sync_master_handle_ack(rx, rx_header); + } + + //PRO_ACCHIT_CLK_LOWER_TYPE acchit_clk_lower = {.d16 = RD_PPT_REG(PRO_ACCHIT_CLK_LOWER)}; + //PRO_ACCHIT_CLK_UPPER_TYPE acchit_clk_upper = {.d16 = RD_PPT_REG(PRO_ACCHIT_CLK_UPPER)}; + PRO_RX_CRC_LOWER_TYPE rx_crc_lower = {.d16 = RD_PPT_REG(PRO_RX_CRC_LOWER)}; + PRO_RX_CRC_UPPER_TYPE rx_crc_upper = {.d16 = RD_PPT_REG(PRO_RX_CRC_UPPER)}; + uint32_t rx_crc = (rx_crc_upper.d16 << 16) + rx_crc_lower.d16; + rx_crc >>= 32 - SYNC_CRC_LEN; + PRO_RSSI_TYPE rssi = {.d16 = RD_PPT_REG(PRO_RSSI)}; + PRO_LENGTH_TYPE length = {.d16 = RD_PPT_REG(PRO_LENGTH)}; + //PRO_RX_HS_LOWER_TYPE rx_hs_lower = {.d16 = RD_PPT_REG(PRO_RX_HS_LOWER)}; + PRO_RX_HS_UPPER_TYPE rx_hs_upper = {.d16 = RD_PPT_REG(PRO_RX_HS_UPPER)}; //read 0x62 to pop rx stack + //PRO_INT_CTRL_TYPE int_ctrl = {.d16 = RD_PPT_REG(PRO_INT_CTRL)}; + + if (SYNC_ISR_DEBUG) + { + APP_PRINT_INFO4("sync_isr: ptx rx stack 0x%04x, rssi %d, hp 0x%02x, len %d", rx_stack.d16, + ppt_get_rssi(rssi.rssi), hp.hp, length.d16); + } + + sync_channel_statistic(rx); + sync_ctx.chan_used_count += 1; + if (false == rx) + { + if (sync_master_ctx.pair_state == SYNC_PAIR_STATE_PAIRED) + { + if (sync_master_ctx.state == SYNC_STATE_SYNC) + { + sync_master_handle_sync_lost_to(); + } + else if (sync_master_ctx.state == SYNC_STATE_SYNC_SLOW) + { + sync_master_handle_sync_slow_to(); + } + else if (sync_master_ctx.state == SYNC_STATE_SYNC_FAST) + { + sync_master_handle_sync_fast_to(); + } + } + else if (sync_master_ctx.pair_state == SYNC_PAIR_STATE_PAIRING) + { + if (sync_master_ctx.phase == SYNC_MASTER_PAIR_PHASE_SEND_REQ) + { + sync_master_handle_pair_req_to(); + } + else if (sync_master_ctx.phase == SYNC_MASTER_PAIR_PHASE_SEND_CFM) + { + sync_master_handle_pair_cfm_to(); + } + } + } + else + { + uint16_t rx_len = length.d16 + SYNC_OVERHEAD_LEN; + uint8_t *rx_buffer = ppt_get_rx_buffer(rx_len); + ppt_pop_rx_fifo(0, rx_buffer, rx_len); + sync_pdu_t *pdu = (sync_pdu_t *)(rx_buffer + SYNC_OVERHEAD_LEN); + sync_header_t rx_header; + rx_header.value = hp.hp; + + //APP_PRINT_INFO2("sync_isr: ptx rx len %d, %b", rx_len, TRACE_BINARY(rx_len, rx_buffer)); + if (sync_master_ctx.pair_state == SYNC_PAIR_STATE_PAIRED) + { + bool handle_rx = true; + if (sync_master_ctx.state == SYNC_STATE_SYNC) + { + if (sync_master_ctx.count != 0) + { + sync_master_ctx.count = 0; + } + } + else if (sync_master_ctx.state == SYNC_STATE_SYNC_SLOW) + { + handle_rx = false; + if (length.d16 == sizeof(sync_opcode_t) && pdu->opcode == SYNC_OPCODE_CONN_RSP) + { + sync_master_ctx.state = SYNC_STATE_SYNC; + sync_master_ctx.count = 0; + sync_master_ctx.tx_ptr = ppt_trigger_fw_ack(0); + sync_ppt_set_tifs(false); + APP_PRINT_INFO2("sync: connected on %d[%d]!", sync_ctx.chan_cur, + sync_ctx.chan_cfg[sync_ctx.chan_cur].freq); + sync_master_ctx.rx = 1; + sync_master_ctx.seq_tx = 0; + sync_master_ctx.handling_ack = false; +#if SYNC_SUPPORT_MT1R + if (sync_ctx.mt1r.flag) + { + uint32_t clk = sync_hw_frtimer_get_count(); + uint32_t delay = sync_hw_frtimer_time_elapse(clk, sync_master_ctx.quick.ce_clk); + delay = SYNC_CONNECT_DELAY > delay ? SYNC_CONNECT_DELAY - delay : 30; + sync_hw_timer_start(delay, sync_master_handle_sync_early_first_quick); + sync_ppt_set_rf_time_mt1r(); + sync_ctx.conn_interval = 1000; + APP_PRINT_ERROR0("sync: quick enter"); + if (sync_ctx.rte_req_cb) + { + sync_ctx.rte_req_cb(true); + } + } + else +#endif + { + sync_master_ctx.curr_time_in_ce = SYNC_SYNC_SPEED; + sync_master_start_sync_timer(); + if (SYNC_SYNC_SPEED_HIGH <= SYNC_SYNC_SPEED_HIGH_MIN) + { + if (sync_ctx.rte_req_cb) + { + sync_ctx.rte_req_cb(true); + } + } + } + sync_pendcall(sync_master_handle_connected, 0, 0); + sync_channel_clear_statistic(); +#if SYNC_SUPPORT_POWER_CONTROL + if (sync_ctx.tx_power_adaptive) + { + sync_power_ctrl_start(); + } +#endif + } + else + { + sync_master_handle_sync_slow_to(); + } + } + else if (sync_master_ctx.state == SYNC_STATE_SYNC_FAST) + { + sync_master_ctx.curr_time_in_ce = SYNC_SYNC_SPEED; + sync_master_start_sync_timer(); + sync_master_ctx.state = SYNC_STATE_SYNC; + sync_master_ctx.count = 0; + APP_PRINT_INFO2("sync: reconnected on %d[%d]!", sync_ctx.chan_cur, + sync_ctx.chan_cfg[sync_ctx.chan_cur].freq); +#ifdef SYNC_DEBUG + sync_pendcall(sync_master_handle_sync_reconnected, 0, 0); +#endif + } + if (handle_rx) + { + sync_master_handle_rx(true, rx_header, (sync_pdu_t *)(rx_buffer + SYNC_OVERHEAD_LEN), length.d16, + rssi.rssi, rx_crc); + } + } + else if (sync_master_ctx.pair_state == SYNC_PAIR_STATE_PAIRING) + { + if (sync_master_ctx.phase == SYNC_MASTER_PAIR_PHASE_SEND_REQ) + { + bool retry = true; + do + { + int8_t rssi_dbm = ppt_get_rssi(rssi.rssi); + if (rssi_dbm < sync_ctx.pair_rssi_th) + { + APP_PRINT_ERROR2("sync: pair rssi check fail, %d < %d", rssi_dbm, sync_ctx.pair_rssi_th); + break; + } + if (length.d16 == sizeof(sync_opcode_t) + sizeof(sync_pair_rsp_t)) + { + sync_pdu_t *pdu = (sync_pdu_t *)(rx_buffer + SYNC_OVERHEAD_LEN); + if (pdu->opcode == SYNC_OPCODE_PAIR_RSP) + { + retry = false; + sync_master_ctx.phase = SYNC_MASTER_PAIR_PHASE_SEND_CFM; + sync_master_ctx.count1 = 0; + sync_ppt_set_tifs(false); + sync_hw_timer_start(SYNC_SYNC_SPEED, sync_master_handle_sync_slow_early); + + sync_master_ctx.acc_data = pdu->pair_rsp.acc; + sync_acc_set(sync_master_ctx.acc_data); + + sync_master_ctx.tx_ptr = ppt_trigger_fw_ack(0); + sync_master_ctx.rx = 1; + sync_master_ctx.seq_tx = 0; + sync_set_header(1, 0); + sync_pdu_t pdu; + pdu.opcode = SYNC_OPCODE_PAIR_CONF; + ppt_push_tx_data(sizeof(sync_opcode_t), (uint8_t *)&pdu); + + APP_PRINT_INFO3("sync: pairing 0x%08x on %d[%d]!", sync_master_ctx.acc_data.addr, sync_ctx.chan_cur, + sync_ctx.chan_cfg[sync_ctx.chan_cur].freq); + } + } + } + while (0); + if (retry) + { + sync_master_handle_pair_req_to(); + } + } + else if (sync_master_ctx.phase == SYNC_MASTER_PAIR_PHASE_SEND_CFM) + { + if (rx_header.ack) + { + sync_master_ctx.pair_state = SYNC_PAIR_STATE_PAIRED; + sync_master_ctx.state = SYNC_STATE_SYNC; + sync_master_ctx.count = 0; + sync_master_ctx.tx_ptr = ppt_trigger_fw_ack(0); + + sync_master_ctx.rx = 1; + sync_master_ctx.seq_tx = 0; + sync_master_ctx.handling_ack = false; + APP_PRINT_INFO3("sync: paired 0x%08x on %d[%d]!", sync_master_ctx.acc_data.addr, sync_ctx.chan_cur, + sync_ctx.chan_cfg[sync_ctx.chan_cur].freq); +#if SYNC_SUPPORT_MT1R + if (sync_ctx.mt1r.flag) + { + uint32_t clk = sync_hw_frtimer_get_count(); + uint32_t total_time = SYNC_PAIR_CFM_PERIOD + SYNC_CONNECT_DELAY; + uint32_t delay = sync_hw_frtimer_time_elapse(clk, sync_master_ctx.quick.ce_clk); + delay = total_time > delay ? total_time - delay : 30; + sync_hw_timer_start(delay, sync_master_handle_sync_early_first_quick); + sync_ppt_set_rf_time_mt1r(); + sync_ctx.conn_interval = 1000; + APP_PRINT_ERROR0("sync: quick enter"); + if (sync_ctx.rte_req_cb) + { + sync_ctx.rte_req_cb(true); + } + } + else +#endif + { + sync_master_ctx.curr_time_in_ce = SYNC_SYNC_SPEED; + sync_master_start_sync_timer(); + if (SYNC_SYNC_SPEED_HIGH <= SYNC_SYNC_SPEED_HIGH_MIN) + { + if (sync_ctx.rte_req_cb) + { + sync_ctx.rte_req_cb(true); + } + } + } + sync_pendcall(sync_master_handle_paired, 0, 0); + sync_channel_clear_statistic(); +#if SYNC_SUPPORT_POWER_CONTROL + if (sync_ctx.tx_power_adaptive) + { + sync_power_ctrl_start(); + } +#endif + sync_header_t rx_header; + rx_header.value = hp.hp; + sync_master_handle_rx(true, rx_header, (sync_pdu_t *)(rx_buffer + SYNC_OVERHEAD_LEN), length.d16, + rssi.rssi, rx_crc); + } + else + { + sync_master_handle_pair_cfm_to(); + } + } + } + } + } + + if (reg_misr.kill_ptx_int) + { + ppt_clear_radio(); + WR_PPT_REG(PRO_MISR, BIT4); + ppt_ctx->fsm = PPT_FSM_STANDBY; + ppt_ctx->sync_flag = false; + } + time_debug_level_low(TIME_DEBUG_CHAN_ISR); +} + +void sync_master_init(void) +{ + sync_ppt_init(); + ppt_reg_handler(sync_master_ppt_isr_handler); + sync_hw_timer_init(); +#ifdef SYNC_DEBUG + sync_hw_frtimer_init(); +#endif + sync_ctx.role = SYNC_ROLE_MASTER; + memset(&sync_master_ctx, 0, sizeof(sync_master_ctx)); +} + +bool sync_master_set_hb_param(uint8_t level, uint32_t interval, uint32_t beat_times) +{ + if (level >= SYNC_MASTER_HB_RHY_NUMBER) + { + return false; + } + if (level != 0) + { + sync_master_hb_rhy[level].speed = interval; + } + if (level != SYNC_MASTER_HB_RHY_NUMBER - 1) + { + sync_master_hb_rhy[level].period = beat_times; + } + return true; +} + +bool sync_master_wakeup_hb(void) +{ + uint32_t lock = sync_enter_critical(); + if (sync_master_ctx.state != SYNC_STATE_SYNC || + sync_master_ctx.pair_state != SYNC_PAIR_STATE_PAIRED) + { + sync_exit_critical(lock); + return false; + } + + if (sync_master_ctx.hb.slow == false) + { + sync_master_hb_exit(true); + sync_exit_critical(lock); + return false; + } + + if (sync_master_ctx.busy == false) + { + /* reuse this function to activate */ + sync_master_handle_tx_trigger(); + } + else + { + sync_master_hb_exit(true); + } + sync_exit_critical(lock); + return true; +} + +void sync_master_reg_tx_prepare_cb(void (*cb)(void)) +{ + sync_master_param.tx_prepare_cb = cb; +} + +void sync_master_set_tx_scheme(sync_master_tx_scheme_t tx_scheme) +{ + sync_master_param.tx_scheme = tx_scheme; +} + +void sync_master_check_feature(void) +{ + sync_check_feature(); + +#if SYNC_SUPPORT_MT1R + if (sync_ctx.mt1r.flag == false) +#endif + { + sync_master_param.tx_align_enable = sync_master_param.tx_scheme.tx_align == SYNC_FEATURE_USE_DEFAULT + ? SYNC_SYNC_SPEED_HIGH > 1000 : sync_master_param.tx_scheme.tx_align == SYNC_FEATURE_ENABLE; + sync_master_param.early_high_prio_enable = sync_master_param.tx_scheme.early_high_prio == + SYNC_FEATURE_USE_DEFAULT ? SYNC_SYNC_SPEED_HIGH == SYNC_SYNC_SPEED_HIGH_MIN : + sync_master_param.tx_scheme.early_high_prio == SYNC_FEATURE_ENABLE; + sync_master_param.retrans_at_ack_enable = sync_master_param.tx_scheme.retrans_at_ack == + SYNC_FEATURE_USE_DEFAULT ? (SYNC_SYNC_SPEED_HIGH == SYNC_SYNC_SPEED) && + (SYNC_SYNC_SPEED_HIGH > SYNC_SYNC_SPEED_HIGH_MIN) : sync_master_param.tx_scheme.retrans_at_ack == + SYNC_FEATURE_ENABLE; + sync_master_param.tx_new_at_retrans_int_enable = sync_master_param.tx_scheme.tx_new_at_retrans_int + == SYNC_FEATURE_USE_DEFAULT ? false : sync_master_param.tx_scheme.tx_new_at_retrans_int == + SYNC_FEATURE_ENABLE; + } + uint32_t speed = SYNC_SYNC_SPEED; + sync_time_get(SYNC_TIME_PARAM_CONNECT_INTERVAL, &speed); + APP_PRINT_INFO7("sync: speed %dus high %dus, scheme %d-%d-%d-%d, tx cb 0x%x", speed, + SYNC_SYNC_SPEED_HIGH, + sync_master_param.tx_align_enable, sync_master_param.early_high_prio_enable, + sync_master_param.retrans_at_ack_enable, sync_master_param.tx_new_at_retrans_int_enable, + sync_master_param.tx_prepare_cb); +} + +void sync_master_enable(void) +{ + +} + +sync_err_code_t sync_master_pair(void) +{ + if (sync_master_ctx.state != SYNC_STATE_IDLE || sync_master_ctx.pair_state != SYNC_PAIR_STATE_IDLE) + { + APP_PRINT_INFO2("sync: fail to start pair, state %d, pair state %d!", sync_master_ctx.state, + sync_master_ctx.pair_state); + return SYNC_ERR_CODE_INVALID_STATE; + } + + memset(&sync_master_ctx, 0, sizeof(sync_master_ctx)); + sync_master_ctx.state = SYNC_STATE_SYNC_SLOW; + sync_master_ctx.pair_state = SYNC_PAIR_STATE_PAIRING; + sync_master_ctx.phase = SYNC_MASTER_PAIR_PHASE_SEND_REQ; + sync_master_ctx.seq_rx = 0xff; + sync_master_init_tx_fifo(); + sync_ppt_set_tifs(true); + sync_master_check_feature(); + + APP_PRINT_INFO0("sync: start pair!"); + sync_channel_change(0); + sync_acc_t acc = {.addr = SYNC_ACC_ADDR_BR}; + sync_acc_set(acc); + + uint16_t interval = SYNC_SYNC_SPEED; +#if SYNC_SUPPORT_MT1R + WR_PPT_REG_FIELD(PRO_FIELD_LENGTH, hp_field_length_3_0, SYNC_HEADER_LEN); + WR_PPT_REG_FIELD(PRO_HS_LENGTH, hs_field_length_4_0, 0); + sync_ppt_set_rf_time(); + if (sync_ctx.mt1r.flag) + { + interval = 125; + sync_ctx.conn_interval = 250; + sync_hw_frtimer_init(); + } +#endif + + sync_set_header(0, 0); + sync_pdu_t pdu; + pdu.opcode = SYNC_OPCODE_PAIR_REQ; + pdu.pair_req.interval = interval; + ppt_push_tx_data(sizeof(sync_opcode_t) + sizeof(sync_pair_req_t), (uint8_t *)&pdu); + + { + ppt_ptx_mode_ext_t param = + { + { + .ack_mode = true, + .periodic_mode = false, + .periodic_interval = SYNC_PAIR_SPEED / 125 - 1 + }, + .retransmit_times = 0xffff + }; + ppt_set_ptx_mode_ext(¶m); + } + sync_master_ctx.busy = true; + ppt_execute_instruction(PPT_HW_INSTRUCTION_PTX_ENABLE); + sync_hw_timer_start(SYNC_PAIR_SPEED, sync_master_handle_sync_slow_early); + return SYNC_ERR_CODE_SUCCESS; +} + +sync_err_code_t sync_master_connect(sync_bond_info_t *bond_info) +{ + if (bond_info == NULL) + { + return SYNC_ERR_CODE_NULL_POINTER; + } + if (sync_master_ctx.state != SYNC_STATE_IDLE) + { + APP_PRINT_INFO1("sync: fail to start connect, state %d!", sync_master_ctx.state); + return SYNC_ERR_CODE_INVALID_STATE; + } + + memset(&sync_master_ctx, 0, sizeof(sync_master_ctx)); + sync_master_ctx.state = SYNC_STATE_SYNC_SLOW; + sync_master_ctx.pair_state = SYNC_PAIR_STATE_PAIRED; + sync_master_ctx.acc_data = bond_info->acc; + sync_master_ctx.seq_rx = 0xff; + sync_master_init_tx_fifo(); + sync_ppt_set_tifs(true); + sync_master_check_feature(); + + APP_PRINT_INFO1("sync: start connect 0x%08x!", bond_info->acc.addr); + sync_channel_change(0); + sync_acc_set(sync_master_ctx.acc_data); + + uint16_t interval = SYNC_SYNC_SPEED; +#if SYNC_SUPPORT_MT1R + WR_PPT_REG_FIELD(PRO_FIELD_LENGTH, hp_field_length_3_0, SYNC_HEADER_LEN); + WR_PPT_REG_FIELD(PRO_HS_LENGTH, hs_field_length_4_0, 0); + sync_ppt_set_rf_time(); + if (sync_ctx.mt1r.flag) + { + interval = 125; + sync_ctx.conn_interval = 250; + sync_hw_frtimer_init(); + } +#endif + + sync_set_header(0, 0); + sync_pdu_t pdu; + pdu.opcode = SYNC_OPCODE_CONN_REQ; + pdu.conn_req.interval = interval; + ppt_push_tx_data(sizeof(sync_opcode_t) + sizeof(sync_conn_req_t), (uint8_t *)&pdu); + + { + ppt_ptx_mode_ext_t param = + { + { + .ack_mode = true, + .periodic_mode = false, + .periodic_interval = SYNC_SYNC_SLOW_SPEED / 125 - 1 + }, + .retransmit_times = 0xffff + }; + ppt_set_ptx_mode_ext(¶m); + } + sync_master_ctx.busy = true; + ppt_execute_instruction(PPT_HW_INSTRUCTION_PTX_ENABLE); + sync_hw_timer_start(SYNC_SYNC_SLOW_SPEED, sync_master_handle_sync_slow_early); + return SYNC_ERR_CODE_SUCCESS; +} + +void sync_master_stop(void) +{ + if (sync_master_ctx.state == SYNC_STATE_IDLE) + { + return; + } + + uint32_t lock = sync_enter_critical(); + sync_master_ctx.state = SYNC_STATE_IDLE; + sync_hw_timer_stop(); + sync_master_close(); + sync_master_msg_sending_free(); +#if SYNC_SUPPORT_POWER_CONTROL + if (sync_ctx.tx_power_adaptive) + { + sync_power_ctrl_stop(); + } +#endif +#if SYNC_SUPPORT_MT1R + ppt_reg_handler(sync_master_ppt_isr_handler); +#endif + memset(&sync_master_ctx, 0, sizeof(sync_master_ctx)); + if (sync_ctx.rte_req_cb) + { + sync_ctx.rte_req_cb(false); + } + sync_exit_critical(lock); + APP_PRINT_INFO0("sync: stopped!"); +} + +void sync_master_deinit(void) +{ + +} + +PPT_API_SECTION static bool sync_master_dlps_check(uint32_t *wakeup_time_diff) +{ + //APP_PRINT_ERROR4("sync: dlps check, state %d, pair state %d, hb slow %d busy %d", + // sync_master_ctx.state, sync_master_ctx.pair_state, + // sync_master_ctx.hb.slow, sync_master_ctx.busy); + + if (sync_master_ctx.state == SYNC_STATE_IDLE && + sync_master_ctx.pair_state == SYNC_PAIR_STATE_IDLE) + { + return true; + } + + if (sync_master_ctx.state == SYNC_STATE_SYNC && + sync_master_ctx.pair_state == SYNC_PAIR_STATE_PAIRED && + sync_master_ctx.hb.slow && sync_master_ctx.busy == false) + { +#if SYNC_SUPPORT_MT1R + if (sync_master_ctx.quick.enable) + { + if (sync_master_ctx.hb.sleep) + { + return true; + } + if (sync_master_ctx.hb.sleep_cal) + { + return false; + } + time_debug_level_high(TIME_DEBUG_CHAN_DLPS); + sync_master_ctx.hb.time_left1 = sync_hw_timer_get_left(); + sync_master_ctx.hb.sleep_time = sync_native_time_read(); + time_debug_level_low(TIME_DEBUG_CHAN_DLPS); + if (sync_hw_timer_check_pending()) + { + return false; + } + sync_master_ctx.hb.time_left = sync_master_ctx.hb.ce_cnt >= sync_master_ctx.quick.ce_cnt ? + sync_master_ctx.hb.ce_cnt - sync_master_ctx.quick.ce_cnt : 0x10000 - sync_master_ctx.quick.ce_cnt + + sync_master_ctx.hb.ce_cnt; + sync_master_ctx.hb.time_left *= 1000; + sync_master_ctx.hb.time_left += 625 + sync_master_ctx.hb.time_left1 - sync_master_ctx.quick.count * + 125; + //APP_PRINT_ERROR4("sync: dlps check, time left %dus, hw left %d, ce %d, count %d", + // sync_master_ctx.hb.time_left, sync_master_ctx.hb.time_left1, sync_master_ctx.quick.ce_cnt, + // sync_master_ctx.quick.count); + if (sync_master_ctx.hb.time_left <= SYNC_MASTER_HB_SLEEP_MIN_PERIOD_MT1R) + { + return false; + } + *wakeup_time_diff = us_to_rtc_clk(sync_master_ctx.hb.time_left - SYNC_MASTER_HB_SLEEP_OH, ROUND); + sync_hw_timer_stop(); + sync_master_ctx.hb.sleep = true; + return true; + } + else +#endif + { + sync_master_ctx.hb.time_left = sync_hw_timer_get_left(); + //APP_PRINT_ERROR1("sync: dlps check, time left %dus", sync_master_ctx.hb.time_left); + if (sync_master_ctx.hb.time_left <= SYNC_MASTER_HB_SLEEP_MIN_PERIOD) + { + return false; + } + sync_master_ctx.hb.sleep_clk = platform_rtc_get_counter(); + *wakeup_time_diff = us_to_rtc_clk(sync_master_ctx.hb.time_left, ROUND); + time_debug_level_high(TIME_DEBUG_CHAN_DLPS); + time_debug_level_low(TIME_DEBUG_CHAN_DLPS); + return true; + } + } + + return false; +} + +PPT_API_SECTION static void sync_master_dlps_mac_enter(void) +{ +#if SYNC_SUPPORT_MT1R + sync_master_ctx.hb.sleep_mac = true; +#endif +} + +PPT_API_SECTION static void sync_master_dlps_mac_exit(void) +{ +#if SYNC_SUPPORT_MT1R + if (sync_master_ctx.state == SYNC_STATE_SYNC && + sync_master_ctx.pair_state == SYNC_PAIR_STATE_PAIRED && + sync_master_ctx.hb.slow && sync_master_ctx.busy == false) + { + if (sync_master_ctx.quick.enable) + { + time_debug_level_high(TIME_DEBUG_CHAN_DLPS); + uint64_t wakeup_time = sync_native_time_read(); + time_debug_level_low(TIME_DEBUG_CHAN_DLPS); + uint32_t sleep_us = wakeup_time - sync_master_ctx.hb.sleep_time; + bool rte_req = sync_master_ctx.hb.time_left <= sleep_us + SYNC_MASTER_HB_SLEEP_MIN_PERIOD_MT1R; + uint32_t sleep_counter = 0; + sync_master_ctx.hb.oversleep = sync_master_ctx.hb.time_left <= sleep_us; + sync_master_ctx.hb.time_left = sleep_us; + sleep_us += 12; + if (sleep_us >= sync_master_ctx.hb.time_left1) + { + sleep_us -= sync_master_ctx.hb.time_left1; + sleep_counter += 1; + } + sleep_counter += sleep_us / 125 + sync_master_ctx.quick.count; + sleep_us = sleep_us % 125; + sync_master_ctx.hb.time_left1 = sleep_us; + sync_master_ctx.quick.ce_cnt += sleep_counter >> 3; + sync_master_ctx.quick.count = sleep_counter & 0x7; + sync_master_ctx.hb.sleep = false; + sync_master_ctx.hb.sleep_mac = false; + sync_master_ctx.hb.sleep_cal = true; + time_debug_level_high(TIME_DEBUG_CHAN_DLPS); + if (sleep_us == 0) + { + sync_master_ctx.quick.count -= 1; + sync_master_handle_sync_early_hb_quick(); + } + else + { + if (sleep_us >= 110) + { + sync_master_ctx.quick.count += 1; + if (sync_master_ctx.quick.count == 8) + { + sync_master_ctx.quick.count = 0; + sync_master_ctx.quick.ce_cnt += 1; + } + sync_hw_timer_start(250 - sleep_us, sync_master_handle_sync_early_hb_quick); + } + else + { + sync_hw_timer_start(125 - sleep_us, sync_master_handle_sync_early_hb_quick); + } + } + time_debug_level_low(TIME_DEBUG_CHAN_DLPS); + if (rte_req) + { + if (sync_ctx.rte_req_cb) + { + sync_ctx.rte_req_cb(true); + } + } + } + } +#endif +} + +PPT_API_SECTION static void sync_master_dlps_enter(void) +{ + +} + +PPT_API_SECTION static void sync_master_dlps_exit(void) +{ + // Pad_Config(P1_0, PAD_SW_MODE, PAD_IS_PWRON, PAD_PULL_DOWN, PAD_OUT_ENABLE, + // PAD_OUT_LOW); + // Pad_Config(P1_0, PAD_SW_MODE, PAD_IS_PWRON, PAD_PULL_DOWN, PAD_OUT_ENABLE, + // PAD_OUT_HIGH); + //APP_PRINT_ERROR4("sync: dlps exit, state %d, pair state %d, hb slow %d busy %d", + // sync_master_ctx.state, sync_master_ctx.pair_state, + // sync_master_ctx.hb.slow, sync_master_ctx.busy); + uint32_t lock = sync_enter_critical(); + if (sync_master_ctx.state == SYNC_STATE_SYNC && + sync_master_ctx.pair_state == SYNC_PAIR_STATE_PAIRED && + sync_master_ctx.hb.slow && sync_master_ctx.busy == false) + { +#if SYNC_SUPPORT_MT1R + if (sync_master_ctx.quick.enable == false) +#endif + { + time_debug_level_high(TIME_DEBUG_CHAN_DLPS); + time_debug_level_low(TIME_DEBUG_CHAN_DLPS); + uint32_t last_sleep_clk = sync_master_ctx.hb.sleep_clk; + uint32_t last_wakeup_clk = platform_rtc_get_counter(); + uint32_t sleep_us = rtc_clk_to_us(clk_cnt_diff(last_sleep_clk, last_wakeup_clk, BIT64(32)), ROUND); + //APP_PRINT_INFO2("sync: dlps exit, sleep %dus, time left %dus", sleep_us, + // sync_master_ctx.hb.time_left); + if (sleep_us >= sync_master_ctx.hb.time_left) + { + sync_hw_timer_stop(); + sync_master_handle_hb_to(); + } + else + { + sync_hw_timer_start(sync_master_ctx.hb.time_left - sleep_us, sync_master_handle_hb_to); + } + } + } + sync_exit_critical(lock); + //Pad_Config(P1_0, PAD_SW_MODE, PAD_IS_PWRON, PAD_PULL_DOWN, PAD_OUT_ENABLE, + // PAD_OUT_LOW); +} + +void sync_master_dlps_init(void) +{ + ppt_dlps_init(); + ppt_dlps_reg_mac_check_cb(sync_master_dlps_check); + ppt_dlps_reg_mac_enter_cb(sync_master_dlps_mac_enter); + ppt_dlps_reg_mac_exit_cb(sync_master_dlps_mac_exit); + ppt_dlps_reg_pf_enter_cb(sync_master_dlps_enter); + ppt_dlps_reg_pf_exit_cb(sync_master_dlps_exit); +} diff --git a/bee/drivers/ppt/sync/src/ppt_sync_pendcall.c b/bee/drivers/ppt/sync/src/ppt_sync_pendcall.c new file mode 100644 index 00000000..2410e74a --- /dev/null +++ b/bee/drivers/ppt/sync/src/ppt_sync_pendcall.c @@ -0,0 +1,41 @@ +/** +***************************************************************************************** +* Copyright(c) 2020, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file ppt_sync_pendcall.c + * @brief Source file for sync protocol. + * @details + * @author bill + * @date 2022-03-15 + * @version v0.1 + * ************************************************************************************* + */ + +/* Add Includes here */ +#include "ppt_sync_pendcall.h" +#include "zephyr/kernel.h" +#include "os_mem.h" + +typedef struct { + struct k_work work; + sync_pendcall_t func; + void *para1; + uint32_t para2; +} sync_work_t; + +static void sync_work_cb(struct k_work *item) +{ + sync_work_t *psync_work = CONTAINER_OF(item, sync_work_t, work); + psync_work->func(psync_work->para1, psync_work->para2); + os_mem_free(psync_work); +} + +void sync_pendcall(sync_pendcall_t func, void *para1, uint32_t para2) +{ + sync_work_t *psync_work = (sync_work_t *)os_mem_alloc(RAM_TYPE_DATA_ON, sizeof(sync_work_t)); + k_work_init(&psync_work->work, sync_work_cb); + psync_work->func = func; + psync_work->para1 = para1; + psync_work->para2 = para2; + k_work_submit(&psync_work->work); +} diff --git a/bee/drivers/ppt/sync/src/ppt_sync_pendcall.h b/bee/drivers/ppt/sync/src/ppt_sync_pendcall.h new file mode 100644 index 00000000..26bf715b --- /dev/null +++ b/bee/drivers/ppt/sync/src/ppt_sync_pendcall.h @@ -0,0 +1,67 @@ +/** +***************************************************************************************** +* Copyright(c) 2020, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file ppt_sync_pendcall.h + * @brief Head file for sync protocol. + * @details data structs and external functions declaration. + * @author bill + * @date 2022-03-15 + * @version v0.1 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _PPT_SYNC_PENDCALL_H_ +#define _PPT_SYNC_PENDCALL_H_ + +/* Add Includes here */ +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** @addtogroup PPT_SYNC_Driver + * @{ + */ + +/** @defgroup PPT_SYNC_Driver_Exported_Macros Exported Macros + * @brief + * @{ + */ + +/** @} End of PPT_SYNC_Driver_Exported_Macros */ + +/** @defgroup PPT_SYNC_Driver_Exported_Types Exported Types + * @brief + * @{ + */ + +typedef void (*sync_pendcall_t)(void *para1, uint32_t para2); + +/** @} End of PPT_SYNC_Driver_Exported_Types */ + +/** @defgroup PPT_SYNC_Driver_Exported_Functions Exported Functions + * @brief + * @{ + */ + +/** + * @brief pend the function to execute + * @param[in] func: pend call + * @param[in] para1: pointer parameter + * @param[in] para2: normal parameter + * @return none + */ +void sync_pendcall(sync_pendcall_t func, void *para1, uint32_t para2); + +/** @} End of PPT_SYNC_Driver_Exported_Functions */ + +/** @} End of PPT_SYNC_Driver */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/bee/drivers/ppt/sync/src/ppt_sync_slave.c b/bee/drivers/ppt/sync/src/ppt_sync_slave.c new file mode 100644 index 00000000..ddf74700 --- /dev/null +++ b/bee/drivers/ppt/sync/src/ppt_sync_slave.c @@ -0,0 +1,1937 @@ +/** +***************************************************************************************** +* Copyright(c) 2020, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file ppt_sync_slave.c + * @brief Source file for sync protocol. + * @details + * @author bill + * @date 2022-03-15 + * @version v0.1 + * ************************************************************************************* + */ + +/* Add Includes here */ +#include +#include "ppt_simple.h" +#include "ppt_sync_int.h" +#include "ppt_sync_slave.h" +//#include "trace.h" +#include "os_sync.h" +#include "os_timer.h" +#include "utils.h" + +LOG_MODULE_REGISTER(ppt_sync_slave, PPT_SYNC_LOG_LEVEL); + +#define SYNC_SLAVE_CCA_ENABLE 1 +#if SYNC_SLAVE_CCA_ENABLE == 0 +//#define SYNC_SLAVE_FIXED_CHANNEL 3 +#endif + +#define SYNC_SLAVE_TX_MSG_NUM 3 + +#define SYNC_RX_MSG_QUEUE_SIZE 16 +#define SYNC_RX_MSG_QUEUE_DATA_LEN 16 + +#define SYNC_SLAVE_TEST_RX_STOP 0 + +#define SYNC_SLAVE_TIME_DEBUG_RX -1 +#define SYNC_SLAVE_TIME_DEBUG_REQ_ACK -1 +#define SYNC_SLAVE_TIME_DEBUG_ALL_ACK -3 +#define SYNC_SLAVE_TIME_DEBUG_SEQ_ACK -2 +#define SYNC_SLAVE_TIME_DEBUG_REFRESH_ACK -4 +#define SYNC_SLAVE_TIME_DEBUG_UPDATE_ACK -5 + +typedef enum +{ + SYNC_SLAVE_PAIR_PHASE_WAIT_REQ, + SYNC_SLAVE_PAIR_PHASE_SEND_RSP, + SYNC_SLAVE_PAIR_PHASE_WAIT_CFM, + SYNC_SLAVE_PAIR_PHASE_SEND_ACK +} sync_slave_pair_phase_t; + +typedef enum +{ + SYNC_SLAVE_HB_STATE_IDLE, + SYNC_SLAVE_HB_STATE_HB_RECEIVED +} sync_slave_hb_state_t; + +struct +{ + sync_state_t state; + sync_pair_state_t pair_state; + uint8_t phase; + uint16_t count; + sync_acc_t acc_data; + bool ack; + uint8_t seq_tx; + uint8_t seq_rx; + uint32_t crc_rx; + sync_msg_t *pmsg_sending[SYNC_SLAVE_TX_MSG_NUM]; + uint8_t pmsg_ptr[SYNC_SLAVE_TX_MSG_NUM]; + uint8_t pmsg_sending_idx; + bool pmsg_switching; + bool pmsg_last_empty; + struct + { + uint16_t interval; + sync_slave_hb_state_t state; + bool slow; + bool exit_pend; + bool interval_changed; + } hb; + volatile bool busy; //!< tx or rx ongoing + bool tx_trigger_pending; +#if SYNC_SUPPORT_MT1R + struct + { + bool enable; + uint16_t ce_cnt; + volatile uint8_t count; + int8_t slot_idx; + uint8_t ack_field[3]; + uint8_t req_ack_field[3]; + uint8_t ack_rsp_idx; + uint8_t ack_curr_idx; + uint8_t seq_ack_rx; + bool req_ack; + uint32_t rx_clk; + } quick; + uint32_t ce_clk; + bool rx_ok; +#endif +} sync_slave_ctx; + +#if SYNC_SUPPORT_MT1R +typedef struct +{ + int8_t rssi; + uint8_t len; + uint8_t data[SYNC_RX_MSG_QUEUE_DATA_LEN]; +} sync_rx_msg_t; + +typedef struct +{ + sync_rx_msg_t buffer[SYNC_RX_MSG_QUEUE_SIZE]; + volatile uint8_t head; + volatile uint8_t tail; +} sync_rx_msg_queue_t; + +sync_rx_msg_queue_t sync_rx_msg_queue; +static inline uint8_t sync_slave_get_ack_field(void); +static void sync_slave_handle_rx_task(void *para1, uint32_t para2); +#endif + +static void sync_slave_ppt_isr_handler(void); + +int8_t sync_slave_cca_get(uint8_t start_idx, uint8_t num) +{ + APP_PRINT_INFO2("sync_slave_cca_get: start_idx=%d, num=%d",start_idx,num); + uint8_t idx = 0; + uint8_t count = 0; + uint8_t bank = 0; + int16_t rssi_min = 0; + uint8_t rssi_min_idx = 0; + PRO_CHANNEL_BANK_TYPE ch_bank = {.d16 = RD_PPT_REG(PRO_CHANNEL_BANK)}; + bank = ch_bank.bank; + for (count = 0; count < num; count++) + { + idx = start_idx + count; + sync_ctx.chan_cfg[idx].rssi = -128; + } + for (uint8_t loop = 0; loop < SYNC_CCA_TIMES; loop++) + { + for (count = 0; count < num; count++) + { + idx = start_idx + count; + ppt_clear_psd_result(); + if (ch_bank.bank != sync_ctx.chan_cfg[idx].bank) + { + ch_bank.bank = sync_ctx.chan_cfg[idx].bank; + WR_PPT_REG(PRO_CHANNEL_BANK, ch_bank.d16); + } + + ppt_psd_mode_ext_t param = + { + { + .chann_start = sync_ctx.chan_cfg[idx].channel, + .chann_stop = sync_ctx.chan_cfg[idx].channel, + .chann_step = 1, + .mode = 0, + .timeout = 0x3ff + } + }; + ppt_set_psd_mode_ext(¶m); + ppt_enable_psd(NULL); + int16_t rssi = ppt_get_psd_result(sync_ctx.chan_cfg[idx].channel); + //APP_PRINT_TRACE3("sync: cca loop %d %d %d", loop, idx, rssi); + if (rssi > sync_ctx.chan_cfg[idx].rssi) + { + sync_ctx.chan_cfg[idx].rssi = rssi; + } + } + } + + if (ch_bank.bank != bank) + { + ch_bank.bank = bank; + WR_PPT_REG(PRO_CHANNEL_BANK, ch_bank.d16); + } + + for (count = 0; count < num; count++) + { + idx = start_idx + count; + if (sync_ctx.chan_cfg[idx].rssi < rssi_min) + { + rssi_min = sync_ctx.chan_cfg[idx].rssi; + rssi_min_idx = idx; + } + } + + if (rssi_min >= -85) + { + APP_PRINT_WARN3("sync: cca ret %d %d %d", rssi_min_idx, sync_ctx.chan_cfg[rssi_min_idx].freq, + rssi_min); + } + return rssi_min_idx; +} + +static void sync_slave_close(bool quit_tx) +{ + ppt_kill_hw_fsm(PPT_FSM_PRX); + if (quit_tx) + { + /* not all cases need it */ + ppt_force_fw_ack(0); + } +} + +static void sync_slave_init_tx_fifo(void) +{ + ppt_set_tx_fifo_rdptr(0, PPT_TX_FIFO_SIZE - 1); + ppt_force_fw_ack(0); + ppt_flush_tx_fifo(0); +} + +static void sync_slave_free_sending_msg(void) +{ + for (uint8_t loop = 0; loop < SYNC_SLAVE_TX_MSG_NUM; loop++) + { + sync_msg_t *pmsg = sync_slave_ctx.pmsg_sending[loop]; + if (pmsg) + { + if (pmsg->send_cb) + { + pmsg->send_info.res = SYNC_SEND_RESULT_UNKNOWN; + sync_pendcall(sync_msg_handle_tx_done, pmsg, 0); + } + else + { + sync_ctx.msg_count[pmsg->type] -= 1; + plt_list_push(&sync_ctx.msg_free, pmsg); + } + sync_slave_ctx.pmsg_sending[loop] = NULL; + } + } +} + +void sync_slave_handle_hopping(void); +static void sync_slave_handle_hopping_task(void *para1, uint32_t para2) +{ + if (sync_slave_ctx.state != SYNC_STATE_SYNC_SLOW) + { + APP_PRINT_WARN1("sync: slow hopping, state invalid %d!", sync_slave_ctx.state); + return; + } + +#if SYNC_SLAVE_CCA_ENABLE + int8_t chan_next = sync_slave_cca_get(0, sync_ctx.chan_num); +#else + uint8_t chan_next = sync_rand() % sync_ctx.chan_num; +#endif + //APP_PRINT_TRACE1("sync: slow hopping, cca change to %d!", chan_next); + sync_channel_change(chan_next); + /* restart rx */ + ppt_execute_instruction(PPT_HW_INSTRUCTION_PRX_ENABLE); + sync_hw_timer_start(SYNC_SLAVE_HOPPING_SPEED, sync_slave_handle_hopping); +} + +void sync_slave_handle_hopping(void) +{ + sync_slave_close(false); + if (sync_slave_ctx.pair_state == SYNC_PAIR_STATE_PAIRING) + { + if (sync_slave_ctx.phase != SYNC_SLAVE_PAIR_PHASE_WAIT_REQ) + { + sync_slave_ctx.phase = SYNC_SLAVE_PAIR_PHASE_WAIT_REQ; + } + } + sync_pendcall(sync_slave_handle_hopping_task, 0, 0); +} + +static void sync_slave_handle_paired(void *para1, uint32_t para2) +{ + sync_bond_info_t bond_info; + bond_info.acc = sync_slave_ctx.acc_data; + sync_nvm_set_bond_info(&bond_info); + + if (sync_ctx.event_cb) + { + sync_ctx.event_cb(SYNC_EVENT_PAIRED); + } + if (sync_ctx.event_cb) + { + sync_ctx.event_cb(SYNC_EVENT_CONNECTED); + } +} + +static void sync_slave_handle_connected(void *para1, uint32_t para2) +{ + if (sync_ctx.event_cb) + { + sync_ctx.event_cb(SYNC_EVENT_CONNECTED); + } +} + +static void sync_slave_handle_disconnected(void *para1, uint32_t para2) +{ + if (sync_ctx.event_cb) + { + sync_ctx.event_cb(SYNC_EVENT_CONNECT_LOST); + } +} + +static void sync_slave_handle_exception(void) +{ + sync_slave_stop(); + sync_pendcall(sync_slave_handle_disconnected, 0, 0); +} + +#ifdef SYNC_DEBUG +static void sync_slave_handle_sync_lost(void *para1, uint32_t para2) +{ + if (sync_ctx.event_cb) + { + sync_ctx.event_cb(SYNC_EVENT_SYNC_LOST); + } +} + +static void sync_slave_handle_sync_reconnected(void *para1, uint32_t para2) +{ + if (sync_ctx.event_cb) + { + sync_ctx.event_cb(SYNC_EVENT_SYNC_RECONNECTED); + } +} +#endif + +void sync_slave_handle_sync_fast_to(void) +{ + sync_slave_close(true); + sync_slave_free_sending_msg(); +#if SYNC_SUPPORT_POWER_CONTROL + if (sync_ctx.tx_power_adaptive) + { + sync_power_ctrl_stop(); + } +#endif +#if SYNC_SUPPORT_MT1R + sync_hw_timer1_stop(); + ppt_reg_handler(sync_slave_ppt_isr_handler); +#endif + sync_slave_ctx.pair_state = SYNC_PAIR_STATE_IDLE; + sync_slave_ctx.state = SYNC_STATE_IDLE; + if (sync_ctx.rte_req_cb) + { + sync_ctx.rte_req_cb(false); + } + APP_PRINT_ERROR0("sync: disconnected!"); + sync_pendcall(sync_slave_handle_disconnected, 0, 0); +} + +static void sync_slave_handle_sync_lost_to_task(void *para1, uint32_t para2) +{ + if (sync_slave_ctx.state != SYNC_STATE_SYNC_FAST) + { + APP_PRINT_WARN1("sync: lost, state invalid %d!", sync_slave_ctx.state); + return; + } + + uint8_t chan_num, chan_start; + chan_num = sync_ctx.chan_num / sync_ctx.chan_group_num; + chan_start = (sync_ctx.chan_cur / chan_num) * chan_num; +#if SYNC_SLAVE_CCA_ENABLE + int8_t chan_next = sync_slave_cca_get(chan_start, chan_num); +#else + uint8_t chan_next = chan_start + sync_rand() % chan_num; +#endif + APP_PRINT_INFO2("sync: lost, cca change to %d[%d]!", chan_next, sync_ctx.chan_cfg[chan_next].freq); + sync_channel_change(chan_next); + /* restart rx */ + ppt_execute_instruction(PPT_HW_INSTRUCTION_PRX_ENABLE); + sync_hw_timer_start(SYNC_SYNC_FAST_PERIOD, sync_slave_handle_sync_fast_to); +} + +void sync_slave_handle_sync_lost_to(void) +{ + sync_slave_ctx.state = SYNC_STATE_SYNC_FAST; +#ifdef SYNC_SLAVE_FIXED_CHANNEL + APP_PRINT_INFO0("sync: lost!"); +#ifdef SYNC_DEBUG + sync_pendcall(sync_slave_handle_sync_lost, 0, 0); +#endif +#if SYNC_SUPPORT_SYNC_FAST_DISABLE + if (SYNC_SYNC_FAST_PERIOD == SYNC_SYNC_FAST_PERIOD_DISABLE) + { + sync_slave_handle_sync_fast_to(); + } + else +#endif + { + sync_hw_timer_start(SYNC_SYNC_FAST_PERIOD, sync_slave_handle_sync_fast_to); + } +#else +#if SYNC_SUPPORT_SYNC_FAST_DISABLE + if (SYNC_SYNC_FAST_PERIOD == SYNC_SYNC_FAST_PERIOD_DISABLE) + { + APP_PRINT_INFO0("sync: lost!"); +#ifdef SYNC_DEBUG + sync_pendcall(sync_slave_handle_sync_lost, 0, 0); +#endif + sync_slave_handle_sync_fast_to(); + } + else +#endif + { + /* stop rx */ + sync_slave_close(false); + sync_pendcall(sync_slave_handle_sync_lost_to_task, 0, 0); + } +#endif +} + +void sync_slave_handle_pair_cfm_to(void) +{ + sync_slave_ctx.phase = SYNC_SLAVE_PAIR_PHASE_WAIT_REQ; + APP_PRINT_INFO0("sync: back to pair!"); + + ppt_force_fw_ack(0); + sync_acc_t acc = {.addr = SYNC_ACC_ADDR_BR}; + sync_acc_set(acc); + sync_ppt_set_tifs(true); + + sync_set_header(0, 0); + sync_pdu_t pdu; + pdu.opcode = SYNC_OPCODE_PAIR_RSP; + pdu.pair_rsp.acc = sync_slave_ctx.acc_data; + ppt_push_tx_data(sizeof(sync_opcode_t) + sizeof(sync_pair_rsp_t), (uint8_t *)&pdu); + +#ifndef SYNC_SLAVE_FIXED_CHANNEL + sync_slave_handle_hopping(); +#endif +} + +PPT_API_SECTION void sync_slave_hb_exit(void) +{ + sync_slave_ctx.hb.slow = false; + sync_slave_ctx.hb.state = SYNC_SLAVE_HB_STATE_IDLE; + sync_slave_ctx.hb.exit_pend = false; + sync_hw_timer_start(SYNC_SYNC_LOST_PERIOD, sync_slave_handle_sync_lost_to); + APP_PRINT_INFO0("sync: hb exit"); + if (sync_ctx.hb_cb) + { + sync_hb_cb_param_t param = {}; + param.enter = false; + sync_ctx.hb_cb(¶m); + } +} + +PPT_ISR_SECTION void sync_slave_handle_tx_trigger(void) +{ + if (sync_slave_ctx.pair_state != SYNC_PAIR_STATE_PAIRED + || sync_slave_ctx.state != SYNC_STATE_SYNC) + { + return; + } + + if (sync_slave_ctx.hb.slow) + { + if (sync_slave_ctx.pmsg_sending[sync_slave_ctx.pmsg_sending_idx] == NULL) + { + if (sync_slave_ctx.busy == false) + { + sync_msg_t *pmsg = (sync_msg_t *)plt_list_pop(&sync_ctx.msg_send); + ppt_update_tx_fifo(0, pmsg->data, pmsg->len); + sync_slave_ctx.pmsg_sending[sync_slave_ctx.pmsg_sending_idx] = pmsg; + } + else + { + /* trigger latter after tx */ + sync_slave_ctx.tx_trigger_pending = true; + } + } + } +} + +PPT_ISR_SECTION void sync_slave_handle_ack(bool rx, sync_header_t rx_header) +{ + /* mark busy when send pkt immediately */ + sync_slave_ctx.busy = true; + + /* the old pkt is acked, just skip */ + if (sync_slave_ctx.pmsg_switching) + { + return; + } + + bool retrans = false; + uint8_t pmsg_sending_prev_idx = (sync_slave_ctx.pmsg_sending_idx + SYNC_SLAVE_TX_MSG_NUM - 1) % + SYNC_SLAVE_TX_MSG_NUM; + sync_msg_t *pmsg_sending_prev = sync_slave_ctx.pmsg_sending[pmsg_sending_prev_idx]; + if (pmsg_sending_prev && (rx == false || rx_header.ack == false)) + { + switch (pmsg_sending_prev->type) + { + case SYNC_MSG_TYPE_FINITE_RETRANS: + if (sync_ctx.msg_retrans_count < sync_ctx.msg_finite_retrans_num) + { + retrans = true; + } + break; + case SYNC_MSG_TYPE_INFINITE_RETRANS: + retrans = true; + break; + case SYNC_MSG_TYPE_DYNAMIC_RETRANS: + if (sync_ctx.msg_retrans_count < sync_ctx.msg_dynamic_retrans_num_lower || + (sync_ctx.msg_send.count == 0 && + (sync_ctx.msg_dynamic_retrans_num_upper == SYNC_MSG_RETRANS_NUM_INFINITE || + sync_ctx.msg_retrans_count < sync_ctx.msg_dynamic_retrans_num_upper))) + { + retrans = true; + } + break; + default: + break; + } + } + + if (retrans) + { + sync_ctx.msg_retrans_count += 1; + sync_set_header(rx, sync_slave_ctx.seq_tx); + sync_slave_ctx.pmsg_switching = false; + } + else + { +#if SYNC_SUPPORT_MT1R + if (sync_slave_ctx.quick.enable) + { + ppt_lock(0, true); + ppt_trigger_fw_ack_lock(0, false); + sync_slave_ctx.seq_tx += 1; + sync_slave_set_header(rx, sync_slave_ctx.seq_tx); + WR_PPT_REG_FIELD(PRO_HS_LENGTH, hs_field_length_4_0, SYNC_SUFFIX_LEN); + uint8_t ack_field = sync_slave_get_ack_field(); + WR_PPT_REG(PRO_HS_0_LOWER, ack_field); +#if TIME_DEBUG + if (ack_field == 0x7f) + { + time_debug_level_high(SYNC_SLAVE_TIME_DEBUG_ALL_ACK); + time_debug_level_low(SYNC_SLAVE_TIME_DEBUG_ALL_ACK); + } +#endif + ppt_lock(0, false); + } + else +#endif + { + uint8_t rd_ptr = ppt_trigger_fw_ack(0); + sync_slave_ctx.pmsg_ptr[sync_slave_ctx.pmsg_sending_idx] = rd_ptr; + sync_slave_ctx.pmsg_switching = true; + sync_slave_ctx.pmsg_last_empty = pmsg_sending_prev == NULL; + sync_slave_ctx.seq_tx += 1; + sync_set_header(rx, sync_slave_ctx.seq_tx); + } + + if (pmsg_sending_prev) + { + sync_msg_t *pmsg = pmsg_sending_prev; + sync_slave_ctx.pmsg_sending[pmsg_sending_prev_idx] = NULL; + if (pmsg->send_cb) + { + pmsg->send_info.res = rx ? (rx_header.ack ? SYNC_SEND_RESULT_ACKED : SYNC_SEND_RESULT_NACKED) : + SYNC_SEND_RESULT_UNKNOWN; + pmsg->send_info.retrans_count = sync_ctx.msg_retrans_count; + sync_pendcall(sync_msg_handle_tx_done, pmsg, 0); + } + else + { + sync_ctx.msg_count[pmsg->type] -= 1; + plt_list_push(&sync_ctx.msg_free, pmsg); + } + } + + sync_ctx.msg_retrans_count = 0; + uint8_t pmsg_sending_next_idx = (sync_slave_ctx.pmsg_sending_idx + 1) % SYNC_SLAVE_TX_MSG_NUM; + if (sync_ctx.msg_send.count == 0) + { + sync_pdu_t pdu; + pdu.opcode = SYNC_OPCODE_EMPTY; + DBG_DIRECT("ppt slave send empty data"); + ppt_push_tx_data(sizeof(sync_opcode_t), (uint8_t *)&pdu); + sync_slave_ctx.pmsg_sending[pmsg_sending_next_idx] = NULL; + } + else + { + sync_msg_t *pmsg = (sync_msg_t *)plt_list_pop(&sync_ctx.msg_send); + DBG_DIRECT("ppt slave send pmsg data"); + ppt_push_tx_fifo(0, pmsg->data, pmsg->len); + sync_slave_ctx.pmsg_sending[pmsg_sending_next_idx] = pmsg; + } + } + +#if SYNC_SUPPORT_POWER_CONTROL + if (sync_ctx.tx_power_adaptive) + { + sync_ctx.power_ctrl_count_fail += !(rx && rx_header.ack); + } +#endif +} + +PPT_ISR_SECTION void sync_slave_handle_rx(bool rx, sync_header_t rx_header, sync_pdu_t *rx_pdu, + uint16_t rx_len, int8_t rssi, uint32_t rx_crc) +{ + //APP_PRINT_ERROR5("sync: prx rx %d, header 0x%x, seq rx %d, len %d %b", rx, rx_header.value, sync_slave_ctx.seq_rx, rx_len, TRACE_BINARY(rx_len, rx_pdu)); + if (rx) + { + /* rx fail may due to interference, so can't exit hb */ + sync_slave_ctx.hb.state = SYNC_SLAVE_HB_STATE_IDLE; + bool seq_check = false; +#if SYNC_SUPPORT_MT1R + if (sync_slave_ctx.quick.enable) + { + if (sync_slave_ctx.seq_rx != rx_header.m.seq) + { + seq_check = true; + sync_slave_ctx.seq_rx = rx_header.m.seq; + } + } + else +#endif + { + if (sync_slave_ctx.seq_rx != rx_header.seq) + { + seq_check = true; + sync_slave_ctx.seq_rx = rx_header.seq; + } + } + if (seq_check) + { + sync_slave_ctx.crc_rx = rx_crc; + if (rx_len > 0) + { + if (rx_pdu->opcode >= SYNC_OPCODE_APP_START) + { +#if SYNC_SUPPORT_MT1R + if (sync_slave_ctx.quick.enable) + { + if (sync_rx_msg_queue.tail + 1 == sync_rx_msg_queue.head) + { + APP_PRINT_ERROR0("sync: rx full"); + } + else + { + if (rx_len <= SYNC_RX_MSG_QUEUE_DATA_LEN) + { + uint8_t idx = sync_rx_msg_queue.tail & (SYNC_RX_MSG_QUEUE_SIZE - 1); + sync_rx_msg_queue.buffer[idx].rssi = rssi; + sync_rx_msg_queue.buffer[idx].len = rx_len; + memcpy(sync_rx_msg_queue.buffer[idx].data, (uint8_t *)rx_pdu, rx_len); + sync_rx_msg_queue.tail += 1; + sync_pendcall(sync_slave_handle_rx_task, 0, 0); + } + else + { + APP_PRINT_ERROR1("sync: rx length exceed %d", rx_len); + } + } + } + else +#endif + { + if (sync_ctx.msg_receive_cb) + { + sync_receive_info_t info = {}; + info.rssi = rssi; + sync_ctx.msg_receive_cb((uint8_t *)rx_pdu, rx_len, &info); + } + } + } + else + { + bool handle = false; + switch (rx_pdu->opcode) + { + case SYNC_OPCODE_EMPTY: + if (rx_len == 1) + { + handle = true; + } + break; + case SYNC_OPCODE_HEARTBEAT: + if (rx_len == sizeof(sync_opcode_t) + sizeof(sync_heartbeat_t)) + { + handle = true; + if (rx_pdu->heartbeat.interval != 0) + { + if (sync_slave_ctx.hb.interval != rx_pdu->heartbeat.interval) + { + sync_slave_ctx.hb.interval_changed = true; + sync_slave_ctx.hb.interval = rx_pdu->heartbeat.interval; + } + sync_slave_ctx.hb.state = SYNC_SLAVE_HB_STATE_HB_RECEIVED; + } + else + { + APP_PRINT_ERROR0("sync: hb interval invalid"); + } + } + break; + default: + break; + } + if (handle == false) + { + APP_PRINT_WARN3("sync: rx unknown opcode %d, len %d, data %b", rx_pdu->opcode, rx_len, + TRACE_BINARY(rx_len, rx_pdu)); + } + } + } + } + } +} + +#if SYNC_SUPPORT_MT1R +static void sync_slave_handle_sync_lost_to_task_quick(void *para1, uint32_t para2) +{ + if (sync_slave_ctx.state != SYNC_STATE_SYNC_FAST) + { + APP_PRINT_WARN1("sync: lost, state invalid %d!", sync_slave_ctx.state); + return; + } + uint8_t chan_num, chan_start; + chan_num = sync_ctx.chan_num / sync_ctx.chan_group_num; + chan_start = (sync_ctx.chan_cur / chan_num) * chan_num; +#if SYNC_SLAVE_CCA_ENABLE + int8_t chan_next = sync_slave_cca_get(chan_start, chan_num); +#else + uint8_t chan_next = chan_start + sync_rand() % chan_num; +#endif + APP_PRINT_INFO2("sync: lost, cca change to %d[%d]!", chan_next, sync_ctx.chan_cfg[chan_next].freq); + sync_channel_change(chan_next); + + /* restart rx */ + ppt_execute_instruction(PPT_HW_INSTRUCTION_PRX_ENABLE); + sync_slave_ctx.count = 0; +} + +void sync_slave_handle_sync_lost_to_quick(void) +{ + sync_slave_ctx.state = SYNC_STATE_SYNC_FAST; + sync_slave_ctx.count = 0; + + APP_PRINT_INFO0("sync: lost!"); +#ifdef SYNC_DEBUG + sync_pendcall(sync_slave_handle_sync_lost, 0, 0); +#endif + +#if SYNC_SUPPORT_SYNC_FAST_DISABLE + if (SYNC_SYNC_FAST_PERIOD == SYNC_SYNC_FAST_PERIOD_DISABLE) + { + sync_hw_timer_stop(); + sync_hw_timer1_stop(); + sync_slave_handle_sync_fast_to(); + return; + } +#endif + +#ifndef SYNC_SLAVE_FIXED_CHANNEL + { + /* stop rx */ + sync_slave_close(false); + sync_pendcall(sync_slave_handle_sync_lost_to_task_quick, 0, 0); + } +#endif +} + +void sync_rx_msg_queue_clear(void) +{ + sync_rx_msg_queue.head = 0; + sync_rx_msg_queue.tail = 0; +} + +static void sync_slave_handle_rx_task(void *para1, uint32_t para2) +{ + while (sync_rx_msg_queue.tail != sync_rx_msg_queue.head) + { + uint8_t idx = sync_rx_msg_queue.head & (SYNC_RX_MSG_QUEUE_SIZE - 1); + if (sync_ctx.msg_receive_cb) + { + sync_receive_info_t info = {}; + info.rssi = sync_rx_msg_queue.buffer[idx].rssi; + sync_ctx.msg_receive_cb(sync_rx_msg_queue.buffer[idx].data, sync_rx_msg_queue.buffer[idx].len, + &info); + } + sync_rx_msg_queue.head += 1; + } +} + +static void sync_slave_close_quick(void) +{ + PRO_MISR_TYPE reg_misr; + reg_misr.d16 = RD_PPT_REG(PRO_MISR); + bool clear = reg_misr.tx_int == false && reg_misr.rx_int == false; + ppt_execute_instruction(PPT_HW_INSTRUCTION_PRX_DISABLE); + ppt_clear_radio(); + do + { + reg_misr.d16 = RD_PPT_REG(PRO_MISR); + } + while (reg_misr.kill_prx_int == 0); + WR_PPT_REG(PRO_MISR, BIT5); + if (clear) + { + ppt_flush_trx_int(); + } +} + + +PPT_ISR_SECTION static inline void sync_slave_init_ack_field(void) +{ + sync_slave_ctx.quick.seq_ack_rx = 1; + sync_slave_ctx.quick.ack_rsp_idx = 2; + sync_slave_ctx.quick.ack_curr_idx = 2; + sync_slave_ctx.quick.ack_field[2] = 0xff; +} + +PPT_ISR_SECTION static inline uint8_t sync_slave_get_ack_field(void) +{ + return sync_slave_ctx.quick.ack_field[sync_slave_ctx.quick.ack_rsp_idx]; +} + +PPT_ISR_SECTION static inline void sync_slave_refresh_ack_field(void) +{ + uint8_t num = (3 - sync_slave_ctx.quick.ack_rsp_idx + sync_slave_ctx.quick.ack_curr_idx) % 3 + 1; + if (num > 1) + { + time_debug_level_high(SYNC_SLAVE_TIME_DEBUG_REFRESH_ACK); + time_debug_level_low(SYNC_SLAVE_TIME_DEBUG_REFRESH_ACK); + if (num > 2) + { + time_debug_level_high(SYNC_SLAVE_TIME_DEBUG_REFRESH_ACK); + time_debug_level_low(SYNC_SLAVE_TIME_DEBUG_REFRESH_ACK); + } + } + + if (num < 3) + { + sync_slave_ctx.quick.ack_curr_idx = (sync_slave_ctx.quick.ack_curr_idx + 1) % 3; + } + else + { + uint8_t ack = sync_slave_ctx.quick.ack_field[sync_slave_ctx.quick.ack_curr_idx]; + if (ack) + { + uint8_t idx = (sync_slave_ctx.quick.ack_curr_idx + 2) % 3; + sync_slave_ctx.quick.ack_field[idx] = ack; + } + } + sync_slave_ctx.quick.ack_field[sync_slave_ctx.quick.ack_curr_idx] = 0; + if (SYNC_ISR_DEBUG) + { + APP_PRINT_WARN7("sync_isr: ack refresh ce %d, seq %d, rsp %d, curr %d, 0x%x 0x%x 0x%x", + sync_slave_ctx.quick.ce_cnt, sync_slave_ctx.quick.seq_ack_rx, + sync_slave_ctx.quick.ack_rsp_idx, sync_slave_ctx.quick.ack_curr_idx, + sync_slave_ctx.quick.ack_field[0], sync_slave_ctx.quick.ack_field[1], + sync_slave_ctx.quick.ack_field[2]); + } + +} + +PPT_ISR_SECTION static inline bool sync_slave_update_ack_field(uint8_t slot_idx, uint8_t seq_ack, + bool req_ack) +{ + bool ack = true; + uint32_t lock = sync_enter_critical(); + if (req_ack) + { + if (sync_slave_ctx.quick.seq_ack_rx != seq_ack) + { + sync_slave_ctx.quick.ack_rsp_idx = (sync_slave_ctx.quick.ack_rsp_idx + 1) % 3; + } + else + { + ack = false; + uint8_t num = (3 - sync_slave_ctx.quick.ack_rsp_idx + sync_slave_ctx.quick.ack_curr_idx) % 3 + 1; + if (num == 3) + { + time_debug_level_high(SYNC_SLAVE_TIME_DEBUG_UPDATE_ACK); + time_debug_level_low(SYNC_SLAVE_TIME_DEBUG_UPDATE_ACK); + uint8_t ack = sync_slave_ctx.quick.ack_field[sync_slave_ctx.quick.ack_curr_idx]; + sync_slave_ctx.quick.ack_curr_idx = (sync_slave_ctx.quick.ack_curr_idx + 2) % 3; + sync_slave_ctx.quick.ack_field[sync_slave_ctx.quick.ack_curr_idx] = ack; + } + } + } + else + { + sync_slave_ctx.quick.ack_field[sync_slave_ctx.quick.ack_curr_idx] |= BIT(slot_idx); + sync_slave_ctx.quick.ack_rsp_idx = sync_slave_ctx.quick.ack_curr_idx; + } + sync_slave_ctx.quick.seq_ack_rx = seq_ack; + sync_exit_critical(lock); + if (sync_slave_ctx.quick.seq_ack_rx & 0x1) + { + time_debug_level_high(SYNC_SLAVE_TIME_DEBUG_SEQ_ACK); + } + else + { + time_debug_level_low(SYNC_SLAVE_TIME_DEBUG_SEQ_ACK); + } + return ack; +} + +PPT_ISR_SECTION void sync_slave_handle_sync_early_delay(void) +{ + WR_PPT_REG_FIELD(PRO_TRX_CONTROL, ack_enable, 1); +} + +PPT_ISR_SECTION void sync_slave_handle_sync_early_quick(void) +{ + sync_slave_ctx.quick.count = (sync_slave_ctx.quick.count + 1) & 0x7; + if (sync_slave_ctx.quick.count == 0) + { + time_debug_level_low(TIME_DEBUG_CHAN_TIMING); + sync_slave_ctx.quick.ce_cnt += 1; + sync_slave_refresh_ack_field(); + WR_PPT_REG_FIELD(PRO_TRX_CONTROL, ack_enable, 0); + + time_debug_level_high(TIME_DEBUG_CHAN_TIMING); + sync_slave_ctx.rx_ok = false; + sync_slave_ctx.ce_clk = sync_hw_frtimer_get_count(); + } + else if (sync_slave_ctx.quick.count == 7) + { + if (sync_slave_ctx.rx_ok == false) + { + if (sync_slave_ctx.state == SYNC_STATE_SYNC) + { + sync_slave_ctx.count += 1; + uint32_t hb_time = sync_slave_ctx.count * SYNC_SYNC_SPEED; + if (sync_slave_ctx.hb.slow) + { + uint32_t hb_interval = SYNC_HB_TO_TIMES * sync_slave_ctx.hb.interval * 1000; + if (hb_time >= hb_interval + SYNC_SYNC_LOST_PERIOD) + { + sync_slave_handle_sync_lost_to_quick(); + } + else if (hb_time >= hb_interval) + { + sync_hw_timer_shift(-5); + } + } + else + { + if (hb_time >= SYNC_SYNC_LOST_PERIOD) + { + sync_slave_handle_sync_lost_to_quick(); + } + else if (sync_slave_ctx.count >= 2) + { + sync_hw_timer_shift(-5); + } + } + } + else if (sync_slave_ctx.state == SYNC_STATE_SYNC_FAST) + { + sync_slave_ctx.count += 1; + if (sync_slave_ctx.count >= SYNC_SYNC_FAST_PERIOD / SYNC_SYNC_SPEED) + { + sync_hw_timer_stop(); + sync_hw_timer1_stop(); + sync_slave_handle_sync_fast_to(); + } + } + } + else + { + sync_slave_ctx.count = 0; + } + } + else + { + if (sync_slave_ctx.quick.count == 6) + { + /* delay to start ack in case of ack at slot 5 */ + sync_hw_timer1_start(30, sync_slave_handle_sync_early_delay); + } + } +} + +PPT_ISR_SECTION static void sync_slave_ppt_isr_handler_quick(void) +{ + time_debug_level_high(TIME_DEBUG_CHAN_ISR); + PRO_MISR_TYPE reg_misr; + reg_misr.d16 = RD_PPT_REG(PRO_MISR); + //APP_PRINT_INFO1("sync_isr: prx isr 0x%04x", reg_misr.d16); + + if (reg_misr.rx_int) + { + do + { + /* pop rx stack */ + //PRO_LENGTH_INCLUDE_ADDON_TYPE len_inc_addon = {.d16 = RD_PPT_REG(PRO_LENGTH_INCLUDE_ADDON)}; + PRO_RX_STACK_TYPE rx_stack = {.d16 = RD_PPT_REG(PRO_RX_STACK)}; + if (rx_stack.is_max_length) + { + if (SYNC_ISR_DEBUG) + { + APP_PRINT_WARN0("sync_isr: prx rx max length"); + } + PRO_RX_HS_UPPER_TYPE rx_hs_upper = {.d16 = RD_PPT_REG(PRO_RX_HS_UPPER)}; //read 0x62 to pop rx stack + break; + } + + if (rx_stack.rx_time_out || rx_stack.rx_abort_rd) + { + PRO_RX_HS_UPPER_TYPE rx_hs_upper = {.d16 = RD_PPT_REG(PRO_RX_HS_UPPER)}; //read 0x62 to pop rx stack + break; + } + + PRO_RX_HP_TYPE hp = {.d16 = RD_PPT_REG(PRO_RX_HP)}; + bool rx = !(rx_stack.rx_time_out || rx_stack.rx_hit == false || rx_stack.is_crc_error); + sync_slave_ctx.rx_ok = rx; + sync_slave_ctx.busy = sync_slave_ctx.rx_ok; + + PRO_LENGTH_TYPE length = {.d16 = RD_PPT_REG(PRO_LENGTH)}; + PRO_ACCHIT_CLK_LOWER_TYPE acchit_clk_lower = {.d16 = RD_PPT_REG(PRO_ACCHIT_CLK_LOWER)}; + PRO_ACCHIT_CLK_UPPER_TYPE acchit_clk_upper = {.d16 = RD_PPT_REG(PRO_ACCHIT_CLK_UPPER)}; + uint32_t acchit_clk = (acchit_clk_upper.acchit_clk_31_16 << 16) + acchit_clk_lower.acchit_clk_15_0; + sync_slave_ctx.quick.rx_clk = acchit_clk; + int32_t clk_diff = 0; + /* determine slot only when rx success */ + bool ack_slot_flag = false; + sync_slave_ctx.quick.slot_idx = -1; + if (rx_stack.rx_time_out == false && rx_stack.rx_hit) + { + time_debug_level_high(SYNC_SLAVE_TIME_DEBUG_RX); + uint32_t lock = sync_enter_critical(); + do + { + //if (sync_slave_ctx.quick.count == 6 || sync_slave_ctx.quick.count == 7) + { + clk_diff = sync_hw_frtimer_time_diff(acchit_clk, sync_slave_ctx.ce_clk); + //APP_PRINT_ERROR3("DIFF %d %x %x", clk_diff, sync_slave_ctx.ce_clk, acchit_clk); + /* the acchit time is at least 30us */ + if (clk_diff < 30) + { + break; + } + clk_diff -= 30; + sync_slave_ctx.quick.slot_idx = clk_diff / 125; + /* ack slot */ + if (clk_diff < 750 || clk_diff >= 875) + { + break; + } + ack_slot_flag = true; + } + } + while (0); + sync_exit_critical(lock); + time_debug_level_low(SYNC_SLAVE_TIME_DEBUG_RX); +#if TIME_DEBUG + if (length.d16 != 1) + { + time_debug_level_high(SYNC_SLAVE_TIME_DEBUG_RX); + time_debug_level_low(SYNC_SLAVE_TIME_DEBUG_RX); + } +#endif + } + +#if SYNC_SLAVE_TEST_RX_STOP + bool switch_ptx = false; +#endif + sync_header_t rx_header; + rx_header.value = hp.hp; + if (rx) + { + /* check ack status */ + if (sync_slave_ctx.quick.slot_idx >= 0) + { + bool ack = sync_slave_update_ack_field(sync_slave_ctx.quick.slot_idx, rx_header.m.ack, + rx_header.m.req_ack); + rx_header.ack = ack; + } + + if (sync_slave_ctx.quick.slot_idx < 6 && ((sync_slave_ctx.quick.slot_idx & 0x1) == 0) && + rx_header.m.req_ack) + { + time_debug_level_high(SYNC_SLAVE_TIME_DEBUG_REQ_ACK); + time_debug_level_low(SYNC_SLAVE_TIME_DEBUG_REQ_ACK); + + //time_debug_level_high(TIME_DEBUG_CHAN_THREAD); + ppt_kill_hw_fsm(PPT_FSM_PRX); + //time_debug_level_low(TIME_DEBUG_CHAN_THREAD); + ppt_execute_instruction(PPT_HW_INSTRUCTION_PTX_ENABLE); + sync_slave_handle_ack(rx, rx_header); + sync_slave_ctx.quick.req_ack = true; +#if SYNC_SLAVE_TEST_RX_STOP + switch_ptx = true; +#endif + } + } + + /* only ack slot ptx pkt is used */ + if (rx && ack_slot_flag) + { + sync_slave_handle_ack(rx, rx_header); + + int32_t slot_shift = clk_diff - 750; + slot_shift -= 48; + if (ABS(slot_shift) > 2) + { + uint32_t lock = sync_enter_critical(); + sync_hw_timer_shift(slot_shift); + sync_exit_critical(lock); + } + } + + PRO_RX_CRC_LOWER_TYPE rx_crc_lower = {.d16 = RD_PPT_REG(PRO_RX_CRC_LOWER)}; + PRO_RX_CRC_UPPER_TYPE rx_crc_upper = {.d16 = RD_PPT_REG(PRO_RX_CRC_UPPER)}; + uint32_t rx_crc = (rx_crc_upper.d16 << 16) + rx_crc_lower.d16; + rx_crc >>= 32 - SYNC_CRC_LEN; + //PRO_RX_HS_LOWER_TYPE rx_hs_lower = {.d16 = RD_PPT_REG(PRO_RX_HS_LOWER)}; + PRO_RSSI_TYPE rssi = {.d16 = RD_PPT_REG(PRO_RSSI)}; + PRO_RX_HS_UPPER_TYPE rx_hs_upper = {.d16 = RD_PPT_REG(PRO_RX_HS_UPPER)}; //read 0x62 to pop rx stack + //PRO_INT_CTRL_TYPE int_ctrl = {.d16 = RD_PPT_REG(PRO_INT_CTRL)}; + if (SYNC_ISR_DEBUG) + { + APP_PRINT_INFO6("sync_isr: prx rx stack 0x%04x, ce %d, clk %d, slot %d, hp 0x%02x, len %d", + rx_stack.d16, + sync_slave_ctx.quick.ce_cnt, clk_diff, sync_slave_ctx.quick.slot_idx, hp.hp, length.d16); + } + + /* clear rx fifo */ + if (ack_slot_flag || rx == false) + { + uint16_t rx_len = rx ? length.d16 + SYNC_OVERHEAD_LEN : 0; + if (rx_len & 0x1) + { + rx_len += 1; + } + ACL_RX_FIFO_S rx_fifo_ptr = {.d32 = RD_U32_BZDMA_REG(BZDMA_REG_ACL_RXFIFO_PTR)}; + uint16_t fifo_len = BZDMA_ACL_RXFIFO_GET_LEFT(rx_fifo_ptr); + while (fifo_len > rx_len) + { + uint16_t pop_len = MIN(fifo_len - rx_len, PPT_RX_BUFFER_SIZE); + uint8_t *rx_buffer = ppt_get_rx_buffer(pop_len); + ppt_pop_rx_fifo(0, rx_buffer, pop_len); + fifo_len -= pop_len; + } + } + + if (rx) + { + uint16_t rx_len = length.d16 + SYNC_OVERHEAD_LEN; + uint8_t *rx_buffer = ppt_get_rx_buffer(rx_len); + ppt_pop_rx_fifo(0, rx_buffer, rx_len); +#if SYNC_SLAVE_TEST_RX_STOP + uint32_t rand = sync_rand() % 100; + if (rand < 30) + { + time_debug_level_high(TIME_DEBUG_CHAN_THREAD); + ppt_kill_hw_fsm(switch_ptx ? PPT_FSM_PTX : PPT_FSM_PRX); + time_debug_level_low(TIME_DEBUG_CHAN_THREAD); + time_debug_level_high(TIME_DEBUG_CHAN_THREAD); + ppt_execute_instruction(PPT_HW_INSTRUCTION_PRX_ENABLE); + time_debug_level_low(TIME_DEBUG_CHAN_THREAD); + WR_PPT_REG_FIELD(PRO_HS_LENGTH, hs_field_length_4_0, 0); + } + else +#endif + { + sync_pdu_t *pdu = (sync_pdu_t *)(rx_buffer + SYNC_OVERHEAD_LEN); + uint16_t buffer_head = rx_buffer[0] + (rx_buffer[1] << 8); + uint8_t buffer_len = ((buffer_head >> SYNC_HEADER_LEN_MT1R) & (0xffff >> (16 - SYNC_LENGTH_LEN))); + if (length.d16 != buffer_len) + { + APP_PRINT_INFO3("sync_isr: rx fifo corrupt, count %d, rx len %d, buffer len %d", + sync_slave_ctx.quick.count, length.d16, buffer_len); + break; + } + if (length.d16 == sizeof(sync_opcode_t) + sizeof(sync_conn_req_t) && + pdu->opcode == SYNC_OPCODE_CONN_REQ) + { + APP_PRINT_ERROR0("sync: state out of sync"); + sync_slave_handle_exception(); + break; + } + + sync_header_t rx_header; + rx_header.value = hp.hp; + int8_t rssi_dbm = ppt_get_rssi(rssi.rssi); + sync_slave_handle_rx(true, rx_header, pdu, length.d16, rssi_dbm, rx_crc); + } + } + else + { + if (ack_slot_flag) + { + sync_slave_close(false); + ppt_execute_instruction(PPT_HW_INSTRUCTION_PRX_ENABLE); + } + } + } + while (0); + } + + if (reg_misr.tx_int) + { + sync_slave_ctx.busy = false; + sync_slave_ctx.count = 0; + WR_PPT_REG_FIELD(PRO_HS_LENGTH, hs_field_length_4_0, 0); + /* pop tx stack */ + PRO_TX_STACK_TYPE tx_stack = {.d16 = RD_PPT_REG(PRO_TX_STACK)}; + PRO_TX_HS_LOWER_TYPE hs_lower = {.d16 = RD_PPT_REG(PRO_TX_HS_LOWER)}; + PRO_TX_HS_UPPER_TYPE hs_upper = {.d16 = RD_PPT_REG(PRO_TX_HS_UPPER)}; + PRO_TX_CLK_LOWER_TYPE tx_clk_lower = {.d16 = RD_PPT_REG(PRO_TX_CLK_LOWER)}; + PRO_TX_CLK_UPPER_TYPE tx_clk_upper = {.d16 = RD_PPT_REG(PRO_TX_CLK_UPPER)}; + PRO_TX_LENGTH_TYPE length = {.d16 = RD_PPT_REG(PRO_TX_LENGTH)}; // Read 0x6a to pop stack + + if (sync_slave_ctx.quick.req_ack) + { + sync_slave_ctx.quick.req_ack = false; + ppt_execute_instruction(PPT_HW_INSTRUCTION_PRX_ENABLE); + } + + uint32_t tx_clk = (tx_clk_upper.tx_clk_31_16 << 16) + tx_clk_lower.tx_clk_15_0; + uint32_t tx_delay = sync_hw_frtimer_time_elapse(tx_clk, sync_slave_ctx.quick.rx_clk); + + + uint32_t hs = (hs_upper.d16 << 16) + hs_lower.d16; + if (SYNC_ISR_DEBUG) + { + APP_PRINT_INFO8("sync_isr: prx tx stack 0x%04x(ptr %d), ce %d slot %d, delay %d hs 0x%x(0x%x), len %d", + tx_stack.d16, + tx_stack.tx_ptr, sync_slave_ctx.quick.ce_cnt, sync_slave_ctx.quick.slot_idx, + tx_delay, hs, sync_slave_get_ack_field(), length.tx_length); + } + if (hs != sync_slave_get_ack_field()) + { + if (SYNC_ISR_DEBUG) + { + APP_PRINT_WARN0("sync_isr: prx tx header fail"); + } + } + + sync_msg_t *pmsg = sync_slave_ctx.pmsg_sending[sync_slave_ctx.pmsg_sending_idx]; + //APP_PRINT_INFO3("sync: hb sending idx %d 0x%x, hb state %d", sync_slave_ctx.pmsg_sending_idx, pmsg, + // sync_slave_ctx.hb.state); + bool slow = false; + if (pmsg == NULL) + { + if (sync_slave_ctx.hb.state == SYNC_SLAVE_HB_STATE_HB_RECEIVED) + { + slow = true; + } + } + + if (slow) + { + if (sync_slave_ctx.hb.slow == false || sync_slave_ctx.hb.interval_changed) + { + sync_slave_ctx.hb.slow = true; + sync_slave_ctx.hb.interval_changed = false; + APP_PRINT_INFO1("sync: hb enter %dms", sync_slave_ctx.hb.interval); + if (sync_ctx.hb_cb) + { + sync_hb_cb_param_t param = {}; + param.enter = true; + param.interval = sync_slave_ctx.hb.interval; + sync_ctx.hb_cb(¶m); + } + } + } + else + { + if (sync_slave_ctx.hb.slow) + { + sync_slave_ctx.hb.slow = false; + sync_slave_ctx.hb.state = SYNC_SLAVE_HB_STATE_IDLE; + APP_PRINT_INFO0("sync: hb exit"); + if (sync_ctx.hb_cb) + { + sync_hb_cb_param_t param = {}; + param.enter = false; + sync_ctx.hb_cb(¶m); + } + } + } + sync_slave_ctx.pmsg_sending_idx = (sync_slave_ctx.pmsg_sending_idx + 1) % SYNC_SLAVE_TX_MSG_NUM; + + if (sync_slave_ctx.state == SYNC_STATE_SYNC && sync_slave_ctx.rx_ok) + { + //sync_hw_timer_set_periodic(false); + //sync_slave_handle_sync_early(); + } + } + + time_debug_level_low(TIME_DEBUG_CHAN_ISR); +} + +PPT_ISR_SECTION void sync_slave_handle_sync_early_first_quick(void) +{ + sync_hw_timer_start(125, sync_slave_handle_sync_early_quick); + sync_hw_timer_set_periodic(true); + sync_hw_timer_impr_ip(true); + ppt_reg_handler(sync_slave_ppt_isr_handler_quick); + sync_slave_ctx.quick.enable = true; + sync_slave_ctx.quick.count = 7; + sync_slave_ctx.quick.ce_cnt -= 1; + sync_slave_init_ack_field(); + WR_PPT_REG_FIELD(PRO_FIELD_LENGTH, hp_field_length_3_0, SYNC_HEADER_LEN_MT1R); + sync_slave_handle_sync_early_quick(); +} +#endif + +PPT_ISR_SECTION static void sync_slave_ppt_isr_handler(void) +{ + time_debug_level_high(TIME_DEBUG_CHAN_ISR); + PRO_MISR_TYPE reg_misr; + reg_misr.d16 = RD_PPT_REG(PRO_MISR); + //APP_PRINT_INFO1("sync_isr: prx isr 0x%04x", reg_misr.d16); + + if (reg_misr.rx_int) + { + do + { + /* pop rx stack */ + //PRO_LENGTH_INCLUDE_ADDON_TYPE len_inc_addon = {.d16 = RD_PPT_REG(PRO_LENGTH_INCLUDE_ADDON)}; + PRO_RX_STACK_TYPE rx_stack = {.d16 = RD_PPT_REG(PRO_RX_STACK)}; + if (rx_stack.is_max_length) + { + APP_PRINT_WARN0("sync_isr: prx rx max length"); + PRO_RX_HS_UPPER_TYPE rx_hs_upper = {.d16 = RD_PPT_REG(PRO_RX_HS_UPPER)}; //read 0x62 to pop rx stack + break; + } + + PRO_RX_HP_TYPE hp = {.d16 = RD_PPT_REG(PRO_RX_HP)}; + bool rx = !(rx_stack.rx_time_out || rx_stack.rx_hit == false || rx_stack.is_crc_error); + /* no need ack when rx fail */ + if (rx) + { + if (sync_slave_ctx.pair_state == SYNC_PAIR_STATE_PAIRED && + sync_slave_ctx.state != SYNC_STATE_SYNC_SLOW) + { + sync_header_t rx_header; + rx_header.value = hp.hp; + sync_slave_handle_ack(rx, rx_header); + + /* exit hb state if acked when pending */ + if (sync_slave_ctx.hb.slow && sync_slave_ctx.hb.exit_pend) + { + if (rx_header.ack) + { + sync_slave_hb_exit(); + } + } + } + } + +#if SYNC_SUPPORT_MT1R + PRO_ACCHIT_CLK_LOWER_TYPE acchit_clk_lower = {.d16 = RD_PPT_REG(PRO_ACCHIT_CLK_LOWER)}; + PRO_ACCHIT_CLK_UPPER_TYPE acchit_clk_upper = {.d16 = RD_PPT_REG(PRO_ACCHIT_CLK_UPPER)}; +#endif + PRO_RX_CRC_LOWER_TYPE rx_crc_lower = {.d16 = RD_PPT_REG(PRO_RX_CRC_LOWER)}; + PRO_RX_CRC_UPPER_TYPE rx_crc_upper = {.d16 = RD_PPT_REG(PRO_RX_CRC_UPPER)}; + uint32_t rx_crc = (rx_crc_upper.d16 << 16) + rx_crc_lower.d16; + rx_crc >>= 32 - SYNC_CRC_LEN; + //PRO_RX_HS_LOWER_TYPE rx_hs_lower = {.d16 = RD_PPT_REG(PRO_RX_HS_LOWER)}; + PRO_RSSI_TYPE rssi = {.d16 = RD_PPT_REG(PRO_RSSI)}; + PRO_LENGTH_TYPE length = {.d16 = RD_PPT_REG(PRO_LENGTH)}; + PRO_RX_HS_UPPER_TYPE rx_hs_upper = {.d16 = RD_PPT_REG(PRO_RX_HS_UPPER)}; //read 0x62 to pop rx stack + //PRO_INT_CTRL_TYPE int_ctrl = {.d16 = RD_PPT_REG(PRO_INT_CTRL)}; + if (SYNC_ISR_DEBUG) + { + APP_PRINT_INFO4("sync_isr: prx rx stack 0x%04x, rssi %d, hp 0x%02x, len %d", rx_stack.d16, + ppt_get_rssi(rssi.rssi), hp.hp, length.d16); + } + + if (rx) + { + uint16_t rx_len = length.d16 + SYNC_OVERHEAD_LEN; + uint8_t *rx_buffer = ppt_get_rx_buffer(rx_len); + ppt_pop_rx_fifo(0, rx_buffer, rx_len); + sync_pdu_t *pdu = (sync_pdu_t *)(rx_buffer + SYNC_OVERHEAD_LEN); + + if (sync_slave_ctx.pair_state == SYNC_PAIR_STATE_PAIRED) + { + bool handle_rx = true; + if (sync_slave_ctx.state == SYNC_STATE_SYNC) + { +#if SYNC_SUPPORT_MT1R + if (sync_slave_ctx.quick.enable == false) +#endif + { + sync_hw_timer_restart(); + } + } + else if (sync_slave_ctx.state == SYNC_STATE_SYNC_SLOW) + { + handle_rx = false; + if (length.d16 == sizeof(sync_opcode_t) + sizeof(sync_conn_req_t) && + pdu->opcode == SYNC_OPCODE_CONN_REQ) + { +#if SYNC_SUPPORT_MT1R + sync_ctx.mt1r.flag = pdu->conn_req.interval == 125; + sync_ctx.conn_interval = sync_ctx.mt1r.flag ? 250 : pdu->conn_req.interval; + if (sync_ctx.mt1r.flag) + { + sync_slave_ctx.ce_clk = (acchit_clk_upper.acchit_clk_31_16 << 16) + + acchit_clk_lower.acchit_clk_15_0; + } +#else + sync_ctx.conn_interval = pdu->conn_req.interval; +#endif + } + else + { + sync_slave_close(false); + ppt_execute_instruction(PPT_HW_INSTRUCTION_PRX_ENABLE); + } + } + else if (sync_slave_ctx.state == SYNC_STATE_SYNC_FAST) + { + APP_PRINT_INFO2("sync: reconnected on %d[%d]!", sync_ctx.chan_cur, + sync_ctx.chan_cfg[sync_ctx.chan_cur].freq); + sync_slave_ctx.state = SYNC_STATE_SYNC; + sync_hw_timer_start(SYNC_SYNC_LOST_PERIOD, sync_slave_handle_sync_lost_to); +#ifdef SYNC_DEBUG + sync_pendcall(sync_slave_handle_sync_reconnected, 0, 0); +#endif + } + + if (handle_rx) + { + if (length.d16 == sizeof(sync_opcode_t) + sizeof(sync_conn_req_t) && + pdu->opcode == SYNC_OPCODE_CONN_REQ) + { + APP_PRINT_ERROR0("sync: state out of sync"); + sync_slave_handle_exception(); + break; + } + + sync_header_t rx_header; + rx_header.value = hp.hp; + int8_t rssi_dbm = ppt_get_rssi(rssi.rssi); + sync_slave_handle_rx(true, rx_header, pdu, length.d16, + rssi_dbm, rx_crc); + } + } + else if (sync_slave_ctx.pair_state == SYNC_PAIR_STATE_PAIRING) + { + bool retry = true; + if (sync_slave_ctx.phase == SYNC_SLAVE_PAIR_PHASE_WAIT_REQ) + { + if (length.d16 == sizeof(sync_opcode_t) + sizeof(sync_pair_req_t) && + pdu->opcode == SYNC_OPCODE_PAIR_REQ) + { + int8_t rssi_dbm = ppt_get_rssi(rssi.rssi); + if (rssi_dbm < sync_ctx.pair_rssi_th) + { + APP_PRINT_ERROR2("sync: pair rssi check fail, %d < %d", rssi_dbm, sync_ctx.pair_rssi_th); + } + else + { + retry = false; + sync_slave_ctx.phase = SYNC_SLAVE_PAIR_PHASE_SEND_RSP; +#if SYNC_SUPPORT_MT1R + sync_ctx.mt1r.flag = pdu->pair_req.interval == 125; + sync_ctx.conn_interval = sync_ctx.mt1r.flag ? 250 : pdu->pair_req.interval; + if (sync_ctx.mt1r.flag) + { + sync_slave_ctx.ce_clk = (acchit_clk_upper.acchit_clk_31_16 << 16) + + acchit_clk_lower.acchit_clk_15_0; + } +#else + sync_ctx.conn_interval = pdu->pair_req.interval; +#endif + } + } + } + else if (sync_slave_ctx.phase == SYNC_SLAVE_PAIR_PHASE_WAIT_CFM) + { + if (length.d16 == sizeof(sync_opcode_t) && pdu->opcode == SYNC_OPCODE_PAIR_CONF) + { + retry = false; + sync_slave_ctx.phase = SYNC_SLAVE_PAIR_PHASE_SEND_ACK; + } + } + + if (retry) + { + sync_slave_close(false); + ppt_execute_instruction(PPT_HW_INSTRUCTION_PRX_ENABLE); + } + } + } + else + { + sync_slave_close(false); + ppt_execute_instruction(PPT_HW_INSTRUCTION_PRX_ENABLE); + } + } + while (0); + } + + if (reg_misr.tx_int) + { + sync_slave_ctx.busy = false; + /* pop tx stack */ + PRO_TX_STACK_TYPE tx_stack = {.d16 = RD_PPT_REG(PRO_TX_STACK)}; + //PRO_TX_HS_LOWER_TYPE hs_lower = {.d16 = RD_PPT_REG(PRO_TX_HS_LOWER)}; + //PRO_TX_HS_UPPER_TYPE hs_upper = {.d16 = RD_PPT_REG(PRO_TX_HS_UPPER)}; + PRO_TX_LENGTH_TYPE length = {.d16 = RD_PPT_REG(PRO_TX_LENGTH)}; // Read 0x6a to pop stack + if (SYNC_ISR_DEBUG) + { + APP_PRINT_INFO3("sync_isr: prx tx stack 0x%04x(ptr %d), len %d", tx_stack.d16, tx_stack.tx_ptr, + length.tx_length); + } + +#if SYNC_SUPPORT_POWER_CONTROL + if (sync_ctx.tx_power_adaptive) + { + sync_ctx.power_ctrl_count += 1; + } +#endif + + if (sync_slave_ctx.pair_state == SYNC_PAIR_STATE_PAIRING) + { + if (sync_slave_ctx.phase == SYNC_SLAVE_PAIR_PHASE_SEND_RSP) + { + APP_PRINT_INFO0("sync: pairing!"); + sync_slave_ctx.phase = SYNC_SLAVE_PAIR_PHASE_WAIT_CFM; + sync_hw_timer_start(SYNC_PAIR_CFM_PERIOD, sync_slave_handle_pair_cfm_to); + + sync_acc_set(sync_slave_ctx.acc_data); + ppt_trigger_fw_ack(0); + sync_ppt_set_tifs(false); + + sync_slave_ctx.seq_tx = 0; + /* ack is checked by master */ + sync_set_header(1, 0); + sync_pdu_t pdu; + pdu.opcode = SYNC_OPCODE_EMPTY; + ppt_push_tx_data(sizeof(sync_opcode_t), (uint8_t *)&pdu); + } + else if (sync_slave_ctx.phase == SYNC_SLAVE_PAIR_PHASE_SEND_ACK) + { + /* ack later in sync_slave_handle_ack */ + //ppt_trigger_fw_ack(0); + + sync_slave_ctx.seq_tx = 1; + sync_set_header(0, 0); + sync_pdu_t pdu; + pdu.opcode = SYNC_OPCODE_EMPTY; + ppt_push_tx_data(sizeof(sync_opcode_t), (uint8_t *)&pdu); + + sync_slave_ctx.pair_state = SYNC_PAIR_STATE_PAIRED; + sync_slave_ctx.state = SYNC_STATE_SYNC; + APP_PRINT_INFO3("sync: paired 0x%08x on %d[%d]!", sync_slave_ctx.acc_data.addr, sync_ctx.chan_cur, + sync_ctx.chan_cfg[sync_ctx.chan_cur].freq); +#if SYNC_SUPPORT_MT1R + if (sync_ctx.mt1r.flag) + { + uint32_t clk = sync_hw_frtimer_get_count(); + uint32_t total_time = SYNC_PAIR_CFM_PERIOD + SYNC_CONNECT_DELAY; + uint32_t delay = sync_hw_frtimer_time_elapse(clk, sync_slave_ctx.ce_clk); + delay += 29; + delay = total_time > delay ? total_time - delay : 30; + sync_hw_timer_start(delay, sync_slave_handle_sync_early_first_quick); + sync_hw_timer1_init(); + sync_ppt_set_rf_time_mt1r(); + sync_ctx.conn_interval = 1000; + APP_PRINT_ERROR0("sync: quick enter"); + } + else +#endif + { + sync_hw_timer_start(SYNC_SYNC_LOST_PERIOD, sync_slave_handle_sync_lost_to); + } + sync_pendcall(sync_slave_handle_paired, 0, 0); + sync_channel_print_statistic(); + sync_channel_clear_statistic(); +#if SYNC_SUPPORT_POWER_CONTROL + if (sync_ctx.tx_power_adaptive) + { + sync_power_ctrl_start(); + } +#endif + } + } + else if (sync_slave_ctx.pair_state == SYNC_PAIR_STATE_PAIRED) + { + if (sync_slave_ctx.state == SYNC_STATE_SYNC_SLOW) + { + /* ack later in sync_slave_handle_ack */ + //ppt_trigger_fw_ack(0); + sync_ppt_set_tifs(false); + + sync_slave_ctx.seq_tx = 0; + sync_set_header(0, 0); + sync_pdu_t pdu; + pdu.opcode = SYNC_OPCODE_EMPTY; + ppt_push_tx_data(sizeof(sync_opcode_t), (uint8_t *)&pdu); + + APP_PRINT_INFO2("sync: connected on %d[%d]!", sync_ctx.chan_cur, + sync_ctx.chan_cfg[sync_ctx.chan_cur].freq); + sync_slave_ctx.state = SYNC_STATE_SYNC; +#if SYNC_SUPPORT_MT1R + if (sync_ctx.mt1r.flag) + { + uint32_t clk = sync_hw_frtimer_get_count(); + uint32_t delay = sync_hw_frtimer_time_elapse(clk, sync_slave_ctx.ce_clk); + delay += 29; + delay = SYNC_CONNECT_DELAY > delay ? SYNC_CONNECT_DELAY - delay : 30; + sync_hw_timer_start(delay, sync_slave_handle_sync_early_first_quick); + sync_hw_timer1_init(); + sync_ppt_set_rf_time_mt1r(); + sync_ctx.conn_interval = 1000; + APP_PRINT_ERROR0("sync: quick enter"); + } + else +#endif + { + sync_hw_timer_start(SYNC_SYNC_LOST_PERIOD, sync_slave_handle_sync_lost_to); + } + sync_pendcall(sync_slave_handle_connected, 0, 0); + sync_channel_print_statistic(); + sync_channel_clear_statistic(); +#if SYNC_SUPPORT_POWER_CONTROL + if (sync_ctx.tx_power_adaptive) + { + sync_power_ctrl_start(); + } +#endif + } + else + { + uint8_t msg_idx = sync_slave_ctx.pmsg_sending_idx; + sync_msg_t *pmsg = sync_slave_ctx.pmsg_sending[msg_idx]; + //APP_PRINT_INFO3("sync: hb sending idx %d 0x%x, hb state %d", sync_slave_ctx.pmsg_sending_idx, pmsg, + // sync_slave_ctx.hb.state); + bool slow = false; + /* check if msg updated timely */ + if (sync_slave_ctx.pmsg_ptr[msg_idx] != tx_stack.tx_ptr + || (pmsg == NULL && sizeof(sync_opcode_t) != length.tx_length) + || (pmsg != NULL && pmsg->len != length.tx_length)) + { + APP_PRINT_WARN3("sync: pkt 0x%x not switched timely, tx ptr %d, pkt ptr %d", pmsg, tx_stack.tx_ptr, + sync_slave_ctx.pmsg_ptr[msg_idx]); + /* old pkt may also trigger enter hb */ + if (sync_slave_ctx.pmsg_last_empty && sync_slave_ctx.hb.state == SYNC_SLAVE_HB_STATE_HB_RECEIVED) + { + slow = true; + } + } + else + { + if (sync_slave_ctx.pmsg_switching) + { + sync_slave_ctx.pmsg_switching = false; + /* switch when new pkt is transmitted */ + sync_slave_ctx.pmsg_sending_idx = (sync_slave_ctx.pmsg_sending_idx + 1) % SYNC_SLAVE_TX_MSG_NUM; + } + + if (pmsg == NULL) + { + if (sync_slave_ctx.hb.state == SYNC_SLAVE_HB_STATE_HB_RECEIVED) + { + slow = true; + } + } + } + + if (slow) + { + sync_hw_timer_start(SYNC_HB_TO_TIMES * sync_slave_ctx.hb.interval * 1000 + SYNC_SYNC_LOST_PERIOD, + sync_slave_handle_sync_lost_to); + if (sync_slave_ctx.hb.slow == false || sync_slave_ctx.hb.interval_changed) + { + sync_slave_ctx.hb.slow = true; + sync_slave_ctx.hb.interval_changed = false; + APP_PRINT_INFO1("sync: hb enter %dms", sync_slave_ctx.hb.interval); + if (sync_ctx.hb_cb) + { + sync_hb_cb_param_t param = {}; + param.enter = true; + param.interval = sync_slave_ctx.hb.interval; + sync_ctx.hb_cb(¶m); + } + } + } + else + { + if (sync_slave_ctx.hb.slow) + { + if (sync_slave_ctx.hb.state != SYNC_SLAVE_HB_STATE_HB_RECEIVED) + { + sync_slave_hb_exit(); + } + else + { + /* exit only when acked if tx a message */ + sync_slave_ctx.hb.exit_pend = true; + } + } + } + + /* re-trigger at last in case the state is changed */ + if (sync_slave_ctx.tx_trigger_pending) + { + sync_slave_ctx.tx_trigger_pending = false; + sync_slave_handle_tx_trigger(); + } + } + } + } + + if (reg_misr.kill_prx_int) + { + ppt_clear_radio(); + WR_PPT_REG(PRO_MISR, BIT5); + ppt_flush_rx_fifo(); + ppt_ctx->fsm = PPT_FSM_STANDBY; + ppt_ctx->sync_flag = false; + } + + if (reg_misr.reset_trig_int) + { + ppt_clear_radio(); + WR_PPT_REG(PRO_MISR, BIT6); + ppt_flush_rx_fifo(); + ppt_ctx->fsm = PPT_FSM_STANDBY; + ppt_ctx->sync_flag = false; + } + time_debug_level_low(TIME_DEBUG_CHAN_ISR); +} + +void sync_slave_init(void) +{ + sync_ppt_init(); + ppt_reg_handler(sync_slave_ppt_isr_handler); + sync_hw_timer_init(); +#if defined(SYNC_DEBUG) || SYNC_SUPPORT_MT1R + sync_hw_frtimer_init(); +#endif + sync_ctx.role = SYNC_ROLE_SLAVE; + memset(&sync_slave_ctx, 0, sizeof(sync_slave_ctx)); +} + +void sync_slave_check_feature(void) +{ + sync_check_feature(); + if (sync_ctx.rte_req_cb) + { + sync_ctx.rte_req_cb(true); + } +} + +void sync_slave_enable(void) +{ + +} + +sync_err_code_t sync_slave_pair(void) +{ + if (sync_slave_ctx.state != SYNC_STATE_IDLE || sync_slave_ctx.pair_state != SYNC_PAIR_STATE_IDLE) + { + APP_PRINT_INFO2("sync: fail to start pair, state %d, pair state %d!", sync_slave_ctx.state, + sync_slave_ctx.pair_state); + return SYNC_ERR_CODE_INVALID_STATE; + } + + memset(&sync_slave_ctx, 0, sizeof(sync_slave_ctx)); + sync_slave_ctx.state = SYNC_STATE_SYNC_SLOW; + sync_slave_ctx.pair_state = SYNC_PAIR_STATE_PAIRING; + sync_slave_ctx.phase = SYNC_SLAVE_PAIR_PHASE_WAIT_REQ; + sync_slave_ctx.seq_rx = 0xff; + sync_slave_init_tx_fifo(); + sync_ppt_set_tifs(true); + sync_slave_check_feature(); +#if SYNC_SUPPORT_MT1R + WR_PPT_REG_FIELD(PRO_FIELD_LENGTH, hp_field_length_3_0, SYNC_HEADER_LEN); + WR_PPT_REG_FIELD(PRO_HS_LENGTH, hs_field_length_4_0, 0); + sync_ppt_set_rf_time(); +#endif +#ifdef SYNC_SLAVE_FIXED_CHANNEL + uint8_t chan_idx = SYNC_SLAVE_FIXED_CHANNEL; +#else +#if SYNC_SLAVE_CCA_ENABLE + int8_t chan_idx = sync_slave_cca_get(0, sync_ctx.chan_num); +#else + uint8_t chan_idx = sync_rand() % sync_ctx.chan_num; +#endif + sync_hw_timer_start(SYNC_SLAVE_HOPPING_SPEED, sync_slave_handle_hopping); +#endif + + APP_PRINT_INFO2("sync: start pair on %d[%d]!", chan_idx, sync_ctx.chan_cfg[chan_idx].freq); + sync_channel_change(chan_idx); + + sync_slave_ctx.acc_data = sync_acc_gen_data(); + sync_acc_t acc = {.addr = SYNC_ACC_ADDR_BR}; + sync_acc_set(acc); + + sync_set_header(0, 0); + sync_pdu_t pdu; + pdu.opcode = SYNC_OPCODE_PAIR_RSP; + pdu.pair_rsp.acc = sync_slave_ctx.acc_data; + ppt_push_tx_data(sizeof(sync_opcode_t) + sizeof(sync_pair_rsp_t), (uint8_t *)&pdu); + + { + ppt_prx_mode_ext_t param = + { + { + .ack_mode = true, + .continuous_mode = true + } + }; + ppt_set_prx_mode_ext(¶m); + } + + ppt_execute_instruction(PPT_HW_INSTRUCTION_PRX_ENABLE); + return SYNC_ERR_CODE_SUCCESS; +} + +sync_err_code_t sync_slave_connect(sync_bond_info_t *bond_info) +{ + if (bond_info == NULL) + { + return SYNC_ERR_CODE_NULL_POINTER; + } + + if (sync_slave_ctx.state != SYNC_STATE_IDLE) + { + APP_PRINT_INFO1("sync: fail to start connect, state %d!", sync_slave_ctx.state); + return SYNC_ERR_CODE_INVALID_STATE; + } + + memset(&sync_slave_ctx, 0, sizeof(sync_slave_ctx)); + sync_slave_ctx.state = SYNC_STATE_SYNC_SLOW; + sync_slave_ctx.pair_state = SYNC_PAIR_STATE_PAIRED; + sync_slave_ctx.seq_rx = 0xff; + sync_slave_init_tx_fifo(); + sync_ppt_set_tifs(true); + sync_slave_check_feature(); +#if SYNC_SUPPORT_MT1R + WR_PPT_REG_FIELD(PRO_FIELD_LENGTH, hp_field_length_3_0, SYNC_HEADER_LEN); + WR_PPT_REG_FIELD(PRO_HS_LENGTH, hs_field_length_4_0, 0); + sync_ppt_set_rf_time(); +#endif +#ifdef SYNC_SLAVE_FIXED_CHANNEL + uint8_t chan_idx = SYNC_SLAVE_FIXED_CHANNEL; +#else +#if SYNC_SLAVE_CCA_ENABLE + int8_t chan_idx = sync_slave_cca_get(0, sync_ctx.chan_num); +#else + uint8_t chan_idx = sync_rand() % sync_ctx.chan_num; +#endif + sync_hw_timer_start(SYNC_SLAVE_HOPPING_SPEED, sync_slave_handle_hopping); +#endif + + APP_PRINT_INFO3("sync: start connect 0x%08x on %d[%d]!", bond_info->acc.addr, chan_idx, + sync_ctx.chan_cfg[chan_idx].freq); + sync_channel_change(chan_idx); + + sync_slave_ctx.acc_data = bond_info->acc; + sync_acc_set(sync_slave_ctx.acc_data); + +#if SYNC_SUPPORT_MT1R + WR_PPT_REG_FIELD(PRO_FIELD_LENGTH, hp_field_length_3_0, SYNC_HEADER_LEN); + WR_PPT_REG_FIELD(PRO_HS_LENGTH, hs_field_length_4_0, 0); + sync_ppt_set_rf_time(); +#endif + + sync_set_header(0, 0); + sync_pdu_t pdu; + pdu.opcode = SYNC_OPCODE_CONN_RSP; + ppt_push_tx_data(sizeof(sync_opcode_t), (uint8_t *)&pdu); + + { + ppt_prx_mode_ext_t param = + { + { + .ack_mode = true, + .continuous_mode = true + } + }; + ppt_set_prx_mode_ext(¶m); + } + + ppt_execute_instruction(PPT_HW_INSTRUCTION_PRX_ENABLE); + return SYNC_ERR_CODE_SUCCESS; +} + +void sync_slave_stop(void) +{ + if (sync_slave_ctx.state == SYNC_STATE_IDLE) + { + return; + } + + uint32_t lock = sync_enter_critical(); + sync_hw_timer_stop(); +#if SYNC_SUPPORT_MT1R + sync_hw_timer1_stop(); + ppt_reg_handler(sync_slave_ppt_isr_handler); +#endif + sync_slave_close(true); + sync_slave_free_sending_msg(); +#if SYNC_SUPPORT_POWER_CONTROL + if (sync_ctx.tx_power_adaptive) + { + sync_power_ctrl_stop(); + } +#endif + memset(&sync_slave_ctx, 0, sizeof(sync_slave_ctx)); + if (sync_ctx.rte_req_cb) + { + sync_ctx.rte_req_cb(false); + } + sync_exit_critical(lock); + APP_PRINT_INFO0("sync: stopped!"); + return; +} + +void sync_slave_deinit(void) +{ + +} + +PPT_API_SECTION static bool sync_slave_dlps_check(uint32_t *wakeup_time_diff) +{ + if (sync_slave_ctx.state == SYNC_STATE_IDLE && + sync_slave_ctx.pair_state == SYNC_PAIR_STATE_IDLE) + { + return true; + } + + return false; +} + +void sync_slave_dlps_init(void) +{ + ppt_dlps_init(); + ppt_dlps_reg_mac_check_cb(sync_slave_dlps_check); +} diff --git a/bee/rtl87x2g/boot/inc/debug_port.h b/bee/rtl87x2g/boot/inc/debug_port.h new file mode 100644 index 00000000..1393eb52 --- /dev/null +++ b/bee/rtl87x2g/boot/inc/debug_port.h @@ -0,0 +1,81 @@ +/** +********************************************************************************************************* +* Copyright(c) 2021, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file debug_port.h +* @brief +* @details +* @author +* @date 2021-4-6 +* @version v1.0 +* ********************************************************************************************************* +*/ + + +#ifndef _DEBUG_PORT_H_ +#define _DEBUG_PORT_H_ + +#ifdef __cplusplus +extern "C" { +#endif +#include "rtl876x.h" + +typedef enum _t_debug_mode +{ + DIGI_DBG_SYSON, + DIGI_DBG_BT, + DIGI_DBG_PROCESSOR_SYS, + DIGI_DBG_APB_ADC, + DIGI_DBG_RTC, + + ANA_DBG_AUX_ADC = 0x10, + ANA_DBG_RF_TRXIQ_AFE_TRMK_ADC, + ANA_DBG_RF_TRANCERIVER +} T_DEBUG_MODE; + + +typedef enum _t_debug_pin_group +{ + DBG_PIN_GROUP_A, //mapping to debug_pin_table_a + DBG_PIN_GROUP_B, //mapping to debug_pin_table_b + DBG_PIN_GROUP_C, //mapping to debug_pin_table_c + DBG_PIN_GROUP_ALL_PAD = 0xff, +} T_PIN_GROUP; + +/** + * @brief Open the debug port mode on specific pins + * @param red_table_mask: the pin bit map used in the table debug_pin_table_red. + * @param black_table_mask: the pin bit map used in the table debug_pin_table_black. + * @param debug_mode: debug mode select from T_DEBUG_MODE + * @retval None + */ +extern void (*debug_port_open)(T_DEBUG_MODE debug_mode); + +/** + * @brief Close the debug mode + * @retval None + */ +void debug_port_close(void); + +/** + * @brief set debug mode on specific pins + * @param pin_group: the pin group selected. + * This parameter can be any combination of the following values: + * @arg DBG_PIN_GROUP_A : the digital debug pin bit 0 ~ 31 could be selected as below table. + * ADC_0, ADC_1, ADC_2, ADC_3, P1_0, P1_1, P2_0, P2_1, //digi_debug_0 ~ 7 + * P2_2, P2_3, P2_4, P2_5, P3_2, P3_3, MIC2_P, MIC2_N, //digi_debug_8 ~ 15 + * MICBIAS, LOUT_P, LOUT_N, P10_0 //digi_debug_16 ~ 19 + * @arg DBG_PIN_GROUP_B : the digital debug pin bit 0 ~ 31 could be selected as below table. + * MIC1_P, MIC1_N, //digi_debug_12 ~ 13 + * @retval None + */ +extern void (*debug_port_set_pin_bit_map)(T_PIN_GROUP pin_group, uint32_t dbg_bitmap); + +void debug_port_bt_mac(bool is_set); + +#ifdef __cplusplus +} +#endif + +#endif /* _DEBUG_PORT_H_ */ + diff --git a/bee/rtl87x2g/boot/inc/platform_rtc.h b/bee/rtl87x2g/boot/inc/platform_rtc.h new file mode 100644 index 00000000..498d54aa --- /dev/null +++ b/bee/rtl87x2g/boot/inc/platform_rtc.h @@ -0,0 +1,83 @@ +/** +********************************************************************************************************* +* Copyright(c) 2022, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************** +* @file platform_rtc.h +* @brief Platfrom RTC implementation head file. +* @details +* @author js.lin +* @date 2022-8-31 +* @version v0.1 +********************************************************************************************************* +*/ + +/*============================================================================* + * Define to prevent recursive inclusion + *============================================================================*/ +#ifndef __PLATFORM_RTC_H +#define __PLATFORM_RTC_H + +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#include +#include "rtl876x.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define PF_RTC_BIT_NUM BIT64(32) + +/*============================================================================* + * Types + *============================================================================*/ +/** @defgroup PLATFORM_RTC_Exported_Types Platform RTC Exported Types + * @{ + */ + +typedef enum PFRTCComparator +{ + PF_RTC_COMP0 = 0x01, + PF_RTC_COMP1 = 0x02, + PF_RTC_COMP2 = 0x04, + PF_RTC_COMP3 = 0x08, +} PFRTCComparator; + +/** @} */ /* End of group PLATFORM_RTC_Exported_Types */ + +/*============================================================================* + * Functions + *============================================================================*/ +/** @defgroup PLATFORM_RTC_Exported_Functions Platform RTC Exported Functions + * @{ + */ + +extern void (*platform_rtc_aon_init)(void); +extern void (*platform_rtc_non_aon_init)(void); +extern void (*platform_rtc_reset)(void); +extern void (*platform_rtc_run_cmd)(bool); +extern uint32_t (*platform_rtc_get_counter)(void); +extern void (*platform_rtc_set_comp_intr_config)(PFRTCComparator, bool, bool); +extern void (*platform_rtc_set_comp_wk_config)(PFRTCComparator, bool); +extern void (*platform_rtc_set_intr_group_config)(bool); +extern void (*platform_rtc_set_wk_group_config)(bool); +extern bool (*platform_rtc_get_intr_group_config)(void); +extern bool (*platform_rtc_get_wk_group_config)(void); +extern void (*platform_rtc_set_comp)(PFRTCComparator, uint32_t); +extern uint32_t (*platform_rtc_get_comp)(PFRTCComparator); +extern PFRTCComparator(*platform_rtc_get_comp_intr_status)(void); +extern PFRTCComparator(*platform_rtc_get_comp_wk_status)(void); +extern void (*platform_rtc_set_comp_manual_intr)(PFRTCComparator); +extern PFRTCComparator(*platform_rtc_get_comp_manual_intr)(void); +extern void (*platform_rtc_clear_comp_intr_status)(PFRTCComparator); +extern void (*platform_rtc_clear_comp_wk_status)(PFRTCComparator); + +/** @} */ /* End of group PLATFORM_RTC_Exported_Functions */ + +#ifdef __cplusplus +} +#endif + +#endif /* __PLATFORM_RTC_H */ diff --git a/bee/rtl87x2g/boot/inc/power_manager_slave.h b/bee/rtl87x2g/boot/inc/power_manager_slave.h new file mode 100644 index 00000000..f2484d09 --- /dev/null +++ b/bee/rtl87x2g/boot/inc/power_manager_slave.h @@ -0,0 +1,207 @@ +/** +***************************************************************************************** +* Copyright(c) 2022, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file power_manager_slave.h + * @brief Power Manager Slave implementation head file. + * @author George Chang, js.lin + * @date 2022-08-29 + * @version v1.0 + * ************************************************************************************* + */ + +/*============================================================================* + * Define to prevent recursive inclusion + *============================================================================*/ +#ifndef __POWER_MANAGER_SLAVE_H +#define __POWER_MANAGER_SLAVE_H + + +/*============================================================================* + * Header Files +*============================================================================*/ +#include +#include +#include "power_manager_interface.h" +#include "platform_rtc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define IRQ_TAG_FILL_WORD ( 0x5a5a5a5aU ) + +#define POWER_MANAGER_GET_TIMESTAMP(stamp) \ + do { \ + stamp = platform_rtc_get_counter(); \ + } while(0) + +#define POWER_MANAGER_GET_TIMEDIFF(start, end, diff) \ + do { \ + diff = clk_cnt_diff(start, end, PF_RTC_BIT_NUM); \ + } while(0) + +#define POWER_MANAGER_UPDATE_EXTREMUM(diff, diff_max, diff_min) \ + do { \ + diff_max = diff > diff_max ? diff : diff_max; \ + diff_min = diff < diff_min ? diff : diff_min; \ + } while(0) + +#define PM_SYSTEM_LEVEL_UNIT_NUM 2 + +/*============================================================================* + * Types +*============================================================================*/ +/** @defgroup POWER_MANAGER_Exported_Types Power Manager Exported Types + * @{ + */ +typedef PMCheckResult(*PMUnitCheckFunc)(uint32_t, uint32_t, uint32_t *); +typedef void (*PMUnitStoreFunc)(void); +typedef void (*PMUnitRestoreFunc)(void); +typedef void (*PMUnitEnterFunc)(void); +typedef void (*PMUnitExitFunc)(void); + +typedef PMCheckResult(*PMCheckWakeupTimeFunc)(uint32_t *); +typedef void (*PMFuncToReturn)(void); + +typedef enum +{ + PROFILING_PM_SLAVE_CHECK = 0, + PROFILING_PM_SLAVE_STORE = 1, + PROFILING_PM_SLAVE_ENTER = 2, + PROFILING_PM_SLAVE_EXIT = 3, + PROFILING_PM_SLAVE_RESTORE = 4, + PROFILING_PM_SLAVE_STAGE_MAX = 5 +} ProfilingPMSlaveStage; + +typedef struct +{ + uint32_t stage_start; + uint32_t stage_end; + uint32_t stage_time[PROFILING_PM_SLAVE_STAGE_MAX]; + uint32_t stage_time_max[PROFILING_PM_SLAVE_STAGE_MAX]; + uint32_t stage_time_min[PROFILING_PM_SLAVE_STAGE_MAX]; +} ProfilingPMSlaveData; + +typedef struct +{ + PMUnitCheckFunc check_func; + PMUnitStoreFunc store_func; + PMUnitRestoreFunc restore_func; + PMUnitEnterFunc enter_func; + PMUnitExitFunc exit_func; + + PMUnitID unit_id; + + ProfilingPMSlaveData *profiling_data; +} PowerManagerSlaveUnit; + +typedef struct +{ + PMUnitID unit_id; + uint32_t pon_delay_time; + uint32_t pon_stage_time; + uint32_t pof_delay_time; + uint32_t pof_stage_time; + uint32_t minimum_sleep_guard_time; +} PowerManagerSlaveRequestResource; + +typedef struct +{ + uint32_t start_time_diff; + uint32_t end_time_diff; +} PMTimePeriod; + +typedef struct +{ + uint32_t cur_clk; + PMTimePeriod occupied; +} PMOccupyTimeInfo; + +typedef struct +{ + PowerManagerSlaveUnit *unit_array[PM_SYSTEM_LEVEL_DEF_MAX][PM_SYSTEM_LEVEL_UNIT_NUM]; + + PMOccupyTimeInfo slave[PM_SYSTEM_LEVEL_DEF_MAX][PM_SYSTEM_LEVEL_UNIT_NUM]; + + uint32_t suspended; + + PMFuncToReturn func_to_return; +} PowerManagerSlaveSystem; + +typedef union +{ + uint8_t value; + struct + { + uint8_t profiling_mode: 1; + uint8_t irq_control_by_master: 1; + uint8_t m2s_inact_msg_dbg: 1; + uint8_t s2m_inact_msg_dbg: 1; + uint8_t m2s_act_msg_dbg: 1; + uint8_t s2m_act_msg_dbg: 1; + uint8_t rsvd: 2; + }; +} PowerManagerSlaveFeatureConfig; + +/*============================================================================* + * Variables +*============================================================================*/ +/** @defgroup POWER_MANAGER_Exported_Variables Power Manager Exported Variables + * @{ + */ +extern PowerManagerSlaveFeatureConfig power_manager_slave_feature_cfg; +extern PowerManagerSlaveSystem power_manager_slave_system; + +extern bool (*power_manager_slave_check)(const PMM2SInactivateMessage *); +extern void (*power_manager_slave_store_and_enter)(const PMM2SInactivateMessage *); +extern void (*power_manager_slave_exit_and_restore)(const PMM2SActivateMessage *); +extern void (*power_manager_slave_cpu_sleep)(bool); +extern bool (*power_manager_slave_check_interrupt_occur)(void); +extern void (*power_manager_slave_handle_irq)(bool, bool *); +extern void (*power_manager_slave_init)(void); + +extern uint32_t (*power_manager_slave_align_clk)(const uint32_t, uint32_t *, uint32_t *, uint32_t); +extern PMCheckResult(*power_manager_slave_align_wakeup_time)(PMCheckWakeupTimeFunc, const uint32_t, + uint32_t *); +extern void (*power_manager_slave_set_occupied_time_descending)(const uint32_t, + const PMOccupyTimeInfo *, PMTimePeriod *, uint8_t); +extern bool (*power_manager_slave_check_occupied_time)(const PMTimePeriod *, const uint8_t, + uint32_t *, uint32_t, uint32_t); +extern void (*power_manager_slave_register_resource)(PMUnitID, uint32_t, uint32_t, uint32_t); +extern void (*power_manager_slave_unregister_resource)(PMUnitID); +extern bool (*power_manager_slave_request_resource)(const uint32_t, uint32_t *, + PowerManagerSlaveRequestResource *); + +extern bool (*power_manager_slave_inact_msg_handler)(const PMM2SInactivateMessage *, bool *); +extern void (*power_manager_slave_act_msg_handler)(const PMM2SActivateMessage *); + +extern void (*power_manager_slave_inact_action_handler)(void); +extern void (*power_manager_slave_act_action_handler)(void); +/** @} */ /* End of group POWER_MANAGER_Exported_Variables */ + +/*============================================================================* + * Functions +*============================================================================*/ + +/** @defgroup POWER_MANAGER_Exported_Functions Power Manager Exported Functions + * @{ + */ +void power_manager_slave_register_function_to_return(PMFuncToReturn func); +void power_manager_slave_register_unit(PMUnitID unit_id, PowerManagerSlaveUnit *p_unit); +PowerManagerSlaveUnit *power_manager_slave_get_unit(PMUnitID unit_id); +void power_manager_slave_suspend_unit(PMUnitID unit_id); +void power_manager_slave_resume_unit(PMUnitID unit_id); +void power_manager_slave_suspend_all(void); +void power_manager_slave_resume_all(void); + +/** @} */ /* End of group POWER_MANAGER_Exported_Functions */ + +/** @} */ /* End of group POWER_MANAGER */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __POWER_MANAGER_SLAVE_H */