raspikeyer/src/keyer.cpp

196 lines
5 KiB
C++
Raw Normal View History

2024-02-10 23:51:55 +01:00
#include <stdio.h>
#include "pico/stdlib.h"
2024-02-09 12:20:30 +01:00
#include "keyer.h"
2024-02-12 15:57:50 +01:00
#include "sidetone.h"
2024-02-09 12:20:30 +01:00
2024-02-12 13:48:58 +01:00
extern const uint LED_PIN;
2024-02-10 23:51:55 +01:00
extern const uint LEFT_PADDLE_PIN;
2024-02-12 13:48:58 +01:00
extern const uint RIGHT_PADDLE_PIN;
2024-02-10 23:51:55 +01:00
2024-02-12 15:57:50 +01:00
const uint SIDETONE_FREQ = 622;
2024-02-10 23:51:55 +01:00
bool left_paddle_pressed()
{
2024-02-11 15:45:12 +01:00
if (!gpio_get(LEFT_PADDLE_PIN))
2024-02-10 23:51:55 +01:00
{
return true;
}
return false;
}
2024-02-12 13:48:58 +01:00
bool right_paddle_pressed()
{
if (!gpio_get(RIGHT_PADDLE_PIN))
{
return true;
}
return false;
}
uint64_t calcElementDurationUs(uint8_t wpm)
{
uint64_t duration = static_cast<uint64_t>(1.2 / static_cast<uint64_t>(wpm) * 1000 * 1000);
return duration;
}
2024-02-13 09:00:39 +01:00
Keyer::Keyer(uint8_t wpm, Mode mode) : m_wpm(wpm), m_mode(mode)
2024-02-12 13:48:58 +01:00
{
m_elementDuration = calcElementDurationUs(m_wpm);
}
2024-02-14 11:05:33 +01:00
void Keyer::setSpeed(uint8_t wpm)
{
m_wpm = wpm;
m_elementDuration = calcElementDurationUs(wpm);
}
2024-02-09 12:20:30 +01:00
void Keyer::run()
{
2024-02-12 13:48:58 +01:00
auto timestamp = get_absolute_time();
2024-02-09 12:20:30 +01:00
switch (state)
{
2024-02-10 23:51:55 +01:00
case State::Wait:
2024-02-12 14:10:04 +01:00
if (left_paddle_pressed() && right_paddle_pressed())
{
2024-02-13 10:46:11 +01:00
m_keyNextIambicB = false;
2024-02-13 09:03:14 +01:00
if (m_previousState == State::Dit)
2024-02-13 09:00:39 +01:00
{
2024-02-12 14:10:04 +01:00
state = State::Dah;
2024-02-13 09:00:39 +01:00
}
2024-02-13 09:03:14 +01:00
else if (m_previousState == State::Dah)
2024-02-13 09:00:39 +01:00
{
2024-02-12 14:10:04 +01:00
state = State::Dit;
}
}
2024-02-13 10:46:11 +01:00
else if (left_paddle_pressed())
2024-02-12 14:10:04 +01:00
{
2024-02-13 10:46:11 +01:00
m_keyNextIambicB = false;
2024-02-11 16:26:55 +01:00
state = State::Dit;
2024-02-12 14:10:04 +01:00
}
else if (right_paddle_pressed())
{
2024-02-13 10:46:11 +01:00
m_keyNextIambicB = false;
2024-02-12 13:48:58 +01:00
state = State::Dah;
}
2024-02-13 10:46:11 +01:00
else
{
if (m_mode == Mode::IAMBIC_B && m_keyNextIambicB)
{
if (m_previousState == State::Dit)
state = State::Dah;
else
state = State::Dit;
m_keyNextIambicB = false;
}
}
2024-02-10 23:51:55 +01:00
break;
2024-02-11 16:26:55 +01:00
case State::Dit:
2024-02-12 13:48:58 +01:00
if (!m_currentlyKeying)
{
m_currentlyKeying = true;
m_keying_until = make_timeout_time_us(m_elementDuration);
gpio_put(LED_PIN, 1);
2024-02-12 15:57:50 +01:00
m_Sidetone.on(SIDETONE_FREQ);
2024-02-12 13:48:58 +01:00
}
2024-02-11 15:45:12 +01:00
else
2024-02-11 16:26:55 +01:00
{
2024-02-13 09:00:39 +01:00
if (right_paddle_pressed() && !m_keyNextIambicB)
m_keyNextIambicB = true;
2024-02-12 13:48:58 +01:00
if (absolute_time_diff_us(timestamp, m_keying_until) <= 0)
{
m_currentlyKeying = false;
gpio_put(LED_PIN, 0);
2024-02-12 15:57:50 +01:00
m_Sidetone.off();
2024-02-12 13:48:58 +01:00
m_previousState = State::Dit;
2024-02-11 16:26:55 +01:00
state = State::InterCharSpace;
2024-02-12 13:48:58 +01:00
}
2024-02-11 16:26:55 +01:00
}
break;
2024-02-12 13:48:58 +01:00
case State::Dah:
2024-02-12 14:10:04 +01:00
if (!m_currentlyKeying)
{
2024-02-12 13:48:58 +01:00
m_currentlyKeying = true;
m_keying_until = make_timeout_time_us(m_elementDuration * 3);
gpio_put(LED_PIN, 1);
2024-02-12 15:57:50 +01:00
m_Sidetone.on(SIDETONE_FREQ);
2024-02-12 14:10:04 +01:00
}
else
{
2024-02-13 09:00:39 +01:00
if (left_paddle_pressed() && !m_keyNextIambicB)
m_keyNextIambicB = true;
2024-02-12 13:48:58 +01:00
if (absolute_time_diff_us(timestamp, m_keying_until) <= 0)
{
m_currentlyKeying = false;
gpio_put(LED_PIN, 0);
2024-02-12 15:57:50 +01:00
m_Sidetone.off();
2024-02-12 13:48:58 +01:00
m_previousState = State::Dah;
state = State::InterCharSpace;
}
}
break;
2024-02-11 15:45:12 +01:00
case State::InterCharSpace:
2024-02-13 09:00:39 +01:00
if (!m_currentlyPausing)
2024-02-12 13:48:58 +01:00
{
m_pausing_until = make_timeout_time_us(m_elementDuration);
2024-02-13 09:00:39 +01:00
m_currentlyPausing = true;
2024-02-12 13:48:58 +01:00
}
// Handle the case when the other paddle is pressed during the inter character space
else if (absolute_time_diff_us(timestamp, m_pausing_until) > 0)
{
if (left_paddle_pressed() && m_previousState == State::Dah && m_nextState == State::Wait)
{
2024-02-15 13:59:30 +01:00
// printf("--- Pause --- Next state is Dit!\n");
m_nextState = State::Dit;
2024-02-11 15:45:12 +01:00
m_keyNextIambicB = right_paddle_pressed() ? true : false;
}
else if (right_paddle_pressed() && m_previousState == State::Dit && m_nextState == State::Wait)
{
2024-02-15 13:59:30 +01:00
// printf("--- Pause --- Next state is Dah!\n");
m_nextState = State::Dah;
m_keyNextIambicB = left_paddle_pressed() ? true : false;
}
else if (m_previousState == State::Wait)
{
m_nextState = State::Wait;
}
}
else
2024-02-12 14:10:04 +01:00
{
if (absolute_time_diff_us(timestamp, m_pausing_until) <= 0)
{
m_currentlyPausing = false;
state = m_nextState;
m_nextState = State::Wait;
}
2024-02-12 13:48:58 +01:00
}
2024-02-09 12:20:30 +01:00
break;
2024-02-14 11:32:09 +01:00
case State::Abort:
gpio_put(LED_PIN, 0);
m_Sidetone.off();
m_keyNextIambicB = false;
m_currentlyPausing = false;
m_currentlyKeying = false;
m_previousState = State::Abort;
m_nextState = State::Wait;
2024-02-14 11:32:09 +01:00
state = State::Wait;
break;
2024-02-09 12:20:30 +01:00
default:
break;
}
2024-02-14 11:32:09 +01:00
}
void Keyer::stop()
{
state = State::Abort;
2024-02-09 12:20:30 +01:00
}