jgaeddert / liquid-dsp

digital signal processing library for software-defined radios
http://liquidsdr.org
MIT License
1.87k stars 439 forks source link

Demodulator output does not match with modulating signal #357

Closed Mas313 closed 5 months ago

Mas313 commented 6 months ago

Hi, When running GMSK example it is observed that GMSK demodulator output does not match with the modulating signal (symbol). It matches only rarely and after that again the output does not match. I have added print statements to print the input and output symbols. code is shown below

#include <liquid/liquid.h>

int main() {
    // options
    unsigned int k  =    10;    // filter samples/symbol
    unsigned int m  =     7;    // filter delay (symbols)
    float        BT = 0.25f;    // bandwidth-time product

    // create modulator/demodulator objects
    gmskmod mod   = gmskmod_create(k, m, BT);
    gmskdem demod = gmskdem_create(k, m, BT);

    unsigned int  i;
    unsigned int  sym_in;       // input data symbol
    float complex x[k];         // modulated samples
    unsigned int  sym_out;      // demodulated data symbol

 int n=0;
 while(n<6)
    {
        // generate random symbol {0,1}
        sym_in = rand() % 2;                        
        print("Input Symbol=%d\n",sym_in);
        // modulate
        gmskmod_modulate(mod, sym_in, x);

        // demodulate
        gmskdem_demodulate(demod, x, &sym_out);
        print("output Symbol=%d\n",sym_out);
    }

    // destroy modem objects
    gmskmod_destroy(mod);
    gmskdem_destroy(demod);
}

I get result as

Input Symbol=0
output Symbol=1
Input Symbol=0
output Symbol=1
Input Symbol=1
output Symbol=1
Input Symbol=1
output Symbol=0
Input Symbol=0
output Symbol=1
Input Symbol=0
output Symbol=1

Any idea what is the issue here. Thanks

jgaeddert commented 5 months ago

Great question! GMSK is a nonlinear modulation scheme (unlike e.g. BPSK which is linear). This means that the modulation is tied directly to the waveform, and in which case we need to account for the delay in its filters. Here's a quick modification on your example:

#include <liquid/liquid.h>

int main() {
    // options
    unsigned int k  =    10;    // filter samples/symbol
    unsigned int m  =     7;    // filter delay (symbols)
    float        BT = 0.25f;    // bandwidth-time product
    unsigned int  num_symbols = 30;

    // create modulator/demodulator objects
    gmskmod mod   = gmskmod_create(k, m, BT);
    gmskdem demod = gmskdem_create(k, m, BT);

    // derived values
    unsigned int  delay = 2 * m;    // total delay between mod and demod
    unsigned int  symbols_in[num_symbols];   // input data symbol
    unsigned int  symbols_out[num_symbols];   // input data symbol
    float complex buf[k];         // modulated samples

    // pre-generate symbols
    unsigned int i;
    for (i=0; i<num_symbols; i++)
        symbols_in[i] = rand() & 1;

    // run through modulator/demodulator
    for (i=0; i<num_symbols; i++)
    {
        // modulate symbol and store samples into buffer
        gmskmod_modulate(mod, symbols_in[i], buf);

        // demodulate
        gmskdem_demodulate(demod, buf, symbols_out+i);

        // print result *accounting for delay*
        printf("[%2u] out=%1u", i, symbols_out[i]);
        if (i >= delay)
            printf(" : in=%1u\n", symbols_in[i-delay]);
        else
            printf("\n");
    }

    // destroy modem objects
    gmskmod_destroy(mod);
    gmskdem_destroy(demod);
}

This produces the following result:

[ 0] out=0
[ 1] out=0
[ 2] out=0
[ 3] out=0
[ 4] out=0
[ 5] out=0
[ 6] out=0
[ 7] out=0
[ 8] out=1
[ 9] out=1
[10] out=1
[11] out=1
[12] out=0
[13] out=0
[14] out=1 : in=1
[15] out=1 : in=1
[16] out=1 : in=1
[17] out=0 : in=0
[18] out=0 : in=0
[19] out=0 : in=0
[20] out=0 : in=0
[21] out=0 : in=0
[22] out=1 : in=1
[23] out=1 : in=1
[24] out=0 : in=0
[25] out=1 : in=1
[26] out=0 : in=0
[27] out=0 : in=0
[28] out=1 : in=1
[29] out=1 : in=1

Notice that when you account for the total delay (in this case, m symbols from the modulator and another m symbols from the receiver), you get an output that perfectly matches the input