FastArduino v1.10
C++ library to build fast but small Arduino/AVR projects
Loading...
Searching...
No Matches
i2c_debug.h
Go to the documentation of this file.
1// Copyright 2016-2023 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 "i2c_handler_common.h"
26#include "i2c_status.h"
27
28namespace i2c
29{
35 namespace debug
36 {
37 }
38}
39
40namespace i2c::debug
41{
43 // Add utility ostream insert operator for FutureStatus
44 template<typename OSTREAM> OSTREAM& operator<<(OSTREAM& out, i2c::DebugStatus status)
45 {
46 // Conversion lambda for local usage
47 auto convert = [](i2c::DebugStatus s)
48 {
49 switch (s)
50 {
52 return F("ST ");
53
55 return F("RS ");
56
58 return F("AW ");
59
61 return F("AR ");
62
64 return F("S ");
65
67 return F("R ");
68
70 return F("RL ");
71
73 return F("SP ");
74
76 return F("So ");
77
79 return F("Se ");
80
82 return F("Ro ");
83
85 return F("Re ");
86
87 default:
88 return F("");
89 }
90 };
91 return out << convert(status);
92 }
94
101 enum class DEBUG : uint8_t
102 {
114 DEBUG_STEPS = 0x01,
116 DEBUG_SEND_OK = 0x02,
118 DEBUG_SEND_ERR = 0x04,
120 DEBUG_RECV_OK = 0x08,
122 DEBUG_RECV_ERR = 0x10,
124 DEBUG_ALL = 0xFF
125 };
126
128 DEBUG operator|(DEBUG a, DEBUG b);
130
139 template<uint8_t SIZE> class I2CDebugRecorder
140 {
141 public:
156 explicit I2CDebugRecorder(DEBUG debug = DEBUG::DEBUG_ALL) : debug_{debug} {}
157
162 void reset()
163 {
164 index_ = 0;
165 }
166
172 template<typename OSTREAM>
173 void trace(OSTREAM& out)
174 {
175 for (uint8_t i = 0; i < index_; ++i)
176 {
177 const i2c::DebugStatus status = status_[i];
178 switch (status)
179 {
188 out << status;
189 break;
190
191 default:
192 out << status;
194 out << data_[i] << ' ';
195 }
196 }
197 if (index_ >= SIZE)
198 out << F("# OVF #");
199 out << '\n';
200 index_ = 0;
201 }
202
204 void operator()(i2c::DebugStatus status, uint8_t data)
205 {
206 if (index_ >= SIZE) return;
207 switch (status)
208 {
217 if (uint8_t(debug_) & uint8_t(DEBUG::DEBUG_STEPS))
218 {
219 status_[index_] = status;
220 data_[index_++] = data;
221 }
222 break;
223
225 if (uint8_t(debug_) & uint8_t(DEBUG::DEBUG_SEND_OK))
226 {
227 status_[index_] = status;
228 data_[index_++] = data;
229 }
230 break;
231
233 if (uint8_t(debug_) & uint8_t(DEBUG::DEBUG_SEND_ERR))
234 {
235 status_[index_] = status;
236 data_[index_++] = data;
237 }
238 break;
239
241 if (uint8_t(debug_) & uint8_t(DEBUG::DEBUG_RECV_OK))
242 {
243 status_[index_] = status;
244 data_[index_++] = data;
245 }
246 break;
247
249 if (uint8_t(debug_) & uint8_t(DEBUG::DEBUG_RECV_ERR))
250 {
251 status_[index_] = status;
252 data_[index_++] = data;
253 }
254 break;
255 }
256 }
258
259 private:
260 i2c::DebugStatus status_[SIZE];
261 uint8_t data_[SIZE];
262 uint8_t index_ = 0;
263 DEBUG debug_;
264 };
265
274 template<typename OSTREAM>
276 {
277 public:
285 I2CDebugLiveLogger(OSTREAM& out, DEBUG debug = DEBUG::DEBUG_ALL) : out_{out}, debug_{debug} {}
286
288 void operator()(i2c::DebugStatus status, uint8_t data)
289 {
290 bool display = false;
291 switch (status)
292 {
301 display = (uint8_t(debug_) & uint8_t(DEBUG::DEBUG_STEPS));
302 break;
303
305 display = (uint8_t(debug_) & uint8_t(DEBUG::DEBUG_SEND_OK));
306 break;
307
309 display = (uint8_t(debug_) & uint8_t(DEBUG::DEBUG_SEND_ERR));
310 break;
311
313 display = (uint8_t(debug_) & uint8_t(DEBUG::DEBUG_RECV_OK));
314 break;
315
317 display = (uint8_t(debug_) & uint8_t(DEBUG::DEBUG_RECV_ERR));
318 break;
319 }
320 if (display)
321 {
322 // Show data only if relevant
323 switch (status)
324 {
333 out_ << status;
334 break;
335
336 default:
337 out_ << status;
339 out_ << data << ' ';
340 }
341 }
342 }
344
345 private:
346 OSTREAM& out_;
347 DEBUG debug_;
348 };
349
361 template<uint8_t SIZE_STATUS, uint8_t SIZE_DEBUG>
363 public i2c::status::I2CStatusRecorder<SIZE_STATUS>, public I2CDebugRecorder<SIZE_DEBUG>
364 {
365 public:
366 using I2CDebugRecorder<SIZE_DEBUG>::operator();
367 using i2c::status::I2CStatusRecorder<SIZE_STATUS>::operator();
368
386 : i2c::status::I2CStatusRecorder<SIZE_STATUS>{trace}, I2CDebugRecorder<SIZE_DEBUG>{debug} {}
387
392 void reset()
393 {
396 }
397
405 template<typename OSTREAM>
406 void trace(OSTREAM& out, bool hex_status = true)
407 {
410 }
411 };
412
420 template<typename OSTREAM>
422 public i2c::status::I2CStatusLiveLogger<OSTREAM>, public I2CDebugLiveLogger<OSTREAM>
423 {
424 public:
425 using I2CDebugLiveLogger<OSTREAM>::operator();
426 using i2c::status::I2CStatusLiveLogger<OSTREAM>::operator();
427
443 DEBUG debug = DEBUG::DEBUG_ALL,
444 bool hex_status = true)
445 : i2c::status::I2CStatusLiveLogger<OSTREAM>{out, trace, hex_status},
446 I2CDebugLiveLogger<OSTREAM>{out, debug} {}
447 };
448}
449
450#endif /* I2C_DEBUG_HH */
Class tracing I2C debug notifications live to out.
Definition: i2c_debug.h:276
I2CDebugLiveLogger(OSTREAM &out, DEBUG debug=DEBUG::DEBUG_ALL)
Create an I2CDebugLiveLogger that can trace live I2C notifications determined by debug list.
Definition: i2c_debug.h:285
Class recording I2C debug notifications for later output.
Definition: i2c_debug.h:140
void reset()
Clear all recorded notifications.
Definition: i2c_debug.h:162
I2CDebugRecorder(DEBUG debug=DEBUG::DEBUG_ALL)
Create an I2CDebugRecorder that can record I2C notifications determined by debug list.
Definition: i2c_debug.h:156
void trace(OSTREAM &out)
Output all recorded I2C notifications to out then clear all records.
Definition: i2c_debug.h:173
Class tracing I2C status and debug notifications live to out.
Definition: i2c_debug.h:423
I2CDebugStatusLiveLogger(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:441
Class recording I2C debug and status notifications for later output.
Definition: i2c_debug.h:364
void reset()
Clear all recorded notifications.
Definition: i2c_debug.h:392
void trace(OSTREAM &out, bool hex_status=true)
Output all recorded I2C notifications to out then clear all records.
Definition: i2c_debug.h:406
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:384
Class tracing I2C status notifications live to out.
Definition: i2c_status.h:142
I2CStatusLiveLogger(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:153
Class recording I2C status notifications for later output.
Definition: i2c_status.h:61
I2CStatusRecorder(STATUS trace=STATUS::TRACE_ALL)
Create an I2CStatusRecorder that can record I2C status notifications determined by trace.
Definition: i2c_status.h:77
void trace(OSTREAM &out, bool hex_status=true)
Output all recorded I2C status notifications to out then clear all records.
Definition: i2c_status.h:96
void reset()
Clear all recorded notifications.
Definition: i2c_status.h:83
static constexpr fmtflags basefield
Bitmask constant used with setf(fmtflags, fmtflags) when changing the output base format.
Definition: ios.h:227
static constexpr fmtflags hex
Read or write integral values using hexadecimal (0..9,A..F) base format.
Definition: ios.h:218
Flash memory utilities.
#define F(ptr)
Force string constant to be stored as flash storage.
Definition: flash.h:150
Common I2C Manager API.
I2C status hook utilities.
Defines API to ease I2C devices debugging.
Definition: i2c_debug.cpp:18
DEBUG
Indicate what in I2C protocol shall be debugged.
Definition: i2c_debug.h:102
@ DEBUG_SEND_OK
Debug successfully written bytes.
@ DEBUG_RECV_OK
Debug successfully received bytes.
@ DEBUG_RECV_ERR
Debug error during receiving bytes.
@ DEBUG_STEPS
Debug all individual steps of I2C protocol:
@ DEBUG_ALL
Debug everything.
@ DEBUG_SEND_ERR
Debug written bytes not acknowledged by slave.
STATUS
Indicate when status should be traced.
Definition: i2c_status.h:47
@ TRACE_ALL
Trace everything.
Define API to define and manage I2C devices.
Definition: i2c.h:51
DebugStatus
List of debug states that are reported by the I2C Manager in debug mode.
@ SEND_OK
The latest sent byte has been acknowledged by the slave.
@ SEND_ERROR
The latest sent byte has not been acknowledged by the slave.
@ SLAR
A slave address has just been sent for reading.
@ RECV_OK
I2C Manager has acknowledged the latest received byte from the slave.
@ SEND
A byte has just be sent to the slave.
@ STOP
A stop condition has just been sent.
@ REPEAT_START
A repeat start condition has just been sent.
@ RECV_LAST
The last byte is being received from the slave.
@ START
A start condition has just been sent.
@ RECV
A byte is being received from the slave.
@ RECV_ERROR
I2C Manager has not acknowledged the latest received byte from the slave.
@ SLAW
A slave address has just been sent for writing.