Improvements to Olieman's MODI2C library. Supports calls from IRQ.
Dependents: FreeIMU FreeIMU_external_magnetometer FreeIMU
Fork of MODI2C by
MODI2C.cpp
00001 #include "MODI2C.h" 00002 00003 MODI2C::I2CBuffer MODI2C::Buffer1; 00004 MODI2C::I2CBuffer MODI2C::Buffer2; 00005 00006 //int MODI2C::status=0; 00007 int MODI2C::defaultStatus=0; 00008 00009 00010 00011 00012 MODI2C::MODI2C(PinName sda, PinName scl) : led(LED3){ 00013 //Check which connection we are using, if not correct, go to error status 00014 if ((sda==p9) && (scl==p10)) 00015 I2CMODULE = LPC_I2C1; 00016 else if ((sda==p28) && (scl==p27)) 00017 I2CMODULE = LPC_I2C2; 00018 else 00019 error("MODI2C pins not valid"); 00020 00021 //Default settings: 00022 frequency(400000); 00023 00024 writePinState(); 00025 } 00026 00027 int MODI2C::write(int address, char *data, int length, uint32_t(*function)(uint32_t), void* pass_to_irq, bool repeated, int *status) { 00028 00029 I2CBuffer *Buffer; 00030 if (I2CMODULE == LPC_I2C1) { 00031 Buffer = &Buffer1; 00032 } else { 00033 Buffer = &Buffer2; 00034 } 00035 00036 I2CData *Data = Buffer->pool.calloc(); 00037 if (Data == NULL){ 00038 if (__get_IPSR() != 0) 00039 return -1; //no waiting in ISR 00040 else 00041 while (Data == NULL) Data = Buffer->pool.calloc(); 00042 } 00043 00044 //Store relevant information 00045 address &= 0xFE; 00046 Data->caller = this; 00047 Data->address = address; 00048 Data->repeated = repeated; 00049 Data->data = data; 00050 Data->length = length; 00051 Data->status = status; 00052 Data->pass_to_irq = (uint32_t)pass_to_irq; 00053 Data->monitor_addr = NULL; 00054 00055 if (function!=NULL){ 00056 Data->IRQOp = IRQ_I2C_WRITE; 00057 Data->callback.attach(function); 00058 }else{ 00059 Data->IRQOp = NULL; 00060 } 00061 00062 addBuffer(Data, I2CMODULE); 00063 00064 return 0; 00065 } 00066 00067 int MODI2C::write(int address, char *data, int length, int *status) { 00068 return write(address, data, length, NULL, NULL, false, status); 00069 } 00070 00071 int MODI2C::write(int address, char *data, int length, bool repeated) { 00072 return write(address, data, length, NULL, NULL, repeated); 00073 } 00074 00075 int MODI2C::read_nb(int address, char *data, int length, uint32_t(*function)(uint32_t), void* pass_to_irq, bool repeated, int *status) { 00076 //Store relevant information 00077 address |= 0x01; 00078 00079 I2CBuffer *Buffer; 00080 if (I2CMODULE == LPC_I2C1) { 00081 Buffer = &Buffer1; 00082 } else { 00083 Buffer = &Buffer2; 00084 } 00085 00086 I2CData *Data = Buffer->pool.calloc(); 00087 if (Data == NULL){ 00088 if (__get_IPSR() != 0) 00089 return -1; //no waiting in ISR 00090 else 00091 while (Data == NULL) Data = Buffer->pool.calloc(); 00092 } 00093 00094 Data->caller = this; 00095 Data->address = address; 00096 Data->repeated = repeated; 00097 Data->data = data; 00098 Data->length = length; 00099 Data->status = status; 00100 Data->IRQOp = IRQ_I2C_READ; 00101 Data->pass_to_irq = (uint32_t)pass_to_irq; 00102 Data->callback.attach(function); 00103 Data->monitor_addr = NULL; 00104 00105 addBuffer(Data, I2CMODULE); 00106 00107 return 0; 00108 } 00109 00110 int MODI2C::read(int address, char *data, int length, bool repeated) { 00111 int stat; 00112 //Store relevant information 00113 address |= 0x01; 00114 00115 I2CBuffer *Buffer; 00116 if (I2CMODULE == LPC_I2C1) { 00117 Buffer = &Buffer1; 00118 } else { 00119 Buffer = &Buffer2; 00120 } 00121 00122 I2CData *Data = Buffer->pool.calloc(); 00123 if (Data == NULL){ 00124 if (__get_IPSR() != 0) 00125 return -1; //no waiting in ISR 00126 else 00127 while (Data == NULL) Data = Buffer->pool.calloc(); 00128 } 00129 00130 Data->caller = this; 00131 Data->address = address; 00132 Data->repeated = repeated; 00133 Data->data = data; 00134 Data->length = length; 00135 Data->status = &stat; 00136 Data->IRQOp = NULL; 00137 00138 volatile char monitor = 1; 00139 Data->monitor_addr = &monitor; 00140 00141 addBuffer(Data, I2CMODULE); 00142 00143 while(monitor!=0) wait_us(1); 00144 00145 if (stat==0x58) //Return zero if ended correctly, otherwise return return code. 00146 return 0; 00147 else 00148 return stat; 00149 } 00150 00151 00152 void MODI2C::start( void ) { 00153 _start(I2CMODULE); 00154 } 00155 00156 void MODI2C::stop( void ) { 00157 _stop(I2CMODULE); 00158 } 00159 00160 void MODI2C::frequency(int hz) { 00161 //The I2C clock by default runs on quarter of system clock, which is 96MHz 00162 //So to calculate high/low count times, we do 96MHz/4/2/frequency 00163 duty = SystemCoreClock/8/hz; 00164 if (duty>65535) 00165 duty=65535; 00166 if (duty<4) 00167 duty=4; 00168 } 00169 00170 //******************************************* 00171 //***********Internal functions************** 00172 //******************************************* 00173 00174 00175 void MODI2C::writeSettings( void ) { 00176 I2CMODULE->I2CONSET = 1<<I2C_ENABLE; //Enable I2C 00177 I2CMODULE->I2CONCLR = I2C_STOP; 00178 I2CMODULE->MMCTRL = 0; //Disable monitor mode 00179 I2CMODULE->I2SCLH = duty; 00180 I2CMODULE->I2SCLL = duty; 00181 00182 } 00183 00184 void MODI2C::writePinState( void ) { 00185 if (I2CMODULE == LPC_I2C1) { 00186 LPC_PINCON->PINSEL0 |= 0x0000000F; //Sets pins as I2C 00187 LPC_PINCON->PINMODE0 |= 0x0000000A; //Neither pull up nor pull down 00188 LPC_PINCON->PINMODE_OD0 |= 0x00000003; //Open drain mode enabled 00189 } else if (I2CMODULE == LPC_I2C2) { 00190 LPC_PINCON->PINSEL0 |= (1<<21)|(1<<23); //Same story, different register settings 00191 LPC_PINCON->PINMODE0 |= (1<<21)|(1<<23); 00192 LPC_PINCON->PINMODE_OD0 |= (1<<10)|(1<<11); 00193 } 00194 } 00195 00196 void MODI2C::_start(LPC_I2C_TypeDef *I2CMODULE) { 00197 if (!(I2CMODULE->I2CONSET & 1<<I2C_START)) //If already sent, skip 00198 I2CMODULE->I2CONSET = 1<<I2C_START; //Send start condition 00199 } 00200 00201 void MODI2C::_stop(LPC_I2C_TypeDef *I2CMODULE) { 00202 I2CMODULE->I2CONSET = 1<<I2C_STOP; //Send stop condition 00203 I2CMODULE->I2CONCLR = 1<<I2C_FLAG; 00204 } 00205 00206 //Set interrupt vector 00207 void MODI2C::setISR(void) { 00208 _setISR(I2CMODULE); 00209 } 00210 00211 void MODI2C::_setISR(LPC_I2C_TypeDef *I2CMODULE) { 00212 if (I2CMODULE == LPC_I2C1) { 00213 NVIC_SetVector(I2C1_IRQn, (uint32_t)&IRQ1Handler); 00214 NVIC_EnableIRQ(I2C1_IRQn); 00215 } else if (I2CMODULE == LPC_I2C2) { 00216 NVIC_SetVector(I2C2_IRQn, (uint32_t)&IRQ2Handler); 00217 NVIC_EnableIRQ(I2C2_IRQn); 00218 } 00219 } 00220 00221 void MODI2C::clearISR( void ) { 00222 _clearISR(I2CMODULE); 00223 } 00224 00225 void MODI2C::_clearISR( LPC_I2C_TypeDef *I2CMODULE ) { 00226 if (I2CMODULE == LPC_I2C1) { 00227 NVIC_DisableIRQ(I2C1_IRQn); 00228 } else if (I2CMODULE == LPC_I2C2) { 00229 NVIC_DisableIRQ(I2C2_IRQn); 00230 } 00231 }
Generated on Tue Jul 12 2022 16:58:30 by
