Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-dev by
targets/TARGET_TOSHIBA/TARGET_TMPM066/i2c_api.c@172:7d866c31b3c5, 2017-08-31 (annotated)
- Committer:
- AnnaBridge
- Date:
- Thu Aug 31 17:27:04 2017 +0100
- Revision:
- 172:7d866c31b3c5
This updates the lib to the mbed lib v 150
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| AnnaBridge | 172:7d866c31b3c5 | 1 | /* mbed Microcontroller Library |
| AnnaBridge | 172:7d866c31b3c5 | 2 | * (C)Copyright TOSHIBA ELECTRONIC DEVICES & STORAGE CORPORATION 2017 All rights reserved |
| AnnaBridge | 172:7d866c31b3c5 | 3 | * |
| AnnaBridge | 172:7d866c31b3c5 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| AnnaBridge | 172:7d866c31b3c5 | 5 | * you may not use this file except in compliance with the License. |
| AnnaBridge | 172:7d866c31b3c5 | 6 | * You may obtain a copy of the License at |
| AnnaBridge | 172:7d866c31b3c5 | 7 | * |
| AnnaBridge | 172:7d866c31b3c5 | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| AnnaBridge | 172:7d866c31b3c5 | 9 | * |
| AnnaBridge | 172:7d866c31b3c5 | 10 | * Unless required by applicable law or agreed to in writing, software |
| AnnaBridge | 172:7d866c31b3c5 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| AnnaBridge | 172:7d866c31b3c5 | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| AnnaBridge | 172:7d866c31b3c5 | 13 | * See the License for the specific language governing permissions and |
| AnnaBridge | 172:7d866c31b3c5 | 14 | * limitations under the License. |
| AnnaBridge | 172:7d866c31b3c5 | 15 | */ |
| AnnaBridge | 172:7d866c31b3c5 | 16 | #include "i2c_api.h" |
| AnnaBridge | 172:7d866c31b3c5 | 17 | #include "mbed_error.h" |
| AnnaBridge | 172:7d866c31b3c5 | 18 | #include "PeripheralNames.h" |
| AnnaBridge | 172:7d866c31b3c5 | 19 | #include "pinmap.h" |
| AnnaBridge | 172:7d866c31b3c5 | 20 | |
| AnnaBridge | 172:7d866c31b3c5 | 21 | #define I2C_NACK (0) |
| AnnaBridge | 172:7d866c31b3c5 | 22 | #define I2C_ACK (1) |
| AnnaBridge | 172:7d866c31b3c5 | 23 | #define I2C_NO_DATA (0) |
| AnnaBridge | 172:7d866c31b3c5 | 24 | #define I2C_READ_ADDRESSED (1) |
| AnnaBridge | 172:7d866c31b3c5 | 25 | #define I2C_WRITE_GENERAL (2) |
| AnnaBridge | 172:7d866c31b3c5 | 26 | #define I2C_WRITE_ADDRESSED (3) |
| AnnaBridge | 172:7d866c31b3c5 | 27 | #define SELF_ADDR (0xE0) |
| AnnaBridge | 172:7d866c31b3c5 | 28 | #define I2C_TIMEOUT (100000) |
| AnnaBridge | 172:7d866c31b3c5 | 29 | |
| AnnaBridge | 172:7d866c31b3c5 | 30 | static const PinMap PinMap_I2C_SDA[] = { |
| AnnaBridge | 172:7d866c31b3c5 | 31 | {PC1, I2C_0, PIN_DATA(1, 2)}, |
| AnnaBridge | 172:7d866c31b3c5 | 32 | {PG1, I2C_1, PIN_DATA(1, 2)}, |
| AnnaBridge | 172:7d866c31b3c5 | 33 | {NC, NC, 0} |
| AnnaBridge | 172:7d866c31b3c5 | 34 | }; |
| AnnaBridge | 172:7d866c31b3c5 | 35 | |
| AnnaBridge | 172:7d866c31b3c5 | 36 | static const PinMap PinMap_I2C_SCL[] = { |
| AnnaBridge | 172:7d866c31b3c5 | 37 | {PC0, I2C_0, PIN_DATA(1, 2)}, |
| AnnaBridge | 172:7d866c31b3c5 | 38 | {PG0, I2C_1, PIN_DATA(1, 2)}, |
| AnnaBridge | 172:7d866c31b3c5 | 39 | {NC, NC, 0} |
| AnnaBridge | 172:7d866c31b3c5 | 40 | }; |
| AnnaBridge | 172:7d866c31b3c5 | 41 | |
| AnnaBridge | 172:7d866c31b3c5 | 42 | void I2C_ClearINTOutput(TSB_I2C_TypeDef * I2Cx); |
| AnnaBridge | 172:7d866c31b3c5 | 43 | // Clock setting structure definition |
| AnnaBridge | 172:7d866c31b3c5 | 44 | typedef struct { |
| AnnaBridge | 172:7d866c31b3c5 | 45 | uint32_t sck; |
| AnnaBridge | 172:7d866c31b3c5 | 46 | uint32_t prsck; |
| AnnaBridge | 172:7d866c31b3c5 | 47 | } I2C_clock_setting_t; |
| AnnaBridge | 172:7d866c31b3c5 | 48 | |
| AnnaBridge | 172:7d866c31b3c5 | 49 | static const uint32_t I2C_SCK_DIVIDER_TBL[8] = {20, 24, 32, 48, 80, 144, 272, 528}; // SCK Divider value table |
| AnnaBridge | 172:7d866c31b3c5 | 50 | static uint32_t start_flag = 0; |
| AnnaBridge | 172:7d866c31b3c5 | 51 | I2C_clock_setting_t clk; |
| AnnaBridge | 172:7d866c31b3c5 | 52 | I2C_State status; |
| AnnaBridge | 172:7d866c31b3c5 | 53 | |
| AnnaBridge | 172:7d866c31b3c5 | 54 | static int32_t wait_status(i2c_t *obj) |
| AnnaBridge | 172:7d866c31b3c5 | 55 | { |
| AnnaBridge | 172:7d866c31b3c5 | 56 | volatile int32_t timeout = I2C_TIMEOUT; |
| AnnaBridge | 172:7d866c31b3c5 | 57 | |
| AnnaBridge | 172:7d866c31b3c5 | 58 | while (I2C_GetINTI2CStatus(obj->i2c) == DISABLE) { |
| AnnaBridge | 172:7d866c31b3c5 | 59 | if ((timeout--) == 0) { |
| AnnaBridge | 172:7d866c31b3c5 | 60 | return (-1); |
| AnnaBridge | 172:7d866c31b3c5 | 61 | } |
| AnnaBridge | 172:7d866c31b3c5 | 62 | } |
| AnnaBridge | 172:7d866c31b3c5 | 63 | return (0); |
| AnnaBridge | 172:7d866c31b3c5 | 64 | } |
| AnnaBridge | 172:7d866c31b3c5 | 65 | |
| AnnaBridge | 172:7d866c31b3c5 | 66 | // Initialize the I2C peripheral. It sets the default parameters for I2C |
| AnnaBridge | 172:7d866c31b3c5 | 67 | void i2c_init(i2c_t *obj, PinName sda, PinName scl) |
| AnnaBridge | 172:7d866c31b3c5 | 68 | { |
| AnnaBridge | 172:7d866c31b3c5 | 69 | MBED_ASSERT(obj != NULL); |
| AnnaBridge | 172:7d866c31b3c5 | 70 | I2CName i2c_sda = (I2CName)pinmap_peripheral(sda, PinMap_I2C_SDA); |
| AnnaBridge | 172:7d866c31b3c5 | 71 | I2CName i2c_scl = (I2CName)pinmap_peripheral(scl, PinMap_I2C_SCL); |
| AnnaBridge | 172:7d866c31b3c5 | 72 | I2CName i2c_name = (I2CName)pinmap_merge(i2c_sda, i2c_scl); |
| AnnaBridge | 172:7d866c31b3c5 | 73 | MBED_ASSERT((int)i2c_name != NC); |
| AnnaBridge | 172:7d866c31b3c5 | 74 | |
| AnnaBridge | 172:7d866c31b3c5 | 75 | switch (i2c_name) { |
| AnnaBridge | 172:7d866c31b3c5 | 76 | case I2C_0: |
| AnnaBridge | 172:7d866c31b3c5 | 77 | CG_SetFcPeriphA(CG_FC_PERIPH_I2C0, ENABLE); |
| AnnaBridge | 172:7d866c31b3c5 | 78 | obj->i2c = TSB_I2C0; |
| AnnaBridge | 172:7d866c31b3c5 | 79 | obj->IRQn = INTI2C0_IRQn; |
| AnnaBridge | 172:7d866c31b3c5 | 80 | break; |
| AnnaBridge | 172:7d866c31b3c5 | 81 | case I2C_1: |
| AnnaBridge | 172:7d866c31b3c5 | 82 | CG_SetFcPeriphB(CG_FC_PERIPH_I2C1, ENABLE); |
| AnnaBridge | 172:7d866c31b3c5 | 83 | obj->i2c = TSB_I2C1; |
| AnnaBridge | 172:7d866c31b3c5 | 84 | obj->IRQn = INTI2C1_IRQn; |
| AnnaBridge | 172:7d866c31b3c5 | 85 | break; |
| AnnaBridge | 172:7d866c31b3c5 | 86 | default: |
| AnnaBridge | 172:7d866c31b3c5 | 87 | error("I2C is not available"); |
| AnnaBridge | 172:7d866c31b3c5 | 88 | break; |
| AnnaBridge | 172:7d866c31b3c5 | 89 | } |
| AnnaBridge | 172:7d866c31b3c5 | 90 | |
| AnnaBridge | 172:7d866c31b3c5 | 91 | pinmap_pinout(sda, PinMap_I2C_SDA); |
| AnnaBridge | 172:7d866c31b3c5 | 92 | pin_mode(sda, OpenDrain); |
| AnnaBridge | 172:7d866c31b3c5 | 93 | pin_mode(sda, PullUp); |
| AnnaBridge | 172:7d866c31b3c5 | 94 | |
| AnnaBridge | 172:7d866c31b3c5 | 95 | pinmap_pinout(scl, PinMap_I2C_SCL); |
| AnnaBridge | 172:7d866c31b3c5 | 96 | pin_mode(scl, OpenDrain); |
| AnnaBridge | 172:7d866c31b3c5 | 97 | pin_mode(scl, PullUp); |
| AnnaBridge | 172:7d866c31b3c5 | 98 | |
| AnnaBridge | 172:7d866c31b3c5 | 99 | NVIC_DisableIRQ(obj->IRQn); |
| AnnaBridge | 172:7d866c31b3c5 | 100 | |
| AnnaBridge | 172:7d866c31b3c5 | 101 | i2c_reset(obj); |
| AnnaBridge | 172:7d866c31b3c5 | 102 | i2c_frequency(obj, 100000); |
| AnnaBridge | 172:7d866c31b3c5 | 103 | } |
| AnnaBridge | 172:7d866c31b3c5 | 104 | |
| AnnaBridge | 172:7d866c31b3c5 | 105 | // Configure the I2C frequency |
| AnnaBridge | 172:7d866c31b3c5 | 106 | void i2c_frequency(i2c_t *obj, int hz) |
| AnnaBridge | 172:7d866c31b3c5 | 107 | { |
| AnnaBridge | 172:7d866c31b3c5 | 108 | uint64_t sck, tmp_sck; |
| AnnaBridge | 172:7d866c31b3c5 | 109 | uint64_t prsck, tmp_prsck; |
| AnnaBridge | 172:7d866c31b3c5 | 110 | uint64_t fscl, tmp_fscl; |
| AnnaBridge | 172:7d866c31b3c5 | 111 | uint64_t fx; |
| AnnaBridge | 172:7d866c31b3c5 | 112 | |
| AnnaBridge | 172:7d866c31b3c5 | 113 | SystemCoreClockUpdate(); |
| AnnaBridge | 172:7d866c31b3c5 | 114 | |
| AnnaBridge | 172:7d866c31b3c5 | 115 | if (hz <= 1000000) { |
| AnnaBridge | 172:7d866c31b3c5 | 116 | sck = tmp_sck = 0; |
| AnnaBridge | 172:7d866c31b3c5 | 117 | prsck = tmp_prsck = 1; |
| AnnaBridge | 172:7d866c31b3c5 | 118 | fscl = tmp_fscl = 0; |
| AnnaBridge | 172:7d866c31b3c5 | 119 | for (prsck = 1; prsck <= 32; prsck++) { |
| AnnaBridge | 172:7d866c31b3c5 | 120 | fx = ((uint64_t)SystemCoreClock / prsck); |
| AnnaBridge | 172:7d866c31b3c5 | 121 | if ((fx < 40000000U) && (fx > 6666666U)) { |
| AnnaBridge | 172:7d866c31b3c5 | 122 | for (sck = 0; sck <= 7; sck++) { |
| AnnaBridge | 172:7d866c31b3c5 | 123 | fscl = (fx / (uint64_t)I2C_SCK_DIVIDER_TBL[sck]); |
| AnnaBridge | 172:7d866c31b3c5 | 124 | if ((fscl <= (uint64_t)hz) && (fscl > tmp_fscl)) { |
| AnnaBridge | 172:7d866c31b3c5 | 125 | tmp_fscl = fscl; |
| AnnaBridge | 172:7d866c31b3c5 | 126 | tmp_sck = sck; |
| AnnaBridge | 172:7d866c31b3c5 | 127 | tmp_prsck = (prsck < 32)? prsck: 0; |
| AnnaBridge | 172:7d866c31b3c5 | 128 | } |
| AnnaBridge | 172:7d866c31b3c5 | 129 | } |
| AnnaBridge | 172:7d866c31b3c5 | 130 | } |
| AnnaBridge | 172:7d866c31b3c5 | 131 | } |
| AnnaBridge | 172:7d866c31b3c5 | 132 | clk.sck = (uint32_t)tmp_sck; |
| AnnaBridge | 172:7d866c31b3c5 | 133 | clk.prsck = (tmp_prsck < 32) ? (uint32_t)(tmp_prsck) : 0; |
| AnnaBridge | 172:7d866c31b3c5 | 134 | } |
| AnnaBridge | 172:7d866c31b3c5 | 135 | obj->myi2c.I2CSelfAddr = SELF_ADDR; |
| AnnaBridge | 172:7d866c31b3c5 | 136 | obj->myi2c.I2CDataLen = I2C_DATA_LEN_8; |
| AnnaBridge | 172:7d866c31b3c5 | 137 | obj->myi2c.I2CACKState = ENABLE; |
| AnnaBridge | 172:7d866c31b3c5 | 138 | obj->myi2c.I2CClkDiv = clk.sck; |
| AnnaBridge | 172:7d866c31b3c5 | 139 | obj->myi2c.PrescalerClkDiv = clk.prsck; |
| AnnaBridge | 172:7d866c31b3c5 | 140 | |
| AnnaBridge | 172:7d866c31b3c5 | 141 | I2C_Init(obj->i2c, &obj->myi2c); |
| AnnaBridge | 172:7d866c31b3c5 | 142 | NVIC_DisableIRQ(obj->IRQn); |
| AnnaBridge | 172:7d866c31b3c5 | 143 | } |
| AnnaBridge | 172:7d866c31b3c5 | 144 | |
| AnnaBridge | 172:7d866c31b3c5 | 145 | int i2c_start(i2c_t *obj) |
| AnnaBridge | 172:7d866c31b3c5 | 146 | { |
| AnnaBridge | 172:7d866c31b3c5 | 147 | start_flag = 1; |
| AnnaBridge | 172:7d866c31b3c5 | 148 | return 0; |
| AnnaBridge | 172:7d866c31b3c5 | 149 | } |
| AnnaBridge | 172:7d866c31b3c5 | 150 | |
| AnnaBridge | 172:7d866c31b3c5 | 151 | int i2c_stop(i2c_t *obj) |
| AnnaBridge | 172:7d866c31b3c5 | 152 | { |
| AnnaBridge | 172:7d866c31b3c5 | 153 | I2C_GenerateStop(obj->i2c); |
| AnnaBridge | 172:7d866c31b3c5 | 154 | return 0; |
| AnnaBridge | 172:7d866c31b3c5 | 155 | } |
| AnnaBridge | 172:7d866c31b3c5 | 156 | |
| AnnaBridge | 172:7d866c31b3c5 | 157 | void i2c_reset(i2c_t *obj) |
| AnnaBridge | 172:7d866c31b3c5 | 158 | { |
| AnnaBridge | 172:7d866c31b3c5 | 159 | I2C_SWReset(obj->i2c); |
| AnnaBridge | 172:7d866c31b3c5 | 160 | } |
| AnnaBridge | 172:7d866c31b3c5 | 161 | |
| AnnaBridge | 172:7d866c31b3c5 | 162 | int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) |
| AnnaBridge | 172:7d866c31b3c5 | 163 | { |
| AnnaBridge | 172:7d866c31b3c5 | 164 | int32_t result = 0; |
| AnnaBridge | 172:7d866c31b3c5 | 165 | int32_t count = 0; |
| AnnaBridge | 172:7d866c31b3c5 | 166 | |
| AnnaBridge | 172:7d866c31b3c5 | 167 | if (length > 0) { |
| AnnaBridge | 172:7d866c31b3c5 | 168 | start_flag = 1; // Start Condition |
| AnnaBridge | 172:7d866c31b3c5 | 169 | if (i2c_byte_write(obj, (int32_t)((uint32_t)address | 1U)) == I2C_ACK) { |
| AnnaBridge | 172:7d866c31b3c5 | 170 | while (count < length) { |
| AnnaBridge | 172:7d866c31b3c5 | 171 | int32_t pdata = i2c_byte_read(obj, ((count < (length - 1)) ? 0 : 1)); |
| AnnaBridge | 172:7d866c31b3c5 | 172 | if (pdata < 0) { |
| AnnaBridge | 172:7d866c31b3c5 | 173 | break; |
| AnnaBridge | 172:7d866c31b3c5 | 174 | } |
| AnnaBridge | 172:7d866c31b3c5 | 175 | data[count++] = (uint8_t)pdata; |
| AnnaBridge | 172:7d866c31b3c5 | 176 | } |
| AnnaBridge | 172:7d866c31b3c5 | 177 | result = count; |
| AnnaBridge | 172:7d866c31b3c5 | 178 | } else { |
| AnnaBridge | 172:7d866c31b3c5 | 179 | stop = 1; |
| AnnaBridge | 172:7d866c31b3c5 | 180 | result = I2C_ERROR_NO_SLAVE; |
| AnnaBridge | 172:7d866c31b3c5 | 181 | } |
| AnnaBridge | 172:7d866c31b3c5 | 182 | |
| AnnaBridge | 172:7d866c31b3c5 | 183 | if (stop) { // Stop Condition |
| AnnaBridge | 172:7d866c31b3c5 | 184 | i2c_stop(obj); |
| AnnaBridge | 172:7d866c31b3c5 | 185 | } |
| AnnaBridge | 172:7d866c31b3c5 | 186 | } |
| AnnaBridge | 172:7d866c31b3c5 | 187 | return (result); |
| AnnaBridge | 172:7d866c31b3c5 | 188 | } |
| AnnaBridge | 172:7d866c31b3c5 | 189 | |
| AnnaBridge | 172:7d866c31b3c5 | 190 | int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop) // Blocking sending data |
| AnnaBridge | 172:7d866c31b3c5 | 191 | { |
| AnnaBridge | 172:7d866c31b3c5 | 192 | int32_t result = 0; |
| AnnaBridge | 172:7d866c31b3c5 | 193 | int32_t count = 0; |
| AnnaBridge | 172:7d866c31b3c5 | 194 | |
| AnnaBridge | 172:7d866c31b3c5 | 195 | start_flag = 1; // Start Condition |
| AnnaBridge | 172:7d866c31b3c5 | 196 | if (i2c_byte_write(obj, address) == I2C_ACK) { |
| AnnaBridge | 172:7d866c31b3c5 | 197 | while (count < length) { |
| AnnaBridge | 172:7d866c31b3c5 | 198 | if (i2c_byte_write(obj, (int32_t)data[count++]) < I2C_ACK) { |
| AnnaBridge | 172:7d866c31b3c5 | 199 | break; |
| AnnaBridge | 172:7d866c31b3c5 | 200 | } |
| AnnaBridge | 172:7d866c31b3c5 | 201 | } |
| AnnaBridge | 172:7d866c31b3c5 | 202 | result = count; |
| AnnaBridge | 172:7d866c31b3c5 | 203 | } else { |
| AnnaBridge | 172:7d866c31b3c5 | 204 | stop = 1; |
| AnnaBridge | 172:7d866c31b3c5 | 205 | result = I2C_ERROR_NO_SLAVE; |
| AnnaBridge | 172:7d866c31b3c5 | 206 | } |
| AnnaBridge | 172:7d866c31b3c5 | 207 | |
| AnnaBridge | 172:7d866c31b3c5 | 208 | if (stop) { // Stop Condition |
| AnnaBridge | 172:7d866c31b3c5 | 209 | i2c_stop(obj); |
| AnnaBridge | 172:7d866c31b3c5 | 210 | } |
| AnnaBridge | 172:7d866c31b3c5 | 211 | return (result); |
| AnnaBridge | 172:7d866c31b3c5 | 212 | } |
| AnnaBridge | 172:7d866c31b3c5 | 213 | |
| AnnaBridge | 172:7d866c31b3c5 | 214 | int i2c_byte_read(i2c_t *obj, int last) |
| AnnaBridge | 172:7d866c31b3c5 | 215 | { |
| AnnaBridge | 172:7d866c31b3c5 | 216 | int32_t result; |
| AnnaBridge | 172:7d866c31b3c5 | 217 | |
| AnnaBridge | 172:7d866c31b3c5 | 218 | I2C_ClearINTOutput(obj->i2c); |
| AnnaBridge | 172:7d866c31b3c5 | 219 | |
| AnnaBridge | 172:7d866c31b3c5 | 220 | if (last) { |
| AnnaBridge | 172:7d866c31b3c5 | 221 | I2C_SelectACKoutput(obj->i2c, ENABLE); |
| AnnaBridge | 172:7d866c31b3c5 | 222 | } else { |
| AnnaBridge | 172:7d866c31b3c5 | 223 | I2C_SelectACKoutput(obj->i2c, DISABLE); |
| AnnaBridge | 172:7d866c31b3c5 | 224 | } |
| AnnaBridge | 172:7d866c31b3c5 | 225 | I2C_SetSendData(obj->i2c, 0x00); |
| AnnaBridge | 172:7d866c31b3c5 | 226 | |
| AnnaBridge | 172:7d866c31b3c5 | 227 | if (wait_status(obj) < 0) { |
| AnnaBridge | 172:7d866c31b3c5 | 228 | result = -1; |
| AnnaBridge | 172:7d866c31b3c5 | 229 | } else { |
| AnnaBridge | 172:7d866c31b3c5 | 230 | result = (int32_t)I2C_GetReceiveData(obj->i2c); |
| AnnaBridge | 172:7d866c31b3c5 | 231 | } |
| AnnaBridge | 172:7d866c31b3c5 | 232 | return (result); |
| AnnaBridge | 172:7d866c31b3c5 | 233 | } |
| AnnaBridge | 172:7d866c31b3c5 | 234 | |
| AnnaBridge | 172:7d866c31b3c5 | 235 | void I2C_Start_Condition(i2c_t *p_obj, uint32_t data) |
| AnnaBridge | 172:7d866c31b3c5 | 236 | { |
| AnnaBridge | 172:7d866c31b3c5 | 237 | status = I2C_GetState(p_obj->i2c); |
| AnnaBridge | 172:7d866c31b3c5 | 238 | if (status.Bit.BusState) { |
| AnnaBridge | 172:7d866c31b3c5 | 239 | I2C_SetRepeatStart(p_obj->i2c, ENABLE); |
| AnnaBridge | 172:7d866c31b3c5 | 240 | } |
| AnnaBridge | 172:7d866c31b3c5 | 241 | I2C_SetSendData(p_obj->i2c, (uint32_t)data); |
| AnnaBridge | 172:7d866c31b3c5 | 242 | I2C_GenerateStart(p_obj->i2c); |
| AnnaBridge | 172:7d866c31b3c5 | 243 | } |
| AnnaBridge | 172:7d866c31b3c5 | 244 | |
| AnnaBridge | 172:7d866c31b3c5 | 245 | int i2c_byte_write(i2c_t *obj, int data) |
| AnnaBridge | 172:7d866c31b3c5 | 246 | { |
| AnnaBridge | 172:7d866c31b3c5 | 247 | int32_t result; |
| AnnaBridge | 172:7d866c31b3c5 | 248 | |
| AnnaBridge | 172:7d866c31b3c5 | 249 | I2C_ClearINTOutput(obj->i2c); |
| AnnaBridge | 172:7d866c31b3c5 | 250 | |
| AnnaBridge | 172:7d866c31b3c5 | 251 | if (start_flag == 1) { |
| AnnaBridge | 172:7d866c31b3c5 | 252 | I2C_Start_Condition(obj, (uint32_t)data); |
| AnnaBridge | 172:7d866c31b3c5 | 253 | start_flag = 0; |
| AnnaBridge | 172:7d866c31b3c5 | 254 | } else { |
| AnnaBridge | 172:7d866c31b3c5 | 255 | I2C_SetSendData(obj->i2c, (uint32_t)data); |
| AnnaBridge | 172:7d866c31b3c5 | 256 | } |
| AnnaBridge | 172:7d866c31b3c5 | 257 | |
| AnnaBridge | 172:7d866c31b3c5 | 258 | if (wait_status(obj) < 0) { |
| AnnaBridge | 172:7d866c31b3c5 | 259 | return (-1); |
| AnnaBridge | 172:7d866c31b3c5 | 260 | } |
| AnnaBridge | 172:7d866c31b3c5 | 261 | |
| AnnaBridge | 172:7d866c31b3c5 | 262 | status = I2C_GetState(obj->i2c); |
| AnnaBridge | 172:7d866c31b3c5 | 263 | if (!status.Bit.LastRxBit) { |
| AnnaBridge | 172:7d866c31b3c5 | 264 | result = 1; |
| AnnaBridge | 172:7d866c31b3c5 | 265 | } else { |
| AnnaBridge | 172:7d866c31b3c5 | 266 | result = 0; |
| AnnaBridge | 172:7d866c31b3c5 | 267 | } |
| AnnaBridge | 172:7d866c31b3c5 | 268 | return (result); |
| AnnaBridge | 172:7d866c31b3c5 | 269 | } |
| AnnaBridge | 172:7d866c31b3c5 | 270 | |
| AnnaBridge | 172:7d866c31b3c5 | 271 | void i2c_slave_mode(i2c_t *obj, int enable_slave) |
| AnnaBridge | 172:7d866c31b3c5 | 272 | { |
| AnnaBridge | 172:7d866c31b3c5 | 273 | i2c_reset(obj); |
| AnnaBridge | 172:7d866c31b3c5 | 274 | |
| AnnaBridge | 172:7d866c31b3c5 | 275 | obj->myi2c.I2CDataLen = I2C_DATA_LEN_8; |
| AnnaBridge | 172:7d866c31b3c5 | 276 | obj->myi2c.I2CACKState = ENABLE; |
| AnnaBridge | 172:7d866c31b3c5 | 277 | obj->myi2c.I2CClkDiv = clk.sck; |
| AnnaBridge | 172:7d866c31b3c5 | 278 | obj->myi2c.PrescalerClkDiv = clk.prsck; |
| AnnaBridge | 172:7d866c31b3c5 | 279 | |
| AnnaBridge | 172:7d866c31b3c5 | 280 | if (enable_slave) { |
| AnnaBridge | 172:7d866c31b3c5 | 281 | obj->myi2c.I2CSelfAddr = obj->address; |
| AnnaBridge | 172:7d866c31b3c5 | 282 | I2C_SetINTI2CReq(obj->i2c, ENABLE); |
| AnnaBridge | 172:7d866c31b3c5 | 283 | } else { |
| AnnaBridge | 172:7d866c31b3c5 | 284 | obj->myi2c.I2CSelfAddr = SELF_ADDR; |
| AnnaBridge | 172:7d866c31b3c5 | 285 | NVIC_DisableIRQ(obj->IRQn); |
| AnnaBridge | 172:7d866c31b3c5 | 286 | I2C_ClearINTOutput(obj->i2c); |
| AnnaBridge | 172:7d866c31b3c5 | 287 | } |
| AnnaBridge | 172:7d866c31b3c5 | 288 | I2C_Init(obj->i2c, &obj->myi2c); |
| AnnaBridge | 172:7d866c31b3c5 | 289 | } |
| AnnaBridge | 172:7d866c31b3c5 | 290 | |
| AnnaBridge | 172:7d866c31b3c5 | 291 | int i2c_slave_receive(i2c_t *obj) |
| AnnaBridge | 172:7d866c31b3c5 | 292 | { |
| AnnaBridge | 172:7d866c31b3c5 | 293 | int32_t result = I2C_NO_DATA; |
| AnnaBridge | 172:7d866c31b3c5 | 294 | |
| AnnaBridge | 172:7d866c31b3c5 | 295 | if ((I2C_GetINTI2CStatus(obj->i2c)) && (I2C_GetSlaveAddrMatchState(obj->i2c))) { |
| AnnaBridge | 172:7d866c31b3c5 | 296 | status = I2C_GetState(obj->i2c); |
| AnnaBridge | 172:7d866c31b3c5 | 297 | if (!status.Bit.TRx) { |
| AnnaBridge | 172:7d866c31b3c5 | 298 | result = I2C_WRITE_ADDRESSED; |
| AnnaBridge | 172:7d866c31b3c5 | 299 | } else { |
| AnnaBridge | 172:7d866c31b3c5 | 300 | result = I2C_READ_ADDRESSED; |
| AnnaBridge | 172:7d866c31b3c5 | 301 | } |
| AnnaBridge | 172:7d866c31b3c5 | 302 | } |
| AnnaBridge | 172:7d866c31b3c5 | 303 | return (result); |
| AnnaBridge | 172:7d866c31b3c5 | 304 | } |
| AnnaBridge | 172:7d866c31b3c5 | 305 | |
| AnnaBridge | 172:7d866c31b3c5 | 306 | int i2c_slave_read(i2c_t *obj, char *data, int length) |
| AnnaBridge | 172:7d866c31b3c5 | 307 | { |
| AnnaBridge | 172:7d866c31b3c5 | 308 | int32_t count = 0; |
| AnnaBridge | 172:7d866c31b3c5 | 309 | |
| AnnaBridge | 172:7d866c31b3c5 | 310 | while (count < length) { |
| AnnaBridge | 172:7d866c31b3c5 | 311 | int32_t pdata = i2c_byte_read(obj, ((count < (length - 1))? 0: 1)); |
| AnnaBridge | 172:7d866c31b3c5 | 312 | status = I2C_GetState(obj->i2c); |
| AnnaBridge | 172:7d866c31b3c5 | 313 | if (status.Bit.TRx) { |
| AnnaBridge | 172:7d866c31b3c5 | 314 | return (count); |
| AnnaBridge | 172:7d866c31b3c5 | 315 | } else { |
| AnnaBridge | 172:7d866c31b3c5 | 316 | if (pdata < 0) { |
| AnnaBridge | 172:7d866c31b3c5 | 317 | break; |
| AnnaBridge | 172:7d866c31b3c5 | 318 | } |
| AnnaBridge | 172:7d866c31b3c5 | 319 | data[count++] = (uint8_t)pdata; |
| AnnaBridge | 172:7d866c31b3c5 | 320 | } |
| AnnaBridge | 172:7d866c31b3c5 | 321 | } |
| AnnaBridge | 172:7d866c31b3c5 | 322 | i2c_slave_mode(obj, 1); |
| AnnaBridge | 172:7d866c31b3c5 | 323 | return (count); |
| AnnaBridge | 172:7d866c31b3c5 | 324 | } |
| AnnaBridge | 172:7d866c31b3c5 | 325 | |
| AnnaBridge | 172:7d866c31b3c5 | 326 | int i2c_slave_write(i2c_t *obj, const char *data, int length) |
| AnnaBridge | 172:7d866c31b3c5 | 327 | { |
| AnnaBridge | 172:7d866c31b3c5 | 328 | int32_t count = 0; |
| AnnaBridge | 172:7d866c31b3c5 | 329 | |
| AnnaBridge | 172:7d866c31b3c5 | 330 | while (count < length) { |
| AnnaBridge | 172:7d866c31b3c5 | 331 | if (i2c_byte_write(obj, (int32_t)data[count++]) < I2C_ACK) { |
| AnnaBridge | 172:7d866c31b3c5 | 332 | break; |
| AnnaBridge | 172:7d866c31b3c5 | 333 | } |
| AnnaBridge | 172:7d866c31b3c5 | 334 | } |
| AnnaBridge | 172:7d866c31b3c5 | 335 | i2c_slave_mode(obj, 1); |
| AnnaBridge | 172:7d866c31b3c5 | 336 | return (count); |
| AnnaBridge | 172:7d866c31b3c5 | 337 | } |
| AnnaBridge | 172:7d866c31b3c5 | 338 | |
| AnnaBridge | 172:7d866c31b3c5 | 339 | void i2c_slave_address(i2c_t *obj, int idx, uint32_t address, uint32_t mask) |
| AnnaBridge | 172:7d866c31b3c5 | 340 | { |
| AnnaBridge | 172:7d866c31b3c5 | 341 | obj->address = address & 0xFE; |
| AnnaBridge | 172:7d866c31b3c5 | 342 | i2c_slave_mode(obj, 1); |
| AnnaBridge | 172:7d866c31b3c5 | 343 | } |
