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

#include <stdlib.h>
#include "common.h"

struct rf_test_tx_param_t {
	uint16_t channel_min;
	uint16_t channel_max;
	uint16_t tx_count;
	uint8_t phy;
	uint8_t hop_time;
};

struct rf_test_tx_param_t rf_test_tx_param;

uint8_t prf_test_start_flag;
uint16_t rf_test_txcnt;
uint32_t tx_data_cnt;
uint16_t rf_test_rxcnt;


void app_emi_timer_start(void)
{
	SysTick_Config(SystemCoreClock / 1000);				//1ms
}

void app_emi_timer_stop(void)
{
	SysTick->CTRL  &= ~(SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk);    
}

void emi_data_transfer(uint8_t *data, uint8_t len)
{
	SYS_delay_10nop(20000);
	usb_vendor_ep_in(len, data);
}

static void emi_prf_start(uint8_t *data)
{
	prf_test_start_flag = 1;
	rf_test_txcnt = 0;
	rf_test_rxcnt = 0;

	data[4] = 0x00;
	emi_data_transfer(data, 5);
}

static void emi_prf_end(uint8_t *data)
{
	data[4] = 0x00;
	if (prf_test_start_flag == 4) {
		data[5] = (rf_test_rxcnt & 0xff);
		data[6] = (rf_test_rxcnt >> 8);
		emi_data_transfer(data, 7);
		rf_test_rxcnt = 0;
		panchip_prf_reset();
	} else {
		emi_data_transfer(data, 5);
	}
	app_emi_timer_stop();

	prf_test_start_flag = 0;
}

static void emi_prf_tx_carrier(uint8_t *data)
{
	int8_t tx_power;
	uint16_t channel;

	tx_power = data[5];
	channel = (data[3] | (data[4] << 8));
	panchip_prf_set_tx_pwr(tx_power);
	panchip_prf_carrier_start(channel);

	data[6] = 0x00;
	emi_data_transfer(data, 7);
}

static void emi_prf_tx_hop(uint8_t *data)
{
	uint32_t addr[2] = { 0x71754173, 0x68 };

	rf_test_tx_param.channel_max = (data[3] | (data[4] << 8));
	rf_test_tx_param.channel_min = (data[5] | (data[6] << 8));
	rf_test_tx_param.phy = data[8];
	rf_test_tx_param.hop_time = (data[9] + 1);
	rf_test_tx_param.tx_count = (data[10] | (data[11] << 8));

	panchip_prf_init(&rf_config);

	PRI_RF_ChipModeSel(PRI_RF, PRF_CHIP_MODE_SEL_XN297);
	panchip_prf_reset();
	PRI_RF_SetAddrByteLen(PRI_RF, 3);
	PRI_RF_SetTrxAddr(PRI_RF, PRI_RF_MODE_SEL_TRX, PRF_PIPE0, addr);
	panchip_prf_set_tx_pwr(data[7]);
	panchip_prf_set_phy((prf_phy_t)rf_test_tx_param.phy);
	/* Change from calib to no calib */
	panchip_prf_set_chn(rf_test_tx_param.channel_min);
	PRI_RF_EnhanceEn(PRI_RF, (FunctionalState)0);
	PRI_RF_TrxFuncSel(PRI_RF, (FunctionalState)0);

	panchip_prf_payload_t tx_payload = {
		.data_length = 10,
		.data = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a },
	};
	panchip_prf_set_data(&tx_payload);

	data[12] = 0x00;
	emi_data_transfer(data, 13);

	app_emi_timer_start();
}


static void emi_prf_rx_data(uint8_t *data)
{
	data[6] = 0x00;
	emi_data_transfer(data, 7);

	uint32_t addr[2] = { 0x71754173, 0x68 };
	uint16_t channel = (data[3] | (data[4] << 8));
	uint8_t phy = data[5];

	panchip_prf_reset();
	rf_config.chip_mode = PRF_CHIP_MODE_SEL_XN297;
	rf_config.trx_mode = PRF_RX_MODE;
	rf_config.work_mode = PRF_MODE_NORMAL;
	rf_config.phy = (prf_phy_t)phy;
	rf_config.rf_channel = channel;
	rf_config.rx_length = 10;
	rf_config.rx_timeout = 0;
	panchip_prf_init(&rf_config);

	PRI_RF_SetAddrByteLen(PRI_RF, 3);
	PRI_RF_SetTrxAddr(PRI_RF, PRI_RF_MODE_SEL_TRX, PRF_PIPE0, addr);

	panchip_prf_trx_start();
}

static void emi_prf_tx_data(uint8_t *data)
{
	data[9] = 0x00;

	emi_data_transfer(data, 10);

	uint32_t addr[2] = { 0x71754173, 0x68 };

	uint16_t channel = (data[3] | (data[4] << 8));
	uint8_t phy = data[8];
	int8_t tx_power = data[7];

	rf_test_txcnt = (data[5] | (data[6] << 8));

	panchip_prf_reset();
	rf_config.tx_power = tx_power;
	rf_config.chip_mode = PRF_CHIP_MODE_SEL_XN297;
	rf_config.trx_mode = PRF_TX_MODE;
	rf_config.work_mode = PRF_MODE_NORMAL;
	rf_config.phy = (prf_phy_t)phy;
	rf_config.rf_channel = channel;
	panchip_prf_init(&rf_config);

	PRI_RF_SetAddrByteLen(PRI_RF, 3);
	PRI_RF_SetTrxAddr(PRI_RF, PRI_RF_MODE_SEL_TRX, PRF_PIPE0, addr);

	panchip_prf_payload_t tx_payload = {
		.data_length = 10,
		.data = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a },
	};
	panchip_prf_set_data(&tx_payload);

	app_emi_timer_start();
}

void usb_emi_prf_test(uint8_t *usb_data)
{
	#if PRINT_EMI
	APP_LOG_INFO("EMI PRF: ");
	data_printf(usb_data, 10);
	#endif

	switch (usb_data[2]) {
	case 0x1a:
	{
		if (usb_data[3] == 0x01) {
			prf_test_start_flag = 1;
			emi_prf_start(usb_data);
		} else {
			emi_prf_end(usb_data);
			prf_test_start_flag = 0;
		}
		break;
	}
	case 0x1b:
	{
		prf_test_start_flag = 2;
		emi_prf_tx_carrier(usb_data);
		break;
	}
	case 0x1c:
	{
		prf_test_start_flag = 3;
		emi_prf_tx_hop(usb_data);
		break;
	}
	case 0x1d:
	{
		prf_test_start_flag = 4;
		emi_prf_rx_data(usb_data);
		break;
	}
	case 0x1e:
	{
		prf_test_start_flag = 5;
		emi_prf_tx_data(usb_data);
		break;
	}
	default:
		break;
	}
}

void SysTick_Handler(void)
{
	if (prf_test_start_flag == 3) {
		panchip_prf_reset();
		rf_config.phy = (prf_phy_t)rf_test_tx_param.phy;
		uint32_t chan = 2402 + rand() % 79;
		panchip_prf_set_chn(chan);

		panchip_prf_trx_start();
	} else if (prf_test_start_flag == 5) {
		if (((tx_data_cnt > rf_test_txcnt) || (tx_data_cnt == rf_test_txcnt)) && (rf_test_txcnt != 0)) {
			tx_data_cnt = 0;
			rf_test_txcnt = 0;

			uint8_t data[5] = { 0x0a, 0x31, 0x1a, 0x00, 0x00 };

			emi_prf_end(data);
		} else {
			if (rf_test_txcnt > 0) {
				tx_data_cnt++;
			}
			panchip_prf_trx_start();
		}
	}
}
