vail-adapter/adapter.cpp

127 lines
3.3 KiB
C++

#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) {
this->keyboardMode = true;
this->buzzer = new PolyBuzzer(PiezoPin);
this->txToneFrequency = 440;
}
// Send a MIDI Key Event
void VailAdapter::midiKey(uint8_t key, bool down) {
midiEventPacket_t event = {uint8_t(down?9:8), uint8_t(down?0x90:0x80), key, 0x7f};
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;
if (this->keyer) {
this->keyer->SetDitDuration(this->ditDuration);
}
break;
}
break;
case 0xC0: // Program Change
if (this->keyer) {
this->keyer->Release();
}
this->keyer = GetKeyerByNumber(event.byte2, this);
this->keyer->SetDitDuration(this->ditDuration);
break;
case 0x80: // Note off
this->buzzer->NoTone(1);
break;
case 0x90: // Note on
this->buzzer->Note(1, event.byte2);
break;
}
}
void VailAdapter::Tick(unsigned millis) {
if (this->keyer) {
this->keyer->Tick(millis);
}
}