From c36382ba4fe37f29cb2faab2afc9df8b8d64c08e Mon Sep 17 00:00:00 2001 From: Micah Elizabeth Scott <micah@scanlime.org> Date: Tue, 23 Jul 2013 17:07:19 -0700 Subject: [PATCH] Simple timed interpolation --- examples/usb-basic.py | 2 +- firmware/fadecandy.cpp | 28 +++++++++++++++++++++++++--- firmware/fc_usb.cpp | 1 + firmware/fc_usb.h | 1 + 4 files changed, 28 insertions(+), 4 deletions(-) diff --git a/examples/usb-basic.py b/examples/usb-basic.py index 30bd077..42f2b5a 100755 --- a/examples/usb-basic.py +++ b/examples/usb-basic.py @@ -59,5 +59,5 @@ while True: #time.sleep(0.1) print - time.sleep(2) + time.sleep(0.1) diff --git a/firmware/fadecandy.cpp b/firmware/fadecandy.cpp index f29414f..5ad420d 100644 --- a/firmware/fadecandy.cpp +++ b/firmware/fadecandy.cpp @@ -39,6 +39,29 @@ static OctoWS2811z leds(LEDS_PER_STRIP, ledBuffer, WS2811_800kHz); static int8_t residual[CHANNELS_TOTAL]; +static uint32_t calculateInterpCoefficient() +{ + /* + * Calculate our interpolation coefficient. This is a value between + * 0x0000 and 0x10000, representing some point in between fbPrev and fbNext. + * + * We timestamp each frame at the moment its final packet has been received. + * In other words, fbNew has no valid timestamp yet, and fbPrev/fbNext both + * have timestamps in the recent past. + * + * fbNext's timestamp indicates when both fbPrev and fbNext entered their current + * position in the keyframe queue. The difference between fbPrev and fbNext indicate + * how long the interpolation between those keyframes should take. + */ + + uint32_t now = millis(); + uint32_t tsPrev = buffers.fbPrev->timestamp; + uint32_t tsNext = buffers.fbNext->timestamp; + + uint32_t scaled = ((now - tsNext) << 16) / (tsNext - tsPrev); + return std::min<uint32_t>(scaled, 0x10000); +} + ALWAYS_INLINE static inline uint32_t lutInterpolate(const uint16_t *lut, uint32_t arg) { /* @@ -54,7 +77,7 @@ ALWAYS_INLINE static inline uint32_t lutInterpolate(const uint16_t *lut, uint32_ return (lut[index] * invAlpha + lut[index + 1] * alpha) >> 8; } -static inline uint32_t updatePixel(uint32_t icPrev, uint32_t icNext, +static uint32_t updatePixel(uint32_t icPrev, uint32_t icNext, const uint8_t *pixelPrev, const uint8_t *pixelNext, const uint16_t *lut, int8_t *pResidual) { @@ -416,8 +439,7 @@ extern "C" int main() while (1) { buffers.handleUSB(); - - updateDrawBuffer((millis() << 4) & 0xFFFF); + updateDrawBuffer(calculateInterpCoefficient()); leds.show(); // Optionally disable dithering by clearing our residual buffer every frame. diff --git a/firmware/fc_usb.cpp b/firmware/fc_usb.cpp index de1ec1f..3642239 100644 --- a/firmware/fc_usb.cpp +++ b/firmware/fc_usb.cpp @@ -86,6 +86,7 @@ void fcBuffers::handleUSB() void fcBuffers::finalizeFramebuffer() { fcFramebuffer *recycle = fbPrev; + fbNew->timestamp = millis(); fbPrev = fbNext; fbNext = fbNew; fbNew = recycle; diff --git a/firmware/fc_usb.h b/firmware/fc_usb.h index e975cde..5d69081 100644 --- a/firmware/fc_usb.h +++ b/firmware/fc_usb.h @@ -36,6 +36,7 @@ template <unsigned tSize> struct fcPacketBuffer { usb_packet_t *packets[tSize]; + uint32_t timestamp; fcPacketBuffer() { -- GitLab