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.
I2CTransaction.cpp
00001 #include "I2CTransaction.h" 00002 #include "rtos.h" 00003 00004 /** 00005 I2C Transaction Class. 00006 00007 Author: Andrew H. Fagg (May, 2014) 00008 00009 TODO: finish this description 00010 00011 This class provides: 00012 - Interrupt-driven I2C master functionality 00013 - Representations of whole transactions 00014 00015 I2C Transactions generally come in two varieties: a write and a write followed by a read 00016 00017 00018 00019 Notes: 00020 I2C Status codes: 00021 - 32: write NO-ACK 00022 - 72: read NO-ACK 00023 - 40: write ACK 00024 - 48: ?? 00025 - 88: read ACK 00026 */ 00027 00028 // Initialization of static member (kind of gross to do it this way - need to find another solution) 00029 //MODI2C* I2CTransaction::i2c = new MODI2C(p9, p10); 00030 MODI2C* I2CTransaction::i2c = NULL; //new MODI2C(p28, p27); 00031 int I2CTransaction::maxRetryCount = -1; // No recovery by default 00032 00033 /** 00034 Transaction constructor 00035 00036 @param I2C address (7-bit address) 00037 @param writePacket Pointer to the data structure to be written 00038 @param writePacketLength Number of bytes to be written 00039 @param readPacket Pointer to the data structure to be filled during the read (NULL = none) 00040 @param readPacketLength Number of bytes to read 00041 */ 00042 00043 I2CTransaction::I2CTransaction(int address, char* writePacket, int writePacketLength, char* readPacket, int readPacketLength) 00044 { 00045 this->address = address; 00046 this->writePacket = writePacket; 00047 this->writePacketLength = writePacketLength; 00048 this->readPacket = readPacket; 00049 this->readPacketLength = readPacketLength; 00050 if(readPacket == NULL) this->readPacketLength = 0; 00051 status[0] = status[1] = -1; 00052 } 00053 00054 /** 00055 Set the I2C bus frequency 00056 00057 @param frequency in Hertz 00058 */ 00059 00060 void I2CTransaction::setFrequency(int frequency) 00061 { 00062 i2c->frequency(frequency); 00063 } 00064 00065 00066 void I2CTransaction::setMaxRetry(int maxRetry) 00067 { 00068 maxRetryCount = maxRetry; 00069 } 00070 00071 /** 00072 Indicate whether the transaction has completed (whether successful or not) 00073 00074 Note: assumes that for the case with no read part of the transaction, status[1] 00075 has been left in its initial state (-1) 00076 */ 00077 00078 bool I2CTransaction::completed() 00079 { 00080 return(status[0] != 0 && status[1] != 0); 00081 } 00082 00083 /** 00084 Return the specified status code for this transaction 00085 00086 @param i 0 = write status code; 1 = read status code 00087 @return Status code (see documentation at top of this file) 00088 */ 00089 00090 int I2CTransaction::getStatus(int i) 00091 { 00092 if(i >= 0 && i <= 1) return status[i]; 00093 else return -1; 00094 } 00095 00096 /** 00097 Start a transaction. 00098 00099 Does not initiate a transaction if it is already in progress. 00100 00101 Note: no error checking yet on the read and write calls 00102 00103 @return true if transaction has been initiated; false if it is already in progress 00104 */ 00105 00106 bool I2CTransaction::initiateTransaction() 00107 { 00108 if(!completed()) { 00109 // Already in progress: bail 00110 00111 return false; 00112 } else { 00113 // Start the write 00114 i2c->write(address << 1, writePacket, writePacketLength, false, &(status[0])); 00115 00116 // Start the read if it exists 00117 if(readPacket != NULL) { 00118 i2c->read_nb(address << 1, readPacket, readPacketLength, false, &(status[1])); 00119 } 00120 // Reset the retry count; 00121 retryCount = 0; 00122 return true; 00123 } 00124 } 00125 00126 bool I2CTransaction::checkTransaction() 00127 { 00128 // Increment the counter for number of times we have tried to initiate this transaction. 00129 ++retryCount; 00130 00131 // Have we exceeded the maximum number of allowed retries 00132 if(maxRetryCount != -1 && retryCount >= maxRetryCount) { 00133 // Yes: reset so next time we can try again 00134 status[0] = status[1] = -1; 00135 retryCount = 0; 00136 return true; 00137 } 00138 return false; 00139 } 00140 00141 /** 00142 Wait until the transaction has completed, up to the specified number of milliseconds 00143 00144 @param timeout Number of milliseconds to wait 00145 00146 @return true if transaction completed; false if timed out 00147 */ 00148 00149 bool I2CTransaction::waitForCompletion(int timeout) 00150 { 00151 for(int i = 0; i < timeout; ++i) { 00152 if(this->completed()) return true; 00153 wait_ms(1); 00154 } 00155 return(false); 00156 } 00157 00158 /** 00159 Display the transaction status codes 00160 00161 @param pc Pointer to an initialized serial handler 00162 @param strg String description of this transaction 00163 */ 00164 00165 void I2CTransaction::displayStatus(Serial *pc, char* strg) 00166 { 00167 if(readPacket == NULL) { 00168 // Write only 00169 pc->printf("%s\t%x\n\r", strg, status[0]); 00170 } else { 00171 // Write - Read 00172 pc->printf("%s\t%x\t%x\n\r", strg, status[0], status[1]); 00173 } 00174 } 00175 00176 /** 00177 Check that the transaction was successfully completed. 00178 00179 @return true if successful, false if not 00180 */ 00181 00182 bool I2CTransaction::success() 00183 { 00184 // Write transaction must have completed with the correct status code (40) 00185 // Read transaction, if it exists, must also complete correctly (88) 00186 return (status[0] == 40) && (readPacket == NULL || status[1] == 88); 00187 } 00188 00189 00190 /** 00191 Check that the transaction has an error 00192 00193 @return true if error, false if not 00194 */ 00195 00196 bool I2CTransaction::transmissionError() 00197 { 00198 // Write transaction has completed with an error code (can't be 0 (in progress) or 40 (correct)) 00199 // Read transaction, if it exists, has completed with an error code (can't be 0 (in progress) or 88 (correct)) 00200 return (status[0] != 0 && status[0] != 40) || (readPacket != NULL && status[1] != 0 && status[1] != 88); 00201 } 00202 00203 /** 00204 Report the number of I2C transactions that are in the queue 00205 00206 @return Number of items 00207 */ 00208 00209 int I2CTransaction::getI2CQueueLength() 00210 { 00211 return(i2c->getQueue()); 00212 } 00213 00214 /** 00215 Attempt a reset of the I2C bus by forcing a STOP message. Use with caution. 00216 **/ 00217 00218 void I2CTransaction::reset() 00219 { 00220 delete i2c; 00221 i2c = new MODI2C(p28, p27); 00222 } 00223 00224 void I2CTransaction::resetBus() 00225 { 00226 i2c->stop(); 00227 i2c->start(); 00228 i2c->stop(); 00229 } 00230 00231 void I2CTransaction::cycleBus() 00232 { 00233 i2c->start(); 00234 Thread::wait(1); 00235 i2c->stop(); 00236 } 00237 00238 /** 00239 Set the status of the transaction back to -1 (usable). 00240 00241 Use at your own risk 00242 */ 00243 00244 void I2CTransaction::clearStatus() 00245 { 00246 status[0] = status[1] = -1; 00247 } 00248 00249 /** 00250 Initialize the I2C pins and other hardware. If it has already been initialized, then 00251 we will re-initialize. 00252 00253 @param sda Name of the pin that is used for data 00254 @param scl Name of the pin that is used for the clock 00255 */ 00256 00257 void I2CTransaction::initI2C(PinName sda, PinName scl) 00258 { 00259 if(i2c) { 00260 delete i2c; 00261 } 00262 i2c = new MODI2C(sda, scl); //p28, p27); 00263 }
Generated on Tue Jul 12 2022 23:09:24 by
1.7.2