| Linduino 1.3.0 Linear Technology Arduino-Compatible Demonstration Board

LTC2970.cpp
Go to the documentation of this file.
1 #include "LTC2970.h"
2
3 //! Set GPIO_n high
4 //! @return void
5 void ltc2970_gpio_up(LT_SMBus *smbus, uint8_t ltc2970_i2c_address, int gpio_number)
6 {
7 uint16_t return_val;
8 if (gpio_number == 0)
9 {
10 return_val = smbus->readWord(ltc2970_i2c_address,LTC2970_IO);
11 return_val = (return_val & 0xFEFE) | 0x0012;
12 smbus->writeWord(ltc2970_i2c_address, LTC2970_IO, return_val);
13 }
14 else if (gpio_number == 1)
15 {
16 return_val = smbus->readWord(ltc2970_i2c_address,LTC2970_IO);
17 return_val = (return_val & 0xFEFB) | 0x0028;
18 smbus->writeWord(ltc2970_i2c_address, LTC2970_IO, return_val);
19 }
20 else
21 {
22 // error, no such GPIO
23 }
24 }
25
26 //! Set GPIO_n low
27 //! @return void
28 void ltc2970_gpio_down(LT_SMBus *smbus, uint8_t ltc2970_i2c_address, int gpio_number)
29 {
30 uint16_t return_val;
31 if (gpio_number == 0)
32 {
33 return_val = smbus->readWord(ltc2970_i2c_address,LTC2970_IO);
34 return_val = (return_val & 0xFEEE) | 0x0002;
35 smbus->writeWord(ltc2970_i2c_address, LTC2970_IO, return_val);
36 }
37 else if (gpio_number == 1)
38 {
39 return_val = smbus->readWord(ltc2970_i2c_address,LTC2970_IO);
40 return_val = (return_val & 0xFEDB) | 0x0008;
41 smbus->writeWord(ltc2970_i2c_address, LTC2970_IO, return_val);
42 }
43 else
44 {
45 // error, no such GPIO
46 }
47 }
48
49 //! Disconnect a DAC from its channel
50 //! @return void
51 void ltc2970_dac_disconnect(LT_SMBus *smbus, uint8_t ltc2970_i2c_address, int dac_number)
52 {
53 uint16_t return_val,
54 idac_reg;
55
56 if (dac_number == 0)
57 {
58 Serial.print(F("\nDISCONNECT CHANNEL 0 : "));
59 return_val = smbus->readWord(ltc2970_i2c_address, LTC2970_CH0_A_IDAC);
60 idac_reg = 0xFCFF & return_val;
61 smbus->writeWord(ltc2970_i2c_address, LTC2970_CH0_A_IDAC, idac_reg);
62 }
63 else if (dac_number == 1)
64 {
65 Serial.print(F("\nDISCONNECT CHANNEL 1 : "));
66 return_val = smbus->readWord(ltc2970_i2c_address, LTC2970_CH1_A_IDAC);
67 idac_reg = 0xFCFF & return_val;
68 smbus->writeWord(ltc2970_i2c_address, LTC2970_CH1_A_IDAC, idac_reg);
69 }
70 else
71 {
72 Serial.print(F("\nERROR CANNOT DISCONNECT NON-EXISTENT CHANNEL"));
73 // error, no such DAC
74 }
75 Serial.print(F("\n\n"));
76 }
77
78 //! Unceremoniously connect DAC0 to the control node
79 //! set DAC to a hard value
80 //! no attempt to equalize voltages
81 //! @return void
82 void ltc2970_hard_connect_dac(LT_SMBus *smbus, uint8_t ltc2970_i2c_address, int dac_number, uint8_t dac_value_8)
83 {
84 uint16_t return_val,
85 idac_ctrl,
86 idac_reg,
87 dac_value = (uint16_t)dac_value_8;
88
89 if (dac_number == 0)
90 {
91 Serial.print(F("\nHARD CONNECT CHANNEL 0 : "));
92 return_val = smbus->readWord(ltc2970_i2c_address, LTC2970_CH0_A_IDAC);
93 idac_ctrl = 0x0300;
94 idac_reg = (0xFC00 & return_val) | (0x00FF & dac_value) | idac_ctrl ;
95 smbus->writeWord(ltc2970_i2c_address, LTC2970_CH0_A_IDAC, idac_reg);
96 }
97 else if (dac_number == 1)
98 {
99 Serial.print(F("\nHARD CONNECT CHANNEL 1 : "));
100 return_val = smbus->readWord(ltc2970_i2c_address, LTC2970_CH1_A_IDAC);
101 idac_ctrl = 0x0300;
102 idac_reg = (0xFC00 & return_val) | (0x00FF & dac_value) | idac_ctrl ;
103 smbus->writeWord(ltc2970_i2c_address, LTC2970_CH1_A_IDAC, idac_reg);
104 }
105 else
106 {
107 Serial.print(F("\nERROR CANNOT HARD CONNECT NON-EXISTENT CHANNEL"));
108 // error, no such DAC
109 }
110 }
111
112 //! soft-connect DACn to its controlled node
113 //! @return int
114 int ltc2970_soft_connect_dac(LT_SMBus *smbus, uint8_t ltc2970_i2c_address, int dac_number)
115 {
116 uint16_t return_val,
117 idac_reg,
118 idac_ctrl,
119 idac_value;
120
121 int soft_connect_delay = 1000; // milliseconds to wait for soft connect
122
123 if (dac_number == 0)
124 {
125 // check for existing faults
126 return_val = smbus->readWord(ltc2970_i2c_address, LTC2970_FAULT);
127 if ((return_val & 0x001B) == 0x0000)
128 {
129 // make sure that the channel is not already connected
130 return_val = smbus->readWord(ltc2970_i2c_address, LTC2970_CH0_A_IDAC);
131 if ((return_val & 0x0300) == 0x0000)
132 {
133 // the soft-connect operation can succeed with no faults, setting IDAC[9] = 1
134 // or it can fail, and not set IDAC[9]
135 // we wait a safe amount of time, then check for results
136 Serial.print(F("\nSOFT CONNECT CHANNEL 0 : "));
137 idac_ctrl = 0x0100;
138 idac_value = 0x0080; // soft connect will override this value automatically
139 idac_reg = (0xFC00 & return_val) | (0x00FF & idac_value) | idac_ctrl ;
140 smbus->writeWord(ltc2970_i2c_address, LTC2970_CH0_A_IDAC, idac_reg);
141 delay(soft_connect_delay);
142 return_val = smbus->readWord(ltc2970_i2c_address, LTC2970_CH0_A_IDAC);
143 if ((return_val & 0x0300) == 0x0000)
144 {
145 Serial.print(F("\nCHANNEL 0 FAILED TO CONNECT"));
146 Serial.print(F("\n FAULT REGISTER: "));
147 return_val = smbus->readWord(ltc2970_i2c_address, LTC2970_FAULT);
148 Serial.print(F("0x"));
149 Serial.println(return_val, HEX);
150 }
151 else
152 {
153 Serial.print(F("\nCHANNEL 0 SOFT CONNECT SUCCESS"));
154 // return_val = smbus->readWord(ltc2970_i2c_address, LTC2970_CH0_A_ADC);
155 // servo0_value = (return_val & 0x7FFF);
156 }
157 }
158 else
159 {
160 Serial.print(F("\nCHANNEL 0 ALREADY CONNECTED"));
161 }
162 }
163 else
164 {
165 Serial.print(F("\nERROR: CANNOT SOFT-CONNECT WITH FAULTS ON CHANNEL 0: "));
166 Serial.println(return_val, HEX);
167 }
168 }
169 else if (dac_number == 1)
170 {
171 // check for existing faults
172 return_val = smbus->readWord(ltc2970_i2c_address,LTC2970_FAULT);
173 // if ((return_val & 0x03E0) == 0x0000) {
174 if ((return_val & 0x0360) == 0x0000)
175 {
176 // make sure that the channel is not already connected
177 return_val = smbus->readWord(ltc2970_i2c_address, LTC2970_CH1_A_IDAC);
178 if ((return_val & 0x0300) == 0x0000)
179 {
180 // the soft-connect operation can succeed with no faults, setting IDAC[9] = 1
181 // or it can fail, and not set IDAC[9]
182 // we wait a safe amount of time, then check for results
183 Serial.print(F("\nSOFT CONNECT CHANNEL 1 : "));
184 idac_ctrl = 0x0100;
185 idac_value = 0x0080; // soft connect will override this value automatically
186 idac_reg = (0xFC00 & return_val) | (0x00FF & idac_value) | idac_ctrl ;
187 smbus->writeWord(ltc2970_i2c_address, LTC2970_CH1_A_IDAC, idac_reg);
188 delay(soft_connect_delay);
189 return_val = smbus->readWord(ltc2970_i2c_address, LTC2970_CH1_A_IDAC);
190 if ((return_val & 0x0300) == 0x0000)
191 {
192 Serial.print(F("\nCHANNEL 1 FAILED TO CONNECT"));
193 Serial.print(F("\n FAULT REGISTER: "));
194 return_val = smbus->readWord(ltc2970_i2c_address, LTC2970_FAULT);
195 Serial.print(F("0x"));
196 Serial.println(return_val, HEX);
197 }
198 else
199 {
200 Serial.print(F("\nCHANNEL 1 SOFT CONNECT SUCCESS"));
201 // return_val = smbus->readWord(ltc2970_i2c_address, LTC2970_CH1_A_ADC);
202 // servo1_value = (return_val & 0x7FFF);
203 }
204 }
205 else
206 {
207 Serial.print(F("\nCHANNEL 1 ALREADY CONNECTED"));
208 }
209 }
210 else
211 {
212 Serial.print(F("\nERROR: CANNOT SOFT-CONNECT WITH FAULTS ON CHANNEL 1: "));
213 Serial.println(return_val, HEX);
214 }
215 }
216 else
217 {
218 Serial.print(F("\nERROR: CANNOT SOFT CONNECT NON-EXISTENT CHANNEL"));
219 // error, no such DAC
220 }
221 Serial.print(F("\n\n"));
222 }
223
224
225 //! Servo once to a given ADC value
226 //! @return void
227 void ltc2970_servo_to_adc_val(LT_SMBus *smbus, uint8_t ltc2970_i2c_address, int channel_number, uint16_t code)
228 {
229 uint16_t return_val;
230
231 uint16_t code_in;
232 // uint16_t code_max = 0x18B7,
233 // code_min = 0x0AE0;
234
235 // get rid of bit 15 to make limit calculations easier
236 // note that limits may be different per channel
237 code_in = (code & 0x7FFF);
238 // code_in = (code_in > code_max) ? code_max : code_in;
239 // code_in = (code_in < code_min) ? code_min : code_in;
240
241 // ensure that bit 15 is high to enable servoing
242 code_in = (code_in + 0x8000);
243
244 if (channel_number == 0)
245 {
246 Serial.print(F("\nSERVO CHANNEL 0."));
247 smbus->writeWord(ltc2970_i2c_address, LTC2970_CH0_A_SERVO, code_in);
248
249 }
250 else if (channel_number == 1)
251 {
252 Serial.print(F("\nSERVO CHANNEL 1."));
253 smbus->writeWord(ltc2970_i2c_address, LTC2970_CH1_A_SERVO, code_in);
254 }
255 else
256 {
257 Serial.print(F("\nERROR CANNOT SERVO NON-EXISTENT CHANNEL"));
258 // error, no such channel
259 }
260 Serial.print(F("\n\n"));
261 }
262
263 //! Prints die temperature on the LTC2970
264 //! @return void
265 void ltc2970_print_die_temp (LT_SMBus *smbus, uint8_t ltc2970_i2c_address)
266 {
267 static float temp_scale = 4;
268 static float temp_offset = 1093; //adc codes
269
270 float temperature;
271 uint16_t return_val;
272 //print the on-die temperature for the LTC2970
273 return_val =
274 smbus->readWord(ltc2970_i2c_address, LTC2970_TEMP_ADC);
275 return_val = return_val & 0x7FFF; // drop bit 15
276
277 temperature = ((float(return_val) - temp_offset) / temp_scale);
278
279 Serial.print(F("\n LTC_2970 DIE TEMP: "));
280 Serial.println(temperature, DEC);
281 Serial.print(F(" HEX VALUE : 0x"));
282 Serial.println(return_val, HEX);
283 Serial.print(F("\n\n"));
284 }
285
286 //! Read FAULT, FAULT_LA, and FAULT_LA_INDEX registers
287 //! print the results
288 //! @return void
289 void ltc2970_read_faults(LT_SMBus *smbus, uint8_t ltc2970_i2c_address)
290 {
291 uint16_t return_val;
292
293 return_val =
294 smbus->readWord(ltc2970_i2c_address,LTC2970_FAULT);
295 Serial.print(F("\n LTC2970_FAULT: "));
296 Serial.print(F("0x"));
297 Serial.println(return_val, HEX);
298 return_val =
299 smbus->readWord(ltc2970_i2c_address,LTC2970_FAULT_LA);
300 Serial.print(F("\n LTC2970_FAULT_LA (CLEARED ON READ): "));
301 Serial.print(F("0x"));
302 Serial.println(return_val, HEX);
303 return_val =
304 smbus->readWord(ltc2970_i2c_address,LTC2970_FAULT_LA_INDEX);
305 Serial.print(F("\n LTC2970_FAULT_LA_INDEX: "));
306 Serial.print(F("0x"));
307 Serial.println(return_val, HEX);
308
309 }
310
LTC2970_CH1_A_SERVO
#define LTC2970_CH1_A_SERVO
Definition: LTC2970.h:128
LTC2970_TEMP_ADC
#define LTC2970_TEMP_ADC
Definition: LTC2970.h:141
LTC2970_CH0_A_SERVO
#define LTC2970_CH0_A_SERVO
Definition: LTC2970.h:114
LTC2970_FAULT
#define LTC2970_FAULT
Definition: LTC2970.h:79
ltc2970_print_die_temp
void ltc2970_print_die_temp(LT_SMBus *smbus, uint8_t ltc2970_i2c_address)
Prints die temperature on the LTC2970.
Definition: LTC2970.cpp:265
LTC2970_FAULT_LA_INDEX
#define LTC2970_FAULT_LA_INDEX
Definition: LTC2970.h:85
ltc2970_read_faults
void ltc2970_read_faults(LT_SMBus *smbus, uint8_t ltc2970_i2c_address)
Read FAULT, FAULT_LA, and FAULT_LA_INDEX registers print the results.
Definition: LTC2970.cpp:289
LT_SMBus::writeWord
virtual void writeWord(uint8_t address, uint8_t command, uint16_t data)=0
SMBus write word command.
smbus
LT_SMBusGroup * smbus
Definition: retention.ino:139
LT_SMBus
Definition: LT_SMBus.h:61
ltc2970_i2c_address
static uint8_t ltc2970_i2c_address
Definition: DC2467.ino:69
LTC2970_FAULT_LA
#define LTC2970_FAULT_LA
Definition: LTC2970.h:86
ltc2970_dac_disconnect
void ltc2970_dac_disconnect(LT_SMBus *smbus, uint8_t ltc2970_i2c_address, int dac_number)
Disconnect a DAC from its channel.
Definition: LTC2970.cpp:51
ltc2970_servo_to_adc_val
void ltc2970_servo_to_adc_val(LT_SMBus *smbus, uint8_t ltc2970_i2c_address, int channel_number, uint16_t code)
Servo once to a given ADC value.
Definition: LTC2970.cpp:227
LTC2970_CH0_A_IDAC
#define LTC2970_CH0_A_IDAC
Definition: LTC2970.h:115
LTC2970_IO
#define LTC2970_IO
Definition: LTC2970.h:90
LTC2970.h
Header for LTC2970: Dual I2C Power Supply Monitor and Margining Controller.
ltc2970_soft_connect_dac
int ltc2970_soft_connect_dac(LT_SMBus *smbus, uint8_t ltc2970_i2c_address, int dac_number)
soft-connect DACn to its controlled node
Definition: LTC2970.cpp:114
ltc2970_hard_connect_dac
void ltc2970_hard_connect_dac(LT_SMBus *smbus, uint8_t ltc2970_i2c_address, int dac_number, uint8_t dac_value_8)
Unceremoniously connect DAC0 to the control node set DAC to a hard value no attempt to equalize volta...
Definition: LTC2970.cpp:82
LTC2970_CH1_A_IDAC
#define LTC2970_CH1_A_IDAC
Definition: LTC2970.h:129
LT_SMBus::readWord
virtual uint16_t readWord(uint8_t address, uint8_t command)=0
SMBus read word command.
ltc2970_gpio_up
void ltc2970_gpio_up(LT_SMBus *smbus, uint8_t ltc2970_i2c_address, int gpio_number)
Set GPIO_n high.
Definition: LTC2970.cpp:5
ltc2970_gpio_down
void ltc2970_gpio_down(LT_SMBus *smbus, uint8_t ltc2970_i2c_address, int gpio_number)
Set GPIO_n low.
Definition: LTC2970.cpp:28