Skip to content
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

I2S driver fixes for IRQs, protocol, factoring #4574

Merged
merged 5 commits into from
Mar 27, 2018

Conversation

earlephilhower
Copy link
Collaborator

All redundant ICACHE_FLASH_ATTR decorators were removed, we already do
this by default for all routines, anyway,

The actual ISR and its called function moved to to IRAM. Used to be in flash
due to the decorator, which could lead to crashes.

Fix the I2S on-the-wire protocol by enabling the transmit delay I2STMS because
I2S is supposed to send the MSB one clock after LRCLK toggles. This was
causing I2S to be twice as loud as intended in the best of cases, and causing
garbage/noise output when the MSB was set since data was effectively shifted.

Refactor the clock divider setting to be done in one function only, as there
is no reason to do the same complicated bit setting in two spots.

Fixes #4571 and a few other things I've been noticing.

@earlephilhower
Copy link
Collaborator Author

I've just got a USB 8-line logic analyzer and will try and capture the fixed I2S waveform tonight to verify the I2S protocol fix. Just comparing the output using the simple playback example in the issue sounds much better (since it is sending out full-swing samples it was clipping something fierce before), but if at all possible I'd like to catch the entire waveform since there's not really documentation on these registers.

@earlephilhower
Copy link
Collaborator Author

The change looks good. Here is the I2S sending 32767 (0x7FFF). The add'l bit shift is clearly visible and correct:
image

@earlephilhower
Copy link
Collaborator Author

For comparison, the wrong, unshifted version that's in the repo now:

image

All redundant ICACHE_FLASH_ATTR decorators were removed, we already do
this by default for all routines, anyway,

The actual ISR and its called function moved to to IRAM.  Used to be in flash
due to the decorator, which could lead to crashes.  Use ets_memset to mute
buffers in ISR.

Fix the I2S on-the-wire protocol by enabling the transmit delay I2STMS because
I2S is supposed to send the MSB one clock after LRCLK toggles.  This was
causing I2S to be twice as loud as intended in the best of cases, and causing
garbage/noise output when the MSB was set since data was effectively shifted.

Refactor the clock divider setting to be done in one function only, as there
is no reason to do the same complicated bit setting in two spots.
@devyte
Copy link
Collaborator

devyte commented Mar 27, 2018

My one comment is similar as I mentioned before: could you add comments for the register definitions/operations? At least for any changes/additions. If you're not sure, then suspicions are ok, as long as you explain that. Suspicions on how/why something works is better than no explanation at all!

Comment the known and unknown I2S register settings for posterity, using
the ESP32 guide as a basis.

Use optimistic_yield() instead of esp_wdt_disable/enable when busy
waiting in blocking writes to ensure we don't hog the CPU completely.

Move the constant IO pins to #defines for easier understanding.
@earlephilhower
Copy link
Collaborator Author

I've added what I can glean for the I2S block. Looks very close to the ESP32 so it's not so bad. SLC (DMA) is not so simple, but this patch isn't touching that.

@devyte devyte merged commit decfbdd into esp8266:master Mar 27, 2018
@earlephilhower earlephilhower deleted the i2s_bitdelay_fix branch March 28, 2018 01:44
@Simon-L
Copy link

Simon-L commented May 9, 2019

Hello!
I am using a PT8211 on ESP8266, it's got an unusual I2S format called Left Signifiant Bit Justified, or "japanese", as the datasheet puts it.
I think adding I2STMS to the I2S config broke using this DAC on ESP8266.
This comment from another excellent library of yours put me on the right track: earlephilhower/ESP8266Audio#100 (comment)

Temporary fix: change line 474 in https://github.com/esp8266/Arduino/blob/master/cores/esp8266/core_esp8266_i2s.cpp#L474 to:
I2SC |= I2SRF | I2SMR | I2SRMS | (div1 << I2SBD) | (div2 << I2SCD);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

I2S sending data 1 bit too early, results in clipping/garbage at high volumes
3 participants