blob: 91f96ef930f94c709ea5f53db016defe3f095b2a [file] [log] [blame]
/*
* Copyright 2017, Data61
* Commonwealth Scientific and Industrial Research Organisation (CSIRO)
* ABN 41 687 119 230.
*
* This software may be distributed and modified according to the terms of
* the BSD 2-Clause license. Note that NO WARRANTY is provided.
* See "LICENSE_BSD2.txt" for details.
*
* @TAG(DATA61_BSD)
*/
#include <assert.h>
#include <ringbuffer/ringbuffer.h>
#include <stdlib.h>
#include <sys/types.h>
struct ringbuffer {
volatile unsigned char *base;
size_t size;
off_t offset;
};
ringbuffer_t *rb_new(void *base, size_t size) {
ringbuffer_t *r = malloc(sizeof(*r));
if (r == NULL) {
return NULL;
}
r->base = (volatile unsigned char*)base;
r->size = size;
r->offset = 0;
return r;
}
void rb_transmit_byte(ringbuffer_t *r, unsigned char c) {
/* We can't send 0s. */
if (c == 0) {
return;
}
/* Write 0 into the following slot in the buffer. We always need a zero
* following the last piece of data to indicate to the receiver where to
* wait for more data.
*/
off_t next = (r->offset + 1) % r->size;
r->base[next] = 0;
/* Write the character and increment to the next slot for next time. */
r->base[r->offset] = c;
r->offset = next;
}
unsigned char rb_poll_byte(ringbuffer_t *r) {
if (r->base[r->offset] != 0) {
/* Read the data that's now available and increment to the next slot.
*/
unsigned char c = r->base[r->offset];
r->offset = (r->offset + 1) % r->size;
return c;
}
return 0;
}
unsigned char rb_receive_byte(ringbuffer_t *r) {
unsigned char c;
/* Busy wait for available data. */
while ((c = rb_poll_byte(r)) == 0);
return c;
}
void rb_destroy(ringbuffer_t *r) {
free(r);
}
size_t rb_transmit_string(ringbuffer_t *r, const char *s) {
size_t sent = 0;
while (*s != '\0') {
rb_transmit_byte(r, (unsigned char)*s);
sent++;
s++;
}
return sent;
}
size_t rb_receive_string(ringbuffer_t *r, char *s, size_t len) {
size_t received = 0;
while (len > 0) {
*s = (char)rb_receive_byte(r);
s++;
len--;
}
return received;
}
size_t rb_transmit(ringbuffer_t *r, const void *src, size_t len) {
size_t sent = 0;
unsigned char *s = (unsigned char*)src;
while (len > 0) {
rb_transmit_byte(r, *s);
s++;
len--;
}
return sent;
}
size_t rb_receive_data(ringbuffer_t *r, void *dest, size_t len) {
size_t received = 0;
unsigned char *d = (unsigned char*)dest;
while (len > 0) {
*d = rb_receive_byte(r);
d++;
len--;
}
return received;
}