Statistics
| Branch: | Revision:

ddr4s / fw / WiringPi / wiringPi / wiringPiI2C.c @ 32:cadb9025f1e0

History | View | Annotate | Download (6.58 KB)

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
int wiringPiI2CReadWord (int fd, int reg)
158
{
159
  union i2c_smbus_data data;
160
    uint16_t dat;
161

    
162
  i2c_smbus_access (fd, I2C_SMBUS_READ, reg, I2C_SMBUS_WORD_DATA, &data);
163
  dat = ((data.word & 0xFF00) >> 8) | ((data.word & 0x00ff) << 8);
164

    
165
  if (i2c_smbus_access (fd, I2C_SMBUS_READ, reg, I2C_SMBUS_WORD_DATA, &data))
166
    return -1 ;
167
  else
168
    return dat & 0xFFFF ;
169
}
170

    
171
/*
172
 * wiringPiI2CWrite:
173
 *        Simple device write
174
 *********************************************************************************
175
 */
176

    
177
int wiringPiI2CWrite (int fd, int data)
178
{
179
  return i2c_smbus_access (fd, I2C_SMBUS_WRITE, data, I2C_SMBUS_BYTE, NULL) ;
180
}
181

    
182

    
183
/*
184
 * wiringPiI2CWriteReg8: wiringPiI2CWriteReg16:
185
 *        Write an 8 or 16-bit value to the given register
186
 *********************************************************************************
187
 */
188

    
189
int wiringPiI2CWriteReg8 (int fd, int reg, int value)
190
{
191
  union i2c_smbus_data data ;
192

    
193
  data.byte = value ;
194
  return i2c_smbus_access (fd, I2C_SMBUS_WRITE, reg, I2C_SMBUS_BYTE_DATA, &data) ;
195
}
196

    
197
int wiringPiI2CWriteReg16 (int fd, int reg, int value)
198
{
199
  union i2c_smbus_data data ;
200

    
201
  data.word = value ;
202
  return i2c_smbus_access (fd, I2C_SMBUS_WRITE, reg, I2C_SMBUS_WORD_DATA, &data) ;
203
}
204

    
205

    
206
/*
207
 * wiringPiI2CSetupInterface:
208
 *        Undocumented access to set the interface explicitly - might be used
209
 *        for the Pi's 2nd I2C interface...
210
 *********************************************************************************
211
 */
212

    
213
int wiringPiI2CSetupInterface (const char *device, int devId)
214
{
215
  int fd ;
216

    
217
  if ((fd = open (device, O_RDWR)) < 0)
218
    return wiringPiFailure (WPI_ALMOST, "Unable to open I2C device: %s\n", strerror (errno)) ;
219

    
220
  if (ioctl (fd, I2C_SLAVE, devId) < 0)
221
    return wiringPiFailure (WPI_ALMOST, "Unable to select I2C device: %s\n", strerror (errno)) ;
222

    
223
  return fd ;
224
}
225

    
226

    
227
/*
228
 * wiringPiI2CSetup:
229
 *        Open the I2C device, and regsiter the target device
230
 *********************************************************************************
231
 */
232

    
233
int wiringPiI2CSetup (const int devId)
234
{
235
  int rev ;
236
  const char *device ;
237

    
238
  rev = piBoardRev () ;
239

    
240
  if (rev == 1)
241
    device = "/dev/i2c-0" ;
242
  else
243
    device = "/dev/i2c-0" ;
244

    
245
  return wiringPiI2CSetupInterface (device, devId) ;
246
}