Problem understanding some downloaded code

Hi all,

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'?

void setVoltage(int dacpin, bool channel, bool gain, unsigned int mV) {
  unsigned int command = channel ? 0x9000 : 0x1000;
  command |= gain ? 0x0000 : 0x2000;
  command |= (mV & 0x0FFF);
  
  SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0));
  digitalWrite(dacpin,LOW);
  SPI.transfer(command>>8);
  SPI.transfer(command&0xFF);
  digitalWrite(dacpin,HIGH);
  SPI.endTransaction();
}

Thanks for any help getting me to understand this code.

Cheers

NM

Hi @nuttymonk .
Line 2: unsigned int command = channel ? 0x9000 : 0x1000;
use conditional_operator.

Now,
"|" is a "bitwise or" and "&" is a "bitwise and", ie they make logical bitwise operations.

Ex: old = 0x45, new = 0xA7 , old | new --->> 0XEF
0100 0101 ....................1010 0111 -----> 1110 1111

bitshift '>>' (x) shifts x bits by one value to the right.
blue = 0xA0 blue>>3 = 0x15
1010 1001 ------>> 0001 0101

RV mineirin

command |= gain ? 0x0000 : 0x2000;`

Is equivalent to

if (gain == 0) command = command | 0x2000;

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 if you see

x += y;

it's a better way to say exactly

x = x + y;

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.

a7

Wow,

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.

Thanks Arduino.cc forum members !!!

NM

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.