diff --git a/libraries/FastSerial/FastSerial.cpp b/libraries/FastSerial/FastSerial.cpp index 8f703bc6ef..5181eac1b6 100644 --- a/libraries/FastSerial/FastSerial.cpp +++ b/libraries/FastSerial/FastSerial.cpp @@ -29,10 +29,10 @@ // +#include "FastSerial.h" #include #include #include -#include "FastSerial.h" #if defined(__AVR_ATmega1280__) # define FS_MAX_PORTS 4 @@ -40,13 +40,14 @@ # define FS_MAX_PORTS 1 #endif -static FastSerial *ports[FS_MAX_PORTS]; +FastSerial *__FastSerial__ports[FS_MAX_PORTS]; #define RX_BUFFER_SIZE sizeof(((FastSerial::RXBuffer *)1)->bytes) #define TX_BUFFER_SIZE sizeof(((FastSerial::TXBuffer *)1)->bytes) // Interrupt handlers ////////////////////////////////////////////////////////// +#if 0 #define HANDLERS(_PORT, _RXVECTOR, _TXVECTOR, _UDR) \ SIGNAL(_RXVECTOR) \ { \ @@ -70,6 +71,7 @@ HANDLERS(2, SIG_USART2_RECV, SIG_USART2_DATA, UDR2); HANDLERS(3, SIG_USART3_RECV, SIG_USART3_DATA, UDR3); #endif #endif +#endif // Constructor ///////////////////////////////////////////////////////////////// @@ -139,7 +141,7 @@ FastSerial::FastSerial(uint8_t portNumber) _rxBuffer.head = _rxBuffer.tail = 0; // claim the port - ports[portNumber] = this; + __FastSerial__ports[portNumber] = this; } // Public Methods ////////////////////////////////////////////////////////////// diff --git a/libraries/FastSerial/FastSerial.h b/libraries/FastSerial/FastSerial.h index b6bc1bc43b..399c092fe5 100644 --- a/libraries/FastSerial/FastSerial.h +++ b/libraries/FastSerial/FastSerial.h @@ -44,11 +44,26 @@ #ifndef FastSerial_h #define FastSerial_h +// disable the stock Arduino serial driver +#define HardwareSerial_h + #include #include -// disable the stock Arduino serial driver -#define HardwareSerial_h +// +// Because Arduino libraries aren't really libraries, but we want to +// only define interrupt handlers for serial ports that are actually +// used, we have to force our users to define them using a macro. +// +// Due to the way interrupt vectors are specified, we have to have +// a separate macro for every port. Ugh. +// +#define FastSerialPort0(_portName) FastSerial _portName(0); FastSerialHandler0 +#if defined(__AVR_ATmega1280__) +#define FastSerialPort1(_portName) FastSerial _portName(1); FastSerialHandler1 +#define FastSerialPort2(_portName) FastSerial _portName(2); FastSerialHandler2 +#define FastSerialPort3(_portName) FastSerial _portName(3); FastSerialHandler3 +#endif class FastSerial : public Print { public: @@ -97,9 +112,40 @@ private: }; // For clients that want to assume that the default Serial* objects exist. +// Note that the application is responsible for ensuring that these actually get defined, +// otherwise Arduino will suck in the HardwareSerial library and linking will fail. extern class FastSerial Serial; extern class FastSerial Serial1; extern class FastSerial Serial2; extern class FastSerial Serial3; +// Used by the per-port interrupt vectors +extern FastSerial *__FastSerial__ports[]; + +// Generic Rx/Tx vectors for a serial port - needs to know magic numbers +#define FastSerialHandler(_PORT, _RXVECTOR, _TXVECTOR, _UDR) \ +ISR(_RXVECTOR, ISR_BLOCK) \ +{ \ + unsigned char c = _UDR; \ + __FastSerial__ports[_PORT]->receive(c); \ +} \ + ISR(_TXVECTOR, ISR_BLOCK) \ +{ \ + __FastSerial__ports[_PORT]->transmit(); \ +} \ +struct hack + +// Magic numbers for the Rx/Tx vectors indexed by serial port number +#if defined(__AVR_ATmega8__) +# define FastSerialHandler0 FastSerialHandler(0, SIG_UART_RECV, SIG_UART_DATA, UDR); +#else +# define FastSerialHandler0 FastSerialHandler(0, SIG_USART0_RECV, SIG_USART0_DATA, UDR0); +#endif +#if defined(__AVR_ATmega1280__) +# define FastSerialHandler1 FastSerialHandler(1, SIG_USART1_RECV, SIG_USART1_DATA, UDR1); +# define FastSerialHandler2 FastSerialHandler(2, SIG_USART2_RECV, SIG_USART2_DATA, UDR2); +# define FastSerialHandler3 FastSerialHandler(3, SIG_USART3_RECV, SIG_USART3_DATA, UDR3); +#endif + + #endif // FastSerial_h