Digispark-Morse-Keyboard
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