From 8abfd9edaeb3f0848f49a7772355116c0d699966 Mon Sep 17 00:00:00 2001 From: Attila Body Date: Sun, 29 Jun 2025 21:54:20 +0200 Subject: [PATCH] Implement all stream interface functions on the console handler --- inc/f4ll/console_handler.h | 23 +++++++- src/console_handler.cpp | 114 ++++++++++++++++++++++++++++++++++++- 2 files changed, 134 insertions(+), 3 deletions(-) diff --git a/inc/f4ll/console_handler.h b/inc/f4ll/console_handler.h index 14e15a6..5f76c90 100644 --- a/inc/f4ll/console_handler.h +++ b/inc/f4ll/console_handler.h @@ -8,6 +8,7 @@ #pragma once #include +#include #include #include @@ -15,7 +16,7 @@ namespace f4ll { -class console_handler : public usart_core, public initialized_singleton +class console_handler : public initialized_singleton, public usart_core, public ioutput_stream { friend class initialized_singleton; @@ -34,6 +35,16 @@ public: iringbuffer &get_rx_buffer() { return m_rx_buffer; } + // ioutput_stream interface implementations + ioutput_stream &operator<<(ioutput_stream::format fmt) override; + ioutput_stream &operator<<(char const *str) override; + ioutput_stream &operator<<(char chr) override; + ioutput_stream &operator<<(uint8_t byte) override; + ioutput_stream &operator<<(uint16_t ui16) override; + ioutput_stream &operator<<(int16_t i16) override; + ioutput_stream &operator<<(uint32_t ui32) override; + ioutput_stream &operator<<(int32_t i32) override; + private: console_handler( USART_TypeDef *usart, DMA_TypeDef *dma, uint32_t stream_rx, uint32_t stream_tx, uint8_t *rx_buffer, size_type x_buffer_size, @@ -41,7 +52,7 @@ private: void setup_receive(void); - // LL_UsartCore pure virtual function implementations + // usart_core pure virtual function implementations void receiver_idle(void) override; void transmission_complete(void) override; void framing_error(void) override; @@ -53,6 +64,14 @@ private: void tx_dma_half_transfer(void) override; void tx_dma_error(dma_helper::dma_error_type reason) override; + // iotput_stream-related member variables + ioutput_stream::format m_fmt = ioutput_stream::format::dec; + + // iotput_stream-related helper functions + template void print_unsigned(T input); + template void print_signed(T input); + + // ringbuffer_ext m_tx_buffer; size_type m_bytes_sent = 0; diff --git a/src/console_handler.cpp b/src/console_handler.cpp index e1955f1..9ff43e7 100644 --- a/src/console_handler.cpp +++ b/src/console_handler.cpp @@ -5,10 +5,12 @@ * Author: abody */ +#include "f4ll/output_stream.h" #include #include #include +#include namespace f4ll { @@ -36,7 +38,7 @@ void console_handler::receiver_idle(void) { uint16_t rcvd_bytes = m_bytes_requested - m_reqd_bytes_registered - LL_DMA_GetDataLength(m_rx_dma.get_dma(), m_rx_dma.get_stream()); if (rcvd_bytes) { - m_reqd_bytes_registered += rcvd_bytes; + m_reqd_bytes_registered += rcvd_bytes; m_rx_buffer.produced(rcvd_bytes); m_rx_buffer.commit(); if (m_rx_callback) { @@ -130,4 +132,114 @@ void console_handler::print(char const *s) flush(); } +ioutput_stream &console_handler::operator<<(ioutput_stream::format const fmt) +{ + m_fmt = fmt; + return *this; +} + +ioutput_stream &console_handler::operator<<(char const *str) +{ + print(str); + return *this; +} + +ioutput_stream &console_handler::operator<<(char chr) +{ + m_tx_buffer.put(reinterpret_cast(&chr), 1); + flush(); + return *this; +} + +ioutput_stream &console_handler::operator<<(uint8_t byte) +{ + print_unsigned(byte); + return *this; +} + +ioutput_stream &console_handler::operator<<(uint16_t ui16) +{ + print_unsigned(ui16); + return *this; +} + +ioutput_stream &console_handler::operator<<(int16_t i16) +{ + print_signed(i16); + return *this; +} + +ioutput_stream &console_handler::operator<<(uint32_t ui32) +{ + print_unsigned(ui32); + return *this; +} + +ioutput_stream &console_handler::operator<<(int32_t i32) +{ + print_signed(i32); + return *this; +} + +template void console_handler::print_unsigned(T input) +{ + if (m_fmt != ioutput_stream::format::dec) { + append("0x"); + } + if (!input) { + append("0"); + flush(); + return; + } + + T res; + uint8_t cres; + + if (m_fmt == ioutput_stream::format::dec) { + static constexpr uint32_t const divisors[4] = {100, 10000, 10000000, 1000000000}; + T divisor = static_cast(divisors[sizeof(T) - 1]); + bool found = false; + + while (divisor) { + res = input / divisor; + if (res || found) { + cres = static_cast(res + '0'); + m_tx_buffer.put(&cres, 1); + input -= res * divisor; + found = true; + } + divisor /= 10; + } + } else { + uint8_t nibbles = sizeof(T) * 2; + bool found = false; + do { + uint8_t shift = (nibbles - 1) * 4; + T mask = 0xf << shift; + uint8_t bin = (input & mask) >> shift; + uint8_t chr = bin <= 9 ? bin + '0' : bin - 10 + 'A'; + if (!found && !bin && m_fmt == ioutput_stream::format::hex_trimmed) { + continue; + } + found = true; + m_tx_buffer.put(&chr, 1); + } while (--nibbles); + } + flush(); +} + +template void console_handler::print_signed(T input) +{ + using unsigned_t = typename std::make_unsigned::type; + unsigned_t uinput; + + if (m_fmt == ioutput_stream::format::dec && input < 0) { + append("-"); + uinput = static_cast(-input); + } else { + uinput = static_cast(input); + } + print_unsigned(uinput); +} + } /* namespace f4ll */