⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 receiver.c

📁 此文件用于仿真MIMO-STBC 系统性能程序
💻 C
字号:

#include "STBC_includ.h"

void generate_trellis()
{
   int i;
   int state_bin[K_BIT], input_bin[K_BIT];
   int conv_bit[N_BIT], map_sig[N_SIG];

   /* the trellis will represented by input and output signals, 
      input signals decide the output signals for group 1 and the next state
      current states decide the output signals for group 2
   */
   for (i = 0; i < NUM_INPUT_DEC; i++) 
   {        
      memset(input_bin, 0, sizeof(int) * K_BIT);
      memset(conv_bit, 0, sizeof(int) * N_BIT);
      memset(map_sig, 0, sizeof(int) * N_SIG);

      /* i is the decimal number of input bits, it decides the output signals of group 1*/    
      de_to_bi(i, input_bin, K_BIT);
      /* get the block code by multiplying generator matrix 1*/
      mtxmtx(input_bin, s_p_context->gen_matrix_1, conv_bit, 1, K_BIT, N_BIT, M_2);
      /* get the natural map*/
      mtxmtx(conv_bit, s_p_context->map_matrix, map_sig, 1, N_BIT, N_SIG, M_8);

      s_p_context->output_signal_1[i][0].real = cos(M_2PI / s_p_context->psk_1 * map_sig [0]); 
      s_p_context->output_signal_1[i][0].imag = sin(M_2PI / s_p_context->psk_1 * map_sig [0]);
      s_p_context->output_signal_1[i][1].real = cos(M_2PI / s_p_context->psk_1 * map_sig [1]); 
      s_p_context->output_signal_1[i][1].imag = sin(M_2PI / s_p_context->psk_1 * map_sig [1]);

   } /* end of j for loop */   

   for (i = 0; i < NUM_STATES_DEC; i++) 
   {        
      memset(state_bin, 0, sizeof(int) * K_BIT);
      memset(conv_bit, 0, sizeof(int) * N_BIT);
      memset(map_sig, 0, sizeof(int) * N_SIG);

      /* i is the decimal number of states, it decides the output signals of group 2*/    
      de_to_bi(i, state_bin, K_BIT);
      /* get the block code by multiplying generator matrix 1*/
      mtxmtx(state_bin, s_p_context->gen_matrix_2, conv_bit, 1, K_BIT, N_BIT, M_2);
      /* get the natural map*/
      mtxmtx(conv_bit, s_p_context->map_matrix, map_sig, 1, N_BIT, N_SIG, M_8);

      s_p_context->output_signal_2[i][0].real = cos(M_2PI / s_p_context->psk_1 * map_sig [0]); 
      s_p_context->output_signal_2[i][0].imag = sin(M_2PI / s_p_context->psk_1 * map_sig [0]);
      s_p_context->output_signal_2[i][1].real = cos(M_2PI / s_p_context->psk_1 * map_sig [1]); 
      s_p_context->output_signal_2[i][1].imag = sin(M_2PI / s_p_context->psk_1 * map_sig [1]);

   }   
}

void  get_receive_signal_sequence(double es_ovr_n0, t_COMPLEX *path_gain, t_COMPLEX output_signals[][NUM_TX],  t_COMPLEX *receive_signals)
{
   int i,j;
   t_COMPLEX rec_sig_temp, noise;
   
   for (i = 0; i < 2*NUM_SIGS_PER_FRAME; i++)
   { 

      receive_signals[i].real = 0;
      receive_signals[i].imag = 0;

      for (j = 0; j < NUM_TX; j++)
      {
         rec_sig_temp = complextimes(output_signals[i][j], path_gain[j]);
	      receive_signals[i].real += rec_sig_temp.real;
	      receive_signals[i].imag += rec_sig_temp.imag;
      }

      noise =  Cgaussian(&random_seed);
      //noise.real = 0;
      //noise.imag = 0;
      /*r=sqrt(Es/(n0*NT)HX+N*/
	   receive_signals[i].real = sqrt(es_ovr_n0 ) * receive_signals[i].real + noise.real;
	   receive_signals[i].imag = sqrt(es_ovr_n0 ) * receive_signals[i].imag + noise.imag;
   }
}

void  viterbi_decode(double es_ovr_n0, t_COMPLEX *path_gain, t_COMPLEX *receive_signals, int *estimate_binary_sequence)
{
   long int t;
   int i,j,l,k;
   int state_sequence[NUM_SIGS_PER_FRAME];        /* input sequence list */   
   t_COMPLEX transmit_block[2][NUM_TX];      /* STBC block*/           
   t_COMPLEX receive_block[2];               /* receive block, 2 symbols each*/           
   t_COMPLEX branch_metric_temp_1, branch_metric_temp_2;   
   double branch_metric, x;
   int step, h, est_count; /* misc variables */ 

   est_count = 0;
   for (t = 0; t < NUM_SIGS_PER_FRAME -1; t++)
   {
      if (flag == 0)           
      {/* assume starting with zeroes, so just compute paths from all-zeroes state,
         the memory of UM is 1, exhaustive calculation will start from next step
        */  
         step = NUM_STATES_DEC;        
         flag = 1;
      }
      else            
         step = 1;        
      
      /* the 2 receive signals, for STBC block calculate every two symbols*/
      receive_block[0].real = receive_signals[2 * t].real;
      receive_block[0].imag = receive_signals[2 * t].imag;
      receive_block[1].real = receive_signals[2 * t + 1].real;
      receive_block[1].imag = receive_signals[2 * t + 1].imag;

      /* repeat for each possible state */        
      for (i = 0; i < NUM_STATES_DEC; i+= step) 
      {            
         /* compute branch metric per 2 channel symbol, 
      and sum for all   channel symbols in the convolutional encoder output n-tuple */ 
         transmit_block[0][2].real = s_p_context->output_signal_2[i][0].real;
         transmit_block[0][2].imag = s_p_context->output_signal_2[i][0].imag;
         transmit_block[0][3].real = s_p_context->output_signal_2[i][1].real;
         transmit_block[0][3].imag = s_p_context->output_signal_2[i][1].imag;
         transmit_block[1][2].real = -s_p_context->output_signal_2[i][1].real;
         transmit_block[1][2].imag = s_p_context->output_signal_2[i][1].imag;
         transmit_block[1][3].real = s_p_context->output_signal_2[i][0].real;
         transmit_block[1][3].imag = -s_p_context->output_signal_2[i][0].imag;
         /* repeat for each possible convolutional encoder output N-tuple */
         for (j = 0; j < NUM_INPUT_DEC; j++) 
         {               
            branch_metric = 0;               
            transmit_block[0][0].real = s_p_context->output_signal_1[j][0].real;
            transmit_block[0][0].imag = s_p_context->output_signal_1[j][0].imag;
            transmit_block[0][1].real = s_p_context->output_signal_1[j][1].real;
            transmit_block[0][1].imag = s_p_context->output_signal_1[j][1].imag;
            transmit_block[1][0].real = -s_p_context->output_signal_1[j][1].real;
            transmit_block[1][0].imag = s_p_context->output_signal_1[j][1].imag;
            transmit_block[1][1].real = s_p_context->output_signal_1[j][0].real;
            transmit_block[1][1].imag = -s_p_context->output_signal_1[j][0].imag;
            
            /* calculate the branch metric, |r1-(h1*s1+...)|^2 + |r2-(h1*s1^*+...)|^2 minimum */
            for (l = 0; l < 2; l++)
            {
               branch_metric_temp_1.real = 0;
               branch_metric_temp_1.imag = 0;
               for (k = 0; k < NUM_TX; k++)
               {
                  branch_metric_temp_2 = complextimes(transmit_block[l][k], path_gain[k]);
	               branch_metric_temp_1.real += branch_metric_temp_2.real;
	               branch_metric_temp_1.imag += branch_metric_temp_2.imag;
               }
               branch_metric_temp_1.real = receive_block[l].real - sqrt(es_ovr_n0) * branch_metric_temp_1.real;
               branch_metric_temp_1.imag = receive_block[l].imag - sqrt(es_ovr_n0) * branch_metric_temp_1.imag;

               branch_metric += complex_dist(branch_metric_temp_1);
            }


/* now choose the surviving path--the one with the smaller accumlated error metric... */                
            if (s_p_context->accum_err_metric[j][1] > s_p_context->accum_err_metric[i][0] + branch_metric )
            {
               /* save an accumulated metric value for the survivor state */                               
               s_p_context->accum_err_metric[j] [1] = s_p_context->accum_err_metric[i][0] +  branch_metric;          
               /* update the state_history array with the state number of the survivor 
               */                    
               s_p_context->state_history[j] [t+1] = i;            
            } /* end of if-statement */           
         } /* end of 'j' for-loop */        
      } /* end of 'i' for-loop -- we have now updated the trellis */      
      /* for all rows of accum_err_metric, move col 2 to col 1 and flag col 2 */       
      for (j = 0; j < NUM_STATES_DEC; j++) 
      {           
         if (s_p_context->accum_err_metric[j][1] != MAXINT)
            s_p_context->accum_err_metric[j][0] = s_p_context->accum_err_metric[j][1];            
         s_p_context->accum_err_metric[j][1] = MAXINT;        
      } /* end of 'j' for-loop */          
   }

   /* last 2 received signals*/
   receive_block[0].real = receive_signals[2 * t].real;
   receive_block[0].imag = receive_signals[2 * t].imag;
   receive_block[1].real = receive_signals[2 * t + 1].real;
   receive_block[1].imag = receive_signals[2 * t + 1].imag;

   /* deal with the last block and convert the state back to zero*/
   /* input is all zero*/

   transmit_block[0][0].real = s_p_context->output_signal_1[0][0].real;
   transmit_block[0][0].imag = s_p_context->output_signal_1[0][0].imag;
   transmit_block[0][1].real = s_p_context->output_signal_1[0][1].real;
   transmit_block[0][1].imag = s_p_context->output_signal_1[0][1].imag;
   transmit_block[1][0].real = -s_p_context->output_signal_1[0][1].real;
   transmit_block[1][0].imag = s_p_context->output_signal_1[0][1].imag;
   transmit_block[1][1].real = s_p_context->output_signal_1[0][0].real;
   transmit_block[1][1].imag = -s_p_context->output_signal_1[0][0].imag;

   for (i = 0; i < NUM_STATES_DEC; i++) 
   {            
      branch_metric = 0;               
      
      transmit_block[0][2].real = s_p_context->output_signal_2[i][0].real;
      transmit_block[0][2].imag = s_p_context->output_signal_2[i][0].imag;
      transmit_block[0][3].real = s_p_context->output_signal_2[i][1].real;
      transmit_block[0][3].imag = s_p_context->output_signal_2[i][1].imag;
      transmit_block[1][2].real = -s_p_context->output_signal_2[i][1].real;
      transmit_block[1][2].imag = s_p_context->output_signal_2[i][1].imag;
      transmit_block[1][3].real = s_p_context->output_signal_2[i][0].real;
      transmit_block[1][3].imag = -s_p_context->output_signal_2[i][0].imag;
   /* repeat for each possible convolutional encoder output N-tuple */

      
      /* calculate the branch metric, |r1-(h1*s1+...)|^2 + |r2-(h1*s1^*+...)|^2 minimum */
      for (l = 0; l < 2; l++)
      {
         branch_metric_temp_1.real = 0;
         branch_metric_temp_1.imag = 0;
         for (k = 0; k < NUM_TX; k++)
         {
            branch_metric_temp_2 = complextimes(transmit_block[l][k], path_gain[k]);
	         branch_metric_temp_1.real += branch_metric_temp_2.real;
	         branch_metric_temp_1.imag += branch_metric_temp_2.imag;
         }
         branch_metric_temp_1.real = receive_block[l].real - sqrt(es_ovr_n0) * branch_metric_temp_1.real;
         branch_metric_temp_1.imag = receive_block[l].imag - sqrt(es_ovr_n0) * branch_metric_temp_1.imag;

         branch_metric += complex_dist(branch_metric_temp_1);
      }


/* now choose the surviving path--the one with the smaller accumlated error metric... */                
      if (s_p_context->accum_err_metric[0][1] > s_p_context->accum_err_metric[i][0] + branch_metric )
      {
         /* save an accumulated metric value for the survivor state */                               
         s_p_context->accum_err_metric[0] [1] = s_p_context->accum_err_metric[i][0] +  branch_metric;          
         /* update the state_history array with the state number of the survivor 
         */                    
         s_p_context->state_history[0] [t+1] = i;            
      } /* end of if-statement */           
   } /* end of 'i' for-loop */ 
   
   x = s_p_context->accum_err_metric[0][1];                    
   h = 0;                

   memset(state_sequence, 0, sizeof(int)* (NUM_SIGS_PER_FRAME+1));

   /* now pick the starting point for traceback */ 
   /* the key point is that the state is the previous input sequence*/
   state_sequence[NUM_SIGS_PER_FRAME] = h;             
   /* now work backwards from the end of the trellis to the oldest state 
   in the trellis to determine the optimal path. The purpose of this 
   is to determine the most likely state sequence at the encoder                
   based on what channel symbols we received. */            
   for (j = NUM_SIGS_PER_FRAME; j > 0; j--)
      state_sequence[j - 1] = s_p_context->state_history[state_sequence[j]] [j];

   for (i = 1; i < NUM_SIGS_PER_FRAME; i++)        
   {
      de_to_bi(state_sequence[i], &estimate_binary_sequence[est_count * K_BIT], K_BIT);
      est_count ++;
   }
} /* end of depth of trellis*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -