/* Includes ------------------------------------------------------------------*/
#include "compute.h"

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
const uint8_t bytes1[8] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88};
const uint16_t bytes2[4] = {0x2211, 0x4433, 0x6655, 0x8877};
const uint32_t bytes3[2] = {0x44332211, 0x88776655};

uint32_t result1 = 0;
uint32_t result2 = 0;
uint32_t result3 = 0;
uint32_t result4 = 0;

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

/**
  * @brief  Verify CRC computes the byte array
  * @param  None
  * @retval 0 - Pass
  *         Others - Failed
  */
uint8_t compute(void)
{
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_CRC, ENABLE);

  /************* x16+x12+x5+1, Input data reverse, Output data reverse , 8bit acess ***************/
  result1 = CRC16_X25_ComputeBytes(bytes1, _countof(bytes1));
  if (result1 != 0xF74A)
    return 0x01;

  /************* x16+x12+x5+1, Input data reverse, Output data reverse , 8bit acess ***************/
  CRC16_X25_ComputeBytes(bytes1, 4);
  result2 = CRC16_X25_ComputeBytesContinue(bytes1 + 4, _countof(bytes1) - 4);
  if (result2 != 0xF74A)
    return 0x02;

  /************* x16+x12+x5+1, Input data reverse, Output data reverse , 16bit acess ***************/
  result3 = CRC16_X25_ComputeHalfWords(bytes2, _countof(bytes2));
  if (result3 != 0xF74A)
    return 0x03;

  /************* x16+x12+x5+1, Input data reverse, Output data reverse , 32bit acess ***************/
  result4 = CRC16_X25_ComputeWords(bytes3, _countof(bytes3));
  if (result4 != 0xF74A)
    return 0x04;

  return 0x00;
}

/**
  * @brief  Computes the 16-bit CRC-CCITT of a given buffer of byte(8-bit) with default seed.
  * @param  ptr_data: Pointer to the buffer containing the data to be computed
  * @param  data_len: Length of the buffer to be computed
  * @retval 16-bit CRC-CCITT
  */
uint16_t CRC16_X25_ComputeBytes(const uint8_t *ptr_data, uint32_t data_len)
{
  CRC_InitResult(); // Reset the CRC result
  while (data_len--)
  {
    *(uint8_t *)(CRC_DataAddress) = *ptr_data++;
  }
  __NOP();
  __NOP();
  return (CRC->RESULT & CRC_RESULT_RESULT_Msk);
}

/**
  * @brief  Continue Computes the 16-bit CRC-CCITT of a given buffer of byte(8-bit) with default seed.
  * @param  ptr_data: Pointer to the buffer containing the data to be computed
  * @param  data_len: Length of the buffer to be computed
  * @retval 16-bit CRC-CCITT
  */
uint16_t CRC16_X25_ComputeBytesContinue(const uint8_t *ptr_data, uint32_t data_len)
{
  while (data_len--)
  {
    *(uint8_t *)(CRC_DataAddress) = *ptr_data++;
  }
  __NOP();
  __NOP();
  return (CRC->RESULT & CRC_RESULT_RESULT_Msk);
}

/**
  * @brief  Computes the 16-bit CRC-CCITT of a given buffer of byte(8-bit) with default seed.
  * @param  ptr_data: Pointer to the buffer containing the data to be computed
  * @param  data_len: Length of the buffer to be computed
  * @retval 16-bit CRC-CCITT
  */
uint16_t CRC16_X25_ComputeHalfWords(const uint16_t *ptr_data, uint32_t data_len)
{
  CRC_InitResult(); // Reset the CRC result
  while (data_len--)
  {
    *(uint16_t *)(CRC_DataAddress) = *ptr_data++;
  }
  __NOP();
  __NOP();
  return (CRC->RESULT & CRC_RESULT_RESULT_Msk);
}

/**
  * @brief  Computes the 16-bit CRC-CCITT of a given buffer of byte(8-bit) with default seed.
  * @param  ptr_data: Pointer to the buffer containing the data to be computed
  * @param  data_len: Length of the buffer to be computed
  * @retval 16-bit CRC-CCITT
  */
uint16_t CRC16_X25_ComputeWords(const uint32_t *ptr_data, uint32_t data_len)
{
  CRC_InitResult(); // Reset the CRC result
  while (data_len--)
  {
    *(uint32_t *)(CRC_DataAddress) = *ptr_data++;
  }
  __NOP();
  __NOP();
  return (CRC->RESULT & CRC_RESULT_RESULT_Msk);
}
