Mouse code for the MacroRat

Dependencies:   ITG3200 QEI

Committer:
sahilmgandhi
Date:
Sun May 14 23:18:57 2017 +0000
Revision:
18:6a4db94011d3
Publishing again

Who changed what in which revision?

UserRevisionLine numberNew contents of line
sahilmgandhi 18:6a4db94011d3 1 /* mbed Microcontroller Library
sahilmgandhi 18:6a4db94011d3 2 * Copyright (c) 2006-2015 ARM Limited
sahilmgandhi 18:6a4db94011d3 3 *
sahilmgandhi 18:6a4db94011d3 4 * Licensed under the Apache License, Version 2.0 (the "License");
sahilmgandhi 18:6a4db94011d3 5 * you may not use this file except in compliance with the License.
sahilmgandhi 18:6a4db94011d3 6 * You may obtain a copy of the License at
sahilmgandhi 18:6a4db94011d3 7 *
sahilmgandhi 18:6a4db94011d3 8 * http://www.apache.org/licenses/LICENSE-2.0
sahilmgandhi 18:6a4db94011d3 9 *
sahilmgandhi 18:6a4db94011d3 10 * Unless required by applicable law or agreed to in writing, software
sahilmgandhi 18:6a4db94011d3 11 * distributed under the License is distributed on an "AS IS" BASIS,
sahilmgandhi 18:6a4db94011d3 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
sahilmgandhi 18:6a4db94011d3 13 * See the License for the specific language governing permissions and
sahilmgandhi 18:6a4db94011d3 14 * limitations under the License.
sahilmgandhi 18:6a4db94011d3 15 */
sahilmgandhi 18:6a4db94011d3 16 #include "mbed_assert.h"
sahilmgandhi 18:6a4db94011d3 17 #include "i2c_api.h"
sahilmgandhi 18:6a4db94011d3 18
sahilmgandhi 18:6a4db94011d3 19 #include "cmsis.h"
sahilmgandhi 18:6a4db94011d3 20 #include "pinmap.h"
sahilmgandhi 18:6a4db94011d3 21 #include "clk_freqs.h"
sahilmgandhi 18:6a4db94011d3 22 #include "PeripheralPins.h"
sahilmgandhi 18:6a4db94011d3 23
sahilmgandhi 18:6a4db94011d3 24 static const uint16_t ICR[0x40] = {
sahilmgandhi 18:6a4db94011d3 25 20, 22, 24, 26, 28,
sahilmgandhi 18:6a4db94011d3 26 30, 34, 40, 28, 32,
sahilmgandhi 18:6a4db94011d3 27 36, 40, 44, 48, 56,
sahilmgandhi 18:6a4db94011d3 28 68, 48, 56, 64, 72,
sahilmgandhi 18:6a4db94011d3 29 80, 88, 104, 128, 80,
sahilmgandhi 18:6a4db94011d3 30 96, 112, 128, 144, 160,
sahilmgandhi 18:6a4db94011d3 31 192, 240, 160, 192, 224,
sahilmgandhi 18:6a4db94011d3 32 256, 288, 320, 384, 480,
sahilmgandhi 18:6a4db94011d3 33 320, 384, 448, 512, 576,
sahilmgandhi 18:6a4db94011d3 34 640, 768, 960, 640, 768,
sahilmgandhi 18:6a4db94011d3 35 896, 1024, 1152, 1280, 1536,
sahilmgandhi 18:6a4db94011d3 36 1920, 1280, 1536, 1792, 2048,
sahilmgandhi 18:6a4db94011d3 37 2304, 2560, 3072, 3840
sahilmgandhi 18:6a4db94011d3 38 };
sahilmgandhi 18:6a4db94011d3 39
sahilmgandhi 18:6a4db94011d3 40
sahilmgandhi 18:6a4db94011d3 41 void i2c_init(i2c_t *obj, PinName sda, PinName scl) {
sahilmgandhi 18:6a4db94011d3 42 // determine the I2C to use
sahilmgandhi 18:6a4db94011d3 43 I2CName i2c_sda = (I2CName)pinmap_peripheral(sda, PinMap_I2C_SDA);
sahilmgandhi 18:6a4db94011d3 44 I2CName i2c_scl = (I2CName)pinmap_peripheral(scl, PinMap_I2C_SCL);
sahilmgandhi 18:6a4db94011d3 45 obj->i2c = (I2C_Type*)pinmap_merge(i2c_sda, i2c_scl);
sahilmgandhi 18:6a4db94011d3 46 MBED_ASSERT((int)obj->i2c != NC);
sahilmgandhi 18:6a4db94011d3 47
sahilmgandhi 18:6a4db94011d3 48 #if defined(TARGET_K20DX256)
sahilmgandhi 18:6a4db94011d3 49 switch ((int)obj->i2c) {
sahilmgandhi 18:6a4db94011d3 50 case I2C_0: SIM->SCGC4 |= SIM_SCGC4_I2C0_MASK;
sahilmgandhi 18:6a4db94011d3 51 case I2C_1: SIM->SCGC4 |= SIM_SCGC4_I2C1_MASK;
sahilmgandhi 18:6a4db94011d3 52 }
sahilmgandhi 18:6a4db94011d3 53 #else
sahilmgandhi 18:6a4db94011d3 54 SIM->SCGC4 |= SIM_SCGC4_I2C0_MASK;
sahilmgandhi 18:6a4db94011d3 55 #endif
sahilmgandhi 18:6a4db94011d3 56
sahilmgandhi 18:6a4db94011d3 57 // set default frequency at 100k
sahilmgandhi 18:6a4db94011d3 58 i2c_frequency(obj, 100000);
sahilmgandhi 18:6a4db94011d3 59
sahilmgandhi 18:6a4db94011d3 60 // enable I2C interface
sahilmgandhi 18:6a4db94011d3 61 obj->i2c->C1 |= 0x80;
sahilmgandhi 18:6a4db94011d3 62
sahilmgandhi 18:6a4db94011d3 63 pinmap_pinout(sda, PinMap_I2C_SDA);
sahilmgandhi 18:6a4db94011d3 64 pinmap_pinout(scl, PinMap_I2C_SCL);
sahilmgandhi 18:6a4db94011d3 65 /* enable open drain for I2C pins, only port b available */
sahilmgandhi 18:6a4db94011d3 66 uint32_t pin_n = (uint32_t)(sda & 0x7C) >> 2;
sahilmgandhi 18:6a4db94011d3 67 PORTB->PCR[pin_n] |= PORT_PCR_ODE_MASK;
sahilmgandhi 18:6a4db94011d3 68 pin_n = (uint32_t)(scl & 0x7C) >> 2;
sahilmgandhi 18:6a4db94011d3 69 PORTB->PCR[pin_n] |= PORT_PCR_ODE_MASK;
sahilmgandhi 18:6a4db94011d3 70 }
sahilmgandhi 18:6a4db94011d3 71
sahilmgandhi 18:6a4db94011d3 72 int i2c_start(i2c_t *obj) {
sahilmgandhi 18:6a4db94011d3 73 // if we are in the middle of a transaction
sahilmgandhi 18:6a4db94011d3 74 // activate the repeat_start flag
sahilmgandhi 18:6a4db94011d3 75 if (obj->i2c->S & I2C_S_BUSY_MASK) {
sahilmgandhi 18:6a4db94011d3 76 obj->i2c->C1 |= 0x04;
sahilmgandhi 18:6a4db94011d3 77 } else {
sahilmgandhi 18:6a4db94011d3 78 obj->i2c->C1 |= I2C_C1_MST_MASK;
sahilmgandhi 18:6a4db94011d3 79 obj->i2c->C1 |= I2C_C1_TX_MASK;
sahilmgandhi 18:6a4db94011d3 80 }
sahilmgandhi 18:6a4db94011d3 81 return 0;
sahilmgandhi 18:6a4db94011d3 82 }
sahilmgandhi 18:6a4db94011d3 83
sahilmgandhi 18:6a4db94011d3 84 int i2c_stop(i2c_t *obj) {
sahilmgandhi 18:6a4db94011d3 85 volatile uint32_t n = 0;
sahilmgandhi 18:6a4db94011d3 86 obj->i2c->C1 &= ~I2C_C1_MST_MASK;
sahilmgandhi 18:6a4db94011d3 87 obj->i2c->C1 &= ~I2C_C1_TX_MASK;
sahilmgandhi 18:6a4db94011d3 88 while(obj->i2c->S & I2C_S_BUSY_MASK);
sahilmgandhi 18:6a4db94011d3 89 return 0;
sahilmgandhi 18:6a4db94011d3 90 }
sahilmgandhi 18:6a4db94011d3 91
sahilmgandhi 18:6a4db94011d3 92 static int timeout_status_poll(i2c_t *obj, uint32_t mask) {
sahilmgandhi 18:6a4db94011d3 93 uint32_t i, timeout = 100000;
sahilmgandhi 18:6a4db94011d3 94
sahilmgandhi 18:6a4db94011d3 95 for (i = 0; i < timeout; i++) {
sahilmgandhi 18:6a4db94011d3 96 if (obj->i2c->S & mask)
sahilmgandhi 18:6a4db94011d3 97 return 0;
sahilmgandhi 18:6a4db94011d3 98 }
sahilmgandhi 18:6a4db94011d3 99
sahilmgandhi 18:6a4db94011d3 100 return 1;
sahilmgandhi 18:6a4db94011d3 101 }
sahilmgandhi 18:6a4db94011d3 102
sahilmgandhi 18:6a4db94011d3 103 // this function waits the end of a tx transfer and return the status of the transaction:
sahilmgandhi 18:6a4db94011d3 104 // 0: OK ack received
sahilmgandhi 18:6a4db94011d3 105 // 1: OK ack not received
sahilmgandhi 18:6a4db94011d3 106 // 2: failure
sahilmgandhi 18:6a4db94011d3 107 static int i2c_wait_end_tx_transfer(i2c_t *obj) {
sahilmgandhi 18:6a4db94011d3 108
sahilmgandhi 18:6a4db94011d3 109 // wait for the interrupt flag
sahilmgandhi 18:6a4db94011d3 110 if (timeout_status_poll(obj, I2C_S_IICIF_MASK)) {
sahilmgandhi 18:6a4db94011d3 111 return 2;
sahilmgandhi 18:6a4db94011d3 112 }
sahilmgandhi 18:6a4db94011d3 113
sahilmgandhi 18:6a4db94011d3 114 obj->i2c->S |= I2C_S_IICIF_MASK;
sahilmgandhi 18:6a4db94011d3 115
sahilmgandhi 18:6a4db94011d3 116 // wait transfer complete
sahilmgandhi 18:6a4db94011d3 117 if (timeout_status_poll(obj, I2C_S_TCF_MASK)) {
sahilmgandhi 18:6a4db94011d3 118 return 2;
sahilmgandhi 18:6a4db94011d3 119 }
sahilmgandhi 18:6a4db94011d3 120
sahilmgandhi 18:6a4db94011d3 121 // check if we received the ACK or not
sahilmgandhi 18:6a4db94011d3 122 return obj->i2c->S & I2C_S_RXAK_MASK ? 1 : 0;
sahilmgandhi 18:6a4db94011d3 123 }
sahilmgandhi 18:6a4db94011d3 124
sahilmgandhi 18:6a4db94011d3 125 // this function waits the end of a rx transfer and return the status of the transaction:
sahilmgandhi 18:6a4db94011d3 126 // 0: OK
sahilmgandhi 18:6a4db94011d3 127 // 1: failure
sahilmgandhi 18:6a4db94011d3 128 static int i2c_wait_end_rx_transfer(i2c_t *obj) {
sahilmgandhi 18:6a4db94011d3 129 // wait for the end of the rx transfer
sahilmgandhi 18:6a4db94011d3 130 if (timeout_status_poll(obj, I2C_S_IICIF_MASK)) {
sahilmgandhi 18:6a4db94011d3 131 return 1;
sahilmgandhi 18:6a4db94011d3 132 }
sahilmgandhi 18:6a4db94011d3 133
sahilmgandhi 18:6a4db94011d3 134 obj->i2c->S |= I2C_S_IICIF_MASK;
sahilmgandhi 18:6a4db94011d3 135
sahilmgandhi 18:6a4db94011d3 136 return 0;
sahilmgandhi 18:6a4db94011d3 137 }
sahilmgandhi 18:6a4db94011d3 138
sahilmgandhi 18:6a4db94011d3 139 static void i2c_send_nack(i2c_t *obj) {
sahilmgandhi 18:6a4db94011d3 140 obj->i2c->C1 |= I2C_C1_TXAK_MASK; // NACK
sahilmgandhi 18:6a4db94011d3 141 }
sahilmgandhi 18:6a4db94011d3 142
sahilmgandhi 18:6a4db94011d3 143 static void i2c_send_ack(i2c_t *obj) {
sahilmgandhi 18:6a4db94011d3 144 obj->i2c->C1 &= ~I2C_C1_TXAK_MASK; // ACK
sahilmgandhi 18:6a4db94011d3 145 }
sahilmgandhi 18:6a4db94011d3 146
sahilmgandhi 18:6a4db94011d3 147 static int i2c_do_write(i2c_t *obj, int value) {
sahilmgandhi 18:6a4db94011d3 148 // write the data
sahilmgandhi 18:6a4db94011d3 149 obj->i2c->D = value;
sahilmgandhi 18:6a4db94011d3 150
sahilmgandhi 18:6a4db94011d3 151 // init and wait the end of the transfer
sahilmgandhi 18:6a4db94011d3 152 return i2c_wait_end_tx_transfer(obj);
sahilmgandhi 18:6a4db94011d3 153 }
sahilmgandhi 18:6a4db94011d3 154
sahilmgandhi 18:6a4db94011d3 155 static int i2c_do_read(i2c_t *obj, char * data, int last) {
sahilmgandhi 18:6a4db94011d3 156 if (last) {
sahilmgandhi 18:6a4db94011d3 157 i2c_send_nack(obj);
sahilmgandhi 18:6a4db94011d3 158 } else {
sahilmgandhi 18:6a4db94011d3 159 i2c_send_ack(obj);
sahilmgandhi 18:6a4db94011d3 160 }
sahilmgandhi 18:6a4db94011d3 161
sahilmgandhi 18:6a4db94011d3 162 *data = (obj->i2c->D & 0xFF);
sahilmgandhi 18:6a4db94011d3 163
sahilmgandhi 18:6a4db94011d3 164 // start rx transfer and wait the end of the transfer
sahilmgandhi 18:6a4db94011d3 165 return i2c_wait_end_rx_transfer(obj);
sahilmgandhi 18:6a4db94011d3 166 }
sahilmgandhi 18:6a4db94011d3 167
sahilmgandhi 18:6a4db94011d3 168 void i2c_frequency(i2c_t *obj, int hz) {
sahilmgandhi 18:6a4db94011d3 169 uint8_t icr = 0;
sahilmgandhi 18:6a4db94011d3 170 uint8_t mult = 0;
sahilmgandhi 18:6a4db94011d3 171 uint32_t error = 0;
sahilmgandhi 18:6a4db94011d3 172 uint32_t p_error = 0xffffffff;
sahilmgandhi 18:6a4db94011d3 173 uint32_t ref = 0;
sahilmgandhi 18:6a4db94011d3 174 uint8_t i, j;
sahilmgandhi 18:6a4db94011d3 175 // bus clk
sahilmgandhi 18:6a4db94011d3 176 uint32_t PCLK = bus_frequency();
sahilmgandhi 18:6a4db94011d3 177 uint32_t pulse = PCLK / (hz * 2);
sahilmgandhi 18:6a4db94011d3 178
sahilmgandhi 18:6a4db94011d3 179 // we look for the values that minimize the error
sahilmgandhi 18:6a4db94011d3 180
sahilmgandhi 18:6a4db94011d3 181 // test all the MULT values
sahilmgandhi 18:6a4db94011d3 182 for (i = 1; i < 5; i*=2) {
sahilmgandhi 18:6a4db94011d3 183 for (j = 0; j < 0x40; j++) {
sahilmgandhi 18:6a4db94011d3 184 ref = PCLK / (i*ICR[j]);
sahilmgandhi 18:6a4db94011d3 185 if (ref > (uint32_t)hz)
sahilmgandhi 18:6a4db94011d3 186 continue;
sahilmgandhi 18:6a4db94011d3 187 error = hz - ref;
sahilmgandhi 18:6a4db94011d3 188 if (error < p_error) {
sahilmgandhi 18:6a4db94011d3 189 icr = j;
sahilmgandhi 18:6a4db94011d3 190 mult = i/2;
sahilmgandhi 18:6a4db94011d3 191 p_error = error;
sahilmgandhi 18:6a4db94011d3 192 }
sahilmgandhi 18:6a4db94011d3 193 }
sahilmgandhi 18:6a4db94011d3 194 }
sahilmgandhi 18:6a4db94011d3 195 pulse = icr | (mult << 6);
sahilmgandhi 18:6a4db94011d3 196
sahilmgandhi 18:6a4db94011d3 197 // I2C Rate
sahilmgandhi 18:6a4db94011d3 198 obj->i2c->F = pulse;
sahilmgandhi 18:6a4db94011d3 199 }
sahilmgandhi 18:6a4db94011d3 200
sahilmgandhi 18:6a4db94011d3 201 int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) {
sahilmgandhi 18:6a4db94011d3 202 int count;
sahilmgandhi 18:6a4db94011d3 203 char dummy_read, *ptr;
sahilmgandhi 18:6a4db94011d3 204
sahilmgandhi 18:6a4db94011d3 205 if (i2c_start(obj)) {
sahilmgandhi 18:6a4db94011d3 206 i2c_stop(obj);
sahilmgandhi 18:6a4db94011d3 207 return I2C_ERROR_BUS_BUSY;
sahilmgandhi 18:6a4db94011d3 208 }
sahilmgandhi 18:6a4db94011d3 209
sahilmgandhi 18:6a4db94011d3 210 if (i2c_do_write(obj, (address | 0x01))) {
sahilmgandhi 18:6a4db94011d3 211 i2c_stop(obj);
sahilmgandhi 18:6a4db94011d3 212 return I2C_ERROR_NO_SLAVE;
sahilmgandhi 18:6a4db94011d3 213 }
sahilmgandhi 18:6a4db94011d3 214
sahilmgandhi 18:6a4db94011d3 215 // set rx mode
sahilmgandhi 18:6a4db94011d3 216 obj->i2c->C1 &= ~I2C_C1_TX_MASK;
sahilmgandhi 18:6a4db94011d3 217
sahilmgandhi 18:6a4db94011d3 218 // Read in bytes
sahilmgandhi 18:6a4db94011d3 219 for (count = 0; count < (length); count++) {
sahilmgandhi 18:6a4db94011d3 220 ptr = (count == 0) ? &dummy_read : &data[count - 1];
sahilmgandhi 18:6a4db94011d3 221 uint8_t stop_ = (count == (length - 1)) ? 1 : 0;
sahilmgandhi 18:6a4db94011d3 222 if (i2c_do_read(obj, ptr, stop_)) {
sahilmgandhi 18:6a4db94011d3 223 i2c_stop(obj);
sahilmgandhi 18:6a4db94011d3 224 return count;
sahilmgandhi 18:6a4db94011d3 225 }
sahilmgandhi 18:6a4db94011d3 226 }
sahilmgandhi 18:6a4db94011d3 227
sahilmgandhi 18:6a4db94011d3 228 // If not repeated start, send stop.
sahilmgandhi 18:6a4db94011d3 229 if (stop)
sahilmgandhi 18:6a4db94011d3 230 i2c_stop(obj);
sahilmgandhi 18:6a4db94011d3 231
sahilmgandhi 18:6a4db94011d3 232 // last read
sahilmgandhi 18:6a4db94011d3 233 data[count-1] = obj->i2c->D;
sahilmgandhi 18:6a4db94011d3 234
sahilmgandhi 18:6a4db94011d3 235 return length;
sahilmgandhi 18:6a4db94011d3 236 }
sahilmgandhi 18:6a4db94011d3 237 int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop) {
sahilmgandhi 18:6a4db94011d3 238 int i;
sahilmgandhi 18:6a4db94011d3 239
sahilmgandhi 18:6a4db94011d3 240 if (i2c_start(obj)) {
sahilmgandhi 18:6a4db94011d3 241 i2c_stop(obj);
sahilmgandhi 18:6a4db94011d3 242 return I2C_ERROR_BUS_BUSY;
sahilmgandhi 18:6a4db94011d3 243 }
sahilmgandhi 18:6a4db94011d3 244
sahilmgandhi 18:6a4db94011d3 245 if (i2c_do_write(obj, (address & 0xFE))) {
sahilmgandhi 18:6a4db94011d3 246 i2c_stop(obj);
sahilmgandhi 18:6a4db94011d3 247 return I2C_ERROR_NO_SLAVE;
sahilmgandhi 18:6a4db94011d3 248 }
sahilmgandhi 18:6a4db94011d3 249
sahilmgandhi 18:6a4db94011d3 250 for (i = 0; i < length; i++) {
sahilmgandhi 18:6a4db94011d3 251 if(i2c_do_write(obj, data[i])) {
sahilmgandhi 18:6a4db94011d3 252 i2c_stop(obj);
sahilmgandhi 18:6a4db94011d3 253 return i;
sahilmgandhi 18:6a4db94011d3 254 }
sahilmgandhi 18:6a4db94011d3 255 }
sahilmgandhi 18:6a4db94011d3 256
sahilmgandhi 18:6a4db94011d3 257 if (stop)
sahilmgandhi 18:6a4db94011d3 258 i2c_stop(obj);
sahilmgandhi 18:6a4db94011d3 259
sahilmgandhi 18:6a4db94011d3 260 return length;
sahilmgandhi 18:6a4db94011d3 261 }
sahilmgandhi 18:6a4db94011d3 262
sahilmgandhi 18:6a4db94011d3 263 void i2c_reset(i2c_t *obj) {
sahilmgandhi 18:6a4db94011d3 264 i2c_stop(obj);
sahilmgandhi 18:6a4db94011d3 265 }
sahilmgandhi 18:6a4db94011d3 266
sahilmgandhi 18:6a4db94011d3 267 int i2c_byte_read(i2c_t *obj, int last) {
sahilmgandhi 18:6a4db94011d3 268 char data;
sahilmgandhi 18:6a4db94011d3 269
sahilmgandhi 18:6a4db94011d3 270 // set rx mode
sahilmgandhi 18:6a4db94011d3 271 obj->i2c->C1 &= ~I2C_C1_TX_MASK;
sahilmgandhi 18:6a4db94011d3 272
sahilmgandhi 18:6a4db94011d3 273 // Setup read
sahilmgandhi 18:6a4db94011d3 274 i2c_do_read(obj, &data, last);
sahilmgandhi 18:6a4db94011d3 275
sahilmgandhi 18:6a4db94011d3 276 // set tx mode
sahilmgandhi 18:6a4db94011d3 277 obj->i2c->C1 |= I2C_C1_TX_MASK;
sahilmgandhi 18:6a4db94011d3 278 return obj->i2c->D;
sahilmgandhi 18:6a4db94011d3 279 }
sahilmgandhi 18:6a4db94011d3 280
sahilmgandhi 18:6a4db94011d3 281 int i2c_byte_write(i2c_t *obj, int data) {
sahilmgandhi 18:6a4db94011d3 282 // set tx mode
sahilmgandhi 18:6a4db94011d3 283 obj->i2c->C1 |= I2C_C1_TX_MASK;
sahilmgandhi 18:6a4db94011d3 284
sahilmgandhi 18:6a4db94011d3 285 return !i2c_do_write(obj, (data & 0xFF));
sahilmgandhi 18:6a4db94011d3 286 }
sahilmgandhi 18:6a4db94011d3 287
sahilmgandhi 18:6a4db94011d3 288
sahilmgandhi 18:6a4db94011d3 289 #if DEVICE_I2CSLAVE
sahilmgandhi 18:6a4db94011d3 290 void i2c_slave_mode(i2c_t *obj, int enable_slave) {
sahilmgandhi 18:6a4db94011d3 291 if (enable_slave) {
sahilmgandhi 18:6a4db94011d3 292 // set slave mode
sahilmgandhi 18:6a4db94011d3 293 obj->i2c->C1 &= ~I2C_C1_MST_MASK;
sahilmgandhi 18:6a4db94011d3 294 obj->i2c->C1 |= I2C_C1_IICIE_MASK;
sahilmgandhi 18:6a4db94011d3 295 } else {
sahilmgandhi 18:6a4db94011d3 296 // set master mode
sahilmgandhi 18:6a4db94011d3 297 obj->i2c->C1 |= I2C_C1_MST_MASK;
sahilmgandhi 18:6a4db94011d3 298 }
sahilmgandhi 18:6a4db94011d3 299 }
sahilmgandhi 18:6a4db94011d3 300
sahilmgandhi 18:6a4db94011d3 301 int i2c_slave_receive(i2c_t *obj) {
sahilmgandhi 18:6a4db94011d3 302 switch(obj->i2c->S) {
sahilmgandhi 18:6a4db94011d3 303 // read addressed
sahilmgandhi 18:6a4db94011d3 304 case 0xE6:
sahilmgandhi 18:6a4db94011d3 305 return 1;
sahilmgandhi 18:6a4db94011d3 306 // write addressed
sahilmgandhi 18:6a4db94011d3 307 case 0xE2:
sahilmgandhi 18:6a4db94011d3 308 return 3;
sahilmgandhi 18:6a4db94011d3 309 default:
sahilmgandhi 18:6a4db94011d3 310 return 0;
sahilmgandhi 18:6a4db94011d3 311 }
sahilmgandhi 18:6a4db94011d3 312 }
sahilmgandhi 18:6a4db94011d3 313
sahilmgandhi 18:6a4db94011d3 314 int i2c_slave_read(i2c_t *obj, char *data, int length) {
sahilmgandhi 18:6a4db94011d3 315 uint8_t dummy_read;
sahilmgandhi 18:6a4db94011d3 316 uint8_t * ptr;
sahilmgandhi 18:6a4db94011d3 317 int count;
sahilmgandhi 18:6a4db94011d3 318
sahilmgandhi 18:6a4db94011d3 319 // set rx mode
sahilmgandhi 18:6a4db94011d3 320 obj->i2c->C1 &= ~I2C_C1_TX_MASK;
sahilmgandhi 18:6a4db94011d3 321
sahilmgandhi 18:6a4db94011d3 322 // first dummy read
sahilmgandhi 18:6a4db94011d3 323 dummy_read = obj->i2c->D;
sahilmgandhi 18:6a4db94011d3 324 if (i2c_wait_end_rx_transfer(obj))
sahilmgandhi 18:6a4db94011d3 325 return 0;
sahilmgandhi 18:6a4db94011d3 326
sahilmgandhi 18:6a4db94011d3 327 // read address
sahilmgandhi 18:6a4db94011d3 328 dummy_read = obj->i2c->D;
sahilmgandhi 18:6a4db94011d3 329 if (i2c_wait_end_rx_transfer(obj))
sahilmgandhi 18:6a4db94011d3 330 return 0;
sahilmgandhi 18:6a4db94011d3 331
sahilmgandhi 18:6a4db94011d3 332 // read (length - 1) bytes
sahilmgandhi 18:6a4db94011d3 333 for (count = 0; count < (length - 1); count++) {
sahilmgandhi 18:6a4db94011d3 334 data[count] = obj->i2c->D;
sahilmgandhi 18:6a4db94011d3 335 if (i2c_wait_end_rx_transfer(obj))
sahilmgandhi 18:6a4db94011d3 336 return count;
sahilmgandhi 18:6a4db94011d3 337 }
sahilmgandhi 18:6a4db94011d3 338
sahilmgandhi 18:6a4db94011d3 339 // read last byte
sahilmgandhi 18:6a4db94011d3 340 ptr = (length == 0) ? &dummy_read : (uint8_t *)&data[count];
sahilmgandhi 18:6a4db94011d3 341 *ptr = obj->i2c->D;
sahilmgandhi 18:6a4db94011d3 342
sahilmgandhi 18:6a4db94011d3 343 return (length) ? (count + 1) : 0;
sahilmgandhi 18:6a4db94011d3 344 }
sahilmgandhi 18:6a4db94011d3 345
sahilmgandhi 18:6a4db94011d3 346 int i2c_slave_write(i2c_t *obj, const char *data, int length) {
sahilmgandhi 18:6a4db94011d3 347 int i, count = 0;
sahilmgandhi 18:6a4db94011d3 348
sahilmgandhi 18:6a4db94011d3 349 // set tx mode
sahilmgandhi 18:6a4db94011d3 350 obj->i2c->C1 |= I2C_C1_TX_MASK;
sahilmgandhi 18:6a4db94011d3 351
sahilmgandhi 18:6a4db94011d3 352 for (i = 0; i < length; i++) {
sahilmgandhi 18:6a4db94011d3 353 if (i2c_do_write(obj, data[count++]) == 2)
sahilmgandhi 18:6a4db94011d3 354 return i;
sahilmgandhi 18:6a4db94011d3 355 }
sahilmgandhi 18:6a4db94011d3 356
sahilmgandhi 18:6a4db94011d3 357 // set rx mode
sahilmgandhi 18:6a4db94011d3 358 obj->i2c->C1 &= ~I2C_C1_TX_MASK;
sahilmgandhi 18:6a4db94011d3 359
sahilmgandhi 18:6a4db94011d3 360 // dummy rx transfer needed
sahilmgandhi 18:6a4db94011d3 361 // otherwise the master cannot generate a stop bit
sahilmgandhi 18:6a4db94011d3 362 obj->i2c->D;
sahilmgandhi 18:6a4db94011d3 363 if (i2c_wait_end_rx_transfer(obj) == 2)
sahilmgandhi 18:6a4db94011d3 364 return count;
sahilmgandhi 18:6a4db94011d3 365
sahilmgandhi 18:6a4db94011d3 366 return count;
sahilmgandhi 18:6a4db94011d3 367 }
sahilmgandhi 18:6a4db94011d3 368
sahilmgandhi 18:6a4db94011d3 369 void i2c_slave_address(i2c_t *obj, int idx, uint32_t address, uint32_t mask) {
sahilmgandhi 18:6a4db94011d3 370 obj->i2c->A1 = address & 0xfe;
sahilmgandhi 18:6a4db94011d3 371 }
sahilmgandhi 18:6a4db94011d3 372 #endif