I got my Radio Amateur's (HAM) license a few years back because I wanted to experiment with radio telemetry for my rocketry and high altitude balloon projects. After running some tests using XBee modules, I decided that the Amateur Packet Reporting System (APRS) offered potentially longer range and would be more suitable for HA balloon projects. There are already quite a few commercially available products that work with APRS but, being a do it myself kind of guy, I wanted to build my own. Also, given that the loss of a rocket, or balloon is quite a high probability, the roll my own approach also offer the potential for lower costs in the case of lost, or destroyed telemetry equipment.
My first project was to try and build an APRS decoding system I could hook to my handheld transceiver in order to monitor local APRS transmissions. However, I quickly discovered that many of the designs I could find online were based on parts, such as the MX614, that were either obsolete, or hard to find (expensive.) Modern systems, it seems, often use a software-only solution that uses DSP-based software running on a laptop in combination with a sound input, or sound card to decode the Bell 202-style 1200 baud AFSK signals that APRS most commonly uses for modulation and demodulation. I was hoping to build something far more compact, so I began to wonder whether I could implement Bell 202 modulation and demodulation on a cheap micro controller chip.
Then, I remembered reading an article many years ago in Circuit Cellar magazine, about a guy that built his own digital answering machine. One feature that stuck out in my memory was that his design implemented Caller ID using a software-base modem. Caller ID is also based on the Bell 202, 1200 baud modulation scheme, so I reasoned this could be adapted to my purposes. I tracked down a copy of the article, here, and discovered that he based his design on a German author's work (which you can find, here) that was originally intended for HAM Radio packet communication, so it seemed even more appropriate to adapt this design to my purposes.
The approach used is to sample the incoming FSK signal at 9600 samples/second (8 times the 1200 Hz frequency used in Bell 202 modulation) and pass this through two digital filters, one tuned to 1200 Hz and the other to 2200 Hz. The secret of the demodulation scheme is to implement the digital filters using tables of Sine and Cosine values for each frequency. The following bit of Java code shows the basic technique. The
To try out the approach, I wrote a Java application that used the code above to demodulate a test file of Bell 202-modulated data saved at 9600 samples/second. This worked surprisingly well, so I decided to see if I could adapt this code to run on a cheap micro controller. After some experimentation using my Java test application, I discovered that because the multiplications were all against constant values, they could easily be replaced with shifts and adds, which meant I did not need a micro controller with a hardware multiplier. So, out of a perverse desire to see how far I could push this idea, I decided on the ATTiny10 as my target micro controller.
By using careful register management, and by unrolling the central loop, I was able to avoid loading the sin/cos values from a table. Instead, I wrote out the entire loop as one long series of sift, add/sub, move, etc. instructions. To get an idea how this works, here's the first iteration of the central loop in unrolled form:
This type of coding continues for the remaining 7 iterations of the loop, but different combinations of shifts, adds and subtracts are used to multiply by different coefficients. Rather than repeat all this here, I refer you to complete source code, which you can download from the
Bell 202 Modulation
To complement my demodulation code, I wrote companion Bell 202 modulator code, also for the ATTiny10, which you can download from the