Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion Firmware/LoRaSerial_Firmware/Commands.ino
Original file line number Diff line number Diff line change
Expand Up @@ -413,11 +413,15 @@ bool commandAT(const char * commandString)
systemPrintln(" Clock Synchronization");
systemPrint(" ACK Time: ");
systemPrint(txDataAckUsec);
systemPrintln(" uSec");
systemPrint(" FIND_PARTNER Time: ");
systemPrint(txFindPartnerUsec);
systemPrintln(" uSec");
systemPrint(" HEARTBEAT Time: ");
systemPrint(txHeartbeatUsec);
systemPrintln(" uSec");
systemPrint(" SYNC_CLOCKS Time: ");
systemPrint(txSyncClockUsec);
systemPrint(txSyncClocksUsec);
systemPrintln(" uSec");
systemPrint(" Uptime: ");
deltaMillis = millis();
Expand Down
8 changes: 5 additions & 3 deletions Firmware/LoRaSerial_Firmware/LoRaSerial_Firmware.ino
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ const int FIRMWARE_VERSION_MINOR = 0;
//Frame lengths
#define MP_HEARTBEAT_BYTES 0 //Number of data bytes in the MP_HEARTBEAT frame
#define P2P_FIND_PARTNER_BYTES sizeof(unsigned long) //Number of data bytes in the FIND_PARTNER frame
#define P2P_SYNC_CLOCKS_BYTES (sizeof(uint8_t) + sizeof(unsigned long) + sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint32_t)) //Number of data bytes in the SYNC_CLOCKS frame
#define P2P_SYNC_CLOCKS_BYTES (sizeof(uint8_t) + sizeof(unsigned long)) //Number of data bytes in the SYNC_CLOCKS frame
#define P2P_ZERO_ACKS_BYTES sizeof(unsigned long) //Number of data bytes in the ZERO_ACKS frame
#define P2P_HEARTBEAT_BYTES sizeof(unsigned long) //Number of data bytes in the HEARTBEAT frame
#define P2P_ACK_BYTES sizeof(unsigned long) //Number of data bytes in the ACK frame
Expand Down Expand Up @@ -465,7 +465,6 @@ unsigned long linkDownTimer;
unsigned long rcvTimeMillis;
unsigned long xmitTimeMillis;
long timestampOffset;
unsigned long vcTxHeartbeatMillis;

//Transmit control
uint8_t * endOfTxData;
Expand Down Expand Up @@ -589,12 +588,15 @@ uint16_t txRxTimeMsec;
uint32_t txSetChannelTimerMicros; //Timestamp when millis is read in TX routine to set channel timer value
uint32_t transactionCompleteMicros; //Timestamp at the beginning of the transactionCompleteIsr routine
uint32_t txDataAckUsec; //Time in microseconds to transmit the DATA_ACK frame
uint32_t txFindPartnerUsec; //Time in microseconds to transmit the FIND_PARTNER frame
uint32_t txHeartbeatUsec; //Time in microseconds to transmit the HEARTBEAT frame
uint32_t txSyncClockUsec; //Time in microseconds to transmit the SYNC_CLOCKS frame
uint32_t txSyncClocksUsec; //Time in microseconds to transmit the SYNC_CLOCKS frame
uint32_t txDatagramMicros; //Timestamp at the beginning of the transmitDatagram routine
uint16_t maxFrameAirTime; //Air time of the maximum sized message
unsigned long remoteSystemMillis; //Millis value contained in the received message

#define VC_DELAY_HEARTBEAT_MSEC 5

bool rxFirstAck; //Set true when first ACK is received
bool txFirstAck; //Set true when first ACK is transmitted

Expand Down
137 changes: 105 additions & 32 deletions Firmware/LoRaSerial_Firmware/Radio.ino
Original file line number Diff line number Diff line change
Expand Up @@ -889,24 +889,15 @@ bool xmitDatagramP2PSyncClocks()
memcpy(endOfTxData, &currentMillis, sizeof(currentMillis));
endOfTxData += sizeof(unsigned long);

memcpy(endOfTxData, &txHeartbeatUsec, sizeof(txHeartbeatUsec));
endOfTxData += sizeof(txHeartbeatUsec);

memcpy(endOfTxData, &txSyncClockUsec, sizeof(txSyncClockUsec));
endOfTxData += sizeof(txSyncClockUsec);

memcpy(endOfTxData, &txDataAckUsec, sizeof(txDataAckUsec));
endOfTxData += sizeof(txDataAckUsec);

/*
endOfTxData ---.
|
V
+----------+---------+----------+------------+---------+---------+-------------+-------------+-----------+----------+
| Optional | | Optional | Optional | Channel | | HEARTBEAT | SYNC_CLOCKS | DATA_ACK | |
| NET ID | Control | C-Timer | SF6 Length | Number | Millis | Micros | Micros | Micros | Trailer |
| 8 bits | 8 bits | 2 bytes | 8 bits | 1 byte | 4 bytes | 4 Bytes | 4 Bytes | 4 Bytes | n Bytes |
+----------+---------+----------+------------+---------+---------+-------------+-------------+-----------+----------+
endOfTxData ---.
|
V
+----------+---------+----------+------------+---------+---------+----------+
| Optional | | Optional | Optional | Channel | | |
| NET ID | Control | C-Timer | SF6 Length | Number | Millis | Trailer |
| 8 bits | 8 bits | 2 bytes | 8 bits | 1 byte | 4 bytes | n Bytes |
+----------+---------+----------+------------+---------+---------+----------+
*/

//Verify the data length
Expand Down Expand Up @@ -1365,6 +1356,11 @@ bool xmitVcDatagram()
}

//Broadcast a HEARTBEAT to all of the VCs
bool xmitVcHeartbeat()
{
return xmitVcHeartbeat(VC_IGNORE_TX, myUniqueId);
}

bool xmitVcHeartbeat(int8_t addr, uint8_t * id)
{
uint32_t currentMillis = millis();
Expand Down Expand Up @@ -1414,10 +1410,6 @@ bool xmitVcHeartbeat(int8_t addr, uint8_t * id)
txControl.datagramType = DATAGRAM_VC_HEARTBEAT;
txControl.ackNumber = 0;

//Determine the time that it took to pass this frame to the radio
//This time is used to adjust the time offset
vcTxHeartbeatMillis = millis() - currentMillis;

//Select a random for the next heartbeat
setVcHeartbeatTimer();
return (transmitDatagram());
Expand Down Expand Up @@ -1932,6 +1924,20 @@ PacketType rcvDatagram()
return (DATAGRAM_BAD);
}

//Ignore this frame is requested
if (rxControl.ignoreFrame)
{
if (settings.debugReceive || settings.debugDatagrams)
{
systemPrintTimestamp();
systemPrint("RX: Ignore this ");
systemPrintln(datagramType);
outputSerialData(true);
}
badFrames++;
return (DATAGRAM_BAD);
}

//Display the CRC
if (settings.enableCRC16 && settings.debugReceive)
{
Expand Down Expand Up @@ -2933,12 +2939,17 @@ void printControl(uint8_t value)
systemPrintln(control->datagramType);
}

systemPrintTimestamp();
systemPrint(" requestYield ");
if (control->requestYield)
systemPrintln("1");
else
systemPrintln("0");
{
systemPrintTimestamp();
systemPrintln(" requestYield");
}

if (control->ignoreFrame)
{
systemPrintTimestamp();
systemPrintln(" Ignore Frame");
}

outputSerialData(true);

Expand Down Expand Up @@ -3086,6 +3097,68 @@ bool retransmitDatagram(VIRTUAL_CIRCUIT * vc)
return (true); //Transmission has started
}

//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//Transmit Ignored Frames
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

bool getTxTime(bool (*transmitFrame)(), uint32_t * txFrameUsec, const char * frameName)
{
bool txStatus;
uint32_t transmitDelay;

#define IGNORE_TRANSMIT_DELAY_MSEC 100

//Transmit the frame
transmitDelay = 0;
do
{
//Delay between retries
if (transmitDelay)
delay(transmitDelay);
transmitDelay += IGNORE_TRANSMIT_DELAY_MSEC;

//Fail transmission after 5 attempts
if (transmitDelay > (5 * IGNORE_TRANSMIT_DELAY_MSEC))
{
if (settings.debugSync)
{
systemPrintTimestamp();
systemPrint("TX ignore ");
systemPrint(frameName);
systemPrintln(" failed!");
outputSerialData(true);
}
return false;
}

//Attempt to transmit the requested frame
txControl.ignoreFrame = true;
txStatus = transmitFrame();
txControl.ignoreFrame = false;
} while (!txStatus);

//Wait for transmit completion
while (!transactionComplete)
petWDT();
transactionComplete = false;

//Compute the transmit time
*txFrameUsec = transactionCompleteMicros - txSetChannelTimerMicros;
if (settings.debugSync)
{
systemPrintTimestamp();
systemPrint("TX ");
systemPrint(frameName);
systemPrint(": ");
systemPrint(*txFrameUsec);
systemPrintln(" mSec");
outputSerialData(true);
}
return true;
}

//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

//Use the maximum dwell setting to start the timer that indicates when to hop channels
void startChannelTimer()
{
Expand Down Expand Up @@ -3124,11 +3197,12 @@ void stopChannelTimer()

//Given the remote unit's number of ms before its next hop,
//adjust our own channelTimer interrupt to be synchronized with the remote unit
void syncChannelTimer(uint16_t frameAirTimeMsec)
void syncChannelTimer(uint32_t frameAirTimeUsec)
{
int16_t adjustment;
unsigned long currentMillis;
int8_t delayedHopCount;
uint16_t frameAirTimeMsec;
int16_t lclHopTimeMsec;
uint16_t msToNextHop;
int16_t rmtHopTimeMsec;
Expand Down Expand Up @@ -3207,6 +3281,7 @@ void syncChannelTimer(uint16_t frameAirTimeMsec)
//Compute the remote system's channel timer firing time offset in milliseconds
//using the channel timer value and the adjustments for transmit and receive
//time (time of flight)
frameAirTimeMsec = (frameAirTimeUsec + TX_TO_RX_USEC + micros() - transactionCompleteMicros) / 1000;
rmtHopTimeMsec = msToNextHopRemote - frameAirTimeMsec;

//Compute the when the local system last hopped
Expand Down Expand Up @@ -3469,7 +3544,7 @@ void setVcHeartbeatTimer()
petWDT();

//Determine the delay before channel zero is reached
deltaMillis = mSecToChannelZero() - heartbeatTimer;
deltaMillis = mSecToChannelZero();

//Determine the delay before the next HEARTBEAT frame
if ((!settings.server) || (deltaMillis > ((3 * settings.heartbeatTimeout) / 2))
Expand All @@ -3480,17 +3555,15 @@ void setVcHeartbeatTimer()
else if (deltaMillis >= settings.heartbeatTimeout)
heartbeatRandomTime = deltaMillis / 2;
else
heartbeatRandomTime = deltaMillis;
heartbeatRandomTime = deltaMillis + VC_DELAY_HEARTBEAT_MSEC;

//Display the next HEARTBEAT time interval
if (settings.debugHeartbeat)
{
systemPrint("deltaMillis: ");
systemPrint("mSecToChannelZero: ");
systemPrintln(deltaMillis);
systemPrint("heartbeatRandomTime: ");
systemPrintln(heartbeatRandomTime);
outputSerialData(true);
petWDT();
}
}

Expand Down
Loading