FastArduino v1.10
C++ library to build fast but small Arduino/AVR projects
Loading...
Searching...
No Matches
soft_uart.h
Go to the documentation of this file.
1// Copyright 2016-2023 Jean-Francois Poilpret
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
16
21#ifndef SOFTUART_HH
22#define SOFTUART_HH
23
24#include "boards/board.h"
25#include "interrupts.h"
26#include "utilities.h"
27#include "uart_commons.h"
28#include "streams.h"
29#include "gpio.h"
30#include "pci.h"
31#include "int.h"
32
39#define REGISTER_UARX_PCI_ISR(RX, PCI_NUM) \
40 ISR(CAT3(PCINT, PCI_NUM, _vect)) \
41 { \
42 serial::soft::isr_handler::check_uarx_pci<PCI_NUM, RX>(); \
43 }
44
51#define REGISTER_UARX_INT_ISR(RX, INT_NUM) \
52 ISR(CAT3(INT, INT_NUM, _vect)) \
53 { \
54 serial::soft::isr_handler::check_uarx_int<INT_NUM, RX>(); \
55 }
56
64#define REGISTER_UART_PCI_ISR(RX, TX, PCI_NUM) \
65 ISR(CAT3(PCINT, PCI_NUM, _vect)) \
66 { \
67 serial::soft::isr_handler::check_uart_pci<PCI_NUM, RX, TX>(); \
68 }
69
77#define REGISTER_UART_INT_ISR(RX, TX, INT_NUM) \
78 ISR(CAT3(INT, INT_NUM, _vect)) \
79 { \
80 serial::soft::isr_handler::check_uart_int<INT_NUM, RX, TX>(); \
81 }
82
83namespace serial
84{
95 namespace soft
96 {
97 }
98}
99
100namespace serial::soft
101{
103 class AbstractUATX
104 {
105 public:
110 streams::ostream out()
111 {
112 return streams::ostream(out_());
113 }
114
115 protected:
116 AbstractUATX(const AbstractUATX&) = delete;
117 AbstractUATX& operator=(const AbstractUATX&) = delete;
118
119 template<uint8_t SIZE_TX>
120 explicit AbstractUATX(char (&output)[SIZE_TX]) : obuf_{output} {}
121
122 // WARNING!!! This computation is super touchy for high rates because it depends totally on generated code
123 // Code generation may change:
124 // - when we change optimization options (we never do it and never shall)
125 // - when we change avr-gcc version: we have to recalculate based on write_,TX>() generated code analysis
126 // Actual timing is based on number of times to count 4 cycles, because we use _delay_loop_2(), this is
127 // why all values are divided by 4
128 void compute_times(uint32_t rate, StopBits stop_bits)
129 {
130 // Calculate timing for TX in number of cycles
131 uint16_t bit_time = uint16_t(F_CPU / rate);
132
133 // 5 or 6 cycles + delay [counted from start bit (cbi) to first bit (sbi or cbi)]
134 // if 1st bit is 1: ldi + sbrs + cbi => 1 + 2 + 2 = 5
135 // if 1st bit is 0: ldi + sbrs + rjmp + sbi => 1 + 1 + 2 + 2 = 6
136 // => we select 5 (because it is preferrable that rounding provides higher waiting times)
137 start_bit_tx_time_ = (bit_time - 5) / 4;
138
139 // between 8 and 11 cycles + delay counted from first bit (sbi or cbi) to second bit (sbi or cbi)
140 // part 1: if previous bit is 1: nothing => 0
141 // part 1: if previous bit is 0: rjmp => 2
142 // part 2: lsr + subi + brne => 1 + 1 + 2 = 4
143 // part 3: if current bit is 1: sbrs + sbi => 2 + 2 = 4
144 // part 3: if current bit is 0: sbrs + rjmp + cbi => 1 + 2 + 2 = 5
145 // => we select 9 (mid-range lowest value, because it is preferrable that rounding provides higher waiting times)
146 interbit_tx_time_ = (bit_time - 9) / 4;
147
148 // This one is simple because waiting loop occurs immediately after sbi (stop bit set)
149 stop_bit_tx_time_ = (bit_time / 4);
150 if (stop_bits == StopBits::TWO) stop_bit_tx_time_ *= 2;
151 // For stop bit we lengthen the bit duration of 25% to guarantee alignment of RX side on stop duration
152 stop_bit_tx_time_ = (bit_time / 4) * 5 / 4;
153 }
154
155 static Parity calculate_parity(Parity parity, uint8_t value)
156 {
157 if (parity == Parity::NONE) return Parity::NONE;
158 bool odd = false;
159 while (value)
160 {
161 if (value & 0x01) odd = !odd;
162 value >>= 1;
163 }
164 return (odd ? Parity::ODD : Parity::EVEN);
165 }
166
167 streams::ostreambuf& out_()
168 {
169 return obuf_;
170 }
171
172 void check_overflow(Errors& errors)
173 {
174 errors.queue_overflow = obuf_.overflow();
175 }
176
177 template<board::DigitalPin DPIN> void write(Parity parity, uint8_t value)
178 {
179 synchronized write_<DPIN>(parity, value);
180 }
181 template<board::DigitalPin DPIN> void write_(Parity parity, uint8_t value);
182
183 private:
184 // NOTE declaring obuf_ first instead of last optimizes code size (4 bytes)
186
187 // Various timing constants based on rate
188 uint16_t interbit_tx_time_;
189 uint16_t start_bit_tx_time_;
190 uint16_t stop_bit_tx_time_;
191 };
192
193 template<board::DigitalPin DPIN> void AbstractUATX::write_(Parity parity, uint8_t value)
194 {
195 using TX = gpio::FastPinType<DPIN>;
196 // Pre-calculate all what we need: parity bit
197 Parity parity_bit = calculate_parity(parity, value);
198
199 // Write start bit
200 TX::clear();
201 // Wait before starting actual value transmission
202 _delay_loop_2(start_bit_tx_time_);
203 for (uint8_t bit = 0; bit < 8; ++bit)
204 {
205 if (value & 0x01)
206 TX::set();
207 else
208 TX::clear();
209 value >>= 1;
210 _delay_loop_2(interbit_tx_time_);
211 }
212 // Add parity if needed
213 if (parity_bit != Parity::NONE)
214 {
215 if (parity_bit == parity)
216 TX::clear();
217 else
218 TX::set();
219 _delay_loop_2(interbit_tx_time_);
220 }
221 // Add stop bit
222 TX::set();
223 _delay_loop_2(stop_bit_tx_time_);
224 }
226
238 template<board::DigitalPin TX_> class UATX : public AbstractUATX, public UARTErrors
239 {
240 public:
242 static constexpr const board::DigitalPin TX = TX_;
243
250 template<uint8_t SIZE_TX> explicit UATX(char (&output)[SIZE_TX]) : AbstractUATX{output}
251 {
253 }
254
265 void begin(uint32_t rate, Parity parity = Parity::NONE, StopBits stop_bits = StopBits::ONE)
266 {
267 parity_ = parity;
268 compute_times(rate, stop_bits);
269 out_().queue().unlock();
270 }
271
281 {
282 out_().queue().lock();
283 }
284
285 private:
286 bool on_put(streams::ostreambuf& obuf)
287 {
288 if (&obuf != &out_()) return false;
289 check_overflow(errors());
290 char value;
291 while (out_().queue().pull(value)) write<TX>(parity_, uint8_t(value));
292 return true;
293 }
294
295 Parity parity_;
297
299 };
300
302 class AbstractUARX
303 {
304 public:
310 {
311 return streams::istream(in_());
312 }
313
314 protected:
315 AbstractUARX(const AbstractUARX&) = delete;
316 AbstractUARX& operator=(const AbstractUARX&) = delete;
317
318 template<uint8_t SIZE_RX> explicit AbstractUARX(char (&input)[SIZE_RX]) : ibuf_{input} {}
319
321 {
322 return ibuf_;
323 }
324
325 void compute_times(uint32_t rate, UNUSED bool has_parity, UNUSED StopBits stop_bits)
326 {
327 // Calculate timing for RX in number of cycles
328 uint16_t bit_time = uint16_t(F_CPU / rate);
329
330 // Actual timing is based on number of times to count 4 cycles, because we use _delay_loop_2()
331
332 // Time to wait (_delay_loop_2) between detection of start bit and sampling of first bit
333 // For sampling of first bit we wait until middle of first bit
334 // We remove processing time due to ISR call and ISR code:
335 // - 3 cycles to generate the PCI interrupt
336 // - 1-4 (take 2) cycles to complete current instruction
337 // - 4 cycles to process the interrupt + 2 cycles rjmp in vector table
338 // - 48 cycles spent in PCINT vector to save context and check stop bit (sbic)
339 // 17 push + 1 in + 1 eor => 34 + 1 + 1 = 36
340 // 2 lds + 1 ldd + 1 in + 1 mov + 1 andi + 1 sbrc => 4 + 2 + 1 + 1 + 1 + 3 = 12
341 // - 2 cycles to setup stack variables
342 // 1 std => 2
343 // - (4N) + 4 in delay
344 // - 8 cycles until first bit sample read (sbis)
345 // 2 ldd + 3 ldi + 1 sbis => 4 + 3 + 1
346 start_bit_rx_time_ = compute_delay((3 * bit_time) / 2, 3 + 2 + 4 + 48 + 2 + 4 + 8);
347
348 // Time to wait (_delay_loop_2) between sampling of 2 consecutive data bits
349 // This is also use between last bit and parity bit (if checked) or stop bit
350 // We have to wait exactly for `bit_time` cycles
351 // We remove processing time due to each bit sampling and data value update
352 // - 10+4N cycles elapse between processing of each bit
353 interbit_rx_time_ = compute_delay(bit_time, 10);
354
355 // No extra delay is used after sampling of first stop bit (as there are already
356 // enough code cycles used for pushing data and restoring context on ISR leave)
357 // Actually, >80 cycles elapse until next PCI can be handled
358 }
359
360 template<board::DigitalPin DPIN> void pin_change(Parity parity, Errors& errors);
361
362 private:
363 static constexpr uint16_t compute_delay(uint16_t total_cycles, uint16_t less_cycles)
364 {
365 // We add 3 cycles to allow rounding
366 return (total_cycles > less_cycles) ? ((total_cycles - less_cycles + 3) / 4) : 1;
367 }
368
369 // NOTE declaring ibuf_ first instead of last optimizes code size (2 bytes)
371
372 // Various timing constants based on rate
373 uint16_t interbit_rx_time_;
374 uint16_t start_bit_rx_time_;
375 };
376
377 template<board::DigitalPin DPIN> void AbstractUARX::pin_change(Parity parity, Errors& errors)
378 {
379 using RX = gpio::FastPinType<DPIN>;
380 // Check RX is low (start bit)
381 if (RX::value()) return;
382 uint8_t value = 0;
383 bool odd = false;
384 errors.has_errors = 0;
385 // Wait for start bit to finish
386 _delay_loop_2(start_bit_rx_time_);
387 // Read first 7 bits
388 for (uint8_t i = 0; i < 8; ++i)
389 {
390 if (RX::value())
391 {
392 value |= 0x80;
393 odd = !odd;
394 }
395 if (i < 7)
396 value >>= 1;
397 _delay_loop_2(interbit_rx_time_);
398 }
399
400 if (parity != Parity::NONE)
401 {
402 // Check parity bit
403 bool parity_bit = (parity == Parity::ODD ? !odd : odd);
404 // Check parity bit
405 errors.parity_error = (RX::value() != parity_bit);
406 _delay_loop_2(interbit_rx_time_);
407 }
408
409 // Check we receive a stop bit
410 if (!RX::value())
411 errors.frame_error = true;
412 // Push value if no error
413 if (errors.has_errors == 0)
414 errors.queue_overflow = !in_().queue().push_(char(value));
415 }
417
419 template<typename T, T IRQ> class UARX {};
421
423 template<board::ExternalInterruptPin RX_>
424 class UARX<board::ExternalInterruptPin, RX_> : public AbstractUARX, public UARTErrors
425 {
426 public:
432 static constexpr const board::DigitalPin RX = board::EXT_PIN<RX_>();
433
440
452 template<uint8_t SIZE_RX>
453 explicit UARX(char (&input)[SIZE_RX], INT_TYPE& enabler) : AbstractUARX{input}, int_{enabler}
454 {
456 }
457
468 void begin(uint32_t rate, Parity parity = Parity::NONE, StopBits stop_bits = StopBits::ONE)
469 {
470 parity_ = parity;
471 AbstractUARX::compute_times(rate, parity != Parity::NONE, stop_bits);
472 int_.enable();
473 }
474
482 void end(BufferHandling buffer_handling = BufferHandling::KEEP)
483 {
484 int_.disable();
485 if (buffer_handling == BufferHandling::CLEAR)
486 in_().queue().clear();
487 }
488
489 private:
490 void on_pin_change()
491 {
492 this->pin_change<RX>(parity_, errors());
493 // Clear PCI interrupt to remove pending PCI occurred during this method and to detect next start bit
494 int_.clear_();
495 }
496
497 Parity parity_;
499 INT_TYPE& int_;
500 friend struct isr_handler;
501 };
502
504 template<typename T, T IRQ, board::DigitalPin TX> class UART {};
506
508 template<board::ExternalInterruptPin RX_, board::DigitalPin TX_>
509 class UART<board::ExternalInterruptPin, RX_, TX_> : public AbstractUARX, public AbstractUATX, public UARTErrors
510 {
511 public:
513 static constexpr const board::DigitalPin TX = TX_;
517 static constexpr const board::DigitalPin RX = board::EXT_PIN<RX_>();
518
525
538 template<uint8_t SIZE_RX, uint8_t SIZE_TX>
539 explicit UART(char (&input)[SIZE_RX], char (&output)[SIZE_TX], INT_TYPE& enabler)
540 : AbstractUARX{input}, AbstractUATX{output}, int_{enabler}
541 {
543 }
544
555 void begin(uint32_t rate, Parity parity = Parity::NONE, StopBits stop_bits = StopBits::ONE)
556 {
557 out_().queue().unlock();
558 parity_ = parity;
559 AbstractUARX::compute_times(rate, parity != Parity::NONE, stop_bits);
560 AbstractUATX::compute_times(rate, stop_bits);
561 int_.enable();
562 }
563
571 void end(BufferHandling buffer_handling = BufferHandling::KEEP)
572 {
573 int_.disable();
574 if (buffer_handling == BufferHandling::CLEAR)
575 in_().queue().clear();
576 out_().queue().lock();
577 }
578
579 private:
580 bool on_put(streams::ostreambuf& obuf)
581 {
582 if (&obuf != &out_()) return false;
583 check_overflow(errors());
584 char value;
585 while (out_().queue().pull(value)) write<TX>(parity_, uint8_t(value));
586 return true;
587 }
588
589 void on_pin_change()
590 {
591 this->pin_change<RX>(parity_, errors());
592 // Clear PCI interrupt to remove pending PCI occurred during this method and to detect next start bit
593 int_.clear_();
594 }
595
596 Parity parity_;
599 INT_TYPE& int_;
600
601 friend struct isr_handler;
603 };
604
606 template<board::InterruptPin RX_> class UARX<board::InterruptPin, RX_> : public AbstractUARX, public UARTErrors
607 {
608 public:
614 static constexpr const board::DigitalPin RX = board::PCI_PIN<RX_>();
615
622
634 template<uint8_t SIZE_RX>
635 explicit UARX(char (&input)[SIZE_RX], PCI_TYPE& enabler)
636 : AbstractUARX{input}, pci_{enabler}
637 {
639 }
640
651 void begin(uint32_t rate, Parity parity = Parity::NONE, StopBits stop_bits = StopBits::ONE)
652 {
653 parity_ = parity;
654 AbstractUARX::compute_times(rate, parity != Parity::NONE, stop_bits);
655 pci_.template enable_pin<RX_>();
656 }
657
665 void end(BufferHandling buffer_handling = BufferHandling::KEEP)
666 {
667 pci_.template disable_pin<RX_>();
668 if (buffer_handling == BufferHandling::CLEAR)
669 in_().queue().clear();
670 }
671
672 private:
673 void on_pin_change()
674 {
675 this->pin_change<RX>(parity_, errors());
676 // Clear PCI interrupt to remove pending PCI occurred during this method and to detect next start bit
677 pci_.clear_();
678 }
679
680 Parity parity_;
682 PCI_TYPE& pci_;
683 friend struct isr_handler;
684 };
685
687 template<board::InterruptPin RX_, board::DigitalPin TX_>
688 class UART<board::InterruptPin, RX_, TX_> : public AbstractUARX, public AbstractUATX, public UARTErrors
689 {
690 public:
692 static constexpr const board::DigitalPin TX = TX_;
696 static constexpr const board::DigitalPin RX = board::PCI_PIN<RX_>();
697
704
717 template<uint8_t SIZE_RX, uint8_t SIZE_TX>
718 explicit UART(char (&input)[SIZE_RX], char (&output)[SIZE_TX], PCI_TYPE& enabler)
719 : AbstractUARX{input}, AbstractUATX{output}, pci_{enabler}
720 {
722 }
723
734 void begin(uint32_t rate, Parity parity = Parity::NONE, StopBits stop_bits = StopBits::ONE)
735 {
736 out_().queue().unlock();
737 parity_ = parity;
738 AbstractUARX::compute_times(rate, parity != Parity::NONE, stop_bits);
739 AbstractUATX::compute_times(rate, stop_bits);
740 pci_.template enable_pin<RX_>();
741 }
742
751 void end(BufferHandling buffer_handling = BufferHandling::KEEP)
752 {
753 pci_.template disable_pin<RX_>();
754 if (buffer_handling == BufferHandling::CLEAR)
755 in_().queue().clear();
756 out_().queue().lock();
757 }
758
759 private:
760 bool on_put(streams::ostreambuf& obuf)
761 {
762 if (&obuf != &out_()) return false;
763 check_overflow(errors());
764 char value;
765 while (out_().queue().pull(value)) write<TX>(parity_, uint8_t(value));
766 return true;
767 }
768
769 void on_pin_change()
770 {
771 this->pin_change<RX>(parity_, errors());
772 // Clear PCI interrupt to remove pending PCI occurred during this method and to detect next start bit
773 pci_.clear_();
774 }
775
776 Parity parity_;
779 PCI_TYPE& pci_;
780
781 friend struct isr_handler;
783 };
784
785 // Useful type aliases
786 //=====================
787
800 template<board::ExternalInterruptPin RX_> using UARX_EXT = UARX<board::ExternalInterruptPin, RX_>;
801
814 template<board::InterruptPin RX_> using UARX_PCI = UARX<board::InterruptPin, RX_>;
815
832 template<board::ExternalInterruptPin RX_, board::DigitalPin TX_>
833 using UART_EXT = UART<board::ExternalInterruptPin, RX_, TX_>;
834
851 template<board::InterruptPin RX_, board::DigitalPin TX_>
852 using UART_PCI = UART<board::InterruptPin, RX_, TX_>;
853
855 struct isr_handler
856 {
857 template<uint8_t PCI_NUM_, board::InterruptPin RX_> static void check_uarx_pci()
858 {
859 interrupt::isr_handler_pci::check_pci_pins<PCI_NUM_, RX_>();
860 using UARX = serial::soft::UARX_PCI<RX_>;
861 interrupt::HandlerHolder<UARX>::handler()->on_pin_change();
862 }
863
864 template<uint8_t INT_NUM_, board::ExternalInterruptPin RX_> static void check_uarx_int()
865 {
866 interrupt::isr_handler_int::check_int_pin<INT_NUM_, RX_>();
867 using UARX = serial::soft::UARX_EXT<RX_>;
868 interrupt::HandlerHolder<UARX>::handler()->on_pin_change();
869 }
870
871 template<uint8_t PCI_NUM_, board::InterruptPin RX_, board::DigitalPin TX_> static void check_uart_pci()
872 {
873 interrupt::isr_handler_pci::check_pci_pins<PCI_NUM_, RX_>();
875 interrupt::HandlerHolder<UART>::handler()->on_pin_change();
876 }
877
878 template<uint8_t INT_NUM_, board::ExternalInterruptPin RX_, board::DigitalPin TX_> static void check_uart_int()
879 {
880 interrupt::isr_handler_int::check_int_pin<INT_NUM_, RX_>();
882 interrupt::HandlerHolder<UART>::handler()->on_pin_change();
883 }
884 };
886}
887
888namespace serial
889{
891 // Specific traits of HW UART classes
892 template<board::DigitalPin TX> struct UART_trait<soft::UATX<TX>>
893 {
894 static constexpr bool IS_UART = true;
895 static constexpr bool IS_HW_UART = false;
896 static constexpr bool IS_SW_UART = true;
897 static constexpr bool HAS_TX = true;
898 static constexpr bool HAS_RX = false;
899 };
900 template<board::InterruptPin RX> struct UART_trait<soft::UARX_PCI<RX>>
901 {
902 static constexpr bool IS_UART = true;
903 static constexpr bool IS_HW_UART = false;
904 static constexpr bool IS_SW_UART = true;
905 static constexpr bool HAS_TX = false;
906 static constexpr bool HAS_RX = true;
907 };
908 template<board::ExternalInterruptPin RX> struct UART_trait<soft::UARX_EXT<RX>>
909 {
910 static constexpr bool IS_UART = true;
911 static constexpr bool IS_HW_UART = false;
912 static constexpr bool IS_SW_UART = true;
913 static constexpr bool HAS_TX = false;
914 static constexpr bool HAS_RX = true;
915 };
916 template<board::DigitalPin TX, board::InterruptPin RX> struct UART_trait<soft::UART_PCI<RX, TX>>
917 {
918 static constexpr bool IS_UART = true;
919 static constexpr bool IS_HW_UART = false;
920 static constexpr bool IS_SW_UART = true;
921 static constexpr bool HAS_TX = true;
922 static constexpr bool HAS_RX = true;
923 };
924 template<board::DigitalPin TX, board::ExternalInterruptPin RX> struct UART_trait<soft::UART_EXT<RX, TX>>
925 {
926 static constexpr bool IS_UART = true;
927 static constexpr bool IS_HW_UART = false;
928 static constexpr bool IS_SW_UART = true;
929 static constexpr bool HAS_TX = true;
930 static constexpr bool HAS_RX = true;
931 };
933}
934
935#endif /* SOFTUART_HH */
API that manipulates a given digital IO pin of a the target MCU.
Definition: gpio.h:551
Handler of an External Interrupt.
Definition: int.h:132
Holder of latest UART errors.
Definition: uart_commons.h:96
UART(char(&input)[SIZE_RX], char(&output)[SIZE_TX], INT_TYPE &enabler)
Construct a new software serial receiver/transceiver and provide it with 2 buffers,...
Definition: soft_uart.h:539
void begin(uint32_t rate, Parity parity=Parity::NONE, StopBits stop_bits=StopBits::ONE)
Enable the receiver/transceiver.
Definition: soft_uart.h:555
typename interrupt::INTSignal< RX_ > INT_TYPE
The interrupt::INTSignal type for RX_ pin, if it is a External Interrupt pin.
Definition: soft_uart.h:524
void end(BufferHandling buffer_handling=BufferHandling::KEEP)
Stop all transmissions and receptions.
Definition: soft_uart.h:571
void begin(uint32_t rate, Parity parity=Parity::NONE, StopBits stop_bits=StopBits::ONE)
Enable the receiver/transceiver.
Definition: soft_uart.h:734
void end(BufferHandling buffer_handling=BufferHandling::KEEP)
Stop all transmissions and receptions.
Definition: soft_uart.h:751
UART(char(&input)[SIZE_RX], char(&output)[SIZE_TX], PCI_TYPE &enabler)
Construct a new software serial receiver/transceiver and provide it with 2 buffers,...
Definition: soft_uart.h:718
interrupt::PCI_SIGNAL< RX_ > PCI_TYPE
The interrupt::PCISignal type for RX_ pin, if it is a PinChangeInterrupt pin.
Definition: soft_uart.h:703
UARX(char(&input)[SIZE_RX], INT_TYPE &enabler)
Construct a new software serial receiver and provide it with a buffer for interrupt-based reception.
Definition: soft_uart.h:453
void end(BufferHandling buffer_handling=BufferHandling::KEEP)
Stop reception.
Definition: soft_uart.h:482
void begin(uint32_t rate, Parity parity=Parity::NONE, StopBits stop_bits=StopBits::ONE)
Enable the receiver.
Definition: soft_uart.h:468
typename interrupt::INTSignal< RX_ > INT_TYPE
The interrupt::INTSignal type for RX_ pin, if it is a External Interrupt pin.
Definition: soft_uart.h:439
void end(BufferHandling buffer_handling=BufferHandling::KEEP)
Stop reception.
Definition: soft_uart.h:665
interrupt::PCI_SIGNAL< RX_ > PCI_TYPE
The interrupt::PCISignal type for RX_ pin, if it is a PinChangeInterrupt pin.
Definition: soft_uart.h:621
void begin(uint32_t rate, Parity parity=Parity::NONE, StopBits stop_bits=StopBits::ONE)
Enable the receiver.
Definition: soft_uart.h:651
UARX(char(&input)[SIZE_RX], PCI_TYPE &enabler)
Construct a new software serial receiver and provide it with a buffer for interrupt-based reception.
Definition: soft_uart.h:635
Software-emulated serial transmitter API.
Definition: soft_uart.h:239
void end(UNUSED BufferHandling buffer_handling=BufferHandling::KEEP)
Stop all transmissions.
Definition: soft_uart.h:280
UATX(char(&output)[SIZE_TX])
Construct a new software serial transmitter and provide it with a buffer for payload transmission.
Definition: soft_uart.h:250
static constexpr const board::DigitalPin TX
The board::DigitalPin to which transmitted signal is sent.
Definition: soft_uart.h:242
void begin(uint32_t rate, Parity parity=Parity::NONE, StopBits stop_bits=StopBits::ONE)
Enable the transmitter.
Definition: soft_uart.h:265
Input stream wrapper to provide formatted input API, a la C++.
Definition: streams.h:360
Input API based on a ring buffer.
Definition: streambuf.h:257
Output stream wrapper to provide formatted output API, a la C++.
Definition: streams.h:61
Output API based on a ring buffer.
Definition: streambuf.h:96
#define UNUSED
Specific GCC attribute to declare an argument or variable unused, so that the compiler does not emit ...
Definition: defines.h:45
General Purpose (digital) Input Output API.
General API for handling External Interrupt pins.
General API for handling AVR interrupt vectors.
Defines all types and constants specific to support a specific MCU target.
Definition: empty.h:38
DigitalPin
Defines all available digital input/output pins of the target MCU.
Definition: empty.h:56
This namespace defines common errors that can be returned by some FastArduino API methods,...
Definition: errors.h:38
typename FastPinType< DPIN_ >::TYPE FAST_PIN
Useful alias type to the FastPin type matching a given board::DigitalPin.
Definition: gpio.h:694
@ OUTPUT
Digital pin is configured as output.
@ INPUT
Digital pin is configured as high-impedance (open drain) input.
typename PCIType< PIN >::TYPE PCI_SIGNAL
Useful alias type to the PCISignal type matching a given board::InterruptPin.
Definition: pci.h:568
void register_handler(Handler &handler)
Register a class instance containing methods that shall be called back by an ISR.
Definition: interrupts.h:185
Defines API types used by software UART features.
Definition: soft_uart.h:96
UARX< board::InterruptPin, RX_ > UARX_PCI
Software-emulated serial receiver API.
Definition: soft_uart.h:814
UART< board::ExternalInterruptPin, RX_, TX_ > UART_EXT
Software-emulated serial receiver/transceiver API.
Definition: soft_uart.h:833
UARX< board::ExternalInterruptPin, RX_ > UARX_EXT
Software-emulated serial receiver API.
Definition: soft_uart.h:800
UART< board::InterruptPin, RX_, TX_ > UART_PCI
Software-emulated serial receiver/transceiver API.
Definition: soft_uart.h:852
Defines all API for UART features.
Definition: soft_uart.h:84
BufferHandling
How the TX/RX buffer should be handled when ending transmission (see end() methods) on UATX/UARX.
Definition: uart_commons.h:63
@ KEEP
Stop transmission immediately, keep buffer as-is.
StopBits
Number of stop bits used for serial transmission.
Definition: uart_commons.h:51
@ ONE
One stop bit.
Parity
Parity used for serial transmission.
Definition: uart_commons.h:38
@ ODD
Odd parity bit.
@ NONE
No parity bit.
General API for handling Pin Change Interrupts.
#define DECL_OSTREAMBUF_LISTENERS_FRIEND
This macro shall be used in a class containing a private callback method bool on_put(streams::ostream...
Definition: streambuf.h:73
C++-like std::iostream facilities.
Common definitions for serial API.
General utilities API that have broad application in programs.