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-05-22
Revision:
2:19e7e472a51f
Parent:
0:96a7926b9d64

File content as of revision 2:19e7e472a51f:

#include "I2CTransaction.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
    - 88: read ACK
*/

// Initialization of static member (kind of gross to do it this way)
//MODI2C* I2CTransaction::i2c = new MODI2C(p9, p10);
MODI2C* I2CTransaction::i2c = new MODI2C(p28, p27);

/**
    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);
}

/**
    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]));
        }
        return true;
    }
}

/**
    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%d\n\r", strg, status[0]);
    } else {
        // Write - Read
        pc->printf("%s\t%d\t%d\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);
}