Mouse code for the MacroRat

Dependencies:   ITG3200 QEI

Committer:
sahilmgandhi
Date:
Sat Jun 03 00:22:44 2017 +0000
Revision:
46:b156ef445742
Parent:
18:6a4db94011d3
Final code for internal battlebot competition.

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-2013 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 "i2c_api.h"
sahilmgandhi 18:6a4db94011d3 17 #include "cmsis.h"
sahilmgandhi 18:6a4db94011d3 18 #include "pinmap.h"
sahilmgandhi 18:6a4db94011d3 19
sahilmgandhi 18:6a4db94011d3 20 #if DEVICE_I2C
sahilmgandhi 18:6a4db94011d3 21
sahilmgandhi 18:6a4db94011d3 22 static const SWM_Map SWM_I2C_SDA[] = {
sahilmgandhi 18:6a4db94011d3 23 {7, 24},
sahilmgandhi 18:6a4db94011d3 24 };
sahilmgandhi 18:6a4db94011d3 25
sahilmgandhi 18:6a4db94011d3 26 static const SWM_Map SWM_I2C_SCL[] = {
sahilmgandhi 18:6a4db94011d3 27 {8, 0},
sahilmgandhi 18:6a4db94011d3 28 };
sahilmgandhi 18:6a4db94011d3 29
sahilmgandhi 18:6a4db94011d3 30 static uint8_t repeated_start = 0;
sahilmgandhi 18:6a4db94011d3 31
sahilmgandhi 18:6a4db94011d3 32 #define I2C_DAT(x) (x->i2c->MSTDAT)
sahilmgandhi 18:6a4db94011d3 33 #define I2C_STAT(x) ((x->i2c->STAT >> 1) & (0x07))
sahilmgandhi 18:6a4db94011d3 34
sahilmgandhi 18:6a4db94011d3 35 static inline int i2c_status(i2c_t *obj) {
sahilmgandhi 18:6a4db94011d3 36 return I2C_STAT(obj);
sahilmgandhi 18:6a4db94011d3 37 }
sahilmgandhi 18:6a4db94011d3 38
sahilmgandhi 18:6a4db94011d3 39 // Wait until the Serial Interrupt (SI) is set
sahilmgandhi 18:6a4db94011d3 40 static int i2c_wait_SI(i2c_t *obj) {
sahilmgandhi 18:6a4db94011d3 41 int timeout = 0;
sahilmgandhi 18:6a4db94011d3 42 while (!(obj->i2c->STAT & (1 << 0))) {
sahilmgandhi 18:6a4db94011d3 43 timeout++;
sahilmgandhi 18:6a4db94011d3 44 if (timeout > 100000) return -1;
sahilmgandhi 18:6a4db94011d3 45 }
sahilmgandhi 18:6a4db94011d3 46 return 0;
sahilmgandhi 18:6a4db94011d3 47 }
sahilmgandhi 18:6a4db94011d3 48
sahilmgandhi 18:6a4db94011d3 49 static inline void i2c_interface_enable(i2c_t *obj) {
sahilmgandhi 18:6a4db94011d3 50 obj->i2c->CFG |= (1 << 0);
sahilmgandhi 18:6a4db94011d3 51 }
sahilmgandhi 18:6a4db94011d3 52
sahilmgandhi 18:6a4db94011d3 53 static inline void i2c_power_enable(i2c_t *obj) {
sahilmgandhi 18:6a4db94011d3 54 LPC_SYSCON->SYSAHBCLKCTRL |= (1<<5);
sahilmgandhi 18:6a4db94011d3 55 LPC_SYSCON->PRESETCTRL &= ~(0x1<<6);
sahilmgandhi 18:6a4db94011d3 56 LPC_SYSCON->PRESETCTRL |= (0x1<<6);
sahilmgandhi 18:6a4db94011d3 57 }
sahilmgandhi 18:6a4db94011d3 58
sahilmgandhi 18:6a4db94011d3 59 void i2c_init(i2c_t *obj, PinName sda, PinName scl) {
sahilmgandhi 18:6a4db94011d3 60 obj->i2c = (LPC_I2C_TypeDef *)LPC_I2C;
sahilmgandhi 18:6a4db94011d3 61
sahilmgandhi 18:6a4db94011d3 62 const SWM_Map *swm;
sahilmgandhi 18:6a4db94011d3 63 uint32_t regVal;
sahilmgandhi 18:6a4db94011d3 64
sahilmgandhi 18:6a4db94011d3 65 swm = &SWM_I2C_SDA[0];
sahilmgandhi 18:6a4db94011d3 66 regVal = LPC_SWM->PINASSIGN[swm->n] & ~(0xFF << swm->offset);
sahilmgandhi 18:6a4db94011d3 67 LPC_SWM->PINASSIGN[swm->n] = regVal | (sda << swm->offset);
sahilmgandhi 18:6a4db94011d3 68
sahilmgandhi 18:6a4db94011d3 69 swm = &SWM_I2C_SCL[0];
sahilmgandhi 18:6a4db94011d3 70 regVal = LPC_SWM->PINASSIGN[swm->n] & ~(0xFF << swm->offset);
sahilmgandhi 18:6a4db94011d3 71 LPC_SWM->PINASSIGN[swm->n] = regVal | (scl << swm->offset);
sahilmgandhi 18:6a4db94011d3 72
sahilmgandhi 18:6a4db94011d3 73 // enable power
sahilmgandhi 18:6a4db94011d3 74 i2c_power_enable(obj);
sahilmgandhi 18:6a4db94011d3 75 // set default frequency at 100k
sahilmgandhi 18:6a4db94011d3 76 i2c_frequency(obj, 100000);
sahilmgandhi 18:6a4db94011d3 77 i2c_interface_enable(obj);
sahilmgandhi 18:6a4db94011d3 78 }
sahilmgandhi 18:6a4db94011d3 79
sahilmgandhi 18:6a4db94011d3 80 //Actually Wrong. Spec says: First store Address in DAT before setting STA !
sahilmgandhi 18:6a4db94011d3 81 //Undefined state when using single byte I2C operations and too much delay
sahilmgandhi 18:6a4db94011d3 82 //between i2c_start and do_i2c_write(Address).
sahilmgandhi 18:6a4db94011d3 83 //Also note that lpc812 will immediately continue reading a byte when Address b0 == 1
sahilmgandhi 18:6a4db94011d3 84 inline int i2c_start(i2c_t *obj) {
sahilmgandhi 18:6a4db94011d3 85 int status = 0;
sahilmgandhi 18:6a4db94011d3 86 if (repeated_start) {
sahilmgandhi 18:6a4db94011d3 87 obj->i2c->MSTCTL = (1 << 1) | (1 << 0);
sahilmgandhi 18:6a4db94011d3 88 repeated_start = 0;
sahilmgandhi 18:6a4db94011d3 89 } else {
sahilmgandhi 18:6a4db94011d3 90 obj->i2c->MSTCTL = (1 << 1);
sahilmgandhi 18:6a4db94011d3 91 }
sahilmgandhi 18:6a4db94011d3 92 return status;
sahilmgandhi 18:6a4db94011d3 93 }
sahilmgandhi 18:6a4db94011d3 94
sahilmgandhi 18:6a4db94011d3 95 //Generate Stop condition and wait until bus is Idle
sahilmgandhi 18:6a4db94011d3 96 //Will also send NAK for previous RD
sahilmgandhi 18:6a4db94011d3 97 inline int i2c_stop(i2c_t *obj) {
sahilmgandhi 18:6a4db94011d3 98 int timeout = 0;
sahilmgandhi 18:6a4db94011d3 99
sahilmgandhi 18:6a4db94011d3 100 obj->i2c->MSTCTL = (1 << 2) | (1 << 0); // STP bit and Continue bit. Sends NAK to complete previous RD
sahilmgandhi 18:6a4db94011d3 101
sahilmgandhi 18:6a4db94011d3 102 //Spin until Ready (b0 == 1)and Status is Idle (b3..b1 == 000)
sahilmgandhi 18:6a4db94011d3 103 while ((obj->i2c->STAT & ((7 << 1) | (1 << 0))) != ((0 << 1) | (1 << 0))) {
sahilmgandhi 18:6a4db94011d3 104 timeout ++;
sahilmgandhi 18:6a4db94011d3 105 if (timeout > 100000) return 1;
sahilmgandhi 18:6a4db94011d3 106 }
sahilmgandhi 18:6a4db94011d3 107
sahilmgandhi 18:6a4db94011d3 108 return 0;
sahilmgandhi 18:6a4db94011d3 109 }
sahilmgandhi 18:6a4db94011d3 110
sahilmgandhi 18:6a4db94011d3 111 static inline int i2c_do_write(i2c_t *obj, int value, uint8_t addr) {
sahilmgandhi 18:6a4db94011d3 112 // write the data
sahilmgandhi 18:6a4db94011d3 113 I2C_DAT(obj) = value;
sahilmgandhi 18:6a4db94011d3 114
sahilmgandhi 18:6a4db94011d3 115 if (!addr)
sahilmgandhi 18:6a4db94011d3 116 obj->i2c->MSTCTL = (1 << 0);
sahilmgandhi 18:6a4db94011d3 117
sahilmgandhi 18:6a4db94011d3 118 // wait and return status
sahilmgandhi 18:6a4db94011d3 119 i2c_wait_SI(obj);
sahilmgandhi 18:6a4db94011d3 120 return i2c_status(obj);
sahilmgandhi 18:6a4db94011d3 121 }
sahilmgandhi 18:6a4db94011d3 122
sahilmgandhi 18:6a4db94011d3 123 static inline int i2c_do_read(i2c_t *obj, int last) {
sahilmgandhi 18:6a4db94011d3 124 // wait for it to arrive
sahilmgandhi 18:6a4db94011d3 125 i2c_wait_SI(obj);
sahilmgandhi 18:6a4db94011d3 126 if (!last)
sahilmgandhi 18:6a4db94011d3 127 obj->i2c->MSTCTL = (1 << 0);
sahilmgandhi 18:6a4db94011d3 128
sahilmgandhi 18:6a4db94011d3 129 // return the data
sahilmgandhi 18:6a4db94011d3 130 return (I2C_DAT(obj) & 0xFF);
sahilmgandhi 18:6a4db94011d3 131 }
sahilmgandhi 18:6a4db94011d3 132
sahilmgandhi 18:6a4db94011d3 133 void i2c_frequency(i2c_t *obj, int hz) {
sahilmgandhi 18:6a4db94011d3 134 // No peripheral clock divider on the M0
sahilmgandhi 18:6a4db94011d3 135 uint32_t PCLK = SystemCoreClock;
sahilmgandhi 18:6a4db94011d3 136
sahilmgandhi 18:6a4db94011d3 137 uint32_t clkdiv = PCLK / (hz * 4) - 1;
sahilmgandhi 18:6a4db94011d3 138
sahilmgandhi 18:6a4db94011d3 139 obj->i2c->DIV = clkdiv;
sahilmgandhi 18:6a4db94011d3 140 obj->i2c->MSTTIME = 0;
sahilmgandhi 18:6a4db94011d3 141 }
sahilmgandhi 18:6a4db94011d3 142
sahilmgandhi 18:6a4db94011d3 143 // The I2C does a read or a write as a whole operation
sahilmgandhi 18:6a4db94011d3 144 // There are two types of error conditions it can encounter
sahilmgandhi 18:6a4db94011d3 145 // 1) it can not obtain the bus
sahilmgandhi 18:6a4db94011d3 146 // 2) it gets error responses at part of the transmission
sahilmgandhi 18:6a4db94011d3 147 //
sahilmgandhi 18:6a4db94011d3 148 // We tackle them as follows:
sahilmgandhi 18:6a4db94011d3 149 // 1) we retry until we get the bus. we could have a "timeout" if we can not get it
sahilmgandhi 18:6a4db94011d3 150 // which basically turns it in to a 2)
sahilmgandhi 18:6a4db94011d3 151 // 2) on error, we use the standard error mechanisms to report/debug
sahilmgandhi 18:6a4db94011d3 152 //
sahilmgandhi 18:6a4db94011d3 153 // Therefore an I2C transaction should always complete. If it doesn't it is usually
sahilmgandhi 18:6a4db94011d3 154 // because something is setup wrong (e.g. wiring), and we don't need to programatically
sahilmgandhi 18:6a4db94011d3 155 // check for that
sahilmgandhi 18:6a4db94011d3 156
sahilmgandhi 18:6a4db94011d3 157 //New version WH, Tested OK for Start and Repeated Start
sahilmgandhi 18:6a4db94011d3 158 //Old version was Wrong: Calls i2c_start without setting address, i2c_do_read continues before checking status, status check for wrong value
sahilmgandhi 18:6a4db94011d3 159 int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) {
sahilmgandhi 18:6a4db94011d3 160 int count, status;
sahilmgandhi 18:6a4db94011d3 161
sahilmgandhi 18:6a4db94011d3 162 //Store the address+RD and then generate STA
sahilmgandhi 18:6a4db94011d3 163 I2C_DAT(obj) = address | 0x01;
sahilmgandhi 18:6a4db94011d3 164 i2c_start(obj);
sahilmgandhi 18:6a4db94011d3 165
sahilmgandhi 18:6a4db94011d3 166 // Wait for completion of STA and Sending of SlaveAddress+RD and first Read byte
sahilmgandhi 18:6a4db94011d3 167 i2c_wait_SI(obj);
sahilmgandhi 18:6a4db94011d3 168 status = i2c_status(obj);
sahilmgandhi 18:6a4db94011d3 169 if (status == 0x03) { // NAK on SlaveAddress
sahilmgandhi 18:6a4db94011d3 170 i2c_stop(obj);
sahilmgandhi 18:6a4db94011d3 171 return I2C_ERROR_NO_SLAVE;
sahilmgandhi 18:6a4db94011d3 172 }
sahilmgandhi 18:6a4db94011d3 173
sahilmgandhi 18:6a4db94011d3 174 // Read in all except last byte
sahilmgandhi 18:6a4db94011d3 175 for (count = 0; count < (length-1); count++) {
sahilmgandhi 18:6a4db94011d3 176
sahilmgandhi 18:6a4db94011d3 177 // Wait for it to arrive, note that first byte read after address+RD is already waiting
sahilmgandhi 18:6a4db94011d3 178 i2c_wait_SI(obj);
sahilmgandhi 18:6a4db94011d3 179 status = i2c_status(obj);
sahilmgandhi 18:6a4db94011d3 180 if (status != 0x01) { // RX RDY
sahilmgandhi 18:6a4db94011d3 181 i2c_stop(obj);
sahilmgandhi 18:6a4db94011d3 182 return count;
sahilmgandhi 18:6a4db94011d3 183 }
sahilmgandhi 18:6a4db94011d3 184 data[count] = I2C_DAT(obj) & 0xFF; // Store read byte
sahilmgandhi 18:6a4db94011d3 185
sahilmgandhi 18:6a4db94011d3 186 obj->i2c->MSTCTL = (1 << 0); // Send ACK and Continue to read
sahilmgandhi 18:6a4db94011d3 187 }
sahilmgandhi 18:6a4db94011d3 188
sahilmgandhi 18:6a4db94011d3 189 // Read final byte
sahilmgandhi 18:6a4db94011d3 190 // Wait for it to arrive
sahilmgandhi 18:6a4db94011d3 191 i2c_wait_SI(obj);
sahilmgandhi 18:6a4db94011d3 192
sahilmgandhi 18:6a4db94011d3 193 status = i2c_status(obj);
sahilmgandhi 18:6a4db94011d3 194 if (status != 0x01) { // RX RDY
sahilmgandhi 18:6a4db94011d3 195 i2c_stop(obj);
sahilmgandhi 18:6a4db94011d3 196 return count;
sahilmgandhi 18:6a4db94011d3 197 }
sahilmgandhi 18:6a4db94011d3 198 data[count] = I2C_DAT(obj) & 0xFF; // Store final read byte
sahilmgandhi 18:6a4db94011d3 199
sahilmgandhi 18:6a4db94011d3 200 // If not repeated start, send stop.
sahilmgandhi 18:6a4db94011d3 201 if (stop) {
sahilmgandhi 18:6a4db94011d3 202 i2c_stop(obj); // Also sends NAK for last read byte
sahilmgandhi 18:6a4db94011d3 203 } else {
sahilmgandhi 18:6a4db94011d3 204 repeated_start = 1;
sahilmgandhi 18:6a4db94011d3 205 }
sahilmgandhi 18:6a4db94011d3 206
sahilmgandhi 18:6a4db94011d3 207 return length;
sahilmgandhi 18:6a4db94011d3 208 }
sahilmgandhi 18:6a4db94011d3 209
sahilmgandhi 18:6a4db94011d3 210
sahilmgandhi 18:6a4db94011d3 211
sahilmgandhi 18:6a4db94011d3 212 //New version WH, Tested OK for Start and Repeated Start
sahilmgandhi 18:6a4db94011d3 213 //Old version was Wrong: Calls i2c_start without setting address first
sahilmgandhi 18:6a4db94011d3 214 int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop) {
sahilmgandhi 18:6a4db94011d3 215 int i, status;
sahilmgandhi 18:6a4db94011d3 216
sahilmgandhi 18:6a4db94011d3 217 //Store the address+/WR and then generate STA
sahilmgandhi 18:6a4db94011d3 218 I2C_DAT(obj) = address & 0xFE;
sahilmgandhi 18:6a4db94011d3 219 i2c_start(obj);
sahilmgandhi 18:6a4db94011d3 220
sahilmgandhi 18:6a4db94011d3 221 // Wait for completion of STA and Sending of SlaveAddress+/WR
sahilmgandhi 18:6a4db94011d3 222 i2c_wait_SI(obj);
sahilmgandhi 18:6a4db94011d3 223 status = i2c_status(obj);
sahilmgandhi 18:6a4db94011d3 224 if (status == 0x03) { // NAK SlaveAddress
sahilmgandhi 18:6a4db94011d3 225 i2c_stop(obj);
sahilmgandhi 18:6a4db94011d3 226 return I2C_ERROR_NO_SLAVE;
sahilmgandhi 18:6a4db94011d3 227 }
sahilmgandhi 18:6a4db94011d3 228
sahilmgandhi 18:6a4db94011d3 229 //Write all bytes
sahilmgandhi 18:6a4db94011d3 230 for (i=0; i<length; i++) {
sahilmgandhi 18:6a4db94011d3 231 status = i2c_do_write(obj, data[i], 0);
sahilmgandhi 18:6a4db94011d3 232 if (status != 0x02) { // TX RDY. Handles a Slave NAK on datawrite
sahilmgandhi 18:6a4db94011d3 233 i2c_stop(obj);
sahilmgandhi 18:6a4db94011d3 234 return i;
sahilmgandhi 18:6a4db94011d3 235 }
sahilmgandhi 18:6a4db94011d3 236 }
sahilmgandhi 18:6a4db94011d3 237
sahilmgandhi 18:6a4db94011d3 238 // If not repeated start, send stop.
sahilmgandhi 18:6a4db94011d3 239 if (stop) {
sahilmgandhi 18:6a4db94011d3 240 i2c_stop(obj);
sahilmgandhi 18:6a4db94011d3 241 } else {
sahilmgandhi 18:6a4db94011d3 242 repeated_start = 1;
sahilmgandhi 18:6a4db94011d3 243 }
sahilmgandhi 18:6a4db94011d3 244
sahilmgandhi 18:6a4db94011d3 245 return length;
sahilmgandhi 18:6a4db94011d3 246 }
sahilmgandhi 18:6a4db94011d3 247
sahilmgandhi 18:6a4db94011d3 248
sahilmgandhi 18:6a4db94011d3 249
sahilmgandhi 18:6a4db94011d3 250 void i2c_reset(i2c_t *obj) {
sahilmgandhi 18:6a4db94011d3 251 i2c_stop(obj);
sahilmgandhi 18:6a4db94011d3 252 }
sahilmgandhi 18:6a4db94011d3 253
sahilmgandhi 18:6a4db94011d3 254 int i2c_byte_read(i2c_t *obj, int last) {
sahilmgandhi 18:6a4db94011d3 255 return (i2c_do_read(obj, last) & 0xFF);
sahilmgandhi 18:6a4db94011d3 256 }
sahilmgandhi 18:6a4db94011d3 257
sahilmgandhi 18:6a4db94011d3 258 int i2c_byte_write(i2c_t *obj, int data) {
sahilmgandhi 18:6a4db94011d3 259 int ack;
sahilmgandhi 18:6a4db94011d3 260 int status = i2c_do_write(obj, (data & 0xFF), 0);
sahilmgandhi 18:6a4db94011d3 261
sahilmgandhi 18:6a4db94011d3 262 switch(status) {
sahilmgandhi 18:6a4db94011d3 263 case 2:
sahilmgandhi 18:6a4db94011d3 264 ack = 1;
sahilmgandhi 18:6a4db94011d3 265 break;
sahilmgandhi 18:6a4db94011d3 266 default:
sahilmgandhi 18:6a4db94011d3 267 ack = 0;
sahilmgandhi 18:6a4db94011d3 268 break;
sahilmgandhi 18:6a4db94011d3 269 }
sahilmgandhi 18:6a4db94011d3 270
sahilmgandhi 18:6a4db94011d3 271 return ack;
sahilmgandhi 18:6a4db94011d3 272 }
sahilmgandhi 18:6a4db94011d3 273
sahilmgandhi 18:6a4db94011d3 274 #if DEVICE_I2CSLAVE
sahilmgandhi 18:6a4db94011d3 275
sahilmgandhi 18:6a4db94011d3 276 #define I2C_SLVDAT(x) (x->i2c->SLVDAT)
sahilmgandhi 18:6a4db94011d3 277 #define I2C_SLVSTAT(x) ((x->i2c->STAT >> 9) & (0x03))
sahilmgandhi 18:6a4db94011d3 278 #define I2C_SLVSI(x) ((x->i2c->STAT >> 8) & (0x01))
sahilmgandhi 18:6a4db94011d3 279 //#define I2C_SLVCNT(x) (x->i2c->SLVCTL = (1 << 0))
sahilmgandhi 18:6a4db94011d3 280 //#define I2C_SLVNAK(x) (x->i2c->SLVCTL = (1 << 1))
sahilmgandhi 18:6a4db94011d3 281
sahilmgandhi 18:6a4db94011d3 282 #if(0)
sahilmgandhi 18:6a4db94011d3 283 // Wait until the Slave Serial Interrupt (SI) is set
sahilmgandhi 18:6a4db94011d3 284 // Timeout when it takes too long.
sahilmgandhi 18:6a4db94011d3 285 static int i2c_wait_slave_SI(i2c_t *obj) {
sahilmgandhi 18:6a4db94011d3 286 int timeout = 0;
sahilmgandhi 18:6a4db94011d3 287 while (!(obj->i2c->STAT & (1 << 8))) {
sahilmgandhi 18:6a4db94011d3 288 timeout++;
sahilmgandhi 18:6a4db94011d3 289 if (timeout > 100000) return -1;
sahilmgandhi 18:6a4db94011d3 290 }
sahilmgandhi 18:6a4db94011d3 291 return 0;
sahilmgandhi 18:6a4db94011d3 292 }
sahilmgandhi 18:6a4db94011d3 293 #endif
sahilmgandhi 18:6a4db94011d3 294
sahilmgandhi 18:6a4db94011d3 295 void i2c_slave_mode(i2c_t *obj, int enable_slave) {
sahilmgandhi 18:6a4db94011d3 296
sahilmgandhi 18:6a4db94011d3 297 if (enable_slave) {
sahilmgandhi 18:6a4db94011d3 298 // obj->i2c->CFG &= ~(1 << 0); //Disable Master mode
sahilmgandhi 18:6a4db94011d3 299 obj->i2c->CFG |= (1 << 1); //Enable Slave mode
sahilmgandhi 18:6a4db94011d3 300 }
sahilmgandhi 18:6a4db94011d3 301 else {
sahilmgandhi 18:6a4db94011d3 302 // obj->i2c->CFG |= (1 << 0); //Enable Master mode
sahilmgandhi 18:6a4db94011d3 303 obj->i2c->CFG &= ~(1 << 1); //Disable Slave mode
sahilmgandhi 18:6a4db94011d3 304 }
sahilmgandhi 18:6a4db94011d3 305 }
sahilmgandhi 18:6a4db94011d3 306
sahilmgandhi 18:6a4db94011d3 307 // Wait for next I2C event and find out what is going on
sahilmgandhi 18:6a4db94011d3 308 //
sahilmgandhi 18:6a4db94011d3 309 int i2c_slave_receive(i2c_t *obj) {
sahilmgandhi 18:6a4db94011d3 310 int addr;
sahilmgandhi 18:6a4db94011d3 311
sahilmgandhi 18:6a4db94011d3 312 // Check if there is any data pending
sahilmgandhi 18:6a4db94011d3 313 if (! I2C_SLVSI(obj)) {
sahilmgandhi 18:6a4db94011d3 314 return 0; //NoData
sahilmgandhi 18:6a4db94011d3 315 };
sahilmgandhi 18:6a4db94011d3 316
sahilmgandhi 18:6a4db94011d3 317 // Check State
sahilmgandhi 18:6a4db94011d3 318 switch(I2C_SLVSTAT(obj)) {
sahilmgandhi 18:6a4db94011d3 319 case 0x0: // Slave address plus R/W received
sahilmgandhi 18:6a4db94011d3 320 // At least one of the four slave addresses has been matched by hardware.
sahilmgandhi 18:6a4db94011d3 321 // You can figure out which address by checking Slave address match Index in STAT register.
sahilmgandhi 18:6a4db94011d3 322
sahilmgandhi 18:6a4db94011d3 323 // Get the received address
sahilmgandhi 18:6a4db94011d3 324 addr = I2C_SLVDAT(obj) & 0xFF;
sahilmgandhi 18:6a4db94011d3 325 // Send ACK on address and Continue
sahilmgandhi 18:6a4db94011d3 326 obj->i2c->SLVCTL = (1 << 0);
sahilmgandhi 18:6a4db94011d3 327
sahilmgandhi 18:6a4db94011d3 328 if (addr == 0x00) {
sahilmgandhi 18:6a4db94011d3 329 return 2; //WriteGeneral
sahilmgandhi 18:6a4db94011d3 330 }
sahilmgandhi 18:6a4db94011d3 331 //check the RW bit
sahilmgandhi 18:6a4db94011d3 332 if ((addr & 0x01) == 0x01) {
sahilmgandhi 18:6a4db94011d3 333 return 1; //ReadAddressed
sahilmgandhi 18:6a4db94011d3 334 }
sahilmgandhi 18:6a4db94011d3 335 else {
sahilmgandhi 18:6a4db94011d3 336 return 3; //WriteAddressed
sahilmgandhi 18:6a4db94011d3 337 }
sahilmgandhi 18:6a4db94011d3 338 //break;
sahilmgandhi 18:6a4db94011d3 339
sahilmgandhi 18:6a4db94011d3 340 case 0x1: // Slave receive. Received data is available (Slave Receiver mode).
sahilmgandhi 18:6a4db94011d3 341 // Oops, should never get here...
sahilmgandhi 18:6a4db94011d3 342 obj->i2c->SLVCTL = (1 << 1); // Send NACK on received data, try to recover...
sahilmgandhi 18:6a4db94011d3 343 return 0; //NoData
sahilmgandhi 18:6a4db94011d3 344
sahilmgandhi 18:6a4db94011d3 345 case 0x2: // Slave transmit. Data can be transmitted (Slave Transmitter mode).
sahilmgandhi 18:6a4db94011d3 346 // Oops, should never get here...
sahilmgandhi 18:6a4db94011d3 347 I2C_SLVDAT(obj) = 0xFF; // Send dummy data for transmission
sahilmgandhi 18:6a4db94011d3 348 obj->i2c->SLVCTL = (1 << 0); // Continue and try to recover...
sahilmgandhi 18:6a4db94011d3 349 return 0; //NoData
sahilmgandhi 18:6a4db94011d3 350
sahilmgandhi 18:6a4db94011d3 351 case 0x3: // Reserved.
sahilmgandhi 18:6a4db94011d3 352 default: // Oops, should never get here...
sahilmgandhi 18:6a4db94011d3 353 obj->i2c->SLVCTL = (1 << 0); // Continue and try to recover...
sahilmgandhi 18:6a4db94011d3 354 return 0; //NoData
sahilmgandhi 18:6a4db94011d3 355 //break;
sahilmgandhi 18:6a4db94011d3 356 } //switch status
sahilmgandhi 18:6a4db94011d3 357 }
sahilmgandhi 18:6a4db94011d3 358
sahilmgandhi 18:6a4db94011d3 359 // The dedicated I2C Slave byte read and byte write functions need to be called
sahilmgandhi 18:6a4db94011d3 360 // from 'common' mbed I2CSlave API for devices that have separate Master and
sahilmgandhi 18:6a4db94011d3 361 // Slave engines such as the lpc812 and lpc1549.
sahilmgandhi 18:6a4db94011d3 362
sahilmgandhi 18:6a4db94011d3 363 //Called when Slave is addressed for Write, Slave will receive Data in polling mode
sahilmgandhi 18:6a4db94011d3 364 //Parameter last=1 means received byte will be NACKed.
sahilmgandhi 18:6a4db94011d3 365 int i2c_slave_byte_read(i2c_t *obj, int last) {
sahilmgandhi 18:6a4db94011d3 366 int data;
sahilmgandhi 18:6a4db94011d3 367
sahilmgandhi 18:6a4db94011d3 368 // Wait for data
sahilmgandhi 18:6a4db94011d3 369 while (!I2C_SLVSI(obj)); // Wait forever
sahilmgandhi 18:6a4db94011d3 370 //if (i2c_wait_slave_SI(obj) != 0) {return -2;} // Wait with timeout
sahilmgandhi 18:6a4db94011d3 371
sahilmgandhi 18:6a4db94011d3 372 // Dont bother to check State, were not returning it anyhow..
sahilmgandhi 18:6a4db94011d3 373 //if (I2C_SLVSTAT(obj)) == 0x01) {
sahilmgandhi 18:6a4db94011d3 374 // Slave receive. Received data is available (Slave Receiver mode).
sahilmgandhi 18:6a4db94011d3 375 //};
sahilmgandhi 18:6a4db94011d3 376
sahilmgandhi 18:6a4db94011d3 377 data = I2C_SLVDAT(obj) & 0xFF; // Get and store the received data
sahilmgandhi 18:6a4db94011d3 378 if (last) {
sahilmgandhi 18:6a4db94011d3 379 obj->i2c->SLVCTL = (1 << 1); // Send NACK on received data and Continue
sahilmgandhi 18:6a4db94011d3 380 }
sahilmgandhi 18:6a4db94011d3 381 else {
sahilmgandhi 18:6a4db94011d3 382 obj->i2c->SLVCTL = (1 << 0); // Send ACK on data and Continue to read
sahilmgandhi 18:6a4db94011d3 383 }
sahilmgandhi 18:6a4db94011d3 384
sahilmgandhi 18:6a4db94011d3 385 return data;
sahilmgandhi 18:6a4db94011d3 386 }
sahilmgandhi 18:6a4db94011d3 387
sahilmgandhi 18:6a4db94011d3 388
sahilmgandhi 18:6a4db94011d3 389 //Called when Slave is addressed for Read, Slave will send Data in polling mode
sahilmgandhi 18:6a4db94011d3 390 //
sahilmgandhi 18:6a4db94011d3 391 int i2c_slave_byte_write(i2c_t *obj, int data) {
sahilmgandhi 18:6a4db94011d3 392
sahilmgandhi 18:6a4db94011d3 393 // Wait until Ready
sahilmgandhi 18:6a4db94011d3 394 while (!I2C_SLVSI(obj)); // Wait forever
sahilmgandhi 18:6a4db94011d3 395 // if (i2c_wait_slave_SI(obj) != 0) {return -2;} // Wait with timeout
sahilmgandhi 18:6a4db94011d3 396
sahilmgandhi 18:6a4db94011d3 397 // Check State
sahilmgandhi 18:6a4db94011d3 398 switch(I2C_SLVSTAT(obj)) {
sahilmgandhi 18:6a4db94011d3 399 case 0x0: // Slave address plus R/W received
sahilmgandhi 18:6a4db94011d3 400 // At least one of the four slave addresses has been matched by hardware.
sahilmgandhi 18:6a4db94011d3 401 // You can figure out which address by checking Slave address match Index in STAT register.
sahilmgandhi 18:6a4db94011d3 402 // I2C Restart occurred
sahilmgandhi 18:6a4db94011d3 403 return -1;
sahilmgandhi 18:6a4db94011d3 404 //break;
sahilmgandhi 18:6a4db94011d3 405 case 0x1: // Slave receive. Received data is available (Slave Receiver mode).
sahilmgandhi 18:6a4db94011d3 406 // Should not get here...
sahilmgandhi 18:6a4db94011d3 407 return -2;
sahilmgandhi 18:6a4db94011d3 408 //break;
sahilmgandhi 18:6a4db94011d3 409 case 0x2: // Slave transmit. Data can be transmitted (Slave Transmitter mode).
sahilmgandhi 18:6a4db94011d3 410 I2C_SLVDAT(obj) = data & 0xFF; // Store the data for transmission
sahilmgandhi 18:6a4db94011d3 411 obj->i2c->SLVCTL = (1 << 0); // Continue to send
sahilmgandhi 18:6a4db94011d3 412
sahilmgandhi 18:6a4db94011d3 413 return 1;
sahilmgandhi 18:6a4db94011d3 414 //break;
sahilmgandhi 18:6a4db94011d3 415 case 0x3: // Reserved.
sahilmgandhi 18:6a4db94011d3 416 default:
sahilmgandhi 18:6a4db94011d3 417 // Should not get here...
sahilmgandhi 18:6a4db94011d3 418 return -3;
sahilmgandhi 18:6a4db94011d3 419 //break;
sahilmgandhi 18:6a4db94011d3 420 } // switch status
sahilmgandhi 18:6a4db94011d3 421 }
sahilmgandhi 18:6a4db94011d3 422
sahilmgandhi 18:6a4db94011d3 423
sahilmgandhi 18:6a4db94011d3 424 //Called when Slave is addressed for Write, Slave will receive Data in polling mode
sahilmgandhi 18:6a4db94011d3 425 //Parameter length (>=1) is the maximum allowable number of bytes. All bytes will be ACKed.
sahilmgandhi 18:6a4db94011d3 426 int i2c_slave_read(i2c_t *obj, char *data, int length) {
sahilmgandhi 18:6a4db94011d3 427 int count=0;
sahilmgandhi 18:6a4db94011d3 428
sahilmgandhi 18:6a4db94011d3 429 // Read and ACK all expected bytes
sahilmgandhi 18:6a4db94011d3 430 while (count < length) {
sahilmgandhi 18:6a4db94011d3 431 // Wait for data
sahilmgandhi 18:6a4db94011d3 432 while (!I2C_SLVSI(obj)); // Wait forever
sahilmgandhi 18:6a4db94011d3 433 // if (i2c_wait_slave_SI(obj) != 0) {return -2;} // Wait with timeout
sahilmgandhi 18:6a4db94011d3 434
sahilmgandhi 18:6a4db94011d3 435 // Check State
sahilmgandhi 18:6a4db94011d3 436 switch(I2C_SLVSTAT(obj)) {
sahilmgandhi 18:6a4db94011d3 437 case 0x0: // Slave address plus R/W received
sahilmgandhi 18:6a4db94011d3 438 // At least one of the four slave addresses has been matched by hardware.
sahilmgandhi 18:6a4db94011d3 439 // You can figure out which address by checking Slave address match Index in STAT register.
sahilmgandhi 18:6a4db94011d3 440 // I2C Restart occurred
sahilmgandhi 18:6a4db94011d3 441 return -1;
sahilmgandhi 18:6a4db94011d3 442 //break;
sahilmgandhi 18:6a4db94011d3 443
sahilmgandhi 18:6a4db94011d3 444 case 0x1: // Slave receive. Received data is available (Slave Receiver mode).
sahilmgandhi 18:6a4db94011d3 445 data[count] = I2C_SLVDAT(obj) & 0xFF; // Get and store the received data
sahilmgandhi 18:6a4db94011d3 446 obj->i2c->SLVCTL = (1 << 0); // Send ACK on data and Continue to read
sahilmgandhi 18:6a4db94011d3 447 break;
sahilmgandhi 18:6a4db94011d3 448
sahilmgandhi 18:6a4db94011d3 449 case 0x2: // Slave transmit. Data can be transmitted (Slave Transmitter mode).
sahilmgandhi 18:6a4db94011d3 450 case 0x3: // Reserved.
sahilmgandhi 18:6a4db94011d3 451 default: // Should never get here...
sahilmgandhi 18:6a4db94011d3 452 return -2;
sahilmgandhi 18:6a4db94011d3 453 //break;
sahilmgandhi 18:6a4db94011d3 454 } // switch status
sahilmgandhi 18:6a4db94011d3 455
sahilmgandhi 18:6a4db94011d3 456 count++;
sahilmgandhi 18:6a4db94011d3 457 } // for all bytes
sahilmgandhi 18:6a4db94011d3 458
sahilmgandhi 18:6a4db94011d3 459 return count; // Received the expected number of bytes
sahilmgandhi 18:6a4db94011d3 460 }
sahilmgandhi 18:6a4db94011d3 461
sahilmgandhi 18:6a4db94011d3 462
sahilmgandhi 18:6a4db94011d3 463 //Called when Slave is addressed for Read, Slave will send Data in polling mode
sahilmgandhi 18:6a4db94011d3 464 //Parameter length (>=1) is the maximum number of bytes. Exit when Slave byte is NACKed.
sahilmgandhi 18:6a4db94011d3 465 int i2c_slave_write(i2c_t *obj, const char *data, int length) {
sahilmgandhi 18:6a4db94011d3 466 int count;
sahilmgandhi 18:6a4db94011d3 467
sahilmgandhi 18:6a4db94011d3 468 // Send and all bytes or Exit on NAK
sahilmgandhi 18:6a4db94011d3 469 for (count=0; count < length; count++) {
sahilmgandhi 18:6a4db94011d3 470 // Wait until Ready for data
sahilmgandhi 18:6a4db94011d3 471 while (!I2C_SLVSI(obj)); // Wait forever
sahilmgandhi 18:6a4db94011d3 472 // if (i2c_wait_slave_SI(obj) != 0) {return -2;} // Wait with timeout
sahilmgandhi 18:6a4db94011d3 473
sahilmgandhi 18:6a4db94011d3 474 // Check State
sahilmgandhi 18:6a4db94011d3 475 switch(I2C_SLVSTAT(obj)) {
sahilmgandhi 18:6a4db94011d3 476 case 0x0: // Slave address plus R/W received
sahilmgandhi 18:6a4db94011d3 477 // At least one of the four slave addresses has been matched by hardware.
sahilmgandhi 18:6a4db94011d3 478 // You can figure out which address by checking Slave address match Index in STAT register.
sahilmgandhi 18:6a4db94011d3 479 // I2C Restart occurred
sahilmgandhi 18:6a4db94011d3 480 return -1;
sahilmgandhi 18:6a4db94011d3 481 //break;
sahilmgandhi 18:6a4db94011d3 482 case 0x1: // Slave receive. Received data is available (Slave Receiver mode).
sahilmgandhi 18:6a4db94011d3 483 // Should not get here...
sahilmgandhi 18:6a4db94011d3 484 return -2;
sahilmgandhi 18:6a4db94011d3 485 //break;
sahilmgandhi 18:6a4db94011d3 486 case 0x2: // Slave transmit. Data can be transmitted (Slave Transmitter mode).
sahilmgandhi 18:6a4db94011d3 487 I2C_SLVDAT(obj) = data[count] & 0xFF; // Store the data for transmission
sahilmgandhi 18:6a4db94011d3 488 obj->i2c->SLVCTL = (1 << 0); // Continue to send
sahilmgandhi 18:6a4db94011d3 489 break;
sahilmgandhi 18:6a4db94011d3 490 case 0x3: // Reserved.
sahilmgandhi 18:6a4db94011d3 491 default:
sahilmgandhi 18:6a4db94011d3 492 // Should not get here...
sahilmgandhi 18:6a4db94011d3 493 return -3;
sahilmgandhi 18:6a4db94011d3 494 //break;
sahilmgandhi 18:6a4db94011d3 495 } // switch status
sahilmgandhi 18:6a4db94011d3 496 } // for all bytes
sahilmgandhi 18:6a4db94011d3 497
sahilmgandhi 18:6a4db94011d3 498 return length; // Transmitted the max number of bytes
sahilmgandhi 18:6a4db94011d3 499 }
sahilmgandhi 18:6a4db94011d3 500
sahilmgandhi 18:6a4db94011d3 501
sahilmgandhi 18:6a4db94011d3 502 // Set the four slave addresses.
sahilmgandhi 18:6a4db94011d3 503 void i2c_slave_address(i2c_t *obj, int idx, uint32_t address, uint32_t mask) {
sahilmgandhi 18:6a4db94011d3 504 obj->i2c->SLVADR0 = (address & 0xFE); // Store address in address 0 register
sahilmgandhi 18:6a4db94011d3 505 obj->i2c->SLVADR1 = (0x00 & 0xFE); // Store general call write address in address 1 register
sahilmgandhi 18:6a4db94011d3 506 obj->i2c->SLVADR2 = (0x01); // Disable address 2 register
sahilmgandhi 18:6a4db94011d3 507 obj->i2c->SLVADR3 = (0x01); // Disable address 3 register
sahilmgandhi 18:6a4db94011d3 508 obj->i2c->SLVQUAL0 = (mask & 0xFE); // Qualifier mask for address 0 register. Any maskbit that is 1 will always be a match
sahilmgandhi 18:6a4db94011d3 509 }
sahilmgandhi 18:6a4db94011d3 510
sahilmgandhi 18:6a4db94011d3 511 #endif
sahilmgandhi 18:6a4db94011d3 512
sahilmgandhi 18:6a4db94011d3 513 #endif