Bit masking for I2C writes?

0

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!

edit: this is the link of the api I'm using

c
bit-manipulation
asked on Stack Overflow Aug 5, 2020 by innyme • edited Aug 5, 2020 by innyme

2 Answers

0

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.

answered on Stack Overflow Aug 5, 2020 by 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.

answered on Stack Overflow Aug 5, 2020 by Eugene Sh.

User contributions licensed under CC BY-SA 3.0