/* ****************************************************************************** * @copyright Copyright (C), 2023-2023, ConvenientPower. Co., Ltd. * @file util.h * @brief Utility Macros and Functions ****************************************************************************** */ #ifndef UTIL_H #define UTIL_H #include #include #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 */