first attempt to send messages
This commit is contained in:
parent
c57f9251c2
commit
e8901e514d
5 changed files with 230 additions and 26 deletions
168
src/keyer.cpp
168
src/keyer.cpp
|
@ -47,13 +47,147 @@ void Keyer::setSpeed(uint8_t wpm)
|
||||||
m_elementDuration = calcElementDurationUs(wpm);
|
m_elementDuration = calcElementDurationUs(wpm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Keyer::sendMessage(const std::string &msg)
|
||||||
|
{
|
||||||
|
for (auto c : msg) {
|
||||||
|
m_messageQueue.push(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Keyer::run()
|
void Keyer::run()
|
||||||
{
|
{
|
||||||
auto timestamp = get_absolute_time();
|
auto timestamp = get_absolute_time();
|
||||||
|
|
||||||
// If there is something to send …
|
// If there is something to send …
|
||||||
if (!m_messageQueue.empty()) {
|
if (!m_messageQueue.empty() || m_messageKeyingState != MessageState::Wait) {
|
||||||
// TODO
|
// Stop all paddle keying, if necessary
|
||||||
|
if (m_PaddleKeyingState != State::Wait) {
|
||||||
|
gpio_put(LED_PIN, 0);
|
||||||
|
gpio_put(CW_OUT_PIN, 0);
|
||||||
|
m_buzzer.off();
|
||||||
|
m_keyNextIambicB = false;
|
||||||
|
m_currentlyPausing = false;
|
||||||
|
m_currentlyKeying = false;
|
||||||
|
m_previousState = State::Abort;
|
||||||
|
m_PaddleKeyingState = State::Wait;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (m_messageKeyingState) {
|
||||||
|
case MessageState::Wait:
|
||||||
|
m_messageChar = m_messageQueue.front();
|
||||||
|
|
||||||
|
switch (m_messageChar) {
|
||||||
|
case '.':
|
||||||
|
m_messageKeyingState = MessageState::Dit;
|
||||||
|
break;
|
||||||
|
case '-':
|
||||||
|
m_messageKeyingState = MessageState::Dit;
|
||||||
|
break;
|
||||||
|
case 'i':
|
||||||
|
m_messageKeyingState = MessageState::IntraCharSpace;
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
m_messageKeyingState = MessageState::InterCharSpace;
|
||||||
|
break;
|
||||||
|
case 'w':
|
||||||
|
m_messageKeyingState = MessageState::InterWordSpace;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case MessageState::Dit:
|
||||||
|
if (!m_currentlyKeying) {
|
||||||
|
m_currentlyKeying = true;
|
||||||
|
m_keying_until = make_timeout_time_us(m_elementDuration);
|
||||||
|
gpio_put(LED_PIN, 1);
|
||||||
|
gpio_put(CW_OUT_PIN, 1);
|
||||||
|
m_buzzer.on(SIDETONE_FREQ);
|
||||||
|
}
|
||||||
|
if (left_paddle_pressed() || right_paddle_pressed()) {
|
||||||
|
m_messageKeyingState = MessageState::Abort;
|
||||||
|
}
|
||||||
|
if (absolute_time_diff_us(timestamp, m_keying_until) <= 0) {
|
||||||
|
m_currentlyKeying = false;
|
||||||
|
gpio_put(LED_PIN, 0);
|
||||||
|
gpio_put(CW_OUT_PIN, 0);
|
||||||
|
m_buzzer.off();
|
||||||
|
m_messageKeyingState = MessageState::Wait;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MessageState::Dah:
|
||||||
|
if (!m_currentlyKeying) {
|
||||||
|
m_currentlyKeying = true;
|
||||||
|
m_keying_until = make_timeout_time_us(m_elementDuration * 3);
|
||||||
|
gpio_put(LED_PIN, 1);
|
||||||
|
gpio_put(CW_OUT_PIN, 1);
|
||||||
|
m_buzzer.on(SIDETONE_FREQ);
|
||||||
|
}
|
||||||
|
if (left_paddle_pressed() || right_paddle_pressed()) {
|
||||||
|
m_messageKeyingState = MessageState::Abort;
|
||||||
|
}
|
||||||
|
if (absolute_time_diff_us(timestamp, m_keying_until) <= 0) {
|
||||||
|
m_currentlyKeying = false;
|
||||||
|
gpio_put(LED_PIN, 0);
|
||||||
|
gpio_put(CW_OUT_PIN, 0);
|
||||||
|
m_buzzer.off();
|
||||||
|
m_messageKeyingState = MessageState::Wait;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MessageState::IntraCharSpace:
|
||||||
|
if (!m_currentlyPausing) {
|
||||||
|
m_pausing_until = make_timeout_time_us(m_elementDuration);
|
||||||
|
m_currentlyPausing = true;
|
||||||
|
}
|
||||||
|
if (left_paddle_pressed() || right_paddle_pressed()) {
|
||||||
|
m_messageKeyingState = MessageState::Abort;
|
||||||
|
}
|
||||||
|
if (absolute_time_diff_us(timestamp, m_pausing_until) <= 0) {
|
||||||
|
m_currentlyPausing = false;
|
||||||
|
m_messageKeyingState = MessageState::Wait;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MessageState::InterCharSpace:
|
||||||
|
if (!m_currentlyPausing) {
|
||||||
|
m_pausing_until = make_timeout_time_us(m_elementDuration * 3);
|
||||||
|
m_currentlyPausing = true;
|
||||||
|
}
|
||||||
|
if (left_paddle_pressed() || right_paddle_pressed()) {
|
||||||
|
m_messageKeyingState = MessageState::Abort;
|
||||||
|
}
|
||||||
|
if (absolute_time_diff_us(timestamp, m_pausing_until) <= 0) {
|
||||||
|
m_currentlyPausing = false;
|
||||||
|
m_messageKeyingState = MessageState::Wait;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MessageState::InterWordSpace:
|
||||||
|
if (!m_currentlyPausing) {
|
||||||
|
m_pausing_until = make_timeout_time_us(m_elementDuration * 7);
|
||||||
|
m_currentlyPausing = true;
|
||||||
|
}
|
||||||
|
if (left_paddle_pressed() || right_paddle_pressed()) {
|
||||||
|
m_messageKeyingState = MessageState::Abort;
|
||||||
|
}
|
||||||
|
if (absolute_time_diff_us(timestamp, m_pausing_until) <= 0) {
|
||||||
|
m_currentlyPausing = false;
|
||||||
|
m_messageKeyingState = MessageState::Wait;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MessageState::Abort:
|
||||||
|
{
|
||||||
|
gpio_put(LED_PIN, 0);
|
||||||
|
gpio_put(CW_OUT_PIN, 0);
|
||||||
|
m_buzzer.off();
|
||||||
|
m_currentlyPausing = false;
|
||||||
|
m_currentlyKeying = false;
|
||||||
|
std::queue<char> emptyQueue;
|
||||||
|
std::swap(m_messageQueue, emptyQueue);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we are in Straight key mode …
|
// If we are in Straight key mode …
|
||||||
|
@ -72,20 +206,20 @@ void Keyer::run()
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we are in IambicA or IambicB-Mode …
|
// If we are in IambicA or IambicB-Mode …
|
||||||
switch (m_state) {
|
switch (m_PaddleKeyingState) {
|
||||||
case State::Wait:
|
case State::Wait:
|
||||||
if (left_paddle_pressed()) {
|
if (left_paddle_pressed()) {
|
||||||
m_keyNextIambicB = false;
|
m_keyNextIambicB = false;
|
||||||
m_state = State::Dit;
|
m_PaddleKeyingState = State::Dit;
|
||||||
} else if (right_paddle_pressed()) {
|
} else if (right_paddle_pressed()) {
|
||||||
m_keyNextIambicB = false;
|
m_keyNextIambicB = false;
|
||||||
m_state = State::Dah;
|
m_PaddleKeyingState = State::Dah;
|
||||||
} else {
|
} else {
|
||||||
if (m_mode == Mode::IambicB && m_keyNextIambicB) {
|
if (m_mode == Mode::IambicB && m_keyNextIambicB) {
|
||||||
if (m_previousState == State::Dit)
|
if (m_previousState == State::Dit)
|
||||||
m_state = State::Dah;
|
m_PaddleKeyingState = State::Dah;
|
||||||
else
|
else
|
||||||
m_state = State::Dit;
|
m_PaddleKeyingState = State::Dit;
|
||||||
|
|
||||||
m_keyNextIambicB = false;
|
m_keyNextIambicB = false;
|
||||||
}
|
}
|
||||||
|
@ -112,7 +246,7 @@ void Keyer::run()
|
||||||
m_buzzer.off();
|
m_buzzer.off();
|
||||||
// m_audioOut.off();
|
// m_audioOut.off();
|
||||||
m_previousState = State::Dit;
|
m_previousState = State::Dit;
|
||||||
m_state = State::DitPause;
|
m_PaddleKeyingState = State::DitPause;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -137,7 +271,7 @@ void Keyer::run()
|
||||||
m_buzzer.off();
|
m_buzzer.off();
|
||||||
// m_audioOut.off();
|
// m_audioOut.off();
|
||||||
m_previousState = State::Dah;
|
m_previousState = State::Dah;
|
||||||
m_state = State::DahPause;
|
m_PaddleKeyingState = State::DahPause;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -150,13 +284,13 @@ void Keyer::run()
|
||||||
m_currentlyPausing = false;
|
m_currentlyPausing = false;
|
||||||
|
|
||||||
if (right_paddle_pressed()) {
|
if (right_paddle_pressed()) {
|
||||||
m_state = State::Dah;
|
m_PaddleKeyingState = State::Dah;
|
||||||
m_keyNextIambicB = false;
|
m_keyNextIambicB = false;
|
||||||
} else if (left_paddle_pressed()) {
|
} else if (left_paddle_pressed()) {
|
||||||
m_state = State::Dit;
|
m_PaddleKeyingState = State::Dit;
|
||||||
m_keyNextIambicB = false;
|
m_keyNextIambicB = false;
|
||||||
} else {
|
} else {
|
||||||
m_state = State::Wait;
|
m_PaddleKeyingState = State::Wait;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -170,13 +304,13 @@ void Keyer::run()
|
||||||
m_currentlyPausing = false;
|
m_currentlyPausing = false;
|
||||||
|
|
||||||
if (left_paddle_pressed()) {
|
if (left_paddle_pressed()) {
|
||||||
m_state = State::Dit;
|
m_PaddleKeyingState = State::Dit;
|
||||||
m_keyNextIambicB = false;
|
m_keyNextIambicB = false;
|
||||||
} else if (right_paddle_pressed()) {
|
} else if (right_paddle_pressed()) {
|
||||||
m_state = State::Dah;
|
m_PaddleKeyingState = State::Dah;
|
||||||
m_keyNextIambicB = false;
|
m_keyNextIambicB = false;
|
||||||
} else {
|
} else {
|
||||||
m_state = State::Wait;
|
m_PaddleKeyingState = State::Wait;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -190,11 +324,11 @@ void Keyer::run()
|
||||||
m_currentlyPausing = false;
|
m_currentlyPausing = false;
|
||||||
m_currentlyKeying = false;
|
m_currentlyKeying = false;
|
||||||
m_previousState = State::Abort;
|
m_previousState = State::Abort;
|
||||||
m_state = State::Wait;
|
m_PaddleKeyingState = State::Wait;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Keyer::stop() { m_state = State::Abort; }
|
void Keyer::stop() { m_PaddleKeyingState = State::Abort; }
|
20
src/keyer.h
20
src/keyer.h
|
@ -14,6 +14,7 @@ class Keyer final
|
||||||
|
|
||||||
void setMode(Mode mode) { m_mode = mode; }
|
void setMode(Mode mode) { m_mode = mode; }
|
||||||
void setSpeed(uint8_t wpm);
|
void setSpeed(uint8_t wpm);
|
||||||
|
void sendMessage(const std::string &msg);
|
||||||
|
|
||||||
void run();
|
void run();
|
||||||
void stop();
|
void stop();
|
||||||
|
@ -28,6 +29,16 @@ class Keyer final
|
||||||
Abort,
|
Abort,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class MessageState {
|
||||||
|
Wait,
|
||||||
|
Dit,
|
||||||
|
Dah,
|
||||||
|
IntraCharSpace,
|
||||||
|
InterCharSpace,
|
||||||
|
InterWordSpace,
|
||||||
|
Abort,
|
||||||
|
};
|
||||||
|
|
||||||
uint8_t m_wpm {18};
|
uint8_t m_wpm {18};
|
||||||
Mode m_mode {Mode::IambicB};
|
Mode m_mode {Mode::IambicB};
|
||||||
|
|
||||||
|
@ -37,12 +48,15 @@ class Keyer final
|
||||||
Sidetone m_buzzer;
|
Sidetone m_buzzer;
|
||||||
// Sidetone m_audioOut;
|
// Sidetone m_audioOut;
|
||||||
|
|
||||||
State m_state {State::Wait};
|
State m_PaddleKeyingState {State::Wait};
|
||||||
State m_previousState {State::Wait};
|
State m_previousState {State::Wait};
|
||||||
|
|
||||||
|
std::queue<char> m_messageQueue;
|
||||||
|
MessageState m_messageKeyingState {MessageState::Wait};
|
||||||
|
char m_messageChar;
|
||||||
|
|
||||||
uint64_t m_elementDuration {0};
|
uint64_t m_elementDuration {0};
|
||||||
bool m_currentlyKeying {false};
|
bool m_currentlyKeying {false};
|
||||||
bool m_currentlyPausing {false};
|
bool m_currentlyPausing {false};
|
||||||
bool m_keyNextIambicB {false};
|
bool m_keyNextIambicB {false};
|
||||||
|
|
||||||
std::queue<std::string> m_messageQueue;
|
|
||||||
};
|
};
|
|
@ -45,3 +45,47 @@ std::string refurbishMessage(const std::string &msg)
|
||||||
|
|
||||||
return msgRefurb;
|
return msgRefurb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string messageToMorse(const std::string &msg)
|
||||||
|
{
|
||||||
|
std::string refMsg = refurbishMessage(msg);
|
||||||
|
std::string morseString;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < refMsg.length(); i++) {
|
||||||
|
auto c = refMsg[i];
|
||||||
|
if (c == ' ') {
|
||||||
|
// morseString.append(" ");
|
||||||
|
morseString += 'w';
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ignore and continue with next char, if not found
|
||||||
|
auto search = morseCode.find(c);
|
||||||
|
if (search == morseCode.end()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned int j = 0; j < morseCode[c].length(); j++) {
|
||||||
|
auto m = morseCode[c][j];
|
||||||
|
if (j == 0 && i > 0 && refMsg[i - 1] != ' ') {
|
||||||
|
// morseString.append(" ");
|
||||||
|
morseString += 'c';
|
||||||
|
}
|
||||||
|
|
||||||
|
morseString += m;
|
||||||
|
|
||||||
|
if (j < morseCode[c].length() - 1) {
|
||||||
|
// morseString.append(" ");
|
||||||
|
morseString += 'i';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append word space if last char was not a blank
|
||||||
|
if (refMsg.back() != ' ') {
|
||||||
|
// morseString.append(" ");
|
||||||
|
morseString += 'w';
|
||||||
|
}
|
||||||
|
|
||||||
|
return morseString;
|
||||||
|
}
|
|
@ -2,4 +2,4 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
std::string refurbishMessage(const std::string msg);
|
std::string messageToMorse(const std::string &msg);
|
|
@ -31,11 +31,13 @@ enum class KeyerQueueCommand {
|
||||||
Stop,
|
Stop,
|
||||||
Config,
|
Config,
|
||||||
Wait,
|
Wait,
|
||||||
|
SendMessage,
|
||||||
};
|
};
|
||||||
struct KeyerQueueData {
|
struct KeyerQueueData {
|
||||||
KeyerQueueCommand cmd;
|
KeyerQueueCommand cmd;
|
||||||
uint8_t wpm;
|
uint8_t wpm;
|
||||||
Mode mode;
|
Mode mode;
|
||||||
|
std::string message;
|
||||||
};
|
};
|
||||||
|
|
||||||
queue_t keyerQueue;
|
queue_t keyerQueue;
|
||||||
|
@ -90,6 +92,9 @@ void core1_main()
|
||||||
keyer.setMode(data.mode);
|
keyer.setMode(data.mode);
|
||||||
data.cmd = KeyerQueueCommand::Run;
|
data.cmd = KeyerQueueCommand::Run;
|
||||||
break;
|
break;
|
||||||
|
case KeyerQueueCommand::SendMessage:
|
||||||
|
keyer.sendMessage(data.message);
|
||||||
|
break;
|
||||||
case KeyerQueueCommand::Wait:
|
case KeyerQueueCommand::Wait:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -179,9 +184,11 @@ int main()
|
||||||
}
|
}
|
||||||
lastWpm = currentWpm;
|
lastWpm = currentWpm;
|
||||||
|
|
||||||
KeyerQueueData keyerQueueData {KeyerQueueCommand::Run, currentWpm, settings.mode};
|
KeyerQueueData keyerQueueData {KeyerQueueCommand::Run, currentWpm, settings.mode, ""};
|
||||||
queue_add_blocking(&keyerQueue, &keyerQueueData);
|
queue_add_blocking(&keyerQueue, &keyerQueueData);
|
||||||
|
|
||||||
|
static bool used = false;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
tud_task();
|
tud_task();
|
||||||
cdc_task();
|
cdc_task();
|
||||||
|
@ -190,13 +197,18 @@ int main()
|
||||||
|
|
||||||
// If WPM in settings is set to 0 -> take speed from poti
|
// If WPM in settings is set to 0 -> take speed from poti
|
||||||
if (settings.wpm == 0 && (currentWpm != lastWpm)) {
|
if (settings.wpm == 0 && (currentWpm != lastWpm)) {
|
||||||
KeyerQueueData keyerQueueData {KeyerQueueCommand::Config, currentWpm, settings.mode};
|
KeyerQueueData keyerQueueData {KeyerQueueCommand::Config, currentWpm, settings.mode, ""};
|
||||||
queue_add_blocking(&keyerQueue, &keyerQueueData);
|
queue_add_blocking(&keyerQueue, &keyerQueueData);
|
||||||
printf("WPM has changed to: %d\n", currentWpm);
|
printf("WPM has changed to: %d\n", currentWpm);
|
||||||
lastWpm = currentWpm;
|
lastWpm = currentWpm;
|
||||||
}
|
}
|
||||||
|
|
||||||
//busy_wait_ms(1000);
|
busy_wait_ms(10000);
|
||||||
|
if (!used) {
|
||||||
|
KeyerQueueData keyerQueueData {KeyerQueueCommand::SendMessage, 0, settings.mode, "cq cq de dg2smb dg2smb pse k"};
|
||||||
|
queue_add_blocking(&keyerQueue, &keyerQueueData);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Reference in a new issue