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

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

typedef enum
{
    kKitResult_Ok = 0x00,
    kKitResult_Error,
    kKitResult_Null,
    kKitResult_TimeOut,
    kKitResult_OutRange,
    
    kKitResult_NullPtr,
    kKitResult_ParamErr,
    kKitResult_CheckErr,
    kKitResult_OverFlow,
}KitResult;

#define USE_BIT_ARRAY           false

typedef void (* NoArgCall) (void);
typedef void (* VoidArgCall) (void *arg);
typedef void (* UintArgCall) (uint32_t arg);
typedef void (* KitIrqCall) (KitResult res, void *data);
typedef void (* UintCall) (KitResult res, uint32_t data);



#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_CREAT_BIT(pos)              bit_array[bit]
#else
#define KIT_CREAT_BIT(pos)			    ((uint32_t)0x01u << (pos))
#define KIT_CREAT_64BIT(pos)			((uint64_t)0x01u << (pos))
#endif

#define KIT_OR_BIT(val, pos, bit)       ((val) |=  ((bit) << (pos)))
#define KIT_CREAT_BITS(start, end)		((0xFFFFFFFFu << (start)) & (0xFFFFFFFFu >> (31u - (uint32_t)(end)))) 
#define KIT_SET_BIT(val,pos)  		    ((val) |=  KIT_CREAT_BIT(pos))
#define KIT_SET_64BIT(val,pos)          ((val) |=  KIT_CREAT_64BIT(pos))
#define KIT_CLR_BIT(val,pos)  		    ((val) &= ~KIT_CREAT_BIT(pos))
#define KIT_CLR_64BIT(val,pos)          ((val) &= ~KIT_CREAT_64BIT(pos))  
#define KIT_GET_BIT(val,pos)  		    ((val) &   KIT_CREAT_BIT(pos)) 
#define KIT_GET_64BIT(val,pos)  		((val) &   KIT_CREAT_64BIT(pos)) 
#define KIT_TOGGLE_BIT(val, mask)		((val) ^= (mask))
#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 KIT_READ_32U_BT(buf, addr)				((buf[(addr) + 3]) + ((uint32_t)(buf[(addr) + 2]) << 8) + ((uint32_t)(buf[(addr) + 1]) << 16) + ((uint32_t)(buf[(addr)]) << 24))
//#define KIT_ADD_READ_16U_BT(buf, addr)			((addr) += 2; READ_BT_INT16U(buf, (addr - 2)))
//#define KIT_ADD_READ_32U_BT(buf, addr)			((addr) += 4; KIT_READ_32U_BT(buf, (addr - 4)))

//#define KIT_WRITE_16U_BT(buf, addr, value)		{buf[(addr)] = (uint8_t)((value) >> 8); buf[(addr) + 1] = (uint8_t)(value);}
//#define KIT_WRITE_32U_BT(buf, addr, value)		{buf[(addr)] = (uint8_t)((value) >> 24); buf[(addr) + 1] = (uint8_t)((value) >> 16); buf[(addr) + 2] = (uint8_t)((value) >> 8); buf[(addr) + 3] = (uint8_t)(value);}
//#define KIT_ADD_WRITE_16U_BT(buf, addr, value)	{buf[addr++] = (uint8_t)((value) >> 8); buf[addr++] = (uint8_t)(value);}
//#define KIT_ADD_WRITE_32U_BT(buf, addr, value)	{buf[addr++] = (uint8_t)((value) >> 24); buf[addr++] = (uint8_t)((value) >> 16); buf[addr++] = (uint8_t)((value) >> 8); buf[addr++] = (uint8_t)(value);}

//#define KIT_READ_16U_LT(buf, addr)				((buf[(addr)]) + ((uint16_t)(buf[(addr) + 1]) << 8))
//#define KIT_READ_32U_LT(buf, addr)				((buf[(addr)]) + ((uint32_t)(buf[(addr) + 1]) << 8) + ((uint32_t)(buf[(addr) + 2]) << 16) + ((uint32_t)(buf[(addr) + 3]) << 24))
//#define KIT_ADD_READ_16U_LT(buf, addr)			((addr) += 2; KIT_READ_16U_LT(buf, (addr - 2)))
//#define KIT_ADD_READ_32U_LT(buf, addr)			((addr) += 4; KIT_READ_32U_LT(buf, (addr - 4)))

//#define KIT_WRITE_16U_LT(buf, addr, value)		{buf[(addr)] = (uint8_t)(value); buf[(addr) + 1] = (uint8_t)((value) >> 8);}
//#define KIT_WRITE_32U_LT(buf, addr, value)		{buf[(addr)] = (uint8_t)(value); buf[(addr) + 1] = (uint8_t)((value) >> 8); buf[(addr) + 2] = (uint8_t)((value) >> 16); buf[(addr) + 3] = (uint8_t)((value) >> 24);}
//#define KIT_ADD_WRITE_16U_LT(buf, addr, value)	{buf[addr++] = (uint8_t)(value); buf[addr++] = (uint8_t)((value) >> 8);}
//#define KIT_ADD_WRITE_32U_LT(buf, addr, value)	{buf[addr++] = (uint8_t)(value); buf[addr++] = (uint8_t)((value) >> 8); buf[addr++] = (uint8_t)((value) >> 16); buf[addr++] = (uint8_t)((value) >> 24);}
	

#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 + 1]) + ((uint32_t)(ADDRESS[POS]) << 8) + ((uint32_t)(ADDRESS[POS]) << 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 + 1]) << 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_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_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);}

#ifdef __cplusplus
}
#endif

#endif
