Skip to content
Snippets Groups Projects
Commit dd5ca68c authored by Bernhard's avatar Bernhard
Browse files

get rid of indirect ringbuffer calls, made some inlines, removed virtual and...

get rid of indirect ringbuffer calls, made some inlines, removed virtual and streaming class requirements.
parent dd5296ad
Branches
Tags
No related merge requests found
......@@ -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)
/// 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
......
......@@ -23,15 +23,30 @@
#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;
......@@ -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<<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)
......
......@@ -17,6 +17,8 @@
* along with the Arduino SdFat Library. If not, see
* <http://www.gnu.org/licenses/>.
*/
#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
......
......@@ -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);
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);
......@@ -369,8 +366,6 @@ class SdBaseFile {
// to be deleted
static void printDirName( const dir_t& dir,
uint8_t width, bool printSlash);
static void printDirName(Print* pr, const dir_t& dir,
uint8_t width, bool printSlash);
//------------------------------------------------------------------------------
// Deprecated functions - suppress cpplint warnings with NOLINT comment
#if ALLOW_DEPRECATED_FUNCTIONS && !defined(DOXYGEN)
......
......@@ -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);
}
......@@ -38,8 +38,8 @@
namespace SdFatUtil {
int FreeRam();
void print_P(Print* pr, PGM_P str);
void println_P(Print* pr, PGM_P str);
void print_P( PGM_P str);
void println_P( PGM_P str);
void SerialPrint_P(PGM_P str);
void SerialPrintln_P(PGM_P str);
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment