#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define LGX 17
#define LMX 48

//generator polynomial x^16 + x^12 + x^5 + 1
char gX[] = {1,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,1};

//this does mX/gX and puts remainder in tX. Note that
//mX is overwritten, so keep a copy.
void crc (char mX[LMX], char tX[LGX]) {

    int i, j, k;

    for (i = 0; i < LMX-LGX+1; i++) {
	if (mX[i] == 0)
	    //xor with all 0s
	    continue;
	else {
	    //do actual xor
	    for (j = 0, k = i; j < LGX; j++, k++) {
		if ((gX[j] == 0 && mX[k] == 0) ||
		    (gX[j] == 1 && mX[k] == 1))
		    mX[k] = 0;
		else
		    mX[k] = 1;
	    }
	}
    }

    //copy the result to tX
    for (i = LMX-LGX+1, j = 0; i < LMX; i++, j++)
	tX[j] = mX[i];

    return;
}

int main () {

    char mX[LMX], mXcopy[LMX], tX[LGX];

    int i, j, k, r;

    srandom (time (NULL));
    //randomly fill the data
    printf ("Random data: ");
    for (i = 0; i < LMX-LGX+1; i++) {
	mX[i] = random()%2;
	printf ("%d", (int)mX[i]);
    }
    printf ("\n");

    //augment LGX-1 zeroes at the end
    for (i = LMX-LGX+1; i < LMX; i++)
	mX[i] = 0;

    //copy the mX array
    for (i = 0; i < LMX; i++)
	mXcopy[i] = mX[i];

    crc (mX, tX);

    //copy back the mX array
    for (i = 0; i < LMX; i++)
	mX[i] = mXcopy[i];

    //change the last LGX bits to tX
    for (i = LMX-LGX+1, j = 0; i < LMX; i++, j++)
	mX[i] = tX[j];

    printf ("Data sent: ");
    for (i = 0 ;i < LMX; i++)
	printf ("%d", mX[i]);
    printf ("\n");

    //introduce a random error at a 50% chance
    if (random()%2 == 0) {
	r = random()%LMX;
	if (mX[r] == 1)
	    mX[r] = 0;
	else
	    mX[r] = 1;
	printf ("Random error introduced...\n");
    }

    //now calculate crc again.
    crc (mX, tX);

    //if tX is not all zeroes, there has been an error
    for (i = 0; i < LMX; i++)
	if (tX[i] == 1) {
	    printf ("Error detected...\n");
	    return 0;
	}

    printf ("No error detected...\n");
    return 0;
}

