2022-05-20 20:46:27 +00:00
# include <Task.h>
2022-04-02 01:20:16 +00:00
# include <TimeLib.h>
2022-05-20 20:46:27 +00:00
# include <logger.h>
2022-04-02 01:20:16 +00:00
2022-04-02 01:36:06 +00:00
# include "TaskRadiolib.h"
2022-04-02 01:20:16 +00:00
2022-04-02 23:39:56 +00:00
RadiolibTask : : RadiolibTask ( TaskQueue < std : : shared_ptr < APRSMessage > > & fromModem , TaskQueue < std : : shared_ptr < APRSMessage > > & toModem ) : Task ( TASK_RADIOLIB , TaskRadiolib ) , _fromModem ( fromModem ) , _toModem ( toModem ) {
2022-04-02 01:20:16 +00:00
}
RadiolibTask : : ~ RadiolibTask ( ) {
2022-04-02 04:16:24 +00:00
radio - > clearDio0Action ( ) ;
2022-04-02 01:20:16 +00:00
}
volatile bool RadiolibTask : : enableInterrupt = true ; // Need to catch interrupt or not.
volatile bool RadiolibTask : : operationDone = false ; // Caught IRQ or not.
void RadiolibTask : : setFlag ( void ) {
if ( ! enableInterrupt ) {
return ;
}
operationDone = true ;
}
bool RadiolibTask : : setup ( System & system ) {
2023-02-10 21:01:31 +00:00
SPI . begin ( system . getBoardConfig ( ) - > Lora . Sck , system . getBoardConfig ( ) - > Lora . Miso , system . getBoardConfig ( ) - > Lora . Mosi , system . getBoardConfig ( ) - > Lora . CS ) ;
module = new Module ( system . getBoardConfig ( ) - > Lora . CS , system . getBoardConfig ( ) - > Lora . IRQ , system . getBoardConfig ( ) - > Lora . Reset ) ;
2022-04-02 01:20:16 +00:00
radio = new SX1278 ( module ) ;
config = system . getUserConfig ( ) - > lora ;
rxEnable = true ;
txEnable = config . tx_enable ;
float freqMHz = ( float ) config . frequencyRx / 1000000 ;
float BWkHz = ( float ) config . signalBandwidth / 1000 ;
2022-04-02 09:50:54 +00:00
const uint16_t preambleLength = 8 ;
int16_t state = radio - > begin ( freqMHz , BWkHz , config . spreadingFactor , config . codingRate4 , RADIOLIB_SX127X_SYNC_WORD , config . power , preambleLength , config . gainRx ) ;
2022-04-02 01:20:16 +00:00
if ( state ! = RADIOLIB_ERR_NONE ) {
switch ( state ) {
case RADIOLIB_ERR_INVALID_FREQUENCY :
system . getLogger ( ) . log ( logging : : LoggerLevel : : LOGGER_LEVEL_ERROR , getName ( ) , " [%s] SX1278 init failed, The supplied frequency value (%fMHz) is invalid for this module. " , timeString ( ) . c_str ( ) , freqMHz ) ;
rxEnable = false ;
txEnable = false ;
break ;
case RADIOLIB_ERR_INVALID_BANDWIDTH :
system . getLogger ( ) . log ( logging : : LoggerLevel : : LOGGER_LEVEL_ERROR , getName ( ) , " [%s] SX1278 init failed, The supplied bandwidth value (%fkHz) is invalid for this module. Should be 7800, 10400, 15600, 20800, 31250, 41700 ,62500, 125000, 250000, 500000. " , timeString ( ) . c_str ( ) , BWkHz ) ;
rxEnable = false ;
txEnable = false ;
break ;
case RADIOLIB_ERR_INVALID_SPREADING_FACTOR :
system . getLogger ( ) . log ( logging : : LoggerLevel : : LOGGER_LEVEL_ERROR , getName ( ) , " [%s] SX1278 init failed, The supplied spreading factor value (%d) is invalid for this module. " , timeString ( ) . c_str ( ) , config . spreadingFactor ) ;
rxEnable = false ;
txEnable = false ;
break ;
case RADIOLIB_ERR_INVALID_CODING_RATE :
system . getLogger ( ) . log ( logging : : LoggerLevel : : LOGGER_LEVEL_ERROR , getName ( ) , " [%s] SX1278 init failed, The supplied coding rate value (%d) is invalid for this module. " , timeString ( ) . c_str ( ) , config . codingRate4 ) ;
rxEnable = false ;
txEnable = false ;
break ;
case RADIOLIB_ERR_INVALID_OUTPUT_POWER :
system . getLogger ( ) . log ( logging : : LoggerLevel : : LOGGER_LEVEL_ERROR , getName ( ) , " [%s] SX1278 init failed, The supplied output power value (%d) is invalid for this module. " , timeString ( ) . c_str ( ) , config . power ) ;
txEnable = false ;
break ;
case RADIOLIB_ERR_INVALID_PREAMBLE_LENGTH :
system . getLogger ( ) . log ( logging : : LoggerLevel : : LOGGER_LEVEL_ERROR , getName ( ) , " [%s] SX1278 init failed, The supplied preamble length is invalid. " , timeString ( ) . c_str ( ) ) ;
txEnable = false ;
break ;
case RADIOLIB_ERR_INVALID_GAIN :
system . getLogger ( ) . log ( logging : : LoggerLevel : : LOGGER_LEVEL_ERROR , getName ( ) , " [%s] SX1278 init failed, The supplied gain value (%d) is invalid. " , timeString ( ) . c_str ( ) , config . gainRx ) ;
rxEnable = false ;
break ;
default :
system . getLogger ( ) . log ( logging : : LoggerLevel : : LOGGER_LEVEL_ERROR , getName ( ) , " [%s] SX1278 init failed, code %d " , timeString ( ) . c_str ( ) , state ) ;
rxEnable = false ;
txEnable = false ;
}
2022-05-20 20:46:27 +00:00
_stateInfo = " LoRa-Modem failed " ;
_state = Error ;
2022-04-02 01:20:16 +00:00
}
state = radio - > setCRC ( true ) ;
if ( state ! = RADIOLIB_ERR_NONE ) {
system . getLogger ( ) . log ( logging : : LoggerLevel : : LOGGER_LEVEL_ERROR , getName ( ) , " [%s] setCRC failed, code %d " , timeString ( ) . c_str ( ) , state ) ;
2022-05-20 20:46:27 +00:00
_stateInfo = " LoRa-Modem failed " ;
_state = Error ;
2022-04-02 01:20:16 +00:00
}
radio - > setDio0Action ( setFlag ) ;
if ( rxEnable ) {
int state = startRX ( RADIOLIB_SX127X_RXCONTINUOUS ) ;
if ( state ! = RADIOLIB_ERR_NONE ) {
system . getLogger ( ) . log ( logging : : LoggerLevel : : LOGGER_LEVEL_ERROR , getName ( ) , " [%s] startRX failed, code %d " , timeString ( ) . c_str ( ) , state ) ;
2022-05-20 20:46:27 +00:00
rxEnable = false ;
_stateInfo = " LoRa-Modem failed " ;
_state = Error ;
2022-04-02 01:20:16 +00:00
}
}
2023-01-10 20:14:48 +00:00
if ( config . power > 17 & & config . tx_enable ) {
radio - > setCurrentLimit ( 140 ) ;
}
2022-04-02 09:50:54 +00:00
preambleDurationMilliSec = ( ( uint64_t ) ( preambleLength + 4 ) < < ( config . spreadingFactor + 10 /* to milli-sec */ ) ) / config . signalBandwidth ;
2022-05-20 20:46:27 +00:00
_stateInfo = " " ;
2022-04-02 01:20:16 +00:00
return true ;
}
int transmissionState = RADIOLIB_ERR_NONE ;
bool transmitFlag = false ; // Transmitting or not.
bool RadiolibTask : : loop ( System & system ) {
if ( operationDone ) { // occurs interrupt.
enableInterrupt = false ;
if ( transmitFlag ) { // transmitted.
if ( transmissionState = = RADIOLIB_ERR_NONE ) {
system . getLogger ( ) . log ( logging : : LoggerLevel : : LOGGER_LEVEL_DEBUG , getName ( ) , " [%s] TX done " , timeString ( ) . c_str ( ) ) ;
} else {
system . getLogger ( ) . log ( logging : : LoggerLevel : : LOGGER_LEVEL_ERROR , getName ( ) , " [%s] transmitFlag failed, code %d " , timeString ( ) . c_str ( ) , transmissionState ) ;
}
operationDone = false ;
transmitFlag = false ;
2022-04-02 09:50:54 +00:00
txWaitTimer . setTimeout ( preambleDurationMilliSec * 2 ) ;
txWaitTimer . start ( ) ;
2022-04-02 01:20:16 +00:00
} else { // received.
String str ;
int state = radio - > readData ( str ) ;
if ( state ! = RADIOLIB_ERR_NONE ) {
system . getLogger ( ) . log ( logging : : LoggerLevel : : LOGGER_LEVEL_ERROR , getName ( ) , " [%s] readData failed, code %d " , timeString ( ) . c_str ( ) , state ) ;
} else {
if ( str . substring ( 0 , 3 ) ! = " < \xff \x01 " ) {
2022-11-13 21:27:42 +00:00
system . getLogger ( ) . log ( logging : : LoggerLevel : : LOGGER_LEVEL_DEBUG , getName ( ) , " [%s] Unknown packet '%s' with RSSI %.0fdBm, SNR %.2fdB and FreqErr %fHz " , timeString ( ) . c_str ( ) , str . c_str ( ) , radio - > getRSSI ( ) , radio - > getSNR ( ) , - radio - > getFrequencyError ( ) ) ;
2022-04-02 01:20:16 +00:00
} else {
std : : shared_ptr < APRSMessage > msg = std : : shared_ptr < APRSMessage > ( new APRSMessage ( ) ) ;
msg - > decode ( str . substring ( 3 ) ) ;
_fromModem . addElement ( msg ) ;
system . getLogger ( ) . log ( logging : : LoggerLevel : : LOGGER_LEVEL_DEBUG , getName ( ) , " [%s] Received packet '%s' with RSSI %.0fdBm, SNR %.2fdB and FreqErr %fHz " , timeString ( ) . c_str ( ) , msg - > toString ( ) . c_str ( ) , radio - > getRSSI ( ) , radio - > getSNR ( ) , - radio - > getFrequencyError ( ) ) ;
system . getDisplay ( ) . addFrame ( std : : shared_ptr < DisplayFrame > ( new TextFrame ( " LoRa " , msg - > toString ( ) . c_str ( ) ) ) ) ;
}
}
operationDone = false ;
}
if ( rxEnable ) {
int state = startRX ( RADIOLIB_SX127X_RXCONTINUOUS ) ;
if ( state ! = RADIOLIB_ERR_NONE ) {
system . getLogger ( ) . log ( logging : : LoggerLevel : : LOGGER_LEVEL_ERROR , getName ( ) , " [%s] startRX failed, code %d " , timeString ( ) . c_str ( ) , state ) ;
rxEnable = false ;
}
}
enableInterrupt = true ;
} else { // not interrupt.
2022-04-02 09:50:54 +00:00
if ( ! txWaitTimer . check ( ) ) {
2022-04-02 01:20:16 +00:00
} else {
2022-04-02 09:50:54 +00:00
if ( ! txEnable ) {
// system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, getName(), "[%s] TX is not enabled", timeString().c_str());
2022-04-02 01:20:16 +00:00
} else {
2022-04-02 09:50:54 +00:00
if ( transmitFlag ) {
// system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, getName(), "[%s] TX signal detected. Waiting TX", timeString().c_str());
} else {
if ( ! _toModem . empty ( ) ) {
if ( config . frequencyRx = = config . frequencyTx & & ( radio - > getModemStatus ( ) & 0x01 ) = = 0x01 ) {
// system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, getName(), "[%s] RX signal detected. Waiting TX", timeString().c_str());
} else {
std : : shared_ptr < APRSMessage > msg = _toModem . getElement ( ) ;
system . getLogger ( ) . log ( logging : : LoggerLevel : : LOGGER_LEVEL_DEBUG , getName ( ) , " [%s] Transmitting packet '%s' " , timeString ( ) . c_str ( ) , msg - > toString ( ) . c_str ( ) ) ;
int16_t state = startTX ( " < \xff \x01 " + msg - > encode ( ) ) ;
if ( state ! = RADIOLIB_ERR_NONE ) {
system . getLogger ( ) . log ( logging : : LoggerLevel : : LOGGER_LEVEL_ERROR , getName ( ) , " [%s] startTX failed, code %d " , timeString ( ) . c_str ( ) , state ) ;
txEnable = false ;
return true ;
}
2022-04-02 01:20:16 +00:00
}
}
}
}
}
}
return true ;
}
int16_t RadiolibTask : : startRX ( uint8_t mode ) {
if ( config . frequencyTx ! = config . frequencyRx ) {
int16_t state = radio - > setFrequency ( ( float ) config . frequencyRx / 1000000 ) ;
if ( state ! = RADIOLIB_ERR_NONE ) {
return state ;
}
}
return radio - > startReceive ( 0 , mode ) ;
}
int16_t RadiolibTask : : startTX ( String & str ) {
if ( config . frequencyTx ! = config . frequencyRx ) {
int16_t state = radio - > setFrequency ( ( float ) config . frequencyTx / 1000000 ) ;
if ( state ! = RADIOLIB_ERR_NONE ) {
return state ;
}
}
transmissionState = radio - > startTransmit ( str ) ;
transmitFlag = true ;
return RADIOLIB_ERR_NONE ;
}