Arrow / Mbed OS DAPLink Reset
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers i2c_gpio.c Source File

i2c_gpio.c

Go to the documentation of this file.
00001 /**
00002  * @file    i2c_gpio.c
00003  * @brief   I2C GPIO control for musca PCA9537
00004  *
00005  * DAPLink Interface Firmware
00006  * Copyright (c) 2009-2016, ARM Limited, All Rights Reserved
00007  * SPDX-License-Identifier: Apache-2.0
00008  *
00009  * Licensed under the Apache License, Version 2.0 (the "License"); you may
00010  * not use this file except in compliance with the License.
00011  * You may obtain a copy of the License at
00012  *
00013  * http://www.apache.org/licenses/LICENSE-2.0
00014  *
00015  * Unless required by applicable law or agreed to in writing, software
00016  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
00017  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00018  * See the License for the specific language governing permissions and
00019  * limitations under the License.
00020  */
00021 
00022 #include "string.h"
00023 #include "stdio.h"
00024 #include "stdint.h"
00025 
00026 #include "gpio.h"
00027 #include "utils.h"
00028 #include "i2c_gpio.h"
00029 
00030 // Clock registers
00031 #define I2CGPIO_FREQ    6            // Sets OSC Clock SCL frequency
00032 #define I2CGPIO_WR      0            // Write command
00033 #define I2CGPIO_RD      1            // Read command
00034 #define I2CGPIO_ADDR    0x49         // Default slave address for PCA9537
00035 
00036 /*----------------------------------------------------------------------------
00037   I2C Address + Wr + A
00038  *----------------------------------------------------------------------------*/
00039 void i2c_gpio_addr(unsigned int addr, unsigned int read)
00040 {
00041     unsigned int loop, data;
00042     
00043     // Repeated Start condition (if required after Command)
00044     LPC_GPIO->DIR[PIN_I2C_SCL_PORT] &= ~PIN_I2C_SCL;
00045     delay_us(I2CGPIO_FREQ);
00046     LPC_GPIO->DIR[PIN_I2C_SDA_PORT] &= ~PIN_I2C_SDA;
00047     delay_us(I2CGPIO_FREQ);
00048     
00049     // Start condition 'S' (DATA > CLK)
00050     LPC_GPIO->DIR[PIN_I2C_SDA_PORT] |= PIN_I2C_SDA;
00051     delay_us(I2CGPIO_FREQ);
00052     LPC_GPIO->DIR[PIN_I2C_SCL_PORT] |= PIN_I2C_SCL;
00053     delay_us(I2CGPIO_FREQ);
00054     
00055     // Addr is 7 bits so add Read
00056     data = (addr << 1) & 0xFE;
00057     if (read)
00058         data |= 0x01;
00059     
00060     // Clock out the 8 bits
00061     for (loop = 0; loop < 8; loop++)
00062     {
00063         if (data & (0x80 >> loop))
00064         {
00065             LPC_GPIO->DIR[PIN_I2C_SDA_PORT] &= ~PIN_I2C_SDA;
00066             delay_us(I2CGPIO_FREQ);
00067             LPC_GPIO->DIR[PIN_I2C_SCL_PORT] &= ~PIN_I2C_SCL;
00068             delay_us(I2CGPIO_FREQ);
00069             LPC_GPIO->DIR[PIN_I2C_SCL_PORT] |= PIN_I2C_SCL;
00070             delay_us(I2CGPIO_FREQ);
00071         }
00072         else
00073         {
00074             LPC_GPIO->DIR[PIN_I2C_SDA_PORT] |= PIN_I2C_SDA;
00075             delay_us(I2CGPIO_FREQ);
00076             LPC_GPIO->DIR[PIN_I2C_SCL_PORT] &= ~PIN_I2C_SCL;
00077             delay_us(I2CGPIO_FREQ);
00078             LPC_GPIO->DIR[PIN_I2C_SCL_PORT] |= PIN_I2C_SCL;
00079             delay_us(I2CGPIO_FREQ);
00080         }
00081     }
00082 
00083     // Set data low
00084     delay_us(I2CGPIO_FREQ);
00085     LPC_GPIO->DIR[PIN_I2C_SDA_PORT] |= PIN_I2C_SDA;
00086     delay_us(I2CGPIO_FREQ);
00087     
00088     // Transmission clock 'A'
00089     LPC_GPIO->DIR[PIN_I2C_SCL_PORT] &= ~PIN_I2C_SCL;
00090     delay_us(I2CGPIO_FREQ);
00091     LPC_GPIO->DIR[PIN_I2C_SCL_PORT] |= PIN_I2C_SCL;
00092     delay_us(I2CGPIO_FREQ);
00093 }
00094 
00095 /*----------------------------------------------------------------------------
00096   I2C Command + A
00097  *----------------------------------------------------------------------------*/
00098 void i2c_gpio_cmd(unsigned int cmd)
00099 {
00100     unsigned int loop;
00101     
00102     // Clock out the 8 bits
00103     for (loop = 0; loop < 8; loop++)
00104     {
00105         if (cmd & (0x80 >> loop))
00106         {
00107             LPC_GPIO->DIR[PIN_I2C_SDA_PORT] &= ~PIN_I2C_SDA;
00108             delay_us(I2CGPIO_FREQ);
00109             LPC_GPIO->DIR[PIN_I2C_SCL_PORT] &= ~PIN_I2C_SCL;
00110             delay_us(I2CGPIO_FREQ);
00111             LPC_GPIO->DIR[PIN_I2C_SCL_PORT] |= PIN_I2C_SCL;
00112             delay_us(I2CGPIO_FREQ);
00113         }
00114         else
00115         {
00116             LPC_GPIO->DIR[PIN_I2C_SDA_PORT] |= PIN_I2C_SDA;
00117             delay_us(I2CGPIO_FREQ);
00118             LPC_GPIO->DIR[PIN_I2C_SCL_PORT] &= ~PIN_I2C_SCL;
00119             delay_us(I2CGPIO_FREQ);
00120             LPC_GPIO->DIR[PIN_I2C_SCL_PORT] |= PIN_I2C_SCL;
00121             delay_us(I2CGPIO_FREQ);
00122         }
00123     }
00124 
00125     // Set data low
00126     delay_us(I2CGPIO_FREQ);
00127     LPC_GPIO->DIR[PIN_I2C_SDA_PORT] |= PIN_I2C_SDA;
00128     delay_us(I2CGPIO_FREQ);
00129     
00130     // Transmission clock 'A'
00131     LPC_GPIO->DIR[PIN_I2C_SCL_PORT] &= ~PIN_I2C_SCL;
00132     delay_us(I2CGPIO_FREQ);
00133     LPC_GPIO->DIR[PIN_I2C_SCL_PORT] |= PIN_I2C_SCL;
00134     delay_us(I2CGPIO_FREQ);
00135 }
00136 
00137 /*----------------------------------------------------------------------------
00138   I2C Write Data + A + P
00139  *----------------------------------------------------------------------------*/
00140 void i2c_gpio_write(unsigned int data)
00141 {
00142     unsigned int loop;
00143     
00144     // Clock out the 8 bits
00145     for (loop = 0; loop < 8; loop++)
00146     {
00147         if (data & (0x80 >> loop))
00148         {
00149             LPC_GPIO->DIR[PIN_I2C_SDA_PORT] &= ~PIN_I2C_SDA;
00150             delay_us(I2CGPIO_FREQ);
00151             LPC_GPIO->DIR[PIN_I2C_SCL_PORT] &= ~PIN_I2C_SCL;
00152             delay_us(I2CGPIO_FREQ);
00153             LPC_GPIO->DIR[PIN_I2C_SCL_PORT] |= PIN_I2C_SCL;
00154             delay_us(I2CGPIO_FREQ);
00155         }
00156         else
00157         {
00158             LPC_GPIO->DIR[PIN_I2C_SDA_PORT] |= PIN_I2C_SDA;
00159             delay_us(I2CGPIO_FREQ);
00160             LPC_GPIO->DIR[PIN_I2C_SCL_PORT] &= ~PIN_I2C_SCL;
00161             delay_us(I2CGPIO_FREQ);
00162             LPC_GPIO->DIR[PIN_I2C_SCL_PORT] |= PIN_I2C_SCL;
00163             delay_us(I2CGPIO_FREQ);
00164         }
00165     }
00166 
00167     // Set data low
00168     delay_us(I2CGPIO_FREQ);
00169     LPC_GPIO->DIR[PIN_I2C_SDA_PORT] |= PIN_I2C_SDA;
00170     delay_us(I2CGPIO_FREQ);
00171     
00172     // Transmission clock 'A'
00173     LPC_GPIO->DIR[PIN_I2C_SCL_PORT] &= ~PIN_I2C_SCL;
00174     delay_us(I2CGPIO_FREQ);
00175     LPC_GPIO->DIR[PIN_I2C_SCL_PORT] |= PIN_I2C_SCL;
00176     delay_us(I2CGPIO_FREQ);
00177     
00178     // Stop condition 'P'
00179     LPC_GPIO->DIR[PIN_I2C_SCL_PORT] &= ~PIN_I2C_SCL;
00180     delay_us(I2CGPIO_FREQ);
00181     LPC_GPIO->DIR[PIN_I2C_SDA_PORT] &= ~PIN_I2C_SDA;
00182     delay_us(I2CGPIO_FREQ);
00183 }
00184 
00185 /*----------------------------------------------------------------------------
00186   I2C Read Data + A + P
00187  *----------------------------------------------------------------------------*/
00188 void i2c_gpio_read(unsigned int *data, unsigned int ack)
00189 {
00190     unsigned int loop;
00191     
00192     // Set SDA high (O/D) and allow PCA9537 to drive SDA
00193     LPC_GPIO->DIR[PIN_I2C_SDA_PORT] &= ~PIN_I2C_SDA;
00194     delay_us(I2CGPIO_FREQ);
00195     
00196     // Clock in the 8 bits
00197     *data = 0;
00198     for (loop = 0; loop < 8; loop++)
00199     {
00200         LPC_GPIO->DIR[PIN_I2C_SCL_PORT] &= ~PIN_I2C_SCL;
00201         delay_us(I2CGPIO_FREQ);
00202         if (LPC_GPIO->DIR[PIN_I2C_SDA_PORT] & PIN_I2C_SDA)
00203             *data &= ~(0x80 >> loop);
00204         LPC_GPIO->DIR[PIN_I2C_SCL_PORT] |= PIN_I2C_SCL;
00205         delay_us(I2CGPIO_FREQ);
00206     }
00207 
00208     // Set data for acknowledge
00209     delay_us(I2CGPIO_FREQ);
00210     if (ack)
00211         LPC_GPIO->DIR[PIN_I2C_SDA_PORT] |= PIN_I2C_SDA;
00212     else
00213         LPC_GPIO->DIR[PIN_I2C_SDA_PORT] &= ~PIN_I2C_SDA;
00214     delay_us(I2CGPIO_FREQ);
00215         
00216     // Transmission clock 'A'
00217     LPC_GPIO->DIR[PIN_I2C_SCL_PORT] &= ~PIN_I2C_SCL;
00218     delay_us(I2CGPIO_FREQ);
00219     LPC_GPIO->DIR[PIN_I2C_SCL_PORT] |= PIN_I2C_SCL;
00220     delay_us(I2CGPIO_FREQ);
00221 
00222     // End of acknowledge
00223     LPC_GPIO->DIR[PIN_I2C_SDA_PORT] |= PIN_I2C_SDA;
00224     delay_us(I2CGPIO_FREQ);
00225     
00226     // Stop condition 'P'
00227     LPC_GPIO->DIR[PIN_I2C_SCL_PORT] &= ~PIN_I2C_SCL;
00228     delay_us(I2CGPIO_FREQ);
00229     LPC_GPIO->DIR[PIN_I2C_SDA_PORT] &= ~PIN_I2C_SDA;
00230     delay_us(I2CGPIO_FREQ);
00231 }
00232 
00233 /*----------------------------------------------------------------------------
00234   I2C Write byte
00235  *----------------------------------------------------------------------------*/
00236 void i2c_gpio_wbyte(unsigned int cmd, unsigned int data)
00237 {
00238     // Set slave address write
00239     i2c_gpio_addr(I2CGPIO_ADDR, I2CGPIO_WR);
00240     // Set command
00241     i2c_gpio_cmd(cmd);
00242     // Write the data
00243     i2c_gpio_write(data);
00244 }
00245 
00246 /*----------------------------------------------------------------------------
00247   I2C Read byte
00248  *----------------------------------------------------------------------------*/
00249 void i2c_gpio_rbyte(unsigned int cmd, unsigned int *data)
00250 {
00251     // Set slave address write
00252     i2c_gpio_addr(I2CGPIO_ADDR, I2CGPIO_WR);
00253     // Set command
00254     i2c_gpio_cmd(cmd);
00255     
00256     // Set slave address write
00257     i2c_gpio_addr(I2CGPIO_ADDR, I2CGPIO_RD);
00258     // Read the data
00259     i2c_gpio_read(data, 0);
00260 }
00261 
00262 // end of i2c_gpio.c