/*!
 * \file      sx1262mbxcas-board.c
 *
 * \brief     Target board SX1262MBXCAS 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 "sx126x-board.h"

uint8_t SPI_WriteBuffer[256+4];
uint8_t SPI_ReadBuffer[256+4];


/*!
 * Flag used to mark if basic io init have finished.
 */
static bool LoRaIOInitFlag = false;


#if defined( USE_RADIO_DEBUG )
/*!
 * \brief Writes new Tx debug pin state
 *
 * \param [IN] state Debug pin state
 */
static void SX126xDbgPinTxWrite( uint8_t state );

/*!
 * \brief Writes new Rx debug pin state
 *
 * \param [IN] state Debug pin state
 */
static void SX126xDbgPinRxWrite( uint8_t state );
#endif

/*!
 * \brief Holds the internal operating mode of the radio
 */
static RadioOperatingModes_t OperatingMode;


void SX126xIoInit( void )//[移植需修改]
{
	//需要对RESET、DIO、BUSY引脚初始化，如果已在前边进行了初始化，则可以省略
  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_SET);

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

  /*Configure GPIO pin : DIO1_Pin */
  GPIO_InitStruct.Pin = DIO1_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
  GPIO_InitStruct.Pull = GPIO_PULLDOWN;
  HAL_GPIO_Init(DIO1_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : BUSY_Pin */
  GPIO_InitStruct.Pin = BUSY_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(BUSY_GPIO_Port, &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;



void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)//[移植需修改]
{
	//此函数为HAL库提供的GPIO外部中断接口，客户应在各自平台的外部中断中回调各DIO_IRQ_Handler(x)函数
	if(LoRaIOInitFlag)
	{
		if(GPIO_Pin == GPIO_PIN_0)
		{
			//printf("dio0 interrupt.\r\n");
			if(DIOx_IRQ_Function!=NULL)
			{
				DIOx_IRQ_Function(NULL);
			}
		}	
	}
}


void SX126xIoIrqInit( DioIrqHandler dioIrq )//[移植需修改]
{
    DIOx_IRQ_Function=dioIrq;

	//应当在配置好中断服务函数和各自的回调后再开启外部引脚中断，对于没有使用的引脚，应予以关闭
	/* EXTI interrupt init*/
	if(DIOx_IRQ_Function != NULL)
	{
		HAL_NVIC_SetPriority(EXTI0_IRQn, 0, 0);
		HAL_NVIC_EnableIRQ(EXTI0_IRQn);
	}
	else
	{
		HAL_NVIC_DisableIRQ(EXTI0_IRQn);
	}
	LoRaIOInitFlag = true;
}



void SX126xIoDbgInit( 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 SX126xReset( void )//[移植需修改]
{
	//根据客户平台接口完成模块复位操作

		//延时10ms
		DelayMs( 10 );
	
		//将RESET引脚拉低
		HAL_GPIO_WritePin(RESET_GPIO_Port, RESET_Pin, GPIO_PIN_RESET);

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

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

void SX126xWaitOnBusy( void )//[移植需修改]
{
    while( GPIO_PIN_SET == HAL_GPIO_ReadPin(BUSY_GPIO_Port,BUSY_Pin));
}

void SX126xWakeup( void )//[移植需修改]
{
		SPI_WriteBuffer[0] = RADIO_GET_STATUS;
		SPI_WriteBuffer[1] =  0;
	
		HAL_GPIO_WritePin(SPI1_NSS_GPIO_Port, SPI1_NSS_Pin, GPIO_PIN_RESET);
		HAL_SPI_Transmit(&hspi1,SPI_WriteBuffer,2,500);
    HAL_GPIO_WritePin(SPI1_NSS_GPIO_Port, SPI1_NSS_Pin, GPIO_PIN_SET);

    // Wait for chip to be ready.
    SX126xWaitOnBusy( );

    // Update operating mode context variable
    SX126xSetOperatingMode( MODE_STDBY_RC );

}

void SX126xWriteCommand( RadioCommands_t command, uint8_t *buffer, uint16_t size )//[移植需修改]
{
    SX126xCheckDeviceReady( );

    SPI_WriteBuffer[0] = command ;
		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);

    if( command != RADIO_SET_SLEEP )
    {
        SX126xWaitOnBusy( );
    }
}

uint8_t SX126xReadCommand( RadioCommands_t command, uint8_t *buffer, uint16_t size )//[移植需修改]
{
    uint8_t status = 0;

    SX126xCheckDeviceReady( );

		SPI_WriteBuffer[0] = command;
		memset(&SPI_WriteBuffer[1],0,size+1);
		//需要比size多1个的NOP(0),是因为发送完命令字后需要等待模块处理，具体参见13.5节
	
		HAL_GPIO_WritePin(SPI1_NSS_GPIO_Port, SPI1_NSS_Pin, GPIO_PIN_RESET);
		HAL_SPI_TransmitReceive(&hspi1,SPI_WriteBuffer,SPI_ReadBuffer,size+2,500);
		HAL_GPIO_WritePin(SPI1_NSS_GPIO_Port, SPI1_NSS_Pin, GPIO_PIN_SET);
	
    status = SPI_ReadBuffer[1];
	
		memcpy(buffer,&SPI_ReadBuffer[2],size);

    SX126xWaitOnBusy( );

    return status;
}

void SX126xWriteRegisters( uint16_t address, uint8_t *buffer, uint16_t size )//[移植需修改]
{
    SX126xCheckDeviceReady( );

		SPI_WriteBuffer[0] = RADIO_WRITE_REGISTER;
		SPI_WriteBuffer[1] = ( address & 0xFF00 ) >> 8;
		SPI_WriteBuffer[2] = address & 0x00FF;
		memcpy(&SPI_WriteBuffer[3],buffer,size);
	
		HAL_GPIO_WritePin(SPI1_NSS_GPIO_Port, SPI1_NSS_Pin, GPIO_PIN_RESET);
		HAL_SPI_Transmit(&hspi1,SPI_WriteBuffer,size+3,500);
		HAL_GPIO_WritePin(SPI1_NSS_GPIO_Port, SPI1_NSS_Pin, GPIO_PIN_SET);

    SX126xWaitOnBusy( );
}


void SX126xReadRegisters( uint16_t address, uint8_t *buffer, uint16_t size )//[移植需修改]
{
    SX126xCheckDeviceReady( );

		SPI_WriteBuffer[0] = RADIO_READ_REGISTER;
		SPI_WriteBuffer[1] = ( address & 0xFF00 ) >> 8;
		SPI_WriteBuffer[2] = address & 0x00FF;
		memset(&SPI_WriteBuffer[3],0,size+1);
		//需要比size多1个的NOP(0),是因为发送完命令字和地址/偏移后需要等待模块处理，具体参见13.2节
	
		HAL_GPIO_WritePin(SPI1_NSS_GPIO_Port, SPI1_NSS_Pin, GPIO_PIN_RESET);
		HAL_SPI_TransmitReceive(&hspi1,SPI_WriteBuffer,SPI_ReadBuffer,size+4,500);
		HAL_GPIO_WritePin(SPI1_NSS_GPIO_Port, SPI1_NSS_Pin, GPIO_PIN_SET);
	
		memcpy(buffer,&SPI_ReadBuffer[4],size);
	
    SX126xWaitOnBusy( );
}



void SX126xWriteBuffer( uint8_t offset, uint8_t *buffer, uint8_t size )//[移植需修改]
{
    SX126xCheckDeviceReady( );

		SPI_WriteBuffer[0] = RADIO_WRITE_BUFFER;
		SPI_WriteBuffer[1] = offset;
		memcpy(&SPI_WriteBuffer[2],buffer,size);
	
		HAL_GPIO_WritePin(SPI1_NSS_GPIO_Port, SPI1_NSS_Pin, GPIO_PIN_RESET);
		HAL_SPI_Transmit(&hspi1,SPI_WriteBuffer,size+2,500);
		HAL_GPIO_WritePin(SPI1_NSS_GPIO_Port, SPI1_NSS_Pin, GPIO_PIN_SET);
		
    SX126xWaitOnBusy( );
}

void SX126xReadBuffer( uint8_t offset, uint8_t *buffer, uint8_t size )//[移植需修改]
{
    SX126xCheckDeviceReady( );

		SPI_WriteBuffer[0] = RADIO_READ_BUFFER;
		SPI_WriteBuffer[1] = offset;
		memset(&SPI_WriteBuffer[2],0,size+1);
		//需要比size多1个的NOP(0),是因为发送完命令字和地址/偏移后需要等待模块处理，具体参见13.2节

		HAL_GPIO_WritePin(SPI1_NSS_GPIO_Port, SPI1_NSS_Pin, GPIO_PIN_RESET);
		HAL_SPI_TransmitReceive(&hspi1,SPI_WriteBuffer,SPI_ReadBuffer,size+3,500);
		HAL_GPIO_WritePin(SPI1_NSS_GPIO_Port, SPI1_NSS_Pin, GPIO_PIN_SET);
	
		memcpy(buffer,&SPI_ReadBuffer[3],size);
		
    SX126xWaitOnBusy( );
}

uint32_t SX126xGetDio1PinState( 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 )
static void SX126xDbgPinTxWrite( 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);
		}
}

static void SX126xDbgPinRxWrite( 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 SX126xIoTcxoInit( void )
{
    //LR30-H10不使用TCXO
		/*
    CalibrationParams_t calibParam;

    SX126xSetDio3AsTcxoCtrl( TCXO_CTRL_1_7V, SX126xGetBoardTcxoWakeupTime( ) << 6 ); // convert from ms to SX126x time base
    calibParam.Value = 0x7F;
    SX126xCalibrate( calibParam );
		*/
}

uint32_t SX126xGetBoardTcxoWakeupTime( void )
{
    return 0;//LR30-H10不使用TCXO
}

void SX126xIoRfSwitchInit( void )
{
    SX126xSetDio2AsRfSwitchCtrl( true );
}

RadioOperatingModes_t SX126xGetOperatingMode( void )
{
    return OperatingMode;
}

void SX126xSetOperatingMode( RadioOperatingModes_t mode )
{
    OperatingMode = mode;

    switch( mode )
    {
        case MODE_TX:
						SX126xAntSwTx();
#if defined( USE_RADIO_DEBUG )
            SX126xDbgPinTxWrite( 1 );
            SX126xDbgPinRxWrite( 0 );
#endif	
            break;
        case MODE_RX:
        case MODE_RX_DC:
				case MODE_CAD:
						SX126xAntSwRx();
#if defined( USE_RADIO_DEBUG )
            SX126xDbgPinTxWrite( 0 );
            SX126xDbgPinRxWrite( 1 );
#endif
            break;
        default:
						SX126xAntSwOff();
#if defined( USE_RADIO_DEBUG )
            SX126xDbgPinTxWrite( 0 );
            SX126xDbgPinRxWrite( 0 );
#endif
            break;
    }

}
void SX126xIoDeInit( void )
{
    //实际并不需要反初始化
}
void SX126xWriteRegister( uint16_t address, uint8_t value )
{
    SX126xWriteRegisters( address, &value, 1 );
}
uint8_t SX126xReadRegister( uint16_t address )
{
    uint8_t data;
    SX126xReadRegisters( address, &data, 1 );
    return data;
}


void SX126xSetRfTxPower( int8_t power )
{
    SX126xSetTxParams( power, RADIO_RAMP_40_US );
}

uint8_t SX126xGetDeviceId( void )
{
   return SX1262;
}

void SX126xAntSwOn( void )
{
    //LR30-H10的射频开关控制为自动，此处留空
}
void SX126xAntSwTx( void )//[移植需修改]
{
    //LR30-H10的射频开关控制为自动，此处留空
}
void SX126xAntSwRx( void )//[移植需修改]
{
    //LR30-H10的射频开关控制为自动，此处留空

}	
void SX126xAntSwOff( void )
{
    //LR30-H10的射频开关控制为自动，此处留空
}

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