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
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
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
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
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 
#define LTC2970_CH1_A_SERVO
Definition: LTC2970.h:128
#define LTC2970_TEMP_ADC
Definition: LTC2970.h:141
#define LTC2970_CH0_A_SERVO
Definition: LTC2970.h:114
#define LTC2970_FAULT
Definition: LTC2970.h:79
void ltc2970_print_die_temp(LT_SMBus *smbus, uint8_t ltc2970_i2c_address)
Prints die temperature on the LTC2970.
Definition: LTC2970.cpp:265
#define LTC2970_FAULT_LA_INDEX
Definition: LTC2970.h:85
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
virtual void writeWord(uint8_t address, uint8_t command, uint16_t data)=0
SMBus write word command.
LT_SMBusGroup * smbus
Definition: retention.ino:139
static uint8_t ltc2970_i2c_address
Definition: DC2467.ino:69
#define LTC2970_FAULT_LA
Definition: LTC2970.h:86
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
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
#define LTC2970_CH0_A_IDAC
Definition: LTC2970.h:115
#define LTC2970_IO
Definition: LTC2970.h:90
Header for LTC2970: Dual I2C Power Supply Monitor and Margining Controller.
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
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
#define LTC2970_CH1_A_IDAC
Definition: LTC2970.h:129
virtual uint16_t readWord(uint8_t address, uint8_t command)=0
SMBus read word command.
void ltc2970_gpio_up(LT_SMBus *smbus, uint8_t ltc2970_i2c_address, int gpio_number)
Set GPIO_n high.
Definition: LTC2970.cpp:5
void ltc2970_gpio_down(LT_SMBus *smbus, uint8_t ltc2970_i2c_address, int gpio_number)
Set GPIO_n low.
Definition: LTC2970.cpp:28