Ardupilot2/libraries/AP_HAL_F4Light/hardware/hal/ring_buffer_pulse.h

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