STAR
Cal STAR — firmware, DAQ server, and engine design
Loading...
Searching...
No Matches
hotfire_log.h
Go to the documentation of this file.
1#ifndef HOTFIRE_LOG_H
2#define HOTFIRE_LOG_H
3
4#include <Arduino.h>
5
6// ─────────────────────────────────────────────────────────────────────────────
7// Two-tier serial logging + optional server streaming (shared by all hotfire
8// boards + OTA).
9//
10// Tier 1 HF_LOG* — high-value, low-rate: boot/identity, state
11// transitions,
12// config/command summaries, self-test verdicts, OTA
13// lifecycle, errors/warnings.
14// Tier 2 HF_VERBOSE* — high-rate/debug detail: per-packet "Sent:" lines,
15// per-sample dumps, raw hex, repeating debug, field
16// dumps.
17//
18// Each macro fans out to two sinks, each independently gated:
19// • USB serial — Tier 1 always; Tier 2 only when g_verbose.
20// • Network buffer (g_logbuf) — Tier 1 when g_log_stream_level >= 1;
21// Tier 2 when g_log_stream_level >= 2.
22// A ~1 Hz flush (in each board's loop) sends the buffer to the server as a
23// LOGS packet (type 15).
24//
25// Both gates come from the config packet's `enable_serial_printing` byte
26// (mode):
27// 0: USB Tier1 stream off
28// 1: USB Tier1+Tier2 stream off
29// 2: USB Tier1 stream Tier1
30// 3: USB Tier1+Tier2 stream Tier1+Tier2
31// => g_verbose = (mode & 1); g_log_stream_level = (mode >= 2) ? (mode - 1) :
32// 0;
33//
34// Each board defines `bool g_verbose = true;` once in its main .cpp. g_logbuf
35// and g_log_stream_level are inline (header-defined) — no per-board
36// boilerplate.
37// ─────────────────────────────────────────────────────────────────────────────
38
39extern bool g_verbose;
40
41#ifndef LOG_BUF_SIZE
42#define LOG_BUF_SIZE \
43 1024 // capped to one packet: a 1 Hz flush is always one UDP datagram
44#endif
45
46// Fixed-size log accumulator. Being a Print subclass, g_logbuf.print(x) accepts
47// every type the macros use (strings, ints, IPAddress, "..., HEX"), just like
48// Serial. Overflow drops the excess and raises the TRUNCATED flag.
49class LogBuffer : public Print {
50public:
51 size_t write(uint8_t c) override {
52 if (len_ < LOG_BUF_SIZE) {
53 buf_[len_++] = static_cast<char>(c);
54 return 1;
55 }
56 truncated_ = true;
57 return 0;
58 }
59 size_t write(const uint8_t* data, size_t size) override {
60 size_t n = 0;
61 while (n < size && len_ < LOG_BUF_SIZE)
62 buf_[len_++] = static_cast<char>(data[n++]);
63 if (n < size)
64 truncated_ = true;
65 return n;
66 }
67 const uint8_t* data() const {
68 return reinterpret_cast<const uint8_t*>(buf_);
69 }
70 uint16_t length() const {
71 return static_cast<uint16_t>(len_);
72 }
73 bool empty() const {
74 return len_ == 0;
75 }
76 bool nearFull() const {
77 return len_ >= (LOG_BUF_SIZE * 4) / 5;
78 } // 80%
79 uint8_t flags() const {
80 return truncated_ ? 0x01 : 0x00;
81 } // bit0 = TRUNCATED
82 void clear() {
83 len_ = 0;
84 truncated_ = false;
85 }
86
87private:
89 size_t len_ = 0;
90 bool truncated_ = false;
91};
92
94inline uint8_t g_log_stream_level =
95 1; // default: stream Tier 1 once Ethernet is up
96
97// Variadic so they accept both print(x) and print(x, HEX).
98// Tier 1 — USB always; stream when level >= 1.
99#define HF_LOG(...) \
100 do { \
101 Serial.print(__VA_ARGS__); \
102 if (g_log_stream_level >= 1) \
103 g_logbuf.print(__VA_ARGS__); \
104 } while (0)
105#define HF_LOGLN(...) \
106 do { \
107 Serial.println(__VA_ARGS__); \
108 if (g_log_stream_level >= 1) \
109 g_logbuf.println(__VA_ARGS__); \
110 } while (0)
111#define HF_LOGLN_() \
112 do { \
113 Serial.println(); \
114 if (g_log_stream_level >= 1) \
115 g_logbuf.println(); \
116 } while (0)
117#define HF_LOGF(...) \
118 do { \
119 Serial.printf(__VA_ARGS__); \
120 if (g_log_stream_level >= 1) \
121 g_logbuf.printf(__VA_ARGS__); \
122 } while (0)
123
124// Tier 2 — USB only when g_verbose; stream when level >= 2.
125#define HF_VERBOSE(...) \
126 do { \
127 if (g_verbose) \
128 Serial.print(__VA_ARGS__); \
129 if (g_log_stream_level >= 2) \
130 g_logbuf.print(__VA_ARGS__); \
131 } while (0)
132#define HF_VERBOSELN(...) \
133 do { \
134 if (g_verbose) \
135 Serial.println(__VA_ARGS__); \
136 if (g_log_stream_level >= 2) \
137 g_logbuf.println(__VA_ARGS__); \
138 } while (0)
139#define HF_VERBOSELN_() \
140 do { \
141 if (g_verbose) \
142 Serial.println(); \
143 if (g_log_stream_level >= 2) \
144 g_logbuf.println(); \
145 } while (0)
146#define HF_VERBOSEF(...) \
147 do { \
148 if (g_verbose) \
149 Serial.printf(__VA_ARGS__); \
150 if (g_log_stream_level >= 2) \
151 g_logbuf.printf(__VA_ARGS__); \
152 } while (0)
153
154#endif // HOTFIRE_LOG_H
uint16_t length() const
Definition hotfire_log.h:70
size_t len_
Definition hotfire_log.h:89
uint8_t flags() const
Definition hotfire_log.h:79
size_t write(const uint8_t *data, size_t size) override
Definition hotfire_log.h:59
const uint8_t * data() const
Definition hotfire_log.h:67
bool empty() const
Definition hotfire_log.h:73
size_t write(uint8_t c) override
Definition hotfire_log.h:51
void clear()
Definition hotfire_log.h:82
bool truncated_
Definition hotfire_log.h:90
bool nearFull() const
Definition hotfire_log.h:76
char buf_[LOG_BUF_SIZE]
Definition hotfire_log.h:88
bool g_verbose
Definition main.cpp:65
LogBuffer g_logbuf
Definition hotfire_log.h:93
uint8_t g_log_stream_level
Definition hotfire_log.h:94
#define LOG_BUF_SIZE
Definition hotfire_log.h:42
*brief user defined string literal for JSON values *sa std::size_t n
Definition json.hpp:24474