S&B Volcano vaporizer remote control with Pi Pico W
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

serial.c 4.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. /*
  2. * serial.c
  3. *
  4. * https://github.com/raspberrypi/pico-examples/blob/master/uart/uart_advanced/uart_advanced.c
  5. * https://forums.raspberrypi.com/viewtopic.php?t=343110
  6. *
  7. * Copyright (c) 2023 Thomas Buck (thomas@xythobuz.de)
  8. *
  9. * This program is free software: you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation, either version 3 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * See <http://www.gnu.org/licenses/>.
  20. */
  21. // UART0, Tx GP0, Rx GP1
  22. #define UART_ID uart0
  23. #define UART_IRQ UART0_IRQ
  24. #define UART_TX_PIN 0
  25. #define UART_RX_PIN 1
  26. // Serial port parameters
  27. #define BAUD_RATE 115200
  28. #define DATA_BITS 8
  29. #define PARITY UART_PARITY_NONE
  30. #define STOP_BITS 1
  31. #define UART_RX_BUFF_LEN 64
  32. #define UART_TX_BUFF_LEN 128
  33. #include "hardware/uart.h"
  34. #include "hardware/gpio.h"
  35. #include "config.h"
  36. #include "console.h"
  37. #include "log.h"
  38. #include "util.h"
  39. #include "ring.h"
  40. #include "serial.h"
  41. static uint8_t rx_buff[UART_RX_BUFF_LEN] = {0};
  42. static struct ring_buffer rx = RB_INIT(rx_buff, sizeof(rx_buff), 1);
  43. static uint8_t tx_buff[UART_TX_BUFF_LEN] = {0};
  44. static struct ring_buffer tx = RB_INIT(tx_buff, sizeof(tx_buff), 1);
  45. static bool reroute_serial_debug = false;
  46. static bool tx_irq_state = false;
  47. static bool rx_irq_state = false;
  48. #define SET_TX_IRQ(v) { \
  49. tx_irq_state = v; \
  50. uart_set_irq_enables(UART_ID, \
  51. rx_irq_state, \
  52. tx_irq_state); \
  53. }
  54. #define SET_RX_IRQ(v) { \
  55. rx_irq_state = v; \
  56. uart_set_irq_enables(UART_ID, \
  57. rx_irq_state, \
  58. tx_irq_state); \
  59. }
  60. static void serial_irq(void) {
  61. // Rx - read from UART FIFO to local buffer
  62. while (uart_is_readable(UART_ID) && (rb_space(&rx) > 0)) {
  63. uint8_t ch = uart_getc(UART_ID);
  64. rb_push(&rx, &ch);
  65. }
  66. // Tx - write to UART FIFO if needed
  67. while (uart_is_writable(UART_ID)) {
  68. if (rb_len(&tx) > 0) {
  69. uint8_t c;
  70. rb_pop(&tx, &c);
  71. uart_putc_raw(UART_ID, c);
  72. } else {
  73. SET_TX_IRQ(false);
  74. break;
  75. }
  76. }
  77. }
  78. void serial_init(void) {
  79. uart_init(UART_ID, BAUD_RATE);
  80. gpio_set_function(UART_TX_PIN, GPIO_FUNC_UART);
  81. gpio_set_function(UART_RX_PIN, GPIO_FUNC_UART);
  82. uart_set_hw_flow(UART_ID, false, false);
  83. uart_set_format(UART_ID, DATA_BITS, STOP_BITS, PARITY);
  84. uart_set_fifo_enabled(UART_ID, true);
  85. irq_set_exclusive_handler(UART_IRQ, serial_irq);
  86. irq_set_enabled(UART_IRQ, true);
  87. SET_RX_IRQ(true);
  88. SET_TX_IRQ(false);
  89. }
  90. void serial_write(const void *buf, size_t count) {
  91. SET_TX_IRQ(false);
  92. while ((rb_len(&tx) == 0) && uart_is_writable(UART_ID) && (count > 0)) {
  93. uart_putc_raw(UART_ID, *(uint8_t *)buf);
  94. buf++;
  95. count--;
  96. }
  97. if (count == 0) {
  98. return;
  99. }
  100. size_t off = 0;
  101. #ifdef SERIAL_WRITES_BLOCK_WHEN_BUFFER_FULL
  102. while (count > rb_space(&tx)) {
  103. size_t space = rb_space(&tx);
  104. rb_add(&tx, buf + off, space);
  105. count -= space;
  106. off += space;
  107. SET_TX_IRQ(true);
  108. sleep_ms(1);
  109. SET_TX_IRQ(false);
  110. }
  111. #endif // SERIAL_WRITES_BLOCK_WHEN_BUFFER_FULL
  112. rb_add(&tx, buf + off, count);
  113. SET_TX_IRQ(true);
  114. }
  115. void serial_set_reroute(bool reroute) {
  116. reroute_serial_debug = reroute;
  117. }
  118. void serial_run(void) {
  119. SET_RX_IRQ(false);
  120. if (rb_len(&rx) >= 1) {
  121. uint8_t c;
  122. rb_peek(&rx, &c);
  123. if (c == ENTER_BOOTLOADER_MAGIC) {
  124. reset_to_bootloader();
  125. } else if (reroute_serial_debug) {
  126. rb_move(&rx, debug_handle_input);
  127. } else {
  128. rb_move(&rx, cnsl_handle_input);
  129. }
  130. }
  131. SET_RX_IRQ(true);
  132. }