You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
146 lines
3.5 KiB
146 lines
3.5 KiB
|
|
/** |
|
|
|
(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 |
|
|
|
|