#ifdef RGB_MATRIX_ENABLE
# include "arm_atsam_protocol.h"
# include "led.h"
# include "rgb_matrix.h"
# include <string.h>
# include <math.h>
# ifdef USE_MASSDROP_CONFIGURATOR
__attribute__((weak)) led_instruction_t led_instructions[] = {{.end = 1}};
static void md_rgb_matrix_config_override(int i);
# endif
void SERCOM1_0_Handler(void) {
if (SERCOM1->I2CM.INTFLAG.bit.ERROR) {
SERCOM1->I2CM.INTFLAG.reg = SERCOM_I2CM_INTENCLR_ERROR;
}
}
void DMAC_0_Handler(void) {
if (DMAC->Channel[0].CHINTFLAG.bit.TCMPL) {
DMAC->Channel[0].CHINTFLAG.reg = DMAC_CHINTENCLR_TCMPL;
i2c1_stop();
i2c_led_q_running = 0;
i2c_led_q_run();
return;
}
if (DMAC->Channel[0].CHINTFLAG.bit.TERR) {
DMAC->Channel[0].CHINTFLAG.reg = DMAC_CHINTENCLR_TERR;
}
}
issi3733_driver_t issidrv[ISSI3733_DRIVER_COUNT];
issi3733_led_t led_map[ISSI3733_LED_COUNT] = ISSI3733_LED_MAP;
RGB led_buffer[ISSI3733_LED_COUNT];
uint8_t gcr_desired;
uint8_t gcr_actual;
uint8_t gcr_actual_last;
# ifdef USE_MASSDROP_CONFIGURATOR
uint8_t gcr_breathe;
float breathe_mult;
float pomod;
# endif
# define ACT_GCR_NONE 0
# define ACT_GCR_INC 1
# define ACT_GCR_DEC 2
# define LED_GCR_STEP_AUTO 2
static uint8_t gcr_min_counter;
static uint8_t v_5v_cat_hit;
void gcr_compute(void) {
uint8_t action = ACT_GCR_NONE;
uint8_t gcr_use = gcr_desired;
# ifdef USE_MASSDROP_CONFIGURATOR
if (led_animation_breathing) {
gcr_use = gcr_breathe;
}
# endif
if (v_5v < V5_CAT) {
I2C3733_Control_Set(0);
v_5v_cat_hit = 20; gcr_actual = 0; usb_gcr_auto = 1; return;
} else if (v_5v_cat_hit > 1) {
v_5v_cat_hit--;
return;
} else if (v_5v_cat_hit == 1) {
I2C3733_Control_Set(1);
CDC_print("USB: WARNING: Re-enabling LED drivers\r\n");
v_5v_cat_hit = 0;
return;
}
if (usb_gcr_auto) {
if (v_5v_avg < V5_LOW)
action = ACT_GCR_DEC;
else if (v_5v_avg > V5_HIGH && gcr_actual < gcr_use)
action = ACT_GCR_INC;
else if (gcr_actual > gcr_use)
action = ACT_GCR_DEC;
} else {
if (gcr_actual < gcr_use)
action = ACT_GCR_INC;
else if (gcr_actual > gcr_use)
action = ACT_GCR_DEC;
}
if (action == ACT_GCR_NONE) {
gcr_min_counter = 0;
} else if (action == ACT_GCR_INC) {
if (LED_GCR_STEP_AUTO > LED_GCR_MAX - gcr_actual)
gcr_actual = LED_GCR_MAX; else
gcr_actual += LED_GCR_STEP_AUTO;
gcr_min_counter = 0;
} else if (action == ACT_GCR_DEC) {
if (LED_GCR_STEP_AUTO > gcr_actual) {
gcr_actual = 0;
if (usb_extra_state != USB_EXTRA_STATE_DISABLED_UNTIL_REPLUG) {
if (usb_extra_state == USB_EXTRA_STATE_ENABLED) {
gcr_min_counter++;
if (gcr_min_counter > 200) {
USB_ExtraSetState(USB_EXTRA_STATE_DISABLED_UNTIL_REPLUG);
usb_extra_manual = 0; if (usb_extra_manual)
CDC_print("USB: Disabling extra port until replug and manual mode toggle!\r\n");
else
CDC_print("USB: Disabling extra port until replug!\r\n");
}
}
}
} else {
gcr_actual -= LED_GCR_STEP_AUTO;
gcr_min_counter = 0;
# ifdef USE_MASSDROP_CONFIGURATOR
if (led_animation_breathing == 1) {
gcr_breathe = gcr_actual;
}
# endif
}
}
}
void issi3733_prepare_arrays(void) {
memset(issidrv, 0, sizeof(issi3733_driver_t) * ISSI3733_DRIVER_COUNT);
int i;
uint8_t addrs[ISSI3733_DRIVER_COUNT] = ISSI3773_DRIVER_ADDRESSES;
for (i = 0; i < ISSI3733_DRIVER_COUNT; i++) {
issidrv[i].addr = addrs[i];
}
for (uint8_t i = 0; i < ISSI3733_LED_COUNT; i++) {
led_map[i].rgb.g = issidrv[led_map[i].adr.drv - 1].pwm + 1 + ((led_map[i].adr.swg - 1) * 16 + (led_map[i].adr.cs - 1));
led_map[i].rgb.r = issidrv[led_map[i].adr.drv - 1].pwm + 1 + ((led_map[i].adr.swr - 1) * 16 + (led_map[i].adr.cs - 1));
led_map[i].rgb.b = issidrv[led_map[i].adr.drv - 1].pwm + 1 + ((led_map[i].adr.swb - 1) * 16 + (led_map[i].adr.cs - 1));
*(issidrv[led_map[i].adr.drv - 1].onoff + 1 + (led_map[i].adr.swg - 1) * 2 + (led_map[i].adr.cs - 1) / 8) |= (1 << ((led_map[i].adr.cs - 1) % 8));
*(issidrv[led_map[i].adr.drv - 1].onoff + 1 + (led_map[i].adr.swr - 1) * 2 + (led_map[i].adr.cs - 1) / 8) |= (1 << ((led_map[i].adr.cs - 1) % 8));
*(issidrv[led_map[i].adr.drv - 1].onoff + 1 + (led_map[i].adr.swb - 1) * 2 + (led_map[i].adr.cs - 1) / 8) |= (1 << ((led_map[i].adr.cs - 1) % 8));
}
}
void md_rgb_matrix_prepare(void) {
for (uint8_t i = 0; i < ISSI3733_LED_COUNT; i++) {
*led_map[i].rgb.r = 0;
*led_map[i].rgb.g = 0;
*led_map[i].rgb.b = 0;
}
}
static void led_set_one(int i, uint8_t r, uint8_t g, uint8_t b) {
if (i < ISSI3733_LED_COUNT) {
# ifdef USE_MASSDROP_CONFIGURATOR
md_rgb_matrix_config_override(i);
# else
led_buffer[i].r = r;
led_buffer[i].g = g;
led_buffer[i].b = b;
# endif
}
}
static void led_set_all(uint8_t r, uint8_t g, uint8_t b) {
for (uint8_t i = 0; i < ISSI3733_LED_COUNT; i++) {
led_set_one(i, r, g, b);
}
}
static void init(void) {
DBGC(DC_LED_MATRIX_INIT_BEGIN);
issi3733_prepare_arrays();
md_rgb_matrix_prepare();
gcr_min_counter = 0;
v_5v_cat_hit = 0;
DBGC(DC_LED_MATRIX_INIT_COMPLETE);
}
static void flush(void) {
# ifdef USE_MASSDROP_CONFIGURATOR
if (!led_enabled) {
return;
} # else
if (!sr_exp_data.bit.SDB_N) {
return;
} # endif
while (i2c_led_q_running) {
}
for (uint8_t i = 0; i < ISSI3733_LED_COUNT; i++) {
*led_map[i].rgb.r = led_buffer[i].r;
*led_map[i].rgb.g = led_buffer[i].g;
*led_map[i].rgb.b = led_buffer[i].b;
}
# ifdef USE_MASSDROP_CONFIGURATOR
breathe_mult = 1;
if (led_animation_breathing) {
led_animation_breathe_cur += BREATHE_STEP * breathe_dir;
if (led_animation_breathe_cur >= BREATHE_MAX_STEP)
breathe_dir = -1;
else if (led_animation_breathe_cur <= BREATHE_MIN_STEP)
breathe_dir = 1;
breathe_mult = 0.000015 * led_animation_breathe_cur * led_animation_breathe_cur;
if (breathe_mult > 1)
breathe_mult = 1;
else if (breathe_mult < 0)
breathe_mult = 0;
}
pomod = (float)((g_rgb_timer / 10) % (uint32_t)(1000.0f / led_animation_speed)) / 10.0f * led_animation_speed;
pomod *= 100.0f;
pomod = (uint32_t)pomod % 10000;
pomod /= 100.0f;
# endif
uint8_t drvid;
if (gcr_actual != gcr_actual_last) {
for (drvid = 0; drvid < ISSI3733_DRIVER_COUNT; drvid++) I2C_LED_Q_GCR(drvid); gcr_actual_last = gcr_actual;
}
for (drvid = 0; drvid < ISSI3733_DRIVER_COUNT; drvid++) I2C_LED_Q_PWM(drvid);
i2c_led_q_run();
}
void md_rgb_matrix_indicators(void) {
uint8_t kbled = keyboard_leds();
if (kbled && rgb_matrix_config.enable) {
for (uint8_t i = 0; i < ISSI3733_LED_COUNT; i++) {
if (
# if USB_LED_NUM_LOCK_SCANCODE != 255
(led_map[i].scan == USB_LED_NUM_LOCK_SCANCODE && (kbled & (1 << USB_LED_NUM_LOCK))) ||
# endif # if USB_LED_CAPS_LOCK_SCANCODE != 255
(led_map[i].scan == USB_LED_CAPS_LOCK_SCANCODE && (kbled & (1 << USB_LED_CAPS_LOCK))) ||
# endif # if USB_LED_SCROLL_LOCK_SCANCODE != 255
(led_map[i].scan == USB_LED_SCROLL_LOCK_SCANCODE && (kbled & (1 << USB_LED_SCROLL_LOCK))) ||
# endif # if USB_LED_COMPOSE_SCANCODE != 255
(led_map[i].scan == USB_LED_COMPOSE_SCANCODE && (kbled & (1 << USB_LED_COMPOSE))) ||
# endif # if USB_LED_KANA_SCANCODE != 255
(led_map[i].scan == USB_LED_KANA_SCANCODE && (kbled & (1 << USB_LED_KANA))) ||
# endif (0)) {
if (rgb_matrix_get_flags() & LED_FLAG_INDICATOR) {
led_buffer[i].r = 255 - led_buffer[i].r;
led_buffer[i].g = 255 - led_buffer[i].g;
led_buffer[i].b = 255 - led_buffer[i].b;
}
}
}
}
}
const rgb_matrix_driver_t rgb_matrix_driver = {.init = init, .flush = flush, .set_color = led_set_one, .set_color_all = led_set_all};
# ifdef USE_MASSDROP_CONFIGURATOR
uint8_t led_animation_orientation = 0;
uint8_t led_animation_direction = 0;
uint8_t led_animation_breathing = 0;
uint8_t led_animation_id = 0;
float led_animation_speed = 4.0f;
uint8_t led_lighting_mode = LED_MODE_NORMAL;
uint8_t led_enabled = 1;
uint8_t led_animation_breathe_cur = BREATHE_MIN_STEP;
uint8_t breathe_dir = 1;
static void led_run_pattern(led_setup_t* f, float* ro, float* go, float* bo, float pos) {
float po;
while (f->end != 1) {
po = pos;
if ((!led_animation_direction && f->ef & EF_SCR_R) || (led_animation_direction && (f->ef & EF_SCR_L))) {
po -= pomod;
if (po > 100)
po -= 100;
else if (po < 0)
po += 100;
} else if ((!led_animation_direction && f->ef & EF_SCR_L) || (led_animation_direction && (f->ef & EF_SCR_R))) {
po += pomod;
if (po > 100)
po -= 100;
else if (po < 0)
po += 100;
}
if (po < f->hs) {
f++;
continue;
}
if (po > f->he) {
f++;
continue;
}
po = (po - f->hs) / (f->he - f->hs);
if (f->ef & EF_OVER) {
*ro = (po * (f->re - f->rs)) + f->rs; *go = (po * (f->ge - f->gs)) + f->gs; *bo = (po * (f->be - f->bs)) + f->bs; } else if (f->ef & EF_SUBTRACT) {
*ro -= (po * (f->re - f->rs)) + f->rs; *go -= (po * (f->ge - f->gs)) + f->gs; *bo -= (po * (f->be - f->bs)) + f->bs; } else {
*ro += (po * (f->re - f->rs)) + f->rs; *go += (po * (f->ge - f->gs)) + f->gs; *bo += (po * (f->be - f->bs)) + f->bs; }
f++;
}
}
static void md_rgb_matrix_config_override(int i) {
float ro = 0;
float go = 0;
float bo = 0;
float po = (led_animation_orientation) ? (float)g_led_config.point[i].y / 64.f * 100 : (float)g_led_config.point[i].x / 224.f * 100;
uint8_t highest_active_layer = biton32(layer_state);
if (led_lighting_mode == LED_MODE_KEYS_ONLY && HAS_FLAGS(g_led_config.flags[i], LED_FLAG_UNDERGLOW)) {
} else if (led_lighting_mode == LED_MODE_NON_KEYS_ONLY && !HAS_FLAGS(g_led_config.flags[i], LED_FLAG_UNDERGLOW)) {
} else if (led_lighting_mode == LED_MODE_INDICATORS_ONLY) {
} else {
led_instruction_t* led_cur_instruction = led_instructions;
while (!led_cur_instruction->end) {
if ((led_cur_instruction->flags & LED_FLAG_MATCH_LAYER) && (led_cur_instruction->layer != highest_active_layer)) {
goto next_iter;
}
if (led_cur_instruction->flags & LED_FLAG_MATCH_ID) {
uint8_t modid = i / 32; uint32_t modidbit = 1 << (i % 32); uint32_t* bitfield = &led_cur_instruction->id0 + modid; if (~(*bitfield) & modidbit) { goto next_iter;
}
}
if (led_cur_instruction->flags & LED_FLAG_USE_RGB) {
ro = led_cur_instruction->r;
go = led_cur_instruction->g;
bo = led_cur_instruction->b;
} else if (led_cur_instruction->flags & LED_FLAG_USE_PATTERN) {
led_run_pattern(led_setups[led_cur_instruction->pattern_id], &ro, &go, &bo, po);
} else if (led_cur_instruction->flags & LED_FLAG_USE_ROTATE_PATTERN) {
led_run_pattern(led_setups[led_animation_id], &ro, &go, &bo, po);
}
next_iter:
led_cur_instruction++;
}
if (ro > 255)
ro = 255;
else if (ro < 0)
ro = 0;
if (go > 255)
go = 255;
else if (go < 0)
go = 0;
if (bo > 255)
bo = 255;
else if (bo < 0)
bo = 0;
if (led_animation_breathing) {
ro *= breathe_mult;
go *= breathe_mult;
bo *= breathe_mult;
}
}
led_buffer[i].r = (uint8_t)ro;
led_buffer[i].g = (uint8_t)go;
led_buffer[i].b = (uint8_t)bo;
}
# endif #endif