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.
179 lines
4.4 KiB
179 lines
4.4 KiB
/*
|
|
******************************************************************************
|
|
* @copyright Copyright (C), 2023-2023, ConvenientPower. Co., Ltd.
|
|
* @file util.h
|
|
* @brief Utility Macros and Functions
|
|
******************************************************************************
|
|
*/
|
|
|
|
#ifndef UTIL_H
|
|
#define UTIL_H
|
|
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
|
|
#ifndef ARRAY_LEN
|
|
#define ARRAY_LEN(x) (sizeof(x) / sizeof((x)[0]))
|
|
#endif
|
|
|
|
#ifndef BIT
|
|
#define BIT(n) (1ul << (n))
|
|
#endif
|
|
|
|
#ifndef MIN
|
|
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
|
#endif
|
|
|
|
#ifndef MAX
|
|
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
|
#endif
|
|
|
|
#define time_diff(_a, _b) ((int32_t)((uint32_t)(_a) - (uint32_t)(_b)))
|
|
#define time_after(_a, _b) (time_diff((_a), (_b)) > 0)
|
|
#define time_after_eq(_a, _b) (time_diff((_a), (_b)) >= 0)
|
|
#define time_before(_a, _b) time_after(_b, _a)
|
|
#define time_before_eq(_a, _b) time_after_eq(_b, _a)
|
|
|
|
#define CLAMP(value, min, max) ((value) < (min) ? (min) : ((value) > (max) ? (max) : (value)))
|
|
#define CLAMP_HIGH(value, max) ((value) > (max) ? (max) : (value))
|
|
#define CLAMP_LOW(value, min) ((value) < (min) ? (min) : (value))
|
|
|
|
#define FLOAT_TO_INT_MUL(x, float_y, shift_bit) \
|
|
(((x) * ((int32_t)((float_y) * (1 << (shift_bit))))) >> (shift_bit))
|
|
|
|
static inline uint32_t get_sys_time(void)
|
|
{
|
|
extern volatile uint32_t g_systick_cnt;
|
|
|
|
return g_systick_cnt;
|
|
}
|
|
|
|
static inline void register_mask_set(volatile uint32_t *reg, uint32_t mask,
|
|
uint32_t val)
|
|
{
|
|
uint32_t reg_val;
|
|
|
|
reg_val = *reg;
|
|
reg_val &= ~mask;
|
|
reg_val |= (val) & mask;
|
|
|
|
*reg = reg_val;
|
|
}
|
|
|
|
/*
|
|
* Debouncer
|
|
*/
|
|
typedef struct debouncer
|
|
{
|
|
uint16_t cnt;
|
|
uint16_t out;
|
|
} debouncer_s;
|
|
|
|
typedef struct debouncer_param
|
|
{
|
|
uint16_t up_time;
|
|
uint16_t down_time;
|
|
} debouncer_param_s;
|
|
|
|
bool __debounce(debouncer_s *obj, bool in, uint16_t up_time, uint16_t down_time);
|
|
|
|
static inline bool debounce(debouncer_s *obj, bool in, const debouncer_param_s *param)
|
|
{
|
|
return __debounce(obj, in, param->up_time, param->down_time);
|
|
}
|
|
|
|
static inline bool debouncer_out(debouncer_s *obj)
|
|
{
|
|
return obj->out;
|
|
}
|
|
|
|
static inline void __init_debouncer(debouncer_s *obj, uint16_t initial_cnt, bool initial_output)
|
|
{
|
|
obj->cnt = initial_cnt;
|
|
obj->out = initial_output;
|
|
}
|
|
|
|
void init_debouncer(debouncer_s *obj, bool initial_output, const debouncer_param_s *param);
|
|
|
|
#define DEBOUNCER_INIT(initial_cnt, initial_output) \
|
|
{ \
|
|
.cnt = (initial_cnt), .out = (initial_output), \
|
|
}
|
|
|
|
typedef struct debouncer_ext
|
|
{
|
|
debouncer_s base;
|
|
debouncer_param_s param;
|
|
} debouncer_ext_s;
|
|
|
|
bool debounce_ext(debouncer_ext_s*obj, bool in);
|
|
|
|
static inline bool debouncer_ext_out(debouncer_ext_s *obj)
|
|
{
|
|
return obj->base.out;
|
|
}
|
|
|
|
#define DEBOUNCER_EXT_INIT(initial_output, _up_time, _down_time) \
|
|
{ \
|
|
.base = DEBOUNCER_INIT((initial_output) ? (_down_time) : (_up_time), initial_output), \
|
|
.param = \
|
|
{ \
|
|
.down_time = (_down_time), \
|
|
.up_time = (_up_time), \
|
|
}, \
|
|
}
|
|
|
|
static inline void debouncer_ext_force_set_out(debouncer_ext_s *obj, bool out)
|
|
{
|
|
obj->base.out = out;
|
|
obj->base.cnt = out ? obj->param.down_time : obj->param.up_time;
|
|
}
|
|
|
|
/*
|
|
* Schmitt trigger
|
|
*/
|
|
|
|
typedef struct schmitt_trigger
|
|
{
|
|
uint16_t high_thresh;
|
|
uint16_t low_thresh;
|
|
} schmitt_trigger_s;
|
|
|
|
#define SCHMITT_TRIGGER_INIT(high, low) \
|
|
{ \
|
|
.high_thresh = (high), \
|
|
.low_thresh = (low), \
|
|
}
|
|
|
|
static inline bool schmitt_process(const schmitt_trigger_s *obj, uint16_t input, bool prev_state)
|
|
{
|
|
return prev_state ? input > obj->low_thresh : input >= obj->high_thresh;
|
|
}
|
|
|
|
static inline bool schmitt_process_inverse(const schmitt_trigger_s *obj, uint16_t input, bool prev_state)
|
|
{
|
|
return prev_state ? input < obj->high_thresh : input <= obj->low_thresh;
|
|
}
|
|
|
|
/*
|
|
* RAMP
|
|
*/
|
|
|
|
#define RAMP(var, target, max_step) \
|
|
((target) > (var) ? \
|
|
(((var) + (max_step) > (target)) ? (target) : (var) + (max_step)) : \
|
|
(((var) < (target) + (max_step))? (target) : (var) - (max_step)))
|
|
|
|
/*
|
|
* Bitwise Operations
|
|
*/
|
|
|
|
uint8_t count_set_bits(uint32_t n);
|
|
|
|
#define FOREACH_BIT_U32(value, pos) \
|
|
for(uint32_t temp = (value), pos = __builtin_ffs(temp) - 1; temp != 0; temp &= (temp - 1), pos = __builtin_ffs(temp) - 1)
|
|
|
|
void enter_critical_section(void);
|
|
void exit_critical_section(void);
|
|
|
|
#endif /* UTIL_H */
|
|
|