
* 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>
129 lines
2.9 KiB
C++
129 lines
2.9 KiB
C++
#include "FSK4.h"
|
|
#include <math.h>
|
|
#if !RADIOLIB_EXCLUDE_FSK4
|
|
|
|
FSK4Client::FSK4Client(PhysicalLayer* phy) {
|
|
phyLayer = phy;
|
|
#if !RADIOLIB_EXCLUDE_AFSK
|
|
audioClient = nullptr;
|
|
#endif
|
|
}
|
|
|
|
#if !RADIOLIB_EXCLUDE_AFSK
|
|
FSK4Client::FSK4Client(AFSKClient* audio) {
|
|
phyLayer = audio->phyLayer;
|
|
audioClient = audio;
|
|
}
|
|
#endif
|
|
|
|
int16_t FSK4Client::begin(float base, uint32_t shift, uint16_t rate) {
|
|
// save configuration
|
|
baseFreqHz = base;
|
|
shiftFreqHz = shift;
|
|
|
|
// calculate duration of 1 bit
|
|
bitDuration = (RadioLibTime_t)1000000/rate;
|
|
|
|
// calculate carrier shift
|
|
shiftFreq = getRawShift(shift);
|
|
|
|
// Write resultant tones into arrays for quick lookup when modulating.
|
|
for(uint8_t i = 0; i < 4; i++) {
|
|
tones[i] = shiftFreq*i;
|
|
tonesHz[i] = shiftFreqHz*i;
|
|
}
|
|
|
|
// calculate 24-bit frequency
|
|
baseFreq = (base * 1000000.0) / phyLayer->getFreqStep();
|
|
|
|
// configure for direct mode
|
|
return(phyLayer->startDirect());
|
|
}
|
|
|
|
void FSK4Client::idle() {
|
|
// Idle at Tone 0.
|
|
tone(0);
|
|
}
|
|
|
|
int16_t FSK4Client::setCorrection(int16_t offsets[], float length) {
|
|
for(uint8_t i = 0; i < 4; i++) {
|
|
tones[i] += getRawShift(offsets[i]);
|
|
tonesHz[i] += offsets[i];
|
|
}
|
|
bitDuration *= length;
|
|
return(RADIOLIB_ERR_NONE);
|
|
}
|
|
|
|
size_t FSK4Client::write(uint8_t* buff, size_t len) {
|
|
size_t n = 0;
|
|
for(size_t i = 0; i < len; i++) {
|
|
n += FSK4Client::write(buff[i]);
|
|
}
|
|
FSK4Client::standby();
|
|
return(n);
|
|
}
|
|
|
|
size_t FSK4Client::write(uint8_t b) {
|
|
// send symbols MSB first
|
|
for(uint8_t i = 0; i < 4; i++) {
|
|
// Extract 4FSK symbol (2 bits)
|
|
uint8_t symbol = (b & 0xC0) >> 6;
|
|
|
|
// Modulate
|
|
FSK4Client::tone(symbol);
|
|
|
|
// Shift to next symbol
|
|
b = b << 2;
|
|
}
|
|
|
|
return(1);
|
|
}
|
|
|
|
void FSK4Client::tone(uint8_t i) {
|
|
Module* mod = phyLayer->getMod();
|
|
RadioLibTime_t start = mod->hal->micros();
|
|
transmitDirect(baseFreq + tones[i], baseFreqHz + tonesHz[i]);
|
|
mod->waitForMicroseconds(start, bitDuration);
|
|
}
|
|
|
|
int16_t FSK4Client::transmitDirect(uint32_t freq, uint32_t freqHz) {
|
|
#if !RADIOLIB_EXCLUDE_AFSK
|
|
if(audioClient != nullptr) {
|
|
return(audioClient->tone(freqHz));
|
|
}
|
|
#endif
|
|
return(phyLayer->transmitDirect(freq));
|
|
}
|
|
|
|
int16_t FSK4Client::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());
|
|
}
|
|
#endif
|
|
return(phyLayer->standby());
|
|
}
|
|
|
|
int32_t FSK4Client::getRawShift(int32_t shift) {
|
|
// calculate module carrier frequency resolution
|
|
int32_t step = round(phyLayer->getFreqStep());
|
|
|
|
// check minimum shift value
|
|
if(abs(shift) < step / 2) {
|
|
return(0);
|
|
}
|
|
|
|
// round shift to multiples of frequency step size
|
|
if(abs(shift) % step < (step / 2)) {
|
|
return(shift / step);
|
|
}
|
|
if(shift < 0) {
|
|
return((shift / step) - 1);
|
|
}
|
|
return((shift / step) + 1);
|
|
}
|
|
|
|
#endif
|