66enum class LogLevel : uint8_t
75template<CcfConfig Config>
78 using RxFrame =
CircularBuffer<uint8_t, Config.rxBufSize, Config.maxPktSize>::Frame;
80 using TxFrame =
CircularBuffer<uint8_t, Config.txBufSize, Config.maxPktSize>::Frame;
95 const uint8_t value = decoder.get(
byte);
96 const bool do_output = decoder.feed(
byte);
101 if (!rxBuf.dropping())
107 rxBuf.reset_dropped();
113 rxBuf.push_back(value);
127 return txBuf.get_frame(frame);
140 template<
typename Rpc>
144 std::optional<RxFrame> frame;
145 while (rxBuf.get_frame(frame))
149 for (
auto c : *frame)
153 std::span span{pktBuf, len};
160 std::ranges::copy(
"Bad RPC!\n", std::back_inserter(txBuf));
161 txBuf.push_back(
static_cast<uint8_t
>(0));
167 uint8_t channel = span[0];
176 std::ranges::copy(
"Corrupted request\n", std::back_inserter(txBuf));
177 txBuf.push_back(
static_cast<uint8_t
>(0));
185 span.size() - Fnv1a::size -
sizeof(channel));
187 uint8_t seqNo = span[0];
188 uint8_t function = span[1];
189 span = span.subspan(
sizeof(seqNo) +
sizeof(function));
192 auto header =
sizeof(channel) +
sizeof(seqNo) +
sizeof(function);
193 auto ret = std::span<uint8_t>(
194 pktBuf + header,
sizeof(pktBuf) - header - Fnv1a::size);
195 if (!rpc.call(function, span, ret))
200 std::ranges::copy(
"RPC failed\n", std::back_inserter(txBuf));
201 txBuf.push_back(
static_cast<uint8_t
>(0));
207 pktBuf[1] = seqNo + 1;
208 pktBuf[2] = function;
209 auto respLen =
static_cast<size_t>(ret.data() - pktBuf);
210 std::span resp{pktBuf +
sizeof(channel), respLen -
sizeof(channel)};
211 output = output ||
send(Channels::Rpc, resp);
230 const size_t toSend = data.size() +
sizeof(channel) + Fnv1a::size;
231 if (toSend >
sizeof(pktBuf))
233 debugf(
"Data for send too large\n");
236 std::span resp{pktBuf, toSend};
239 if (&data[0] != &resp[1])
241 memmove(&resp[1], data.data(), data.size_bytes());
243 uint8_t chan =
static_cast<uint8_t
>(channel);
250 txBuf.push_back(
static_cast<uint8_t
>(0));
251 if (txBuf.dropping())
253 txBuf.reset_dropped();
285#if defined(DEFERRED_FORMATTING)
286 template <
typename... Args>
288 std::span<uint8_t> & span,
291 std::string_view fmt,
295 std::span<uint8_t> & span,
303 const auto ret =
vLogToBuffer(span, level, module, fmt, args);
309 std::span<uint8_t> & span,
316 if (module > (1 << 5) - 1)
320 uint8_t initialByte = (
static_cast<uint8_t
>(level) << 5) | module;
321 span[0] = initialByte;
323 const auto start = span.begin() + 2;
324#if defined(DEFERRED_FORMATTING)
325 const auto written = std::distance(start, std::ranges::copy(fmt, start).out);
326 auto rest = span.subspan(2 + written);
328 const auto end = rest.begin();
330 int written = vsnprintf(
331 reinterpret_cast<char *
>(&*start),
332 std::distance(start, span.end()),
336 bool ok = 0 < written &&
static_cast<size_t>(written) < span.size();
337 const auto end = start + written;
344 size_t total = std::distance(span.begin(), end);
345 span = span.subspan(total);
363#if defined(DEFERRED_FORMATTING)
364 template <
typename... Args>
365 std::optional<size_t>
log(
368 std::string_view fmt,
371 std::optional<size_t>
log(
378 std::span<uint8_t> span{pktBuf};
379#if defined(DEFERRED_FORMATTING)
380 const auto formatted =
logToBuffer(span, level, module, fmt, std::forward<Args>(args)...);
384 const auto formatted =
vLogToBuffer(span, level, module, fmt, args);
389 std::span<uint8_t> toSend{pktBuf, *formatted};
390 if (
send(Channels::Log, toSend))
400 CircularBuffer<uint8_t, Config.txBufSize, Config.maxPktSize> txBuf;
401 CircularBuffer<uint8_t, Config.rxBufSize, Config.maxPktSize> rxBuf;
403 uint8_t pktBuf[Config.maxPktSize];
Encoding for structured data (numbers, strings, bytes, arrays and maps). Also supports custom tags.
Channels
Definition ccf.hpp:57
@ Trace
Definition ccf.hpp:61
Buffer for queuing received bytes.
bool receiveCharacter(uint8_t byte)
Push RX'ed character to RX queue. Safe to call from interrupt context.
Definition ccf.hpp:92
bool poll(const Rpc &rpc)
Process incoming packets to dispatch e.g. RPC.
Definition ccf.hpp:141
std::optional< size_t > vLogToBuffer(std::span< uint8_t > &span, LogLevel level, uint8_t module, const char *fmt, va_list args)
Same as logToBuffer but taking va_list instead of ... varargs.
Definition ccf.hpp:308
bool charactersToSend(std::optional< TxFrame > &frame)
Get TX queue size. Safe to call from interrupt context.
Definition ccf.hpp:125
bool send(Channels channel, std::span< uint8_t > &data)
Send data over a channel.
Definition ccf.hpp:228
std::optional< size_t > logToBuffer(std::span< uint8_t > &span, LogLevel level, uint8_t module, const char *fmt,...)
Logs to a buffer, returning logged size. Threadsafe because it doesn't send the message,...
Definition ccf.hpp:294
std::optional< size_t > log(LogLevel level, uint8_t module, const char *fmt,...)
Sends a logs message.
Definition ccf.hpp:371
Definition circular_buffer.hpp:82
Decodes data as a state-machine.
Definition cobs.hpp:108
Simple framing (marking packet start/stop) with self-synchronisation.
Simple non-cryptographic hash with decent performance.
constexpr void putAtEnd(std::span< uint8_t, Size > span, uint32_t hash=initialHash)
Definition fnv1a.hpp:65
constexpr bool checkAtEnd(std::span< uint8_t, Size > span, uint32_t hash=initialHash)
Definition fnv1a.hpp:82
#define debugf(...)
Definition ndebug.hpp:23
#define END
Terminator of log message at the end.
Definition ndebug.hpp:50
#define LOGLEVEL_ARGS
Definition ndebug.hpp:28
#define DEBUG
Debug levels at the start of debugf.
Definition ndebug.hpp:33
Parametrized CBOR interface.
Definition cbor.hpp:400