bit field manipulation / endian woes

There's the potential for a part 2 to this issue I'm faced with nonetheless, I've got code here that is littered with - and i quote ' compiler independent bit field maniuplation methods'.  The function GetBitsValueShifted is actually encapsulated in a class but for discussion purposes I've opted to provide a stripped down version of the source.  At issue:  Because of endian issues I'm not getting the desired result from the function GetBitsValueShifted.  
    Simply put for bits zero to 7, the value 0x113 should be 1 as opposed to 0x13.

How could I resolve  this?  (not sure if the solution lies in MMASKS)

# include <vector>
# include <ios>
# include <iomanip>
 
static const int MTOTAL_BITS_IN_TYPE=16;
const int MTOTAL_BITS_ZERO_BASED = MTOTAL_BITS_IN_TYPE-1;
const unsigned short MMASK_BIT0  = 0x0001;
const unsigned short MMASK_BIT1  = 0x0002;
const unsigned short MMASK_BIT2  = 0x0004;
const unsigned short MMASK_BIT3  = 0x0008;
const unsigned short MMASK_BIT4  = 0x0010;
const unsigned short MMASK_BIT5  = 0x0020;
const unsigned short MMASK_BIT6  = 0x0040;
const unsigned short MMASK_BIT7  = 0x0080;
const unsigned short MMASK_BIT8  = 0x0100;
const unsigned short MMASK_BIT9  = 0x0200;
const unsigned short MMASK_BIT10 = 0x0400;
const unsigned short MMASK_BIT11 = 0x0800;
const unsigned short MMASK_BIT12 = 0x1000;
const unsigned short MMASK_BIT13 = 0x2000;
const unsigned short MMASK_BIT14 = 0x4000;
const unsigned short MMASK_BIT15 = 0x8000;
const unsigned short MMASK_BIT16 = 0x0000;
 
//const unsigned short MMASK_BIT0  = 0x8000;
//const unsigned short MMASK_BIT1  = 0x4000;
//const unsigned short MMASK_BIT2  = 0x2000;
//const unsigned short MMASK_BIT3  = 0x1000;
//const unsigned short MMASK_BIT4  = 0x0800;
//const unsigned short MMASK_BIT5  = 0x0400;
//const unsigned short MMASK_BIT6  = 0x0200;
//const unsigned short MMASK_BIT7  = 0x0100;
//const unsigned short MMASK_BIT8  = 0x0080;
//const unsigned short MMASK_BIT9  = 0x0040;
//const unsigned short MMASK_BIT10 = 0x0020;
//const unsigned short MMASK_BIT11 = 0x0010;
//const unsigned short MMASK_BIT12 = 0x0008;
//const unsigned short MMASK_BIT13 = 0x0004;
//const unsigned short MMASK_BIT14 = 0x0002;
//const unsigned short MMASK_BIT15 = 0x0001;
//const unsigned short MMASK_BIT16 = 0x0000;
 
const unsigned short MMASKS[MTOTAL_BITS_IN_TYPE+1 ]= {
                                             MMASK_BIT0,
                                             MMASK_BIT1,
                                             MMASK_BIT2,
                                             MMASK_BIT3,
                                             MMASK_BIT4,
                                             MMASK_BIT5,
                                             MMASK_BIT6,
                                             MMASK_BIT7,
                                             MMASK_BIT8,
                                             MMASK_BIT9,
                                             MMASK_BIT10,
                                             MMASK_BIT11,
                                             MMASK_BIT12,
                                             MMASK_BIT13,
                                             MMASK_BIT14,
                                             MMASK_BIT15,
                                             MMASK_BIT16};
 
unsigned short GetBitsValueShifted(unsigned short mShortData_, 
                                   unsigned char startBit_, 
                                   unsigned char stopBit_)
{
   static unsigned int bitMask;
   static unsigned int numBits;
 
   unsigned short bitsValue = 0;
   
   // Create a bit mask at the bit location
   unsigned char stopBit = (stopBit_ + 15) % 15;
   unsigned char startBit = (startBit_ + 15) % 15;
   
   numBits = stopBit - startBit + 1;
   bitMask = (unsigned short) ((unsigned short) (MMASKS[numBits]-1));  //(2**numBits)-1
 
   bitsValue = ( (mShortData_ >> startBit) & bitMask);
 
   return (bitsValue);
}
 
typedef std::vector < unsigned short > USHORT_VEC ;
int main() 
{ 
  USHORT_VEC usv ( 30 ) ; 
  usv [ 2 ] = 0x113 ;
  for ( int pdx ( 0 ); pdx < usv.size(); ++pdx ) 
  {
    unsigned short mVal = GetBitsValueShifted  ( usv [ pdx ], 0, 7 ) ;
    std::cout << std::hex << "0x" << mVal << std::endl;
  }
  std::cin.get() ;
 
}

Open in new window

forums_mpAsked:
Who is Participating?
 
DanRollinsCommented:
Well, I have to agree that whoever wrote that made it much more complicated than it needed to be.  
I simplified the logic and trimmed it down to the 150 lines of the attached code snippet.  You will want to add some members to the CMsgPkt class -- (the orignal code had SetXxxx and code to calculate the checksum, etc.  But it's pretty straight forward and should be easy to understand now.
The part you really wanted to see is my revised
  CMsgPkt::GetBitsValueShifted( ... )
function.  I used to formula to convert the layout in the documentation into the layout that actually exists in the data.  
   int nStopActual=  abs( 15-nStart );  
   int nStartActual= abs( 15-nStop  );
What I was trying to get at in my earlier post:  You have documentation on how the bit fields are laid out --- including bit-by-bit groupings.   It would actually be easier to just the real bit layout than the "backword" one that you have.  You didn't want to do that, so I had to convert from the documentation notation into real values.

// Console23.cpp : Defines the entry point for the console application.
//
 
# include <iostream>
# include <fstream>
 
typedef unsigned char  BYTE8;
typedef unsigned short WORD16;
 
WORD16 MaskTable[] = {
	0x0000, 0x0001, 0x0003, 0x0007, 0x000f,
	0x001f, 0x002f, 0x003f, 0x007f, 0x01ff,
	0x02ff, 0x03ff, 0x07ff, 0x1fff, 0x2fff,
	0x3fff, 0x7fff, 0xffff  
};
 
class CMsgPkt 
{
public:
	WORD16 m_PacketData[32];          // 32 16-bit words
	CMsgPkt::CMsgPkt( BYTE8* pData );
	
	WORD16 Get_R_Subaddress() {
		return GetBitsValueShifted( m_nCmdWord, 5,10 );
	}
	WORD16 Get_Type() { 
		return GetBitsValueShifted( GetDataWord(2), 0, 7);
	}
	WORD16 Get_Station_Number() {
		return GetBitsValueShifted( GetDataWord(2), 8, 12);
	}
	WORD16 Get_Bay_Number() {
		return GetBitsValueShifted( GetDataWord(2), 13, 15);
	}
 
	WORD16 Get_Type_Invalid() {
		return GetBit( GetDataWord(1), 0 );
	}
	WORD16 Get_Station_Number_Invalid()  {
		return GetBit( GetDataWord(1), 1 );
	}
	WORD16 Get_Bay_Number_Invalid()  {
		return GetBit( GetDataWord(1), 2 );
	}
 
	WORD16  GetCmdWord()         { return( m_PacketData[0]   ); }
	WORD16  GetDataWord( int n ) { return( m_PacketData[n+1] ); }
 
private:
 
	WORD16 GetBitsValueShifted( WORD16 v, int nStart, int nStop );
	WORD16 GetBit(              WORD16 v, int nBitLoc );
 
	WORD16  m_nCmdWord;
	WORD16* m_panDataWords;
};
 
CMsgPkt::CMsgPkt( BYTE8* pData ) {   // 64 bytes
	memcpy( &m_PacketData[0], pData, 64 );
	m_nCmdWord =     m_PacketData[0];
	m_panDataWords=  &m_PacketData[1];
}
 
// the documentation uses backword notation, for instance, 
// when it indicates bits 0-7,   it really wants bits 8-15, 
// when it indicates bits 13-15, it really wants bits 0-2, 
// so we adjust for that here
 
WORD16 CMsgPkt::GetBitsValueShifted( WORD16 v, int nStart, int nStop )
{
	int nStopActual=  abs( 15-nStart );  
	int nStartActual= abs( 15-nStop  );
	
	nStop=  nStopActual;
	nStart= nStartActual;
 
	WORD16 nRet=0;
	int nMaskLen= (nStop-nStart) +1;  // eg 0,1 is two bits, 3,6 is four buts; 0,0 is one bit
	nRet= v >> nStart;
	
	nRet &= MaskTable[nMaskLen];
	return (nRet );
}
 
WORD16 CMsgPkt::GetBit( WORD16 v, int nBitLoc )
{
	WORD16 nRet=0;
	int nBitLocActual=  abs( 15-nBitLoc );  
 
	nRet= v >> nBitLoc;
	nRet &= 0x0001; // one bit only
	return (nRet );
}
 
 
//----------------------------------------------------------------------
//---- main ------------------------------------------------------------
//----------------------------------------------------------------------
 
int main(int argc, char* argv[])
{
	int const BUFFER_SIZE = 64 ; 
 
	//---------------------------------- read raw data into the buffer
	BYTE8 rxBuffer[ BUFFER_SIZE ];
 
	std::ifstream ifs( "InFile.bin"  ) ; 
	if ( !ifs ) {
	  return EXIT_FAILURE ; 
	}
	ifs.read ( (char*)rxBuffer, BUFFER_SIZE ) ; 
	ifs.close() ;
 
	//------------------------------ create packet from raw data
	CMsgPkt cPkt( rxBuffer );
 
	//------------------------------ display it as 16-bit words for fun
	for ( int j=0; j< 32; j++ ) {             
		WORD16 nValue=  cPkt.m_PacketData[j]; 
		if ( nValue != 0 ) {
			printf("[%02d] = 0x%04x\r\n", j, nValue );
		}
	}
	
	// ----------------- Get RxAddress	
	WORD16 nRxAddr= cPkt.Get_R_Subaddress();
	printf("===========================\r\n"); 
	printf("RxAddress:0x%04x\r\n", nRxAddr );
	printf("===========================\r\n"); 
	// data words are the ones following the Command Word
 
	printf("0x%04x (%d)\r\n", cPkt.GetDataWord(0), cPkt.GetDataWord(0) );
	printf("0x%04x (%d)\r\n", cPkt.GetDataWord(1), cPkt.GetDataWord(1) );
	printf("0x%04x (%d)\r\n", cPkt.GetDataWord(2), cPkt.GetDataWord(2) );
	printf("0x%04x (%d)\r\n", cPkt.GetDataWord(3), cPkt.GetDataWord(3) );
	printf("0x%04x (%d)\r\n", cPkt.GetDataWord(4), cPkt.GetDataWord(4) );
	printf("0x%04x (%d)\r\n", cPkt.GetDataWord(5), cPkt.GetDataWord(5) );
	printf("0x%04x (%d)\r\n", cPkt.GetDataWord(6), cPkt.GetDataWord(6) );
	printf("0x%04x (%d)\r\n", cPkt.GetDataWord(7), cPkt.GetDataWord(7) );
	printf("0x%04x (%d)\r\n", cPkt.GetDataWord(8), cPkt.GetDataWord(8) );
	printf("===========================\r\n"); 
 
	printf("Type            = %d\r\n", cPkt.Get_Type() ) ;
	printf("StationNum      = %d\r\n", cPkt.Get_Station_Number() );
	printf("BayNumber       = %d\r\n", cPkt.Get_Bay_Number() );
	printf("Invalid         = %d\r\n", cPkt.Get_Type_Invalid() );
	printf("StNumInvalid    = %d\r\n", cPkt.Get_Station_Number_Invalid() );
	printf("BayNumInvalid   = %d\r\n", cPkt.Get_Bay_Number_Invalid() ) ;
 
	return 0;
}

Open in new window

0
 
Infinity08Commented:
>> Simply put for bits zero to 7, the value 0x113 should be 1 as opposed to 0x13.

bits 0 to 7 of the value 0x0113 are always 0x13, and endianness has nothing to do with that. Endianness is just how the value is stored, but it doesn't modify the value.
0
 
DanRollinsCommented:
0x0113 & 0xFF is, in fact, 0x0013.
It is working correctly.
 
0
Get your problem seen by more experts

Be seen. Boost your question’s priority for more expert views and faster solutions

 
evilrixSenior Software Engineer (Avast)Commented:
the code always bitshifts by 0 (meaning it shifts nothing) and then ands with a mask of 255. If you pass 275 (0x113) into this function you end up returning 275 & 255, which is 19 (0x13)

100010011 == 0x113 == 275
&11111111 ==  0xff == 255
---------------
         10011 == 0x13 == 19
0
 
evilrixSenior Software Engineer (Avast)Commented:
Hmmm... it seems I take longer to read code that I8 and Dan (and I'm sure I8 is meant to me watching Rambo III) :)
0
 
Infinity08Commented:
>> (and I'm sure I8 is meant to me watching Rambo III) :)

Heh ... Toilet + EE break ;)
0
 
forums_mpAuthor Commented:
Something is amiss..

The MSB is bit 0 so when data arrives, data is 'deserialized' and gets stored in an array of unsigned short.  So given 0x113.   [0000][0001][0001][0011]

When decoded, I should end up with:

Bits 0.. 7 should produce a    1.  i.e: [0000][0001]
Bits 8..12 should produce a   2.  i.e. [0001][0]
Bits 13..15 should produce a 3   i.e. [011]

how would i modify function (GetBitsValueShifted) to get desired result.
  for ( int pdx ( 0 ); pdx < usv.size(); ++pdx ) 
  {
    unsigned short mPtype      = GetBitsValueShifted  ( usv [ pdx ], 0, 7 ) ;
    unsigned short mStationNum = GetBitsValueShifted  ( usv [ pdx ], 8, 12 ) ;
    unsigned short mPBay       = GetBitsValueShifted  ( usv [ pdx ], 13, 15 ) ;
    if  ( pdx == 2 ) 
    {
      std::cout << " Ptype =0x" << mPtype << " mStationNum=0x" << mStationNum 
                << " mPBay=0x" << mPBay 
                << std::endl; 
    }
  }

Open in new window

0
 
Infinity08Commented:
>> The MSB is bit 0

Bit 0 is the least significant bit (LSB), or the bit with the lowest value. The MSB is the bit with the highest value.

If you have the 16 bit value 0x0113, in binary, that is : 0000 0001 0001 0011. Bit 0 is 1, bit 1 is 1, bit 2 is 0, etc. (from right to left), up to bit 15, which is 0.

So :

bits 0 to 7 gives a value of 00010011 = 0x13 = 19
bits 8 to 12 gives a value of 00001 = 0x01 = 1
bits 13 to 15 gives a value of 000 = 0x00 = 0
0
 
forums_mpAuthor Commented:
Infinity; I understand that and its not what i want  My question is, what to do to get what I want  
0
 
DanRollinsCommented:
It looks like you are getting data in groups of four bits (aka nybbles). Given the input you describe and the desired output, you should first convert the data into 16-bit values; that is take them four at a time.
Then, to use the existing GetBitsValueShifted fn, you should identify bit fields 8-15, 3-7, and 0-2
usv[0]= 0;
usv[1]= 1;
usv[2]= 1;
usv[3]= 3;
int nAccumulator =
(usv[0]*1024) + (usv[1] * 256) + (usv[2] * 16) + (usv[3] );

unsigned short mVal1 = GetBitsValueShifted( nAccumulator, 8,15 ); // 8-bit field
unsigned short mVal2 = GetBitsValueShifted( nAccumulator, 3, 7 ); // 5-bit field
unsigned short mVal3 = GetBitsValueShifted( nAccumulator, 0, 2 ); // 3-bit field

0
 
forums_mpAuthor Commented:
Dan, I'd hope the solution lied within GetBitsValueShifted.  This way the underlying calls to GetBitsValueShifted remains unchanged (i.e 0..7 remains 0..7 as opposed to 8..15).  So given the source snippet. pType would be  1, mStationNum would be  2 and mPbay would equate to 3.


  for ( int pdx ( 0 ); pdx < usv.size(); ++pdx ) 
  {
    unsigned short mPtype      = GetBitsValueShifted  ( usv [ pdx ], 0, 7 ) ;
    unsigned short mStationNum = GetBitsValueShifted  ( usv [ pdx ], 8, 12 ) ;
    unsigned short mPBay       = GetBitsValueShifted  ( usv [ pdx ], 13, 15 ) ;
    if  ( pdx == 2 ) 
    {
      std::cout << " Ptype =0x" << mPtype << " mStationNum=0x" << mStationNum 
                << " mPBay=0x" << mPBay 
                << std::endl; 
    }
  }

Open in new window

0
 
DanRollinsCommented:
It would be possible to redo the GetBitsValueShifted() fn, but whatever you do, you can't pass individual values into it... you need to group them.  As you showed in your own example,
Bits 8..12 should produce a   2.  i.e. [0001][0] <<< parts of two data elements

at least one of the fields spans two of the data elements.  And the loop you use in calling the function is sending individual data elements into the function.  It just can't work.
Also: What difference does it make if you call the bit field (for instance) "0-2" or "13-15" ??
It's the same two bits either way.
 
0
 
Infinity08Commented:
>> Infinity; I understand that and its not what i want  My question is, what to do to get what I want

Well, it seems you want to re-define what MSB and LSB mean ... My response was to not do that, but rather to re-visit your understanding of what they mean, and align yourself to the way everybody else understands them ;)

If you do change GetBitsValueShifted to suit your understanding, you'll confuse everybody else reading your code, with possibly disastrous consequences.
0
 
forums_mpAuthor Commented:
DanRollins
|| Also: What difference does it make if you call the bit field (for instance)
||  "0-2" or "13-15" ?? It's the same two bits either way.
For discussion purposes, I provided a very stripped down version of _one_ problem area.   In other words, part of what's lacking here is 'context'.  You're not seeing big picture and the huge impact that I may end up having to do long term (i inherited this mess and I'd like to fix it..)

infinity08:
|| If you do change GetBitsValueShifted to suit your understanding,
|| you'll confuse everybody else reading your code, with possibly disastrous consequences
I dont disagree with you.  Sometime today I'll put together a complete example to highlight what I'm faced with and get ideas/perhaps source on how to overhaul this mess.  In the iterim i've redefined MSB (so another user can continue his testing)

 
unsigned short GetBitsValueShifted(unsigned short mShortData_, 
                                   unsigned char startBit_, 
                                   unsigned char stopBit_)
{
   static unsigned int bitMask;
   static unsigned int numBits;
 
   unsigned short bitsValue = 0;
   
   // Create a bit mask at the bit location
   unsigned char stopBit  = 15 - startBit_ ;
   unsigned char startBit = 15 - stopBit_ ;   
   numBits = stopBit - startBit + 1;
   bitMask = (unsigned short) ((unsigned short) (MMASKS[numBits]-1));  //(2**numBits)-1
   bitsValue = ( (mShortData_ >> startBit) & bitMask);
   return (bitsValue);
}

Open in new window

0
 
Infinity08Commented:
>> (i inherited this mess and I'd like to fix it..)

Ah, now it starts making sense heh ;)
0
 
DanRollinsCommented:
What you may actually need is a flexible way to extract a range of bits from an array of unsigned short values.... The extraction logic would know that only the bottom four bits of each array element were populated.
But then I am not seeing the big picture -- perhaps because I've only been given a tiny peephole through which to look.  Here's an idea: Describe your situation in more detail. Lots of detail. Remember that this is the first time that any of us has ever even looked at your problem. Tell us everything.
0
 
evilrixSenior Software Engineer (Avast)Commented:
>> i inherited this mess and I'd like to fix it
I know that feeling only too well :(
0
 
forums_mpAuthor Commented:
|| Here's an idea: Describe your situation in more detail. Lots of detail.
|| Remember that this is the first time that any of us has ever even looked at your problem.
|| Tell us everything.

For starters:  
Rename all .txt files to .h (apparently EE doesn't accept .h and .cpp as attachments).  

Similarilily rename:
   bitfields_ushort.doc to bitfields_ushort.cpp
   main.doc to main.cpp
   base_msg.doc to base_msg.cpp

Lastly, rename InFile.doc to InFile.bin

Reference layout.doc for information on the R1 message description.

The source code compiles with Version 9 (MSVC.NET)

Noteworthy:

The file InFile.bin contains 64 bytes of incoming data.

-      The data is deserialized and stored in the array of unsigned short. To do this the Deserialize method in C_Msg_Base strips off the command word, stores the 30 data words in the array of unsigned short and ignores the status word.

-      To set or get information pertaining to specific proxies in a word, individual methods within C_Msg_R1 is invoked

In my view this is one horrible piece of code.. Alas, help needed:
1) [xxx] Refers to my rants based on my understand of the serializer source (it appears to be a pile of - to put it mildly - crap).  I'd like stream line this thing.
2) Streamline base_msg.  Given a multi-threaded environment I suspect I may need to stick with char* (std::string from what i understand is not thread safe).
3) When viewed from the context of the word document, it appears the definitions of MSB and LSB defined in r1_msg.cpp is incorrect.. To proceed with my test activities I quickly redefined MSB and LSB in the c_bitfields_ushort class class (thus far I've only changed - i.e redefined MSB and LSB  in - GetBitsValueShifted) .  Given there's a litany of messages redefining MSB and LSB is a significant change.  In the interim, I'll like to hear if my assessment is correct (i.e the layout in r1_msg.cpp is incorrect) and if there's a viable solution that doesn't require changing the proxies in all the messages.


msg-integration.zip
0
 
mrjoltcolaCommented:
I arrived late at this party, but it seems everyone has zonked out, maybe Rambo III was too much for Infinity and evilrix. My quick overview of the code gives me the feeling that the original author might not have fully understood how to handle byteordering and serialization. It appears to be very complex for byteordering / serialization API. But again, I only spent 5 minutes looking it over. I can say, from writing the bytecode loader for Parrot/Perl6 runtime, I don't think it took me 1/2 that much code. So, I concur with your opinion that it is one horrible piece of code, but I'm not sure where to start. I surely don't have time or desire to dig into it myself, I would probably just take the original requirements and start over on this one.
0
 
DanRollinsCommented:
mrjoltcola,
>> I would probably just take the original requirements and start over...
That's pretty much exactly what I did :-)
I've never been good at working on other people's code ... Why on EARTH did he do THAT?!?!?! :-).  The task itself is not complicated once you have the specs.
0
 
mrjoltcolaCommented:
Dan you are the man on this one, I must admit, or you were just bored. :)

0
 
Infinity08Commented:
>> but it seems everyone has zonked out, maybe Rambo III was too much for Infinity and evilrix.

lol. Rather ... dozed off, but just got woken up again ;)

I don't have the time to re-work it like DanRollins did (hats off), but then I don't need to any more heh.

Just a small note about the mask table : it seems to be a bit off ... :)
0
 
evilrixSenior Software Engineer (Avast)Commented:
>> >> but it seems everyone has zonked out, maybe Rambo III was too much for Infinity and evilrix.
There were already enough grade A experts working this thread... better suited to provide an answer than me :)
0
 
forums_mpAuthor Commented:
|| Dan you are the man on this one, I must admit,
||  or you were just bored. :)
Dan is the reason why folks like me keep our EE membership.  

Infinity08 and evilrix let me down on this one :).  I was shocked infinity wasn't  the first to fire off a 'try this' - with accompanying source code.
0
 
forums_mpAuthor Commented:
Dan, I'll need to stare at this some more later, nonethelesss it seems like you eliminated the use of the the serializer class.?
0
 
Infinity08Commented:
>> I was shocked infinity wasn't  the first to fire off a 'try this' - with accompanying source code.

;) My time management capabilities are being stretched to the limit at the moment ... sorry :)
0
 
DanRollinsCommented:
>> it seems like you eliminated the use of the the serializer class.?
I eliminated all of everything but what you see there.  It provides the significnat functionality, but you will need to add back some of the other stuff (if you need it).
0
 
evilrixSenior Software Engineer (Avast)Commented:
>> Infinity08 and evilrix let me down on this one
Like I said, there were already enough experts working on this.
0
 
forums_mpAuthor Commented:
|| It would actually be easier to just the real bit layout than the "backword" one that you have.  
|| You didn't want to do that, so I had to convert from the documentation notation into real values.
Question on this backward issue.  Why is it necessary to redefine MSB for the case where I'm tryin gto pull out individual bits yet that's not necessary for the case where I want to grab all 16 bits?  Seems odd to me.


0
 
DanRollinsCommented:
Yes.  The only distinction is that the documentation used a reversed bit ordering.  
A 16-bit value is a 16-bit value (a single entity, a quantity) regardless of how it is transported.  A bit fiield, on the other hand can be interpreted either left-to-right or right-to-left.   Whoever wrote the spec decided to layout it out a certain way and that left significant ambiguity.  The only way to resolve it is to examine the bit patterns in the data and compare to the expected output.  
Infinity08
>>Just a small note about the mask table : it seems to be a bit off ... :)
Good catch!  That made me recheck.   My mask table was in error, but the first part was correct and, by coincidence, the sample data did not use the latter part of the table.  The attached snippet is the correct code.

WORD16 MaskTable[] = {
	0x0000, 
	0x0001, 0x0003, 0x0007, 0x000f,
	0x001f, 0x003f, 0x007f, 0x00ff,
	0x01ff, 0x03ff, 0x07ff, 0x0fff, 
	0x1fff, 0x3fff, 0x7fff, 0xffff  
};

Open in new window

0
 
evilrixSenior Software Engineer (Avast)Commented:
Nice work Dan. :)
0
 
DanRollinsCommented:
thanks :-)
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.