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] removes code forcing two slots in PCM Short Slot (IDFGH-14064) #14879

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

Conversation

gl-agnx
Copy link

@gl-agnx gl-agnx commented Nov 13, 2024

Description

Changes the i2s_hal and i2s_tdm configuration to not force two slots when only one slot is required.

This issue prevents a configuration of I2S_STD_SLOT_LEFT and I2S_SLOT_MODE_MONO.

If two slots are required, then I2S_STD_SLOT_BOTH could be specified by the use

This change was made because it was not possible to generate a 16-bit PCM output that's mono with only one slot, which is the case in some configurations

Explanation:
I2S_SLOT_MODE_MONO forces data to repeat across all slots. By definition, I2S_STD_SLOT_LEFT, I2S_STD_SLOT_RIGHT, or I2S_STD_SLOT_BOTH define whether we enable the left, right or both slots with 1 bit encoding.
However, requiring always at least 2 slots removes the ability to send out a single slot and makes I2S_STD_SLOT_BOTH useless.

The current code was enforcing the requirement of 2 slots at a low level for some reason in mono.

Related

None

Testing

Tested on ESP32-S3-DevKitC with a logic analyzer and can see properly that only a single slot is sent when configuring I2S_STD_SLOT_LEFT. Tested with I2S_STD_SLOT_BOTH and can see that both slots are being sent, as was the case before this cahnge.

Configuration example:

i2s_tdm_config_t tdm_cfg = {
        .clk_cfg  = I2S_TDM_CLK_DEFAULT_CONFIG(8000),
       
        .slot_cfg = I2S_TDM_PCM_SHORT_SLOT_DEFAULT_CONFIG(config->data_width, I2S_SLOT_MODE_MONO, I2S_STD_SLOT_LEFT),
        .gpio_cfg = {
            .mclk = config->mclk_pin,    // some codecs may require mclk signal, this example doesn't need it
            .bclk = config->bclk_pin,
            .ws   = config->ws_pin,
            .dout = config->dout_pin,
            .din  = config->din_pin, // In duplex mode, bind output and input to a same gpio can loopback internally
            .invert_flags = {
                .mclk_inv = config->mclk_pin_inv,
                .bclk_inv = config->bclk_pin_inv,
                .ws_inv   = config->ws_pin_inv,
            },
        },
    };

Checklist

Before submitting a Pull Request, please ensure the following:

  • 🚨 This PR does not introduce breaking changes.
  • All CI checks (GH Actions) pass.
  • Documentation is updated as needed.
  • Tests are updated or added as necessary.
  • Code is well-commented, especially in complex areas.
  • Git history is clean — commits are squashed to the minimum necessary.

@CLAassistant
Copy link

CLAassistant commented Nov 13, 2024

CLA assistant check
All committers have signed the CLA.

Copy link

github-actions bot commented Nov 13, 2024

Messages
📖 🎉 Good Job! All checks are passing!

👋 Hello gl-agnx, we appreciate your contribution to this project!


📘 Please review the project's Contributions Guide for key guidelines on code, documentation, testing, and more.

🖊️ Please also make sure you have read and signed the Contributor License Agreement for this project.

Click to see more instructions ...


This automated output is generated by the PR linter DangerJS, which checks if your Pull Request meets the project's requirements and helps you fix potential issues.

DangerJS is triggered with each push event to a Pull Request and modify the contents of this comment.

Please consider the following:
- Danger mainly focuses on the PR structure and formatting and can't understand the meaning behind your code or changes.
- Danger is not a substitute for human code reviews; it's still important to request a code review from your colleagues.
- To manually retry these Danger checks, please navigate to the Actions tab and re-run last Danger workflow.

Review and merge process you can expect ...


We do welcome contributions in the form of bug reports, feature requests and pull requests via this public GitHub repository.

This GitHub project is public mirror of our internal git repository

1. An internal issue has been created for the PR, we assign it to the relevant engineer.
2. They review the PR and either approve it or ask you for changes or clarifications.
3. Once the GitHub PR is approved, we synchronize it into our internal git repository.
4. In the internal git repository we do the final review, collect approvals from core owners and make sure all the automated tests are passing.
- At this point we may do some adjustments to the proposed change, or extend it by adding tests or documentation.
5. If the change is approved and passes the tests it is merged into the default branch.
5. On next sync from the internal git repository merged change will appear in this public GitHub repository.

Generated by 🚫 dangerJS against 3e0e2b1

@espressif-bot espressif-bot added the Status: Opened Issue is new label Nov 13, 2024
@github-actions github-actions bot changed the title [I2S] removes code forcing two slots in PCM Short Slot [I2S] removes code forcing two slots in PCM Short Slot (IDFGH-14064) Nov 13, 2024
@L-KAYA
Copy link
Collaborator

L-KAYA commented Nov 14, 2024

Thanks for looking into this issue! And you've caught the exact buggy line.

But removing the limitation directly will affect the Philips and MSB format, and might cause some breaking changes, so I suggest to add one more conditions so that we can only allow one slot in PCM SHORT format. (See suggestions as follows)

@@ -104,8 +104,7 @@ static esp_err_t i2s_tdm_set_slot(i2s_chan_handle_t handle, const i2s_tdm_slot_c
handle->active_slot = slot_cfg->slot_mode == I2S_SLOT_MODE_MONO ? 1 : __builtin_popcount(slot_cfg->slot_mask);
uint32_t max_slot_num = 32 - __builtin_clz(slot_cfg->slot_mask);
handle->total_slot = slot_cfg->total_slot < max_slot_num ? max_slot_num : slot_cfg->total_slot;
handle->total_slot = handle->total_slot < 2 ? 2 : handle->total_slot; // At least two slots in a frame
Copy link
Collaborator

Choose a reason for hiding this comment

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

handle->total_slot = (handle->total_slot < 2) && (slot_cfg->ws_width != 1) ? 2 : handle->total_slot;

Choose a reason for hiding this comment

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

Similar here with adding () around the conditions.

@@ -318,8 +318,7 @@ void i2s_hal_tdm_set_tx_slot(i2s_hal_context_t *hal, bool is_slave, const i2s_ha
uint32_t msk = slot_cfg->tdm.slot_mask;
/* Get the maximum slot number */
cnt = 32 - __builtin_clz(msk);
/* There should be at least 2 slots in total even for mono mode */
cnt = cnt < 2 ? 2 : cnt;
Copy link
Collaborator

Choose a reason for hiding this comment

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

cnt = (cnt < 2) && (slot_cfg->tdm.ws_width != 1) ? 2 : cnt;

Copy link

@atanisoft atanisoft Nov 14, 2024

Choose a reason for hiding this comment

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

I'd suggest:

cnt = ((cnt < 2) && (slot_cfg->tdm.ws_width != 1)) ? 2 : cnt;

as depending on the compiler optimization it may end up assigning zero to cnt if the first piece (cnt < 2) is evaluated first and shortcircuits the remaining operation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Opened Issue is new
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants