mbed-os

Dependents:   cobaLCDJoyMotor_Thread odometry_omni_3roda_v3 odometry_omni_3roda_v1 odometry_omni_3roda_v2 ... more

Committer:
be_bryan
Date:
Mon Dec 11 17:54:04 2017 +0000
Revision:
0:b74591d5ab33
motor ++

Who changed what in which revision?

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