-
bit mux / demux
Hi,
I'm trying to implement a mux / demux in C. The basic idea is, given an input buffer of char[], i want to be able to read the required number of bits and place them in the destination buffer and then read the next number of bits and place them in the next destination buffer, etc...
eg
given a char[]
take first 3 bits and put into buffer a
take next 4 bits and put into buffer b
take next 5 bits and put into buffer c
take next 3 bits and put into buffer a
take next 4 bits and put into buffer b
.... etc
and for the demux i would like to be able to reverse the process, so that i can recreate the char[].
Anyone have any ideas??? I've thought about bit shifting and stuff but you can only shift bits in a byte and can't shift an entire array right??
Thanks for your help.
-
Simple enough
Code:
#include <stdio.h>
#include <limits.h>
int getBits ( char *buff, int *bitpos, int numbits ) {
int byte = *bitpos / CHAR_BIT;
int bit = *bitpos % CHAR_BIT;
int mask = (1<<numbits)-1;
int word = buff[byte] | (buff[byte+1]<<8);
*bitpos += numbits;
return ( word >> bit ) & mask;
}
int main ( ) {
char buff[] = "hello world";
int bitpos=0;
printf( "3=%x\n", getBits(buff,&bitpos,3) );
printf( "4=%x\n", getBits(buff,&bitpos,4) );
printf( "5=%x\n", getBits(buff,&bitpos,5) );
printf( "3=%x\n", getBits(buff,&bitpos,3) );
printf( "4=%x\n", getBits(buff,&bitpos,4) );
printf( "5=%x\n", getBits(buff,&bitpos,5) );
return 0;
}
-
:D
Salem, how the hell did you come up with that??!
Anyway, very nice work :)
-
I think the code posted by Salem may be incorrect.
Code:
#include <stdio.h>
#include <limits.h>
int getBits ( char *buff, int *bitpos, int numbits ) {
int byte = *bitpos / CHAR_BIT;
int bit = *bitpos % CHAR_BIT;
int mask = (1<<numbits)-1;
int word = buff[byte] | (buff[byte+1]<<8);
*bitpos += numbits;
return ( word >> bit ) & mask;
}
void test(const char *buff)
{
int bitpos=0;
printf( "3=%x\n", getBits(buff,&bitpos,3) );
printf( "4=%x\n", getBits(buff,&bitpos,4) );
printf( "5=%x\n", getBits(buff,&bitpos,5) );
printf( "3=%x\n", getBits(buff,&bitpos,3) );
printf( "4=%x\n", getBits(buff,&bitpos,4) );
printf( "5=%x\n", getBits(buff,&bitpos,5) );
}
int main(void)
{
/* LSB 0001:1110-0000:0001-1119:0000 MSB */
/* 3334:4445-5555:3334-4445:5555 */
const char buf1[] = { 0x78, 0x80, 0x07 };
/* LSB 0101:0101-1010:1010-0101:0101 MSB */
/* 3334:4445-5555:3334-4445:5555 */
const char buf2[] = { 0xAA, 0x55, 0xAA };
/* LSB 1010:1010-0101:0101-1010:1010 MSB */
/* 3334:4445-5555:3334-4445:5555 */
const char buf3[] = { 0x55, 0xAA, 0x55 };
test(buf1);
puts("---");
test(buf2);
puts("---");
test(buf3);
return 0;
}
/* my (annotated) output
3=0
4=f
5=0
3=0
4=f
5=0
---
3=2
4=5
5=1f <<< incorrect, should be 0xB
3=5
4=4
5=15
---
3=5
4=a
5=14
3=2
4=f <<< incorrect, should be 0xB
5=a
*/
I haven't come up with a better solution yet, I just wanted to point this out. Also, should the 8 in the following have been CHAR_BIT?
Code:
int word = buff[byte] | (buff[byte+1]<<8);
-
The algorithm is good, it's just the implementation which is off :(
Code:
int getBits ( const unsigned char *buff, int *bitpos, int numbits ) {
int byte = *bitpos / CHAR_BIT;
int bit = *bitpos % CHAR_BIT;
unsigned int mask = (1<<numbits)-1;
unsigned int word = buff[byte] | (buff[byte+1]<<CHAR_BIT);
*bitpos += numbits;
return ( word >> bit ) & mask;
}
My mistake for testing with ascii data not binary data
The problem was the sign extension when converting bytes with the MSB set (eg. 0xaa) to ints, resulting in all the most significant bits being set.
> Also, should the 8 in the following have been CHAR_BIT?
Yes