diff --git a/Libraries/SerialPort/SerialPort.cpp b/Libraries/SerialPort/SerialPort.cpp
index 44b62db..909f641 100644
--- a/Libraries/SerialPort/SerialPort.cpp
+++ b/Libraries/SerialPort/SerialPort.cpp
@@ -17,9 +17,16 @@
* along with the Arduino SerialPort Library. If not, see
* .
*/
+/**
+ * @file
+ * @brief Serial Port class
+ */
#include
//------------------------------------------------------------------------------
-/** \return the number of bytes in the ring buffer */
+/** @return The number of bytes in the ring buffer.
+ *
+ * @note This function must not be called with interrupts disabled.
+ */
int SerialRingBuffer::available() {
uint8_t s = SREG;
cli();
@@ -28,7 +35,10 @@ int SerialRingBuffer::available() {
return n < 0 ? size_ + n : n;
}
//------------------------------------------------------------------------------
-/** Discard all data in the ring buffer. */
+/** Discard all data in the ring buffer.
+ *
+ * @note This function must not be called with interrupts disabled.
+ */
void SerialRingBuffer::flush() {
uint8_t s = SREG;
cli();
@@ -36,9 +46,10 @@ void SerialRingBuffer::flush() {
SREG = s;
}
//------------------------------------------------------------------------------
-/** get the next byte
- * \param[in] b location for the returned byte
- * \return true if a byte was returned or false if the ring buffer is empty
+/** Get the next byte from the ring buffer.
+ *
+ * @param[in] b location for the returned byte
+ * @return @c true if a byte was returned or @c false if the ring buffer is empty
*/
bool SerialRingBuffer::get(uint8_t* b) {
buf_size_t t = tail_;
@@ -50,12 +61,13 @@ bool SerialRingBuffer::get(uint8_t* b) {
//------------------------------------------------------------------------------
/**
* Get the maximum number of contiguous bytes from the ring buffer
- * with one call to memcpy. Do not use this function with interrupts
- * disabled.
+ * with one call to memcpy.
*
- * \param[in] b pointer to data
- * \param[in] n number of bytes to transfer from the ring buffer
- * \return number of bytes transferred
+ * @note This function must not be called with interrupts disabled.
+ *
+ * @param[in] b Pointer to the data.
+ * @param[in] n Number of bytes to transfer from the ring buffer.
+ * @return Number of bytes transferred.
*/
SerialRingBuffer::buf_size_t SerialRingBuffer::get(uint8_t* b, buf_size_t n) {
buf_size_t nr;
@@ -77,9 +89,9 @@ SerialRingBuffer::buf_size_t SerialRingBuffer::get(uint8_t* b, buf_size_t n) {
return nr;
}
//------------------------------------------------------------------------------
-/** initialize the ring buffer
- * \param[in] b buffer for data
- * \param[in] s size of the buffer
+/** Initialize the ring buffer.
+ * @param[in] b Buffer for the data.
+ * @param[in] s Size of the buffer.
*/
void SerialRingBuffer::init(uint8_t* b, buf_size_t s) {
buf_ = b;
@@ -87,20 +99,22 @@ void SerialRingBuffer::init(uint8_t* b, buf_size_t s) {
head_ = tail_ = 0;
}
//------------------------------------------------------------------------------
-/** peek at the next byte in the ring buffer
- * \return the next byte that would ber read or -1 if the ring buffer is empty
+/** Peek at the next byte in the ring buffer.
+ * @return The next byte that would be read or -1 if the ring buffer is empty.
*/
int SerialRingBuffer::peek() {
return empty() ? -1 : buf_[tail_];
}
//------------------------------------------------------------------------------
-/** put a byte into the ring buffer
- * \param[in] b the byte
- * \return true if byte was transferred or false if the ring buffer is full
+/** Put a byte into the ring buffer.
+ *
+ * @param[in] b the byte
+ * @return @c true if byte was transferred or
+ * @c false if the ring buffer is full.
*/
bool SerialRingBuffer::put(uint8_t b) {
buf_size_t h = head_;
- // OK to store here even if ring is full
+ // OK to store here even if ring is full.
buf_[h++] = b;
if (h >= size_) h = 0;
if (h == tail_) return false;
@@ -109,12 +123,14 @@ bool SerialRingBuffer::put(uint8_t b) {
}
//------------------------------------------------------------------------------
/**
- * Put the maximum number of contiguous bytes into the ring buffer
+ * Put the maximum number of contiguous bytes into the ring buffer.
* with one call to memcpy.
*
- * \param[in] b pointer to data
- * \param[in] n number of bytes to transfer to the ring buffer
- * \return number of bytes transferred
+ * @note This function must not be called with interrupts disabled.
+ *
+ * @param[in] b pointer to data.
+ * @param[in] n number of bytes to transfer to the ring buffer.
+ * @return number of bytes transferred.
*/
SerialRingBuffer::buf_size_t
SerialRingBuffer::put(const uint8_t* b, buf_size_t n) {
@@ -137,12 +153,14 @@ SerialRingBuffer::buf_size_t
}
//------------------------------------------------------------------------------
/**
- * Put the maximum number of contiguous bytes into the ring buffer
+ * Put the maximum number of contiguous bytes into the ring buffer.
* with one call to memcpy.
*
- * \param[in] b pointer to data
- * \param[in] n number of bytes to transfer to the ring buffer
- * \return number of bytes transferred
+ * @note This function must not be called with interrupts disabled.
+ *
+ * @param[in] b pointer to data.
+ * @param[in] n number of bytes to transfer to the ring buffer.
+ * @return number of bytes transferred.
*/
SerialRingBuffer::buf_size_t SerialRingBuffer::put_P(PGM_P b, buf_size_t n) {
cli();
@@ -190,19 +208,25 @@ inline static void rx_isr(uint8_t n) {
// SerialRingBuffer rxbuf0;
#if defined(USART_RX_vect)
ISR(USART_RX_vect) {
-#elif defined(SIG_USART0_RECV)
-ISR(SIG_USART0_RECV) {
-#elif defined(SIG_UART0_RECV)
-ISR(SIG_UART0_RECV) {
-#elif defined(USART0_RX_vect)
-ISR(USART0_RX_vect) {
-#elif defined(SIG_UART_RECV)
-ISR(SIG_UART_RECV) {
-#else // vector
-#error No ISR rx vector for UART0
-#endif // vector
rx_isr(0);
}
+#elif defined(SIG_USART0_RECV)
+ISR(SIG_USART0_RECV) {
+ rx_isr(0);
+}
+#elif defined(SIG_UART0_RECV)
+ISR(SIG_UART0_RECV) {
+ rx_isr(0);
+}
+#elif defined(USART0_RX_vect)
+ISR(USART0_RX_vect) {
+ rx_isr(0);
+}
+#elif defined(SIG_UART_RECV)
+ISR(SIG_UART_RECV) {
+ rx_isr(0);
+}
+#endif // vector USART0
#ifdef USART1_RX_vect
ISR(USART1_RX_vect) {
rx_isr(1);
@@ -237,17 +261,22 @@ inline static void tx_isr(uint8_t n) {
}
#if defined(UART0_UDRE_vect)
ISR(UART0_UDRE_vect) {
-#elif defined(UART_UDRE_vect)
-ISR(UART_UDRE_vect) {
-#elif defined(USART0_UDRE_vect)
-ISR(USART0_UDRE_vect) {
-#elif defined(USART_UDRE_vect)
-ISR(USART_UDRE_vect) {
-#else
-#error N0 ISR tx vector for UART0
-#endif
tx_isr(0);
}
+#elif defined(UART_UDRE_vect)
+ISR(UART_UDRE_vect) {
+ tx_isr(0);
+}
+#elif defined(USART0_UDRE_vect)
+ISR(USART0_UDRE_vect) {
+ tx_isr(0);
+}
+#elif defined(USART_UDRE_vect)
+ISR(USART_UDRE_vect) {
+ tx_isr(0);
+}
+#endif // USART0 TX
+
#ifdef USART1_UDRE_vect
ISR(USART1_UDRE_vect) {
tx_isr(1);
diff --git a/Libraries/SerialPort/SerialPort.h b/Libraries/SerialPort/SerialPort.h
index 3efeec2..4f028ad 100644
--- a/Libraries/SerialPort/SerialPort.h
+++ b/Libraries/SerialPort/SerialPort.h
@@ -1,5 +1,5 @@
/* Arduino SerialPort Library
- * Copyright (C) 2011 by William Greiman
+ * Copyright (C) 2012 by William Greiman
*
* This file is part of the Arduino SerialPort Library
*
@@ -17,18 +17,19 @@
* along with the Arduino SerialPort Library. If not, see
* .
*/
- /**
- * \file
- * \brief SerialPort class
+/**
+ * @file
+ * @brief Serial Port class
*/
#ifndef SerialPort_h
#define SerialPort_h
//------------------------------------------------------------------------------
/** SerialPort version YYYYMMDD */
-#define SERIAL_PORT_VERSION 20120106
+#define SERIAL_PORT_VERSION 20140216
//------------------------------------------------------------------------------
/**
* Set ALLOW_LARGE_BUFFERS to zero to limit buffer sizes to 254 bytes.
+ *
* ALLOW_LARGE_BUFFERS controls whether uint16_t or uint8_t will be
* used for buffer indices.
*/
@@ -36,13 +37,15 @@
//------------------------------------------------------------------------------
/**
* Set USE_WRITE_OVERRIDES to zero to use the Arduino Print version
- * of write(const char*) and write(const uint8_t*, size_t). This will
- * save some flash but is much slower.
+ * of write(const char*) and write(const uint8_t*, size_t).
+ *
+ * This will save some flash but is much slower.
*/
#define USE_WRITE_OVERRIDES 1
//------------------------------------------------------------------------------
/**
* Set BUFFERED_RX zero to save flash and RAM if no RX buffering is used.
+ *
* RxBufSize must be zero in all SerialPort constructors if
* BUFFERED_RX is zero.
*/
@@ -50,6 +53,7 @@
//------------------------------------------------------------------------------
/**
* Set BUFFERED_TX zero to save flash and RAM if no TX buffering is used.
+ *
* TxBufSize must be zero in all SerialPort constructors if
* BUFFERED_TX is zero.
*/
@@ -72,14 +76,7 @@
//------------------------------------------------------------------------------
#include
#include
-#if ARDUINO < 100
-#include
-class __FlashStringHelper;
-#define F(string_literal)\
- (reinterpret_cast<__FlashStringHelper *>(PSTR(string_literal)))
-#else // ARDUINO < 100
#include
-#endif // ARDUINO < 100
//------------------------------------------------------------------------------
#if defined(UCSR3A)
static const uint8_t SERIAL_PORT_COUNT = 4;
@@ -90,11 +87,11 @@ static const uint8_t SERIAL_PORT_COUNT = 2;
#elif defined(UCSR0A) || defined(UCSRA)
static const uint8_t SERIAL_PORT_COUNT = 1;
#else
-#error no serial ports
+#error no serial ports.
#endif
//------------------------------------------------------------------------------
#ifdef UCSR0A
-// bits in UCSRA
+// Bits in UCSRA.
static const uint8_t M_RXC = 1 << RXC0;
static const uint8_t M_TXC = 1 << TXC0;
static const uint8_t M_UDRE = 1 << UDRE0;
@@ -102,20 +99,20 @@ static const uint8_t M_FE = 1 << FE0;
static const uint8_t M_DOR = 1 << DOR0;
static const uint8_t M_UPE = 1 << UPE0;
static const uint8_t M_U2X = 1 << U2X0;
-// bits in UCSRB
+// Bits in UCSRB.
static const uint8_t M_RXCIE = 1 << RXCIE0;
static const uint8_t M_TXCIE = 1 << TXCIE0;
static const uint8_t M_UDRIE = 1 << UDRIE0;
static const uint8_t M_RXEN = 1 << RXEN0;
static const uint8_t M_TXEN = 1 << TXEN0;
-// bits in UCSRC
+// Bits in UCSRC.
static const uint8_t M_UPM0 = 1 << UPM00;
static const uint8_t M_UPM1 = 1 << UPM01;
static const uint8_t M_USBS = 1 << USBS0;
static const uint8_t M_UCSZ0 = 1 << UCSZ00;
static const uint8_t M_UCSZ1 = 1 << UCSZ01;
#elif defined(UCSRA) // UCSR0A
-// bits in UCSRA
+// Bits in UCSRA.
static const uint8_t M_RXC = 1 << RXC;
static const uint8_t M_TXC = 1 << TXC;
static const uint8_t M_UDRE = 1 << UDRE;
@@ -123,67 +120,91 @@ static const uint8_t M_FE = 1 << FE;
static const uint8_t M_DOR = 1 << DOR;
static const uint8_t M_UPE = 1 << PE;
static const uint8_t M_U2X = 1 << U2X;
-// bits in UCSRB
+// Bits in UCSRB.
static const uint8_t M_RXCIE = 1 << RXCIE;
static const uint8_t M_TXCIE = 1 << TXCIE;
static const uint8_t M_UDRIE = 1 << UDRIE;
static const uint8_t M_RXEN = 1 << RXEN;
static const uint8_t M_TXEN = 1 << TXEN;
-// bits in UCSRC
+// Bits in UCSRC.
static const uint8_t M_UPM0 = 1 << UPM0;
static const uint8_t M_UPM1 = 1 << UPM1;
static const uint8_t M_USBS = 1 << USBS;
static const uint8_t M_UCSZ0 = 1 << UCSZ0;
static const uint8_t M_UCSZ1 = 1 << UCSZ1;
+#elif defined(UCSR1A) // UCSR0A
+// Bits in UCSRA.
+static const uint8_t M_RXC = 1 << RXC1;
+static const uint8_t M_TXC = 1 << TXC1;
+static const uint8_t M_UDRE = 1 << UDRE1;
+static const uint8_t M_FE = 1 << FE1;
+static const uint8_t M_DOR = 1 << DOR1;
+static const uint8_t M_UPE = 1 << UPE1;
+static const uint8_t M_U2X = 1 << U2X1;
+// Bits in UCSRB.
+static const uint8_t M_RXCIE = 1 << RXCIE1;
+static const uint8_t M_TXCIE = 1 << TXCIE1;
+static const uint8_t M_UDRIE = 1 << UDRIE1;
+static const uint8_t M_RXEN = 1 << RXEN1;
+static const uint8_t M_TXEN = 1 << TXEN1;
+// Bits in UCSRC.
+static const uint8_t M_UPM0 = 1 << UPM10;
+static const uint8_t M_UPM1 = 1 << UPM11;
+static const uint8_t M_USBS = 1 << USBS1;
+static const uint8_t M_UCSZ0 = 1 << UCSZ10;
+static const uint8_t M_UCSZ1 = 1 << UCSZ11;
#else // UCSR0A
#error no serial ports
#endif // UCSR0A
//------------------------------------------------------------------------------
-/** use one stop bit */
+/** Use one stop bit. */
static const uint8_t SP_1_STOP_BIT = 0;
-/** use two stop bits */
+/** Use two stop bits. */
static const uint8_t SP_2_STOP_BIT = M_USBS;
-/** disable parity bit */
+/** No parity bit. */
static const uint8_t SP_NO_PARITY = 0;
-/** use even parity */
+/** Use even parity. */
static const uint8_t SP_EVEN_PARITY = M_UPM1;
-/** use odd parity */
+/** Use odd parity. */
static const uint8_t SP_ODD_PARITY = M_UPM0 | M_UPM1;
-/** use 5-bit character size */
+/** Use 5-bit character size. */
static const uint8_t SP_5_BIT_CHAR = 0;
-/** use 6-bit character size */
+/** Use 6-bit character size. */
static const uint8_t SP_6_BIT_CHAR = M_UCSZ0;
-/** use 7-bit character size */
+/** Use 7-bit character size. */
static const uint8_t SP_7_BIT_CHAR = M_UCSZ1;
-/** use 8-bit character size */
+/** Use 8-bit character size. */
static const uint8_t SP_8_BIT_CHAR = M_UCSZ0 | M_UCSZ1;
-/** mask for all options bits */
+/** Mask for all options bits. */
static const uint8_t SP_OPT_MASK = M_USBS | M_UPM0 | M_UPM1 |M_UCSZ0 | M_UCSZ1;
-/** USART frame error bit */
+/** USART framing error bit. */
static const uint8_t SP_FRAMING_ERROR = M_FE;
-/** USART RX data overrun error bit */
+/** USART RX data overrun error bit. */
static const uint8_t SP_RX_DATA_OVERRUN = M_DOR;
-/** USART parity error bit */
+/** USART parity error bit. */
static const uint8_t SP_PARITY_ERROR = M_UPE;
-/** mask for all error bits in UCSRA */
+/** Mask for all error bits in UCSRA. */
static const uint8_t SP_UCSRA_ERROR_MASK = M_FE | M_DOR | M_UPE;
-/** RX ring buffer full overrun */
+/** RX ring buffer full overrun. */
static const uint8_t SP_RX_BUF_OVERRUN = 1;
+#if 1 & ((1 << FE0) | (1 << DOR0) |(1 << UPE0))
+#error Invalid SP_RX_BUF_OVERRUN bit
+#endif // SP_RX_BUF_OVERRUN
//------------------------------------------------------------------------------
/**
- * \class UsartRegister
- * \brief addresses of USART registers
+ * @class UsartRegister
+ * @brief Addresses of USART registers.
*/
struct UsartRegister {
- volatile uint8_t* ucsra; /**< USART Control and Status Register A */
- volatile uint8_t* ucsrb; /**< USART Control and Status Register B */
- volatile uint8_t* ucsrc; /**< USART Control and Status Register C */
- volatile uint8_t* ubrrl; /**< USART Baud Rate Register Low */
- volatile uint8_t* ubrrh; /**< USART Baud Rate Register High */
- volatile uint8_t* udr; /**< USART I/O Data Register */
+ volatile uint8_t* ucsra; /**< USART Control and Status Register A. */
+ volatile uint8_t* ucsrb; /**< USART Control and Status Register B. */
+ volatile uint8_t* ucsrc; /**< USART Control and Status Register C. */
+ volatile uint8_t* ubrrl; /**< USART Baud Rate Register Low. */
+ volatile uint8_t* ubrrh; /**< USART Baud Rate Register High. */
+ volatile uint8_t* udr; /**< USART I/O Data Register. */
};
//------------------------------------------------------------------------------
/**
@@ -219,8 +240,8 @@ static const UsartRegister usart[] = {
};
//------------------------------------------------------------------------------
/**
- * \class SerialRingBuffer
- * \brief ring buffer for RX and TX data
+ * @class SerialRingBuffer
+ * @brief Ring buffer for RX and TX data.
*/
class SerialRingBuffer {
public:
@@ -231,7 +252,7 @@ class SerialRingBuffer {
typedef uint8_t buf_size_t;
#endif // ALLOW_LARGE_BUFFERS
int available();
- /** \return true if the ring buffer is empty else false */
+ /** @return @c true if the ring buffer is empty else @c false. */
bool empty() {return head_ == tail_;}
void flush();
bool get(uint8_t* b);
@@ -248,49 +269,52 @@ class SerialRingBuffer {
buf_size_t size_; /**< Size of the buffer. Capacity is size -1. */
};
//------------------------------------------------------------------------------
-/** RX ring buffers */
+/** RX ring buffers. */
extern SerialRingBuffer rxRingBuf[];
-/** TX ring buffers */
+/** TX ring buffers. */
extern SerialRingBuffer txRingBuf[];
-/** RX error bits */
+/** RX error bits. */
extern uint8_t rxErrorBits[];
//------------------------------------------------------------------------------
-/** Cause error message for bad port number
- * \return Never returns since it is never called
+/** Cause error message for bad port number.
+ * @return Never returns since it is never called.
*/
uint8_t badPortNumber(void)
__attribute__((error("Bad port number")));
-/** Cause error message for bad port number
- * \return Never returns since it is never called
+/** Cause error message for bad port number.
+ * @return Never returns since it is never called.
*/
uint8_t badRxBufSize(void)
__attribute__((error("RX buffer size too large")));
-/** Cause error message for bad port number
- * \return Never returns since it is never called
+/** Cause error message for bad port number.
+ * @return Never returns since it is never called.
*/
uint8_t badTxBufSize(void)
__attribute__((error("TX buffer size too large")));
//------------------------------------------------------------------------------
/**
- * \class SerialPort
- * \brief class for avr hardware USART ports
+ * @class SerialPort
+ * @brief Class for avr hardware USART ports.
*/
template
class SerialPort : public Stream {
public:
//----------------------------------------------------------------------------
+ /** Constructor */
SerialPort() {
- if (PortNumber >= SERIAL_PORT_COUNT) badPortNumber();
+ if (PortNumber >= SERIAL_PORT_COUNT || !usart[PortNumber].ucsra) {
+ badPortNumber();
+ }
if (sizeof(SerialRingBuffer::buf_size_t) == 1) {
- if (RxBufSize >254) badRxBufSize();
- if (TxBufSize >254) badTxBufSize();
+ if (RxBufSize > 254) badRxBufSize();
+ if (TxBufSize > 254) badTxBufSize();
}
if (RxBufSize) rxRingBuf[PortNumber].init(rxBuffer_, sizeof(rxBuffer_));
if (TxBufSize) txRingBuf[PortNumber].init(txBuffer_, sizeof(txBuffer_));
}
//----------------------------------------------------------------------------
/**
- * \return The number of bytes (characters) available for reading from
+ * @return The number of bytes (characters) available for reading from
* the serial port.
*/
int available(void) {
@@ -304,31 +328,23 @@ class SerialPort : public Stream {
/**
* Sets the data rate in bits per second (baud) for serial data transmission.
*
- * \param[in] baud rate in bits per second (baud)
- * \param[in] options constructed by a bitwise-inclusive
+ * @param[in] baud Rate in bits per second (baud).
+ * @param[in] options constructed by a bitwise-inclusive
* OR of values from the following list. Choose one value for stop bit,
* parity, and character size.
*
+ * - SP_1_STOP_BIT - Use one stop bit (default if stop bit not specified).
+ * - SP_2_STOP_BIT - Use two stop bits.
+ * - SP_NO_PARITY - No parity bit (default if parity not specified).
+ * - SP_EVEN_PARITY - Add even parity bit.
+ * - SP_ODD_PARITY - Add odd parity bit.
+ * - SP_5_BIT_CHAR - Use 5-bit characters (default if size not specified).
+ * - SP_6_BIT_CHAR - Use 6-bit characters.
+ * - SP_7_BIT_CHAR - Use 7-bit characters.
+ * - SP_8_BIT_CHAR - Use 8-bit characters.
+ * .
* The default is SP_8_BIT_CHAR which results in one stop bit, no parity,
* and 8-bit characters.
- *
- * SP_1_STOP_BIT - use one stop bit (default if stop bit not specified)
- *
- * SP_2_STOP_BIT - use two stop bits
- *
- * SP_NO_PARITY - no parity bit (default if parity not specified)
- *
- * SP_EVEN_PARITY - add even parity bit
- *
- * SP_ODD_PARITY - add odd parity bit
- *
- * SP_5_BIT_CHAR - use 5-bit characters (default if size not specified)
- *
- * SP_6_BIT_CHAR - use 6-bit characters
- *
- * SP_7_BIT_CHAR - use 7-bit characters
- *
- * SP_8_BIT_CHAR - use 8-bit characters
*/
void begin(uint32_t baud, uint8_t options = SP_8_BIT_CHAR) {
uint16_t baud_setting;
@@ -339,16 +355,22 @@ class SerialPort : public Stream {
// set option bits
*usart[PortNumber].ucsrc = options & SP_OPT_MASK;
- if (F_CPU == 16000000UL && baud == 57600) {
- // hardcoded exception for compatibility with the bootloader shipped
- // with the Duemilanove and previous boards and the firmware on the 8U2
- // on the Uno and Mega 2560.
+ baud_setting = F_CPU/4/baud;
+
+ if (baud_setting > 8192 || (F_CPU == 16000000UL && baud == 57600)) {
+ // Hardcoded exception for compatibility with the bootloader shipped
+ // with the Duemilanove and previous boards and the firmware on the
+ // 8U2/16U2 on the Uno and Mega 2560.
+ // Prevent overflow of 12-bit UBRR at 300 baud.
*usart[PortNumber].ucsra = 0;
- baud_setting = (F_CPU / 8 / baud - 1) / 2;
+ baud_setting /= 2;
} else {
+ // Use U2X for better high baud rates.
*usart[PortNumber].ucsra = M_U2X;
- baud_setting = (F_CPU / 4 / baud - 1) / 2;
}
+ // Rounded value for datasheet expression.
+ baud_setting = (baud_setting - 1)/2;
+
// assign the baud_setting, a.k.a. ubbr (USART Baud Rate Register)
*usart[PortNumber].ubrrh = baud_setting >> 8;
*usart[PortNumber].ubrrl = baud_setting;
@@ -362,9 +384,15 @@ class SerialPort : public Stream {
}
//----------------------------------------------------------------------------
#if ENABLE_RX_ERROR_CHECKING
- /** clear RX error bits */
+ /** Clear RX error bits. */
void clearRxError() {rxErrorBits[PortNumber] = 0;}
- /** \return RX error bits */
+ /** @return RX error bits. Possible error bits are:
+ * - @ref SP_RX_BUF_OVERRUN
+ * - @ref SP_RX_DATA_OVERRUN
+ * - @ref SP_FRAMING_ERROR
+ * - @ref SP_PARITY_ERROR
+ * .
+ */
uint8_t getRxError() {return rxErrorBits[PortNumber];}
#endif // ENABLE_RX_ERROR_CHECKING
//----------------------------------------------------------------------------
@@ -386,13 +414,8 @@ class SerialPort : public Stream {
//----------------------------------------------------------------------------
/**
* For Arduino 1.0 and greater call flushTx().
- * For Arduino 0023 and before call flushRx().
*/
- #if ARDUINO < 100
- void flush() {flushRx();}
- #else // ARDUINO < 100
void flush() {flushTx();}
- #endif // ARDUINO < 100
//----------------------------------------------------------------------------
/**
* Discard any buffered incoming serial data.
@@ -416,8 +439,8 @@ class SerialPort : public Stream {
}
//----------------------------------------------------------------------------
/**
- * \return the first byte of incoming serial data available or
- * -1 if no data is available. Peek() always return -1 for unbuffered RX.
+ * @return The first byte of incoming serial data available or
+ * -1 if no data is available. -1 is always returned for unbuffered RX.
*/
int peek(void) {
return RxBufSize ? rxRingBuf[PortNumber].peek() : -1;
@@ -426,8 +449,8 @@ class SerialPort : public Stream {
/**
* Read incoming serial data.
*
- * \return the first byte of incoming serial data available
- * or -1 if no data is available
+ * @return The first byte of incoming serial data available
+ * or -1 if no data is available.
*/
__attribute__((noinline))
int read() {
@@ -447,9 +470,9 @@ class SerialPort : public Stream {
* Read incoming serial data. Stop when RX buffer is empty or n
* bytes have been read.
*
- * \param[in] b location to receive the data
- * \param[in] n maximum number of bytes to read
- * \return number of bytes read
+ * @param[in] b The location to receive the data.
+ * @param[in] n Maximum number of bytes to read.
+ * @return The number of bytes read.
*/
__attribute__((noinline))
size_t read(uint8_t* b, size_t n) {
@@ -461,7 +484,6 @@ class SerialPort : public Stream {
if (sizeof(SerialRingBuffer::buf_size_t) == 1 && nr > 255) nr = 255;
p += rxRingBuf[PortNumber].get(p, nr);
}
- return p - b;
} else {
while (p < limit) {
int rb = read();
@@ -475,77 +497,55 @@ class SerialPort : public Stream {
/**
* Write binary data to the serial port.
*
- * \param[in] b byte to be written.
- * \return number of bytes written to the serial port
+ * @param[in] b The byte to be written.
+ * @return The number of bytes written to the serial port.
*/
__attribute__((noinline))
- #if ARDUINO < 100
- void write(uint8_t b) {
- #else // ARDUINO < 100
size_t write(uint8_t b) {
- #endif // ARDUINO < 100
if (!TxBufSize) {
while (!(*usart[PortNumber].ucsra & M_UDRE)) {}
*usart[PortNumber].udr = b;
} else {
- // wait for TX ISR if buffer is full
+ // Wait for TX ISR if buffer is full.
while (!txRingBuf[PortNumber].put(b)) {}
- // enable interrupts
+
+ // Enable interrupts.
*usart[PortNumber].ucsrb |= M_UDRIE;
}
- #if ARDUINO > 99
return 1;
- #endif // ARDUINO > 99
}
//----------------------------------------------------------------------------
- /** write CR LF
- * \return 2
+ /** Write CR/LF.
+ * @return 2
*/
__attribute__((noinline))
- #if ARDUINO < 100
- void writeln() {
- write('\r');
- write('\n');
- }
- #else // ARDUINO < 100
size_t writeln() {
write('\r');
write('\n');
return 2;
}
- #endif // ARDUINO >= 100
//----------------------------------------------------------------------------
/**
- * Write a string to the serial port followed by CF LF
+ * Write a string to the serial port followed by CR/LF.
*
- * \param[in] s string to be written.
- * \return number of bytes written to the serial port
+ * @param[in] s The string to be written.
+ * @return The number of bytes written to the serial port.
*/
__attribute__((noinline))
- #if ARDUINO < 100
- void writeln(const char* s) {
- write(s);
- writeln();
- }
- #else // ARDUINO < 100
size_t writeln(const char* s) {
return write(s) + writeln();
}
- #endif // ARDUINO >= 100
+
//----------------------------------------------------------------------------
/**
* Write binary data from flash memory to the serial port.
*
- * \param[in] b bytes to be written
- * \param[in] n number of bytes to write
- * \return number of bytes written to the serial port
+ * @param[in] b Location of the bytes to be written.
+ * @param[in] n The number of bytes to write.
+ * @return The number of bytes written to the serial port.
*/
__attribute__((noinline))
- #if ARDUINO < 100
- void write_P(PGM_P b, size_t n) {
- #else // ARDUINO < 100
size_t write_P(PGM_P b, size_t n) {
- #endif // ARDUINO < 100
if (!TxBufSize) {
for (size_t i = 0; i < n; i++) write(pgm_read_byte(b + i));
} else {
@@ -554,70 +554,50 @@ class SerialPort : public Stream {
size_t nw = w;
if (sizeof(SerialRingBuffer::buf_size_t) == 1 && nw > 255) nw = 255;
size_t m = txRingBuf[PortNumber].put_P(b, nw);
+
// enable interrupts
*usart[PortNumber].ucsrb |= M_UDRIE;
w -= m;
b += m;
}
}
- #if ARDUINO >= 100
return n;
- #endif // ARDUINO >= 100
}
//----------------------------------------------------------------------------
/**
* Write a flash string to the serial port.
*
- * \param[in] s string to be written.
- * \return number of bytes written to the serial port
+ * @param[in] s The string to be written.
+ * @return The number of bytes written to the serial port.
*/
__attribute__((noinline))
- #if ARDUINO < 100
- void write(const __FlashStringHelper* s) {
- const prog_char* p = (const prog_char*)s;
- size_t n = strlen_P(p);
- write_P(p, n);
- }
- #else // ARDUINO < 100
size_t write(const __FlashStringHelper* s) {
- const prog_char* p = (const prog_char*)s;
+ const char PROGMEM* p = (const char PROGMEM*)s;
size_t n = strlen_P(p);
return write_P(p, n);
}
- #endif // ARDUINO >= 100
//----------------------------------------------------------------------------
/**
- * Write a flash string to the serial port followed by CF LF
+ * Write a flash string to the serial port followed by CR/LF.
*
- * \param[in] s string to be written.
- * \return number of bytes written to the serial port
+ * @param[in] s The string to be written.
+ * @return The number of bytes written to the serial port.
*/
__attribute__((noinline))
- #if ARDUINO < 100
- void writeln(const __FlashStringHelper* s) {
- write(s);
- writeln();
- }
- #else // ARDUINO < 100
size_t writeln(const __FlashStringHelper* s) {
return write(s) + writeln();
}
- #endif // ARDUINO >= 100
#if USE_WRITE_OVERRIDES
//----------------------------------------------------------------------------
/**
* Write binary data to the serial port.
*
- * \param[in] b bytes to be written
- * \param[in] n number of bytes to write
- * \return number of bytes written to the serial port
+ * @param[in] b Location of the bytes to be written.
+ * @param[in] n The number of bytes to write.
+ * @return The number of bytes written to the serial port.
*/
__attribute__((noinline))
- #if ARDUINO < 100
- void write(const uint8_t* b, size_t n) {
- #else // ARDUINO < 100
size_t write(const uint8_t* b, size_t n) {
- #endif // ARDUINO < 100
if (!TxBufSize) {
for (size_t i = 0; i < n; i++) write(b[i]);
} else {
@@ -626,35 +606,27 @@ class SerialPort : public Stream {
size_t nw = w;
if (sizeof(SerialRingBuffer::buf_size_t) == 1 && nw > 255) nw = 255;
size_t m = txRingBuf[PortNumber].put(b, nw);
- // enable interrupts
+
+ // Enable interrupts.
*usart[PortNumber].ucsrb |= M_UDRIE;
w -= m;
b += m;
}
}
- #if ARDUINO >= 100
return n;
- #endif // ARDUINO >= 100
}
//----------------------------------------------------------------------------
/**
* Write a string to the serial port.
*
- * \param[in] s string to be written.
- * \return number of bytes written to the serial port
+ * @param[in] s The string to be written.
+ * @return The number of bytes written to the serial port
*/
__attribute__((noinline))
- #if ARDUINO < 100
- void write(const char* s) {
- size_t n = strlen(s);
- write(reinterpret_cast(s), n);
- }
- #else // ARDUINO < 100
size_t write(const char* s) {
size_t n = strlen(s);
return write(reinterpret_cast(s), n);
}
- #endif // ARDUINO >= 100
#else // USE_WRITE_OVERRIDES
using Print::write; // use write(str) and write(buf, size) from Print
#endif // USE_WRITE_OVERRIDES
@@ -662,7 +634,7 @@ class SerialPort : public Stream {
private:
// RX buffer with a capacity of RxBufSize.
uint8_t rxBuffer_[RxBufSize + 1];
- // TX buffer with a capacity of TxBufSize
+ // TX buffer with a capacity of TxBufSize.
uint8_t txBuffer_[TxBufSize + 1];
};
//------------------------------------------------------------------------------
diff --git a/Libraries/SerialPort/examples/ArduinoSize/ArduinoSize.ino b/Libraries/SerialPort/examples/ArduinoSize/ArduinoSize.ino
new file mode 100644
index 0000000..f8894ad
--- /dev/null
+++ b/Libraries/SerialPort/examples/ArduinoSize/ArduinoSize.ino
@@ -0,0 +1,10 @@
+// Print free RAM for Arduino HardwareSerial
+//
+#include "FreeRam.h"
+
+void setup() {
+ Serial.begin(9600);
+ Serial.println(FreeRam());
+}
+void loop() {
+}
diff --git a/Libraries/SerialPort/examples/ArduinoSize/FreeRam.h b/Libraries/SerialPort/examples/ArduinoSize/FreeRam.h
index b03537c..bbd9dd3 100644
--- a/Libraries/SerialPort/examples/ArduinoSize/FreeRam.h
+++ b/Libraries/SerialPort/examples/ArduinoSize/FreeRam.h
@@ -1,15 +1,10 @@
+#include
static inline int FreeRam() {
- extern int __bss_end;
- extern int* __brkval;
- int free_memory;
- if (reinterpret_cast(__brkval) == 0) {
- // if no heap use from end of bss section
- free_memory = reinterpret_cast(&free_memory)
- - reinterpret_cast(&__bss_end);
- } else {
- // use from top of stack to heap
- free_memory = reinterpret_cast(&free_memory)
- - reinterpret_cast(__brkval);
- }
- return free_memory;
+ extern char *__brkval;
+ char top;
+#if defined(CORE_TEENSY)
+ return &top - __brkval;
+#else // malloc type
+ return __brkval ? &top - __brkval : &top - __malloc_heap_start;
+#endif // malloc type
}
diff --git a/Libraries/SerialPort/examples/ArduinoTest/ArduinoTest.ino b/Libraries/SerialPort/examples/ArduinoTest/ArduinoTest.ino
new file mode 100644
index 0000000..7b23808
--- /dev/null
+++ b/Libraries/SerialPort/examples/ArduinoTest/ArduinoTest.ino
@@ -0,0 +1,20 @@
+
+void setup() {
+ Serial.begin(9600);
+ uint32_t t = micros();
+ Serial.write("This string is used to measure the time to buffer data.\r\n");
+ t = micros() - t;
+ Serial.write("Time: ");
+ Serial.print(t);
+ Serial.write(" us\r\n");
+}
+void loop() {
+ Serial.write("\r\nenter a string\r\n");
+ while (!Serial.available()) {}
+ do {
+ Serial.write(Serial.read());
+ uint32_t m = millis();
+ while (!Serial.available() && (millis() - m) < 3) {}
+ } while(Serial.available());
+ Serial.write("\r\n");
+}
\ No newline at end of file
diff --git a/Libraries/SerialPort/examples/BufferedSize/BufferedSize.ino b/Libraries/SerialPort/examples/BufferedSize/BufferedSize.ino
new file mode 100644
index 0000000..86089a0
--- /dev/null
+++ b/Libraries/SerialPort/examples/BufferedSize/BufferedSize.ino
@@ -0,0 +1,15 @@
+// Print free RAM for Arduino 1.0 style buffering.
+//
+#include
+#include "FreeRam.h"
+
+SerialPort<0, 63, 63> NewSerial;
+
+// for Arduino 0022 style buffering use this
+//SerialPort<0, 127, 0> NewSerial;
+
+void setup() {
+ NewSerial.begin(9600);
+ NewSerial.println(FreeRam());
+}
+void loop() {}
\ No newline at end of file
diff --git a/Libraries/SerialPort/examples/BufferedSize/FreeRam.h b/Libraries/SerialPort/examples/BufferedSize/FreeRam.h
index b03537c..bbd9dd3 100644
--- a/Libraries/SerialPort/examples/BufferedSize/FreeRam.h
+++ b/Libraries/SerialPort/examples/BufferedSize/FreeRam.h
@@ -1,15 +1,10 @@
+#include
static inline int FreeRam() {
- extern int __bss_end;
- extern int* __brkval;
- int free_memory;
- if (reinterpret_cast(__brkval) == 0) {
- // if no heap use from end of bss section
- free_memory = reinterpret_cast(&free_memory)
- - reinterpret_cast(&__bss_end);
- } else {
- // use from top of stack to heap
- free_memory = reinterpret_cast(&free_memory)
- - reinterpret_cast(__brkval);
- }
- return free_memory;
+ extern char *__brkval;
+ char top;
+#if defined(CORE_TEENSY)
+ return &top - __brkval;
+#else // malloc type
+ return __brkval ? &top - __brkval : &top - __malloc_heap_start;
+#endif // malloc type
}
diff --git a/Libraries/SerialPort/examples/BufferedTest/BufferedTest.ino b/Libraries/SerialPort/examples/BufferedTest/BufferedTest.ino
new file mode 100644
index 0000000..489fdfd
--- /dev/null
+++ b/Libraries/SerialPort/examples/BufferedTest/BufferedTest.ino
@@ -0,0 +1,25 @@
+// Check time to buffer data and function of available().
+#include
+
+// port zero, 63 character RX and TX buffers
+SerialPort<0, 63, 63> NewSerial;
+
+void setup() {
+ NewSerial.begin(9600);
+ uint32_t t = micros();
+ NewSerial.write("This string is used to measure the time to buffer data.\r\n");
+ t = micros() - t;
+ NewSerial.write("Time: ");
+ NewSerial.print(t);
+ NewSerial.write(" us\r\n");
+}
+void loop() {
+ NewSerial.write("\r\nenter a string\r\n");
+ while (!NewSerial.available()) {}
+ do {
+ NewSerial.write(NewSerial.read());
+ uint32_t m = millis();
+ while (!NewSerial.available() && (millis() - m) < 3) {}
+ } while(NewSerial.available());
+ NewSerial.write("\r\n");
+}
\ No newline at end of file
diff --git a/Libraries/SerialPort/examples/HelloWorld/HelloWorld.ino b/Libraries/SerialPort/examples/HelloWorld/HelloWorld.ino
new file mode 100644
index 0000000..086d820
--- /dev/null
+++ b/Libraries/SerialPort/examples/HelloWorld/HelloWorld.ino
@@ -0,0 +1,11 @@
+// Simple usage with buffering like Arduino 1.0.
+#include
+
+// use NewSerial for port 0
+USE_NEW_SERIAL;
+
+void setup() {
+ NewSerial.begin(9600);
+ NewSerial.println("Hello World!");
+}
+void loop() {}
\ No newline at end of file
diff --git a/Libraries/SerialPort/examples/MegaTest/MegaTest.ino b/Libraries/SerialPort/examples/MegaTest/MegaTest.ino
new file mode 100644
index 0000000..7dca6fc
--- /dev/null
+++ b/Libraries/SerialPort/examples/MegaTest/MegaTest.ino
@@ -0,0 +1,48 @@
+// Test all ports on the Mega.
+//
+// A string read on port zero will be sent to port one,
+// it will then be read from port one and sent to port
+// two, next it will be read from port two and sent to
+// port three, and finally it will be read from port
+// three and sent to port zero.
+//
+// Place a loopback jumper connecting
+// RX1 to TX1, RX2 to TX2, RX3 to TX3 on ports 1, 2, and 3.
+// Do not place a jumper on port zero.
+//
+#include
+// port 0 unbuffered
+SerialPort<0, 0, 0> port0;
+
+// port 1 buffered RX
+SerialPort<1, 32, 0> port1;
+
+// port 2 buffered RX and TX
+SerialPort<2, 32, 32> port2;
+
+// port 3 buffered RX and TX
+SerialPort<3, 32, 32> port3;
+
+void transfer(Stream* in, Stream* out) {
+ while(!in->available()) {}
+ do {
+ out->write(in->read());
+ uint32_t m = millis();
+ while (!in->available() && (millis() -m) < 3) {}
+ } while (in->available());
+}
+
+void setup() {
+ port0.begin(9600);
+ port1.begin(9600);
+ port2.begin(9600);
+ port3.begin(9600);
+}
+void loop() {
+ port0.write("type a string\r\n");
+ transfer(&port0, &port1);
+ transfer(&port1, &port2);
+ transfer(&port2, &port3);
+ transfer(&port3, &port0);
+ port0.write("\r\n\r\n");
+}
diff --git a/Libraries/SerialPort/examples/MegaTestArduino/MegaTestArduino.ino b/Libraries/SerialPort/examples/MegaTestArduino/MegaTestArduino.ino
new file mode 100644
index 0000000..32538ab
--- /dev/null
+++ b/Libraries/SerialPort/examples/MegaTestArduino/MegaTestArduino.ino
@@ -0,0 +1,35 @@
+// Test all ports on the Mega.
+//
+//
+// A string read on port zero will be sent to port one,
+// it will then be read from port one and sent to port
+// two, next it will be read from port two and sent to
+// port three, and finally it will be read from port
+// three and sent to port zero.
+//
+// Place a loopback jumper connecting
+// RX1 to TX1, RX2 to TX2, RX3 to TX3 on ports 1, 2, and 3.
+// Do not place a jumper on port zero.
+//
+void transfer(Stream* in, Stream* out) {
+ while(!in->available()) {}
+ do {
+ out->write(in->read());
+ uint32_t m = millis();
+ while (!in->available() && (millis() - m) < 3) {}
+ } while (in->available());
+}
+void setup() {
+ Serial.begin(9600);
+ Serial1.begin(9600);
+ Serial2.begin(9600);
+ Serial3.begin(9600);
+}
+void loop() {
+ Serial.write("type a string\r\n");
+ transfer(&Serial, &Serial1);
+ transfer(&Serial1, &Serial2);
+ transfer(&Serial2, &Serial3);
+ transfer(&Serial3, &Serial);
+ Serial.write("\r\n\r\n");
+}
diff --git a/Libraries/SerialPort/examples/ReadWriteTest/ReadWriteTest.ino b/Libraries/SerialPort/examples/ReadWriteTest/ReadWriteTest.ino
new file mode 100644
index 0000000..c1df3c8
--- /dev/null
+++ b/Libraries/SerialPort/examples/ReadWriteTest/ReadWriteTest.ino
@@ -0,0 +1,32 @@
+// Test that ring buffer overrun can be detected.
+#include
+// port 0, 16 byte RX and TX buffers
+SerialPort<0, 16, 16> port0;
+
+void setup() {
+ port0.begin(9600);
+ port0.write("SerialPort version: ");
+ port0.println(SERIAL_PORT_VERSION);
+}
+void loop() {
+ uint8_t buffer[10];
+ port0.writeln("Enter a string. Overrun error for more than 16 bytes.");
+ while (!port0.available()) {}
+ // delay so an ring buffer overrun will occur for long strings
+ delay(50);
+ uint32_t m = millis();
+ do {
+ size_t n = port0.read(buffer, sizeof (buffer));
+ if (n) {
+ m = millis();
+ port0.write(buffer, n);
+ }
+ } while ((millis() - m) < 4);
+ port0.writeln();
+ uint8_t e = port0.getRxError();
+ if (e) {
+ port0.write("Error: ");
+ port0.println(e, HEX);
+ port0.clearRxError();
+ }
+}
\ No newline at end of file
diff --git a/Libraries/SerialPort/examples/UnbufferedSize/FreeRam.h b/Libraries/SerialPort/examples/UnbufferedSize/FreeRam.h
index b03537c..bbd9dd3 100644
--- a/Libraries/SerialPort/examples/UnbufferedSize/FreeRam.h
+++ b/Libraries/SerialPort/examples/UnbufferedSize/FreeRam.h
@@ -1,15 +1,10 @@
+#include
static inline int FreeRam() {
- extern int __bss_end;
- extern int* __brkval;
- int free_memory;
- if (reinterpret_cast(__brkval) == 0) {
- // if no heap use from end of bss section
- free_memory = reinterpret_cast(&free_memory)
- - reinterpret_cast(&__bss_end);
- } else {
- // use from top of stack to heap
- free_memory = reinterpret_cast(&free_memory)
- - reinterpret_cast(__brkval);
- }
- return free_memory;
+ extern char *__brkval;
+ char top;
+#if defined(CORE_TEENSY)
+ return &top - __brkval;
+#else // malloc type
+ return __brkval ? &top - __brkval : &top - __malloc_heap_start;
+#endif // malloc type
}
diff --git a/Libraries/SerialPort/examples/UnbufferedSize/UnbufferedSize.ino b/Libraries/SerialPort/examples/UnbufferedSize/UnbufferedSize.ino
new file mode 100644
index 0000000..4b1f60a
--- /dev/null
+++ b/Libraries/SerialPort/examples/UnbufferedSize/UnbufferedSize.ino
@@ -0,0 +1,17 @@
+// Print free RAM for unbuffered mode.
+//
+// You can reduce flash and RAM use more by setting
+// BUFFERED_TX and BUFFERED_RX zero in SerialPort.h
+// to always disable buffering.
+//
+#include
+#include "FreeRam.h"
+
+// no buffers
+SerialPort<0, 0, 0> NewSerial;
+
+void setup() {
+ NewSerial.begin(9600);
+ NewSerial.println(FreeRam());
+}
+void loop() {}
\ No newline at end of file
diff --git a/Libraries/SerialPort/examples/UnbufferedTest/UnbufferedTest.ino b/Libraries/SerialPort/examples/UnbufferedTest/UnbufferedTest.ino
new file mode 100644
index 0000000..9043410
--- /dev/null
+++ b/Libraries/SerialPort/examples/UnbufferedTest/UnbufferedTest.ino
@@ -0,0 +1,24 @@
+#include
+
+// serial port zero with no RX or TX buffering
+SerialPort<0, 0, 0> NewSerial;
+
+void setup() {
+ NewSerial.begin(9600);
+ uint32_t t = micros();
+ NewSerial.write("This string is used to measure the time to buffer data.\r\n");
+ t = micros() - t;
+ NewSerial.write("Time: ");
+ NewSerial.print(t);
+ NewSerial.write(" us\r\n");
+}
+void loop() {
+ NewSerial.write("\r\nenter a string\r\n");
+ while (!NewSerial.available()) {}
+ do {
+ NewSerial.write(NewSerial.read());
+ uint32_t m = millis();
+ while (!NewSerial.available() && (millis() - m) < 3) {}
+ } while(NewSerial.available());
+ NewSerial.write("\r\n");
+}
\ No newline at end of file
diff --git a/Libraries/SerialPort/examples/WriteFlash/WriteFlash.ino b/Libraries/SerialPort/examples/WriteFlash/WriteFlash.ino
new file mode 100644
index 0000000..09a05b1
--- /dev/null
+++ b/Libraries/SerialPort/examples/WriteFlash/WriteFlash.ino
@@ -0,0 +1,20 @@
+// Test write() time for a flash string.
+#include
+
+SerialPort<0, 0, 32> port;
+
+void setup(void) {
+ port.begin(9600);
+
+ for (int route = 0; route < 11; route++) {
+ uint32_t start = micros();
+ port.writeln(F("Selecting passenger route x"));
+ uint32_t stop = micros();
+ port.write(F("Message time: "));
+ port.print(stop - start, DEC);
+ port.writeln(F(" us"));
+ delay(400);
+ }
+ port.println(F("Done!"));
+}
+void loop(void) {}