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