diff --git a/libraries/FastSerial/BetterStream.cpp b/libraries/FastSerial/BetterStream.cpp new file mode 100644 index 0000000000..c8b80ecf20 --- /dev/null +++ b/libraries/FastSerial/BetterStream.cpp @@ -0,0 +1,86 @@ +// -*- Mode: C++; c-basic-offset: 8; indent-tabs-mode: nil -*- +// +// Copyright (c) 2010 Michael Smith. All rights reserved. +// +// This is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the +// Free Software Foundation; either version 2.1 of the License, or (at +// your option) any later version. +// + +// +// Enhancements to the Arduino Stream class. +// + +#include "BetterStream.h" + +// Stream extensions//////////////////////////////////////////////////////////// + +void +BetterStream::print_P(const prog_char *s) +{ + char c; + + while ('\0' != (c = pgm_read_byte(s++))) + write(c); +} + +void +BetterStream::println_P(const char *s) +{ + print_P(s); + println(); +} + +// STDIO emulation ///////////////////////////////////////////////////////////// + +int +BetterStream::_putchar(char c, FILE *stream) +{ + BetterStream *bs; + + bs = (BetterStream *)fdev_get_udata(stream); + if ('\n' == c) + bs->write('\r'); // ASCII translation on the cheap + bs->write(c); + return(0); +} + +int +BetterStream::_getchar(FILE *stream) +{ + BetterStream *bs; + + bs = (BetterStream *)fdev_get_udata(stream); + + // We return -1 if there is nothing to read, which the library interprets + // as an error, which our clients will need to deal with. + return(bs->read()); +} + +int +BetterStream::printf(const char *fmt, ...) +{ + va_list ap; + int i; + + va_start(ap, fmt); + i = vfprintf(&fd, fmt, ap); + va_end(ap); + + return(i); +} + +int +BetterStream::printf_P(const char *fmt, ...) +{ + va_list ap; + int i; + + va_start(ap, fmt); + i = vfprintf_P(&fd, fmt, ap); + va_end(ap); + + return(i); +} + diff --git a/libraries/FastSerial/BetterStream.h b/libraries/FastSerial/BetterStream.h new file mode 100644 index 0000000000..76956a6858 --- /dev/null +++ b/libraries/FastSerial/BetterStream.h @@ -0,0 +1,38 @@ +// -*- Mode: C++; c-basic-offset: 8; indent-tabs-mode: nil -*- +// +// Copyright (c) 2010 Michael Smith. All rights reserved. +// +// This is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the +// Free Software Foundation; either version 2.1 of the License, or (at +// your option) any later version. +// + +#include +#include + +class BetterStream : public Stream { +public: + BetterStream(void) { + // init stdio + fdev_setup_stream(&fd, &BetterStream::_putchar, &BetterStream::_getchar, _FDEV_SETUP_RW); + fdev_set_udata(&fd, this); + } + + // Stream extensions + void print_P(const char *s); + void println_P(const char *s); + + // stdio extensions + int printf(const char *fmt, ...); + int printf_P(const char *fmt, ...); + +protected: + // subclasses can use this to e.g. set up stdin/stdout/stderr. + FILE fd; + +private: + // stdio emulation + static int _putchar(char c, FILE *stream); + static int _getchar(FILE *stream); +}; diff --git a/libraries/FastSerial/FastSerial.cpp b/libraries/FastSerial/FastSerial.cpp index d88d4cc108..68b50082fe 100644 --- a/libraries/FastSerial/FastSerial.cpp +++ b/libraries/FastSerial/FastSerial.cpp @@ -102,13 +102,10 @@ FastSerial::FastSerial(const uint8_t portNumber, _txBuffer = &__FastSerial__txBuffer[portNumber]; _rxBuffer->head = _rxBuffer->tail = 0; - // init stdio - fdev_setup_stream(&_fd, &FastSerial::_putchar, &FastSerial::_getchar, _FDEV_SETUP_RW); - fdev_set_udata(&_fd, this); if (0 == portNumber) { - stdout = &_fd; // serial port 0 is always the default console - stdin = &_fd; - stderr = &_fd; + stdout = &fd; // serial port 0 is always the default console + stdin = &fd; + stderr = &fd; } } @@ -259,58 +256,6 @@ FastSerial::write(uint8_t c) *_ucsrb |= _portTxBits; } -// STDIO emulation ///////////////////////////////////////////////////////////// - -int -FastSerial::_putchar(char c, FILE *stream) -{ - FastSerial *fs; - - fs = (FastSerial *)fdev_get_udata(stream); - if ('\n' == c) - fs->write('\r'); // ASCII translation on the cheap - fs->write(c); - return(0); -} - -int -FastSerial::_getchar(FILE *stream) -{ - FastSerial *fs; - - fs = (FastSerial *)fdev_get_udata(stream); - - // We return -1 if there is nothing to read, which the library interprets - // as an error, which our clients will need to deal with. - return(fs->read()); -} - -int -FastSerial::printf(const char *fmt, ...) -{ - va_list ap; - int i; - - va_start(ap, fmt); - i = vfprintf(&_fd, fmt, ap); - va_end(ap); - - return(i); -} - -int -FastSerial::printf_P(const char *fmt, ...) -{ - va_list ap; - int i; - - va_start(ap, fmt); - i = vfprintf_P(&_fd, fmt, ap); - va_end(ap); - - return(i); -} - // Buffer management /////////////////////////////////////////////////////////// bool diff --git a/libraries/FastSerial/FastSerial.h b/libraries/FastSerial/FastSerial.h index 96ed468cbc..8524a2fbee 100644 --- a/libraries/FastSerial/FastSerial.h +++ b/libraries/FastSerial/FastSerial.h @@ -50,9 +50,10 @@ #include #include #include -#include #include +#include "BetterStream.h" + // // Because Arduino libraries aren't really libraries, but we want to // only define interrupt handlers for serial ports that are actually @@ -82,8 +83,7 @@ extern class FastSerial Serial1; extern class FastSerial Serial2; extern class FastSerial Serial3; - -class FastSerial : public Stream { +class FastSerial : public BetterStream { public: FastSerial(const uint8_t portNumber, volatile uint8_t *ubrrh, @@ -96,19 +96,14 @@ public: const uint8_t portTxBits); // Serial API - void begin(long baud); - void begin(long baud, unsigned int rxSpace, unsigned int txSpace); - void end(void); - int available(void); - int read(void); - void flush(void); - void write(uint8_t c); - using Stream::write; - - // stdio extensions - int printf(const char *fmt, ...); - int printf_P(const char *fmt, ...); - FILE *getfd(void) { return &_fd; }; + virtual void begin(long baud); + virtual void begin(long baud, unsigned int rxSpace, unsigned int txSpace); + virtual void end(void); + virtual int available(void); + virtual int read(void); + virtual void flush(void); + virtual void write(uint8_t c); + using BetterStream::write; // public so the interrupt handlers can see it struct Buffer { @@ -137,11 +132,6 @@ private: bool _allocBuffer(Buffer *buffer, unsigned int size); void _freeBuffer(Buffer *buffer); - - // stdio emulation - FILE _fd; - static int _putchar(char c, FILE *stream); - static int _getchar(FILE *stream); }; // Used by the per-port interrupt vectors diff --git a/libraries/FastSerial/examples/FastSerial/FastSerial.pde b/libraries/FastSerial/examples/FastSerial/FastSerial.pde index e752e5c099..c3483e5b51 100644 --- a/libraries/FastSerial/examples/FastSerial/FastSerial.pde +++ b/libraries/FastSerial/examples/FastSerial/FastSerial.pde @@ -38,6 +38,8 @@ void setup(void) // And send a message. // Serial.println("begin"); + Serial.printf("printf\n"); + Serial.println_P(PSTR("progmem")); } void