diff --git a/README.md b/README.md index 286d69bc5b..6198040515 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,8 @@ This repository includes source code and firmware releases for the Original Prusa 3D printers based on the 32-bit ARM microcontrollers. The currently supported models are: -- Original Prusa MINI +- Original Prusa MINI/MINI+ +- Original Prusa MK3.9 - Original Prusa MK4 - Original Prusa XL @@ -59,15 +60,9 @@ The build process of this project is driven by CMake and `build.py` is just a hi - [Eclipse, STM32CubeIDE](doc/editor/stm32cubeide.md) - [Other LSP-based IDEs (Atom, Sublime Text, ...)](doc/editor/lsp-based-ides.md) -#### Formatting +#### Contributing -All the source code in this repository is automatically formatted: - -- C/C++ files using [clang-format](https://clang.llvm.org/docs/ClangFormat.html), -- Python files using [yapf](https://github.com/google/yapf), -- and CMake files using [cmake-format](https://github.com/cheshirekow/cmake_format). - -If you want to contribute, make sure to install [pre-commit](https://pre-commit.com) and then run `pre-commit install` within the repository. This makes sure that all your future commits will be formatted appropriately. Our build server automatically rejects improperly formatted pull requests. +If you want to contribute to the codebase, please read the [Contribution Guidelines](doc/contributing.md). #### XL and Puppies diff --git a/doc/contributing.md b/doc/contributing.md new file mode 100644 index 0000000000..56850ee770 --- /dev/null +++ b/doc/contributing.md @@ -0,0 +1,64 @@ +# Contribution Guidelines + +## Git + +### Merging: Use rebase whenever possible + +The goal is to have a simple and linear git history. +It is not always possible; for example when merging master into private. +In such cases, it is ok to use git-merge. + +### Commit: Atomicity + +A commit should be a single complete unit of work. +Every commit should be buildable and follow the rules in this document. + +### Commit: Message + +- Commit message comprises a subject and a body (separated by an empty line). +- Commit message is written in English. +- Subject uses the imperative mood. +- Subject starts with a capital letter and does not end with a period. +- When a commit is relevant to some subset/module of the project (most of the time), use it as a prefix of the subject as follows: + ``` + metrics: Add support for syslog + ``` + or + ``` + gui: Add touch support + ``` +- Write the module in lowercase +- Limit the subject to 72 letters. +- Wrap the body to 72 letters per line. +- Put an issue tracker reference (BFW-xxxx) at the end of the body if you have one. Do not put it in the subject line. + +## Formatting & Code Organization + +### Formatting + +All the source code in this repository is automatically formatted: + +- C/C++ files using [clang-format](https://clang.llvm.org/docs/ClangFormat.html), +- Python files using [yapf](https://github.com/google/yapf), +- and CMake files using [cmake-format](https://github.com/cheshirekow/cmake_format). + +If you want to contribute, make sure to install [pre-commit](https://pre-commit.com) and then run `pre-commit install` within the repository. This makes sure that all your future commits will be formatted appropriately. Our build server automatically rejects improperly formatted pull requests. + +### Files: Include Guards +Use the `#pragma once` as a file guard. +Do not use the `#ifdef FILE_X`, `#define FILE_X`, `#endif` pattern. + +### Files: Author & Copyright + +Do not add file headers with author/creation time/copyright, etc. +Those data are already stored in the commit, and we don't want to duplicate them. + +This does not apply to 3rd party code in our repository. + +### Code Style: C/C++ Naming Conventions + +- Types & Classes are in `PascalCase`. +- Global constants in `SCREAMING_CASE` +- Variables (local, class, etc), class-level constants, `enum class` items, methods and namespaces are in `snake_case`. +- File names are in `snake_case.cpp` (even if the only thing the file contains is a class named in `PascalCase`). +- Types never end with a `'_t'`. diff --git a/include/marlin/Configuration_MINI.h b/include/marlin/Configuration_MINI.h index 957b534e70..72c8bb729b 100644 --- a/include/marlin/Configuration_MINI.h +++ b/include/marlin/Configuration_MINI.h @@ -397,7 +397,7 @@ // Above this temperature the heater will be switched off. // This can protect components from overheating, but NOT from shorts and failures. // (Use MINTEMP for thermistor short/failure protection.) -#define HEATER_0_MAXTEMP 290 +#define HEATER_0_MAXTEMP 295 #define HEATER_1_MAXTEMP 275 #define HEATER_2_MAXTEMP 275 #define HEATER_3_MAXTEMP 275 diff --git a/lib/Marlin/Marlin/src/gcode/feature/input_shaper/M74.cpp b/lib/Marlin/Marlin/src/gcode/feature/input_shaper/M74.cpp index 47ed4b519d..2dc8a3bf7a 100644 --- a/lib/Marlin/Marlin/src/gcode/feature/input_shaper/M74.cpp +++ b/lib/Marlin/Marlin/src/gcode/feature/input_shaper/M74.cpp @@ -48,10 +48,10 @@ void GcodeSuite::M74() { if (parser.seen('W')) { const float m = parser.value_float(); - if (m > 0) { + if (m >= 0.f) { params.mass = m; } else { - SERIAL_ECHO_MSG("?Mass (W) must be greater than 0"); + SERIAL_ECHO_MSG("?Mass (W) must be greater or equal 0"); } } diff --git a/lib/WUI/link_content/basic_gets.cpp b/lib/WUI/link_content/basic_gets.cpp index 4049a1f1c3..b0870e7627 100644 --- a/lib/WUI/link_content/basic_gets.cpp +++ b/lib/WUI/link_content/basic_gets.cpp @@ -185,7 +185,7 @@ JsonResult get_printer(size_t resume_point, JsonOutput &output) { JsonResult get_version(size_t resume_point, JsonOutput &output) { char hostname[ETH_HOSTNAME_LEN + 1]; netdev_get_hostname(netdev_get_active_id(), hostname, sizeof hostname); - auto nozzle_diameter = config_store().get_nozzle_diameter(0); + float nozzle_diameter = config_store().get_nozzle_diameter(0); // Keep the indentation of the JSON in here! // clang-format off @@ -210,7 +210,7 @@ JsonResult get_version(size_t resume_point, JsonOutput &output) { JsonResult get_info(size_t resume_point, JsonOutput &output) { char hostname[ETH_HOSTNAME_LEN + 1]; netdev_get_hostname(netdev_get_active_id(), hostname, sizeof hostname); - auto nozzle_diameter = config_store().get_nozzle_diameter(0); + float nozzle_diameter = config_store().get_nozzle_diameter(0); auto mmu2_enabled = #if HAS_MMU2() config_store().mmu2_enabled.get(); diff --git a/lib/WUI/nhttp/req_parser.cpp b/lib/WUI/nhttp/req_parser.cpp index b423720d68..f1dc33aa66 100644 --- a/lib/WUI/nhttp/req_parser.cpp +++ b/lib/WUI/nhttp/req_parser.cpp @@ -111,7 +111,8 @@ ExecutionControl RequestParser::event(Event event) { error_code = Status::RequestHeaderFieldsTooLarge; return ExecutionControl::Continue; } - case Names::Nonce: { + case Names::Nonce: + case Names::NonceUnquoted: { if (!holds_alternative(auth_status)) { auth_status = DigestAuthParams {}; } @@ -126,7 +127,8 @@ ExecutionControl RequestParser::event(Event event) { digest_params.recieved_nonce += static_cast(value); return ExecutionControl::Continue; } - case Names::Response: { + case Names::Response: + case Names::ResponseUnquoted: { if (!holds_alternative(auth_status)) { auth_status = DigestAuthParams {}; } diff --git a/src/common/filament.hpp b/src/common/filament.hpp index 05b5165037..1f8dcf6982 100644 --- a/src/common/filament.hpp +++ b/src/common/filament.hpp @@ -31,6 +31,50 @@ enum class Type : uint8_t { _last = PA }; +struct ColorIndex { + const char *name; + uint32_t color; +}; + +enum class ColorName : uint32_t { + NONE = 0, + BLACK, + BLUE, + GREEN, + BROWN, + PURPLE, + GRAY, + TERRACOTTA, + SILVER, + GOLD, + RED, + PINK, + ORANGE, + TRANSPARENT, + YELLOW, + WHITE, + _last = WHITE +}; + +const ColorIndex colortable[size_t(filament::ColorName::_last) + 1] = { + { "NONE", 0 }, + { "BLACK", 0x000000 }, + { "BLUE", 0x0000FF }, + { "GREEN", 0x00FF00 }, + { "BROWN", 0x800000 }, + { "PURPLE", 0x800080 }, + { "GRAY", 0x999999 }, + { "TERRACOTTA", 0xB87F6A }, + { "SILVER", 0xC0C0C0 }, + { "GOLD", 0xD4AF37 }, + { "RED", 0xFF0000 }, + { "PINK", 0xFF007F }, + { "ORANGE", 0xFF8000 }, + { "TRANSPARENT", 0xF0F0F0 }, + { "YELLOW", 0xFFFF00 }, + { "WHITE", 0xFFFFFF } +}; + constexpr Type default_type = Type::PLA; constexpr float cold_nozzle = 50.f; constexpr float cold_bed = 45.f; @@ -53,6 +97,17 @@ struct Colour { return red << 16 | green << 8 | blue; } + static Colour from_string(char *name) { + // first name is not valid ("---") + size_t name_len = strlen(name); + for (size_t i = size_t(ColorName::NONE) + 1; i <= size_t(ColorName::_last); ++i) { + if ((strlen(colortable[i].name) == name_len) && (!strncmp(name, colortable[i].name, name_len))) { + return from_int(colortable[i].color); + } + } + return from_int(atoi(name)); + } + static Colour from_int(int value) { return Colour { .red = static_cast((value >> 16) & 0xFF), diff --git a/src/common/gcode/gcode_info.cpp b/src/common/gcode/gcode_info.cpp index 4673c55afc..e8bc108431 100644 --- a/src/common/gcode/gcode_info.cpp +++ b/src/common/gcode/gcode_info.cpp @@ -220,8 +220,8 @@ void GCodeInfo::EvaluateToolsValid() { if (per_extruder_info[e].nozzle_diameter.has_value()) { auto do_nozzle_check = [&](uint8_t hotend) { assert(hotend < HOTENDS); - float nozzle_diameter_distance = per_extruder_info[e].nozzle_diameter.value() - config_store().get_nozzle_diameter(hotend); - if (nozzle_diameter_distance > 0.001f || nozzle_diameter_distance < -0.001f) { + float nozzle_diameter_distance = std::abs(per_extruder_info[e].nozzle_diameter.value() - config_store().get_nozzle_diameter(hotend)); + if (nozzle_diameter_distance > 0.001f) { valid_printer_settings.wrong_nozzle_diameter.fail(); } }; diff --git a/src/common/marlin_print_preview.cpp b/src/common/marlin_print_preview.cpp index 3404da2eaf..1d90ab8a60 100644 --- a/src/common/marlin_print_preview.cpp +++ b/src/common/marlin_print_preview.cpp @@ -166,8 +166,8 @@ auto PrintPreview::check_tools_mapping_validity(const ToolMapper &mapper, const return true; } - float nozzle_diameter_distance = gcode.get_extruder_info(gcode_tool).nozzle_diameter.value() - get_nozzle_diameter(physical_extruder); - if (nozzle_diameter_distance > 0.001f || nozzle_diameter_distance < -0.001f) { + float nozzle_diameter_distance = std::abs(static_cast(gcode.get_extruder_info(gcode_tool).nozzle_diameter.value()) - static_cast(get_nozzle_diameter(physical_extruder))); + if (nozzle_diameter_distance > 0.001f) { return false; } diff --git a/src/gui/dialogs/DialogConnectReg.hpp b/src/gui/dialogs/DialogConnectReg.hpp index d1ddf987eb..6b5c5a6472 100644 --- a/src/gui/dialogs/DialogConnectReg.hpp +++ b/src/gui/dialogs/DialogConnectReg.hpp @@ -12,7 +12,7 @@ class DialogConnectRegister : public AddSuperWindow { private: char attempt_buffer[30]; char detail_buffer[70]; - char error_buffer[88]; + char error_buffer[90]; // TODO: Doesn't fit constexpr static const char *const headerLabel = N_("PRUSA CONNECT"); diff --git a/src/gui/screen_tools_mapping.cpp b/src/gui/screen_tools_mapping.cpp index 71483c7014..655bf4bcc3 100644 --- a/src/gui/screen_tools_mapping.cpp +++ b/src/gui/screen_tools_mapping.cpp @@ -144,11 +144,11 @@ void disable_radio(RadioButton &radio) { radio.Invalidate(); } -double get_nozzle_diameter([[maybe_unused]] size_t idx) { +float get_nozzle_diameter([[maybe_unused]] size_t idx) { #if HAS_TOOLCHANGER() - return static_cast(config_store().get_nozzle_diameter(idx)); + return static_cast(config_store().get_nozzle_diameter(idx)); #elif HAS_MMU2() - return static_cast(config_store().get_nozzle_diameter(0)); + return static_cast(config_store().get_nozzle_diameter(0)); #endif } @@ -162,7 +162,7 @@ void print_right_tool_into_buffer(size_t idx, std::array(get_nozzle_diameter(idx))); } } @@ -268,8 +268,8 @@ bool all_nozzles_same(GCodeInfo &gcode_info) { bool initialized { false }; auto nozzles_are_matching = [](float lhs, float rhs) { - float nozzle_diameter_distance = lhs - rhs; - return !(nozzle_diameter_distance > 0.001f || nozzle_diameter_distance < -0.001f); + float nozzle_diameter_distance = std::abs(lhs - rhs); + return nozzle_diameter_distance <= 0.001f; }; // check gcodes EXTRUDER_LOOP() { diff --git a/src/marlin_stubs/host/M46.cpp b/src/marlin_stubs/host/M46.cpp index e96c5e007d..c8462e4b38 100644 --- a/src/marlin_stubs/host/M46.cpp +++ b/src/marlin_stubs/host/M46.cpp @@ -8,12 +8,13 @@ void GcodeSuite::M46() { netdev_get_ipv4_addresses(netdev_get_active_id(), ðconfig); uint8_t *ipp = (uint8_t *)ðconfig.addr_ip4; char ip4[17] = { 0 }; - sprintf(ip4, "%u.%u.%u.%u\n", ipp[0], ipp[1], ipp[2], ipp[3]); + snprintf(ip4, sizeof(ip4), "%u.%u.%u.%u\n", ipp[0], ipp[1], ipp[2], ipp[3]); serialprintPGM(ip4); - if (parser.seen('M')) { mac_address_t mac; + char mac_buffer[19] = { 0 }; get_MAC_address(&mac, netdev_get_active_id()); - serialprintPGM(mac); + snprintf(mac_buffer, sizeof(mac_buffer), "%s\n", mac); + serialprintPGM(mac_buffer); } } diff --git a/src/marlin_stubs/pause/M600.cpp b/src/marlin_stubs/pause/M600.cpp index d998daf228..4d6282801f 100644 --- a/src/marlin_stubs/pause/M600.cpp +++ b/src/marlin_stubs/pause/M600.cpp @@ -77,6 +77,9 @@ static void M600_manual(); * B[count] - Number of times to beep, -1 for indefinite (if equipped with a buzzer) * T[toolhead] - Select extruder for filament change * A - If automatic spool join is configured for this tool, do that instead, if not, do manual filament change + * C[color] - Set color for filament change (color rgb value as integer) + * C"color" - Set color for filament change (color name as string) + * S"filament" - Set filament type for filament change. RepRap compatible. * * Default values are used for omitted arguments. */ @@ -116,10 +119,58 @@ void GcodeSuite::M600() { } void M600_execute(xyz_pos_t park_point, int8_t target_extruder, - xyze_float_t resume_point, std::optional unloadLength, std::optional fastLoadLength, std::optional retractLength, - pause::Settings::CalledFrom); + xyze_float_t resume_point, std::optional unloadLength, std::optional fastLoadLength, + std::optional retractLength, std::optional filament_colour, + std::optional filament_type, pause::Settings::CalledFrom); void M600_manual() { + char colourtype[16] = { '\0' }; + + auto filament_to_be_loaded = filament::Type::NONE; + const char *text_begin = 0; + if (parser.seen('S')) { + text_begin = strchr(parser.string_arg, '"'); + if (text_begin) { + ++text_begin; // move pointer from '"' to first letter + const char *text_end = strchr(text_begin, '"'); + if (text_end) { + auto filament = filament::get_type(text_begin, text_end - text_begin); + if (filament != filament::Type::NONE) { + filament_to_be_loaded = filament; + } + } + } + } + + if (parser.seen('C')) { + const char *colourtype_ptr = nullptr; + if ((colourtype_ptr = strstr(parser.string_arg, "C\"")) != nullptr) { + text_begin = strchr(colourtype_ptr, '"'); + if (text_begin) { + ++text_begin; + strlcpy(colourtype, text_begin, sizeof(colourtype)); + for (char *fn = colourtype; *fn; ++fn) { + if (*fn == '"') { + *fn = '\0'; + break; + } + } + } + } else if ((colourtype_ptr = strstr(parser.string_arg, "C ")) != nullptr) { + text_begin = strchr(colourtype_ptr, ' '); + if (text_begin) { + ++text_begin; + strlcpy(colourtype, text_begin, sizeof(colourtype)); + for (char *fn = colourtype; *fn; ++fn) { + if (*fn == ' ') { + *fn = '\0'; + break; + } + } + } + } + } + const int8_t target_extruder = GcodeSuite::get_target_extruder_from_command(); if (target_extruder < 0) { return; @@ -160,11 +211,15 @@ void M600_manual() { parser.seen('U') ? std::make_optional(parser.value_axis_units(E_AXIS)) : std::nullopt, parser.seen('L') ? std::make_optional(parser.value_axis_units(E_AXIS)) : std::nullopt, parser.seen('E') ? std::make_optional(std::abs(parser.value_axis_units(E_AXIS))) : std::nullopt, + parser.seen('C') ? std::make_optional(filament::Colour::from_string(colourtype)) : std::nullopt, + parser.seen('S') ? std::make_optional(filament_to_be_loaded) : std::nullopt, pause::Settings::CalledFrom::Pause); } void M600_execute(xyz_pos_t park_point, int8_t target_extruder, xyze_float_t resume_point, - std::optional unloadLength, std::optional fastLoadLength, std::optional retractLength, pause::Settings::CalledFrom called_from) { + std::optional unloadLength, std::optional fastLoadLength, std::optional retractLength, + std::optional filament_colour, std::optional filament_type, + pause::Settings::CalledFrom called_from) { #if ENABLED(CRASH_RECOVERY) if (crash_s.get_state() != Crash_s::PRINTING && crash_s.get_state() != Crash_s::IDLE) { @@ -201,8 +256,12 @@ void M600_execute(xyz_pos_t park_point, int8_t target_extruder, xyze_float_t res thermalManager.setTargetHotend(disp_temp, target_extruder); } + if (filament_type.has_value()) { + config_store().set_filament_type(target_extruder, filament_type.value()); + } + filament::set_type_to_load(config_store().get_filament_type(target_extruder)); - filament::set_color_to_load(std::nullopt); + filament::set_color_to_load(filament_colour.value()); Pause::Instance().FilamentChange(settings); marlin_server::nozzle_timeout_on(); @@ -225,6 +284,7 @@ void PrusaGcodeSuite::M1601() { active_extruder, current_position, std::nullopt, std::nullopt, std::nullopt, + std::nullopt, std::nullopt, pause::Settings::CalledFrom::FilamentStuck); } #else diff --git a/tests/unit/common/automata/generated.cpp b/tests/unit/common/automata/generated.cpp index 8b0c2ab4e5..90fedd2861 100644 --- a/tests/unit/common/automata/generated.cpp +++ b/tests/unit/common/automata/generated.cpp @@ -288,3 +288,19 @@ TEST_CASE("Digest auth whole") { REQUIRE(ex.collect_entered(Names::Nonce) == "dcd98b7102dd2f0e"); REQUIRE(ex.collect_entered(Names::Response) == "684d849df474f295771de997e7412ea4"); } + +TEST_CASE("Digest auth with algorithm") { + using test::http::Names; + TestExecution ex(http_request); + ex.consume("GET /api/version HTTP/1.1\r\nAuthorization: Digest username=\"user\", realm=\"Printer API\", nonce=\"dcd98b7102dd2f0e\", uri=\"/api/version\", algorithm=MD5, response=\"684d849df474f295771de997e7412ea4\"\r\n\r\n"); + REQUIRE(ex.collect_entered(Names::Nonce) == "dcd98b7102dd2f0e"); + REQUIRE(ex.collect_entered(Names::Response) == "684d849df474f295771de997e7412ea4"); +} + +TEST_CASE("Digest auth without quotes") { + using test::http::Names; + TestExecution ex(http_request); + ex.consume("GET /api/version HTTP/1.1\r\nAuthorization: Digest username=\"user\", realm=\"Printer API\", nonce=dcd98b7102dd2f0e, uri=\"/api/version\", response=684d849df474f295771de997e7412ea4\r\n\r\n"); + REQUIRE(ex.collect_entered(Names::NonceUnquoted) == "dcd98b7102dd2f0e"); + REQUIRE(ex.collect_entered(Names::ResponseUnquoted) == "684d849df474f295771de997e7412ea4"); +} diff --git a/utils/gen-automata/http.py b/utils/gen-automata/http.py index a106df3cd2..6e0edfb937 100644 --- a/utils/gen-automata/http.py +++ b/utils/gen-automata/http.py @@ -287,7 +287,7 @@ def content_encryption_mode_header(): for t in terminals: terminals[t].mark_enter() terminals[t].set_name(encryption_modes[t]) - # Eat spaces before the content type + # Eat spaces before the encryption mode start = tr.start() start.loop('HorizWhitespace', LabelType.Special) @@ -322,23 +322,45 @@ def create_folder_header(): def auth_value(name): + name_unquoted = f"{name}Unquoted" if name != None else None + auto = Automaton() start = auto.start() - value = auto.add_state() + quote = auto.add_state() + value_quoted = auto.add_state() + value_unquoted = auto.add_state() + end = auto.add_state() start.loop("HorizWhitespace", LabelType.Special) - start.loop("\"", LabelType.Char) - value.set_name(name) - value.mark_enter() - line, end = newline() - end.loop('HorizWhitespace', LabelType.Special) + start.add_transition('\"', LabelType.Char, quote) + start.add_transition('Whitespace', + LabelType.Special, + end, + fallthrough=True) # Vertical whitespace + start.add_transition(',', LabelType.Char, end, fallthrough=True) + start.add_transition('All', LabelType.Special, value_unquoted) + + quote.add_transition('\"', LabelType.Char, end) + quote.add_transition('All', LabelType.Special, value_quoted) + + value_quoted.set_name(name) + value_quoted.mark_enter() + value_quoted.add_transition('\"', LabelType.Char, end) + value_quoted.loop_fallback() + + value_unquoted.set_name(name_unquoted) + value_unquoted.mark_enter() + value_unquoted.add_transition('Whitespace', + LabelType.Special, + end, + fallthrough=True) + value_unquoted.add_transition(',', LabelType.Char, end, fallthrough=True) + value_unquoted.loop_fallback() + + end.loop("HorizWhitespace", LabelType.Special) end.loop(',', LabelType.Char) - auto.join(start, line) - start.add_transition('All', LabelType.Special, value) - value.add_transition('\"', LabelType.Char, end) - value.loop_fallback() - return auto, end, False + return auto, end, True def authorization_header(): @@ -347,39 +369,48 @@ def authorization_header(): Authorization: Digest username="user", realm="Printer API", nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", uri="/api/version", response="684d849df474f295771de997e7412ea4" """ + # Consume the auth scheme (Digest) + auto, scheme_spaces = read_until("HorizWhitespace", LabelType.Special) + + # Eat spaces before the parameters + scheme_spaces.loop('HorizWhitespace', LabelType.Special) + # We only really read nonce and response, the rest is assumed for # performance reasons. auth_values = { 'nonce': auth_value('Nonce'), 'response': auth_value('Response'), } - auto, terminals, add_unknowns = trie(auth_values) - start = auto.start() + tr, terminals, add_unknowns = trie(auth_values) + tr_start = tr.start() line, end = newline() - auto.join(start, line) + tr.join(tr_start, line) for parameter in auth_values: term = terminals[parameter] term.loop("HorizWhitespace", LabelType.Special) - separator = auto.add_state() + separator = tr.add_state() separator.loop("HorizWhitespace", LabelType.Special) term.add_transition('=', LabelType.Char, separator) read_par, read_par_end, fallthrough = auth_values[parameter] - auto.join_transition(separator, read_par, fallthrough=fallthrough) - read_par_end.add_fallback(start, fallthrough=True) + tr.join_transition(separator, read_par, fallthrough=fallthrough) + read_par_end.add_fallback(tr_start, fallthrough=True) # Handling of unknown/ not parsed values - unknown = auto.add_state() + unknown = tr.add_state() for u in add_unknowns: u.add_fallback(unknown) - unknown.loop("HorizWhitespace", LabelType.Special) - after_unknown = auto.add_state() + after_unknown = tr.add_state() unknown.add_transition('=', LabelType.Char, after_unknown) unknown.loop_fallback() after_unknown.loop("HorizWhitespace", LabelType.Special) - ignore_unknown_header, iuh_end, _ = auth_value(None) - auto.join_transition(after_unknown, ignore_unknown_header) - iuh_end.add_fallback(start, fallthrough=True) + ignore_unknown_header, iuh_end, fallthrough = auth_value(None) + tr.join_transition(after_unknown, + ignore_unknown_header, + fallthrough=fallthrough) + iuh_end.add_fallback(tr_start, fallthrough=True) + + auto.join(scheme_spaces, tr) return auto, end, True diff --git a/utils/simulator/simulator.py b/utils/simulator/simulator.py index 4d8bb6b07c..61d3f91b0e 100644 --- a/utils/simulator/simulator.py +++ b/utils/simulator/simulator.py @@ -50,6 +50,7 @@ async def run( eeprom_content: Optional[Tuple[Path, Path]] = None, xflash_content: Optional[Path] = None, nographic=False, + usbserial=True, invoke_callback: Optional[Callable[[List[str]], None]] = None, extra_arguments: Optional[List[str]] = None): # prepare the arguments @@ -61,7 +62,7 @@ async def run( if machine.is_puppy: params += ['-icount', '5'] else: - params += ['-icount', 'auto'] + params += ['-icount', '2'] if scriptio_port: params += [ '-chardev', @@ -98,6 +99,8 @@ async def run( ] if nographic: params += ['-nographic'] + if usbserial: + params += ['-chardev', 'vc,rows=25,cols=80,id=stm32usbfscdc'] if extra_arguments: params += extra_arguments