diff --git a/src/shared/drivers/i2c/I2C.cpp b/src/shared/drivers/i2c/I2C.cpp index a58a3049de8b9ecd6e00cccffaee0ec45e846848..56b2a9f4d795205593d2ea57a5d7cdd5815874eb 100644 --- a/src/shared/drivers/i2c/I2C.cpp +++ b/src/shared/drivers/i2c/I2C.cpp @@ -32,39 +32,163 @@ I2C::I2C(I2C_TypeDef *i2c, const miosix::GpioPin &scl, } bool I2C::read(const I2CDriver::I2CSlaveConfig &slaveConfig, void *buffer, - const size_t &nBytes) + const size_t nBytes) { i2c.flushBus(); return i2c.read(slaveConfig, buffer, nBytes); } bool I2C::write(const I2CDriver::I2CSlaveConfig &slaveConfig, - const void *buffer, const size_t &nBytes) + const void *buffer, const size_t nBytes) { i2c.flushBus(); return i2c.write(slaveConfig, buffer, nBytes); } bool I2C::readRegister(const I2CDriver::I2CSlaveConfig &slaveConfig, - const uint8_t ®isterAddress, uint8_t ®isterContent) + const uint8_t registerAddress, uint8_t ®isterContent) { i2c.flushBus(); return i2c.write(slaveConfig, ®isterAddress, 1, false) && i2c.read(slaveConfig, ®isterContent, 1); } +bool I2C::readRegister16(const I2CDriver::I2CSlaveConfig &slaveConfig, + const uint8_t registerAddress, + uint16_t ®isterContent) +{ + i2c.flushBus(); + uint8_t buf[2] = {0}; + if (i2c.write(slaveConfig, ®isterAddress, 1, false) && + i2c.read(slaveConfig, buf, 2)) + { + registerContent = + (slaveConfig.MSBFirst ? ((uint16_t)buf[0]) << 8 | buf[1] + : ((uint16_t)buf[1]) << 8 | buf[0]); + return true; + } + return false; +} + +bool I2C::readRegister24(const I2CDriver::I2CSlaveConfig &slaveConfig, + const uint8_t registerAddress, + uint32_t ®isterContent) +{ + i2c.flushBus(); + uint8_t buf[3] = {0}; + if (i2c.write(slaveConfig, ®isterAddress, 1, false) && + i2c.read(slaveConfig, buf, 3)) + { + registerContent = + (slaveConfig.MSBFirst + ? ((uint32_t)buf[0]) << 16 | ((uint32_t)buf[1] << 8) | buf[2] + : ((uint32_t)buf[2]) << 16 | ((uint32_t)buf[1] << 8) | buf[0]); + return true; + } + return false; +} + +bool I2C::readRegister32(const I2CDriver::I2CSlaveConfig &slaveConfig, + const uint8_t registerAddress, + uint32_t ®isterContent) +{ + i2c.flushBus(); + uint8_t buf[4] = {0}; + if (i2c.write(slaveConfig, ®isterAddress, 1, false) && + i2c.read(slaveConfig, buf, 4)) + { + registerContent = + (slaveConfig.MSBFirst + ? ((uint32_t)buf[0]) << 24 | ((uint32_t)buf[1] << 16) | + ((uint32_t)buf[2] << 8) | buf[3] + : ((uint32_t)buf[3]) << 24 | ((uint32_t)buf[2] << 16) | + ((uint32_t)buf[1] << 8) | buf[0]); + return true; + } + return false; +} + bool I2C::writeRegister(const I2CDriver::I2CSlaveConfig &slaveConfig, - const uint8_t ®isterAddress, - const uint8_t ®isterContent) + const uint8_t registerAddress, + const uint8_t registerContent) { const uint8_t reg[2] = {registerAddress, registerContent}; i2c.flushBus(); return i2c.write(slaveConfig, reg, 2); } +bool I2C::writeRegister16(const I2CDriver::I2CSlaveConfig &slaveConfig, + const uint8_t registerAddress, + const uint16_t registerContent) +{ + i2c.flushBus(); + if (slaveConfig.MSBFirst) + { + const uint8_t reg[3] = {registerAddress, // subAddr + (uint8_t)(registerContent >> 8), // MSB + (uint8_t)(registerContent)}; // LSB + return i2c.write(slaveConfig, reg, 3); + } + else + { + const uint8_t reg[3] = {registerAddress, // subAddr + (uint8_t)(registerContent), // LSB + (uint8_t)(registerContent >> 8)}; // MSB + return i2c.write(slaveConfig, reg, 3); + } +} + +bool I2C::writeRegister24(const I2CDriver::I2CSlaveConfig &slaveConfig, + const uint8_t registerAddress, + const uint32_t registerContent) +{ + i2c.flushBus(); + if (slaveConfig.MSBFirst) + { + const uint8_t reg[4] = {registerAddress, // subAddr + (uint8_t)(registerContent >> 16), // MSB + (uint8_t)(registerContent >> 8), // + (uint8_t)registerContent}; // LSB + return i2c.write(slaveConfig, reg, 4); + } + else + { + const uint8_t reg[4] = {registerAddress, // subAddr + (uint8_t)(registerContent), // LSB + (uint8_t)(registerContent >> 8), // + (uint8_t)(registerContent >> 16)}; // MSB + return i2c.write(slaveConfig, reg, 4); + } +} + +bool I2C::writeRegister32(const I2CDriver::I2CSlaveConfig &slaveConfig, + const uint8_t registerAddress, + const uint32_t registerContent) +{ + i2c.flushBus(); + if (slaveConfig.MSBFirst) + { + const uint8_t reg[5] = {registerAddress, // subAddr + (uint8_t)(registerContent >> 24), // MSB + (uint8_t)(registerContent >> 16), // + (uint8_t)(registerContent >> 8), // + (uint8_t)registerContent}; // LSB + return i2c.write(slaveConfig, reg, 5); + } + else + { + const uint8_t reg[5] = {registerAddress, // subAddr + (uint8_t)(registerContent), // LSB + (uint8_t)(registerContent >> 8), // + (uint8_t)(registerContent >> 16), // + (uint8_t)(registerContent >> 24)}; // MSB + return i2c.write(slaveConfig, reg, 5); + } +} + bool I2C::readFromRegister(const I2CDriver::I2CSlaveConfig &slaveConfig, - const uint8_t ®isterAddress, void *buffer, - const size_t &nBytes) + const uint8_t registerAddress, void *buffer, + const size_t nBytes) { i2c.flushBus(); return i2c.write(slaveConfig, ®isterAddress, 1, false) && @@ -86,38 +210,86 @@ SyncedI2C::SyncedI2C(I2C_TypeDef *i2c, const miosix::GpioPin &scl, } bool SyncedI2C::read(const I2CDriver::I2CSlaveConfig &slaveConfig, void *buffer, - const size_t &nBytes) + const size_t nBytes) { miosix::Lock<miosix::FastMutex> lock(mutex); return I2C::read(slaveConfig, buffer, nBytes); } bool SyncedI2C::write(const I2CDriver::I2CSlaveConfig &slaveConfig, - const void *buffer, const size_t &nBytes) + const void *buffer, const size_t nBytes) { miosix::Lock<miosix::FastMutex> lock(mutex); return I2C::write(slaveConfig, buffer, nBytes); } bool SyncedI2C::readRegister(const I2CDriver::I2CSlaveConfig &slaveConfig, - const uint8_t ®isterAddress, + const uint8_t registerAddress, uint8_t ®isterContent) { miosix::Lock<miosix::FastMutex> lock(mutex); return I2C::readRegister(slaveConfig, registerAddress, registerContent); } +bool SyncedI2C::readRegister16(const I2CDriver::I2CSlaveConfig &slaveConfig, + const uint8_t registerAddress, + uint16_t ®isterContent) +{ + miosix::Lock<miosix::FastMutex> lock(mutex); + return I2C::readRegister16(slaveConfig, registerAddress, registerContent); +} + +bool SyncedI2C::readRegister24(const I2CDriver::I2CSlaveConfig &slaveConfig, + const uint8_t registerAddress, + uint32_t ®isterContent) +{ + miosix::Lock<miosix::FastMutex> lock(mutex); + return I2C::readRegister24(slaveConfig, registerAddress, registerContent); +} + +bool SyncedI2C::readRegister32(const I2CDriver::I2CSlaveConfig &slaveConfig, + const uint8_t registerAddress, + uint32_t ®isterContent) +{ + miosix::Lock<miosix::FastMutex> lock(mutex); + return I2C::readRegister32(slaveConfig, registerAddress, registerContent); +} + bool SyncedI2C::writeRegister(const I2CDriver::I2CSlaveConfig &slaveConfig, - const uint8_t ®isterAddress, - const uint8_t ®isterContent) + const uint8_t registerAddress, + const uint8_t registerContent) { miosix::Lock<miosix::FastMutex> lock(mutex); return I2C::writeRegister(slaveConfig, registerAddress, registerContent); } +bool SyncedI2C::writeRegister16(const I2CDriver::I2CSlaveConfig &slaveConfig, + const uint8_t registerAddress, + const uint16_t registerContent) +{ + miosix::Lock<miosix::FastMutex> lock(mutex); + return I2C::writeRegister16(slaveConfig, registerAddress, registerContent); +} + +bool SyncedI2C::writeRegister24(const I2CDriver::I2CSlaveConfig &slaveConfig, + const uint8_t registerAddress, + const uint32_t registerContent) +{ + miosix::Lock<miosix::FastMutex> lock(mutex); + return I2C::writeRegister24(slaveConfig, registerAddress, registerContent); +} + +bool SyncedI2C::writeRegister32(const I2CDriver::I2CSlaveConfig &slaveConfig, + const uint8_t registerAddress, + const uint32_t registerContent) +{ + miosix::Lock<miosix::FastMutex> lock(mutex); + return I2C::writeRegister32(slaveConfig, registerAddress, registerContent); +} + bool SyncedI2C::readFromRegister(const I2CDriver::I2CSlaveConfig &slaveConfig, - const uint8_t ®isterAddress, void *buffer, - const size_t &nBytes) + const uint8_t registerAddress, void *buffer, + const size_t nBytes) { miosix::Lock<miosix::FastMutex> lock(mutex); return I2C::readFromRegister(slaveConfig, registerAddress, buffer, nBytes); diff --git a/src/shared/drivers/i2c/I2C.h b/src/shared/drivers/i2c/I2C.h index a97cbb99cf2bb3e00ea6f30c67402455ec2f9709..f9b7d01c5e5ef88f0130e070b1c16fa3a8f17b8a 100644 --- a/src/shared/drivers/i2c/I2C.h +++ b/src/shared/drivers/i2c/I2C.h @@ -71,7 +71,7 @@ public: * @returns True if the read is successful, false otherwise. */ [[nodiscard]] bool read(const I2CDriver::I2CSlaveConfig &slaveConfig, - void *buffer, const size_t &nBytes); + void *buffer, const size_t nBytes); /** * @brief Non blocking write operation to write nBytes. @@ -86,10 +86,10 @@ public: * @returns True if the write is successful, false otherwise. */ [[nodiscard]] bool write(const I2CDriver::I2CSlaveConfig &slaveConfig, - const void *buffer, const size_t &nBytes); + const void *buffer, const size_t nBytes); /** - * @brief Non blocking operation to read a 1-byte register from a slave. + * @brief Non blocking operation to read an 8-bit register from a slave. * * This method, if necessary, flushes the bus before the read operation is * performed. In case of an error during the communication, this method @@ -102,10 +102,58 @@ public: */ [[nodiscard]] bool readRegister( const I2CDriver::I2CSlaveConfig &slaveConfig, - const uint8_t ®isterAddress, uint8_t ®isterContent); + const uint8_t registerAddress, uint8_t ®isterContent); /** - * @brief Non blocking operation to write a 1-byte register from a slave. + * @brief Non blocking operation to read a 16-bit register from a slave. + * + * This method, if necessary, flushes the bus before the read operation is + * performed. In case of an error during the communication, this method + * returns false immediately. + * @warning Check always if the operation succeeded or not! + * @param slaveConfig The configuration struct of the slave device. + * @param registerAddress Byte that represents the address of the register. + * @param registerContent Where to store the content of the register. + * @returns True if the read is successful, false otherwise. + */ + [[nodiscard]] bool readRegister16( + const I2CDriver::I2CSlaveConfig &slaveConfig, + const uint8_t registerAddress, uint16_t ®isterContent); + + /** + * @brief Non blocking operation to read a 24-bit register from a slave. + * + * This method, if necessary, flushes the bus before the read operation is + * performed. In case of an error during the communication, this method + * returns false immediately. + * @warning Check always if the operation succeeded or not! + * @param slaveConfig The configuration struct of the slave device. + * @param registerAddress Byte that represents the address of the register. + * @param registerContent Where to store the content of the register. + * @returns True if the read is successful, false otherwise. + */ + [[nodiscard]] bool readRegister24( + const I2CDriver::I2CSlaveConfig &slaveConfig, + const uint8_t registerAddress, uint32_t ®isterContent); + + /** + * @brief Non blocking operation to read a 32-bit register from a slave. + * + * This method, if necessary, flushes the bus before the read operation is + * performed. In case of an error during the communication, this method + * returns false immediately. + * @warning Check always if the operation succeeded or not! + * @param slaveConfig The configuration struct of the slave device. + * @param registerAddress Byte that represents the address of the register. + * @param registerContent Where to store the content of the register. + * @returns True if the read is successful, false otherwise. + */ + [[nodiscard]] bool readRegister32( + const I2CDriver::I2CSlaveConfig &slaveConfig, + const uint8_t registerAddress, uint32_t ®isterContent); + + /** + * @brief Non blocking operation to write an 8-bit register from a slave. * * This method, if necessary, flushes the bus before the write operation is * performed. In case of an error during the communication, this method @@ -118,7 +166,55 @@ public: */ [[nodiscard]] bool writeRegister( const I2CDriver::I2CSlaveConfig &slaveConfig, - const uint8_t ®isterAddress, const uint8_t ®isterContent); + const uint8_t registerAddress, const uint8_t registerContent); + + /** + * @brief Non blocking operation to write a 16-bit register from a slave. + * + * This method, if necessary, flushes the bus before the read operation is + * performed. In case of an error during the communication, this method + * returns false immediately. + * @warning Check always if the operation succeeded or not! + * @param slaveConfig The configuration struct of the slave device. + * @param registerAddress Byte that represents the address of the register. + * @param registerContent The content to write on the register. + * @returns True if the write is successful, false otherwise. + */ + [[nodiscard]] bool writeRegister16( + const I2CDriver::I2CSlaveConfig &slaveConfig, + const uint8_t registerAddress, const uint16_t registerContent); + + /** + * @brief Non blocking operation to write a 24-bit register from a slave. + * + * This method, if necessary, flushes the bus before the read operation is + * performed. In case of an error during the communication, this method + * returns false immediately. + * @warning Check always if the operation succeeded or not! + * @param slaveConfig The configuration struct of the slave device. + * @param registerAddress Byte that represents the address of the register. + * @param registerContent The content to write on the register. + * @returns True if the write is successful, false otherwise. + */ + [[nodiscard]] bool writeRegister24( + const I2CDriver::I2CSlaveConfig &slaveConfig, + const uint8_t registerAddress, const uint32_t registerContent); + + /** + * @brief Non blocking operation to write a 32-bit register from a slave. + * + * This method, if necessary, flushes the bus before the read operation is + * performed. In case of an error during the communication, this method + * returns false immediately. + * @warning Check always if the operation succeeded or not! + * @param slaveConfig The configuration struct of the slave device. + * @param registerAddress Byte that represents the address of the register. + * @param registerContent The content to write on the register. + * @returns True if the write is successful, false otherwise. + */ + [[nodiscard]] bool writeRegister32( + const I2CDriver::I2CSlaveConfig &slaveConfig, + const uint8_t registerAddress, const uint32_t registerContent); /** * @brief Non blocking operation to read n-bytes from register from a slave. @@ -135,7 +231,7 @@ public: */ [[nodiscard]] bool readFromRegister( const I2CDriver::I2CSlaveConfig &slaveConfig, - const uint8_t ®isterAddress, void *buffer, const size_t &nBytes); + const uint8_t registerAddress, void *buffer, const size_t nBytes); /** * @brief Non blocking operation to check if a slave is available. @@ -200,7 +296,7 @@ public: * @returns True if the read is successful, false otherwise. */ [[nodiscard]] bool read(const I2CDriver::I2CSlaveConfig &slaveConfig, - void *buffer, const size_t &nBytes); + void *buffer, const size_t nBytes); /** * @brief Write operation to write nBytes. @@ -215,10 +311,10 @@ public: * @returns True if the write is successful, false otherwise. */ [[nodiscard]] bool write(const I2CDriver::I2CSlaveConfig &slaveConfig, - const void *buffer, const size_t &nBytes); + const void *buffer, const size_t nBytes); /** - * @brief Read a one-byte register from the device. + * @brief Read an 8-bit register from the device. * * This method could have to wait that no other thread is trying to do some * operation on the bus. In case of an error during the communication, this @@ -231,10 +327,58 @@ public: */ [[nodiscard]] bool readRegister( const I2CDriver::I2CSlaveConfig &slaveConfig, - const uint8_t ®isterAddress, uint8_t ®isterContent); + const uint8_t registerAddress, uint8_t ®isterContent); /** - * @brief Write a one-byte register from the device. + * @brief Read a 16-bit register from the device. + * + * This method could have to wait that no other thread is trying to do some + * operation on the bus. In case of an error during the communication, this + * method returns false immediately. + * @warning Check always if the operation succeeded or not! + * @param slaveConfig The configuration struct of the slave device. + * @param registerAddress Byte that represents the address of the register. + * @param registerContent Where to store the content of the register. + * @returns True if the read is successful, false otherwise. + */ + [[nodiscard]] bool readRegister16( + const I2CDriver::I2CSlaveConfig &slaveConfig, + const uint8_t registerAddress, uint16_t ®isterContent); + + /** + * @brief Read a 24-bit register from the device. + * + * This method could have to wait that no other thread is trying to do some + * operation on the bus. In case of an error during the communication, this + * method returns false immediately. + * @warning Check always if the operation succeeded or not! + * @param slaveConfig The configuration struct of the slave device. + * @param registerAddress Byte that represents the address of the register. + * @param registerContent Where to store the content of the register. + * @returns True if the read is successful, false otherwise. + */ + [[nodiscard]] bool readRegister24( + const I2CDriver::I2CSlaveConfig &slaveConfig, + const uint8_t registerAddress, uint32_t ®isterContent); + + /** + * @brief Read a 32-bit register from the device. + * + * This method could have to wait that no other thread is trying to do some + * operation on the bus. In case of an error during the communication, this + * method returns false immediately. + * @warning Check always if the operation succeeded or not! + * @param slaveConfig The configuration struct of the slave device. + * @param registerAddress Byte that represents the address of the register. + * @param registerContent Where to store the content of the register. + * @returns True if the read is successful, false otherwise. + */ + [[nodiscard]] bool readRegister32( + const I2CDriver::I2CSlaveConfig &slaveConfig, + const uint8_t registerAddress, uint32_t ®isterContent); + + /** + * @brief Write an 8-bit register from the device. * * This method could have to wait that no other thread is trying to do some * operation on the bus. In case of an error during the communication, this @@ -247,7 +391,55 @@ public: */ [[nodiscard]] bool writeRegister( const I2CDriver::I2CSlaveConfig &slaveConfig, - const uint8_t ®isterAddress, const uint8_t ®isterContent); + const uint8_t registerAddress, const uint8_t registerContent); + + /** + * @brief Write a 16-bit register from the device. + * + * This method could have to wait that no other thread is trying to do some + * operation on the bus. In case of an error during the communication, this + * method returns false immediately. + * @warning Check always if the operation succeeded or not! + * @param slaveConfig The configuration struct of the slave device. + * @param registerAddress Byte that represents the address of the register. + * @param registerContent The content to write on the register. + * @returns True if the write is successful, false otherwise. + */ + [[nodiscard]] bool writeRegister16( + const I2CDriver::I2CSlaveConfig &slaveConfig, + const uint8_t registerAddress, const uint16_t registerContent); + + /** + * @brief Write a 24-bit register from the device. + * + * This method could have to wait that no other thread is trying to do some + * operation on the bus. In case of an error during the communication, this + * method returns false immediately. + * @warning Check always if the operation succeeded or not! + * @param slaveConfig The configuration struct of the slave device. + * @param registerAddress Byte that represents the address of the register. + * @param registerContent The content to write on the register. + * @returns True if the write is successful, false otherwise. + */ + [[nodiscard]] bool writeRegister24( + const I2CDriver::I2CSlaveConfig &slaveConfig, + const uint8_t registerAddress, const uint32_t registerContent); + + /** + * @brief Write a 32-bit register from the device. + * + * This method could have to wait that no other thread is trying to do some + * operation on the bus. In case of an error during the communication, this + * method returns false immediately. + * @warning Check always if the operation succeeded or not! + * @param slaveConfig The configuration struct of the slave device. + * @param registerAddress Byte that represents the address of the register. + * @param registerContent The content to write on the register. + * @returns True if the write is successful, false otherwise. + */ + [[nodiscard]] bool writeRegister32( + const I2CDriver::I2CSlaveConfig &slaveConfig, + const uint8_t registerAddress, const uint32_t registerContent); /** * @brief Read n-bytes from register from a slave. @@ -264,7 +456,7 @@ public: */ [[nodiscard]] bool readFromRegister( const I2CDriver::I2CSlaveConfig &slaveConfig, - const uint8_t ®isterAddress, void *buffer, const size_t &nBytes); + const uint8_t registerAddress, void *buffer, const size_t nBytes); /** * @brief Check if a slave is available. diff --git a/src/shared/drivers/i2c/I2CDriver.h b/src/shared/drivers/i2c/I2CDriver.h index f017422ce2256d53040d81e4a05eb388cfbeef7a..159a288c593210ae3342f7f7d840c7140e8a0be2 100644 --- a/src/shared/drivers/i2c/I2CDriver.h +++ b/src/shared/drivers/i2c/I2CDriver.h @@ -108,6 +108,8 @@ public: ///< addressing |6-bit unused|10-bit address|). I2CDriver::Addressing addressing; ///< Addressing mode of the device. I2CDriver::Speed speed; ///< Speed mode of the communication. + bool MSBFirst; ///< Registers with lower values are the MSB of + ///< multi-byte registers } I2CSlaveConfig; /**