Search code examples
cmatlabembeddedsimulinktelecommunication

Translating matlab's AGC function to C


I am trying to translate the Automatic Gain Control block from Matlab's communications toolbox. Here is the documentation but the relevant parts are summarized below:

The block diagram

Block Diagram

Where

enter image description here

enter image description here

And

enter image description here

This is the code I've written:

double AGC_Detector(int N, float complex* input, int ndx)
{
   double samp = 0;
   for(int i = ndx*N; i < (ndx+1)*(N-1); i++)
   {
       samp += cabs(input[i])*cabs(input[i]);
   }
   samp = samp/N;
   return samp;
}

void use_AGC(float complex* input, 
             float complex* output, 
             double step, 
             double desired_pwr, 
             int avrg_len, 
             int max_pwr, 
             int len)
{
   double z = 0;
   double e = 0;
   double g = 0;
   double prev_g = 0;
   double dtctr = 0;

   for(int i = 0; i < len; i++)
   {
       dtctr = AGC_Detector(avrg_len,input,i);
       z = dtctr * exp(2*prev_g);
       e = desired_pwr - log(z);
       g = prev_g + step*e;
       if(g > max_pwr)
       {
           g = max_pwr;
       }
       prev_g = g;
       output[i] = input[i] * exp(prev_g);
   }
}

But I am not getting the same output I get for the same values in Matlab. What am I doing wrong?

Thank You!


Solution

  • I figured it out. Code below gives same output as matlab for a given set of complex data.

    double AGC_Detector(double complex input, double* sum, double state[], unsigned int* idx, int N)
    {
        unsigned int first;
        unsigned int nth;
        double output;
        double val = cabs(input)*cabs(input);
        *sum += val;
        output = (*sum)*(1.0/N);
        *sum -= state[*idx-1];
    
        if(*sum < 0.0){*sum = 0.0;}
    
        state[*idx-1] = val;
        first = *idx;
        nth = first + 1;
    
        if(nth < first){nth = 0xFFFFFFFF;}
    
        *idx = nth;
    
        if(*idx > N-1){*idx = 1;}
    
        return output;
    }
    
    
    void use_AGC(double complex* input, double complex* output, double step, double desired_pwr, int avrg_len, int max_pwr, int len)
    {
        unsigned int idx = 1;
        int filt_len = avrg_len-1;
        double K = step;
        double g = 0;
        double sum = 0;
        double dtctr = 0;
        double filterState[filt_len];
    
        for(int i = 0; i < filt_len; i++){filterState[i] = 0;}
    
        for(int i = 0; i < avrg_len; i++)
        {
            dtctr = AGC_Detector(input[i], &sum, filterState, &idx, avrg_len);
            output[i] = input[i] * exp(g);
            dtctr = log(dtctr);
            g += K*(desired_pwr - (dtctr + 2.0*g));
            if(g > max_pwr){g = max_pwr;}
        }
    }