Question about ISL29125 Colour Sensor Library

Hi all, I just got a ISL29125 breakout board and I’m peering through the libraries (download here). I found this section that confused me (patched some parts together so the below code makes sense):

#define RED_L 0x0B  //Address for red sensor data read low
#define RED_H 0x0C  //Address for red sensor data read high

// Read the latest Sensor ADC reading for the color Red
uint16_t SFE_ISL29125::readRed()
{
  return read16(RED_L);
}


// Generic I2C read registers (two bytes, LSB first)
uint16_t SFE_ISL29125::read16(uint8_t reg)
{
  uint16_t data = 0x0000;

  Wire.beginTransmission(_addr);
  Wire.write(reg);
  Wire.endTransmission();
  
  Wire.beginTransmission(_addr);
  Wire.requestFrom(_addr, (uint8_t)2); // request 2 bytes of data
  data = Wire.read();
  data |= (Wire.read() << 8);
  Wire.endTransmission();

  return data;
}

_addr refers to the device address.

The readRed() function is described as retrieving a 16-bit integer from the sensor, which from the datasheet here (refer to table 20) would appear to require reading from two registers, the high (0x0C, RED_H) and the low (0x0B, RED_L) register. readRed() however seems to only request from RED_L, but still expects 16 bits and even attempts to concatenate two 8-bit Wire.read()s.

Anyone familiar with this sensor can help to explain this?

You forgot to post a link to the library.

However, the name of the "read16" function called by readRed() strongly suggests that it reads both the high and low bytes, starting with the address of the low byte, concatenates them and returns the 16 bit result.

Oops, added a link in the OP to the lib.

The example sketch in the lib seems to correctly output a 16bit number with readRed(), but I can't for the life of me figure out how it does so from the code. The read16 function only accepts one address, so by right I should only be expecting either data from RED_L or RED_H, not both. The line Wire.requestFrom(_addr, (uint8_t)2); asks for two bytes, but if I'm understanding the datasheet correctly, querying one registry only returns 1 byte of data.

I re-wrote the library to read 1 byte from RED_L, then 1 byte from RED_H separately, then concatenate, and the results appear to be the same as requesting 2 bytes from RED_L. It would appear the ISL29125 has an undocumented feature which releases both registers by requesting only from one.

The converse appears to true as well: requesting 2 bytes from RED_H gives you 1 byte from RED_H then 1 from RED_L, but obviously you will need to concatenate it differently.

Any additional inputs are welcome.

Undocumented feature - maybe.

Common feature of I2C devices - for sure.

Request two bytes from one register and most devices automatically send the second byte from the next register. Same for writing multiple bytes.

The converse appears to true as well: requesting 2 bytes from RED_H gives you 1 byte from RED_H then 1 from RED_L, but obviously you will need to concatenate it differently.

That is VERY unlikely. Usually, during multibyte requests the register address is simply incremented as each byte is accessed.

So even if the two bytes seem to be correct, that may be an accident.

wvmarle: Request two bytes from one register and most devices automatically send the second byte from the next register. Same for writing multiple bytes.

I'm not too adept at using I2C so this is new to me. So requesting three bytes from, say 0x05 will give you results from 0x05, 0x06, then 0x07?

Is there any documentation or guide I can read about this? It seems everyday I learn something new about serial comms.

Normally, yes. Depending on the device in question, of course.

Is there any documentation or guide I can read about this?

I don’t think this is part of the I2C specification. Some devices support multibyte reads, autoincrementing the register addresses, others don’t.

You really must read the device data sheet very carefully. Most are quite explicit when it comes to defining exactly what I2C protocols are supported, including timing diagrams.

Hmm, will need to be careful in the future then. Thanks both.