This has probably already been asked but I'm having trouble understanding how to do masking when writing using I2C. Say I have a function called i2c_update with the following parameters:
dev Pointer to the device structure for the driver instance.
dev_addr    Address of the I2C device for updating.
reg_addr    Address of the internal register being updated.
mask    Bitmask for updating internal register.
value   Value for updating internal register.
I know how to deal with the dev, dev_addr and reg_addr but I'm confused on how to mask and what value to use. For example, if 0x00000111 is at the register I want to modify currently and I want to change it to 0x01000000 what mask and what value would I want to use?
Thanks!
It takes 5 minutes to find the function in the project repo
static inline int i2c_reg_update_byte(struct device *dev, uint8_t dev_addr,
                      uint8_t reg_addr, uint8_t mask,
                      uint8_t value)
{
    uint8_t old_value, new_value;
    int rc;
    rc = i2c_reg_read_byte(dev, dev_addr, reg_addr, &old_value);
    if (rc != 0) {
        return rc;
    }
    new_value = (old_value & ~mask) | (value & mask);
    if (new_value == old_value) {
        return 0;
    }
    return i2c_reg_write_byte(dev, dev_addr, reg_addr, new_value);
}
new_value = (old_value & ~mask) | (value & mask); :
old_value & ~mask - clears masked bits
value & mask clears all other bits except the mask
| sets the cleared bits in the old_value with the bits left in the value
Do you need more explanation? If yes it is the time to learn a bit bitwise operations.
 0___________
 0___________I have looked up the Zephyr project source code and found the implementation of the function here:
static inline int i2c_reg_update_byte(struct device *dev, u8_t dev_addr,
                      u8_t reg_addr, u8_t mask,
                      u8_t value)
{
    u8_t old_value, new_value;
    int rc;
    rc = i2c_reg_read_byte(dev, dev_addr, reg_addr, &old_value);
    if (rc != 0) {
        return rc;
    }
    new_value = (old_value & ~mask) | (value & mask);
    if (new_value == old_value) {
        return 0;
    }
    return i2c_reg_write_byte(dev, dev_addr, reg_addr, new_value);
}
As you can see the net action is
new_value = (old_value & ~mask) | (value & mask);
So it will only assign the bits of value corresponding to ones in the mask to the new_value, and the rest will remain same as old_value.
 Eugene Sh.
 Eugene Sh.User contributions licensed under CC BY-SA 3.0