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

Dependencies:   FPointer

Dependents:   FreeIMU FreeIMU_external_magnetometer FreeIMU

Fork of MODI2C by Erik -

Revision:
1:eed116eb680a
Parent:
0:ff579e7e8efa
Child:
2:22f93d992c83
--- a/MODI2C.cpp	Sat Jun 30 14:55:14 2012 +0000
+++ b/MODI2C.cpp	Sat Nov 09 08:59:02 2013 +0000
@@ -1,14 +1,15 @@
 #include "MODI2C.h"
 
-MODI2C::I2CBuffer MODI2C::Buffer1 = {0,0};        //Sets the initial buffer empty and count on zero
-MODI2C::I2CBuffer MODI2C::Buffer2 = {0,0};        //Sets the initial buffer empty
+MODI2C::I2CBuffer MODI2C::Buffer1;
+MODI2C::I2CBuffer MODI2C::Buffer2;
+
 //int MODI2C::status=0;
 int MODI2C::defaultStatus=0;
 
 
 
 
-MODI2C::MODI2C(PinName sda, PinName scl) : led(LED3) {
+MODI2C::MODI2C(PinName sda, PinName scl) : led(LED3){
     //Check which connection we are using, if not correct, go to error status
     if ((sda==p9) && (scl==p10))
         I2CMODULE = LPC_I2C1;
@@ -18,74 +19,13 @@
         error("MODI2C pins not valid");
 
     //Default settings:
-    frequency(100000);
+    frequency(400000);
 
     writePinState();
 }
 
-int MODI2C::write(int address, char *data, int length, bool repeated, int *status) {
-
-    I2CData Data;
-    //Store relevant information
-    address &= 0xFE;
-    Data.caller = this;
-    Data.address = address;
-    Data.repeated = repeated;
-    Data.data = data;
-    Data.length = length;
-    Data.status = status;
-
-    while(!addBuffer(Data, I2CMODULE));
-
-    return 0;
-}
-
-int MODI2C::write(int address, char *data, int length, int *status) {
-    return write(address, data, length, false, status);
-    }
-
-int MODI2C::read_nb(int address, char *data, int length, bool repeated, int *status) {
-    //Store relevant information
-    address |= 0x01;
-
-    //isIdle check here
-    I2CData Data;
-
+int MODI2C::write(int address, char *data, int length, uint32_t(*function)(uint32_t), void* pass_to_irq, bool repeated, int *status) {
 
-    Data.caller = this;
-    Data.address = address;
-    Data.repeated = repeated;
-    Data.data = data;
-    Data.length = length;
-    Data.status = status;
-
-    while(!addBuffer(Data, I2CMODULE));
-
-    return 0;
-}
-
-int MODI2C::read_nb(int address, char *data, int length, int *status) {
-    return read_nb(address, data, length, false, status);
-    }
-
-int MODI2C::read(int address, char *data, int length, bool repeated) {
-    int stat;
-    //Store relevant information
-    address |= 0x01;
-
-    //isIdle check here
-    I2CData Data;
-
-
-    Data.caller = this;
-    Data.address = address;
-    Data.repeated = repeated;
-    Data.data = data;
-    Data.length = length;
-    Data.status = &stat;
-
-    while(!addBuffer(Data, I2CMODULE));
-    
     I2CBuffer *Buffer;
     if (I2CMODULE == LPC_I2C1) {
         Buffer = &Buffer1;
@@ -93,8 +33,114 @@
         Buffer = &Buffer2;
     }
     
-    while(Buffer->queue!=0)
-        wait_us(1);
+    I2CData *Data = Buffer->pool.calloc();
+    if (Data == NULL){
+        if (__get_IPSR() != 0) 
+            return -1;   //no waiting in ISR
+        else
+            while (Data == NULL) Data = Buffer->pool.calloc();
+    }
+
+    //Store relevant information
+    address &= 0xFE;
+    Data->caller = this;
+    Data->address = address;
+    Data->repeated = repeated;
+    Data->data = data;
+    Data->length = length;
+    Data->status = status;
+    Data->pass_to_irq = (uint32_t)pass_to_irq;
+    Data->monitor_addr = NULL;
+    
+    if (function!=NULL){
+        Data->IRQOp = IRQ_I2C_WRITE;
+        Data->callback.attach(function);
+    }else{
+        Data->IRQOp = NULL;
+    }
+
+    addBuffer(Data, I2CMODULE);
+
+    return 0;
+}
+
+int MODI2C::write(int address, char *data, int length, int *status) {
+    return write(address, data, length, NULL, NULL, false, status);
+}
+
+int MODI2C::write(int address, char *data, int length, bool repeated) {
+    return write(address, data, length, NULL, NULL, repeated);
+}
+
+int MODI2C::read_nb(int address, char *data, int length, uint32_t(*function)(uint32_t), void* pass_to_irq, bool repeated, int *status) {
+    //Store relevant information
+    address |= 0x01;
+
+    I2CBuffer *Buffer;
+    if (I2CMODULE == LPC_I2C1) {
+        Buffer = &Buffer1;
+    } else {
+        Buffer = &Buffer2;
+    }
+    
+    I2CData *Data = Buffer->pool.calloc();
+    if (Data == NULL){
+        if (__get_IPSR() != 0) 
+            return -1;   //no waiting in ISR
+        else
+            while (Data == NULL) Data = Buffer->pool.calloc();
+    }
+
+    Data->caller = this;
+    Data->address = address;
+    Data->repeated = repeated;
+    Data->data = data;
+    Data->length = length;
+    Data->status = status;
+    Data->IRQOp = IRQ_I2C_READ;
+    Data->pass_to_irq = (uint32_t)pass_to_irq;
+    Data->callback.attach(function);
+    Data->monitor_addr = NULL;
+
+    addBuffer(Data, I2CMODULE);
+
+    return 0;
+}
+
+int MODI2C::read(int address, char *data, int length, bool repeated) {
+    int stat;
+    //Store relevant information
+    address |= 0x01;
+
+    I2CBuffer *Buffer;
+    if (I2CMODULE == LPC_I2C1) {
+        Buffer = &Buffer1;
+    } else {
+        Buffer = &Buffer2;
+    }
+    
+    I2CData *Data = Buffer->pool.calloc();
+    if (Data == NULL){
+        if (__get_IPSR() != 0) 
+            return -1;   //no waiting in ISR
+        else
+            while (Data == NULL) Data = Buffer->pool.calloc();
+    }
+
+    Data->caller = this;
+    Data->address = address;
+    Data->repeated = repeated;
+    Data->data = data;
+    Data->length = length;
+    Data->status = &stat;
+    Data->IRQOp = NULL;
+    
+    volatile char monitor = 1;
+    Data->monitor_addr = &monitor;
+
+    addBuffer(Data, I2CMODULE);
+    
+    while(monitor!=0) wait_us(1);
     
     if (stat==0x58)         //Return zero if ended correctly, otherwise return return code.
         return 0;
@@ -114,25 +160,13 @@
 void MODI2C::frequency(int hz) {
     //The I2C clock by default runs on quarter of system clock, which is 96MHz
     //So to calculate high/low count times, we do 96MHz/4/2/frequency
-    duty = 96000000/8/hz;
+    duty = 120000000/8/hz;
     if (duty>65535)
         duty=65535;
     if (duty<4)
         duty=4;
 }
 
-int MODI2C::getQueue( void ) {
-    I2CBuffer *Buffer;
-    if (I2CMODULE == LPC_I2C1) {
-        Buffer = &Buffer1;
-    } else {
-        Buffer = &Buffer2;
-    }
-    return Buffer->queue;
-    }
-
-
-
 //*******************************************
 //***********Internal functions**************
 //*******************************************
@@ -159,23 +193,6 @@
     }
 }
 
-
-
-void MODI2C::attach( void (*function)(void), int operation) {
-    IRQOp = operation;
-    callback.attach(function);
-}
-
-template<typename T>
-void MODI2C::attach(T *object, void (T::*member)(void), int operation) {
-    IRQOp = operation;
-    callback.attach(object, member);
-}
-
-void MODI2C::detach( void ) {
-    callback.attach(NULL);
-}
-
 void MODI2C::_start(LPC_I2C_TypeDef *I2CMODULE) {
     if (!(I2CMODULE->I2CONSET & 1<<I2C_START))  //If already sent, skip
         I2CMODULE->I2CONSET = 1<<I2C_START;     //Send start condition