Implement a driver for ISSI IS31FL3743A
This PR adds support for a IS31FL3743A LED matrix driver as a proposition for more energy efficient 'bling' on ZMK powered devices. Hopefully it can also be leveraged in implementing per-key RGB support (#554).
I took some notes from #555 and made the driver conform to Zephyr's led_strip API.
The driver works by setting all configuration and white-balance scaling registers on init, and only uses PWM registers for manipulating LED brightness and color.
My test configuration for reference:
@i2c0 {
is31fl3743a@20 {
compatible = "issi,is31fl3743a";
label = "IS31FL3743A_0";
reg = <0x20>;
riset = <68>;
sw-setting = <0x01>;
led-max-current = <5>;
cs-order = [01 02 00 04 05 03 07 06 08 0A 0B 09 0D 0E 0C 10 11 0F];
sdb-gpios = <&gpio1 13 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>;
sync = <0x11>;
};
};
Food for thought: I wonder what the best way would be for handling software/hardware shutdown to preserve energy when LEDs aren't in use. Zephyr's led_strip API seems to leave this question open.
Food for thought: I wonder what the best way would be for handling software/hardware shutdown to preserve energy when LEDs aren't in use. Zephyr's
led_stripAPI seems to leave this question open.
Zephyr has a power management API that we can implement for each driver: https://docs.zephyrproject.org/latest/reference/power_management/index.html#device-model-with-power-management-support
For example, putting this driver into DEVICE_PM_LOW_POWER_STATE could toggle the SDB pin. Then we could start doing things like putting LED drivers into low power state when all the LED colors are (0,0,0) or when the keyboard is idle.
Are there plans to ever merge these LED matrix drivers into main? Would be very useful. 😄
I think this driver needs some updates to fit with newer Zephyr, but I'm currently designing some hardware that will use one of these, so I will eventually be trying to get this through review.
One example of a change that should likely be made is to copy the color-mapping property from Zephyr's ws2812 driver, which gives the order of the color channels. If, for example, if you set color-mapping = <LED_COLOR_ID_RED>, then you should get a strip of up to 351 single color LEDs (controlled by the red channel of each pixel) instead of 117 RGB LEDs.
It might also be useful to be able to reorder the sw pins? Maybe that could be handled by a higher level transform similar to the kscan matrix transform though.
Just going to note here that this is somewhat outdated and I think my implementation for IS31FL3741 (#886) is much better in that regard. I was meaning to update this to whatever we do there eventually, but haven't gotten much feedback on it so far either.
Regarding the stuff you mentioned @joelspadin, the IS31FL3741 implementation does indeed allow to map individual channels, not just entire RGB LEDs like so:
map = <
RGB(SW(1), CS(1), CS(2), CS(3))
RGB(SW(7), CS(3), CS(2), CS(1))
>;
These macros expand to three integers which are the register numbers on the ISSI chip for the three LEDs. The driver does assume every three subsequent positions are the red, green and blue channels for a single RGB LED, and I think the macros go a long way of making that manageable so you can assign them in whatever order makes sense for your project.
If you're not using RGB LEDs this still allows for full control over the order, but of course update_rgb will produce unexpected results in that case.
The RGB() macro works both ways, as in you can also do RGB(CS(i), SW(j), SW(k), SW(l)) if you happen to be using common cathode LEDs. That said it probably still makes sense to have another macro that just takes a single pair if you're doing something really weird, and to make it easier to assign non-rgb LEDs.
Either way, we should probably continue that discussion in #886 when the time comes.
For posterity - I think you meant issue #866 and not #886.
(Disclaimer: opinion not related to being associated with ZMK project as accepting it isn't my decision to make anyway)
Would you consider making this a module so that it can be used independently from a ZMK branch? The structure looks like it would cleanly transfer. Here is an example of such a driver: https://github.com/petejohanson/cirque-input-module
I think that's a good idea. My intention is to eventually push this to Zephyr itself, but it seems like a module would be a nice intermediate solution for anyone interested in the meantime.
It's been a while since I last touched it so for now I'm trying to make sense of it again, but I should be able to set it up in the next few weeks.
This PR has been automatically marked as stale because it has not had activity in 10 months. It will be closed in 14 days if no further activity occurs. Feel free to give a status update or re-open when it has been rebased and is ready for review (again). Thanks!
This PR was closed because it had no activity for over 10 months. Feel free to give a status update or re-open when it has been rebased and is ready for review (again).
Just noting the implementation of this driver has been completed and is now available as a standard zephyr module.
@ice9js would it be possible for you to try and upstream the drivers for those chips to Zephyr? That would be the ideal end result, and definitely beats having them in-tree of ZMK or in a module.
@ice9js would it be possible for you to try and upstream the drivers for those chips to Zephyr?
Yeah, I did give it a look briefly and it's still my intention but I have no idea when I'll get around to it. The code will work as is, I just haven't gotten around to figuring out core Zephyr development for writing some tests or providing test instructions, which will probably be welcome. But maybe I can at least get a conversation going before EOY with what I already have.