1
0
mirror of https://github.com/DCC-EX/CommandStation-EX.git synced 2024-11-24 08:36:14 +01:00

Compare commits

..

No commits in common. "08f0a2b37de4297e045f7a2597c1b6786242b077" and "763c9d8ae6d2d46fe09cbaff4f4ac82bef94496a" have entirely different histories.

4 changed files with 33 additions and 63 deletions

11
DCC.cpp
View File

@ -595,7 +595,7 @@ void DCC::loop() {
void DCC::issueReminders() { void DCC::issueReminders() {
// if the main track transmitter still has a pending packet, skip this time around. // if the main track transmitter still has a pending packet, skip this time around.
if (!DCCWaveform::mainTrack.isReminderWindowOpen()) return; if ( DCCWaveform::mainTrack.getPacketPending()) return;
// Move to next loco slot. If occupied, send a reminder. // Move to next loco slot. If occupied, send a reminder.
int reg = lastLocoReminder+1; int reg = lastLocoReminder+1;
if (reg > highestUsedReg) reg = 0; // Go to start of table if (reg > highestUsedReg) reg = 0; // Go to start of table
@ -620,23 +620,14 @@ bool DCC::issueReminder(int reg) {
case 1: // remind function group 1 (F0-F4) case 1: // remind function group 1 (F0-F4)
if (flags & FN_GROUP_1) if (flags & FN_GROUP_1)
setFunctionInternal(loco,0, 128 | ((functions>>1)& 0x0F) | ((functions & 0x01)<<4)); // 100D DDDD setFunctionInternal(loco,0, 128 | ((functions>>1)& 0x0F) | ((functions & 0x01)<<4)); // 100D DDDD
#ifdef DISABLE_FUNCTION_REMINDERS
flags&= ~FN_GROUP_1; // dont send them again
#endif
break; break;
case 2: // remind function group 2 F5-F8 case 2: // remind function group 2 F5-F8
if (flags & FN_GROUP_2) if (flags & FN_GROUP_2)
setFunctionInternal(loco,0, 176 | ((functions>>5)& 0x0F)); // 1011 DDDD setFunctionInternal(loco,0, 176 | ((functions>>5)& 0x0F)); // 1011 DDDD
#ifdef DISABLE_FUNCTION_REMINDERS
flags&= ~FN_GROUP_2; // dont send them again
#endif
break; break;
case 3: // remind function group 3 F9-F12 case 3: // remind function group 3 F9-F12
if (flags & FN_GROUP_3) if (flags & FN_GROUP_3)
setFunctionInternal(loco,0, 160 | ((functions>>9)& 0x0F)); // 1010 DDDD setFunctionInternal(loco,0, 160 | ((functions>>9)& 0x0F)); // 1010 DDDD
#ifdef DISABLE_FUNCTION_REMINDERS
flags&= ~FN_GROUP_3; // dont send them again
#endif
break; break;
case 4: // remind function group 4 F13-F20 case 4: // remind function group 4 F13-F20
if (flags & FN_GROUP_4) if (flags & FN_GROUP_4)

View File

@ -106,7 +106,6 @@ void DCCWaveform::interruptHandler() {
DCCWaveform::DCCWaveform( byte preambleBits, bool isMain) { DCCWaveform::DCCWaveform( byte preambleBits, bool isMain) {
isMainTrack = isMain; isMainTrack = isMain;
packetPending = false; packetPending = false;
reminderWindowOpen = false;
memcpy(transmitPacket, idlePacket, sizeof(idlePacket)); memcpy(transmitPacket, idlePacket, sizeof(idlePacket));
state = WAVE_START; state = WAVE_START;
// The +1 below is to allow the preamble generator to create the stop bit // The +1 below is to allow the preamble generator to create the stop bit
@ -128,15 +127,9 @@ void DCCWaveform::interrupt2() {
if (remainingPreambles > 0 ) { if (remainingPreambles > 0 ) {
state=WAVE_MID_1; // switch state to trigger LOW on next interrupt state=WAVE_MID_1; // switch state to trigger LOW on next interrupt
remainingPreambles--; remainingPreambles--;
// As we get to the end of the preambles, open the reminder window.
// This delays any reminder insertion until the last moment so
// that the reminder doesn't block a more urgent packet.
reminderWindowOpen=transmitRepeats==0 && remainingPreambles<4 && remainingPreambles>1;
if (remainingPreambles==1) promotePendingPacket();
// Update free memory diagnostic as we don't have anything else to do this time. // Update free memory diagnostic as we don't have anything else to do this time.
// Allow for checkAck and its called functions using 22 bytes more. // Allow for checkAck and its called functions using 22 bytes more.
else DCCTimer::updateMinimumFreeMemoryISR(22); DCCTimer::updateMinimumFreeMemoryISR(22);
return; return;
} }
@ -155,8 +148,29 @@ void DCCWaveform::interrupt2() {
if (bytes_sent >= transmitLength) { if (bytes_sent >= transmitLength) {
// end of transmission buffer... repeat or switch to next message // end of transmission buffer... repeat or switch to next message
bytes_sent = 0; bytes_sent = 0;
// preamble for next packet will start...
remainingPreambles = requiredPreambles; remainingPreambles = requiredPreambles;
if (transmitRepeats > 0) {
transmitRepeats--;
}
else if (packetPending) {
// Copy pending packet to transmit packet
// a fixed length memcpy is faster than a variable length loop for these small lengths
// for (int b = 0; b < pendingLength; b++) transmitPacket[b] = pendingPacket[b];
memcpy( transmitPacket, pendingPacket, sizeof(pendingPacket));
transmitLength = pendingLength;
transmitRepeats = pendingRepeats;
packetPending = false;
clearResets();
}
else {
// Fortunately reset and idle packets are the same length
memcpy( transmitPacket, isMainTrack ? idlePacket : resetPacket, sizeof(idlePacket));
transmitLength = sizeof(idlePacket);
transmitRepeats = 0;
if (getResets() < 250) sentResetsSincePacket++; // only place to increment (private!)
}
} }
} }
} }
@ -179,39 +193,8 @@ void DCCWaveform::schedulePacket(const byte buffer[], byte byteCount, byte repea
packetPending = true; packetPending = true;
clearResets(); clearResets();
} }
bool DCCWaveform::getPacketPending() {
bool DCCWaveform::isReminderWindowOpen() { return packetPending;
return reminderWindowOpen && ! packetPending;
}
void DCCWaveform::promotePendingPacket() {
// fill the transmission packet from the pending packet
// Just keep going if repeating
if (transmitRepeats > 0) {
transmitRepeats--;
return;
}
if (packetPending) {
// Copy pending packet to transmit packet
// a fixed length memcpy is faster than a variable length loop for these small lengths
// for (int b = 0; b < pendingLength; b++) transmitPacket[b] = pendingPacket[b];
memcpy( transmitPacket, pendingPacket, sizeof(pendingPacket));
transmitLength = pendingLength;
transmitRepeats = pendingRepeats;
packetPending = false;
clearResets();
return;
}
// nothing to do, just send idles or resets
// Fortunately reset and idle packets are the same length
memcpy( transmitPacket, isMainTrack ? idlePacket : resetPacket, sizeof(idlePacket));
transmitLength = sizeof(idlePacket);
transmitRepeats = 0;
if (getResets() < 250) sentResetsSincePacket++; // only place to increment (private!)
} }
#endif #endif
@ -283,15 +266,15 @@ void DCCWaveform::schedulePacket(const byte buffer[], byte byteCount, byte repea
} }
} }
bool DCCWaveform::isReminderWindowOpen() { bool DCCWaveform::getPacketPending() {
if(isMainTrack) { if(isMainTrack) {
if (rmtMainChannel == NULL) if (rmtMainChannel == NULL)
return false; return true;
return !rmtMainChannel->busy(); return rmtMainChannel->busy();
} else { } else {
if (rmtProgChannel == NULL) if (rmtProgChannel == NULL)
return false; return true;
return !rmtProgChannel->busy(); return rmtProgChannel->busy();
} }
} }
void IRAM_ATTR DCCWaveform::loop() { void IRAM_ATTR DCCWaveform::loop() {

View File

@ -76,13 +76,11 @@ class DCCWaveform {
}; };
#endif #endif
void schedulePacket(const byte buffer[], byte byteCount, byte repeats); void schedulePacket(const byte buffer[], byte byteCount, byte repeats);
bool isReminderWindowOpen(); bool getPacketPending();
void promotePendingPacket();
private: private:
#ifndef ARDUINO_ARCH_ESP32 #ifndef ARDUINO_ARCH_ESP32
volatile bool packetPending; volatile bool packetPending;
volatile bool reminderWindowOpen;
volatile byte sentResetsSincePacket; volatile byte sentResetsSincePacket;
#else #else
volatile uint32_t resetPacketBase; volatile uint32_t resetPacketBase;

View File

@ -3,9 +3,7 @@
#include "StringFormatter.h" #include "StringFormatter.h"
#define VERSION "5.2.14" #define VERSION "5.2.13"
// 5.2.14 - Reminder window DCC packet optimization
// - Optional #define DISABLE_FUNCTION_REMINDERS
// 5.2.13 - EXRAIL STEALTH // 5.2.13 - EXRAIL STEALTH
// 5.2.12 - ESP32 add AP mode LCD messages with SSID/PW for // 5.2.12 - ESP32 add AP mode LCD messages with SSID/PW for
// - STM32 change to UID_BASE constants in DCCTimerSTM32 rather than raw hex addresses for UID registers // - STM32 change to UID_BASE constants in DCCTimerSTM32 rather than raw hex addresses for UID registers