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}