Help in understanding SPI and I2C Code (Bit Math)

Hi, I'm hoping someone more knowledgeable will have the generosity to help me understand some code I'm looking at modifying.
Below is a code block used to drive an MCP4911 (10-bit SPI DAC).

(dat is a number from 0-1023)

 digitalWrite(LDAC, HIGH) ;//spi communication
 digitalWrite(SS, LOW) ;
 SPI.transfer((dat >> 6) | 0x30) ;
 SPI.transfer((dat << 2) & 0xff) ;
 digitalWrite(SS, HIGH) ;
 digitalWrite(LDAC, LOW) ;

What I can't understand are the two SPI.transfer lines.

I understand >> 6 means shift the bits 6 bits to the right, and the | 0x30 is some kind of bit-setting "mask", but this translates to 110000 so I'm not sure what bits exactly it is acting on.

I understand << 2 means shift the bits 2 bits to the left and similarly 0xff is 11111111 so we are changing 8 of the bits.

What I can't understand is why we are shifting the bits 6 increments and then 2 increments, and how the 6-bit and 8-bit binary masks relate to what is two bytes.

I feel like I'm missing some knowledge involving the 'order' of the bits (I have looked at the datasheet and this code for hours now and it looks like the first 4 bits are to set the DAC commands, then data is the next 10 bits, then 2 bits are ignored... How this relates to shifting 6 bits across and 2 back I don't know.

I'm trying to understand this code in order to translate the larger piece of code to work with a different DAC (MCP7425, an I2C 12-bit DAC). I have a different piece of reference code that's closely related to the same function as the SPI code above, but this is shifting the bits by 8 positions.

 Wire.beginTransmission(0x60);
 Wire.write((MCP_OUT >> 8) & 0x0F);
 Wire.write(MCP_OUT);
 Wire.endTransmission();

Again, I have studied the code and datasheet at length and it looks to me like the first 4 bits should be command data, then the next 12 bits are the data-data.

As there are 2-bits of difference in how much the two codes are shifting the bits, I am assuming this is related to the DAC's bit counts somehow, but I don't have the intellect to figure out what is going on.

I would really appreciate any advice about this.

Datasheet: http://ww1.microchip.com/downloads/en/devicedoc/22248a.pdf

If you look at chapter 5, it describes the register. The register that you write to is a 16-bit register so two SPI transfers are used. Looking at that register (datasheet register 5-2) states that the first byte that you transfer contains D5-D0 and the lower two bits are "don't care"; this is the second SPI.transfer in your code
The first transfer contains the remaining bits D9-D6 of the value; shifting it 6 to the right moves those to the beginning of the byte that you're going to transfer; the 0x30 are the settings for the /GA and /SHDN bits.

1 Like

Thank you... From what you are saying, it seems like everything is communicated "in reverse"? I see that the 5-2 register on the datasheet does show bit 15 being the first bit and bit 0 being the last bit which would make sense.

I think I'm getting confused with this concept and shifting bits to the right/left... It feels like shifting the 10-bit data 6 to the right would lose the last 6 bits of the data, but I think I understand we are actually shifting bits to the left by 6, when performing the >> 6. Wouldn't that mean the binary representation of our data is actually reversed though?

Sorry for being so lost, as you can probably see, this is my first experience with this aspect of coding.

[quote="snowballinhell, post:3, topic:1264380"]
Wouldn't that mean the binary representation of our data is actually reversed though?
[/quote

I think this explains it:

No, >> is right shift. That instruction is sending the high data bits first, ORed with the control bits /GA and /SHDN.

The next instruction sends the low bits, properly positioned. You need to very carefully study the data sheet to understand those actions.

Apologies for my lack of understanding, but I don't understand this.

Could you explain what ORed is, and what are 'low bits' in this context?

Sounds like you jumped into the deep end before learning to swim.

If you lack the basic concepts of bits, bytes and elementary logic operations, you will need to spend some time learning about those before trying to understand a device data sheet, and device programming.

1 Like

Read this

https://docs.arduino.cc/learn/programming/bit-math/

and here

https://docs.arduino.cc/learn/programming/bit-mask/

which may fill in some gaps or make some sense of it all.

a7

Maybe this visualisation will help.

Note:
The numbers are the number of the bit (0..9) with the exception of 0011 in 0x30 for the first transfer (bottom of image)

@alto777 Thanks for posting to the links to those tutorials in post #8. They are pretty good!

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