/**
  ******************************************************************************
  * @file    MBUtils.cpp
  * @author  北京聚英翱翔电子有限公司 刘盼
  * @version V1.0.0
  * @date    2012年12月28日
  **@brief   Modbus 位操作类
  * @details 
  ******************************************************************************
**/

#include "stdafx.h"
#include "MBUtils.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
#define BITS_UCHAR      8U

CMBUtils::CMBUtils()
{

}

CMBUtils::~CMBUtils()
{

}

void CMBUtils::xMBUtilSetBits(u8 *ucByteBuf, u16 usBitOffset, u8 ucNBits, u8 ucValue)
{
	u16          usWordBuf;
    u16          usMask;
    u16          usByteOffset;
    u16          usNPreBits;
    u16          usValue = ucValue;

    /* Calculate byte offset for first byte containing the bit values starting
     * at usBitOffset. */
    usByteOffset = (u16)((usBitOffset) / BITS_UCHAR);

    /* How many bits precede our bits to set. */
    usNPreBits = (u16)(usBitOffset - usByteOffset * BITS_UCHAR);

    /* Move bit field into position over bits to set */
    usValue <<= usNPreBits;

    /* Prepare a mask for setting the new bits. */
    usMask = (u16)((1 << (u16)ucNBits) - 1);
    usMask <<= usBitOffset - usByteOffset * BITS_UCHAR;

    /* copy bits into temporary storage. */
    usWordBuf = ucByteBuf[usByteOffset];
    usWordBuf |= ucByteBuf[usByteOffset + 1] << BITS_UCHAR;

    /* Zero out bit field bits and then or value bits into them. */
    usWordBuf = (u16)((usWordBuf & (~usMask)) | usValue);

    /* move bits back into storage */
    ucByteBuf[usByteOffset] = (u8)(usWordBuf & 0xFF);
    ucByteBuf[usByteOffset + 1] = (u8)(usWordBuf >> BITS_UCHAR);
}

u8 CMBUtils::xMBUtilGetBits(u8 *ucByteBuf, u16 usBitOffset, u8 ucNBits)
{
	u16          usWordBuf;
    u16          usMask;
    u16          usByteOffset;
    u16          usNPreBits;

    /* Calculate byte offset for first byte containing the bit values starting
     * at usBitOffset. */
    usByteOffset = (u16)((usBitOffset) / BITS_UCHAR);

    /* How many bits precede our bits to set. */
    usNPreBits = (u16)(usBitOffset - usByteOffset * BITS_UCHAR);

    /* Prepare a mask for setting the new bits. */
    usMask = (u16)((1 << (u16)ucNBits) - 1);

    /* copy bits into temporary storage. */
    usWordBuf = ucByteBuf[usByteOffset];
    usWordBuf |= ucByteBuf[usByteOffset + 1] << BITS_UCHAR;

    /* throw away unneeded bits. */
    usWordBuf >>= usNPreBits;

    /* mask away bits above the requested bitfield. */
    usWordBuf &= usMask;

    return(u8)usWordBuf;
}
