Test code for Grove Node BLE

Dependencies:   BLE_API nRF51822

Fork of BLE_LoopbackUART by Bluetooth Low Energy

Committer:
yihui
Date:
Thu Nov 27 09:30:36 2014 +0000
Revision:
10:22480ac31879
Parent:
9:05f0b5a3a70a
change to new revision hardware

Who changed what in which revision?

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