```/* Soft decision Viterbi Decoder Test Driver                        */
/* Copyright (c) 1999, Spectrum Applications, Derwood, MD, USA      */

#include <alloc.h>
#include <conio.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#include "vdsim.h"

extern void gen01dat(long data_len, int *out_array);
extern void cnv_encd(int g[2][K], long data_len, int *in_array, int *out_array);
extern void addnoise(float es_ovr_n0, long data_len, int *in_array, float *out_array);
extern void sdvd(int g[2][K], float es_ovr_n0, long channel_length,
float *channel_output_vector, int *decoder_output_matrix);

void testsdvd(void) {

long iter, t, msg_length, channel_length; /* loop variables, length of I/O files */

int *onezer;
int *encoded;                    /* original, encoded, & decoded data arrays */
int *sdvdout;

int start;

float *splusn;                   /* noisy data array */

int i_rxdata, m;                 /* int rx data , m = K - 1*/
float es_ovr_n0, number_errors_encoded, number_errors_unencoded,
e_threshold, ue_threshold, e_ber, ue_ber; /* various statistics */

#if K == 3        /* polynomials for K = 3 */
int g[2][K] = {{1, 1, 1},     /* 7 */
{1, 0, 1}};    /* 5 */
#endif

#if K == 5        /* polynomials for K = 5 */
int g[2][K] = {{1, 1,  1, 0, 1},  /* 35 */
{1, 0,  0, 1, 1}}; /* 23 */
#endif

#if K == 7        /* polynomials for K = 7 */
int g[2][K] = {{1,  1, 1, 1,  0, 0, 1},  /* 171 */
{1,  0, 1, 1,  0, 1, 1}}; /* 133 */
#endif

#if K == 9        /* polynomials for K = 9 */
int g[2][K] = {{1, 1, 1,  1, 0, 1,  0, 1, 1}, /* 753 */
{1, 0, 1,  1, 1, 0,  0, 0, 1}}; /* 561 */
#endif

clrscr();

printf("\nK = %d", K);

#if K == 3
printf("\ng1 = %d%d%d", g[0][0], g[0][1], g[0][2] );
printf("\ng2 = %d%d%d\n", g[1][0], g[1][1], g[1][2] );
#endif

#if K == 5
printf("\ng1 = %d%d %d%d%d", g[0][0], g[0][1], g[0][2], g[0][3], g[0][4] );
printf("\ng2 = %d%d %d%d%d\n", g[1][0], g[1][1], g[1][2], g[1][3], g[1][4] );
#endif

#if K == 7
printf("\ng1 = %d %d%d%d %d%d%d", g[0][0], g[0][1], g[0][2], g[0][3], g[0][4],
g[0][5], g[0][6] );
printf("\ng2 = %d %d%d%d %d%d%d\n", g[1][0], g[1][1], g[1][2], g[1][3], g[1][4],
g[1][5], g[1][6] );
#endif

#if K == 9
printf("\ng1 = %d%d%d %d%d%d %d%d%d", g[0][0], g[0][1], g[0][2], g[0][3], g[0][4],
g[0][5], g[0][6], g[0][7], g[0][8] );
printf("\ng2 = %d%d%d %d%d%d %d%d%d\n", g[1][0], g[1][1], g[1][2], g[1][3], g[1][4],
g[1][5], g[1][6], g[1][7], g[1][8] );
#endif

m = K - 1;
msg_length = MSG_LEN;
channel_length = ( msg_length + m ) * 2;

onezer = malloc( msg_length * sizeof( int ) );
if (onezer == NULL) {
printf("\n testsdvd.c:  error allocating onezer array, aborting!");
exit(1);
}

encoded = malloc( channel_length * sizeof(int) );
if (encoded == NULL) {
printf("\n testsdvd.c:  error allocating encoded array, aborting!");
exit(1);
}

splusn = malloc( channel_length * sizeof(float) );
if (splusn == NULL) {
printf("\n testsdvd.c:  error allocating splusn array, aborting!");
exit(1);
}

sdvdout = malloc( msg_length * sizeof( int ) );
if (sdvdout == NULL) {
printf("\n testsdvd.c:  error allocating sdvdout array, aborting!");
exit(1);
}

for (es_ovr_n0 = LOESN0; es_ovr_n0 <= HIESN0; es_ovr_n0 += ESN0STEP) {

start = time(NULL);

number_errors_encoded = 0.0;
e_ber = 0.0;
iter = 0;

#ifdef DOENC
if (es_ovr_n0 <= 9)
e_threshold = 100; /* +/- 20% */
else
e_threshold = 20; /* +/- 100 % */

while (number_errors_encoded < e_threshold) {
iter += 1;

/*printf("Generating one-zero data\n");*/
gen01dat(msg_length, onezer);

/*printf("Convolutionally encoding the data\n");*/
cnv_encd(g, msg_length, onezer, encoded);

/*printf("Adding noise to the encoded data\n");*/

/*printf("Decoding the BSC data\n");*/
sdvd(g, es_ovr_n0, channel_length, splusn, sdvdout);

for (t = 0; t < msg_length; t++) {
if ( *(onezer + t) != *(sdvdout + t) ) {
/*printf("\n error occurred at location %ld", t);*/
number_errors_encoded += 1;
} /* end if */
} /* end t for-loop */

if (kbhit()) exit(0);
/*printf("\nDone!");*/

}

e_ber = number_errors_encoded / (msg_length * iter);

printf("\nThe elapsed time was %d seconds for %d iterations",
time(NULL) - start, iter);
#endif

number_errors_unencoded = 0.0;
ue_ber = 0.0;
iter = 0;

#ifdef DONOENC
if (es_ovr_n0 <= 12)
ue_threshold = 100;
else
ue_threshold = 20;

while (number_errors_unencoded < ue_threshold) {
iter += 1;

/*printf("Generating one-zero data\n");*/
gen01dat(msg_length, onezer);

/*printf("Adding noise to the unencoded data\n");*/

for (t = 0; t < msg_length; t++) {

if ( *(splusn + t) < 0.0 )
i_rxdata = 1;
else
i_rxdata = 0;

if ( *(onezer + t) != i_rxdata )
number_errors_unencoded += 1;
}

if (kbhit()) exit(0);
/*printf("\nDone!");*/

}

ue_ber = number_errors_unencoded / (msg_length * iter);
#endif

printf("\nAt %1.1fdB Es/No, ", es_ovr_n0);

#ifdef DOENC
printf("the e_ber was %1.1e ", e_ber);
#ifdef DONOENC
printf("and ");
#endif
#endif

#ifdef DONOENC
printf("the ue_ber was %1.1e", ue_ber);
#endif

}

free(onezer);
free(encoded);
free(splusn);
free(sdvdout);

while ( !kbhit() ) {
}

exit(0);
}```