#RGB Matrix indicator on encoder action?

81 messages ยท Page 1 of 1 (latest)

restive sage
#

I've come up with this, in order to change the color of the LED where my encoder is, based on a CCW/CW spin:

static bool encoder_active = false;
static bool encoder_clockwise = false;

#define ENCODER_LED_INDEX 65

bool process_record_user(uint16_t keycode, keyrecord_t *record) {
    if (last_encoder_activity_elapsed() < 500) {
        encoder_active = true;
    } else {
        encoder_active = false;
    }

    if (record->event.type == ENCODER_CW_EVENT) {
        encoder_clockwise = true;
    } else if (record->event.type == ENCODER_CCW_EVENT) {
        encoder_clockwise = false;
    }

    return true;
}

bool rgb_matrix_indicators_user(void) {
    if (encoder_active) {
        if (encoder_clockwise) {
            rgb_matrix_set_color(ENCODER_LED_INDEX, 0, 0xff, 0);
        } else {
            rgb_matrix_set_color(ENCODER_LED_INDEX, 0xff, 0, 0);
        }
    }

    return true;
}

I was able to figure out the index with some logging and investigation, but this just doesn't seem to be working at all... Anyone see what I'm missing?

jade pecan
#

not that it is the problem, but your encoder_active function variable is useless

#

just check if (last_encoder_activity_elapsed() < 500) inside rgb_matrix_indicators_user

restive sage
#

oh sure, that makes sense

#

uhh. i don't have a good feeling that'll fix it though ๐Ÿ˜ฎโ€๐Ÿ’จ

jade pecan
#

did you read the first part of the message?

#

where i say "not the problem but ... "

restive sage
#

yes lol

#

i was agreeing with you

jade pecan
#

have you tried returning false from your func?

#

that makes further logic (if any) running RGB indicators NOT to run its things

#

as in: maybe you are actually setting the color, but another piece of code is overwriting your change

viral storm
#

this is a split board, yes?
if the led index is not on the same side that is plugged in, then this probably won't work

restive sage
#

it is a split board yes... led is index 65, and is on the slave side

jade pecan
#

each half can only affect its own LEDs, and processing of user input (ie: process_record_user) only happens on master half (ie: the one with USB plugged)

#

you would need to sync some info across halves

restive sage
#

ahh ok, I did wonder about this: #help message

#

but rgb_matrix_indicators_advanced_user runs on both sides?

jade pecan
#

yup

restive sage
#

ok, will report back. luckily, I'm already familiar with custom data sync ๐Ÿ˜…

restive sage
#

that compiles, but my slave doesn't work when I flash it lol

jade pecan
#

Code is muuuch more complex than needed

#

First thing, im pretty sure the "last activity" timers already get sync'ed by QMK

dusty ruin
#

yup

#
#define SPLIT_ACTIVITY_ENABLE
#

but would need custom data syncing to syng the encoder activity

restive sage
#

thanks all!

jade pecan
# restive sage finally got it!

took a quick look at code, you are no longer using encoder_led_t as far as i can tell (sending a bool directly over the wire), if so, i'd remove the typedef to avoid confusion

#

and the whole state_changed logic is very hard to read, could simply:

        const bool previous = g_encoder_clockwise;
        if (record->event.type == ENCODER_CW_EVENT) {
            g_encoder_clockwise = true;
        } else if (record->event.type == ENCODER_CCW_EVENT) {
            g_encoder_clockwise = false;
        }

        if (g_encoder_clockwise != previous) {
            transaction_rpc_send(ENCODER_LED_SYNC, sizeof(bool), &g_encoder_clockwise);
        }
restive sage
#

ohh, don't need to bother with doing it in housekeeping then?

jade pecan
#

Wtdym

restive sage
#

I thought I had to wait until the housekeeping task to send the sync packet, but you've demonstrated that I can do it in process_record_user just fine

restive sage
jade pecan
#

As a rule of thumb, every thing happens on both sides except for processing user input

#

But just put your question in a help channel if unsure

restive sage
restive sage
#

I had to figure out the LED index at the position on the matrix where my encoder is "manually"... how can I figure this out programmatically? I'm attempting to convert this to work similarly to Encoder Map, just with colors instead of keycodes ๐Ÿ‘€

dusty ruin
#

there isn't a foolproof way to do so

#

if you know the matrix position for the switch on the encoder, you can use that to check the row and column in the g_led_config. But you may not know that, or it may not be exposed in a way that is readable to modules.

#

In theory, the layout section in the json should be mapping it, bu tthat's not always the case.

restive sage
#

which, again, works for me because I went and found them, but I basically want to write a function that can take in encoder index and give me led index

#

fwiw I got 65, not from the layouts section, but from the rgb_matrix section ([9, 5])

restive sage
#

more accurately, if I know the index of the encoder (< NUM_ENCODERS), I need to find the row and column in the switch matrix that correspond to that position

warm charm
#

Encoder pins are unrelated to the LED position isn't it?

restive sage
#

yeah, probably?

warm charm
#

which index maps to an/each encoder
If QMK does not have the index or physical location, it will need to be supplied with that information to determine it programmatically.

restive sage
#

right, now that makes sense... ok I have a path forward here ๐Ÿ‘Œ

restive sage
#

Ok, so I've made a bunch of refactors to how I'm managing this functionality, and am super close to being able to slap a "release" sticker on the module, but am running into something with timers

#

I've added the ability to specify LED color on a per-layer, per-encoder, per-direction basis, similar to Encoder Map, and supporting (see: requiring lol) elpekenin/indicators colors, like this:

const uint8_t encoder_leds[NUM_ENCODERS] = { 65 };
const color_t PROGMEM encoder_ledmap[][NUM_ENCODERS][NUM_DIRECTIONS] = {
    [0] = { { HUE(HUE_RED), HUE(HUE_GREEN) } },
    [1] = { { HUE(HUE_YELLOW), HUE(HUE_YELLOW) } },
    [2] = { { HUE(HUE_PURPLE), HUE(HUE_PURPLE) } },
    [3] = { { HUE(HUE_ORANGE), HUE(HUE_ORANGE) } },
    [4] = { { HUE(HUE_CYAN), HUE(HUE_CYAN) } },
};
#

this all works great, up until this commit, where I'm trying to give each encoder its own timing. I am pretty sure that the current implementation is going to act funky if there are two encoders, so I feel like I need to do that... but I don't have two encoders on my board for this to even be tested lol

#

what I do have is one encoder, but it's on my slave side, hence the attention to making sure this is handled properly with slave sync

#

with the changes from that commit, my LED simply stops lighting up altogether, which makes me suspicious that timers are not synced to the slave, only the various activity timestamps... is that right?

jade pecan
#

sync_timer_elapsed() exists

#

(unless user opts out of sync'ing it)

#

and FYI; you might want to use the 32 variant of timer APIs instead... using 16bits means the timer can count up to 2 ^ 16 - 1 milliseconds, which is not much (~65 seconds)

dusty ruin
#

the 32 bit one is something like 45 days, IIRC

jade pecan
#

(2 ^ 32 - 1) / (1000 * 60 * 60 * 24) to be precise ๐Ÿ˜›

restive sage
#

ok yep, fair enough! and thanks for letting me to the sync timer methods... not mentioned in the docs anywhere I can see ๐Ÿ˜‘ those fixed it immediately, two lines changed ๐Ÿ”ฅ

dusty ruin
#

well, not many people need to use them. They're mostly for stuff that actually needs syncing between halves, timing wise. Like animations. And even then ... it's a best effort, not a proper sync. "Current time + 2ms, and hope it's close enough"

restive sage
jade pecan
#

i should maybe move my code to elpekenin/colors ๐Ÿค”

#

and make both indicators and ledmap depend on it

restive sage
#

I was thinking of trying to do that myself and make some PRs to you ๐Ÿ‘€

jade pecan
#

Will spend weekend out of home, but can do it myself (or merge PR) when i get back

restive sage
#

we'll see if I get around to it tbh lol

restive sage
#

well I did lol I didn't refactor ledmap... it is a bit more involved, but seems like adding colors might make it significantly simpler ๐Ÿ‘€

jade pecan
#

Im on phone, wont bother doing a proper review on github

#

No need to include colors.h from indicators.c, it already includes indicators.h with in turn includes colors.h

#

And I'd also like to move the palette (u8 enum) to colors' module

#

But, of course, the getter to read one of those from ledmaps array would stay where it is

jade pecan
#

I just thought, though, that maybe i could extend color_t with a transparent variant, and use it (instead of current palette) for ledmap

#

Seems like a better plan, can do it after merging the PR

#

Wont touch the PC today, but will try and do both things tomorrow

restive sage
#

no problem, I will change up that import real quick, but yes I'd agree the "extras" like trans, none, white, and black would be good to have here

restive sage
#

those are definitely things I want to support in encoder_ledmap, at least trans and white

jade pecan
#

trans, none, white, and black

  • trans: i intended to add that already ๐Ÿค“
  • none: is already a thing, if you forget to assign a value for color_t::type(ie: default value of 0), you get that
  • white: assuming you mean a white value whose brightness is the current RGB matrix's setting - was in my mind too
  • black: does this need special-casing? RGB_COLOR(RGB_BLACK) should just work ๐Ÿค”