From 644cb29a3a55f32f6db58459dad81afc90822fa3 Mon Sep 17 00:00:00 2001 From: Neil McKechnie Date: Tue, 22 Nov 2022 17:24:11 +0000 Subject: [PATCH] Performance improvements in function DCC::issueReminders Function issueReminders was taking around 1700us to complete. It has been refactored to optimise calculations and reduce the amount of the loco table that needs to be scanned each time. It now takes typically under 50us to execute. --- DCC.cpp | 44 +++++++++++++++++--------------------------- DCC.h | 3 ++- 2 files changed, 19 insertions(+), 28 deletions(-) diff --git a/DCC.cpp b/DCC.cpp index 2334842..375725a 100644 --- a/DCC.cpp +++ b/DCC.cpp @@ -589,36 +589,24 @@ byte DCC::loopStatus=0; void DCC::loop() { TrackManager::loop(); // power overload checks + bitSet(DDRE, 4); + bitSet(PORTE, 4); issueReminders(); + bitClear(PORTE, 4); } void DCC::issueReminders() { // if the main track transmitter still has a pending packet, skip this time around. if ( DCCWaveform::mainTrack.getPacketPending()) return; - - // This loop searches for a loco in the speed table starting at nextLoco and cycling back around - /* - for (int reg=0;reg=MAX_LOCOS) slot-=MAX_LOCOS; - if (speedTable[slot].loco > 0) { - // have found the next loco to remind - // issueReminder will return true if this loco is completed (ie speed and functions) - if (issueReminder(slot)) nextLoco=slot+1; - return; - } - } - */ - for (int reg=nextLoco;reg 0) { - // have found the next loco to remind - // issueReminder will return true if this loco is completed (ie speed and functions) - if (issueReminder(slot)) - nextLoco=(slot+1)%MAX_LOCOS; - 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 + if (speedTable[reg].loco > 0) { + // have found loco to remind + if (issueReminder(reg)) + lastLocoReminder = reg; + } else + lastLocoReminder = reg; } bool DCC::issueReminder(int reg) { @@ -698,6 +686,7 @@ int DCC::lookupSpeedTable(int locoId, bool autoCreate) { speedTable[reg].groupFlags=0; speedTable[reg].functions=0; } + if (reg > highestUsedReg) highestUsedReg = reg; return reg; } @@ -705,7 +694,7 @@ void DCC::updateLocoReminder(int loco, byte speedCode) { if (loco==0) { // broadcast stop/estop but dont change direction - for (int reg = 0; reg < MAX_LOCOS; reg++) { + for (int reg = 0; reg < highestUsedReg; reg++) { if (speedTable[reg].loco==0) continue; byte newspeed=(speedTable[reg].speedCode & 0x80) | (speedCode & 0x7f); if (speedTable[reg].speedCode != newspeed) { @@ -725,13 +714,14 @@ void DCC::updateLocoReminder(int loco, byte speedCode) { } DCC::LOCO DCC::speedTable[MAX_LOCOS]; -int DCC::nextLoco = 0; +int DCC::lastLocoReminder = 0; +int DCC::highestUsedReg = 0; void DCC::displayCabList(Print * stream) { int used=0; - for (int reg = 0; reg < MAX_LOCOS; reg++) { + for (int reg = 0; reg <= highestUsedReg; reg++) { if (speedTable[reg].loco>0) { used ++; StringFormatter::send(stream,F("cab=%d, speed=%d, dir=%c \n"), diff --git a/DCC.h b/DCC.h index 46b3b83..15d5a4f 100644 --- a/DCC.h +++ b/DCC.h @@ -108,7 +108,8 @@ private: static void updateLocoReminder(int loco, byte speedCode); static void setFunctionInternal(int cab, byte fByte, byte eByte); static bool issueReminder(int reg); - static int nextLoco; + static int lastLocoReminder; + static int highestUsedReg; static FSH *shieldName; static byte globalSpeedsteps;