From d6b6f41f79849a37946fa5a758cf1b233259f83b Mon Sep 17 00:00:00 2001 From: markus983 Date: Fri, 2 Dec 2022 11:04:12 +0100 Subject: [PATCH] UART plugin recovers granularity if timing improves --- plugins/uartdmx/UartDmxThread.cpp | 39 +++++++++++++++++++++++++------ plugins/uartdmx/UartDmxThread.h | 1 + 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/plugins/uartdmx/UartDmxThread.cpp b/plugins/uartdmx/UartDmxThread.cpp index 8f776b4a78..291743b1b9 100644 --- a/plugins/uartdmx/UartDmxThread.cpp +++ b/plugins/uartdmx/UartDmxThread.cpp @@ -72,11 +72,14 @@ bool UartDmxThread::WriteDMX(const DmxBuffer &buffer) { * The method called by the thread */ void *UartDmxThread::Run() { - TimeStamp ts1, ts2; + TimeStamp ts1, ts2, ts3; Clock clock; CheckTimeGranularity(); DmxBuffer buffer; + int frameTime = static_cast(floor( + (m_malft / static_cast(1000)) + static_cast(0.5))); + // Setup the widget if (!m_widget->IsOpen()) m_widget->SetupOutput(); @@ -93,6 +96,8 @@ void *UartDmxThread::Run() { buffer.Set(m_buffer); } + clock.CurrentMonotonicTime(&ts1); + if (!m_widget->SetBreak(true)) goto framesleep; @@ -110,7 +115,31 @@ void *UartDmxThread::Run() { framesleep: // Sleep for the remainder of the DMX frame time - usleep(m_malft); + clock.CurrentMonotonicTime(&ts2); + TimeInterval elapsed = ts2 - ts1; + + if (m_granularity == GOOD) { + while (elapsed.InMilliSeconds() < frameTime) { + usleep(1000); + clock.CurrentMonotonicTime(&ts2); + elapsed = ts2 - ts1; + } + } else { + // See if we can drop out of bad mode. + usleep(1000); + clock.CurrentMonotonicTime(&ts3); + TimeInterval interval = ts3 - ts2; + if (interval.InMilliSeconds() <= BAD_GRANULARITY_LIMIT) { + m_granularity = GOOD; + OLA_INFO << "Switching from BAD to GOOD granularity for UART thread"; + } + + elapsed = ts3 - ts1; + while (elapsed.InMilliSeconds() < frameTime) { + clock.CurrentMonotonicTime(&ts2); + elapsed = ts2 - ts1; + } + } } return NULL; } @@ -122,17 +151,13 @@ void *UartDmxThread::Run() { void UartDmxThread::CheckTimeGranularity() { TimeStamp ts1, ts2; Clock clock; - /** If sleeping for 1ms takes longer than this, don't trust - * usleep for this session - */ - const int threshold = 3; clock.CurrentMonotonicTime(&ts1); usleep(1000); clock.CurrentMonotonicTime(&ts2); TimeInterval interval = ts2 - ts1; - m_granularity = interval.InMilliSeconds() > threshold ? BAD : GOOD; + m_granularity = interval.InMilliSeconds() > BAD_GRANULARITY_LIMIT ? BAD : GOOD; OLA_INFO << "Granularity for UART thread is " << (m_granularity == GOOD ? "GOOD" : "BAD"); } diff --git a/plugins/uartdmx/UartDmxThread.h b/plugins/uartdmx/UartDmxThread.h index cbd8d8f945..78d59bdfc3 100644 --- a/plugins/uartdmx/UartDmxThread.h +++ b/plugins/uartdmx/UartDmxThread.h @@ -53,6 +53,7 @@ class UartDmxThread : public ola::thread::Thread { void CheckTimeGranularity(); static const uint32_t DMX_MAB = 16; + static const uint32_t BAD_GRANULARITY_LIMIT = 3; DISALLOW_COPY_AND_ASSIGN(UartDmxThread); };