# Demodulating digital signal (FSK?) from audio

**URL:** <https://www.ruby-forum.com/t/demodulating-digital-signal-fsk-from-audio/230992>\
**Category:** GNU Radio\
**Created:** [July 16, 2014, 2:53pm UTC](https://www.ruby-forum.com/t/demodulating-digital-signal-fsk-from-audio/230992 "2014-07-16T14:53:08Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![addis\_a](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/c4cdca/32.png) [@addis\_a](https://www.ruby-forum.com/u/addis_a)\
**Post date:** [July 16, 2014, 2:53pm UTC](https://www.ruby-forum.com/t/demodulating-digital-signal-fsk-from-audio/230992/1 "2014-07-16T14:53:08Z")

</div>

Hello,

I would like to write an application that checks the battery status of  
wireless microphones. The battery status is transmitted as a very low  
frequency (below 10 Hz) signal that is mixed in the normal audio. I was  
able to filter the signal out of the demodulated audio and display it  
(see image). AFAIK this modulation is called FSK.  
The signal that is shown there should decode to data-blocks containing  
“11100000000” or something like that, are there any blocks in GnuRadio  
that can do that?  
Because the signal is derived from audio it is not complex but normal  
float, all GnuRadio demodulators seem to work only on complex data.  
Can somebody please help me?

Best regards,  
Stefan

---

<div class="post-metadata">

**Author:** ![Stefan\_O](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/a8b319/32.png) [@Stefan\_O](https://www.ruby-forum.com/u/Stefan_O)\
**Post date:** [July 16, 2014, 3:10pm UTC](https://www.ruby-forum.com/t/demodulating-digital-signal-fsk-from-audio/230992/2 "2014-07-16T15:10:18Z")

</div>

-----BEGIN PGP SIGNED MESSAGE-----  
Hash: SHA1

Hi Stefan,

this doesn’t look like FSK, because then the amplitude of the  
oscillations shouldn’t change (only their frequency).  
If I had to guess, it would be on-off-keying, and you could simply  
detect that by squaring the signal, and using the integrate block on  
that, with a integration length amounting to your symbol duration in  
samples, which might be a little hard to guess from the signal you  
posted, but maybe you know the symbol rate from elsewhere, or can  
determine it by comparing signals from different battery states?

Greetings,  
Marcus

On 16.07.2014 14:51, Stefan O. wrote:

> from audio it is not complex but normal float, all GnuRadio

-----BEGIN PGP SIGNATURE-----  
Version: GnuPG v1  
Comment: Using GnuPG with Thunderbird - [http://www.enigmail.net/](http://www.enigmail.net/)

iQEcBAEBAgAGBQJTxnlbAAoJEBQ6EdjyzlHtSbwIAL0FWUAahmlcfY9/axEdBnMN  
3IGTeiGempmKFNN6CVOO/mO+8oeHQjhxwDfxTobnWnViJ5borrpVcMCMW+e+25T0  
0s+ABX72mMiGp4IbMX6NAWJQFUZlrYJc3iiglFdSLM9AAKjtN9H4v6t67XVrM0Xo  
OH14TQH+pJzErvYivLmRNUEvp+wNYxjSJN8ZM/APBt0qX4jPAi4Kyl0FEsY1XmUb  
CuMS0XAkEenWR8vM/yomKOb5cMyaDUpzKI+8iS897lhIYTW/xhTZB3IFhGkSgyZp  
6JJ2IuJYEip1SBVVdeSlWDcqLCjAhDMgRhrXNh47hW0hzKnHQ5koitaICS9pLIg=  
=uuqu  
-----END PGP SIGNATURE-----

---

<div class="post-metadata">

**Author:** ![Stefan\_O](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/a8b319/32.png) [@Stefan\_O](https://www.ruby-forum.com/u/Stefan_O)\
**Post date:** [July 16, 2014, 3:20pm UTC](https://www.ruby-forum.com/t/demodulating-digital-signal-fsk-from-audio/230992/3 "2014-07-16T15:20:01Z")

</div>

On 07/16/2014 03:08 PM, Marcus M. wrote:

> this doesn’t look like FSK, because then the amplitude of the  
> oscillations shouldn’t change (only their frequency).  
> If I had to guess, it would be on-off-keying, and you could simply  
> detect that by squaring the signal, and using the integrate block on  
> that, with a integration length amounting to your symbol duration in  
> samples, which might be a little hard to guess from the signal you  
> posted, but maybe you know the symbol rate from elsewhere, or can  
> determine it by comparing signals from different battery states?

The dips might also be between bursts – it does look a bit like FSK,  
but hard to say.  
Stefan: If you mix this down to zero, your signal will be complex anyway  
(radio signals are also always real, but we don’t care 😃 ). Then you  
can put it into a quadrature\_demod\_cf.  
Question is, how do you synchronise? Maybe you can use those dips to do  
that… Or maybe the symbol timing is well defined, then it’s easier.

M

---

<div class="post-metadata">

**Author:** ![Stefan\_O](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/a8b319/32.png) [@Stefan\_O](https://www.ruby-forum.com/u/Stefan_O)\
**Post date:** [July 16, 2014, 3:45pm UTC](https://www.ruby-forum.com/t/demodulating-digital-signal-fsk-from-audio/230992/4 "2014-07-16T15:45:44Z")

</div>

Ahh-- my mistake, I was assuming the “dips” were something like one  
symbol, the other being the continous wave with the 400u amplitude, and  
completely missed the differences in period on the non-dippy signal…  
The lower halfwaves of the lower-frequency oscillations look a little  
strange; maybe this signal was generated by RC-lowpassing a PWM signal?

---

<div class="post-metadata">

**Author:** ![Stefan\_O](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/a8b319/32.png) [@Stefan\_O](https://www.ruby-forum.com/u/Stefan_O)\
**Post date:** [July 17, 2014, 1:07am UTC](https://www.ruby-forum.com/t/demodulating-digital-signal-fsk-from-audio/230992/5 "2014-07-17T01:07:00Z")

</div>

Thank you very much for the fast answers!  
The signal I attached in the last message is generated by a ??C and then  
a lowpass is applied (not just RC, but two op-amps). In another mic type  
the signal is generated by changing the reference frequency (a varicap  
controlled by the ??C is connected to the main crystal).

What exactly does mix to zero mean? From what I understood so far,  
I=RF_cos(??t) and Q=RF_sin(??t), when I set ??=0 =\> I=RF and Q=0 is that  
what you mean?

I changed the filter settings and now the dip between two blocks is more  
precise. I attached two signals generated by the different microphone  
types using the same protocol. I tried the quadrature\_demod, but result  
especially for the varicap-mic seems not be useful (also tried changing  
the only parameter).  
I think what I have to do is measure the distance between two peaks  
(only positive, threshold 200u):  
Distance more than 0,5s -\> New Block starts  
Distance between 0,3s and 0,4s -\> 1  
Distance between 0,15s and 0,25s -\> 0  
else -\> reset (delete buffer and wait for new block start)  
Can this be done with GnuRadio?

Best regards  
Stefan

Am 16.07.2014 15:43, schrieb Marcus M??ller:

---

<div class="post-metadata">

**Author:** ![Stefan\_O](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/a8b319/32.png) [@Stefan\_O](https://www.ruby-forum.com/u/Stefan_O)\
**Post date:** [July 18, 2014, 5:25am UTC](https://www.ruby-forum.com/t/demodulating-digital-signal-fsk-from-audio/230992/6 "2014-07-18T05:25:11Z")

</div>

Am 17.07.2014 10:04, schrieb Martin B.:

> No, that would still be a real signal. In your nomenclature, if ??=10Hz \*  
> 2\pi, then you get a complex signal (10 Hz being what you said was the  
> center frequency of the battery signal).

I think the center is 4 Hz, the signal is below 10 Hz

> > I changed the filter settings and now the dip between two blocks is more  
> > precise. I attached two signals generated by the different microphone  
> > types using the same protocol. I tried the quadrature\_demod, but result  
> > especially for the varicap-mic seems not be useful (also tried changing  
> > the only parameter).
> 
> To understand what’s going on, I recommend you generate an FSK signal in  
> GRC and then use quadrature\_demod and see what happens.

That??s a good idea, but I have a stupid question: How do I generate a  
FSK signal? There are lots of modulators available, but no FSK.

> > I think what I have to do is measure the distance between two peaks  
> > (only positive, threshold 200u):  
> > Distance more than 0,5s → New Block starts  
> > Distance between 0,3s and 0,4s → 1  
> > Distance between 0,15s and 0,25s → 0  
> > else → reset (delete buffer and wait for new block start)  
> > Can this be done with GnuRadio?
> 
> Hm, this sounds too much like guesswork. Do you have a spec sheet or  
> something describing the modulation in more detail?

No, it??s a proprietary protocol and I??m reverse-engineering it (I can  
actually read it when I look at the signal, what I have to do is make  
the software read it). All I have is circuit diagrams (service manuals)  
of microphones and receivers. There is no detailed description of the  
battery status signal (and of course no source of the ??C code), no more  
than it??s a low frequency signal in the range around 5 Hz with a  
nominal  
FM deviation of 2 kHz.

I was able to remove everything below 200u of the signal, convert it to  
complex and then quadrature\_demod generates something quite nice. Is  
that how the demodulated signal is supposed to look like? AFAIK it??s  
now  
pulse position modulation.  
But it??s still an “analog” signal, how can I make a real digital  
signal?

Best regards  
Stefan

---

<div class="post-metadata">

**Author:** ![Stefan\_O](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/a8b319/32.png) [@Stefan\_O](https://www.ruby-forum.com/u/Stefan_O)\
**Post date:** [July 17, 2014, 10:05am UTC](https://www.ruby-forum.com/t/demodulating-digital-signal-fsk-from-audio/230992/7 "2014-07-17T10:05:58Z")

</div>

On 07/17/2014 01:05 AM, Stefan O. wrote:

> Thank you very much for the fast answers!  
> The signal I attached in the last message is generated by a µC and then  
> a lowpass is applied (not just RC, but two op-amps). In another mic type  
> the signal is generated by changing the reference frequency (a varicap  
> controlled by the µC is connected to the main crystal).
> 
> What exactly does mix to zero mean? From what I understood so far,  
> I=RF_cos(ωt) and Q=RF_sin(ωt), when I set ω=0 =\> I=RF and Q=0 is that  
> what you mean?

No, that would still be a real signal. In your nomenclature, if ω=10Hz \*  
2\pi, then you get a complex signal (10 Hz being what you said was the  
center frequency of the battery signal).

> I changed the filter settings and now the dip between two blocks is more  
> precise. I attached two signals generated by the different microphone  
> types using the same protocol. I tried the quadrature\_demod, but result  
> especially for the varicap-mic seems not be useful (also tried changing  
> the only parameter).

To understand what’s going on, I recommend you generate an FSK signal in  
GRC and then use quadrature\_demod and see what happens.

> I think what I have to do is measure the distance between two peaks  
> (only positive, threshold 200u):  
> Distance more than 0,5s → New Block starts  
> Distance between 0,3s and 0,4s → 1  
> Distance between 0,15s and 0,25s → 0  
> else → reset (delete buffer and wait for new block start)  
> Can this be done with GnuRadio?

Hm, this sounds too much like guesswork. Do you have a spec sheet or  
something describing the modulation in more detail?

M

---

<div class="post-metadata">

**Author:** ![Stefan\_O](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/a8b319/32.png) [@Stefan\_O](https://www.ruby-forum.com/u/Stefan_O)\
**Post date:** [July 18, 2014, 11:09am UTC](https://www.ruby-forum.com/t/demodulating-digital-signal-fsk-from-audio/230992/8 "2014-07-18T11:09:07Z")

</div>

On 07/18/2014 05:23 AM, Stefan O. wrote:

> > > What exactly does mix to zero mean? From what I understood so far,  
> > > I=RF_cos(ωt) and Q=RF_sin(ωt), when I set ω=0 =\> I=RF and Q=0 is that  
> > > what you mean?
> > 
> > No, that would still be a real signal. In your nomenclature, if ω=10Hz \*  
> > 2\pi, then you get a complex signal (10 Hz being what you said was the  
> > center frequency of the battery signal).
> 
> I think the center is 4 Hz, the signal is below 10 Hz

Hint: You can dowconvert with an exp(j2\pi \omega t) instead of a sine  
and cosine, but it doesn’t really matter.  
But the more I think about it it’s probably not something you need  
complex math to demod, given the simplicity.

> FSK signal? There are lots of modulators available, but no FSK.  
> You can either drive a ‘Frequency Mod’ with discrete keys, or use the  
> ‘Continuous Phase Modulation’ block with appropriate settings.

> that how the demodulated signal is supposed to look like? AFAIK it´s now  
> pulse position modulation.  
> But it´s still an “analog” signal, how can I make a real digital signal?

The big issue is synchronisation. In general, for digital comms, you  
need to find the ‘right’ time to sample your signal, then make a  
decision based on your value. Finding the ‘right’ time is always the  
funky part of digital receivers. Here, there should be a simple rule, if  
this is supposed to be decoded by simple µCs.

M

---

<div class="post-metadata">

**Author:** ![Stefan\_O](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/a8b319/32.png) [@Stefan\_O](https://www.ruby-forum.com/u/Stefan_O)\
**Post date:** [July 18, 2014, 6:18pm UTC](https://www.ruby-forum.com/t/demodulating-digital-signal-fsk-from-audio/230992/9 "2014-07-18T18:18:42Z")

</div>

Am 18.07.2014 11:07, schrieb Martin B.:

> > > To understand what’s going on, I recommend you generate an FSK signal in  
> > > GRC and then use quadrature\_demod and see what happens.
> > 
> > That??s a good idea, but I have a stupid question: How do I generate a  
> > FSK signal? There are lots of modulators available, but no FSK.
> 
> You can either drive a ‘Frequency Mod’ with discrete keys, or use the  
> ‘Continuous Phase Modulation’ block with appropriate settings.

I did that (see pic) but I have no still have no idea what  
quadrature\_demod actually does, no matter how I change the parameters,  
that only affects amplitude of demodulated signal.

> > that how the demodulated signal is supposed to look like? AFAIK it??s now  
> > pulse position modulation.  
> > But it??s still an “analog” signal, how can I make a real digital signal?
> 
> The big issue is synchronisation. In general, for digital comms, you  
> need to find the ‘right’ time to sample your signal, then make a  
> decision based on your value. Finding the ‘right’ time is always the  
> funky part of digital receivers. Here, there should be a simple rule, if  
> this is supposed to be decoded by simple ??Cs.

I think decoding in ??C is done like I described: Measuring distances  
between peaks. There are 3 different ones, 0, 1 and new packet.  
I found out the result of quadrature\_demod is not that nice: The  
distance between the peaks is quite precise while the output of  
quadrature\_demod is not good in case the shape of the curve is not  
symmetrical. I tried Peak Detector (2), but I cannot get anything but 0  
out of it.  
Any ideas how I can implement that in GnuRadio (measure distance between  
peaks)? Ans then convert the distances into packets of 0 and 1?

Best regards  
Stefan
