[1] https://en.wikipedia.org/wiki/WSJT_(amateur_radio_software)#FT8
On 2 April 2018 at 11:48, Jeff Long <address@hidden
<mailto:address@hidden>> wrote:
The gr-op25 code handles 4FSK. The demod and slicer code might be
expanded to 8FSK.
On 04/02/2018 06:22 AM, Jeff Long wrote:
This looks like an amateur M-FSK signal. You might have luck
with fldigi and save yourself some work. It uses FFTs and then
analyzes frequency shifts. You could do some of this in GR, but
syncing to the signal would be hard because you would miss a few
transitions trying to get synced.
On 04/02/2018 04:48 AM, Thomas Habets wrote:
Hi.
As an experiment I'm trying to decode an FT8 signal I've
captured. I've gotten far enough that I can clearly see the
packet (https://blog.habets.se/tmp/ft8_packet.png
<https://blog.habets.se/tmp/ft8_packet.png>
<https://blog.habets.se/tmp/ft8_packet.png
<https://blog.habets.se/tmp/ft8_packet.png>>), but now I
want to actually turn that into bits.
I know it's 8FSK (the above screenshot is quad demod of
that), but I have a few questions on clock recovery:
* Is the GFSK block only for BFSK? If so then that's out.
* Is there a "best" clock recovery block nowadays? I seem to
recall "Clock Recovery MM" being discouraged in favor of
"Polyphase Clock Sync".
* I'm trying to read up on the parameters Polyphase Clock
Sync wants, but any pointers would be helpful.
* Would it be a good idea to throw in a costas loop for
frequency tuning?
* Does Polyphase Clock Sync have the same dislike of
"staircase" inputs? That is, I should try to make the center
of the bits more "pointy"? (e.g. lowpass filter them)
I've done some custom OOT decoders before, so I'm not shy
about that. Maybe the best thing is some whole-packet clock
recovery[1]. But if I just write a block that takes the quad
demod (see above screenshot) and finds the "platforms",
outputting a message that is a list of floats, and then
another block that takes a list of floats and the number 8
and decodes it as 8FSK, well it seems like I may be
reimplementing things where I'm guessing someone might say
"oh just use this block".
Also for experimentation and my own understanding I'd like
to turn it into bits using in-tree blocks, if possible.
Maybe a correct Polyphase Clock Sync of the quad demod
followed by a Constellation decoder? I could use the float
as the phase, with magnitude 1. Does that make sense? Is it
a good idea?
What I have so far is:
Data:
https://blog.habets.se/tmp/ft8-burst-10k.raw
<https://blog.habets.se/tmp/ft8-burst-10k.raw>
<https://blog.habets.se/tmp/ft8-burst-10k.raw
<https://blog.habets.se/tmp/ft8-burst-10k.raw>> (10k samp_rate)
<https://blog.habets.se/tmp/ft8-burst-10k.raw>
GRC:
https://blog.habets.se/tmp/ft8_decode.grc
<https://blog.habets.se/tmp/ft8_decode.grc>
<https://blog.habets.se/tmp/ft8_decode.grc
<https://blog.habets.se/tmp/ft8_decode.grc>>
<https://blog.habets.se/tmp/ft8_decode.grc>
Screenshot:
https://blog.habets.se/tmp/ft8_decode_grc.png
<https://blog.habets.se/tmp/ft8_decode_grc.png>
<https://blog.habets.se/tmp/ft8_decode_grc.png
<https://blog.habets.se/tmp/ft8_decode_grc.png>>
<https://blog.habets.se/tmp/ft8_decode_grc.png>
(everything off-screen to the right is failed clock recovery
experiments)
Quad demod
https://blog.habets.se/tmp/ft8_packet.png
<https://blog.habets.se/tmp/ft8_packet.png>
<https://blog.habets.se/tmp/ft8_packet.png
<https://blog.habets.se/tmp/ft8_packet.png>>
<https://blog.habets.se/tmp/ft8_packet.png>
[1] Like https://www.youtube.com/watch?v=rQkBDMeODHc
<https://www.youtube.com/watch?v=rQkBDMeODHc>
<https://www.youtube.com/watch?v=rQkBDMeODHc
<https://www.youtube.com/watch?v=rQkBDMeODHc>> which I
turned into
https://github.com/ThomasHabets/radiostuff/blob/master/gr-habets/python/magic_decoder.py
<https://github.com/ThomasHabets/radiostuff/blob/master/gr-habets/python/magic_decoder.py>
<https://github.com/ThomasHabets/radiostuff/blob/master/gr-habets/python/magic_decoder.py
<https://github.com/ThomasHabets/radiostuff/blob/master/gr-habets/python/magic_decoder.py>>
--
typedef struct me_s {
char name[] = { "Thomas Habets" };
char email[] = { "address@hidden
<mailto:address@hidden> <mailto:address@hidden
<mailto:address@hidden>>" };
char kernel[] = { "Linux" };
char *pgpKey[] = { "http://www.habets.pp.se/pubkey.txt
<http://www.habets.pp.se/pubkey.txt>" };
char pgp[] = { "9907 8698 8A24 F52F 1C2E 87F6 39A4 9EEA
460A 0169" };
char coolcmd[] = { "echo '. ./_&. ./_'>_;. ./_" };
} me_t;
_______________________________________________
Discuss-gnuradio mailing list
address@hidden <mailto:address@hidden>
<mailto:address@hidden>
https://lists.gnu.org/mailman/listinfo/discuss-gnuradio
<https://lists.gnu.org/mailman/listinfo/discuss-gnuradio>
<https://lists.gnu.org/mailman/listinfo/discuss-gnuradio>
_______________________________________________
Discuss-gnuradio mailing list
address@hidden <mailto:address@hidden>
<mailto:address@hidden>
<https://lists.gnu.org/mailman/listinfo/discuss-gnuradio>https://lists.gnu.org/mailman/listinfo/discuss-gnuradio
<https://lists.gnu.org/mailman/listinfo/discuss-gnuradio>
--
typedef struct me_s {
char name[] = { "Thomas Habets" };
char email[] = { "address@hidden <mailto:address@hidden>" };
char kernel[] = { "Linux" };
char *pgpKey[] = { "http://www.habets.pp.se/pubkey.txt" };
char pgp[] = { "9907 8698 8A24 F52F 1C2E 87F6 39A4 9EEA 460A 0169" };
char coolcmd[] = { "echo '. ./_&. ./_'>_;. ./_" };
} me_t;