Reading and Writing I2C to DS1086, ignoring some bits

Hello,

I am trying to read and write to a DS1086 silicon oscillator. I started with I2C scanner and added lines building up reading the registers then writing them.

There are 5 registers to read and 4 to write with then a final command to commit to the EEPROM.

Problem 1: I am unsure how I discard what ever the 3 MSBs are.
What I am finding tricky is recovering, for example, the 5 LSBs of a returned byte.

Eg, the "Range" 0x37 will return

MSB                         LSB
NA	NA	NA	b4	b3	b2	b1	b0

And then I need to recover bits 4 to 0 and apply an offset before writing that new value back.

Problem 2: Writing MSBs to a register, possibly, not sure
After that, i need to write 2 registers for DAC values (0x08 DAC hi and 0X09 DAC low). The Hi i am able to get to work and read back correctly, but the low is not working.

Possibly the issue is the low register value needs to be justified towards the MSB;

MSB                        LSB
b1	b0	0	0	0	0	0	0

EG if my low needs to be 11000000, i would write C0 but it comes back as B1. Even if i write 0x00, i get B1 back.

Register       Address     Sending     Reads Back
Prescaler      0x02        0xF3        0xF3
DAC Hi         0x08        0x4F        0x4F
DAC Lo         0x09        0xC0 / 00   0xB1   //writing anything reads back B1
Offset         0x0E        0xEB        0xEB
Addr           0x0D        NA
Range          0x37        NA          //example 0001 0010  but only interested in 1 00 10
Write EE       0x3F        NA

For writing the DAC values, i tried first writing 2 registers one after the other, but found https://github.com/hvictor/DS1086/blob/main/ds1086_prog.ino and hvictor wrote these sequentially. Not sure the right thing to do.

My full code running on Mega 2560:



#include <Wire.h>
byte devAddr;
byte offsetDefault;
byte currentDAChi;
byte currentDAClo;
byte currentRange;  //offset default
byte currentOffset;
byte currentPrescaler;

void setup() {
  Wire.begin();
  Serial.begin(9200);
  delay(100);
  Serial.println("\nI2C Scanner");

  byte error, address;
  int nDevices;
  Serial.println("Scanning...");
  nDevices = 0;
  for (address = 1; address < 127; address++ ) {
    Wire.beginTransmission(address);
    error = Wire.endTransmission();
    if (error == 0) {
      Serial.print("I2C device found at address 0x");
      if (address < 16) {
        Serial.print("0");
      }
      Serial.println(address, HEX);
      devAddr = address;
      nDevices++;
    }
    else if (error == 4) {
      Serial.print("Unknow error at address 0x");
      if (address < 16) {
        Serial.print("0");
      }
      Serial.println(address, HEX);
    }
  }
  if (nDevices == 0) {
    Serial.println("No I2C devices found\n");
  }
  else {
    Serial.println("done\n");
  }

  delay(500);

}

void loop() {

  Serial.println("");
  Serial.println("###########################");
  Serial.print("Reading device: ");
  Serial.println(devAddr, HEX);

  //DAChi
  Wire.beginTransmission(devAddr);
  Wire.write(0x08);               // Point to  register
  Wire.endTransmission(false);    // Do not release the line
  Wire.requestFrom(devAddr, 1);      // Request to read 1 byte. The address has the last bit set (READ bit).
  currentDAChi = Wire.read();// & 0xFF;

  //DAClo
  Wire.beginTransmission(devAddr);
  Wire.write(0x09);               // Point to  register
  Wire.endTransmission(false);    // Do not release the line
  Wire.requestFrom(devAddr, 1);      // Request to read 1 byte. The address has the last bit set (READ bit).
  currentDAClo = Wire.read();// & 0xC0;

  //Range or default offset   **READ ONLY**
  Wire.beginTransmission(devAddr);
  Wire.write(0x37);               // Point to  register
  Wire.endTransmission(false);    // Do not release the line
  Wire.requestFrom(devAddr, 1);      // Request to read 1 byte. The address has the last bit set (READ bit).
  currentRange = Wire.read();// & 0x1F;

  //Offset
  Wire.beginTransmission(devAddr);
  Wire.write(0x0E);               // Point to  register
  Wire.endTransmission(false);    // Do not release the line
  Wire.requestFrom(devAddr, 1);      // Request to read 1 byte. The address has the last bit set (READ bit).
  currentOffset = Wire.read();// & 0x1F;

  //Prescaller
  Wire.beginTransmission(devAddr);
  Wire.write(0x02);               // Point to  register
  Wire.endTransmission(false);    // Do not release the line
  Wire.requestFrom(devAddr, 1);      // Request to read 1 byte. The address has the last bit set (READ bit).
  currentPrescaler = Wire.read();// & 0x0F;

  Serial.print("Current DAChi = ");
  Serial.println(currentDAChi, HEX);

  Serial.print("Current DAClo = ");
  Serial.println(currentDAClo, HEX);

  Serial.print("Current Range = ");
  Serial.println(currentRange, HEX);

  Serial.print("Current Offset = ");
  Serial.println(currentOffset, HEX);

  Serial.print("Current Prescaler = ");
  Serial.println(currentPrescaler, HEX);

  delay(2000);

  //byte newOffset = currentRange - 2;

  byte newOffset = 0xEB;

  Serial.print("New Offset = ");
  Serial.println(newOffset, HEX);



  Serial.println("Writing EEPROM");

  // PRESCALER register
  // Store 0x03 in the
  // Add 0xF[value]  ie binary 1111[bbbb]
  Wire.beginTransmission(devAddr);
  Wire.write(0x02); // PRESCALER address = 0x02
  Wire.write(0xF3);
  Wire.endTransmission();
  delay(10);

  // OFFSET register
  // Store Result of range 0x37 minus the table offset at the offset 0x0E register.
  // Need to add leading 111[bbbbb]
  Wire.beginTransmission(0x58);
  Wire.write(0x0E); // OFFSET address = 0x0E
  Wire.write(newOffset);
  Wire.endTransmission();
  delay(10);

  // DAC registers
  // DAC High
  Wire.beginTransmission(0x58);
  Wire.write(0x08); // DAC address = 0x08
  Wire.write(0x4F);
  Wire.write(0xC0);
  Wire.endTransmission();
  delay(10);

  // DAC registers
  // DAC Low
  //Wire.beginTransmission(0x58);
  //Wire.write(0x09);
  //Wire.write(0xC0);
  //Wire.endTransmission();
  //delay(10);

  // Write EEPROM
  Wire.beginTransmission(0x58);
  Wire.write(0x3F);
  Wire.endTransmission();

  Serial.print("Reading device: ");
  Serial.println(devAddr, HEX);



  //DAChi
  Wire.beginTransmission(devAddr);
  Wire.write(0x08);               // Point to  register
  Wire.endTransmission(false);    // Do not release the line
  Wire.requestFrom(devAddr, 1);      // Request to read 1 byte. The address has the last bit set (READ bit).
  currentDAChi = Wire.read();// & 0xFF;

  //DAClo
  Wire.beginTransmission(devAddr);
  Wire.write(0x09);               // Point to  register
  Wire.endTransmission(false);    // Do not release the line
  Wire.requestFrom(devAddr, 1);      // Request to read 1 byte. The address has the last bit set (READ bit).
  currentDAClo = Wire.read();// & 0xC0;

  //Range or default offset   **READ ONLY**
  Wire.beginTransmission(devAddr);
  Wire.write(0x37);               // Point to  register
  Wire.endTransmission(false);    // Do not release the line
  Wire.requestFrom(devAddr, 1);      // Request to read 1 byte. The address has the last bit set (READ bit).
  currentRange = Wire.read();// & 0x1F;

  //Offset
  Wire.beginTransmission(devAddr);
  Wire.write(0x0E);               // Point to  register
  Wire.endTransmission(false);    // Do not release the line
  Wire.requestFrom(devAddr, 1);      // Request to read 1 byte. The address has the last bit set (READ bit).
  currentOffset = Wire.read();// & 0x1F;

  //Prescaller
  Wire.beginTransmission(devAddr);
  Wire.write(0x02);               // Point to  register
  Wire.endTransmission(false);    // Do not release the line
  Wire.requestFrom(devAddr, 1);      // Request to read 1 byte. The address has the last bit set (READ bit).
  currentPrescaler = Wire.read();// & 0x0F;

  Serial.print("Current DAChi = ");
  Serial.println(currentDAChi, HEX);

  Serial.print("Current DAClo = ");
  Serial.println(currentDAClo, HEX);

  Serial.print("Current Range = ");
  Serial.println(currentRange, HEX);

  Serial.print("Current Offset = ");
  Serial.println(currentOffset, HEX);

  Serial.print("Current Prescaler = ");
  Serial.println(currentPrescaler, HEX);










  delay(2000);

  while (1) {
    digitalWrite(LED_BUILTIN, HIGH);
    delay(20);
    digitalWrite(LED_BUILTIN, LOW);
    delay(20);
    digitalWrite(LED_BUILTIN, HIGH);
    delay(20);
    digitalWrite(LED_BUILTIN, LOW);
    delay(20);
    digitalWrite(LED_BUILTIN, HIGH);
    delay(20);
    digitalWrite(LED_BUILTIN, LOW);
    delay(20);
    delay(1000);
  }
}

Appreciate if anybody can help!

You need to apply a bit mask to the value using the bitwise AND operator & just like many of the comments in your code.

The mask you need is 0 for bits to ignore and 1 for the bits you want.

mask = 0b00011111; // or in hex notation 0x1F;

It appears your DAC value is 10 bits - 8 go into the MSB and 2 go into the LSB, justified towards the top. You need to shift those values around

uinit16_t value = 0x01AB;  // 0000 0001 1010 1011
byte msb = value >> 6;       // 0110 1010
byte lsb = (value & 0xFF) << 6; // 0000 1100

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