View on GitHub

MSF60decoder

A software decoder for the 60kHz NPL time signal (aka MSF)

MSF-60 decoder

A simple software decoder for the 60kHz NPL time signal (aka MSF) accurate to a few tens of milliseconds.

The UK radio time signal is broadcast on 60kHz from Anthorn, Cumbria, UK (see Time from NPL)

There are many ways to decode this signal already out there but all seem to involve significant hardware (e.g. current search). This project uses just a bit of wire into a soundcard and does all the hard work in software. I’m about 250 miles away from the transmitter and I put about 4 meters of wire out of an upstairs window and attached it to a tree. Others suggest that a small loop antenna or a few turns around a ferrite rod would do the trick as well. Whatever antenna is used, there is no radio frequency hardware (e.g. demodulator), everything is done by sampling and software.

Testing install

test.sh just calls MSF60decoder.py on a standard file, test.wav (after uncompressing it if that hasn’t already been done). You should see: packet: 2019-05-31 13:49 sysDiff +0.025

This is the decoded packet formatted as a date and time plus a rough guess at the difference between radio time and system time.

Recording audio

I have a Intel DX58SO motherboard (from 2008!) which has a 82801JI HD Audio Controller, but anything that samples at 192kHz will probably do. If you haven’t got 32bit input you may have a “20dB boost”. You’ll probably have to fiddle with both the sox recording line and boosting the kernal prioities of the recording process. MSF60decoder.sh contains a ‘good enough’ solution for me, and also has links to documentation. MSF60decoder.sh also calls MSF60decoder.py, so once you’ve got everything set up you can call this and decode the time from MSF-60.

Signal processing

So how does MSF60decoder.py work? Lines marked with ## can be uncommented to show the signal processing steps. If you do this don’t forget to add a ‘plt.show()’ line so that the plot is displayed. The plots below come from the supplied test.wav file.

So what does the recorded waveform look like? Here are the first few samples:

waveform

Well, there’s certaily something happening there. The low frequnecy is almost certainly 50Hz mains noise, and there’s a lot more happening at other frequencies. so let’s look at the waveform in the frequency domain:

FFT of waveform

Good, there is a peak at 60kHz, that’s the signal we are after.

Now let’s construct a filter to pick out that signal, here is the filter called swindow which is a windowed sine wave:

swindow

That’s a lot of points, too many to see the sine wave, just its envelope. So let’s look at the firt 64 points:

swindow64

That doesn’t look much like a sine wave because it’s at 60kHz and the maximum frequency we can represent is 96 kHz, but it is a sine wave and because it repeats so many times it’s good at filtering out all the other frequencies present. So now we can demodulate our original waveform and we get:

demod

There’s defintely some structure there, let’s look at the first part:

demod

And there we have it, our time signal. All we need to do now is get the exact timing of the signal (as we have oversampled) and then we can digitise and get all the bits out.

sysDiff

The final field of a packet decode is systemTime (computed from the mtime of the file) minus radioTime (computed from the radio time signal). Many file systems only store times to a second, in which case you can’t expect any better accuracy than a second. However, if you are running ext4 then you are in luck and you should get the time to at least 0.1s.

Extensions