console.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. // Copyright 2015 by Thorsten von Eicken, see LICENSE.txt
  2. #include <esp8266.h>
  3. #include "uart.h"
  4. #include "cgi.h"
  5. #include "uart.h"
  6. #include "serbridge.h"
  7. #include "serled.h"
  8. #include "config.h"
  9. #include "console.h"
  10. // Microcontroller console capturing the last 1024 characters received on the uart so
  11. // they can be shown on a web page
  12. // Buffer to hold concole contents.
  13. // Invariants:
  14. // - console_rd==console_wr <=> buffer empty
  15. // - *console_rd == next char to read
  16. // - *console_wr == next char to write
  17. // - 0 <= console_xx < BUF_MAX
  18. // - (console_wr+1)%BUF_MAX) == console_rd <=> buffer full
  19. #define BUF_MAX (1024)
  20. static char console_buf[BUF_MAX];
  21. static int console_wr, console_rd;
  22. static int console_pos; // offset since reset of buffer
  23. static void ICACHE_FLASH_ATTR
  24. console_write(char c) {
  25. console_buf[console_wr] = c;
  26. console_wr = (console_wr+1) % BUF_MAX;
  27. if (console_wr == console_rd) {
  28. // full, we write anyway and loose the oldest char
  29. console_rd = (console_rd+1) % BUF_MAX; // full, eat first char
  30. console_pos++;
  31. }
  32. }
  33. #if 0
  34. // return previous character in console, 0 if at start
  35. static char ICACHE_FLASH_ATTR
  36. console_prev(void) {
  37. if (console_wr == console_rd) return 0;
  38. return console_buf[(console_wr-1+BUF_MAX)%BUF_MAX];
  39. }
  40. #endif
  41. void ICACHE_FLASH_ATTR
  42. console_write_char(char c) {
  43. //if (c == '\n' && console_prev() != '\r') console_write('\r'); // does more harm than good
  44. console_write(c);
  45. }
  46. int ICACHE_FLASH_ATTR
  47. ajaxConsoleReset(HttpdConnData *connData) {
  48. if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up.
  49. jsonHeader(connData, 200);
  50. console_rd = console_wr = console_pos = 0;
  51. serbridgeReset();
  52. return HTTPD_CGI_DONE;
  53. }
  54. int ICACHE_FLASH_ATTR
  55. ajaxConsoleBaud(HttpdConnData *connData) {
  56. if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up.
  57. char buff[512];
  58. int len, status = 400;
  59. len = httpdFindArg(connData->getArgs, "rate", buff, sizeof(buff));
  60. if (len > 0) {
  61. int rate = atoi(buff);
  62. if (rate >= 300 && rate <= 1000000) {
  63. uart0_baud(rate);
  64. flashConfig.baud_rate = rate;
  65. status = configSave() ? 200 : 400;
  66. }
  67. } else if (connData->requestType == HTTPD_METHOD_GET) {
  68. status = 200;
  69. }
  70. jsonHeader(connData, status);
  71. os_sprintf(buff, "{\"rate\": %d}", flashConfig.baud_rate);
  72. httpdSend(connData, buff, -1);
  73. return HTTPD_CGI_DONE;
  74. }
  75. int ICACHE_FLASH_ATTR
  76. ajaxConsoleFormat(HttpdConnData *connData) {
  77. if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up.
  78. char buff[16];
  79. int len, status = 400;
  80. len = httpdFindArg(connData->getArgs, "fmt", buff, sizeof(buff));
  81. if (len >= 3) {
  82. int c = buff[0];
  83. if (c >= '5' && c <= '8') flashConfig.data_bits = c - '5' + FIVE_BITS;
  84. if (buff[1] == 'N') flashConfig.parity = NONE_BITS;
  85. if (buff[1] == 'E') flashConfig.parity = EVEN_BITS;
  86. if (buff[1] == 'O') flashConfig.parity = ODD_BITS;
  87. if (buff[2] == '1') flashConfig.stop_bits = ONE_STOP_BIT;
  88. if (buff[2] == '2') flashConfig.stop_bits = TWO_STOP_BIT;
  89. uart0_config(flashConfig.data_bits, flashConfig.parity, flashConfig.stop_bits);
  90. status = configSave() ? 200 : 400;
  91. } else if (connData->requestType == HTTPD_METHOD_GET) {
  92. status = 200;
  93. }
  94. jsonHeader(connData, status);
  95. os_sprintf(buff, "{\"fmt\": \"%c%c%c\"}", flashConfig.data_bits + '5',
  96. flashConfig.parity ? 'E' : 'N', flashConfig.stop_bits ? '2': '1');
  97. httpdSend(connData, buff, -1);
  98. return HTTPD_CGI_DONE;
  99. }
  100. int ICACHE_FLASH_ATTR
  101. ajaxConsoleSend(HttpdConnData *connData) {
  102. if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up.
  103. char buff[2048];
  104. int len, status = 400;
  105. // figure out where to start in buffer based on URI param
  106. len = httpdFindArg(connData->getArgs, "text", buff, sizeof(buff));
  107. if (len > 0) {
  108. serledFlash(50); // short blink on serial LED
  109. uart0_tx_buffer(buff, len);
  110. status = 200;
  111. }
  112. jsonHeader(connData, status);
  113. return HTTPD_CGI_DONE;
  114. }
  115. int ICACHE_FLASH_ATTR
  116. ajaxConsole(HttpdConnData *connData) {
  117. if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up.
  118. char buff[2048];
  119. int len; // length of text in buff
  120. int console_len = (console_wr+BUF_MAX-console_rd) % BUF_MAX; // num chars in console_buf
  121. int start = 0; // offset onto console_wr to start sending out chars
  122. jsonHeader(connData, 200);
  123. // figure out where to start in buffer based on URI param
  124. len = httpdFindArg(connData->getArgs, "start", buff, sizeof(buff));
  125. if (len > 0) {
  126. start = atoi(buff);
  127. if (start < console_pos) {
  128. start = 0;
  129. } else if (start >= console_pos+console_len) {
  130. start = console_len;
  131. } else {
  132. start = start - console_pos;
  133. }
  134. }
  135. // start outputting
  136. len = os_sprintf(buff, "{\"len\":%d, \"start\":%d, \"text\": \"",
  137. console_len-start, console_pos+start);
  138. int rd = (console_rd+start) % BUF_MAX;
  139. while (len < 2040 && rd != console_wr) {
  140. uint8_t c = console_buf[rd];
  141. if (c == '\\' || c == '"') {
  142. buff[len++] = '\\';
  143. buff[len++] = c;
  144. } else if (c == '\r') {
  145. // this is crummy, but browsers display a newline for \r\n sequences
  146. } else if (c < ' ') {
  147. len += os_sprintf(buff+len, "\\u%04x", c);
  148. } else {
  149. buff[len++] = c;
  150. }
  151. rd = (rd + 1) % BUF_MAX;
  152. }
  153. os_strcpy(buff+len, "\"}"); len+=2;
  154. httpdSend(connData, buff, len);
  155. return HTTPD_CGI_DONE;
  156. }
  157. void ICACHE_FLASH_ATTR consoleInit() {
  158. console_wr = 0;
  159. console_rd = 0;
  160. }