Incorporated some code changes that I made while on travel. Most of the significant items are in 'temp.h', which incorporates a bunch of proposed changes. However, I don't believe I'm going this direction, at this point. But, I did want to incorporate the code into a database.

This commit is contained in:
Rob French 2021-03-03 10:12:58 -06:00
parent cc94f89cfe
commit 5e280b33dd
4 changed files with 436 additions and 44 deletions

View File

@ -61,7 +61,7 @@ speed(wpm), symWeight(weight)
// Calculate the length of dot, dash and silence
void UBitxKeyer::calcRatio()
{
float w = (1 + symWeight) / (symWeight -1);
float w = (1.0 + symWeight) / (symWeight - 1.0);
spaceLen = (1200 / speed);
dotLen = spaceLen * (w - 1);
dashLen = (1 + w) * spaceLen;
@ -73,6 +73,12 @@ void UBitxKeyer::setWPM(int wpm)
calcRatio();
}
void UBitxKeyer::setWeight(float weight)
{
symWeight = weight;
calcRatio();
}
//======================================================================
// Latch paddle press
//======================================================================
@ -107,11 +113,10 @@ bool UBitxKeyer::doPaddles()
if ((digitalRead(LP_in) == LOW) || (digitalRead(RP_in) == LOW) || (keyerControl & 0x03)) {
updatePaddleLatch();
keyerState = CHK_DIT;
// letting this fall through // return true;
} else {
return false;
return true;
}
// break;
return false;
//break;
case CHK_DIT: // See if the dit paddle was pressed
if (keyerControl & DIT_L) {
@ -119,59 +124,57 @@ bool UBitxKeyer::doPaddles()
ktimer = dotLen;
keyerState = KEYED_PREP;
return true;
} else { // fall through
keyerState = CHK_DAH;
}
// 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;
return true;
} else {
keyerState = IDLE;
return false;
}
// break;
//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_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
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 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
return true;
} else if (keyMode == IAMBICB) { // Iambic B Mode ?
updatePaddleLatch(); // yes, early paddle latch in Iambic B mode
}
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 {
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;
}
// break;
}
return true;
//break;
}
return false; // resolve compiler warning; do we ever get here?

View File

@ -44,10 +44,12 @@ public:
//void cw_pin(int pin);
//void ptt_pin(int pin);
void setWPM(int wpm);
inline int getWPM() { return speed; }
void setWeight(float weight);
inline float getWeight() { return symWeight; }
inline void setMode(int mode) { keyMode = mode; }
inline int getMode() { return keyMode; }
inline bool isDown() { return keyDown; }
// void setWeight();
bool doPaddles();

View File

@ -5,7 +5,8 @@
#include <Arduino.h>
#include "TR.h"
UBitxTR TR(DSP);
UBitxTR _tr(DSP);
UBitxTR& TR = _tr;
void UBitxTR::update(bool cw, bool extKey) {
updateKey();

386
TeensyDSP/temp.h Normal file
View File

@ -0,0 +1,386 @@
const int rxLoCutSSB[] = { 0, 50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000};
const int rxHiCutSSB[] = {1000, 1200, 1400, 1600, 1800, 2000, 2200, 2400, 2600, 2800, 3000, 3400, 4000, 5000};
const int rxDataWidth[] = { 50, 80, 100, 150, 200, 250, 300, 400, 500, 600, 1000, 1500, 2000, 2500};
#ifdef USE_TS590SG
const int rxDataShift[] = {1000, 1100, 1200, 1300, 1400, 1500, 1600, 1700, 1750, 1800, 1900, 2000, 2100, 2210};
#else
const int rxDataShift[] = {1000, 1100, 1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2100, 2210};
#endif
const int txLowCutFilter[] = { 10, 100, 200, 300, 400, 500};
const int txHighCutFilter[] = {2500, 2600, 2700, 2800, 2900, 3000};
const int timeOutMinutes[] = {3, 5, 10, 20, 30};
#define MAX_MENU_TITLE_LEN 13
#define MAX_MENU_OPTION_LEN 13
typedef void (*toggleFunc)(UBitxRig&);
typedef bool (*boolStatus)(UBitxRig&);
#define KEYER_MIN_SPEED 4
#define KEYER_MAX_SPEED 60
/**********************************************************************/
/*!
* @brief Abstract base class for a switch/toggle (on/off, A/B, etc.)
* option. Derived classes must provide set() and get()
* methods for controlling the state of the switch.
*/
struct ConfigSwitch {
virtual ~ConfigSwitch() = 0;
virtual void set(bool on) = 0;
virtual bool get() const = 0;
};
/*!
* @brief Abstract base class for an option that supports a linear
* sequence of integer values. There can be a minimum and a
* maximum value, but otherwise, all integers between those
* should be acceptable. The base class takes care of checking
* min/max bounds, so the derived class must provide an get()
* and onSet() methods. In addition, derived classes can
* optionally override the onTooHigh() and onTooLow(), which
* by default clamp any out-of-band inputs to the min/max.
*/
struct ConfigInteger {
ConfigInteger(int min, int max)
: myMin(min), myMax(max) {}
virtual ~ConfigInteger() = 0;
inline void set(int val) {
if (val > myMax) val = onTooHigh(val);
if (val < myMin) val = onTooLow(val);
onSet(val);
}
virtual int get() const = 0;
virtual void onSet() = 0;
virtual int onTooHigh(int val) const { return myMax; }
virtual int onTooLow(int val) const { return myMin; }
int myMin, myMax;
};
/*!
* @brief Abstract base class for an option that supports a set
* of integer values stored in an array. The derived
* class must provide get() and onSet() methods. It can
* optionally provide an onTooHigh() method, which by
* default will clamp indices to the highest allowable.
*/
struct ConfigArray {
ConfigArray(int len, int* data)
: myLen(len), myData(data) {}
virtual ~ConfigArray() = 0;
inline void set(int i) {
if (i < 0) i = 0;
if (i > myLen - 1) i = onTooHigh(i);
onSet(myData[i]);
}
virtual int get() const = 0;
virtual void onSet(int val) = 0;
virtual int onTooHigh(int i) const { return myLen - 1; }
inline int getData(int i) { return myData[i]; }
int myLen;
int *myData;
};
/**********************************************************************/
/*!
* @brief Option class to set the configuration of the RX DSP filter.
*/
template<bool isHIGH>
struct ConfigRXFilter : public ConfigArray {
ConfigFilter(UBitxDSP& d, int default)
: ConfigArray(0, NULL), dsp(d), useData(false) {
if (isHIGH) {
current[0] = 10; // SSB - hi cut
current[1] = 05; // Data - center (shift)
data[0] = rxHiCutSSB;
data[1] = rxDataShift;
length[0] = sizeof(rxHiCutSSB)/sizeof(rxHiCutSSB[0]);
length[1] = sizeof(rxDataShift)/sizeof(rxDataShift[0]);
} else {
current[0] = 04; // SSB - lo cut
current[1] = 12; // Data - width
data[0] = rxLoCutSSB;
data[1] = rxDataWidth;
length[0] = sizeof(rxLoCutSSB)/sizeof(rxLoCutSSB[0]);
length[1] = sizeof(rxDataWidth)/sizeof(rxDataWidth[0]);
}
}
// TODO - A TON MORE TO DO HERE TO MAKE IT CONSISTENT WITH CONSTRUCTION
inline void setSSB() {
useData = false;
}
inline void setData() { useData = true; }
virtual void get() { return current; }
virtual void onSet(int i) {
current = i;
float value = static_cast<float>(getData(i));
if (isHIGH) {
if (useCENTER) {
dsp.setRxFilterCenter(value);
} else {
dsp.setRxFilterHi(value);
}
} else {
if (useCENTER) {
dsp.setRxFilterWidth(value);
} else {
dsp.setRxFilterLo(static_cast<float>(getData(i)));
}
}
}
private:
UBitxDSP& dsp;
int* data[2];
int length[2];
int current[2];
int mode; // 0 = SSB, 1 = Data
};
typedef ConfigRXFilter<false, false> ConfigRxLoCutSSB;
typedef ConfigRXFilter<true, false> ConfigRxHiCutSSB;
typedef ConfigRXFilter<false, true > ConfigRxLoCutData;
typedef ConfigRXFilter<true, true > ConfigRxHiCutData;
struct DSPConfigurator {
DSPConfigurator(UBitxDSP& d)
: dsp(d) {}
ConfigRxLoCutSSB ssbRxLoCut;
ConfigRxHiCutSSB ssbRxHiCut;
ConfigRxLoCutData dataRxLoCut;
ConfigRxHiCutData dataRxHiCut;
private:
UBitxDSP& dsp;
} dspConfigurator(DSP);
/**********************************************************************/
/**********************************************************************/
/*!
* @brief A configuration class for the Keyer. Since the Keyer has
* its own state that is not 100% compatible with the way way
* the Rig will interact with it (primarily in terms of CAT
* commands), this class provides the glue. (This is mostly
* used because, while the configuration objects are generally
* all separate, there is some state that needs to be
* communicated between e.g. the iambic mode configuration and
* the bug mode configuration.)
*/
struct KeyerConfigurator {
KeyerConfigurator(UBitxKeyer& k): keyer(k) { iambicAB = keyer.getMode(); }
/*!
* @brief An inner class that supports switching between Iambic A & B.
*/
struct IambicMode : public ConfigSwitch {
IambicMode(KeyerConfigurator& c): ConfigSwitch(), config(c) {}
virtual void set(bool on) {
config.iambicAB = on;
if (config.keyer.getMode() != STRAIGHT) {
config.keyer.setMode(config.iambicAB ? IAMBICB : IAMBICA);
}
}
virtual bool get() const { return config.iambicAB; }
private: KeyerConfigurator& config;
} iambicMode;
/*!
* @brief An inner class that supports switching bug mode on/off.
*/
struct BugMode : public ConfigSwitch {
BugMode(KeyerConfigurator& c): ConfigSwitch(), config(c) {}
virtual void set(bool on) {
config.isBug = on;
if (config.isBug && (config.keyer.getMode() != STRAIGHT)) {
config.keyer.setMode(STRAIGHT);
} else if (!config.isBug && (config.keyer.getMode() == STRAIGHT)) {
config.keyer.setMode(config.iambicAB ? IAMBICB : IAMBICA);
}
}
virtual bool get() const { return config.isBug; }
private: KeyerConfigurator& config;
} bugMode;
/*!
* @brief An inner class that supports switching the left and right
* paddles. TODO: This currently does nothing.
*/
struct PaddleSwap : public ConfigSwitch {
PaddleSwap(KeyerConfigurator& c): ConfigSwitch(), config(c) {}
virtual void set(bool on) { ; }
virtual bool get() const { return false(); }
private: KeyerConfigurator& config;
} paddleSwap;
/*!
* @brief An inner class that supports changing the keyer speed.
*/
struct KeyerSpeed : public ConfigInteger {
KeyerSpeed(KeyerConfigurator& c): ConfigInteger(KEYER_MIN_SPEED, KEYER_MAX_SPEED), config(c) {}
virtual void onSet(int val) { config.keyer.setWPM(val); }
virtual int get { return config.keyer.getWPM(); }
private: KeyerConfigurator& config;
} keyerSpeed;
private:
Keyer& keyer;
bool iambicAB;
bool isBug;
} keyerConfigurator(Keyer);
/**********************************************************************/
/**********************************************************************/
class MenuItem {
public:
MenuItem(int idno, const char* title, int numOpt, int defOpt, ): myID(idno), myTitle(title), numOptions(numOpt), selected(defOpt) {}
virtual ~MenuItem() = 0;
inline void id() { return myID; }
inline void writeTitle(char* outbuf, int maxlen) { strncpy(outbuf, myTitle, maxlen); }
inline char* writeOption(char* outbuf, int o = -1, int maxlen = MAX_MENU_OPTION_LEN) {
if (o == -1) {
setOptionText(selected);
} else if ((o >= 0) && (o < numOptions)) {
setOptionTitle(o);
} else {
memset(myOption, '\0', MAX_MENU_OPTION_LEN);
}
return strncpy(outbuf, myOption, maxlen);
}
inline int getNumOptions() { return numOptions; }
inline int getSelected() { return selected; }
inline int nextOption(bool doUpdate = true) {
selected = (selected + 1) % numOptions;
if (doUpdate) update();
return selected;
}
inline int prevOption(bool doUpdate = true) {
selected = (selected - 1) % numOptions;
if (doUpdate) update();
return selected;
}
inline int gotoOption(int o, bool doUpdate = true) {
selected = o >= numOptions ? numOptions : (o < 0 ? 0 : o);
if (doUpdate) update();
return selected;
}
virtual void update() = 0;
private:
int myID;
char myTitle[MAX_MENU_TITLE_LEN] = {'\0'};
char myOption[MAX_MENU_OPTION_LEN] = {'\0'};
int numOptions;
int selected;
};
class StepItem : public MenuItem {
public:
StepItem(int idno, const char* title, int numOpt, int defOpt): MenuItem(idno, title, numOpt, defOpt) {}
};
static const char off_str[] = "OFF";
static const char on_str[] = "ON";
static const char line_str[] = "LINE";
static const char usb_str[] = "USB";
static const char key_a_str[] = "A";
static const char key_b_str[] = "B";
class ToggleItem : public MenuItem {
public:
ToggleItem(int idno, const char* title, const char* off, const char* on, int defOpt): MenuItem(idno, title, 2, defOpt) {}
};
/**********************************************************************/
struct MenuConfig {
byte sidetoneVolume = 9;
byte ssbLoCut = 0;
byte ssbHiCut = 5;
byte dataLoCut = 0;
byte dataHiCut = 0;
byte keyerAB = 0;
byte sidetonePitch = 6;
};
// CAT COMMANDS - BASIC
// KS - Sets and reads the Keying speed.
IntegerItem ("KS", "KEYER SPEED", 0, 2, keyerConfigurator.keyerSpeed),
ArrayItem ("SH", "RX HI CUT ", 0, 2, dspConfigurator.ssbRxHiCut),
ArrayItem ("SL", "RX LO CUT ", 0, 2, dspConfigurator.ssbRxLoCut),
// CAT COMMANDS - EX MENU
// Sidetone volume
Steps {004, "ST VOL ", 10, [](auto x) { return static_cast<double>(x-48)/9.0; }},
// SSB/AM Low Cut transmit filter (Hz)
Steps {025, "SSB TX LO ", 6, [](auto x) { return txLowCutFilter[x]; }},
// SSB/AM High Cut transmit filter (Hz)
Steps {026, "SSB TX HI ", 6, [](auto x) { return txHighCutFilter[x]; }},
// SSB-DATA Low Cut transmit filter (Hz)
Steps {027, "DATA TX LO ", 6, [](auto x) { return txLowCutFilter[x]; }},
// SSB-DATA High Cut transmit filter (Hz)
Steps {028, "DATA TX HI ", 6, [](auto x) { return txHighCutFilter[x]; }},
// Electronic keyer operation mode
ToggleItem (032, "KEYER A/B ", "A ", "B ", keyerConfigurator.iambicMode),
// Sidetone/ pitch frequency setting (Hz)
Steps {034, "ST PITCH ", 15, [](auto x) { return 300+(x*50); }},
// Keying weight ratio
StepsSpec {036, "KEYER WEIGHT", 17, ...},
// Bug key function
ToggleItem (038, "KEYER BUG ", "OFF ", "ON ", keyerConfigurator.bugMode),
// Paddle dot/dash replacement setting
ToggleItem (039, "KEYER SWAP ", "OFF ", "ON ", keyerConfigurator.paddleSwap),
// Auto CW TX in SSB mode
//ToggleItem (041, "AUTO CW TX ", "OFF ", "ON ", [&Rig](bool on) { Rig.setKeyerAutoTransmitCW(on); } ),
// Time-out Timer
//StepsSpec {049, "TIMEOUT ", 6, ... },
// Transmit inhibit
ToggleItem (060, "TX INHIBIT ", "OFF ", "ON ", [&Rig](bool on) { Rig.setTransmitInhibit(on); } ),
// DATA moduleation line
ToggleItem (063, "DATA LINE ", "LINE", "USB ", [&Rig](bool usb) { Rig.setDataInputLine(usb); } ),
// USB audio input level
Steps {064, "USB IN LVL ", [](auto x) { return static_cast<double>(x-48)/9.0; }},
// USB audio output level
Steps {065, "USB OUT LVL ", [](auto x) { return static_cast<double>(x-48)/9.0; }},
// ACC2 terminal AF input level
Steps {066, "LINE IN LVL ", [](auto x) { return static_cast<double>(x-48)/9.0; }},
// ACC2 terminal AF output level
Steps {067, "LINE OUT LVL", [](auto x) { return static_cast<double>(x-48)/9.0; }},
// DATA VOX
ToggleItem (069, "DATA VOX ", "OFF ", "ON ", [&Rig](bool on) { Rig.setDataVoxOn(on); } ),
// DATA VOX delay
Steps {070, "DATA VOX DEL", 20, ...},
// DATA VOX gain for USB audio input
Steps {071, "USB VOX LVL ", 10, [](auto x) { return static_cast<double>(x-48)/9.0; }},
// DATA VOX gain for ACC2 terminal input
Steps {072, "LINE VOX LVL", 10, [](auto x) { return static_cast<double>(x-48)/9.0; }},