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_NXP/TARGET_LPC82X/i2c_api.c@149:156823d33999, 2016-10-28 (annotated)
- Committer:
- <>
- Date:
- Fri Oct 28 11:17:30 2016 +0100
- Revision:
- 149:156823d33999
- Parent:
- targets/hal/TARGET_NXP/TARGET_LPC82X/i2c_api.c@144:ef7eb2e8f9f7
This updates the lib to the mbed lib v128
NOTE: This release includes a restructuring of the file and directory locations and thus some
include paths in your code may need updating accordingly.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
<> | 144:ef7eb2e8f9f7 | 1 | /* mbed Microcontroller Library |
<> | 144:ef7eb2e8f9f7 | 2 | * Copyright (c) 2006-2013 ARM Limited |
<> | 144:ef7eb2e8f9f7 | 3 | * |
<> | 144:ef7eb2e8f9f7 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
<> | 144:ef7eb2e8f9f7 | 5 | * you may not use this file except in compliance with the License. |
<> | 144:ef7eb2e8f9f7 | 6 | * You may obtain a copy of the License at |
<> | 144:ef7eb2e8f9f7 | 7 | * |
<> | 144:ef7eb2e8f9f7 | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
<> | 144:ef7eb2e8f9f7 | 9 | * |
<> | 144:ef7eb2e8f9f7 | 10 | * Unless required by applicable law or agreed to in writing, software |
<> | 144:ef7eb2e8f9f7 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
<> | 144:ef7eb2e8f9f7 | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
<> | 144:ef7eb2e8f9f7 | 13 | * See the License for the specific language governing permissions and |
<> | 144:ef7eb2e8f9f7 | 14 | * limitations under the License. |
<> | 144:ef7eb2e8f9f7 | 15 | */ |
<> | 144:ef7eb2e8f9f7 | 16 | #include <stdlib.h> |
<> | 144:ef7eb2e8f9f7 | 17 | #include <string.h> |
<> | 144:ef7eb2e8f9f7 | 18 | |
<> | 144:ef7eb2e8f9f7 | 19 | #include "i2c_api.h" |
<> | 144:ef7eb2e8f9f7 | 20 | #include "cmsis.h" |
<> | 144:ef7eb2e8f9f7 | 21 | #include "pinmap.h" |
<> | 144:ef7eb2e8f9f7 | 22 | |
<> | 144:ef7eb2e8f9f7 | 23 | #define LPC824_I2C0_FMPLUS 1 |
<> | 144:ef7eb2e8f9f7 | 24 | |
<> | 144:ef7eb2e8f9f7 | 25 | #if DEVICE_I2C |
<> | 144:ef7eb2e8f9f7 | 26 | |
<> | 144:ef7eb2e8f9f7 | 27 | static const SWM_Map SWM_I2C_SDA[] = { |
<> | 144:ef7eb2e8f9f7 | 28 | //PINASSIGN Register ID, Pinselect bitfield position |
<> | 144:ef7eb2e8f9f7 | 29 | { 9, 8}, |
<> | 144:ef7eb2e8f9f7 | 30 | { 9, 24}, |
<> | 144:ef7eb2e8f9f7 | 31 | {10, 8}, |
<> | 144:ef7eb2e8f9f7 | 32 | }; |
<> | 144:ef7eb2e8f9f7 | 33 | |
<> | 144:ef7eb2e8f9f7 | 34 | static const SWM_Map SWM_I2C_SCL[] = { |
<> | 144:ef7eb2e8f9f7 | 35 | //PINASSIGN Register ID, Pinselect bitfield position |
<> | 144:ef7eb2e8f9f7 | 36 | { 9, 16}, |
<> | 144:ef7eb2e8f9f7 | 37 | {10, 0}, |
<> | 144:ef7eb2e8f9f7 | 38 | {10, 16}, |
<> | 144:ef7eb2e8f9f7 | 39 | }; |
<> | 144:ef7eb2e8f9f7 | 40 | |
<> | 144:ef7eb2e8f9f7 | 41 | |
<> | 144:ef7eb2e8f9f7 | 42 | static int i2c_used = 0; |
<> | 144:ef7eb2e8f9f7 | 43 | static uint8_t repeated_start = 0; |
<> | 144:ef7eb2e8f9f7 | 44 | |
<> | 144:ef7eb2e8f9f7 | 45 | #define I2C_DAT(x) (x->i2c->MSTDAT) |
<> | 144:ef7eb2e8f9f7 | 46 | #define I2C_STAT(x) ((x->i2c->STAT >> 1) & (0x07)) |
<> | 144:ef7eb2e8f9f7 | 47 | |
<> | 144:ef7eb2e8f9f7 | 48 | static inline void i2c_power_enable(int ch) |
<> | 144:ef7eb2e8f9f7 | 49 | { |
<> | 144:ef7eb2e8f9f7 | 50 | switch(ch) { |
<> | 144:ef7eb2e8f9f7 | 51 | case 0: |
<> | 144:ef7eb2e8f9f7 | 52 | // I2C0, Same as for LPC812 |
<> | 144:ef7eb2e8f9f7 | 53 | LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 5); |
<> | 144:ef7eb2e8f9f7 | 54 | LPC_SYSCON->PRESETCTRL &= ~(1 << 6); |
<> | 144:ef7eb2e8f9f7 | 55 | LPC_SYSCON->PRESETCTRL |= (1 << 6); |
<> | 144:ef7eb2e8f9f7 | 56 | break; |
<> | 144:ef7eb2e8f9f7 | 57 | case 1: |
<> | 144:ef7eb2e8f9f7 | 58 | case 2: |
<> | 144:ef7eb2e8f9f7 | 59 | case 3: |
<> | 144:ef7eb2e8f9f7 | 60 | // I2C1,I2C2 or I2C3. Not available for LPC812 |
<> | 144:ef7eb2e8f9f7 | 61 | LPC_SYSCON->SYSAHBCLKCTRL |= (1 << (20 + ch)); |
<> | 144:ef7eb2e8f9f7 | 62 | LPC_SYSCON->PRESETCTRL &= ~(1 << (13 + ch)); |
<> | 144:ef7eb2e8f9f7 | 63 | LPC_SYSCON->PRESETCTRL |= (1 << (13 + ch)); |
<> | 144:ef7eb2e8f9f7 | 64 | break; |
<> | 144:ef7eb2e8f9f7 | 65 | default: |
<> | 144:ef7eb2e8f9f7 | 66 | break; |
<> | 144:ef7eb2e8f9f7 | 67 | } |
<> | 144:ef7eb2e8f9f7 | 68 | } |
<> | 144:ef7eb2e8f9f7 | 69 | |
<> | 144:ef7eb2e8f9f7 | 70 | |
<> | 144:ef7eb2e8f9f7 | 71 | static inline void i2c_interface_enable(i2c_t *obj) { |
<> | 144:ef7eb2e8f9f7 | 72 | obj->i2c->CFG |= (1 << 0); // Enable Master mode |
<> | 144:ef7eb2e8f9f7 | 73 | // obj->i2c->CFG &= ~(1 << 1); // Disable Slave mode |
<> | 144:ef7eb2e8f9f7 | 74 | } |
<> | 144:ef7eb2e8f9f7 | 75 | |
<> | 144:ef7eb2e8f9f7 | 76 | |
<> | 144:ef7eb2e8f9f7 | 77 | static int get_available_i2c(void) { |
<> | 144:ef7eb2e8f9f7 | 78 | int i; |
<> | 144:ef7eb2e8f9f7 | 79 | for (i=0; i<3; i++) { |
<> | 144:ef7eb2e8f9f7 | 80 | if ((i2c_used & (1 << i)) == 0) |
<> | 144:ef7eb2e8f9f7 | 81 | return i+1; |
<> | 144:ef7eb2e8f9f7 | 82 | } |
<> | 144:ef7eb2e8f9f7 | 83 | return -1; |
<> | 144:ef7eb2e8f9f7 | 84 | } |
<> | 144:ef7eb2e8f9f7 | 85 | |
<> | 144:ef7eb2e8f9f7 | 86 | void i2c_init(i2c_t *obj, PinName sda, PinName scl) |
<> | 144:ef7eb2e8f9f7 | 87 | { |
<> | 144:ef7eb2e8f9f7 | 88 | const SWM_Map *swm; |
<> | 144:ef7eb2e8f9f7 | 89 | uint32_t regVal; |
<> | 144:ef7eb2e8f9f7 | 90 | int i2c_ch = 0; |
<> | 144:ef7eb2e8f9f7 | 91 | |
<> | 144:ef7eb2e8f9f7 | 92 | //LPC824 |
<> | 144:ef7eb2e8f9f7 | 93 | //I2C0 can support FM+ but only on P0_11 and P0_10 |
<> | 144:ef7eb2e8f9f7 | 94 | if (sda == I2C_SDA && scl == I2C_SCL) { |
<> | 144:ef7eb2e8f9f7 | 95 | //Select I2C mode for P0_11 and P0_10 |
<> | 144:ef7eb2e8f9f7 | 96 | LPC_SWM->PINENABLE0 &= ~(0x3 << 11); |
<> | 144:ef7eb2e8f9f7 | 97 | |
<> | 144:ef7eb2e8f9f7 | 98 | #if(LPC824_I2C0_FMPLUS == 1) |
<> | 144:ef7eb2e8f9f7 | 99 | // Enable FM+ mode on P0_11, P0_10 |
<> | 144:ef7eb2e8f9f7 | 100 | LPC_IOCON->PIO0_10 &= ~(0x3 << 8); |
<> | 144:ef7eb2e8f9f7 | 101 | LPC_IOCON->PIO0_10 |= (0x2 << 8); //FM+ mode |
<> | 144:ef7eb2e8f9f7 | 102 | LPC_IOCON->PIO0_11 &= ~(0x3 << 8); |
<> | 144:ef7eb2e8f9f7 | 103 | LPC_IOCON->PIO0_11 |= (0x2 << 8); //FM+ mode |
<> | 144:ef7eb2e8f9f7 | 104 | #endif |
<> | 144:ef7eb2e8f9f7 | 105 | } |
<> | 144:ef7eb2e8f9f7 | 106 | else { |
<> | 144:ef7eb2e8f9f7 | 107 | //Select any other pin for I2C1, I2C2 or I2C3 |
<> | 144:ef7eb2e8f9f7 | 108 | i2c_ch = get_available_i2c(); |
<> | 144:ef7eb2e8f9f7 | 109 | if (i2c_ch == -1) |
<> | 144:ef7eb2e8f9f7 | 110 | return; |
<> | 144:ef7eb2e8f9f7 | 111 | i2c_used |= (1 << (i2c_ch - 1)); |
<> | 144:ef7eb2e8f9f7 | 112 | |
<> | 144:ef7eb2e8f9f7 | 113 | swm = &SWM_I2C_SDA[i2c_ch - 1]; |
<> | 144:ef7eb2e8f9f7 | 114 | regVal = LPC_SWM->PINASSIGN[swm->n] & ~(0xFF << swm->offset); |
<> | 144:ef7eb2e8f9f7 | 115 | LPC_SWM->PINASSIGN[swm->n] = regVal | ((sda >> PIN_SHIFT) << swm->offset); |
<> | 144:ef7eb2e8f9f7 | 116 | |
<> | 144:ef7eb2e8f9f7 | 117 | swm = &SWM_I2C_SCL[i2c_ch - 1]; |
<> | 144:ef7eb2e8f9f7 | 118 | regVal = LPC_SWM->PINASSIGN[swm->n] & ~(0xFF << swm->offset); |
<> | 144:ef7eb2e8f9f7 | 119 | LPC_SWM->PINASSIGN[swm->n] = regVal | ((scl >> PIN_SHIFT) << swm->offset); |
<> | 144:ef7eb2e8f9f7 | 120 | } |
<> | 144:ef7eb2e8f9f7 | 121 | |
<> | 144:ef7eb2e8f9f7 | 122 | switch(i2c_ch) { |
<> | 144:ef7eb2e8f9f7 | 123 | case 0: |
<> | 144:ef7eb2e8f9f7 | 124 | obj->i2c = (LPC_I2C0_Type *)LPC_I2C0; |
<> | 144:ef7eb2e8f9f7 | 125 | break; |
<> | 144:ef7eb2e8f9f7 | 126 | case 1: |
<> | 144:ef7eb2e8f9f7 | 127 | obj->i2c = (LPC_I2C0_Type *)LPC_I2C1; |
<> | 144:ef7eb2e8f9f7 | 128 | break; |
<> | 144:ef7eb2e8f9f7 | 129 | case 2: |
<> | 144:ef7eb2e8f9f7 | 130 | obj->i2c = (LPC_I2C0_Type *)LPC_I2C2; |
<> | 144:ef7eb2e8f9f7 | 131 | break; |
<> | 144:ef7eb2e8f9f7 | 132 | case 3: |
<> | 144:ef7eb2e8f9f7 | 133 | obj->i2c = (LPC_I2C0_Type *)LPC_I2C3; |
<> | 144:ef7eb2e8f9f7 | 134 | break; |
<> | 144:ef7eb2e8f9f7 | 135 | default: |
<> | 144:ef7eb2e8f9f7 | 136 | break; |
<> | 144:ef7eb2e8f9f7 | 137 | } |
<> | 144:ef7eb2e8f9f7 | 138 | |
<> | 144:ef7eb2e8f9f7 | 139 | // enable power |
<> | 144:ef7eb2e8f9f7 | 140 | i2c_power_enable(i2c_ch); |
<> | 144:ef7eb2e8f9f7 | 141 | // set default frequency at 100k |
<> | 144:ef7eb2e8f9f7 | 142 | i2c_frequency(obj, 100000); |
<> | 144:ef7eb2e8f9f7 | 143 | i2c_interface_enable(obj); |
<> | 144:ef7eb2e8f9f7 | 144 | } |
<> | 144:ef7eb2e8f9f7 | 145 | |
<> | 144:ef7eb2e8f9f7 | 146 | |
<> | 144:ef7eb2e8f9f7 | 147 | static inline int i2c_status(i2c_t *obj) { |
<> | 144:ef7eb2e8f9f7 | 148 | return I2C_STAT(obj); |
<> | 144:ef7eb2e8f9f7 | 149 | } |
<> | 144:ef7eb2e8f9f7 | 150 | |
<> | 144:ef7eb2e8f9f7 | 151 | // Wait until the Master Serial Interrupt (SI) is set |
<> | 144:ef7eb2e8f9f7 | 152 | // Timeout when it takes too long. |
<> | 144:ef7eb2e8f9f7 | 153 | static int i2c_wait_SI(i2c_t *obj) { |
<> | 144:ef7eb2e8f9f7 | 154 | int timeout = 0; |
<> | 144:ef7eb2e8f9f7 | 155 | while (!(obj->i2c->STAT & (1 << 0))) { |
<> | 144:ef7eb2e8f9f7 | 156 | timeout++; |
<> | 144:ef7eb2e8f9f7 | 157 | if (timeout > 100000) return -1; |
<> | 144:ef7eb2e8f9f7 | 158 | } |
<> | 144:ef7eb2e8f9f7 | 159 | return 0; |
<> | 144:ef7eb2e8f9f7 | 160 | } |
<> | 144:ef7eb2e8f9f7 | 161 | |
<> | 144:ef7eb2e8f9f7 | 162 | |
<> | 144:ef7eb2e8f9f7 | 163 | //Attention. Spec says: First store Address in DAT before setting STA ! |
<> | 144:ef7eb2e8f9f7 | 164 | //Undefined state when using single byte I2C operations and too much delay |
<> | 144:ef7eb2e8f9f7 | 165 | //between i2c_start and do_i2c_write(Address). |
<> | 144:ef7eb2e8f9f7 | 166 | //Also note that lpc812/824 will immediately continue reading a byte when Address b0 == 1 |
<> | 144:ef7eb2e8f9f7 | 167 | inline int i2c_start(i2c_t *obj) { |
<> | 144:ef7eb2e8f9f7 | 168 | int status = 0; |
<> | 144:ef7eb2e8f9f7 | 169 | if (repeated_start) { |
<> | 144:ef7eb2e8f9f7 | 170 | obj->i2c->MSTCTL = (1 << 1) | (1 << 0); // STA bit and Continue bit to complete previous RD or WR |
<> | 144:ef7eb2e8f9f7 | 171 | repeated_start = 0; |
<> | 144:ef7eb2e8f9f7 | 172 | } else { |
<> | 144:ef7eb2e8f9f7 | 173 | obj->i2c->MSTCTL = (1 << 1); // STA bit |
<> | 144:ef7eb2e8f9f7 | 174 | } |
<> | 144:ef7eb2e8f9f7 | 175 | return status; |
<> | 144:ef7eb2e8f9f7 | 176 | } |
<> | 144:ef7eb2e8f9f7 | 177 | |
<> | 144:ef7eb2e8f9f7 | 178 | //Generate Stop condition and wait until bus is Idle |
<> | 144:ef7eb2e8f9f7 | 179 | //Will also send NAK for previous RD |
<> | 144:ef7eb2e8f9f7 | 180 | inline int i2c_stop(i2c_t *obj) { |
<> | 144:ef7eb2e8f9f7 | 181 | int timeout = 0; |
<> | 144:ef7eb2e8f9f7 | 182 | |
<> | 144:ef7eb2e8f9f7 | 183 | // STP bit and Continue bit. Sends NAK to complete previous RD |
<> | 144:ef7eb2e8f9f7 | 184 | obj->i2c->MSTCTL = (1 << 2) | (1 << 0); |
<> | 144:ef7eb2e8f9f7 | 185 | |
<> | 144:ef7eb2e8f9f7 | 186 | //Spin until Ready (b0 == 1)and Status is Idle (b3..b1 == 000) |
<> | 144:ef7eb2e8f9f7 | 187 | while ((obj->i2c->STAT & ((7 << 1) | (1 << 0))) != ((0 << 1) | (1 << 0))) { |
<> | 144:ef7eb2e8f9f7 | 188 | timeout ++; |
<> | 144:ef7eb2e8f9f7 | 189 | if (timeout > 100000) return 1; |
<> | 144:ef7eb2e8f9f7 | 190 | } |
<> | 144:ef7eb2e8f9f7 | 191 | |
<> | 144:ef7eb2e8f9f7 | 192 | // repeated_start = 0; // bus free |
<> | 144:ef7eb2e8f9f7 | 193 | return 0; |
<> | 144:ef7eb2e8f9f7 | 194 | } |
<> | 144:ef7eb2e8f9f7 | 195 | |
<> | 144:ef7eb2e8f9f7 | 196 | //Spec says: first check Idle and status is Ok |
<> | 144:ef7eb2e8f9f7 | 197 | static inline int i2c_do_write(i2c_t *obj, int value, uint8_t addr) { |
<> | 144:ef7eb2e8f9f7 | 198 | // write the data |
<> | 144:ef7eb2e8f9f7 | 199 | I2C_DAT(obj) = value; |
<> | 144:ef7eb2e8f9f7 | 200 | |
<> | 144:ef7eb2e8f9f7 | 201 | if (!addr) |
<> | 144:ef7eb2e8f9f7 | 202 | obj->i2c->MSTCTL = (1 << 0); //Set continue for data. Should not be set for addr since that uses STA |
<> | 144:ef7eb2e8f9f7 | 203 | |
<> | 144:ef7eb2e8f9f7 | 204 | // wait and return status |
<> | 144:ef7eb2e8f9f7 | 205 | i2c_wait_SI(obj); |
<> | 144:ef7eb2e8f9f7 | 206 | return i2c_status(obj); |
<> | 144:ef7eb2e8f9f7 | 207 | } |
<> | 144:ef7eb2e8f9f7 | 208 | |
<> | 144:ef7eb2e8f9f7 | 209 | |
<> | 144:ef7eb2e8f9f7 | 210 | //Attention, correct Order: wait for data ready, read data, read status, continue, return |
<> | 144:ef7eb2e8f9f7 | 211 | //Dont read DAT or STAT when not ready, so dont read after setting continue. |
<> | 144:ef7eb2e8f9f7 | 212 | //Results may be invalid when next read is underway. |
<> | 144:ef7eb2e8f9f7 | 213 | static inline int i2c_do_read(i2c_t *obj, int last) { |
<> | 144:ef7eb2e8f9f7 | 214 | // wait for it to arrive |
<> | 144:ef7eb2e8f9f7 | 215 | i2c_wait_SI(obj); |
<> | 144:ef7eb2e8f9f7 | 216 | if (!last) |
<> | 144:ef7eb2e8f9f7 | 217 | obj->i2c->MSTCTL = (1 << 0); //ACK and Continue |
<> | 144:ef7eb2e8f9f7 | 218 | |
<> | 144:ef7eb2e8f9f7 | 219 | // return the data |
<> | 144:ef7eb2e8f9f7 | 220 | return (I2C_DAT(obj) & 0xFF); |
<> | 144:ef7eb2e8f9f7 | 221 | } |
<> | 144:ef7eb2e8f9f7 | 222 | |
<> | 144:ef7eb2e8f9f7 | 223 | |
<> | 144:ef7eb2e8f9f7 | 224 | void i2c_frequency(i2c_t *obj, int hz) { |
<> | 144:ef7eb2e8f9f7 | 225 | // No peripheral clock divider on the M0 |
<> | 144:ef7eb2e8f9f7 | 226 | uint32_t PCLK = SystemCoreClock; |
<> | 144:ef7eb2e8f9f7 | 227 | |
<> | 144:ef7eb2e8f9f7 | 228 | uint32_t clkdiv = PCLK / (hz * 4) - 1; |
<> | 144:ef7eb2e8f9f7 | 229 | |
<> | 144:ef7eb2e8f9f7 | 230 | obj->i2c->CLKDIV = clkdiv; |
<> | 144:ef7eb2e8f9f7 | 231 | obj->i2c->MSTTIME = 0; |
<> | 144:ef7eb2e8f9f7 | 232 | } |
<> | 144:ef7eb2e8f9f7 | 233 | |
<> | 144:ef7eb2e8f9f7 | 234 | // The I2C does a read or a write as a whole operation |
<> | 144:ef7eb2e8f9f7 | 235 | // There are two types of error conditions it can encounter |
<> | 144:ef7eb2e8f9f7 | 236 | // 1) it can not obtain the bus |
<> | 144:ef7eb2e8f9f7 | 237 | // 2) it gets error responses at part of the transmission |
<> | 144:ef7eb2e8f9f7 | 238 | // |
<> | 144:ef7eb2e8f9f7 | 239 | // We tackle them as follows: |
<> | 144:ef7eb2e8f9f7 | 240 | // 1) we retry until we get the bus. we could have a "timeout" if we can not get it |
<> | 144:ef7eb2e8f9f7 | 241 | // which basically turns it in to a 2) |
<> | 144:ef7eb2e8f9f7 | 242 | // 2) on error, we use the standard error mechanisms to report/debug |
<> | 144:ef7eb2e8f9f7 | 243 | // |
<> | 144:ef7eb2e8f9f7 | 244 | // Therefore an I2C transaction should always complete. If it doesn't it is usually |
<> | 144:ef7eb2e8f9f7 | 245 | // because something is setup wrong (e.g. wiring), and we don't need to programatically |
<> | 144:ef7eb2e8f9f7 | 246 | // check for that |
<> | 144:ef7eb2e8f9f7 | 247 | int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) { |
<> | 144:ef7eb2e8f9f7 | 248 | int count, status; |
<> | 144:ef7eb2e8f9f7 | 249 | |
<> | 144:ef7eb2e8f9f7 | 250 | //Store the address+RD and then generate STA |
<> | 144:ef7eb2e8f9f7 | 251 | I2C_DAT(obj) = address | 0x01; |
<> | 144:ef7eb2e8f9f7 | 252 | i2c_start(obj); |
<> | 144:ef7eb2e8f9f7 | 253 | |
<> | 144:ef7eb2e8f9f7 | 254 | // Wait for completion of STA and Sending of SlaveAddress+RD and first Read byte |
<> | 144:ef7eb2e8f9f7 | 255 | i2c_wait_SI(obj); |
<> | 144:ef7eb2e8f9f7 | 256 | status = i2c_status(obj); |
<> | 144:ef7eb2e8f9f7 | 257 | if (status == 0x03) { // NAK on SlaveAddress |
<> | 144:ef7eb2e8f9f7 | 258 | i2c_stop(obj); |
<> | 144:ef7eb2e8f9f7 | 259 | return I2C_ERROR_NO_SLAVE; |
<> | 144:ef7eb2e8f9f7 | 260 | } |
<> | 144:ef7eb2e8f9f7 | 261 | |
<> | 144:ef7eb2e8f9f7 | 262 | // Read in all except last byte |
<> | 144:ef7eb2e8f9f7 | 263 | for (count = 0; count < (length-1); count++) { |
<> | 144:ef7eb2e8f9f7 | 264 | |
<> | 144:ef7eb2e8f9f7 | 265 | // Wait for it to arrive, note that first byte read after address+RD is already waiting |
<> | 144:ef7eb2e8f9f7 | 266 | i2c_wait_SI(obj); |
<> | 144:ef7eb2e8f9f7 | 267 | status = i2c_status(obj); |
<> | 144:ef7eb2e8f9f7 | 268 | if (status != 0x01) { // RX RDY |
<> | 144:ef7eb2e8f9f7 | 269 | i2c_stop(obj); |
<> | 144:ef7eb2e8f9f7 | 270 | return count; |
<> | 144:ef7eb2e8f9f7 | 271 | } |
<> | 144:ef7eb2e8f9f7 | 272 | data[count] = I2C_DAT(obj) & 0xFF; // Store read byte |
<> | 144:ef7eb2e8f9f7 | 273 | |
<> | 144:ef7eb2e8f9f7 | 274 | obj->i2c->MSTCTL = (1 << 0); // Send ACK and Continue to read |
<> | 144:ef7eb2e8f9f7 | 275 | } |
<> | 144:ef7eb2e8f9f7 | 276 | |
<> | 144:ef7eb2e8f9f7 | 277 | // Read final byte |
<> | 144:ef7eb2e8f9f7 | 278 | // Wait for it to arrive |
<> | 144:ef7eb2e8f9f7 | 279 | i2c_wait_SI(obj); |
<> | 144:ef7eb2e8f9f7 | 280 | |
<> | 144:ef7eb2e8f9f7 | 281 | status = i2c_status(obj); |
<> | 144:ef7eb2e8f9f7 | 282 | if (status != 0x01) { // RX RDY |
<> | 144:ef7eb2e8f9f7 | 283 | i2c_stop(obj); |
<> | 144:ef7eb2e8f9f7 | 284 | return count; |
<> | 144:ef7eb2e8f9f7 | 285 | } |
<> | 144:ef7eb2e8f9f7 | 286 | data[count] = I2C_DAT(obj) & 0xFF; // Store final read byte |
<> | 144:ef7eb2e8f9f7 | 287 | |
<> | 144:ef7eb2e8f9f7 | 288 | // If not repeated start, send stop. |
<> | 144:ef7eb2e8f9f7 | 289 | if (stop) { |
<> | 144:ef7eb2e8f9f7 | 290 | i2c_stop(obj); // Also sends NAK for last read byte |
<> | 144:ef7eb2e8f9f7 | 291 | } else { |
<> | 144:ef7eb2e8f9f7 | 292 | repeated_start = 1; |
<> | 144:ef7eb2e8f9f7 | 293 | } |
<> | 144:ef7eb2e8f9f7 | 294 | |
<> | 144:ef7eb2e8f9f7 | 295 | return length; |
<> | 144:ef7eb2e8f9f7 | 296 | } |
<> | 144:ef7eb2e8f9f7 | 297 | |
<> | 144:ef7eb2e8f9f7 | 298 | |
<> | 144:ef7eb2e8f9f7 | 299 | int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop) { |
<> | 144:ef7eb2e8f9f7 | 300 | int i, status; |
<> | 144:ef7eb2e8f9f7 | 301 | |
<> | 144:ef7eb2e8f9f7 | 302 | //Store the address+/WR and then generate STA |
<> | 144:ef7eb2e8f9f7 | 303 | I2C_DAT(obj) = address & 0xFE; |
<> | 144:ef7eb2e8f9f7 | 304 | i2c_start(obj); |
<> | 144:ef7eb2e8f9f7 | 305 | |
<> | 144:ef7eb2e8f9f7 | 306 | // Wait for completion of STA and Sending of SlaveAddress+/WR |
<> | 144:ef7eb2e8f9f7 | 307 | i2c_wait_SI(obj); |
<> | 144:ef7eb2e8f9f7 | 308 | status = i2c_status(obj); |
<> | 144:ef7eb2e8f9f7 | 309 | if (status == 0x03) { // NAK SlaveAddress |
<> | 144:ef7eb2e8f9f7 | 310 | i2c_stop(obj); |
<> | 144:ef7eb2e8f9f7 | 311 | return I2C_ERROR_NO_SLAVE; |
<> | 144:ef7eb2e8f9f7 | 312 | } |
<> | 144:ef7eb2e8f9f7 | 313 | |
<> | 144:ef7eb2e8f9f7 | 314 | //Write all bytes |
<> | 144:ef7eb2e8f9f7 | 315 | for (i=0; i<length; i++) { |
<> | 144:ef7eb2e8f9f7 | 316 | status = i2c_do_write(obj, data[i], 0); |
<> | 144:ef7eb2e8f9f7 | 317 | if (status != 0x02) { // TX RDY. Handles a Slave NAK on datawrite |
<> | 144:ef7eb2e8f9f7 | 318 | i2c_stop(obj); |
<> | 144:ef7eb2e8f9f7 | 319 | return i; |
<> | 144:ef7eb2e8f9f7 | 320 | } |
<> | 144:ef7eb2e8f9f7 | 321 | } |
<> | 144:ef7eb2e8f9f7 | 322 | |
<> | 144:ef7eb2e8f9f7 | 323 | // If not repeated start, send stop. |
<> | 144:ef7eb2e8f9f7 | 324 | if (stop) { |
<> | 144:ef7eb2e8f9f7 | 325 | i2c_stop(obj); |
<> | 144:ef7eb2e8f9f7 | 326 | } else { |
<> | 144:ef7eb2e8f9f7 | 327 | repeated_start = 1; |
<> | 144:ef7eb2e8f9f7 | 328 | } |
<> | 144:ef7eb2e8f9f7 | 329 | |
<> | 144:ef7eb2e8f9f7 | 330 | return length; |
<> | 144:ef7eb2e8f9f7 | 331 | } |
<> | 144:ef7eb2e8f9f7 | 332 | |
<> | 144:ef7eb2e8f9f7 | 333 | void i2c_reset(i2c_t *obj) { |
<> | 144:ef7eb2e8f9f7 | 334 | i2c_stop(obj); |
<> | 144:ef7eb2e8f9f7 | 335 | } |
<> | 144:ef7eb2e8f9f7 | 336 | |
<> | 144:ef7eb2e8f9f7 | 337 | int i2c_byte_read(i2c_t *obj, int last) { |
<> | 144:ef7eb2e8f9f7 | 338 | return (i2c_do_read(obj, last) & 0xFF); |
<> | 144:ef7eb2e8f9f7 | 339 | // return (i2c_do_read(obj, last, 0) & 0xFF); |
<> | 144:ef7eb2e8f9f7 | 340 | } |
<> | 144:ef7eb2e8f9f7 | 341 | |
<> | 144:ef7eb2e8f9f7 | 342 | int i2c_byte_write(i2c_t *obj, int data) { |
<> | 144:ef7eb2e8f9f7 | 343 | int ack; |
<> | 144:ef7eb2e8f9f7 | 344 | int status = i2c_do_write(obj, (data & 0xFF), 0); |
<> | 144:ef7eb2e8f9f7 | 345 | |
<> | 144:ef7eb2e8f9f7 | 346 | switch(status) { |
<> | 144:ef7eb2e8f9f7 | 347 | case 2: // TX RDY. Handles a Slave NAK on datawrite |
<> | 144:ef7eb2e8f9f7 | 348 | ack = 1; |
<> | 144:ef7eb2e8f9f7 | 349 | break; |
<> | 144:ef7eb2e8f9f7 | 350 | default: |
<> | 144:ef7eb2e8f9f7 | 351 | ack = 0; |
<> | 144:ef7eb2e8f9f7 | 352 | break; |
<> | 144:ef7eb2e8f9f7 | 353 | } |
<> | 144:ef7eb2e8f9f7 | 354 | |
<> | 144:ef7eb2e8f9f7 | 355 | return ack; |
<> | 144:ef7eb2e8f9f7 | 356 | } |
<> | 144:ef7eb2e8f9f7 | 357 | |
<> | 144:ef7eb2e8f9f7 | 358 | |
<> | 144:ef7eb2e8f9f7 | 359 | #if DEVICE_I2CSLAVE |
<> | 144:ef7eb2e8f9f7 | 360 | |
<> | 144:ef7eb2e8f9f7 | 361 | #define I2C_SLVDAT(x) (x->i2c->SLVDAT) |
<> | 144:ef7eb2e8f9f7 | 362 | #define I2C_SLVSTAT(x) ((x->i2c->STAT >> 9) & (0x03)) |
<> | 144:ef7eb2e8f9f7 | 363 | #define I2C_SLVSI(x) ((x->i2c->STAT >> 8) & (0x01)) |
<> | 144:ef7eb2e8f9f7 | 364 | //#define I2C_SLVCNT(x) (x->i2c->SLVCTL = (1 << 0)) |
<> | 144:ef7eb2e8f9f7 | 365 | //#define I2C_SLVNAK(x) (x->i2c->SLVCTL = (1 << 1)) |
<> | 144:ef7eb2e8f9f7 | 366 | |
<> | 144:ef7eb2e8f9f7 | 367 | #if(0) |
<> | 144:ef7eb2e8f9f7 | 368 | // Wait until the Slave Serial Interrupt (SI) is set |
<> | 144:ef7eb2e8f9f7 | 369 | // Timeout when it takes too long. |
<> | 144:ef7eb2e8f9f7 | 370 | static int i2c_wait_slave_SI(i2c_t *obj) { |
<> | 144:ef7eb2e8f9f7 | 371 | int timeout = 0; |
<> | 144:ef7eb2e8f9f7 | 372 | while (!(obj->i2c->STAT & (1 << 8))) { |
<> | 144:ef7eb2e8f9f7 | 373 | timeout++; |
<> | 144:ef7eb2e8f9f7 | 374 | if (timeout > 100000) return -1; |
<> | 144:ef7eb2e8f9f7 | 375 | } |
<> | 144:ef7eb2e8f9f7 | 376 | return 0; |
<> | 144:ef7eb2e8f9f7 | 377 | } |
<> | 144:ef7eb2e8f9f7 | 378 | #endif |
<> | 144:ef7eb2e8f9f7 | 379 | |
<> | 144:ef7eb2e8f9f7 | 380 | void i2c_slave_mode(i2c_t *obj, int enable_slave) { |
<> | 144:ef7eb2e8f9f7 | 381 | |
<> | 144:ef7eb2e8f9f7 | 382 | if (enable_slave) { |
<> | 144:ef7eb2e8f9f7 | 383 | // obj->i2c->CFG &= ~(1 << 0); //Disable Master mode |
<> | 144:ef7eb2e8f9f7 | 384 | obj->i2c->CFG |= (1 << 1); //Enable Slave mode |
<> | 144:ef7eb2e8f9f7 | 385 | } |
<> | 144:ef7eb2e8f9f7 | 386 | else { |
<> | 144:ef7eb2e8f9f7 | 387 | // obj->i2c->CFG |= (1 << 0); //Enable Master mode |
<> | 144:ef7eb2e8f9f7 | 388 | obj->i2c->CFG &= ~(1 << 1); //Disable Slave mode |
<> | 144:ef7eb2e8f9f7 | 389 | } |
<> | 144:ef7eb2e8f9f7 | 390 | } |
<> | 144:ef7eb2e8f9f7 | 391 | |
<> | 144:ef7eb2e8f9f7 | 392 | // Wait for next I2C event and find out what is going on |
<> | 144:ef7eb2e8f9f7 | 393 | // |
<> | 144:ef7eb2e8f9f7 | 394 | int i2c_slave_receive(i2c_t *obj) { |
<> | 144:ef7eb2e8f9f7 | 395 | int addr; |
<> | 144:ef7eb2e8f9f7 | 396 | |
<> | 144:ef7eb2e8f9f7 | 397 | // Check if there is any data pending |
<> | 144:ef7eb2e8f9f7 | 398 | if (! I2C_SLVSI(obj)) { |
<> | 144:ef7eb2e8f9f7 | 399 | return 0; //NoData |
<> | 144:ef7eb2e8f9f7 | 400 | }; |
<> | 144:ef7eb2e8f9f7 | 401 | |
<> | 144:ef7eb2e8f9f7 | 402 | // Check State |
<> | 144:ef7eb2e8f9f7 | 403 | switch(I2C_SLVSTAT(obj)) { |
<> | 144:ef7eb2e8f9f7 | 404 | case 0x0: // Slave address plus R/W received |
<> | 144:ef7eb2e8f9f7 | 405 | // At least one of the four slave addresses has been matched by hardware. |
<> | 144:ef7eb2e8f9f7 | 406 | // You can figure out which address by checking Slave address match Index in STAT register. |
<> | 144:ef7eb2e8f9f7 | 407 | |
<> | 144:ef7eb2e8f9f7 | 408 | // Get the received address |
<> | 144:ef7eb2e8f9f7 | 409 | addr = I2C_SLVDAT(obj) & 0xFF; |
<> | 144:ef7eb2e8f9f7 | 410 | // Send ACK on address and Continue |
<> | 144:ef7eb2e8f9f7 | 411 | obj->i2c->SLVCTL = (1 << 0); |
<> | 144:ef7eb2e8f9f7 | 412 | |
<> | 144:ef7eb2e8f9f7 | 413 | if (addr == 0x00) { |
<> | 144:ef7eb2e8f9f7 | 414 | return 2; //WriteGeneral |
<> | 144:ef7eb2e8f9f7 | 415 | } |
<> | 144:ef7eb2e8f9f7 | 416 | //check the RW bit |
<> | 144:ef7eb2e8f9f7 | 417 | if ((addr & 0x01) == 0x01) { |
<> | 144:ef7eb2e8f9f7 | 418 | return 1; //ReadAddressed |
<> | 144:ef7eb2e8f9f7 | 419 | } |
<> | 144:ef7eb2e8f9f7 | 420 | else { |
<> | 144:ef7eb2e8f9f7 | 421 | return 3; //WriteAddressed |
<> | 144:ef7eb2e8f9f7 | 422 | } |
<> | 144:ef7eb2e8f9f7 | 423 | //break; |
<> | 144:ef7eb2e8f9f7 | 424 | |
<> | 144:ef7eb2e8f9f7 | 425 | case 0x1: // Slave receive. Received data is available (Slave Receiver mode). |
<> | 144:ef7eb2e8f9f7 | 426 | // Oops, should never get here... |
<> | 144:ef7eb2e8f9f7 | 427 | obj->i2c->SLVCTL = (1 << 1); // Send NACK on received data, try to recover... |
<> | 144:ef7eb2e8f9f7 | 428 | return 0; //NoData |
<> | 144:ef7eb2e8f9f7 | 429 | |
<> | 144:ef7eb2e8f9f7 | 430 | case 0x2: // Slave transmit. Data can be transmitted (Slave Transmitter mode). |
<> | 144:ef7eb2e8f9f7 | 431 | // Oops, should never get here... |
<> | 144:ef7eb2e8f9f7 | 432 | I2C_SLVDAT(obj) = 0xFF; // Send dummy data for transmission |
<> | 144:ef7eb2e8f9f7 | 433 | obj->i2c->SLVCTL = (1 << 0); // Continue and try to recover... |
<> | 144:ef7eb2e8f9f7 | 434 | return 0; //NoData |
<> | 144:ef7eb2e8f9f7 | 435 | |
<> | 144:ef7eb2e8f9f7 | 436 | case 0x3: // Reserved. |
<> | 144:ef7eb2e8f9f7 | 437 | default: // Oops, should never get here... |
<> | 144:ef7eb2e8f9f7 | 438 | obj->i2c->SLVCTL = (1 << 0); // Continue and try to recover... |
<> | 144:ef7eb2e8f9f7 | 439 | return 0; //NoData |
<> | 144:ef7eb2e8f9f7 | 440 | //break; |
<> | 144:ef7eb2e8f9f7 | 441 | } //switch status |
<> | 144:ef7eb2e8f9f7 | 442 | } |
<> | 144:ef7eb2e8f9f7 | 443 | |
<> | 144:ef7eb2e8f9f7 | 444 | // The dedicated I2C Slave byte read and byte write functions need to be called |
<> | 144:ef7eb2e8f9f7 | 445 | // from 'common' mbed I2CSlave API for devices that have separate Master and |
<> | 144:ef7eb2e8f9f7 | 446 | // Slave engines such as the lpc812 and lpc1549. |
<> | 144:ef7eb2e8f9f7 | 447 | |
<> | 144:ef7eb2e8f9f7 | 448 | //Called when Slave is addressed for Write, Slave will receive Data in polling mode |
<> | 144:ef7eb2e8f9f7 | 449 | //Parameter last=1 means received byte will be NACKed. |
<> | 144:ef7eb2e8f9f7 | 450 | int i2c_slave_byte_read(i2c_t *obj, int last) { |
<> | 144:ef7eb2e8f9f7 | 451 | int data; |
<> | 144:ef7eb2e8f9f7 | 452 | |
<> | 144:ef7eb2e8f9f7 | 453 | // Wait for data |
<> | 144:ef7eb2e8f9f7 | 454 | while (!I2C_SLVSI(obj)); // Wait forever |
<> | 144:ef7eb2e8f9f7 | 455 | //if (i2c_wait_slave_SI(obj) != 0) {return -2;} // Wait with timeout |
<> | 144:ef7eb2e8f9f7 | 456 | |
<> | 144:ef7eb2e8f9f7 | 457 | // Dont bother to check State, were not returning it anyhow.. |
<> | 144:ef7eb2e8f9f7 | 458 | //if (I2C_SLVSTAT(obj)) == 0x01) { |
<> | 144:ef7eb2e8f9f7 | 459 | // Slave receive. Received data is available (Slave Receiver mode). |
<> | 144:ef7eb2e8f9f7 | 460 | //}; |
<> | 144:ef7eb2e8f9f7 | 461 | |
<> | 144:ef7eb2e8f9f7 | 462 | data = I2C_SLVDAT(obj) & 0xFF; // Get and store the received data |
<> | 144:ef7eb2e8f9f7 | 463 | if (last) { |
<> | 144:ef7eb2e8f9f7 | 464 | obj->i2c->SLVCTL = (1 << 1); // Send NACK on received data and Continue |
<> | 144:ef7eb2e8f9f7 | 465 | } |
<> | 144:ef7eb2e8f9f7 | 466 | else { |
<> | 144:ef7eb2e8f9f7 | 467 | obj->i2c->SLVCTL = (1 << 0); // Send ACK on data and Continue to read |
<> | 144:ef7eb2e8f9f7 | 468 | } |
<> | 144:ef7eb2e8f9f7 | 469 | |
<> | 144:ef7eb2e8f9f7 | 470 | return data; |
<> | 144:ef7eb2e8f9f7 | 471 | } |
<> | 144:ef7eb2e8f9f7 | 472 | |
<> | 144:ef7eb2e8f9f7 | 473 | |
<> | 144:ef7eb2e8f9f7 | 474 | //Called when Slave is addressed for Read, Slave will send Data in polling mode |
<> | 144:ef7eb2e8f9f7 | 475 | // |
<> | 144:ef7eb2e8f9f7 | 476 | int i2c_slave_byte_write(i2c_t *obj, int data) { |
<> | 144:ef7eb2e8f9f7 | 477 | |
<> | 144:ef7eb2e8f9f7 | 478 | // Wait until Ready |
<> | 144:ef7eb2e8f9f7 | 479 | while (!I2C_SLVSI(obj)); // Wait forever |
<> | 144:ef7eb2e8f9f7 | 480 | // if (i2c_wait_slave_SI(obj) != 0) {return -2;} // Wait with timeout |
<> | 144:ef7eb2e8f9f7 | 481 | |
<> | 144:ef7eb2e8f9f7 | 482 | // Check State |
<> | 144:ef7eb2e8f9f7 | 483 | switch(I2C_SLVSTAT(obj)) { |
<> | 144:ef7eb2e8f9f7 | 484 | case 0x0: // Slave address plus R/W received |
<> | 144:ef7eb2e8f9f7 | 485 | // At least one of the four slave addresses has been matched by hardware. |
<> | 144:ef7eb2e8f9f7 | 486 | // You can figure out which address by checking Slave address match Index in STAT register. |
<> | 144:ef7eb2e8f9f7 | 487 | // I2C Restart occurred |
<> | 144:ef7eb2e8f9f7 | 488 | return -1; |
<> | 144:ef7eb2e8f9f7 | 489 | //break; |
<> | 144:ef7eb2e8f9f7 | 490 | case 0x1: // Slave receive. Received data is available (Slave Receiver mode). |
<> | 144:ef7eb2e8f9f7 | 491 | // Should not get here... |
<> | 144:ef7eb2e8f9f7 | 492 | return -2; |
<> | 144:ef7eb2e8f9f7 | 493 | //break; |
<> | 144:ef7eb2e8f9f7 | 494 | case 0x2: // Slave transmit. Data can be transmitted (Slave Transmitter mode). |
<> | 144:ef7eb2e8f9f7 | 495 | I2C_SLVDAT(obj) = data & 0xFF; // Store the data for transmission |
<> | 144:ef7eb2e8f9f7 | 496 | obj->i2c->SLVCTL = (1 << 0); // Continue to send |
<> | 144:ef7eb2e8f9f7 | 497 | |
<> | 144:ef7eb2e8f9f7 | 498 | return 1; |
<> | 144:ef7eb2e8f9f7 | 499 | //break; |
<> | 144:ef7eb2e8f9f7 | 500 | case 0x3: // Reserved. |
<> | 144:ef7eb2e8f9f7 | 501 | default: |
<> | 144:ef7eb2e8f9f7 | 502 | // Should not get here... |
<> | 144:ef7eb2e8f9f7 | 503 | return -3; |
<> | 144:ef7eb2e8f9f7 | 504 | //break; |
<> | 144:ef7eb2e8f9f7 | 505 | } // switch status |
<> | 144:ef7eb2e8f9f7 | 506 | } |
<> | 144:ef7eb2e8f9f7 | 507 | |
<> | 144:ef7eb2e8f9f7 | 508 | |
<> | 144:ef7eb2e8f9f7 | 509 | //Called when Slave is addressed for Write, Slave will receive Data in polling mode |
<> | 144:ef7eb2e8f9f7 | 510 | //Parameter length (>=1) is the maximum allowable number of bytes. All bytes will be ACKed. |
<> | 144:ef7eb2e8f9f7 | 511 | int i2c_slave_read(i2c_t *obj, char *data, int length) { |
<> | 144:ef7eb2e8f9f7 | 512 | int count=0; |
<> | 144:ef7eb2e8f9f7 | 513 | |
<> | 144:ef7eb2e8f9f7 | 514 | // Read and ACK all expected bytes |
<> | 144:ef7eb2e8f9f7 | 515 | while (count < length) { |
<> | 144:ef7eb2e8f9f7 | 516 | // Wait for data |
<> | 144:ef7eb2e8f9f7 | 517 | while (!I2C_SLVSI(obj)); // Wait forever |
<> | 144:ef7eb2e8f9f7 | 518 | // if (i2c_wait_slave_SI(obj) != 0) {return -2;} // Wait with timeout |
<> | 144:ef7eb2e8f9f7 | 519 | |
<> | 144:ef7eb2e8f9f7 | 520 | // Check State |
<> | 144:ef7eb2e8f9f7 | 521 | switch(I2C_SLVSTAT(obj)) { |
<> | 144:ef7eb2e8f9f7 | 522 | case 0x0: // Slave address plus R/W received |
<> | 144:ef7eb2e8f9f7 | 523 | // At least one of the four slave addresses has been matched by hardware. |
<> | 144:ef7eb2e8f9f7 | 524 | // You can figure out which address by checking Slave address match Index in STAT register. |
<> | 144:ef7eb2e8f9f7 | 525 | // I2C Restart occurred |
<> | 144:ef7eb2e8f9f7 | 526 | return -1; |
<> | 144:ef7eb2e8f9f7 | 527 | //break; |
<> | 144:ef7eb2e8f9f7 | 528 | |
<> | 144:ef7eb2e8f9f7 | 529 | case 0x1: // Slave receive. Received data is available (Slave Receiver mode). |
<> | 144:ef7eb2e8f9f7 | 530 | data[count] = I2C_SLVDAT(obj) & 0xFF; // Get and store the received data |
<> | 144:ef7eb2e8f9f7 | 531 | obj->i2c->SLVCTL = (1 << 0); // Send ACK on data and Continue to read |
<> | 144:ef7eb2e8f9f7 | 532 | break; |
<> | 144:ef7eb2e8f9f7 | 533 | |
<> | 144:ef7eb2e8f9f7 | 534 | case 0x2: // Slave transmit. Data can be transmitted (Slave Transmitter mode). |
<> | 144:ef7eb2e8f9f7 | 535 | case 0x3: // Reserved. |
<> | 144:ef7eb2e8f9f7 | 536 | default: // Should never get here... |
<> | 144:ef7eb2e8f9f7 | 537 | return -2; |
<> | 144:ef7eb2e8f9f7 | 538 | //break; |
<> | 144:ef7eb2e8f9f7 | 539 | } // switch status |
<> | 144:ef7eb2e8f9f7 | 540 | |
<> | 144:ef7eb2e8f9f7 | 541 | count++; |
<> | 144:ef7eb2e8f9f7 | 542 | } // for all bytes |
<> | 144:ef7eb2e8f9f7 | 543 | |
<> | 144:ef7eb2e8f9f7 | 544 | return count; // Received the expected number of bytes |
<> | 144:ef7eb2e8f9f7 | 545 | } |
<> | 144:ef7eb2e8f9f7 | 546 | |
<> | 144:ef7eb2e8f9f7 | 547 | |
<> | 144:ef7eb2e8f9f7 | 548 | //Called when Slave is addressed for Read, Slave will send Data in polling mode |
<> | 144:ef7eb2e8f9f7 | 549 | //Parameter length (>=1) is the maximum number of bytes. Exit when Slave byte is NACKed. |
<> | 144:ef7eb2e8f9f7 | 550 | int i2c_slave_write(i2c_t *obj, const char *data, int length) { |
<> | 144:ef7eb2e8f9f7 | 551 | int count; |
<> | 144:ef7eb2e8f9f7 | 552 | |
<> | 144:ef7eb2e8f9f7 | 553 | // Send and all bytes or Exit on NAK |
<> | 144:ef7eb2e8f9f7 | 554 | for (count=0; count < length; count++) { |
<> | 144:ef7eb2e8f9f7 | 555 | // Wait until Ready for data |
<> | 144:ef7eb2e8f9f7 | 556 | while (!I2C_SLVSI(obj)); // Wait forever |
<> | 144:ef7eb2e8f9f7 | 557 | // if (i2c_wait_slave_SI(obj) != 0) {return -2;} // Wait with timeout |
<> | 144:ef7eb2e8f9f7 | 558 | |
<> | 144:ef7eb2e8f9f7 | 559 | // Check State |
<> | 144:ef7eb2e8f9f7 | 560 | switch(I2C_SLVSTAT(obj)) { |
<> | 144:ef7eb2e8f9f7 | 561 | case 0x0: // Slave address plus R/W received |
<> | 144:ef7eb2e8f9f7 | 562 | // At least one of the four slave addresses has been matched by hardware. |
<> | 144:ef7eb2e8f9f7 | 563 | // You can figure out which address by checking Slave address match Index in STAT register. |
<> | 144:ef7eb2e8f9f7 | 564 | // I2C Restart occurred |
<> | 144:ef7eb2e8f9f7 | 565 | return -1; |
<> | 144:ef7eb2e8f9f7 | 566 | //break; |
<> | 144:ef7eb2e8f9f7 | 567 | case 0x1: // Slave receive. Received data is available (Slave Receiver mode). |
<> | 144:ef7eb2e8f9f7 | 568 | // Should not get here... |
<> | 144:ef7eb2e8f9f7 | 569 | return -2; |
<> | 144:ef7eb2e8f9f7 | 570 | //break; |
<> | 144:ef7eb2e8f9f7 | 571 | case 0x2: // Slave transmit. Data can be transmitted (Slave Transmitter mode). |
<> | 144:ef7eb2e8f9f7 | 572 | I2C_SLVDAT(obj) = data[count] & 0xFF; // Store the data for transmission |
<> | 144:ef7eb2e8f9f7 | 573 | obj->i2c->SLVCTL = (1 << 0); // Continue to send |
<> | 144:ef7eb2e8f9f7 | 574 | break; |
<> | 144:ef7eb2e8f9f7 | 575 | case 0x3: // Reserved. |
<> | 144:ef7eb2e8f9f7 | 576 | default: |
<> | 144:ef7eb2e8f9f7 | 577 | // Should not get here... |
<> | 144:ef7eb2e8f9f7 | 578 | return -3; |
<> | 144:ef7eb2e8f9f7 | 579 | //break; |
<> | 144:ef7eb2e8f9f7 | 580 | } // switch status |
<> | 144:ef7eb2e8f9f7 | 581 | } // for all bytes |
<> | 144:ef7eb2e8f9f7 | 582 | |
<> | 144:ef7eb2e8f9f7 | 583 | return length; // Transmitted the max number of bytes |
<> | 144:ef7eb2e8f9f7 | 584 | } |
<> | 144:ef7eb2e8f9f7 | 585 | |
<> | 144:ef7eb2e8f9f7 | 586 | |
<> | 144:ef7eb2e8f9f7 | 587 | // Set the four slave addresses. |
<> | 144:ef7eb2e8f9f7 | 588 | void i2c_slave_address(i2c_t *obj, int idx, uint32_t address, uint32_t mask) { |
<> | 144:ef7eb2e8f9f7 | 589 | obj->i2c->SLVADR0 = (address & 0xFE); // Store address in address 0 register |
<> | 144:ef7eb2e8f9f7 | 590 | obj->i2c->SLVADR1 = (0x00 & 0xFE); // Store general call write address in address 1 register |
<> | 144:ef7eb2e8f9f7 | 591 | obj->i2c->SLVADR2 = (0x01); // Disable address 2 register |
<> | 144:ef7eb2e8f9f7 | 592 | obj->i2c->SLVADR3 = (0x01); // Disable address 3 register |
<> | 144:ef7eb2e8f9f7 | 593 | obj->i2c->SLVQUAL0 = (mask & 0xFE); // Qualifier mask for address 0 register. Any maskbit that is 1 will always be a match |
<> | 144:ef7eb2e8f9f7 | 594 | } |
<> | 144:ef7eb2e8f9f7 | 595 | |
<> | 144:ef7eb2e8f9f7 | 596 | #endif |
<> | 144:ef7eb2e8f9f7 | 597 | |
<> | 144:ef7eb2e8f9f7 | 598 | #endif |