Compare commits
No commits in common. "d1470595319cdba20e27872841dddb66afec38de" and "6f51f5e9620a83ab3b8a11457a753cb9784134c9" have entirely different histories.
d147059531
...
6f51f5e962
6 changed files with 111 additions and 150 deletions
|
@ -17,7 +17,5 @@ target_sources(raspi_keyer PRIVATE
|
||||||
keyer.cpp
|
keyer.cpp
|
||||||
sidetone.cpp
|
sidetone.cpp
|
||||||
morse.cpp
|
morse.cpp
|
||||||
winkeyer.cpp
|
|
||||||
utils.cpp
|
|
||||||
usb_descriptors.c
|
usb_descriptors.c
|
||||||
)
|
)
|
||||||
|
|
|
@ -12,8 +12,11 @@
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
#include "tusb_config.h"
|
#include "tusb_config.h"
|
||||||
#include "utils.h"
|
|
||||||
#include "winkeyer.h"
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
extern const uint LED_PIN = PICO_DEFAULT_LED_PIN;
|
extern const uint LED_PIN = PICO_DEFAULT_LED_PIN;
|
||||||
extern const uint LEFT_PADDLE_PIN = 14;
|
extern const uint LEFT_PADDLE_PIN = 14;
|
||||||
|
@ -23,6 +26,21 @@ extern const uint CW_OUT_PIN = 17;
|
||||||
// extern const uint AUDIO_OUT_PIN = 16;
|
// extern const uint AUDIO_OUT_PIN = 16;
|
||||||
extern const uint ADC_PIN = 26;
|
extern const uint ADC_PIN = 26;
|
||||||
|
|
||||||
|
// Stuff for communicating between cores
|
||||||
|
enum class KeyerQueueCommand {
|
||||||
|
Run,
|
||||||
|
Stop,
|
||||||
|
Config,
|
||||||
|
Wait,
|
||||||
|
SendMessage,
|
||||||
|
};
|
||||||
|
struct KeyerQueueData {
|
||||||
|
KeyerQueueCommand cmd;
|
||||||
|
uint8_t wpm;
|
||||||
|
Mode mode;
|
||||||
|
char message;
|
||||||
|
};
|
||||||
|
|
||||||
queue_t keyerQueue;
|
queue_t keyerQueue;
|
||||||
|
|
||||||
void setup()
|
void setup()
|
||||||
|
@ -47,17 +65,13 @@ void setup()
|
||||||
adc_init();
|
adc_init();
|
||||||
gpio_init(ADC_PIN);
|
gpio_init(ADC_PIN);
|
||||||
adc_select_input(0);
|
adc_select_input(0);
|
||||||
|
|
||||||
// Setup USB
|
|
||||||
board_init();
|
|
||||||
tud_init(BOARD_TUD_RHPORT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Let's do all the keying stuff in the second core, so there are no timing problems. */
|
/* Let's do all the keying stuff in the second core, so there are no timing problems. */
|
||||||
void core1_main()
|
void core1_main()
|
||||||
{
|
{
|
||||||
flash_safe_execute_core_init();
|
flash_safe_execute_core_init();
|
||||||
|
printf("Hello from core1!\n");
|
||||||
KeyerQueueData data;
|
KeyerQueueData data;
|
||||||
queue_remove_blocking(&keyerQueue, &data);
|
queue_remove_blocking(&keyerQueue, &data);
|
||||||
|
|
||||||
|
@ -91,12 +105,100 @@ void core1_main()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void usbSend(uint8_t itf, uint8_t buf[], uint32_t count)
|
||||||
|
{
|
||||||
|
for (uint32_t i = 0; i < count; i++) {
|
||||||
|
tud_cdc_n_write_char(itf, buf[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
tud_cdc_n_write_flush(itf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void usbSend(uint8_t itf, uint8_t value)
|
||||||
|
{
|
||||||
|
tud_cdc_n_write_char(itf, value);
|
||||||
|
tud_cdc_n_write_flush(itf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cdc_task()
|
||||||
|
{
|
||||||
|
const uint8_t USB_IF = 0;
|
||||||
|
|
||||||
|
if (tud_cdc_n_available(USB_IF)) {
|
||||||
|
uint8_t buf[64];
|
||||||
|
|
||||||
|
//printf("AHA!!! %d\n", (int)tud_cdc_n_available(USB_IF));
|
||||||
|
uint32_t count = tud_cdc_n_read(USB_IF, buf, sizeof(buf));
|
||||||
|
|
||||||
|
if (count > 0) {
|
||||||
|
switch (buf[0]) {
|
||||||
|
case 'a' ... 'z':
|
||||||
|
[[fallthrough]];
|
||||||
|
case 'A' ... 'Z':
|
||||||
|
[[fallthrough]];
|
||||||
|
case '0' ... '9':
|
||||||
|
[[fallthrough]];
|
||||||
|
case ' ':
|
||||||
|
[[fallthrough]];
|
||||||
|
case '+':
|
||||||
|
[[fallthrough]];
|
||||||
|
case '=':
|
||||||
|
[[fallthrough]];
|
||||||
|
case '?':
|
||||||
|
[[fallthrough]];
|
||||||
|
case ',':
|
||||||
|
[[fallthrough]];
|
||||||
|
case '.':
|
||||||
|
{
|
||||||
|
KeyerQueueData keyerQueueData {KeyerQueueCommand::SendMessage, 0, Mode::IambicB, buf[0]};
|
||||||
|
queue_add_blocking(&keyerQueue, &keyerQueueData);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x00: // ADMIN COMMAND
|
||||||
|
switch (buf[1]) {
|
||||||
|
case 0x02: // HOST OPEN
|
||||||
|
usbSend(USB_IF, 9); // Send WK1 (v9) for now (no WinKeyer PTT control)
|
||||||
|
break;
|
||||||
|
case 0x04: // ECHO TEST
|
||||||
|
usbSend(USB_IF, &buf[2], 1); // Send the received byte back
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("Unknown admin command: %x\n", buf[1]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("Unknown command: %d.\n", buf[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
timer_hw->dbgpause = 0; // workaround for problem with debug and sleep_ms
|
timer_hw->dbgpause = 0; // workaround for problem with debug and sleep_ms
|
||||||
// https://github.com/raspberrypi/pico-sdk/issues/1152#issuecomment-1418248639
|
// https://github.com/raspberrypi/pico-sdk/issues/1152#issuecomment-1418248639
|
||||||
|
|
||||||
setup();
|
setup();
|
||||||
|
board_init();
|
||||||
|
tud_init(BOARD_TUD_RHPORT);
|
||||||
|
|
||||||
printf("RaspiKeyer Version %s\n", PROJECT_VERSION);
|
printf("RaspiKeyer Version %s\n", PROJECT_VERSION);
|
||||||
|
|
||||||
|
@ -120,8 +222,6 @@ int main()
|
||||||
KeyerQueueData keyerQueueData {KeyerQueueCommand::Run, currentWpm, settings.mode, 0};
|
KeyerQueueData keyerQueueData {KeyerQueueCommand::Run, currentWpm, settings.mode, 0};
|
||||||
queue_add_blocking(&keyerQueue, &keyerQueueData);
|
queue_add_blocking(&keyerQueue, &keyerQueueData);
|
||||||
|
|
||||||
WinKeyer winKeyer;
|
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
currentWpm = calcWPM(potiRead(), settings.wpmPotiMin, settings.wpmPotiMax);
|
currentWpm = calcWPM(potiRead(), settings.wpmPotiMin, settings.wpmPotiMax);
|
||||||
|
|
||||||
|
@ -133,9 +233,8 @@ int main()
|
||||||
lastWpm = currentWpm;
|
lastWpm = currentWpm;
|
||||||
}
|
}
|
||||||
|
|
||||||
tud_task(); // Internal PICO purposes
|
tud_task();
|
||||||
|
cdc_task();
|
||||||
winKeyer.run(keyerQueue);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
#include <cmath>
|
|
||||||
|
|
||||||
#include "hardware/adc.h"
|
|
||||||
#include "pico/stdlib.h"
|
|
||||||
#include "tusb.h"
|
|
||||||
|
|
||||||
#include "utils.h"
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
void usbSend(uint8_t itf, uint8_t buf[], uint32_t count)
|
|
||||||
{
|
|
||||||
for (uint32_t i = 0; i < count; i++) {
|
|
||||||
tud_cdc_n_write_char(itf, buf[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
tud_cdc_n_write_flush(itf);
|
|
||||||
}
|
|
||||||
|
|
||||||
void usbSend(uint8_t itf, uint8_t value)
|
|
||||||
{
|
|
||||||
tud_cdc_n_write_char(itf, value);
|
|
||||||
tud_cdc_n_write_flush(itf);
|
|
||||||
}
|
|
29
src/utils.h
29
src/utils.h
|
@ -1,29 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "settings.h"
|
|
||||||
|
|
||||||
// Stuff for communicating between cores
|
|
||||||
enum class KeyerQueueCommand {
|
|
||||||
Run,
|
|
||||||
Stop,
|
|
||||||
Config,
|
|
||||||
Wait,
|
|
||||||
SendMessage,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct KeyerQueueData {
|
|
||||||
KeyerQueueCommand cmd;
|
|
||||||
uint8_t wpm;
|
|
||||||
Mode mode;
|
|
||||||
uint8_t message;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Calculates the WPM speed from the volt percentage */
|
|
||||||
uint8_t calcWPM(float percent, uint8_t wpmMin, uint8_t wpmMax);
|
|
||||||
|
|
||||||
/* Returns the voltage level in percent (3,3V == 100%) */
|
|
||||||
float potiRead();
|
|
||||||
|
|
||||||
// Sending bytes over USB
|
|
||||||
void usbSend(uint8_t itf, uint8_t buf[], uint32_t count);
|
|
||||||
void usbSend(uint8_t itf, uint8_t value);
|
|
|
@ -1,58 +0,0 @@
|
||||||
#include "pico/stdlib.h"
|
|
||||||
#include "tusb.h"
|
|
||||||
|
|
||||||
#include "utils.h"
|
|
||||||
|
|
||||||
#include "winkeyer.h"
|
|
||||||
|
|
||||||
void WinKeyer::run(queue_t &queue)
|
|
||||||
{
|
|
||||||
const uint8_t USB_IF = 0;
|
|
||||||
|
|
||||||
if (tud_cdc_n_available(USB_IF)) {
|
|
||||||
uint8_t buf[64];
|
|
||||||
|
|
||||||
// printf("AHA!!! %d\n", (int)tud_cdc_n_available(USB_IF));
|
|
||||||
uint32_t count = tud_cdc_n_read(USB_IF, buf, sizeof(buf));
|
|
||||||
|
|
||||||
if (count > 0) {
|
|
||||||
switch (buf[0]) {
|
|
||||||
case 'a' ... 'z':
|
|
||||||
[[fallthrough]];
|
|
||||||
case 'A' ... 'Z':
|
|
||||||
[[fallthrough]];
|
|
||||||
case '0' ... '9':
|
|
||||||
[[fallthrough]];
|
|
||||||
case ' ':
|
|
||||||
[[fallthrough]];
|
|
||||||
case '+':
|
|
||||||
[[fallthrough]];
|
|
||||||
case '=':
|
|
||||||
[[fallthrough]];
|
|
||||||
case '?':
|
|
||||||
[[fallthrough]];
|
|
||||||
case ',':
|
|
||||||
[[fallthrough]];
|
|
||||||
case '.': {
|
|
||||||
KeyerQueueData keyerQueueData {KeyerQueueCommand::SendMessage, 0, Mode::IambicB, buf[0]};
|
|
||||||
queue_add_blocking(&queue, &keyerQueueData);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 0x00: // ADMIN COMMAND
|
|
||||||
switch (buf[1]) {
|
|
||||||
case 0x02: // HOST OPEN
|
|
||||||
usbSend(USB_IF, 9); // Send WK1 (v9) for now (no WinKeyer PTT control)
|
|
||||||
break;
|
|
||||||
case 0x04: // ECHO TEST
|
|
||||||
usbSend(USB_IF, &buf[2], 1); // Send the received byte back
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
printf("Unknown admin command: %x\n", buf[1]);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
printf("Unknown command: %d.\n", buf[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "pico/util/queue.h"
|
|
||||||
|
|
||||||
class WinKeyer final
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void run(queue_t &queue);
|
|
||||||
|
|
||||||
private:
|
|
||||||
};
|
|
Loading…
Reference in a new issue