#include <FastLED.h>
#define WIDTH 22
#define HEIGHT 22
#define NUM_LEDS ((WIDTH) * (HEIGHT))
#define POINTS 5
CRGB leds[NUM_LEDS + 1];
uint16_t XY(uint8_t x, uint8_t y) {
if (x >= WIDTH) return NUM_LEDS;
if (y >= HEIGHT) return NUM_LEDS;
if (y & 1)
return (y + 1) * WIDTH - 1 - x;
else
return y * WIDTH + x;
}
#include "wuLineAA.h"
// x & y are Q7.8 fixed-point
// dx & dy are Q.7 deltas for x & y.
struct Point {
saccum78 x, y;
sfract7 dx, dy;
};
Point points[POINTS];
void setup() {
Serial.begin(115200);
FastLED.addLeds<NEOPIXEL, 3>(leds, NUM_LEDS);
FastLED.setCorrection(UncorrectedColor);
FastLED.setTemperature(UncorrectedTemperature);
FastLED.setDither(DISABLE_DITHER);
}
void loop()
{
static int frame; frame++;
uint32_t ms = millis();
FastLED.clear();
// change `effect` every 3-seconds
static uint8_t effect = 0;
EVERY_N_MILLIS(3000) {
// Serial.println(FastLED.getFPS());
if (++effect > 6) effect = 5;
}
for (uint8_t i = 0; i < POINTS; i++) {
points[i].x = cos16(ms * 2 + i * (65536 / POINTS)) / (256 / WIDTH + 2) + WIDTH * 128;
points[i].y = sin16(ms * 2 + i * (65536 / POINTS)) / (256 / HEIGHT + 2) + HEIGHT * 128;
}
CRGB plot_colour = 0xffffff;
// draw lines between each point
for (uint8_t i = 0; i < POINTS; i++) {
switch (effect) {
// show aliased lines
case 0:
plotLine( points[i].x >> 8,
points[i].y >> 8,
points[(i + 1) % POINTS].x >> 8,
points[(i + 1) % POINTS].y >> 8,
&plot_colour);
break;
// ...and anti-aliased
case 1:
plotLineAA( points[i].x >> 8,
points[i].y >> 8,
points[(i + 1) % POINTS].x >> 8,
points[(i + 1) % POINTS].y >> 8,
&plot_colour);
break;
case 2:
// 1/2 sub-pixel
wuLineAA( points[i].x & 0xff80,
points[i].y & 0xff80,
points[(i + 1) % POINTS].x & 0xff80,
points[(i + 1) % POINTS].y & 0xff80,
&plot_colour);
break;
case 3:
// 1/4 sub-pixel
wuLineAA( points[i].x & 0xffc0,
points[i].y & 0xffc0,
points[(i + 1) % POINTS].x & 0xffc0,
points[(i + 1) % POINTS].y & 0xffc0,
&plot_colour);
break;
case 4:
// 1/8th sub-pixel
wuLineAA( points[i].x & 0xffe0,
points[i].y & 0xffe0,
points[(i + 1) % POINTS].x & 0xffe0,
points[(i + 1) % POINTS].y & 0xffe0,
&plot_colour);
break;
case 5:
// 1/16th sub-pixel
wuLineAA( points[i].x & 0xfff0,
points[i].y & 0xfff0,
points[(i + 1) % POINTS].x & 0xfff0,
points[(i + 1) % POINTS].y & 0xfff0,
&plot_colour);
break;
default:
// ...and 1/256th sub-pixel positioned anti-aliased
wuLineAA( points[i].x,
points[i].y,
points[(i + 1) % POINTS].x,
points[(i + 1) % POINTS].y,
&plot_colour);
}
}
FastLED.show();
// delay(1000);
}
// from: https://github.com/FastLED/FastLED/pull/202
CRGB ColorFromPaletteExtended(const CRGBPalette16& pal, uint16_t index, uint8_t brightness, TBlendType blendType) {
// Extract the four most significant bits of the index as a palette index.
uint8_t index_4bit = (index >> 12);
// Calculate the 8-bit offset from the palette index.
uint8_t offset = (uint8_t)(index >> 4);
// Get the palette entry from the 4-bit index
const CRGB* entry = &(pal[0]) + index_4bit;
uint8_t red1 = entry->red;
uint8_t green1 = entry->green;
uint8_t blue1 = entry->blue;
uint8_t blend = offset && (blendType != NOBLEND);
if (blend) {
if (index_4bit == 15) {
entry = &(pal[0]);
} else {
entry++;
}
// Calculate the scaling factor and scaled values for the lower palette value.
uint8_t f1 = 255 - offset;
red1 = scale8_LEAVING_R1_DIRTY(red1, f1);
green1 = scale8_LEAVING_R1_DIRTY(green1, f1);
blue1 = scale8_LEAVING_R1_DIRTY(blue1, f1);
// Calculate the scaled values for the neighbouring palette value.
uint8_t red2 = entry->red;
uint8_t green2 = entry->green;
uint8_t blue2 = entry->blue;
red2 = scale8_LEAVING_R1_DIRTY(red2, offset);
green2 = scale8_LEAVING_R1_DIRTY(green2, offset);
blue2 = scale8_LEAVING_R1_DIRTY(blue2, offset);
cleanup_R1();
// These sums can't overflow, so no qadd8 needed.
red1 += red2;
green1 += green2;
blue1 += blue2;
}
if (brightness != 255) {
// nscale8x3_video(red1, green1, blue1, brightness);
nscale8x3(red1, green1, blue1, brightness);
}
return CRGB(red1, green1, blue1);
}