Commit d867dbde authored by bradomyn's avatar bradomyn

Imported the hamming/reed solomon from the wr-switch-sw repo, authors: Wesley,Maceij and Cesar

parent 1406bc93
#Makefile for Hamming Code
CC = g++
CFLAGS = -g3 -O0 -lm -w -Wall
TESTER = test
DECODER = decoder
ifdef TEST
OBJS = test-driver.o code.o fec.o crc.o hamming.o
OUTPUT= $(TESTER)
else
OBJS = fec_decoder.o code.o fec.o crc.o hamming.o
OUTPUT= $(DECODER)
endif
all : $(OBJS)
$(CC) $(CFLAGS) $(OBJS) -o $(OUTPUT)
clean:
rm -f $(OBJS) $(TESTER) $(DECODER)
/* 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);
const GF256 GF256::g(3);
/* 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
#ifdef __cplusplus
extern "C" {
#endif
void crcInit(void);
crc crcSlow(unsigned char const message[], int nBytes);
crc crcFast(unsigned char const message[], int nBytes);
#ifdef __cplusplus
}
#endif
#endif /* _crc_h */
This diff is collapsed.
#ifndef FEC_H
#define FEC_H
#ifdef __cplusplus
extern "C" {
#endif
//#define DBG_SHOW_CHUNKS
//#define DBG_SHOW_PARAMETERS
//#define DBG_SHOW_HEADER
typedef struct {
unsigned int schemaID; // 4 bits
unsigned int fragmentID; // 4 bits
unsigned int msgID; // 16 bits
unsigned int etherType; // 16 bits
unsigned int originSize; // 13 bits
unsigned int framgentSize; // 8 bits
} fec_header_t;
typedef struct {
unsigned int receivedOrderNumber; //received as which in turn
unsigned int sentOrderNumber; //fragmentID
unsigned int recoveredBitsNumber; //how many bits where recovered using Hamming
unsigned int duplicatesReceived; //number of duplicates
unsigned int framgentSize;
bool fragmentRecovered; //was the fragment recovered in the end
bool fragmentUsed; //was the fragment used
bool errorInHeader; //was the error in FEC header
} fec_decoder_fragment_raport_t;
typedef struct {
fec_decoder_fragment_raport_t fragments[8];
unsigned int bitsRecovered;
unsigned int fragmentsLost;
unsigned int fragmentsReceived;
unsigned int duplicatesReceived;
bool msgRecovered;
bool tooManyFragments;
} fec_decoder_msg_raport_t;
/* 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 fragSize,
int* origMsgSize, unsigned int* origEtherType);
/* 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);
int fec_encoder(const unsigned char* origMsg, unsigned int origMsgLen,
unsigned int origEtherType, const unsigned char** encodedMsgs,
unsigned int* encodedMsgLen, unsigned int* msg_number);
int erasure_channel(const unsigned char** errorMsgs, const unsigned char** encodedMsgs,
unsigned int encodedMsgLen[], unsigned int msg_number) ;
int fec_decoder_report();
#ifdef __cplusplus
}
#endif
#endif
/*
* ===============================================================================
* Project: FEC decoder @ SW
*
* Filename: fec_decoder.cpp
*
* Description: Reads FEC frames (recognized by EtherType) from the socket
* Recognizes FEC header
* Does de-hamming (based on Cesar's with corrected table)
* Hamming parity bytes at the end of each chunk (not at the
* end of the frame )
*
* Version: 1.0
* Created: 04/09/2011
* Revision: none
* Compiler: gcc
*
* Author: Maciej Lipinski (based on test-drive.c by C.Prados)
* Company: CERN
*
* ============================================================================
*/
#include "fec.h"
#include "fec_decoder.h"
my_socket *create_socket(wr_sockaddr_t *bind_addr)
{
struct sockaddr_ll sll;
struct my_socket *s;
struct ifreq f;
int fd;
fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if(fd < 0)
{
perror("socket()");
return NULL;
}
fcntl(fd, F_SETFL, O_NONBLOCK);
// Put the controller in promiscious mode, so it receives everything
strcpy(f.ifr_name, bind_addr->if_name);
if(ioctl(fd, SIOCGIFFLAGS,&f) < 0) { perror("ioctl()"); return NULL; }
f.ifr_flags |= IFF_PROMISC;
if(ioctl(fd, SIOCSIFFLAGS,&f) < 0) { perror("ioctl()"); return NULL; }
// Find the inteface index
strcpy(f.ifr_name, bind_addr->if_name);
ioctl(fd, SIOCGIFINDEX, &f);
sll.sll_ifindex = f.ifr_ifindex;
sll.sll_family = AF_PACKET;
sll.sll_protocol = htons(bind_addr->ethertype);
sll.sll_halen = 6;
memcpy(sll.sll_addr, bind_addr->mac, 6);
if(bind(fd, (struct sockaddr *)&sll, sizeof(struct sockaddr_ll)) < 0)
{
close(fd);
perror("bind()");
return NULL;
}
s=(struct my_socket*)calloc(sizeof(struct my_socket), 1);
s->if_index = f.ifr_ifindex;
memcpy(s->local_mac, f.ifr_hwaddr.sa_data, 6);
memcpy(&s->bind_addr, bind_addr, sizeof(wr_sockaddr_t));
s->fd = fd;
return (my_socket*)s;
}
int recvfrom(my_socket *sock, wr_sockaddr_t *from, void *data, size_t data_length)
{
struct my_socket *s = (struct my_socket *)sock;
struct etherpacket pkt;
struct msghdr msg;
struct iovec entry;
struct sockaddr_ll from_addr;
struct {
struct cmsghdr cm;
char control[1024];
} control;
struct cmsghdr *cmsg;
size_t len = data_length + sizeof(struct ethhdr);
memset(&msg, 0, sizeof(msg));
msg.msg_iov = &entry;
msg.msg_iovlen = 1;
entry.iov_base = &pkt;
entry.iov_len = len;
msg.msg_name = (caddr_t)&from_addr;
msg.msg_namelen = sizeof(from_addr);
msg.msg_control = &control;
msg.msg_controllen = sizeof(control);
int ret = recvmsg(s->fd, &msg, MSG_DONTWAIT);
if(ret < 0 && errno==EAGAIN) return 0; // would be blocking
if(ret == -EAGAIN) return 0;
if(ret <= 0) return ret;
memcpy(data, pkt.data, ret - sizeof(struct ethhdr));
from->ethertype = ntohs(pkt.ether.h_proto);
memcpy(from->mac, pkt.ether.h_source, 6);
memcpy(from->mac_dest, pkt.ether.h_dest, 6);
return ret - sizeof(struct ethhdr);
}
int main()
{
struct my_socket *socket;
wr_sockaddr_t bindaddr;
wr_sockaddr_t dummy_addr;
int recv_msg_size, i;
unsigned char buf[PACKET_SIZE];
unsigned char msg[PACKET_SIZE];
const unsigned char* recoveredMessage;
int recoveredMsgSize = 0;
unsigned int recoveredEtherType;
int fec_decoder_ret;
/* open socket and other connection magic*/
strcpy(bindaddr.if_name, "eth4"); //TODO
bindaddr.ethertype = 0xDEED; // FEC's etherType, fecked
memcpy(bindaddr.mac, FEC_ADDR, sizeof(mac_addr_t));
socket = create_socket(&bindaddr);
int cnt=1;
while(1)
{
if((recv_msg_size = recvfrom(socket, &dummy_addr, (unsigned char*)buf, PACKET_SIZE)) > 0)
{
printf("\n----------------------------- FEC_DECODER ----------------------------\n");
printf("received sth of size: %d bytes\n",recv_msg_size);
cnt++;
for(i=0;i<recv_msg_size;) //endianess
{
//header
if(i < FEC_HEADE_SIZE)
{
msg[i] = buf[i];
msg[i+1] = buf[i+1];
i=i+2;
}
//payload
else
{
msg[i] = buf[i+1];
msg[i+1] = buf[i];
i=i+2;
}
}
recoveredMessage = fec_decode(msg,recv_msg_size,&fec_decoder_ret, &recoveredEtherType);
if(fec_decoder_ret > 0)//message recovered
{
printf("--------------------------------------------------------------------------\n");
printf("-------------message recovered: size = %d, etherType = 0x%x---------------\n",
fec_decoder_ret,recoveredEtherType);
printf("--------------------------------------------------------------------------");
for(i=0;i<fec_decoder_ret;i++)
{
if(i%16 == 0) printf("\n");
printf("0x%2x|",recoveredMessage[i]);
}
printf("\n");
}
printf("------------------------------------------------------------------------\n\n\n");
if(cnt % 40 == 0)
fec_decoder_report();
}
}
return 1;
}
#ifndef _fec_decoder_h
#define _fec_decoder_h
#include "fec.h"
#include <stdio.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#include <linux/if_arp.h>
#include <linux/errqueue.h>
#include <linux/sockios.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <asm/types.h>
#include <fcntl.h>
#include <errno.h>
#include <ctype.h>
#define DEMO__
//#define DEMO__ // makes a binary for the demo
#include <asm/socket.h>
#define PACKET_SIZE 1518
#define IFACE_NAME_LEN 16
#define ETHER_MTU 1518
#define PACKED __attribute__((packed))
// FECed frame header size [bytes]
#define FEC_HEADE_SIZE 8
typedef uint32_t ipv4_addr_t;
typedef char Octet;
typedef uint8_t mac_addr_t[6];
const mac_addr_t FEC_ADDR = {0x76, 0x54, 0xba, 0x98 , 0xfe, 0xdc};
PACKED struct etherpacket {
struct ethhdr ether;
char data[ETHER_MTU];
};
typedef void *wr_socket_t;
typedef struct {
// Network interface name (eth0, ...)
char if_name[IFACE_NAME_LEN];
// MAC address
mac_addr_t mac;
// Destination MASC address, filled by recvfrom() function on interfaces bound to multiple addresses
mac_addr_t mac_dest;
// IP address
ipv4_addr_t ip;
// UDP port
uint16_t port;
// RAW ethertype
uint16_t ethertype;
// physical port to bind socket to
uint16_t physical_port;
} wr_sockaddr_t;
struct my_socket {
int fd;
wr_sockaddr_t bind_addr;
mac_addr_t local_mac;
int if_index;
} ;
#endif
\ No newline at end of file
/* Copyright 2010-2011 GSI GmbH.
* All rights reserved.
*
* A quick-and-dirty implementation of GF(2^8).
* Optimized for ease of translation into hardware, not speed.
*
* Author: Wesley W. Terpstra
*/
#ifndef __GF256_H__
#define __GF256_H__
#include <iostream>
#include <iomanip>
class GF256
{
protected:
typedef unsigned char rep;
rep value;
GF256(rep x) : value(x) { }
public:
GF256() : value(0) { }
GF256(const GF256& y) : value(y.value) { }
/* Important constants */
static const GF256 zero;
static const GF256 one;
static const GF256 g;
/* Explicit conversion operators */
static GF256 embed(rep v) { return GF256(v); }
rep project() const { return value; }
bool operator == (GF256 y)
{
return value == y.value;
}
bool operator != (GF256 y)
{
return value != y.value;
}
GF256& operator = (GF256 y)
{
value = y.value;
return *this;
}
GF256& operator += (GF256 y)
{
value ^= y.value;
return *this;
}
GF256& operator -= (GF256 y)
{
value ^= y.value;
return *this;
}
GF256 operator + (GF256 y) const
{
GF256 out(*this);
out += y;
return out;
}
GF256 operator - (GF256 y) const
{
GF256 out(*this);
out -= y;
return out;
}
GF256 operator - () const
{
return GF256(*this);
}
GF256 operator * (GF256 y) const
{
rep a = value;
rep b = y.value;
rep a0 = (a>>0)&1;
rep a1 = (a>>1)&1;
rep a2 = (a>>2)&1;
rep a3 = (a>>3)&1;
rep a4 = (a>>4)&1;
rep a5 = (a>>5)&1;
rep a6 = (a>>6)&1;
rep a7 = (a>>7)&1;
rep b0 = (b>>0)&1;
rep b1 = (b>>1)&1;
rep b2 = (b>>2)&1;
rep b3 = (b>>3)&1;
rep b4 = (b>>4)&1;
rep b5 = (b>>5)&1;
rep b6 = (b>>6)&1;
rep b7 = (b>>7)&1;
#if 1
/* This is output from gates-gf targetting the modulus 2d */
rep c0 = (a0&b0) ^ (a1&b7) ^ (a2&b6) ^ (a3&b5) ^ (a4&b4) ^ (a4&b7) ^ (a5&b3) ^ (a5&b6) ^ (a6&b2) ^ (a6&b5) ^ (a6&b7) ^ (a7&b1) ^ (a7&b4) ^ (a7&b6);
rep c1 = (a0&b1) ^ (a1&b0) ^ (a2&b7) ^ (a3&b6) ^ (a4&b5) ^ (a5&b4) ^ (a5&b7) ^ (a6&b3) ^ (a6&b6) ^ (a7&b2) ^ (a7&b5) ^ (a7&b7);
rep c2 = (a0&b2) ^ (a1&b1) ^ (a1&b7) ^ (a2&b0) ^ (a2&b6) ^ (a3&b5) ^ (a3&b7) ^ (a4&b4) ^ (a4&b6) ^ (a4&b7) ^ (a5&b3) ^ (a5&b5) ^ (a5&b6) ^ (a6&b2) ^ (a6&b4) ^ (a6&b5) ^ (a7&b1) ^ (a7&b3) ^ (a7&b4);
rep c3 = (a0&b3) ^ (a1&b2) ^ (a1&b7) ^ (a2&b1) ^ (a2&b6) ^ (a2&b7) ^ (a3&b0) ^ (a3&b5) ^ (a3&b6) ^ (a4&b4) ^ (a4&b5) ^ (a5&b3) ^ (a5&b4) ^ (a5&b7) ^ (a6&b2) ^ (a6&b3) ^ (a6&b6) ^ (a6&b7) ^ (a7&b1) ^ (a7&b2) ^ (a7&b5) ^ (a7&b6);
rep c4 = (a0&b4) ^ (a1&b3) ^ (a2&b2) ^ (a2&b7) ^ (a3&b1) ^ (a3&b6) ^ (a3&b7) ^ (a4&b0) ^ (a4&b5) ^ (a4&b6) ^ (a5&b4) ^ (a5&b5) ^ (a6&b3) ^ (a6&b4) ^ (a6&b7) ^ (a7&b2) ^ (a7&b3) ^ (a7&b6) ^ (a7&b7);
rep c5 = (a0&b5) ^ (a1&b4) ^ (a1&b7) ^ (a2&b3) ^ (a2&b6) ^ (a3&b2) ^ (a3&b5) ^ (a3&b7) ^ (a4&b1) ^ (a4&b4) ^ (a4&b6) ^ (a5&b0) ^ (a5&b3) ^ (a5&b5) ^ (a6&b2) ^ (a6&b4) ^ (a6&b7) ^ (a7&b1) ^ (a7&b3) ^ (a7&b6) ^ (a7&b7);
rep c6 = (a0&b6) ^ (a1&b5) ^ (a2&b4) ^ (a2&b7) ^ (a3&b3) ^ (a3&b6) ^ (a4&b2) ^ (a4&b5) ^ (a4&b7) ^ (a5&b1) ^ (a5&b4) ^ (a5&b6) ^ (a6&b0) ^ (a6&b3) ^ (a6&b5) ^ (a7&b2) ^ (a7&b4) ^ (a7&b7);
rep c7 = (a0&b7) ^ (a1&b6) ^ (a2&b5) ^ (a3&b4) ^ (a3&b7) ^ (a4&b3) ^ (a4&b6) ^ (a5&b2) ^ (a5&b5) ^ (a5&b7) ^ (a6&b1) ^ (a6&b4) ^ (a6&b6) ^ (a7&b0) ^ (a7&b3) ^ (a7&b5);
#else
rep modulus = 0x1b;
/* ci = b*x^i */
/* bi*modulus is just bi?modulus:0 */
rep c0 = b;
rep c1 = (c0 << 1) ^ (c0 >> 7)*modulus;
rep c2 = (c1 << 1) ^ (c1 >> 7)*modulus;
rep c3 = (c2 << 1) ^ (c2 >> 7)*modulus;
rep c4 = (c3 << 1) ^ (c3 >> 7)*modulus;
rep c5 = (c4 << 1) ^ (c4 >> 7)*modulus;
rep c6 = (c5 << 1) ^ (c5 >> 7)*modulus;
rep c7 = (c6 << 1) ^ (c6 >> 7)*modulus;
/* x*y here is just y?x:0 */
rep o0 = c0 * ((a>>0)&1);
rep o1 = c1 * ((a>>1)&1);
rep o2 = c2 * ((a>>2)&1);
rep o3 = c3 * ((a>>3)&1);
rep o4 = c4 * ((a>>4)&1);
rep o5 = c5 * ((a>>5)&1);
rep o6 = c6 * ((a>>6)&1);
rep o7 = c7 * ((a>>7)&1);
return ((o0^o1)^(o2^o3))^((o4^o5)^(o6^o7));
#endif
return (c7<<7)|(c6<<6)|(c5<<5)|(c4<<4)|(c3<<3)|(c2<<2)|(c1<<1)|(c0<<0);
}
GF256& operator *= (GF256 y)
{
return *this = *this * y;
}
GF256 operator ^ (int x) const
{
GF256 out(1);
GF256 pow(*this);
x %= 255;
if (x < 0) x += 255;
for (; x > 0; x >>= 1)
{
if ((x & 1) != 0)
out *= pow;
pow *= pow;
}
return out;
}
GF256 inverse () const
{
return *this ^ 254;
}
GF256 operator / (GF256 y) const
{
return *this * y.inverse();
}
GF256& operator /= (GF256 y)
{
return *this = *this / y;
}
friend std::ostream& operator << (std::ostream& o, GF256 y)
{
return o << std::hex << std::setw(2) << (int)y.value;
}
};
#endif
#include "hamming.h"
#define NUM_CHECK_BITS 7 // plus parity bit
#define BIT_MASK 0x1
#define SIZE 8 // 8 words 64 bits
//#define printf_debugging
//corrected matrix provided by Cesar
unsigned int pbits0[NUM_CHECK_BITS][SIZE] ={{0x5B, 0xAD, 0xAA, 0x56, 0x55, 0x55, 0x55, 0xAB}, // check vector 1
{0x6D, 0x36, 0x33, 0x9B, 0x99, 0x99, 0x99, 0xCD}, // check vector 2
{0x8E, 0xC7, 0xC3, 0xE3, 0xE1, 0xE1, 0xE1, 0xF1}, // check vector 3
{0xF0, 0x07, 0xFC, 0x03, 0xFE, 0x01, 0xFE, 0x01}, // check vector 4
{0x00, 0xF8, 0xFF, 0x03, 0x00, 0xFE, 0xFF, 0x01}, // check vector 5
{0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x01}, // check vector 6
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE} // check vector 7
};
/*
input :
frame - buffer with entire msg
ichunk - index of the first byte in the chunk which is being processed
chunks - index of the parity byte (in original Cesar's, it was the number of all chunks, since all the parity bytes where at the end)
nBytep - output - the number of the byte (in the chunk) in which the bitflip is
nBitp - output - the number of the bit (in the nByte) in which the bitflip is
return:
0 = no errors
1 = single error, so corrected
2 = double error, could not correct
*/
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;
//calculate parity of the chunk (8 byte)
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 */
//check parity bit (for all bits in the chunk)
unsigned int parityBit = 0;
if((parity[0] & 0x1) == (static_cast<unsigned char>(frame[chunks]) & 0x1))
parityBit = 1; // No error or double error
#ifdef printf_debugging
int d;
for(d=0; d<8;d++)
printf(" 0x%x\n",static_cast<unsigned char>(frame[d+ichunk]));
printf("parity: 0x%x vs 0x%x\n",static_cast<unsigned char>(frame[d+ichunk]),parity[0]);
#endif
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;
result = 1 ; //repaired
}
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: 21/10/2011 01:48:23 PM
* Revision: none
* Compiler: gcc
*
* Author: Maciej Lipinski (based on code from Cesar Prados Boda (cp), c.prados@gsi.de)
* Company: CERN
*
* =================================================================================================
*/
#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 MAX_MSG_SIZE 1024
#define MAX_NR_EN_MSGs 8
#define MSG_SIZE 501
// (x + 1) ->> because if we have text, we need to cut the end char
/*
* Control Debugging
*/
//#define DBG_SHOW_ORIG_MSG
/*
* The encoder receives message of some size from somewhere, this
* function simulates it, in the function you decide on the
* message content and size.
* So, the function basically only outputs data (msg and size)
*/
int createOriginalMsg(unsigned char msg[], unsigned int* size, unsigned int* etherType)
{
// decode on message size
unsigned int msgSize = MSG_SIZE; // 500 bytes
*size = msgSize;
*etherType = 0xABCD;
// decider on message content
unsigned char nasty_data_filler = 0x0;
for (int i=0; i<msgSize;i++)
if(i%2==0) msg[i] = nasty_data_filler++;
else msg[i] = 0x0;
#ifdef DBG_SHOW_ORIG_MSG
// print the result
printf("\n********************** message to be encoded (payload of %3d bytes) ***************************", msgSize);
for (int i = 0; i < msgSize; ++i)
{
if(i % 16 == 0) printf("\n");
printf("0x%2x, ", msg[i]);
}
printf("\n***********************************************************************************************\n");
#endif
}
int show_encoded_msgs(const unsigned char** encodedMsgs,unsigned int* encodedMsgLen, unsigned int msg_number)
{
printf("FEC encoded into %d Ethernet frames\n",msg_number);
for(unsigned int i = 0; i< msg_number; i++)
{
printf("MSG_%d [payload size(with FEC header): %d]:\n",i,encodedMsgLen[i]);
printf("HEADER: ");
for(unsigned int j = 0; j< encodedMsgLen[i]; j++)
{
if(j > 7 && (j-8) % 18 == 0) printf("\n");
printf("0x%2x, ", encodedMsgs[i][j]);
if(j==7) printf("\nPAYLOAD:"); //end of header
}
printf("\n");
}
}
int compare_results(const unsigned char* origMsg, unsigned int origMsgSize,
const unsigned char* recoveredMsg, int recoveredMsgSize)
{
int ret = 0;
if(origMsgSize != recoveredMsgSize)
{
printf("FEC FAILED: wrong size of recovered message. origMsgSize=%d recoveredMsgSize = %d\n",
origMsgSize, recoveredMsgSize);
return -1;
}
for (int i = 0; i< origMsgSize; i++)
{
if(origMsg[i] != recoveredMsg[i])
{
printf("Error in byte %d, original data: 0x%x, recovered data: 0x%x\n", origMsg[i], recoveredMsg[i] );
ret = -1;
}
return ret;
}
}
int main()
{
int ret = 0;
//init FEC (bullshit)
fec_open();
/***************************************************************************************
/* Creating message
***************************************************************************************/
unsigned int origMessageSize;
unsigned int origEtherType;
unsigned char origMessage[MAX_MSG_SIZE];
//create a message
createOriginalMsg(origMessage, &origMessageSize, &origEtherType);
/***************************************************************************************
/* Encoding
***************************************************************************************/
const unsigned char* encodedMessages[MAX_NR_EN_MSGs];
unsigned int encoded_msgs_len[MAX_NR_EN_MSGs];
unsigned int encoded_msgs_number;
//encode original message into a number of ethernet frames
ret = fec_encoder(origMessage,origMessageSize, origEtherType, encodedMessages,
encoded_msgs_len, &encoded_msgs_number);
if(ret < 0 ) printf("fec_encoder error\n");
/***************************************************************************************
/* "Sending [erasure channel]
***************************************************************************************/
const unsigned char* erroredMessages[MAX_NR_EN_MSGs];
//show the effect
//show_encoded_msgs(encodedMessages, encoded_msgs_len,encoded_msgs_number);
erasure_channel(erroredMessages, encodedMessages, encoded_msgs_len, encoded_msgs_number);
/***************************************************************************************
/* Decoding
***************************************************************************************/
const unsigned char* recoveredMessage;
int recoveredMsgSize = 0;
unsigned int recoveredEtherType;
ret = 0;
printf("\n----------------------------- FEC_DECODER ----------------------------\n");
for(int i =0; i < encoded_msgs_number; i++)
{
if(recoveredMsgSize == 0) //not recovered the frame yet
{
recoveredMessage = fec_decode(erroredMessages[i], encoded_msgs_len[i] /*I dont like this*/,
&ret, &recoveredEtherType);
if(ret > 0) //record the size
recoveredMsgSize = ret;
}
else //go through the unnecessary fragments
fec_decode(erroredMessages[i], encoded_msgs_len[i], &ret, &recoveredEtherType);
}
printf("------------------------------------------------------------------------\n");
ret = -1;
if(recoveredMsgSize > 0)
ret=compare_results(origMessage, origMessageSize, recoveredMessage,recoveredMsgSize);
if(ret==0 && recoveredMsgSize > 0)
printf("\n\n\n \t\t CONGRATULATIONS ! \n \t message recovered succesfully \n\n\n ");
else
printf("\n\n\n \t\t Message not recovered\n\n\n");
fec_decoder_report();
return 0;//below is the shity code provided by CESAR and modified by me
}
#Makefile for Hamming Code
CC = g++
CFLAGS = -g3 -O0 -lm -w -Wall
OBJS = fec_decoder.o code.o fec.o crc.o hamming.o
OUTPUT= test
all : $(OBJS)
$(CC) $(CFLAGS) $(OBJS) -o $(OUTPUT)
clean:
rm -f $(OBJS) $(OUTPUT)
/* 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);
const GF256 GF256::g(3);
/* 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
#ifdef __cplusplus
extern "C" {
#endif
void crcInit(void);
crc crcSlow(unsigned char const message[], int nBytes);
crc crcFast(unsigned char const message[], int nBytes);
#ifdef __cplusplus
}
#endif
#endif /* _crc_h */
This diff is collapsed.
#ifndef FEC_H
#define FEC_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
unsigned int schemaID;
unsigned int fragmentID;
unsigned int msgID;
unsigned int etherType;
unsigned int originSize;
unsigned int framgentSize;
} fec_header_t;
/* 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, fec_header_t *fec_header);
/* 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
/*
* ===============================================================================
* Project: FEC decoder @ SW
*
* Filename: fec_decoder.cpp
*
* Description: Reads FEC frames (recognized by EtherType) from the socket
* Recognizes FEC header
* Does de-hamming (based on Cesar's with corrected table)
* Hamming parity bytes at the end of each chunk (not at the
* end of the frame )
*
* Version: 1.0
* Created: 04/09/2011
* Revision: none
* Compiler: gcc
*
* Author: Maciej Lipinski (based on test-drive.c by C.Prados)
* Company: CERN
*
* ============================================================================
*/
#include "fec.h"
#include "fec_decoder.h"
my_socket *create_socket(wr_sockaddr_t *bind_addr)
{
struct sockaddr_ll sll;
struct my_socket *s;
struct ifreq f;
int fd;
fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if(fd < 0)
{
perror("socket()");
return NULL;
}
fcntl(fd, F_SETFL, O_NONBLOCK);
// Put the controller in promiscious mode, so it receives everything
strcpy(f.ifr_name, bind_addr->if_name);
if(ioctl(fd, SIOCGIFFLAGS,&f) < 0) { perror("ioctl()"); return NULL; }
f.ifr_flags |= IFF_PROMISC;
if(ioctl(fd, SIOCSIFFLAGS,&f) < 0) { perror("ioctl()"); return NULL; }
// Find the inteface index
strcpy(f.ifr_name, bind_addr->if_name);
ioctl(fd, SIOCGIFINDEX, &f);
sll.sll_ifindex = f.ifr_ifindex;
sll.sll_family = AF_PACKET;
sll.sll_protocol = htons(bind_addr->ethertype);
sll.sll_halen = 6;
memcpy(sll.sll_addr, bind_addr->mac, 6);
if(bind(fd, (struct sockaddr *)&sll, sizeof(struct sockaddr_ll)) < 0)
{
close(fd);
perror("bind()");
return NULL;
}
s=(struct my_socket*)calloc(sizeof(struct my_socket), 1);
s->if_index = f.ifr_ifindex;
memcpy(s->local_mac, f.ifr_hwaddr.sa_data, 6);
memcpy(&s->bind_addr, bind_addr, sizeof(wr_sockaddr_t));
s->fd = fd;
return (my_socket*)s;
}
int recvfrom(my_socket *sock, wr_sockaddr_t *from, void *data, size_t data_length)
{
struct my_socket *s = (struct my_socket *)sock;
struct etherpacket pkt;
struct msghdr msg;
struct iovec entry;
struct sockaddr_ll from_addr;
struct {
struct cmsghdr cm;
char control[1024];
} control;
struct cmsghdr *cmsg;
size_t len = data_length + sizeof(struct ethhdr);
memset(&msg, 0, sizeof(msg));
msg.msg_iov = &entry;
msg.msg_iovlen = 1;
entry.iov_base = &pkt;
entry.iov_len = len;
msg.msg_name = (caddr_t)&from_addr;
msg.msg_namelen = sizeof(from_addr);
msg.msg_control = &control;
msg.msg_controllen = sizeof(control);
int ret = recvmsg(s->fd, &msg, MSG_DONTWAIT);
if(ret < 0 && errno==EAGAIN) return 0; // would be blocking
if(ret == -EAGAIN) return 0;
if(ret <= 0) return ret;
memcpy(data, pkt.data, ret - sizeof(struct ethhdr));
from->ethertype = ntohs(pkt.ether.h_proto);
memcpy(from->mac, pkt.ether.h_source, 6);
memcpy(from->mac_dest, pkt.ether.h_dest, 6);
return ret - sizeof(struct ethhdr);
}
int main()
{
struct my_socket *socket;
wr_sockaddr_t bindaddr;
wr_sockaddr_t dummy_addr;
int ret, i;
//Octet buf[PACKET_SIZE];
unsigned char buf[PACKET_SIZE];
unsigned char msg[PACKET_SIZE];
const unsigned char* cbuf;
unsigned int len;
strcpy(bindaddr.if_name, "eth4");
bindaddr.ethertype = 0xDEED; // FEC's etherType, fecked
memcpy(bindaddr.mac, FEC_ADDR, sizeof(mac_addr_t));
socket = create_socket(&bindaddr);
int CM_cnt = 0;
int CMs_frame_cnt=0;
fec_header_t fec_header;
while(1)
{
if((ret = recvfrom(socket, &dummy_addr, (unsigned char*)buf, PACKET_SIZE)) > 0)
{
if(CMs_frame_cnt == 0)
{
printf("\n");
printf("|------------------------------------------------------------------------|\n");
printf("| STARTING reception of Control Message [%2d] |\n",CM_cnt);
printf("|------------------------------------------------------------------------|\n");
printf("\n");
}
printf(" >> FEC-encoded Ethernet Frame nr %d received [size=%d] << \n",CMs_frame_cnt,ret);
#ifdef printf_debugging
printf("----- FEC header -----\n");
#endif
for(i=0;i<ret;) //endianess
{
//header
if(i < FEC_HEADE_SIZE)
{
//msg[i] = buf[i+1];
//msg[i+1] = buf[i];
msg[i] = buf[i];
msg[i+1] = buf[i+1];
#ifdef printf_debugging
printf("msg[%3d] = 0x%2x <-> buf[%3d] = 0x%2x\n",i,msg[i],i, buf[i]);
printf("msg[%3d] = 0x%2x <-> buf[%3d] = 0x%2x\n",i+1,msg[i+1],i+1, buf[i+1]);
if(i==6) printf("----- Payload -----\n");
#endif
i=i+2;
}
//payload
else
{
msg[i] = buf[i+1];
msg[i+1] = buf[i];
#ifdef printf_debugging
printf("msg[%3d] = 0x%2x <-> buf[%3d] = 0x%2x\n",i,msg[i],i, buf[i]);
printf("msg[%3d] = 0x%2x <-> buf[%3d] = 0x%2x\n",i+1,msg[i+1],i+1, buf[i+1]);
#endif
i=i+2;
}
}
#ifdef printf_debugging
printf("----- End of Ethernet Frame -----\n");
#endif
printf("\n>>>>>>>>>>>>>>>>>>>>>>>>>>>> de-FEC-ing start <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
len = (unsigned int)ret;
cbuf = fec_decode(msg, &len, &fec_header);
printf("\n>>>>>>>>>>>>>>>>>>>>>>>>>>>> de-FEC-ing finish<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
if(CMs_frame_cnt == 3)
{
printf("\n");
printf("|------------------------------------------------------------------------|\n");
printf("| FINISHED reception of Control Message [%2d] |\n",CM_cnt);
printf("|------------------------------------------------------------------------|\n");
//for(int z =0;
printf("|------------------------------------------------------------------------|\n");
printf("\n");
}
else
CMs_frame_cnt++;
}
}
return 1;
}
#ifndef _fec_decoder_h
#define _fec_decoder_h
#include "fec.h"
#include <stdio.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#include <linux/if_arp.h>
#include <linux/errqueue.h>
#include <linux/sockios.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <asm/types.h>
#include <fcntl.h>
#include <errno.h>
#include <ctype.h>
#define DEMO__
//#define DEMO__ // makes a binary for the demo
#include <asm/socket.h>
#define PACKET_SIZE 1518
#define IFACE_NAME_LEN 16
#define ETHER_MTU 1518
#define PACKED __attribute__((packed))
// FECed frame header size [bytes]
#define FEC_HEADE_SIZE 8
typedef uint32_t ipv4_addr_t;
typedef char Octet;
typedef uint8_t mac_addr_t[6];
const mac_addr_t FEC_ADDR = {0x76, 0x54, 0xba, 0x98 , 0xfe, 0xdc};
PACKED struct etherpacket {
struct ethhdr ether;
char data[ETHER_MTU];
};
typedef void *wr_socket_t;
typedef struct {
// Network interface name (eth0, ...)
char if_name[IFACE_NAME_LEN];
// MAC address
mac_addr_t mac;
// Destination MASC address, filled by recvfrom() function on interfaces bound to multiple addresses
mac_addr_t mac_dest;
// IP address
ipv4_addr_t ip;
// UDP port
uint16_t port;
// RAW ethertype
uint16_t ethertype;
// physical port to bind socket to
uint16_t physical_port;
} wr_sockaddr_t;
struct my_socket {
int fd;
wr_sockaddr_t bind_addr;
mac_addr_t local_mac;
int if_index;
} ;
#endif
\ No newline at end of file
/* Copyright 2010-2011 GSI GmbH.
* All rights reserved.
*
* A quick-and-dirty implementation of GF(2^8).
* Optimized for ease of translation into hardware, not speed.
*
* Author: Wesley W. Terpstra
*/
#ifndef __GF256_H__
#define __GF256_H__
#include <iostream>
#include <iomanip>
class GF256
{
protected:
typedef unsigned char rep;
rep value;
GF256(rep x) : value(x) { }
public:
GF256() : value(0) { }
GF256(const GF256& y) : value(y.value) { }
/* Important constants */
static const GF256 zero;
static const GF256 one;
static const GF256 g;
/* Explicit conversion operators */
static GF256 embed(rep v) { return GF256(v); }
rep project() const { return value; }
bool operator == (GF256 y)
{
return value == y.value;
}
bool operator != (GF256 y)
{
return value != y.value;
}
GF256& operator = (GF256 y)
{
value = y.value;
return *this;
}
GF256& operator += (GF256 y)
{
value ^= y.value;
return *this;
}
GF256& operator -= (GF256 y)
{
value ^= y.value;
return *this;
}
GF256 operator + (GF256 y) const
{
GF256 out(*this);
out += y;
return out;
}
GF256 operator - (GF256 y) const
{
GF256 out(*this);
out -= y;
return out;
}
GF256 operator - () const
{
return GF256(*this);
}
GF256 operator * (GF256 y) const
{
rep a = value;
rep b = y.value;
rep a0 = (a>>0)&1;
rep a1 = (a>>1)&1;
rep a2 = (a>>2)&1;
rep a3 = (a>>3)&1;
rep a4 = (a>>4)&1;
rep a5 = (a>>5)&1;
rep a6 = (a>>6)&1;
rep a7 = (a>>7)&1;
rep b0 = (b>>0)&1;
rep b1 = (b>>1)&1;
rep b2 = (b>>2)&1;
rep b3 = (b>>3)&1;
rep b4 = (b>>4)&1;
rep b5 = (b>>5)&1;
rep b6 = (b>>6)&1;
rep b7 = (b>>7)&1;
#if 1
/* This is output from gates-gf targetting the modulus 2d */
rep c0 = (a0&b0) ^ (a1&b7) ^ (a2&b6) ^ (a3&b5) ^ (a4&b4) ^ (a4&b7) ^ (a5&b3) ^ (a5&b6) ^ (a6&b2) ^ (a6&b5) ^ (a6&b7) ^ (a7&b1) ^ (a7&b4) ^ (a7&b6);
rep c1 = (a0&b1) ^ (a1&b0) ^ (a2&b7) ^ (a3&b6) ^ (a4&b5) ^ (a5&b4) ^ (a5&b7) ^ (a6&b3) ^ (a6&b6) ^ (a7&b2) ^ (a7&b5) ^ (a7&b7);
rep c2 = (a0&b2) ^ (a1&b1) ^ (a1&b7) ^ (a2&b0) ^ (a2&b6) ^ (a3&b5) ^ (a3&b7) ^ (a4&b4) ^ (a4&b6) ^ (a4&b7) ^ (a5&b3) ^ (a5&b5) ^ (a5&b6) ^ (a6&b2) ^ (a6&b4) ^ (a6&b5) ^ (a7&b1) ^ (a7&b3) ^ (a7&b4);
rep c3 = (a0&b3) ^ (a1&b2) ^ (a1&b7) ^ (a2&b1) ^ (a2&b6) ^ (a2&b7) ^ (a3&b0) ^ (a3&b5) ^ (a3&b6) ^ (a4&b4) ^ (a4&b5) ^ (a5&b3) ^ (a5&b4) ^ (a5&b7) ^ (a6&b2) ^ (a6&b3) ^ (a6&b6) ^ (a6&b7) ^ (a7&b1) ^ (a7&b2) ^ (a7&b5) ^ (a7&b6);
rep c4 = (a0&b4) ^ (a1&b3) ^ (a2&b2) ^ (a2&b7) ^ (a3&b1) ^ (a3&b6) ^ (a3&b7) ^ (a4&b0) ^ (a4&b5) ^ (a4&b6) ^ (a5&b4) ^ (a5&b5) ^ (a6&b3) ^ (a6&b4) ^ (a6&b7) ^ (a7&b2) ^ (a7&b3) ^ (a7&b6) ^ (a7&b7);
rep c5 = (a0&b5) ^ (a1&b4) ^ (a1&b7) ^ (a2&b3) ^ (a2&b6) ^ (a3&b2) ^ (a3&b5) ^ (a3&b7) ^ (a4&b1) ^ (a4&b4) ^ (a4&b6) ^ (a5&b0) ^ (a5&b3) ^ (a5&b5) ^ (a6&b2) ^ (a6&b4) ^ (a6&b7) ^ (a7&b1) ^ (a7&b3) ^ (a7&b6) ^ (a7&b7);
rep c6 = (a0&b6) ^ (a1&b5) ^ (a2&b4) ^ (a2&b7) ^ (a3&b3) ^ (a3&b6) ^ (a4&b2) ^ (a4&b5) ^ (a4&b7) ^ (a5&b1) ^ (a5&b4) ^ (a5&b6) ^ (a6&b0) ^ (a6&b3) ^ (a6&b5) ^ (a7&b2) ^ (a7&b4) ^ (a7&b7);
rep c7 = (a0&b7) ^ (a1&b6) ^ (a2&b5) ^ (a3&b4) ^ (a3&b7) ^ (a4&b3) ^ (a4&b6) ^ (a5&b2) ^ (a5&b5) ^ (a5&b7) ^ (a6&b1) ^ (a6&b4) ^ (a6&b6) ^ (a7&b0) ^ (a7&b3) ^ (a7&b5);
#else
rep modulus = 0x1b;
/* ci = b*x^i */
/* bi*modulus is just bi?modulus:0 */
rep c0 = b;
rep c1 = (c0 << 1) ^ (c0 >> 7)*modulus;
rep c2 = (c1 << 1) ^ (c1 >> 7)*modulus;
rep c3 = (c2 << 1) ^ (c2 >> 7)*modulus;
rep c4 = (c3 << 1) ^ (c3 >> 7)*modulus;
rep c5 = (c4 << 1) ^ (c4 >> 7)*modulus;
rep c6 = (c5 << 1) ^ (c5 >> 7)*modulus;
rep c7 = (c6 << 1) ^ (c6 >> 7)*modulus;
/* x*y here is just y?x:0 */
rep o0 = c0 * ((a>>0)&1);
rep o1 = c1 * ((a>>1)&1);
rep o2 = c2 * ((a>>2)&1);
rep o3 = c3 * ((a>>3)&1);
rep o4 = c4 * ((a>>4)&1);
rep o5 = c5 * ((a>>5)&1);
rep o6 = c6 * ((a>>6)&1);
rep o7 = c7 * ((a>>7)&1);
return ((o0^o1)^(o2^o3))^((o4^o5)^(o6^o7));
#endif
return (c7<<7)|(c6<<6)|(c5<<5)|(c4<<4)|(c3<<3)|(c2<<2)|(c1<<1)|(c0<<0);
}
GF256& operator *= (GF256 y)
{
return *this = *this * y;
}
GF256 operator ^ (int x) const
{
GF256 out(1);
GF256 pow(*this);
x %= 255;
if (x < 0) x += 255;
for (; x > 0; x >>= 1)
{
if ((x & 1) != 0)
out *= pow;
pow *= pow;
}
return out;
}
GF256 inverse () const
{
return *this ^ 254;
}
GF256 operator / (GF256 y) const
{
return *this * y.inverse();
}
GF256& operator /= (GF256 y)
{
return *this = *this / y;
}
friend std::ostream& operator << (std::ostream& o, GF256 y)
{
return o << std::hex << std::setw(2) << (int)y.value;
}
};
#endif
#include "hamming.h"
#define NUM_CHECK_BITS 7 // plus parity bit
#define BIT_MASK 0x1
#define SIZE 8 // 8 words 64 bits
//#define printf_debugging
//corrected matrix provided by Cesar
unsigned int pbits0[NUM_CHECK_BITS][SIZE] ={{0x5B, 0xAD, 0xAA, 0x56, 0x55, 0x55, 0x55, 0xAB}, // check vector 1
{0x6D, 0x36, 0x33, 0x9B, 0x99, 0x99, 0x99, 0xCD}, // check vector 2
{0x8E, 0xC7, 0xC3, 0xE3, 0xE1, 0xE1, 0xE1, 0xF1}, // check vector 3
{0xF0, 0x07, 0xFC, 0x03, 0xFE, 0x01, 0xFE, 0x01}, // check vector 4
{0x00, 0xF8, 0xFF, 0x03, 0x00, 0xFE, 0xFF, 0x01}, // check vector 5
{0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x01}, // check vector 6
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE} // check vector 7
};
/*
input :
frame - buffer with entire msg
ichunk - index of the first byte in the chunk which is being processed
chunks - index of the parity byte (in original Cesar's, it was the number of all chunks, since all the parity bytes where at the end)
nBytep - output - the number of the byte (in the chunk) in which the bitflip is
nBitp - output - the number of the bit (in the nByte) in which the bitflip is
return:
0 = no errors
1 = single error, so corrected
2 = double error, could not correct
*/
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;
//calculate parity of the chunk (8 byte)
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 */
//check parity bit (for all bits in the chunk)
unsigned int parityBit = 0;
if((parity[0] & 0x1) == (static_cast<unsigned char>(frame[chunks]) & 0x1))
parityBit = 1; // No error or double error
#ifdef printf_debugging
int d;
for(d=0; d<8;d++)
printf(" 0x%x\n",static_cast<unsigned char>(frame[d+ichunk]));
printf("parity: 0x%x vs 0x%x\n",static_cast<unsigned char>(frame[d+ichunk]),parity[0]);
#endif
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;
result = 1 ; //repaired
}
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__
//#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);
printf("fec_encode done\n");
cbuf = fec_decode(buf, &len);
printf("fec_decode done\n");
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;
}
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
#Makefile for Hamming Code
CC = g++
CFLAGS = -g3 -O0 -lm -w -Wall
OBJS = test-driver.o code.o crc.o fec.o hamming.o
OUTPUT= test
all : $(OBJS)
$(CC) $(CFLAGS) $(OBJS) -o $(OUTPUT)
clean:
rm -f $(OBJS) $(OUTPUT)
/* 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];
}
This diff is collapsed.
/**********************************************************************
*
* 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
#ifdef __cplusplus
extern "C" {
#endif
void crcInit(void);
crc crcSlow(unsigned char const message[], int nBytes);
crc crcFast(unsigned char const message[], int nBytes);
#ifdef __cplusplus
}
#endif
#endif /* _crc_h */
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);
/* 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
This diff is collapsed.
This diff is collapsed.
#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
This diff is collapsed.
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