Skip to content

fix(firmware): audio logic does not use all of the available buffers - #7689

Open
philmoz wants to merge 1 commit into
mainfrom
philmoz/fix-audio-buffering
Open

fix(firmware): audio logic does not use all of the available buffers#7689
philmoz wants to merge 1 commit into
mainfrom
philmoz/fix-audio-buffering

Conversation

@philmoz

@philmoz philmoz commented Aug 21, 2026

Copy link
Copy Markdown
Collaborator

The audio logic uses a circular buffer array to handle writing and reading data to the audio hardware.

The code would not allow all of the available buffers to be filled as it marked the buffers as full when there was still one empty buffer available.

A fix for this was applied to 2.11 in #7472 (plus #7685).

This PR applies to fixed logic for 2.12 and 3.0.
It also removes some unused code.

@philmoz philmoz added this to the 3.0 milestone Aug 21, 2026
@philmoz philmoz added bug 🪲 Something isn't working firmware General radio firmware issue, not colorlcd or B&W specific backport/2.12 To be backported to a 2.12 release also. labels Aug 21, 2026
@pfeerick

Copy link
Copy Markdown
Member

@richardclli Can you follow this one up, as you did mention in #7472 you were going to check main also ;)

@raphaelcoeffic

Copy link
Copy Markdown
Member

This PR reclaims the wasted slot by adding bufferFull, which is now written by both sides (audioPushBuffer sets it true, freeNextFilledBuffer sets it false).

I would strongly prefer an implementation that preserves the property of textbook SPSC: single writer for each variable.
Normally this is done by using free running counters and using power-of-2 buffer sizes to automatically reduce the index whenever needed.

The same technique can be used slightly generalised for any N by computing the modulo on index usage rather than only counter advances.

Something like this:

private:
  volatile uint8_t readIdx;   // free-running in [0, 2*AUDIO_BUFFER_COUNT)
  volatile uint8_t writeIdx;

  inline uint8_t nextIndex(uint8_t idx) const {
    return (idx >= 2 * AUDIO_BUFFER_COUNT - 1 ? 0 : idx + 1);
  }
  inline uint8_t slot(uint8_t idx) const {
    return idx >= AUDIO_BUFFER_COUNT ? idx - AUDIO_BUFFER_COUNT : idx;
  }
  uint8_t used() const {
    return writeIdx >= readIdx ? writeIdx - readIdx
                               : writeIdx + 2 * AUDIO_BUFFER_COUNT - readIdx;
  }
  bool full()  const { return used() == AUDIO_BUFFER_COUNT; }
  bool empty() const { return readIdx == writeIdx; }

public:
  AudioBuffer* getEmptyBuffer() const {
    return full() ? nullptr : &audioBuffers[slot(writeIdx)];
  }
  void audioPushBuffer() { writeIdx = nextIndex(writeIdx); }
  void freeNextFilledBuffer() { readIdx = nextIndex(readIdx); }
  const AudioBuffer* getNextFilledBuffer() {
    return empty() ? nullptr : &audioBuffers[slot(readIdx)];
  }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport/2.12 To be backported to a 2.12 release also. bug 🪲 Something isn't working firmware General radio firmware issue, not colorlcd or B&W specific

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants