Inherit from SoftSerial and use software buffers for TX and RX. This allows the SoftSerial to operate in a IRQ driven mode. Overrides most (but not all) stdio functions as SoftSerial did
Dependencies: Buffer SoftSerial
Dependents: 2014_Ensoul_Capstone F103RB_tcp_rtu_modbus_copy_v1_0 SDP_Testing Nucleo_SFM ... more
Fork of BufferedSerial by
Todo: Write something here :)
Revision 6:4e3e18b41ea6, committed 2014-04-26
- Comitter:
- Sissors
- Date:
- Sat Apr 26 20:55:42 2014 +0000
- Parent:
- 5:4d6a311fc8bf
- Child:
- 7:58d0adeb95aa
- Commit message:
- BufferedSerial -> BufferedSoftSerial
Changed in this revision
--- a/BufferedSerial.cpp Mon Mar 24 19:56:57 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,148 +0,0 @@ -/** - * @file BufferedSerial.cpp - * @brief Software Buffer - Extends mbed Serial functionallity adding irq driven TX and RX - * @author sam grove - * @version 1.0 - * @see - * - * Copyright (c) 2013 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "BufferedSerial.h" -#include <stdarg.h> - -BufferedSerial::BufferedSerial(PinName tx, PinName rx, const char* name) - : Serial(tx, rx, name) -{ - Serial::attach(this, &BufferedSerial::rxIrq, Serial::RxIrq); - - return; -} - -BufferedSerial::~BufferedSerial(void) -{ - Serial::attach(NULL, Serial::RxIrq); - Serial::attach(NULL, Serial::TxIrq); - - return; -} - -int BufferedSerial::readable(void) -{ - return _rxbuf.available(); // note: look if things are in the buffer -} - -int BufferedSerial::writeable(void) -{ - return 1; // buffer allows overwriting by design, always true -} - -int BufferedSerial::getc(void) -{ - return _rxbuf; -} - -int BufferedSerial::putc(int c) -{ - _txbuf = (char)c; - BufferedSerial::prime(); - - return c; -} - -int BufferedSerial::puts(const char *s) -{ - const char* ptr = s; - - while(*(ptr) != 0) { - _txbuf = *(ptr++); - } - _txbuf = '\n'; // done per puts definition - BufferedSerial::prime(); - - return (ptr - s) + 1; -} - -int BufferedSerial::printf(const char* format, ...) -{ - char buf[256] = {0}; - int r = 0; - - va_list arg; - va_start(arg, format); - r = vsprintf(buf, format, arg); - // this may not hit the heap but should alert the user anyways - if(r > sizeof(buf)) { - error("%s %d buffer overwrite!\n", __FILE__, __LINE__); - } - va_end(arg); - r = BufferedSerial::write(buf, r); - - return r; -} - -ssize_t BufferedSerial::write(const void *s, size_t length) -{ - const char* ptr = (const char*)s; - const char* end = ptr + length; - - while (ptr != end) { - _txbuf = *(ptr++); - } - BufferedSerial::prime(); - - return ptr - (const char*)s; -} - - -void BufferedSerial::rxIrq(void) -{ - // read from the peripheral and make sure something is available - if(serial_readable(&_serial)) { - _rxbuf = serial_getc(&_serial); // if so load them into a buffer - } - - return; -} - -void BufferedSerial::txIrq(void) -{ - // see if there is room in the hardware fifo and if something is in the software fifo - while(serial_writable(&_serial)) { - if(_txbuf.available()) { - serial_putc(&_serial, (int)_txbuf.get()); - } else { - // disable the TX interrupt when there is nothing left to send - Serial::attach(NULL, Serial::TxIrq); - break; - } - } - - return; -} - -void BufferedSerial::prime(void) -{ - // if already busy then the irq will pick this up - if(serial_writable(&_serial)) { - Serial::attach(NULL, Serial::TxIrq); // make sure not to cause contention in the irq - BufferedSerial::txIrq(); // only write to hardware in one place - Serial::attach(this, &BufferedSerial::txIrq, Serial::TxIrq); - } - - return; -} - -
--- a/BufferedSerial.h Mon Mar 24 19:56:57 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,135 +0,0 @@ - -/** - * @file BufferedSerial.h - * @brief Software Buffer - Extends mbed Serial functionallity adding irq driven TX and RX - * @author sam grove - * @version 1.0 - * @see - * - * Copyright (c) 2013 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef BUFFEREDSERIAL_H -#define BUFFEREDSERIAL_H - -#include "mbed.h" -#include "Buffer.h" - -/** A serial port (UART) for communication with other serial devices - * - * Can be used for Full Duplex communication, or Simplex by specifying - * one pin as NC (Not Connected) - * - * Example: - * @code - * #include "mbed.h" - * #include "BufferedSerial.h" - * - * BufferedSerial pc(USBTX, USBRX); - * - * int main() - * { - * while(1) - * { - * Timer s; - * - * s.start(); - * pc.printf("Hello World - buffered\n"); - * int buffered_time = s.read_us(); - * wait(0.1f); // give time for the buffer to empty - * - * s.reset(); - * printf("Hello World - blocking\n"); - * int polled_time = s.read_us(); - * s.stop(); - * wait(0.1f); // give time for the buffer to empty - * - * pc.printf("printf buffered took %d us\n", buffered_time); - * pc.printf("printf blocking took %d us\n", polled_time); - * wait(0.5f); - * } - * } - * @endcode - */ - -/** - * @class BufferedSerial - * @brief Software buffers and interrupt driven tx and rx for Serial - */ -class BufferedSerial : public Serial -{ -private: - Buffer <char> _rxbuf; - Buffer <char> _txbuf; - - void rxIrq(void); - void txIrq(void); - void prime(void); - -public: - /** Create a BufferedSerial port, connected to the specified transmit and receive pins - * @param tx Transmit pin - * @param rx Receive pin - * @note Either tx or rx may be specified as NC if unused - */ - BufferedSerial(PinName tx, PinName rx, const char* name=NULL); - - /** Destroy a BufferedSerial port - */ - virtual ~BufferedSerial(void); - - /** Check on how many bytes are in the rx buffer - * @return 1 if something exists, 0 otherwise - */ - virtual int readable(void); - - /** Check to see if the tx buffer has room - * @return 1 always has room and can overwrite previous content if too small / slow - */ - virtual int writeable(void); - - /** Get a single byte from the BufferedSerial Port. - * Should check readable() before calling this. - * @return A byte that came in on the Serial Port - */ - virtual int getc(void); - - /** Write a single byte to the BufferedSerial Port. - * @param c The byte to write to the Serial Port - * @return The byte that was written to the Serial Port Buffer - */ - virtual int putc(int c); - - /** Write a string to the BufferedSerial Port. Must be NULL terminated - * @param s The string to write to the Serial Port - * @return The number of bytes written to the Serial Port Buffer - */ - virtual int puts(const char *s); - - /** Write a formatted string to the BufferedSerial Port. - * @param format The string + format specifiers to write to the Serial Port - * @return The number of bytes written to the Serial Port Buffer - */ - virtual int printf(const char* format, ...); - - /** Write data to the Buffered Serial Port - * @param s A pointer to data to send - * @param length The amount of data being pointed to - * @return The number of bytes written to the Serial Port Buffer - */ - virtual ssize_t write(const void *s, std::size_t length); -}; - -#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BufferedSoftSerial.cpp Sat Apr 26 20:55:42 2014 +0000 @@ -0,0 +1,148 @@ +/** + * @file BufferedSoftSerial.cpp + * @brief Software Buffer - Extends mbed Serial functionallity adding irq driven TX and RX + * @author sam grove + * @version 1.0 + * @see + * + * Copyright (c) 2013 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "BufferedSoftSerial.h" +#include <stdarg.h> + +BufferedSoftSerial::BufferedSoftSerial(PinName tx, PinName rx, const char* name) + : SoftSerial(tx, rx, name) +{ + SoftSerial::attach(this, &BufferedSoftSerial::rxIrq, SoftSerial::RxIrq); + + return; +} + +BufferedSoftSerial::~BufferedSoftSerial(void) +{ + SoftSerial::attach(NULL, SoftSerial::RxIrq); + SoftSerial::attach(NULL, SoftSerial::TxIrq); + + return; +} + +int BufferedSoftSerial::readable(void) +{ + return _rxbuf.available(); // note: look if things are in the buffer +} + +int BufferedSoftSerial::writeable(void) +{ + return 1; // buffer allows overwriting by design, always true +} + +int BufferedSoftSerial::getc(void) +{ + return _rxbuf; +} + +int BufferedSoftSerial::putc(int c) +{ + _txbuf = (char)c; + BufferedSoftSerial::prime(); + + return c; +} + +int BufferedSoftSerial::puts(const char *s) +{ + const char* ptr = s; + + while(*(ptr) != 0) { + _txbuf = *(ptr++); + } + _txbuf = '\n'; // done per puts definition + BufferedSoftSerial::prime(); + + return (ptr - s) + 1; +} + +int BufferedSoftSerial::printf(const char* format, ...) +{ + char buf[256] = {0}; + int r = 0; + + va_list arg; + va_start(arg, format); + r = vsprintf(buf, format, arg); + // this may not hit the heap but should alert the user anyways + if(r > sizeof(buf)) { + error("%s %d buffer overwrite!\n", __FILE__, __LINE__); + } + va_end(arg); + r = BufferedSoftSerial::write(buf, r); + + return r; +} + +ssize_t BufferedSoftSerial::write(const void *s, size_t length) +{ + const char* ptr = (const char*)s; + const char* end = ptr + length; + + while (ptr != end) { + _txbuf = *(ptr++); + } + BufferedSoftSerial::prime(); + + return ptr - (const char*)s; +} + + +void BufferedSoftSerial::rxIrq(void) +{ + // read from the peripheral and make sure something is available + if(SoftSerial::readable()) { + _rxbuf = _getc(); // if so load them into a buffer + } + + return; +} + +void BufferedSoftSerial::txIrq(void) +{ + // see if there is room in the hardware fifo and if something is in the software fifo + while(SoftSerial::writeable()) { + if(_txbuf.available()) { + _putc((int)_txbuf.get()); + } else { + // disable the TX interrupt when there is nothing left to send + SoftSerial::attach(NULL, SoftSerial::TxIrq); + break; + } + } + + return; +} + +void BufferedSoftSerial::prime(void) +{ + // if already busy then the irq will pick this up + if(SoftSerial::writeable()) { + SoftSerial::attach(NULL, SoftSerial::TxIrq); // make sure not to cause contention in the irq + BufferedSoftSerial::txIrq(); // only write to hardware in one place + SoftSerial::attach(this, &BufferedSoftSerial::txIrq, SoftSerial::TxIrq); + } + + return; +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BufferedSoftSerial.h Sat Apr 26 20:55:42 2014 +0000 @@ -0,0 +1,143 @@ + +/** + * @file BufferedSoftSerial.h + * @brief Software Buffer - Extends mbed Serial functionallity adding irq driven TX and RX + * @author sam grove + * @version 1.0 + * @see + * + * Copyright (c) 2013 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BUFFEREDSOFTSERIAL_H +#define BUFFEREDSOFTSERIAL_H + +#include "mbed.h" +#include "Buffer.h" +#include "SoftSerial.h" + +/** A serial port (UART) for communication with other serial devices + * + * Can be used for Full Duplex communication, or Simplex by specifying + * one pin as NC (Not Connected) + * + * This uses software serial emulation, regular serial pins are alot better, + * however if you don't have spare ones, you can use this. It is advicable + * to put the serial connection with highest speed to hardware serial. + * + * If you lack RAM memory you can also use SoftSerial without this buffer around it. + * In that case it is fully blocking. + * + * Example: + * @code + * #include "mbed.h" + * #include "BufferedSoftSerial.h" + * + * BufferedSoftSerial buf(USBTX, USBRX); + * SoftSerial block(USBTX, USBRX); + * + * int main() + * { + * while(1) { + * Timer s; + * + * s.start(); + * buf.printf("Hello World - buffered\r\n"); + * int buffered_time = s.read_us(); + * wait(0.1f); // give time for the buffer to empty + * + * s.reset(); + * block.printf("Hello World - blocking\r\n"); + * int polled_time = s.read_us(); + * s.stop(); + * wait(0.1f); // give time for the buffer to empty + * + * buf.printf("printf buffered took %d us\r\n", buffered_time); + * buf.printf("printf blocking took %d us\r\n", polled_time); + * wait(5); + * } + * } + * @endcode + */ + +/** + * @class BufferedSerial + * @brief Software buffers and interrupt driven tx and rx for SoftSerial + */ +class BufferedSoftSerial : public SoftSerial +{ +private: + Buffer <char> _rxbuf; + Buffer <char> _txbuf; + + void rxIrq(void); + void txIrq(void); + void prime(void); + +public: + /** Create a BufferedSoftSerial port, connected to the specified transmit and receive pins + * @param tx Transmit pin + * @param rx Receive pin + * @note Either tx or rx may be specified as NC if unused + */ + BufferedSoftSerial(PinName tx, PinName rx, const char* name=NULL); + + /** Destroy a BufferedSoftSerial port + */ + virtual ~BufferedSoftSerial(void); + + /** Check on how many bytes are in the rx buffer + * @return 1 if something exists, 0 otherwise + */ + virtual int readable(void); + + /** Check to see if the tx buffer has room + * @return 1 always has room and can overwrite previous content if too small / slow + */ + virtual int writeable(void); + + /** Get a single byte from the BufferedSoftSerial Port. + * Should check readable() before calling this. + * @return A byte that came in on the BufferedSoftSerial Port + */ + virtual int getc(void); + + /** Write a single byte to the BufferedSoftSerial Port. + * @param c The byte to write to the BufferedSoftSerial Port + * @return The byte that was written to the BufferedSoftSerial Port Buffer + */ + virtual int putc(int c); + + /** Write a string to the BufferedSoftSerial Port. Must be NULL terminated + * @param s The string to write to the Serial Port + * @return The number of bytes written to the Serial Port Buffer + */ + virtual int puts(const char *s); + + /** Write a formatted string to the BufferedSoftSerial Port. + * @param format The string + format specifiers to write to the BufferedSoftSerial Port + * @return The number of bytes written to the Serial Port Buffer + */ + virtual int printf(const char* format, ...); + + /** Write data to the BufferedSoftSerial Port + * @param s A pointer to data to send + * @param length The amount of data being pointed to + * @return The number of bytes written to the Serial Port Buffer + */ + virtual ssize_t write(const void *s, std::size_t length); +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SoftSerial.lib Sat Apr 26 20:55:42 2014 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/Sissors/code/SoftSerial/#acfd0329f648