2022-05-22 21:55:22 -06:00
|
|
|
#include <Arduino.h>
|
|
|
|
#include <Keyboard.h>
|
|
|
|
#include <MIDIUSB.h>
|
|
|
|
#include <cstddef>
|
|
|
|
#include "keyers.h"
|
|
|
|
#include "adapter.h"
|
|
|
|
#include "polybuzzer.h"
|
|
|
|
|
|
|
|
#define MILLISECOND 1
|
|
|
|
#define SECOND (1000 * MILLISECOND)
|
|
|
|
|
|
|
|
VailAdapter::VailAdapter(unsigned int PiezoPin) {
|
2022-06-26 12:24:00 -06:00
|
|
|
this->keyboardMode = true;
|
2022-05-22 21:55:22 -06:00
|
|
|
this->buzzer = new PolyBuzzer(PiezoPin);
|
|
|
|
this->txToneFrequency = 440;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Send a MIDI Key Event
|
|
|
|
void VailAdapter::midiKey(uint8_t key, bool down) {
|
2022-05-28 15:18:28 -06:00
|
|
|
midiEventPacket_t event = {uint8_t(down?9:8), uint8_t(down?0x90:0x80), key, 0x7f};
|
2022-05-22 21:55:22 -06:00
|
|
|
MidiUSB.sendMIDI(event);
|
|
|
|
MidiUSB.flush();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Send a keyboard key event
|
|
|
|
void VailAdapter::keyboardKey(uint8_t key, bool down) {
|
|
|
|
if (down) {
|
|
|
|
Keyboard.press(key);
|
|
|
|
} else {
|
|
|
|
Keyboard.release(key);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Begin transmitting
|
|
|
|
void VailAdapter::BeginTx() {
|
|
|
|
this->buzzer->Tone(0, this->txToneFrequency);
|
|
|
|
if (this->keyboardMode) {
|
|
|
|
this->keyboardKey(KEY_LEFT_CTRL, true);
|
|
|
|
} else {
|
|
|
|
this->midiKey(0, true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Stop transmitting
|
|
|
|
void VailAdapter::EndTx() {
|
|
|
|
this->buzzer->NoTone(0);
|
|
|
|
if (this->keyboardMode) {
|
|
|
|
this->keyboardKey(KEY_LEFT_CTRL, false);
|
|
|
|
} else {
|
|
|
|
this->midiKey(0, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Handle a paddle being pressed.
|
|
|
|
//
|
|
|
|
// The caller needs to debounce keys and deal with keys wired in parallel.
|
|
|
|
void VailAdapter::HandlePaddle(Paddle paddle, bool pressed) {
|
|
|
|
switch (paddle) {
|
|
|
|
case PADDLE_STRAIGHT:
|
|
|
|
if (pressed) {
|
|
|
|
this->BeginTx();
|
|
|
|
} else {
|
|
|
|
this->EndTx();
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
case PADDLE_DIT:
|
|
|
|
if (this->keyer) {
|
|
|
|
this->keyer->Key(paddle, pressed);
|
|
|
|
} else if (this->keyboardMode) {
|
|
|
|
this->keyboardKey(KEY_LEFT_CTRL, pressed);
|
|
|
|
} else {
|
|
|
|
this->midiKey(1, pressed);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PADDLE_DAH:
|
|
|
|
if (this->keyer) {
|
|
|
|
this->keyer->Key(paddle, pressed);
|
|
|
|
} else if (this->keyboardMode) {
|
|
|
|
this->keyboardKey(KEY_RIGHT_CTRL, pressed);
|
|
|
|
} else {
|
|
|
|
this->midiKey(2, pressed);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Handle a MIDI event.
|
|
|
|
//
|
|
|
|
// We act as a MIDI
|
|
|
|
void VailAdapter::HandleMIDI(midiEventPacket_t event) {
|
|
|
|
uint16_t msg = (event.byte1 << 8) | (event.byte2 << 0);
|
|
|
|
switch (event.byte1) {
|
|
|
|
case 0xB0: // Controller Change
|
|
|
|
switch (event.byte2) {
|
|
|
|
case 0: // turn keyboard mode on/off
|
|
|
|
this->keyboardMode = (event.byte3 > 0x3f);
|
|
|
|
MidiUSB.sendMIDI(event); // Send it back to acknowledge
|
|
|
|
break;
|
|
|
|
case 1: // set dit duration (0-254) *2ms
|
|
|
|
this->ditDuration = event.byte3 * 2 * MILLISECOND;
|
2022-05-28 15:38:10 -06:00
|
|
|
if (this->keyer) {
|
|
|
|
this->keyer->SetDitDuration(this->ditDuration);
|
|
|
|
}
|
2022-05-22 21:55:22 -06:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 0xC0: // Program Change
|
2022-05-28 15:18:28 -06:00
|
|
|
if (this->keyer) {
|
|
|
|
this->keyer->Release();
|
|
|
|
}
|
2022-05-22 21:55:22 -06:00
|
|
|
this->keyer = GetKeyerByNumber(event.byte2, this);
|
2022-06-26 10:55:28 -06:00
|
|
|
this->keyer->SetDitDuration(this->ditDuration);
|
2022-05-22 21:55:22 -06:00
|
|
|
break;
|
|
|
|
case 0x80: // Note off
|
|
|
|
this->buzzer->NoTone(1);
|
|
|
|
break;
|
|
|
|
case 0x90: // Note on
|
|
|
|
this->buzzer->Note(1, event.byte2);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2022-05-28 15:18:28 -06:00
|
|
|
|
|
|
|
void VailAdapter::Tick(unsigned millis) {
|
|
|
|
if (this->keyer) {
|
|
|
|
this->keyer->Tick(millis);
|
|
|
|
}
|
|
|
|
}
|