Search code examples
c++arraysrgbled

Need help generating new 24 byte RGB lookup array from 12 byte, or a better way to code this


I am using 4 RGB leds as a indicator gauge for engine parameters. "My" code works by looking up 12 bytes from a 500 entry array, which the engine parameters are scaled to. 0 RPM = 1 blue LED, and 7000 RPM = 4 red LEDs. At 3500 RPM, two lower LEDs are green. I have config menus through a oled display and encoder to set these low/center/high values and save/load them from eeprom. In this way I can use one LED RGB array for displaying many operating parameters all scaled slightly differently.

I am making a new LED ring board using smaller LEDs so I can fit 8 leds in the space of 4 prior for better resolution. I would like to scale, or preferably find out how this array I have was generated so I can try different things. The current array is 500 12 bit entries, I would like to rescale or rewrite it for 1024 24 bit entries.

When I say "my" code, I mean I'm using a piece of some code I found on the internet here. I've gone through and rewrote or at the very least figured out what every bit is doing, but I still can't figure if this array was generated in excel somehow, or if it's hand coded.

http://www.msextra.com/forums/viewtopic.php?f=67&t=52539

I have made new hardware using a larger display and rewritten most of the code here...

https://github.com/deezums/TeensyMS

The relevant parts are in TeensyMS/Code/_171_LED_INIT.ino and TeensyMS/blob/master/Code/_371_LED_LOOP.ino

You can see how the LEDs work around 1:10 in this video https://www.youtube.com/watch?v=5pkusOi-U0U&feature=youtu.be

I am/plan on using a SAMD54, so I should have plenty of storage space.

struct ledval {
  byte r0;
  byte g0;
  byte b0;
  byte r1;
  byte g1;
  byte b1;
  byte r2;
  byte g2;
  byte b2;
  byte r3;
  byte g3;
  byte b3;
};

const ledval ledarray[] PROGMEM = {
//r0, g0, b0, r1, g1, b1, r2, g2, b2, r3, g3, b3
{0x0,0x5,0xFF,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}, //0
{0x0,0x6,0xFE,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}, //1
{0x0,0x7,0xFD,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}, //2
{0x0,0x8,0xFC,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}, //3
{0x0,0x9,0xFB,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}, //4
{0x0,0xA,0xFA,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}, //5
{0x0,0xB,0xF9,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}, //6
{0x0,0xC,0xF8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}, //7
{0x0,0xD,0xF7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}, //8
{0x0,0xE,0xF6,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}, //9
{0x0,0xF,0xF5,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}, //10
{0x0,0x10,0xF4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}, //11
{0x0,0x11,0xF3,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}, //12
{0x0,0x12,0xF2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}, //13
{0x0,0x13,0xF1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}, //14
{0x0,0x14,0xF0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}, //15
{0x0,0x15,0xEF,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}, //16
{0x0,0x16,0xEE,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}, //17
{0x0,0x17,0xED,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}, //18
{0x0,0x18,0xEC,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}, //19
{0x0,0x19,0xEB,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}, //20
{0x0,0x1A,0xEA,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}, //21
{0x0,0x1B,0xE9,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}, //22
{0x0,0x1C,0xE8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}, //23
{0x0,0x1D,0xE7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}, //24
{0x0,0x1E,0xE6,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}, //25
{0x0,0x1F,0xE5,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}, //26
{0x0,0x20,0xE4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}, //27
{0x0,0x21,0xE3,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}, //28
......
{0x0,0xEA,0x1A,0x0,0x31,0x5,0x0,0xA,0x1,0x0,0x0,0x0}, //229
{0x0,0xEB,0x19,0x0,0x31,0x5,0x0,0xA,0x1,0x0,0x0,0x0}, //230
{0x0,0xEC,0x18,0x0,0x32,0x5,0x0,0xA,0x1,0x0,0x0,0x0}, //231
{0x0,0xED,0x17,0x0,0x33,0x4,0x0,0xA,0x1,0x0,0x0,0x0}, //232
{0x0,0xEE,0x16,0x0,0x33,0x4,0x0,0xB,0x1,0x0,0x0,0x0}, //233
{0x0,0xEF,0x15,0x0,0x34,0x4,0x0,0xB,0x1,0x0,0x0,0x0}, //234
{0x0,0xF0,0x14,0x0,0x35,0x4,0x0,0xB,0x0,0x0,0x0,0x0}, //235
{0x0,0xF1,0x13,0x0,0x35,0x4,0x0,0xB,0x0,0x0,0x0,0x0}, //236
{0x0,0xF2,0x12,0x0,0x36,0x4,0x0,0xC,0x0,0x0,0x0,0x0}, //237
{0x0,0xF3,0x11,0x0,0x37,0x3,0x0,0xC,0x0,0x0,0x0,0x0}, //238
{0x0,0xF4,0x10,0x0,0x37,0x3,0x0,0xC,0x0,0x0,0x0,0x0}, //239
{0x0,0xF5,0xF,0x0,0x38,0x3,0x0,0xD,0x0,0x0,0x0,0x0}, //240
{0x0,0xF6,0xE,0x0,0x39,0x3,0x0,0xD,0x0,0x0,0x0,0x0}, //241
{0x0,0xF7,0xD,0x0,0x39,0x3,0x0,0xD,0x0,0x0,0x0,0x0}, //242
{0x0,0xF8,0xC,0x0,0x3A,0x2,0x0,0xD,0x0,0x0,0x0,0x0}, //243
{0x0,0xF9,0xB,0x0,0x3B,0x2,0x0,0xE,0x0,0x0,0x0,0x0}, //244
{0x0,0xFA,0xA,0x0,0x3C,0x2,0x0,0xE,0x0,0x0,0x0,0x0}, //245
{0x1,0xFB,0x9,0x0,0x3C,0x2,0x0,0xE,0x0,0x0,0x0,0x0}, //246
{0x2,0xFC,0x8,0x0,0x3D,0x1,0x0,0xF,0x0,0x0,0x0,0x0}, //247
{0x3,0xFD,0x7,0x0,0x3E,0x1,0x0,0xF,0x0,0x0,0x0,0x0}, //248
{0x4,0xFE,0x6,0x0,0x3E,0x1,0x0,0xF,0x0,0x0,0x0,0x0}, //249
{0x5,0xFF,0x5,0x1,0x3F,0x1,0x0,0xF,0x0,0x0,0x0,0x0}, //250
{0x6,0xFE,0x4,0x1,0x40,0x1,0x0,0x10,0x0,0x0,0x1,0x0}, //251
{0x7,0xFD,0x3,0x1,0x40,0x0,0x0,0x10,0x0,0x0,0x1,0x0}, //252
{0x8,0xFC,0x2,0x2,0x40,0x0,0x0,0x10,0x0,0x0,0x1,0x0}, //253
{0x9,0xFB,0x1,0x2,0x40,0x0,0x0,0x10,0x0,0x0,0x1,0x0}, //254
{0xA,0xFA,0x0,0x2,0x41,0x0,0x0,0x10,0x0,0x0,0x1,0x0}, //255
{0xB,0xF9,0x0,0x2,0x41,0x0,0x0,0x11,0x0,0x0,0x1,0x0}, //256
{0xC,0xF8,0x0,0x3,0x41,0x0,0x0,0x11,0x0,0x0,0x1,0x0}, //257
{0xD,0xF7,0x0,0x3,0x41,0x0,0x0,0x11,0x0,0x0,0x1,0x0}, //258
{0xE,0xF6,0x0,0x3,0x42,0x0,0x1,0x11,0x0,0x0,0x1,0x0}, //259
{0xF,0xF5,0x0,0x4,0x42,0x0,0x1,0x11,0x0,0x0,0x1,0x0}, //260
{0x10,0xF4,0x0,0x4,0x42,0x0,0x1,0x12,0x0,0x0,0x1,0x0}, //261
{0x11,0xF3,0x0,0x4,0x42,0x0,0x1,0x12,0x0,0x0,0x1,0x0}, //262
{0x12,0xF2,0x0,0x4,0x42,0x0,0x1,0x12,0x0,0x0,0x1,0x0}, //263
{0x13,0xF1,0x0,0x5,0x43,0x0,0x1,0x12,0x0,0x0,0x1,0x0}, //264
{0x14,0xF0,0x0,0x5,0x43,0x0,0x1,0x12,0x0,0x0,0x1,0x0}, //265
{0x15,0xEF,0x0,0x5,0x43,0x0,0x1,0x13,0x0,0x0,0x1,0x0}, //266
{0x16,0xEE,0x0,0x6,0x43,0x0,0x1,0x13,0x0,0x0,0x1,0x0}, //267
{0x17,0xED,0x0,0x6,0x44,0x0,0x1,0x13,0x0,0x0,0x1,0x0}, //268
.....
{0xF0,0x14,0x0,0xE1,0x12,0x0,0xD4,0x11,0x0,0xBC,0xF,0x0}, //485
{0xF1,0x13,0x0,0xE3,0x11,0x0,0xD7,0x10,0x0,0xC0,0xF,0x0}, //486
{0xF2,0x12,0x0,0xE5,0x11,0x0,0xD9,0x10,0x0,0xC4,0xE,0x0}, //487
{0xF3,0x11,0x0,0xE7,0x10,0x0,0xDC,0xF,0x0,0xC8,0xD,0x0}, //488
{0xF4,0x10,0x0,0xE9,0xF,0x0,0xDF,0xE,0x0,0xCC,0xD,0x0}, //489
{0xF5,0xF,0x0,0xEB,0xE,0x0,0xE1,0xD,0x0,0xD0,0xC,0x0}, //490
{0xF6,0xE,0x0,0xED,0xD,0x0,0xE4,0xD,0x0,0xD4,0xC,0x0}, //491
{0xF7,0xD,0x0,0xEF,0xC,0x0,0xE7,0xC,0x0,0xD9,0xB,0x0}, //492
{0xF8,0xC,0x0,0xF1,0xB,0x0,0xEA,0xB,0x0,0xDD,0xA,0x0}, //493
{0xF9,0xB,0x0,0xF3,0xA,0x0,0xED,0xA,0x0,0xE2,0x9,0x0}, //494
{0xFA,0xA,0x0,0xF5,0x9,0x0,0xF0,0x9,0x0,0xE6,0x9,0x0}, //495
{0xFB,0x9,0x0,0xF7,0x8,0x0,0xF3,0x8,0x0,0xEB,0x8,0x0}, //496
{0xFC,0x8,0x0,0xF8,0x7,0x0,0xF6,0x7,0x0,0xF0,0x7,0x0}, //497
{0xFD,0x7,0x0,0xFA,0x6,0x0,0xF8,0x6,0x0,0xF5,0x6,0x0}, //498
{0xFE,0x6,0x0,0xFC,0x5,0x0,0xFB,0x5,0x0,0xF9,0x5,0x0}, //499
{0xFF,0x5,0x0,0xFC,0x5,0x0,0xFB,0x5,0x0,0x28,0x8,0x0} //500
};

Entire LED array is here... https://github.com/deezums/TeensyMS/blob/master/Code/_171_LED_INIT.ino#L93

Thank you!


Solution

  • It might be best to implement a function that produces 4 RGB values in your code than to hard-code a lookup table. I believe that table was generated using a function like this anyways, so you can just save all of its outputs if you really need to have them pre-computed.

    // Generates an RGB color between Red and Green based on the given value (V).
    void LerpRGB(const uint8_t V, uint8_t& R, uint8_t& G, uint8_t& B)
    {
        R = V;
        G = 255 - V;
        B = 0;
    }
    
    // Takes a normalized value between 0 (min incl.) and 1024 (max excl.) and
    // an array of 12 bytes to store the output of the 4 RGB LED colors.
    void CalcLEDs(int value, uint8_t* ledValues)
    {
        // Set all 12 bytes to 0
        for (int i = 0; i < 12; i++)
        {
            ledValues[i] = 0x00;
        }
    
        // Set first LED to blue and exit if value is 0
        if (value == 0)
        {
            ledValues[2] = 0xFF;
            return;
        }
    
        // For 4 LEDs...
        for (int i = 0; i < 4; i++)
        {
            // Get some handy references to the RGB components
            uint8_t& r = ledValues[i * 3 + 0];
            uint8_t& g = ledValues[i * 3 + 1];
            uint8_t& b = ledValues[i * 3 + 2];
    
            // Calculate the domain for the current LED
            int lerpStart = 256 * i;
            int lerpStop = 256 * (i + 1);
    
            // Clamp the value if it is outside the domain, otherwise lerp between green and red
            if (value < lerpStart)
                g = 0xFF;
            else if (value >= lerpStop)
                r = 0xFF;
            else
                LerpRGB(value - lerpStart, r, g, b);
        }
    }
    

    Then you can use the function like this...

    uint8_t* ledVals = new uint8_t[12];
    CalcLEDs(your_operational_value, ledVals);
    // Do something with ledVals...
    delete[] ledVals
    

    The CalcLEDs function takes an input in the range of [0, 1023] since that simplifies the math. I also made sure that no floating point types were used here, since the CPU on your board has an optional FPU. You may also replace uint8_t with whatever byte type you are working with.