My Marlin configs for Fabrikator Mini and CTC i3 Pro B
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.

wifiSerial_STM32.cpp 9.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. /**
  2. * Marlin 3D Printer Firmware
  3. * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
  4. *
  5. * Based on Sprinter and grbl.
  6. * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
  7. *
  8. * This program is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation, either version 3 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  20. *
  21. */
  22. #include "../../../HAL/platforms.h"
  23. #ifdef HAL_STM32
  24. #include "../../../inc/MarlinConfigPre.h"
  25. #if BOTH(HAS_TFT_LVGL_UI, MKS_WIFI_MODULE)
  26. #include "tft_lvgl_configuration.h"
  27. #include "draw_ui.h"
  28. #include "wifiSerial.h"
  29. WifiSerial WifiSerial1(USART1);
  30. void WifiSerial::setRx(uint32_t _rx) { _serial.pin_rx = digitalPinToPinName(_rx); }
  31. void WifiSerial::setTx(uint32_t _tx) { _serial.pin_tx = digitalPinToPinName(_tx); }
  32. void WifiSerial::setRx(PinName _rx) { _serial.pin_rx = _rx; }
  33. void WifiSerial::setTx(PinName _tx) { _serial.pin_tx = _tx; }
  34. void WifiSerial::init(PinName _rx, PinName _tx) {
  35. _serial.pin_rx = (_rx == _tx) ? NC : _rx;
  36. _serial.pin_tx = _tx;
  37. _serial.rx_buff = wifiRxBuf;
  38. _serial.rx_head = 0;
  39. _serial.rx_tail = 0;
  40. _serial.tx_buff = wifiTxBuf;
  41. _serial.tx_head = 0;
  42. _serial.tx_tail = 0;
  43. }
  44. WifiSerial::WifiSerial(void *peripheral) {
  45. // If PIN_SERIALy_RX is not defined assume half-duplex
  46. _serial.pin_rx = NC;
  47. if (false) {
  48. // for else if / else below...
  49. }
  50. // If Serial is defined in variant set
  51. // the Rx/Tx pins for com port if defined
  52. #if defined(Serial) && defined(PIN_SERIAL_TX)
  53. else if ((void *)this == (void *)&Serial) {
  54. #ifdef PIN_SERIAL_RX
  55. setRx(PIN_SERIAL_RX);
  56. #endif
  57. setTx(PIN_SERIAL_TX);
  58. }
  59. #endif
  60. #if defined(PIN_SERIAL1_TX) && defined(USART1_BASE)
  61. else if (peripheral == USART1) {
  62. #ifdef PIN_SERIAL1_RX
  63. setRx(PIN_SERIAL1_RX);
  64. #endif
  65. setTx(PIN_SERIAL1_TX);
  66. }
  67. #endif
  68. #if defined(PIN_SERIAL2_TX) && defined(USART2_BASE)
  69. else if (peripheral == USART2) {
  70. #ifdef PIN_SERIAL2_RX
  71. setRx(PIN_SERIAL2_RX);
  72. #endif
  73. setTx(PIN_SERIAL2_TX);
  74. }
  75. #endif
  76. #if defined(PIN_SERIAL3_TX) && defined(USART3_BASE)
  77. else if (peripheral == USART3) {
  78. #ifdef PIN_SERIAL3_RX
  79. setRx(PIN_SERIAL3_RX);
  80. #endif
  81. setTx(PIN_SERIAL3_TX);
  82. }
  83. #endif
  84. #ifdef PIN_SERIAL4_TX
  85. else if (false
  86. #ifdef USART4_BASE
  87. || peripheral == USART4
  88. #elif defined(UART4_BASE)
  89. || peripheral == UART4
  90. #endif
  91. ) {
  92. #ifdef PIN_SERIAL4_RX
  93. setRx(PIN_SERIAL4_RX);
  94. #endif
  95. setTx(PIN_SERIAL4_TX);
  96. }
  97. #endif
  98. #ifdef PIN_SERIAL5_TX
  99. else if (false
  100. #ifdef USART5_BASE
  101. || peripheral == USART5
  102. #elif defined(UART5_BASE)
  103. || peripheral == UART5
  104. #endif
  105. ) {
  106. #ifdef PIN_SERIAL5_RX
  107. setRx(PIN_SERIAL5_RX);
  108. #endif
  109. setTx(PIN_SERIAL5_TX);
  110. }
  111. #endif
  112. #if defined(PIN_SERIAL6_TX) && defined(USART6_BASE)
  113. else if (peripheral == USART6) {
  114. #ifdef PIN_SERIAL6_RX
  115. setRx(PIN_SERIAL6_RX);
  116. #endif
  117. setTx(PIN_SERIAL6_TX);
  118. }
  119. #endif
  120. #ifdef PIN_SERIAL7_TX
  121. else if (false
  122. #ifdef USART7_BASE
  123. || peripheral == USART7
  124. #elif defined(UART7_BASE)
  125. || peripheral == UART7
  126. #endif
  127. ) {
  128. #ifdef PIN_SERIAL7_RX
  129. setRx(PIN_SERIAL7_RX);
  130. #endif
  131. setTx(PIN_SERIAL7_TX);
  132. }
  133. #endif
  134. #ifdef PIN_SERIAL8_TX
  135. else if (false
  136. #ifdef USART8_BASE
  137. || peripheral == USART8
  138. #elif defined(UART8_BASE)
  139. || peripheral == UART8
  140. #endif
  141. ) {
  142. #ifdef PIN_SERIAL8_RX
  143. setRx(PIN_SERIAL8_RX);
  144. #endif
  145. setTx(PIN_SERIAL8_TX);
  146. }
  147. #endif
  148. #if defined(PIN_SERIAL9_TX) && defined(UART9_BASE)
  149. else if (peripheral == UART9) {
  150. #ifdef PIN_SERIAL9_RX
  151. setRx(PIN_SERIAL9_RX);
  152. #endif
  153. setTx(PIN_SERIAL9_TX);
  154. }
  155. #endif
  156. #ifdef PIN_SERIAL10_TX
  157. else if (false
  158. #ifdef USART10_BASE
  159. || peripheral == USART10
  160. #elif defined(UART10_BASE)
  161. || peripheral == UART10
  162. #endif
  163. ) {
  164. #ifdef PIN_SERIAL10_RX
  165. setRx(PIN_SERIAL10_RX);
  166. #endif
  167. setTx(PIN_SERIAL10_TX);
  168. }
  169. #endif
  170. #if defined(PIN_SERIALLP1_TX) && defined(LPUART1_BASE)
  171. else if (peripheral == LPUART1) {
  172. #ifdef PIN_SERIALLP1_RX
  173. setRx(PIN_SERIALLP1_RX);
  174. #endif
  175. setTx(PIN_SERIALLP1_TX);
  176. }
  177. #endif
  178. // else get the pins of the first peripheral occurrence in PinMap
  179. else {
  180. _serial.pin_rx = pinmap_pin(peripheral, PinMap_UART_RX);
  181. _serial.pin_tx = pinmap_pin(peripheral, PinMap_UART_TX);
  182. }
  183. //if (halfDuplex == HALF_DUPLEX_ENABLED) _serial.pin_rx = NC;
  184. init(_serial.pin_rx, _serial.pin_tx);
  185. }
  186. void WifiSerial::flush() {
  187. // If we have never written a byte, no need to flush. This special
  188. // case is needed since there is no way to force the TXC (transmit
  189. // complete) bit to 1 during initialization
  190. if (!_written) return;
  191. while ((_serial.tx_head != _serial.tx_tail)) {
  192. // nop, the interrupt handler will free up space for us
  193. }
  194. // If we get here, nothing is queued anymore (DRIE is disabled) and
  195. // the hardware finished transmission (TXC is set).
  196. }
  197. bool WifiSerial::isHalfDuplex() const { return _serial.pin_rx == NC; }
  198. void WifiSerial::enableHalfDuplexRx() {
  199. if (isHalfDuplex()) {
  200. // In half-duplex mode we have to wait for all TX characters to
  201. // be transmitted before we can receive data.
  202. flush();
  203. if (!_rx_enabled) {
  204. _rx_enabled = true;
  205. uart_enable_rx(&_serial);
  206. }
  207. }
  208. }
  209. // Actual interrupt handlers //////////////////////////////////////////////////////////////
  210. void WifiSerial::_rx_complete_irq(serial_t *obj) {
  211. // No Parity error, read byte and store it in the buffer if there is room
  212. unsigned char c;
  213. if (uart_getc(obj, &c) == 0) {
  214. WRITE(WIFI_IO1_PIN, HIGH);
  215. rx_buffer_index_t i = (unsigned int)(obj->rx_head + 1) % WIFI_RX_BUF_SIZE;
  216. // if we should be storing the received character into the location
  217. // just before the tail (meaning that the head would advance to the
  218. // current location of the tail), we're about to overflow the buffer
  219. // and so we don't write the character or advance the head.
  220. if (i != obj->rx_tail) {
  221. obj->rx_buff[obj->rx_head] = c;
  222. obj->rx_head = i;
  223. }
  224. }
  225. }
  226. // Actual interrupt handlers //////////////////////////////////////////////////////////////
  227. int WifiSerial::_tx_complete_irq(serial_t *obj) {
  228. // If interrupts are enabled, there must be more data in the output
  229. // buffer. Send the next byte
  230. obj->tx_tail = (obj->tx_tail + 1) % WIFI_TX_BUF_SIZE;
  231. return (obj->tx_head == obj->tx_tail) ? -1 : 0;
  232. }
  233. void WifiSerial::begin(unsigned long baud) { begin(baud, SERIAL_8N1); }
  234. void WifiSerial::begin(unsigned long baud, byte config) {
  235. uint32_t databits = 0, stopbits = 0, parity = 0;
  236. _baud = baud;
  237. _config = config;
  238. // Manage databits
  239. switch (config & 0x07) {
  240. case 0x02: databits = 6; break;
  241. case 0x04: databits = 7; break;
  242. case 0x06: databits = 8; break;
  243. default: databits = 0; break;
  244. }
  245. if ((config & 0x30) == 0x30) {
  246. parity = UART_PARITY_ODD;
  247. databits++;
  248. }
  249. else if ((config & 0x20) == 0x20) {
  250. parity = UART_PARITY_EVEN;
  251. databits++;
  252. }
  253. else
  254. parity = UART_PARITY_NONE;
  255. stopbits = ((config & 0x08) == 0x08) ? UART_STOPBITS_2 : UART_STOPBITS_1;
  256. switch (databits) {
  257. #ifdef UART_WORDLENGTH_7B
  258. case 7: databits = UART_WORDLENGTH_7B; break;
  259. #endif
  260. case 8: databits = UART_WORDLENGTH_8B; break;
  261. case 9: databits = UART_WORDLENGTH_9B; break;
  262. default:
  263. case 0: Error_Handler(); break;
  264. }
  265. uart_init(&_serial, (uint32_t)baud, databits, parity, stopbits);
  266. enableHalfDuplexRx();
  267. if (baud == WIFI_BAUDRATE)
  268. uart_attach_rx_callback(&_serial, _rx_complete_irq);
  269. else
  270. USART1->CR1 |= USART_CR1_RE; // Preserve word length, etc. Use 'or' to preserve USART_CR1_M_8N1
  271. }
  272. void WifiSerial::end() {
  273. // wait for transmission of outgoing data
  274. flush();
  275. uart_deinit(&_serial);
  276. // clear any received data
  277. _serial.rx_head = _serial.rx_tail;
  278. }
  279. int WifiSerial::available() {
  280. return ((unsigned int)(WIFI_RX_BUF_SIZE + _serial.rx_head - _serial.rx_tail)) % WIFI_RX_BUF_SIZE;
  281. }
  282. //
  283. // I/O
  284. //
  285. int WifiSerial::read() {
  286. enableHalfDuplexRx();
  287. // if the head isn't ahead of the tail, we don't have any characters
  288. if (_serial.rx_head == _serial.rx_tail) return -1;
  289. unsigned char c = _serial.rx_buff[_serial.rx_tail];
  290. _serial.rx_tail = (rx_buffer_index_t)(_serial.rx_tail + 1) % WIFI_RX_BUF_SIZE;
  291. return c;
  292. }
  293. int WifiSerial::write(uint8_t c) {
  294. _written = true;
  295. if (isHalfDuplex()) {
  296. if (_rx_enabled) {
  297. _rx_enabled = false;
  298. uart_enable_tx(&_serial);
  299. }
  300. }
  301. tx_buffer_index_t i = (_serial.tx_head + 1) % WIFI_TX_BUF_SIZE;
  302. // If the output buffer is full, there's nothing for it other than to
  303. // wait for the interrupt handler to empty it a bit
  304. while (i == _serial.tx_tail) {
  305. // nop, the interrupt handler will free up space for us
  306. }
  307. _serial.tx_buff[_serial.tx_head] = c;
  308. _serial.tx_head = i;
  309. if (!serial_tx_active(&_serial))
  310. uart_attach_tx_callback(&_serial, _tx_complete_irq);
  311. return 1;
  312. }
  313. #endif // HAS_TFT_LVGL_UI && MKS_WIFI_MODULE
  314. #endif // HAL_STM32