RadioLib/src/protocols/RTTY/RTTY.cpp

128 wiersze
2.8 KiB
C++
Czysty Zwykły widok Historia

2018-08-20 18:42:14 +00:00
#include "RTTY.h"
2023-04-30 09:34:58 +00:00
2023-04-30 09:37:38 +00:00
#include <math.h>
#if !RADIOLIB_EXCLUDE_RTTY
2018-08-20 18:42:14 +00:00
RTTYClient::RTTYClient(PhysicalLayer* phy) {
phyLayer = phy;
2023-04-29 20:54:27 +00:00
lineFeed = "\r\n";
#if !RADIOLIB_EXCLUDE_AFSK
audioClient = nullptr;
2020-07-04 19:19:23 +00:00
#endif
2020-04-30 15:11:09 +00:00
}
#if !RADIOLIB_EXCLUDE_AFSK
2020-04-30 15:11:09 +00:00
RTTYClient::RTTYClient(AFSKClient* audio) {
phyLayer = audio->phyLayer;
2023-04-29 20:54:27 +00:00
lineFeed = "\r\n";
audioClient = audio;
2018-08-20 18:42:14 +00:00
}
2020-06-30 08:45:52 +00:00
#endif
2018-08-20 18:42:14 +00:00
int16_t RTTYClient::begin(float base, uint32_t shift, uint16_t rate, uint8_t enc, uint8_t stopBits) {
2018-08-20 18:42:14 +00:00
// save configuration
2023-04-29 20:54:27 +00:00
RadioLibPrint::encoding = enc;
stopBitsNum = stopBits;
baseFreqHz = base;
shiftFreqHz = shift;
2018-08-20 18:42:14 +00:00
// calculate duration of 1 bit
Use RadioLibTime_t (aka unsigned long) when dealing with millis() and micros() (#1075) * Use unsigned long when dealing with millis() and micros(). Although sizeof(uint32_t) == sizeof(unsigned long) on Arduino, this is not the case on 64-bit Linux, where sizeof(unsigned long) == sizeof(uint64_t). Most timestamp arithmetic and comparisons have been left alone, to reduce code churn. This is fine, as uint32_t is perfectly wide to store most timestamp deltas this library will deal with, and C will promote the integer rather than do a narrowing conversion. The real problem arises with narrowing conversions being done by assuming timestamps are 32-bit. No functional changes intended for platforms where sizeof(uint32_t) == sizeof(unsigned long) (so most 8/16/32-bit platforms). Signed-off-by: Elizabeth Myers <elizabeth.jennifer.myers@gmail.com> * Change most timestamps to use RadioLibTime_t. This makes it obvious what is and isn't a timestamp. Not everything has been converted; anything dealing with protocol and chip-level timestamps has been left alone on purpose, to make it clear that these functions do require 32-bit timestamps. No functional changes intended on platforms where sizeof(uint32_t) == sizeof(unsigned long). Signed-off-by: Elizabeth Myers <elizabeth.jennifer.myers@gmail.com> * Use uint32_t internally in getTimeOnAir. We need to not overflow the integers with the shifts and multiplications, so this is correct behaviour. Signed-off-by: Elizabeth Myers <elizabeth.jennifer.myers@gmail.com> --------- Signed-off-by: Elizabeth Myers <elizabeth.jennifer.myers@gmail.com>
2024-04-25 19:50:58 +00:00
bitDuration = (RadioLibTime_t)1000000/rate;
2018-12-26 10:19:30 +00:00
// calculate module carrier frequency resolution
uint32_t step = round(phyLayer->getFreqStep());
2018-12-26 10:19:30 +00:00
// check minimum shift value
if(shift < step / 2) {
2021-11-14 10:40:52 +00:00
return(RADIOLIB_ERR_INVALID_RTTY_SHIFT);
2018-12-26 10:19:30 +00:00
}
2018-12-26 10:19:30 +00:00
// round shift to multiples of frequency step size
if(shift % step < (step / 2)) {
shiftFreq = shift / step;
2018-12-26 10:19:30 +00:00
} else {
shiftFreq = (shift / step) + 1;
2018-12-26 10:19:30 +00:00
}
2018-08-20 18:42:14 +00:00
// calculate 24-bit frequency
baseFreq = (base * 1000000.0) / phyLayer->getFreqStep();
2018-08-20 18:42:14 +00:00
2021-02-13 16:43:05 +00:00
// configure for direct mode
return(phyLayer->startDirect());
2018-08-20 18:42:14 +00:00
}
2018-08-23 07:21:05 +00:00
void RTTYClient::idle() {
2018-08-20 18:42:14 +00:00
mark();
}
size_t RTTYClient::write(uint8_t b) {
2023-04-29 20:54:27 +00:00
uint8_t dataBitsNum = 0;
switch(RadioLibPrint::encoding) {
case RADIOLIB_ASCII:
dataBitsNum = 7;
break;
case RADIOLIB_ASCII_EXTENDED:
dataBitsNum = 8;
break;
case RADIOLIB_ITA2:
dataBitsNum = 5;
break;
default:
return(0);
}
2018-08-20 18:42:14 +00:00
space();
uint16_t maxDataMask = 0x01 << (dataBitsNum - 1);
2020-09-12 11:53:28 +00:00
for(uint16_t mask = 0x01; mask <= maxDataMask; mask <<= 1) {
2018-08-20 18:42:14 +00:00
if(b & mask) {
mark();
} else {
space();
}
}
for(uint8_t i = 0; i < stopBitsNum; i++) {
2018-08-20 18:42:14 +00:00
mark();
}
2018-08-20 18:42:14 +00:00
return(1);
}
void RTTYClient::mark() {
Module* mod = phyLayer->getMod();
Use RadioLibTime_t (aka unsigned long) when dealing with millis() and micros() (#1075) * Use unsigned long when dealing with millis() and micros(). Although sizeof(uint32_t) == sizeof(unsigned long) on Arduino, this is not the case on 64-bit Linux, where sizeof(unsigned long) == sizeof(uint64_t). Most timestamp arithmetic and comparisons have been left alone, to reduce code churn. This is fine, as uint32_t is perfectly wide to store most timestamp deltas this library will deal with, and C will promote the integer rather than do a narrowing conversion. The real problem arises with narrowing conversions being done by assuming timestamps are 32-bit. No functional changes intended for platforms where sizeof(uint32_t) == sizeof(unsigned long) (so most 8/16/32-bit platforms). Signed-off-by: Elizabeth Myers <elizabeth.jennifer.myers@gmail.com> * Change most timestamps to use RadioLibTime_t. This makes it obvious what is and isn't a timestamp. Not everything has been converted; anything dealing with protocol and chip-level timestamps has been left alone on purpose, to make it clear that these functions do require 32-bit timestamps. No functional changes intended on platforms where sizeof(uint32_t) == sizeof(unsigned long). Signed-off-by: Elizabeth Myers <elizabeth.jennifer.myers@gmail.com> * Use uint32_t internally in getTimeOnAir. We need to not overflow the integers with the shifts and multiplications, so this is correct behaviour. Signed-off-by: Elizabeth Myers <elizabeth.jennifer.myers@gmail.com> --------- Signed-off-by: Elizabeth Myers <elizabeth.jennifer.myers@gmail.com>
2024-04-25 19:50:58 +00:00
RadioLibTime_t start = mod->hal->micros();
transmitDirect(baseFreq + shiftFreq, baseFreqHz + shiftFreqHz);
mod->waitForMicroseconds(start, bitDuration);
2018-08-20 18:42:14 +00:00
}
void RTTYClient::space() {
Module* mod = phyLayer->getMod();
Use RadioLibTime_t (aka unsigned long) when dealing with millis() and micros() (#1075) * Use unsigned long when dealing with millis() and micros(). Although sizeof(uint32_t) == sizeof(unsigned long) on Arduino, this is not the case on 64-bit Linux, where sizeof(unsigned long) == sizeof(uint64_t). Most timestamp arithmetic and comparisons have been left alone, to reduce code churn. This is fine, as uint32_t is perfectly wide to store most timestamp deltas this library will deal with, and C will promote the integer rather than do a narrowing conversion. The real problem arises with narrowing conversions being done by assuming timestamps are 32-bit. No functional changes intended for platforms where sizeof(uint32_t) == sizeof(unsigned long) (so most 8/16/32-bit platforms). Signed-off-by: Elizabeth Myers <elizabeth.jennifer.myers@gmail.com> * Change most timestamps to use RadioLibTime_t. This makes it obvious what is and isn't a timestamp. Not everything has been converted; anything dealing with protocol and chip-level timestamps has been left alone on purpose, to make it clear that these functions do require 32-bit timestamps. No functional changes intended on platforms where sizeof(uint32_t) == sizeof(unsigned long). Signed-off-by: Elizabeth Myers <elizabeth.jennifer.myers@gmail.com> * Use uint32_t internally in getTimeOnAir. We need to not overflow the integers with the shifts and multiplications, so this is correct behaviour. Signed-off-by: Elizabeth Myers <elizabeth.jennifer.myers@gmail.com> --------- Signed-off-by: Elizabeth Myers <elizabeth.jennifer.myers@gmail.com>
2024-04-25 19:50:58 +00:00
RadioLibTime_t start = mod->hal->micros();
transmitDirect(baseFreq, baseFreqHz);
mod->waitForMicroseconds(start, bitDuration);
2018-08-20 18:42:14 +00:00
}
2020-04-30 15:11:09 +00:00
int16_t RTTYClient::transmitDirect(uint32_t freq, uint32_t freqHz) {
#if !RADIOLIB_EXCLUDE_AFSK
if(audioClient != nullptr) {
return(audioClient->tone(freqHz));
2020-04-30 15:11:09 +00:00
}
2020-07-04 19:19:23 +00:00
#endif
return(phyLayer->transmitDirect(freq));
2020-04-30 15:11:09 +00:00
}
int16_t RTTYClient::standby() {
// ensure everything is stopped in interrupt timing mode
Module* mod = phyLayer->getMod();
mod->waitForMicroseconds(0, 0);
#if !RADIOLIB_EXCLUDE_AFSK
if(audioClient != nullptr) {
return(audioClient->noTone());
2020-04-30 15:11:09 +00:00
}
2020-07-04 19:19:23 +00:00
#endif
return(phyLayer->standby());
2020-04-30 15:11:09 +00:00
}
2020-06-30 08:45:52 +00:00
#endif