1

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 |  
Joel Spolsky
  • 33,372
  • 17
  • 89
  • 105
Mr. Anderson
  • 83
  • 1
  • 8
  • 3
    You want to convert 2d coords into a flat index? `x + y * width` – Neil Kirk Oct 10 '15 at 23:08
  • Yea, but I'd like the origin point to be the bottom left (no the top left) in my 2D array. Plus that flat packing only works if you're not using a serpentine pattern. I'll add the output of my code to try and show what I mean. – Mr. Anderson Oct 10 '15 at 23:19
  • Please carefully describe the required pattern as it's not obvious from your question. I don't think the particulars about your LED project etc is relevant to the algorithm. – Neil Kirk Oct 10 '15 at 23:21
  • Hopefully the output helps with understanding the arrangement pattern. So, for example, index 79 is (1, 1), index 0 is (1, 8), index 9 is (10, 8). I just mentioned the details about the LEDs to give an idea of the physical constrains on the problem. – Mr. Anderson Oct 10 '15 at 23:39
  • I can't see any issues. If it's working and you don't get any performance problem, I wouldn't worry about it. The only thing I can suggest is using `int` to store the values (at least in algorithms) might be slightly faster. – Neil Kirk Oct 10 '15 at 23:42
  • If you have some free memory, you can build an array to directly get the value but before try to optimise, be sure you have an issue, – Ôrel Oct 11 '15 at 09:08

0 Answers0