diff --git a/uart.hpp b/uart.hpp index c7cef43..45c1738 100644 --- a/uart.hpp +++ b/uart.hpp @@ -1,5 +1,7 @@ #pragma once +#include + #include "config.hpp" #include "hardware0.hpp" #include "hardware1.hpp" @@ -12,6 +14,38 @@ namespace uart { +namespace detail { + +template +static constexpr size_t cntDigits() +{ + T num = limit; + size_t cnt = 0; + + if (num < 0) { + num = -num; + ++cnt; + } + + do { + num /= 10; + ++cnt; + } while (num > 0); + + return cnt; +} + +template +static constexpr size_t maxNumDigits() +{ + T minDigits = cntDigits::min(), Base>(); + T maxDigits = cntDigits::max(), Base>(); + + return (minDigits < maxDigits) ? maxDigits : minDigits; +} + +} // namespace detail + template class Uart { public: @@ -70,6 +104,32 @@ class Uart { txByte(ch); } + template + static inline void txNumber(const T &val) + { + // static_assert(util::is_integral_v, "Only supported on integral types"); + + constexpr size_t numDigits = detail::maxNumDigits(); + typename Driver::data_t buffer[numDigits]; + typename Driver::data_t *bufEnd = buffer + numDigits - 1; + + T digits = val; + + if (digits < 0) { + digits = -digits; + txByte('-'); + } + + do { + typename Driver::data_t lastDigit = digits % Base; + *bufEnd-- = '0' + lastDigit; + digits /= Base; + } while (digits > 0); + + for (typename Driver::data_t *buf = bufEnd + 1; buf < buffer + numDigits; ++buf) + txByte(*buf); + } + ////////////////////////////////////////////////////////////////////////// // Output stream overloads @@ -86,91 +146,91 @@ class Uart { } template - Uart &operator<<(char) + Uart &operator<<(char) const { static_assert(util::always_false_v, "Not implemented"); } template - Uart &operator<<(unsigned char) + Uart &operator<<(unsigned char) const { static_assert(util::always_false_v, "Not implemented"); } template - Uart &operator<<(short) + Uart &operator<<(short) const { static_assert(util::always_false_v, "Not implemented"); } template - Uart &operator<<(unsigned short) + Uart &operator<<(unsigned short) const + { + static_assert(util::always_false_v, "Not implemented"); + } + + Uart &operator<<(const int &val) + { + txNumber(val); + return *this; + } + + template + Uart &operator<<(unsigned int) const { static_assert(util::always_false_v, "Not implemented"); } template - Uart &operator<<(int) + Uart &operator<<(long) const { static_assert(util::always_false_v, "Not implemented"); } template - Uart &operator<<(unsigned int) + Uart &operator<<(unsigned long) const { static_assert(util::always_false_v, "Not implemented"); } template - Uart &operator<<(long) + Uart &operator<<(long long) const { static_assert(util::always_false_v, "Not implemented"); } template - Uart &operator<<(unsigned long) + Uart &operator<<(unsigned long long) const { static_assert(util::always_false_v, "Not implemented"); } template - Uart &operator<<(long long) + Uart &operator<<(float) const { static_assert(util::always_false_v, "Not implemented"); } template - Uart &operator<<(unsigned long long) + Uart &operator<<(double) const { static_assert(util::always_false_v, "Not implemented"); } template - Uart &operator<<(float) + Uart &operator<<(long double) const { static_assert(util::always_false_v, "Not implemented"); } template - Uart &operator<<(double) + Uart &operator<<(bool) const { static_assert(util::always_false_v, "Not implemented"); } template - Uart &operator<<(long double) - { - static_assert(util::always_false_v, "Not implemented"); - } - - template - Uart &operator<<(bool) - { - static_assert(util::always_false_v, "Not implemented"); - } - - template - Uart &operator<<(const void *) + Uart &operator<<(const void *) const { static_assert(util::always_false_v, "Not implemented"); } @@ -179,91 +239,91 @@ class Uart { // Input stream overloads template - Uart &operator>>(char &) + Uart &operator>>(char &) const { static_assert(util::always_false_v, "Not implemented"); } template - Uart &operator>>(unsigned char &) + Uart &operator>>(unsigned char &) const { static_assert(util::always_false_v, "Not implemented"); } template - Uart &operator>>(short &) + Uart &operator>>(short &) const { static_assert(util::always_false_v, "Not implemented"); } template - Uart &operator>>(unsigned short &) + Uart &operator>>(unsigned short &) const { static_assert(util::always_false_v, "Not implemented"); } template - Uart &operator>>(int &) + Uart &operator>>(int &) const { static_assert(util::always_false_v, "Not implemented"); } template - Uart &operator>>(unsigned int &) + Uart &operator>>(unsigned int &) const { static_assert(util::always_false_v, "Not implemented"); } template - Uart &operator>>(long &) + Uart &operator>>(long &) const { static_assert(util::always_false_v, "Not implemented"); } template - Uart &operator>>(unsigned long &) + Uart &operator>>(unsigned long &) const { static_assert(util::always_false_v, "Not implemented"); } template - Uart &operator>>(long long &) + Uart &operator>>(long long &) const { static_assert(util::always_false_v, "Not implemented"); } template - Uart &operator>>(unsigned long long &) + Uart &operator>>(unsigned long long &) const { static_assert(util::always_false_v, "Not implemented"); } template - Uart &operator>>(float &) + Uart &operator>>(float &) const { static_assert(util::always_false_v, "Not implemented"); } template - Uart &operator>>(double &) + Uart &operator>>(double &) const { static_assert(util::always_false_v, "Not implemented"); } template - Uart &operator>>(long double &) + Uart &operator>>(long double &) const { static_assert(util::always_false_v, "Not implemented"); } template - Uart &operator>>(bool &) + Uart &operator>>(bool &) const { static_assert(util::always_false_v, "Not implemented"); } template - Uart &operator>>(const void *&) + Uart &operator>>(const void *&) const { static_assert(util::always_false_v, "Not implemented"); }