vail-adapter/keyers.cpp

424 lines
8.8 KiB
C++
Raw Permalink Normal View History

2022-05-22 21:55:22 -06:00
#include <stddef.h>
#include "keyers.h"
#define len(t) (sizeof(t)/sizeof(*t))
// Queue Set: A Set you can shift and pop.
class QSet {
int arr[MAX_KEYER_QUEUE];
unsigned int arrlen = 0;
public:
int shift() {
if (arrlen == 0) {
return -1;
}
int ret = arr[0];
arrlen--;
for (int i = 0; i < arrlen; i++) {
arr[i] = arr[i+1];
}
return ret;
}
int pop() {
if (arrlen == 0) {
return -1;
}
int ret = arr[arrlen];
arrlen--;
return ret;
}
void add(int val) {
2022-05-28 21:23:26 -06:00
if (arrlen == MAX_KEYER_QUEUE) {
2022-05-22 21:55:22 -06:00
return;
}
for (int i = 0; i < arrlen; i++) {
2022-05-28 21:23:26 -06:00
if (arr[i] == val) {
2022-05-22 21:55:22 -06:00
return;
}
}
arr[arrlen] = val;
arrlen++;
}
};
class StraightKeyer: public Keyer {
public:
bool transmitting = false;
unsigned int ditDuration = 100;
2022-05-22 21:55:22 -06:00
bool txRelays[2];
2022-05-28 15:18:28 -06:00
StraightKeyer() {
2022-05-22 21:55:22 -06:00
this->Reset();
}
char *Name() {
return "straight";
2022-05-22 21:55:22 -06:00
}
2022-06-26 10:55:28 -06:00
void SetDitDuration(unsigned int duration) {
2022-05-22 21:55:22 -06:00
this->ditDuration = duration;
}
void Reset() {
this->transmitting = false;
2022-05-28 15:18:28 -06:00
}
2022-05-22 21:55:22 -06:00
bool TxClosed() {
for (int i = 0; i < len(this->txRelays); i++) {
if (this->TxClosed(i)) {
return true;
}
}
return false;
}
bool TxClosed(int relay) {
return this->txRelays[relay];
}
void Tx(int relay, bool closed) {
bool wasClosed = this->TxClosed();
this->txRelays[relay] = closed;
this->transmitting = this->TxClosed();
2022-05-22 21:55:22 -06:00
}
void Key(Paddle key, bool pressed) {
this->Tx(key, pressed);
}
bool Tick(unsigned long now) {
return this->transmitting;
}
2022-05-22 21:55:22 -06:00
};
class BugKeyer: public StraightKeyer {
public:
2022-05-28 15:18:28 -06:00
unsigned int nextPulse = 0;
2022-05-22 21:55:22 -06:00
bool keyPressed[2];
using StraightKeyer::StraightKeyer;
char *Name() {
return "bug";
}
2022-05-22 21:55:22 -06:00
void Reset() {
StraightKeyer::Reset();
2022-05-28 15:18:28 -06:00
this->nextPulse = 0;
2022-05-22 21:55:22 -06:00
this->keyPressed[0] = false;
this->keyPressed[1] = false;
}
void Key(Paddle key, bool pressed) {
this->keyPressed[key] = pressed;
if (key == 0) {
this->beginPulsing();
} else {
StraightKeyer::Key(key, pressed);
}
}
bool Tick(unsigned long now) {
if (this->nextPulse && (now >= this->nextPulse)) {
this->pulse(now);
2022-05-28 15:18:28 -06:00
}
return this->transmitting;
2022-05-28 15:18:28 -06:00
}
2022-05-22 21:55:22 -06:00
void beginPulsing() {
2022-05-28 15:38:10 -06:00
if (!this->nextPulse) {
this->nextPulse = 1;
}
2022-05-22 21:55:22 -06:00
}
virtual void pulse(unsigned int now) {
2022-05-22 21:55:22 -06:00
if (this->TxClosed(0)) {
this->Tx(0, false);
} else if (this->keyPressed[0]) {
this->Tx(0, true);
} else {
2022-05-28 15:18:28 -06:00
this->nextPulse = 0;
2022-05-22 21:55:22 -06:00
return;
}
this->nextPulse = now + this->ditDuration;
2022-05-22 21:55:22 -06:00
}
};
class ElBugKeyer: public BugKeyer {
public:
unsigned int nextRepeat;
using BugKeyer::BugKeyer;
char *Name() {
return "el bug";
}
2022-05-22 21:55:22 -06:00
void Reset() {
BugKeyer::Reset();
this->nextRepeat = -1;
}
// Return which key is pressed. If none, return -1.
int whichKeyPressed() {
for (int i = 0; i < len(this->keyPressed); i++) {
if (this->keyPressed[i]) {
return i;
}
}
return -1;
}
void Key(Paddle key, bool pressed) {
this->keyPressed[key] = pressed;
if (pressed) {
this->nextRepeat = key;
2022-05-28 15:18:28 -06:00
this->beginPulsing();
2022-05-22 21:55:22 -06:00
} else {
this->nextRepeat = this->whichKeyPressed();
}
}
unsigned int keyDuration(int key) {
switch (key) {
2022-05-28 15:18:28 -06:00
case PADDLE_DIT:
2022-05-22 21:55:22 -06:00
return this->ditDuration;
2022-05-28 15:18:28 -06:00
case PADDLE_DAH:
return 3 * (this->ditDuration);
2022-05-22 21:55:22 -06:00
}
2022-05-28 15:18:28 -06:00
return this->ditDuration; // XXX
2022-05-22 21:55:22 -06:00
}
2022-05-28 15:18:28 -06:00
virtual int nextTx() {
2022-05-22 21:55:22 -06:00
if (this->whichKeyPressed() == -1) {
return -1;
}
return this->nextRepeat;
}
virtual void pulse(unsigned int now) {
2022-05-22 21:55:22 -06:00
int nextPulse = 0;
if (this->TxClosed(0)) {
// Pause if we're currently transmitting
2022-05-28 15:18:28 -06:00
nextPulse = this->keyDuration(PADDLE_DIT);
2022-05-22 21:55:22 -06:00
this->Tx(0, false);
} else {
int next = this->nextTx();
if (next >= 0) {
nextPulse = this->keyDuration(next);
this->Tx(0, true);
}
}
if (nextPulse) {
this->nextPulse = now + nextPulse;
2022-05-22 21:55:22 -06:00
} else {
2022-05-28 15:18:28 -06:00
this->nextPulse = 0;
2022-05-22 21:55:22 -06:00
}
}
};
class UltimaticKeyer: public ElBugKeyer {
public:
2022-05-28 15:38:10 -06:00
QSet queue;
2022-05-22 21:55:22 -06:00
using ElBugKeyer::ElBugKeyer;
char *Name() {
return "ultimatic";
}
2022-05-22 21:55:22 -06:00
void Key(Paddle key, bool pressed) {
if (pressed) {
2022-05-28 15:38:10 -06:00
this->queue.add(key);
2022-05-22 21:55:22 -06:00
}
ElBugKeyer::Key(key, pressed);
}
2022-05-28 15:18:28 -06:00
virtual int nextTx() {
2022-05-28 15:38:10 -06:00
int key = this->queue.shift();
2022-05-22 21:55:22 -06:00
if (key != -1) {
return key;
}
return ElBugKeyer::nextTx();
}
};
class SingleDotKeyer: public ElBugKeyer {
public:
2022-05-28 15:38:10 -06:00
QSet queue;
2022-05-22 21:55:22 -06:00
using ElBugKeyer::ElBugKeyer;
char *Name() {
return "single dot";
}
2022-05-22 21:55:22 -06:00
void Key(Paddle key, bool pressed) {
2022-05-28 15:38:10 -06:00
if (pressed && (key == PADDLE_DIT)) {
this->queue.add(key);
2022-05-22 21:55:22 -06:00
}
ElBugKeyer::Key(key, pressed);
}
2022-05-28 15:18:28 -06:00
virtual int nextTx() {
2022-05-28 15:38:10 -06:00
int key = this->queue.shift();
2022-05-22 21:55:22 -06:00
if (key != -1) {
return key;
}
if (this->keyPressed[1]) return 1;
if (this->keyPressed[0]) return 0;
return -1;
}
};
class IambicKeyer: public ElBugKeyer {
public:
using ElBugKeyer::ElBugKeyer;
char *Name() {
return "iambic plain";
}
2022-05-28 15:18:28 -06:00
virtual int nextTx() {
2022-05-22 21:55:22 -06:00
int next = ElBugKeyer::nextTx();
2022-05-28 15:38:10 -06:00
if (this->keyPressed[PADDLE_DIT] && this->keyPressed[PADDLE_DAH]) {
2022-05-22 21:55:22 -06:00
this->nextRepeat = 1 - this->nextRepeat;
}
return next;
}
};
class IambicAKeyer: public IambicKeyer {
public:
2022-05-28 15:38:10 -06:00
QSet queue;
2022-05-22 21:55:22 -06:00
using IambicKeyer::IambicKeyer;
char *Name() {
return "iambic a";
}
2022-05-22 21:55:22 -06:00
void Key(Paddle key, bool pressed) {
2022-05-28 15:38:10 -06:00
if (pressed && (key == PADDLE_DIT)) {
this->queue.add(key);
2022-05-22 21:55:22 -06:00
}
IambicKeyer::Key(key, pressed);
}
2022-05-28 15:18:28 -06:00
virtual int nextTx() {
2022-05-22 21:55:22 -06:00
int next = IambicKeyer::nextTx();
2022-05-28 15:38:10 -06:00
int key = this->queue.shift();
2022-05-22 21:55:22 -06:00
if (key != -1) {
return key;
}
return next;
}
};
class IambicBKeyer: public IambicKeyer {
public:
2022-05-28 15:38:10 -06:00
QSet queue;
int sending;
2022-05-22 21:55:22 -06:00
using IambicKeyer::IambicKeyer;
char *Name() {
return "iambic b";
}
2022-05-22 21:55:22 -06:00
void Reset() {
this->sending = -1;
2022-05-22 21:55:22 -06:00
IambicKeyer::Reset();
}
void Key(Paddle key, bool pressed) {
if (pressed && (this->sending != key)) {
2022-05-28 15:38:10 -06:00
this->queue.add(key);
2022-05-22 21:55:22 -06:00
}
IambicKeyer::Key(key, pressed);
}
2022-05-28 15:18:28 -06:00
virtual int nextTx() {
2022-05-28 15:38:10 -06:00
for (int key = 0; key < len(this->keyPressed); key++) {
2022-05-22 21:55:22 -06:00
if (this->keyPressed[key]) {
2022-05-28 15:38:10 -06:00
this->queue.add(key);
2022-05-22 21:55:22 -06:00
}
}
this->sending = this->queue.shift();
return this->sending;
2022-05-22 21:55:22 -06:00
}
};
class KeyaheadKeyer: public ElBugKeyer {
public:
int queue[MAX_KEYER_QUEUE];
unsigned int qlen;
using ElBugKeyer::ElBugKeyer;
char *Name() {
return "keyahead";
}
2022-05-22 21:55:22 -06:00
void Reset() {
ElBugKeyer::Reset();
this->qlen = 0;
}
void Key(Paddle key, bool pressed) {
if (pressed) {
if (this->qlen < MAX_KEYER_QUEUE) {
this->queue[this->qlen++] = key;
}
}
ElBugKeyer::Key(key, pressed);
}
2022-05-28 15:18:28 -06:00
virtual int nextTx() {
2022-05-22 21:55:22 -06:00
if (this->qlen > 0) {
int next = this->queue[0];
this->qlen--;
for (int i = 0; i < this->qlen; i++) {
this->queue[i] = this->queue[i+1];
}
return next;
}
return ElBugKeyer::nextTx();
}
};
2022-05-28 15:38:10 -06:00
StraightKeyer straightKeyer = StraightKeyer();
BugKeyer bugKeyer = BugKeyer();
ElBugKeyer elBugKeyer = ElBugKeyer();
SingleDotKeyer singleDotKeyer = SingleDotKeyer();
UltimaticKeyer ultimaticKeyer = UltimaticKeyer();
IambicKeyer iambicKeyer = IambicKeyer();
IambicAKeyer iambicAKeyer = IambicAKeyer();
IambicBKeyer iambicBKeyer = IambicBKeyer();
KeyaheadKeyer keyaheadKeyer = KeyaheadKeyer();
2022-05-28 15:18:28 -06:00
Keyer *AllKeyers[] = {
2022-05-28 15:38:10 -06:00
&straightKeyer,
&bugKeyer,
&elBugKeyer,
&singleDotKeyer,
&ultimaticKeyer,
&iambicKeyer,
&iambicAKeyer,
&iambicBKeyer,
&keyaheadKeyer,
2022-05-28 15:18:28 -06:00
};
Keyer *GetKeyerByNumber(int n) {
if (n >= len(AllKeyers)) {
return NULL;
}
2022-05-28 15:18:28 -06:00
return AllKeyers[n];
}