module: ofdm_detector
description: received symbols are first mapped to a qam symbol 
           (in min-distance sense) and then to corresponding grey-encoded bits
parameters: int num_channels
inputs: IntVector vec_bit_settings, Vector vec_dqam_i, Vector vec_dqam_q, 
        double clk_frame 
outputs: IntVector vec_bits, Vector vec_demod_i, Vector vec_demod_q
static_variables: 
       double d_min, double data_val_i, double data_val_q, 
       double demod_i, double demod_q, 
       int code_val_i, int code_val_q, int code_val, int num_bits
classes: EdgeDetect clk_frame_edge()
set_output_vector_lengths:
   vec_bits=num_channels
   vec_demod_i=num_channels
   vec_demod_q=num_channels
init:
   if (vec_bit_settings.get_length() != num_channels)
      {
       printf("error in 'ofdm_detector':  length of vec_bit_settings (= %d)\n",
            vec_bit_settings.get_length());
       printf("   is not equal to num_channels (= %d)\n",num_channels);
       exit(1);
      }
   if (vec_dqam_i.get_length() != num_channels)
      {
       printf("error in 'ofdm_detector':  length of vec_dqam_i (= %d)\n",
            vec_dqam_i.get_length());
       printf("   is not equal to num_channels (= %d)\n",num_channels);
       exit(1);
      }
   if (vec_dqam_q.get_length() != num_channels)
      {
       printf("error in 'ofdm_detector':  length of vec_dqam_q (= %d)\n",
            vec_dqam_q.get_length());
       printf("   is not equal to num_channels (= %d)\n",num_channels);
       exit(1);
      }
code:
int i;
if (clk_frame_edge.inp(clk_frame))
    {
    for (i = 0; i < num_channels; i++)
        {
        num_bits = vec_bit_settings.get_elem(i);
        if (num_bits == 1)
        {
          vec_demod_q.set_elem(i,0);
          if (vec_dqam_i.get_elem(i) >= 0)  
            {
            vec_demod_i.set_elem(i, sqrt(2.0));
            vec_bits.set_elem(i, 0);
            }
          else 
            {
            vec_demod_i.set_elem(i, -sqrt(2.0));  
            vec_bits.set_elem(i, 1);
            }
        }
        else 
        {
        if (num_bits % 2 != 0)
        {
        printf("error in 'ofdm_detector':  num_bits must be even!\n");
        printf("  in this case, num_bits = %d\n",num_bits);
        exit(1);
        }
        data_val_i = vec_dqam_i.get_elem(i);
        data_val_q = vec_dqam_q.get_elem(i);
        if (num_bits == 0)
            d_min = 0.0;
        else if (num_bits == 2)
            d_min = 2.0;
        else if (num_bits == 4)
            d_min = 0.6667;    //2/3
        else if (num_bits == 6)
            d_min = 0.2857;    //2/7
        else if (num_bits == 8)
            d_min = 0.1333;    //2/15
        else 
           {
            printf("error in 'ofdm_detector': num_bits != 0,2,4,6,8 is not supported\n");
            printf(" in this case, num_bits = %d\n", num_bits);
            exit(1);
            }    
        demod_i = ofdm_demodulator(num_bits/2, data_val_i,d_min);
        demod_q = ofdm_demodulator(num_bits/2, data_val_q,d_min);
        vec_demod_i.set_elem(i, demod_i);
        vec_demod_q.set_elem(i, demod_q);
        code_val_i = ofdm_grey_decoder(num_bits/2,demod_i);
        code_val_q = ofdm_grey_decoder(num_bits/2,demod_q);
        code_val = ofdm_i_q_bits(num_bits/2,code_val_i,code_val_q); 
        vec_bits.set_elem(i,code_val);
        }
        }        
    }    
functions:
int ofdm_grey_decoder(int num_bits, double in_val)
{
int code_val;
if (num_bits == 0)
    code_val = 0;
else if (num_bits == 1)
    {
    if (in_val == 1.0)
        code_val = 0;
    else if (in_val == -1.0) 
        code_val = 1;
    else
        {
        printf("error in 'ofdm_grey_decoder': in_val is not mapped correctly\n");
        printf("    in this case, in_val = %d, num_bits = %d\n", in_val,num_bits);
        exit(1);
        }
    }        
else if (num_bits == 2)
    {
    if (in_val == 3.0)
        code_val = 0;
    else if (in_val == 1.0)
        code_val = 1;
    else if (in_val == -3.0)
        code_val = 2;
    else if (in_val == -1.0)
        code_val = 3;
    else
        {
        printf("error in 'ofdm_grey_decoder': in_val is not mapped correctly\n");
        printf("    in this case, in_val = %d, num_bits = %d\n", in_val,num_bits);
        exit(1);
        }
    }
else if (num_bits == 3)
    {
    if (in_val == 7.0)
        code_val  = 0;
    else if (in_val == 5.0)
        code_val = 1;
    else if (in_val == 1.0)
        code_val = 2;
    else if (in_val == 3.0)
        code_val = 3;
    else if (in_val == -7.0)
        code_val = 4;
    else if (in_val == -5.0)
        code_val = 5;
    else if (in_val == -1.0)
        code_val = 6;
    else if (in_val == -3.0)
        code_val = 7;
    else
        {
        printf("error in 'ofdm_grey_decoder': in_val is not mapped correctly\n");
        printf("    in this case, in_val = %d, num_bits = %d\n", in_val,num_bits);
        exit(1);
        }
    }
else if (num_bits == 4)
    {
    if (in_val == 15.0)
        code_val = 0;
    else if (in_val == 13.0)
        code_val = 1;
    else if (in_val == 9.0)
        code_val = 2;
    else if (in_val == 11.0)
        code_val = 3;
    else if (in_val == 1.0)
        code_val = 4;
    else if (in_val == 3.0)
        code_val = 5;
    else if (in_val == 7.0)
        code_val = 6;
    else if (in_val == 5.0)
        code_val = 7;
    else if (in_val == -15.0)
        code_val = 8;
    else if (in_val == -13.0)
        code_val = 9;
    else if (in_val == -9.0)
        code_val = 10;
    else if (in_val == -11.0)
        code_val = 11;
    else if (in_val == -1.0)
        code_val = 12;
    else if (in_val == -3.0)
        code_val = 13;
    else if (in_val == -7.0)
        code_val = 14;
    else if (in_val == -5.0)
        code_val = 15;    
    else
        {
        printf("error in 'ofdm_grey_decoder': in_val is not mapped correctly\n");
        printf("    in this case, in_val = %d, num_bits = %d\n", in_val,num_bits);
        exit(1);
        }
    }
else 
    {
    printf("error in 'ofdm_grey_decoder': num_bits > 4 is not supported\n");
    printf(" in this case, num_bits = %d\n", num_bits);
    exit(1);
    }
return(code_val);
}
double ofdm_demodulator(int num_bits, double in_val, double d_min)
{
double out;
in_val *= 2.0/d_min;
if (num_bits == 0)
    out = 0.0;
else if (num_bits == 1)
    {
    if (in_val >= 0.0)    
        out = 1.0;
    else        
        out = -1.0;
    }
else if (num_bits == 2)
    {
    if (in_val >= 2.0)
        out = 3.0;
    else if (in_val < 2.0 && in_val >= 0.0)
        out = 1.0;
    else if (in_val < 0.0 && in_val >= -2.0) 
        out = -1.0;
    else    
        out = -3.0;
    }
else if (num_bits == 3)
    {
    if (in_val >= 6.0)
        out = 7.0;
    else if (in_val < 6.0 && in_val >= 4.0)
        out = 5.0;
    else if (in_val < 4.0 && in_val >= 2.0)
        out = 3.0;
    else if (in_val < 2.0 && in_val >= 0.0)
        out = 1.0;
    else if (in_val < 0.0 && in_val >= -2.0)
        out = -1.0;
    else if (in_val < -2.0 && in_val >= -4.0)
        out = -3.0;
    else if (in_val < -4.0 && in_val >= -6.0)
        out = -5.0;
    else
        out = -7.0;
    }
else if (num_bits == 4)
    {
    if (in_val >= 14.0)
        out = 15.0;
    else if (in_val < 14.0 && in_val >= 12.0)
        out = 13.0;
    else if (in_val < 12.0 && in_val >= 10.0)
        out = 11.0;
    else if (in_val < 10.0 && in_val >= 8.0)
        out = 9.0;
    else if (in_val < 8.0 && in_val >= 6.0)
        out = 7.0;
    else if (in_val < 6.0 && in_val >= 4.0)
        out = 5.0;
    else if (in_val < 4.0 && in_val >= 2.0)
        out = 3.0;
    else if (in_val < 2.0 && in_val >= 0.0)
        out = 1.0;
    else if (in_val < 0.0 && in_val >= -2.0)
        out = -1.0;
    else if (in_val < -2.0 && in_val >= -4.0)
        out = -3.0;
    else if (in_val < -4.0 && in_val >= -6.0)
        out = -5.0;
    else if (in_val < -6.0 && in_val >= -8.0)    
        out = -7.0;
    else if (in_val < -8.0 && in_val >= -10.0)
        out = -9.0;
    else if (in_val < -10.0 && in_val >= -12.0)
        out = -11.0;
    else if (in_val < -12.0 && in_val >= -14.0)
        out = -13.0;
    else 
        out = -15.0;
    }
else
   {
     printf("error in 'ofdm_demodulator':  num_bits > 4 is not supported\n");
     printf("   in this case, num_bits = %d\n",num_bits);
     exit(1);
   }
return(out);
}
int ofdm_i_q_bits(int num_bits, int in_i, int in_q)
{
int mask_lsb, mask_nlsb, out_lsb, out_nlsb, out;
mask_lsb = (1 << num_bits) - 1;
mask_nlsb = mask_lsb << num_bits;
out_lsb = in_i & mask_lsb;
out_nlsb = (in_q << num_bits)&mask_nlsb;
out = out_nlsb + out_lsb;
return(out);
}
