The other day I was playing with the idea of building an iambic keyer, using the new PIC16F1827 from Microchip. My dad (W7GP) enjoys making code keys and I have a friend up in Colorado that still uses Morse on the air. Besides, I had promised myself that I would relearn the code and actually use it on the air (N7KGC). In addition, the PIC16F1827 was a perfect choice for the project due to a wealth of CCPs and a new modulation peripheral.
I was completely caught up in the wild enthusiasm of a new project; I had figured out the timing, allocated the necessary pins and resources for the tone generation, and was considering what kind of user interface when I hit a brick wall over the question of how to handle code speed, dit-to-dah weighting, and tone volume.
All three functions had typically been handled by a potentiometers, they gave the user a simple interface that was intuitive and simple to handle while actually using the keyer. In fact, all three functions were typically adjusted while generating dits and dahs until the rate, volume, and weighting “felt right.”
The problem was, in the back of my mind, I was stuck on the misconception that because the keyer was digital, the user interface also had to be digital. And, try as I might, I couldn’t come up with a simple system that would work as well as the old fashioned pots.
A menu driven user interface with UP and DOWN buttons was going to be too slow, and would require the user to look at the display. Touch button sliders would work, but if I accidentally touched one, I could mess up their settings and I would need some kind of Braille guide to keep my fingers aligned on the slider. Encoders would also work, but the cost of both the encoders and the code space required to decode them would not be worth it.
It was about this time, that I suddenly saw the light, and promptly gave my self a swift kick in the cerebellum for being dense. The answer was the KISS principal, Keep-It-Simple-Stupid. The potentiometers had the right feel, they retained their setting when the power was removed, and they provided a simple visual feedback and they were simple to interface. All I needed to do was digitize the wiper voltage with an ADC channel, and I would have my simple, cheep, and intuitive user interface to my digital keyer.
So, I setup a Timer0 interrupt for 4.096mS, and dropped a simple statemachine into the ISR to periodically sample the three ADC inputs. The results were stuffed into the appropriate variables, and whiz-bang, I had the perfect interface. I could even adjust the offset and slope in code to provide convenient values.
No complex commands to decode, no expensive graphics LCD module to show a virtual knob, and I even saved pins. Keeping It simple not only saved resources, it also saved about 20 pages worth of user’s manual explaining how to set the rate, weighting, and volume of the keyer.
Of course their was one annoying intermittent problem. Every once in a while I would get a glitch on the pot I was adjusting. I the value would momentarily jump by ¼ or ½ of full scale. After several hours of hair pulling and 2 attempts to digitally filter the values, it finally dawned on me, I was using the values out of the variables at exactly the same time that the ISR was updating the values. The result was a 01FF when the values rolled over from 0FF to 100, or a 000 output when I rolled over 100 to 0FF. The solution was to simple; turn off the interrupts, copy the values into a separate set of variables, and then turn the interrupts back on. Basically, I created the software equivalent of double buffering.
While the final result did take some extra storage space and required a small increase in code size, it was still far smaller than any of the other alternatives and a lot more convenient to use.