[Morse] Added support for Morse code transmissions

pull/13/head
jgromes 2019-02-09 09:38:50 +01:00
rodzic 2101203d07
commit 344afee97a
5 zmienionych plików z 476 dodań i 0 usunięć

Wyświetl plik

@ -0,0 +1,98 @@
/*
RadioLib Morse Transmit Example
This example sends Morse code message using
SX1278's FSK modem.
Other modules that can be used for Morse:
- SX1272/73/76/77/79
- RF69
- SX1231
- CC1101
*/
// include the library
#include <RadioLib.h>
// SX1278 module is in slot A on the shield
SX1278 fsk = RadioShield.ModuleA;
// create Morse client instance using the FSK module
MorseClient morse(&fsk);
void setup() {
Serial.begin(9600);
// initialize SX1278
Serial.print(F("[SX1278] Initializing ... "));
// carrier frequency: 434.0 MHz
// bit rate: 48.0 kbps
// frequency deviation: 50.0 kHz
// Rx bandwidth: 125.0 kHz
// output power: 13 dBm
// current limit: 100 mA
// sync word: 0x2D 0x01
int state = fsk.beginFSK();
if(state == ERR_NONE) {
Serial.println(F("success!"));
} else {
Serial.print(F("failed, code "));
Serial.println(state);
while(true);
}
// initialize Morse client
Serial.print(F("[Morse] Initializing ... "));
// base frequency: 434.0 MHz
// speed: 20 words per minute
state = morse.begin(434.0);
if(state == ERR_NONE) {
Serial.println(F("success!"));
} else {
Serial.print(F("failed, code "));
Serial.println(state);
while(true);
}
}
void loop() {
Serial.print(F("[Morse] Sending Morse data ... "));
// MorseClient supports all methods of the Serial class
// NOTE: Characters that do not have ITU-R M.1677-1
// representation will not be sent! Lower case
// letters will be capitalized.
// send start signal first
morse.startSignal();
// Arduino String class
String aStr = "Arduino String";
morse.print(aStr);
// character array (C-String)
morse.print("C-String");
// character
morse.print('c');
// byte
// formatting DEC/HEX/OCT/BIN is supported for
// any integer type (byte/int/long)
morse.print(255, HEX);
// integer number
int i = 1000;
morse.print(i);
// floating point number
// NOTE: When using println(), the transmission will be
// terminated with cross signal (.-.-.).
float f = -3.1415;
morse.println(f, 3);
Serial.println(F("done!"));
// wait for a second before transmitting again
delay(1000);
}

Wyświetl plik

@ -32,6 +32,7 @@ XBeeSerial KEYWORD1
MQTTClient KEYWORD1
HTTPClient KEYWORD1
RTTYClient KEYWORD1
MorseClient KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
@ -113,6 +114,9 @@ check KEYWORD2
idle KEYWORD2
byteArr KEYWORD2
# Morse
startSignal KEYWORD2
# TransportLayer
openTransportConnection KEYWORD2
closeTransportConnection KEYWORD2

Wyświetl plik

@ -22,6 +22,7 @@
#include "modules/XBee.h"
#include "protocols/PhysicalLayer.h"
#include "protocols/Morse.h"
#include "protocols/RTTY.h"
#include "protocols/TransportLayer.h"

Wyświetl plik

@ -0,0 +1,322 @@
#include "Morse.h"
// structure to save data about character Morse code
struct Morse_t {
char c; // ASCII character
const char* m; // Morse code representation
};
// array of all Morse code characters
static const Morse_t MorseTable[MORSE_LENGTH] = {
{.c = 'A', .m = ".-"},
{.c = 'B', .m = "-..."},
{.c = 'C', .m = "-.-."},
{.c = 'D', .m = "-.."},
{.c = 'E', .m = "."},
{.c = 'F', .m = "..-."},
{.c = 'G', .m = "--."},
{.c = 'H', .m = "...."},
{.c = 'I', .m = ".."},
{.c = 'J', .m = ".---"},
{.c = 'K', .m = "-.-"},
{.c = 'L', .m = ".-.."},
{.c = 'M', .m = "--"},
{.c = 'N', .m = "-."},
{.c = 'O', .m = "---"},
{.c = 'P', .m = ".--."},
{.c = 'Q', .m = "--.-"},
{.c = 'R', .m = ".-."},
{.c = 'S', .m = "..."},
{.c = 'T', .m = "-"},
{.c = 'U', .m = "..-"},
{.c = 'V', .m = "...-"},
{.c = 'W', .m = ".--"},
{.c = 'X', .m = "-..-"},
{.c = 'Y', .m = "-.--"},
{.c = 'Z', .m = "--.."},
{.c = '1', .m = ".----"},
{.c = '2', .m = "..---"},
{.c = '3', .m = "...--"},
{.c = '4', .m = "....-"},
{.c = '5', .m = "....."},
{.c = '6', .m = "-...."},
{.c = '7', .m = "--..."},
{.c = '8', .m = "---.."},
{.c = '9', .m = "----."},
{.c = '0', .m = "-----"},
{.c = '.', .m = ".-.-.-"},
{.c = ',', .m = "--..--"},
{.c = ':', .m = "---..."},
{.c = '?', .m = "..--.."},
{.c = '\'', .m = ".----."},
{.c = '-', .m = "-....-"},
{.c = '/', .m = "-..-."},
{.c = '(', .m = "-.--."},
{.c = ')', .m = "-.--.-"},
{.c = '\"', .m = ".-..-."},
{.c = '=', .m = "-...-"},
{.c = '+', .m = ".-.-."},
{.c = '@', .m = ".--.-."},
{.c = ' ', .m = "_"}, // space is used to separate words
{.c = 0x01, .m = "-.-.-"}, // ASCII SOH (start of heading) is used as alias for start signal
{.c = 0x02, .m = ".-.-."} // ASCII EOT (end of transmission) is used as alias for stop signal
};
MorseClient::MorseClient(PhysicalLayer* phy) {
_phy = phy;
}
int16_t MorseClient::begin(float base, uint8_t speed) {
// calculate 24-bit frequency
_base = (base * (uint32_t(1) << _phy->getDivExponent())) / _phy->getCrystalFreq();
// calculate dot length (assumes PARIS as typical word)
_dotLength = 1200 / speed;
// set module frequency deviation to 0
int16_t state = _phy->setFrequencyDeviation(0);
return(state);
}
size_t MorseClient::write(const char* str) {
if(str == NULL) {
return(0);
}
return(MorseClient::write((uint8_t*)str, strlen(str)));
}
size_t MorseClient::write(uint8_t* buff, size_t len) {
size_t n = 0;
for(size_t i = 0; i < len; i++) {
n += MorseClient::write(buff[i]);
}
return(n);
}
size_t MorseClient::write(uint8_t b) {
// find the correct Morse code in array
uint8_t pos;
bool found = false;
for(pos = 0; pos < MORSE_LENGTH; pos++) {
if(MorseTable[pos].c == toupper(b)) {
found = true;
break;
}
}
Serial.print((char)b);
Serial.print('\t');
// check if the requested code was found in the array
if(found) {
// iterate over Morse code representation and output appropriate tones
for(uint8_t i = 0; i < strlen(MorseTable[pos].m); i++) {
Serial.print(MorseTable[pos].m[i]);
switch(MorseTable[pos].m[i]) {
case '.':
_phy->transmitDirect(_base);
delay(_dotLength);
break;
case '-':
_phy->transmitDirect(_base);
delay(_dotLength * 3);
break;
case '_':
// do nothing (word space)
break;
}
// symbol space
_phy->receiveDirect();
delay(_dotLength);
}
Serial.println();
// letter space
delay(_dotLength * 3);
return(1);
}
return(0);
}
size_t MorseClient::startSignal() {
return(MorseClient::write(0x01));
}
size_t MorseClient::print(const String& str) {
return(MorseClient::write((uint8_t*)str.c_str(), str.length()));
}
size_t MorseClient::print(const char* str) {
return(MorseClient::write((uint8_t*)str, strlen(str)));
}
size_t MorseClient::print(char c) {
return(MorseClient::write(c));
}
size_t MorseClient::print(unsigned char b, int base) {
return(MorseClient::print((unsigned long)b, base));
}
size_t MorseClient::print(int n, int base) {
return(MorseClient::print((long)n, base));
}
size_t MorseClient::print(unsigned int n, int base) {
return(MorseClient::print((unsigned long)n, base));
}
size_t MorseClient::print(long n, int base) {
if(base == 0) {
return(MorseClient::write(n));
} else if(base == DEC) {
if (n < 0) {
int t = MorseClient::print('-');
n = -n;
return(MorseClient::printNumber(n, DEC) + t);
}
return(MorseClient::printNumber(n, DEC));
} else {
return(MorseClient::printNumber(n, base));
}
}
size_t MorseClient::print(unsigned long n, int base) {
if(base == 0) {
return(MorseClient::write(n));
} else {
return(MorseClient::printNumber(n, base));
}
}
size_t MorseClient::print(double n, int digits) {
return(MorseClient::printFloat(n, digits));
}
size_t MorseClient::println(void) {
return(MorseClient::write(0x02));
}
size_t MorseClient::println(const String& str) {
size_t n = MorseClient::print(str);
n += MorseClient::println();
return(n);
}
size_t MorseClient::println(const char* str) {
size_t n = MorseClient::print(str);
n += MorseClient::println();
return(n);
}
size_t MorseClient::println(char c) {
size_t n = MorseClient::print(c);
n += MorseClient::println();
return(n);
}
size_t MorseClient::println(unsigned char b, int base) {
size_t n = MorseClient::print(b, base);
n += MorseClient::println();
return(n);
}
size_t MorseClient::println(int num, int base) {
size_t n = MorseClient::print(num, base);
n += MorseClient::println();
return(n);
}
size_t MorseClient::println(unsigned int num, int base) {
size_t n = MorseClient::print(num, base);
n += MorseClient::println();
return(n);
}
size_t MorseClient::println(long num, int base) {
size_t n = MorseClient::print(num, base);
n += MorseClient::println();
return(n);
}
size_t MorseClient::println(unsigned long num, int base) {
size_t n = MorseClient::print(num, base);
n += MorseClient::println();
return(n);
}
size_t MorseClient::println(double d, int digits) {
size_t n = MorseClient::print(d, digits);
n += MorseClient::println();
return(n);
}
size_t MorseClient::printNumber(unsigned long n, uint8_t base) {
char buf[8 * sizeof(long) + 1];
char *str = &buf[sizeof(buf) - 1];
*str = '\0';
if(base < 2) {
base = 10;
}
do {
char c = n % base;
n /= base;
*--str = c < 10 ? c + '0' : c + 'A' - 10;
} while(n);
return(MorseClient::write(str));
}
size_t MorseClient::printFloat(double number, uint8_t digits) {
size_t n = 0;
char code[] = {0x00, 0x00, 0x00, 0x00};
if (isnan(number)) strcpy(code, "nan");
if (isinf(number)) strcpy(code, "inf");
if (number > 4294967040.0) strcpy(code, "ovf"); // constant determined empirically
if (number <-4294967040.0) strcpy(code, "ovf"); // constant determined empirically
if(code[0] != 0x00) {
return(MorseClient::write(code));
}
// Handle negative numbers
if (number < 0.0) {
n += MorseClient::print('-');
number = -number;
}
// Round correctly so that print(1.999, 2) prints as "2.00"
double rounding = 0.5;
for(uint8_t i = 0; i < digits; ++i) {
rounding /= 10.0;
}
number += rounding;
// Extract the integer part of the number and print it
unsigned long int_part = (unsigned long)number;
double remainder = number - (double)int_part;
n += MorseClient::print(int_part);
// Print the decimal point, but only if there are digits beyond
if(digits > 0) {
n += MorseClient::print('.');
}
// Extract digits from the remainder one at a time
while(digits-- > 0) {
remainder *= 10.0;
unsigned int toPrint = (unsigned int)(remainder);
n += MorseClient::print(toPrint);
remainder -= toPrint;
}
return n;
}

Wyświetl plik

@ -0,0 +1,51 @@
#ifndef _RADIOLIB_MORSE_H
#define _RADIOLIB_MORSE_H
#include "TypeDef.h"
#include "PhysicalLayer.h"
#define MORSE_LENGTH 52
class MorseClient {
public:
MorseClient(PhysicalLayer* phy);
// basic methods
int16_t begin(float base, uint8_t speed = 20);
size_t write(const char* str);
size_t write(uint8_t* buff, size_t len);
size_t write(uint8_t b);
size_t startSignal();
size_t print(const String &);
size_t print(const char[]);
size_t print(char);
size_t print(unsigned char, int = DEC);
size_t print(int, int = DEC);
size_t print(unsigned int, int = DEC);
size_t print(long, int = DEC);
size_t print(unsigned long, int = DEC);
size_t print(double, int = 2);
size_t println(void);
size_t println(const String &s);
size_t println(const char[]);
size_t println(char);
size_t println(unsigned char, int = DEC);
size_t println(int, int = DEC);
size_t println(unsigned int, int = DEC);
size_t println(long, int = DEC);
size_t println(unsigned long, int = DEC);
size_t println(double, int = 2);
private:
PhysicalLayer* _phy;
uint32_t _base;
uint16_t _dotLength;
size_t printNumber(unsigned long, uint8_t);
size_t printFloat(double, uint8_t);
};
#endif