I2CRTOS Driver by Helmut Schmücker. Removed included mbed-rtos library to prevent multiple definition. Make sure to include mbed-rtos library in your program!

Fork of I2cRtosDriver by Helmut Schmücker

Committer:
humlet
Date:
Sat Apr 20 11:56:35 2013 +0000
Revision:
5:8a418c89e515
Parent:
3:967dde37e712
Child:
6:5b98c902a659
pre-publish

Who changed what in which revision?

UserRevisionLine numberNew contents of line
humlet 0:13c962fecb13 1 #ifndef I2CDRIVER_H
humlet 0:13c962fecb13 2 #define I2CDRIVER_H
humlet 0:13c962fecb13 3
humlet 0:13c962fecb13 4 #include "stdint.h"
humlet 0:13c962fecb13 5
humlet 0:13c962fecb13 6 #include "I2C.h"
humlet 0:13c962fecb13 7
humlet 0:13c962fecb13 8 #include "Thread.h"
humlet 0:13c962fecb13 9 #include "Mutex.h"
humlet 0:13c962fecb13 10
humlet 0:13c962fecb13 11 namespace mbed
humlet 0:13c962fecb13 12 {
humlet 5:8a418c89e515 13 /// I2C driver based on mbed RTOS and I2C-C-API.
humlet 5:8a418c89e515 14 /// Supports Master and Slave mode
humlet 3:967dde37e712 15 class I2CDriver
humlet 0:13c962fecb13 16 {
humlet 0:13c962fecb13 17 public:
humlet 5:8a418c89e515 18 /// Status returned by the receiveSlave() function
humlet 3:967dde37e712 19 enum SlaveRxStatus {
humlet 3:967dde37e712 20 NoData = 0,
humlet 3:967dde37e712 21 ReadAddressed = 1,
humlet 3:967dde37e712 22 WriteGeneral = 2,
humlet 3:967dde37e712 23 WriteAddressed = 3
humlet 3:967dde37e712 24 };
humlet 0:13c962fecb13 25
humlet 5:8a418c89e515 26 /** Create an I2C Master interface, connected to the specified pins.
humlet 0:13c962fecb13 27 *
humlet 0:13c962fecb13 28 * @param sda I2C data line pin
humlet 0:13c962fecb13 29 * @param scl I2C clock line pin
humlet 5:8a418c89e515 30 *
humlet 5:8a418c89e515 31 * @note Has to be created in a thread context, i.e. within the main or some other function. A global delaration does not work
humlet 0:13c962fecb13 32 */
humlet 3:967dde37e712 33 I2CDriver(PinName sda, PinName scl, int hz=100000, int slaveAdr=0);
humlet 3:967dde37e712 34
humlet 3:967dde37e712 35 /** Set the frequency of the I2C interface
humlet 3:967dde37e712 36 *
humlet 3:967dde37e712 37 * @param hz The bus frequency in hertz
humlet 3:967dde37e712 38 */
humlet 3:967dde37e712 39 void frequency(int hz) {
humlet 3:967dde37e712 40 m_freq = hz;
humlet 3:967dde37e712 41 }
humlet 0:13c962fecb13 42
humlet 0:13c962fecb13 43 /** Read from an I2C slave
humlet 0:13c962fecb13 44 *
humlet 0:13c962fecb13 45 * Performs a complete read transaction. The bottom bit of
humlet 0:13c962fecb13 46 * the address is forced to 1 to indicate a read.
humlet 0:13c962fecb13 47 *
humlet 0:13c962fecb13 48 * @param address 8-bit I2C slave address [ addr | 1 ]
humlet 0:13c962fecb13 49 * @param data Pointer to the byte-array to read data in to
humlet 0:13c962fecb13 50 * @param length Number of bytes to read
humlet 0:13c962fecb13 51 * @param repeated Repeated start, true - don't send stop at end
humlet 0:13c962fecb13 52 *
humlet 0:13c962fecb13 53 * @returns
humlet 0:13c962fecb13 54 * 0 on success (ack),
humlet 0:13c962fecb13 55 * non-0 on failure (nack)
humlet 0:13c962fecb13 56 */
humlet 3:967dde37e712 57 int readMaster(int address, char *data, int length, bool repeated = false);
humlet 0:13c962fecb13 58
humlet 3:967dde37e712 59 /** Read from a given I2C slave register
humlet 3:967dde37e712 60 *
humlet 3:967dde37e712 61 * Performs a complete write-register-read-data-transaction. The bottom bit of
humlet 3:967dde37e712 62 * the address is forced to 1 to indicate a read.
humlet 3:967dde37e712 63 *
humlet 3:967dde37e712 64 * @param address 8-bit I2C slave address [ addr | 1 ]
humlet 3:967dde37e712 65 * @param _register 8-bit regster address
humlet 3:967dde37e712 66 * @param data Pointer to the byte-array to read data in to
humlet 3:967dde37e712 67 * @param length Number of bytes to read
humlet 3:967dde37e712 68 * @param repeated Repeated start, true - don't send stop at end
humlet 3:967dde37e712 69 *
humlet 3:967dde37e712 70 * @returns
humlet 3:967dde37e712 71 * 0 on success (ack),
humlet 3:967dde37e712 72 * non-0 on failure (nack)
humlet 3:967dde37e712 73 */
humlet 3:967dde37e712 74 int readMaster(int address, uint8_t _register, char *data, int length, bool repeated = false);
humlet 1:90455d5bdd8c 75
humlet 0:13c962fecb13 76 /** Read a single byte from the I2C bus
humlet 0:13c962fecb13 77 *
humlet 0:13c962fecb13 78 * @param ack indicates if the byte is to be acknowledged (1 = acknowledge)
humlet 0:13c962fecb13 79 *
humlet 0:13c962fecb13 80 * @returns
humlet 0:13c962fecb13 81 * the byte read
humlet 0:13c962fecb13 82 */
humlet 3:967dde37e712 83 int readMaster(int ack=1);
humlet 0:13c962fecb13 84
humlet 0:13c962fecb13 85 /** Write to an I2C slave
humlet 0:13c962fecb13 86 *
humlet 0:13c962fecb13 87 * Performs a complete write transaction. The bottom bit of
humlet 0:13c962fecb13 88 * the address is forced to 0 to indicate a write.
humlet 0:13c962fecb13 89 *
humlet 0:13c962fecb13 90 * @param address 8-bit I2C slave address [ addr | 0 ]
humlet 0:13c962fecb13 91 * @param data Pointer to the byte-array data to send
humlet 0:13c962fecb13 92 * @param length Number of bytes to send
humlet 0:13c962fecb13 93 * @param repeated Repeated start, true - do not send stop at end
humlet 0:13c962fecb13 94 *
humlet 0:13c962fecb13 95 * @returns
humlet 0:13c962fecb13 96 * 0 on success (ack),
humlet 0:13c962fecb13 97 * non-0 on failure (nack)
humlet 0:13c962fecb13 98 */
humlet 3:967dde37e712 99 int writeMaster(int address, const char *data, int length, bool repeated = false);
humlet 0:13c962fecb13 100
humlet 0:13c962fecb13 101 /** Write single byte out on the I2C bus
humlet 0:13c962fecb13 102 *
humlet 0:13c962fecb13 103 * @param data data to write out on bus
humlet 0:13c962fecb13 104 *
humlet 0:13c962fecb13 105 * @returns
humlet 0:13c962fecb13 106 * '1' if an ACK was received,
humlet 0:13c962fecb13 107 * '0' otherwise
humlet 0:13c962fecb13 108 */
humlet 3:967dde37e712 109 int writeMaster(int data);
humlet 3:967dde37e712 110
humlet 3:967dde37e712 111 /** Sets the I2C slave address.
humlet 3:967dde37e712 112 *
humlet 3:967dde37e712 113 * @param address The address to set for the slave (ignoring the least
humlet 3:967dde37e712 114 * signifcant bit). If set to 0, the slave will only respond to the
humlet 3:967dde37e712 115 * general call address.
humlet 3:967dde37e712 116 */
humlet 3:967dde37e712 117 void addressSlave(int address) {
humlet 3:967dde37e712 118 m_slaveAdr=address;
humlet 3:967dde37e712 119 }
humlet 3:967dde37e712 120
humlet 3:967dde37e712 121 /** Checks to see if this I2C Slave has been addressed.
humlet 3:967dde37e712 122 *
humlet 3:967dde37e712 123 * @returns
humlet 3:967dde37e712 124 * A status indicating if the device has been addressed, and how
humlet 3:967dde37e712 125 * - NoData - the slave has not been addressed
humlet 3:967dde37e712 126 * - ReadAddressed - the master has requested a read from this slave
humlet 3:967dde37e712 127 * - WriteAddressed - the master is writing to this slave
humlet 3:967dde37e712 128 * - WriteGeneral - the master is writing to all slave
humlet 3:967dde37e712 129 */
humlet 3:967dde37e712 130 int receiveSlave(uint32_t timeout_ms=osWaitForever);
humlet 3:967dde37e712 131
humlet 3:967dde37e712 132 /** Read from an I2C master.
humlet 3:967dde37e712 133 *
humlet 3:967dde37e712 134 * @param data pointer to the byte array to read data in to
humlet 3:967dde37e712 135 * @param length maximum number of bytes to read
humlet 3:967dde37e712 136 *
humlet 3:967dde37e712 137 * @returns
humlet 3:967dde37e712 138 * 0 on success,
humlet 3:967dde37e712 139 * non-0 otherwise
humlet 3:967dde37e712 140 */
humlet 3:967dde37e712 141 int readSlave(char *data, int length);
humlet 3:967dde37e712 142
humlet 3:967dde37e712 143 /** Read a single byte from an I2C master.
humlet 3:967dde37e712 144 *
humlet 3:967dde37e712 145 * @returns
humlet 3:967dde37e712 146 * the byte read
humlet 3:967dde37e712 147 */
humlet 3:967dde37e712 148 int readSlave(void);
humlet 3:967dde37e712 149
humlet 3:967dde37e712 150 /** Write to an I2C master.
humlet 3:967dde37e712 151 *
humlet 3:967dde37e712 152 * @param data pointer to the byte array to be transmitted
humlet 3:967dde37e712 153 * @param length the number of bytes to transmite
humlet 3:967dde37e712 154 *
humlet 3:967dde37e712 155 * @returns
humlet 3:967dde37e712 156 * 0 on success,
humlet 3:967dde37e712 157 * non-0 otherwise
humlet 3:967dde37e712 158 */
humlet 3:967dde37e712 159 int writeSlave(const char *data, int length);
humlet 3:967dde37e712 160
humlet 3:967dde37e712 161 /** Write a single byte to an I2C master.
humlet 3:967dde37e712 162 *
humlet 3:967dde37e712 163 * @data the byte to write
humlet 3:967dde37e712 164 *
humlet 3:967dde37e712 165 * @returns
humlet 3:967dde37e712 166 * '1' if an ACK was received,
humlet 3:967dde37e712 167 * '0' otherwise
humlet 3:967dde37e712 168 */
humlet 3:967dde37e712 169 int writeSlave(int data);
humlet 3:967dde37e712 170
humlet 0:13c962fecb13 171
humlet 0:13c962fecb13 172 /// Creates a start condition on the I2C bus
humlet 3:967dde37e712 173 void startMaster(void);
humlet 0:13c962fecb13 174
humlet 0:13c962fecb13 175 ///Creates a stop condition on the I2C bus
humlet 3:967dde37e712 176 void stopSlave(void);
humlet 3:967dde37e712 177
humlet 3:967dde37e712 178 ///Creates a stop condition on the I2C bus
humlet 3:967dde37e712 179 void stopMaster(void);
humlet 3:967dde37e712 180
humlet 3:967dde37e712 181
humlet 0:13c962fecb13 182
humlet 0:13c962fecb13 183 /// Wait until the i2c driver becomes available.
humlet 3:967dde37e712 184 ///
humlet 3:967dde37e712 185 /// Useful if you want to run a sequence of command without interrution by another thread.
humlet 3:967dde37e712 186 /// There's no need to call this function for running single request, because all driver functions
humlet 3:967dde37e712 187 /// will lock the device for exclusive access automatically.
humlet 2:514105beb343 188 void lock() {
humlet 3:967dde37e712 189 // One and the same thread can lock twice, but then it needs also to unlock twice.
humlet 0:13c962fecb13 190 // exactly what we need here
humlet 1:90455d5bdd8c 191 m_channel->mutex.lock(osWaitForever);
humlet 0:13c962fecb13 192 }
humlet 0:13c962fecb13 193
humlet 3:967dde37e712 194 /// Unlock the driver that has previously been locked by the same thread.
humlet 2:514105beb343 195 void unlock() {
humlet 1:90455d5bdd8c 196 m_channel->mutex.unlock();
humlet 0:13c962fecb13 197 }
humlet 0:13c962fecb13 198
humlet 0:13c962fecb13 199 protected:
humlet 5:8a418c89e515 200 // commands sent from user to drive thread
humlet 0:13c962fecb13 201 enum Command {
humlet 0:13c962fecb13 202 START,
humlet 0:13c962fecb13 203 STOP,
humlet 3:967dde37e712 204 READ_MST,
humlet 3:967dde37e712 205 READ_MST_REG,
humlet 3:967dde37e712 206 READ_SLV,
humlet 0:13c962fecb13 207 READ_BYTE,
humlet 3:967dde37e712 208 WRITE_MST,
humlet 3:967dde37e712 209 WRITE_SLV,
humlet 3:967dde37e712 210 WRITE_BYTE,
humlet 3:967dde37e712 211 RECEIVE
humlet 1:90455d5bdd8c 212 };
humlet 5:8a418c89e515 213
humlet 5:8a418c89e515 214 // data transfer struct for communication between user and driver thread
humlet 0:13c962fecb13 215 struct Transfer {
humlet 0:13c962fecb13 216 Command cmd;
humlet 3:967dde37e712 217 int ret;
humlet 0:13c962fecb13 218 int freq;
humlet 0:13c962fecb13 219 int adr;
humlet 0:13c962fecb13 220 char* dta;
humlet 1:90455d5bdd8c 221 const char* wdta;
humlet 0:13c962fecb13 222 int len;
humlet 1:90455d5bdd8c 223 int ack;
humlet 0:13c962fecb13 224 bool rep;
humlet 3:967dde37e712 225 uint8_t reg;
humlet 3:967dde37e712 226 bool slv;
humlet 3:967dde37e712 227 uint32_t tmout;
humlet 3:967dde37e712 228 osThreadId caller;
humlet 1:90455d5bdd8c 229 };
humlet 0:13c962fecb13 230
humlet 5:8a418c89e515 231 // structure that holds handles/locks for accessing the I2C channels
humlet 0:13c962fecb13 232 struct Channel {
humlet 5:8a418c89e515 233 osThreadId driver;
humlet 1:90455d5bdd8c 234 rtos::Mutex mutex;
humlet 1:90455d5bdd8c 235 volatile Transfer transfer;
humlet 1:90455d5bdd8c 236 };
humlet 5:8a418c89e515 237
humlet 5:8a418c89e515 238 // current frequency setting
humlet 3:967dde37e712 239 int m_freq;
humlet 5:8a418c89e515 240 // current slave address setting
humlet 3:967dde37e712 241 int m_slaveAdr;
humlet 5:8a418c89e515 242
humlet 5:8a418c89e515 243 // the pin names fo the i2c channels
humlet 1:90455d5bdd8c 244 static const PinName c_sdas[2];
humlet 1:90455d5bdd8c 245 static const PinName c_scls[2];
humlet 0:13c962fecb13 246
humlet 5:8a418c89e515 247 // static storage for the I2C channel access objects
humlet 2:514105beb343 248 static Channel* s_channels[2];
humlet 5:8a418c89e515 249
humlet 5:8a418c89e515 250 // i2c channel object of this driver interface, in fact just pointer
humlet 5:8a418c89e515 251 /// to one of the entries in s_channels
humlet 2:514105beb343 252 Channel* m_channel;
humlet 5:8a418c89e515 253
humlet 5:8a418c89e515 254 // ISRs
humlet 0:13c962fecb13 255 static void channel_0_ISR();
humlet 0:13c962fecb13 256 static void channel_1_ISR();
humlet 5:8a418c89e515 257
humlet 5:8a418c89e515 258 // the driver thread function
humlet 1:90455d5bdd8c 259 static void threadFun(void const *args);
humlet 5:8a418c89e515 260
humlet 3:967dde37e712 261 int sendNwait();
humlet 1:90455d5bdd8c 262 };
humlet 0:13c962fecb13 263 }
humlet 0:13c962fecb13 264 #endif