# The GMSK demodulation

**URL:** <https://www.ruby-forum.com/t/the-gmsk-demodulation/239482>\
**Category:** GNU Radio\
**Created:** [February 28, 2014, 3:32pm UTC](https://www.ruby-forum.com/t/the-gmsk-demodulation/239482 "2014-02-28T15:32:54Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![musicdenotation](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/ea666f/32.png) [@musicdenotation](https://www.ruby-forum.com/u/musicdenotation)\
**Post date:** [February 28, 2014, 3:32pm UTC](https://www.ruby-forum.com/t/the-gmsk-demodulation/239482/1 "2014-02-28T15:32:54Z")

</div>

Hi,

As I have known, GSM uses GMSK modulation which BT = 0.3 and it  
uses Viterbi algorithm for demodulation. And I took a look at the code  
of  
GMSK demod code in GNU Radio, it use quadrature\_demod but not Viterbi as  
demodulation method. So which one is better in doing demodulating GMSK?

Moreover, GSM uses Viterbi algorithm to decode the convolution encoding.  
Would it be possible to use quadrature\_demod to demodulate GSM signal  
instead of Viterbi? What about the convolution decoding part (maybe by  
some  
other method)?

Cheers,  
Zhenhua

---

<div class="post-metadata">

**Author:** ![zhenhua\_han](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/z/d2c977/32.png) [@zhenhua\_han](https://www.ruby-forum.com/u/zhenhua_han)\
**Post date:** [February 28, 2014, 3:42pm UTC](https://www.ruby-forum.com/t/the-gmsk-demodulation/239482/2 "2014-02-28T15:42:19Z")

</div>

> other method)?

I think you are mixing up the modulation and coding components.

At the transmitter, you first code (convolutional code), and then you  
modulate (GMSK).

At the receiver, you first demodulate (quadrature demodulate) and then  
you  
decode (Viterbi).

Coding takes a stream of bits and converts it to another stream of bits.  
Modulation refers to the process of converting the post-coded bits into  
“symbols” that you will then send over-the-air.

best,  
aditya

---

<div class="post-metadata">

**Author:** ![zhenhua\_han](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/z/d2c977/32.png) [@zhenhua\_han](https://www.ruby-forum.com/u/zhenhua_han)\
**Post date:** [February 28, 2014, 4:05pm UTC](https://www.ruby-forum.com/t/the-gmsk-demodulation/239482/3 "2014-02-28T16:05:17Z")

</div>

What confused me is the Viterbi algorithm. I saw it can be used to  
demodulate GMSK in more than one place (such as here:  
[http://www.mathworks.cn/cn/help/comm/ref/comm.gmskdemodulatorclass.html](http://www.mathworks.cn/cn/help/comm/ref/comm.gmskdemodulatorclass.html)  
)

I think it’s better for me to read some materials of Viterbi and find  
out  
what really it is.

Cheers  
Zhenhua  
2014-2-28 10:40 “Aditya D.” [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)д

---

<div class="post-metadata">

**Author:** ![zhenhua\_han](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/z/d2c977/32.png) [@zhenhua\_han](https://www.ruby-forum.com/u/zhenhua_han)\
**Post date:** [February 28, 2014, 4:13pm UTC](https://www.ruby-forum.com/t/the-gmsk-demodulation/239482/4 "2014-02-28T16:13:31Z")

</div>

Hi Zhenhua,  
as Aditya pointed out: Viterby is /not/ a demodulator.  
You should read something on digital communication that explains the  
difference between channel coding and modulation, then everything will  
be clearer to you.

Greetings,  
Marcus

---

<div class="post-metadata">

**Author:** ![zhenhua\_han](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/z/d2c977/32.png) [@zhenhua\_han](https://www.ruby-forum.com/u/zhenhua_han)\
**Post date:** [February 28, 2014, 4:32pm UTC](https://www.ruby-forum.com/t/the-gmsk-demodulation/239482/5 "2014-02-28T16:32:22Z")

</div>

Also as a side note, you can’t demod GSM and then slice it. You have  
to demod it burst by burst so that you can lock to the training  
sequence of each. So the demod block of GR is pretty much useless  
here.

airprobe has a viterbi demod (which is probably one of the few good  
part of airprobe to re-use).

Cheers,

```
Sylvain
```

---

<div class="post-metadata">

**Author:** ![zhenhua\_han](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/z/d2c977/32.png) [@zhenhua\_han](https://www.ruby-forum.com/u/zhenhua_han)\
**Post date:** [February 28, 2014, 4:29pm UTC](https://www.ruby-forum.com/t/the-gmsk-demodulation/239482/6 "2014-02-28T16:29:25Z")

</div>

On Fri, Feb 28, 2014 at 10:12 AM, Marcus M. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> 2014-2-28 10:40 “Aditya D.” [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) д
> 
> > > other method)?  
> > > Coding takes a stream of bits and converts it to another stream of bits.  
> > > Modulation refers to the process of converting the post-coded bits into  
> > > “symbols” that you will then send over-the-air.
> > 
> > best,  
> > aditya

Actually, guys…

> **[HPRC-GMSK-Demod.pdf](https://www.ittc.ku.edu/~prescott/kcp/HPRC-GMSK-Demod.pdf)**
>
> 863.36 KB

You can demodulate GMSK using the Viterbi algorithm.

Zhenhua,

We don’t implement this method in our GMSK demodulator, though I have  
wanted to see someone do it. The Viterbi is the maximum likelihood  
detector for GMSK, but it’s more complicated to implement. The  
quadrature method we use is simple and intuitive but suboptimal.

Tom

---

<div class="post-metadata">

**Author:** ![zhenhua\_han](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/z/d2c977/32.png) [@zhenhua\_han](https://www.ruby-forum.com/u/zhenhua_han)\
**Post date:** [February 28, 2014, 5:53pm UTC](https://www.ruby-forum.com/t/the-gmsk-demodulation/239482/7 "2014-02-28T17:53:34Z")

</div>

I’m working on a generalized CPM demod based on Achilleas’s previous  
work  
in gr-trellis/src/examples/test\_cpm.py, and I have it more or less  
working  
although there are plenty of little bugs to work out. Since the Viterbi  
part was more or less worked out for me, synchronization is the hard  
part;  
my application isn’t GSM, and I’d like the solution in Gnuradio to be  
applicable to a wide range of systems – this means closed-loop timing  
and  
freq synchronization instead of just doing data-aided estimates from the  
preamble. I’ve implemented a timing synchronizer based on the D’andrea,  
Mengali, Reggiannini paper following MATLAB’s example, and I’m using an  
adaptation of the correlate\_and\_sync block to synchronize to (G)MSK  
preambles.

Don’t know when I’ll have it ready to release (i.e. when the code isn’t  
an  
embarrassment to look at) but it’s Working In The Lab ™. It also  
takes  
quite a bit of setup to apply to each use case.

If you don’t need those extra few dB, it’s a whole heck of a lot simpler  
both in implementation complexity and CPU cycles to just stick with the  
existing noncoherent GMSK block. When I release code I’ll also release  
an  
updated noncoherent GMSK receiver block which uses the new timing  
estimator, as the primary weakness of the existing GMSK block is timing  
recovery.

–n

---

<div class="post-metadata">

**Author:** ![zhenhua\_han](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/z/d2c977/32.png) [@zhenhua\_han](https://www.ruby-forum.com/u/zhenhua_han)\
**Post date:** [February 28, 2014, 6:31pm UTC](https://www.ruby-forum.com/t/the-gmsk-demodulation/239482/8 "2014-02-28T18:31:13Z")

</div>

Nick,

Are you going to release the non-coherent timing recovery improvement as  
a  
separate block too (not baked into a GMSK hier block)? Thanks!

Very Respectfully,

Dan CaJacob

---

<div class="post-metadata">

**Author:** ![zhenhua\_han](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/z/d2c977/32.png) [@zhenhua\_han](https://www.ruby-forum.com/u/zhenhua_han)\
**Post date:** [February 28, 2014, 7:23pm UTC](https://www.ruby-forum.com/t/the-gmsk-demodulation/239482/9 "2014-02-28T19:23:00Z")

</div>

On Fri, Feb 28, 2014 at 11:51 AM, Nick F. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> I’m working on a generalized CPM demod based on Achilleas’s previous work in  
> gr-trellis/src/examples/test\_cpm.py, and I have it more or less working  
> although there are plenty of little bugs to work out. Since the Viterbi part  
> was more or less worked out for me, synchronization is the hard part; my  
> application isn’t GSM, and I’d like the solution in Gnuradio to be  
> applicable to a wide range of systems – this means closed-loop timing and  
> freq synchronization instead of just doing data-aided estimates from the  
> preamble.

I don’t have much to add, but Nick and Sylvain touched on the largest  
difference between the Gnuradio GMSK demod and GSM/TDMA type burst  
processing - and it’s not the Viterbi. The use of synchronization  
loops (or lack thereof) in the demod is really the separating factor.

-TT

---

<div class="post-metadata">

**Author:** ![zhenhua\_han](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/z/d2c977/32.png) [@zhenhua\_han](https://www.ruby-forum.com/u/zhenhua_han)\
**Post date:** [February 28, 2014, 6:31pm UTC](https://www.ruby-forum.com/t/the-gmsk-demodulation/239482/10 "2014-02-28T18:31:49Z")

</div>

It’s already a separate block, so yes.

---

<div class="post-metadata">

**Author:** ![zhenhua\_han](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/z/d2c977/32.png) [@zhenhua\_han](https://www.ruby-forum.com/u/zhenhua_han)\
**Post date:** [February 28, 2014, 8:27pm UTC](https://www.ruby-forum.com/t/the-gmsk-demodulation/239482/11 "2014-02-28T20:27:45Z")

</div>

On Fri, Feb 28, 2014 at 1:54 PM, Nick F. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> the loop gain pretty low and still acquire quickly. This is what Tom (R) is  
> doing with the correlate\_and\_sync and polyphase\_clock\_sync blocks, and it’s  
> what I’m doing in my MSK timing recovery block, although I’m still dealing  
> with a bug in that estimate. If you want to rely strictly on the timing  
> phase estimate of the preamble as in GMSK’s case you could just turn the  
> loop gain of your favorite timing sync block to zero and let it act as a  
> naive (and inefficient) decimator.

I wasn’t implying that a combined method couldn’t be done. But for  
GSM, the assumption is that frequency sync is acquired separately  
(with embedded tones), timing is derived from frequency, and Doppler  
effects restricted (i.e. high speed train is not a supported use  
case). Add in short durations before/after mid-amble and the benefits  
of closed-loop timing begin to diminish.

Of course, these assumptions from GSM specification don’t extend to  
the generalized case and collapse when we handle continuous signals.  
That was really the only point I was trying to make.

-TT

---

<div class="post-metadata">

**Author:** ![zhenhua\_han](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/z/d2c977/32.png) [@zhenhua\_han](https://www.ruby-forum.com/u/zhenhua_han)\
**Post date:** [February 28, 2014, 7:56pm UTC](https://www.ruby-forum.com/t/the-gmsk-demodulation/239482/12 "2014-02-28T19:56:34Z")

</div>

On Fri, Feb 28, 2014 at 10:21 AM, Tom T. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> and
> 
> > freq synchronization instead of just doing data-aided estimates from the  
> > preamble.
> 
> I don’t have much to add, but Nick and Sylvain touched on the largest  
> difference between the Gnuradio GMSK demod and GSM/TDMA type burst  
> processing - and it’s not the Viterbi. The use of synchronization  
> loops (or lack thereof) in the demod is really the separating factor.

Sample tagging in GR makes it easier to have it both ways in this case.  
If  
you have a correlator block that outputs timing phase estimates based on  
the preamble (or whatever), this should be used to initialize a  
closed-loop  
timing recovery block’s phase. For bursty transmissions this lets you  
keep  
the loop gain pretty low and still acquire quickly. This is what Tom (R)  
is  
doing with the correlate\_and\_sync and polyphase\_clock\_sync blocks, and  
it’s  
what I’m doing in my MSK timing recovery block, although I’m still  
dealing  
with a bug in that estimate. If you want to rely strictly on the timing  
phase estimate of the preamble as in GMSK’s case you could just turn the  
loop gain of your favorite timing sync block to zero and let it act as a  
naive (and inefficient) decimator.

–n

---

<div class="post-metadata">

**Author:** ![zhenhua\_han](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/z/d2c977/32.png) [@zhenhua\_han](https://www.ruby-forum.com/u/zhenhua_han)\
**Post date:** [March 3, 2014, 6:44pm UTC](https://www.ruby-forum.com/t/the-gmsk-demodulation/239482/13 "2014-03-03T18:44:44Z")

</div>

W dniu 28.02.2014 15:31, zhenhua han pisze:

> GSM signal instead of Viterbi? What about the convolution decoding  
> part (maybe by some other method)?
> 
> Cheers,  
> Zhenhua
> 
> * * *
> 
> Discuss-gnuradio mailing list  
> [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
> [Discuss-gnuradio Info Page](https://lists.gnu.org/mailman/listinfo/discuss-gnuradio)  
> Hello all,

Regarding usage of viterbi algorithm for maximum likelihood sequence  
estimation in GSM - you may look at and try gsm-receiver that I once  
submitted to airprobe. I’ve prepared version where I thrown out all of  
decoding stuff and left only synchronization, channel estimation and  
detection of bits with viterbi algorithm. It’s available for download in  
here:

> **[GitHub - ptrkrysik/gr-gsm: Gnuradio blocks and tools for receiving GSM...](https://github.com/ptrkrysik/gr-gsm)**
>
> Gnuradio blocks and tools for receiving GSM transmissions

It compiles with newest gnu-radio and it has gnuradio companion xml file  
as well. It can be easily connected to different sources in gnuradio  
(file, rtl-sdr, usrp) and it has a message sink where burst bits and  
gsmtap headers are sent. I’ve corrected some issues with synchronization  
and turned off frequency offset correction that introduced instability  
of the receiver. After compiling and installing you can start with  
examples.

–  
Best Regards,  
Piotr K.

---

<div class="post-metadata">

**Author:** ![zhenhua\_han](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/z/d2c977/32.png) [@zhenhua\_han](https://www.ruby-forum.com/u/zhenhua_han)\
**Post date:** [March 3, 2014, 6:37pm UTC](https://www.ruby-forum.com/t/the-gmsk-demodulation/239482/14 "2014-03-03T18:37:40Z")

</div>

W dniu 28.02.2014 15:31, zhenhua han pisze:

> GSM signal instead of Viterbi? What about the convolution decoding  
> part (maybe by some other method)?
> 
> Cheers,  
> Zhenhua
> 
> * * *
> 
> Discuss-gnuradio mailing list  
> [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
> [Discuss-gnuradio Info Page](https://lists.gnu.org/mailman/listinfo/discuss-gnuradio)  
> Hello all,

Regarding usage of viterbi algorithm for maximum likelihood sequence  
estimation in GSM - you may look at and try gsm-receiver that I once  
submitted to airprobe. I’ve prepared version where I thrown out all of  
decoding stuff and left only synchronization, channel estimation and  
detection of GMKS symbols with viterbi algorithm. It’s available for  
download in here:

> **[GitHub - ptrkrysik/gr-gsm: Gnuradio blocks and tools for receiving GSM...](https://github.com/ptrkrysik/gr-gsm)**
>
> Gnuradio blocks and tools for receiving GSM transmissions

It compiles with newest gnu-radio and it has gnuradio companion xml file  
as well. It can be easily connected to different sources in gnuradio  
(file, rtl-sdr, usrp). I’ve corrected some issues with synchronization  
and turned off frequency offset correction that introduced instability  
of the receiver. There are examples of in the “examples” directory.

P.S. If someone applied Achilleas’s implementation of viterbi algorithm  
from gnu-radio in GSM I’m very interested to see how it can be done.

–  
Best Regards,  
Piotr K.

---

<div class="post-metadata">

**Author:** ![zhenhua\_han](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/z/d2c977/32.png) [@zhenhua\_han](https://www.ruby-forum.com/u/zhenhua_han)\
**Post date:** [March 4, 2014, 2:30am UTC](https://www.ruby-forum.com/t/the-gmsk-demodulation/239482/15 "2014-03-04T02:30:03Z")

</div>

Hi Perper,

I took a look at your code, and I found this

//set\_frequency(d\_freq\_offset);

It seems you have turned off the the frequency offset correction as you  
said.  
Do you know the reason of the introduced instability by this part?

Best,  
Zhenhua

2014-03-04 1:42 GMT+08:00 Perper [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

---

<div class="post-metadata">

**Author:** ![zhenhua\_han](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/z/d2c977/32.png) [@zhenhua\_han](https://www.ruby-forum.com/u/zhenhua_han)\
**Post date:** [March 4, 2014, 2:33am UTC](https://www.ruby-forum.com/t/the-gmsk-demodulation/239482/16 "2014-03-04T02:33:35Z")

</div>

Hi guys,

I’m reading the code of Airprobe and I found this function.

double gsm\_receiver\_cf::compute\_freq\_offset(const gr\_complex \* input,  
unsigned first\_sample, unsigned last\_sample)  
{  
double phase\_sum = 0;  
unsigned ii;

for (ii = first\_sample; ii \< last\_sample; ii++) {  
double phase\_diff = compute\_phase\_diff(input[ii], input[ii-1]) -  
(M\_PI /  
2) / d\_OSR;  
phase\_sum += phase\_diff;  
}

double phase\_offset = phase\_sum / (last\_sample - first\_sample);  
double freq\_offset = phase\_offset \* 1625000.0 / (12.0 \* M\_PI);  
return freq\_offset;  
}

It calculates the frequency offset with “freq\_offset = phase\_offset \*  
1625000.0 / (12.0 \* M\_PI);” I guess the (1625000.0/12\*pi) equals  
(1625000/6)/(2pi) and 1625/6 kbit/s is the modulation rate of GSM.

So, what is the principle of this calculation? How to calculate the  
freq\_offset with phase\_offset. I tried some derivation but failed. Can  
anyone help me to find out the derivation ?

Best wishes,  
Zhenhua

2014-03-04 9:28 GMT+08:00 zhenhua han [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

---

<div class="post-metadata">

**Author:** ![zhenhua\_han](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/z/d2c977/32.png) [@zhenhua\_han](https://www.ruby-forum.com/u/zhenhua_han)\
**Post date:** [March 4, 2014, 2:37am UTC](https://www.ruby-forum.com/t/the-gmsk-demodulation/239482/17 "2014-03-04T02:37:42Z")

</div>

2014-03-04 9:32 GMT+08:00 zhenhua han [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> for (ii = first\_sample; ii \< last\_sample; ii++) {
> 
> Best wishes,  
> Zhenhua

BTW, this is a question I raised in my former email.(But no one  
replied…).  
Maybe, there is some relationship between the introduced instability  
and  
my question.

---

<div class="post-metadata">

**Author:** ![zhenhua\_han](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/z/d2c977/32.png) [@zhenhua\_han](https://www.ruby-forum.com/u/zhenhua_han)\
**Post date:** [March 4, 2014, 4:51am UTC](https://www.ruby-forum.com/t/the-gmsk-demodulation/239482/18 "2014-03-04T04:51:11Z")

</div>

OK, I’ve got it.  
Thank you for your help.

Cheers,  
Zhenhua

2014-03-04 10:28 GMT+08:00 Tom T. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

---

<div class="post-metadata">

**Author:** ![zhenhua\_han](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/z/d2c977/32.png) [@zhenhua\_han](https://www.ruby-forum.com/u/zhenhua_han)\
**Post date:** [March 4, 2014, 3:30am UTC](https://www.ruby-forum.com/t/the-gmsk-demodulation/239482/19 "2014-03-04T03:30:02Z")

</div>

On Mon, Mar 3, 2014 at 8:32 PM, zhenhua han [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> I’m reading the code of Airprobe and I found this function.
> 
> double gsm\_receiver\_cf::compute\_freq\_offset(const gr\_complex \* input,  
> unsigned first\_sample, unsigned last\_sample)

~

> It calculates the frequency offset with “freq\_offset = phase\_offset \*  
> 1625000.0 / (12.0 \* M\_PI);” I guess the (1625000.0/12\*pi) equals  
> (1625000/6)/(2pi) and 1625/6 kbit/s is the modulation rate of GSM.
> 
> So, what is the principle of this calculation? How to calculate the  
> freq\_offset with phase\_offset. I tried some derivation but failed. Can  
> anyone help me to find out the derivation ?

The offset is derived assuming the signal is a constant tone. The code  
is averaging the phase shift between subsequent samples in a burst.  
Frequency is the first derivative of phase with respect to time, so  
the phase shift multiplied by the sample rate will give you the  
frequency of the tone.

-TT

---

<div class="post-metadata">

**Author:** ![zhenhua\_han](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/z/d2c977/32.png) [@zhenhua\_han](https://www.ruby-forum.com/u/zhenhua_han)\
**Post date:** [March 4, 2014, 2:56pm UTC](https://www.ruby-forum.com/t/the-gmsk-demodulation/239482/20 "2014-03-04T14:56:43Z")

</div>

> Best,  
> Zhenhua  
> Hi Zhenhua,

The reason of instability is in the method of correction of the  
frequency offset.

The offset is computed inside of gsm-receiver gnuradio block and it is  
fed to a frequency shifting fir filter.

The connection of the blocks look like this:

```
         __freq. offset_____
        | |
        v |

```

xlating\_fir\_filter → gsm-receiver

There is lact of synchronization between computation of frequency offset  
and its correction inside of xlating\_fir\_filter. Synchronisation in this  
case is needed because the moment of computation of the estimate affects  
it.  
When new estimate of frequency correction is computed before previous is  
applied the connection with frequency offset becomes additive feedback  
loop.

This problem can be corrected by integration frequency correction inside  
of the gsm-receiver or with use of stream tags.

Generally I would like to split gr-gsm into smaller blocks that are  
easier to test but it will happen only if I find enough time for this.

P.S. for some reason I didn’t get your reply through my mailing list  
subscription (together with many more missing messages)…  
I’ve found it through the webpage  
[discuss-gnuradio Archives](http://lists.gnu.org/archive/html/discuss-gnuradio/) .

–  
Best Regards,  
Piotr K.

[Next page](https://www.ruby-forum.com/t/the-gmsk-demodulation/239482.md?page=2)
