Linduino  1.3.0
Linear Technology Arduino-Compatible Demonstration Board
LT_2975FaultLog.cpp
Go to the documentation of this file.
1 /*!
2 LTC SMBus Support: API for a LTC2975 Fault Log
3 
4 @verbatim
5 
6 This API is shared with Linduino and RTOS code. End users should code to this
7 API to enable use of the PMBus code without modifications.
8 
9 @endverbatim
10 
11 
12 Copyright 2018(c) Analog Devices, Inc.
13 
14 All rights reserved.
15 
16 Redistribution and use in source and binary forms, with or without
17 modification, are permitted provided that the following conditions are met:
18  - Redistributions of source code must retain the above copyright
19  notice, this list of conditions and the following disclaimer.
20  - Redistributions in binary form must reproduce the above copyright
21  notice, this list of conditions and the following disclaimer in
22  the documentation and/or other materials provided with the
23  distribution.
24  - Neither the name of Analog Devices, Inc. nor the names of its
25  contributors may be used to endorse or promote products derived
26  from this software without specific prior written permission.
27  - The use of this software may or may not infringe the patent rights
28  of one or more patent holders. This license does not release you
29  from the requirement that you obtain separate licenses from these
30  patent holders to use this software.
31  - Use of the software either in source or binary form, must be run
32  on or directly connected to an Analog Devices Inc. component.
33 
34 THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
35 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
36 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
37 IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
38 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
39 LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
40 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
41 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
42 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
43 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44 */
45 
46 //! @ingroup PMBus_SMBus
47 //! @{
48 //! @defgroup LT_2975FaultLog LT_2975FaultLog
49 //! @}
50 
51 /*! @file
52  @ingroup LT_2975FaultLog
53  Library Header File for LT_2975FaultLog
54 */
55 
56 #include <Arduino.h>
57 #include "LT_2975FaultLog.h"
58 
59 #define RAW_EEPROM
60 
62 {
63  faultLog2975 = NULL;
64 
65  buffer = NULL;
66  voutPeaks = NULL;
67  ioutPeaks = NULL;
68  tempPeaks = NULL;
69  chanStatuses = NULL;
70  voutDatas = NULL;
71  ioutDatas = NULL;
72  poutDatas = NULL;
73  tempDatas = NULL;
74 }
75 
76 
78 {
79  return (uint8_t *)pos >= (uint8_t *)this + firstValidByte && (uint8_t *)pos + (size - 1) <= (uint8_t *)this + lastValidByte;
80 }
81 
82 /*
83  * Read LTC2975 fault log
84  *
85  * address: PMBUS address
86  */
87 void
89 {
90  // Copy to RAM
92  // Monitor BUSY bit
93  while ((pmbus_->smbus()->readByte(address, MFR_COMMON) & (1 << 6)) == 0);
94 
95  uint16_t size = sizeof(struct LT_2975FaultLog::FaultLogLtc2975);
96  uint8_t *data = (uint8_t *) malloc(size);
97  if (data == 0)
98  Serial.print(F("bad malloc."));
99 #ifdef RAW_EEPROM
100  getNvmBlock(address, 0, 128, 0xC8, data);
101 #else
102  // Read block data with log
103  pmbus_->smbus()->readBlock(address, MFR_FAULT_LOG, data, 255);
104 #endif
105 
107 
108  log->firstValidByte = 79; // first byte after preamble
109 
110  log->lastValidByte = 238; // last byte of loop data
111 
112  uint8_t cycle_start = log->preamble.position_last;
113 
114  //57 corresponds to datasheet p77, last line 2nd column
115  log->loops = (LT_2975FaultLog::FaultLogReadLoopLtc2975 *) (log->telemetryData - 57 + cycle_start);
116 
117  faultLog2975 = log;
118 }
119 
120 
122 {
123  free(faultLog2975);
124  faultLog2975 = 0;
125 }
126 
128 {
129  return (uint8_t *)faultLog2975;
130 }
131 
133 {
134  return 255;
135 }
136 
137 void LT_2975FaultLog::dumpBinary(Print *printer)
138 {
139  dumpBin(printer, (uint8_t *)faultLog2975, 255);
140 }
141 
142 void LT_2975FaultLog::print(Print *printer)
143 {
144  if (printer == 0)
145  printer = &Serial;
146  buffer = new char[FILE_TEXT_LINE_MAX];
147 
148  printTitle(printer);
149 
150  printTime(printer);
151 
152  printPeaks(printer);
153 
154  printAllLoops(printer);
155 
156 
157  delete [] buffer;
158 }
159 
160 
161 void LT_2975FaultLog::printTitle(Print *printer)
162 {
163  printer->print(F("LTC2975 Log Data\n"));
164 }
165 
166 void LT_2975FaultLog::printTime(Print *printer)
167 {
168  uint8_t *time = (uint8_t *)&faultLog2975->preamble.shared_time;
169  snprintf_P(buffer, FILE_TEXT_LINE_MAX, PSTR("Fault Time 0x%02x%02x%02x%02x%02x%02x\n"), time[5], time[4], time[3], time[2], time[1], time[0]);
170  printer->print(buffer);
171  printer->print((long) getSharedTime200us(faultLog2975->preamble.shared_time));
172  printer->println(F(" Ticks (200us each)"));
173 }
174 
175 void LT_2975FaultLog::printPeaks(Print *printer)
176 {
177  voutPeaks = new Peak16Words*[4];
178  ioutPeaks = new Peak5_11Words*[4];
179  tempPeaks = new Peak5_11Words*[4];
180  chanStatuses = new ChanStatus*[4];
181 
182  voutPeaks[0] = &faultLog2975->preamble.peaks.vout0_peaks;
183  voutPeaks[1] = &faultLog2975->preamble.peaks.vout1_peaks;
184  voutPeaks[2] = &faultLog2975->preamble.peaks.vout2_peaks;
185  voutPeaks[3] = &faultLog2975->preamble.peaks.vout3_peaks;
186 
187  ioutPeaks[0] = &faultLog2975->preamble.peaks.iout0_peaks;
188  ioutPeaks[1] = &faultLog2975->preamble.peaks.iout1_peaks;
189  ioutPeaks[2] = &faultLog2975->preamble.peaks.iout2_peaks;
190  ioutPeaks[3] = &faultLog2975->preamble.peaks.iout3_peaks;
191 
192  tempPeaks[0] = &faultLog2975->preamble.peaks.temp0_peaks;
193  tempPeaks[1] = &faultLog2975->preamble.peaks.temp1_peaks;
194  tempPeaks[2] = &faultLog2975->preamble.peaks.temp2_peaks;
195  tempPeaks[3] = &faultLog2975->preamble.peaks.temp3_peaks;
196 
201 
202 
203  printer->println(F("\nPeak Values and Fast Status:"));
204  printer->println(F("--------"));
205 
206  printFastChannel(0, printer);
207 
208  float vin_max, vin_min;
211  printer->print(F("Vin: Min: "));
212  printer->print(vin_min, 6);
213  printer->print(F(", Peak: "));
214  printer->println(vin_max, 6);
215 
216  float iin_max, iin_min;
219  printer->print(F("Iin: Min: "));
220  printer->print(iin_min, 6);
221  printer->print(F(", Peak: "));
222  printer->println(iin_max, 6);
223  printer->println();
224 
225  float pin_max, pin_min;
228  printer->print(F("Pin: Min: "));
229  printer->print(pin_min, 6);
230  printer->print(F(", Peak: "));
231  printer->println(pin_max, 6);
232  printer->println();
233 
234  printFastChannel(1, printer);
235  printFastChannel(2, printer);
236  printFastChannel(3, printer);
237 
238  delete [] voutPeaks;
239  delete [] ioutPeaks;
240  delete [] tempPeaks;
241  delete [] chanStatuses;
242 }
243 
244 void LT_2975FaultLog::printFastChannel(uint8_t index, Print *printer)
245 {
246  float vout_peak, vout_min, iout_peak, iout_min, temp_peak, temp_min;
247  uint8_t status;
248  vout_peak = math_.lin16_to_float(getLin16WordVal(voutPeaks[index]->peak), 0x13);
249  vout_min = math_.lin16_to_float(getLin16WordVal(voutPeaks[index]->min), 0x13);
250  printer->print(F("Vout"));
251  printer->print(index);
252  printer->print(F(": Min: "));
253  printer->print(vout_min, 6);
254  printer->print(F(", Peak: "));
255  printer->println(vout_peak, 6);
256  temp_peak = math_.lin11_to_float(getLin5_11WordVal(tempPeaks[index]->peak));
257  temp_min = math_.lin11_to_float(getLin5_11WordVal(tempPeaks[index]->min));
258  printer->print(F("Temp"));
259  printer->print(index);
260  printer->print(F(": Min: "));
261  printer->print(temp_min, 6);
262  printer->print(F(", Peak: "));
263  printer->println(temp_peak, 6);
264  iout_peak = math_.lin11_to_float(getLin5_11WordVal(ioutPeaks[index]->peak));
265  iout_min = math_.lin11_to_float(getLin5_11WordVal(ioutPeaks[index]->min));
266  printer->print(F("Iout"));
267  printer->print(index);
268  printer->print(F(": Min: "));
269  printer->print(iout_min, 6);
270  printer->print(F(", Peak: "));
271  printer->println(iout_peak, 6);
272 
273  printer->print(F("Fast Status"));
274  printer->println(index);
275  status = getRawByteVal(chanStatuses[index]->status_vout);
276  snprintf_P(buffer, FILE_TEXT_LINE_MAX, PSTR(" STATUS_VOUT%u: 0x%02x\n"), index, status);
277  printer->print(buffer);
278  status = getRawByteVal(chanStatuses[index]->status_iout);
279  snprintf_P(buffer, FILE_TEXT_LINE_MAX, PSTR(" STATUS_IOUT%u: 0x%02x\n"), index, status);
280  printer->print(buffer);
281  status = getRawByteVal(chanStatuses[index]->status_mfr_specific);
282  snprintf_P(buffer, FILE_TEXT_LINE_MAX, PSTR(" STATUS_MFR%u: 0x%02x\n"), index, status);
283  printer->println(buffer);
284 }
285 
286 void LT_2975FaultLog::printAllLoops(Print *printer)
287 {
288  voutDatas = new VoutData*[4];
289  ioutDatas = new IoutData*[4];
290  poutDatas = new PoutData*[4];
291  tempDatas = new TempData*[4];
292 
293  printer->println(F("Fault Log Loops Follow:"));
294  printer->println(F("(most recent data first)"));
295 
296  for (int index = 0; index <= 4 && (index < 4 || faultLog2975->isValidData(&faultLog2975->loops[index])); index++)
297  {
298  printLoop(index, printer);
299  }
300 
301  delete [] voutDatas;
302  delete [] ioutDatas;
303  delete [] poutDatas;
304  delete [] tempDatas;
305 }
306 
307 void LT_2975FaultLog::printLoop(uint8_t index, Print *printer)
308 {
309  printer->println(F("-------"));
310  printer->print(F("Loop: "));
311  printer->println(index);
312  printer->println(F("-------"));
313 
314  voutDatas[0] = &faultLog2975->loops[index].vout_data0;
315  voutDatas[1] = &faultLog2975->loops[index].vout_data1;
316  voutDatas[2] = &faultLog2975->loops[index].vout_data2;
317  voutDatas[3] = &faultLog2975->loops[index].vout_data3;
318 
319  ioutDatas[0] = &faultLog2975->loops[index].iout_data0;
320  ioutDatas[1] = &faultLog2975->loops[index].iout_data1;
321  ioutDatas[2] = &faultLog2975->loops[index].iout_data2;
322  ioutDatas[3] = &faultLog2975->loops[index].iout_data3;
323 
324  poutDatas[0] = &faultLog2975->loops[index].pout_data0;
325  poutDatas[1] = &faultLog2975->loops[index].pout_data1;
326  poutDatas[2] = &faultLog2975->loops[index].pout_data2;
327  poutDatas[3] = &faultLog2975->loops[index].pout_data3;
328 
329  tempDatas[0] = &faultLog2975->loops[index].temp_data0;
330  tempDatas[1] = &faultLog2975->loops[index].temp_data1;
331  tempDatas[2] = &faultLog2975->loops[index].temp_data2;
332  tempDatas[3] = &faultLog2975->loops[index].temp_data3;
333 
334  uint8_t stat;
335  float val;
336 
337  printLoopChannel(3, printer);
338  printLoopChannel(2, printer);
339  printLoopChannel(1, printer);
340 
342  {
343  printer->println(F("VIN:"));
345  snprintf_P(buffer, FILE_TEXT_LINE_MAX, PSTR(" STATUS_INPUT: 0x%02x\n"), stat);
346  printer->print(buffer);
347  }
349  {
351  printer->print(F(" READ_VIN: "));
352  printer->print(val, 6);
353  printer->println(F(" V"));
354  }
356  {
358  printer->print(F(" READ_IIN: "));
359  printer->print(val, 6);
360  printer->println(F(" A"));
361  }
363  {
365  printer->print(F(" READ_PIN: "));
366  printer->print(val, 6);
367  printer->println(F(" W"));
368  }
369 
370  printLoopChannel(0, printer);
371 
373  {
374  printer->println(F("Chip Temp:"));
376  printer->print(F(" CHIP TEMP: "));
377  printer->print(val, 6);
378  printer->println(F(" C"));
379  }
380 
381 
382 }
383 
384 void LT_2975FaultLog::printLoopChannel(uint8_t index, Print *printer)
385 {
386  uint8_t stat;
387  float val;
388 
389  if (faultLog2975->isValidData(&poutDatas[index]->read_pout, 2))
390  {
391  printer->print(F("CHAN"));
392  printer->print(index);
393  printer->println(F(":"));
394  val = math_.lin11_to_float(getLin5_11WordReverseVal(poutDatas[index]->read_pout));
395  printer->print(F(" READ POUT: "));
396  printer->print(val, 6);
397  printer->println(F(" W "));
398  }
399  if (faultLog2975->isValidData(&ioutDatas[index]->read_iout, 2))
400  {
401  val = math_.lin11_to_float(getLin5_11WordReverseVal(ioutDatas[index]->read_iout));
402  printer->print(F(" READ IOUT: "));
403  printer->print(val, 6);
404  printer->println(F(" A "));
405  }
406  if (faultLog2975->isValidData(&ioutDatas[index]->status_iout, 1))
407  {
408  stat = getRawByteVal(ioutDatas[index]->status_iout);
409  snprintf_P(buffer, FILE_TEXT_LINE_MAX, PSTR(" STATUS IOUT: 0x%02x\n"), stat);
410  printer->print(buffer);
411  }
412  if (faultLog2975->isValidData(&tempDatas[index]->status_temp, 1))
413  {
414  stat = getRawByteVal(tempDatas[index]->status_temp);
415  snprintf_P(buffer, FILE_TEXT_LINE_MAX, PSTR(" STATUS TEMP: 0x%02x\n"), stat);
416  printer->print(buffer);
417  }
418  if (faultLog2975->isValidData(&tempDatas[index]->read_temp1, 2))
419  {
420  val = math_.lin11_to_float(getLin5_11WordReverseVal(tempDatas[index]->read_temp1));
421  printer->print(F(" READ TEMP: "));
422  printer->print(val, 6);
423  printer->println(F(" C"));
424  }
425  if (faultLog2975->isValidData(&voutDatas[index]->status_mfr, 1))
426  {
427  stat = getRawByteVal(voutDatas[index]->status_mfr);
428  snprintf_P(buffer, FILE_TEXT_LINE_MAX, PSTR(" STATUS_MFR: 0x%02x\n"), stat);
429  printer->print(buffer);
430  }
431  if (faultLog2975->isValidData(&voutDatas[index]->status_vout, 1))
432  {
433  stat = getRawByteVal(voutDatas[index]->status_vout);
434  snprintf_P(buffer, FILE_TEXT_LINE_MAX, PSTR(" STATUS_VOUT: 0x%02x\n"), stat);
435  printer->print(buffer);
436  }
437  if (faultLog2975->isValidData(&voutDatas[index]->read_vout))
438  {
439  val = math_.lin16_to_float(getLin16WordReverseVal(voutDatas[index]->read_vout), 0x13);
440  printer->print(F(" READ_VOUT: "));
441  printer->print(val, 6);
442  printer->println(F(" V"));
443  }
444 }
445 
446 
447 
uint16_t getLin5_11WordReverseVal(Lin5_11WordReverse value)
void dumpBin(Print *printer, uint8_t *log, uint8_t size)
#define MFR_FAULT_LOG
Definition: LT_PMBus.h:140
struct Lin5_11WordReverse vin
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
uint16_t getBinarySize()
Get size of binary data.
struct Lin5_11WordReverse read_iin
FaultLogLtc2975 * faultLog2975
void release()
Frees the memory reserved for the fault log.
virtual void sendByte(uint8_t address, uint8_t command)=0
SMBus send byte command.
uint16_t getLin5_11WordVal(Lin5_11Word value)
bool isValidData(void *pos, uint8_t size=2)
uint8_t * getBinary()
Get binary of the fault log or NULL if no log.
void getNvmBlock(uint8_t address, uint16_t offset, uint16_t numWords, uint8_t command, uint8_t *data)
LT_PMBusMath math_
LT_2975FaultLog(LT_PMBus *pmbus)
Constructor.
static LT_PMBus * pmbus
Definition: DC2875A.ino:82
float lin11_to_float(lin11_t xin)
#define FILE_TEXT_LINE_MAX
Definition: LT_FaultLog.h:60
void dumpBinary(Print *printer=0)
Dumps binary of the fault log to a Print inheriting object, or Serial if none specified.
#define min(a, b)
LT_PMBus * pmbus_
Definition: LT_FaultLog.h:129
static uint8_t address
Definition: DC2091A.ino:83
union LT_union_int32_4bytes data
Definition: DC2094A.ino:138
struct FaultLogReadStatusLtc2975 fault_log_status
static int16_t pos
uint16_t getLin16WordVal(Lin16Word value)
struct Lin5_11WordReverse read_temp1
struct Lin5_11WordReverse read_pin
LTC SMBus Support: Implementation for a LTC2975 Fault Log.
virtual uint8_t readByte(uint8_t address, uint8_t command)=0
SMBus read byte command.
struct Lin16WordReverse read_vout
void read(uint8_t address)
Reads the fault log from the specified address, reserves memory to hold the data. ...
#define MFR_COMMON
Definition: LT_PMBus.h:141
LT_SMBus * smbus()
Definition: LT_PMBus.h:401
uint64_t getSharedTime200us(FaultLogTimeStamp time_stamp)
void print(Print *printer=0)
Pretty prints this part&#39;s fault log to a Print inheriting object, or Serial if none specified...
struct FaultLogPreambleLtc2975 preamble
struct Lin5_11WordReverse read_pout
static int index
virtual uint8_t readBlock(uint8_t address, uint8_t command, uint8_t *block, uint16_t block_size)=0
SMBus read block command.
struct FaultLogReadLoopLtc2975 * loops
uint8_t getRawByteVal(RawByte value)
uint16_t getLin16WordReverseVal(Lin16WordReverse value)
#define MFR_FAULT_LOG_RESTORE
Definition: LT_PMBus.h:136
struct Lin5_11WordReverse read_iout
PMBus communication.
Definition: LT_PMBus.h:370