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
- Committer:
- symbiotic
- Date:
- 2014-12-20
- Revision:
- 8:63e07ac95a2c
- Parent:
- 7:61e9a1da1f20
File content as of revision 8:63e07ac95a2c:
#include "I2CTransaction.h" #include "rtos.h" /** I2C Transaction Class. Author: Andrew H. Fagg (May, 2014) TODO: finish this description This class provides: - Interrupt-driven I2C master functionality - Representations of whole transactions I2C Transactions generally come in two varieties: a write and a write followed by a read Notes: I2C Status codes: - 32: write NO-ACK - 72: read NO-ACK - 40: write ACK - 48: ?? - 88: read ACK */ // Initialization of static member (kind of gross to do it this way - need to find another solution) //MODI2C* I2CTransaction::i2c = new MODI2C(p9, p10); MODI2C* I2CTransaction::i2c = NULL; //new MODI2C(p28, p27); int I2CTransaction::maxRetryCount = -1; // No recovery by default /** Transaction constructor @param I2C address (7-bit address) @param writePacket Pointer to the data structure to be written @param writePacketLength Number of bytes to be written @param readPacket Pointer to the data structure to be filled during the read (NULL = none) @param readPacketLength Number of bytes to read */ I2CTransaction::I2CTransaction(int address, char* writePacket, int writePacketLength, char* readPacket, int readPacketLength) { this->address = address; this->writePacket = writePacket; this->writePacketLength = writePacketLength; this->readPacket = readPacket; this->readPacketLength = readPacketLength; if(readPacket == NULL) this->readPacketLength = 0; status[0] = status[1] = -1; } /** Set the I2C bus frequency @param frequency in Hertz */ void I2CTransaction::setFrequency(int frequency) { i2c->frequency(frequency); } void I2CTransaction::setMaxRetry(int maxRetry) { maxRetryCount = maxRetry; } /** Indicate whether the transaction has completed (whether successful or not) Note: assumes that for the case with no read part of the transaction, status[1] has been left in its initial state (-1) */ bool I2CTransaction::completed() { return(status[0] != 0 && status[1] != 0); } /** Return the specified status code for this transaction @param i 0 = write status code; 1 = read status code @return Status code (see documentation at top of this file) */ int I2CTransaction::getStatus(int i) { if(i >= 0 && i <= 1) return status[i]; else return -1; } /** Start a transaction. Does not initiate a transaction if it is already in progress. Note: no error checking yet on the read and write calls @return true if transaction has been initiated; false if it is already in progress */ bool I2CTransaction::initiateTransaction() { if(!completed()) { // Already in progress: bail return false; } else { // Start the write i2c->write(address << 1, writePacket, writePacketLength, false, &(status[0])); // Start the read if it exists if(readPacket != NULL) { i2c->read_nb(address << 1, readPacket, readPacketLength, false, &(status[1])); } // Reset the retry count; retryCount = 0; return true; } } bool I2CTransaction::checkTransaction() { // Increment the counter for number of times we have tried to initiate this transaction. ++retryCount; // Have we exceeded the maximum number of allowed retries if(maxRetryCount != -1 && retryCount >= maxRetryCount) { // Yes: reset so next time we can try again status[0] = status[1] = -1; retryCount = 0; return true; } return false; } /** Wait until the transaction has completed, up to the specified number of milliseconds @param timeout Number of milliseconds to wait @return true if transaction completed; false if timed out */ bool I2CTransaction::waitForCompletion(int timeout) { for(int i = 0; i < timeout; ++i) { if(this->completed()) return true; wait_ms(1); } return(false); } /** Display the transaction status codes @param pc Pointer to an initialized serial handler @param strg String description of this transaction */ void I2CTransaction::displayStatus(Serial *pc, char* strg) { if(readPacket == NULL) { // Write only pc->printf("%s\t%x\n\r", strg, status[0]); } else { // Write - Read pc->printf("%s\t%x\t%x\n\r", strg, status[0], status[1]); } } /** Check that the transaction was successfully completed. @return true if successful, false if not */ bool I2CTransaction::success() { // Write transaction must have completed with the correct status code (40) // Read transaction, if it exists, must also complete correctly (88) return (status[0] == 40) && (readPacket == NULL || status[1] == 88); } /** Check that the transaction has an error @return true if error, false if not */ bool I2CTransaction::transmissionError() { // Write transaction has completed with an error code (can't be 0 (in progress) or 40 (correct)) // Read transaction, if it exists, has completed with an error code (can't be 0 (in progress) or 88 (correct)) return (status[0] != 0 && status[0] != 40) || (readPacket != NULL && status[1] != 0 && status[1] != 88); } /** Report the number of I2C transactions that are in the queue @return Number of items */ int I2CTransaction::getI2CQueueLength() { return(i2c->getQueue()); } /** Attempt a reset of the I2C bus by forcing a STOP message. Use with caution. **/ void I2CTransaction::reset() { delete i2c; i2c = new MODI2C(p28, p27); } void I2CTransaction::resetBus() { i2c->stop(); i2c->start(); i2c->stop(); } void I2CTransaction::cycleBus() { i2c->start(); Thread::wait(1); i2c->stop(); } /** Set the status of the transaction back to -1 (usable). Use at your own risk */ void I2CTransaction::clearStatus() { status[0] = status[1] = -1; } /** Initialize the I2C pins and other hardware. If it has already been initialized, then we will re-initialize. @param sda Name of the pin that is used for data @param scl Name of the pin that is used for the clock */ void I2CTransaction::initI2C(PinName sda, PinName scl) { if(i2c) { delete i2c; } i2c = new MODI2C(sda, scl); //p28, p27); }