/*!
 * \file      sx1276mb1las-board.c
 *
 * \brief     Target board SX1276MB1LAS shield driver implementation
 *
 * \copyright Revised BSD License, see section \ref LICENSE.
 *
 * \code
 *                ______                              _
 *               / _____)             _              | |
 *              ( (____  _____ ____ _| |_ _____  ____| |__
 *               \____ \| ___ |    (_   _) ___ |/ ___)  _ \
 *               _____) ) ____| | | || |_| ____( (___| | | |
 *              (______/|_____)_|_|_| \__)_____)\____)_| |_|
 *              (C)2013-2017 Semtech
 *
 * \endcode
 *
 * \author    Miguel Luis ( Semtech )
 *
 * \author    Gregory Cristian ( Semtech )
 */
#include <stdlib.h>
#include "radio.h"
#include "stdio.h"
#include "sx1276-board.h"



uint8_t SPI_WriteBuffer[256+4];
uint8_t SPI_ReadBuffer[256+4];
void DIO_IRQ_Handler(uint8_t id);
/*!
 * Flag used to mark if basic io init have finished.
 */
static bool LoRaIOInitFlag = false;

/*!
 * Radio driver structure initialization
 */
const struct Radio_s Radio =
{
    SX1276Init,
    SX1276GetStatus,
    SX1276SetModem,
    SX1276SetChannel,
    SX1276IsChannelFree,
    SX1276Random,
    SX1276SetRxConfig,
    SX1276SetTxConfig,
    SX1276CheckRfFrequency,
    SX1276GetTimeOnAir,
    SX1276Send,
    SX1276SetSleep,
    SX1276SetStby,
    SX1276SetRx,
    SX1276StartCad,
    SX1276SetTxContinuousWave,
    SX1276ReadRssi,
    SX1276Write,
    SX1276Read,
    SX1276WriteBuffer,
    SX1276ReadBuffer,
    SX1276SetMaxPayloadLength,
    SX1276SetPublicNetwork,
    SX1276GetWakeupTime,
    NULL, // void ( *IrqProcess )( void )
    NULL, // void ( *RxBoosted )( uint32_t timeout ) - SX126x Only
    NULL, // void ( *SetRxDutyCycle )( uint32_t rxTime, uint32_t sleepTime ) - SX126x Only
};

void SX1276IoInit( void )//[移植需修改]
{
	//需要对RESET、DIOx、SPI引脚初始化，如果已在前边进行了初始化，则可以省略
	//DIOx引脚实际并不需要6个全部使用，参考SX1278的Datasheet “Digital IO Pin Mapping”一节可知，仅使用DIO0、DIO1即可满足绝大部分应用
	//如果客户仅使用其中某个DIO，应在SX1276IoInit函数和SX1276IoIrqInit函数中作出相应配置修改。
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOF_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(RESET_GPIO_Port, RESET_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(SPI1_NSS_GPIO_Port, SPI1_NSS_Pin, GPIO_PIN_SET);

  /*Configure GPIO pins : DIO0_Pin DIO1_Pin DIO2_Pin DIO3_Pin
                           DIO4_Pin DIO5_Pin */
  GPIO_InitStruct.Pin = DIO0_Pin|DIO1_Pin|DIO2_Pin|DIO3_Pin
                          |DIO4_Pin|DIO5_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
  GPIO_InitStruct.Pull = GPIO_PULLDOWN;
  HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);

  /*Configure GPIO pin : RESET_Pin */
  GPIO_InitStruct.Pin = RESET_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(RESET_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : SPI1_NSS_Pin */
  GPIO_InitStruct.Pin = SPI1_NSS_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(SPI1_NSS_GPIO_Port, &GPIO_InitStruct);
}
DioIrqHandler *DIOx_IRQ_Function[6];



void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)//[移植需修改]
{
	//此函数为HAL库提供的GPIO外部中断接口，客户应在各自平台的外部中断中回调各DIO_IRQ_Handler(x)函数
	if(LoRaIOInitFlag)
	{
		switch(GPIO_Pin)
		{
			case GPIO_PIN_0:DIO_IRQ_Handler(0);break;
			case GPIO_PIN_1:DIO_IRQ_Handler(1);break;
			case GPIO_PIN_2:DIO_IRQ_Handler(2);break;
			case GPIO_PIN_3:DIO_IRQ_Handler(3);break;
			case GPIO_PIN_4:DIO_IRQ_Handler(4);break;
			case GPIO_PIN_5:DIO_IRQ_Handler(5);break;
			default:break;
		}	
	}
}
void SX1276IoIrqInit( DioIrqHandler **irqHandlers )//[移植需修改]
{
	DIOx_IRQ_Function[0]=irqHandlers[0];
	DIOx_IRQ_Function[1]=irqHandlers[1];
	DIOx_IRQ_Function[2]=irqHandlers[2];
	DIOx_IRQ_Function[3]=irqHandlers[3];
	DIOx_IRQ_Function[4]=irqHandlers[4];
	DIOx_IRQ_Function[5]=irqHandlers[5];
	
	
	//应当在配置好中断服务函数和各自的回调后再开启外部引脚中断，对于没有使用的引脚，应予以关闭
	  /* EXTI interrupt init*/
	if(DIOx_IRQ_Function[0] != NULL)
	{
		HAL_NVIC_SetPriority(EXTI0_IRQn, 0, 0);
		HAL_NVIC_EnableIRQ(EXTI0_IRQn);
	}
	else
	{
		HAL_NVIC_DisableIRQ(EXTI0_IRQn);
	}
	if(DIOx_IRQ_Function[1] != NULL)
	{
  HAL_NVIC_SetPriority(EXTI1_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(EXTI1_IRQn);
	}
	else
	{
		HAL_NVIC_DisableIRQ(EXTI1_IRQn);
	}
	if(DIOx_IRQ_Function[2] != NULL)
	{
  HAL_NVIC_SetPriority(EXTI2_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(EXTI2_IRQn);
	}
	else
	{
		HAL_NVIC_DisableIRQ(EXTI2_IRQn);
	}
	if(DIOx_IRQ_Function[3] != NULL)
	{
  HAL_NVIC_SetPriority(EXTI3_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(EXTI3_IRQn);
	}
	else
	{
		HAL_NVIC_DisableIRQ(EXTI3_IRQn);
	}
	if(DIOx_IRQ_Function[4] != NULL)
	{
  HAL_NVIC_SetPriority(EXTI4_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(EXTI4_IRQn);
	}
	else
	{
		HAL_NVIC_DisableIRQ(EXTI4_IRQn);
	}
	if(DIOx_IRQ_Function[5] != NULL)
	{
  HAL_NVIC_SetPriority(EXTI9_5_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(EXTI9_5_IRQn);
	}
	else
	{
		HAL_NVIC_DisableIRQ(EXTI9_5_IRQn);
	}
	LoRaIOInitFlag = true;
}


void SX1276WriteBuffer( uint32_t addr, uint8_t *buffer, uint8_t size )//[移植需修改]
{
	//需按照客户的平台完成SPI传输函数
		SPI_WriteBuffer[0] = addr | 0x80;
		memcpy(&SPI_WriteBuffer[1],buffer,size);
		HAL_GPIO_WritePin(SPI1_NSS_GPIO_Port, SPI1_NSS_Pin, GPIO_PIN_RESET);
		HAL_SPI_Transmit(&hspi1,SPI_WriteBuffer,size+1,500);
		HAL_GPIO_WritePin(SPI1_NSS_GPIO_Port, SPI1_NSS_Pin, GPIO_PIN_SET);
}

void SX1276ReadBuffer( uint32_t addr, uint8_t *buffer, uint8_t size )//[移植需修改]
{
	//需按照客户的平台完成SPI传输函数
		SPI_WriteBuffer[0] = addr & 0x7F;
		memset(&SPI_WriteBuffer[1],0,size);
		HAL_GPIO_WritePin(SPI1_NSS_GPIO_Port, SPI1_NSS_Pin, GPIO_PIN_RESET);
		HAL_SPI_TransmitReceive(&hspi1,SPI_WriteBuffer,SPI_ReadBuffer,size+1,500);
		HAL_GPIO_WritePin(SPI1_NSS_GPIO_Port, SPI1_NSS_Pin, GPIO_PIN_SET);
    memcpy(buffer,&SPI_ReadBuffer[1],size);
}


void SX1276IoDbgInit( void )//[移植需修改]
{
	//本函数用2个IO来指示模块所处状态，以供调试使用，如不需要，可取消USE_RADIO_DEBUG宏定义
#if defined( USE_RADIO_DEBUG )

	//需要对DEBUG引脚初始化，如果已在前边进行了初始化，则可以省略
	
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOA_CLK_ENABLE();
	
	/*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOA, DBG_PIN_TX_Pin|DBG_PIN_RX_Pin, GPIO_PIN_RESET);
	
  /*Configure GPIO pins : DBG_PIN_TX_Pin DBG_PIN_RX_Pin */
  GPIO_InitStruct.Pin = DBG_PIN_TX_Pin|DBG_PIN_RX_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
#endif
	
}

void SX1276Reset( void )//[移植需修改]
{
	//根据客户平台接口完成模块复位操作
    // Enables the TCXO if available on the board design
    SX1276SetBoardTcxo( true );

		//将RESET引脚拉低
		HAL_GPIO_WritePin(RESET_GPIO_Port, RESET_Pin, GPIO_PIN_RESET);

		//延时1ms
		DelayMs( 1 );
	
		//将RESET引脚拉高
		HAL_GPIO_WritePin(RESET_GPIO_Port, RESET_Pin, GPIO_PIN_SET);

		//延时6ms
		DelayMs( 6 );
}

uint32_t SX1276GetDio1PinState( void )//[移植需修改]
{
	//反馈DIO1引脚状态，高为1，低为0
	if(GPIO_PIN_SET == HAL_GPIO_ReadPin(DIO1_GPIO_Port,DIO1_Pin))
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

#if defined( USE_RADIO_DEBUG )
void SX1276DbgPinTxWrite( uint8_t state )//[移植需修改]
{
		//调试引脚输出状态
		if(state)
		{
			HAL_GPIO_WritePin(DBG_PIN_TX_GPIO_Port, DBG_PIN_TX_Pin, GPIO_PIN_SET);
		}
		else
		{
			HAL_GPIO_WritePin(DBG_PIN_TX_GPIO_Port, DBG_PIN_TX_Pin, GPIO_PIN_RESET);
		}
}

void SX1276DbgPinRxWrite( uint8_t state )//[移植需修改]
{
		//调试引脚输出状态
		if(state)
		{
			HAL_GPIO_WritePin(DBG_PIN_RX_GPIO_Port, DBG_PIN_RX_Pin, GPIO_PIN_SET);
		}
		else
		{
			HAL_GPIO_WritePin(DBG_PIN_RX_GPIO_Port, DBG_PIN_RX_Pin, GPIO_PIN_RESET);
		}
}
#endif






//以下函数不需要修改




void SX1276AntSwInit( void )
{
    //LR31的射频开关控制为自动，此处留空
}

void SX1276AntSwDeInit( void )
{
    //LR31的射频开关控制为自动，此处留空
}
void SX1276AntSwOn( void )
{
    //LR31的射频开关控制为自动，此处留空
}
void SX1276AntSwTx( void )//[移植需修改]
{
   //LR31的射频开关控制为自动，此处留空
}
void SX1276AntSwRx( void )//[移植需修改]
{
  //LR31的射频开关控制为自动，此处留空
}	
void SX1276AntSwOff( void )//[移植需修改]
{
	//LR31的射频开关控制为自动，此处留空
}
void SX1276SetAntSw( uint8_t opMode )
{
    switch( opMode )
    {
    case RFLR_OPMODE_TRANSMITTER:
        SX1276AntSwTx();
    break;
    case RFLR_OPMODE_RECEIVER:
    case RFLR_OPMODE_RECEIVER_SINGLE:
    case RFLR_OPMODE_CAD:
				SX1276AntSwRx();
    default:
        SX1276AntSwOff();
    break;
    }
}

bool SX1276CheckRfFrequency( uint32_t frequency )
{
    // Implement check. Currently all frequencies are supported
    return true;
}


//此函数需要在DIOx引脚中断中被回调，id输入0~5
void DIO_IRQ_Handler(uint8_t id)
{

	if(id<=5)
	{
		//printf("dio%d interrupt.\r\n",id);
		if(DIOx_IRQ_Function[id]!=NULL)
		{
			DIOx_IRQ_Function[id](NULL);
		}
	}

}

void SX1276Write( uint32_t addr, uint8_t data )
{
    SX1276WriteBuffer( addr, &data, 1 );
}

uint8_t SX1276Read( uint32_t addr )
{
    uint8_t data;
    SX1276ReadBuffer( addr, &data, 1 );
    return data;
}

void SX1276IoDeInit( void )
{
	//实际并不需要反初始化
}

void SX1276IoTcxoInit( void )
{
    //LR31不使用TCXO
}

void SX1276SetBoardTcxo( uint8_t state )
{
    //LR31不使用TCXO
}

uint32_t SX1276GetBoardTcxoWakeupTime( void )
{
    return 0;//LR31不使用TCXO
}

