1 /*
2  * Author: Jon Trulson <jtrulson@ics.com>
3  * Copyright (c) 2014 Intel Corporation.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining
6  * a copy of this software and associated documentation files (the
7  * "Software"), to deal in the Software without restriction, including
8  * without limitation the rights to use, copy, modify, merge, publish,
9  * distribute, sublicense, and/or sell copies of the Software, and to
10  * permit persons to whom the Software is furnished to do so, subject to
11  * the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be
14  * included in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24 #pragma once
25 
26 #include <string>
27 #include <mraa/i2c.h>
28 
29 #define ADC121C021_I2C_BUS 0
30 #define ADC121C021_DEFAULT_I2C_ADDR 0x55
31 
32 #define ADC121C021_RESOLUTION  4096 // 12 bits
33 
34 /**
35  * ADC121C021 registers
36  */
37 
38 #define ADC121C021_REG_RESULT          0x00
39 #define ADC121C021_REG_ALERT_STATUS    0x01
40 #define ADC121C021_REG_CONFIG          0x02
41 #define ADC121C021_REG_ALERT_LIM_UNDER 0x03
42 #define ADC121C021_REG_ALERT_LIM_OVER  0x04
43 #define ADC121C021_REG_ALERT_HYS       0x05
44 #define ADC121C021_REG_LOWEST_CONV     0x06
45 #define ADC121C021_REG_HIGHEST_CONV    0x07
46 
47 // For the Grove I2C ADC
48 #define ADC121C021_DEFAULT_VREF        3.0
49 
50 namespace upm {
51   /**
52    * @brief ADC121C021 I2C Analog-to-Digital Converter library
53    * @defgroup adc121c021 libupm-adc121c021
54    * @ingroup seeed i2c electric
55    */
56 
57 
58   /**
59    * Valid cycle times for the automatic conversion mode
60    */
61 
62   typedef enum { ADC121C021_CYCLE_NONE = 0,  // disabled
63                  ADC121C021_CYCLE_32   = 1,  // 27 ksps
64                  ADC121C021_CYCLE_64   = 2,  // 13.5
65                  ADC121C021_CYCLE_128  = 3,  // 6.7
66                  ADC121C021_CYCLE_256  = 4,  // 3.4
67                  ADC121C021_CYCLE_512  = 5,  // 1.7
68                  ADC121C021_CYCLE_1024 = 6,  // 0.9
69                  ADC121C021_CYCLE_2048 = 7   // 0.4
70   } ADC121C021_CYCLE_TIME_T;
71 
72   /**
73    * @library adc121c021
74    * @sensor adc121c021
75    * @comname ADC121C021 Analog-to-Digital Converter
76    * @altname Grove I2C ADC
77    * @type electric
78    * @man seeed
79    * @web http://www.seeedstudio.com/depot/Grove-I2C-ADC-p-1580.html
80    * @con i2c
81    *
82    * @brief API for the ADC121C021 I2C Analog-to-Digital Converter
83    *
84    * UPM module for the ADC121C021 12-bit analog-to-digital converter (ADC).
85    * By constantly providing a reference voltage, this sensor helps
86    * increase the accuracy of a value collected from an analog sensor.
87    *
88    * @image html adc121c021.jpg
89    * @snippet adc121c021.cxx Interesting
90    */
91   class ADC121C021 {
92   public:
93     /**
94      * ADC121C021 ADC constructor
95      *
96      * @param bus I2C bus to use
97      * @param address Address for this sensor; default is 0x55
98      * @param vref Reference voltage for this sensor; default is 3.0v
99      */
100     ADC121C021(int bus, uint8_t address = ADC121C021_DEFAULT_I2C_ADDR,
101                float vref = ADC121C021_DEFAULT_VREF);
102 
103     /**
104      * ADC121C021 destructor
105      */
106     ~ADC121C021();
107 
108     /**
109      * Writes a byte value into the register
110      *
111      * @param reg Register location to write into
112      * @param byte Byte to write
113      * @return 0 (MRAA_SUCCESS) if successful; non-zero otherwise
114      */
115     mraa_result_t writeByte(uint8_t reg, uint8_t byte);
116 
117     /**
118      * Writes a word value into the register
119      *
120      * @param reg Register location to write into
121      * @param word Word to write
122      * @return 0 (MRAA_SUCCESS) if successful; non-zero otherwise
123      */
124     mraa_result_t writeWord(uint8_t reg, uint16_t word);
125 
126     /**
127      * Reads the byte value from the register
128      *
129      * @param reg Register location to read from
130      * @return Value in the specified register
131      */
132     uint8_t readByte(uint8_t reg);
133 
134     /**
135      * Reads the word value from the register
136      *
137      * @param reg Register location to read from
138      * @return Value in the specified register
139      */
140     uint16_t readWord(uint8_t reg);
141 
142     /**
143      * Reads the current value of conversion
144      *
145      * @return Current value of conversion
146      */
147     uint16_t value();
148 
149     /**
150      * Converts a supplied value to voltage based on the set vref
151      *
152      * @param val Value of conversion (from value())
153      * @return Value of conversion in volts
154      */
155     float valueToVolts(uint16_t val);
156 
157     /**
158      * Reads the current status of the alert flag.  If the flag is set, the
159      * low or high alert indicators are set as appropriate, and
160      * you can access these values with alertLowTriggered() or
161      * alertHighTriggered().
162      *
163      * @return True if the alert flag is set
164      */
165     bool getAlertStatus();
166 
167     /**
168      * Returns the current value of m_alertLow.  You must call
169      * getAlertStatus() to update this value.
170      *
171      * @return Current status of the alert low flag
172      */
alertLowTriggered()173     bool alertLowTriggered() { return m_alertLow; };
174 
175     /**
176      * Returns the current value of m_alertHigh.  You must call
177      * getAlertStatus() to update this value.
178      *
179      * @return Current status of the alert high flag
180      */
alertHighTriggered()181     bool alertHighTriggered() { return m_alertHigh; };
182 
183     /**
184      * Clears the alert low and alert high flags. This also clears the
185      * last stored alert values.
186      */
187     void clearAlertStatus();
188 
189     /**
190      * Enables or disables the alert flag functionality.  If enabled,
191      * when the measured value exceeds the low or high limits
192      * configured, the alert flag is set. Use getAlertStatus()
193      * to access these values.
194      *
195      * @param enable If true, enables the alert flag; otherwise, disables the
196      * alert flag
197      */
198     void enableAlertFlag(bool enable);
199 
200     /**
201      * Enables or disables the alert pin functionality.
202      *
203      * @param enable If true, enables the alert pin; otherwise, disables the
204      * alert pin
205      */
206     void enableAlertPin(bool enable);
207 
208     /**
209      * Enables or disables the alert hold functionality.  When the alert
210      * hold is enabled, the alert status remains until manually
211      * cleared via clearAlertStatus().  Otherwise, the alert self-clears
212      * when the value moves into the defined limits if alerts
213      * are enabled via enableAlertFlag().
214      *
215      * @param enable If true, enables the alert hold; otherwise, disables the
216      * alert hold
217      */
218     void enableAlertHold(bool enable);
219 
220     /**
221      * If the alert pin is enabled, defines the active
222      * polarity of the pin in an alert condition. Enabling this sets
223      * the pin to active high in an alert condition; otherwise,
224      * active low is used.
225      *
226      * @param enable If true, the alert pin is active high; otherwise, active
227      * low
228      */
229     void enableAlertPinPolarityHigh(bool enable);
230 
231     /**
232      * Enables or disables the automatic conversion mode. When enabled, the
233      * ADC samples and updates the conversion value independently.
234      * It is disabled by default, so conversion is only done by
235      * calling value().
236      *
237      * @param cycleTime Sets the cycle time for automatic conversion
238      */
239     void setAutomaticConversion(ADC121C021_CYCLE_TIME_T cycleTime);
240 
241     /**
242      * Sets the alert low limit.  If alerts are enabled and the
243      * measured conversion value is lower than the low limit, an alert is
244      * triggered.
245      *
246      * @param limit Alert low limit
247      * @return 0 (MRAA_SUCCESS) if successful; non-zero otherwise
248      */
249     mraa_result_t setAlertLowLimit(uint16_t limit);
250 
251     /**
252      * Sets the alert high limit.  If alerts are enabled and the
253      * measured conversion value is higher than the high limit, an alert is
254      * triggered.
255      *
256      * @param limit Alert high limit
257      * @return 0 (MRAA_SUCCESS) if successful; non-zero otherwise
258      */
259     mraa_result_t setAlertHighLimit(uint16_t limit);
260 
261     /**
262      * Sets the hysteresis value.  If a high or low alert condition is
263      * triggered, the conversion result must move within the high or
264      * low limit by more than this value to clear the alert condition.
265      * If the alert hold is set, the alert doesn't self-clear
266      * regardless of this value.
267      *
268      * @param limit Hysteresis limit
269      * @return 0 (MRAA_SUCCESS) if successful; non-zero otherwise
270      */
271     mraa_result_t setHysteresis(uint16_t limit);
272 
273     /**
274      * Returns the highest conversion value recorded so far. This value
275      * is only updated by the converter when the automatic conversion mode
276      * is enabled.
277      *
278      * @return Highest conversion value
279      */
280     uint16_t getHighestConversion();
281 
282     /**
283      * Returns the lowest conversion value recorded so far. This value
284      * is only updated by the converter when the automatic conversion mode
285      * is enabled.
286      *
287      * @return Lowest conversion value
288      */
289     uint16_t getLowestConversion();
290 
291     /**
292      * Clears the highest conversion value recorded so far.
293      *
294      * @return 0 (MRAA_SUCCESS) if successful; non-zero otherwise
295      */
296     mraa_result_t clearHighestConversion();
297 
298     /**
299      * Clears the lowest conversion value recorded so far.
300      *
301      * @return 0 (MRAA_SUCCESS) if successful; non-zero otherwise
302      */
303     mraa_result_t clearLowestConversion();
304 
305   private:
306     mraa_i2c_context m_i2c;
307     uint8_t m_addr;
308     float m_vref;
309     bool m_alertLow;
310     bool m_alertHigh;
311   };
312 }
313 
314 
315