Mouse code for the MacroRat

Dependencies:   ITG3200 QEI

Committer:
sahilmgandhi
Date:
Sun May 14 23:18:57 2017 +0000
Revision:
18:6a4db94011d3
Publishing again

Who changed what in which revision?

UserRevisionLine numberNew contents of line
sahilmgandhi 18:6a4db94011d3 1 /* mbed Microcontroller Library
sahilmgandhi 18:6a4db94011d3 2 * Copyright (c) 2015 ARM Limited
sahilmgandhi 18:6a4db94011d3 3 *
sahilmgandhi 18:6a4db94011d3 4 * Licensed under the Apache License, Version 2.0 (the "License");
sahilmgandhi 18:6a4db94011d3 5 * you may not use this file except in compliance with the License.
sahilmgandhi 18:6a4db94011d3 6 * You may obtain a copy of the License at
sahilmgandhi 18:6a4db94011d3 7 *
sahilmgandhi 18:6a4db94011d3 8 * http://www.apache.org/licenses/LICENSE-2.0
sahilmgandhi 18:6a4db94011d3 9 *
sahilmgandhi 18:6a4db94011d3 10 * Unless required by applicable law or agreed to in writing, software
sahilmgandhi 18:6a4db94011d3 11 * distributed under the License is distributed on an "AS IS" BASIS,
sahilmgandhi 18:6a4db94011d3 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
sahilmgandhi 18:6a4db94011d3 13 * See the License for the specific language governing permissions and
sahilmgandhi 18:6a4db94011d3 14 * limitations under the License.
sahilmgandhi 18:6a4db94011d3 15 */
sahilmgandhi 18:6a4db94011d3 16 #include "i2c_api.h"
sahilmgandhi 18:6a4db94011d3 17 #include "i2c_def.h"
sahilmgandhi 18:6a4db94011d3 18 #include "cmsis.h"
sahilmgandhi 18:6a4db94011d3 19 #include "pinmap.h"
sahilmgandhi 18:6a4db94011d3 20 #include "mbed_error.h"
sahilmgandhi 18:6a4db94011d3 21 #include "mbed_wait_api.h"
sahilmgandhi 18:6a4db94011d3 22 /* States of a possibly combined I2C transfer */
sahilmgandhi 18:6a4db94011d3 23 typedef enum i2c_transfer_state_t {
sahilmgandhi 18:6a4db94011d3 24 I2C_TRANSFER_SINGLE, /* Non combined transfer */
sahilmgandhi 18:6a4db94011d3 25 I2C_TRANSFER_COMBINED_FIRST_MESSAGE, /*
sahilmgandhi 18:6a4db94011d3 26 * First message of a
sahilmgandhi 18:6a4db94011d3 27 * combined transfer
sahilmgandhi 18:6a4db94011d3 28 */
sahilmgandhi 18:6a4db94011d3 29 I2C_TRANSFER_COMBINED_INTERMEDIATE_MESSAGE, /*
sahilmgandhi 18:6a4db94011d3 30 * Message in the middle
sahilmgandhi 18:6a4db94011d3 31 * of a combined
sahilmgandhi 18:6a4db94011d3 32 * transfer
sahilmgandhi 18:6a4db94011d3 33 */
sahilmgandhi 18:6a4db94011d3 34 I2C_TRANSFER_COMBINED_LAST_MESSAGE, /*
sahilmgandhi 18:6a4db94011d3 35 * Last message of a combined
sahilmgandhi 18:6a4db94011d3 36 * transfer
sahilmgandhi 18:6a4db94011d3 37 */
sahilmgandhi 18:6a4db94011d3 38 } i2c_transfer_state_t;
sahilmgandhi 18:6a4db94011d3 39
sahilmgandhi 18:6a4db94011d3 40 /*
sahilmgandhi 18:6a4db94011d3 41 * Driver private data structure that should not be shared by multiple
sahilmgandhi 18:6a4db94011d3 42 * instances of the driver
sahilmgandhi 18:6a4db94011d3 43 * (same driver for multiple instances of the IP)
sahilmgandhi 18:6a4db94011d3 44 */
sahilmgandhi 18:6a4db94011d3 45 typedef struct private_i2c_t {
sahilmgandhi 18:6a4db94011d3 46 /* State of a possibly combined ongoing i2c transfer */
sahilmgandhi 18:6a4db94011d3 47 i2c_transfer_state_t transfer_state;
sahilmgandhi 18:6a4db94011d3 48 }private_i2c_t;
sahilmgandhi 18:6a4db94011d3 49
sahilmgandhi 18:6a4db94011d3 50
sahilmgandhi 18:6a4db94011d3 51 /*
sahilmgandhi 18:6a4db94011d3 52 * Retrieve the private data of the instance related to a given IP
sahilmgandhi 18:6a4db94011d3 53 */
sahilmgandhi 18:6a4db94011d3 54 static private_i2c_t* get_i2c_private(i2c_t *obj) {
sahilmgandhi 18:6a4db94011d3 55 static private_i2c_t data0, data1;
sahilmgandhi 18:6a4db94011d3 56 /*
sahilmgandhi 18:6a4db94011d3 57 * Select which instance to give using the base
sahilmgandhi 18:6a4db94011d3 58 * address of registers
sahilmgandhi 18:6a4db94011d3 59 */
sahilmgandhi 18:6a4db94011d3 60 switch((intptr_t)obj->i2c) {
sahilmgandhi 18:6a4db94011d3 61 case I2C0_BASE:
sahilmgandhi 18:6a4db94011d3 62 return &data0;
sahilmgandhi 18:6a4db94011d3 63 case I2C1_BASE:
sahilmgandhi 18:6a4db94011d3 64 return &data1;
sahilmgandhi 18:6a4db94011d3 65 default:
sahilmgandhi 18:6a4db94011d3 66 error("i2c driver private data structure not found for this registers base address");
sahilmgandhi 18:6a4db94011d3 67 return (void*)0;
sahilmgandhi 18:6a4db94011d3 68 }
sahilmgandhi 18:6a4db94011d3 69 }
sahilmgandhi 18:6a4db94011d3 70
sahilmgandhi 18:6a4db94011d3 71 /*
sahilmgandhi 18:6a4db94011d3 72 * Infer the current state of a possibly combined transfer
sahilmgandhi 18:6a4db94011d3 73 * (repeated restart) from the current state and the "stop" parameter
sahilmgandhi 18:6a4db94011d3 74 * of read and write functions
sahilmgandhi 18:6a4db94011d3 75 * MUST be called ONCE AND ONLY ONCE at the beginning of i2c transfer
sahilmgandhi 18:6a4db94011d3 76 * functions (read and write)
sahilmgandhi 18:6a4db94011d3 77 */
sahilmgandhi 18:6a4db94011d3 78 static i2c_transfer_state_t update_transfer_state(i2c_t *obj, int stop) {
sahilmgandhi 18:6a4db94011d3 79 private_i2c_t* private_data = get_i2c_private(obj);
sahilmgandhi 18:6a4db94011d3 80 i2c_transfer_state_t *state = &private_data->transfer_state;
sahilmgandhi 18:6a4db94011d3 81
sahilmgandhi 18:6a4db94011d3 82 /*
sahilmgandhi 18:6a4db94011d3 83 * Choose the current and next state depending on the current state
sahilmgandhi 18:6a4db94011d3 84 * This basically implements rising and falling edge detection on
sahilmgandhi 18:6a4db94011d3 85 * "stop" variable
sahilmgandhi 18:6a4db94011d3 86 */
sahilmgandhi 18:6a4db94011d3 87 switch(*state) {
sahilmgandhi 18:6a4db94011d3 88 /* This is the default state for non restarted repeat transfer */
sahilmgandhi 18:6a4db94011d3 89 default:
sahilmgandhi 18:6a4db94011d3 90 case I2C_TRANSFER_SINGLE: /* Not a combined transfer */
sahilmgandhi 18:6a4db94011d3 91 if (stop) {
sahilmgandhi 18:6a4db94011d3 92 *state = I2C_TRANSFER_SINGLE;
sahilmgandhi 18:6a4db94011d3 93 } else {
sahilmgandhi 18:6a4db94011d3 94 *state = I2C_TRANSFER_COMBINED_FIRST_MESSAGE;
sahilmgandhi 18:6a4db94011d3 95 }
sahilmgandhi 18:6a4db94011d3 96 break;
sahilmgandhi 18:6a4db94011d3 97
sahilmgandhi 18:6a4db94011d3 98 /* First message of a combined transfer */
sahilmgandhi 18:6a4db94011d3 99 case I2C_TRANSFER_COMBINED_FIRST_MESSAGE:
sahilmgandhi 18:6a4db94011d3 100 /* Message in the middle of a combined transfer */
sahilmgandhi 18:6a4db94011d3 101 case I2C_TRANSFER_COMBINED_INTERMEDIATE_MESSAGE:
sahilmgandhi 18:6a4db94011d3 102 if (stop) {
sahilmgandhi 18:6a4db94011d3 103 *state = I2C_TRANSFER_COMBINED_LAST_MESSAGE;
sahilmgandhi 18:6a4db94011d3 104 } else {
sahilmgandhi 18:6a4db94011d3 105 *state = I2C_TRANSFER_COMBINED_INTERMEDIATE_MESSAGE;
sahilmgandhi 18:6a4db94011d3 106 }
sahilmgandhi 18:6a4db94011d3 107 break;
sahilmgandhi 18:6a4db94011d3 108
sahilmgandhi 18:6a4db94011d3 109 /* Last message of a combined transfer */
sahilmgandhi 18:6a4db94011d3 110 case I2C_TRANSFER_COMBINED_LAST_MESSAGE:
sahilmgandhi 18:6a4db94011d3 111 if (stop) {
sahilmgandhi 18:6a4db94011d3 112 *state = I2C_TRANSFER_SINGLE;
sahilmgandhi 18:6a4db94011d3 113 } else {
sahilmgandhi 18:6a4db94011d3 114 *state = I2C_TRANSFER_COMBINED_FIRST_MESSAGE;
sahilmgandhi 18:6a4db94011d3 115 }
sahilmgandhi 18:6a4db94011d3 116 break;
sahilmgandhi 18:6a4db94011d3 117 }
sahilmgandhi 18:6a4db94011d3 118
sahilmgandhi 18:6a4db94011d3 119 return *state;
sahilmgandhi 18:6a4db94011d3 120 }
sahilmgandhi 18:6a4db94011d3 121
sahilmgandhi 18:6a4db94011d3 122
sahilmgandhi 18:6a4db94011d3 123 static const PinMap PinMap_I2C_SDA[] = {
sahilmgandhi 18:6a4db94011d3 124 {SHIELD_SDA, I2C_0, 0},
sahilmgandhi 18:6a4db94011d3 125 {SENSOR_SDA, I2C_1, 0},
sahilmgandhi 18:6a4db94011d3 126 {NC, NC , 0}
sahilmgandhi 18:6a4db94011d3 127 };
sahilmgandhi 18:6a4db94011d3 128
sahilmgandhi 18:6a4db94011d3 129 static const PinMap PinMap_I2C_SCL[] = {
sahilmgandhi 18:6a4db94011d3 130 {SHIELD_SCL, I2C_0, 0},
sahilmgandhi 18:6a4db94011d3 131 {SENSOR_SCL, I2C_1, 0},
sahilmgandhi 18:6a4db94011d3 132 {NC, NC, 0}
sahilmgandhi 18:6a4db94011d3 133 };
sahilmgandhi 18:6a4db94011d3 134
sahilmgandhi 18:6a4db94011d3 135 static void clear_isr(i2c_t *obj) {
sahilmgandhi 18:6a4db94011d3 136 /*
sahilmgandhi 18:6a4db94011d3 137 * Writing to the IRQ status register clears set bits. Therefore, to
sahilmgandhi 18:6a4db94011d3 138 * clear indiscriminately, just read the register and write it back.
sahilmgandhi 18:6a4db94011d3 139 */
sahilmgandhi 18:6a4db94011d3 140 uint32_t reg = obj->i2c->IRQ_STATUS;
sahilmgandhi 18:6a4db94011d3 141 obj->i2c->IRQ_STATUS = reg;
sahilmgandhi 18:6a4db94011d3 142 }
sahilmgandhi 18:6a4db94011d3 143
sahilmgandhi 18:6a4db94011d3 144 void i2c_init(i2c_t *obj, PinName sda, PinName scl) {
sahilmgandhi 18:6a4db94011d3 145 /* Determine the I2C to use */
sahilmgandhi 18:6a4db94011d3 146 I2CName i2c_sda = (I2CName)pinmap_peripheral(sda, PinMap_I2C_SDA);
sahilmgandhi 18:6a4db94011d3 147 I2CName i2c_scl = (I2CName)pinmap_peripheral(scl, PinMap_I2C_SCL);
sahilmgandhi 18:6a4db94011d3 148 obj->i2c = (I2C_TypeDef *)pinmap_merge(i2c_sda, i2c_scl);
sahilmgandhi 18:6a4db94011d3 149
sahilmgandhi 18:6a4db94011d3 150 if ((int)obj->i2c == NC) {
sahilmgandhi 18:6a4db94011d3 151 error("I2C pin mapping failed");
sahilmgandhi 18:6a4db94011d3 152 }
sahilmgandhi 18:6a4db94011d3 153
sahilmgandhi 18:6a4db94011d3 154 pinmap_pinout(sda, PinMap_I2C_SDA);
sahilmgandhi 18:6a4db94011d3 155 pinmap_pinout(scl, PinMap_I2C_SCL);
sahilmgandhi 18:6a4db94011d3 156
sahilmgandhi 18:6a4db94011d3 157 /*
sahilmgandhi 18:6a4db94011d3 158 * Default configuration:
sahilmgandhi 18:6a4db94011d3 159 * - MS : Master mode
sahilmgandhi 18:6a4db94011d3 160 * - NEA : Normal (7-bit) addressing
sahilmgandhi 18:6a4db94011d3 161 * - ACKEN : Send ACKs when reading from slave
sahilmgandhi 18:6a4db94011d3 162 * - CLR_FIFO : Not a configuration bit => clears the FIFO
sahilmgandhi 18:6a4db94011d3 163 */
sahilmgandhi 18:6a4db94011d3 164 uint32_t reg = I2C_CTRL_MS | \
sahilmgandhi 18:6a4db94011d3 165 I2C_CTRL_NEA | \
sahilmgandhi 18:6a4db94011d3 166 I2C_CTRL_ACKEN | \
sahilmgandhi 18:6a4db94011d3 167 I2C_CTRL_CLR_FIFO;
sahilmgandhi 18:6a4db94011d3 168
sahilmgandhi 18:6a4db94011d3 169 obj->i2c->CONTROL = reg;
sahilmgandhi 18:6a4db94011d3 170
sahilmgandhi 18:6a4db94011d3 171 get_i2c_private(obj)->transfer_state = I2C_TRANSFER_SINGLE;
sahilmgandhi 18:6a4db94011d3 172
sahilmgandhi 18:6a4db94011d3 173 i2c_frequency(obj, 100000); /* Default to 100kHz SCL frequency */
sahilmgandhi 18:6a4db94011d3 174 }
sahilmgandhi 18:6a4db94011d3 175
sahilmgandhi 18:6a4db94011d3 176 int i2c_start(i2c_t *obj) {
sahilmgandhi 18:6a4db94011d3 177 return 0;
sahilmgandhi 18:6a4db94011d3 178 }
sahilmgandhi 18:6a4db94011d3 179
sahilmgandhi 18:6a4db94011d3 180 int i2c_stop(i2c_t *obj) {
sahilmgandhi 18:6a4db94011d3 181 /* Clear the hardware FIFO */
sahilmgandhi 18:6a4db94011d3 182 obj->i2c->CONTROL |= I2C_CTRL_CLR_FIFO;
sahilmgandhi 18:6a4db94011d3 183 /* Clear the HOLD bit used for performing combined transfers */
sahilmgandhi 18:6a4db94011d3 184 obj->i2c->CONTROL &= ~I2C_CTRL_HOLD;
sahilmgandhi 18:6a4db94011d3 185 /* Reset the transfer size (read and write) */
sahilmgandhi 18:6a4db94011d3 186 obj->i2c->TRANSFER_SIZE = 0;
sahilmgandhi 18:6a4db94011d3 187 /* Clear interrupts */
sahilmgandhi 18:6a4db94011d3 188 clear_isr(obj);
sahilmgandhi 18:6a4db94011d3 189 return 0;
sahilmgandhi 18:6a4db94011d3 190 }
sahilmgandhi 18:6a4db94011d3 191
sahilmgandhi 18:6a4db94011d3 192 void i2c_frequency(i2c_t *obj, int hz) {
sahilmgandhi 18:6a4db94011d3 193 /*
sahilmgandhi 18:6a4db94011d3 194 * Divider is split in two halfs : A and B
sahilmgandhi 18:6a4db94011d3 195 * A is 2 bits wide and B is 6 bits wide
sahilmgandhi 18:6a4db94011d3 196 * The Fscl frequency (SCL clock) is calculated with the following
sahilmgandhi 18:6a4db94011d3 197 * equation:
sahilmgandhi 18:6a4db94011d3 198 * Fscl=SystemCoreClock/(22*(A+1)*(B+1))
sahilmgandhi 18:6a4db94011d3 199 * Here, we only calculate the B divisor which already enables a
sahilmgandhi 18:6a4db94011d3 200 * wide enough range of values
sahilmgandhi 18:6a4db94011d3 201 */
sahilmgandhi 18:6a4db94011d3 202 uint32_t divisor_a = 0; /* Could be changed if a wider range of hz
sahilmgandhi 18:6a4db94011d3 203 is needed */
sahilmgandhi 18:6a4db94011d3 204 uint32_t divisor_b = (SystemCoreClock / (22.0 * hz)) - 1;
sahilmgandhi 18:6a4db94011d3 205
sahilmgandhi 18:6a4db94011d3 206 /* Clamp the divisors to their maximal value */
sahilmgandhi 18:6a4db94011d3 207 divisor_a = divisor_a > I2C_CTRL_DIVISOR_A_BIT_MASK ?
sahilmgandhi 18:6a4db94011d3 208 I2C_CTRL_DIVISOR_A_BIT_MASK : divisor_a;
sahilmgandhi 18:6a4db94011d3 209 divisor_b = divisor_b > I2C_CTRL_DIVISOR_B_BIT_MASK ?
sahilmgandhi 18:6a4db94011d3 210 I2C_CTRL_DIVISOR_B_BIT_MASK : divisor_b;
sahilmgandhi 18:6a4db94011d3 211
sahilmgandhi 18:6a4db94011d3 212 uint8_t divisor_combinded = (divisor_a & I2C_CTRL_DIVISOR_A_BIT_MASK)
sahilmgandhi 18:6a4db94011d3 213 | (divisor_b & I2C_CTRL_DIVISOR_B_BIT_MASK);
sahilmgandhi 18:6a4db94011d3 214
sahilmgandhi 18:6a4db94011d3 215 obj->i2c->CONTROL = (obj->i2c->CONTROL & ~I2C_CTRL_DIVISORS)
sahilmgandhi 18:6a4db94011d3 216 | (divisor_combinded << I2C_CTRL_DIVISOR_OFFSET);
sahilmgandhi 18:6a4db94011d3 217 }
sahilmgandhi 18:6a4db94011d3 218
sahilmgandhi 18:6a4db94011d3 219 int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) {
sahilmgandhi 18:6a4db94011d3 220 int bytes_read = 0;
sahilmgandhi 18:6a4db94011d3 221 int length_backup = length;
sahilmgandhi 18:6a4db94011d3 222 char *data_backup = data;
sahilmgandhi 18:6a4db94011d3 223 obj->last_xfer_address = address;
sahilmgandhi 18:6a4db94011d3 224 i2c_transfer_state_t transfer_state = update_transfer_state(obj, stop);
sahilmgandhi 18:6a4db94011d3 225
sahilmgandhi 18:6a4db94011d3 226 /* Try to write until it finally succeed or times out */
sahilmgandhi 18:6a4db94011d3 227 int main_timeout = 10;
sahilmgandhi 18:6a4db94011d3 228 int retry = 0;
sahilmgandhi 18:6a4db94011d3 229 do {
sahilmgandhi 18:6a4db94011d3 230 main_timeout--;
sahilmgandhi 18:6a4db94011d3 231
sahilmgandhi 18:6a4db94011d3 232 retry = 0;
sahilmgandhi 18:6a4db94011d3 233 bytes_read = 0;
sahilmgandhi 18:6a4db94011d3 234 length = length_backup;
sahilmgandhi 18:6a4db94011d3 235 data = data_backup;
sahilmgandhi 18:6a4db94011d3 236
sahilmgandhi 18:6a4db94011d3 237 uint32_t reg = obj->i2c->CONTROL & 0xff7f;
sahilmgandhi 18:6a4db94011d3 238 reg |= I2C_CTRL_RW | \
sahilmgandhi 18:6a4db94011d3 239 I2C_CTRL_CLR_FIFO;
sahilmgandhi 18:6a4db94011d3 240 /*
sahilmgandhi 18:6a4db94011d3 241 * Only touch the HOLD bit at the beginning of
sahilmgandhi 18:6a4db94011d3 242 * (possibly combined) transactions
sahilmgandhi 18:6a4db94011d3 243 */
sahilmgandhi 18:6a4db94011d3 244 if(transfer_state == I2C_TRANSFER_COMBINED_FIRST_MESSAGE
sahilmgandhi 18:6a4db94011d3 245 || transfer_state == I2C_TRANSFER_SINGLE) {
sahilmgandhi 18:6a4db94011d3 246
sahilmgandhi 18:6a4db94011d3 247 reg |= I2C_CTRL_HOLD;
sahilmgandhi 18:6a4db94011d3 248 }
sahilmgandhi 18:6a4db94011d3 249 obj->i2c->CONTROL = reg;
sahilmgandhi 18:6a4db94011d3 250
sahilmgandhi 18:6a4db94011d3 251 /* Set the expected number of bytes to be received */
sahilmgandhi 18:6a4db94011d3 252 if (length > I2C_TRANSFER_SIZE) {
sahilmgandhi 18:6a4db94011d3 253 error("I2C transfer size too big for the FIFO");
sahilmgandhi 18:6a4db94011d3 254 }
sahilmgandhi 18:6a4db94011d3 255 obj->i2c->TRANSFER_SIZE = length & I2C_TRANSFER_SIZE;
sahilmgandhi 18:6a4db94011d3 256
sahilmgandhi 18:6a4db94011d3 257 clear_isr(obj);
sahilmgandhi 18:6a4db94011d3 258
sahilmgandhi 18:6a4db94011d3 259 /*
sahilmgandhi 18:6a4db94011d3 260 * Start the transaction by writing address.
sahilmgandhi 18:6a4db94011d3 261 * Discard the lower bit as it is automatically set
sahilmgandhi 18:6a4db94011d3 262 * by the controller based on I2C_CTRL_RW bit in CONTROL
sahilmgandhi 18:6a4db94011d3 263 * register
sahilmgandhi 18:6a4db94011d3 264 */
sahilmgandhi 18:6a4db94011d3 265 obj->i2c->ADDRESS = (address & 0xFF) >> 1;
sahilmgandhi 18:6a4db94011d3 266
sahilmgandhi 18:6a4db94011d3 267 if(transfer_state == I2C_TRANSFER_COMBINED_LAST_MESSAGE
sahilmgandhi 18:6a4db94011d3 268 || transfer_state == I2C_TRANSFER_SINGLE) {
sahilmgandhi 18:6a4db94011d3 269
sahilmgandhi 18:6a4db94011d3 270 /* Clear the hold bit before reading the DATA register */
sahilmgandhi 18:6a4db94011d3 271 obj->i2c->CONTROL &= ~I2C_CTRL_HOLD;
sahilmgandhi 18:6a4db94011d3 272 }
sahilmgandhi 18:6a4db94011d3 273
sahilmgandhi 18:6a4db94011d3 274 /* Wait for completion of the address transfer */
sahilmgandhi 18:6a4db94011d3 275 int completion_timeout = 1000;
sahilmgandhi 18:6a4db94011d3 276 while (completion_timeout) {
sahilmgandhi 18:6a4db94011d3 277 completion_timeout--;
sahilmgandhi 18:6a4db94011d3 278
sahilmgandhi 18:6a4db94011d3 279 uint32_t irq_status = obj->i2c->IRQ_STATUS;
sahilmgandhi 18:6a4db94011d3 280 if (irq_status & I2C_IRQ_NACK
sahilmgandhi 18:6a4db94011d3 281 || irq_status & I2C_IRQ_ARB_LOST) {
sahilmgandhi 18:6a4db94011d3 282
sahilmgandhi 18:6a4db94011d3 283 retry = 1;
sahilmgandhi 18:6a4db94011d3 284 break;
sahilmgandhi 18:6a4db94011d3 285 }
sahilmgandhi 18:6a4db94011d3 286
sahilmgandhi 18:6a4db94011d3 287 if(irq_status & I2C_IRQ_COMP) {
sahilmgandhi 18:6a4db94011d3 288 break;
sahilmgandhi 18:6a4db94011d3 289 }
sahilmgandhi 18:6a4db94011d3 290 }
sahilmgandhi 18:6a4db94011d3 291
sahilmgandhi 18:6a4db94011d3 292 /* If retry, jump to the beginning and try again */
sahilmgandhi 18:6a4db94011d3 293 if (retry || !completion_timeout) {
sahilmgandhi 18:6a4db94011d3 294 retry = 1;
sahilmgandhi 18:6a4db94011d3 295 continue;
sahilmgandhi 18:6a4db94011d3 296 }
sahilmgandhi 18:6a4db94011d3 297
sahilmgandhi 18:6a4db94011d3 298 clear_isr(obj);
sahilmgandhi 18:6a4db94011d3 299
sahilmgandhi 18:6a4db94011d3 300 /* Read the data from the DATA register */
sahilmgandhi 18:6a4db94011d3 301 completion_timeout = 1000;
sahilmgandhi 18:6a4db94011d3 302 while (length && completion_timeout) {
sahilmgandhi 18:6a4db94011d3 303 completion_timeout--;
sahilmgandhi 18:6a4db94011d3 304
sahilmgandhi 18:6a4db94011d3 305 uint32_t irq_status = obj->i2c->IRQ_STATUS;
sahilmgandhi 18:6a4db94011d3 306 uint32_t status = obj->i2c->STATUS;
sahilmgandhi 18:6a4db94011d3 307
sahilmgandhi 18:6a4db94011d3 308 if(irq_status & I2C_IRQ_NACK ||
sahilmgandhi 18:6a4db94011d3 309 irq_status & I2C_IRQ_ARB_LOST) {
sahilmgandhi 18:6a4db94011d3 310
sahilmgandhi 18:6a4db94011d3 311 retry = 1;
sahilmgandhi 18:6a4db94011d3 312 break;
sahilmgandhi 18:6a4db94011d3 313 }
sahilmgandhi 18:6a4db94011d3 314
sahilmgandhi 18:6a4db94011d3 315 /*
sahilmgandhi 18:6a4db94011d3 316 * Just wait for RXDV because COMP is only risen at the end
sahilmgandhi 18:6a4db94011d3 317 * of the transfer
sahilmgandhi 18:6a4db94011d3 318 */
sahilmgandhi 18:6a4db94011d3 319 if (status & I2C_STATUS_RXDV) {
sahilmgandhi 18:6a4db94011d3 320 *data++ = obj->i2c->DATA & 0xFF;
sahilmgandhi 18:6a4db94011d3 321 length--;
sahilmgandhi 18:6a4db94011d3 322 bytes_read++;
sahilmgandhi 18:6a4db94011d3 323 }
sahilmgandhi 18:6a4db94011d3 324
sahilmgandhi 18:6a4db94011d3 325 if (irq_status & I2C_IRQ_RX_UNF) {
sahilmgandhi 18:6a4db94011d3 326 error("Reading more bytes than the I2C transfer size");
sahilmgandhi 18:6a4db94011d3 327 retry = 1;
sahilmgandhi 18:6a4db94011d3 328 break;
sahilmgandhi 18:6a4db94011d3 329 }
sahilmgandhi 18:6a4db94011d3 330 }
sahilmgandhi 18:6a4db94011d3 331
sahilmgandhi 18:6a4db94011d3 332 /* If retry, jump to the beginning and try again */
sahilmgandhi 18:6a4db94011d3 333 if (retry || !completion_timeout) {
sahilmgandhi 18:6a4db94011d3 334 retry = 1;
sahilmgandhi 18:6a4db94011d3 335 continue;
sahilmgandhi 18:6a4db94011d3 336 }
sahilmgandhi 18:6a4db94011d3 337 } while(retry && main_timeout);
sahilmgandhi 18:6a4db94011d3 338
sahilmgandhi 18:6a4db94011d3 339 if (!main_timeout) {
sahilmgandhi 18:6a4db94011d3 340 bytes_read = 0;
sahilmgandhi 18:6a4db94011d3 341 data = data_backup;
sahilmgandhi 18:6a4db94011d3 342 }
sahilmgandhi 18:6a4db94011d3 343
sahilmgandhi 18:6a4db94011d3 344 obj->i2c->CONTROL |= I2C_CTRL_CLR_FIFO;
sahilmgandhi 18:6a4db94011d3 345 clear_isr(obj);
sahilmgandhi 18:6a4db94011d3 346 return bytes_read;
sahilmgandhi 18:6a4db94011d3 347 }
sahilmgandhi 18:6a4db94011d3 348
sahilmgandhi 18:6a4db94011d3 349 int i2c_write(i2c_t *obj, int address, const char *data, int length,
sahilmgandhi 18:6a4db94011d3 350 int stop) {
sahilmgandhi 18:6a4db94011d3 351
sahilmgandhi 18:6a4db94011d3 352 int bytes_written = 0;
sahilmgandhi 18:6a4db94011d3 353 int length_backup = length;
sahilmgandhi 18:6a4db94011d3 354 const char *data_backup = data;
sahilmgandhi 18:6a4db94011d3 355 obj->last_xfer_address = address;
sahilmgandhi 18:6a4db94011d3 356 i2c_transfer_state_t transfer_state = update_transfer_state(obj, stop);
sahilmgandhi 18:6a4db94011d3 357
sahilmgandhi 18:6a4db94011d3 358 /* Try to write until it finally succeed or times out */
sahilmgandhi 18:6a4db94011d3 359 int main_timeout = 10;
sahilmgandhi 18:6a4db94011d3 360 int retry = 0;
sahilmgandhi 18:6a4db94011d3 361 do {
sahilmgandhi 18:6a4db94011d3 362 main_timeout--;
sahilmgandhi 18:6a4db94011d3 363
sahilmgandhi 18:6a4db94011d3 364 retry = 0;
sahilmgandhi 18:6a4db94011d3 365 bytes_written = 0;
sahilmgandhi 18:6a4db94011d3 366 length = length_backup;
sahilmgandhi 18:6a4db94011d3 367 data = data_backup;
sahilmgandhi 18:6a4db94011d3 368
sahilmgandhi 18:6a4db94011d3 369 /* Read the defined bits in the control register */
sahilmgandhi 18:6a4db94011d3 370 uint32_t reg = obj->i2c->CONTROL & 0xff7f;
sahilmgandhi 18:6a4db94011d3 371 reg |= I2C_CTRL_CLR_FIFO;
sahilmgandhi 18:6a4db94011d3 372 reg &= ~I2C_CTRL_RW;
sahilmgandhi 18:6a4db94011d3 373
sahilmgandhi 18:6a4db94011d3 374 /*
sahilmgandhi 18:6a4db94011d3 375 * Only touch the HOLD bit at the beginning of
sahilmgandhi 18:6a4db94011d3 376 * (possibly combined) transactions
sahilmgandhi 18:6a4db94011d3 377 */
sahilmgandhi 18:6a4db94011d3 378 if(transfer_state == I2C_TRANSFER_COMBINED_FIRST_MESSAGE
sahilmgandhi 18:6a4db94011d3 379 || transfer_state == I2C_TRANSFER_SINGLE) {
sahilmgandhi 18:6a4db94011d3 380
sahilmgandhi 18:6a4db94011d3 381 reg |= I2C_CTRL_HOLD;
sahilmgandhi 18:6a4db94011d3 382 }
sahilmgandhi 18:6a4db94011d3 383 obj->i2c->CONTROL = reg;
sahilmgandhi 18:6a4db94011d3 384
sahilmgandhi 18:6a4db94011d3 385 clear_isr(obj);
sahilmgandhi 18:6a4db94011d3 386
sahilmgandhi 18:6a4db94011d3 387 /* Set the expected number of bytes to be transmitted */
sahilmgandhi 18:6a4db94011d3 388 if (length > I2C_TRANSFER_SIZE) {
sahilmgandhi 18:6a4db94011d3 389 error("I2C transfer size too big for the FIFO");
sahilmgandhi 18:6a4db94011d3 390 }
sahilmgandhi 18:6a4db94011d3 391
sahilmgandhi 18:6a4db94011d3 392 /* Set the expected number of bytes to be transmitted */
sahilmgandhi 18:6a4db94011d3 393 obj->i2c->TRANSFER_SIZE = length & I2C_TRANSFER_SIZE;
sahilmgandhi 18:6a4db94011d3 394
sahilmgandhi 18:6a4db94011d3 395 /*
sahilmgandhi 18:6a4db94011d3 396 * Write the address, triggering the start of the transfer
sahilmgandhi 18:6a4db94011d3 397 * Discard the lower bit as it is automatically set
sahilmgandhi 18:6a4db94011d3 398 * by the controller based on I2C_CTRL_RW bit in CONTROL
sahilmgandhi 18:6a4db94011d3 399 * register
sahilmgandhi 18:6a4db94011d3 400 */
sahilmgandhi 18:6a4db94011d3 401 obj->i2c->ADDRESS = (address & 0xFF) >> 1;
sahilmgandhi 18:6a4db94011d3 402
sahilmgandhi 18:6a4db94011d3 403 /* Send the data bytes */
sahilmgandhi 18:6a4db94011d3 404 int write_timeout = 1000 + length;
sahilmgandhi 18:6a4db94011d3 405 while (length && write_timeout) {
sahilmgandhi 18:6a4db94011d3 406 write_timeout--;
sahilmgandhi 18:6a4db94011d3 407 uint32_t irq_status = obj->i2c->IRQ_STATUS;
sahilmgandhi 18:6a4db94011d3 408 /* If overflow, undo last step */
sahilmgandhi 18:6a4db94011d3 409 if (irq_status & I2C_IRQ_TX_OVF) {
sahilmgandhi 18:6a4db94011d3 410 *data--;
sahilmgandhi 18:6a4db94011d3 411 length++;
sahilmgandhi 18:6a4db94011d3 412 bytes_written--;
sahilmgandhi 18:6a4db94011d3 413 /* Clear the bit by writing 1 to it */
sahilmgandhi 18:6a4db94011d3 414 obj->i2c->IRQ_STATUS |= I2C_IRQ_TX_OVF;
sahilmgandhi 18:6a4db94011d3 415 }
sahilmgandhi 18:6a4db94011d3 416
sahilmgandhi 18:6a4db94011d3 417 if (irq_status & I2C_IRQ_NACK
sahilmgandhi 18:6a4db94011d3 418 || irq_status & I2C_IRQ_ARB_LOST) {
sahilmgandhi 18:6a4db94011d3 419
sahilmgandhi 18:6a4db94011d3 420 retry = 1;
sahilmgandhi 18:6a4db94011d3 421 break;
sahilmgandhi 18:6a4db94011d3 422 }
sahilmgandhi 18:6a4db94011d3 423
sahilmgandhi 18:6a4db94011d3 424 obj->i2c->DATA = *data++;
sahilmgandhi 18:6a4db94011d3 425 length--;
sahilmgandhi 18:6a4db94011d3 426 bytes_written++;
sahilmgandhi 18:6a4db94011d3 427 }
sahilmgandhi 18:6a4db94011d3 428
sahilmgandhi 18:6a4db94011d3 429 /* If retry, jump to the beginning and try again */
sahilmgandhi 18:6a4db94011d3 430 if (retry || !write_timeout) {
sahilmgandhi 18:6a4db94011d3 431 retry = 1;
sahilmgandhi 18:6a4db94011d3 432 continue;
sahilmgandhi 18:6a4db94011d3 433 }
sahilmgandhi 18:6a4db94011d3 434
sahilmgandhi 18:6a4db94011d3 435 if(transfer_state == I2C_TRANSFER_COMBINED_LAST_MESSAGE
sahilmgandhi 18:6a4db94011d3 436 || transfer_state == I2C_TRANSFER_SINGLE) {
sahilmgandhi 18:6a4db94011d3 437 /*
sahilmgandhi 18:6a4db94011d3 438 * Clear the hold bit to signify the end
sahilmgandhi 18:6a4db94011d3 439 * of the write sequence
sahilmgandhi 18:6a4db94011d3 440 */
sahilmgandhi 18:6a4db94011d3 441 obj->i2c->CONTROL &= ~I2C_CTRL_HOLD;
sahilmgandhi 18:6a4db94011d3 442 }
sahilmgandhi 18:6a4db94011d3 443
sahilmgandhi 18:6a4db94011d3 444
sahilmgandhi 18:6a4db94011d3 445 /* Wait for transfer completion */
sahilmgandhi 18:6a4db94011d3 446 int completion_timeout = 1000;
sahilmgandhi 18:6a4db94011d3 447 while (completion_timeout) {
sahilmgandhi 18:6a4db94011d3 448 completion_timeout--;
sahilmgandhi 18:6a4db94011d3 449
sahilmgandhi 18:6a4db94011d3 450 uint32_t irq_status = obj->i2c->IRQ_STATUS;
sahilmgandhi 18:6a4db94011d3 451 if(irq_status & I2C_IRQ_NACK
sahilmgandhi 18:6a4db94011d3 452 || irq_status & I2C_IRQ_ARB_LOST) {
sahilmgandhi 18:6a4db94011d3 453 retry = 1;
sahilmgandhi 18:6a4db94011d3 454 break;
sahilmgandhi 18:6a4db94011d3 455 }
sahilmgandhi 18:6a4db94011d3 456 if(irq_status & I2C_IRQ_COMP) {
sahilmgandhi 18:6a4db94011d3 457 break;
sahilmgandhi 18:6a4db94011d3 458 }
sahilmgandhi 18:6a4db94011d3 459 }
sahilmgandhi 18:6a4db94011d3 460
sahilmgandhi 18:6a4db94011d3 461 /* If retry, jump to the beginning and try again */
sahilmgandhi 18:6a4db94011d3 462 if (retry || !completion_timeout) {
sahilmgandhi 18:6a4db94011d3 463 continue;
sahilmgandhi 18:6a4db94011d3 464 }
sahilmgandhi 18:6a4db94011d3 465
sahilmgandhi 18:6a4db94011d3 466 obj->i2c->CONTROL |= I2C_CTRL_CLR_FIFO;
sahilmgandhi 18:6a4db94011d3 467 clear_isr(obj);
sahilmgandhi 18:6a4db94011d3 468 } while(retry && main_timeout);
sahilmgandhi 18:6a4db94011d3 469
sahilmgandhi 18:6a4db94011d3 470 return bytes_written;
sahilmgandhi 18:6a4db94011d3 471 }
sahilmgandhi 18:6a4db94011d3 472
sahilmgandhi 18:6a4db94011d3 473 void i2c_reset(i2c_t *obj) {
sahilmgandhi 18:6a4db94011d3 474 i2c_stop(obj);
sahilmgandhi 18:6a4db94011d3 475 }
sahilmgandhi 18:6a4db94011d3 476
sahilmgandhi 18:6a4db94011d3 477 int i2c_byte_read(i2c_t *obj, int last) {
sahilmgandhi 18:6a4db94011d3 478 char i2c_ret = 0;
sahilmgandhi 18:6a4db94011d3 479 i2c_read(obj, obj->last_xfer_address, &i2c_ret, 1, last);
sahilmgandhi 18:6a4db94011d3 480 return i2c_ret;
sahilmgandhi 18:6a4db94011d3 481 }
sahilmgandhi 18:6a4db94011d3 482
sahilmgandhi 18:6a4db94011d3 483 int i2c_byte_write(i2c_t *obj, int data) {
sahilmgandhi 18:6a4db94011d3 484 /* Store the number of written bytes */
sahilmgandhi 18:6a4db94011d3 485 uint32_t wb = i2c_write(obj, obj->last_xfer_address, (char*)&data, 1, 0);
sahilmgandhi 18:6a4db94011d3 486 if (wb == 1)
sahilmgandhi 18:6a4db94011d3 487 return 1;
sahilmgandhi 18:6a4db94011d3 488 else
sahilmgandhi 18:6a4db94011d3 489 return 0;
sahilmgandhi 18:6a4db94011d3 490 }
sahilmgandhi 18:6a4db94011d3 491
sahilmgandhi 18:6a4db94011d3 492 void i2c_slave_mode(i2c_t *obj, int enable_slave) {
sahilmgandhi 18:6a4db94011d3 493 }
sahilmgandhi 18:6a4db94011d3 494
sahilmgandhi 18:6a4db94011d3 495 int i2c_slave_receive(i2c_t *obj) {
sahilmgandhi 18:6a4db94011d3 496 return 0;
sahilmgandhi 18:6a4db94011d3 497 }
sahilmgandhi 18:6a4db94011d3 498
sahilmgandhi 18:6a4db94011d3 499 int i2c_slave_read(i2c_t *obj, char *data, int length) {
sahilmgandhi 18:6a4db94011d3 500 return 0;
sahilmgandhi 18:6a4db94011d3 501 }
sahilmgandhi 18:6a4db94011d3 502
sahilmgandhi 18:6a4db94011d3 503 int i2c_slave_write(i2c_t *obj, const char *data, int length) {
sahilmgandhi 18:6a4db94011d3 504 return 0;
sahilmgandhi 18:6a4db94011d3 505 }
sahilmgandhi 18:6a4db94011d3 506
sahilmgandhi 18:6a4db94011d3 507 void i2c_slave_address(i2c_t *obj, int idx, uint32_t address, uint32_t mask) {
sahilmgandhi 18:6a4db94011d3 508 }