From efbb530d9d631616c5bd81a1e65d4b352d88aab6 Mon Sep 17 00:00:00 2001 From: Mike Toon Date: Thu, 5 Sep 2019 15:42:04 +0100 Subject: [PATCH] BLOCKS: Fix heap sync issue when block is reconnected Reset lastPacketIndexReceived when a device is reconnected to mirror behaviour in firmware. --- .../littlefoot/juce_LittleFootRemoteHeap.h | 117 +++++++++++------- .../internal/juce_BlockImplementation.cpp | 7 +- 2 files changed, 74 insertions(+), 50 deletions(-) diff --git a/modules/juce_blocks_basics/littlefoot/juce_LittleFootRemoteHeap.h b/modules/juce_blocks_basics/littlefoot/juce_LittleFootRemoteHeap.h index c124ecd0f1..045244790f 100644 --- a/modules/juce_blocks_basics/littlefoot/juce_LittleFootRemoteHeap.h +++ b/modules/juce_blocks_basics/littlefoot/juce_LittleFootRemoteHeap.h @@ -19,8 +19,15 @@ ============================================================================== */ +#ifndef JUCE_DUMP_LITTLEFOOT_HEAP_STATUS + #define JUCE_DUMP_LITTLEFOOT_HEAP_STATUS 0 +#endif -#define JUCE_DUMP_LITTLEFOOT_HEAP_STATUS 0 +#if JUCE_DUMP_LITTLEFOOT_HEAP_STATUS + #define JUCE_LOG_LITTLEFOOT_HEAP(text) DBG(text) +#else + #define JUCE_LOG_LITTLEFOOT_HEAP(text) +#endif namespace littlefoot { @@ -43,15 +50,27 @@ struct LittleFootRemoteHeap resetDeviceStateToUnknown(); } - void clear() noexcept + void reset() { + JUCE_LOG_LITTLEFOOT_HEAP ("Resetting heap state"); + clearTargetData(); + resetDeviceStateToUnknown(); + lastPacketIndexReceived = 0; + } + + void clearTargetData() noexcept + { + JUCE_LOG_LITTLEFOOT_HEAP ("Clearing target heap data"); zeromem (targetData, sizeof (targetData)); - invalidateData(); + needsSyncing = true; + programStateKnown = false; } void resetDeviceStateToUnknown() { - invalidateData(); + JUCE_LOG_LITTLEFOOT_HEAP ("Resetting device state to unknown"); + needsSyncing = true; + programStateKnown = false; messagesSent.clear(); resetDataRangeToUnknown (0, ImplementationClass::maxBlockSize); } @@ -66,20 +85,19 @@ struct LittleFootRemoteHeap void setByte (size_t offset, uint8 value) noexcept { - if (offset < blockSize) + if (offset >= blockSize) { - if (targetData[offset] != value) - { - targetData[offset] = value; - needsSyncing = true; - - if (programStateKnown && offset < programSize) - programStateKnown = false; - } + jassertfalse; + return; } - else + + if (targetData[offset] != value) { - jassertfalse; + targetData[offset] = value; + needsSyncing = true; + + if (offset < programSize) + programStateKnown = false; } } @@ -99,8 +117,14 @@ struct LittleFootRemoteHeap if (readLittleEndianBitsInBuffer (targetData, startBit, numBits) != value) { + JUCE_LOG_LITTLEFOOT_HEAP ("Set bits sync " << String (startBit) << " " << String (numBits) << String (value)); + writeLittleEndianBitsInBuffer (targetData, startBit, numBits, value); - invalidateData(); + + needsSyncing = true; + + if (startBit < programSize) + programStateKnown = false; } } @@ -113,12 +137,6 @@ struct LittleFootRemoteHeap return 0; } - void invalidateData() noexcept - { - needsSyncing = true; - programStateKnown = false; - } - bool isFullySynced() const noexcept { return ! needsSyncing; @@ -167,7 +185,8 @@ struct LittleFootRemoteHeap m->dispatchTime = Time::getCurrentTime(); bi.sendMessageToDevice (m->packet); - //DBG ("Sending packet " << (int) m->packetIndex << " - " << m->packet.size() << " bytes, device " << bi.getDeviceIndex()); + + JUCE_LOG_LITTLEFOOT_HEAP ("Sending packet " << (int) m->packetIndex << " - " << m->packet.size() << " bytes, device " << bi.getDeviceIndex()); if (getTotalSizeOfMessagesSent() > 200) break; @@ -176,43 +195,45 @@ struct LittleFootRemoteHeap void handleACKFromDevice (ImplementationClass& bi, uint32 packetIndex) noexcept { - //DBG ("ACK " << (int) packetIndex << " device " << (int) bi.getDeviceIndex()); + if (packetIndex == lastPacketIndexReceived) + return; - if (lastPacketIndexReceived != packetIndex) - { - lastPacketIndexReceived = packetIndex; + JUCE_LOG_LITTLEFOOT_HEAP ("ACK " << (int) packetIndex << " device " << (int) bi.getDeviceIndex() + << ", last packet received " << String (lastPacketIndexReceived)); - for (int i = messagesSent.size(); --i >= 0;) - { - auto& m = *messagesSent.getUnchecked(i); + lastPacketIndexReceived = packetIndex; - if (m.packetIndex == packetIndex) - { - for (uint32 j = 0; j < blockSize; ++j) - deviceState[j] = m.resultDataState[j]; + for (int i = messagesSent.size(); --i >= 0;) + { + auto& m = *messagesSent.getUnchecked(i); - programStateKnown = false; - messagesSent.removeRange (0, i + 1); - dumpStatus(); - sendChanges (bi, false); + if (m.packetIndex == packetIndex) + { + for (uint32 j = 0; j < blockSize; ++j) + deviceState[j] = m.resultDataState[j]; - if (messagesSent.isEmpty()) - needsSyncing = false; + programStateKnown = false; + messagesSent.removeRange (0, i + 1); + dumpStatus(); + sendChanges (bi, false); - return; + if (messagesSent.isEmpty()) + { + JUCE_LOG_LITTLEFOOT_HEAP ("Heap fully synced"); + needsSyncing = false; } - } - resetDeviceStateToUnknown(); + return; + } } + + resetDeviceStateToUnknown(); } bool isProgramLoaded() noexcept { if (! programStateKnown) { - programStateKnown = true; - uint8 deviceMemory[ImplementationClass::maxBlockSize]; for (size_t i = 0; i < blockSize; ++i) @@ -221,6 +242,8 @@ struct LittleFootRemoteHeap littlefoot::Program prog (deviceMemory, (uint32) blockSize); programLoaded = prog.checksumMatches(); programSize = prog.getProgramSize(); + + programStateKnown = true; } return programLoaded; @@ -287,8 +310,8 @@ private: ignoreUnused (proportionOK); - DBG ("Heap: " << areas << " " << String (roundToInt (100 * proportionOK)) << "% " - << (isProgramLoaded() ? "Ready" : "Loading")); + JUCE_LOG_LITTLEFOOT_HEAP ("Heap: " << areas << " " << String (roundToInt (100 * proportionOK)) + << "% " << (isProgramLoaded() ? "Ready" : "Loading")); #endif } diff --git a/modules/juce_blocks_basics/topology/internal/juce_BlockImplementation.cpp b/modules/juce_blocks_basics/topology/internal/juce_BlockImplementation.cpp index 9bc3dcf124..6d3a7fbde1 100644 --- a/modules/juce_blocks_basics/topology/internal/juce_BlockImplementation.cpp +++ b/modules/juce_blocks_basics/topology/internal/juce_BlockImplementation.cpp @@ -85,8 +85,9 @@ public: updateDeviceInfo (deviceInfo); + remoteHeap.reset(); + setProgram (nullptr); - remoteHeap.resetDeviceStateToUnknown(); if (auto surface = dynamic_cast (touchSurface.get())) surface->activateTouchSurface(); @@ -294,7 +295,7 @@ public: if (program == nullptr) { - remoteHeap.clear(); + remoteHeap.clearTargetData(); return Result::ok(); } @@ -316,7 +317,7 @@ public: programSize = (uint32) size; remoteHeap.resetDataRangeToUnknown (0, remoteHeap.blockSize); - remoteHeap.clear(); + remoteHeap.clearTargetData(); remoteHeap.sendChanges (*this, true); remoteHeap.resetDataRangeToUnknown (0, (uint32) size);