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:
5:fa0cca8e28b6
--- a/MODI2C_IRQ.cpp	Sat Jun 30 14:55:14 2012 +0000
+++ b/MODI2C_IRQ.cpp	Sat Nov 09 08:59:02 2013 +0000
@@ -4,15 +4,16 @@
 //*********************IRQ FUNCTIONS************************
 //**********************************************************
 
-
-void MODI2C::runUserIRQ(I2CData Data) {
+void MODI2C::runUserIRQ(I2CData *Data) {
      
-    if (IRQOp==IRQ_I2C_BOTH)        //Always call if both
-        callback.call();
-    if ((IRQOp==IRQ_I2C_READ)&&(Data.address&0x01)) //Call if read and byte was read
-        callback.call();
-    if ((IRQOp==IRQ_I2C_WRITE)&&(!(Data.address&0x01))) //Call if write and byte was written
-        callback.call();
+    if (Data->IRQOp==IRQ_I2C_BOTH)        //Always call if both
+        Data->callback.call(Data->pass_to_irq);
+    if ((Data->IRQOp==IRQ_I2C_READ)&&(Data->address&0x01)) //Call if read and byte was read
+        Data->callback.call(Data->pass_to_irq);
+    if ((Data->IRQOp==IRQ_I2C_WRITE)&&(!(Data->address&0x01))) //Call if write and byte was written
+        Data->callback.call(Data->pass_to_irq);
+        
+    if (Data->monitor_addr!=NULL) *(Data->monitor_addr)=0;
 }
 
 void MODI2C::IRQ1Handler( void ) {
@@ -24,7 +25,7 @@
 }
 
 void MODI2C::IRQHandler( I2CBuffer *Buffer, LPC_I2C_TypeDef *I2CMODULE) {
-    I2CData *Data = &Buffer->Data[0];
+    I2CData *Data = (I2CData*)Buffer->curr;
 
     //Depending on the status register it determines next action, see datasheet
     //This is also pretty much copy pasting the datasheet
@@ -144,66 +145,70 @@
     }
 
     //Start user interrupt
-    Buffer->Data[0].caller->runUserIRQ(Buffer->Data[0]);
-
-    removeBuffer(I2CMODULE);
-
-
-
-    if (Buffer->queue!=0)
+    Buffer->curr->caller->runUserIRQ((I2CData*)Buffer->curr);
+    
+    Buffer->pool.free((I2CData*)Buffer->curr);
+    
+    if (Buffer->crit_flag) return;
+    
+    osEvent evt = Buffer->queue.get(0);
+    if (evt.status == osEventMessage){
+        Buffer->curr = (I2CData*)evt.value.p;
         startBuffer(I2CMODULE);
-    else
+    }
+    else{
+        Buffer->curr = NULL;
         _clearISR(I2CMODULE);
+    }
 }
 
 //Returns true if succeeded, false if buffer is full
-bool MODI2C::addBuffer(I2CData Data, LPC_I2C_TypeDef *I2CMODULE) {
+bool MODI2C::addBuffer(I2CData *Data, LPC_I2C_TypeDef *I2CMODULE) {
+
+    int interrupt = __get_IPSR();
+
     I2CBuffer *Buffer;
     if (I2CMODULE == LPC_I2C1) {
         Buffer = &Buffer1;
     } else {
         Buffer = &Buffer2;
     }
-    if (Buffer->queue<I2C_BUFFER) {
-        
-        if(Data.status == NULL) {
-            Data.status = &defaultStatus;
-            wait_us(1);     //I blame the compiler that this is needed
-            }
-        *Data.status = 0;
-            
-        Buffer->Data[Buffer->queue]=Data;
-        Buffer->queue++;
-
-        //If queue was empty, set I2C settings, start conversion
-        if (Buffer->queue==1) {
+    
+    if(Data->status == NULL) {
+        Data->status = &defaultStatus;
+        wait_us(1);     //I blame the compiler that this is needed
+    }
+    *(Data->status) = 0;
+    
+    if (Buffer->queue.put(Data, 0)!=osOK){
+        if (interrupt!=0)
+            return false;   //no waiting in ISR
+        else
+            while (Buffer->queue.put(Data, 0)!=osOK);
+    }
+    
+    if (interrupt!=0){
+        if (Buffer->crit_flag_isr) return true;
+    }else Buffer->crit_flag_isr = true;
+    
+    if (Buffer->curr == NULL){
+        if (interrupt==0) Buffer->crit_flag = true;
+        osEvent evt = Buffer->queue.get(0);
+        if (evt.status == osEventMessage){
+            Buffer->curr = (volatile I2CData*)(evt.value.p);
+            if (interrupt==0) Buffer->crit_flag_isr = false;
+            if (interrupt==0) Buffer->crit_flag = false;
             startBuffer(I2CMODULE);
+        }else{
+            if (interrupt==0) Buffer->crit_flag_isr = false;
+            if (interrupt==0) Buffer->crit_flag = false;
         }
-
-        return true;
-    } else
-        return false;
-
-}
-
-//Returns true if buffer still has data, false if empty
-bool MODI2C::removeBuffer(LPC_I2C_TypeDef *I2CMODULE) {
-    I2CBuffer *Buffer;
-    if (I2CMODULE == LPC_I2C1) {
-        Buffer = &Buffer1;
-    } else {
-        Buffer= &Buffer2;
+    }else{
+        if (interrupt==0) Buffer->crit_flag_isr = false;
     }
-
-    if (Buffer->queue>0) {
-        for (int i =0; i<Buffer->queue-1; i++)
-            Buffer->Data[i]=Buffer->Data[i+1];
-        Buffer->queue--;
-    }
-    if (Buffer->queue>0)
-        return true;
-    else
-        return false;
+    
+    
+    return true;
 }
 
 //Starts new conversion
@@ -216,7 +221,7 @@
     }
 
     //Write settings
-    Buffer->Data[0].caller->writeSettings();
+    Buffer->curr->caller->writeSettings();
     Buffer->count=0;
 
     //Send Start