Skip to content

Instantly share code, notes, and snippets.

@kasperkamperman
Last active January 22, 2016 09:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kasperkamperman/b0d0d8058246d674dd01 to your computer and use it in GitHub Desktop.
Save kasperkamperman/b0d0d8058246d674dd01 to your computer and use it in GitHub Desktop.
Test with sqrt blending color values using FastLED functions.
// sqrt blending test
// http://scottsievert.com/blog/2015/04/24/image-sqrt/
// https://plus.google.com/+KasperKamperman/posts/jkACVWijSDN
// algorithms sqrt32 from: http://stackoverflow.com/questions/1100090/looking-for-an-efficient-integer-square-root-algorithm-for-arm-thumb2
#include "FastLED.h"
// How many leds in your strip?
#define NUM_LEDS 128
#define DATA_PIN 11
#define CLOCK_PIN 14
CRGB red = CRGB(255,0,0);
CRGB green = CRGB(0,255,0);
CRGB leds[NUM_LEDS];
unsigned long t1; // for measuring purposes
unsigned long t2; // for measuring purposes
unsigned long t3 = 0; // for measuring purposes
void setup() {
Serial.begin(57600);
LEDS.addLeds<APA102, DATA_PIN, CLOCK_PIN, BGR, DATA_RATE_MHZ(16)>(leds, NUM_LEDS);
LEDS.setBrightness(255);
LEDS.setDither(0);
delay(2000);
}
void loop() {
// setTime();
// for(int i = 0; i < 256; i++) {
// leds[i] = blend(red, green, i);
// }
// printTime();
Serial.println("sqrt16");
setTime();
for(int i = 0; i < 64; i++) {
leds[i] = sqrtBlend(red, green, i*4);
}
printTime();
Serial.println("sqrt32");
setTime();
for(int i = 64; i < 128; i++) {
leds[i] = sqrt32Blend(red, green, (i-64)*2);
}
printTime();
LEDS.show();
delay(5000);
}
CRGB sqrtBlend(CRGB a, CRGB b, uint8_t t) {
CRGB rgb;
rgb.r = sqrt16(scale16by8( a.r * a.r, (255 - t) ) + scale16by8( b.r * b.r, t ));
rgb.g = sqrt16(scale16by8( a.g * a.g, (255 - t) ) + scale16by8( b.g * b.g, t ));
rgb.b = sqrt16(scale16by8( a.b * a.b, (255 - t) ) + scale16by8( b.b * b.b, t ));
return rgb;
}
CRGB sqrt32Blend(CRGB a, CRGB b, uint8_t t) {
CRGB rgb;
uint16_t r1 = a.r <<8;
uint16_t r2 = b.r <<8;
uint16_t g1 = a.g <<8;
uint16_t g2 = b.g <<8;
uint16_t b1 = a.b <<8;
uint16_t b2 = b.b <<8;
// typecast to uint64_t
// https://forum.pjrc.com/threads/27622-try-to-multiply-two-uint32_t-into-a-uint64_t-seems-not-to-work
uint16_t ro = sqrt32(scale32by8( (uint64_t) r1 * r1, (255 - t) ) + scale32by8( (uint64_t) r2 * r2, t ));
uint16_t go = sqrt32(scale32by8( (uint64_t) g1 * g1, (255 - t) ) + scale32by8( (uint64_t) g2 * g2, t ));
uint16_t bo = sqrt32(scale32by8( (uint64_t) b1 * b1, (255 - t) ) + scale32by8( (uint64_t) b2 * b2, t ));
rgb.r = ro >> 8;
rgb.g = go >> 8;
rgb.b = bo >> 8;
return rgb;
}
// typecast
// https://forum.pjrc.com/threads/27622-try-to-multiply-two-uint32_t-into-a-uint64_t-seems-not-to-work
uint32_t scale32by8( uint32_t i, uint8_t scale ) {
return (i * (uint64_t) scale) / 256;
}
/*
* Tested different algorithms from:
* http://stackoverflow.com/questions/1100090/looking-for-an-efficient-integer-square-root-algorithm-for-arm-thumb2
* This one (from Craig McQueen) was the fastest (tested in a blend from red to green with a Teensy 3.0)
* rounded version doesn't cost really much more: 464us vs 446us (not rounded version)
* fastled sqrt16 takes 652
* so we stick with the rounded version
* Fractional parts of the answer are discarded.
*/
uint16_t sqrt32(uint32_t a_nInput)
{
uint32_t op = a_nInput;
uint32_t res = 0;
uint32_t one = 1uL << 30; // The second-to-top bit is set: use 1u << 14 for uint16_t type; use 1uL<<30 for uint32_t type
// "one" starts at the highest power of four <= than the argument.
while (one > op) {
one >>= 2;
}
while (one != 0) {
if (op >= res + one) {
op = op - (res + one);
res = res + 2 * one;
}
res >>= 1;
one >>= 2;
}
/* Do arithmetic rounding to nearest integer */
if (op > res) {
res++;
}
return res;
}
void setTime()
{ t1 = micros();
}
void printTime()
{
t2 = micros()-t1;
if(t2>t3) t3 = t2;
Serial.print(F("time used: "));
Serial.print(t3);
Serial.print(" ");
Serial.print(t2);
Serial.println();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment