962a3ce80f
This reverts commit 86ae1ddb2f
.
186 lines
5.8 KiB
C++
186 lines
5.8 KiB
C++
//======================================================================
|
|
//
|
|
// 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 <Arduino.h>
|
|
//#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
|
|
//======================================================================
|