FastArduino  v1.8
C++ library to build fast but small Arduino/AVR projects
i2c_debug.h
Go to the documentation of this file.
1 // Copyright 2016-2021 Jean-Francois Poilpret
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
16 
21 #ifndef I2C_DEBUG_HH
22 #define I2C_DEBUG_HH
23 
24 #include "flash.h"
25 #include "streams.h"
26 #include "i2c_handler_common.h"
27 #include "i2c_status.h"
28 
29 namespace i2c
30 {
36  namespace debug
37  {
38  }
39 }
40 
41 namespace i2c::debug
42 {
44  // Add utility ostream insert operator for FutureStatus
47 
54  enum class DEBUG : uint8_t
55  {
67  DEBUG_STEPS = 0x01,
69  DEBUG_SEND_OK = 0x02,
71  DEBUG_SEND_ERR = 0x04,
73  DEBUG_RECV_OK = 0x08,
75  DEBUG_RECV_ERR = 0x10,
77  DEBUG_ALL = 0xFF
78  };
79 
81  DEBUG operator|(DEBUG a, DEBUG b);
83 
92  template<uint8_t SIZE> class I2CDebugRecorder
93  {
94  public:
109  explicit I2CDebugRecorder(DEBUG debug = DEBUG::DEBUG_ALL) : debug_{debug} {}
110 
115  void reset()
116  {
117  index_ = 0;
118  }
119 
126  {
127  for (uint8_t i = 0; i < index_; ++i)
128  {
129  const i2c::DebugStatus status = status_[i];
130  switch (status)
131  {
138  case i2c::DebugStatus::SEND_ERROR:
139  case i2c::DebugStatus::SEND_OK:
140  out << status << streams::flush;
141  break;
142 
143  default:
144  out << status << streams::hex << data_[i] << ' ' << streams::flush;
145  }
146  }
147  if (index_ >= SIZE)
148  out << F("# OVF #");
149  out << streams::endl;
150  index_ = 0;
151  }
152 
154  void operator()(i2c::DebugStatus status, uint8_t data)
155  {
156  if (index_ >= SIZE) return;
157  switch (status)
158  {
167  if (uint8_t(debug_) & uint8_t(DEBUG::DEBUG_STEPS))
168  {
169  status_[index_] = status;
170  data_[index_++] = data;
171  }
172  break;
173 
174  case i2c::DebugStatus::SEND_OK:
175  if (uint8_t(debug_) & uint8_t(DEBUG::DEBUG_SEND_OK))
176  {
177  status_[index_] = status;
178  data_[index_++] = data;
179  }
180  break;
181 
182  case i2c::DebugStatus::SEND_ERROR:
183  if (uint8_t(debug_) & uint8_t(DEBUG::DEBUG_SEND_ERR))
184  {
185  status_[index_] = status;
186  data_[index_++] = data;
187  }
188  break;
189 
190  case i2c::DebugStatus::RECV_OK:
191  if (uint8_t(debug_) & uint8_t(DEBUG::DEBUG_RECV_OK))
192  {
193  status_[index_] = status;
194  data_[index_++] = data;
195  }
196  break;
197 
199  if (uint8_t(debug_) & uint8_t(DEBUG::DEBUG_RECV_ERR))
200  {
201  status_[index_] = status;
202  data_[index_++] = data;
203  }
204  break;
205  }
206  }
208 
209  private:
210  i2c::DebugStatus status_[SIZE];
211  uint8_t data_[SIZE];
212  uint8_t index_ = 0;
213  DEBUG debug_;
214  };
215 
225  {
226  public:
234  I2CDebugLiveLogger(streams::ostream& out, DEBUG debug = DEBUG::DEBUG_ALL) : out_{out}, debug_{debug} {}
235 
237  void operator()(i2c::DebugStatus status, uint8_t data)
238  {
239  bool display = false;
240  switch (status)
241  {
250  display = (uint8_t(debug_) & uint8_t(DEBUG::DEBUG_STEPS));
251  break;
252 
253  case i2c::DebugStatus::SEND_OK:
254  display = (uint8_t(debug_) & uint8_t(DEBUG::DEBUG_SEND_OK));
255  break;
256 
257  case i2c::DebugStatus::SEND_ERROR:
258  display = (uint8_t(debug_) & uint8_t(DEBUG::DEBUG_SEND_ERR));
259  break;
260 
261  case i2c::DebugStatus::RECV_OK:
262  display = (uint8_t(debug_) & uint8_t(DEBUG::DEBUG_RECV_OK));
263  break;
264 
266  display = (uint8_t(debug_) & uint8_t(DEBUG::DEBUG_RECV_ERR));
267  break;
268  }
269  if (display)
270  {
271  // Show data only if relevant
272  switch (status)
273  {
280  case i2c::DebugStatus::SEND_ERROR:
281  case i2c::DebugStatus::SEND_OK:
282  out_ << status << streams::flush;
283  break;
284 
285  default:
286  out_ << status << streams::hex << data << ' ' << streams::flush;
287  }
288  }
289  }
291 
292  private:
293  streams::ostream& out_;
294  DEBUG debug_;
295  };
296 
308  template<uint8_t SIZE_STATUS, uint8_t SIZE_DEBUG>
310  public i2c::status::I2CStatusRecorder<SIZE_STATUS>, public I2CDebugRecorder<SIZE_DEBUG>
311  {
312  public:
315 
333  : i2c::status::I2CStatusRecorder<SIZE_STATUS>{trace}, I2CDebugRecorder<SIZE_DEBUG>{debug} {}
334 
339  void reset()
340  {
343  }
344 
352  void trace(streams::ostream& out, bool hex_status = true)
353  {
356  }
357  };
358 
367  {
368  public:
369  using I2CDebugLiveLogger::operator();
370  using i2c::status::I2CStatusLiveLogger::operator();
371 
387  DEBUG debug = DEBUG::DEBUG_ALL,
388  bool hex_status = true)
389  : i2c::status::I2CStatusLiveLogger{out, trace, hex_status}, I2CDebugLiveLogger{out, debug} {}
390  };
391 }
392 
393 #endif /* I2C_DEBUG_HH */
394 
i2c::debug::I2CDebugLiveLogger
Class tracing I2C debug notifications live to out.
Definition: i2c_debug.h:225
streams::ostream
Output stream wrapper to provide formatted output API, a la C++.
Definition: streams.h:61
streams.h
C++-like std::iostream facilities.
i2c::DebugStatus::SLAW
@ SLAW
A slave address has just been sent for writing.
i2c::debug::I2CDebugRecorder::reset
void reset()
Clear all recorded notifications.
Definition: i2c_debug.h:115
i2c_handler_common.h
Common I2C Manager API.
i2c::debug::DEBUG
DEBUG
Indicate what in I2C protocol shall be debugged.
Definition: i2c_debug.h:55
i2c::debug::I2CDebugRecorder
Class recording I2C debug notifications for later output.
Definition: i2c_debug.h:93
i2c::status::I2CStatusRecorder::trace
void trace(streams::ostream &out, bool hex_status=true)
Output all recorded I2C status notifications to out then clear all records.
Definition: i2c_status.h:95
i2c::DebugStatus
DebugStatus
List of debug states that are reported by the I2C Manager in debug mode.
Definition: i2c_handler_common.h:44
streams::endl
void endl(FSTREAM &stream)
Manipulator for an output stream, which will insert a new-line character and flush the stream buffer.
Definition: streams.h:722
i2c::DebugStatus::STOP
@ STOP
A stop condition has just been sent.
i2c::DebugStatus::REPEAT_START
@ REPEAT_START
A repeat start condition has just been sent.
i2c::DebugStatus::START
@ START
A start condition has just been sent.
timer::operator|
constexpr TimerInterrupt operator|(TimerInterrupt i1, TimerInterrupt i2)
Combine 2 timer interrupts for use with Timer.set_interrupts().
Definition: timer.h:254
i2c::status::STATUS::TRACE_ERROR
@ TRACE_ERROR
Trace only status that differ (between expected and actual).
streams::hex
void hex(FSTREAM &stream)
Manipulator for an output or input stream, which will set the base, used to represent (output) or int...
Definition: ios.h:774
i2c::DebugStatus::SLAR
@ SLAR
A slave address has just been sent for reading.
i2c::debug::I2CDebugStatusLiveLogger::I2CDebugStatusLiveLogger
I2CDebugStatusLiveLogger(streams::ostream &out, i2c::status::STATUS trace=i2c::status::STATUS::TRACE_ALL, DEBUG debug=DEBUG::DEBUG_ALL, bool hex_status=true)
Create an I2CDebugLiveLogger that can trace live I2C notifications determined by debug and trace list...
Definition: i2c_debug.h:385
i2c::status::I2CStatusRecorder
Class recording I2C status notifications for later output.
Definition: i2c_status.h:61
i2c::debug::I2CDebugStatusRecorder
Class recording I2C debug and status notifications for later output.
Definition: i2c_debug.h:311
i2c::debug::I2CDebugRecorder::trace
void trace(streams::ostream &out)
Output all recorded I2C notifications to out then clear all records.
Definition: i2c_debug.h:125
i2c::debug::I2CDebugLiveLogger::I2CDebugLiveLogger
I2CDebugLiveLogger(streams::ostream &out, DEBUG debug=DEBUG::DEBUG_ALL)
Create an I2CDebugLiveLogger that can trace live I2C notifications determined by debug list.
Definition: i2c_debug.h:234
i2c::debug::DEBUG::DEBUG_STEPS
@ DEBUG_STEPS
Debug all individual steps of I2C protocol:
i2c::debug::I2CDebugStatusRecorder::trace
void trace(streams::ostream &out, bool hex_status=true)
Output all recorded I2C notifications to out then clear all records.
Definition: i2c_debug.h:352
i2c::debug::I2CDebugStatusLiveLogger
Class tracing I2C status and debug notifications live to out.
Definition: i2c_debug.h:367
i2c::status::I2CStatusRecorder::reset
void reset()
Clear all recorded notifications.
Definition: i2c_status.h:83
i2c::DebugStatus::RECV
@ RECV
A byte is being received from the slave.
i2c::status::I2CStatusRecorder< SIZE_STATUS >::I2CStatusRecorder
I2CStatusRecorder(STATUS trace=STATUS::TRACE_ALL)
Create an I2CStatusRecorder that can record I2C status notifications determined by trace.
Definition: i2c_status.h:77
i2c::DebugStatus::RECV_LAST
@ RECV_LAST
The last byte is being received from the slave.
i2c_status.h
I2C status hook utilities.
i2c
Define API to define and manage I2C devices.
Definition: i2c.cpp:18
i2c::status::I2CStatusLiveLogger::I2CStatusLiveLogger
I2CStatusLiveLogger(streams::ostream &out, STATUS trace=STATUS::TRACE_ALL, bool hex_status=true)
Create an I2CStatusLiveLogger that can trace live I2C notifications determined by trace.
Definition: i2c_status.h:147
i2c::debug
Defines API to ease I2C devices debugging.
Definition: i2c_debug.cpp:18
i2c::status::STATUS
STATUS
Indicate when status should be traced.
Definition: i2c_status.h:47
F
#define F(ptr)
Force string constant to be stored as flash storage.
Definition: flash.h:118
i2c::status::I2CStatusLiveLogger
Class tracing I2C status notifications live to out.
Definition: i2c_status.h:136
i2c::DebugStatus::SEND
@ SEND
A byte has just be sent to the slave.
i2c::debug::I2CDebugStatusRecorder::I2CDebugStatusRecorder
I2CDebugStatusRecorder(i2c::status::STATUS trace=i2c::status::STATUS::TRACE_ALL, DEBUG debug=DEBUG::DEBUG_ALL)
Create an I2CDebugStatusRecorder that can record I2C notifications determined by debug list.
Definition: i2c_debug.h:331
streams::flush
void flush(FSTREAM &stream)
Manipulator for an output stream, which will flush the stream buffer.
Definition: streams.h:713
flash.h
Flash memory utilities.
i2c::debug::I2CDebugStatusRecorder::reset
void reset()
Clear all recorded notifications.
Definition: i2c_debug.h:339
i2c::debug::I2CDebugRecorder::I2CDebugRecorder
I2CDebugRecorder(DEBUG debug=DEBUG::DEBUG_ALL)
Create an I2CDebugRecorder that can record I2C notifications determined by debug list.
Definition: i2c_debug.h:109