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 /***************************************************************************//**
sahilmgandhi 18:6a4db94011d3 2 * @file i2c_api.c
sahilmgandhi 18:6a4db94011d3 3 *******************************************************************************
sahilmgandhi 18:6a4db94011d3 4 * @section License
sahilmgandhi 18:6a4db94011d3 5 * <b>(C) Copyright 2015 Silicon Labs, http://www.silabs.com</b>
sahilmgandhi 18:6a4db94011d3 6 *******************************************************************************
sahilmgandhi 18:6a4db94011d3 7 *
sahilmgandhi 18:6a4db94011d3 8 * SPDX-License-Identifier: Apache-2.0
sahilmgandhi 18:6a4db94011d3 9 *
sahilmgandhi 18:6a4db94011d3 10 * Licensed under the Apache License, Version 2.0 (the "License"); you may
sahilmgandhi 18:6a4db94011d3 11 * not use this file except in compliance with the License.
sahilmgandhi 18:6a4db94011d3 12 * You may obtain a copy of the License at
sahilmgandhi 18:6a4db94011d3 13 *
sahilmgandhi 18:6a4db94011d3 14 * http://www.apache.org/licenses/LICENSE-2.0
sahilmgandhi 18:6a4db94011d3 15 *
sahilmgandhi 18:6a4db94011d3 16 * Unless required by applicable law or agreed to in writing, software
sahilmgandhi 18:6a4db94011d3 17 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
sahilmgandhi 18:6a4db94011d3 18 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
sahilmgandhi 18:6a4db94011d3 19 * See the License for the specific language governing permissions and
sahilmgandhi 18:6a4db94011d3 20 * limitations under the License.
sahilmgandhi 18:6a4db94011d3 21 *
sahilmgandhi 18:6a4db94011d3 22 ******************************************************************************/
sahilmgandhi 18:6a4db94011d3 23
sahilmgandhi 18:6a4db94011d3 24 #include "device.h"
sahilmgandhi 18:6a4db94011d3 25 #include "clocking.h"
sahilmgandhi 18:6a4db94011d3 26 #include <stdio.h>
sahilmgandhi 18:6a4db94011d3 27
sahilmgandhi 18:6a4db94011d3 28 #if DEVICE_I2C
sahilmgandhi 18:6a4db94011d3 29
sahilmgandhi 18:6a4db94011d3 30 #include "mbed_assert.h"
sahilmgandhi 18:6a4db94011d3 31 #include "i2c_api.h"
sahilmgandhi 18:6a4db94011d3 32 #include "PeripheralPins.h"
sahilmgandhi 18:6a4db94011d3 33 #include "pinmap_function.h"
sahilmgandhi 18:6a4db94011d3 34 #include "sleepmodes.h"
sahilmgandhi 18:6a4db94011d3 35
sahilmgandhi 18:6a4db94011d3 36 #include "em_i2c.h"
sahilmgandhi 18:6a4db94011d3 37 #include "em_cmu.h"
sahilmgandhi 18:6a4db94011d3 38
sahilmgandhi 18:6a4db94011d3 39 /** Error flags indicating I2C transfer has failed somehow. */
sahilmgandhi 18:6a4db94011d3 40 /* Notice that I2C_IF_TXOF (transmit overflow) is not really possible with */
sahilmgandhi 18:6a4db94011d3 41 /* this SW supporting master mode. Likewise for I2C_IF_RXUF (receive underflow) */
sahilmgandhi 18:6a4db94011d3 42 /* RXUF is only likely to occur with this SW if using a debugger peeking into */
sahilmgandhi 18:6a4db94011d3 43 /* RXDATA register. Thus, we ignore those types of fault. */
sahilmgandhi 18:6a4db94011d3 44 #define I2C_IF_ERRORS (I2C_IF_BUSERR | I2C_IF_ARBLOST)
sahilmgandhi 18:6a4db94011d3 45 #define I2C_TIMEOUT 100000
sahilmgandhi 18:6a4db94011d3 46
sahilmgandhi 18:6a4db94011d3 47 /* Prototypes */
sahilmgandhi 18:6a4db94011d3 48 int block_and_wait_for_ack(I2C_TypeDef *i2c);
sahilmgandhi 18:6a4db94011d3 49 void i2c_enable(i2c_t *obj, uint8_t enable);
sahilmgandhi 18:6a4db94011d3 50 void i2c_enable_pins(i2c_t *obj, uint8_t enable);
sahilmgandhi 18:6a4db94011d3 51 void i2c_enable_interrupt(i2c_t *obj, uint32_t address, uint8_t enable);
sahilmgandhi 18:6a4db94011d3 52
sahilmgandhi 18:6a4db94011d3 53 static uint8_t i2c_get_index(i2c_t *obj)
sahilmgandhi 18:6a4db94011d3 54 {
sahilmgandhi 18:6a4db94011d3 55 uint8_t index = 0;
sahilmgandhi 18:6a4db94011d3 56 switch ((int)obj->i2c.i2c) {
sahilmgandhi 18:6a4db94011d3 57 #ifdef I2C0
sahilmgandhi 18:6a4db94011d3 58 case I2C_0:
sahilmgandhi 18:6a4db94011d3 59 index = 0;
sahilmgandhi 18:6a4db94011d3 60 break;
sahilmgandhi 18:6a4db94011d3 61 #endif
sahilmgandhi 18:6a4db94011d3 62 #ifdef I2C1
sahilmgandhi 18:6a4db94011d3 63 case I2C_1:
sahilmgandhi 18:6a4db94011d3 64 index = 1;
sahilmgandhi 18:6a4db94011d3 65 break;
sahilmgandhi 18:6a4db94011d3 66 #endif
sahilmgandhi 18:6a4db94011d3 67 default:
sahilmgandhi 18:6a4db94011d3 68 printf("I2C module not available.. Out of bound access.");
sahilmgandhi 18:6a4db94011d3 69 break;
sahilmgandhi 18:6a4db94011d3 70 }
sahilmgandhi 18:6a4db94011d3 71 return index;
sahilmgandhi 18:6a4db94011d3 72 }
sahilmgandhi 18:6a4db94011d3 73
sahilmgandhi 18:6a4db94011d3 74 static CMU_Clock_TypeDef i2c_get_clock(i2c_t *obj)
sahilmgandhi 18:6a4db94011d3 75 {
sahilmgandhi 18:6a4db94011d3 76 CMU_Clock_TypeDef clock;
sahilmgandhi 18:6a4db94011d3 77 switch ((int)obj->i2c.i2c) {
sahilmgandhi 18:6a4db94011d3 78 #ifdef I2C0
sahilmgandhi 18:6a4db94011d3 79 case I2C_0:
sahilmgandhi 18:6a4db94011d3 80 clock = cmuClock_I2C0;
sahilmgandhi 18:6a4db94011d3 81 break;
sahilmgandhi 18:6a4db94011d3 82 #endif
sahilmgandhi 18:6a4db94011d3 83 #ifdef I2C1
sahilmgandhi 18:6a4db94011d3 84 case I2C_1:
sahilmgandhi 18:6a4db94011d3 85 clock = cmuClock_I2C1;
sahilmgandhi 18:6a4db94011d3 86 break;
sahilmgandhi 18:6a4db94011d3 87 #endif
sahilmgandhi 18:6a4db94011d3 88 default:
sahilmgandhi 18:6a4db94011d3 89 printf("I2C module not available.. Out of bound access. (clock)");
sahilmgandhi 18:6a4db94011d3 90 clock = cmuClock_HFPER;
sahilmgandhi 18:6a4db94011d3 91 break;
sahilmgandhi 18:6a4db94011d3 92 }
sahilmgandhi 18:6a4db94011d3 93 return clock;
sahilmgandhi 18:6a4db94011d3 94 }
sahilmgandhi 18:6a4db94011d3 95
sahilmgandhi 18:6a4db94011d3 96 void i2c_init(i2c_t *obj, PinName sda, PinName scl)
sahilmgandhi 18:6a4db94011d3 97 {
sahilmgandhi 18:6a4db94011d3 98 /* Find out which I2C peripheral we're asked to use */
sahilmgandhi 18:6a4db94011d3 99 I2CName i2c_sda = (I2CName) pinmap_peripheral(sda, PinMap_I2C_SDA);
sahilmgandhi 18:6a4db94011d3 100 I2CName i2c_scl = (I2CName) pinmap_peripheral(scl, PinMap_I2C_SCL);
sahilmgandhi 18:6a4db94011d3 101 obj->i2c.i2c = (I2C_TypeDef*) pinmap_merge(i2c_sda, i2c_scl);
sahilmgandhi 18:6a4db94011d3 102 MBED_ASSERT(((int) obj->i2c.i2c) != NC);
sahilmgandhi 18:6a4db94011d3 103
sahilmgandhi 18:6a4db94011d3 104 /* You need both SDA and SCL for I2C, so configuring one of them to NC is illegal */
sahilmgandhi 18:6a4db94011d3 105 MBED_ASSERT((uint32_t)sda != (uint32_t)NC);
sahilmgandhi 18:6a4db94011d3 106 MBED_ASSERT((uint32_t)scl != (uint32_t)NC);
sahilmgandhi 18:6a4db94011d3 107
sahilmgandhi 18:6a4db94011d3 108 /* Enable clock for the peripheral */
sahilmgandhi 18:6a4db94011d3 109 CMU_ClockEnable(i2c_get_clock(obj), true);
sahilmgandhi 18:6a4db94011d3 110
sahilmgandhi 18:6a4db94011d3 111 /* Initializing the I2C */
sahilmgandhi 18:6a4db94011d3 112 /* Using default settings */
sahilmgandhi 18:6a4db94011d3 113 I2C_Init_TypeDef i2cInit = I2C_INIT_DEFAULT;
sahilmgandhi 18:6a4db94011d3 114 I2C_Init(obj->i2c.i2c, &i2cInit);
sahilmgandhi 18:6a4db94011d3 115
sahilmgandhi 18:6a4db94011d3 116 /* Enable pins at correct location */
sahilmgandhi 18:6a4db94011d3 117 #ifdef I2C_ROUTE_SDAPEN
sahilmgandhi 18:6a4db94011d3 118 /* Find common location in pinmap */
sahilmgandhi 18:6a4db94011d3 119 int loc_sda = pin_location(sda, PinMap_I2C_SDA);
sahilmgandhi 18:6a4db94011d3 120 int loc_scl = pin_location(scl, PinMap_I2C_SCL);
sahilmgandhi 18:6a4db94011d3 121 int loc = pinmap_merge(loc_sda, loc_scl);
sahilmgandhi 18:6a4db94011d3 122 MBED_ASSERT(loc != NC);
sahilmgandhi 18:6a4db94011d3 123 /* Set location */
sahilmgandhi 18:6a4db94011d3 124 obj->i2c.location = I2C_ROUTE_SDAPEN | I2C_ROUTE_SCLPEN | (loc << _I2C_ROUTE_LOCATION_SHIFT);
sahilmgandhi 18:6a4db94011d3 125 obj->i2c.i2c->ROUTE = I2C_ROUTE_SDAPEN | I2C_ROUTE_SCLPEN | (loc << _I2C_ROUTE_LOCATION_SHIFT);
sahilmgandhi 18:6a4db94011d3 126 #else
sahilmgandhi 18:6a4db94011d3 127 obj->i2c.i2c->ROUTEPEN = I2C_ROUTEPEN_SDAPEN | I2C_ROUTEPEN_SCLPEN;
sahilmgandhi 18:6a4db94011d3 128 obj->i2c.location = (pin_location(sda, PinMap_I2C_SDA) << _I2C_ROUTELOC0_SDALOC_SHIFT) |
sahilmgandhi 18:6a4db94011d3 129 (pin_location(scl, PinMap_I2C_SCL) << _I2C_ROUTELOC0_SCLLOC_SHIFT);
sahilmgandhi 18:6a4db94011d3 130 obj->i2c.i2c->ROUTELOC0 = obj->i2c.location;
sahilmgandhi 18:6a4db94011d3 131 #endif
sahilmgandhi 18:6a4db94011d3 132
sahilmgandhi 18:6a4db94011d3 133 /* Set up the pins for I2C use */
sahilmgandhi 18:6a4db94011d3 134 /* Note: Set up pins in higher drive strength to reduce slew rate */
sahilmgandhi 18:6a4db94011d3 135 /* Though this requires user knowledge, since drive strength is controlled per port, not pin */
sahilmgandhi 18:6a4db94011d3 136 pin_mode(scl, WiredAndPullUp);
sahilmgandhi 18:6a4db94011d3 137 pin_mode(sda, WiredAndPullUp);
sahilmgandhi 18:6a4db94011d3 138
sahilmgandhi 18:6a4db94011d3 139 /* Enable General Call Address Mode. That is; we respond to the general address (0x0) */
sahilmgandhi 18:6a4db94011d3 140 obj->i2c.i2c->CTRL |= _I2C_CTRL_GCAMEN_MASK;
sahilmgandhi 18:6a4db94011d3 141
sahilmgandhi 18:6a4db94011d3 142 /* We are assuming that there is only one master. So disable automatic arbitration */
sahilmgandhi 18:6a4db94011d3 143 obj->i2c.i2c->CTRL |= _I2C_CTRL_ARBDIS_MASK;
sahilmgandhi 18:6a4db94011d3 144
sahilmgandhi 18:6a4db94011d3 145 /* Set to master (needed if this I2C block was used previously as slave) */
sahilmgandhi 18:6a4db94011d3 146 i2c_slave_mode(obj, false);
sahilmgandhi 18:6a4db94011d3 147
sahilmgandhi 18:6a4db94011d3 148 /* Enable i2c */
sahilmgandhi 18:6a4db94011d3 149 i2c_enable(obj, true);
sahilmgandhi 18:6a4db94011d3 150 }
sahilmgandhi 18:6a4db94011d3 151
sahilmgandhi 18:6a4db94011d3 152 void i2c_enable(i2c_t *obj, uint8_t enable)
sahilmgandhi 18:6a4db94011d3 153 {
sahilmgandhi 18:6a4db94011d3 154 I2C_Enable(obj->i2c.i2c, enable);
sahilmgandhi 18:6a4db94011d3 155 if (!enable) {
sahilmgandhi 18:6a4db94011d3 156 /* After a reset BUSY is usually set. We assume that we are the only master and call abort,
sahilmgandhi 18:6a4db94011d3 157 * which sends nothing on the bus, it just allows us to assume that the bus is idle */
sahilmgandhi 18:6a4db94011d3 158 if (obj->i2c.i2c->STATE & I2C_STATE_BUSY) {
sahilmgandhi 18:6a4db94011d3 159 obj->i2c.i2c->CMD = I2C_CMD_ABORT;
sahilmgandhi 18:6a4db94011d3 160 }
sahilmgandhi 18:6a4db94011d3 161 }
sahilmgandhi 18:6a4db94011d3 162 }
sahilmgandhi 18:6a4db94011d3 163
sahilmgandhi 18:6a4db94011d3 164 void i2c_enable_interrupt(i2c_t *obj, uint32_t address, uint8_t enable)
sahilmgandhi 18:6a4db94011d3 165 {
sahilmgandhi 18:6a4db94011d3 166 IRQn_Type irq_number;
sahilmgandhi 18:6a4db94011d3 167
sahilmgandhi 18:6a4db94011d3 168 switch (i2c_get_index(obj)) {
sahilmgandhi 18:6a4db94011d3 169 #ifdef I2C0
sahilmgandhi 18:6a4db94011d3 170 case 0:
sahilmgandhi 18:6a4db94011d3 171 irq_number = I2C0_IRQn;
sahilmgandhi 18:6a4db94011d3 172 break;
sahilmgandhi 18:6a4db94011d3 173 #endif
sahilmgandhi 18:6a4db94011d3 174 #ifdef I2C1
sahilmgandhi 18:6a4db94011d3 175 case 1:
sahilmgandhi 18:6a4db94011d3 176 irq_number = I2C1_IRQn;
sahilmgandhi 18:6a4db94011d3 177 break;
sahilmgandhi 18:6a4db94011d3 178 #endif
sahilmgandhi 18:6a4db94011d3 179 }
sahilmgandhi 18:6a4db94011d3 180
sahilmgandhi 18:6a4db94011d3 181 NVIC_SetVector(irq_number, address);
sahilmgandhi 18:6a4db94011d3 182 /* Lower IRQ priority to avoid messing with asynch RX on UART */
sahilmgandhi 18:6a4db94011d3 183 NVIC_SetPriority(irq_number, 1);
sahilmgandhi 18:6a4db94011d3 184 if (enable) {
sahilmgandhi 18:6a4db94011d3 185 NVIC_EnableIRQ(irq_number);
sahilmgandhi 18:6a4db94011d3 186 } else {
sahilmgandhi 18:6a4db94011d3 187 NVIC_DisableIRQ(irq_number);
sahilmgandhi 18:6a4db94011d3 188 }
sahilmgandhi 18:6a4db94011d3 189 }
sahilmgandhi 18:6a4db94011d3 190
sahilmgandhi 18:6a4db94011d3 191 /* Set the frequency of the I2C interface */
sahilmgandhi 18:6a4db94011d3 192 void i2c_frequency(i2c_t *obj, int hz)
sahilmgandhi 18:6a4db94011d3 193 {
sahilmgandhi 18:6a4db94011d3 194 /* Set frequency. As the second argument is 0,
sahilmgandhi 18:6a4db94011d3 195 * HFPER clock frequency is used as reference freq */
sahilmgandhi 18:6a4db94011d3 196 if (hz <= 0) return;
sahilmgandhi 18:6a4db94011d3 197 /* In I2C Normal mode (50% duty), we can go up to 100kHz */
sahilmgandhi 18:6a4db94011d3 198 if (hz <= 100000) {
sahilmgandhi 18:6a4db94011d3 199 I2C_BusFreqSet(obj->i2c.i2c, REFERENCE_FREQUENCY, hz, i2cClockHLRStandard);
sahilmgandhi 18:6a4db94011d3 200 }
sahilmgandhi 18:6a4db94011d3 201 /* In I2C Fast mode (6:3 ratio), we can go up to 400kHz */
sahilmgandhi 18:6a4db94011d3 202 else if (hz <= 400000) {
sahilmgandhi 18:6a4db94011d3 203 I2C_BusFreqSet(obj->i2c.i2c, REFERENCE_FREQUENCY, hz, i2cClockHLRAsymetric);
sahilmgandhi 18:6a4db94011d3 204 }
sahilmgandhi 18:6a4db94011d3 205 /* In I2C Fast+ mode (11:6 ratio), we can go up to 1 MHz */
sahilmgandhi 18:6a4db94011d3 206 else if (hz <= 1000000) {
sahilmgandhi 18:6a4db94011d3 207 I2C_BusFreqSet(obj->i2c.i2c, REFERENCE_FREQUENCY, hz, i2cClockHLRFast);
sahilmgandhi 18:6a4db94011d3 208 }
sahilmgandhi 18:6a4db94011d3 209 /* Cap requested frequency at 1MHz */
sahilmgandhi 18:6a4db94011d3 210 else {
sahilmgandhi 18:6a4db94011d3 211 I2C_BusFreqSet(obj->i2c.i2c, REFERENCE_FREQUENCY, 1000000, i2cClockHLRFast);
sahilmgandhi 18:6a4db94011d3 212 }
sahilmgandhi 18:6a4db94011d3 213 }
sahilmgandhi 18:6a4db94011d3 214
sahilmgandhi 18:6a4db94011d3 215 /* Creates a start condition on the I2C bus */
sahilmgandhi 18:6a4db94011d3 216 int i2c_start(i2c_t *obj)
sahilmgandhi 18:6a4db94011d3 217 {
sahilmgandhi 18:6a4db94011d3 218 I2C_TypeDef *i2c = obj->i2c.i2c;
sahilmgandhi 18:6a4db94011d3 219
sahilmgandhi 18:6a4db94011d3 220 /* Restore pin configuration in case we changed I2C object */
sahilmgandhi 18:6a4db94011d3 221 #ifdef I2C_ROUTE_SDAPEN
sahilmgandhi 18:6a4db94011d3 222 obj->i2c.i2c->ROUTE = obj->i2c.location;
sahilmgandhi 18:6a4db94011d3 223 #else
sahilmgandhi 18:6a4db94011d3 224 obj->i2c.i2c->ROUTELOC0 = obj->i2c.location;
sahilmgandhi 18:6a4db94011d3 225 #endif
sahilmgandhi 18:6a4db94011d3 226
sahilmgandhi 18:6a4db94011d3 227 /* Ensure buffers are empty */
sahilmgandhi 18:6a4db94011d3 228 i2c->CMD = I2C_CMD_CLEARPC | I2C_CMD_CLEARTX;
sahilmgandhi 18:6a4db94011d3 229 if (i2c->IF & I2C_IF_RXDATAV) {
sahilmgandhi 18:6a4db94011d3 230 (void) i2c->RXDATA;
sahilmgandhi 18:6a4db94011d3 231 }
sahilmgandhi 18:6a4db94011d3 232
sahilmgandhi 18:6a4db94011d3 233 /* Clear all pending interrupts prior to starting transfer. */
sahilmgandhi 18:6a4db94011d3 234 i2c->IFC = _I2C_IFC_MASK;
sahilmgandhi 18:6a4db94011d3 235
sahilmgandhi 18:6a4db94011d3 236 /* Send start */
sahilmgandhi 18:6a4db94011d3 237 obj->i2c.i2c->CMD = I2C_CMD_START;
sahilmgandhi 18:6a4db94011d3 238 return 0;
sahilmgandhi 18:6a4db94011d3 239 }
sahilmgandhi 18:6a4db94011d3 240
sahilmgandhi 18:6a4db94011d3 241 /* Creates a stop condition on the I2C bus */
sahilmgandhi 18:6a4db94011d3 242 int i2c_stop(i2c_t *obj)
sahilmgandhi 18:6a4db94011d3 243 {
sahilmgandhi 18:6a4db94011d3 244 obj->i2c.i2c->CMD = I2C_CMD_STOP;
sahilmgandhi 18:6a4db94011d3 245
sahilmgandhi 18:6a4db94011d3 246 /* Wait for the stop to be sent */
sahilmgandhi 18:6a4db94011d3 247 int timeout = I2C_TIMEOUT;
sahilmgandhi 18:6a4db94011d3 248 while (!(obj->i2c.i2c->IF & I2C_IF_MSTOP) && !timeout--);
sahilmgandhi 18:6a4db94011d3 249
sahilmgandhi 18:6a4db94011d3 250 return 0;
sahilmgandhi 18:6a4db94011d3 251 }
sahilmgandhi 18:6a4db94011d3 252
sahilmgandhi 18:6a4db94011d3 253 /* Returns number of bytes read */
sahilmgandhi 18:6a4db94011d3 254 int i2c_read(i2c_t *obj, int address, char *data, int length, int stop)
sahilmgandhi 18:6a4db94011d3 255 {
sahilmgandhi 18:6a4db94011d3 256 int retval;
sahilmgandhi 18:6a4db94011d3 257
sahilmgandhi 18:6a4db94011d3 258 i2c_start(obj);
sahilmgandhi 18:6a4db94011d3 259
sahilmgandhi 18:6a4db94011d3 260 retval = i2c_byte_write(obj, (address | 1));
sahilmgandhi 18:6a4db94011d3 261 if ((!retval) || (length == 0)) { //Write address with W flag (last bit 1)
sahilmgandhi 18:6a4db94011d3 262 obj->i2c.i2c->CMD = I2C_CMD_STOP | I2C_CMD_ABORT;
sahilmgandhi 18:6a4db94011d3 263 while(obj->i2c.i2c->STATE & I2C_STATE_BUSY); // Wait until the bus is done
sahilmgandhi 18:6a4db94011d3 264 return (retval == 0 ? I2C_ERROR_NO_SLAVE : 0); //NACK or error when writing adress. Return 0 as 0 bytes were read
sahilmgandhi 18:6a4db94011d3 265 }
sahilmgandhi 18:6a4db94011d3 266 int i = 0;
sahilmgandhi 18:6a4db94011d3 267 while (i < length) {
sahilmgandhi 18:6a4db94011d3 268 uint8_t last = (i == length - 1);
sahilmgandhi 18:6a4db94011d3 269 data[i++] = i2c_byte_read(obj, last);
sahilmgandhi 18:6a4db94011d3 270 }
sahilmgandhi 18:6a4db94011d3 271
sahilmgandhi 18:6a4db94011d3 272 if (stop) {
sahilmgandhi 18:6a4db94011d3 273 i2c_stop(obj);
sahilmgandhi 18:6a4db94011d3 274 }
sahilmgandhi 18:6a4db94011d3 275
sahilmgandhi 18:6a4db94011d3 276 return length;
sahilmgandhi 18:6a4db94011d3 277 }
sahilmgandhi 18:6a4db94011d3 278
sahilmgandhi 18:6a4db94011d3 279 int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop)
sahilmgandhi 18:6a4db94011d3 280 {
sahilmgandhi 18:6a4db94011d3 281 i2c_start(obj);
sahilmgandhi 18:6a4db94011d3 282
sahilmgandhi 18:6a4db94011d3 283 if (!i2c_byte_write(obj, (address & 0xFE))) {
sahilmgandhi 18:6a4db94011d3 284 i2c_stop(obj);
sahilmgandhi 18:6a4db94011d3 285 return I2C_ERROR_NO_SLAVE; //NACK or error when writing adress. Return 0 as 0 bytes were written
sahilmgandhi 18:6a4db94011d3 286 }
sahilmgandhi 18:6a4db94011d3 287 int i;
sahilmgandhi 18:6a4db94011d3 288 for (i = 0; i < length; i++) {
sahilmgandhi 18:6a4db94011d3 289 if (!i2c_byte_write(obj, data[i])) {
sahilmgandhi 18:6a4db94011d3 290 i2c_stop(obj);
sahilmgandhi 18:6a4db94011d3 291 return i;
sahilmgandhi 18:6a4db94011d3 292 }
sahilmgandhi 18:6a4db94011d3 293 }
sahilmgandhi 18:6a4db94011d3 294
sahilmgandhi 18:6a4db94011d3 295 if (stop) {
sahilmgandhi 18:6a4db94011d3 296 i2c_stop(obj);
sahilmgandhi 18:6a4db94011d3 297 }
sahilmgandhi 18:6a4db94011d3 298
sahilmgandhi 18:6a4db94011d3 299 return length;
sahilmgandhi 18:6a4db94011d3 300 }
sahilmgandhi 18:6a4db94011d3 301
sahilmgandhi 18:6a4db94011d3 302 void i2c_reset(i2c_t *obj)
sahilmgandhi 18:6a4db94011d3 303 {
sahilmgandhi 18:6a4db94011d3 304 /* EMLib function */
sahilmgandhi 18:6a4db94011d3 305 I2C_Reset(obj->i2c.i2c);
sahilmgandhi 18:6a4db94011d3 306 }
sahilmgandhi 18:6a4db94011d3 307
sahilmgandhi 18:6a4db94011d3 308 int i2c_byte_read(i2c_t *obj, int last)
sahilmgandhi 18:6a4db94011d3 309 {
sahilmgandhi 18:6a4db94011d3 310 int timeout = I2C_TIMEOUT;
sahilmgandhi 18:6a4db94011d3 311 /* Wait for data */
sahilmgandhi 18:6a4db94011d3 312 while (!(obj->i2c.i2c->STATUS & I2C_STATUS_RXDATAV) && timeout--);
sahilmgandhi 18:6a4db94011d3 313
sahilmgandhi 18:6a4db94011d3 314 if (timeout <= 0) {
sahilmgandhi 18:6a4db94011d3 315 return 0; //TODO Is this the correct way to handle this?
sahilmgandhi 18:6a4db94011d3 316 }
sahilmgandhi 18:6a4db94011d3 317 char data = obj->i2c.i2c->RXDATA;
sahilmgandhi 18:6a4db94011d3 318
sahilmgandhi 18:6a4db94011d3 319 if (last) {
sahilmgandhi 18:6a4db94011d3 320 obj->i2c.i2c->CMD = I2C_CMD_NACK;
sahilmgandhi 18:6a4db94011d3 321 } else {
sahilmgandhi 18:6a4db94011d3 322 obj->i2c.i2c->CMD = I2C_CMD_ACK;
sahilmgandhi 18:6a4db94011d3 323 }
sahilmgandhi 18:6a4db94011d3 324 return data;
sahilmgandhi 18:6a4db94011d3 325 }
sahilmgandhi 18:6a4db94011d3 326
sahilmgandhi 18:6a4db94011d3 327 int i2c_byte_write(i2c_t *obj, int data)
sahilmgandhi 18:6a4db94011d3 328 {
sahilmgandhi 18:6a4db94011d3 329 obj->i2c.i2c->TXDATA = data;
sahilmgandhi 18:6a4db94011d3 330 return block_and_wait_for_ack(obj->i2c.i2c);
sahilmgandhi 18:6a4db94011d3 331 }
sahilmgandhi 18:6a4db94011d3 332
sahilmgandhi 18:6a4db94011d3 333 /*
sahilmgandhi 18:6a4db94011d3 334 * Returns 1 for ACK. 0 for NACK, timeout or error.
sahilmgandhi 18:6a4db94011d3 335 */
sahilmgandhi 18:6a4db94011d3 336 int block_and_wait_for_ack(I2C_TypeDef *i2c)
sahilmgandhi 18:6a4db94011d3 337 {
sahilmgandhi 18:6a4db94011d3 338 uint32_t pending;
sahilmgandhi 18:6a4db94011d3 339 uint32_t timeout = I2C_TIMEOUT;
sahilmgandhi 18:6a4db94011d3 340 while (timeout > 0) {
sahilmgandhi 18:6a4db94011d3 341 timeout -= 1;
sahilmgandhi 18:6a4db94011d3 342 pending = i2c->IF;
sahilmgandhi 18:6a4db94011d3 343 /* If some sort of fault, abort transfer. */
sahilmgandhi 18:6a4db94011d3 344 if (pending & I2C_IF_ERRORS) {
sahilmgandhi 18:6a4db94011d3 345 if (pending & I2C_IF_ARBLOST) {
sahilmgandhi 18:6a4db94011d3 346 /* If arbitration fault, it indicates either a slave device */
sahilmgandhi 18:6a4db94011d3 347 /* not responding as expected, or other master which is not */
sahilmgandhi 18:6a4db94011d3 348 /* supported by this SW. */
sahilmgandhi 18:6a4db94011d3 349 return 0;
sahilmgandhi 18:6a4db94011d3 350 } else if (pending & I2C_IF_BUSERR) {
sahilmgandhi 18:6a4db94011d3 351 /* A bus error indicates a misplaced start or stop, which should */
sahilmgandhi 18:6a4db94011d3 352 /* not occur in master mode controlled by this SW. */
sahilmgandhi 18:6a4db94011d3 353 return 0;
sahilmgandhi 18:6a4db94011d3 354 }
sahilmgandhi 18:6a4db94011d3 355 }
sahilmgandhi 18:6a4db94011d3 356
sahilmgandhi 18:6a4db94011d3 357 if (pending & I2C_IF_NACK) {
sahilmgandhi 18:6a4db94011d3 358 i2c->IFC = I2C_IFC_NACK;
sahilmgandhi 18:6a4db94011d3 359 return 0; //Received NACK
sahilmgandhi 18:6a4db94011d3 360 } else if (pending & I2C_IF_ACK) {
sahilmgandhi 18:6a4db94011d3 361 i2c->IFC = I2C_IFC_ACK;
sahilmgandhi 18:6a4db94011d3 362 return 1; //Got ACK
sahilmgandhi 18:6a4db94011d3 363 }
sahilmgandhi 18:6a4db94011d3 364 }
sahilmgandhi 18:6a4db94011d3 365 return 0; //Timeout
sahilmgandhi 18:6a4db94011d3 366 }
sahilmgandhi 18:6a4db94011d3 367
sahilmgandhi 18:6a4db94011d3 368 #if DEVICE_I2CSLAVE
sahilmgandhi 18:6a4db94011d3 369
sahilmgandhi 18:6a4db94011d3 370 #define NoData 0
sahilmgandhi 18:6a4db94011d3 371 #define ReadAddressed 1
sahilmgandhi 18:6a4db94011d3 372 #define WriteGeneral 2
sahilmgandhi 18:6a4db94011d3 373 #define WriteAddressed 3
sahilmgandhi 18:6a4db94011d3 374
sahilmgandhi 18:6a4db94011d3 375
sahilmgandhi 18:6a4db94011d3 376 void i2c_slave_mode(i2c_t *obj, int enable_slave)
sahilmgandhi 18:6a4db94011d3 377 {
sahilmgandhi 18:6a4db94011d3 378 if(enable_slave) {
sahilmgandhi 18:6a4db94011d3 379 /* Reference manual note: DIV must be set to 1 during slave operation */
sahilmgandhi 18:6a4db94011d3 380 obj->i2c.i2c->CLKDIV = 1;
sahilmgandhi 18:6a4db94011d3 381 obj->i2c.i2c->CTRL |= _I2C_CTRL_SLAVE_MASK;
sahilmgandhi 18:6a4db94011d3 382 obj->i2c.i2c->CTRL |= _I2C_CTRL_AUTOACK_MASK; //Slave implementation assumes auto acking
sahilmgandhi 18:6a4db94011d3 383 } else {
sahilmgandhi 18:6a4db94011d3 384 obj->i2c.i2c->CTRL &= ~_I2C_CTRL_SLAVE_MASK;
sahilmgandhi 18:6a4db94011d3 385 obj->i2c.i2c->CTRL &= ~_I2C_CTRL_AUTOACK_MASK; //Master implementation ACKs manually
sahilmgandhi 18:6a4db94011d3 386 /* function is only called with enable_slave = false through i2c_init(..), so frequency is
sahilmgandhi 18:6a4db94011d3 387 already guaranteed to be set */
sahilmgandhi 18:6a4db94011d3 388 }
sahilmgandhi 18:6a4db94011d3 389 }
sahilmgandhi 18:6a4db94011d3 390
sahilmgandhi 18:6a4db94011d3 391 int i2c_slave_receive(i2c_t *obj)
sahilmgandhi 18:6a4db94011d3 392 {
sahilmgandhi 18:6a4db94011d3 393
sahilmgandhi 18:6a4db94011d3 394 if(obj->i2c.i2c->IF & I2C_IF_ADDR) {
sahilmgandhi 18:6a4db94011d3 395 obj->i2c.i2c->IFC = I2C_IF_ADDR; //Clear interrupt
sahilmgandhi 18:6a4db94011d3 396 /*0x00 is the address for general write.
sahilmgandhi 18:6a4db94011d3 397 The address the master wrote is in RXDATA now
sahilmgandhi 18:6a4db94011d3 398 and reading it also frees the buffer for the next
sahilmgandhi 18:6a4db94011d3 399 write which can then be acked. */
sahilmgandhi 18:6a4db94011d3 400 if(obj->i2c.i2c->RXDATA == 0x00) {
sahilmgandhi 18:6a4db94011d3 401 return WriteGeneral; //Read the address;
sahilmgandhi 18:6a4db94011d3 402 }
sahilmgandhi 18:6a4db94011d3 403
sahilmgandhi 18:6a4db94011d3 404 if(obj->i2c.i2c->STATE & I2C_STATE_TRANSMITTER) {
sahilmgandhi 18:6a4db94011d3 405 return ReadAddressed;
sahilmgandhi 18:6a4db94011d3 406 } else {
sahilmgandhi 18:6a4db94011d3 407 return WriteAddressed;
sahilmgandhi 18:6a4db94011d3 408 }
sahilmgandhi 18:6a4db94011d3 409 }
sahilmgandhi 18:6a4db94011d3 410
sahilmgandhi 18:6a4db94011d3 411 return NoData;
sahilmgandhi 18:6a4db94011d3 412
sahilmgandhi 18:6a4db94011d3 413 }
sahilmgandhi 18:6a4db94011d3 414
sahilmgandhi 18:6a4db94011d3 415 int i2c_slave_read(i2c_t *obj, char *data, int length)
sahilmgandhi 18:6a4db94011d3 416 {
sahilmgandhi 18:6a4db94011d3 417 int count;
sahilmgandhi 18:6a4db94011d3 418 for (count = 0; count < length; count++) {
sahilmgandhi 18:6a4db94011d3 419 data[count] = i2c_byte_read(obj, 0);
sahilmgandhi 18:6a4db94011d3 420 }
sahilmgandhi 18:6a4db94011d3 421
sahilmgandhi 18:6a4db94011d3 422 return count;
sahilmgandhi 18:6a4db94011d3 423
sahilmgandhi 18:6a4db94011d3 424 }
sahilmgandhi 18:6a4db94011d3 425
sahilmgandhi 18:6a4db94011d3 426 int i2c_slave_write(i2c_t *obj, const char *data, int length)
sahilmgandhi 18:6a4db94011d3 427 {
sahilmgandhi 18:6a4db94011d3 428 int count;
sahilmgandhi 18:6a4db94011d3 429 for (count = 0; count < length; count++) {
sahilmgandhi 18:6a4db94011d3 430 i2c_byte_write(obj, data[count]);
sahilmgandhi 18:6a4db94011d3 431 }
sahilmgandhi 18:6a4db94011d3 432
sahilmgandhi 18:6a4db94011d3 433 return count;
sahilmgandhi 18:6a4db94011d3 434 }
sahilmgandhi 18:6a4db94011d3 435
sahilmgandhi 18:6a4db94011d3 436 void i2c_slave_address(i2c_t *obj, int idx, uint32_t address, uint32_t mask)
sahilmgandhi 18:6a4db94011d3 437 {
sahilmgandhi 18:6a4db94011d3 438 obj->i2c.i2c->SADDR = address;
sahilmgandhi 18:6a4db94011d3 439 obj->i2c.i2c->SADDRMASK = 0xFE;//mask;
sahilmgandhi 18:6a4db94011d3 440 }
sahilmgandhi 18:6a4db94011d3 441
sahilmgandhi 18:6a4db94011d3 442 #endif //DEVICE_I2CSLAVE
sahilmgandhi 18:6a4db94011d3 443
sahilmgandhi 18:6a4db94011d3 444 #ifdef DEVICE_I2C_ASYNCH
sahilmgandhi 18:6a4db94011d3 445
sahilmgandhi 18:6a4db94011d3 446 #include "em_dma.h"
sahilmgandhi 18:6a4db94011d3 447 #include "dma_api_HAL.h"
sahilmgandhi 18:6a4db94011d3 448 #include "dma_api.h"
sahilmgandhi 18:6a4db94011d3 449 #include "sleep_api.h"
sahilmgandhi 18:6a4db94011d3 450 #include "buffer.h"
sahilmgandhi 18:6a4db94011d3 451
sahilmgandhi 18:6a4db94011d3 452 /** Start i2c asynchronous transfer.
sahilmgandhi 18:6a4db94011d3 453 * @param obj The I2C object
sahilmgandhi 18:6a4db94011d3 454 * @param tx The buffer to send
sahilmgandhi 18:6a4db94011d3 455 * @param tx_length The number of words to transmit
sahilmgandhi 18:6a4db94011d3 456 * @param rx The buffer to receive
sahilmgandhi 18:6a4db94011d3 457 * @param rx_length The number of words to receive
sahilmgandhi 18:6a4db94011d3 458 * @param address The address to be set - 7bit or 9 bit
sahilmgandhi 18:6a4db94011d3 459 * @param stop If true, stop will be generated after the transfer is done
sahilmgandhi 18:6a4db94011d3 460 * @param handler The I2C IRQ handler to be set
sahilmgandhi 18:6a4db94011d3 461 * @param hint DMA hint usage
sahilmgandhi 18:6a4db94011d3 462 */
sahilmgandhi 18:6a4db94011d3 463 void i2c_transfer_asynch(i2c_t *obj, const void *tx, size_t tx_length, void *rx, size_t rx_length, uint32_t address, uint32_t stop, uint32_t handler, uint32_t event, DMAUsage hint)
sahilmgandhi 18:6a4db94011d3 464 {
sahilmgandhi 18:6a4db94011d3 465 I2C_TransferReturn_TypeDef retval;
sahilmgandhi 18:6a4db94011d3 466 if(i2c_active(obj)) return;
sahilmgandhi 18:6a4db94011d3 467 if((tx_length == 0) && (rx_length == 0)) return;
sahilmgandhi 18:6a4db94011d3 468 // For now, we are assuming a solely interrupt-driven implementation.
sahilmgandhi 18:6a4db94011d3 469
sahilmgandhi 18:6a4db94011d3 470 #ifdef I2C_ROUTE_SDAPEN
sahilmgandhi 18:6a4db94011d3 471 obj->i2c.i2c->ROUTE = obj->i2c.location;
sahilmgandhi 18:6a4db94011d3 472 #else
sahilmgandhi 18:6a4db94011d3 473 obj->i2c.i2c->ROUTELOC0 = obj->i2c.location;
sahilmgandhi 18:6a4db94011d3 474 #endif
sahilmgandhi 18:6a4db94011d3 475
sahilmgandhi 18:6a4db94011d3 476 // Store transfer config
sahilmgandhi 18:6a4db94011d3 477 obj->i2c.xfer.addr = address;
sahilmgandhi 18:6a4db94011d3 478
sahilmgandhi 18:6a4db94011d3 479 // Some combination of tx_length and rx_length will tell us what to do
sahilmgandhi 18:6a4db94011d3 480 if((tx_length > 0) && (rx_length == 0)) {
sahilmgandhi 18:6a4db94011d3 481 obj->i2c.xfer.flags = I2C_FLAG_WRITE;
sahilmgandhi 18:6a4db94011d3 482 //Store buffer info
sahilmgandhi 18:6a4db94011d3 483 obj->i2c.xfer.buf[0].data = (void *)tx;
sahilmgandhi 18:6a4db94011d3 484 obj->i2c.xfer.buf[0].len = (uint16_t) tx_length;
sahilmgandhi 18:6a4db94011d3 485 } else if ((tx_length == 0) && (rx_length > 0)) {
sahilmgandhi 18:6a4db94011d3 486 obj->i2c.xfer.flags = I2C_FLAG_READ;
sahilmgandhi 18:6a4db94011d3 487 //Store buffer info
sahilmgandhi 18:6a4db94011d3 488 obj->i2c.xfer.buf[0].data = rx;
sahilmgandhi 18:6a4db94011d3 489 obj->i2c.xfer.buf[0].len = (uint16_t) rx_length;
sahilmgandhi 18:6a4db94011d3 490 } else if ((tx_length > 0) && (rx_length > 0)) {
sahilmgandhi 18:6a4db94011d3 491 obj->i2c.xfer.flags = I2C_FLAG_WRITE_READ;
sahilmgandhi 18:6a4db94011d3 492 //Store buffer info
sahilmgandhi 18:6a4db94011d3 493 obj->i2c.xfer.buf[0].data = (void *)tx;
sahilmgandhi 18:6a4db94011d3 494 obj->i2c.xfer.buf[0].len = (uint16_t) tx_length;
sahilmgandhi 18:6a4db94011d3 495 obj->i2c.xfer.buf[1].data = rx;
sahilmgandhi 18:6a4db94011d3 496 obj->i2c.xfer.buf[1].len = (uint16_t) rx_length;
sahilmgandhi 18:6a4db94011d3 497 }
sahilmgandhi 18:6a4db94011d3 498
sahilmgandhi 18:6a4db94011d3 499 if(address > 255) obj->i2c.xfer.flags |= I2C_FLAG_10BIT_ADDR;
sahilmgandhi 18:6a4db94011d3 500
sahilmgandhi 18:6a4db94011d3 501 // Store event flags
sahilmgandhi 18:6a4db94011d3 502 obj->i2c.events = event;
sahilmgandhi 18:6a4db94011d3 503
sahilmgandhi 18:6a4db94011d3 504 // Enable interrupt
sahilmgandhi 18:6a4db94011d3 505 i2c_enable_interrupt(obj, handler, true);
sahilmgandhi 18:6a4db94011d3 506
sahilmgandhi 18:6a4db94011d3 507 // Kick off the transfer
sahilmgandhi 18:6a4db94011d3 508 retval = I2C_TransferInit(obj->i2c.i2c, &(obj->i2c.xfer));
sahilmgandhi 18:6a4db94011d3 509
sahilmgandhi 18:6a4db94011d3 510 if(retval == i2cTransferInProgress) {
sahilmgandhi 18:6a4db94011d3 511 blockSleepMode(EM1);
sahilmgandhi 18:6a4db94011d3 512 } else {
sahilmgandhi 18:6a4db94011d3 513 // something happened, and the transfer did not go through
sahilmgandhi 18:6a4db94011d3 514 // So, we need to clean up
sahilmgandhi 18:6a4db94011d3 515
sahilmgandhi 18:6a4db94011d3 516 // Disable interrupt
sahilmgandhi 18:6a4db94011d3 517 i2c_enable_interrupt(obj, 0, false);
sahilmgandhi 18:6a4db94011d3 518
sahilmgandhi 18:6a4db94011d3 519 // Block until free
sahilmgandhi 18:6a4db94011d3 520 while(i2c_active(obj));
sahilmgandhi 18:6a4db94011d3 521 }
sahilmgandhi 18:6a4db94011d3 522 }
sahilmgandhi 18:6a4db94011d3 523
sahilmgandhi 18:6a4db94011d3 524 /** The asynchronous IRQ handler
sahilmgandhi 18:6a4db94011d3 525 * @param obj The I2C object which holds the transfer information
sahilmgandhi 18:6a4db94011d3 526 * @return Returns event flags if a transfer termination condition was met or 0 otherwise.
sahilmgandhi 18:6a4db94011d3 527 */
sahilmgandhi 18:6a4db94011d3 528 uint32_t i2c_irq_handler_asynch(i2c_t *obj)
sahilmgandhi 18:6a4db94011d3 529 {
sahilmgandhi 18:6a4db94011d3 530
sahilmgandhi 18:6a4db94011d3 531 // For now, we are assuming a solely interrupt-driven implementation.
sahilmgandhi 18:6a4db94011d3 532
sahilmgandhi 18:6a4db94011d3 533 I2C_TransferReturn_TypeDef status = I2C_Transfer(obj->i2c.i2c);
sahilmgandhi 18:6a4db94011d3 534 switch(status) {
sahilmgandhi 18:6a4db94011d3 535 case i2cTransferInProgress:
sahilmgandhi 18:6a4db94011d3 536 // Still busy transferring, so let it.
sahilmgandhi 18:6a4db94011d3 537 return 0;
sahilmgandhi 18:6a4db94011d3 538 case i2cTransferDone:
sahilmgandhi 18:6a4db94011d3 539 // Transfer has completed
sahilmgandhi 18:6a4db94011d3 540
sahilmgandhi 18:6a4db94011d3 541 // Disable interrupt
sahilmgandhi 18:6a4db94011d3 542 i2c_enable_interrupt(obj, 0, false);
sahilmgandhi 18:6a4db94011d3 543
sahilmgandhi 18:6a4db94011d3 544 unblockSleepMode(EM1);
sahilmgandhi 18:6a4db94011d3 545
sahilmgandhi 18:6a4db94011d3 546 return I2C_EVENT_TRANSFER_COMPLETE & obj->i2c.events;
sahilmgandhi 18:6a4db94011d3 547 case i2cTransferNack:
sahilmgandhi 18:6a4db94011d3 548 // A NACK has been received while an ACK was expected. This is usually because the slave did not respond to the address.
sahilmgandhi 18:6a4db94011d3 549 // Disable interrupt
sahilmgandhi 18:6a4db94011d3 550 i2c_enable_interrupt(obj, 0, false);
sahilmgandhi 18:6a4db94011d3 551
sahilmgandhi 18:6a4db94011d3 552 unblockSleepMode(EM1);
sahilmgandhi 18:6a4db94011d3 553
sahilmgandhi 18:6a4db94011d3 554 return I2C_EVENT_ERROR_NO_SLAVE & obj->i2c.events;
sahilmgandhi 18:6a4db94011d3 555 default:
sahilmgandhi 18:6a4db94011d3 556 // An error situation has arisen.
sahilmgandhi 18:6a4db94011d3 557 // Disable interrupt
sahilmgandhi 18:6a4db94011d3 558 i2c_enable_interrupt(obj, 0, false);
sahilmgandhi 18:6a4db94011d3 559
sahilmgandhi 18:6a4db94011d3 560 unblockSleepMode(EM1);
sahilmgandhi 18:6a4db94011d3 561
sahilmgandhi 18:6a4db94011d3 562 // return error
sahilmgandhi 18:6a4db94011d3 563 return I2C_EVENT_ERROR & obj->i2c.events;
sahilmgandhi 18:6a4db94011d3 564 }
sahilmgandhi 18:6a4db94011d3 565 }
sahilmgandhi 18:6a4db94011d3 566
sahilmgandhi 18:6a4db94011d3 567 /** Attempts to determine if I2C peripheral is already in use.
sahilmgandhi 18:6a4db94011d3 568 * @param obj The I2C object
sahilmgandhi 18:6a4db94011d3 569 * @return non-zero if the I2C module is active or zero if it is not
sahilmgandhi 18:6a4db94011d3 570 */
sahilmgandhi 18:6a4db94011d3 571 uint8_t i2c_active(i2c_t *obj)
sahilmgandhi 18:6a4db94011d3 572 {
sahilmgandhi 18:6a4db94011d3 573 return (obj->i2c.i2c->STATE & I2C_STATE_BUSY);
sahilmgandhi 18:6a4db94011d3 574 }
sahilmgandhi 18:6a4db94011d3 575
sahilmgandhi 18:6a4db94011d3 576 /** Abort ongoing asynchronous transaction.
sahilmgandhi 18:6a4db94011d3 577 * @param obj The I2C object
sahilmgandhi 18:6a4db94011d3 578 */
sahilmgandhi 18:6a4db94011d3 579 void i2c_abort_asynch(i2c_t *obj)
sahilmgandhi 18:6a4db94011d3 580 {
sahilmgandhi 18:6a4db94011d3 581 // Do not deactivate I2C twice
sahilmgandhi 18:6a4db94011d3 582 if (!i2c_active(obj)) return;
sahilmgandhi 18:6a4db94011d3 583
sahilmgandhi 18:6a4db94011d3 584 // Disable interrupt
sahilmgandhi 18:6a4db94011d3 585 i2c_enable_interrupt(obj, 0, false);
sahilmgandhi 18:6a4db94011d3 586
sahilmgandhi 18:6a4db94011d3 587 // Abort
sahilmgandhi 18:6a4db94011d3 588 obj->i2c.i2c->CMD = I2C_CMD_STOP | I2C_CMD_ABORT;
sahilmgandhi 18:6a4db94011d3 589
sahilmgandhi 18:6a4db94011d3 590 // Block until free
sahilmgandhi 18:6a4db94011d3 591 while(i2c_active(obj));
sahilmgandhi 18:6a4db94011d3 592
sahilmgandhi 18:6a4db94011d3 593 unblockSleepMode(EM1);
sahilmgandhi 18:6a4db94011d3 594 }
sahilmgandhi 18:6a4db94011d3 595
sahilmgandhi 18:6a4db94011d3 596 #endif //DEVICE_I2C ASYNCH
sahilmgandhi 18:6a4db94011d3 597 #endif //DEVICE_I2C