Software serial, for when you are out of serial pins

Dependents:   BufferedSoftSerial neurGAI_Seeed_BLUETOOTH LPC-SD-35 ESP-WROOM-02_test ... more

Files at this revision

API Documentation at this revision

Comitter:
Sissors
Date:
Sat Apr 26 14:46:03 2014 +0000
Child:
1:f8b4b764ace7
Commit message:
TX basic finished

Changed in this revision

SoftSerial.cpp Show annotated file Show diff for this revision Revisions of this file
SoftSerial.h Show annotated file Show diff for this revision Revisions of this file
SoftSerial_rx.cpp Show annotated file Show diff for this revision Revisions of this file
SoftSerial_tx.cpp Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SoftSerial.cpp	Sat Apr 26 14:46:03 2014 +0000
@@ -0,0 +1,29 @@
+#include "SoftSerial.h"
+
+SoftSerial::SoftSerial(PinName TX, PinName RX) {
+    tx_en = rx_en = false;
+    if (TX != NC) {
+        tx = new DigitalOut(TX);
+        tx_en = true;
+        tx->write(1);
+        tx_bit = -1;
+    }
+    if (RX != NC) {
+        rx = new InterruptIn(RX);
+        rx_en = true;
+        rx->fall(this, &SoftSerial::rx_gpio_irq_handler);
+    }
+    
+    baud(9600);
+    format();
+}
+
+void SoftSerial::baud(int baudrate) {
+    bit_period = 1000000 / baudrate;
+}
+
+void SoftSerial::format(int bits, Parity parity, int stop_bits) {
+    _bits = bits;
+    _parity = parity;
+    _stop_bits = stop_bits;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SoftSerial.h	Sat Apr 26 14:46:03 2014 +0000
@@ -0,0 +1,111 @@
+#ifndef SOFTSERIAL_H
+#define SOFTSERIAL_H
+
+#include "mbed.h"
+
+/** A software serial implementation
+ *
+ */
+class SoftSerial: public Stream {
+
+public:
+    /**
+    * Constructor
+    *
+    * @param TX Name of the TX pin, NC for not connected
+    * @param RX Name of the RX pin, NC for not connected, must be capable of being InterruptIn
+    */
+    SoftSerial(PinName TX, PinName RX);
+    
+    /** Set the baud rate of the serial port
+     *
+     *  @param baudrate The baudrate of the serial port (default = 9600).
+     */
+    void baud(int baudrate);
+
+    enum Parity {
+        None = 0,
+        Odd,
+        Even,
+        Forced1,
+        Forced0
+    };
+
+    enum IrqType {
+        RxIrq = 0,
+        TxIrq
+    };
+
+    /** Set the transmission format used by the serial port
+     *
+     *  @param bits The number of bits in a word (default = 8)
+     *  @param parity The parity used (SerialBase::None, SerialBase::Odd, SerialBase::Even, SerialBase::Forced1, SerialBase::Forced0; default = SerialBase::None)
+     *  @param stop The number of stop bits (default = 1)
+     */
+    void format(int bits=8, Parity parity=SoftSerial::None, int stop_bits=1);
+
+    /** Determine if there is a character available to read
+     *
+     *  @returns
+     *    1 if there is a character available to read,
+     *    0 otherwise
+     */
+    int readable();
+
+    /** Determine if there is space available to write a character
+     *
+     *  @returns
+     *    1 if there is space to write a character,
+     *    0 otherwise
+     */
+    int writeable();
+
+    /** Attach a function to call whenever a serial interrupt is generated
+     *
+     *  @param fptr A pointer to a void function, or 0 to set as none
+     *  @param type Which serial interrupt to attach the member function to (Seriall::RxIrq for receive, TxIrq for transmit buffer empty)
+     */
+    void attach(void (*fptr)(void), IrqType type=RxIrq);
+
+    /** Attach a member function to call whenever a serial interrupt is generated
+     *
+     *  @param tptr pointer to the object to call the member function on
+     *  @param mptr pointer to the member function to be called
+     *  @param type Which serial interrupt to attach the member function to (Seriall::RxIrq for receive, TxIrq for transmit buffer empty)
+     */
+    template<typename T>
+    void attach(T* tptr, void (T::*mptr)(void), IrqType type=RxIrq);
+
+    /** Generate a break condition on the serial line
+     */
+    void send_break();
+
+protected:
+    DigitalOut *tx;
+    InterruptIn *rx;
+    
+    bool tx_en, rx_en;
+    int bit_period;
+    int _bits, _stop_bits;
+    Parity _parity;
+    
+    void rx_gpio_irq_handler(void);
+    void rx_fall_handler(void);
+    void rx_handler(bool rise);
+    
+    //tx
+    void tx_handler(void);
+    inline int get_bit(int bit);
+    Timeout timeout;
+    int _char;
+    volatile int tx_bit;
+    
+    
+    
+    virtual int _getc();
+    virtual int _putc(int c);
+};
+
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SoftSerial_rx.cpp	Sat Apr 26 14:46:03 2014 +0000
@@ -0,0 +1,10 @@
+#include "SoftSerial.h"
+
+int SoftSerial::_getc( void ) {
+    return 0;
+    }
+
+void SoftSerial::rx_gpio_irq_handler(void) {
+    
+};    
+ 
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SoftSerial_tx.cpp	Sat Apr 26 14:46:03 2014 +0000
@@ -0,0 +1,77 @@
+#include "SoftSerial.h"
+
+int SoftSerial::_putc(int c) {
+    while(!writeable());
+    tx_bit = 0;
+    _char = c;
+    tx_handler();
+    return 0;
+    }
+
+int SoftSerial::writeable(void) {
+    if (!tx_en)
+        return false;
+    if (tx_bit == -1)
+        return true;
+    return false;
+}
+
+void SoftSerial::tx_handler(void) {
+    if (get_bit(tx_bit) == -1) {
+        tx_bit = -1;
+        return;
+    }
+    
+    //Flip output
+    int cur_out = tx->read();
+    tx->write(!cur_out);
+         
+    //Calculate when to do it again
+    int count = bit_period;
+    tx_bit++;
+    while(get_bit(tx_bit) == !cur_out) {
+        count+=bit_period;
+        tx_bit++;
+    }
+    
+    timeout.attach_us(this, &SoftSerial::tx_handler, count);
+}
+
+int SoftSerial::get_bit(int bit) {
+    //Start bit is never asked
+    
+    //Data bits
+    if (bit <= _bits )
+        return ((_char >> (bit - 1)) & 0x01);
+    
+    //Parity
+    bool retval;
+    if (bit == _bits + 1) {
+        switch (_parity) {
+            case Forced1:
+                return 1;
+            case Forced0:
+                return 0;
+            case Even:
+                retval = false;
+                for (int i = 0; i<_bits; i++) {
+                    if (((_char >> i) & 0x01) == 1)
+                        retval = !retval;
+                }
+                return retval;
+            case Odd:
+                retval = true;
+                for (int i = 0; i<_bits; i++) {
+                    if (((_char >> i) & 0x01) == 1)
+                        retval = !retval;
+                }
+                return retval;
+        }
+    }
+    
+    //Stop bits:
+    if (bit < 1 + _bits + (bool)_parity + _stop_bits) 
+        return 1;
+    
+    return -1;   
+}
\ No newline at end of file