388 lines
15 KiB
C#
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===================================================================*/
|
|
|