#ifndef HW_LIB_TOOL_H
#define HW_LIB_TOOL_H
#ifdef __cplusplus
extern "C" {
#endif
typedef unsigned int u32;
typedef unsigned short u16;
typedef unsigned char u8;
typedef int s32;
typedef short int s16;
typedef char s8;
typedef union {
    int i;
    char c[4];
    float f;
    s8 s8[4];
    s16 s16[2];
    s32 s32;
    u8 u8[4];
    u16 u16[2];
    u32 u32;
} Data32_t;

typedef union {
    char c[2];
    s8 s8[2];
    s16 s16;
    u8 u8[2];
    u16 u16;
} Data16_t;
typedef enum {  // 定义枚举类型Type_t,包含不同数据类型
    T_U8,  // 无符号8位整数
    T_U16,  // 无符号16位整数
    T_U32,  // 无符号32位整数

    T_CHAR,  // 字符
    T_SHORT,  // 短整数
    T_INT,  // 整数

    T_FLOAT,  // 浮点数
    T_DOUBLE,  // 双精度浮点数
} Type_t;

#define TYPE_T(v) _Generic((v), \
    u8 *:0,u16 *:1,u32 *:2,     \
    char *:3,short *:4,int *:5, \
    float *:6,double *:7,      \
    default: ((void)0))

#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))  // 计算数组的元素个数
//#define in ,  // 定义逗号为in
#define _foreach(e, a) for(size_t e = 0; e < ARRAY_SIZE(a); e++)  // 实现foreach宏,遍历数组a,e为当前元素下标
#define foreach(exp) _foreach(exp)  // 定义foreach宏,用于遍历数组

#define _VA_ARGS_N(_9, _8, _7, _6, _5, _4, _3, _2, _1, _0, N, ...) N
#define VA_ARGS_N(...) _VA_ARGS_N(0 __VA_OPT__(,) __VA_ARGS__, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
#define _range_1(var, n) (size_t var = 0; var < n; var++)  // 定义范围循环,从0到n-1
#define _range_2(var, a, b) (size_t var = a; var < b; var++)  // 定义范围循环,从a到b-1
#define _range_3(var, start, stop, step) (size_t var = start; var < stop; var += step)  // 定义范围循环,从start开始,每次增加step,直到stop
#define _range_n_cat(a, b) a ## b
#define _range_n(n) _range_n_cat(_range_, n)
#define _range(...) _range_n(VA_ARGS_N(__VA_ARGS__))  // 根据传入参数个数选择对应的范围循环宏
/**
 * @Name    范围循环
 * @brief   根据传入参数个数生成不同范围的遍历
 * @param   val: [输入]      循环变量
 * @param   a: [输入]    0到a-1
 * @param   b: [输入]    a到b-1
 * @param   c: [输入]    a到b-1,布进c
 * @retval    需求处理值
 * @example range(i, 10) → (size_t i = 0; i < 10; i++)
 * @example range(c, 1, 10) → (size_t c = 1; c < 10; c++)
 * @example range(n, 10, 32, 3) → (size_t n = 10; n < 32; n += 3)
 **/
#define range(var, ...) for _range(__VA_ARGS__)(var, __VA_ARGS__)  // 定义范围循环,传入循环变量和参数

/**
 * @Name    Mapping
 * @brief   数据映射(缩放)
 * @param   val: [输入]        数据采集值
 * @param   I_Min: [输入]    数据最小值
 * @param   I_Max: [输入]    数据最大值
 * @param   O_Min: [输入]    需求最小值
 * @param   O_Max: [输入]    需求最小值
 * @return    需求处理值
 * @example Mapping(128,0,4096,0.0,3.3) //0.10
 *            ADC采集引脚电压
 **/
float Mapping(float val, float I_Min, float I_Max, float O_Min, float O_Max);

/**
 * @brief   数组内容HEX打印
 * @param   name: [输入]     标识名
 * @param   buf: [输入]      数组
 * @param   len: [输入]      数组长度
 * @param   frame: [输入]    断帧大小
 * @return  void
 * @example BufPrint("TX", buf, 64, 16); //将长64的buf以16个数据断帧打印
 **/
#define Buf_Print(n, b, l, f) BufPrint(n,b,TYPE_T(b),l,f)

/**
 * @brief   数组内容HEX打印
 * @param   name: [输入]     标识名
 * @param   buf: [输入]      数组
 * @param   size: [输入]     数组类型 Type_t[U8,U16,U32,CHAR,SHORT,INT...]
 * @param   len: [输入]      数组长度
 * @param   frame: [输入]    断帧大小
 * @return  void
 * @example BufPrint("TX", buf, 8, 64, 16); //将长64的8位buf以16个数据断帧打印
 **/
void BufPrint(char *name, void *buf, Type_t type, unsigned int len, unsigned char frame);

/**
 * @brief   字符串转浮点数
 * @param   str: [输入]     输入的字符串
 * @return  float          转换后的浮点数
 * @example Str2Float("3.14");
 **/
float Str2Float(char *str);

/**
 * @brief   数组内容打印
 * @param   arr: [输入]     标识名数组
 * @param   fmt: [输入]     格式化字段
 * @param   frame: [输入]    断帧大小
 * @return  void
 * @example BufPrint("TX", buf, 8, 64, 16); //将长64的8位buf以16个数据断帧打印
 **/
#define PRINT_ARRAY(arr, fmt, frame) do {  \
    printf("\n"#arr ":\n");  \
    _foreach(i,arr) {\
        if(i%frame==0&&i!=0) printf("\n");\
        printf(fmt " ", arr[i]);  }\
    printf("\n"); } while (0)

/**
 * @brief   测试函数执行时间
 * @param   name: [输入]     测试名称
 * @param   pFunction: [输入]     指向待测试函数的指针
 * @return  void
 * @example Test("FunctionName", functionName);
**/
void Test_RunTime(char *name, void (*pFunction)());

#define END "\n"
#define TYPE_F(v) _Generic((v), \
char :"[char]-> "#v"=%c" END,           \
short :"[short]-> "#v"=%d" END,         \
int :"[int]-> "#v"=%d" END,             \
float :"[float]-> "#v"=%.2f" END ,       \
double :"[double]-> "#v"=%.2f" END,     \
default: "[err]-> "#v"=%p" END)
#define POUT(s) printf(TYPE_F(s) ,s)

#define    GET_BIT(x, bit)    ((x & (1 << bit)) >> bit)

#ifdef __cplusplus
}
#endif
#endif //HW_LIB_TOOL_H