From d4aeca7469ff8e90348928fbc76c936403a428d8 Mon Sep 17 00:00:00 2001 From: Marian Buschsieweke Date: Thu, 29 Aug 2019 13:29:38 +0200 Subject: [PATCH] sys/arduino: Extended Serial.print() / println() - Serial.print() and Serial.println() have been extended to support: - unsigned int - long - unsigned long - The SerialFormat BIN has been implemented - Serial.println(void) has been added --- sys/arduino/include/serialport.hpp | 186 +++++++++++++++++++++++++++++ sys/arduino/serialport.cpp | 137 +++++++++++++++++---- 2 files changed, 303 insertions(+), 20 deletions(-) diff --git a/sys/arduino/include/serialport.hpp b/sys/arduino/include/serialport.hpp index f9a22ca0fd..6be92549b4 100644 --- a/sys/arduino/include/serialport.hpp +++ b/sys/arduino/include/serialport.hpp @@ -48,6 +48,8 @@ private: uart_t dev; char rx_mem[SERIAL_RX_BUFSIZE]; ringbuffer_t rx_buf; + template size_t _println(T val); + template size_t _println(T val, SerialFormat format); public: /** @@ -125,6 +127,93 @@ public: */ size_t print(int val, SerialFormat format); + /** + * @brief Prints data to the serial port as human-readable ASCII text + * + * Prints data to the serial port as human-readable ASCII text. This command + * can take many forms. Numbers are printed using an ASCII character for + * each digit. Floats are similarly printed as ASCII digits, defaulting to + * two decimal places. Bytes are sent as a single character. Characters and + * strings are sent as is. + * + * Copied from https://www.arduino.cc/en/Serial/Print + * + * @param[in] val the value to print + * + * @return the number of bytes written, reading that number is optional + */ + size_t print(unsigned int val); + + /** + * @brief Prints data to the serial port as human-readable ASCII text + * + * @see print() + * + * @param[in] val the value to print + * @param[in] format specifies the number base + * + * @return the number of bytes written, reading that number is optional + */ + size_t print(unsigned int val, SerialFormat format); + + /** + * @brief Prints data to the serial port as human-readable ASCII text + * + * Prints data to the serial port as human-readable ASCII text. This command + * can take many forms. Numbers are printed using an ASCII character for + * each digit. Floats are similarly printed as ASCII digits, defaulting to + * two decimal places. Bytes are sent as a single character. Characters and + * strings are sent as is. + * + * Copied from https://www.arduino.cc/en/Serial/Print + * + * @param[in] val the value to print + * + * @return the number of bytes written, reading that number is optional + */ + size_t print(long val); + + /** + * @brief Prints data to the serial port as human-readable ASCII text + * + * @see print() + * + * @param[in] val the value to print + * @param[in] format specifies the number base + * + * @return the number of bytes written, reading that number is optional + */ + size_t print(long val, SerialFormat format); + + /** + * @brief Prints data to the serial port as human-readable ASCII text + * + * Prints data to the serial port as human-readable ASCII text. This command + * can take many forms. Numbers are printed using an ASCII character for + * each digit. Floats are similarly printed as ASCII digits, defaulting to + * two decimal places. Bytes are sent as a single character. Characters and + * strings are sent as is. + * + * Copied from https://www.arduino.cc/en/Serial/Print + * + * @param[in] val the value to print + * + * @return the number of bytes written, reading that number is optional + */ + size_t print(unsigned long val); + + /** + * @brief Prints data to the serial port as human-readable ASCII text + * + * @see print() + * + * @param[in] val the value to print + * @param[in] format specifies the number base + * + * @return the number of bytes written, reading that number is optional + */ + size_t print(unsigned long val, SerialFormat format); + /** * @brief Prints data to the serial port as human-readable ASCII text * @@ -197,6 +286,93 @@ public: */ size_t println(int val, SerialFormat format); + /** + * @brief Prints data to the serial port as human-readable ASCII text + * followed by a carriage return character (ASCII 13, or "\r") and + * a newline character (ASCII 10, or "\n") + * + * This command takes the same forms as @ref print(). + * + * Copied from https://www.arduino.cc/en/Serial/Println + * + * @param[in] val the value to print + * + * @return the number of bytes written, reading that number is optional + */ + size_t println(unsigned int val); + + /** + * @brief Prints data to the serial port as human-readable ASCII text + * followed by a carriage return character (ASCII 13, or "\r") and + * a newline character (ASCII 10, or "\n") + * + * @see println() + * + * @param[in] val the value to print + * @param[in] format specifies the number base + * + * @return the number of bytes written, reading that number is optional + */ + size_t println(unsigned int val, SerialFormat format); + + /** + * @brief Prints data to the serial port as human-readable ASCII text + * followed by a carriage return character (ASCII 13, or "\r") and + * a newline character (ASCII 10, or "\n") + * + * This command takes the same forms as @ref print(). + * + * Copied from https://www.arduino.cc/en/Serial/Println + * + * @param[in] val the value to print + * + * @return the number of bytes written, reading that number is optional + */ + size_t println(long val); + + /** + * @brief Prints data to the serial port as human-readable ASCII text + * followed by a carriage return character (ASCII 13, or "\r") and + * a newline character (ASCII 10, or "\n") + * + * @see println() + * + * @param[in] val the value to print + * @param[in] format specifies the number base + * + * @return the number of bytes written, reading that number is optional + */ + size_t println(long val, SerialFormat format); + + /** + * @brief Prints data to the serial port as human-readable ASCII text + * followed by a carriage return character (ASCII 13, or "\r") and + * a newline character (ASCII 10, or "\n") + * + * This command takes the same forms as @ref print(). + * + * Copied from https://www.arduino.cc/en/Serial/Println + * + * @param[in] val the value to print + * + * @return the number of bytes written, reading that number is optional + */ + size_t println(unsigned long val); + + /** + * @brief Prints data to the serial port as human-readable ASCII text + * followed by a carriage return character (ASCII 13, or "\r") and + * a newline character (ASCII 10, or "\n") + * + * @see println() + * + * @param[in] val the value to print + * @param[in] format specifies the number base + * + * @return the number of bytes written, reading that number is optional + */ + size_t println(unsigned long val, SerialFormat format); + /** * @brief Prints data to the serial port as human-readable ASCII text * followed by a carriage return character (ASCII 13, or "\r") and @@ -250,6 +426,16 @@ public: */ size_t println(const char *val); + /** + * @brief Prints a carriage return character (ASCII 13, or "\r") and + * a newline character (ASCII 10, or "\n") + * + * @see println() + * + * @return the number of bytes written, reading that number is optional + */ + size_t println(void); + /** * @brief Reads incoming serial data * diff --git a/sys/arduino/serialport.cpp b/sys/arduino/serialport.cpp index 29828f43f8..e7c4f5e0c4 100644 --- a/sys/arduino/serialport.cpp +++ b/sys/arduino/serialport.cpp @@ -57,25 +57,81 @@ void SerialPort::end(void) size_t SerialPort::print(int val) { - return print(val, DEC); + return print((long)val, DEC); } size_t SerialPort::print(int val, SerialFormat format) +{ + if (format == DEC) { + return print((long)val, format); + } + + /* Propagation to long of negative number changes binary representation. + * This cast should add leading zeros to the binary representation, that + * will be skipped by print(unsigned long, SerialFormat) + */ + return print((unsigned long)((unsigned)val), format); +} + +size_t SerialPort::print(unsigned int val) +{ + return print((unsigned long)val, DEC); +} + +size_t SerialPort::print(unsigned int val, SerialFormat format) +{ + return print((unsigned long)val, format); +} + +size_t SerialPort::print(long val) +{ + return print(val, DEC); +} + +size_t SerialPort::print(long val, SerialFormat format) +{ + if (format == DEC) { + char buf[64]; + size_t len; + len = sprintf(buf, "%li", val); + write(buf, len); + return len; + } + + return print((unsigned long)val, format); +} + +size_t SerialPort::print(unsigned long val) +{ + return print(val, DEC); +} + +size_t SerialPort::print(unsigned long val, SerialFormat format) { char buf[64]; size_t len; switch (format) { case BIN: - /* TODO */ - return 0; + len = 0; + { + static const unsigned long mask = 1UL << (8 * sizeof(unsigned long) - 1); + unsigned pos = 0; + while (!(val & (mask >> pos))) { + pos ++; + } + for (; pos < 8 * sizeof(unsigned long); pos++) { + buf[len++] = (val & (mask >> pos)) ? '1' : '0'; + } + } + break; case OCT: - len = sprintf(buf, "%o", (unsigned)val); + len = sprintf(buf, "%lo", val); break; case DEC: - len = sprintf(buf, "%i", val); + len = sprintf(buf, "%lu", val); break; case HEX: - len = sprintf(buf, "%x", (unsigned)val); + len = sprintf(buf, "%lx", val); break; default: return 0; @@ -107,46 +163,87 @@ size_t SerialPort::print(const char *val) return (size_t)write(val); } -size_t SerialPort::println(int val) +template size_t SerialPort::_println(T val) { size_t res = print(val); write("\r\n"); - return (res + 2); + return res + 2; +} + +template size_t SerialPort::_println(T val, SerialFormat format) +{ + size_t res = print(val, format); + write("\r\n"); + return res + 2; +} + +size_t SerialPort::println(int val) +{ + return _println(val); } size_t SerialPort::println(int val, SerialFormat format) { - size_t res = print(val, format); - write("\r\n"); - return (res + 2); + return _println(val, format); +} + +size_t SerialPort::println(unsigned int val) +{ + return _println(val); +} + +size_t SerialPort::println(unsigned int val, SerialFormat format) +{ + return _println(val, format); +} + +size_t SerialPort::println(long val) +{ + return _println(val); +} + +size_t SerialPort::println(long val, SerialFormat format) +{ + return _println(val, format); +} + +size_t SerialPort::println(unsigned long val) +{ + return _println(val); +} + +size_t SerialPort::println(unsigned long val, SerialFormat format) +{ + return _println(val, format); } size_t SerialPort::println(float val) { - size_t res = print(val); - write("\r\n"); - return (res + 2); + return _println(val); } size_t SerialPort::println(float val, int format) { + /* cannot use template here, second parameter differs in type */ size_t res = print(val, format); write("\r\n"); - return (res + 2); + return res + 2; } size_t SerialPort::println(char val) { - size_t res = print(val); - write("\r\n"); - return (res + 2); + return _println(val); } size_t SerialPort::println(const char *val) { - size_t res = print(val); + return _println(val); +} + +size_t SerialPort::println(void) +{ write("\r\n"); - return (res + 2); + return 2; } int SerialPort::read(void)