mbed library sources

Dependents:   FRDM-KL46Z_LCD_Test FRDM-KL46Z_LCD_Test FRDM-KL46Z_Plantilla FRDM-KL46Z_Plantilla ... more

Committer:
ebrus
Date:
Thu Jul 28 15:56:34 2016 +0000
Revision:
0:6bc4ac881c8e
1;

Who changed what in which revision?

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