/*********************************************************************************************************************/ /*!@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===================================================================*/