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.
Revision 0:c2a44165fec8, committed 2014-08-31
- Comitter:
- sibu2
- Date:
- Sun Aug 31 12:52:08 2014 +0000
- Commit message:
- 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.
Changed in this revision
diff -r 000000000000 -r c2a44165fec8 myi2c.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/myi2c.cpp Sun Aug 31 12:52:08 2014 +0000 @@ -0,0 +1,92 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include <stdio.h> +#include "myi2c.h" + +//#if DEVICE_I2C + +namespace mbed { + +myI2C *myI2C::_owner = NULL; + +myI2C::myI2C(PinName sda, PinName scl) : _i2c(), _hz(100000) { + // The init function also set the frequency to 100000 + i2c_init(&_i2c, sda, scl); + + // Used to avoid unnecessary frequency updates + _owner = this; +} + +void myI2C::frequency(int hz) { + _hz = hz; + + // We want to update the frequency even if we are already the bus owners + i2c_frequency(&_i2c, _hz); + + // Updating the frequency of the bus we become the owners of it + _owner = this; +} + +void myI2C::aquire() { + if (_owner != this) { + i2c_frequency(&_i2c, _hz); + _owner = this; + } +} + +// write - Master Transmitter Mode +int myI2C::write(int address, const char* data, int length, bool repeated) { + aquire(); + + int stop = (repeated) ? 0 : 1; + int written = i2c_write(&_i2c, address, data, length, stop); + + return length != written; +} + +int myI2C::write(int data) { + return i2c_byte_write(&_i2c, data); +} + +// read - Master Reciever Mode +int myI2C::read(int address, char* data, int length, bool repeated) { + aquire(); + + int stop = (repeated) ? 0 : 1; + int read = i2c_read(&_i2c, address, data, length, stop); + + return length != read; +} + +int myI2C::read(int ack) { + if (ack) { + return i2c_byte_read(&_i2c, 0); + } else { + return i2c_byte_read(&_i2c, 1); + } +} + +void myI2C::start(void) { + i2c_start(&_i2c); +} + +void myI2C::stop(void) { + i2c_stop(&_i2c); +} + +} // namespace mbed + +//#endif
diff -r 000000000000 -r c2a44165fec8 myi2c.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/myi2c.h Sun Aug 31 12:52:08 2014 +0000 @@ -0,0 +1,144 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBED_MYI2C_H +#define MBED_MYI2C_H + +//#include "platform.h" + +//#if DEVICE_MYI2C + +#include "myi2c_api.h" + +namespace mbed { + +/** An I2C Master, used for communicating with I2C slave devices + * + * Example: + * @code + * // Read from I2C slave at address 0x62 + * + * #include "mbed.h" + * + * I2C i2c(p28, p27); + * + * int main() { + * int address = 0x62; + * char data[2]; + * i2c.read(address, data, 2); + * } + * @endcode + */ +class myI2C { + +public: + enum RxStatus { + NoData, + MasterGeneralCall, + MasterWrite, + MasterRead + }; + + enum Acknowledge { + NoACK = 0, + ACK = 1 + }; + + /** Create an I2C Master interface, connected to the specified pins + * + * @param sda I2C data line pin + * @param scl I2C clock line pin + */ + myI2C(PinName sda, PinName scl); + + /** Set the frequency of the I2C interface + * + * @param hz The bus frequency in hertz + */ + void frequency(int hz); + + /** Read from an I2C slave + * + * Performs a complete read transaction. The bottom bit of + * the address is forced to 1 to indicate a read. + * + * @param address 8-bit I2C slave address [ addr | 1 ] + * @param data Pointer to the byte-array to read data in to + * @param length Number of bytes to read + * @param repeated Repeated start, true - don't send stop at end + * + * @returns + * 0 on success (ack), + * non-0 on failure (nack) + */ + int read(int address, char *data, int length, bool repeated = false); + + /** Read a single byte from the I2C bus + * + * @param ack indicates if the byte is to be acknowledged (1 = acknowledge) + * + * @returns + * the byte read + */ + int read(int ack); + + /** Write to an I2C slave + * + * Performs a complete write transaction. The bottom bit of + * the address is forced to 0 to indicate a write. + * + * @param address 8-bit I2C slave address [ addr | 0 ] + * @param data Pointer to the byte-array data to send + * @param length Number of bytes to send + * @param repeated Repeated start, true - do not send stop at end + * + * @returns + * 0 on success (ack), + * non-0 on failure (nack) + */ + int write(int address, const char *data, int length, bool repeated = false); + + /** Write single byte out on the I2C bus + * + * @param data data to write out on bus + * + * @returns + * '1' if an ACK was received, + * '0' otherwise + */ + int write(int data); + + /** Creates a start condition on the I2C bus + */ + + void start(void); + + /** Creates a stop condition on the I2C bus + */ + void stop(void); + +protected: + void aquire(); + + i2c_t _i2c; + static myI2C *_owner; + int _hz; +}; + +} // namespace mbed + +//#endif + +#endif
diff -r 000000000000 -r c2a44165fec8 myi2c_api.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/myi2c_api.c Sun Aug 31 12:52:08 2014 +0000 @@ -0,0 +1,286 @@ +/* mbed Microcontroller Library + * Copyright (c) 2013 Nordic Semiconductor + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "mbed_assert.h" +#include "myi2c_api.h" +#include "cmsis.h" +#include "pinmap.h" + +static const PinMap PinMap_I2C_SDA[] = { + {p22, I2C_0, 1}, + {p13, I2C_1, 2}, + {NC, NC, 0} +}; + +static const PinMap PinMap_I2C_SCL[] = { + {p21, I2C_0, 1}, + {p15, I2C_1, 2}, + {NC, NC, 0} +}; + +uint8_t addrSet = 0; + +void i2c_interface_enable(i2c_t *obj) +{ + obj->i2c->ENABLE = (TWI_ENABLE_ENABLE_Enabled << TWI_ENABLE_ENABLE_Pos); +} + +void twi_master_init(i2c_t *obj, PinName sda, PinName scl, int frequency) +{ + NRF_GPIO->PIN_CNF[scl] = ((GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos) | + (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) | + (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos) | + (GPIO_PIN_CNF_DRIVE_S0D1 << GPIO_PIN_CNF_DRIVE_Pos) | + (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)); + + NRF_GPIO->PIN_CNF[sda] = ((GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos) | + (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) | + (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos) | + (GPIO_PIN_CNF_DRIVE_S0D1 << GPIO_PIN_CNF_DRIVE_Pos) | + (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)); + + obj->i2c->PSELSCL = scl; + obj->i2c->PSELSDA = sda; + // set default frequency at 100k + i2c_frequency(obj, frequency); + i2c_interface_enable(obj); +} + +void i2c_init(i2c_t *obj, PinName sda, PinName scl) +{ + // determine the SPI to use + I2CName i2c_sda = (I2CName)pinmap_peripheral(sda, PinMap_I2C_SDA); + I2CName i2c_scl = (I2CName)pinmap_peripheral(scl, PinMap_I2C_SCL); + I2CName i2c = (I2CName)pinmap_merge(i2c_sda, i2c_scl); + obj->i2c = (NRF_TWI_Type *)i2c; + + MBED_ASSERT((int)obj->i2c != NC); + + obj->scl = scl; + obj->sda = sda; + obj->i2c->EVENTS_ERROR = 0; + obj->i2c->ENABLE = TWI_ENABLE_ENABLE_Disabled << TWI_ENABLE_ENABLE_Pos; + obj->i2c->POWER = 0; + + for (int i = 0; i<100; i++) { + } + + obj->i2c->POWER = 1; + twi_master_init(obj, sda, scl, 100000); +} + +void i2c_reset(i2c_t *obj) +{ + obj->i2c->EVENTS_ERROR = 0; + obj->i2c->ENABLE = TWI_ENABLE_ENABLE_Disabled << TWI_ENABLE_ENABLE_Pos; + obj->i2c->POWER = 0; + for (int i = 0; i<100; i++) { + } + + obj->i2c->POWER = 1; + twi_master_init(obj, obj->sda, obj->scl, obj->freq); +} + +int i2c_start(i2c_t *obj) +{ + int status = 0; + i2c_reset(obj); + addrSet = 0; + return status; +} + +int i2c_stop(i2c_t *obj) +{ + int timeOut = 100000; + obj->i2c->EVENTS_STOPPED = 0; + // write the stop bit + obj->i2c->TASKS_STOP = 1; + while (!obj->i2c->EVENTS_STOPPED) { + timeOut--; + if (timeOut<0) { + return 1; + } + } + addrSet = 0; + i2c_reset(obj); + return 0; +} + +int i2c_do_write(i2c_t *obj, int value) +{ + int timeOut = 100000; + obj->i2c->TXD = value; + while (!obj->i2c->EVENTS_TXDSENT) { + timeOut--; + if (timeOut<0) { + return 1; + } + } + obj->i2c->EVENTS_TXDSENT = 0; + return 0; +} + +int i2c_do_read(i2c_t *obj, char *data, int last) +{ + int timeOut = 100000; + + if (last) { + obj->i2c->TASKS_STOP = 1; + } + while (!obj->i2c->EVENTS_RXDREADY) { + timeOut--; + if (timeOut<0) { + return 1; + } + } + obj->i2c->EVENTS_RXDREADY = 0; + + *data = obj->i2c->RXD; + + for (int i = 0; i<320; i++) { + } + + obj->i2c->TASKS_RESUME = 1; + + return 0; +} + +void i2c_frequency(i2c_t *obj, int hz) +{ + if (hz<250000) { + obj->freq = 100000; + obj->i2c->FREQUENCY = (TWI_FREQUENCY_FREQUENCY_K100 << TWI_FREQUENCY_FREQUENCY_Pos); + } else if (hz<400000) { + obj->freq = 250000; + obj->i2c->FREQUENCY = (TWI_FREQUENCY_FREQUENCY_K250 << TWI_FREQUENCY_FREQUENCY_Pos); + } else { + obj->freq = 400000; + obj->i2c->FREQUENCY = (TWI_FREQUENCY_FREQUENCY_K400 << TWI_FREQUENCY_FREQUENCY_Pos); + } +} + +int checkError(i2c_t *obj) +{ + if (obj->i2c->EVENTS_ERROR == 1) { + if (obj->i2c->ERRORSRC & TWI_ERRORSRC_ANACK_Msk) { + obj->i2c->EVENTS_ERROR = 0; + obj->i2c->TASKS_STOP = 1; + return I2C_ERROR_BUS_BUSY; + } + + obj->i2c->EVENTS_ERROR = 0; + obj->i2c->TASKS_STOP = 1; + return I2C_ERROR_NO_SLAVE; + } + return 0; +} + +int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) +{ + int status, count, errorResult; + obj->i2c->ADDRESS = (address >> 1); + obj->i2c->SHORTS = 0; + obj->i2c->EVENTS_RXDREADY = 0; + obj->i2c->TASKS_STARTRX = 1; + + // Read in all except last byte + for (count = 0; count < (length - 1); count++) { + status = i2c_do_read(obj, &data[count], 0); + if (status) { + errorResult = checkError(obj); + i2c_reset(obj); + if (errorResult<0) { + return errorResult; + } + return count; + } + } + + // read in last byte + status = i2c_do_read(obj, &data[length - 1], 1); + if (status) { + i2c_reset(obj); + return length - 1; + } + // If not repeated start, send stop. + if (stop) { + while (!obj->i2c->EVENTS_STOPPED) { + } + obj->i2c->EVENTS_STOPPED = 0; + } + return length; +} + +int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop) +{ + int status, errorResult; + obj->i2c->ADDRESS = (address >> 1); + obj->i2c->SHORTS = 0; + obj->i2c->TASKS_STARTTX = 1; + + for (int i = 0; i<length; i++) { + status = i2c_do_write(obj, data[i]); + if (status) { + i2c_reset(obj); + errorResult = checkError(obj); + if (errorResult<0) { + return errorResult; + } + return i; + } + } + + // If not repeated start, send stop. + if (stop) { + if (i2c_stop(obj)) { + return I2C_ERROR_NO_SLAVE; + } + } + return length; +} + +int i2c_byte_read(i2c_t *obj, int last) +{ + char data; + int status; + + status = i2c_do_read(obj, &data, last); + if (status) { + i2c_reset(obj); + } + return data; +} + +int i2c_byte_write(i2c_t *obj, int data) +{ + int status = 0; + if (!addrSet) { + addrSet = 1; + obj->i2c->ADDRESS = (data >> 1); + + if (data & 1) { + obj->i2c->EVENTS_RXDREADY = 0; + obj->i2c->TASKS_STARTRX = 1; + } else { + obj->i2c->TASKS_STARTTX = 1; + } + } else { + status = i2c_do_write(obj, data); + if (status) { + i2c_reset(obj); + } + } + return (1 - status); +}
diff -r 000000000000 -r c2a44165fec8 myi2c_api.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/myi2c_api.h Sun Aug 31 12:52:08 2014 +0000 @@ -0,0 +1,58 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBED_I2C_API_H +#define MBED_I2C_API_H + +#include "device.h" + +//#if DEVICE_I2C + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct i2c_s i2c_t; + +enum { + I2C_ERROR_NO_SLAVE = -1, + I2C_ERROR_BUS_BUSY = -2 +}; + +void i2c_init (i2c_t *obj, PinName sda, PinName scl); +void i2c_frequency (i2c_t *obj, int hz); +int i2c_start (i2c_t *obj); +int i2c_stop (i2c_t *obj); +int i2c_read (i2c_t *obj, int address, char *data, int length, int stop); +int i2c_write (i2c_t *obj, int address, const char *data, int length, int stop); +void i2c_reset (i2c_t *obj); +int i2c_byte_read (i2c_t *obj, int last); +int i2c_byte_write (i2c_t *obj, int data); + +#if DEVICE_I2CSLAVE +void i2c_slave_mode (i2c_t *obj, int enable_slave); +int i2c_slave_receive(i2c_t *obj); +int i2c_slave_read (i2c_t *obj, char *data, int length); +int i2c_slave_write (i2c_t *obj, const char *data, int length); +void i2c_slave_address(i2c_t *obj, int idx, uint32_t address, uint32_t mask); +#endif + +#ifdef __cplusplus +} +#endif + +//#endif + +#endif