MacroRat / MouseCode

Dependencies:   ITG3200 QEI

Revision:
18:6a4db94011d3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-dev/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/api/i2c_api.c	Sun May 14 23:18:57 2017 +0000
@@ -0,0 +1,286 @@
+/* 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 "mbed_assert.h"
+#include "i2c_api.h"
+
+#if DEVICE_I2C
+
+#include "cmsis.h"
+#include "pinmap.h"
+#include "fsl_i2c.h"
+#include "fsl_port.h"
+#include "peripheral_clock_defines.h"
+#include "PeripheralPins.h"
+
+/* 7 bit IIC addr - R/W flag not included */
+static int i2c_address = 0;
+/* Array of I2C peripheral base address. */
+static I2C_Type *const i2c_addrs[] = I2C_BASE_PTRS;
+/* Array of I2C bus clock frequencies */
+static clock_name_t const i2c_clocks[] = I2C_CLOCK_FREQS;
+
+void i2c_init(i2c_t *obj, PinName sda, PinName scl)
+{
+    uint32_t i2c_sda = pinmap_peripheral(sda, PinMap_I2C_SDA);
+    uint32_t i2c_scl = pinmap_peripheral(scl, PinMap_I2C_SCL);
+    obj->instance = pinmap_merge(i2c_sda, i2c_scl);
+    obj->next_repeated_start = 0;
+    MBED_ASSERT((int)obj->instance != NC);
+
+    i2c_master_config_t master_config;
+
+    I2C_MasterGetDefaultConfig(&master_config);
+    I2C_MasterInit(i2c_addrs[obj->instance], &master_config, CLOCK_GetFreq(i2c_clocks[obj->instance]));
+    I2C_EnableInterrupts(i2c_addrs[obj->instance], kI2C_GlobalInterruptEnable);
+
+    pinmap_pinout(sda, PinMap_I2C_SDA);
+    pinmap_pinout(scl, PinMap_I2C_SCL);
+
+#if defined(FSL_FEATURE_PORT_HAS_OPEN_DRAIN) && FSL_FEATURE_PORT_HAS_OPEN_DRAIN
+    PORT_Type *port_addrs[] = PORT_BASE_PTRS;
+    PORT_Type *base = port_addrs[sda >> GPIO_PORT_SHIFT];
+
+    base->PCR[sda & 0xFF] |= PORT_PCR_ODE_MASK;
+    base->PCR[scl & 0xFF] |= PORT_PCR_ODE_MASK;
+#endif
+}
+
+int i2c_start(i2c_t *obj)
+{
+    I2C_Type *base = i2c_addrs[obj->instance];
+    uint32_t statusFlags = I2C_MasterGetStatusFlags(base);
+
+    /* Return an error if the bus is already in use. */
+    if (statusFlags & kI2C_BusBusyFlag) {
+        return 1;
+    }
+    /* Send the START signal. */
+    base->C1 |= I2C_C1_MST_MASK | I2C_C1_TX_MASK;
+
+#if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFERING) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFERING
+    while (!(base->S2 & I2C_S2_EMPTY_MASK))
+    {
+    }
+#endif /* FSL_FEATURE_I2C_HAS_DOUBLE_BUFFERING */
+
+    return 0;
+}
+
+int i2c_stop(i2c_t *obj)
+{
+    obj->next_repeated_start = 0;
+    if (I2C_MasterStop(i2c_addrs[obj->instance]) != kStatus_Success) {
+        return 1;
+    }
+
+    return 0;
+}
+
+void i2c_frequency(i2c_t *obj, int hz)
+{
+    uint32_t busClock;
+
+    busClock = CLOCK_GetFreq(i2c_clocks[obj->instance]);
+    I2C_MasterSetBaudRate(i2c_addrs[obj->instance], hz, busClock);
+}
+
+int i2c_read(i2c_t *obj, int address, char *data, int length, int stop)
+{
+    I2C_Type *base = i2c_addrs[obj->instance];
+    i2c_master_transfer_t master_xfer;
+
+    i2c_address = address >> 1;
+    memset(&master_xfer, 0, sizeof(master_xfer));
+    master_xfer.slaveAddress = address >> 1;
+    master_xfer.direction = kI2C_Read;
+    master_xfer.data = (uint8_t *)data;
+    master_xfer.dataSize = length;
+    if (obj->next_repeated_start) {
+        master_xfer.flags |= kI2C_TransferRepeatedStartFlag;
+    }
+    if (!stop) {
+        master_xfer.flags |= kI2C_TransferNoStopFlag;
+    }
+    obj->next_repeated_start = master_xfer.flags & kI2C_TransferNoStopFlag ? 1 : 0;
+
+    /* The below function will issue a STOP signal at the end of the transfer.
+     * This is required by the hardware in order to receive the last byte
+     */
+    if (I2C_MasterTransferBlocking(base, &master_xfer) != kStatus_Success) {
+        return I2C_ERROR_NO_SLAVE;
+    }
+
+    return length;
+}
+
+int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop)
+{
+    I2C_Type *base = i2c_addrs[obj->instance];
+    i2c_master_transfer_t master_xfer;
+
+    if (length == 0) {
+        if (I2C_MasterStart(base, address >> 1, kI2C_Write) != kStatus_Success) {
+            return I2C_ERROR_NO_SLAVE;
+        }
+
+        while (!(base->S & kI2C_IntPendingFlag)) {
+        }
+
+        base->S = kI2C_IntPendingFlag;
+
+        if (base->S & kI2C_ReceiveNakFlag) {
+            i2c_stop(obj);
+            return I2C_ERROR_NO_SLAVE;
+        } else {
+            i2c_stop(obj);
+            return length;
+        }
+    }
+
+    memset(&master_xfer, 0, sizeof(master_xfer));
+    master_xfer.slaveAddress = address >> 1;
+    master_xfer.direction = kI2C_Write;
+    master_xfer.data = (uint8_t *)data;
+    master_xfer.dataSize = length;
+    if (obj->next_repeated_start) {
+        master_xfer.flags |= kI2C_TransferRepeatedStartFlag;
+    }
+    if (!stop) {
+        master_xfer.flags |= kI2C_TransferNoStopFlag;
+    }
+    obj->next_repeated_start = master_xfer.flags & kI2C_TransferNoStopFlag ? 1 : 0;
+
+    if (I2C_MasterTransferBlocking(base, &master_xfer) != kStatus_Success) {
+        return I2C_ERROR_NO_SLAVE;
+    }
+
+    return length;
+}
+
+void i2c_reset(i2c_t *obj)
+{
+    i2c_stop(obj);
+}
+
+int i2c_byte_read(i2c_t *obj, int last)
+{
+    uint8_t data;
+    I2C_Type *base = i2c_addrs[obj->instance];
+    i2c_master_transfer_t master_xfer;
+
+    memset(&master_xfer, 0, sizeof(master_xfer));
+    master_xfer.slaveAddress = i2c_address;
+    master_xfer.direction = kI2C_Read;
+    master_xfer.data = &data;
+    master_xfer.dataSize = 1;
+
+    /* The below function will issue a STOP signal at the end of the transfer.
+     * This is required by the hardware in order to receive the last byte
+     */
+    if (I2C_MasterTransferBlocking(base, &master_xfer) != kStatus_Success) {
+        return I2C_ERROR_NO_SLAVE;
+    }
+    return data;
+}
+
+int i2c_byte_write(i2c_t *obj, int data)
+{
+    status_t ret_value;
+#if FSL_I2C_DRIVER_VERSION > MAKE_VERSION(2, 0, 1)
+    ret_value = I2C_MasterWriteBlocking(i2c_addrs[obj->instance], (uint8_t *)(&data), 1, kI2C_TransferNoStopFlag);
+#else
+    ret_value = I2C_MasterWriteBlocking(i2c_addrs[obj->instance], (uint8_t *)(&data), 1);
+#endif
+
+    if (ret_value == kStatus_Success) {
+        return 1;
+    } else if (ret_value == kStatus_I2C_Nak) {
+        return 0;
+    } else {
+        return 2;
+    }
+}
+
+
+#if DEVICE_I2CSLAVE
+void i2c_slave_mode(i2c_t *obj, int enable_slave)
+{
+    i2c_slave_config_t slave_config;
+    I2C_SlaveGetDefaultConfig(&slave_config);
+    slave_config.slaveAddress = 0;
+    slave_config.enableSlave = (bool)enable_slave;
+#if FSL_I2C_DRIVER_VERSION > MAKE_VERSION(2, 0, 1)
+    I2C_SlaveInit(i2c_addrs[obj->instance], &slave_config, CLOCK_GetFreq(i2c_clocks[obj->instance]));
+#else
+    I2C_SlaveInit(i2c_addrs[obj->instance], &slave_config);
+#endif
+}
+
+int i2c_slave_receive(i2c_t *obj)
+{
+    uint32_t status_flags = I2C_SlaveGetStatusFlags(i2c_addrs[obj->instance]);
+
+    if (status_flags & kI2C_AddressMatchFlag) {
+        if (status_flags & kI2C_TransferDirectionFlag) {
+            // read addressed
+            return 1;
+        } else {
+            // write addressed
+            return 3;
+        }
+    } else {
+        // slave not addressed
+        return 0;
+    }
+}
+
+int i2c_slave_read(i2c_t *obj, char *data, int length)
+{
+    I2C_Type *base = i2c_addrs[obj->instance];
+
+    if (base->S & kI2C_AddressMatchFlag) {
+        /* Slave receive, master writing to slave. */
+        base->C1 &= ~(I2C_C1_TX_MASK | I2C_C1_TXAK_MASK);
+        /* Read dummy to release the bus. */
+        base->D;
+    }
+
+    I2C_SlaveReadBlocking(base, (uint8_t *)data, length);
+
+    return length;
+}
+
+int i2c_slave_write(i2c_t *obj, const char *data, int length)
+{
+    I2C_Type *base = i2c_addrs[obj->instance];
+
+    I2C_SlaveWriteBlocking(base, (uint8_t *)data, length);
+
+    /* Switch to receive mode. */
+    base->C1 &= ~(I2C_C1_TX_MASK | I2C_C1_TXAK_MASK);
+    /* Read dummy to release bus. */
+    base->D;
+
+    return length;
+}
+
+void i2c_slave_address(i2c_t *obj, int idx, uint32_t address, uint32_t mask)
+{
+    i2c_addrs[obj->instance]->A1 = address & 0xfe;
+}
+#endif
+
+#endif