Linduino  1.3.0
Linear Technology Arduino-Compatible Demonstration Board
LT_PMBus.cpp
Go to the documentation of this file.
1 /*!
2 LTC PMBus Support
3 
4 @verbatim
5 
6 This PMBus code does not cover the entire PMBus command set. The intention
7 is to cover the common commands. It was written for LTC PMBus devices,
8 and may not perform properly with other PMBus devices.
9 
10 @endverbatim
11 
12 
13 Copyright 2018(c) Analog Devices, Inc.
14 
15 All rights reserved.
16 
17 Redistribution and use in source and binary forms, with or without
18 modification, are permitted provided that the following conditions are met:
19  - Redistributions of source code must retain the above copyright
20  notice, this list of conditions and the following disclaimer.
21  - Redistributions in binary form must reproduce the above copyright
22  notice, this list of conditions and the following disclaimer in
23  the documentation and/or other materials provided with the
24  distribution.
25  - Neither the name of Analog Devices, Inc. nor the names of its
26  contributors may be used to endorse or promote products derived
27  from this software without specific prior written permission.
28  - The use of this software may or may not infringe the patent rights
29  of one or more patent holders. This license does not release you
30  from the requirement that you obtain separate licenses from these
31  patent holders to use this software.
32  - Use of the software either in source or binary form, must be run
33  on or directly connected to an Analog Devices Inc. component.
34 
35 THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
36 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
37 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
38 IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
39 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
40 LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
41 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
42 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
43 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
44 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
45 */
46 
47 //! @ingroup PMBus_SMBus
48 //! @{
49 //! @defgroup LT_PMBus LT_PMBus: PMBus commands
50 //! @}
51 
52 /*! @file
53  @ingroup LT_PMBus
54  Library File for LT_PMBus
55 */
56 #include <Arduino.h>
57 #include <stdint.h>
58 #include "Linduino.h"
59 #include "LT_PMBus.h"
60 
61 /*
62  * Be aware that many of these calls require setting the page before calling.
63  *
64  * malloc() is not checked for errors.
65  * SMBus errors are printed and swallowed.
66  * The assumption is this code will be in an embedded environment and tested,
67  * without a need to respond to errors. If that assumption does not hold,
68  * you must implement error handling.
69  */
70 
71 // Fast math is the in the LT_PMBusMath.cpp file and is optimized for performance.
72 // Setting USE_FAST_MATH to 0 uses simpler routines that are conceptually better for learning.
73 #define USE_FAST_MATH 1
74 
75 // Set to 0 for LTC3883 which does not support PEND
76 #define USE_PEND 1
77 
78 #define NOT_BUSY 1 << 6
79 #define NOT_TRANS 1 << 4
80 #if (USE_PEND)
81 #define NOT_PENDING 1 << 5
82 #else
83 #define NOT_PENDING 0
84 #endif
85 
87 {
88  smbus_ = new LT_SMBusGroup(smbus, smbus->i2cbus()->getSpeed());
89 }
90 
92 {
93  delete smbus_;
94 }
95 
97 {
98  uint16_t id;
99 
100  id = 0xFFF0 & smbus_->readWord(address, MFR_SPECIAL_ID);
101  switch (id)
102  {
103  case 0x4020:
104  return LTC3880;
105  case 0x4200:
106  return LTC3882;
107  case 0x4240:
108  return LTC3882_1;
109  case 0x4300:
110  return LTC3883;
111  case 0x4600:
112  return LTC3886;
113  case 0x47A0:
114  return LTM4675;
115  case 0x4400:
116  return LTM4676;
117  case 0x4480:
118  return LTM4676;
119  case 0x47E0:
120  return LTM4676A;
121  case 0x47B0:
122  return LTM4677;
123  case 0x0210:
124  return LTC2974;
125  case 0x0220:
126  return LTC2975;
127  case 0x0130:
128  return LTC2977;
129  case 0x8030:
130  return LTC2980;
131  case 0x8040:
132  return LTC2980;
133  case 0x8010:
134  return LTM2987;
135  case 0x8020:
136  return LTM2987;
137  case 0x0110:
138  return LTC2978;
139  case 0x0120:
140  return LTC2978;
141  default:
142  return LTCUnknown;
143  }
144 }
145 
147 {
148  PsmDeviceType t = deviceType(address);
149  return (t == LTC2974 || t == LTC2975 || t == LTC2977 || t == LTC2978 || t == LTC2980 || t == LTM2987);
150 }
151 
153 {
154  PsmDeviceType t = deviceType(address);
155  return (t == LTC2977 || t == LTC2980 || t == LTM2987);
156 }
157 
159 {
160  PsmDeviceType t = deviceType(address);
161  return (t == LTC2974 || t == LTC2975);
162 }
163 
165 {
166  bool is_ltc2978;
167  uint8_t mfr_common;
168  mfr_common = smbus_->readByte(address, MFR_COMMON);
169  is_ltc2978 = ((mfr_common & (1 << 2)) == 0);
170  return is_ltc2978;
171 }
172 
173 /*
174  * Write a byte with polling
175  *
176  * address: SMBUS address
177  * command: SMBUS command
178  * data: data to send
179  */
180 void LT_PMBus::pmbusWriteByteWithPolling(uint8_t address, uint8_t command, uint8_t data)
181 {
182  smbus_->waitForAck(address, 0x00);
183  if (waitForNotBusy(address) == 1) //! 1) Wait for not busy
184  {
185  // Device cannot be made not busy...
186  }
187 
188  smbus_->writeByte(address, command, data); //! 2) Write Byte
189 }
190 
191 /*
192  * Read one byte with polling
193  *
194  * address: SMBUS address
195  * command: SMB command
196  */
197 uint8_t LT_PMBus::pmbusReadByteWithPolling(uint8_t address, uint8_t command)
198 {
199  uint8_t return_value;
200 
201  smbus_->waitForAck(address, 0x00);
202  if (waitForNotBusy(address) == 1) //! 1) Wait for not busy
203  {
204  // Device cannot be made not busy...
205  }
206 
207  return_value = smbus_->readByte(address, command); //! 2) Read Byte
208 
209  return return_value;
210 }
211 
212 /*
213  * Read word with polling
214  *
215  * address: SMBUS address
216  * command: SMBUS command
217  */
218 uint16_t LT_PMBus::pmbusReadWordWithPolling(uint8_t address, uint8_t command)
219 {
220  uint16_t return_value;
221 
222  smbus_->waitForAck(address, 0x00);
223  if (waitForNotBusy(address) == 1) //! 1) Wait for not busy
224  {
225  // Device cannot be made not busy...
226  }
227 
228  return_value = smbus_->readWord(address, command);//! 2) Read Word
229 
230  return return_value;
231 }
232 
233 /*
234  * Set the output voltage
235  *
236  * address: PMBUS address
237  * voltage: the target voltage
238  */
239 void LT_PMBus::setVout(uint8_t address, float voltage)
240 {
241  uint16_t vout;
242 
243 #if USE_FAST_MATH
244  LT_PMBusMath::lin16_t vout_mode;
245  vout_mode = (LT_PMBusMath::lin16_t)(smbus_->readByte(address, VOUT_MODE) & 0x1F); //! 1) Read VOUT_MODE & 0x1F
246  vout = math_.float_to_lin16(voltage, vout_mode); //! 2) Convert voltage to Lin16
247 #else
248  vout = Float_to_L16(address, voltage);
249 #endif
250  smbus_->writeWord(address, VOUT_COMMAND, vout); //! 3) Write VOUT_COMMAND
251 }
252 
253 /*
254  * Set the output voltage
255  *
256  * address: PMBUS address
257  * voltage: the target voltage
258  * page: page
259  */
260 void LT_PMBus::setVoutWithPage(uint8_t address, float voltage, uint8_t page)
261 {
262  setPage(address, page);
263  setVout(address, voltage);
264 }
265 
266 /*
267  * Set the output voltage
268  *
269  * address: PMBUS address
270  * voltage: the target voltage
271  * page: page
272  */
273 void LT_PMBus::setVoutWithPagePlus(uint8_t address, float voltage, uint8_t page)
274 {
275  uint16_t vout;
276  uint8_t data[4];
277 
278 #if USE_FAST_MATH
279  LT_PMBusMath::lin16_t vout_mode;
280  vout_mode = (LT_PMBusMath::lin16_t)(smbus_->readByte(address, VOUT_MODE) & 0x1F); //! 1) Read VOUT_MODE & 0x1F
281  vout = math_.float_to_lin16(voltage, vout_mode); //! 2) Convert voltage to Lin16
282 #else
283  vout = Float_to_L16(address, voltage);
284 #endif
285 
286  data[0] = page;
287  data[1] = VOUT_COMMAND;
288  data[2] = 0xFF & vout;
289  data[3] = vout >> 8;
290  smbus_->writeBlock(address, PAGE_PLUS_WRITE, data, 4); //! 3) Write VOUT_COMMAND
291 }
292 
293 /*
294  * Set the output voltage, margin voltage, and warning voltage
295  *
296  * address: PMBUS address
297  * voltage: output voltage
298  * margin_percent: percent to margin high/low
299  * warn_percent: percent to set warning voltage high/low
300  * fault_percent: percent to set fault voltage high/low
301  *
302  * This will move values in order that prevents fault. However, there are no delays between changes.
303  */
304 void LT_PMBus::setVoutWithSupervision(uint8_t address, float voltage, float margin_percent, float warn_percent, float fault_percent)
305 {
306  float old_vout;
307 
308  old_vout = readVout(address, false); //! 1) Read VOUT
309 
310  if (voltage >= old_vout)
311  {
312  setVoutOvFaultLimit(address, voltage * (1.0 + fault_percent)); //! 2a) Set VOUT_OV_FAULT
313  setVoutOvWarnLimit(address, voltage * (1.0 + warn_percent)); //! 3a) Set VOUT_OV_WARN
314  setVoutMarginHigh(address, voltage * (1.0 + margin_percent)); //! 4a) Set VOUT_MARGIN_HIGH
315  setVout(address, voltage); //! 5a) Set VOUT
316  setVoutMarginLow(address, voltage * (1.0 - margin_percent)); //! 6a) Set VOUT_MARGIN_LOW
317  setVoutUvWarnLimit(address, voltage * (1.0 - warn_percent)); //! 7a) Set VOUT_UV_WARN_LIMIT
318  setVoutUvFaultLimit(address, voltage * (1.0 - fault_percent)); //! 8a) Set VOUT_UV_FAULT_LIMIT
319  }
320  else
321  {
322  setVoutUvFaultLimit(address, voltage * (1.0 - fault_percent)); //! 2b) Set VOUT_UV_FAULT_LIMIT
323  setVoutUvWarnLimit(address, voltage * (1.0 - warn_percent));//! 3b) Set VOUT_UV_WARN_LIMIT
324  setVoutMarginLow(address, voltage * (1.0 - margin_percent));//! 4b) Set VOUT_MARGIN_LOW
325  setVout(address, voltage); //! 5b) Set VOUT
326  setVoutMarginHigh(address, voltage * (1.0 + margin_percent)); //! 6b) Set VOUT_MARGIN_HIGH
327  setVoutOvWarnLimit(address, voltage * (1.0 + warn_percent)); //! 7b) Set VOUT_OV_WARN
328  setVoutOvFaultLimit(address, voltage * (1.0 + fault_percent)); //! 8b) Set VOUT_OV_FAULT
329  }
330 }
331 
332 /*
333  * Set the output voltage, margin voltage, and warning voltage
334  *
335  * address: PMBUS address
336  * voltage: output voltage
337  * margin_percent: percent to margin high/low
338  * warn_percent: percent to set warning voltage high/low
339  * fault_percent: percent to set fault voltage high/low
340  * page: page
341  *
342  * This will move values in order that prevents fault. However, there are no delays between changes.
343  */
345  float margin_percent, float warn_percent, float fault_percent, uint8_t page)
346 {
347  setPage(address, page);
348  setVoutWithSupervision(address, voltage, margin_percent, warn_percent, fault_percent);
349 }
350 
351 /*
352  * Set the output voltage, margin voltage, and warning voltage
353  *
354  * address: PMBUS address
355  * voltage: output voltage
356  * margin_percent: percent to margin high/low
357  * warn_percent: percent to set warning voltage high/low
358  * fault_percent: percent to set fault voltage high/low
359  * page: page
360  *
361  * This will move values in order that prevents fault. However, there are no delays between changes.
362  */
364  float margin_percent, float warn_percent, float fault_percent, uint8_t page)
365 {
366  float old_vout;
367 
368  old_vout = readVoutWithPage(address, page); //! 1) Read VOUT
369 
370  if (voltage >= old_vout)
371  {
372  setVoutOvFaultLimitWithPagePlus(address, voltage * (1.0 + fault_percent), page); //! 2a) Set VOUT_OV_FAULT
373  setVoutOvWarnLimitWithPagePlus(address, voltage * (1.0 + warn_percent), page); //! 3a) Set VOUT_OV_WARN
374  setVoutMarginHighWithPagePlus(address, voltage * (1.0 + margin_percent), page); //! 4a) Set VOUT_MARGIN_HIGH
375  setVoutWithPagePlus(address, voltage, page); //! 5a) Set VOUT
376  setVoutMarginLowWithPagePlus(address, voltage * (1.0 - margin_percent), page); //! 6a) Set VOUT_MARGIN_LOW
377  setVoutUvWarnLimitWithPagePlus(address, voltage * (1.0 - warn_percent), page); //! 7a) Set VOUT_UV_WARN_LIMIT
378  setVoutUvFaultLimitWithPagePlus(address, voltage * (1.0 - fault_percent), page); //! 8a) Set VOUT_UV_FAULT_LIMIT
379  }
380  else
381  {
382  setVoutUvFaultLimitWithPagePlus(address, voltage * (1.0 - fault_percent), page); //! 2b) Set VOUT_UV_FAULT_LIMIT
383  setVoutUvWarnLimitWithPagePlus(address, voltage * (1.0 - warn_percent), page);//! 3b) Set VOUT_UV_WARN_LIMIT
384  setVoutMarginLowWithPagePlus(address, voltage * (1.0 - margin_percent), page);//! 4b) Set VOUT_MARGIN_LOW
385  setVoutWithPagePlus(address, voltage, page); //! 5b) Set VOUT
386  setVoutMarginHighWithPagePlus(address, voltage * (1.0 + margin_percent), page); //! 6b) Set VOUT_MARGIN_HIGH
387  setVoutOvWarnLimitWithPagePlus(address, voltage * (1.0 + warn_percent), page); //! 7b) Set VOUT_OV_WARN
388  setVoutOvFaultLimitWithPagePlus(address, voltage * (1.0 + fault_percent), page); //! 8b) Set VOUT_OV_FAULT
389  }
390 }
391 
392 /*
393  * Set the maximum voltage
394  *
395  * address: PMBUS address
396  * voltage: maximum voltage
397  */
399 {
400  uint16_t vout;
401 
402 #if USE_FAST_MATH
403  LT_PMBusMath::lin16_t vout_mode;
404  vout_mode = (LT_PMBusMath::lin16_t)(smbus_->readByte(address, VOUT_MODE) & 0x1F); //! 1) Read VOUT_MODE & 0x1F
405  vout = math_.float_to_lin16(voltage, vout_mode); //! 2) Convert to Lin16
406 #else
407 
408  vout = Float_to_L16(address, voltage);
409 #endif
410  smbus_->writeWord(address, VOUT_MAX, vout); //! 3) Write VOUT_MAX
411 }
412 
413 /*
414  * Set the maximum voltage
415  *
416  * address: PMBUS address
417  * voltage: maximum voltage
418  * page: page
419  */
420 void LT_PMBus::setVoutMaxWithPage(uint8_t address, float voltage, uint8_t page)
421 {
422  setPage(address, page);
423  setVoutMax(address, voltage);
424 }
425 
426 /*
427  * Set the maximum voltage
428  *
429  * address: PMBUS address
430  * voltage: maximum voltage
431  * page: page
432  */
434 {
435  uint16_t vout;
436  uint8_t data[4];
437 
438 #if USE_FAST_MATH
439  LT_PMBusMath::lin16_t vout_mode;
440  vout_mode = (LT_PMBusMath::lin16_t)(smbus_->readByte(address, VOUT_MODE) & 0x1F); //! 1) Read VOUT_MODE & 0x1F
441  vout = math_.float_to_lin16(voltage, vout_mode); //! 2) Convert to Lin16
442 #else
443  vout = Float_to_L16(address, voltage);
444 #endif
445 
446  data[0] = page;
447  data[1] = VOUT_MAX;
448  data[2] = 0xFF & vout;
449  data[3] = vout >> 8;
450  smbus_->writeBlock(address, PAGE_PLUS_WRITE, data, 4); //! 3) Write VOUT_MAX
451 }
452 
453 
454 /*
455  * Set the TON_DELAY
456  *
457  * address: PMBUS address
458  * delay: delay
459  */
460 void LT_PMBus::setTonDelay(uint8_t address, float delay)
461 {
462  uint16_t time;
463 
464 #if USE_FAST_MATH
465  time = math_.float_to_lin11(delay); //! 1) Convert to Lin11
466 #else
467  time = Float_to_L11(delay);
468 #endif
469 
470  smbus_->writeWord(address, TON_DELAY, time); //! 2) Write TON_DELAY
471 }
472 
473 /*
474  * Set the TON_RISE
475  *
476  * address: PMBUS address
477  * rise: rise time
478  */
479 void LT_PMBus::setTonRise(uint8_t address, float rise)
480 {
481  uint16_t time;
482 
483 #if USE_FAST_MATH
484  time = math_.float_to_lin11(rise); //! 1) Convert to Lin11
485 #else
486  time = Float_to_L11(rise);
487 #endif
488 
489  smbus_->writeWord(address, TON_RISE, time); //! 2) Write TON_RISE
490 }
491 
492 /*
493  * Set the TON_MAX
494  *
495  * address: PMBUS address
496  * max: max time
497  */
498 void LT_PMBus::setTonMaxFaultLimit(uint8_t address, float max)
499 {
500  uint16_t time;
501 
502 #if USE_FAST_MATH
503  time = math_.float_to_lin11(max); //! 1) Convert to Lin11
504 #else
505  time = Float_to_L11(max);
506 #endif
507 
508  smbus_->writeWord(address, TON_MAX_FAULT_LIMIT, time); //! 2) Write TON_MAX_FAULT_LIMIT
509 }
510 
511 /*
512  * Set the TOFF_DELAY
513  *
514  * address: PMBUS address
515  * delay: delay
516  */
517 void LT_PMBus::setToffDelay(uint8_t address, float delay)
518 {
519  uint16_t time;
520 
521 #if USE_FAST_MATH
522  time = math_.float_to_lin11(delay); //! 1) Convert to Lin11
523 #else
524  time = Float_to_L11(delay);
525 #endif
526 
527  smbus_->writeWord(address, TOFF_DELAY, time); //! 2) Write TOFF_DELAY
528 }
529 
530 /*
531  * Set the TOFF_FALL
532  *
533  * address: PMBUS address
534  * fall: fall time
535  */
536 void LT_PMBus::setToffFall(uint8_t address, float fall)
537 {
538  uint16_t time;
539 
540 #if USE_FAST_MATH
541  time = math_.float_to_lin11(fall); //! 1) Convert to L11
542 #else
543  time = Float_to_L11(fall);
544 #endif
545 
546  smbus_->writeWord(address, TOFF_FALL, time); //! 2) Write TOFF_FALL
547 }
548 
549 /*
550  * Set the TOFF_MAX_WARN
551  *
552  * address: PMBUS address
553  * max: max time
554  */
555 void LT_PMBus::setToffMaxWarnLimit(uint8_t address, float max)
556 {
557  uint16_t time;
558 
559 #if USE_FAST_MATH
560  time = math_.float_to_lin11(max); //! 1) Convert to Lin11
561 #else
562  time = Float_to_L11(max);
563 #endif
564 
565  smbus_->writeWord(address, TOFF_MAX_WARN_LIMIT, time); //! 2) Write TOFF_MAX_WARN_LIMIT
566 }
567 
568 /*
569  * Set the over voltage fault
570  *
571  * address: PMBUS address
572  * voltage: fault voltage
573  */
575 {
576  uint16_t vout;
577 
578 #if USE_FAST_MATH
579  LT_PMBusMath::lin16_t vout_mode;
580  vout_mode = (LT_PMBusMath::lin16_t)(smbus_->readByte(address, VOUT_MODE) & 0x1F); //! 1) Read VOUT_MODE & 0x1F
581  vout = math_.float_to_lin16(voltage, vout_mode); //! 2) Convert to Lin16
582 #else
583  vout = Float_to_L16(address, voltage);
584 #endif
585  smbus_->writeWord(address, VOUT_OV_FAULT_LIMIT, vout); //! 3) Write VOUT_OV_FAULT_LIMIT
586 }
587 
588 /*
589  * Set the over voltage fault
590  *
591  * address: PMBUS address
592  * voltage: fault voltage
593  * page: page
594  */
596 {
597  setPage(address, page);
598  setVoutOvFaultLimit(address, voltage);
599 }
600 
601 /*
602  * Set the over voltage fault
603  *
604  * address: PMBUS address
605  * voltage: fault voltage
606  * page: page
607  */
609 {
610  uint16_t vout;
611  uint8_t data[4];
612 
613 #if USE_FAST_MATH
614  LT_PMBusMath::lin16_t vout_mode;
615  vout_mode = (LT_PMBusMath::lin16_t)(smbus_->readByte(address, VOUT_MODE) & 0x1F); //! 1) REad VOUT_MODE & 0x1F
616  vout = math_.float_to_lin16(voltage, vout_mode); //! 2) Convert to Lin16
617 #else
618  vout = Float_to_L16(address, voltage);
619 #endif
620 
621  data[0] = page;
622  data[1] = VOUT_OV_FAULT_LIMIT;
623  data[2] = 0xFF & vout;
624  data[3] = vout >> 8;
625  smbus_->writeBlock(address, PAGE_PLUS_WRITE, data, 4); //! 3) Write VOUT_OV_FAULT_LIMIT
626 }
627 
628 /*
629  * Set the over voltage warning
630  *
631  * address: PMBUS address
632  * voltage: warning voltage
633  */
635 {
636  uint16_t vout;
637 
638 #if USE_FAST_MATH
639  LT_PMBusMath::lin16_t vout_mode;
640  vout_mode = (LT_PMBusMath::lin16_t)(smbus_->readByte(address, VOUT_MODE) & 0x1F); //! 1) Read VOUT_MODE & 0x1F
641  vout = math_.float_to_lin16(voltage, vout_mode); //! 2) Convert to Lin16
642 #else
643  vout = Float_to_L16(address, voltage);
644 #endif
645  smbus_->writeWord(address, VOUT_OV_WARN_LIMIT, vout); //! 3) Write VOUT_OV_WARN_LIMIT
646 }
647 
648 /*
649  * Set the over voltage warning
650  *
651  * address: PMBUS address
652  * voltage: warning voltage
653  * page: page
654  */
656 {
657  setPage(address, page);
658  setVoutOvWarnLimit(address, voltage);
659 }
660 
661 /*
662  * Set the over voltage warning
663  *
664  * address: PMBUS address
665  * voltage: warning voltage
666  * page: page
667  */
669 {
670  uint16_t vout;
671  uint8_t data[4];
672 
673 #if USE_FAST_MATH
674  LT_PMBusMath::lin16_t vout_mode;
675  vout_mode = (LT_PMBusMath::lin16_t)(smbus_->readByte(address, VOUT_MODE) & 0x1F); //! 1) Read VOUT_MODE & 0x1F
676  vout = math_.float_to_lin16(voltage, vout_mode); //! 2) Convert to Lin16
677 #else
678  vout = Float_to_L16(address, voltage);
679 #endif
680 
681  data[0] = page;
682  data[1] = VOUT_OV_WARN_LIMIT;
683  data[2] = 0xFF & vout;
684  data[3] = vout >> 8;
685  smbus_->writeBlock(address, PAGE_PLUS_WRITE, data, 4); //! 3) Write VOUT_OV_WARN_LIMIT
686 }
687 
688 /*
689  * Set the high margin voltage
690  *
691  * address: PMBUS address
692  * voltage: margin voltage
693  */
695 {
696  uint16_t vout;
697 
698 #if USE_FAST_MATH
699  LT_PMBusMath::lin16_t vout_mode;
700  vout_mode = (LT_PMBusMath::lin16_t)(smbus_->readByte(address, VOUT_MODE) & 0x1F); //! 1) REad VOUT_MODE & 0x1F
701  vout = math_.float_to_lin16(voltage, vout_mode); //! 2) Convert to Lin16
702 #else
703  vout = Float_to_L16(address, voltage);
704 #endif
705  smbus_->writeWord(address, VOUT_MARGIN_HIGH, vout); //! 3) Write VOUT_MARGIN_HIGH
706 }
707 
708 /*
709  * Set the high margin voltage
710  *
711  * address: PMBUS address
712  * voltage: margin voltage
713  * page: page
714  */
716 {
717  setPage(address, page);
718  setVoutMarginHigh(address, voltage);
719 }
720 
721 /*
722  * Set the high margin voltage
723  *
724  * address: PMBUS address
725  * voltage: margin voltage
726  * page: page
727  */
729 {
730  uint16_t vout;
731  uint8_t data[4];
732 
733 #if USE_FAST_MATH
734  LT_PMBusMath::lin16_t vout_mode;
735  vout_mode = (LT_PMBusMath::lin16_t)(smbus_->readByte(address, VOUT_MODE) & 0x1F); //! 1) Read VOUT_MODE & 0x1F
736  vout = math_.float_to_lin16(voltage, vout_mode); //! 2) Convert to Lin16
737 #else
738  vout = Float_to_L16(address, voltage);
739 #endif
740 
741  data[0] = page;
742  data[1] = VOUT_MARGIN_HIGH;
743  data[2] = 0xFF & vout;
744  data[3] = vout >> 8;
745  smbus_->writeBlock(address, PAGE_PLUS_WRITE, data, 4); //! 3) Write VOUT_MARGIN_HIGH
746 }
747 
748 /*
749  * Set the low margin voltage
750  *
751  * address: PMBUS address
752  * voltage: margin voltage
753  */
755 {
756  uint16_t vout;
757 
758 #if USE_FAST_MATH
759  LT_PMBusMath::lin16_t vout_mode;
760  vout_mode = (LT_PMBusMath::lin16_t)(smbus_->readByte(address, VOUT_MODE) & 0x1F); //! Read VOUT_MODE & 0x1F
761  vout = math_.float_to_lin16(voltage, vout_mode); //! 2) Convert to Lin16
762 #else
763  vout = Float_to_L16(address, voltage);
764 #endif
765  smbus_->writeWord(address, VOUT_MARGIN_LOW, vout); //! 3) Write VOUT_MARGIN_HIGH
766 }
767 
768 /*
769  * Set the low margin voltage
770  *
771  * address: PMBUS address
772  * voltage: margin voltage
773  * page: page
774  */
776 {
777  setPage(address, page);
778  setVoutMarginLow(address, voltage);
779 }
780 
781 /*
782  * Set the low margin voltage
783  *
784  * address: PMBUS address
785  * voltage: margin voltage
786  * page: page
787  */
789 {
790  uint16_t vout;
791  uint8_t data[4];
792 
793 #if USE_FAST_MATH
794  LT_PMBusMath::lin16_t vout_mode;
795  vout_mode = (LT_PMBusMath::lin16_t)(smbus_->readByte(address, VOUT_MODE) & 0x1F); //! 1) Read VOUT_MODE & 0x1F
796  vout = math_.float_to_lin16(voltage, vout_mode); //! 2) Convert to L16
797 #else
798  vout = Float_to_L16(address, voltage);
799 #endif
800 
801  data[0] = page;
802  data[1] = VOUT_MARGIN_LOW;
803  data[2] = 0xFF & vout;
804  data[3] = vout >> 8;
805  smbus_->writeBlock(address, PAGE_PLUS_WRITE, data, 4); //! 3) Write VOUT_MARGIN_LOW
806 }
807 
808 /*
809  * Set the under voltage warning
810  *
811  * address: PMBUS address
812  * voltage: warning voltage
813  */
815 {
816  uint16_t vout;
817 
818 #if USE_FAST_MATH
819  LT_PMBusMath::lin16_t vout_mode;
820  vout_mode = (LT_PMBusMath::lin16_t)(smbus_->readByte(address, VOUT_MODE) & 0x1F); //! 1) Read VOUT_MODE & 0x1F
821  vout = math_.float_to_lin16(voltage, vout_mode); //! 2) Convert to Lin16
822 #else
823  vout = Float_to_L16(address, voltage);
824 #endif
825  smbus_->writeWord(address, VOUT_UV_WARN_LIMIT, vout); //! 3) Write VOUT_UV_WARN_LIMIT
826 }
827 
828 /*
829  * Set the under voltage warning
830  *
831  * address: PMBUS address
832  * voltage: warning voltage
833  * page: page
834  */
836 {
837  setPage(address, page);
838  setVoutUvWarnLimit(address, voltage);
839 }
840 
841 /*
842  * Set the under voltage warning
843  *
844  * address: PMBUS address
845  * voltage: warning voltage
846  * page: page
847  */
849 {
850  uint16_t vout;
851  uint8_t data[4];
852 
853 #if USE_FAST_MATH
854  LT_PMBusMath::lin16_t vout_mode;
855  vout_mode = (LT_PMBusMath::lin16_t)(smbus_->readByte(address, VOUT_MODE) & 0x1F); //! 1) Rread VOUT_MODE & 0x1F
856  vout = math_.float_to_lin16(voltage, vout_mode); //! 2) Convert to Lin16
857 #else
858  vout = Float_to_L16(address, voltage);
859 #endif
860 
861  data[0] = page;
862  data[1] = VOUT_UV_WARN_LIMIT;
863  data[2] = 0xFF & vout;
864  data[3] = vout >> 8;
865  smbus_->writeBlock(address, PAGE_PLUS_WRITE, data, 4); //! 3) Write VOUT_UV_WARN_LIMIT
866 }
867 
868 /*
869  * Set the under voltage limit
870  *
871  * address: PMBUS address
872  * voltage: limit voltage
873  */
875 {
876  uint16_t vout;
877 
878 #if USE_FAST_MATH
879  LT_PMBusMath::lin16_t vout_mode;
880  vout_mode = (LT_PMBusMath::lin16_t)(smbus_->readByte(address, VOUT_MODE) & 0x1F); //! 1) Read VOUT_MODE & 0x1F
881  vout = math_.float_to_lin16(voltage, vout_mode); //! 2) Convert to Lin16
882 #else
883  vout = Float_to_L16(address, voltage);
884 #endif
885  smbus_->writeWord(address, VOUT_UV_FAULT_LIMIT, vout); //! 3) Write VOUT_UV_FAULT_LIMIT
886 }
887 
888 /*
889  * Set the under voltage limit
890  *
891  * address: PMBUS address
892  * voltage: limit voltage
893  * page: page
894  */
896 {
897  setPage(address, page);
898  setVoutUvFaultLimit(address, voltage);
899 }
900 
901 /*
902  * Set the under voltage limit
903  *
904  * address: PMBUS address
905  * voltage: limit voltage
906  * page: page
907  */
909 {
910  uint16_t vout;
911  uint8_t data[4];
912 
913 #if USE_FAST_MATH
914  LT_PMBusMath::lin16_t vout_mode;
915  vout_mode = (LT_PMBusMath::lin16_t)(smbus_->readByte(address, VOUT_MODE) & 0x1F); //! 1) Read VOUT_MODE & 0x1F
916  vout = math_.float_to_lin16(voltage, vout_mode); //! 2) Convert to L16
917 #else
918  vout = Float_to_L16(address, voltage);
919 #endif
920 
921  data[0] = page;
922  data[1] = VOUT_UV_FAULT_LIMIT;
923  data[2] = 0xFF & vout;
924  data[3] = vout >> 8;
925  smbus_->writeBlock(address, PAGE_PLUS_WRITE, data, 4); //! 3) Write VOUT_UV_FAULT_LIMIT
926 }
927 
928 /*
929  * Set the over current fault
930  *
931  * address: PMBUS address
932  * current: fault current
933  */
935 {
936  uint16_t iout;
937 
938 #if USE_FAST_MATH
939  iout = math_.float_to_lin11(current); //! 1) Convert to Lin11
940 #else
941  iout = Float_to_L11(current);
942 #endif
943 
944  smbus_->writeWord(address, IOUT_OC_FAULT_LIMIT, iout); //! 2) Write IOUT_OC_FAULT_LIMIT
945 }
946 
947 /*
948  * Set the over current fault
949  *
950  * address: PMBUS address
951  * current: fault current
952  * page: page
953  */
955 {
956  setPage(address, page);
957  setIoutOcFaultLimit(address, current);
958 }
959 
960 /*
961  * Set the over current fault
962  *
963  * address: PMBUS address
964  * current: fault current
965  * page: page
966  */
968 {
969  uint16_t iout;
970  uint8_t data[4];
971 
972 #if USE_FAST_MATH
973  iout = math_.float_to_lin11(current); //! 1) Convert to Lin11
974 #else
975  iout = Float_to_L11(current);
976 #endif
977 
978  data[0] = page;
979  data[1] = IOUT_OC_FAULT_LIMIT;
980  data[2] = 0xFF & iout;
981  data[3] = iout >> 8;
982  smbus_->writeBlock(address, PAGE_PLUS_WRITE, data, 4); //! 2) Write IOUT_OC_FAULT_LIMIT
983 }
984 
985 /*
986  * Set the over current warning
987  *
988  * address: PMBUS address
989  * current: warning current
990  */
992 {
993  uint16_t iout;
994 
995 #if USE_FAST_MATH
996  iout = math_.float_to_lin11(current); //! 1) Convert to Lin11
997 #else
998  iout = Float_to_L11(current);
999 #endif
1000 
1001  smbus_->writeWord(address, IOUT_OC_WARN_LIMIT, iout); //! 2) Write IOUT_OC_WARN_LIMIT
1002 }
1003 
1004 /*
1005  * Set the over current warning
1006  *
1007  * address: PMBUS address
1008  * current: warning current
1009  * page: page
1010  */
1012 {
1013  setPage(address, page);
1014  setIoutOcWarnLimit(address, current);
1015 }
1016 
1017 /*
1018  * Set the over current warning
1019  *
1020  * address: PMBUS address
1021  * current: warning current
1022  * page: page
1023  */
1025 {
1026  uint16_t iout;
1027  uint8_t data[4];
1028 
1029 #if USE_FAST_MATH
1030  iout = math_.float_to_lin11(current); //! 1) Convert to Lin11
1031 #else
1032  iout = Float_to_L11(current);
1033 #endif
1034 
1035  data[0] = page;
1036  data[1] = IOUT_OC_WARN_LIMIT;
1037  data[2] = 0xFF & iout;
1038  data[3] = iout >> 8;
1039  smbus_->writeBlock(address, PAGE_PLUS_WRITE, data, 4); //! 2) Write IOUT_OC_WARN_LIMIT
1040 }
1041 
1042 /*
1043  * Set the input voltage fault
1044  *
1045  * address: PMBUS address
1046  * current: fault voltage
1047  */
1049 {
1050  uint16_t vin;
1051 
1052 #if USE_FAST_MATH
1053  vin = math_.float_to_lin11(voltage); //! 1) Convert to Lin11
1054 #else
1055  vin = Float_to_L11(voltage);
1056 #endif
1057 
1058  smbus_->writeWord(address, VIN_OV_FAULT_LIMIT, vin); //! 2) Write VIN_OV_FAULT_LIMIT
1059 }
1060 
1061 /*
1062  * Set the input voltage warning
1063  *
1064  * address: PMBUS address
1065  * current: fault voltage
1066  */
1068 {
1069  uint16_t vin;
1070 
1071 #if USE_FAST_MATH
1072  vin = math_.float_to_lin11(voltage); //! 1) Convert to Lin11
1073 #else
1074  vin = Float_to_L11(voltage);
1075 #endif
1076 
1077  smbus_->writeWord(address, VIN_OV_WARN_LIMIT, vin); //! 2) Convert to VIN_OV_WARN_LIMIT
1078 }
1079 
1080 /*
1081  * Set the input voltage fault
1082  *
1083  * address: PMBUS address
1084  * current: warning voltage
1085  */
1087 {
1088  uint16_t vin;
1089 
1090 #if USE_FAST_MATH
1091  vin = math_.float_to_lin11(voltage); //! 1) Convert to Lin11
1092 #else
1093  vin = Float_to_L11(voltage);
1094 #endif
1095 
1096  smbus_->writeWord(address, VIN_UV_FAULT_LIMIT, vin); //! 2) Write VIN_UV_FAULT_LIMIT
1097 }
1098 
1099 /*
1100  * Set the input voltage warning
1101  *
1102  * address: PMBUS address
1103  * current: warning voltage
1104  */
1106 {
1107  uint16_t vin;
1108 
1109 #if USE_FAST_MATH
1110  vin = math_.float_to_lin11(voltage); //! 1) Convert to Lin11
1111 #else
1112  vin = Float_to_L11(voltage);
1113 #endif
1114 
1115  smbus_->writeWord(address, VIN_UV_WARN_LIMIT, vin); //! 2) Write VIN_UV_WARN_LIMIT
1116 }
1117 
1118 /*
1119  * Set the input current warning
1120  *
1121  * address: PMBUS address
1122  * current: warning current
1123  */
1125 {
1126  uint16_t iin;
1127 
1128 #if USE_FAST_MATH
1129  iin = math_.float_to_lin11(current); //! 1) Convert to Lin11
1130 #else
1131  iin = Float_to_L11(current);
1132 #endif
1133 
1134  smbus_->writeWord(address, IIN_OC_WARN_LIMIT, iin); //! 2) Write IIN_OC_WARN_LIMIT
1135 }
1136 
1137 /*
1138  * Set the over temperature fault
1139  *
1140  * address: PMBUS address
1141  * current: warning temperature
1142  */
1143 void LT_PMBus::setOtFaultLimit(uint8_t address, float temperature)
1144 {
1145  uint16_t temp;
1146 
1147 #if USE_FAST_MATH
1148  temp = math_.float_to_lin11(temperature); //! 1) Convert to Lin11
1149 #else
1150  temp = Float_to_L11(temperature);
1151 #endif
1152 
1153  smbus_->writeWord(address, OT_FAULT_LIMIT, temp); //! 2) Write OT_FAULT_LIMIT
1154 }
1155 
1156 
1157 /*
1158  * Set the over temperature warning
1159  *
1160  * address: PMBUS address
1161  * current: warning temperature
1162  */
1163 void LT_PMBus::setOtWarnLimit(uint8_t address, float temperature)
1164 {
1165  uint16_t temp;
1166 
1167 #if USE_FAST_MATH
1168  temp = math_.float_to_lin11(temperature); //! 1) Convert to Lin11
1169 #else
1170  temp = Float_to_L11(temperature);
1171 #endif
1172  smbus_->writeWord(address, OT_WARN_LIMIT, temp); //! 2) Write OT_WARN_LIMIT
1173 }
1174 
1175 /*
1176  * Set the over temperature fault
1177  *
1178  * address: PMBUS address
1179  * current: warning temperature
1180  */
1181 void LT_PMBus::setOtFaultLimitWithPage(uint8_t address, float temperature, uint8_t page)
1182 {
1183  setPage(address, page);
1184  setOtFaultLimit(address, temperature);
1185 }
1186 
1187 /*
1188  * Set the over temperature fault
1189  *
1190  * address: PMBUS address
1191  * current: warning temperature
1192  */
1193 void LT_PMBus::setOtFaultLimitWithPagePlus(uint8_t address, float temperature, uint8_t page)
1194 {
1195  uint16_t temp;
1196  uint8_t data[4];
1197 
1198 #if USE_FAST_MATH
1199  temp = math_.float_to_lin11(temperature); //! 1) Convert to Lin11
1200 #else
1201  temp = Float_to_L11(temperature);
1202 #endif
1203 
1204 
1205  data[0] = page;
1206  data[1] = OT_FAULT_LIMIT;
1207  data[2] = 0xFF & temp;
1208  data[3] = temp >> 8;
1209 
1210  smbus_->writeBlock(address, PAGE_PLUS_WRITE, data, 4); //! 2) Write OT_FAULT_LIMIT
1211 }
1212 
1213 
1214 /*
1215  * Set the under temperature fault
1216  *
1217  * address: PMBUS address
1218  * current: warning temperature
1219  */
1220 void LT_PMBus::setUtFaultLimit(uint8_t address, float temperature)
1221 {
1222  uint16_t temp;
1223 
1224 #if USE_FAST_MATH
1225  temp = math_.float_to_lin11(temperature); //! 1) Convert to Lin11
1226 #else
1227  temp = Float_to_L11(temperature);
1228 #endif
1229 
1230  smbus_->writeWord(address, UT_FAULT_LIMIT, temp); //! 2) Write UT_FAULT_LIMIT
1231 }
1232 
1233 /*
1234  * Set the over temperature warning
1235  *
1236  * address: PMBUS address
1237  * current: warning temperature
1238  */
1239 void LT_PMBus::setOtWarnLimitWithPage(uint8_t address, float temperature, uint8_t page)
1240 {
1241  setPage(address, page);
1242  setOtWarnLimit(address, temperature);
1243 }
1244 
1245 /*
1246  * Set the over temperature warning
1247  *
1248  * address: PMBUS address
1249  * current: warning temperature
1250  */
1251 void LT_PMBus::setOtWarnLimitWithPagePlus(uint8_t address, float temperature, uint8_t page)
1252 {
1253  uint16_t temp;
1254  uint8_t data[4];
1255 
1256 #if USE_FAST_MATH
1257  temp = math_.float_to_lin11(temperature); //! 1) Convert to Lin11
1258 #else
1259  temp = Float_to_L11(temperature);
1260 #endif
1261 
1262  data[0] = page;
1263  data[1] = OT_WARN_LIMIT;
1264  data[2] = 0xFF & temp;
1265  data[3] = temp >> 8;
1266 
1267  smbus_->writeBlock(address, PAGE_PLUS_WRITE, data, 4); //! 2) Write OT_WARN_LIMIT
1268 }
1269 
1270 /*
1271  * Set the under temperature warning
1272  *
1273  * address: PMBUS address
1274  * current: warning temperature
1275  */
1276 void LT_PMBus::setUtWarnLimit(uint8_t address, float temperature)
1277 {
1278  uint16_t temp;
1279 
1280 #if USE_FAST_MATH
1281  temp = math_.float_to_lin11(temperature); //! 1) Confert to Lin11
1282 #else
1283  temp = Float_to_L11(temperature);
1284 #endif
1285 
1286  smbus_->writeWord(address, UT_WARN_LIMIT, temp); //! Write UT_WARN_LIMIT
1287 }
1288 
1289 /*
1290  * Set the under temperature fault
1291  *
1292  * address: PMBUS address
1293  * current: warning temperature
1294  */
1295 void LT_PMBus::setUtFaultLimitWithPage(uint8_t address, float temperature, uint8_t page)
1296 {
1297  setPage(address, page);
1298  setUtFaultLimit(address, temperature);
1299 }
1300 
1301 /*
1302  * Set the under temperature fault
1303  *
1304  * address: PMBUS address
1305  * current: warning temperature
1306  */
1307 void LT_PMBus::setUtFaultLimitWithPagePlus(uint8_t address, float temperature, uint8_t page)
1308 {
1309  uint16_t temp;
1310  uint8_t data[4];
1311 
1312 #if USE_FAST_MATH
1313  temp = math_.float_to_lin11(temperature);
1314 #else
1315  temp = Float_to_L11(temperature); //! 1) Convert to Lin11
1316 #endif
1317 
1318  data[0] = page;
1319  data[1] = UT_FAULT_LIMIT;
1320  data[2] = 0xFF & temp;
1321  data[3] = temp >> 8;
1322 
1323  smbus_->writeBlock(address, PAGE_PLUS_WRITE, data, 4); //! 2) Write UT_FAULT_LIMIT
1324 }
1325 
1326 /*
1327  * Set the under temperature warning
1328  *
1329  * address: PMBUS address
1330  * current: warning temperature
1331  */
1332 void LT_PMBus::setUtWarnLimitWithPage(uint8_t address, float temperature, uint8_t page)
1333 {
1334  setPage(address, page);
1335  setUtWarnLimit(address, temperature);
1336 }
1337 
1338 /*
1339  * Set the under temperature warning
1340  *
1341  * address: PMBUS address
1342  * current: warning temperature
1343  */
1344 void LT_PMBus::setUtWarnLimitWithPagePlus(uint8_t address, float temperature, uint8_t page)
1345 {
1346  uint16_t temp;
1347  uint8_t data[4];
1348 
1349 #if USE_FAST_MATH
1350  temp = math_.float_to_lin11(temperature); //! 1) Convert to Lin11
1351 #else
1352  temp = Float_to_L11(temperature);
1353 #endif
1354 
1355  data[0] = page;
1356  data[1] = UT_WARN_LIMIT;
1357  data[2] = 0xFF & temp;
1358  data[3] = temp >> 8;
1359 
1360  smbus_->writeBlock(address, PAGE_PLUS_WRITE, data, 4); //! 2) Write UT_WARN_LIMIT
1361 }
1362 
1363 /*
1364  * Set the temperature gain
1365  *
1366  * address: PMBUS address
1367  * gain: gain
1368  */
1369 void LT_PMBus::setTemp1Gain(uint8_t address, uint16_t gain)
1370 {
1371  smbus_->writeWord(address, MFR_TEMP_1_GAIN, gain); //! 1) Write MFR_TEMP_1_GAIN with no conversion
1372 }
1373 
1374 /*
1375  * Get the temperature gain
1376  *
1377  * address: PMBUS address
1378  * return: gain
1379  */
1381 {
1382  uint16_t temp;
1383 
1384  temp = smbus_->readWord(address, MFR_TEMP_1_GAIN); //! 1) Read MFR_TEMP_1_GAIN
1385  return temp;
1386 }
1387 
1388 /*
1389  * Set the temperature offset
1390  *
1391  * address: PMBUS address
1392  * offset: offset
1393  */
1394 void LT_PMBus::setTemp1Offset(uint8_t address, float offset)
1395 {
1396  uint16_t temp;
1397 
1398 #if USE_FAST_MATH
1399  temp = math_.float_to_lin11(offset); //! 1) Confert to Lin11
1400 #else
1401  temp = Float_to_L11(offset);
1402 #endif
1403 
1404  smbus_->writeWord(address, MFR_TEMP_1_OFFSET, temp); //! Write MFR_TEMP_1_OFFSET
1405 }
1406 
1407 /*
1408  * Get the temperature offset
1409  *
1410  * address: PMBUS address
1411  * return: offset
1412  */
1414 {
1415  uint16_t temp;
1416 
1417  temp = smbus_->readWord(address, MFR_TEMP_1_OFFSET); //! 1) Read MFR_TEMP1_OFFSET
1418 
1419 #if USE_FAST_MATH
1420  return math_.lin11_to_float(temp); //! 2) Convert from Lin11
1421 #else
1422  return L11_to_Float(temp);
1423 #endif
1424 }
1425 
1426 /*
1427  * get the over temperature warning
1428  *
1429  * address: PMBUS address
1430  * current: warning temperature
1431  */
1433 {
1434  uint16_t temp;
1435 
1436  temp = smbus_->readWord(address, OT_WARN_LIMIT); //! 1) Read OT_WARN_LIMIT
1437 
1438 #if USE_FAST_MATH
1439  return math_.lin11_to_float(temp); //! 2) Convert from Lin11
1440 #else
1441  return L11_to_Float(temp);
1442 #endif
1443 }
1444 
1445 /*
1446  * get the over temperature warning
1447  *
1448  * address: PMBUS address
1449  * current: warning temperature
1450  */
1452 {
1453  setPage(address, page);
1454  return getOtWarnLimit(address);
1455 }
1456 
1457 /*
1458  * get the over temperature warning
1459  *
1460  * address: PMBUS address
1461  * current: warning temperature
1462  */
1464 {
1465  uint16_t temp_L11;
1466  uint8_t data_in[2];
1467  uint8_t data_out[2];
1468 
1469  data_out[0] = page;
1470  data_out[1] = OT_WARN_LIMIT;
1471  smbus_->writeReadBlock(address, PAGE_PLUS_READ, data_out, 2, data_in, 2); //! 1) Read OT_WARN_LIMIT
1472  temp_L11 = (data_in[1] << 8) | data_in[0];
1473 #if USE_FAST_MATH
1474  return math_.lin11_to_float(temp_L11); //! 2) Convert from Lin11
1475 #else
1476  return L11_to_Float(temp_L11);
1477 #endif
1478 }
1479 
1480 /*
1481  * Read the input voltage
1482  *
1483  * address: PMBUS address
1484  * polling: poll if true
1485  * return: the input voltage
1486  */
1487 float LT_PMBus::readVin(uint8_t address, bool polling)
1488 {
1489  uint16_t vin_L11;
1490 
1491  // read the input voltage as an L11
1492  if (polling) //! 1) Read READ_VIN
1493  vin_L11 = pmbusReadWordWithPolling(address, READ_VIN);
1494  else
1495  vin_L11 = smbus_->readWord(address, READ_VIN);
1496 
1497  // convert L11 value to floating point value
1498 #if USE_FAST_MATH
1499  return math_.lin11_to_float(vin_L11); //! 2) Convert from L11
1500 #else
1501  return L11_to_Float(vin_L11);
1502 #endif
1503 }
1504 
1505 /*
1506  * Read the output high fault voltage
1507  *
1508  * address: PMBUS address
1509  * polling: poll if true
1510  * return: the output fault voltage
1511  */
1512 float LT_PMBus::getVoutOv(uint8_t address, bool polling)
1513 {
1514 #if USE_FAST_MATH
1515  LT_PMBusMath::lin16_t vout_mode;
1516  uint16_t vout_L16;
1517 
1518  // read the output voltage as an L16
1519  if (polling)
1520  {
1521  vout_L16 = pmbusReadWordWithPolling(address, VOUT_OV_FAULT_LIMIT); //! 1) Read VOUT_OV_FAULT_LIMIT
1522  vout_mode = (LT_PMBusMath::lin16_t)(pmbusReadByteWithPolling(address, VOUT_MODE) & 0x1F); //! 2) Read VOUT_MODE & 0x1F
1523  return math_.lin16_to_float(vout_L16, vout_mode); //! 3) Convert from L16
1524  }
1525  else
1526  {
1527  vout_L16 = smbus_->readWord(address, VOUT_OV_FAULT_LIMIT);
1528  vout_mode = (LT_PMBusMath::lin16_t)(pmbusReadByteWithPolling(address, VOUT_MODE) & 0x1F);
1529  return math_.lin16_to_float(vout_L16, vout_mode);
1530  }
1531 #else
1532  uint16_t vout_L16;
1533 
1534  // read the output voltage as an L16
1535  if (polling)
1536  {
1537  vout_L16 = pmbusReadWordWithPolling(address, VOUT_OV_FAULT_LIMIT);
1538  return L16_to_Float_with_polling(address, vout_L16);
1539  }
1540  else
1541  {
1542  vout_L16 = smbus_->readWord(address, VOUT_OV_FAULT_LIMIT);
1543  return L16_to_Float(address, vout_L16);
1544  }
1545 #endif
1546 }
1547 
1548 /*
1549  * Read the output high fault voltage
1550  *
1551  * address: PMBUS address
1552  * polling: poll if true
1553  * return: the output fault voltage
1554  * page: page
1555  */
1557 {
1558  setPage(address, page);
1559  return getVoutOv(address, false);
1560 }
1561 
1562 /*
1563  * Read the output high fault voltage
1564  *
1565  * address: PMBUS address
1566  * polling: poll if true
1567  * return: the output fault voltage
1568  * page: page
1569  */
1571 {
1572 //CHECK THIS
1573  uint16_t vout_L16;
1574  uint8_t data_in[2];
1575  uint8_t data_out[2];
1576 #if USE_FAST_MATH
1577  LT_PMBusMath::lin16_t vout_mode;
1578 #endif
1579  data_out[0] = page;
1580  data_out[1] = READ_VOUT;
1581  smbus_->writeReadBlock(address, PAGE_PLUS_READ, data_out, 2, data_in, 2); //! 1) Read READ_VOUT
1582  vout_L16 = (data_in[1] << 8) | data_in[0];
1583 #if USE_FAST_MATH
1584  vout_mode = (LT_PMBusMath::lin16_t)(smbus_->readByte(address, VOUT_MODE) & 0x1F); //! 1) Read VOUT_MODE & 0x1F
1585  return math_.lin16_to_float(vout_L16, vout_mode); //! 3) Convert from L16
1586 #else
1587  return L16_to_Float(address, vout_L16);
1588 #endif
1589 }
1590 
1591 /*
1592  * Read the output voltage
1593  *
1594  * address: PMBUS address
1595  * polling: poll if true
1596  * return: the output voltage
1597  */
1598 float LT_PMBus::readVout(uint8_t address, bool polling)
1599 {
1600  int8_t vout_mode;
1601  uint16_t vout_L16;
1602 
1603 #if USE_FAST_MATH
1604  // Read the output voltage as an L16
1605  if (polling)
1606  {
1607  vout_L16 = pmbusReadWordWithPolling(address, READ_VOUT); //! 1) Read READ_VOUT
1608  vout_mode = (LT_PMBusMath::lin16_t)(pmbusReadByteWithPolling(address, VOUT_MODE) & 0x1F); //! 2) Read VOUT_MODE & 0x1F
1609  return math_.lin16_to_float(vout_L16, vout_mode); //! 3) Convert from Lin16
1610  }
1611  else
1612  {
1613  vout_L16 = smbus_->readWord(address, READ_VOUT);
1614  vout_mode = (LT_PMBusMath::lin16_t)(smbus_->readByte(address, VOUT_MODE) & 0x1F);
1615  return math_.lin16_to_float(vout_L16, vout_mode);
1616  }
1617 #else
1618  // Read the output voltage as an L16
1619  if (polling)
1620  {
1621  vout_L16 = pmbusReadWordWithPolling(address, READ_VOUT); //! 1) Read READ_VOUT
1622  vout_mode = (LT_PMBusMath::lin16_t)(pmbusReadByteWithPolling(address, VOUT_MODE) & 0x1F); //! 2) Read VOUT_MODE & 0x1F
1623  return L16_to_Float_mode(address, vout_L16); //! 3) Convert from Lin16
1624  }
1625  else
1626  {
1627  vout_L16 = smbus_->readWord(address, READ_VOUT);
1628  vout_mode = (LT_PMBusMath::lin16_t)(smbus_->readByte(address, VOUT_MODE) & 0x1F);
1629  return L16_to_Float_mode(vout_mode, vout_L16);
1630  }
1631 #endif
1632 }
1633 
1634 float LT_PMBus::getVout(uint8_t address, bool polling)
1635 {
1636  int8_t vout_mode;
1637  uint16_t vout_L16;
1638 
1639 #if USE_FAST_MATH
1640  // Read the output voltage as an L16
1641  if (polling)
1642  {
1643  vout_L16 = pmbusReadWordWithPolling(address, VOUT_COMMAND); //! 1) Read READ_VOUT
1644  vout_mode = (LT_PMBusMath::lin16_t)(pmbusReadByteWithPolling(address, VOUT_MODE) & 0x1F); //! 2) Read VOUT_MODE & 0x1F
1645  return math_.lin16_to_float(vout_L16, vout_mode); //! 3) Convert from Lin16
1646  }
1647  else
1648  {
1649  vout_L16 = smbus_->readWord(address, VOUT_COMMAND);
1650  vout_mode = (LT_PMBusMath::lin16_t)(smbus_->readByte(address, VOUT_MODE) & 0x1F);
1651  return math_.lin16_to_float(vout_L16, vout_mode);
1652  }
1653 #else
1654  // Read the output voltage as an L16
1655  if (polling)
1656  {
1657  vout_L16 = pmbusReadWordWithPolling(address, VOUT_COMMAND); //! 1) Read READ_VOUT
1658  vout_mode = (LT_PMBusMath::lin16_t)(pmbusReadByteWithPolling(address, VOUT_MODE) & 0x1F); //! 2) Read VOUT_MODE & 0x1F
1659  return L16_to_Float_mode(address, vout_L16); //! 3) Convert from Lin16
1660  }
1661  else
1662  {
1663  vout_L16 = smbus_->readWord(address, VOUT_COMMAND);
1664  vout_mode = (LT_PMBusMath::lin16_t)(smbus_->readByte(address, VOUT_MODE) & 0x1F);
1665  return L16_to_Float_mode(vout_mode, vout_L16);
1666  }
1667 #endif
1668 }
1669 
1670 /*
1671  * Read the output voltage
1672  *
1673  * address: PMBUS address
1674  * polling: poll if true
1675  * return: the output voltage
1676  * page: page
1677  */
1678 float LT_PMBus::readVoutWithPage(uint8_t address, uint8_t page)
1679 {
1680  setPage(address, page);
1681  return readVout(address, false);
1682 }
1683 
1684 /*
1685  * Read the output voltage
1686  *
1687  * address: PMBUS address
1688  * polling: poll if true
1689  * return: the output voltage
1690  * page: page
1691  */
1693 {
1694  uint16_t vout_L16;
1695  uint8_t data_in[2];
1696  uint8_t data_out[2];
1697 #if USE_FAST_MATH
1698  LT_PMBusMath::lin16_t vout_mode;
1699 #endif
1700  data_out[0] = page;
1701  data_out[1] = READ_VOUT;
1702  smbus_->writeReadBlock(address, PAGE_PLUS_READ, data_out, 2, data_in, 2); //! 1) Read READ_VOUT
1703  vout_L16 = (data_in[1] << 8) | data_in[0];
1704 #if USE_FAST_MATH
1705  vout_mode = (LT_PMBusMath::lin16_t)(smbus_->readByte(address, VOUT_MODE) & 0x1F); //! 2) Read VOUT_MODE & 0x1F
1706  return math_.lin16_to_float(vout_L16, vout_mode); //! 3) Convert from Lin16
1707 #else
1708  return L16_to_Float(address, vout_L16);
1709 #endif
1710 }
1711 
1712 /*
1713  * Read the output low fault voltage
1714  *
1715  * address: PMBUS address
1716  * polling: poll if true
1717  * return: the output voltage
1718  */
1719 float LT_PMBus::getVoutUv(uint8_t address, bool polling)
1720 {
1721 #if USE_FAST_MATH
1722  LT_PMBusMath::lin16_t vout_mode;
1723  uint16_t vout_L16;
1724 
1725  // read the output voltage as an L16
1726  if (polling)
1727  {
1728  vout_L16 = pmbusReadWordWithPolling(address, VOUT_UV_FAULT_LIMIT); //! 1) Read VOUT_UV_FAULT_LIMIT
1729  vout_mode = (LT_PMBusMath::lin16_t)(pmbusReadByteWithPolling(address, VOUT_MODE) & 0x1F); //! 2) Read VOUT_MODE & 0x1F
1730  return math_.lin16_to_float(vout_L16, vout_mode); //! 3) Convert frmo Lin16
1731  }
1732  else
1733  {
1734  vout_L16 = smbus_->readWord(address, VOUT_UV_FAULT_LIMIT);
1735  vout_mode = (LT_PMBusMath::lin16_t)(smbus_->readByte(address, VOUT_MODE) & 0x1F);
1736  return math_.lin16_to_float(vout_L16, vout_mode);
1737  }
1738 #else
1739  uint16_t vout_L16;
1740 
1741  // read the output voltage as an L16
1742  if (polling)
1743  {
1744  vout_L16 = pmbusReadWordWithPolling(address, VOUT_UV_FAULT_LIMIT);
1745  return L16_to_Float_with_polling(address, vout_L16);
1746  }
1747  else
1748  {
1749  vout_L16 = smbus_->readWord(address, VOUT_UV_FAULT_LIMIT);
1750  return L16_to_Float(address, vout_L16);
1751  }
1752 #endif
1753 }
1754 
1755 /*
1756  * Read the output low fault voltage
1757  *
1758  * address: PMBUS address
1759  * polling: poll if true
1760  * return: the output voltage
1761  * page: page
1762  */
1764 {
1765  setPage(address, page);
1766  return getVoutUv(address, false);
1767 }
1768 
1769 /*
1770  * Read the output low fault voltage
1771  *
1772  * address: PMBUS address
1773  * polling: poll if true
1774  * return: the output voltage
1775  * page: page
1776  */
1778 {
1779  uint16_t vout_L16;
1780  uint8_t data_in[2];
1781  uint8_t data_out[2];
1782 #if USE_FAST_MATH
1783  LT_PMBusMath::lin16_t vout_mode;
1784 #endif
1785  data_out[0] = page;
1786  data_out[1] = VOUT_UV_FAULT_LIMIT;
1787  smbus_->writeReadBlock(address, PAGE_PLUS_READ, data_out, 2, data_in, 2); //! 1) Read VOUT_UV_FAULT_LIMIT
1788  vout_L16 = (data_in[1] << 8) | data_in[0];
1789 #if USE_FAST_MATH
1790  vout_mode = (LT_PMBusMath::lin16_t)(smbus_->readByte(address, VOUT_MODE) & 0x1F); //! 2) Read VOUT_MODE & 0x1F
1791  return math_.lin16_to_float(vout_L16, vout_mode); //! 3) Convert from Lin16
1792 #else
1793  return L16_to_Float(address, vout_L16);
1794 #endif
1795 }
1796 
1797 
1798 /*
1799  * Read the input current
1800  *
1801  * address: PMBUS address
1802  * polling: poll if true
1803  * return: the input current
1804  */
1805 float LT_PMBus::readIin(uint8_t address, bool polling)
1806 {
1807  uint16_t iin_L11;
1808  uint8_t command = READ_IIN;
1809  PsmDeviceType t = deviceType(address);
1810  if (t == LTC3880)
1811  command = MFR_READ_IIN;
1812 
1813  // read the input current as an L11
1814  if (polling)
1815  iin_L11 = pmbusReadWordWithPolling(address, command); //! 1) Read READ_IIN
1816  else
1817  iin_L11 = smbus_->readWord(address, command);
1818 
1819  // convert L11 value to floating point value
1820 #if USE_FAST_MATH
1821  return math_.lin11_to_float(iin_L11); //! 2) Convert from Lin11
1822 #else
1823  return L11_to_Float(iin_L11);
1824 #endif
1825 }
1826 
1827 /*
1828  * Read the output fault current
1829  *
1830  * address: PMBUS address
1831  * polling: poll if true
1832  * return: the fault current
1833  */
1834 float LT_PMBus::getIoutOc(uint8_t address, bool polling)
1835 {
1836  uint16_t iout_L11;
1837 
1838  // read the output current as an L11
1839  if (polling)
1840  iout_L11 = pmbusReadWordWithPolling(address, IOUT_OC_FAULT_LIMIT); //! 1) Read IOUT_OC_FAULT_LIMIT
1841  else
1842  iout_L11 = smbus_->readWord(address, IOUT_OC_FAULT_LIMIT);
1843 
1844  // convert L11 value to floating point value
1845 #if USE_FAST_MATH
1846  return math_.lin11_to_float(iout_L11); //! 2) Convert from Lin11
1847 #else
1848  return L11_to_Float(iout_L11);
1849 #endif
1850 }
1851 
1852 /*
1853  * Read the output fault current
1854  *
1855  * address: PMBUS address
1856  * polling: poll if true
1857  * return: the fault current
1858  * page: page
1859  */
1861 {
1862  setPage(address, page);
1863  return getIoutOc(address, false);
1864 }
1865 
1866 /*
1867  * Read the output fault current
1868  *
1869  * address: PMBUS address
1870  * polling: poll if true
1871  * return: the fault current
1872  * page: page
1873  */
1875 {
1876  uint16_t iout_L11;
1877  uint8_t data_in[2];
1878  uint8_t data_out[2];
1879 
1880  data_out[0] = page;
1881  data_out[1] = IOUT_OC_FAULT_LIMIT;
1882  smbus_->writeReadBlock(address, PAGE_PLUS_READ, data_out, 2, data_in, 2); //! 1) Read IOUT_OC_FAULT_LIMIT
1883  iout_L11 = (data_in[1] << 8) | data_in[0];
1884 #if USE_FAST_MATH
1885  return math_.lin11_to_float(iout_L11); //! 2) Convert from Lin11
1886 #else
1887  return L11_to_Float(iout_L11);
1888 #endif
1889 }
1890 
1891 /*
1892  * Read the output current
1893  *
1894  * address: PMBUS address
1895  * polling: poll if true
1896  * return: the output current
1897  */
1898 float LT_PMBus::readIout(uint8_t address, bool polling)
1899 {
1900  uint16_t iout_L11;
1901 
1902  // read the output current as an L11
1903  if (polling)
1904  iout_L11 = pmbusReadWordWithPolling(address, READ_IOUT); //! 1) REad READ_IOUT
1905  else
1906  iout_L11 = smbus_->readWord(address, READ_IOUT);
1907 
1908  // convert L11 value to floating point value
1909 #if USE_FAST_MATH
1910  return math_.lin11_to_float(iout_L11); //! 2) Convert from Lin11
1911 #else
1912  return L11_to_Float(iout_L11);
1913 #endif
1914 }
1915 
1916 /*
1917  * Read the output current
1918  *
1919  * address: PMBUS address
1920  * polling: poll if true
1921  * return: the output current
1922  * page: page
1923  */
1924 float LT_PMBus::readIoutWithPage(uint8_t address, uint8_t page)
1925 {
1926  setPage(address, page);
1927  return readIout(address, page);
1928 }
1929 
1930 /*
1931  * Read the output current
1932  *
1933  * address: PMBUS address
1934  * polling: poll if true
1935  * return: the output current
1936  * page: page
1937  */
1939 {
1940  //CHECK THIS
1941  uint16_t iout_L11;
1942  uint8_t data_in[2];
1943  uint8_t data_out[2];
1944 
1945  data_out[0] = page;
1946  data_out[1] = READ_IOUT;
1947  smbus_->writeReadBlock(address, PAGE_PLUS_READ, data_out, 2, data_in, 2); //! Read READ_IOUT
1948  iout_L11 = (data_in[1] << 8) | data_in[0];
1949 #if USE_FAST_MATH
1950  return math_.lin11_to_float(iout_L11); //! 2) Convert from Lin11
1951 #else
1952  return L11_to_Float(iout_L11);
1953 #endif
1954 }
1955 
1956 /*
1957  * Read the output power
1958  *
1959  * address: PMBUS address
1960  * polling: poll if true
1961  * return: the output power
1962  */
1963 float LT_PMBus::readPout(uint8_t address, bool polling)
1964 {
1965  uint16_t pout_L11;
1966 
1967  // read the output current as an L11
1968  if (polling)
1969  pout_L11 = pmbusReadWordWithPolling(address, READ_POUT); //! 1) REad READ_IOUT
1970  else
1971  pout_L11 = smbus_->readWord(address, READ_POUT);
1972 
1973  // convert L11 value to floating point value
1974 #if USE_FAST_MATH
1975  return math_.lin11_to_float(pout_L11); //! 2) Convert from Lin11
1976 #else
1977  return L11_to_Float(pout_L11);
1978 #endif
1979 }
1980 
1981 /*
1982  * Read the output power
1983  *
1984  * address: PMBUS address
1985  * page: page
1986  * return: the output power
1987  */
1988 float LT_PMBus::readPoutWithPage(uint8_t address, uint8_t page)
1989 {
1990  setPage(address, page);
1991  return readPout(address, false);
1992 }
1993 
1994 /*
1995  * Read the output power
1996  *
1997  * address: PMBUS address
1998  * page: page
1999  * return: the output power
2000  */
2002 {
2003  uint16_t pout_L11;
2004  uint8_t data_in[2];
2005  uint8_t data_out[2];
2006 
2007  data_out[0] = page;
2008  data_out[1] = READ_POUT;
2009 
2010  smbus_->writeReadBlock(address, PAGE_PLUS_READ, data_out, 2, data_in, 2); //! Read READ_POUT
2011  pout_L11 = (data_in[1] << 8) | data_in[0];
2012 #if USE_FAST_MATH
2013  return math_.lin11_to_float(pout_L11); //! 2) Convert from Lin11
2014 #else
2015  return L11_to_Float(pout_L11);
2016 #endif
2017 }
2018 
2019 
2020 /*
2021  * Read the input power
2022  *
2023  * address: PMBUS address
2024  * polling: poll if true
2025  * return: the output current
2026  */
2027 float LT_PMBus::readPin(uint8_t address, bool polling)
2028 {
2029  uint16_t iout_L11;
2030 
2031  // read the output current as an L11
2032  if (polling)
2033  iout_L11 = pmbusReadWordWithPolling(address, READ_PIN); //! 1) REad READ_IOUT
2034  else
2035  iout_L11 = smbus_->readWord(address, READ_PIN);
2036 
2037  // convert L11 value to floating point value
2038 #if USE_FAST_MATH
2039  return math_.lin11_to_float(iout_L11); //! 2) Convert from Lin11
2040 #else
2041  return L11_to_Float(iout_L11);
2042 #endif
2043 }
2044 
2045 /*
2046  * Read the external temperature
2047  *
2048  * address: PMBUS address
2049  * polling: poll if true
2050  * return: the temperature
2051  */
2052 float LT_PMBus::readExternalTemperature(uint8_t address, bool polling)
2053 {
2054  uint16_t temp_L11;
2055 
2056  // read the output current as an L11
2057  if (polling)
2058  temp_L11 = pmbusReadWordWithPolling(address, READ_OTEMP); //! 1) Read READ_OTEMP
2059  else
2060  temp_L11 = smbus_->readWord(address, READ_OTEMP);
2061 
2062  // convert L11 value to floating point value
2063 #if USE_FAST_MATH
2064  return math_.lin11_to_float(temp_L11); //! 2) Convert from Lin11
2065 #else
2066  return L11_to_Float(temp_L11);
2067 #endif
2068 }
2069 
2070 /*
2071  * Read the internal temperature
2072  *
2073  * address: PMBUS address
2074  * polling: poll if true
2075  * return: the temperature
2076  */
2077 float LT_PMBus::readInternalTemperature(uint8_t address, bool polling)
2078 {
2079  uint16_t temp_L11;
2080 
2081  // read the output current as an L11
2082  if (polling)
2083  temp_L11 = pmbusReadWordWithPolling(address, READ_ITEMP); //! 1) Read READ_OTEMP
2084  else
2085  temp_L11 = smbus_->readWord(address, READ_ITEMP);
2086 
2087  // convert L11 value to floating point value
2088 #if USE_FAST_MATH
2089  return math_.lin11_to_float(temp_L11); //! 2) Convert from Lin11
2090 #else
2091  return L11_to_Float(temp_L11);
2092 #endif
2093 }
2094 
2095 /*
2096  * Read the duty cycle
2097  *
2098  * address: PMBUS address
2099  * polling: poll if true
2100  * return: the duty cycle
2101  */
2102 float LT_PMBus::readDutyCycle(uint8_t address, bool polling)
2103 {
2104  uint16_t dc_L11;
2105 
2106  // read the output current as an L11
2107  if (polling)
2108  dc_L11 = pmbusReadWordWithPolling(address, READ_DUTY_CYCLE); //! 1) Read READ_DUTY_CYCLE
2109  else
2110  dc_L11 = smbus_->readWord(address, READ_DUTY_CYCLE);
2111 
2112  // convert L11 value to floating point value
2113 #if USE_FAST_MATH
2114  return math_.lin11_to_float(dc_L11); //! 2) Convert from Lin11
2115 #else
2116  return L11_to_Float(dc_L11);
2117 #endif
2118 }
2119 
2120 /*
2121  * Read the internal temperature
2122  *
2123  * address: PMBUS address
2124  * polling: poll if true
2125  * return: the output current
2126  */
2128 {
2129  uint16_t temp_L11;
2130 
2131  // read the output current as an L11
2132  temp_L11 = smbus_->readWord(address, READ_ITEMP);
2133 
2134  // convert L11 value to floating point value
2135 #if USE_FAST_MATH
2136  return math_.lin11_to_float(temp_L11); //! 2) Convert from Lin11
2137 #else
2138  return L11_to_Float(temp_L11);
2139 #endif
2140 }
2141 
2142 /*
2143  * Read the output temperature
2144  *
2145  * address: PMBUS address
2146  * polling: poll if true
2147  * return: the temperature
2148  * page: page
2149  */
2151 {
2152  //CHECK THIS
2153  uint16_t temp_L11;
2154  uint8_t data_in[2];
2155  uint8_t data_out[2];
2156 
2157  data_out[0] = page;
2158  data_out[1] = READ_OTEMP;
2159  smbus_->writeReadBlock(address, PAGE_PLUS_READ, data_out, 2, data_in, 2); //! 1)Read READ_OTEMP
2160  temp_L11 = (data_in[1] << 8) | data_in[0];
2161 #if USE_FAST_MATH
2162  return math_.lin11_to_float(temp_L11); //! 2) Convert frmo Lin11
2163 #else
2164  return L11_to_Float(temp_L11);
2165 #endif
2166 }
2167 
2168 /*
2169  * Read the output temperature
2170  *
2171  * address: PMBUS address
2172  * polling: poll if true
2173  * return: the output current
2174  */
2176 {
2177  uint16_t temp_L11;
2178 
2179  // read the output current as an L11
2180  temp_L11 = smbus_->readWord(address, READ_OTEMP);
2181 
2182  // convert L11 value to floating point value
2183 #if USE_FAST_MATH
2184  return math_.lin11_to_float(temp_L11); //! 2) Convert from Lin11
2185 #else
2186  return L11_to_Float(temp_L11);
2187 #endif
2188 }
2189 
2190 void LT_PMBus::setVoutStatusMask(uint8_t address, uint8_t mask)
2191 {
2192  uint16_t data;
2193 
2194  data = (mask << 8) | STATUS_VOUT;
2195  smbus_->writeWord(address, SMBALERT_MASK, data);
2196 }
2197 
2198 void LT_PMBus::setIoutStatusMask(uint8_t address, uint8_t mask)
2199 {
2200  uint16_t data;
2201 
2202  data = (mask << 8) | STATUS_IOUT;
2203  smbus_->writeWord(address, SMBALERT_MASK, data);
2204 }
2205 
2206 void LT_PMBus::setInputStatusMask(uint8_t address, uint8_t mask)
2207 {
2208  uint16_t data;
2209 
2210  data = (mask << 8) | STATUS_INPUT;
2211  smbus_->writeWord(address, SMBALERT_MASK, data);
2212 }
2213 
2214 void LT_PMBus::setTemperatureStatusMask(uint8_t address, uint8_t mask)
2215 {
2216  uint16_t data;
2217 
2218  data = (mask << 8) | STATUS_TEMP;
2219  smbus_->writeWord(address, SMBALERT_MASK, data);
2220 }
2221 
2222 void LT_PMBus::setCmlStatusMask(uint8_t address, uint8_t mask)
2223 {
2224  uint16_t data;
2225 
2226  data = (mask << 8) | STATUS_CML;
2227  smbus_->writeWord(address, SMBALERT_MASK, data);
2228 }
2229 
2230 void LT_PMBus::setMfrStatusMask(uint8_t address, uint8_t mask)
2231 {
2232  uint16_t data;
2233 
2234  data = (mask << 8) | STATUS_MFR_SPECIFIC;
2235  smbus_->writeWord(address, SMBALERT_MASK, data);
2236 }
2237 
2239 {
2240  uint8_t data_out[1];
2241  uint8_t data_in[1];
2242 
2243  data_out[0] = STATUS_VOUT;
2244 
2245  smbus_->writeReadBlock(address, SMBALERT_MASK, data_out, 1, data_in, 1);
2246 
2247  return data_in[0];
2248 }
2249 
2251 {
2252  uint8_t data_out[1];
2253  uint8_t data_in[1];
2254 
2255  data_out[0] = STATUS_IOUT;
2256 
2257  smbus_->writeReadBlock(address, SMBALERT_MASK, data_out, 1, data_in, 1);
2258 
2259  return data_in[0];
2260 }
2261 
2263 {
2264  uint8_t data_out[1];
2265  uint8_t data_in[1];
2266 
2267  data_out[0] = STATUS_INPUT;
2268 
2269  smbus_->writeReadBlock(address, SMBALERT_MASK, data_out, 1, data_in, 0);
2270 
2271  return data_in[0];
2272 }
2273 
2275 {
2276  uint8_t data_out[1];
2277  uint8_t data_in[1];
2278 
2279  data_out[0] = STATUS_TEMP;
2280 
2281  smbus_->writeReadBlock(address, SMBALERT_MASK, data_out, 1, data_in, 1);
2282 
2283  return data_in[0];
2284 }
2285 
2287 {
2288  uint8_t data_out[1];
2289  uint8_t data_in[1];
2290 
2291  data_out[0] = STATUS_CML;
2292 
2293  smbus_->writeReadBlock(address, SMBALERT_MASK, data_out, 1, data_in, 1);
2294 
2295  return data_in[0];
2296 }
2297 
2299 {
2300  uint8_t data_out[1];
2301  uint8_t data_in[1];
2302 
2303  data_out[0] = STATUS_MFR_SPECIFIC;
2304 
2305  smbus_->writeReadBlock(address, SMBALERT_MASK, data_out, 1, data_in, 1);
2306 
2307  return data_in[0];
2308 }
2309 
2311 {
2312  uint8_t status_byte;
2313 
2314  status_byte = smbus_->readByte(address, STATUS_VOUT);
2315  return status_byte;
2316 }
2317 
2319 {
2320  uint8_t status_byte;
2321 
2322  status_byte = smbus_->readByte(address, STATUS_IOUT);
2323  return status_byte;
2324 }
2325 
2327 {
2328  uint8_t status_byte;
2329 
2330  status_byte = smbus_->readByte(address, STATUS_INPUT);
2331  return status_byte;
2332 }
2333 
2335 {
2336  uint8_t status_byte;
2337 
2338  status_byte = smbus_->readByte(address, STATUS_INPUT);
2339  return status_byte;
2340 }
2341 
2343 {
2344  uint8_t status_byte;
2345 
2346  status_byte = smbus_->readByte(address, STATUS_CML);
2347  return status_byte;
2348 }
2349 
2351 {
2352  uint8_t status_byte;
2353 
2354  status_byte = smbus_->readByte(address, STATUS_MFR_SPECIFIC);
2355  return status_byte;
2356 }
2357 
2359 {
2360  uint8_t status_byte;
2361 
2362  status_byte = smbus_->readByte(address, MFR_FAULT_LOG_STATUS);
2363  return status_byte;
2364 }
2365 
2367 {
2368  uint16_t status_word;
2369 
2370  status_word = smbus_->readWord(address, MFR_PADS);
2371  return status_word;
2372 }
2373 
2374 /*
2375  * Read the pmbus revision
2376  *
2377  * address: PMBUS address
2378  * return: revision
2379  */
2381 {
2382  uint8_t revision;
2383 
2384  return revision;
2385 }
2386 
2387 /*
2388  * Read the slave revision
2389  *
2390  * address: PMBUS address
2391  * return: revision
2392  */
2393 void LT_PMBus::readRevision(uint8_t address, uint8_t *revision)
2394 {
2395  uint8_t buffer[8];
2396 
2397  // This keeps memory problems out of the driver code where it is
2398  // easier to deal with.
2399  memcpy(revision, buffer, 7);
2400  revision[7] = '\0';
2401 }
2402 
2403 /*
2404  * Read the pmbus model
2405  *
2406  * address: PMBUS address
2407  * return: revision
2408  */
2409 void LT_PMBus::readModel(uint8_t address, uint8_t *model)
2410 {
2411  uint8_t block_size;
2412 
2413  block_size = smbus_->readBlock(address, MFR_MODEL, model, 8);
2414  model[block_size] = '\0';
2415 }
2416 
2417 /*
2418  * Read the status byte
2419  *
2420  * address: PMBUS address
2421  * return: status byte
2422  */
2424 {
2425  uint8_t status_byte;
2426 
2427  status_byte = smbus_->readByte(address, STATUS_BYTE);
2428  return status_byte;
2429 }
2430 
2431 /*
2432  * Read the status byte
2433  *
2434  * address: PMBUS address
2435  * page: PMBUS page
2436  * return: status byte
2437  */
2439 {
2440  setPage(address, page);
2441  return readStatusByte(address);
2442 }
2443 
2444 /*
2445  * Read the status byte
2446  *
2447  * address: PMBUS address
2448  * page: PMBUS page
2449  * return: status byte
2450  */
2452 {
2453  uint8_t data_in[1];
2454  uint8_t data_out[2];
2455  uint8_t status_byte;
2456 
2457  data_out[0] = page;
2458  data_out[1] = STATUS_BYTE;
2459  smbus_->writeReadBlock(address, PAGE_PLUS_READ, data_out, 2, data_in, 1);
2460  status_byte = data_in[0];
2461  return status_byte;
2462 }
2463 
2464 /*
2465  * Read the status word
2466  *
2467  * address: PMBUS address
2468  * return: status word
2469  */
2471 {
2472  uint16_t status_word;
2473 
2474  status_word = smbus_->readWord(address, STATUS_WORD);
2475  return status_word;
2476 }
2477 
2478 /*
2479  * Read the status word
2480  *
2481  * address: PMBUS address
2482  * page: PMBUS page
2483  * return: status word
2484  */
2486 {
2487  setPage(address, page);
2488  return readStatusWord(address);
2489 }
2490 
2491 /*
2492  * Read the status word
2493  *
2494  * address: PMBUS address
2495  * page: PMBUS page
2496  * return: status word
2497  */
2499 {
2500  uint8_t data_in[2];
2501  uint8_t data_out[2];
2502  uint8_t status_word;
2503 
2504  data_out[0] = page;
2505  data_out[1] = STATUS_WORD;
2506  smbus_->writeReadBlock(address, PAGE_PLUS_READ, data_out, 2, data_in, 2);
2507  status_word = (data_in[1] << 8) | data_in[0];
2508  return status_word;
2509 }
2510 
2511 /*
2512  * Read the status CML byte
2513  *
2514  * address: PMBUS address
2515  * return: status byte
2516  */
2518 {
2519  uint8_t status_byte;
2520 
2521  status_byte = smbus_->readByte(address, STATUS_CML);
2522  return status_byte;
2523 }
2524 
2525 /*
2526  * Enable write protect
2527  *
2528  * address: PMBUS address
2529  */
2531 {
2532  smbus_->writeByte(address, WRITE_PROTECT, 0x80);
2533 }
2534 
2535 /*
2536  * Enable write protect
2537  */
2539 {
2540  smbus_->writeByte(0x5B, WRITE_PROTECT, 0x80);
2541 }
2542 
2543 /*
2544  * Disable write protect
2545  *
2546  * address: PMBUS address
2547  */
2549 {
2550  smbus_->writeByte(address, WRITE_PROTECT, 0x00);
2551 }
2552 
2553 /*
2554  * Disable write protect
2555  */
2557 {
2558  smbus_->writeByte(0x5B, WRITE_PROTECT, 0x00);
2559 }
2560 
2561 /*
2562  * Clear faults
2563  *
2564  * address: PMBUS address
2565  */
2567 {
2568  smbus_->sendByte(address, CLEAR_FAULTS);
2569 }
2570 
2571 /*
2572  * Clear all faults
2573  *
2574  * address: PMBUS address
2575  */
2577 {
2578  uint8_t page;
2579 
2580  if (isLtc2974(address))
2581  {
2582  for (page = 0x00; page <= 0x03; page++)
2583  {
2584  setPage(address, page);
2585  smbus_->sendByte(address, CLEAR_FAULTS);
2586  }
2587  }
2588  else if (isLtc2977(address))
2589  {
2590  for (page = 0x00; page <= 0x07; page++)
2591  {
2592  setPage(address, page);
2593  smbus_->sendByte(address, CLEAR_FAULTS);
2594  }
2595  }
2596  else
2597  {
2598  setPage(address, 0xFF);
2599  smbus_->sendByte(address, CLEAR_FAULTS);
2600  }
2601 }
2602 
2603 /*
2604  * Clear all faults on all rails
2605  */
2607 {
2608  // This is the best possible without knowledge of what is on the bus.
2609 
2610  // Clear all pages for devices that can do so.
2611  setPage(0x5B, 0xFF);
2612  smbus_->sendByte(0x5B, CLEAR_FAULTS);
2613 
2614 
2615  // Use 0x00 for any devices that don't do 0xFF. Will not clear other pages.
2616  setPage(0x5B, 0x00);
2617  smbus_->sendByte(0x5B, CLEAR_FAULTS);
2618 }
2619 
2620 /*
2621  * Set the first watch dog value
2622  *
2623  * address: PMBUS address
2624  * delay: time to wait
2625  */
2626 void LT_PMBus::setMfrWatchdogFirst(uint8_t address, float delay)
2627 {
2628  uint16_t time;
2629 
2630 #if USE_FAST_MATH
2631  time = math_.float_to_lin11(delay);
2632 #else
2633  time = Float_to_L11(delay);
2634 #endif
2635 
2636  smbus_->writeWord(address, MFR_WATCHDOG_T_FIRST, time);
2637 }
2638 
2639 /*
2640  * Set the first watch dog value
2641  *
2642  * address: PMBUS address
2643  * delay: time to wait
2644  */
2645 void LT_PMBus::setMfrWatchdog(uint8_t address, float delay)
2646 {
2647  uint16_t time;
2648 
2649 #if USE_FAST_MATH
2650  time = math_.float_to_lin11(delay); //! 1) Convert to Lin11
2651 #else
2652  time = Float_to_L11(delay);
2653 #endif
2654 
2655  smbus_->writeWord(address, MFR_WATCHDOG_T, time); //! 2) Write MFR_WATCHDOG_T
2656 }
2657 
2658 /*
2659  * Restore all values from non-volatile memory
2660  *
2661  * address: PMBUS address
2662  */
2664 {
2665  smbus_->sendByte(address, RESTORE_USER_ALL);
2666 }
2667 
2668 /*
2669  * Restore all values from non-volatile memory
2670  *
2671  * address: PMBUS address
2672  */
2673 void LT_PMBus::restoreFromNvmAll(uint8_t *addresses, uint8_t no_addresses)
2674 {
2675  uint8_t index;
2676  for (index = 0; index < no_addresses; index++)
2677  smbus_->sendByte(addresses[index], RESTORE_USER_ALL);
2678 }
2679 
2680 /*
2681  * Restore all values from non-volatile memory
2682  */
2684 {
2685  smbus_->sendByte(0x5B, RESTORE_USER_ALL);
2686 }
2687 
2689 {
2690  smbus_->sendByte(address, STORE_USER_ALL);
2691 }
2692 
2693 void LT_PMBus::storeToNvmAll(uint8_t *addresses, uint8_t no_addresses)
2694 {
2695  uint8_t index;
2696  for (index = 0; index < no_addresses; index++)
2697  smbus_->sendByte(addresses[index], STORE_USER_ALL);
2698 }
2699 
2701 {
2702  smbus_->sendByte(0x5B, STORE_USER_ALL);
2703 }
2704 
2706 {
2707  uint8_t d;
2708 
2709  if (lockNVM(address))
2710  {
2711  Serial.print(F("Unlock failed during lock on address "));
2712  Serial.println(address, HEX);
2713  return true;
2714  }
2715 
2716  waitForNotBusy(address);
2717  smbus_->writeByte(address, MFR_EE_UNLOCK, 0x2B);
2718  waitForNotBusy(address);
2719  smbus_->writeByte(address, MFR_EE_UNLOCK, 0xD4);
2720  waitForNotBusy(address);
2721 
2722  d = smbus_->readByte(address, MFR_EE_UNLOCK);
2723  if (d == 0xD4)
2724  return false;
2725  else
2726  return true;
2727 }
2728 
2730 {
2731  uint8_t d;
2732 
2733  waitForNotBusy(address);
2734  smbus_->writeByte(address, MFR_EE_UNLOCK, 0x00);
2735  waitForNotBusy(address);
2736  d = smbus_->readByte(address, MFR_EE_UNLOCK);
2737  if (d == 0x00)
2738  return false;
2739  else
2740  return true;
2741 }
2742 
2744 {
2745  waitForNotBusy(address);
2746  smbus_->writeByte(address, MFR_EE_ERASE, 0x2B);
2747  waitForNotBusy(address);
2748 }
2749 
2751 {
2752  uint8_t status;
2753 
2754  waitForNotBusy(address);
2755  smbus_->sendByte(address, MFR_COMPARE_USER_ALL);
2756  waitForNotBusy(address);
2757  waitForNvmDone(address);
2758  status = readStatusByte(address);
2759  return ((status & 0x02) != 0);
2760 }
2761 
2762 /*
2763  * Set the page register for a list of addresses
2764  *
2765  * addresses: list of addresses
2766  * no_addresses: the length of the list
2767  */
2768 void LT_PMBus::page(uint8_t *addresses, uint8_t no_addresses)
2769 {
2770  uint8_t *commands;
2771  uint8_t *data_bytes;
2772  uint8_t index;
2773 
2774  commands = new uint8_t [no_addresses];
2775  for (index = 0; index < no_addresses; index++)
2776  commands[index] = PAGE;
2777 
2778  data_bytes = new uint8_t [no_addresses];
2779  for (index = 0; index < no_addresses; index++)
2780  data_bytes[index] = 0xFF;
2781 
2782  smbus_->writeBytes(addresses, commands, data_bytes, no_addresses);
2783 
2784  delete [] commands;
2785  delete [] data_bytes;
2786 }
2787 
2788 /*
2789  * Turn on the rails for a list of addresses
2790  *
2791  * addresses: list of addresses
2792  * no_addresses: the length of the list
2793  */
2794 void LT_PMBus::sequenceOn(uint8_t *addresses, uint8_t no_addresses)
2795 {
2796  uint8_t *commands;
2797  uint8_t *data_bytes;
2798  uint8_t index;
2799 
2800  // Not using group protocol because there may be more than one
2801  // page per device. Timing of the operation is not perfectly aligned.
2802  commands = new uint8_t [no_addresses];
2803  for (index = 0; index < no_addresses; index++)
2804  commands[index] = OPERATION;
2805 
2806  data_bytes = new uint8_t [no_addresses];
2807  for (index = 0; index < no_addresses; index++)
2808  data_bytes[index] = 0x80;
2809 
2810  smbus_->writeBytes(addresses, commands, data_bytes, no_addresses);
2811 
2812  delete [] commands;
2813  delete [] data_bytes;
2814 }
2815 
2816 /*
2817  * Turn off the rails for a list of addresses
2818  *
2819  * addresses: list of addresses
2820  * no_addresses: the length of the list
2821  */
2822 void LT_PMBus::immediateOff(uint8_t *addresses, uint8_t no_addresses)
2823 {
2824  uint8_t *commands;
2825  uint8_t *data_bytes;
2826  uint8_t index;
2827 
2828  // Not using group protocol because there may be more than one
2829  // page per device. Timing of the operation is not perfectly aligned.
2830  commands = new uint8_t [no_addresses];
2831  for (index = 0; index < no_addresses; index++)
2832  commands[index] = OPERATION;
2833 
2834  data_bytes = new uint8_t [no_addresses];
2835  for (index = 0; index < no_addresses; index++)
2836  data_bytes[index] = 0x00;
2837 
2838  smbus_->writeBytes(addresses, commands, data_bytes, no_addresses);
2839 
2840  delete [] commands;
2841  delete [] data_bytes;
2842 }
2843 
2844 /*
2845  * Sequence off the rails for a list of addresses
2846  *
2847  * addresses: list of addresses
2848  * no_addresses: the length of the list
2849  */
2850 void LT_PMBus::sequenceOff(uint8_t *addresses, uint8_t no_addresses)
2851 {
2852  uint8_t *commands;
2853  uint8_t *data_bytes;
2854  uint8_t index;
2855 
2856  // Not using group protocol because there may be more than one
2857  // page per device. Timing of the operation is not perfectly aligned.
2858  commands = new uint8_t [no_addresses];
2859  for (index = 0; index < no_addresses; index++)
2860  commands[index] = OPERATION;
2861 
2862  data_bytes = new uint8_t [no_addresses];
2863  for (index = 0; index < no_addresses; index++)
2864  data_bytes[index] = 0x40;
2865 
2866  smbus_->writeBytes(addresses, commands, data_bytes, no_addresses);
2867 
2868  delete [] commands;
2869  delete [] data_bytes;
2870 }
2871 
2872 /*
2873  * Sequence off the rails
2874  *
2875  */
2877 {
2878  setPage(0x5B, 0xFF);
2879  smbus_->writeByte(0x5B, OPERATION, 0x40);
2880 }
2881 
2882 /*
2883  * Sequence off the rails
2884  *
2885  */
2887 {
2888  setPage(0x5B, 0xFF);
2889  smbus_->writeByte(0x5B, OPERATION, 0x00);
2890 }
2891 
2892 /*
2893  * Sequence on the rails
2894  *
2895  */
2897 {
2898  setPage(0x5B, 0xFF);
2899  smbus_->writeByte(0x5B, OPERATION, 0x80);
2900 }
2901 
2902 /*
2903  * Sequence off the rails
2904  *
2905  */
2907 {
2908  setPage(0x5B, 0xFF);
2909  smbus_->sendByte(0x5B, MFR_RESET);
2910 }
2911 
2913 {
2914  smbus_->sendByte(address, MFR_RESET);
2915 }
2916 
2917 /*
2918  * Margin high rails for a list of addresses
2919  *
2920  * addresses: list of addresses
2921  * no_addresses: the length of the list
2922  */
2923 void LT_PMBus::marginHighAll(uint8_t *addresses, uint8_t *pages, uint8_t no_addresses)
2924 {
2925  uint8_t *addrs;
2926  uint8_t *commands;
2927  uint8_t *data_bytes;
2928  uint8_t index;
2929  uint8_t pos;
2930 
2931  addrs = new uint8_t [2*no_addresses];
2932  commands = new uint8_t [2*no_addresses];
2933  pos = 0;
2934  for (index = 0; index < 2*no_addresses; index+=2)
2935  {
2936  addrs[index] = addresses[pos];
2937  addrs[index+1] = addresses[pos];
2938  commands[index] = PAGE;
2939  commands[index+1] = OPERATION;
2940  pos++;
2941  }
2942 
2943  data_bytes = new uint8_t [2*no_addresses];
2944  pos = 0;
2945  for (index = 0; index < 2*no_addresses; index+=2)
2946  {
2947  data_bytes[index] = pages[pos];
2948  data_bytes[index+1] = 0xA8;
2949  pos++;
2950  }
2951 
2952  smbus_->writeBytes(addrs, commands, data_bytes, 2*no_addresses);
2953 
2954  delete [] addrs;
2955  delete [] commands;
2956  delete [] data_bytes;
2957 }
2958 
2959 /*
2960  * Margin low rails for a list of addresses
2961  *
2962  * addresses: list of addresses
2963  * no_addresses: the length of the list
2964  */
2965 void LT_PMBus::marginLowAll(uint8_t *addresses, uint8_t *pages, uint8_t no_addresses)
2966 {
2967  uint8_t *addrs;
2968  uint8_t *commands;
2969  uint8_t *data_bytes;
2970  uint8_t index;
2971  uint8_t pos;
2972 
2973  addrs = new uint8_t [2*no_addresses];
2974  commands = new uint8_t [2*no_addresses];
2975  pos = 0;
2976  for (index = 0; index < 2*no_addresses; index+=2)
2977  {
2978  addrs[index] = addresses[pos];
2979  addrs[index+1] = addresses[pos];
2980  commands[index] = PAGE;
2981  commands[index+1] = OPERATION;
2982  pos++;
2983  }
2984 
2985  data_bytes = new uint8_t [2*no_addresses];
2986  pos = 0;
2987  for (index = 0; index < 2*no_addresses; index+=2)
2988  {
2989  data_bytes[index] = pages[pos];
2990  data_bytes[index+1] = 0x98;
2991  pos++;
2992  }
2993 
2994  smbus_->writeBytes(addrs, commands, data_bytes, 2*no_addresses);
2995 
2996  delete [] addrs;
2997  delete [] commands;
2998  delete [] data_bytes;
2999 }
3000 
3001 void LT_PMBus::marginOffAll(uint8_t *addresses, uint8_t *pages, uint8_t no_addresses)
3002 {
3003  uint8_t *addrs;
3004  uint8_t *commands;
3005  uint8_t *data_bytes;
3006  uint8_t index;
3007  uint8_t pos;
3008 
3009  addrs = new uint8_t [2*no_addresses];
3010  commands = new uint8_t [2*no_addresses];
3011  pos = 0;
3012  for (index = 0; index < 2*no_addresses; index+=2)
3013  {
3014  addrs[index] = addresses[pos];
3015  addrs[index+1] = addresses[pos];
3016  commands[index] = PAGE;
3017  commands[index+1] = OPERATION;
3018  pos++;
3019  }
3020 
3021  data_bytes = new uint8_t [2*no_addresses];
3022  pos = 0;
3023  for (index = 0; index < 2*no_addresses; index+=2)
3024  {
3025  data_bytes[index] = pages[pos];
3026  data_bytes[index+1] = 0x80;
3027  pos++;
3028  }
3029 
3030  smbus_->writeBytes(addrs, commands, data_bytes, 2*no_addresses);
3031 
3032  delete [] addrs;
3033  delete [] commands;
3034  delete [] data_bytes;
3035 }
3036 
3037 /*
3038  * Margin rail high
3039  *
3040  */
3042 {
3043  smbus_->writeByte(address, OPERATION, 0xA8);
3044 }
3045 
3046 /*
3047  * Margin rail low
3048  *
3049  */
3051 {
3052  smbus_->writeByte(address, OPERATION, 0x98);
3053 }
3054 
3055 /*
3056  * Margin rail off
3057  *
3058  */
3060 {
3061  smbus_->writeByte(address, OPERATION, 0x80);
3062 }
3063 
3064 /*
3065  * Margin all rails high
3066  *
3067  */
3069 {
3070  setPage(0x5B, 0xFF);
3071  smbus_->writeByte(0x5B, OPERATION, 0xA8);
3072 }
3073 
3074 /*
3075  * Margin all rails low
3076  *
3077  */
3079 {
3080  setPage(0x5B, 0xFF);
3081  smbus_->writeByte(0x5B, OPERATION, 0x98);
3082 }
3083 
3084 /*
3085  * Margin all rails off
3086  *
3087  */
3089 {
3090  setPage(0x5B, 0xFF);
3091  smbus_->writeByte(0x5B, OPERATION, 0x80);
3092 }
3093 
3094 void LT_PMBus::setUserData03(uint8_t address, uint16_t data)
3095 {
3096  smbus_->writeWord(address, USER_DATA_03, data);
3097 }
3098 
3100 {
3101  return smbus_->readWord(address, USER_DATA_03);
3102 }
3103 
3104 void LT_PMBus::setUserData04(uint8_t address, uint16_t data)
3105 {
3106  smbus_->writeWord(address, USER_DATA_04, data);
3107 }
3108 
3110 {
3111  return smbus_->readWord(address, USER_DATA_04);
3112 }
3113 
3114 void LT_PMBus::setSpareData0(uint8_t address, uint16_t data)
3115 {
3116  smbus_->writeWord(address, MFR_SPARE_0, data);
3117 
3118 }
3119 
3121 {
3122  return smbus_->readWord(address, MFR_SPARE_0);
3123 }
3124 
3125 
3126 void LT_PMBus::setRailAddress(uint8_t address, uint8_t rail_address)
3127 {
3128  smbus_->writeByte(address, MFR_RAIL_ADDRESS, rail_address);
3129 }
3130 
3132 {
3133  uint8_t rail_address;
3134  rail_address = smbus_->readByte(address, MFR_RAIL_ADDRESS);
3135  return rail_address;
3136 }
3137 
3138 /*
3139  * Set the page of a device using polling
3140  *
3141  * address: PMBUS address
3142  * page: the page
3143  */
3145 {
3146  // Set the page of the device to desired_page
3147  pmbusWriteByteWithPolling(address, PAGE, page);
3148 }
3149 
3150 /*
3151  * Set the page of a device
3152  *
3153  * address: PMBUS address
3154  * page: the page
3155  */
3156 void LT_PMBus::setPage(uint8_t address, uint8_t page)
3157 {
3158  // Set the page of the device to desired_page
3159  smbus_->writeByte(address, PAGE, page);
3160 }
3161 
3162 /*
3163  * Get the page of a device
3164  *
3165  * address: PMBUS address
3166  */
3167 uint8_t LT_PMBus::getPage(uint8_t address)
3168 {
3169  // Set the page of the device to desired_page
3170  return smbus_->readByte(address, PAGE);
3171 }
3172 
3174 {
3175  uint8_t config;
3176  uint16_t config2;
3177 
3178  PsmDeviceType t = deviceType(address);
3179 
3180  if (
3181  (t == LTC3880)
3182  || (t == LTC3882)
3183  || (t == LTC3882_1)
3184  || (t == LTC3883)
3185  || (t == LTM4675)
3186  || (t == LTM4676)
3187  || (t == LTM4676A)
3188  || (t == LTM4677)
3189  || (t == LTC2978)
3190  )
3191  {
3192  config = smbus_->readByte(address, MFR_CONFIG_ALL);
3193  config |= 0x04;
3194  smbus_->writeByte(address, MFR_CONFIG_ALL, config);
3195  }
3196  else if (
3197  (t == LTC2974)
3198  || (t == LTC2975)
3199  || (t == LTC2977)
3200  || (t == LTC2980)
3201  || (t == LTM2987)
3202  )
3203  {
3204  config2 = smbus_->readWord(address, MFR_CONFIG_ALL );
3205  config2 |= 0x04;
3206  smbus_->writeWord(address, MFR_CONFIG_ALL, config2);
3207  }
3208 }
3209 
3211 {
3212  uint8_t config;
3213  uint16_t config2;
3214 
3215  PsmDeviceType t = deviceType(address);
3216 
3217  if (
3218  (t == LTC3880)
3219  || (t == LTC3882)
3220  || (t == LTC3882_1)
3221  || (t == LTC3883)
3222  || (t == LTM4675)
3223  || (t == LTM4676)
3224  || (t == LTM4676A)
3225  || (t == LTM4677)
3226  || (t == LTC2978)
3227  )
3228  {
3229  config = smbus_->readByte(address, MFR_CONFIG_ALL);
3230  config &= ~(0x04);
3231  smbus_->writeByte(address, MFR_CONFIG_ALL, config);
3232  }
3233  else if (
3234  (t == LTC2974)
3235  || (t == LTC2975)
3236  || (t == LTC2977)
3237  || (t == LTC2980)
3238  || (t == LTM2987)
3239  )
3240  {
3241  config2 = smbus_->readWord(address, MFR_CONFIG_ALL );
3242  config2 &= ~(0x04);
3243  smbus_->writeWord(address, MFR_CONFIG_ALL, config2);
3244  }
3245 }
3246 
3247 /*
3248  * Wait for the busy bit to clear.
3249  *
3250  * This uses the MFR_COMMON BUSY/PEND bits. LTC2978 does not support this bit and
3251  * will cause a timeout. LTC3883 does not support PEND, which will cause a timeout
3252  * if not disabled by setting USE_PEND to 0.
3253  */
3255 {
3256  uint16_t timeout = 4096;
3257  uint8_t mfr_common;
3258 
3259  while (timeout-- > 0)
3260  {
3261  mfr_common = smbus_->readByte(address, MFR_COMMON);
3262  // If too busy to answer, poll again.
3263  if (mfr_common == 0xFF)
3264  continue;
3265  // Can add not transition bit for controllers. Managers do not support it.
3266 // if ((mfr_common & (NOT_BUSY | NOT_PENDING | NOT_TRANS)) == (NOT_BUSY | NOT_PENDING | NOT_TRANS))
3267  if ((mfr_common & (NOT_BUSY | NOT_PENDING)) == (NOT_BUSY | NOT_PENDING))
3268  return SUCCESS;
3269  }
3270  return FAILURE;
3271 }
3272 
3273 /*
3274  * Wait for the nvm done bit to clear.
3275  *
3276  * This uses the MFR_EEPROM_STATUS BUSY bit. LTC297X does not support this register.
3277  */
3279 {
3280  uint16_t timeout = 8192;
3281  uint8_t mfr_eeprom_status;
3282 
3283  while (timeout-- > 0)
3284  {
3285  smbus_->waitForAck(address, 0x00);
3286  mfr_eeprom_status = smbus_->readByte(address, MFR_EEPROM_STATUS);
3287  if (mfr_eeprom_status == 0xFF)
3288  continue;
3289  if ((mfr_eeprom_status & 0xC0) == 0)
3290  return SUCCESS;
3291  }
3292  return FAILURE;
3293 }
3294 
3295 uint8_t *LT_PMBus::bricks(uint8_t *addresses, uint8_t no_addresses)
3296 {
3297  uint8_t i,j;
3298  bool found;
3299  uint8_t len;
3300 
3301  // Get a list of addresses on the bus
3302  uint8_t *addresses_on_bus = smbus_->probe(0x00);
3303  for (len=0; addresses_on_bus[len]!='\0'; ++len);
3304 
3305  // Iterate through given addresses
3306  for (i = 0; i < no_addresses; i++)
3307  {
3308  // Interate on the probed addresses
3309  found = false;
3310  for (j = 0; j < len; j++)
3311  {
3312  // Check if we match; break if we match
3313  if (addresses[i] == addresses_on_bus[j])
3314  {
3315  found = true;
3316  break;
3317  }
3318  }
3319  // Found, so we check CML for a MEM fault, just in case the device lands on the correct address.
3320  // This will not find a bricked device if non-bricked device is at the same effective address
3321  // and answers to this command with a bit value of zero. The non bricked device will coverup
3322  // the bricked device. The solution is to define base addresses and ASEL values that guearentee
3323  // this can never happen.
3324  if (found && (1 << 4) != (smbus_->readByte(addresses[i], STATUS_CML) & (1 << 4)))
3325  addresses[i] = 0x00; // Good device, so remove.
3326  }
3327 
3328 
3329  // Pack the bricked addresses to the left.
3330  i = 0;
3331  while (i < no_addresses)
3332  {
3333  if (addresses[i] == 0x00)
3334  {
3335  j = i + 1;
3336  while (addresses[i] == 0x00 && j < no_addresses)
3337  {
3338  addresses[i] = addresses[j];
3339  addresses[j] = 0x00;
3340  j++;
3341  }
3342  }
3343  i++;
3344  }
3345 
3346 
3347  return addresses; // Returning in the origonal array.
3348 }
3349 
3351 {
3352  smbus_->beginStoring();
3353 }
3354 
3355 
3357 {
3358  smbus_->execute();
3359 }
3360 
3362 {
3363  return smbus_->readWord(address, MFR_SPECIAL_ID);
3364 }
3365 
3366 /*
3367  * Convert L16 value to float with polling
3368  *
3369  * address: PMBUS address
3370  * input_value: the value to convert
3371  * return: converted value
3372  *
3373  * The address is used to get the exponent to use
3374  */
3375 float LT_PMBus::L16_to_Float_with_polling(uint8_t address, uint16_t input_val)
3376 {
3377  // Read mode from the VOUT_MODE register of the device
3378  uint8_t vout_mode = (uint8_t)(pmbusReadByteWithPolling(address, VOUT_MODE) & 0x1F);
3379 
3380  return L16_to_Float_mode(vout_mode, input_val);
3381 }
3382 
3383 /*
3384  * Convert L16 value to float
3385  *
3386  * address: PMBUS address
3387  * input_value: the value to convert
3388  * return: converted value
3389  *
3390  * The address is used to get the exponent to use
3391  */
3392 float LT_PMBus::L16_to_Float(uint8_t address, uint16_t input_val)
3393 {
3394  // Read mode from the VOUT_MODE register of the device
3395  uint8_t vout_mode = (uint8_t)(smbus_->readByte(address, VOUT_MODE) & 0x1F);
3396 
3397  return L16_to_Float_mode(vout_mode, input_val);
3398 }
3399 
3400 /*
3401  * Convert Float value to L16
3402  *
3403  * address: PMBUS address
3404  * input_value: the value to convert
3405  * return: converted value
3406  *
3407  * The address is used to get the exponent to use
3408  */
3409 uint16_t LT_PMBus::Float_to_L16(uint8_t address, float input_val)
3410 {
3411  // Get the mode from the device.
3412  uint8_t vout_mode = (uint8_t)(smbus_->readByte(address, VOUT_MODE) & 0x1F);
3413 
3414  return Float_to_L16_mode(vout_mode, input_val);
3415 }
3416 
3417 /*
3418  * Convert L16 value to float
3419  *
3420  * exponent: vout_mode
3421  * input_value: the value to convert
3422  * return: converted value
3423  *
3424  * The address is used to get the exponent to use
3425  */
3426 float LT_PMBus::L16_to_Float_mode(uint8_t vout_mode, uint16_t input_val)
3427 {
3428  // Assume Linear 16, pull out 5 bits of exponent, and use signed value.
3429  int8_t exponent = (int8_t) vout_mode & 0x1F;
3430 
3431  // Sign extend exponent from 5 to 8 bits
3432  if (exponent > 0x0F) exponent |= 0xE0;
3433 
3434  // Convert mantissa to a float so we can do math.
3435  float mantissa = (float)input_val;
3436 
3437  float value = mantissa * pow(2.0, exponent);
3438 
3439  return value;
3440 }
3441 
3442 /*
3443  * Convert Float value to L16
3444  *
3445  * vout_mode: vout_mode
3446  * input_value: the value to convert
3447  * return: converted value
3448  *
3449  * The address is used to get the exponent to use
3450  */
3451 uint16_t LT_PMBus::Float_to_L16_mode(uint8_t vout_mode, float input_val)
3452 {
3453  // Assume Linear 16, pull out 5 bits of exponent, and use signed value.
3454  int8_t exponent = vout_mode & 0x1F;
3455 
3456  // Sign extend exponent from 5 to 8 bits
3457  if (exponent > 0x0F) exponent |= 0xE0;
3458 
3459  // Scale the value to a mantissa based on the exponent
3460  uint16_t mantissa = (uint16_t)(input_val / pow(2.0, exponent));
3461 
3462  return mantissa;
3463 }
3464 
3465 
3466 /*
3467  * Convert L11 value to float
3468  *
3469  * input_value: value to convert
3470  * return: converted value
3471  */
3472 float LT_PMBus::L11_to_Float(uint16_t input_val)
3473 {
3474  // Extract exponent as MS 5 bits
3475  int8_t exponent = (int8_t) (input_val >> 11);
3476 
3477  // Extract mantissa as LS 11 bits
3478  int16_t mantissa = input_val & 0x7ff;
3479 
3480  // Sign extend exponent from 5 to 8 bits
3481  if (exponent > 0x0F) exponent |= 0xE0;
3482 
3483  // Sign extend mantissa from 11 to 16 bits
3484  if (mantissa > 0x03FF) mantissa |= 0xF800;
3485 
3486  // Compute value as mantissa * 2^(exponent)
3487  return mantissa * pow(2.0,(float)exponent);
3488 }
3489 /*
3490  * Convert float to L11
3491  *
3492  * input_val: the value to convert
3493  * return: converted value
3494  */
3495 uint16_t LT_PMBus::Float_to_L11(float input_val)
3496 {
3497  uint16_t uExponent;
3498  uint16_t uMantissa;
3499 
3500  // Set exponent to -16
3501  int exponent = -16;
3502 
3503  // Extract mantissa from input value
3504  int mantissa = (int)(input_val / pow(2.0, exponent));
3505  // Search for an exponent that produces
3506  // a valid 11-bit mantissa
3507  do
3508  {
3509  if ((mantissa >= -1024) && (mantissa <= +1023))
3510  {
3511  break; // stop if mantissa valid
3512  }
3513  exponent++;
3514  mantissa = (int)(input_val / pow(2.0, exponent));
3515  }
3516  while (exponent < +15);
3517 
3518  // Format the exponent of the L11
3519  uExponent = exponent << 11; // Format the mantissa of the L11
3520  uMantissa = mantissa & 0x07FF;
3521 
3522  // Compute value as exponent | mantissa
3523  return uExponent | uMantissa;
3524 }
void storeToNvmAll(uint8_t *addresses, uint8_t no_addresses)
Store RAM to NVM for list of devices.
Definition: LT_PMBus.cpp:2693
static int id
Definition: rail_logger.ino:99
void setCmlStatusMask(uint8_t address, uint8_t mask)
Get the CML status mask.
Definition: LT_PMBus.cpp:2222
uint8_t waitForNvmDone(uint8_t address)
Read MFR_EEPROM_STATUS until done (LTC388X only)
Definition: LT_PMBus.cpp:3278
float readIoutWithPagePlus(uint8_t address, uint8_t page)
Get the measured output current.
Definition: LT_PMBus.cpp:1938
void sequenceOff(uint8_t *addresses, uint8_t no_addresses)
Sequence off a list of addresses.
Definition: LT_PMBus.cpp:2850
#define OPERATION
Definition: LT_PMBus.h:66
#define READ_POUT
Definition: LT_PMBus.h:120
#define WRITE_PROTECT
Definition: LT_PMBus.h:71
lin16_t float_to_lin16(float xin, lin16m_t vout_mode)
void setMfrStatusMask(uint8_t address, uint8_t mask)
Get the MFR status mask.
Definition: LT_PMBus.cpp:2230
void sequenceOn(uint8_t *addresses, uint8_t no_addresses)
Sequence on a list of devices.
Definition: LT_PMBus.cpp:2794
void setPageWithPolling(uint8_t address, uint8_t page)
Set the page and poll the busy bit.
Definition: LT_PMBus.cpp:3144
float getOtWarnLimitWithPagePlus(uint8_t address, uint8_t page)
Get the over temperature warning limit.
Definition: LT_PMBus.cpp:1463
float getOtWarnLimitWithPage(uint8_t address, uint8_t page)
Get the over temperature warning limit.
Definition: LT_PMBus.cpp:1451
float readPout(uint8_t address, bool polling)
Get the measured output power.
Definition: LT_PMBus.cpp:1963
uint8_t readByte(uint8_t address, uint8_t command)
SMBus read byte command.
uint8_t getPage(uint8_t address)
Get the page.
Definition: LT_PMBus.cpp:3167
uint8_t getInputStatusMask(uint8_t address)
Get the input status mask.
Definition: LT_PMBus.cpp:2262
#define IOUT_OC_WARN_LIMIT
Definition: LT_PMBus.h:88
#define RESTORE_USER_ALL
Definition: LT_PMBus.h:73
#define TOFF_FALL
Definition: LT_PMBus.h:102
uint8_t readIoutStatusByte(uint8_t address)
Get the output current status byte.
Definition: LT_PMBus.cpp:2318
bool compareRamWithNvm(uint8_t address)
Compare RAM to NVM for device.
Definition: LT_PMBus.cpp:2750
#define VOUT_OV_WARN_LIMIT
Definition: LT_PMBus.h:83
#define TOFF_MAX_WARN_LIMIT
Definition: LT_PMBus.h:103
#define CLEAR_FAULTS
Definition: LT_PMBus.h:68
float getOtWarnLimit(uint8_t address)
Get the over temperature warning limit.
Definition: LT_PMBus.cpp:1432
float readOtemp(uint8_t address)
Get the external measured temperature.
Definition: LT_PMBus.cpp:2175
bool isLtc2974(uint8_t address)
Determine if the device is from the LTC2974 family, by using the product id in MFR_SPECIAL_ID.
Definition: LT_PMBus.cpp:158
void marginOff(uint8_t address)
Margin rails off.
Definition: LT_PMBus.cpp:3059
float readVoutWithPagePlus(uint8_t address, uint8_t page)
Get the measured output voltage.
Definition: LT_PMBus.cpp:1692
#define STATUS_CML
Definition: LT_PMBus.h:111
void marginOffAll(uint8_t *addresses, uint8_t *pages, uint8_t no_addresses)
Margin off a list of rails low.
Definition: LT_PMBus.cpp:3001
void setIoutOcWarnLimit(uint8_t address, float current)
Set the over current warning limit.
Definition: LT_PMBus.cpp:991
#define IOUT_OC_FAULT_LIMIT
Definition: LT_PMBus.h:87
#define UT_WARN_LIMIT
Definition: LT_PMBus.h:92
void setOtWarnLimit(uint8_t address, float temperature)
Set the over temperature warning limit.
Definition: LT_PMBus.cpp:1163
uint8_t * probe(uint8_t command)
SMBus bus probe.
void setVoutMarginHigh(uint8_t address, float voltage)
Set the margin high.
Definition: LT_PMBus.cpp:694
void reset(uint8_t address)
Issue reset to one device.
Definition: LT_PMBus.cpp:2912
float lin16_to_float(lin16_t lin16_mant, lin16m_t vout_mode)
String status(void)
Returns a descriptive string based on status of pins.
Definition: DC2364A.ino:217
void setVinUvFaultLimit(uint8_t address, float voltage)
Set the input under voltage fault limit.
Definition: LT_PMBus.cpp:1086
uint8_t readStatusByte(uint8_t address)
Get the status byte.
Definition: LT_PMBus.cpp:2423
void setVoutOvWarnLimit(uint8_t address, float voltage)
Set the over voltage supervisor warning limit.
Definition: LT_PMBus.cpp:634
uint8_t * bricks(uint8_t *addresses, uint8_t no_addresses)
Find bricked devices.
Definition: LT_PMBus.cpp:3295
void disableWriteProtectGlobal(void)
Disable the write protect.
Definition: LT_PMBus.cpp:2556
#define PAGE
Definition: LT_PMBus.h:65
float getVoutUvWithPagePlus(uint8_t address, uint8_t page)
Get the under voltage limit.
Definition: LT_PMBus.cpp:1777
void setVoutUvFaultLimitWithPagePlus(uint8_t address, float voltage, uint8_t page)
Set the under voltage fault limit.
Definition: LT_PMBus.cpp:908
void setVoutUvWarnLimitWithPagePlus(uint8_t address, float voltage, uint8_t page)
Set the under voltage supervisor warning limit.
Definition: LT_PMBus.cpp:848
void setVoutMax(uint8_t address, float voltage)
Set the maximum output voltage.
Definition: LT_PMBus.cpp:398
~LT_PMBus()
Definition: LT_PMBus.cpp:91
uint8_t writeReadBlock(uint8_t address, uint8_t command, uint8_t *block_out, uint16_t block_out_size, uint8_t *block_in, uint16_t block_in_size)
SMBus write then read block command.
Header File for Linduino Libraries and Demo Code.
void storeToNvmGlobal(void)
Store RAM to NVM for all devices.
Definition: LT_PMBus.cpp:2700
#define MFR_READ_IIN
Definition: LT_PMBus.h:138
void storeToNvm(uint8_t address)
Store RAM to NVM.
Definition: LT_PMBus.cpp:2688
#define FAILURE
Definition: LT_PMBus.h:63
#define MFR_SPARE_0
Definition: LT_PMBus.h:142
void setVoutWithPage(uint8_t address, float voltage, uint8_t page)
Set output voltage.
Definition: LT_PMBus.cpp:260
void setIoutStatusMask(uint8_t address, uint8_t mask)
Get the output current status mask.
Definition: LT_PMBus.cpp:2198
#define TOFF_DELAY
Definition: LT_PMBus.h:101
void enablePec(uint8_t address)
Enable pec for all transactions.
Definition: LT_PMBus.cpp:3173
void setOtWarnLimitWithPage(uint8_t address, float temperature, uint8_t page)
Set the over temperature warning limit.
Definition: LT_PMBus.cpp:1239
float readItemp(uint8_t address)
Get the internal measured temperature.
Definition: LT_PMBus.cpp:2127
void setVoutWithSupervisionWithPagePlus(uint8_t address, float voltage, float margin_percent, float warn_percent, float fault_percent, uint8_t page)
Set output voltage and supervisors.
Definition: LT_PMBus.cpp:363
uint8_t getTemperatureStatusMask(uint8_t address)
Get the temperature status mask.
Definition: LT_PMBus.cpp:2274
void setMfrWatchdogFirst(uint8_t address, float delay)
Set the first watchdog timer.
Definition: LT_PMBus.cpp:2626
void disableWriteProtect(uint8_t address)
Disable the write protect.
Definition: LT_PMBus.cpp:2548
void setUtFaultLimit(uint8_t address, float temperature)
Set the under temperature fault limit.
Definition: LT_PMBus.cpp:1220
void beginStoring()
Group Protocol Begin.
void setTonDelay(uint8_t address, float delay)
Set delay before rail turns on.
Definition: LT_PMBus.cpp:460
void setUtWarnLimitWithPagePlus(uint8_t address, float temperature, uint8_t page)
Set the under temperature warning limit.
Definition: LT_PMBus.cpp:1344
uint16_t readStatusWord(uint8_t address)
Get the status word.
Definition: LT_PMBus.cpp:2470
float readIout(uint8_t address, bool polling)
Get the measured output current.
Definition: LT_PMBus.cpp:1898
#define STORE_USER_ALL
Definition: LT_PMBus.h:72
#define VOUT_OV_FAULT_LIMIT
Definition: LT_PMBus.h:81
void readModel(uint8_t address, uint8_t *model)
Get the model.
Definition: LT_PMBus.cpp:2409
#define STATUS_VOUT
Definition: LT_PMBus.h:107
void execute()
Group Protocol Execute queued commands.
void writeByte(uint8_t address, uint8_t command, uint8_t data)
SMBus write byte command.
void setVoutWithSupervisionWithPage(uint8_t address, float voltage, float margin_percent, float warn_percent, float fault_percent, uint8_t page)
Set output voltage and supervisors.
Definition: LT_PMBus.cpp:344
void clearFaults(uint8_t address)
Clear the faults of the existing page.
Definition: LT_PMBus.cpp:2566
#define STATUS_INPUT
Definition: LT_PMBus.h:109
#define TON_DELAY
Definition: LT_PMBus.h:97
void setVoutWithSupervision(uint8_t address, float voltage, float margin_percent, float warn_percent, float fault_percent)
Set output voltage and supervisors.
Definition: LT_PMBus.cpp:304
#define READ_IOUT
Definition: LT_PMBus.h:116
void setVoutOvFaultLimitWithPage(uint8_t address, float voltage, uint8_t page)
Set the over voltage supervisor fault limit.
Definition: LT_PMBus.cpp:595
LT_PMBusMath math_
void disablePec(uint8_t address)
Disable pec for all transactions.
Definition: LT_PMBus.cpp:3210
void setVoutOvWarnLimitWithPage(uint8_t address, float voltage, uint8_t page)
Set the over voltage supervisor warning limit.
Definition: LT_PMBus.cpp:655
float lin11_to_float(lin11_t xin)
#define READ_OTEMP
Definition: LT_PMBus.h:117
#define VOUT_COMMAND
Definition: LT_PMBus.h:77
float getVoutOvWithPagePlus(uint8_t address, uint8_t page)
Get the output over voltage limit.
Definition: LT_PMBus.cpp:1570
#define VOUT_MARGIN_LOW
Definition: LT_PMBus.h:80
void setVoutMarginHighWithPagePlus(uint8_t address, float voltage, uint8_t page)
Set the margin high.
Definition: LT_PMBus.cpp:728
#define MFR_WATCHDOG_T_FIRST
Definition: LT_PMBus.h:130
float getVoutUvWithPage(uint8_t address, uint8_t page)
Get the under voltage limit.
Definition: LT_PMBus.cpp:1763
void setIoutOcFaultLimitWithPage(uint8_t address, float current, uint8_t page)
Set the over current fault limit.
Definition: LT_PMBus.cpp:954
uint16_t getTemp1Gain(uint8_t address)
Get the temperature 1 gain.
Definition: LT_PMBus.cpp:1380
static uint8_t pages[2]
Definition: DC1989A.ino:87
uint8_t readPmbusRevision(uint8_t address)
Get the pmbus revision.
Definition: LT_PMBus.cpp:2380
#define PAGE_PLUS_WRITE
Definition: LT_PMBus.h:69
void marginOffGlobal(void)
Margin all rails off.
Definition: LT_PMBus.cpp:3088
uint8_t getVoutStatusMask(uint8_t address)
Get the output voltage status mask.
Definition: LT_PMBus.cpp:2238
void marginHigh(uint8_t address)
Margin rail high.
Definition: LT_PMBus.cpp:3041
#define VOUT_MODE
Definition: LT_PMBus.h:76
#define TON_RISE
Definition: LT_PMBus.h:98
static uint8_t address
Definition: DC2091A.ino:83
void setVoutUvFaultLimit(uint8_t address, float voltage)
Set the under voltage fault limit.
Definition: LT_PMBus.cpp:874
LT_SMBusGroup * smbus
Definition: retention.ino:139
union LT_union_int32_4bytes data
Definition: DC2094A.ino:138
uint8_t waitForNotBusy(uint8_t address)
Read MFR_COMMON until not Busy.
Definition: LT_PMBus.cpp:3254
void writeBlock(uint8_t address, uint8_t command, uint8_t *block, uint16_t block_size)
SMBus write block command.
static int16_t pos
void setVoutUvWarnLimit(uint8_t address, float voltage)
Set the under voltage supervisor warning limit.
Definition: LT_PMBus.cpp:814
void setOtFaultLimitWithPage(uint8_t address, float temperature, uint8_t page)
Set the over temperature fault limit.
Definition: LT_PMBus.cpp:1181
void setUtWarnLimitWithPage(uint8_t address, float temperature, uint8_t page)
Set the under temperature warning limit.
Definition: LT_PMBus.cpp:1332
#define VOUT_UV_WARN_LIMIT
Definition: LT_PMBus.h:84
#define OT_FAULT_LIMIT
Definition: LT_PMBus.h:89
uint8_t getMfrStatusMask(uint8_t address)
Get the MFR status mask.
Definition: LT_PMBus.cpp:2298
uint8_t readStatusByteWithPagePlus(uint8_t address, uint8_t page)
Get the status byte.
Definition: LT_PMBus.cpp:2451
float readPin(uint8_t address, bool polling)
Get the measured input power.
Definition: LT_PMBus.cpp:2027
void startGroupProtocol(void)
starts group protocol
Definition: LT_PMBus.cpp:3350
#define READ_ITEMP
Definition: LT_PMBus.h:118
void setVoutMarginLowWithPage(uint8_t address, float voltage, uint8_t page)
Set the margin low.
Definition: LT_PMBus.cpp:775
void enableWriteProtect(uint8_t address)
Enable the write protect.
Definition: LT_PMBus.cpp:2530
#define MFR_TEMP_1_OFFSET
Definition: LT_PMBus.h:147
float readVout(uint8_t address, bool polling)
Get the measured output voltage.
Definition: LT_PMBus.cpp:1598
void setVoutOvWarnLimitWithPagePlus(uint8_t address, float voltage, uint8_t page)
Set the over voltage supervisor warning limit.
Definition: LT_PMBus.cpp:668
void setVinUvWarnLimit(uint8_t address, float voltage)
Set the input under voltage warning limit.
Definition: LT_PMBus.cpp:1105
#define MFR_WATCHDOG_T
Definition: LT_PMBus.h:131
void setToffMaxWarnLimit(uint8_t address, float max)
Set the maximum time allow to turn off.
Definition: LT_PMBus.cpp:555
float getVoutOvWithPage(uint8_t address, uint8_t page)
Get the output over voltage limit.
Definition: LT_PMBus.cpp:1556
uint8_t readMfrStatusByte(uint8_t address)
Get the MFR status byte.
Definition: LT_PMBus.cpp:2350
float getVoutOv(uint8_t address, bool polling)
Get the output over voltage limit.
Definition: LT_PMBus.cpp:1512
#define MFR_EE_UNLOCK
Definition: LT_PMBus.h:125
uint8_t readTemperatureStatusByte(uint8_t address)
Get the temperature status byte.
Definition: LT_PMBus.cpp:2334
static float vout
#define VOUT_MAX
Definition: LT_PMBus.h:78
void setVoutStatusMask(uint8_t address, uint8_t mask)
Get the output voltage status mask.
Definition: LT_PMBus.cpp:2190
void immediateOffGlobal(void)
Turn off all rails immediately.
Definition: LT_PMBus.cpp:2886
uint8_t readInputStatusByte(uint8_t address)
Get the input status byte.
Definition: LT_PMBus.cpp:2326
#define STATUS_IOUT
Definition: LT_PMBus.h:108
void writeWord(uint8_t address, uint8_t command, uint16_t data)
SMBus write word command.
float readOtempWithPage(uint8_t address, uint8_t page)
Get the external measured temperature.
Definition: LT_PMBus.cpp:2150
void writeBytes(uint8_t *addresses, uint8_t *commands, uint8_t *data, uint8_t no_addresses)
SMBus write byte command for a list of addresses.
#define VIN_UV_FAULT_LIMIT
Definition: LT_PMBus.h:96
float readPoutWithPage(uint8_t address, uint8_t page)
Get the measured output power.
Definition: LT_PMBus.cpp:1988
uint16_t getUserData04(uint8_t address)
Get user data 4.
Definition: LT_PMBus.cpp:3109
void resetGlobal(void)
Issue reset to all devices.
Definition: LT_PMBus.cpp:2906
#define VOUT_MARGIN_HIGH
Definition: LT_PMBus.h:79
float getIoutOcWithPage(uint8_t address, uint8_t page)
Get the over current limit.
Definition: LT_PMBus.cpp:1860
#define VIN_OV_FAULT_LIMIT
Definition: LT_PMBus.h:93
void setVoutMaxWithPage(uint8_t address, float voltage, uint8_t page)
Set the maximum output voltage.
Definition: LT_PMBus.cpp:420
void setVoutMaxWithPagePlus(uint8_t address, float voltage, uint8_t page)
Set the maximum output voltage.
Definition: LT_PMBus.cpp:433
#define MFR_CONFIG_ALL
Definition: LT_PMBus.h:129
bool unlockNVM(uint8_t address)
Unlock NVM.
Definition: LT_PMBus.cpp:2705
void setOtFaultLimit(uint8_t address, float temperature)
Set the over temperature fault limit.
Definition: LT_PMBus.cpp:1143
uint8_t readVoutStatusByte(uint8_t address)
Get the output voltage status byte.
Definition: LT_PMBus.cpp:2310
void setVoutMarginLowWithPagePlus(uint8_t address, float voltage, uint8_t page)
Set the margin low.
Definition: LT_PMBus.cpp:788
PsmDeviceType
Definition: LT_PMBus.h:345
void setIoutOcFaultLimit(uint8_t address, float current)
Set the over current fault limit.
Definition: LT_PMBus.cpp:934
bool isLtc297x(uint8_t address)
Determine if the device is from the LTC297X family, by using the product id in MFR_SPECIAL_ID.
Definition: LT_PMBus.cpp:146
void setVoutUvWarnLimitWithPage(uint8_t address, float voltage, uint8_t page)
Set the under voltage supervisor warning limit.
Definition: LT_PMBus.cpp:835
void setPage(uint8_t address, uint8_t page)
Set the page.
Definition: LT_PMBus.cpp:3156
bool lockNVM(uint8_t address)
Lock NVM.
Definition: LT_PMBus.cpp:2729
float getIoutOc(uint8_t address, bool polling)
Get the over current limit.
Definition: LT_PMBus.cpp:1834
#define MFR_SPECIAL_ID
Definition: LT_PMBus.h:134
#define STATUS_WORD
Definition: LT_PMBus.h:106
void marginLowGlobal(void)
Margin all rails low.
Definition: LT_PMBus.cpp:3078
float readExternalTemperature(uint8_t address, bool polling)
Get the measured external temperature.
Definition: LT_PMBus.cpp:2052
void setInputStatusMask(uint8_t address, uint8_t mask)
Get the input status mask.
Definition: LT_PMBus.cpp:2206
#define MFR_COMMON
Definition: LT_PMBus.h:141
#define STATUS_BYTE
Definition: LT_PMBus.h:105
#define MFR_COMPARE_USER_ALL
Definition: LT_PMBus.h:74
#define TON_MAX_FAULT_LIMIT
Definition: LT_PMBus.h:99
uint8_t readStatusCml(uint8_t address)
Get the status CML byte.
Definition: LT_PMBus.cpp:2517
void setIoutOcFaultLimitWithPagePlus(uint8_t address, float current, uint8_t page)
Set the over current fault limit.
Definition: LT_PMBus.cpp:967
void restoreFromNvmAll(uint8_t *addresses, uint8_t no_addresses)
Restore list of devices from NVM.
Definition: LT_PMBus.cpp:2673
void setUserData03(uint8_t address, uint16_t data)
Set user data 3.
Definition: LT_PMBus.cpp:3094
#define MFR_FAULT_LOG_STATUS
Definition: LT_PMBus.h:139
void page(uint8_t *addresses, uint8_t no_addresses)
Set the page.
Definition: LT_PMBus.cpp:2768
void sequenceOnGlobal(void)
Sequence on all rails.
Definition: LT_PMBus.cpp:2896
void marginLowAll(uint8_t *addresses, uint8_t *pages, uint8_t no_addresses)
Margin a list of rails low.
Definition: LT_PMBus.cpp:2965
void clearAllFaults(uint8_t address)
Clear all the faults for all pages.
Definition: LT_PMBus.cpp:2576
uint16_t readWord(uint8_t address, uint8_t command)
SMBus read word command.
void setVinOvFaultLimit(uint8_t address, float voltage)
Set the input over voltage fault limit.
Definition: LT_PMBus.cpp:1048
LT_PMBus(LT_SMBus *smbus)
Construct a LT_PMBus.
Definition: LT_PMBus.cpp:86
void setVoutOvFaultLimit(uint8_t address, float voltage)
Set the over voltage supervisor fault limit.
Definition: LT_PMBus.cpp:574
uint8_t readStatusByteWithPage(uint8_t address, uint8_t page)
Get the status byte.
Definition: LT_PMBus.cpp:2438
uint16_t getSpareData0(uint8_t address)
Get spare data 0.
Definition: LT_PMBus.cpp:3120
long timeout
uint8_t getIoutStatusMask(uint8_t address)
Get the output current status mask.
Definition: LT_PMBus.cpp:2250
void marginLow(uint8_t address)
Margin rails low.
Definition: LT_PMBus.cpp:3050
void setToffFall(uint8_t address, float fall)
Set the turn off fall time.
Definition: LT_PMBus.cpp:536
void setVoutMarginHighWithPage(uint8_t address, float voltage, uint8_t page)
Set the margin high.
Definition: LT_PMBus.cpp:715
void sendByte(uint8_t address, uint8_t command)
SMBus send byte command.
uint8_t readMfrFaultLogStatusByte(uint8_t address)
Get the fault log status byte.
Definition: LT_PMBus.cpp:2358
float getVoutUv(uint8_t address, bool polling)
Get the under voltage limit.
Definition: LT_PMBus.cpp:1719
float getIoutOcWithPagePlus(uint8_t address, uint8_t page)
Get the over current limit.
Definition: LT_PMBus.cpp:1874
#define VIN_UV_WARN_LIMIT
Definition: LT_PMBus.h:95
float readInternalTemperature(uint8_t address, bool polling)
Get the measured internal temperature.
Definition: LT_PMBus.cpp:2077
#define MFR_MODEL
Definition: LT_PMBus.h:122
void setVoutOvFaultLimitWithPagePlus(uint8_t address, float voltage, uint8_t page)
Set the over voltage supervisor fault limit.
Definition: LT_PMBus.cpp:608
float readIin(uint8_t address, bool polling)
Get the input current.
Definition: LT_PMBus.cpp:1805
#define IIN_OC_WARN_LIMIT
Definition: LT_PMBus.h:104
void setUserData04(uint8_t address, uint16_t data)
Set user data 4.
Definition: LT_PMBus.cpp:3104
virtual LT_I2CBus * i2cbus(void)=0
void setVoutWithPagePlus(uint8_t address, float voltage, uint8_t page)
Set output voltage.
Definition: LT_PMBus.cpp:273
void setIoutOcWarnLimitWithPagePlus(uint8_t address, float current, uint8_t page)
Set the over current warning limit.
Definition: LT_PMBus.cpp:1024
float getTemp1Offset(uint8_t address)
Get the temperature 1 offset.
Definition: LT_PMBus.cpp:1413
void setTemp1Offset(uint8_t address, float offset)
Set the temperature 1 offset.
Definition: LT_PMBus.cpp:1394
void setIinOcWarnLimit(uint8_t address, float current)
Set the input over current warning limit.
Definition: LT_PMBus.cpp:1124
void setVinOvWarningLimit(uint8_t address, float voltage)
Set the input over voltage warning limit.
Definition: LT_PMBus.cpp:1067
#define OT_WARN_LIMIT
Definition: LT_PMBus.h:90
#define NOT_BUSY
Definition: LT_PMBus.cpp:78
#define USER_DATA_03
Definition: LT_PMBus.h:123
static int index
#define STATUS_MFR_SPECIFIC
Definition: LT_PMBus.h:112
uint8_t readCmlStatusByte(uint8_t address)
Get the CML status byte.
Definition: LT_PMBus.cpp:2342
bool isLtc2978(uint8_t address)
Determine if the device is a LTC2978/A by looking at bit 2 (RESERVED2) in the MFR_COMMON.
Definition: LT_PMBus.cpp:164
void sequenceOffGlobal(void)
Sequence off all rails.
Definition: LT_PMBus.cpp:2876
void setOtWarnLimitWithPagePlus(uint8_t address, float temperature, uint8_t page)
Set the over temperature warning limit.
Definition: LT_PMBus.cpp:1251
void setUtWarnLimit(uint8_t address, float temperature)
Set the under temperature warning limit.
Definition: LT_PMBus.cpp:1276
float readVin(uint8_t address, bool polling)
Get the input voltage.
Definition: LT_PMBus.cpp:1487
void setRailAddress(uint8_t address, uint8_t rail_address)
Set rail address of a Controller.
Definition: LT_PMBus.cpp:3126
uint32_t getSpeed()
Get the speed of the bus.
Definition: LT_I2CBus.cpp:78
void setToffDelay(uint8_t address, float delay)
Set the delay before the rail turns off.
Definition: LT_PMBus.cpp:517
void clearFaultsGlobal(void)
Clear all the faults for all pages of all devices.
Definition: LT_PMBus.cpp:2606
uint8_t readBlock(uint8_t address, uint8_t command, uint8_t *block, uint16_t block_size)
SMBus read block command.
void setTemperatureStatusMask(uint8_t address, uint8_t mask)
Get the temperature status mask.
Definition: LT_PMBus.cpp:2214
void setVout(uint8_t address, float voltage)
Set output voltage.
Definition: LT_PMBus.cpp:239
void executeGroupProtocol(void)
ends group protocol
Definition: LT_PMBus.cpp:3356
void setOtFaultLimitWithPagePlus(uint8_t address, float temperature, uint8_t page)
Set the over temperature fault limit.
Definition: LT_PMBus.cpp:1193
void setMfrWatchdog(uint8_t address, float delay)
Set watchdog timer.
Definition: LT_PMBus.cpp:2645
#define SUCCESS
Definition: LT_PMBus.h:62
void restoreFromNvm(uint8_t address)
Restore device from NVM.
Definition: LT_PMBus.cpp:2663
bool is_ltc2978(uint8_t address)
Definition: retention.ino:179
#define READ_DUTY_CYCLE
Definition: LT_PMBus.h:119
void setTonRise(uint8_t address, float rise)
Set the turn on rise time.
Definition: LT_PMBus.cpp:479
void setVoutMarginLow(uint8_t address, float voltage)
Set the margin low.
Definition: LT_PMBus.cpp:754
LTC PMBus Support.
#define MFR_EEPROM_STATUS
Definition: LT_PMBus.h:148
unsigned int lin16_t
Definition: LT_PMBusMath.h:60
#define READ_PIN
Definition: LT_PMBus.h:121
float readPoutWithPagePlus(uint8_t address, uint8_t page)
Get the measured output power.
Definition: LT_PMBus.cpp:2001
uint16_t readMfrSpecialId(uint8_t address)
Get speical ID.
Definition: LT_PMBus.cpp:3361
uint8_t getCmlStatusMask(uint8_t address)
Get the CML status mask.
Definition: LT_PMBus.cpp:2286
void immediateOff(uint8_t *addresses, uint8_t no_addresses)
Turn off all devices immediately.
Definition: LT_PMBus.cpp:2822
lin11_t float_to_lin11(float xin)
#define VOUT_UV_FAULT_LIMIT
Definition: LT_PMBus.h:85
#define NOT_PENDING
Definition: LT_PMBus.cpp:81
void setUtFaultLimitWithPage(uint8_t address, float temperature, uint8_t page)
Set the under temperature fault limit.
Definition: LT_PMBus.cpp:1295
static int i
Definition: DC2430A.ino:184
PsmDeviceType deviceType(uint8_t address)
Get the type of PSM device.
Definition: LT_PMBus.cpp:96
static float voltage
Definition: DC2289AA.ino:71
#define MFR_RAIL_ADDRESS
Definition: LT_PMBus.h:149
uint16_t readStatusWordWithPage(uint8_t address, uint8_t page)
Get the status word.
Definition: LT_PMBus.cpp:2485
float getVout(uint8_t address, bool polling)
Get the set output voltage.
Definition: LT_PMBus.cpp:1634
void restoreFromNvmGlobal(void)
Restore all devices from NVM.
Definition: LT_PMBus.cpp:2683
static uint16_t current
the current measurement from the LTC3335&#39;s counter test mode.
Definition: DC2343A.ino:114
#define PAGE_PLUS_READ
Definition: LT_PMBus.h:70
void marginHighGlobal(void)
Margin all rails high.
Definition: LT_PMBus.cpp:3068
void setTonMaxFaultLimit(uint8_t address, float max)
Set the maximum time allow for turn on.
Definition: LT_PMBus.cpp:498
#define VIN_OV_WARN_LIMIT
Definition: LT_PMBus.h:94
#define MFR_TEMP_1_GAIN
Definition: LT_PMBus.h:146
void marginHighAll(uint8_t *addresses, uint8_t *pages, uint8_t no_addresses)
Margin a list of rails high.
Definition: LT_PMBus.cpp:2923
#define STATUS_TEMP
Definition: LT_PMBus.h:110
float readVoutWithPage(uint8_t address, uint8_t page)
Get the measured output voltage.
Definition: LT_PMBus.cpp:1678
void readRevision(uint8_t address, uint8_t *revision)
Get the slave revision.
Definition: LT_PMBus.cpp:2393
#define READ_VOUT
Definition: LT_PMBus.h:115
#define READ_VIN
Definition: LT_PMBus.h:113
void eraseNVM(uint8_t address)
Definition: LT_PMBus.cpp:2743
uint16_t getUserData03(uint8_t address)
Get user data 3.
Definition: LT_PMBus.cpp:3099
void setVoutUvFaultLimitWithPage(uint8_t address, float voltage, uint8_t page)
Set the under voltage fault limit.
Definition: LT_PMBus.cpp:895
bool isLtc2977(uint8_t address)
Determine if the device is from the LTC2977 family, by using the product id in MFR_SPECIAL_ID.
Definition: LT_PMBus.cpp:152
void setIoutOcWarnLimitWithPage(uint8_t address, float current, uint8_t page)
Set the over current warning limit.
Definition: LT_PMBus.cpp:1011
#define MFR_PADS
Definition: LT_PMBus.h:132
#define UT_FAULT_LIMIT
Definition: LT_PMBus.h:91
void setTemp1Gain(uint8_t address, uint16_t gain)
Set the temperature 1 gain.
Definition: LT_PMBus.cpp:1369
uint16_t readStatusWordWithPagePlus(uint8_t address, uint8_t page)
Get the status word.
Definition: LT_PMBus.cpp:2498
float readIoutWithPage(uint8_t address, uint8_t page)
Get the measured output current.
Definition: LT_PMBus.cpp:1924
uint8_t getRailAddress(uint8_t address)
Get the rail address of a Controller.
Definition: LT_PMBus.cpp:3131
void setSpareData0(uint8_t address, uint16_t data)
Set spare data 0.
Definition: LT_PMBus.cpp:3114
#define MFR_EE_ERASE
Definition: LT_PMBus.h:126
float readDutyCycle(uint8_t address, bool polling)
Get the duty cycle.
Definition: LT_PMBus.cpp:2102
#define READ_IIN
Definition: LT_PMBus.h:114
void enableWriteProtectGlobal(void)
Enable the write protect.
Definition: LT_PMBus.cpp:2538
#define MFR_RESET
Definition: LT_PMBus.h:150
uint16_t readMfrPads(uint8_t address)
Get the state of the pads.
Definition: LT_PMBus.cpp:2366
#define USER_DATA_04
Definition: LT_PMBus.h:124
#define SMBALERT_MASK
Definition: LT_PMBus.h:75
void setUtFaultLimitWithPagePlus(uint8_t address, float temperature, uint8_t page)
Set the under temperature fault limit.
Definition: LT_PMBus.cpp:1307
uint8_t waitForAck(uint8_t address, uint8_t command)
Read with the address and command in loop until ack, then issue stop.