Improvements to Olieman's MODI2C library. Supports calls from IRQ.
Dependents: FreeIMU FreeIMU_external_magnetometer FreeIMU
Fork of MODI2C by
MODI2C.cpp@0:ff579e7e8efa, 2012-06-30 (annotated)
- Committer:
- Sissors
- Date:
- Sat Jun 30 14:55:14 2012 +0000
- Revision:
- 0:ff579e7e8efa
- Child:
- 1:eed116eb680a
v1.0
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Sissors | 0:ff579e7e8efa | 1 | #include "MODI2C.h" |
Sissors | 0:ff579e7e8efa | 2 | |
Sissors | 0:ff579e7e8efa | 3 | MODI2C::I2CBuffer MODI2C::Buffer1 = {0,0}; //Sets the initial buffer empty and count on zero |
Sissors | 0:ff579e7e8efa | 4 | MODI2C::I2CBuffer MODI2C::Buffer2 = {0,0}; //Sets the initial buffer empty |
Sissors | 0:ff579e7e8efa | 5 | //int MODI2C::status=0; |
Sissors | 0:ff579e7e8efa | 6 | int MODI2C::defaultStatus=0; |
Sissors | 0:ff579e7e8efa | 7 | |
Sissors | 0:ff579e7e8efa | 8 | |
Sissors | 0:ff579e7e8efa | 9 | |
Sissors | 0:ff579e7e8efa | 10 | |
Sissors | 0:ff579e7e8efa | 11 | MODI2C::MODI2C(PinName sda, PinName scl) : led(LED3) { |
Sissors | 0:ff579e7e8efa | 12 | //Check which connection we are using, if not correct, go to error status |
Sissors | 0:ff579e7e8efa | 13 | if ((sda==p9) && (scl==p10)) |
Sissors | 0:ff579e7e8efa | 14 | I2CMODULE = LPC_I2C1; |
Sissors | 0:ff579e7e8efa | 15 | else if ((sda==p28) && (scl==p27)) |
Sissors | 0:ff579e7e8efa | 16 | I2CMODULE = LPC_I2C2; |
Sissors | 0:ff579e7e8efa | 17 | else |
Sissors | 0:ff579e7e8efa | 18 | error("MODI2C pins not valid"); |
Sissors | 0:ff579e7e8efa | 19 | |
Sissors | 0:ff579e7e8efa | 20 | //Default settings: |
Sissors | 0:ff579e7e8efa | 21 | frequency(100000); |
Sissors | 0:ff579e7e8efa | 22 | |
Sissors | 0:ff579e7e8efa | 23 | writePinState(); |
Sissors | 0:ff579e7e8efa | 24 | } |
Sissors | 0:ff579e7e8efa | 25 | |
Sissors | 0:ff579e7e8efa | 26 | int MODI2C::write(int address, char *data, int length, bool repeated, int *status) { |
Sissors | 0:ff579e7e8efa | 27 | |
Sissors | 0:ff579e7e8efa | 28 | I2CData Data; |
Sissors | 0:ff579e7e8efa | 29 | //Store relevant information |
Sissors | 0:ff579e7e8efa | 30 | address &= 0xFE; |
Sissors | 0:ff579e7e8efa | 31 | Data.caller = this; |
Sissors | 0:ff579e7e8efa | 32 | Data.address = address; |
Sissors | 0:ff579e7e8efa | 33 | Data.repeated = repeated; |
Sissors | 0:ff579e7e8efa | 34 | Data.data = data; |
Sissors | 0:ff579e7e8efa | 35 | Data.length = length; |
Sissors | 0:ff579e7e8efa | 36 | Data.status = status; |
Sissors | 0:ff579e7e8efa | 37 | |
Sissors | 0:ff579e7e8efa | 38 | while(!addBuffer(Data, I2CMODULE)); |
Sissors | 0:ff579e7e8efa | 39 | |
Sissors | 0:ff579e7e8efa | 40 | return 0; |
Sissors | 0:ff579e7e8efa | 41 | } |
Sissors | 0:ff579e7e8efa | 42 | |
Sissors | 0:ff579e7e8efa | 43 | int MODI2C::write(int address, char *data, int length, int *status) { |
Sissors | 0:ff579e7e8efa | 44 | return write(address, data, length, false, status); |
Sissors | 0:ff579e7e8efa | 45 | } |
Sissors | 0:ff579e7e8efa | 46 | |
Sissors | 0:ff579e7e8efa | 47 | int MODI2C::read_nb(int address, char *data, int length, bool repeated, int *status) { |
Sissors | 0:ff579e7e8efa | 48 | //Store relevant information |
Sissors | 0:ff579e7e8efa | 49 | address |= 0x01; |
Sissors | 0:ff579e7e8efa | 50 | |
Sissors | 0:ff579e7e8efa | 51 | //isIdle check here |
Sissors | 0:ff579e7e8efa | 52 | I2CData Data; |
Sissors | 0:ff579e7e8efa | 53 | |
Sissors | 0:ff579e7e8efa | 54 | |
Sissors | 0:ff579e7e8efa | 55 | Data.caller = this; |
Sissors | 0:ff579e7e8efa | 56 | Data.address = address; |
Sissors | 0:ff579e7e8efa | 57 | Data.repeated = repeated; |
Sissors | 0:ff579e7e8efa | 58 | Data.data = data; |
Sissors | 0:ff579e7e8efa | 59 | Data.length = length; |
Sissors | 0:ff579e7e8efa | 60 | Data.status = status; |
Sissors | 0:ff579e7e8efa | 61 | |
Sissors | 0:ff579e7e8efa | 62 | while(!addBuffer(Data, I2CMODULE)); |
Sissors | 0:ff579e7e8efa | 63 | |
Sissors | 0:ff579e7e8efa | 64 | return 0; |
Sissors | 0:ff579e7e8efa | 65 | } |
Sissors | 0:ff579e7e8efa | 66 | |
Sissors | 0:ff579e7e8efa | 67 | int MODI2C::read_nb(int address, char *data, int length, int *status) { |
Sissors | 0:ff579e7e8efa | 68 | return read_nb(address, data, length, false, status); |
Sissors | 0:ff579e7e8efa | 69 | } |
Sissors | 0:ff579e7e8efa | 70 | |
Sissors | 0:ff579e7e8efa | 71 | int MODI2C::read(int address, char *data, int length, bool repeated) { |
Sissors | 0:ff579e7e8efa | 72 | int stat; |
Sissors | 0:ff579e7e8efa | 73 | //Store relevant information |
Sissors | 0:ff579e7e8efa | 74 | address |= 0x01; |
Sissors | 0:ff579e7e8efa | 75 | |
Sissors | 0:ff579e7e8efa | 76 | //isIdle check here |
Sissors | 0:ff579e7e8efa | 77 | I2CData Data; |
Sissors | 0:ff579e7e8efa | 78 | |
Sissors | 0:ff579e7e8efa | 79 | |
Sissors | 0:ff579e7e8efa | 80 | Data.caller = this; |
Sissors | 0:ff579e7e8efa | 81 | Data.address = address; |
Sissors | 0:ff579e7e8efa | 82 | Data.repeated = repeated; |
Sissors | 0:ff579e7e8efa | 83 | Data.data = data; |
Sissors | 0:ff579e7e8efa | 84 | Data.length = length; |
Sissors | 0:ff579e7e8efa | 85 | Data.status = &stat; |
Sissors | 0:ff579e7e8efa | 86 | |
Sissors | 0:ff579e7e8efa | 87 | while(!addBuffer(Data, I2CMODULE)); |
Sissors | 0:ff579e7e8efa | 88 | |
Sissors | 0:ff579e7e8efa | 89 | I2CBuffer *Buffer; |
Sissors | 0:ff579e7e8efa | 90 | if (I2CMODULE == LPC_I2C1) { |
Sissors | 0:ff579e7e8efa | 91 | Buffer = &Buffer1; |
Sissors | 0:ff579e7e8efa | 92 | } else { |
Sissors | 0:ff579e7e8efa | 93 | Buffer = &Buffer2; |
Sissors | 0:ff579e7e8efa | 94 | } |
Sissors | 0:ff579e7e8efa | 95 | |
Sissors | 0:ff579e7e8efa | 96 | while(Buffer->queue!=0) |
Sissors | 0:ff579e7e8efa | 97 | wait_us(1); |
Sissors | 0:ff579e7e8efa | 98 | |
Sissors | 0:ff579e7e8efa | 99 | if (stat==0x58) //Return zero if ended correctly, otherwise return return code. |
Sissors | 0:ff579e7e8efa | 100 | return 0; |
Sissors | 0:ff579e7e8efa | 101 | else |
Sissors | 0:ff579e7e8efa | 102 | return stat; |
Sissors | 0:ff579e7e8efa | 103 | } |
Sissors | 0:ff579e7e8efa | 104 | |
Sissors | 0:ff579e7e8efa | 105 | |
Sissors | 0:ff579e7e8efa | 106 | void MODI2C::start( void ) { |
Sissors | 0:ff579e7e8efa | 107 | _start(I2CMODULE); |
Sissors | 0:ff579e7e8efa | 108 | } |
Sissors | 0:ff579e7e8efa | 109 | |
Sissors | 0:ff579e7e8efa | 110 | void MODI2C::stop( void ) { |
Sissors | 0:ff579e7e8efa | 111 | _stop(I2CMODULE); |
Sissors | 0:ff579e7e8efa | 112 | } |
Sissors | 0:ff579e7e8efa | 113 | |
Sissors | 0:ff579e7e8efa | 114 | void MODI2C::frequency(int hz) { |
Sissors | 0:ff579e7e8efa | 115 | //The I2C clock by default runs on quarter of system clock, which is 96MHz |
Sissors | 0:ff579e7e8efa | 116 | //So to calculate high/low count times, we do 96MHz/4/2/frequency |
Sissors | 0:ff579e7e8efa | 117 | duty = 96000000/8/hz; |
Sissors | 0:ff579e7e8efa | 118 | if (duty>65535) |
Sissors | 0:ff579e7e8efa | 119 | duty=65535; |
Sissors | 0:ff579e7e8efa | 120 | if (duty<4) |
Sissors | 0:ff579e7e8efa | 121 | duty=4; |
Sissors | 0:ff579e7e8efa | 122 | } |
Sissors | 0:ff579e7e8efa | 123 | |
Sissors | 0:ff579e7e8efa | 124 | int MODI2C::getQueue( void ) { |
Sissors | 0:ff579e7e8efa | 125 | I2CBuffer *Buffer; |
Sissors | 0:ff579e7e8efa | 126 | if (I2CMODULE == LPC_I2C1) { |
Sissors | 0:ff579e7e8efa | 127 | Buffer = &Buffer1; |
Sissors | 0:ff579e7e8efa | 128 | } else { |
Sissors | 0:ff579e7e8efa | 129 | Buffer = &Buffer2; |
Sissors | 0:ff579e7e8efa | 130 | } |
Sissors | 0:ff579e7e8efa | 131 | return Buffer->queue; |
Sissors | 0:ff579e7e8efa | 132 | } |
Sissors | 0:ff579e7e8efa | 133 | |
Sissors | 0:ff579e7e8efa | 134 | |
Sissors | 0:ff579e7e8efa | 135 | |
Sissors | 0:ff579e7e8efa | 136 | //******************************************* |
Sissors | 0:ff579e7e8efa | 137 | //***********Internal functions************** |
Sissors | 0:ff579e7e8efa | 138 | //******************************************* |
Sissors | 0:ff579e7e8efa | 139 | |
Sissors | 0:ff579e7e8efa | 140 | |
Sissors | 0:ff579e7e8efa | 141 | void MODI2C::writeSettings( void ) { |
Sissors | 0:ff579e7e8efa | 142 | I2CMODULE->I2CONSET = 1<<I2C_ENABLE; //Enable I2C |
Sissors | 0:ff579e7e8efa | 143 | I2CMODULE->I2CONCLR = I2C_STOP; |
Sissors | 0:ff579e7e8efa | 144 | I2CMODULE->MMCTRL = 0; //Disable monitor mode |
Sissors | 0:ff579e7e8efa | 145 | I2CMODULE->I2SCLH = duty; |
Sissors | 0:ff579e7e8efa | 146 | I2CMODULE->I2SCLL = duty; |
Sissors | 0:ff579e7e8efa | 147 | |
Sissors | 0:ff579e7e8efa | 148 | } |
Sissors | 0:ff579e7e8efa | 149 | |
Sissors | 0:ff579e7e8efa | 150 | void MODI2C::writePinState( void ) { |
Sissors | 0:ff579e7e8efa | 151 | if (I2CMODULE == LPC_I2C1) { |
Sissors | 0:ff579e7e8efa | 152 | LPC_PINCON->PINSEL0 |= 0x0000000F; //Sets pins as I2C |
Sissors | 0:ff579e7e8efa | 153 | LPC_PINCON->PINMODE0 |= 0x0000000A; //Neither pull up nor pull down |
Sissors | 0:ff579e7e8efa | 154 | LPC_PINCON->PINMODE_OD0 |= 0x00000003; //Open drain mode enabled |
Sissors | 0:ff579e7e8efa | 155 | } else if (I2CMODULE == LPC_I2C2) { |
Sissors | 0:ff579e7e8efa | 156 | LPC_PINCON->PINSEL0 |= (1<<21)|(1<<23); //Same story, different register settings |
Sissors | 0:ff579e7e8efa | 157 | LPC_PINCON->PINMODE0 |= (1<<21)|(1<<23); |
Sissors | 0:ff579e7e8efa | 158 | LPC_PINCON->PINMODE_OD0 |= (1<<10)|(1<<11); |
Sissors | 0:ff579e7e8efa | 159 | } |
Sissors | 0:ff579e7e8efa | 160 | } |
Sissors | 0:ff579e7e8efa | 161 | |
Sissors | 0:ff579e7e8efa | 162 | |
Sissors | 0:ff579e7e8efa | 163 | |
Sissors | 0:ff579e7e8efa | 164 | void MODI2C::attach( void (*function)(void), int operation) { |
Sissors | 0:ff579e7e8efa | 165 | IRQOp = operation; |
Sissors | 0:ff579e7e8efa | 166 | callback.attach(function); |
Sissors | 0:ff579e7e8efa | 167 | } |
Sissors | 0:ff579e7e8efa | 168 | |
Sissors | 0:ff579e7e8efa | 169 | template<typename T> |
Sissors | 0:ff579e7e8efa | 170 | void MODI2C::attach(T *object, void (T::*member)(void), int operation) { |
Sissors | 0:ff579e7e8efa | 171 | IRQOp = operation; |
Sissors | 0:ff579e7e8efa | 172 | callback.attach(object, member); |
Sissors | 0:ff579e7e8efa | 173 | } |
Sissors | 0:ff579e7e8efa | 174 | |
Sissors | 0:ff579e7e8efa | 175 | void MODI2C::detach( void ) { |
Sissors | 0:ff579e7e8efa | 176 | callback.attach(NULL); |
Sissors | 0:ff579e7e8efa | 177 | } |
Sissors | 0:ff579e7e8efa | 178 | |
Sissors | 0:ff579e7e8efa | 179 | void MODI2C::_start(LPC_I2C_TypeDef *I2CMODULE) { |
Sissors | 0:ff579e7e8efa | 180 | if (!(I2CMODULE->I2CONSET & 1<<I2C_START)) //If already sent, skip |
Sissors | 0:ff579e7e8efa | 181 | I2CMODULE->I2CONSET = 1<<I2C_START; //Send start condition |
Sissors | 0:ff579e7e8efa | 182 | } |
Sissors | 0:ff579e7e8efa | 183 | |
Sissors | 0:ff579e7e8efa | 184 | void MODI2C::_stop(LPC_I2C_TypeDef *I2CMODULE) { |
Sissors | 0:ff579e7e8efa | 185 | I2CMODULE->I2CONSET = 1<<I2C_STOP; //Send stop condition |
Sissors | 0:ff579e7e8efa | 186 | I2CMODULE->I2CONCLR = 1<<I2C_FLAG; |
Sissors | 0:ff579e7e8efa | 187 | } |
Sissors | 0:ff579e7e8efa | 188 | |
Sissors | 0:ff579e7e8efa | 189 | //Set interrupt vector |
Sissors | 0:ff579e7e8efa | 190 | void MODI2C::setISR(void) { |
Sissors | 0:ff579e7e8efa | 191 | _setISR(I2CMODULE); |
Sissors | 0:ff579e7e8efa | 192 | } |
Sissors | 0:ff579e7e8efa | 193 | |
Sissors | 0:ff579e7e8efa | 194 | void MODI2C::_setISR(LPC_I2C_TypeDef *I2CMODULE) { |
Sissors | 0:ff579e7e8efa | 195 | if (I2CMODULE == LPC_I2C1) { |
Sissors | 0:ff579e7e8efa | 196 | NVIC_SetVector(I2C1_IRQn, (uint32_t)&IRQ1Handler); |
Sissors | 0:ff579e7e8efa | 197 | NVIC_EnableIRQ(I2C1_IRQn); |
Sissors | 0:ff579e7e8efa | 198 | } else if (I2CMODULE == LPC_I2C2) { |
Sissors | 0:ff579e7e8efa | 199 | NVIC_SetVector(I2C2_IRQn, (uint32_t)&IRQ2Handler); |
Sissors | 0:ff579e7e8efa | 200 | NVIC_EnableIRQ(I2C2_IRQn); |
Sissors | 0:ff579e7e8efa | 201 | } |
Sissors | 0:ff579e7e8efa | 202 | } |
Sissors | 0:ff579e7e8efa | 203 | |
Sissors | 0:ff579e7e8efa | 204 | void MODI2C::clearISR( void ) { |
Sissors | 0:ff579e7e8efa | 205 | _clearISR(I2CMODULE); |
Sissors | 0:ff579e7e8efa | 206 | } |
Sissors | 0:ff579e7e8efa | 207 | |
Sissors | 0:ff579e7e8efa | 208 | void MODI2C::_clearISR( LPC_I2C_TypeDef *I2CMODULE ) { |
Sissors | 0:ff579e7e8efa | 209 | if (I2CMODULE == LPC_I2C1) { |
Sissors | 0:ff579e7e8efa | 210 | NVIC_DisableIRQ(I2C1_IRQn); |
Sissors | 0:ff579e7e8efa | 211 | } else if (I2CMODULE == LPC_I2C2) { |
Sissors | 0:ff579e7e8efa | 212 | NVIC_DisableIRQ(I2C2_IRQn); |
Sissors | 0:ff579e7e8efa | 213 | } |
Sissors | 0:ff579e7e8efa | 214 | } |