From 9a1eb3ede9b9dcd1a3ecfd9810106be1a3e8dcb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 22 May 2019 15:48:37 +0200 Subject: [PATCH] [ion/display] Add timeout in waitForVBlank --- ion/include/ion/display.h | 2 +- ion/include/ion/timing.h | 2 +- ion/src/device/shared/drivers/display.cpp | 47 +++++++++++++++++++---- ion/src/shared/dummy/display.cpp | 3 +- 4 files changed, 43 insertions(+), 11 deletions(-) diff --git a/ion/include/ion/display.h b/ion/include/ion/display.h index 5eb383cfd..30fb079d1 100644 --- a/ion/include/ion/display.h +++ b/ion/include/ion/display.h @@ -21,7 +21,7 @@ void pushRect(KDRect r, const KDColor * pixels); void pushRectUniform(KDRect r, KDColor c); void pullRect(KDRect r, KDColor * pixels); -void waitForVBlank(); +bool waitForVBlank(); constexpr int Width = 320; constexpr int Height = 240; diff --git a/ion/include/ion/timing.h b/ion/include/ion/timing.h index 523232f8e..3a3b0c9ca 100644 --- a/ion/include/ion/timing.h +++ b/ion/include/ion/timing.h @@ -11,7 +11,7 @@ void msleep(uint32_t ms); /* millis is the number of milliseconds ellapsed since a random epoch. * On the device, epoch is the boot time. */ -uint64_t millis(); +volatile uint64_t millis(); } } diff --git a/ion/src/device/shared/drivers/display.cpp b/ion/src/device/shared/drivers/display.cpp index 0665177b6..32c5b9eb2 100644 --- a/ion/src/device/shared/drivers/display.cpp +++ b/ion/src/device/shared/drivers/display.cpp @@ -44,15 +44,46 @@ void pullRect(KDRect r, KDColor * pixels) { pullPixels(pixels, r.width()*r.height()); } -void waitForVBlank() { - // We want to return as soon as the TE line is transitionning from "DOWN" to "UP" - while (Config::TearingEffectPin.group().IDR()->get(Config::TearingEffectPin.pin())) { - // Loop while high, exit when low - // Wait for zero - } - while (!Config::TearingEffectPin.group().IDR()->get(Config::TearingEffectPin.pin())) { - // Loop while low, exit when high +bool waitForVBlank() { + /* Min screen frequency is 40Hz so the maximal period is T = 1/40Hz = 25ms. + * If after T ms, we still do not have a VBlank event, just return. */ + constexpr uint64_t timeoutDelta = 50; + uint64_t startTime = Timing::millis(); + uint64_t timeout = startTime + timeoutDelta; + + /* If current time is big enough, currentTime + timeout wraps aroud the + * uint64_t. We need to take this into account when computing the terminating + * event. + * + * NO WRAP |----------------|++++++++++|------| + * 0 startTime timeout max uint64_t + * + * WRAP |++++|----------------------|++++++| + * 0 timeout startTime max uint64_t + */ + bool noWrap = startTime < timeout; + + /* We want to return at the beginning of a high signal, so we wait for the + * signal to be low then high. */ + bool wasLow = false; + + uint64_t currentTime = startTime; + while (noWrap ? + (currentTime >= startTime && currentTime < timeout) : + (currentTime >= startTime || currentTime < timeout)) + { + if (!wasLow) { + wasLow = !Config::TearingEffectPin.group().IDR()->get(Config::TearingEffectPin.pin()); + } + if (wasLow) { + if (Config::TearingEffectPin.group().IDR()->get(Config::TearingEffectPin.pin())) { + return true; + } + } + currentTime = Timing::millis(); + // TODO: sleep? } + return false; } void POSTPushMulticolor(int shift, int tileSize) { diff --git a/ion/src/shared/dummy/display.cpp b/ion/src/shared/dummy/display.cpp index c1b14b4ac..e2fd9f46c 100644 --- a/ion/src/shared/dummy/display.cpp +++ b/ion/src/shared/dummy/display.cpp @@ -3,5 +3,6 @@ void Ion::Display::POSTPushMulticolor(int shift, int tileSize) { } -void Ion::Display::waitForVBlank() { +bool Ion::Display::waitForVBlank() { + return true; }