Skip to content

Ability to read_exact so that producer can fill up the rest of the buffer #96

@ninjasource

Description

@ninjasource

Hi @jamesmunns,

Awesome project! I am using BBQueue to shuffle audio data from a producer loop that is temporally unstable (some audio frames take longer to process than others) into a buffer and then reading that data at very critically timed intervals (inside an I2S interrupt) to pass it to a digital to analog converter. I've tried to distill the essence of this setup in the code below.

   // runs forever
    fn producer_task(producer: &mut Producer<'_, 1000>) {
        loop {
            match producer.grant_exact(100) {
                Ok(mut grant) => {
                    grant.to_commit(100);
                    // get audio bytes and copy them into write grant
                }
                Err(_) => {
                    // Input queue full, this is normal
                    // the i2s interrupt firing should free up space
                    cortex_m::asm::wfi();
                }
            }
        }
    }

    // fired by interrupt every 10 ms
    fn consumer_task(previous_grant: GrantR<'_, 1000>, consumer: &mut Consumer<'_, 1000>) {
        previous_grant.release(100);

        match consumer.read() {
            Ok(grant) => {
                long_running_dma_copy(grant);
            }
            Err(_) => {
                // no audio to play - play silence
            }
        }
    }

The long running consumer read operation holds the read grant for all the data available to read when it only really needs to read a small chunk here (100 bytes). This seems to put undue back-pressure on the producer resulting in the whole thing operating more like a turnstyle than a buffer.

My current solution to this problem is to use a double buffer and copy the data out of the BBQueue read grant and release the grant immediately. The double buffer is needed because there is only really enough time to switch pointers in this I2S interrupt handler or the audio will glitch.

My question is this, would it be possible to hold a read grant for only a small window of the data (say 100 bytes out of 1000) so that the producer can continue to write data to the queue elsewhere. Like a read_exact() function on the consumer. This may not be possible due to how read and write pointers work in bip buffers. However, if you think it is possible and worthwhile adding then I would like to attempt to implement it.

PS, I took a look at the framed stuff but that pesky frame length header messes up my alignment!

Metadata

Metadata

Assignees

No one assigned

    Labels

    docsDocumentation improvements

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions