/**
  ******************************************************************************
  * @file    SPI_common_interface.c
  * @author  MCD Application Team
  * @brief   Contains USART HW configuration
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2023 Puya Semiconductor Co.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by Puya 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
  *
  ******************************************************************************
  */

#include "spi_common_interface.h"
#include "iwdg_interface.h"
#include "wwdg_interface.h"
#include "openbl_usart_cmd.h"
#include "string.h"

#define SPI_STATE_IDLE 0
#define SPI_STATE_CMD 1


void SPI_Init(SPI_TypeDef * spix, SPI_HandleTypeDef* hspi)
{
  hspi->Instance               = spix;                       /* SPI */
  hspi->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;    /* prescaler :256 */
  hspi->Init.Direction         = SPI_DIRECTION_2LINES;       /* full duplex */
  hspi->Init.CLKPolarity       = SPI_POLARITY_LOW;           /* SPI Clock Polarity: low */
  hspi->Init.CLKPhase          = SPI_PHASE_1EDGE ;           /* Data sampling starts at the first clock edge */
  hspi->Init.DataSize          = SPI_DATASIZE_8BIT;          /* SPI Data Size is 8 bit */
  hspi->Init.FirstBit          = SPI_FIRSTBIT_MSB;           /* SPI MSB Transmission */
  hspi->Init.NSS               = SPI_NSS_HARD_INPUT;         /* NSS Hardware Mode */
  hspi->Init.Mode              = SPI_MODE_SLAVE;             /* Configure as slave */
  hspi->Init.CRCCalculation    = SPI_CRCCALCULATION_DISABLE; /* The CRC check is disabled */

  HAL_SPI_Init(hspi);
}

void SPI_DeInit(SPI_HandleTypeDef* hspi)
{
  HAL_SPI_DeInit(hspi);
}

static void SPI_ReadWrite(SPI_HandleTypeDef* hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t size)
{
  /* Variable used to alternate Rx and Tx during transfer */
  uint32_t             txallowed = 1U;

  /* Set the transaction information */
  hspi->ErrorCode   = HAL_SPI_ERROR_NONE;
  hspi->pRxBuffPtr  = (uint8_t *)pRxData;
  hspi->RxXferCount = size;
  hspi->RxXferSize  = size;
  hspi->pTxBuffPtr  = (uint8_t *)pTxData;
  hspi->TxXferCount = size;
  hspi->TxXferSize  = size;

  /* Check if the SPI is already enabled */
  if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
  {
    /* Enable SPI peripheral */
    __HAL_SPI_ENABLE(hspi);
  }

  if ((hspi->Init.Mode == SPI_MODE_SLAVE) || (size == 0x01U))
  {
    *((__IO uint8_t *)&hspi->Instance->DR) = (*hspi->pTxBuffPtr);
    hspi->pTxBuffPtr += sizeof(uint8_t);
    hspi->TxXferCount--;
  }

  while ((hspi->TxXferCount > 0U) || (hspi->RxXferCount > 0U))
  {
    /* Check TXE flag */
    if ((__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE)) && (hspi->TxXferCount > 0U) && (txallowed == 1U))
    {
      *(__IO uint8_t *)&hspi->Instance->DR = (*hspi->pTxBuffPtr);
      hspi->pTxBuffPtr++;
      hspi->TxXferCount--;
      /* Next Data is a reception (Rx). Tx not allowed */
      txallowed = 0U;
    }

    /* Wait until RXNE flag is reset */
    if ((__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_RXNE)) && (hspi->RxXferCount > 0U))
    {
      (*(uint8_t *)hspi->pRxBuffPtr) = *(__IO uint8_t *)&hspi->Instance->DR;
      hspi->pRxBuffPtr++;
      hspi->RxXferCount--;
      /* Next Data is a Transmission (Tx). Tx is allowed */
      txallowed = 1U;
    }

    OPENBL_WWDG_Refresh();
    OPENBL_IWDG_Refresh();
  }

  while ((hspi->Instance->SR & SPI_FLAG_FTLVL) != SPI_FTLVL_EMPTY)
  {
    OPENBL_WWDG_Refresh();
    OPENBL_IWDG_Refresh();
  }

  while ((__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_BSY) ? SET : RESET) != RESET)
  {
    OPENBL_WWDG_Refresh();
    OPENBL_IWDG_Refresh();
  }

  while ((hspi->Instance->SR & SPI_FLAG_FRLVL) != SPI_FRLVL_EMPTY)
  {
    OPENBL_WWDG_Refresh();
    OPENBL_IWDG_Refresh();
  }
}

void SPI_Read(SPI_HandleTypeDef* hspi, uint8_t *buf, uint16_t size)
{
  uint8_t tmp[0x210];
  SPI_ReadWrite(hspi, tmp, buf, size);
}

void SPI_Write(SPI_HandleTypeDef* hspi, uint8_t *buf, uint16_t size)
{
  uint8_t tmp[0x210];
  SPI_ReadWrite(hspi, buf, tmp, size);
}

uint8_t SPI_ProtocolDetection(SPI_HandleTypeDef* hspi)
{
  uint8_t tmp_rx[0x3];
  uint8_t tmp_tx[0x3];

  OPENBL_WWDG_Refresh();
  OPENBL_IWDG_Refresh();

  /* Check if the SPI is already enabled */
  if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
  {
    /* Enable SPI peripheral */
    __HAL_SPI_ENABLE(hspi);

    *(__IO uint8_t *)&hspi->Instance->DR = 0xA5;
  }

  /* Check the RXNE flag */
  if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_RXNE))
  {
    /* read the received data */
    tmp_rx[0] = *(__IO uint8_t *)&hspi->Instance->DR;

    if(SYNC_BYTE == tmp_rx[0])
    {
      tmp_tx[0] = ACK_BYTE;

      SPI_Write(hspi, tmp_tx, 1);

      return 1;
    }

    *(__IO uint8_t *)&hspi->Instance->DR = 0xA5;
  }

  return 0;
}

/************************ (C) COPYRIGHT Puya *****END OF FILE****/
