#include "sx1276.h"
#include "sx1276-LoRa.h"
#include "sx1276-LoRaMisc.h"
#include "sx1276-Hal.h"
#include "radio.h"
#include <string.h>
#include "application.h"
#include "main.h"

/** 
 * 模组基本参数定义
 */
extern tLoRaSettings LoRaSettings;

/** 
 * 模组数据操作缓存 
 */
static uint8_t  e32_buffer[128];

/** 
 * 模组数据操作长度
 */
static uint16_t e32_rx_length = 0;

/**
 * @brief  (可选的)模组SPI读写测试
 *
 * @note 如果失败了，请检查电气链接。也可以先短接SPI的 MISO MOSI，先测试自发自收是否正确
 */
static void e32_spi_check(void)
{
		uint8_t temp = 0;
	
		SX1276Reset();
	
		SX1276Read(REG_LR_FRFMSB,&temp);
		
		/* 比较 */
    if( 0x6C != temp )
    {
        /* 一般是SPI通信异常 请检查接线 */
				while(1);
    }		
}

/**
 * @brief  模组初始化
 */
void e32_demo_init( void )
{
	/* (可选) SPI通信检查 */
	e32_spi_check();	
	
	/* 工作参数 */
	LoRaSettings.RFFrequency      = 915000000; // 收发频率Hz
	LoRaSettings.SignalBw         = 9;         // 发送带宽BW [0: 7.8kHz, 1: 10.4 kHz, 2: 15.6 kHz, 3: 20.8 kHz, 4: 31.2 kHz,5: 41.6 kHz, 6: 62.5 kHz, 7: 125 kHz, 8: 250 kHz, 9: 500 kHz]
	LoRaSettings.SpreadingFactor  = 11;        // 扩频因子SF [6~12]
	LoRaSettings.ErrorCoding      = 1;         // 编码CR     [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8]
	LoRaSettings.CrcOn            = true;      // CrcOn            [0: OFF, 1: ON]
	LoRaSettings.ImplicitHeaderOn = false,     // ImplicitHeaderOn [0: OFF, 1: ON]
	LoRaSettings.RxSingleOn       = 1,         // RxSingleOn       [0: Continuous, 1 Single]
	LoRaSettings.FreqHopOn        = 0,         // FreqHopOn        [0: OFF, 1: ON]
	LoRaSettings.HopPeriod        = 4,         // HopPeriod Hops every frequency hopping period symbols
	LoRaSettings.TxPacketTimeout  = 1000,      // TxPacketTimeout
	LoRaSettings.RxPacketTimeout  = 1000,      // RxPacketTimeout
	LoRaSettings.PayloadLength    = 128,       // PayloadLength (used for implicit header mode)
	
	/**
	 * 1级 发射功率 20dBm
	 * (30dBm模组的)软件控制功率仅仅是射频芯片输出功率(1级)，经由功率放大器PA增益后才输出最终功率(2级)
	 * 由于PA本身的非线性特性，一般需要射频功率计或者频谱仪对最终功率(2级)进行标定
	 * @note 915MHz只能粗略给出1级与2级对应关系，仅供参考：
	 * 1级20dBm ≈  2级30dBm    
	 * 1级17dBm ≈  2级27dBm    
	 * 1级14dBm ≈  2级24dBm    
	 * 1级11dBm ≈  2级21dBm    	 	 
	 */	
	LoRaSettings.Power            = 20;        // 发送功率dBm[5~20]

	/* 初始化 */
	SX1276Init();
}

/**
 * @brief 使用显示菜单用户配置参数重新配置模组
 *
 * @param config 菜单配置参数信息
 */
void e32_demo_menu_config( menu_config_t *config )
{
	int8_t power_select;
	
	/* LORA调制参数 (与空中速率、接收灵敏度有关联)
     可以使用计算器	https://www.semtech.com/design-support/lora-calculator */
	LoRaSettings.RFFrequency      = config->frequency_mhz * 1000000; // 收发频率Hz
	LoRaSettings.SignalBw         = config->lora_bw;                 // 发送带宽BW [0: 7.8kHz, 1: 10.4 kHz, 2: 15.6 kHz, 3: 20.8 kHz, 4: 31.2 kHz,5: 41.6 kHz, 6: 62.5 kHz, 7: 125 kHz, 8: 250 kHz, 9: 500 kHz]
	LoRaSettings.SpreadingFactor  = config->lora_sf;                 // 扩频因子SF [6~12]
	LoRaSettings.ErrorCoding      = config->lora_cr;                 // 编码CR     [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8]

	/* 菜单设定2级功率转换为对应的1级功率 */	
	switch( config->tx_power )
	{
		case 27: 
			power_select = 17; 
			break;
		
		case 24:
			power_select = 14; 
			break;			
		
		case 21:
			power_select = 11; 
			break;	

		default:
			power_select = 20; 
			break;
	}		
	
	/**
	 * 1级 发射功率 
	 * (30dBm模组的)软件控制功率仅仅是射频芯片输出功率(1级)，经由功率放大器PA增益后才输出最终功率(2级)
	 * 由于PA本身的非线性特性，一般需要射频功率计或者频谱仪对最终功率(2级)进行标定
	 * @note 915MHz只能粗略给出1级与2级对应关系，仅供参考：
	 * 1级20dBm ≈  2级30dBm    
	 * 1级17dBm ≈  2级27dBm    
	 * 1级14dBm ≈  2级24dBm    
	 * 1级11dBm ≈  2级21dBm    	 	 
	 */		
	LoRaSettings.Power = power_select; // 发送功率dBm[5~20]	
	
	/* 初始化 */
	SX1276Init();
}

/**
 * @brief 向模组写入数据并开始发射
 *
 * @param buffer 指向数据缓存
 * @param length 写入长度
 */
void e32_demo_transmit( uint8_t *buffer , uint8_t length )
{
	gpio_led_tx_on();
	
	///@note 启动发射并不带表发送已完成，要等到发送完成标识读取到后才算是完成 请参考 RF_TX_DONE
	SX1276SetTxPacket( buffer , length );
}

/**
 * @brief  模组切换到接收状态
 */
void e32_demo_receive( void )
{
	SX1276StartRx();
}

/**
 * @brief  查询是否有接收数据
 *
 * @param   buffer 指向待拷贝数据缓存
 * @param   length 接收数据长度
 * @return  bool 有新接收数据则返回true; 否则返回false。
 */
bool e32_demo_check_rx_done( uint8_t *buffer, uint8_t * length  , double *rssi)
{
	bool ret = false;
	
	if( e32_rx_length != 0 )
	{
		memcpy( buffer ,  e32_buffer , e32_rx_length );
		
		*length = e32_rx_length ;
		e32_rx_length = 0;
		
		*rssi = SX1276LoRaGetPacketRssi();
		
		ret = true;
	}
	
	return ret;
}

/**
 * @brief  模组轮询任务 (状态机)
 *
 * @note 该示例仅放在主循环中执行
 */
void e32_demo_task(void)
{
	switch ( SX1276Process() )
	{
		case RF_RX_DONE:
			SX1276GetRxPacket( e32_buffer , &e32_rx_length );
			gpio_led_rx_on();
			break;
		
		case RF_TX_DONE:
			gpio_led_tx_off();
			break;		
	}
}


