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
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 }
Generated on Sat Jul 16 2022 11:45:43 by 1.7.2