Can anyone help me with some code i need to implement bit stuffing on an array of data? The program is for an AVR micro-controller (Tiny84A) using GNU C.
unsigned char datas[3] = {00011111,10000001,00000000};
To add 0 to each set of 5 one’s i.e. after every five consecutive 1′s appear a zero
Therefore data should be
00011111,10000001 becomes 00011111 01000000 10000000
I'm unsure where to start, an example would be great!
There are lots of examples on the web for bit stuffing (inserting a 0 after 5 1s). Unfortunately, many of them involve reading and writing strings of characters 0 and 1.
There are also examples of bit streams. It looks like you need to find examples of each and combine them.
You need to expand your question to explain more of the design decisions you have made.
In particular, it looks like you are expecting the input to be in an array instead of a stream. Are you expecting to write the output to the same array? That is a little bit trickier than writing to a different array. A stream of bits would be different again.
The basic idea is to keep counters of where you are in the input and output streams, and load and write bytes appropriately as you reach the end of 8 bits.
unsigned char datas[3] = {00011111,10000001,00000000};
int in_byte, in_bit, out_byte, out_bit;
void init()
{
in_byte = 0; in_bit = 0; out_byte = 0; out_bit = 0;
}
int get_bit()
{
int ret = 0;
if (datas[in_byte] & 1 << (7 - in_bit))
{
ret = 1;
{
++in_bit;
if (in_bit == 8)
{
in_bit = 0;
++in_byte;
}
return ret;
}
You have to write your own void put_bit(int bit), but it is similar using the "or" operator |.
You also need to make a function to do the loop that counts up to 5 and puts an extra 0. Look at the examples on the web for that.
Related
I wrote this function that performs a slightly modified variation of run-length encoding on text files in C.
I'm trying to generalize it to binary files but I have no experience working with them. I understand that, while I can compare bytes of binary data much the same way I can compare chars from a text file, I am not sure how to go about printing the number of occurrences of a byte to the compressed version like I do in the code below.
A note on the type of RLE I'm using: bytes that occur more than once in a row are duplicated to signal the next-to-come number is in fact the number of occurrences vs just a number following the character in the file. For occurrences longer than one digit, they are broken down into runs that are 9 occurrences long.
For example, aaaaaaaaaaabccccc becomes aa9aa2bcc5.
Here's my code:
char* encode(char* str)
{
char* ret = calloc(2 * strlen(str) + 1, 1);
size_t retIdx = 0, inIdx = 0;
while (str[inIdx]) {
size_t count = 1;
size_t contIdx = inIdx;
while (str[inIdx] == str[++contIdx]) {
count++;
}
size_t tmpCount = count;
// break down counts with 2 or more digits into counts ≤ 9
while (tmpCount > 9) {
tmpCount -= 9;
ret[retIdx++] = str[inIdx];
ret[retIdx++] = str[inIdx];
ret[retIdx++] = '9';
}
char tmp[2];
ret[retIdx++] = str[inIdx];
if (tmpCount > 1) {
// repeat character (this tells the decompressor that the next digit
// is in fact the # of consecutive occurrences of this char)
ret[retIdx++] = str[inIdx];
// convert single-digit count to string
snprintf(tmp, 2, "%ld", tmpCount);
ret[retIdx++] = tmp[0];
}
inIdx += count;
}
return ret;
}
What changes are in order to adapt this to a binary stream? The first problem I see is with the snprintf call since it's operating using a text format. Something that rings a bell is also the way I'm handling the multiple-digit occurrence runs. We're not working in base 10 anymore so that has to change, I'm just unsure how having almost never worked with binary data.
A few ideas that can be useful to you:
one simple method to generalize RLE to binary data is to use a bit-based compression. For example the bit sequence 00000000011111100111 can be translated to the sequence 0 9623. Since the binary alphabet is composed by only two symbols, you need to only store the first bit value (this can be as simple as storing it in the very first bit) and then the number of the contiguous equal values. Arbitrarily large integers can be stored in a binary format using Elias gamma coding. Extra padding can be added to fit the entire sequence nicely into an integer number of bytes. So using this method, the above sequence can be encoded like this:
00000000011111100111 -> 0 0001001 00110 010 011
^ ^ ^ ^ ^
first bit 9 6 2 3
If you want to keep it byte based, one idea is to consider all the even bytes frequencies (interpreted as an unsigned char) and all the odd bytes the values. If one byte occur more than 255 times, than you can just repeat it. This can be very inefficient, though, but it is definitively simple to implement, and it might be good enough if you can make some assumptions on the input.
Also, you can consider moving out from RLE and implement Huffman's coding or other sophisticated algorithms (e.g. LZW).
Implementation wise, i think tucuxi already gave you some hints.
You only have to address 2 problems:
you cannot use any str-related functions, because C strings do not deal well with '\0'. So for example, strlen will return the index of the 1st 0x0 byte in a string. The length of the input must be passed in as an additional parameter: char *encode(char *start, size_t length)
your output cannot have an implicit length of strlen(ret), because there may be extra 0-bytes sprinkled about in the output. You again need an extra parameter: size_t encode(char *start, size_t length, char *output) (this version would require the output buffer to be reserved externally, with a size of at least length*2, and return the length of the encoded string)
The rest of the code, assuming it was working before, should continue to work correctly now. If you want to go beyond base-10, and for instance use base-256 for greater compression, you would only need to change the constant in the break-things-up loop (from 9 to 255), and replace the snprintf as follows:
// before
snprintf(tmp, 2, "%ld", tmpCount);
ret[retIdx++] = tmp[0];
// after: much easier
ret[retIdx++] = tmpCount;
I am using Tiva C Series TM4C123GH6PM with Code Composer Studio for getting data from another microcontroller of the same type. Well, I get the data in bytes. The Goal of project is to assemble each 8 bytes and convert them to double then send these double to the computer. I have to use USART to send the data to the computer.
When I use USART, I have two Methods:
One to get data from a USART_x: UARTCharGet(UART1_BASE)
The other to send the data over USART_x: UARTCharPut(UART0_BASE,d)
The problem consists in having two methods that accept only characters. So using these methods for double is impossible since a double is 8 bytes and a character is one byte. I am trying to send doubles to my computer. Any idea?
The second Problem is to write a program from the side of the computer to get the data (bytes) from the microcontroller.
Should I write this program in c (an alternative is using matlab because I will use these data for simulation)?
How can I access com-Port in c (or in matlab if it is possible)?
You need to find a way to break up large amounts of data, and send it to the client, who then needs a way to re-assemble the data, and also know when such data is being sent.
A very simple approach would be to convert all the digits of the double to characters. Inefficient, but it gets the job done easily enough, as shown below. The reason this is preferable is because it lets you easily create your own "instruction set". For example, you could reserve the character '!' as "the letter following ! denotes a special instruction", so when the client sees the sequence "!d", it knows the following 32 bytes of data represent a double, and to re-assemble it.
If you just send the raw bytes, it becomes more convoluted when you want to create escape codes or op codes to signal special circumstances to the client.
Code Listing
#include <stdio.h>
#define BUF_LEN (32)
typedef union {
float f;
struct {
unsigned int mantissa : 23;
unsigned int exponent : 8;
unsigned int sign : 1;
} parts;
} double_cast;
int main(void)
{
double_cast d1;
d1.f = 0.15625;
printf("sign = %x\n",d1.parts.sign);
printf("exponent = %x\n",d1.parts.exponent);
printf("mantissa = %x\n",d1.parts.mantissa);
char buf[BUF_LEN+1] = { 0 };
snprintf(buf, BUF_LEN+1, "%01X%08X%023X", d1.parts.sign, d1.parts.exponent,
d1.parts.mantissa);
// Send over UART
printf("Double as string: [%s]\n", buf);
//UART_printf("!d%s", buf);
return 0;
}
Sample Output
sign = 0
exponent = 7c
mantissa = 200000
Double as string: [00000007C0000000000000000020000]
Credit for the code to break a double into a string goes to u/eran.
Another solution (similar to the solution of Krystian) that works for me. I defined a function that has as parameters a double and an array of Bytes. The double must be converted to an array of Bytes. That´s why I defined an array of Bytes which has a size of 8 Bytes. Here some code:
unsigned char bytesArray[sizeof(double)];
unsigned char * doubleToBytes(double num,unsigned char bytes []){
return memcpy(bytes,&num,sizeof(double));
}
After getting the Bytes in the Array you can send data using the following loop:
for(i=0;i<sizeof(double);i++){
UARTCharPut(UART1_BASE,(unsigned char)*(bytesArray+i));
}
Generally speaking you are facing here serialization problem and the best approach would be using specialized library for this purpose.
In a dirty but simple way you can solve it like that. You have to just properly assemble your data on the other side back to double.
typedef union _MyDouble {
double d;
unsigned char bytes[sizeof(double)];
} MyDouble;
MyDouble my_double;
my_double.d = 1.234;
for(i=0; i < sizeof(double); i++) {
UARTCharPut(UART0_BASE, (char)my_double.bytes[i]).
}
The other thing is that if you are using UART you should encapsulate this union into some frame e.g. in order to successfully reassemble this on the other side.
_____________ ________ __________ ___________ ________
| | | | | |
| FRAME_BEGIN | LENGTH | MyDouble | FRAME_END | CRC-8? |
|_____________|________|__________|___________|________|
The next thing is that you should probably enforce byte alignment on this struct which is done by the compiler directives. It ensures that your struct has no padding bytes etc. and allocates minimum requires size. This is very popular in embedded applications use-cases where some binary object is going to be transmitted on the serial interface - which is exactly your case. Such a simple solution might work on specific hw+sw configuration but for sure it is not portable and good solution from professional point of view.
I'm programming AVR microcontroller Atmega16 in C.
I don't understand C, i spend my time programming in PHP, and i just don't get it in C.
I don't get also how can i post sourcecode here.
If someone know, please fix my tags.
My problem is, i have this function:
unsigned char
convert_sn_to_string (const unsigned char *SN_a /* IDstring */ )
{
unsigned char i;
for (i = 0; i < 6; i++) //6 byte az SN
{
if(SN_a[i]==0x00)
{
Send_A_String("00");
}
}
return 1;
}
Inside for loop i can acces 6 byte value by hex.
Inside variable SN_A i can have
SN_A[0]=0x00;
SN_A[1]=0xFF;
SN_A[3]=0xAA;
SN_A[4]=0x11;
(...)
and similar.
It could be from 00 to FF.
What i need, is to convert that code to 12 char string.
If i have
SN_A[0]=0x00;
SN_A[1]=0xFF;
SN_A[3]=0xAA;
SN_A[4]=0x11;
(...)
I would like get at output
new[0]=0;
new[1]=0;
new[2]=A;
new[3]=A;
new[4]=1;
new[5]=1;
(...)
and so to 12, because i would like change that 6 (double) AA values, to separated.
So then i can do a loop
for i=0 i<12 i++
{
do_something_with_one_letter(new[i]);
}
Now i can play with that values, i can send them to display, or anything i need.
A hex value is simply another way of writing integers. 0xFF == 255.
So, if you want to "split" them, you need to first decide how you want to split them. This, essentially, decides on the exact way you stuff the split values into your new array.
To split a value, something like this can be used:
hexval = 0x1A
low_nybble = hexval & 0xF
high_nybble = (hexval >> 4) & 0xF
You now have 1 stored in high_nybble and 10 stored in low_nybble.
I am trying to read pixel data from a PPM file. I have a function to read the header so I know it's pointing to the beginning of the pixel data. I tried using fgetc(file) but if the value is more than one digit it will not work. I also tried using an array and converting the array to an int or char but I have no way of knowing how many digits each value is. I'm also not sure if the values are separated by whitespace or not. Basically I need a way to extract the pixel data. (I'm using C.)
My code right now is:
char read_byte(FILE *ipt) {
int c, i=0, sum=0;
while (i<16) {
c=fgetc(ipt);
if((i%2)!=0 {
if(c&1) {
sum+=pow(2,i/2);
}
}
i++;
}
return (char)sum;
}
EDIT:
At first I thought the file was stored as the ASCII values, then I realized it's stored as binary. Right now I think I'm making it act like hex. I'm not sure if that's correct. I'm really stuck.
EDIT: changed my code a bit
char read_byte(FILE *ipt) {
int c, i=0, sum=0;
while(i<8) {
c = fgetc(ipt);
c=c&1;
sum+=c*pow(2,i);
i++;
}
return sum;
}
I print the sum as %c
Must you write this for an assignment, or is it for pleasure, or could you use someone else's code?
There is an Open Source solution.
"Netpbm is a package of graphics programs and a programming library. " which includes programs to read PPM at http://netpbm.sourceforge.net/doc/
Edit:
Have you got, or read the definition of the file format, e.g. http://netpbm.sourceforge.net/doc/ppm.html?
It looks like the data is either sequences of one byte RGB triples, or sequences of two byte RGB triples.
The program can detect which format is used from item 7 "The maximum color value (Maxval)". It says "If the Maxval is less than 256, it is 1 byte. Otherwise, it is 2 bytes."
So you code a function which reads one byte/component RGB data, then code another to read two byte/component RGB data.
The program can choose which to call once it has read the value of Maxval.
Edit {
According to the document at that link, the image data in a 'P6' ppm is binary.
So if MaxValue is <256, and hence the data for each colour component is one byte, then reading three bytes, with three calls of fgetc(fp) would return the binary value of one RGB pixel.
If the program has read the header, it has the values of width and height for the image data. So it could allocate an array for every row (width wide of RGB pixels), and an array of pointers to each allocated pixel row array. Then read the binary data into each row, and the program has something straightforward to operate on; a 2d array.
} end edit
My reading of your question suggests you already know how to read one byte data using fgetc.
Edit - it seems like this is irrelevant:
You can read two byte data by calling fgetc twice, and shifting and bit or-ing the data, e.g. (partly ignoring error checking):
int a = fgetc(fp);
int b = fgetc(fp);
if (a >= 0 && b >= 0) { // then all is okay
unsigned int twobyte = (a<<8) | b; // or (b<<8) | a; depending on byte order
// ...
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Best algorithm to count the number of set bits in a 32-bit integer?
Hello,
Is there a more compact way of counting the number of ones in a byte without using a loop? I don't want to do the following if I don't have to. Thanks.
char myValue = 0x0F;
int counter = 0;
while (myValue > 0)
{
if (myValue & 0x01)
{
counter ++;
}
myValue = myValue >> 1;
}
((i>>3)&1)+((i>>2)&1)+((i>>1)&1)+(i&1)
Or use assembly (SSE/MMX).
http://gurmeet.net/puzzles/fast-bit-counting-routines/
This works if you initialize the table correctly.
static const unsigned char one_bits_in_byte[] = { 0, 1, 1, 2, 1, ... };
int counter = one_bits_in_byte[myValue & 0xFF];
Of course, you'd write a program with a loop in it to generate the table so that your final program doesn't have a loop in it. If you are feeling cost conscious, you can encode just the data for 0..15 and process the two halves (nybbles) of the value with shifts. But with 24 GB of physical memory, this is unlikely to be a major problem. And you could also simply compute the value on demand with masking operations, etc (like VGE suggests, but extended to a whole byte).