1/*=============================================================================
  2|
  3| NAME
  4|  
  5|      crcCode.cpp
  6|
  7| DESCRIPTION
  8|  
  9|      CRC code implementation.
 10|    
 11| AUTHOR
 12|
 13|      Sean O'Connor
 14|
 15| LEGAL
 16|
 17|     CRCDemo Version 2.1 - A Program for generating and checking CRC codes.
 18|     Copyright (C) 1999-2025 by Sean Erik O'Connor.  All Rights Reserved.
 19|
 20|     This program is free software: you can redistribute it and/or modify
 21|     it under the terms of the GNU General Public License as published by
 22|     the Free Software Foundation, either version 3 of the License, or
 23|     (at your option) any later version.
 24|
 25|     This program is distributed in the hope that it will be useful,
 26|     but WITHOUT ANY WARRANTY; without even the implied warranty of
 27|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 28|     GNU General Public License for more details.
 29|
 30|     You should have received a copy of the GNU General Public License
 31|     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 32|     
 33|     The author's address is seanerikoconnor!AT!gmail!DOT!com
 34|     with !DOT! replaced by . and the !AT! replaced by @
 35|
 36+============================================================================*/
 37
 38#include "dataTypes.hpp"     // 
 39#include "shiftRegister.hpp" // Binary linear feedback shift register class.
 40#include "crcCode.hpp"       // CRC code class.
 41
 42
 43// Construct a CRC code object.
 44
 45CRCCode::CRCCode( const string & g,
 46				  syndrome_t shiftRegisterPreset,
 47				  bool invertParity )
 48        : shiftRegister_( g )
 49		, shiftRegisterPreset_( shiftRegisterPreset ) 
 50		, invertParity_( invertParity )
 51{
 52	// For CRC codes, the number of parity bits is
 53	// n-k, which is the same as the degree of the
 54	// CRC generator polynomial.
 55	numParityBits_ = shiftRegister_.getDegreeOfGeneratorPoly() ;
 56}
 57
 58
 59CRCCode::~CRCCode()
 60{
 61}
 62
 63
 64// Return the number of parity bytes.
 65int CRCCode::getNumParityBytes( void ) const
 66{
 67    return numParityBits_ / 8 ;
 68}
 69
 70
 71// Return the parity bits computed on the data in the buffer.
 72// Parity bits are in the most significant bits of the buffer.
 73
 74syndrome_t
 75CRCCode::parityBits( unsigned char * buffer, 
 76					 long int        n )
 77{
 78	// Clear the shift register to its preset value.
 79	shiftRegister_.clear( shiftRegisterPreset_ ) ;
 80
 81	// Shift message bytes into the shift register.
 82	for (long int i = 0 ;  i < n ;  ++i)
 83		shiftRegister_.shiftInByte( buffer[ i ] ) ;
 84
 85	// Return the parity bits.
 86	if (invertParity_)
 87		return ~shiftRegister_.shiftRegContents() ;
 88	else
 89	    return shiftRegister_.shiftRegContents() ;
 90}
 91        
 92
 93// Append CRC parity bytes to the end of the buffer.
 94// The buffer must be long enough to accomodate the
 95// extra parity bits.  Buffer length is increased
 96// upon exit.
 97void CRCCode::addParityToBuffer( unsigned char * buffer, long int n )
 98{
 99	// Compute the parity bits from the data.
100    syndrome_t parity = parityBits( buffer, n ) ;
101
102
103	// Initial mask is 0xFF00...00, whatever the word size.
104	int downShiftAmount = 8 * (sizeof( parity ) - 1) ;
105	syndrome_t mask = 0xFF << downShiftAmount ;
106
107    // Append parity bits to the end of the buffer.
108	for (int i = 0 ;  i < numParityBits_ / 8 ;  ++i)
109	{
110	    buffer[ n++ ] = (unsigned char)
111			            ((mask & parity) >> downShiftAmount) ;
112		mask >>= 8 ;
113		downShiftAmount -= 8 ;
114	}
115
116	return ;
117}
118
119
120// Compute the shifted syndrome of the codeword.
121// Zero indicates we have a codeword.
122syndrome_t
123CRCCode::shiftedSyndrome( unsigned char * buffer, 
124			              long int        n )
125{
126	// Clear the shift register to its preset value.
127	shiftRegister_.clear( shiftRegisterPreset_ ) ;
128
129    // Invert parity bytes if necessary.
130	if (invertParity_)
131	{
132		for (long int j = 0 ;  j < numParityBits_ / 8 ;  ++j)
133		    buffer[ (n-1)-j ] = ~buffer[ (n-1)-j ] ;
134	}
135
136	// Shift codeword bytes into the shift register.
137	for (long int i = 0 ;  i < n ;  ++i)
138		shiftRegister_.shiftInByte( buffer[ i ] ) ;
139
140	// Return the shifted syndrome.
141	// Zero means we have a codeword.
142	return shiftRegister_.shiftRegContents() ;
143}