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) 2006-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 "mbed_assert.h"
sahilmgandhi 18:6a4db94011d3 17 #include "i2c_api.h"
sahilmgandhi 18:6a4db94011d3 18
sahilmgandhi 18:6a4db94011d3 19 #include <math.h>
sahilmgandhi 18:6a4db94011d3 20
sahilmgandhi 18:6a4db94011d3 21 #include "cmsis.h"
sahilmgandhi 18:6a4db94011d3 22 #include "pinmap.h"
sahilmgandhi 18:6a4db94011d3 23 #include "sercom.h"
sahilmgandhi 18:6a4db94011d3 24 #include "i2c_master.h"
sahilmgandhi 18:6a4db94011d3 25 #include "i2c_slave.h"
sahilmgandhi 18:6a4db94011d3 26
sahilmgandhi 18:6a4db94011d3 27 #include "pinmap_function.h"
sahilmgandhi 18:6a4db94011d3 28
sahilmgandhi 18:6a4db94011d3 29 #if DEVICE_I2C_ASYNCH
sahilmgandhi 18:6a4db94011d3 30 #include "i2c_master_interrupt.h"
sahilmgandhi 18:6a4db94011d3 31 #endif
sahilmgandhi 18:6a4db94011d3 32
sahilmgandhi 18:6a4db94011d3 33
sahilmgandhi 18:6a4db94011d3 34 #if DEVICE_I2C_ASYNCH
sahilmgandhi 18:6a4db94011d3 35 #define pI2C_S(obj) (&obj->i2c)
sahilmgandhi 18:6a4db94011d3 36 #else
sahilmgandhi 18:6a4db94011d3 37 #define pI2C_S(obj) obj
sahilmgandhi 18:6a4db94011d3 38 #endif
sahilmgandhi 18:6a4db94011d3 39
sahilmgandhi 18:6a4db94011d3 40 #define I2C_MASTER_DEFAULT_BAUD 100000
sahilmgandhi 18:6a4db94011d3 41
sahilmgandhi 18:6a4db94011d3 42 /**
sahilmgandhi 18:6a4db94011d3 43 * \brief I2C modes enum
sahilmgandhi 18:6a4db94011d3 44 *
sahilmgandhi 18:6a4db94011d3 45 * I2C mode selection.
sahilmgandhi 18:6a4db94011d3 46 */
sahilmgandhi 18:6a4db94011d3 47 enum i2c_mode {
sahilmgandhi 18:6a4db94011d3 48 /** Master mode. */
sahilmgandhi 18:6a4db94011d3 49 I2C_MODE_MASTER = 0x5,
sahilmgandhi 18:6a4db94011d3 50 /** Slave mode. */
sahilmgandhi 18:6a4db94011d3 51 I2C_MODE_SLAVE = 0x4,
sahilmgandhi 18:6a4db94011d3 52 };
sahilmgandhi 18:6a4db94011d3 53
sahilmgandhi 18:6a4db94011d3 54 /* Extern Variables */
sahilmgandhi 18:6a4db94011d3 55 extern uint8_t g_sys_init;
sahilmgandhi 18:6a4db94011d3 56
sahilmgandhi 18:6a4db94011d3 57 typedef void (*I2CHandler)(void);
sahilmgandhi 18:6a4db94011d3 58
sahilmgandhi 18:6a4db94011d3 59 #if DEVICE_I2C_ASYNCH
sahilmgandhi 18:6a4db94011d3 60 #define _SERCOM_INTERRUPT_HANDLERS(n, unused) (uint32_t)SERCOM##n##_Handler,
sahilmgandhi 18:6a4db94011d3 61
sahilmgandhi 18:6a4db94011d3 62 /* To save the i2c objects */
sahilmgandhi 18:6a4db94011d3 63 static uint32_t i2c_instances[SERCOM_INST_NUM] = {0};
sahilmgandhi 18:6a4db94011d3 64 const uint32_t sercom_irq_handlers[SERCOM_INST_NUM] = {
sahilmgandhi 18:6a4db94011d3 65 MREPEAT(SERCOM_INST_NUM, _SERCOM_INTERRUPT_HANDLERS, ~)
sahilmgandhi 18:6a4db94011d3 66 };
sahilmgandhi 18:6a4db94011d3 67
sahilmgandhi 18:6a4db94011d3 68 #endif
sahilmgandhi 18:6a4db94011d3 69
sahilmgandhi 18:6a4db94011d3 70 /* Forward declaration */
sahilmgandhi 18:6a4db94011d3 71 enum status_code _i2c_master_wait_for_bus(
sahilmgandhi 18:6a4db94011d3 72 struct i2c_master_module *const module);
sahilmgandhi 18:6a4db94011d3 73
sahilmgandhi 18:6a4db94011d3 74 enum status_code _i2c_master_address_response(
sahilmgandhi 18:6a4db94011d3 75 struct i2c_master_module *const module);
sahilmgandhi 18:6a4db94011d3 76
sahilmgandhi 18:6a4db94011d3 77 enum status_code _i2c_master_send_hs_master_code(
sahilmgandhi 18:6a4db94011d3 78 struct i2c_master_module *const module,
sahilmgandhi 18:6a4db94011d3 79 uint8_t hs_master_code);
sahilmgandhi 18:6a4db94011d3 80
sahilmgandhi 18:6a4db94011d3 81 /* Adding function from ASF for compatibility */
sahilmgandhi 18:6a4db94011d3 82 static enum status_code _i2c_slave_wait_for_bus(
sahilmgandhi 18:6a4db94011d3 83 struct i2c_slave_module *const module)
sahilmgandhi 18:6a4db94011d3 84 {
sahilmgandhi 18:6a4db94011d3 85 /* Sanity check arguments. */
sahilmgandhi 18:6a4db94011d3 86 MBED_ASSERT(module);
sahilmgandhi 18:6a4db94011d3 87 MBED_ASSERT(module->hw);
sahilmgandhi 18:6a4db94011d3 88
sahilmgandhi 18:6a4db94011d3 89 SercomI2cs *const i2c_hw = &(module->hw->I2CS);
sahilmgandhi 18:6a4db94011d3 90
sahilmgandhi 18:6a4db94011d3 91 /* Wait for reply. */
sahilmgandhi 18:6a4db94011d3 92 uint16_t timeout_counter = 0;
sahilmgandhi 18:6a4db94011d3 93 while ((!(i2c_hw->INTFLAG.reg & SERCOM_I2CS_INTFLAG_DRDY)) &&
sahilmgandhi 18:6a4db94011d3 94 (!(i2c_hw->INTFLAG.reg & SERCOM_I2CS_INTFLAG_PREC)) &&
sahilmgandhi 18:6a4db94011d3 95 (!(i2c_hw->INTFLAG.reg & SERCOM_I2CS_INTFLAG_AMATCH))) {
sahilmgandhi 18:6a4db94011d3 96
sahilmgandhi 18:6a4db94011d3 97 /* Check timeout condition. */
sahilmgandhi 18:6a4db94011d3 98 if (++timeout_counter >= module->buffer_timeout) {
sahilmgandhi 18:6a4db94011d3 99 return STATUS_ERR_TIMEOUT;
sahilmgandhi 18:6a4db94011d3 100 }
sahilmgandhi 18:6a4db94011d3 101 }
sahilmgandhi 18:6a4db94011d3 102 return STATUS_OK;
sahilmgandhi 18:6a4db94011d3 103 }
sahilmgandhi 18:6a4db94011d3 104
sahilmgandhi 18:6a4db94011d3 105 /** Initialize the I2C peripheral
sahilmgandhi 18:6a4db94011d3 106 *
sahilmgandhi 18:6a4db94011d3 107 * Configures the pins used by I2C, sets a default format and frequency, and enables the peripheral
sahilmgandhi 18:6a4db94011d3 108 * @param[out] obj The I2C object to initialize
sahilmgandhi 18:6a4db94011d3 109 * @param[in] sda The pin to use for SDA
sahilmgandhi 18:6a4db94011d3 110 * @param[in] scl The pin to use for SCL
sahilmgandhi 18:6a4db94011d3 111 * @return void
sahilmgandhi 18:6a4db94011d3 112 */
sahilmgandhi 18:6a4db94011d3 113 void i2c_init(i2c_t *obj, PinName sda, PinName scl)
sahilmgandhi 18:6a4db94011d3 114 {
sahilmgandhi 18:6a4db94011d3 115 Sercom* hw;
sahilmgandhi 18:6a4db94011d3 116 uint32_t mux_func;
sahilmgandhi 18:6a4db94011d3 117 struct i2c_master_config config_i2c_master;
sahilmgandhi 18:6a4db94011d3 118
sahilmgandhi 18:6a4db94011d3 119 /* Sanity check arguments */
sahilmgandhi 18:6a4db94011d3 120 MBED_ASSERT(obj);
sahilmgandhi 18:6a4db94011d3 121 MBED_ASSERT(sda != NC);
sahilmgandhi 18:6a4db94011d3 122 MBED_ASSERT(scl != NC);
sahilmgandhi 18:6a4db94011d3 123
sahilmgandhi 18:6a4db94011d3 124 if (g_sys_init == 0) {
sahilmgandhi 18:6a4db94011d3 125 system_init();
sahilmgandhi 18:6a4db94011d3 126 g_sys_init = 1;
sahilmgandhi 18:6a4db94011d3 127 }
sahilmgandhi 18:6a4db94011d3 128
sahilmgandhi 18:6a4db94011d3 129 pI2C_S(obj)->pins[0] = sda;
sahilmgandhi 18:6a4db94011d3 130 pI2C_S(obj)->pins[1] = scl;
sahilmgandhi 18:6a4db94011d3 131
sahilmgandhi 18:6a4db94011d3 132 /* Calculate SERCOM instance from pins */
sahilmgandhi 18:6a4db94011d3 133 uint32_t sercom_index = pinmap_merge_sercom(sda, scl);
sahilmgandhi 18:6a4db94011d3 134 if (sercom_index == (uint32_t)NC) {
sahilmgandhi 18:6a4db94011d3 135 return;
sahilmgandhi 18:6a4db94011d3 136 }
sahilmgandhi 18:6a4db94011d3 137 hw = (Sercom*)pinmap_peripheral_sercom(NC, sercom_index);
sahilmgandhi 18:6a4db94011d3 138
sahilmgandhi 18:6a4db94011d3 139 i2c_master_get_config_defaults(&config_i2c_master);
sahilmgandhi 18:6a4db94011d3 140
sahilmgandhi 18:6a4db94011d3 141 /* SERCOM PAD0 - SDA */
sahilmgandhi 18:6a4db94011d3 142 mux_func = pinmap_function_sercom(sda, sercom_index);
sahilmgandhi 18:6a4db94011d3 143 if (mux_func == (uint32_t)NC) return;
sahilmgandhi 18:6a4db94011d3 144 config_i2c_master.pinmux_pad0 = (sda << 16) | (mux_func & 0xFFFF);
sahilmgandhi 18:6a4db94011d3 145
sahilmgandhi 18:6a4db94011d3 146 /* SERCOM PAD1 - SCL */
sahilmgandhi 18:6a4db94011d3 147 mux_func = pinmap_function_sercom(scl, sercom_index);
sahilmgandhi 18:6a4db94011d3 148 if (mux_func == (uint32_t)NC) return;
sahilmgandhi 18:6a4db94011d3 149 config_i2c_master.pinmux_pad1 = (scl << 16) | (mux_func & 0xFFFF);
sahilmgandhi 18:6a4db94011d3 150
sahilmgandhi 18:6a4db94011d3 151 /* Default baud rate is set to 100kHz */
sahilmgandhi 18:6a4db94011d3 152 pI2C_S(obj)->baud_rate = I2C_MASTER_DEFAULT_BAUD;
sahilmgandhi 18:6a4db94011d3 153 config_i2c_master.baud_rate = pI2C_S(obj)->baud_rate / 1000;
sahilmgandhi 18:6a4db94011d3 154
sahilmgandhi 18:6a4db94011d3 155 while(i2c_master_init(&pI2C_S(obj)->master, hw, &config_i2c_master) != STATUS_OK);
sahilmgandhi 18:6a4db94011d3 156 pI2C_S(obj)->mode = I2C_MODE_MASTER;
sahilmgandhi 18:6a4db94011d3 157
sahilmgandhi 18:6a4db94011d3 158 #if DEVICE_I2C_ASYNCH
sahilmgandhi 18:6a4db94011d3 159 /* Save the i2c object */
sahilmgandhi 18:6a4db94011d3 160 i2c_instances[sercom_index] = (uint32_t)obj;
sahilmgandhi 18:6a4db94011d3 161 #endif
sahilmgandhi 18:6a4db94011d3 162
sahilmgandhi 18:6a4db94011d3 163 i2c_master_enable(&pI2C_S(obj)->master);
sahilmgandhi 18:6a4db94011d3 164 }
sahilmgandhi 18:6a4db94011d3 165
sahilmgandhi 18:6a4db94011d3 166 /** Configure the I2C frequency.
sahilmgandhi 18:6a4db94011d3 167 * @param obj The i2c object
sahilmgandhi 18:6a4db94011d3 168 * @param hz Frequency in Hz
sahilmgandhi 18:6a4db94011d3 169 */
sahilmgandhi 18:6a4db94011d3 170 void i2c_frequency(i2c_t *obj, int hz)
sahilmgandhi 18:6a4db94011d3 171 {
sahilmgandhi 18:6a4db94011d3 172 /* Temporary variables. */
sahilmgandhi 18:6a4db94011d3 173 int32_t baud_rate;
sahilmgandhi 18:6a4db94011d3 174 int32_t tmp_baud;
sahilmgandhi 18:6a4db94011d3 175 int32_t tmp_baud_hs;
sahilmgandhi 18:6a4db94011d3 176 enum status_code tmp_status_code;
sahilmgandhi 18:6a4db94011d3 177
sahilmgandhi 18:6a4db94011d3 178 /* Sanity check arguments */
sahilmgandhi 18:6a4db94011d3 179 MBED_ASSERT(obj);
sahilmgandhi 18:6a4db94011d3 180 MBED_ASSERT(pI2C_S(obj)->master.hw);
sahilmgandhi 18:6a4db94011d3 181
sahilmgandhi 18:6a4db94011d3 182 /* Return if in Slave mode, slave do not have any baud to set */
sahilmgandhi 18:6a4db94011d3 183 if (pI2C_S(obj)->mode != I2C_MODE_MASTER) return;
sahilmgandhi 18:6a4db94011d3 184
sahilmgandhi 18:6a4db94011d3 185 SercomI2cm *const i2c_module = &(pI2C_S(obj)->master.hw->I2CM);
sahilmgandhi 18:6a4db94011d3 186
sahilmgandhi 18:6a4db94011d3 187 /* Disable I2C Module */
sahilmgandhi 18:6a4db94011d3 188 i2c_master_disable(&pI2C_S(obj)->master);
sahilmgandhi 18:6a4db94011d3 189
sahilmgandhi 18:6a4db94011d3 190 baud_rate = hz / 1000; /* To kHz */
sahilmgandhi 18:6a4db94011d3 191
sahilmgandhi 18:6a4db94011d3 192 /* Give a dummy supported value */
sahilmgandhi 18:6a4db94011d3 193 pI2C_S(obj)->baud_rate_high_speed = I2C_MASTER_BAUD_RATE_3400KHZ;
sahilmgandhi 18:6a4db94011d3 194
sahilmgandhi 18:6a4db94011d3 195 uint32_t sercom_index = _sercom_get_sercom_inst_index(pI2C_S(obj)->master.hw);
sahilmgandhi 18:6a4db94011d3 196
sahilmgandhi 18:6a4db94011d3 197 /* Find and set baudrate. */
sahilmgandhi 18:6a4db94011d3 198 tmp_baud = (int32_t)(div_ceil(
sahilmgandhi 18:6a4db94011d3 199 system_gclk_chan_get_hz(SERCOM0_GCLK_ID_CORE + sercom_index), (2000*(baud_rate))) - 5);
sahilmgandhi 18:6a4db94011d3 200
sahilmgandhi 18:6a4db94011d3 201 /* Check that baudrate is supported at current speed. */
sahilmgandhi 18:6a4db94011d3 202 if (tmp_baud > 255 || tmp_baud < 0) {
sahilmgandhi 18:6a4db94011d3 203 /* Baud rate not supported. */
sahilmgandhi 18:6a4db94011d3 204 tmp_status_code = STATUS_ERR_BAUDRATE_UNAVAILABLE;
sahilmgandhi 18:6a4db94011d3 205 } else {
sahilmgandhi 18:6a4db94011d3 206 /* Find baudrate for high speed */
sahilmgandhi 18:6a4db94011d3 207 tmp_baud_hs = (int32_t)(div_ceil(
sahilmgandhi 18:6a4db94011d3 208 system_gclk_chan_get_hz(SERCOM0_GCLK_ID_CORE + sercom_index),
sahilmgandhi 18:6a4db94011d3 209 (2000*(pI2C_S(obj)->baud_rate_high_speed))) - 1);
sahilmgandhi 18:6a4db94011d3 210
sahilmgandhi 18:6a4db94011d3 211 /* Check that baudrate is supported at current speed. */
sahilmgandhi 18:6a4db94011d3 212 if (tmp_baud_hs > 255 || tmp_baud_hs < 0) {
sahilmgandhi 18:6a4db94011d3 213 /* Baud rate not supported. */
sahilmgandhi 18:6a4db94011d3 214 tmp_status_code = STATUS_ERR_BAUDRATE_UNAVAILABLE;
sahilmgandhi 18:6a4db94011d3 215 }
sahilmgandhi 18:6a4db94011d3 216 }
sahilmgandhi 18:6a4db94011d3 217 if (tmp_status_code != STATUS_ERR_BAUDRATE_UNAVAILABLE) {
sahilmgandhi 18:6a4db94011d3 218 /* Baud rate acceptable. */
sahilmgandhi 18:6a4db94011d3 219 i2c_module->BAUD.reg = SERCOM_I2CM_BAUD_BAUD(tmp_baud) | SERCOM_I2CM_BAUD_HSBAUD(tmp_baud_hs);
sahilmgandhi 18:6a4db94011d3 220 pI2C_S(obj)->baud_rate = hz;
sahilmgandhi 18:6a4db94011d3 221 }
sahilmgandhi 18:6a4db94011d3 222
sahilmgandhi 18:6a4db94011d3 223 /* Enable back the I2C Module */
sahilmgandhi 18:6a4db94011d3 224 i2c_master_enable(&pI2C_S(obj)->master);
sahilmgandhi 18:6a4db94011d3 225 }
sahilmgandhi 18:6a4db94011d3 226
sahilmgandhi 18:6a4db94011d3 227 /** Send START command.
sahilmgandhi 18:6a4db94011d3 228 * @param obj The i2c object
sahilmgandhi 18:6a4db94011d3 229 */
sahilmgandhi 18:6a4db94011d3 230 int i2c_start(i2c_t *obj)
sahilmgandhi 18:6a4db94011d3 231 {
sahilmgandhi 18:6a4db94011d3 232 /* Sanity check arguments */
sahilmgandhi 18:6a4db94011d3 233 MBED_ASSERT(obj);
sahilmgandhi 18:6a4db94011d3 234
sahilmgandhi 18:6a4db94011d3 235 if (pI2C_S(obj)->mode == I2C_MODE_MASTER) {
sahilmgandhi 18:6a4db94011d3 236 pI2C_S(obj)->start_pending = 1;
sahilmgandhi 18:6a4db94011d3 237 }
sahilmgandhi 18:6a4db94011d3 238 return 0;
sahilmgandhi 18:6a4db94011d3 239 }
sahilmgandhi 18:6a4db94011d3 240
sahilmgandhi 18:6a4db94011d3 241 /** Send STOP command.
sahilmgandhi 18:6a4db94011d3 242 * @param obj The i2c object
sahilmgandhi 18:6a4db94011d3 243 */
sahilmgandhi 18:6a4db94011d3 244 int i2c_stop(i2c_t *obj)
sahilmgandhi 18:6a4db94011d3 245 {
sahilmgandhi 18:6a4db94011d3 246 /* Sanity check arguments */
sahilmgandhi 18:6a4db94011d3 247 MBED_ASSERT(obj);
sahilmgandhi 18:6a4db94011d3 248
sahilmgandhi 18:6a4db94011d3 249 if (pI2C_S(obj)->mode == I2C_MODE_MASTER) {
sahilmgandhi 18:6a4db94011d3 250 /* Send STOP command */
sahilmgandhi 18:6a4db94011d3 251 i2c_master_send_stop(&pI2C_S(obj)->master);
sahilmgandhi 18:6a4db94011d3 252 } else {
sahilmgandhi 18:6a4db94011d3 253 SercomI2cs *const i2c_hw = &(pI2C_S(obj)->slave.hw->I2CS);
sahilmgandhi 18:6a4db94011d3 254 /* Release line and wait for next start condition */
sahilmgandhi 18:6a4db94011d3 255 i2c_hw->CTRLB.reg |= SERCOM_I2CS_CTRLB_CMD(0x2);
sahilmgandhi 18:6a4db94011d3 256 }
sahilmgandhi 18:6a4db94011d3 257
sahilmgandhi 18:6a4db94011d3 258 pI2C_S(obj)->start_pending = 0;
sahilmgandhi 18:6a4db94011d3 259
sahilmgandhi 18:6a4db94011d3 260 /* TODO: Wait till STOP is send */
sahilmgandhi 18:6a4db94011d3 261 return 0;
sahilmgandhi 18:6a4db94011d3 262 }
sahilmgandhi 18:6a4db94011d3 263
sahilmgandhi 18:6a4db94011d3 264 /** Blocking reading data.
sahilmgandhi 18:6a4db94011d3 265 * @param obj The i2c object
sahilmgandhi 18:6a4db94011d3 266 * @param address 7-bit address (last bit is 1)
sahilmgandhi 18:6a4db94011d3 267 * @param data The buffer for receiving
sahilmgandhi 18:6a4db94011d3 268 * @param length Number of bytes to read
sahilmgandhi 18:6a4db94011d3 269 * @param stop Stop to be generated after the transfer is done
sahilmgandhi 18:6a4db94011d3 270 * @return Number of read bytes
sahilmgandhi 18:6a4db94011d3 271 */
sahilmgandhi 18:6a4db94011d3 272 int i2c_read(i2c_t *obj, int address, char *data, int length, int stop)
sahilmgandhi 18:6a4db94011d3 273 {
sahilmgandhi 18:6a4db94011d3 274 /* Sanity check arguments */
sahilmgandhi 18:6a4db94011d3 275 MBED_ASSERT(obj);
sahilmgandhi 18:6a4db94011d3 276 MBED_ASSERT(pI2C_S(obj)->master.hw);
sahilmgandhi 18:6a4db94011d3 277
sahilmgandhi 18:6a4db94011d3 278 enum status_code tmp_status;
sahilmgandhi 18:6a4db94011d3 279
sahilmgandhi 18:6a4db94011d3 280 #if DEVICE_I2C_ASYNCH
sahilmgandhi 18:6a4db94011d3 281 if (i2c_active(obj)) {
sahilmgandhi 18:6a4db94011d3 282 /* I2C is busy with a job */
sahilmgandhi 18:6a4db94011d3 283 return 0;
sahilmgandhi 18:6a4db94011d3 284 }
sahilmgandhi 18:6a4db94011d3 285 #endif
sahilmgandhi 18:6a4db94011d3 286
sahilmgandhi 18:6a4db94011d3 287 struct i2c_master_packet packet;
sahilmgandhi 18:6a4db94011d3 288 packet.address = (address & 0xFF) >> 1;
sahilmgandhi 18:6a4db94011d3 289 packet.data_length = length;
sahilmgandhi 18:6a4db94011d3 290 packet.data = (uint8_t*)data;
sahilmgandhi 18:6a4db94011d3 291 packet.ten_bit_address = false;
sahilmgandhi 18:6a4db94011d3 292 packet.high_speed = false;
sahilmgandhi 18:6a4db94011d3 293
sahilmgandhi 18:6a4db94011d3 294 if (stop) {
sahilmgandhi 18:6a4db94011d3 295 tmp_status = i2c_master_read_packet_wait(&pI2C_S(obj)->master, &packet);
sahilmgandhi 18:6a4db94011d3 296 } else {
sahilmgandhi 18:6a4db94011d3 297 tmp_status = i2c_master_read_packet_wait_no_stop(&pI2C_S(obj)->master, &packet);
sahilmgandhi 18:6a4db94011d3 298 }
sahilmgandhi 18:6a4db94011d3 299
sahilmgandhi 18:6a4db94011d3 300 if (tmp_status == STATUS_OK) {
sahilmgandhi 18:6a4db94011d3 301 return length;
sahilmgandhi 18:6a4db94011d3 302 } else {
sahilmgandhi 18:6a4db94011d3 303 /* Currently, no way to track no of bytes received, so return 0 if fail */
sahilmgandhi 18:6a4db94011d3 304 return 0;
sahilmgandhi 18:6a4db94011d3 305 }
sahilmgandhi 18:6a4db94011d3 306 }
sahilmgandhi 18:6a4db94011d3 307
sahilmgandhi 18:6a4db94011d3 308 /** Blocking sending data.
sahilmgandhi 18:6a4db94011d3 309 * @param obj The i2c object
sahilmgandhi 18:6a4db94011d3 310 * @param address 7-bit address (last bit is 0)
sahilmgandhi 18:6a4db94011d3 311 * @param data The buffer for sending
sahilmgandhi 18:6a4db94011d3 312 * @param length Number of bytes to write
sahilmgandhi 18:6a4db94011d3 313 * @param stop Stop to be generated after the transfer is done
sahilmgandhi 18:6a4db94011d3 314 * @return Number of written bytes
sahilmgandhi 18:6a4db94011d3 315 */
sahilmgandhi 18:6a4db94011d3 316 int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop)
sahilmgandhi 18:6a4db94011d3 317 {
sahilmgandhi 18:6a4db94011d3 318 /* Sanity check arguments */
sahilmgandhi 18:6a4db94011d3 319 MBED_ASSERT(obj);
sahilmgandhi 18:6a4db94011d3 320 MBED_ASSERT(pI2C_S(obj)->master.hw);
sahilmgandhi 18:6a4db94011d3 321
sahilmgandhi 18:6a4db94011d3 322 enum status_code tmp_status;
sahilmgandhi 18:6a4db94011d3 323
sahilmgandhi 18:6a4db94011d3 324 #if DEVICE_I2C_ASYNCH
sahilmgandhi 18:6a4db94011d3 325 if (i2c_active(obj)) {
sahilmgandhi 18:6a4db94011d3 326 /* I2C is busy with a job */
sahilmgandhi 18:6a4db94011d3 327 return 0;
sahilmgandhi 18:6a4db94011d3 328 }
sahilmgandhi 18:6a4db94011d3 329 #endif
sahilmgandhi 18:6a4db94011d3 330
sahilmgandhi 18:6a4db94011d3 331 struct i2c_master_packet packet;
sahilmgandhi 18:6a4db94011d3 332 packet.address = (address & 0xFF) >> 1;
sahilmgandhi 18:6a4db94011d3 333 packet.data_length = length;
sahilmgandhi 18:6a4db94011d3 334 packet.data = (uint8_t *)data;
sahilmgandhi 18:6a4db94011d3 335 packet.ten_bit_address = false;
sahilmgandhi 18:6a4db94011d3 336 packet.high_speed = false;
sahilmgandhi 18:6a4db94011d3 337
sahilmgandhi 18:6a4db94011d3 338 if (stop) {
sahilmgandhi 18:6a4db94011d3 339 tmp_status = i2c_master_write_packet_wait(&pI2C_S(obj)->master, &packet);
sahilmgandhi 18:6a4db94011d3 340 } else {
sahilmgandhi 18:6a4db94011d3 341 tmp_status = i2c_master_write_packet_wait_no_stop(&pI2C_S(obj)->master, &packet);
sahilmgandhi 18:6a4db94011d3 342 }
sahilmgandhi 18:6a4db94011d3 343
sahilmgandhi 18:6a4db94011d3 344 if (tmp_status == STATUS_OK) {
sahilmgandhi 18:6a4db94011d3 345 return length;
sahilmgandhi 18:6a4db94011d3 346 } else {
sahilmgandhi 18:6a4db94011d3 347 /* Currently, no way to track no of bytes transmitted, so return 0 if fail */
sahilmgandhi 18:6a4db94011d3 348 return 0;
sahilmgandhi 18:6a4db94011d3 349 }
sahilmgandhi 18:6a4db94011d3 350 }
sahilmgandhi 18:6a4db94011d3 351
sahilmgandhi 18:6a4db94011d3 352 /** Reset I2C peripheral.
sahilmgandhi 18:6a4db94011d3 353 * @param obj The i2c object
sahilmgandhi 18:6a4db94011d3 354 */
sahilmgandhi 18:6a4db94011d3 355 void i2c_reset(i2c_t *obj)
sahilmgandhi 18:6a4db94011d3 356 {
sahilmgandhi 18:6a4db94011d3 357 /* Sanity check arguments */
sahilmgandhi 18:6a4db94011d3 358 MBED_ASSERT(obj);
sahilmgandhi 18:6a4db94011d3 359
sahilmgandhi 18:6a4db94011d3 360 /* Send STOP */
sahilmgandhi 18:6a4db94011d3 361 i2c_stop(obj);
sahilmgandhi 18:6a4db94011d3 362
sahilmgandhi 18:6a4db94011d3 363 pI2C_S(obj)->start_pending = 0;
sahilmgandhi 18:6a4db94011d3 364 }
sahilmgandhi 18:6a4db94011d3 365
sahilmgandhi 18:6a4db94011d3 366 /** Write address preceded by START condition.
sahilmgandhi 18:6a4db94011d3 367 * @param obj The i2c object
sahilmgandhi 18:6a4db94011d3 368 * @param address Address to be placed
sahilmgandhi 18:6a4db94011d3 369 * @param rw_flag read or write flag
sahilmgandhi 18:6a4db94011d3 370 * @return 1 if NAK was received, 0 if ACK was received, 2 for timeout.
sahilmgandhi 18:6a4db94011d3 371 */
sahilmgandhi 18:6a4db94011d3 372 int i2c_write_address(i2c_t *obj, int address, int rw_flag)
sahilmgandhi 18:6a4db94011d3 373 {
sahilmgandhi 18:6a4db94011d3 374 /* Sanity check arguments */
sahilmgandhi 18:6a4db94011d3 375 MBED_ASSERT(obj);
sahilmgandhi 18:6a4db94011d3 376 MBED_ASSERT(pI2C_S(obj)->master.hw);
sahilmgandhi 18:6a4db94011d3 377
sahilmgandhi 18:6a4db94011d3 378 enum status_code tmp_status;
sahilmgandhi 18:6a4db94011d3 379 SercomI2cm *const i2c_module = &(pI2C_S(obj)->master.hw->I2CM);
sahilmgandhi 18:6a4db94011d3 380
sahilmgandhi 18:6a4db94011d3 381 _i2c_master_wait_for_sync(&pI2C_S(obj)->master);
sahilmgandhi 18:6a4db94011d3 382
sahilmgandhi 18:6a4db94011d3 383 /* Set action to ACK. */
sahilmgandhi 18:6a4db94011d3 384 i2c_module->CTRLB.reg &= ~SERCOM_I2CM_CTRLB_ACKACT;
sahilmgandhi 18:6a4db94011d3 385
sahilmgandhi 18:6a4db94011d3 386 /* Write 7-bit address + read/write flag */
sahilmgandhi 18:6a4db94011d3 387 i2c_module->ADDR.reg = ((address & 0x7F) << 1) | (rw_flag & 0x01) | (0 << SERCOM_I2CM_ADDR_HS_Pos);
sahilmgandhi 18:6a4db94011d3 388
sahilmgandhi 18:6a4db94011d3 389 /* Wait for response on bus. */
sahilmgandhi 18:6a4db94011d3 390 tmp_status = _i2c_master_wait_for_bus(&pI2C_S(obj)->master);
sahilmgandhi 18:6a4db94011d3 391 /* Check for error. */
sahilmgandhi 18:6a4db94011d3 392 if (tmp_status != STATUS_OK) {
sahilmgandhi 18:6a4db94011d3 393 return I2C_ERROR_BUS_BUSY;
sahilmgandhi 18:6a4db94011d3 394 }
sahilmgandhi 18:6a4db94011d3 395 /* Check for address response error unless previous error is detected. */
sahilmgandhi 18:6a4db94011d3 396 tmp_status = _i2c_master_address_response(&pI2C_S(obj)->master);
sahilmgandhi 18:6a4db94011d3 397 if (tmp_status != STATUS_OK) {
sahilmgandhi 18:6a4db94011d3 398 return I2C_ERROR_NO_SLAVE;
sahilmgandhi 18:6a4db94011d3 399 }
sahilmgandhi 18:6a4db94011d3 400
sahilmgandhi 18:6a4db94011d3 401 return 0;
sahilmgandhi 18:6a4db94011d3 402 }
sahilmgandhi 18:6a4db94011d3 403
sahilmgandhi 18:6a4db94011d3 404 /** Read one byte.
sahilmgandhi 18:6a4db94011d3 405 * @param obj The i2c object
sahilmgandhi 18:6a4db94011d3 406 * @param last Acknowledge
sahilmgandhi 18:6a4db94011d3 407 * @return The read byte
sahilmgandhi 18:6a4db94011d3 408 */
sahilmgandhi 18:6a4db94011d3 409 int i2c_byte_read(i2c_t *obj, int last)
sahilmgandhi 18:6a4db94011d3 410 {
sahilmgandhi 18:6a4db94011d3 411 int data = -1;
sahilmgandhi 18:6a4db94011d3 412 /* Sanity check arguments */
sahilmgandhi 18:6a4db94011d3 413 MBED_ASSERT(obj);
sahilmgandhi 18:6a4db94011d3 414 MBED_ASSERT(pI2C_S(obj)->master.hw);
sahilmgandhi 18:6a4db94011d3 415
sahilmgandhi 18:6a4db94011d3 416 enum status_code tmp_status;
sahilmgandhi 18:6a4db94011d3 417
sahilmgandhi 18:6a4db94011d3 418 if (pI2C_S(obj)->mode == I2C_MODE_MASTER) {
sahilmgandhi 18:6a4db94011d3 419 SercomI2cm *const i2c_module = &(pI2C_S(obj)->master.hw->I2CM);
sahilmgandhi 18:6a4db94011d3 420
sahilmgandhi 18:6a4db94011d3 421 if (last) {
sahilmgandhi 18:6a4db94011d3 422 /* Set action to nack. */
sahilmgandhi 18:6a4db94011d3 423 i2c_module->CTRLB.reg |= SERCOM_I2CM_CTRLB_ACKACT;
sahilmgandhi 18:6a4db94011d3 424 } else {
sahilmgandhi 18:6a4db94011d3 425 /* Set action to ack. */
sahilmgandhi 18:6a4db94011d3 426 i2c_module->CTRLB.reg &= ~SERCOM_I2CM_CTRLB_ACKACT;
sahilmgandhi 18:6a4db94011d3 427 }
sahilmgandhi 18:6a4db94011d3 428
sahilmgandhi 18:6a4db94011d3 429 /* Check that bus ownership is not lost. */
sahilmgandhi 18:6a4db94011d3 430 if (!(i2c_module->STATUS.reg & SERCOM_I2CM_STATUS_BUSSTATE(2))) {
sahilmgandhi 18:6a4db94011d3 431 return -1; /* Return invalid data*/
sahilmgandhi 18:6a4db94011d3 432 }
sahilmgandhi 18:6a4db94011d3 433
sahilmgandhi 18:6a4db94011d3 434 /* Save data to buffer. */
sahilmgandhi 18:6a4db94011d3 435 _i2c_master_wait_for_sync(&pI2C_S(obj)->master);
sahilmgandhi 18:6a4db94011d3 436 data = i2c_module->DATA.reg;
sahilmgandhi 18:6a4db94011d3 437 /* Wait for response. */
sahilmgandhi 18:6a4db94011d3 438 tmp_status = _i2c_master_wait_for_bus(&pI2C_S(obj)->master);
sahilmgandhi 18:6a4db94011d3 439
sahilmgandhi 18:6a4db94011d3 440 /* Check for error. */
sahilmgandhi 18:6a4db94011d3 441 if (tmp_status != STATUS_OK) {
sahilmgandhi 18:6a4db94011d3 442 return -1; /* Return invalid data*/
sahilmgandhi 18:6a4db94011d3 443 }
sahilmgandhi 18:6a4db94011d3 444
sahilmgandhi 18:6a4db94011d3 445 } else {
sahilmgandhi 18:6a4db94011d3 446 #if DEVICE_I2CSLAVE
sahilmgandhi 18:6a4db94011d3 447 SercomI2cs *const i2c_hw = &(pI2C_S(obj)->slave.hw->I2CS);
sahilmgandhi 18:6a4db94011d3 448
sahilmgandhi 18:6a4db94011d3 449 /* Check direction */
sahilmgandhi 18:6a4db94011d3 450 if (i2c_hw->STATUS.reg & SERCOM_I2CS_STATUS_DIR) {
sahilmgandhi 18:6a4db94011d3 451 /* Write request from master, send NACK and return */
sahilmgandhi 18:6a4db94011d3 452 i2c_hw->CTRLB.reg |= SERCOM_I2CS_CTRLB_ACKACT;
sahilmgandhi 18:6a4db94011d3 453 i2c_hw->CTRLB.reg |= SERCOM_I2CS_CTRLB_CMD(0x3);
sahilmgandhi 18:6a4db94011d3 454 return -1; /* Return invalid data*/
sahilmgandhi 18:6a4db94011d3 455 }
sahilmgandhi 18:6a4db94011d3 456
sahilmgandhi 18:6a4db94011d3 457 if (i2c_hw->INTFLAG.reg & SERCOM_I2CS_INTFLAG_AMATCH) {
sahilmgandhi 18:6a4db94011d3 458 /* Request from master, Address not yet acknowledged */
sahilmgandhi 18:6a4db94011d3 459 i2c_hw->CTRLB.reg &= ~SERCOM_I2CS_CTRLB_ACKACT;
sahilmgandhi 18:6a4db94011d3 460 i2c_hw->CTRLB.reg |= SERCOM_I2CS_CTRLB_CMD(0x3);
sahilmgandhi 18:6a4db94011d3 461 i2c_hw->INTFLAG.reg = SERCOM_I2CS_INTFLAG_AMATCH;
sahilmgandhi 18:6a4db94011d3 462 }
sahilmgandhi 18:6a4db94011d3 463 if (last) {
sahilmgandhi 18:6a4db94011d3 464 /* Set action to nack. */
sahilmgandhi 18:6a4db94011d3 465 i2c_hw->CTRLB.reg |= SERCOM_I2CM_CTRLB_ACKACT;
sahilmgandhi 18:6a4db94011d3 466 } else {
sahilmgandhi 18:6a4db94011d3 467 /* Set action to ack. */
sahilmgandhi 18:6a4db94011d3 468 i2c_hw->CTRLB.reg &= ~SERCOM_I2CM_CTRLB_ACKACT;
sahilmgandhi 18:6a4db94011d3 469 }
sahilmgandhi 18:6a4db94011d3 470
sahilmgandhi 18:6a4db94011d3 471 /* Wait for next byte or stop condition */
sahilmgandhi 18:6a4db94011d3 472 tmp_status = _i2c_slave_wait_for_bus(&pI2C_S(obj)->slave);
sahilmgandhi 18:6a4db94011d3 473 if (tmp_status != STATUS_OK) {
sahilmgandhi 18:6a4db94011d3 474 /* Timeout, return */
sahilmgandhi 18:6a4db94011d3 475 return -1;
sahilmgandhi 18:6a4db94011d3 476 }
sahilmgandhi 18:6a4db94011d3 477
sahilmgandhi 18:6a4db94011d3 478 if (i2c_hw->INTFLAG.reg & SERCOM_I2CS_INTFLAG_PREC) {
sahilmgandhi 18:6a4db94011d3 479 /* Master sent stop condition, or repeated start, read done */
sahilmgandhi 18:6a4db94011d3 480 /* Clear stop flag */
sahilmgandhi 18:6a4db94011d3 481 i2c_hw->INTFLAG.reg = SERCOM_I2CS_INTFLAG_PREC;
sahilmgandhi 18:6a4db94011d3 482 return -1;
sahilmgandhi 18:6a4db94011d3 483 }
sahilmgandhi 18:6a4db94011d3 484
sahilmgandhi 18:6a4db94011d3 485 /* Read data */
sahilmgandhi 18:6a4db94011d3 486 _i2c_slave_wait_for_sync(&pI2C_S(obj)->slave);
sahilmgandhi 18:6a4db94011d3 487 data = i2c_hw->DATA.reg;
sahilmgandhi 18:6a4db94011d3 488 #endif
sahilmgandhi 18:6a4db94011d3 489 }
sahilmgandhi 18:6a4db94011d3 490
sahilmgandhi 18:6a4db94011d3 491 return data;
sahilmgandhi 18:6a4db94011d3 492 }
sahilmgandhi 18:6a4db94011d3 493
sahilmgandhi 18:6a4db94011d3 494 /** Write one byte.
sahilmgandhi 18:6a4db94011d3 495 * @param obj The i2c object
sahilmgandhi 18:6a4db94011d3 496 * @param data Byte to be written
sahilmgandhi 18:6a4db94011d3 497 * @return 1 if NAK was received, 0 if ACK was received, 2 for timeout.
sahilmgandhi 18:6a4db94011d3 498 */
sahilmgandhi 18:6a4db94011d3 499 int i2c_byte_write(i2c_t *obj, int data)
sahilmgandhi 18:6a4db94011d3 500 {
sahilmgandhi 18:6a4db94011d3 501 /* Sanity check arguments */
sahilmgandhi 18:6a4db94011d3 502 MBED_ASSERT(obj);
sahilmgandhi 18:6a4db94011d3 503 MBED_ASSERT(pI2C_S(obj)->master.hw);
sahilmgandhi 18:6a4db94011d3 504
sahilmgandhi 18:6a4db94011d3 505 enum status_code tmp_status;
sahilmgandhi 18:6a4db94011d3 506
sahilmgandhi 18:6a4db94011d3 507 data = data & 0xFF;
sahilmgandhi 18:6a4db94011d3 508
sahilmgandhi 18:6a4db94011d3 509 if (pI2C_S(obj)->mode == I2C_MODE_MASTER) {
sahilmgandhi 18:6a4db94011d3 510 SercomI2cm *const i2c_module = &(pI2C_S(obj)->master.hw->I2CM);
sahilmgandhi 18:6a4db94011d3 511
sahilmgandhi 18:6a4db94011d3 512 if (pI2C_S(obj)->start_pending) {
sahilmgandhi 18:6a4db94011d3 513 pI2C_S(obj)->start_pending = 0;
sahilmgandhi 18:6a4db94011d3 514 /* Write address */
sahilmgandhi 18:6a4db94011d3 515 return i2c_write_address(obj, (data >> 1), (data & 0x01));
sahilmgandhi 18:6a4db94011d3 516 } else {
sahilmgandhi 18:6a4db94011d3 517 /* Write data */
sahilmgandhi 18:6a4db94011d3 518 /* Check that bus ownership is not lost. */
sahilmgandhi 18:6a4db94011d3 519 if (!(i2c_module->STATUS.reg & SERCOM_I2CM_STATUS_BUSSTATE(2))) {
sahilmgandhi 18:6a4db94011d3 520 return I2C_ERROR_NO_SLAVE;
sahilmgandhi 18:6a4db94011d3 521 }
sahilmgandhi 18:6a4db94011d3 522
sahilmgandhi 18:6a4db94011d3 523 /* Write byte to slave. */
sahilmgandhi 18:6a4db94011d3 524 _i2c_master_wait_for_sync(&pI2C_S(obj)->master);
sahilmgandhi 18:6a4db94011d3 525 i2c_module->DATA.reg = data;
sahilmgandhi 18:6a4db94011d3 526
sahilmgandhi 18:6a4db94011d3 527 /* Wait for response. */
sahilmgandhi 18:6a4db94011d3 528 tmp_status = _i2c_master_wait_for_bus(&pI2C_S(obj)->master);
sahilmgandhi 18:6a4db94011d3 529 /* Check for error. */
sahilmgandhi 18:6a4db94011d3 530 if (tmp_status != STATUS_OK) {
sahilmgandhi 18:6a4db94011d3 531 return I2C_ERROR_BUS_BUSY;
sahilmgandhi 18:6a4db94011d3 532 }
sahilmgandhi 18:6a4db94011d3 533
sahilmgandhi 18:6a4db94011d3 534 /* Check for NACK from slave. */
sahilmgandhi 18:6a4db94011d3 535 if (i2c_module->STATUS.reg & SERCOM_I2CM_STATUS_RXNACK) {
sahilmgandhi 18:6a4db94011d3 536 /* Return bad data value. */
sahilmgandhi 18:6a4db94011d3 537 return I2C_ERROR_NO_SLAVE;
sahilmgandhi 18:6a4db94011d3 538 }
sahilmgandhi 18:6a4db94011d3 539 }
sahilmgandhi 18:6a4db94011d3 540 } else {
sahilmgandhi 18:6a4db94011d3 541 #if DEVICE_I2CSLAVE
sahilmgandhi 18:6a4db94011d3 542 SercomI2cs *const i2c_hw = &(pI2C_S(obj)->slave.hw->I2CS);
sahilmgandhi 18:6a4db94011d3 543
sahilmgandhi 18:6a4db94011d3 544 if (i2c_hw->INTFLAG.reg & SERCOM_I2CS_INTFLAG_AMATCH) {
sahilmgandhi 18:6a4db94011d3 545 /* Read request from master, Address not yet acknowledged */
sahilmgandhi 18:6a4db94011d3 546 i2c_hw->CTRLB.reg &= ~SERCOM_I2CS_CTRLB_ACKACT;
sahilmgandhi 18:6a4db94011d3 547 i2c_hw->CTRLB.reg |= SERCOM_I2CS_CTRLB_CMD(0x3);
sahilmgandhi 18:6a4db94011d3 548 i2c_hw->INTFLAG.reg = SERCOM_I2CS_INTFLAG_AMATCH;
sahilmgandhi 18:6a4db94011d3 549 }
sahilmgandhi 18:6a4db94011d3 550
sahilmgandhi 18:6a4db94011d3 551 /* Write data */
sahilmgandhi 18:6a4db94011d3 552 _i2c_slave_wait_for_sync(&pI2C_S(obj)->slave);
sahilmgandhi 18:6a4db94011d3 553 i2c_hw->DATA.reg = data;
sahilmgandhi 18:6a4db94011d3 554
sahilmgandhi 18:6a4db94011d3 555 /* Wait for response from master */
sahilmgandhi 18:6a4db94011d3 556 tmp_status = _i2c_slave_wait_for_bus(&pI2C_S(obj)->slave);
sahilmgandhi 18:6a4db94011d3 557
sahilmgandhi 18:6a4db94011d3 558 if (tmp_status != STATUS_OK) {
sahilmgandhi 18:6a4db94011d3 559 /* Timeout, return */
sahilmgandhi 18:6a4db94011d3 560 return I2C_ERROR_BUS_BUSY;
sahilmgandhi 18:6a4db94011d3 561 }
sahilmgandhi 18:6a4db94011d3 562
sahilmgandhi 18:6a4db94011d3 563 if (i2c_hw->STATUS.reg & SERCOM_I2CS_STATUS_RXNACK) {
sahilmgandhi 18:6a4db94011d3 564 /* NACK from master, abort */
sahilmgandhi 18:6a4db94011d3 565 /* Release line */
sahilmgandhi 18:6a4db94011d3 566 i2c_hw->CTRLB.reg |= SERCOM_I2CS_CTRLB_CMD(0x02);
sahilmgandhi 18:6a4db94011d3 567
sahilmgandhi 18:6a4db94011d3 568 return I2C_ERROR_NO_SLAVE;
sahilmgandhi 18:6a4db94011d3 569 }
sahilmgandhi 18:6a4db94011d3 570 #endif
sahilmgandhi 18:6a4db94011d3 571 }
sahilmgandhi 18:6a4db94011d3 572
sahilmgandhi 18:6a4db94011d3 573 return 0;
sahilmgandhi 18:6a4db94011d3 574 }
sahilmgandhi 18:6a4db94011d3 575
sahilmgandhi 18:6a4db94011d3 576
sahilmgandhi 18:6a4db94011d3 577 #if DEVICE_I2CSLAVE
sahilmgandhi 18:6a4db94011d3 578
sahilmgandhi 18:6a4db94011d3 579 /**
sahilmgandhi 18:6a4db94011d3 580 * \defgroup SynchI2C Synchronous I2C Hardware Abstraction Layer for slave
sahilmgandhi 18:6a4db94011d3 581 * @{
sahilmgandhi 18:6a4db94011d3 582 */
sahilmgandhi 18:6a4db94011d3 583
sahilmgandhi 18:6a4db94011d3 584 /** Configure I2C as slave or master.
sahilmgandhi 18:6a4db94011d3 585 * @param obj The I2C object
sahilmgandhi 18:6a4db94011d3 586 * @param enable_slave configure I2C in slave mode or not
sahilmgandhi 18:6a4db94011d3 587 * @return void
sahilmgandhi 18:6a4db94011d3 588 */
sahilmgandhi 18:6a4db94011d3 589 void i2c_slave_mode(i2c_t *obj, int enable_slave)
sahilmgandhi 18:6a4db94011d3 590 {
sahilmgandhi 18:6a4db94011d3 591 int i;
sahilmgandhi 18:6a4db94011d3 592 /* Sanity check arguments */
sahilmgandhi 18:6a4db94011d3 593 MBED_ASSERT(obj);
sahilmgandhi 18:6a4db94011d3 594 MBED_ASSERT(pI2C_S(obj)->master.hw);
sahilmgandhi 18:6a4db94011d3 595
sahilmgandhi 18:6a4db94011d3 596 uint32_t mux_func[2];
sahilmgandhi 18:6a4db94011d3 597 uint32_t sercom_index = _sercom_get_sercom_inst_index(pI2C_S(obj)->master.hw);
sahilmgandhi 18:6a4db94011d3 598 for (i=0; i<2; i++) {
sahilmgandhi 18:6a4db94011d3 599 mux_func[i] = pinmap_function_sercom(pI2C_S(obj)->pins[0], sercom_index);
sahilmgandhi 18:6a4db94011d3 600 if (mux_func[i] == (uint32_t)NC) return;
sahilmgandhi 18:6a4db94011d3 601 }
sahilmgandhi 18:6a4db94011d3 602
sahilmgandhi 18:6a4db94011d3 603 if (enable_slave) {
sahilmgandhi 18:6a4db94011d3 604 /* Disable I2C Master module if active */
sahilmgandhi 18:6a4db94011d3 605 i2c_master_disable(&pI2C_S(obj)->master);
sahilmgandhi 18:6a4db94011d3 606
sahilmgandhi 18:6a4db94011d3 607 struct i2c_slave_config config_i2c_slave;
sahilmgandhi 18:6a4db94011d3 608 i2c_slave_get_config_defaults(&config_i2c_slave);
sahilmgandhi 18:6a4db94011d3 609
sahilmgandhi 18:6a4db94011d3 610 /* SERCOM PAD0 - SDA */
sahilmgandhi 18:6a4db94011d3 611 config_i2c_slave.pinmux_pad0 = (pI2C_S(obj)->pins[0] << 16) | (mux_func[0] & 0xFFFF);
sahilmgandhi 18:6a4db94011d3 612 /* SERCOM PAD1 - SCL */
sahilmgandhi 18:6a4db94011d3 613 config_i2c_slave.pinmux_pad1 = (pI2C_S(obj)->pins[1] << 16) | (mux_func[1] & 0xFFFF);
sahilmgandhi 18:6a4db94011d3 614
sahilmgandhi 18:6a4db94011d3 615 i2c_slave_init(&pI2C_S(obj)->slave, pI2C_S(obj)->master.hw, &config_i2c_slave);
sahilmgandhi 18:6a4db94011d3 616
sahilmgandhi 18:6a4db94011d3 617 pI2C_S(obj)->mode = I2C_MODE_SLAVE;
sahilmgandhi 18:6a4db94011d3 618
sahilmgandhi 18:6a4db94011d3 619 i2c_slave_enable(&pI2C_S(obj)->slave);
sahilmgandhi 18:6a4db94011d3 620 } else {
sahilmgandhi 18:6a4db94011d3 621 if ((pI2C_S(obj)->master.hw) && (pI2C_S(obj)->mode == I2C_MODE_MASTER)) {
sahilmgandhi 18:6a4db94011d3 622 /* Already configured, enable and return */
sahilmgandhi 18:6a4db94011d3 623 i2c_master_enable(&pI2C_S(obj)->master);
sahilmgandhi 18:6a4db94011d3 624 return;
sahilmgandhi 18:6a4db94011d3 625 } else if ((pI2C_S(obj)->slave.hw) && (pI2C_S(obj)->mode == I2C_MODE_SLAVE)) {
sahilmgandhi 18:6a4db94011d3 626 /* Disable slave */
sahilmgandhi 18:6a4db94011d3 627 i2c_slave_disable(&pI2C_S(obj)->slave);
sahilmgandhi 18:6a4db94011d3 628 }
sahilmgandhi 18:6a4db94011d3 629
sahilmgandhi 18:6a4db94011d3 630 struct i2c_master_config config_i2c_master;
sahilmgandhi 18:6a4db94011d3 631 /* SERCOM PAD0 - SDA */
sahilmgandhi 18:6a4db94011d3 632 config_i2c_master.pinmux_pad0 = (pI2C_S(obj)->pins[0] << 16) | (mux_func[0] & 0xFFFF);
sahilmgandhi 18:6a4db94011d3 633 /* SERCOM PAD1 - SCL */
sahilmgandhi 18:6a4db94011d3 634 config_i2c_master.pinmux_pad1 = (pI2C_S(obj)->pins[1] << 16) | (mux_func[1] & 0xFFFF);
sahilmgandhi 18:6a4db94011d3 635 /* Baud rate */
sahilmgandhi 18:6a4db94011d3 636 config_i2c_master.baud_rate = pI2C_S(obj)->baud_rate / 1000;
sahilmgandhi 18:6a4db94011d3 637
sahilmgandhi 18:6a4db94011d3 638 while(i2c_master_init(&pI2C_S(obj)->master, pI2C_S(obj)->master.hw, &config_i2c_master) != STATUS_OK);
sahilmgandhi 18:6a4db94011d3 639 pI2C_S(obj)->mode = I2C_MODE_MASTER;
sahilmgandhi 18:6a4db94011d3 640
sahilmgandhi 18:6a4db94011d3 641 i2c_master_enable(&pI2C_S(obj)->master);
sahilmgandhi 18:6a4db94011d3 642 }
sahilmgandhi 18:6a4db94011d3 643 }
sahilmgandhi 18:6a4db94011d3 644
sahilmgandhi 18:6a4db94011d3 645 /** Check to see if the I2C slave has been addressed.
sahilmgandhi 18:6a4db94011d3 646 * @param obj The I2C object
sahilmgandhi 18:6a4db94011d3 647 * @return The status - 1 - read addresses, 2 - write to all slaves,
sahilmgandhi 18:6a4db94011d3 648 * 3 write addressed, 0 - the slave has not been addressed
sahilmgandhi 18:6a4db94011d3 649 */
sahilmgandhi 18:6a4db94011d3 650 int i2c_slave_receive(i2c_t *obj)
sahilmgandhi 18:6a4db94011d3 651 {
sahilmgandhi 18:6a4db94011d3 652 /* Sanity check arguments */
sahilmgandhi 18:6a4db94011d3 653 MBED_ASSERT(obj);
sahilmgandhi 18:6a4db94011d3 654 MBED_ASSERT(pI2C_S(obj)->slave.hw);
sahilmgandhi 18:6a4db94011d3 655
sahilmgandhi 18:6a4db94011d3 656 SercomI2cs *const i2c_module = &(pI2C_S(obj)->slave.hw->I2CS);
sahilmgandhi 18:6a4db94011d3 657
sahilmgandhi 18:6a4db94011d3 658 if (i2c_module->INTFLAG.reg & SERCOM_I2CS_INTFLAG_AMATCH) {
sahilmgandhi 18:6a4db94011d3 659 if (i2c_module->STATUS.reg & SERCOM_I2CS_STATUS_DIR) {
sahilmgandhi 18:6a4db94011d3 660 /* Slave is read addressed */
sahilmgandhi 18:6a4db94011d3 661 return 1;
sahilmgandhi 18:6a4db94011d3 662 } else {
sahilmgandhi 18:6a4db94011d3 663 if (!(i2c_module->DATA.reg & 0xFF)) {
sahilmgandhi 18:6a4db94011d3 664 /* General call address detected */
sahilmgandhi 18:6a4db94011d3 665 return 2;
sahilmgandhi 18:6a4db94011d3 666 } else {
sahilmgandhi 18:6a4db94011d3 667 /* Slave is write addressed */
sahilmgandhi 18:6a4db94011d3 668 return 3;
sahilmgandhi 18:6a4db94011d3 669 }
sahilmgandhi 18:6a4db94011d3 670 }
sahilmgandhi 18:6a4db94011d3 671 }
sahilmgandhi 18:6a4db94011d3 672
sahilmgandhi 18:6a4db94011d3 673 return 0;
sahilmgandhi 18:6a4db94011d3 674 }
sahilmgandhi 18:6a4db94011d3 675
sahilmgandhi 18:6a4db94011d3 676 /** Blocking reading data.
sahilmgandhi 18:6a4db94011d3 677 * @param obj The i2c slave object
sahilmgandhi 18:6a4db94011d3 678 * @param data The buffer for receiving
sahilmgandhi 18:6a4db94011d3 679 * @param length Number of bytes to read
sahilmgandhi 18:6a4db94011d3 680 * @return Number of read bytes
sahilmgandhi 18:6a4db94011d3 681 */
sahilmgandhi 18:6a4db94011d3 682 int i2c_slave_read(i2c_t *obj, char *data, int length)
sahilmgandhi 18:6a4db94011d3 683 {
sahilmgandhi 18:6a4db94011d3 684 /* Sanity check arguments */
sahilmgandhi 18:6a4db94011d3 685 MBED_ASSERT(obj);
sahilmgandhi 18:6a4db94011d3 686 MBED_ASSERT(pI2C_S(obj)->slave.hw);
sahilmgandhi 18:6a4db94011d3 687
sahilmgandhi 18:6a4db94011d3 688 if (!data || !length) return 0;
sahilmgandhi 18:6a4db94011d3 689
sahilmgandhi 18:6a4db94011d3 690 enum status_code tmp_status;
sahilmgandhi 18:6a4db94011d3 691
sahilmgandhi 18:6a4db94011d3 692 struct i2c_slave_packet packet;
sahilmgandhi 18:6a4db94011d3 693 packet.data_length = length;
sahilmgandhi 18:6a4db94011d3 694 packet.data = (uint8_t*)data;
sahilmgandhi 18:6a4db94011d3 695
sahilmgandhi 18:6a4db94011d3 696 tmp_status = i2c_slave_read_packet_wait(&pI2C_S(obj)->slave, &packet);
sahilmgandhi 18:6a4db94011d3 697
sahilmgandhi 18:6a4db94011d3 698 if (tmp_status == STATUS_OK) {
sahilmgandhi 18:6a4db94011d3 699 return length;
sahilmgandhi 18:6a4db94011d3 700 } else {
sahilmgandhi 18:6a4db94011d3 701 /* Currently, no way to track no of bytes transmitted, so return 0 */
sahilmgandhi 18:6a4db94011d3 702 return 0;
sahilmgandhi 18:6a4db94011d3 703 }
sahilmgandhi 18:6a4db94011d3 704
sahilmgandhi 18:6a4db94011d3 705 }
sahilmgandhi 18:6a4db94011d3 706
sahilmgandhi 18:6a4db94011d3 707 /** Blocking writing data.
sahilmgandhi 18:6a4db94011d3 708 * @param obj The i2c slave object
sahilmgandhi 18:6a4db94011d3 709 * @param data The buffer for transmitting
sahilmgandhi 18:6a4db94011d3 710 * @param length Number of bytes to write
sahilmgandhi 18:6a4db94011d3 711 * @return Number of bytes written
sahilmgandhi 18:6a4db94011d3 712 */
sahilmgandhi 18:6a4db94011d3 713 int i2c_slave_write(i2c_t *obj, const char *data, int length)
sahilmgandhi 18:6a4db94011d3 714 {
sahilmgandhi 18:6a4db94011d3 715 /* Sanity check arguments */
sahilmgandhi 18:6a4db94011d3 716 MBED_ASSERT(obj);
sahilmgandhi 18:6a4db94011d3 717 MBED_ASSERT(pI2C_S(obj)->slave.hw);
sahilmgandhi 18:6a4db94011d3 718
sahilmgandhi 18:6a4db94011d3 719 if (!data || !length) return 0;
sahilmgandhi 18:6a4db94011d3 720
sahilmgandhi 18:6a4db94011d3 721 enum status_code tmp_status;
sahilmgandhi 18:6a4db94011d3 722
sahilmgandhi 18:6a4db94011d3 723 struct i2c_slave_packet packet;
sahilmgandhi 18:6a4db94011d3 724 packet.data_length = length;
sahilmgandhi 18:6a4db94011d3 725 packet.data = (uint8_t *)data;
sahilmgandhi 18:6a4db94011d3 726
sahilmgandhi 18:6a4db94011d3 727 tmp_status = i2c_slave_write_packet_wait(&pI2C_S(obj)->slave, &packet);
sahilmgandhi 18:6a4db94011d3 728
sahilmgandhi 18:6a4db94011d3 729 if (tmp_status == STATUS_OK) {
sahilmgandhi 18:6a4db94011d3 730 return length;
sahilmgandhi 18:6a4db94011d3 731 } else {
sahilmgandhi 18:6a4db94011d3 732 /* Currently, no way to track no of bytes transmitted, so return 0 */
sahilmgandhi 18:6a4db94011d3 733 return 0;
sahilmgandhi 18:6a4db94011d3 734 }
sahilmgandhi 18:6a4db94011d3 735
sahilmgandhi 18:6a4db94011d3 736 }
sahilmgandhi 18:6a4db94011d3 737
sahilmgandhi 18:6a4db94011d3 738 /** Configure I2C slave address.
sahilmgandhi 18:6a4db94011d3 739 * @param obj The I2C object
sahilmgandhi 18:6a4db94011d3 740 * @param idx Currently not used
sahilmgandhi 18:6a4db94011d3 741 * @param address The address to be set
sahilmgandhi 18:6a4db94011d3 742 * @param mask Currently not used
sahilmgandhi 18:6a4db94011d3 743 */
sahilmgandhi 18:6a4db94011d3 744 void i2c_slave_address(i2c_t *obj, int idx, uint32_t address, uint32_t mask)
sahilmgandhi 18:6a4db94011d3 745 {
sahilmgandhi 18:6a4db94011d3 746 /* Sanity check arguments */
sahilmgandhi 18:6a4db94011d3 747 MBED_ASSERT(obj);
sahilmgandhi 18:6a4db94011d3 748 MBED_ASSERT(pI2C_S(obj)->slave.hw);
sahilmgandhi 18:6a4db94011d3 749
sahilmgandhi 18:6a4db94011d3 750 /* Disable I2C Module */
sahilmgandhi 18:6a4db94011d3 751 i2c_slave_disable(&pI2C_S(obj)->slave);
sahilmgandhi 18:6a4db94011d3 752
sahilmgandhi 18:6a4db94011d3 753 SercomI2cs *const i2c_hw = &(pI2C_S(obj)->slave.hw->I2CS);
sahilmgandhi 18:6a4db94011d3 754
sahilmgandhi 18:6a4db94011d3 755 address = (address & 0xFF) >> 1;
sahilmgandhi 18:6a4db94011d3 756 if (!mask) {
sahilmgandhi 18:6a4db94011d3 757 mask = (0xFE >> 1);
sahilmgandhi 18:6a4db94011d3 758 }
sahilmgandhi 18:6a4db94011d3 759 /* Set the address and address mask */
sahilmgandhi 18:6a4db94011d3 760 i2c_hw->ADDR.reg = (address << SERCOM_I2CS_ADDR_ADDR_Pos) |
sahilmgandhi 18:6a4db94011d3 761 (mask << SERCOM_I2CS_ADDR_ADDRMASK_Pos) |
sahilmgandhi 18:6a4db94011d3 762 (0 << SERCOM_I2CS_ADDR_TENBITEN_Pos) |
sahilmgandhi 18:6a4db94011d3 763 (1 << SERCOM_I2CS_ADDR_GENCEN_Pos);
sahilmgandhi 18:6a4db94011d3 764
sahilmgandhi 18:6a4db94011d3 765 /* Enable I2C Module */
sahilmgandhi 18:6a4db94011d3 766 i2c_slave_enable(&pI2C_S(obj)->slave);
sahilmgandhi 18:6a4db94011d3 767 }
sahilmgandhi 18:6a4db94011d3 768
sahilmgandhi 18:6a4db94011d3 769 #endif /* DEVICE_I2CSLAVE */
sahilmgandhi 18:6a4db94011d3 770
sahilmgandhi 18:6a4db94011d3 771 /**@}*/
sahilmgandhi 18:6a4db94011d3 772
sahilmgandhi 18:6a4db94011d3 773 #if DEVICE_I2C_ASYNCH
sahilmgandhi 18:6a4db94011d3 774
sahilmgandhi 18:6a4db94011d3 775 /**
sahilmgandhi 18:6a4db94011d3 776 * \defgroup AsynchI2C Asynchronous I2C Hardware Abstraction Layer
sahilmgandhi 18:6a4db94011d3 777 * @{
sahilmgandhi 18:6a4db94011d3 778 */
sahilmgandhi 18:6a4db94011d3 779
sahilmgandhi 18:6a4db94011d3 780 /**
sahilmgandhi 18:6a4db94011d3 781 * \internal
sahilmgandhi 18:6a4db94011d3 782 * Callback for transfer finish.
sahilmgandhi 18:6a4db94011d3 783 *
sahilmgandhi 18:6a4db94011d3 784 * \param[in,out] module Pointer to SPI software instance struct
sahilmgandhi 18:6a4db94011d3 785 */
sahilmgandhi 18:6a4db94011d3 786 void i2c_transfer_complete_callback(struct i2c_master_module *const module)
sahilmgandhi 18:6a4db94011d3 787 {
sahilmgandhi 18:6a4db94011d3 788 uint32_t sercom_index = _sercom_get_sercom_inst_index(module->hw);
sahilmgandhi 18:6a4db94011d3 789
sahilmgandhi 18:6a4db94011d3 790 if (sercom_index >= SERCOM_INST_NUM) {
sahilmgandhi 18:6a4db94011d3 791 /* TODO: Abort operation */
sahilmgandhi 18:6a4db94011d3 792 return;
sahilmgandhi 18:6a4db94011d3 793 }
sahilmgandhi 18:6a4db94011d3 794
sahilmgandhi 18:6a4db94011d3 795 i2c_t *obj = (i2c_t*)i2c_instances[sercom_index];
sahilmgandhi 18:6a4db94011d3 796
sahilmgandhi 18:6a4db94011d3 797 i2c_master_disable_callback(&pI2C_S(obj)->master, I2C_MASTER_CALLBACK_WRITE_COMPLETE);
sahilmgandhi 18:6a4db94011d3 798 i2c_master_disable_callback(&pI2C_S(obj)->master, I2C_MASTER_CALLBACK_READ_COMPLETE);
sahilmgandhi 18:6a4db94011d3 799 i2c_master_disable_callback(&pI2C_S(obj)->master, I2C_MASTER_CALLBACK_ERROR);
sahilmgandhi 18:6a4db94011d3 800
sahilmgandhi 18:6a4db94011d3 801 /* Call the handler function */
sahilmgandhi 18:6a4db94011d3 802 if (pI2C_S(obj)->handler) {
sahilmgandhi 18:6a4db94011d3 803 ((I2CHandler)pI2C_S(obj)->handler)();
sahilmgandhi 18:6a4db94011d3 804 }
sahilmgandhi 18:6a4db94011d3 805 }
sahilmgandhi 18:6a4db94011d3 806
sahilmgandhi 18:6a4db94011d3 807 /**
sahilmgandhi 18:6a4db94011d3 808 * \internal
sahilmgandhi 18:6a4db94011d3 809 * Callback for write complete. Initiate read from here.
sahilmgandhi 18:6a4db94011d3 810 *
sahilmgandhi 18:6a4db94011d3 811 * \param[in,out] module Pointer to SPI software instance struct
sahilmgandhi 18:6a4db94011d3 812 */
sahilmgandhi 18:6a4db94011d3 813 void i2c_write_complete_callback(struct i2c_master_module *const module)
sahilmgandhi 18:6a4db94011d3 814 {
sahilmgandhi 18:6a4db94011d3 815 uint32_t sercom_index = _sercom_get_sercom_inst_index(module->hw);
sahilmgandhi 18:6a4db94011d3 816
sahilmgandhi 18:6a4db94011d3 817 if (sercom_index >= SERCOM_INST_NUM) {
sahilmgandhi 18:6a4db94011d3 818 /* TODO: Abort operation */
sahilmgandhi 18:6a4db94011d3 819 return;
sahilmgandhi 18:6a4db94011d3 820 }
sahilmgandhi 18:6a4db94011d3 821
sahilmgandhi 18:6a4db94011d3 822 i2c_t *obj = (i2c_t*)i2c_instances[sercom_index];
sahilmgandhi 18:6a4db94011d3 823
sahilmgandhi 18:6a4db94011d3 824 if (!(pI2C_S(obj)->rd_packet.data) || (pI2C_S(obj)->rd_packet.data_length == 0)) {
sahilmgandhi 18:6a4db94011d3 825 /* Call the handler function */
sahilmgandhi 18:6a4db94011d3 826 i2c_transfer_complete_callback(module);
sahilmgandhi 18:6a4db94011d3 827 } else {
sahilmgandhi 18:6a4db94011d3 828 i2c_master_disable_callback(&pI2C_S(obj)->master, I2C_MASTER_CALLBACK_WRITE_COMPLETE);
sahilmgandhi 18:6a4db94011d3 829
sahilmgandhi 18:6a4db94011d3 830 /* Register read complete callback */
sahilmgandhi 18:6a4db94011d3 831 i2c_master_register_callback(&pI2C_S(obj)->master, i2c_transfer_complete_callback, I2C_MASTER_CALLBACK_READ_COMPLETE);
sahilmgandhi 18:6a4db94011d3 832 i2c_master_enable_callback(&pI2C_S(obj)->master, I2C_MASTER_CALLBACK_READ_COMPLETE);
sahilmgandhi 18:6a4db94011d3 833
sahilmgandhi 18:6a4db94011d3 834 /* Initiate read operation */
sahilmgandhi 18:6a4db94011d3 835 if (pI2C_S(obj)->master.send_stop) {
sahilmgandhi 18:6a4db94011d3 836 i2c_master_read_packet_job(&pI2C_S(obj)->master,&pI2C_S(obj)->rd_packet);
sahilmgandhi 18:6a4db94011d3 837 } else {
sahilmgandhi 18:6a4db94011d3 838 i2c_master_read_packet_job_no_stop(&pI2C_S(obj)->master, &pI2C_S(obj)->rd_packet);
sahilmgandhi 18:6a4db94011d3 839 }
sahilmgandhi 18:6a4db94011d3 840 }
sahilmgandhi 18:6a4db94011d3 841 }
sahilmgandhi 18:6a4db94011d3 842
sahilmgandhi 18:6a4db94011d3 843 /** Start i2c asynchronous transfer.
sahilmgandhi 18:6a4db94011d3 844 * @param obj The I2C object
sahilmgandhi 18:6a4db94011d3 845 * @param tx The buffer to send
sahilmgandhi 18:6a4db94011d3 846 * @param tx_length The number of words to transmit
sahilmgandhi 18:6a4db94011d3 847 * @param rx The buffer to receive
sahilmgandhi 18:6a4db94011d3 848 * @param rx_length The number of words to receive
sahilmgandhi 18:6a4db94011d3 849 * @param address The address to be set - 7bit or 9 bit
sahilmgandhi 18:6a4db94011d3 850 * @param stop If true, stop will be generated after the transfer is done
sahilmgandhi 18:6a4db94011d3 851 * @param handler The I2C IRQ handler to be set
sahilmgandhi 18:6a4db94011d3 852 * @param hint DMA hint usage
sahilmgandhi 18:6a4db94011d3 853 */
sahilmgandhi 18:6a4db94011d3 854 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 855 {
sahilmgandhi 18:6a4db94011d3 856 /* Sanity check arguments */
sahilmgandhi 18:6a4db94011d3 857 MBED_ASSERT(obj);
sahilmgandhi 18:6a4db94011d3 858 MBED_ASSERT(pI2C_S(obj)->master.hw);
sahilmgandhi 18:6a4db94011d3 859
sahilmgandhi 18:6a4db94011d3 860 /* Return if in Slave mode */
sahilmgandhi 18:6a4db94011d3 861 if (pI2C_S(obj)->mode != I2C_MODE_MASTER) return;
sahilmgandhi 18:6a4db94011d3 862
sahilmgandhi 18:6a4db94011d3 863 uint32_t sercom_index = _sercom_get_sercom_inst_index(pI2C_S(obj)->master.hw);
sahilmgandhi 18:6a4db94011d3 864
sahilmgandhi 18:6a4db94011d3 865 /* Init i2c packet. */
sahilmgandhi 18:6a4db94011d3 866 pI2C_S(obj)->wr_packet.address = address >> 1;
sahilmgandhi 18:6a4db94011d3 867 pI2C_S(obj)->wr_packet.data_length = tx_length;
sahilmgandhi 18:6a4db94011d3 868 pI2C_S(obj)->wr_packet.data = (uint8_t *)tx;
sahilmgandhi 18:6a4db94011d3 869
sahilmgandhi 18:6a4db94011d3 870 pI2C_S(obj)->rd_packet.address = address >> 1;
sahilmgandhi 18:6a4db94011d3 871 pI2C_S(obj)->rd_packet.data_length = rx_length;
sahilmgandhi 18:6a4db94011d3 872 pI2C_S(obj)->rd_packet.data = rx;
sahilmgandhi 18:6a4db94011d3 873
sahilmgandhi 18:6a4db94011d3 874 /* Save event mask and handler function pointer */
sahilmgandhi 18:6a4db94011d3 875 pI2C_S(obj)->events = event;
sahilmgandhi 18:6a4db94011d3 876 pI2C_S(obj)->handler = handler;
sahilmgandhi 18:6a4db94011d3 877
sahilmgandhi 18:6a4db94011d3 878 /* TODO: Current implementation is interrupt based only */
sahilmgandhi 18:6a4db94011d3 879
sahilmgandhi 18:6a4db94011d3 880 /* Set interrupt handler to default handler of ASF */
sahilmgandhi 18:6a4db94011d3 881 /* Enable interrupt */
sahilmgandhi 18:6a4db94011d3 882 NVIC_SetVector((IRQn_Type)((uint32_t)SERCOM0_IRQn + sercom_index), sercom_irq_handlers[sercom_index]);
sahilmgandhi 18:6a4db94011d3 883 NVIC_EnableIRQ((IRQn_Type)((uint32_t)SERCOM0_IRQn + sercom_index));
sahilmgandhi 18:6a4db94011d3 884
sahilmgandhi 18:6a4db94011d3 885 /* Register callbacks */
sahilmgandhi 18:6a4db94011d3 886 i2c_master_register_callback(&pI2C_S(obj)->master, i2c_transfer_complete_callback, I2C_MASTER_CALLBACK_ERROR);
sahilmgandhi 18:6a4db94011d3 887 i2c_master_enable_callback(&pI2C_S(obj)->master, I2C_MASTER_CALLBACK_ERROR);
sahilmgandhi 18:6a4db94011d3 888 if (tx && tx_length) {
sahilmgandhi 18:6a4db94011d3 889 i2c_master_register_callback(&pI2C_S(obj)->master, i2c_write_complete_callback, I2C_MASTER_CALLBACK_WRITE_COMPLETE);
sahilmgandhi 18:6a4db94011d3 890 i2c_master_enable_callback(&pI2C_S(obj)->master, I2C_MASTER_CALLBACK_WRITE_COMPLETE);
sahilmgandhi 18:6a4db94011d3 891
sahilmgandhi 18:6a4db94011d3 892 /* Start I2C write */
sahilmgandhi 18:6a4db94011d3 893 if (stop) {
sahilmgandhi 18:6a4db94011d3 894 i2c_master_write_packet_job(&pI2C_S(obj)->master, &pI2C_S(obj)->wr_packet);
sahilmgandhi 18:6a4db94011d3 895 } else {
sahilmgandhi 18:6a4db94011d3 896 i2c_master_write_packet_job_no_stop(&pI2C_S(obj)->master, &pI2C_S(obj)->wr_packet);
sahilmgandhi 18:6a4db94011d3 897 }
sahilmgandhi 18:6a4db94011d3 898 } else if (rx && rx_length) {
sahilmgandhi 18:6a4db94011d3 899 i2c_master_register_callback(&pI2C_S(obj)->master, i2c_transfer_complete_callback, I2C_MASTER_CALLBACK_READ_COMPLETE);
sahilmgandhi 18:6a4db94011d3 900 i2c_master_enable_callback(&pI2C_S(obj)->master, I2C_MASTER_CALLBACK_READ_COMPLETE);
sahilmgandhi 18:6a4db94011d3 901
sahilmgandhi 18:6a4db94011d3 902 /* Start I2C read */
sahilmgandhi 18:6a4db94011d3 903 if (stop) {
sahilmgandhi 18:6a4db94011d3 904 i2c_master_read_packet_job(&pI2C_S(obj)->master,&pI2C_S(obj)->rd_packet);
sahilmgandhi 18:6a4db94011d3 905 } else {
sahilmgandhi 18:6a4db94011d3 906 i2c_master_read_packet_job_no_stop(&pI2C_S(obj)->master, &pI2C_S(obj)->rd_packet);
sahilmgandhi 18:6a4db94011d3 907 }
sahilmgandhi 18:6a4db94011d3 908 } else {
sahilmgandhi 18:6a4db94011d3 909 /* Nothing to transfer, invoke callback */
sahilmgandhi 18:6a4db94011d3 910 i2c_transfer_complete_callback(&pI2C_S(obj)->master);
sahilmgandhi 18:6a4db94011d3 911 }
sahilmgandhi 18:6a4db94011d3 912 }
sahilmgandhi 18:6a4db94011d3 913
sahilmgandhi 18:6a4db94011d3 914 /** The asynchronous IRQ handler
sahilmgandhi 18:6a4db94011d3 915 * @param obj The I2C object which holds the transfer information
sahilmgandhi 18:6a4db94011d3 916 * @return event flags if a transfer termination condition was met or 0 otherwise.
sahilmgandhi 18:6a4db94011d3 917 */
sahilmgandhi 18:6a4db94011d3 918 uint32_t i2c_irq_handler_asynch(i2c_t *obj)
sahilmgandhi 18:6a4db94011d3 919 {
sahilmgandhi 18:6a4db94011d3 920 /* Sanity check arguments */
sahilmgandhi 18:6a4db94011d3 921 MBED_ASSERT(obj);
sahilmgandhi 18:6a4db94011d3 922 MBED_ASSERT(pI2C_S(obj)->master.hw);
sahilmgandhi 18:6a4db94011d3 923
sahilmgandhi 18:6a4db94011d3 924 uint32_t event_mask = pI2C_S(obj)->events;
sahilmgandhi 18:6a4db94011d3 925
sahilmgandhi 18:6a4db94011d3 926 /* TODO: Current implementation is interrupt based only */
sahilmgandhi 18:6a4db94011d3 927
sahilmgandhi 18:6a4db94011d3 928 switch (pI2C_S(obj)->master.status) {
sahilmgandhi 18:6a4db94011d3 929 case STATUS_OK:
sahilmgandhi 18:6a4db94011d3 930 /* Transfer is complete */
sahilmgandhi 18:6a4db94011d3 931 return (I2C_EVENT_TRANSFER_COMPLETE & event_mask);
sahilmgandhi 18:6a4db94011d3 932
sahilmgandhi 18:6a4db94011d3 933 case STATUS_ERR_BAD_ADDRESS:
sahilmgandhi 18:6a4db94011d3 934 /* Received a NACK */
sahilmgandhi 18:6a4db94011d3 935 return (I2C_EVENT_ERROR_NO_SLAVE & event_mask);
sahilmgandhi 18:6a4db94011d3 936
sahilmgandhi 18:6a4db94011d3 937 case STATUS_ERR_PACKET_COLLISION:
sahilmgandhi 18:6a4db94011d3 938 /* An error occurred in between transfer */
sahilmgandhi 18:6a4db94011d3 939 return (I2C_EVENT_ERROR & event_mask);
sahilmgandhi 18:6a4db94011d3 940
sahilmgandhi 18:6a4db94011d3 941 default:
sahilmgandhi 18:6a4db94011d3 942 return 0;
sahilmgandhi 18:6a4db94011d3 943 }
sahilmgandhi 18:6a4db94011d3 944
sahilmgandhi 18:6a4db94011d3 945 //return 0;
sahilmgandhi 18:6a4db94011d3 946 }
sahilmgandhi 18:6a4db94011d3 947
sahilmgandhi 18:6a4db94011d3 948 /** Attempts to determine if I2C peripheral is already in use.
sahilmgandhi 18:6a4db94011d3 949 * @param obj The I2C object
sahilmgandhi 18:6a4db94011d3 950 * @return non-zero if the I2C module is active or zero if it is not
sahilmgandhi 18:6a4db94011d3 951 */
sahilmgandhi 18:6a4db94011d3 952 uint8_t i2c_active(i2c_t *obj)
sahilmgandhi 18:6a4db94011d3 953 {
sahilmgandhi 18:6a4db94011d3 954 /* Sanity check arguments */
sahilmgandhi 18:6a4db94011d3 955 MBED_ASSERT(obj);
sahilmgandhi 18:6a4db94011d3 956 MBED_ASSERT(pI2C_S(obj)->master.hw);
sahilmgandhi 18:6a4db94011d3 957
sahilmgandhi 18:6a4db94011d3 958 return (pI2C_S(obj)->master.status == STATUS_BUSY);
sahilmgandhi 18:6a4db94011d3 959 }
sahilmgandhi 18:6a4db94011d3 960
sahilmgandhi 18:6a4db94011d3 961 /** Abort ongoing asynchronous transaction.
sahilmgandhi 18:6a4db94011d3 962 * @param obj The I2C object
sahilmgandhi 18:6a4db94011d3 963 */
sahilmgandhi 18:6a4db94011d3 964 void i2c_abort_asynch(i2c_t *obj)
sahilmgandhi 18:6a4db94011d3 965 {
sahilmgandhi 18:6a4db94011d3 966 /* Sanity check arguments */
sahilmgandhi 18:6a4db94011d3 967 MBED_ASSERT(obj);
sahilmgandhi 18:6a4db94011d3 968 MBED_ASSERT(pI2C_S(obj)->master.hw);
sahilmgandhi 18:6a4db94011d3 969
sahilmgandhi 18:6a4db94011d3 970 /* Pointer to the hardware module instance */
sahilmgandhi 18:6a4db94011d3 971 SercomI2cm *const i2c_module = &(pI2C_S(obj)->master.hw->I2CM);
sahilmgandhi 18:6a4db94011d3 972
sahilmgandhi 18:6a4db94011d3 973 /* Abort ongoing job */
sahilmgandhi 18:6a4db94011d3 974
sahilmgandhi 18:6a4db94011d3 975 /* Stop packet operation */
sahilmgandhi 18:6a4db94011d3 976 i2c_module->INTENCLR.reg = SERCOM_I2CM_INTENCLR_MB | SERCOM_I2CM_INTENCLR_SB;
sahilmgandhi 18:6a4db94011d3 977
sahilmgandhi 18:6a4db94011d3 978 pI2C_S(obj)->master.buffer_length = 0;
sahilmgandhi 18:6a4db94011d3 979 pI2C_S(obj)->master.buffer_remaining = 0;
sahilmgandhi 18:6a4db94011d3 980
sahilmgandhi 18:6a4db94011d3 981 /* Send nack and stop command unless arbitration is lost */
sahilmgandhi 18:6a4db94011d3 982 if ((pI2C_S(obj)->master.status != STATUS_ERR_PACKET_COLLISION) && pI2C_S(obj)->master.send_stop) {
sahilmgandhi 18:6a4db94011d3 983 _i2c_master_wait_for_sync(&pI2C_S(obj)->master);
sahilmgandhi 18:6a4db94011d3 984 i2c_module->CTRLB.reg |= SERCOM_I2CM_CTRLB_ACKACT | SERCOM_I2CM_CTRLB_CMD(3);
sahilmgandhi 18:6a4db94011d3 985 }
sahilmgandhi 18:6a4db94011d3 986
sahilmgandhi 18:6a4db94011d3 987 /* Disable any registered callback */
sahilmgandhi 18:6a4db94011d3 988 i2c_master_disable_callback(&pI2C_S(obj)->master, I2C_MASTER_CALLBACK_WRITE_COMPLETE);
sahilmgandhi 18:6a4db94011d3 989 i2c_master_disable_callback(&pI2C_S(obj)->master, I2C_MASTER_CALLBACK_READ_COMPLETE);
sahilmgandhi 18:6a4db94011d3 990 i2c_master_disable_callback(&pI2C_S(obj)->master, I2C_MASTER_CALLBACK_ERROR);
sahilmgandhi 18:6a4db94011d3 991
sahilmgandhi 18:6a4db94011d3 992 pI2C_S(obj)->master.status = STATUS_ABORTED;
sahilmgandhi 18:6a4db94011d3 993 }
sahilmgandhi 18:6a4db94011d3 994
sahilmgandhi 18:6a4db94011d3 995 #endif