bleSDK_expansion_board/ble/api/utils.h

535 lines
17 KiB
C

/**
****************************************************************************************
*
* @file utils.h
*
* @brief Common Utilities definitions (functions and macros).
*
****************************************************************************************
*/
#ifndef _UTILS_H_
#define _UTILS_H_
/*
* INCLUDE FILES
****************************************************************************************
*/
#include <stdint.h>
#include <stddef.h>
#include <stdlib.h>
#ifndef __INLINE__
#define __INLINE__ __forceinline static
#endif
#ifndef ASSERT_ERR
/// Assertions showing a critical error
#define ASSERT_ERR(cond)
/// Assertions showing a critical info
#define ASSERT_INFO(cond, param0, param1)
/// Assertions showing a non-critical problem
#define ASSERT_WARN(cond, param0, param1)
/// DUMP data array present in the SW.
#define DUMP_DATA(data, length)
#endif
/*
* MACRO
****************************************************************************************
*/
/// Value with one bit set
#ifndef BIT
#define BIT(pos) (1UL<<(pos))
#endif
#define IS_POWER2(n) ((n) && !((n) & (n-1)))
/// Number of '1' bits in a byte
#define NB_1BITS(byte) popcnt8(byte)
#define ONE_BITS(byte) NB_1BITS(byte)
/// Get the number of elements within an array
#define ARRAY_LEN(array) (sizeof((array))/sizeof((array)[0]))
/// maroc to Get a structure from one of its structure field
#define CONTAINER_OF(ptr, type, member) ((type *)((char *)ptr - offsetof(type,member)))
/// Bit checking
#define CHKF(flag, mask) (((flag)&(mask)) == mask)
/// Get a field from a value containing several fields
/// @param[in] __r bit field value
/// @param[in] __f field name(_MASK & _LSB)
/// @return the value of the register masked and shifted
#define GETF(__r, __f) (( (__r) & (__f##_MASK) ) >> (__f##_LSB))
/// Set a field value into a value containing several fields.
/// @param[in] __r bit field value
/// @param[in] __f field name(_MASK & _LSB)
/// @param[in] __v value to put in field
#define SETF(__r, __f, __v) \
do { \
ASSERT_ERR( ( ( ( (__v) << (__f##_LSB) ) & ( ~(__f##_MASK) ) ) ) == 0); \
__r = (((__r) & ~(__f##_MASK)) | (__v) << (__f##_LSB)); \
} while (0)
/// Get a bit field from a value containing several fields
/// @param[in] __r bit field value
/// @param[in] __b bit field name(_BIT & _POS)
/// @return the value of the register masked and shifted
#define GETB(__r, __b) (( (__r) & (__b##_BIT) ) >> (__b##_POS))
/// set a bit field value into a value containing several fields.
/// @param[in] __r bit field value
/// @param[in] __b bit field name
/// @param[in] __v value to put in field
#define SETB(__r, __b, __v) \
do { \
ASSERT_ERR( ( ( ( (__v) << (__b##_POS) ) & ( ~(__b##_BIT) ) ) ) == 0 ); \
__r = (((__r) & ~(__b##_BIT)) | (__v) << (__b##_POS)); \
} while (0)
/// Align value on the multiple of 4 equal or nearest higher.
/// @param[in] val Value to align.
#define ALIGN4_HI(_val) (((_val) + 3) & ~3)
/// Align value on the multiple of 4 equal or nearest lower.
/// * @param[in] _val Value to align.
#define ALIGN4_LO(_val) ((_val) & ~3)
/// @brief Align value on the multiple of 2 equal or nearest higher.
/// * @param[in] _val Value to align.
#define ALIGN2_HI(_val) (((_val) + 1) & ~1)
/// @brief Align value on the multiple of 2 equal or nearest lower.
/// * @param[in] _val Value to align.
#define ALIGN2_LO(_val) ((_val) & ~1)
/// Perform a modulo(%) operation
/// @param[in] _val Dividend
/// @param[in] _div Divisor
#define MOD(_val, _div) ((_val) % (_div))
/// Perform a division and ceil up the result
/// * @param[in] _val Value to divide
/// * @param[in] _div Divide value
#define DIV_CEIL(_val, _div) (((_val) + ((_div) - 1))/ (_div))
/// Perform a division and round the result
/// @param[in] _val Value to divide
/// @param[in] _div Divide value
#define DIV_ROUND(_val, _div) (((_val) + ((_div) >> 1))/ (_div))
/// Increment value (wrap to 0 if reach max)
/// * @param[in] _val Value to inc
/// * @param[in] _max Max Range
#define VAL_INC(_val, _max) \
(_val) = (_val) + 1; \
if ((_val) >= (_max)) (_val) = 0
/*
* FUNCTION DECLARATIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Function to initialize the random seed.
* @param[in] seed The seed number to use to generate the random sequence.
****************************************************************************************
*/
__INLINE__ void rand_init(uint32_t seed)
{
srand(seed);
}
/**
****************************************************************************************
* @brief Function to get an 8 bit random number.
* @return Random byte value.
****************************************************************************************
*/
__INLINE__ uint8_t rand_byte(void)
{
return (uint8_t)(rand() & 0xFF);
}
/**
****************************************************************************************
* @brief Function to get an 16 bit random number.
* @return Random half word value.
****************************************************************************************
*/
__INLINE__ uint16_t rand_hword(void)
{
return (uint16_t)(rand() & 0xFFFF);
}
/**
****************************************************************************************
* @brief Function to get an 32 bit random number.
* @return Random word value.
****************************************************************************************
*/
__INLINE__ uint32_t rand_word(void)
{
return (uint32_t)rand();
}
/**
****************************************************************************************
* @brief Read an aligned 32 bit word.
* @param[in] ptr32 The address of the first byte of the 32 bit word.
* @return The 32 bit value.
****************************************************************************************
*/
__INLINE__ uint32_t read32(const void *ptr32)
{
return *((uint32_t*)ptr32);
}
/**
****************************************************************************************
* @brief Read an aligned 16 bits word.
* @param[in] ptr16 The address of the first byte of the 16 bits word.
* @return The 16 bits value.
****************************************************************************************
*/
__INLINE__ uint16_t read16(const void *ptr16)
{
return *((uint16_t*)ptr16);
}
/**
****************************************************************************************
* @brief Write an aligned 32 bits word.
* @param[in] ptr32 The address of the first byte of the 32 bits word.
* @param[in] value The value to write.
****************************************************************************************
*/
__INLINE__ void write32(const void *ptr32, uint32_t value)
{
*(uint32_t*)ptr32 = value;
}
/**
****************************************************************************************
* @brief Write an aligned 16 bits word.
* @param[in] ptr16 The address of the first byte of the 16 bits word.
* @param[in] value The value to write.
****************************************************************************************
*/
__INLINE__ void write16(const void *ptr16, uint32_t value)
{
*(uint16_t*)ptr16 = value;
}
/**
****************************************************************************************
* @brief Write a 8 bits word.
* @param[in] ptr8 The address of the first byte of the 8 bits word.
* @param[in] value The value to write.
****************************************************************************************
*/
__INLINE__ void write8(const void *ptr8, uint32_t value)
{
*(uint8_t*)ptr8 = value;
}
/**
****************************************************************************************
* @brief Read a packed 16 bits word.
* @param[in] ptr16 The address of the first byte of the 16 bits word.
* @return The 16 bits value.
****************************************************************************************
*/
__INLINE__ uint16_t read16p(const void *ptr16)
{
uint16_t value = ((uint8_t *)ptr16)[0] | ((uint8_t *)ptr16)[1] << 8;
return value;
}
/**
****************************************************************************************
* @brief Write a packed 16 bits word.
* @param[in] ptr16 The address of the first byte of the 16 bits word.
* @param[in] value The value to write.
****************************************************************************************
*/
__INLINE__ void write16p(const void *ptr16, uint16_t value)
{
uint8_t *ptr=(uint8_t*)ptr16;
*ptr++ = value&0xff;
*ptr = (value&0xff00)>>8;
}
/**
****************************************************************************************
* @brief Read a packed 24 bits word.
* @param[in] ptr24 The address of the first byte of the 24 bits word.
* @return The 24 bits value.
****************************************************************************************
*/
__INLINE__ uint32_t read24p(const void *ptr24)
{
uint16_t addr_l, addr_h;
addr_l = read16p(ptr24);
addr_h = *((uint8_t *)ptr24 + 2) & 0x00FF;
return ((uint32_t)addr_l | (uint32_t)addr_h << 16);
}
/**
****************************************************************************************
* @brief Write a packed 24 bits word.
* @param[in] ptr24 The address of the first byte of the 24 bits word.
* @param[in] value The value to write.
****************************************************************************************
*/
__INLINE__ void write24p(const void *ptr24, uint32_t value)
{
uint8_t *ptr=(uint8_t*)ptr24;
*ptr++ = (uint8_t)(value&0xff);
*ptr++ = (uint8_t)((value&0xff00)>>8);
*ptr++ = (uint8_t)((value&0xff0000)>>16);
}
/**
****************************************************************************************
* @brief Read a packed 32 bits word.
* @param[in] ptr32 The address of the first byte of the 32 bits word.
* @return The 32 bits value.
****************************************************************************************
*/
__INLINE__ uint32_t read32p(const void *ptr32)
{
uint16_t addr_l, addr_h;
addr_l = read16p(ptr32);
addr_h = read16p((uint8_t *)ptr32 + 2);
return ((uint32_t)addr_l | (uint32_t)addr_h << 16);
}
/**
****************************************************************************************
* @brief Write a packed 32 bits word.
* @param[in] ptr32 The address of the first byte of the 32 bits word.
* @param[in] value The value to write.
****************************************************************************************
*/
__INLINE__ void write32p(const void *ptr32, uint32_t value)
{
uint8_t *ptr=(uint8_t*)ptr32;
*ptr++ = (uint8_t)(value&0xff);
*ptr++ = (uint8_t)((value&0xff00)>>8);
*ptr++ = (uint8_t)((value&0xff0000)>>16);
*ptr = (uint8_t)((value&0xff000000)>>24);
}
/**
****************************************************************************************
* @brief Reads a 16-bit word in an array
* @param[in] ptr16 The address of the first byte of the 16 bits word.
* @return The 16 bits value.
****************************************************************************************
*/
__INLINE__ uint16_t read16Swap(const void *ptr16)
{
uint16_t value = ((uint8_t *)ptr16)[1] | ((uint8_t *)ptr16)[0] << 8;
return value;
}
/**
****************************************************************************************
* @brief Write a 16-bit word in an array
* @param[in] ptr16 The address of the first byte of the 16 bits word.
* @param[in] value The value to write.
****************************************************************************************
*/
__INLINE__ void write16Swap(const void *ptr16, uint16_t value)
{
uint8_t *ptr=(uint8_t*)ptr16;
*ptr++ = (value&0xff00)>>8;
*ptr = value&0xff;
}
/**
****************************************************************************************
* @brief Count leading zeros.
* @param[in] val Value to count the number of leading zeros on.
* @return Number of leading zeros when value is written as 32 bits.
****************************************************************************************
*/
#if !(USE_ARM_FUNC)
uint32_t co_clz(uint32_t val);
#else
__INLINE__ uint32_t co_clz(uint32_t val)
{
#if defined(__arm__)
return __builtin_clz(val);
#elif defined(__GNUC__)
if (val == 0)
{
return 32;
}
return __builtin_clz(val);
#else
uint32_t i;
for (i = 0; i < 32; i++)
{
if (val & BIT(31 - i))
break;
}
return i;
#endif // defined(__arm__)
}
#endif //(USE_ARM_FUNC)
/**
****************************************************************************************
* @brief Count trailing zeros.
* @param[in] val Value to count the number of trailing zeros on.
* @return Number of trailing zeros when value is written as 32 bits.
****************************************************************************************
*/
#if !(USE_ARM_FUNC)
uint32_t co_ctz(uint32_t val);
#else
__INLINE__ uint32_t co_ctz(uint32_t val)
{
#if defined(__arm__)
return __builtin_ctz(val);
#elif defined(__GNUC__)
if (val == 0)
{
return 32;
}
return __builtin_ctz(val);
#else
uint32_t i;
for (i = 0; i < 32; i++)
{
if (val & BIT(i))
break;
}
return i;
#endif // defined(__arm__)
}
#endif //(USE_ARM_FUNC)
/**
****************************************************************************************
* @brief Count binary ones.
* @param[in] val Value to count the number of ones in the binary representation.
* @return Number of ones when value is written as 32 bits.
****************************************************************************************
*/
#if !(USE_ARM_FUNC)
uint8_t co_ones(uint32_t val);
#else
__INLINE__ uint8_t co_ones(uint32_t val)
{
#if defined(__arm__) || defined(__GNUC__)
return __builtin_popcount(val);
#else
uint32_t i, ones=0;
for (i = 0; i < 32; i++)
{
if (val & BIT(i))
ones++;
}
return ones;
#endif // defined(__arm__)
}
#endif //(USE_ARM_FUNC)
/**
****************************************************************************************
* @brief Count '1' bits in a byte value, repalce NB_1BITS(byte)
* @return Number of '1' bits in a byte
****************************************************************************************
*/
uint8_t popcnt8(uint8_t byte);
/**
****************************************************************************************
* @brief Function to return the smallest of 2 unsigned 32 bits words.
* @return The smallest value.
****************************************************************************************
*/
__INLINE__ uint32_t co_min(uint32_t a, uint32_t b)
{
return a < b ? a : b;
}
/**
****************************************************************************************
* @brief Function to return the smallest of 2 signed 32 bits words.
* @return The smallest value.
****************************************************************************************
*/
__INLINE__ int32_t co_min_s(int32_t a, int32_t b)
{
return a < b ? a : b;
}
/**
****************************************************************************************
* @brief Function to return the greatest of 2 unsigned 32 bits words.
* @return The greatest value.
****************************************************************************************
*/
__INLINE__ uint32_t co_max(uint32_t a, uint32_t b)
{
return a > b ? a : b;
}
/**
****************************************************************************************
* @brief Function to return the absolute value of a signed integer.
* @return The absolute value.
****************************************************************************************
*/
__INLINE__ int co_abs(int val)
{
return val < 0 ? val*(-1) : val;
}
/**
****************************************************************************************
* @brief Perform a modulo operation
* @return val%div
****************************************************************************************
*/
__INLINE__ uint32_t co_mod(uint32_t val, uint32_t div)
{
//ASSERT_ERR(div);
return ((val) % (div));
}
/**
****************************************************************************************
* @brief Function to return the hex char of a 4bit.
* @return The hex char.
****************************************************************************************
*/
__INLINE__ uint8_t co_hex(uint8_t b4)
{
return b4 < 10 ? b4 + '0' : b4 - 10 + 'A';
}
#endif // _UTILS_H_