#ifndef _KIT_MACRO_H_
#define _KIT_MACRO_H_
#ifdef __cplusplus
extern "C"
{
#endif

#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>

    typedef enum
    {
        kKit_Ret_Ok = 0x00,
        kKit_Ret_Error,
        kKit_Ret_Null,
        kKit_Ret_TimeOut,
        kKit_Ret_OutRange,

        kKit_Ret_NullPtr,
        kKit_Ret_ParamErr,
        kKit_Ret_CheckErr,
        kKit_Ret_OverFlow,
    } kit_ret_e;

#define USE_BIT_ARRAY false
#define KIT_ABS(a) (((a) < 0) ? (-(a)) : (a))
#define KIT_ABS_DIFF(a, b) (((a) > (b)) ? ((a) - (b)) : ((b) - (a)))
#define KIT_MAX(a, b) (((a) > (b)) ? (a) : (b))
#define KIT_MIN(a, b) (((a) < (b)) ? (a) : (b))

#if (USE_BIT_ARRAY == true)
    extern const uint32_t bit_array[];
#define KIT_BIT_MASK_32(pos) bit_array[bit]
#else
#define KIT_BIT_MASK_32(pos) ((uint32_t)0x01u << (pos))
#define KIT_BIT_MASK_64(pos) ((uint64_t)0x01u << (pos))
#endif

#define KIT_GET_BIT_VAL(val, pos) (((val) >> (pos)) & 0x01u)

#define KIT_SET_BIT_MASK_32_AT_POS(val, pos, bit) ((val) |= ((bit) << (pos)))
#define KIT_BIT_MASK_32S(start, end) ((0xFFFFFFFFu << (start)) & (0xFFFFFFFFu >> (31u - (uint32_t)(end))))
#define KIT_SET_BIT_MASK_32(val, pos) ((val) |= KIT_BIT_MASK_32(pos))
#define KIT_SET_BIT_MASK_64(val, pos) ((val) |= KIT_BIT_MASK_64(pos))
#define KIT_CLR_BIT_32(val, pos) ((val) &= ~KIT_BIT_MASK_32(pos))
#define KIT_CLR_BIT_64(val, pos) ((val) &= ~KIT_BIT_MASK_64(pos))
#define KIT_GET_BIT_32(val, pos) ((val) & KIT_BIT_MASK_32(pos))
#define KIT_GET_BIT_64(val, pos) ((val) & KIT_BIT_MASK_64(pos))
#define KIT_TOGGLE_BIT(val, mask) ((val) ^= (mask))
#define KIT_BIT_MASK_64S(start, end) ((0xFFFFFFFFFFFFFFFFu << (start)) & (0xFFFFFFFFFFFFFFFFu >> (63u - (uint32_t)(end))))
    // #define KIT_IS_BIT_SET(val, mask)		(((val) & (mask)) == (mask))
    // #define KIT_IS_BIT_CLR(val, mask)		(((val) & (mask)) == 0u)

#define KIT_CREATE_IP(ip1, ip2, ip3, ip4) ((ip1) + ((uint32_t)(ip2) << 8) + ((uint32_t)(ip3) << 16) + ((uint32_t)(ip4) << 24))
#define KIT_CUR_CONVERT(val) ((val * 10))
#define KIT_TEMP_CONVERT(val) ((val + 50) * 10)
#define KIT_MILLI_CONVERT(val) (val)
#define KIT_SECOND_CONVERT(val) ((val) * 1000)
#define KIT_MINUTE_CONVERT(val) (KIT_SECOND_CONVERT(val) * 60)
#define KIT_HOUR_CONVERT(val) (KIT_MINUTE_CONVERT(val) * 60)

#define READ_BT_INT8U(ADDRESS, POS) (POS++, ADDRESS[POS - 1])
#define READ_BT_INT16U(ADDRESS, POS) (POS += 2, (ADDRESS[POS - 1]) + ((uint16_t)(ADDRESS[POS - 2]) << 8))
#define READ_BT_INT16U_BY_CONST_POS(ADDRESS, POS) ((ADDRESS[POS + 1]) + ((uint16_t)(ADDRESS[POS]) << 8))
#define READ_BT_INT24U(ADDRESS, POS) (POS += 3, (ADDRESS[POS - 1]) + ((uint32_t)(ADDRESS[POS - 2]) << 8) + ((uint32_t)(ADDRESS[POS - 3]) << 16))
#define READ_BT_INT24U_BY_CONST_POS(ADDRESS, POS) ((ADDRESS[POS + 2]) + ((uint32_t)(ADDRESS[POS + 1]) << 8) + ((uint32_t)(ADDRESS[POS]) << 16))
#define READ_BT_INT32U(ADDRESS, POS) (POS += 4, (ADDRESS[POS - 1]) + ((uint32_t)(ADDRESS[POS - 2]) << 8) + ((uint32_t)(ADDRESS[POS - 3]) << 16) + ((uint32_t)(ADDRESS[POS - 4]) << 24))
#define READ_BT_INT32U_BY_CONST_POS(ADDRESS, POS) ((ADDRESS[POS + 3]) + ((uint32_t)(ADDRESS[POS + 2]) << 8) + ((uint32_t)(ADDRESS[POS + 1]) << 16) + ((uint32_t)(ADDRESS[POS]) << 24))

#define READ_LT_INT8U(ADDRESS, POS) (POS++, ADDRESS[POS - 1])
#define READ_LT_INT16U(ADDRESS, POS) (POS += 2, (ADDRESS[POS - 2]) + ((uint16_t)(ADDRESS[POS - 1]) << 8))
#define READ_LT_INT24U(ADDRESS, POS) (POS += 3, (ADDRESS[POS - 3]) + ((uint32_t)(ADDRESS[POS - 2]) << 8) + ((uint32_t)(ADDRESS[POS - 1]) << 16))
#define READ_LT_INT32U(ADDRESS, POS) (POS += 4, (ADDRESS[POS - 4]) + ((uint32_t)(ADDRESS[POS - 3]) << 8) + ((uint32_t)(ADDRESS[POS - 2]) << 16) + ((uint32_t)(ADDRESS[POS - 1]) << 24))

#define READ_LT_INT8U_BY_CONST_POS(ADDRESS, POS) (ADDRESS[POS])
#define READ_LT_INT16U_BY_CONST_POS(ADDRESS, POS) ((ADDRESS[POS]) + ((uint16_t)(ADDRESS[POS + 1]) << 8))
#define READ_LT_INT24U_BY_CONST_POS(ADDRESS, POS) ((ADDRESS[POS]) + ((uint32_t)(ADDRESS[POS + 1]) << 8) + ((uint32_t)(ADDRESS[POS + 2]) << 16))
#define READ_LT_INT32U_BY_CONST_POS(ADDRESS, POS) ((ADDRESS[POS]) + ((uint32_t)(ADDRESS[POS + 1]) << 8) + ((uint32_t)(ADDRESS[POS + 2]) << 16) + ((uint32_t)(ADDRESS[POS + 3]) << 24))

#define WRITE_BT_INT8U(ADDRESS, POS, VALUE) \
    {                                       \
        ADDRESS[POS++] = (uint8_t)(VALUE);  \
    }
#define WRITE_BT_INT16U(ADDRESS, POS, VALUE)      \
    {                                             \
        ADDRESS[POS++] = (uint8_t)((VALUE) >> 8); \
        ADDRESS[POS++] = (uint8_t)(VALUE & 0xFF); \
    }
#define WRITE_BT_INT24U(ADDRESS, POS, VALUE)       \
    {                                              \
        ADDRESS[POS++] = (uint8_t)((VALUE) >> 16); \
        ADDRESS[POS++] = (uint8_t)((VALUE) >> 8);  \
        ADDRESS[POS++] = (uint8_t)(VALUE & 0xFF);  \
    }
#define WRITE_BT_INT32U(ADDRESS, POS, VALUE)       \
    {                                              \
        ADDRESS[POS++] = (uint8_t)((VALUE) >> 24); \
        ADDRESS[POS++] = (uint8_t)((VALUE) >> 16); \
        ADDRESS[POS++] = (uint8_t)((VALUE) >> 8);  \
        ADDRESS[POS++] = (uint8_t)(VALUE & 0xFF);  \
    }

#define WRITE_BT_INT16U_BY_CONST_POS(ADDRESS, POS, VALUE) \
    {                                                     \
        ADDRESS[POS] = (uint8_t)((VALUE) >> 8);           \
        ADDRESS[POS + 1] = (uint8_t)(VALUE & 0xFF);       \
    }
#define WRITE_BT_INT32U_BY_CONST_POS(ADDRESS, POS, VALUE) \
    {                                                     \
        ADDRESS[POS] = (uint8_t)((VALUE) >> 24);          \
        ADDRESS[POS + 1] = (uint8_t)((VALUE) >> 16);      \
        ADDRESS[POS + 2] = (uint8_t)((VALUE) >> 8);       \
        ADDRESS[POS + 3] = (uint8_t)(VALUE & 0xFF);       \
    }

#define WRITE_LT_INT32U(ADDRESS, POS, VALUE)       \
    {                                              \
        ADDRESS[POS++] = (uint8_t)(VALUE);         \
        ADDRESS[POS++] = (uint8_t)((VALUE) >> 8);  \
        ADDRESS[POS++] = (uint8_t)((VALUE) >> 16); \
        ADDRESS[POS++] = (uint8_t)((VALUE) >> 24); \
    }
#define WRITE_LT_INT24U(ADDRESS, POS, VALUE)       \
    {                                              \
        ADDRESS[POS++] = (uint8_t)(VALUE);         \
        ADDRESS[POS++] = (uint8_t)((VALUE) >> 8);  \
        ADDRESS[POS++] = (uint8_t)((VALUE) >> 16); \
    }
#define WRITE_LT_INT16U(ADDRESS, POS, VALUE)      \
    {                                             \
        ADDRESS[POS++] = (uint8_t)(VALUE);        \
        ADDRESS[POS++] = (uint8_t)((VALUE) >> 8); \
    }
#define WRITE_LT_INT8U(ADDRESS, POS, VALUE) \
    {                                       \
        ADDRESS[POS++] = (uint8_t)(VALUE);  \
    }

#define WRITE_LT_INT32U_WITH_BUFF_SIZE(ADDRESS, POS, VALUE, SIZE) \
    {                                                             \
        if (POS + 3 < SIZE)                                       \
            WRITE_LT_INT32U(ADDRESS, POS, VALUE);                 \
    }
#define WRITE_LT_INT24U_WITH_BUFF_SIZE(ADDRESS, POS, VALUE, SIZE) \
    {                                                             \
        if (POS + 2 < SIZE)                                       \
            WRITE_LT_INT24U(ADDRESS, POS, VALUE);                 \
    }
#define WRITE_LT_INT16U_WITH_BUFF_SIZE(ADDRESS, POS, VALUE, SIZE) \
    {                                                             \
        if (POS + 1 < SIZE)                                       \
            WRITE_LT_INT16U(ADDRESS, POS, VALUE);                 \
    }
#define WRITE_LT_INT8U_WITH_BUFF_SIZE(ADDRESS, POS, VALUE, SIZE) \
    {                                                            \
        if (POS < SIZE)                                          \
            WRITE_LT_INT8U(ADDRESS, POS, VALUE);                 \
    }

#define WRITE_LT_INT16U_BY_CONST_POS(ADDRESS, POS, VALUE) \
    {                                                     \
        ADDRESS[POS] = (uint8_t)(VALUE);                  \
        ADDRESS[POS + 1] = (uint8_t)((VALUE) >> 8);       \
    }
#define WRITE_LT_INT24U_BY_CONST_POS(ADDRESS, POS, VALUE) \
    {                                                     \
        ADDRESS[POS] = (uint8_t)(VALUE);                  \
        ADDRESS[POS + 1] = (uint8_t)((VALUE) >> 8);       \
        ADDRESS[POS + 2] = (uint8_t)((VALUE) >> 16);      \
    }
#define WRITE_LT_INT32U_BY_CONST_POS(ADDRESS, POS, VALUE) \
    {                                                     \
        ADDRESS[POS] = (uint8_t)(VALUE);                  \
        ADDRESS[POS + 1] = (uint8_t)((VALUE) >> 8);       \
        ADDRESS[POS + 2] = (uint8_t)((VALUE) >> 16);      \
        ADDRESS[POS + 3] = (uint8_t)((VALUE) >> 24);      \
    }

#define ARM_READ_INT16U(addr) *((uint16_t *)(addr))
#define ARM_READ_INT32U(addr) *((uint32_t *)(addr))

#define ARM_WRITE_INT32U(addr) *((uint32_t *)(addr))

    typedef void (*NoArgFuncCall)(void);
    typedef void (*VoidArgFunCall)(void *arg);
    typedef void (*UintArgFunCall)(uint32_t arg);
    typedef void (*KitIrqCall)(kit_ret_e res, void *data);
    typedef void (*UintArgFunCall2)(kit_ret_e res, uint32_t data);

#ifdef __cplusplus
}
#endif

#endif