So I'm using the FastLED library with Arduino (8-bit AVR) and I have my LEDs arranged in a regular 2D grid (serpentine pattern). To produce bitmap text and images I need a way converting 2D Cartesian coordinates to a physical LED (array index) address (0 for the first LED, 1 for the second LED...). I created a function display_addr_get which does what I want, but because I'm using it so frequently I was wondering if it is optimal i.e. can I make it faster/simpler? I know there is currently no error checking to see if the row/col indexes are within the range of a byte, so if there is solution using saturated math (things like qadd8() that limit the sum to 255) that would be ideal.
My SRAM is practically full, so I can't implement a lookup table there (for mapping 2D coordinates to an array address), and I'm not sure how much of a speed sacrifice it will be to store the lookup table in the PROGMEM and constantly be reading data back from there.
The code below demonstrates what I'm trying to achieve by printing the array index value from top left to bottom right for every legal row and col value.
#include <stdio.h>
#define MATRIX_WIDTH 10
#define MATRIX_HEIGHT 8
typedef unsigned char uint8_t;
uint8_t display_addr_get(uint8_t row, uint8_t col);
uint8_t display_addr_get2(uint8_t row, uint8_t col);
int main()
{
printf("Starting Test:\n");
uint8_t col = 0;
uint8_t row = 0;
for (row = MATRIX_HEIGHT; row > 0; row--) {
for (col = 1; col <= MATRIX_WIDTH; col++) {
printf("|Index: %-3d|", display_addr_get(row, col));
}
printf("\n");
}
return 0;
}
// My custom function
uint8_t display_addr_get(uint8_t row, uint8_t col) {
uint8_t AddrLED = 0; // var size limits the strip length to 256 LEDs
if (row & 1) { // y (row) index is odd
AddrLED = -col + MATRIX_WIDTH * (MATRIX_HEIGHT - row + 1);
}
else { // y (row) index is even
AddrLED = col - 1 + MATRIX_WIDTH * (MATRIX_HEIGHT - row);
}
return AddrLED;
}
// Snippet from the FastLED lib (uses a different origin reference point)
uint8_t display_addr_get2(uint8_t y, uint8_t x) {
uint8_t i = 0;
if( y & 0x01) {
// Odd rows run backwards
uint8_t reverseX = (MATRIX_WIDTH - 1) - x;
i = (y * MATRIX_WIDTH) + reverseX;
} else {
// Even rows run forwards
i = (y * MATRIX_WIDTH) + x;
}
return i;
}
The program output (notice the serpentine pattern means indices are reversed on odd numbered rows, this is due to the physical connection of the LEDs so it can't be changed):
Starting Test:
|Index: 0 ||Index: 1 ||Index: 2 ||Index: 3 ||Index: 4 ||Index: 5 ||Index: 6 ||Index: 7 ||Index: 8 ||Index: 9 |
|Index: 19 ||Index: 18 ||Index: 17 ||Index: 16 ||Index: 15 ||Index: 14 ||Index: 13 ||Index: 12 ||Index: 11 ||Index: 10 |
|Index: 20 ||Index: 21 ||Index: 22 ||Index: 23 ||Index: 24 ||Index: 25 ||Index: 26 ||Index: 27 ||Index: 28 ||Index: 29 |
|Index: 39 ||Index: 38 ||Index: 37 ||Index: 36 ||Index: 35 ||Index: 34 ||Index: 33 ||Index: 32 ||Index: 31 ||Index: 30 |
|Index: 40 ||Index: 41 ||Index: 42 ||Index: 43 ||Index: 44 ||Index: 45 ||Index: 46 ||Index: 47 ||Index: 48 ||Index: 49 |
|Index: 59 ||Index: 58 ||Index: 57 ||Index: 56 ||Index: 55 ||Index: 54 ||Index: 53 ||Index: 52 ||Index: 51 ||Index: 50 |
|Index: 60 ||Index: 61 ||Index: 62 ||Index: 63 ||Index: 64 ||Index: 65 ||Index: 66 ||Index: 67 ||Index: 68 ||Index: 69 |
|Index: 79 ||Index: 78 ||Index: 77 ||Index: 76 ||Index: 75 ||Index: 74 ||Index: 73 ||Index: 72 ||Index: 71 ||Index: 70 |