/*!
  * \file      sx1276mb1mas-board.c
  *
  * \brief     Target board SX1276MB1MAS 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 )
  */
/**
  ******************************************************************************
  * @file    sx1276mb1mas.c
  * @author  MCD Application Team
  * @brief   driver sx1276mb1mas board
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2018 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/

#include "sx1276mb1mas.h"


#define IRQ_HIGH_PRIORITY  10

#define RF_MID_BAND_THRESH                          525000000

extern osMutexId SPIMutexHandle;

/* Private variables ---------------------------------------------------------*/
static const uint32_t RADIO_DIO_EXTI_LINE[RADIO_DIOn] =
{
  RADIO_DIO_0_EXTI_LINE,
  RADIO_DIO_1_EXTI_LINE,
  RADIO_DIO_2_EXTI_LINE,
  RADIO_DIO_3_EXTI_LINE,
#if( RADIO_DIOn > 4 )
  RADIO_DIO_4_EXTI_LINE,
#endif
#if( RADIO_DIOn > 5 )
  RADIO_DIO_5_EXTI_LINE,
#endif
};

#ifndef SPI3_HAL_CONFIG
static const uint32_t RADIO_DIO_IT_PRIO [RADIO_DIOn] =
{
  RADIO_DIO_0_IT_PRIO,
  RADIO_DIO_1_IT_PRIO,
  RADIO_DIO_2_IT_PRIO,
  RADIO_DIO_3_IT_PRIO,
#if( RADIO_DIOn > 4 )
  RADIO_DIO_4_IT_PRIO,
#endif
#if( RADIO_DIOn > 5 )
  RADIO_DIO_5_IT_PRIO,
#endif
};

static const IRQn_Type RADIO_DIO_IRQn [RADIO_DIOn]   =
{
  RADIO_DIO_0_IRQn,
  RADIO_DIO_1_IRQn,
  RADIO_DIO_2_IRQn,
  RADIO_DIO_3_IRQn,
#if( RADIO_DIOn > 4 )
  RADIO_DIO_4_IRQn,
#endif
#if( RADIO_DIOn > 5 )
  RADIO_DIO_5_IRQn,
#endif
};
#endif

static GPIO_TypeDef *RADIO_DIO_PORT[RADIO_DIOn] =
{
  RADIO_DIO_0_PORT,
  RADIO_DIO_1_PORT,
  RADIO_DIO_2_PORT,
  RADIO_DIO_3_PORT,
#if( RADIO_DIOn > 4 )
  RADIO_DIO_4_PORT,
#endif
#if( RADIO_DIOn > 5 )
  RADIO_DIO_5_PORT,
#endif
};

static const uint16_t RADIO_DIO_PIN[RADIO_DIOn] =
{
  RADIO_DIO_0_PIN,
  RADIO_DIO_1_PIN,
  RADIO_DIO_2_PIN,
  RADIO_DIO_3_PIN,
#if( RADIO_DIOn > 4 )
  RADIO_DIO_4_PIN,
#endif
#if( RADIO_DIOn > 5 )
  RADIO_DIO_5_PIN,
#endif
};

static const uint32_t RADIO_DIO_MODE[RADIO_DIOn] =
{
  GPIO_MODE_IT_RISING,
  GPIO_MODE_IT_RISING_FALLING,
  GPIO_MODE_IT_RISING,
  GPIO_MODE_IT_RISING,
#if( RADIO_DIOn > 4 )
  GPIO_MODE_IT_RISING,
#endif
#if( RADIO_DIOn > 5 )
  GPIO_MODE_IT_RISING,
#endif
};

/* static */ EXTI_HandleTypeDef hRADIO_DIO_exti[RADIO_DIOn];

/* Private function prototypes -----------------------------------------------*/

static void SX1276MB1MAS_RADIO_SPI_IoInit(SPI_HandleTypeDef *spiHandle);
static void SX1276MB1MAS_RADIO_SPI_IoDeInit(void);

/* Exported functions ---------------------------------------------------------*/
uint32_t SX1276MB1MAS_RADIO_GetWakeUpTime(void)
{
  return  BOARD_WAKEUP_TIME;
}

void SX1276MB1MAS_RADIO_SetXO(uint8_t state)
{
}

void SX1276MB1MAS_RADIO_IoInit(void)
{
  GPIO_InitTypeDef initStruct = {0};
  SPI_HandleTypeDef dummy_hspi;

  /* Enable DIO GPIO clock */
  RADIO_DIO_0_GPIO_CLK_ENABLE();
  RADIO_DIO_1_GPIO_CLK_ENABLE();
  RADIO_DIO_2_GPIO_CLK_ENABLE();
  RADIO_DIO_3_GPIO_CLK_ENABLE();
#if( RADIO_DIOn > 4 )
  RADIO_DIO_4_GPIO_CLK_ENABLE();
#endif
#if( RADIO_DIOn > 5 )
  RADIO_DIO_5_GPIO_CLK_ENABLE();
#endif

  /* DIO IO Init */
  initStruct.Pull = GPIO_PULLDOWN;
  initStruct.Speed = GPIO_SPEED_HIGH;

  for (uint32_t i = 0; i < RADIO_DIOn ; i++)
  {
    initStruct.Mode = RADIO_DIO_MODE[i];
    initStruct.Pin = RADIO_DIO_PIN[i];
    HAL_GPIO_Init(RADIO_DIO_PORT[i], &initStruct);
  }

#ifdef RFM95
  /* Antenna IO Init */
  RADIO_ANT_CLK_ENABLE();

  initStruct.Pin = RADIO_ANT_SWITCH_PIN;
  initStruct.Mode = GPIO_MODE_OUTPUT_PP;
  initStruct.Pull = GPIO_NOPULL;
  initStruct.Speed = GPIO_SPEED_HIGH;

  //HAL_GPIO_Init(RADIO_ANT_SWITCH_PORT, &initStruct);
#endif

  /* SPI IO Init */
  /* Normally done by the HAL_MSP callback but not for this applic */
  SX1276MB1MAS_RADIO_SPI_IoInit(&dummy_hspi);

  /* NSS initialization */
  initStruct.Pin = RADIO_NSS_PIN;
  initStruct.Mode = GPIO_MODE_OUTPUT_PP;
  initStruct.Pull = GPIO_PULLUP;

  /* Enable NSS */
  RADIO_NSS_CLK_ENABLE();
  HAL_GPIO_Init(RADIO_NSS_PORT, &initStruct);
  HAL_GPIO_WritePin(RADIO_NSS_PORT, RADIO_NSS_PIN, GPIO_PIN_SET);
}

void SX1276MB1MAS_RADIO_IoDeInit(void)
{
  GPIO_InitTypeDef initStruct = {0};

  /* DIO IO DeInit */

  initStruct.Pull = GPIO_PULLDOWN;

  for (uint32_t i = 0; i < RADIO_DIOn ; i++)
  {
    initStruct.Mode = RADIO_DIO_MODE[i];
    initStruct.Pin = RADIO_DIO_PIN[i];
    HAL_GPIO_Init(RADIO_DIO_PORT[i], &initStruct);
  }

  /* SPI IO DeInit */
  SX1276MB1MAS_RADIO_SPI_IoDeInit();

  /* NSS IO DeInit is not done */

  /* Antenna IO DeInit is not done */

  /* Reset IO DeInit is not done */
}

void SX1276MB1MAS_RADIO_IoIrqInit(DioIrqHandler **irqHandlers)
{
  CRITICAL_SECTION_BEGIN();
  for (uint32_t i = 0; i < RADIO_DIOn ; i++)
  {
    HAL_EXTI_GetHandle(&hRADIO_DIO_exti[i], RADIO_DIO_EXTI_LINE[i]);
    HAL_EXTI_RegisterCallback(&hRADIO_DIO_exti[i], HAL_EXTI_COMMON_CB_ID, irqHandlers[i]);
#ifndef SPI3_HAL_CONFIG
    HAL_NVIC_SetPriority(RADIO_DIO_IRQn[i], RADIO_DIO_IT_PRIO[i], 0x00);
    HAL_NVIC_EnableIRQ(RADIO_DIO_IRQn[i]);
#endif
  }
  CRITICAL_SECTION_END();
}

/*!
 * @brief it points the demanded line in the EXTI_HandleTypeDef TABLE before calling HAL_EXTI_IRQHandler()
 * @param [IN]: DIO extiLine demanded
 * @retval none
 * @note "stm32lyxx_it.c" code generated by MX do not call this function but directly the HAL_EXTI_IRQHandler()
 */
void SX1276MB1MAS_RADIO_IRQHandler(RADIO_DIO_TypeDef DIO)
{
  HAL_EXTI_IRQHandler(&hRADIO_DIO_exti[DIO]);
}

TxConfig_TypeDef SX1276MB1MAS_RADIO_GetPaSelect(uint32_t channel)
{
#ifdef RFM95
  return CONF_RFO_LF;
#else
  if (channel > RF_MID_BAND_THRESH)
  {
    return CONF_RFO_LP;
  }
  else
  {
    return CONF_RFO_LF;
  }
#endif
}

void SX1276MB1MAS_RADIO_SetAntSw(RfSw_TypeDef state)
{
#ifndef RFM95
  switch (state)
  {
    case RFSW_OFF:
    {
      HAL_GPIO_WritePin(RADIO_ANT_SWITCH_PORT, RADIO_ANT_SWITCH_PIN, GPIO_PIN_RESET);
      break;
    }
    case RFSW_RX:
    {
      HAL_GPIO_WritePin(RADIO_ANT_SWITCH_PORT, RADIO_ANT_SWITCH_PIN, GPIO_PIN_RESET);
      break;
    }
    case RFSW_RFO_LP:
    {
      HAL_GPIO_WritePin(RADIO_ANT_SWITCH_PORT, RADIO_ANT_SWITCH_PIN, GPIO_PIN_SET);
      break;
    }
    case RFSW_RFO_HP:
    {
      break;
    }
    case RFSW_RFO_LF:
    {
      break;
    }
    default:
      HAL_GPIO_WritePin(RADIO_ANT_SWITCH_PORT, RADIO_ANT_SWITCH_PIN, GPIO_PIN_RESET);
      break;
  }
#endif
}

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

void SX1276MB1MAS_RADIO_Reset(void)
{
#ifndef RFM95
  GPIO_InitTypeDef initStruct = { 0 };

  initStruct.Mode = GPIO_MODE_OUTPUT_PP;
  initStruct.Pull = GPIO_NOPULL;
  initStruct.Speed = GPIO_SPEED_HIGH;
  initStruct.Pin = RADIO_RESET_PIN;

  // Set RESET pin to 0
  HAL_GPIO_Init(RADIO_RESET_PORT, &initStruct);
  HAL_GPIO_WritePin(RADIO_RESET_PORT, RADIO_RESET_PIN, GPIO_PIN_RESET);

  // Wait 1 ms
  osDelay(1);

  // Configure RESET as input
  initStruct.Mode = GPIO_NOPULL;
  HAL_GPIO_Init(RADIO_RESET_PORT, &initStruct);

  // Wait 6 ms
  osDelay(6);
#else
  HAL_GPIO_WritePin(RADIO_RESET_PORT, RADIO_RESET_PIN, GPIO_PIN_RESET);

  // Wait 1 ms
  osDelay(1);
  HAL_GPIO_WritePin(RADIO_RESET_PORT, RADIO_RESET_PIN, GPIO_PIN_SET);

  // Wait 6 ms
  osDelay(6);

#endif
}

/* Bus mapping to SPI */

void SX1276MB1MAS_RADIO_Bus_Init(void)
{
  RADIO_SPI_Init();
}

void SX1276MB1MAS_RADIO_Bus_deInit(void)
{
  RADIO_SPI_DeInit();
}

/**
  * @brief  Send Receive data via SPI
  * @param  Data to send
  * @retval Received data
  */
uint16_t SX1276MB1MAS_RADIO_SendRecv(uint16_t txData)
{
  uint16_t rxData ;

  RADIO_SPI_SendRecv((uint8_t *) &txData, (uint8_t *) &rxData, 1);

  return rxData;
}

void SX1276MB1MAS_RADIO_ChipSelect(int32_t state)
{
  if (state == 0)
  {
	  osStatus status = osMutexWait(SPIMutexHandle, 10);
	  if( status == osOK )
	  {
		  HAL_GPIO_WritePin(RADIO_NSS_PORT, RADIO_NSS_PIN, GPIO_PIN_RESET);
	  }
  }
  else
  {
	  HAL_GPIO_WritePin(RADIO_NSS_PORT, RADIO_NSS_PIN, GPIO_PIN_SET);
	  osMutexRelease(SPIMutexHandle);
  }
}

uint32_t SX1276MB1MAS_RADIO_GetDio1PinState(void)
{
  return HAL_GPIO_ReadPin(RADIO_DIO_1_PORT, RADIO_DIO_1_PIN);
}
/* Private functions --------------------------------------------------------*/

/**
  * @brief  Initializes SPI MSP.
  * @param  hspi  SPI handler
  * @retval None
*/
static void SX1276MB1MAS_RADIO_SPI_IoInit(SPI_HandleTypeDef *spiHandle)
{
  GPIO_InitTypeDef GPIO_InitStruct;
  /* USER CODE BEGIN SPI3_MspInit 0 */

  /* USER CODE END SPI3_MspInit 0 */
  /* Enable Peripheral clock */
  RADIO_SPI_SCK_GPIO_CLK_ENABLE();
  RADIO_SPI_MOSI_GPIO_CLK_ENABLE();
  RADIO_SPI_MISO_GPIO_CLK_ENABLE();

  /**SPI1 GPIO Configuration
  PC10    ------> SPI3_SCK
  PC11    ------> SPI3_MISO
  PC12    ------> SPI3_MOSI
    */
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull = GPIO_PULLDOWN;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;

  GPIO_InitStruct.Alternate = RADIO_SPI_MOSI_GPIO_AF;
  GPIO_InitStruct.Pin = RADIO_SPI_MOSI_GPIO_PIN;
  HAL_GPIO_Init(RADIO_SPI_MOSI_GPIO_PORT, &GPIO_InitStruct);
  GPIO_InitStruct.Alternate = RADIO_SPI_MISO_GPIO_AF;
  GPIO_InitStruct.Pin = RADIO_SPI_MISO_GPIO_PIN;
  HAL_GPIO_Init(RADIO_SPI_MISO_GPIO_PORT, &GPIO_InitStruct);
  GPIO_InitStruct.Alternate = RADIO_SPI_SCK_GPIO_AF;
  GPIO_InitStruct.Pin = RADIO_SPI_SCK_GPIO_PIN;
  HAL_GPIO_Init(RADIO_SPI_SCK_GPIO_PORT, &GPIO_InitStruct);
}

/**
  * @brief  DeInitializes SPI MSP.
  * @param  hspi  SPI handler
  * @retval None
  */
static void SX1276MB1MAS_RADIO_SPI_IoDeInit(void)
{
  GPIO_InitTypeDef GPIO_InitStruct;

  /* Peripheral clock disable */
  /* no need to call SPI1_CLK_DISABLE() because going in LowPower it gets disabled automatically */

  /* DeInitialize Peripheral GPIOs */
  /* Instead of using HAL_GPIO_DeInit() which set ANALOG mode
     it's preferred to set in OUTPUT_PP mode, with the pins set to 0 */

  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLDOWN;
  GPIO_InitStruct.Pin = RADIO_SPI_MOSI_GPIO_PIN;
  HAL_GPIO_Init(RADIO_SPI_MOSI_GPIO_PORT, &GPIO_InitStruct);
  GPIO_InitStruct.Pin = RADIO_SPI_MISO_GPIO_PIN;
  HAL_GPIO_Init(RADIO_SPI_MISO_GPIO_PORT, &GPIO_InitStruct);
  GPIO_InitStruct.Pin = RADIO_SPI_SCK_GPIO_PIN;
  HAL_GPIO_Init(RADIO_SPI_SCK_GPIO_PORT, &GPIO_InitStruct);


  HAL_GPIO_WritePin(RADIO_SPI_MOSI_GPIO_PORT, RADIO_SPI_MOSI_GPIO_PIN, GPIO_PIN_RESET);
  HAL_GPIO_WritePin(RADIO_SPI_MISO_GPIO_PORT, RADIO_SPI_MISO_GPIO_PIN, GPIO_PIN_RESET);
  HAL_GPIO_WritePin(RADIO_SPI_SCK_GPIO_PORT, RADIO_SPI_SCK_GPIO_PIN, GPIO_PIN_RESET);

}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
