#include <cstdlib>
#include <cstdint>
#include <cstdio>
#include <time.h>
#include <stdlib.h>


#define T_LEN  8

uint8_t transmission[T_LEN] = {0x0D, 0x0E, 0x0A, 0x0D, 
			       0x0B, 0x0E, 0x0E, 0x0F};

uint8_t syndromeShift[7] = {4, 5, 0, 6, 1, 2, 3};
//	Affected bit:	    x  y  a  z  b  c  d
//	Syndrome: 	    1  2  3  4  5  6  7
// this array enables us to use a bitmask to flip the bit
// associated with a particular syndrome
// NOTE: position 0 is for syndrome 001

void seed_rng()
{
	srand(time(NULL));
}

void introduce_error(uint8_t* transmission)
{
	uint8_t codeword = (rand() % T_LEN);
	uint8_t mask = 0x01 << (rand() % 7);

	transmission[codeword] ^= mask;
}

uint8_t find_codeword(uint8_t message)
{
	bool 
	a = message & 0x01,
	b = (message >> 1) & 0x01,
	c = (message >> 2) & 0x01,
	d = (message >> 3) & 0x01;

	return message | 
	(((a ^ b) ^ d) << 4) | 
	(((a ^ c) ^ d) << 5) |
	(((b ^ c) ^ d) << 6); 
}

uint8_t find_syndrome(uint8_t codeword)
{
	bool 
	a = codeword & 0x1,
	b = (codeword >> 1) & 0x01,
	c = (codeword >> 2) & 0x01,
	d = (codeword >> 3) & 0x01,
	x = (codeword >> 4) & 0x01,
	y = (codeword >> 5) & 0x01,
	z = (codeword >> 6) & 0x01;

	uint8_t syndrome = 
	a ^ b ^ d ^ x |
	(a ^ c ^ d ^ y) << 1 | 
	(b ^ c ^ d ^ z) << 2;
       	
	return syndrome;
}

uint8_t correct_error(uint8_t codeword)
{
	uint8_t syndrome = find_syndrome(codeword);
	
	if (syndrome == 0)
		return codeword;

	uint8_t mask = 0x01 << syndromeShift[syndrome - 1];

	return codeword ^= mask;
}

void correct_transmission(uint8_t* transmission)
{
	for(int i = 0; i < T_LEN; i++)
		transmission[i] = correct_error(transmission[i]);
}

void convert_transmission(uint8_t* transmission)
{
	for(int i = 0; i < T_LEN; i++)
		transmission[i] = find_codeword(transmission[i]);
}

void print_transmission(uint8_t* transmission)
{
	for(int i = 0; i < T_LEN; i++)
		printf("%x ", transmission[i] & 0x0F); 

	printf("     ");

	for(int i = 0; i < T_LEN; i++)
		printf("%x ", transmission[i] & 0x7F); 

	printf("\n");
}

int main()
{
	seed_rng();

	int numErrors = (rand() % 4) + 1;

	convert_transmission(transmission);

	printf("original transmission:            ");
	print_transmission(transmission);

	for (int n = 0; n < numErrors; n++) 
		introduce_error(transmission);

	printf("transmission with %d errors:       ", numErrors);
	print_transmission(transmission);

	correct_transmission(transmission);

	printf("corrected transmission:           ");
	print_transmission(transmission);	
}
