Skip to content

Commit

Permalink
py/ringbuf: Add micropython.ringbuffer() interface for general use.
Browse files Browse the repository at this point in the history
Signed-off-by: Andrew Leech <[email protected]>
  • Loading branch information
pi-anl committed Aug 15, 2024
1 parent a20fca8 commit 5e95d35
Showing 1 changed file with 43 additions and 19 deletions.
62 changes: 43 additions & 19 deletions py/ringbuf.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,14 +75,8 @@ int ringbuf_put16(ringbuf_t *r, uint16_t v) {
return 0;
}

// Returns:
// 0: Success
// -1: Not enough data available to complete read (try again later)
// -2: Requested read is larger than buffer - will never succeed
int ringbuf_get_bytes(ringbuf_t *r, uint8_t *data, size_t data_len) {
if (ringbuf_avail(r) < data_len) {
return (r->size <= data_len) ? -2 : -1;
}
static inline __attribute__((always_inline)) void _ringbuf_memcpy_get(ringbuf_t *r, uint8_t *data, size_t data_len) {
// Ensure bounds / space checking is done before running this
uint32_t iget = r->iget;
uint32_t iget_a = (iget + data_len) % r->size;
uint8_t *datap = data;
Expand All @@ -94,17 +88,10 @@ int ringbuf_get_bytes(ringbuf_t *r, uint8_t *data, size_t data_len) {
}
memcpy(datap, r->buf + iget, iget_a - iget);
r->iget = iget_a;
return 0;
}

// Returns:
// 0: Success
// -1: Not enough free space available to complete write (try again later)
// -2: Requested write is larger than buffer - will never succeed
int ringbuf_put_bytes(ringbuf_t *r, const uint8_t *data, size_t data_len) {
if (ringbuf_free(r) < data_len) {
return (r->size <= data_len) ? -2 : -1;
}
static inline __attribute__((always_inline)) void _ringbuf_memcpy_put(ringbuf_t *r, const uint8_t *data, size_t data_len) {
// Ensure bounds / space checking is done before running this
uint32_t iput = r->iput;
uint32_t iput_a = (iput + data_len) % r->size;
const uint8_t *datap = data;
Expand All @@ -116,6 +103,29 @@ int ringbuf_put_bytes(ringbuf_t *r, const uint8_t *data, size_t data_len) {
}
memcpy(r->buf + iput, datap, iput_a - iput);
r->iput = iput_a;
}

// Returns:
// 0: Success
// -1: Not enough data available to complete read (try again later)
// -2: Requested read is larger than buffer - will never succeed
int ringbuf_get_bytes(ringbuf_t *r, uint8_t *data, size_t data_len) {
if (ringbuf_avail(r) < data_len) {
return (r->size <= data_len) ? -2 : -1;
}
_ringbuf_memcpy_get(r, data, data_len);
return 0;
}

// Returns:
// 0: Success
// -1: Not enough free space available to complete write (try again later)
// -2: Requested write is larger than buffer - will never succeed
int ringbuf_put_bytes(ringbuf_t *r, const uint8_t *data, size_t data_len) {
if (ringbuf_free(r) < data_len) {
return (r->size <= data_len) ? -2 : -1;
}
_ringbuf_memcpy_put(r, data, data_len);
return 0;
}

Expand All @@ -124,6 +134,10 @@ int ringbuf_put_bytes(ringbuf_t *r, const uint8_t *data, size_t data_len) {
#include "py/stream.h"
#include "py/mphal.h"

#ifndef MICROPY_PY_MICROPYTHON_RINGBUFFER_USE_MEMCPY
#define MICROPY_PY_MICROPYTHON_RINGBUFFER_USE_MEMCPY (1)
#endif

typedef struct _micropython_ringbuffer_obj_t {
mp_obj_base_t base;
ringbuf_t ringbuffer;
Expand Down Expand Up @@ -154,21 +168,31 @@ static mp_obj_t micropython_ringbuffer_make_new(const mp_obj_type_t *type, size_
static mp_uint_t micropython_ringbuffer_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) {
micropython_ringbuffer_obj_t *self = MP_OBJ_TO_PTR(self_in);
size = MIN(size, ringbuf_avail(&self->ringbuffer));
#if MICROPY_PY_MICROPYTHON_RINGBUFFER_USE_MEMCPY
_ringbuf_memcpy_get(&(self->ringbuffer), buf_in, size);
#else
uint8_t *dest = buf_in;
for (mp_uint_t i = 0; i < size; i++) {
const uint8_t *dest_end = dest + size;
while (dest < dest_end) {
*dest++ = ringbuf_get(&(self->ringbuffer));
}
#endif
*errcode = 0;
return size;
}

static mp_uint_t micropython_ringbuffer_write(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode) {
micropython_ringbuffer_obj_t *self = MP_OBJ_TO_PTR(self_in);
size = MIN(size, ringbuf_free(&self->ringbuffer));
#if MICROPY_PY_MICROPYTHON_RINGBUFFER_USE_MEMCPY
_ringbuf_memcpy_put(&(self->ringbuffer), buf_in, size);
#else
const uint8_t *src = buf_in;
for (mp_uint_t i = 0; i < size; i++) {
const uint8_t *src_end = src + size;
while (src < src_end) {
ringbuf_put(&(self->ringbuffer), *src++);
}
#endif
*errcode = 0;
return size;
}
Expand Down

0 comments on commit 5e95d35

Please sign in to comment.