root / arduino-1.0 / libraries / SoftwareSerial / SoftwareSerial.cpp @ 58d82c77
History | View | Annotate | Download (13.1 KB)
1 |
/*
|
---|---|
2 |
SoftwareSerial.cpp (formerly NewSoftSerial.cpp) -
|
3 |
Multi-instance software serial library for Arduino/Wiring
|
4 |
-- Interrupt-driven receive and other improvements by ladyada
|
5 |
(http://ladyada.net)
|
6 |
-- Tuning, circular buffer, derivation from class Print/Stream,
|
7 |
multi-instance support, porting to 8MHz processors,
|
8 |
various optimizations, PROGMEM delay tables, inverse logic and
|
9 |
direct port writing by Mikal Hart (http://www.arduiniana.org)
|
10 |
-- Pin change interrupt macros by Paul Stoffregen (http://www.pjrc.com)
|
11 |
-- 20MHz processor support by Garrett Mace (http://www.macetech.com)
|
12 |
-- ATmega1280/2560 support by Brett Hagman (http://www.roguerobotics.com/)
|
13 |
|
14 |
This library is free software; you can redistribute it and/or
|
15 |
modify it under the terms of the GNU Lesser General Public
|
16 |
License as published by the Free Software Foundation; either
|
17 |
version 2.1 of the License, or (at your option) any later version.
|
18 |
|
19 |
This library is distributed in the hope that it will be useful,
|
20 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
21 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
22 |
Lesser General Public License for more details.
|
23 |
|
24 |
You should have received a copy of the GNU Lesser General Public
|
25 |
License along with this library; if not, write to the Free Software
|
26 |
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
27 |
|
28 |
The latest version of this library can always be found at
|
29 |
http://arduiniana.org.
|
30 |
*/
|
31 |
|
32 |
// When set, _DEBUG co-opts pins 11 and 13 for debugging with an
|
33 |
// oscilloscope or logic analyzer. Beware: it also slightly modifies
|
34 |
// the bit times, so don't rely on it too much at high baud rates
|
35 |
#define _DEBUG 0 |
36 |
#define _DEBUG_PIN1 11 |
37 |
#define _DEBUG_PIN2 13 |
38 |
//
|
39 |
// Includes
|
40 |
//
|
41 |
#include <avr/interrupt.h> |
42 |
#include <avr/pgmspace.h> |
43 |
#include "Arduino.h" |
44 |
#include "SoftwareSerial.h" |
45 |
//
|
46 |
// Lookup table
|
47 |
//
|
48 |
typedef struct _DELAY_TABLE |
49 |
{ |
50 |
long baud;
|
51 |
unsigned short rx_delay_centering; |
52 |
unsigned short rx_delay_intrabit; |
53 |
unsigned short rx_delay_stopbit; |
54 |
unsigned short tx_delay; |
55 |
} DELAY_TABLE; |
56 |
|
57 |
#if F_CPU == 16000000 |
58 |
|
59 |
static const DELAY_TABLE PROGMEM table[] = |
60 |
{ |
61 |
// baud rxcenter rxintra rxstop tx
|
62 |
{ 115200, 1, 17, 17, 12, }, |
63 |
{ 57600, 10, 37, 37, 33, }, |
64 |
{ 38400, 25, 57, 57, 54, }, |
65 |
{ 31250, 31, 70, 70, 68, }, |
66 |
{ 28800, 34, 77, 77, 74, }, |
67 |
{ 19200, 54, 117, 117, 114, }, |
68 |
{ 14400, 74, 156, 156, 153, }, |
69 |
{ 9600, 114, 236, 236, 233, }, |
70 |
{ 4800, 233, 474, 474, 471, }, |
71 |
{ 2400, 471, 950, 950, 947, }, |
72 |
{ 1200, 947, 1902, 1902, 1899, }, |
73 |
{ 300, 3804, 7617, 7617, 7614, }, |
74 |
}; |
75 |
|
76 |
const int XMIT_START_ADJUSTMENT = 5; |
77 |
|
78 |
#elif F_CPU == 8000000 |
79 |
|
80 |
static const DELAY_TABLE table[] PROGMEM = |
81 |
{ |
82 |
// baud rxcenter rxintra rxstop tx
|
83 |
{ 115200, 1, 5, 5, 3, }, |
84 |
{ 57600, 1, 15, 15, 13, }, |
85 |
{ 38400, 2, 25, 26, 23, }, |
86 |
{ 31250, 7, 32, 33, 29, }, |
87 |
{ 28800, 11, 35, 35, 32, }, |
88 |
{ 19200, 20, 55, 55, 52, }, |
89 |
{ 14400, 30, 75, 75, 72, }, |
90 |
{ 9600, 50, 114, 114, 112, }, |
91 |
{ 4800, 110, 233, 233, 230, }, |
92 |
{ 2400, 229, 472, 472, 469, }, |
93 |
{ 1200, 467, 948, 948, 945, }, |
94 |
{ 300, 1895, 3805, 3805, 3802, }, |
95 |
}; |
96 |
|
97 |
const int XMIT_START_ADJUSTMENT = 4; |
98 |
|
99 |
#elif F_CPU == 20000000 |
100 |
|
101 |
// 20MHz support courtesy of the good people at macegr.com.
|
102 |
// Thanks, Garrett!
|
103 |
|
104 |
static const DELAY_TABLE PROGMEM table[] = |
105 |
{ |
106 |
// baud rxcenter rxintra rxstop tx
|
107 |
{ 115200, 3, 21, 21, 18, }, |
108 |
{ 57600, 20, 43, 43, 41, }, |
109 |
{ 38400, 37, 73, 73, 70, }, |
110 |
{ 31250, 45, 89, 89, 88, }, |
111 |
{ 28800, 46, 98, 98, 95, }, |
112 |
{ 19200, 71, 148, 148, 145, }, |
113 |
{ 14400, 96, 197, 197, 194, }, |
114 |
{ 9600, 146, 297, 297, 294, }, |
115 |
{ 4800, 296, 595, 595, 592, }, |
116 |
{ 2400, 592, 1189, 1189, 1186, }, |
117 |
{ 1200, 1187, 2379, 2379, 2376, }, |
118 |
{ 300, 4759, 9523, 9523, 9520, }, |
119 |
}; |
120 |
|
121 |
const int XMIT_START_ADJUSTMENT = 6; |
122 |
|
123 |
#else
|
124 |
|
125 |
#error This version of SoftwareSerial supports only 20, 16 and 8MHz processors |
126 |
|
127 |
#endif
|
128 |
|
129 |
//
|
130 |
// Statics
|
131 |
//
|
132 |
SoftwareSerial *SoftwareSerial::active_object = 0;
|
133 |
char SoftwareSerial::_receive_buffer[_SS_MAX_RX_BUFF];
|
134 |
volatile uint8_t SoftwareSerial::_receive_buffer_tail = 0; |
135 |
volatile uint8_t SoftwareSerial::_receive_buffer_head = 0; |
136 |
|
137 |
//
|
138 |
// Debugging
|
139 |
//
|
140 |
// This function generates a brief pulse
|
141 |
// for debugging or measuring on an oscilloscope.
|
142 |
inline void DebugPulse(uint8_t pin, uint8_t count) |
143 |
{ |
144 |
#if _DEBUG
|
145 |
volatile uint8_t *pport = portOutputRegister(digitalPinToPort(pin));
|
146 |
|
147 |
uint8_t val = *pport; |
148 |
while (count--)
|
149 |
{ |
150 |
*pport = val | digitalPinToBitMask(pin); |
151 |
*pport = val; |
152 |
} |
153 |
#endif
|
154 |
} |
155 |
|
156 |
//
|
157 |
// Private methods
|
158 |
//
|
159 |
|
160 |
/* static */
|
161 |
inline void SoftwareSerial::tunedDelay(uint16_t delay) { |
162 |
uint8_t tmp=0;
|
163 |
|
164 |
asm volatile("sbiw %0, 0x01 \n\t" |
165 |
"ldi %1, 0xFF \n\t"
|
166 |
"cpi %A0, 0xFF \n\t"
|
167 |
"cpc %B0, %1 \n\t"
|
168 |
"brne .-10 \n\t"
|
169 |
: "+r" (delay), "+a" (tmp) |
170 |
: "0" (delay)
|
171 |
); |
172 |
} |
173 |
|
174 |
// This function sets the current object as the "listening"
|
175 |
// one and returns true if it replaces another
|
176 |
bool SoftwareSerial::listen()
|
177 |
{ |
178 |
if (active_object != this) |
179 |
{ |
180 |
_buffer_overflow = false;
|
181 |
uint8_t oldSREG = SREG; |
182 |
cli(); |
183 |
_receive_buffer_head = _receive_buffer_tail = 0;
|
184 |
active_object = this;
|
185 |
SREG = oldSREG; |
186 |
return true; |
187 |
} |
188 |
|
189 |
return false; |
190 |
} |
191 |
|
192 |
//
|
193 |
// The receive routine called by the interrupt handler
|
194 |
//
|
195 |
void SoftwareSerial::recv()
|
196 |
{ |
197 |
|
198 |
#if GCC_VERSION < 40302 |
199 |
// Work-around for avr-gcc 4.3.0 OSX version bug
|
200 |
// Preserve the registers that the compiler misses
|
201 |
// (courtesy of Arduino forum user *etracer*)
|
202 |
asm volatile( |
203 |
"push r18 \n\t"
|
204 |
"push r19 \n\t"
|
205 |
"push r20 \n\t"
|
206 |
"push r21 \n\t"
|
207 |
"push r22 \n\t"
|
208 |
"push r23 \n\t"
|
209 |
"push r26 \n\t"
|
210 |
"push r27 \n\t"
|
211 |
::); |
212 |
#endif
|
213 |
|
214 |
uint8_t d = 0;
|
215 |
|
216 |
// If RX line is high, then we don't see any start bit
|
217 |
// so interrupt is probably not for us
|
218 |
if (_inverse_logic ? rx_pin_read() : !rx_pin_read())
|
219 |
{ |
220 |
// Wait approximately 1/2 of a bit width to "center" the sample
|
221 |
tunedDelay(_rx_delay_centering); |
222 |
DebugPulse(_DEBUG_PIN2, 1);
|
223 |
|
224 |
// Read each of the 8 bits
|
225 |
for (uint8_t i=0x1; i; i <<= 1) |
226 |
{ |
227 |
tunedDelay(_rx_delay_intrabit); |
228 |
DebugPulse(_DEBUG_PIN2, 1);
|
229 |
uint8_t noti = ~i; |
230 |
if (rx_pin_read())
|
231 |
d |= i; |
232 |
else // else clause added to ensure function timing is ~balanced |
233 |
d &= noti; |
234 |
} |
235 |
|
236 |
// skip the stop bit
|
237 |
tunedDelay(_rx_delay_stopbit); |
238 |
DebugPulse(_DEBUG_PIN2, 1);
|
239 |
|
240 |
if (_inverse_logic)
|
241 |
d = ~d; |
242 |
|
243 |
// if buffer full, set the overflow flag and return
|
244 |
if ((_receive_buffer_tail + 1) % _SS_MAX_RX_BUFF != _receive_buffer_head) |
245 |
{ |
246 |
// save new data in buffer: tail points to where byte goes
|
247 |
_receive_buffer[_receive_buffer_tail] = d; // save new byte
|
248 |
_receive_buffer_tail = (_receive_buffer_tail + 1) % _SS_MAX_RX_BUFF;
|
249 |
} |
250 |
else
|
251 |
{ |
252 |
#if _DEBUG // for scope: pulse pin as overflow indictator |
253 |
DebugPulse(_DEBUG_PIN1, 1);
|
254 |
#endif
|
255 |
_buffer_overflow = true;
|
256 |
} |
257 |
} |
258 |
|
259 |
#if GCC_VERSION < 40302 |
260 |
// Work-around for avr-gcc 4.3.0 OSX version bug
|
261 |
// Restore the registers that the compiler misses
|
262 |
asm volatile( |
263 |
"pop r27 \n\t"
|
264 |
"pop r26 \n\t"
|
265 |
"pop r23 \n\t"
|
266 |
"pop r22 \n\t"
|
267 |
"pop r21 \n\t"
|
268 |
"pop r20 \n\t"
|
269 |
"pop r19 \n\t"
|
270 |
"pop r18 \n\t"
|
271 |
::); |
272 |
#endif
|
273 |
} |
274 |
|
275 |
void SoftwareSerial::tx_pin_write(uint8_t pin_state)
|
276 |
{ |
277 |
if (pin_state == LOW)
|
278 |
*_transmitPortRegister &= ~_transmitBitMask; |
279 |
else
|
280 |
*_transmitPortRegister |= _transmitBitMask; |
281 |
} |
282 |
|
283 |
uint8_t SoftwareSerial::rx_pin_read() |
284 |
{ |
285 |
return *_receivePortRegister & _receiveBitMask;
|
286 |
} |
287 |
|
288 |
//
|
289 |
// Interrupt handling
|
290 |
//
|
291 |
|
292 |
/* static */
|
293 |
inline void SoftwareSerial::handle_interrupt() |
294 |
{ |
295 |
if (active_object)
|
296 |
{ |
297 |
active_object->recv(); |
298 |
} |
299 |
} |
300 |
|
301 |
#if defined(PCINT0_vect)
|
302 |
ISR(PCINT0_vect) |
303 |
{ |
304 |
SoftwareSerial::handle_interrupt(); |
305 |
} |
306 |
#endif
|
307 |
|
308 |
#if defined(PCINT1_vect)
|
309 |
ISR(PCINT1_vect) |
310 |
{ |
311 |
SoftwareSerial::handle_interrupt(); |
312 |
} |
313 |
#endif
|
314 |
|
315 |
#if defined(PCINT2_vect)
|
316 |
ISR(PCINT2_vect) |
317 |
{ |
318 |
SoftwareSerial::handle_interrupt(); |
319 |
} |
320 |
#endif
|
321 |
|
322 |
#if defined(PCINT3_vect)
|
323 |
ISR(PCINT3_vect) |
324 |
{ |
325 |
SoftwareSerial::handle_interrupt(); |
326 |
} |
327 |
#endif
|
328 |
|
329 |
//
|
330 |
// Constructor
|
331 |
//
|
332 |
SoftwareSerial::SoftwareSerial(uint8_t receivePin, uint8_t transmitPin, bool inverse_logic /* = false */) : |
333 |
_rx_delay_centering(0),
|
334 |
_rx_delay_intrabit(0),
|
335 |
_rx_delay_stopbit(0),
|
336 |
_tx_delay(0),
|
337 |
_buffer_overflow(false),
|
338 |
_inverse_logic(inverse_logic) |
339 |
{ |
340 |
setTX(transmitPin); |
341 |
setRX(receivePin); |
342 |
} |
343 |
|
344 |
//
|
345 |
// Destructor
|
346 |
//
|
347 |
SoftwareSerial::~SoftwareSerial() |
348 |
{ |
349 |
end(); |
350 |
} |
351 |
|
352 |
void SoftwareSerial::setTX(uint8_t tx)
|
353 |
{ |
354 |
pinMode(tx, OUTPUT); |
355 |
digitalWrite(tx, HIGH); |
356 |
_transmitBitMask = digitalPinToBitMask(tx); |
357 |
uint8_t port = digitalPinToPort(tx); |
358 |
_transmitPortRegister = portOutputRegister(port); |
359 |
} |
360 |
|
361 |
void SoftwareSerial::setRX(uint8_t rx)
|
362 |
{ |
363 |
pinMode(rx, INPUT); |
364 |
if (!_inverse_logic)
|
365 |
digitalWrite(rx, HIGH); // pullup for normal logic!
|
366 |
_receivePin = rx; |
367 |
_receiveBitMask = digitalPinToBitMask(rx); |
368 |
uint8_t port = digitalPinToPort(rx); |
369 |
_receivePortRegister = portInputRegister(port); |
370 |
} |
371 |
|
372 |
//
|
373 |
// Public methods
|
374 |
//
|
375 |
|
376 |
void SoftwareSerial::begin(long speed) |
377 |
{ |
378 |
_rx_delay_centering = _rx_delay_intrabit = _rx_delay_stopbit = _tx_delay = 0;
|
379 |
|
380 |
for (unsigned i=0; i<sizeof(table)/sizeof(table[0]); ++i) |
381 |
{ |
382 |
long baud = pgm_read_dword(&table[i].baud);
|
383 |
if (baud == speed)
|
384 |
{ |
385 |
_rx_delay_centering = pgm_read_word(&table[i].rx_delay_centering); |
386 |
_rx_delay_intrabit = pgm_read_word(&table[i].rx_delay_intrabit); |
387 |
_rx_delay_stopbit = pgm_read_word(&table[i].rx_delay_stopbit); |
388 |
_tx_delay = pgm_read_word(&table[i].tx_delay); |
389 |
break;
|
390 |
} |
391 |
} |
392 |
|
393 |
// Set up RX interrupts, but only if we have a valid RX baud rate
|
394 |
if (_rx_delay_stopbit)
|
395 |
{ |
396 |
if (digitalPinToPCICR(_receivePin))
|
397 |
{ |
398 |
*digitalPinToPCICR(_receivePin) |= _BV(digitalPinToPCICRbit(_receivePin)); |
399 |
*digitalPinToPCMSK(_receivePin) |= _BV(digitalPinToPCMSKbit(_receivePin)); |
400 |
} |
401 |
tunedDelay(_tx_delay); // if we were low this establishes the end
|
402 |
} |
403 |
|
404 |
#if _DEBUG
|
405 |
pinMode(_DEBUG_PIN1, OUTPUT); |
406 |
pinMode(_DEBUG_PIN2, OUTPUT); |
407 |
#endif
|
408 |
|
409 |
listen(); |
410 |
} |
411 |
|
412 |
void SoftwareSerial::end()
|
413 |
{ |
414 |
if (digitalPinToPCMSK(_receivePin))
|
415 |
*digitalPinToPCMSK(_receivePin) &= ~_BV(digitalPinToPCMSKbit(_receivePin)); |
416 |
} |
417 |
|
418 |
|
419 |
// Read data from buffer
|
420 |
int SoftwareSerial::read()
|
421 |
{ |
422 |
if (!isListening())
|
423 |
return -1; |
424 |
|
425 |
// Empty buffer?
|
426 |
if (_receive_buffer_head == _receive_buffer_tail)
|
427 |
return -1; |
428 |
|
429 |
// Read from "head"
|
430 |
uint8_t d = _receive_buffer[_receive_buffer_head]; // grab next byte
|
431 |
_receive_buffer_head = (_receive_buffer_head + 1) % _SS_MAX_RX_BUFF;
|
432 |
return d;
|
433 |
} |
434 |
|
435 |
int SoftwareSerial::available()
|
436 |
{ |
437 |
if (!isListening())
|
438 |
return 0; |
439 |
|
440 |
return (_receive_buffer_tail + _SS_MAX_RX_BUFF - _receive_buffer_head) % _SS_MAX_RX_BUFF;
|
441 |
} |
442 |
|
443 |
size_t SoftwareSerial::write(uint8_t b) |
444 |
{ |
445 |
if (_tx_delay == 0) { |
446 |
setWriteError(); |
447 |
return 0; |
448 |
} |
449 |
|
450 |
uint8_t oldSREG = SREG; |
451 |
cli(); // turn off interrupts for a clean txmit
|
452 |
|
453 |
// Write the start bit
|
454 |
tx_pin_write(_inverse_logic ? HIGH : LOW); |
455 |
tunedDelay(_tx_delay + XMIT_START_ADJUSTMENT); |
456 |
|
457 |
// Write each of the 8 bits
|
458 |
if (_inverse_logic)
|
459 |
{ |
460 |
for (byte mask = 0x01; mask; mask <<= 1) |
461 |
{ |
462 |
if (b & mask) // choose bit |
463 |
tx_pin_write(LOW); // send 1
|
464 |
else
|
465 |
tx_pin_write(HIGH); // send 0
|
466 |
|
467 |
tunedDelay(_tx_delay); |
468 |
} |
469 |
|
470 |
tx_pin_write(LOW); // restore pin to natural state
|
471 |
} |
472 |
else
|
473 |
{ |
474 |
for (byte mask = 0x01; mask; mask <<= 1) |
475 |
{ |
476 |
if (b & mask) // choose bit |
477 |
tx_pin_write(HIGH); // send 1
|
478 |
else
|
479 |
tx_pin_write(LOW); // send 0
|
480 |
|
481 |
tunedDelay(_tx_delay); |
482 |
} |
483 |
|
484 |
tx_pin_write(HIGH); // restore pin to natural state
|
485 |
} |
486 |
|
487 |
SREG = oldSREG; // turn interrupts back on
|
488 |
tunedDelay(_tx_delay); |
489 |
|
490 |
return 1; |
491 |
} |
492 |
|
493 |
void SoftwareSerial::flush()
|
494 |
{ |
495 |
if (!isListening())
|
496 |
return;
|
497 |
|
498 |
uint8_t oldSREG = SREG; |
499 |
cli(); |
500 |
_receive_buffer_head = _receive_buffer_tail = 0;
|
501 |
SREG = oldSREG; |
502 |
} |
503 |
|
504 |
int SoftwareSerial::peek()
|
505 |
{ |
506 |
if (!isListening())
|
507 |
return -1; |
508 |
|
509 |
// Empty buffer?
|
510 |
if (_receive_buffer_head == _receive_buffer_tail)
|
511 |
return -1; |
512 |
|
513 |
// Read from "head"
|
514 |
return _receive_buffer[_receive_buffer_head];
|
515 |
} |