mbed library sources. Supersedes mbed-src.

Dependents:   BREAK_SENSOR_LED

Fork of mbed-dev by mbed official

Committer:
<>
Date:
Fri Oct 28 11:17:30 2016 +0100
Revision:
149:156823d33999
Parent:
targets/hal/TARGET_Freescale/TARGET_KLXX/i2c_api.c@144:ef7eb2e8f9f7
This updates the lib to the mbed lib v128

NOTE: This release includes a restructuring of the file and directory locations and thus some
include paths in your code may need updating accordingly.

Who changed what in which revision?

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