1 | /* |
2 | HardwareSerial_private.h - Hardware serial library for Wiring |
3 | Copyright (c) 2006 Nicholas Zambetti. All right reserved. |
4 | |
5 | This library is free software; you can redistribute it and/or |
6 | modify it under the terms of the GNU Lesser General Public |
7 | License as published by the Free Software Foundation; either |
8 | version 2.1 of the License, or (at your option) any later version. |
9 | |
10 | This library is distributed in the hope that it will be useful, |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | Lesser General Public License for more details. |
14 | |
15 | You should have received a copy of the GNU Lesser General Public |
16 | License along with this library; if not, write to the Free Software |
17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
18 | |
19 | Modified 23 November 2006 by David A. Mellis |
20 | Modified 28 September 2010 by Mark Sproul |
21 | Modified 14 August 2012 by Alarus |
22 | */ |
23 |
|
24 | #include "wiring_private.h" |
25 |
|
26 | // this next line disables the entire HardwareSerial.cpp, |
27 | // this is so I can support Attiny series and any other chip without a uart |
28 | #if defined(HAVE_HWSERIAL0) || defined(HAVE_HWSERIAL1) || defined(HAVE_HWSERIAL2) || defined(HAVE_HWSERIAL3) |
29 |
|
30 | // Ensure that the various bit positions we use are available with a 0 |
31 | // postfix, so we can always use the values for UART0 for all UARTs. The |
32 | // alternative, passing the various values for each UART to the |
33 | // HardwareSerial constructor also works, but makes the code bigger and |
34 | // slower. |
35 | #if !defined(TXC0) |
36 | #if defined(TXC) |
37 | // Some chips like ATmega8 don't have UPE, only PE. The other bits are |
38 | // named as expected. |
39 | #if !defined(UPE) && defined(PE) |
40 | #define UPE PE |
41 | #endif |
42 | // On ATmega8, the uart and its bits are not numbered, so there is no TXC0 etc. |
43 | #define TXC0 TXC |
44 | #define RXEN0 RXEN |
45 | #define TXEN0 TXEN |
46 | #define RXCIE0 RXCIE |
47 | #define UDRIE0 UDRIE |
48 | #define U2X0 U2X |
49 | #define UPE0 UPE |
50 | #define UDRE0 UDRE |
51 | #elif defined(TXC1) |
52 | // Some devices have uart1 but no uart0 |
53 | #define TXC0 TXC1 |
54 | #define RXEN0 RXEN1 |
55 | #define TXEN0 TXEN1 |
56 | #define RXCIE0 RXCIE1 |
57 | #define UDRIE0 UDRIE1 |
58 | #define U2X0 U2X1 |
59 | #define UPE0 UPE1 |
60 | #define UDRE0 UDRE1 |
61 | #else |
62 | #error No UART found in HardwareSerial.cpp |
63 | #endif |
64 | #endif // !defined TXC0 |
65 | |
66 | // Check at compiletime that it is really ok to use the bit positions of |
67 | // UART0 for the other UARTs as well, in case these values ever get |
68 | // changed for future hardware. |
69 | #if defined(TXC1) && (TXC1 != TXC0 || RXEN1 != RXEN0 || RXCIE1 != RXCIE0 || \ |
70 | UDRIE1 != UDRIE0 || U2X1 != U2X0 || UPE1 != UPE0 || \ |
71 | UDRE1 != UDRE0) |
72 | #error "Not all bit positions for UART1 are the same as for UART0" |
73 | #endif |
74 | #if defined(TXC2) && (TXC2 != TXC0 || RXEN2 != RXEN0 || RXCIE2 != RXCIE0 || \ |
75 | UDRIE2 != UDRIE0 || U2X2 != U2X0 || UPE2 != UPE0 || \ |
76 | UDRE2 != UDRE0) |
77 | #error "Not all bit positions for UART2 are the same as for UART0" |
78 | #endif |
79 | #if defined(TXC3) && (TXC3 != TXC0 || RXEN3 != RXEN0 || RXCIE3 != RXCIE0 || \ |
80 | UDRIE3 != UDRIE0 || U3X3 != U3X0 || UPE3 != UPE0 || \ |
81 | UDRE3 != UDRE0) |
82 | #error "Not all bit positions for UART3 are the same as for UART0" |
83 | #endif |
84 |
|
85 | // Constructors //////////////////////////////////////////////////////////////// |
86 |
|
87 | HardwareSerial::HardwareSerial( |
88 | volatile uint8_t *ubrrh, volatile uint8_t *ubrrl, |
89 | volatile uint8_t *ucsra, volatile uint8_t *ucsrb, |
90 | volatile uint8_t *ucsrc, volatile uint8_t *udr) : |
91 | _ubrrh(ubrrh), _ubrrl(ubrrl), |
92 | _ucsra(ucsra), _ucsrb(ucsrb), _ucsrc(ucsrc), |
93 | _udr(udr), |
94 | _rx_buffer_head(0), _rx_buffer_tail(0), |
95 | _tx_buffer_head(0), _tx_buffer_tail(0) |
96 | { |
97 | } |
98 |
|
99 | // Actual interrupt handlers ////////////////////////////////////////////////////////////// |
100 |
|
101 | void HardwareSerial::_rx_complete_irq(void) |
102 | { |
103 | if (bit_is_clear(*_ucsra, UPE0)) { |
104 | // No Parity error, read byte and store it in the buffer if there is |
105 | // room |
106 | unsigned char c = *_udr; |
107 | rx_buffer_index_t i = (unsigned int)(_rx_buffer_head + 1) % SERIAL_RX_BUFFER_SIZE; |
108 |
|
109 | // if we should be storing the received character into the location |
110 | // just before the tail (meaning that the head would advance to the |
111 | // current location of the tail), we're about to overflow the buffer |
112 | // and so we don't write the character or advance the head. |
113 | if (i != _rx_buffer_tail) { |
114 | _rx_buffer[_rx_buffer_head] = c; |
115 | _rx_buffer_head = i; |
116 | } |
117 | } else { |
118 | // Parity error, read byte but discard it |
119 | *_udr; |
120 | }; |
121 | } |
122 |
|
123 | #endif // whole file |
124 |
|