mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2024-11-24 00:26:13 +01:00
Compare commits
6 Commits
91cff82499
...
9c2ce40367
Author | SHA1 | Date | |
---|---|---|---|
|
9c2ce40367 | ||
|
08f0a2b37d | ||
|
6637ea6fe7 | ||
|
a69017f8bb | ||
|
3f4099520a | ||
|
07fd4bc309 |
11
DCC.cpp
11
DCC.cpp
|
@ -595,7 +595,7 @@ void DCC::loop() {
|
|||
|
||||
void DCC::issueReminders() {
|
||||
// if the main track transmitter still has a pending packet, skip this time around.
|
||||
if ( DCCWaveform::mainTrack.getPacketPending()) return;
|
||||
if (!DCCWaveform::mainTrack.isReminderWindowOpen()) return;
|
||||
// Move to next loco slot. If occupied, send a reminder.
|
||||
int reg = lastLocoReminder+1;
|
||||
if (reg > highestUsedReg) reg = 0; // Go to start of table
|
||||
|
@ -620,14 +620,23 @@ bool DCC::issueReminder(int reg) {
|
|||
case 1: // remind function group 1 (F0-F4)
|
||||
if (flags & FN_GROUP_1)
|
||||
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;
|
||||
case 2: // remind function group 2 F5-F8
|
||||
if (flags & FN_GROUP_2)
|
||||
setFunctionInternal(loco,0, 176 | ((functions>>5)& 0x0F)); // 1011 DDDD
|
||||
#ifdef DISABLE_FUNCTION_REMINDERS
|
||||
flags&= ~FN_GROUP_2; // dont send them again
|
||||
#endif
|
||||
break;
|
||||
case 3: // remind function group 3 F9-F12
|
||||
if (flags & FN_GROUP_3)
|
||||
setFunctionInternal(loco,0, 160 | ((functions>>9)& 0x0F)); // 1010 DDDD
|
||||
#ifdef DISABLE_FUNCTION_REMINDERS
|
||||
flags&= ~FN_GROUP_3; // dont send them again
|
||||
#endif
|
||||
break;
|
||||
case 4: // remind function group 4 F13-F20
|
||||
if (flags & FN_GROUP_4)
|
||||
|
|
|
@ -106,6 +106,7 @@ void DCCWaveform::interruptHandler() {
|
|||
DCCWaveform::DCCWaveform( byte preambleBits, bool isMain) {
|
||||
isMainTrack = isMain;
|
||||
packetPending = false;
|
||||
reminderWindowOpen = false;
|
||||
memcpy(transmitPacket, idlePacket, sizeof(idlePacket));
|
||||
state = WAVE_START;
|
||||
// The +1 below is to allow the preamble generator to create the stop bit
|
||||
|
@ -127,9 +128,15 @@ void DCCWaveform::interrupt2() {
|
|||
if (remainingPreambles > 0 ) {
|
||||
state=WAVE_MID_1; // switch state to trigger LOW on next interrupt
|
||||
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.
|
||||
// Allow for checkAck and its called functions using 22 bytes more.
|
||||
DCCTimer::updateMinimumFreeMemoryISR(22);
|
||||
else DCCTimer::updateMinimumFreeMemoryISR(22);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -148,30 +155,9 @@ void DCCWaveform::interrupt2() {
|
|||
if (bytes_sent >= transmitLength) {
|
||||
// end of transmission buffer... repeat or switch to next message
|
||||
bytes_sent = 0;
|
||||
// preamble for next packet will start...
|
||||
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!)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma GCC pop_options
|
||||
|
@ -193,8 +179,39 @@ void DCCWaveform::schedulePacket(const byte buffer[], byte byteCount, byte repea
|
|||
packetPending = true;
|
||||
clearResets();
|
||||
}
|
||||
bool DCCWaveform::getPacketPending() {
|
||||
return packetPending;
|
||||
|
||||
bool DCCWaveform::isReminderWindowOpen() {
|
||||
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
|
||||
|
||||
|
@ -266,15 +283,15 @@ void DCCWaveform::schedulePacket(const byte buffer[], byte byteCount, byte repea
|
|||
}
|
||||
}
|
||||
|
||||
bool DCCWaveform::getPacketPending() {
|
||||
bool DCCWaveform::isReminderWindowOpen() {
|
||||
if(isMainTrack) {
|
||||
if (rmtMainChannel == NULL)
|
||||
return true;
|
||||
return rmtMainChannel->busy();
|
||||
return false;
|
||||
return !rmtMainChannel->busy();
|
||||
} else {
|
||||
if (rmtProgChannel == NULL)
|
||||
return true;
|
||||
return rmtProgChannel->busy();
|
||||
return false;
|
||||
return !rmtProgChannel->busy();
|
||||
}
|
||||
}
|
||||
void IRAM_ATTR DCCWaveform::loop() {
|
||||
|
|
|
@ -76,11 +76,13 @@ class DCCWaveform {
|
|||
};
|
||||
#endif
|
||||
void schedulePacket(const byte buffer[], byte byteCount, byte repeats);
|
||||
bool getPacketPending();
|
||||
bool isReminderWindowOpen();
|
||||
void promotePendingPacket();
|
||||
|
||||
private:
|
||||
#ifndef ARDUINO_ARCH_ESP32
|
||||
volatile bool packetPending;
|
||||
volatile bool reminderWindowOpen;
|
||||
volatile byte sentResetsSincePacket;
|
||||
#else
|
||||
volatile uint32_t resetPacketBase;
|
||||
|
|
|
@ -3,7 +3,9 @@
|
|||
|
||||
#include "StringFormatter.h"
|
||||
|
||||
#define VERSION "5.2.13"
|
||||
#define VERSION "5.2.14"
|
||||
// 5.2.14 - Reminder window DCC packet optimization
|
||||
// - Optional #define DISABLE_FUNCTION_REMINDERS
|
||||
// 5.2.13 - EXRAIL STEALTH
|
||||
// 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
|
||||
|
|
Loading…
Reference in New Issue
Block a user