Digispark-Morse-Keyboard       

von Ralf Beesner                
Elektronik-Labor   Projekte   AVR 




Vorgeschichte

Klassische Morsekeyboards setzen Tastenanschläge in Morsesignale um. Dieses Morse-Keyboard funktioniert umgekehrt, es setzt Morsezeichen in Tastendrücke eines virtuellen USB-Keyboards um, so dass man per Morsetaste in eine beliebige PC- Anwendung hineinschreiben kann. Ich hatte mich bereits in früheren Beiträgen mit einer Implementation in Bascom, einer in C und einer für den Arduino Leonardo bzw. Arduino Micro abgemüht; die Bascom-Version ist mittlerweile obsolet, weil die USB-Lib veraltet ist und nicht mehr gepflegt wird, die C-Version ist sehr kompliziert, die Arduino-Version erfordert überdimensionierte und vergleichsweise teure Hardware. Mit Digispark-Arduino lässt sich nun endlich eine Lösung realisieren, die angemessenen Hardware-Aufwand mit dem relativ einfachen Arduino-Quellcode kombiniert und zudem dank der plattformübergreifenden Arduino-IDE recht einfach unter allen gängigen PC-Betriebssystemen kompiliert werden kann.


Hardware

Sie entspricht der Grundbeschaltung. An Port-Pin B0 liegt zusätzlich ein Piezoschwinger, an B1 die Morsetaste, an B2 der Geschwindigkeitsumschalter und am Reset-Eingang der Schalter für die Leerzeichen-Automatik. Der Schalter ist nicht direkt angeschlossen, sondern über einen hochohmigen Vorwiderstand, so dass die Spannung nur ein wenig einbricht und kein Reset ausgelöst wird. Die Pegeländerung wird über den ADC-Eingang 0 ausgelesen, bei offenem Schalter liegt der Pegel über 1000, bei geschlossenem unter 1000.




Software

Die Morsedecodierung ist von Burkhard Kainka "ausgeborgt" und auf einige andere Mikrocontroller portiert, unter anderem auf den Arduino Micro. USB-Softwarelösungen sind recht zeitkritisch, daher darf man blockierenden Code, z.B. die normale Wartefunktion delay() im eigenen Programmteil nicht beliebig einsetzen. Netterweise gibt es jedoch die Funktion DigiKeyboard.delay(), die nicht nur einfach Zeit vertrödelt, sondern im Hintergrund den USB bedient. Sie ermöglicht es, einfacheren (quasi-blockierenden) Code zu schreiben. Daher kann der Code für den Arduino Micro fast 1:1 auf den Digispark übernommen werden, und die Bedienungshinweise zur Arduino-Micro-Version treffen hier ebenfalls zu.
// Arduino Morse Decoder
// Software bases on:
// Burkhard Kainka
// morse.bas
// morse code decoder with Mega169 and LCD butterfly driver

// screwed up by Ralf Beesner, DK5BU

// ported to DigiSpark and changed for output via virtual USB keyboard
// some keycodes have been added, e.g. + - ? ( ) . ,
// and, most important keycode: space between words ;-)
// all timing constants are derived from the duration of a short morse element 
// ("dit"), so its easier to change speed

//---------------------------------
// there are two ways to insert spaces: by simply waiting (look at mainloop for 
// variable "iconst") or by a dedicated character (morsecode <AS>; wait a 
// second) which is better for talking to a computer
//---------------------------------

// Return (ASCII 13) is generated by the morsecode <KN>
// Backspace (ASCII 8) is generated by morsecode Error (...... and .......).
// Only 6 or 7 dots are recognized as error character (maximum possible length 
// of a character is 7)

// Buzzer is attached to DigitalPin 0
// Keyer is attached to DigitalPin 1
// Speed switch is attached to DigitalPin 2 (60 or 90 characters per minute)
// Space switch is attached to AnalogInput 0 (inserts space by idling time or 
// only by character <AS>). AnalogInput 0 is the Reset Pin 


#include "usToDE.h"
#include "morsedec.h"
#include <DigiKeyboard.h>

static unsigned char key;
static unsigned char keystrokeDE;
static unsigned char morsechar;
static unsigned int timepressed;
static unsigned int timenotpressed;
static unsigned char charactercode;
static unsigned int idling;

static unsigned int dithalf;
static unsigned int tpconst;
static unsigned int tnpconst;
static unsigned int iconst;

#define Buzzer 0 
#define Keyer 1
#define SpeedSwitch 2
#define SpaceSwitch 0  // analog Input 0 = Reset Pin #define Freq 700 void setup() {
    tone (Buzzer, Freq);
    pinMode(Buzzer, OUTPUT);
//      pinMode(Keyer, INPUT_PULLUP) //      pinMode(Speedswitch, INPUT_PULLUP); //      does not work, Compiler complains "INPUT_PULLUP" was not declared in this scope", WTF? //      so we use  C notation:      PORTB |= ((1 << PORTB1) | ( PORTB2));   } //...................................................... void printdisplay(void){
    morsechar = morsetable[charactercode];
    keystrokeDE = (usToDE[morsechar]);
    DigiKeyboard.write(keystrokeDE);
}


void getkey(void){
    key = !( digitalRead(Keyer) ); //if key pressed: key = 1     if (key > 0){
        pinMode(Buzzer, OUTPUT);
    }
    else{
        pinMode(Buzzer, INPUT);
    }
}


void getkeytimes(void){
    timepressed = 0;
    timenotpressed = 0;
    idling = 0;
    do {
        getkey();
        DigiKeyboard.delay (1);
        idling++;
    } 
    while (key == 0);
    do {
        DigiKeyboard.delay(1);
        timepressed++;
        getkey();
    } 
    while (key > 0);

    do {
        DigiKeyboard.delay(1);
        timenotpressed++;
        getkey();
    } 
    while ((key == 0) & (timenotpressed < tnpconst));
}

//----------------------------------------------------- void loop() {

    if ( !( digitalRead(SpeedSwitch))) { //Speedswitch Low         dithalf = 33;                        // duration of half a dit in ms; speed is 90 characters / min.     }     else{
        dithalf = 90;                        // duration of half a dit in ms; speed is 60 characters / min.     }     tpconst = dithalf * 3;                                     // 1.5 * Dit; maximum tinme for a dit     tnpconst = dithalf * 4;                                    // 2 * Dit; minimum time for a dah     iconst = dithalf * 6;                                      // space between words     charactercode = 1;     do {

        getkeytimes();
        if ((idling > iconst) & (analogRead(SpaceSwitch) < 1000)){ // inserts space between morse words             printdisplay();                  // may be deactivated if you want to insert spaces only by <AS>         }         charactercode = charactercode << 1;         if (timepressed > tpconst){
            charactercode++;
        }
    } 
    while (timenotpressed < tnpconst);
    printdisplay();
}


Download: 0115-digispark-morsekb.zip



Elektronik-Labor   Projekte   AVR