Improvements to Olieman's MODI2C library. Supports calls from IRQ.
Dependents: FreeIMU FreeIMU_external_magnetometer FreeIMU
Fork of MODI2C by
Diff: MODI2C.cpp
- 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