Improvements to Olieman's MODI2C library. Supports calls from IRQ.

Dependencies:   FPointer

Dependents:   FreeIMU FreeIMU_external_magnetometer FreeIMU

Fork of MODI2C by Erik -

Committer:
Sissors
Date:
Sat Jun 30 14:55:14 2012 +0000
Revision:
0:ff579e7e8efa
Child:
1:eed116eb680a
v1.0

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Sissors 0:ff579e7e8efa 1 #include "MODI2C.h"
Sissors 0:ff579e7e8efa 2
Sissors 0:ff579e7e8efa 3 //**********************************************************
Sissors 0:ff579e7e8efa 4 //*********************IRQ FUNCTIONS************************
Sissors 0:ff579e7e8efa 5 //**********************************************************
Sissors 0:ff579e7e8efa 6
Sissors 0:ff579e7e8efa 7
Sissors 0:ff579e7e8efa 8 void MODI2C::runUserIRQ(I2CData Data) {
Sissors 0:ff579e7e8efa 9
Sissors 0:ff579e7e8efa 10 if (IRQOp==IRQ_I2C_BOTH) //Always call if both
Sissors 0:ff579e7e8efa 11 callback.call();
Sissors 0:ff579e7e8efa 12 if ((IRQOp==IRQ_I2C_READ)&&(Data.address&0x01)) //Call if read and byte was read
Sissors 0:ff579e7e8efa 13 callback.call();
Sissors 0:ff579e7e8efa 14 if ((IRQOp==IRQ_I2C_WRITE)&&(!(Data.address&0x01))) //Call if write and byte was written
Sissors 0:ff579e7e8efa 15 callback.call();
Sissors 0:ff579e7e8efa 16 }
Sissors 0:ff579e7e8efa 17
Sissors 0:ff579e7e8efa 18 void MODI2C::IRQ1Handler( void ) {
Sissors 0:ff579e7e8efa 19 IRQHandler(&Buffer1, LPC_I2C1);
Sissors 0:ff579e7e8efa 20 }
Sissors 0:ff579e7e8efa 21
Sissors 0:ff579e7e8efa 22 void MODI2C::IRQ2Handler( void ) {
Sissors 0:ff579e7e8efa 23 IRQHandler(&Buffer2, LPC_I2C2);
Sissors 0:ff579e7e8efa 24 }
Sissors 0:ff579e7e8efa 25
Sissors 0:ff579e7e8efa 26 void MODI2C::IRQHandler( I2CBuffer *Buffer, LPC_I2C_TypeDef *I2CMODULE) {
Sissors 0:ff579e7e8efa 27 I2CData *Data = &Buffer->Data[0];
Sissors 0:ff579e7e8efa 28
Sissors 0:ff579e7e8efa 29 //Depending on the status register it determines next action, see datasheet
Sissors 0:ff579e7e8efa 30 //This is also pretty much copy pasting the datasheet
Sissors 0:ff579e7e8efa 31 //General options
Sissors 0:ff579e7e8efa 32 switch (I2CMODULE->I2STAT) {
Sissors 0:ff579e7e8efa 33 case(0x08):
Sissors 0:ff579e7e8efa 34 case(0x10):
Sissors 0:ff579e7e8efa 35 //Send Address
Sissors 0:ff579e7e8efa 36 I2CMODULE->I2DAT = Data->address;
Sissors 0:ff579e7e8efa 37 I2CMODULE->I2CONCLR = 1<<I2C_FLAG | 1<<I2C_START;
Sissors 0:ff579e7e8efa 38 break;
Sissors 0:ff579e7e8efa 39
Sissors 0:ff579e7e8efa 40 //All master TX options
Sissors 0:ff579e7e8efa 41
Sissors 0:ff579e7e8efa 42 //Address + W has been sent, ACK received
Sissors 0:ff579e7e8efa 43 //Data has been sent, ACK received
Sissors 0:ff579e7e8efa 44 case(0x18):
Sissors 0:ff579e7e8efa 45 case(0x28):
Sissors 0:ff579e7e8efa 46 if (Buffer->count==Data->length) {
Sissors 0:ff579e7e8efa 47 *Data->status=I2CMODULE->I2STAT;
Sissors 0:ff579e7e8efa 48 if (!Data->repeated)
Sissors 0:ff579e7e8efa 49 _stop(I2CMODULE);
Sissors 0:ff579e7e8efa 50 else {
Sissors 0:ff579e7e8efa 51 I2CMODULE->I2CONSET = 1<<I2C_START;
Sissors 0:ff579e7e8efa 52 I2CMODULE->I2CONCLR = 1<<I2C_FLAG;
Sissors 0:ff579e7e8efa 53 }
Sissors 0:ff579e7e8efa 54 bufferHandler(I2CMODULE);
Sissors 0:ff579e7e8efa 55 } else {
Sissors 0:ff579e7e8efa 56 I2CMODULE->I2DAT = Data->data[Buffer->count];
Sissors 0:ff579e7e8efa 57 I2CMODULE->I2CONSET = 1<<I2C_ASSERT_ACK; //I dont see why I have to enable that bit, but datasheet says so
Sissors 0:ff579e7e8efa 58 I2CMODULE->I2CONCLR = 1<<I2C_FLAG;
Sissors 0:ff579e7e8efa 59 Buffer->count++;
Sissors 0:ff579e7e8efa 60 }
Sissors 0:ff579e7e8efa 61 break;
Sissors 0:ff579e7e8efa 62
Sissors 0:ff579e7e8efa 63 //Address + W has been sent, NACK received
Sissors 0:ff579e7e8efa 64 //Data has been sent, NACK received
Sissors 0:ff579e7e8efa 65 case(0x20):
Sissors 0:ff579e7e8efa 66 case(0x30):
Sissors 0:ff579e7e8efa 67 *Data->status=I2CMODULE->I2STAT;
Sissors 0:ff579e7e8efa 68 _stop(I2CMODULE);
Sissors 0:ff579e7e8efa 69 bufferHandler(I2CMODULE);
Sissors 0:ff579e7e8efa 70 break;
Sissors 0:ff579e7e8efa 71
Sissors 0:ff579e7e8efa 72 //Arbitration lost (situation looks pretty hopeless to me if you arrive here)
Sissors 0:ff579e7e8efa 73 case(0x38):
Sissors 0:ff579e7e8efa 74 _start(I2CMODULE);
Sissors 0:ff579e7e8efa 75 break;
Sissors 0:ff579e7e8efa 76
Sissors 0:ff579e7e8efa 77
Sissors 0:ff579e7e8efa 78 //All master RX options
Sissors 0:ff579e7e8efa 79
Sissors 0:ff579e7e8efa 80 //Address + R has been sent, ACK received
Sissors 0:ff579e7e8efa 81 case(0x40):
Sissors 0:ff579e7e8efa 82 //If next byte is last one, NACK, otherwise ACK
Sissors 0:ff579e7e8efa 83 if (Data->length <= Buffer->count + 1)
Sissors 0:ff579e7e8efa 84 I2CMODULE->I2CONCLR = 1<<I2C_ASSERT_ACK;
Sissors 0:ff579e7e8efa 85 else
Sissors 0:ff579e7e8efa 86 I2CMODULE->I2CONSET = 1<<I2C_ASSERT_ACK;
Sissors 0:ff579e7e8efa 87 I2CMODULE->I2CONCLR = 1<<I2C_FLAG;
Sissors 0:ff579e7e8efa 88 break;
Sissors 0:ff579e7e8efa 89
Sissors 0:ff579e7e8efa 90 //Address + R has been sent, NACK received
Sissors 0:ff579e7e8efa 91 case(0x48):
Sissors 0:ff579e7e8efa 92 *Data->status=I2CMODULE->I2STAT;
Sissors 0:ff579e7e8efa 93 _stop(I2CMODULE);
Sissors 0:ff579e7e8efa 94 bufferHandler(I2CMODULE);
Sissors 0:ff579e7e8efa 95 break;
Sissors 0:ff579e7e8efa 96
Sissors 0:ff579e7e8efa 97 //Data was received, ACK returned
Sissors 0:ff579e7e8efa 98 case(0x50):
Sissors 0:ff579e7e8efa 99 //Read data
Sissors 0:ff579e7e8efa 100 Data->data[Buffer->count]=I2CMODULE->I2DAT;
Sissors 0:ff579e7e8efa 101 Buffer->count++;
Sissors 0:ff579e7e8efa 102
Sissors 0:ff579e7e8efa 103 //If next byte is last one, NACK, otherwise ACK
Sissors 0:ff579e7e8efa 104 if (Data->length == Buffer->count + 1)
Sissors 0:ff579e7e8efa 105 I2CMODULE->I2CONCLR = 1<<I2C_ASSERT_ACK;
Sissors 0:ff579e7e8efa 106 else
Sissors 0:ff579e7e8efa 107 I2CMODULE->I2CONSET = 1<<I2C_ASSERT_ACK;
Sissors 0:ff579e7e8efa 108
Sissors 0:ff579e7e8efa 109 I2CMODULE->I2CONCLR = 1<<I2C_FLAG;
Sissors 0:ff579e7e8efa 110 break;
Sissors 0:ff579e7e8efa 111
Sissors 0:ff579e7e8efa 112 //Data was received, NACK returned (last byte)
Sissors 0:ff579e7e8efa 113 case(0x58):
Sissors 0:ff579e7e8efa 114 //Read data
Sissors 0:ff579e7e8efa 115 *Data->status=I2CMODULE->I2STAT;
Sissors 0:ff579e7e8efa 116 Data->data[Buffer->count]=I2CMODULE->I2DAT;
Sissors 0:ff579e7e8efa 117 if (!Data->repeated)
Sissors 0:ff579e7e8efa 118 _stop(I2CMODULE);
Sissors 0:ff579e7e8efa 119 else {
Sissors 0:ff579e7e8efa 120 I2CMODULE->I2CONSET = 1<<I2C_START;
Sissors 0:ff579e7e8efa 121 I2CMODULE->I2CONCLR = 1<<I2C_FLAG;
Sissors 0:ff579e7e8efa 122 }
Sissors 0:ff579e7e8efa 123 bufferHandler(I2CMODULE);
Sissors 0:ff579e7e8efa 124 break;
Sissors 0:ff579e7e8efa 125
Sissors 0:ff579e7e8efa 126 default:
Sissors 0:ff579e7e8efa 127 *Data->status=I2CMODULE->I2STAT;
Sissors 0:ff579e7e8efa 128 bufferHandler(I2CMODULE);
Sissors 0:ff579e7e8efa 129 break;
Sissors 0:ff579e7e8efa 130 }
Sissors 0:ff579e7e8efa 131 }
Sissors 0:ff579e7e8efa 132
Sissors 0:ff579e7e8efa 133
Sissors 0:ff579e7e8efa 134 //**********************************************************
Sissors 0:ff579e7e8efa 135 //*********************COMMAND BUFFER***********************
Sissors 0:ff579e7e8efa 136 //**********************************************************
Sissors 0:ff579e7e8efa 137
Sissors 0:ff579e7e8efa 138 void MODI2C::bufferHandler(LPC_I2C_TypeDef *I2CMODULE) {
Sissors 0:ff579e7e8efa 139 I2CBuffer *Buffer;
Sissors 0:ff579e7e8efa 140 if (I2CMODULE == LPC_I2C1) {
Sissors 0:ff579e7e8efa 141 Buffer = &Buffer1;
Sissors 0:ff579e7e8efa 142 } else {
Sissors 0:ff579e7e8efa 143 Buffer = &Buffer2;
Sissors 0:ff579e7e8efa 144 }
Sissors 0:ff579e7e8efa 145
Sissors 0:ff579e7e8efa 146 //Start user interrupt
Sissors 0:ff579e7e8efa 147 Buffer->Data[0].caller->runUserIRQ(Buffer->Data[0]);
Sissors 0:ff579e7e8efa 148
Sissors 0:ff579e7e8efa 149 removeBuffer(I2CMODULE);
Sissors 0:ff579e7e8efa 150
Sissors 0:ff579e7e8efa 151
Sissors 0:ff579e7e8efa 152
Sissors 0:ff579e7e8efa 153 if (Buffer->queue!=0)
Sissors 0:ff579e7e8efa 154 startBuffer(I2CMODULE);
Sissors 0:ff579e7e8efa 155 else
Sissors 0:ff579e7e8efa 156 _clearISR(I2CMODULE);
Sissors 0:ff579e7e8efa 157 }
Sissors 0:ff579e7e8efa 158
Sissors 0:ff579e7e8efa 159 //Returns true if succeeded, false if buffer is full
Sissors 0:ff579e7e8efa 160 bool MODI2C::addBuffer(I2CData Data, LPC_I2C_TypeDef *I2CMODULE) {
Sissors 0:ff579e7e8efa 161 I2CBuffer *Buffer;
Sissors 0:ff579e7e8efa 162 if (I2CMODULE == LPC_I2C1) {
Sissors 0:ff579e7e8efa 163 Buffer = &Buffer1;
Sissors 0:ff579e7e8efa 164 } else {
Sissors 0:ff579e7e8efa 165 Buffer = &Buffer2;
Sissors 0:ff579e7e8efa 166 }
Sissors 0:ff579e7e8efa 167 if (Buffer->queue<I2C_BUFFER) {
Sissors 0:ff579e7e8efa 168
Sissors 0:ff579e7e8efa 169 if(Data.status == NULL) {
Sissors 0:ff579e7e8efa 170 Data.status = &defaultStatus;
Sissors 0:ff579e7e8efa 171 wait_us(1); //I blame the compiler that this is needed
Sissors 0:ff579e7e8efa 172 }
Sissors 0:ff579e7e8efa 173 *Data.status = 0;
Sissors 0:ff579e7e8efa 174
Sissors 0:ff579e7e8efa 175 Buffer->Data[Buffer->queue]=Data;
Sissors 0:ff579e7e8efa 176 Buffer->queue++;
Sissors 0:ff579e7e8efa 177
Sissors 0:ff579e7e8efa 178 //If queue was empty, set I2C settings, start conversion
Sissors 0:ff579e7e8efa 179 if (Buffer->queue==1) {
Sissors 0:ff579e7e8efa 180 startBuffer(I2CMODULE);
Sissors 0:ff579e7e8efa 181 }
Sissors 0:ff579e7e8efa 182
Sissors 0:ff579e7e8efa 183 return true;
Sissors 0:ff579e7e8efa 184 } else
Sissors 0:ff579e7e8efa 185 return false;
Sissors 0:ff579e7e8efa 186
Sissors 0:ff579e7e8efa 187 }
Sissors 0:ff579e7e8efa 188
Sissors 0:ff579e7e8efa 189 //Returns true if buffer still has data, false if empty
Sissors 0:ff579e7e8efa 190 bool MODI2C::removeBuffer(LPC_I2C_TypeDef *I2CMODULE) {
Sissors 0:ff579e7e8efa 191 I2CBuffer *Buffer;
Sissors 0:ff579e7e8efa 192 if (I2CMODULE == LPC_I2C1) {
Sissors 0:ff579e7e8efa 193 Buffer = &Buffer1;
Sissors 0:ff579e7e8efa 194 } else {
Sissors 0:ff579e7e8efa 195 Buffer= &Buffer2;
Sissors 0:ff579e7e8efa 196 }
Sissors 0:ff579e7e8efa 197
Sissors 0:ff579e7e8efa 198 if (Buffer->queue>0) {
Sissors 0:ff579e7e8efa 199 for (int i =0; i<Buffer->queue-1; i++)
Sissors 0:ff579e7e8efa 200 Buffer->Data[i]=Buffer->Data[i+1];
Sissors 0:ff579e7e8efa 201 Buffer->queue--;
Sissors 0:ff579e7e8efa 202 }
Sissors 0:ff579e7e8efa 203 if (Buffer->queue>0)
Sissors 0:ff579e7e8efa 204 return true;
Sissors 0:ff579e7e8efa 205 else
Sissors 0:ff579e7e8efa 206 return false;
Sissors 0:ff579e7e8efa 207 }
Sissors 0:ff579e7e8efa 208
Sissors 0:ff579e7e8efa 209 //Starts new conversion
Sissors 0:ff579e7e8efa 210 void MODI2C::startBuffer(LPC_I2C_TypeDef *I2CMODULE) {
Sissors 0:ff579e7e8efa 211 I2CBuffer *Buffer;
Sissors 0:ff579e7e8efa 212 if (I2CMODULE == LPC_I2C1) {
Sissors 0:ff579e7e8efa 213 Buffer = &Buffer1;
Sissors 0:ff579e7e8efa 214 } else {
Sissors 0:ff579e7e8efa 215 Buffer = &Buffer2;
Sissors 0:ff579e7e8efa 216 }
Sissors 0:ff579e7e8efa 217
Sissors 0:ff579e7e8efa 218 //Write settings
Sissors 0:ff579e7e8efa 219 Buffer->Data[0].caller->writeSettings();
Sissors 0:ff579e7e8efa 220 Buffer->count=0;
Sissors 0:ff579e7e8efa 221
Sissors 0:ff579e7e8efa 222 //Send Start
Sissors 0:ff579e7e8efa 223 _start(I2CMODULE);
Sissors 0:ff579e7e8efa 224
Sissors 0:ff579e7e8efa 225 //Start ISR (when buffer wasnt empty this wont do anything)
Sissors 0:ff579e7e8efa 226 _setISR(I2CMODULE);
Sissors 0:ff579e7e8efa 227
Sissors 0:ff579e7e8efa 228 }