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:
Mon May 26 20:06:44 2014 +0000
Revision:
5:ad382f9f43ca
Parent:
4:73de554a67ff
Child:
6:4775131da69b
Added support for resetting transactions that are in an error state (not clear that this is a good idea with theMODI2C library)

Who changed what in which revision?

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