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