diff --git a/Firmware/LoRaSerial/Begin.ino b/Firmware/LoRaSerial/Begin.ino index abf9a2f4..26a7cabf 100644 --- a/Firmware/LoRaSerial/Begin.ino +++ b/Firmware/LoRaSerial/Begin.ino @@ -27,27 +27,6 @@ void blinkStartup() //========================================================================================= -//Initialize the radio layer -void beginLoRa() -{ - radio = arch.radio(); - - float centerFreq = (settings.frequencyMax - settings.frequencyMin) / 2; - centerFreq += settings.frequencyMin; - - int state = radio.begin(centerFreq); //Doesn't matter what freq we start at - if (state != RADIOLIB_ERR_NONE) - { - systemPrint("Radio init failed with code: "); - systemPrintln(state); - waitForever("Radio init failed!"); - } - - changeState(RADIO_RESET); -} - -//========================================================================================= - //Initialize the button driver void beginButton() { @@ -94,57 +73,3 @@ void petWDT() arch.petWDT(); } } - -//========================================================================================= - -void CheckChannelHopAndKickWatchdog(void) -{ - if (timeToHop == true) //If the channelTimer has expired, move to next frequency - hopChannel(); - - petWDT(); -} - -//========================================================================================= - -void CheckChannelHop(void) -{ - if (timeToHop == true) //If the channelTimer has expired, move to next frequency - hopChannel(); -} - -//========================================================================================= - -//Start the timer measuring the dwell interval and indicating that it is time to -//hop channels -void beginChannelTimer() -{ - if (channelTimer.attachInterruptInterval_MS(settings.maxDwellTime, channelTimerHandler) == false) - systemPrintln("Error starting ChannelTimer!"); - - stopChannelTimer(); //Start timer in state machine - beginChannelTimer -} - -//========================================================================================= - -//ISR that fires when channel timer expires -void channelTimerHandler() -{ - channelTimerStart = millis(); //Record when this ISR happened. Used for calculating clock sync. - radioCallHistory[RADIO_CALL_channelTimerHandler] = channelTimerStart; - - //If the last timer was used to sync clocks, restore full timer interval - if (reloadChannelTimer == true) - { - reloadChannelTimer = false; - channelTimer.setInterval_MS(settings.maxDwellTime, channelTimerHandler); - channelTimerMsec = settings.maxDwellTime; //ISR update - } - - if (settings.frequencyHop) - { - digitalWrite(pin_hop_timer, ((channelNumber + 1) % settings.numberOfChannels) & 1); - triggerEvent(TRIGGER_CHANNEL_TIMER_ISR); - timeToHop = true; - } -} diff --git a/Firmware/LoRaSerial/Commands.ino b/Firmware/LoRaSerial/Commands.ino index 22dfc0eb..3b850df8 100644 --- a/Firmware/LoRaSerial/Commands.ino +++ b/Firmware/LoRaSerial/Commands.ino @@ -221,7 +221,6 @@ bool commandAT(const char * commandString) systemPrintln(" ATI1 - Show board variant"); systemPrintln(" ATI2 - Show firmware version"); systemPrintln(" ATI3 - Display RSSI value"); - systemPrintln(" ATI4 - Get random byte from RSSI"); systemPrintln(" ATI5 - Show max possible bytes per second"); systemPrintln(" ATI6 - Display AES key"); systemPrintln(" ATI7 - Show current FHSS channel"); @@ -258,11 +257,7 @@ bool commandAT(const char * commandString) return true; case ('3'): //ATI3 - Display latest RSSI - systemPrintln(radio.getRSSI()); - return true; - - case ('4'): //ATI4 - Get random byte from RSSI - systemPrintln(radio.randomByte()); + systemPrintln(radioGetRSSI()); return true; case ('5'): //ATI5 - Show max possible bytes per second @@ -559,12 +554,12 @@ bool commandAT(const char * commandString) } else systemPrintln("None"); - systemPrint(" radio.startReceive Failure: "); + systemPrint(" radioStartReceive Failure: "); if (startReceiveFailureMillis) { systemPrintTimestamp(startReceiveFailureMillis + timestampOffset); systemPrintln(); - systemPrint(" radio.startReceive Status: "); + systemPrint(" radioStartReceive Status: "); systemPrintln(startReceiveFailureState); } else @@ -1375,6 +1370,7 @@ const COMMAND_ENTRY commands[] = {'P', 1, 0, 0, 1, 0, TYPE_BOOL, valInt, "CopyTriggers", &tempSettings.copyTriggers}, {'P', 1, 0, 0, 0xffffffff, 0, TYPE_U32, valInt, "TriggerEnable_31-0", &tempSettings.triggerEnable}, {'P', 1, 0, 0, 0xffffffff, 0, TYPE_U32, valInt, "TriggerEnable_63-32", &tempSettings.triggerEnable2}, + {'P', 1, 0, 0, 0xffffffff, 0, TYPE_U32, valInt, "TriggerEnable_95-64", &tempSettings.triggerEnable3}, {'P', 1, 0, 1, 255, 0, TYPE_U8, valInt, "TriggerWidth", &tempSettings.triggerWidth}, {'P', 1, 0, 0, 1, 0, TYPE_BOOL, valInt, "TriggerWidthIsMultiplier", &tempSettings.triggerWidthIsMultiplier}, diff --git a/Firmware/LoRaSerial/LoRaSerial.ino b/Firmware/LoRaSerial/LoRaSerial.ino index 9b434d02..49f7f215 100644 --- a/Firmware/LoRaSerial/LoRaSerial.ino +++ b/Firmware/LoRaSerial/LoRaSerial.ino @@ -151,7 +151,6 @@ uint8_t pin_hop_timer = PIN_UNDEFINED; //Radio Library //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- #include //Click here to get the library: http://librarymanager/All#RadioLib v5.6.0 -SX1276 radio = NULL; //We can't instantiate here because we don't yet know what pin numbers to use float *channels; uint8_t channelNumber = 0; @@ -190,7 +189,6 @@ bool inTraining; //True if training is in process SAMDTimer channelTimer(TIMER_TCC); //Available: TC3, TC4, TC5, TCC, TCC1 or TCC2 volatile uint16_t channelTimerMsec; //Last value programmed into the channel timer volatile unsigned long channelTimerStart = 0; //Tracks how long our timer has been running since last hop -volatile bool timeToHop = false; //Set by channelTimerHandler to indicate that hopChannel needs to be called volatile bool reloadChannelTimer = false; //When set channel timer interval needs to be reloaded with settings.maxDwellTime //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= @@ -658,12 +656,10 @@ void setup() arch.uniqueID(myUniqueId); //Get the unique ID - beginLoRa(); //Start radio + radioBeginLoRa(); //Start radio beginButton(); //Start watching the train button - beginChannelTimer(); //Setup (but do not start) hardware timer for channel hopping - updateRTS(true); //We're ready for more data systemPrintTimestamp(); diff --git a/Firmware/LoRaSerial/Radio.ino b/Firmware/LoRaSerial/Radio.ino index 0ddbcf00..245ddae0 100644 --- a/Firmware/LoRaSerial/Radio.ino +++ b/Firmware/LoRaSerial/Radio.ino @@ -1,5 +1,482 @@ //========================================================================================= // Radio.ino +// +// Hop synchronization between LoRaSerial radios is maintained with a +// hardware timer (channelTimer) interrupt routine. The hop timer +// interrupt needs to switch frequencies which requires a SPI +// transaction with the radio. To prevent other SPI transactions with +// the radio from being interrupted, all SPI transactions need to be +// done within a critical section (interrupts disabled). The following +// radio support routines are the only routines that reference the radio +// structure. No other radio. calls should be made! +//========================================================================================= + +static SX1276 radio = NULL; //We can't instantiate here because we don't yet know what pin numbers to use + +int16_t radioAutoLDRO() +{ + int16_t status; + + noInterrupts(); + status = radio.autoLDRO(); + interrupts(); + return status; +} + +//========================================================================================= + +//Initialize the radio layer +void radioBeginLoRa() +{ + int16_t status; + + float centerFrequency = (settings.frequencyMax - settings.frequencyMin) / 2; + centerFrequency += settings.frequencyMin; + + // Disabling interrupts here causes the system to crash!!! + // + // Since this call is made only during setup and the channel timer is + // not running yet, it is not possible for the SPI operations to get + // interrupted during these radio calls. + radio = arch.radio(); + status = radio.begin(centerFrequency); //Doesn't matter what freq we start at + if (status != RADIOLIB_ERR_NONE) + { + systemPrint("Radio init failed with code: "); + systemPrintln(status); + waitForever("Radio init failed!"); + } + + // Establish the channel (hop) timer interrupt handler + if (!channelTimer.attachInterruptInterval_MS(settings.maxDwellTime, + channelTimerHandler)) + waitForever("Error starting ChannelTimer!"); + + // Stop the timer + stopChannelTimer(); //Start timer in state machine - beginChannelTimer + + changeState(RADIO_RESET); +} + +//========================================================================================= + +void radioClearFHSSInt() +{ + noInterrupts(); + radio.clearFHSSInt(); + interrupts(); +} + +//========================================================================================= + +int16_t radioExplicitHeader() +{ + int16_t status; + + noInterrupts(); + status = radio.explicitHeader(); + interrupts(); + return status; +} + +//========================================================================================= + +int16_t radioForceLDRO(bool enable) +{ + int16_t status; + + noInterrupts(); + status = radio.forceLDRO(enable); + interrupts(); + return status; +} + +//========================================================================================= + +float radioGetFrequencyError() +{ + float frequencyError; + + noInterrupts(); + frequencyError = radio.getFrequencyError(); + interrupts(); + return frequencyError; +} + +//========================================================================================= + +uint16_t radioGetIRQFlags() +{ + uint16_t irqFlags; + + noInterrupts(); + irqFlags = radio.getIRQFlags(); + interrupts(); + return irqFlags; +} + +//========================================================================================= + +uint8_t radioGetModemStatus() +{ + uint8_t radioStatus; + + noInterrupts(); + radioStatus = radio.getModemStatus(); + interrupts(); + return radioStatus; +} + +//========================================================================================= + +size_t radioGetPacketLength() +{ + size_t packetLength; + + noInterrupts(); + packetLength = radio.getPacketLength(); + interrupts(); + return packetLength; +} + +//========================================================================================= + +int radioGetRSSI() +{ + int RSSI; + + noInterrupts(); + RSSI = radio.getRSSI(); + interrupts(); + return RSSI; +} + +//========================================================================================= + +float radioGetSNR() +{ + float signalToNoiseRatio; + + noInterrupts(); + signalToNoiseRatio = radio.getSNR(); + interrupts(); + return signalToNoiseRatio; +} + +//========================================================================================= + +int16_t radioImplicitHeader(size_t len) +{ + int16_t status; + + noInterrupts(); + status = radio.implicitHeader(len); + interrupts(); + return status; +} + +//========================================================================================= + +uint8_t radioRandomByte() +{ + int16_t status; + + // Disabling interrupts around this call causes the system to reset!!! + // + // Instead disable the channel (hop) timer to eliminate any SPI + // transactions interrupting the SPI transactions made by calling + // radio.randomByte + // + // This routine is called only during the RADIO_RESET state and training + stopChannelTimer(); + status = radio.randomByte(); + return status; +} + +//========================================================================================= + +int16_t radioReadData(uint8_t * buffer, size_t bufferLength) +{ + int16_t status; + + noInterrupts(); + status = radio.readData(buffer, bufferLength); + interrupts(); + return status; +} + +//========================================================================================= + +int16_t radioSetBandwidth(float bandwidth) +{ + int16_t status; + + noInterrupts(); + status = radio.setBandwidth(bandwidth); + interrupts(); + return status; +} + +//========================================================================================= + +int16_t radioSetCodingRate(uint8_t codingRate) +{ + int16_t status; + + noInterrupts(); + status = radio.setCodingRate(codingRate); + interrupts(); + return status; +} + +//========================================================================================= + +int16_t radioSetCRC(bool enable) +{ + int16_t status; + + noInterrupts(); + status = radio.setCRC(enable); + interrupts(); + return status; +} + +//========================================================================================= + +int16_t radioSetDio0Action(void (*function)(void)) +{ + int16_t status; + + noInterrupts(); + radio.setDio0Action(function); + interrupts(); + return status; +} + +//========================================================================================= + +int16_t radioSetDio1Action(void (*function)(void)) +{ + int16_t status; + + noInterrupts(); + radio.setDio1Action(function); + interrupts(); + return status; +} + +//========================================================================================= + +int16_t radioSetFHSSHoppingPeriod(uint8_t freqHoppingPeriod) +{ + int16_t status; + + noInterrupts(); + status = radio.setFHSSHoppingPeriod(freqHoppingPeriod); + interrupts(); + return status; +} + +//========================================================================================= + +int16_t radioSetFrequency(bool inInterruptRoutine, float frequency) +{ + int16_t status; + + if (inInterruptRoutine) + return radio.setFrequency(frequency); + + // Disable interrupts to prevent the channel (hop) timer interrupt + // from interrupting and corrupting the SPI operations necessary to + // change the frequency. + noInterrupts(); + status = radio.setFrequency(frequency); + interrupts(); + return status; +} + +//========================================================================================= + +int16_t radioSetOutputPower(int8_t power) +{ + int16_t status; + + noInterrupts(); + status = radio.setOutputPower(power); + interrupts(); + return status; +} + +//========================================================================================= + +int16_t radioSetPreambleLength(uint16_t preambleLength) +{ + int16_t status; + + noInterrupts(); + status = radio.setPreambleLength(preambleLength); + interrupts(); + return status; +} + +//========================================================================================= + +void radioSetRfSwitchPins(RADIOLIB_PIN_TYPE rxEn, RADIOLIB_PIN_TYPE txEn) +{ + noInterrupts(); + radio.setRfSwitchPins(rxEn, txEn); + interrupts(); +} + +//========================================================================================= + +int16_t radioSetSpreadingFactor(uint8_t spreadFactor) +{ + int16_t status; + + noInterrupts(); + status = radio.setSpreadingFactor(spreadFactor); + interrupts(); + return status; +} + +//========================================================================================= + +int16_t radioSetSyncWord(uint8_t syncWord) +{ + int16_t status; + + noInterrupts(); + status = radio.setSyncWord(syncWord); + interrupts(); + return status; +} + +//========================================================================================= + +int radioStartReceive() +{ + int state; + + noInterrupts(); + state = radio.startReceive(); + interrupts(); + return state; +} + +int radioStartReceive(uint8_t expectedSize) +{ + int state; + + noInterrupts(); + state = radio.startReceive(expectedSize); + interrupts(); + return state; +} + +//========================================================================================= + +int radioStartTransmit(uint8_t * buffer, uint8_t lengthInBytes) +{ + int state; + + noInterrupts(); + state = radio.startTransmit(buffer, lengthInBytes); + interrupts(); + return state; +} + +//========================================================================================= +#ifdef RADIOLIB_LOW_LEVEL +//========================================================================================= + +//Read a register from the SX1276 chip +uint8_t readSX1276Register(uint8_t reg) +{ + uint8_t data; + + radioCallHistory[RADIO_CALL_readSX1276Register] = millis(); + + noInterrupts(); + data = radio._mod->SPIreadRegister(reg); + interrupts(); + return data; +} + +//========================================================================================= + +//SX1276 LoRa Register Names +const char * const sx1276RegisterNames[] = +{ + NULL, "RegOpMode", NULL, NULL, // 0 - 3 + NULL, NULL, "RegFrfMsb", "RegFrfMid", // 4 - 7 + "RegFrfLsb", "RegPaConfig", "RegPaRamp", "RegOcp", // 8 - b + "RegLna", "RegFifoAddrPtr", "RegFifoTxBaseAddr", "regFifoRxBaseAddr", // c - f + + "FifoRxCurrentAddr", "RegIrqFlagsMask", "RegIrqFlags", "RegRxNbBytes", //10 - 13 + "RegRxHeaderCntValueMsb", "RegRxHeaderCntValueLsb", "RegRxPacketCntValueMsb", "RegRxPacketCntValueLsb", //14 - 17 + "RegModemStat", "RegPktSnrValue", "RegPktRssiValue", "RegRssiValue", //18 - 1b + "RegHopChannel", "RegModemConfig1", "RegModemConfig2", "RegSymbTimeoutLsb", //1c - 1f + + "RegPreambleMsb", "RegPreambleLsb", "RegPayloadLength", "RegMaxPayloadLength",//20 - 23 + "RegHopPeriod", "RegFifoRxByteAddr", "RegModemConfig3", NULL, //24 - 27 + "RegFeiMsb", "RegFeiMid", "RegFeiLsb", NULL, //28 - 2b + "RegRssiWideband", NULL, NULL, "RegIfFreq1", //2c - 2f + + "RegIfFreq2", "ReqDetectOptimize", NULL, "ReqInvertIQ", //30 - 33 + NULL, NULL, "RegHighBwOpimize1", "RegDetectionThreshold", //34 - 37 + NULL, "RegSyncWord", "RegHighBwOptimize2", "RegInvertIQ2", //38 - 3b + NULL, NULL, NULL, NULL, //3c - 3f + + "RegDioMapping1", "RegDioMapping2", "RegVersion", NULL, //40 - 43 + NULL, NULL, NULL, NULL, //44 - 47 + NULL, NULL, NULL, "RegTcxo", //48 - 4b + NULL, "RegPaDac", NULL, NULL, //4C - 4F + + NULL, NULL, NULL, NULL, //50 - 53 + NULL, NULL, NULL, NULL, //54 - 57 + NULL, NULL, NULL, "RegFormerTemp", //58 - 5b + NULL, NULL, NULL, NULL, //5c - 5f + + NULL, "RegAgcRef", "RegAgcThresh1", "RegAgcThresh2", //60 - 63 + "RegAgcThresh3", NULL, NULL, NULL, //64 - 67 + NULL, NULL, NULL, NULL, //68 - 6b + NULL, NULL, NULL, NULL, //6c - 6f + + "RegPII", //70 +}; + +//Print the SX1276 LoRa registers +void printSX1276Registers() +{ + radioCallHistory[RADIO_CALL_printSX1276Registers] = millis(); + + petWDT(); + systemPrintln("SX1276 Registers:"); + systemPrintln(" Reg Value Name"); + for (uint8_t i = 0; i < (sizeof(sx1276RegisterNames) / sizeof(sx1276RegisterNames[0])); i++) + { + //Only read and print the valid registers + if (sx1276RegisterNames[i]) + { + systemPrint(" 0x"); + systemPrint(i, HEX); + systemPrint(": 0x"); + systemPrint(readSX1276Register(i), HEX); + systemPrint(", "); + systemPrintln(sx1276RegisterNames[i]); + outputSerialData(true); + petWDT(); + } + } +} + +//========================================================================================= +#endif //RADIOLIB_LOW_LEVEL +//========================================================================================= + +//========================================================================================= +//***** All "radio." references must be in this module and above this line!!! ***** //========================================================================================= //Apply settings to radio @@ -11,43 +488,43 @@ bool configureRadio() radioCallHistory[RADIO_CALL_configureRadio] = millis(); channelNumber = 0; - if (!setRadioFrequency(false)) + if (!setRadioFrequency(false, false)) success = false; //The SX1276 and RadioLib accepts a value of 2 to 17, with 20 enabling the power amplifier //Measuring actual power output the radio will output 14dBm (25mW) to 27.9dBm (617mW) in constant transmission //So we use a lookup to convert between the user's chosen power and the radio setting int radioPowerSetting = covertdBmToSetting(settings.radioBroadcastPower_dbm); - if (radio.setOutputPower(radioPowerSetting) == RADIOLIB_ERR_INVALID_OUTPUT_POWER) + if (radioSetOutputPower(radioPowerSetting) == RADIOLIB_ERR_INVALID_OUTPUT_POWER) success = false; - if (radio.setBandwidth(settings.radioBandwidth) == RADIOLIB_ERR_INVALID_BANDWIDTH) + if (radioSetBandwidth(settings.radioBandwidth) == RADIOLIB_ERR_INVALID_BANDWIDTH) success = false; - if (radio.setSpreadingFactor(settings.radioSpreadFactor) == RADIOLIB_ERR_INVALID_SPREADING_FACTOR) + if (radioSetSpreadingFactor(settings.radioSpreadFactor) == RADIOLIB_ERR_INVALID_SPREADING_FACTOR) success = false; - if (radio.setCodingRate(settings.radioCodingRate) == RADIOLIB_ERR_INVALID_CODING_RATE) + if (radioSetCodingRate(settings.radioCodingRate) == RADIOLIB_ERR_INVALID_CODING_RATE) success = false; - if (radio.setSyncWord(settings.radioSyncWord) != RADIOLIB_ERR_NONE) + if (radioSetSyncWord(settings.radioSyncWord) != RADIOLIB_ERR_NONE) success = false; - if (radio.setPreambleLength(settings.radioPreambleLength) == RADIOLIB_ERR_INVALID_PREAMBLE_LENGTH) + if (radioSetPreambleLength(settings.radioPreambleLength) == RADIOLIB_ERR_INVALID_PREAMBLE_LENGTH) success = false; - if (radio.setCRC(true) == RADIOLIB_ERR_INVALID_CRC_CONFIGURATION) //Enable hardware CRC + if (radioSetCRC(true) == RADIOLIB_ERR_INVALID_CRC_CONFIGURATION) //Enable hardware CRC success = false; //SF6 requires an implicit header. We will transmit 255 bytes for most packets and 2 bytes for ACK packets. if (settings.radioSpreadFactor == 6) { - if (radio.implicitHeader(MAX_PACKET_SIZE) != RADIOLIB_ERR_NONE) + if (radioImplicitHeader(MAX_PACKET_SIZE) != RADIOLIB_ERR_NONE) success = false; } else { - if (radio.explicitHeader() != RADIOLIB_ERR_NONE) + if (radioExplicitHeader() != RADIOLIB_ERR_NONE) success = false; } @@ -55,20 +532,20 @@ bool configureRadio() uint16_t airSpeed = convertSettingsToAirSpeed(&settings); if (airSpeed <= 400) { - if (radio.forceLDRO(true) != RADIOLIB_ERR_NONE) + if (radioForceLDRO(true) != RADIOLIB_ERR_NONE) success = false; } else { - if (radio.autoLDRO() != RADIOLIB_ERR_NONE) + if (radioAutoLDRO() != RADIOLIB_ERR_NONE) success = false; } - radio.setDio0Action(transactionCompleteISR); //Called when transmission is finished - radio.setDio1Action(hopISR); //Called after a transmission has started, so we can move to next freq + radioSetDio0Action(transactionCompleteISR); //Called when transmission is finished + radioSetDio1Action(hopISR); //Called after a transmission has started, so we can move to next freq if (pin_rxen != PIN_UNDEFINED) - radio.setRfSwitchPins(pin_rxen, pin_txen); + radioSetRfSwitchPins(pin_rxen, pin_txen); // HoppingPeriod = Tsym * FreqHoppingPeriod // Given defaults of spreadfactor = 9, bandwidth = 125, it follows Tsym = 4.10ms @@ -76,7 +553,7 @@ bool configureRadio() uint16_t hoppingPeriod = settings.maxDwellTime / calcSymbolTimeMsec(); //Limit FHSS dwell time to 400ms max. / automatically floors number if (hoppingPeriod > 255) hoppingPeriod = 255; //Limit to 8 bits. if (settings.frequencyHop == false) hoppingPeriod = 0; //Disable - if (radio.setFHSSHoppingPeriod(hoppingPeriod) != RADIOLIB_ERR_NONE) + if (radioSetFHSSHoppingPeriod(hoppingPeriod) != RADIOLIB_ERR_NONE) success = false; if ((settings.debug == true) || (settings.debugRadio == true)) @@ -187,7 +664,7 @@ uint16_t convertSettingsToAirSpeed(Settings *newSettings) //========================================================================================= //Set radio frequency -bool setRadioFrequency(bool rxAdjust) +bool setRadioFrequency(bool inInterruptRoutine, bool rxAdjust) { float previousFrequency; static uint8_t previousChannelNumber; @@ -201,7 +678,7 @@ bool setRadioFrequency(bool rxAdjust) radioFrequency -= frequencyCorrection; //Set the new frequency - if (radio.setFrequency(radioFrequency) == RADIOLIB_ERR_INVALID_FREQUENCY) + if (radioSetFrequency(inInterruptRoutine, radioFrequency) == RADIOLIB_ERR_INVALID_FREQUENCY) return false; if (settings.debugSync) @@ -244,14 +721,14 @@ void returnToReceiving() int state; if (settings.radioSpreadFactor > 6) { - state = radio.startReceive(); + state = radioStartReceive(); } else { if (settings.operatingMode == MODE_POINT_TO_POINT) { - radio.implicitHeader(sf6ExpectedSize); - state = radio.startReceive(sf6ExpectedSize); //Set the size we expect to see + radioImplicitHeader(sf6ExpectedSize); + state = radioStartReceive(sf6ExpectedSize); //Set the size we expect to see if (sf6ExpectedSize < MAX_PACKET_SIZE) triggerEvent(TRIGGER_RTR_SHORT_PACKET); @@ -571,12 +1048,38 @@ uint16_t myRand() //========================================================================================= +//ISR that fires when channel timer expires +void channelTimerHandler() +{ + channelTimerStart = millis(); //Record when this ISR happened. Used for calculating clock sync. + radioCallHistory[RADIO_CALL_channelTimerHandler] = channelTimerStart; + + //If the last timer was used to sync clocks, restore full timer interval + if (reloadChannelTimer == true) + { + reloadChannelTimer = false; + channelTimer.setInterval_MS(settings.maxDwellTime, channelTimerHandler); + channelTimerMsec = settings.maxDwellTime; //ISR update + } + + if (settings.frequencyHop) + { + // Move to the next channel + hopChannel(true, true, 1); //Move forward + + digitalWrite(pin_hop_timer, (channelNumber % settings.numberOfChannels) & 1); + triggerEvent(TRIGGER_CHANNEL_TIMER_ISR); + } +} + +//========================================================================================= + //Move to the next channel //This is called when the FHSS interrupt is received //at the beginning and during of a transmission or reception void hopChannel() { - hopChannel(true, 1); //Move forward + hopChannel(false, true, 1); //Move forward } //========================================================================================= @@ -584,18 +1087,16 @@ void hopChannel() //Hop to the previous channel in the frequency list void hopChannelReverse() { - hopChannel(false, 1); //Move backward + hopChannel(false, false, 1); //Move backward } //========================================================================================= //Set the next radio frequency given the hop direction and frequency table -void hopChannel(bool moveForwardThroughTable, uint8_t channelCount) +void hopChannel(bool inInterruptRoutine, bool moveForwardThroughTable, uint8_t channelCount) { radioCallHistory[RADIO_CALL_hopChannel] = millis(); - timeToHop = false; - if (moveForwardThroughTable) channelNumber += channelCount; else @@ -603,7 +1104,7 @@ void hopChannel(bool moveForwardThroughTable, uint8_t channelCount) channelNumber %= settings.numberOfChannels; //Select the new frequency - setRadioFrequency(radioStateTable[radioState].rxState); + setRadioFrequency(inInterruptRoutine, radioStateTable[radioState].rxState); blinkChannelHopLed(true); } @@ -630,7 +1131,7 @@ unsigned long mSecToChannelZero() //Returns true if the radio indicates we have an ongoing reception bool receiveInProcess(bool startClock) { - uint8_t radioStatus = radio.getModemStatus(); + uint8_t radioStatus = radioGetModemStatus(); radioStatus &= 0b11011; //Get bits 0, 1, 3, and 4 //Known states where a reception is in progress @@ -679,88 +1180,6 @@ uint8_t covertdBmToSetting(uint8_t userSetting) } } -//========================================================================================= -#ifdef RADIOLIB_LOW_LEVEL -//========================================================================================= - -//Read a register from the SX1276 chip -uint8_t readSX1276Register(uint8_t reg) -{ - radioCallHistory[RADIO_CALL_readSX1276Register] = millis(); - - return radio._mod->SPIreadRegister(reg); -} - -//========================================================================================= - -//SX1276 LoRa Register Names -const char * const sx1276RegisterNames[] = -{ - NULL, "RegOpMode", NULL, NULL, // 0 - 3 - NULL, NULL, "RegFrfMsb", "RegFrfMid", // 4 - 7 - "RegFrfLsb", "RegPaConfig", "RegPaRamp", "RegOcp", // 8 - b - "RegLna", "RegFifoAddrPtr", "RegFifoTxBaseAddr", "regFifoRxBaseAddr", // c - f - - "FifoRxCurrentAddr", "RegIrqFlagsMask", "RegIrqFlags", "RegRxNbBytes", //10 - 13 - "RegRxHeaderCntValueMsb", "RegRxHeaderCntValueLsb", "RegRxPacketCntValueMsb", "RegRxPacketCntValueLsb", //14 - 17 - "RegModemStat", "RegPktSnrValue", "RegPktRssiValue", "RegRssiValue", //18 - 1b - "RegHopChannel", "RegModemConfig1", "RegModemConfig2", "RegSymbTimeoutLsb", //1c - 1f - - "RegPreambleMsb", "RegPreambleLsb", "RegPayloadLength", "RegMaxPayloadLength",//20 - 23 - "RegHopPeriod", "RegFifoRxByteAddr", "RegModemConfig3", NULL, //24 - 27 - "RegFeiMsb", "RegFeiMid", "RegFeiLsb", NULL, //28 - 2b - "RegRssiWideband", NULL, NULL, "RegIfFreq1", //2c - 2f - - "RegIfFreq2", "ReqDetectOptimize", NULL, "ReqInvertIQ", //30 - 33 - NULL, NULL, "RegHighBwOpimize1", "RegDetectionThreshold", //34 - 37 - NULL, "RegSyncWord", "RegHighBwOptimize2", "RegInvertIQ2", //38 - 3b - NULL, NULL, NULL, NULL, //3c - 3f - - "RegDioMapping1", "RegDioMapping2", "RegVersion", NULL, //40 - 43 - NULL, NULL, NULL, NULL, //44 - 47 - NULL, NULL, NULL, "RegTcxo", //48 - 4b - NULL, "RegPaDac", NULL, NULL, //4C - 4F - - NULL, NULL, NULL, NULL, //50 - 53 - NULL, NULL, NULL, NULL, //54 - 57 - NULL, NULL, NULL, "RegFormerTemp", //58 - 5b - NULL, NULL, NULL, NULL, //5c - 5f - - NULL, "RegAgcRef", "RegAgcThresh1", "RegAgcThresh2", //60 - 63 - "RegAgcThresh3", NULL, NULL, NULL, //64 - 67 - NULL, NULL, NULL, NULL, //68 - 6b - NULL, NULL, NULL, NULL, //6c - 6f - - "RegPII", //70 -}; - -//Print the SX1276 LoRa registers -void printSX1276Registers() -{ - radioCallHistory[RADIO_CALL_printSX1276Registers] = millis(); - - petWDT(); - systemPrintln("SX1276 Registers:"); - systemPrintln(" Reg Value Name"); - for (uint8_t i = 0; i < (sizeof(sx1276RegisterNames) / sizeof(sx1276RegisterNames[0])); i++) - { - //Only read and print the valid registers - if (sx1276RegisterNames[i]) - { - systemPrint(" 0x"); - systemPrint(i, HEX); - systemPrint(": 0x"); - systemPrint(readSX1276Register(i), HEX); - systemPrint(", "); - systemPrintln(sx1276RegisterNames[i]); - outputSerialData(true); - petWDT(); - } - } -} - -//========================================================================================= -#endif //RADIOLIB_LOW_LEVEL //========================================================================================= //ISR when DIO0 goes low @@ -803,7 +1222,7 @@ void updateHopISR() if (hop) //Clear hop ISR as needed { hop = false; - radio.clearFHSSInt(); //Clear the interrupt + radioClearFHSSInt(); //Clear the interrupt } } @@ -1742,11 +2161,11 @@ PacketType rcvDatagram() rcvTimeMillis = millis(); //Get the IRQ flags - irqFlags = radio.getIRQFlags(); + irqFlags = radioGetIRQFlags(); //Get the received datagram framesReceived++; - int state = radio.readData(incomingBuffer, MAX_PACKET_SIZE); + int state = radioReadData(incomingBuffer, MAX_PACKET_SIZE); printPacketQuality(); //Display the RSSI, SNR and frequency error values @@ -1754,7 +2173,7 @@ PacketType rcvDatagram() { rxSuccessMillis = rcvTimeMillis; triggerEvent(TRIGGER_RX_SPI_DONE); - packetRSSI = radio.getRSSI(); + packetRSSI = radioGetRSSI(); } else { @@ -1785,7 +2204,7 @@ PacketType rcvDatagram() } } - rxDataBytes = radio.getPacketLength(); + rxDataBytes = radioGetPacketLength(); packetLength = rxDataBytes; //Total bytes received, used for calculating clock sync times in multi-point mode returnToReceiving(); //Immediately begin listening while we process new data @@ -1820,7 +2239,7 @@ PacketType rcvDatagram() systemPrint(rxDataBytes, HEX); systemPrintln(") bytes"); outputSerialData(true); - CheckChannelHopAndKickWatchdog(); + petWDT(); if (settings.printRfData && rxDataBytes) dumpBuffer(incomingBuffer, rxDataBytes); outputSerialData(true); @@ -1830,10 +2249,7 @@ PacketType rcvDatagram() radioComputeWhitening(incomingBuffer, rxDataBytes); if (settings.encryptData == true) - { decryptBuffer(incomingBuffer, rxDataBytes); - CheckChannelHop(); - } if (settings.debugReceive) { @@ -1852,7 +2268,7 @@ PacketType rcvDatagram() systemPrint(rxDataBytes, HEX); systemPrintln(") bytes"); outputSerialData(true); - CheckChannelHopAndKickWatchdog(); + petWDT(); if (settings.printRfData && rxDataBytes) dumpBuffer(incomingBuffer, rxDataBytes); outputSerialData(true); @@ -1871,7 +2287,7 @@ PacketType rcvDatagram() systemPrint(rxDataBytes, HEX); systemPrintln(") bytes"); outputSerialData(true); - CheckChannelHopAndKickWatchdog(); + petWDT(); if (settings.printRfData && rxDataBytes) dumpBuffer(incomingBuffer, rxDataBytes); outputSerialData(true); @@ -1915,7 +2331,7 @@ PacketType rcvDatagram() systemPrintln(); outputSerialData(true); } - CheckChannelHopAndKickWatchdog(); + petWDT(); if (settings.debugReceive && settings.printPktData && rxDataBytes) dumpBuffer(incomingBuffer, rxDataBytes); outputSerialData(true); @@ -1923,7 +2339,7 @@ PacketType rcvDatagram() return (DATAGRAM_NETID_MISMATCH); } } // MODE_POINT_TO_POINT - CheckChannelHopAndKickWatchdog(); + petWDT(); //Process the trailer if (settings.enableCRC16) @@ -1933,10 +2349,8 @@ PacketType rcvDatagram() //Compute the CRC-16 value crc = 0xffff; - CheckChannelHop(); for (data = incomingBuffer; data < &incomingBuffer[rxDataBytes - 2]; data++) crc = crc16Table[*data ^ (uint8_t)(crc >> (16 - 8))] ^ (crc << 8); - CheckChannelHop(); if ((incomingBuffer[rxDataBytes - 2] != (crc >> 8)) || (incomingBuffer[rxDataBytes - 1] != (crc & 0xff))) { @@ -1950,7 +2364,7 @@ PacketType rcvDatagram() systemPrint(" expected 0x"); systemPrintln(crc, HEX); outputSerialData(true); - CheckChannelHopAndKickWatchdog(); + petWDT(); if (settings.printRfData && rxDataBytes) dumpBuffer(incomingBuffer, rxDataBytes); outputSerialData(true); @@ -2016,7 +2430,6 @@ PacketType rcvDatagram() systemPrint(incomingBuffer[rxDataBytes - 2], HEX); systemPrintln(incomingBuffer[rxDataBytes - 1], HEX); outputSerialData(true); - CheckChannelHop(); } /* @@ -2043,7 +2456,6 @@ PacketType rcvDatagram() systemPrint(" Channel Timer(ms): "); systemPrintln(msToNextHopRemote); outputSerialData(true); - CheckChannelHop(); } } @@ -2076,7 +2488,6 @@ PacketType rcvDatagram() systemPrint((int)rxDataBytes - minDatagramSize); systemPrintln(" received bytes"); outputSerialData(true); - CheckChannelHop(); } badFrames++; return (DATAGRAM_BAD); @@ -2087,7 +2498,6 @@ PacketType rcvDatagram() systemPrint(" SF6 Length: "); systemPrintln(rxDataBytes); outputSerialData(true); - CheckChannelHop(); } } else //SF6 @@ -2107,7 +2517,6 @@ PacketType rcvDatagram() systemPrint(rxDataBytes); systemPrintln(" bytes, expecting at least 3 bytes"); outputSerialData(true); - CheckChannelHop(); } badFrames++; return DATAGRAM_BAD; @@ -2136,7 +2545,6 @@ PacketType rcvDatagram() else systemPrintln(rxSrcVc); outputSerialData(true); - CheckChannelHop(); } //Validate the source VC @@ -2151,7 +2559,6 @@ PacketType rcvDatagram() systemPrint("Invalid source VC: "); systemPrintln(rxSrcVc); outputSerialData(true); - CheckChannelHop(); if (settings.printRfData && rxDataBytes) dumpBuffer(incomingBuffer, rxDataBytes); outputSerialData(true); @@ -2174,7 +2581,6 @@ PacketType rcvDatagram() systemPrintln(rxDataBytes); outputSerialData(true); } - CheckChannelHop(); if (vc) vc->badLength++; badFrames++; @@ -2190,7 +2596,6 @@ PacketType rcvDatagram() systemPrint("Not my VC: "); systemPrintln(rxDestVc); outputSerialData(true); - CheckChannelHop(); if (settings.printPktData && rxDataBytes) dumpBuffer(incomingBuffer, rxDataBytes); outputSerialData(true); @@ -2218,7 +2623,6 @@ PacketType rcvDatagram() systemPrint(" expecting "); systemPrintln(vc->txAckNumber); outputSerialData(true); - CheckChannelHop(); } badFrames++; return (DATAGRAM_BAD); @@ -2314,7 +2718,7 @@ PacketType rcvDatagram() systemPrint(rxDataBytes, HEX); systemPrintln(") bytes"); outputSerialData(true); - CheckChannelHopAndKickWatchdog(); + petWDT(); if (settings.printPktData && rxDataBytes) dumpBuffer(rxData, rxDataBytes); } @@ -2362,8 +2766,6 @@ PacketType rcvDatagram() outputSerialData(true); } // debugDatagrams - CheckChannelHop(); - //Process the packet datagramsReceived++; linkDownTimer = millis(); @@ -2395,7 +2797,6 @@ PacketType validateDatagram(VIRTUAL_CIRCUIT * vc, PacketType datagramType, uint8 systemPrint("Duplicate datagram received, ACK "); systemPrintln(ackNumber); outputSerialData(true); - CheckChannelHop(); } linkDownTimer = millis(); duplicateFrames++; @@ -2411,7 +2812,6 @@ PacketType validateDatagram(VIRTUAL_CIRCUIT * vc, PacketType datagramType, uint8 systemPrint(" expecting "); systemPrintln(vc->rmtTxAckNumber); outputSerialData(true); - CheckChannelHop(); } badFrames++; return DATAGRAM_BAD; @@ -2476,8 +2876,6 @@ bool transmitDatagram() VIRTUAL_CIRCUIT * vc; VC_RADIO_MESSAGE_HEADER * vcHeader; - CheckChannelHop(); - //Remove some jitter by getting this time after the hopChannel txDatagramMicros = micros(); radioCallHistory[RADIO_CALL_transmitDatagram] = millis(); @@ -2562,7 +2960,6 @@ bool transmitDatagram() systemPrintln(); outputSerialData(true); - CheckChannelHop(); } /* @@ -2588,7 +2985,7 @@ bool transmitDatagram() systemPrint(" (0x"); systemPrint(length, HEX); systemPrintln(") bytes"); - CheckChannelHopAndKickWatchdog(); + petWDT(); if (settings.printPktData) dumpBuffer(&endOfTxData[-length], length); outputSerialData(true); @@ -2605,7 +3002,6 @@ bool transmitDatagram() systemPrint(headerBytes); systemPrintln(") bytes"); outputSerialData(true); - CheckChannelHop(); } /* @@ -2637,7 +3033,7 @@ bool transmitDatagram() systemPrint(settings.netID, HEX); systemPrintln(")"); outputSerialData(true); - CheckChannelHopAndKickWatchdog(); + petWDT(); } } @@ -2666,9 +3062,6 @@ bool transmitDatagram() //Add the clock sync information if (settings.frequencyHop == true) { - //Make sure that the transmitted msToNextHop is in the range 0 - maxDwellTime - CheckChannelHop(); - //Measure the time to the next hop triggerEvent(TRIGGER_TX_LOAD_CHANNEL_TIMER_VALUE); txSetChannelTimerMicros = micros(); @@ -2734,7 +3127,6 @@ bool transmitDatagram() systemPrint(" Channel Timer(ms): "); systemPrintln(msToNextHop); outputSerialData(true); - CheckChannelHop(); } } else @@ -2777,7 +3169,7 @@ bool transmitDatagram() break; } - radio.implicitHeader(txDatagramSize); //Set header size so that hardware CRC is calculated correctly + radioImplicitHeader(txDatagramSize); //Set header size so that hardware CRC is calculated correctly endOfTxData = &outgoingPacket[txDatagramSize]; if (settings.debugTransmit) @@ -2788,7 +3180,6 @@ bool transmitDatagram() systemPrint(" SF6 TX Header Size: "); systemPrintln(txDatagramSize); outputSerialData(true); - CheckChannelHop(); } } @@ -2823,7 +3214,6 @@ bool transmitDatagram() else systemPrintln(srcVc); outputSerialData(true); - CheckChannelHop(); } /* @@ -2845,8 +3235,6 @@ bool transmitDatagram() uint16_t crc; uint8_t * txData; - CheckChannelHop(); - //Compute the CRC-16 value crc = 0xffff; for (txData = outgoingPacket; txData < endOfTxData; txData++) @@ -2855,7 +3243,6 @@ bool transmitDatagram() *endOfTxData++ = (uint8_t)(crc & 0xff); } txDatagramSize += trailerBytes; - CheckChannelHop(); //Display the trailer if (trailerBytes && settings.debugTransmit) @@ -2867,7 +3254,6 @@ bool transmitDatagram() systemPrint(trailerBytes); systemPrintln(") bytes"); outputSerialData(true); - CheckChannelHop(); //Display the CRC if (settings.enableCRC16 && (settings.printPktData || settings.debugReceive)) @@ -2877,7 +3263,6 @@ bool transmitDatagram() systemPrint(endOfTxData[-2], HEX); systemPrintln(endOfTxData[-1], HEX); outputSerialData(true); - CheckChannelHop(); } } @@ -2904,7 +3289,7 @@ bool transmitDatagram() systemPrint(txDatagramSize, HEX); systemPrintln(") bytes"); outputSerialData(true); - CheckChannelHopAndKickWatchdog(); + petWDT(); if (settings.printRfData) { dumpBuffer(outgoingPacket, txDatagramSize); @@ -2921,10 +3306,7 @@ bool transmitDatagram() //Encrypt the datagram if (settings.encryptData == true) - { encryptBuffer(outgoingPacket, txDatagramSize); - CheckChannelHop(); - } //Scramble the datagram if (settings.dataScrambling == true) @@ -2941,7 +3323,7 @@ bool transmitDatagram() systemPrint(txDatagramSize, HEX); systemPrintln(") bytes"); outputSerialData(true); - CheckChannelHopAndKickWatchdog(); + petWDT(); if (settings.printRfData) { dumpBuffer(outgoingPacket, txDatagramSize); @@ -2973,14 +3355,10 @@ void printControl(uint8_t value) systemPrint(" Control: 0x"); systemPrintln(value, HEX); - CheckChannelHop(); - systemPrintTimestamp(); systemPrint(" ACK # "); systemPrintln(value & 3); - CheckChannelHop(); - systemPrintTimestamp(); systemPrint(" datagramType "); if (control->datagramType < MAX_DATAGRAM_TYPE) @@ -3004,8 +3382,7 @@ void printControl(uint8_t value) } outputSerialData(true); - - CheckChannelHopAndKickWatchdog(); + petWDT(); } //========================================================================================= @@ -3026,8 +3403,6 @@ bool retransmitDatagram(VIRTUAL_CIRCUIT * vc) |<------------------------- txDatagramSize --------------------------->| */ - CheckChannelHop(); - //Display the transmitted frame bytes if (frameSentCount && (settings.printRfData || settings.debugTransmit)) { @@ -3040,7 +3415,7 @@ bool retransmitDatagram(VIRTUAL_CIRCUIT * vc) systemPrint(txDatagramSize, HEX); systemPrintln(") bytes"); outputSerialData(true); - CheckChannelHopAndKickWatchdog(); + petWDT(); if (settings.printRfData) { dumpBuffer(outgoingPacket, txDatagramSize); @@ -3049,8 +3424,6 @@ bool retransmitDatagram(VIRTUAL_CIRCUIT * vc) } //Transmit this frame - CheckChannelHop(); - frameAirTimeUsec = calcAirTimeUsec(txDatagramSize); //Calculate frame air size while we're transmitting in the background uint16_t responseDelay = frameAirTimeUsec / responseDelayDivisor; //Give the receiver a bit of wiggle time to respond @@ -3089,7 +3462,7 @@ bool retransmitDatagram(VIRTUAL_CIRCUIT * vc) else { //Move the data to the radio over SPI - int state = radio.startTransmit(outgoingPacket, txDatagramSize); + int state = radioStartTransmit(outgoingPacket, txDatagramSize); if (state == RADIOLIB_ERR_NONE) { @@ -3117,14 +3490,12 @@ bool retransmitDatagram(VIRTUAL_CIRCUIT * vc) systemPrint(frameAirTimeUsec); systemPrintln(" uSec"); outputSerialData(true); - CheckChannelHop(); systemPrintTimestamp(); systemPrint("TX: responseDelay "); systemPrint(responseDelay); systemPrintln(" mSec"); outputSerialData(true); - CheckChannelHop(); } } else @@ -3234,7 +3605,6 @@ void startChannelTimer(int16_t startAmount) channelTimer.setInterval_MS(startAmount, channelTimerHandler); digitalWrite(pin_hop_timer, channelNumber & 1); reloadChannelTimer = (startAmount != settings.maxDwellTime); - timeToHop = false; channelTimerStart = millis(); //startChannelTimer - ISR updates value channelTimerMsec = startAmount; //startChannelTimer - ISR updates value channelTimer.enableTimer(); @@ -3254,7 +3624,6 @@ void stopChannelTimer() channelTimerMsec = 0; //Indicate that the timer is off triggerEvent(TRIGGER_HOP_TIMER_STOP); - timeToHop = false; } //========================================================================================= @@ -3321,13 +3690,7 @@ void syncChannelTimer(uint32_t frameAirTimeUsec, bool clockStarting) //Synchronize with the hardware timer channelTimer.disableTimer(); - - //When timeToHop is true, a hop is required to match the hops indicated by - //the channelTimerStart value. Delay this hop to avoid adding unaccounted - //delay. After the channel timer is restarted, perform this hop because - //the channelTimerStart value indicated that it was done. The channel - //timer update will add only microseconds to when the hop is done. - delayedHopCount = timeToHop ? 1 : 0; + delayedHopCount = 0; // 4800 BPS operation // @@ -3514,12 +3877,10 @@ void syncChannelTimer(uint32_t frameAirTimeUsec, bool clockStarting) clockSyncData[clockSyncIndex].adjustment = adjustment; clockSyncData[clockSyncIndex].delayedHopCount = delayedHopCount; clockSyncData[clockSyncIndex].lclHopTimeMsec = lclHopTimeMsec; - clockSyncData[clockSyncIndex].timeToHop = timeToHop; clockSyncIndex += 1; if (clockSyncIndex >= (sizeof(clockSyncData) / sizeof(CLOCK_SYNC_DATA)) ) clockSyncIndex = 0; //Restart the channel timer - timeToHop = false; channelTimer.setInterval_MS(msToNextHop, channelTimerHandler); //Adjust our hardware timer to match our mate's digitalWrite(pin_hop_timer, ((channelNumber + delayedHopCount) % settings.numberOfChannels) & 1); channelTimerStart = currentMillis; @@ -3535,7 +3896,7 @@ void syncChannelTimer(uint32_t frameAirTimeUsec, bool clockStarting) //Hop if the timer fired prior to disabling the timer, resetting the channelTimerStart value if (delayedHopCount) - hopChannel(true, delayedHopCount); + hopChannel(false, true, delayedHopCount); //Display the channel sync timer calculations if (settings.debugSync) @@ -3840,7 +4201,7 @@ void dummyRead() triggerEvent(TRIGGER_DUMMY_READ); systemPrintln("Dummy read"); - int state = radio.readData(incomingBuffer, MAX_PACKET_SIZE); + int state = radioReadData(incomingBuffer, MAX_PACKET_SIZE); if (state != RADIOLIB_ERR_NONE) { diff --git a/Firmware/LoRaSerial/Serial.ino b/Firmware/LoRaSerial/Serial.ino index 487ae671..460f4eae 100644 --- a/Firmware/LoRaSerial/Serial.ino +++ b/Firmware/LoRaSerial/Serial.ino @@ -340,9 +340,7 @@ void updateSerial() while (bufferSpace-- && arch.serialAvailable() && (transactionComplete == false)) { blinkSerialRxLed(true); //Turn on LED during serial reception - - //Take a break if there are ISRs to attend to - CheckChannelHopAndKickWatchdog(); + petWDT(); byte incoming = systemRead(); @@ -365,7 +363,7 @@ void updateSerial() systemPrint(sizeof(serialReceiveBuffer) - previousHead + rxHead); systemPrintln(" bytes into serialReceiveBuffer"); outputSerialData(true); - CheckChannelHopAndKickWatchdog(); + petWDT(); } //Process the serial data @@ -396,7 +394,7 @@ void updateSerial() systemPrint(commandLength); systemPrintln(" bytes from commandRXBuffer into commandBuffer"); outputSerialData(true); - CheckChannelHopAndKickWatchdog(); + petWDT(); } if (commandBuffer[0] == 'R') //Error check @@ -429,8 +427,7 @@ void processSerialInput() && ((!inCommandMode) || (!waitRemoteCommandResponse)) && (transactionComplete == false)) { - //Take a break if there are ISRs to attend to - CheckChannelHopAndKickWatchdog(); + petWDT(); byte incoming = serialReceiveBuffer[rxTail++]; rxTail %= sizeof(serialReceiveBuffer); @@ -597,9 +594,7 @@ void outputSerialData(bool ignoreISR) while (dataBytes-- && isCTS() && (ignoreISR || (!transactionComplete))) { blinkSerialTxLed(true); //Turn on LED during serial transmissions - - //Take a break if there are ISRs to attend to - CheckChannelHopAndKickWatchdog(); + petWDT(); arch.serialWrite(serialTransmitBuffer[txTail]); systemFlush(); //Prevent serial hardware from blocking more than this one write @@ -805,8 +800,7 @@ void vcProcessSerialInput() while (dataBytes && (availableRadioTXBytes() < (sizeof(radioTxBuffer) - 256)) && (transactionComplete == false)) { - //Take a break if there are ISRs to attend to - CheckChannelHopAndKickWatchdog(); + petWDT(); //Skip any garbage in the input stream data = serialReceiveBuffer[rxTail]; @@ -964,9 +958,7 @@ void vcProcessSerialInput() //Determine how much data is left in the buffer dataBytes = availableRXBytes(); } - - //Take a break if there are ISRs to attend to - CheckChannelHopAndKickWatchdog(); + petWDT(); } //========================================================================================= diff --git a/Firmware/LoRaSerial/States.ino b/Firmware/LoRaSerial/States.ino index 72ec7422..069f9e16 100644 --- a/Firmware/LoRaSerial/States.ino +++ b/Firmware/LoRaSerial/States.ino @@ -23,7 +23,7 @@ #define P2P_SEND_ACK(trigger) \ { \ /*Compute the frequency correction*/ \ - frequencyCorrection += radio.getFrequencyError() / 1000000.0; \ + frequencyCorrection += radioGetFrequencyError() / 1000000.0; \ \ /*Send the ACK to the remote system*/ \ triggerEvent(trigger); \ @@ -105,7 +105,7 @@ void updateRadioState() //Initialize the radio rssi = -200; - radioSeed = radio.randomByte(); //Puts radio into standy-by state + radioSeed = radioRandomByte(); //Puts radio into standy-by state randomSeed(radioSeed); if ((settings.debug == true) || (settings.debugRadio == true)) { @@ -274,7 +274,7 @@ void updateRadioState() if (channelNumber != 0) { channelNumber = 0; - setRadioFrequency(false); + setRadioFrequency(false, false); } //Stop the channel timer if it is running @@ -356,7 +356,7 @@ void updateRadioState() { triggerEvent(TRIGGER_TX_DONE); transactionComplete = false; //Reset ISR flag - irqFlags = radio.getIRQFlags(); + irqFlags = radioGetIRQFlags(); startChannelTimerPending = true; //Starts at RX of SYNC_CLOCKS frame returnToReceiving(); changeState(RADIO_P2P_WAIT_SYNC_CLOCKS); @@ -479,7 +479,7 @@ void updateRadioState() { triggerEvent(TRIGGER_TX_DONE); transactionComplete = false; //Reset ISR flag - irqFlags = radio.getIRQFlags(); + irqFlags = radioGetIRQFlags(); //Hop to the next channel hopChannel(); @@ -566,7 +566,7 @@ void updateRadioState() if (transactionComplete) { transactionComplete = false; //Reset ISR flag - irqFlags = radio.getIRQFlags(); + irqFlags = radioGetIRQFlags(); setHeartbeatShort(); //We sent the last ack so be responsible for sending the next heartbeat //Bring up the link @@ -641,13 +641,11 @@ void updateRadioState() //Wait for the data transmission to complete //==================== case RADIO_P2P_LINK_UP_WAIT_TX_DONE: - CheckChannelHop(); - if (transactionComplete) { transactionComplete = false; //Reset ISR flag triggerEvent(TRIGGER_TX_DONE); - irqFlags = radio.getIRQFlags(); + irqFlags = radioGetIRQFlags(); //Determine the next packet size for SF6 if (ackTimer) @@ -674,8 +672,6 @@ void updateRadioState() // * Link timeout //==================== case RADIO_P2P_LINK_UP: - CheckChannelHop(); - //Check for a received datagram if (transactionComplete == true) { @@ -762,7 +758,7 @@ void updateRadioState() STOP_ACK_TIMER(); setHeartbeatLong(); //Those who send an ACK have short time to next heartbeat. Those who send a heartbeat or data have long time to next heartbeat. - frequencyCorrection += radio.getFrequencyError() / 1000000.0; + frequencyCorrection += radioGetFrequencyError() / 1000000.0; break; case DATAGRAM_REMOTE_COMMAND: @@ -1072,7 +1068,7 @@ void updateRadioState() if (((frameAirTimeUsec + txDataAckUsec + settings.txToRxUsec) / 1000) > (settings.maxDwellTime / 2)) { channelNumber = 0; - setRadioFrequency(false); + setRadioFrequency(false, false); stopChannelTimer(); changeState(RADIO_DISCOVER_STANDBY); } @@ -1155,7 +1151,7 @@ void updateRadioState() { //Change to the server's channel number channelNumber = rxData[0]; - setRadioFrequency(false); + setRadioFrequency(false, false); //Update the timestamp COMPUTE_TIMESTAMP_OFFSET(rxData + 1, 0, txSyncClocksUsec); @@ -1175,10 +1171,9 @@ void updateRadioState() systemPrintDec(channelNumber, 2); systemPrintln(); outputSerialData(true); - CheckChannelHop(); } - frequencyCorrection += radio.getFrequencyError() / 1000000.0; + frequencyCorrection += radioGetFrequencyError() / 1000000.0; lastPacketReceived = millis(); //Reset changeState(RADIO_MP_STANDBY); @@ -1216,7 +1211,7 @@ void updateRadioState() //Give up, return to channel 0, and wait in Standby for Server to Xmit HB channelNumber = 0; - setRadioFrequency(false); + setRadioFrequency(false, false); changeState(RADIO_DISCOVER_STANDBY); } @@ -1238,7 +1233,7 @@ void updateRadioState() if (transactionComplete) { transactionComplete = false; //Reset ISR flag - irqFlags = radio.getIRQFlags(); + irqFlags = radioGetIRQFlags(); returnToReceiving(); changeState(RADIO_DISCOVER_SCANNING); } @@ -1248,14 +1243,11 @@ void updateRadioState() //Wait for the Server to transmit a HB on Channel 0 //==================== case RADIO_DISCOVER_STANDBY: - //Hop channels when required - if (timeToHop == true) - hopChannel(); if (channelNumber && (!channelTimerMsec)) { //Return to channel zero channelNumber = 0; - setRadioFrequency(false); + setRadioFrequency(false, false); } rssi = -200; //Force RSSI LEDs off until link is up @@ -1322,7 +1314,7 @@ void updateRadioState() { //Change to the server's channel number channelNumber = rxData[0]; - setRadioFrequency(false); + setRadioFrequency(false, false); //Start and adjust freq hop ISR based on remote's remaining clock channelTimerStart -= settings.maxDwellTime; @@ -1336,10 +1328,9 @@ void updateRadioState() systemPrintDec(channelNumber, 2); systemPrintln(); outputSerialData(true); - CheckChannelHop(); } - frequencyCorrection += radio.getFrequencyError() / 1000000.0; + frequencyCorrection += radioGetFrequencyError() / 1000000.0; lastPacketReceived = millis(); //Update timestamp for Link LED @@ -1373,9 +1364,6 @@ void updateRadioState() // * Link timeout //==================== case RADIO_MP_STANDBY: - //Hop channels when required - CheckChannelHop(); - //Process the receive packet if (transactionComplete == true) { @@ -1418,7 +1406,7 @@ void updateRadioState() case DATAGRAM_REMOTE_COMMAND: case DATAGRAM_REMOTE_COMMAND_RESPONSE: //We should not be receiving these datagrams, but if we do, just ignore - frequencyCorrection += radio.getFrequencyError() / 1000000.0; + frequencyCorrection += radioGetFrequencyError() / 1000000.0; triggerEvent(TRIGGER_BAD_PACKET); break; @@ -1450,7 +1438,7 @@ void updateRadioState() //Received heartbeat - do not ack. triggerEvent(TRIGGER_RX_HEARTBEAT); - frequencyCorrection += radio.getFrequencyError() / 1000000.0; + frequencyCorrection += radioGetFrequencyError() / 1000000.0; lastPacketReceived = millis(); //Update timestamp for Link LED @@ -1465,7 +1453,7 @@ void updateRadioState() //Place any available data in the serial output buffer serialBufferOutput(rxData, rxDataBytes); - frequencyCorrection += radio.getFrequencyError() / 1000000.0; + frequencyCorrection += radioGetFrequencyError() / 1000000.0; lastPacketReceived = millis(); //Update timestamp for Link LED break; @@ -1527,14 +1515,11 @@ void updateRadioState() //Wait for the frame transmission to complete //==================== case RADIO_MP_WAIT_TX_DONE: - //Hop channels when required - CheckChannelHop(); - //If transmit is complete then start receiving if (transactionComplete == true) { transactionComplete = false; //Reset ISR flag - irqFlags = radio.getIRQFlags(); + irqFlags = radioGetIRQFlags(); returnToReceiving(); changeState(RADIO_MP_STANDBY); } @@ -1596,7 +1581,7 @@ void updateRadioState() //Indicate that the receive is complete triggerEvent(TRIGGER_TRAINING_CLIENT_TX_FIND_PARTNER_DONE); - irqFlags = radio.getIRQFlags(); + irqFlags = radioGetIRQFlags(); //Start the receive operation returnToReceiving(); @@ -1674,7 +1659,7 @@ void updateRadioState() if (transactionComplete == true) { transactionComplete = false; - irqFlags = radio.getIRQFlags(); + irqFlags = radioGetIRQFlags(); endClientServerTraining(TRIGGER_TRAINING_CLIENT_TX_ACK_DONE); } break; @@ -1761,7 +1746,7 @@ void updateRadioState() systemPrintUniqueID(rxData); systemPrintln(); int radioPowerSetting = covertdBmToSetting(settings.radioBroadcastPower_dbm); - radio.setOutputPower(radioPowerSetting); + radioSetOutputPower(radioPowerSetting); } //Find a slot in the NVM unique ID table @@ -1829,7 +1814,7 @@ void updateRadioState() //Indicate that the receive is complete triggerEvent(TRIGGER_TRAINING_SERVER_TX_PARAMS_DONE); - irqFlags = radio.getIRQFlags(); + irqFlags = radioGetIRQFlags(); //Start the receive operation returnToReceiving(); @@ -1929,7 +1914,7 @@ void updateRadioState() if (channelNumber != 0) { channelNumber = 0; - setRadioFrequency(false); + setRadioFrequency(false, false); } //If dio0ISR has fired, a packet has arrived @@ -1965,16 +1950,13 @@ void updateRadioState() //Wait for the transmission to complete //==================== case RADIO_VC_WAIT_TX_DONE: - //Hop channels when required - CheckChannelHop(); - //If dio0ISR has fired, we are done transmitting if (transactionComplete == true) { //Indicate that the transmission is complete transactionComplete = false; triggerEvent(TRIGGER_TX_DONE); - irqFlags = radio.getIRQFlags(); + irqFlags = radioGetIRQFlags(); //Start the receive operation returnToReceiving(); @@ -1997,9 +1979,6 @@ void updateRadioState() // * Link timeout //==================== case RADIO_VC_WAIT_RECEIVE: - //Hop channels when required - CheckChannelHop(); - //If dio0ISR has fired, a packet has arrived currentMillis = millis(); if (transactionComplete == true) @@ -2066,7 +2045,7 @@ void updateRadioState() break; case DATAGRAM_DUPLICATE: - frequencyCorrection += radio.getFrequencyError() / 1000000.0; + frequencyCorrection += radioGetFrequencyError() / 1000000.0; if (xmitVcAckFrame(rxSrcVc)) { @@ -2120,7 +2099,7 @@ void updateRadioState() } petWDT(); - frequencyCorrection += radio.getFrequencyError() / 1000000.0; + frequencyCorrection += radioGetFrequencyError() / 1000000.0; //Transmit ACK if (xmitVcAckFrame(rxSrcVc)) @@ -2204,7 +2183,7 @@ void updateRadioState() serialBufferOutput(&rxData[index], length); } - frequencyCorrection += radio.getFrequencyError() / 1000000.0; + frequencyCorrection += radioGetFrequencyError() / 1000000.0; //ACK the command response if (xmitVcAckFrame(rxSrcVc)) //Transmit ACK @@ -2929,8 +2908,6 @@ void dumpClockSynchronization() systemPrint(" msToNextHop"); if (clockSyncData[index].delayedHopCount) { - systemPrint(", timeToHop: "); - systemPrintDec(clockSyncData[index].timeToHop, 3); systemPrint(", Hops: "); systemPrintDec(clockSyncData[index].delayedHopCount, 2); } diff --git a/Firmware/LoRaSerial/System.ino b/Firmware/LoRaSerial/System.ino index 4b8e6538..2c0582d0 100644 --- a/Firmware/LoRaSerial/System.ino +++ b/Firmware/LoRaSerial/System.ino @@ -491,7 +491,6 @@ void radioComputeWhitening(uint8_t *buffer, uint16_t bufferSize) for (uint16_t j = 0 ; j < bufferSize ; j++) { - CheckChannelHop(); buffer[j] ^= WhiteningKeyLSB; for (uint8_t i = 0 ; i < 8 ; i++) @@ -519,7 +518,12 @@ void triggerEvent(uint8_t triggerNumber) //Determine which trigger enable to use triggerBitNumber = triggerNumber; triggerEnable = settings.triggerEnable; - if (triggerNumber >= 32) + if (triggerNumber >= 64) + { + triggerBitNumber -= 64; + triggerEnable = settings.triggerEnable3; + } + else if (triggerNumber >= 32) { triggerBitNumber -= 32; triggerEnable = settings.triggerEnable2; @@ -621,14 +625,14 @@ void dumpBuffer(uint8_t * data, int length) { systemPrint(" "); systemPrint(*data++, HEX); - CheckChannelHopAndKickWatchdog(); + petWDT(); } // Space over to the ASCII display for (; index < displayWidth; index++) { systemPrint(" "); - CheckChannelHopAndKickWatchdog(); + petWDT(); } systemPrint(" "); @@ -639,7 +643,7 @@ void dumpBuffer(uint8_t * data, int length) systemPrint(((byte[0] < ' ') || (byte[0] >= 0x7f)) ? "." : byte); } systemPrintln(); - CheckChannelHopAndKickWatchdog(); + petWDT(); } } @@ -686,7 +690,7 @@ void dumpCircularBuffer(uint8_t * buffer, uint16_t tail, uint16_t bufferLength, for (index = 0; index < delta; index++) { systemPrint(" "); - CheckChannelHopAndKickWatchdog(); + petWDT(); } } @@ -701,14 +705,14 @@ void dumpCircularBuffer(uint8_t * buffer, uint16_t tail, uint16_t bufferLength, systemWrite(' '); data = buffer[(offset + index) % bufferLength]; systemPrint(data, HEX); - CheckChannelHopAndKickWatchdog(); + petWDT(); } //Space over to the ASCII display for (; (delta + index) < displayWidth; index++) { systemPrint(" "); - CheckChannelHopAndKickWatchdog(); + petWDT(); } systemPrint(" "); @@ -720,7 +724,7 @@ void dumpCircularBuffer(uint8_t * buffer, uint16_t tail, uint16_t bufferLength, systemWrite(((data < ' ') || (data >= 0x7f)) ? '.' : data); } systemPrintln(); - CheckChannelHopAndKickWatchdog(); + petWDT(); outputSerialData(true); offset += bytes; length -= bytes; @@ -1371,9 +1375,9 @@ void printPacketQuality() systemPrint("R:"); systemPrint(rssi); systemPrint("\tS:"); - systemPrint(radio.getSNR()); + systemPrint(radioGetSNR()); systemPrint("\tfE:"); - systemPrint(radio.getFrequencyError()); + systemPrint(radioGetFrequencyError()); systemPrintln(); } } diff --git a/Firmware/LoRaSerial/Train.ino b/Firmware/LoRaSerial/Train.ino index 772162bd..cccb75ed 100644 --- a/Firmware/LoRaSerial/Train.ino +++ b/Firmware/LoRaSerial/Train.ino @@ -25,7 +25,7 @@ void generateRandomKeysID(Settings * radioSettings) } //Seed random number based on RF noise. We use Arduino random() because platform specific generation does not matter - randomSeed(radio.randomByte()); + randomSeed(radioRandomByte()); //Generate new NetID radioSettings->netID = random(0, 256); //Inclusive, exclusive diff --git a/Firmware/LoRaSerial/settings.h b/Firmware/LoRaSerial/settings.h index 88884b3a..5fcd06a3 100644 --- a/Firmware/LoRaSerial/settings.h +++ b/Firmware/LoRaSerial/settings.h @@ -379,7 +379,6 @@ typedef struct _CLOCK_SYNC_DATA int16_t lclHopTimeMsec; int16_t adjustment; int8_t delayedHopCount; - bool timeToHop; } CLOCK_SYNC_DATA; typedef struct _AIR_SPEED_TABLE @@ -526,7 +525,7 @@ typedef struct struct_settings { uint32_t triggerEnable = 0; //Determine which triggers are enabled: 31 - 0 uint32_t triggerEnable2 = 0; //Determine which triggers are enabled: 63 - 32 - + uint32_t triggerEnable3 = 0; //Determine which triggers are enabled: 95 - 64 //---------------------------------------- //Debug parameters