this is i2c library on wallbot BLE. wallbot BLE using BL600. BL600 has one of nRF51822 module. but P0_20 is not use any I/O. this library has use P0_20:SCL P0_21:SDA. based on mbed-src i2c class.

Committer:
sibu2
Date:
Sun Aug 31 12:52:08 2014 +0000
Revision:
0:c2a44165fec8
this is my testing i2c library for BL600; BL600 has one of nRF51822 module.; but P0_20 is not use any I/O.; this library use SCL:P0_21 and SDA:P0_22.; based on mbed-src i2c class.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
sibu2 0:c2a44165fec8 1 /* mbed Microcontroller Library
sibu2 0:c2a44165fec8 2 * Copyright (c) 2013 Nordic Semiconductor
sibu2 0:c2a44165fec8 3 *
sibu2 0:c2a44165fec8 4 * Licensed under the Apache License, Version 2.0 (the "License");
sibu2 0:c2a44165fec8 5 * you may not use this file except in compliance with the License.
sibu2 0:c2a44165fec8 6 * You may obtain a copy of the License at
sibu2 0:c2a44165fec8 7 *
sibu2 0:c2a44165fec8 8 * http://www.apache.org/licenses/LICENSE-2.0
sibu2 0:c2a44165fec8 9 *
sibu2 0:c2a44165fec8 10 * Unless required by applicable law or agreed to in writing, software
sibu2 0:c2a44165fec8 11 * distributed under the License is distributed on an "AS IS" BASIS,
sibu2 0:c2a44165fec8 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
sibu2 0:c2a44165fec8 13 * See the License for the specific language governing permissions and
sibu2 0:c2a44165fec8 14 * limitations under the License.
sibu2 0:c2a44165fec8 15 */
sibu2 0:c2a44165fec8 16 #include "mbed_assert.h"
sibu2 0:c2a44165fec8 17 #include "myi2c_api.h"
sibu2 0:c2a44165fec8 18 #include "cmsis.h"
sibu2 0:c2a44165fec8 19 #include "pinmap.h"
sibu2 0:c2a44165fec8 20
sibu2 0:c2a44165fec8 21 static const PinMap PinMap_I2C_SDA[] = {
sibu2 0:c2a44165fec8 22 {p22, I2C_0, 1},
sibu2 0:c2a44165fec8 23 {p13, I2C_1, 2},
sibu2 0:c2a44165fec8 24 {NC, NC, 0}
sibu2 0:c2a44165fec8 25 };
sibu2 0:c2a44165fec8 26
sibu2 0:c2a44165fec8 27 static const PinMap PinMap_I2C_SCL[] = {
sibu2 0:c2a44165fec8 28 {p21, I2C_0, 1},
sibu2 0:c2a44165fec8 29 {p15, I2C_1, 2},
sibu2 0:c2a44165fec8 30 {NC, NC, 0}
sibu2 0:c2a44165fec8 31 };
sibu2 0:c2a44165fec8 32
sibu2 0:c2a44165fec8 33 uint8_t addrSet = 0;
sibu2 0:c2a44165fec8 34
sibu2 0:c2a44165fec8 35 void i2c_interface_enable(i2c_t *obj)
sibu2 0:c2a44165fec8 36 {
sibu2 0:c2a44165fec8 37 obj->i2c->ENABLE = (TWI_ENABLE_ENABLE_Enabled << TWI_ENABLE_ENABLE_Pos);
sibu2 0:c2a44165fec8 38 }
sibu2 0:c2a44165fec8 39
sibu2 0:c2a44165fec8 40 void twi_master_init(i2c_t *obj, PinName sda, PinName scl, int frequency)
sibu2 0:c2a44165fec8 41 {
sibu2 0:c2a44165fec8 42 NRF_GPIO->PIN_CNF[scl] = ((GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos) |
sibu2 0:c2a44165fec8 43 (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) |
sibu2 0:c2a44165fec8 44 (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos) |
sibu2 0:c2a44165fec8 45 (GPIO_PIN_CNF_DRIVE_S0D1 << GPIO_PIN_CNF_DRIVE_Pos) |
sibu2 0:c2a44165fec8 46 (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos));
sibu2 0:c2a44165fec8 47
sibu2 0:c2a44165fec8 48 NRF_GPIO->PIN_CNF[sda] = ((GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos) |
sibu2 0:c2a44165fec8 49 (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) |
sibu2 0:c2a44165fec8 50 (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos) |
sibu2 0:c2a44165fec8 51 (GPIO_PIN_CNF_DRIVE_S0D1 << GPIO_PIN_CNF_DRIVE_Pos) |
sibu2 0:c2a44165fec8 52 (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos));
sibu2 0:c2a44165fec8 53
sibu2 0:c2a44165fec8 54 obj->i2c->PSELSCL = scl;
sibu2 0:c2a44165fec8 55 obj->i2c->PSELSDA = sda;
sibu2 0:c2a44165fec8 56 // set default frequency at 100k
sibu2 0:c2a44165fec8 57 i2c_frequency(obj, frequency);
sibu2 0:c2a44165fec8 58 i2c_interface_enable(obj);
sibu2 0:c2a44165fec8 59 }
sibu2 0:c2a44165fec8 60
sibu2 0:c2a44165fec8 61 void i2c_init(i2c_t *obj, PinName sda, PinName scl)
sibu2 0:c2a44165fec8 62 {
sibu2 0:c2a44165fec8 63 // determine the SPI to use
sibu2 0:c2a44165fec8 64 I2CName i2c_sda = (I2CName)pinmap_peripheral(sda, PinMap_I2C_SDA);
sibu2 0:c2a44165fec8 65 I2CName i2c_scl = (I2CName)pinmap_peripheral(scl, PinMap_I2C_SCL);
sibu2 0:c2a44165fec8 66 I2CName i2c = (I2CName)pinmap_merge(i2c_sda, i2c_scl);
sibu2 0:c2a44165fec8 67 obj->i2c = (NRF_TWI_Type *)i2c;
sibu2 0:c2a44165fec8 68
sibu2 0:c2a44165fec8 69 MBED_ASSERT((int)obj->i2c != NC);
sibu2 0:c2a44165fec8 70
sibu2 0:c2a44165fec8 71 obj->scl = scl;
sibu2 0:c2a44165fec8 72 obj->sda = sda;
sibu2 0:c2a44165fec8 73 obj->i2c->EVENTS_ERROR = 0;
sibu2 0:c2a44165fec8 74 obj->i2c->ENABLE = TWI_ENABLE_ENABLE_Disabled << TWI_ENABLE_ENABLE_Pos;
sibu2 0:c2a44165fec8 75 obj->i2c->POWER = 0;
sibu2 0:c2a44165fec8 76
sibu2 0:c2a44165fec8 77 for (int i = 0; i<100; i++) {
sibu2 0:c2a44165fec8 78 }
sibu2 0:c2a44165fec8 79
sibu2 0:c2a44165fec8 80 obj->i2c->POWER = 1;
sibu2 0:c2a44165fec8 81 twi_master_init(obj, sda, scl, 100000);
sibu2 0:c2a44165fec8 82 }
sibu2 0:c2a44165fec8 83
sibu2 0:c2a44165fec8 84 void i2c_reset(i2c_t *obj)
sibu2 0:c2a44165fec8 85 {
sibu2 0:c2a44165fec8 86 obj->i2c->EVENTS_ERROR = 0;
sibu2 0:c2a44165fec8 87 obj->i2c->ENABLE = TWI_ENABLE_ENABLE_Disabled << TWI_ENABLE_ENABLE_Pos;
sibu2 0:c2a44165fec8 88 obj->i2c->POWER = 0;
sibu2 0:c2a44165fec8 89 for (int i = 0; i<100; i++) {
sibu2 0:c2a44165fec8 90 }
sibu2 0:c2a44165fec8 91
sibu2 0:c2a44165fec8 92 obj->i2c->POWER = 1;
sibu2 0:c2a44165fec8 93 twi_master_init(obj, obj->sda, obj->scl, obj->freq);
sibu2 0:c2a44165fec8 94 }
sibu2 0:c2a44165fec8 95
sibu2 0:c2a44165fec8 96 int i2c_start(i2c_t *obj)
sibu2 0:c2a44165fec8 97 {
sibu2 0:c2a44165fec8 98 int status = 0;
sibu2 0:c2a44165fec8 99 i2c_reset(obj);
sibu2 0:c2a44165fec8 100 addrSet = 0;
sibu2 0:c2a44165fec8 101 return status;
sibu2 0:c2a44165fec8 102 }
sibu2 0:c2a44165fec8 103
sibu2 0:c2a44165fec8 104 int i2c_stop(i2c_t *obj)
sibu2 0:c2a44165fec8 105 {
sibu2 0:c2a44165fec8 106 int timeOut = 100000;
sibu2 0:c2a44165fec8 107 obj->i2c->EVENTS_STOPPED = 0;
sibu2 0:c2a44165fec8 108 // write the stop bit
sibu2 0:c2a44165fec8 109 obj->i2c->TASKS_STOP = 1;
sibu2 0:c2a44165fec8 110 while (!obj->i2c->EVENTS_STOPPED) {
sibu2 0:c2a44165fec8 111 timeOut--;
sibu2 0:c2a44165fec8 112 if (timeOut<0) {
sibu2 0:c2a44165fec8 113 return 1;
sibu2 0:c2a44165fec8 114 }
sibu2 0:c2a44165fec8 115 }
sibu2 0:c2a44165fec8 116 addrSet = 0;
sibu2 0:c2a44165fec8 117 i2c_reset(obj);
sibu2 0:c2a44165fec8 118 return 0;
sibu2 0:c2a44165fec8 119 }
sibu2 0:c2a44165fec8 120
sibu2 0:c2a44165fec8 121 int i2c_do_write(i2c_t *obj, int value)
sibu2 0:c2a44165fec8 122 {
sibu2 0:c2a44165fec8 123 int timeOut = 100000;
sibu2 0:c2a44165fec8 124 obj->i2c->TXD = value;
sibu2 0:c2a44165fec8 125 while (!obj->i2c->EVENTS_TXDSENT) {
sibu2 0:c2a44165fec8 126 timeOut--;
sibu2 0:c2a44165fec8 127 if (timeOut<0) {
sibu2 0:c2a44165fec8 128 return 1;
sibu2 0:c2a44165fec8 129 }
sibu2 0:c2a44165fec8 130 }
sibu2 0:c2a44165fec8 131 obj->i2c->EVENTS_TXDSENT = 0;
sibu2 0:c2a44165fec8 132 return 0;
sibu2 0:c2a44165fec8 133 }
sibu2 0:c2a44165fec8 134
sibu2 0:c2a44165fec8 135 int i2c_do_read(i2c_t *obj, char *data, int last)
sibu2 0:c2a44165fec8 136 {
sibu2 0:c2a44165fec8 137 int timeOut = 100000;
sibu2 0:c2a44165fec8 138
sibu2 0:c2a44165fec8 139 if (last) {
sibu2 0:c2a44165fec8 140 obj->i2c->TASKS_STOP = 1;
sibu2 0:c2a44165fec8 141 }
sibu2 0:c2a44165fec8 142 while (!obj->i2c->EVENTS_RXDREADY) {
sibu2 0:c2a44165fec8 143 timeOut--;
sibu2 0:c2a44165fec8 144 if (timeOut<0) {
sibu2 0:c2a44165fec8 145 return 1;
sibu2 0:c2a44165fec8 146 }
sibu2 0:c2a44165fec8 147 }
sibu2 0:c2a44165fec8 148 obj->i2c->EVENTS_RXDREADY = 0;
sibu2 0:c2a44165fec8 149
sibu2 0:c2a44165fec8 150 *data = obj->i2c->RXD;
sibu2 0:c2a44165fec8 151
sibu2 0:c2a44165fec8 152 for (int i = 0; i<320; i++) {
sibu2 0:c2a44165fec8 153 }
sibu2 0:c2a44165fec8 154
sibu2 0:c2a44165fec8 155 obj->i2c->TASKS_RESUME = 1;
sibu2 0:c2a44165fec8 156
sibu2 0:c2a44165fec8 157 return 0;
sibu2 0:c2a44165fec8 158 }
sibu2 0:c2a44165fec8 159
sibu2 0:c2a44165fec8 160 void i2c_frequency(i2c_t *obj, int hz)
sibu2 0:c2a44165fec8 161 {
sibu2 0:c2a44165fec8 162 if (hz<250000) {
sibu2 0:c2a44165fec8 163 obj->freq = 100000;
sibu2 0:c2a44165fec8 164 obj->i2c->FREQUENCY = (TWI_FREQUENCY_FREQUENCY_K100 << TWI_FREQUENCY_FREQUENCY_Pos);
sibu2 0:c2a44165fec8 165 } else if (hz<400000) {
sibu2 0:c2a44165fec8 166 obj->freq = 250000;
sibu2 0:c2a44165fec8 167 obj->i2c->FREQUENCY = (TWI_FREQUENCY_FREQUENCY_K250 << TWI_FREQUENCY_FREQUENCY_Pos);
sibu2 0:c2a44165fec8 168 } else {
sibu2 0:c2a44165fec8 169 obj->freq = 400000;
sibu2 0:c2a44165fec8 170 obj->i2c->FREQUENCY = (TWI_FREQUENCY_FREQUENCY_K400 << TWI_FREQUENCY_FREQUENCY_Pos);
sibu2 0:c2a44165fec8 171 }
sibu2 0:c2a44165fec8 172 }
sibu2 0:c2a44165fec8 173
sibu2 0:c2a44165fec8 174 int checkError(i2c_t *obj)
sibu2 0:c2a44165fec8 175 {
sibu2 0:c2a44165fec8 176 if (obj->i2c->EVENTS_ERROR == 1) {
sibu2 0:c2a44165fec8 177 if (obj->i2c->ERRORSRC & TWI_ERRORSRC_ANACK_Msk) {
sibu2 0:c2a44165fec8 178 obj->i2c->EVENTS_ERROR = 0;
sibu2 0:c2a44165fec8 179 obj->i2c->TASKS_STOP = 1;
sibu2 0:c2a44165fec8 180 return I2C_ERROR_BUS_BUSY;
sibu2 0:c2a44165fec8 181 }
sibu2 0:c2a44165fec8 182
sibu2 0:c2a44165fec8 183 obj->i2c->EVENTS_ERROR = 0;
sibu2 0:c2a44165fec8 184 obj->i2c->TASKS_STOP = 1;
sibu2 0:c2a44165fec8 185 return I2C_ERROR_NO_SLAVE;
sibu2 0:c2a44165fec8 186 }
sibu2 0:c2a44165fec8 187 return 0;
sibu2 0:c2a44165fec8 188 }
sibu2 0:c2a44165fec8 189
sibu2 0:c2a44165fec8 190 int i2c_read(i2c_t *obj, int address, char *data, int length, int stop)
sibu2 0:c2a44165fec8 191 {
sibu2 0:c2a44165fec8 192 int status, count, errorResult;
sibu2 0:c2a44165fec8 193 obj->i2c->ADDRESS = (address >> 1);
sibu2 0:c2a44165fec8 194 obj->i2c->SHORTS = 0;
sibu2 0:c2a44165fec8 195 obj->i2c->EVENTS_RXDREADY = 0;
sibu2 0:c2a44165fec8 196 obj->i2c->TASKS_STARTRX = 1;
sibu2 0:c2a44165fec8 197
sibu2 0:c2a44165fec8 198 // Read in all except last byte
sibu2 0:c2a44165fec8 199 for (count = 0; count < (length - 1); count++) {
sibu2 0:c2a44165fec8 200 status = i2c_do_read(obj, &data[count], 0);
sibu2 0:c2a44165fec8 201 if (status) {
sibu2 0:c2a44165fec8 202 errorResult = checkError(obj);
sibu2 0:c2a44165fec8 203 i2c_reset(obj);
sibu2 0:c2a44165fec8 204 if (errorResult<0) {
sibu2 0:c2a44165fec8 205 return errorResult;
sibu2 0:c2a44165fec8 206 }
sibu2 0:c2a44165fec8 207 return count;
sibu2 0:c2a44165fec8 208 }
sibu2 0:c2a44165fec8 209 }
sibu2 0:c2a44165fec8 210
sibu2 0:c2a44165fec8 211 // read in last byte
sibu2 0:c2a44165fec8 212 status = i2c_do_read(obj, &data[length - 1], 1);
sibu2 0:c2a44165fec8 213 if (status) {
sibu2 0:c2a44165fec8 214 i2c_reset(obj);
sibu2 0:c2a44165fec8 215 return length - 1;
sibu2 0:c2a44165fec8 216 }
sibu2 0:c2a44165fec8 217 // If not repeated start, send stop.
sibu2 0:c2a44165fec8 218 if (stop) {
sibu2 0:c2a44165fec8 219 while (!obj->i2c->EVENTS_STOPPED) {
sibu2 0:c2a44165fec8 220 }
sibu2 0:c2a44165fec8 221 obj->i2c->EVENTS_STOPPED = 0;
sibu2 0:c2a44165fec8 222 }
sibu2 0:c2a44165fec8 223 return length;
sibu2 0:c2a44165fec8 224 }
sibu2 0:c2a44165fec8 225
sibu2 0:c2a44165fec8 226 int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop)
sibu2 0:c2a44165fec8 227 {
sibu2 0:c2a44165fec8 228 int status, errorResult;
sibu2 0:c2a44165fec8 229 obj->i2c->ADDRESS = (address >> 1);
sibu2 0:c2a44165fec8 230 obj->i2c->SHORTS = 0;
sibu2 0:c2a44165fec8 231 obj->i2c->TASKS_STARTTX = 1;
sibu2 0:c2a44165fec8 232
sibu2 0:c2a44165fec8 233 for (int i = 0; i<length; i++) {
sibu2 0:c2a44165fec8 234 status = i2c_do_write(obj, data[i]);
sibu2 0:c2a44165fec8 235 if (status) {
sibu2 0:c2a44165fec8 236 i2c_reset(obj);
sibu2 0:c2a44165fec8 237 errorResult = checkError(obj);
sibu2 0:c2a44165fec8 238 if (errorResult<0) {
sibu2 0:c2a44165fec8 239 return errorResult;
sibu2 0:c2a44165fec8 240 }
sibu2 0:c2a44165fec8 241 return i;
sibu2 0:c2a44165fec8 242 }
sibu2 0:c2a44165fec8 243 }
sibu2 0:c2a44165fec8 244
sibu2 0:c2a44165fec8 245 // If not repeated start, send stop.
sibu2 0:c2a44165fec8 246 if (stop) {
sibu2 0:c2a44165fec8 247 if (i2c_stop(obj)) {
sibu2 0:c2a44165fec8 248 return I2C_ERROR_NO_SLAVE;
sibu2 0:c2a44165fec8 249 }
sibu2 0:c2a44165fec8 250 }
sibu2 0:c2a44165fec8 251 return length;
sibu2 0:c2a44165fec8 252 }
sibu2 0:c2a44165fec8 253
sibu2 0:c2a44165fec8 254 int i2c_byte_read(i2c_t *obj, int last)
sibu2 0:c2a44165fec8 255 {
sibu2 0:c2a44165fec8 256 char data;
sibu2 0:c2a44165fec8 257 int status;
sibu2 0:c2a44165fec8 258
sibu2 0:c2a44165fec8 259 status = i2c_do_read(obj, &data, last);
sibu2 0:c2a44165fec8 260 if (status) {
sibu2 0:c2a44165fec8 261 i2c_reset(obj);
sibu2 0:c2a44165fec8 262 }
sibu2 0:c2a44165fec8 263 return data;
sibu2 0:c2a44165fec8 264 }
sibu2 0:c2a44165fec8 265
sibu2 0:c2a44165fec8 266 int i2c_byte_write(i2c_t *obj, int data)
sibu2 0:c2a44165fec8 267 {
sibu2 0:c2a44165fec8 268 int status = 0;
sibu2 0:c2a44165fec8 269 if (!addrSet) {
sibu2 0:c2a44165fec8 270 addrSet = 1;
sibu2 0:c2a44165fec8 271 obj->i2c->ADDRESS = (data >> 1);
sibu2 0:c2a44165fec8 272
sibu2 0:c2a44165fec8 273 if (data & 1) {
sibu2 0:c2a44165fec8 274 obj->i2c->EVENTS_RXDREADY = 0;
sibu2 0:c2a44165fec8 275 obj->i2c->TASKS_STARTRX = 1;
sibu2 0:c2a44165fec8 276 } else {
sibu2 0:c2a44165fec8 277 obj->i2c->TASKS_STARTTX = 1;
sibu2 0:c2a44165fec8 278 }
sibu2 0:c2a44165fec8 279 } else {
sibu2 0:c2a44165fec8 280 status = i2c_do_write(obj, data);
sibu2 0:c2a44165fec8 281 if (status) {
sibu2 0:c2a44165fec8 282 i2c_reset(obj);
sibu2 0:c2a44165fec8 283 }
sibu2 0:c2a44165fec8 284 }
sibu2 0:c2a44165fec8 285 return (1 - status);
sibu2 0:c2a44165fec8 286 }