mirror of
				https://github.com/gnss-sdr/gnss-sdr
				synced 2025-10-31 15:23:04 +00:00 
			
		
		
		
	Galileo INAV de-interleaver and Viterbi decoder implemented.
git-svn-id: https://svn.code.sf.net/p/gnss-sdr/code/trunk@390 64b25241-fba3-4117-9849-534c7e92360d
This commit is contained in:
		| @@ -1,6 +1,6 @@ | ||||
| /*! | ||||
|  * \file galileo_e1b_telemetry_decoder_cc.cc | ||||
|  * \brief Implementation of a NAV message demodulator block | ||||
|  * \brief Implementation of a Galileo INAV message demodulator block | ||||
|  * \author Mara Branzanti 2013. mara.branzanti(at)gmail.com | ||||
|  * \author Javier Arribas 2013. jarribas(at)cttc.es | ||||
|  * | ||||
| @@ -42,6 +42,8 @@ | ||||
|  | ||||
| #include "gnss_synchro.h" | ||||
|  | ||||
| #include "convolutional.h" | ||||
|  | ||||
| using google::LogMessage; | ||||
|  | ||||
|  | ||||
| @@ -63,6 +65,59 @@ void galileo_e1b_telemetry_decoder_cc::forecast (int noutput_items, gr_vector_in | ||||
|         } | ||||
| } | ||||
|  | ||||
|  | ||||
| void galileo_e1b_telemetry_decoder_cc::viterbi_decoder(double *page_part_symbols, int *page_part_bits) | ||||
| { | ||||
|  | ||||
| 	int CodeLength=240; | ||||
| 	int DataLength; | ||||
| 	int	nn, KK, mm, max_states; | ||||
| 	int g_encoder[2]; | ||||
|  | ||||
| 	nn = 2; //Coding rate 1/n | ||||
| 	KK = 7; //Constraint Length | ||||
| 	g_encoder[0]=121; // Polynomial G1 | ||||
| 	g_encoder[1]=91; // Polinomial G2 | ||||
|  | ||||
| 	mm = KK - 1; | ||||
| 	max_states = 1 << mm;			/* 2^mm */ | ||||
| 	DataLength = (CodeLength/nn)-mm; | ||||
|  | ||||
| 	/* create appropriate transition matrices */ | ||||
| 	int     *out0, *out1, *state0, *state1; | ||||
| 	out0 = (int*)calloc( max_states, sizeof(int) ); | ||||
| 	out1 = (int*)calloc( max_states, sizeof(int) ); | ||||
| 	state0 = (int*)calloc( max_states, sizeof(int) ); | ||||
| 	state1 = (int*)calloc( max_states, sizeof(int) ); | ||||
|  | ||||
| 	nsc_transit( out0, state0, 0, g_encoder, KK, nn ); | ||||
| 	nsc_transit( out1, state1, 1, g_encoder, KK, nn ); | ||||
|  | ||||
| 	Viterbi( page_part_bits, out0, state0, out1, state1, | ||||
| 			page_part_symbols, KK, nn, DataLength ); | ||||
|  | ||||
|  | ||||
| 	/* Clean up memory */ | ||||
| 	free( out0 ); | ||||
| 	free( out1 ); | ||||
| 	free( state0 ); | ||||
| 	free( state1 ); | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| void galileo_e1b_telemetry_decoder_cc::deinterleaver(int rows, int cols, double *in, double *out) | ||||
| { | ||||
| 	for (int r=0;r<rows;r++) | ||||
| 	{ | ||||
| 		for(int c=0;c<cols;c++) | ||||
| 		{ | ||||
| 			out[c*rows+r]=in[r*cols+c]; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
| galileo_e1b_telemetry_decoder_cc::galileo_e1b_telemetry_decoder_cc( | ||||
|         Gnss_Satellite satellite, | ||||
|         long if_freq, | ||||
| @@ -120,19 +175,6 @@ galileo_e1b_telemetry_decoder_cc::galileo_e1b_telemetry_decoder_cc( | ||||
|     d_TOW_at_current_symbol = 0; | ||||
|     flag_TOW_set = false; | ||||
|  | ||||
|     // set up de-interleaver table | ||||
| //    std::vector<int> positions; | ||||
| //    for (int rows=0;rows<GALILEO_INAV_INTERLEAVER_ROWS;rows++) | ||||
| //    { | ||||
| //    	for (int cols=0;cols<GALILEO_INAV_INTERLEAVER_COLS;cols++) | ||||
| //    	{ | ||||
| //    		positions.push_back(rows*GALILEO_INAV_INTERLEAVER_ROWS+cols); | ||||
| //    	} | ||||
| //    } | ||||
| //    d_interleaver= new gr::trellis::interleaver(); | ||||
|  | ||||
|     // set up trellis decoder | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -174,10 +216,8 @@ int galileo_e1b_telemetry_decoder_cc::general_work (int noutput_items, gr_vector | ||||
|     if (abs(corr_value) >= d_symbols_per_preamble) | ||||
|         { | ||||
|     		//std::cout << "Positive preamble correlation for Galileo SAT " << this->d_satellite << std::endl; | ||||
|             //TODO: Rewrite with state machine | ||||
|             if (d_stat == 0) | ||||
|                 { | ||||
|                     //d_GPS_FSM.Event_gps_word_preamble(); | ||||
|                     d_preamble_index = d_sample_counter;//record the preamble sample stamp | ||||
|                     std::cout << "Preamble detection for Galileo SAT " << this->d_satellite << std::endl; | ||||
|                     d_stat = 1; // enter into frame pre-detection status | ||||
| @@ -188,14 +228,88 @@ int galileo_e1b_telemetry_decoder_cc::general_work (int noutput_items, gr_vector | ||||
|                     //std::cout << "preamble_diff="<< preamble_diff <<" for Galileo SAT " << this->d_satellite << std::endl; | ||||
|                     if (abs(preamble_diff - GALILEO_INAV_PREAMBLE_PERIOD_SYMBOLS) < 1) | ||||
|                         { | ||||
|  | ||||
|                     		//std::cout<<"d_sample_counter="<<d_sample_counter<<std::endl; | ||||
|                     		//std::cout<<"corr_value="<<corr_value<<std::endl; | ||||
|                     		// NEW Galileo page part is received | ||||
|                     	    // 0. fetch the symbols into an array | ||||
|                     	    int frame_length=GALILEO_INAV_PAGE_PART_SYMBOLS-d_symbols_per_preamble; | ||||
|                     	    double page_part_symbols[frame_length]; | ||||
|                     	    double page_part_symbols_deint[frame_length]; | ||||
|  | ||||
|                     	    for (int i=0;i<frame_length;i++) | ||||
|                     	    { | ||||
|                     	    	page_part_symbols[i]=in[0][i+d_symbols_per_preamble].Prompt_I; // because last symbol of the preamble is just received now! | ||||
|                     	    } | ||||
|  | ||||
|                     		// 1. De-interleave | ||||
|                     	    deinterleaver(GALILEO_INAV_INTERLEAVER_ROWS,GALILEO_INAV_INTERLEAVER_COLS,page_part_symbols, page_part_symbols_deint); | ||||
|  | ||||
|                     		// 2. Viterbi decoder | ||||
|                     	    // 2.1 Take into account the NOT gate in G2 polynomial (Galileo ICD Figure 13, FEC encoder) | ||||
|                     	    // 2.2 Take into account the possible inversion of the polarity due to PLL lock at 180º | ||||
|                     	    for (int i=0;i<frame_length;i++) | ||||
|                     	    { | ||||
|                     	    	if (corr_value<0) | ||||
|                     	    	{ | ||||
|                     	    		page_part_symbols_deint[i]=-page_part_symbols_deint[i]; | ||||
|                     	    	} | ||||
|                     	    	if (i%2==0) | ||||
|                     	    	{ | ||||
|                     	    		page_part_symbols_deint[i]=-page_part_symbols_deint[i]; | ||||
|                     	    	} | ||||
|                     	    } | ||||
|  | ||||
|                     	    int page_part_bits[frame_length/2]; | ||||
|                     	    viterbi_decoder(page_part_symbols_deint, page_part_bits); | ||||
|  | ||||
|                     		// 3. Call the Galileo page decoder | ||||
|  | ||||
|                             //d_GPS_FSM.Event_gps_word_preamble(); | ||||
| //                    	    std::cout<<"frame_symbols=["; | ||||
| //                    	    for (int i=0;i<frame_length;i++) | ||||
| //                    	     { | ||||
| //                    	    	if (page_part_symbols[i]>0) | ||||
| //                    	    	{ | ||||
| //                    	    		std::cout<<",1"; | ||||
| //                    	    	}else{ | ||||
| //                    	    		std::cout<<",0"; | ||||
| //                    	    	} | ||||
| //                    	     } | ||||
| //                    	    std::cout<<"]"<<std::endl; | ||||
| //                      	    std::cout<<"frame_symbols_deint=["; | ||||
| //                        	    for (int i=0;i<frame_length;i++) | ||||
| //                        	     { | ||||
| //                        	    	if (page_part_symbols_deint[i]>0) | ||||
| //                        	    	{ | ||||
| //                        	    		std::cout<<",1"; | ||||
| //                        	    	}else{ | ||||
| //                        	    		std::cout<<",0"; | ||||
| //                        	    	} | ||||
| //                        	     } | ||||
| //                        	    std::cout<<"]"<<std::endl; | ||||
| // | ||||
| //                          	    std::cout<<"frame_bits=["; | ||||
| //                            	    for (int i=0;i<frame_length/2;i++) | ||||
| //                            	     { | ||||
| //                            	    	if (page_part_bits[i]>0) | ||||
| //                            	    	{ | ||||
| //                            	    		std::cout<<",1"; | ||||
| //                            	    	}else{ | ||||
| //                            	    		std::cout<<",0"; | ||||
| //                            	    	} | ||||
| //                            	     } | ||||
| //                            	    std::cout<<"]"<<std::endl; | ||||
|  | ||||
|                              if (page_part_bits[0]==1) | ||||
|                              { | ||||
|                             	 std::cout<<"Page Odd"<<std::endl; | ||||
|                              }else | ||||
|                              { | ||||
|                             	 std::cout<<"Page Even"<<std::endl; | ||||
|                              } | ||||
|                             //ToDo: Call here the frame decoder | ||||
|  | ||||
|  | ||||
|                             d_flag_preamble = true; | ||||
|                             d_preamble_index = d_sample_counter;  //record the preamble sample stamp (t_P) | ||||
|                             d_preamble_time_seconds = in[0][0].Tracking_timestamp_secs;// - d_preamble_duration_seconds; //record the PRN start sample index associated to the preamble | ||||
|   | ||||
| @@ -89,6 +89,10 @@ private: | ||||
|     galileo_e1b_telemetry_decoder_cc(Gnss_Satellite satellite, long if_freq, long fs_in, unsigned | ||||
|             int vector_length, boost::shared_ptr<gr::msg_queue> queue, bool dump); | ||||
|  | ||||
|     void viterbi_decoder(double *page_part_symbols, int *page_part_bits); | ||||
|  | ||||
|     void deinterleaver(int rows, int cols, double *in, double *out); | ||||
|  | ||||
|     unsigned short int d_preambles_bits[GALILEO_INAV_PREAMBLE_LENGTH_BITS]; | ||||
|  | ||||
|     signed int *d_preambles_symbols; | ||||
|   | ||||
							
								
								
									
										637
									
								
								src/algorithms/telemetry_decoder/libs/convolutional.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										637
									
								
								src/algorithms/telemetry_decoder/libs/convolutional.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,637 @@ | ||||
| /* File convolutional.h | ||||
|     | ||||
|    Description: General functions used to implement convolutional encoding.    | ||||
|  | ||||
|    Copyright (C) 2006-2008, Matthew C. Valenti | ||||
|  | ||||
|    Last updated on May 22, 2008 | ||||
|  | ||||
|    The functions in this file are part of the Iterative Solutions  | ||||
|    Coded Modulation Library. The Iterative Solutions Coded Modulation  | ||||
|    Library is free software; you can redistribute it and/or modify it  | ||||
|    under the terms of the GNU Lesser General Public License as published  | ||||
|    by the Free Software Foundation; either version 2.1 of the License,  | ||||
|    or (at your option) any later version. | ||||
|  | ||||
|    This library is distributed in the hope that it will be useful, | ||||
|    but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|    Lesser General Public License for more details. | ||||
|    | ||||
|    You should have received a copy of the GNU Lesser General Public | ||||
|    License along with this library; if not, write to the Free Software | ||||
|    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA | ||||
|  | ||||
| */ | ||||
|  | ||||
| /* define constants used throughout the library */ | ||||
| #define MAXLOG 1e7  /* Define infinity */ | ||||
|  | ||||
| /* function itob() | ||||
|  | ||||
|   Description: Converts an integer symbol into a vector of bits | ||||
|  | ||||
| 	Output parameters: | ||||
| 		binvec_p: The binary vector | ||||
| 		 | ||||
|     Input parameters: | ||||
| 	    symbol:  The integer-valued symbol | ||||
| 		length:  The length of the binary vector | ||||
| 	 | ||||
|   This function is used by conv_encode()  */ | ||||
|  | ||||
| void itob( | ||||
| 						int	binvec_p[], | ||||
| 						int symbol, | ||||
| 						int length ) | ||||
| { | ||||
| 	int counter; | ||||
|  | ||||
| 	/* Go through each bit in the vector */ | ||||
| 	for (counter=0;counter<length;counter++) { | ||||
| 		binvec_p[length-counter-1] = (symbol&1); | ||||
| 		symbol = symbol>>1; | ||||
| 	} | ||||
|  | ||||
| 	return; | ||||
| } | ||||
|  | ||||
| /* function parity_counter() | ||||
|  | ||||
|   Description: Determines if a symbol has odd (1) or even (0) parity | ||||
|  | ||||
| 	Output parameters: | ||||
| 		(returned int): The symbol's parity = 1 for odd and 0 for even | ||||
| 		 | ||||
|     Input parameters: | ||||
| 	    symbol:  The integer-valued symbol | ||||
| 		length:  The highest bit position in the symbol | ||||
| 	 | ||||
|   This function is used by nsc_enc_bit(), rsc_enc_bit(), and rsc_tail()  */ | ||||
|  | ||||
| int parity_counter( int symbol, int length ) | ||||
| { | ||||
| 	int counter; | ||||
| 	int temp_parity = 0; | ||||
|  | ||||
| 	for (counter=0;counter<length;counter++) { | ||||
| 		temp_parity = temp_parity^(symbol&1); | ||||
| 		symbol = symbol>>1; | ||||
| 	} | ||||
|  | ||||
| 	return( temp_parity ); | ||||
| } | ||||
|  | ||||
|  | ||||
| /* Function nsc_enc_bit()  | ||||
|  | ||||
|   Description: Convolutionally encodes a single bit using a rate 1/n encoder. | ||||
|   Takes in one input bit at a time, and produces a n-bit output. | ||||
|    | ||||
| 	Input parameters: | ||||
| 		input		The input data bit (i.e. a 0 or 1). | ||||
| 		state_in	The starting state of the encoder (an int from 0 to 2^m-1). | ||||
| 		g[]			An n-element vector containing the code generators in binary form. | ||||
| 		KK			The constraint length of the convolutional code. | ||||
|  | ||||
| 	Output parameters: | ||||
| 		output_p[]		An n-element vector containing the encoded bits. | ||||
| 		state_out_p[]	An integer containing the final state of the encoder	 | ||||
| 						(i.e. the state after encoding this bit) | ||||
| 	 | ||||
|   This function is used by rsc_encode(), nsc_transit(), rsc_transit(), and nsc_transit() */ | ||||
|  | ||||
| static int nsc_enc_bit( | ||||
| 				   int	state_out_p[], | ||||
| 				   int	input, | ||||
| 				   int	state_in,  | ||||
| 				   int  g[], | ||||
| 				   int  KK, | ||||
| 				   int  nn ) | ||||
| { | ||||
| 	/* declare variables */ | ||||
| 	int state, i; | ||||
| 	int out = 0;	 | ||||
|  | ||||
| 	/* create a word made up of state and new input */ | ||||
| 	state = (input<<(KK-1))^state_in; | ||||
| 	 | ||||
| 	/* AND the word with the generators */ | ||||
| 	for (i=0;i<nn;i++) | ||||
|     {		 | ||||
| 		/* update output symbol */ | ||||
| 		out = (out<<1) + parity_counter( state&g[i], KK ); 		 | ||||
|     } | ||||
| 	 | ||||
| 	/* shift the state to make the new state */ | ||||
| 	state_out_p[0] = state>>1; 	 | ||||
| 	return(out); | ||||
| } | ||||
|  | ||||
| /* like nsc_enc_bit() but for a RSC code */ | ||||
| static int rsc_enc_bit( | ||||
| 				   int	state_out_p[], | ||||
| 				   int	input, | ||||
| 				   int	state_in,  | ||||
| 				   int  g[], | ||||
| 				   int  KK, | ||||
| 				   int  nn ) | ||||
| { | ||||
| 	/* declare variables */ | ||||
| 	int state, i, out, a_k;	 | ||||
|  | ||||
| 	/* systematic output */ | ||||
| 	out = input; | ||||
|  | ||||
| 	/* determine feedback bit */ | ||||
| 	a_k = input^parity_counter( g[0]&state_in, KK ); | ||||
|  | ||||
| 	/* create a word made up of state and feedback bit */ | ||||
| 	state = (a_k<<(KK-1))^state_in; | ||||
|  | ||||
| 	/* AND the word with the generators */ | ||||
| 	for (i=1;i<nn;i++) | ||||
|     {		 | ||||
| 		/* update output symbol */ | ||||
| 		out = (out<<1) + parity_counter( state&g[i], KK ); 		 | ||||
|     } | ||||
| 	 | ||||
| 	/* shift the state to make the new state */ | ||||
| 	state_out_p[0] = state>>1; 	 | ||||
| 	return(out); | ||||
| } | ||||
|  | ||||
| /* function that creates the transit and output vectors */ | ||||
| static void nsc_transit( | ||||
| 						int		output_p[], | ||||
| 						int		trans_p[], | ||||
| 						int		input, | ||||
| 						int     g[], | ||||
| 						int     KK, | ||||
| 						int     nn ) | ||||
| { | ||||
| 	int nextstate[1]; | ||||
| 	int state, states; | ||||
| 	states = (1<<(KK-1));  /* The number of states: 2^mm */ | ||||
|  | ||||
| 	/* Determine the output and next state for each possible starting state */ | ||||
| 	for(state=0;state<states;state++) { | ||||
| 		output_p[state]  = nsc_enc_bit( nextstate, input, state, g, KK, nn );  | ||||
| 		trans_p[state]  = nextstate[0]; | ||||
| 	} | ||||
| 	return; | ||||
| } | ||||
|  | ||||
| /* Function rsc_transit() | ||||
|  | ||||
|   Description: Calculates the "transition matrix" for the trellis. | ||||
|   This information tells the decoder what the next state and output bits | ||||
|   will be given the current state and input bit. | ||||
|  | ||||
| 	Input parameters: | ||||
| 		input		Either 0 or 1 --- the input data bit. | ||||
| 		g[]			A two element vector containing the code generators. | ||||
| 		KK			The constraint length of the convolutional code. | ||||
|  | ||||
| 	Output parameters: | ||||
| 		output_p[]	A vector of length max_states = 2^(KK-1) containing | ||||
| 		            the output symbols. | ||||
| 		trans_p[]   A vector of length max_states that tells the decoder | ||||
| 					what the next state will be given the input and current state. | ||||
| 	 | ||||
|   This function is used by turbo_decode()   */ | ||||
|  | ||||
| static void rsc_transit( | ||||
| 						int	output_p[], | ||||
| 						int trans_p[], | ||||
| 						int	input, | ||||
| 						int g[], | ||||
| 						int KK, | ||||
| 						int nn ) | ||||
| { | ||||
| 	int nextstate[1]; | ||||
| 	int state, states;  | ||||
|  | ||||
| 	states = 1 << (KK-1); /* The number of states: 2^mm */ | ||||
|  | ||||
| 	/* Determine the output and next state for each possible starting state */ | ||||
| 	for(state=0;state<states;state++) { | ||||
| 		output_p[state] = rsc_enc_bit( nextstate, input, state, g, KK, nn );  | ||||
| 		trans_p[state]  = nextstate[0]; | ||||
| 	}	 | ||||
| 	return; | ||||
| } | ||||
|  | ||||
| /* determine the tail for a RSC code */ | ||||
| static void rsc_tail( | ||||
| 						int	tail_p[], | ||||
| 						int g[], | ||||
| 						int max_states, | ||||
| 						int mm ) | ||||
| { | ||||
| 	int state; | ||||
|  | ||||
| 	/* Determine the tail for each state */ | ||||
| 	for(state=0;state<max_states;state++) {		 | ||||
| 		/* determine feedback word */ | ||||
| 		tail_p[state] = parity_counter( g[0]&state, mm ); | ||||
| 	} | ||||
| 	return; | ||||
| } | ||||
|  | ||||
| /* perform convolutional encoding */ | ||||
| static void conv_encode( | ||||
| 	     int		output_p[], | ||||
| 	     int		input[], | ||||
| 		 int		out0[],  | ||||
| 		 int		state0[],  | ||||
| 		 int		out1[],  | ||||
| 		 int		state1[], | ||||
|          int		tail[],	  | ||||
|          int        KK, | ||||
|          int        LL, | ||||
| 		 int        nn ) | ||||
| { | ||||
|   int i, j, outsym; | ||||
|   int *bin_vec; | ||||
|   int state = 0; | ||||
|  | ||||
|   /* Negative value in "tail" is a flag that this is  | ||||
|   a tail-biting NSC code.  Determine initial state */ | ||||
|  | ||||
|   if ( tail[0] < 0 ) { | ||||
| 	  for (i=LL-KK+1;i<LL;i++) {   | ||||
| 		  if (input[i]) {			   | ||||
| 			  /* Determine next state */ | ||||
| 			  state = state1[state]; | ||||
| 		  } else {	   | ||||
| 			  /* Determine next state */ | ||||
| 			  state = state0[state]; | ||||
| 		  } | ||||
| 	  } | ||||
|   } | ||||
|  | ||||
|   bin_vec = (int*)calloc( nn, sizeof(int) ); | ||||
|  | ||||
|   /* encode data bits one bit at a time */ | ||||
|   for (i=0;i<LL;i++) {   | ||||
| 	  if (input[i]) { | ||||
| 		  /* Input is a one */ | ||||
| 		  outsym = out1[state];  /* The output symbol */ | ||||
| 		   | ||||
| 		  /* Determine next state */ | ||||
| 		  state = state1[state]; | ||||
| 	  } else { | ||||
| 		  /* Input is a zero */ | ||||
| 		  outsym = out0[state];  /* The output symbol */ | ||||
| 		   | ||||
| 		  /* Determine next state */ | ||||
| 		  state = state0[state]; | ||||
| 	  } | ||||
|  | ||||
| 	  /* Convert symbol to a binary vector	*/ | ||||
| 	  itob( bin_vec, outsym, nn ); | ||||
| 		   | ||||
| 	  /* Assign to output */ | ||||
| 	  for (j=0;j<nn;j++) | ||||
| 		  output_p[nn*i+j] = bin_vec[j]; | ||||
|   } | ||||
|  | ||||
|   /* encode tail if needed */ | ||||
|   if (tail[0] >= 0) { | ||||
| 	  for (i=LL;i<LL+KK-1;i++) { | ||||
| 		  if (tail[state]) { | ||||
| 			  /* Input is a one */ | ||||
| 			  outsym = out1[state];  /* The output symbol */ | ||||
| 			   | ||||
| 			  /* Determine next state */ | ||||
| 			  state = state1[state]; | ||||
| 		  } else { | ||||
| 			  /* Input is a zero */ | ||||
| 			  outsym = out0[state];  /* The output symbol */ | ||||
| 			   | ||||
| 			  /* Determine next state */ | ||||
| 			  state = state0[state]; | ||||
| 		  } | ||||
| 		   | ||||
| 		  /* Convert symbol to a binary vector	*/ | ||||
| 		  itob( bin_vec, outsym, nn ); | ||||
| 		   | ||||
| 		  /* Assign to output */ | ||||
| 		  for (j=0;j<nn;j++) | ||||
| 			  output_p[nn*i+j] = bin_vec[j]; | ||||
| 	  } | ||||
|   } | ||||
|  | ||||
|   free(bin_vec); | ||||
|  | ||||
|   return; | ||||
| } | ||||
|  | ||||
|  | ||||
| /* function Gamma() | ||||
|    | ||||
| 	Description: Computes the branch metric used for decoding. | ||||
|  | ||||
| 	Output parameters: | ||||
| 		(returned float) 	The metric between the hypothetical symbol and the recevieved vector | ||||
| 	 | ||||
| 	Input parameters: | ||||
| 		rec_array			The received vector, of length nn | ||||
| 		symbol				The hypothetical symbol | ||||
| 		nn					The length of the received vector | ||||
| 	 | ||||
|   This function is used by siso()  */ | ||||
|  | ||||
|  | ||||
| static float Gamma(float  rec_array[], | ||||
| 				   int    symbol, | ||||
| 				   int    nn ) | ||||
| { | ||||
| 	float rm = 0; | ||||
| 	int i; | ||||
| 	int mask; | ||||
| 	 | ||||
| 	mask = 1; | ||||
| 	for (i=0;i<nn;i++) { | ||||
| 		if (symbol&mask) | ||||
| 			rm += rec_array[nn-i-1]; | ||||
| 		mask = mask<<1; | ||||
| 	}  | ||||
| 	 | ||||
| 	return(rm); | ||||
| }  | ||||
|  | ||||
|  | ||||
| /* Function Viterbi() | ||||
|  | ||||
|   Description: Uses the Viterbi algorithm to perform hard-decision decoding of a convolutional code. | ||||
|  | ||||
| 	Input parameters: | ||||
| 		out0[]		The output bits for each state if input is a 0 (generated by rsc_transit). | ||||
| 		state0[]	The next state if input is a 0 (generated by rsc_transit). | ||||
| 		out1[]		The output bits for each state if input is a 1 (generated by rsc_transit). | ||||
| 		state1[]	The next state if input is a 1 (generated by rsc_transit). | ||||
| 		r[]			The received signal in LLR-form. For BPSK, must be in form r = 2*a*y/(sigma^2). | ||||
| 		KK			The constraint length of the convolutional code. | ||||
| 		LL			The number of data bits. | ||||
|  | ||||
| 	Output parameters: | ||||
| 		output_u_int[]		Hard decisions on the data bits | ||||
| 	 | ||||
| */ | ||||
|  | ||||
| static void Viterbi( | ||||
| 				int    output_u_int[], | ||||
| 				int    out0[],  | ||||
| 				int    state0[],  | ||||
| 				int    out1[],  | ||||
| 				int    state1[], | ||||
| 				double  input_c[], | ||||
| 				int    KK, | ||||
| 				int    nn, | ||||
| 				int    LL | ||||
| 				) | ||||
| { | ||||
| 	int i, t, state, mm, states; | ||||
| 	int number_symbols; | ||||
| 	float metric; | ||||
| 	float *prev_section, *next_section; | ||||
| 	int *prev_bit; | ||||
| 	int *prev_state; | ||||
| 	float *metric_c;	/* Set of all possible branch metrics */ | ||||
| 	float *rec_array;   /* Received values for one trellis section */ | ||||
| 	float max_val; | ||||
| 	 | ||||
| 	/* some derived constants */ | ||||
| 	mm = KK-1; | ||||
| 	states = 1 << mm;			/* 2^mm */ | ||||
| 	number_symbols = 1 << nn;	    /* 2^nn */ | ||||
| 	 | ||||
| 	/* dynamically allocate memory */  | ||||
| 	prev_section = (float*)calloc( states, sizeof(float) ); | ||||
| 	next_section = (float*)calloc( states, sizeof(float) ); | ||||
| 	prev_bit = (int*)calloc( states*(LL+mm), sizeof(int) ); | ||||
| 	prev_state = (int*)calloc( states*(LL+mm), sizeof(int) ); | ||||
| 	rec_array = (float*)calloc( nn, sizeof(float) ); | ||||
| 	metric_c = (float*)calloc( number_symbols, sizeof(float) ); | ||||
| 	 | ||||
| 	/* initialize trellis */ | ||||
| 	for (state=0;state<states;state++) { | ||||
| 		prev_section[state] = -MAXLOG;  | ||||
| 		next_section[state] = -MAXLOG; | ||||
| 	} | ||||
| 	prev_section[0] = 0; /* start in all-zeros state */ | ||||
| 	 | ||||
| 	/* go through trellis */ | ||||
| 	for (t=0;t<LL+mm;t++) { | ||||
| 		for (i=0;i<nn;i++) | ||||
| 			rec_array[i] = (float)input_c[nn*t+i]; | ||||
| 		 | ||||
| 		/* precompute all possible branch metrics */ | ||||
| 		for (i=0;i<number_symbols;i++) | ||||
| 			metric_c[i] = Gamma( rec_array, i, nn );  | ||||
| 		 | ||||
| 		/* step through all states */ | ||||
| 		for (state=0;state<states;state++) { | ||||
| 			 | ||||
| 			/* hypothesis: info bit is a zero */ | ||||
| 			metric = prev_section[state] + metric_c[ out0[ state ] ]; | ||||
| 			 | ||||
| 			/* store new metric if more than metric in storage */ | ||||
| 			if ( metric > next_section[state0[state]] ) { | ||||
| 				next_section[state0[state]] = metric; | ||||
| 				prev_state[t*states+state0[state]] = state; | ||||
| 				prev_bit[t*states+state0[state]] = 0; | ||||
| 			} | ||||
| 			 | ||||
| 			/* hypothesis: info bit is a one */ | ||||
| 			metric = prev_section[state] + metric_c[ out1[ state ] ]; | ||||
| 			 | ||||
| 			/* store new metric if more than metric in storage */ | ||||
| 			if ( metric > next_section[state1[state]] ) { | ||||
| 				next_section[state1[state]] = metric; | ||||
| 				prev_state[t*states+state1[state]] = state; | ||||
| 				prev_bit[t*states+state1[state]] = 1; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		/* normalize */ | ||||
| 		max_val = 0; | ||||
| 		for (state=0;state<states;state++) { | ||||
| 			if (next_section[state]>max_val){ | ||||
| 				max_val = next_section[state]; | ||||
| 			} | ||||
| 		} | ||||
| 		for (state=0;state<states;state++) { | ||||
| 			prev_section[state] = next_section[state] - max_val; | ||||
| 			next_section[state] = -MAXLOG; | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	/* trace-back operation */ | ||||
| 	state = 0; | ||||
|  | ||||
| 	/* tail, no need to output */ | ||||
| 	for (t=LL+mm-1; t>=LL; t--) { | ||||
| 		state = prev_state[t*states+state]; | ||||
| 	} | ||||
|  | ||||
| 	for (t=LL-1; t>=0; t--) {		 | ||||
| 		output_u_int[t] = prev_bit[t*states+state]; | ||||
| 		state = prev_state[t*states+state]; | ||||
| 	} | ||||
| 	 | ||||
| 	/* free the dynamically allocated memory */ | ||||
| 	free(prev_section); | ||||
| 	free(next_section); | ||||
| 	free(prev_bit); | ||||
| 	free(prev_state); | ||||
| 	free(rec_array); | ||||
| 	free(metric_c);  | ||||
| 	 | ||||
| } | ||||
|  | ||||
| /* Function ViterbiTb() | ||||
|  | ||||
|   Description: Uses the Viterbi algorithm to perform hard-decision decoding of a tail-biting convolutional code. | ||||
|  | ||||
| 	Input parameters: | ||||
| 		out0[]		The output bits for each state if input is a 0 (generated by rsc_transit). | ||||
| 		state0[]	The next state if input is a 0 (generated by rsc_transit). | ||||
| 		out1[]		The output bits for each state if input is a 1 (generated by rsc_transit). | ||||
| 		state1[]	The next state if input is a 1 (generated by rsc_transit). | ||||
| 		r[]			The received signal in LLR-form. For BPSK, must be in form r = 2*a*y/(sigma^2). | ||||
| 		KK			The constraint length of the convolutional code. | ||||
| 		LL			The number of data bits. | ||||
| 		depth		head and tail decoding length [Ref. W. Sung, Electronics Letters, vol. 36, no. 7] | ||||
|  | ||||
| 	Output parameters: | ||||
| 		output_u_int[]		Hard decisions on the data bits | ||||
|    | ||||
| */ | ||||
|  | ||||
|  | ||||
| static void ViterbiTb( | ||||
| 				int    output_u_int[], | ||||
| 				int    out0[],  | ||||
| 				int    state0[],  | ||||
| 				int    out1[],  | ||||
| 				int    state1[], | ||||
| 				double  input_c[], | ||||
| 				int    KK, | ||||
| 				int    nn, | ||||
| 				int    LL, | ||||
| 				int	   depth | ||||
| 				) | ||||
| { | ||||
| 	int i, t, state, mm, states, max_state; | ||||
| 	int number_symbols, starting_bit; | ||||
| 	float metric; | ||||
| 	float *prev_section, *next_section; | ||||
| 	int *prev_bit; | ||||
| 	int *prev_state; | ||||
| 	float *metric_c;	/* Set of all possible branch metrics */ | ||||
| 	float *rec_array;   /* Received values for one trellis section */ | ||||
| 	float max_val; | ||||
| 	 | ||||
| 	/* some derived constants */ | ||||
| 	mm = KK-1; | ||||
| 	states = 1 << mm;			/* 2^mm */ | ||||
| 	number_symbols = 1 << nn;	    /* 2^nn */ | ||||
| 	 | ||||
| 	/* dynamically allocate memory */  | ||||
| 	prev_section = (float*)calloc( states, sizeof(float) ); | ||||
| 	next_section = (float*)calloc( states, sizeof(float) ); | ||||
| 	prev_bit = (int*)calloc( states*(LL+depth), sizeof(int) ); | ||||
| 	prev_state = (int*)calloc( states*(LL+depth), sizeof(int) ); | ||||
| 	rec_array = (float*)calloc( nn, sizeof(float) ); | ||||
| 	metric_c = (float*)calloc( number_symbols, sizeof(float) ); | ||||
| 	 | ||||
| 	/* initialize trellis */ | ||||
| 	for (state=0;state<states;state++) { | ||||
| 		prev_section[state] = 0; /* equally likely starting state */ | ||||
| 		next_section[state] = -MAXLOG; | ||||
| 	} | ||||
| 	 | ||||
| 	/* go through trellis */ | ||||
| 	for (t=-depth;t<LL+depth;t++) { | ||||
| 		/* determine the corresponding data bits */ | ||||
| 		starting_bit = nn*(t%LL); | ||||
| 		if (starting_bit < 0 ) | ||||
| 			starting_bit = nn*LL + starting_bit; | ||||
| 		 | ||||
| 		/* printf( "start at %d\n", starting_bit ); */ | ||||
| 		for (i=0;i<nn;i++) { | ||||
| 			rec_array[i] = (float)input_c[starting_bit+i]; | ||||
| 			/* printf( "%1f\n", rec_array[i] ); */ | ||||
| 		} | ||||
|  | ||||
| 		/* precompute all possible branch metrics */ | ||||
| 		for (i=0;i<number_symbols;i++) | ||||
| 			metric_c[i] = Gamma( rec_array, i, nn );  | ||||
| 		 | ||||
| 		/* step through all states */ | ||||
| 		for (state=0;state<states;state++) { | ||||
| 			 | ||||
| 			/* hypothesis: info bit is a zero */ | ||||
| 			metric = prev_section[state] + metric_c[ out0[ state ] ]; | ||||
| 			 | ||||
| 			/* store new metric if more than metric in storage */ | ||||
| 			if ( metric > next_section[state0[state]] ) { | ||||
| 				next_section[state0[state]] = metric; | ||||
| 				if (t>=0) {				 | ||||
| 					prev_state[t*states+state0[state]] = state; | ||||
| 					prev_bit[t*states+state0[state]] = 0; | ||||
| 				} | ||||
| 			} | ||||
| 			 | ||||
| 			/* hypothesis: info bit is a one */ | ||||
| 			metric = prev_section[state] + metric_c[ out1[ state ] ]; | ||||
| 			 | ||||
| 			/* store new metric if more than metric in storage */ | ||||
| 			if ( metric > next_section[state1[state]] ) { | ||||
| 				next_section[state1[state]] = metric; | ||||
| 				if (t>=0) {				 | ||||
| 					prev_state[t*states+state1[state]] = state;				 | ||||
| 					prev_bit[t*states+state1[state]] = 1; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		 | ||||
| 		/* normalize */ | ||||
| 		max_val = 0; | ||||
| 		for (state=0;state<states;state++) { | ||||
| 			if (next_section[state]>max_val){ | ||||
| 				max_val = next_section[state]; | ||||
| 				max_state = state; | ||||
| 			} | ||||
| 		} | ||||
| 		for (state=0;state<states;state++) { | ||||
| 			prev_section[state] = next_section[state] - max_val; | ||||
| 			next_section[state] = -MAXLOG; | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	/* trace-back operation */ | ||||
| 	state = max_state; | ||||
|  | ||||
| 	/* tail, no need to output */ | ||||
| 	for (t=LL+depth-1; t>=LL; t--) { | ||||
| 		state = prev_state[t*states+state]; | ||||
| 	} | ||||
|  | ||||
| 	for (t=LL-1; t>=0; t--) {		 | ||||
| 		output_u_int[t] = prev_bit[t*states+state]; | ||||
| 		state = prev_state[t*states+state]; | ||||
| 	} | ||||
| 	 | ||||
| 	/* free the dynamically allocated memory */ | ||||
| 	free(prev_section); | ||||
| 	free(next_section); | ||||
| 	free(prev_bit); | ||||
| 	free(prev_state); | ||||
| 	free(rec_array); | ||||
| 	free(metric_c);  | ||||
| 	 | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 Javier Arribas
					Javier Arribas