1 /* mbed Microcontroller Library
2 * Copyright (c) 2013 Nordic Semiconductor
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 #include "mbed_assert.h"
20 #include "mbed_error.h"
22 // nRF51822's I2C_0 and SPI_0 (I2C_1, SPI_1 and SPIS1) share the same address.
23 // They can't be used at the same time. So we use two global variable to track the usage.
24 // See nRF51822 address information at nRF51822_PS v2.0.pdf - Table 15 Peripheral instance reference
25 volatile i2c_spi_peripheral_t i2c0_spi0_peripheral
= {0, 0, 0, 0};
26 volatile i2c_spi_peripheral_t i2c1_spi1_peripheral
= {0, 0, 0, 0};
28 void i2c_interface_enable(i2c_t
*obj
)
30 obj
->i2c
->ENABLE
= (TWI_ENABLE_ENABLE_Enabled
<< TWI_ENABLE_ENABLE_Pos
);
33 void twi_master_init(i2c_t
*obj
, PinName sda
, PinName scl
, int frequency
)
35 NRF_GPIO
->PIN_CNF
[scl
] = ((GPIO_PIN_CNF_DIR_Input
<< GPIO_PIN_CNF_DIR_Pos
) |
36 (GPIO_PIN_CNF_INPUT_Connect
<< GPIO_PIN_CNF_INPUT_Pos
) |
37 (GPIO_PIN_CNF_PULL_Disabled
<< GPIO_PIN_CNF_PULL_Pos
) |
38 (GPIO_PIN_CNF_DRIVE_S0D1
<< GPIO_PIN_CNF_DRIVE_Pos
) |
39 (GPIO_PIN_CNF_SENSE_Disabled
<< GPIO_PIN_CNF_SENSE_Pos
));
41 NRF_GPIO
->PIN_CNF
[sda
] = ((GPIO_PIN_CNF_DIR_Input
<< GPIO_PIN_CNF_DIR_Pos
) |
42 (GPIO_PIN_CNF_INPUT_Connect
<< GPIO_PIN_CNF_INPUT_Pos
) |
43 (GPIO_PIN_CNF_PULL_Disabled
<< GPIO_PIN_CNF_PULL_Pos
) |
44 (GPIO_PIN_CNF_DRIVE_S0D1
<< GPIO_PIN_CNF_DRIVE_Pos
) |
45 (GPIO_PIN_CNF_SENSE_Disabled
<< GPIO_PIN_CNF_SENSE_Pos
));
47 obj
->i2c
->PSELSCL
= scl
;
48 obj
->i2c
->PSELSDA
= sda
;
49 // set default frequency at 100k
50 i2c_frequency(obj
, frequency
);
51 i2c_interface_enable(obj
);
54 void i2c_init(i2c_t
*obj
, PinName sda
, PinName scl
)
58 if (i2c0_spi0_peripheral
.usage
== I2C_SPI_PERIPHERAL_FOR_I2C
&&
59 i2c0_spi0_peripheral
.sda_mosi
== (uint8_t)sda
&&
60 i2c0_spi0_peripheral
.scl_miso
== (uint8_t)scl
) {
61 // The I2C with the same pins is already initialized
62 i2c
= (NRF_TWI_Type
*)I2C_0
;
63 obj
->peripheral
= 0x1;
64 } else if (i2c1_spi1_peripheral
.usage
== I2C_SPI_PERIPHERAL_FOR_I2C
&&
65 i2c1_spi1_peripheral
.sda_mosi
== (uint8_t)sda
&&
66 i2c1_spi1_peripheral
.scl_miso
== (uint8_t)scl
) {
67 // The I2C with the same pins is already initialized
68 i2c
= (NRF_TWI_Type
*)I2C_1
;
69 obj
->peripheral
= 0x2;
70 } else if (i2c0_spi0_peripheral
.usage
== 0) {
71 i2c0_spi0_peripheral
.usage
= I2C_SPI_PERIPHERAL_FOR_I2C
;
72 i2c0_spi0_peripheral
.sda_mosi
= (uint8_t)sda
;
73 i2c0_spi0_peripheral
.scl_miso
= (uint8_t)scl
;
75 i2c
= (NRF_TWI_Type
*)I2C_0
;
76 obj
->peripheral
= 0x1;
77 } else if (i2c1_spi1_peripheral
.usage
== 0) {
78 i2c1_spi1_peripheral
.usage
= I2C_SPI_PERIPHERAL_FOR_I2C
;
79 i2c1_spi1_peripheral
.sda_mosi
= (uint8_t)sda
;
80 i2c1_spi1_peripheral
.scl_miso
= (uint8_t)scl
;
82 i2c
= (NRF_TWI_Type
*)I2C_1
;
83 obj
->peripheral
= 0x2;
85 // No available peripheral
86 error("No available I2C");
92 obj
->i2c
->EVENTS_ERROR
= 0;
93 obj
->i2c
->ENABLE
= TWI_ENABLE_ENABLE_Disabled
<< TWI_ENABLE_ENABLE_Pos
;
96 for (int i
= 0; i
<100; i
++) {
100 twi_master_init(obj
, sda
, scl
, 100000);
103 void i2c_reset(i2c_t
*obj
)
105 obj
->i2c
->EVENTS_ERROR
= 0;
106 obj
->i2c
->ENABLE
= TWI_ENABLE_ENABLE_Disabled
<< TWI_ENABLE_ENABLE_Pos
;
108 for (int i
= 0; i
<100; i
++) {
112 twi_master_init(obj
, obj
->sda
, obj
->scl
, obj
->freq
);
115 int i2c_start(i2c_t
*obj
)
119 obj
->address_set
= 0;
123 int i2c_stop(i2c_t
*obj
)
125 int timeOut
= 100000;
126 obj
->i2c
->EVENTS_STOPPED
= 0;
127 // write the stop bit
128 obj
->i2c
->TASKS_STOP
= 1;
129 while (!obj
->i2c
->EVENTS_STOPPED
) {
135 obj
->address_set
= 0;
140 int i2c_do_write(i2c_t
*obj
, int value
)
142 int timeOut
= 100000;
143 obj
->i2c
->TXD
= value
;
144 while (!obj
->i2c
->EVENTS_TXDSENT
) {
150 obj
->i2c
->EVENTS_TXDSENT
= 0;
154 int i2c_do_read(i2c_t
*obj
, char *data
, int last
)
156 int timeOut
= 100000;
159 // To trigger stop task when a byte is received,
160 // must be set before resume task.
161 obj
->i2c
->SHORTS
= 2;
164 obj
->i2c
->TASKS_RESUME
= 1;
166 while (!obj
->i2c
->EVENTS_RXDREADY
) {
172 obj
->i2c
->EVENTS_RXDREADY
= 0;
173 *data
= obj
->i2c
->RXD
;
178 void i2c_frequency(i2c_t
*obj
, int hz
)
182 obj
->i2c
->FREQUENCY
= (TWI_FREQUENCY_FREQUENCY_K100
<< TWI_FREQUENCY_FREQUENCY_Pos
);
183 } else if (hz
<400000) {
185 obj
->i2c
->FREQUENCY
= (TWI_FREQUENCY_FREQUENCY_K250
<< TWI_FREQUENCY_FREQUENCY_Pos
);
188 obj
->i2c
->FREQUENCY
= (TWI_FREQUENCY_FREQUENCY_K400
<< TWI_FREQUENCY_FREQUENCY_Pos
);
192 int checkError(i2c_t
*obj
)
194 if (obj
->i2c
->EVENTS_ERROR
== 1) {
195 if (obj
->i2c
->ERRORSRC
& TWI_ERRORSRC_ANACK_Msk
) {
196 obj
->i2c
->EVENTS_ERROR
= 0;
197 obj
->i2c
->TASKS_STOP
= 1;
198 return I2C_ERROR_BUS_BUSY
;
201 obj
->i2c
->EVENTS_ERROR
= 0;
202 obj
->i2c
->TASKS_STOP
= 1;
203 return I2C_ERROR_NO_SLAVE
;
208 int i2c_read(i2c_t
*obj
, int address
, char *data
, int length
, int stop
)
210 int status
, count
, errorResult
;
211 obj
->i2c
->ADDRESS
= (address
>> 1);
212 obj
->i2c
->SHORTS
= 1; // to trigger suspend task when a byte is received
213 obj
->i2c
->EVENTS_RXDREADY
= 0;
214 obj
->i2c
->TASKS_STARTRX
= 1;
216 // Read in all except last byte
217 for (count
= 0; count
< (length
- 1); count
++) {
218 status
= i2c_do_read(obj
, &data
[count
], 0);
220 errorResult
= checkError(obj
);
230 status
= i2c_do_read(obj
, &data
[length
- 1], 1);
235 // If not repeated start, send stop.
237 while (!obj
->i2c
->EVENTS_STOPPED
) {
239 obj
->i2c
->EVENTS_STOPPED
= 0;
244 int i2c_write(i2c_t
*obj
, int address
, const char *data
, int length
, int stop
)
246 int status
, errorResult
;
247 obj
->i2c
->ADDRESS
= (address
>> 1);
248 obj
->i2c
->SHORTS
= 0;
249 obj
->i2c
->TASKS_STARTTX
= 1;
251 for (int i
= 0; i
<length
; i
++) {
252 status
= i2c_do_write(obj
, data
[i
]);
255 errorResult
= checkError(obj
);
263 // If not repeated start, send stop.
266 return I2C_ERROR_NO_SLAVE
;
272 int i2c_byte_read(i2c_t
*obj
, int last
)
277 status
= i2c_do_read(obj
, &data
, last
);
284 int i2c_byte_write(i2c_t
*obj
, int data
)
287 if (!obj
->address_set
) {
288 obj
->address_set
= 1;
289 obj
->i2c
->ADDRESS
= (data
>> 1);
292 obj
->i2c
->EVENTS_RXDREADY
= 0;
293 obj
->i2c
->SHORTS
= 1;
294 obj
->i2c
->TASKS_STARTRX
= 1;
296 obj
->i2c
->SHORTS
= 0;
297 obj
->i2c
->TASKS_STARTTX
= 1;
300 status
= i2c_do_write(obj
, data
);