Change MSB and leave remaining bits unchanged - c

The question is as follows:
Write a single line of C-code that sets the four MSB in DDRD to 1011 and leave the rest unchanged.
The best I can do is:
DDRD = (DDRD & 0xF) | (1<<7) | (1<<5) | (1<<4);
or just
DDRD = (DDRD & 0xF) | (0b1011 << 4);
It gets the job done, but it's certainly not the cleanest. Is there a better solution I'm not seeing?

The most readable and conventional form ought to be something like:
#define DDRD7 (1u << 7)
#define DDRD6 (1u << 6)
...
DDRD = (DDRD & 0x0Fu) | DDRD7 | DDRD5 | DDRD4;
Alternatively the bit masks could also be named something application-specific like LED2 or whatever. Naming signals the same way in the firmware as in the schematic is very good practice.
"Magic numbers" should be avoided, except 0xF which is used for bit-masking purposes so it's fine to use and self-documenting. DDRD & (DDRD0|DDRD1|DDRD2|DDRD3) would be less readable.
1<< should always be avoided since left-shifting a signed integer (1 has type int) is pretty much always a bug. Use 1u<<.
Binary constants should be avoided since they are not (yet) standard and may not be supported. Plus they are very hard to read when numbers get large. Serious beginner programmers are expected to understand hex before writing their first line of code, so why more experienced programmers ever need to use binary, I don't know.
Regarding 0xFu vs 0x0Fu, they are identical, but the latter is self-documenting code for "I am aware that I'm dealing with an 8 bit register".

Related

Weird problem in Fujitsu Softune IDE - wrong calculation of 11 bit CAN ID

The code below is part of my code to read CAN ID in Rx callback:
tmpp = (((0x07 << 0x1D)|(0x368 << 0x12)) & 0x1FFC0000); //unsigned long long int tmpp - equal to 0xDA00000
if (CAN0_IF2ARB0_ID == tmpp) {
//do some action
}
The problem is that while the 29 bit CAN ID is 0xDA00000, the condition is not true. But when I directly set tmpp as tmpp = 0xDA00000, the program successfully enters the loop. In fact, the calculation tmpp = (((0x07 << 0x1D)|(0x368 << 0x12)) & 0x1FFC0000); seems to have some problem (the value is 0xDA00000, but in Softune, it is not calculated correctly). I would be grateful if you could help me to find the problem. Thanks.
0x07 is an int - perhaps even a 16-bit int. Use at least unsigned long constants for values to be shifted into a 32-bit value.
// tmpp = (((0x07 << 0x1D)|(0x368 << 0x12)) & 0x1FFC0000);
tmpp = ((0x07ul << 0x1D) | (0x368ul << 0x12)) & 0x1FFC0000u;
Left-shifting an integer constant such as 1 is almost always a bug, because integer constants in C have a type just like variables and in most cases it is int. Now since int is a signed type, we cannot left shift data into the sign bit or we invoke undefined behavior. 0x07 << 0x1D does exactly that, it shifts data into bits 31 (sign bit), 30 and 29.
Solve this by always adding an u suffix to all your integer constants.
Furthermore, you shouldn't use "magic numbers" but named constants. And in case you mean to shift something 29 bits, use decimal notation 29 since that's self-documenting code.
Your fixed code should look something like this (replace "MASKn" with something meaningful):
#define MASK1 (0x07u << 29)
#define MASK2 (0x368u << 18)
#define MASK3 (MASK1 | MASK2)
#define MASK4 0x1FFC0000u
if (CAN0_IF2ARB0_ID == (MASK3 & MASK4))
Also an extended CAN identifier doesn't use those bits 31,30,29... so I have no idea what you are even doing here. If you seek to calculate some value for CAN acceptance filtering etc, then it would seem you seem to have managed to confuse yourself by the original use of hex constants for shifting.

bitwise operation confusion in tutorials

how is:
GIMSK |= (1 << PCIE);
PCMSK |= (1 << PCINT4);
equal to (I can use the above or the below in my setup of my program, both work and activate pin 4), the GIMSK and the PCMSK are for some reason equal to each other, I am trying to learn why.
GIMSK = 0b00100000;
PCMSK = 0b00010000;
first:
https://thewanderingengineer.com/2014/08/11/pin-change-interrupts-on-attiny85/
second:
https://embeddedthoughts.com/2016/06/06/attiny85-introduction-to-pin-change-and-timer-interrupts/
data:
http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-2586-AVR-8-bit-Microcontroller-ATtiny25-ATtiny45-ATtiny85_Datasheet.pdf
The sheet says PCIE is 0b00100000 in the bit mask, so somehow |= (1 << PCIE) equals that? I don't get it if PCIE is supposed to be that, doing a shift would change that value..
how and why would you use that instead of binary? I would guess it changes it but obviously, somehow it doesn't. I've asked this on several different places nobody has an answer so I came here. Hopefully someone can explain.
I'm new to C, I just learned bitwise operations today to try to figure out what is going on here, my code does work with either or but I want to know why! Thanks.
It is equal because all other bits of those registers were 0 before the OR operation
1u << x shifts one by x positions left. As a result you have the number with all bits except x cleared
Short Version
Break apart the compound expression from x |= y to x = x | y
Load integer '1' which is just binary `[0000 0001] and shift it to the spot we want.
Variable is defined in a header, or elsewhere which says where that bit is for compatibility. New card? Just get a new definition file- this is done automatically- usually). PCIE and PCINT4 are defined somewhere, look for it if needed, but this is supposed to handle those details for you.
Yet- we know is PCINT4 is 4 and PCIE is 5 respectively because of the second set- where we see a shifted '1'- 5 spaces for PCIE and 4 spaces for PCINT4. That's why they seem equivalent. Because they are literally equivalent- once you evaluate the expression you know that 0b means that what follows is binary (which might have been obvious). But they are NOT equivalent. Not exactly- see below--
4-So if you "OR" a register, it overrides whatever is there if TRUE and forces it to be what True and leaves everything else alone. We shift that 1 to show the bit we want, then we choose the operant that will have the effect we want. Look at the table for others.**
But we get GIMSK = GIMSK OR 0b00100000 and PCMSK = PCMSK OR 0b00010000;
Which is similar, but not exactly the same thing.
The devil is in the details, see below for
Detailed Explanation.
AKA someone better read this, took me forever.
GIMSK |= (1 << PCIE);
PCMSK |= (1 << PCINT4);
equal to (I can use the above or the below in my setup of my program, both work and activate pin 4), the
GIMSK and the PCMSK are for some reason equal to each other, I am
trying to learn why.
GIMSK = 0b00100000;
PCMSK = 0b00010000;
Let's take it lexicographically by the token to start, so we are all talking about the same thing.
GIMSK |= (1 << PCIE);
Starting at the first bit. Pick it apart-
GIMSK- variable or 'id'
|= - operator and assignment combo bitwise OR and =
1 - the integer 1
<< - shift operation
PCIE - Variable and ID
Of course, this makes it harder to explain. What is |=? I'm certain that led to confusion on this question for some. The better-known one is +=. So if I have a variable x, and I always add to itself, really any time you are counting, etc. the variable is on both sides of the equation. Like this:
x = x + 1 ;this is so common though, that in C, it was shortened to +=
x += 1 ; now its written like this. It takes some time
so programmers are lazy, and if something 'cool' pops up in one language, it usually spreads to the others, so most languages allow this now. It does make a difference if you write += or =+, at least in Java. Won't hit that though.
y = y * 2; it works for other types of operands
y *= 2; Now we take y, multiply by 2 and assign back to y.
Now, let's look at 'C' style bitwise operators- most languages have adopted similar notation though there are exceptions.
Usually in C you use two symbols to compare '&&" or '||' or '=='
Well, that's because the single operator compares bits. This got one symbol because it's much more natural on a computer and much more common. Not to us anymore, we are abstracted away from it by layers of software.
So we have: ** Good Source for more info
Bitwise AND (&)
Bitwise OR (|)
Bitwise XOR (^)
Bitwise NOT (~)
And we can also make this compond (Click for more info)
Basically, they compare some variable on the right with the left and assign it back to the right. Like this x = x* y => x *= y.
Likewise we have x &= y, x |= y and, x ^= y
So for the above- let's unwrap it first- write it out longhand to make it easier to understand-
GIMSK |= (1 << PCIE)
GIMSK = GIMSK | (1 << PCIE) #OK! much easier to understand if your new.
#NOW we can lexigraphically analyze this
VarA {assignment} VarA OR ( 1 {Operator} VarB )
#Ignore the assignment side, for now, practice order of Operations
#Start with Parenthetical Exp.
1 {Operator} VarB
#It turns out this is defined.
#OP Didnt know but computer does. = 5 in this case.
#so 1, shift left 5. To bitwise shift, need bits
1 => 0b00000001 << 5 = 0b00100000
# shift left is really multiplied by 2 in base 10, divide by 2 in shift right. Beware Right Shift, esp in float.
So now we have: GIMSK = GIMSK OR 0b00100000
GIMSK |= (1 << PCIE); PCMSK |= (1 << PCINT4);
GIMSK = 0b00100000; PCMSK = 0b00010000;
Which is just what you already said. More or less. The 2nd operations are not equivalent though as I mentioned above in the short answer. Thats covered at the end.
This is Assembly format, GIMSK is an 8-bit register. We created a bitmask, by moving a 1 to the register we want to effect, and putting a 0 in the bits we want to leave alone. The |= means we will compare the two the save it back to the same register. That's it. OR 1 will always turn it on. Which is what we want.
Think about what we want to do to start. We want to set a boolean value to HIGH or TRUE, or 1, however, you put it. We say "Lets set the register bit that we specify if your value (0/1) OR my value (1) is 1." Well, we know our value is 1 because that's what we put. So when you bit-wise OR (is that a verb?), you are writing a value on the basis of one of 2 values being a 1. It either writes a one or leaves a one, unless you send 0 and it sends 0 it stays off.
It says "I think this should be on. If any other process thinks this should be on, leave it even if I don't need it so (it sends a 0)" It's worth thinking through on paper, and thinking through each of the operands. Make a colored table, that's how I got to understand them. Not of the operands will flip the values whatever it is. AND checks the value for you, it leaves the register the same- Operating on each reg will have this effect. I used to have a cheat sheet, I would have loved to include, but I lost it- but it summarized for my dumb brain the behavior of each operand.
REMEMBER- we can not operate on a single bit. This is a critical bit you need to understand. You cant change just one bit. If I have 0010 0010 and I want to say, hey computer, change byte 6. You cant! You have to load the whole word or byte into a register or at least half (16bits in MIPS, 8 in ATMEL 16bit controllers**), and operate on the whole thing. You can't operate directly from memory (Ram, SSD, L2 Cache- way too far away). There's no such thing as popping a single bit into a register to change it, though there are tricks to make new bytes (8bit) in the shape you want. Want just the 6th bit, well {0100 000} -with AND, will get it for you. Then you can shift right, or divide by 2^6, etc. We will get back to this. First- the actions of the Comparators if you care to learn more:
*this chip is 8 bit. Doubt they have half read. Bit
Logical Operators v. Registers
Register(b) Me OR NOR XOR AND NAND N XNOR
1 0 1 0 1 0 1 0 0
0 0 0 1 0 0 1 1 1
1 1 1 0 0 1 0 0 1
0 1 1 0 1 0 1 1 0
So the above looks at the single bit we want to effect. The left 2 columns are all possible scenarios (just 4), where we show the bit of the register in that byte. I keep saying byte. A register is, as I mentioned 16 or 32 bits usually, so I really mean Word. I have just organized this example around a hypothetical 8 bit machine. edit- this is an 8 bit chip, 32 registers. one of which is this one
Now! What do we want to do? We Want to change 1 byte, which represents a boolean value, but we don't want to mess with the rest! If you OR across all 8 bytes- do this on paper- it leaves the values in there already alone. Perfect! That's what we want.
Whatever they are set to, they stay, if it's 1, OR leaves it a 1, if it's 0, it stays.
Ah, I should mention why.
Its because you start with 0000 0001 (1) so everything is 0, except the 1st bit. Why did we start with 0000 0001? because you told it to.
See here syntax Arduino Doc Bitwise Ops
So, without reviewing Binary, 1 in binary is 0000 0001 It should be noted, that in a computer, it can't tell that 11001100 isn't 11,001,100 (eleven million), or if its 204 (binary) or even 285,217,024 (if it was HEX), or 2,359,872 (in Octal).
The compiler and computer 'know' we always think base 10, but the computer never does, just base 2 or compressed for easy human reading, into octal (2^2,) or hex (2^4) eg, each 'character' is 2 bits or 4 bits. 0x0A is 0b1010. And right there is where I am getting at. We indicate the values are not base 10, with a prefix. 0b***** is binary. 0x**** is hex. And I can never remember Octal- no one uses it anyway.
So!
see here if needed: Another practical book I wrote on Bitwise Ops, that covers basic Binary a little.
Then you shift that bit by the PIN NUMBER I don't know the right term, and this is certainly not it, but you say the register you want to effect is the 5th register. Ok.
#take a 1,
0000 0001 = $temp
#shift it 5 spots "<<" , where 5 is the PCIE 'bit' value spot number.
1<<5 = 32
#binary equals 32.
You could replace either GIMSK value with 32 and it would be fine, again equivalent, or 0x020
# 0010 0000
# Then OR this with whats in the register now:
1010 1010 (made up number, a mix of ones and 0s)
0010 0000 (Our Value)
OR=>
1010 1010 Result.
Note how we left the other bits alone, and only changed what we wanted! Effective bit mask!
Now, why does it say PCIE, and whatever the other one is. Its because somewhere, when you compile, there is a file that assigns values to those variables. This allows the code to be compatible across several different chip designs. The ATMEGA and the ATTINY do not have the same interrupt pin. Though it likely goes to the same internal register.
#Take it bit by bit, no Pun intended
GIMSK |= (1 << PCIE);
PCMSK |= (1 << PCINT4);
GIMSK = 0b00100000;
PCMSK = 0b00010000;
Again, starting at the first bit from above.
GIMSK- some variable
|= - bitwise OR
1 - the integer 1
`<`< - shift operation
PCIE - another var
So all you are doing is taking a base 10 integer- 1, which we know equals 0b0000 0001, then we are pushing that 1 (now in binary to the spot indicated by PCIE or PCINT4. So the latter 2 are just simply variables that hold the bit number, so if it changes, the code doesn't break.
From the latter 2 lines, we infer that PCIE is 5 and PCINT4 is 4. GIMSK is now equal to 32 and the other 16. Shifting << and >> has the effect of multiplying or diving by 2. Although, shifting down is risky for reasons I won't get into, but if you need to multiply a number by 2, for a computer, it's much faster to shift left by 1 bit than it is to go through the multiplayer.
We talked about the OR already. It sets a 1, if there's not one, otherwise it leaves the other bits alone because they are 0.
Equivalent or Not??
GIMSK |= (1 << PCIE);
GIMSK = 0b00100000;
GIMSK = GIMSK OR 0b00100000
PCMSK |= (1 << PCINT4);
PCMSK = 0b00010000;
PCMSK = PCMSK OR 0b00010000
So evaluating the 1st expression in each set gets the 3rd equation. But notice they look a little different. They are not equivalent statements, though, as you say they may work. It depends on what those other bits are.
PCMSK = 0b00010000; #This sets the PCMSK register to be exactly
=> PCMSK = `0|0|0|1|0|0|0|0
#While
PCMSK = PCMSK OR 0b00010000; # yields PCMSK = `?|?|?|1|?|?|?|?`
#Obviously,
GIMSK = 0b00001000; # This sets the GIMSK register to be exactly
=> GIMSK = `0|0|0|0|1|0|0|0`
While`GIMSK = GIMSK OR 0b00001000; # yields
GIMSK = ` ?|?|?|?|1|?|?|? `
while the OR statement leaves the other bits alone, if they were set by something else, and just changes the 5 (or 4th bit) as the case my be. The OR statement is probably the better statement. If you found the latter statement suggested in a reputable place though, it's probably fine.
Conclusion
So that's it. It's much easier than you thought probably now that the different bits make sense. I wrote this though with the hope it'll give some lasting insight rather than just a quick answer. Although in truth- it was complicated. There are a LOT of computer science concepts buried in those 2 statements, that if you're not in the know, might as well be hieroglyphics.
All this makes much more sense if you dive into how a computer works.
Check out Chapter 2 and 3 of Computer Organization and Design (5th ed) Patterson and Hennesy. It's the standard. If this is for fun, you can skim it. But the computer has Registered, of a defined width- 8, 16, 32. and 64 or even 128 (rarely e.g. x86 AVX- Intel x86). but usually 32 bit. These are the bits of data in hand, what the processor actually touches. The processor can only operate on registers. So everything, under the hood, will end up back there.
Now using interrupts correctly is a whole other topic. I again recommend the same book- Ch 5 and Appendix A7
Note- My assembly class was in MIPS. I've never specifically studied this microcontroller. If I get some of the architecture wrong, forgive me.

Reinterpreting memory/pointers

Just a quick question concerning the rust programming language.
Assume you had the following in C:
uint8_t *someblockofdata; /* has certain length of 4 */
uint32_t *anotherway = (uint32_t*) someblockofdata;
Regardless of the code not being all that useful and rather ugly, how would I go about doing that in rust? Say you have a &[u8]with a length divisible by 4, how would you "convert" it to a &[u32] and back (preferrably avoiding unsafe code as much as possible and retaining as much speed as possible).
Just to be complete, the case where I would want to do that is an application which reads u8s from a file and then manipulates those.
Reinterpret casting a pointer is defined between pointers to objects of alignment-compatible types, and it may be valid in some implementations, but it's non-portable. For one thing, the result depends on the endianness (byte order) of your data, so you may lose performance anyway through byte-swapping.
First rewrite your C as follows, verify that it does what you expect, and then translate it to Rust.
// If the bytes in the file are little endian (10 32 means 0x3210), do this:
uint32_t value = someblockofdata[0] | (someblockofdata[1] << 8)
| (someblockofdata[2] << 16) | (someblockofdata[3] << 24);
// If the bytes in the file are big endian (32 10 means 0x3210), do this:
uint32_t value = someblockofdata[3] | (someblockofdata[2] << 8)
| (someblockofdata[1] << 16) | (someblockofdata[0] << 24);
// Middle endian is left as an exercise for the reader.

Is there a convenient way of writing simple but long hex values in c?

I'm currently writing a code where I need to modify an 8 Byte variable 1 bit at a time. I was wondering, if there's a more convenient way to write a long but simple hex value like:
Variable & 0x8000000000000000
I know i can declare a char as 0x80 and then cast it to a different type and shift it. I'm just looking for something simpler and more practical.
You can use the bit-wise left shift operator to make it more clear:
variable & 1ULL << 63
well, though it's a shift, but you can use arduino's BV() macro, that is short and convenient:
#define _BV(bit) (1ULL << (bit))
which is used that way:
var & (0x8 * _BV(60));
if you want to work on the byte furthest left or directly:
var & _BV(63);
to access 63rd bit.

bitwise indexing in C?

I'm trying to implement a data compression idea I've had, and since I'm imagining running it against a large corpus of test data, I had thought to code it in C (I mostly have experience in scripting languages like Ruby and Tcl.)
Looking through the O'Reilly 'cow' books on C, I realize that I can't simply index the bits of a simple 'char' or 'int' type variable as I'd like to to do bitwise comparisons and operators.
Am I correct in this perception? Is it reasonable for me to use an enumerated type for representing a bit (and make an array of these, and writing functions to convert to and from char)? If so, is such a type and functions defined in a standard library already somewhere? Are there other (better?) approaches? Is there some example code somewhere that someone could point me to?
Thanks -
Following on from what Kyle has said, you can use a macro to do the hard work for you.
It is possible.
To set the nth bit, use OR:
x |= (1 << 5); // sets the 6th-from
right
To clear a bit, use AND:
x &= ~(1 << 5); // clears
6th-from-right
To flip a bit, use XOR:
x ^= (1 << 5); // flips 6th-from-right
Or...
#define GetBit(var, bit) ((var & (1 << bit)) != 0) // Returns true / false if bit is set
#define SetBit(var, bit) (var |= (1 << bit))
#define FlipBit(var, bit) (var ^= (1 << bit))
Then you can use it in code like:
int myVar = 0;
SetBit(myVar, 5);
if (GetBit(myVar, 5))
{
// Do something
}
It is possible.
To set the nth bit, use OR:
x |= (1 << 5); // sets the 5th-from right
To clear a bit, use AND:
x &= ~(1 << 5); // clears 5th-from-right
To flip a bit, use XOR:
x ^= (1 << 5); // flips 5th-from-right
To get the value of a bit use shift and AND:
(x & (1 << 5)) >> 5 // gets the value (0 or 1) of the 5th-from-right
note: the shift right 5 is to ensure the value is either 0 or 1. If you're just interested in 0/not 0, you can get by without the shift.
Have a look at the answers to this question.
Theory
There is no C syntax for accessing or setting the n-th bit of a built-in datatype (e.g. a 'char'). However, you can access bits using a logical AND operation, and set bits using a logical OR operation.
As an example, say that you have a variable that holds 1101 and you want to check the 2nd bit from the left. Simply perform a logical AND with 0100:
1101
0100
---- AND
0100
If the result is non-zero, then the 2nd bit must have been set; otherwise is was not set.
If you want to set the 3rd bit from the left, then perform a logical OR with 0010:
1101
0010
---- OR
1111
You can use the C operators && (for AND) and || (for OR) to perform these tasks. You will need to construct the bit access patterns (the 0100 and 0010 in the above examples) yourself. The trick is to remember that the least significant bit (LSB) counts 1s, the next LSB counts 2s, then 4s etc. So, the bit access pattern for the n-th LSB (starting at 0) is simply the value of 2^n. The easiest way to compute this in C is to shift the binary value 0001 (in this four bit example) to the left by the required number of places. As this value is always equal to 1 in unsigned integer-like quantities, this is just '1 << n'
Example
unsigned char myVal = 0x65; /* in hex; this is 01100101 in binary. */
/* Q: is the 3-rd least significant bit set (again, the LSB is the 0th bit)? */
unsigned char pattern = 1;
pattern <<= 3; /* Shift pattern left by three places.*/
if(myVal && (char)(1<<3)) {printf("Yes!\n");} /* Perform the test. */
/* Set the most significant bit. */
myVal |= (char)(1<<7);
This example hasn't been tested, but should serve to illustrate the general idea.
To query state of bit with specific index:
int index_state = variable & ( 1 << bit_index );
To set bit:
varabile |= 1 << bit_index;
To restart bit:
variable &= ~( 1 << bit_index );
Try using bitfields. Be careful the implementation can vary by compiler.
http://publications.gbdirect.co.uk/c_book/chapter6/bitfields.html
IF you want to index a bit you could:
bit = (char & 0xF0) >> 7;
gets the msb of a char. You could even leave out the right shift and do a test on 0.
bit = char & 0xF0;
if the bit is set the result will be > 0;
obviousuly, you need to change the mask to get different bits (NB: the 0xF is the bit mask if it is unclear). It is possible to define numerous masks e.g.
#define BIT_0 0x1 // or 1 << 0
#define BIT_1 0x2 // or 1 << 1
#define BIT_2 0x4 // or 1 << 2
#define BIT_3 0x8 // or 1 << 3
etc...
This gives you:
bit = char & BIT_1;
You can use these definitions in the above code to sucessfully index a bit within either a macro or a function.
To set a bit:
char |= BIT_2;
To clear a bit:
char &= ~BIT_3
To toggle a bit
char ^= BIT_4
This help?
Individual bits can be indexed as follows.
Define a struct like this one:
struct
{
unsigned bit0 : 1;
unsigned bit1 : 1;
unsigned bit2 : 1;
unsigned bit3 : 1;
unsigned reserved : 28;
} bitPattern;
Now if I want to know the individual bit values of a var named "value", do the following:
CopyMemory( &input, &value, sizeof(value) );
To see if bit 2 is high or low:
int state = bitPattern.bit2;
Hope this helps.
There is a standard library container for bits: std::vector. It is specialised in the library to be space efficient. There is also a boost dynamic_bitset class.
These will let you perform operations on a set of boolean values, using one bit per value of underlying storage.
Boost dynamic bitset documentation
For the STL documentation, see your compiler documentation.
Of course, you can also address the individual bits in other integral types by hand. If you do that, you should use unsigned types so that you don't get undefined behaviour if decide to do a right shift on a value with the high bit set. However, it sounds like you want the containers.
To the commenter who claimed this takes 32x more space than necessary: boost::dynamic_bitset and vector are specialised to use one bit per entry, and so there is not a space penalty, assuming that you actually want more than the number of bits in a primitive type. These classes allow you to address individual bits in a large container with efficient underlying storage. If you just want (say) 32 bits, by all means, use an int. If you want some large number of bits, you can use a library container.

Resources