mbed library sources

Dependents:   Encrypted my_mbed lklk CyaSSL_DTLS_Cellular ... more

Superseded

This library was superseded by mbed-dev - https://os.mbed.com/users/mbed_official/code/mbed-dev/.

Development branch of the mbed library sources. This library is kept in synch with the latest changes from the mbed SDK and it is not guaranteed to work.

If you are looking for a stable and tested release, please import one of the official mbed library releases:

Import librarymbed

The official Mbed 2 C/C++ SDK provides the software platform and libraries to build your applications.

Committer:
humlet
Date:
Sun Jun 30 16:34:50 2013 +0000
Revision:
11:f9e72c209510
Parent:
10:3bc89ef62ce7
fix for mbed lib issue 1 (i2c problem) see also https://mbed.org/users/mbed_official/code/mbed/issues/1

Who changed what in which revision?

UserRevisionLine numberNew contents of line
emilmont 10:3bc89ef62ce7 1 /* mbed Microcontroller Library
emilmont 10:3bc89ef62ce7 2 * Copyright (c) 2006-2013 ARM Limited
emilmont 10:3bc89ef62ce7 3 *
emilmont 10:3bc89ef62ce7 4 * Licensed under the Apache License, Version 2.0 (the "License");
emilmont 10:3bc89ef62ce7 5 * you may not use this file except in compliance with the License.
emilmont 10:3bc89ef62ce7 6 * You may obtain a copy of the License at
emilmont 10:3bc89ef62ce7 7 *
emilmont 10:3bc89ef62ce7 8 * http://www.apache.org/licenses/LICENSE-2.0
emilmont 10:3bc89ef62ce7 9 *
emilmont 10:3bc89ef62ce7 10 * Unless required by applicable law or agreed to in writing, software
emilmont 10:3bc89ef62ce7 11 * distributed under the License is distributed on an "AS IS" BASIS,
emilmont 10:3bc89ef62ce7 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
emilmont 10:3bc89ef62ce7 13 * See the License for the specific language governing permissions and
emilmont 10:3bc89ef62ce7 14 * limitations under the License.
emilmont 10:3bc89ef62ce7 15 */
emilmont 10:3bc89ef62ce7 16 #include "i2c_api.h"
emilmont 10:3bc89ef62ce7 17 #include "cmsis.h"
emilmont 10:3bc89ef62ce7 18 #include "pinmap.h"
emilmont 10:3bc89ef62ce7 19 #include "error.h"
emilmont 10:3bc89ef62ce7 20
emilmont 10:3bc89ef62ce7 21 static const PinMap PinMap_I2C_SDA[] = {
emilmont 10:3bc89ef62ce7 22 {P0_0 , I2C_1, 3},
emilmont 10:3bc89ef62ce7 23 {P0_10, I2C_2, 2},
emilmont 10:3bc89ef62ce7 24 {P0_19, I2C_1, 3},
emilmont 10:3bc89ef62ce7 25 {P0_27, I2C_0, 1},
emilmont 10:3bc89ef62ce7 26 {P1_15, I2C_2, 3},
emilmont 10:3bc89ef62ce7 27 {P1_30, I2C_0, 4},
emilmont 10:3bc89ef62ce7 28 {P2_14, I2C_1, 2},
emilmont 10:3bc89ef62ce7 29 {P2_30, I2C_2, 2},
emilmont 10:3bc89ef62ce7 30 {P4_20, I2C_2, 4},
emilmont 10:3bc89ef62ce7 31 {P5_2, I2C_0, 5},
emilmont 10:3bc89ef62ce7 32 {NC , NC , 0}
emilmont 10:3bc89ef62ce7 33 };
emilmont 10:3bc89ef62ce7 34
emilmont 10:3bc89ef62ce7 35 static const PinMap PinMap_I2C_SCL[] = {
emilmont 10:3bc89ef62ce7 36 {P0_1 , I2C_1, 3},
emilmont 10:3bc89ef62ce7 37 {P0_11, I2C_2, 2},
emilmont 10:3bc89ef62ce7 38 {P0_20, I2C_1, 3},
emilmont 10:3bc89ef62ce7 39 {P0_28, I2C_0, 1},
emilmont 10:3bc89ef62ce7 40 {P1_31, I2C_0, 4},
emilmont 10:3bc89ef62ce7 41 {P2_15, I2C_1, 2},
emilmont 10:3bc89ef62ce7 42 {P2_31, I2C_2, 2},
emilmont 10:3bc89ef62ce7 43 {P4_21, I2C_2, 2},
emilmont 10:3bc89ef62ce7 44 {P4_29, I2C_2, 4},
emilmont 10:3bc89ef62ce7 45 {P5_3, I2C_0, 5},
emilmont 10:3bc89ef62ce7 46 {NC , NC, 0}
emilmont 10:3bc89ef62ce7 47 };
emilmont 10:3bc89ef62ce7 48
emilmont 10:3bc89ef62ce7 49 #define I2C_CONSET(x) (x->i2c->CONSET)
emilmont 10:3bc89ef62ce7 50 #define I2C_CONCLR(x) (x->i2c->CONCLR)
emilmont 10:3bc89ef62ce7 51 #define I2C_STAT(x) (x->i2c->STAT)
emilmont 10:3bc89ef62ce7 52 #define I2C_DAT(x) (x->i2c->DAT)
emilmont 10:3bc89ef62ce7 53 #define I2C_SCLL(x, val) (x->i2c->SCLL = val)
emilmont 10:3bc89ef62ce7 54 #define I2C_SCLH(x, val) (x->i2c->SCLH = val)
emilmont 10:3bc89ef62ce7 55
emilmont 10:3bc89ef62ce7 56 static const uint32_t I2C_addr_offset[2][4] = {
emilmont 10:3bc89ef62ce7 57 {0x0C, 0x20, 0x24, 0x28},
emilmont 10:3bc89ef62ce7 58 {0x30, 0x34, 0x38, 0x3C}
emilmont 10:3bc89ef62ce7 59 };
emilmont 10:3bc89ef62ce7 60
emilmont 10:3bc89ef62ce7 61 static inline void i2c_conclr(i2c_t *obj, int start, int stop, int interrupt, int acknowledge) {
emilmont 10:3bc89ef62ce7 62 I2C_CONCLR(obj) = (start << 5)
emilmont 10:3bc89ef62ce7 63 | (stop << 4)
emilmont 10:3bc89ef62ce7 64 | (interrupt << 3)
emilmont 10:3bc89ef62ce7 65 | (acknowledge << 2);
emilmont 10:3bc89ef62ce7 66 }
emilmont 10:3bc89ef62ce7 67
emilmont 10:3bc89ef62ce7 68 static inline void i2c_conset(i2c_t *obj, int start, int stop, int interrupt, int acknowledge) {
emilmont 10:3bc89ef62ce7 69 I2C_CONSET(obj) = (start << 5)
emilmont 10:3bc89ef62ce7 70 | (stop << 4)
emilmont 10:3bc89ef62ce7 71 | (interrupt << 3)
emilmont 10:3bc89ef62ce7 72 | (acknowledge << 2);
emilmont 10:3bc89ef62ce7 73 }
emilmont 10:3bc89ef62ce7 74
emilmont 10:3bc89ef62ce7 75 // Clear the Serial Interrupt (SI)
emilmont 10:3bc89ef62ce7 76 static inline void i2c_clear_SI(i2c_t *obj) {
emilmont 10:3bc89ef62ce7 77 i2c_conclr(obj, 0, 0, 1, 0);
emilmont 10:3bc89ef62ce7 78 }
emilmont 10:3bc89ef62ce7 79
emilmont 10:3bc89ef62ce7 80 static inline int i2c_status(i2c_t *obj) {
emilmont 10:3bc89ef62ce7 81 return I2C_STAT(obj);
emilmont 10:3bc89ef62ce7 82 }
emilmont 10:3bc89ef62ce7 83
emilmont 10:3bc89ef62ce7 84 // Wait until the Serial Interrupt (SI) is set
emilmont 10:3bc89ef62ce7 85 static int i2c_wait_SI(i2c_t *obj) {
emilmont 10:3bc89ef62ce7 86 int timeout = 0;
emilmont 10:3bc89ef62ce7 87 while (!(I2C_CONSET(obj) & (1 << 3))) {
emilmont 10:3bc89ef62ce7 88 timeout++;
emilmont 10:3bc89ef62ce7 89 if (timeout > 100000) return -1;
emilmont 10:3bc89ef62ce7 90 }
emilmont 10:3bc89ef62ce7 91 return 0;
emilmont 10:3bc89ef62ce7 92 }
emilmont 10:3bc89ef62ce7 93
emilmont 10:3bc89ef62ce7 94 static inline void i2c_interface_enable(i2c_t *obj) {
emilmont 10:3bc89ef62ce7 95 I2C_CONSET(obj) = 0x40;
emilmont 10:3bc89ef62ce7 96 }
emilmont 10:3bc89ef62ce7 97
emilmont 10:3bc89ef62ce7 98 static inline void i2c_power_enable(i2c_t *obj) {
emilmont 10:3bc89ef62ce7 99 switch ((int)obj->i2c) {
emilmont 10:3bc89ef62ce7 100 case I2C_0: LPC_SC->PCONP |= 1 << 7; break;
emilmont 10:3bc89ef62ce7 101 case I2C_1: LPC_SC->PCONP |= 1 << 19; break;
emilmont 10:3bc89ef62ce7 102 case I2C_2: LPC_SC->PCONP |= 1 << 26; break;
emilmont 10:3bc89ef62ce7 103 }
emilmont 10:3bc89ef62ce7 104 }
emilmont 10:3bc89ef62ce7 105
emilmont 10:3bc89ef62ce7 106 void i2c_init(i2c_t *obj, PinName sda, PinName scl) {
emilmont 10:3bc89ef62ce7 107 // determine the SPI to use
emilmont 10:3bc89ef62ce7 108 I2CName i2c_sda = (I2CName)pinmap_peripheral(sda, PinMap_I2C_SDA);
emilmont 10:3bc89ef62ce7 109 I2CName i2c_scl = (I2CName)pinmap_peripheral(scl, PinMap_I2C_SCL);
emilmont 10:3bc89ef62ce7 110 obj->i2c = (LPC_I2C_TypeDef *)pinmap_merge(i2c_sda, i2c_scl);
emilmont 10:3bc89ef62ce7 111 if ((int)obj->i2c == NC) {
emilmont 10:3bc89ef62ce7 112 error("I2C pin mapping failed");
emilmont 10:3bc89ef62ce7 113 }
emilmont 10:3bc89ef62ce7 114
emilmont 10:3bc89ef62ce7 115 // enable power
emilmont 10:3bc89ef62ce7 116 i2c_power_enable(obj);
emilmont 10:3bc89ef62ce7 117
emilmont 10:3bc89ef62ce7 118 // set default frequency at 100k
emilmont 10:3bc89ef62ce7 119 i2c_frequency(obj, 100000);
emilmont 10:3bc89ef62ce7 120 i2c_conclr(obj, 1, 1, 1, 1);
emilmont 10:3bc89ef62ce7 121 i2c_interface_enable(obj);
emilmont 10:3bc89ef62ce7 122
emilmont 10:3bc89ef62ce7 123 pinmap_pinout(sda, PinMap_I2C_SDA);
emilmont 10:3bc89ef62ce7 124 pinmap_pinout(scl, PinMap_I2C_SCL);
emilmont 10:3bc89ef62ce7 125 }
emilmont 10:3bc89ef62ce7 126
emilmont 10:3bc89ef62ce7 127 inline int i2c_start(i2c_t *obj) {
emilmont 10:3bc89ef62ce7 128 int status = 0;
emilmont 10:3bc89ef62ce7 129 // 8.1 Before master mode can be entered, I2CON must be initialised to:
emilmont 10:3bc89ef62ce7 130 // - I2EN STA STO SI AA - -
emilmont 10:3bc89ef62ce7 131 // - 1 0 0 0 x - -
emilmont 10:3bc89ef62ce7 132 // if AA = 0, it can't enter slave mode
emilmont 10:3bc89ef62ce7 133 i2c_conclr(obj, 1, 1, 1, 1);
emilmont 10:3bc89ef62ce7 134
emilmont 10:3bc89ef62ce7 135 // The master mode may now be entered by setting the STA bit
emilmont 10:3bc89ef62ce7 136 // this will generate a start condition when the bus becomes free
emilmont 10:3bc89ef62ce7 137 i2c_conset(obj, 1, 0, 0, 1);
emilmont 10:3bc89ef62ce7 138
emilmont 10:3bc89ef62ce7 139 i2c_wait_SI(obj);
emilmont 10:3bc89ef62ce7 140 status = i2c_status(obj);
emilmont 10:3bc89ef62ce7 141
emilmont 10:3bc89ef62ce7 142 // Clear start bit now transmitted, and interrupt bit
emilmont 10:3bc89ef62ce7 143 i2c_conclr(obj, 1, 0, 0, 0);
emilmont 10:3bc89ef62ce7 144 return status;
emilmont 10:3bc89ef62ce7 145 }
emilmont 10:3bc89ef62ce7 146
emilmont 10:3bc89ef62ce7 147 inline void i2c_stop(i2c_t *obj) {
emilmont 10:3bc89ef62ce7 148 // write the stop bit
emilmont 10:3bc89ef62ce7 149 i2c_conset(obj, 0, 1, 0, 0);
emilmont 10:3bc89ef62ce7 150 i2c_clear_SI(obj);
emilmont 10:3bc89ef62ce7 151
emilmont 10:3bc89ef62ce7 152 // wait for STO bit to reset
emilmont 10:3bc89ef62ce7 153 while(I2C_CONSET(obj) & (1 << 4));
emilmont 10:3bc89ef62ce7 154 }
emilmont 10:3bc89ef62ce7 155
emilmont 10:3bc89ef62ce7 156
emilmont 10:3bc89ef62ce7 157 static inline int i2c_do_write(i2c_t *obj, int value, uint8_t addr) {
emilmont 10:3bc89ef62ce7 158 // write the data
emilmont 10:3bc89ef62ce7 159 I2C_DAT(obj) = value;
emilmont 10:3bc89ef62ce7 160
emilmont 10:3bc89ef62ce7 161 // clear SI to init a send
emilmont 10:3bc89ef62ce7 162 i2c_clear_SI(obj);
emilmont 10:3bc89ef62ce7 163
emilmont 10:3bc89ef62ce7 164 // wait and return status
emilmont 10:3bc89ef62ce7 165 i2c_wait_SI(obj);
emilmont 10:3bc89ef62ce7 166 return i2c_status(obj);
emilmont 10:3bc89ef62ce7 167 }
emilmont 10:3bc89ef62ce7 168
emilmont 10:3bc89ef62ce7 169 static inline int i2c_do_read(i2c_t *obj, int last) {
emilmont 10:3bc89ef62ce7 170 // we are in state 0x40 (SLA+R tx'd) or 0x50 (data rx'd and ack)
emilmont 10:3bc89ef62ce7 171 if(last) {
emilmont 10:3bc89ef62ce7 172 i2c_conclr(obj, 0, 0, 0, 1); // send a NOT ACK
emilmont 10:3bc89ef62ce7 173 } else {
emilmont 10:3bc89ef62ce7 174 i2c_conset(obj, 0, 0, 0, 1); // send a ACK
emilmont 10:3bc89ef62ce7 175 }
emilmont 10:3bc89ef62ce7 176
emilmont 10:3bc89ef62ce7 177 // accept byte
emilmont 10:3bc89ef62ce7 178 i2c_clear_SI(obj);
emilmont 10:3bc89ef62ce7 179
emilmont 10:3bc89ef62ce7 180 // wait for it to arrive
emilmont 10:3bc89ef62ce7 181 i2c_wait_SI(obj);
emilmont 10:3bc89ef62ce7 182
emilmont 10:3bc89ef62ce7 183 // return the data
emilmont 10:3bc89ef62ce7 184 return (I2C_DAT(obj) & 0xFF);
emilmont 10:3bc89ef62ce7 185 }
emilmont 10:3bc89ef62ce7 186
emilmont 10:3bc89ef62ce7 187 void i2c_frequency(i2c_t *obj, int hz) {
emilmont 10:3bc89ef62ce7 188 uint32_t PCLK = PeripheralClock;
emilmont 10:3bc89ef62ce7 189 uint32_t pulse = PCLK / (hz * 2);
emilmont 10:3bc89ef62ce7 190
emilmont 10:3bc89ef62ce7 191 // I2C Rate
emilmont 10:3bc89ef62ce7 192 I2C_SCLL(obj, pulse);
emilmont 10:3bc89ef62ce7 193 I2C_SCLH(obj, pulse);
emilmont 10:3bc89ef62ce7 194 }
emilmont 10:3bc89ef62ce7 195
emilmont 10:3bc89ef62ce7 196 // The I2C does a read or a write as a whole operation
emilmont 10:3bc89ef62ce7 197 // There are two types of error conditions it can encounter
emilmont 10:3bc89ef62ce7 198 // 1) it can not obtain the bus
emilmont 10:3bc89ef62ce7 199 // 2) it gets error responses at part of the transmission
emilmont 10:3bc89ef62ce7 200 //
emilmont 10:3bc89ef62ce7 201 // We tackle them as follows:
emilmont 10:3bc89ef62ce7 202 // 1) we retry until we get the bus. we could have a "timeout" if we can not get it
emilmont 10:3bc89ef62ce7 203 // which basically turns it in to a 2)
emilmont 10:3bc89ef62ce7 204 // 2) on error, we use the standard error mechanisms to report/debug
emilmont 10:3bc89ef62ce7 205 //
emilmont 10:3bc89ef62ce7 206 // Therefore an I2C transaction should always complete. If it doesn't it is usually
emilmont 10:3bc89ef62ce7 207 // because something is setup wrong (e.g. wiring), and we don't need to programatically
emilmont 10:3bc89ef62ce7 208 // check for that
emilmont 10:3bc89ef62ce7 209 int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) {
emilmont 10:3bc89ef62ce7 210 int count, status;
emilmont 10:3bc89ef62ce7 211
emilmont 10:3bc89ef62ce7 212 status = i2c_start(obj);
emilmont 10:3bc89ef62ce7 213
emilmont 10:3bc89ef62ce7 214 if ((status != 0x10) && (status != 0x08)) {
emilmont 10:3bc89ef62ce7 215 i2c_stop(obj);
emilmont 10:3bc89ef62ce7 216 return status;
emilmont 10:3bc89ef62ce7 217 }
emilmont 10:3bc89ef62ce7 218
emilmont 10:3bc89ef62ce7 219 status = i2c_do_write(obj, (address | 0x01), 1);
emilmont 10:3bc89ef62ce7 220 if (status != 0x40) {
emilmont 10:3bc89ef62ce7 221 i2c_stop(obj);
emilmont 10:3bc89ef62ce7 222 return status;
emilmont 10:3bc89ef62ce7 223 }
emilmont 10:3bc89ef62ce7 224
emilmont 10:3bc89ef62ce7 225 // Read in all except last byte
emilmont 10:3bc89ef62ce7 226 for (count = 0; count < (length - 1); count++) {
emilmont 10:3bc89ef62ce7 227 int value = i2c_do_read(obj, 0);
emilmont 10:3bc89ef62ce7 228 status = i2c_status(obj);
emilmont 10:3bc89ef62ce7 229 if (status != 0x50) {
emilmont 10:3bc89ef62ce7 230 i2c_stop(obj);
emilmont 10:3bc89ef62ce7 231 return status;
emilmont 10:3bc89ef62ce7 232 }
emilmont 10:3bc89ef62ce7 233 data[count] = (char) value;
emilmont 10:3bc89ef62ce7 234 }
emilmont 10:3bc89ef62ce7 235
emilmont 10:3bc89ef62ce7 236 // read in last byte
emilmont 10:3bc89ef62ce7 237 int value = i2c_do_read(obj, 1);
emilmont 10:3bc89ef62ce7 238 status = i2c_status(obj);
emilmont 10:3bc89ef62ce7 239 if (status != 0x58) {
emilmont 10:3bc89ef62ce7 240 i2c_stop(obj);
emilmont 10:3bc89ef62ce7 241 return status;
emilmont 10:3bc89ef62ce7 242 }
emilmont 10:3bc89ef62ce7 243
emilmont 10:3bc89ef62ce7 244 data[count] = (char) value;
emilmont 10:3bc89ef62ce7 245
emilmont 10:3bc89ef62ce7 246 // If not repeated start, send stop.
emilmont 10:3bc89ef62ce7 247 if (stop) {
emilmont 10:3bc89ef62ce7 248 i2c_stop(obj);
emilmont 10:3bc89ef62ce7 249 }
emilmont 10:3bc89ef62ce7 250
emilmont 10:3bc89ef62ce7 251 return 0;
emilmont 10:3bc89ef62ce7 252 }
emilmont 10:3bc89ef62ce7 253
emilmont 10:3bc89ef62ce7 254 int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop) {
emilmont 10:3bc89ef62ce7 255 int i, status;
emilmont 10:3bc89ef62ce7 256
emilmont 10:3bc89ef62ce7 257 status = i2c_start(obj);
emilmont 10:3bc89ef62ce7 258
emilmont 10:3bc89ef62ce7 259 if ((status != 0x10) && (status != 0x08)) {
emilmont 10:3bc89ef62ce7 260 i2c_stop(obj);
emilmont 10:3bc89ef62ce7 261 return status;
emilmont 10:3bc89ef62ce7 262 }
emilmont 10:3bc89ef62ce7 263
emilmont 10:3bc89ef62ce7 264 status = i2c_do_write(obj, (address & 0xFE), 1);
emilmont 10:3bc89ef62ce7 265 if (status != 0x18) {
emilmont 10:3bc89ef62ce7 266 i2c_stop(obj);
emilmont 10:3bc89ef62ce7 267 return status;
emilmont 10:3bc89ef62ce7 268 }
emilmont 10:3bc89ef62ce7 269
emilmont 10:3bc89ef62ce7 270 for (i=0; i<length; i++) {
emilmont 10:3bc89ef62ce7 271 status = i2c_do_write(obj, data[i], 0);
emilmont 10:3bc89ef62ce7 272 if (status != 0x28) {
emilmont 10:3bc89ef62ce7 273 i2c_stop(obj);
emilmont 10:3bc89ef62ce7 274 return status;
emilmont 10:3bc89ef62ce7 275 }
emilmont 10:3bc89ef62ce7 276 }
emilmont 10:3bc89ef62ce7 277
humlet 11:f9e72c209510 278 // clearing the serial interrupt here might cause an unintended rewrite of the last byte
humlet 11:f9e72c209510 279 // see also issue report https://mbed.org/users/mbed_official/code/mbed/issues/1
humlet 11:f9e72c209510 280 // i2c_clear_SI(obj);
emilmont 10:3bc89ef62ce7 281
emilmont 10:3bc89ef62ce7 282 // If not repeated start, send stop.
emilmont 10:3bc89ef62ce7 283 if (stop) {
emilmont 10:3bc89ef62ce7 284 i2c_stop(obj);
emilmont 10:3bc89ef62ce7 285 }
emilmont 10:3bc89ef62ce7 286
emilmont 10:3bc89ef62ce7 287 return 0;
emilmont 10:3bc89ef62ce7 288 }
emilmont 10:3bc89ef62ce7 289
emilmont 10:3bc89ef62ce7 290 void i2c_reset(i2c_t *obj) {
emilmont 10:3bc89ef62ce7 291 i2c_stop(obj);
emilmont 10:3bc89ef62ce7 292 }
emilmont 10:3bc89ef62ce7 293
emilmont 10:3bc89ef62ce7 294 int i2c_byte_read(i2c_t *obj, int last) {
emilmont 10:3bc89ef62ce7 295 return (i2c_do_read(obj, last) & 0xFF);
emilmont 10:3bc89ef62ce7 296 }
emilmont 10:3bc89ef62ce7 297
emilmont 10:3bc89ef62ce7 298 int i2c_byte_write(i2c_t *obj, int data) {
emilmont 10:3bc89ef62ce7 299 int ack;
emilmont 10:3bc89ef62ce7 300 int status = i2c_do_write(obj, (data & 0xFF), 0);
emilmont 10:3bc89ef62ce7 301
emilmont 10:3bc89ef62ce7 302 switch(status) {
emilmont 10:3bc89ef62ce7 303 case 0x18: case 0x28: // Master transmit ACKs
emilmont 10:3bc89ef62ce7 304 ack = 1;
emilmont 10:3bc89ef62ce7 305 break;
emilmont 10:3bc89ef62ce7 306
emilmont 10:3bc89ef62ce7 307 case 0x40: // Master receive address transmitted ACK
emilmont 10:3bc89ef62ce7 308 ack = 1;
emilmont 10:3bc89ef62ce7 309 break;
emilmont 10:3bc89ef62ce7 310
emilmont 10:3bc89ef62ce7 311 case 0xB8: // Slave transmit ACK
emilmont 10:3bc89ef62ce7 312 ack = 1;
emilmont 10:3bc89ef62ce7 313 break;
emilmont 10:3bc89ef62ce7 314
emilmont 10:3bc89ef62ce7 315 default:
emilmont 10:3bc89ef62ce7 316 ack = 0;
emilmont 10:3bc89ef62ce7 317 break;
emilmont 10:3bc89ef62ce7 318 }
emilmont 10:3bc89ef62ce7 319
emilmont 10:3bc89ef62ce7 320 return ack;
emilmont 10:3bc89ef62ce7 321 }
emilmont 10:3bc89ef62ce7 322
emilmont 10:3bc89ef62ce7 323 void i2c_slave_mode(i2c_t *obj, int enable_slave) {
emilmont 10:3bc89ef62ce7 324 if (enable_slave != 0) {
emilmont 10:3bc89ef62ce7 325 i2c_conclr(obj, 1, 1, 1, 0);
emilmont 10:3bc89ef62ce7 326 i2c_conset(obj, 0, 0, 0, 1);
emilmont 10:3bc89ef62ce7 327 } else {
emilmont 10:3bc89ef62ce7 328 i2c_conclr(obj, 1, 1, 1, 1);
emilmont 10:3bc89ef62ce7 329 }
emilmont 10:3bc89ef62ce7 330 }
emilmont 10:3bc89ef62ce7 331
emilmont 10:3bc89ef62ce7 332 int i2c_slave_receive(i2c_t *obj) {
emilmont 10:3bc89ef62ce7 333 int status;
emilmont 10:3bc89ef62ce7 334 int retval;
emilmont 10:3bc89ef62ce7 335
emilmont 10:3bc89ef62ce7 336 status = i2c_status(obj);
emilmont 10:3bc89ef62ce7 337 switch(status) {
emilmont 10:3bc89ef62ce7 338 case 0x60: retval = 3; break;
emilmont 10:3bc89ef62ce7 339 case 0x70: retval = 2; break;
emilmont 10:3bc89ef62ce7 340 case 0xA8: retval = 1; break;
emilmont 10:3bc89ef62ce7 341 default : retval = 0; break;
emilmont 10:3bc89ef62ce7 342 }
emilmont 10:3bc89ef62ce7 343
emilmont 10:3bc89ef62ce7 344 return(retval);
emilmont 10:3bc89ef62ce7 345 }
emilmont 10:3bc89ef62ce7 346
emilmont 10:3bc89ef62ce7 347 int i2c_slave_read(i2c_t *obj, char *data, int length) {
emilmont 10:3bc89ef62ce7 348 int count = 0;
emilmont 10:3bc89ef62ce7 349 int status;
emilmont 10:3bc89ef62ce7 350
emilmont 10:3bc89ef62ce7 351 do {
emilmont 10:3bc89ef62ce7 352 i2c_clear_SI(obj);
emilmont 10:3bc89ef62ce7 353 i2c_wait_SI(obj);
emilmont 10:3bc89ef62ce7 354 status = i2c_status(obj);
emilmont 10:3bc89ef62ce7 355 if((status == 0x80) || (status == 0x90)) {
emilmont 10:3bc89ef62ce7 356 data[count] = I2C_DAT(obj) & 0xFF;
emilmont 10:3bc89ef62ce7 357 }
emilmont 10:3bc89ef62ce7 358 count++;
emilmont 10:3bc89ef62ce7 359 } while (((status == 0x80) || (status == 0x90) ||
emilmont 10:3bc89ef62ce7 360 (status == 0x060) || (status == 0x70)) && (count < length));
emilmont 10:3bc89ef62ce7 361
emilmont 10:3bc89ef62ce7 362 if(status != 0xA0) {
emilmont 10:3bc89ef62ce7 363 i2c_stop(obj);
emilmont 10:3bc89ef62ce7 364 }
emilmont 10:3bc89ef62ce7 365
emilmont 10:3bc89ef62ce7 366 i2c_clear_SI(obj);
emilmont 10:3bc89ef62ce7 367
emilmont 10:3bc89ef62ce7 368 return (count - 1);
emilmont 10:3bc89ef62ce7 369 }
emilmont 10:3bc89ef62ce7 370
emilmont 10:3bc89ef62ce7 371 int i2c_slave_write(i2c_t *obj, const char *data, int length) {
emilmont 10:3bc89ef62ce7 372 int count = 0;
emilmont 10:3bc89ef62ce7 373 int status;
emilmont 10:3bc89ef62ce7 374
emilmont 10:3bc89ef62ce7 375 if(length <= 0) {
emilmont 10:3bc89ef62ce7 376 return(0);
emilmont 10:3bc89ef62ce7 377 }
emilmont 10:3bc89ef62ce7 378
emilmont 10:3bc89ef62ce7 379 do {
emilmont 10:3bc89ef62ce7 380 status = i2c_do_write(obj, data[count], 0);
emilmont 10:3bc89ef62ce7 381 count++;
emilmont 10:3bc89ef62ce7 382 } while ((count < length) && (status == 0xB8));
emilmont 10:3bc89ef62ce7 383
emilmont 10:3bc89ef62ce7 384 if((status != 0xC0) && (status != 0xC8)) {
emilmont 10:3bc89ef62ce7 385 i2c_stop(obj);
emilmont 10:3bc89ef62ce7 386 }
emilmont 10:3bc89ef62ce7 387
emilmont 10:3bc89ef62ce7 388 i2c_clear_SI(obj);
emilmont 10:3bc89ef62ce7 389
emilmont 10:3bc89ef62ce7 390 return(count);
emilmont 10:3bc89ef62ce7 391 }
emilmont 10:3bc89ef62ce7 392
emilmont 10:3bc89ef62ce7 393 void i2c_slave_address(i2c_t *obj, int idx, uint32_t address, uint32_t mask) {
emilmont 10:3bc89ef62ce7 394 uint32_t addr;
emilmont 10:3bc89ef62ce7 395
emilmont 10:3bc89ef62ce7 396 if ((idx >= 0) && (idx <= 3)) {
emilmont 10:3bc89ef62ce7 397 addr = ((uint32_t)obj->i2c) + I2C_addr_offset[0][idx];
emilmont 10:3bc89ef62ce7 398 *((uint32_t *) addr) = address & 0xFF;
emilmont 10:3bc89ef62ce7 399 addr = ((uint32_t)obj->i2c) + I2C_addr_offset[1][idx];
emilmont 10:3bc89ef62ce7 400 *((uint32_t *) addr) = mask & 0xFE;
emilmont 10:3bc89ef62ce7 401 }
emilmont 10:3bc89ef62ce7 402 }