From e633222cd38e4b5c15ac4d2a310510ea8031f687 Mon Sep 17 00:00:00 2001 From: Markus Hitter Date: Mon, 25 Apr 2016 02:45:24 +0200 Subject: [PATCH] Make message/text sending aware of the sending destination. Point of this change is to allow using these functions for writing to the display, too, without duplicating all the code. To reduce confusion, functions were renamed (they're no longer 'serial', after all: serwrite_xxx() -> write_xxx() sersendf_P() -> sendf_P() To avoid changing all the existing code, a couple of macros with the old names are provided. They might even be handy as convenience macros. Nicely, this addition costs no additional RAM. Not surprising, it costs quite some binary size, 278 bytes. Sizes now: Program: 24058 bytes 168% 79% 38% 19% Data: 1525 bytes 149% 75% 38% 19% EEPROM: 32 bytes 4% 2% 2% 1% Regarding USB Serial: code was adjusted without testing on hardware. --- dda.c | 1 - dda_lookahead.c | 1 - dda_queue.c | 1 - gcode_process.c | 1 - i2c_test.c | 3 ++- sermsg.c => msg.c | 54 +++++++++++++++++++++---------------------- msg.h | 24 +++++++++++++++++++ sersendf.c => sendf.c | 53 ++++++++++++++++++++++++------------------ sendf.h | 11 +++++++++ serial-arm.c | 7 +++--- serial.h | 1 - sermsg.h | 36 ++++++++++++++--------------- sersendf.h | 12 +++++++--- usb_serial.c | 32 +++++++++++++------------ usb_serial.h | 2 +- 15 files changed, 143 insertions(+), 96 deletions(-) rename sermsg.c => msg.c (58%) create mode 100644 msg.h rename sersendf.c => sendf.c (51%) create mode 100644 sendf.h diff --git a/dda.c b/dda.c index c658d52..92307f3 100644 --- a/dda.c +++ b/dda.c @@ -15,7 +15,6 @@ #include "cpu.h" #include "timer.h" #include "serial.h" -#include "sermsg.h" #include "gcode_parse.h" #include "dda_queue.h" #include "debug.h" diff --git a/dda_lookahead.c b/dda_lookahead.c index aa5294a..879d5a5 100644 --- a/dda_lookahead.c +++ b/dda_lookahead.c @@ -17,7 +17,6 @@ #include "timer.h" #include "delay.h" #include "serial.h" -#include "sermsg.h" #include "gcode_parse.h" #include "dda_queue.h" #include "debug.h" diff --git a/dda_queue.c b/dda_queue.c index 3054905..3a2c5fc 100644 --- a/dda_queue.c +++ b/dda_queue.c @@ -9,7 +9,6 @@ #include "config_wrapper.h" #include "timer.h" #include "serial.h" -#include "sermsg.h" #include "temp.h" #include "delay.h" #include "sersendf.h" diff --git a/gcode_process.c b/gcode_process.c index 778c8e5..79493e9 100644 --- a/gcode_process.c +++ b/gcode_process.c @@ -14,7 +14,6 @@ #include "watchdog.h" #include "delay.h" #include "serial.h" -#include "sermsg.h" #include "temp.h" #include "heater.h" #include "timer.h" diff --git a/i2c_test.c b/i2c_test.c index abf196a..1cbd143 100644 --- a/i2c_test.c +++ b/i2c_test.c @@ -17,6 +17,7 @@ #include "config_wrapper.h" #include "display.h" #include "font.h" +#include "sendf.h" static void i2c_test(void) { @@ -25,7 +26,7 @@ static void i2c_test(void) { 128 columns, so we offset by 32 columns to get it to the center. */ display_set_cursor(1, 32); - display_writestr_P(PSTR("Welcome to Teacup")); + sendf_P(display_writechar, PSTR("Welcome to Teacup")); } #endif /* I2C_TEST */ diff --git a/sermsg.c b/msg.c similarity index 58% rename from sermsg.c rename to msg.c index 43899ad..6ce1f47 100644 --- a/sermsg.c +++ b/msg.c @@ -1,44 +1,44 @@ -#include "sermsg.h" -/** \file sermsg.c - \brief primitives for sending numbers over the serial link +/** \file msg.c + + \brief Primitives for sending numbers over links. */ -#include "serial.h" +#include "msg.h" /** write a single hex digit \param v hex digit to write, higher nibble ignored */ -void serwrite_hex4(uint8_t v) { +void write_hex4(void (*writechar)(uint8_t), uint8_t v) { v &= 0xF; if (v < 10) - serial_writechar('0' + v); + writechar('0' + v); else - serial_writechar('A' - 10 + v); + writechar('A' - 10 + v); } /** write a pair of hex digits \param v byte to write. One byte gives two hex digits */ -void serwrite_hex8(uint8_t v) { - serwrite_hex4(v >> 4); - serwrite_hex4(v & 0x0F); +void write_hex8(void (*writechar)(uint8_t), uint8_t v) { + write_hex4(writechar, v >> 4); + write_hex4(writechar, v & 0x0F); } /** write four hex digits \param v word to write */ -void serwrite_hex16(uint16_t v) { - serwrite_hex8(v >> 8); - serwrite_hex8(v & 0xFF); +void write_hex16(void (*writechar)(uint8_t), uint16_t v) { + write_hex8(writechar, v >> 8); + write_hex8(writechar, v & 0xFF); } /** write eight hex digits \param v long word to write */ -void serwrite_hex32(uint32_t v) { - serwrite_hex16(v >> 16); - serwrite_hex16(v & 0xFFFF); +void write_hex32(void (*writechar)(uint8_t), uint32_t v) { + write_hex16(writechar, v >> 16); + write_hex16(writechar, v & 0xFFFF); } /// list of powers of ten, used for dividing down decimal numbers for sending, and also for our crude floating point algorithm @@ -47,7 +47,7 @@ const uint32_t powers[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 1 /** write decimal digits from a long unsigned int \param v number to send */ -void serwrite_uint32(uint32_t v) { +void write_uint32(void (*writechar)(uint8_t), uint32_t v) { uint8_t e, t; for (e = 9; e > 0; e--) { @@ -58,7 +58,7 @@ void serwrite_uint32(uint32_t v) { do { for (t = 0; v >= powers[e]; v -= powers[e], t++); - serial_writechar(t + '0'); + writechar(t + '0'); } while (e--); } @@ -66,20 +66,20 @@ void serwrite_uint32(uint32_t v) { /** write decimal digits from a long signed int \param v number to send */ -void serwrite_int32(int32_t v) { +void write_int32(void (*writechar)(uint8_t), int32_t v) { if (v < 0) { - serial_writechar('-'); + writechar('-'); v = -v; } - serwrite_uint32(v); + write_uint32(writechar, v); } /** write decimal digits from a long unsigned int \param v number to send \param fp number of decimal places to the right of the decimal point */ -void serwrite_uint32_vf(uint32_t v, uint8_t fp) { +void write_uint32_vf(void (*writechar)(uint8_t), uint32_t v, uint8_t fp) { uint8_t e, t; for (e = 9; e > 0; e--) { @@ -93,9 +93,9 @@ void serwrite_uint32_vf(uint32_t v, uint8_t fp) { do { for (t = 0; v >= powers[e]; v -= powers[e], t++); - serial_writechar(t + '0'); + writechar(t + '0'); if (e == fp) - serial_writechar('.'); + writechar('.'); } while (e--); } @@ -104,11 +104,11 @@ void serwrite_uint32_vf(uint32_t v, uint8_t fp) { \param v number to send \param fp number of decimal places to the right of the decimal point */ -void serwrite_int32_vf(int32_t v, uint8_t fp) { +void write_int32_vf(void (*writechar)(uint8_t), int32_t v, uint8_t fp) { if (v < 0) { - serial_writechar('-'); + writechar('-'); v = -v; } - serwrite_uint32_vf(v, fp); + write_uint32_vf(writechar, v, fp); } diff --git a/msg.h b/msg.h new file mode 100644 index 0000000..f34d5b4 --- /dev/null +++ b/msg.h @@ -0,0 +1,24 @@ +#ifndef _SERMSG_H +#define _SERMSG_H + +#include + +// functions for sending hexadecimal +void write_hex4(void (*writechar)(uint8_t), uint8_t v); +void write_hex8(void (*writechar)(uint8_t), uint8_t v); +void write_hex16(void (*writechar)(uint8_t), uint16_t v); +void write_hex32(void (*writechar)(uint8_t), uint32_t v); + +// functions for sending decimal +#define write_uint8(v, w) write_uint32(v, w) +#define write_int8(v, w) write_int32(v, w) +#define write_uint16(v, w) write_uint32(v, w) +#define write_int16(v, w) write_int32(v, w) + +void write_uint32(void (*writechar)(uint8_t), uint32_t v); +void write_int32(void (*writechar)(uint8_t), int32_t v); + +void write_uint32_vf(void (*writechar)(uint8_t), uint32_t v, uint8_t fp); +void write_int32_vf(void (*writechar)(uint8_t), int32_t v, uint8_t fp); + +#endif /* _SERMSG_H */ diff --git a/sersendf.c b/sendf.c similarity index 51% rename from sersendf.c rename to sendf.c index 162ce2d..340be72 100644 --- a/sersendf.c +++ b/sendf.c @@ -1,4 +1,3 @@ -#include "sersendf.h" /** \file sersendf.c \brief Simplified printf implementation @@ -6,13 +5,18 @@ #include -#include "serial.h" -#include "sermsg.h" +#include "sendf.h" +#include "msg.h" /** \brief Simplified printf - \param format pointer to output format specifier string stored in FLASH. - \param ... output data + + \param writechar The function to use for writing a character. Typically + serial_writechar() or display_writechar(). + + \param format Pointer to output format specifier string stored in FLASH. + + \param ... Data according to the placeholders in format. Implements only a tiny subset of printf's format specifiers :- @@ -31,7 +35,11 @@ Example: - \code sersendf_P(PSTR("X:%ld Y:%ld temp:%u.%d flags:%sx Q%su/%su%c\n"), target.X, target.Y, current_temp >> 2, (current_temp & 3) * 25, dda.allflags, mb_head, mb_tail, (queue_full()?'F':(queue_empty()?'E':' '))) \endcode + \code sersendf_P(serial_writechar, + PSTR("X:%ld Y:%ld temp:%u.%d flags:%sx Q%su/%su%c\n"), + target.X, target.Y, current_temp >> 2, + (current_temp & 3) * 25, dda.allflags, mb_head, mb_tail, + (queue_full()?'F':(queue_empty()?'E':' '))) \endcode */ /** @@ -45,7 +53,7 @@ #define GET_ARG(T) ((T)va_arg(args, int)) #endif -void sersendf_P(PGM_P format_P, ...) { +void sendf_P(void (*writechar)(uint8_t), PGM_P format_P, ...) { va_list args; va_start(args, format_P); @@ -62,44 +70,45 @@ void sersendf_P(PGM_P format_P, ...) { break; case 'u': if (j == 1) - serwrite_uint8((uint8_t)GET_ARG(uint16_t)); + write_uint8(writechar, (uint8_t)GET_ARG(uint16_t)); else if (j == 2) - serwrite_uint16((uint16_t)GET_ARG(uint16_t)); + write_uint16(writechar, (uint16_t)GET_ARG(uint16_t)); else - serwrite_uint32(GET_ARG(uint32_t)); + write_uint32(writechar, GET_ARG(uint32_t)); j = 0; break; case 'd': if (j == 1) - serwrite_int8((int8_t)GET_ARG(int16_t)); + write_int8(writechar, (int8_t)GET_ARG(int16_t)); else if (j == 2) - serwrite_int16((int16_t)GET_ARG(int16_t)); + write_int16(writechar, (int16_t)GET_ARG(int16_t)); else - serwrite_int32(GET_ARG(int32_t)); + write_int32(writechar, GET_ARG(int32_t)); j = 0; break; case 'c': - serial_writechar((uint8_t)GET_ARG(uint16_t)); + writechar((uint8_t)GET_ARG(uint16_t)); j = 0; break; case 'x': - serial_writestr_P(PSTR("0x")); + writechar('0'); + writechar('x'); if (j == 1) - serwrite_hex8((uint8_t)GET_ARG(uint16_t)); + write_hex8(writechar, (uint8_t)GET_ARG(uint16_t)); else if (j == 2) - serwrite_hex16((uint16_t)GET_ARG(uint16_t)); + write_hex16(writechar, (uint16_t)GET_ARG(uint16_t)); else - serwrite_hex32(GET_ARG(uint32_t)); + write_hex32(writechar, GET_ARG(uint32_t)); j = 0; break; /* case 'p': - serwrite_hex16(GET_ARG(uint16_t));*/ + serwrite_hex16(writechar, GET_ARG(uint16_t));*/ case 'q': - serwrite_int32_vf(GET_ARG(uint32_t), 3); + write_int32_vf(writechar, GET_ARG(uint32_t), 3); j = 0; break; default: - serial_writechar(c); + writechar(c); j = 0; break; } @@ -109,7 +118,7 @@ void sersendf_P(PGM_P format_P, ...) { j = 2; } else { - serial_writechar(c); + writechar(c); } } } diff --git a/sendf.h b/sendf.h new file mode 100644 index 0000000..64c7249 --- /dev/null +++ b/sendf.h @@ -0,0 +1,11 @@ + +#ifndef _SENDF_H +#define _SENDF_H + +#include "arduino.h" + + +// No __attribute__ ((format (printf, 1, 2)) here because %q isn't supported. +void sendf_P(void (*writechar)(uint8_t), PGM_P format_P, ...); + +#endif /* _SENDF_H */ diff --git a/serial-arm.c b/serial-arm.c index 49919a6..96d65f1 100644 --- a/serial-arm.c +++ b/serial-arm.c @@ -199,9 +199,10 @@ void serial_init() { serial_writestr_P(PSTR("\nSerial port parameters were calculated at ")); serial_writestr_P(PSTR("runtime.\nInsert these values to the list of ")); serial_writestr_P(PSTR("known settings in serial-arm.c:\n")); - sersendf_P(PSTR(" UART_DLM %sx\n"), (DL >> 8) & 0xFF); - sersendf_P(PSTR(" UART_DLL %sx\n"), (DL >> 0) & 0xFF); - sersendf_P(PSTR(" UART_FDR %sx\n"), (DivAddVal << 0) | (MulVal << 4)); + sersendf_P(serial_writechar, PSTR(" UART_DLM %sx\n"), (DL >> 8) & 0xFF); + sersendf_P(serial_writechar, PSTR(" UART_DLL %sx\n"), (DL >> 0) & 0xFF); + sersendf_P(serial_writechar, PSTR(" UART_FDR %sx\n"), + (DivAddVal << 0) | (MulVal << 4)); serial_writestr_P(PSTR("Doing so will speed up serial considerably.\n\n")); #endif } diff --git a/serial.h b/serial.h index bda9b78..663ad67 100644 --- a/serial.h +++ b/serial.h @@ -10,7 +10,6 @@ #define serial_init() usb_init() #define serial_rxchars() usb_serial_available() #define serial_popchar() usb_serial_getchar() - #define serial_writechar(c) usb_serial_putchar(c) #else // initialise serial subsystem void serial_init(void); diff --git a/sermsg.h b/sermsg.h index d2ad543..753c8c4 100644 --- a/sermsg.h +++ b/sermsg.h @@ -1,24 +1,22 @@ -#ifndef _SERMSG_H -#define _SERMSG_H -#include +#ifndef _MSG_H +#define _MSG_H -// functions for sending hexadecimal -void serwrite_hex4(uint8_t v); -void serwrite_hex8(uint8_t v); -void serwrite_hex16(uint16_t v); -void serwrite_hex32(uint32_t v); +#include "msg.h" +#include "serial.h" -// functions for sending decimal -#define serwrite_uint8(v) serwrite_uint32(v) -#define serwrite_int8(v) serwrite_int32(v) -#define serwrite_uint16(v) serwrite_uint32(v) -#define serwrite_int16(v) serwrite_int32(v) +/** + Before we had display support, all messages went to the serial link, + so this destination was hardcoded. These macros avoid changing some + older code. -void serwrite_uint32(uint32_t v); -void serwrite_int32(int32_t v); + Deprecated macros? Convenience macros? Dunno. +*/ +#define serwrite_uint8(v) write_uint8(serial_writechar, v) +#define serwrite_int8(v) write_int8(serial_writechar, v) +#define serwrite_uint16(v) write_uint32(serial_writechar, v) +#define serwrite_int16(v) write_int32(serial_writechar, v) +#define serwrite_uint32(v) write_uint32(serial_writechar, v); +#define serwrite_int32(v) write_int32(serial_writechar, v); -void serwrite_uint32_vf(uint32_t v, uint8_t fp); -void serwrite_int32_vf(int32_t v, uint8_t fp); - -#endif /* _SERMSG_H */ \ No newline at end of file +#endif /* _MSG_H */ diff --git a/sersendf.h b/sersendf.h index 516198c..2dfefcf 100644 --- a/sersendf.h +++ b/sersendf.h @@ -1,10 +1,16 @@ #ifndef _SERSENDF_H #define _SERSENDF_H -#include "arduino.h" +#include "sendf.h" +#include "serial.h" +/** + Before we had display support, all messages went to the serial link, + so this destination was hardcoded. This macro avoids changing a whole lot + of older code. -// No __attribute__ ((format (printf, 1, 2)) here because %q isn't supported. -void sersendf_P(PGM_P format_P, ...); + Deprecated macro? Convenience macro? Dunno. +*/ +#define sersendf_P(...) sendf_P(serial_writechar, __VA_ARGS__) #endif /* _SERSENDF_H */ diff --git a/usb_serial.c b/usb_serial.c index 8c6bfc8..1b0b713 100644 --- a/usb_serial.c +++ b/usb_serial.c @@ -1,17 +1,17 @@ /* USB Serial Example for Teensy USB Development Board * http://www.pjrc.com/teensy/usb_serial.html * Copyright (c) 2008,2010,2011 PJRC.COM, LLC - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -310,7 +310,7 @@ static uint8_t transmit_previous_timeout=0; // serial port settings (baud rate, control signals, etc) set // by the PC. These are ignored, but kept in RAM. -static union{ +static union{ uint8_t bytes[7]; uint32_t baud; } cdc_line_coding={{0x00, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x08}}; static uint8_t cdc_line_rtsdtr=0; @@ -366,7 +366,7 @@ int16_t usb_serial_getchar(void) if (c & (1<