-
-
Notifications
You must be signed in to change notification settings - Fork 40.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adds IS31FL3731 RGB Matrix Implementation #2910
Conversation
bool process_rgb_matrix(uint16_t keycode, keyrecord_t *record) { | ||
if ( record->event.pressed ) { | ||
uint8_t led[8], led_count; | ||
map_row_column_to_led(record->event.key.row, record->event.key.col, led, &led_count); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As far as I see, process_rgb_matrix
is called every cycle, right? In that case... this part here may become a bit costy, because map_row_column_to_led
iterates over all DRIVER_LED_TOTAL
LEDs, for each key pressed. When chording or typing fast, this may have a significant impact on performance.
Would it not be better to have an array that maps rows and columns directly to LED indexes? One could do it with two lookups then: one row,column to LED index, and a LED index to that led[8]
thing... That'd be a bit more RAM used, but O(1) lookups.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My original code had a map of row/col to LED indices... this can be a future optimization.
quantum/quantum.c
Outdated
// if (rgb_matrix_task_counter == 0) | ||
rgb_matrix_task(); | ||
// rgb_matrix_task_counter = ((rgb_matrix_task_counter + 1) % 5); | ||
rgb_matrix_update_pwm_buffers(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So... this gets called every cycle. rgb_matrix_update_pwm_buffers
will call IS31FL3731_update_pwm_buffers
and IS31FL3731_update_led_control_registers
, both of which are guarded by dirty flags, and only update when things changed.
If we have animations that change something every cycle, updating every cycle will be slow. I'm not familiar with the hardware here, but I imagine updating here isn't cheap either (otherwise the dirty flags would be pointless). In Kaleidoscope, we were facing a similar situation, where the keyboard felt laggy (see keyboardio/Kaleidoscope#113 and keyboardio/Kaleidoscope-LEDControl#1 for details and some numbers), so we changed the LED sync to happen only every 16msec or so (still netting us ~60fps), and the results were amazing.
Perhaps it would be worth considering doing something similar here, too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My original code would update backlight effect state using a 20Hz timer/interrupt, but then update the LED driver registers in between matrix scans.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I moved it from the timer to the task to avoid conflicts with other timers (1 & 3 are used by audio), and I had played around with the counter that is commented out there a little to lighten the load - I think something like that might work well.
The setup via I think we can switch to the existing I2C library already in QMK but recommend doing this in a future PR. It won't hurt to use TWIlib for now. The refactoring of my Zeal60/Zeal65 code into I have been too slow to refactor my implementation into a generic one, as it is highly coupled with the use of EEPROM memory to store the current effect, colors, brightness, user-defined keycodes, etc. so I can't complain too much about this implementation not being "complete" enough for me to refactor my Zeal60/Zeal65/M60-A implementation to use it wholesale. Can we come up with some compromise? Pull all this into master now, and I will refactor the Zeal60/Zeal65/M60-A implementation to use the low-level ISSI driver, but use its own higher-level RGB backlight effect/setting code. I can't see any other way, because to add more features to this RGB matrix driver would bloat it, especially with specific things that other keyboards wouldn't need. Yet I would also want to push something generalized for multiple keyboards to use, Zeal60, Zeal65, M60-A, the HS60 PCB by @yiancar, etc. Not sure how that can be done other than adding a 2nd, alternate I'm not against the idea of merging and even improving this RGB matrix driver with the same optimizations... willing to share how I pre-calculate polar co-ordinates for radial effects without floating-point math, etc. Possibly even generalizing out the effects and letting them be pulled into either implementation, perhaps even letting the keyboard implementation decide which effects it wants in its list.... But I think it's better to just commit this now, and let me refactor and commit an alternative one, and work towards refactoring/generalizing them while side-by-side, than spend more time trying to merge them together before committing anything. |
I had a look over this and I think I generally agree with @Wilba6582. I personally am a big supported of storing rgb settings in EEPROM in order to be able to be updated over hid (rawhid etc). I will implement the above commits on HS60 tonight and see how it goes. For my setup I had to use a non blocking version of TWIlib. This is mostly related to my I2C sometimes dropping a packet which hangs the system. For an application like this, missing a frame every 10 minutes is not a big deal and should not hang the system. Will come back when I have more results to offer! Thank you for this :) |
@Wilba6582 that sounds good - its own file alongside rgb_matrix.c would be fine, but I think a vendor/keyboard-specific one in the keyboard folder would work well too. I'd like to have the rgb_matrix extendable in a way (with a separate The polar cors optimisations are very welcome :) thanks for the feedback everybody! I'll merge this now. |
I am porting HS60 now to this to see how its going. I would personally suggest adding a warning for the polar effect as well due to high computational power |
@yiancar I didn't notice any major lag with that effect, but I'll add a note. I'm merging in the changes from master right now if you wanna wait a little bit. |
@jackhumbert oke making my config ready as we speak:) |
@yiancar should be good now :) merging! Failures are unrelated to changes |
endif | ||
ifeq ($(strip $(MCU)), at90usb1286) | ||
BOOTLOADER_SIZE = 8192 | ||
endif | ||
endif | ||
ifeq ($(strip $(BOOTLOADER)), halfkay) | ||
OPT_DEFS += -DBOOTLOADER_HALFKAY |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about the Teensy ++ 2.0?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That case is already handled here :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe, but the bootloader size is 1024, not 512 bytes. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, that code handles the address without that variable - mainly just defined there to avoid errors I think :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, okay.
Because I have seen issues with this in the past. ..... not that I can find them now. So clearly, it was in gitter
@jackhumbert Ok so I have to report the following:
I think that the most universal way to solve the update rate jerkiness is using a timer. |
* adds is31fl3731 rgb matrix implementation * fix build script for force pushes * allow bootloader size to be overwritten * adds planck light implementation * split led config into 2 arrays * idk * betterize register handling * update planck implementation * update planck * refine rgb interface * cleanup names, rgb matrix * start documentation * finish up docs * add effects list * clean-up merge * add RGB_MATRIX_SKIP_FRAMES * add support for at90usb1286 to bootloader options
* adds is31fl3731 rgb matrix implementation * fix build script for force pushes * allow bootloader size to be overwritten * adds planck light implementation * split led config into 2 arrays * idk * betterize register handling * update planck implementation * update planck * refine rgb interface * cleanup names, rgb matrix * start documentation * finish up docs * add effects list * clean-up merge * add RGB_MATRIX_SKIP_FRAMES * add support for at90usb1286 to bootloader options
This is a rework of #1857 and @Wilba6582's driver and RGB matrix implementation. Some points of improvement for future PRs (feel free to suggest):
Below are the docs being added as well:
RGB Matrix Lighting
There is basic support for addressable RGB matrix lighting with the I2C IS31FL3731 RGB controller. To enable it, add this to your
rules.mk
:Configure the hardware via your
config.h
:Currently only 2 drivers are supported, but it would be trivial to support all 4 combinations.
Define these arrays listing all the LEDs in your
<keyboard>.c
:Where
Cx_y
is the location of the LED in the matrix defined by the datasheet. Thedriver
is the index of the driver you defined in yourconfig.h
(0
or1
right now).The format for the matrix position used in this array is
{row | (col << 4)}
. Thex
is between (inclusive) 0-224, andy
is between (inclusive) 0-64. The easiest way to calculate these positions is:Where all variables are decimels/floats.
modifier
is a boolean, whether or not a certain key is considered a modifier (used in some effects).Keycodes
All RGB keycodes are currently shared with the RGBLIGHT system:
RGB Matrix Effects
These are the effects that are currently available:
Custom layer effects
Custom layer effects can be done by defining this in your
<keyboard>.c
:A similar function works in the keymap as
rgb_matrix_indicators_user
.Additional
config.h
OptionsEEPROM storage
The EEPROM for it is currently shared with the RGBLIGHT system (it's generally assumed only one RGB would be used at a time), but could be configured to use its own 32bit address with:
Where
16
is an unused index fromeeconfig.h
.Suspended state
To use the suspend feature, add this to your
<keyboard>.c
: