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.

MarlinSerial.h 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. /**
  2. * Marlin 3D Printer Firmware
  3. * Copyright (c) 2020 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. #pragma once
  23. /**
  24. * MarlinSerial.h - Hardware serial library for Wiring
  25. * Copyright (c) 2006 Nicholas Zambetti. All right reserved.
  26. *
  27. * Modified 28 September 2010 by Mark Sproul
  28. * Modified 14 February 2016 by Andreas Hardtung (added tx buffer)
  29. * Modified 01 October 2017 by Eduardo José Tagle (added XON/XOFF)
  30. * Templatized 01 October 2018 by Eduardo José Tagle to allow multiple instances
  31. */
  32. #include <WString.h>
  33. #include "../../inc/MarlinConfigPre.h"
  34. #include "../../core/serial_hook.h"
  35. #ifndef SERIAL_PORT
  36. #define SERIAL_PORT 0
  37. #endif
  38. #ifndef USBCON
  39. // The presence of the UBRRH register is used to detect a UART.
  40. #define UART_PRESENT(port) ((port == 0 && (defined(UBRRH) || defined(UBRR0H))) || \
  41. (port == 1 && defined(UBRR1H)) || (port == 2 && defined(UBRR2H)) || \
  42. (port == 3 && defined(UBRR3H)))
  43. // These are macros to build serial port register names for the selected SERIAL_PORT (C preprocessor
  44. // requires two levels of indirection to expand macro values properly)
  45. #define SERIAL_REGNAME(registerbase,number,suffix) _SERIAL_REGNAME(registerbase,number,suffix)
  46. #if SERIAL_PORT == 0 && (!defined(UBRR0H) || !defined(UDR0)) // use un-numbered registers if necessary
  47. #define _SERIAL_REGNAME(registerbase,number,suffix) registerbase##suffix
  48. #else
  49. #define _SERIAL_REGNAME(registerbase,number,suffix) registerbase##number##suffix
  50. #endif
  51. // Registers used by MarlinSerial class (expanded depending on selected serial port)
  52. // Templated 8bit register (generic)
  53. #define UART_REGISTER_DECL_BASE(registerbase, suffix) \
  54. template<int portNr> struct R_##registerbase##x##suffix {}
  55. // Templated 8bit register (specialization for each port)
  56. #define UART_REGISTER_DECL(port, registerbase, suffix) \
  57. template<> struct R_##registerbase##x##suffix<port> { \
  58. constexpr R_##registerbase##x##suffix(int) {} \
  59. FORCE_INLINE void operator=(uint8_t newVal) const { SERIAL_REGNAME(registerbase,port,suffix) = newVal; } \
  60. FORCE_INLINE operator uint8_t() const { return SERIAL_REGNAME(registerbase,port,suffix); } \
  61. }
  62. // Templated 1bit register (generic)
  63. #define UART_BIT_DECL_BASE(registerbase, suffix, bit) \
  64. template<int portNr>struct B_##bit##x {}
  65. // Templated 1bit register (specialization for each port)
  66. #define UART_BIT_DECL(port, registerbase, suffix, bit) \
  67. template<> struct B_##bit##x<port> { \
  68. constexpr B_##bit##x(int) {} \
  69. FORCE_INLINE void operator=(int newVal) const { \
  70. if (newVal) \
  71. SBI(SERIAL_REGNAME(registerbase,port,suffix),SERIAL_REGNAME(bit,port,)); \
  72. else \
  73. CBI(SERIAL_REGNAME(registerbase,port,suffix),SERIAL_REGNAME(bit,port,)); \
  74. } \
  75. FORCE_INLINE operator bool() const { return TEST(SERIAL_REGNAME(registerbase,port,suffix),SERIAL_REGNAME(bit,port,)); } \
  76. }
  77. #define UART_DECL_BASE() \
  78. UART_REGISTER_DECL_BASE(UCSR,A);\
  79. UART_REGISTER_DECL_BASE(UDR,);\
  80. UART_REGISTER_DECL_BASE(UBRR,H);\
  81. UART_REGISTER_DECL_BASE(UBRR,L);\
  82. UART_BIT_DECL_BASE(UCSR,B,RXEN);\
  83. UART_BIT_DECL_BASE(UCSR,B,TXEN);\
  84. UART_BIT_DECL_BASE(UCSR,A,TXC);\
  85. UART_BIT_DECL_BASE(UCSR,B,RXCIE);\
  86. UART_BIT_DECL_BASE(UCSR,A,UDRE);\
  87. UART_BIT_DECL_BASE(UCSR,A,FE);\
  88. UART_BIT_DECL_BASE(UCSR,A,DOR);\
  89. UART_BIT_DECL_BASE(UCSR,B,UDRIE);\
  90. UART_BIT_DECL_BASE(UCSR,A,RXC);\
  91. UART_BIT_DECL_BASE(UCSR,A,U2X)
  92. #define UART_DECL(port) \
  93. UART_REGISTER_DECL(port,UCSR,A);\
  94. UART_REGISTER_DECL(port,UDR,);\
  95. UART_REGISTER_DECL(port,UBRR,H);\
  96. UART_REGISTER_DECL(port,UBRR,L);\
  97. UART_BIT_DECL(port,UCSR,B,RXEN);\
  98. UART_BIT_DECL(port,UCSR,B,TXEN);\
  99. UART_BIT_DECL(port,UCSR,A,TXC);\
  100. UART_BIT_DECL(port,UCSR,B,RXCIE);\
  101. UART_BIT_DECL(port,UCSR,A,UDRE);\
  102. UART_BIT_DECL(port,UCSR,A,FE);\
  103. UART_BIT_DECL(port,UCSR,A,DOR);\
  104. UART_BIT_DECL(port,UCSR,B,UDRIE);\
  105. UART_BIT_DECL(port,UCSR,A,RXC);\
  106. UART_BIT_DECL(port,UCSR,A,U2X)
  107. // Declare empty templates
  108. UART_DECL_BASE();
  109. // And all the specializations for each possible serial port
  110. #if UART_PRESENT(0)
  111. UART_DECL(0);
  112. #endif
  113. #if UART_PRESENT(1)
  114. UART_DECL(1);
  115. #endif
  116. #if UART_PRESENT(2)
  117. UART_DECL(2);
  118. #endif
  119. #if UART_PRESENT(3)
  120. UART_DECL(3);
  121. #endif
  122. #define BYTE 0
  123. // Templated type selector
  124. template<bool b, typename T, typename F> struct TypeSelector { typedef T type;} ;
  125. template<typename T, typename F> struct TypeSelector<false, T, F> { typedef F type; };
  126. template<typename Cfg>
  127. class MarlinSerial {
  128. protected:
  129. // Registers
  130. static constexpr R_UCSRxA<Cfg::PORT> R_UCSRA = 0;
  131. static constexpr R_UDRx<Cfg::PORT> R_UDR = 0;
  132. static constexpr R_UBRRxH<Cfg::PORT> R_UBRRH = 0;
  133. static constexpr R_UBRRxL<Cfg::PORT> R_UBRRL = 0;
  134. // Bits
  135. static constexpr B_RXENx<Cfg::PORT> B_RXEN = 0;
  136. static constexpr B_TXENx<Cfg::PORT> B_TXEN = 0;
  137. static constexpr B_TXCx<Cfg::PORT> B_TXC = 0;
  138. static constexpr B_RXCIEx<Cfg::PORT> B_RXCIE = 0;
  139. static constexpr B_UDREx<Cfg::PORT> B_UDRE = 0;
  140. static constexpr B_FEx<Cfg::PORT> B_FE = 0;
  141. static constexpr B_DORx<Cfg::PORT> B_DOR = 0;
  142. static constexpr B_UDRIEx<Cfg::PORT> B_UDRIE = 0;
  143. static constexpr B_RXCx<Cfg::PORT> B_RXC = 0;
  144. static constexpr B_U2Xx<Cfg::PORT> B_U2X = 0;
  145. // Base size of type on buffer size
  146. typedef typename TypeSelector<(Cfg::RX_SIZE>256), uint16_t, uint8_t>::type ring_buffer_pos_t;
  147. struct ring_buffer_r {
  148. volatile ring_buffer_pos_t head, tail;
  149. unsigned char buffer[Cfg::RX_SIZE];
  150. };
  151. struct ring_buffer_t {
  152. volatile uint8_t head, tail;
  153. unsigned char buffer[Cfg::TX_SIZE];
  154. };
  155. static ring_buffer_r rx_buffer;
  156. static ring_buffer_t tx_buffer;
  157. static bool _written;
  158. static constexpr uint8_t XON_XOFF_CHAR_SENT = 0x80, // XON / XOFF Character was sent
  159. XON_XOFF_CHAR_MASK = 0x1F; // XON / XOFF character to send
  160. // XON / XOFF character definitions
  161. static constexpr uint8_t XON_CHAR = 17, XOFF_CHAR = 19;
  162. static uint8_t xon_xoff_state,
  163. rx_dropped_bytes,
  164. rx_buffer_overruns,
  165. rx_framing_errors;
  166. static ring_buffer_pos_t rx_max_enqueued;
  167. FORCE_INLINE static ring_buffer_pos_t atomic_read_rx_head();
  168. static volatile bool rx_tail_value_not_stable;
  169. static volatile uint16_t rx_tail_value_backup;
  170. FORCE_INLINE static void atomic_set_rx_tail(ring_buffer_pos_t value);
  171. FORCE_INLINE static ring_buffer_pos_t atomic_read_rx_tail();
  172. public:
  173. FORCE_INLINE static void store_rxd_char();
  174. FORCE_INLINE static void _tx_udr_empty_irq();
  175. public:
  176. static void begin(const long);
  177. static void end();
  178. static int peek();
  179. static int read();
  180. static void flush();
  181. static ring_buffer_pos_t available();
  182. static void write(const uint8_t c);
  183. static void flushTX();
  184. #if HAS_DGUS_LCD
  185. static ring_buffer_pos_t get_tx_buffer_free();
  186. #endif
  187. enum { HasEmergencyParser = Cfg::EMERGENCYPARSER };
  188. static bool emergency_parser_enabled() { return Cfg::EMERGENCYPARSER; }
  189. FORCE_INLINE static uint8_t dropped() { return Cfg::DROPPED_RX ? rx_dropped_bytes : 0; }
  190. FORCE_INLINE static uint8_t buffer_overruns() { return Cfg::RX_OVERRUNS ? rx_buffer_overruns : 0; }
  191. FORCE_INLINE static uint8_t framing_errors() { return Cfg::RX_FRAMING_ERRORS ? rx_framing_errors : 0; }
  192. FORCE_INLINE static ring_buffer_pos_t rxMaxEnqueued() { return Cfg::MAX_RX_QUEUED ? rx_max_enqueued : 0; }
  193. };
  194. template <uint8_t serial>
  195. struct MarlinSerialCfg {
  196. static constexpr int PORT = serial;
  197. static constexpr unsigned int RX_SIZE = RX_BUFFER_SIZE;
  198. static constexpr unsigned int TX_SIZE = TX_BUFFER_SIZE;
  199. static constexpr bool XONOFF = ENABLED(SERIAL_XON_XOFF);
  200. static constexpr bool EMERGENCYPARSER = ENABLED(EMERGENCY_PARSER);
  201. static constexpr bool DROPPED_RX = ENABLED(SERIAL_STATS_DROPPED_RX);
  202. static constexpr bool RX_OVERRUNS = ENABLED(SERIAL_STATS_RX_BUFFER_OVERRUNS);
  203. static constexpr bool RX_FRAMING_ERRORS = ENABLED(SERIAL_STATS_RX_FRAMING_ERRORS);
  204. static constexpr bool MAX_RX_QUEUED = ENABLED(SERIAL_STATS_MAX_RX_QUEUED);
  205. };
  206. typedef Serial1Class< MarlinSerial< MarlinSerialCfg<SERIAL_PORT> > > MSerialT1;
  207. extern MSerialT1 customizedSerial1;
  208. #ifdef SERIAL_PORT_2
  209. typedef Serial1Class< MarlinSerial< MarlinSerialCfg<SERIAL_PORT_2> > > MSerialT2;
  210. extern MSerialT2 customizedSerial2;
  211. #endif
  212. #ifdef SERIAL_PORT_3
  213. typedef Serial1Class< MarlinSerial< MarlinSerialCfg<SERIAL_PORT_3> > > MSerialT3;
  214. extern MSerialT3 customizedSerial3;
  215. #endif
  216. #endif // !USBCON
  217. #ifdef MMU2_SERIAL_PORT
  218. template <uint8_t serial>
  219. struct MMU2SerialCfg {
  220. static constexpr int PORT = serial;
  221. static constexpr unsigned int RX_SIZE = 32;
  222. static constexpr unsigned int TX_SIZE = 32;
  223. static constexpr bool XONOFF = false;
  224. static constexpr bool EMERGENCYPARSER = false;
  225. static constexpr bool DROPPED_RX = false;
  226. static constexpr bool RX_FRAMING_ERRORS = false;
  227. static constexpr bool MAX_RX_QUEUED = false;
  228. static constexpr bool RX_OVERRUNS = false;
  229. };
  230. typedef Serial1Class< MarlinSerial< MMU2SerialCfg<MMU2_SERIAL_PORT> > > MSerialMMU2;
  231. extern MSerialMMU2 mmuSerial;
  232. #endif
  233. #ifdef LCD_SERIAL_PORT
  234. template <uint8_t serial>
  235. struct LCDSerialCfg {
  236. static constexpr int PORT = serial;
  237. static constexpr unsigned int RX_SIZE = TERN(HAS_DGUS_LCD, DGUS_RX_BUFFER_SIZE, 64);
  238. static constexpr unsigned int TX_SIZE = TERN(HAS_DGUS_LCD, DGUS_TX_BUFFER_SIZE, 128);
  239. static constexpr bool XONOFF = false;
  240. static constexpr bool EMERGENCYPARSER = ENABLED(EMERGENCY_PARSER);
  241. static constexpr bool DROPPED_RX = false;
  242. static constexpr bool RX_FRAMING_ERRORS = false;
  243. static constexpr bool MAX_RX_QUEUED = false;
  244. static constexpr bool RX_OVERRUNS = BOTH(HAS_DGUS_LCD, SERIAL_STATS_RX_BUFFER_OVERRUNS);
  245. };
  246. typedef Serial1Class< MarlinSerial< LCDSerialCfg<LCD_SERIAL_PORT> > > MSerialLCD;
  247. extern MSerialLCD lcdSerial;
  248. #endif
  249. // Use the UART for Bluetooth in AT90USB configurations
  250. #if defined(USBCON) && ENABLED(BLUETOOTH)
  251. typedef Serial1Class<HardwareSerial> MSerialBT;
  252. extern MSerialBT bluetoothSerial;
  253. #endif