2024-02-21 10:45:46 +01:00
|
|
|
#include <cmath>
|
2024-02-06 15:50:50 +01:00
|
|
|
#include <stdio.h>
|
2024-02-10 23:26:53 +01:00
|
|
|
|
2024-02-19 15:07:29 +01:00
|
|
|
#include "bsp/board.h"
|
2024-02-21 10:45:46 +01:00
|
|
|
#include "hardware/adc.h"
|
2024-02-14 10:13:50 +01:00
|
|
|
#include "pico/multicore.h"
|
2024-02-16 20:56:03 +01:00
|
|
|
#include "pico/stdlib.h"
|
2024-02-14 10:13:50 +01:00
|
|
|
#include "pico/util/queue.h"
|
2024-02-19 14:23:33 +01:00
|
|
|
#include "tusb.h"
|
2024-02-06 15:50:50 +01:00
|
|
|
|
2024-02-10 23:26:53 +01:00
|
|
|
#include "keyer.h"
|
2024-02-16 20:56:03 +01:00
|
|
|
#include "settings.h"
|
2024-02-19 15:07:29 +01:00
|
|
|
#include "tusb_config.h"
|
2024-02-06 22:11:58 +01:00
|
|
|
|
|
|
|
namespace
|
|
|
|
{
|
2024-02-13 09:29:13 +01:00
|
|
|
|
2024-02-06 16:16:18 +01:00
|
|
|
}
|
2024-02-12 13:48:58 +01:00
|
|
|
|
|
|
|
extern const uint LED_PIN = PICO_DEFAULT_LED_PIN;
|
2024-02-10 23:51:55 +01:00
|
|
|
extern const uint LEFT_PADDLE_PIN = 14;
|
2024-02-12 13:48:58 +01:00
|
|
|
extern const uint RIGHT_PADDLE_PIN = 15;
|
2024-02-15 12:32:54 +01:00
|
|
|
extern const uint BUZZER_PIN = 18;
|
2024-02-18 16:53:49 +01:00
|
|
|
extern const uint CW_OUT_PIN = 17;
|
2024-02-21 12:08:25 +01:00
|
|
|
//extern const uint AUDIO_OUT_PIN = 16;
|
2024-02-21 10:45:46 +01:00
|
|
|
extern const uint ADC_PIN = 26;
|
2024-02-06 15:50:50 +01:00
|
|
|
|
2024-02-14 10:49:38 +01:00
|
|
|
// Stuff for communicating between cores
|
2024-02-16 20:56:03 +01:00
|
|
|
enum class KeyerQueueCommand {
|
2024-02-14 10:49:38 +01:00
|
|
|
Run,
|
|
|
|
Stop,
|
|
|
|
Config,
|
2024-02-14 11:32:09 +01:00
|
|
|
Wait,
|
2024-02-14 10:49:38 +01:00
|
|
|
};
|
2024-02-16 20:56:03 +01:00
|
|
|
struct KeyerQueueData {
|
2024-02-14 10:49:38 +01:00
|
|
|
KeyerQueueCommand cmd;
|
|
|
|
uint8_t wpm;
|
|
|
|
Mode mode;
|
|
|
|
};
|
|
|
|
|
2024-02-14 10:13:50 +01:00
|
|
|
queue_t keyerQueue;
|
|
|
|
|
2024-02-09 14:05:15 +01:00
|
|
|
void setup()
|
2024-02-06 15:50:50 +01:00
|
|
|
{
|
2024-02-12 13:48:58 +01:00
|
|
|
stdio_init_all();
|
2024-02-07 11:15:41 +01:00
|
|
|
gpio_init(LED_PIN);
|
|
|
|
gpio_set_dir(LED_PIN, GPIO_OUT);
|
|
|
|
gpio_put(LED_PIN, 0);
|
2024-02-06 15:50:50 +01:00
|
|
|
|
2024-02-09 14:05:15 +01:00
|
|
|
// Setup pins for left and right paddles
|
|
|
|
gpio_init(LEFT_PADDLE_PIN);
|
|
|
|
gpio_set_dir(LEFT_PADDLE_PIN, GPIO_IN);
|
2024-02-11 15:45:12 +01:00
|
|
|
gpio_pull_up(LEFT_PADDLE_PIN);
|
2024-02-09 14:05:15 +01:00
|
|
|
gpio_init(RIGHT_PADDLE_PIN);
|
|
|
|
gpio_set_dir(RIGHT_PADDLE_PIN, GPIO_IN);
|
2024-02-11 15:45:12 +01:00
|
|
|
gpio_pull_up(RIGHT_PADDLE_PIN);
|
2024-02-18 10:21:54 +01:00
|
|
|
gpio_init(CW_OUT_PIN);
|
|
|
|
gpio_set_dir(CW_OUT_PIN, GPIO_OUT);
|
|
|
|
gpio_put(CW_OUT_PIN, 0);
|
2024-02-21 10:45:46 +01:00
|
|
|
|
|
|
|
// Setup ADC
|
|
|
|
adc_init();
|
|
|
|
gpio_init(ADC_PIN);
|
|
|
|
adc_select_input(0);
|
2024-02-09 14:05:15 +01:00
|
|
|
}
|
|
|
|
|
2024-02-14 10:49:38 +01:00
|
|
|
/* Let's do all the keying stuff in the second core, so there are no timing problems. */
|
2024-02-14 10:13:50 +01:00
|
|
|
void core1_main()
|
|
|
|
{
|
2024-02-21 10:45:46 +01:00
|
|
|
flash_safe_execute_core_init();
|
2024-02-14 18:13:09 +01:00
|
|
|
printf("Hello from core1!\n");
|
2024-02-14 10:49:38 +01:00
|
|
|
KeyerQueueData data;
|
|
|
|
queue_remove_blocking(&keyerQueue, &data);
|
2024-02-14 10:13:50 +01:00
|
|
|
|
2024-02-14 10:49:38 +01:00
|
|
|
Keyer keyer(data.wpm, data.mode);
|
2024-02-14 10:13:50 +01:00
|
|
|
|
2024-02-16 20:56:03 +01:00
|
|
|
while (true) {
|
2024-02-14 10:49:38 +01:00
|
|
|
queue_try_remove(&keyerQueue, &data);
|
|
|
|
|
2024-02-16 20:56:03 +01:00
|
|
|
switch (data.cmd) {
|
2024-02-14 10:49:38 +01:00
|
|
|
case KeyerQueueCommand::Run:
|
|
|
|
keyer.run();
|
|
|
|
break;
|
|
|
|
case KeyerQueueCommand::Stop:
|
2024-02-14 11:32:09 +01:00
|
|
|
keyer.stop();
|
|
|
|
data.cmd = KeyerQueueCommand::Wait;
|
2024-02-14 10:49:38 +01:00
|
|
|
break;
|
|
|
|
case KeyerQueueCommand::Config:
|
2024-02-14 11:32:09 +01:00
|
|
|
keyer.setSpeed(data.wpm);
|
|
|
|
keyer.setMode(data.mode);
|
2024-02-14 10:49:38 +01:00
|
|
|
data.cmd = KeyerQueueCommand::Run;
|
|
|
|
break;
|
2024-02-14 11:32:09 +01:00
|
|
|
case KeyerQueueCommand::Wait:
|
|
|
|
break;
|
2024-02-14 10:49:38 +01:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2024-02-14 10:13:50 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-21 10:45:46 +01:00
|
|
|
[[maybe_unused]] static void echo_serial_port(uint8_t itf, uint8_t buf[], uint32_t count)
|
2024-02-19 15:07:29 +01:00
|
|
|
{
|
2024-02-21 10:45:46 +01:00
|
|
|
for (uint32_t i = 0; i < count; i++) {
|
|
|
|
tud_cdc_n_write_char(itf, buf[i]);
|
|
|
|
}
|
2024-02-19 15:07:29 +01:00
|
|
|
|
2024-02-21 10:45:46 +01:00
|
|
|
tud_cdc_n_write_flush(itf);
|
2024-02-19 15:07:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void cdc_task()
|
|
|
|
{
|
|
|
|
const uint8_t UsbInIf = 1;
|
|
|
|
|
|
|
|
if (tud_cdc_n_available(UsbInIf)) {
|
|
|
|
uint8_t buf[64];
|
|
|
|
|
|
|
|
uint32_t count = tud_cdc_n_read(UsbInIf, buf, sizeof(buf));
|
|
|
|
if (count > 1) {
|
|
|
|
printf("Command received …\n");
|
|
|
|
switch (buf[0]) {
|
2024-02-21 10:45:46 +01:00
|
|
|
case 0: // ADMIN COMMAND
|
2024-02-19 15:07:29 +01:00
|
|
|
switch (buf[1]) {
|
2024-02-21 10:45:46 +01:00
|
|
|
case 2: // Host Open
|
|
|
|
// TODO: send back revision code
|
|
|
|
default:
|
2024-02-19 15:07:29 +01:00
|
|
|
printf("Unknown admin command.\n");
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2024-02-19 15:40:58 +01:00
|
|
|
printf("Unknown command: %d.\n", buf[0]);
|
2024-02-19 15:07:29 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-21 10:45:46 +01:00
|
|
|
/* Returns the voltage level in percent (3,3V == 100%) */
|
|
|
|
float potiRead()
|
|
|
|
{
|
|
|
|
// 12-bit conversion, assume max value == ADC_VREF == 3.3 V
|
|
|
|
const float conversion_factor = 3.3f / (1 << 12);
|
|
|
|
float voltage = adc_read() * conversion_factor;
|
|
|
|
|
|
|
|
return voltage * 100 / 3.3;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Calculates the WPM speed from the volt percentage */
|
|
|
|
uint8_t calcWPM(float percent, uint8_t wpmMin, uint8_t wpmMax)
|
|
|
|
{
|
|
|
|
auto wpm = (percent * (wpmMax - wpmMin) / 100) + wpmMin;
|
|
|
|
uint8_t result = static_cast<uint8_t>(std::round(wpm));
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2024-02-09 14:05:15 +01:00
|
|
|
int main()
|
|
|
|
{
|
2024-02-21 10:45:46 +01:00
|
|
|
timer_hw->dbgpause = 0; // workaround for problem with debug and sleep_ms
|
2024-02-16 20:56:03 +01:00
|
|
|
// https://github.com/raspberrypi/pico-sdk/issues/1152#issuecomment-1418248639
|
2024-02-10 23:26:53 +01:00
|
|
|
|
2024-02-09 14:05:15 +01:00
|
|
|
setup();
|
2024-02-19 14:23:33 +01:00
|
|
|
board_init();
|
|
|
|
tud_init(BOARD_TUD_RHPORT);
|
2024-02-19 15:07:29 +01:00
|
|
|
|
2024-02-14 18:13:09 +01:00
|
|
|
printf("Hello from core0!\n");
|
|
|
|
|
2024-02-21 11:13:53 +01:00
|
|
|
queue_init(&keyerQueue, sizeof(KeyerQueueData), 2);
|
|
|
|
multicore_reset_core1();
|
|
|
|
multicore_launch_core1(core1_main);
|
|
|
|
|
|
|
|
Settings settings {read_settings()};
|
2024-02-21 12:03:10 +01:00
|
|
|
|
|
|
|
uint8_t currentWpm {0};
|
|
|
|
uint8_t lastWpm {0};
|
|
|
|
|
|
|
|
// If WPM in settings is set to 0 -> take speed from poti
|
2024-02-21 10:45:46 +01:00
|
|
|
if (settings.wpm == 0) {
|
|
|
|
currentWpm = calcWPM(potiRead(), settings.wpmPotiMin, settings.wpmPotiMax);
|
|
|
|
} else {
|
|
|
|
currentWpm = settings.wpm;
|
|
|
|
}
|
|
|
|
lastWpm = currentWpm;
|
2024-02-07 11:15:41 +01:00
|
|
|
|
2024-02-21 10:45:46 +01:00
|
|
|
KeyerQueueData keyerQueueData {KeyerQueueCommand::Run, currentWpm, settings.mode};
|
2024-02-14 10:49:38 +01:00
|
|
|
queue_add_blocking(&keyerQueue, &keyerQueueData);
|
2024-02-10 23:26:53 +01:00
|
|
|
|
2024-02-16 20:56:03 +01:00
|
|
|
while (true) {
|
2024-02-19 14:23:33 +01:00
|
|
|
tud_task();
|
2024-02-19 15:07:29 +01:00
|
|
|
cdc_task();
|
2024-02-21 10:45:46 +01:00
|
|
|
|
|
|
|
currentWpm = calcWPM(potiRead(), settings.wpmPotiMin, settings.wpmPotiMax);
|
2024-02-21 12:03:10 +01:00
|
|
|
|
|
|
|
// If WPM in settings is set to 0 -> take speed from poti
|
|
|
|
if (settings.wpm == 0 && (currentWpm != lastWpm)) {
|
2024-02-21 10:45:46 +01:00
|
|
|
KeyerQueueData keyerQueueData {KeyerQueueCommand::Config, currentWpm, settings.mode};
|
|
|
|
queue_add_blocking(&keyerQueue, &keyerQueueData);
|
|
|
|
printf("WPM has changed to: %d\n", currentWpm);
|
|
|
|
lastWpm = currentWpm;
|
|
|
|
}
|
|
|
|
|
2024-02-21 12:03:10 +01:00
|
|
|
//busy_wait_ms(1000);
|
2024-02-14 10:49:38 +01:00
|
|
|
}
|
2024-02-07 09:32:11 +01:00
|
|
|
|
2024-02-06 15:50:50 +01:00
|
|
|
return 0;
|
|
|
|
}
|