Class for representing and controlling entire I2C transactions (the master side). This class allows one to separate in code the configuration of I2C transactions from their use. This property simplifies the process of executing transactions in, for example, the body of a real-time control loop.

Committer:
symbiotic
Date:
Sat Dec 20 15:41:21 2014 +0000
Revision:
8:63e07ac95a2c
Parent:
7:61e9a1da1f20
Added Transaction reset support

Who changed what in which revision?

UserRevisionLine numberNew contents of line
symbiotic 0:96a7926b9d64 1 #include "I2CTransaction.h"
symbiotic 6:4775131da69b 2 #include "rtos.h"
symbiotic 0:96a7926b9d64 3
symbiotic 0:96a7926b9d64 4 /**
symbiotic 0:96a7926b9d64 5 I2C Transaction Class.
symbiotic 5:ad382f9f43ca 6
symbiotic 0:96a7926b9d64 7 Author: Andrew H. Fagg (May, 2014)
symbiotic 5:ad382f9f43ca 8
symbiotic 0:96a7926b9d64 9 TODO: finish this description
symbiotic 5:ad382f9f43ca 10
symbiotic 0:96a7926b9d64 11 This class provides:
symbiotic 0:96a7926b9d64 12 - Interrupt-driven I2C master functionality
symbiotic 0:96a7926b9d64 13 - Representations of whole transactions
symbiotic 5:ad382f9f43ca 14
symbiotic 0:96a7926b9d64 15 I2C Transactions generally come in two varieties: a write and a write followed by a read
symbiotic 0:96a7926b9d64 16
symbiotic 0:96a7926b9d64 17
symbiotic 0:96a7926b9d64 18
symbiotic 0:96a7926b9d64 19 Notes:
symbiotic 0:96a7926b9d64 20 I2C Status codes:
symbiotic 0:96a7926b9d64 21 - 32: write NO-ACK
symbiotic 0:96a7926b9d64 22 - 72: read NO-ACK
symbiotic 0:96a7926b9d64 23 - 40: write ACK
symbiotic 4:73de554a67ff 24 - 48: ??
symbiotic 0:96a7926b9d64 25 - 88: read ACK
symbiotic 0:96a7926b9d64 26 */
symbiotic 0:96a7926b9d64 27
symbiotic 1:5d9e9c0682f0 28 // Initialization of static member (kind of gross to do it this way - need to find another solution)
symbiotic 0:96a7926b9d64 29 //MODI2C* I2CTransaction::i2c = new MODI2C(p9, p10);
symbiotic 7:61e9a1da1f20 30 MODI2C* I2CTransaction::i2c = NULL; //new MODI2C(p28, p27);
symbiotic 5:ad382f9f43ca 31 int I2CTransaction::maxRetryCount = -1; // No recovery by default
symbiotic 0:96a7926b9d64 32
symbiotic 0:96a7926b9d64 33 /**
symbiotic 0:96a7926b9d64 34 Transaction constructor
symbiotic 5:ad382f9f43ca 35
symbiotic 0:96a7926b9d64 36 @param I2C address (7-bit address)
symbiotic 0:96a7926b9d64 37 @param writePacket Pointer to the data structure to be written
symbiotic 0:96a7926b9d64 38 @param writePacketLength Number of bytes to be written
symbiotic 0:96a7926b9d64 39 @param readPacket Pointer to the data structure to be filled during the read (NULL = none)
symbiotic 0:96a7926b9d64 40 @param readPacketLength Number of bytes to read
symbiotic 0:96a7926b9d64 41 */
symbiotic 0:96a7926b9d64 42
symbiotic 0:96a7926b9d64 43 I2CTransaction::I2CTransaction(int address, char* writePacket, int writePacketLength, char* readPacket, int readPacketLength)
symbiotic 0:96a7926b9d64 44 {
symbiotic 0:96a7926b9d64 45 this->address = address;
symbiotic 0:96a7926b9d64 46 this->writePacket = writePacket;
symbiotic 0:96a7926b9d64 47 this->writePacketLength = writePacketLength;
symbiotic 0:96a7926b9d64 48 this->readPacket = readPacket;
symbiotic 0:96a7926b9d64 49 this->readPacketLength = readPacketLength;
symbiotic 0:96a7926b9d64 50 if(readPacket == NULL) this->readPacketLength = 0;
symbiotic 0:96a7926b9d64 51 status[0] = status[1] = -1;
symbiotic 0:96a7926b9d64 52 }
symbiotic 0:96a7926b9d64 53
symbiotic 0:96a7926b9d64 54 /**
symbiotic 0:96a7926b9d64 55 Set the I2C bus frequency
symbiotic 5:ad382f9f43ca 56
symbiotic 0:96a7926b9d64 57 @param frequency in Hertz
symbiotic 0:96a7926b9d64 58 */
symbiotic 0:96a7926b9d64 59
symbiotic 0:96a7926b9d64 60 void I2CTransaction::setFrequency(int frequency)
symbiotic 0:96a7926b9d64 61 {
symbiotic 0:96a7926b9d64 62 i2c->frequency(frequency);
symbiotic 0:96a7926b9d64 63 }
symbiotic 0:96a7926b9d64 64
symbiotic 5:ad382f9f43ca 65
symbiotic 5:ad382f9f43ca 66 void I2CTransaction::setMaxRetry(int maxRetry)
symbiotic 5:ad382f9f43ca 67 {
symbiotic 5:ad382f9f43ca 68 maxRetryCount = maxRetry;
symbiotic 5:ad382f9f43ca 69 }
symbiotic 5:ad382f9f43ca 70
symbiotic 0:96a7926b9d64 71 /**
symbiotic 0:96a7926b9d64 72 Indicate whether the transaction has completed (whether successful or not)
symbiotic 5:ad382f9f43ca 73
symbiotic 0:96a7926b9d64 74 Note: assumes that for the case with no read part of the transaction, status[1]
symbiotic 0:96a7926b9d64 75 has been left in its initial state (-1)
symbiotic 0:96a7926b9d64 76 */
symbiotic 0:96a7926b9d64 77
symbiotic 0:96a7926b9d64 78 bool I2CTransaction::completed()
symbiotic 0:96a7926b9d64 79 {
symbiotic 0:96a7926b9d64 80 return(status[0] != 0 && status[1] != 0);
symbiotic 0:96a7926b9d64 81 }
symbiotic 0:96a7926b9d64 82
symbiotic 0:96a7926b9d64 83 /**
symbiotic 0:96a7926b9d64 84 Return the specified status code for this transaction
symbiotic 5:ad382f9f43ca 85
symbiotic 0:96a7926b9d64 86 @param i 0 = write status code; 1 = read status code
symbiotic 0:96a7926b9d64 87 @return Status code (see documentation at top of this file)
symbiotic 0:96a7926b9d64 88 */
symbiotic 0:96a7926b9d64 89
symbiotic 0:96a7926b9d64 90 int I2CTransaction::getStatus(int i)
symbiotic 0:96a7926b9d64 91 {
symbiotic 0:96a7926b9d64 92 if(i >= 0 && i <= 1) return status[i];
symbiotic 0:96a7926b9d64 93 else return -1;
symbiotic 0:96a7926b9d64 94 }
symbiotic 0:96a7926b9d64 95
symbiotic 0:96a7926b9d64 96 /**
symbiotic 0:96a7926b9d64 97 Start a transaction.
symbiotic 5:ad382f9f43ca 98
symbiotic 0:96a7926b9d64 99 Does not initiate a transaction if it is already in progress.
symbiotic 5:ad382f9f43ca 100
symbiotic 0:96a7926b9d64 101 Note: no error checking yet on the read and write calls
symbiotic 5:ad382f9f43ca 102
symbiotic 0:96a7926b9d64 103 @return true if transaction has been initiated; false if it is already in progress
symbiotic 0:96a7926b9d64 104 */
symbiotic 0:96a7926b9d64 105
symbiotic 0:96a7926b9d64 106 bool I2CTransaction::initiateTransaction()
symbiotic 0:96a7926b9d64 107 {
symbiotic 0:96a7926b9d64 108 if(!completed()) {
symbiotic 0:96a7926b9d64 109 // Already in progress: bail
symbiotic 5:ad382f9f43ca 110
symbiotic 0:96a7926b9d64 111 return false;
symbiotic 0:96a7926b9d64 112 } else {
symbiotic 0:96a7926b9d64 113 // Start the write
symbiotic 0:96a7926b9d64 114 i2c->write(address << 1, writePacket, writePacketLength, false, &(status[0]));
symbiotic 5:ad382f9f43ca 115
symbiotic 0:96a7926b9d64 116 // Start the read if it exists
symbiotic 0:96a7926b9d64 117 if(readPacket != NULL) {
symbiotic 0:96a7926b9d64 118 i2c->read_nb(address << 1, readPacket, readPacketLength, false, &(status[1]));
symbiotic 0:96a7926b9d64 119 }
symbiotic 5:ad382f9f43ca 120 // Reset the retry count;
symbiotic 5:ad382f9f43ca 121 retryCount = 0;
symbiotic 0:96a7926b9d64 122 return true;
symbiotic 0:96a7926b9d64 123 }
symbiotic 0:96a7926b9d64 124 }
symbiotic 0:96a7926b9d64 125
symbiotic 5:ad382f9f43ca 126 bool I2CTransaction::checkTransaction()
symbiotic 5:ad382f9f43ca 127 {
symbiotic 5:ad382f9f43ca 128 // Increment the counter for number of times we have tried to initiate this transaction.
symbiotic 5:ad382f9f43ca 129 ++retryCount;
symbiotic 5:ad382f9f43ca 130
symbiotic 5:ad382f9f43ca 131 // Have we exceeded the maximum number of allowed retries
symbiotic 5:ad382f9f43ca 132 if(maxRetryCount != -1 && retryCount >= maxRetryCount) {
symbiotic 5:ad382f9f43ca 133 // Yes: reset so next time we can try again
symbiotic 5:ad382f9f43ca 134 status[0] = status[1] = -1;
symbiotic 5:ad382f9f43ca 135 retryCount = 0;
symbiotic 5:ad382f9f43ca 136 return true;
symbiotic 5:ad382f9f43ca 137 }
symbiotic 5:ad382f9f43ca 138 return false;
symbiotic 5:ad382f9f43ca 139 }
symbiotic 5:ad382f9f43ca 140
symbiotic 0:96a7926b9d64 141 /**
symbiotic 0:96a7926b9d64 142 Wait until the transaction has completed, up to the specified number of milliseconds
symbiotic 5:ad382f9f43ca 143
symbiotic 0:96a7926b9d64 144 @param timeout Number of milliseconds to wait
symbiotic 5:ad382f9f43ca 145
symbiotic 0:96a7926b9d64 146 @return true if transaction completed; false if timed out
symbiotic 0:96a7926b9d64 147 */
symbiotic 0:96a7926b9d64 148
symbiotic 0:96a7926b9d64 149 bool I2CTransaction::waitForCompletion(int timeout)
symbiotic 0:96a7926b9d64 150 {
symbiotic 0:96a7926b9d64 151 for(int i = 0; i < timeout; ++i) {
symbiotic 0:96a7926b9d64 152 if(this->completed()) return true;
symbiotic 0:96a7926b9d64 153 wait_ms(1);
symbiotic 0:96a7926b9d64 154 }
symbiotic 0:96a7926b9d64 155 return(false);
symbiotic 0:96a7926b9d64 156 }
symbiotic 0:96a7926b9d64 157
symbiotic 0:96a7926b9d64 158 /**
symbiotic 0:96a7926b9d64 159 Display the transaction status codes
symbiotic 0:96a7926b9d64 160
symbiotic 0:96a7926b9d64 161 @param pc Pointer to an initialized serial handler
symbiotic 0:96a7926b9d64 162 @param strg String description of this transaction
symbiotic 0:96a7926b9d64 163 */
symbiotic 0:96a7926b9d64 164
symbiotic 0:96a7926b9d64 165 void I2CTransaction::displayStatus(Serial *pc, char* strg)
symbiotic 0:96a7926b9d64 166 {
symbiotic 0:96a7926b9d64 167 if(readPacket == NULL) {
symbiotic 0:96a7926b9d64 168 // Write only
symbiotic 5:ad382f9f43ca 169 pc->printf("%s\t%x\n\r", strg, status[0]);
symbiotic 0:96a7926b9d64 170 } else {
symbiotic 0:96a7926b9d64 171 // Write - Read
symbiotic 5:ad382f9f43ca 172 pc->printf("%s\t%x\t%x\n\r", strg, status[0], status[1]);
symbiotic 0:96a7926b9d64 173 }
symbiotic 0:96a7926b9d64 174 }
symbiotic 0:96a7926b9d64 175
symbiotic 0:96a7926b9d64 176 /**
symbiotic 0:96a7926b9d64 177 Check that the transaction was successfully completed.
symbiotic 0:96a7926b9d64 178
symbiotic 0:96a7926b9d64 179 @return true if successful, false if not
symbiotic 0:96a7926b9d64 180 */
symbiotic 0:96a7926b9d64 181
symbiotic 0:96a7926b9d64 182 bool I2CTransaction::success()
symbiotic 0:96a7926b9d64 183 {
symbiotic 0:96a7926b9d64 184 // Write transaction must have completed with the correct status code (40)
symbiotic 0:96a7926b9d64 185 // Read transaction, if it exists, must also complete correctly (88)
symbiotic 0:96a7926b9d64 186 return (status[0] == 40) && (readPacket == NULL || status[1] == 88);
symbiotic 0:96a7926b9d64 187 }
symbiotic 0:96a7926b9d64 188
symbiotic 0:96a7926b9d64 189
symbiotic 0:96a7926b9d64 190 /**
symbiotic 0:96a7926b9d64 191 Check that the transaction has an error
symbiotic 0:96a7926b9d64 192
symbiotic 0:96a7926b9d64 193 @return true if error, false if not
symbiotic 0:96a7926b9d64 194 */
symbiotic 3:a9d61e73fe97 195
symbiotic 3:a9d61e73fe97 196 bool I2CTransaction::transmissionError()
symbiotic 0:96a7926b9d64 197 {
symbiotic 0:96a7926b9d64 198 // Write transaction has completed with an error code (can't be 0 (in progress) or 40 (correct))
symbiotic 0:96a7926b9d64 199 // Read transaction, if it exists, has completed with an error code (can't be 0 (in progress) or 88 (correct))
symbiotic 0:96a7926b9d64 200 return (status[0] != 0 && status[0] != 40) || (readPacket != NULL && status[1] != 0 && status[1] != 88);
symbiotic 1:5d9e9c0682f0 201 }
symbiotic 5:ad382f9f43ca 202
symbiotic 7:61e9a1da1f20 203 /**
symbiotic 7:61e9a1da1f20 204 Report the number of I2C transactions that are in the queue
symbiotic 7:61e9a1da1f20 205
symbiotic 7:61e9a1da1f20 206 @return Number of items
symbiotic 7:61e9a1da1f20 207 */
symbiotic 7:61e9a1da1f20 208
symbiotic 5:ad382f9f43ca 209 int I2CTransaction::getI2CQueueLength()
symbiotic 5:ad382f9f43ca 210 {
symbiotic 5:ad382f9f43ca 211 return(i2c->getQueue());
symbiotic 5:ad382f9f43ca 212 }
symbiotic 6:4775131da69b 213
symbiotic 7:61e9a1da1f20 214 /**
symbiotic 7:61e9a1da1f20 215 Attempt a reset of the I2C bus by forcing a STOP message. Use with caution.
symbiotic 7:61e9a1da1f20 216 **/
symbiotic 7:61e9a1da1f20 217
symbiotic 6:4775131da69b 218 void I2CTransaction::reset()
symbiotic 6:4775131da69b 219 {
symbiotic 6:4775131da69b 220 delete i2c;
symbiotic 6:4775131da69b 221 i2c = new MODI2C(p28, p27);
symbiotic 6:4775131da69b 222 }
symbiotic 6:4775131da69b 223
symbiotic 6:4775131da69b 224 void I2CTransaction::resetBus()
symbiotic 6:4775131da69b 225 {
symbiotic 6:4775131da69b 226 i2c->stop();
symbiotic 8:63e07ac95a2c 227 i2c->start();
symbiotic 8:63e07ac95a2c 228 i2c->stop();
symbiotic 6:4775131da69b 229 }
symbiotic 6:4775131da69b 230
symbiotic 6:4775131da69b 231 void I2CTransaction::cycleBus()
symbiotic 6:4775131da69b 232 {
symbiotic 6:4775131da69b 233 i2c->start();
symbiotic 6:4775131da69b 234 Thread::wait(1);
symbiotic 6:4775131da69b 235 i2c->stop();
symbiotic 6:4775131da69b 236 }
symbiotic 6:4775131da69b 237
symbiotic 7:61e9a1da1f20 238 /**
symbiotic 7:61e9a1da1f20 239 Set the status of the transaction back to -1 (usable).
symbiotic 7:61e9a1da1f20 240
symbiotic 7:61e9a1da1f20 241 Use at your own risk
symbiotic 7:61e9a1da1f20 242 */
symbiotic 7:61e9a1da1f20 243
symbiotic 7:61e9a1da1f20 244 void I2CTransaction::clearStatus()
symbiotic 7:61e9a1da1f20 245 {
symbiotic 7:61e9a1da1f20 246 status[0] = status[1] = -1;
symbiotic 7:61e9a1da1f20 247 }
symbiotic 7:61e9a1da1f20 248
symbiotic 7:61e9a1da1f20 249 /**
symbiotic 7:61e9a1da1f20 250 Initialize the I2C pins and other hardware. If it has already been initialized, then
symbiotic 7:61e9a1da1f20 251 we will re-initialize.
symbiotic 7:61e9a1da1f20 252
symbiotic 7:61e9a1da1f20 253 @param sda Name of the pin that is used for data
symbiotic 7:61e9a1da1f20 254 @param scl Name of the pin that is used for the clock
symbiotic 7:61e9a1da1f20 255 */
symbiotic 7:61e9a1da1f20 256
symbiotic 7:61e9a1da1f20 257 void I2CTransaction::initI2C(PinName sda, PinName scl)
symbiotic 7:61e9a1da1f20 258 {
symbiotic 7:61e9a1da1f20 259 if(i2c) {
symbiotic 7:61e9a1da1f20 260 delete i2c;
symbiotic 7:61e9a1da1f20 261 }
symbiotic 7:61e9a1da1f20 262 i2c = new MODI2C(sda, scl); //p28, p27);
symbiotic 7:61e9a1da1f20 263 }