/*
 * Copyright (c) 2021 Shanghai Panchip Microelectronics Co.,Ltd.
 *
 * SPDX-License-Identifier: Apache-2.0
 */
#include "comm_prf.h"
#include "pan_phy.h"
#include "pan_sys.h"

#define XN297_RX_TO_TX_TIME			(XN297_RX_TO_TX_TIME_VICE - PRTX_SPI_TRANS_TIME - PRTX_LEGENCY)
#define XN297_RX_TO_TX_TIME_VICE	(390)
#define PRTX_SPI_TRANS_TIME			(22)
#define PRTX_LEGENCY				(12)
#define PRTX_TRANS_TIME				(XN297_RX_TO_TX_TIME - 96)

#define XN297_TX_TO_RX_TIME			(XN297_TX_TO_RX_TIME_VICE - PTRX_SPI_TRANS_TIME)
#define XN297_TX_TO_RX_TIME_VICE	(381)
#define PTRX_SPI_TRANS_TIME			(29)
#define PTRX_TRANS_TIME				(XN297_TX_TO_RX_TIME - 59)

#define NRF_RX_TO_TX_TIME			(30)
#define NRF_TX_TO_RX_TIME			(30)


uint32_t data_addr_tx = 0;
uint32_t data_addr_rx = 0x20 * 4;
uint8_t prf_init_flag = 0;

void panchip_prf_isr_proc(void)
{
	uint8_t ptxprx = 0;     /* 0:ptx; 1:prx */
	uint8_t enhc = 0;       /* 0:norm; 1:enhc */
	uint8_t normal_m1 = 0;
	uint8_t noack = 0;
	uint8_t rx_header = 0;
	uint8_t noack_invert = 0;

	ptxprx = PRI_RF_IsRxSel(PRI_RF);
	enhc = PRI_RF_IsEnhance(PRI_RF);
	normal_m1 = (uint8_t)((PRI_RF->R04_RX_CTL & R04_RX_CTL_NORMAL_M1_Msk) >> R04_RX_CTL_NORMAL_M1_Pos);
	noack = PRI_RF_IsTxNoAckEn(PRI_RF);
	rx_header = (uint8_t)((PRI_RF->R04_RX_CTL & R04_RX_CTL_RX_HEADER0_Msk) >> R04_RX_CTL_RX_HEADER0_Pos);
	noack_invert = (uint8_t)((PRI_RF->R10_CFG & R10_CFG_NDC_ACK_SEL_Msk) >> R10_CFG_NDC_ACK_SEL_Pos);
	

	if (PRI_RF_IntFlag(PRI_RF, R11_CFG_PRI_TIMEOUT_IRQ_FLAG_Msk)
		&& !((PRI_RF->R01_INT & R01_INT_TX_RXACK_OUTTIME_IRQ_MASK_Msk) == R01_INT_TX_RXACK_OUTTIME_IRQ_MASK_Msk)) {
		while (!(PRI_RF->R01_INT & R01_INT_RX_DONE_IRQ_FLAG_Msk)) {
		}			/* wait rx done */
		ana_prf_ldo_dis();
		PRI_RF_SetTrxRamReady(PRI_RF, PRI_RF_MODE_SEL_TRX, 0);

		if (isr_cb.rx_timeout_cb != NULL) {
			(*isr_cb.rx_timeout_cb)();
		}
	}

	if (PRI_RF_IntFlag(PRI_RF, R11_CFG_PRI_RX_IRQ_FLAG_Msk)
		&& !((PRI_RF->R01_INT & R01_INT_RX_IRQ_MASK_Msk) == R01_INT_RX_IRQ_MASK_Msk)) {
		if (((enhc == 0) && (normal_m1 == 0) && ptxprx) || !ptxprx || (ptxprx && ((!noack_invert && !rx_header) || (noack_invert && rx_header)))) {
			while (!(PRI_RF->R01_INT & R01_INT_RX_DONE_IRQ_FLAG_Msk)) {
			}			/* wait rx done */
			ana_prf_ldo_dis();
			PRI_RF_SetTrxRamReady(PRI_RF, PRI_RF_MODE_SEL_TRX, 0);
		}
		if (isr_cb.rx_cb != NULL) {
			(*isr_cb.rx_cb)();
		}
	}

	if (PRI_RF_IntFlag(PRI_RF, R11_CFG_PRI_CRC_ERR_IRQ_FLAG_Msk)
		&& !((PRI_RF->R01_INT & R01_INT_RX_CRC_ERR_IRQ_MASK_Msk) == R01_INT_RX_CRC_ERR_IRQ_MASK_Msk)) {
		while (!(PRI_RF->R01_INT & R01_INT_RX_DONE_IRQ_FLAG_Msk)) {
		}			/* wait rx done */
		ana_prf_ldo_dis();
		PRI_RF_SetTrxRamReady(PRI_RF, PRI_RF_MODE_SEL_TRX, 0);

		if (isr_cb.rx_crc_err_cb != NULL) {
			(*isr_cb.rx_crc_err_cb)();
		}
	}

	if (PRI_RF_IntFlag(PRI_RF, R11_CFG_PRI_LENGTH_ERR_IRQ_FLAG_Msk)
		&& !((PRI_RF->R01_INT & R01_INT_PRI_RX_LNGTH_ERR_IRQ_MASK_Msk) == R01_INT_PRI_RX_LNGTH_ERR_IRQ_MASK_Msk)) {
        while (!(PRI_RF->R01_INT & R01_INT_RX_DONE_IRQ_FLAG_Msk)) {
		}			/* wait rx done */
		ana_prf_ldo_dis();
        PRI_RF_SetTrxRamReady(PRI_RF, PRI_RF_MODE_SEL_TRX, 0);

		if (isr_cb.rx_len_err_cb != NULL) {
			(*isr_cb.rx_len_err_cb)();
		}
    }
	
	if (PRI_RF_IntFlag(PRI_RF, R11_CFG_PRI_ACC_ADDR_ERR_IRQ_FLAG_Msk)
		&& !((PRI_RF->R01_INT & R01_INT_ACC_ADDR_ERR_MASK_Msk) == R01_INT_ACC_ADDR_ERR_MASK_Msk)) {
        while (!(PRI_RF->R01_INT & R01_INT_RX_DONE_IRQ_FLAG_Msk)) {
		}			/* wait rx done */
		ana_prf_ldo_dis();
        PRI_RF_SetTrxRamReady(PRI_RF, PRI_RF_MODE_SEL_TRX, 0);

		if (isr_cb.rx_acc_adr_err_cb != NULL) {
			(*isr_cb.rx_acc_adr_err_cb)();
		}
    }

	if ((PRI_RF->R01_INT & R01_INT_RX_PID_ERR_IRQ_FLAG_Msk)
		&& !((PRI_RF->R01_INT & R01_INT_RX_PID_ERR_IRQ_MASK_Msk) == R01_INT_RX_PID_ERR_IRQ_MASK_Msk)) {
		while (!(PRI_RF->R01_INT & R01_INT_RX_DONE_IRQ_FLAG_Msk)) {
		}			/* wait rx done */
		if (ptxprx == 0) {
			ana_prf_ldo_dis();
		}

		if (isr_cb.rx_pid_err_cb != NULL) {
			(*isr_cb.rx_pid_err_cb)();
		}
	}
	
	if ((PRI_RF_IntFlag(PRI_RF, R11_CFG_PRI_TX_DONE_IRQ_FLAG_Msk))
		&& !((PRI_RF->R01_INT & R01_INT_TX_DONE_IRQ_EN_Msk) == R01_INT_TX_DONE_IRQ_EN_Msk)) {
		if (((((enhc == 0) && (normal_m1 == 0)) || ((enhc == 1) && noack)) && !ptxprx) || ptxprx) {
			ana_prf_ldo_dis();
			PRI_RF_SetTrxRamReady(PRI_RF, PRI_RF_MODE_SEL_TRX, 0);
		}

		if (isr_cb.tx_cb != NULL) {
			(*isr_cb.tx_cb)();
		}
	}

	PRI_RF_ClearAllIrqEn(PRI_RF, ENABLE);
}


__ramfunc void LL_IRQHandler(void)
{
	/*prf isr handler*/
	panchip_prf_isr_proc();
}

__weak void panchip_prf_irq_enable(void)
{

}

__weak void panchip_prf_isr_init(void)
{

}


void panchip_prf_module_enable(pan_prf_config_t *p_config)
{	
	if(prf_init_flag == 0 || wake_from_lp_mode)
	{
		prf_init_flag = 1;
		panchip_prf_module_init();
	}
}

__weak void panchip_prf_set_phy(prf_phy_t phy)
{
	if(LE_1M == phy)
	{
		PRI_RF_WRITE_REG_VALUE(PRI_RF, R10_CFG, 250K_MODE_EN, DISABLE);
		PRI_RF_WRITE_REG_VALUE(PRI_RF, R00_CTL, BW_MODE, 0);  //0 1M; 1 2m
	}
	else if (LE_2M == phy)
	{
		PRI_RF_WRITE_REG_VALUE(PRI_RF, R10_CFG, 250K_MODE_EN, DISABLE);
		PRI_RF_WRITE_REG_VALUE(PRI_RF, R00_CTL, BW_MODE, 1);  //0 1M; 1 2m
    }
	else if(LE_250K == phy)
	{
		PRI_RF_WRITE_REG_VALUE(PRI_RF, R00_CTL, BW_MODE, 0);
		PRI_RF_WRITE_REG_VALUE(PRI_RF, R10_CFG, 250K_MODE_EN, ENABLE);
	}
	else if((PRF_PHY_CODED_S8 == phy) || (PRF_PHY_CODED == phy))
	{
		PRI_RF_WRITE_REG_VALUE(PRI_RF, R00_CTL, BW_MODE, 0);  //0 1M; 1 2m
		if(PRF_PHY_CODED_S8 == phy)
		{
			PRI_RF_WRITE_REG_VALUE(PRI_RF, R04_RX_CTL, PRI_CI_MODE, 0);
		}
		else if(PRF_PHY_CODED == phy)
		{
			PRI_RF_WRITE_REG_VALUE(PRI_RF, R04_RX_CTL, PRI_CI_MODE, 1);
		}
	}
	else if((PRF_PHY_250K_S8 == phy) || (PRF_PHY_250K_S2 == phy))
	{
		PRI_RF_WRITE_REG_VALUE(PRI_RF, R00_CTL, BW_MODE, 0);  //0 1M; 1 2m
		PRI_RF_WRITE_REG_VALUE(PRI_RF, R10_CFG, 250K_MODE_EN, ENABLE);
		if(PRF_PHY_250K_S8 == phy)
		{
			PRI_RF_WRITE_REG_VALUE(PRI_RF, R04_RX_CTL, PRI_CI_MODE, 0);
		}
		else if(PRF_PHY_250K_S2 == phy)
		{
			PRI_RF_WRITE_REG_VALUE(PRI_RF, R04_RX_CTL, PRI_CI_MODE, 1);
		}
	}
}

__weak void panchip_prf_trx_trans_time(pan_prf_config_t *p_config)
{
	uint16_t trans_wait_time = 0;
	if(p_config->trx_mode == PRF_TX_MODE)
	{
		if (p_config->chip_mode == PRF_CHIP_MODE_SEL_XN297) {            // xn297 mode
			trans_wait_time = XN297_TX_TO_RX_TIME;
		} else if (p_config->chip_mode == PRF_CHIP_MODE_SEL_NRF) {       // nordic mode
			uint32_t value = 0x00159012;
			PHY_WriteCfgFifoBatch(&value, 1, NULL);
			trans_wait_time = NRF_TX_TO_RX_TIME;
		}
	}
	else if(p_config->trx_mode == PRF_RX_MODE)
	{
		if (p_config->chip_mode == PRF_CHIP_MODE_SEL_XN297) {            // xn297 mode
			trans_wait_time = XN297_RX_TO_TX_TIME;
		} else if (p_config->chip_mode == PRF_CHIP_MODE_SEL_NRF) {       // nordic mode
			trans_wait_time = NRF_RX_TO_TX_TIME;
		}
	}
	
	#ifdef CONFIG_PRF_REDUCE_TRX_TRANS_TIME
	uint32_t value = 0x00059012;
	PHY_WriteCfgFifoBatch(&value, 1, NULL);
	
	value = 0x00098e12;
	PHY_WriteCfgFifoBatch(&value, 1, NULL);
	trans_wait_time = 0;
	#endif
	
	PRI_RF_SetTrxTransWaitTime(PRI_RF, trans_wait_time);
}

__ramfunc void panchip_prf_trx_start(void)
{
	#ifdef CONFIG_PRF_REDUCE_TRX_TRANS_TIME
	PRI_RF_SET_FUNC_ENABLE(PRI_RF,R07_SRAM_CTL,TX_RAM_READY,DISABLE);
	PRI_RF_SET_FUNC_ENABLE(PRI_RF,R07_SRAM_CTL,RX_RAM_READY,DISABLE);
	PRI_RF_SET_FUNC_ENABLE(PRI_RF,R07_SRAM_CTL,TX_RAM_READY,ENABLE);
	PRI_RF_SET_FUNC_ENABLE(PRI_RF,R07_SRAM_CTL,RX_RAM_READY,ENABLE);
	#else

	PRI_RF_SetTrxRamReady(PRI_RF, PRI_RF_MODE_SEL_TRX, DISABLE);
	ana_prf_ldo_en();
	PRI_RF_SetTrxRamReady(PRI_RF, PRI_RF_MODE_SEL_TRX, ENABLE);
	#endif
}

__ramfunc void ana_prf_ldo_en(void)
{
	SYS->ANA_RFLDO |= ANA_RFLDO_EN_LDO_ADC_Msk;
}

__ramfunc __weak void ana_prf_ldo_dis(void)
{
	#ifndef CONFIG_PRF_REDUCE_TRX_TRANS_TIME
	SYS->ANA_RFLDO &= ~(ANA_RFLDO_EN_LDO_ADC_Msk);
	#endif
}

void panchip_prf_wl_set(uint8_t match_mode)
{
//	0x89 0x5B 0x6B 0x8C 0x7B 0x2B

	uint16_t wl_msb_data = 0x2B7B;
	uint32_t wl_lsb_data = 0x8C6B5B89;
	
	PRI_RF->R12_WL &= ~R12_WL_PRI_RX_WL_ADVA_LSB_Msk;
	PRI_RF->R12_WL = wl_lsb_data;
	
	PRI_RF->R13_WL_CFG &= ~R13_WL_CFG_PRI_RX_WL_ADVA_MSB_Msk;
	PRI_RF->R13_WL_CFG |= wl_msb_data;
	
	PRI_RF->R13_WL_CFG &= ~R13_WL_CFG_PRI_RX_PLD_START_BYTE_Msk;		//offset 0 byte
	PRI_RF->R13_WL_CFG |= 0 << R13_WL_CFG_PRI_RX_PLD_START_BYTE_Pos;	//offset 0 byte, not include header, start payload 0 byte
	
	PRI_RF->R13_WL_CFG &= ~R13_WL_CFG_PRI_RX_WL_MATCH_MODE_Msk;
	PRI_RF->R13_WL_CFG |= match_mode << R13_WL_CFG_PRI_RX_WL_MATCH_MODE_Pos;
	
	PRI_RF->R01_INT |= R01_INT_PRI_RX_GOON_Msk;
}

void panchip_prf_tx_retrans_set(uint8_t times, uint16_t interval_us)
{
	if(times > 7) {
		times = 7;
	}
	
	if(interval_us > 32768) {
		interval_us = 32768;
	}
	
	PRI_RF_WRITE_REG_VALUE(PRI_RF, R11_CFG, TIMEOUT_RETRANS_EN,ENABLE);
	PRI_RF_WRITE_REG_VALUE(PRI_RF, R11_CFG, CRC_ERR_RETRANS_EN,DISABLE);
	PRI_RF_WRITE_REG_VALUE(PRI_RF, R11_CFG, LENGTH_ERR_RETRANS_EN,DISABLE);
	PRI_RF_WRITE_REG_VALUE(PRI_RF, R11_CFG, ACC_ADDR_ERR_RETRANS_EN,DISABLE);
	
	PRI_RF_WRITE_REG_VALUE(PRI_RF, R11_CFG, RETRANSMIT_MAX_CNT,times);
	PRI_RF_WRITE_REG_VALUE(PRI_RF, R11_CFG, RETANS_WAIT_TIME,interval_us);
}