/*******************************************************************************
*
*
* File:        tau_operations.h
* Description  位操作与字节操作相关定义头文件
* Version      V0.1
* Date         2020-09-07
* Author       lzy
 *******************************************************************************/
#ifndef __TAU_BYTEOPS_H
#define __TAU_BYTEOPS_H

/**
 * \name 通用位常数定义
 * @{
 */

/** \brief 长整数位数 */
#ifndef TAU_BITS_PER_LONG
    #define TAU_BITS_PER_LONG       32
#endif

/** \brief 字节位数 */
#define TAU_BITS_PER_BYTE       8

/** @} */


/******************************************************************************/

/**
 * \name 通用位操作
 * @{
 */

/** \brief bit移位
 * TAU_BIT(2) is 0x4
 */
#define TAU_BIT(bit)                  (1u << (bit))

/** \brief 值移位
 * TAU_SBF(0xFF, 8) is 0xff00
 */
#define TAU_SBF(value, field)         ((value) << (field))

/** \brief bit置位
 * TAU_BIT_SET(0, 8) is 0x100
 */
#define TAU_BIT_SET(data, bit)        ((data) |= TAU_BIT(bit))

/** \brief bit清零
 * TAU_BIT_CLR(0xFF, 2) is 0xfb
 */
#define TAU_BIT_CLR(data, bit)        ((data) &= ~TAU_BIT(bit))

/** \brief bit置位, 根据 mask 指定的位
 * TAU_BIT_SET_MASK(0xF0F0, 0xF00) is 0xfff0
 */
#define TAU_BIT_SET_MASK(data, mask)  ((data) |= (mask))

/** \brief bit清零, 根据 mask 指定的位
 * TAU_BIT_CLR_MASK(0xFFFF, 0xFF00) is 0xff
 */
#define TAU_BIT_CLR_MASK(data, mask)  ((data) &= ~(mask))

/** \brief bit翻转
 * TAU_BIT_TOGGLE(0xFFFF, 0) is 0xfffe
 * TAU_BIT_TOGGLE(0x0000, 1) is 0x2
 */
#define TAU_BIT_TOGGLE(data, bit)     ((data) ^= TAU_BIT(bit))

/** \brief bit修改
 * TAU_BIT_MODIFY(0, 8, 1) is 0x100
 * TAU_BIT_MODIFY(0xFFFF, 1, 0) is 0xfffd
 */
#define TAU_BIT_MODIFY(data, bit, value) \
    ((value) ? TAU_BIT_SET(data, bit) : TAU_BIT_CLR(data, bit))

/** \brief 测试bit是否置位
 * TAU_BIT_ISSET(0xF0F1, 1) is 0
 * TAU_BIT_ISSET(0xF0F2, 1) is 2
 */
#define TAU_BIT_ISSET(data, bit)      ((data) & TAU_BIT(bit))

/** \brief 获取bit值
 * TAU_BIT_GET(0xF0F1, 1) is 0
 * TAU_BIT_GET(0xF0F2, 1) is 1
 */
#define TAU_BIT_GET(data, bit)        (TAU_BIT_ISSET(data, bit) ? 1 : 0)

/** \brief 检测bit值
 * TAU_BIT_CHECK(0xF5FF, 4) is 1
 */
#define TAU_BIT_CHECK(data, bit)  \
    (((data) & TAU_BIT(bit)) ? 1 : 0)

/** \brief 获取 n bits 掩码值
 * TAU_BITS_MASK(2) is 0x3
 */
#define TAU_BITS_MASK(n)              (~((~0u) << (n)))

/** \brief 获取位段值
 * TAU_BITS_GET(0xF5FF, 0x0F00, 8) is 0x5
 */
#define TAU_BITS_GET(data, mask, pos)  \
    (((data) & (mask)) >> (pos))

/** \brief 获取位段值
 * TAU_BITS_CHECK(0xF5FF, 0x0F00) is 1
 */
#define TAU_BITS_CHECK(data, mask)  \
    (((data) & (mask)) ? 1 : 0)

/** \brief 修改位段值
 * TAU_BITS_MODIFY(0xF5FF, 0x0FF0, 0x8A0) is 0xF8AF
*/
#define TAU_BITS_MODIFY(data, clear_mask, set_mask) \
    (data) = (((data) & (~(clear_mask))) | (set_mask))

/** \brief 设置位段值
 * TAU_WRITE_REG32(0x05FF, 0xFFFA) is 0xFFFA
*/
#define TAU_WRITE_REG32(data, value) ((data) = (value))

/** \brief 设置位段值
 * TAU_READ_REG32(0x05FF) is 0x05FF
*/
#define TAU_READ_REG32(data) (data)


/** @} */

/******************************************************************************/

/**
 * \brief 取2-byte整数的高位byte
 *
 * \par 示例
 * \code
 *  uint16_t a = 0x1234;
 *  uint16_t b;
 *
 *  b = TAU_MSB(a);  //b=0x12
 * \endcode
 */
#define TAU_MSB(x)       (((x) >> 8) & 0xff)

/**
 * \brief 取2-byte整数的低位byte
 *
 * \par 示例
 * \code
 *  uint16_t a = 0x1234;
 *  uint16_t b;
 *
 *  b = TAU_LSB(a);  //b=0x34
 * \endcode
 */
#define TAU_LSB(x)       ((x) & 0xff)

/**
 * \brief 取2-word整数的高位word
 *
 * \par 示例
 * \code
 *  uint32_t a = 0x12345678;
 *  uint32_t b;
 *
 *  b = TAU_MSW(a);  //b=0x1234
 * \endcode
 */
#define TAU_MSW(x)       (((x) >> 16) & 0xffff)

/**
 * \brief 取2-word整数的低位word
 *
 * \par 示例
 * \code
 *  uint32_t a = 0x12345678;
 *  uint32_t b;
 *
 *  b = TAU_LSW(a);  //b=0x5678
 * \endcode
 */
#define TAU_LSW(x)       ((x) & 0xffff)

/**
 * \brief 交换32-bit整数的高位word和低位word
 *
 * \par 示例
 * \code
 *  uint32_t a = 0x12345678;
 *  uint32_t b;
 *
 *  b = TAU_WORDSWAP(a); //b=0x56781234
 * \endcode
 */
#define TAU_WORDSWAP(x)  (TAU_MSW(x) | (TAU_LSW(x) << 16))

/**
 * \brief 交换32-bit整数的字节顺序
 *
 * \par 示例
 * \code
 *  uint32_t a = 0x12345678;
 *  uint32_t b;
 *
 *  b = TAU_LONGSWAP(a); //b=0x78563412
 * \endcode
 */
#define TAU_LONGSWAP(x)  ((TAU_LLSB(x) << 24) | \
                          (TAU_LNLSB(x) << 16) | \
                          (TAU_LNMSB(x) << 8)  | \
                          (TAU_LMSB(x)))

#define TAU_LLSB(x)      ((x) & 0xff)                    /**< \brief 取32bit整数第1个字节 */
#define TAU_LNLSB(x)     (((x) >> 8) & 0xff)             /**< \brief 取32bit整数第2个字节 */
#define TAU_LNMSB(x)     (((x) >> 16) & 0xff)            /**< \brief 取32bit整数第3个字节 */
#define TAU_LMSB(x)      (((x) >> 24) & 0xff)            /**< \brief 取32bit整数第4个字节 */
#define TAU_LNSB(x,n)    (((x) >> ((n) * 8) ) & 0xff)      /**< \brief 取32bit整数第n个字节 ,参数 0 - 3*/

/**
 * @}
 */

#endif /* __TAU_BYTEOPS_H */

/* end of file */

