diff --git a/openrtx/include/peripherals/i2c.h b/openrtx/include/peripherals/i2c.h new file mode 100644 index 00000000..04adb95a --- /dev/null +++ b/openrtx/include/peripherals/i2c.h @@ -0,0 +1,160 @@ +/*************************************************************************** + * Copyright (C) 2024 by Federico Amedeo Izzo IU2NUO, * + * Niccolò Izzo IU2KIN * + * Frederik Saraci IU2NRO * + * Silvano Seva IU2KWO * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, see * + ***************************************************************************/ + +#ifndef I2C_H +#define I2C_H + +#include +#include +#include + +/** + * Enumeration type for I2C bus speeds + */ +enum I2CSpeed +{ + I2C_SPEED_LOW = 0, ///< Generic, implementation-specific, low speed + I2C_SPEED_100kHz, ///< Standard I2C speed + I2C_SPEED_400kHz, ///< Fast I2C speed + I2C_SPEED_1MHz ///< Fast Plus I2C speed +}; + +struct i2cDevice; + +/** + * I2C driver API. + */ +struct i2cApi +{ + /** + * Perform a read operation on an I2C device. + * + * @param dev: pointer to the device managing the bus. + * @param addr: 7-bit address of the remote peripheral. + * @param data: pointer to the destination buffer for data read. + * @param len: number of bytes to read. + * @param stop: set to true to send a stop condition at the end of the transfer. + * @return zero on success, a negative error code otherwise. + */ + int (*read)(const struct i2cDevice *dev, const uint8_t addr, void *data, + const size_t len, const bool stop); + + /** + * Perform a write operation on an I2C device. + * + * @param dev: pointer to the device managing the bus. + * @param addr: 7-bit address of the remote peripheral. + * @param data: data to be written. + * @param len: number of bytes to read. + * @param stop: set to true to send a stop condition at the end of the transfer. + * @return zero on success, a negative error code otherwise. + */ + int (*write)(const struct i2cDevice *dev, const uint8_t addr, + const void *data, const size_t len, const bool stop); +}; + +/** + * I2C peripheral descriptor. + */ +struct i2cDevice +{ + const struct i2cApi *driver; ///< Driver API + const void *periph; ///< Underlying hardware peripheral + const pthread_mutex_t *mutex; ///< Mutex for exclusive access +}; + + +/** + * Acquire exclusive ownership on an I2C peripheral. + * + * @param dev: pointer to peripheral descriptor. + * @return zero on success, a negative error code on failure. + */ +static inline int i2c_acquire(const struct i2cDevice *dev) +{ + if(dev->mutex == NULL) + return 0; + + return pthread_mutex_lock((pthread_mutex_t *) dev->mutex); +} + +/** + * Attempt to acquire exclusive ownership on an I2C peripheral. + * + * @param dev: pointer to peripheral descriptor. + * @return zero on success, a negative error code on failure. + */ +static inline int i2c_tryAcquire(const struct i2cDevice *dev) +{ + if(dev->mutex == NULL) + return 0; + + return pthread_mutex_trylock((pthread_mutex_t *) dev->mutex); +} + +/** + * Release exclusive ownership on an I2C peripheral. + * + * @param dev: pointer to peripheral descriptor. + * @return zero on success, a negative error code on failure. + */ +static inline int i2c_release(const struct i2cDevice *dev) +{ + if(dev->mutex == NULL) + return 0; + + return pthread_mutex_unlock((pthread_mutex_t *) dev->mutex); +} + +/** + * Read data from an I2C device connected on the bus managed by the peripheral. + * + * @param dev: pointer to peripheral descriptor. + * @param addr: 7-bit device address. + * @param data: pointer to a buffer where to store the received data. + * @param len: number of bytes to read. + * @param stop: if true, an I2C stop condition is generated at the end of the + * transfer. + * @return zero on success, a negative error code on failure. + */ +static inline int i2c_read(const struct i2cDevice *dev, const uint8_t addr, + void *data, const size_t len, const bool stop) +{ + return dev->driver->read(dev, addr, data, len, stop); +} + +/** + * Send data to an I2C device connected on the bus managed by the peripheral. + * + * @param dev: pointer to peripheral descriptor. + * @param addr: 7-bit device address. + * @param data: pointer to the data to be sent. + * @param len: number of bytes to send. + * @param stop: if true, an I2C stop condition is generated at the end of the + * transfer. + * @return zero on success, a negative error code on failure. + */ +static inline int i2c_write(const struct i2cDevice *dev, const uint8_t addr, + const void *data, const size_t len, const bool stop) +{ + return dev->driver->write(dev, addr, data, len, stop); +} + +#endif /* I2C_H */