From e90b28d8ccb9eedc19c23ebeb0129308a74e2865 Mon Sep 17 00:00:00 2001 From: Thomas Vanbesien Date: Tue, 16 Jun 2026 17:03:26 +0200 Subject: fix: add workaround for turning all printheads on/off --- src/Xpl2Client.cpp | 136 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) (limited to 'src/Xpl2Client.cpp') diff --git a/src/Xpl2Client.cpp b/src/Xpl2Client.cpp index 102970e..40118b1 100644 --- a/src/Xpl2Client.cpp +++ b/src/Xpl2Client.cpp @@ -6,6 +6,8 @@ #include +#include + bool Xpl2Client::s_wireDebug = false; /* ------------------------------------------------------------------ */ @@ -163,6 +165,10 @@ Xpl2Client::Xpl2Client (QObject *parent) : QObject (parent) connect (&m_retryTimer, &QTimer::timeout, this, &Xpl2Client::retryConnection); + + m_jettingScanTimer.setSingleShot (true); + connect (&m_jettingScanTimer, &QTimer::timeout, this, + &Xpl2Client::onJettingScanTimeout); } /* ------------------------------------------------------------------ */ @@ -301,6 +307,12 @@ Xpl2Client::disconnectFromProxy () void Xpl2Client::getJcVersion () { + qWarning ("%s getJcVersion() is unreliable on this controller (wrong " + "printhead count) — do not use. See docs/DISCREPANCIES.md (D3).", + qPrintable (logTag (&m_commandSocket))); + emit errorOccurred ( + QStringLiteral ("getJcVersion() is unreliable on this controller (wrong " + "printhead count) — do not use it.")); sendCommand (&m_commandSocket, "GS_JC_VERSION"); } @@ -317,6 +329,14 @@ Xpl2Client::getPhVersion (int printheadId) void Xpl2Client::jettingAllOn () { + qWarning ( + "%s jettingAllOn() is broken on this controller (only drives heads " + "before the first ID gap) — use jettingAvailableOn(). See " + "docs/DISCREPANCIES.md (D6).", + qPrintable (logTag (&m_commandSocket))); + emit errorOccurred (QStringLiteral ( + "jettingAllOn() is broken on this controller — use jettingAvailableOn() " + "instead.")); sendCommand (&m_commandSocket, "CN_JETTING_ALL_ON"); } @@ -329,6 +349,13 @@ Xpl2Client::jettingOn (const QString &jettingMask) void Xpl2Client::jettingOff () { + qWarning ("%s jettingOff() mirrors the jettingAllOn() defect on this " + "controller — use jettingAvailableOff(). See " + "docs/DISCREPANCIES.md (D6).", + qPrintable (logTag (&m_commandSocket))); + emit errorOccurred ( + QStringLiteral ("jettingOff() is unreliable on this controller — use " + "jettingAvailableOff() instead.")); sendCommand (&m_commandSocket, "CN_JETTING_OFF"); } @@ -345,6 +372,106 @@ Xpl2Client::phJettingOff (int printheadId) sendCommand (&m_commandSocket, "CN_PH_JETTING_OFF", { printheadId }); } +void +Xpl2Client::jettingAvailableOn () +{ + startJettingScan (true); +} + +void +Xpl2Client::jettingAvailableOff () +{ + startJettingScan (false); +} + +bool +Xpl2Client::phVersionIsAvailable (const QString &mcuFirmwareVersion, + const QString &fpgaFirmwareVersion, + const QString &fpgaHardwareVersion, + const QString &bootloaderVersion) +{ + // Absent printheads reply with all-zero versions. mcuHardwareVersion and + // mcuFirmwareVariant read "00" even on present heads, so they are not part + // of the test (see docs/DISCREPANCIES.md). + return mcuFirmwareVersion.toDouble () != 0.0 + || fpgaFirmwareVersion.toDouble () != 0.0 + || fpgaHardwareVersion.toDouble () != 0.0 + || bootloaderVersion.toDouble () != 0.0; +} + +void +Xpl2Client::startJettingScan (bool turnOn) +{ + if (!m_connected) + { + emit errorOccurred ( + QStringLiteral ("Not connected for jettingAvailable%1") + .arg (turnOn ? QStringLiteral ("On") : QStringLiteral ("Off"))); + return; + } + if (m_jettingScanActive) + { + qWarning ("%s jettingAvailable: a scan is already in progress, ignoring", + qPrintable (logTag (&m_commandSocket))); + return; + } + + m_jettingScanActive = true; + m_jettingScanTurnOn = turnOn; + m_jettingScanAvailable.clear (); + m_jettingScanPending.clear (); + for (int id = 1; id <= MaxProbedPrintheadId; ++id) + { + m_jettingScanPending.insert (id); + getPhVersion (id); + } + m_jettingScanTimer.start (JettingScanTimeoutMs); + qDebug ("%s jettingAvailable%s: probing %d printheads", + qPrintable (logTag (&m_commandSocket)), turnOn ? "On" : "Off", + MaxProbedPrintheadId); +} + +void +Xpl2Client::finishJettingScan () +{ + m_jettingScanTimer.stop (); + m_jettingScanActive = false; + m_jettingScanPending.clear (); + std::sort (m_jettingScanAvailable.begin (), m_jettingScanAvailable.end ()); + + if (m_connected) + for (int id : m_jettingScanAvailable) + { + if (m_jettingScanTurnOn) + phJettingOn (id, QString::fromLatin1 (AllNozzlesOnMask)); + else + phJettingOff (id); + } + qDebug ("%s jettingAvailable%s: jetted %lld available printhead(s)", + qPrintable (logTag (&m_commandSocket)), + m_jettingScanTurnOn ? "On" : "Off", + static_cast (m_jettingScanAvailable.size ())); + emit jettingAvailableComplete (m_jettingScanTurnOn, m_jettingScanAvailable); +} + +void +Xpl2Client::onJettingScanTimeout () +{ + if (!m_jettingScanActive) + return; + qWarning ( + "%s jettingAvailable: timed out waiting for %lld version reply(ies);" + " proceeding with %lld available", + qPrintable (logTag (&m_commandSocket)), + static_cast (m_jettingScanPending.size ()), + static_cast (m_jettingScanAvailable.size ())); + emit errorOccurred ( + QStringLiteral ( + "jettingAvailable: %1 printhead(s) did not respond in time") + .arg (m_jettingScanPending.size ())); + finishJettingScan (); +} + void Xpl2Client::jcIdLedOn () { @@ -789,6 +916,15 @@ Xpl2Client::handleGsPhVersion (const QVariantList ¶ms) .arg (bootVer)); emit phVersionReceived (cid, phId, mcuFw, mcuHw, mcuFwVar, fpgaFw, fpgaHw, bootVer); + + // Feed an in-progress jettingAvailableOn()/Off() scan. + if (m_jettingScanActive && m_jettingScanPending.remove (phId)) + { + if (phVersionIsAvailable (mcuFw, fpgaFw, fpgaHw, bootVer)) + m_jettingScanAvailable.append (phId); + if (m_jettingScanPending.isEmpty ()) + finishJettingScan (); + } } bool -- cgit v1.3.1