#include "sx126x_cmd_process.h"
#include <stdio.h>
#include <stdlib.h>
#include "radio.h"
#include "stm32f10x_it.h"
#include "delay.h"
#include "string.h"
#include "project_config.h"
#include "cJSON.h"
#include "HAL_uart.h"
#include "sx126x-board.h"
#include "tb05_control.h"

#define PA_MODE 1

#define PACKET_NUM 5 //how many packets need to send by default

#define GREEN_LED GPIO_Pin_8
#define Ra03sch_PORT GPIOA
#define Ra03sch_CTRL1 GPIO_Pin_11
#define Ra03sch_CTRL2 GPIO_Pin_12

#define RESPONE_STATUS 10

#define RADIO_OK 0
#define RADIO_FAILED -1

#define CMD_MAX_LENGTH 200
#define RESPONE_MAX_LENGTH 80
#define KEY_MAX_LENGTH 10

#define RADIO_SEND_CMD 1
#define RADIO_RECV_CMD 2
#define RADIO_CAD_CMD 3
#define RADIO_STANDBY_CMD 4
#define RADIO_SLEEP_CMD 5
#define UPDATE_CMD 6
// #define SEND_UPDATE_CMD 6
// #define RECV_UPDATE_CMD 7
// #define CAD_UPDATE_CMD 8

#define SEND_RESPONE_CMD 1
#define RECV_RESPONE_CMD 2
#define CAD_RESPONE_CMD 3
#define STANDBY_RESPONE_CMD 4
#define SLEEP_RESPONE_CMD 5

static uint8_t radio_init_already = 0;
static uint8_t radio_sleep_ready = 0;
static uint8_t radio_standby_ready = 0;
int g_lora_tx_done = 0;
int g_lora_rx_done = 0;

typedef enum
{
	IDELE = 0,
	TX_MODE = 1,
	RX_MODE,
	CAD_MODE,
	STAND_BY,
	DEEPSLEEP,
}LoRa_mode_t;
LoRa_mode_t LoRa_realtime_Mode = IDELE;

char *LoRa_Mode_String[6] = {"IDELE", "TX_MODE", "RX_MODE", "CAD_MODE", "STAND_BY", "DEEPSLEEP"};

typedef struct
{
	int modem; // FSK or LoRa
	uint32_t freq;
	int bandwidth;
	int sf;
	int coderate;
	int preambleLen;
	int packetID;
	int packet_rssi;
	int packet_snr;
	int packetNum;
	struct
	{
		char buffer[200];
		int bufferLen;
		int power;
		int interval;	  // period of tx
	} tx_process_data;

	struct
	{
		uint32_t rxPeriod;
		uint32_t sleepPeriod;
	} cad_process_data;
} Radio_peocess_t;
Radio_peocess_t _radio_peocess = {0};

static RadioEvents_t SX126xRadioEvents;
void radio_status_upload(int type);

static void Ra03sch_TxMode_Set(void){
	GPIO_InitTypeDef GPIO_InitStructure;

	delay_ms(10);

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE);
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
	GPIO_InitStructure.GPIO_Pin = Ra03sch_CTRL1;
	GPIO_Init(Ra03sch_PORT, &GPIO_InitStructure);

	delay_ms(20);
	
	GPIO_InitStructure.GPIO_Pin = Ra03sch_CTRL2;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_Init(Ra03sch_PORT, &GPIO_InitStructure);

	delay_ms(10);
}

static void Ra03sch_RxMode_Set(void){
	GPIO_InitTypeDef GPIO_InitStructure;

	delay_ms(10);

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE);
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
	GPIO_InitStructure.GPIO_Pin = Ra03sch_CTRL2;
	GPIO_Init(Ra03sch_PORT, &GPIO_InitStructure);

	delay_ms(20);
	
	GPIO_InitStructure.GPIO_Pin = Ra03sch_CTRL1;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_Init(Ra03sch_PORT, &GPIO_InitStructure);

	delay_ms(10);
}

/* STATUS LED */
static void SX126x_LED_init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Pin = GREEN_LED;
	GPIO_Init(GPIOA, &GPIO_InitStructure);

	GPIO_WriteBit(GPIOA, GREEN_LED, Bit_RESET);
}

static void SX126xOnTxDone(void)
{
	printf("On TxDone\r\n");
	Radio.Standby();
	_radio_peocess.packetID++;
	g_lora_tx_done = 1;
	g_lora_rx_done = 0;
	radio_status_upload(SEND_RESPONE_CMD);
}

/*
{"type": 2,"RxNum ": 8,"per ": 0}
*/
static void SX126xOnRxDone(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr)
{
	printf("On RxDone\r\n");
	g_lora_tx_done = 0;
	g_lora_rx_done = 1;
	_radio_peocess.packet_rssi = rssi;
	_radio_peocess.packet_snr = snr;
	printf("[ %d ] Received, rssi = %d, snr = %d, %s\r\n", _radio_peocess.packetID, rssi, (int16_t)snr, payload);
	if (RX_MODE == LoRa_realtime_Mode)
	{
		Radio.Standby();
		// if (_radio_peocess.packetID < _radio_peocess.packetNum)
		// {
		_radio_peocess.packetID++;
		radio_status_upload(RECV_RESPONE_CMD);
		Radio.Rx(LORA_RX_TIMEOUT_VALUE);
		// }
	}
	else if (CAD_MODE == LoRa_realtime_Mode)
	{
		Radio.Standby();
		if (_radio_peocess.packetID < _radio_peocess.packetNum)
		{
			_radio_peocess.packetID++;
			radio_status_upload(CAD_RESPONE_CMD);
			Radio.SetRxDutyCycle(_radio_peocess.cad_process_data.rxPeriod, _radio_peocess.cad_process_data.sleepPeriod);
		}
	}
}

static void SX126xOnTxTimeout(void)
{
	printf("TxTimeout\r\n");
	if (TX_MODE == LoRa_realtime_Mode)
	{
		Radio.Send((uint8_t *)_radio_peocess.tx_process_data.buffer, _radio_peocess.tx_process_data.bufferLen);
	}
}

static void SX126xOnRxTimeout(void)
{
	Radio.Standby();
	printf("RxTimeout retry recive\r\n");
	if (RX_MODE == LoRa_realtime_Mode)
	{
		Radio.Rx(LORA_RX_TIMEOUT_VALUE);
	}
}

static void SX126xOnRxError(void)
{
	Radio.Standby();
	printf("RxError retry recive\r\n");
	if (RX_MODE == LoRa_realtime_Mode)
	{
		Radio.Rx(LORA_RX_TIMEOUT_VALUE);
	}
}

static void SX126xOnCadDone(bool channelActivityDetected)
{
	if (true == channelActivityDetected)
	{
		radio_status_upload(CAD_RESPONE_CMD);
		printf("CAD_Detected\r\n");
	}
	else
	{
		printf("CAD_Timeout\r\n");
	}
}

static void SX126xRxPreambleDetect(void)
{
	if (CAD_MODE == LoRa_realtime_Mode)
	{
		printf("On RxPreambleDetect\r\n");
	}
}

/* LoRa module init */
static void	SX126xRadioInit(void)
{
	if (0 == radio_init_already)
	{
		SX126xRadioEvents.TxDone = SX126xOnTxDone;
		SX126xRadioEvents.RxDone = SX126xOnRxDone;
		SX126xRadioEvents.TxTimeout = SX126xOnTxTimeout;
		SX126xRadioEvents.RxTimeout = SX126xOnRxTimeout;
		SX126xRadioEvents.RxError = SX126xOnRxError;
		SX126xRadioEvents.CadDone = SX126xOnCadDone;
		SX126xRadioEvents.RxPreambleDetect = SX126xRxPreambleDetect;
		SX126x_LED_init();
		Radio.Init(&SX126xRadioEvents);
		radio_init_already = 1;
		printf("RadioInit\r\n");
	}else{
		Radio.ReInit();
		printf("RadioReInit\r\n");
	}
}

int radio_tx_process(void){
	if (1 == radio_sleep_ready)
	{
		radio_sleep_ready = 0;
		radio_status_upload(SLEEP_RESPONE_CMD);
	}
	if (1 == radio_standby_ready)
	{
		radio_standby_ready = 0;
		radio_status_upload(STANDBY_RESPONE_CMD);
	}
	SX126xRadioInit();
	switch (_radio_peocess.modem)
	{
	case 0:
		return RADIO_FAILED;
	case 1:
		if (_radio_peocess.freq < 410000000 || _radio_peocess.freq > 930000000)
		{
			printf("error freq\r\n");
			return RADIO_FAILED;
		}
		if (_radio_peocess.sf < 5 || _radio_peocess.sf > 12)
		{
			printf("error sf\r\n");
			return RADIO_FAILED;
		}
		if (_radio_peocess.bandwidth < 0 || _radio_peocess.bandwidth > 2)
		{
			printf("error bandwidth\r\n");
			return RADIO_FAILED;
		}
		if (_radio_peocess.coderate < 1 || _radio_peocess.coderate > 4)
		{
			printf("error coderate\r\n");
			return RADIO_FAILED;
		}
		if (_radio_peocess.tx_process_data.power < 0 || _radio_peocess.tx_process_data.power > 22)
		{
			printf("error power\r\n");
			return RADIO_FAILED;
		}
		if (_radio_peocess.preambleLen < 1 || _radio_peocess.preambleLen > 500)
		{
			printf("error preambleLen\r\n");
			return RADIO_FAILED;
		}
		if (_radio_peocess.packetNum < 1)
		{
			printf("error packetNum\r\n");
			return RADIO_FAILED;
		}
		if (_radio_peocess.tx_process_data.interval < 1)
		{
			printf("error interval\r\n");
			return RADIO_FAILED;
		}
		if (_radio_peocess.tx_process_data.bufferLen < 1)
		{
			printf("error bufferLen\r\n");
			return RADIO_FAILED;
		}
	
		if(1 == PA_MODE && _radio_peocess.tx_process_data.power > 3){
			_radio_peocess.tx_process_data.power = 3;
			printf("PA Mode:Power less than 3\r\n");
		}

		SX126xRxTimerStop();
		Ra03sch_TxMode_Set();
		Radio.SetChannel(_radio_peocess.freq);
		Radio.SetTxConfig(MODEM_LORA, _radio_peocess.tx_process_data.power, 0, _radio_peocess.bandwidth,
						  _radio_peocess.sf, _radio_peocess.coderate,
						  _radio_peocess.preambleLen, LORA_FIX_LENGTH_PAYLOAD_ON,
						  true, 0, 0, LORA_IQ_INVERSION_ON, 60000);
		// printf("start radio transmit modem: %s, freq: %d\r\n",(_radio_peocess.modem == 1)?"LoRa":" FSK" ,_radio_peocess.freq);
		// printf("start radio transmit power: %d, bandwidth: %d, sf: %d, coderate: %d, preambleLen: %d\r\n", _radio_peocess.tx_process_data.power, _radio_peocess.bandwidth, _radio_peocess.sf, _radio_peocess.coderate, _radio_peocess.preambleLen);
		// printf("start radio transmit length: %d,body: %s\r\n", _radio_peocess.tx_process_data.bufferLen, _radio_peocess.tx_process_data.buffer);
		Radio.Send((uint8_t*)_radio_peocess.tx_process_data.buffer, _radio_peocess.tx_process_data.bufferLen);
		return RADIO_OK;
	default:
		return RADIO_FAILED;
	}
}

int radio_rx_process(void)
{
	if (1 == radio_sleep_ready)
	{
		radio_sleep_ready = 0;
		radio_status_upload(SLEEP_RESPONE_CMD);
	}
	if (1 == radio_standby_ready)
	{
		radio_standby_ready = 0;
		radio_status_upload(STANDBY_RESPONE_CMD);
	}
	SX126xRadioInit();
	switch (_radio_peocess.modem)
	{
	case 0:
		return RADIO_FAILED;
	case 1:
		if (_radio_peocess.freq < 410000000 || _radio_peocess.freq > 930000000)
		{
			return RADIO_FAILED;
		}
		if (_radio_peocess.sf < 5 || _radio_peocess.sf > 12)
		{
			return RADIO_FAILED;
		}
		if (_radio_peocess.bandwidth < 0 || _radio_peocess.bandwidth > 2)
		{
			return RADIO_FAILED;
		}
		if (_radio_peocess.coderate < 1 || _radio_peocess.coderate > 4)
		{
			return RADIO_FAILED;
		}
		if (_radio_peocess.preambleLen < 1 || _radio_peocess.preambleLen > 500)
		{
			return RADIO_FAILED;
		}
		if (_radio_peocess.packetNum < 1)
		{
			return RADIO_FAILED;
		}
		SX126xTxTimerStop();
		Ra03sch_RxMode_Set();
		Radio.SetChannel(_radio_peocess.freq);
		Radio.SetRxConfig(MODEM_LORA, _radio_peocess.bandwidth, _radio_peocess.sf,
						  _radio_peocess.coderate, 0, _radio_peocess.preambleLen,
						  LORA_SX126X_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON,
						  0, true, 0, 0, LORA_IQ_INVERSION_ON, true);
		Radio.Rx(LORA_RX_TIMEOUT_VALUE);
		printf("start radio receive modem: %s, freq: %d\r\n",(_radio_peocess.modem == 1)?"LoRa":" FSK" ,_radio_peocess.freq);
		printf("start radio transmit bandwidth: %d, sf: %d, coderate: %d, preambleLen: %d\r\n", _radio_peocess.bandwidth, _radio_peocess.sf, _radio_peocess.coderate, _radio_peocess.preambleLen);
		return RADIO_OK;
	default:
		return RADIO_FAILED;
	}
}

int radio_cad_process(void)
{
	if (1 == radio_sleep_ready)
	{
		radio_sleep_ready = 0;
		radio_status_upload(SLEEP_RESPONE_CMD);
	}
	if (1 == radio_standby_ready)
	{
		radio_standby_ready = 0;
		radio_status_upload(STANDBY_RESPONE_CMD);
	}
	SX126xRadioInit();
	printf("freq:%d \r\n", _radio_peocess.freq);
	printf("sf:%d\r\n", _radio_peocess.sf);
	printf("bandwidth:%d\r\n", _radio_peocess.bandwidth);
	printf("coderate:%d\r\n", _radio_peocess.coderate);
	printf("preambleLen:%d\r\n", _radio_peocess.preambleLen);
	printf("rxPeriod:%d\r\n", _radio_peocess.cad_process_data.rxPeriod);
	printf("sleepPeriod:%d\r\n", _radio_peocess.cad_process_data.sleepPeriod);
	switch (_radio_peocess.modem)
	{
	case 0:
		return RADIO_FAILED;
	case 1:
		if (_radio_peocess.freq < 410000000 || _radio_peocess.freq > 930000000)
		{
			printf("freq RADIO_FAILED\r\n");
			return RADIO_FAILED;
		}
		if (_radio_peocess.sf < 5 || _radio_peocess.sf > 12)
		{
			printf("sf RADIO_FAILED\r\n");
			return RADIO_FAILED;
		}
		if (_radio_peocess.bandwidth < 0 || _radio_peocess.bandwidth > 2)
		{
			printf("bandwidth RADIO_FAILED\r\n");
			return RADIO_FAILED;
		}
		if (_radio_peocess.coderate < 1 || _radio_peocess.coderate > 4)
		{
			printf("coderate RADIO_FAILED\r\n");
			return RADIO_FAILED;
		}
		if (_radio_peocess.preambleLen < 1 || _radio_peocess.preambleLen > 500)
		{
			printf("preambleLen RADIO_FAILED: %d\r\n", _radio_peocess.preambleLen);
			return RADIO_FAILED;
		}
		if (_radio_peocess.cad_process_data.rxPeriod < 1)
		{
			printf("rxPeriod RADIO_FAILED:%d \r\n", _radio_peocess.cad_process_data.rxPeriod);
			return RADIO_FAILED;
		}
		if (_radio_peocess.cad_process_data.sleepPeriod < 1)
		{
			printf("sleepPeriod RADIO_FAILED: %d\r\n", _radio_peocess.cad_process_data.sleepPeriod);
			return RADIO_FAILED;
		}
		Ra03sch_RxMode_Set();
		Radio.SetChannel(_radio_peocess.freq);
		Radio.SetRxConfig(MODEM_LORA, _radio_peocess.bandwidth, _radio_peocess.sf,
						  _radio_peocess.coderate, 0, _radio_peocess.preambleLen,
						  LORA_SX126X_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON,
						  0, true, 0, 0, LORA_IQ_INVERSION_ON, true);
		Radio.SetRxDutyCycle(_radio_peocess.cad_process_data.rxPeriod, _radio_peocess.cad_process_data.sleepPeriod);
		printf("start radio cad\r\n");
		return RADIO_OK;
	default:
		return RADIO_FAILED;
	}
}

int radio_standby_process(void)
{
	if (1 == radio_sleep_ready)
	{
		radio_sleep_ready = 0;
		radio_status_upload(SLEEP_RESPONE_CMD);
	}
	SX126xRadioInit();
	Radio.Standby();
	radio_standby_ready = 1;
	return RADIO_OK;
}

int radio_sleep_process(void)
{
	if (1 == radio_standby_ready)
	{
		radio_standby_ready = 0;
		radio_status_upload(STANDBY_RESPONE_CMD);
	}
	SX126xRadioInit();
	Radio.Sleep();
	radio_sleep_ready = 1;
	return RADIO_OK;
}

void tb05_status_respone(int type, int status)
{
	char cmd_data[RESPONE_MAX_LENGTH] = {0};
	memset(cmd_data, 0, RESPONE_MAX_LENGTH);
	if (type > 0 && type < 6)
	{
		snprintf(cmd_data, sizeof(cmd_data), "{\"type\": %d,\"status\":%d}", type, status);
		tb05_radio_respone(cmd_data, (strlen(cmd_data) + 1));
	}
}

/* reporting the operating status */
void radio_status_upload(int type)
{
	char cmd_data[RESPONE_MAX_LENGTH] = {0};
	float per = 0, temp = 0;
	memset(cmd_data, 0, RESPONE_MAX_LENGTH);
	switch (type)
	{
	case SEND_RESPONE_CMD:
		snprintf(cmd_data, sizeof(cmd_data), "{\"type\":21,\"TxDoneNum\":%d}", _radio_peocess.packetID);
		if (0 == tb05_radio_respone(cmd_data, (strlen(cmd_data) + 1)))
			printf("SEND_RESPONE_CMD status upload\r\n");
		break;
	case RECV_RESPONE_CMD:
		temp = (_radio_peocess.packetNum - _radio_peocess.packetID) * 100;
		per = temp / _radio_peocess.packetNum;
		snprintf(cmd_data, sizeof(cmd_data), "{\"type\":22,\"rssi\":%d,\"snr\":%d,\"RxNum\":%d,\"per\":%02f}", _radio_peocess.packet_rssi, _radio_peocess.packet_snr, _radio_peocess.packetID, per);
		if (0 == tb05_radio_respone(cmd_data, (strlen(cmd_data) + 1)))
			printf("RECV_RESPONE_CMD status upload, temp: %02f, per: %02f\r\n", temp, per);
		break;
	case CAD_RESPONE_CMD:
		snprintf(cmd_data, sizeof(cmd_data), "{\"type\":23,\"rssi\":%d,\"snr\":%d,\"awake\":1,\"RxNum\":%d}", _radio_peocess.packet_rssi, _radio_peocess.packet_snr, _radio_peocess.packetID);
		if (0 == tb05_radio_respone(cmd_data, (strlen(cmd_data) + 1)))
			printf("CAD_RESPONE_CMD status upload\r\n");
		break;
	case STANDBY_RESPONE_CMD:
		snprintf(cmd_data, sizeof(cmd_data), "{\"type\":24,\"awake\":1}");
		if (0 == tb05_radio_respone(cmd_data, (strlen(cmd_data) + 1)))
			printf("STANDBY_RESPONE_CMD status upload\r\n");
		break;
	case SLEEP_RESPONE_CMD:
		snprintf(cmd_data, sizeof(cmd_data), "{\"type\":25,\"awake\":1}");
		if (0 == tb05_radio_respone(cmd_data, (strlen(cmd_data) + 1)))
			printf("SLEEP_RESPONE_CMD status upload\r\n");
		break;
	default:
		break;
	}
}

/* upload all config once connected (Synchronous configuration) */
void radio_setting_update(LoRa_mode_t realtime_Mode)
{
	// char cmd_data[200] = "{\"type\":1,\"modem\":1,\"frq\":\"470000000\",\"sf\":7,\"bw\":0,\"cr\":1,\"pwr\":22,\"preambleLength\":8,\"packetNum\":101,\"interval\":200,\"dataLength\":5,\"data\":\"hello\"}";
	int JSON_Length = 0;
	cJSON *root = cJSON_CreateObject();
	cJSON_AddItemToObject(root, "type", cJSON_CreateNumber(realtime_Mode)); // add tpye
	switch (realtime_Mode)
	{
	case TX_MODE:
		cJSON_AddItemToObject(root, "modem", cJSON_CreateNumber(_radio_peocess.modem));
		cJSON_AddItemToObject(root, "frq", cJSON_CreateNumber(_radio_peocess.freq));
		cJSON_AddItemToObject(root, "sf", cJSON_CreateNumber(_radio_peocess.sf));
		cJSON_AddItemToObject(root, "bw", cJSON_CreateNumber(_radio_peocess.bandwidth));
		cJSON_AddItemToObject(root, "cr", cJSON_CreateNumber(_radio_peocess.coderate));
		cJSON_AddItemToObject(root, "pwr", cJSON_CreateNumber(_radio_peocess.tx_process_data.power));
		cJSON_AddItemToObject(root, "preambleLength", cJSON_CreateNumber(_radio_peocess.preambleLen));
		cJSON_AddItemToObject(root, "packetNum", cJSON_CreateNumber(_radio_peocess.packetNum));
		cJSON_AddItemToObject(root, "interval", cJSON_CreateNumber(_radio_peocess.tx_process_data.interval));
		cJSON_AddItemToObject(root, "dataLength", cJSON_CreateNumber(_radio_peocess.tx_process_data.bufferLen));
		cJSON_AddItemToObject(root, "data", cJSON_CreateString(_radio_peocess.tx_process_data.buffer));
		break;
	case RX_MODE:
		cJSON_AddItemToObject(root, "modem", cJSON_CreateNumber(_radio_peocess.modem));
		cJSON_AddItemToObject(root, "frq", cJSON_CreateNumber(_radio_peocess.freq));
		cJSON_AddItemToObject(root, "sf", cJSON_CreateNumber(_radio_peocess.sf));
		cJSON_AddItemToObject(root, "bw", cJSON_CreateNumber(_radio_peocess.bandwidth));
		cJSON_AddItemToObject(root, "cr", cJSON_CreateNumber(_radio_peocess.coderate));
		cJSON_AddItemToObject(root, "preambleLength", cJSON_CreateNumber(_radio_peocess.preambleLen));
		cJSON_AddItemToObject(root, "packetNum", cJSON_CreateNumber(_radio_peocess.packetNum));
		break;
	case CAD_MODE:
		cJSON_AddItemToObject(root, "modem", cJSON_CreateNumber(_radio_peocess.modem));
		cJSON_AddItemToObject(root, "frq", cJSON_CreateNumber(_radio_peocess.freq));
		cJSON_AddItemToObject(root, "sf", cJSON_CreateNumber(_radio_peocess.sf));
		cJSON_AddItemToObject(root, "bw", cJSON_CreateNumber(_radio_peocess.bandwidth));
		cJSON_AddItemToObject(root, "cr", cJSON_CreateNumber(_radio_peocess.coderate));
		cJSON_AddItemToObject(root, "preambleLength", cJSON_CreateNumber(_radio_peocess.preambleLen));
		cJSON_AddItemToObject(root, "rxPeriod", cJSON_CreateNumber(_radio_peocess.cad_process_data.rxPeriod));
		cJSON_AddItemToObject(root, "sleepPeriod", cJSON_CreateNumber(_radio_peocess.cad_process_data.sleepPeriod));
		break;
	case STAND_BY: //{"type":4}
		break;
	case DEEPSLEEP: //{"type":5}
		break;
	default:
		break;
	}
	char * json_data = cJSON_PrintUnformatted(root);
	JSON_Length = strlen(json_data);
	if (LoRa_realtime_Mode > 1 || LoRa_realtime_Mode < 6)
	{
		// printf("LoRa_realtime_Mode value: %s", LoRa_Mode_String[LoRa_realtime_Mode]);
		// printf("send cmd: %s", json_data);
		tb05_radio_respone(json_data, JSON_Length);
	}
	free(json_data);
	cJSON_free(root);
}

/* send data by default when power on */
void sx126x_init_process(void) {
	// /*
	memset(&_radio_peocess, 0, sizeof(Radio_peocess_t));

	_radio_peocess.modem = LORA_MODE;
	_radio_peocess.freq = LORA_FRE;
	_radio_peocess.tx_process_data.power = LORA_TX_OUTPUT_POWER;
	_radio_peocess.bandwidth = LORA_BANDWIDTH;
	_radio_peocess.sf = LORA_SPREADING_FACTOR;
	_radio_peocess.coderate = LORA_CODINGRATE;
	_radio_peocess.tx_process_data.interval = TX_INTERVAL;
	_radio_peocess.preambleLen = LORA_PREAMBLE_LENGTH;
	memcpy(_radio_peocess.tx_process_data.buffer, TX_BUFFER, sizeof(TX_BUFFER));
	_radio_peocess.tx_process_data.bufferLen = TX_BUFFER_LEN;
	_radio_peocess.packetID = 0;
	_radio_peocess.packet_rssi = 0;
	_radio_peocess.packet_snr = 0;
	_radio_peocess.packetNum = PACKET_NUM;
	SX126xRadioInit();

	Ra03sch_TxMode_Set();

	if(1 == PA_MODE && _radio_peocess.tx_process_data.power > 3){
		_radio_peocess.tx_process_data.power = 3;
		printf("PA Mode:Power less than 3\r\n");
	}

	Radio.SetChannel(_radio_peocess.freq);
	Radio.SetTxConfig(MODEM_LORA, _radio_peocess.tx_process_data.power, 0, _radio_peocess.bandwidth,
					_radio_peocess.sf, _radio_peocess.coderate,
					_radio_peocess.preambleLen, LORA_FIX_LENGTH_PAYLOAD_ON,
					true, 0, 0, LORA_IQ_INVERSION_ON, 60000);
	printf("start radio transmit modem: %s, freq: %d\r\n", (_radio_peocess.modem == 1) ? "LoRa" : " FSK", _radio_peocess.freq);
	printf("start radio transmit power: %d, bandwidth: %d, sf: %d, coderate: %d, preambleLen: %d\r\n", _radio_peocess.tx_process_data.power, _radio_peocess.bandwidth, _radio_peocess.sf, _radio_peocess.coderate, _radio_peocess.preambleLen);
	printf("start radio transmit length: %d,body: %s\r\n", _radio_peocess.tx_process_data.bufferLen, _radio_peocess.tx_process_data.buffer);
	Radio.Send((uint8_t *)_radio_peocess.tx_process_data.buffer, _radio_peocess.tx_process_data.bufferLen);
	LoRa_realtime_Mode = TX_MODE;
	// */
	/*
	memset(&_radio_peocess, 0, sizeof(Radio_peocess_t));
	_radio_peocess.modem = LORA_MODE;
	_radio_peocess.freq = LORA_FRE;
	_radio_peocess.bandwidth = LORA_BANDWIDTH;
	_radio_peocess.sf = LORA_SPREADING_FACTOR;
	_radio_peocess.coderate = LORA_CODINGRATE;
	_radio_peocess.preambleLen = LORA_PREAMBLE_LENGTH;
	_radio_peocess.packetID = 0;
	_radio_peocess.packetNum = 100;
	_radio_peocess.cad_process_data.rxPeriod = 1280; // n*15.625   20ms
	_radio_peocess.cad_process_data.sleepPeriod = 16000; // n*15.625 280ms
	SX126xRadioInit();

	Ra03sch_RxMode_Set();

	Radio.SetChannel(_radio_peocess.freq);
	Radio.SetRxConfig(MODEM_LORA, _radio_peocess.bandwidth, _radio_peocess.sf,
	_radio_peocess.coderate, 0, _radio_peocess.preambleLen,
	LORA_SX126X_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON,
	0, true, 0, 0, LORA_IQ_INVERSION_ON, true);
	Radio.Rx(LORA_RX_TIMEOUT_VALUE);
	// Radio.SetRxDutyCycle(_radio_peocess.cad_process_data.rxPeriod, _radio_peocess.cad_process_data.sleepPeriod);
	LoRa_realtime_Mode = RX_MODE;
	printf("start radio transmit modem: %s, freq: %d\r\n", (_radio_peocess.modem == 1) ? "LoRa" : " FSK", _radio_peocess.freq);
	// printf("start radio bandwidth: %d, sf: %d, coderate: %d, preambleLen: %d\r\n", _radio_peocess.bandwidth, _radio_peocess.sf, _radio_peocess.coderate, _radio_peocess.preambleLen);
	*/
} 

/*lora config data parse and process*/
void sx126x_cmd_process(void)
{
	char radio_freq[KEY_MAX_LENGTH] = {0};
	char radio_data[KEY_MAX_LENGTH] = {0};
	char radio_preambleLen[KEY_MAX_LENGTH] = {0};
	int cmd_type_int = 0, key_len = 0;
	cJSON *pJsonRoot, *pJSON_cmd_type, *pJSON_radio_modem, *pJSON_radio_freq,
		*pJSON_radio_sf, *pJSON_radio_bw, *pJSON_radio_cr, *pJSON_radio_power,
		*pJSON_radio_packetNum, *pJSON_radio_interval, *pJSON_radio_dataLen,
		*pJSON_radio_data, *pJSON_radio_preambleLen;
	memset(radio_freq, 0, KEY_MAX_LENGTH);
	memset(radio_data, 0, KEY_MAX_LENGTH);
	memset(radio_preambleLen, 0, KEY_MAX_LENGTH);
	printf("Got cmd length: %d\r\nbody: %s\r\n", TB05_Fram_Record_Struct.InfBit.FramLength, TB05_Fram_Record_Struct.Data_RX_BUF);
	pJsonRoot = cJSON_Parse(TB05_Fram_Record_Struct.Data_RX_BUF);
	if (pJsonRoot != NULL)
	{
		pJSON_cmd_type = cJSON_GetObjectItem(pJsonRoot, "type");
		if (pJSON_cmd_type != NULL)
		{
			cmd_type_int = pJSON_cmd_type->valueint;
			// printf("Got cmd type: %d\r\n", cmd_type_int);
			switch (cmd_type_int)
			{
			case RADIO_SEND_CMD:
				printf("RADIO_SEND_CMD\r\n");
				// {
				// 	"type":1,
				// 	"modem":1,
				// 	"frq":"470000000",
				// 	"sf":7,
				// 	"bw":0,
				// 	"cr":1,
				// 	"pwr":22,
				//  "preambleLength":8,
				// 	"packetNum":101,
				// 	"interval":200,
				// 	"dataLength":5,
				// 	"data":"hello"
				// }
				pJSON_radio_modem = cJSON_GetObjectItem(pJsonRoot, "modem");
				if (pJSON_radio_modem != NULL)
				{
					_radio_peocess.modem = pJSON_radio_modem->valueint;
					printf("Got cmd modem: %d\r\n", _radio_peocess.modem);
				}
				pJSON_radio_freq = cJSON_GetObjectItem(pJsonRoot, "frq");
				if (pJSON_radio_freq != NULL)
				{
					key_len = strlen(pJSON_radio_freq->valuestring);
					memcpy(radio_freq, pJSON_radio_freq->valuestring, key_len);
					radio_freq[key_len + 1] = '\0';
					_radio_peocess.freq = atol(radio_freq);
					printf("Got cmd frq: %u\r\n", _radio_peocess.freq);
				}
				pJSON_radio_sf = cJSON_GetObjectItem(pJsonRoot, "sf");
				if (pJSON_radio_sf != NULL)
				{
					_radio_peocess.sf = pJSON_radio_sf->valueint;
					printf("Got cmd sf: %d\r\n", _radio_peocess.sf);
				}
				pJSON_radio_bw = cJSON_GetObjectItem(pJsonRoot, "bw");
				if (pJSON_radio_bw != NULL)
				{
					_radio_peocess.bandwidth = pJSON_radio_bw->valueint;
					printf("Got cmd bw: %d\r\n", _radio_peocess.bandwidth);
				}
				pJSON_radio_cr = cJSON_GetObjectItem(pJsonRoot, "cr");
				if (pJSON_radio_cr != NULL)
				{
					_radio_peocess.coderate = pJSON_radio_cr->valueint;
					printf("Got cmd cr: %d\r\n", _radio_peocess.coderate);
				}
				pJSON_radio_preambleLen = cJSON_GetObjectItem(pJsonRoot, "preambleLength");
				if (pJSON_radio_preambleLen != NULL)
				{
					_radio_peocess.preambleLen = pJSON_radio_preambleLen->valueint;
					printf("Got cmd preambleLen: %d\r\n", _radio_peocess.preambleLen);
				}
				pJSON_radio_power = cJSON_GetObjectItem(pJsonRoot, "pwr");
				if (pJSON_radio_power != NULL)
				{
					_radio_peocess.tx_process_data.power = pJSON_radio_power->valueint;
					printf("Got cmd pwr: %d\r\n", _radio_peocess.tx_process_data.power);
				}
				pJSON_radio_packetNum = cJSON_GetObjectItem(pJsonRoot, "packetNum");
				if (pJSON_radio_packetNum != NULL)
				{
					_radio_peocess.packetNum = pJSON_radio_packetNum->valueint;
					printf("Got cmd packetNum: %d\r\n", _radio_peocess.packetNum);
				}
				pJSON_radio_interval = cJSON_GetObjectItem(pJsonRoot, "interval");
				if (pJSON_radio_interval != NULL)
				{
					_radio_peocess.tx_process_data.interval = pJSON_radio_interval->valueint;
					printf("Got cmd interval: %d\r\n", _radio_peocess.tx_process_data.interval);
				}
				pJSON_radio_dataLen = cJSON_GetObjectItem(pJsonRoot, "dataLength");
				if (pJSON_radio_dataLen != NULL)
				{
					_radio_peocess.tx_process_data.bufferLen = pJSON_radio_dataLen->valueint;
					printf("Got cmd dataLength: %d\r\n", _radio_peocess.tx_process_data.bufferLen);
				}
				pJSON_radio_data = cJSON_GetObjectItem(pJsonRoot, "data");
				if (pJSON_radio_data != NULL)
				{
					memcpy(_radio_peocess.tx_process_data.buffer, pJSON_radio_data->valuestring, _radio_peocess.tx_process_data.bufferLen);
					_radio_peocess.tx_process_data.buffer[_radio_peocess.tx_process_data.bufferLen] = '\0';
					printf("Got cmd data: %s\r\n", _radio_peocess.tx_process_data.buffer);
				}
				_radio_peocess.packetID = 0;
				if (RADIO_OK == radio_tx_process())
				{
					tb05_status_respone(cmd_type_int + RESPONE_STATUS, 1);
					LoRa_realtime_Mode = TX_MODE;
				}else
				{
					tb05_status_respone(cmd_type_int + RESPONE_STATUS, 0);
				}
				break;
			case RADIO_RECV_CMD:
				printf("RADIO_RECV_CMD\r\n");
				// {
				// 	"type":2,
				// 	"modem":1,
				// 	"frq":"470000000",
				//  "preambleLength":8,
				// 	"sf":7,
				// 	"bw":0,
				// 	"cr":1,
				// 	"packetNum":101
				// }
				pJSON_radio_modem = cJSON_GetObjectItem(pJsonRoot, "modem");
				if (pJSON_radio_modem != NULL)
				{
					_radio_peocess.modem = pJSON_radio_modem->valueint;
					printf("Got cmd modem: %d\r\n", _radio_peocess.modem);
				}
				pJSON_radio_freq = cJSON_GetObjectItem(pJsonRoot, "frq");
				if (pJSON_radio_freq != NULL)
				{
					key_len = strlen(pJSON_radio_freq->valuestring);
					memcpy(radio_freq, pJSON_radio_freq->valuestring, key_len);
					radio_freq[key_len + 1] = '\0';
					_radio_peocess.freq = atol(radio_freq);
					printf("Got cmd frq: %u\r\n", _radio_peocess.freq);
				}
				pJSON_radio_sf = cJSON_GetObjectItem(pJsonRoot, "sf");
				if (pJSON_radio_sf != NULL)
				{
					_radio_peocess.sf = pJSON_radio_sf->valueint;
					printf("Got cmd sf: %d\r\n", _radio_peocess.sf);
				}
				pJSON_radio_bw = cJSON_GetObjectItem(pJsonRoot, "bw");
				if (pJSON_radio_bw != NULL)
				{
					_radio_peocess.bandwidth = pJSON_radio_bw->valueint;
					printf("Got cmd bw: %d\r\n", _radio_peocess.bandwidth);
				}
				pJSON_radio_cr = cJSON_GetObjectItem(pJsonRoot, "cr");
				if (pJSON_radio_cr != NULL)
				{
					_radio_peocess.coderate = pJSON_radio_cr->valueint;
					printf("Got cmd bw: %d\r\n", _radio_peocess.coderate);
				}
				pJSON_radio_preambleLen = cJSON_GetObjectItem(pJsonRoot, "preambleLength");
				if (pJSON_radio_preambleLen != NULL)
				{
					_radio_peocess.preambleLen = pJSON_radio_preambleLen->valueint;
					printf("Got cmd preambleLen: %d\r\n", _radio_peocess.preambleLen);
				}
				pJSON_radio_packetNum = cJSON_GetObjectItem(pJsonRoot, "packetNum");
				if (pJSON_radio_packetNum != NULL)
				{
					_radio_peocess.packetNum = pJSON_radio_packetNum->valueint;
					printf("Got cmd packetNum: %d\r\n", _radio_peocess.packetNum);
				}
				_radio_peocess.packetID = 0;
				if (RADIO_OK == radio_rx_process())
				{
					tb05_status_respone(cmd_type_int + RESPONE_STATUS, 1);
					LoRa_realtime_Mode = RX_MODE;
				}
				else
				{
					tb05_status_respone(cmd_type_int + RESPONE_STATUS, 0);
				}
				break;
			case RADIO_CAD_CMD:
				printf("RADIO_CAD_CMD\r\n");
				// {
				// 	"type": 3,
				// 	"modem":1,
				// 	"preambleLength":8,
				// 	"frq":"470000000",
				// 	"sf":7,
				// 	"bw":0,
				// 	"cr":1,
				// 	"rxPeriod":6400	  #单位，秒（15.625 µs），RxDuration = 6400 * 15.625 µs = 100ms
				// 	"sleepPeriod":6400  #单位，秒（15.625 µs），sleepDuration = 6400 * 15.625 µs = 100ms
				// }
				pJSON_radio_modem = cJSON_GetObjectItem(pJsonRoot, "modem");
				if (pJSON_radio_modem != NULL)
				{
					_radio_peocess.modem = pJSON_radio_modem->valueint;
					printf("Got cmd modem: %d\r\n", _radio_peocess.modem);
				}
				pJSON_radio_freq = cJSON_GetObjectItem(pJsonRoot, "frq");
				if (pJSON_radio_freq != NULL)
				{
					key_len = strlen(pJSON_radio_freq->valuestring);
					memcpy(radio_freq, pJSON_radio_freq->valuestring, key_len);
					radio_freq[key_len + 1] = '\0';
					_radio_peocess.freq = atol(radio_freq);
					printf("Got cmd frq: %u\r\n", _radio_peocess.freq);
				}
				pJSON_radio_sf = cJSON_GetObjectItem(pJsonRoot, "sf");
				if (pJSON_radio_sf != NULL)
				{
					_radio_peocess.sf = pJSON_radio_sf->valueint;
					printf("Got cmd sf: %d\r\n", _radio_peocess.sf);
				}
				pJSON_radio_bw = cJSON_GetObjectItem(pJsonRoot, "bw");
				if (pJSON_radio_bw != NULL)
				{
					_radio_peocess.bandwidth = pJSON_radio_bw->valueint;
					printf("Got cmd bw: %d\r\n", _radio_peocess.bandwidth);
				}
				pJSON_radio_cr = cJSON_GetObjectItem(pJsonRoot, "cr");
				if (pJSON_radio_cr != NULL)
				{
					_radio_peocess.coderate = pJSON_radio_cr->valueint;
					printf("Got cmd bw: %d\r\n", _radio_peocess.coderate);
				}
				pJSON_radio_preambleLen = cJSON_GetObjectItem(pJsonRoot, "preambleLength");
				if (pJSON_radio_preambleLen != NULL)
				{
					_radio_peocess.preambleLen = pJSON_radio_preambleLen->valueint;
					printf("Got cmd preambleLen: %d\r\n", _radio_peocess.preambleLen);
				}
				pJSON_radio_packetNum = cJSON_GetObjectItem(pJsonRoot, "rxPeriod");
				if (pJSON_radio_packetNum != NULL)
				{
					_radio_peocess.cad_process_data.rxPeriod = pJSON_radio_packetNum->valueint;
					printf("Got cmd packetNum: %d\r\n", _radio_peocess.cad_process_data.rxPeriod);
				}
				pJSON_radio_interval = cJSON_GetObjectItem(pJsonRoot, "sleepPeriod");
				if (pJSON_radio_interval != NULL)
				{
					_radio_peocess.cad_process_data.sleepPeriod = pJSON_radio_interval->valueint;
					printf("Got cmd packetNum: %d\r\n", _radio_peocess.cad_process_data.sleepPeriod);
				}
				_radio_peocess.packetID = 0;
				if (RADIO_OK == radio_cad_process())
				{
					tb05_status_respone(cmd_type_int + RESPONE_STATUS, 1);
					LoRa_realtime_Mode = CAD_MODE;
				}
				else
				{
					tb05_status_respone(cmd_type_int + RESPONE_STATUS, 0);
				}
				break;
			case RADIO_STANDBY_CMD:
				//{"type":4}
				printf("RADIO_STANDBY_CMD\r\n");
				if (RADIO_OK == radio_standby_process())
				{
					tb05_status_respone(cmd_type_int + RESPONE_STATUS, 1);
					LoRa_realtime_Mode = STAND_BY;
				}
				else
				{
					tb05_status_respone(cmd_type_int + RESPONE_STATUS, 0);
				}
				break;
			case RADIO_SLEEP_CMD:
				//{"type":5}
				printf("RADIO_SLEEP_CMD\r\n");
				if (RADIO_OK == radio_sleep_process())
				{
					tb05_status_respone(cmd_type_int + RESPONE_STATUS, 1);
					LoRa_realtime_Mode = DEEPSLEEP;
				}
				else
				{
					tb05_status_respone(cmd_type_int + RESPONE_STATUS, 0);
				}
				break;
			case UPDATE_CMD:
				printf("SEND UPDATE DATA\r\n");
				radio_setting_update(LoRa_realtime_Mode);
				break;
			default:
				printf("error command\r\n");
				break;
			}
		}
		else
		{
			printf("error type\r\n");
		}
	}
	else
	{
		printf("data is not an JSON\r\n");
	}
	cJSON_Delete(pJsonRoot);
}

void LoRa_IRQ_Handle(void){
	static int blink_count = 0;
	static int tx_interval = 0;
	Radio.IrqProcess();
	if (1 == g_lora_rx_done)
	{
		if(blink_count < 100){
			GPIO_WriteBit(GPIOA, GREEN_LED, Bit_SET);
		}else {
			g_lora_tx_done = 0;
			g_lora_rx_done = 0;
		}
		blink_count ++;
	}
	else if (1 == g_lora_tx_done)
	{
		if (blink_count < (_radio_peocess.tx_process_data.interval / 2))
		{
			GPIO_WriteBit(GPIOA, GREEN_LED, Bit_SET);
		}
		else if (blink_count < _radio_peocess.tx_process_data.interval)
		{
			GPIO_WriteBit(GPIOA, GREEN_LED, Bit_RESET);
			if (TX_MODE == LoRa_realtime_Mode)
			{
				if (tx_interval > (_radio_peocess.tx_process_data.interval/100))
				{
					if(_radio_peocess.packetID < _radio_peocess.packetNum){
						Radio.Send((uint8_t *)_radio_peocess.tx_process_data.buffer, _radio_peocess.tx_process_data.bufferLen);
					}
					tx_interval = 0;
					g_lora_tx_done = 0;
				}
				tx_interval++;
			}
		}else{
			blink_count = 0;
		}
		blink_count++;
		g_lora_rx_done = 0;
	}
	else
	{
		blink_count = 0;
		GPIO_WriteBit(GPIOA, GREEN_LED, Bit_RESET);
	}
}
