I'm using an arduino uno to create a light based communication for my college project. I'm using the arduino to take characters in a string, convert it to binary, and after encoding, sending it over a distance by a laser.
However, the infinite loop stops after processing 7-8 characters each time. The arduino stops, and Serial monitor stops printing (i'm printing the character, it's binary representation and its hamming encoded representation for debugging).
The individual blocks are:
char_to_binary(): convert char 'c' to binary and writes to global array 'c_binary'
repeater(): repeats each bit in a binary array 'reps' times
Can also perform majority detection for each set of 'reps' bits depending on 'arg' == 1 or 0
interleaver(): performs interleaving using matrix fill method
Can also perform deinterleaving for arg==0
hamming_code(): takes 4-bit array and converts it to a 7-bit hamming encoded array.
I use it twice to convert an 8-bit char to a 14-bit hamming_arr.
Can also decode 7-bit hamming codes with self-correction to 4-bits if arg==0
Here's the sketch:
#define LED_PIN A0
#define PERIOD 30
#define STARTUP_DELAY 0
//variables that the infinite loop uses
char c;
int c_binary[8]; //character's binary form
int left_nibble[4];
int right_nibble[4];
int* left_hamming;
int* right_hamming;
int hamming_arr[14]; //hamming array
int* rep_arr; //repeated array
int* tx_arr;
int tx_arr_len;
byte pin = LED_PIN;
int reps = 3;
int il_cols = 4;
char* string = "qwertyuiopasdfghjklzxcvbnm";
//REPEATER VERIFIED
//does repetition for arg==1, majority detection for arg==0
int* repeater(int *input, int input_len, int reps, int arg) {
int *output;
int output_len;
if (arg==1){ //repetition
output_len = input_len*reps;
output = (int*)malloc(sizeof(int)*output_len);
for (int i=0; i<input_len; i++){
for (int j=0; j<reps; j++){
output[i*reps+j] = input[i];
}
}
}
else{ //majority detection
output_len = input_len/reps;
output = (int*)malloc(sizeof(int)*output_len);
for (int i=0; i<output_len; i++){
int sum = 0;
for (int j=0; j<reps; j++){
sum += input[i*reps+j];
}
output[i] = sum>reps/2 ? 1 : 0;
}
}
return output;
}
//INTERLEAVER VERIFIED
//does interleaving for arg==1, deinterleaving for arg==0
int* interleaver(int *input, int input_len, int il_cols, int arg){
int* output;
int rows, cols;
if (arg==1){
cols = il_cols;
rows = ceil((float)input_len/(float)cols);
}
else{
rows = il_cols;
cols = ceil((float)input_len/(float)rows);
}
output = (int*)malloc(rows * cols * sizeof (int));
for (int i=0; i<rows; i++){
for (int j=0; j<cols; j++){
if (cols*i+j < input_len){
output[rows*j+i] = input[cols*i+j];
}
else{
output[rows*j+i] = 0;
}
}
}
return output;
}
//HAMMING CODE VERIFIED
//converts between 4-length word and 7-length codeword acc to arg==1 or 0
int* hamming_code(int *input, int arg){
int hamming_gmat[4][7] = {{1, 1, 1, 0, 0, 0, 0},
{1, 0, 0, 1, 1, 0, 0},
{0, 1, 0, 1, 0, 1, 0},
{1, 1, 0, 1, 0, 0, 1}};
int hamming_hmat[3][7] = {{1, 0, 1, 0, 1, 0, 1},
{0, 1, 1, 0, 0, 1, 1},
{0, 0, 0, 1, 1, 1, 1}};
//each row is row[0] = binary form of syndrome, row[1] = corrupted bit index
int syndrome_table[8][2] = {{1,3},
{2,1},
{3,5},
{4,0},
{5,4},
{6,2},
{7,6}};
//first 4 indices are the word, next index is decimal-converted codeword for easy comparision
int codeword_table[16][5] = {{0,0,0,0, 0},
{0,0,0,1, 105},
{0,0,1,0, 42},
{0,0,1,1, 67},
{0,1,0,0, 76},
{0,1,0,1, 37},
{0,1,1,0, 102},
{0,1,1,1, 15},
{1,0,0,0,112},
{1,0,0,1, 25},
{1,0,1,0, 90},
{1,0,1,1, 51},
{1,1,0,0, 60},
{1,1,0,1, 85},
{1,1,1,0, 22},
{1,1,1,1,127}};
int* output;
if (arg==1){ //encoding
output = (int*)malloc(7*sizeof(int));
for (int i=0; i<7; i++){
int sum=0;
for (int j=0; j<4; j++){sum+=input[j]*hamming_gmat[j][i];}
output[i] = sum%2;
}
}
else{ //decoding
int *codeword = (int*) malloc(7*sizeof (int));
for (int j=0; j<7; j++){codeword[j] = input[j];} //let codeword be same as input initially
int synd=0; //now we find the syndrome int
for (int i=0; i<3; i++){
int sum=0;
for (int j=0; j<7; j++){
sum += input[j]*hamming_hmat[i][j];
}
synd += (sum%2)*(int)pow(2,2-i);
}
//check if syndrome is in the syndrome table, if yes, then make necessary corrections
for (int i=0; i<7; i++){
if (syndrome_table[i][0]==synd) {
codeword[syndrome_table[i][1]] = (codeword[syndrome_table[i][1]] + 1) % 2;
break;
}
}
output = (int*)malloc(4*sizeof (int));
for (int i=0; i<4; i++){output[i]=0;}
//now that we have the corrected codeword, we can find what the initial word was
int codeword_int=0;
for (int i=0; i<7; i++){codeword_int += codeword[i]*pow(2,6-i);}
for (int i=0; i<16; i++){
if (codeword_table[i][4]==codeword_int){
for (int j=0; j<4; j++){output[j] = codeword_table[i][j];}
break;
}
}
}
return output;
}
//no
//function to convert a string to a array of bits
void char_to_binary(char c) {
int i, j;
for (i = 7; i >= 0; i--) {
j = 1 << i; // Bitwise left shift to get the current bit value
c_binary[7 - i] = (c & j) ? 1 : 0; // Check if the current bit is set and set the binary string accordingly
}
}
//no memory leak problems
void setup(){
Serial.begin(9600);
pinMode(LED_PIN, OUTPUT);
delay(STARTUP_DELAY); //delay to help the RX set up first, so both TX and RX need not be activated at the exact same time
}
//all variables shifted to global scope
void loop(){
for (int i=0; i<strlen(string); i++){
//Serial.print(i); Serial.println();
c = string[i];
Serial.println(c);
Serial.println("binary complete");
char_to_binary(c);
//verified!!!
for (int j=0; j<8; j++){Serial.print(c_binary[j]);}
Serial.println();
for (int j=0; j<4; j++){
left_nibble[j] = c_binary[j];
right_nibble[j] = c_binary[j+4];
}
left_hamming = hamming_code(left_nibble, 1);
right_hamming = hamming_code(right_nibble, 1);
for (int j=0; j<7; j++){
hamming_arr[j] = left_hamming[j];
hamming_arr[j+7] = right_hamming[j];
}
Serial.println("hamming complete");
rep_arr = repeater(hamming_arr, 14, reps, 1); //repeated array
Serial.println("repetition complete");
tx_arr = interleaver(rep_arr, 14*reps, il_cols, 1); //transmitted array aka the interleaved array
Serial.println("interleaving complete");
if (14*reps % il_cols == 0){tx_arr_len = 14*reps;}
else{tx_arr_len = 14*reps + il_cols - (14*reps)%il_cols;}
send_bits();
}
}
//no memory leak problems
void send_bits(){
digitalWrite(LED_PIN, HIGH);
delay(PERIOD);
digitalWrite(pin, LOW);
delay(PERIOD);
for (int i=0; i<tx_arr_len; i++){
digitalWrite(pin, HIGH);
delay(PERIOD/3);
if (tx_arr[i]==0){digitalWrite(pin, LOW);}
Serial.print(tx_arr[i]);
delay(PERIOD/3);
digitalWrite(pin, LOW);
delay(PERIOD/3);
}
Serial.println();
}