/*
 * peps_util.c
 *
 *  Created on: 2020Äê12ÔÂ6ÈÕ
 *      Author: nxa16228
 */
#include <NJJ29C2_Drv.h>
#include <PEPS_Util.h>
#include <stdint.h>
#include <stdbool.h>
#include "Mcal.h"
#include "Crc_Ip.h"

static uint16_t sphscaCendricCadsConfig_Lfsr = 0xACE1u;

bool cenVerifySpiCrc(const uint8_t *data, uint8_t len)
{
	bool retVal = true;
	uint32_t chkResult = 0x0000u;
	/*
	(void) CRC_DRV_SetSeed(NJJ_CRC_INST, NJJ_CRC_SEED);
	CRC_DRV_WriteData(NJJ_CRC_INST, data, (uint32_t) ((uint32_t) len - 2u));
	chkResult = CRC_DRV_GetCrcResult(NJJ_CRC_INST);
	*/
	chkResult = (uint32_t) Crc_Ip_SetChannelCalculate(
			0, /* const uint32 LogicChannel, */
			data, /* const uint8  *DataPtr, */
			len-2, /* const uint32  Length, */
			0xFFFFFFFF, /* const uint64 StartValue, */
			TRUE);
	/* Verify CRC result */
	if (0x0000u	!= ((uint16_t) (chkResult & 0xFFFFu) ^ 0x0000u))
		retVal = false;
	return retVal;
}

void cenGenerateSpiCrc(uint8_t *data, uint8_t len)
{
	uint32_t chkResult = 0u;
	/*
	(void) CRC_DRV_SetSeed(NJJ_CRC_INST, NJJ_CRC_SEED);
	CRC_DRV_WriteData(NJJ_CRC_INST, data, (uint32_t) ((uint32_t) len - 2u));
	chkResult = CRC_DRV_GetCrcResult(NJJ_CRC_INST);
	*/
	chkResult = (uint32_t) Crc_Ip_SetChannelCalculate(
			0, /* const uint32 LogicChannel, */
			data, /* const uint8  *DataPtr, */
			len-2, /* const uint32  Length, */
			0xFFFFFFFF, /* const uint64 StartValue, */
			TRUE);


	/* Append CRC value to data */
	data[len - 1u] = (uint8_t) ((uint16_t) (chkResult & 0x00FFu));
	data[len - 2u] = (uint8_t) ((uint16_t) (chkResult & 0xFF00u) >> 8u);
}
bool cenVerifyCrcForPkeData(const uint8_t *data, uint8_t len)
{
	bool retVal = false;
	uint16_t i = 0u;
	uint8_t j = 0u;
	uint8_t cCrc = 0u;
	/* The generator polynomial x^8 + x^2 + x + 1 */
	uint8_t cPolynome = 0x07u;
	for (j = 0u; j < len - 1u; j++)
	{
		cCrc = cCrc ^ (data[j]);
		for (i = 0u; i < 8u; i++)
		{
			if (0u != (cCrc & 0x80u))
			{
				cCrc = (uint8_t) (cCrc << 1u);
				cCrc ^= cPolynome;
			}
			else
			{
				cCrc = (uint8_t) (cCrc << 1u);
			}
		}
	}

	/* Checks CRC8 value */
	if (data[len - 1u] == cCrc)
	{
		retVal = true;
	}

	return retVal;
}

void cenGeneratePkeCrc(uint8_t *pkeFrame, uint8_t len)
{
	uint16_t i = 0u;
	uint8_t j = 0u;
	uint8_t cCrc = 0u;
	/* The generator polynomial x^8 + x^2 + x + 1 */
	uint8_t cPolynome = 0x07u;
	for (j = 4u; j < len - 1u; j++)
	{
		cCrc = cCrc ^ (pkeFrame[j]);
		for (i = 0u; i < 8u; i++)
		{
			if (0u != (cCrc & 0x80u))
			{
				cCrc = (uint8_t) (cCrc << 1u);
				cCrc ^= cPolynome;
			}
			else
			{
				cCrc = (uint8_t) (cCrc << 1u);
			}
		}
	}
	/* Append CRC8 value to PKE frame */
	pkeFrame[len - 1u] = cCrc;

}

uint8_t cenGenerateHTPro2Crc(uint8_t * buf, uint8_t len, uint16_t seed)
{
	uint16_t byte = 0u;
	uint16_t crcVal = seed;

	uint8_t i = 0u;
	uint8_t j = 0u;

	for (j = 0u; j < len; j++)
	{
		byte = (uint16_t) buf[j];

		for (i = 0u; i < 8u; i++)
		{
			/* get MSB bit */
			byte = (uint16_t) (byte << 1u);

			crcVal = (uint16_t) (crcVal << 1u);

			if (0u != ((uint8_t) (crcVal >= 0x100u) ^ (uint8_t) (byte >= 0x100u)))

			{
				/* CRC Polynome = (x^8 + x^2 + x + 1) */
				crcVal = crcVal ^ 0x07u;
			}

			crcVal = crcVal & 0xFFu;
			byte = byte & 0xFFu;
		}
	}
	return ((uint8_t) crcVal);
}

uint16_t cenGenerateRandom(void)
{
	uint16_t bitVal = 0u;
	/**feedback polynomial: x^16 + x^14 + x^13 + x^11 + 1 */
	bitVal = ((sphscaCendricCadsConfig_Lfsr >> 0u) ^ (sphscaCendricCadsConfig_Lfsr >> 2u)
			^ (sphscaCendricCadsConfig_Lfsr >> 3u) ^ (sphscaCendricCadsConfig_Lfsr >> 5u))
			& (uint16_t) 1u;

	sphscaCendricCadsConfig_Lfsr = (uint16_t) ((sphscaCendricCadsConfig_Lfsr >> 1u)
			| (bitVal << 15u));

	return sphscaCendricCadsConfig_Lfsr;
}

/* print SPI message via UART */
void cenLogSpiTxRx(void) {
#if CENDRIC_SPI_LOG_ENABLE
	char str[128];
	uint8_t len=0;
	uint8_t *pt;
	pt = &txBufNjj[0];
	for(uint8_t i=0; i<32; i++){
		len = sprintf(str+i*3, " %02X", *pt++);
	}
	LOGI("Cendric", "SPI Tx: %s", str);
	cenDelayMs(10);
	pt = &rxBufNjj[0];
	for(uint8_t i=0; i<32; i++){
		len = sprintf(str+i*3, " %02X", *pt++);
	}
	LOGI("Cendric", "SPI Rx: %s", str);
	cenDelayMs(10);
#endif
}


// ------------------------------------------------------------------------------
// Convert NXP-format float (24-bit, 3 bytes) to IEEE standard float
// ------------------------------------------------------------------------------
float NXPFloat24_to_IEEEFloat( uint8_t * pu8_Float24 )
// ------------------------------------------------------------------------------
{
  union Trans {
    float FloatValue;                   // IEEE float value (single precision)
    uint8_t ByteValue[4];                  // Bytes of FloatValue
  } FloatTrans;
  uint8_t real_exp;

  if ( pu8_Float24[2] == 0x82 )
  {
    // real_exp = 0;                    // Exponent in IEEE-754 float
    FloatTrans.ByteValue[0] = ( pu8_Float24[0] & 0x01 ) ? 0x80 : 0x00;
    FloatTrans.ByteValue[1] = ( pu8_Float24[0] >> 1 )|( ( pu8_Float24[1] & 0x01 ) ? 0x80:0x00 );
    // Set bit m22=1, m21=m14, ...
    FloatTrans.ByteValue[2] = ( (pu8_Float24[1] & 0x7F) >> 1 ) | 0x40;
    FloatTrans.ByteValue[3] = ( pu8_Float24[1] & 0x80 ); // Sign bit and exp.=0
  }
  else if ( pu8_Float24[2] == 0x81 )
  {
    // real_exp = 0;	                  // Exponent in IEEE-754 float
    FloatTrans.ByteValue[0] = ( pu8_Float24[0] & 0x3 ) << 6 ;
    FloatTrans.ByteValue[1] = ( pu8_Float24[0] >> 2 ) | ( ( pu8_Float24[1] & 0x03 ) << 6 );
    // Set bit m22=0, m21=1, m20=m14, ...
    FloatTrans.ByteValue[2] = ( (pu8_Float24[1] & 0x7F) >> 2 ) | 0x20;
    FloatTrans.ByteValue[3] = ( pu8_Float24[1] & 0x80 );
  }
  else if( (pu8_Float24[2] == 0x80) )
  {
    if ( ( pu8_Float24[0] == 0 ) && ( ( pu8_Float24[1] & 0x7F ) == 0 ) )
    {
      // Mantissa = min, exp = min means value is zero!
      FloatTrans.FloatValue = 0.0;
    }
    else
    {
      // real_exp = 0;				          // Exponent in IEEE-754 float
      FloatTrans.ByteValue[0] = ( pu8_Float24[0] & 0x7 ) << 5 ;
      FloatTrans.ByteValue[1] = ( pu8_Float24[0] >> 3 ) | ( ( pu8_Float24[1] & 0x07 ) << 5 );
      // Set bit m22=m21=0, m20=1, m19=m14, ...
      FloatTrans.ByteValue[2] = ( (pu8_Float24[1] & 0x7F) >> 3 ) | 0x10;
      FloatTrans.ByteValue[3] = (  pu8_Float24[1] & 0x80 );
    }
  }
  else
  {
    // Normalized number in IEEE format
    real_exp = pu8_Float24[2] - 0x82;	  // or equiv.: real_exp = pu8_Float24[2] + 0x7E;
    FloatTrans.ByteValue[0] = 0;
    FloatTrans.ByteValue[1] = pu8_Float24[0];
    FloatTrans.ByteValue[2] = ( pu8_Float24[1] & 0x7F ) | ( (real_exp & 0x01) ? 0x80 : 0);
    FloatTrans.ByteValue[3] = ( real_exp /2 ) | ( pu8_Float24[1] & 0x80 );
  }
  return FloatTrans.FloatValue;
}

