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

Dependencies:   FPointer

Dependents:   FreeIMU FreeIMU_external_magnetometer FreeIMU

Fork of MODI2C by Erik -

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MODI2C.cpp Source File

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 }