Skip to content

drivers: led_strip: ws2812_i2s: add full pre reset if active low #89203

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

jeppenodgaard
Copy link

Idle is high if output is active low.

Hold idle inactive for full reset duration before sending strip data to ensure initial data is not corrupted.

Idle is high if output is active low.

Hold idle inactive for full reset duration before sending strip data to
ensure initial data is not corrupted.

Signed-off-by: Jeppe Odgaard <jeppe.odgaard@prevas.dk>
@github-actions github-actions bot added the area: LED Label to identify LED subsystem label Apr 28, 2025
Copy link
Contributor

@simonguinot simonguinot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @jeppenodgaard,

IIUC the problem is that the I2S signal is active at idle state on your device, isn't it ? And then the signal edge when starting the data transmission is interpreted by the first LED controller of the strip as a bit ? Is that correct ?

Note that we had a lot of similar issues on the ws2812_spi driver with several SPI controllers / SoC. Most of them have been fixed at the SPI controller / SoC level.

And I'd like to have the same resolution here too.

@@ -83,7 +85,7 @@ static int ws2812_strip_update_rgb(const struct device *dev, struct led_rgb *pix
tx_buf = (uint32_t *)mem_block;

/* Add a pre-data reset, so the first pixel isn't skipped by the strip. */
for (uint16_t i = 0; i < WS2812_I2S_PRE_DELAY_WORDS; i++) {
for (uint16_t i = 0; i < pre_delay_words; i++) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So if the signal is active low, we are waiting for a reset delay before AND after sending data ?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. Otherwise the first LED is misbehaving.

@@ -69,6 +69,8 @@ static int ws2812_strip_update_rgb(const struct device *dev, struct led_rgb *pix
const uint8_t sym_one = cfg->nibble_one;
const uint8_t sym_zero = cfg->nibble_zero;
const uint32_t reset_word = cfg->active_low ? ~0 : 0;
const uint16_t pre_delay_words =
cfg->active_low ? cfg->reset_words : WS2812_I2S_PRE_DELAY_WORDS_DEFAULT;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that having a signal active at idle state can also happen with a signal active high.

Copy link
Author

@jeppenodgaard jeppenodgaard May 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True. It should probably have its own property (unless it can be resolved at a lower level as you suggest).

@jeppenodgaard
Copy link
Author

jeppenodgaard commented Apr 29, 2025

Hi @simonguinot

IIUC the problem is that the I2S signal is active at idle state on your device, isn't it ?

Yes. It is the samme issue with the SPI driver.

And then the signal edge when starting the data transmission is interpreted by the first LED controller of the strip as a bit ? Is that correct ?

Yes.

Note that we had a lot of similar issues on the ws2812_spi driver with several SPI controllers / SoC. Most of them have been fixed at the SPI controller / SoC level.

And I'd like to have the same resolution here too.

Since cpol and cpha normally only affects the clock signal I could not see how to keep the MOSI idle high.

How was it resolved at SPI/SoC level?

@jeppenodgaard
Copy link
Author

@simonguinot I am not sure how to fix this at at a lower level.
I can only find #38683 but I do not think this is identical to this issue..?

@simonguinot
Copy link
Contributor

@simonguinot I am not sure how to fix this at at a lower level. I can only find #38683 but I do not think this is identical to this issue..?

Yes it is pretty much the same kind of issue. The MOSI state when idle was OK, but became high when the SPI controller was preparing to transmit.

I also can find:

I know there are other cases, but I can't find them. Some have also been discussed on Discord.

What SoC are you using ? Did you check if the pin can be configured to invert the polarity for example ?

@jeppenodgaard
Copy link
Author

Thank you for the links @simonguinot! Those were exactly what I was looking for.

I read through the comments in #66664 and they make a lot of sense.

What SoC are you using ?

A am using an STM32H563.

Did you check if the pin can be configured to invert the polarity for example ?

I check the reference manual and I see no way to control the MOSI polarity and idle state.

I am not sure it makes sense to control MOSI idle level when using SPI for ordinary SPI communication because it is unused when CLK is inactive nor can I see anything specified in the "official SPI specification".

Therefore I do not think controlling the idle MOSI level makes sense nor accepted as a SPI binding property or similar.

Anyway AFAIK I am currently unable to use any drivers as I2S and SPI drivers requires specific idle state which I cannot achieve without driver changes.

@Casperdroid5
Copy link

Casperdroid5 commented Jun 12, 2025

Thank you for the links @simonguinot! Those were exactly what I was looking for.

I read through the comments in #66664 and they make a lot of sense.

What SoC are you using ?

A am using an STM32H563.

Did you check if the pin can be configured to invert the polarity for example ?

I check the reference manual and I see no way to control the MOSI polarity and idle state.

I am not sure it makes sense to control MOSI idle level when using SPI for ordinary SPI communication because it is unused when CLK is inactive nor can I see anything specified in the "official SPI specification".

Therefore I do not think controlling the idle MOSI level makes sense nor accepted as a SPI binding property or similar.

Anyway AFAIK I am currently unable to use any drivers as I2S and SPI drivers requires specific idle state which I cannot achieve without driver changes.

Ok, so how will users be able to use adressable leds with (for example) the NXP frdm K64 board? This one suffers from the same "idle high" complication with SPI and I2S.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: LED Label to identify LED subsystem
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants