PA5ET – CW Decoder

CW Decoder January 2017



We discuss a small PIC-based CW decoder, a great help for a beginning ham. The base is taken from Budd Churchward WB7FHC's Arduino-based decoder. My own source code, for a PIC16F88, is on GitHub.

Porting to PIC

While the project is great, I was unable to resign myself to use an Arduino. Arduino is nice for prototyping, but too many people use it as an end product, wasting space and resources. Worst of all, they fail to learn principles of electrical engineering and programming on minimal architectures.

Hence, I decided to port the project to a PIC microcontroller. PIC is a wide range of microcontrollers developed by Microchip. For this project, a simple 8-bit chip is more than enough. The only thing we need to look out for is that the clock is fast enough. I went with the PIC16F88 which has 5MIPS, for the simple reason that I had it in stock. Anything will do.

Porting the Arduino code (which is a C++ dialect) to C is relatively easy. The only complication is the millis() function. On Arduino, this returns the number of milliseconds since startup. This is part of the Arduino bootstrapping code, which we do not have on PIC, so a small wrapper for this function had to be written. The same functionality can be achieved with a timer and an interrupt service routine (which is, I assume, the way it works on Arduino as well).

For the LCD I used a 4x40 display with green backlight. It is HD44780-based but has two control chips, which can be turned on and off using two enable lines. My HD44780_PIC C library can deal with this, as well as with 4- and 8-bit interface. (This is all done through preprocessing #define statements so it does not slow down the code.)

Other than these two points, porting the code was straightforward and no major changes have been made.


There was not much space left next to the display. I had just enough space for the LED, the reset button and the volume button. The LED is absolutely necessary on the front for feedback.

The 4x40 LCD performs very well. A 4x20 or perhaps 2x40 would do the job as well, but I wouldn't go smaller than that. Sometimes characters are missed or noise is interpreted as a character, so you should expect that perhaps 80% of the character space is used for the actual text.

There is no need to place the frequency potentiometer on the front because it should be fixed to your side tone. I found that a high-precision potentiometer is very useful to adjust the frequency. The bandwidth of the audio mixer is relatively narrow.

Future plans

I intend to make the decoded text not only available on the LCD but also on the UART module. The RX pin is used already, but one-way communication will be enough. This way, another module could log QSOs to an SD card, another idea I have been playing with.

Another addition I'd like to make is a fix-frequency button. This would disable the automatic adaption to the current speed. It could be pressed at the start of a QSO and released afterwards. I hope that in this way the decoder can become less sensitive to background noise.

Lastly, some status information would be nice on the LCD. Concretely, I'm thinking about the estimated WPM. This should be fairly simple to implement. It could also be useful to have an accuracy estimation. Figures that could be used for this are the standard deviation on the length of dits and dahs and the amount of jitter during a dit or dah.