diff options
| author | Dan Halbert <halbert@halwitz.org> | 2020-04-21 17:37:22 -0400 |
|---|---|---|
| committer | Dan Halbert <halbert@halwitz.org> | 2020-04-21 17:38:20 -0400 |
| commit | 38ec3bc57476c6fde45cd7d722370a5408fd8e10 (patch) | |
| tree | bea75dc24a3f94c14e564cb885af3fde87f9c033 /py | |
| parent | 1a71c8c51577cc7014d5db1c05084778c0b977e9 (diff) | |
further ringbuf cleanup
Diffstat (limited to 'py')
| -rw-r--r-- | py/py.mk | 1 | ||||
| -rw-r--r-- | py/ringbuf.c | 109 | ||||
| -rw-r--r-- | py/ringbuf.h | 82 |
3 files changed, 125 insertions, 67 deletions
@@ -257,6 +257,7 @@ PY_CORE_O_BASENAME = $(addprefix py/,\ repl.o \ smallint.o \ frozenmod.o \ + ringbuf.o \ ) PY_EXTMOD_O_BASENAME = \ diff --git a/py/ringbuf.c b/py/ringbuf.c new file mode 100644 index 000000000..70245461f --- /dev/null +++ b/py/ringbuf.c @@ -0,0 +1,109 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Paul Sokolovsky + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "ringbuf.h" + +// Dynamic initialization. This should be accessible from a root pointer. +// capacity is the number of bytes the ring buffer can hold. The actual +// size of the buffer is one greater than that, due to how the buffer +// handles empty and full statuses. +bool ringbuf_alloc(ringbuf_t *r, size_t capacity, bool long_lived) { + r->buf = gc_alloc(capacity + 1, false, long_lived); + r->size = capacity + 1; + r->iget = r->iput = 0; + return r->buf != NULL; +} + +size_t ringbuf_capacity(ringbuf_t *r) { + return r->size - 1; +} + +// Returns -1 if buffer is empty, else returns byte fetched. +int ringbuf_get(ringbuf_t *r) { + if (r->iget == r->iput) { + return -1; + } + uint8_t v = r->buf[r->iget++]; + if (r->iget >= r->size) { + r->iget = 0; + } + return v; +} + +// Returns -1 if no room in buffer, else returns 0. +int ringbuf_put(ringbuf_t *r, uint8_t v) { + uint32_t iput_new = r->iput + 1; + if (iput_new >= r->size) { + iput_new = 0; + } + if (iput_new == r->iget) { + return -1; + } + r->buf[r->iput] = v; + r->iput = iput_new; + return 0; +} + +void ringbuf_clear(ringbuf_t *r) { + r->iput = r->iget = 0; +} + +// Number of free slots that can be written. +size_t ringbuf_free(ringbuf_t *r) { + return (r->size + r->iget - r->iput - 1) % r->size; +} + +// Number of bytes available to read. +size_t ringbuf_avail(ringbuf_t *r) { + return (r->size + r->iput - r->iget) % r->size; +} + +// If the ring buffer fills up, not all bytes will be written. +// Returns how many bytes were successfully written. +size_t ringbuf_put_n(ringbuf_t* r, uint8_t* buf, size_t bufsize) +{ + for(size_t i=0; i < bufsize; i++) { + if ( ringbuf_put(r, buf[i]) < 0 ) { + // If ringbuf is full, give up and return how many bytes + // we wrote so far. + return i; + } + } + return bufsize; +} + +// Returns how many bytes were fetched. +size_t ringbuf_get_n(ringbuf_t* r, uint8_t* buf, size_t bufsize) +{ + for(size_t i=0; i < bufsize; i++) { + int b = ringbuf_get(r); + if (b < 0) { + return i; + } + buf[i] = b; + } + return bufsize; +} diff --git a/py/ringbuf.h b/py/ringbuf.h index 7fc35d266..1e01091ab 100644 --- a/py/ringbuf.h +++ b/py/ringbuf.h @@ -32,78 +32,26 @@ typedef struct _ringbuf_t { uint8_t *buf; - uint16_t size; - uint16_t iget; - uint16_t iput; + // Allocated size; capacity is one less. Don't reference this directly. + uint32_t size; + uint32_t iget; + uint32_t iput; } ringbuf_t; +// Note that the capacity of the buffer is N-1! + // Static initialization: // byte buf_array[N]; // ringbuf_t buf = {buf_array, sizeof(buf_array)}; -// Dynamic initialization. This creates root pointer! -#define ringbuf_alloc(r, sz, long_lived) \ -{ \ - (r)->buf = gc_alloc(sz, false, long_lived); \ - (r)->size = sz; \ - (r)->iget = (r)->iput = 0; \ -} - -static inline int ringbuf_get(ringbuf_t *r) { - if (r->iget == r->iput) { - return -1; - } - uint8_t v = r->buf[r->iget++]; - if (r->iget >= r->size) { - r->iget = 0; - } - return v; -} - -static inline int ringbuf_put(ringbuf_t *r, uint8_t v) { - uint32_t iput_new = r->iput + 1; - if (iput_new >= r->size) { - iput_new = 0; - } - if (iput_new == r->iget) { - return -1; - } - r->buf[r->iput] = v; - r->iput = iput_new; - return 0; -} - -static inline uint16_t ringbuf_count(ringbuf_t *r) -{ - volatile int count = r->iput - r->iget; - if ( count < 0 ) { - count += r->size; - } - - return (uint16_t) count; -} - -static inline void ringbuf_clear(ringbuf_t *r) -{ - r->iput = r->iget = 0; -} - -// will overwrite old data -static inline void ringbuf_put_n(ringbuf_t* r, uint8_t* buf, uint8_t bufsize) -{ - for(uint8_t i=0; i < bufsize; i++) { - if ( ringbuf_put(r, buf[i]) < 0 ) { - // if full overwrite old data - (void) ringbuf_get(r); - ringbuf_put(r, buf[i]); - } - } -} +bool ringbuf_alloc(ringbuf_t *r, size_t capacity, bool long_lived); +size_t ringbuf_capacity(ringbuf_t *r); +int ringbuf_get(ringbuf_t *r); +int ringbuf_put(ringbuf_t *r, uint8_t v); +void ringbuf_clear(ringbuf_t *r); +size_t ringbuf_free(ringbuf_t *r); +size_t ringbuf_avail(ringbuf_t *r); +size_t ringbuf_put_n(ringbuf_t* r, uint8_t* buf, size_t bufsize); +size_t ringbuf_get_n(ringbuf_t* r, uint8_t* buf, size_t bufsize); -static inline void ringbuf_get_n(ringbuf_t* r, uint8_t* buf, uint8_t bufsize) -{ - for(uint8_t i=0; i < bufsize; i++) { - buf[i] = ringbuf_get(r); - } -} #endif // MICROPY_INCLUDED_PY_RINGBUF_H |
