Improvements to Olieman's MODI2C library. Supports calls from IRQ.
Dependents: FreeIMU FreeIMU_external_magnetometer FreeIMU
Fork of MODI2C by
MODI2C.cpp
- Committer:
- Sissors
- Date:
- 2012-06-30
- Revision:
- 0:ff579e7e8efa
- Child:
- 1:eed116eb680a
File content as of revision 0:ff579e7e8efa:
#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 //int MODI2C::status=0; int MODI2C::defaultStatus=0; 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; else if ((sda==p28) && (scl==p27)) I2CMODULE = LPC_I2C2; else error("MODI2C pins not valid"); //Default settings: frequency(100000); 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; 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; } else { Buffer = &Buffer2; } while(Buffer->queue!=0) wait_us(1); if (stat==0x58) //Return zero if ended correctly, otherwise return return code. return 0; else return stat; } void MODI2C::start( void ) { _start(I2CMODULE); } void MODI2C::stop( void ) { _stop(I2CMODULE); } 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; 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************** //******************************************* void MODI2C::writeSettings( void ) { I2CMODULE->I2CONSET = 1<<I2C_ENABLE; //Enable I2C I2CMODULE->I2CONCLR = I2C_STOP; I2CMODULE->MMCTRL = 0; //Disable monitor mode I2CMODULE->I2SCLH = duty; I2CMODULE->I2SCLL = duty; } void MODI2C::writePinState( void ) { if (I2CMODULE == LPC_I2C1) { LPC_PINCON->PINSEL0 |= 0x0000000F; //Sets pins as I2C LPC_PINCON->PINMODE0 |= 0x0000000A; //Neither pull up nor pull down LPC_PINCON->PINMODE_OD0 |= 0x00000003; //Open drain mode enabled } else if (I2CMODULE == LPC_I2C2) { LPC_PINCON->PINSEL0 |= (1<<21)|(1<<23); //Same story, different register settings LPC_PINCON->PINMODE0 |= (1<<21)|(1<<23); LPC_PINCON->PINMODE_OD0 |= (1<<10)|(1<<11); } } 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 } void MODI2C::_stop(LPC_I2C_TypeDef *I2CMODULE) { I2CMODULE->I2CONSET = 1<<I2C_STOP; //Send stop condition I2CMODULE->I2CONCLR = 1<<I2C_FLAG; } //Set interrupt vector void MODI2C::setISR(void) { _setISR(I2CMODULE); } void MODI2C::_setISR(LPC_I2C_TypeDef *I2CMODULE) { if (I2CMODULE == LPC_I2C1) { NVIC_SetVector(I2C1_IRQn, (uint32_t)&IRQ1Handler); NVIC_EnableIRQ(I2C1_IRQn); } else if (I2CMODULE == LPC_I2C2) { NVIC_SetVector(I2C2_IRQn, (uint32_t)&IRQ2Handler); NVIC_EnableIRQ(I2C2_IRQn); } } void MODI2C::clearISR( void ) { _clearISR(I2CMODULE); } void MODI2C::_clearISR( LPC_I2C_TypeDef *I2CMODULE ) { if (I2CMODULE == LPC_I2C1) { NVIC_DisableIRQ(I2C1_IRQn); } else if (I2CMODULE == LPC_I2C2) { NVIC_DisableIRQ(I2C2_IRQn); } }