mbed library sources. Supersedes mbed-src.

Dependents:   Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more

Committer:
AnnaBridge
Date:
Wed Feb 20 22:31:08 2019 +0000
Revision:
189:f392fc9709a3
Parent:
188:bcfe06ba3d64
mbed library release version 165

Who changed what in which revision?

UserRevisionLine numberNew contents of line
AnnaBridge 188:bcfe06ba3d64 1 /*
AnnaBridge 188:bcfe06ba3d64 2 * mbed Microcontroller Library
AnnaBridge 188:bcfe06ba3d64 3 * Copyright (c) 2017-2018 Future Electronics
AnnaBridge 189:f392fc9709a3 4 * Copyright (c) 2018-2019 Cypress Semiconductor Corporation
AnnaBridge 189:f392fc9709a3 5 * SPDX-License-Identifier: Apache-2.0
AnnaBridge 188:bcfe06ba3d64 6 *
AnnaBridge 188:bcfe06ba3d64 7 * Licensed under the Apache License, Version 2.0 (the "License");
AnnaBridge 188:bcfe06ba3d64 8 * you may not use this file except in compliance with the License.
AnnaBridge 188:bcfe06ba3d64 9 * You may obtain a copy of the License at
AnnaBridge 188:bcfe06ba3d64 10 *
AnnaBridge 188:bcfe06ba3d64 11 * http://www.apache.org/licenses/LICENSE-2.0
AnnaBridge 188:bcfe06ba3d64 12 *
AnnaBridge 188:bcfe06ba3d64 13 * Unless required by applicable law or agreed to in writing, software
AnnaBridge 188:bcfe06ba3d64 14 * distributed under the License is distributed on an "AS IS" BASIS,
AnnaBridge 188:bcfe06ba3d64 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
AnnaBridge 188:bcfe06ba3d64 16 * See the License for the specific language governing permissions and
AnnaBridge 188:bcfe06ba3d64 17 * limitations under the License.
AnnaBridge 188:bcfe06ba3d64 18 */
AnnaBridge 188:bcfe06ba3d64 19
AnnaBridge 188:bcfe06ba3d64 20 #include "cmsis.h"
AnnaBridge 188:bcfe06ba3d64 21 #include "mbed_assert.h"
AnnaBridge 188:bcfe06ba3d64 22 #include "mbed_error.h"
AnnaBridge 188:bcfe06ba3d64 23 #include "PeripheralPins.h"
AnnaBridge 188:bcfe06ba3d64 24 #include "pinmap.h"
AnnaBridge 188:bcfe06ba3d64 25 #include "i2c_api.h"
AnnaBridge 188:bcfe06ba3d64 26 #include "psoc6_utils.h"
AnnaBridge 188:bcfe06ba3d64 27
AnnaBridge 189:f392fc9709a3 28 #include "cy_sysclk.h"
AnnaBridge 189:f392fc9709a3 29 #include "cy_gpio.h"
AnnaBridge 189:f392fc9709a3 30 #include "cy_scb_i2c.h"
AnnaBridge 189:f392fc9709a3 31 #include "cy_sysint.h"
AnnaBridge 188:bcfe06ba3d64 32
AnnaBridge 188:bcfe06ba3d64 33 #define I2C_DEFAULT_SPEED 100000
AnnaBridge 188:bcfe06ba3d64 34 #define NUM_I2C_PORTS 8
AnnaBridge 188:bcfe06ba3d64 35 #define I2C_DEFAULT_IRQ_PRIORITY 3
AnnaBridge 188:bcfe06ba3d64 36 #define I2C_NUM_DIVIDERS 3
AnnaBridge 188:bcfe06ba3d64 37 #define MIN_I2C_CLOCK_FREQUENCY CY_SCB_I2C_SLAVE_STD_CLK_MIN
AnnaBridge 188:bcfe06ba3d64 38 // Default timeout in milliseconds.
AnnaBridge 188:bcfe06ba3d64 39 #define I2C_DEFAULT_TIMEOUT 1000
AnnaBridge 188:bcfe06ba3d64 40
AnnaBridge 188:bcfe06ba3d64 41 #define PENDING_NONE 0
AnnaBridge 188:bcfe06ba3d64 42 #define PENDING_RX 1
AnnaBridge 188:bcfe06ba3d64 43 #define PENDING_TX 2
AnnaBridge 188:bcfe06ba3d64 44 #define PENDING_TX_RX 3
AnnaBridge 188:bcfe06ba3d64 45
AnnaBridge 188:bcfe06ba3d64 46 typedef enum {
AnnaBridge 188:bcfe06ba3d64 47 I2C_DIVIDER_LOW = 0,
AnnaBridge 188:bcfe06ba3d64 48 I2C_DIVIDER_MID,
AnnaBridge 188:bcfe06ba3d64 49 I2C_DIVIDER_HIGH,
AnnaBridge 188:bcfe06ba3d64 50 I2C_INVALID_DIVIDER = 0xff
AnnaBridge 188:bcfe06ba3d64 51 } I2cDividerType;
AnnaBridge 188:bcfe06ba3d64 52
AnnaBridge 188:bcfe06ba3d64 53
AnnaBridge 188:bcfe06ba3d64 54 typedef struct {
AnnaBridge 188:bcfe06ba3d64 55 uint32_t div_num;
AnnaBridge 188:bcfe06ba3d64 56 cy_en_divider_types_t div_type;
AnnaBridge 188:bcfe06ba3d64 57 uint32_t clk_frequency;
AnnaBridge 188:bcfe06ba3d64 58 } I2cDividerInfo;
AnnaBridge 188:bcfe06ba3d64 59
AnnaBridge 188:bcfe06ba3d64 60
AnnaBridge 188:bcfe06ba3d64 61 static const cy_stc_scb_i2c_config_t default_i2c_config = {
AnnaBridge 188:bcfe06ba3d64 62 .i2cMode = CY_SCB_I2C_MASTER,
AnnaBridge 188:bcfe06ba3d64 63 .useRxFifo = true,
AnnaBridge 188:bcfe06ba3d64 64 .useTxFifo = true,
AnnaBridge 188:bcfe06ba3d64 65 .slaveAddress = 0,
AnnaBridge 188:bcfe06ba3d64 66 .slaveAddressMask = 0,
AnnaBridge 188:bcfe06ba3d64 67 .acceptAddrInFifo = false,
AnnaBridge 188:bcfe06ba3d64 68 .ackGeneralAddr = false,
AnnaBridge 188:bcfe06ba3d64 69 .enableWakeFromSleep = false
AnnaBridge 188:bcfe06ba3d64 70 };
AnnaBridge 188:bcfe06ba3d64 71
AnnaBridge 188:bcfe06ba3d64 72
AnnaBridge 188:bcfe06ba3d64 73 static I2cDividerInfo i2c_dividers[I2C_NUM_DIVIDERS] = {
AnnaBridge 189:f392fc9709a3 74 { I2C_INVALID_DIVIDER, CY_SYSCLK_DIV_8_BIT, CY_SCB_I2C_SLAVE_STD_CLK_MIN }, // Low divider uses lowest possible frequency.
AnnaBridge 189:f392fc9709a3 75 { I2C_INVALID_DIVIDER, CY_SYSCLK_DIV_8_BIT, CY_SCB_I2C_SLAVE_FST_CLK_MIN },
AnnaBridge 189:f392fc9709a3 76 { I2C_INVALID_DIVIDER, CY_SYSCLK_DIV_8_BIT, CY_SCB_I2C_SLAVE_FSTP_CLK_MIN }
AnnaBridge 188:bcfe06ba3d64 77 };
AnnaBridge 188:bcfe06ba3d64 78
AnnaBridge 189:f392fc9709a3 79
AnnaBridge 188:bcfe06ba3d64 80 typedef struct i2c_s i2c_obj_t;
AnnaBridge 188:bcfe06ba3d64 81
AnnaBridge 188:bcfe06ba3d64 82 #if DEVICE_I2C_ASYNCH
AnnaBridge 188:bcfe06ba3d64 83 #define OBJ_P(in) (&(in->i2c))
AnnaBridge 188:bcfe06ba3d64 84 #else
AnnaBridge 188:bcfe06ba3d64 85 #define OBJ_P(in) (in)
AnnaBridge 188:bcfe06ba3d64 86 #endif
AnnaBridge 188:bcfe06ba3d64 87
AnnaBridge 188:bcfe06ba3d64 88
AnnaBridge 188:bcfe06ba3d64 89 #if DEVICE_I2C_ASYNCH
AnnaBridge 188:bcfe06ba3d64 90
AnnaBridge 188:bcfe06ba3d64 91 static IRQn_Type i2c_irq_allocate_channel(i2c_obj_t *obj)
AnnaBridge 188:bcfe06ba3d64 92 {
AnnaBridge 188:bcfe06ba3d64 93 #if defined (TARGET_MCU_PSOC6_M0)
AnnaBridge 188:bcfe06ba3d64 94 obj->cm0p_irq_src = scb_0_interrupt_IRQn + obj->i2c_id;
AnnaBridge 188:bcfe06ba3d64 95 return cy_m0_nvic_allocate_channel(CY_SERIAL_IRQN_ID + obj->i2c_id);
AnnaBridge 188:bcfe06ba3d64 96 #else
AnnaBridge 189:f392fc9709a3 97 return (IRQn_Type)(scb_0_interrupt_IRQn + obj->i2c_id);
AnnaBridge 189:f392fc9709a3 98 #endif /* (TARGET_MCU_PSOC6_M0) */
AnnaBridge 188:bcfe06ba3d64 99 }
AnnaBridge 188:bcfe06ba3d64 100
AnnaBridge 188:bcfe06ba3d64 101 static int i2c_irq_setup_channel(i2c_obj_t *obj)
AnnaBridge 188:bcfe06ba3d64 102 {
AnnaBridge 188:bcfe06ba3d64 103 cy_stc_sysint_t irq_config;
AnnaBridge 188:bcfe06ba3d64 104
AnnaBridge 188:bcfe06ba3d64 105 if (obj->irqn == unconnected_IRQn) {
AnnaBridge 188:bcfe06ba3d64 106 IRQn_Type irqn = i2c_irq_allocate_channel(obj);
AnnaBridge 188:bcfe06ba3d64 107 if (irqn < 0) {
AnnaBridge 188:bcfe06ba3d64 108 return (-1);
AnnaBridge 188:bcfe06ba3d64 109 }
AnnaBridge 188:bcfe06ba3d64 110 // Configure NVIC
AnnaBridge 188:bcfe06ba3d64 111 irq_config.intrPriority = I2C_DEFAULT_IRQ_PRIORITY;
AnnaBridge 188:bcfe06ba3d64 112 irq_config.intrSrc = irqn;
AnnaBridge 188:bcfe06ba3d64 113 #if defined (TARGET_MCU_PSOC6_M0)
AnnaBridge 188:bcfe06ba3d64 114 irq_config.cm0pSrc = obj->cm0p_irq_src;
AnnaBridge 188:bcfe06ba3d64 115 #endif
AnnaBridge 188:bcfe06ba3d64 116 if (Cy_SysInt_Init(&irq_config, (cy_israddress)(obj->handler)) != CY_SYSINT_SUCCESS) {
AnnaBridge 189:f392fc9709a3 117 return (-1);
AnnaBridge 188:bcfe06ba3d64 118 }
AnnaBridge 188:bcfe06ba3d64 119
AnnaBridge 188:bcfe06ba3d64 120 obj->irqn = irqn;
AnnaBridge 188:bcfe06ba3d64 121 NVIC_EnableIRQ(irqn);
AnnaBridge 188:bcfe06ba3d64 122 }
AnnaBridge 188:bcfe06ba3d64 123 return 0;
AnnaBridge 188:bcfe06ba3d64 124 }
AnnaBridge 188:bcfe06ba3d64 125
AnnaBridge 188:bcfe06ba3d64 126 #endif // DEVICE_I2C_ASYNCH
AnnaBridge 188:bcfe06ba3d64 127
AnnaBridge 188:bcfe06ba3d64 128 static int allocate_divider(I2cDividerType divider)
AnnaBridge 188:bcfe06ba3d64 129 {
AnnaBridge 188:bcfe06ba3d64 130 I2cDividerInfo *p_div = &i2c_dividers[divider];
AnnaBridge 188:bcfe06ba3d64 131
AnnaBridge 188:bcfe06ba3d64 132 if (p_div->div_num == CY_INVALID_DIVIDER) {
AnnaBridge 188:bcfe06ba3d64 133 p_div->div_num = cy_clk_allocate_divider(CY_SYSCLK_DIV_8_BIT);
AnnaBridge 188:bcfe06ba3d64 134 if (p_div->div_num != CY_INVALID_DIVIDER) {
AnnaBridge 188:bcfe06ba3d64 135 p_div->div_type = CY_SYSCLK_DIV_8_BIT;
AnnaBridge 188:bcfe06ba3d64 136 } else {
AnnaBridge 188:bcfe06ba3d64 137 p_div->div_num = cy_clk_allocate_divider(CY_SYSCLK_DIV_16_BIT);
AnnaBridge 188:bcfe06ba3d64 138 if (p_div->div_num != CY_INVALID_DIVIDER) {
AnnaBridge 188:bcfe06ba3d64 139 p_div->div_type = CY_SYSCLK_DIV_16_BIT;
AnnaBridge 188:bcfe06ba3d64 140 }
AnnaBridge 188:bcfe06ba3d64 141 }
AnnaBridge 188:bcfe06ba3d64 142 }
AnnaBridge 188:bcfe06ba3d64 143
AnnaBridge 188:bcfe06ba3d64 144 if (p_div->div_num != CY_INVALID_DIVIDER) {
AnnaBridge 188:bcfe06ba3d64 145 // Set up proper frequency;
AnnaBridge 189:f392fc9709a3 146 uint32_t div_value = cy_PeriClkFreqHz / p_div->clk_frequency;
AnnaBridge 189:f392fc9709a3 147 p_div->clk_frequency = cy_PeriClkFreqHz / div_value;
AnnaBridge 188:bcfe06ba3d64 148 if (Cy_SysClk_PeriphSetDivider(p_div->div_type, p_div->div_num, div_value) == CY_SYSCLK_SUCCESS) {
AnnaBridge 188:bcfe06ba3d64 149 Cy_SysClk_PeriphEnableDivider(p_div->div_type, p_div->div_num);
AnnaBridge 188:bcfe06ba3d64 150 } else {
AnnaBridge 188:bcfe06ba3d64 151 p_div->div_num = CY_INVALID_DIVIDER;
AnnaBridge 188:bcfe06ba3d64 152 }
AnnaBridge 188:bcfe06ba3d64 153 }
AnnaBridge 188:bcfe06ba3d64 154
AnnaBridge 189:f392fc9709a3 155 return (p_div->div_num == CY_INVALID_DIVIDER) ? -1 : 0;
AnnaBridge 188:bcfe06ba3d64 156 }
AnnaBridge 188:bcfe06ba3d64 157
AnnaBridge 188:bcfe06ba3d64 158 /*
AnnaBridge 188:bcfe06ba3d64 159 * Select one of the 3 dividers used depending on the required frequency.
AnnaBridge 188:bcfe06ba3d64 160 */
AnnaBridge 188:bcfe06ba3d64 161 static I2cDividerType select_divider(uint32_t frequency)
AnnaBridge 188:bcfe06ba3d64 162 {
AnnaBridge 188:bcfe06ba3d64 163 if (frequency <= (MIN_I2C_CLOCK_FREQUENCY / CY_SCB_I2C_DUTY_CYCLE_MAX)) {
AnnaBridge 188:bcfe06ba3d64 164 // Required speed lower than min supported.
AnnaBridge 188:bcfe06ba3d64 165 return I2C_INVALID_DIVIDER;
AnnaBridge 188:bcfe06ba3d64 166 } else if (frequency <= CY_SCB_I2C_STD_DATA_RATE) {
AnnaBridge 188:bcfe06ba3d64 167 return I2C_DIVIDER_LOW;
AnnaBridge 188:bcfe06ba3d64 168 } else if (frequency <= CY_SCB_I2C_FST_DATA_RATE) {
AnnaBridge 188:bcfe06ba3d64 169 return I2C_DIVIDER_MID;
AnnaBridge 188:bcfe06ba3d64 170 } else if (frequency <= CY_SCB_I2C_FSTP_DATA_RATE) {
AnnaBridge 188:bcfe06ba3d64 171 return I2C_DIVIDER_HIGH;
AnnaBridge 188:bcfe06ba3d64 172 } else {
AnnaBridge 188:bcfe06ba3d64 173 // Required speed too high;
AnnaBridge 188:bcfe06ba3d64 174 return I2C_INVALID_DIVIDER;
AnnaBridge 188:bcfe06ba3d64 175 }
AnnaBridge 188:bcfe06ba3d64 176 }
AnnaBridge 188:bcfe06ba3d64 177
AnnaBridge 188:bcfe06ba3d64 178 /*
AnnaBridge 188:bcfe06ba3d64 179 * Initializes i2c clock for the required speed
AnnaBridge 188:bcfe06ba3d64 180 */
AnnaBridge 188:bcfe06ba3d64 181 static cy_en_sysclk_status_t i2c_init_clock(i2c_obj_t *obj, uint32_t speed)
AnnaBridge 188:bcfe06ba3d64 182 {
AnnaBridge 188:bcfe06ba3d64 183 I2cDividerInfo *p_div = NULL;
AnnaBridge 188:bcfe06ba3d64 184 cy_en_sysclk_status_t status = CY_SYSCLK_INVALID_STATE;
AnnaBridge 188:bcfe06ba3d64 185 I2cDividerType divider = select_divider(speed);
AnnaBridge 188:bcfe06ba3d64 186
AnnaBridge 188:bcfe06ba3d64 187 if (divider == I2C_INVALID_DIVIDER) {
AnnaBridge 189:f392fc9709a3 188 error("I2C: required speed/frequency is out of valid range.");
AnnaBridge 188:bcfe06ba3d64 189 }
AnnaBridge 188:bcfe06ba3d64 190
AnnaBridge 188:bcfe06ba3d64 191 if (allocate_divider(divider) < 0) {
AnnaBridge 189:f392fc9709a3 192 error("I2C: cannot allocate clock divider.");
AnnaBridge 188:bcfe06ba3d64 193 }
AnnaBridge 188:bcfe06ba3d64 194
AnnaBridge 188:bcfe06ba3d64 195 obj->divider = divider;
AnnaBridge 188:bcfe06ba3d64 196 p_div = &i2c_dividers[divider];
AnnaBridge 188:bcfe06ba3d64 197
AnnaBridge 188:bcfe06ba3d64 198 status = Cy_SysClk_PeriphAssignDivider(obj->clock, p_div->div_type, p_div->div_num);
AnnaBridge 188:bcfe06ba3d64 199 if (status != CY_SYSCLK_SUCCESS) {
AnnaBridge 189:f392fc9709a3 200 error("I2C: cannot assign clock divider.");
AnnaBridge 188:bcfe06ba3d64 201 }
AnnaBridge 188:bcfe06ba3d64 202
AnnaBridge 188:bcfe06ba3d64 203 /* Set desired speed/frequency */
AnnaBridge 188:bcfe06ba3d64 204 obj->actual_speed = Cy_SCB_I2C_SetDataRate(obj->base, speed, p_div->clk_frequency);
AnnaBridge 189:f392fc9709a3 205 return (obj->actual_speed != 0) ? CY_SYSCLK_SUCCESS : CY_SYSCLK_BAD_PARAM;
AnnaBridge 188:bcfe06ba3d64 206 }
AnnaBridge 188:bcfe06ba3d64 207
AnnaBridge 188:bcfe06ba3d64 208 /*
AnnaBridge 188:bcfe06ba3d64 209 * Initializes i/o pins for i2c sda/scl.
AnnaBridge 188:bcfe06ba3d64 210 */
AnnaBridge 188:bcfe06ba3d64 211 static void i2c_init_pins(i2c_obj_t *obj)
AnnaBridge 188:bcfe06ba3d64 212 {
AnnaBridge 189:f392fc9709a3 213 /* MBED driver reserves pins for I2C as Ditigal IO while doing I2C error
AnnaBridge 189:f392fc9709a3 214 * recovery in constructor.
AnnaBridge 189:f392fc9709a3 215 */
AnnaBridge 189:f392fc9709a3 216 pin_function(obj->pin_sda, pinmap_function(obj->pin_sda, PinMap_I2C_SDA));
AnnaBridge 189:f392fc9709a3 217 pin_function(obj->pin_scl, pinmap_function(obj->pin_scl, PinMap_I2C_SCL));
AnnaBridge 188:bcfe06ba3d64 218 }
AnnaBridge 188:bcfe06ba3d64 219
AnnaBridge 188:bcfe06ba3d64 220
AnnaBridge 188:bcfe06ba3d64 221 /*
AnnaBridge 188:bcfe06ba3d64 222 * Initializes and enables I2C/SCB.
AnnaBridge 188:bcfe06ba3d64 223 */
AnnaBridge 188:bcfe06ba3d64 224 static void i2c_init_peripheral(i2c_obj_t *obj)
AnnaBridge 188:bcfe06ba3d64 225 {
AnnaBridge 188:bcfe06ba3d64 226 cy_stc_scb_i2c_config_t i2c_config = default_i2c_config;
AnnaBridge 188:bcfe06ba3d64 227 I2cDividerInfo *p_div = &i2c_dividers[obj->divider];
AnnaBridge 188:bcfe06ba3d64 228
AnnaBridge 188:bcfe06ba3d64 229 Cy_SCB_I2C_Init(obj->base, &i2c_config, &obj->context);
AnnaBridge 189:f392fc9709a3 230 Cy_SCB_I2C_SetDataRate(obj->base, obj->actual_speed, p_div->clk_frequency);
AnnaBridge 188:bcfe06ba3d64 231 Cy_SCB_I2C_Enable(obj->base);
AnnaBridge 188:bcfe06ba3d64 232 }
AnnaBridge 188:bcfe06ba3d64 233
AnnaBridge 188:bcfe06ba3d64 234 /*
AnnaBridge 188:bcfe06ba3d64 235 * Coverts PDL status into Mbed status.
AnnaBridge 188:bcfe06ba3d64 236 */
AnnaBridge 188:bcfe06ba3d64 237 static int i2c_convert_status(cy_en_scb_i2c_status_t status)
AnnaBridge 188:bcfe06ba3d64 238 {
AnnaBridge 188:bcfe06ba3d64 239 switch (status) {
AnnaBridge 188:bcfe06ba3d64 240 case CY_SCB_I2C_MASTER_NOT_READY:
AnnaBridge 188:bcfe06ba3d64 241 case CY_SCB_I2C_MASTER_MANUAL_ARB_LOST:
AnnaBridge 188:bcfe06ba3d64 242 case CY_SCB_I2C_MASTER_MANUAL_BUS_ERR:
AnnaBridge 188:bcfe06ba3d64 243 case CY_SCB_I2C_MASTER_MANUAL_ABORT_START:
AnnaBridge 188:bcfe06ba3d64 244 return I2C_ERROR_BUS_BUSY;
AnnaBridge 188:bcfe06ba3d64 245
AnnaBridge 188:bcfe06ba3d64 246 case CY_SCB_I2C_MASTER_MANUAL_TIMEOUT:
AnnaBridge 188:bcfe06ba3d64 247 case CY_SCB_I2C_MASTER_MANUAL_ADDR_NAK:
AnnaBridge 188:bcfe06ba3d64 248 case CY_SCB_I2C_MASTER_MANUAL_NAK:
AnnaBridge 188:bcfe06ba3d64 249 return I2C_ERROR_NO_SLAVE;
AnnaBridge 188:bcfe06ba3d64 250
AnnaBridge 188:bcfe06ba3d64 251 case CY_SCB_I2C_SUCCESS:
AnnaBridge 188:bcfe06ba3d64 252 case CY_SCB_I2C_BAD_PARAM:
AnnaBridge 188:bcfe06ba3d64 253 default:
AnnaBridge 188:bcfe06ba3d64 254 return 0;
AnnaBridge 188:bcfe06ba3d64 255 }
AnnaBridge 188:bcfe06ba3d64 256 }
AnnaBridge 188:bcfe06ba3d64 257
AnnaBridge 188:bcfe06ba3d64 258 /*
AnnaBridge 188:bcfe06ba3d64 259 * Callback function to handle into and out of deep sleep state transitions.
AnnaBridge 188:bcfe06ba3d64 260 */
AnnaBridge 189:f392fc9709a3 261 #if DEVICE_SLEEP && DEVICE_LPTICKER
AnnaBridge 189:f392fc9709a3 262 static cy_en_syspm_status_t i2c_pm_callback(cy_stc_syspm_callback_params_t *callback_params, cy_en_syspm_callback_mode_t mode)
AnnaBridge 188:bcfe06ba3d64 263 {
AnnaBridge 188:bcfe06ba3d64 264 cy_stc_syspm_callback_params_t params = *callback_params;
AnnaBridge 188:bcfe06ba3d64 265 i2c_obj_t *obj = (i2c_obj_t *)params.context;
AnnaBridge 188:bcfe06ba3d64 266 params.context = &obj->context;
AnnaBridge 188:bcfe06ba3d64 267
AnnaBridge 189:f392fc9709a3 268 return Cy_SCB_I2C_DeepSleepCallback(&params, mode);
AnnaBridge 188:bcfe06ba3d64 269 }
AnnaBridge 189:f392fc9709a3 270 #endif // DEVICE_SLEEP && DEVICE_LPTICKER
AnnaBridge 188:bcfe06ba3d64 271
AnnaBridge 188:bcfe06ba3d64 272
AnnaBridge 188:bcfe06ba3d64 273 void i2c_init(i2c_t *obj_in, PinName sda, PinName scl)
AnnaBridge 188:bcfe06ba3d64 274 {
AnnaBridge 188:bcfe06ba3d64 275 i2c_obj_t *obj = OBJ_P(obj_in);
AnnaBridge 189:f392fc9709a3 276
AnnaBridge 188:bcfe06ba3d64 277 uint32_t i2c = pinmap_peripheral(sda, PinMap_I2C_SDA);
AnnaBridge 188:bcfe06ba3d64 278 i2c = pinmap_merge(i2c, pinmap_peripheral(scl, PinMap_I2C_SCL));
AnnaBridge 189:f392fc9709a3 279
AnnaBridge 189:f392fc9709a3 280 if (i2c != (uint32_t) NC) {
AnnaBridge 189:f392fc9709a3 281 /* Initialize configuration */
AnnaBridge 189:f392fc9709a3 282 obj->base = (CySCB_Type *) i2c;
AnnaBridge 189:f392fc9709a3 283 obj->i2c_id = ((I2CName) i2c - I2C_0) / (I2C_1 - I2C_0);
AnnaBridge 189:f392fc9709a3 284 obj->clock = CY_PIN_CLOCK(pinmap_function(scl, PinMap_I2C_SCL));
AnnaBridge 189:f392fc9709a3 285 obj->divider = I2C_INVALID_DIVIDER;
AnnaBridge 189:f392fc9709a3 286 obj->already_reserved = (0 != cy_reserve_scb(obj->i2c_id));
AnnaBridge 188:bcfe06ba3d64 287 obj->pin_sda = sda;
AnnaBridge 188:bcfe06ba3d64 288 obj->pin_scl = scl;
AnnaBridge 189:f392fc9709a3 289
AnnaBridge 189:f392fc9709a3 290 obj->mode = CY_SCB_I2C_MASTER;
AnnaBridge 188:bcfe06ba3d64 291 obj->timeout = I2C_DEFAULT_TIMEOUT;
AnnaBridge 189:f392fc9709a3 292
AnnaBridge 188:bcfe06ba3d64 293 #if DEVICE_I2C_ASYNCH
AnnaBridge 189:f392fc9709a3 294 obj->irqn = unconnected_IRQn;
AnnaBridge 188:bcfe06ba3d64 295 obj->pending = PENDING_NONE;
AnnaBridge 189:f392fc9709a3 296 obj->events = 0;
AnnaBridge 189:f392fc9709a3 297 #endif /* DEVICE_I2C_ASYNCH */
AnnaBridge 189:f392fc9709a3 298
AnnaBridge 189:f392fc9709a3 299 /* Check if resource severed */
AnnaBridge 189:f392fc9709a3 300 if (obj->already_reserved) {
AnnaBridge 189:f392fc9709a3 301
AnnaBridge 189:f392fc9709a3 302 /* SCB pins and clocks are connected */
AnnaBridge 189:f392fc9709a3 303
AnnaBridge 189:f392fc9709a3 304 /* Disable block and get it into the default state */
AnnaBridge 189:f392fc9709a3 305 Cy_SCB_I2C_Disable(obj->base, &obj->context);
AnnaBridge 189:f392fc9709a3 306 Cy_SCB_I2C_DeInit(obj->base);
AnnaBridge 189:f392fc9709a3 307
AnnaBridge 189:f392fc9709a3 308 /* The proper clock will be connected by i2c_init_clock(obj, I2C_DEFAULT_SPEED) */
AnnaBridge 189:f392fc9709a3 309 obj->divider = I2C_DIVIDER_LOW;
AnnaBridge 189:f392fc9709a3 310 } else {
AnnaBridge 189:f392fc9709a3 311 #if DEVICE_SLEEP && DEVICE_LPTICKER
AnnaBridge 189:f392fc9709a3 312 /* Register callback once */
AnnaBridge 189:f392fc9709a3 313 obj->pm_callback_handler.callback = i2c_pm_callback;
AnnaBridge 189:f392fc9709a3 314 obj->pm_callback_handler.type = CY_SYSPM_DEEPSLEEP;
AnnaBridge 189:f392fc9709a3 315 obj->pm_callback_handler.skipMode = 0;
AnnaBridge 189:f392fc9709a3 316 obj->pm_callback_handler.callbackParams = &obj->pm_callback_params;
AnnaBridge 189:f392fc9709a3 317 obj->pm_callback_params.base = obj->base;
AnnaBridge 189:f392fc9709a3 318 obj->pm_callback_params.context = obj;
AnnaBridge 189:f392fc9709a3 319 if (!Cy_SysPm_RegisterCallback(&obj->pm_callback_handler)) {
AnnaBridge 189:f392fc9709a3 320 error("PM callback registration failed!");
AnnaBridge 189:f392fc9709a3 321 }
AnnaBridge 189:f392fc9709a3 322 #endif /* DEVICE_SLEEP && DEVICE_LPTICKER */
AnnaBridge 189:f392fc9709a3 323 }
AnnaBridge 189:f392fc9709a3 324
AnnaBridge 189:f392fc9709a3 325 /* Configure hardware resources */
AnnaBridge 188:bcfe06ba3d64 326 i2c_init_clock(obj, I2C_DEFAULT_SPEED);
AnnaBridge 188:bcfe06ba3d64 327 i2c_init_pins(obj);
AnnaBridge 188:bcfe06ba3d64 328 i2c_init_peripheral(obj);
AnnaBridge 189:f392fc9709a3 329
AnnaBridge 188:bcfe06ba3d64 330 } else {
AnnaBridge 189:f392fc9709a3 331 error("I2C pinout mismatch. Requested pins SDA and SCL can't be used for the same I2C communication.");
AnnaBridge 188:bcfe06ba3d64 332 }
AnnaBridge 188:bcfe06ba3d64 333 }
AnnaBridge 188:bcfe06ba3d64 334
AnnaBridge 188:bcfe06ba3d64 335 void i2c_frequency(i2c_t *obj_in, int hz)
AnnaBridge 188:bcfe06ba3d64 336 {
AnnaBridge 188:bcfe06ba3d64 337 i2c_obj_t *obj = OBJ_P(obj_in);
AnnaBridge 188:bcfe06ba3d64 338 Cy_SCB_I2C_Disable(obj->base, &obj->context);
AnnaBridge 188:bcfe06ba3d64 339 i2c_init_clock(obj, hz);
AnnaBridge 188:bcfe06ba3d64 340 Cy_SCB_I2C_Enable(obj->base);
AnnaBridge 188:bcfe06ba3d64 341 }
AnnaBridge 188:bcfe06ba3d64 342
AnnaBridge 188:bcfe06ba3d64 343 int i2c_start(i2c_t *obj_in)
AnnaBridge 188:bcfe06ba3d64 344 {
AnnaBridge 189:f392fc9709a3 345 i2c_obj_t *obj = OBJ_P(obj_in);
AnnaBridge 189:f392fc9709a3 346
AnnaBridge 189:f392fc9709a3 347 if (CY_SCB_I2C_IDLE == obj->context.state) {
AnnaBridge 189:f392fc9709a3 348 /* Set the read or write direction */
AnnaBridge 189:f392fc9709a3 349 obj->context.state = CY_SCB_I2C_MASTER_ADDR;
AnnaBridge 189:f392fc9709a3 350
AnnaBridge 189:f392fc9709a3 351 /* Clean up the hardware before a transfer. Note RX FIFO is empty at here */
AnnaBridge 189:f392fc9709a3 352 Cy_SCB_ClearMasterInterrupt(obj->base, CY_SCB_I2C_MASTER_INTR_ALL);
AnnaBridge 189:f392fc9709a3 353 Cy_SCB_ClearRxInterrupt(obj->base, CY_SCB_RX_INTR_NOT_EMPTY);
AnnaBridge 189:f392fc9709a3 354 Cy_SCB_ClearTxFifo(obj->base);
AnnaBridge 189:f392fc9709a3 355
AnnaBridge 189:f392fc9709a3 356 /* Generate a Start and send address byte */
AnnaBridge 189:f392fc9709a3 357 SCB_I2C_M_CMD(obj->base) = SCB_I2C_M_CMD_M_START_ON_IDLE_Msk;
AnnaBridge 189:f392fc9709a3 358
AnnaBridge 189:f392fc9709a3 359 /* Wait until Start is generated */
AnnaBridge 189:f392fc9709a3 360 while (0 != (SCB_I2C_M_CMD(obj->base) & SCB_I2C_M_CMD_M_START_ON_IDLE_Msk)) {
AnnaBridge 189:f392fc9709a3 361 }
AnnaBridge 189:f392fc9709a3 362
AnnaBridge 189:f392fc9709a3 363 return 0;
AnnaBridge 189:f392fc9709a3 364 }
AnnaBridge 189:f392fc9709a3 365
AnnaBridge 189:f392fc9709a3 366 return (-1);
AnnaBridge 188:bcfe06ba3d64 367 }
AnnaBridge 188:bcfe06ba3d64 368
AnnaBridge 188:bcfe06ba3d64 369 int i2c_stop(i2c_t *obj_in)
AnnaBridge 188:bcfe06ba3d64 370 {
AnnaBridge 189:f392fc9709a3 371 i2c_obj_t *obj = OBJ_P(obj_in);
AnnaBridge 189:f392fc9709a3 372 cy_en_scb_i2c_status_t status = Cy_SCB_I2C_MasterSendStop(obj->base, obj->timeout, &obj->context);
AnnaBridge 189:f392fc9709a3 373
AnnaBridge 189:f392fc9709a3 374 return i2c_convert_status(status);
AnnaBridge 188:bcfe06ba3d64 375 }
AnnaBridge 188:bcfe06ba3d64 376
AnnaBridge 188:bcfe06ba3d64 377 int i2c_read(i2c_t *obj_in, int address, char *data, int length, int stop)
AnnaBridge 188:bcfe06ba3d64 378 {
AnnaBridge 188:bcfe06ba3d64 379 cy_en_scb_i2c_status_t status = CY_SCB_I2C_SUCCESS;
AnnaBridge 188:bcfe06ba3d64 380 i2c_obj_t *obj = OBJ_P(obj_in);
AnnaBridge 188:bcfe06ba3d64 381 cy_en_scb_i2c_command_t ack = CY_SCB_I2C_ACK;
AnnaBridge 188:bcfe06ba3d64 382 int byte_count = 0;
AnnaBridge 188:bcfe06ba3d64 383 address >>= 1;
AnnaBridge 188:bcfe06ba3d64 384
AnnaBridge 188:bcfe06ba3d64 385 // Start transaction, send address.
AnnaBridge 188:bcfe06ba3d64 386 if (obj->context.state == CY_SCB_I2C_IDLE) {
AnnaBridge 188:bcfe06ba3d64 387 status = Cy_SCB_I2C_MasterSendStart(obj->base, address, CY_SCB_I2C_READ_XFER, obj->timeout, &obj->context);
AnnaBridge 188:bcfe06ba3d64 388 }
AnnaBridge 188:bcfe06ba3d64 389 if (status == CY_SCB_I2C_SUCCESS) {
AnnaBridge 188:bcfe06ba3d64 390 while (length > 0) {
AnnaBridge 188:bcfe06ba3d64 391 if (length == 1) {
AnnaBridge 188:bcfe06ba3d64 392 ack = CY_SCB_I2C_NAK;
AnnaBridge 188:bcfe06ba3d64 393 }
AnnaBridge 188:bcfe06ba3d64 394 status = Cy_SCB_I2C_MasterReadByte(obj->base, ack, (uint8_t *)data, obj->timeout, &obj->context);
AnnaBridge 188:bcfe06ba3d64 395 if (status != CY_SCB_I2C_SUCCESS) {
AnnaBridge 188:bcfe06ba3d64 396 break;
AnnaBridge 188:bcfe06ba3d64 397 }
AnnaBridge 188:bcfe06ba3d64 398 ++byte_count;
AnnaBridge 188:bcfe06ba3d64 399 --length;
AnnaBridge 188:bcfe06ba3d64 400 ++data;
AnnaBridge 188:bcfe06ba3d64 401 }
AnnaBridge 188:bcfe06ba3d64 402 // SCB in I2C mode is very time sensitive. In practice we have to request STOP after
AnnaBridge 188:bcfe06ba3d64 403 // each block, otherwise it may break the transmission.
AnnaBridge 188:bcfe06ba3d64 404 Cy_SCB_I2C_MasterSendStop(obj->base, obj->timeout, &obj->context);
AnnaBridge 188:bcfe06ba3d64 405 }
AnnaBridge 188:bcfe06ba3d64 406
AnnaBridge 188:bcfe06ba3d64 407 if (status != CY_SCB_I2C_SUCCESS) {
AnnaBridge 188:bcfe06ba3d64 408 Cy_SCB_I2C_MasterSendStop(obj->base, obj->timeout, &obj->context);
AnnaBridge 188:bcfe06ba3d64 409 byte_count = i2c_convert_status(status);
AnnaBridge 188:bcfe06ba3d64 410 }
AnnaBridge 188:bcfe06ba3d64 411
AnnaBridge 188:bcfe06ba3d64 412 return byte_count;
AnnaBridge 188:bcfe06ba3d64 413 }
AnnaBridge 188:bcfe06ba3d64 414
AnnaBridge 188:bcfe06ba3d64 415 int i2c_write(i2c_t *obj_in, int address, const char *data, int length, int stop)
AnnaBridge 188:bcfe06ba3d64 416 {
AnnaBridge 188:bcfe06ba3d64 417 cy_en_scb_i2c_status_t status = CY_SCB_I2C_SUCCESS;
AnnaBridge 188:bcfe06ba3d64 418 i2c_obj_t *obj = OBJ_P(obj_in);
AnnaBridge 188:bcfe06ba3d64 419 int byte_count = 0;
AnnaBridge 188:bcfe06ba3d64 420 address >>= 1;
AnnaBridge 188:bcfe06ba3d64 421
AnnaBridge 188:bcfe06ba3d64 422 // Start transaction, send address.
AnnaBridge 188:bcfe06ba3d64 423 if (obj->context.state == CY_SCB_I2C_IDLE) {
AnnaBridge 188:bcfe06ba3d64 424 status = Cy_SCB_I2C_MasterSendStart(obj->base, address, CY_SCB_I2C_WRITE_XFER, obj->timeout, &obj->context);
AnnaBridge 188:bcfe06ba3d64 425 }
AnnaBridge 188:bcfe06ba3d64 426 if (status == CY_SCB_I2C_SUCCESS) {
AnnaBridge 188:bcfe06ba3d64 427 while (length > 0) {
AnnaBridge 188:bcfe06ba3d64 428 status = Cy_SCB_I2C_MasterWriteByte(obj->base, *data, obj->timeout, &obj->context);
AnnaBridge 188:bcfe06ba3d64 429 if (status != CY_SCB_I2C_SUCCESS) {
AnnaBridge 188:bcfe06ba3d64 430 break;;
AnnaBridge 188:bcfe06ba3d64 431 }
AnnaBridge 188:bcfe06ba3d64 432 ++byte_count;
AnnaBridge 188:bcfe06ba3d64 433 --length;
AnnaBridge 188:bcfe06ba3d64 434 ++data;
AnnaBridge 188:bcfe06ba3d64 435 }
AnnaBridge 188:bcfe06ba3d64 436 // SCB in I2C mode is very time sensitive. In practice we have to request STOP after
AnnaBridge 188:bcfe06ba3d64 437 // each block, otherwise it may break the transmission.
AnnaBridge 188:bcfe06ba3d64 438 Cy_SCB_I2C_MasterSendStop(obj->base, obj->timeout, &obj->context);
AnnaBridge 188:bcfe06ba3d64 439 }
AnnaBridge 188:bcfe06ba3d64 440
AnnaBridge 188:bcfe06ba3d64 441 if (status != CY_SCB_I2C_SUCCESS) {
AnnaBridge 188:bcfe06ba3d64 442 Cy_SCB_I2C_MasterSendStop(obj->base, obj->timeout, &obj->context);
AnnaBridge 188:bcfe06ba3d64 443 byte_count = i2c_convert_status(status);
AnnaBridge 188:bcfe06ba3d64 444 }
AnnaBridge 188:bcfe06ba3d64 445
AnnaBridge 188:bcfe06ba3d64 446 return byte_count;
AnnaBridge 188:bcfe06ba3d64 447 }
AnnaBridge 188:bcfe06ba3d64 448
AnnaBridge 188:bcfe06ba3d64 449 void i2c_reset(i2c_t *obj_in)
AnnaBridge 188:bcfe06ba3d64 450 {
AnnaBridge 189:f392fc9709a3 451 i2c_obj_t *obj = OBJ_P(obj_in);
AnnaBridge 189:f392fc9709a3 452
AnnaBridge 189:f392fc9709a3 453 /* Back block into default state */
AnnaBridge 189:f392fc9709a3 454 Cy_SCB_FwBlockReset(obj->base);
AnnaBridge 189:f392fc9709a3 455 obj->context.state = CY_SCB_I2C_IDLE;
AnnaBridge 188:bcfe06ba3d64 456 }
AnnaBridge 188:bcfe06ba3d64 457
AnnaBridge 188:bcfe06ba3d64 458 int i2c_byte_read(i2c_t *obj_in, int last)
AnnaBridge 188:bcfe06ba3d64 459 {
AnnaBridge 188:bcfe06ba3d64 460 i2c_obj_t *obj = OBJ_P(obj_in);
AnnaBridge 188:bcfe06ba3d64 461 uint8_t tmp_byte = 0;
AnnaBridge 189:f392fc9709a3 462 cy_en_scb_i2c_command_t ack = last ? CY_SCB_I2C_NAK : CY_SCB_I2C_ACK;
AnnaBridge 189:f392fc9709a3 463
AnnaBridge 189:f392fc9709a3 464 /* i2c_start and i2c_byte_write was called. Update state to receive data */
AnnaBridge 189:f392fc9709a3 465 if (CY_SCB_I2C_MASTER_TX == obj->context.state) {
AnnaBridge 189:f392fc9709a3 466 obj->context.state = CY_SCB_I2C_MASTER_RX0;
AnnaBridge 189:f392fc9709a3 467 }
AnnaBridge 189:f392fc9709a3 468
AnnaBridge 188:bcfe06ba3d64 469 cy_en_scb_i2c_status_t status = Cy_SCB_I2C_MasterReadByte(obj->base, ack, &tmp_byte, obj->timeout, &obj->context);
AnnaBridge 188:bcfe06ba3d64 470
AnnaBridge 188:bcfe06ba3d64 471 if (status == CY_SCB_I2C_SUCCESS) {
AnnaBridge 188:bcfe06ba3d64 472 return tmp_byte;
AnnaBridge 188:bcfe06ba3d64 473 } else {
AnnaBridge 189:f392fc9709a3 474 return (-1);
AnnaBridge 188:bcfe06ba3d64 475 }
AnnaBridge 188:bcfe06ba3d64 476 }
AnnaBridge 188:bcfe06ba3d64 477
AnnaBridge 188:bcfe06ba3d64 478 int i2c_byte_write(i2c_t *obj_in, int data)
AnnaBridge 188:bcfe06ba3d64 479 {
AnnaBridge 188:bcfe06ba3d64 480 i2c_obj_t *obj = OBJ_P(obj_in);
AnnaBridge 189:f392fc9709a3 481
AnnaBridge 189:f392fc9709a3 482 /* i2c_start was called update state to receive data */
AnnaBridge 189:f392fc9709a3 483 if (CY_SCB_I2C_MASTER_ADDR == obj->context.state) {
AnnaBridge 189:f392fc9709a3 484 obj->context.state = CY_SCB_I2C_MASTER_TX;
AnnaBridge 189:f392fc9709a3 485 }
AnnaBridge 189:f392fc9709a3 486
AnnaBridge 188:bcfe06ba3d64 487 cy_en_scb_i2c_status_t status = Cy_SCB_I2C_MasterWriteByte(obj->base, (uint8_t)data, obj->timeout, &obj->context);
AnnaBridge 189:f392fc9709a3 488
AnnaBridge 188:bcfe06ba3d64 489 switch (status) {
AnnaBridge 188:bcfe06ba3d64 490 case CY_SCB_I2C_MASTER_MANUAL_TIMEOUT:
AnnaBridge 188:bcfe06ba3d64 491 return 2;
AnnaBridge 188:bcfe06ba3d64 492 case CY_SCB_I2C_MASTER_MANUAL_ADDR_NAK:
AnnaBridge 188:bcfe06ba3d64 493 case CY_SCB_I2C_MASTER_MANUAL_NAK:
AnnaBridge 188:bcfe06ba3d64 494 return 0;
AnnaBridge 188:bcfe06ba3d64 495 case CY_SCB_I2C_SUCCESS:
AnnaBridge 188:bcfe06ba3d64 496 return 1;
AnnaBridge 188:bcfe06ba3d64 497 default:
AnnaBridge 189:f392fc9709a3 498 /* Error has occurred */
AnnaBridge 188:bcfe06ba3d64 499 return (-1);
AnnaBridge 188:bcfe06ba3d64 500 }
AnnaBridge 188:bcfe06ba3d64 501 }
AnnaBridge 188:bcfe06ba3d64 502
AnnaBridge 188:bcfe06ba3d64 503 #if DEVICE_I2C_ASYNCH
AnnaBridge 188:bcfe06ba3d64 504
AnnaBridge 188:bcfe06ba3d64 505 void i2c_transfer_asynch(i2c_t *obj_in,
AnnaBridge 188:bcfe06ba3d64 506 const void *tx,
AnnaBridge 188:bcfe06ba3d64 507 size_t tx_length,
AnnaBridge 188:bcfe06ba3d64 508 void *rx, size_t rx_length,
AnnaBridge 188:bcfe06ba3d64 509 uint32_t address,
AnnaBridge 188:bcfe06ba3d64 510 uint32_t stop,
AnnaBridge 188:bcfe06ba3d64 511 uint32_t handler,
AnnaBridge 188:bcfe06ba3d64 512 uint32_t event,
AnnaBridge 188:bcfe06ba3d64 513 DMAUsage hint)
AnnaBridge 188:bcfe06ba3d64 514 {
AnnaBridge 188:bcfe06ba3d64 515 i2c_obj_t *obj = OBJ_P(obj_in);
AnnaBridge 188:bcfe06ba3d64 516
AnnaBridge 188:bcfe06ba3d64 517 (void)hint; // At the moment we do not support DMA transfers, so this parameter gets ignored.
AnnaBridge 188:bcfe06ba3d64 518
AnnaBridge 188:bcfe06ba3d64 519 if (obj->pending != PENDING_NONE) {
AnnaBridge 188:bcfe06ba3d64 520 return;
AnnaBridge 188:bcfe06ba3d64 521 }
AnnaBridge 188:bcfe06ba3d64 522
AnnaBridge 188:bcfe06ba3d64 523 obj->rx_config.slaveAddress = address >> 1;
AnnaBridge 188:bcfe06ba3d64 524 obj->tx_config.slaveAddress = address >> 1;
AnnaBridge 188:bcfe06ba3d64 525 obj->events = event;
AnnaBridge 188:bcfe06ba3d64 526 obj->handler = handler;
AnnaBridge 188:bcfe06ba3d64 527 if (i2c_irq_setup_channel(obj) < 0) {
AnnaBridge 188:bcfe06ba3d64 528 return;
AnnaBridge 188:bcfe06ba3d64 529 }
AnnaBridge 188:bcfe06ba3d64 530
AnnaBridge 188:bcfe06ba3d64 531 obj->rx_config.buffer = rx;
AnnaBridge 188:bcfe06ba3d64 532 obj->rx_config.bufferSize = rx_length;
AnnaBridge 188:bcfe06ba3d64 533 obj->rx_config.xferPending = !stop;
AnnaBridge 188:bcfe06ba3d64 534
AnnaBridge 189:f392fc9709a3 535 obj->tx_config.buffer = (void *)tx;
AnnaBridge 188:bcfe06ba3d64 536 obj->tx_config.bufferSize = tx_length;
AnnaBridge 188:bcfe06ba3d64 537 obj->tx_config.xferPending = rx_length || !stop;
AnnaBridge 188:bcfe06ba3d64 538
AnnaBridge 188:bcfe06ba3d64 539 if (tx_length) {
AnnaBridge 188:bcfe06ba3d64 540 // Write first, then read, or write only.
AnnaBridge 188:bcfe06ba3d64 541 if (rx_length > 0) {
AnnaBridge 188:bcfe06ba3d64 542 obj->pending = PENDING_TX_RX;
AnnaBridge 188:bcfe06ba3d64 543 } else {
AnnaBridge 188:bcfe06ba3d64 544 obj->pending = PENDING_TX;
AnnaBridge 188:bcfe06ba3d64 545 }
AnnaBridge 188:bcfe06ba3d64 546 Cy_SCB_I2C_MasterWrite(obj->base, &obj->tx_config, &obj->context);
AnnaBridge 188:bcfe06ba3d64 547 } else if (rx_length) {
AnnaBridge 188:bcfe06ba3d64 548 // Read transaction;
AnnaBridge 188:bcfe06ba3d64 549 obj->pending = PENDING_RX;
AnnaBridge 188:bcfe06ba3d64 550 Cy_SCB_I2C_MasterRead(obj->base, &obj->rx_config, &obj->context);
AnnaBridge 188:bcfe06ba3d64 551 }
AnnaBridge 188:bcfe06ba3d64 552 }
AnnaBridge 188:bcfe06ba3d64 553
AnnaBridge 189:f392fc9709a3 554
AnnaBridge 189:f392fc9709a3 555 static void i2c_gen_stop(i2c_t *obj_in)
AnnaBridge 189:f392fc9709a3 556 {
AnnaBridge 189:f392fc9709a3 557 i2c_obj_t *obj = OBJ_P(obj_in);
AnnaBridge 189:f392fc9709a3 558
AnnaBridge 189:f392fc9709a3 559 // Enable master interrupts and generate Stop
AnnaBridge 189:f392fc9709a3 560 Cy_SCB_SetMasterInterruptMask(obj->base, CY_SCB_I2C_MASTER_INTR);
AnnaBridge 189:f392fc9709a3 561 SCB_I2C_M_CMD(obj->base) = (SCB_I2C_M_CMD_M_STOP_Msk | SCB_I2C_M_CMD_M_NACK_Msk);
AnnaBridge 189:f392fc9709a3 562 }
AnnaBridge 189:f392fc9709a3 563
AnnaBridge 189:f392fc9709a3 564
AnnaBridge 188:bcfe06ba3d64 565 uint32_t i2c_irq_handler_asynch(i2c_t *obj_in)
AnnaBridge 188:bcfe06ba3d64 566 {
AnnaBridge 188:bcfe06ba3d64 567 i2c_obj_t *obj = OBJ_P(obj_in);
AnnaBridge 188:bcfe06ba3d64 568 uint32_t event = 0;
AnnaBridge 188:bcfe06ba3d64 569 // Process actual interrupt.
AnnaBridge 188:bcfe06ba3d64 570 Cy_SCB_I2C_Interrupt(obj->base, &obj->context);
AnnaBridge 189:f392fc9709a3 571
AnnaBridge 189:f392fc9709a3 572 if (false == (CY_SCB_I2C_MASTER_BUSY & obj->context.masterStatus)) {
AnnaBridge 189:f392fc9709a3 573 // Transfer was completed
AnnaBridge 189:f392fc9709a3 574 event = I2C_EVENT_TRANSFER_COMPLETE;
AnnaBridge 189:f392fc9709a3 575
AnnaBridge 189:f392fc9709a3 576 // Parse results of single transfer
AnnaBridge 189:f392fc9709a3 577 if (CY_SCB_I2C_MASTER_ERR & obj->context.masterStatus) {
AnnaBridge 189:f392fc9709a3 578 if (CY_SCB_I2C_MASTER_ADDR_NAK & obj->context.masterStatus) {
AnnaBridge 189:f392fc9709a3 579 event |= I2C_EVENT_ERROR_NO_SLAVE;
AnnaBridge 189:f392fc9709a3 580 } else if (CY_SCB_I2C_MASTER_DATA_NAK & obj->context.masterStatus) {
AnnaBridge 189:f392fc9709a3 581 event |= I2C_EVENT_TRANSFER_EARLY_NACK;
AnnaBridge 188:bcfe06ba3d64 582 } else {
AnnaBridge 189:f392fc9709a3 583 // CY_SCB_I2C_MASTER_ARB_LOST || CY_SCB_I2C_MASTER_BUS_ERR || CY_SCB_I2C_MASTER_ABORT_START
AnnaBridge 189:f392fc9709a3 584 event |= I2C_EVENT_ERROR;
AnnaBridge 189:f392fc9709a3 585 }
AnnaBridge 189:f392fc9709a3 586 }
AnnaBridge 189:f392fc9709a3 587
AnnaBridge 189:f392fc9709a3 588 // Check if a read phase is pending after write.
AnnaBridge 189:f392fc9709a3 589 if (obj->pending == PENDING_TX_RX) {
AnnaBridge 189:f392fc9709a3 590 obj->pending = PENDING_RX;
AnnaBridge 189:f392fc9709a3 591
AnnaBridge 189:f392fc9709a3 592 if (event == I2C_EVENT_TRANSFER_COMPLETE) {
AnnaBridge 189:f392fc9709a3 593 // Send ReStart and continue with RX transfer
AnnaBridge 189:f392fc9709a3 594 event = 0;
AnnaBridge 189:f392fc9709a3 595 Cy_SCB_I2C_MasterRead(obj->base, &obj->rx_config, &obj->context);
AnnaBridge 189:f392fc9709a3 596 } else {
AnnaBridge 189:f392fc9709a3 597 // NACK - generate Stop (do not execute RX transfer)
AnnaBridge 189:f392fc9709a3 598 // Error - do not execute RX transfer and report transfer complete
AnnaBridge 189:f392fc9709a3 599 if (false == (event & I2C_EVENT_ERROR)) {
AnnaBridge 189:f392fc9709a3 600 // Report events after Stop generation
AnnaBridge 189:f392fc9709a3 601 event = 0;
AnnaBridge 189:f392fc9709a3 602 obj->context.state = CY_SCB_I2C_MASTER_WAIT_STOP;
AnnaBridge 189:f392fc9709a3 603 obj->context.masterPause = false;
AnnaBridge 189:f392fc9709a3 604
AnnaBridge 189:f392fc9709a3 605 i2c_gen_stop(obj_in);
AnnaBridge 189:f392fc9709a3 606 }
AnnaBridge 188:bcfe06ba3d64 607 }
AnnaBridge 188:bcfe06ba3d64 608 } else {
AnnaBridge 189:f392fc9709a3 609 obj->pending = PENDING_NONE;
AnnaBridge 188:bcfe06ba3d64 610 }
AnnaBridge 188:bcfe06ba3d64 611 }
AnnaBridge 189:f392fc9709a3 612
AnnaBridge 189:f392fc9709a3 613 return (event & obj->events);
AnnaBridge 188:bcfe06ba3d64 614 }
AnnaBridge 188:bcfe06ba3d64 615
AnnaBridge 188:bcfe06ba3d64 616 uint8_t i2c_active(i2c_t *obj_in)
AnnaBridge 188:bcfe06ba3d64 617 {
AnnaBridge 188:bcfe06ba3d64 618 i2c_obj_t *obj = OBJ_P(obj_in);
AnnaBridge 188:bcfe06ba3d64 619 return (obj->pending != PENDING_NONE);
AnnaBridge 188:bcfe06ba3d64 620 }
AnnaBridge 188:bcfe06ba3d64 621
AnnaBridge 188:bcfe06ba3d64 622 void i2c_abort_asynch(i2c_t *obj_in)
AnnaBridge 188:bcfe06ba3d64 623 {
AnnaBridge 188:bcfe06ba3d64 624 i2c_obj_t *obj = OBJ_P(obj_in);
AnnaBridge 188:bcfe06ba3d64 625 if (obj->pending != PENDING_NONE) {
AnnaBridge 188:bcfe06ba3d64 626 if (obj->pending == PENDING_RX) {
AnnaBridge 188:bcfe06ba3d64 627 Cy_SCB_I2C_MasterAbortRead(obj->base, &obj->context);
AnnaBridge 188:bcfe06ba3d64 628 } else {
AnnaBridge 188:bcfe06ba3d64 629 Cy_SCB_I2C_MasterAbortWrite(obj->base, &obj->context);
AnnaBridge 188:bcfe06ba3d64 630 }
AnnaBridge 188:bcfe06ba3d64 631 }
AnnaBridge 188:bcfe06ba3d64 632 }
AnnaBridge 188:bcfe06ba3d64 633
AnnaBridge 188:bcfe06ba3d64 634 #endif // DEVICE_ASYNCH