//----------------------------------------------------------------------------
//
//
//----------------------------------------------------------------------------


//---Includes-----------------------------------------------------------------

#include <biwak/crc.hpp>
#include <biwak/rcc.h>
#include <HALWrapper/stm32_crc.h>
#include <string.h>
#include <biwak/exception.h>
#include <arpa/inet.h>


//---Declarations-------------------------------------------------------------


// Needed for calcCrc32Biwak() so it can replace/overload leptos calcCrc32()
CCrc *pCrc=nullptr;

/// \brief  Le contructeur
///
///         This constructor does not set anything. you have to call init()
///         afterwards
CCrc::CCrc( )
{
   #if IS_ENABLED( CONFIG_BIWAK_AUTO_RCC )
   rccCrcClockEnable(m_handler.Instance);
   #endif

   m_pHandler=new CRC_HandleTypeDef{
      .Instance { CRC },
      #if defined ( DEFAULT_INIT_VALUE_ENABLE )
      .Init {
         #if defined ( CRC_POL_POL )
         .DefaultPolynomialUse    { DEFAULT_POLYNOMIAL_ENABLE },
         #endif
         .DefaultInitValueUse     { DEFAULT_INIT_VALUE_ENABLE },
         .InputDataInversionMode  { CRC_INPUTDATA_INVERSION_BYTE },
                    .OutputDataInversionMode { CRC_OUTPUTDATA_INVERSION_ENABLE },
      },
      #else
      #endif
      #if defined( CRC_INPUTDATA_FORMAT_BYTES )
          .InputDataFormat         { CRC_INPUTDATA_FORMAT_BYTES },
      #endif // ? CRC_INPUTDATA_FORMAT_BYTES
   };

   if (HAL_CRC_Init( m_pHandler ) != HAL_OK)
   {
     /* Initialization Error */
     exception();
   }

   pCrc=this;
}

CCrc::~CCrc()
{
   pCrc=nullptr;
}


uint32_t CCrc::calculateCrc32( const void *_buf, uint32_t len)
{
      uint32_t crc;
      crc = crc32Init();
      crc = crc32Update( crc, _buf, len);
      crc = crc32Finalize( crc );
      
      return(crc);
}

uint32_t CCrc::crc32Update( uint32_t crc, const void *_buf, uint32_t len )
{
   #if defined( STM32F1 )
      uint32_t part;
      uint32_t *buf32=(uint32_t *)_buf;
      bAssert( ( len & 0b11 ) == 0, len );

      for(unsigned int i1=0; i1<len>>2; i1++)
      {
         part=htonl(buf32[i1]);
         crc = HAL_CRC_Accumulate(m_pHandler, &part, 1 );
      }
   #else
      crc = HAL_CRC_Accumulate(m_pHandler, (uint32_t*)_buf, len );
   #endif

   return( crc );
}

uint32_t CCrc::crc32Finalize( uint32_t crc )
{
   #if defined( STM32F1 )
      return( crc );
   #else
      return( ~crc );
   #endif
}

uint32_t CCrc::crc32Init( ) const
{
   return( HAL_CRC_Calculate(m_pHandler, (uint32_t *)this, 0 ) );
}

uint32_t calcCrc32Biwak( const void *_buf, uint32_t len)
{
   return(pCrc->calculateCrc32( _buf, len));
}


uint32_t crc32InitBiwak( )
{
   return( pCrc->crc32Init( ) );
}

uint32_t crc32UpdateBiwak( uint32_t crc, const void *_buf, uint32_t len)
{
   return(pCrc->crc32Update( crc, _buf, len ) );
}

uint32_t crc32FinalizeBiwak( uint32_t crc )
{
   return( pCrc->crc32Finalize( crc ) );
}


//----------------------------------------------------------------------------
