Color Oled(SSD1331) connect to STMicroelectronics Nucleo-F466

Dependencies:   ssd1331

Committer:
kadonotakashi
Date:
Thu Oct 11 02:27:46 2018 +0000
Revision:
3:f3764f852aa8
Parent:
0:8fdf9a60065b
Nucreo 446 + SSD1331 test version;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kadonotakashi 0:8fdf9a60065b 1 /* mbed Microcontroller Library
kadonotakashi 0:8fdf9a60065b 2 * Copyright (c) 2006-2015 ARM Limited
kadonotakashi 0:8fdf9a60065b 3 *
kadonotakashi 0:8fdf9a60065b 4 * Licensed under the Apache License, Version 2.0 (the "License");
kadonotakashi 0:8fdf9a60065b 5 * you may not use this file except in compliance with the License.
kadonotakashi 0:8fdf9a60065b 6 * You may obtain a copy of the License at
kadonotakashi 0:8fdf9a60065b 7 *
kadonotakashi 0:8fdf9a60065b 8 * http://www.apache.org/licenses/LICENSE-2.0
kadonotakashi 0:8fdf9a60065b 9 *
kadonotakashi 0:8fdf9a60065b 10 * Unless required by applicable law or agreed to in writing, software
kadonotakashi 0:8fdf9a60065b 11 * distributed under the License is distributed on an "AS IS" BASIS,
kadonotakashi 0:8fdf9a60065b 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
kadonotakashi 0:8fdf9a60065b 13 * See the License for the specific language governing permissions and
kadonotakashi 0:8fdf9a60065b 14 * limitations under the License.
kadonotakashi 0:8fdf9a60065b 15 */
kadonotakashi 0:8fdf9a60065b 16
kadonotakashi 0:8fdf9a60065b 17 #include "device.h"
kadonotakashi 0:8fdf9a60065b 18 #include "buffer.h"
kadonotakashi 0:8fdf9a60065b 19 #include "dma_api.h"
kadonotakashi 0:8fdf9a60065b 20 #include "i2c_api.h"
kadonotakashi 0:8fdf9a60065b 21 #include "PeripheralPins.h"
kadonotakashi 0:8fdf9a60065b 22 #include "twi.h"
kadonotakashi 0:8fdf9a60065b 23 #include "pdc.h"
kadonotakashi 0:8fdf9a60065b 24 #include "mbed_assert.h"
kadonotakashi 0:8fdf9a60065b 25 #include "ioport.h"
kadonotakashi 0:8fdf9a60065b 26
kadonotakashi 0:8fdf9a60065b 27 /**
kadonotakashi 0:8fdf9a60065b 28 * \defgroup GeneralI2C I2C Configuration Functions
kadonotakashi 0:8fdf9a60065b 29 * @{
kadonotakashi 0:8fdf9a60065b 30 */
kadonotakashi 0:8fdf9a60065b 31
kadonotakashi 0:8fdf9a60065b 32 /** TWI Bus Clock 400kHz */
kadonotakashi 0:8fdf9a60065b 33 extern uint8_t g_sys_init;
kadonotakashi 0:8fdf9a60065b 34
kadonotakashi 0:8fdf9a60065b 35 #define TWI_CLK (400000u)
kadonotakashi 0:8fdf9a60065b 36
kadonotakashi 0:8fdf9a60065b 37 #define ADDR_LENGTH 0
kadonotakashi 0:8fdf9a60065b 38
kadonotakashi 0:8fdf9a60065b 39 #define MAX_I2C 8
kadonotakashi 0:8fdf9a60065b 40
kadonotakashi 0:8fdf9a60065b 41 extern uint32_t twi_mk_addr(const uint8_t *addr, int len);
kadonotakashi 0:8fdf9a60065b 42
kadonotakashi 0:8fdf9a60065b 43 void pinmap_find_i2c_info(Twi *sercombase, i2c_t *obj)
kadonotakashi 0:8fdf9a60065b 44 {
kadonotakashi 0:8fdf9a60065b 45 if(sercombase==TWI0) {
kadonotakashi 0:8fdf9a60065b 46 obj->i2c.flexcom=FLEXCOM0;
kadonotakashi 0:8fdf9a60065b 47 obj->i2c.module_number=0;
kadonotakashi 0:8fdf9a60065b 48 obj->i2c.pdc =PDC_TWI0;
kadonotakashi 0:8fdf9a60065b 49 obj->i2c.irq_type=FLEXCOM0_IRQn;
kadonotakashi 0:8fdf9a60065b 50 } else if(sercombase==TWI1) {
kadonotakashi 0:8fdf9a60065b 51 obj->i2c.flexcom=FLEXCOM1;
kadonotakashi 0:8fdf9a60065b 52 obj->i2c.module_number=1;
kadonotakashi 0:8fdf9a60065b 53 obj->i2c.pdc =PDC_TWI1;
kadonotakashi 0:8fdf9a60065b 54 obj->i2c.irq_type=FLEXCOM1_IRQn;
kadonotakashi 0:8fdf9a60065b 55 } else if(sercombase==TWI2) {
kadonotakashi 0:8fdf9a60065b 56 obj->i2c.flexcom=FLEXCOM2;
kadonotakashi 0:8fdf9a60065b 57 obj->i2c.module_number=2;
kadonotakashi 0:8fdf9a60065b 58 obj->i2c.pdc =PDC_TWI2;
kadonotakashi 0:8fdf9a60065b 59 obj->i2c.irq_type=FLEXCOM2_IRQn;
kadonotakashi 0:8fdf9a60065b 60 } else if(sercombase==TWI3) {
kadonotakashi 0:8fdf9a60065b 61 obj->i2c.flexcom=FLEXCOM3;
kadonotakashi 0:8fdf9a60065b 62 obj->i2c.module_number=3;
kadonotakashi 0:8fdf9a60065b 63 obj->i2c.pdc =PDC_TWI3;
kadonotakashi 0:8fdf9a60065b 64 obj->i2c.irq_type=FLEXCOM3_IRQn;
kadonotakashi 0:8fdf9a60065b 65 } else if(sercombase==TWI4) {
kadonotakashi 0:8fdf9a60065b 66 obj->i2c.flexcom=FLEXCOM4;
kadonotakashi 0:8fdf9a60065b 67 obj->i2c.module_number=4;
kadonotakashi 0:8fdf9a60065b 68 obj->i2c.pdc =PDC_TWI4;
kadonotakashi 0:8fdf9a60065b 69 obj->i2c.irq_type=FLEXCOM4_IRQn;
kadonotakashi 0:8fdf9a60065b 70 } else if(sercombase==TWI5) {
kadonotakashi 0:8fdf9a60065b 71 obj->i2c.flexcom=FLEXCOM5;
kadonotakashi 0:8fdf9a60065b 72 obj->i2c.module_number=5;
kadonotakashi 0:8fdf9a60065b 73 obj->i2c.pdc =PDC_TWI5;
kadonotakashi 0:8fdf9a60065b 74 obj->i2c.irq_type=FLEXCOM5_IRQn;
kadonotakashi 0:8fdf9a60065b 75 } else if(sercombase==TWI6) {
kadonotakashi 0:8fdf9a60065b 76 obj->i2c.flexcom=FLEXCOM6;
kadonotakashi 0:8fdf9a60065b 77 obj->i2c.module_number=6;
kadonotakashi 0:8fdf9a60065b 78 obj->i2c.pdc =PDC_TWI6;
kadonotakashi 0:8fdf9a60065b 79 obj->i2c.irq_type=FLEXCOM6_IRQn;
kadonotakashi 0:8fdf9a60065b 80 } else if(sercombase==TWI7) {
kadonotakashi 0:8fdf9a60065b 81 obj->i2c.flexcom=FLEXCOM7;
kadonotakashi 0:8fdf9a60065b 82 obj->i2c.module_number=7;
kadonotakashi 0:8fdf9a60065b 83 obj->i2c.pdc =PDC_TWI7;
kadonotakashi 0:8fdf9a60065b 84 obj->i2c.irq_type=FLEXCOM7_IRQn;
kadonotakashi 0:8fdf9a60065b 85 } else {
kadonotakashi 0:8fdf9a60065b 86 obj->i2c.flexcom=(Flexcom *)NC;
kadonotakashi 0:8fdf9a60065b 87 obj->i2c.module_number=0;
kadonotakashi 0:8fdf9a60065b 88 obj->i2c.pdc =(Pdc *) NC;
kadonotakashi 0:8fdf9a60065b 89 }
kadonotakashi 0:8fdf9a60065b 90 }
kadonotakashi 0:8fdf9a60065b 91
kadonotakashi 0:8fdf9a60065b 92
kadonotakashi 0:8fdf9a60065b 93 /** Initialize the I2C peripheral. It sets the default parameters for I2C
kadonotakashi 0:8fdf9a60065b 94 * peripheral, and configure its specifieds pins.
kadonotakashi 0:8fdf9a60065b 95 * @param obj The i2c object
kadonotakashi 0:8fdf9a60065b 96 * @param sda The sda pin
kadonotakashi 0:8fdf9a60065b 97 * @param scl The scl pin
kadonotakashi 0:8fdf9a60065b 98 */
kadonotakashi 0:8fdf9a60065b 99 void i2c_init(i2c_t *obj, PinName sda, PinName scl)
kadonotakashi 0:8fdf9a60065b 100 {
kadonotakashi 0:8fdf9a60065b 101 MBED_ASSERT(obj);
kadonotakashi 0:8fdf9a60065b 102 MBED_ASSERT(sda !=NC && scl!=NC );
kadonotakashi 0:8fdf9a60065b 103
kadonotakashi 0:8fdf9a60065b 104 if (g_sys_init == 0) {
kadonotakashi 0:8fdf9a60065b 105 sysclk_init();
kadonotakashi 0:8fdf9a60065b 106 board_init();
kadonotakashi 0:8fdf9a60065b 107 g_sys_init = 1;
kadonotakashi 0:8fdf9a60065b 108 }
kadonotakashi 0:8fdf9a60065b 109
kadonotakashi 0:8fdf9a60065b 110
kadonotakashi 0:8fdf9a60065b 111 Twi* sda_base = (Twi*)pinmap_peripheral(sda, PinMap_I2C_SDA);
kadonotakashi 0:8fdf9a60065b 112 Twi* scl_base = (Twi*)pinmap_peripheral(scl, PinMap_I2C_SCL);
kadonotakashi 0:8fdf9a60065b 113 Twi* I2cBase = (Twi*)pinmap_merge((uint32_t)sda_base, (uint32_t)scl_base);
kadonotakashi 0:8fdf9a60065b 114
kadonotakashi 0:8fdf9a60065b 115 MBED_ASSERT(I2cBase !=NC );
kadonotakashi 0:8fdf9a60065b 116
kadonotakashi 0:8fdf9a60065b 117 obj->i2c.i2c_base=I2cBase;
kadonotakashi 0:8fdf9a60065b 118 pinmap_find_i2c_info(I2cBase,obj);
kadonotakashi 0:8fdf9a60065b 119
kadonotakashi 0:8fdf9a60065b 120 /* Configure I2C pins */
kadonotakashi 0:8fdf9a60065b 121 pin_function(sda, pinmap_find_function(sda, PinMap_I2C_SDA));
kadonotakashi 0:8fdf9a60065b 122 ioport_disable_pin(sda);
kadonotakashi 0:8fdf9a60065b 123
kadonotakashi 0:8fdf9a60065b 124 pin_function(scl, pinmap_find_function(scl, PinMap_I2C_SCL));
kadonotakashi 0:8fdf9a60065b 125 ioport_disable_pin(scl);
kadonotakashi 0:8fdf9a60065b 126
kadonotakashi 0:8fdf9a60065b 127 #if (SAMG55)
kadonotakashi 0:8fdf9a60065b 128 /* Enable the peripheral and set TWI mode. */
kadonotakashi 0:8fdf9a60065b 129 MBED_ASSERT((int)obj->i2c.flexcom!=NC);
kadonotakashi 0:8fdf9a60065b 130 flexcom_enable(obj->i2c.flexcom);
kadonotakashi 0:8fdf9a60065b 131 flexcom_set_opmode(obj->i2c.flexcom, FLEXCOM_TWI);
kadonotakashi 0:8fdf9a60065b 132 #else
kadonotakashi 0:8fdf9a60065b 133 /* Enable the peripheral clock for TWI */
kadonotakashi 0:8fdf9a60065b 134 pmc_enable_periph_clk(obj->i2c.i2c_base);
kadonotakashi 0:8fdf9a60065b 135 #endif
kadonotakashi 0:8fdf9a60065b 136
kadonotakashi 0:8fdf9a60065b 137 twi_options_t twi_options;
kadonotakashi 0:8fdf9a60065b 138 twi_options.master_clk=sysclk_get_cpu_hz();
kadonotakashi 0:8fdf9a60065b 139 twi_options.speed=TWI_CLK;
kadonotakashi 0:8fdf9a60065b 140 twi_options.smbus = 0;
kadonotakashi 0:8fdf9a60065b 141
kadonotakashi 0:8fdf9a60065b 142 twi_master_init(obj->i2c.i2c_base,&twi_options);
kadonotakashi 0:8fdf9a60065b 143
kadonotakashi 0:8fdf9a60065b 144 obj->i2c.is_slave=false;
kadonotakashi 0:8fdf9a60065b 145 obj->i2c.speed=TWI_CLK;
kadonotakashi 0:8fdf9a60065b 146 obj->i2c.master_clk=twi_options.master_clk;
kadonotakashi 0:8fdf9a60065b 147 }
kadonotakashi 0:8fdf9a60065b 148
kadonotakashi 0:8fdf9a60065b 149 /** Configure the I2C frequency.
kadonotakashi 0:8fdf9a60065b 150 * @param obj The i2c object
kadonotakashi 0:8fdf9a60065b 151 * @param hz Frequency in Hz
kadonotakashi 0:8fdf9a60065b 152 */
kadonotakashi 0:8fdf9a60065b 153 void i2c_frequency(i2c_t *obj, int hz)
kadonotakashi 0:8fdf9a60065b 154 {
kadonotakashi 0:8fdf9a60065b 155 MBED_ASSERT(obj);
kadonotakashi 0:8fdf9a60065b 156 if(obj->i2c.is_slave)
kadonotakashi 0:8fdf9a60065b 157 twi_disable_slave_mode(obj->i2c.i2c_base);
kadonotakashi 0:8fdf9a60065b 158 else
kadonotakashi 0:8fdf9a60065b 159 twi_disable_master_mode(obj->i2c.i2c_base);
kadonotakashi 0:8fdf9a60065b 160
kadonotakashi 0:8fdf9a60065b 161 twi_set_speed(obj->i2c.i2c_base,hz,obj->i2c.master_clk);
kadonotakashi 0:8fdf9a60065b 162
kadonotakashi 0:8fdf9a60065b 163 if(obj->i2c.is_slave)
kadonotakashi 0:8fdf9a60065b 164 twi_enable_slave_mode(obj->i2c.i2c_base);
kadonotakashi 0:8fdf9a60065b 165 else
kadonotakashi 0:8fdf9a60065b 166 twi_enable_master_mode(obj->i2c.i2c_base);
kadonotakashi 0:8fdf9a60065b 167 }
kadonotakashi 0:8fdf9a60065b 168
kadonotakashi 0:8fdf9a60065b 169 /** Send START command.
kadonotakashi 0:8fdf9a60065b 170 * @param obj The i2c object
kadonotakashi 0:8fdf9a60065b 171 */
kadonotakashi 0:8fdf9a60065b 172 int i2c_start(i2c_t *obj)
kadonotakashi 0:8fdf9a60065b 173 {
kadonotakashi 0:8fdf9a60065b 174 MBED_ASSERT(obj);
kadonotakashi 0:8fdf9a60065b 175 obj->i2c.i2c_base->TWI_CR = TWI_CR_START;
kadonotakashi 0:8fdf9a60065b 176 return 0;
kadonotakashi 0:8fdf9a60065b 177 }
kadonotakashi 0:8fdf9a60065b 178
kadonotakashi 0:8fdf9a60065b 179 /** Send STOP command.
kadonotakashi 0:8fdf9a60065b 180 * @param obj The i2c object
kadonotakashi 0:8fdf9a60065b 181 */
kadonotakashi 0:8fdf9a60065b 182 int i2c_stop(i2c_t *obj)
kadonotakashi 0:8fdf9a60065b 183 {
kadonotakashi 0:8fdf9a60065b 184 MBED_ASSERT(obj);
kadonotakashi 0:8fdf9a60065b 185 obj->i2c.i2c_base->TWI_CR = TWI_CR_STOP;
kadonotakashi 0:8fdf9a60065b 186 return 0;
kadonotakashi 0:8fdf9a60065b 187 }
kadonotakashi 0:8fdf9a60065b 188
kadonotakashi 0:8fdf9a60065b 189
kadonotakashi 0:8fdf9a60065b 190 uint32_t twi_master_read_no_stop(Twi *p_twi, twi_packet_t *p_packet, uint8_t stopena)
kadonotakashi 0:8fdf9a60065b 191 {
kadonotakashi 0:8fdf9a60065b 192 uint32_t status;
kadonotakashi 0:8fdf9a60065b 193 uint32_t cnt = p_packet->length;
kadonotakashi 0:8fdf9a60065b 194 uint8_t *buffer = p_packet->buffer;
kadonotakashi 0:8fdf9a60065b 195 uint8_t stop_sent = 0;
kadonotakashi 0:8fdf9a60065b 196 uint32_t timeout = TWI_TIMEOUT;;
kadonotakashi 0:8fdf9a60065b 197
kadonotakashi 0:8fdf9a60065b 198 /* Check argument */
kadonotakashi 0:8fdf9a60065b 199 if (cnt == 0) {
kadonotakashi 0:8fdf9a60065b 200 return TWI_INVALID_ARGUMENT;
kadonotakashi 0:8fdf9a60065b 201 }
kadonotakashi 0:8fdf9a60065b 202
kadonotakashi 0:8fdf9a60065b 203 /* Set read mode, slave address and 3 internal address byte lengths */
kadonotakashi 0:8fdf9a60065b 204 p_twi->TWI_MMR = 0;
kadonotakashi 0:8fdf9a60065b 205 p_twi->TWI_MMR = TWI_MMR_MREAD | TWI_MMR_DADR(p_packet->chip) |
kadonotakashi 0:8fdf9a60065b 206 ((p_packet->addr_length << TWI_MMR_IADRSZ_Pos) &
kadonotakashi 0:8fdf9a60065b 207 TWI_MMR_IADRSZ_Msk);
kadonotakashi 0:8fdf9a60065b 208
kadonotakashi 0:8fdf9a60065b 209 /* Send a START condition */
kadonotakashi 0:8fdf9a60065b 210 if ((cnt == 1) && (stopena == 1)) {
kadonotakashi 0:8fdf9a60065b 211 p_twi->TWI_CR = TWI_CR_START | TWI_CR_STOP;
kadonotakashi 0:8fdf9a60065b 212 stop_sent = 1;
kadonotakashi 0:8fdf9a60065b 213 } else {
kadonotakashi 0:8fdf9a60065b 214 p_twi->TWI_CR = TWI_CR_START;
kadonotakashi 0:8fdf9a60065b 215 stop_sent = 0;
kadonotakashi 0:8fdf9a60065b 216 }
kadonotakashi 0:8fdf9a60065b 217
kadonotakashi 0:8fdf9a60065b 218 while (cnt > 0) {
kadonotakashi 0:8fdf9a60065b 219 status = p_twi->TWI_SR;
kadonotakashi 0:8fdf9a60065b 220 if (status & TWI_SR_NACK) {
kadonotakashi 0:8fdf9a60065b 221 return TWI_RECEIVE_NACK;
kadonotakashi 0:8fdf9a60065b 222 }
kadonotakashi 0:8fdf9a60065b 223
kadonotakashi 0:8fdf9a60065b 224 if (!timeout--) {
kadonotakashi 0:8fdf9a60065b 225 return TWI_ERROR_TIMEOUT;
kadonotakashi 0:8fdf9a60065b 226 }
kadonotakashi 0:8fdf9a60065b 227
kadonotakashi 0:8fdf9a60065b 228 /* Last byte ? */
kadonotakashi 0:8fdf9a60065b 229 if ((cnt == 1) && (!stop_sent) && (stopena == 1)) {
kadonotakashi 0:8fdf9a60065b 230 p_twi->TWI_CR = TWI_CR_STOP;
kadonotakashi 0:8fdf9a60065b 231 stop_sent = 1;
kadonotakashi 0:8fdf9a60065b 232 }
kadonotakashi 0:8fdf9a60065b 233
kadonotakashi 0:8fdf9a60065b 234 if (!(status & TWI_SR_RXRDY)) {
kadonotakashi 0:8fdf9a60065b 235 continue;
kadonotakashi 0:8fdf9a60065b 236 }
kadonotakashi 0:8fdf9a60065b 237 *buffer++ = p_twi->TWI_RHR;
kadonotakashi 0:8fdf9a60065b 238
kadonotakashi 0:8fdf9a60065b 239 cnt--;
kadonotakashi 0:8fdf9a60065b 240 timeout = TWI_TIMEOUT;
kadonotakashi 0:8fdf9a60065b 241 }
kadonotakashi 0:8fdf9a60065b 242 if(stopena) {
kadonotakashi 0:8fdf9a60065b 243 while (!(p_twi->TWI_SR & TWI_SR_TXCOMP)) {
kadonotakashi 0:8fdf9a60065b 244 }
kadonotakashi 0:8fdf9a60065b 245 }
kadonotakashi 0:8fdf9a60065b 246
kadonotakashi 0:8fdf9a60065b 247 p_twi->TWI_SR;
kadonotakashi 0:8fdf9a60065b 248
kadonotakashi 0:8fdf9a60065b 249 return TWI_SUCCESS;
kadonotakashi 0:8fdf9a60065b 250
kadonotakashi 0:8fdf9a60065b 251 }
kadonotakashi 0:8fdf9a60065b 252
kadonotakashi 0:8fdf9a60065b 253
kadonotakashi 0:8fdf9a60065b 254
kadonotakashi 0:8fdf9a60065b 255
kadonotakashi 0:8fdf9a60065b 256
kadonotakashi 0:8fdf9a60065b 257 /** Blocking reading data.
kadonotakashi 0:8fdf9a60065b 258 * @param obj The i2c object
kadonotakashi 0:8fdf9a60065b 259 * @param address 7-bit address (last bit is 1)
kadonotakashi 0:8fdf9a60065b 260 * @param data The buffer for receiving
kadonotakashi 0:8fdf9a60065b 261 * @param length Number of bytes to read
kadonotakashi 0:8fdf9a60065b 262 * @param stop Stop to be generated after the transfer is done
kadonotakashi 0:8fdf9a60065b 263 * @return Number of read bytes
kadonotakashi 0:8fdf9a60065b 264 */
kadonotakashi 0:8fdf9a60065b 265 int i2c_read(i2c_t *obj, int address, char *data, int length, int stop)
kadonotakashi 0:8fdf9a60065b 266 {
kadonotakashi 0:8fdf9a60065b 267 MBED_ASSERT(obj);
kadonotakashi 0:8fdf9a60065b 268
kadonotakashi 0:8fdf9a60065b 269 twi_packet_t packet;
kadonotakashi 0:8fdf9a60065b 270 packet.chip= (address>>1) & 0x7F;
kadonotakashi 0:8fdf9a60065b 271 packet.addr_length=ADDR_LENGTH;
kadonotakashi 0:8fdf9a60065b 272 packet.buffer=data;
kadonotakashi 0:8fdf9a60065b 273 packet.length=length;
kadonotakashi 0:8fdf9a60065b 274
kadonotakashi 0:8fdf9a60065b 275 uint8_t status;
kadonotakashi 0:8fdf9a60065b 276 status= twi_master_read_no_stop(obj->i2c.i2c_base, &packet, stop);
kadonotakashi 0:8fdf9a60065b 277
kadonotakashi 0:8fdf9a60065b 278 if(TWI_SUCCESS==status)
kadonotakashi 0:8fdf9a60065b 279 return length;
kadonotakashi 0:8fdf9a60065b 280
kadonotakashi 0:8fdf9a60065b 281 return 0;
kadonotakashi 0:8fdf9a60065b 282 }
kadonotakashi 0:8fdf9a60065b 283
kadonotakashi 0:8fdf9a60065b 284
kadonotakashi 0:8fdf9a60065b 285 uint32_t twi_master_write_no_stop(Twi *p_twi, twi_packet_t *p_packet, uint8_t stopena)
kadonotakashi 0:8fdf9a60065b 286 {
kadonotakashi 0:8fdf9a60065b 287 uint32_t status;
kadonotakashi 0:8fdf9a60065b 288 uint32_t cnt = p_packet->length;
kadonotakashi 0:8fdf9a60065b 289 uint8_t *buffer = p_packet->buffer;
kadonotakashi 0:8fdf9a60065b 290
kadonotakashi 0:8fdf9a60065b 291 /* Check argument */
kadonotakashi 0:8fdf9a60065b 292 if (cnt == 0) {
kadonotakashi 0:8fdf9a60065b 293 return TWI_INVALID_ARGUMENT;
kadonotakashi 0:8fdf9a60065b 294 }
kadonotakashi 0:8fdf9a60065b 295
kadonotakashi 0:8fdf9a60065b 296 /* Set write mode, slave address and 3 internal address byte lengths */
kadonotakashi 0:8fdf9a60065b 297 p_twi->TWI_MMR = 0;
kadonotakashi 0:8fdf9a60065b 298 p_twi->TWI_MMR = TWI_MMR_DADR(p_packet->chip) |
kadonotakashi 0:8fdf9a60065b 299 ((p_packet->addr_length << TWI_MMR_IADRSZ_Pos) &
kadonotakashi 0:8fdf9a60065b 300 TWI_MMR_IADRSZ_Msk);
kadonotakashi 0:8fdf9a60065b 301
kadonotakashi 0:8fdf9a60065b 302 /* Send a START condition */
kadonotakashi 0:8fdf9a60065b 303 if ((cnt == 1) && (stopena == 1)) {
kadonotakashi 0:8fdf9a60065b 304 p_twi->TWI_CR = TWI_CR_START | TWI_CR_STOP;
kadonotakashi 0:8fdf9a60065b 305 } else {
kadonotakashi 0:8fdf9a60065b 306 p_twi->TWI_CR = TWI_CR_START;
kadonotakashi 0:8fdf9a60065b 307 }
kadonotakashi 0:8fdf9a60065b 308
kadonotakashi 0:8fdf9a60065b 309 /* Send all bytes */
kadonotakashi 0:8fdf9a60065b 310 while (cnt > 0) {
kadonotakashi 0:8fdf9a60065b 311 status = p_twi->TWI_SR;
kadonotakashi 0:8fdf9a60065b 312 if (status & TWI_SR_NACK) {
kadonotakashi 0:8fdf9a60065b 313 return TWI_RECEIVE_NACK;
kadonotakashi 0:8fdf9a60065b 314 }
kadonotakashi 0:8fdf9a60065b 315
kadonotakashi 0:8fdf9a60065b 316 if (!(status & TWI_SR_TXRDY)) {
kadonotakashi 0:8fdf9a60065b 317 continue;
kadonotakashi 0:8fdf9a60065b 318 }
kadonotakashi 0:8fdf9a60065b 319 p_twi->TWI_THR = *buffer++;
kadonotakashi 0:8fdf9a60065b 320
kadonotakashi 0:8fdf9a60065b 321 cnt--;
kadonotakashi 0:8fdf9a60065b 322 }
kadonotakashi 0:8fdf9a60065b 323
kadonotakashi 0:8fdf9a60065b 324 while (1) {
kadonotakashi 0:8fdf9a60065b 325 status = p_twi->TWI_SR;
kadonotakashi 0:8fdf9a60065b 326 if (status & TWI_SR_NACK) {
kadonotakashi 0:8fdf9a60065b 327 return TWI_RECEIVE_NACK;
kadonotakashi 0:8fdf9a60065b 328 }
kadonotakashi 0:8fdf9a60065b 329
kadonotakashi 0:8fdf9a60065b 330 if (status & TWI_SR_TXRDY) {
kadonotakashi 0:8fdf9a60065b 331 break;
kadonotakashi 0:8fdf9a60065b 332 }
kadonotakashi 0:8fdf9a60065b 333 }
kadonotakashi 0:8fdf9a60065b 334
kadonotakashi 0:8fdf9a60065b 335 if (stopena) {
kadonotakashi 0:8fdf9a60065b 336 p_twi->TWI_CR = TWI_CR_STOP;
kadonotakashi 0:8fdf9a60065b 337 while (!(p_twi->TWI_SR & TWI_SR_TXCOMP));
kadonotakashi 0:8fdf9a60065b 338 }
kadonotakashi 0:8fdf9a60065b 339
kadonotakashi 0:8fdf9a60065b 340 return TWI_SUCCESS;
kadonotakashi 0:8fdf9a60065b 341 }
kadonotakashi 0:8fdf9a60065b 342
kadonotakashi 0:8fdf9a60065b 343
kadonotakashi 0:8fdf9a60065b 344
kadonotakashi 0:8fdf9a60065b 345 /** Blocking sending data.
kadonotakashi 0:8fdf9a60065b 346 * @param obj The i2c object
kadonotakashi 0:8fdf9a60065b 347 * @param address 7-bit address (last bit is 0)
kadonotakashi 0:8fdf9a60065b 348 * @param data The buffer for sending
kadonotakashi 0:8fdf9a60065b 349 * @param length Number of bytes to wrte
kadonotakashi 0:8fdf9a60065b 350 * @param stop Stop to be generated after the transfer is done
kadonotakashi 0:8fdf9a60065b 351 * @return Number of written bytes
kadonotakashi 0:8fdf9a60065b 352 */
kadonotakashi 0:8fdf9a60065b 353 int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop)
kadonotakashi 0:8fdf9a60065b 354 {
kadonotakashi 0:8fdf9a60065b 355 MBED_ASSERT(obj);
kadonotakashi 0:8fdf9a60065b 356
kadonotakashi 0:8fdf9a60065b 357 twi_packet_t packet;
kadonotakashi 0:8fdf9a60065b 358 packet.chip= (address>>1) & 0x7F;
kadonotakashi 0:8fdf9a60065b 359 packet.addr_length=ADDR_LENGTH;
kadonotakashi 0:8fdf9a60065b 360 packet.buffer= (void *)data;
kadonotakashi 0:8fdf9a60065b 361 packet.length=length;
kadonotakashi 0:8fdf9a60065b 362
kadonotakashi 0:8fdf9a60065b 363 uint8_t status;
kadonotakashi 0:8fdf9a60065b 364 status= twi_master_write_no_stop(obj->i2c.i2c_base,&packet, stop);
kadonotakashi 0:8fdf9a60065b 365
kadonotakashi 0:8fdf9a60065b 366 if(TWI_SUCCESS==status)
kadonotakashi 0:8fdf9a60065b 367 return length;
kadonotakashi 0:8fdf9a60065b 368
kadonotakashi 0:8fdf9a60065b 369 return 0;
kadonotakashi 0:8fdf9a60065b 370 }
kadonotakashi 0:8fdf9a60065b 371
kadonotakashi 0:8fdf9a60065b 372 /** Reset I2C peripheral. TODO: The action here. Most of the implementation sends stop().
kadonotakashi 0:8fdf9a60065b 373 * @param obj The i2c object
kadonotakashi 0:8fdf9a60065b 374 */
kadonotakashi 0:8fdf9a60065b 375 void i2c_reset(i2c_t *obj)
kadonotakashi 0:8fdf9a60065b 376 {
kadonotakashi 0:8fdf9a60065b 377 MBED_ASSERT(obj);
kadonotakashi 0:8fdf9a60065b 378 twi_reset(obj->i2c.i2c_base);
kadonotakashi 0:8fdf9a60065b 379 }
kadonotakashi 0:8fdf9a60065b 380
kadonotakashi 0:8fdf9a60065b 381 /** Read one byte.
kadonotakashi 0:8fdf9a60065b 382 * @param obj The i2c object
kadonotakashi 0:8fdf9a60065b 383 * @param last Acknoledge
kadonotakashi 0:8fdf9a60065b 384 * @return The read byte
kadonotakashi 0:8fdf9a60065b 385 */
kadonotakashi 0:8fdf9a60065b 386 int i2c_byte_read(i2c_t *obj, int last)
kadonotakashi 0:8fdf9a60065b 387 {
kadonotakashi 0:8fdf9a60065b 388 MBED_ASSERT(obj);
kadonotakashi 0:8fdf9a60065b 389 if(!last)
kadonotakashi 0:8fdf9a60065b 390 twi_enable_slave_nack(obj->i2c.i2c_base);
kadonotakashi 0:8fdf9a60065b 391
kadonotakashi 0:8fdf9a60065b 392 return twi_read_byte(obj->i2c.i2c_base);
kadonotakashi 0:8fdf9a60065b 393 }
kadonotakashi 0:8fdf9a60065b 394
kadonotakashi 0:8fdf9a60065b 395 /** Write one byte.
kadonotakashi 0:8fdf9a60065b 396 * @param obj The i2c object
kadonotakashi 0:8fdf9a60065b 397 * @param data Byte to be written
kadonotakashi 0:8fdf9a60065b 398 * @return 1 if NAK was received, 0 if ACK was received, 2 for timeout.
kadonotakashi 0:8fdf9a60065b 399 */
kadonotakashi 0:8fdf9a60065b 400 #define ACK 0
kadonotakashi 0:8fdf9a60065b 401 #define NAK 1
kadonotakashi 0:8fdf9a60065b 402 #define TIMEOUT 2
kadonotakashi 0:8fdf9a60065b 403
kadonotakashi 0:8fdf9a60065b 404 int i2c_byte_write(i2c_t *obj, int data)
kadonotakashi 0:8fdf9a60065b 405 {
kadonotakashi 0:8fdf9a60065b 406 MBED_ASSERT(obj);
kadonotakashi 0:8fdf9a60065b 407 twi_write_byte(obj->i2c.i2c_base,data);
kadonotakashi 0:8fdf9a60065b 408
kadonotakashi 0:8fdf9a60065b 409 uint32_t timeout = TWI_TIMEOUT;
kadonotakashi 0:8fdf9a60065b 410 while (timeout--) {
kadonotakashi 0:8fdf9a60065b 411 uint32_t status = obj->i2c.i2c_base->TWI_SR;
kadonotakashi 0:8fdf9a60065b 412 if (status & TWI_SR_NACK) {
kadonotakashi 0:8fdf9a60065b 413 return NAK;
kadonotakashi 0:8fdf9a60065b 414 }
kadonotakashi 0:8fdf9a60065b 415
kadonotakashi 0:8fdf9a60065b 416 if (status & TWI_SR_TXRDY) {
kadonotakashi 0:8fdf9a60065b 417 return ACK;
kadonotakashi 0:8fdf9a60065b 418 }
kadonotakashi 0:8fdf9a60065b 419
kadonotakashi 0:8fdf9a60065b 420 if (timeout<1) {
kadonotakashi 0:8fdf9a60065b 421 return TIMEOUT;
kadonotakashi 0:8fdf9a60065b 422 }
kadonotakashi 0:8fdf9a60065b 423 }
kadonotakashi 0:8fdf9a60065b 424
kadonotakashi 0:8fdf9a60065b 425 return ACK;
kadonotakashi 0:8fdf9a60065b 426 }
kadonotakashi 0:8fdf9a60065b 427
kadonotakashi 0:8fdf9a60065b 428 /**@}*/
kadonotakashi 0:8fdf9a60065b 429
kadonotakashi 0:8fdf9a60065b 430 #if DEVICE_I2CSLAVE
kadonotakashi 0:8fdf9a60065b 431
kadonotakashi 0:8fdf9a60065b 432 /**
kadonotakashi 0:8fdf9a60065b 433 * \defgroup SynchI2C Synchronous I2C Hardware Abstraction Layer for slave
kadonotakashi 0:8fdf9a60065b 434 * @{
kadonotakashi 0:8fdf9a60065b 435 */
kadonotakashi 0:8fdf9a60065b 436
kadonotakashi 0:8fdf9a60065b 437 /** Configure I2C as slave or master.
kadonotakashi 0:8fdf9a60065b 438 * @param obj The I2C object
kadonotakashi 0:8fdf9a60065b 439 * @return non-zero if a value is available
kadonotakashi 0:8fdf9a60065b 440 */
kadonotakashi 0:8fdf9a60065b 441 void i2c_slave_mode(i2c_t *obj, int enable_slave)
kadonotakashi 0:8fdf9a60065b 442 {
kadonotakashi 0:8fdf9a60065b 443 MBED_ASSERT(obj);
kadonotakashi 0:8fdf9a60065b 444 /* Disable TWI interrupts */
kadonotakashi 0:8fdf9a60065b 445 obj->i2c.i2c_base->TWI_IDR = ~0UL;
kadonotakashi 0:8fdf9a60065b 446 obj->i2c.i2c_base->TWI_SR;
kadonotakashi 0:8fdf9a60065b 447
kadonotakashi 0:8fdf9a60065b 448 /* Reset TWI */
kadonotakashi 0:8fdf9a60065b 449 twi_reset(obj->i2c.i2c_base);
kadonotakashi 0:8fdf9a60065b 450
kadonotakashi 0:8fdf9a60065b 451 MBED_ASSERT(obj);
kadonotakashi 0:8fdf9a60065b 452 if(enable_slave)
kadonotakashi 0:8fdf9a60065b 453 twi_enable_slave_mode(obj->i2c.i2c_base);
kadonotakashi 0:8fdf9a60065b 454 else
kadonotakashi 0:8fdf9a60065b 455 twi_enable_master_mode(obj->i2c.i2c_base);
kadonotakashi 0:8fdf9a60065b 456 }
kadonotakashi 0:8fdf9a60065b 457
kadonotakashi 0:8fdf9a60065b 458 /** Check to see if the I2C slave has been addressed.
kadonotakashi 0:8fdf9a60065b 459 * @param obj The I2C object
kadonotakashi 0:8fdf9a60065b 460 * @return The status - 1 - read addresses, 2 - write to all slaves,
kadonotakashi 0:8fdf9a60065b 461 * 3 write addressed, 0 - the slave has not been addressed
kadonotakashi 0:8fdf9a60065b 462 */
kadonotakashi 0:8fdf9a60065b 463 int i2c_slave_receive(i2c_t *obj)
kadonotakashi 0:8fdf9a60065b 464 {
kadonotakashi 0:8fdf9a60065b 465 uint32_t status = obj->i2c.i2c_base->TWI_SR;
kadonotakashi 0:8fdf9a60065b 466 if((status & TWI_SR_SVACC)) {
kadonotakashi 0:8fdf9a60065b 467 if(status & TWI_SR_SVREAD)
kadonotakashi 0:8fdf9a60065b 468 return 1;
kadonotakashi 0:8fdf9a60065b 469 else
kadonotakashi 0:8fdf9a60065b 470 return 3;
kadonotakashi 0:8fdf9a60065b 471 }
kadonotakashi 0:8fdf9a60065b 472 return 0;
kadonotakashi 0:8fdf9a60065b 473 }
kadonotakashi 0:8fdf9a60065b 474
kadonotakashi 0:8fdf9a60065b 475
kadonotakashi 0:8fdf9a60065b 476 uint32_t twi_slave_read_n(Twi *p_twi, uint8_t *p_data, int length)
kadonotakashi 0:8fdf9a60065b 477 {
kadonotakashi 0:8fdf9a60065b 478 uint32_t status, cnt = 0;
kadonotakashi 0:8fdf9a60065b 479
kadonotakashi 0:8fdf9a60065b 480 do {
kadonotakashi 0:8fdf9a60065b 481 status = p_twi->TWI_SR;
kadonotakashi 0:8fdf9a60065b 482 if (status & TWI_SR_SVACC) {
kadonotakashi 0:8fdf9a60065b 483 if (!(status & (TWI_SR_GACC| TWI_SR_SVREAD )) &&
kadonotakashi 0:8fdf9a60065b 484 (status & TWI_SR_RXRDY)
kadonotakashi 0:8fdf9a60065b 485 ) {
kadonotakashi 0:8fdf9a60065b 486 *p_data++ = (uint8_t) p_twi->TWI_RHR;
kadonotakashi 0:8fdf9a60065b 487 cnt++;
kadonotakashi 0:8fdf9a60065b 488 if(cnt>=length) break;
kadonotakashi 0:8fdf9a60065b 489 }
kadonotakashi 0:8fdf9a60065b 490 } else if ((status & (TWI_SR_EOSACC | TWI_SR_TXCOMP))
kadonotakashi 0:8fdf9a60065b 491 == (TWI_SR_EOSACC | TWI_SR_TXCOMP)) {
kadonotakashi 0:8fdf9a60065b 492 break;
kadonotakashi 0:8fdf9a60065b 493 }
kadonotakashi 0:8fdf9a60065b 494 } while (1);
kadonotakashi 0:8fdf9a60065b 495
kadonotakashi 0:8fdf9a60065b 496 return cnt;
kadonotakashi 0:8fdf9a60065b 497 }
kadonotakashi 0:8fdf9a60065b 498
kadonotakashi 0:8fdf9a60065b 499 /** Read I2C slave.
kadonotakashi 0:8fdf9a60065b 500 * @param obj The I2C object
kadonotakashi 0:8fdf9a60065b 501 * @return non-zero if a value is available
kadonotakashi 0:8fdf9a60065b 502 */
kadonotakashi 0:8fdf9a60065b 503 int i2c_slave_read(i2c_t *obj, char *data, int length)
kadonotakashi 0:8fdf9a60065b 504 {
kadonotakashi 0:8fdf9a60065b 505 MBED_ASSERT(obj);
kadonotakashi 0:8fdf9a60065b 506 int read= twi_slave_read_n(obj->i2c.i2c_base,(uint8_t *) data,length);
kadonotakashi 0:8fdf9a60065b 507 return read;
kadonotakashi 0:8fdf9a60065b 508 }
kadonotakashi 0:8fdf9a60065b 509
kadonotakashi 0:8fdf9a60065b 510
kadonotakashi 0:8fdf9a60065b 511 uint32_t twi_slave_write_n(Twi *p_twi, uint8_t *p_data, int length)
kadonotakashi 0:8fdf9a60065b 512 {
kadonotakashi 0:8fdf9a60065b 513 uint32_t status, cnt = 0;
kadonotakashi 0:8fdf9a60065b 514
kadonotakashi 0:8fdf9a60065b 515 do {
kadonotakashi 0:8fdf9a60065b 516 status = p_twi->TWI_SR;
kadonotakashi 0:8fdf9a60065b 517 if (status & TWI_SR_SVACC) {
kadonotakashi 0:8fdf9a60065b 518 if ((status & TWI_SR_SVREAD) && !(status & TWI_SR_GACC) &&
kadonotakashi 0:8fdf9a60065b 519 (status & TWI_SR_TXRDY)) {
kadonotakashi 0:8fdf9a60065b 520 p_twi->TWI_THR = *p_data++;
kadonotakashi 0:8fdf9a60065b 521 cnt++;
kadonotakashi 0:8fdf9a60065b 522 if(cnt>=length) break;
kadonotakashi 0:8fdf9a60065b 523 }
kadonotakashi 0:8fdf9a60065b 524 } else if ((status & (TWI_SR_EOSACC | TWI_SR_TXCOMP))
kadonotakashi 0:8fdf9a60065b 525 == (TWI_SR_EOSACC | TWI_SR_TXCOMP)) {
kadonotakashi 0:8fdf9a60065b 526 break;
kadonotakashi 0:8fdf9a60065b 527 }
kadonotakashi 0:8fdf9a60065b 528 } while (1);
kadonotakashi 0:8fdf9a60065b 529
kadonotakashi 0:8fdf9a60065b 530 return cnt;
kadonotakashi 0:8fdf9a60065b 531 }
kadonotakashi 0:8fdf9a60065b 532
kadonotakashi 0:8fdf9a60065b 533
kadonotakashi 0:8fdf9a60065b 534 /** Write I2C as slave.
kadonotakashi 0:8fdf9a60065b 535 * @param obj The I2C object
kadonotakashi 0:8fdf9a60065b 536 * @return non-zero if a value is available
kadonotakashi 0:8fdf9a60065b 537 */
kadonotakashi 0:8fdf9a60065b 538 int i2c_slave_write(i2c_t *obj, const char *data, int length)
kadonotakashi 0:8fdf9a60065b 539 {
kadonotakashi 0:8fdf9a60065b 540 MBED_ASSERT(obj);
kadonotakashi 0:8fdf9a60065b 541 int write= twi_slave_write_n(obj->i2c.i2c_base, (uint8_t *) data,length);
kadonotakashi 0:8fdf9a60065b 542 return write;
kadonotakashi 0:8fdf9a60065b 543 }
kadonotakashi 0:8fdf9a60065b 544
kadonotakashi 0:8fdf9a60065b 545 /** Configure I2C address.
kadonotakashi 0:8fdf9a60065b 546 * @param obj The I2C object
kadonotakashi 0:8fdf9a60065b 547 * @param idx Currently not used
kadonotakashi 0:8fdf9a60065b 548 * @param address The address to be set
kadonotakashi 0:8fdf9a60065b 549 * @param mask Currently not used
kadonotakashi 0:8fdf9a60065b 550 */
kadonotakashi 0:8fdf9a60065b 551 void i2c_slave_address(i2c_t *obj, int idx/*not used*/, uint32_t address, uint32_t mask)
kadonotakashi 0:8fdf9a60065b 552 {
kadonotakashi 0:8fdf9a60065b 553 MBED_ASSERT(obj);
kadonotakashi 0:8fdf9a60065b 554 twi_set_slave_addr(obj->i2c.i2c_base, (address>>1));
kadonotakashi 0:8fdf9a60065b 555 }
kadonotakashi 0:8fdf9a60065b 556
kadonotakashi 0:8fdf9a60065b 557 #endif
kadonotakashi 0:8fdf9a60065b 558
kadonotakashi 0:8fdf9a60065b 559 /**@}*/
kadonotakashi 0:8fdf9a60065b 560
kadonotakashi 0:8fdf9a60065b 561 #if DEVICE_I2C_ASYNCH
kadonotakashi 0:8fdf9a60065b 562
kadonotakashi 0:8fdf9a60065b 563 /**
kadonotakashi 0:8fdf9a60065b 564 * \defgroup AsynchI2C Asynchronous I2C Hardware Abstraction Layer
kadonotakashi 0:8fdf9a60065b 565 * @{
kadonotakashi 0:8fdf9a60065b 566 */
kadonotakashi 0:8fdf9a60065b 567
kadonotakashi 0:8fdf9a60065b 568 /** Start i2c asynchronous transfer.
kadonotakashi 0:8fdf9a60065b 569 * @param obj The I2C object
kadonotakashi 0:8fdf9a60065b 570 * @param tx The buffer to send
kadonotakashi 0:8fdf9a60065b 571 * @param tx_length The number of words to transmit
kadonotakashi 0:8fdf9a60065b 572 * @param rx The buffer to receive
kadonotakashi 0:8fdf9a60065b 573 * @param rx_length The number of words to receive
kadonotakashi 0:8fdf9a60065b 574 * @param address The address to be set - 7bit or 9 bit
kadonotakashi 0:8fdf9a60065b 575 * @param stop If true, stop will be generated after the transfer is done
kadonotakashi 0:8fdf9a60065b 576 * @param handler The I2C IRQ handler to be set
kadonotakashi 0:8fdf9a60065b 577 * @param hint DMA hint usage
kadonotakashi 0:8fdf9a60065b 578 */
kadonotakashi 0:8fdf9a60065b 579 #warning "Only DMA async supported by I2C master transfer"
kadonotakashi 0:8fdf9a60065b 580
kadonotakashi 0:8fdf9a60065b 581 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 /*Not Used*/)
kadonotakashi 0:8fdf9a60065b 582 {
kadonotakashi 0:8fdf9a60065b 583 uint32_t pdcenable=0;
kadonotakashi 0:8fdf9a60065b 584
kadonotakashi 0:8fdf9a60065b 585 if(address) {
kadonotakashi 0:8fdf9a60065b 586 twi_packet_t pdc_packet;
kadonotakashi 0:8fdf9a60065b 587 pdc_packet.chip=(address>>1) & 0x7F;
kadonotakashi 0:8fdf9a60065b 588 pdc_packet.addr_length=ADDR_LENGTH;
kadonotakashi 0:8fdf9a60065b 589
kadonotakashi 0:8fdf9a60065b 590 /* Set write mode, slave address and 3 internal address byte lengths */
kadonotakashi 0:8fdf9a60065b 591 obj->i2c.i2c_base->TWI_MMR = 0;
kadonotakashi 0:8fdf9a60065b 592 obj->i2c.i2c_base->TWI_MMR = TWI_MMR_DADR(pdc_packet.chip) |
kadonotakashi 0:8fdf9a60065b 593 ((pdc_packet.addr_length << TWI_MMR_IADRSZ_Pos) &
kadonotakashi 0:8fdf9a60065b 594 TWI_MMR_IADRSZ_Msk);
kadonotakashi 0:8fdf9a60065b 595 }
kadonotakashi 0:8fdf9a60065b 596
kadonotakashi 0:8fdf9a60065b 597 if(tx) {
kadonotakashi 0:8fdf9a60065b 598 pdc_packet_t pdc_packet_tx;
kadonotakashi 0:8fdf9a60065b 599 pdc_packet_tx.ul_addr=(uint32_t)tx;
kadonotakashi 0:8fdf9a60065b 600 pdc_packet_tx.ul_size=tx_length;
kadonotakashi 0:8fdf9a60065b 601
kadonotakashi 0:8fdf9a60065b 602 pdcenable|=PERIPH_PTCR_TXTEN;
kadonotakashi 0:8fdf9a60065b 603 /* Configure PDC for data send */
kadonotakashi 0:8fdf9a60065b 604 pdc_tx_init(obj->i2c.pdc, &pdc_packet_tx, NULL);
kadonotakashi 0:8fdf9a60065b 605 }
kadonotakashi 0:8fdf9a60065b 606
kadonotakashi 0:8fdf9a60065b 607 if(rx) {
kadonotakashi 0:8fdf9a60065b 608 obj->i2c.i2c_base->TWI_MMR |= TWI_MMR_MREAD;
kadonotakashi 0:8fdf9a60065b 609 pdc_rx_clear_cnt(obj->i2c.pdc);
kadonotakashi 0:8fdf9a60065b 610 pdc_packet_t pdc_packet_rx;
kadonotakashi 0:8fdf9a60065b 611 pdc_packet_rx.ul_addr=(uint32_t)rx;
kadonotakashi 0:8fdf9a60065b 612 pdc_packet_rx.ul_size=rx_length;
kadonotakashi 0:8fdf9a60065b 613 pdcenable|=PERIPH_PTCR_RXTEN;
kadonotakashi 0:8fdf9a60065b 614
kadonotakashi 0:8fdf9a60065b 615 /* Configure PDC for data receive */
kadonotakashi 0:8fdf9a60065b 616 pdc_rx_init(obj->i2c.pdc, &pdc_packet_rx, NULL);
kadonotakashi 0:8fdf9a60065b 617 }
kadonotakashi 0:8fdf9a60065b 618
kadonotakashi 0:8fdf9a60065b 619 obj->i2c.dma_usage=hint;
kadonotakashi 0:8fdf9a60065b 620 obj->i2c.event=event;
kadonotakashi 0:8fdf9a60065b 621 obj->i2c.stop=stop;
kadonotakashi 0:8fdf9a60065b 622 obj->i2c.address=address;
kadonotakashi 0:8fdf9a60065b 623
kadonotakashi 0:8fdf9a60065b 624 NVIC_ClearPendingIRQ(obj->i2c.irq_type);
kadonotakashi 0:8fdf9a60065b 625 NVIC_DisableIRQ(obj->i2c.irq_type);
kadonotakashi 0:8fdf9a60065b 626 NVIC_SetVector(obj->i2c.irq_type,handler);
kadonotakashi 0:8fdf9a60065b 627 NVIC_EnableIRQ(obj->i2c.irq_type);
kadonotakashi 0:8fdf9a60065b 628
kadonotakashi 0:8fdf9a60065b 629 /* Enable TWI IRQ */
kadonotakashi 0:8fdf9a60065b 630 twi_enable_interrupt(obj->i2c.i2c_base, TWI_IER_RXBUFF| TWI_IER_TXBUFE | TWI_IER_UNRE | TWI_IER_OVRE | TWI_IER_PECERR);
kadonotakashi 0:8fdf9a60065b 631
kadonotakashi 0:8fdf9a60065b 632 /* Enable PDC transfers */
kadonotakashi 0:8fdf9a60065b 633 pdc_enable_transfer(obj->i2c.pdc, pdcenable );
kadonotakashi 0:8fdf9a60065b 634
kadonotakashi 0:8fdf9a60065b 635 }
kadonotakashi 0:8fdf9a60065b 636
kadonotakashi 0:8fdf9a60065b 637 /** The asynchronous IRQ handler
kadonotakashi 0:8fdf9a60065b 638 * @param obj The I2C object which holds the transfer information
kadonotakashi 0:8fdf9a60065b 639 * @return event flags if a transfer termination condition was met or 0 otherwise.
kadonotakashi 0:8fdf9a60065b 640 */
kadonotakashi 0:8fdf9a60065b 641 uint32_t i2c_irq_handler_asynch(i2c_t *obj)
kadonotakashi 0:8fdf9a60065b 642 {
kadonotakashi 0:8fdf9a60065b 643 uint32_t event=0;
kadonotakashi 0:8fdf9a60065b 644
kadonotakashi 0:8fdf9a60065b 645 if(obj->i2c.stop) {
kadonotakashi 0:8fdf9a60065b 646 i2c_stop(obj);
kadonotakashi 0:8fdf9a60065b 647 }
kadonotakashi 0:8fdf9a60065b 648
kadonotakashi 0:8fdf9a60065b 649 // Data transferred via DMA
kadonotakashi 0:8fdf9a60065b 650 if((obj->i2c.i2c_base->TWI_SR & TWI_IER_TXBUFE)) {
kadonotakashi 0:8fdf9a60065b 651 twi_disable_interrupt(obj->i2c.i2c_base, TWI_IDR_TXBUFE | TWI_IDR_UNRE | TWI_IDR_OVRE | TWI_IDR_PECERR);
kadonotakashi 0:8fdf9a60065b 652 if(obj->i2c.event | I2C_EVENT_TRANSFER_COMPLETE)
kadonotakashi 0:8fdf9a60065b 653 event |=I2C_EVENT_TRANSFER_COMPLETE;
kadonotakashi 0:8fdf9a60065b 654 }
kadonotakashi 0:8fdf9a60065b 655
kadonotakashi 0:8fdf9a60065b 656 if((obj->i2c.i2c_base->TWI_SR & TWI_IER_RXBUFF)) {
kadonotakashi 0:8fdf9a60065b 657 twi_disable_interrupt(obj->i2c.i2c_base, TWI_IDR_RXBUFF | TWI_IDR_UNRE | TWI_IDR_OVRE | TWI_IDR_PECERR);
kadonotakashi 0:8fdf9a60065b 658 if(obj->i2c.event | I2C_EVENT_TRANSFER_COMPLETE)
kadonotakashi 0:8fdf9a60065b 659 event |=I2C_EVENT_TRANSFER_COMPLETE;
kadonotakashi 0:8fdf9a60065b 660 }
kadonotakashi 0:8fdf9a60065b 661
kadonotakashi 0:8fdf9a60065b 662 if(obj->i2c.i2c_base->TWI_SR & TWI_IER_NACK) {
kadonotakashi 0:8fdf9a60065b 663 if(obj->i2c.event | I2C_EVENT_TRANSFER_EARLY_NACK)
kadonotakashi 0:8fdf9a60065b 664 event |=I2C_EVENT_TRANSFER_EARLY_NACK;
kadonotakashi 0:8fdf9a60065b 665 }
kadonotakashi 0:8fdf9a60065b 666
kadonotakashi 0:8fdf9a60065b 667
kadonotakashi 0:8fdf9a60065b 668 if((obj->i2c.i2c_base->TWI_SR & TWI_IER_UNRE) || (obj->i2c.i2c_base->TWI_SR & TWI_IER_OVRE) || (obj->i2c.i2c_base->TWI_SR & TWI_IER_PECERR) || (obj->i2c.i2c_base->TWI_SR & TWI_SR_TOUT) ) {
kadonotakashi 0:8fdf9a60065b 669 if((obj->i2c.event | I2C_EVENT_ERROR))
kadonotakashi 0:8fdf9a60065b 670 event |=I2C_EVENT_ERROR;
kadonotakashi 0:8fdf9a60065b 671
kadonotakashi 0:8fdf9a60065b 672 if(obj->i2c.address) {
kadonotakashi 0:8fdf9a60065b 673 uint8_t status= twi_probe(obj->i2c.i2c_base,obj->i2c.address);
kadonotakashi 0:8fdf9a60065b 674 if((obj->i2c.event | I2C_EVENT_ERROR_NO_SLAVE) && (status!=TWI_SUCCESS) )
kadonotakashi 0:8fdf9a60065b 675 event |=I2C_EVENT_ERROR_NO_SLAVE;
kadonotakashi 0:8fdf9a60065b 676 }
kadonotakashi 0:8fdf9a60065b 677 }
kadonotakashi 0:8fdf9a60065b 678
kadonotakashi 0:8fdf9a60065b 679 return event;
kadonotakashi 0:8fdf9a60065b 680 }
kadonotakashi 0:8fdf9a60065b 681
kadonotakashi 0:8fdf9a60065b 682 /** Attempts to determine if I2C peripheral is already in use.
kadonotakashi 0:8fdf9a60065b 683 * @param obj The I2C object
kadonotakashi 0:8fdf9a60065b 684 * @return non-zero if the I2C module is active or zero if it is not
kadonotakashi 0:8fdf9a60065b 685 */
kadonotakashi 0:8fdf9a60065b 686 uint8_t i2c_active(i2c_t *obj)
kadonotakashi 0:8fdf9a60065b 687 {
kadonotakashi 0:8fdf9a60065b 688
kadonotakashi 0:8fdf9a60065b 689 if(obj->i2c.i2c_base->TWI_SR & TWI_SR_ENDTX && obj->i2c.i2c_base->TWI_SR & TWI_SR_ENDRX)
kadonotakashi 0:8fdf9a60065b 690 return 0;
kadonotakashi 0:8fdf9a60065b 691
kadonotakashi 0:8fdf9a60065b 692 return 1;
kadonotakashi 0:8fdf9a60065b 693
kadonotakashi 0:8fdf9a60065b 694 }
kadonotakashi 0:8fdf9a60065b 695
kadonotakashi 0:8fdf9a60065b 696 /** Abort ongoing asynchronous transaction.
kadonotakashi 0:8fdf9a60065b 697 * @param obj The I2C object
kadonotakashi 0:8fdf9a60065b 698 */
kadonotakashi 0:8fdf9a60065b 699 void i2c_abort_asynch(i2c_t *obj)
kadonotakashi 0:8fdf9a60065b 700 {
kadonotakashi 0:8fdf9a60065b 701 /* Disable PDC transfers */
kadonotakashi 0:8fdf9a60065b 702 pdc_disable_transfer(obj->i2c.pdc, PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS);
kadonotakashi 0:8fdf9a60065b 703
kadonotakashi 0:8fdf9a60065b 704 /* Clear PDC buffer receive counter */
kadonotakashi 0:8fdf9a60065b 705 pdc_rx_clear_cnt(obj->i2c.pdc);
kadonotakashi 0:8fdf9a60065b 706
kadonotakashi 0:8fdf9a60065b 707 /* Disable I2C IRQ */
kadonotakashi 0:8fdf9a60065b 708 twi_disable_interrupt(obj->i2c.i2c_base, TWI_IDR_TXBUFE);
kadonotakashi 0:8fdf9a60065b 709 twi_disable_interrupt(obj->i2c.i2c_base, TWI_IDR_RXBUFF);
kadonotakashi 0:8fdf9a60065b 710
kadonotakashi 0:8fdf9a60065b 711 /* Disable I2C interrupt */
kadonotakashi 0:8fdf9a60065b 712 NVIC_DisableIRQ(obj->i2c.irq_type);
kadonotakashi 0:8fdf9a60065b 713 }
kadonotakashi 0:8fdf9a60065b 714
kadonotakashi 0:8fdf9a60065b 715 #endif