diff --git a/examples/Morse/Morse_Transmit/Morse_Transmit.ino b/examples/Morse/Morse_Transmit/Morse_Transmit.ino index e0d6d1fe..4f3c07e4 100644 --- a/examples/Morse/Morse_Transmit/Morse_Transmit.ino +++ b/examples/Morse/Morse_Transmit/Morse_Transmit.ino @@ -13,6 +13,9 @@ - nRF24 - Si443x/RFM2x - SX128x + + For full API reference, see the GitHub Pages + https://jgromes.github.io/RadioLib/ */ // include the library diff --git a/examples/Morse/Morse_Transmit_AFSK/Morse_Transmit_AFSK.ino b/examples/Morse/Morse_Transmit_AFSK/Morse_Transmit_AFSK.ino new file mode 100644 index 00000000..3dbb5d6f --- /dev/null +++ b/examples/Morse/Morse_Transmit_AFSK/Morse_Transmit_AFSK.ino @@ -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 + +// 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); +} diff --git a/src/protocols/Morse/Morse.cpp b/src/protocols/Morse/Morse.cpp index 6b3e0c16..fe516132 100644 --- a/src/protocols/Morse/Morse.cpp +++ b/src/protocols/Morse/Morse.cpp @@ -2,17 +2,27 @@ MorseClient::MorseClient(PhysicalLayer* phy) { _phy = phy; + _audio = nullptr; +} + +MorseClient::MorseClient(AFSKClient* audio) { + _phy = audio->_phy; + _audio = audio; } int16_t MorseClient::begin(float base, uint8_t speed) { // calculate 24-bit frequency + _baseHz = base; _base = (base * 1000000.0) / _phy->getFreqStep(); // calculate dot length (assumes PARIS as typical word) _dotLength = 1200 / speed; - // set module frequency deviation to 0 - int16_t state = _phy->setFrequencyDeviation(0); + // set module frequency deviation to 0 if using FSK + int16_t state = ERR_NONE; + if(_audio == nullptr) { + state = _phy->setFrequencyDeviation(0); + } return(state); } @@ -46,7 +56,7 @@ size_t MorseClient::write(uint8_t b) { // inter-word pause (space) if(b == ' ') { RADIOLIB_DEBUG_PRINTLN(F("space")); - _phy->standby(); + standby(); delay(4 * _dotLength); return(1); } @@ -65,16 +75,16 @@ size_t MorseClient::write(uint8_t b) { // send dot or dash if (code & MORSE_DASH) { RADIOLIB_DEBUG_PRINT('-'); - _phy->transmitDirect(_base); + transmitDirect(_base, _baseHz); delay(3 * _dotLength); } else { RADIOLIB_DEBUG_PRINT('.'); - _phy->transmitDirect(_base); + transmitDirect(_base, _baseHz); delay(_dotLength); } // symbol space - _phy->standby(); + standby(); delay(_dotLength); // move onto the next bit @@ -82,7 +92,7 @@ size_t MorseClient::write(uint8_t b) { } // letter space - _phy->standby(); + standby(); delay(2 * _dotLength); RADIOLIB_DEBUG_PRINTLN(); @@ -283,3 +293,19 @@ size_t MorseClient::printFloat(double number, uint8_t digits) { 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()); + } +} diff --git a/src/protocols/Morse/Morse.h b/src/protocols/Morse/Morse.h index 66df3280..e09fece0 100644 --- a/src/protocols/Morse/Morse.h +++ b/src/protocols/Morse/Morse.h @@ -3,6 +3,7 @@ #include "../../TypeDef.h" #include "../PhysicalLayer/PhysicalLayer.h" +#include "../AFSK/AFSK.h" #define MORSE_DOT 0b0 #define MORSE_DASH 0b1 @@ -88,18 +89,25 @@ static const uint8_t MorseTable[] PROGMEM = { class MorseClient { public: /*! - \brief Default constructor. + \brief Constructor for 2-FSK mode. \param phy Pointer to the wireless module providing PhysicalLayer communication. */ MorseClient(PhysicalLayer* phy); + /*! + \brief Constructor for AFSK mode. + + \param audio Pointer to the AFSK instance providing audio. + */ + MorseClient(AFSKClient* audio); + // basic methods /*! \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. @@ -145,11 +153,16 @@ class MorseClient { private: #endif PhysicalLayer* _phy; - uint32_t _base; + AFSKClient* _audio; + + uint32_t _base, _baseHz; uint16_t _dotLength; size_t printNumber(unsigned long, uint8_t); size_t printFloat(double, uint8_t); + + int16_t transmitDirect(uint32_t freq = 0, uint32_t freqHz = 0); + int16_t standby(); }; #endif