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 LCD displays: Busy waiting for idle will not work like this. (AEGHB-291) #81

Closed
masterxq opened this issue May 6, 2020 · 1 comment

Comments

@masterxq
Copy link

masterxq commented May 6, 2020

This will cause problems:

    I2S[i2s_num]->conf.tx_start = 0;
    I2S[i2s_num]->conf.tx_reset = 1;
    I2S[i2s_num]->conf.tx_reset = 0;
    I2S[i2s_num]->conf.tx_fifo_reset = 1;
    I2S[i2s_num]->conf.tx_fifo_reset = 0;

    REG_WRITE(I2S_FIFO_ADD[i2s_num], (cmd << 8));
    I2S[i2s_num]->conf.tx_start = 1;
    while (!(I2S[i2s_num]->state.tx_idle)) {
        // vTaskDelay(20);
        ;
    }

The problem is, tx_idle will be set in the next tick of the i2s unit. Specially with lower I2S frequencies this will fail, because idle is not cleared when entering the the while loop.

A good solution would be:

    I2S[i2s_num]->conf.tx_start = 0;
    I2S[i2s_num]->conf.tx_reset = 1;
    I2S[i2s_num]->conf.tx_reset = 0;
    I2S[i2s_num]->conf.tx_fifo_reset = 1;
    I2S[i2s_num]->conf.tx_fifo_reset = 0;

    REG_WRITE(I2S_FIFO_ADD[i2s_num], (cmd << 8));
    I2S[i2s_num]->conf.tx_start = 1;
    //TODO: Wait to next I2S tick.
    while (!(I2S[i2s_num]->state.tx_idle)) {
        // vTaskDelay(20);
        ;
    }

Sadly i don't know how to wait for the next I2S tick, so in order to get it work i did like this:

    I2S[i2s_num]->conf.tx_start = 0;
    I2S[i2s_num]->conf.tx_reset = 1;
    I2S[i2s_num]->conf.tx_reset = 0;
    I2S[i2s_num]->conf.tx_fifo_reset = 1;
    I2S[i2s_num]->conf.tx_fifo_reset = 0;

    REG_WRITE(I2S_FIFO_ADD[i2s_num], (cmd << 8));
    I2S[i2s_num]->conf.tx_start = 1;
    for(uint32_t i = 0; i < WAIT_FOR_NOT_IDLE; i++)
    {
        if(!I2S[i2s_num]->state.tx_idle)
        {
            printf("got not idle:%d\n", i);
            break;
        }
    }
    while (!(I2S[i2s_num]->state.tx_idle)) {
        // vTaskDelay(20);
        ;
    }

The problem with my solution that if the I2S is working with fast frequencies, it often happen that the !idle state will not be detected, because it already is idle again when checking the state. So it lowers the speed of sending single data packages or commands.

For CLK_DIV > 8 it will mostly detect the !idle state. So my output looking depending on frequency like this:

got not idle:4
got not idle:2
got not idle:5
got not idle:7
got not idle:4
got not idle:5
got not idle:3
got not idle:5
got not idle:4

So the loop will will call break in 1-7 iterations.

For CLK_DIV 2, 4 or 8 i run often in the timeout.
But i still get:

got not idle:1
got not idle:1
got not idle:1
got not idle:1
got not idle:1

in some cases. I have never seen 0 here. Don't know why.
In every case this may not be ignored, because the I2S could be stopped before it did his work.
Maybe the solution could be to wait for an interrupt, but I'm not sure that this is faster then my loop timeout. Specially not if WAIT_FOR_NOT_IDLE (Max loop iterations) is set depending on the I2S frequency (clk divider and cpu speed).

@leeebo
Copy link
Collaborator

leeebo commented Jul 10, 2023

@masterxq Sorry for the late response, the I2S LCD driver in esp-iot-solution is archived now. Currently, we suggest using the latest esp-lcd for the LCD development.

@leeebo leeebo closed this as not planned Won't fix, can't repro, duplicate, stale Jul 10, 2023
@github-actions github-actions bot changed the title I2S LCD displays: Busy waiting for idle will not work like this. I2S LCD displays: Busy waiting for idle will not work like this. (AEGHB-291) Jul 10, 2023
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

No branches or pull requests

2 participants