147 lines
3.5 KiB
C
147 lines
3.5 KiB
C
|
|
/**
|
|
|
|
(c) 2017 night_ghost@ykoctpa.ru
|
|
|
|
based on: ring_buffer.h
|
|
|
|
* @file ring_buffer_pulse.h
|
|
* @brief Simple circular buffer for PEM input
|
|
*
|
|
* This implementation is not thread-safe. In particular, none of
|
|
* these functions is guaranteed re-entrant.
|
|
*/
|
|
|
|
#ifndef _PULSE_BUFFER_H_
|
|
#define _PULSE_BUFFER_H_
|
|
|
|
#include "hal_types.h"
|
|
#include "pwm_in.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/**
|
|
* Ring buffer type.
|
|
*
|
|
* The buffer is empty when head == tail.
|
|
*
|
|
* The buffer is full when the head is one byte in front of the tail,
|
|
* modulo buffer length.
|
|
*
|
|
* One element is left free to distinguish empty from full. */
|
|
typedef struct Pulse_buffer {
|
|
Pulse *buf; /**< Buffer items are stored into */
|
|
uint16_t head; /**< Index of the next item to remove */
|
|
volatile uint16_t tail; /**< Index where the next item will get inserted */
|
|
uint16_t size; /**< Buffer capacity minus one */
|
|
} pulse_buffer;
|
|
|
|
|
|
|
|
/**
|
|
* Initialise a ring buffer.
|
|
*
|
|
* @param pb Instance to initialise
|
|
*
|
|
* @param size Number of items in buf. The ring buffer will always
|
|
* leave one element unoccupied, so the maximum number of
|
|
* elements it can store will be size - 1. Thus, size
|
|
* must be at least 2.
|
|
*
|
|
* @param buf Buffer to store items into
|
|
*/
|
|
static inline void pb_init(volatile pulse_buffer *pb, uint16_t size, Pulse *buf) {
|
|
pb->head = 0;
|
|
pb->tail = 0;
|
|
pb->size = size - 1;
|
|
pb->buf = buf;
|
|
}
|
|
|
|
/**
|
|
* @brief Return the number of elements stored in the ring buffer.
|
|
* @param pb Buffer whose elements to count.
|
|
*/
|
|
static inline uint16_t pb_full_count(volatile pulse_buffer *pb) {
|
|
uint16_t h=pb->head;
|
|
uint16_t t=pb->tail;
|
|
int32_t size = t - h;
|
|
if (t < h) {
|
|
size += pb->size + 1;
|
|
}
|
|
return (uint16_t)size;
|
|
}
|
|
|
|
/**
|
|
* @brief Returns true if and only if the ring buffer is full.
|
|
* @param pb Buffer to test.
|
|
*/
|
|
static inline int pb_is_full(volatile pulse_buffer *pb) {
|
|
uint16_t t = pb->tail;
|
|
uint16_t h = pb->head;
|
|
return (t + 1 == h) || (t == pb->size && h == 0);
|
|
}
|
|
|
|
/**
|
|
* @brief Returns true if and only if the ring buffer is empty.
|
|
* @param pb Buffer to test.
|
|
*/
|
|
static inline int pb_is_empty(volatile pulse_buffer *pb) {
|
|
bool ret=pb->head == pb->tail;
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* Append element onto the end of a ring buffer.
|
|
* @param pb Buffer to append onto.
|
|
* @param element Value to append.
|
|
*/
|
|
static inline void pb_insert(volatile pulse_buffer *pb, Pulse element) {
|
|
uint16_t t = pb->tail;
|
|
pb->buf[t] = element;
|
|
pb->tail = (t == pb->size) ? 0 : t + 1;
|
|
}
|
|
|
|
/**
|
|
* @brief Remove and return the first item from a ring buffer.
|
|
* @param pb Buffer to remove from, must contain at least one element.
|
|
*/
|
|
static inline Pulse pb_remove(volatile pulse_buffer *pb) {
|
|
uint16_t h = pb->head;
|
|
Pulse p = pb->buf[h];
|
|
pb->head = (h == pb->size) ? 0 : h + 1;
|
|
return p;
|
|
}
|
|
|
|
/**
|
|
* @brief Attempt to insert an element into a ring buffer.
|
|
*
|
|
* @param pb Buffer to insert into.
|
|
* @param element Value to insert into pb.
|
|
* @sideeffect If pb is not full, appends element onto buffer.
|
|
* @return If element was appended, then 1; otherwise, 0. */
|
|
static inline int pb_safe_insert(volatile pulse_buffer *pb, Pulse element) {
|
|
if (pb_is_full(pb)) {
|
|
return 0;
|
|
}
|
|
pb_insert(pb, element);
|
|
return 1;
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief Discard all items from a ring buffer.
|
|
* @param pb Ring buffer to discard all items from.
|
|
*/
|
|
static inline void pb_reset(volatile pulse_buffer *pb) {
|
|
pb->tail = pb->head;
|
|
}
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif
|
|
|