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

/home/jgoppert/Projects/ap/libraries/FastSerial/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 // Due to the way interrupt vectors are specified, we have to have
00064 // a separate macro for every port.  Ugh.
00065 //
00066 // The macros are:
00067 //
00068 // FastSerialPort0(<port name>)         creates <port name> referencing serial port 0
00069 // FastSerialPort1(<port name>)         creates <port name> referencing serial port 1
00070 // FastSerialPort2(<port name>)         creates <port name> referencing serial port 2
00071 // FastSerialPort3(<port name>)         creates <port name> referencing serial port 3
00072 //
00073 // Note that macros are only defined for ports that exist on the target device.
00074 //
00075 
00076 //
00077 // Forward declarations for clients that want to assume that the
00078 // default Serial* objects exist.
00079 //
00080 // Note that the application is responsible for ensuring that these
00081 // actually get defined, otherwise Arduino will suck in the
00082 // HardwareSerial library and linking will fail.
00083 //
00084 extern class FastSerial Serial;
00085 extern class FastSerial Serial1;
00086 extern class FastSerial Serial2;
00087 extern class FastSerial Serial3;
00088 
00089 class FastSerial : public BetterStream {
00090 public:
00091         FastSerial(const uint8_t portNumber,
00092                    volatile uint8_t *ubrrh,
00093                    volatile uint8_t *ubrrl,
00094                    volatile uint8_t *ucsra,
00095                    volatile uint8_t *ucsrb,
00096                    const uint8_t u2x,
00097                    const uint8_t portEnableBits,
00098                    const uint8_t portTxBits);
00099 
00100         // Serial API
00101         virtual void    begin(long baud);
00102         virtual void    begin(long baud, unsigned int rxSpace, unsigned int txSpace);
00103         virtual void    end(void);
00104         virtual int     available(void);
00105         virtual int     read(void);
00106         virtual int     peek(void);
00107         virtual void    flush(void);
00108         virtual void    write(uint8_t c);
00109         using BetterStream::write;
00110 
00111         // public so the interrupt handlers can see it
00112         struct Buffer {
00113                 volatile uint16_t head, tail;
00114                 uint16_t        mask;
00115                 uint8_t         *bytes;
00116         };
00117 
00118 private:
00119         // register accessors
00120         volatile uint8_t *_ubrrh;
00121         volatile uint8_t *_ubrrl;
00122         volatile uint8_t *_ucsra;
00123         volatile uint8_t *_ucsrb;
00124 
00125         // register magic numbers
00126         uint8_t         _portEnableBits;        // rx, tx and rx interrupt enables
00127         uint8_t         _portTxBits;            // tx data and completion interrupt enables
00128         uint8_t         _u2x;
00129 
00130         // ring buffers
00131         Buffer          *_rxBuffer;
00132         Buffer          *_txBuffer;
00133         bool            _open;
00134 
00135         static bool     _allocBuffer(Buffer *buffer, unsigned int size);
00136         static void     _freeBuffer(Buffer *buffer);
00137 };
00138 
00139 // Used by the per-port interrupt vectors
00140 extern FastSerial::Buffer       __FastSerial__rxBuffer[];
00141 extern FastSerial::Buffer       __FastSerial__txBuffer[];
00142 
00143 // Generic Rx/Tx vectors for a serial port - needs to know magic numbers
00144 #define FastSerialHandler(_PORT, _RXVECTOR, _TXVECTOR, _UDR, _UCSRB, _TXBITS) \
00145 ISR(_RXVECTOR, ISR_BLOCK)                                               \
00146 {                                                                       \
00147         uint8_t c;                                                      \
00148         int16_t i;                                                      \
00149                                                                         \
00150         /* read the byte as quickly as possible */                      \
00151         c = _UDR;                                                       \
00152         /* work out where the head will go next */                      \
00153         i = (__FastSerial__rxBuffer[_PORT].head + 1) & __FastSerial__rxBuffer[_PORT].mask; \
00154         /* decide whether we have space for another byte */             \
00155         if (i != __FastSerial__rxBuffer[_PORT].tail) {                  \
00156                 /* we do, move the head */                              \
00157                 __FastSerial__rxBuffer[_PORT].bytes[__FastSerial__rxBuffer[_PORT].head] = c; \
00158                 __FastSerial__rxBuffer[_PORT].head = i;                 \
00159         }                                                               \
00160 }                                                                       \
00161 ISR(_TXVECTOR, ISR_BLOCK)                                               \
00162 {                                                                       \
00163         /* if there is another character to send */                     \
00164         if (__FastSerial__txBuffer[_PORT].tail != __FastSerial__txBuffer[_PORT].head) { \
00165                 _UDR = __FastSerial__txBuffer[_PORT].bytes[__FastSerial__txBuffer[_PORT].tail]; \
00166                 /* increment the tail */                                \
00167                 __FastSerial__txBuffer[_PORT].tail =                    \
00168                         (__FastSerial__txBuffer[_PORT].tail + 1) & __FastSerial__txBuffer[_PORT].mask; \
00169         } else {                                                        \
00170                 /* there are no more bytes to send, disable the interrupt */ \
00171                 if (__FastSerial__txBuffer[_PORT].head == __FastSerial__txBuffer[_PORT].tail) \
00172                         _UCSRB &= ~_TXBITS;                             \
00173         }                                                               \
00174 }                                                                       \
00175 struct hack
00176 
00177 //
00178 // Portability; convert various older sets of defines for U(S)ART0 up
00179 // to match the definitions for the 1280 and later devices.
00180 //
00181 #if !defined(USART0_RX_vect)
00182 # if defined(USART_RX_vect)
00183 #  define USART0_RX_vect        USART_RX_vect
00184 #  define USART0_UDRE_vect      USART_UDRE_vect
00185 # elif defined(UART0_RX_vect)
00186 #  define USART0_RX_vect        UART0_RX_vect
00187 #  define USART0_UDRE_vect      UART0_UDRE_vect
00188 # endif
00189 #endif
00190 
00191 #if !defined(USART1_RX_vect)
00192 # if defined(UART1_RX_vect)
00193 #  define USART1_RX_vect        UART1_RX_vect
00194 #  define USART1_UDRE_vect      UART1_UDRE_vect
00195 # endif
00196 #endif
00197 
00198 #if !defined(UDR0)
00199 # if defined(UDR)
00200 #  define UDR0                  UDR
00201 #  define UBRR0H                UBRRH
00202 #  define UBRR0L                UBRRL
00203 #  define UCSR0A                UCSRA
00204 #  define UCSR0B                UCSRB
00205 #  define U2X0                  U2X
00206 #  define RXEN0                 RXEN
00207 #  define TXEN0                 TXEN
00208 #  define RXCIE0                RXCIE
00209 #  define UDRIE0                UDRIE
00210 # endif
00211 #endif
00212 
00213 //
00214 // Macro defining a FastSerial port instance.
00215 //
00216 #define FastSerialPort(_name, _num)                                     \
00217         FastSerial _name(_num,                                          \
00218                          &UBRR##_num##H,                                \
00219                          &UBRR##_num##L,                                \
00220                          &UCSR##_num##A,                                \
00221                          &UCSR##_num##B,                                \
00222                          U2X##_num,                                     \
00223                          (_BV(RXEN##_num) |  _BV(TXEN##_num) | _BV(RXCIE##_num)), \
00224                          (_BV(UDRIE##_num)));                           \
00225         FastSerialHandler(_num,                                         \
00226                           USART##_num##_RX_vect,                        \
00227                           USART##_num##_UDRE_vect,                      \
00228                           UDR##_num,                                    \
00229                           UCSR##_num##B,                                \
00230                           _BV(UDRIE##_num))
00231 
00232 //
00233 // Compatibility macros for previous FastSerial versions.
00234 //
00235 // Note that these are not conditionally defined, as the errors
00236 // generated when using these macros for a board that does not support
00237 // the port are better than the errors generated for a macro that's not
00238 // defined at all.
00239 //
00240 #define FastSerialPort0(_portName)     FastSerialPort(_portName, 0)
00241 #define FastSerialPort1(_portName)     FastSerialPort(_portName, 1)
00242 #define FastSerialPort2(_portName)     FastSerialPort(_portName, 2)
00243 #define FastSerialPort3(_portName)     FastSerialPort(_portName, 3)
00244 
00245 #endif // FastSerial_h

Generated for ArduPilot Libraries by doxygen