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:
Fri Apr 19 21:33:29 2013 +0000
Revision:
3:967dde37e712
Parent:
2:514105beb343
Child:
5:8a418c89e515
refactored, compiles and crashes

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