Files
hpw421/component/boot2/bsp/bsp_2_4G.c
T
2026-07-03 18:08:25 +08:00

713 lines
17 KiB
C

/*----------------------------------------------------------------------------------------------------
INCLUDE HEADE FILES
----------------------------------------------------------------------------------------------------*/
#include "Includes.h"
#include "bsp_2_4G.h"
#define AON_RF_AONREG ((volatile unsigned *)0x40002430)
#define RF_ANA02 ((volatile unsigned *)(0X4002F000 + 0x008))
#define RF_ANA03 ((volatile unsigned *)(0X4002F000 + 0x00C))
#define RF_ANA08 ((volatile unsigned *)(0X4002F000 + 0x020))
#define RF_ANA15 ((volatile unsigned *)(0X4002F000 + 0x03C))
#define RF_ANA21 ((volatile unsigned *)(0X4002F000 + 0x054))
#define RF_ANA26 ((volatile unsigned *)(0X4002F000 + 0x068))
#define RF_ANA27 ((volatile unsigned *)(0X4002F000 + 0x06C))
#define RF_ANA28 ((volatile unsigned *)(0X4002F000 + 0x070))
#define RF_ANA29 ((volatile unsigned *)(0X4002F000 + 0x074))
#define BT_RF_CTRL_SEL ((volatile unsigned *)(0X4002F000 + 0x0B8))
#define CPR_RF_REG0 ((volatile unsigned *)(0x40000000 + 0x1B0))
#define CPR_RF_REG1 ((volatile unsigned *)(0x40000000 + 0x1B4))
void delay_cn(uint32_t cn)
{
while (cn--)
__NOP();
}
/*! ********************************************************
* @name wbit
* @desc wbit
* *********************************************************/
static void wbit(uint16_t reg_addr, int end, int start, char *bit_str)
{
uint16_t reg_val = 0;
char ch = 0;
uint16_t i = 0;
uint16_t s_len = 0;
while (*(bit_str + s_len))
s_len++;
if (s_len != (end - start + 1))
while (1)
;
reg_val = *(uint16_t *)(0X4002F000 + reg_addr);
for (i = start; i <= end; i++)
{
int bit_idx = i - start;
ch = bit_str[(end - start) - bit_idx] - '0';
if (ch == 1)
setbit(reg_val, i);
else if (ch == 0)
clrbit(reg_val, i);
}
*(uint16_t *)(0X4002F000 + reg_addr) = reg_val;
}
/*! ********************************************************
* @name wbit
* @desc wbit
* *********************************************************/
static uint16_t rbit(uint16_t reg_addr)
{
return *(uint16_t *)(0X4002F000 + reg_addr);
}
/*! ********************************************************
* @name rf_rccali
* @desc rf rc filter calib
* *********************************************************/
void rf_rccalib(void)
{
static uint8_t rccalib_flag = 0;
if (rccalib_flag)
return;
uint32_t timeout = 0;
uint16_t val = 0;
wbit(0x0080, 10, 8, "111"); // RG_RCCAL_CTRL(Rccal 输出码值控制) def"100"
wbit(0x0080, 5, 5, "1"); // RG_RCCAL_RESETN=1
wbit(0x0080, 3, 3, "0"); // RG_RCCAL_SEL =0
wbit(0x0080, 2, 2, "1"); // RG_RCCAL_EN=1
wbit(0x0080, 4, 4, "1"); // RG_RCCAL_START=1
while (!(rbit(0x0084) & 0x8000))
{ // 等待AD_RCCAL_FINISH拉高 得出校准值 AD_RCCAL_CTRIM
if ((timeout++) > 0x10000)
break;
}
val = rbit(0x0084);
val = (val & 0x7FFF) >> 10; // 将校准值AD_RCCAL_CTRIM保存
wbit(0x0080, 3, 3, "1"); // RG_RCCAL_SEL =1
wbit(0x0080, 2, 2, "0"); // RG_RCCAL_EN=0
wbit(0x0080, 4, 4, "0"); // RG_RCCAL_START=0
char tb[6] = {0}; // 将保存的校准值转换成字符串
tb[4] = ((val & 0x01) ? '1' : '0');
tb[3] = ((val & 0x02) ? '1' : '0');
tb[2] = ((val & 0x04) ? '1' : '0');
tb[1] = ((val & 0x08) ? '1' : '0');
tb[0] = ((val & 0x10) ? '1' : '0');
wbit(0x0080, 15, 11, tb);
rccalib_flag = 1;
// printf("\nRG_RCCAL_CC:%X \n",rbit(0x80));
}
/*! ********************************************************
* @name reset_2_4g_modem
* @desc reset 2.4g modem
* *********************************************************/
void reset_2_4g_modem(void)
{
*CPR_RF_REG1 &= (~(1 << 21)); // reset
delay_cn(200);
*CPR_RF_REG1 |= (1 << 21); // unreset
delay_cn(200);
}
/*! ********************************************************
* @name _Ctune_Set
* @desc frequency offset tune
* *********************************************************/
void freq_tune(uint8_t tu)
{
*AON_RF_AONREG = (*AON_RF_AONREG & (~(0x3f << 20))) | ((tu & 0x3f) << 20); //- frequency offset
}
/**
* Copyright (c) 2022 - 2025, XinChip
*
* All rights reserved.
*
* Author :
*
*/
void config_2_4g_rf(void)
{
// uint32_t val;
// *((uint32_t volatile*)0x40000070) = 0x4000400; //- bt_pclk
// *((uint32_t volatile*)0x40002450)|= 0x1; //- open rf digital
//
// freq_tune(0x36); //- frequency offset
#if 1
*BT_RF_CTRL_SEL |= 0xE000; //- sel_24G_rfchan sel_24G_rfldoen sel_24G_rampout use 2.4G signal
/*2.4 ack
ana8<9:6> 0001 to 0000
ana15<3:1> 010 to 100
ana21<5:2> 1000 to 1011
ana2<12> 1 to 0
*/
*RF_ANA08 = *RF_ANA08 & (~0x3C0);
*RF_ANA15 = (*RF_ANA15 & (~0xE)) | 0x8;
*RF_ANA21 = (*RF_ANA21 & (~0x3c)) | 0x2c;
*RF_ANA02 &= (~0x1000);
#if _24G_CLK_SOURCE == CLK_BBPLL64M
// bbpll 64M
*RF_ANA26 |= 0xF000;
*RF_ANA27 |= 0x02;
*RF_ANA26 = (*RF_ANA26 & (~0x3F)) | 0x04;
#elif _24G_CLK_SOURCE == CLK_BBPLL96M
// bbpll 96M
*RF_ANA26 |= 0xF000;
*RF_ANA27 |= 0x02;
*RF_ANA26 = (*RF_ANA26 & (~0x3F)) | 0x06;
#endif
#if (TRANS_RATE == RATE_1M)
*RF_ANA21 = (*RF_ANA21 & (0xFFFF8FFF)) | 0x3000; //- tx dac gc def110 Optimization
#elif (TRANS_RATE == RATE_2M)
*RF_ANA21 = (*RF_ANA21 & (0xFFFF8FFF)) | 0x2000; //- tx dac gc def110 Optimization
#else
*RF_ANA21 = (*RF_ANA21 & (0xFFFF8FFF)) | 0x6000; //- tx dac gc def110 Optimization
#endif
#if (TRANS_RATE == RATE_2M)
*RF_ANA03 |= 0x01;
#endif
*RF_ANA29 |= 0x02; //- manual afc
*RF_ANA28 |= 0x01; //- afc pulse
reset_2_4g_modem();
#if _24G_CLK_SOURCE == CLK_BBPLL64M
*CPR_RF_REG1 = (*CPR_RF_REG1 & 0xFFFF3F0F) | 0x00C030; // enable 2.4G_mclk 2.4G_hclk 4div
//*CPR_RF_REG1 =(*CPR_RF_REG1&0xFFFF3F0F)|0x00C070;//enable 2.4G_mclk 2.4G_hclk 8div
#elif _24G_CLK_SOURCE == CLK_BBPLL96M
*CPR_RF_REG1 = (*CPR_RF_REG1 & 0xFFFF3F0F) | 0x00C050; // enable 2.4G_mclk 2.4G_hclk 6div
#endif
*CPR_RF_REG0 |= 0x600; // set 2.4G agc and iq from 2.4 modem
#endif
}
/**
* Copyright (c) 2022 - 2025, XinChip
*
* All rights reserved.
*
* Author :
*
*/
void set_power(uint8_t txgm)
{
*RF_ANA21 = (*RF_ANA21 & (~0xfc0)) | ((txgm & 0x3f) << 6);
}
/**
* Copyright (c) 2022 - 2025, XinChip
*
* All rights reserved.
*
* Author :
*
*/
void set_channel(uint16_t channel)
{
printf("%x\n", *RF_CH);
#if (TRANS_RATE == RATE_2M)
*RF_CH = ((*CFG_TOP & 0x01) ? (channel - 2) : channel);
#else
*RF_CH = ((*CFG_TOP & 0x01) ? (channel - 1) : channel);
#endif
printf("%x\n", *RF_CH);
delay_cn(200);
*RF_ANA28 &= (~0x1); //- afc pulse
delay_cn(200);
*RF_ANA28 |= 0x1; //- afc pulse
delay_cn(200);
}
/**
* Copyright (c) 2022 - 2025, XinChip
*
* All rights reserved.
*
* Author :
*
*/
void set_txaddr(uint32_t txaddr_l, uint32_t txaddr_h)
{
uint32_t val;
__write_hw_reg32(TX_ADDR_L, txaddr_l);
__read_hw_reg32(TX_ADDR_H, val);
__write_hw_reg32(TX_ADDR_H, (txaddr_h & 0xff) | (val & 0xffffff00));
}
/**
* Copyright (c) 2022 - 2025, XinChip
*
* All rights reserved.
*
* Author :
*
*/
void set_pipe0_rxaddr(uint32_t rxaddr_l, uint32_t rxaddr_h)
{
__write_hw_reg32(RX_ADDR_P0_L, rxaddr_l);
__write_hw_reg32(RX_ADDR_P0_H, rxaddr_h & 0xff);
}
/**
* Copyright (c) 2022 - 2025, XinChip
*
* All rights reserved.
*
* Author :
*
*/
void set_trx_addr_len(uint8_t len)
{
switch (len)
{
case 3:
__write_hw_reg32(SETUP_AW, 0xa5);
break;
case 4:
__write_hw_reg32(SETUP_AW, 0xaa);
break;
case 5:
__write_hw_reg32(SETUP_AW, 0xaf);
break;
}
}
/**
* Copyright (c) 2022 - 2025, XinChip
*
* All rights reserved.
*
* Author :
*
*/
void set_rate(uint8_t rate)
{
__write_hw_reg32(SETUP_RF, rate);
}
/**
* Copyright (c) 2022 - 2025, XinChip
*
* All rights reserved.
*
* Author :
*
*/
void set_feature(uint8_t long_pld, uint8_t fec, uint8_t whiten, uint8_t dpl, uint8_t ack_pay)
{
__write_hw_reg32(FEATURE, (long_pld << 5) | (fec << 4) | (whiten << 3) | (dpl << 2) | (ack_pay << 1));
}
/**
* Copyright (c) 2022 - 2025, XinChip
*
* All rights reserved.
*
* Author :
*
*/
void set_mode(uint8_t mode)
{
uint32_t val;
__read_hw_reg32(CFG_TOP, val); //
#if (TRANS_RATE == RATE_2M)
__write_hw_reg32(CFG_TOP, (val & (~0x1ffff3)) | (mode & 0x01) | 0x1b8672);
#else
__write_hw_reg32(CFG_TOP, (val & (~0x1ffff3)) | (mode & 0x01) | 0x0b8272);
#endif
}
/**
* Copyright (c) 2022 - 2025, XinChip
*
* All rights reserved.
*
* Author :
*
*/
void set_crc(uint8_t enable, uint8_t crc_bit)
{
uint32_t val;
__read_hw_reg32(CFG_TOP, val); //
if (enable)
{
if (crc_bit == CRC_1BIT)
{
__write_hw_reg32(CFG_TOP, (val | (~0x0C)) | 0x08);
}
else
{
__write_hw_reg32(CFG_TOP, val | 0x0C);
}
}
else
{
__write_hw_reg32(CFG_TOP, val & (~0x08));
}
}
/**
* Copyright (c) 2022 - 2025, XinChip
*
* All rights reserved.
*
* Author :
*
*/
void set_p012345_revlen(uint32_t p0123len, uint32_t p45len)
{
__write_hw_reg32(RX_PW_PX_L, p0123len);
__write_hw_reg32(RX_PW_PX_H, p45len);
}
/**
* Copyright (c) 2022 - 2025, XinChip
*
* All rights reserved.
*
* Author :
*
*/
void set_pipe0_revlen(uint8_t p0len)
{
*RX_PW_PX_L = (*RX_PW_PX_L & (~0xff)) | p0len;
}
void set_retry_cnt(uint8_t cnt)
{
*SETUP_RETR = (*SETUP_RETR & (~0x0f)) | cnt;
}
/**
* Copyright (c) 2022 - 2025, XinChip
*
* All rights reserved.
*
* Author :
*
*/
void send_cmd(uint8_t cmd)
{
nop();
__write_hw_reg32(CMD_BYTE, cmd | CMD_DONE);
nop();
}
/**
* Copyright (c) 2022 - 2025, XinChip
*
* All rights reserved.
*
* Author :
*
*/
void XC_AckPayload(uint8_t *txbuf, uint8_t len)
{
send_cmd(FLUSH_TX);
if (!((*STATUS_FIFO) & TX_FULL)) // tx FIFO is not full
{
send_cmd(W_ACK_PLOAD);
for (int i = 0; i < len; i++)
{
*TXFIFO_WDATA = txbuf[i];
nop();
}
}
}
void XC_TxPacket(uint8_t *txbuf, uint8_t len) // r
{
send_cmd(FLUSH_TX);
__write_hw_reg32(STATUS, ALL_IRQ_STATUS);
if (!((*STATUS_FIFO) & TX_FULL)) // tx FIFO is not full
{
send_cmd(W_TX_PLOAD);
for (int i = 0; i < len; i++)
{
*TXFIFO_WDATA = txbuf[i];
nop();
}
CE_High;
for (int i = 0; i < 0x1000; i++)
; // delay us
CE_Low;
}
}
/**
* Copyright (c) 2022 - 2025, XinChip
*
* All rights reserved.
*
* Author :
*
*/
uint8_t XC_RxPacket(uint8_t en_ack_pay, uint8_t *ack_pay_buf, uint8_t ack_len, uint8_t *rxbuf) // r
{
static uint8_t cnt = 0x01;
uint32_t status = 0, len = 0;
__read_hw_reg32(STATUS, status); // read status
if ((status & 0x0e) != 0x0e)
{
send_cmd(R_RX_PL_WID);
len = *RXFIFO_LEN & 0xFF; // pipe = (status & 0xe) >> 1;
for (int i = 0; i < 4; i++)
send_cmd(R_RX_PLOAD);
for (int i = 0; i < len; i++)
*(rxbuf + i) = *RXFIFO_RDTA;
ack_pay_buf[0] = cnt++;
switch (rxbuf[2])
{
case 1: // match packet
ack_pay_buf[4] = 0x02;
ack_pay_buf[5] = STATUS_OK;
break;
case 3: // bin info packet
ack_pay_buf[4] = 0x04;
// ack_pay_buf[5]=STATUS_OK;
ack_pay_buf[5] = info_24g.DataStatus;
break;
case 5: // bin packet
ack_pay_buf[4] = 0x05;
ack_pay_buf[5] = STATUS_OK;
break;
case 6: // ota result
ack_pay_buf[4] = 0x07;
ack_pay_buf[5] = info_24g.CheckStatus; // ack_pay_buf[5]=STATUS_OK;
break;
case 8: // ready
ack_pay_buf[4] = 0x09;
ack_pay_buf[5] = STATUS_READY;
break;
default:
break;
}
if (en_ack_pay)
XC_AckPayload(ack_pay_buf, ack_len); //
// if(en_ack_pay) XC_AckPayload(ack_pay_buf,5);//250K payload max 5
// if(en_ack_pay) XC_AckPayload(ack_pay_buf,32);//1M payload max 32
}
__write_hw_reg32(STATUS, ALL_IRQ_STATUS); // clear all status inter
send_cmd(FLUSH_RX);
return len;
}
/**
* Copyright (c) 2022 - 2025, XinChip
*
* All rights reserved.
*
* Author :
*
*/
void set_dynpd(uint8_t val)
{
__write_hw_reg32(DYNPD, val);
}
/**
* Copyright (c) 2022 - 2025, XinChip
*
* All rights reserved.
*
* Author :
*
*/
void go_rx(uint16_t ch)
{
uint8_t tv = *STATUS_FIFO;
if (((tv & 0x2) && (tv & 0x0C)))
{
printf("reset_2_4g_modem\n");
reset_2_4g_modem();
init_24G(RX_MODE);
}
else
{
send_cmd(FLUSH_RX);
set_mode(RX_MODE);
}
set_channel(ch);
}
void go_tx(uint16_t ch)
{
send_cmd(FLUSH_TX);
set_mode(TX_MODE);
set_channel(ch);
}
/**
* Copyright (c) 2022 - 2025, XinChip
*
* All rights reserved.
*
* Author :
*
*/
uint8_t wait_ack(uint8_t *ack_pay_buf, uint8_t *len, uint32_t timeout)
{
while (timeout--)
{
if ((*STATUS) & XC_TX_DS)
{
if (len != NULL)
*len = XC_RxPacket(0, NULL, 0, ack_pay_buf);
return 1; // rev ack
}
if ((*STATUS) & XC_MAX_RT)
{
return 0; // no rev ack
}
}
return 0; // no rev ack
}
/**
* Copyright (c) 2022 - 2025, XinChip
*
* All rights reserved.
*
* Author :
*
*/
void init_adv(uint8_t mode)
{
set_txaddr(0x71917d6b, 0); // tx addr 4byte
set_pipe0_rxaddr(0x71917d6b, 0); // rx pipe0 addr 4byte
set_trx_addr_len(4); // set trx addrlen is 4byte
set_rate(TRANS_RATE); // set rate
set_crc(DIS_CRC, CRC_2BIT);
set_feature(EN_LONG_PLD, DIS_FEC, DIS_WHITEN, DIS_DPL, DIS_ACK_PAY);
set_pipe0_revlen(BUFF_ADV_LENGTH); // set_p012345_revlen(0x2A2A2A2A,0x2A2A);//pipe0-1-2-3-4-pipe5 payload 42byte
set_mode(mode); // set tx or rx
set_power(POWER_LEVEL);
rf_rccalib(); // Initialization finally performs the calibration rc filter,This function is executed only once internally
}
/**
* Copyright (c) 2022 - 2025, XinChip
*
* All rights reserved.
*
* Author :
*
*/
void init_24G(uint8_t mode)
{
// set_retry_cnt(3);//set auto retransmit count
set_dynpd(0x3f); // enable dynamic payload
set_txaddr(0xE7E7C2E6, 0xC2); // tx addr 5byte
set_pipe0_rxaddr(0xE7E7C2E6, 0xC2); // rx pipe0 addr 5byte
set_trx_addr_len(5); // set trx addrlen is 5byte
set_rate(TRANS_RATE); // set rate
set_crc(EN_CRC, CRC_2BIT);
set_feature(DIS_LONG_PLD, EN_FEC, EN_WHITEN, EN_DPL, EN_ACK_PAY);
set_pipe0_revlen(BUFF_24G_LENGTH); // set_p012345_revlen(0x20202020,0x2020); //pipe0-1-2-3-4-pipe5 payload 32byte
set_mode(mode); // set tx or rx
set_power(POWER_LEVEL);
rf_rccalib(); // Initialization finally performs the calibration rc filter,This function is executed only once internally
}
/*******************************adv**********************************/
/**
* Copyright (c) 2022 - 2025, XinChip
*
* All rights reserved.
*
* Author :
*
*/
uint8_t reverseBits(uint8_t input)
{
uint8_t i = 0, temp = 0;
for (; i < 8; i++)
{
temp <<= 1;
temp = ((input >> i) & 0x01) ? (temp | 0x01) : (temp | 0x00);
}
return temp;
}
/**
* Copyright (c) 2022 - 2025, XinChip
*
* All rights reserved.
*
* Author :
*
*/
uint8_t bleWhitenStart(uint16_t Fre)
{
uint8_t chan = (Fre == RF_ADV_CHANNELS_38) ? 38 : ((Fre == RF_ADV_CHANNELS_37) ? 37 : 39);
return reverseBits(chan) | 2;
}
/**
* Copyright (c) 2022 - 2025, XinChip
*
* All rights reserved.
*
* Author :
*
*/
/*白化,LFSR的方式进行白化*/
void bleWhiten(uint8_t *data, uint8_t len, uint8_t whitenCoeff)
{
uint8_t m;
while (len--)
{
for (m = 1; m; m <<= 1)
{
if (whitenCoeff & 0x80)
{
whitenCoeff ^= 0x11;
(*data) ^= m;
}
whitenCoeff <<= 1;
}
*data = reverseBits(*data); // 新增 -- 翻转变量
data++;
}
}
/**
* Copyright (c) 2022 - 2025, XinChip
*
* All rights reserved.
*
* Author :
*
*/
void BLEcrc(const uint8_t *data, uint8_t dataLen, uint8_t *outputCRC)
{
// calculating the CRC based on a LFSR
uint8_t i, temp, tempData;
while (dataLen--)
{
tempData = *data++;
for (i = 0; i < 8; i++, tempData >>= 1)
{
temp = outputCRC[0] >> 7;
outputCRC[0] <<= 1;
if (outputCRC[1] & 0x80)
{
outputCRC[0] |= 1;
}
outputCRC[1] <<= 1;
if (outputCRC[2] & 0x80)
{
outputCRC[1] |= 1;
}
outputCRC[2] <<= 1;
if (temp != (tempData & 1))
{
outputCRC[2] ^= 0x5B;
outputCRC[1] ^= 0x06;
}
}
}
outputCRC[2] = reverseBits(outputCRC[2]);
outputCRC[1] = reverseBits(outputCRC[1]);
outputCRC[0] = reverseBits(outputCRC[0]);
}