Sound Byte Libs 0.5.1-121-g3358a44
C++ firmware library for audio applications on 32-bit ARM Cortex-M processors
Loading...
Searching...
No Matches
banner.hpp
Go to the documentation of this file.
1/**
2 * @file banner.hpp
3 * @brief Boot banner formatter
4 *
5 * Formats a startup banner with app name, build info, MCU metadata,
6 * and audio configuration. Uses __has_include for optional headers
7 * so it works in both firmware and unit test builds.
8 *
9 * Usage:
10 * #include <sbl/common/log/banner.hpp>
11 *
12 * char buf[384];
13 * int len = sbl::log::format_banner(buf, sizeof(buf),
14 * "hello-instrument", 48000, 48);
15 * SBL_LOG_OUTPUT::write(buf);
16 *
17 * Gated behind SBL_BOOT_BANNER (default: 1). Set to 0 to disable.
18 */
19#ifndef SBL_COMMON_LOG_BANNER_HPP_
20#define SBL_COMMON_LOG_BANNER_HPP_
21
22#include <cstddef>
23#include <cstdint>
24
25#ifndef SBL_BOOT_BANNER
26#define SBL_BOOT_BANNER 1
27#endif
28
29// Optional constexpr-only headers — silently omitted when absent
30#if __has_include(<sbl/hw/config/mcu.hpp>)
31#include <sbl/hw/config/mcu.hpp>
32#define SBL_BANNER_HAS_MCU 1
33#else
34#define SBL_BANNER_HAS_MCU 0
35#endif
36
37#if __has_include(<sbl/hw/config/system.hpp>)
38#include <sbl/hw/config/system.hpp>
39#define SBL_BANNER_HAS_SYSTEM 1
40#else
41#define SBL_BANNER_HAS_SYSTEM 0
42#endif
43
44#if __has_include(<sbl/version.hpp>)
45#include <sbl/version.hpp>
46#define SBL_BANNER_HAS_VERSION 1
47#else
48#define SBL_BANNER_HAS_VERSION 0
49#endif
50
51namespace sbl::log {
52
53namespace detail {
54
55// Minimal string append helpers — no printf dependency
56inline int banner_append(char* buf, size_t size, int pos, const char* str) {
57 while (*str && static_cast<size_t>(pos) < size - 1) {
58 buf[pos++] = *str++;
59 }
60 return pos;
61}
62
63inline int banner_append_uint(char* buf, size_t size, int pos, uint32_t val) {
64 char tmp[12];
65 int len = 0;
66 if (val == 0) {
67 tmp[len++] = '0';
68 } else {
69 char rev[12];
70 int rlen = 0;
71 while (val > 0) {
72 rev[rlen++] = static_cast<char>('0' + (val % 10));
73 val /= 10;
74 }
75 while (rlen > 0) tmp[len++] = rev[--rlen];
76 }
77 for (int i = 0; i < len && static_cast<size_t>(pos) < size - 1; ++i) {
78 buf[pos++] = tmp[i];
79 }
80 return pos;
81}
82
83} // namespace detail
84
85/**
86 * @brief Format a boot banner into a buffer
87 *
88 * @param buf Output buffer
89 * @param size Buffer size (recommend >= 384)
90 * @param app_name Application name (e.g., "hello-instrument")
91 * @param sample_rate Audio sample rate in Hz (e.g., 48000)
92 * @param block_size Audio block size in frames (e.g., 48)
93 * @return Number of characters written (excluding null terminator)
94 */
95inline int format_banner(char* buf, size_t size, const char* app_name,
96 uint32_t sample_rate, uint16_t block_size) {
97#if !SBL_BOOT_BANNER
98 (void)app_name; (void)sample_rate; (void)block_size;
99 if (size > 0) buf[0] = '\0';
100 return 0;
101#else
102 if (size == 0 || buf == nullptr) return 0;
103
104 int p = 0;
105 const char* sep = "======================================\r\n";
106
107 p = detail::banner_append(buf, size, p, sep);
108
109 // App name + version
110 p = detail::banner_append(buf, size, p, " ");
111 p = detail::banner_append(buf, size, p, app_name);
112#if SBL_BANNER_HAS_VERSION
113 p = detail::banner_append(buf, size, p, " (sbl ");
114 p = detail::banner_append(buf, size, p, sbl::version::string);
115 p = detail::banner_append(buf, size, p, ")");
116#endif
117 p = detail::banner_append(buf, size, p, "\r\n");
118
119 // Build date/time
120 p = detail::banner_append(buf, size, p, " Built: ");
121 p = detail::banner_append(buf, size, p, __DATE__);
122 p = detail::banner_append(buf, size, p, " ");
123 p = detail::banner_append(buf, size, p, __TIME__);
124 p = detail::banner_append(buf, size, p, "\r\n");
125
126 // MCU info
127#if SBL_BANNER_HAS_MCU
128 p = detail::banner_append(buf, size, p, " MCU: ");
129 p = detail::banner_append(buf, size, p, sbl::hw::mcu::name);
130#if SBL_BANNER_HAS_SYSTEM
131 p = detail::banner_append(buf, size, p, " @ ");
132 p = detail::banner_append_uint(buf, size, p, sbl::hw::system::sysclk_mhz);
133 p = detail::banner_append(buf, size, p, " MHz");
134#endif
135 p = detail::banner_append(buf, size, p, "\r\n");
136#endif
137
138 // Audio config
139 p = detail::banner_append(buf, size, p, " Audio: ");
140 p = detail::banner_append_uint(buf, size, p, sample_rate);
141 p = detail::banner_append(buf, size, p, " Hz / ");
142 p = detail::banner_append_uint(buf, size, p, block_size);
143 p = detail::banner_append(buf, size, p, " frames\r\n");
144
145 // Profiling status
146#ifdef SBL_PROFILING_ENABLED
147 p = detail::banner_append(buf, size, p, " Profiling: enabled\r\n");
148#endif
149
150 // Git info
151#if SBL_BANNER_HAS_VERSION
152 p = detail::banner_append(buf, size, p, " Git: ");
153 p = detail::banner_append(buf, size, p, sbl::version::git_hash);
154 if (sbl::version::git_dirty) {
155 p = detail::banner_append(buf, size, p, "-dirty");
156 }
157 p = detail::banner_append(buf, size, p, "\r\n");
158#endif
159
160 p = detail::banner_append(buf, size, p, sep);
161
162 buf[static_cast<size_t>(p) < size ? p : size - 1] = '\0';
163 return p;
164#endif // SBL_BOOT_BANNER
165}
166
167} // namespace sbl::log
168
169#endif // SBL_COMMON_LOG_BANNER_HPP_
int banner_append(char *buf, size_t size, int pos, const char *str)
Definition banner.hpp:56
int banner_append_uint(char *buf, size_t size, int pos, uint32_t val)
Definition banner.hpp:63
Logging.
Definition banner.hpp:51
int format_banner(char *buf, size_t size, const char *app_name, uint32_t sample_rate, uint16_t block_size)
Format a boot banner into a buffer.
Definition banner.hpp:95