Reading someone's C code, can't seem to decipher bitwise operations - c

I've been researching for an Arduino project I will be starting soon and I came across some relevant code (Un-commented...) but I can't seem to decipher how the most important part works! The way the code should work is there are 4 bytes in question (yaw, pitch, throttle, and trim (all dec values)) and each bit in each byte corresponds to a sequence of LED flashes encoded in the sendZero() and sendOne() commands. Here is the code in question:
void sendCommand() {
byte b;
sendHeader();
for (int i=0; i<=7; i++) {
b = (yaw & (1 << i)) >> i;
if (b > 0) sendOne(); else sendZero();
}
for (int i=0; i<=7; i++) {
b = (pitch & (1 << i)) >> i;
if (b > 0) sendOne(); else sendZero();
}
for (int i=0; i<=7; i++) {
b = (throttle & (1 << i)) >> i;
if (b > 0) sendOne(); else sendZero();
}
for (int i=0; i<=7; i++) {
b = (trim & (1 << i)) >> i;
if (b > 0) sendOne(); else sendZero();
}
}
The part that gets me is the inside of each for-loop as I have no clue what's going on with those bitwise operations. My guess is they are somehow converting the dec value into binary and then iterating through it, registering zeros or ones accordingly? It's this:
b = (x & (1 << i)) >> i;
where I can't seem to see what's going on or why. Any help would be appreciated.

You are checking the each bit of x (0 to 7) in the code by doing
b = (x & (1 << i)) >> i;
Say for example: You want to display 0 on the led. the seven segment code for displaying 0 on led is 0X3F (The variable x has the value 0X3F). (For more on seven segment display).
You are checking the each bit of the 0X3F and the variable 'b' has the value whether the bit i is 0 or 1.
`0X3F` is
0 1 1 1 1 1 1 1
3 F
For example:
int main()
{
int i, x, b;
x = 0x3F;
for(i = 0; i< 7; i++)
{
b = (x & (1 << i)) >> i;
printf("%d ", b); // I am printing the value of b here
}
getchar();
return 0;
}
Will print
1 1 1 1 1 1 0
when you say
b = (yaw & (1 << i)) >> i;
if (b > 0) sendOne(); else sendZero();
the variable yaw is having the seven segment code for the number you want to display on LED and you are checking each bit of yaw. If the bit is 1 you are calling sendOne() function, which might be sending a high voltage to the LED and which will light up the corresponding LED in the 7 segment display. If the bit is 0, you are calling sendZero() to send a low voltage.
Here you can notice that you are trying to light up the individual LEDs in the 7 Segment. The above program will be so fast that, you will see all the LEDs (who's bits are 1 as per the 7 segment code)lighted up.

Those are left shifts << and right shifts >> respectively.
A left shift is equivalent to multiplication by some power of two.
a << 1; // a * 2.
A right shift is division,
a >> 1; // a / 2.
The constant one is indicates 21 (or the value 2).

To expand. each x & (1 << i) is creating a mask of the desired bit and testing it against x
x & 00000001
x & 00000010
etc..
x & 01000000
x & 10000000
and then shifting the bit of interest down to the LSB so that it can be tested with b = (result of mask and input) >> i; as to transmit either a one or zero. Where the for loop walks the desired bit across the byte.
Note: this later part is not really needed as it will be greater then zero, regardless of it being shifted to the 1's bit.
since you are looking at helicopter code. I would like to point out mine, as I have decoded several common 3.5ch.
Library
and Demo INO
it is a bit cleaner in that bit structures assemble the message and a union shifts it all out, regardless of the different formats.

Related

Reversing Endianess C

I'm lost on bit shifting operations, I'm trying to reverse byte order on 32 bit ints, what I've managed to look up online I only got this far but cant seem to find why its not working
int32_t swapped = 0; // Assign num to the tmp
for(int i = 0; i < 32; i++)
{
swapped |= num & 1; // putting the set bits of num
swapped >>= 1; //shift the swapped Right side
num <<= 1; //shift the swapped left side
}
And I'm printing like this
num = swapped;
for (size_t i = 0; i < 32; i++)
{
printf("%d",(num >> i));
}
Your code looks likes its attempting to swap bits, and not bytes. If you are wanting to swap bytes, then the 'complete' method would be:
int32_t swapped = ((num >> 24) & 0x000000FF) |
((num >> 8) & 0x0000FF00) |
((num << 8) & 0x00FF0000) |
((num << 24) & 0xFF000000);
I say 'complete', because the last bitwise-and can be omitted, and the first bitwise-and can be omitted if num is unsigned.
If you want to swap the bits in a 32bit number, your loop should probably max out at 16 (if it's 32, the first 16 steps will swap the bits, the next 16 steps will swap them back again).
int32_t swapped = 0;
for(int i = 0; i < 16; ++i)
{
// the masks for the two bits (hi and lo) we will be swapping
// shift a '1' to the correct bit location based on the index 'i'
uint32_t hi_mask = 1 << (31 - i);
uint32_t lo_mask = 1 << i;
// use bitwise and to mask out the original bits in the number
uint32_t hi_bit = num & hi_mask;
uint32_t lo_bit = num & lo_mask;
// shift the bits so they switch places
uint32_t new_lo_bit = hi_bit >> (31 - i);
uint32_t new_hi_bit = lo_bit << (31 - i);
// use bitwise-or to combine back into an int
swapped |= new_lo_bit;
swapped |= new_hi_bit;
}
Code written for readability - there are faster ways to reverse the bits in a 32bit number. As for printing:
for (size_t i = 0; i < 32; i++)
{
bool bit = (num >> (31 - i)) & 0x1;
printf(bit ? "1" : "0");
}

XORing a 32 bit integer with itself

I'm stuck on XORing a 32-bit integer with it itself. I'm supposed to XOR the 4 8-bit portions of the integers. I understand how it works, but without storing the integer anywhere, I don't get how to do this.
I've thought it over and I'm thinking of using binary left shift and right shift operators to separate the 32 bit integer into 4 parts to XOR them. For example, if I were to use an 8-bit integer, I would do something like this:
int a = <some integer here>
(a << 4) ^ (a >> 4)
So far, it isn't working the way I thought it would work.
Here's a part of my code:
else if (choice == 2) {
int bits = 8;
printf("Enter an integer for checksum calculation: ");
scanf("%d", &in);
printf("Integer: %d, ", in);
int x = in, i;
int mask = 1 << sizeof(int) * bits - 1;
printf("Bit representation: ");
for (i = 1; i <= sizeof(int) * bits; i++) {
if (x & mask)
putchar('1');
else
putchar('0');
x <<= 1;
if (! (i % 8)) {
putchar(' ');
}
}
printf("\n");
}
Here's an example of an output:
What type of display do you want?
Enter 1 for character parity, 2 for integer checksum: 2
Enter an integer for checksum calculation: 1024
Integer: 1024, Bit representation: 00000000 00000000 00000100 00000000
Checksum of the number is: 4, Bit representation: 00000100
To accumulate the XOR of 8-bit values, you simply shift and XOR each part of the value. Conceptually it's this:
uint32_t checksum = ( (a >> 24) ^ (a >> 16) ^ (a >> 8) ^ a ) & 0xff;
However, since XOR can be done in any order, you can do the same with fewer operations:
uint32_t checksum = (a >> 16) ^ a;
checksum = ((checksum >> 8) ^ checksum) & 0xff;
If you're doing this over many values, you can extend this idea by only condensing the value at the very end. This is quite similar to how parallel commutative operations are done in larger registers with technologies like SIMD (and indeed, compilers with SIMD support should be able to optimize the following code to make it much faster):
uint32_t simple_checksum( uint32_t *v, size_t count )
{
uint32_t checksum = 0;
uint32_t *end = v + count;
for( ; v != end; v++ )
{
checksum ^= *v; /* accumulate XOR of each 32-bit value */
}
checksum ^= (checksum >> 16); /* XOR high and low words into low word */
checksum ^= (checksum >> 8 ); /* XOR each byte of low word into low byte */
return checksum & 0xff; /* everything from bits 8-31 is rubbish */
}
In general Xoring a number with itself should provide you with the value 0 so you can just as easily set the variable to 0.
0100101^0100101=0
This is a result of the Karnaugh map for the xor operation providing a 0 when both bits are a one, or both are a zero.

Pushing Nibbles onto an integer stack in C

I have an unsigned integer, and I want to push nibbles into it. For example, if I have nibbles with values 1, 2, 3, 4, 5, 6, 7 & 8, I want to be able to push the first nibble into my integer to make:
0x10000000 (268435456)
After the second push, I will have:
0x12000000 (301989888)
After the third push, I will have:
0x12300000 (305135616)
And so forth. Does anyone have a neat and cunning idea for how I might achieve this? The solution will need to be able to be given any number as a starting point and push onto the first available zero. So providing int 301989888 as a starting point and pushing 3 will result in 305135616. Pushing from MSB or LSB would be useful as well.
My apologies. It sounds like an exam question. It isn't - I just want to try an experiment, and I'm stuck before I start!
The answer ticked is perfect! I've modified it slightly as follows (just to make it self contained), and I'm as a happy as a tick!
#define left 0
#define right 1
void push(unsigned* number, int nibble,int direction){
int i, shift;
if (direction){
for (i = 28; i >= 0; i -= 4){
if (!(*number & (0xfU << i)))
shift = i;
}
}
else{
for (i = 0; i <= 28; i += 4){
if (!(*number & (0xfU << i)))
shift = i;
}
}
*number|=nibble<<shift;
}
Called as follows:
push(&x,nibble,left);
My apologies for the formatting.
There are two things you need to do - detect where to put the next nibble, and then put it there. For detection, you can mask & shift:
int nextLocation(uint32_t x)
{
int i;
for (i = 28; i >= 0; i -= 4)
{
if (!(x & (0xfU << i)))
return i;
}
return -1;
}
This function will return the amount of upshift you need to "push" your next nibble (or -1 if your integer is already full).
Then, you need to put in the new value (assuming that x is the value you want to push into and nibble is the value you want to push):
int shiftAmount = nextLocation(x);
x |= nibble << shiftAmount;
To push the other direction, you can just change the direction of the for loop in the nextLocation function:
for (i = 0; i <= 28; i += 4)
Here is an overly simple example which does what you want. It "pushes," but not in an automated way (if that's what you're looking for). But this demonstrates the concept (note: I combined each nibble into a byte).
#include <iostream>
using namespace std;
int main()
{
int x = (0x12 << 24) | (0x34 << 16) | (0x56 << 8) | (0x78);
cout<< hex << x << endl;
return 0;
}

Bitwise operations equivalent of greater than operator

I am working on a function that will essentially see which of two ints is larger. The parameters that are passed are 2 32-bit ints. The trick is the only operators allowed are ! ~ | & << >> ^ (no casting, other data types besides signed int, *, /, -, etc..).
My idea so far is to ^ the two binaries together to see all the positions of the 1 values that they don't share. What I want to do is then take that value and isolate the 1 farthest to the left. Then see of which of them has that value in it. That value then will be the larger.
(Say we use 8-bit ints instead of 32-bit).
If the two values passed were 01011011 and 01101001
I used ^ on them to get 00100010.
I then want to make it 00100000 in other words 01xxxxxx -> 01000000
Then & it with the first number
!! the result and return it.
If it is 1, then the first # is larger.
Any thoughts on how to 01xxxxxx -> 01000000 or anything else to help?
Forgot to note: no ifs, whiles, fors etc...
Here's a loop-free version which compares unsigned integers in O(lg b) operations where b is the word size of the machine. Note the OP states no other data types than signed int, so it seems likely the top part of this answer does not meet the OP's specifications. (Spoiler version as at the bottom.)
Note that the behavior we want to capture is when the most significant bit mismatch is 1 for a and 0 for b. Another way of thinking about this is any bit in a being larger than the corresponding bit in b means a is greater than b, so long as there wasn't an earlier bit in a that was less than the corresponding bit in b.
To that end, we compute all the bits in a greater than the corresponding bits in b, and likewise compute all the bits in a less than the corresponding bits in b. We now want to mask out all the 'greater than' bits that are below any 'less than' bits, so we take all the 'less than' bits and smear them all to the right making a mask: the most significant bit set all the way down to the least significant bit are now 1.
Now all we have to do is remove the 'greater than' bits set by using simple bit masking logic.
The resulting value is 0 if a <= b and nonzero if a > b. If we want it to be 1 in the latter case we can do a similar smearing trick and just take a look at the least significant bit.
#include <stdio.h>
// Works for unsigned ints.
// Scroll down to the "actual algorithm" to see the interesting code.
// Utility function for displaying binary representation of an unsigned integer
void printBin(unsigned int x) {
for (int i = 31; i >= 0; i--) printf("%i", (x >> i) & 1);
printf("\n");
}
// Utility function to print out a separator
void printSep() {
for (int i = 31; i>= 0; i--) printf("-");
printf("\n");
}
int main()
{
while (1)
{
unsigned int a, b;
printf("Enter two unsigned integers separated by spaces: ");
scanf("%u %u", &a, &b);
getchar();
printBin(a);
printBin(b);
printSep();
/************ The actual algorithm starts here ************/
// These are all the bits in a that are less than their corresponding bits in b.
unsigned int ltb = ~a & b;
// These are all the bits in a that are greater than their corresponding bits in b.
unsigned int gtb = a & ~b;
ltb |= ltb >> 1;
ltb |= ltb >> 2;
ltb |= ltb >> 4;
ltb |= ltb >> 8;
ltb |= ltb >> 16;
// Nonzero if a > b
// Zero if a <= b
unsigned int isGt = gtb & ~ltb;
// If you want to make this exactly '1' when nonzero do this part:
isGt |= isGt >> 1;
isGt |= isGt >> 2;
isGt |= isGt >> 4;
isGt |= isGt >> 8;
isGt |= isGt >> 16;
isGt &= 1;
/************ The actual algorithm ends here ************/
// Print out the results.
printBin(ltb); // Debug info
printBin(gtb); // Debug info
printSep();
printBin(isGt); // The actual result
}
}
Note: This should work for signed integers as well if you flip the top bit on both of the inputs, e.g. a ^= 0x80000000.
Spoiler
If you want an answer that meets all of the requirements (including 25 operators or less):
int isGt(int a, int b)
{
int diff = a ^ b;
diff |= diff >> 1;
diff |= diff >> 2;
diff |= diff >> 4;
diff |= diff >> 8;
diff |= diff >> 16;
diff &= ~(diff >> 1) | 0x80000000;
diff &= (a ^ 0x80000000) & (b ^ 0x7fffffff);
return !!diff;
}
I'll leave explaining why it works up to you.
To convert 001xxxxx to 00100000, you first execute:
x |= x >> 4;
x |= x >> 2;
x |= x >> 1;
(this is for 8 bits; to extend it to 32, add shifts by 8 and 16 at the start of the sequence).
This leaves us with 00111111 (this technique is sometimes called "bit-smearing"). We can then chop off all but the first 1 bit:
x ^= x >> 1;
leaving us with 00100000.
An unsigned variant given that one can use logical (&&, ||) and comparison (!=, ==).
int u_isgt(unsigned int a, unsigned int b)
{
return a != b && ( /* If a == b then a !> b and a !< b. */
b == 0 || /* Else if b == 0 a has to be > b (as a != 0). */
(a / b) /* Else divide; integer division always truncate */
); /* towards zero. Giving 0 if a < b. */
}
!= and == can easily be eliminated., i.e.:
int u_isgt(unsigned int a, unsigned int b)
{
return a ^ b && (
!(b ^ 0) ||
(a / b)
);
}
For signed one could then expand to something like:
int isgt(int a, int b)
{
return
(a != b) &&
(
(!(0x80000000 & a) && 0x80000000 & b) || /* if a >= 0 && b < 0 */
(!(0x80000000 & a) && b == 0) ||
/* Two more lines, can add them if you like, but as it is homework
* I'll leave it up to you to decide.
* Hint: check on "both negative" and "both not negative". */
)
;
}
Can be more compact / eliminate ops. (at least one) but put it like this for clarity.
Instead of 0x80000000 one could say ie:
#include <limits.h>
static const int INT_NEG = (1 << ((sizeof(int) * CHAR_BIT) - 1));
Using this to test:
void test_isgt(int a, int b)
{
fprintf(stdout,
"%11d > %11d = %d : %d %s\n",
a, b,
isgt(a, b), (a > b),
isgt(a, b) != (a>b) ? "BAD!" : "OK!");
}
Result:
33 > 0 = 1 : 1 OK!
-33 > 0 = 0 : 0 OK!
0 > 33 = 0 : 0 OK!
0 > -33 = 1 : 1 OK!
0 > 0 = 0 : 0 OK!
33 > 33 = 0 : 0 OK!
-33 > -33 = 0 : 0 OK!
-5 > -33 = 1 : 1 OK!
-33 > -5 = 0 : 0 OK!
-2147483647 > 2147483647 = 0 : 0 OK!
2147483647 > -2147483647 = 1 : 1 OK!
2147483647 > 2147483647 = 0 : 0 OK!
2147483647 > 0 = 1 : 1 OK!
0 > 2147483647 = 0 : 0 OK!
A fully branchless version of Kaganar's smaller isGt function might look like so:
int isGt(int a, int b)
{
int diff = a ^ b;
diff |= diff >> 1;
diff |= diff >> 2;
diff |= diff >> 4;
diff |= diff >> 8;
diff |= diff >> 16;
//1+ on GT, 0 otherwise.
diff &= ~(diff >> 1) | 0x80000000;
diff &= (a ^ 0x80000000) & (b ^ 0x7fffffff);
//flatten back to range of 0 or 1.
diff |= diff >> 1;
diff |= diff >> 2;
diff |= diff >> 4;
diff |= diff >> 8;
diff |= diff >> 16;
diff &= 1;
return diff;
}
This clocks in at around 60 instructions for the actual computation (MSVC 2010 compiler, on an x86 arch), plus an extra 10 stack ops or so for the function's prolog/epilog.
EDIT:
Okay, there were some issues with the code, but I revised it and the following works.
This auxiliary function compares the numbers' n'th significant digit:
int compare ( int a, int b, int n )
{
int digit = (0x1 << n-1);
if ( (a & digit) && (b & digit) )
return 0; //the digit is the same
if ( (a & digit) && !(b & digit) )
return 1; //a is greater than b
if ( !(a & digit) && (b & digit) )
return -1; //b is greater than a
}
The following should recursively return the larger number:
int larger ( int a, int b )
{
for ( int i = 8*sizeof(a) - 1 ; i >= 0 ; i-- )
{
if ( int k = compare ( a, b, i ) )
{
return (k == 1) ? a : b;
}
}
return 0; //equal
}
As much as I don't want to do someone else's homework I couldn't resist this one.. :) I am sure others can think of a more compact one..but here is mine..works well, including negative numbers..
Edit: there are couple of bugs though. I will leave it to the OP to find it and fix it.
#include<unistd.h>
#include<stdio.h>
int a, b, i, ma, mb, a_neg, b_neg, stop;
int flipnum(int *num, int *is_neg) {
*num = ~(*num) + 1;
*is_neg = 1;
return 0;
}
int print_num1() {
return ((a_neg && printf("bigger number %d\n", mb)) ||
printf("bigger number %d\n", ma));
}
int print_num2() {
return ((b_neg && printf("bigger number %d\n", ma)) ||
printf("bigger number %d\n", mb));
}
int check_num1(int j) {
return ((a & j) && print_num1());
}
int check_num2(int j) {
return ((b & j) && print_num2());
}
int recursive_check (int j) {
((a & j) ^ (b & j)) && (check_num1(j) || check_num2(j)) && (stop = 1, j = 0);
return(!stop && (j = j >> 1) && recursive_check(j));
}
int main() {
int j;
scanf("%d%d", &a, &b);
ma = a; mb = b;
i = (sizeof (int) * 8) - 1;
j = 1 << i;
((a & j) && flipnum(&a, &a_neg));
((b & j) && flipnum(&b, &b_neg));
j = 1 << (i - 1);
recursive_check(j);
(!stop && printf("numbers are same..\n"));
}
I think I have a solution with 3 operations:
Add one to the first number, the subtract it from the largest possible number you can represent (all 1's). Add that number to the second number. If it it overflows, then the first number is less than the second.
I'm not 100% sure if this is correct. That is you might not need to add 1, and I don't know if it's possible to check for overflow (if not then just reserve the last bit and test if it's 1 at the end.)
EDIT: The constraints make the simple approach at the bottom invalid. I am adding the binary search function and the final comparison to detect the greater value:
unsigned long greater(unsigned long a, unsigned long b) {
unsigned long x = a;
unsigned long y = b;
unsigned long t = a ^ b;
if (t & 0xFFFF0000) {
x >>= 16;
y >>= 16;
t >>= 16;
}
if (t & 0xFF00) {
x >>= 8;
y >>= 8;
t >>= 8;
}
if (t & 0xf0) {
x >>= 4;
y >>= 4;
t >>= 4;
}
if ( t & 0xc) {
x >>= 2;
y >>= 2;
t >>= 2;
}
if ( t & 0x2) {
x >>= 1;
y >>= 1;
t >>= 1;
}
return (x & 1) ? a : b;
}
The idea is to start off with the most significant half of the word we are interested in and see if there are any set bits in there. If there are, then we don't need the least significant half, so we shift the unwanted bits away. If not, we do nothing (the half is zero anyway, so it won't get in the way). Since we cannot keep track of the shifted amount (it would require addition), we also shift the original values so that we can do the final and to determine the larger number. We repeat this process with half the size of the previous mask until we collapse the interesting bits into bit position 0.
I didn't add the equal case in here on purpose.
Old answer:
The simplest method is probably the best for a homework. Once you've got the mismatching bit value, you start off with another mask at 0x80000000 (or whatever suitable max bit position for your word size), and keep right shifting this until you hit a bit that is set in your mismatch value. If your right shift ends up with 0, then the mismatch value is 0.
I assume you already know the final step required to determine the larger number.

C Read char as binary

This is actually part of a project I'm working on using an avr. I'm interfacing via twi with a DS1307 real-time clock IC. It reports information back as a series of 8 chars. It returns in the format:
// Second : ds1307[0]
// Minute : ds1307[1]
// Hour : ds1307[2]
// Day : ds1307[3]
// Date : ds1307[4]
// Month : ds1307[5]
// Year : ds1307[6]
What I would like to do is take each part of the time and read it bit by bit. I can't think of a way to do this. Basically lighting up an led if the bit is a 1, but not if it's a 0.
I'd imagine that there is a rather simple way to do it by bitshifting, but I can't put my finger on the logic to do it.
Checking whether the bit N is set can be done with a simple expression like:
(bitmap & (0x1 << N)) != 0
where bitmap is the integer value (e.g. 64 bit in your case) containing the bits.
Finding the seconds:
(bitmap & 0xFF)
Finding the minute:
(bitmap & 0xFF00) >> 8
Finding the hour:
(bitmap & 0xFF0000) >> 16
If I'm interpreting you correctly, the following iterates over all the bits from lowest to highest. That is, the 8 bits of Seconds, followed by the 8 bits of Minutes, etc.
unsigned char i, j;
for (i = 0; i < sizeof(ds1307); i++)
{
unsigned char value = ds1307[i]; // seconds, minutes, hours etc
for (j = 0; j < 8; j++)
{
if (value & 0x01)
{
// bit is 1
}
else
{
// bit is 0
}
value >>= 1;
}
}
Yes - you can use >> to shift the bits right by one, and & 1 to obtain the value of the least significant bit:
unsigned char ds1307[7];
int i, j;
for (i = 0; i < 7; i++)
for (j = 0; j < 8; j++)
printf("byte %d, bit %d = %u\n", i, j, (ds1307[i] >> j) & 1U);
(This will examine the bits from least to most significant. By the way, your example array only has 7 bytes, not 8...)
essentially, if the 6 LEDs to show the seconds in binary format are connected to PORTA2-PORTA7, you can PORTA = ds1307[0] to have the seconds automatically lit up correctly.

Resources