/*
 * Copyright (c) 2021 Shanghai Panchip Microelectronics Co.,Ltd.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include "pan271x.h"
#include "comm_prf.h"
#include "ring_buffer.h"
#include "common.h"
#include "dongle_prf.h"
#include "pan_pri_rf.h"
#include "dongle_p24c02.h"

#define PRF_DBG_PIN                                     0
#define PAIR_ONLY_ONE                                   1
#define HOP_ENABLE                                      1


struct prf_state_t prf_state;
bool hoping = false;
volatile bool prf_ack_ready = false;
volatile bool pair_addr0_write = false;
volatile bool pair_addr1_write = false;
uint16_t channel_list_private[9] = { 2404, 2412, 2418, 2430, 2438, 2444, 2456, 2474 };
uint16_t channel_public = 2412;
uint8_t read_addr0[6];
uint8_t read_addr1[6];


pan_prf_config_t __align(4) rf_config = 
{
	.work_mode			= PRF_MODE_ENHANCE,//PRF_MODE_NORMAL,PRF_MODE_ENHANCE
	.chip_mode			= PRF_CHIP_MODE_SEL_XN297,//PRF_CHIP_MODE_SEL_NRF,//PRF_CHIP_MODE_SEL_XN297,
	.trx_mode			= PRF_RX_MODE,
	.phy				= PRF_PHY_2M,//PRF_PHY_250K,//PRF_PHY_1M,PRF_PHY_2M
	.crc				= PRF_CRC_SEL_CRC16,
	.scr				= PRF_SCR_SEL_EN,
	.mode_conf			= PRF_BLE_CONF,//PRF_BLE_CONF
	.pipe				= PRF_PIPE0,
	.rx_timeout			= 10000,			//us
	.rf_channel			= PAIR_PUBLIC_CHANNEL,
	.tx_no_ack			= DISABLE,
	.rx_length			= 30,
	.sync_length		= 4,
	.sync				= PAIR_PUBLIC_ADDR,	
	.crc_include_sync	= ENABLE,
	.scr_include_sync	= ENABLE,
	.auto_pyl_flag		= ENABLE,
	.pid_manual_flag	= ENABLE,
	.endian				= PRF_BIG_ENDIAN,
	.tx_power			= 8,
};

panchip_prf_payload_t tx_payload = {
	.data_length = 0,
	.data = { 0 },
};

/* set addr will set the tx addr, if want to ack data from dynamic rx pipe ,rx isr must set tx addr */
void app_prf_set_tx_addr(uint8_t *addr)
{
	#if SET_TX_ADDR_DIRECT
	/* 1.25us */
	uint32_t tx_addr;

	tx_addr = (addr[0]) | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24);

	PRI_RF_WRITE_REG_VALUE(PRI_RF, R05_TX_ADDR_L, L32B, tx_addr);
	#else
	/* 6us no used third param */
	panchip_prf_set_addr(addr, 4, PRF_PIPE0, PRI_RF_MODE_SEL_TX);
	#endif
}

void calculate_combo_freq(uint8_t *addr)
{
	/* channel = 8x + yi(x ∈ (0，4), yi from y0 to (y0 + 7) %d)*/
	uint8_t x = addr[0] % 5;
	uint8_t y = addr[2] % 8;

	mini_printf("calculate_combo_freq use ");
	data_printf(addr, 4);
	mini_printf("x = %d y = %d\n", x, y);

	for (uint8_t i = 0; i < 8; i++) {
		channel_list_private[i] = 2402 + 2 * (8 * x + y);
		x = (x + 1) % 5;
		y = (y + 1) % 8;
		if ((channel_list_private[i] == 2432) || (channel_list_private[i] == 2464)) {
			mini_printf("%d abandon\n", channel_list_private[i]);
			channel_list_private[i] = 2402 + 2 * (8 * x + y);
			x = (x + 1) % 5;
		}
	}

	mini_printf("calculate private freq: ");
	for (uint8_t i = 0; i < 8; i++) {
		mini_printf("%d ", channel_list_private[i]);
	}
	channel_list_private[8] = 2412;
	mini_printf("\n");
}

void event_tx_fun(void)
{
//	mini_printf("t");
	if(prf_test_start_flag == 5) {
		return;
	}
	if (prf_state.paird_addr_active[0]) {
		static bool addr_first0 = false;
		if (!addr_first0) {
			addr_first0 = true;
			if (memcmp(read_addr0, &prf_state.pair_private_addr[0][0], 6)) {
				pair_addr0_write = true;
			} else {
				mini_printf("paired addr0: ");
				data_printf(&prf_state.pair_private_addr[0][0], 6);
			}
			#if PAIR_ONLY_ONE
			prf_state.pairing = false;
			/* disable PIPE0 pair scan */
			PRI_RF->R09_RX_ADDR1_L &= ~(R09_RX_ADDR0_EN_Msk | R09_RX_ADDR2_EN_Msk);
			#endif
		}
	}
	if (prf_state.paird_addr_active[1]) {
		static bool addr_first1 = false;
		if (!addr_first1) {
			addr_first1 = true;
			if (memcmp(read_addr1, &prf_state.pair_private_addr[1][0], 6)) {
				pair_addr1_write = true;
			} else {
				mini_printf("paired addr0: ");
				data_printf(&prf_state.pair_private_addr[1][0], 6);
			}
		}
	}
	if (prf_ack_ready) {
		prf_ack_ready = false;
	}
	if (hoping) {
		hoping = false;
		mini_printf("hop end @ %d\n", channel_list_private[prf_state.channel_index]);
	}

	if (prf_test_start_flag != 5) {
		panchip_prf_trx_start();
	}
}

static void prf_data_process(uint8_t *data, uint32_t len)
{
	uint8_t trans_data[64];

//	data_printf(data,len);
	switch (data[0]) {
	case 0x00:
		break;
	case 0x04:
		trans_data[0] = 0x05;
		for (uint8_t i = 1; i < len - 2; i++) {
			trans_data[i] = data[i + 2];
		}
		ring_buf_put(&ringbuf_raw2, trans_data, REPORT_SIZE);

		if (data[2] == 0x15) {
			for (uint8_t i = 0; i < 6; i++) {
				trans_data[i + 2] = 0;
			}
			ring_buf_put(&ringbuf_raw2, trans_data, REPORT_SIZE);
		}
		break;
	case 0x81:
		/* ep 1 report 1 reserved cal */
		trans_data[0] = 0x11;
		trans_data[1] = 8;
		memcpy(trans_data + 2, data + 2, 8);
		ring_buf_put(&ringbuf_raw, trans_data, REPORT_SIZE);
		break;
	case 0x82:
		/* ep 2 report 1 reserved cal*/
		trans_data[0] = 0x02;
		trans_data[1] = 15;
		memcpy(trans_data + 2, data + 2, 15);
		ring_buf_put(&ringbuf_raw2, trans_data, REPORT_SIZE);
		break;
	case 0x83:
		trans_data[0] = 0x03;
		trans_data[1] = 2;
		memcpy(trans_data + 2, data + 2, 2);
		ring_buf_put(&ringbuf_raw2, trans_data, REPORT_SIZE);
		break;
	case 0x84:
		trans_data[0] = 0x04;
		trans_data[1] = 1;
		memcpy(trans_data + 2, data + 2, 1);
		ring_buf_put(&ringbuf_raw2, trans_data, REPORT_SIZE);
		break;
	case 0x85:
		/* FN no need */
		break;

	case 0x88:
		/* data_printf(data, len); */
		trans_data[0] = 0x06;
		trans_data[1] = len - 2;
		memcpy(trans_data + 2, data + 2, len - 2);
		ring_buf_put(&ringbuf_raw2, trans_data, REPORT_SIZE);
		break;
	default:
		break;
	}
}

void event_rx_fun(void)
{
	uint8_t addr_format[4];
	panchip_prf_payload_t rx_payload;

	uint8_t pipe_num = panchip_prf_get_pipe();

	prf_state.rx_test_cnt++;
	rx_payload.data_length = panchip_prf_data_rec(&rx_payload);
	switch (pipe_num) {
	case 0:
		if ((rx_payload.data[0] == (PAIR_MAGIC & 0xff)) && (rx_payload.data[1] == (PAIR_MAGIC >> 8))) {
			if (((rx_payload.data[2] >> 4) == 1) && (!prf_state.paird_addr_active[0])) {
				prf_state.pair_private_addr[0][0] = rx_payload.data[3];
				prf_state.pair_private_addr[0][1] = rx_payload.data[4];
				prf_state.pair_private_addr[0][2] = rx_payload.data[5];
				prf_state.pair_private_addr[0][3] = rx_payload.data[6];
				prf_state.pair_private_addr[0][4] = rx_payload.data[7];
				prf_state.pair_private_addr[0][5] = rx_payload.data[8];

				addr_format[0] = rx_payload.data[8];
				addr_format[1] = rx_payload.data[7];
				addr_format[2] = rx_payload.data[6];
				addr_format[3] = (rx_payload.data[5] & 0xf) | 0x50;

				panchip_prf_set_addr(addr_format, 4, PRF_PIPE1, PRI_RF_MODE_SEL_RX);

				app_prf_set_tx_addr(addr_format);

				panchip_prf_payload_t ack_payload;

				ack_payload.data[0] = PAIR_MAGIC & 0xff;
				ack_payload.data[1] = PAIR_MAGIC >> 8;
				ack_payload.data[2] = PAIR_DONGLE_1K_FLAG;
				ack_payload.data[3] = prf_state.own_addr[0];
				ack_payload.data[4] = prf_state.own_addr[1];
				ack_payload.data[5] = prf_state.own_addr[2];
				ack_payload.data[6] = prf_state.own_addr[3];
				ack_payload.data[7] = prf_state.own_addr[4];
				ack_payload.data[8] = prf_state.own_addr[5];
				ack_payload.data_length = 9;
				panchip_prf_set_data(&ack_payload);

			} else if ((rx_payload.data[2] == 0x20) && (!prf_state.paird_addr_active[1])) {
				prf_state.pair_private_addr[1][0] = rx_payload.data[3];
				prf_state.pair_private_addr[1][1] = rx_payload.data[4];
				prf_state.pair_private_addr[1][2] = rx_payload.data[5];
				prf_state.pair_private_addr[1][3] = rx_payload.data[6];
				prf_state.pair_private_addr[1][4] = rx_payload.data[7];
				prf_state.pair_private_addr[1][5] = rx_payload.data[8];

				addr_format[0] = rx_payload.data[8];
				addr_format[1] = rx_payload.data[7];
				addr_format[2] = rx_payload.data[6];
				addr_format[3] = (rx_payload.data[5] & 0xf) | 0x50;

				panchip_prf_set_addr(addr_format, 4, PRF_PIPE2, PRI_RF_MODE_SEL_RX);

				app_prf_set_tx_addr(addr_format);

				panchip_prf_payload_t ack_payload;

				ack_payload.data[0] = PAIR_MAGIC & 0xff;
				ack_payload.data[1] = PAIR_MAGIC >> 8;
				ack_payload.data[2] = PAIR_DONGLE_1K_FLAG;
				ack_payload.data[3] = prf_state.own_addr[0];
				ack_payload.data[4] = prf_state.own_addr[1];
				ack_payload.data[5] = prf_state.own_addr[2];
				ack_payload.data[6] = prf_state.own_addr[3];
				ack_payload.data[7] = prf_state.own_addr[4];
				ack_payload.data[8] = prf_state.own_addr[5];
				ack_payload.data_length = 9;
				panchip_prf_set_data(&ack_payload);
			}
		} else {
			rf_test_rxcnt++;
			panchip_prf_trx_start();
		}
		break;
	case 1:
		addr_format[0] = prf_state.pair_private_addr[0][5];
		addr_format[1] = prf_state.pair_private_addr[0][4];
		addr_format[2] = prf_state.pair_private_addr[0][3];
		addr_format[3] = (prf_state.pair_private_addr[0][2] & 0xf) | 0x50;

		if (!prf_ack_ready) {
			app_prf_set_tx_addr(addr_format);
			panchip_prf_set_data(&tx_payload);
		}
		prf_state.paird_addr_active[0] = true;
		static uint8_t seq_num;

		if (seq_num != rx_payload.data[1]) {
			seq_num = rx_payload.data[1];
			if (rx_payload.data[0] == 0x04) { /* MS data check */
				prf_state.valid_rx_test_cnt++;
				ring_buf_put(&ringbuf_raw, (uint8_t *)rx_payload.data, MOUSE_REPORT_SIZE);
			}
		}
		break;
	case 2:
		addr_format[0] = prf_state.pair_private_addr[1][5];
		addr_format[1] = prf_state.pair_private_addr[1][4];
		addr_format[2] = prf_state.pair_private_addr[1][3];
		addr_format[3] = (prf_state.pair_private_addr[1][2] & 0xf) | 0x50;

		if (!prf_ack_ready) {
			app_prf_set_tx_addr(addr_format);
			panchip_prf_set_data(&tx_payload);
		}
		prf_state.paird_addr_active[1] = true;
		static uint8_t seq_num2;

		if (seq_num2 != rx_payload.data[1]) { /* MS data check */
			seq_num2 = rx_payload.data[1];
			if (rx_payload.data[0] == 0x04) {
				prf_state.valid_rx_test_cnt++;

				ring_buf_put(&ringbuf_raw2, (uint8_t *)rx_payload.data, MOUSE_REPORT_SIZE);
			}
		}
		break;

	default:
		break;
	}
}

void event_rx_timeout_fun(void)
{
	/* lldbg to isr 9us */
	prf_state.timout_test_cnt++;

	prf_state.channel_index++;
	#if PAIR_ONLY_ONE
	if (prf_state.pairing) {
		prf_state.channel_index = prf_state.channel_index % 9;
	} else {
		prf_state.channel_index = prf_state.channel_index % 8;
	}
	#else
	prf_state.channel_index = prf_state.channel_index % 9;
	#endif

	rf_config.rf_channel = channel_list_private[prf_state.channel_index];

	/* 50us */
	panchip_prf_set_chn(rf_config.rf_channel);
	/* 3us */
	panchip_prf_trx_start();
	hoping = true;
}

void event_crc_err_fun(void)
{
//	mini_printf("c ");

	prf_state.crc_test_cnt++;

	panchip_prf_trx_start();
}

void event_pid_err_fun(void)
{
	mini_printf("rx data pid err\n");
}

void event_rx_len_err_fun(void)
{
//	mini_printf("L ");

	prf_state.rx_len_err_test_cnt++;
	panchip_prf_trx_start();
}

void panchip_prf_isr_init(void)
{
	isr_cb.tx_cb = event_tx_fun;
	isr_cb.rx_cb = event_rx_fun;
	isr_cb.rx_timeout_cb = event_rx_timeout_fun;
	isr_cb.rx_crc_err_cb = event_crc_err_fun;
	isr_cb.rx_pid_err_cb = event_pid_err_fun;
	isr_cb.rx_len_err_cb = event_rx_len_err_fun;
}

void panchip_prf_irq_enable(void)
{
	NVIC_SetPriority(LL_IRQn, 0);
	/* Enable RF interrupt */
	NVIC_EnableIRQ(LL_IRQn);
}

void dongle_prf_cnt_printf(void)
{
	mini_printf("1s rx %d valid %d timeout %d crc %d len err %d\n",
	       prf_state.rx_test_cnt, prf_state.valid_rx_test_cnt, prf_state.timout_test_cnt, prf_state.crc_test_cnt, prf_state.rx_len_err_test_cnt);
	prf_state.rx_test_cnt = 0;
	prf_state.timout_test_cnt = 0;
	prf_state.crc_test_cnt = 0;
	prf_state.rx_len_err_test_cnt = 0;
	prf_state.valid_rx_test_cnt = 0;
}

void get_mac_addr(void)
{
	for (uint8_t i = 0; i < 6; i++) {
		prf_state.own_addr[i] = 0xa0 + i;
	}

	memcpy(prf_state.own_addr, m_chip_mac, 6);

	mini_printf("get_mac_addr: ");
	data_printf(prf_state.own_addr, 6);

	calculate_combo_freq(&prf_state.own_addr[2]);
}

void write_pair_addr(void)
{
	if(pair_addr0_write) {
		pair_addr0_write = false;
		P24C02_WritePage(0x10, &prf_state.pair_private_addr[0][0], 6);
		mini_printf("save new pair addr1: ");
		data_printf(&prf_state.pair_private_addr[0][0], 6);
	}
	
	if(pair_addr1_write) {
		pair_addr1_write = false;
		P24C02_WritePage(0x20, &prf_state.pair_private_addr[1][0], 6);
		mini_printf("save new pair addr2: ");
		data_printf(&prf_state.pair_private_addr[1][0], 6);
	}
}

void load_pair_addr(void)
{
	uint8_t addr_format[4];

	for (uint8_t i = 0; i < PAIR_MAX_NUM; i++) {
		prf_state.paird_addr_active[i] = false;
	}
	prf_state.pairing = true;

	P24C02_ReadSequential(0x10, read_addr0, 6);
	P24C02_ReadSequential(0x20, read_addr1, 6);

	data_printf(read_addr0, 6);
	data_printf(read_addr1, 6);
	memcpy(&prf_state.pair_private_addr[0][0], read_addr0, 6);
	memcpy(&prf_state.pair_private_addr[1][0], read_addr1, 6);

	/* set PRI_RF_MODE_SEL_RX addr will set the rx addr & pipe */
	/* set PRI_RF_MODE_SEL_TX addr will set the single tx addr, no set tx will use init tx addr */
	/* set PRI_RF_MODE_SEL_TRX addr will set the trx addr both, no set tx will use init tx addr */

	addr_format[0] = read_addr0[5];
	addr_format[1] = read_addr0[4];
	addr_format[2] = read_addr0[3];
	addr_format[3] = (read_addr0[2] & 0xf) | 0x50;

	panchip_prf_set_addr(addr_format, 4, PRF_PIPE1, PRI_RF_MODE_SEL_RX);
	data_printf(addr_format, 4);

	addr_format[0] = read_addr1[5];
	addr_format[1] = read_addr0[4];
	addr_format[2] = read_addr0[3];
	addr_format[3] = (read_addr0[2] & 0xf) | 0x50;

	panchip_prf_set_addr(addr_format, 4, PRF_PIPE2, PRI_RF_MODE_SEL_RX);
}

void dongle_prf_pair_init(void)
{
	get_mac_addr();
	load_pair_addr();
}

void dongle_prf_init(void)
{
	panchip_prf_init(&rf_config);

	/* enable len err isr */
	panchip_prf_rx_length_irq_cfg(rf_config.rx_length);

	SYS_SET_MFP(P2,1,LL_DEBUG_0);		//tx_on
	SYS_SET_MFP(P2,0,LL_DEBUG_1);		//rx_on
	SYS_SET_MFP(P0,4,LL_DEBUG_9);		//match

	dongle_prf_pair_init();

	panchip_prf_trx_start();
}
