ALPHA WORK IN PROGRESS. DO NOT USE IN PRODUCTION CODE. based on:\\ IAR Application Note G - 001 Generic Software UART\\ mbed/trunk/Serial.h\\ the venerable Andy Kirkham's MAX3100\\

Dependents:   SoftwareUART

Revision:
0:25b087be2989
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SoftwareSerial.cpp	Sat Mar 17 17:25:55 2012 +0000
@@ -0,0 +1,205 @@
+#include "mbed.h"
+#include "SoftwareSerial.h"
+
+namespace chag {
+
+/*unsigned char SoftwareSerial::inbuf[SOFTWARE_SERIAL_RX_BUFFER_SIZE];
+unsigned char SoftwareSerial::qin = 0;
+unsigned char SoftwareSerial::qout = 0;
+char SoftwareSerial::flag_rx_waiting_for_stop_bit;
+char SoftwareSerial::flag_rx_off;
+char SoftwareSerial::rx_mask;
+char SoftwareSerial::flag_rx_ready;
+char SoftwareSerial::flag_tx_ready;
+char SoftwareSerial::timer_rx_ctr;
+char SoftwareSerial::timer_tx_ctr;
+char SoftwareSerial::bits_left_in_rx;
+char SoftwareSerial::bits_left_in_tx;
+char SoftwareSerial::rx_num_of_bits;
+char SoftwareSerial::tx_num_of_bits;
+char SoftwareSerial::internal_rx_buffer;
+char SoftwareSerial::internal_tx_buffer;
+char SoftwareSerial::user_tx_buffer;
+*/
+
+DigitalOut led1(LED1);
+DigitalOut led2(LED2);
+DigitalOut led3(LED3);
+DigitalOut led4(LED4);
+
+
+SoftwareSerial::SoftwareSerial(PinName tx, PinName rx, const char *name) {
+    // save pins
+    
+    this->tx = (tx == NC) ? (DigitalOut *)NULL : new DigitalOut(tx);
+    this->rx = (rx == NC) ? (DigitalIn *)NULL : new DigitalIn(rx);
+    
+    flag_tx_ready = false;
+    flag_rx_ready = false;
+    flag_rx_waiting_for_stop_bit = false;
+    flag_rx_off = (rx == NC);
+    rx_num_of_bits = 10;
+    tx_num_of_bits = 10;
+
+    set_tx_pin_low();
+
+    baud(9600);
+}
+
+void SoftwareSerial::baud(int baudrate) {
+    baud_rate = baudrate;
+    ticker.detach();
+  
+    ticker.attach_us(this, &SoftwareSerial::timer_isr, 1000000.0 / (baudrate * 3.0));
+    
+    //timer_set( baud_rate );   //    Sets the timer to 3 times the baud rate.
+    //set_timer_interrupt( &SoftwareSerial::timer_isr );
+}
+
+// putc, etc
+
+int SoftwareSerial::readable() {
+    return( kbhit() );
+}
+
+int SoftwareSerial::writeable() {
+    return ( 1 );
+}
+
+// end
+
+
+int SoftwareSerial::get_rx_pin_status() {
+    //    Returns 0 or 1 dependent on whether the receive pin is high or low.
+    return( rx->read() );
+}
+
+void SoftwareSerial::set_tx_pin_high() {
+    //    Sets the transmit pin to the high state.
+    tx->write(1);
+    //led4 = 1;
+}
+
+void SoftwareSerial::set_tx_pin_low() {
+    //    Sets the transmit pin to the low state.
+    tx->write(0);
+    //led4 = 0;
+}
+
+void SoftwareSerial::idle() {
+    //    Background functions to execute while waiting for input.
+    
+}
+
+
+// protected/private members
+
+void SoftwareSerial::timer_isr( void ) {
+    char mask, start_bit, flag_in;
+
+    // Transmitter Section
+    if ( flag_tx_ready ) {
+        if( --timer_tx_ctr<=0 ) {
+            mask = internal_tx_buffer&1;
+            internal_tx_buffer >>= 1;
+            if ( mask ) {
+                set_tx_pin_high();
+            } else {
+                set_tx_pin_low();
+            }
+            timer_tx_ctr = 3;
+            if ( --bits_left_in_tx<=0 ) {
+                flag_tx_ready = false;
+            }
+        }
+    }
+    
+    // Receiver Section
+    if ( flag_rx_off==false ) {
+        if ( flag_rx_waiting_for_stop_bit ) {
+            if ( --timer_rx_ctr<=0 ) {
+                flag_rx_waiting_for_stop_bit = false;
+                flag_rx_ready = false;
+                internal_rx_buffer &= 0xFF;
+                if ( internal_rx_buffer!=0xC2 ) {
+                    inbuf[qin] = internal_rx_buffer;
+                    if ( ++qin>=SOFTWARE_SERIAL_RX_BUFFER_SIZE ) {
+                        qin = 0;
+                    }
+                }
+            }
+        } else {    // rx_test_busy
+            if ( flag_rx_ready==false ) {
+                start_bit = get_rx_pin_status();
+                // Test for Start Bit
+                if ( start_bit==0 ) {
+                    flag_rx_ready = true;
+                    internal_rx_buffer = 0;
+                    timer_rx_ctr = 4;
+                    bits_left_in_rx = rx_num_of_bits;
+                    rx_mask = 1;
+                }
+            } else {    // rx_busy
+                if ( --timer_rx_ctr<=0 ) {                // rcv
+                    timer_rx_ctr = 3;
+                    flag_in = get_rx_pin_status();
+                    if ( flag_in ) {
+                        internal_rx_buffer |= rx_mask;
+                    }
+                    rx_mask <<= 1;
+                    if ( --bits_left_in_rx<=0 ) {
+                        flag_rx_waiting_for_stop_bit = true;
+                    }
+                }
+            }
+        }
+    }
+}
+
+int SoftwareSerial::getc( void ) {
+    char        ch;
+
+    do {
+        while ( qout==qin ) {
+            idle();
+        }
+        ch = inbuf[qout] & 0xFF;
+        if ( ++qout>=SOFTWARE_SERIAL_RX_BUFFER_SIZE ) {
+            qout = 0;
+        }
+    } while ( ch==0x0A || ch==0xC2 );
+    return( (int)ch );
+}
+
+int SoftwareSerial::putc( int c ) {
+    led1 = !led1;
+    while ( flag_tx_ready );
+    user_tx_buffer = c;
+
+    // invoke_UART_transmit
+    timer_tx_ctr = 3;
+    bits_left_in_tx = tx_num_of_bits;
+    internal_tx_buffer = (user_tx_buffer<<1) | 0x200;
+    flag_tx_ready = true;
+    return(1);
+}
+
+void SoftwareSerial::flush_input_buffer( void ) {
+    qin = 0;
+    qout = 0;
+}
+
+char SoftwareSerial::kbhit( void ) {
+    return( qin!=qout );
+}
+
+void SoftwareSerial::turn_rx_on( void ) {
+    flag_rx_off = false;
+}
+
+void SoftwareSerial::turn_rx_off( void ) {
+    flag_rx_off = true;
+}
+
+
+} // end namespace
\ No newline at end of file