// ------------------------------------------------------------------------ // File: tcm_8psk.c // Date: April 2, 2002. // Description: TCM decoder, maximum likelihood decoding. // ------------------------------------------------------------------------ // This program is complementary material for the book: // // R.H. Morelos-Zaragoza, The Art of Error Correcting Coding, Wiley, 2002. // // ISBN 0471 49581 6 // // This and other programs are available at http://the-art-of-ecc.com // // You may use this program for academic and personal purposes only. // If this program is used to perform simulations whose results are // published in a journal or book, please refer to the book above. // // The use of this program in a commercial product requires explicitely // written permission from the author. The author is not responsible or // liable for damage or loss that may be caused by the use of this program. // // Copyright (c) 2002. Robert H. Morelos-Zaragoza. All rights reserved. // ------------------------------------------------------------------------ #include #include #include #include // #include "viterbi_conventional.h" #define MAX_RANDOM LONG_MAX // Use the compiling directive -DSHOW_PROGRESS to see how the decoder // converges to the decoded sequence by monitoring the survivor memory #ifdef SHOW_PROGRESS #define DELTA 1 #endif int k2=1, n2, m2; int NUM_STATES, OUT_SYM, NUM_TRANS; long TRUNC_LENGTH; double RATE; double INIT_SNR, FINAL_SNR, SNR_INC; long NUMSIM; char name1[40], name2[40]; FILE *fp; /* Pointer for trellis data file */ // unsigned int g2[n2][k2] = { /* rate-1/2 memory=6 */ // 0x4f, /* REVERSE ORDER */ // 0x6d }; /* */ unsigned int g2[10][10]; unsigned int memory2, output; /* Memory and output */ unsigned int data2; /* Data */ unsigned long seed; /* Seed for random generator */ unsigned int data_symbol[1024]; /* 1-bit data sequence */ unsigned int data_symbol2[1024]; /* 1-bit data sequence */ unsigned long indxx; /* Simulation index */ double psk_I[8], psk_Q[8]; int transmitted; /* index of transmitted signal */ double transmitted_I; /* Transmitted signals/branch */ double transmitted_Q; /* Transmitted signals/branch */ int estimate_data2; double snr, amp; double received_I; /* Received signals/branch */ double received_Q; /* Received signals/branch */ // Data structures used for trellis sections and survivors struct trel { int init; /* initial state */ int data; /* data symbol */ int final; /* final state */ int output; /* output coded symbols (branch label) */ }; struct surv { double metric; /* metric */ int data[1024]; /* estimated data symbols */ int data2[1024]; /* estimated data symbols */ int state[1024]; /* state sequence */ }; // A trellis section is an array of branches, indexed by an initial // state and a k_2-bit input data. The values read // are the final state and the output symbols struct trel trellis[1024][100]; /* A survivor is a sequence of states and estimated data, of length equal to TRUNC_LENGTH, together with its corresponding metric. A total of NUM_STATES survivors are needed */ struct surv survivor[1024], surv_temp[1024]; /* Function prototypes */ void encoder2(void); /* Encoder for C_{O2} */ int random_data(void); /* Random data generator */ void transmit(void); /* Encoder & BPSK modulator */ void awgn(void); /* Add AWGN */ void viterbi(void); /* Viterbi decoder */ double comp_metric(double rec_I, double rec_Q, int ref); /* Metric calc */ double comp_correl(double rec_I, double rec_Q, int ref); /* Metric calc */ void open_files(void); /* Open files for output */ void close_files(void); /* Close files */ main(int argc, char *argv[]) { register int i, j, k; int init, data, final, output; register int error; unsigned long error_count, error_coded, error_uncoded; FILE *fp_ber; /* Pointer for overall BER data file */ double RATE; // Command line processing if (argc != 8) { printf("Usage %s file_input file_output truncation snr_init snr_final snr_ inc num_sim\n", argv[0]); exit(0); } sscanf(argv[1],"%s", name1); sscanf(argv[2],"%s", name2); sscanf(argv[3],"%ld", &TRUNC_LENGTH); sscanf(argv[4],"%lf", &INIT_SNR); sscanf(argv[5],"%lf", &FINAL_SNR); sscanf(argv[6],"%lf", &SNR_INC); sscanf(argv[7],"%ld", &NUMSIM); printf("\nSimulation of TCM decoding with 8-PSK modulation over an AWGN channel\n"); printf("%ld simulations per Eb/No (dB) point\n", NUMSIM); fp_ber = fopen(name2,"w"); /* Open file with trellis data */ if (!(fp = fopen(name1,"r"))) { printf("Error opening file!\n"); exit(1); } fscanf(fp, "%d %d", &n2, &m2); RATE = (2.0 / (double) n2)*3.0; // 2 bits per symbol if encoder is rate 1/2 fscanf(fp, "%d %d %d", &NUM_STATES, &OUT_SYM, &NUM_TRANS); for (j=0; j>1) & 1 ); /* */ #ifdef PRINT printf("Transmitted data sequence:\n"); printf("%2d %x ",(indxx % TRUNC_LENGTH), data_symbol[indxx % TRUNC_LENGTH]); for (i=0; i> 5) & 3 ); } /****************************************************************************/ void encoder2() { /* Conventional convolutional encoder, rate 1/n2 (fixed k_2=1) */ register int i, j, result, temp; temp = memory2; output = 0; temp = (temp<<1) ^ data_symbol[indxx % TRUNC_LENGTH]; for (i=0; i=0; j--) result ^= ( ( temp & g2[i][0] ) >> j ) & 1; output = ( output<<1 ) ^ result; } memory2 = temp ; } /****************************************************************************/ void transmit() { /* Encode and modulate a 1-bit data sequence */ int i; encoder2(); /* */ #ifdef DEB printf("memory2 = %x\n", memory2); #endif transmitted = output + 4*data_symbol2[indxx % TRUNC_LENGTH]; } /****************************************************************************/ void awgn() { /* Add AWGN to transmitted sequence */ double u1,u2,s,noise,randmum; int i; #ifdef PRINT printf("Received = "); #endif #ifdef NO_NOISE received_I = psk_I[transmitted]; received_Q = psk_Q[transmitted]; return; } #else do { randmum = (double)(random())/MAX_RANDOM; u1 = randmum*2.0 - 1.0; randmum = (double)(random())/MAX_RANDOM; u2 = randmum*2.0 - 1.0; s = u1*u1 + u2*u2; } while( s >= 1); noise = u1 * sqrt( (-2.0*log(s))/s )/amp; received_I = psk_I[transmitted] + noise; do { randmum = (double)(random())/MAX_RANDOM; u1 = randmum*2.0 - 1.0; randmum = (double)(random())/MAX_RANDOM; u2 = randmum*2.0 - 1.0; s = u1*u1 + u2*u2; } while( s >= 1); noise = u1 * sqrt( (-2.0*log(s))/s )/amp; received_Q = psk_Q[transmitted] + noise; #ifdef PRINT printf("%4.2lf %4.2lf ", received_I, received_Q); #endif #ifdef PRINT printf("\n"); #endif } #endif /****************************************************************************/ void viterbi() { /* Viterbi decoding */ double aux_metric, surv_metric[NUM_STATES]; register int i,j,k; double metrics[4]; int estimated[4]; /* Branch metric computation and uncoded bit */ for (i=0; i<4; i++) { metrics[i] = comp_metric(received_I,received_Q,i); estimated[i] = estimate_data2; } for (i=0; i ",i); for (k=0; k