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

Dependencies:   FPointer

Dependents:   FreeIMU FreeIMU_external_magnetometer FreeIMU

Fork of MODI2C by Erik -

Committer:
tyftyftyf
Date:
Sat Nov 09 08:59:02 2013 +0000
Revision:
1:eed116eb680a
Parent:
0:ff579e7e8efa
Child:
2:22f93d992c83
Based on Olieman's MODI2C library. Enables per-request interrupt config. The library can now be used in an interrupt.

Who changed what in which revision?

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