Modems

The SDRVM comes with a series of modems sharing the common features.

These are :

Symbol rate

The symbol rate depends on two different factors :

  • The sample rate (noted R in the following),
  • The number of samples per symbol (noted k in the following).

Each symbol uses k samples transmitted at R samples per second. Hence the bit rate is : R/k.

When the modulateBits() method is called, it returns a IQData object where the sample rate is set to 0. You have to specify the sample rate to be used, depending on the symbol rate you want.

  • Example :

We want to generate a 2400 symbols/sec (bits/second in this case) GMSK signal.

  • We will use a sample rate of 48000 Hz,
  • We need to set the 'samples per symbol' value to 48000/2400=20
var samples_per_symbol = 20 ;
var sample_rate = 48e3 ;
var filter_delay = 3 ;
var bt = .35 ;

var txmodem = new GMSKModem('tx') ;

txmodem.configure({
    'sps' : samples_per_symbol,
    'delay' : filter_delay,
    'bt' : bt
});

var bitrate = sample_rate / samples_per_symbol ; 
print('GMSK params :');
print(' Sample rate:' + sample_rate + ' Hz');
print(' Speed : '  + bitrate + ' Bits per second.') ; 

Delay

Processing delay :

Modems embeds FIR filters. The output of the FIR filters is delayed by N-1, where N is the number of taps in the filter. When started, the FIR outputs N-2 zeros before the first valid sample is available.
When used as demodulators, converting the input IQ samples to symbols, this delay must be taken into account.

Consequence:

The following example shows what happens if we push the output of the modulator into a demodulator :

function printBits( x ) {
    var l=0 ;
    var m = '' ;
    while( l < x.length  ) {

         for( var b=0 ; (b<8) && (l<x.length) ; b++,l++) {
              if( x[l]>0 ) {
                  m = m + '1' ;
              } else {
                  m = m + '0' ;
              }
         }
         m = m + ' ' ;

    }
    print(m);
}

// Generate 16 bytes message
var L = 21*8 ;
var tx_bits = new Uint8Array(L) ;
for( var i=0 ; i < L ; i+=2 ) {
    tx_bits[i] = 1 ;
    tx_bits[i+1] = 0 ;
}

var samples_per_symbol = 50 ;
var sample_rate = 48e3 ;
var filter_delay = 3 ;
var bt = .35 ;

var txmodem = new GMSKModem('tx') ;
var rx_modem = new GMSKModem('rx');

txmodem.configure({
    'sps' : samples_per_symbol,
    'delay' : filter_delay,
    'bt' : bt
});
rx_modem.configure({
    'sps' : samples_per_symbol,
    'delay' : filter_delay,
    'bt' : bt
});


// modulate, demodulate to compare
var IQ = txmodem.modulateBits( tx_bits ) ;
IQ.setSampleRate(sample_rate);
var rx_bits = rx_modem.demodulate(IQ);

// print the output bits
printBits(tx_bits);
printBits(rx_bits);

This code will produce the following output :

(boot:0)> 10101010 10101010 10101010 10101010 ...
(boot:0)> 00010110 10101010 10101010 10101010 ...

One will note that the first ouput bits are different. This is the consequence of the FIR delay : A series of 0 is generated before the demodulator correctly decodes the input stream.

Last update: January 8, 2022