/*
 * rgbled.c
 *
 *  Created on: Oct 13, 2024
 *      Author: true
 */

#include <CH59x_common.h>

#include "rgbled.h"
#include "hsv2rgb.h"

#include "hw/aw20xxx.h"

#include "user_config.h"



#define AW20X_DIM           31  // initial global current setting

#define AW20X_COLS          4
#define AW20X_ROWS          9
#define AW20X_FADE_COUNT    (AW20X_ROWS * AW20X_COLS)



/*
static const uint16_t pwm_cie_256in_1024out[] = {
    0,    1,    1,    1,    2,    2,    3,    3,    4,    4,    4,    5,    5,    6,    6,    7,
    7,    8,    8,    8,    9,    9,   10,   10,   11,   11,   12,   12,   13,   13,   14,   15,
   15,   16,   17,   17,   18,   19,   19,   20,   21,   22,   22,   23,   24,   25,   26,   27,
   28,   29,   30,   31,   32,   33,   34,   35,   36,   37,   38,   39,   40,   42,   43,   44,
   45,   47,   48,   50,   51,   52,   54,   55,   57,   58,   60,   61,   63,   65,   66,   68,
   70,   71,   73,   75,   77,   79,   81,   83,   84,   86,   88,   90,   93,   95,   97,   99,
  101,  103,  106,  108,  110,  113,  115,  118,  120,  123,  125,  128,  130,  133,  136,  138,
  141,  144,  147,  149,  152,  155,  158,  161,  164,  167,  171,  174,  177,  180,  183,  187,
  190,  194,  197,  200,  204,  208,  211,  215,  218,  222,  226,  230,  234,  237,  241,  245,
  249,  254,  258,  262,  266,  270,  275,  279,  283,  288,  292,  297,  301,  306,  311,  315,
  320,  325,  330,  335,  340,  345,  350,  355,  360,  365,  370,  376,  381,  386,  392,  397,
  403,  408,  414,  420,  425,  431,  437,  443,  449,  455,  461,  467,  473,  480,  486,  492,
  499,  505,  512,  518,  525,  532,  538,  545,  552,  559,  566,  573,  580,  587,  594,  601,
  609,  616,  624,  631,  639,  646,  654,  662,  669,  677,  685,  693,  701,  709,  717,  726,
  734,  742,  751,  759,  768,  776,  785,  794,  802,  811,  820,  829,  838,  847,  857,  866,
  875,  885,  894,  903,  913,  923,  932,  942,  952,  962,  972,  982,  992, 1002, 1013, 1023,
};
*/

/*
 * there are various RGBLED arrangements to consider:
 * addressed order:   0 1 2 3 4 5    6  7  8  9 10 11
 * off by one:        1 2 3 4 5 6    7  8  9 10 11 12
 * connected order:   5 4 6 2 1 3   11 10 12  8  7  9
 * clockwise from TL: 6 3 5 2 4 1   10  7 11  8 12  9
 * these form the following conversion map:
 */

/*
// rgb output order:
static const uint8_t led_map[12] = {
    2,  5,  0,  3,  1,  4,
    7, 10,  6,  9,  8, 11
};
*/
/*
// program input order:
static const uint8_t led_map[12] = {
    4,  3,  5,  1,  0,  2,
    10, 9, 11,  7,  6,  8
};
*/

// manually figured out order because I can't math when sleep deprived:




AW20x awled;
static uint8_t awled_fade[AW20X_FADE_COUNT];

static uint8_t led_matrix_needs_update = 0;

struct color_rgb rgb_out[RGBLED_COUNT];
struct color_hsv hsv_out[RGBLED_COUNT];



const uint8_t rgb_str_unused[] = "Unused";
const uint8_t rgb_str_reserved[] = "Reserved";
const uint8_t rgb_str_increment[] = "Increment";
const uint8_t rgb_str_delay[] = "Delay";
const uint8_t rgb_str_brightness[] = "Brightness";



void rgbled_init()
{
    volatile uint32_t x;

    // make sure the hardware pin is on before calling.


    // wait a little while to ensure controller is awake
    x = GetSysClock() / 131072;
    while (x--);

    // clear fade
    memset(awled_fade, 0x00, sizeof(awled_fade));

    // set up RGBLED chip
    awled.fade = awled_fade;
    aw20x_init(&awled, AW20X_ADDR_GND << 1, AW20X_COLS, AW20X_ROWS, AW20X_IMAX_13_3MA);

    aw20x_set_dim_global(&awled, AW20X_DIM);
    aw20x_set_fade(&awled);
    aw20x_led_enable_range(&awled, 0, (AW20X_COLS * AW20X_MAX_ROWS) - 1);
}

void rgbled_flag_update()
{
    led_matrix_needs_update = 1;
}

void rgbled_send()
{
    int8_t i;
    uint8_t *fade = awled_fade;

    if (led_matrix_needs_update) {
        led_matrix_needs_update = 0;

        // leds off?
        if ((uconf.flags & UCONF_FLAGS_LEDS_DISABLE) || !(uconf.flags & UCONF_FLAGS_LEDS_ENABLE)) {
            // yes, clear the data
            memset(awled_fade, 0x00, sizeof(awled_fade));
        } else {
            for (i = 0; i < RGBLED_COUNT; i++) {
                hsv2rgb(hsv_out[i].h,
                        hsv_out[i].s,
                        hsv_out[i].v,
                        fade+0, fade+1, fade+2);
                fade += 3;
            }
        }

        aw20x_set_fade(&awled);
    }
}

void rgbled_runprog(uint8_t tick_ctr)
{
    uint8_t idx = uconf.ledprog_rgb_idx;

    // run program
    if (rgb_pgm[idx].prog) {
        // render
        rgb_pgm[idx].prog(uconf.ledprog_rgb_data[uconf.ledprog_rgb_idx], tick_ctr);

        // and for now, always force an update
        led_matrix_needs_update = 1;
    }
}

void rgbled_set_imax_normal()
{
    aw20x_set_imax(&awled, RGBLED_BRT_STANDARD);
}

void rgbled_set_imax_dim()
{
    aw20x_set_imax(&awled, RGBLED_BRT_DIMMED);
}
