laatzen/CRC_CCITT/crcGenerator.cs
2021-10-01 11:09:20 +02:00

388 lines
15 KiB
C#

/*********************************************************************************************************************/
/*!@file crcGenerator.cs
* @brief Implementation of CRC algorithms.
*
*====================================================================================================================\n
* @copyright
*
* ___________________________________________________________________________________________________________________\n
* Copyright (c) 2016 SENSUS, GmbH.\n
* All Rights Reserved.\n
* \n
* Confidential property of\n
* SENSUS GmbH,\n
* Meineckestr. 10, 30880 LAATZEN, GERMANY\n
* \n
* Design by\n
* Hard- und Softwareentwicklung Thomas Wiedebusch,\n
* Ostermarsch 17c, 31191 ALGERMISSEN/UMMELN, GERMANY\n
* \n
*====================================================================================================================\n
* @intro
*
*____________________________________________________________________________________________________________________\n
* Functions:\n
* CRC16 LSB 0x1021,\n
* CRC16 MSB 0x1021.\n
*
*====================================================================================================================\n
* @version
*
*____________________________________________________________________________________________________________________\n
* V1.00 19-Feb-2016..23-Feb-2016 by Thomas Wiedebusch\n
* - Initial.
*
*
*====================================================================================================================\n
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CRC_CCITT
{
/*---------------------------------------------------------------------------------------------------------------*/
/*!@brief Prototype of delegate for memory set function.
* @author Thomas Wiedebusch
* @date 20-Feb-2016
* @param[in] memAddress_u32 address to fill
* @param[in] memData_u8 data for memory
*
*/
/*---------------------------------------------------------------------------------------------------------------*/
public delegate void crcGenrator_memSetFn_t(UInt32 memAddress_u32, Byte memData_u8);
/**/
/*---------------------------------------------------------------------------------------------------------------*/
/*!@brief Prototype of delegate for memory get function.
* @author Thomas Wiedebusch
* @date 20-Feb-2016
* @param[in] memAddress_u32 address to fill
* @return memData_u8
*
*/
/*---------------------------------------------------------------------------------------------------------------*/
public delegate Byte crcGenrator_memGetFn_t(UInt32 memAddress_u32);
/**/
/*---------------------------------------------------------------------------------------------------------------*/
/*!@brief crcGenerator class.
* @author Thomas Wiedebusch
* @date 19-Feb-2016..20-Feb-2016
*
*/
/*---------------------------------------------------------------------------------------------------------------*/
public class crcGenerator_t
{
//class variables
public const UInt32 maxMemBytes_cu32 = 0xFFFFFF; //maximum size of memory
Byte addressRangeLoops_u8 = 0; //no address range
Byte[] memory_u8a;
UInt16 crcValue_u16;
UInt32 startAddress1_u32;
UInt32 length1_u32;
UInt32 startAddress2_u32;
UInt32 length2_u32;
Byte bitSize_u8;
delegate void crc16Fn_t();
crc16Fn_t Crc16Fn_vdp; //internal reminder for CRC function
/*---------------------------------------------------------------------------------------------------------------*/
/*!@brief Constructor for CRC generation class:\n
* -initializes required address ranges,\n
* -initializes memory with 0xFF,\n
* -sets function pointer to required CRC function.
* @author Thomas Wiedebusch
* @date 19-Feb-2016..20-Feb-2016
* @param[in] startAddress1_u32 first address to compute
* @param[in] length1_u32 length of data of first segment
* @param[in] startAddress2_u32 second address to compute
* @param[in] length2_u32 length of data of second segment
* @param[in] seed_u16 initial seed value for computation
* @param[in] wordAccess_bol access data as word if set, else as byte
* @param[in] lsbFirst_bol access data LSB first if set, else MSB first
*
*/
/*---------------------------------------------------------------------------------------------------------------*/
public crcGenerator_t( UInt32 startAddress1In_u32, UInt32 length1In_u32, UInt32 startAddress2In_u32,
UInt32 length2In_u32, UInt16 seedIn_u16, bool wordAccessIn_bol, bool lsbFirstIn_bol)
{
crcValue_u16 = seedIn_u16;
startAddress1_u32 = startAddress1In_u32;
length1_u32 = length1In_u32;
startAddress2_u32 = startAddress2In_u32;
length2_u32 = length2In_u32;
//allocate memory for data
memory_u8a = new Byte[maxMemBytes_cu32];
//assign pointer to function
if (lsbFirstIn_bol)
{
Crc16Fn_vdp = new crc16Fn_t(Crc16Lsb_vd);
}
else
{
Crc16Fn_vdp = new crc16Fn_t(Crc16Msb_vd);
}
//calculate bit size to process
if (wordAccessIn_bol)//access word wise
{
bitSize_u8 = 16;
}
else//access byte wise
{
bitSize_u8 = 8;
}
//check first address range
if ((startAddress1_u32 > 0) && (length1_u32 > 0))
{
addressRangeLoops_u8++;
}
//check second address range
if ((startAddress2_u32 > 0) && (length2_u32 > 0))
{
addressRangeLoops_u8++;
}
//Init entire memory with 0xFF
InitMemory_vd();
}
/**/
/*---------------------------------------------------------------------------------------------------------------*/
/*!@brief Get delegate of memory set function.
* @author Thomas Wiedebusch
* @date 20-Feb-2016
* @return SetMemory_vd delegate
*
*/
/*---------------------------------------------------------------------------------------------------------------*/
public crcGenrator_memSetFn_t MemSetFn_vdp()
{
return SetMemory_vd;
}
/**/
/*---------------------------------------------------------------------------------------------------------------*/
/*!@brief Get delegate of memory get function.
* @author Thomas Wiedebusch
* @date 20-Feb-2016
* @return GetMemory_u8 delegate
*
*/
/*---------------------------------------------------------------------------------------------------------------*/
public crcGenrator_memGetFn_t MemGetFn_u8p()
{
return GetMemory_u8;
}
/**/
/*---------------------------------------------------------------------------------------------------------------*/
/*!@brief Initialize memory with 0xFF each cell.
* @author Thomas Wiedebusch
* @date 19-Feb-2016
*
*/
/*---------------------------------------------------------------------------------------------------------------*/
void InitMemory_vd()
{
for (UInt32 ctr_u32 = 0; ctr_u32 < maxMemBytes_cu32; ctr_u32++)
{
memory_u8a[ctr_u32] = 0xFF;
}
}
/**/
/*---------------------------------------------------------------------------------------------------------------*/
/*!@brief Builds the CRC16 LSB first.
* @author Thomas Wiedebusch
* @date 19-Feb-2016..23-Feb-2016
*
*/
/*---------------------------------------------------------------------------------------------------------------*/
void Crc16Lsb_vd()
{
UInt32 memAddress_u32;
UInt32 byteCtr_u32;
UInt32 byteSize_u32;
Byte bitCtr_u8;
Byte dataByte_u8;
UInt16 dataWord_u16;
//load first address range
memAddress_u32 = startAddress1_u32;
//byte size is one higher to accumulate the start and end address
byteSize_u32 = length1_u32 + 1;
//process entire memory
while( addressRangeLoops_u8-- > 0)
{
for( byteCtr_u32 = 0; byteCtr_u32 < byteSize_u32; byteCtr_u32 += (UInt32)( bitSize_u8/8) )
{
//read data lower byte
dataByte_u8 = memory_u8a[ memAddress_u32++ ];
//copy lower data byte to lower word because of LSB will be XORed
dataWord_u16 = (UInt16)((UInt16)dataByte_u8 & 0x00FF);
//assemble word if word access is required
if( 16 == bitSize_u8)
{
//read data byte higher byte
dataByte_u8 = memory_u8a[ memAddress_u32++ ];
//put higher byte to higher word
dataWord_u16 |= (UInt16)((((UInt16)dataByte_u8 << 8) & 0xFF00));
}
//process single byte or word
for( bitCtr_u8 = 0; bitCtr_u8 < bitSize_u8; bitCtr_u8++)
{
//test if CRC highest bit or data input lowest bit is XORed set to one
if( 0x8000 == ( (crcValue_u16 ^ ( dataWord_u16 << 15) ) & 0x8000) )//inverse shifted in LSB first
{
//shift CRC high bit out
crcValue_u16 <<= 1;
//apply generator polynomial
crcValue_u16 ^= 0x1021;
}
else//CRC highest bit and data input lowest bit is equal
{
crcValue_u16 <<= 1;
}
dataWord_u16 >>= 1; //LSB first shifted in
}//process single byte or word
}//byte counter
//load second address range
memAddress_u32 = startAddress2_u32;
//byte size is one higher to accumulate the start and end address
byteSize_u32 = length2_u32 + 1;
}//process entire memory while()
}
/**/
/*---------------------------------------------------------------------------------------------------------------*/
/*!@brief Builds the CRC16 MSB first.
* @author Thomas Wiedebusch
* @date 19-Feb-2016..23-Feb-2016
*
*/
/*---------------------------------------------------------------------------------------------------------------*/
void Crc16Msb_vd()
{
UInt32 memAddress_u32;
UInt32 byteCtr_u32;
UInt32 byteSize_u32;
Byte bitCtr_u8;
Byte dataByte_u8;
UInt16 dataWord_u16;
//load first address range
memAddress_u32 = startAddress1_u32;
//byte size is one higher to accumulate the start and end address
byteSize_u32 = length1_u32 + 1;
//process entire memory
while( addressRangeLoops_u8-- > 0)
{
for ( byteCtr_u32 = 0; byteCtr_u32 < byteSize_u32; byteCtr_u32 += (UInt32)( bitSize_u8 / 8))
{
//read data lower byte
dataByte_u8 = memory_u8a[ memAddress_u32++ ];
//copy lower data byte to higher word because of MSB will be XORed
dataWord_u16 = (UInt16)((((UInt16)dataByte_u8 << 8) & 0xFF00));
//assemble word if word access is required
if ( 16 == bitSize_u8)
{
//read data byte higher byte
dataByte_u8 = memory_u8a[ memAddress_u32++ ];
//move lower byte back to lower word
dataWord_u16 >>= 8;
//put higher byte to higher word
dataWord_u16 |= (UInt16)((((UInt16)dataByte_u8 << 8) & 0xFF00));
}
//process single byte or word
for (bitCtr_u8 = 0; bitCtr_u8 < bitSize_u8; bitCtr_u8++)
{
//test if CRC highest bit or data input highest bit is XORed set to one
if (0x8000 == ( ( crcValue_u16 ^ dataWord_u16) & 0x8000) )//shifted in MSB first
{
//shift CRC high bit out
crcValue_u16 <<= 1;
//apply generator polynomial
crcValue_u16 ^= 0x1021;
}
else//CRC highest bit and data input highest bit is equal
{
crcValue_u16 <<= 1;
}
dataWord_u16 <<= 1; //MSB first shifted in
}//process single byte or word
}//byte counter
//load second address range
memAddress_u32 = startAddress2_u32;
//byte size is one higher to accumulate the start and end address
byteSize_u32 = length2_u32 + 1;
}//process entire memory while()
}
/**/
/*---------------------------------------------------------------------------------------------------------------*/
/*!@brief Builds the CRC16 based on assigned function pointer.
* @author Thomas Wiedebusch
* @date 19-Feb-2016
* @return crcValue_u16 built CRC16 result
*
*/
/*---------------------------------------------------------------------------------------------------------------*/
public UInt16 CrcCalculate_u16()
{
Crc16Fn_vdp();
return crcValue_u16;
}
/**/
/*---------------------------------------------------------------------------------------------------------------*/
/*!@brief Set/Fill memory at address with data, check the address range.
* @author Thomas Wiedebusch
* @date 19-Feb-2016
* @param[in] address_u32 address to fill
* @param[in] data_u8 data for memory
*
*/
/*---------------------------------------------------------------------------------------------------------------*/
void SetMemory_vd(UInt32 address_u32, Byte data_u8)
{
if (address_u32 < maxMemBytes_cu32) //avoid access beyond the reserved range
{
memory_u8a[address_u32] = data_u8;
}
}
/**/
/*---------------------------------------------------------------------------------------------------------------*/
/*!@brief Get data of memory at address.
* @author Thomas Wiedebusch
* @date 19-Feb-2016
* @param[in] address_u32 address to read
* @return data_u8 at memory location
*
*/
/*---------------------------------------------------------------------------------------------------------------*/
Byte GetMemory_u8(UInt32 address_u32)
{
return memory_u8a[address_u32];
}
/**/
/*---------------------------------------------------------------------------------------------------------------*/
/*!@brief Get maximum value for memory address.
* @author Thomas Wiedebusch
* @date 21-Feb-2016
* @return maxMemBytes_cu32 maximum memory addresses
*
*/
/*---------------------------------------------------------------------------------------------------------------*/
public UInt32 GetMaxMemoryAddress_u8()
{
return maxMemBytes_cu32;
}
/**/
/*---------------------------------------------------------------------------------------------------------------*/
}//class crcGenerator
}//namespace CRC_CCITT
/*=====================================END OF FILE===================================================================*/