Tachyon based, P1 CW keyer for high speed Morse code practice
This project's objective is to learn Tachyon Forth and a P1 microcontroller while making something useful (to me).
Main goals are:
1. Use whatever P1 hardware one has available - this means it must run on a minimum P1 hardware. I will use my home made P1 "ugly" board.
2. Minimal but adequate feature set - this means it must:
- take the dual paddle or a single lever key as input
allow for the manual speed control with basic but proper timing of the Morse code characters,
preferably by means of the quadrature encoder or up/down buttonsallow for saving the parameters on power off and automatically restoring them on power on
- produce sound, which frequency can be user determined to be between 300Hz and 800Hz, when the key contacts are closed - I hate the sound of the square wave but that's what I'll start with
- provide visual indication for dits and dahs
- consume as low power as only possible while retaining all of the above features - the plan is to have it battery operated in the field
- Future proof - it must allow for easy addition and customizations of features but still be able to
operate on the same hardware and Tachyon platforms as it's core - this means new features must not
require any changes to the core hardware (the minimum P1 hardware I start with) but hardware
expansion is allowed if necessary. - Open source - based on the open schematics and software.
- Move to the new features only if, and when, these basic ones are realized and proven to be working
flawlessly.
Now, I am fully aware that what is described above exists on other microcontroller platforms and most probably on the P1 as well (I don't know for sure, I haven't checked) but none of them meets my project objective.
Moreover, this is only a small step towards the much bigger Tachyon/TAQOZ project I have in mind and is meant as a first step. If I fail with this one it'll mean I'm not ready for the more ambitious target.
I expect a lot of problems on the way and will post them here so stay tuned if interested but do not count on the fast pace. This is just a hobby project and my quality hobby time is very limited at this time of year.
You are, of course, invited to contribute to this little project, if you feel like it, in a way that suits you best but please, do not try to discourage me as this will be a wasted effort.
Comments
One thing at a time.
The first bullet on the list says:
All that is needed to do that is to detect if the key contact is at a high level or at a low one (logic 1, logic 0). Sounds simple.
Actually, I think I only need to detect 0 (contact closed to ground) reliably and to treat any other state of the contact as logic 1 (non 0). That should simplify the program a bit.
But I need to do it reliably each time and every time. Mechanical contact bounce and I need to factor that out too.
I have no influence over key contacts' behavior so I need to take care of this issue at the keyer side.
There are two ways to deal with it I know off. One of them is to reduce the bounce effect in hardware and the second one is to do it in software.
The hardware path (at the the keyer side) is easy as it requires just a resistor and a capacitor for each pair of contacts. The software path may be more complicated (to me for sure) but it requires no external components and is more flexible. And it takes zero board space on the PCB.
Maybe I'm wrong on this as I haven't started writing a program yet but I am assuming it will be more difficult.
The next thing would be to decide how to do polling of the contacts. Probably the easiest way would be to use constant polling of both contacts (paddle arms) simultaneously or maybe sequentially but I think it is not needed. It would be sufficient to poll the given contact only when it is not closed (logical 1).
Ideally, a Morse "dot", in it's canonical form, is formed by a pulse followed by a pause lasting the same amount of time as the pulse. The "dash" is a pulse tree times as long as the pulse in the "dot" and a pause that last just the same amount of time as a "dot" pause (or pulse as these are equal in the "dot").
Maybe it would be even better to poll a contact after at least some time after it goes high ?
If I polled a contact only right after that moment, when a dot or a dash finished, I would gain a certain amount of immunity to whatever happens to the contact during that "dot" or "dash" time. That I could use to ensure a character I am sending will not be interrupted by an accidental contact closure until it ends. That would be an advantage.
I'll post the code when I'm done with that piece.
Hi Maciek! I like this project as it is simple and usefull. Even in a very early stage. And can be expanded over and over. So I copied the first two entries and pasted them into a CMap to show the structure of the text and later the structure of the solution. This map can be found here as a rendered SVG. But the CMap tools is available for free, even if not open sourve and so everybody is invited to use it as a tool to work with in one or another way.
I will continue to copy the content of this thread and we will see, if it is usefull.
Thanks, @ErNa .
I am doing it for myself. It's better for me to start simple. There are caveats in this simple project as well but I will get to them as I proceed.
Hi Maciek, it would be interesting to see the process as there are some hurdles for beginner we could point to. The paddle or key needs sampling a pin, the decoder has to run in parallel, etc. I will do something similar implementing the incremental encoder. While the basic task is to decode the quadrature signal, there is a lot around to have a fully featured functional block. That can be used without understanding whats under the hood.
Hi Maciek,
two comments perhaps:
1. If you want to, you could have a look into my DCF-77 decoder. As a matter of fact, one main element of that code is to decide, if a pulse at a pin is longer or shorter than a threshold time. - This is the same task as you have to do here.
2. I don't know, if you are aware: If you want to run with batteries, the direct way to reduce power consumption ist to use a lower clock speed. Current draw is proportional to clock speed. If battery operation is really important, it seems wise to study the possibilities here at the very beginning. Then design the code to the findings. For example ms pause commands are really bad, as they let run the cog at full speed in a loop, burning power for nothing. I am not sure, but I seem to remember, that the waitxxx instructions do not need power. It is somewhat funny: If you have to care about battery life, speed is a very different value. If you can speed up code by factor 10, you can instead use a 10th of the clock speed and have 10fold battery life.
Hi Christof,
ad 1. thanks for that tip. I'll look into the code.
ad 2. Yes, I am well aware of what you point out. That's what I called "caveats" in my post above (#4). My main goal for now is to have the code for a given functionality working. Then I will put all of the pieces together and then I will optimize for the power consumption. But I am thinking of that aspect at the beginning too as conserving the power will most likely influence the way a given functionality is coded. Just do not want to complicate things at start.
I will try to find the picture, but I saw a modified Bencher key at a ham show that used flexible mounts and strain gauges instead of contacts. It had a little MCU that would allow you to send macros by TWISTING both keys gently and then “entering” the macro number via dits. One guy modified this further and had the amount of paddle deflection control the CW output power: small excursions got you QRP with large key excursions dialing up QRO. I’m not much of a brass pounder but I mentally tagged it because the design was slick and intuitive.