Reading the May 2014 issue of QST, on page 65, I found a mention of an interesting story about Oona Raisanen OH2EIQ.
Oona was watching the helicopter news video of a police chase when she realized that the audio track contained a data feed. As the very talented hacker that she actually is, Oona managed to filter and successfully decode the data using Perl and SoX.
As a result, she was able to plot the helicopter light path on a map. What a nice catch! I thought…
A few days later I was reading a piece about a serious incident that happened in Italy: the city of Rome was theater of violent clashes between supporters of opposing soccer teams. Near the stadium the situation degenerated to the point that a person was shot and critically wounded while hordes of violent supporters put the surrounding area under siege. Dramatic footage from an aviation unit of the Italian State Police completed the article.
When I saw this report for the first time, I obviously still had Oona’s story still fresh in my mind so I wondered if the video released by the Police eventually contained any audio tracks at all. The answer was surprising: not only the data feed was present, but it didn’t even need to be filtered! A clear invitation to attempt decoding it! I put myself to work immediately…
The audio clearly sounded like an unmodulated carrier that took turns with bursts of 1200 Baud AFSK. Visual inspection of the modulated waveform confirmed no signs of phase changes so it definitely had to some form of FSK. Assuming it really was 1200 baud, then each bit was supposed to be around 0.8 ms long.
With that in mind, I tried manually decoding the beginning of each burst, and I noticed that each one always begun with the same sequence. It took a few attempts and some patience to identify what that sequence actually meant… Here it is:
Ignoring the start and the stop bits and reversing the payload (that is LSB) the resulting byte would be “00100011” which in the ASCII table corresponds to the pound sign (#). Great start! Now I just had to decode all the rest of stream!
Unfortunately Oona did not explain in details how she demodulated her stream so I had to come up with something else of my own. My first attempt was using Python and numpy: after splitting the samples in chunks that I calculated being around 0.83 ms long, I applied the FFT on each of them in order to find their predominant frequency components. It was kind of working but I could not find an easy way to keep my chunks in sync with the actual bitstream so, after a few hours of hacking, I asked myself a question: am I really the first (actually… the second!) person who’s trying to decode 1200 bd AFSK? Obviously I was not. There must have been something readily available that was capable of doing exactly what I needed. Instead of reinventing the wheel, all I had to do was finding it.
I Googled a bit… I didn’t take long to realized that minimodem by Kamal Mostafa was probably the right tool for the job. Indeed, after a bit of wrestling to compile it on my Mac, it worked at the very first try:
Boom… There was my bit stream! Data bursts were indeed beginning with a pound sign, were consistent in length and, most interestingly, they appeared to have repeating patterns that enclosed some variating information.
The first thing that caught my attention were those N’s and those E’s. Did they mean North and East? If so, those were probably coordinates. I tried various possibilities and found that yes, they were indeed DMS latitude and longitudes values. This is how they are encoded:
Observing the other values and applying the same logic I was able to identify the flight level (probably expressed in feet) and the compass heading of the helicopter. Other values that are present in the stream and that certainly represent useful information are still unknown and I still cannot guess what they are…
In order to parse my data I wrote a few rows of Python and, after plotting them with Google Maps, I saw that the helicopter was exactly where I expected it to be: circling the aerea where reportedly the soccer thugs clashed with the police, and where they shot each other. This is the result:
Around 1 minute into the video a Police is being surrounded by an angry mob. For no apparent reason the mob also attacks nearby cars and buses. A scene of total anarchy… Below is a screenshot of the Police coverage compared with a view from Google Earth.
All in all, so far I was able to decode the coordinates, height and heading. That is better than I anticipated, and I’m sure there must be even more!