Linduino  1.3.0
Linear Technology Arduino-Compatible Demonstration Board
LT_2977FaultLog.cpp
Go to the documentation of this file.
1 /*!
2 LTC SMBus Support: API for a LTC2977 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_2977FaultLog LT_2977FaultLog
49 //! @}
50 
51 /*! @file
52  @ingroup LT_2977FaultLog
53  Library Header File for LT_2977FaultLog
54 */
55 
56 #include <Arduino.h>
57 #include "LT_2977FaultLog.h"
58 
59 #define RAW_EEPROM
60 
62 {
63  faultLog2977 = NULL;
64 
65  buffer = NULL;
66  voutPeaks = NULL;
67  chanStatuses = NULL;
68  voutDatas = NULL;
69 }
70 
71 
73 {
74  return (uint8_t *)pos >= (uint8_t *)this + firstValidByte && (uint8_t *)pos + (size - 1) <= (uint8_t *)this + lastValidByte;
75 }
76 
77 /*
78  * Read LTC2977 fault log
79  *
80  * address: PMBUS address
81  */
82 void
84 {
85  // Copy to RAM
87  // Monitor BUSY bit
88  while ((pmbus_->smbus()->readByte(address, MFR_COMMON) & (1 << 6)) == 0);
89 
90  uint16_t size = sizeof(struct LT_2977FaultLog::FaultLogLtc2977);
91  uint8_t *data = (uint8_t *) malloc(size);
92  if (data == 0)
93  Serial.print(F("bad malloc."));
94 #ifdef RAW_EEPROM
95  getNvmBlock(address, 0, 128, 0xC0, data);
96 #else
97  // Read block data with log
98  pmbus_->smbus()->readBlock(address, MFR_FAULT_LOG, data, 255);
99 #endif
100 
102 
103  log->firstValidByte = 72;
104 
105  uint8_t count = log->preamble.cyclic_data_count;
106  if (count == 255)
107  log->lastValidByte = 237;
108  else
109  log->lastValidByte = 237 - (166-count);
110 
111  uint8_t cycle_start = log->preamble.position_last;
112 
113  log->loops = (LT_2977FaultLog::FaultLogReadLoopLtc2977 *) (log->telemetryData - 45 + cycle_start);
114 
115  faultLog2977 = log;
116 }
117 
118 
120 {
121  free(faultLog2977);
122  faultLog2977 = 0;
123 }
124 
126 {
127  return (uint8_t *)faultLog2977;
128 }
129 
131 {
132  return 255;
133 }
134 
135 void LT_2977FaultLog::dumpBinary(Print *printer)
136 {
137  dumpBin(printer, (uint8_t *)faultLog2977, 255);
138 }
139 
140 void LT_2977FaultLog::print(Print *printer)
141 {
142  if (printer == 0)
143  printer = &Serial;
144  buffer = new char[FILE_TEXT_LINE_MAX];
145 
146  printTitle(printer);
147 
148  printTime(printer);
149 
150  printPeaks(printer);
151 
152  printAllLoops(printer);
153 
154 
155  delete [] buffer;
156 }
157 
158 
159 void LT_2977FaultLog::printTitle(Print *printer)
160 {
161  printer->print(F("LTC2977 Log Data\n"));
162 }
163 
164 void LT_2977FaultLog::printTime(Print *printer)
165 {
166  uint8_t *time = (uint8_t *)&faultLog2977->preamble.shared_time;
167  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]);
168  printer->print(buffer);
169  printer->print((long) getSharedTime200us(faultLog2977->preamble.shared_time));
170  printer->println(F(" Ticks (200us each)"));
171 }
172 
173 void LT_2977FaultLog::printPeaks(Print *printer)
174 {
175  voutPeaks = new Peak16Words*[8];
176  chanStatuses = new ChanStatus*[8];
177 
178  voutPeaks[0] = &faultLog2977->preamble.peaks.vout0_peaks;
179  voutPeaks[1] = &faultLog2977->preamble.peaks.vout1_peaks;
180  voutPeaks[2] = &faultLog2977->preamble.peaks.vout2_peaks;
181  voutPeaks[3] = &faultLog2977->preamble.peaks.vout3_peaks;
182  voutPeaks[4] = &faultLog2977->preamble.peaks.vout4_peaks;
183  voutPeaks[5] = &faultLog2977->preamble.peaks.vout5_peaks;
184  voutPeaks[6] = &faultLog2977->preamble.peaks.vout6_peaks;
185  voutPeaks[7] = &faultLog2977->preamble.peaks.vout7_peaks;
186 
195 
196 
197  printer->println(F("\nPeak Values and Fast Status:"));
198  printer->println(F("--------"));
199 
200  printFastChannel(0, printer);
201  printFastChannel(1, printer);
202 
203  float vin_max, vin_min, temp_max, temp_min;
206  printer->print(F("Vin: Min: "));
207  printer->print(vin_min, 6);
208  printer->print(F(", Peak: "));
209  printer->println(vin_max, 6);
210  printer->println();
211 
212  printFastChannel(2, printer);
213  printFastChannel(3, printer);
214 
217  printer->print(F("Temp: Min: "));
218  printer->print(temp_min, 6);
219  printer->print(F(", Peak: "));
220  printer->println(temp_max, 6);
221  printer->println();
222 
223  printFastChannel(4, printer);
224  printFastChannel(5, printer);
225  printFastChannel(6, printer);
226  printFastChannel(7, printer);
227 
228  delete [] voutPeaks;
229  delete [] chanStatuses;
230 }
231 
232 void LT_2977FaultLog::printFastChannel(uint8_t index, Print *printer)
233 {
234  float vout_peak, vout_min;
235  uint8_t status;
236  vout_peak = math_.lin16_to_float(getLin16WordVal(voutPeaks[index]->peak), 0x13);
237  vout_min = math_.lin16_to_float(getLin16WordVal(voutPeaks[index]->min), 0x13);
238  printer->print(F("Vout"));
239  printer->print(index);
240  printer->print(F(": Min: "));
241  printer->print(vout_min, 6);
242  printer->print(F(", Peak: "));
243  printer->println(vout_peak, 6);
244  printer->print(F("Fast Status"));
245  printer->println(index);
246  status = getRawByteVal(chanStatuses[index]->status_vout);
247  snprintf_P(buffer, FILE_TEXT_LINE_MAX, PSTR(" STATUS_VOUT%u: 0x%02x\n"), index, status);
248  printer->print(buffer);
249  status = getRawByteVal(chanStatuses[index]->status_mfr);
250  snprintf_P(buffer, FILE_TEXT_LINE_MAX, PSTR(" STATUS_MFR%u: 0x%02x\n"), index, status);
251  printer->print(buffer);
252  status = getRawByteVal(chanStatuses[index]->mfr_status2);
253  snprintf_P(buffer, FILE_TEXT_LINE_MAX, PSTR(" MFR_STATUS_2%u: 0x%02x\n"), index, status);
254  printer->println(buffer);
255 }
256 
257 void LT_2977FaultLog::printAllLoops(Print *printer)
258 {
259  voutDatas = new VoutData*[8];
260 
261  printer->println(F("Fault Log Loops Follow:"));
262  printer->println(F("(most recent data first)"));
263 
264  for (int index = 0; index <= 4 && (index < 4 || faultLog2977->isValidData(&faultLog2977->loops[index])); index++)
265  {
266  printLoop(index, printer);
267  }
268 
269  delete [] voutDatas;
270 }
271 
272 void LT_2977FaultLog::printLoop(uint8_t index, Print *printer)
273 {
274  printer->println(F("-------"));
275  printer->print(F("Loop: "));
276  printer->println(index);
277  printer->println(F("-------"));
278 
279  voutDatas[0] = &faultLog2977->loops[index].vout_data0;
280  voutDatas[1] = &faultLog2977->loops[index].vout_data1;
281  voutDatas[2] = &faultLog2977->loops[index].vout_data2;
282  voutDatas[3] = &faultLog2977->loops[index].vout_data3;
283  voutDatas[4] = &faultLog2977->loops[index].vout_data4;
284  voutDatas[5] = &faultLog2977->loops[index].vout_data5;
285  voutDatas[6] = &faultLog2977->loops[index].vout_data6;
286  voutDatas[7] = &faultLog2977->loops[index].vout_data7;
287 
288  uint8_t stat;
289  float val;
290 
291  printLoopChannel(7, printer);
292  printLoopChannel(6, printer);
293  printLoopChannel(5, printer);
294  printLoopChannel(4, printer);
295 
297  {
298  printer->println(F("TEMPERATURE:"));
300  snprintf_P(buffer, FILE_TEXT_LINE_MAX, PSTR(" STATUS_TEMP: 0x%02x\n"), stat);
301  printer->print(buffer);
302  }
304  {
306  printer->print(F(" READ_TEMP: "));
307  printer->print(val, 6);
308  printer->println(F(" C"));
309  }
310 
311  printLoopChannel(3, printer);
312  printLoopChannel(2, printer);
313 
315  {
316  printer->println(F("VIN:"));
318  snprintf_P(buffer, FILE_TEXT_LINE_MAX, PSTR(" STATUS_INPUT: 0x%02x\n"), stat);
319  printer->print(buffer);
320  }
322  {
324  printer->print(F(" READ_VIN: "));
325  printer->print(val, 6);
326  printer->println(F(" V"));
327  }
328 
329  printLoopChannel(1, printer);
330  printLoopChannel(0, printer);
331 }
332 
333 void LT_2977FaultLog::printLoopChannel(uint8_t index, Print *printer)
334 {
335  uint8_t stat;
336  float val;
337 
338  if (faultLog2977->isValidData(&voutDatas[index]->mfr_status2, 1))
339  {
340  printer->print(F("CHAN"));
341  printer->print(index);
342  printer->println(F(":"));
343  stat = getRawByteVal(voutDatas[index]->mfr_status2);
344  snprintf_P(buffer, FILE_TEXT_LINE_MAX, PSTR(" MFR_STATUS_2: 0x%02x\n"), stat);
345  printer->print(buffer);
346  }
347  if (faultLog2977->isValidData(&voutDatas[index]->status_mfr, 1))
348  {
349  stat = getRawByteVal(voutDatas[index]->status_mfr);
350  snprintf_P(buffer, FILE_TEXT_LINE_MAX, PSTR(" STATUS_MFR: 0x%02x\n"), stat);
351  printer->print(buffer);
352  }
353  if (faultLog2977->isValidData(&voutDatas[index]->status_vout, 1))
354  {
355  stat = getRawByteVal(voutDatas[index]->status_vout);
356  snprintf_P(buffer, FILE_TEXT_LINE_MAX, PSTR(" STATUS_VOUT: 0x%02x\n"), stat);
357  printer->print(buffer);
358  }
359  if (faultLog2977->isValidData(&voutDatas[index]->read_vout))
360  {
361  val = math_.lin16_to_float(getLin16WordReverseVal(voutDatas[index]->read_vout), 0x13);
362  printer->print(F(" READ_VOUT: "));
363  printer->print(val, 6);
364  printer->println(F(" V"));
365  }
366 }
367 
368 
369 
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 Lin16WordReverse read_vout
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
LTC SMBus Support: Implementation for a LTC2977 Fault Log.
virtual void sendByte(uint8_t address, uint8_t command)=0
SMBus send byte command.
uint16_t getLin5_11WordVal(Lin5_11Word value)
void dumpBinary(Print *printer=0)
Dumps binary of the fault log to a Print inheriting object, or Serial if none specified.
struct FaultLogPreambleLtc2977 preamble
void getNvmBlock(uint8_t address, uint16_t offset, uint16_t numWords, uint8_t command, uint8_t *data)
struct Lin5_11WordReverse temp
LT_PMBusMath math_
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
#define min(a, b)
LT_PMBus * pmbus_
Definition: LT_FaultLog.h:129
void read(uint8_t address)
Reads the fault log from the specified address, reserves memory to hold the data. ...
static uint8_t address
Definition: DC2091A.ino:83
union LT_union_int32_4bytes data
Definition: DC2094A.ino:138
static int16_t pos
bool isValidData(void *pos, uint8_t size=2)
uint16_t getLin16WordVal(Lin16Word value)
struct FaultLogReadStatusLtc2977 fault_log_status
struct LT_FaultLog::FaultLogTimeStamp shared_time
uint8_t * getBinary()
Get binary of the fault log or NULL if no log.
virtual uint8_t readByte(uint8_t address, uint8_t command)=0
SMBus read byte command.
#define MFR_COMMON
Definition: LT_PMBus.h:141
LT_SMBus * smbus()
Definition: LT_PMBus.h:401
uint64_t getSharedTime200us(FaultLogTimeStamp time_stamp)
struct FaultLogReadLoopLtc2977 * loops
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.
LT_2977FaultLog(LT_PMBus *pmbus)
Constructor.
struct Lin5_11WordReverse vin
uint8_t getRawByteVal(RawByte value)
uint16_t getLin16WordReverseVal(Lin16WordReverse value)
void release()
Frees the memory reserved for the fault log.
uint16_t getBinarySize()
Get size of binary data.
#define MFR_FAULT_LOG_RESTORE
Definition: LT_PMBus.h:136
FaultLogLtc2977 * faultLog2977
PMBus communication.
Definition: LT_PMBus.h:370