Commit 9825b31a authored by Alessandro Rubini's avatar Alessandro Rubini

robustness/ from svn 1116

parent 460d5556
Hamming Code implements the Hamming coding scheme for all the lengths
from (7,4) up to (12000, 11986).
Cesar Prados, GSI
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This folder contain the Hamming code and Hamming Matrix
HAMMING MATRIX
generate a matrix for a hamming code, the size must be define in the source.
hamming_matrix.c
make matrix
HAMMIN CODE
encode and decode according to the rate define (m,n)
bit_counter
bit_operation
bit_operation
define
hamming
make
#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include <stdlib.h>
/*
* =====================================================================================
*
* Filename: bit_counter.c
*
* Description:
*
* Version: 1.0
* Created: 18.03.2011 21:44:37
* Revision: none
* Compiler: gcc
*
* Author: YOUR NAME (),
* Company:
*
* =====================================================================================
*/
#define TWO(c) (0x1u << (c))
#define MASK(c) (((unsigned int)(-1)) / (TWO(TWO(c)) + 1u))
#define COUNT(x,c) ((x) & MASK(c)) + (((x) >> (TWO(c))) & MASK(c))
int bitcount(unsigned int );
int bitcount_1(unsigned int );
int bitcount_2(int);
int bitcount_3(unsigned int);
int bitcount (unsigned int n) {
n = COUNT(n, 1);
n = COUNT(n, 1);
n = COUNT(n, 2);
n = COUNT(n, 3);
n = COUNT(n, 4);
/* n = COUNT(n, 5) ; for 64-bit integers */
return n ;
}
int bitcount_1 (unsigned int n) {
int count = 8 * sizeof(int);
n ^= (unsigned int) - 1;
while (n)
{
count--;
n &= (n - 1);
}
return count ;
}
int bitcount_2(int n)
{
unsigned int uCount;
uCount = n
- ((n >> 1) & 033333333333)
- ((n >> 2) & 011111111111);
return (int) (((uCount + (uCount >> 3))& 030707070707) % 63);
}
int bitcount_3(unsigned int v)
{
unsigned int c=0;
while(v > 0)
// for (c = 0; v; v >>= 1)
{
c++;
v = v >> 1;
}
return c;
}
/*
* === FUNCTION ======================================================================
* Name: main
* Description:
* =====================================================================================
*/
int
main ( int argc, char *argv[] )
{
int number_bits;
number_bits = bitcount_3(00000000000000);
printf("Numero de bits %d \n",number_bits);
return EXIT_SUCCESS;
} /* ---------- end of function main ---------- */
/*
* =====================================================================================
*
* Filename: bit_operation.c
*
* Description:
*
* Version: 1.0
* Created: 03/24/2011 03:20:53 PM
* Revision: none
* Compiler: gcc
*
* Author: Cesar Prados Boda (cp), c.prados@gsi.de
* Company: GSI
*
* =====================================================================================
*/
#include "bit_operation.h"
/*
* =====================================================================================
*
* Filename: bit_counter.c
*
* Description:
*
* Version: 1.0
* Created: 18.03.2011 21:44:37
* Revision: none
* Compiler: gcc
*
* Author: YOUR NAME (),
* Company:
*
* =====================================================================================
*/
int bitcount (unsigned int n) {
n = COUNT(n, 1);
n = COUNT(n, 1);
n = COUNT(n, 2);
n = COUNT(n, 3);
n = COUNT(n, 4);
/* n = COUNT(n, 5) ; for 64-bit integers */
return n ;
}
int bitcount_1 (unsigned int n) {
int count = 8 * sizeof(int);
n ^= (unsigned int) - 1;
while (n)
{
count--;
n &= (n - 1);
}
return count ;
}
int bitcount_2(int n)
{
unsigned int uCount;
uCount = n
- ((n >> 1) & 033333333333)
- ((n >> 2) & 011111111111);
return (int) (((uCount + (uCount >> 3))& 030707070707) % 63);
}
/*
* =====================================================================================
*
* Filename: bit_operation.h
*
* Description:
*
* Version: 1.0
* Created: 03/24/2011 03:16:43 PM
* Revision: none
* Compiler: gcc
*
* Author: Cesar Prados Boda (cp), c.prados@gsi.de
* Company: GSI
*
* =====================================================================================
*/
#include <ctype.h>
#define TWO(c) (0x1u << (c))
#define MASK(c) (((unsigned int)(-1)) / (TWO(TWO(c)) + 1u))
#define COUNT(x,c) ((x) & MASK(c)) + (((x) >> (TWO(c))) & MASK(c))
int bitcount(unsigned int );
int bitcount_1(unsigned int );
int bitcount_2(int);
/*
* =============================================================================
*
* Filename: define.h
*
* Description: define
*
* Version: 1.0
* Created: 03/24/2011 02:13:27 PM
* Revision: none
* Compiler: gcc
*
* Author: Cesar Prados Boda (cp), c.prados@gsi.de
* Company: GSI
*
* ==============================================================================*/
//#define PARIiTY_CHECK_1 0x55B // 10101011011
//#define PARITY_CHECK_2 0x66D // 11001101101
//#define PARITY_CHECK_4 0x78E // 11110001110
//#define PARITY_CHECK_8 0x7F0 // 11111110000
#define BITS_VECTOR 32
#define LOG_2_32 5
#define MOD_BIT_32 31
//parity check vectors for 64 bits words,
#define PARITY_CHECK_1 0xfdfff80e
#define PARITY_CHECK_2 0x56aaaff4
#define PARITY_CHECK_4 0x1222266f
#define PARITY_CHECK_8 0x202060e
#define PARITY_CHECK_16 0x2000600
#define PARITY_CHECK_32 0xfdffffff
#define PARITY_CHECK_64 0xfe000000
#define RATE_3_1 2
#define RATE_7_4 3
#define RATE_15_11 4
#define RATE_31_26 5
#define RATE_63_57 6
#define RATE_127_120 7
#define RATE_255_247 8
#define RATE_511_502 9
#define RATE_1023_1013 10
#define RATE_2047_2036 11
#define RATE_4095_4083 12
#define RATE_8191_8178 13
#define RATE_12000_11986 14
//TO DO define the rest of the legnth
#define FRAME_4 1
#define FRAME_12000 375
// In a payload of 1500
#define MAX_LENGTH_PAYLOAD 12000
#define READ_DFILTER 6
#define READ_DVECTOR 5
#define READ_FILTER 4
#define READ_VECTOR 3
#define CLEAN 2
#define WRITE 1
#define READ 0
#define ERROR 1
#define OK 0
// will be 21 encoded words with 7 parity check bits
// thus, 1344 bits are information 147 bit parity check bits
#define CODE_WORD 64
#define ENCODED_WORD 71
#define BIT_MASK 0x1
#define NUM_PARITY_BITS 4
#ifdef DBG
#define dbg(x, ...) fprintf(stderr, "(debug) " x, ##__VA_ARGS__)
#else
#define dbg(x, ...)
#endif
This diff is collapsed.
#include "define.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <math.h>
#include <string.h>
/*
* =====================================================================================
*
* Filename: hamming.h
*
* Description: header of hamming code
*
* Version: 1.0
* Created: 03/17/2011 07:13:27 PM
* Revision: none
* Compiler: gcc
*
* Author: Cesar Prados Boda (cp), c.prados@gsi.de
* Company: GSI
*
* =====================================================================================
*/
typedef struct {
uint32_t *pvector;
}hamming_vector;
typedef struct {
uint32_t *mask;
}filter_vector;
uint32_t *hamming_encoder (uint32_t *, uint16_t );
uint32_t *hamming_decoder(uint32_t *, uint16_t);
uint8_t parity_check(uint32_t * , uint32_t *,uint16_t, uint16_t );
uint16_t bitcount(uint16_t);
uint16_t find_num_parity_bits(uint16_t );
hamming_vector *vector_generator(uint16_t);
uint16_t generator(hamming_vector *, uint16_t);
uint16_t dGenerator(hamming_vector *, uint16_t);
uint16_t hamming_init(uint16_t, uint16_t );
uint16_t vector_length(uint16_t);
uint16_t payload_length(uint16_t);
uint16_t func_malloc(hamming_vector ** , uint32_t, uint32_t);
uint16_t filter_number(uint16_t);
uint16_t random_error(uint32_t *);
uint16_t filter_generator(hamming_vector *,uint16_t );
uint16_t dFilter_generator(hamming_vector *,uint16_t );
/*************************************
hamming_matrix.c
Cesar Prados
this source generates either the vector
of the parity checks bits for a given
(64,) with m as the numbers bits of the word
**************************************/
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <strings.h>
#include <string.h>
#include <stdint.h>
#define BIT_MASK 0x1
#define LENGTH 71
typedef struct {
uint8_t b : 1;
} bit;
int main ( void )
{
int i=0,j=0;
int position_bit;
bool power_2;
bit *parity_check_mask;
int position_matrix=0;
uint64_t *h_parity_check_mask;
parity_check_mask = (bit *)malloc(LENGTH*sizeof(bit));
h_parity_check_mask = (uint64_t *)malloc(sizeof(uint64_t));
for(i=1;i<=LENGTH;i++)
{
position_matrix = 0;
power_2= ((i & (i - 1)) == 0);
memset(parity_check_mask, '0', LENGTH *sizeof(bit));
memset(h_parity_check_mask, '\0',sizeof(uint64_t));
if(power_2)
{
printf("****Mask for Parity bit %d ******\n",i);
position_bit = ffsl(i)-1;
for(j=1;j<=LENGTH;j++)
{
if((0x1 & (j>>position_bit)) && !((j & (j - 1))==0))
{
(parity_check_mask+position_matrix)->b ^= BIT_MASK;
*h_parity_check_mask ^= ( BIT_MASK << position_matrix );
if((*h_parity_check_mask & 0x1) != 0x1){
printf("change %d \n",j);
printf("VALUE %llx ",*h_parity_check_mask);
}
position_matrix++;
}
else if(!((j & (j - 1))==0) && !(0x1 & (j>>position_bit)) )
{
position_matrix++;
}
}
printf("%llx \n",*h_parity_check_mask);
printf("%d \n",position_matrix);
for(j=0;j<position_matrix;j++)
{
printf("%d ",(parity_check_mask+j)->b);
}
printf("\n");
}
}
free(parity_check_mask);
free(h_parity_check_mask);
return 0;
}
#Makefile for Hamming Code
CC = gcc
CFLAGS = -g -O2 -lm -w -DEXE -DDBG #-Wall
OBJS = hamming.o
OBJS_M = hamming_matrix.o
OUTPUT= hamming
OUTPUT_M = hamming_matrix
all : $(OBJS)
$(CC) $(CFLAGS) $(OBJS) -o $(OUTPUT)
matrix: $(OBJS_M)
$(CC) $(CFLAGS) $(OBJS_M) -o $(OUTPUT_M)
%.o : %.c
${CC} -c $^ $(CFLAGS)
install:
clean:
rm -f $(OBJS) $(OBJS_M)
CC = g++
CFLAGS = -Wall -O2 -g -fPIC -shared
OBJS = hamming.o
all: $(OBJS)
$(CC) $(CFLAGS) $(OBJS) -o hamming.so
clean:
rm -f *.o *.so
%.o : %.cpp
$(CC) $(CFLAGS) -c $^
Hamming Code implements the Hamming coding plus parity bit (64,72).
Cesar Prados, GSI
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Makefile creates a library.
CALLING FUNCTIONS
Hamming_decode
**************
This function decode word of 64 bits with a 8 bits redundancy, 7 parity checks
bits and 1 complete parity of the word.
INPUT
std::payload
unsigned int chunk2encode .- Pointer to the beginning of the words
unsigned int num_chunks.- Position in Chunk2encode of the redundancy
unsigned int *nBytep.- Position in Bytes of the error
unsigned int *nBitP.- Position in Bits of the error
OUTPUT
unsigned int result .- return if the chunk has one error, two errors and more
than two erros.
Hamming_encode
**************
This function encode words of of 64 into 72 bits, 7 parity checks bits and 1 bit
for the parity of the complete word.
INPUT
const char *frame .- payload to encode
OUTPUT
std::string with the 8 bits parity bits.
#include "hamming.h"
/*
* =====================================================================================
*
* Filename: hamming code plus parity bit 64 72
*
* Description:
*
* Version: 1.0
* Created: 04/07/2011 01:48:23 PM
* Revision: none
* Compiler: gcc
*
* Author: Cesar Prados Boda (cp), c.prados@gsi.de
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
*
* =====================================================================================*/
#define NUM_CHECK_BITS 7 // plus parity bit
#define BIT_MASK 0x1
#define SIZE 8 // 8 words 64 bits
unsigned int pbits0[NUM_CHECK_BITS][SIZE] ={ {0x5B, 0xAD, 0xAA, 0x56, 0x55, 0x55, 0x55, 0xAB}, // check vector 1
{0x6D, 0x36, 0x33, 0x99, 0x99, 0x99, 0xD9, 0x0C}, // check vector 2
{0x8E, 0xC7, 0xC3, 0xE3, 0xE1, 0xE1, 0xE1, 0xF1}, // check vector 3
{0xF0, 0x07, 0xFC, 0xE3, 0x1F, 0xE0, 0x1F, 0xFF}, // check vector 4
{0x00, 0xF8, 0xFF, 0x03, 0xE0, 0xFF, 0x1F, 0x00}, // check vector 5
{0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x01}, // check vector 6
{0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF} // check vector 7
};
unsigned int hamming_decode(std::string frame,unsigned int ichunk, unsigned int chunks, unsigned int *nBytep, unsigned int *nBitP)
{
unsigned char parity[]="";
unsigned int checkBitResult=0;
unsigned result;
for(int i=0; i<NUM_CHECK_BITS; ++i) { // parity vector x
int temp=0;
for(int j=0 ; j<SIZE ; j++) // byte by byte the frame
{
temp = ((bitset<8>(static_cast<unsigned char>(frame[ichunk + j])) & bitset<8>(pbits0[i][j])).count());
parity[0] ^= (unsigned char)((((bitset<8>((uint8_t)(frame[ichunk + j])) & bitset<8>(pbits0[i][j])).count() & 0x1 ?
1 : 0)
<< (i+1)));
}
}
// Parity bit, XOR of all the bits and the party bits
unsigned numBits=0;
for(int j=0 ; j<SIZE ; j++) // byte by byte the frame and the parity vector
{
numBits += (bitset<8>(static_cast<unsigned char>(frame[ichunk+j])).count());
}
parity[0] ^= (unsigned char)(numBits & 0x1 ?
1 : 0); // Postion 0 is for the parity bit */
unsigned int parityBit = 0;
if((parity[0] & 0x1) == (static_cast<unsigned char>(frame[chunks]) & 0x1))
parityBit = 1; // No error or double error
checkBitResult = 0;
for(int i=1;i<NUM_CHECK_BITS;i++)
checkBitResult ^= (((parity[0] >> (i)) ^ (static_cast<unsigned char >(frame[chunks]) >> (i))) & (BIT_MASK))<< (i-1);
if((checkBitResult!=0) && (parityBit == 1 ))
{
result = 2; // Double Error;
}
else if(checkBitResult != 0 )// single error, we can repair it
{
checkBitResult = postionInfraeme(checkBitResult);
unsigned int nByte = checkBitResult / SIZE;
unsigned int nBit = checkBitResult % SIZE;
*nBitP = nBit;
*nBytep = nByte;
//cout << "************ERROR IN BYTE " << nByte << " BIT " << nBit << "************" << endl;
result = 1 ;
}
else // No errors
{
result = 0;
}
return result ;
}
int postionInfraeme(int postion)
{
int postionDiff;
if((postion >4) && (postion <=7)) postionDiff = postion - 3;
else if((postion >8)&& (postion <=15)) postionDiff = postion - 4;
else if((postion >16)&& (postion <=31)) postionDiff = postion - 5;
else if(postion >32) postionDiff = postion - 6;
// the error is in the parity checks
return postionDiff;
}
std::string hamming_encode(const char *frame)
{
unsigned char parity[]="";
for(int i=0; i<NUM_CHECK_BITS; ++i) {// parity vector x
for(int j=0 ; j<SIZE ; j++) // byte by byte the frame and the parity vector
{
parity[0] ^= (unsigned char)((((bitset<8>(frame[j]) & bitset<8>(pbits0[i][j])).count() & 0x1 ?
1 : 0)
<< (i+1)));
}
}
// Parity bit, XOR of all the bits and the party bits
int numBits=0;
for(int j=0 ; j<SIZE ; j++) // byte by byte the frame and the parity vector
{
numBits += (bitset<8>(frame[j]).count());
}
parity[0] ^= (unsigned char)(numBits & 0x1 ?
1 : 0); // Postion 0 is for the parity bit */
string eFrame;
eFrame.resize(1);
if(parity[0]== 0) // if the parity check is 0
eFrame[0] = 0; // set to 0000000
else eFrame[0]= parity[0]; // in the last byte parity word
return eFrame;
}
#include <iterator>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <iostream>
#include <bitset>
using namespace std;
#ifdef __cplusplus
extern "C" {
#endif
std::string hamming_encode(const char *);
unsigned int hamming_decode(std::string frame,unsigned int , unsigned int , unsigned int *, unsigned int *);
int postionInfraeme(int );
#ifdef __cplusplus
}
#endif
/* A hardware-like C++ implementation of a Reed-Solomon erasure code.
* Copyright (C) 2010-2011 GSI GmbH.
* Author: Wesley W. Terpstra
*/
#include "gf256.h"
#include <vector>
#include <cstdlib>
#include <cstdio>
#include <assert.h>
const GF256 GF256::zero(0);
const GF256 GF256::one(1);
const GF256 GF256::g(2);
/* The hard-coded number of losses this code is designed to recover.
* Presumably a parameter for a VHDL generic.
*/
#define K 2
/* This Reed-Solomon code uses systematic encoding, which means that the
* codewords include as a prefix the original message.
*
* Each codeword c(x) is defined to be a multiple of product_i (x-g^i)
* for i=0..(K-1). The encoder and decoder are implemented with the same
* circuit. Given n symbols of which K are unknown (and set to 0), the
* missing K values are recovered.
*/
/* This circuit precomputes the lambda values needed by the (en|de)coder.
* It should be run once after all the packets have been received.
*
* The output polynomial the lowest order polynomial with roots on the
* generator; ie: lambda(x) := (x - g^i0)*(x - g^i1)*...
*
* Input:
* The indices of the lost packets.
* Output:
* The coefficients of lambda(x).
* The roots of lambda(x).
*/
void precompute(int i[K], GF256 gi[K], GF256 lambda[K+1])
{
GF256 g2; /* Register for the expression g^2^clock */
int is[K]; /* Bit-shift register for the indices */
/* Initial values of the registers */
g2 = GF256::g;
lambda[0] = GF256::one;
for (int j = 0; j < K; ++j) {
gi[j] = GF256::one;
is[j] = i[j];
lambda[j+1] = GF256::zero;
}
/* Step 1 is to compute the values gi */
for (int clock = 0; clock < 8; ++clock) {
/* Look at the low bit of the shift registers */
for (int j = 0; j < K; ++j) {
gi[j] = gi[j] * ((is[j]&1)?g2:GF256::one);
is[j] = is[j] >> 1;
}
g2 = g2*g2;
}
/* Step 2 is to compute the polynomial product */
for (int clock = 0; clock < K; ++clock) {
/* A K-wide "shift" register composed of bytes */
for (int j = K; j > 0; --j)
lambda[j] = lambda[j]*gi[clock] + lambda[j-1];
lambda[0] = lambda[0] * gi[clock];
}
}
/* Input:
* The number of symbols in the codeword (n > K)
* The indices of the codeword which are missing.
* The result of precompute on those indices.
* Output:
* Fills in the missing values of c.
*/
void code(int n, GF256 c[], int i[K], GF256 gi[K], GF256 lambda[K+1])
{
/* Registers */
GF256 lg[K+1]; /* lambda[i]*g^(i*clock) */
GF256 a[K]; /* Accumulator for the missing symbols */
GF256 dli[K]; /* (d/dx lambda)(g^i) */
GF256 gic[K]; /* g^i*g^-c */
/* Hard-wired constants */
GF256 gj1[K+1]; /* g^(j-1) */
/* Clear the unknown symbols to zero */
// for (int j = 0; j < K; ++j)
// c[i[j]] = GF256::zero;
/* Initialize the registers and constants */
for (int j = 0; j < K; ++j) {
lg[j] = lambda[j];
gic[j] = gi[j];
a[j] = GF256::zero;
dli[j] = GF256::zero;
gj1[j] = GF256::g^(j-1);
}
lg[K] = lambda[K];
gj1[K] = GF256::g^(K-1);
/* In each step, we read c[clock] from memory */
for (int clock = 0; clock < n; ++clock) {
/* This circuit feeds l1c and dlc into the decoders */
GF256 dlc = GF256::zero, l1c = GF256::zero;
for (int j = 0; j < K+1; ++j) {
l1c += lg[j]; /* XOR all the lg[j] together */
dlc += (j&1)?lg[j]:GF256::zero; /* XOR the odd lg[j] together */
lg[j] = lg[j] * gj1[j]; /* Hard-wired multiplier */
}
/* Load from main memory: */
GF256 cc = c[clock];
GF256 product = cc * l1c;
/* Replicate this circuit for each K */
for (int j = 0; j < K; ++j) {
GF256 divisor = GF256::one - gic[j];
gic[j] *= GF256::g.inverse(); /* Hard-wired multiplier */
a[j] = a[j] + (product / divisor);
/* Record dlc if it's our index */
//if (clock == i[j])
if (divisor == GF256::zero) dli[j] = dlc;
}
}
/* Implement multiplicative inverse using a lookup table */
for (int j = 0; j < K; ++j)
c[i[j]] = a[j] * dli[j].inverse();
}
#define MAX_FRAG_SIZE 1500
static unsigned char result[K][MAX_FRAG_SIZE];
/* Command-line driven test-cases */
void RS_code(unsigned int fragLen, std::vector<const unsigned char*>& fragments) {
int missing[K];
int missing_index;
assert (fragLen < MAX_FRAG_SIZE);
assert (fragments.size() > K);
missing_index = 0;
for (unsigned int i = 0; i < fragments.size(); ++i) {
if (fragments[i] == 0) {
assert (missing_index < K);
missing[missing_index++] = i;
}
}
GF256 c[fragments.size()]; //code word
GF256 gi[K];
GF256 lambda[K+1];
precompute(missing, gi, lambda);
for (unsigned int i = 0; i < fragLen; ++i) { // stripe by stripe
for (unsigned int j = 0; j < fragments.size(); ++j) { // code by code word
if (fragments[j])
c[j] = GF256::embed(fragments[j][i]);
else
c[j] = GF256::zero;
}
code(fragments.size(), c, missing, gi, lambda); // fills in 0 values
for (unsigned j = 0; j < K; ++j)
result[j][i] = c[missing[j]].project();
}
for (unsigned int j = 0; j < K; ++j)
fragments[missing[j]] = result[j];
}
/**********************************************************************
*
* Filename: crc.c
*
* Description: Slow and fast implementations of the CRC standards.
*
* Notes: The parameters for each supported CRC standard are
* defined in the header file crc.h. The implementations
* here should stand up to further additions to that list.
*
*
* Copyright (c) 2000 by Michael Barr. This software is placed into
* the public domain and may be used for any purpose. However, this
* notice must not be changed or removed and no warranty is either
* expressed or implied by its publication or distribution.
**********************************************************************/
#include "crc.h"
/*
* Derive parameters from the standard-specific parameters in crc.h.
*/
#define WIDTH (8 * sizeof(crc))
#define TOPBIT (1 << (WIDTH - 1))
#if (REFLECT_DATA == TRUE)
#undef REFLECT_DATA
#define REFLECT_DATA(X) ((unsigned char) reflect((X), 8))
#else
#undef REFLECT_DATA
#define REFLECT_DATA(X) (X)
#endif
#if (REFLECT_REMAINDER == TRUE)
#undef REFLECT_REMAINDER
#define REFLECT_REMAINDER(X) ((crc) reflect((X), WIDTH))
#else
#undef REFLECT_REMAINDER
#define REFLECT_REMAINDER(X) (X)
#endif
/*********************************************************************
*
* Function: reflect()
*
* Description: Reorder the bits of a binary sequence, by reflecting
* them about the middle position.
*
* Notes: No checking is done that nBits <= 32.
*
* Returns: The reflection of the original data.
*
*********************************************************************/
static unsigned long
reflect(unsigned long data, unsigned char nBits)
{
unsigned long reflection = 0x00000000;
unsigned char bit;
/*
* Reflect the data about the center bit.
*/
for (bit = 0; bit < nBits; ++bit)
{
/*
* If the LSB bit is set, set the reflection of it.
*/
if (data & 0x01)
{
reflection |= (1 << ((nBits - 1) - bit));
}
data = (data >> 1);
}
return (reflection);
} /* reflect() */
/*********************************************************************
*
* Function: crcSlow()
*
* Description: Compute the CRC of a given message.
*
* Notes:
*
* Returns: The CRC of the message.
*
*********************************************************************/
crc
crcSlow(unsigned char const message[], int nBytes)
{
crc remainder = INITIAL_REMAINDER;
int byte;
unsigned char bit;
/*
* Perform modulo-2 division, a byte at a time.
*/
for (byte = 0; byte < nBytes; ++byte)
{
/*
* Bring the next byte into the remainder.
*/
remainder ^= (REFLECT_DATA(message[byte]) << (WIDTH - 8));
/*
* Perform modulo-2 division, a bit at a time.
*/
for (bit = 8; bit > 0; --bit)
{
/*
* Try to divide the current data bit.
*/
if (remainder & TOPBIT)
{
remainder = (remainder << 1) ^ POLYNOMIAL;
}
else
{
remainder = (remainder << 1);
}
}
}
/*
* The final remainder is the CRC result.
*/
return (REFLECT_REMAINDER(remainder) ^ FINAL_XOR_VALUE);
} /* crcSlow() */
crc crcTable[256];
/*********************************************************************
*
* Function: crcInit()
*
* Description: Populate the partial CRC lookup table.
*
* Notes: This function must be rerun any time the CRC standard
* is changed. If desired, it can be run "offline" and
* the table results stored in an embedded system's ROM.
*
* Returns: None defined.
*
*********************************************************************/
void
crcInit(void)
{
crc remainder;
int dividend;
unsigned char bit;
/*
* Compute the remainder of each possible dividend.
*/
for (dividend = 0; dividend < 256; ++dividend)
{
/*
* Start with the dividend followed by zeros.
*/
remainder = dividend << (WIDTH - 8);
/*
* Perform modulo-2 division, a bit at a time.
*/
for (bit = 8; bit > 0; --bit)
{
/*
* Try to divide the current data bit.
*/
if (remainder & TOPBIT)
{
remainder = (remainder << 1) ^ POLYNOMIAL;
}
else
{
remainder = (remainder << 1);
}
}
/*
* Store the result into the table.
*/
crcTable[dividend] = remainder;
}
} /* crcInit() */
/*********************************************************************
*
* Function: crcFast()
*
* Description: Compute the CRC of a given message.
*
* Notes: crcInit() must be called first.
*
* Returns: The CRC of the message.
*
*********************************************************************/
crc
crcFast(unsigned char const message[], int nBytes)
{
crc remainder = INITIAL_REMAINDER;
unsigned char data;
int byte;
/*
* Divide the message by the polynomial, a byte at a time.
*/
for (byte = 0; byte < nBytes; ++byte)
{
data = REFLECT_DATA(message[byte]) ^ (remainder >> (WIDTH - 8));
remainder = crcTable[data] ^ (remainder << 8);
}
/*
* The final remainder is the CRC.
*/
return (REFLECT_REMAINDER(remainder) ^ FINAL_XOR_VALUE);
} /* crcFast() */
/**********************************************************************
*
* Filename: crc.h
*
* Description: A header file describing the various CRC standards.
*
* Notes:
*
*
* Copyright (c) 2000 by Michael Barr. This software is placed into
* the public domain and may be used for any purpose. However, this
* notice must not be changed or removed and no warranty is either
* expressed or implied by its publication or distribution.
**********************************************************************/
#ifndef _crc_h
#define _crc_h
#define FALSE 0
#define TRUE !FALSE
/*
* Select the CRC standard from the list that follows.
*/
#define CRC_CCITT
#if defined(CRC_CCITT)
typedef unsigned short crc;
#define CRC_NAME "CRC-CCITT"
#define POLYNOMIAL 0x1021
#define INITIAL_REMAINDER 0xFFFF
#define FINAL_XOR_VALUE 0x0000
#define REFLECT_DATA FALSE
#define REFLECT_REMAINDER FALSE
#define CHECK_VALUE 0x29B1
#elif defined(CRC16)
typedef unsigned short crc;
#define CRC_NAME "CRC-16"
#define POLYNOMIAL 0x8005
#define INITIAL_REMAINDER 0x0000
#define FINAL_XOR_VALUE 0x0000
#define REFLECT_DATA TRUE
#define REFLECT_REMAINDER TRUE
#define CHECK_VALUE 0xBB3D
#elif defined(CRC32)
typedef unsigned long crc;
#define CRC_NAME "CRC-32"
#define POLYNOMIAL 0x04C11DB7
#define INITIAL_REMAINDER 0xFFFFFFFF
#define FINAL_XOR_VALUE 0xFFFFFFFF
#define REFLECT_DATA TRUE
#define REFLECT_REMAINDER TRUE
#define CHECK_VALUE 0xCBF43926
#else
#error "One of CRC_CCITT, CRC16, or CRC32 must be #define'd."
#endif
void crcInit(void);
crc crcSlow(unsigned char const message[], int nBytes);
crc crcFast(unsigned char const message[], int nBytes);
#endif /* _crc_h */
\ No newline at end of file
This diff is collapsed.
#ifndef FEC_H
#define FEC_H
#ifdef __cplusplus
extern "C" {
#endif
/* Initialize any buffers / state needed to encode/decode packets */
void fec_open();
/* Free any resources used by the encoder/decoder */
void fec_close();
/* Input: data received from ethernet payload [chunk, chunk+*len)
* Output:
* If cannot (yet) decode, returns 0
* Otherwise, returns pointer to decoded message and modifies *len
*
* Note: inside be buffers
*/
const unsigned char* fec_decode(const unsigned char* chunk, unsigned int* len);
const unsigned char* fec_decode_no(const unsigned char* chunk, unsigned int* len);
/* Input: ethernet payload to send [chunk, chunk+*len)
* index, starts at 0 and incremented each call until done
* Output:
* If no more chunks follow, returns 0
* Returns encoded packet and modifies *len
*/
const unsigned char* fec_encode(const unsigned char* chunk, unsigned int* len, int index);
#ifdef __cplusplus
}
#endif
#endif
#include "hamming.h"
/*
* =====================================================================================
*
* Filename: hamming code plus parity bit 64 72
*
* Description:
*
* Version: 1.0
* Created: 04/07/2011 01:48:23 PM
* Revision: none
* Compiler: gcc
*
* Author: Cesar Prados Boda (cp), c.prados@gsi.de
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
*
* =====================================================================================*/
#define NUM_CHECK_BITS 7 // plus parity bit
#define BIT_MASK 0x1
#define SIZE 8 // 8 words 64 bits
unsigned int pbits0[NUM_CHECK_BITS][SIZE] ={ {0x5B, 0xAD, 0xAA, 0x56, 0x55, 0x55, 0x55, 0xAB}, // check vector 1
{0x6D, 0x36, 0x33, 0x99, 0x99, 0x99, 0xD9, 0x0C}, // check vector 2
{0x8E, 0xC7, 0xC3, 0xE3, 0xE1, 0xE1, 0xE1, 0xF1}, // check vector 3
{0xF0, 0x07, 0xFC, 0xE3, 0x1F, 0xE0, 0x1F, 0xFF}, // check vector 4
{0x00, 0xF8, 0xFF, 0x03, 0xE0, 0xFF, 0x1F, 0x00}, // check vector 5
{0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x01}, // check vector 6
{0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF} // check vector 7
};
unsigned int hamming_decode(std::string frame,unsigned int ichunk, unsigned int chunks, unsigned int *nBytep, unsigned int *nBitP)
{
unsigned char parity[]="";
unsigned int checkBitResult=0;
unsigned result;
for(int i=0; i<NUM_CHECK_BITS; ++i) { // parity vector x
int temp=0;
for(int j=0 ; j<SIZE ; j++) // byte by byte the frame
{
temp = ((bitset<8>(static_cast<unsigned char>(frame[ichunk + j])) & bitset<8>(pbits0[i][j])).count());
parity[0] ^= (unsigned char)((((bitset<8>((uint8_t)(frame[ichunk + j])) & bitset<8>(pbits0[i][j])).count() & 0x1 ?
1 : 0)
<< (i+1)));
}
}
// Parity bit, XOR of all the bits and the party bits
unsigned numBits=0;
for(int j=0 ; j<SIZE ; j++) // byte by byte the frame and the parity vector
{
numBits += (bitset<8>(static_cast<unsigned char>(frame[ichunk+j])).count());
}
parity[0] ^= (unsigned char)(numBits & 0x1 ?
1 : 0); // Postion 0 is for the parity bit */
unsigned int parityBit = 0;
if((parity[0] & 0x1) == (static_cast<unsigned char>(frame[chunks]) & 0x1))
parityBit = 1; // No error or double error
checkBitResult = 0;
for(int i=1;i<NUM_CHECK_BITS;i++)
checkBitResult ^= (((parity[0] >> (i)) ^ (static_cast<unsigned char >(frame[chunks]) >> (i))) & (BIT_MASK))<< (i-1);
if((checkBitResult!=0) && (parityBit == 1 ))
{
result = 2; // Double Error;
}
else if(checkBitResult != 0 )// single error, we can repair it
{
checkBitResult = postionInfraeme(checkBitResult);
unsigned int nByte = checkBitResult / SIZE;
unsigned int nBit = checkBitResult % SIZE;
*nBitP = nBit;
*nBytep = nByte;
//cout << "************ERROR IN BYTE " << nByte << " BIT " << nBit << "************" << endl;
result = 1 ;
}
else // No errors
{
result = 0;
}
return result ;
}
int postionInfraeme(int postion)
{
int postionDiff;
if((postion >4) && (postion <=7)) postionDiff = postion - 3;
else if((postion >8)&& (postion <=15)) postionDiff = postion - 4;
else if((postion >16)&& (postion <=31)) postionDiff = postion - 5;
else if(postion >32) postionDiff = postion - 6;
// the error is in the parity checks
return postionDiff;
}
std::string hamming_encode(const char *frame)
{
unsigned char parity[]="";
for(int i=0; i<NUM_CHECK_BITS; ++i) {// parity vector x
for(int j=0 ; j<SIZE ; j++) // byte by byte the frame and the parity vector
{
parity[0] ^= (unsigned char)((((bitset<8>(frame[j]) & bitset<8>(pbits0[i][j])).count() & 0x1 ?
1 : 0)
<< (i+1)));
}
}
// Parity bit, XOR of all the bits and the party bits
int numBits=0;
for(int j=0 ; j<SIZE ; j++) // byte by byte the frame and the parity vector
{
numBits += (bitset<8>(frame[j]).count());
}
parity[0] ^= (unsigned char)(numBits & 0x1 ?
1 : 0); // Postion 0 is for the parity bit */
string eFrame;
eFrame.resize(1);
if(parity[0]== 0) // if the parity check is 0
eFrame[0] = 0; // set to 0000000
else eFrame[0]= parity[0]; // in the last byte parity word
return eFrame;
}
#include <iterator>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <iostream>
#include <bitset>
using namespace std;
#ifdef __cplusplus
extern "C" {
#endif
std::string hamming_encode(const char *);
unsigned int hamming_decode(std::string frame,unsigned int , unsigned int , unsigned int *, unsigned int *);
int postionInfraeme(int );
#ifdef __cplusplus
}
#endif
/*
* =====================================================================================
*
* Filename: test-driver.cpp
*
* Description:
*
* Version: 1.0
* Created: 04/07/2011 01:48:23 PM
* Revision: none
* Compiler: gcc
*
* Author: Cesar Prados Boda (cp), c.prados@gsi.de
* Wesley Terpstra w.terpstra@gsi.de
*
* This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
*
* =====================================================================================
*/
#include "fec.h"
#include <stdio.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <ctype.h>
//#define DEMO__ // makes a binary for the demo
int main()
{
unsigned char msg[] = "PAYLOAD1"
"PAYLOAD2"
"PAYLOAD3"
"PAYLOAD4";
// unsigned char msg[] = "Nel mezzo del "
// "camin di nostra "
// "vita mi ritrovai"
// " per una selva "
// "oscura,ché la "
// "diritta via era "
// "smarrita........";
int c;
const unsigned char* buf;
const unsigned char* cbuf;
unsigned int i, len,len_temp;
unsigned char *temp;
printf("\n \n \n");
printf("*************************************************************\n");
printf(" WE WANT TO ENCODE: \n");
printf("");
for (i = 0; i < sizeof(msg)-1; ++i)
{
printf("%c", msg[i]);
}
printf("\n");
printf("*************************************************************\n");
printf("\n \n \n");
#ifdef DEMO__
system("sleep 1");
#endif
fec_open();
for (c = 0; len = sizeof(msg)-1, (buf = fec_encode(msg, &len, c)) != 0; ++c)
{
//for (i = 0; i < len; ++i)
//printf("%c(%02x)", isprint(buf[i])?buf[i]:"x", buf[i]);
//printf("\n");
}
// fflush(stdout);
len = sizeof(msg)-1;
buf = fec_encode(msg, &len, 0);
cbuf = fec_decode(buf, &len);
len = sizeof(msg)-1;
buf = fec_encode(msg, &len, 1);
cbuf = fec_decode(buf, &len);
len = sizeof(msg)-1;
buf = fec_encode(msg, &len, 3);
if (cbuf != 0) {
printf("\n \n \n");
printf("******************************************************************\n");
printf("!!!!!!!!!!!!!!!!!THE CONTROL MESSAGE IS DECODED!!!!!!!!!!!!!!!!!\n");
printf("******************************************************************\n");
printf("");
for (i = 0; i < len; ++i)
{
printf("%c", cbuf[i]);
}
printf("\n");
}
else
{
printf("\n \n \n");
printf("******************************************************************\n");
printf("!!!!!!!!!!!!!!!!!THE CONTROL MESSAGE IS NOT DECODED!!!!!!!!!!!!!!!!!\n");
printf("******************************************************************\n");
}
fec_close();
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment