Converting Arduino functions to Mbed

I have three arduino-style functions in a library which i want to convert to Mbed form:

void DFRobot_BMX160::writeReg(uint8_t reg, uint8_t *pBuf, uint16_t len)
{
    Wire.begin();
    Wire.beginTransmission(_addr);
    Wire.write(reg);
    for(uint16_t i = 0; i < len; i ++)
        Wire.write(pBuf[i]);
    Wire.endTransmission();
}

void DFRobot_BMX160::readReg(uint8_t reg, uint8_t *pBuf, uint16_t len)
{
    Wire.begin();
    Wire.beginTransmission(_addr);
    Wire.write(reg);
    if(Wire.endTransmission() != 0)
        return;
    Wire.requestFrom(_addr, (uint8_t) len);
    for(uint16_t i = 0; i < len; i ++) {
        pBuf[i] = Wire.read();
    }
    Wire.endTransmission();
}

bool DFRobot_BMX160::scan()
{
    Wire.beginTransmission(_addr);
    if (Wire.endTransmission() == 0){
        return true;
    }
    return false;
}

Can anyone provide equivalent Mbed code?

Most of this translates 1:1 using the Mbed I2C class. This is my best guess at an equivalent:

I2C i2c(<fill in correct pins>)

void DFRobot_BMX160::writeReg(uint8_t reg, uint8_t *pBuf, uint16_t len)
{
    i2c.lock();
    i2c.start();
    i2c.write(_addr << 1); // to indicate an i2c write, shift the 7 bit address up 1 bit and keep bit 0 as a 0
    i2c.write(reg);
    for(uint16_t i = 0; i < len; i ++)
        i2c.write(pBuf[i]);
    i2c.stop();
    i2c.unlock();
}

void DFRobot_BMX160::readReg(uint8_t reg, uint8_t *pBuf, uint16_t len)
{
    i2c.lock();
    i2c.start();

    // to indicate an i2c read, shift the 7 bit address up 1 bit and set bit 0 to a 1
    i2c.write(_addr << 1 | 1)    

    int writeResult = i2c.write(reg);
    i2c.stop();
    i2c.unlock();
    if(writeResult != 1)
    {
        return;
    }
    
    i2c.read(addr << 1, pBuf, len);
}

bool DFRobot_BMX160::scan()
{
    i2c.lock();
    i2c.start();

    // to indicate an i2c read, shift the 7 bit address up 1 bit and set bit 0 to a 1
    int writeResult = i2c.write(_addr << 1 | 1) ;

    i2c.stop();
    i2c.unlock();

    if (writeResult == 1){
        return true;
    }
    return false;
}

As you can see, there are basically two different I2C APIs: the “piecewise” one that uses start(), stop(), and the one-argument read() and write() functions; and the “transaction” API that uses the multi-argument read() and write() functions. The transaction API is nice: you just pass it an address, a buffer, and a length, and it will handle sending or receiving the data. However, sometimes it can’t handle certain formats, such as in writeReg() where reg is outside the pBuf array. In these cases, the piecewise API is helpful, even though it is less efficient for long transfers since it can’t operate asynchronously.

1 Like

Hi,

Thanks for the code. There’s a small error I am getting:
Error: No matching member function for call to ‘read’ in “DFBot/DFBot/DFRobot_BMX160.cpp”, Line: 319, Col: 9

^ It’s happening in the i2c.read() function: i2c.read(addr << 1, pBuf, len);. Surprisingly the error doesn’t show up for any other i2c functions.

Ok i fixed the error thanks to help from another forum user

i2c.read((int)_addr << 1, (char*)pBuf, (int)len); << Correction

When writing C++ code, one should use static_cast< int >( addr ) instead of the C-style cast. You will thank yourself later when it is easy to grep for casts. And the compiler will reward you with much more sensible warning or error messages when a cast does not make sense.