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\\
Revision 0:25b087be2989, committed 2012-03-17
- Comitter:
- chag
- Date:
- Sat Mar 17 17:25:55 2012 +0000
- Commit message:
Changed in this revision
SoftwareSerial.cpp | Show annotated file Show diff for this revision Revisions of this file |
SoftwareSerial.h | Show annotated file Show diff for this revision Revisions of this file |
diff -r 000000000000 -r 25b087be2989 SoftwareSerial.cpp --- /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
diff -r 000000000000 -r 25b087be2989 SoftwareSerial.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SoftwareSerial.h Sat Mar 17 17:25:55 2012 +0000 @@ -0,0 +1,272 @@ +// modified from mbed library, original copyright: + +/* mbed Microcontroller Library - Serial + * Copyright (c) 2007-2011 ARM Limited. All rights reserved. + */ + + +#ifndef SOFTWARE_SERIAL_H +#define SOFTWARE_SERIAL_H + +#ifndef SOFTWARE_SERIAL_RX_BUFFER_SIZE +#define SOFTWARE_SERIAL_RX_BUFFER_SIZE 256 +#endif + + +#include "mbed.h" + + +namespace SoftwareSerial { + +/* Class: SoftwareSerial + * A software implemented 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: + * > // Print "Hello World" to the PC + * > + * > #include "mbed.h" + * > #include "SoftwareSerial.h" + * > + * > SoftwareSerial ser(P19, P20); + * > + * > int main() { + * > ser.printf("Hello World\n"); + * > } + */ +class SoftwareSerial : public Stream { + +public: + + /* Constructor: SoftwareSerial + * Create a SoftwareSerial port, connected to the specified transmit and receive pins + * + * Variables: + * tx - Transmit pin + * rx - Receive pin + * + * Note: Either tx or rx may be specified as NC if unused + */ + SoftwareSerial(PinName tx, PinName rx, const char *name = NULL); + + /* Function: baud + * Set the baud rate of the serial port + * + * Variables: + * 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 + }; + + /* Function: format + * Set the transmission format used by the Serial port + * + * Variables: + * bits - The number of bits in a word (5-8; default = 8) + * parity - The parity used (SoftwareSerial::None, SoftwareSerial::Odd, SoftwareSerial::Even, SoftwareSerial::Forced1, SoftwareSerial::Forced0; default = SoftwareSerial::None) + * stop - The number of stop bits (1 or 2; default = 1) + */ + /*void format(int bits = 8, Parity parity = Serial::None, int stop_bits = 1); */ + +#if 0 // Inhereted from Stream, for documentation only + + /* Function: putc + * Write a character + * + * Variables: + * c - The character to write to the serial port + */ + int putc(int c); + + + /* Function: getc + * Read a character + * + * Reads a character from the serial port. This will block until + * a character is available. To see if a character is available, + * see <readable> + * + * Variables: + * returns - The character read from the serial port + */ + int getc(); + + /* Function: printf + * Write a formated string + * + * Variables: + * format - A printf-style format string, followed by the + * variables to use in formating the string. + */ + int printf(const char* format, ...); + + /* Function: scanf + * Read a formated string + * + * Variables: + * format - A scanf-style format string, + * followed by the pointers to variables to store the results. + */ + int scanf(const char* format, ...); + +#endif + + +#if 1 + /** putc + * @param int c The byte to write. + */ + int putc(int c); + + /** puts + * @param char * The string to print. + */ + //void puts(char *s); + + /** getc + * @return int c The byte read or -1 if no bytes to read. + */ + int getc(void); + + /** gets + * Get a string. Note, this method blocks until size bytes are read. + * @param char *s where to place the incoming bytes. + * @param int size How many bytes to read. + * @return char * The value of *s passed in. + */ + //char *gets(char *s, int size); + + /** peek + * like getc() but does NOT remove the byte from the buffer. + * @see getc*( + */ + //int peek(void); + +#endif + + /* Function: readable + * Determine if there is a character available to read + * + * Variables: + * returns - 1 if there is a character available to read, else 0 + */ + int readable(); + + /* Function: writeable + * Determine if there is space available to write a character + * + * Variables: + * returns - 1 if there is space to write a character, else 0 + */ + int writeable(); + + /* Function: attach + * Attach a function to call whenever a serial interrupt is generated + * + * Variables: + * fptr - A pointer to a void function, or 0 to set as none + * 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); + + /* Function: attach + * Attach a member function to call whenever a serial interrupt is generated + * + * Variables: + * tptr - pointer to the object to call the member function on + * mptr - pointer to the member function to be called + * 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) { + if((mptr != NULL) && (tptr != NULL)) { + _irq[type].attach(tptr, mptr); + setup_interrupt(type); + } + } + +#ifdef MBED_RPC + //virtual const struct rpc_method *get_rpc_methods(); + static struct rpc_class *get_rpc_class(); +#endif + +protected: + + //void setup_interrupt(IrqType type); + //void remove_interrupt(IrqType type); + + //UARTName _uart; + //FunctionPointer _irq[2]; + //int _uidx; + + virtual int _putc(int c) { return putc(c); } + virtual int _getc() { return getc(); } + + + + int get_rx_pin_status(); + void set_tx_pin_high(); + void set_tx_pin_low(); + void idle(); + void timer_set( int baud ); + void set_timer_interrupt( void (*timer_isr)(void) ); + + + + void timer_isr( void ); + void init_uart( void ); + //char _getchar( void ); + //void _putchar( char ch ); + void flush_input_buffer( void ); + char kbhit( void ); + void turn_rx_on( void ); + void turn_rx_off( void ); + + +private: + DigitalOut *tx; + DigitalIn *rx; + + Ticker ticker; + + int baud_rate; + + unsigned char inbuf[SOFTWARE_SERIAL_RX_BUFFER_SIZE]; + unsigned char qin; + unsigned char qout; + char flag_rx_waiting_for_stop_bit; + bool flag_rx_off; + char rx_mask; + bool flag_rx_ready; + bool flag_tx_ready; + char timer_rx_ctr; + char timer_tx_ctr; + char bits_left_in_rx; + char bits_left_in_tx; + char rx_num_of_bits; + char tx_num_of_bits; + char internal_rx_buffer; + char internal_tx_buffer; + char user_tx_buffer; + +}; + +} // namespace + +using namespace SoftwareSerial; + +#endif