#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;
}
}
#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;
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;
}
}
// 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)
+
+
+
+/// imports from print.h
+/* default implementation: may be overridden */
+void MarlinSerial::write(const char *str)
{
- while (!((*_ucsra) & (1 << _udre)))
- ;
+ while (*str)
+ write(*str++);
+}
- *_udr = c;
+/* default implementation: may be overridden */
+void MarlinSerial::write(const uint8_t *buffer, size_t size)
+{
+ while (size--)
+ write(*buffer++);
}
-void MarlinSerial::checkRx()
+void MarlinSerial::print(const String &s)
{
- if((UCSR0A & (1<<RXC0)) != 0) {
- unsigned char c = UDR0;
- store_char(c, &rx_buffer);
+ for (int i = 0; i < s.length(); i++) {
+ write(s[i]);
}
}
+void MarlinSerial::print(const char str[])
+{
+ write(str);
+}
+
+void MarlinSerial::print(char c, int base)
+{
+ print((long) c, base);
+}
+
+void MarlinSerial::print(unsigned char b, int base)
+{
+ print((unsigned long) b, base);
+}
+
+void MarlinSerial::print(int n, int base)
+{
+ print((long) n, base);
+}
+
+void MarlinSerial::print(unsigned int n, int base)
+{
+ print((unsigned long) n, base);
+}
+
+void MarlinSerial::print(long n, int base)
+{
+ if (base == 0) {
+ write(n);
+ } else if (base == 10) {
+ if (n < 0) {
+ print('-');
+ n = -n;
+ }
+ printNumber(n, 10);
+ } else {
+ printNumber(n, base);
+ }
+}
+
+void MarlinSerial::print(unsigned long n, int base)
+{
+ if (base == 0) write(n);
+ else printNumber(n, base);
+}
+
+void MarlinSerial::print(double n, int digits)
+{
+ printFloat(n, digits);
+}
+
+void MarlinSerial::println(void)
+{
+ print('\r');
+ print('\n');
+}
+
+void MarlinSerial::println(const String &s)
+{
+ print(s);
+ println();
+}
+
+void MarlinSerial::println(const char c[])
+{
+ print(c);
+ println();
+}
+
+void MarlinSerial::println(char c, int base)
+{
+ print(c, base);
+ println();
+}
+
+void MarlinSerial::println(unsigned char b, int base)
+{
+ print(b, base);
+ println();
+}
+
+void MarlinSerial::println(int n, int base)
+{
+ print(n, base);
+ println();
+}
+
+void MarlinSerial::println(unsigned int n, int base)
+{
+ print(n, base);
+ println();
+}
+
+void MarlinSerial::println(long n, int base)
+{
+ print(n, base);
+ println();
+}
+
+void MarlinSerial::println(unsigned long n, int base)
+{
+ print(n, base);
+ println();
+}
+
+void MarlinSerial::println(double n, int digits)
+{
+ print(n, digits);
+ println();
+}
+
+// Private Methods /////////////////////////////////////////////////////////////
+
+void MarlinSerial::printNumber(unsigned long n, uint8_t base)
+{
+ unsigned char buf[8 * sizeof(long)]; // Assumes 8-bit chars.
+ unsigned long i = 0;
+
+ if (n == 0) {
+ print('0');
+ return;
+ }
+
+ while (n > 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<digits; ++i)
+ rounding /= 10.0;
+
+ number += rounding;
+
+ // Extract the integer part of the number and print it
+ unsigned long int_part = (unsigned long)number;
+ double remainder = number - (double)int_part;
+ print(int_part);
+
+ // Print the decimal point, but only if there are digits beyond
+ if (digits > 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
#define MarlinSerial_h
#include <inttypes.h>
+#include <Stream.h>
-#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;
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<<RXC0)) != 0) {
+ unsigned char c = UDR0;
+ 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;
+ }
+ }
+ }
+
+
+ private:
+ void printNumber(unsigned long, uint8_t);
+ void printFloat(double, uint8_t);
+
+
+ public:
+ void write(const char *str);
+ void write( const uint8_t *buffer, size_t size);
+
+ void print(const String &);
+ void print(const char[]);
+ void print(char, int = BYTE);
+ void print(unsigned char, int = BYTE);
+ void print(int, int = DEC);
+ void print(unsigned int, int = DEC);
+ void print(long, int = DEC);
+ void print(unsigned long, int = DEC);
+ void print(double, int = 2);
+
+ void println(const String &s);
+ void println(const char[]);
+ void println(char, int = BYTE);
+ void println(unsigned char, int = BYTE);
+ void println(int, int = DEC);
+ void println(unsigned int, int = DEC);
+ void println(long, int = DEC);
+ void println(unsigned long, int = DEC);
+ void println(double, int = 2);
+ void println(void);
};
#if defined(UBRRH) || defined(UBRR0H)
* along with the Arduino SdFat Library. If not, see
* <http://www.gnu.org/licenses/>.
*/
+
+#define SERIAL MSerial
#include "SdBaseFile.h"
//------------------------------------------------------------------------------
// pointer to cwd directory
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.
*
* \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));
}
}
//------------------------------------------------------------------------------
// 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;
&& 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;
}
//------------------------------------------------------------------------------
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.
* \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.
*
* \param[in] fatDate The date field from a directory entry.
*/
-void SdBaseFile::printFatDate(uint16_t fatDate) {
- printFatDate(&MSerial, fatDate);
-}
+
//------------------------------------------------------------------------------
/** %Print a directory date field.
*
* \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.
*
* \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
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) {
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);
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);
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
* \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.
* \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.
* \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.
* \param[in] str Pointer to string stored in flash memory.
*/
void SdFatUtil::SerialPrintln_P(PGM_P str) {
- println_P(&MSerial, str);
+ println_P( str);
}
-/* 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
- * <http://www.gnu.org/licenses/>.
- */
-#ifndef SdFatUtil_h
-#define SdFatUtil_h
-/**
- * \file
- * \brief Useful utility functions.
- */
-#include <avr/pgmspace.h>
-#if ARDUINO < 100
-#define HardwareSerial_h // trick to disable the standard HWserial
-#include <WProgram.h>
-#include "MarlinSerial.h"
-#else // ARDUINO
-#include <Arduino.h>
-#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\r
+ * Copyright (C) 2008 by William Greiman\r
+ *\r
+ * This file is part of the Arduino SdFat Library\r
+ *\r
+ * This Library is free software: you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation, either version 3 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * This Library is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with the Arduino SdFat Library. If not, see\r
+ * <http://www.gnu.org/licenses/>.\r
+ */\r
+#ifndef SdFatUtil_h\r
+#define SdFatUtil_h\r
+/**\r
+ * \file\r
+ * \brief Useful utility functions.\r
+ */\r
+#include <avr/pgmspace.h>\r
+#if ARDUINO < 100\r
+#define HardwareSerial_h // trick to disable the standard HWserial\r
+#include <WProgram.h>\r
+#include "MarlinSerial.h"\r
+#else // ARDUINO\r
+#include <Arduino.h>\r
+#endif // ARDUINO\r
+/** Store and print a string in flash memory.*/\r
+#define PgmPrint(x) SerialPrint_P(PSTR(x))\r
+/** Store and print a string in flash memory followed by a CR/LF.*/\r
+#define PgmPrintln(x) SerialPrintln_P(PSTR(x))\r
+\r
+namespace SdFatUtil {\r
+ int FreeRam();\r
+ void print_P( PGM_P str);\r
+ void println_P( PGM_P str);\r
+ void SerialPrint_P(PGM_P str);\r
+ void SerialPrintln_P(PGM_P str);\r
+}\r
+\r
+using namespace SdFatUtil; // NOLINT\r
#endif // #define SdFatUtil_h\r