i have been using arduino.cc to understand how to code for a while now and find it very useful but recently i've come across some code i don't understand and can't get my head around so i need to ask for help. I don't know much about bitwise operations and masking but i think that is what i am looking at here. It's from a MIDI to CV converter which is taking in MIDI data and sending it to a DAC using SPI.
Is anyone able to explain what the following lines of code are doing? Any help would be greatly appreciated. The main problem i have in understanding this code lies in lines 2-4 and 8-9. Lines 2-4 i can't understand what the '|=', '?', ':' and '&' are doing. Lines 8-9 i don't understand what the bitshift '>>' is being used for and also the '&'. Also how is all of that being stored in an 'unsigned int'?
The ? and : are for the ternary operator, basically a shorthand version of an if statement.
See the commented code below for further explanation.
void setVoltage(int dacpin, bool channel, bool gain, unsigned int mV) {
//unsigned int command = channel ? 0x9000 : 0x1000;
unsigned int command;
if (channel == true) {
command = 0x9000;
} else {
command = 0x1000;
}
//command |= gain ? 0x0000 : 0x2000;
if (gain == true) {
command = command | 0x0000; //bitwise OR of current contents of command with 0x0000
} else {
command = command | 0x2000; //bitwise OR of current contents of command with 0x2000
}
//bitwise OR the current contents of command with the lower 12 bits of mV
// ( (mv & 0x0FFF) performs a bitwise AND to mask off the upper 4 bits of mV)
command |= (mV & 0x0FFF);
SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0));
digitalWrite(dacpin, LOW);
//shifts command 8 bits right,
// placing the upper 8 bits into the lower 8 bit positions,
// and setting upper bits to 0's
// (the effect is to send the upper byte of command on the SPI bus)
SPI.transfer(command >> 8);
//masks off the upper 8 bits of command,
// so that only the lower 8 bits are sent
SPI.transfer(command & 0xFF);
digitalWrite(dacpin, HIGH);
SPI.endTransaction();
}
and the same shorthand can be used for many operators
command |= (mV & 0x0FFF);
is the same as
command = command | (mV & 0x0FFF);
and so forth.
It makes typing and reading easier.
Typing - no need to worry about getting the left hand right typing it twice. The left hand can be complex - it isn't here - and typing it twice is an opportunity to make a mistake that is yet valid, a hard to find error.
Reading - once you get the hang of it, it reads easier - no need to get on one's hands and knees to be sure the left hand side is the same as it is written again on the right hand side.
Again, more important when the left hand side is complex; sometimes it isn't the exact thing you want on the right hand side, using += &c. makes it clears that the left- and right-hand side are, in fact the same expression.
And if the writer is good, if += is not used, it's an instant heads up that the two are different.
Guy in a book said it better, around the time Jim Morrison died. 50 years go today, RIP.
loads of fast, useful answers. Thanks very much everyone. You really helped me out a lot.
Since i'm using an 8-bit DAC in an 8-bit mode, most of this code won't be necessary for me to keep as i modify it further since a lot of it seems to be dealing with 6-bit numbers in a 12-bit DAC. Also i won't be dealing with anything other than a gain of 1 thankfully so more code can be removed.