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 3.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  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));
  43. static uint8_t tx_buff[UART_TX_BUFF_LEN] = {0};
  44. static struct ring_buffer tx = RB_INIT(tx_buff, sizeof(tx_buff));
  45. static bool reroute_serial_debug = false;
  46. static bool tx_irq_state = false;
  47. static void serial_irq(void) {
  48. // Rx - read from UART FIFO to local buffer
  49. while (uart_is_readable(UART_ID) && (rb_space(&rx) > 0)) {
  50. uint8_t ch = uart_getc(UART_ID);
  51. rb_push(&rx, ch);
  52. }
  53. // Tx - write to UART FIFO if needed
  54. while (uart_is_writable(UART_ID)) {
  55. if (rb_len(&tx) > 0) {
  56. uart_putc_raw(UART_ID, rb_pop(&tx));
  57. } else {
  58. uart_set_irq_enables(UART_ID, true, false);
  59. tx_irq_state = false;
  60. break;
  61. }
  62. }
  63. }
  64. void serial_init(void) {
  65. uart_init(UART_ID, BAUD_RATE);
  66. gpio_set_function(UART_TX_PIN, GPIO_FUNC_UART);
  67. gpio_set_function(UART_RX_PIN, GPIO_FUNC_UART);
  68. uart_set_hw_flow(UART_ID, false, false);
  69. uart_set_format(UART_ID, DATA_BITS, STOP_BITS, PARITY);
  70. uart_set_fifo_enabled(UART_ID, true);
  71. irq_set_exclusive_handler(UART_IRQ, serial_irq);
  72. irq_set_enabled(UART_IRQ, true);
  73. uart_set_irq_enables(UART_ID, true, false);
  74. tx_irq_state = false;
  75. }
  76. void serial_write(const uint8_t *buf, size_t count) {
  77. uart_set_irq_enables(UART_ID, true, false);
  78. tx_irq_state = false;
  79. while ((rb_len(&tx) == 0) && uart_is_writable(UART_ID) && (count > 0)) {
  80. uart_putc_raw(UART_ID, *buf++);
  81. count--;
  82. }
  83. if (count == 0) {
  84. return;
  85. }
  86. size_t off = 0;
  87. #ifdef SERIAL_WRITES_BLOCK_WHEN_BUFFER_FULL
  88. while (count > rb_space(&tx)) {
  89. size_t space = rb_space(&tx);
  90. rb_add(&tx, buf + off, space);
  91. count -= space;
  92. off += space;
  93. uart_set_irq_enables(UART_ID, true, true);
  94. tx_irq_state = true;
  95. sleep_ms(1);
  96. uart_set_irq_enables(UART_ID, true, false);
  97. tx_irq_state = false;
  98. }
  99. #endif // SERIAL_WRITES_BLOCK_WHEN_BUFFER_FULL
  100. rb_add(&tx, buf + off, count);
  101. uart_set_irq_enables(UART_ID, true, true);
  102. tx_irq_state = true;
  103. }
  104. void serial_set_reroute(bool reroute) {
  105. reroute_serial_debug = reroute;
  106. }
  107. void serial_run(void) {
  108. uart_set_irq_enables(UART_ID, false, tx_irq_state);
  109. // Rx - pass local buffer to further processing
  110. if (rb_len(&rx) >= 1) {
  111. if (rb_peek(&rx) == ENTER_BOOTLOADER_MAGIC) {
  112. reset_to_bootloader();
  113. } else if (reroute_serial_debug) {
  114. rb_move(&rx, debug_handle_input);
  115. } else {
  116. rb_move(&rx, cnsl_handle_input);
  117. }
  118. }
  119. uart_set_irq_enables(UART_ID, true, tx_irq_state);
  120. }