diff --git a/vail-adapter.ino b/vail-adapter.ino index bc120e1..2c8a051 100644 --- a/vail-adapter.ino +++ b/vail-adapter.ino @@ -11,11 +11,13 @@ # define DIT_PIN 2 # define DAH_PIN 1 # define KEY_PIN 0 +# define PIEZO 7 # define LED_ON false #else # define DIT_PIN 12 # define DAH_PIN 11 # define KEY_PIN 10 +# define PIEZO 8 # define LED_ON true #endif #define LED_OFF (!LED_ON) @@ -23,39 +25,61 @@ #define STRAIGHT_KEY ',' #define DIT_KEY KEY_LEFT_CTRL #define DAH_KEY KEY_RIGHT_CTRL +#define TONE 660 + +#define MILLISECOND 1 +#define SECOND (1 * MILLISECOND) -bool iambic = true; bool keyboard = true; +bool trs = false; // true if a TRS plug is in a TRRS jack +uint16_t iambicDelay = 80 * MILLISECOND; Bounce dit = Bounce(); Bounce dah = Bounce(); Bounce key = Bounce(); void setup() { pinMode(LED_BUILTIN, OUTPUT); + pinMode(PIEZO, OUTPUT); dit.attach(DIT_PIN, INPUT_PULLUP); dah.attach(DAH_PIN, INPUT_PULLUP); key.attach(KEY_PIN, INPUT_PULLUP); Keyboard.begin(); - // Straight keys need to wire the dah pin to ground somehow. - // The easiest way I can think of to do this is to use a TS connector - // instead of a TRS connector. + // To auto-sense a straight key in a TRRS jack, + // we just check to see if DAH is closed. + // The sleeve on the straight key's TRS plug + // will short the second ring to the sleeve. for (int i = 0; i < 16; i++) { delay(20); dah.update(); } if (dah.read() == LOW) { - iambic = false; - } else { - iambic = true; + trs = true; } +} - // Blink out a V - for (int i = 0; i < 4; i++) { - digitalWrite(LED_BUILTIN, LED_ON); delay(80 + (i/3)*160); - digitalWrite(LED_BUILTIN, LED_OFF); delay(80 + (i/3)*160); +// A reentrant doodad to blink out the letter V at startup +// After startup, display the status of the keyboard +#define HELLO_BITS 0b0000101010111000 +void setLED() { + static bool beepin = false; + int beat = millis() / iambicDelay; + bool on = keyboard; // If we're not in intro, display status of keyboard + + if (beat < 16) { + on = HELLO_BITS & (1 << (15-beat)); + if (on != beepin) { + if (on) { + tone(PIEZO, TONE); + } else { + noTone(PIEZO); + } + beepin = on; + } } + + digitalWrite(LED_BUILTIN, on?LED_ON:LED_OFF); } void midiKey(bool down, uint8_t key) { @@ -66,54 +90,57 @@ void midiKey(bool down, uint8_t key) { void midiProbe() { midiEventPacket_t event = MidiUSB.read(); - if (event.byte1 == 0x80) { - // Key release, channel 0 - if (event.byte2 == 0x00) { - // C0 note - keyboard = false; - } - } + + uint16_t msg = (event.byte1 << 8) | (event.byte2 << 0); + switch (msg) { + case 0x8B00: // Controller 0: turn keyboard mode on/off + keyboard = (event.byte3 > 0x3f); + break; + case 0x8B01: // Controller 1: set iambic speed (0-254) + iambicDelay = event.byte3 << 1; + break; + } } void loop() { midiProbe(); - digitalWrite(LED_BUILTIN, keyboard?LED_ON:LED_OFF); + setLED(); // Monitor straight key pin if (key.update()) { midiKey(key.fell(), 0); - if (keyboard) { - if (key.fell()) { + if (key.fell()) { + tone(PIEZO, TONE); + if (keyboard) { Keyboard.press(STRAIGHT_KEY); - } else { + } + } else { + noTone(PIEZO); + if (keyboard) { Keyboard.release(STRAIGHT_KEY); } } } - - // Monitor dit pin, which could be straight key if dah was closed on boot + + // If we made dit = dah, we have a straight key on the dit pin, + // so we skip iambic polling. + if (trs) { + return; + } + if (dit.update()) { - uint8_t kbdKey, mKey; - if (iambic) { - kbdKey = DIT_KEY; - mKey = 1; - } else { - kbdKey = STRAIGHT_KEY; - mKey = 0; - } - - midiKey(dit.fell(), mKey); + midiKey(dit.fell(), 1); if (keyboard) { if (dit.fell()) { - Keyboard.press(kbdKey); + Keyboard.press(DIT_KEY); } else { - Keyboard.release(kbdKey); + Keyboard.release(DAH_KEY); } } } // Monitor dah pin - if (iambic && dah.update()) { + if (dah.update()) { midiKey(dah.fell(), 2); if (keyboard) {