/**
 * \file    utils.h
 * \brief   System adaptation layer utilities
 *
 * \par     Copyright (c) 2018 UWE Technologies Corp., Ltd. All Rights Reserved.
 * \author  James
 * \date    2018-03-05
 * \version 
 * 
 * \history 
 *  Date        Note
 *  2018-03-05  Original Creation
 * 
 */
 
#ifndef __UTILS_H_
#define __UTILS_H_


#include "types.h"


/** Check if the bit position is set */
#define SAL_IS_BIT_SET(val,pos) \
    ((val) & (1 << (pos)))

/** Check if the bit position is cleared */
#define SAL_IS_BIT_CLEARED(val,pos) \
    (((val) & (1 << (pos))) ^ (1 << (pos)))

/** Clear bit */
#define SAL_BIT_CLEAR(val,pos) \
    do { \
        val &= ~(1 << (pos)); \
    } while(0)

/** Set bit to 1 */
#define SAL_BIT_SET(val,pos) \
    do { \
        val |= 1 << (pos); \
    } while(0)

/** Get dst field value */
#define SAL_FIELD_GET(dst,reg,field) \
    (((dst)&(reg##_##field##_FLDSET))>>(reg##_##field))

/** Set dst field value */
#define SAL_FIELD_SET(dst,reg,field,val) \
    do { \
        dst=((dst)&(reg##_##field##_FLDMSK))|(((val)<<(reg##_##field))&(reg##_##field##_FLDSET)); \
    } while(0)

/** Clear dst field value */
#define SAL_FIELD_CLEAR(dst,reg,field) \
    do { \
        dst=(dst)&(reg##_##field##_FLDMSK); \
    } while(0)

/** Get dst field with width */
#define SAL_FIELD_GET2(dst,field,width) \
    ((((dst) & ((~(0xFFFFFFFF << (width))) << (field))) >> (field)))

/** Set dst field with width */
#define SAL_FIELD_SET2(dst,field,width,val) \
    ((dst) = ((dst)&(~((~(0xFFFFFFFF<<(width)))<<(field))))|(((val)<<(field))&((~(0xFFFFFFFF<<(width)))<<(field))))


#define SAL_U32_BYTE0(val)  ((u8_t)(val))
#define SAL_U32_BYTE1(val)  ((u8_t)((val) >> 8))
#define SAL_U32_BYTE2(val)  ((u8_t)((val) >> 16))
#define SAL_U32_BYTE3(val)  ((u8_t)((val) >> 24))

#define SAL_4BYTES_U32(val1,val2,val3,val4)  ((u32_t)((val1)|((u32_t)(val2)<<8)|((u32_t)(val3)<<16)|((u32_t)(val4)<<24)))


#define SAL_U16_BYTE0(val)  ((u8_t)(val))
#define SAL_U16_BYTE1(val)  ((u8_t)((val) >> 8))

#define SAL_2BYTES_U16(val1,val2)  ((u16_t)(((val1)<<8)|(val2)))

#define SAL_U16_MSB_BYTE(val)  ((u8_t)((val) >> 8))
#define SAL_U16_LSB_BYTE(val)  ((u8_t)(val))


#define SWAP_2BYTES(val) \
    ((((val)&0x00ff)<<8)|(((val)&0xff00)>>8))

#define SWAP_4BYTES(val) \
    ((((val)&0xff000000)>>24)|(((val)&0x000000ff)<<24)|(((val)&0x00ff0000)>>8)|(((val)&0x0000ff00)<<8))


/** Nonzero if X is not aligned on a "u32_t" boundary.  */
#define UNALIGNED_32BITS(X) \
    ((u32_t)(X) & (sizeof (u32_t) - 1))

/** Nonzero if X is not aligned on a "u16_t" boundary.  */
#define UNALIGNED_16BITS(X) \
    ((u16_t)(X) & (sizeof (u16_t) - 1))

/** Align X to a "u32_t" boundary.  */
#define ALIGN_32BITS(X) \
    ( ((X)+sizeof(u32_t)-1) & ~(sizeof(u32_t)-1) )


/** SAL miliseconds per second */
#define SAL_SECOND_MS (1000UL)

/** SAL microseconds per second */
#define SAL_SECOND_US (1000000UL)

void delay(int cnt);
u32_t set_bits_get(u32_t value);
u32_t clear_bits_get(u32_t value);


#endif /* #ifndef __UTILS_H_ */

