S&B Volcano vaporizer remote control with Pi Pico W
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

log.c 4.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. /*
  2. * log.c
  3. *
  4. * Copyright (c) 2022 - 2023 Thomas Buck (thomas@xythobuz.de)
  5. *
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * See <http://www.gnu.org/licenses/>.
  17. */
  18. #include <stdio.h>
  19. #include <string.h>
  20. #include "hardware/watchdog.h"
  21. #include "ff.h"
  22. #include "config.h"
  23. #include "main.h"
  24. #include "lcd.h"
  25. #include "textbox.h"
  26. #include "usb_cdc.h"
  27. #include "serial.h"
  28. #include "ring.h"
  29. #include "log.h"
  30. static uint8_t log_buff[4096] = {0};
  31. static struct ring_buffer log = RB_INIT(log_buff, sizeof(log_buff), 1);
  32. static uint8_t line_buff[256] = {0};
  33. static volatile bool got_input = false;
  34. static int16_t lcd_off = 0;
  35. #ifndef PICOWOTA
  36. static FIL log_file_fat;
  37. #endif // PICOWOTA
  38. static void add_to_log(const void *buff, size_t len) {
  39. rb_add(&log, buff, len);
  40. }
  41. static void lcd_write(const void *buf, size_t len) {
  42. char tmp[len + 1];
  43. memcpy(tmp, buf, len);
  44. tmp[len] = '\0';
  45. lcd_off = text_box(tmp, false,
  46. "fixed_10x20",
  47. 0, LCD_WIDTH,
  48. lcd_off, LCD_HEIGHT - lcd_off,
  49. 0);
  50. }
  51. void log_dump_to_lcd(void) {
  52. static size_t prev_len = 0;
  53. size_t len = rb_len(&log);
  54. if (len == prev_len) {
  55. return;
  56. }
  57. prev_len = len;
  58. lcd_off = 0;
  59. const size_t todo = 120;
  60. size_t text_off = 0;
  61. if (len > todo) {
  62. text_off = len - todo;
  63. }
  64. rb_dump(&log, lcd_write, text_off);
  65. }
  66. #ifndef PICOWOTA
  67. static void log_dump_to_x(void (*write)(const void *, size_t)) {
  68. if (rb_len(&log) == 0) {
  69. return;
  70. }
  71. int l = snprintf((char *)line_buff, sizeof(line_buff), "\r\n\r\nbuffered log output:\r\n");
  72. if ((l > 0) && (l <= (int)sizeof(line_buff))) {
  73. write(line_buff, l);
  74. }
  75. rb_dump(&log, write, 0);
  76. l = snprintf((char *)line_buff, sizeof(line_buff), "\r\n\r\nlive log:\r\n");
  77. if ((l > 0) && (l <= (int)sizeof(line_buff))) {
  78. write(line_buff, l);
  79. }
  80. }
  81. void log_dump_to_usb(void) {
  82. log_dump_to_x(usb_cdc_write);
  83. }
  84. void log_dump_to_uart(void) {
  85. #ifndef NDEBUG
  86. log_dump_to_x(serial_write);
  87. #endif // NDEBUG
  88. }
  89. static void log_file_write_callback(const void *data, size_t len) {
  90. UINT bw;
  91. FRESULT res = f_write(&log_file_fat, data, len, &bw);
  92. if ((res != FR_OK) || (bw != len)) {
  93. debug("error: f_write %u returned %d", len, res);
  94. }
  95. }
  96. void log_dump_to_disk(void) {
  97. FRESULT res = f_open(&log_file_fat, "log.txt", FA_CREATE_ALWAYS | FA_WRITE);
  98. if (res != FR_OK) {
  99. debug("error: f_open returned %d", res);
  100. return;
  101. }
  102. rb_dump(&log, log_file_write_callback, 0);
  103. res = f_close(&log_file_fat);
  104. if (res != FR_OK) {
  105. debug("error: f_close returned %d", res);
  106. }
  107. }
  108. #endif // PICOWOTA
  109. void debug_log_va(bool log, const char *format, va_list args) {
  110. int l = vsnprintf((char *)line_buff, sizeof(line_buff), format, args);
  111. if (l < 0) {
  112. // encoding error
  113. l = snprintf((char *)line_buff, sizeof(line_buff), "%s: encoding error\r\n", __func__);
  114. } else if (l >= (ssize_t)sizeof(line_buff)) {
  115. // not enough space for string
  116. l = snprintf((char *)line_buff, sizeof(line_buff), "%s: message too long (%d)\r\n", __func__, l);
  117. }
  118. if ((l > 0) && (l <= (int)sizeof(line_buff))) {
  119. #ifndef PICOWOTA
  120. usb_cdc_write(line_buff, l);
  121. #ifndef NDEBUG
  122. serial_write(line_buff, l);
  123. #endif // NDEBUG
  124. #endif // PICOWOTA
  125. if (log) {
  126. add_to_log(line_buff, l);
  127. }
  128. }
  129. }
  130. void debug_log(bool log, const char* format, ...) {
  131. va_list args;
  132. va_start(args, format);
  133. debug_log_va(log, format, args);
  134. va_end(args);
  135. }
  136. #ifndef PICOWOTA
  137. void debug_handle_input(const void *buff, size_t len) {
  138. (void)buff;
  139. if (len > 0) {
  140. got_input = true;
  141. }
  142. }
  143. void debug_wait_input(const char *format, ...) {
  144. va_list args;
  145. va_start(args, format);
  146. debug_log_va(false, format, args);
  147. va_end(args);
  148. got_input = false;
  149. usb_cdc_set_reroute(true);
  150. serial_set_reroute(true);
  151. while (!got_input) {
  152. main_loop_hw();
  153. }
  154. usb_cdc_set_reroute(false);
  155. serial_set_reroute(false);
  156. }
  157. #endif // PICOWOTA