#pragma once #include #include #include #include "pico/time.h" struct log_entry { uint32_t timestamp_us; std::string message; }; class log_iterator { const log_entry* data; uint16_t base; uint16_t cap; uint16_t pos; public: log_iterator(const log_entry* d, uint16_t b, uint16_t c, uint16_t p) : data(d), base(b), cap(c), pos(p) {} const log_entry& operator*() const { return data[(base + pos) % cap]; } log_iterator& operator++() { ++pos; return *this; } bool operator!=(const log_iterator& o) const { return pos != o.pos; } }; class log_view { const log_entry* data; uint16_t base; uint16_t cap; uint16_t count; public: log_view(const log_entry* d, uint16_t b, uint16_t c, uint16_t n) : data(d), base(b), cap(c), count(n) {} log_iterator begin() const { return {data, base, cap, 0}; } log_iterator end() const { return {data, base, cap, count}; } }; log_view log_entries(); void dlog(std::string_view msg); __attribute__((format(printf, 1, 2))) void dlogf(const char* fmt, ...); template inline void dlog_if_slow(std::string_view label, uint32_t threshold_us, F&& fn) { uint32_t t0 = time_us_32(); fn(); uint32_t elapsed = time_us_32() - t0; if (elapsed > threshold_us) { dlogf("%.*s %luus", static_cast(label.size()), label.data(), static_cast(elapsed)); } }