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:
emimon01
Date:
Wed Jul 24 11:11:21 2013 +0100
Revision:
12:5fa2273de5db
Parent:
10:3bc89ef62ce7
Remove sources for toolchains unknown by the online compiler

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
emilmont 10:3bc89ef62ce7 18 #include "cmsis.h"
emilmont 10:3bc89ef62ce7 19 #include "pinmap.h"
emilmont 10:3bc89ef62ce7 20 #include "error.h"
emilmont 10:3bc89ef62ce7 21
emilmont 10:3bc89ef62ce7 22 static const PinMap PinMap_I2C_SDA[] = {
emilmont 10:3bc89ef62ce7 23 {PTE25, I2C_0, 5},
emilmont 10:3bc89ef62ce7 24 {PTC9, I2C_0, 2},
emilmont 10:3bc89ef62ce7 25 {PTE0, I2C_1, 6},
emilmont 10:3bc89ef62ce7 26 {PTB1, I2C_0, 2},
emilmont 10:3bc89ef62ce7 27 {PTB3, I2C_0, 2},
emilmont 10:3bc89ef62ce7 28 {NC , NC , 0}
emilmont 10:3bc89ef62ce7 29 };
emilmont 10:3bc89ef62ce7 30
emilmont 10:3bc89ef62ce7 31 static const PinMap PinMap_I2C_SCL[] = {
emilmont 10:3bc89ef62ce7 32 {PTE24, I2C_0, 5},
emilmont 10:3bc89ef62ce7 33 {PTC8, I2C_0, 2},
emilmont 10:3bc89ef62ce7 34 {PTE1, I2C_1, 6},
emilmont 10:3bc89ef62ce7 35 {PTB0, I2C_0, 2},
emilmont 10:3bc89ef62ce7 36 {PTB2, I2C_0, 2},
emilmont 10:3bc89ef62ce7 37 {NC , NC, 0}
emilmont 10:3bc89ef62ce7 38 };
emilmont 10:3bc89ef62ce7 39
emilmont 10:3bc89ef62ce7 40 static const uint16_t ICR[0x40] = {
emilmont 10:3bc89ef62ce7 41 20, 22, 24, 26, 28,
emilmont 10:3bc89ef62ce7 42 30, 34, 40, 28, 32,
emilmont 10:3bc89ef62ce7 43 36, 40, 44, 48, 56,
emilmont 10:3bc89ef62ce7 44 68, 48, 56, 64, 72,
emilmont 10:3bc89ef62ce7 45 80, 88, 104, 128, 80,
emilmont 10:3bc89ef62ce7 46 96, 112, 128, 144, 160,
emilmont 10:3bc89ef62ce7 47 192, 240, 160, 192, 224,
emilmont 10:3bc89ef62ce7 48 256, 288, 320, 384, 480,
emilmont 10:3bc89ef62ce7 49 320, 384, 448, 512, 576,
emilmont 10:3bc89ef62ce7 50 640, 768, 960, 640, 768,
emilmont 10:3bc89ef62ce7 51 896, 1024, 1152, 1280, 1536,
emilmont 10:3bc89ef62ce7 52 1920, 1280, 1536, 1792, 2048,
emilmont 10:3bc89ef62ce7 53 2304, 2560, 3072, 3840
emilmont 10:3bc89ef62ce7 54 };
emilmont 10:3bc89ef62ce7 55
emilmont 10:3bc89ef62ce7 56 static uint8_t first_read;
emilmont 10:3bc89ef62ce7 57
emilmont 10:3bc89ef62ce7 58
emilmont 10:3bc89ef62ce7 59 void i2c_init(i2c_t *obj, PinName sda, PinName scl) {
emilmont 10:3bc89ef62ce7 60 // determine the I2C to use
emilmont 10:3bc89ef62ce7 61 I2CName i2c_sda = (I2CName)pinmap_peripheral(sda, PinMap_I2C_SDA);
emilmont 10:3bc89ef62ce7 62 I2CName i2c_scl = (I2CName)pinmap_peripheral(scl, PinMap_I2C_SCL);
emilmont 10:3bc89ef62ce7 63 obj->i2c = (I2C_Type*)pinmap_merge(i2c_sda, i2c_scl);
emilmont 10:3bc89ef62ce7 64 if ((int)obj->i2c == NC) {
emilmont 10:3bc89ef62ce7 65 error("I2C pin mapping failed");
emilmont 10:3bc89ef62ce7 66 }
emilmont 10:3bc89ef62ce7 67
emilmont 10:3bc89ef62ce7 68 // enable power
emilmont 10:3bc89ef62ce7 69 switch ((int)obj->i2c) {
emilmont 10:3bc89ef62ce7 70 case I2C_0: SIM->SCGC5 |= 1 << 13; SIM->SCGC4 |= 1 << 6; break;
emilmont 10:3bc89ef62ce7 71 case I2C_1: SIM->SCGC5 |= 1 << 11; SIM->SCGC4 |= 1 << 7; break;
emilmont 10:3bc89ef62ce7 72 }
emilmont 10:3bc89ef62ce7 73
emilmont 10:3bc89ef62ce7 74 // set default frequency at 100k
emilmont 10:3bc89ef62ce7 75 i2c_frequency(obj, 100000);
emilmont 10:3bc89ef62ce7 76
emilmont 10:3bc89ef62ce7 77 // enable I2C interface
emilmont 10:3bc89ef62ce7 78 obj->i2c->C1 |= 0x80;
emilmont 10:3bc89ef62ce7 79
emilmont 10:3bc89ef62ce7 80 pinmap_pinout(sda, PinMap_I2C_SDA);
emilmont 10:3bc89ef62ce7 81 pinmap_pinout(scl, PinMap_I2C_SCL);
emilmont 10:3bc89ef62ce7 82
emilmont 10:3bc89ef62ce7 83 first_read = 1;
emilmont 10:3bc89ef62ce7 84 }
emilmont 10:3bc89ef62ce7 85
emilmont 10:3bc89ef62ce7 86 int i2c_start(i2c_t *obj) {
emilmont 10:3bc89ef62ce7 87 // if we are in the middle of a transaction
emilmont 10:3bc89ef62ce7 88 // activate the repeat_start flag
emilmont 10:3bc89ef62ce7 89 if (obj->i2c->S & I2C_S_BUSY_MASK) {
emilmont 10:3bc89ef62ce7 90 obj->i2c->C1 |= 0x04;
emilmont 10:3bc89ef62ce7 91 } else {
emilmont 10:3bc89ef62ce7 92 obj->i2c->C1 |= I2C_C1_MST_MASK;
emilmont 10:3bc89ef62ce7 93 obj->i2c->C1 |= I2C_C1_TX_MASK;
emilmont 10:3bc89ef62ce7 94 }
emilmont 10:3bc89ef62ce7 95 first_read = 1;
emilmont 10:3bc89ef62ce7 96 return 0;
emilmont 10:3bc89ef62ce7 97 }
emilmont 10:3bc89ef62ce7 98
emilmont 10:3bc89ef62ce7 99 void i2c_stop(i2c_t *obj) {
emilmont 10:3bc89ef62ce7 100 volatile uint32_t n = 0;
emilmont 10:3bc89ef62ce7 101 obj->i2c->C1 &= ~I2C_C1_MST_MASK;
emilmont 10:3bc89ef62ce7 102 obj->i2c->C1 &= ~I2C_C1_TX_MASK;
emilmont 10:3bc89ef62ce7 103
emilmont 10:3bc89ef62ce7 104 // It seems that there are timing problems
emilmont 10:3bc89ef62ce7 105 // when there is no waiting time after a STOP.
emilmont 10:3bc89ef62ce7 106 // This wait is also included on the samples
emilmont 10:3bc89ef62ce7 107 // code provided with the freedom board
emilmont 10:3bc89ef62ce7 108 for (n = 0; n < 100; n++) __NOP();
emilmont 10:3bc89ef62ce7 109 first_read = 1;
emilmont 10:3bc89ef62ce7 110 }
emilmont 10:3bc89ef62ce7 111
emilmont 10:3bc89ef62ce7 112 static int timeout_status_poll(i2c_t *obj, uint32_t mask) {
emilmont 10:3bc89ef62ce7 113 uint32_t i, timeout = 1000;
emilmont 10:3bc89ef62ce7 114
emilmont 10:3bc89ef62ce7 115 for (i = 0; i < timeout; i++) {
emilmont 10:3bc89ef62ce7 116 if (obj->i2c->S & mask)
emilmont 10:3bc89ef62ce7 117 return 0;
emilmont 10:3bc89ef62ce7 118 }
emilmont 10:3bc89ef62ce7 119
emilmont 10:3bc89ef62ce7 120 return 1;
emilmont 10:3bc89ef62ce7 121 }
emilmont 10:3bc89ef62ce7 122
emilmont 10:3bc89ef62ce7 123 // this function waits the end of a tx transfer and return the status of the transaction:
emilmont 10:3bc89ef62ce7 124 // 0: OK ack received
emilmont 10:3bc89ef62ce7 125 // 1: OK ack not received
emilmont 10:3bc89ef62ce7 126 // 2: failure
emilmont 10:3bc89ef62ce7 127 static int i2c_wait_end_tx_transfer(i2c_t *obj) {
emilmont 10:3bc89ef62ce7 128
emilmont 10:3bc89ef62ce7 129 // wait for the interrupt flag
emilmont 10:3bc89ef62ce7 130 if (timeout_status_poll(obj, I2C_S_IICIF_MASK)) {
emilmont 10:3bc89ef62ce7 131 return 2;
emilmont 10:3bc89ef62ce7 132 }
emilmont 10:3bc89ef62ce7 133
emilmont 10:3bc89ef62ce7 134 obj->i2c->S |= I2C_S_IICIF_MASK;
emilmont 10:3bc89ef62ce7 135
emilmont 10:3bc89ef62ce7 136 // wait transfer complete
emilmont 10:3bc89ef62ce7 137 if (timeout_status_poll(obj, I2C_S_TCF_MASK)) {
emilmont 10:3bc89ef62ce7 138 return 2;
emilmont 10:3bc89ef62ce7 139 }
emilmont 10:3bc89ef62ce7 140
emilmont 10:3bc89ef62ce7 141 // check if we received the ACK or not
emilmont 10:3bc89ef62ce7 142 return obj->i2c->S & I2C_S_RXAK_MASK ? 1 : 0;
emilmont 10:3bc89ef62ce7 143 }
emilmont 10:3bc89ef62ce7 144
emilmont 10:3bc89ef62ce7 145 // this function waits the end of a rx transfer and return the status of the transaction:
emilmont 10:3bc89ef62ce7 146 // 0: OK
emilmont 10:3bc89ef62ce7 147 // 1: failure
emilmont 10:3bc89ef62ce7 148 static int i2c_wait_end_rx_transfer(i2c_t *obj) {
emilmont 10:3bc89ef62ce7 149 // wait for the end of the rx transfer
emilmont 10:3bc89ef62ce7 150 if (timeout_status_poll(obj, I2C_S_IICIF_MASK)) {
emilmont 10:3bc89ef62ce7 151 return 1;
emilmont 10:3bc89ef62ce7 152 }
emilmont 10:3bc89ef62ce7 153
emilmont 10:3bc89ef62ce7 154 obj->i2c->S |= I2C_S_IICIF_MASK;
emilmont 10:3bc89ef62ce7 155
emilmont 10:3bc89ef62ce7 156 return 0;
emilmont 10:3bc89ef62ce7 157 }
emilmont 10:3bc89ef62ce7 158
emilmont 10:3bc89ef62ce7 159 static void i2c_send_nack(i2c_t *obj) {
emilmont 10:3bc89ef62ce7 160 obj->i2c->C1 |= I2C_C1_TXAK_MASK; // NACK
emilmont 10:3bc89ef62ce7 161 }
emilmont 10:3bc89ef62ce7 162
emilmont 10:3bc89ef62ce7 163 static void i2c_send_ack(i2c_t *obj) {
emilmont 10:3bc89ef62ce7 164 obj->i2c->C1 &= ~I2C_C1_TXAK_MASK; // ACK
emilmont 10:3bc89ef62ce7 165 }
emilmont 10:3bc89ef62ce7 166
emilmont 10:3bc89ef62ce7 167 static int i2c_do_write(i2c_t *obj, int value) {
emilmont 10:3bc89ef62ce7 168 // write the data
emilmont 10:3bc89ef62ce7 169 obj->i2c->D = value;
emilmont 10:3bc89ef62ce7 170
emilmont 10:3bc89ef62ce7 171 // init and wait the end of the transfer
emilmont 10:3bc89ef62ce7 172 return i2c_wait_end_tx_transfer(obj);
emilmont 10:3bc89ef62ce7 173 }
emilmont 10:3bc89ef62ce7 174
emilmont 10:3bc89ef62ce7 175 static int i2c_do_read(i2c_t *obj, char * data, int last) {
emilmont 10:3bc89ef62ce7 176 if (last)
emilmont 10:3bc89ef62ce7 177 i2c_send_nack(obj);
emilmont 10:3bc89ef62ce7 178 else
emilmont 10:3bc89ef62ce7 179 i2c_send_ack(obj);
emilmont 10:3bc89ef62ce7 180
emilmont 10:3bc89ef62ce7 181 *data = (obj->i2c->D & 0xFF);
emilmont 10:3bc89ef62ce7 182
emilmont 10:3bc89ef62ce7 183 // start rx transfer and wait the end of the transfer
emilmont 10:3bc89ef62ce7 184 return i2c_wait_end_rx_transfer(obj);
emilmont 10:3bc89ef62ce7 185 }
emilmont 10:3bc89ef62ce7 186
emilmont 10:3bc89ef62ce7 187 void i2c_frequency(i2c_t *obj, int hz) {
emilmont 10:3bc89ef62ce7 188 uint8_t icr = 0;
emilmont 10:3bc89ef62ce7 189 uint8_t mult = 0;
emilmont 10:3bc89ef62ce7 190 uint32_t error = 0;
emilmont 10:3bc89ef62ce7 191 uint32_t p_error = 0xffffffff;
emilmont 10:3bc89ef62ce7 192 uint32_t ref = 0;
emilmont 10:3bc89ef62ce7 193 uint8_t i, j;
emilmont 10:3bc89ef62ce7 194 // bus clk
emilmont 10:3bc89ef62ce7 195 uint32_t PCLK = 24000000u;
emilmont 10:3bc89ef62ce7 196 uint32_t pulse = PCLK / (hz * 2);
emilmont 10:3bc89ef62ce7 197
emilmont 10:3bc89ef62ce7 198 // we look for the values that minimize the error
emilmont 10:3bc89ef62ce7 199
emilmont 10:3bc89ef62ce7 200 // test all the MULT values
emilmont 10:3bc89ef62ce7 201 for (i = 1; i < 5; i*=2) {
emilmont 10:3bc89ef62ce7 202 for (j = 0; j < 0x40; j++) {
emilmont 10:3bc89ef62ce7 203 ref = PCLK / (i*ICR[j]);
emilmont 10:3bc89ef62ce7 204 error = (ref > hz) ? ref - hz : hz - ref;
emilmont 10:3bc89ef62ce7 205 if (error < p_error) {
emilmont 10:3bc89ef62ce7 206 icr = j;
emilmont 10:3bc89ef62ce7 207 mult = i/2;
emilmont 10:3bc89ef62ce7 208 p_error = error;
emilmont 10:3bc89ef62ce7 209 }
emilmont 10:3bc89ef62ce7 210 }
emilmont 10:3bc89ef62ce7 211 }
emilmont 10:3bc89ef62ce7 212 pulse = icr | (mult << 6);
emilmont 10:3bc89ef62ce7 213
emilmont 10:3bc89ef62ce7 214 // I2C Rate
emilmont 10:3bc89ef62ce7 215 obj->i2c->F = pulse;
emilmont 10:3bc89ef62ce7 216 }
emilmont 10:3bc89ef62ce7 217
emilmont 10:3bc89ef62ce7 218 int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) {
emilmont 10:3bc89ef62ce7 219 uint8_t count;
emilmont 10:3bc89ef62ce7 220 char dummy_read, *ptr;
emilmont 10:3bc89ef62ce7 221
emilmont 10:3bc89ef62ce7 222 if (i2c_start(obj)) {
emilmont 10:3bc89ef62ce7 223 i2c_stop(obj);
emilmont 10:3bc89ef62ce7 224 return 1;
emilmont 10:3bc89ef62ce7 225 }
emilmont 10:3bc89ef62ce7 226
emilmont 10:3bc89ef62ce7 227 if (i2c_do_write(obj, (address | 0x01))) {
emilmont 10:3bc89ef62ce7 228 i2c_stop(obj);
emilmont 10:3bc89ef62ce7 229 return 1;
emilmont 10:3bc89ef62ce7 230 }
emilmont 10:3bc89ef62ce7 231
emilmont 10:3bc89ef62ce7 232 // set rx mode
emilmont 10:3bc89ef62ce7 233 obj->i2c->C1 &= ~I2C_C1_TX_MASK;
emilmont 10:3bc89ef62ce7 234
emilmont 10:3bc89ef62ce7 235 // Read in bytes
emilmont 10:3bc89ef62ce7 236 for (count = 0; count < (length); count++) {
emilmont 10:3bc89ef62ce7 237 ptr = (count == 0) ? &dummy_read : &data[count - 1];
emilmont 10:3bc89ef62ce7 238 uint8_t stop_ = (count == (length - 1)) ? 1 : 0;
emilmont 10:3bc89ef62ce7 239 if (i2c_do_read(obj, ptr, stop_)) {
emilmont 10:3bc89ef62ce7 240 i2c_stop(obj);
emilmont 10:3bc89ef62ce7 241 return 1;
emilmont 10:3bc89ef62ce7 242 }
emilmont 10:3bc89ef62ce7 243 }
emilmont 10:3bc89ef62ce7 244
emilmont 10:3bc89ef62ce7 245 // If not repeated start, send stop.
emilmont 10:3bc89ef62ce7 246 if (stop) {
emilmont 10:3bc89ef62ce7 247 i2c_stop(obj);
emilmont 10:3bc89ef62ce7 248 }
emilmont 10:3bc89ef62ce7 249
emilmont 10:3bc89ef62ce7 250 // last read
emilmont 10:3bc89ef62ce7 251 data[count-1] = obj->i2c->D;
emilmont 10:3bc89ef62ce7 252
emilmont 10:3bc89ef62ce7 253 return 0;
emilmont 10:3bc89ef62ce7 254 }
emilmont 10:3bc89ef62ce7 255 int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop) {
emilmont 10:3bc89ef62ce7 256 int i;
emilmont 10:3bc89ef62ce7 257
emilmont 10:3bc89ef62ce7 258 if (i2c_start(obj)) {
emilmont 10:3bc89ef62ce7 259 i2c_stop(obj);
emilmont 10:3bc89ef62ce7 260 return 1;
emilmont 10:3bc89ef62ce7 261 }
emilmont 10:3bc89ef62ce7 262
emilmont 10:3bc89ef62ce7 263 if (i2c_do_write(obj, (address & 0xFE))) {
emilmont 10:3bc89ef62ce7 264 i2c_stop(obj);
emilmont 10:3bc89ef62ce7 265 return 1;
emilmont 10:3bc89ef62ce7 266 }
emilmont 10:3bc89ef62ce7 267
emilmont 10:3bc89ef62ce7 268 for (i = 0; i < length; i++) {
emilmont 10:3bc89ef62ce7 269 if(i2c_do_write(obj, data[i])) {
emilmont 10:3bc89ef62ce7 270 i2c_stop(obj);
emilmont 10:3bc89ef62ce7 271 return 1;
emilmont 10:3bc89ef62ce7 272 }
emilmont 10:3bc89ef62ce7 273 }
emilmont 10:3bc89ef62ce7 274
emilmont 10:3bc89ef62ce7 275 if (stop) {
emilmont 10:3bc89ef62ce7 276 i2c_stop(obj);
emilmont 10:3bc89ef62ce7 277 }
emilmont 10:3bc89ef62ce7 278
emilmont 10:3bc89ef62ce7 279 return 0;
emilmont 10:3bc89ef62ce7 280 }
emilmont 10:3bc89ef62ce7 281
emilmont 10:3bc89ef62ce7 282 void i2c_reset(i2c_t *obj) {
emilmont 10:3bc89ef62ce7 283 i2c_stop(obj);
emilmont 10:3bc89ef62ce7 284 }
emilmont 10:3bc89ef62ce7 285
emilmont 10:3bc89ef62ce7 286 int i2c_byte_read(i2c_t *obj, int last) {
emilmont 10:3bc89ef62ce7 287 char data;
emilmont 10:3bc89ef62ce7 288
emilmont 10:3bc89ef62ce7 289 // set rx mode
emilmont 10:3bc89ef62ce7 290 obj->i2c->C1 &= ~I2C_C1_TX_MASK;
emilmont 10:3bc89ef62ce7 291
emilmont 10:3bc89ef62ce7 292 if(first_read) {
emilmont 10:3bc89ef62ce7 293 // first dummy read
emilmont 10:3bc89ef62ce7 294 i2c_do_read(obj, &data, 0);
emilmont 10:3bc89ef62ce7 295 first_read = 0;
emilmont 10:3bc89ef62ce7 296 }
emilmont 10:3bc89ef62ce7 297
emilmont 10:3bc89ef62ce7 298 if (last) {
emilmont 10:3bc89ef62ce7 299 // set tx mode
emilmont 10:3bc89ef62ce7 300 obj->i2c->C1 |= I2C_C1_TX_MASK;
emilmont 10:3bc89ef62ce7 301 return obj->i2c->D;
emilmont 10:3bc89ef62ce7 302 }
emilmont 10:3bc89ef62ce7 303
emilmont 10:3bc89ef62ce7 304 i2c_do_read(obj, &data, last);
emilmont 10:3bc89ef62ce7 305
emilmont 10:3bc89ef62ce7 306 return data;
emilmont 10:3bc89ef62ce7 307 }
emilmont 10:3bc89ef62ce7 308
emilmont 10:3bc89ef62ce7 309 int i2c_byte_write(i2c_t *obj, int data) {
emilmont 10:3bc89ef62ce7 310 first_read = 1;
emilmont 10:3bc89ef62ce7 311
emilmont 10:3bc89ef62ce7 312 // set tx mode
emilmont 10:3bc89ef62ce7 313 obj->i2c->C1 |= I2C_C1_TX_MASK;
emilmont 10:3bc89ef62ce7 314
emilmont 10:3bc89ef62ce7 315 return !i2c_do_write(obj, (data & 0xFF));
emilmont 10:3bc89ef62ce7 316 }
emilmont 10:3bc89ef62ce7 317
emilmont 10:3bc89ef62ce7 318
emilmont 10:3bc89ef62ce7 319 #if DEVICE_I2CSLAVE
emilmont 10:3bc89ef62ce7 320 void i2c_slave_mode(i2c_t *obj, int enable_slave) {
emilmont 10:3bc89ef62ce7 321 if (enable_slave) {
emilmont 10:3bc89ef62ce7 322 // set slave mode
emilmont 10:3bc89ef62ce7 323 obj->i2c->C1 &= ~I2C_C1_MST_MASK;
emilmont 10:3bc89ef62ce7 324 obj->i2c->C1 |= I2C_C1_IICIE_MASK;
emilmont 10:3bc89ef62ce7 325 } else {
emilmont 10:3bc89ef62ce7 326 // set master mode
emilmont 10:3bc89ef62ce7 327 obj->i2c->C1 |= I2C_C1_MST_MASK;
emilmont 10:3bc89ef62ce7 328 }
emilmont 10:3bc89ef62ce7 329 }
emilmont 10:3bc89ef62ce7 330
emilmont 10:3bc89ef62ce7 331 int i2c_slave_receive(i2c_t *obj) {
emilmont 10:3bc89ef62ce7 332 switch(obj->i2c->S) {
emilmont 10:3bc89ef62ce7 333 // read addressed
emilmont 10:3bc89ef62ce7 334 case 0xE6: return 1;
emilmont 10:3bc89ef62ce7 335
emilmont 10:3bc89ef62ce7 336 // write addressed
emilmont 10:3bc89ef62ce7 337 case 0xE2: return 3;
emilmont 10:3bc89ef62ce7 338
emilmont 10:3bc89ef62ce7 339 default: return 0;
emilmont 10:3bc89ef62ce7 340 }
emilmont 10:3bc89ef62ce7 341 }
emilmont 10:3bc89ef62ce7 342
emilmont 10:3bc89ef62ce7 343 int i2c_slave_read(i2c_t *obj, char *data, int length) {
emilmont 10:3bc89ef62ce7 344 uint8_t dummy_read, count;
emilmont 10:3bc89ef62ce7 345 uint8_t * ptr;
emilmont 10:3bc89ef62ce7 346
emilmont 10:3bc89ef62ce7 347 // set rx mode
emilmont 10:3bc89ef62ce7 348 obj->i2c->C1 &= ~I2C_C1_TX_MASK;
emilmont 10:3bc89ef62ce7 349
emilmont 10:3bc89ef62ce7 350 // first dummy read
emilmont 10:3bc89ef62ce7 351 dummy_read = obj->i2c->D;
emilmont 10:3bc89ef62ce7 352 if(i2c_wait_end_rx_transfer(obj)) {
emilmont 10:3bc89ef62ce7 353 return 0;
emilmont 10:3bc89ef62ce7 354 }
emilmont 10:3bc89ef62ce7 355
emilmont 10:3bc89ef62ce7 356 // read address
emilmont 10:3bc89ef62ce7 357 dummy_read = obj->i2c->D;
emilmont 10:3bc89ef62ce7 358 if(i2c_wait_end_rx_transfer(obj)) {
emilmont 10:3bc89ef62ce7 359 return 0;
emilmont 10:3bc89ef62ce7 360 }
emilmont 10:3bc89ef62ce7 361
emilmont 10:3bc89ef62ce7 362 // read (length - 1) bytes
emilmont 10:3bc89ef62ce7 363 for (count = 0; count < (length - 1); count++) {
emilmont 10:3bc89ef62ce7 364 data[count] = obj->i2c->D;
emilmont 10:3bc89ef62ce7 365 if(i2c_wait_end_rx_transfer(obj)) {
emilmont 10:3bc89ef62ce7 366 return 0;
emilmont 10:3bc89ef62ce7 367 }
emilmont 10:3bc89ef62ce7 368 }
emilmont 10:3bc89ef62ce7 369
emilmont 10:3bc89ef62ce7 370 // read last byte
emilmont 10:3bc89ef62ce7 371 ptr = (length == 0) ? &dummy_read : (uint8_t *)&data[count];
emilmont 10:3bc89ef62ce7 372 *ptr = obj->i2c->D;
emilmont 10:3bc89ef62ce7 373
emilmont 10:3bc89ef62ce7 374 return (length) ? (count + 1) : 0;
emilmont 10:3bc89ef62ce7 375 }
emilmont 10:3bc89ef62ce7 376
emilmont 10:3bc89ef62ce7 377 int i2c_slave_write(i2c_t *obj, const char *data, int length) {
emilmont 10:3bc89ef62ce7 378 uint32_t i, count = 0;
emilmont 10:3bc89ef62ce7 379
emilmont 10:3bc89ef62ce7 380 // set tx mode
emilmont 10:3bc89ef62ce7 381 obj->i2c->C1 |= I2C_C1_TX_MASK;
emilmont 10:3bc89ef62ce7 382
emilmont 10:3bc89ef62ce7 383 for (i = 0; i < length; i++) {
emilmont 10:3bc89ef62ce7 384 if(i2c_do_write(obj, data[count++]) == 2) {
emilmont 10:3bc89ef62ce7 385 return 0;
emilmont 10:3bc89ef62ce7 386 }
emilmont 10:3bc89ef62ce7 387 }
emilmont 10:3bc89ef62ce7 388
emilmont 10:3bc89ef62ce7 389 // set rx mode
emilmont 10:3bc89ef62ce7 390 obj->i2c->C1 &= ~I2C_C1_TX_MASK;
emilmont 10:3bc89ef62ce7 391
emilmont 10:3bc89ef62ce7 392 // dummy rx transfer needed
emilmont 10:3bc89ef62ce7 393 // otherwise the master cannot generate a stop bit
emilmont 10:3bc89ef62ce7 394 obj->i2c->D;
emilmont 10:3bc89ef62ce7 395 if(i2c_wait_end_rx_transfer(obj) == 2) {
emilmont 10:3bc89ef62ce7 396 return 0;
emilmont 10:3bc89ef62ce7 397 }
emilmont 10:3bc89ef62ce7 398
emilmont 10:3bc89ef62ce7 399 return count;
emilmont 10:3bc89ef62ce7 400 }
emilmont 10:3bc89ef62ce7 401
emilmont 10:3bc89ef62ce7 402 void i2c_slave_address(i2c_t *obj, int idx, uint32_t address, uint32_t mask) {
emilmont 10:3bc89ef62ce7 403 obj->i2c->A1 = address & 0xfe;
emilmont 10:3bc89ef62ce7 404 }
emilmont 10:3bc89ef62ce7 405 #endif
emilmont 10:3bc89ef62ce7 406