#pragma once #include "firmware_types.h" #include #include #include #include #define M_PI 3.14159265358979323846 // pi #define DEFAULT_FIRMWARE_TYPE firmware_types::MARLIN_2 #define LATEST_FIRMWARE_VERSION_NAME "LATEST_RELEASE" #define DEFAULT_FIRMWARE_VERSION_NAME LATEST_FIRMWARE_VERSION_NAME // Arc interpretation settings: #define DEFAULT_MM_PER_ARC_SEGMENT 1.0 // REQUIRED - The enforced maximum length of an arc segment #define DEFAULT_ARC_SEGMENTS_PER_R 0; #define DEFAULT_MIN_MM_PER_ARC_SEGMENT 0 /* OPTIONAL - the enforced minimum length of an interpolated segment. Must be smaller than MM_PER_ARC_SEGMENT. Only has an effect if MIN_ARC_SEGMENTS > 0 or ARC_SEGMENTS_PER_SEC > 0 */ // If both MIN_ARC_SEGMENTS and ARC_SEGMENTS_PER_SEC is defined, the minimum calculated segment length is used. #define DEFAULT_MIN_ARC_SEGMENTS 0 // OPTIONAL - The enforced minimum segments in a full circle of the same radius. #define DEFAULT_ARC_SEGMENTS_PER_SEC 0 // OPTIONAL - Use feedrate to choose segment length. // approximation will not be used for the first segment. Subsequent segments will be corrected following DEFAULT_N_ARC_CORRECTION. #define DEFAULT_N_ARC_CORRECTIONS 24 // This setting is for the gcode position processor to help interpret G90/G91 behavior #define DEFAULT_G90_G91_INFLUENCES_EXTRUDER false // This currently is only used in Smoothieware. The maximum error for line segments that divide arcs. Set to 0 to disable. #define DEFAULT_MM_MAX_ARC_ERROR 0.01 struct firmware_state { firmware_state() { is_relative = false; is_extruder_relative = false; } bool is_relative; bool is_extruder_relative; }; struct firmware_position { firmware_position() { x = 0; y = 0; z = 0; e = 0; f = 0; } double x; double y; double z; double e; double f; }; struct firmware_arguments { public: firmware_arguments() { mm_per_arc_segment = DEFAULT_MM_PER_ARC_SEGMENT; arc_segments_per_r = DEFAULT_ARC_SEGMENTS_PER_R; min_mm_per_arc_segment = DEFAULT_MIN_MM_PER_ARC_SEGMENT; min_arc_segments = DEFAULT_MIN_ARC_SEGMENTS; arc_segments_per_sec = DEFAULT_ARC_SEGMENTS_PER_SEC; n_arc_correction = DEFAULT_N_ARC_CORRECTIONS; g90_g91_influences_extruder = DEFAULT_G90_G91_INFLUENCES_EXTRUDER; mm_max_arc_error = DEFAULT_MM_MAX_ARC_ERROR; version = DEFAULT_FIRMWARE_VERSION_NAME; firmware_type = (firmware_types)DEFAULT_FIRMWARE_TYPE; latest_release_version = LATEST_FIRMWARE_VERSION_NAME; // add a list of all possible arguments, including aliases all_arguments_.clear(); all_arguments_.push_back("mm_per_arc_segment"); all_arguments_.push_back("arc_segments_per_r"); all_arguments_.push_back("min_mm_per_arc_segment"); all_arguments_.push_back("min_arc_segments"); all_arguments_.push_back("arc_segments_per_sec"); all_arguments_.push_back("n_arc_correction"); all_arguments_.push_back("g90_g91_influences_extruder"); all_arguments_.push_back("mm_max_arc_error"); all_arguments_.push_back("min_circle_segments"); all_arguments_.push_back("min_arc_segment_mm"); all_arguments_.push_back("max_arc_segment_mm"); }; /// /// The maximum mm per arc segment. /// double mm_per_arc_segment; /// /// The maximum segment length /// double arc_segments_per_r; /// /// The minimum mm per arc segment. If less than or equal to 0, this is disabled /// double min_mm_per_arc_segment; /// /// The number of arc segments that will be drawn per second based on the given feedrate. /// If less than or equal to zero, this is disabled. /// double arc_segments_per_sec; /// /// This currently is only used in Smoothieware. The maximum error for line segments that divide arcs. Set to 0 to disable. /// double mm_max_arc_error; /// /// The minimum number of arc segments in a full circle of the arc's radius. /// If less than or equal to zero, this is disabled /// int min_arc_segments; /// /// // Number of interpolated segments before true sin and cos corrections will be applied. /// If less than or equal to zero, true sin and cos will always be used. /// int n_arc_correction; /// /// This value will set the behavior of G90/G91. /// bool g90_g91_influences_extruder; /// /// The type of firmware to use when interpolating. /// firmware_types firmware_type; /// /// The firmware version to use. Defaults to LATEST /// std::string version; /// /// True if the current version is the latest release. For informational purposes only /// std::string latest_release_version; /// Aliases for variour parameters int get_min_circle_segments() const { return min_arc_segments; } void set_min_circle_segments(int segments) { min_arc_segments = segments; } double get_min_arc_segment_mm() const { return min_mm_per_arc_segment; } void set_min_arc_segment_mm(double mm) { min_mm_per_arc_segment = mm; } double get_max_arc_segment_mm() const { return mm_per_arc_segment; } void set_max_arc_segment_mm(double mm) { mm_per_arc_segment = mm; } void set_used_arguments(std::vector arguments) { used_arguments_ = arguments; } std::vector get_unused_arguments() { std::vector unused_arguments; for (std::vector::iterator it = all_arguments_.begin(); it != all_arguments_.end(); it++) { if (!is_argument_used(*it)) { unused_arguments.push_back(*it); } } return unused_arguments; } std::string get_unused_arguments_string() { std::string unusaed_argument_string = ""; std::vector unused_argumnts = get_unused_arguments(); for (std::vector::iterator it = unused_argumnts.begin(); it != unused_argumnts.end(); it++) { if (unusaed_argument_string.size() > 0) { unusaed_argument_string += ", "; } unusaed_argument_string += *it; } return unusaed_argument_string; } std::vector get_available_arguments() { return used_arguments_; } std::string get_argument_description() { std::stringstream stream; stream << "Firmware Arguments:\n"; stream << "\tFirmware Type : " << firmware_type_names[firmware_type] << "\n"; stream << "\tFirmware Version : " << (version == LATEST_FIRMWARE_VERSION_NAME || version == latest_release_version ? latest_release_version + " (" + LATEST_FIRMWARE_VERSION_NAME + ")" : version) <<"\n"; stream << std::fixed << std::setprecision(0); // Bool values if (is_argument_used("g90_g91_influences_extruder")) { stream << "\tg90_g91_influences_extruder : " << (g90_g91_influences_extruder ? "True" : "False") << "\n"; } // Int values if (is_argument_used("min_arc_segments")) { stream << "\tmin_arc_segments : " << min_arc_segments << "\n"; } if (is_argument_used("min_circle_segments")) { stream << "\tmin_circle_segments : " << get_min_circle_segments() << "\n"; } if (is_argument_used("n_arc_correction")) { stream << "\tn_arc_correction : " << n_arc_correction << "\n"; } stream << std::fixed << std::setprecision(2); // Double values // if (is_argument_used("mm_per_arc_segment")) { stream << "\tmm_per_arc_segment : " << mm_per_arc_segment << "\n"; } // if (is_argument_used("arc_segments_per_r")) { stream << "\tarc_segments_per_r : " << arc_segments_per_r << "\n"; } // if (is_argument_used("min_mm_per_arc_segment")) { stream << "\tmin_mm_per_arc_segment : " << min_mm_per_arc_segment << "\n"; } // if (is_argument_used("arc_segments_per_sec")) { stream << "\tarc_segments_per_sec : " << arc_segments_per_sec << "\n"; } // if (is_argument_used("mm_max_arc_error")) { stream << "\tmm_max_arc_error : " << mm_max_arc_error << "\n"; } // if (is_argument_used("min_arc_segment_mm")) { stream << "\tmin_arc_segment_mm : " << get_min_arc_segment_mm() << "\n"; } // if (is_argument_used("max_arc_segment_mm")) { stream << "\tmax_arc_segment_mm : " << get_max_arc_segment_mm() << "\n"; } std::string unused_argument_string = get_unused_arguments_string(); if (unused_argument_string.size() > 0) { stream << "The following parameters do not apply to this firmware version: " << unused_argument_string << "\n"; } return stream.str(); } bool is_argument_used(std::string argument_name) { return (std::find(used_arguments_.begin(), used_arguments_.end(), argument_name) != used_arguments_.end()); } private: std::vector all_arguments_; std::vector used_arguments_; }; class firmware { public: firmware(); firmware(firmware_arguments args); /// /// Generate G1 gcode strings separated by line breaks representing the supplied G2/G3 command. /// /// The current printer position /// The target printer position /// Specifies the X offset for the arc's center. /// Specifies the Y offset for the arc's center. /// Specifies the radius of the arc. If r is greater than 0, this will override the i and j parameters. /// If true, this is a G2 command. If false, this is a G3 command. /// If this is true, the extruder is currently in relative mode. Else it is in absolute mode. /// This is the absolute offset for absolute E coordinates if the extruder is not in relative mode. /// virtual std::string interpolate_arc(firmware_position& target, double i, double j, double r, bool is_clockwise); /// /// Sets the current position. Should be called before interpolate_arc. /// /// The position to set void set_current_position(firmware_position& position); /// /// Sets firmware offsets and the xyze axis mode. /// /// The state to set void set_current_state(firmware_state& state); /// /// Create a G1 command from the current position and offsets. /// /// The position of the printer after the G1 command is completed. /// The G1 command virtual std::string g1_command(firmware_position& target); /// /// Checks a string to see if it is a valid version. /// /// The version to check. /// True if the supplied version is valid bool is_valid_version(std::string version); /// /// Returns all valid versions for this firmware. /// /// Vector of strings, one for each supported version std::vector get_version_names(); /// /// Returns the current g90_g91_influences_extruder value for the firmware. /// /// bool get_g90_g91_influences_extruder(); /// /// Returns the number of arc segments that were generated from g2/g3 commands. /// /// int get_num_arc_segments_generated(); /// /// Outputs a string description of the firmware arguments. /// /// std::string get_argument_description(); /// /// Sets all available versions names and the version index based on args_.version /// /// void set_versions(std::vector version_names, std::string latest_release_version_name); virtual firmware_arguments get_default_arguments_for_current_version()const; void set_arguments(firmware_arguments args); virtual void apply_arguments(); protected: firmware_position position_; firmware_state state_; firmware_arguments args_; std::vector version_names_; int version_index_; int num_arc_segments_generated_; virtual firmware_arguments arguments_changed(firmware_arguments current_args, firmware_arguments new_args); };