2
$\begingroup$

I am trying to write my own AFSK decoder with QT/C++.

I can read/and identify the SPACE and MARK in the audio stream.... And whilst I can see how to encode (depending on which variant of encoding that you use) - I am unable to figure out how to synchronize the data stream.

For example:

If I were to send HI

This would be encoded as (ITA2 LSB)

10100 00110

So on decoding ... is there a preamble i.e. ? Note: This is my made-up preamble.

01010 10100 00110
<PRE> <H>   <I> 

Any pointers/links would be appreciated if not a direct answer.

73s

Tim. DU3TW.

$\endgroup$
2
  • $\begingroup$ I can start an answer, but it stops at "depends on how exactly you convert your FSK signal to 0s and 1s"; for any further hint, would need to know your FSK receiver/demod method! $\endgroup$ Aug 11 at 10:39
  • $\begingroup$ Sounds a lot like RTTY ( en.wikipedia.org/wiki/Radioteletype ). It synchronizes by start bit and timing, like asynchronous serial port. So the actual encoding would usually be "1101000 1001100", with idle state being 0 (sometimes inverted). You wait for the first 1 and read bits at regular intervals. $\endgroup$
    – jpa
    Aug 11 at 17:00

2 Answers 2

2
$\begingroup$

I am trying to write my own AFSK decoder with QT/C++.

cool!

(ITA2 LSB)

ITA2 turns 100 in two years, what a legend! Hope you're in for some specialities not owed to it being logical or easy the way it is done, but possible by devices which didn't even have the vacuum tubes and which predate even the fundamental theory behind communications over a noisy channel. This is not a complex mode, but it's one that's actually not well-suited for anything but the original device designs :) This just increases my respect towards this project.

I am unable to figure out how to synchronize the data stream.

That's actually a good sign – synchronization is the harder part in such systems, compared to simple demodulation!

So on decoding ... is there a preamble i.e. ? Note: This is my made-up preamble.

01010 10100 00110
<PRE> <H>   <I>

The problem lies even deeper: your receiver doesn't even know when one 0 ends and another 0 starts, or more generally, what the symbol timing is.

You need timing recovery, as us communications engineers would say!

Now, how to do that really depends on how you're demodulating the AFSK. FSK is generally not the easiest system to synchronize, and you'd work with how the demodulator deals with changes in frequency. However, different demodulators deal with things differently!

But: of course, if you have a preamble that's long enough (so that the energy in preamble -to- energy in noise during preamble is high enough) you can just use a correlator that you just let run all the time on the raw input signal. As soon it sees a preamble, it can output a sample-accurate (sub-sample-accurate, even, if you know a bit about the FSK pulse shaping) estimate of the time at which the preamble happens – and from there, it's just counting forwards.

However, Baudot code ITA2 is 98 years old, so no, it doesn't have a proper preamble. You're picking an unnecessarily hard system! It only has a five-pulse "preamble", which isn't unique, has bad autocorrelation properties, and thus, is hard to detect.

No

$\endgroup$
1
  • $\begingroup$ Marcus - great info. Still progressing this. $\endgroup$
    – Tim Seed
    Aug 12 at 5:57
0
$\begingroup$

What you've really discovered is that just saying "AFSK" isn't enough to describe a communications protocol. You need to specify some additional stuff about framing and timing. You can have two different systems that differ in those details, while using FSK in the same way, and they won't be able to talk to each other.

One option, that applies to pretty much any system that can transmit a sequence of marks and spaces, is to agree in advance on a baud rate, a character size (5 bits in your case), a bit order, and that you will follow the rules of asynchronous serial. Namely:

  • A station that's on the air but has nothing to send idles in the MARK state.
  • A station sends a character by sending SPACE for one bit time (the "start bit") followed by the bits of the character, in the specified order (e.g. LSB first), for one bit time each (the "data bits").
  • Immediately after sending a character, a station must idle in the MARK state for at least a specified number of bit times (the "stop bits", usually 1, 1.5, or 2); idling for longer is permitted.

Then the decoder simply has to wait for a MARK to SPACE transition, and sample the n bits following the SPACE, at the defined baud rate, to receive one character. The rules ensure that there will always be transitions (since the start and stop bits are opposite polarity), and allow for a few percent of timing slop between sender and receiver without too much trouble (each character is decoded relative to the timing of its own start bit, not anything previous). Noise immunity is only so-so, and desyncs are possible, but generally fix themselves within a few characters under realistic circumstances.

If you apply those rules with a baud rate of 45.45 (a bit time of just a hair over 22ms), ITA-2 LSB-first, 1.5 stop bits, and a mark-space separation of 170 Hz then you have RTTY as commonly employed by amateurs.

But of course many other things are possible; you can have a preamble more complicated than a single start bit, for more robust synchronization; you can have frames that contain more than one character, you can provide checksums or error correcting codes, and you can be synchronous rather than asynchronous. It all depends on the protocol you're implementing (or inventing).

$\endgroup$
1
  • $\begingroup$ Many thanks for the feedback. You are quite correct it would be for Ham "RTTY". With Marcus and your input I am progressing to an R&D version of the code using Python. I will post examples/code here when I have something to show. Appreciate the feedback. $\endgroup$
    – Tim Seed
    Aug 12 at 5:58

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .