Linduino  1.3.0
Linear Technology Arduino-Compatible Demonstration Board
LT_2974FaultLog.cpp
Go to the documentation of this file.
1 /*!
2 LTC SMBus Support: API for a LTC2974 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_2974FaultLog LT_2974FaultLog
49 //! @}
50 
51 /*! @file
52  @ingroup LT_2974FaultLog
53  Library Header File for LT_2974FaultLog
54 */
55 
56 #include <Arduino.h>
57 #include "LT_2974FaultLog.h"
58 
59 #define RAW_EEPROM
60 
61 void rotate(uint8_t *buf, int start, int len)
62 {
63 
64  int count = 0;
65  int offset = 0;
66 
67  while (count < len)
68  {
69 
70  int index = offset;
71  char tmp = buf[index];
72  int index2 = (start + index) % len;
73 
74  while (index2 != offset)
75  {
76 
77  buf[index] = buf[index2];
78  count++;
79 
80  index = index2;
81  index2 = (start + index) % len;
82  }
83 
84  buf[index] = tmp;
85  count++;
86 
87  offset++;
88  }
89 }
90 
92 {
93  faultLog2974 = NULL;
94 
95  buffer = NULL;
96  voutPeaks = NULL;
97  ioutPeaks = NULL;
98  tempPeaks = NULL;
99  chanStatuses = NULL;
100  voutDatas = NULL;
101  ioutDatas = NULL;
102  poutDatas = NULL;
103  tempDatas = NULL;
104 }
105 
106 
108 {
109  return (uint8_t *)pos >= (uint8_t *)this + firstValidByte && (uint8_t *)pos + (size - 1) <= (uint8_t *)this + lastValidByte;
110 }
111 
112 /*
113  * Read LTC2974 fault log
114  *
115  * address: PMBUS address
116  */
117 void
119 {
120  // Copy to RAM
122  // Monitor BUSY bit
123  while ((pmbus_->smbus()->readByte(address, MFR_COMMON) & (1 << 6)) == 0);
124 
125  uint16_t size = sizeof(struct LT_2974FaultLog::FaultLogLtc2974);
126  uint8_t *data = (uint8_t *) malloc(size);
127  if (data == 0)
128  Serial.print(F("bad malloc."));
129 #ifdef RAW_EEPROM
130  // For MFR_EE_DATA, but would require reversing cyclic data
131  getNvmBlock(address, 384, 128, 0x00, data);
132  // Points to the beginning of the cyclic data
133  uint8_t block_address = data[0];
134  // Shift the last data to the top
135  rotate(&data[72], block_address - 71, 167);
136  // Drop the block address
137  memmove(data, data+1, size-1);
138  // Reverse the order of cyclic data
139  for (int i = 71; i < 71 + 83; i++)
140  {
141  uint8_t d = data[237-(i-71)];
142  data[237-(i-71)] = data[i];
143  data[i] = d;
144  }
145 
146 #else
147  // Read block data with log
148  pmbus_->smbus()->readBlock(address, MFR_FAULT_LOG, data, 255);
149 #endif
150 
152 
153  log->firstValidByte = 71;
154 
155  log->lastValidByte = 237;
156 
157  uint8_t cycle_start = log->preamble.position_last;
158 
159  log->loops = (LT_2974FaultLog::FaultLogReadLoopLtc2974 *) (log->telemetryData - 53 + cycle_start);
160 
161  faultLog2974 = log;
162 }
163 
164 
166 {
167  free(faultLog2974);
168  faultLog2974 = 0;
169 }
170 
172 {
173  return (uint8_t *)faultLog2974;
174 }
175 
177 {
178  return 255;
179 }
180 
181 void LT_2974FaultLog::dumpBinary(Print *printer)
182 {
183  dumpBin(printer, (uint8_t *)faultLog2974, 255);
184 }
185 
186 void LT_2974FaultLog::print(Print *printer)
187 {
188  if (printer == 0)
189  printer = &Serial;
190  buffer = new char[FILE_TEXT_LINE_MAX];
191 
192  printTitle(printer);
193 
194  printTime(printer);
195 
196  printPeaks(printer);
197 
198  printAllLoops(printer);
199 
200 
201  delete [] buffer;
202 }
203 
204 
205 void LT_2974FaultLog::printTitle(Print *printer)
206 {
207  printer->print(F("LTC2974 Log Data\n"));
208 }
209 
210 void LT_2974FaultLog::printTime(Print *printer)
211 {
212  uint8_t *time = (uint8_t *)&faultLog2974->preamble.shared_time;
213  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]);
214  printer->print(buffer);
215  printer->print((long) getSharedTime200us(faultLog2974->preamble.shared_time));
216  printer->println(F(" Ticks (200us each)"));
217 }
218 
219 void LT_2974FaultLog::printPeaks(Print *printer)
220 {
221  voutPeaks = new Peak16Words*[4];
222  ioutPeaks = new Peak5_11Words*[4];
223  tempPeaks = new Peak5_11Words*[4];
224  chanStatuses = new ChanStatus*[4];
225 
226  voutPeaks[0] = &faultLog2974->preamble.peaks.vout0_peaks;
227  voutPeaks[1] = &faultLog2974->preamble.peaks.vout1_peaks;
228  voutPeaks[2] = &faultLog2974->preamble.peaks.vout2_peaks;
229  voutPeaks[3] = &faultLog2974->preamble.peaks.vout3_peaks;
230 
231  ioutPeaks[0] = &faultLog2974->preamble.peaks.iout0_peaks;
232  ioutPeaks[1] = &faultLog2974->preamble.peaks.iout1_peaks;
233  ioutPeaks[2] = &faultLog2974->preamble.peaks.iout2_peaks;
234  ioutPeaks[3] = &faultLog2974->preamble.peaks.iout3_peaks;
235 
236  tempPeaks[0] = &faultLog2974->preamble.peaks.temp0_peaks;
237  tempPeaks[1] = &faultLog2974->preamble.peaks.temp1_peaks;
238  tempPeaks[2] = &faultLog2974->preamble.peaks.temp2_peaks;
239  tempPeaks[3] = &faultLog2974->preamble.peaks.temp3_peaks;
240 
245 
246 
247  printer->println(F("\nPeak Values and Fast Status:"));
248  printer->println(F("--------"));
249 
250  printFastChannel(0, printer);
251 
252  float vin_max, vin_min;
255  printer->print(F("Vin: Min: "));
256  printer->print(vin_min, 6);
257  printer->print(F(", Peak: "));
258  printer->println(vin_max, 6);
259  printer->println();
260 
261  printFastChannel(1, printer);
262  printFastChannel(2, printer);
263  printFastChannel(3, printer);
264 
265  delete [] voutPeaks;
266  delete [] ioutPeaks;
267  delete [] tempPeaks;
268  delete [] chanStatuses;
269 }
270 
271 void LT_2974FaultLog::printFastChannel(uint8_t index, Print *printer)
272 {
273  float vout_peak, vout_min, iout_peak, iout_min, temp_peak, temp_min;
274  uint8_t status;
275  vout_peak = math_.lin16_to_float(getLin16WordVal(voutPeaks[index]->peak), 0x13);
276  vout_min = math_.lin16_to_float(getLin16WordVal(voutPeaks[index]->min), 0x13);
277  printer->print(F("Vout"));
278  printer->print(index);
279  printer->print(F(": Min: "));
280  printer->print(vout_min, 6);
281  printer->print(F(", Peak: "));
282  printer->println(vout_peak, 6);
283  temp_peak = math_.lin11_to_float(getLin5_11WordVal(tempPeaks[index]->peak));
284  temp_min = math_.lin11_to_float(getLin5_11WordVal(tempPeaks[index]->min));
285  printer->print(F("Temp"));
286  printer->print(index);
287  printer->print(F(": Min: "));
288  printer->print(temp_min, 6);
289  printer->print(F(", Peak: "));
290  printer->println(temp_peak, 6);
291  iout_peak = math_.lin11_to_float(getLin5_11WordVal(ioutPeaks[index]->peak));
292  iout_min = math_.lin11_to_float(getLin5_11WordVal(ioutPeaks[index]->min));
293  printer->print(F("Iout"));
294  printer->print(index);
295  printer->print(F(": Min: "));
296  printer->print(iout_min, 6);
297  printer->print(F(", Peak: "));
298  printer->println(iout_peak, 6);
299 
300  printer->print(F("Fast Status"));
301  printer->println(index);
302  status = getRawByteVal(chanStatuses[index]->status_vout);
303  snprintf_P(buffer, FILE_TEXT_LINE_MAX, PSTR(" STATUS_VOUT%u: 0x%02x\n"), index, status);
304  printer->print(buffer);
305  status = getRawByteVal(chanStatuses[index]->status_iout);
306  snprintf_P(buffer, FILE_TEXT_LINE_MAX, PSTR(" STATUS_IOUT%u: 0x%02x\n"), index, status);
307  printer->print(buffer);
308  status = getRawByteVal(chanStatuses[index]->status_mfr_specific);
309  snprintf_P(buffer, FILE_TEXT_LINE_MAX, PSTR(" STATUS_MFR%u: 0x%02x\n"), index, status);
310  printer->println(buffer);
311 }
312 
313 void LT_2974FaultLog::printAllLoops(Print *printer)
314 {
315  voutDatas = new VoutData*[4];
316  ioutDatas = new IoutData*[4];
317  poutDatas = new PoutData*[4];
318  tempDatas = new TempData*[4];
319 
320  printer->println(F("Fault Log Loops Follow:"));
321  printer->println(F("(most recent data first)"));
322 
323  for (int index = 0; index <= 4 && (index < 4 || faultLog2974->isValidData(&faultLog2974->loops[index])); index++)
324  {
325  printLoop(index, printer);
326  }
327 
328  delete [] voutDatas;
329  delete [] ioutDatas;
330  delete [] poutDatas;
331  delete [] tempDatas;
332 }
333 
334 void LT_2974FaultLog::printLoop(uint8_t index, Print *printer)
335 {
336  printer->println(F("-------"));
337  printer->print(F("Loop: "));
338  printer->println(index);
339  printer->println(F("-------"));
340 
341  voutDatas[0] = &faultLog2974->loops[index].vout_data0;
342  voutDatas[1] = &faultLog2974->loops[index].vout_data1;
343  voutDatas[2] = &faultLog2974->loops[index].vout_data2;
344  voutDatas[3] = &faultLog2974->loops[index].vout_data3;
345 
346  ioutDatas[0] = &faultLog2974->loops[index].iout_data0;
347  ioutDatas[1] = &faultLog2974->loops[index].iout_data1;
348  ioutDatas[2] = &faultLog2974->loops[index].iout_data2;
349  ioutDatas[3] = &faultLog2974->loops[index].iout_data3;
350 
351  poutDatas[0] = &faultLog2974->loops[index].pout_data0;
352  poutDatas[1] = &faultLog2974->loops[index].pout_data1;
353  poutDatas[2] = &faultLog2974->loops[index].pout_data2;
354  poutDatas[3] = &faultLog2974->loops[index].pout_data3;
355 
356  tempDatas[0] = &faultLog2974->loops[index].temp_data0;
357  tempDatas[1] = &faultLog2974->loops[index].temp_data1;
358  tempDatas[2] = &faultLog2974->loops[index].temp_data2;
359  tempDatas[3] = &faultLog2974->loops[index].temp_data3;
360 
361  uint8_t stat;
362  float val;
363 
364  printLoopChannel(3, printer);
365  printLoopChannel(2, printer);
366  printLoopChannel(1, printer);
367 
369  {
370  printer->println(F("VIN:"));
372  snprintf_P(buffer, FILE_TEXT_LINE_MAX, PSTR(" STATUS_INPUT: 0x%02x\n"), stat);
373  printer->print(buffer);
374  }
376  {
378  printer->print(F(" READ_VIN: "));
379  printer->print(val, 6);
380  printer->println(F(" V"));
381  }
382 
383  printLoopChannel(0, printer);
384 
386  {
387  printer->println(F("Chip Temp:"));
389  printer->print(F(" CHIP TEMP: "));
390  printer->print(val, 6);
391  printer->println(F(" C"));
392  }
393 
394 
395 }
396 
397 void LT_2974FaultLog::printLoopChannel(uint8_t index, Print *printer)
398 {
399  uint8_t stat;
400  float val;
401 
402  if (faultLog2974->isValidData(&poutDatas[index]->read_pout, 2))
403  {
404  printer->print(F("CHAN"));
405  printer->print(index);
406  printer->println(F(":"));
407  val = math_.lin11_to_float(getLin5_11WordReverseVal(poutDatas[index]->read_pout));
408  printer->print(F(" READ POUT: "));
409  printer->print(val, 6);
410  printer->println(F(" W "));
411  }
412  if (faultLog2974->isValidData(&ioutDatas[index]->read_iout, 2))
413  {
414  val = math_.lin11_to_float(getLin5_11WordReverseVal(ioutDatas[index]->read_iout));
415  printer->print(F(" READ IOUT: "));
416  printer->print(val, 6);
417  printer->println(F(" A "));
418  }
419  if (faultLog2974->isValidData(&ioutDatas[index]->status_iout, 1))
420  {
421  stat = getRawByteVal(ioutDatas[index]->status_iout);
422  snprintf_P(buffer, FILE_TEXT_LINE_MAX, PSTR(" STATUS IOUT: 0x%02x\n"), stat);
423  printer->print(buffer);
424  }
425  if (faultLog2974->isValidData(&tempDatas[index]->status_temp, 1))
426  {
427  stat = getRawByteVal(tempDatas[index]->status_temp);
428  snprintf_P(buffer, FILE_TEXT_LINE_MAX, PSTR(" STATUS TEMP: 0x%02x\n"), stat);
429  printer->print(buffer);
430  }
431  if (faultLog2974->isValidData(&tempDatas[index]->read_temp1, 2))
432  {
433  val = math_.lin11_to_float(getLin5_11WordReverseVal(tempDatas[index]->read_temp1));
434  printer->print(F(" READ TEMP: "));
435  printer->print(val, 6);
436  printer->println(F(" C"));
437  }
438  if (faultLog2974->isValidData(&voutDatas[index]->status_mfr, 1))
439  {
440  stat = getRawByteVal(voutDatas[index]->status_mfr);
441  snprintf_P(buffer, FILE_TEXT_LINE_MAX, PSTR(" STATUS_MFR: 0x%02x\n"), stat);
442  printer->print(buffer);
443  }
444  if (faultLog2974->isValidData(&voutDatas[index]->status_vout, 1))
445  {
446  stat = getRawByteVal(voutDatas[index]->status_vout);
447  snprintf_P(buffer, FILE_TEXT_LINE_MAX, PSTR(" STATUS_VOUT: 0x%02x\n"), stat);
448  printer->print(buffer);
449  }
450  if (faultLog2974->isValidData(&voutDatas[index]->read_vout))
451  {
452  val = math_.lin16_to_float(getLin16WordReverseVal(voutDatas[index]->read_vout), 0x13);
453  printer->print(F(" READ_VOUT: "));
454  printer->print(val, 6);
455  printer->println(F(" V"));
456  }
457 }
458 
459 
460 
uint16_t getLin5_11WordReverseVal(Lin5_11WordReverse value)
uint16_t getBinarySize()
Get size of binary data.
void dumpBin(Print *printer, uint8_t *log, uint8_t size)
FaultLogLtc2974 * faultLog2974
#define MFR_FAULT_LOG
Definition: LT_PMBus.h:140
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 dumpBinary(Print *printer=0)
Dumps binary of the fault log to a Print inheriting object, or Serial if none specified.
virtual void sendByte(uint8_t address, uint8_t command)=0
SMBus send byte command.
struct Lin5_11WordReverse read_iout
uint16_t getLin5_11WordVal(Lin5_11Word value)
LT_PMBusMath math_
static LT_PMBus * pmbus
Definition: DC2875A.ino:82
uint8_t * getBinary()
Get binary of the fault log or NULL if no log.
float lin11_to_float(lin11_t xin)
#define FILE_TEXT_LINE_MAX
Definition: LT_FaultLog.h:60
#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
static int16_t pos
uint16_t getLin16WordVal(Lin16Word value)
struct FaultLogPreambleLtc2974 preamble
void getNvmBlock(uint8_t address, uint16_t offset, uint16_t numWords, uint8_t command, uint8_t *data)
virtual uint8_t readByte(uint8_t address, uint8_t command)=0
SMBus read byte command.
void release()
Frees the memory reserved for the fault log.
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
bool isValidData(void *pos, uint8_t size=2)
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...
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 Lin5_11WordReverse vin
static float start
struct Lin5_11WordReverse read_pout
struct FaultLogReadStatusLtc2974 fault_log_status
uint8_t getRawByteVal(RawByte value)
void rotate(uint8_t *buf, int start, int len)
LTC SMBus Support: Implementation for a LTC2974 Fault Log.
uint16_t getLin16WordReverseVal(Lin16WordReverse value)
static int i
Definition: DC2430A.ino:184
#define MFR_FAULT_LOG_RESTORE
Definition: LT_PMBus.h:136
struct FaultLogReadLoopLtc2974 * loops
LT_2974FaultLog(LT_PMBus *pmbus)
Constructor.
struct Lin5_11WordReverse read_temp1
PMBus communication.
Definition: LT_PMBus.h:370