#include "test.h"

#define RF_FREQUENCY                                470000000 // Hz
#define TX_OUTPUT_POWER                             22        // dBm
#define LORA_BANDWIDTH                              0         // [0: 125 kHz,
                                                              //  1: 250 kHz,
                                                              //  2: 500 kHz,
                                                              //  3: Reserved]
//注意：官方Demo不推荐使用3(Reserved)，如确需使用，请修改sx1276.c L527~L531和L691~L695的内容以允许其设置
#define LORA_SPREADING_FACTOR                       9         // [SF7..SF12]
#define LORA_CODINGRATE                         																															    1         // [1: 4/5,
                                                              //  2: 4/6,
                                                              //  3: 4/7,
                                                              //  4: 4/8]
#define LORA_PREAMBLE_LENGTH                        8         // Same for Tx and Rx
#define LORA_SYMBOL_TIMEOUT                         5         // Symbols
#define LORA_FIX_LENGTH_PAYLOAD_ON                  false
#define LORA_IQ_INVERSION_ON                        false
#define RX_TIMEOUT_VALUE                            0				//rx continue mode 
																														//当设置为Rx Continue Mode的时候为持续接收（常用），此时则无需再判断接收超时
#define BUFFER_SIZE                                 255 		// Define the payload size here



/**********************************************************************************************
本测试Demo为客户展示了以下内容：
1、LoRa的初始化（包含Radio事件回调函数的注册，SPI通讯验证，LoRa参数的配置等）
2、LoRa的发送示例，在初始化完成后的前4秒内，将进行两次发送，分别发送“hello”“world”两个单词
3、LoRa的接收示例，在接下来的10s内，将等待其他模块发送的数据，接收成功将予以展示。客户可以使用另一个模块发送来测试本模块的接收
4、LoRa的休眠、唤醒示例，在接下来的4s内，将操作LoRa模块进入休眠，然后唤醒（模块进入休眠，MCU主机并没有休眠）
5、LoRa的持续发送载波频率示例，此示例可将模块置于持续发送状态，用户可以使用频谱仪、综测仪等对模块的射频性能进行测试
***********************************************************************************************/
static RadioEvents_t RadioEvents;

uint8_t LoRa_TX_buffer[BUFFER_SIZE],LoRa_RX_buffer[BUFFER_SIZE];

void OnTxDone( void );

void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr );

void OnTxTimeout( void );

void OnRxTimeout( void );

void OnRxError( void );

void LoRa_Init(void)
{
	
		uint8_t Test_Reg=0;
		// Radio initialization
    RadioEvents.TxDone = OnTxDone;
    RadioEvents.RxDone = OnRxDone;
    RadioEvents.TxTimeout = OnTxTimeout;
    RadioEvents.RxTimeout = OnRxTimeout;
    RadioEvents.RxError = OnRxError;
	
		//注册LoRa事件回调函数
    Radio.Init( &RadioEvents );
	
		//本段用来验证客户是否调通了与LoRa芯片的通讯，必须通过才可以进行下一步。

		Radio.Write(0x06C0,0x11);
		Test_Reg = Radio.Read(0x06C0);
		printf("test_reg = 0x%02X\r\nspi read/write test %s\r\n",Test_Reg,Test_Reg==0x11?"passed":"failed");
		if(Test_Reg!=0x11)
		{
			while(1)
			{
				printf("please check spi connect or your software.\r\n");
				DelayMs(2000);
			}
		}
		
		//设置LoRa频率
    Radio.SetChannel( RF_FREQUENCY );


		//设置发送参数
    Radio.SetTxConfig( MODEM_LORA, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH,
                                   LORA_SPREADING_FACTOR, LORA_CODINGRATE,
                                   LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON,
                                   true, 0, 0, LORA_IQ_INVERSION_ON, 3000 );

		//设置接收参数（注意：发送和接收参数有交集，如果该部分配置不一致则以最新配置为准）
    Radio.SetRxConfig( MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR,
                                   LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH,
                                   LORA_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON,
                                   0, true, 0, 0, LORA_IQ_INVERSION_ON, true );

		//设置最大Payload长度，一般设为最大
    Radio.SetMaxPayloadLength( MODEM_LORA, BUFFER_SIZE );
		
		//转入接收状态
		Radio.Rx( RX_TIMEOUT_VALUE );
		
		printf("lora init finish.\r\n");
}
TimerEvent_t TestTimer;


//软定时器回调，将在回调中进行逐项测试
void LoRa_Test_Handle(void * context)
{
	static uint8_t test_cnt=0;
	switch(test_cnt)
	{
		case 0:
			//调用Radio.Send发送数据
			memcpy(LoRa_TX_buffer,"hello",5);
			Radio.Send(LoRa_TX_buffer,5);
			printf("lora send :hello\r\n");
			test_cnt++;
			TimerStart( &TestTimer );
		break;
		case 1:
			//调用Radio.Send发送数据
			memcpy(LoRa_TX_buffer,"world",5);
			Radio.Send(LoRa_TX_buffer,5);
			printf("lora send :world\r\n");
			test_cnt++;
			TimerStart( &TestTimer );
		break;
		case 2:
		case 3:
		case 4:
		case 5:
		case 6:
			//等待接收数据（在上一步发送完成/超时后已在回调中转为接收状态）
			printf("lora waiting to receive\r\n");
			test_cnt++;
			TimerStart( &TestTimer );
		break;
		case 7:
			//让LoRa模块进入休眠
			Radio.Sleep();
			printf("lora sleep\r\n");
			test_cnt++;
			TimerStart( &TestTimer );
		break;
		case 8:
			//让LoRa模块唤醒（可通过将其设为待机、发送、接收、CAD、持续发送等各种工作模式来唤醒）
			Radio.Rx( RX_TIMEOUT_VALUE );
			printf("lora wake up\r\n");
			test_cnt++;
			TimerStart( &TestTimer );
		break;
		case 9:
			//让LoRa模块持续发送载波频率信号
			Radio.SetTxContinuousWave( RF_FREQUENCY, TX_OUTPUT_POWER, 0xffff );
			printf("lora tx continuous wave\r\n");
		break;
	}
	
}
void LoRa_Test_Main(void)
{
	//初始化一个2s的软定时器以按时序展示测试流程
	TimerInit( &TestTimer, LoRa_Test_Handle );
	TimerSetValue( &TestTimer, 2000 );
	TimerStart( &TestTimer );
	
	while(1)
	{
		//该LoRa库需要持续调用IrqProcess()才能处理中断信号回调
		Radio.IrqProcess();
		//该软定时器需要持续调用才能处理回调
		TimerService();
	}
	
}

void OnTxDone( void )
{
	//发送完成回调，发送完成后可以根据客户需求，让其进入接收、休眠、待机等等状态（由于LoRa是一个半双工设备，通常发送完成即转入接收状态）
  Radio.Rx( RX_TIMEOUT_VALUE );
	printf("TxDone\r\n");
}

void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr )
{

	//接收完成回调，可以取出客户需要的信息（如果是持续接收模式则无需再配置为接收模式）
  memcpy(LoRa_RX_buffer,payload, size>BUFFER_SIZE?BUFFER_SIZE:size );

	printf("RxDone,size=%d,rssi=%d,snr=%d,data=\r\n",size,rssi,snr);
	for(uint8_t i=0;i<size;i++)
	{
		printf("[%02X] ",payload[i]);
	}
	printf("\r\n");
}

void OnTxTimeout( void )
{
	//发送超时回调，客户应先检查Radio.SetTxConfig函数所设超时时间是否满足自己正常通讯速率需求（可通过LoRa计算器计算），如确认满足，再分析是否有其他错误导致发送超时
  Radio.Rx( RX_TIMEOUT_VALUE );
	printf("TxTimeout\r\n");
}

void OnRxTimeout( void )
{
	//接收超时回调，客户如果没有选择持续接收模式，则需要给出一个接收时间预期，如果超过该时间则导致回调
  Radio.Rx( RX_TIMEOUT_VALUE );
	printf("RxTimeout\r\n");
}

void OnRxError( void )
{
	//接收错误回调，如果持续出现，客户应分析导致错误的原因
  Radio.Rx( RX_TIMEOUT_VALUE );
	printf("RxError\r\n");
}
