/******************************************************************************/
/**
 * @file crc_calc.c
 *
 * @brief This file contains functions that provides demonstration of
 *        usage of CRC calculation APIs
 *
 * The functions provided in the file provides demonstration on
 * usage of CRCcalculation APIs
 *
 * @copyright Copyright 2023 Antaris, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/******************************************************************************/


#include "crc_cal.h"
#include "stdio.h"
#include "string.h"
#include "exo_common.h"
#include "stm32f7xx_hal_ext.h"
/******************************************************************************/
/*                  Definition of local macros                  			  */
/******************************************************************************/


#ifdef CALC__CRC_HEADER

/*  CRC input for Header part
 *  0x8100000-0x81002C
 *  checksum stored at 0x810002C
 *  buffer size 0x810002C - 0x8100000 = 0x2C
 *  0x420 is checksum address
 */
#define BUFFER_SIZE	(0x2C)/4
#define CRC_APPEND_ADDR 0x810002C
#define CRC_CALC_START_ADDR 0x8100000

#else

/*  CRC input for Binary part
 *  0x8100030-0x810420
 *  checksum stored at 0x8100420
 *  buffer size 0x8100420 - 0x8100030 = 0x3f0
 *  0x420 is checksum address
 */
#define BUFFER_SIZE	(0x3f0)/4
#define CRC_APPEND_ADDR 0x8100420
#define CRC_CALC_START_ADDR 0x8100030

#endif

/******************************************************************************/
/*                       Definition of local variables                        */
/******************************************************************************/

static __IO uint32_t myCRCValue1 = 0xFFFFFFFF;
static uint32_t *myDataBuffer;


/******************************************************************************/
/*                  Declaration of local function prototypes                  */
/******************************************************************************/


/**
 * @brief This function used to calculate CRC by applying CRC32 algorithm
 *
 * @param[in]  Crc : previously calculated CRC
 * @param[in]  Data : data to caluclated CRC
 *
 * @return calculated CRC value
 * @retval CRC value
 */
static uint32_t Crc32(uint32_t Crc, uint32_t Data);

/**
 * @brief This function used to calculate CRC by applying CRC32 algorithm
 */
static uint32_t Crc32(uint32_t Crc, uint32_t Data)
{
  uint8_t index;

  Crc = Crc ^ Data;

  for(index=0; index<32; index++)
  {
    if (Crc & 0x80000000)
      Crc = (Crc << 1) ^ 0x04C11DB7; // Polynomial used in STM32
    else
      Crc = (Crc << 1);
  }
  return(Crc);
}



/******************************************************************************/
/*                      Definition of global functions                        */
/******************************************************************************/


/**
 * @brief This function used to perform integrity check and return the status
 */
uint8_t crc32_checking(uint32_t start_address, uint32_t length, uint32_t crc_append_address )
{
	uint8_t crc_status;

	//  uint16_t myDataBufferCount = BUFFER_SIZE;
	  myDataBuffer = (uint32_t*) start_address;
	  myCRCValue1 = 0xFFFFFFFF;
	  while (length--)
	  {
	    myCRCValue1 = Crc32(myCRCValue1, *myDataBuffer++);
	  }


	  if (myCRCValue1 == *(uint32_t*)crc_append_address)
	  {
		  crc_status = 1;
	  }
	  else
	  {
		  crc_status =0;
	  }
	  return crc_status;
}



/**
 * @brief This function used to calculate CRCand append at the end of data buffer
 *
 * @param[in]  start_address : address of the data buffer to calculate CRC CRC from this memory
 * @param[in]  length : length of memory to calculate CRC
 *
 * @return status of integrity
 * @retval 1 indicates integrity pass
 */
void crc32_calculate_crc_and_append(uint32_t start_address, uint16_t length )
{
	uint32_t *crc_save_addr;
	uint16_t length_save;

	length_save = length*4;
	//  uint16_t myDataBufferCount = BUFFER_SIZE;
	  myDataBuffer = (uint32_t*) start_address;
	  myCRCValue1 = 0xFFFFFFFF;
	  while (length--)
	  {
	    myCRCValue1 = Crc32(myCRCValue1, *myDataBuffer++);
	  }

	  crc_save_addr = (uint32_t*)(start_address + length_save);
	  *crc_save_addr = myCRCValue1;

}




/**
 * @brief This function used to calculate integrity and return the calculated CRC
 */
uint32_t calc_checksum_memory(uint8_t *data_buf,uint32_t length)
{
	uint32_t read_buffer = 0xffffffff;
	uint32_t calc_CRC;
	uint32_t buf_inc;

	// checking if the file exist or not
	if (data_buf == NULL)
	{
		DEBUG_CPRINT(("INTG | Buffer ptr Null  !\n"));
		return 0;
	}
	buf_inc = 0;
	calc_CRC = 0xFFFFFFFF;
	while (length > 3)
	{
		memcpy(&read_buffer,&data_buf[buf_inc],4);
		calc_CRC = Crc32(calc_CRC, read_buffer);
		length -= 4;
		buf_inc +=4;
	}

	return calc_CRC;
}

