@@ -49,41 +49,41 @@ ring_buffer rx_buffer3 = { { 0 }, 0, 0 };
49
49
50
50
inline void store_char (unsigned char c, ring_buffer *rx_buffer)
51
51
{
52
- int i = (rx_buffer->head + 1 ) % RX_BUFFER_SIZE;
53
-
54
- // if we should be storing the received character into the location
55
- // just before the tail (meaning that the head would advance to the
56
- // current location of the tail), we're about to overflow the buffer
57
- // and so we don't write the character or advance the head.
58
- if (i != rx_buffer->tail ) {
59
- rx_buffer->buffer [rx_buffer->head ] = c;
60
- rx_buffer->head = i;
61
- }
52
+ int i = (rx_buffer->head + 1 ) % RX_BUFFER_SIZE;
53
+
54
+ // if we should be storing the received character into the location
55
+ // just before the tail (meaning that the head would advance to the
56
+ // current location of the tail), we're about to overflow the buffer
57
+ // and so we don't write the character or advance the head.
58
+ if (i != rx_buffer->tail ) {
59
+ rx_buffer->buffer [rx_buffer->head ] = c;
60
+ rx_buffer->head = i;
61
+ }
62
62
}
63
63
64
64
#if defined(__AVR_ATmega1280__)
65
65
66
66
SIGNAL (SIG_USART0_RECV)
67
67
{
68
- unsigned char c = UDR0;
68
+ unsigned char c = UDR0;
69
69
store_char (c, &rx_buffer);
70
70
}
71
71
72
72
SIGNAL (SIG_USART1_RECV)
73
73
{
74
- unsigned char c = UDR1;
74
+ unsigned char c = UDR1;
75
75
store_char (c, &rx_buffer1);
76
76
}
77
77
78
78
SIGNAL (SIG_USART2_RECV)
79
79
{
80
- unsigned char c = UDR2;
80
+ unsigned char c = UDR2;
81
81
store_char (c, &rx_buffer2);
82
82
}
83
83
84
84
SIGNAL (SIG_USART3_RECV)
85
85
{
86
- unsigned char c = UDR3;
86
+ unsigned char c = UDR3;
87
87
store_char (c, &rx_buffer3);
88
88
}
89
89
@@ -96,9 +96,9 @@ SIGNAL(USART_RX_vect)
96
96
#endif
97
97
{
98
98
#if defined(__AVR_ATmega8__)
99
- unsigned char c = UDR;
99
+ unsigned char c = UDR;
100
100
#else
101
- unsigned char c = UDR0;
101
+ unsigned char c = UDR0;
102
102
#endif
103
103
store_char (c, &rx_buffer);
104
104
}
@@ -111,7 +111,7 @@ HardwareSerial::HardwareSerial(ring_buffer *rx_buffer,
111
111
volatile uint8_t *ubrrh, volatile uint8_t *ubrrl,
112
112
volatile uint8_t *ucsra, volatile uint8_t *ucsrb,
113
113
volatile uint8_t *udr,
114
- uint8_t rxen, uint8_t txen, uint8_t rxcie, uint8_t udre)
114
+ uint8_t rxen, uint8_t txen, uint8_t rxcie, uint8_t udre, uint8_t u2x )
115
115
{
116
116
_rx_buffer = rx_buffer;
117
117
_ubrrh = ubrrh;
@@ -123,69 +123,97 @@ HardwareSerial::HardwareSerial(ring_buffer *rx_buffer,
123
123
_txen = txen;
124
124
_rxcie = rxcie;
125
125
_udre = udre;
126
+ _u2x = u2x;
126
127
}
127
128
128
129
// Public Methods //////////////////////////////////////////////////////////////
129
130
130
- void HardwareSerial::begin (long speed )
131
+ void HardwareSerial::begin (long baud )
131
132
{
132
- *_ubrrh = ((F_CPU / 16 + speed / 2 ) / speed - 1 ) >> 8 ;
133
- *_ubrrl = ((F_CPU / 16 + speed / 2 ) / speed - 1 );
133
+ uint16_t baud_setting;
134
+ bool use_u2x;
135
+
136
+ // U2X mode is needed for baud rates higher than (CPU Hz / 16)
137
+ if (baud > F_CPU / 16 ) {
138
+ use_u2x = true ;
139
+ } else {
140
+ // figure out if U2X mode would allow for a better connection
141
+
142
+ // calculate the percent difference between the baud-rate specified and
143
+ // the real baud rate for both U2X and non-U2X mode (0-255 error percent)
144
+ uint8_t nonu2x_baud_error = abs ((int )(255 -((F_CPU/(16 *(((F_CPU/8 /baud-1 )/2 )+1 ))*255 )/baud)));
145
+ uint8_t u2x_baud_error = abs ((int )(255 -((F_CPU/(8 *(((F_CPU/4 /baud-1 )/2 )+1 ))*255 )/baud)));
146
+
147
+ // prefer non-U2X mode because it handles clock skew better
148
+ use_u2x = (nonu2x_baud_error > u2x_baud_error);
149
+ }
150
+
151
+ if (use_u2x) {
152
+ *_ucsra = 1 << _u2x;
153
+ baud_setting = (F_CPU / 4 / baud - 1 ) / 2 ;
154
+ } else {
155
+ *_ucsra = 0 ;
156
+ baud_setting = (F_CPU / 8 / baud - 1 ) / 2 ;
157
+ }
158
+
159
+ // assign the baud_setting, a.k.a. ubbr (USART Baud Rate Register)
160
+ *_ubrrh = baud_setting >> 8 ;
161
+ *_ubrrl = baud_setting;
162
+
134
163
sbi (*_ucsrb, _rxen);
135
164
sbi (*_ucsrb, _txen);
136
165
sbi (*_ucsrb, _rxcie);
137
166
}
138
167
139
168
uint8_t HardwareSerial::available (void )
140
169
{
141
- return (RX_BUFFER_SIZE + _rx_buffer->head - _rx_buffer->tail ) % RX_BUFFER_SIZE;
170
+ return (RX_BUFFER_SIZE + _rx_buffer->head - _rx_buffer->tail ) % RX_BUFFER_SIZE;
142
171
}
143
172
144
173
int HardwareSerial::read (void )
145
174
{
146
- // if the head isn't ahead of the tail, we don't have any characters
147
- if (_rx_buffer->head == _rx_buffer->tail ) {
148
- return -1 ;
149
- } else {
150
- unsigned char c = _rx_buffer->buffer [_rx_buffer->tail ];
151
- _rx_buffer->tail = (_rx_buffer->tail + 1 ) % RX_BUFFER_SIZE;
152
- return c;
153
- }
175
+ // if the head isn't ahead of the tail, we don't have any characters
176
+ if (_rx_buffer->head == _rx_buffer->tail ) {
177
+ return -1 ;
178
+ } else {
179
+ unsigned char c = _rx_buffer->buffer [_rx_buffer->tail ];
180
+ _rx_buffer->tail = (_rx_buffer->tail + 1 ) % RX_BUFFER_SIZE;
181
+ return c;
182
+ }
154
183
}
155
184
156
185
void HardwareSerial::flush ()
157
186
{
158
- // don't reverse this or there may be problems if the RX interrupt
159
- // occurs after reading the value of rx_buffer_head but before writing
160
- // the value to rx_buffer_tail; the previous value of rx_buffer_head
161
- // may be written to rx_buffer_tail, making it appear as if the buffer
162
- // don't reverse this or there may be problems if the RX interrupt
163
- // occurs after reading the value of rx_buffer_head but before writing
164
- // the value to rx_buffer_tail; the previous value of rx_buffer_head
165
- // may be written to rx_buffer_tail, making it appear as if the buffer
166
- // were full, not empty.
167
- _rx_buffer->head = _rx_buffer->tail ;
187
+ // don't reverse this or there may be problems if the RX interrupt
188
+ // occurs after reading the value of rx_buffer_head but before writing
189
+ // the value to rx_buffer_tail; the previous value of rx_buffer_head
190
+ // may be written to rx_buffer_tail, making it appear as if the buffer
191
+ // don't reverse this or there may be problems if the RX interrupt
192
+ // occurs after reading the value of rx_buffer_head but before writing
193
+ // the value to rx_buffer_tail; the previous value of rx_buffer_head
194
+ // may be written to rx_buffer_tail, making it appear as if the buffer
195
+ // were full, not empty.
196
+ _rx_buffer->head = _rx_buffer->tail ;
168
197
}
169
198
170
199
void HardwareSerial::write (uint8_t c)
171
200
{
172
- while (!((*_ucsra) & (1 << _udre)))
173
- ;
201
+ while (!((*_ucsra) & (1 << _udre)))
202
+ ;
174
203
175
- *_udr = c;
204
+ *_udr = c;
176
205
}
177
206
178
207
// Preinstantiate Objects //////////////////////////////////////////////////////
179
208
180
209
#if defined(__AVR_ATmega8__)
181
- HardwareSerial Serial (&rx_buffer, &UBRRH, &UBRRL, &UCSRA, &UCSRB, &UDR, RXEN, TXEN, RXCIE, UDRE);
210
+ HardwareSerial Serial (&rx_buffer, &UBRRH, &UBRRL, &UCSRA, &UCSRB, &UDR, RXEN, TXEN, RXCIE, UDRE, U2X );
182
211
#else
183
- HardwareSerial Serial (&rx_buffer, &UBRR0H, &UBRR0L, &UCSR0A, &UCSR0B, &UDR0, RXEN0, TXEN0, RXCIE0, UDRE0);
212
+ HardwareSerial Serial (&rx_buffer, &UBRR0H, &UBRR0L, &UCSR0A, &UCSR0B, &UDR0, RXEN0, TXEN0, RXCIE0, UDRE0, U2X0 );
184
213
#endif
185
214
186
215
#if defined(__AVR_ATmega1280__)
187
- HardwareSerial Serial1 (&rx_buffer1, &UBRR1H, &UBRR1L, &UCSR1A, &UCSR1B, &UDR1, RXEN1, TXEN1, RXCIE1, UDRE1);
188
- HardwareSerial Serial2 (&rx_buffer2, &UBRR2H, &UBRR2L, &UCSR2A, &UCSR2B, &UDR2, RXEN2, TXEN2, RXCIE2, UDRE2);
189
- HardwareSerial Serial3 (&rx_buffer3, &UBRR3H, &UBRR3L, &UCSR3A, &UCSR3B, &UDR3, RXEN3, TXEN3, RXCIE3, UDRE3);
216
+ HardwareSerial Serial1 (&rx_buffer1, &UBRR1H, &UBRR1L, &UCSR1A, &UCSR1B, &UDR1, RXEN1, TXEN1, RXCIE1, UDRE1, U2X1 );
217
+ HardwareSerial Serial2 (&rx_buffer2, &UBRR2H, &UBRR2L, &UCSR2A, &UCSR2B, &UDR2, RXEN2, TXEN2, RXCIE2, UDRE2, U2X2 );
218
+ HardwareSerial Serial3 (&rx_buffer3, &UBRR3H, &UBRR3L, &UCSR3A, &UCSR3B, &UDR3, RXEN3, TXEN3, RXCIE3, UDRE3, U2X3 );
190
219
#endif
191
-
0 commit comments