[2.0.x] Emergency parser for multiple serial ports (#10524)
This commit is contained in:
		| @@ -85,6 +85,10 @@ | ||||
|  | ||||
|   FORCE_INLINE void store_rxd_char() { | ||||
|  | ||||
|     #if ENABLED(EMERGENCY_PARSER) | ||||
|       static EmergencyParser::State emergency_state; // = EP_RESET | ||||
|     #endif | ||||
|  | ||||
|     const ring_buffer_pos_t h = rx_buffer.head, | ||||
|                             i = (ring_buffer_pos_t)(h + 1) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1); | ||||
|  | ||||
| @@ -160,7 +164,7 @@ | ||||
|     #endif // SERIAL_XON_XOFF | ||||
|  | ||||
|     #if ENABLED(EMERGENCY_PARSER) | ||||
|       emergency_parser.update(c); | ||||
|       emergency_parser.update(emergency_state, c); | ||||
|     #endif | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -112,6 +112,10 @@ | ||||
|  | ||||
|   FORCE_INLINE void store_rxd_char() { | ||||
|  | ||||
|     #if ENABLED(EMERGENCY_PARSER) | ||||
|       static EmergencyParser::State emergency_state; // = EP_RESET | ||||
|     #endif | ||||
|  | ||||
|     const ring_buffer_pos_t h = rx_buffer.head, | ||||
|                             i = (ring_buffer_pos_t)(h + 1) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1); | ||||
|  | ||||
| @@ -182,7 +186,7 @@ | ||||
|     #endif // SERIAL_XON_XOFF | ||||
|  | ||||
|     #if ENABLED(EMERGENCY_PARSER) | ||||
|       emergency_parser.update(c); | ||||
|       emergency_parser.update(emergency_state, c); | ||||
|     #endif | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -24,12 +24,6 @@ | ||||
|  | ||||
| #include "HardwareSerial.h" | ||||
|  | ||||
| #include "../../inc/MarlinConfigPre.h" | ||||
|  | ||||
| #if ENABLED(EMERGENCY_PARSER) | ||||
|   #include "../../feature/emergency_parser.h" | ||||
| #endif | ||||
|  | ||||
| #if SERIAL_PORT == 0 || SERIAL_PORT_2 == 0 | ||||
|   HardwareSerial Serial = HardwareSerial(LPC_UART0); | ||||
| #elif SERIAL_PORT == 1 || SERIAL_PORT_2 == 1 | ||||
| @@ -254,7 +248,7 @@ void HardwareSerial::IRQHandler() { | ||||
|     // Clear the FIFO | ||||
|     while (UART_Receive(UARTx, &byte, 1, NONE_BLOCKING)) { | ||||
|       #if ENABLED(EMERGENCY_PARSER) | ||||
|         emergency_parser.update(byte); | ||||
|         emergency_parser.update(emergency_state, byte); | ||||
|       #endif | ||||
|       if ((RxQueueWritePos + 1) % RX_BUFFER_SIZE != RxQueueReadPos) { | ||||
|         RxBuffer[RxQueueWritePos] = byte; | ||||
|   | ||||
| @@ -23,6 +23,11 @@ | ||||
| #ifndef HARDWARE_SERIAL_H_ | ||||
| #define HARDWARE_SERIAL_H_ | ||||
|  | ||||
| #include "../../inc/MarlinConfigPre.h" | ||||
| #if ENABLED(EMERGENCY_PARSER) | ||||
|   #include "../../feature/emergency_parser.h" | ||||
| #endif | ||||
|  | ||||
| #include <stdarg.h> | ||||
| #include <stdio.h> | ||||
| #include <Stream.h> | ||||
| @@ -32,8 +37,6 @@ extern "C" { | ||||
|   #include "lpc17xx_pinsel.h" | ||||
| } | ||||
|  | ||||
| #include "../../inc/MarlinConfigPre.h" | ||||
|  | ||||
| class HardwareSerial : public Stream { | ||||
| private: | ||||
|   LPC_UART_TypeDef *UARTx; | ||||
| @@ -48,6 +51,9 @@ private: | ||||
|     uint32_t TxQueueWritePos; | ||||
|     uint32_t TxQueueReadPos; | ||||
|   #endif | ||||
|   #if ENABLED(EMERGENCY_PARSER) | ||||
|     EmergencyParser::State emergency_state; | ||||
|   #endif | ||||
|  | ||||
| public: | ||||
|   HardwareSerial(LPC_UART_TypeDef *UARTx) | ||||
| @@ -59,6 +65,9 @@ public: | ||||
|       , TxQueueWritePos(0) | ||||
|       , TxQueueReadPos(0) | ||||
|     #endif | ||||
|     #if ENABLED(EMERGENCY_PARSER) | ||||
|       , emergency_state(EmergencyParser::State::EP_RESET) | ||||
|     #endif | ||||
|   { | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -23,6 +23,11 @@ | ||||
| #ifndef _HAL_SERIAL_H_ | ||||
| #define _HAL_SERIAL_H_ | ||||
|  | ||||
| #include "../../../inc/MarlinConfigPre.h" | ||||
| #if ENABLED(EMERGENCY_PARSER) | ||||
|   #include "../../../feature/emergency_parser.h" | ||||
| #endif | ||||
|  | ||||
| #include <stdarg.h> | ||||
| #include <stdio.h> | ||||
|  | ||||
| @@ -73,6 +78,11 @@ private: | ||||
|  | ||||
| class HalSerial { | ||||
| public: | ||||
|  | ||||
|   #if ENABLED(EMERGENCY_PARSER) | ||||
|     EmergencyParser::State emergency_state; | ||||
|   #endif | ||||
|  | ||||
|   HalSerial() { host_connected = false; } | ||||
|  | ||||
|   void begin(int32_t baud) { | ||||
|   | ||||
| @@ -30,92 +30,10 @@ | ||||
|  | ||||
| #include "emergency_parser.h" | ||||
|  | ||||
| extern volatile bool wait_for_user, wait_for_heatup; | ||||
| void quickstop_stepper(); | ||||
|  | ||||
| EmergencyParser::State EmergencyParser::state = EP_RESET; | ||||
| // Static data members | ||||
| bool EmergencyParser::killed_by_M112; // = false | ||||
|  | ||||
| // Global instance | ||||
| EmergencyParser emergency_parser; | ||||
|  | ||||
| void EmergencyParser::update(const uint8_t c) { | ||||
|  | ||||
|   switch (state) { | ||||
|     case EP_RESET: | ||||
|       switch (c) { | ||||
|         case ' ': break; | ||||
|         case 'N': state = EP_N;      break; | ||||
|         case 'M': state = EP_M;      break; | ||||
|         default: state  = EP_IGNORE; | ||||
|       } | ||||
|       break; | ||||
|  | ||||
|     case EP_N: | ||||
|       switch (c) { | ||||
|         case '0': case '1': case '2': | ||||
|         case '3': case '4': case '5': | ||||
|         case '6': case '7': case '8': | ||||
|         case '9': case '-': case ' ':   break; | ||||
|         case 'M': state = EP_M;      break; | ||||
|         default:  state = EP_IGNORE; | ||||
|       } | ||||
|       break; | ||||
|  | ||||
|     case EP_M: | ||||
|       switch (c) { | ||||
|         case ' ': break; | ||||
|         case '1': state = EP_M1;     break; | ||||
|         case '4': state = EP_M4;     break; | ||||
|         default: state  = EP_IGNORE; | ||||
|       } | ||||
|       break; | ||||
|  | ||||
|     case EP_M1: | ||||
|       switch (c) { | ||||
|         case '0': state = EP_M10;    break; | ||||
|         case '1': state = EP_M11;    break; | ||||
|         default: state  = EP_IGNORE; | ||||
|       } | ||||
|       break; | ||||
|  | ||||
|     case EP_M10: | ||||
|       state = (c == '8') ? EP_M108 : EP_IGNORE; | ||||
|       break; | ||||
|  | ||||
|     case EP_M11: | ||||
|       state = (c == '2') ? EP_M112 : EP_IGNORE; | ||||
|       break; | ||||
|  | ||||
|     case EP_M4: | ||||
|       state = (c == '1') ? EP_M41 : EP_IGNORE; | ||||
|       break; | ||||
|  | ||||
|     case EP_M41: | ||||
|       state = (c == '0') ? EP_M410 : EP_IGNORE; | ||||
|       break; | ||||
|  | ||||
|     case EP_IGNORE: | ||||
|       if (c == '\n') state = EP_RESET; | ||||
|       break; | ||||
|  | ||||
|     default: | ||||
|       if (c == '\n') { | ||||
|         switch (state) { | ||||
|           case EP_M108: | ||||
|             wait_for_user = wait_for_heatup = false; | ||||
|             break; | ||||
|           case EP_M112: | ||||
|             killed_by_M112 = true; | ||||
|             break; | ||||
|           case EP_M410: | ||||
|             quickstop_stepper(); | ||||
|             break; | ||||
|           default: | ||||
|             break; | ||||
|         } | ||||
|         state = EP_RESET; | ||||
|       } | ||||
|   } | ||||
| } | ||||
|  | ||||
| #endif // EMERGENCY_PARSER | ||||
|   | ||||
| @@ -27,8 +27,14 @@ | ||||
| #ifndef _EMERGENCY_PARSER_H_ | ||||
| #define _EMERGENCY_PARSER_H_ | ||||
|  | ||||
| // External references | ||||
| extern volatile bool wait_for_user, wait_for_heatup; | ||||
| void quickstop_stepper(); | ||||
|  | ||||
| class EmergencyParser { | ||||
|  | ||||
| public: | ||||
|  | ||||
|   // Currently looking for: M108, M112, M410 | ||||
|   enum State : char { | ||||
|     EP_RESET, | ||||
| @@ -45,14 +51,90 @@ class EmergencyParser { | ||||
|     EP_IGNORE // to '\n' | ||||
|   }; | ||||
|  | ||||
| public: | ||||
|  | ||||
|   static EmergencyParser::State state; | ||||
|   static bool killed_by_M112; | ||||
|  | ||||
|   EmergencyParser() {} | ||||
|  | ||||
|   static void update(const uint8_t c); | ||||
|   __attribute__((always_inline)) inline | ||||
|   static void update(State &state, const uint8_t c) { | ||||
|  | ||||
|     switch (state) { | ||||
|       case EP_RESET: | ||||
|         switch (c) { | ||||
|           case ' ': break; | ||||
|           case 'N': state = EP_N;      break; | ||||
|           case 'M': state = EP_M;      break; | ||||
|           default: state  = EP_IGNORE; | ||||
|         } | ||||
|         break; | ||||
|  | ||||
|       case EP_N: | ||||
|         switch (c) { | ||||
|           case '0': case '1': case '2': | ||||
|           case '3': case '4': case '5': | ||||
|           case '6': case '7': case '8': | ||||
|           case '9': case '-': case ' ':   break; | ||||
|           case 'M': state = EP_M;      break; | ||||
|           default:  state = EP_IGNORE; | ||||
|         } | ||||
|         break; | ||||
|  | ||||
|       case EP_M: | ||||
|         switch (c) { | ||||
|           case ' ': break; | ||||
|           case '1': state = EP_M1;     break; | ||||
|           case '4': state = EP_M4;     break; | ||||
|           default: state  = EP_IGNORE; | ||||
|         } | ||||
|         break; | ||||
|  | ||||
|       case EP_M1: | ||||
|         switch (c) { | ||||
|           case '0': state = EP_M10;    break; | ||||
|           case '1': state = EP_M11;    break; | ||||
|           default: state  = EP_IGNORE; | ||||
|         } | ||||
|         break; | ||||
|  | ||||
|       case EP_M10: | ||||
|         state = (c == '8') ? EP_M108 : EP_IGNORE; | ||||
|         break; | ||||
|  | ||||
|       case EP_M11: | ||||
|         state = (c == '2') ? EP_M112 : EP_IGNORE; | ||||
|         break; | ||||
|  | ||||
|       case EP_M4: | ||||
|         state = (c == '1') ? EP_M41 : EP_IGNORE; | ||||
|         break; | ||||
|  | ||||
|       case EP_M41: | ||||
|         state = (c == '0') ? EP_M410 : EP_IGNORE; | ||||
|         break; | ||||
|  | ||||
|       case EP_IGNORE: | ||||
|         if (c == '\n') state = EP_RESET; | ||||
|         break; | ||||
|  | ||||
|       default: | ||||
|         if (c == '\n') { | ||||
|           switch (state) { | ||||
|             case EP_M108: | ||||
|               wait_for_user = wait_for_heatup = false; | ||||
|               break; | ||||
|             case EP_M112: | ||||
|               killed_by_M112 = true; | ||||
|               break; | ||||
|             case EP_M410: | ||||
|               quickstop_stepper(); | ||||
|               break; | ||||
|             default: | ||||
|               break; | ||||
|           } | ||||
|           state = EP_RESET; | ||||
|         } | ||||
|     } | ||||
|   } | ||||
|  | ||||
| }; | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user