Statistics
| Branch: | Revision:

ddr4s / fw / wiringPi / wiringPi / ads1115.c @ 32:cadb9025f1e0

History | View | Annotate | Download (8.7 KB)

1
/*
2
 * ads1115.c:
3
 *        Extend wiringPi with the ADS1115 I2C 16-bit ADC
4
 *        Copyright (c) 2016 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
 *********************************************************************************
27
 * We're going to work in a hybrid mode to fit in with the wiringPi way of
28
 * doing things, so there will be 4 analog pin which read the 4 single-ended
29
 * channels as usual, also some fake digitalOutputs - these are the control
30
 * registers that allow the user to put it into single/diff mode, set the
31
 * gain and data rates.
32
 *********************************************************************************
33
 */
34

    
35
#include <byteswap.h>
36
#include <stdio.h>
37
#include <stdint.h>
38

    
39
#include <wiringPi.h>
40
#include <wiringPiI2C.h>
41

    
42
#include "ads1115.h"
43

    
44
// Bits in the config register (it's a 16-bit register)
45

    
46
#define        CONFIG_OS_MASK                (0x8000)        // Operational Status Register
47
#define        CONFIG_OS_SINGLE        (0x8000)        // Write - Starts a single-conversion
48
                                                // Read    1 = Conversion complete
49

    
50
// The multiplexor
51

    
52
#define        CONFIG_MUX_MASK                (0x7000)
53

    
54
// Differential modes
55

    
56
#define        CONFIG_MUX_DIFF_0_1        (0x0000)        // Pos = AIN0, Neg = AIN1 (default)
57
#define        CONFIG_MUX_DIFF_0_3        (0x1000)        // Pos = AIN0, Neg = AIN3
58
#define        CONFIG_MUX_DIFF_1_3        (0x2000)        // Pos = AIN1, Neg = AIN3
59
#define        CONFIG_MUX_DIFF_2_3        (0x3000)        // Pos = AIN2, Neg = AIN3 (2nd differential channel)
60

    
61
// Single-ended modes
62

    
63
#define        CONFIG_MUX_SINGLE_0        (0x4000)        // AIN0
64
#define        CONFIG_MUX_SINGLE_1        (0x5000)        // AIN1
65
#define        CONFIG_MUX_SINGLE_2        (0x6000)        // AIN2
66
#define        CONFIG_MUX_SINGLE_3        (0x7000)        // AIN3
67

    
68
// Programmable Gain Amplifier
69

    
70
#define        CONFIG_PGA_MASK                (0x0E00)
71
#define        CONFIG_PGA_6_144V        (0x0000)        // +/-6.144V range = Gain 2/3
72
#define        CONFIG_PGA_4_096V        (0x0200)        // +/-4.096V range = Gain 1
73
#define        CONFIG_PGA_2_048V        (0x0400)        // +/-2.048V range = Gain 2 (default)
74
#define        CONFIG_PGA_1_024V        (0x0600)        // +/-1.024V range = Gain 4
75
#define        CONFIG_PGA_0_512V        (0x0800)        // +/-0.512V range = Gain 8
76
#define        CONFIG_PGA_0_256V        (0x0A00)        // +/-0.256V range = Gain 16
77

    
78
#define        CONFIG_MODE                (0x0100)        // 0 is continuous, 1 is single-shot (default)
79

    
80
// Data Rate
81

    
82
#define        CONFIG_DR_MASK                (0x00E0)
83
#define        CONFIG_DR_8SPS                (0x0000)        //   8 samples per second
84
#define        CONFIG_DR_16SPS                (0x0020)        //  16 samples per second
85
#define        CONFIG_DR_32SPS                (0x0040)        //  32 samples per second
86
#define        CONFIG_DR_64SPS                (0x0060)        //  64 samples per second
87
#define        CONFIG_DR_128SPS        (0x0080)        // 128 samples per second (default)
88
#define        CONFIG_DR_475SPS        (0x00A0)        // 475 samples per second
89
#define        CONFIG_DR_860SPS        (0x00C0)        // 860 samples per second
90

    
91
// Comparator mode
92

    
93
#define        CONFIG_CMODE_MASK        (0x0010)
94
#define        CONFIG_CMODE_TRAD        (0x0000)        // Traditional comparator with hysteresis (default)
95
#define        CONFIG_CMODE_WINDOW        (0x0010)        // Window comparator
96

    
97
// Comparator polarity - the polarity of the output alert/rdy pin
98

    
99
#define        CONFIG_CPOL_MASK        (0x0008)
100
#define        CONFIG_CPOL_ACTVLOW        (0x0000)        // Active low (default)
101
#define        CONFIG_CPOL_ACTVHI        (0x0008)        // Active high
102

    
103
// Latching comparator - does the alert/rdy pin latch
104

    
105
#define        CONFIG_CLAT_MASK        (0x0004)
106
#define        CONFIG_CLAT_NONLAT        (0x0000)        // Non-latching comparator (default)
107
#define        CONFIG_CLAT_LATCH        (0x0004)        // Latching comparator
108

    
109
// Comparitor queue
110

    
111
#define        CONFIG_CQUE_MASK        (0x0003)
112
#define        CONFIG_CQUE_1CONV        (0x0000)        // Assert after one conversions
113
#define        CONFIG_CQUE_2CONV        (0x0001)        // Assert after two conversions
114
#define        CONFIG_CQUE_4CONV        (0x0002)        // Assert after four conversions
115
#define        CONFIG_CQUE_NONE        (0x0003)        // Disable the comparator (default)
116

    
117
#define        CONFIG_DEFAULT                (0x8583)        // From the datasheet
118

    
119

    
120
static const uint16_t dataRates [8] =
121
{
122
  CONFIG_DR_8SPS, CONFIG_DR_16SPS, CONFIG_DR_32SPS, CONFIG_DR_64SPS, CONFIG_DR_128SPS, CONFIG_DR_475SPS, CONFIG_DR_860SPS
123
} ;
124

    
125
static const uint16_t gains [6] =
126
{
127
  CONFIG_PGA_6_144V, CONFIG_PGA_4_096V, CONFIG_PGA_2_048V, CONFIG_PGA_1_024V, CONFIG_PGA_0_512V, CONFIG_PGA_0_256V
128
} ;
129

    
130

    
131
/*
132
 * analogRead:
133
 *        Pin is the channel to sample on the device.
134
 *        Channels 0-3 are single ended inputs,
135
 *        channels 4-7 are the various differential combinations.
136
 *********************************************************************************
137
 */
138

    
139
static int myAnalogRead (struct wiringPiNodeStruct *node, int pin)
140
{
141
  int chan = pin - node->pinBase ;
142
  int16_t  result ;
143
  uint16_t config = CONFIG_DEFAULT ;
144

    
145
  chan &= 7 ;
146

    
147
// Setup the configuration register
148

    
149
//        Set PGA/voltage range
150

    
151
  config &= ~CONFIG_PGA_MASK ;
152
  config |= node->data0 ;
153

    
154
//        Set sample speed
155

    
156
  config &= ~CONFIG_DR_MASK ;
157
  config |= node->data1 ;
158

    
159
//        Set single-ended channel or differential mode
160

    
161
  config &= ~CONFIG_MUX_MASK ;
162

    
163
  switch (chan)
164
  {
165
    case 0: config |= CONFIG_MUX_SINGLE_0 ; break ;
166
    case 1: config |= CONFIG_MUX_SINGLE_1 ; break ;
167
    case 2: config |= CONFIG_MUX_SINGLE_2 ; break ;
168
    case 3: config |= CONFIG_MUX_SINGLE_3 ; break ;
169

    
170
    case 4: config |= CONFIG_MUX_DIFF_0_1 ; break ;
171
    case 5: config |= CONFIG_MUX_DIFF_2_3 ; break ;
172
    case 6: config |= CONFIG_MUX_DIFF_0_3 ; break ;
173
    case 7: config |= CONFIG_MUX_DIFF_1_3 ; break ;
174
  }
175

    
176
//        Start a single conversion
177

    
178
  config |= CONFIG_OS_SINGLE ;
179
  config = __bswap_16 (config) ;
180
  wiringPiI2CWriteReg16 (node->fd, 1, config) ;
181

    
182
// Wait for the conversion to complete
183

    
184
  for (;;)
185
  {
186
    result =  wiringPiI2CReadReg16 (node->fd, 1) ;
187
    result = __bswap_16 (result) ;
188
    if ((result & CONFIG_OS_MASK) != 0)
189
      break ;
190
    delayMicroseconds (100) ;
191
  }
192

    
193
  result =  wiringPiI2CReadReg16 (node->fd, 0) ;
194
  result = __bswap_16 (result) ;
195

    
196
// Sometimes with a 0v input on a single-ended channel the internal 0v reference
197
//        can be higher than the input, so you get a negative result...
198

    
199
  if ( (chan < 4) && (result < 0) ) 
200
    return 0 ;
201
  else
202
    return (int)result ;
203
}
204

    
205

    
206
/*
207
 * digitalWrite:
208
 *        It may seem odd to have a digital write here, but it's the best way
209
 *        to pass paramters into the chip in the wiringPi way of things.
210
 *        We have 2 digital registers:
211
 *                0 is the gain control
212
 *                1 is the data rate control
213
 *********************************************************************************
214
 */
215

    
216
static void myDigitalWrite (struct wiringPiNodeStruct *node, int pin, int data)
217
{
218
  int chan = pin - node->pinBase ;
219
  chan &= 3 ;
220

    
221
  if (chan == 0)        // Gain Control
222
  {
223
    if ( (data < 0) || (data > 6) )        // Use default if out of range
224
      data = 2 ;
225
    node->data0 = gains [data] ;
226
  }
227
  else                        // Data rate control
228
  {
229
    if ( (data < 0) || (data > 7) )        // Use default if out of range
230
      data = 4 ;
231
    node->data1 = dataRates [data] ;        // Bugfix 0-1 by "Eric de jong (gm)" <ericdejong@gmx.net> - Thanks.
232
  }
233
  
234
}
235

    
236

    
237
/*
238
 * analogWrite:
239
 *        We're using this to write to the 2 comparitor threshold registers.
240
 *        We could use a digitalWrite here but as it's an analog comparison
241
 *        then it feels better to do it this way.
242
 *********************************************************************************
243
 */
244

    
245
static void myAnalogWrite (struct wiringPiNodeStruct *node, int pin, int data)
246
{
247
  int chan = pin - node->pinBase ;
248
  int reg ;
249
  int16_t ndata ;
250

    
251
  chan &= 3 ;
252

    
253
  reg = chan + 2 ;
254

    
255
  /**/ if (data < -32767)
256
    ndata = -32767 ;
257
  else if (data > 32767)
258
    ndata = 32767 ;
259
  else
260
    ndata = (int16_t)data ;
261

    
262
  ndata = __bswap_16 (ndata) ;
263
  wiringPiI2CWriteReg16 (node->fd, reg, data) ;
264
}
265

    
266

    
267

    
268
/*
269
 * ads1115Setup:
270
 *        Create a new wiringPi device node for an ads1115 on the Pi's
271
 *        I2C interface.
272
 *********************************************************************************
273
 */
274

    
275
int ads1115Setup (const int pinBase, int i2cAddr)
276
{
277
  struct wiringPiNodeStruct *node ;
278
  int fd ;
279

    
280
  if ((fd = wiringPiI2CSetup (i2cAddr)) < 0)
281
    return FALSE ;
282

    
283
  node = wiringPiNewNode (pinBase, 8) ;
284

    
285
  node->fd           = fd ;
286
  node->data0        = CONFIG_PGA_4_096V ;        // Gain in data0
287
  node->data1        = CONFIG_DR_128SPS ;        // Samples/sec in data1
288
  node->analogRead   = myAnalogRead ;
289
  node->analogWrite  = myAnalogWrite ;
290
  node->digitalWrite = myDigitalWrite ;
291

    
292
  return TRUE ;
293
}