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.
This commit is contained in:
Markus Hitter 2016-04-25 02:45:24 +02:00
parent 6577578051
commit e633222cd3
15 changed files with 143 additions and 96 deletions

1
dda.c
View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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 */

View File

@ -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);
}

24
msg.h Normal file
View File

@ -0,0 +1,24 @@
#ifndef _SERMSG_H
#define _SERMSG_H
#include <stdint.h>
// 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 */

View File

@ -1,4 +1,3 @@
#include "sersendf.h"
/** \file sersendf.c
\brief Simplified printf implementation
@ -6,13 +5,18 @@
#include <stdarg.h>
#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);
}
}
}

11
sendf.h Normal file
View File

@ -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 */

View File

@ -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
}

View File

@ -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);

View File

@ -1,24 +1,22 @@
#ifndef _SERMSG_H
#define _SERMSG_H
#include <stdint.h>
#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 */
#endif /* _MSG_H */

View File

@ -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 */

View File

@ -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<<RXOUTI)) {
UEINTX = 0x6B;
goto retry;
}
}
SREG = intr_state;
return -1;
}
@ -407,19 +407,21 @@ void usb_serial_flush_input(void)
cli();
UENUM = CDC_RX_ENDPOINT;
while ((UEINTX & (1<<RWAL))) {
UEINTX = 0x6B;
UEINTX = 0x6B;
}
SREG = intr_state;
}
}
// transmit a character. 0 returned on success, -1 on error
int8_t usb_serial_putchar(uint8_t c)
{
/**
Transmit a character.
*/
void serial_writechar(uint8_t c) {
uint8_t timeout, intr_state;
// if we're not online (enumerated and configured), error
if (!usb_configuration) return -1;
if ( ! usb_configuration) return;
// interrupts are disabled so these functions can be
// used from the main program or interrupt context,
// even both in the same program!
@ -430,7 +432,7 @@ int8_t usb_serial_putchar(uint8_t c)
if (transmit_previous_timeout) {
if (!(UEINTX & (1<<RWAL))) {
SREG = intr_state;
return -1;
return;
}
transmit_previous_timeout = 0;
}
@ -444,10 +446,11 @@ int8_t usb_serial_putchar(uint8_t c)
// is not running an application that is listening
if (UDFNUML == timeout) {
transmit_previous_timeout = 1;
return -1;
return;
}
// has the USB gone offline?
if (!usb_configuration) return -1;
if ( ! usb_configuration)
return;
// get ready to try checking again
intr_state = SREG;
cli();
@ -459,12 +462,11 @@ int8_t usb_serial_putchar(uint8_t c)
if (!(UEINTX & (1<<RWAL))) UEINTX = 0x3A;
transmit_flush_timer = TRANSMIT_FLUSH_TIMEOUT;
SREG = intr_state;
return 0;
}
// transmit a character, but do not wait if the buffer is full,
// 0 returned on success, -1 on buffer full or error
// 0 returned on success, -1 on buffer full or error
int8_t usb_serial_putchar_nowait(uint8_t c)
{
uint8_t intr_state;

View File

@ -20,7 +20,7 @@ uint8_t usb_serial_available(void); // number of bytes in receive buffer
void usb_serial_flush_input(void); // discard any buffered input
// transmitting data
int8_t usb_serial_putchar(uint8_t c); // transmit a character
void serial_writechar(uint8_t c); // Transmit a character.
int8_t usb_serial_putchar_nowait(uint8_t c); // transmit a character, do not wait
int8_t usb_serial_write(const uint8_t *buffer, uint16_t size); // transmit a buffer
void usb_serial_flush_output(void); // immediately transmit any buffered output