From c31d2b1918fd943f87e8288a608d73dc77f23d30 Mon Sep 17 00:00:00 2001 From: Micah Elizabeth Scott <micah@scanlime.org> Date: Tue, 23 Jul 2013 17:43:32 -0700 Subject: [PATCH] Overflow-safe arithmetic in interpolation calculation --- firmware/fadecandy.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/firmware/fadecandy.cpp b/firmware/fadecandy.cpp index 53c30db..7bb4f5c 100644 --- a/firmware/fadecandy.cpp +++ b/firmware/fadecandy.cpp @@ -39,7 +39,7 @@ static OctoWS2811z leds(LEDS_PER_STRIP, ledBuffer, WS2811_800kHz); static int8_t residual[CHANNELS_TOTAL]; -static uint32_t calculateInterpCoefficient() +static inline uint32_t calculateInterpCoefficient() { /* * Calculate our interpolation coefficient. This is a value between @@ -62,9 +62,11 @@ static uint32_t calculateInterpCoefficient() uint32_t now = millis(); uint32_t tsPrev = buffers.fbPrev->timestamp; uint32_t tsNext = buffers.fbNext->timestamp; + uint32_t tsDiff = tsNext - tsPrev; + uint32_t tsElapsed = now - tsNext; - uint32_t scaled = ((now - tsNext) << 16) / (tsNext - tsPrev); - return std::min<uint32_t>(scaled, 0x10000); + // Careful to avoid overflows if the frames stop coming... + return (std::min<uint32_t>(tsElapsed, tsDiff) << 16) / tsDiff; } ALWAYS_INLINE static inline uint32_t lutInterpolate(const uint16_t *lut, uint32_t arg) @@ -444,8 +446,11 @@ extern "C" int main() leds.begin(); while (1) { + uint32_t ic = calculateInterpCoefficient(); + buffers.handleUSB(); - updateDrawBuffer(calculateInterpCoefficient()); + + updateDrawBuffer(ic); leds.show(); // Optionally disable dithering by clearing our residual buffer every frame. -- GitLab