85 lines
2.1 KiB
C
85 lines
2.1 KiB
C
/*
|
|
* Lock-free SPSC ring buffer for audio transport.
|
|
* Producer: WiFi ISR/promisc callback (writes 16-bit truncated samples).
|
|
* Consumer: UAC mic callback (reads arbitrary byte counts).
|
|
*
|
|
* Byte-granularity. Single writer, single reader, no locks.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <stdint.h>
|
|
#include <stddef.h>
|
|
#include <string.h>
|
|
#include "esp_attr.h"
|
|
|
|
#define RING_BUF_SIZE (48000 * 4 * 1) /* 1 second of 48kHz 16-bit stereo */
|
|
|
|
typedef struct {
|
|
uint8_t buf[RING_BUF_SIZE];
|
|
volatile uint32_t wr;
|
|
volatile uint32_t rd;
|
|
} ring_buf_t;
|
|
|
|
static inline void ring_buf_init(ring_buf_t *rb)
|
|
{
|
|
rb->wr = 0;
|
|
rb->rd = 0;
|
|
}
|
|
|
|
static inline uint32_t ring_buf_fill(const ring_buf_t *rb)
|
|
{
|
|
uint32_t w = rb->wr;
|
|
uint32_t r = rb->rd;
|
|
return (w >= r) ? (w - r) : (RING_BUF_SIZE - r + w);
|
|
}
|
|
|
|
static inline uint32_t ring_buf_free(const ring_buf_t *rb)
|
|
{
|
|
return RING_BUF_SIZE - 1 - ring_buf_fill(rb);
|
|
}
|
|
|
|
/* Write contiguous block. Returns bytes actually written. */
|
|
static inline size_t IRAM_ATTR ring_buf_write(ring_buf_t *rb, const uint8_t *data, size_t len)
|
|
{
|
|
uint32_t free = ring_buf_free(rb);
|
|
if (len > free) len = free;
|
|
if (len == 0) return 0;
|
|
|
|
uint32_t w = rb->wr;
|
|
uint32_t tail = RING_BUF_SIZE - w;
|
|
|
|
if (len <= tail) {
|
|
memcpy(rb->buf + w, data, len);
|
|
} else {
|
|
memcpy(rb->buf + w, data, tail);
|
|
memcpy(rb->buf, data + tail, len - tail);
|
|
}
|
|
|
|
__asm__ __volatile__("memw" ::: "memory");
|
|
rb->wr = (w + len) % RING_BUF_SIZE;
|
|
return len;
|
|
}
|
|
|
|
/* Read up to len bytes. Returns bytes actually read. */
|
|
static inline size_t ring_buf_read(ring_buf_t *rb, uint8_t *dst, size_t len)
|
|
{
|
|
uint32_t fill = ring_buf_fill(rb);
|
|
if (len > fill) len = fill;
|
|
if (len == 0) return 0;
|
|
|
|
uint32_t r = rb->rd;
|
|
uint32_t tail = RING_BUF_SIZE - r;
|
|
|
|
if (len <= tail) {
|
|
memcpy(dst, rb->buf + r, len);
|
|
} else {
|
|
memcpy(dst, rb->buf + r, tail);
|
|
memcpy(dst + tail, rb->buf, len - tail);
|
|
}
|
|
|
|
__asm__ __volatile__("memw" ::: "memory");
|
|
rb->rd = (r + len) % RING_BUF_SIZE;
|
|
return len;
|
|
}
|