diff --git a/Marlin/MarlinSerial.cpp b/Marlin/MarlinSerial.cpp index fade8b293f..34ae6d7676 100644 --- a/Marlin/MarlinSerial.cpp +++ b/Marlin/MarlinSerial.cpp @@ -33,35 +33,25 @@ #include "MarlinSerial.h" -// Define constants and variables for buffering incoming serial data. We're -// using a ring buffer (I think), in which rx_buffer_head is the index of the -// location to which to write the next incoming character and rx_buffer_tail -// is the index of the location from which to read. -#define RX_BUFFER_SIZE 128 -struct ring_buffer -{ - unsigned char buffer[RX_BUFFER_SIZE]; - int head; - int tail; -}; + #if defined(UBRRH) || defined(UBRR0H) ring_buffer rx_buffer = { { 0 }, 0, 0 }; #endif -inline void store_char(unsigned char c, ring_buffer *rx_buffer) +inline void store_char(unsigned char c) { - int i = (unsigned int)(rx_buffer->head + 1) % RX_BUFFER_SIZE; + int i = (unsigned int)(rx_buffer.head + 1) % RX_BUFFER_SIZE; // if we should be storing the received character into the location // just before the tail (meaning that the head would advance to the // current location of the tail), we're about to overflow the buffer // and so we don't write the character or advance the head. - if (i != rx_buffer->tail) { - rx_buffer->buffer[rx_buffer->head] = c; - rx_buffer->head = i; + if (i != rx_buffer.tail) { + rx_buffer.buffer[rx_buffer.head] = c; + rx_buffer.head = i; } } @@ -79,19 +69,18 @@ inline void store_char(unsigned char c, ring_buffer *rx_buffer) #else #error UDR not defined #endif - store_char(c, &rx_buffer); + store_char(c); } #endif // Constructors //////////////////////////////////////////////////////////////// -MarlinSerial::MarlinSerial(ring_buffer *rx_buffer, +MarlinSerial::MarlinSerial( volatile uint8_t *ubrrh, volatile uint8_t *ubrrl, volatile uint8_t *ucsra, volatile uint8_t *ucsrb, volatile uint8_t *udr, uint8_t rxen, uint8_t txen, uint8_t rxcie, uint8_t udre, uint8_t u2x) { - _rx_buffer = rx_buffer; _ubrrh = ubrrh; _ubrrl = ubrrl; _ucsra = ucsra; @@ -144,28 +133,25 @@ void MarlinSerial::end() cbi(*_ucsrb, _rxcie); } -int MarlinSerial::available(void) -{ - return (unsigned int)(RX_BUFFER_SIZE + _rx_buffer->head - _rx_buffer->tail) % RX_BUFFER_SIZE; -} + int MarlinSerial::peek(void) { - if (_rx_buffer->head == _rx_buffer->tail) { + if (rx_buffer.head == rx_buffer.tail) { return -1; } else { - return _rx_buffer->buffer[_rx_buffer->tail]; + return rx_buffer.buffer[rx_buffer.tail]; } } int MarlinSerial::read(void) { // if the head isn't ahead of the tail, we don't have any characters - if (_rx_buffer->head == _rx_buffer->tail) { + if (rx_buffer.head == rx_buffer.tail) { return -1; } else { - unsigned char c = _rx_buffer->buffer[_rx_buffer->tail]; - _rx_buffer->tail = (unsigned int)(_rx_buffer->tail + 1) % RX_BUFFER_SIZE; + unsigned char c = rx_buffer.buffer[rx_buffer.tail]; + rx_buffer.tail = (unsigned int)(rx_buffer.tail + 1) % RX_BUFFER_SIZE; return c; } } @@ -181,29 +167,207 @@ void MarlinSerial::flush() // the value to rx_buffer_tail; the previous value of rx_buffer_head // may be written to rx_buffer_tail, making it appear as if the buffer // were full, not empty. - _rx_buffer->head = _rx_buffer->tail; + rx_buffer.head = rx_buffer.tail; } -void MarlinSerial::write(uint8_t c) -{ - while (!((*_ucsra) & (1 << _udre))) - ; - *_udr = c; + + +/// imports from print.h +/* default implementation: may be overridden */ +void MarlinSerial::write(const char *str) +{ + while (*str) + write(*str++); } -void MarlinSerial::checkRx() +/* default implementation: may be overridden */ +void MarlinSerial::write(const uint8_t *buffer, size_t size) { - if((UCSR0A & (1< 0) { + buf[i++] = n % base; + n /= base; + } + + for (; i > 0; i--) + print((char) (buf[i - 1] < 10 ? + '0' + buf[i - 1] : + 'A' + buf[i - 1] - 10)); +} + +void MarlinSerial::printFloat(double number, uint8_t digits) +{ + // Handle negative numbers + if (number < 0.0) + { + print('-'); + number = -number; + } + + // Round correctly so that print(1.999, 2) prints as "2.00" + double rounding = 0.5; + for (uint8_t i=0; i 0) + print("."); + + // Extract digits from the remainder one at a time + while (digits-- > 0) + { + remainder *= 10.0; + int toPrint = int(remainder); + print(toPrint); + remainder -= toPrint; + } +} + // Preinstantiate Objects ////////////////////////////////////////////////////// #if defined(UBRR0H) && defined(UBRR0L) - MarlinSerial MSerial(&rx_buffer, &UBRR0H, &UBRR0L, &UCSR0A, &UCSR0B, &UDR0, RXEN0, TXEN0, RXCIE0, UDRE0, U2X0); + MarlinSerial MSerial( &UBRR0H, &UBRR0L, &UCSR0A, &UCSR0B, &UDR0, RXEN0, TXEN0, RXCIE0, UDRE0, U2X0); #else #error no serial port defined (port 0) #endif diff --git a/Marlin/MarlinSerial.h b/Marlin/MarlinSerial.h index 79454492a6..3c7381ad13 100644 --- a/Marlin/MarlinSerial.h +++ b/Marlin/MarlinSerial.h @@ -23,15 +23,30 @@ #define MarlinSerial_h #include +#include -#include "Stream.h" -struct ring_buffer; +// Define constants and variables for buffering incoming serial data. We're +// using a ring buffer (I think), in which rx_buffer_head is the index of the +// location to which to write the next incoming character and rx_buffer_tail +// is the index of the location from which to read. +#define RX_BUFFER_SIZE 128 -class MarlinSerial : public Stream + +struct ring_buffer +{ + unsigned char buffer[RX_BUFFER_SIZE]; + int head; + int tail; +}; + +#if defined(UBRRH) || defined(UBRR0H) + extern ring_buffer rx_buffer; +#endif + +class MarlinSerial //: public Stream { private: - ring_buffer *_rx_buffer; volatile uint8_t *_ubrrh; volatile uint8_t *_ubrrl; volatile uint8_t *_ucsra; @@ -43,20 +58,76 @@ class MarlinSerial : public Stream uint8_t _udre; uint8_t _u2x; public: - MarlinSerial(ring_buffer *rx_buffer, + MarlinSerial( volatile uint8_t *ubrrh, volatile uint8_t *ubrrl, volatile uint8_t *ucsra, volatile uint8_t *ucsrb, volatile uint8_t *udr, uint8_t rxen, uint8_t txen, uint8_t rxcie, uint8_t udre, uint8_t u2x); void begin(long); void end(); - virtual int available(void); - virtual int peek(void); - virtual int read(void); - virtual void flush(void); - virtual void write(uint8_t); - virtual void checkRx(void); - using Print::write; // pull in write(str) and write(buf, size) from Print + inline int available(void) + { + return (unsigned int)(RX_BUFFER_SIZE + rx_buffer.head - rx_buffer.tail) % RX_BUFFER_SIZE; + } + int peek(void); + int read(void); + void flush(void); + inline void write(uint8_t c) + { + while (!((*_ucsra) & (1 << _udre))) + ; + + *_udr = c; + } + + + inline void checkRx(void) + { + if((UCSR0A & (1<. */ + +#define SERIAL MSerial #include "SdBaseFile.h" //------------------------------------------------------------------------------ // pointer to cwd directory @@ -294,20 +296,7 @@ void SdBaseFile::getpos(fpos_t* pos) { pos->position = curPosition_; pos->cluster = curCluster_; } -//------------------------------------------------------------------------------ -/** List directory contents to Serial. - * - * \param[in] flags The inclusive OR of - * - * LS_DATE - %Print file modification date - * - * LS_SIZE - %Print file size. - * - * LS_R - Recursive list of subdirectories. - */ -void SdBaseFile::ls(uint8_t flags) { - ls(&MSerial, flags, 0); -} + //------------------------------------------------------------------------------ /** List directory contents. * @@ -324,14 +313,14 @@ void SdBaseFile::ls(uint8_t flags) { * \param[in] indent Amount of space before file name. Used for recursive * list to indicate subdirectory level. */ -void SdBaseFile::ls(Print* pr, uint8_t flags, uint8_t indent) { +void SdBaseFile::ls(uint8_t flags, uint8_t indent) { rewind(); int8_t status; - while ((status = lsPrintNext(pr, flags, indent))) { + while ((status = lsPrintNext( flags, indent))) { if (status > 1 && (flags & LS_R)) { uint16_t index = curPosition()/32 - 1; SdBaseFile s; - if (s.open(this, index, O_READ)) s.ls(pr, flags, indent + 2); + if (s.open(this, index, O_READ)) s.ls( flags, indent + 2); seekSet(32 * (index + 1)); } } @@ -339,7 +328,7 @@ void SdBaseFile::ls(Print* pr, uint8_t flags, uint8_t indent) { //------------------------------------------------------------------------------ // saves 32 bytes on stack for ls recursion // return 0 - EOF, 1 - normal file, or 2 - directory -int8_t SdBaseFile::lsPrintNext(Print *pr, uint8_t flags, uint8_t indent) { +int8_t SdBaseFile::lsPrintNext( uint8_t flags, uint8_t indent) { dir_t dir; uint8_t w = 0; @@ -352,38 +341,38 @@ int8_t SdBaseFile::lsPrintNext(Print *pr, uint8_t flags, uint8_t indent) { && DIR_IS_FILE_OR_SUBDIR(&dir)) break; } // indent for dir level - for (uint8_t i = 0; i < indent; i++) pr->write(' '); + for (uint8_t i = 0; i < indent; i++) MSerial.write(' '); // print name for (uint8_t i = 0; i < 11; i++) { if (dir.name[i] == ' ')continue; if (i == 8) { - pr->write('.'); + MSerial.write('.'); w++; } - pr->write(dir.name[i]); + MSerial.write(dir.name[i]); w++; } if (DIR_IS_SUBDIR(&dir)) { - pr->write('/'); + MSerial.write('/'); w++; } if (flags & (LS_DATE | LS_SIZE)) { - while (w++ < 14) pr->write(' '); + while (w++ < 14) MSerial.write(' '); } // print modify date/time if requested if (flags & LS_DATE) { - pr->write(' '); - printFatDate(pr, dir.lastWriteDate); - pr->write(' '); - printFatTime(pr, dir.lastWriteTime); + MSerial.write(' '); + printFatDate( dir.lastWriteDate); + MSerial.write(' '); + printFatTime( dir.lastWriteTime); } // print size if requested if (!DIR_IS_SUBDIR(&dir) && (flags & LS_SIZE)) { - pr->write(' '); - pr->print(dir.fileSize); + MSerial.write(' '); + MSerial.print(dir.fileSize); } - pr->println(); + MSerial.println(); return DIR_IS_FILE(&dir) ? 1 : 2; } //------------------------------------------------------------------------------ @@ -940,17 +929,7 @@ int SdBaseFile::peek() { if (c >= 0) setpos(&pos); return c; } -//------------------------------------------------------------------------------ -/** %Print the name field of a directory entry in 8.3 format to Serial. - * - * \param[in] dir The directory structure containing the name. - * \param[in] width Blank fill name if length is less than \a width. - * \param[in] printSlash Print '/' after directory names if true. - */ -void SdBaseFile::printDirName(const dir_t& dir, - uint8_t width, bool printSlash) { - printDirName(&MSerial, dir, width, printSlash); -} + //------------------------------------------------------------------------------ /** %Print the name field of a directory entry in 8.3 format. * \param[in] pr Print stream for output. @@ -958,32 +937,32 @@ void SdBaseFile::printDirName(const dir_t& dir, * \param[in] width Blank fill name if length is less than \a width. * \param[in] printSlash Print '/' after directory names if true. */ -void SdBaseFile::printDirName(Print* pr, const dir_t& dir, +void SdBaseFile::printDirName(const dir_t& dir, uint8_t width, bool printSlash) { uint8_t w = 0; for (uint8_t i = 0; i < 11; i++) { if (dir.name[i] == ' ')continue; if (i == 8) { - pr->write('.'); + MSerial.write('.'); w++; } - pr->write(dir.name[i]); + MSerial.write(dir.name[i]); w++; } if (DIR_IS_SUBDIR(&dir) && printSlash) { - pr->write('/'); + MSerial.write('/'); w++; } while (w < width) { - pr->write(' '); + MSerial.write(' '); w++; } } //------------------------------------------------------------------------------ // print uint8_t with width 2 -static void print2u(Print* pr, uint8_t v) { - if (v < 10) pr->write('0'); - pr->print(v, DEC); +static void print2u( uint8_t v) { + if (v < 10) MSerial.write('0'); + MSerial.print(v, DEC); } //------------------------------------------------------------------------------ /** %Print a directory date field to Serial. @@ -992,9 +971,7 @@ static void print2u(Print* pr, uint8_t v) { * * \param[in] fatDate The date field from a directory entry. */ -void SdBaseFile::printFatDate(uint16_t fatDate) { - printFatDate(&MSerial, fatDate); -} + //------------------------------------------------------------------------------ /** %Print a directory date field. * @@ -1003,23 +980,14 @@ void SdBaseFile::printFatDate(uint16_t fatDate) { * \param[in] pr Print stream for output. * \param[in] fatDate The date field from a directory entry. */ -void SdBaseFile::printFatDate(Print* pr, uint16_t fatDate) { - pr->print(FAT_YEAR(fatDate)); - pr->write('-'); - print2u(pr, FAT_MONTH(fatDate)); - pr->write('-'); - print2u(pr, FAT_DAY(fatDate)); -} -//------------------------------------------------------------------------------ -/** %Print a directory time field to Serial. - * - * Format is hh:mm:ss. - * - * \param[in] fatTime The time field from a directory entry. - */ -void SdBaseFile::printFatTime(uint16_t fatTime) { - printFatTime(&MSerial, fatTime); +void SdBaseFile::printFatDate(uint16_t fatDate) { + MSerial.print(FAT_YEAR(fatDate)); + MSerial.write('-'); + print2u( FAT_MONTH(fatDate)); + MSerial.write('-'); + print2u( FAT_DAY(fatDate)); } + //------------------------------------------------------------------------------ /** %Print a directory time field. * @@ -1028,12 +996,12 @@ void SdBaseFile::printFatTime(uint16_t fatTime) { * \param[in] pr Print stream for output. * \param[in] fatTime The time field from a directory entry. */ -void SdBaseFile::printFatTime(Print* pr, uint16_t fatTime) { - print2u(pr, FAT_HOUR(fatTime)); - pr->write(':'); - print2u(pr, FAT_MINUTE(fatTime)); - pr->write(':'); - print2u(pr, FAT_SECOND(fatTime)); +void SdBaseFile::printFatTime( uint16_t fatTime) { + print2u( FAT_HOUR(fatTime)); + MSerial.write(':'); + print2u( FAT_MINUTE(fatTime)); + MSerial.write(':'); + print2u( FAT_SECOND(fatTime)); } //------------------------------------------------------------------------------ /** Print a file's name to Serial diff --git a/Marlin/SdBaseFile.h b/Marlin/SdBaseFile.h index e02ec3c7a5..e184acd968 100644 --- a/Marlin/SdBaseFile.h +++ b/Marlin/SdBaseFile.h @@ -270,8 +270,7 @@ class SdBaseFile { bool isRoot() const { return type_ == FAT_FILE_TYPE_ROOT_FIXED || type_ == FAT_FILE_TYPE_ROOT32; } - void ls(Print* pr, uint8_t flags = 0, uint8_t indent = 0); - void ls(uint8_t flags = 0); + void ls( uint8_t flags = 0, uint8_t indent = 0); bool mkdir(SdBaseFile* dir, const char* path, bool pFlag = true); // alias for backward compactability bool makeDir(SdBaseFile* dir, const char* path) { @@ -284,9 +283,7 @@ class SdBaseFile { bool openRoot(SdVolume* vol); int peek(); static void printFatDate(uint16_t fatDate); - static void printFatDate(Print* pr, uint16_t fatDate); - static void printFatTime(uint16_t fatTime); - static void printFatTime(Print* pr, uint16_t fatTime); + static void printFatTime( uint16_t fatTime); bool printName(); int16_t read(); int16_t read(void* buf, uint16_t nbyte); @@ -359,7 +356,7 @@ class SdBaseFile { bool addCluster(); bool addDirCluster(); dir_t* cacheDirEntry(uint8_t action); - int8_t lsPrintNext(Print *pr, uint8_t flags, uint8_t indent); + int8_t lsPrintNext( uint8_t flags, uint8_t indent); static bool make83Name(const char* str, uint8_t* name, const char** ptr); bool mkdir(SdBaseFile* parent, const uint8_t dname[11]); bool open(SdBaseFile* dirFile, const uint8_t dname[11], uint8_t oflag); @@ -367,9 +364,7 @@ class SdBaseFile { dir_t* readDirCache(); //------------------------------------------------------------------------------ // to be deleted - static void printDirName(const dir_t& dir, - uint8_t width, bool printSlash); - static void printDirName(Print* pr, const dir_t& dir, + static void printDirName( const dir_t& dir, uint8_t width, bool printSlash); //------------------------------------------------------------------------------ // Deprecated functions - suppress cpplint warnings with NOLINT comment diff --git a/Marlin/SdFatUtil.cpp b/Marlin/SdFatUtil.cpp index 7f82a7083b..0bf86f2956 100644 --- a/Marlin/SdFatUtil.cpp +++ b/Marlin/SdFatUtil.cpp @@ -43,8 +43,8 @@ int SdFatUtil::FreeRam() { * \param[in] pr Print object for output. * \param[in] str Pointer to string stored in flash memory. */ -void SdFatUtil::print_P(Print* pr, PGM_P str) { - for (uint8_t c; (c = pgm_read_byte(str)); str++) pr->write(c); +void SdFatUtil::print_P( PGM_P str) { + for (uint8_t c; (c = pgm_read_byte(str)); str++) MSerial.write(c); } //------------------------------------------------------------------------------ /** %Print a string in flash memory followed by a CR/LF. @@ -52,9 +52,9 @@ void SdFatUtil::print_P(Print* pr, PGM_P str) { * \param[in] pr Print object for output. * \param[in] str Pointer to string stored in flash memory. */ -void SdFatUtil::println_P(Print* pr, PGM_P str) { - print_P(pr, str); - pr->println(); +void SdFatUtil::println_P( PGM_P str) { + print_P( str); + MSerial.println(); } //------------------------------------------------------------------------------ /** %Print a string in flash memory to Serial. @@ -62,7 +62,7 @@ void SdFatUtil::println_P(Print* pr, PGM_P str) { * \param[in] str Pointer to string stored in flash memory. */ void SdFatUtil::SerialPrint_P(PGM_P str) { - print_P(&MSerial, str); + print_P(str); } //------------------------------------------------------------------------------ /** %Print a string in flash memory to Serial followed by a CR/LF. @@ -70,5 +70,5 @@ void SdFatUtil::SerialPrint_P(PGM_P str) { * \param[in] str Pointer to string stored in flash memory. */ void SdFatUtil::SerialPrintln_P(PGM_P str) { - println_P(&MSerial, str); + println_P( str); } diff --git a/Marlin/SdFatUtil.h b/Marlin/SdFatUtil.h index c49e77df85..6e3cb4936f 100644 --- a/Marlin/SdFatUtil.h +++ b/Marlin/SdFatUtil.h @@ -1,48 +1,48 @@ -/* Arduino SdFat Library - * Copyright (C) 2008 by William Greiman - * - * This file is part of the Arduino SdFat Library - * - * This Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with the Arduino SdFat Library. If not, see - * . - */ -#ifndef SdFatUtil_h -#define SdFatUtil_h -/** - * \file - * \brief Useful utility functions. - */ -#include -#if ARDUINO < 100 -#define HardwareSerial_h // trick to disable the standard HWserial -#include -#include "MarlinSerial.h" -#else // ARDUINO -#include -#endif // ARDUINO -/** Store and print a string in flash memory.*/ -#define PgmPrint(x) SerialPrint_P(PSTR(x)) -/** Store and print a string in flash memory followed by a CR/LF.*/ -#define PgmPrintln(x) SerialPrintln_P(PSTR(x)) - -namespace SdFatUtil { - int FreeRam(); - void print_P(Print* pr, PGM_P str); - void println_P(Print* pr, PGM_P str); - void SerialPrint_P(PGM_P str); - void SerialPrintln_P(PGM_P str); -} - -using namespace SdFatUtil; // NOLINT +/* Arduino SdFat Library + * Copyright (C) 2008 by William Greiman + * + * This file is part of the Arduino SdFat Library + * + * This Library is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This Library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with the Arduino SdFat Library. If not, see + * . + */ +#ifndef SdFatUtil_h +#define SdFatUtil_h +/** + * \file + * \brief Useful utility functions. + */ +#include +#if ARDUINO < 100 +#define HardwareSerial_h // trick to disable the standard HWserial +#include +#include "MarlinSerial.h" +#else // ARDUINO +#include +#endif // ARDUINO +/** Store and print a string in flash memory.*/ +#define PgmPrint(x) SerialPrint_P(PSTR(x)) +/** Store and print a string in flash memory followed by a CR/LF.*/ +#define PgmPrintln(x) SerialPrintln_P(PSTR(x)) + +namespace SdFatUtil { + int FreeRam(); + void print_P( PGM_P str); + void println_P( PGM_P str); + void SerialPrint_P(PGM_P str); + void SerialPrintln_P(PGM_P str); +} + +using namespace SdFatUtil; // NOLINT #endif // #define SdFatUtil_h