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-2019 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 artificer!AT!seanerikoconnor!DOT!freeservers!DOT!com
 34 |     with !DOT! replaced by . and the !AT! replaced by @
 35 |
 36 +============================================================================*/
 37 
 38 #include "dataTypes.h"     // 
 39 #include "shiftRegister.h" // Binary linear feedback shift register class.
 40 #include "crcCode.h"       // CRC code class.
 41 
 42 
 43 // Construct a CRC code object.
 44 
 45 CRCCode::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 
 59 CRCCode::~CRCCode()
 60 {
 61 }
 62 
 63 
 64 // Return the number of parity bytes.
 65 int 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 
 74 syndrome_t
 75 CRCCode::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.
 97 void 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.
122 syndrome_t
123 CRCCode::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 }