TEAMUSB / mbed-src

Dependents:   SPI_slave_frdm

Fork of mbed-src by mbed official

Revision:
337:6ed01c00b962
Child:
350:a00142a134db
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/targets/hal/TARGET_NXP/TARGET_LPC82X/i2c_api.c	Mon Oct 06 10:00:08 2014 +0100
@@ -0,0 +1,358 @@
+/* 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 <stdlib.h>
+#include <string.h>
+
+#include "i2c_api.h"
+#include "cmsis.h"
+#include "pinmap.h"
+
+#include "rom_i2c_8xx.h"
+
+#if DEVICE_I2C
+
+typedef struct ROM_API {
+    const uint32_t    unused[5];
+    const I2CD_API_T  *pI2CD;    /*!< I2C driver routines functions table */
+} LPC_ROM_API_T;
+
+
+/* Pointer to ROM API function address */
+#define LPC_ROM_API_BASE_LOC    0x1FFF1FF8UL
+#define LPC_ROM_API             (*(LPC_ROM_API_T * *) LPC_ROM_API_BASE_LOC)
+
+/* Pointer to @ref I2CD_API_T functions in ROM */
+#define LPC_I2CD_API            ((LPC_ROM_API)->pI2CD)
+
+static const SWM_Map SWM_I2C_SDA[] = {
+    { 9,  8},
+    { 9, 24},
+    {10,  8},
+};
+
+static const SWM_Map SWM_I2C_SCL[] = {
+    { 9, 16},
+    {10,  0},
+    {10, 16},
+};
+
+
+static int i2c_used = 0;
+static uint8_t repeated_start = 0;
+static uint32_t *i2c_buffer;
+
+#define I2C_DAT(x)          (x->i2c->MSTDAT)
+#define I2C_STAT(x)         ((x->i2c->STAT >> 1) & (0x07))
+
+static inline int i2c_status(i2c_t *obj)
+{
+    return I2C_STAT(obj);
+}
+
+// Wait until the Serial Interrupt (SI) is set
+static int i2c_wait_SI(i2c_t *obj)
+{
+    volatile int timeout = 0;
+    while (!(obj->i2c->STAT & (1 << 0))) {
+        timeout++;
+        if (timeout > 100000) return -1;
+    }
+    return 0;
+}
+
+static inline void i2c_interface_enable(i2c_t *obj)
+{
+    obj->i2c->CFG |= 1;
+}
+
+static inline void i2c_power_enable(int ch)
+{
+    switch(ch) {
+        case 0:
+            LPC_SYSCON->SYSAHBCLKCTRL |=  (1 << 5);
+            LPC_SYSCON->PRESETCTRL    &= ~(1 << 6);
+            LPC_SYSCON->PRESETCTRL    |=  (1 << 6);
+            break;
+        case 1:
+        case 2:
+        case 3:
+            LPC_SYSCON->SYSAHBCLKCTRL |=  (1 << (20 + ch));
+            LPC_SYSCON->PRESETCTRL    &= ~(1 << (13 + ch));
+            LPC_SYSCON->PRESETCTRL    |=  (1 << (13 + ch));
+            break;
+        default:
+            break;
+    }
+}
+
+
+static int get_available_i2c(void) {
+    int i;
+    for (i=0; i<3; i++) {
+        if ((i2c_used & (1 << i)) == 0)
+            return i+1;
+    }
+    return -1;
+}
+
+void i2c_init(i2c_t *obj, PinName sda, PinName scl)
+{
+    const SWM_Map *swm;
+    uint32_t regVal;
+    int i2c_ch = 0;
+
+    if (sda == I2C_SDA && scl == I2C_SCL) {
+        LPC_SWM->PINENABLE0 &= ~(0x3 << 11);
+    }
+    else {
+        i2c_ch = get_available_i2c();
+        if (i2c_ch == -1)
+            return;
+
+        swm = &SWM_I2C_SDA[i2c_ch - 1];
+        regVal = LPC_SWM->PINASSIGN[swm->n] & ~(0xFF << swm->offset);
+        LPC_SWM->PINASSIGN[swm->n] = regVal |  ((sda >> PIN_SHIFT) << swm->offset);
+
+        swm = &SWM_I2C_SCL[i2c_ch - 1];
+        regVal = LPC_SWM->PINASSIGN[swm->n] & ~(0xFF << swm->offset);
+        LPC_SWM->PINASSIGN[swm->n] = regVal |  ((scl >> PIN_SHIFT) << swm->offset);
+    }
+
+    switch(i2c_ch) {
+        case 0:
+            obj->i2c = (LPC_I2C0_Type *)LPC_I2C0;
+            break;
+        case 1:
+            obj->i2c = (LPC_I2C0_Type *)LPC_I2C1;
+            break;
+        case 2:
+            obj->i2c = (LPC_I2C0_Type *)LPC_I2C2;
+            break;
+        case 3:
+            obj->i2c = (LPC_I2C0_Type *)LPC_I2C3;
+            break;
+        default:
+            break;
+    }
+
+    // enable power
+    i2c_power_enable(i2c_ch);
+    i2c_interface_enable(obj);
+
+    uint32_t size_in_bytes = LPC_I2CD_API->i2c_get_mem_size();
+    i2c_buffer = malloc(size_in_bytes);
+    obj->handler = LPC_I2CD_API->i2c_setup((uint32_t)(obj->i2c), i2c_buffer);
+    LPC_I2CD_API->i2c_set_bitrate(obj->handler, SystemCoreClock, 100000);
+    LPC_I2CD_API->i2c_set_timeout(obj->handler, 100000);
+}
+
+inline int i2c_start(i2c_t *obj)
+{
+    int status = 0;
+    if (repeated_start) {
+        obj->i2c->MSTCTL = (1 << 1) | (1 << 0);
+        repeated_start = 0;
+    } else {
+        obj->i2c->MSTCTL = (1 << 1);
+    }
+    return status;
+}
+
+inline int i2c_stop(i2c_t *obj)
+{
+    volatile int timeout = 0;
+
+    obj->i2c->MSTCTL = (1 << 2) | (1 << 0);
+    while ((obj->i2c->STAT & ((1 << 0) | (7 << 1))) != ((1 << 0) | (0 << 1))) {
+        timeout ++;
+        if (timeout > 100000) return 1;
+    }
+
+    return 0;
+}
+
+static inline int i2c_do_write(i2c_t *obj, int value, uint8_t addr)
+{
+    // write the data
+    I2C_DAT(obj) = value;
+
+    if (!addr)
+        obj->i2c->MSTCTL = (1 << 0);
+
+    // wait and return status
+    i2c_wait_SI(obj);
+    return i2c_status(obj);
+}
+
+static inline int i2c_do_read(i2c_t *obj, int last)
+{
+    // wait for it to arrive
+    i2c_wait_SI(obj);
+    if (!last)
+        obj->i2c->MSTCTL = (1 << 0);
+
+    // return the data
+    return (I2C_DAT(obj) & 0xFF);
+}
+
+void i2c_frequency(i2c_t *obj, int hz)
+{
+    LPC_I2CD_API->i2c_set_bitrate(obj->handler, SystemCoreClock, 100000);
+}
+
+int i2c_read(i2c_t *obj, int address, char *data, int length, int stop)
+{
+    ErrorCode_t err;
+    I2C_PARAM_T i2c_param;
+    I2C_RESULT_T i2c_result;
+
+    uint8_t *buf = malloc(length + 1);
+    buf[0] = (uint8_t)((address | 0x01) & 0xFF);
+    i2c_param.buffer_ptr_rec = buf;
+    i2c_param.num_bytes_rec = length + 1;
+    i2c_param.stop_flag = stop;
+    err = LPC_I2CD_API->i2c_master_receive_poll(obj->handler, &i2c_param, &i2c_result);
+    memcpy(data, buf + 1, i2c_result.n_bytes_recd);
+    free(buf);
+    if (err == 0)
+        return i2c_result.n_bytes_recd;
+    else
+        return -1;
+}
+
+int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop)
+{
+    ErrorCode_t err;
+    I2C_PARAM_T i2c_param;
+    I2C_RESULT_T i2c_result;
+
+    uint8_t *buf = malloc(length + 1);
+    buf[0] = (uint8_t)(address & 0xFE);
+    memcpy(buf + 1, data, length);
+    i2c_param.buffer_ptr_send = buf;
+    i2c_param.num_bytes_send = length + 1;
+    i2c_param.stop_flag = stop;
+    err = LPC_I2CD_API->i2c_master_transmit_poll(obj->handler, &i2c_param, &i2c_result);
+    free(buf);
+    if (err == 0)
+        return i2c_result.n_bytes_sent;
+    else
+        return -1;
+}
+
+void i2c_reset(i2c_t *obj)
+{
+    i2c_stop(obj);
+}
+
+int i2c_byte_read(i2c_t *obj, int last)
+{
+    return (i2c_do_read(obj, last) & 0xFF);
+}
+
+int i2c_byte_write(i2c_t *obj, int data)
+{
+    int ack;
+    int status = i2c_do_write(obj, (data & 0xFF), 0);
+
+    switch(status) {
+        case 2:
+            ack = 1;
+            break;
+        default:
+            ack = 0;
+            break;
+    }
+
+    return ack;
+}
+
+#if DEVICE_I2CSLAVE
+
+	void i2c_slave_mode(i2c_t *obj, int enable_slave)
+{
+    obj->handler = LPC_I2CD_API->i2c_setup((uint32_t)(obj->i2c), i2c_buffer);
+    if (enable_slave != 0) {
+        obj->i2c->CFG &= ~(1 << 0);
+        obj->i2c->CFG |= (1 << 1);
+    }
+    else {
+        obj->i2c->CFG |= (1 << 0);
+        obj->i2c->CFG &= ~(1 << 1);
+    }
+
+}
+
+int i2c_slave_receive(i2c_t *obj)
+{
+    CHIP_I2C_MODE_T mode;
+    int ret;
+    
+    mode = LPC_I2CD_API->i2c_get_status(obj->handler);
+    switch(mode) {
+        case SLAVE_SEND:
+            ret = 1;
+            break;
+        case SLAVE_RECEIVE:
+            ret = 3;
+            break;
+        case MASTER_SEND:
+        case MASTER_RECEIVE:
+        default:
+            ret = 0;
+            break;
+    }
+    return ret;
+}
+
+int i2c_slave_read(i2c_t *obj, char *data, int length)
+{
+    ErrorCode_t err;
+    I2C_PARAM_T i2c_param;
+    I2C_RESULT_T i2c_result;
+
+    i2c_param.buffer_ptr_send = (uint8_t *)data;
+    i2c_param.num_bytes_send = length;
+    err = LPC_I2CD_API->i2c_slave_transmit_poll(obj->handler, &i2c_param, &i2c_result);
+    if (err == 0)
+        return i2c_result.n_bytes_sent;
+    else
+        return -1;
+}
+
+int i2c_slave_write(i2c_t *obj, const char *data, int length)
+{
+    ErrorCode_t err;
+    I2C_PARAM_T i2c_param;
+    I2C_RESULT_T i2c_result;
+
+    i2c_param.buffer_ptr_rec = (uint8_t *)data;
+    i2c_param.num_bytes_rec = length;
+    err = LPC_I2CD_API->i2c_slave_receive_poll(obj->handler, &i2c_param, &i2c_result);
+    if (err == 0)
+        return i2c_result.n_bytes_recd;
+    else
+        return -1;
+}
+
+void i2c_slave_address(i2c_t *obj, int idx, uint32_t address, uint32_t mask)
+{
+    LPC_I2CD_API->i2c_set_slave_addr(obj->handler, address, 0);
+}
+
+#endif
+
+#endif