Sound Byte Libs 29c5ff3
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/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#pragma once
20
21#include <cstddef>
22#include <cstdint>
23
24#ifndef SBL_BOOT_BANNER
25#define SBL_BOOT_BANNER 1
26#endif
27
28// Optional constexpr-only headers — silently omitted when absent
29#if __has_include(<sbl/hw/config/mcu.hpp>)
30#include <sbl/hw/config/mcu.hpp>
31#define SBL_BANNER_HAS_MCU 1
32#else
33#define SBL_BANNER_HAS_MCU 0
34#endif
35
36#if __has_include(<sbl/hw/config/system.hpp>)
37#include <sbl/hw/config/system.hpp>
38#define SBL_BANNER_HAS_SYSTEM 1
39#else
40#define SBL_BANNER_HAS_SYSTEM 0
41#endif
42
43#if __has_include(<sbl/version.hpp>)
44#include <sbl/version.hpp>
45#define SBL_BANNER_HAS_VERSION 1
46#else
47#define SBL_BANNER_HAS_VERSION 0
48#endif
49
50namespace sbl::log {
51
52namespace detail {
53
54// Minimal string append helpers — no printf dependency
55inline int banner_append(char* buf, size_t size, int pos, const char* str) {
56 while (*str && static_cast<size_t>(pos) < size - 1) {
57 buf[pos++] = *str++;
58 }
59 return pos;
60}
61
62inline int banner_append_uint(char* buf, size_t size, int pos, uint32_t val) {
63 char tmp[12];
64 int len = 0;
65 if (val == 0) {
66 tmp[len++] = '0';
67 } else {
68 char rev[12];
69 int rlen = 0;
70 while (val > 0) {
71 rev[rlen++] = static_cast<char>('0' + (val % 10));
72 val /= 10;
73 }
74 while (rlen > 0) tmp[len++] = rev[--rlen];
75 }
76 for (int i = 0; i < len && static_cast<size_t>(pos) < size - 1; ++i) {
77 buf[pos++] = tmp[i];
78 }
79 return pos;
80}
81
82} // namespace detail
83
84/**
85 * @brief Format a boot banner into a buffer
86 *
87 * @param buf Output buffer
88 * @param size Buffer size (recommend >= 384)
89 * @param app_name Application name (e.g., "hello-instrument")
90 * @param sample_rate Audio sample rate in Hz (e.g., 48000)
91 * @param block_size Audio block size in frames (e.g., 48)
92 * @return Number of characters written (excluding null terminator)
93 */
94inline int format_banner(char* buf, size_t size, const char* app_name,
95 uint32_t sample_rate, uint16_t block_size) {
96#if !SBL_BOOT_BANNER
97 (void)app_name; (void)sample_rate; (void)block_size;
98 if (size > 0) buf[0] = '\0';
99 return 0;
100#else
101 if (size == 0 || buf == nullptr) return 0;
102
103 int p = 0;
104 const char* sep = "======================================\r\n";
105
106 p = detail::banner_append(buf, size, p, sep);
107
108 // App name + version
109 p = detail::banner_append(buf, size, p, " ");
110 p = detail::banner_append(buf, size, p, app_name);
111#if SBL_BANNER_HAS_VERSION
112 p = detail::banner_append(buf, size, p, " (sbl ");
113 p = detail::banner_append(buf, size, p, sbl::version::string);
114 p = detail::banner_append(buf, size, p, ")");
115#endif
116 p = detail::banner_append(buf, size, p, "\r\n");
117
118 // Build date/time
119 p = detail::banner_append(buf, size, p, " Built: ");
120 p = detail::banner_append(buf, size, p, __DATE__);
121 p = detail::banner_append(buf, size, p, " ");
122 p = detail::banner_append(buf, size, p, __TIME__);
123 p = detail::banner_append(buf, size, p, "\r\n");
124
125 // MCU info
126#if SBL_BANNER_HAS_MCU
127 p = detail::banner_append(buf, size, p, " MCU: ");
128 p = detail::banner_append(buf, size, p, sbl::hw::mcu::name);
129#if SBL_BANNER_HAS_SYSTEM
130 p = detail::banner_append(buf, size, p, " @ ");
131 p = detail::banner_append_uint(buf, size, p, sbl::hw::system::sysclk_mhz);
132 p = detail::banner_append(buf, size, p, " MHz");
133#endif
134 p = detail::banner_append(buf, size, p, "\r\n");
135#endif
136
137 // Audio config
138 p = detail::banner_append(buf, size, p, " Audio: ");
139 p = detail::banner_append_uint(buf, size, p, sample_rate);
140 p = detail::banner_append(buf, size, p, " Hz / ");
141 p = detail::banner_append_uint(buf, size, p, block_size);
142 p = detail::banner_append(buf, size, p, " frames\r\n");
143
144 // Profiling status
145#ifdef SBL_PROFILING_ENABLED
146 p = detail::banner_append(buf, size, p, " Profiling: enabled\r\n");
147#endif
148
149 // Git info
150#if SBL_BANNER_HAS_VERSION
151 p = detail::banner_append(buf, size, p, " Git: ");
152 p = detail::banner_append(buf, size, p, sbl::version::git_hash);
153 if (sbl::version::git_dirty) {
154 p = detail::banner_append(buf, size, p, "-dirty");
155 }
156 p = detail::banner_append(buf, size, p, "\r\n");
157#endif
158
159 p = detail::banner_append(buf, size, p, sep);
160
161 buf[static_cast<size_t>(p) < size ? p : size - 1] = '\0';
162 return p;
163#endif // SBL_BOOT_BANNER
164}
165
166} // namespace sbl::log
int banner_append(char *buf, size_t size, int pos, const char *str)
Definition banner.hpp:55
int banner_append_uint(char *buf, size_t size, int pos, uint32_t val)
Definition banner.hpp:62
Lightweight logging system.
Definition banner.hpp:50
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:94