#include <Arduino.h>
#include <FastLED.h>
#include <colorutils.h>
enum XY_matrix_config {
SERPENTINE = 1,
ROWMAJOR = 2,
FLIPMAJOR = 4,
FLIPMINOR = 8
};
#define BRIGHTNESS 255
// Define LED matrix parameters
#define LED_PIN 3
#define COLOR_ORDER GRB
#define CHIPSET WS2812B
#define MATRIX_WIDTH 40
#define MATRIX_HEIGHT 12
#define NUM_LEDS (MATRIX_WIDTH * MATRIX_HEIGHT)
#define NUM_LINES 2 // the number of lines you are displaying
#define TEST_UI 1 // allow output to the serial console for testing
CRGB leds[NUM_LEDS + 1]; // 1 extra for XY() to use when out-of-bounds
CRGBPalette16 currentPalette = RainbowColors_p;
typedef struct {
int16_t x1, y1, x2, y2;
} LineXY;
LineXY linesXY[NUM_LINES];
void setup() {
FastLED.addLeds<CHIPSET, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS);
FastLED.setCorrection(UncorrectedColor); //optional but turns off any previously set color correction
FastLED.setTemperature(UncorrectedTemperature); //optional but turns of any previously set temperature correction
FastLED.setDither(DISABLE_DITHER); // stops the lights flickering. see this for explanation: https://github.com/FastLED/FastLED/wiki/FastLED-Temporal-Dithering
FastLED.setBrightness(BRIGHTNESS); // set the maximum brightness of the whole display
pinMode(LED_BUILTIN, OUTPUT);
if (TEST_UI) {
if (!SERIAL) {
Serial.begin(9600); // use this on a virtual board in the emulator
}
}
for (uint8_t line = 0; line < NUM_LINES; line++) {
linesXY[line].x1 = random8() * MATRIX_WIDTH;
linesXY[line].x2 = random8() * MATRIX_WIDTH;
linesXY[line].y1 = random8() * MATRIX_HEIGHT;
linesXY[line].y2 = random8() * MATRIX_HEIGHT;
if (TEST_UI) {
Serial.print("linesXY[line].x1: ");
Serial.print(linesXY[line].x1);
Serial.print(", linesXY[line].y1: ");
Serial.print(linesXY[line].y1);
Serial.print(", linesXY[line].x2: ");
Serial.print(linesXY[line].x2);
Serial.print(", linesXY[line].y2: ");
Serial.print(linesXY[line].y2);
Serial.print(", line: ");
Serial.print(line);
Serial.print(", linesXY[line]: ");
Serial.println(uint32_t(&linesXY[line]), HEX);
}
}
}
void loop() {
// Draw a line from (7, 1) to (33, 10)
draw_line(7, 1, 33, 10);
FastLED.show();
delay(1000); // Adjust delay time as needed
fill_solid(leds, NUM_LEDS, CRGB::Black); // Clear the matrix
}
// Function to map 2D (x, y) coordinates to 1D LED array index
int XY(int x, int y) {
if (y % 2 == 0) {
// For even rows, return index directly
return y * MATRIX_WIDTH + x;
} else {
// For odd rows, map x to reverse direction
return y * MATRIX_WIDTH + (MATRIX_WIDTH - 1 - x);
}
}
// Function to draw a line using Bresenham's line algorithm
void draw_line(int x1, int y1, int x2, int y2) {
// Iterators, counters required by algorithm
int x, y, dx, dy, dx1, dy1, px, py, xe, ye, i;
// Calculate line deltas
dx = x2 - x1;
dy = y2 - y1;
// Create a positive copy of deltas (makes iterating easier)
dx1 = abs(dx);
dy1 = abs(dy);
// Calculate error intervals for both axis
px = 2 * dy1 - dx1;
py = 2 * dx1 - dy1;
// The line is X-axis dominant
if (dy1 <= dx1) {
// Line is drawn left to right
if (dx >= 0) {
x = x1; y = y1; xe = x2;
} else { // Line is drawn right to left (swap ends)
x = x2; y = y2; xe = x1;
}
pixel(x, y); // Draw first pixel
// Rasterize the line
for (i = 0; x < xe; i++) {
x = x + 1;
// Deal with octants...
if (px < 0) {
px = px + 2 * dy1;
} else {
if ((dx < 0 && dy < 0) || (dx > 0 && dy > 0)) {
y = y + 1;
} else {
y = y - 1;
}
px = px + 2 * (dy1 - dx1);
}
// Draw pixel from line span at
// currently rasterized position
pixel(x, y);
}
} else { // The line is Y-axis dominant
// Line is drawn bottom to top
if (dy >= 0) {
x = x1; y = y1; ye = y2;
} else { // Line is drawn top to bottom
x = x2; y = y2; ye = y1;
}
pixel(x, y); // Draw first pixel
// Rasterize the line
for (i = 0; y < ye; i++) {
y = y + 1;
// Deal with octants...
if (py <= 0) {
py = py + 2 * dx1;
} else {
if ((dx < 0 && dy < 0) || (dx > 0 && dy > 0)) {
x = x + 1;
} else {
x = x - 1;
}
py = py + 2 * (dx1 - dy1);
}
// Draw pixel from line span at
// currently rasterized position
pixel(x, y);
}
}
}
// Function to perform an action with each pixel
void pixel(int x, int y) {
// Map 2D (x, y) coordinates to 1D LED array index
int index = XY(x, y);
// Do something with the pixel at index
leds[index] = CRGB::White;
}