diff --git a/TeensyDSP/Keyer.cpp b/TeensyDSP/Keyer.cpp new file mode 100644 index 0000000..10fe9c6 --- /dev/null +++ b/TeensyDSP/Keyer.cpp @@ -0,0 +1,185 @@ +//====================================================================== +// +// nanoIO paddle keyer (c) 2018, David Freese, W1HKJ +// +// based on code from Iambic Keyer Code Keyer Sketch +// Copyright (c) 2009 Steven T. Elliott +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details: +// +// Free Software Foundation, Inc., 59 Temple Place, Suite 330, +// Boston, MA 02111-1307 USA +// +//====================================================================== + +#include +//#include "TimerOne.h" +//#include "config.h" +#include "Keyer.h" + +const uint8_t LP_in = KEYER_LEFT_PADDLE_PIN; +const uint8_t RP_in = KEYER_RIGHT_PADDLE_PIN; + +//#define ST_Freq 600 // Set the Sidetone Frequency to 600 Hz + +//====================================================================== +// keyerControl bit definitions +// +#define DIT_L 0x01 // Dit latch +#define DAH_L 0x02 // Dah latch +#define DIT_PROC 0x04 // Dit is being processed +#define PDLSWAP 0x08 // 0 for normal, 1 for swap +//====================================================================== +// +// State Machine Defines + +enum KSTYPE { IDLE, CHK_DIT, CHK_DAH, KEYED_PREP, KEYED, INTER_ELEMENT }; + +UBitxKeyer::UBitxKeyer(int wpm, float weight): +speed(wpm), symWeight(weight) +{ + // Setup outputs + pinMode(LP_in, INPUT_PULLUP); // sets Left Paddle digital pin as input + pinMode(RP_in, INPUT_PULLUP); // sets Right Paddle digital pin as input + + keyerState = IDLE; + keyerControl = 0; + keyMode = IAMBICA; + keyDown = false; + + calcRatio(); +} + +// Calculate the length of dot, dash and silence +void UBitxKeyer::calcRatio() +{ + float w = (1 + symWeight) / (symWeight -1); + spaceLen = (1200 / speed); + dotLen = spaceLen * (w - 1); + dashLen = (1 + w) * spaceLen; +} + +void UBitxKeyer::setWPM(int wpm) +{ + speed = wpm; + calcRatio(); +} + +//====================================================================== +// Latch paddle press +//====================================================================== + +void UBitxKeyer::updatePaddleLatch() +{ + if (digitalRead(LP_in) == LOW) { + keyerControl |= DIT_L; + } + if (digitalRead(RP_in) == LOW) { + keyerControl |= DAH_L; + } +} + +bool UBitxKeyer::doPaddles() +{ + if (keyMode == STRAIGHT) { // Straight Key + if ((digitalRead(LP_in) == LOW) || (digitalRead(RP_in) == LOW)) { + keyDown = true; + return true; + } else { + keyDown = false; + } + return false; + } + + // keyerControl contains processing flags and keyer mode bits + // Supports Iambic A and B + // State machine based, uses calls to millis() for timing. + switch (keyerState) { + case IDLE: // Wait for direct or latched paddle press + if ((digitalRead(LP_in) == LOW) || (digitalRead(RP_in) == LOW) || (keyerControl & 0x03)) { + updatePaddleLatch(); + keyerState = CHK_DIT; + // letting this fall through // return true; + } else { + return false; + } +// break; + + case CHK_DIT: // See if the dit paddle was pressed + if (keyerControl & DIT_L) { + keyerControl |= DIT_PROC; + ktimer = dotLen; + keyerState = KEYED_PREP; + return true; + } else { // fall through + keyerState = CHK_DAH; + } + + case CHK_DAH: // See if dah paddle was pressed + if (keyerControl & DAH_L) { + ktimer = dashLen; + keyerState = KEYED_PREP; + // letting this fall through // return true; + } else { + keyerState = IDLE; + return false; + } +// break; + + case KEYED_PREP: // Assert key down, start timing + // state shared for dit or dah + keyDown = true; + ktimer += millis(); // set ktimer to interval end time + keyerControl &= ~(DIT_L + DAH_L); // clear both paddle latch bits + keyerState = KEYED; // next state + // letting this fall through // return true; +// break; + + case KEYED: // Wait for timer to expire + if (millis() > ktimer) { // are we at end of key down ? + keyDown = false; + ktimer = millis() + spaceLen; // inter-element time + keyerState = INTER_ELEMENT; // next state + // letting this fall through // return true; + } else if (keyMode == IAMBICB) { // Iambic B Mode ? + updatePaddleLatch(); // yes, early paddle latch in Iambic B mode + } else { + return true; + } +// break; + + case INTER_ELEMENT: // Insert time between dits/dahs + updatePaddleLatch(); // latch paddle state + if (millis() > ktimer) { // are we at end of inter-space ? + if (keyerControl & DIT_PROC) { // was it a dit or dah ? + keyerControl &= ~(DIT_L + DIT_PROC); // clear two bits + keyerState = CHK_DAH; // dit done, check for dah + return true; + } else { + keyerControl &= ~(DAH_L); // clear dah latch + keyerState = IDLE; // go idle + return false; + } + } else { + return true; + } +// break; + } + + return false; // resolve compiler warning; do we ever get here? +} + +UBitxKeyer basicKeyer(15, 3.0); +UBitxKeyer& Keyer = basicKeyer; + +//====================================================================== +// EOF +//====================================================================== diff --git a/TeensyDSP/Keyer.h b/TeensyDSP/Keyer.h new file mode 100644 index 0000000..49b5d8c --- /dev/null +++ b/TeensyDSP/Keyer.h @@ -0,0 +1,79 @@ +//********************************************************************** +// +// Keyer, a part of nanoIO +// +// nanoIO paddle keyer (c) 2018, David Freese, W1HKJ +// +// based on code from Iambic Keyer Code Keyer Sketch +// Copyright (c) 2009 Steven T. Elliott +// +// nanoIO is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// nanoIO is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with fldigi. If not, see . +// +//Revisions: +// +//1.0.0: Initial release +// +//********************************************************************** + + +#ifndef __Keyer_h__ +#define __Keyer_h__ + +#define IAMBICA 0 +#define IAMBICB 1 +#define STRAIGHT 2 + +#define KEYER_LEFT_PADDLE_PIN 17 +#define KEYER_RIGHT_PADDLE_PIN 16 + +class UBitxKeyer +{ +public: + UBitxKeyer(int wpm, float weight); + //void cw_pin(int pin); + //void ptt_pin(int pin); + void setWPM(int wpm); + inline void setMode(int mode) { keyMode = mode; } + inline int getMode() { return keyMode; } + inline bool isDown() { return keyDown; } +// void setWeight(); + + bool doPaddles(); + +private: + void calcRatio(); + void updatePaddleLatch(); + + bool keyDown; + + long ktimer; + + int speed; + int dashLen; // Length of dash + int dotLen; // Length of dot + int spaceLen; // Length of space + float symWeight; + + char keyerControl; + char keyerState; + int keyMode; +}; + +extern UBitxKeyer& Keyer; + +#endif + +//====================================================================== +// EOF +//======================================================================