added prescaler for 16 bit pwm in LPC1347 target

Fork of mbed-dev by mbed official

Committer:
bogdanm
Date:
Thu Oct 01 15:25:22 2015 +0300
Revision:
0:9b334a45a8ff
Child:
144:ef7eb2e8f9f7
Initial commit on mbed-dev

Replaces mbed-src (now inactive)

Who changed what in which revision?

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