Gordons Projects

--> Projects Top-Level GIT

Minor changes to the files and removed a bit of debug.
[wiringPi] / wiringPi / wiringPiI2C.c
1 /*
2  * wiringPiI2C.c:
3  *      Simplified I2C access routines
4  *      Copyright (c) 2013 Gordon Henderson
5  ***********************************************************************
6  * This file is part of wiringPi:
7  *      https://projects.drogon.net/raspberry-pi/wiringpi/
8  *
9  *    wiringPi is free software: you can redistribute it and/or modify
10  *    it under the terms of the GNU Lesser General Public License as
11  *    published by the Free Software Foundation, either version 3 of the
12  *    License, or (at your option) any later version.
13  *
14  *    wiringPi is distributed in the hope that it will be useful,
15  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *    GNU Lesser General Public License for more details.
18  *
19  *    You should have received a copy of the GNU Lesser General Public
20  *    License along with wiringPi.
21  *    If not, see <http://www.gnu.org/licenses/>.
22  ***********************************************************************
23  */
24
25 /*
26  * Notes:
27  *      The Linux I2C code is actually the same (almost) as the SMBus code.
28  *      SMBus is System Management Bus - and in essentially I2C with some
29  *      additional functionality added, and stricter controls on the electrical
30  *      specifications, etc. however I2C does work well with it and the
31  *      protocols work over both.
32  *
33  *      I'm directly including the SMBus functions here as some Linux distros
34  *      lack the correct header files, and also some header files are GPLv2
35  *      rather than the LGPL that wiringPi is released under - presumably because
36  *      originally no-one expected I2C/SMBus to be used outside the kernel -
37  *      however enter the Raspberry Pi with people now taking directly to I2C
38  *      devices without going via the kernel...
39  *
40  *      This may ultimately reduce the flexibility of this code, but it won't be
41  *      hard to maintain it and keep it current, should things change.
42  *
43  *      Information here gained from: kernel/Documentation/i2c/dev-interface
44  *      as well as other online resources.
45  *********************************************************************************
46  */
47
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <stdint.h>
51 #include <errno.h>
52 #include <string.h>
53 #include <fcntl.h>
54 #include <sys/ioctl.h>
55
56 #include "wiringPi.h"
57 #include "wiringPiI2C.h"
58
59 // I2C definitions
60
61 #define I2C_SLAVE       0x0703
62 #define I2C_SMBUS       0x0720  /* SMBus-level access */
63
64 #define I2C_SMBUS_READ  1
65 #define I2C_SMBUS_WRITE 0
66
67 // SMBus transaction types
68
69 #define I2C_SMBUS_QUICK             0
70 #define I2C_SMBUS_BYTE              1
71 #define I2C_SMBUS_BYTE_DATA         2 
72 #define I2C_SMBUS_WORD_DATA         3
73 #define I2C_SMBUS_PROC_CALL         4
74 #define I2C_SMBUS_BLOCK_DATA        5
75 #define I2C_SMBUS_I2C_BLOCK_BROKEN  6
76 #define I2C_SMBUS_BLOCK_PROC_CALL   7           /* SMBus 2.0 */
77 #define I2C_SMBUS_I2C_BLOCK_DATA    8
78
79 // SMBus messages
80
81 #define I2C_SMBUS_BLOCK_MAX     32      /* As specified in SMBus standard */    
82 #define I2C_SMBUS_I2C_BLOCK_MAX 32      /* Not specified but we use same structure */
83
84 // Structures used in the ioctl() calls
85
86 union i2c_smbus_data
87 {
88   uint8_t  byte ;
89   uint16_t word ;
90   uint8_t  block [I2C_SMBUS_BLOCK_MAX + 2] ;    // block [0] is used for length + one more for PEC
91 } ;
92
93 struct i2c_smbus_ioctl_data
94 {
95   char read_write ;
96   uint8_t command ;
97   int size ;
98   union i2c_smbus_data *data ;
99 } ;
100
101 static inline int i2c_smbus_access (int fd, char rw, uint8_t command, int size, union i2c_smbus_data *data)
102 {
103   struct i2c_smbus_ioctl_data args ;
104
105   args.read_write = rw ;
106   args.command    = command ;
107   args.size       = size ;
108   args.data       = data ;
109   return ioctl (fd, I2C_SMBUS, &args) ;
110 }
111
112
113 /*
114  * wiringPiI2CRead:
115  *      Simple device read
116  *********************************************************************************
117  */
118
119 int wiringPiI2CRead (int fd)
120 {
121   union i2c_smbus_data data ;
122
123   if (i2c_smbus_access (fd, I2C_SMBUS_READ, 0, I2C_SMBUS_BYTE, &data))
124     return -1 ;
125   else
126     return data.byte & 0xFF ;
127 }
128
129
130 /*
131  * wiringPiI2CReadReg8: wiringPiI2CReadReg16:
132  *      Read an 8 or 16-bit value from a regsiter on the device
133  *********************************************************************************
134  */
135
136 int wiringPiI2CReadReg8 (int fd, int reg)
137 {
138   union i2c_smbus_data data;
139
140   if (i2c_smbus_access (fd, I2C_SMBUS_READ, reg, I2C_SMBUS_BYTE_DATA, &data))
141     return -1 ;
142   else
143     return data.byte & 0xFF ;
144 }
145
146 int wiringPiI2CReadReg16 (int fd, int reg)
147 {
148   union i2c_smbus_data data;
149
150   if (i2c_smbus_access (fd, I2C_SMBUS_READ, reg, I2C_SMBUS_WORD_DATA, &data))
151     return -1 ;
152   else
153     return data.word & 0xFFFF ;
154 }
155
156
157 /*
158  * wiringPiI2CWrite:
159  *      Simple device write
160  *********************************************************************************
161  */
162
163 int wiringPiI2CWrite (int fd, int data)
164 {
165   return i2c_smbus_access (fd, I2C_SMBUS_WRITE, data, I2C_SMBUS_BYTE, NULL) ;
166 }
167
168
169 /*
170  * wiringPiI2CWriteReg8: wiringPiI2CWriteReg16:
171  *      Write an 8 or 16-bit value to the given register
172  *********************************************************************************
173  */
174
175 int wiringPiI2CWriteReg8 (int fd, int reg, int value)
176 {
177   union i2c_smbus_data data ;
178
179   data.byte = value ;
180   return i2c_smbus_access (fd, I2C_SMBUS_WRITE, reg, I2C_SMBUS_BYTE_DATA, &data) ;
181 }
182
183 int wiringPiI2CWriteReg16 (int fd, int reg, int value)
184 {
185   union i2c_smbus_data data ;
186
187   data.word = value ;
188   return i2c_smbus_access (fd, I2C_SMBUS_WRITE, reg, I2C_SMBUS_WORD_DATA, &data) ;
189 }
190
191
192 /*
193  * wiringPiI2CSetupInterface:
194  *      Undocumented access to set the interface explicitly - might be used
195  *      for the Pi's 2nd I2C interface...
196  *********************************************************************************
197  */
198
199 int wiringPiI2CSetupInterface (const char *device, int devId)
200 {
201   int fd ;
202
203   if ((fd = open (device, O_RDWR)) < 0)
204     return wiringPiFailure (WPI_ALMOST, "Unable to open I2C device: %s\n", strerror (errno)) ;
205
206   if (ioctl (fd, I2C_SLAVE, devId) < 0)
207     return wiringPiFailure (WPI_ALMOST, "Unable to select I2C device: %s\n", strerror (errno)) ;
208
209   return fd ;
210 }
211
212
213 /*
214  * wiringPiI2CSetup:
215  *      Open the I2C device, and regsiter the target device
216  *********************************************************************************
217  */
218
219 int wiringPiI2CSetup (const int devId)
220 {
221   int rev ;
222   const char *device ;
223
224   rev = piBoardRev () ;
225
226   if (rev == 1)
227     device = "/dev/i2c-0" ;
228   else
229     device = "/dev/i2c-1" ;
230
231   return wiringPiI2CSetupInterface (device, devId) ;
232 }