Index

auto-plow / 3630027

A wheelchair motor-propelled battery-powered ESP32-driven remote control snow plow.

Latest Commit

{#}TimeHashSubjectAuthor#(+)(-)GPG?
4518 Jan 2019 20:3396057a4SoftwareSerialJoshua14860N

Blob @ auto-plow / include / arduino / SoftwareSerial.cpp

text/plain12958 bytesdownload raw
1/*
2SoftwareSerial.cpp (formerly NewSoftSerial.cpp) -
3Multi-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
14This library is free software; you can redistribute it and/or
15modify it under the terms of the GNU Lesser General Public
16License as published by the Free Software Foundation; either
17version 2.1 of the License, or (at your option) any later version.
18
19This library is distributed in the hope that it will be useful,
20but WITHOUT ANY WARRANTY; without even the implied warranty of
21MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22Lesser General Public License for more details.
23
24You should have received a copy of the GNU Lesser General Public
25License along with this library; if not, write to the Free Software
26Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27
28The latest version of this library can always be found at
29http://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#include <util/delay_basic.h>
46
47//
48// Statics
49//
50SoftwareSerial *SoftwareSerial::active_object = 0;
51uint8_t SoftwareSerial::_receive_buffer[_SS_MAX_RX_BUFF];
52volatile uint8_t SoftwareSerial::_receive_buffer_tail = 0;
53volatile uint8_t SoftwareSerial::_receive_buffer_head = 0;
54
55//
56// Debugging
57//
58// This function generates a brief pulse
59// for debugging or measuring on an oscilloscope.
60#if _DEBUG
61inline void DebugPulse(uint8_t pin, uint8_t count)
62{
63 volatile uint8_t *pport = portOutputRegister(digitalPinToPort(pin));
64
65 uint8_t val = *pport;
66 while (count--)
67 {
68 *pport = val | digitalPinToBitMask(pin);
69 *pport = val;
70 }
71}
72#else
73inline void DebugPulse(uint8_t, uint8_t) {}
74#endif
75
76//
77// Private methods
78//
79
80/* static */
81inline void SoftwareSerial::tunedDelay(uint16_t delay) {
82 _delay_loop_2(delay);
83}
84
85// This function sets the current object as the "listening"
86// one and returns true if it replaces another
87bool SoftwareSerial::listen()
88{
89 if (!_rx_delay_stopbit)
90 return false;
91
92 if (active_object != this)
93 {
94 if (active_object)
95 active_object->stopListening();
96
97 _buffer_overflow = false;
98 _receive_buffer_head = _receive_buffer_tail = 0;
99 active_object = this;
100
101 setRxIntMsk(true);
102 return true;
103 }
104
105 return false;
106}
107
108// Stop listening. Returns true if we were actually listening.
109bool SoftwareSerial::stopListening()
110{
111 if (active_object == this)
112 {
113 setRxIntMsk(false);
114 active_object = NULL;
115 return true;
116 }
117 return false;
118}
119
120//
121// The receive routine called by the interrupt handler
122//
123void SoftwareSerial::recv()
124{
125
126#if GCC_VERSION < 40302
127// Work-around for avr-gcc 4.3.0 OSX version bug
128// Preserve the registers that the compiler misses
129// (courtesy of Arduino forum user *etracer*)
130 asm volatile(
131 "push r18 \n\t"
132 "push r19 \n\t"
133 "push r20 \n\t"
134 "push r21 \n\t"
135 "push r22 \n\t"
136 "push r23 \n\t"
137 "push r26 \n\t"
138 "push r27 \n\t"
139 ::);
140#endif
141
142 uint8_t d = 0;
143
144 // If RX line is high, then we don't see any start bit
145 // so interrupt is probably not for us
146 if (_inverse_logic ? rx_pin_read() : !rx_pin_read())
147 {
148 // Disable further interrupts during reception, this prevents
149 // triggering another interrupt directly after we return, which can
150 // cause problems at higher baudrates.
151 setRxIntMsk(false);
152
153 // Wait approximately 1/2 of a bit width to "center" the sample
154 tunedDelay(_rx_delay_centering);
155 DebugPulse(_DEBUG_PIN2, 1);
156
157 // Read each of the 8 bits
158 for (uint8_t i=8; i > 0; --i)
159 {
160 tunedDelay(_rx_delay_intrabit);
161 d >>= 1;
162 DebugPulse(_DEBUG_PIN2, 1);
163 if (rx_pin_read())
164 d |= 0x80;
165 }
166
167 if (_inverse_logic)
168 d = ~d;
169
170 // if buffer full, set the overflow flag and return
171 uint8_t next = (_receive_buffer_tail + 1) % _SS_MAX_RX_BUFF;
172 if (next != _receive_buffer_head)
173 {
174 // save new data in buffer: tail points to where byte goes
175 _receive_buffer[_receive_buffer_tail] = d; // save new byte
176 _receive_buffer_tail = next;
177 }
178 else
179 {
180 DebugPulse(_DEBUG_PIN1, 1);
181 _buffer_overflow = true;
182 }
183
184 // skip the stop bit
185 tunedDelay(_rx_delay_stopbit);
186 DebugPulse(_DEBUG_PIN1, 1);
187
188 // Re-enable interrupts when we're sure to be inside the stop bit
189 setRxIntMsk(true);
190
191 }
192
193#if GCC_VERSION < 40302
194// Work-around for avr-gcc 4.3.0 OSX version bug
195// Restore the registers that the compiler misses
196 asm volatile(
197 "pop r27 \n\t"
198 "pop r26 \n\t"
199 "pop r23 \n\t"
200 "pop r22 \n\t"
201 "pop r21 \n\t"
202 "pop r20 \n\t"
203 "pop r19 \n\t"
204 "pop r18 \n\t"
205 ::);
206#endif
207}
208
209uint8_t SoftwareSerial::rx_pin_read()
210{
211 return *_receivePortRegister & _receiveBitMask;
212}
213
214//
215// Interrupt handling
216//
217
218/* static */
219inline void SoftwareSerial::handle_interrupt()
220{
221 if (active_object)
222 {
223 active_object->recv();
224 }
225}
226
227#if defined(PCINT0_vect)
228ISR(PCINT0_vect)
229{
230 SoftwareSerial::handle_interrupt();
231}
232#endif
233
234#if defined(PCINT1_vect)
235ISR(PCINT1_vect, ISR_ALIASOF(PCINT0_vect));
236#endif
237
238#if defined(PCINT2_vect)
239ISR(PCINT2_vect, ISR_ALIASOF(PCINT0_vect));
240#endif
241
242#if defined(PCINT3_vect)
243ISR(PCINT3_vect, ISR_ALIASOF(PCINT0_vect));
244#endif
245
246//
247// Constructor
248//
249SoftwareSerial::SoftwareSerial(uint8_t receivePin, uint8_t transmitPin, bool inverse_logic /* = false */) :
250 _rx_delay_centering(0),
251 _rx_delay_intrabit(0),
252 _rx_delay_stopbit(0),
253 _tx_delay(0),
254 _buffer_overflow(false),
255 _inverse_logic(inverse_logic)
256{
257 setTX(transmitPin);
258 setRX(receivePin);
259}
260
261//
262// Destructor
263//
264SoftwareSerial::~SoftwareSerial()
265{
266 end();
267}
268
269void SoftwareSerial::setTX(uint8_t tx)
270{
271 // First write, then set output. If we do this the other way around,
272 // the pin would be output low for a short while before switching to
273 // output high. Now, it is input with pullup for a short while, which
274 // is fine. With inverse logic, either order is fine.
275 digitalWrite(tx, _inverse_logic ? LOW : HIGH);
276 pinMode(tx, OUTPUT);
277 _transmitBitMask = digitalPinToBitMask(tx);
278 uint8_t port = digitalPinToPort(tx);
279 _transmitPortRegister = portOutputRegister(port);
280}
281
282void SoftwareSerial::setRX(uint8_t rx)
283{
284 pinMode(rx, INPUT);
285 if (!_inverse_logic)
286 digitalWrite(rx, HIGH); // pullup for normal logic!
287 _receivePin = rx;
288 _receiveBitMask = digitalPinToBitMask(rx);
289 uint8_t port = digitalPinToPort(rx);
290 _receivePortRegister = portInputRegister(port);
291}
292
293uint16_t SoftwareSerial::subtract_cap(uint16_t num, uint16_t sub) {
294 if (num > sub)
295 return num - sub;
296 else
297 return 1;
298}
299
300//
301// Public methods
302//
303
304void SoftwareSerial::begin(long speed)
305{
306 _rx_delay_centering = _rx_delay_intrabit = _rx_delay_stopbit = _tx_delay = 0;
307
308 // Precalculate the various delays, in number of 4-cycle delays
309 uint16_t bit_delay = (F_CPU / speed) / 4;
310
311 // 12 (gcc 4.8.2) or 13 (gcc 4.3.2) cycles from start bit to first bit,
312 // 15 (gcc 4.8.2) or 16 (gcc 4.3.2) cycles between bits,
313 // 12 (gcc 4.8.2) or 14 (gcc 4.3.2) cycles from last bit to stop bit
314 // These are all close enough to just use 15 cycles, since the inter-bit
315 // timings are the most critical (deviations stack 8 times)
316 _tx_delay = subtract_cap(bit_delay, 15 / 4);
317
318 // Only setup rx when we have a valid PCINT for this pin
319 if (digitalPinToPCICR(_receivePin)) {
320 #if GCC_VERSION > 40800
321 // Timings counted from gcc 4.8.2 output. This works up to 115200 on
322 // 16Mhz and 57600 on 8Mhz.
323 //
324 // When the start bit occurs, there are 3 or 4 cycles before the
325 // interrupt flag is set, 4 cycles before the PC is set to the right
326 // interrupt vector address and the old PC is pushed on the stack,
327 // and then 75 cycles of instructions (including the RJMP in the
328 // ISR vector table) until the first delay. After the delay, there
329 // are 17 more cycles until the pin value is read (excluding the
330 // delay in the loop).
331 // We want to have a total delay of 1.5 bit time. Inside the loop,
332 // we already wait for 1 bit time - 23 cycles, so here we wait for
333 // 0.5 bit time - (71 + 18 - 22) cycles.
334 _rx_delay_centering = subtract_cap(bit_delay / 2, (4 + 4 + 75 + 17 - 23) / 4);
335
336 // There are 23 cycles in each loop iteration (excluding the delay)
337 _rx_delay_intrabit = subtract_cap(bit_delay, 23 / 4);
338
339 // There are 37 cycles from the last bit read to the start of
340 // stopbit delay and 11 cycles from the delay until the interrupt
341 // mask is enabled again (which _must_ happen during the stopbit).
342 // This delay aims at 3/4 of a bit time, meaning the end of the
343 // delay will be at 1/4th of the stopbit. This allows some extra
344 // time for ISR cleanup, which makes 115200 baud at 16Mhz work more
345 // reliably
346 _rx_delay_stopbit = subtract_cap(bit_delay * 3 / 4, (37 + 11) / 4);
347 #else // Timings counted from gcc 4.3.2 output
348 // Note that this code is a _lot_ slower, mostly due to bad register
349 // allocation choices of gcc. This works up to 57600 on 16Mhz and
350 // 38400 on 8Mhz.
351 _rx_delay_centering = subtract_cap(bit_delay / 2, (4 + 4 + 97 + 29 - 11) / 4);
352 _rx_delay_intrabit = subtract_cap(bit_delay, 11 / 4);
353 _rx_delay_stopbit = subtract_cap(bit_delay * 3 / 4, (44 + 17) / 4);
354 #endif
355
356
357 // Enable the PCINT for the entire port here, but never disable it
358 // (others might also need it, so we disable the interrupt by using
359 // the per-pin PCMSK register).
360 *digitalPinToPCICR(_receivePin) |= _BV(digitalPinToPCICRbit(_receivePin));
361 // Precalculate the pcint mask register and value, so setRxIntMask
362 // can be used inside the ISR without costing too much time.
363 _pcint_maskreg = digitalPinToPCMSK(_receivePin);
364 _pcint_maskvalue = _BV(digitalPinToPCMSKbit(_receivePin));
365
366 tunedDelay(_tx_delay); // if we were low this establishes the end
367 }
368
369#if _DEBUG
370 pinMode(_DEBUG_PIN1, OUTPUT);
371 pinMode(_DEBUG_PIN2, OUTPUT);
372#endif
373
374 listen();
375}
376
377void SoftwareSerial::setRxIntMsk(bool enable)
378{
379 if (enable)
380 *_pcint_maskreg |= _pcint_maskvalue;
381 else
382 *_pcint_maskreg &= ~_pcint_maskvalue;
383}
384
385void SoftwareSerial::end()
386{
387 stopListening();
388}
389
390
391// Read data from buffer
392int SoftwareSerial::read()
393{
394 if (!isListening())
395 return -1;
396
397 // Empty buffer?
398 if (_receive_buffer_head == _receive_buffer_tail)
399 return -1;
400
401 // Read from "head"
402 uint8_t d = _receive_buffer[_receive_buffer_head]; // grab next byte
403 _receive_buffer_head = (_receive_buffer_head + 1) % _SS_MAX_RX_BUFF;
404 return d;
405}
406
407int SoftwareSerial::available()
408{
409 if (!isListening())
410 return 0;
411
412 return (_receive_buffer_tail + _SS_MAX_RX_BUFF - _receive_buffer_head) % _SS_MAX_RX_BUFF;
413}
414
415size_t SoftwareSerial::write(uint8_t b)
416{
417 if (_tx_delay == 0) {
418 setWriteError();
419 return 0;
420 }
421
422 // By declaring these as local variables, the compiler will put them
423 // in registers _before_ disabling interrupts and entering the
424 // critical timing sections below, which makes it a lot easier to
425 // verify the cycle timings
426 volatile uint8_t *reg = _transmitPortRegister;
427 uint8_t reg_mask = _transmitBitMask;
428 uint8_t inv_mask = ~_transmitBitMask;
429 uint8_t oldSREG = SREG;
430 bool inv = _inverse_logic;
431 uint16_t delay = _tx_delay;
432
433 if (inv)
434 b = ~b;
435
436 cli(); // turn off interrupts for a clean txmit
437
438 // Write the start bit
439 if (inv)
440 *reg |= reg_mask;
441 else
442 *reg &= inv_mask;
443
444 tunedDelay(delay);
445
446 // Write each of the 8 bits
447 for (uint8_t i = 8; i > 0; --i)
448 {
449 if (b & 1) // choose bit
450 *reg |= reg_mask; // send 1
451 else
452 *reg &= inv_mask; // send 0
453
454 tunedDelay(delay);
455 b >>= 1;
456 }
457
458 // restore pin to natural state
459 if (inv)
460 *reg &= inv_mask;
461 else
462 *reg |= reg_mask;
463
464 SREG = oldSREG; // turn interrupts back on
465 tunedDelay(_tx_delay);
466
467 return 1;
468}
469
470void SoftwareSerial::flush()
471{
472 // There is no tx buffering, simply return
473}
474
475int SoftwareSerial::peek()
476{
477 if (!isListening())
478 return -1;
479
480 // Empty buffer?
481 if (_receive_buffer_head == _receive_buffer_tail)
482 return -1;
483
484 // Read from "head"
485 return _receive_buffer[_receive_buffer_head];
486}
487