diff --git a/include/sta/uart.hpp b/include/sta/uart.hpp new file mode 100644 index 0000000..42068fc --- /dev/null +++ b/include/sta/uart.hpp @@ -0,0 +1,183 @@ +#ifndef STA_UART_HPP +#define STA_UART_HPP + +#include +#include + + +namespace sta +{ + /** + * @brief Integer representation. + */ + enum class IntegerBase + { + DEC, /**< Decimal */ + BIN, /**< Binary */ + HEX /**< Hexadecimal */ + }; + + /** + * @brief Interface for UART. + */ + class UART + { + public: + /** + * @brief Print single character. + * + * @param c Character to print + */ + void print(char c); + /** + * @brief Print boolean value. + * + * @param b Boolean value + */ + void print(bool b); + /** + * @brief Print integer in selected base. + * + * @param num 8-bit unsigned integer + * @param base Integer base + */ + void print(uint8_t num, IntegerBase base = IntegerBase::DEC); + /** + * @brief Print integer in selected base. + * + * @param num 16-bit unsigned integer + * @param base Integer base + */ + void print(uint16_t num, IntegerBase base = IntegerBase::DEC); + /** + * @brief Print integer in selected base. + * + * @param num 32-bit unsigned integer + * @param base Integer base + */ + void print(uint32_t num, IntegerBase base = IntegerBase::DEC); + /** + * @brief Print integer in selected base. + * + * @param num Integer + * @param base Integer base + */ + void print(size_t num, IntegerBase base = IntegerBase::DEC); + /** + * @brief Print c-string. + * + * @param str Null terminated string + */ + void print(const char * str); + /** + * @brief Print string. + * + * @param str String buffer + * @parma length String length + */ + void print(const char * str, size_t length); + + + /** + * @brief Print new-line. + */ + void println(); + /** + * @brief Print single character followed by a new-line. + * + * @param c Character to print + */ + void println(char c); + /** + * @brief Print boolean value followed by a new-line. + * + * @param b Boolean value + */ + void println(bool b); + /** + * @brief Print integer in selected base followed by a new-line. + * + * @param num 8-bit unsigned integer + * @param base Integer base + */ + void println(uint8_t num, IntegerBase base = IntegerBase::DEC); + /** + * @brief Print integer in selected base followed by a new-line. + * + * @param num 16-bit unsigned integer + * @param base Integer base + */ + void println(uint16_t num, IntegerBase base = IntegerBase::DEC); + /** + * @brief Print integer in selected base followed by a new-line. + * + * @param num 32-bit unsigned integer + * @param base Integer base + */ + void println(uint32_t num, IntegerBase base = IntegerBase::DEC); + /** + * @brief Print integer in selected base followed by a new-line. + * + * @param num Integer + * @param base Integer base + */ + void println(size_t num, IntegerBase base = IntegerBase::DEC); + /** + * @brief Print c-string followed by a new-line. + * + * @param str Null terminated string + */ + void println(const char * str); + /** + * @brief Print string followed by a new-line. + * + * @param str String buffer + * @parma length String length + */ + void println(const char * str, size_t length); + + + /** + * @brief Write buffer to UART. + * + * @param buffer Source buffer + * @param size Number of bytes in buffer + */ + virtual void write(const uint8_t * buffer, size_t size) = 0; + + private: + /** + * @brief Print unsigned integer in selected base. + * + * @param value Unsigned integer value + * @param base Integer base + * @param fmt printf format string for base 10 + * @param size Size of value in bytes + */ + void printBase(uintmax_t value, IntegerBase base, const char * fmt, size_t size); + /** + * @brief Print unsigned integer in base 10. + * + * @param value Unsigned integer value + * @param fmt printf format string + */ + void printDec(uintmax_t value, const char * fmt); + /** + * @brief Print unsigned integer in base 2. + * + * @param value Unsigned integer value + * @param digits Number of digits to print + */ + void printBin(uintmax_t value, size_t digits); + /** + * @brief Print unsigned integer in base 16. + * + * @param value Unsigned integer value + * @param digits Number of digits to print + */ + void printHex(uintmax_t value, size_t digits); + }; +} // namespace sta + + +#endif // STA_UART_HPP diff --git a/src/uart.cpp b/src/uart.cpp new file mode 100644 index 0000000..660c5ed --- /dev/null +++ b/src/uart.cpp @@ -0,0 +1,187 @@ +#include + +#include +#include + + +namespace sta +{ + void UART::print(char c) + { + print(&c, 1); + } + + void UART::print(bool b) + { + print(b ? "true" : "false"); + } + + void UART::print(uint8_t num, IntegerBase base /* = IntegerBase::DEC */) + { + printBase(num, base, "%u", sizeof(num)); + } + + void UART::print(uint16_t num, IntegerBase base /* = IntegerBase::DEC */) + { + printBase(num, base, "%u", sizeof(num)); + } + + void UART::print(uint32_t num, IntegerBase base /* = IntegerBase::DEC */) + { + printBase(num, base, "%lu", sizeof(num)); + } + + void UART::print(size_t num, IntegerBase base /* = IntegerBase::DEC */) + { + printBase(num, base, "%u", sizeof(num)); + } + + void UART::print(const char * str) + { + print(str, strlen(str)); + } + + void UART::print(const char * str, size_t length) + { + write(reinterpret_cast(str), length); + } + + + void UART::println() + { + print("\r\n", 2); + } + + void UART::println(char c) + { + print(&c, 1); + println(); + } + + void UART::println(bool b) + { + print(b); + println(); + } + + void UART::println(uint8_t num, IntegerBase base /* = IntegerBase::DEC */) + { + print(num, base); + println(); + } + + void UART::println(uint16_t num, IntegerBase base /* = IntegerBase::DEC */) + { + print(num, base); + println(); + } + + void UART::println(uint32_t num, IntegerBase base /* = IntegerBase::DEC */) + { + print(num, base); + println(); + } + + void UART::println(size_t num, IntegerBase base /* = IntegerBase::DEC */) + { + print(num, base); + println(); + } + + void UART::println(const char * str) + { + println(str, strlen(str)); + } + + void UART::println(const char * str, size_t length) + { + print(str, length); + println(); + } + + + + void UART::printBase(uintmax_t num, IntegerBase base, const char * fmt, size_t size) + { + switch (base) + { + case IntegerBase::DEC: + printDec(num, fmt); + break; + + case IntegerBase::BIN: + // Digits in base 2 = size in bytes * 8 + printBin(num, size * 8); + break; + + case IntegerBase::HEX: + // Digits in base 16 = size in bytes * 2 + printHex(num, size * 2); + break; + + default: + print(""); + } + } + + void UART::printDec(uintmax_t num, const char * fmt) + { + char buffer[64]; + sprintf(buffer, fmt, num); + print(buffer); + } + + void UART::printBin(uintmax_t value, size_t digits) + { + // Need 8 digits for every byte + char buffer[sizeof(value) * 8]; + + // Check bounds + if (digits > sizeof(buffer)) + { + print(""); + return; + } + // Nothing to do + if (digits == 0) + return; + + for (size_t i = 0; i < digits; ++i) + { + // Convert bit to '0' or '1' + // First digit in buffer is MSB in value, so shift from high to low + buffer[i] = '0' + ((value >> (digits - 1 - i)) & 0x1); + } + + print(buffer, digits); + } + + void UART::printHex(uintmax_t value, size_t digits) + { + // Need 2 digits for every byte + char buffer[sizeof(value) * 2]; + + // Check bounds + if (digits > sizeof(buffer)) + { + print(""); + return; + } + // Nothing to do + if (digits == 0) + return; + + for (size_t i = 0; i < digits; ++i) + { + // Convert 4 bits to hex + // First digit in buffer is 4 MSBs in value, so shift from high to low + uint8_t hex = ((value >> ((digits - 1 - i) * 4)) & 0xF); + if (hex > 9) + buffer[i] = 'A' + (hex - 9); + else + buffer[i] = '0' + hex; + } + + print(buffer, digits); + } +} // namespace sta