feat: PS修改为演示验证版本

This commit is contained in:
2024-11-07 11:39:25 +08:00
parent 7dc4f160b6
commit 25c9dd91a3
92 changed files with 35864 additions and 0 deletions
@@ -0,0 +1,134 @@
/*****************************************************************************/
/**
* @file circ_queue.c
* @author FanHao ([email protected])
* @brief A simple circular FIFO bounded queue
* @version 0.1
* @date 2023-02-23
* @note Forked from https://github.com/chrismerck/rpa_queue.git
* @copyright Copyright(c) 2024 Beijing Institute of Technology.\n
* Lab of Communication and Network
*
******************************************************************************/
/**
* @addtogroup Utility
* @{
*/
/**
* @addtogroup CircularQueue
* @{
*/
#include "circ_queue.h"
#include "common.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
inline bool isCircQueueFull(CIRC_QUEUE *queue)
{
ASSERT(queue != NULL);
return ((queue)->nelts == (queue)->bounds);
}
inline bool isCircQueueEmpty(CIRC_QUEUE *queue)
{
ASSERT(queue != NULL);
return ((queue)->nelts == 0);
}
void CircQueueFree(CIRC_QUEUE *queue)
{
ASSERT(queue != NULL);
if (queue->data)
free(queue->data);
free(queue);
}
/**
* @brief Initialize the CIRC_QUEUE.
*/
bool CircQueueCreate(CIRC_QUEUE **q, uint32_t queueCapacity)
{
ASSERT(q != NULL);
CIRC_QUEUE *queue;
queue = malloc(sizeof(CIRC_QUEUE));
if (!queue)
{
return false;
}
*q = queue;
memset(queue, 0, sizeof(CIRC_QUEUE));
/* Set all the data in the queue to NULL */
queue->data = malloc(queueCapacity * sizeof(void *));
if (queue->data == NULL)
{
goto error;
}
queue->bounds = queueCapacity;
queue->nelts = 0;
queue->in = 0;
queue->out = 0;
return true;
error:
free(queue);
return false;
}
/**
* @brief Push new data onto the queue.
*/
bool CircQueuePush(CIRC_QUEUE *queue, void *data)
{
ASSERT(queue != NULL);
if (isCircQueueFull(queue))
{
return false;
}
queue->data[queue->in] = data;
queue->in++;
if (queue->in >= queue->bounds)
{
queue->in -= queue->bounds;
}
queue->nelts++;
return true;
}
/**
* @brief Return current number of element in queue.
*/
inline uint32_t CircQueueSize(CIRC_QUEUE *queue)
{
return queue->nelts;
}
/**
* @brief Retrieves the next item from the queue.
*/
bool CircQueuePop(CIRC_QUEUE *queue, void **data)
{
ASSERT(queue != NULL);
if (isCircQueueEmpty(queue))
{
return false;
}
*data = queue->data[queue->out];
queue->nelts--;
queue->out++;
if (queue->out >= queue->bounds)
{
queue->out -= queue->bounds;
}
return true;
}
/** @} CircularQueue*/
/** @} Utility*/
@@ -0,0 +1,353 @@
/*****************************************************************************/
/**
* @file clist.c
* @author FanHao ([email protected])
* @brief A basic list data structure
* @version 0.1
* @date 2023-02-23
* @note Forked from https://github.com/clibs/list
* @copyright Copyright(c) 2024 Beijing Institute of Technology.\n
* Lab of Communication and Network
*
******************************************************************************/
/**
* @addtogroup Utility
* @{
*/
/**
* @addtogroup cList
* @{
*/
#ifndef LIST_MALLOC
#define LIST_MALLOC malloc
#endif
#ifndef LIST_FREE
#define LIST_FREE free
#endif
#include <stdint.h>
#include "clist.h"
/**
* @brief a new clist_node_t. NULL on failure.
*/
clist_node_t *
clist_node_new(void *val)
{
clist_node_t *self;
if (!(self = LIST_MALLOC(sizeof(clist_node_t))))
return NULL;
self->prev = NULL;
self->next = NULL;
self->val = val;
return self;
}
/**
* @brief Allocate a new clist_t. NULL on failure.
*/
clist_t *
clist_new(void)
{
clist_t *self;
if (!(self = LIST_MALLOC(sizeof(clist_t))))
return NULL;
self->head = NULL;
self->tail = NULL;
self->free = NULL;
self->compare = NULL;
self->len = 0;
return self;
}
/**
* @brief Remove all the node in list.
* @param self: Pointer to the list
*/
void clist_clear(clist_t *self)
{
clist_node_t *next;
clist_node_t *curr = self->head;
while (curr != NULL)
{
next = curr->next;
if (self->free)
self->free(curr->val);
LIST_FREE(curr);
curr = next;
}
self->len = 0;
self->head = NULL;
}
/**
* @brief Free the list.
* @param self: Pointer to the list
*/
void clist_destroy(clist_t *self)
{
clist_clear(self);
LIST_FREE(self);
}
/**
* @brief Append the given node to the list and return the node, NULL on failure.
* @param self: Pointer to the list for popping node
* @param node: the node to push
*/
clist_node_t *
clist_rpush(clist_t *self, clist_node_t *node)
{
if (!node)
return NULL;
if (self->len)
{
node->prev = self->tail;
node->next = NULL;
self->tail->next = node;
self->tail = node;
}
else
{
self->head = self->tail = node;
node->prev = node->next = NULL;
}
++self->len;
return node;
}
/**
* @brief Return / detach the last node in the list, or NULL.
* @param self: Pointer to the list for popping node
*/
clist_node_t *
clist_rpop(clist_t *self)
{
if (!self->len)
return NULL;
clist_node_t *node = self->tail;
if (--self->len)
{
(self->tail = node->prev)->next = NULL;
}
else
{
self->tail = self->head = NULL;
}
node->next = node->prev = NULL;
return node;
}
/**
* @brief Return / detach the first node in the list, or NULL.
* @param self: Pointer to the list for popping node
*/
clist_node_t *
clist_lpop(clist_t *self)
{
if (!self->len)
return NULL;
clist_node_t *node = self->head;
if (--self->len)
{
(self->head = node->next)->prev = NULL;
}
else
{
self->head = self->tail = NULL;
}
node->next = node->prev = NULL;
return node;
}
/**
* @brief Prepend the given node to the list and return the node, NULL on failure.
* @param self: Pointer to the list for pushing node
* @param node: the node to push
*/
clist_node_t *
clist_lpush(clist_t *self, clist_node_t *node)
{
if (!node)
return NULL;
if (self->len)
{
node->next = self->head;
node->prev = NULL;
self->head->prev = node;
self->head = node;
}
else
{
self->head = self->tail = node;
node->prev = node->next = NULL;
}
++self->len;
return node;
}
/**
* @brief Return the node associated to val or NULL.
* @param self: Pointer to the list for finding given value
* @param val: Value to find
*/
clist_node_t *
clist_find(clist_t *self, void *val)
{
clist_iterator_t *it = clist_iterator_new(self, LIST_HEAD);
clist_node_t *node;
while ((node = clist_iterator_next(it)))
{
if (self->compare)
{
if (self->compare(val, node->val) == 0)
{
clist_iterator_destroy(it);
return node;
}
}
else
{
if (val == node->val)
{
clist_iterator_destroy(it);
return node;
}
}
}
clist_iterator_destroy(it);
return NULL;
}
/**
* @brief Return the node at the given index or NULL.
* @param self: Pointer to the list for finding given index
* @param index: the index of node in the list
*/
clist_node_t *
clist_at(clist_t *self, int index)
{
clist_direction_t direction = LIST_HEAD;
if (index < 0)
{
direction = LIST_TAIL;
index = ~index;
}
if ((unsigned)index < self->len)
{
clist_iterator_t *it = clist_iterator_new(self, direction);
clist_node_t *node = clist_iterator_next(it);
while (index--)
node = clist_iterator_next(it);
clist_iterator_destroy(it);
return node;
}
return NULL;
}
/**
* @brief Remove the given node from the list, freeing it and it's value.
* @param self: Pointer to the list to delete a node
* @param node: Pointer the node to be deleted
*/
void clist_remove(clist_t *self, clist_node_t *node)
{
node->prev
? (node->prev->next = node->next)
: (self->head = node->next);
node->next
? (node->next->prev = node->prev)
: (self->tail = node->prev);
if (self->free)
self->free(node->val);
LIST_FREE(node);
--self->len;
}
/**
* @brief Allocate a new clist_iterator_t. NULL on failure.\n
* Accepts a direction, which may be LIST_HEAD or LIST_TAIL.
*/
clist_iterator_t *
clist_iterator_new(clist_t *list, clist_direction_t direction)
{
clist_node_t *node = direction == LIST_HEAD
? list->head
: list->tail;
return clist_iterator_new_from_node(node, direction);
}
/**
* @brief Allocate a new clist_iterator_t with the given start
* node. NULL on failure.
*/
clist_iterator_t *
clist_iterator_new_from_node(clist_node_t *node, clist_direction_t direction)
{
clist_iterator_t *self;
if (!(self = LIST_MALLOC(sizeof(clist_iterator_t))))
return NULL;
self->next = node;
self->direction = direction;
return self;
}
/**
* @brief Return the next clist_node_t or NULL when no more
* nodes remain in the list.
*/
clist_node_t *
clist_iterator_next(clist_iterator_t *self)
{
clist_node_t *curr = self->next;
if (curr)
{
self->next = self->direction == LIST_HEAD
? curr->next
: curr->prev;
}
return curr;
}
/**
* @brief Free the list iterator.
*/
void clist_iterator_destroy(clist_iterator_t *self)
{
LIST_FREE(self);
self = NULL;
}
/** @} cList*/
/** @} Utility*/
@@ -0,0 +1,51 @@
/*****************************************************************************/
/**
* Description: Common functions
*
* Date: 2021-11-16 00:08
* LastEditors: Fan Hao
* LastEditTime: 2022-07-16 17:13
* Revisions: Rev 0.1
* History:
* [2022-07-16]: New branch for Dijian.
* [2021-11-16]: Initial version.
*
* Copyright(c) 2024 Beijing Institute of Technology.
* Lab of Communication and Networking
*
******************************************************************************/
/**
* @addtogroup COMMON_MACRO
* @{
*/
/***************************** Include Files *********************************/
#include "common.h"
#include "error.h"
#include "util.h"
/************************** Constant Definitions *****************************/
/***************** Macros (Inline Functions) Definitions *********************/
/**************************** Type Definitions *******************************/
/************************** Variable Definitions *****************************/
/*****************************************************************************/
/**
* @brief Throw an assert.
*
* @param file indicate the filename of the assertion
* @param line indicate which line the assertion occurs
*
* @return NONE.
*
******************************************************************************/
void AppAssert(const char *file, int line)
{
DBG_PRINT("in %s:%d [assert] .\n", file, line);
while (1)
;
}
/** @} */
@@ -0,0 +1,444 @@
/*****************************************************************************/
/**
* Description: CRC implementation file
*
* Author: Hao Fan
* Date: 2021-11-16 00:50
* LastEditors: Hao Fan
* LastEditTime: 2022-07-17 20:53
* Revisions: Rev 0.0
* History:
* [2022-07-17]: Add CRC16_0x8005 CRC8_0x31.
* [2022-01-06]: Initial verion (Basic CRC-16).
*
* Copyright(c) 2024 Beijing Institute of Technology.
* Lab of Communication and Networking
*
******************************************************************************/
/**
* @addtogroup Utility
* @{
*/
#include "util.h"
#include "error.h"
#ifdef __CRC_LSB
// CRC-16-CCITT G(X)=X16+X12+X5+1
// Reversed
static const uint16_t crc16_1021_lsb_lut[256] =
{
0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF,
0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7,
0x1081, 0x0108, 0x3393, 0x221A, 0x56A5, 0x472C, 0x75B7, 0x643E,
0x9CC9, 0x8D40, 0xBFDB, 0xAE52, 0xDAED, 0xCB64, 0xF9FF, 0xE876,
0x2102, 0x308B, 0x0210, 0x1399, 0x6726, 0x76AF, 0x4434, 0x55BD,
0xAD4A, 0xBCC3, 0x8E58, 0x9FD1, 0xEB6E, 0xFAE7, 0xC87C, 0xD9F5,
0x3183, 0x200A, 0x1291, 0x0318, 0x77A7, 0x662E, 0x54B5, 0x453C,
0xBDCB, 0xAC42, 0x9ED9, 0x8F50, 0xFBEF, 0xEA66, 0xD8FD, 0xC974,
0x4204, 0x538D, 0x6116, 0x709F, 0x0420, 0x15A9, 0x2732, 0x36BB,
0xCE4C, 0xDFC5, 0xED5E, 0xFCD7, 0x8868, 0x99E1, 0xAB7A, 0xBAF3,
0x5285, 0x430C, 0x7197, 0x601E, 0x14A1, 0x0528, 0x37B3, 0x263A,
0xDECD, 0xCF44, 0xFDDF, 0xEC56, 0x98E9, 0x8960, 0xBBFB, 0xAA72,
0x6306, 0x728F, 0x4014, 0x519D, 0x2522, 0x34AB, 0x0630, 0x17B9,
0xEF4E, 0xFEC7, 0xCC5C, 0xDDD5, 0xA96A, 0xB8E3, 0x8A78, 0x9BF1,
0x7387, 0x620E, 0x5095, 0x411C, 0x35A3, 0x242A, 0x16B1, 0x0738,
0xFFCF, 0xEE46, 0xDCDD, 0xCD54, 0xB9EB, 0xA862, 0x9AF9, 0x8B70,
0x8408, 0x9581, 0xA71A, 0xB693, 0xC22C, 0xD3A5, 0xE13E, 0xF0B7,
0x0840, 0x19C9, 0x2B52, 0x3ADB, 0x4E64, 0x5FED, 0x6D76, 0x7CFF,
0x9489, 0x8500, 0xB79B, 0xA612, 0xD2AD, 0xC324, 0xF1BF, 0xE036,
0x18C1, 0x0948, 0x3BD3, 0x2A5A, 0x5EE5, 0x4F6C, 0x7DF7, 0x6C7E,
0xA50A, 0xB483, 0x8618, 0x9791, 0xE32E, 0xF2A7, 0xC03C, 0xD1B5,
0x2942, 0x38CB, 0x0A50, 0x1BD9, 0x6F66, 0x7EEF, 0x4C74, 0x5DFD,
0xB58B, 0xA402, 0x9699, 0x8710, 0xF3AF, 0xE226, 0xD0BD, 0xC134,
0x39C3, 0x284A, 0x1AD1, 0x0B58, 0x7FE7, 0x6E6E, 0x5CF5, 0x4D7C,
0xC60C, 0xD785, 0xE51E, 0xF497, 0x8028, 0x91A1, 0xA33A, 0xB2B3,
0x4A44, 0x5BCD, 0x6956, 0x78DF, 0x0C60, 0x1DE9, 0x2F72, 0x3EFB,
0xD68D, 0xC704, 0xF59F, 0xE416, 0x90A9, 0x8120, 0xB3BB, 0xA232,
0x5AC5, 0x4B4C, 0x79D7, 0x685E, 0x1CE1, 0x0D68, 0x3FF3, 0x2E7A,
0xE70E, 0xF687, 0xC41C, 0xD595, 0xA12A, 0xB0A3, 0x8238, 0x93B1,
0x6B46, 0x7ACF, 0x4854, 0x59DD, 0x2D62, 0x3CEB, 0x0E70, 0x1FF9,
0xF78F, 0xE606, 0xD49D, 0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330,
0x7BC7, 0x6A4E, 0x58D5, 0x495C, 0x3DE3, 0x2C6A, 0x1EF1, 0x0F78
};
// CRC-16-MAXIM G(X)=X16+X15+X2+1
const uint16_t crc16_8005_lsb_lut[256] =
{
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
};
// CRC-8-MAXIM G(X)=X8+X5+X4+1
const uint8_t crc8_31_lsb_lut[256] =
{
0x00, 0x5E, 0xBC, 0xE2, 0x61, 0x3F, 0xDD, 0x83,
0xC2, 0x9C, 0x7E, 0x20, 0xA3, 0xFD, 0x1F, 0x41,
0x9D, 0xC3, 0x21, 0x7F, 0xFC, 0xA2, 0x40, 0x1E,
0x5F, 0x01, 0xE3, 0xBD, 0x3E, 0x60, 0x82, 0xDC,
0x23, 0x7D, 0x9F, 0xC1, 0x42, 0x1C, 0xFE, 0xA0,
0xE1, 0xBF, 0x5D, 0x03, 0x80, 0xDE, 0x3C, 0x62,
0xBE, 0xE0, 0x02, 0x5C, 0xDF, 0x81, 0x63, 0x3D,
0x7C, 0x22, 0xC0, 0x9E, 0x1D, 0x43, 0xA1, 0xFF,
0x46, 0x18, 0xFA, 0xA4, 0x27, 0x79, 0x9B, 0xC5,
0x84, 0xDA, 0x38, 0x66, 0xE5, 0xBB, 0x59, 0x07,
0xDB, 0x85, 0x67, 0x39, 0xBA, 0xE4, 0x06, 0x58,
0x19, 0x47, 0xA5, 0xFB, 0x78, 0x26, 0xC4, 0x9A,
0x65, 0x3B, 0xD9, 0x87, 0x04, 0x5A, 0xB8, 0xE6,
0xA7, 0xF9, 0x1B, 0x45, 0xC6, 0x98, 0x7A, 0x24,
0xF8, 0xA6, 0x44, 0x1A, 0x99, 0xC7, 0x25, 0x7B,
0x3A, 0x64, 0x86, 0xD8, 0x5B, 0x05, 0xE7, 0xB9,
0x8C, 0xD2, 0x30, 0x6E, 0xED, 0xB3, 0x51, 0x0F,
0x4E, 0x10, 0xF2, 0xAC, 0x2F, 0x71, 0x93, 0xCD,
0x11, 0x4F, 0xAD, 0xF3, 0x70, 0x2E, 0xCC, 0x92,
0xD3, 0x8D, 0x6F, 0x31, 0xB2, 0xEC, 0x0E, 0x50,
0xAF, 0xF1, 0x13, 0x4D, 0xCE, 0x90, 0x72, 0x2C,
0x6D, 0x33, 0xD1, 0x8F, 0x0C, 0x52, 0xB0, 0xEE,
0x32, 0x6C, 0x8E, 0xD0, 0x53, 0x0D, 0xEF, 0xB1,
0xF0, 0xAE, 0x4C, 0x12, 0x91, 0xCF, 0x2D, 0x73,
0xCA, 0x94, 0x76, 0x28, 0xAB, 0xF5, 0x17, 0x49,
0x08, 0x56, 0xB4, 0xEA, 0x69, 0x37, 0xD5, 0x8B,
0x57, 0x09, 0xEB, 0xB5, 0x36, 0x68, 0x8A, 0xD4,
0x95, 0xCB, 0x29, 0x77, 0xF4, 0xAA, 0x48, 0x16,
0xE9, 0xB7, 0x55, 0x0B, 0x88, 0xD6, 0x34, 0x6A,
0x2B, 0x75, 0x97, 0xC9, 0x4A, 0x14, 0xF6, 0xA8,
0x74, 0x2A, 0xC8, 0x96, 0x15, 0x4B, 0xA9, 0xF7,
0xB6, 0xE8, 0x0A, 0x54, 0xD7, 0x89, 0x6B, 0x35
};
#else
// CRC-16-CCITT G(X)=X16+X12+X5+1
static const uint16_t crc16_1021_msb_lut[256] =
{
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
};
// CRC-16-MAXIM G(X)=X16+X15+X2+1
const uint16_t crc16_8005_msb_lut[256] =
{
0x0000, 0x8005, 0x800F, 0x000A, 0x801B, 0x001E, 0x0014, 0x8011,
0x8033, 0x0036, 0x003C, 0x8039, 0x0028, 0x802D, 0x8027, 0x0022,
0x8063, 0x0066, 0x006C, 0x8069, 0x0078, 0x807D, 0x8077, 0x0072,
0x0050, 0x8055, 0x805F, 0x005A, 0x804B, 0x004E, 0x0044, 0x8041,
0x80C3, 0x00C6, 0x00CC, 0x80C9, 0x00D8, 0x80DD, 0x80D7, 0x00D2,
0x00F0, 0x80F5, 0x80FF, 0x00FA, 0x80EB, 0x00EE, 0x00E4, 0x80E1,
0x00A0, 0x80A5, 0x80AF, 0x00AA, 0x80BB, 0x00BE, 0x00B4, 0x80B1,
0x8093, 0x0096, 0x009C, 0x8099, 0x0088, 0x808D, 0x8087, 0x0082,
0x8183, 0x0186, 0x018C, 0x8189, 0x0198, 0x819D, 0x8197, 0x0192,
0x01B0, 0x81B5, 0x81BF, 0x01BA, 0x81AB, 0x01AE, 0x01A4, 0x81A1,
0x01E0, 0x81E5, 0x81EF, 0x01EA, 0x81FB, 0x01FE, 0x01F4, 0x81F1,
0x81D3, 0x01D6, 0x01DC, 0x81D9, 0x01C8, 0x81CD, 0x81C7, 0x01C2,
0x0140, 0x8145, 0x814F, 0x014A, 0x815B, 0x015E, 0x0154, 0x8151,
0x8173, 0x0176, 0x017C, 0x8179, 0x0168, 0x816D, 0x8167, 0x0162,
0x8123, 0x0126, 0x012C, 0x8129, 0x0138, 0x813D, 0x8137, 0x0132,
0x0110, 0x8115, 0x811F, 0x011A, 0x810B, 0x010E, 0x0104, 0x8101,
0x8303, 0x0306, 0x030C, 0x8309, 0x0318, 0x831D, 0x8317, 0x0312,
0x0330, 0x8335, 0x833F, 0x033A, 0x832B, 0x032E, 0x0324, 0x8321,
0x0360, 0x8365, 0x836F, 0x036A, 0x837B, 0x037E, 0x0374, 0x8371,
0x8353, 0x0356, 0x035C, 0x8359, 0x0348, 0x834D, 0x8347, 0x0342,
0x03C0, 0x83C5, 0x83CF, 0x03CA, 0x83DB, 0x03DE, 0x03D4, 0x83D1,
0x83F3, 0x03F6, 0x03FC, 0x83F9, 0x03E8, 0x83ED, 0x83E7, 0x03E2,
0x83A3, 0x03A6, 0x03AC, 0x83A9, 0x03B8, 0x83BD, 0x83B7, 0x03B2,
0x0390, 0x8395, 0x839F, 0x039A, 0x838B, 0x038E, 0x0384, 0x8381,
0x0280, 0x8285, 0x828F, 0x028A, 0x829B, 0x029E, 0x0294, 0x8291,
0x82B3, 0x02B6, 0x02BC, 0x82B9, 0x02A8, 0x82AD, 0x82A7, 0x02A2,
0x82E3, 0x02E6, 0x02EC, 0x82E9, 0x02F8, 0x82FD, 0x82F7, 0x02F2,
0x02D0, 0x82D5, 0x82DF, 0x02DA, 0x82CB, 0x02CE, 0x02C4, 0x82C1,
0x8243, 0x0246, 0x024C, 0x8249, 0x0258, 0x825D, 0x8257, 0x0252,
0x0270, 0x8275, 0x827F, 0x027A, 0x826B, 0x026E, 0x0264, 0x8261,
0x0220, 0x8225, 0x822F, 0x022A, 0x823B, 0x023E, 0x0234, 0x8231,
0x8213, 0x0216, 0x021C, 0x8219, 0x0208, 0x820D, 0x8207, 0x0202
};
// CRC-8-MAXIM G(X)=X8+X5+X4+1
const uint8_t crc8_31_msb_lut[256] =
{
0x00, 0x31, 0x62, 0x53, 0xC4, 0xF5, 0xA6, 0x97,
0xB9, 0x88, 0xDB, 0xEA, 0x7D, 0x4C, 0x1F, 0x2E,
0x43, 0x72, 0x21, 0x10, 0x87, 0xB6, 0xE5, 0xD4,
0xFA, 0xCB, 0x98, 0xA9, 0x3E, 0x0F, 0x5C, 0x6D,
0x86, 0xB7, 0xE4, 0xD5, 0x42, 0x73, 0x20, 0x11,
0x3F, 0x0E, 0x5D, 0x6C, 0xFB, 0xCA, 0x99, 0xA8,
0xC5, 0xF4, 0xA7, 0x96, 0x01, 0x30, 0x63, 0x52,
0x7C, 0x4D, 0x1E, 0x2F, 0xB8, 0x89, 0xDA, 0xEB,
0x3D, 0x0C, 0x5F, 0x6E, 0xF9, 0xC8, 0x9B, 0xAA,
0x84, 0xB5, 0xE6, 0xD7, 0x40, 0x71, 0x22, 0x13,
0x7E, 0x4F, 0x1C, 0x2D, 0xBA, 0x8B, 0xD8, 0xE9,
0xC7, 0xF6, 0xA5, 0x94, 0x03, 0x32, 0x61, 0x50,
0xBB, 0x8A, 0xD9, 0xE8, 0x7F, 0x4E, 0x1D, 0x2C,
0x02, 0x33, 0x60, 0x51, 0xC6, 0xF7, 0xA4, 0x95,
0xF8, 0xC9, 0x9A, 0xAB, 0x3C, 0x0D, 0x5E, 0x6F,
0x41, 0x70, 0x23, 0x12, 0x85, 0xB4, 0xE7, 0xD6,
0x7A, 0x4B, 0x18, 0x29, 0xBE, 0x8F, 0xDC, 0xED,
0xC3, 0xF2, 0xA1, 0x90, 0x07, 0x36, 0x65, 0x54,
0x39, 0x08, 0x5B, 0x6A, 0xFD, 0xCC, 0x9F, 0xAE,
0x80, 0xB1, 0xE2, 0xD3, 0x44, 0x75, 0x26, 0x17,
0xFC, 0xCD, 0x9E, 0xAF, 0x38, 0x09, 0x5A, 0x6B,
0x45, 0x74, 0x27, 0x16, 0x81, 0xB0, 0xE3, 0xD2,
0xBF, 0x8E, 0xDD, 0xEC, 0x7B, 0x4A, 0x19, 0x28,
0x06, 0x37, 0x64, 0x55, 0xC2, 0xF3, 0xA0, 0x91,
0x47, 0x76, 0x25, 0x14, 0x83, 0xB2, 0xE1, 0xD0,
0xFE, 0xCF, 0x9C, 0xAD, 0x3A, 0x0B, 0x58, 0x69,
0x04, 0x35, 0x66, 0x57, 0xC0, 0xF1, 0xA2, 0x93,
0xBD, 0x8C, 0xDF, 0xEE, 0x79, 0x48, 0x1B, 0x2A,
0xC1, 0xF0, 0xA3, 0x92, 0x05, 0x34, 0x67, 0x56,
0x78, 0x49, 0x1A, 0x2B, 0xBC, 0x8D, 0xDE, 0xEF,
0x82, 0xB3, 0xE0, 0xD1, 0x46, 0x77, 0x24, 0x15,
0x3B, 0x0A, 0x59, 0x68, 0xFF, 0xCE, 0x9D, 0xAC
};
#endif
/* CRC lookup table algorithm
#define CRC_BIT_NUM 8u/16u/32u/64u
#define BITS_IN_BYTE 8u
uint8_t dataBuff[ARRAY_SIZE] = { 0x32, 0x33, …};
uint8_t/uint16_t/uint32_t crc_val = 0x0;
// LSB
for(int i = 0; i < sizeof(dataBuff); i++)
{
crc_val = (crc_val >> BITS_IN_BYTE) ^ crc_lsb_lut[(uint8)(crc_val^dataBuff[i])];
}
// MSB
for(int i = 0; i < sizeof(dataBuff); i++)
{
crc_val = (crc_val << BITS_IN_BYTE) ^ crc_msb_lut[(uint8)((crc_val>>8)^dataBuff[i])];
}
*/
/*****************************************************************************/
/**
* @brief CRC8 generator
*
* @param buffPtr data buffer pointer.
* @param dataLen data length
* @param poly polynomials of crc
* @param crcVal a pointer to store generated crc value
*
* @return SUCCESS
* FAILURE
*
******************************************************************************/
int crc8_gen(uint8_t *buffPtr, uint32_t dataLen, uint16_t poly, uint8_t *crcVal)
{
uint8_t crc = CRC8_INIT;
const uint8_t *crc_lut = NULL;
switch (poly)
{
#ifdef __CRC_LSB
case 0x31:
crc_lut = crc8_31_lsb_lut;
break;
default:
return FAILURE;
#else
case 0x31:
crc_lut = crc8_31_msb_lut;
break;
default:
return FAILURE;
#endif
}
for (int i = 0; i < dataLen; i++)
{
crc = crc_lut[(uint8_t)(crc ^ buffPtr[i])];
}
*crcVal = crc;
return SUCCESS;
}
/*****************************************************************************/
/**
* @brief CRC16 generator
*
* @param buffPtr data buffer pointer.
* @param dataLen data length
* @param poly polynomials of crc
* @param crcVal a pointer to store generated crc value
*
* @return SUCCESS
* FAILURE
*
******************************************************************************/
int crc16_gen(uint8_t *buffPtr, uint32_t dataLen, uint16_t poly, uint16_t *crcVal)
{
uint16_t crc = CRC16_INIT;
const uint16_t *crc_lut = NULL;
switch (poly)
{
#ifdef __CRC_LSB
case 0x8005:
crc_lut = crc16_8005_lsb_lut;
break;
case 0x1021:
crc_lut = crc16_1021_lsb_lut;
break;
default:
return FAILURE;
#else
case 0x8005:
crc_lut = crc16_8005_msb_lut;
break;
case 0x1021:
crc_lut = crc16_1021_msb_lut;
break;
default:
return FAILURE;
#endif
}
for (int i = 0; i < dataLen; i++)
{
#ifdef __CRC_LSB
crc = (crc >> 8) ^ crc_lut[(uint8_t)(crc ^ buffPtr[i])];
#else
crc = (crc << 8) ^ crc_lut[(uint8_t)((crc >> 8) ^ buffPtr[i])];
#endif
}
*crcVal = crc;
return SUCCESS;
}
/*****************************************************************************/
/**
* @brief CRC8 compare cheker
*
* @param buffPtr data buffer pointer.
* @param dataLen data length
* @param crcOffset byte offset of crc stored position.
* @param poly polynomials of crc
*
* @return true
* false
*
******************************************************************************/
bool crc8_check(uint8_t *buffPtr, uint32_t dataLen, uint32_t crcOffset, uint16_t poly)
{
int Status = SUCCESS;
uint8_t crc_comp;
uint8_t crc;
if (dataLen == 0)
{
return false;
}
crc_comp = (uint8_t)(*(buffPtr + crcOffset));
Status = crc8_gen(buffPtr, dataLen, poly, &crc);
if (Status == SUCCESS)
{
if (crc == crc_comp)
{
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
/*****************************************************************************/
/**
* @brief CRC16 compare cheker
*
* @param buffPtr data buffer pointer.
* @param dataLen data length
* @param crcOffset byte offset of crc stored position.
* @param poly polynomials of crc
*
* @return true
* fasle
*
******************************************************************************/
bool crc16_check(uint8_t *buffPtr, uint32_t dataLen, uint32_t crcOffset, uint16_t poly)
{
int Status = SUCCESS;
uint16_t crc_comp;
uint16_t crc;
if (dataLen == 0)
{
return false;
}
crc_comp = (uint16_t)(*(buffPtr + crcOffset));
crc_comp |= (uint16_t)((*(buffPtr + crcOffset + 1)) << 8);
Status = crc16_gen(buffPtr, dataLen, poly, &crc);
if (Status == SUCCESS)
{
if (crc == crc_comp)
{
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
/** @}*/
@@ -0,0 +1,886 @@
/*******************************************************************************
* @file list.c
* @brief List library implementation
* @author Mihail Chindris ([email protected])
********************************************************************************
* Copyright 2020(c) Analog Devices, Inc.
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* - Neither the name of Analog Devices, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* - The use of this software may or may not infringe the patent rights
* of one or more patent holders. This license does not release you
* from the requirement that you obtain separate licenses from these
* patent holders to use this software.
* - Use of the software either in source or binary form, must be run
* on or directly connected to an Analog Devices Inc. component.
*
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/
/******************************************************************************/
/***************************** Include Files **********************************/
/******************************************************************************/
#include "list.h"
#include "error.h"
#include <stdlib.h>
/******************************************************************************/
/*************************** Types Declarations *******************************/
/******************************************************************************/
/**
* @struct list_elem
* @brief Format of each element of the list
*/
struct list_elem
{
/** User data */
void *data;
/** Reference to previous element */
struct list_elem *prev;
/** Reference to next element */
struct list_elem *next;
};
/**
* @struct list_iterator
* @brief Structure used to iterate through the list
*/
struct iterator
{
/** List reference */
struct _list_desc *list;
/** Current element reference */
struct list_elem *elem;
};
/**
* @struct _list_desc
* @brief List descriptor
*/
struct _list_desc
{
/** Reference to first element in the list */
struct list_elem *first;
/** Reference to last element in the list*/
struct list_elem *last;
/** Number of elements in the list */
uint32_t nb_elements;
/** Function used to compare elements */
f_cmp comparator;
/** Number of current active iterators */
uint32_t nb_iterators;
/** Internal list iterator */
struct iterator l_it;
};
/** @brief Default function used to compare element in the list ( \ref f_cmp) */
static int32_t default_comparator(void *data1, void *data2)
{
return (int32_t)((int32_t *)data1 - (int32_t *)data2);
}
/**
* @brief Creates a new list elements an configure its value
* @param data - To set list_elem.data
* @param prev - To set list_elem.prev
* @param next - To set list_elem.next
* @return Address of the new element or NULL if allocation fails.
*/
static inline struct list_elem *create_element(void *data,
struct list_elem *prev,
struct list_elem *next)
{
struct list_elem *elem;
elem = (struct list_elem *)calloc(1, sizeof(*elem));
if (!elem)
return NULL;
elem->data = data;
elem->prev = prev;
elem->next = next;
return (elem);
}
/**
* @brief Updates the necesary link on the list elements to add or remove one
* @param prev - Low element
* @param elem - Middle element
* @param next - High element
*/
static inline void update_links(struct list_elem *prev, struct list_elem *elem,
struct list_elem *next)
{
if (prev)
prev->next = elem ? elem : next;
if (elem)
{
elem->prev = prev;
elem->next = next;
}
if (next)
next->prev = elem ? elem : prev;
}
/**
* @brief Update according to modification the list descriptor
* @param list - List reference
* @param new_first - New first element
* @param new_last - New last element
*/
static inline void update_desc(struct _list_desc *list,
struct list_elem *new_first,
struct list_elem *new_last)
{
if (new_first == list->first)
{
list->last = new_last;
if (new_first == NULL || new_last == NULL)
list->first = new_last;
}
else
{ /* if (new_last == list->last) */
list->first = new_first;
if (new_last == NULL || new_first == NULL)
list->last = new_first;
}
}
/**
* @brief Set the adapter functions acording to the adapter type
* @param ad - Reference of the adapter
* @param type - Type of the adapter
*/
static inline void set_adapter(struct list_desc *ad, enum adapter_type type)
{
switch (type)
{
case LIST_PRIORITY_LIST:
ad->push = list_add_find;
ad->pop = list_get_first;
ad->top_next = list_read_first;
ad->back = list_read_last;
ad->swap = list_edit_first;
break;
case LIST_QUEUE:
ad->push = list_add_last;
ad->pop = list_get_first;
ad->top_next = list_read_first;
ad->back = list_read_last;
ad->swap = list_edit_first;
break;
case LIST_DEFAULT:
case LIST_STACK:
default:
ad->push = list_add_last;
ad->pop = list_get_last;
ad->top_next = list_read_last;
ad->back = list_read_first;
ad->swap = list_edit_last;
break;
}
}
/**
* @brief Create a new empty list
* @param list_desc - Where to store the reference of the new created list
* @param type - Type of adapter to use.
* @param comparator - Used to compare item when using an ordered list or when
* using the \em find functions.
* @return
* - \ref SUCCESS : On success
* - \ref FAILURE : Otherwise
*/
int32_t list_init(struct list_desc **list_desc, enum adapter_type type,
f_cmp comparator)
{
struct list_desc *l_desc;
struct _list_desc *list;
if (!list_desc)
return FAILURE;
l_desc = (struct list_desc *)calloc(1, sizeof(*l_desc));
if (!l_desc)
return FAILURE;
list = (struct _list_desc *)calloc(1, sizeof(*list));
if (!list)
{
free(l_desc);
return FAILURE;
}
*list_desc = l_desc;
l_desc->priv_desc = list;
list->comparator = comparator ? comparator : default_comparator;
/* Configure wrapper */
set_adapter(l_desc, type);
list->l_it.list = list;
return SUCCESS;
}
/**
* @brief Remove the created list.
*
* All its elements will be cleared and the data inside each will be lost. If
* not all iterators have been removed, the list will not be removed.
* @param list_desc - Reference to the list
* @return
* - \ref SUCCESS : On success
* - \ref FAILURE : Otherwise
*/
int32_t list_remove(struct list_desc *list_desc)
{
void *data;
struct _list_desc *list;
if (!list_desc)
return FAILURE;
list = list_desc->priv_desc;
if (list->nb_iterators != 0)
return FAILURE;
/* Remove all the elements */
while (SUCCESS == list_get_first(list_desc, &data))
;
free(list_desc->priv_desc);
free(list_desc);
return SUCCESS;
}
/**
* @brief Get the number of elements inside the list
* @param list_desc - List reference
* @param out_size - Where to store the number of elements
* @return
* - \ref SUCCESS : On success
* - \ref FAILURE : Otherwise
*/
int32_t list_get_size(struct list_desc *list_desc, uint32_t *out_size)
{
struct _list_desc *list;
if (!list_desc || !out_size)
return FAILURE;
list = list_desc->priv_desc;
*out_size = list->nb_elements;
return SUCCESS;
}
/** @brief Add element at the begining of the list. Refer to \ref f_add */
int32_t list_add_first(struct list_desc *list_desc, void *data)
{
struct list_elem *prev;
struct list_elem *next;
struct list_elem *elem;
struct _list_desc *list;
if (!list_desc)
return FAILURE;
list = list_desc->priv_desc;
prev = NULL;
next = list->first;
elem = create_element(data, prev, next);
if (!elem)
return FAILURE;
update_links(prev, elem, next);
update_desc(list, elem, list->last);
list->nb_elements++;
return SUCCESS;
}
/** @brief Add element at the end of the list. Refer to \ref f_add */
int32_t list_add_last(struct list_desc *list_desc, void *data)
{
struct list_elem *prev;
struct list_elem *next;
struct list_elem *elem;
struct _list_desc *list;
if (!list_desc)
return FAILURE;
list = list_desc->priv_desc;
prev = list->last;
next = NULL;
elem = create_element(data, prev, next);
if (!elem)
return FAILURE;
update_links(prev, elem, next);
update_desc(list, list->first, elem);
list->nb_elements++;
return SUCCESS;
}
/** @brief Add element at the specified idx. Refer to \ref f_add */
int32_t list_add_idx(struct list_desc *list_desc, void *data, uint32_t idx)
{
struct _list_desc *list;
if (!list_desc)
return FAILURE;
list = list_desc->priv_desc;
/* If there are no elements the creation of an iterator will fail */
if (list->nb_elements == 0 || idx == 0)
return list_add_first(list_desc, data);
if (list->nb_elements == idx)
return list_add_last(list_desc, data);
list->l_it.elem = list->first;
if (SUCCESS != iterator_move(&(list->l_it), idx))
return FAILURE;
return iterator_insert(&(list->l_it), data, 0);
}
/** @brief Add element in ascending order. Refer to \ref f_add */
int32_t list_add_find(struct list_desc *list_desc, void *data)
{
struct list_elem *elem;
struct _list_desc *list;
if (!list_desc)
return FAILURE;
list = list_desc->priv_desc;
/* Based on place iterator */
elem = list->first;
while (elem)
{
if (0 < list->comparator(elem->data, data))
break;
elem = elem->next;
}
if (elem == NULL)
{
list->l_it.elem = list->last;
return iterator_insert(&(list->l_it), data, 1);
}
else
{
list->l_it.elem = elem;
return iterator_insert(&(list->l_it), data, 0);
}
}
/** @brief Edit the first element of the list. Refer to \ref f_edit */
int32_t list_edit_first(struct list_desc *list_desc, void *new_data)
{
struct _list_desc *list;
if (!list_desc)
return FAILURE;
list = list_desc->priv_desc;
list->first->data = new_data;
return SUCCESS;
}
/** @brief Edit the last element of the list. Refer to \ref f_edit */
int32_t list_edit_last(struct list_desc *list_desc, void *new_data)
{
struct _list_desc *list;
if (!list_desc)
return FAILURE;
list = list_desc->priv_desc;
list->last->data = new_data;
return SUCCESS;
}
/** @brief Edit the element at the specified idx. Refer to \ref f_edit */
int32_t list_edit_idx(struct list_desc *list_desc, void *new_data, uint32_t idx)
{
struct _list_desc *list;
if (!list_desc)
return FAILURE;
list = list_desc->priv_desc;
list->l_it.elem = list->first;
if (SUCCESS != iterator_move(&(list->l_it), idx))
return FAILURE;
return iterator_edit(&(list->l_it), new_data);
}
/** @brief Edit the element which match with cmp_data. Refer to \ref f_edit */
int32_t list_edit_find(struct list_desc *list_desc, void *new_data,
void *cmp_data)
{
struct _list_desc *list;
if (!list_desc)
return FAILURE;
list = list_desc->priv_desc;
list->l_it.elem = list->first;
if (SUCCESS != iterator_find(&(list->l_it), cmp_data))
return FAILURE;
return iterator_edit(&(list->l_it), new_data);
}
/** @brief Read the first element of the list. Refer to \ref f_read */
int32_t list_read_first(struct list_desc *list_desc, void **data)
{
struct _list_desc *list;
if (!list_desc || !data)
return FAILURE;
*data = NULL;
list = list_desc->priv_desc;
if (!list->first)
return FAILURE;
*data = list->first->data;
return SUCCESS;
}
/** @brief Read the last element of the list. Refer to \ref f_read */
int32_t list_read_last(struct list_desc *list_desc, void **data)
{
struct _list_desc *list;
if (!list_desc || !data)
return FAILURE;
*data = NULL;
list = list_desc->priv_desc;
if (!list->last)
return FAILURE;
*data = list->last->data;
return SUCCESS;
}
/** @brief Read the element at the specified idx. Refer to \ref f_read */
int32_t list_read_idx(struct list_desc *list_desc, void **data, uint32_t idx)
{
struct _list_desc *list;
if (!list_desc || !data)
return FAILURE;
*data = NULL;
list = list_desc->priv_desc;
if (!list)
return FAILURE;
if (idx >= list->nb_elements)
return FAILURE;
list->l_it.elem = list->first;
if (SUCCESS != iterator_move(&(list->l_it), idx))
return FAILURE;
return iterator_read(&(list->l_it), data);
}
/** @brief Read the element which match with cmp_data. Refer to \ref f_read */
int32_t list_read_find(struct list_desc *list_desc, void **data,
void *cmp_data)
{
struct _list_desc *list;
if (!list_desc || !data)
return FAILURE;
*data = NULL;
list = list_desc->priv_desc;
if (!list)
return FAILURE;
list = list_desc->priv_desc;
list->l_it.elem = list->first;
if (SUCCESS != iterator_find(&(list->l_it), cmp_data))
return FAILURE;
return iterator_read(&(list->l_it), data);
}
/** @brief Read and delete the first element of the list. Refer to \ref f_get */
int32_t list_get_first(struct list_desc *list_desc, void **data)
{
struct list_elem *prev;
struct list_elem *next;
struct list_elem *elem;
struct _list_desc *list;
if (!list_desc || !data)
return FAILURE;
*data = NULL;
list = list_desc->priv_desc;
if (!list->nb_elements)
return FAILURE;
elem = list->first;
prev = elem->prev;
next = elem->next;
update_links(prev, NULL, next);
update_desc(list, next, list->last);
list->nb_elements--;
*data = elem->data;
free(elem);
return SUCCESS;
}
/** @brief Read and delete the last element of the list. Refer to \ref f_get */
int32_t list_get_last(struct list_desc *list_desc, void **data)
{
struct list_elem *prev;
struct list_elem *next;
struct list_elem *elem;
struct _list_desc *list;
if (!list_desc || !data)
return FAILURE;
*data = NULL;
list = list_desc->priv_desc;
if (!list->nb_elements)
return FAILURE;
elem = list->last;
prev = elem->prev;
next = elem->next;
update_links(prev, NULL, next);
update_desc(list, list->first, prev);
list->nb_elements--;
*data = elem->data;
free(elem);
return SUCCESS;
}
/** @brief Read and delete the element at idx. Refer to \ref f_get */
int32_t list_get_idx(struct list_desc *list_desc, void **data, uint32_t idx)
{
struct _list_desc *list;
if (!list_desc || !data)
return FAILURE;
*data = NULL;
list = list_desc->priv_desc;
list->l_it.elem = list->first;
if (SUCCESS != iterator_move(&(list->l_it), idx))
return FAILURE;
return iterator_get(&(list->l_it), data);
}
/**
* @brief Read and delete the element which match with cmp_data.
* Refer to \ref f_get
*/
int32_t list_get_find(struct list_desc *list_desc, void **data, void *cmp_data)
{
struct _list_desc *list;
if (!list_desc || !data)
return FAILURE;
*data = NULL;
list = list_desc->priv_desc;
list->l_it.elem = list->first;
if (SUCCESS != iterator_find(&(list->l_it), cmp_data))
return FAILURE;
return iterator_get(&(list->l_it), data);
}
/**
* @brief Create a new iterator
* @param iter - Where to store the reference for the new iterator
* @param list_desc - Reference of the list the iterator will be used for
* @param start - If it is true the iterator will be positioned at the first
* element of the list, else it will be positioned at the last.
* @return
* - \ref SUCCESS : On success
* - \ref FAILURE : Otherwise
*/
int32_t iterator_init(struct iterator **iter, struct list_desc *list_desc,
bool start)
{
struct iterator *it;
if (!list_desc)
return FAILURE;
it = (struct iterator *)calloc(1, sizeof(*it));
if (!it)
return FAILURE;
it->list = list_desc->priv_desc;
it->list->nb_iterators++;
it->elem = start ? it->list->first : it->list->last;
*iter = it;
return SUCCESS;
}
/**
* @brief Remove the created iterator
* @param iter - Reference of the iterator
* @return
* - \ref SUCCESS : On success
* - \ref FAILURE : Otherwise
*/
int32_t iterator_remove(struct iterator *iter)
{
struct iterator *it = iter;
if (!it)
return FAILURE;
it->list->nb_iterators--;
free(it);
return SUCCESS;
}
/**
* @brief Move the position of the iteration through the list.
*
* If the required position is outside the list, the call will fail and the
* iterator will keep its position.
* @param iter - Reference of the iterator
* @param steps - Number of positions to be move. If positive, it will be moved
* forward, otherwise backwords.
* @return
* - \ref SUCCESS : On success
* - \ref FAILURE : Otherwise
*/
int32_t iterator_move(struct iterator *iter, int32_t steps)
{
struct iterator *it = iter;
struct list_elem *elem;
int32_t dir = (steps < 0) ? -1 : 1;
if (!it)
return FAILURE;
steps = abs(steps);
elem = it->elem;
while (steps > 0 && elem)
{
elem = dir > 0 ? elem->next : elem->prev;
steps--;
}
if (!elem)
return FAILURE;
it->elem = elem;
return SUCCESS;
}
/**
* @brief Move the position of the iterator at the specified index of the list.
*
* @param iter - Reference of the iterator
* @param idx - Position in the list. If negative start counting backwords
* @return
* - \ref SUCCESS : On success
* - \ref FAILURE : Otherwise
*/
int32_t iterator_move_to_idx(struct iterator *iter, int32_t idx)
{
struct list_elem *elem;
int32_t dir = (idx < 0) ? -1 : 1;
if (!iter)
return FAILURE;
idx = abs(idx);
elem = dir > 0 ? iter->list->first : iter->list->last;
while (idx > 0 && elem)
{
elem = dir > 0 ? elem->next : elem->prev;
idx--;
}
if (!elem)
return FAILURE;
iter->elem = elem;
return SUCCESS;
}
/**
* @brief Place the iterator where cmp_data if found.
* @param iter - Reference to the iterator
* @param cmp_data - Data to be found
* @return
* - \ref SUCCESS : On success
* - \ref FAILURE : Otherwise
*/
int32_t iterator_find(struct iterator *iter, void *cmp_data)
{
struct iterator *it = iter;
struct list_elem *elem;
if (!it)
return FAILURE;
elem = it->list->first;
while (elem)
{
if (0 == it->list->comparator(elem->data, cmp_data))
{
it->elem = elem;
return SUCCESS;
}
elem = elem->next;
}
return FAILURE;
}
/**
* @brief Replace the data at the current position. Refer to \ref f_edit
*/
int32_t iterator_edit(struct iterator *iter, void *new_data)
{
struct iterator *it = iter;
if (!it)
return FAILURE;
it->elem->data = new_data;
return SUCCESS;
}
/**
* @brief Read and remove the data at the current position. Refer to \ref f_get.
*
* If the current item is the last one, the iterator will be moved to the
* previous one.
*/
int32_t iterator_get(struct iterator *iter, void **data)
{
struct iterator *it = iter;
struct list_elem *next;
if (!it || !it->elem || !data)
return FAILURE;
update_links(it->elem->prev, NULL, it->elem->next);
if (it->elem == it->list->first)
update_desc(it->list, it->elem->next, it->list->last);
else if (it->elem == it->list->last)
update_desc(it->list, it->list->first, it->elem->prev);
it->list->nb_elements--;
*data = it->elem->data;
if (it->elem == it->list->last)
next = it->elem->prev;
else
next = it->elem->next;
free(it->elem);
it->elem = next;
return SUCCESS;
}
/**
* @brief Read the data at the current position. Refer to \ref f_read
*/
int32_t iterator_read(struct iterator *iter, void **data)
{
struct iterator *it = iter;
if (!it || !it->elem || !data)
return FAILURE;
*data = it->elem->data;
return SUCCESS;
}
/**
* @brief Insert an item in the list. Refer to \ref f_add
* @param iter
* @param data
* @param after - If true, the item will be inserted after the current position.
* Otherwise it will be inserted before.
*/
int32_t iterator_insert(struct iterator *iter, void *data, bool after)
{
struct iterator *it = iter;
struct list_elem *elem;
struct list_desc list_desc;
if (!it)
return FAILURE;
list_desc.priv_desc = iter->list;
if (after && it->elem == it->list->last)
return list_add_last(&list_desc, data);
if (!after && it->elem == it->list->first)
return list_add_first(&list_desc, data);
if (after)
elem = create_element(data, it->elem, it->elem->next);
else
elem = create_element(data, it->elem->prev, it->elem);
if (!elem)
return FAILURE;
update_links(elem->prev, elem, elem->next);
it->list->nb_elements++;
return SUCCESS;
}
@@ -0,0 +1,231 @@
Generating CRC table for crc8-31-lsb
0x00, 0x5E, 0xBC, 0xE2, 0x61, 0x3F, 0xDD, 0x83,
0xC2, 0x9C, 0x7E, 0x20, 0xA3, 0xFD, 0x1F, 0x41,
0x9D, 0xC3, 0x21, 0x7F, 0xFC, 0xA2, 0x40, 0x1E,
0x5F, 0x01, 0xE3, 0xBD, 0x3E, 0x60, 0x82, 0xDC,
0x23, 0x7D, 0x9F, 0xC1, 0x42, 0x1C, 0xFE, 0xA0,
0xE1, 0xBF, 0x5D, 0x03, 0x80, 0xDE, 0x3C, 0x62,
0xBE, 0xE0, 0x02, 0x5C, 0xDF, 0x81, 0x63, 0x3D,
0x7C, 0x22, 0xC0, 0x9E, 0x1D, 0x43, 0xA1, 0xFF,
0x46, 0x18, 0xFA, 0xA4, 0x27, 0x79, 0x9B, 0xC5,
0x84, 0xDA, 0x38, 0x66, 0xE5, 0xBB, 0x59, 0x07,
0xDB, 0x85, 0x67, 0x39, 0xBA, 0xE4, 0x06, 0x58,
0x19, 0x47, 0xA5, 0xFB, 0x78, 0x26, 0xC4, 0x9A,
0x65, 0x3B, 0xD9, 0x87, 0x04, 0x5A, 0xB8, 0xE6,
0xA7, 0xF9, 0x1B, 0x45, 0xC6, 0x98, 0x7A, 0x24,
0xF8, 0xA6, 0x44, 0x1A, 0x99, 0xC7, 0x25, 0x7B,
0x3A, 0x64, 0x86, 0xD8, 0x5B, 0x05, 0xE7, 0xB9,
0x8C, 0xD2, 0x30, 0x6E, 0xED, 0xB3, 0x51, 0x0F,
0x4E, 0x10, 0xF2, 0xAC, 0x2F, 0x71, 0x93, 0xCD,
0x11, 0x4F, 0xAD, 0xF3, 0x70, 0x2E, 0xCC, 0x92,
0xD3, 0x8D, 0x6F, 0x31, 0xB2, 0xEC, 0x0E, 0x50,
0xAF, 0xF1, 0x13, 0x4D, 0xCE, 0x90, 0x72, 0x2C,
0x6D, 0x33, 0xD1, 0x8F, 0x0C, 0x52, 0xB0, 0xEE,
0x32, 0x6C, 0x8E, 0xD0, 0x53, 0x0D, 0xEF, 0xB1,
0xF0, 0xAE, 0x4C, 0x12, 0x91, 0xCF, 0x2D, 0x73,
0xCA, 0x94, 0x76, 0x28, 0xAB, 0xF5, 0x17, 0x49,
0x08, 0x56, 0xB4, 0xEA, 0x69, 0x37, 0xD5, 0x8B,
0x57, 0x09, 0xEB, 0xB5, 0x36, 0x68, 0x8A, 0xD4,
0x95, 0xCB, 0x29, 0x77, 0xF4, 0xAA, 0x48, 0x16,
0xE9, 0xB7, 0x55, 0x0B, 0x88, 0xD6, 0x34, 0x6A,
0x2B, 0x75, 0x97, 0xC9, 0x4A, 0x14, 0xF6, 0xA8,
0x74, 0x2A, 0xC8, 0x96, 0x15, 0x4B, 0xA9, 0xF7,
0xB6, 0xE8, 0x0A, 0x54, 0xD7, 0x89, 0x6B, 0x35,
Generating CRC table for crc8-31-msb
0x00, 0x31, 0x62, 0x53, 0xC4, 0xF5, 0xA6, 0x97,
0xB9, 0x88, 0xDB, 0xEA, 0x7D, 0x4C, 0x1F, 0x2E,
0x43, 0x72, 0x21, 0x10, 0x87, 0xB6, 0xE5, 0xD4,
0xFA, 0xCB, 0x98, 0xA9, 0x3E, 0x0F, 0x5C, 0x6D,
0x86, 0xB7, 0xE4, 0xD5, 0x42, 0x73, 0x20, 0x11,
0x3F, 0x0E, 0x5D, 0x6C, 0xFB, 0xCA, 0x99, 0xA8,
0xC5, 0xF4, 0xA7, 0x96, 0x01, 0x30, 0x63, 0x52,
0x7C, 0x4D, 0x1E, 0x2F, 0xB8, 0x89, 0xDA, 0xEB,
0x3D, 0x0C, 0x5F, 0x6E, 0xF9, 0xC8, 0x9B, 0xAA,
0x84, 0xB5, 0xE6, 0xD7, 0x40, 0x71, 0x22, 0x13,
0x7E, 0x4F, 0x1C, 0x2D, 0xBA, 0x8B, 0xD8, 0xE9,
0xC7, 0xF6, 0xA5, 0x94, 0x03, 0x32, 0x61, 0x50,
0xBB, 0x8A, 0xD9, 0xE8, 0x7F, 0x4E, 0x1D, 0x2C,
0x02, 0x33, 0x60, 0x51, 0xC6, 0xF7, 0xA4, 0x95,
0xF8, 0xC9, 0x9A, 0xAB, 0x3C, 0x0D, 0x5E, 0x6F,
0x41, 0x70, 0x23, 0x12, 0x85, 0xB4, 0xE7, 0xD6,
0x7A, 0x4B, 0x18, 0x29, 0xBE, 0x8F, 0xDC, 0xED,
0xC3, 0xF2, 0xA1, 0x90, 0x07, 0x36, 0x65, 0x54,
0x39, 0x08, 0x5B, 0x6A, 0xFD, 0xCC, 0x9F, 0xAE,
0x80, 0xB1, 0xE2, 0xD3, 0x44, 0x75, 0x26, 0x17,
0xFC, 0xCD, 0x9E, 0xAF, 0x38, 0x09, 0x5A, 0x6B,
0x45, 0x74, 0x27, 0x16, 0x81, 0xB0, 0xE3, 0xD2,
0xBF, 0x8E, 0xDD, 0xEC, 0x7B, 0x4A, 0x19, 0x28,
0x06, 0x37, 0x64, 0x55, 0xC2, 0xF3, 0xA0, 0x91,
0x47, 0x76, 0x25, 0x14, 0x83, 0xB2, 0xE1, 0xD0,
0xFE, 0xCF, 0x9C, 0xAD, 0x3A, 0x0B, 0x58, 0x69,
0x04, 0x35, 0x66, 0x57, 0xC0, 0xF1, 0xA2, 0x93,
0xBD, 0x8C, 0xDF, 0xEE, 0x79, 0x48, 0x1B, 0x2A,
0xC1, 0xF0, 0xA3, 0x92, 0x05, 0x34, 0x67, 0x56,
0x78, 0x49, 0x1A, 0x2B, 0xBC, 0x8D, 0xDE, 0xEF,
0x82, 0xB3, 0xE0, 0xD1, 0x46, 0x77, 0x24, 0x15,
0x3B, 0x0A, 0x59, 0x68, 0xFF, 0xCE, 0x9D, 0xAC,
Generating CRC table for crc16-8005-lsb
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040,
Generating CRC table for crc16-8005-msb
0x0000, 0x8005, 0x800F, 0x000A, 0x801B, 0x001E, 0x0014, 0x8011,
0x8033, 0x0036, 0x003C, 0x8039, 0x0028, 0x802D, 0x8027, 0x0022,
0x8063, 0x0066, 0x006C, 0x8069, 0x0078, 0x807D, 0x8077, 0x0072,
0x0050, 0x8055, 0x805F, 0x005A, 0x804B, 0x004E, 0x0044, 0x8041,
0x80C3, 0x00C6, 0x00CC, 0x80C9, 0x00D8, 0x80DD, 0x80D7, 0x00D2,
0x00F0, 0x80F5, 0x80FF, 0x00FA, 0x80EB, 0x00EE, 0x00E4, 0x80E1,
0x00A0, 0x80A5, 0x80AF, 0x00AA, 0x80BB, 0x00BE, 0x00B4, 0x80B1,
0x8093, 0x0096, 0x009C, 0x8099, 0x0088, 0x808D, 0x8087, 0x0082,
0x8183, 0x0186, 0x018C, 0x8189, 0x0198, 0x819D, 0x8197, 0x0192,
0x01B0, 0x81B5, 0x81BF, 0x01BA, 0x81AB, 0x01AE, 0x01A4, 0x81A1,
0x01E0, 0x81E5, 0x81EF, 0x01EA, 0x81FB, 0x01FE, 0x01F4, 0x81F1,
0x81D3, 0x01D6, 0x01DC, 0x81D9, 0x01C8, 0x81CD, 0x81C7, 0x01C2,
0x0140, 0x8145, 0x814F, 0x014A, 0x815B, 0x015E, 0x0154, 0x8151,
0x8173, 0x0176, 0x017C, 0x8179, 0x0168, 0x816D, 0x8167, 0x0162,
0x8123, 0x0126, 0x012C, 0x8129, 0x0138, 0x813D, 0x8137, 0x0132,
0x0110, 0x8115, 0x811F, 0x011A, 0x810B, 0x010E, 0x0104, 0x8101,
0x8303, 0x0306, 0x030C, 0x8309, 0x0318, 0x831D, 0x8317, 0x0312,
0x0330, 0x8335, 0x833F, 0x033A, 0x832B, 0x032E, 0x0324, 0x8321,
0x0360, 0x8365, 0x836F, 0x036A, 0x837B, 0x037E, 0x0374, 0x8371,
0x8353, 0x0356, 0x035C, 0x8359, 0x0348, 0x834D, 0x8347, 0x0342,
0x03C0, 0x83C5, 0x83CF, 0x03CA, 0x83DB, 0x03DE, 0x03D4, 0x83D1,
0x83F3, 0x03F6, 0x03FC, 0x83F9, 0x03E8, 0x83ED, 0x83E7, 0x03E2,
0x83A3, 0x03A6, 0x03AC, 0x83A9, 0x03B8, 0x83BD, 0x83B7, 0x03B2,
0x0390, 0x8395, 0x839F, 0x039A, 0x838B, 0x038E, 0x0384, 0x8381,
0x0280, 0x8285, 0x828F, 0x028A, 0x829B, 0x029E, 0x0294, 0x8291,
0x82B3, 0x02B6, 0x02BC, 0x82B9, 0x02A8, 0x82AD, 0x82A7, 0x02A2,
0x82E3, 0x02E6, 0x02EC, 0x82E9, 0x02F8, 0x82FD, 0x82F7, 0x02F2,
0x02D0, 0x82D5, 0x82DF, 0x02DA, 0x82CB, 0x02CE, 0x02C4, 0x82C1,
0x8243, 0x0246, 0x024C, 0x8249, 0x0258, 0x825D, 0x8257, 0x0252,
0x0270, 0x8275, 0x827F, 0x027A, 0x826B, 0x026E, 0x0264, 0x8261,
0x0220, 0x8225, 0x822F, 0x022A, 0x823B, 0x023E, 0x0234, 0x8231,
0x8213, 0x0216, 0x021C, 0x8219, 0x0208, 0x820D, 0x8207, 0x0202,
Generating CRC table for crc16-1021-lsb
0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF,
0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7,
0x1081, 0x0108, 0x3393, 0x221A, 0x56A5, 0x472C, 0x75B7, 0x643E,
0x9CC9, 0x8D40, 0xBFDB, 0xAE52, 0xDAED, 0xCB64, 0xF9FF, 0xE876,
0x2102, 0x308B, 0x0210, 0x1399, 0x6726, 0x76AF, 0x4434, 0x55BD,
0xAD4A, 0xBCC3, 0x8E58, 0x9FD1, 0xEB6E, 0xFAE7, 0xC87C, 0xD9F5,
0x3183, 0x200A, 0x1291, 0x0318, 0x77A7, 0x662E, 0x54B5, 0x453C,
0xBDCB, 0xAC42, 0x9ED9, 0x8F50, 0xFBEF, 0xEA66, 0xD8FD, 0xC974,
0x4204, 0x538D, 0x6116, 0x709F, 0x0420, 0x15A9, 0x2732, 0x36BB,
0xCE4C, 0xDFC5, 0xED5E, 0xFCD7, 0x8868, 0x99E1, 0xAB7A, 0xBAF3,
0x5285, 0x430C, 0x7197, 0x601E, 0x14A1, 0x0528, 0x37B3, 0x263A,
0xDECD, 0xCF44, 0xFDDF, 0xEC56, 0x98E9, 0x8960, 0xBBFB, 0xAA72,
0x6306, 0x728F, 0x4014, 0x519D, 0x2522, 0x34AB, 0x0630, 0x17B9,
0xEF4E, 0xFEC7, 0xCC5C, 0xDDD5, 0xA96A, 0xB8E3, 0x8A78, 0x9BF1,
0x7387, 0x620E, 0x5095, 0x411C, 0x35A3, 0x242A, 0x16B1, 0x0738,
0xFFCF, 0xEE46, 0xDCDD, 0xCD54, 0xB9EB, 0xA862, 0x9AF9, 0x8B70,
0x8408, 0x9581, 0xA71A, 0xB693, 0xC22C, 0xD3A5, 0xE13E, 0xF0B7,
0x0840, 0x19C9, 0x2B52, 0x3ADB, 0x4E64, 0x5FED, 0x6D76, 0x7CFF,
0x9489, 0x8500, 0xB79B, 0xA612, 0xD2AD, 0xC324, 0xF1BF, 0xE036,
0x18C1, 0x0948, 0x3BD3, 0x2A5A, 0x5EE5, 0x4F6C, 0x7DF7, 0x6C7E,
0xA50A, 0xB483, 0x8618, 0x9791, 0xE32E, 0xF2A7, 0xC03C, 0xD1B5,
0x2942, 0x38CB, 0x0A50, 0x1BD9, 0x6F66, 0x7EEF, 0x4C74, 0x5DFD,
0xB58B, 0xA402, 0x9699, 0x8710, 0xF3AF, 0xE226, 0xD0BD, 0xC134,
0x39C3, 0x284A, 0x1AD1, 0x0B58, 0x7FE7, 0x6E6E, 0x5CF5, 0x4D7C,
0xC60C, 0xD785, 0xE51E, 0xF497, 0x8028, 0x91A1, 0xA33A, 0xB2B3,
0x4A44, 0x5BCD, 0x6956, 0x78DF, 0x0C60, 0x1DE9, 0x2F72, 0x3EFB,
0xD68D, 0xC704, 0xF59F, 0xE416, 0x90A9, 0x8120, 0xB3BB, 0xA232,
0x5AC5, 0x4B4C, 0x79D7, 0x685E, 0x1CE1, 0x0D68, 0x3FF3, 0x2E7A,
0xE70E, 0xF687, 0xC41C, 0xD595, 0xA12A, 0xB0A3, 0x8238, 0x93B1,
0x6B46, 0x7ACF, 0x4854, 0x59DD, 0x2D62, 0x3CEB, 0x0E70, 0x1FF9,
0xF78F, 0xE606, 0xD49D, 0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330,
0x7BC7, 0x6A4E, 0x58D5, 0x495C, 0x3DE3, 0x2C6A, 0x1EF1, 0x0F78,
Generating CRC table for crc16-1021-msb
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0,
#define CRC_BIT_NUM 8u/16u/32u/64u
#define BITS_IN_BYTE 8u
uint8_t dataBuff[ARRAY_SIZE] = { 0x32, 0x33, ...;
uint8_t/uint16_t/uint32_t crc_val = 0x0;
// LSB
for(int i = 0; i < sizeof(dataBuff); i++)
{
crc_val = (crc_val >> BITS_IN_BYTE) ^ crc_lsb_lut[(uint8)(crc_val^dataBuff[i])];
}
// MSB
for(int i = 0; i < sizeof(dataBuff); i++)
{
crc_val = (crc_val << BITS_IN_BYTE) ^ crc_msb_lut[(uint8)((crc_val>>8)^dataBuff[i])];
}
@@ -0,0 +1,403 @@
/*****************************************************************************/
/**
* @file util.c
* @author FanHao ([email protected])
* @brief Utility functions implementation file
* @version 0.0
* @date 2023-05-06
*
* @copyright Copyright(c) 2024 Beijing Institute of Technology.\n
* Lab of Communication and Network
*
******************************************************************************/
/***************************** Include Files **********************************/
/**
* @addtogroup Utility
* @{
*/
#include <string.h>
#include <stdlib.h>
// #include <arm_acle.h>
#include "util.h"
#include "error.h"
/************************** Functions Implementation **************************/
#ifdef __BITSWAP_TABLE
static uint8_t byte_flipLR[256] =
{
0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
};
#endif
/**
* @brief Write a 32bit word to specific memory address
*/
inline void IO_Out32(uintptr_t addr, uint32_t value)
{
volatile uint32_t *localAddr = (volatile uint32_t *)addr;
*localAddr = value;
}
/**
* @brief Read a 32bit word from specific memory address
*/
inline uint32_t IO_In32(uintptr_t addr)
{
return *(volatile uint32_t *)addr;
}
/**
* @brief Swap a byte word bit-wise
*/
uint8_t byte_bit_swap(uint8_t byte)
{
#ifdef __BITSWAP_TABLE
return byte_flipLR[byte];
#else
return bit_swap_constant_8(byte);
#endif
}
/**
* @brief Swap 32bit word bit-wise
*/
uint32_t word_bit_swap(uint32_t word)
{
#ifdef __BITSWAP_TABLE
uint32_t rv_word = (byte_flipLR[word & 0xff] << 24) |
(byte_flipLR[(word >> 8) & 0xff] << 16) |
(byte_flipLR[(word >> 16) & 0xff] << 8) |
(byte_flipLR[(word >> 24) & 0xff]);
return rv_word;
#else
word = (((word & 0xaaaaaaaa) >> 1) | ((word & 0x55555555) << 1));
word = (((word & 0xcccccccc) >> 2) | ((word & 0x33333333) << 2));
word = (((word & 0xf0f0f0f0) >> 4) | ((word & 0x0f0f0f0f) << 4));
word = (((word & 0xff00ff00) >> 8) | ((word & 0x00ff00ff) << 8));
return ((word >> 16) | (word << 16));
#endif
}
/**
* @brief Count ones in an 32bit word
*/
uint32_t count_ones(uint32_t word)
{
#ifdef __GNUC__
return __builtin_popcount(word);
#else
uint32_t one_count = 0;
while (word)
{
if (word & 0x00000001)
one_count++;
word >>= 1;
}
return one_count;
#endif
}
/**
* @brief Convert fix ;oint number to float number
*/
double fix2double(int32_t val, uint8_t frac_bits)
{
return (((double)val) / (BIT(frac_bits)));
}
/**
* @brief Find first set bit in word.
*/
uint32_t find_first_set_bit(uint32_t word)
{
#ifdef __GNUC__
if (word != 0)
{
return __builtin_ctz(word);
}
else
{
return 32;
}
#else
uint32_t first_set_bit = 0;
while (word)
{
if (word & 0x1)
return first_set_bit;
word >>= 1;
first_set_bit++;
}
return 32;
#endif
}
/**
* @brief Find last set bit in word.
*/
uint32_t find_last_set_bit(uint32_t word)
{
#ifdef __GNUC__
if (word != 0)
{
return (31 - __builtin_clz(word));
}
else
{
return 32;
}
#else
uint32_t bit = 0;
uint32_t last_set_bit = 32;
while (word)
{
if (word & 0x1)
last_set_bit = bit;
word >>= 1;
bit++;
}
return last_set_bit;
#endif
}
/**
* @brief Locate the closest element in an array.
*/
uint32_t find_closest(int32_t val,
const int32_t *array,
uint32_t size)
{
int32_t diff = abs(array[0] - val);
uint32_t ret = 0;
uint32_t i;
for (i = 1; i < size; i++)
{
if (abs(array[i] - val) < diff)
{
diff = abs(array[i] - val);
ret = i;
}
}
return ret;
}
/**
* @brief Shift the value and apply the specified mask.
*/
uint32_t field_prep(uint32_t mask, uint32_t val)
{
return (val << find_first_set_bit(mask)) & mask;
}
/**
* @brief Get a field specified by a mask from a word.
*/
uint32_t field_get(uint32_t mask, uint32_t word)
{
return (word & mask) >> find_first_set_bit(mask);
}
/**
* @brief Log base 2 of the given number.
*/
int32_t log_base_2(uint32_t x)
{
return find_last_set_bit(x);
}
/**
* @brief Find greatest common divisor of the given two numbers.
*/
uint32_t greatest_common_divisor(uint32_t a,
uint32_t b)
{
uint32_t div;
uint32_t common_div = 1;
if ((a == 0) || (b == 0))
return max(a, b);
for (div = 1; (div <= a) && (div <= b); div++)
if (!(a % div) && !(b % div))
common_div = div;
return common_div;
}
/**
* @brief Calculate best rational approximation for a given fraction.
*/
void rational_best_approximation(uint32_t given_numerator,
uint32_t given_denominator,
uint32_t max_numerator,
uint32_t max_denominator,
uint32_t *best_numerator,
uint32_t *best_denominator)
{
uint32_t gcd;
gcd = greatest_common_divisor(given_numerator, given_denominator);
*best_numerator = given_numerator / gcd;
*best_denominator = given_denominator / gcd;
if ((*best_numerator > max_numerator) ||
(*best_denominator > max_denominator))
{
*best_numerator = 0;
*best_denominator = 0;
}
}
/**
* @brief Calculate the number of set bits.
*/
uint32_t hweight8(uint32_t word)
{
uint32_t count = 0;
while (word)
{
if (word & 0x1)
count++;
word >>= 1;
}
return count;
}
/**
* @brief Calculate the quotient and the remainder of an integer division.
*/
uint64_t do_div(uint64_t *n,
uint64_t base)
{
uint64_t mod = 0;
mod = *n % base;
*n = *n / base;
return mod;
}
/**
* @brief Unsigned 64bit divide with 64bit divisor and remainder
*/
uint64_t div64_u64_rem(uint64_t dividend, uint64_t divisor, uint64_t *remainder)
{
*remainder = dividend % divisor;
return dividend / divisor;
}
/**
* @brief Unsigned 64bit divide with 32bit divisor with remainder
*/
uint64_t div_u64_rem(uint64_t dividend, uint32_t divisor, uint32_t *remainder)
{
*remainder = do_div(&dividend, divisor);
return dividend;
}
/**
* @brief Signed 64bit divide with 32bit divisor with remainder
*/
int64_t div_s64_rem(int64_t dividend, int32_t divisor, int32_t *remainder)
{
*remainder = dividend % divisor;
return dividend / divisor;
}
/**
* @brief Unsigned 64bit divide with 32bit divisor
*/
uint64_t div_u64(uint64_t dividend, uint32_t divisor)
{
uint32_t remainder;
return div_u64_rem(dividend, divisor, &remainder);
}
/**
* @brief Signed 64bit divide with 32bit divisor
*/
int64_t div_s64(int64_t dividend, int32_t divisor)
{
int32_t remainder;
return div_s64_rem(dividend, divisor, &remainder);
}
/**
* @brief Converts from string to int32_t
* @param *str
* @return int32_t
*/
int32_t str_to_int32(const char *str)
{
char *end;
int32_t value = strtol(str, &end, 0);
if (end == str)
return FAILURE;
else
return value;
}
/**
* @brief Converts from string to uint32_t
* @param *str
* @return uint32_t
*/
uint32_t srt_to_uint32(const char *str)
{
char *end;
uint32_t value = strtoul(str, &end, 0);
if (end == str)
return FAILURE;
else
return value;
}
/** @} */