[Morse] Added AFSK support

This commit is contained in:
jgromes 2020-04-30 17:10:54 +02:00
parent 21c0703383
commit 0a705f5bb9
4 changed files with 175 additions and 10 deletions

View file

@ -13,6 +13,9 @@
- nRF24 - nRF24
- Si443x/RFM2x - Si443x/RFM2x
- SX128x - SX128x
For full API reference, see the GitHub Pages
https://jgromes.github.io/RadioLib/
*/ */
// include the library // include the library

View file

@ -0,0 +1,123 @@
/*
RadioLib Morse Transmit AFSK Example
This example sends Morse code message using
SX1278's FSK modem. The data is modulated
as AFSK.
Other modules that can be used for Morse Code
with AFSK modulation:
- SX127x/RFM9x
- RF69
- SX1231
- CC1101
- Si443x/RFM2x
For full API reference, see the GitHub Pages
https://jgromes.github.io/RadioLib/
*/
// include the library
#include <RadioLib.h>
// SX1278 has the following connections:
// NSS pin: 10
// DIO0 pin: 2
// RESET pin: 9
// DIO1 pin: 3
SX1278 fsk = new Module(10, 2, 9, 3);
// or using RadioShield
// https://github.com/jgromes/RadioShield
//SX1278 fsk = RadioShield.ModuleA;
// create AFSK client instance using the FSK module
// pin 5 is connected to SX1278 DIO2
AFSKClient audio(&fsk, 5);
// create Morse client instance using the AFSK instance
MorseClient morse(&audio);
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
int state = fsk.beginFSK();
// when using one of the non-LoRa modules for Morse code
// (RF69, CC1101, Si4432 etc.), use the basic begin() method
// int state = fsk.begin();
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 ... "));
// AFSK tone frequency: 400 MHz
// speed: 20 words per minute
state = morse.begin(400);
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");
// string saved in flash
morse.print(F("Flash 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 end-of-work signal (...-.-).
float f = -3.1415;
morse.println(f, 3);
Serial.println(F("done!"));
// wait for a second before transmitting again
delay(1000);
}

View file

@ -2,17 +2,27 @@
MorseClient::MorseClient(PhysicalLayer* phy) { MorseClient::MorseClient(PhysicalLayer* phy) {
_phy = phy; _phy = phy;
_audio = nullptr;
}
MorseClient::MorseClient(AFSKClient* audio) {
_phy = audio->_phy;
_audio = audio;
} }
int16_t MorseClient::begin(float base, uint8_t speed) { int16_t MorseClient::begin(float base, uint8_t speed) {
// calculate 24-bit frequency // calculate 24-bit frequency
_baseHz = base;
_base = (base * 1000000.0) / _phy->getFreqStep(); _base = (base * 1000000.0) / _phy->getFreqStep();
// calculate dot length (assumes PARIS as typical word) // calculate dot length (assumes PARIS as typical word)
_dotLength = 1200 / speed; _dotLength = 1200 / speed;
// set module frequency deviation to 0 // set module frequency deviation to 0 if using FSK
int16_t state = _phy->setFrequencyDeviation(0); int16_t state = ERR_NONE;
if(_audio == nullptr) {
state = _phy->setFrequencyDeviation(0);
}
return(state); return(state);
} }
@ -46,7 +56,7 @@ size_t MorseClient::write(uint8_t b) {
// inter-word pause (space) // inter-word pause (space)
if(b == ' ') { if(b == ' ') {
RADIOLIB_DEBUG_PRINTLN(F("space")); RADIOLIB_DEBUG_PRINTLN(F("space"));
_phy->standby(); standby();
delay(4 * _dotLength); delay(4 * _dotLength);
return(1); return(1);
} }
@ -65,16 +75,16 @@ size_t MorseClient::write(uint8_t b) {
// send dot or dash // send dot or dash
if (code & MORSE_DASH) { if (code & MORSE_DASH) {
RADIOLIB_DEBUG_PRINT('-'); RADIOLIB_DEBUG_PRINT('-');
_phy->transmitDirect(_base); transmitDirect(_base, _baseHz);
delay(3 * _dotLength); delay(3 * _dotLength);
} else { } else {
RADIOLIB_DEBUG_PRINT('.'); RADIOLIB_DEBUG_PRINT('.');
_phy->transmitDirect(_base); transmitDirect(_base, _baseHz);
delay(_dotLength); delay(_dotLength);
} }
// symbol space // symbol space
_phy->standby(); standby();
delay(_dotLength); delay(_dotLength);
// move onto the next bit // move onto the next bit
@ -82,7 +92,7 @@ size_t MorseClient::write(uint8_t b) {
} }
// letter space // letter space
_phy->standby(); standby();
delay(2 * _dotLength); delay(2 * _dotLength);
RADIOLIB_DEBUG_PRINTLN(); RADIOLIB_DEBUG_PRINTLN();
@ -283,3 +293,19 @@ size_t MorseClient::printFloat(double number, uint8_t digits) {
return n; return n;
} }
int16_t MorseClient::transmitDirect(uint32_t freq, uint32_t freqHz) {
if(_audio != nullptr) {
return(_audio->tone(freqHz));
} else {
return(_phy->transmitDirect(freq));
}
}
int16_t MorseClient::standby() {
if(_audio != nullptr) {
return(_audio->noTone());
} else {
return(_phy->standby());
}
}

View file

@ -3,6 +3,7 @@
#include "../../TypeDef.h" #include "../../TypeDef.h"
#include "../PhysicalLayer/PhysicalLayer.h" #include "../PhysicalLayer/PhysicalLayer.h"
#include "../AFSK/AFSK.h"
#define MORSE_DOT 0b0 #define MORSE_DOT 0b0
#define MORSE_DASH 0b1 #define MORSE_DASH 0b1
@ -88,18 +89,25 @@ static const uint8_t MorseTable[] PROGMEM = {
class MorseClient { class MorseClient {
public: public:
/*! /*!
\brief Default constructor. \brief Constructor for 2-FSK mode.
\param phy Pointer to the wireless module providing PhysicalLayer communication. \param phy Pointer to the wireless module providing PhysicalLayer communication.
*/ */
MorseClient(PhysicalLayer* phy); MorseClient(PhysicalLayer* phy);
/*!
\brief Constructor for AFSK mode.
\param audio Pointer to the AFSK instance providing audio.
*/
MorseClient(AFSKClient* audio);
// basic methods // basic methods
/*! /*!
\brief Initialization method. \brief Initialization method.
\param base Base RF frequency to be used in MHz. \param base Base RF frequency to be used in MHz (in 2-FSK mode), or the tone frequency in Hz (in AFSK mode)
\param speed Coding speed in words per minute. \param speed Coding speed in words per minute.
@ -145,11 +153,16 @@ class MorseClient {
private: private:
#endif #endif
PhysicalLayer* _phy; PhysicalLayer* _phy;
uint32_t _base; AFSKClient* _audio;
uint32_t _base, _baseHz;
uint16_t _dotLength; uint16_t _dotLength;
size_t printNumber(unsigned long, uint8_t); size_t printNumber(unsigned long, uint8_t);
size_t printFloat(double, uint8_t); size_t printFloat(double, uint8_t);
int16_t transmitDirect(uint32_t freq = 0, uint32_t freqHz = 0);
int16_t standby();
}; };
#endif #endif