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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SoftwareSerial.cpp Source File

SoftwareSerial.cpp

00001 #include "mbed.h"
00002 #include "SoftwareSerial.h"
00003 
00004 namespace chag {
00005 
00006 /*unsigned char SoftwareSerial::inbuf[SOFTWARE_SERIAL_RX_BUFFER_SIZE];
00007 unsigned char SoftwareSerial::qin = 0;
00008 unsigned char SoftwareSerial::qout = 0;
00009 char SoftwareSerial::flag_rx_waiting_for_stop_bit;
00010 char SoftwareSerial::flag_rx_off;
00011 char SoftwareSerial::rx_mask;
00012 char SoftwareSerial::flag_rx_ready;
00013 char SoftwareSerial::flag_tx_ready;
00014 char SoftwareSerial::timer_rx_ctr;
00015 char SoftwareSerial::timer_tx_ctr;
00016 char SoftwareSerial::bits_left_in_rx;
00017 char SoftwareSerial::bits_left_in_tx;
00018 char SoftwareSerial::rx_num_of_bits;
00019 char SoftwareSerial::tx_num_of_bits;
00020 char SoftwareSerial::internal_rx_buffer;
00021 char SoftwareSerial::internal_tx_buffer;
00022 char SoftwareSerial::user_tx_buffer;
00023 */
00024 
00025 DigitalOut led1(LED1);
00026 DigitalOut led2(LED2);
00027 DigitalOut led3(LED3);
00028 DigitalOut led4(LED4);
00029 
00030 
00031 SoftwareSerial::SoftwareSerial(PinName tx, PinName rx, const char *name) {
00032     // save pins
00033     
00034     this->tx = (tx == NC) ? (DigitalOut *)NULL : new DigitalOut(tx);
00035     this->rx = (rx == NC) ? (DigitalIn *)NULL : new DigitalIn(rx);
00036     
00037     flag_tx_ready = false;
00038     flag_rx_ready = false;
00039     flag_rx_waiting_for_stop_bit = false;
00040     flag_rx_off = (rx == NC);
00041     rx_num_of_bits = 10;
00042     tx_num_of_bits = 10;
00043 
00044     set_tx_pin_low();
00045 
00046     baud(9600);
00047 }
00048 
00049 void SoftwareSerial::baud(int baudrate) {
00050     baud_rate = baudrate;
00051     ticker.detach();
00052   
00053     ticker.attach_us(this, &SoftwareSerial::timer_isr, 1000000.0 / (baudrate * 3.0));
00054     
00055     //timer_set( baud_rate );   //    Sets the timer to 3 times the baud rate.
00056     //set_timer_interrupt( &SoftwareSerial::timer_isr );
00057 }
00058 
00059 // putc, etc
00060 
00061 int SoftwareSerial::readable() {
00062     return( kbhit() );
00063 }
00064 
00065 int SoftwareSerial::writeable() {
00066     return ( 1 );
00067 }
00068 
00069 // end
00070 
00071 
00072 int SoftwareSerial::get_rx_pin_status() {
00073     //    Returns 0 or 1 dependent on whether the receive pin is high or low.
00074     return( rx->read() );
00075 }
00076 
00077 void SoftwareSerial::set_tx_pin_high() {
00078     //    Sets the transmit pin to the high state.
00079     tx->write(1);
00080     //led4 = 1;
00081 }
00082 
00083 void SoftwareSerial::set_tx_pin_low() {
00084     //    Sets the transmit pin to the low state.
00085     tx->write(0);
00086     //led4 = 0;
00087 }
00088 
00089 void SoftwareSerial::idle() {
00090     //    Background functions to execute while waiting for input.
00091     
00092 }
00093 
00094 
00095 // protected/private members
00096 
00097 void SoftwareSerial::timer_isr( void ) {
00098     char mask, start_bit, flag_in;
00099 
00100     // Transmitter Section
00101     if ( flag_tx_ready ) {
00102         if( --timer_tx_ctr<=0 ) {
00103             mask = internal_tx_buffer&1;
00104             internal_tx_buffer >>= 1;
00105             if ( mask ) {
00106                 set_tx_pin_high();
00107             } else {
00108                 set_tx_pin_low();
00109             }
00110             timer_tx_ctr = 3;
00111             if ( --bits_left_in_tx<=0 ) {
00112                 flag_tx_ready = false;
00113             }
00114         }
00115     }
00116     
00117     // Receiver Section
00118     if ( flag_rx_off==false ) {
00119         if ( flag_rx_waiting_for_stop_bit ) {
00120             if ( --timer_rx_ctr<=0 ) {
00121                 flag_rx_waiting_for_stop_bit = false;
00122                 flag_rx_ready = false;
00123                 internal_rx_buffer &= 0xFF;
00124                 if ( internal_rx_buffer!=0xC2 ) {
00125                     inbuf[qin] = internal_rx_buffer;
00126                     if ( ++qin>=SOFTWARE_SERIAL_RX_BUFFER_SIZE ) {
00127                         qin = 0;
00128                     }
00129                 }
00130             }
00131         } else {    // rx_test_busy
00132             if ( flag_rx_ready==false ) {
00133                 start_bit = get_rx_pin_status();
00134                 // Test for Start Bit
00135                 if ( start_bit==0 ) {
00136                     flag_rx_ready = true;
00137                     internal_rx_buffer = 0;
00138                     timer_rx_ctr = 4;
00139                     bits_left_in_rx = rx_num_of_bits;
00140                     rx_mask = 1;
00141                 }
00142             } else {    // rx_busy
00143                 if ( --timer_rx_ctr<=0 ) {                // rcv
00144                     timer_rx_ctr = 3;
00145                     flag_in = get_rx_pin_status();
00146                     if ( flag_in ) {
00147                         internal_rx_buffer |= rx_mask;
00148                     }
00149                     rx_mask <<= 1;
00150                     if ( --bits_left_in_rx<=0 ) {
00151                         flag_rx_waiting_for_stop_bit = true;
00152                     }
00153                 }
00154             }
00155         }
00156     }
00157 }
00158 
00159 int SoftwareSerial::getc( void ) {
00160     char        ch;
00161 
00162     do {
00163         while ( qout==qin ) {
00164             idle();
00165         }
00166         ch = inbuf[qout] & 0xFF;
00167         if ( ++qout>=SOFTWARE_SERIAL_RX_BUFFER_SIZE ) {
00168             qout = 0;
00169         }
00170     } while ( ch==0x0A || ch==0xC2 );
00171     return( (int)ch );
00172 }
00173 
00174 int SoftwareSerial::putc( int c ) {
00175     led1 = !led1;
00176     while ( flag_tx_ready );
00177     user_tx_buffer = c;
00178 
00179     // invoke_UART_transmit
00180     timer_tx_ctr = 3;
00181     bits_left_in_tx = tx_num_of_bits;
00182     internal_tx_buffer = (user_tx_buffer<<1) | 0x200;
00183     flag_tx_ready = true;
00184     return(1);
00185 }
00186 
00187 void SoftwareSerial::flush_input_buffer( void ) {
00188     qin = 0;
00189     qout = 0;
00190 }
00191 
00192 char SoftwareSerial::kbhit( void ) {
00193     return( qin!=qout );
00194 }
00195 
00196 void SoftwareSerial::turn_rx_on( void ) {
00197     flag_rx_off = false;
00198 }
00199 
00200 void SoftwareSerial::turn_rx_off( void ) {
00201     flag_rx_off = true;
00202 }
00203 
00204 
00205 } // end namespace