Pico-Arduino
PicoSoftwareSerial.h
1 #include "hardware/clocks.h"
2 #include "hardware/gpio.h"
3 #include "SoftwareSerial/pio_uart_tx.h"
4 #include "SoftwareSerial/pio_uart_rx.h"
5 #include "PicoStreamPrintf.h"
6 
7 namespace pico_arduino {
8 
17 class SoftwareSerial : public Stream, public StreamPrintf {
18  public:
19  SoftwareSerial(PIO pio = pio1, uint stateMachineRxIndex=0,uint stateMachineTxIndex=1) : StreamPrintf(this) {
20  this->pio = pio;
21  this->sm_rx = stateMachineRxIndex;
22  this->sm_tx = stateMachineTxIndex;
23  }
24 
25  void begin(uint baud=9800, int rxPin=-1, int txPin=-1 ){
26  this->baud = baud;
27 
28  if (rxPin >=0 ){
29  setupRx(rxPin);
30  }
31 
32  if (txPin >=0 ){
33  setupTx(txPin);
34  }
35  }
36 
37  virtual int peek() {
38  peekValue = read();
39  return peekValue;
40  }
41 
42  virtual int available() {
43  return pio_sm_get_rx_fifo_level (pio, sm_rx);
44  }
45 
46  virtual int read() {
47  if (peekValue!=-1){
48  int result = peekValue;
49  peekValue = -1;
50  return result;
51  }
52  // 8-bit read from the uppermost byte of the FIFO, as data is left-justified
53  io_rw_8 *rxfifo_shift = (io_rw_8*)&pio->rxf[sm_rx] + 3;
54  if (pio_sm_is_rx_fifo_empty(pio, sm_rx))
55  return -1;
56 
57  tight_loop_contents();
58  return (char)*rxfifo_shift;
59  }
60 
61  virtual size_t write(uint8_t c) {
62  pio_sm_put_blocking(pio, sm_tx, (uint32_t)c);
63  return 1;
64  }
65 
66  using Print::write; // pull in write(str) and write(buf, size) from Print
67  using Print::print; // pull in write(str) and write(buf, size) from Print
68  using Print::println; // pull in write(str) and write(buf, size) from Print
69 
70 
71  protected:
72  PIO pio;
73  uint sm_rx;
74  uint sm_tx;
75  uint baud;
76  int offset;
77  int peekValue=-1;
78 
79  void setupRx(uint pin) {
80  pio_sm_set_consecutive_pindirs(pio, sm_rx, pin, 1, false);
81  pio_gpio_init(pio, pin);
82  gpio_pull_up(pin);
83 
84  int offset = pio_add_program(pio, &pio_uart_rx_program);
85  pio_sm_config c = pio_uart_rx_program_get_default_config(offset);
86  sm_config_set_in_pins(&c, pin); // for WAIT, IN
87  sm_config_set_jmp_pin(&c, pin); // for JMP
88  // Shift to right, autopull disabled
89  sm_config_set_in_shift(&c, true, false, 32);
90  // Deeper FIFO as we're not doing any TX
91  sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_RX);
92  // SM transmits 1 bit per 8 execution cycles.
93  float div = (float)clock_get_hz(clk_sys) / (8 * baud);
94  sm_config_set_clkdiv(&c, div);
95 
96  pio_sm_init(pio, sm_rx, offset, &c);
97  pio_sm_set_enabled(pio, sm_rx, true);
98  }
99 
100  void setupTx(uint pin_tx) {
101  // Tell PIO to initially drive output-high on the selected pin, then map PIO
102  // onto that pin with the IO muxes.
103  pio_sm_set_pins_with_mask(pio, sm_tx, 1u << pin_tx, 1u << pin_tx);
104  pio_sm_set_pindirs_with_mask(pio, sm_tx, 1u << pin_tx, 1u << pin_tx);
105  pio_gpio_init(pio, pin_tx);
106 
107  int offset = pio_add_program(pio, &pio_uart_tx_program);
108  pio_sm_config c = pio_uart_tx_program_get_default_config(offset);
109 
110  // OUT shifts to right, no autopull
111  sm_config_set_out_shift(&c, true, false, 32);
112 
113  // We are mapping both OUT and side-set to the same pin, because sometimes
114  // we need to assert user data onto the pin (with OUT) and sometimes
115  // assert constant values (start/stop bit)
116  sm_config_set_out_pins(&c, pin_tx, 1);
117  sm_config_set_sideset_pins(&c, pin_tx);
118 
119  // We only need TX, so get an 8-deep FIFO!
120  sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);
121 
122  // SM transmits 1 bit per 8 execution cycles.
123  float div = (float)clock_get_hz(clk_sys) / (8 * baud);
124  sm_config_set_clkdiv(&c, div);
125 
126  pio_sm_init(pio, sm_tx, offset, &c);
127  pio_sm_set_enabled(pio, sm_tx, true);
128  }
129 };
130 
131 }
Definition: Stream.h:51
Software Serial Arduino Stream which uses the Pico PIO.
Definition: PicoSoftwareSerial.h:17
Support for Serial.printf. The maximum printable length is defined by PRINTF_BUFFER_SIZE which is set...
Definition: PicoStreamPrintf.h:16
Pico Arduino Framework.
Definition: Arduino.cpp:26