diff --git a/README.md b/README.md index b741500..0525e7f 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,6 @@ to key down. You can also connect a physical key or paddle, through an Arduino micro running a keyer program. -This program is in the [arduino directory](arduino/), +This program is on github as [vail-adapter](https://github.com/nealey/vail-adapter), or [in Arduino Create](https://create.arduino.cc/editor/neale/f94bb765-47bd-4bc4-9cbf-b978f7124bdc). diff --git a/arduino/README.adoc b/arduino/README.adoc deleted file mode 100644 index 0e97a3d..0000000 --- a/arduino/README.adoc +++ /dev/null @@ -1,153 +0,0 @@ -:Author: neale -:Email: neale@woozle.org -:Date: 2020-May-3 -:Revision: 1 -:License: MIT - -= Project: USB Morse Adapter - -This translates Morse key inputs into USB events, -either MIDI or MIDI+Keyboard, -so you can use a computer. - -I use this with an Internet morse code repeater I wrote, -available at https://vail.woozle.org/. - -This project requires an Arduino that can send USB. -I've only used the Micro, -although I have no doubt the Leonardo will work too, -as I've used Leonardos for similar projects. - - -== Step 1: Installation - -This needs the MidiUSB and Keyboard libraries. - -Installing those is documented all over the Internet. -I'm using https://create.arduino.cc/ so this is all magic for me. - - -== Step 2: Assmble the circuit - -Morse code keyers are very simple devices, -they just connect two wires together. -You could use a button if you wanted to, -or even touch wires together. - -The only real complication here is that some browsers -need to get keyboard events instead of musical instrument events. - - -=== Decide what browser you're going to use - -Firefox needs a jumper between pin 9 and ground. -Just take a wire, and connect pin 9 directly to ground. -This puts the Arduino into "keyboard mode", -where it sends a comma for straight key, -and period and slash for iambic. - -If you don't connect pin 9 to ground, -the Arudino only sends MIDI (Musical Instrument Digital Interface) -events, so it looks like you hooked a piano up. -This works great in Chrome, -and lets you switch to other windows while still keying into vail. - -=== Wire up your input device - -Hook a straight key into ground on one side, -pin 10 on the other. -It's okay to leave pin 10 disconnected if you don't have a straight key. - -Hook an iambic paddle in ground in the middle, -pins 11 and 12 on the outside posts. -It's okay to leave pins 11 and 12 disconnected if you don't have a paddle. - -=== Using a headphone jack - -If you prefer, you can wire a headphone jack up to GND, 11, and 12. -GND should be the sleeve, 11 the ring, and 12 the tip. - - o --- 12 - |_| --- 11 - | | --- GND - | | - -Make sure any straight key you plug in has a TS adapter (mono plug): -this will short pin 11 to ground and signal to the Arduino to -go into straight key mode. - -You need to reset the Arduino if you change from an iambic to straight key. -On the micro, reset is a white button. - -If you plug in your straight key and it looks like DAH is being held down, -it means you need to switch the connections to pins 11 and 12. - -If you plug in your straight key and it looks like DIT is being held down, -it means you need to reset the Arduino to make it detect the key type again. - - -== Step 3: Load the code - -Upload the code contained in this sketch on to your board. - -== Step 4: Test it out - -Make sure it's plugged in to your computer's USB port. - -If you connected pin 9 to ground, -Open anything where you can type, -type in "hello", and hit the straight key. -You should see a comma after your hello. - -Now you can open https://vail.woozle.org/, -click the "KEY" button once to let the browser know it's okay to make sound, -and you should be able to wail away on your new USB keyer. - - -=== License - -This project is released under an MIT License. - -Copyright © 2020 Neale Pickett -Copyright © 2013 thomasfredericks - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The software is provided "as is", without warranty of any kind, express or -implied, including but not limited to the warranties of merchantability, fitness -for a particular purpose, and noninfringement. In no event shall the authors or -copyright holders be liable for any claim, damages, or other liability, whether -in an action of contract, tort or otherwise, arising from, out of, or in -connection with the software or the use or other dealings in the software. - - -=== Contributing -To contribute to this project please contact neale@woozle.org -https://id.arduino.cc/neale - - -=== BOM - -In addition to a key, some hookup wires, and a USB cable, -you only need an Arduino. - -|=== -| ID | Part name | Part number | Quantity -| A1 | Arduino Micro | ABX00053 | 1 -|=== - - -=== Help - -This document is written in the _AsciiDoc_ format, a markup language to describe documents. -If you need help you can search the http://www.methods.co.nz/asciidoc[AsciiDoc homepage] -or consult the http://powerman.name/doc/asciidoc[AsciiDoc cheatsheet] - diff --git a/arduino/bounce2.cpp b/arduino/bounce2.cpp deleted file mode 100644 index d175805..0000000 --- a/arduino/bounce2.cpp +++ /dev/null @@ -1,138 +0,0 @@ -// Please read Bounce2.h for information about the liscence and authors - - -#include "bounce2.h" - - - - -Bounce::Bounce() - : previous_millis(0) - , interval_millis(10) - , state(0) - , pin(0) -{} - -void Bounce::attach(int pin) { - this->pin = pin; - state = 0; - if (readCurrentState()) { - setStateFlag(DEBOUNCED_STATE | UNSTABLE_STATE); - } -#ifdef BOUNCE_LOCK_OUT - previous_millis = 0; -#else - previous_millis = millis(); -#endif -} - -void Bounce::attach(int pin, int mode){ - setPinMode(pin, mode); - this->attach(pin); -} - -void Bounce::interval(uint16_t interval_millis) -{ - this->interval_millis = interval_millis; -} - -bool Bounce::update() -{ - - unsetStateFlag(CHANGED_STATE); -#ifdef BOUNCE_LOCK_OUT - - // Ignore everything if we are locked out - if (millis() - previous_millis >= interval_millis) { - bool currentState = readCurrentState(); - if ( currentState != getStateFlag(DEBOUNCED_STATE) ) { - previous_millis = millis(); - changeState(); - } - } - - -#elif defined BOUNCE_WITH_PROMPT_DETECTION - // Read the state of the switch port into a temporary variable. - bool readState = readCurrentState(); - - - if ( readState != getStateFlag(DEBOUNCED_STATE) ) { - // We have seen a change from the current button state. - - if ( millis() - previous_millis >= interval_millis ) { - // We have passed the time threshold, so a new change of state is allowed. - // set the STATE_CHANGED flag and the new DEBOUNCED_STATE. - // This will be prompt as long as there has been greater than interval_misllis ms since last change of input. - // Otherwise debounced state will not change again until bouncing is stable for the timeout period. - changeState(); - } - } - - // If the readState is different from previous readState, reset the debounce timer - as input is still unstable - // and we want to prevent new button state changes until the previous one has remained stable for the timeout. - if ( readState != getStateFlag(UNSTABLE_STATE) ) { - // Update Unstable Bit to macth readState - toggleStateFlag(UNSTABLE_STATE); - previous_millis = millis(); - } - - -#else - // Read the state of the switch in a temporary variable. - bool currentState = readCurrentState(); - - - // If the reading is different from last reading, reset the debounce counter - if ( currentState != getStateFlag(UNSTABLE_STATE) ) { - previous_millis = millis(); - toggleStateFlag(UNSTABLE_STATE); - } else - if ( millis() - previous_millis >= interval_millis ) { - // We have passed the threshold time, so the input is now stable - // If it is different from last state, set the STATE_CHANGED flag - if (currentState != getStateFlag(DEBOUNCED_STATE) ) { - previous_millis = millis(); - - - changeState(); - } - } - - -#endif - - return changed(); - -} - -// WIP HELD -unsigned long Bounce::previousDuration() { - return durationOfPreviousState; -} - -unsigned long Bounce::duration() { - return (millis() - stateChangeLastTime); -} - -inline void Bounce::changeState() { - toggleStateFlag(DEBOUNCED_STATE); - setStateFlag(CHANGED_STATE) ; - durationOfPreviousState = millis() - stateChangeLastTime; - stateChangeLastTime = millis(); -} - -bool Bounce::read() -{ - return getStateFlag(DEBOUNCED_STATE); -} - -bool Bounce::rose() -{ - return getStateFlag(DEBOUNCED_STATE) && getStateFlag(CHANGED_STATE); -} - -bool Bounce::fell() -{ - return !getStateFlag(DEBOUNCED_STATE) && getStateFlag(CHANGED_STATE); -} diff --git a/arduino/bounce2.h b/arduino/bounce2.h deleted file mode 100644 index 14d4c66..0000000 --- a/arduino/bounce2.h +++ /dev/null @@ -1,222 +0,0 @@ -/* - The MIT License (MIT) - - Copyright (c) 2013 thomasfredericks - - Permission is hereby granted, free of charge, to any person obtaining a copy of - this software and associated documentation files (the "Software"), to deal in - the Software without restriction, including without limitation the rights to - use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - the Software, and to permit persons to whom the Software is furnished to do so, - subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * - Main code by Thomas O Fredericks (tof@t-o-f.info) - Previous contributions by Eric Lowry, Jim Schimpf and Tom Harkaway - * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -/** - * @todo Make Bounce2 more abstract. Split it from the hardware layer. - * @body Remove deboucing code from Bounce2 and make a new Debounce class from that code. - * Bounce2 should extend Debounce. - */ - - -#ifndef Bounce2_h -#define Bounce2_h - -#if defined(ARDUINO) && ARDUINO >= 100 -#include "Arduino.h" -#else -#include "WProgram.h" -#endif - -// Uncomment the following line for "LOCK-OUT" debounce method -//#define BOUNCE_LOCK_OUT - -// Uncomment the following line for "BOUNCE_WITH_PROMPT_DETECTION" debounce method -//#define BOUNCE_WITH_PROMPT_DETECTION - -#include - -/** - @example bounce.ino - Simple example of the Bounce library that switches the debug LED when a button is pressed. -*/ - -/** - @example change.ino - This example toggles the debug LED (pin 13) on or off when a button on pin 2 is pressed. -*/ - -/** - @example bounce_multiple.ino - Detect the falling edge of multiple buttons. Eight buttons with internal pullups. Toggles a - LED when any button is pressed. Buttons on pins 2,3,4,5,6,7,8,9 -*/ - -/** - @example bounce2buttons.ino - Example of two instances of the Bounce class that switches the debug LED when either one of - the two buttons is pressed. - */ - -static const uint8_t DEBOUNCED_STATE = 0b00000001; -static const uint8_t UNSTABLE_STATE = 0b00000010; -static const uint8_t CHANGED_STATE = 0b00000100; - -/** - The Bounce class. - */ -class Bounce -{ - public: - -/*! - @brief Create an instance of the Bounce class. - - @code - - // Create an instance of the Bounce class. - Bounce() button; - - @endcode -*/ - Bounce(); - - -/*! - @brief Attach to a pin and sets that pin's mode (INPUT, INPUT_PULLUP or OUTPUT). - - @param pin - The pin that is to be debounced. - @param mode - A valid Arduino pin mode (INPUT, INPUT_PULLUP or OUTPUT). -*/ - void attach(int pin, int mode); - - /** - Attach to a pin for advanced users. Only attach the pin this way once you have previously - set it up. Otherwise use attach(int pin, int mode). - */ - void attach(int pin); - - - /** - @brief Sets the debounce interval in milliseconds. - - @param interval_millis - The interval time in milliseconds. - - */ - void interval(uint16_t interval_millis); - - -/*! - @brief Updates the pin's state. - - Because Bounce does not use interrupts, you have to "update" the object before reading its - value and it has to be done as often as possible (that means to include it in your loop()). - Only call update() once per loop(). - - @return True if the pin changed state. -*/ - - bool update(); - - /** - @brief Returns the pin's state (HIGH or LOW). - - @return HIGH or LOW. - */ - bool read(); - - /** - @brief Returns true if pin signal transitions from high to low. - */ - bool fell(); - - /** - @brief Returns true if pin signal transitions from low to high. - */ - bool rose(); - - - /** - @brief Deprecated (i.e. do not use). Included for partial compatibility for programs written - with Bounce version 1 - */ - bool risingEdge() { return rose(); } - /** - @brief Deprecated (i.e. do not use). Included for partial compatibility for programs written - with Bounce version 1 - */ - bool fallingEdge() { return fell(); } - /** - @brief Deprecated (i.e. do not use). Included for partial compatibility for programs written - with Bounce version 1 - */ - Bounce(uint8_t pin, unsigned long interval_millis ) : Bounce() { - attach(pin); - interval(interval_millis); - } - - /** - @brief Returns the duration in milliseconds of the current state. - - Is reset to 0 once the pin rises ( rose() ) or falls ( fell() ). - - @return The duration in milliseconds (unsigned long) of the current state. - */ - - unsigned long duration(); - - /** - @brief Returns the duration in milliseconds of the previous state. - - Takes the values of duration() once the pin changes state. - - @return The duration in milliseconds (unsigned long) of the previous state. - */ - unsigned long previousDuration(); - - protected: - unsigned long previous_millis; - uint16_t interval_millis; - uint8_t state; - uint8_t pin; - unsigned long stateChangeLastTime; - unsigned long durationOfPreviousState; - virtual bool readCurrentState() { return digitalRead(pin); } - virtual void setPinMode(int pin, int mode) { -#if defined(ARDUINO_ARCH_STM32F1) - pinMode(pin, (WiringPinMode)mode); -#else - pinMode(pin, mode); -#endif - } - - private: - inline void changeState(); - inline void setStateFlag(const uint8_t flag) {state |= flag;} - inline void unsetStateFlag(const uint8_t flag) {state &= ~flag;} - inline void toggleStateFlag(const uint8_t flag) {state ^= flag;} - inline bool getStateFlag(const uint8_t flag) {return((state & flag) != 0);} - - public: - bool changed( ) { return getStateFlag(CHANGED_STATE); } - -}; - -#endif diff --git a/arduino/keyer.ino b/arduino/keyer.ino deleted file mode 100644 index 86f1ecb..0000000 --- a/arduino/keyer.ino +++ /dev/null @@ -1,102 +0,0 @@ -// MIDIUSB - Version: Latest -#include -#include -#include "bounce2.h" - -#define DIT_PIN 12 -#define DAH_PIN 11 -#define KEY_PIN 10 -#define KBD_PIN 9 - -#define STRAIGHT_KEY ',' -#define DIT_KEY '.' -#define DAH_KEY '/' - -bool iambic = true; -Bounce kbd = Bounce(); -Bounce dit = Bounce(); -Bounce dah = Bounce(); -Bounce key = Bounce(); - -void setup() { - pinMode(LED_BUILTIN, OUTPUT); - kbd.attach(KBD_PIN, INPUT_PULLUP); - 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. - for (int i = 0; i < 16; i++) { - dah.update(); - } - if (dah.read() == LOW) { - iambic = false; - } else { - iambic = true; - } - - digitalWrite(LED_BUILTIN, !iambic); -} - -void midiKey(bool down, uint8_t key) { - midiEventPacket_t event = {down?9:8, down?0x90:0x80, key, 0x7f}; - MidiUSB.sendMIDI(event); - MidiUSB.flush(); -} - -void loop() { - bool keyboard; - - kbd.update(); - keyboard = !kbd.read(); - - // Monitor straight key pin - if (key.update()) { - midiKey(key.fell(), 0); - if (keyboard) { - if (key.fell()) { - Keyboard.press(STRAIGHT_KEY); - } else { - Keyboard.release(STRAIGHT_KEY); - } - } - } - - // Monitor dit pin, which could be straight key if dah was closed on boot - if (dit.update()) { - uint8_t kbdKey, mKey; - if (iambic) { - kbdKey = DIT_KEY; - mKey = 1; - } else { - kbdKey = STRAIGHT_KEY; - mKey = 0; - } - - midiKey(dit.fell(), mKey); - if (keyboard) { - if (dit.fell()) { - Keyboard.press(kbdKey); - } else { - Keyboard.release(kbdKey); - } - } - } - - // Monitor dah pin - if (iambic && dah.update()) { - midiKey(dah.fell(), 2); - - if (keyboard) { - if (dah.fell()) { - Keyboard.press(DAH_KEY); - } else { - Keyboard.release(DAH_KEY); - } - } - } -}