You've already forked M5-ProductExampleCodes
mirror of
https://github.com/m5stack/M5-ProductExampleCodes.git
synced 2026-05-20 10:24:10 -07:00
177 lines
4.7 KiB
C
177 lines
4.7 KiB
C
/*!\file cQueue.c
|
|
** \author SMFSW
|
|
** \copyright BSD 3-Clause License (c) 2017-2019, SMFSW
|
|
** \brief Queue handling library (designed in c on STM32)
|
|
** \details Queue handling library (designed in c on STM32)
|
|
**/
|
|
/****************************************************************/
|
|
#include "port_x.h"
|
|
#ifdef ARDUINO8266_SERVER_CPP
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "cQueue.h"
|
|
/****************************************************************/
|
|
|
|
|
|
/*! \brief Increment index
|
|
** \details Increment buffer index \b pIdx rolling back to \b start when limit \b end is reached
|
|
** \param [in,out] pIdx - pointer to index value
|
|
** \param [in] end - counter upper limit value
|
|
** \param [in] start - counter lower limit value
|
|
**/
|
|
static inline void __attribute__((nonnull, always_inline)) inc_idx(uint16_t * const pIdx, const uint16_t end, const uint16_t start)
|
|
{
|
|
// (*pIdx)++;
|
|
// *pIdx %= end;
|
|
if (*pIdx < end - 1) { (*pIdx)++; }
|
|
else { *pIdx = start; }
|
|
}
|
|
|
|
/*! \brief Decrement index
|
|
** \details Decrement buffer index \b pIdx rolling back to \b end when limit \b start is reached
|
|
** \param [in,out] pIdx - pointer to index value
|
|
** \param [in] end - counter upper limit value
|
|
** \param [in] start - counter lower limit value
|
|
**/
|
|
static inline void __attribute__((nonnull, always_inline)) dec_idx(uint16_t * const pIdx, const uint16_t end, const uint16_t start)
|
|
{
|
|
if (*pIdx > start) { (*pIdx)--; }
|
|
else { *pIdx = end - 1; }
|
|
}
|
|
|
|
|
|
void * __attribute__((nonnull)) q_init(Queue_t * const q, const uint16_t size_rec, const uint16_t nb_recs, const QueueType type, const bool overwrite)
|
|
{
|
|
const uint32_t size = nb_recs * size_rec;
|
|
|
|
q->rec_nb = nb_recs;
|
|
q->rec_sz = size_rec;
|
|
q->impl = type;
|
|
q->ovw = overwrite;
|
|
|
|
q_kill(q); // Free existing data (if any)
|
|
q->queue = (uint8_t *) malloc(size);
|
|
|
|
if (q->queue == NULL) { q->queue_sz = 0; return 0; } // Return here if Queue not allocated
|
|
else { q->queue_sz = size; }
|
|
|
|
q->init = QUEUE_INITIALIZED;
|
|
q_flush(q);
|
|
|
|
return q->queue; // return NULL when queue not allocated (beside), Queue address otherwise
|
|
}
|
|
|
|
void __attribute__((nonnull)) q_kill(Queue_t * const q)
|
|
{
|
|
if (q->init == QUEUE_INITIALIZED) { free(q->queue); } // Free existing data (if already initialized)
|
|
q->init = 0;
|
|
}
|
|
|
|
|
|
void __attribute__((nonnull)) q_flush(Queue_t * const q)
|
|
{
|
|
q->in = 0;
|
|
q->out = 0;
|
|
q->cnt = 0;
|
|
}
|
|
|
|
|
|
bool __attribute__((nonnull)) q_push(Queue_t * const q, const void * const record)
|
|
{
|
|
if ((!q->ovw) && q_isFull(q)) { return false; }
|
|
|
|
uint8_t * const pStart = q->queue + (q->rec_sz * q->in);
|
|
memcpy(pStart, record, q->rec_sz);
|
|
|
|
inc_idx(&q->in, q->rec_nb, 0);
|
|
|
|
if (!q_isFull(q)) { q->cnt++; } // Increase records count
|
|
else if (q->ovw) // Queue is full and overwrite is allowed
|
|
{
|
|
if (q->impl == FIFO) { inc_idx(&q->out, q->rec_nb, 0); } // as oldest record is overwritten, increment out
|
|
//else if (q->impl == LIFO) {} // Nothing to do in this case
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool __attribute__((nonnull)) q_pop(Queue_t * const q, void * const record)
|
|
{
|
|
const uint8_t * pStart;
|
|
|
|
if (q_isEmpty(q)) { return false; } // No more records
|
|
|
|
if (q->impl == FIFO)
|
|
{
|
|
pStart = q->queue + (q->rec_sz * q->out);
|
|
inc_idx(&q->out, q->rec_nb, 0);
|
|
}
|
|
else if (q->impl == LIFO)
|
|
{
|
|
dec_idx(&q->in, q->rec_nb, 0);
|
|
pStart = q->queue + (q->rec_sz * q->in);
|
|
}
|
|
else { return false; }
|
|
|
|
memcpy(record, pStart, q->rec_sz);
|
|
q->cnt--; // Decrease records count
|
|
return true;
|
|
}
|
|
|
|
bool __attribute__((nonnull)) q_peek(const Queue_t * const q, void * const record)
|
|
{
|
|
const uint8_t * pStart;
|
|
|
|
if (q_isEmpty(q)) { return false; } // No more records
|
|
|
|
if (q->impl == FIFO)
|
|
{
|
|
pStart = q->queue + (q->rec_sz * q->out);
|
|
// No change on out var as it's just a peek
|
|
}
|
|
else if (q->impl == LIFO)
|
|
{
|
|
uint16_t rec = q->in; // Temporary var for peek (no change on q->in with dec_idx)
|
|
dec_idx(&rec, q->rec_nb, 0);
|
|
pStart = q->queue + (q->rec_sz * rec);
|
|
}
|
|
else { return false; }
|
|
|
|
memcpy(record, pStart, q->rec_sz);
|
|
return true;
|
|
}
|
|
|
|
bool __attribute__((nonnull)) q_drop(Queue_t * const q)
|
|
{
|
|
if (q_isEmpty(q)) { return false; } // No more records
|
|
|
|
if (q->impl == FIFO) { inc_idx(&q->out, q->rec_nb, 0); }
|
|
else if (q->impl == LIFO) { dec_idx(&q->in, q->rec_nb, 0); }
|
|
else { return false; }
|
|
|
|
q->cnt--; // Decrease records count
|
|
return true;
|
|
}
|
|
|
|
bool __attribute__((nonnull)) q_peekIdx(const Queue_t * const q, void * const record, const uint16_t idx)
|
|
{
|
|
const uint8_t * pStart;
|
|
|
|
if (idx + 1 > q_getCount(q)) { return false; } // Index out of range
|
|
|
|
if (q->impl == FIFO)
|
|
{
|
|
pStart = q->queue + (q->rec_sz * ((q->out + idx) % q->rec_nb));
|
|
}
|
|
else if (q->impl == LIFO)
|
|
{
|
|
pStart = q->queue + (q->rec_sz * idx);
|
|
}
|
|
else { return false; }
|
|
|
|
memcpy(record, pStart, q->rec_sz);
|
|
return true;
|
|
}
|
|
|
|
#endif |