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 
25 #include <iostream>
26 #include <string>
27 #include <stdexcept>
28 
29 #include "adc121c021.h"
30 
31 using namespace upm;
32 using namespace std;
33 
34 
ADC121C021(int bus,uint8_t address,float vref)35 ADC121C021::ADC121C021(int bus, uint8_t address, float vref)
36 {
37   // setup our i2c link
38   m_i2c = mraa_i2c_init(bus);
39   if ( !(m_i2c = mraa_i2c_init(bus)) )
40     {
41       throw std::invalid_argument(std::string(__FUNCTION__) +
42                                   ": mraa_i2c_init() failed");
43       return;
44     }
45 
46   m_addr = address;
47 
48   mraa_result_t ret = mraa_i2c_address(m_i2c, m_addr);
49 
50   if (ret != MRAA_SUCCESS)
51     {
52       throw std::invalid_argument(std::string(__FUNCTION__) +
53                                   ": mraa_i2c_address() failed");
54       return;
55     }
56 
57   m_vref = vref;
58 }
59 
~ADC121C021()60 ADC121C021::~ADC121C021()
61 {
62   mraa_i2c_stop(m_i2c);
63 }
64 
writeByte(uint8_t reg,uint8_t byte)65 mraa_result_t ADC121C021::writeByte(uint8_t reg, uint8_t byte)
66 {
67   return mraa_i2c_write_byte_data(m_i2c, byte, reg);
68 }
69 
writeWord(uint8_t reg,uint16_t word)70 mraa_result_t ADC121C021::writeWord(uint8_t reg, uint16_t word)
71 {
72   // We need to swap the bytes
73   uint8_t b1 = (word & 0xff00) >> 8;
74   word <<= 8;
75   word |= b1;
76 
77   return mraa_i2c_write_word_data(m_i2c, word, reg);
78 }
79 
readByte(uint8_t reg)80 uint8_t ADC121C021::readByte(uint8_t reg)
81 {
82   return mraa_i2c_read_byte_data(m_i2c, reg);
83 }
84 
readWord(uint8_t reg)85 uint16_t ADC121C021::readWord(uint8_t reg)
86 {
87   uint16_t val = mraa_i2c_read_word_data(m_i2c, reg);
88   uint8_t b1;
89 
90   // The value returned is in the wrong byte order, so we need to swap them
91   b1 = (val & 0xff00) >> 8;
92   val <<= 8;
93   val |= b1;
94 
95   return val;
96 }
97 
value()98 uint16_t ADC121C021::value()
99 {
100   // mask off alert flag and reserved bits
101   return (readWord(ADC121C021_REG_RESULT) & 0x0fff);
102 }
103 
valueToVolts(uint16_t val)104 float ADC121C021::valueToVolts(uint16_t val)
105 {
106   // The arduino example multiplies this by 2, which seems wrong.  If
107   // the reference voltage is 3.0, then you should never get a voltage
108   // value higher than that.
109   //
110   // val * m_vref * 2.0 / ADC121C021_RESOLUTION
111   return (val * m_vref / ADC121C021_RESOLUTION);
112 }
113 
getAlertStatus()114 bool ADC121C021::getAlertStatus()
115 {
116   // high order bit is the alert flag, mask off the rest
117   bool rv = (readWord(ADC121C021_REG_RESULT) & 0x8000) ? true : false;
118 
119   if (rv)
120     {
121       // read the alert low and high values and set the appropriate
122       // member variables
123       uint8_t astatus = readByte(ADC121C021_REG_ALERT_STATUS);
124       if (astatus & 0x01)
125         m_alertLow = true;
126       else
127         m_alertLow = false;
128 
129       if (astatus & 0x02)
130         m_alertHigh = true;
131       else
132         m_alertHigh = false;
133     }
134 
135   return rv;
136 }
137 
clearAlertStatus()138 void ADC121C021::clearAlertStatus()
139 {
140   // zero out both the low and high alert flags
141   writeByte(ADC121C021_REG_ALERT_STATUS, 0x03);
142 
143   m_alertHigh = false;
144   m_alertLow = false;
145 }
146 
enableAlertFlag(bool enable)147 void ADC121C021::enableAlertFlag(bool enable)
148 {
149   // read the current config register
150   uint8_t val = readByte(ADC121C021_REG_CONFIG);
151 
152   if (enable)
153     val |= 0x08;
154   else
155     val &= ~0x08;
156 
157   // write the register back
158   writeByte(ADC121C021_REG_CONFIG, val);
159 }
160 
enableAlertPin(bool enable)161 void ADC121C021::enableAlertPin(bool enable)
162 {
163   // read the current config register
164   uint8_t val = readByte(ADC121C021_REG_CONFIG);
165 
166   if (enable)
167     val |= 0x04;
168   else
169     val &= ~0x04;
170 
171   // write the register back
172   writeByte(ADC121C021_REG_CONFIG, val);
173 }
174 
enableAlertHold(bool enable)175 void ADC121C021::enableAlertHold(bool enable)
176 {
177   // read the current config register
178   uint8_t val = readByte(ADC121C021_REG_CONFIG);
179 
180   if (enable)
181     val |= 0x10;
182   else
183     val &= ~0x10;
184 
185   // write the register back
186   writeByte(ADC121C021_REG_CONFIG, val);
187 }
188 
enableAlertPinPolarityHigh(bool enable)189 void ADC121C021::enableAlertPinPolarityHigh(bool enable)
190 {
191   // read the current config register
192   uint8_t val = readByte(ADC121C021_REG_CONFIG);
193 
194   if (enable)
195     val |= 0x01;
196   else
197     val &= ~0x01;
198 
199   // write the register back
200   writeByte(ADC121C021_REG_CONFIG, val);
201 }
202 
setAutomaticConversion(ADC121C021_CYCLE_TIME_T cycleTime)203 void ADC121C021::setAutomaticConversion(ADC121C021_CYCLE_TIME_T cycleTime)
204 {
205   // first we
206 
207   // read the current config register, masking off the cycle time bits
208   uint8_t val = readByte(ADC121C021_REG_CONFIG) & 0x1f;
209 
210   val |= ((uint8_t)cycleTime << 5);
211 
212   // write the register back
213   writeByte(ADC121C021_REG_CONFIG, val);
214 }
215 
setAlertLowLimit(uint16_t limit)216 mraa_result_t ADC121C021::setAlertLowLimit(uint16_t limit)
217 {
218   // mask off the invalid bits in case they were set
219   limit &= 0x0fff;
220 
221   // write it
222   return writeWord(ADC121C021_REG_ALERT_LIM_UNDER, limit);
223 }
224 
setAlertHighLimit(uint16_t limit)225 mraa_result_t ADC121C021::setAlertHighLimit(uint16_t limit)
226 {
227   // mask off the invalid bits in case they were set
228   limit &= 0x0fff;
229 
230   // write it
231   return writeWord(ADC121C021_REG_ALERT_LIM_OVER, limit);
232 }
233 
setHysteresis(uint16_t limit)234 mraa_result_t ADC121C021::setHysteresis(uint16_t limit)
235 {
236   // mask off the invalid bits in case they were set
237   limit &= 0x0fff;
238 
239   // write it
240   return writeWord(ADC121C021_REG_ALERT_HYS, limit);
241 }
242 
getHighestConversion()243 uint16_t ADC121C021::getHighestConversion()
244 {
245   return readWord(ADC121C021_REG_HIGHEST_CONV);
246 }
247 
getLowestConversion()248 uint16_t ADC121C021::getLowestConversion()
249 {
250   return readWord(ADC121C021_REG_LOWEST_CONV);
251 }
252 
clearHighestConversion()253 mraa_result_t ADC121C021::clearHighestConversion()
254 {
255   return writeWord(ADC121C021_REG_HIGHEST_CONV, 0x0000);
256 }
257 
clearLowestConversion()258 mraa_result_t ADC121C021::clearLowestConversion()
259 {
260   return writeWord(ADC121C021_REG_LOWEST_CONV, 0x0fff);
261 }
262