ti_lp55231/debug.rs
1/// Macros for low level debugging when developing against I2C devices.
2
3/// Create a debugging scope on the provided context.
4///
5/// A debugging scope causes any subsequent [`text!`] or [`byte!`] calls to be
6/// printed with additional padding and automatically ends once the current code
7/// scope ends.
8///
9/// Scopes can be nested, where the inner scope will further pad any output.
10///
11/// The provided context (`ctx`) can be any struct that has two fields
12/// accessible to these macros:
13/// 1. `debug_enabled: bool`
14/// 2. `debug_depth: Rc<Cell<usize>>`
15///
16/// Example:
17/// ```
18/// debug::scope!(ctx, "entering scope 1");
19/// debug::text!(ctx, "message 1")
20/// debug::scope!(ctx, "entering scope 2");
21/// debug::text!(ctx, "message 2")
22/// {
23/// debug::scope!(ctx, "entering scope 3");
24/// debug::text!(ctx, "message 3")
25/// } // scope 3 ends
26/// debug::text!("message 4")
27/// ```
28/// Prints:
29/// ```text
30/// entering scope 1
31/// message 1
32/// entering scope 2
33/// message 2
34/// entering scope 3
35/// message 3
36/// message 4
37/// ```
38///
39/// The nesting ability of scopes becomes really useful when composing I2C
40/// operations; example:
41/// ```
42/// fn start() {
43/// debug::scope!("start()");
44/// let byte = 1;
45/// debug::byte!(byte, "write start byte", byte)
46/// device.write(byte);
47/// }
48///
49/// fn stop() {
50/// debug::scope!("stop()");
51/// let byte = 0;
52/// debug::byte!(byte, "write stop byte", byte)
53/// device.write(byte);
54/// }
55///
56/// fn restart() {
57/// debug::scope!("restart()");
58/// stop();
59/// start();
60/// }
61///
62/// restart();
63/// // ...
64/// stop();
65/// ```
66///
67/// Would result in the output:
68/// ```text
69/// restart()
70/// stop()
71/// 00000000 write stop byte
72/// start()
73/// 00000001 write start byte
74/// stop()
75/// 00000000 write stop byte
76/// ```
77#[macro_export]
78macro_rules! scope {
79 ($ctx:ident, $fmt:expr $(, $arg:expr)* $(,)?) => {
80 // _unused is dropped at end of scope where this macro is called, which
81 // decrements debug depth.
82 let _unused = if $ctx.debug_enabled {
83 let mut cur_depth = $ctx.debug_depth.lock().unwrap();
84 let padding = " ".repeat(*cur_depth);
85 println!("{}{} {{", padding, format!($fmt $(, $arg)*));
86 *cur_depth += 1;
87 // lock releases after return
88
89 // debug_depth ArcMutex needs to be cloned since guard() takes ownership
90 // of the arg. Code in block below is executed at the end of the code
91 // scope where the `scope` macro is called.
92 Some(scopeguard::guard($ctx.debug_depth.clone(), |depth| {
93 let mut cur_depth = depth.lock().unwrap();
94 if *cur_depth > 0 {
95 *cur_depth -= 1;
96 }
97 println!("{}}}", " ".repeat(*cur_depth));
98 }))
99 } else {
100 None
101 };
102 };
103}
104pub use scope;
105
106/// Print a formated message at current debug depth.
107///
108/// Example:
109/// ```
110/// debug::text!(ctx, "1. top-level debug text");
111/// debug::scope!(ctx, "2. in-scope");
112/// debug::text!(ctx, "2a. in-scope debug text");
113/// ```
114///
115/// Prints:
116/// ```text
117/// 1. top-level debug text
118/// 2. in-scope
119/// 2a. in-scope debug text
120/// ```
121#[macro_export]
122macro_rules! text {
123 ($ctx:expr, $fmt:expr $(, $arg:expr)* $(,)?) => {
124 if $ctx.debug_enabled {
125 let padding = " ".repeat(*$ctx.debug_depth.lock().unwrap());
126 println!("{}{}", padding, format!($fmt $(, $arg)*));
127 };
128 };
129}
130pub use text;
131
132/// Print the binary representation for the given byte, along with a formatted
133/// description at the current debug depth.
134///
135/// Example:
136/// ```
137/// let value = 0b0010_1010;
138/// debug::byte(value, "is binary for {}", value);
139/// ```
140/// Prints:
141/// ```text
142/// 00101010 is binary for 42
143/// ```
144#[macro_export]
145macro_rules! byte {
146 ($ctx:expr, $value:expr, $($description:tt)*) => {
147 if $ctx.debug_enabled {
148 let value: u8 = $value;
149 let formatted_string = format!($($description)*);
150 debug::text!(
151 $ctx,
152 "{:08b} {}",
153 value,
154 formatted_string,
155 );
156 }
157 };
158}
159pub use byte;