Interrupt based I2C functionality for the LPC1768. (If you want the other one, send a PM and I might make it). Also adds buffer functionality to the I2C bus.

Dependents:   Algoritmo_Fuzzy FlyBed1 FlyBedLight

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MODI2C_IRQ.cpp Source File

MODI2C_IRQ.cpp

00001 #include "MODI2C.h"
00002 
00003 //**********************************************************
00004 //*********************IRQ FUNCTIONS************************
00005 //**********************************************************
00006 
00007 
00008 void MODI2C::runUserIRQ(I2CData Data) {
00009      
00010     if (IRQOp==IRQ_I2C_BOTH)        //Always call if both
00011         callback.call();
00012     if ((IRQOp==IRQ_I2C_READ)&&(Data.address&0x01)) //Call if read and byte was read
00013         callback.call();
00014     if ((IRQOp==IRQ_I2C_WRITE)&&(!(Data.address&0x01))) //Call if write and byte was written
00015         callback.call();
00016 }
00017 
00018 void MODI2C::IRQ1Handler( void ) {
00019     IRQHandler(&Buffer1, LPC_I2C1);
00020 }
00021 
00022 void MODI2C::IRQ2Handler( void ) {
00023     IRQHandler(&Buffer2, LPC_I2C2);
00024 }
00025 
00026 void MODI2C::IRQHandler( I2CBuffer *Buffer, LPC_I2C_TypeDef *I2CMODULE) {
00027     I2CData *Data = &Buffer->Data[0];
00028 
00029     //Depending on the status register it determines next action, see datasheet
00030     //This is also pretty much copy pasting the datasheet
00031     //General options
00032     switch (I2CMODULE->I2STAT) {
00033         case(0x08):
00034         case(0x10):
00035             //Send Address
00036             I2CMODULE->I2DAT = Data->address;
00037             I2CMODULE->I2CONCLR = 1<<I2C_FLAG | 1<<I2C_START;
00038             break;
00039 
00040             //All master TX options
00041 
00042             //Address + W has been sent, ACK received
00043             //Data has been sent, ACK received
00044         case(0x18):
00045         case(0x28):
00046             if (Buffer->count==Data->length) {
00047                 *Data->status=I2CMODULE->I2STAT;
00048                 if (!Data->repeated)
00049                     _stop(I2CMODULE);
00050                 else {
00051                     I2CMODULE->I2CONSET = 1<<I2C_START;
00052                     I2CMODULE->I2CONCLR = 1<<I2C_FLAG;
00053                 }
00054                 bufferHandler(I2CMODULE);
00055             } else {
00056                 I2CMODULE->I2DAT = Data->data[Buffer->count];
00057                 I2CMODULE->I2CONSET = 1<<I2C_ASSERT_ACK;        //I dont see why I have to enable that bit, but datasheet says so
00058                 I2CMODULE->I2CONCLR = 1<<I2C_FLAG;
00059                 Buffer->count++;
00060             }
00061             break;
00062 
00063             //Address + W has been sent, NACK received
00064             //Data has been sent, NACK received
00065         case(0x20):
00066         case(0x30):
00067             *Data->status=I2CMODULE->I2STAT;
00068             _stop(I2CMODULE);
00069             bufferHandler(I2CMODULE);
00070             break;
00071 
00072             //Arbitration lost (situation looks pretty hopeless to me if you arrive here)
00073         case(0x38):
00074             _start(I2CMODULE);
00075             break;
00076 
00077 
00078             //All master RX options
00079 
00080             //Address + R has been sent, ACK received
00081         case(0x40):
00082             //If next byte is last one, NACK, otherwise ACK
00083             if (Data->length <= Buffer->count + 1)
00084                 I2CMODULE->I2CONCLR = 1<<I2C_ASSERT_ACK;
00085             else
00086                 I2CMODULE->I2CONSET = 1<<I2C_ASSERT_ACK;
00087             I2CMODULE->I2CONCLR = 1<<I2C_FLAG;
00088             break;
00089 
00090             //Address + R has been sent, NACK received
00091         case(0x48):
00092             *Data->status=I2CMODULE->I2STAT;
00093             _stop(I2CMODULE);
00094             bufferHandler(I2CMODULE);
00095             break;
00096 
00097             //Data was received, ACK returned
00098         case(0x50):
00099             //Read data
00100             Data->data[Buffer->count]=I2CMODULE->I2DAT;
00101             Buffer->count++;
00102 
00103             //If next byte is last one, NACK, otherwise ACK
00104             if (Data->length == Buffer->count + 1)
00105                 I2CMODULE->I2CONCLR = 1<<I2C_ASSERT_ACK;
00106             else
00107                 I2CMODULE->I2CONSET = 1<<I2C_ASSERT_ACK;
00108 
00109             I2CMODULE->I2CONCLR = 1<<I2C_FLAG;
00110             break;
00111 
00112             //Data was received, NACK returned (last byte)
00113         case(0x58):
00114             //Read data
00115             *Data->status=I2CMODULE->I2STAT;
00116             Data->data[Buffer->count]=I2CMODULE->I2DAT;
00117             if (!Data->repeated)
00118                 _stop(I2CMODULE);
00119             else {
00120                 I2CMODULE->I2CONSET = 1<<I2C_START;
00121                 I2CMODULE->I2CONCLR = 1<<I2C_FLAG;
00122             }
00123             bufferHandler(I2CMODULE);
00124             break;
00125 
00126         default:
00127             *Data->status=I2CMODULE->I2STAT;
00128             bufferHandler(I2CMODULE);
00129             break;
00130     }
00131 }
00132 
00133 
00134 //**********************************************************
00135 //*********************COMMAND BUFFER***********************
00136 //**********************************************************
00137 
00138 void MODI2C::bufferHandler(LPC_I2C_TypeDef *I2CMODULE) {
00139     I2CBuffer *Buffer;
00140     if (I2CMODULE == LPC_I2C1) {
00141         Buffer = &Buffer1;
00142     } else {
00143         Buffer = &Buffer2;
00144     }
00145 
00146     //Start user interrupt
00147     Buffer->Data[0].caller->runUserIRQ(Buffer->Data[0]);
00148 
00149     removeBuffer(I2CMODULE);
00150 
00151 
00152 
00153     if (Buffer->queue!=0)
00154         startBuffer(I2CMODULE);
00155     else
00156         _clearISR(I2CMODULE);
00157 }
00158 
00159 //Returns true if succeeded, false if buffer is full
00160 bool MODI2C::addBuffer(I2CData Data, LPC_I2C_TypeDef *I2CMODULE) {
00161     I2CBuffer *Buffer;
00162     if (I2CMODULE == LPC_I2C1) {
00163         Buffer = &Buffer1;
00164     } else {
00165         Buffer = &Buffer2;
00166     }
00167     if (Buffer->queue<I2C_BUFFER) {
00168         
00169         if(Data.status == NULL) {
00170             Data.status = &defaultStatus;
00171             wait_us(1);     //I blame the compiler that this is needed
00172             }
00173         *Data.status = 0;
00174             
00175         Buffer->Data[Buffer->queue]=Data;
00176         Buffer->queue++;
00177 
00178         //If queue was empty, set I2C settings, start conversion
00179         if (Buffer->queue==1) {
00180             startBuffer(I2CMODULE);
00181         }
00182 
00183         return true;
00184     } else
00185         return false;
00186 
00187 }
00188 
00189 //Returns true if buffer still has data, false if empty
00190 bool MODI2C::removeBuffer(LPC_I2C_TypeDef *I2CMODULE) {
00191     I2CBuffer *Buffer;
00192     if (I2CMODULE == LPC_I2C1) {
00193         Buffer = &Buffer1;
00194     } else {
00195         Buffer= &Buffer2;
00196     }
00197 
00198     if (Buffer->queue>0) {
00199         for (int i =0; i<Buffer->queue-1; i++)
00200             Buffer->Data[i]=Buffer->Data[i+1];
00201         Buffer->queue--;
00202     }
00203     if (Buffer->queue>0)
00204         return true;
00205     else
00206         return false;
00207 }
00208 
00209 //Starts new conversion
00210 void MODI2C::startBuffer(LPC_I2C_TypeDef *I2CMODULE) {
00211     I2CBuffer *Buffer;
00212     if (I2CMODULE == LPC_I2C1) {
00213         Buffer = &Buffer1;
00214     } else {
00215         Buffer = &Buffer2;
00216     }
00217 
00218     //Write settings
00219     Buffer->Data[0].caller->writeSettings();
00220     Buffer->count=0;
00221 
00222     //Send Start
00223     _start(I2CMODULE);
00224 
00225     //Start ISR (when buffer wasnt empty this wont do anything)
00226     _setISR(I2CMODULE);
00227 
00228 }