• Main Page
  • Related Pages
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

FastSerial.h

Go to the documentation of this file.
00001 // -*- Mode: C++; c-basic-offset: 8; indent-tabs-mode: nil -*-
00002 //
00003 // Interrupt-driven serial transmit/receive library.
00004 //
00005 //      Copyright (c) 2010 Michael Smith. All rights reserved.
00006 //
00007 // Receive and baudrate calculations derived from the Arduino 
00008 // HardwareSerial driver:
00009 //
00010 //      Copyright (c) 2006 Nicholas Zambetti.  All right reserved.
00011 //
00012 // Transmit algorithm inspired by work:
00013 //
00014 //      Code Jose Julio and Jordi Munoz. DIYDrones.com
00015 //
00016 //      This library is free software; you can redistribute it and/or
00017 //      modify it under the terms of the GNU Lesser General Public
00018 //      License as published by the Free Software Foundation; either
00019 //      version 2.1 of the License, or (at your option) any later
00020 //      version.
00021 //
00022 //      This library is distributed in the hope that it will be
00023 //      useful, but WITHOUT ANY WARRANTY; without even the implied
00024 //      warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
00025 //      PURPOSE.  See the GNU Lesser General Public License for more
00026 //      details.
00027 //
00028 //      You should have received a copy of the GNU Lesser General
00029 //      Public License along with this library; if not, write to the
00030 //      Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
00031 //      Boston, MA 02110-1301 USA
00032 //
00033 
00034 //
00035 // Note that this library does not pre-declare drivers for serial
00036 // ports; the user must explicitly create drivers for the ports they
00037 // wish to use.  This is less friendly than the stock Arduino driver,
00038 // but it saves 24 bytes of RAM for every unused port and frees up
00039 // the vector for another driver (e.g. MSPIM on USARTs).
00040 //
00041 
00042 #ifndef FastSerial_h
00043 #define FastSerial_h
00044 
00045 // disable the stock Arduino serial driver
00046 #ifdef HardwareSerial_h
00047 # error Must include FastSerial.h before the Arduino serial driver is defined.
00048 #endif
00049 #define HardwareSerial_h
00050 
00051 #include <inttypes.h>
00052 #include <stdlib.h>
00053 #include <avr/io.h>
00054 #include <avr/interrupt.h>
00055 
00056 #include "BetterStream.h"
00057 
00058 //
00059 // Because Arduino libraries aren't really libraries, but we want to
00060 // only define interrupt handlers for serial ports that are actually
00061 // used, we have to force our users to define them using a macro.
00062 //
00063 // FastSerialPort(<port name>, <port number>)
00064 //
00065 // <port name> is the name of the object that will be created by the
00066 // macro.  <port number> is the 0-based number of the port that will
00067 // be managed by the object.
00068 //
00069 // Previously ports were defined with a different macro for each port,
00070 // and these macros are retained for compatibility:
00071 //
00072 // FastSerialPort0(<port name>)         creates <port name> referencing serial port 0
00073 // FastSerialPort1(<port name>)         creates <port name> referencing serial port 1
00074 // FastSerialPort2(<port name>)         creates <port name> referencing serial port 2
00075 // FastSerialPort3(<port name>)         creates <port name> referencing serial port 3
00076 //
00077 // Note that compatibility macros are only defined for ports that
00078 // exist on the target device.
00079 //
00080 
00081 //
00082 // Forward declarations for clients that want to assume that the
00083 // default Serial* objects exist.
00084 //
00085 // Note that the application is responsible for ensuring that these
00086 // actually get defined, otherwise Arduino will suck in the
00087 // HardwareSerial library and linking will fail.
00088 //
00089 extern class FastSerial Serial;
00090 extern class FastSerial Serial1;
00091 extern class FastSerial Serial2;
00092 extern class FastSerial Serial3;
00093 
00094 class FastSerial : public BetterStream {
00095 public:
00096         FastSerial(const uint8_t portNumber,
00097                    volatile uint8_t *ubrrh,
00098                    volatile uint8_t *ubrrl,
00099                    volatile uint8_t *ucsra,
00100                    volatile uint8_t *ucsrb,
00101                    const uint8_t u2x,
00102                    const uint8_t portEnableBits,
00103                    const uint8_t portTxBits);
00104 
00105         // Serial API
00106         virtual void    begin(long baud);
00107         virtual void    begin(long baud, unsigned int rxSpace, unsigned int txSpace);
00108         virtual void    end(void);
00109         virtual int     available(void);
00110         virtual int     read(void);
00111         virtual int     peek(void);
00112         virtual void    flush(void);
00113         virtual void    write(uint8_t c);
00114         using BetterStream::write;
00115 
00116         // public so the interrupt handlers can see it
00117         struct Buffer {
00118                 volatile uint16_t head, tail;
00119                 uint16_t        mask;
00120                 uint8_t         *bytes;
00121         };
00122 
00123 private:
00124         // register accessors
00125         volatile uint8_t *_ubrrh;
00126         volatile uint8_t *_ubrrl;
00127         volatile uint8_t *_ucsra;
00128         volatile uint8_t *_ucsrb;
00129 
00130         // register magic numbers
00131         uint8_t         _portEnableBits;        // rx, tx and rx interrupt enables
00132         uint8_t         _portTxBits;            // tx data and completion interrupt enables
00133         uint8_t         _u2x;
00134 
00135         // ring buffers
00136         Buffer          *_rxBuffer;
00137         Buffer          *_txBuffer;
00138         bool            _open;
00139 
00140         static bool     _allocBuffer(Buffer *buffer, unsigned int size);
00141         static void     _freeBuffer(Buffer *buffer);
00142 };
00143 
00144 // Used by the per-port interrupt vectors
00145 extern FastSerial::Buffer       __FastSerial__rxBuffer[];
00146 extern FastSerial::Buffer       __FastSerial__txBuffer[];
00147 
00148 // Generic Rx/Tx vectors for a serial port - needs to know magic numbers
00149 #define FastSerialHandler(_PORT, _RXVECTOR, _TXVECTOR, _UDR, _UCSRB, _TXBITS) \
00150 ISR(_RXVECTOR, ISR_BLOCK)                                               \
00151 {                                                                       \
00152         uint8_t c;                                                      \
00153         int16_t i;                                                      \
00154                                                                         \
00155         /* read the byte as quickly as possible */                      \
00156         c = _UDR;                                                       \
00157         /* work out where the head will go next */                      \
00158         i = (__FastSerial__rxBuffer[_PORT].head + 1) & __FastSerial__rxBuffer[_PORT].mask; \
00159         /* decide whether we have space for another byte */             \
00160         if (i != __FastSerial__rxBuffer[_PORT].tail) {                  \
00161                 /* we do, move the head */                              \
00162                 __FastSerial__rxBuffer[_PORT].bytes[__FastSerial__rxBuffer[_PORT].head] = c; \
00163                 __FastSerial__rxBuffer[_PORT].head = i;                 \
00164         }                                                               \
00165 }                                                                       \
00166 ISR(_TXVECTOR, ISR_BLOCK)                                               \
00167 {                                                                       \
00168         /* if there is another character to send */                     \
00169         if (__FastSerial__txBuffer[_PORT].tail != __FastSerial__txBuffer[_PORT].head) { \
00170                 _UDR = __FastSerial__txBuffer[_PORT].bytes[__FastSerial__txBuffer[_PORT].tail]; \
00171                 /* increment the tail */                                \
00172                 __FastSerial__txBuffer[_PORT].tail =                    \
00173                         (__FastSerial__txBuffer[_PORT].tail + 1) & __FastSerial__txBuffer[_PORT].mask; \
00174         } else {                                                        \
00175                 /* there are no more bytes to send, disable the interrupt */ \
00176                 if (__FastSerial__txBuffer[_PORT].head == __FastSerial__txBuffer[_PORT].tail) \
00177                         _UCSRB &= ~_TXBITS;                             \
00178         }                                                               \
00179 }                                                                       \
00180 struct hack
00181 
00182 //
00183 // Portability; convert various older sets of defines for U(S)ART0 up
00184 // to match the definitions for the 1280 and later devices.
00185 //
00186 #if !defined(USART0_RX_vect)
00187 # if defined(USART_RX_vect)
00188 #  define USART0_RX_vect        USART_RX_vect
00189 #  define USART0_UDRE_vect      USART_UDRE_vect
00190 # elif defined(UART0_RX_vect)
00191 #  define USART0_RX_vect        UART0_RX_vect
00192 #  define USART0_UDRE_vect      UART0_UDRE_vect
00193 # endif
00194 #endif
00195 
00196 #if !defined(USART1_RX_vect)
00197 # if defined(UART1_RX_vect)
00198 #  define USART1_RX_vect        UART1_RX_vect
00199 #  define USART1_UDRE_vect      UART1_UDRE_vect
00200 # endif
00201 #endif
00202 
00203 #if !defined(UDR0)
00204 # if defined(UDR)
00205 #  define UDR0                  UDR
00206 #  define UBRR0H                UBRRH
00207 #  define UBRR0L                UBRRL
00208 #  define UCSR0A                UCSRA
00209 #  define UCSR0B                UCSRB
00210 #  define U2X0                  U2X
00211 #  define RXEN0                 RXEN
00212 #  define TXEN0                 TXEN
00213 #  define RXCIE0                RXCIE
00214 #  define UDRIE0                UDRIE
00215 # endif
00216 #endif
00217 
00218 //
00219 // Macro defining a FastSerial port instance.
00220 //
00221 #define FastSerialPort(_name, _num)                                     \
00222         FastSerial _name(_num,                                          \
00223                          &UBRR##_num##H,                                \
00224                          &UBRR##_num##L,                                \
00225                          &UCSR##_num##A,                                \
00226                          &UCSR##_num##B,                                \
00227                          U2X##_num,                                     \
00228                          (_BV(RXEN##_num) |  _BV(TXEN##_num) | _BV(RXCIE##_num)), \
00229                          (_BV(UDRIE##_num)));                           \
00230         FastSerialHandler(_num,                                         \
00231                           USART##_num##_RX_vect,                        \
00232                           USART##_num##_UDRE_vect,                      \
00233                           UDR##_num,                                    \
00234                           UCSR##_num##B,                                \
00235                           _BV(UDRIE##_num))
00236 
00237 //
00238 // Compatibility macros for previous FastSerial versions.
00239 //
00240 // Note that these are not conditionally defined, as the errors
00241 // generated when using these macros for a board that does not support
00242 // the port are better than the errors generated for a macro that's not
00243 // defined at all.
00244 //
00245 #define FastSerialPort0(_portName)     FastSerialPort(_portName, 0)
00246 #define FastSerialPort1(_portName)     FastSerialPort(_portName, 1)
00247 #define FastSerialPort2(_portName)     FastSerialPort(_portName, 2)
00248 #define FastSerialPort3(_portName)     FastSerialPort(_portName, 3)
00249 
00250 #endif // FastSerial_h

Generated for ArduPilot Libraries by doxygen