diff options
32 files changed, 3665 insertions, 4278 deletions
@@ -73,6 +73,7 @@ <listOptionValue builtIn="false" value=""${workspace_loc:/RRFLibraries/SAM3X_RTOS}""/> </option> <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.cpp.link.option.libs.1006761104" name="Libraries (-l)" superClass="gnu.cpp.link.option.libs" useByScannerDiscovery="false" valueType="libs"> + <listOptionValue builtIn="false" value="supc++"/> <listOptionValue builtIn="false" value="CoreNG"/> <listOptionValue builtIn="false" value="FreeRTOS"/> <listOptionValue builtIn="false" value="RRFLibraries"/> @@ -87,7 +88,7 @@ <option id="gnu.cpp.compiler.option.optimization.level.25432549" name="Optimization Level" superClass="gnu.cpp.compiler.option.optimization.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.optimization.level.more" valueType="enumerated"/> <option id="gnu.cpp.compiler.option.debugging.level.1920128035" name="Debug Level" superClass="gnu.cpp.compiler.option.debugging.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.debugging.level.none" valueType="enumerated"/> <option id="gnu.cpp.compiler.option.other.verbose.1825237573" name="Verbose (-v)" superClass="gnu.cpp.compiler.option.other.verbose" useByScannerDiscovery="false" value="false" valueType="boolean"/> - <option id="gnu.cpp.compiler.option.other.other.165959132" name="Other flags" superClass="gnu.cpp.compiler.option.other.other" useByScannerDiscovery="false" value="-c -mcpu=cortex-m3 -mthumb -ffunction-sections -fdata-sections -fno-threadsafe-statics -fno-rtti -fno-exceptions -nostdlib -Wundef -Wdouble-promotion -fsingle-precision-constant "-Wa,-ahl=$*.s"" valueType="string"/> + <option id="gnu.cpp.compiler.option.other.other.165959132" name="Other flags" superClass="gnu.cpp.compiler.option.other.other" useByScannerDiscovery="false" value="-c -mcpu=cortex-m3 -mthumb -ffunction-sections -fdata-sections -fno-threadsafe-statics -fno-rtti -fexceptions -nostdlib -Wundef -Wdouble-promotion -fsingle-precision-constant "-Wa,-ahl=$*.s"" valueType="string"/> <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.cpp.compiler.option.include.paths.603435221" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath"> <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/cores/arduino}""/> <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/libraries/Flash}""/> @@ -241,7 +242,7 @@ <option id="gnu.cpp.compiler.option.optimization.level.1835678360" name="Optimization Level" superClass="gnu.cpp.compiler.option.optimization.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.optimization.level.more" valueType="enumerated"/> <option id="gnu.cpp.compiler.option.debugging.level.737051102" name="Debug Level" superClass="gnu.cpp.compiler.option.debugging.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.debugging.level.none" valueType="enumerated"/> <option id="gnu.cpp.compiler.option.other.verbose.1225557122" name="Verbose (-v)" superClass="gnu.cpp.compiler.option.other.verbose" useByScannerDiscovery="false" value="false" valueType="boolean"/> - <option id="gnu.cpp.compiler.option.other.other.1423466590" name="Other flags" superClass="gnu.cpp.compiler.option.other.other" useByScannerDiscovery="false" value="-c -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard -ffunction-sections -fdata-sections -fno-threadsafe-statics -fno-rtti -fno-exceptions -nostdlib -Wundef -Wdouble-promotion -fsingle-precision-constant "-Wa,-ahl=$*.s"" valueType="string"/> + <option id="gnu.cpp.compiler.option.other.other.1423466590" name="Other flags" superClass="gnu.cpp.compiler.option.other.other" useByScannerDiscovery="false" value="-c -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard -ffunction-sections -fdata-sections -fno-threadsafe-statics -fno-rtti -fexceptions -nostdlib -Wundef -Wdouble-promotion -fsingle-precision-constant "-Wa,-ahl=$*.s"" valueType="string"/> <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.cpp.compiler.option.include.paths.1505018967" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath"> <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/cores/arduino}""/> <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/libraries/Flash}""/> @@ -397,7 +398,7 @@ <option id="gnu.cpp.compiler.option.optimization.level.1017091230" name="Optimization Level" superClass="gnu.cpp.compiler.option.optimization.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.optimization.level.more" valueType="enumerated"/> <option id="gnu.cpp.compiler.option.debugging.level.326047343" name="Debug Level" superClass="gnu.cpp.compiler.option.debugging.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.debugging.level.none" valueType="enumerated"/> <option id="gnu.cpp.compiler.option.other.verbose.1316817271" name="Verbose (-v)" superClass="gnu.cpp.compiler.option.other.verbose" useByScannerDiscovery="false" value="false" valueType="boolean"/> - <option id="gnu.cpp.compiler.option.other.other.434744183" name="Other flags" superClass="gnu.cpp.compiler.option.other.other" useByScannerDiscovery="false" value="-c -mcpu=cortex-m4 -mthumb -ffunction-sections -fdata-sections -fno-threadsafe-statics -fno-rtti -fno-exceptions -nostdlib -Wundef -Wdouble-promotion -fsingle-precision-constant "-Wa,-ahl=$*.s"" valueType="string"/> + <option id="gnu.cpp.compiler.option.other.other.434744183" name="Other flags" superClass="gnu.cpp.compiler.option.other.other" useByScannerDiscovery="false" value="-c -mcpu=cortex-m4 -mthumb -ffunction-sections -fdata-sections -fno-threadsafe-statics -fno-rtti -fexceptions -nostdlib -Wundef -Wdouble-promotion -fsingle-precision-constant "-Wa,-ahl=$*.s"" valueType="string"/> <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.cpp.compiler.option.include.paths.1102345734" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath"> <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/cores/arduino}""/> <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/libraries/Flash}""/> @@ -465,671 +466,6 @@ </externalSettings> </storageModule> </cconfiguration> - <cconfiguration id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.170574622.649587786.1798324396"> - <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.170574622.649587786.1798324396" moduleId="org.eclipse.cdt.core.settings" name="PCCB_08"> - <macros> - <stringMacro name="LinkFlags2" type="VALUE_TEXT" value="-Wl,--end-group -lm"/> - <stringMacro name="LinkFlags1" type="VALUE_TEXT" value="-mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbols -Wl,--start-group"/> - <stringMacro name="CoreName" type="VALUE_TEXT" value="CoreNG"/> - </macros> - <externalSettings/> - <extensions> - <extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/> - <extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> - <extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/> - <extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> - <extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> - <extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> - </extensions> - </storageModule> - <storageModule moduleId="cdtBuildSystem" version="4.0.0"> - <configuration artifactExtension="elf" artifactName="PccbFirmware" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.170574622.649587786.1798324396" name="PCCB_08" optionalBuildProperties="" parent="cdt.managedbuild.config.gnu.cross.exe.release" postannouncebuildStep="Generating binary file" postbuildStep="arm-none-eabi-objcopy -O binary "${workspace_loc:/${ProjName}/${ConfigName}}/${BuildArtifactFileBaseName}.elf" "${workspace_loc:/${ProjName}/${ConfigName}}/${BuildArtifactFileBaseName}.bin" && crc32appender "${workspace_loc:/${ProjName}/${ConfigName}}/${BuildArtifactFileBaseName}.bin""> - <folderInfo id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.170574622.649587786.1798324396." name="/" resourcePath=""> - <toolChain id="cdt.managedbuild.toolchain.gnu.cross.exe.release.1017317107" name="Cross GCC" superClass="cdt.managedbuild.toolchain.gnu.cross.exe.release"> - <option id="cdt.managedbuild.option.gnu.cross.path.1932906636" name="Path" superClass="cdt.managedbuild.option.gnu.cross.path" useByScannerDiscovery="false" value="${ArmGccPath}" valueType="string"/> - <option id="cdt.managedbuild.option.gnu.cross.prefix.1572241044" name="Prefix" superClass="cdt.managedbuild.option.gnu.cross.prefix" useByScannerDiscovery="false" value="arm-none-eabi-" valueType="string"/> - <targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.targetPlatform.gnu.cross.185324036" isAbstract="false" osList="all" superClass="cdt.managedbuild.targetPlatform.gnu.cross"/> - <builder buildPath="${workspace_loc:/RepRapFirmware}/Release" id="cdt.managedbuild.builder.gnu.cross.1082169056" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="optimal" superClass="cdt.managedbuild.builder.gnu.cross"/> - <tool id="cdt.managedbuild.tool.gnu.cross.assembler.1148717304" name="Cross GCC Assembler" superClass="cdt.managedbuild.tool.gnu.cross.assembler"> - <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.both.asm.option.include.paths.240669562" name="Include paths (-I)" superClass="gnu.both.asm.option.include.paths" valueType="includePath"> - <listOptionValue builtIn="false" value=""${workspace_loc:/RRFLibraries}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/FreeRTOS}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/CoreNG}""/> - </option> - <inputType id="cdt.managedbuild.tool.gnu.assembler.input.2143813580" superClass="cdt.managedbuild.tool.gnu.assembler.input"/> - </tool> - <tool commandLinePattern="${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS}" id="cdt.managedbuild.tool.gnu.cross.c.compiler.1981974117" name="Cross GCC Compiler" superClass="cdt.managedbuild.tool.gnu.cross.c.compiler"> - <option defaultValue="gnu.c.optimization.level.most" id="gnu.c.compiler.option.optimization.level.1510743318" name="Optimization Level" superClass="gnu.c.compiler.option.optimization.level" useByScannerDiscovery="false" value="gnu.c.optimization.level.more" valueType="enumerated"/> - <option id="gnu.c.compiler.option.debugging.level.1424949241" name="Debug Level" superClass="gnu.c.compiler.option.debugging.level" useByScannerDiscovery="false" value="gnu.c.debugging.level.none" valueType="enumerated"/> - <option id="gnu.c.compiler.option.misc.verbose.623464210" name="Verbose (-v)" superClass="gnu.c.compiler.option.misc.verbose" useByScannerDiscovery="false" value="false" valueType="boolean"/> - <option id="gnu.c.compiler.option.misc.other.1167454821" name="Other flags" superClass="gnu.c.compiler.option.misc.other" useByScannerDiscovery="false" value="-c -mcpu=cortex-m4 -mthumb -ffunction-sections -fdata-sections -nostdlib -Wundef -Wdouble-promotion -fsingle-precision-constant "-Wa,-ahl=$*.s"" valueType="string"/> - <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.c.compiler.option.include.paths.531615654" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath"> - <listOptionValue builtIn="false" value=""${workspace_loc:/RRFLibraries}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/FreeRTOS}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/CoreNG}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/cores/arduino}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/libraries/Storage}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/common/utils}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/common/services/ioport}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/drivers}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils/cmsis/sam4s/include}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils/header_files}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils/preprocessor}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/thirdparty/CMSIS/Include}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/variants/sam4s}""/> - </option> - <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.c.compiler.option.preprocessor.def.symbols.507583566" name="Defined symbols (-D)" superClass="gnu.c.compiler.option.preprocessor.def.symbols" useByScannerDiscovery="false" valueType="definedSymbols"> - <listOptionValue builtIn="false" value="__SAM4S8C__"/> - <listOptionValue builtIn="false" value="RTOS"/> - <listOptionValue builtIn="false" value="PCCB"/> - <listOptionValue builtIn="false" value="PCCB_08"/> - </option> - <option id="gnu.c.compiler.option.dialect.flags.1478750267" name="Other dialect flags" superClass="gnu.c.compiler.option.dialect.flags" useByScannerDiscovery="true" value="-std=gnu99" valueType="string"/> - <inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.562849016" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/> - </tool> - <tool id="cdt.managedbuild.tool.gnu.cross.c.linker.1448735774" name="Cross GCC Linker" superClass="cdt.managedbuild.tool.gnu.cross.c.linker"/> - <tool id="cdt.managedbuild.tool.gnu.cross.archiver.886333230" name="Cross GCC Archiver" superClass="cdt.managedbuild.tool.gnu.cross.archiver"/> - <tool command="gcc" commandLinePattern="${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${LinkFlags1} "${workspace_loc:/${CoreName}}/SAM4S/cores/arduino/syscalls.o" ${INPUTS} ${LinkFlags2}" id="cdt.managedbuild.tool.gnu.cross.cpp.linker.687537254" name="Cross G++ Linker" superClass="cdt.managedbuild.tool.gnu.cross.cpp.linker"> - <option id="gnu.cpp.link.option.nostdlibs.1719677032" name="No startup or default libs (-nostdlib)" superClass="gnu.cpp.link.option.nostdlibs" useByScannerDiscovery="false" value="false" valueType="boolean"/> - <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.cpp.link.option.paths.2028936348" name="Library search path (-L)" superClass="gnu.cpp.link.option.paths" useByScannerDiscovery="false" valueType="libPaths"> - <listOptionValue builtIn="false" value=""${workspace_loc:/CoreNG/SAM4S_PCCB/}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/FreeRTOS/SAM4S}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/RRFLibraries/SAM4S_RTOS}""/> - </option> - <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.cpp.link.option.libs.1421214818" name="Libraries (-l)" superClass="gnu.cpp.link.option.libs" useByScannerDiscovery="false" valueType="libs"> - <listOptionValue builtIn="false" value="CoreNG"/> - <listOptionValue builtIn="false" value="FreeRTOS"/> - <listOptionValue builtIn="false" value="RRFLibraries"/> - </option> - <option id="gnu.cpp.link.option.flags.633609481" name="Linker flags" superClass="gnu.cpp.link.option.flags" useByScannerDiscovery="false" value="-Os --specs=nano.specs -Wl,--gc-sections -Wl,--fatal-warnings -mcpu=cortex-m4 -T"${workspace_loc:/${CoreName}/variants/sam4s/linker_scripts/gcc/flash.ld}" -Wl,-Map,"${workspace_loc:/${ProjName}/${ConfigName}}/${BuildArtifactFileBaseName}.map"" valueType="string"/> - <inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.96746585" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input"> - <additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/> - <additionalInput kind="additionalinput" paths="$(LIBS)"/> - </inputType> - </tool> - <tool command="g++" id="cdt.managedbuild.tool.gnu.cross.cpp.compiler.972255361" name="Cross G++ Compiler" superClass="cdt.managedbuild.tool.gnu.cross.cpp.compiler"> - <option id="gnu.cpp.compiler.option.optimization.level.820933483" name="Optimization Level" superClass="gnu.cpp.compiler.option.optimization.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.optimization.level.more" valueType="enumerated"/> - <option id="gnu.cpp.compiler.option.debugging.level.1785551954" name="Debug Level" superClass="gnu.cpp.compiler.option.debugging.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.debugging.level.none" valueType="enumerated"/> - <option id="gnu.cpp.compiler.option.other.verbose.1038790030" name="Verbose (-v)" superClass="gnu.cpp.compiler.option.other.verbose" useByScannerDiscovery="false" value="false" valueType="boolean"/> - <option id="gnu.cpp.compiler.option.other.other.1212511140" name="Other flags" superClass="gnu.cpp.compiler.option.other.other" useByScannerDiscovery="false" value="-c -mcpu=cortex-m4 -mthumb -ffunction-sections -fdata-sections -fno-threadsafe-statics -fno-rtti -fno-exceptions -nostdlib -Wundef -Wdouble-promotion -fsingle-precision-constant "-Wa,-ahl=$*.s"" valueType="string"/> - <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.cpp.compiler.option.include.paths.1648844124" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath"> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/cores/arduino}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/libraries/Flash}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/libraries/SharedSpi}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/libraries/Storage}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/libraries/Wire}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/common/utils}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/common/services/clock}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/common/services/ioport}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/drivers}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/services/flash_efc}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils/cmsis/sam4s/include}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils/header_files}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils/preprocessor}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/thirdparty/CMSIS/Include}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/variants/sam4s}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/src}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/src/Pccb}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/DuetWiFiSocketServer/src/include}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/FreeRTOS/src/include}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/FreeRTOS/src/portable/GCC/ARM_CM3}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/RRFLibraries/src}""/> - </option> - <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.cpp.compiler.option.preprocessor.def.249074867" name="Defined symbols (-D)" superClass="gnu.cpp.compiler.option.preprocessor.def" useByScannerDiscovery="false" valueType="definedSymbols"> - <listOptionValue builtIn="false" value="__SAM4S8C__"/> - <listOptionValue builtIn="false" value="RTOS"/> - <listOptionValue builtIn="false" value="PCCB"/> - <listOptionValue builtIn="false" value="PCCB_08"/> - <listOptionValue builtIn="false" value="_XOPEN_SOURCE"/> - </option> - <option id="gnu.cpp.compiler.option.dialect.std.492686215" name="Language standard" superClass="gnu.cpp.compiler.option.dialect.std" useByScannerDiscovery="true" value="gnu.cpp.compiler.dialect.default" valueType="enumerated"/> - <option id="gnu.cpp.compiler.option.dialect.flags.1059564797" name="Other dialect flags" superClass="gnu.cpp.compiler.option.dialect.flags" useByScannerDiscovery="true" value="-std=gnu++17" valueType="string"/> - <inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.58883174" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/> - </tool> - </toolChain> - </folderInfo> - <sourceEntries> - <entry excluding="src/Duet3_V06|src/Linux|src/Duet3_V05|src/Duet3_V03|src/Alligator|src/SAME70xpld|src/Display|src/Duet|src/Networking|src/Networking/ESP8266WiFi|src/Networking/LwipEthernet|src/DuetNG|src/DuetM|src/RADDS" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/> - </sourceEntries> - </configuration> - </storageModule> - <storageModule moduleId="org.eclipse.cdt.core.externalSettings"> - <externalSettings containerId="CoreNG;cdt.managedbuild.config.gnu.cross.lib.release.897729483.161018050.1509247235.1790499141.139430533" factoryId="org.eclipse.cdt.core.cfg.export.settings.sipplier"> - <externalSetting> - <entry flags="VALUE_WORKSPACE_PATH" kind="includePath" name="/CoreNG"/> - <entry flags="VALUE_WORKSPACE_PATH" kind="libraryPath" name="/CoreNG/SAM4S_RTOS"/> - <entry flags="RESOLVED" kind="libraryFile" name="CoreNG" srcPrefixMapping="" srcRootPath=""/> - </externalSetting> - </externalSettings> - <externalSettings containerId="FreeRTOS;cdt.managedbuild.config.gnu.cross.exe.release.487753828.400703681" factoryId="org.eclipse.cdt.core.cfg.export.settings.sipplier"> - <externalSetting> - <entry flags="VALUE_WORKSPACE_PATH" kind="includePath" name="/FreeRTOS"/> - <entry flags="VALUE_WORKSPACE_PATH" kind="libraryPath" name="/FreeRTOS/SAM4S"/> - <entry flags="RESOLVED" kind="libraryFile" name="FreeRTOS" srcPrefixMapping="" srcRootPath=""/> - </externalSetting> - </externalSettings> - <externalSettings containerId="RRFLibraries;cdt.managedbuild.config.gnu.cross.lib.release.1693990866.1176679643" factoryId="org.eclipse.cdt.core.cfg.export.settings.sipplier"> - <externalSetting> - <entry flags="VALUE_WORKSPACE_PATH" kind="includePath" name="/RRFLibraries"/> - <entry flags="VALUE_WORKSPACE_PATH" kind="libraryPath" name="/RRFLibraries/SAM4S"/> - <entry flags="RESOLVED" kind="libraryFile" name="RRFLibraries" srcPrefixMapping="" srcRootPath=""/> - </externalSetting> - </externalSettings> - </storageModule> - </cconfiguration> - <cconfiguration id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.170574622.649587786.1798324396.239853003"> - <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.170574622.649587786.1798324396.239853003" moduleId="org.eclipse.cdt.core.settings" name="PCCB_08_X5"> - <macros> - <stringMacro name="LinkFlags2" type="VALUE_TEXT" value="-Wl,--end-group -lm"/> - <stringMacro name="LinkFlags1" type="VALUE_TEXT" value="-mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbols -Wl,--start-group"/> - <stringMacro name="CoreName" type="VALUE_TEXT" value="CoreNG"/> - </macros> - <externalSettings/> - <extensions> - <extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/> - <extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> - <extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/> - <extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> - <extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> - <extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> - </extensions> - </storageModule> - <storageModule moduleId="cdtBuildSystem" version="4.0.0"> - <configuration artifactExtension="elf" artifactName="PccbFirmware_X5" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.170574622.649587786.1798324396.239853003" name="PCCB_08_X5" optionalBuildProperties="" parent="cdt.managedbuild.config.gnu.cross.exe.release" postannouncebuildStep="Generating binary file" postbuildStep="arm-none-eabi-objcopy -O binary "${workspace_loc:/${ProjName}/${ConfigName}}/${BuildArtifactFileBaseName}.elf" "${workspace_loc:/${ProjName}/${ConfigName}}/${BuildArtifactFileBaseName}.bin" && crc32appender "${workspace_loc:/${ProjName}/${ConfigName}}/${BuildArtifactFileBaseName}.bin""> - <folderInfo id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.170574622.649587786.1798324396.239853003." name="/" resourcePath=""> - <toolChain id="cdt.managedbuild.toolchain.gnu.cross.exe.release.2113529528" name="Cross GCC" superClass="cdt.managedbuild.toolchain.gnu.cross.exe.release"> - <option id="cdt.managedbuild.option.gnu.cross.path.1216992967" name="Path" superClass="cdt.managedbuild.option.gnu.cross.path" useByScannerDiscovery="false" value="${ArmGccPath}" valueType="string"/> - <option id="cdt.managedbuild.option.gnu.cross.prefix.2115296403" name="Prefix" superClass="cdt.managedbuild.option.gnu.cross.prefix" useByScannerDiscovery="false" value="arm-none-eabi-" valueType="string"/> - <targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.targetPlatform.gnu.cross.650998352" isAbstract="false" osList="all" superClass="cdt.managedbuild.targetPlatform.gnu.cross"/> - <builder buildPath="${workspace_loc:/RepRapFirmware}/Release" id="cdt.managedbuild.builder.gnu.cross.2109049020" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="optimal" superClass="cdt.managedbuild.builder.gnu.cross"/> - <tool id="cdt.managedbuild.tool.gnu.cross.assembler.1562151564" name="Cross GCC Assembler" superClass="cdt.managedbuild.tool.gnu.cross.assembler"> - <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.both.asm.option.include.paths.934101004" name="Include paths (-I)" superClass="gnu.both.asm.option.include.paths" valueType="includePath"> - <listOptionValue builtIn="false" value=""${workspace_loc:/RRFLibraries}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/FreeRTOS}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/CoreNG}""/> - </option> - <inputType id="cdt.managedbuild.tool.gnu.assembler.input.421833380" superClass="cdt.managedbuild.tool.gnu.assembler.input"/> - </tool> - <tool commandLinePattern="${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS}" id="cdt.managedbuild.tool.gnu.cross.c.compiler.907968158" name="Cross GCC Compiler" superClass="cdt.managedbuild.tool.gnu.cross.c.compiler"> - <option defaultValue="gnu.c.optimization.level.most" id="gnu.c.compiler.option.optimization.level.1879548421" name="Optimization Level" superClass="gnu.c.compiler.option.optimization.level" useByScannerDiscovery="false" value="gnu.c.optimization.level.more" valueType="enumerated"/> - <option id="gnu.c.compiler.option.debugging.level.1798838148" name="Debug Level" superClass="gnu.c.compiler.option.debugging.level" useByScannerDiscovery="false" value="gnu.c.debugging.level.none" valueType="enumerated"/> - <option id="gnu.c.compiler.option.misc.verbose.1017329274" name="Verbose (-v)" superClass="gnu.c.compiler.option.misc.verbose" useByScannerDiscovery="false" value="false" valueType="boolean"/> - <option id="gnu.c.compiler.option.misc.other.1392314364" name="Other flags" superClass="gnu.c.compiler.option.misc.other" useByScannerDiscovery="false" value="-c -mcpu=cortex-m4 -mthumb -ffunction-sections -fdata-sections -nostdlib -Wundef -Wdouble-promotion -fsingle-precision-constant "-Wa,-ahl=$*.s"" valueType="string"/> - <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.c.compiler.option.include.paths.712616825" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath"> - <listOptionValue builtIn="false" value=""${workspace_loc:/RRFLibraries}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/FreeRTOS}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/CoreNG}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/cores/arduino}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/libraries/Storage}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/common/utils}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/common/services/ioport}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/drivers}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils/cmsis/sam4s/include}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils/header_files}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils/preprocessor}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/thirdparty/CMSIS/Include}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/variants/sam4s}""/> - </option> - <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.c.compiler.option.preprocessor.def.symbols.1475180073" name="Defined symbols (-D)" superClass="gnu.c.compiler.option.preprocessor.def.symbols" useByScannerDiscovery="false" valueType="definedSymbols"> - <listOptionValue builtIn="false" value="__SAM4S8C__"/> - <listOptionValue builtIn="false" value="RTOS"/> - <listOptionValue builtIn="false" value="PCCB"/> - <listOptionValue builtIn="false" value="PCCB_08_X5"/> - </option> - <option id="gnu.c.compiler.option.dialect.flags.1547294696" name="Other dialect flags" superClass="gnu.c.compiler.option.dialect.flags" useByScannerDiscovery="true" value="-std=gnu99" valueType="string"/> - <inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.1120814753" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/> - </tool> - <tool id="cdt.managedbuild.tool.gnu.cross.c.linker.1936542357" name="Cross GCC Linker" superClass="cdt.managedbuild.tool.gnu.cross.c.linker"/> - <tool id="cdt.managedbuild.tool.gnu.cross.archiver.1577761657" name="Cross GCC Archiver" superClass="cdt.managedbuild.tool.gnu.cross.archiver"/> - <tool command="gcc" commandLinePattern="${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${LinkFlags1} "${workspace_loc:/${CoreName}}/SAM4S/cores/arduino/syscalls.o" ${INPUTS} ${LinkFlags2}" id="cdt.managedbuild.tool.gnu.cross.cpp.linker.523461887" name="Cross G++ Linker" superClass="cdt.managedbuild.tool.gnu.cross.cpp.linker"> - <option id="gnu.cpp.link.option.nostdlibs.1674515330" name="No startup or default libs (-nostdlib)" superClass="gnu.cpp.link.option.nostdlibs" useByScannerDiscovery="false" value="false" valueType="boolean"/> - <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.cpp.link.option.paths.144825348" name="Library search path (-L)" superClass="gnu.cpp.link.option.paths" useByScannerDiscovery="false" valueType="libPaths"> - <listOptionValue builtIn="false" value=""${workspace_loc:/CoreNG/SAM4S_PCCB/}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/FreeRTOS/SAM4S}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/RRFLibraries/SAM4S_RTOS}""/> - </option> - <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.cpp.link.option.libs.1538113275" name="Libraries (-l)" superClass="gnu.cpp.link.option.libs" useByScannerDiscovery="false" valueType="libs"> - <listOptionValue builtIn="false" value="CoreNG"/> - <listOptionValue builtIn="false" value="FreeRTOS"/> - <listOptionValue builtIn="false" value="RRFLibraries"/> - </option> - <option id="gnu.cpp.link.option.flags.1106600671" name="Linker flags" superClass="gnu.cpp.link.option.flags" useByScannerDiscovery="false" value="-Os --specs=nano.specs -Wl,--gc-sections -Wl,--fatal-warnings -mcpu=cortex-m4 -T"${workspace_loc:/${CoreName}/variants/sam4s/linker_scripts/gcc/flash.ld}" -Wl,-Map,"${workspace_loc:/${ProjName}/${ConfigName}}/${BuildArtifactFileBaseName}.map"" valueType="string"/> - <inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.180173717" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input"> - <additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/> - <additionalInput kind="additionalinput" paths="$(LIBS)"/> - </inputType> - </tool> - <tool command="g++" id="cdt.managedbuild.tool.gnu.cross.cpp.compiler.265237939" name="Cross G++ Compiler" superClass="cdt.managedbuild.tool.gnu.cross.cpp.compiler"> - <option id="gnu.cpp.compiler.option.optimization.level.1022715653" name="Optimization Level" superClass="gnu.cpp.compiler.option.optimization.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.optimization.level.more" valueType="enumerated"/> - <option id="gnu.cpp.compiler.option.debugging.level.746816525" name="Debug Level" superClass="gnu.cpp.compiler.option.debugging.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.debugging.level.none" valueType="enumerated"/> - <option id="gnu.cpp.compiler.option.other.verbose.628173646" name="Verbose (-v)" superClass="gnu.cpp.compiler.option.other.verbose" useByScannerDiscovery="false" value="false" valueType="boolean"/> - <option id="gnu.cpp.compiler.option.other.other.195351069" name="Other flags" superClass="gnu.cpp.compiler.option.other.other" useByScannerDiscovery="false" value="-c -mcpu=cortex-m4 -mthumb -ffunction-sections -fdata-sections -fno-threadsafe-statics -fno-rtti -fno-exceptions -nostdlib -Wundef -Wdouble-promotion -fsingle-precision-constant "-Wa,-ahl=$*.s"" valueType="string"/> - <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.cpp.compiler.option.include.paths.1437187820" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath"> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/cores/arduino}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/libraries/Flash}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/libraries/SharedSpi}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/libraries/Storage}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/libraries/Wire}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/common/utils}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/common/services/clock}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/common/services/ioport}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/drivers}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/services/flash_efc}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils/cmsis/sam4s/include}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils/header_files}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils/preprocessor}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/thirdparty/CMSIS/Include}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/variants/sam4s}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/src}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/src/Pccb}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/DuetWiFiSocketServer/src/include}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/FreeRTOS/src/include}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/FreeRTOS/src/portable/GCC/ARM_CM3}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/RRFLibraries/src}""/> - </option> - <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.cpp.compiler.option.preprocessor.def.900153856" name="Defined symbols (-D)" superClass="gnu.cpp.compiler.option.preprocessor.def" useByScannerDiscovery="false" valueType="definedSymbols"> - <listOptionValue builtIn="false" value="__SAM4S8C__"/> - <listOptionValue builtIn="false" value="RTOS"/> - <listOptionValue builtIn="false" value="PCCB"/> - <listOptionValue builtIn="false" value="PCCB_08_X5"/> - <listOptionValue builtIn="false" value="_XOPEN_SOURCE"/> - </option> - <option id="gnu.cpp.compiler.option.dialect.std.2047416966" name="Language standard" superClass="gnu.cpp.compiler.option.dialect.std" useByScannerDiscovery="true" value="gnu.cpp.compiler.dialect.default" valueType="enumerated"/> - <option id="gnu.cpp.compiler.option.dialect.flags.463185638" name="Other dialect flags" superClass="gnu.cpp.compiler.option.dialect.flags" useByScannerDiscovery="true" value="-std=gnu++17" valueType="string"/> - <inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.940275677" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/> - </tool> - </toolChain> - </folderInfo> - <sourceEntries> - <entry excluding="src/Duet3_V06|src/Linux|src/Duet3_V05|src/Duet3_V03|src/Alligator|src/SAME70xpld|src/Display|src/Duet|src/Networking|src/Networking/ESP8266WiFi|src/Networking/LwipEthernet|src/DuetNG|src/DuetM|src/RADDS" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/> - </sourceEntries> - </configuration> - </storageModule> - <storageModule moduleId="org.eclipse.cdt.core.externalSettings"> - <externalSettings containerId="CoreNG;cdt.managedbuild.config.gnu.cross.lib.release.897729483.161018050.1509247235" factoryId="org.eclipse.cdt.core.cfg.export.settings.sipplier"> - <externalSetting> - <entry flags="VALUE_WORKSPACE_PATH" kind="includePath" name="/CoreNG"/> - <entry flags="VALUE_WORKSPACE_PATH" kind="libraryPath" name="/CoreNG/SAM4S"/> - <entry flags="RESOLVED" kind="libraryFile" name="CoreNG" srcPrefixMapping="" srcRootPath=""/> - </externalSetting> - </externalSettings> - <externalSettings containerId="FreeRTOS;cdt.managedbuild.config.gnu.cross.exe.release.487753828.400703681" factoryId="org.eclipse.cdt.core.cfg.export.settings.sipplier"> - <externalSetting> - <entry flags="VALUE_WORKSPACE_PATH" kind="includePath" name="/FreeRTOS"/> - <entry flags="VALUE_WORKSPACE_PATH" kind="libraryPath" name="/FreeRTOS/SAM4S"/> - <entry flags="RESOLVED" kind="libraryFile" name="FreeRTOS" srcPrefixMapping="" srcRootPath=""/> - </externalSetting> - </externalSettings> - <externalSettings containerId="RRFLibraries;cdt.managedbuild.config.gnu.cross.lib.release.1693990866.1176679643" factoryId="org.eclipse.cdt.core.cfg.export.settings.sipplier"> - <externalSetting> - <entry flags="VALUE_WORKSPACE_PATH" kind="includePath" name="/RRFLibraries"/> - <entry flags="VALUE_WORKSPACE_PATH" kind="libraryPath" name="/RRFLibraries/SAM4S"/> - <entry flags="RESOLVED" kind="libraryFile" name="RRFLibraries" srcPrefixMapping="" srcRootPath=""/> - </externalSetting> - </externalSettings> - </storageModule> - </cconfiguration> - <cconfiguration id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.1275216290.274082366.1645191116.1852610203.216858457"> - <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.1275216290.274082366.1645191116.1852610203.216858457" moduleId="org.eclipse.cdt.core.settings" name="SAME70XPLD"> - <macros> - <stringMacro name="LinkFlags2" type="VALUE_TEXT" value="-Wl,--end-group -lm"/> - <stringMacro name="LinkFlags1" type="VALUE_TEXT" value="-mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbols -Wl,--start-group"/> - <stringMacro name="CoreName" type="VALUE_TEXT" value="CoreNG"/> - </macros> - <externalSettings/> - <extensions> - <extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/> - <extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> - <extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/> - <extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> - <extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> - <extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> - </extensions> - </storageModule> - <storageModule moduleId="cdtBuildSystem" version="4.0.0"> - <configuration artifactExtension="elf" artifactName="SAME70XPLDFirmware" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.1275216290.274082366.1645191116.1852610203.216858457" name="SAME70XPLD" optionalBuildProperties="org.eclipse.cdt.docker.launcher.containerbuild.property.selectedvolumes=,org.eclipse.cdt.docker.launcher.containerbuild.property.volumes=" parent="cdt.managedbuild.config.gnu.cross.exe.release" postannouncebuildStep="Generating binary file" postbuildStep="arm-none-eabi-objcopy -O binary "${workspace_loc:/${ProjName}/${ConfigName}}/${BuildArtifactFileBaseName}.elf" "${workspace_loc:/${ProjName}/${ConfigName}}/${BuildArtifactFileBaseName}.bin" && crc32appender "${workspace_loc:/${ProjName}/${ConfigName}}/${BuildArtifactFileBaseName}.bin""> - <folderInfo id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.1275216290.274082366.1645191116.1852610203.216858457." name="/" resourcePath=""> - <toolChain id="cdt.managedbuild.toolchain.gnu.cross.exe.release.1157300775" name="Cross GCC" superClass="cdt.managedbuild.toolchain.gnu.cross.exe.release"> - <option id="cdt.managedbuild.option.gnu.cross.path.2145914464" name="Path" superClass="cdt.managedbuild.option.gnu.cross.path" useByScannerDiscovery="false" value="${ArmGccPath}" valueType="string"/> - <option id="cdt.managedbuild.option.gnu.cross.prefix.777097108" name="Prefix" superClass="cdt.managedbuild.option.gnu.cross.prefix" useByScannerDiscovery="false" value="arm-none-eabi-" valueType="string"/> - <targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.targetPlatform.gnu.cross.998655674" isAbstract="false" osList="all" superClass="cdt.managedbuild.targetPlatform.gnu.cross"/> - <builder buildPath="${workspace_loc:/RepRapFirmware}/Release" id="cdt.managedbuild.builder.gnu.cross.2056908436" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="optimal" superClass="cdt.managedbuild.builder.gnu.cross"/> - <tool id="cdt.managedbuild.tool.gnu.cross.assembler.1879769012" name="Cross GCC Assembler" superClass="cdt.managedbuild.tool.gnu.cross.assembler"> - <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.both.asm.option.include.paths.1538029791" name="Include paths (-I)" superClass="gnu.both.asm.option.include.paths" valueType="includePath"> - <listOptionValue builtIn="false" value=""${workspace_loc:/RRFLibraries}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/FreeRTOS}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/CoreNG}""/> - </option> - <inputType id="cdt.managedbuild.tool.gnu.assembler.input.806612442" superClass="cdt.managedbuild.tool.gnu.assembler.input"/> - </tool> - <tool commandLinePattern="${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS}" id="cdt.managedbuild.tool.gnu.cross.c.compiler.1236802746" name="Cross GCC Compiler" superClass="cdt.managedbuild.tool.gnu.cross.c.compiler"> - <option defaultValue="gnu.c.optimization.level.most" id="gnu.c.compiler.option.optimization.level.1332086190" name="Optimization Level" superClass="gnu.c.compiler.option.optimization.level" useByScannerDiscovery="false" value="gnu.c.optimization.level.more" valueType="enumerated"/> - <option id="gnu.c.compiler.option.debugging.level.1295896937" name="Debug Level" superClass="gnu.c.compiler.option.debugging.level" useByScannerDiscovery="false" value="gnu.c.debugging.level.default" valueType="enumerated"/> - <option id="gnu.c.compiler.option.misc.verbose.264927500" name="Verbose (-v)" superClass="gnu.c.compiler.option.misc.verbose" useByScannerDiscovery="false" value="false" valueType="boolean"/> - <option id="gnu.c.compiler.option.misc.other.257975099" name="Other flags" superClass="gnu.c.compiler.option.misc.other" useByScannerDiscovery="false" value="-c -mcpu=cortex-m7 -mthumb -mfpu=fpv5-d16 -mfloat-abi=hard -ffunction-sections -fdata-sections -nostdlib -Wundef -Wdouble-promotion -fsingle-precision-constant "-Wa,-ahl=$*.s"" valueType="string"/> - <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.c.compiler.option.include.paths.1834911555" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath"> - <listOptionValue builtIn="false" value=""${workspace_loc:/RRFLibraries}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/FreeRTOS}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/CoreNG}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/cores/arduino}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/libraries/Storage}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/common/utils}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/common/services/clock}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/common/services/ioport}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/components/ethernet_phy/ksz8081rna}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/drivers/hsmci}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/drivers/gmac}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/drivers/pmc}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/drivers/rstc}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils/cmsis/same70/include}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils/header_files}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils/preprocessor}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/thirdparty/CMSIS/Include}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/variants/same70}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/src/Networking/LwipEthernet}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/src/Networking/LwipEthernet/Lwip/src/include}""/> - </option> - <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.c.compiler.option.preprocessor.def.symbols.1462879427" name="Defined symbols (-D)" superClass="gnu.c.compiler.option.preprocessor.def.symbols" useByScannerDiscovery="false" valueType="definedSymbols"> - <listOptionValue builtIn="false" value="__SAME70Q21__"/> - <listOptionValue builtIn="false" value="RTOS"/> - <listOptionValue builtIn="false" value="SAME70XPLD"/> - <listOptionValue builtIn="false" value="LWIP_GMAC_TASK=0"/> - </option> - <option id="gnu.c.compiler.option.dialect.std.1111466865" name="Language standard" superClass="gnu.c.compiler.option.dialect.std" useByScannerDiscovery="true" value="gnu.c.compiler.dialect.default" valueType="enumerated"/> - <option id="gnu.c.compiler.option.dialect.flags.22997651" name="Other dialect flags" superClass="gnu.c.compiler.option.dialect.flags" useByScannerDiscovery="true" value="-std=gnu99" valueType="string"/> - <inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.129281940" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/> - </tool> - <tool id="cdt.managedbuild.tool.gnu.cross.c.linker.642836635" name="Cross GCC Linker" superClass="cdt.managedbuild.tool.gnu.cross.c.linker"/> - <tool id="cdt.managedbuild.tool.gnu.cross.archiver.1474356143" name="Cross GCC Archiver" superClass="cdt.managedbuild.tool.gnu.cross.archiver"/> - <tool command="gcc" commandLinePattern="${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${LinkFlags1} "${workspace_loc:/${CoreName}}/SAME70/cores/arduino/syscalls.o" ${INPUTS} ${LinkFlags2}" id="cdt.managedbuild.tool.gnu.cross.cpp.linker.8484819" name="Cross G++ Linker" superClass="cdt.managedbuild.tool.gnu.cross.cpp.linker"> - <option id="gnu.cpp.link.option.nostdlibs.1515694027" name="No startup or default libs (-nostdlib)" superClass="gnu.cpp.link.option.nostdlibs" useByScannerDiscovery="false" value="false" valueType="boolean"/> - <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.cpp.link.option.paths.78806302" name="Library search path (-L)" superClass="gnu.cpp.link.option.paths" useByScannerDiscovery="false" valueType="libPaths"> - <listOptionValue builtIn="false" value=""${workspace_loc:/RRFLibraries/SAME70}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/FreeRTOS/SAME70}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/CoreNG/SAME70XPLD}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/CoreNG/SAME70XPLD/}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/RRFLibraries/SAME70_RTOS}""/> - </option> - <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.cpp.link.option.libs.1498089806" name="Libraries (-l)" superClass="gnu.cpp.link.option.libs" useByScannerDiscovery="false" valueType="libs"> - <listOptionValue builtIn="false" srcPrefixMapping="" srcRootPath="" value="RRFLibraries"/> - <listOptionValue builtIn="false" srcPrefixMapping="" srcRootPath="" value="FreeRTOS"/> - <listOptionValue builtIn="false" srcPrefixMapping="" srcRootPath="" value="CoreNG"/> - </option> - <option id="gnu.cpp.link.option.flags.1694312842" name="Linker flags" superClass="gnu.cpp.link.option.flags" useByScannerDiscovery="false" value="-Os --specs=nano.specs -Wl,--gc-sections -Wl,--fatal-warnings -mcpu=cortex-m7 -mfpu=fpv5-d16 -mfloat-abi=hard -T"${workspace_loc:/${CoreName}/variants/same70/linker_scripts/gcc/flash.ld}" -Wl,-Map,"${workspace_loc:/${ProjName}/${ConfigName}}/${BuildArtifactFileBaseName}.map"" valueType="string"/> - <inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.806549806" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input"> - <additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/> - <additionalInput kind="additionalinput" paths="$(LIBS)"/> - </inputType> - </tool> - <tool command="g++" id="cdt.managedbuild.tool.gnu.cross.cpp.compiler.1181079633" name="Cross G++ Compiler" superClass="cdt.managedbuild.tool.gnu.cross.cpp.compiler"> - <option id="gnu.cpp.compiler.option.optimization.level.2079143150" name="Optimization Level" superClass="gnu.cpp.compiler.option.optimization.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.optimization.level.more" valueType="enumerated"/> - <option id="gnu.cpp.compiler.option.debugging.level.979307845" name="Debug Level" superClass="gnu.cpp.compiler.option.debugging.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.debugging.level.default" valueType="enumerated"/> - <option id="gnu.cpp.compiler.option.other.verbose.389161357" name="Verbose (-v)" superClass="gnu.cpp.compiler.option.other.verbose" useByScannerDiscovery="false" value="false" valueType="boolean"/> - <option id="gnu.cpp.compiler.option.other.other.180760060" name="Other flags" superClass="gnu.cpp.compiler.option.other.other" useByScannerDiscovery="false" value="-c -mcpu=cortex-m7 -mthumb -mfpu=fpv5-d16 -mfloat-abi=hard -ffunction-sections -fdata-sections -fno-threadsafe-statics -fno-rtti -fno-exceptions -nostdlib -Wundef -Wdouble-promotion -fsingle-precision-constant "-Wa,-ahl=$*.s"" valueType="string"/> - <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.cpp.compiler.option.include.paths.2141723263" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath"> - <listOptionValue builtIn="false" value=""${workspace_loc:/RRFLibraries}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/FreeRTOS}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/CoreNG}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/cores/arduino}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/libraries/Flash}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/libraries/SharedSpi}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/libraries/Storage}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/libraries/Wire}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/common/utils}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/common/services/clock}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/common/services/ioport}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/components/ethernet_phy/ksz8081rna}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/drivers}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/drivers/gmac}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/services/flash_efc}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils/cmsis/same70/include}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils/header_files}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils/preprocessor}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/thirdparty/CMSIS/Include}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/variants/same70}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/src}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/src/Networking}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/src/Networking/LwipEthernet}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/src/Networking/LwipEthernet/Lwip/src/include}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/DuetWiFiSocketServer/src/include}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/FreeRTOS/src/include}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/FreeRTOS/src/portable/GCC/ARM_CM7/r0p1}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/RRFLibraries/src}""/> - </option> - <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.cpp.compiler.option.preprocessor.def.1765654706" name="Defined symbols (-D)" superClass="gnu.cpp.compiler.option.preprocessor.def" useByScannerDiscovery="false" valueType="definedSymbols"> - <listOptionValue builtIn="false" value="__SAME70Q21__"/> - <listOptionValue builtIn="false" value="RTOS"/> - <listOptionValue builtIn="false" value="SAME70XPLD"/> - <listOptionValue builtIn="false" value="LWIP_GMAC_TASK=0"/> - <listOptionValue builtIn="false" value="_XOPEN_SOURCE"/> - </option> - <option id="gnu.cpp.compiler.option.dialect.std.152869856" name="Language standard" superClass="gnu.cpp.compiler.option.dialect.std" useByScannerDiscovery="true" value="gnu.cpp.compiler.dialect.default" valueType="enumerated"/> - <option id="gnu.cpp.compiler.option.dialect.flags.1587510705" name="Other dialect flags" superClass="gnu.cpp.compiler.option.dialect.flags" useByScannerDiscovery="true" value="-std=gnu++17" valueType="string"/> - <inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.1317155683" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/> - </tool> - </toolChain> - </folderInfo> - <sourceEntries> - <entry excluding="src/Duet3_V06|src/Networking/ESP8266WiFi|src/Linux|src/Duet3_V05|src/Duet3_V03|src/Networking/LwipEthernet/Lwip/src/apps/snmp|src/Duet|src/Networking/LwipEthernet/Lwip/src/apps/httpd|/src/Networking/LwipEthernet/Lwip/test|src/DuetNG|src/Networking/LwipEthernet/Lwip/src/apps/tftp|src/Networking/W5500Ethernet|src/Alligator|src/Networking/LwipEthernet/Lwip/src/netif/ppp|src/Networking/LwipEthernet/Lwip/src/apps/lwiperf|src/Networking/LwipEthernet/Lwip/src/apps/sntp|src/Display|src/Pccb|/src/Networking/LwipEthernet/Lwip/src/apps/mqtt|src/DuetM|src/RADDS|src/Networking/LwipEthernet/Lwip/doc" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/> - </sourceEntries> - </configuration> - </storageModule> - <storageModule moduleId="org.eclipse.cdt.core.externalSettings"> - <externalSettings containerId="CoreNG;cdt.managedbuild.config.gnu.cross.lib.release.897729483.161018050.906601308.216576016" factoryId="org.eclipse.cdt.core.cfg.export.settings.sipplier"> - <externalSetting> - <entry flags="VALUE_WORKSPACE_PATH" kind="includePath" name="/CoreNG"/> - <entry flags="VALUE_WORKSPACE_PATH" kind="libraryPath" name="/CoreNG/SAME70XPLD"/> - <entry flags="RESOLVED" kind="libraryFile" name="CoreNG" srcPrefixMapping="" srcRootPath=""/> - </externalSetting> - </externalSettings> - <externalSettings containerId="FreeRTOS;cdt.managedbuild.config.gnu.cross.exe.release.487753828.694459458" factoryId="org.eclipse.cdt.core.cfg.export.settings.sipplier"> - <externalSetting> - <entry flags="VALUE_WORKSPACE_PATH" kind="includePath" name="/FreeRTOS"/> - <entry flags="VALUE_WORKSPACE_PATH" kind="libraryPath" name="/FreeRTOS/SAME70"/> - <entry flags="RESOLVED" kind="libraryFile" name="FreeRTOS" srcPrefixMapping="" srcRootPath=""/> - </externalSetting> - </externalSettings> - <externalSettings containerId="RRFLibraries;cdt.managedbuild.config.gnu.cross.lib.release.1693990866.1913177425" factoryId="org.eclipse.cdt.core.cfg.export.settings.sipplier"> - <externalSetting> - <entry flags="VALUE_WORKSPACE_PATH" kind="includePath" name="/RRFLibraries"/> - <entry flags="VALUE_WORKSPACE_PATH" kind="libraryPath" name="/RRFLibraries/SAME70"/> - <entry flags="RESOLVED" kind="libraryFile" name="RRFLibraries" srcPrefixMapping="" srcRootPath=""/> - </externalSetting> - </externalSettings> - </storageModule> - </cconfiguration> - <cconfiguration id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.1275216290.274082366.1645191116.1852610203.289083307"> - <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.1275216290.274082366.1645191116.1852610203.289083307" moduleId="org.eclipse.cdt.core.settings" name="Duet3_V05"> - <macros> - <stringMacro name="LinkFlags2" type="VALUE_TEXT" value="-Wl,--end-group -lm"/> - <stringMacro name="LinkFlags1" type="VALUE_TEXT" value="-mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbols -Wl,--start-group"/> - <stringMacro name="CoreName" type="VALUE_TEXT" value="CoreNG"/> - </macros> - <externalSettings/> - <extensions> - <extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/> - <extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> - <extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/> - <extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> - <extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> - <extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> - </extensions> - </storageModule> - <storageModule moduleId="cdtBuildSystem" version="4.0.0"> - <configuration artifactExtension="elf" artifactName="Duet3Firmware_MBP05" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.1275216290.274082366.1645191116.1852610203.289083307" name="Duet3_V05" optionalBuildProperties="org.eclipse.cdt.docker.launcher.containerbuild.property.selectedvolumes=,org.eclipse.cdt.docker.launcher.containerbuild.property.volumes=" parent="cdt.managedbuild.config.gnu.cross.exe.release" postannouncebuildStep="Generating binary file" postbuildStep="arm-none-eabi-objcopy -O binary "${workspace_loc:/${ProjName}/${ConfigName}}/${BuildArtifactFileBaseName}.elf" "${workspace_loc:/${ProjName}/${ConfigName}}/${BuildArtifactFileBaseName}.bin" && crc32appender "${workspace_loc:/${ProjName}/${ConfigName}}/${BuildArtifactFileBaseName}.bin""> - <folderInfo id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.1275216290.274082366.1645191116.1852610203.289083307." name="/" resourcePath=""> - <toolChain id="cdt.managedbuild.toolchain.gnu.cross.exe.release.1201899424" name="Cross GCC" superClass="cdt.managedbuild.toolchain.gnu.cross.exe.release"> - <option id="cdt.managedbuild.option.gnu.cross.path.2117813818" name="Path" superClass="cdt.managedbuild.option.gnu.cross.path" useByScannerDiscovery="false" value="${ArmGccPath}" valueType="string"/> - <option id="cdt.managedbuild.option.gnu.cross.prefix.62810831" name="Prefix" superClass="cdt.managedbuild.option.gnu.cross.prefix" useByScannerDiscovery="false" value="arm-none-eabi-" valueType="string"/> - <targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.targetPlatform.gnu.cross.533216740" isAbstract="false" osList="all" superClass="cdt.managedbuild.targetPlatform.gnu.cross"/> - <builder buildPath="${workspace_loc:/RepRapFirmware}/Release" id="cdt.managedbuild.builder.gnu.cross.1667192162" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="optimal" superClass="cdt.managedbuild.builder.gnu.cross"/> - <tool id="cdt.managedbuild.tool.gnu.cross.assembler.941461853" name="Cross GCC Assembler" superClass="cdt.managedbuild.tool.gnu.cross.assembler"> - <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.both.asm.option.include.paths.1223499855" name="Include paths (-I)" superClass="gnu.both.asm.option.include.paths" useByScannerDiscovery="false" valueType="includePath"> - <listOptionValue builtIn="false" value=""${workspace_loc:/RRFLibraries}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/FreeRTOS}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/CoreNG}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/CANlib}""/> - </option> - <inputType id="cdt.managedbuild.tool.gnu.assembler.input.718030965" superClass="cdt.managedbuild.tool.gnu.assembler.input"/> - </tool> - <tool commandLinePattern="${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS}" id="cdt.managedbuild.tool.gnu.cross.c.compiler.1329142859" name="Cross GCC Compiler" superClass="cdt.managedbuild.tool.gnu.cross.c.compiler"> - <option defaultValue="gnu.c.optimization.level.most" id="gnu.c.compiler.option.optimization.level.510923138" name="Optimization Level" superClass="gnu.c.compiler.option.optimization.level" useByScannerDiscovery="false" value="gnu.c.optimization.level.more" valueType="enumerated"/> - <option id="gnu.c.compiler.option.debugging.level.1838498254" name="Debug Level" superClass="gnu.c.compiler.option.debugging.level" useByScannerDiscovery="false" value="gnu.c.debugging.level.none" valueType="enumerated"/> - <option id="gnu.c.compiler.option.misc.verbose.785199087" name="Verbose (-v)" superClass="gnu.c.compiler.option.misc.verbose" useByScannerDiscovery="false" value="false" valueType="boolean"/> - <option id="gnu.c.compiler.option.misc.other.1914317039" name="Other flags" superClass="gnu.c.compiler.option.misc.other" useByScannerDiscovery="false" value="-c -mcpu=cortex-m7 -mthumb -mfpu=fpv5-d16 -mfloat-abi=hard -ffunction-sections -fdata-sections -nostdlib -Wundef -Wdouble-promotion -fsingle-precision-constant "-Wa,-ahl=$*.s"" valueType="string"/> - <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.c.compiler.option.include.paths.1116287432" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath"> - <listOptionValue builtIn="false" value=""${workspace_loc:/RRFLibraries}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/FreeRTOS}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/CoreNG}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/CANlib}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/cores/arduino}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/libraries/Storage}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/common/utils}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/common/services/clock}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/common/services/ioport}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/components/ethernet_phy/ksz8081rna}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/drivers/hsmci}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/drivers/gmac}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/drivers/pmc}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/drivers/rstc}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils/cmsis/same70/include}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils/header_files}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils/preprocessor}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/thirdparty/CMSIS/Include}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/variants/same70}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/src/Networking/LwipEthernet}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/src/Networking/LwipEthernet/Lwip/src/include}""/> - </option> - <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.c.compiler.option.preprocessor.def.symbols.132374656" name="Defined symbols (-D)" superClass="gnu.c.compiler.option.preprocessor.def.symbols" useByScannerDiscovery="false" valueType="definedSymbols"> - <listOptionValue builtIn="false" value="__SAME70Q20B__"/> - <listOptionValue builtIn="false" value="RTOS"/> - <listOptionValue builtIn="false" value="DUET3_V05"/> - <listOptionValue builtIn="false" value="LWIP_GMAC_TASK=1"/> - </option> - <option id="gnu.c.compiler.option.dialect.std.1184547155" name="Language standard" superClass="gnu.c.compiler.option.dialect.std" useByScannerDiscovery="true" value="gnu.c.compiler.dialect.default" valueType="enumerated"/> - <option id="gnu.c.compiler.option.dialect.flags.1834251763" name="Other dialect flags" superClass="gnu.c.compiler.option.dialect.flags" useByScannerDiscovery="true" value="-std=gnu99" valueType="string"/> - <inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.1364586652" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/> - </tool> - <tool id="cdt.managedbuild.tool.gnu.cross.c.linker.121136768" name="Cross GCC Linker" superClass="cdt.managedbuild.tool.gnu.cross.c.linker"/> - <tool id="cdt.managedbuild.tool.gnu.cross.archiver.1125960435" name="Cross GCC Archiver" superClass="cdt.managedbuild.tool.gnu.cross.archiver"/> - <tool command="gcc" commandLinePattern="${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${LinkFlags1} "${workspace_loc:/${CoreName}}/SAME70/cores/arduino/syscalls.o" ${INPUTS} ${LinkFlags2}" id="cdt.managedbuild.tool.gnu.cross.cpp.linker.500971768" name="Cross G++ Linker" superClass="cdt.managedbuild.tool.gnu.cross.cpp.linker"> - <option id="gnu.cpp.link.option.nostdlibs.1767130579" name="No startup or default libs (-nostdlib)" superClass="gnu.cpp.link.option.nostdlibs" useByScannerDiscovery="false" value="false" valueType="boolean"/> - <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.cpp.link.option.paths.788743762" name="Library search path (-L)" superClass="gnu.cpp.link.option.paths" useByScannerDiscovery="false" valueType="libPaths"> - <listOptionValue builtIn="false" value=""${workspace_loc:/FreeRTOS/SAME70}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/CoreNG/SAME70_DUET3V03}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/CANlib/SAME70_RTOS}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/RRFLibraries/SAME70_RTOS}""/> - </option> - <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.cpp.link.option.libs.1440094521" name="Libraries (-l)" superClass="gnu.cpp.link.option.libs" useByScannerDiscovery="false" valueType="libs"> - <listOptionValue builtIn="false" value="RRFLibraries"/> - <listOptionValue builtIn="false" value="FreeRTOS"/> - <listOptionValue builtIn="false" value="CoreNG"/> - <listOptionValue builtIn="false" value="CANlib"/> - </option> - <option id="gnu.cpp.link.option.flags.484260170" name="Linker flags" superClass="gnu.cpp.link.option.flags" useByScannerDiscovery="false" value="-Os --specs=nano.specs -Wl,--gc-sections -Wl,--fatal-warnings -mcpu=cortex-m7 -mfpu=fpv5-d16 -mfloat-abi=hard -T"${workspace_loc:/${CoreName}/variants/same70/linker_scripts/gcc/flash.ld}" -Wl,-Map,"${workspace_loc:/${ProjName}/${ConfigName}}/${BuildArtifactFileBaseName}.map"" valueType="string"/> - <inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.1531190586" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input"> - <additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/> - <additionalInput kind="additionalinput" paths="$(LIBS)"/> - </inputType> - </tool> - <tool command="g++" id="cdt.managedbuild.tool.gnu.cross.cpp.compiler.881075301" name="Cross G++ Compiler" superClass="cdt.managedbuild.tool.gnu.cross.cpp.compiler"> - <option id="gnu.cpp.compiler.option.optimization.level.992967314" name="Optimization Level" superClass="gnu.cpp.compiler.option.optimization.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.optimization.level.more" valueType="enumerated"/> - <option id="gnu.cpp.compiler.option.debugging.level.1489217051" name="Debug Level" superClass="gnu.cpp.compiler.option.debugging.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.debugging.level.none" valueType="enumerated"/> - <option id="gnu.cpp.compiler.option.other.verbose.537379981" name="Verbose (-v)" superClass="gnu.cpp.compiler.option.other.verbose" useByScannerDiscovery="false" value="false" valueType="boolean"/> - <option id="gnu.cpp.compiler.option.other.other.1413172601" name="Other flags" superClass="gnu.cpp.compiler.option.other.other" useByScannerDiscovery="false" value="-c -mcpu=cortex-m7 -mthumb -mfpu=fpv5-d16 -mfloat-abi=hard -ffunction-sections -fdata-sections -fno-threadsafe-statics -fno-rtti -fno-exceptions -nostdlib -Wundef -Wdouble-promotion -fsingle-precision-constant "-Wa,-ahl=$*.s"" valueType="string"/> - <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.cpp.compiler.option.include.paths.1340850190" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath"> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/cores/arduino}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/libraries/Flash}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/libraries/SharedSpi}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/libraries/Storage}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/libraries/Wire}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/common/utils}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/common/services/clock}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/common/services/ioport}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/components/ethernet_phy/ksz8081rna}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/drivers}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/drivers/gmac}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/services/flash_efc}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils/cmsis/same70/include}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils/header_files}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/sam/utils/preprocessor}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/asf/thirdparty/CMSIS/Include}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/variants/same70}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/src}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/src/Networking}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/src/Networking/LwipEthernet}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/src/Networking/LwipEthernet/Lwip/src/include}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/DuetWiFiSocketServer/src/include}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/FreeRTOS/src/include}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/FreeRTOS/src/portable/GCC/ARM_CM7/r0p1}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/RRFLibraries/src}""/> - <listOptionValue builtIn="false" value=""${workspace_loc:/CANlib/src}""/> - </option> - <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.cpp.compiler.option.preprocessor.def.1527120003" name="Defined symbols (-D)" superClass="gnu.cpp.compiler.option.preprocessor.def" useByScannerDiscovery="false" valueType="definedSymbols"> - <listOptionValue builtIn="false" value="__SAME70Q20B__"/> - <listOptionValue builtIn="false" value="RTOS"/> - <listOptionValue builtIn="false" value="DUET3_V05"/> - <listOptionValue builtIn="false" value="LWIP_GMAC_TASK=1"/> - <listOptionValue builtIn="false" value="_XOPEN_SOURCE"/> - </option> - <option id="gnu.cpp.compiler.option.dialect.std.264694574" name="Language standard" superClass="gnu.cpp.compiler.option.dialect.std" useByScannerDiscovery="true" value="gnu.cpp.compiler.dialect.default" valueType="enumerated"/> - <option id="gnu.cpp.compiler.option.dialect.flags.1267434221" name="Other dialect flags" superClass="gnu.cpp.compiler.option.dialect.flags" useByScannerDiscovery="true" value="-std=gnu++17" valueType="string"/> - <inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.437325627" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/> - </tool> - </toolChain> - </folderInfo> - <sourceEntries> - <entry excluding="src/Duet3_V06|src/Duet3_V03|src/Networking/ESP8266WiFi|src/SAME70xpld|src/Networking/LwipEthernet/Lwip/src/apps/snmp|src/Duet|src/Networking/LwipEthernet/Lwip/src/apps/httpd|/src/Networking/LwipEthernet/Lwip/test|src/DuetNG|src/Networking/LwipEthernet/Lwip/src/apps/tftp|src/Networking/W5500Ethernet|src/Alligator|src/Networking/LwipEthernet/Lwip/src/netif/ppp|src/Networking/LwipEthernet/Lwip/src/apps/lwiperf|src/Networking/LwipEthernet/Lwip/src/apps/sntp|src/Display|src/Pccb|/src/Networking/LwipEthernet/Lwip/src/apps/mqtt|src/DuetM|src/RADDS|src/Networking/LwipEthernet/Lwip/doc" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/> - </sourceEntries> - </configuration> - </storageModule> - <storageModule moduleId="org.eclipse.cdt.core.externalSettings"> - <externalSettings containerId="CANlib;cdt.managedbuild.config.gnu.cross.lib.release.1485070058" factoryId="org.eclipse.cdt.core.cfg.export.settings.sipplier"> - <externalSetting> - <entry flags="VALUE_WORKSPACE_PATH" kind="includePath" name="/CANlib"/> - <entry flags="VALUE_WORKSPACE_PATH" kind="libraryPath" name="/CANlib/Release"/> - <entry flags="RESOLVED" kind="libraryFile" name="CANlib" srcPrefixMapping="" srcRootPath=""/> - </externalSetting> - </externalSettings> - <externalSettings containerId="CoreNG;cdt.managedbuild.config.gnu.cross.lib.release.897729483.161018050.906601308.290747685" factoryId="org.eclipse.cdt.core.cfg.export.settings.sipplier"> - <externalSetting> - <entry flags="VALUE_WORKSPACE_PATH" kind="includePath" name="/CoreNG"/> - <entry flags="VALUE_WORKSPACE_PATH" kind="libraryPath" name="/CoreNG/SAME70_DUET3V03"/> - <entry flags="RESOLVED" kind="libraryFile" name="CoreNG" srcPrefixMapping="" srcRootPath=""/> - </externalSetting> - </externalSettings> - <externalSettings containerId="FreeRTOS;cdt.managedbuild.config.gnu.cross.exe.release.487753828.694459458" factoryId="org.eclipse.cdt.core.cfg.export.settings.sipplier"> - <externalSetting> - <entry flags="VALUE_WORKSPACE_PATH" kind="includePath" name="/FreeRTOS"/> - <entry flags="VALUE_WORKSPACE_PATH" kind="libraryPath" name="/FreeRTOS/SAME70"/> - <entry flags="RESOLVED" kind="libraryFile" name="FreeRTOS" srcPrefixMapping="" srcRootPath=""/> - </externalSetting> - </externalSettings> - <externalSettings containerId="RRFLibraries;cdt.managedbuild.config.gnu.cross.lib.release.1693990866.1913177425" factoryId="org.eclipse.cdt.core.cfg.export.settings.sipplier"> - <externalSetting> - <entry flags="VALUE_WORKSPACE_PATH" kind="includePath" name="/RRFLibraries"/> - <entry flags="VALUE_WORKSPACE_PATH" kind="libraryPath" name="/RRFLibraries/SAME70"/> - <entry flags="RESOLVED" kind="libraryFile" name="RRFLibraries" srcPrefixMapping="" srcRootPath=""/> - </externalSetting> - </externalSettings> - </storageModule> - </cconfiguration> <cconfiguration id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.170574622.649587786.1798324396.239853003.969416350"> <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.170574622.649587786.1798324396.239853003.969416350" moduleId="org.eclipse.cdt.core.settings" name="PCCB_10"> <macros> @@ -1219,7 +555,7 @@ <option id="gnu.cpp.compiler.option.optimization.level.1342318357" name="Optimization Level" superClass="gnu.cpp.compiler.option.optimization.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.optimization.level.more" valueType="enumerated"/> <option id="gnu.cpp.compiler.option.debugging.level.299293344" name="Debug Level" superClass="gnu.cpp.compiler.option.debugging.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.debugging.level.none" valueType="enumerated"/> <option id="gnu.cpp.compiler.option.other.verbose.913195266" name="Verbose (-v)" superClass="gnu.cpp.compiler.option.other.verbose" useByScannerDiscovery="false" value="false" valueType="boolean"/> - <option id="gnu.cpp.compiler.option.other.other.731452074" name="Other flags" superClass="gnu.cpp.compiler.option.other.other" useByScannerDiscovery="false" value="-c -mcpu=cortex-m4 -mthumb -ffunction-sections -fdata-sections -fno-threadsafe-statics -fno-rtti -fno-exceptions -nostdlib -Wundef -Wdouble-promotion -fsingle-precision-constant "-Wa,-ahl=$*.s"" valueType="string"/> + <option id="gnu.cpp.compiler.option.other.other.731452074" name="Other flags" superClass="gnu.cpp.compiler.option.other.other" useByScannerDiscovery="false" value="-c -mcpu=cortex-m4 -mthumb -ffunction-sections -fdata-sections -fno-threadsafe-statics -fno-rtti -fexceptions -nostdlib -Wundef -Wdouble-promotion -fsingle-precision-constant "-Wa,-ahl=$*.s"" valueType="string"/> <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.cpp.compiler.option.include.paths.1319376517" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath"> <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/cores/arduino}""/> <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/libraries/Flash}""/> @@ -1388,7 +724,7 @@ <option id="gnu.cpp.compiler.option.optimization.level.853356157" name="Optimization Level" superClass="gnu.cpp.compiler.option.optimization.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.optimization.level.more" valueType="enumerated"/> <option id="gnu.cpp.compiler.option.debugging.level.1666050145" name="Debug Level" superClass="gnu.cpp.compiler.option.debugging.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.debugging.level.none" valueType="enumerated"/> <option id="gnu.cpp.compiler.option.other.verbose.513668348" name="Verbose (-v)" superClass="gnu.cpp.compiler.option.other.verbose" useByScannerDiscovery="false" value="false" valueType="boolean"/> - <option id="gnu.cpp.compiler.option.other.other.1799333383" name="Other flags" superClass="gnu.cpp.compiler.option.other.other" useByScannerDiscovery="false" value="-c -mcpu=cortex-m7 -mthumb -mfpu=fpv5-d16 -mfloat-abi=hard -mno-unaligned-access -ffunction-sections -fdata-sections -fno-threadsafe-statics -fno-rtti -fno-exceptions -nostdlib -Wundef -Wdouble-promotion -fsingle-precision-constant "-Wa,-ahl=$*.s"" valueType="string"/> + <option id="gnu.cpp.compiler.option.other.other.1799333383" name="Other flags" superClass="gnu.cpp.compiler.option.other.other" useByScannerDiscovery="false" value="-c -mcpu=cortex-m7 -mthumb -mfpu=fpv5-d16 -mfloat-abi=hard -mno-unaligned-access -ffunction-sections -fdata-sections -fno-threadsafe-statics -fno-rtti -fexceptions -nostdlib -Wundef -Wdouble-promotion -fsingle-precision-constant "-Wa,-ahl=$*.s"" valueType="string"/> <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.cpp.compiler.option.include.paths.1493725201" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath"> <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/cores/arduino}""/> <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/libraries/Flash}""/> @@ -1554,6 +890,7 @@ <listOptionValue builtIn="false" value=""${workspace_loc:/CANlib/SAME70_RTOS_Debug}""/> </option> <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.cpp.link.option.libs.1057428376" name="Libraries (-l)" superClass="gnu.cpp.link.option.libs" useByScannerDiscovery="false" valueType="libs"> + <listOptionValue builtIn="false" value="supc++"/> <listOptionValue builtIn="false" value="CoreNG"/> <listOptionValue builtIn="false" value="FreeRTOS"/> <listOptionValue builtIn="false" value="RRFLibraries"/> @@ -1569,7 +906,7 @@ <option id="gnu.cpp.compiler.option.optimization.level.1193303866" name="Optimization Level" superClass="gnu.cpp.compiler.option.optimization.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.optimization.level.none" valueType="enumerated"/> <option id="gnu.cpp.compiler.option.debugging.level.1196186868" name="Debug Level" superClass="gnu.cpp.compiler.option.debugging.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.debugging.level.max" valueType="enumerated"/> <option id="gnu.cpp.compiler.option.other.verbose.232668458" name="Verbose (-v)" superClass="gnu.cpp.compiler.option.other.verbose" useByScannerDiscovery="false" value="false" valueType="boolean"/> - <option id="gnu.cpp.compiler.option.other.other.661193425" name="Other flags" superClass="gnu.cpp.compiler.option.other.other" useByScannerDiscovery="false" value="-c -mcpu=cortex-m7 -mthumb -mfpu=fpv5-d16 -mfloat-abi=hard -ffunction-sections -fdata-sections -fno-threadsafe-statics -fno-rtti -fno-exceptions -nostdlib -Wundef -Wdouble-promotion -fsingle-precision-constant "-Wa,-ahl=$*.s"" valueType="string"/> + <option id="gnu.cpp.compiler.option.other.other.661193425" name="Other flags" superClass="gnu.cpp.compiler.option.other.other" useByScannerDiscovery="false" value="-c -mcpu=cortex-m7 -mthumb -mfpu=fpv5-d16 -mfloat-abi=hard -ffunction-sections -fdata-sections -fno-threadsafe-statics -fno-rtti -fexceptions -nostdlib -Wundef -Wdouble-promotion -fsingle-precision-constant "-Wa,-ahl=$*.s"" valueType="string"/> <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.cpp.compiler.option.include.paths.1234657875" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath"> <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/cores/arduino}""/> <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/libraries/Flash}""/> @@ -1718,6 +1055,7 @@ <listOptionValue builtIn="false" value="__SAME70Q20B__"/> <listOptionValue builtIn="false" value="RTOS"/> <listOptionValue builtIn="false" value="DUET3_V06"/> + <listOptionValue builtIn="false" value="LWIP_GMAC_TASK=1"/> <listOptionValue builtIn="false" value="USE_CAN0"/> </option> <option id="gnu.c.compiler.option.dialect.std.1589331260" name="Language standard" superClass="gnu.c.compiler.option.dialect.std" useByScannerDiscovery="true" value="gnu.c.compiler.dialect.default" valueType="enumerated"/> @@ -1735,6 +1073,7 @@ <listOptionValue builtIn="false" value=""${workspace_loc:/RRFLibraries/SAME70_RTOS}""/> </option> <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.cpp.link.option.libs.1073394774" name="Libraries (-l)" superClass="gnu.cpp.link.option.libs" useByScannerDiscovery="false" valueType="libs"> + <listOptionValue builtIn="false" value="supc++"/> <listOptionValue builtIn="false" value="RRFLibraries"/> <listOptionValue builtIn="false" value="FreeRTOS"/> <listOptionValue builtIn="false" value="CoreNG"/> @@ -1750,7 +1089,7 @@ <option id="gnu.cpp.compiler.option.optimization.level.1733994699" name="Optimization Level" superClass="gnu.cpp.compiler.option.optimization.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.optimization.level.more" valueType="enumerated"/> <option id="gnu.cpp.compiler.option.debugging.level.977407101" name="Debug Level" superClass="gnu.cpp.compiler.option.debugging.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.debugging.level.none" valueType="enumerated"/> <option id="gnu.cpp.compiler.option.other.verbose.300036040" name="Verbose (-v)" superClass="gnu.cpp.compiler.option.other.verbose" useByScannerDiscovery="false" value="false" valueType="boolean"/> - <option id="gnu.cpp.compiler.option.other.other.1461332896" name="Other flags" superClass="gnu.cpp.compiler.option.other.other" useByScannerDiscovery="false" value="-c -mcpu=cortex-m7 -mthumb -mfpu=fpv5-d16 -mfloat-abi=hard -ffunction-sections -fdata-sections -fno-threadsafe-statics -fno-rtti -fno-exceptions -nostdlib -Wundef -Wdouble-promotion -fsingle-precision-constant "-Wa,-ahl=$*.s"" valueType="string"/> + <option id="gnu.cpp.compiler.option.other.other.1461332896" name="Other flags" superClass="gnu.cpp.compiler.option.other.other" useByScannerDiscovery="false" value="-c -mcpu=cortex-m7 -mthumb -mfpu=fpv5-d16 -mfloat-abi=hard -ffunction-sections -fdata-sections -fno-threadsafe-statics -fno-rtti -fexceptions -nostdlib -Wundef -Wdouble-promotion -fsingle-precision-constant "-Wa,-ahl=$*.s"" valueType="string"/> <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.cpp.compiler.option.include.paths.842937172" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath"> <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/cores/arduino}""/> <listOptionValue builtIn="false" value=""${workspace_loc:/${CoreName}/libraries/Flash}""/> @@ -1785,8 +1124,9 @@ <listOptionValue builtIn="false" value="__SAME70Q20B__"/> <listOptionValue builtIn="false" value="RTOS"/> <listOptionValue builtIn="false" value="DUET3_V06"/> - <listOptionValue builtIn="false" value="USE_CAN0"/> + <listOptionValue builtIn="false" value="LWIP_GMAC_TASK=1"/> <listOptionValue builtIn="false" value="_XOPEN_SOURCE"/> + <listOptionValue builtIn="false" value="USE_CAN0"/> </option> <option id="gnu.cpp.compiler.option.dialect.std.1181997841" name="Language standard" superClass="gnu.cpp.compiler.option.dialect.std" useByScannerDiscovery="true" value="gnu.cpp.compiler.dialect.default" valueType="enumerated"/> <option id="gnu.cpp.compiler.option.dialect.flags.784276622" name="Other dialect flags" superClass="gnu.cpp.compiler.option.dialect.flags" useByScannerDiscovery="true" value="-std=gnu++17" valueType="string"/> diff --git a/src/CAN/CanMessageGenericConstructor.cpp b/src/CAN/CanMessageGenericConstructor.cpp index 3a270c57..c13307c2 100644 --- a/src/CAN/CanMessageGenericConstructor.cpp +++ b/src/CAN/CanMessageGenericConstructor.cpp @@ -117,11 +117,7 @@ bool CanMessageGenericConstructor::PopulateFromCommand(GCodeBuffer& gb, const St case ParamDescriptor::char_p: { String<StringLength20> str; - if (!gb.GetQuotedString(str.GetRef())) - { - reply.printf("expected quoted string after '%c'", d->letter); - return false; - } + gb.GetQuotedString(str.GetRef()); if (str.strlen() != 1) { reply.printf("expected single-character quoted string after '%c'", d->letter); @@ -135,11 +131,7 @@ bool CanMessageGenericConstructor::PopulateFromCommand(GCodeBuffer& gb, const St case ParamDescriptor::string: { String<StringLength20> str; - if (!gb.GetQuotedString(str.GetRef())) - { - reply.printf("expected quoted string after '%c'", d->letter); - return false; - } + gb.GetQuotedString(str.GetRef()); overflowed = StoreValue(str.c_str(), str.strlen() + 1); } break; @@ -147,11 +139,7 @@ bool CanMessageGenericConstructor::PopulateFromCommand(GCodeBuffer& gb, const St case ParamDescriptor::reducedString: { String<StringLength20> str; - if (!gb.GetReducedString(str.GetRef())) - { - reply.printf("expected quoted string after '%c'", d->letter); - return false; - } + gb.GetReducedString(str.GetRef()); // We don't want port names sent to expansion boards to include the board number, so remove the board number. // We also use the reducedString type for sensor names, but they should't start with digits followed by '.'. (void)IoPort::RemoveBoardAddress(str.GetRef()); diff --git a/src/DuetM/Pins_DuetM.h b/src/DuetM/Pins_DuetM.h index e6bd13ea..4208a797 100644 --- a/src/DuetM/Pins_DuetM.h +++ b/src/DuetM/Pins_DuetM.h @@ -40,7 +40,6 @@ constexpr uint32_t IAP_IMAGE_END = 0x0047FFFF; // we allow a full 64K on #define HAS_VOLTAGE_MONITOR 1 #define ENFORCE_MAX_VIN 0 #define HAS_VREF_MONITOR 1 -#define ACTIVE_LOW_HEAT_ON 1 #define SUPPORT_INKJET 0 // set nonzero to support inkjet control #define SUPPORT_ROLAND 0 // set nonzero to support Roland mill diff --git a/src/Endstops/SwitchEndstop.cpp b/src/Endstops/SwitchEndstop.cpp index 00e0e2dd..4b000710 100644 --- a/src/Endstops/SwitchEndstop.cpp +++ b/src/Endstops/SwitchEndstop.cpp @@ -56,12 +56,7 @@ void SwitchEndstop::ReleasePorts() GCodeResult SwitchEndstop::Configure(GCodeBuffer& gb, const StringRef& reply) { String<StringLength50> portNames; - if (!gb.GetReducedString(portNames.GetRef())) - { - reply.copy("Missing port name string"); - return GCodeResult::error; - } - + gb.GetReducedString(portNames.GetRef()); return Configure(portNames.c_str(), reply); } diff --git a/src/Fans/Fan.cpp b/src/Fans/Fan.cpp index c45f602c..d9453398 100644 --- a/src/Fans/Fan.cpp +++ b/src/Fans/Fan.cpp @@ -107,9 +107,10 @@ bool Fan::Configure(unsigned int mcode, size_t fanNum, GCodeBuffer& gb, const St } } - if (gb.Seen('C') && gb.GetQuotedString(name.GetRef())) + if (gb.Seen('C')) { seen = true; + gb.GetQuotedString(name.GetRef()); } if (seen) diff --git a/src/Fans/FansManager.cpp b/src/Fans/FansManager.cpp index 7aa484b3..721c4260 100644 --- a/src/Fans/FansManager.cpp +++ b/src/Fans/FansManager.cpp @@ -96,11 +96,7 @@ GCodeResult FansManager::ConfigureFanPort(uint32_t fanNum, GCodeBuffer& gb, cons if (seenPin) { String<StringLength50> pinName; - if (!gb.GetReducedString(pinName.GetRef())) - { - reply.copy("Missing pin name"); - return GCodeResult::error; - } + gb.GetReducedString(pinName.GetRef()); WriteLocker lock(fansLock); diff --git a/src/GCodes/GCodeBuffer/BinaryParser.cpp b/src/GCodes/GCodeBuffer/BinaryParser.cpp index 870e1673..91f1a6d3 100644 --- a/src/GCodes/GCodeBuffer/BinaryParser.cpp +++ b/src/GCodes/GCodeBuffer/BinaryParser.cpp @@ -115,8 +115,7 @@ float BinaryParser::GetFValue() return value; } - INTERNAL_ERROR; - return 0.0f; + THROW_INTERNAL_ERROR; } int32_t BinaryParser::GetIValue() @@ -144,8 +143,7 @@ int32_t BinaryParser::GetIValue() return value; } - INTERNAL_ERROR; - return 0; + THROW_INTERNAL_ERROR; } uint32_t BinaryParser::GetUIValue() @@ -173,8 +171,7 @@ uint32_t BinaryParser::GetUIValue() return value; } - INTERNAL_ERROR; - return 0; + THROW_INTERNAL_ERROR; } // Get a driver ID @@ -200,24 +197,19 @@ DriverId BinaryParser::GetDriverId() return value; } - INTERNAL_ERROR; - value.Clear(); - return value; + THROW_INTERNAL_ERROR; } -bool BinaryParser::GetIPAddress(IPAddress& returnedIp) +void BinaryParser::GetIPAddress(IPAddress& returnedIp) { if (seenParameter == nullptr) { - INTERNAL_ERROR; - return false; + THROW_INTERNAL_ERROR; } if (seenParameter->type != DataType::String) { - seenParameter = nullptr; - seenParameterValue = nullptr; - return false; + throw ConstructParseException("IP address string expected"); } const char* p = seenParameterValue; @@ -229,9 +221,7 @@ bool BinaryParser::GetIPAddress(IPAddress& returnedIp) const unsigned long v = SafeStrtoul(p, &pp); if (pp == p || pp > seenParameterValue + seenParameter->intValue || v > 255) { - seenParameter = nullptr; - seenParameterValue = nullptr; - return false; + throw ConstructParseException("invalid IP address"); } ip[n] = (uint8_t)v; ++n; @@ -242,36 +232,30 @@ bool BinaryParser::GetIPAddress(IPAddress& returnedIp) } if (n == 4) { - seenParameter = nullptr; - seenParameterValue = nullptr; - return false; + throw ConstructParseException("invalid IP address"); } ++p; } seenParameter = nullptr; seenParameterValue = nullptr; - if (n == 4) + if (n != 4) { - returnedIp.SetV4(ip); - return true; + throw ConstructParseException("invalid IP address"); } - returnedIp.SetNull(); - return false; + + returnedIp.SetV4(ip); } -bool BinaryParser::GetMacAddress(uint8_t mac[6]) +void BinaryParser::GetMacAddress(uint8_t mac[6]) { if (seenParameter == nullptr) { - INTERNAL_ERROR; - return false; + THROW_INTERNAL_ERROR; } if (seenParameter->type != DataType::String) { - seenParameter = nullptr; - seenParameterValue = nullptr; - return false; + throw ConstructParseException("MAC address string expected"); } const char* p = seenParameterValue; @@ -282,9 +266,7 @@ bool BinaryParser::GetMacAddress(uint8_t mac[6]) const unsigned long v = SafeStrtoul(p, &pp, 16); if (pp == p || pp > seenParameterValue + seenParameter->intValue || v > 255) { - seenParameter = nullptr; - seenParameterValue = nullptr; - return false; + throw ConstructParseException("invalid MAC address"); } mac[n] = (uint8_t)v; ++n; @@ -295,30 +277,36 @@ bool BinaryParser::GetMacAddress(uint8_t mac[6]) } if (n == 6) { - seenParameter = nullptr; - seenParameterValue = nullptr; - return false; + throw ConstructParseException("invalid MAC address"); } ++p; } + + if (n != 6) + { + throw ConstructParseException("invalid MAC address"); + } + seenParameter = nullptr; seenParameterValue = nullptr; - return n == 6; } -bool BinaryParser::GetUnprecedentedString(const StringRef& str) +void BinaryParser::GetUnprecedentedString(const StringRef& str, bool allowEmpty) { str.Clear(); WriteParameters(str, false); - return !str.IsEmpty(); + if (!allowEmpty && str.IsEmpty()) + { + throw ConstructParseException("non-empty string expected"); + } } -bool BinaryParser::GetQuotedString(const StringRef& str) +void BinaryParser::GetQuotedString(const StringRef& str) { - return GetPossiblyQuotedString(str); + GetPossiblyQuotedString(str); } -bool BinaryParser::GetPossiblyQuotedString(const StringRef& str) +void BinaryParser::GetPossiblyQuotedString(const StringRef& str) { if (seenParameter != nullptr && (seenParameter->type == DataType::String || seenParameter->type == DataType::Expression)) { @@ -330,10 +318,13 @@ bool BinaryParser::GetPossiblyQuotedString(const StringRef& str) } seenParameter = nullptr; seenParameterValue = nullptr; - return !str.IsEmpty(); + if (str.IsEmpty()) + { + throw ConstructParseException("non-empty string expected"); + } } -bool BinaryParser::GetReducedString(const StringRef& str) +void BinaryParser::GetReducedString(const StringRef& str) { str.Clear(); if (seenParameterValue != nullptr && (seenParameter->type == DataType::String || seenParameter->type == DataType::Expression)) @@ -353,7 +344,7 @@ bool BinaryParser::GetReducedString(const StringRef& str) { seenParameter = nullptr; seenParameterValue = nullptr; - return false; + throw ConstructParseException("control character in string"); } str.cat(tolower(c)); break; @@ -363,7 +354,10 @@ bool BinaryParser::GetReducedString(const StringRef& str) seenParameter = nullptr; seenParameterValue = nullptr; - return !str.IsEmpty(); + if (str.IsEmpty()) + { + throw ConstructParseException("non-empty string expected"); + } } void BinaryParser::GetFloatArray(float arr[], size_t& length, bool doPad) @@ -386,9 +380,7 @@ void BinaryParser::GetDriverIdArray(DriverId arr[], size_t& length) { if (seenParameter == nullptr) { - INTERNAL_ERROR; - length = 0; - return; + THROW_INTERNAL_ERROR; } switch (seenParameter->type) @@ -484,9 +476,7 @@ template<typename T> void BinaryParser::GetArray(T arr[], size_t& length, bool d { if (seenParameter == nullptr) { - INTERNAL_ERROR; - length = 0; - return; + THROW_INTERNAL_ERROR; } int lastIndex = -1; @@ -648,3 +638,19 @@ void BinaryParser::WriteParameters(const StringRef& s, bool quoteStrings) const } } +ParseException BinaryParser::ConstructParseException(const char *str) const +{ + return ParseException(-1, str); +} + +ParseException BinaryParser::ConstructParseException(const char *str, const char *param) const +{ + return ParseException(-1, str, param); +} + +ParseException BinaryParser::ConstructParseException(const char *str, uint32_t param) const +{ + return ParseException(-1, str, param); +} + +// End diff --git a/src/GCodes/GCodeBuffer/BinaryParser.h b/src/GCodes/GCodeBuffer/BinaryParser.h index cfd412a7..ebfb85fb 100644 --- a/src/GCodes/GCodeBuffer/BinaryParser.h +++ b/src/GCodes/GCodeBuffer/BinaryParser.h @@ -11,6 +11,7 @@ #include "Linux/MessageFormats.h" #include "MessageType.h" #include "RepRapFirmware.h" +#include "ParseException.h" class GCodeBuffer; class IPAddress; @@ -28,20 +29,20 @@ public: int GetCommandNumber() const; int8_t GetCommandFraction() const; - float GetFValue() __attribute__((hot)); // Get a float after a key letter - int32_t GetIValue() __attribute__((hot)); // Get an integer after a key letter - uint32_t GetUIValue(); // Get an unsigned integer value - DriverId GetDriverId(); // Get a driver ID - bool GetIPAddress(IPAddress& returnedIp); // Get an IP address quad after a key letter - bool GetMacAddress(uint8_t mac[6]); // Get a MAC address sextet after a key letter - bool GetUnprecedentedString(const StringRef& str); // Get a string with no preceding key letter - bool GetQuotedString(const StringRef& str); // Get and copy a quoted string - bool GetPossiblyQuotedString(const StringRef& str); // Get and copy a string which may or may not be quoted - bool GetReducedString(const StringRef& str); // Get and copy a quoted string, removing certain characters - void GetFloatArray(float arr[], size_t& length, bool doPad) __attribute__((hot)); // Get a colon-separated list of floats after a key letter - void GetIntArray(int32_t arr[], size_t& length, bool doPad); // Get a :-separated list of ints after a key letter - void GetUnsignedArray(uint32_t arr[], size_t& length, bool doPad); // Get a :-separated list of unsigned ints after a key letter - void GetDriverIdArray(DriverId arr[], size_t& length); // Get a :-separated list of drivers after a key letter + float GetFValue() THROWS_PARSE_ERROR __attribute__((hot)); // Get a float after a key letter + int32_t GetIValue() THROWS_PARSE_ERROR __attribute__((hot)); // Get an integer after a key letter + uint32_t GetUIValue() THROWS_PARSE_ERROR; // Get an unsigned integer value + DriverId GetDriverId() THROWS_PARSE_ERROR; // Get a driver ID + void GetIPAddress(IPAddress& returnedIp) THROWS_PARSE_ERROR; // Get an IP address quad after a key letter + void GetMacAddress(uint8_t mac[6]) THROWS_PARSE_ERROR; // Get a MAC address sextet after a key letter + void GetUnprecedentedString(const StringRef& str, bool allowEmpty) THROWS_PARSE_ERROR; // Get a string with no preceding key letter + void GetQuotedString(const StringRef& str) THROWS_PARSE_ERROR; // Get and copy a quoted string + void GetPossiblyQuotedString(const StringRef& str) THROWS_PARSE_ERROR; // Get and copy a string which may or may not be quoted + void GetReducedString(const StringRef& str) THROWS_PARSE_ERROR; // Get and copy a quoted string, removing certain characters + void GetFloatArray(float arr[], size_t& length, bool doPad) THROWS_PARSE_ERROR __attribute__((hot)); // Get a colon-separated list of floats after a key letter + void GetIntArray(int32_t arr[], size_t& length, bool doPad) THROWS_PARSE_ERROR; // Get a :-separated list of ints after a key letter + void GetUnsignedArray(uint32_t arr[], size_t& length, bool doPad) THROWS_PARSE_ERROR; // Get a :-separated list of unsigned ints after a key letter + void GetDriverIdArray(DriverId arr[], size_t& length) THROWS_PARSE_ERROR; // Get a :-separated list of drivers after a key letter void SetFinished(); // Set the G Code finished @@ -54,9 +55,12 @@ public: void AppendFullCommand(const StringRef &s) const; private: - GCodeBuffer& gb; + ParseException ConstructParseException(const char *str) const; + ParseException ConstructParseException(const char *str, const char *param) const; + ParseException ConstructParseException(const char *str, uint32_t param) const; + size_t AddPadding(size_t bytesRead) const; template<typename T> void GetArray(T arr[], size_t& length, bool doPad) __attribute__((hot)); void WriteParameters(const StringRef& s, bool quoteStrings) const; diff --git a/src/GCodes/GCodeBuffer/GCodeBuffer.cpp b/src/GCodes/GCodeBuffer/GCodeBuffer.cpp index 158783d3..62b43164 100644 --- a/src/GCodes/GCodeBuffer/GCodeBuffer.cpp +++ b/src/GCodes/GCodeBuffer/GCodeBuffer.cpp @@ -13,6 +13,7 @@ #endif #include "BinaryParser.h" #include "StringParser.h" +#include "ParseException.h" #include "RepRap.h" #include "Platform.h" @@ -181,6 +182,15 @@ bool GCodeBuffer::Seen(char c) return isBinaryBuffer ? binaryParser.Seen(c) : stringParser.Seen(c); } +// Test for character present, throw error if not +void GCodeBuffer::MustSee(char c) +{ + if (!Seen(c)) + { + throw ParseException(-1, "missing parameter '%c'", (uint32_t)c); + } +} + // Get a float after a key letter float GCodeBuffer::GetFValue() { @@ -206,38 +216,80 @@ uint32_t GCodeBuffer::GetUIValue() } // Get an IP address quad after a key letter -bool GCodeBuffer::GetIPAddress(IPAddress& returnedIp) +void GCodeBuffer::GetIPAddress(IPAddress& returnedIp) { - return isBinaryBuffer ? binaryParser.GetIPAddress(returnedIp) : stringParser.GetIPAddress(returnedIp); + if (isBinaryBuffer) + { + binaryParser.GetIPAddress(returnedIp); + } + else + { + stringParser.GetIPAddress(returnedIp); + } } // Get a MAC address sextet after a key letter -bool GCodeBuffer::GetMacAddress(uint8_t mac[6]) +void GCodeBuffer::GetMacAddress(uint8_t mac[6]) { - return isBinaryBuffer ? binaryParser.GetMacAddress(mac) : stringParser.GetMacAddress(mac); + if (isBinaryBuffer) + { + binaryParser.GetMacAddress(mac); + } + else + { + stringParser.GetMacAddress(mac); + } } // Get a string with no preceding key letter -bool GCodeBuffer::GetUnprecedentedString(const StringRef& str) +void GCodeBuffer::GetUnprecedentedString(const StringRef& str, bool allowEmpty) { - return isBinaryBuffer ? binaryParser.GetUnprecedentedString(str) : stringParser.GetUnprecedentedString(str); + if (isBinaryBuffer) + { + binaryParser.GetUnprecedentedString(str, allowEmpty); + } + else + { + stringParser.GetUnprecedentedString(str, allowEmpty); + } } // Get and copy a quoted string -bool GCodeBuffer::GetQuotedString(const StringRef& str) +void GCodeBuffer::GetQuotedString(const StringRef& str) { - return isBinaryBuffer ? binaryParser.GetQuotedString(str) : stringParser.GetQuotedString(str); + if (isBinaryBuffer) + { + binaryParser.GetQuotedString(str); + } + else + { + stringParser.GetQuotedString(str); + } } // Get and copy a string which may or may not be quoted -bool GCodeBuffer::GetPossiblyQuotedString(const StringRef& str) +void GCodeBuffer::GetPossiblyQuotedString(const StringRef& str) { - return isBinaryBuffer ? binaryParser.GetPossiblyQuotedString(str) : stringParser.GetPossiblyQuotedString(str); + if (isBinaryBuffer) + { + binaryParser.GetPossiblyQuotedString(str); + } + else + { + stringParser.GetPossiblyQuotedString(str); + } } -bool GCodeBuffer::GetReducedString(const StringRef& str) +void GCodeBuffer::GetReducedString(const StringRef& str) { - return isBinaryBuffer ? binaryParser.GetReducedString(str) : stringParser.GetReducedString(str); + if (isBinaryBuffer) + { + binaryParser.GetReducedString(str); + } + else + { + stringParser.GetReducedString(str); + } } // Get a colon-separated list of floats after a key letter @@ -388,9 +440,10 @@ bool GCodeBuffer::TryGetFloatArray(char c, size_t numVals, float vals[], const S // If we found it then set 'seen' true and return true, else leave 'seen' alone and return false bool GCodeBuffer::TryGetQuotedString(char c, const StringRef& str, bool& seen) { - if (Seen(c) && GetQuotedString(str)) + if (Seen(c)) { seen = true; + GetQuotedString(str); return true; } return false; @@ -400,9 +453,10 @@ bool GCodeBuffer::TryGetQuotedString(char c, const StringRef& str, bool& seen) // If we found it then set 'seen' true and return true, else leave 'seen' alone and return false bool GCodeBuffer::TryGetPossiblyQuotedString(char c, const StringRef& str, bool& seen) { - if (Seen(c) && GetPossiblyQuotedString(str)) + if (Seen(c)) { seen = true; + GetPossiblyQuotedString(str); return true; } return false; @@ -813,10 +867,4 @@ void GCodeBuffer::AppendFullCommand(const StringRef &s) const } } -// Report a program error -void GCodeBuffer::ReportProgramError(const char *str) -{ - reprap.GetPlatform().MessageF(AddError(GetResponseMessageType()), "%s\n", str); -} - // End diff --git a/src/GCodes/GCodeBuffer/GCodeBuffer.h b/src/GCodes/GCodeBuffer/GCodeBuffer.h index 50aaa2fc..0e79c6bd 100644 --- a/src/GCodes/GCodeBuffer/GCodeBuffer.h +++ b/src/GCodes/GCodeBuffer/GCodeBuffer.h @@ -59,32 +59,34 @@ public: int8_t GetCommandFraction() const; bool Seen(char c) __attribute__((hot)); // Is a character present? - float GetFValue() __attribute__((hot)); // Get a float after a key letter - float GetDistance(); // Get a distance or coordinate and convert it from inches to mm if necessary - int32_t GetIValue() __attribute__((hot)); // Get an integer after a key letter - uint32_t GetUIValue(); // Get an unsigned integer value - bool GetIPAddress(IPAddress& returnedIp); // Get an IP address quad after a key letter - bool GetMacAddress(uint8_t mac[6]); // Get a MAC address sextet after a key letter - PwmFrequency GetPwmFrequency(); // Get a PWM frequency - float GetPwmValue(); // Get a PWM value - DriverId GetDriverId(); // Get a driver ID - bool GetUnprecedentedString(const StringRef& str); // Get a string with no preceding key letter - bool GetQuotedString(const StringRef& str); // Get and copy a quoted string - bool GetPossiblyQuotedString(const StringRef& str); // Get and copy a string which may or may not be quoted - bool GetReducedString(const StringRef& str); // Get and copy a quoted string, removing certain characters - void GetFloatArray(float arr[], size_t& length, bool doPad) __attribute__((hot)); // Get a colon-separated list of floats after a key letter - void GetIntArray(int32_t arr[], size_t& length, bool doPad); // Get a :-separated list of ints after a key letter - void GetUnsignedArray(uint32_t arr[], size_t& length, bool doPad); // Get a :-separated list of unsigned ints after a key letter - void GetDriverIdArray(DriverId arr[], size_t& length); // Get a :-separated list of drivers after a key letter - - bool TryGetFValue(char c, float& val, bool& seen); - bool TryGetIValue(char c, int32_t& val, bool& seen); - bool TryGetUIValue(char c, uint32_t& val, bool& seen); - bool TryGetBValue(char c, bool& val, bool& seen); - bool TryGetFloatArray(char c, size_t numVals, float vals[], const StringRef& reply, bool& seen, bool doPad = false); - bool TryGetUIArray(char c, size_t numVals, uint32_t vals[], const StringRef& reply, bool& seen, bool doPad = false); - bool TryGetQuotedString(char c, const StringRef& str, bool& seen); - bool TryGetPossiblyQuotedString(char c, const StringRef& str, bool& seen); + void MustSee(char c); // Test for character present, throw error if not + + float GetFValue() THROWS_PARSE_ERROR __attribute__((hot)); // Get a float after a key letter + float GetDistance() THROWS_PARSE_ERROR; // Get a distance or coordinate and convert it from inches to mm if necessary + int32_t GetIValue() THROWS_PARSE_ERROR __attribute__((hot)); // Get an integer after a key letter + uint32_t GetUIValue() THROWS_PARSE_ERROR; // Get an unsigned integer value + void GetIPAddress(IPAddress& returnedIp) THROWS_PARSE_ERROR; // Get an IP address quad after a key letter + void GetMacAddress(uint8_t mac[6]) THROWS_PARSE_ERROR; // Get a MAC address sextet after a key letter + PwmFrequency GetPwmFrequency() THROWS_PARSE_ERROR; // Get a PWM frequency + float GetPwmValue() THROWS_PARSE_ERROR; // Get a PWM value + DriverId GetDriverId() THROWS_PARSE_ERROR; // Get a driver ID + void GetUnprecedentedString(const StringRef& str, bool allowEmpty = false) THROWS_PARSE_ERROR; // Get a string with no preceding key letter + void GetQuotedString(const StringRef& str) THROWS_PARSE_ERROR; // Get and copy a quoted string + void GetPossiblyQuotedString(const StringRef& str) THROWS_PARSE_ERROR; // Get and copy a string which may or may not be quoted + void GetReducedString(const StringRef& str) THROWS_PARSE_ERROR; // Get and copy a quoted string, removing certain characters + void GetFloatArray(float arr[], size_t& length, bool doPad) THROWS_PARSE_ERROR __attribute__((hot)); // Get a colon-separated list of floats after a key letter + void GetIntArray(int32_t arr[], size_t& length, bool doPad) THROWS_PARSE_ERROR; // Get a :-separated list of ints after a key letter + void GetUnsignedArray(uint32_t arr[], size_t& length, bool doPad) THROWS_PARSE_ERROR; // Get a :-separated list of unsigned ints after a key letter + void GetDriverIdArray(DriverId arr[], size_t& length) THROWS_PARSE_ERROR; // Get a :-separated list of drivers after a key letter + + bool TryGetFValue(char c, float& val, bool& seen) THROWS_PARSE_ERROR; + bool TryGetIValue(char c, int32_t& val, bool& seen) THROWS_PARSE_ERROR; + bool TryGetUIValue(char c, uint32_t& val, bool& seen) THROWS_PARSE_ERROR; + bool TryGetBValue(char c, bool& val, bool& seen) THROWS_PARSE_ERROR; + bool TryGetFloatArray(char c, size_t numVals, float vals[], const StringRef& reply, bool& seen, bool doPad = false) THROWS_PARSE_ERROR; + bool TryGetUIArray(char c, size_t numVals, uint32_t vals[], const StringRef& reply, bool& seen, bool doPad = false) THROWS_PARSE_ERROR; + bool TryGetQuotedString(char c, const StringRef& str, bool& seen) THROWS_PARSE_ERROR; + bool TryGetPossiblyQuotedString(char c, const StringRef& str, bool& seen) THROWS_PARSE_ERROR; bool IsIdle() const; bool IsCompletelyIdle() const; @@ -169,8 +171,6 @@ public: GCodeInput *GetNormalInput() const { return normalInput; } //TEMPORARY! private: - void ReportProgramError(const char *str); - const GCodeChannel codeChannel; // Channel number of this instance GCodeInput *normalInput; // Our normal input stream, or nullptr if there isn't one diff --git a/src/GCodes/GCodeBuffer/ParseException.cpp b/src/GCodes/GCodeBuffer/ParseException.cpp new file mode 100644 index 00000000..add55b55 --- /dev/null +++ b/src/GCodes/GCodeBuffer/ParseException.cpp @@ -0,0 +1,23 @@ +/* + * ParseException.cpp + * + * Created on: 21 Dec 2019 + * Author: David + */ + +#include "ParseException.h" + +#include <General/StringRef.h> + +void ParseException::GetMessage(const StringRef &reply) const +{ + reply.copy("Parsing error"); + if (column >= 0) + { + reply.catf(" at column %d", column + 1); + } + reply.cat(": "); + reply.printf(message, param.u); +} + +// End diff --git a/src/GCodes/GCodeBuffer/ParseException.h b/src/GCodes/GCodeBuffer/ParseException.h new file mode 100644 index 00000000..66939224 --- /dev/null +++ b/src/GCodes/GCodeBuffer/ParseException.h @@ -0,0 +1,48 @@ +/* + * ParseException.h + * + * Created on: 21 Dec 2019 + * Author: David + */ + +#ifndef SRC_GCODES_PARSEEXCEPTION_H_ +#define SRC_GCODES_PARSEEXCEPTION_H_ + +#include <cstdint> + +class StringRef; + +class ParseException +{ +public: + ParseException(int col, const char *msg) : column(col), message(msg) { } + + ParseException(int col, const char *msg, const char *sparam) : column(col), message(msg) + { + param.s = sparam; + } + + ParseException(int col, const char *msg, uint32_t uparam) : column(col), message(msg) + { + param.u = uparam; + } + + ParseException(unsigned int col, const char *msg, int32_t iparam) : column(col), message(msg) + { + param.i = iparam; + } + + void GetMessage(const StringRef& reply) const; + +private: + int column; + const char *message; + union + { + int32_t i; + uint32_t u; + const char *s; + } param; +}; + +#endif /* SRC_GCODES_PARSEEXCEPTION_H_ */ diff --git a/src/GCodes/GCodeBuffer/StringParser.cpp b/src/GCodes/GCodeBuffer/StringParser.cpp index ee05cc30..d8600322 100644 --- a/src/GCodes/GCodeBuffer/StringParser.cpp +++ b/src/GCodes/GCodeBuffer/StringParser.cpp @@ -19,14 +19,14 @@ static constexpr char eofString[] = EOF_STRING; // What's at the end of an HTML file? #endif -StringParser::StringParser(GCodeBuffer& gcodeBuffer) +StringParser::StringParser(GCodeBuffer& gcodeBuffer) noexcept : gb(gcodeBuffer), fileBeingWritten(nullptr), writingFileSize(0), eofStringCounter(0), indentToSkipTo(NoIndentSkip), hasCommandNumber(false), commandLetter('Q'), checksumRequired(false), binaryWriting(false) { Init(); } -void StringParser::Init() +void StringParser::Init() noexcept { gcodeLineEnd = 0; commandLength = 0; @@ -37,7 +37,7 @@ void StringParser::Init() commandIndent = 0; } -inline void StringParser::AddToChecksum(char c) +inline void StringParser::AddToChecksum(char c) noexcept { computedChecksum ^= (uint8_t)c; } @@ -410,8 +410,7 @@ void StringParser::ProcessElseCommand(bool skippedIfFalse) } else { - gb.ReportProgramError("'else' did not follow 'if"); - indentToSkipTo = gb.machineState->indentLevel; // skip forwards to the end of the block + throw ConstructParseException("'else' did not follow 'if"); } } @@ -433,7 +432,7 @@ void StringParser::ProcessBreakCommand() { if (gb.machineState->indentLevel == 0) { - gb.ReportProgramError("'break' was not inside a loop"); + throw ConstructParseException("'break' was not inside a loop"); return; } gb.machineState->EndBlock(); @@ -443,15 +442,13 @@ void StringParser::ProcessBreakCommand() void StringParser::ProcessVarCommand() { - gb.ReportProgramError("'var' not implemented yet"); + throw ConstructParseException("'var' not implemented yet"); } // Evaluate the condition that should follow 'if' or 'while' -// If we fail, report an error and return false bool StringParser::EvaluateCondition(const char* keyword) { - reprap.GetPlatform().MessageF(AddError(gb.GetResponseMessageType()), "Failed to evaluate condition after '%s'\n", keyword); - return false; + throw ConstructParseException("Failed to evaluate condition after '%s'", keyword); } // Decode this command and find the start of the next one on the same line. @@ -587,7 +584,7 @@ void StringParser::SetFinished() } // Get the file position at the start of the current command -FilePosition StringParser::GetFilePosition() const +FilePosition StringParser::GetFilePosition() const noexcept { #if HAS_MASS_STORAGE if (gb.machineState->DoingFile()) @@ -598,19 +595,19 @@ FilePosition StringParser::GetFilePosition() const return noFilePosition; } -const char* StringParser::DataStart() const +const char* StringParser::DataStart() const noexcept { return gb.buffer + commandStart; } -size_t StringParser::DataLength() const +size_t StringParser::DataLength() const noexcept { return commandEnd - commandStart; } // Is 'c' in the G Code string? 'c' must be uppercase. -// Leave the pointer there for a subsequent read. -bool StringParser::Seen(char c) +// Leave the pointer one after it for a subsequent read. +bool StringParser::Seen(char c) noexcept { bool inQuotes = false; unsigned int inBrackets = 0; @@ -625,13 +622,14 @@ bool StringParser::Seen(char c) { if (inBrackets == 0 && toupper(b) == c && (c != 'E' || (unsigned int)readPointer == parameterStart || !isdigit(gb.buffer[readPointer - 1]))) { + ++readPointer; return true; } - if (b == '[') + if (b == '{') { ++inBrackets; } - else if (b == ']' && inBrackets != 0) + else if (b == '}' && inBrackets != 0) { --inBrackets; } @@ -644,42 +642,35 @@ bool StringParser::Seen(char c) // Get a float after a G Code letter found by a call to Seen() float StringParser::GetFValue() { - if (readPointer >= 0) + if (readPointer > 0) { - const float result = ReadFloatValue(&gb.buffer[readPointer + 1], nullptr); + const float result = ReadFloatValue(); readPointer = -1; return result; } - INTERNAL_ERROR; - return 0.0; + THROW_INTERNAL_ERROR; } // Get a colon-separated list of floats after a key letter // If doPad is true then we allow just one element to be given, in which case we fill all elements with that value void StringParser::GetFloatArray(float arr[], size_t& returnedLength, bool doPad) { - if (readPointer >= 0) + if (readPointer > 0) { size_t length = 0; - const char *p = gb.buffer + readPointer + 1; for (;;) { if (length >= returnedLength) // array limit has been set in here { - reprap.GetPlatform().MessageF(ErrorMessage, "GCodes: Attempt to read a GCode float array that is too long: %s\n", gb.buffer); - readPointer = -1; - returnedLength = 0; - return; + throw ConstructParseException("array too long, max length = %u", (uint32_t)returnedLength); } - const char *q; - arr[length] = ReadFloatValue(p, &q); - length++; - if (*q != LIST_SEPARATOR) + arr[length++] = ReadFloatValue(); + if (gb.buffer[readPointer] != LIST_SEPARATOR) { break; } - p = q + 1; + ++readPointer; } // Special case if there is one entry and returnedLength requests several. Fill the array with the first entry. @@ -699,35 +690,29 @@ void StringParser::GetFloatArray(float arr[], size_t& returnedLength, bool doPad } else { - INTERNAL_ERROR; - returnedLength = 0; + THROW_INTERNAL_ERROR; } } // Get a :-separated list of ints after a key letter void StringParser::GetIntArray(int32_t arr[], size_t& returnedLength, bool doPad) { - if (readPointer >= 0) + if (readPointer > 0) { size_t length = 0; - const char *p = gb.buffer + readPointer + 1; for (;;) { if (length >= returnedLength) // Array limit has been set in here { - reprap.GetPlatform().MessageF(ErrorMessage, "GCodes: Attempt to read a GCode int array that is too long: %s\n", gb.buffer); - readPointer = -1; - returnedLength = 0; - return; + throw ConstructParseException("array too long, max length = %u", (uint32_t)returnedLength); } - const char *q; - arr[length] = ReadIValue(p, &q); + arr[length] = ReadIValue(); length++; - if (*q != LIST_SEPARATOR) + if (gb.buffer[readPointer] != LIST_SEPARATOR) { break; } - p = q + 1; + ++readPointer; } // Special case if there is one entry and returnedLength requests several. Fill the array with the first entry. @@ -746,35 +731,29 @@ void StringParser::GetIntArray(int32_t arr[], size_t& returnedLength, bool doPad } else { - INTERNAL_ERROR; - returnedLength = 0; + THROW_INTERNAL_ERROR; } } // Get a :-separated list of unsigned ints after a key letter void StringParser::GetUnsignedArray(uint32_t arr[], size_t& returnedLength, bool doPad) { - if (readPointer >= 0) + if (readPointer > 0) { size_t length = 0; - const char *p = gb.buffer + readPointer + 1; for (;;) { if (length >= returnedLength) // Array limit has been set in here { - reprap.GetPlatform().MessageF(ErrorMessage, "GCodes: Attempt to read a GCode unsigned array that is too long: %s\n", gb.buffer); - readPointer = -1; - returnedLength = 0; - return; + throw ConstructParseException("array too long, max length = %u", (uint32_t)returnedLength); } - const char *q; - arr[length] = ReadUIValue(p, &q); + arr[length] = ReadUIValue(); length++; - if (*q != LIST_SEPARATOR) + if (gb.buffer[readPointer] != LIST_SEPARATOR) { break; } - p = q + 1; + ++readPointer; } // Special case if there is one entry and returnedLength requests several. Fill the array with the first entry. @@ -794,35 +773,29 @@ void StringParser::GetUnsignedArray(uint32_t arr[], size_t& returnedLength, bool } else { - INTERNAL_ERROR; - returnedLength = 0; + THROW_INTERNAL_ERROR; } } // Get a :-separated list of drivers after a key letter void StringParser::GetDriverIdArray(DriverId arr[], size_t& returnedLength) { - if (readPointer >= 0) + if (readPointer > 0) { size_t length = 0; - const char *p = gb.buffer + readPointer + 1; for (;;) { if (length >= returnedLength) // Array limit has been set in here { - reprap.GetPlatform().MessageF(ErrorMessage, "GCodes: Attempt to read a GCode driverID array that is too long: %s\n", gb.buffer); - readPointer = -1; - returnedLength = 0; - return; + throw ConstructParseException("array too long, max length = %u", (uint32_t)returnedLength); } - const char *q; - arr[length] = ReadDriverIdValue(p, &q); + arr[length] = ReadDriverIdValue(); length++; - if (*q != LIST_SEPARATOR) + if (gb.buffer[readPointer] != LIST_SEPARATOR) { break; } - p = q + 1; + ++readPointer; } returnedLength = length; @@ -830,39 +803,36 @@ void StringParser::GetDriverIdArray(DriverId arr[], size_t& returnedLength) } else { - INTERNAL_ERROR; - returnedLength = 0; + THROW_INTERNAL_ERROR; } } // Get and copy a quoted string returning true if successful -bool StringParser::GetQuotedString(const StringRef& str) +void StringParser::GetQuotedString(const StringRef& str) { str.Clear(); - if (readPointer >= 0) + if (readPointer > 0) { - ++readPointer; // skip the character that introduced the string switch (gb.buffer[readPointer]) { case '"': - return InternalGetQuotedString(str); + InternalGetQuotedString(str); + return; -#if SUPPORT_OBJECT_MODEL - case '[': - return GetStringExpression(str); -#endif + case '{': + GetStringExpression(str); + return; default: - return false; + throw ConstructParseException("expected string expression"); } } - INTERNAL_ERROR; - return false; + THROW_INTERNAL_ERROR; } // Given that the current character is double-quote, fetch the quoted string -bool StringParser::InternalGetQuotedString(const StringRef& str) +void StringParser::InternalGetQuotedString(const StringRef& str) { str.Clear(); ++readPointer; @@ -871,13 +841,13 @@ bool StringParser::InternalGetQuotedString(const StringRef& str) char c = gb.buffer[readPointer++]; if (c < ' ') { - return false; + throw ConstructParseException("control character in string"); } if (c == '"') { if (gb.buffer[readPointer++] != '"') { - return true; + return; } } else if (c == '\'') @@ -895,38 +865,32 @@ bool StringParser::InternalGetQuotedString(const StringRef& str) } str.cat(c); } - return false; } // Get and copy a string which may or may not be quoted. If it is not quoted, it ends at the first space or control character. -// Return true if successful. -bool StringParser::GetPossiblyQuotedString(const StringRef& str) +void StringParser::GetPossiblyQuotedString(const StringRef& str) { - if (readPointer >= 0) + if (readPointer > 0) { - ++readPointer; - return InternalGetPossiblyQuotedString(str); + InternalGetPossiblyQuotedString(str, false); } - INTERNAL_ERROR; - return false; + THROW_INTERNAL_ERROR; } // Get and copy a string which may or may not be quoted, starting at readPointer. Return true if successful. -bool StringParser::InternalGetPossiblyQuotedString(const StringRef& str) +void StringParser::InternalGetPossiblyQuotedString(const StringRef& str, bool allowEmpty) { str.Clear(); if (gb.buffer[readPointer] == '"') { - return InternalGetQuotedString(str); + InternalGetQuotedString(str); } -#if SUPPORT_OBJECT_MODEL - if (gb.buffer[readPointer] == '[') + if (gb.buffer[readPointer] == '{') { - return GetStringExpression(str); + GetStringExpression(str); } -#endif commandEnd = gcodeLineEnd; // the string is the remainder of the line of gcode for (;;) @@ -939,19 +903,21 @@ bool StringParser::InternalGetPossiblyQuotedString(const StringRef& str) str.cat(c); } str.StripTrailingSpaces(); - return !str.IsEmpty(); + if (!allowEmpty && str.IsEmpty()) + { + throw ConstructParseException("non-empty string expected"); + } } -bool StringParser::GetReducedString(const StringRef& str) +void StringParser::GetReducedString(const StringRef& str) { str.Clear(); - if (readPointer >= 0) + if (readPointer > 0) { // Reduced strings must start with a double-quote - ++readPointer; if (gb.buffer[readPointer] != '"') { - return false; + throw ConstructParseException("string expected"); } ++readPointer; @@ -963,7 +929,7 @@ bool StringParser::GetReducedString(const StringRef& str) case '"': if (gb.buffer[readPointer++] != '"') { - return true; + return; } str.cat(c); break; @@ -976,7 +942,7 @@ bool StringParser::GetReducedString(const StringRef& str) default: if (c < ' ') { - return false; + throw ConstructParseException("control characer in string"); } str.cat(tolower(c)); break; @@ -984,8 +950,7 @@ bool StringParser::GetReducedString(const StringRef& str) } } - INTERNAL_ERROR; - return false; + THROW_INTERNAL_ERROR; } // This returns a string comprising the rest of the line, excluding any comment @@ -993,7 +958,7 @@ bool StringParser::GetReducedString(const StringRef& str) // command that sets the name of a file to be printed. In // preference use GetString() which requires the string to have // been preceded by a tag letter. -bool StringParser::GetUnprecedentedString(const StringRef& str) +void StringParser::GetUnprecedentedString(const StringRef& str, bool allowEmpty) { readPointer = parameterStart; char c; @@ -1001,63 +966,58 @@ bool StringParser::GetUnprecedentedString(const StringRef& str) { ++readPointer; // skip leading spaces } - return InternalGetPossiblyQuotedString(str); + InternalGetPossiblyQuotedString(str, allowEmpty); } // Get an int32 after a G Code letter int32_t StringParser::GetIValue() { - if (readPointer >= 0) + if (readPointer > 0) { - const int32_t result = ReadIValue(&gb.buffer[readPointer + 1], nullptr); + const int32_t result = ReadIValue(); readPointer = -1; return result; } - INTERNAL_ERROR; - return 0; + THROW_INTERNAL_ERROR; } // Get an uint32 after a G Code letter uint32_t StringParser::GetUIValue() { - if (readPointer >= 0) + if (readPointer > 0) { - const uint32_t result = ReadUIValue(&gb.buffer[readPointer + 1], nullptr); + const uint32_t result = ReadUIValue(); readPointer = -1; return result; } - INTERNAL_ERROR; - return 0; + THROW_INTERNAL_ERROR; } // Get a driver ID DriverId StringParser::GetDriverId() { DriverId result; - if (readPointer >= 0) + if (readPointer > 0) { - result = ReadDriverIdValue(&gb.buffer[readPointer + 1], nullptr); + result = ReadDriverIdValue(); readPointer = -1; return result; } - INTERNAL_ERROR; - result.SetLocal(0); - return result; + THROW_INTERNAL_ERROR; } // Get an IP address quad after a key letter -bool StringParser::GetIPAddress(IPAddress& returnedIp) +void StringParser::GetIPAddress(IPAddress& returnedIp) { - if (readPointer < 0) + if (readPointer <= 0) { - INTERNAL_ERROR; - return false; + THROW_INTERNAL_ERROR; } - const char* p = &gb.buffer[readPointer + 1]; + const char* p = gb.buffer + readPointer; uint8_t ip[4]; unsigned int n = 0; for (;;) @@ -1067,7 +1027,7 @@ bool StringParser::GetIPAddress(IPAddress& returnedIp) if (pp == p || v > 255) { readPointer = -1; - return false; + throw ConstructParseException("invalid IP address"); } ip[n] = (uint8_t)v; ++n; @@ -1079,30 +1039,27 @@ bool StringParser::GetIPAddress(IPAddress& returnedIp) if (n == 4) { readPointer = -1; - return false; + throw ConstructParseException("invalid IP address"); } ++p; } readPointer = -1; - if (n == 4) + if (n != 4) { - returnedIp.SetV4(ip); - return true; + throw ConstructParseException("invalid IP address"); } - returnedIp.SetNull(); - return false; + returnedIp.SetV4(ip); } // Get a MAX address sextet after a key letter -bool StringParser::GetMacAddress(uint8_t mac[6]) +void StringParser::GetMacAddress(uint8_t mac[6]) { - if (readPointer < 0) + if (readPointer <= 0) { - INTERNAL_ERROR; - return false; + THROW_INTERNAL_ERROR; } - const char* p = gb.buffer + readPointer + 1; + const char* p = gb.buffer + readPointer; unsigned int n = 0; for (;;) { @@ -1111,7 +1068,7 @@ bool StringParser::GetMacAddress(uint8_t mac[6]) if (pp == p || v > 255) { readPointer = -1; - return false; + throw ConstructParseException("invalid MAC address"); } mac[n] = (uint8_t)v; ++n; @@ -1123,16 +1080,19 @@ bool StringParser::GetMacAddress(uint8_t mac[6]) if (n == 6) { readPointer = -1; - return false; + throw ConstructParseException("invalid MAC address"); } ++p; } readPointer = -1; - return n == 6; + if (n != 6) + { + throw ConstructParseException("invalid MAC address"); + } } // Write the command to a string -void StringParser::PrintCommand(const StringRef& s) const +void StringParser::PrintCommand(const StringRef& s) const noexcept { s.printf("%c%d", commandLetter, commandNumber); if (commandFraction >= 0) @@ -1142,7 +1102,7 @@ void StringParser::PrintCommand(const StringRef& s) const } // Append the full command content to a string -void StringParser::AppendFullCommand(const StringRef &s) const +void StringParser::AppendFullCommand(const StringRef &s) const noexcept { s.cat(gb.buffer); } @@ -1285,13 +1245,14 @@ void StringParser::FileEnded() #endif // Functions to read values from lines of GCode, allowing for expressions and variable substitution -float StringParser::ReadFloatValue(const char *p, const char **endptr) +float StringParser::ReadFloatValue() { -#if SUPPORT_OBJECT_MODEL - if (*p == '{') + ++readPointer; + if (gb.buffer[readPointer] == '{') { - ExpressionValue val; - switch (EvaluateExpression(p, endptr, val)) + ++readPointer; + const ExpressionValue val = EvaluateExpression(); + switch (val.type) { case TYPE_OF(float): return val.fVal; @@ -1303,22 +1264,19 @@ float StringParser::ReadFloatValue(const char *p, const char **endptr) return (float)val.uVal; default: - //TODO report error - return 1.0; + throw ConstructParseException("expected float value"); } } -#endif - return SafeStrtof(p, endptr); + return SafeStrtof(gb.buffer + readPointer, nullptr); } -uint32_t StringParser::ReadUIValue(const char *p, const char **endptr) +uint32_t StringParser::ReadUIValue() { -#if SUPPORT_OBJECT_MODEL - if (*p == '{') + if (gb.buffer[readPointer] == '{') { - ExpressionValue val; - switch (EvaluateExpression(p, endptr, val)) + const ExpressionValue val = EvaluateExpression(); + switch (val.type) { case TYPE_OF(uint32_t): return val.uVal; @@ -1328,37 +1286,34 @@ uint32_t StringParser::ReadUIValue(const char *p, const char **endptr) { return (uint32_t)val.iVal; } - //TODO report error - return 0; + throw ConstructParseException("value must be non-negative"); default: - //TODO report error - return 0; + throw ConstructParseException("expected non-negative integer value"); } } -#endif int base = 10; size_t skipTrailingQuote = 0; // Allow "0xNNNN" or "xNNNN" where NNNN are hex digits - if (*p == '"') + if (gb.buffer[readPointer] == '"') { - ++p; + ++readPointer; skipTrailingQuote = 1; - switch (*p) + switch (gb.buffer[readPointer]) { case 'x': case 'X': base = 16; - ++p; + ++readPointer; break; case '0': - if (*(p + 1) == 'x' || *(p + 1) == 'X') + if (gb.buffer[readPointer + 1] == 'x' || gb.buffer[readPointer + 1] == 'X') { base = 16; - p += 2; + readPointer += 2; } break; @@ -1366,18 +1321,19 @@ uint32_t StringParser::ReadUIValue(const char *p, const char **endptr) break; } } - const uint32_t result = SafeStrtoul(p, endptr, base); - endptr += skipTrailingQuote; + + const char *endptr; + const uint32_t result = SafeStrtoul(gb.buffer + readPointer, &endptr, base); + readPointer = endptr - gb.buffer + skipTrailingQuote; return result; } -int32_t StringParser::ReadIValue(const char *p, const char **endptr) +int32_t StringParser::ReadIValue() { -#if SUPPORT_OBJECT_MODEL - if (*p == '{') + if (gb.buffer[readPointer] == '{') { - ExpressionValue val; - switch (EvaluateExpression(p, endptr, val)) + ExpressionValue val = EvaluateExpression(); + switch (val.type) { case TYPE_OF(int32_t): return val.iVal; @@ -1386,24 +1342,25 @@ int32_t StringParser::ReadIValue(const char *p, const char **endptr) return (int32_t)val.uVal; default: - //TODO report error - return 0; + throw ConstructParseException("expected integer value"); } } -#endif - return SafeStrtol(p, endptr); + const char *endptr; + const int32_t val = SafeStrtol(gb.buffer + readPointer, &endptr); + readPointer = endptr - gb.buffer; + return val; } -DriverId StringParser::ReadDriverIdValue(const char *p, const char **endptr) +DriverId StringParser::ReadDriverIdValue() { DriverId result; - const char *endp; - const uint32_t v1 = ReadUIValue(p, &endp); + const uint32_t v1 = ReadUIValue(); #if SUPPORT_CAN_EXPANSION - if (*endp == '.') + if (gb.buffer[readPointer] == '.') { - const uint32_t v2 = ReadUIValue(endp + 1, &endp); + ++readPointer; + const uint32_t v2 = ReadUIValue(); result.localDriver = v2; result.boardAddress = v1; } @@ -1415,20 +1372,14 @@ DriverId StringParser::ReadDriverIdValue(const char *p, const char **endptr) #else result.localDriver = v1; #endif - if (endptr != nullptr) - { - *endptr = endp; - } return result; } -#if SUPPORT_OBJECT_MODEL - -// Get a string expression. The current character is '['. -bool StringParser::GetStringExpression(const StringRef& str) +// Get a string expression. The current character is '{'. +void StringParser::GetStringExpression(const StringRef& str) { - ExpressionValue val; - switch (EvaluateExpression(gb.buffer + readPointer, nullptr, val)) + const ExpressionValue val = EvaluateExpression(); + switch (val.type) { case TYPE_OF(const char*): str.copy(val.sVal); @@ -1463,55 +1414,161 @@ bool StringParser::GetStringExpression(const StringRef& str) break; default: - //TODO report error - return false; + throw ConstructParseException("string value expected"); } - - return true; } // Evaluate an expression. the current character is '{'. -TypeCode StringParser::EvaluateExpression(const char *p, const char **endptr, ExpressionValue& rslt) +ExpressionValue StringParser::EvaluateExpression() { - ++p; // skip the '{' + ++readPointer; // skip the '{' // For now the only form of expression we handle is {variable-name} - if (isalpha(*p)) // if it's a variable name + if (isalpha(gb.buffer[readPointer])) // if it's a variable name { - const char * const start = p; + unsigned int start = readPointer; unsigned int numBrackets = 0; - while (isalpha(*p) || isdigit(*p) || *p == '_' || *p == '.' || *p == '[' || (*p == ']' && numBrackets != 0)) + char c; + while (isalpha((c = gb.buffer[readPointer])) || isdigit(c) || c == '_' || c == '.' || c == '(' || (c == ')' && numBrackets != 0)) { - if (*p == '[') + if (c == '(') { ++numBrackets; } - else if (*p == ']') + else if (c == ')') { --numBrackets; } - ++p; + ++readPointer; } String<MaxVariableNameLength> varName; - if (varName.copy(start, p - start)) + if (varName.copy(gb.buffer + start, readPointer - start)) { - // variable name is too long - //TODO error handling - return NoType; + throw ConstructParseException("variable name too long");; } //TODO consider supporting standard CNC functions here - const TypeCode tc = reprap.GetObjectValue(rslt, varName.c_str()); - if (tc != NoType && (tc & IsArray) == 0 && *p == '}') + const ExpressionValue val = reprap.GetObjectValue(*this, varName.c_str()); + if (c != '}') + { + throw ConstructParseException("expected '}'"); + } + ++readPointer; + return val; + } + + throw ConstructParseException("expected variable name"); +} + +// Parse a number. the initial character of the string is a decimal digit. +ExpressionValue StringParser::ParseNumber() +{ + // 2. Read digits before decimal point, E or e + unsigned long valueBeforePoint = 0; + char c; + while (isdigit((c = gb.buffer[readPointer]))) + { + const unsigned int digit = c - '0'; + if (valueBeforePoint > ULONG_MAX/10 || (valueBeforePoint *= 10, valueBeforePoint > ULONG_MAX - digit)) + { + throw ConstructParseException("too many digits"); + } + valueBeforePoint += digit; + ++readPointer; + } + + // 3. Check for decimal point before E or e + unsigned long valueAfterPoint = 0; + long digitsAfterPoint = 0; + bool isFloat = (c == '.'); + if (isFloat) + { + ++readPointer; + + // 3b. Read the digits (if any) after the decimal point + while (isdigit((c = gb.buffer[readPointer]))) { - if (endptr != nullptr) + const unsigned int digit = c - '0'; + if (valueAfterPoint > ULONG_MAX/10 || (valueAfterPoint *= 10, valueAfterPoint > ULONG_MAX - digit)) { - *endptr = p + 1; + throw ConstructParseException("too many decimal digits"); } - return tc; + valueAfterPoint += digit; + ++digitsAfterPoint; + ++readPointer; + } + } + + // 5. Check for exponent part + long exponent = 0; + if (toupper(c) == 'E') + { + isFloat = true; + ++readPointer; + c = gb.buffer[readPointer]; + + // 5a. Check for signed exponent + const bool expNegative = (c == '-'); + if (expNegative || c == '+') + { + ++readPointer; + } + + // 5b. Read exponent digits + while (isdigit((c = gb.buffer[readPointer]))) + { + exponent = (10 * exponent) + (c - '0'); // could overflow, but anyone using such large numbers is being very silly + ++readPointer; + } + + if (expNegative) + { + exponent = -exponent; } } - return NoType; + + // 6. Compute the composite value + ExpressionValue retvalue; + + if (isFloat) + { + retvalue.type = TypeOf<float>(); + if (valueAfterPoint != 0) + { + if (valueBeforePoint == 0) + { + retvalue.fVal = (float)((double)valueAfterPoint * pow(10, exponent - digitsAfterPoint)); + } + else + { + retvalue.fVal = (float)(((double)valueAfterPoint/pow(10, digitsAfterPoint) + valueBeforePoint) * pow(10, exponent)); + } + } + else + { + retvalue.fVal = (float)(valueBeforePoint * pow(10, exponent)); + } + } + else + { + retvalue.type = TypeOf<uint32_t>(); + retvalue.uVal = valueBeforePoint; + } + + return retvalue; } -#endif +ParseException StringParser::ConstructParseException(const char *str) const +{ + return ParseException(readPointer, str); +} + +ParseException StringParser::ConstructParseException(const char *str, const char *param) const +{ + return ParseException(readPointer, str, param); +} + +ParseException StringParser::ConstructParseException(const char *str, uint32_t param) const +{ + return ParseException(readPointer, str, param); +} // End diff --git a/src/GCodes/GCodeBuffer/StringParser.h b/src/GCodes/GCodeBuffer/StringParser.h index 815b4d47..e0d10117 100644 --- a/src/GCodes/GCodeBuffer/StringParser.h +++ b/src/GCodes/GCodeBuffer/StringParser.h @@ -12,6 +12,7 @@ #include "GCodes/GCodeInput.h" #include "MessageType.h" #include "ObjectModel/ObjectModel.h" +#include "ParseException.h" class GCodeBuffer; class IPAddress; @@ -19,35 +20,35 @@ class IPAddress; class StringParser { public: - StringParser(GCodeBuffer& gcodeBuffer); - void Init(); // Set it up to parse another G-code - void Diagnostics(MessageType mtype); // Write some debug info + StringParser(GCodeBuffer& gcodeBuffer) noexcept; + void Init() noexcept; // Set it up to parse another G-code + void Diagnostics(MessageType mtype) noexcept; // Write some debug info bool Put(char c) __attribute__((hot)); // Add a character to the end void Put(const char *str, size_t len); // Add an entire string, overwriting any existing content void Put(const char *str); // Add a null-terminated string, overwriting any existing content void FileEnded(); // Called when we reach the end of the file we are reading from - bool Seen(char c) __attribute__((hot)); // Is a character present? - - char GetCommandLetter() const { return commandLetter; } - bool HasCommandNumber() const { return hasCommandNumber; } - int GetCommandNumber() const { return commandNumber; } - int8_t GetCommandFraction() const { return commandFraction; } - - float GetFValue() __attribute__((hot)); // Get a float after a key letter - float GetDistance(); // Get a distance or coordinate and convert it from inches to mm if necessary - int32_t GetIValue() __attribute__((hot)); // Get an integer after a key letter - uint32_t GetUIValue(); // Get an unsigned integer value - DriverId GetDriverId(); // Get a driver ID - bool GetIPAddress(IPAddress& returnedIp); // Get an IP address quad after a key letter - bool GetMacAddress(uint8_t mac[6]); // Get a MAC address sextet after a key letter - bool GetUnprecedentedString(const StringRef& str); // Get a string with no preceding key letter - bool GetQuotedString(const StringRef& str); // Get and copy a quoted string - bool GetPossiblyQuotedString(const StringRef& str); // Get and copy a string which may or may not be quoted - bool GetReducedString(const StringRef& str); // Get and copy a quoted string, removing certain characters - void GetFloatArray(float arr[], size_t& length, bool doPad) __attribute__((hot)); // Get a colon-separated list of floats after a key letter - void GetIntArray(int32_t arr[], size_t& length, bool doPad); // Get a :-separated list of ints after a key letter - void GetUnsignedArray(uint32_t arr[], size_t& length, bool doPad); // Get a :-separated list of unsigned ints after a key letter - void GetDriverIdArray(DriverId arr[], size_t& length); // Get a :-separated list of drivers after a key letter + bool Seen(char c) noexcept __attribute__((hot)); // Is a character present? + + char GetCommandLetter() const noexcept { return commandLetter; } + bool HasCommandNumber() const noexcept { return hasCommandNumber; } + int GetCommandNumber() const noexcept { return commandNumber; } + int8_t GetCommandFraction() const noexcept { return commandFraction; } + + float GetFValue() THROWS_PARSE_ERROR __attribute__((hot)); // Get a float after a key letter + float GetDistance() THROWS_PARSE_ERROR; // Get a distance or coordinate and convert it from inches to mm if necessary + int32_t GetIValue() THROWS_PARSE_ERROR __attribute__((hot)); // Get an integer after a key letter + uint32_t GetUIValue() THROWS_PARSE_ERROR; // Get an unsigned integer value + DriverId GetDriverId() THROWS_PARSE_ERROR; // Get a driver ID + void GetIPAddress(IPAddress& returnedIp) THROWS_PARSE_ERROR; // Get an IP address quad after a key letter + void GetMacAddress(uint8_t mac[6]) THROWS_PARSE_ERROR; // Get a MAC address sextet after a key letter + void GetUnprecedentedString(const StringRef& str, bool allowEmpty) THROWS_PARSE_ERROR; // Get a string with no preceding key letter + void GetQuotedString(const StringRef& str) THROWS_PARSE_ERROR; // Get and copy a quoted string + void GetPossiblyQuotedString(const StringRef& str) THROWS_PARSE_ERROR; // Get and copy a string which may or may not be quoted + void GetReducedString(const StringRef& str) THROWS_PARSE_ERROR; // Get and copy a quoted string, removing certain characters + void GetFloatArray(float arr[], size_t& length, bool doPad) THROWS_PARSE_ERROR __attribute__((hot)); // Get a colon-separated list of floats after a key letter + void GetIntArray(int32_t arr[], size_t& length, bool doPad) THROWS_PARSE_ERROR; // Get a :-separated list of ints after a key letter + void GetUnsignedArray(uint32_t arr[], size_t& length, bool doPad) THROWS_PARSE_ERROR; // Get a :-separated list of unsigned ints after a key letter + void GetDriverIdArray(DriverId arr[], size_t& length) THROWS_PARSE_ERROR; // Get a :-separated list of drivers after a key letter void SetFinished(); // Set the G Code finished void SetCommsProperties(uint32_t arg) { checksumRequired = (arg & 1); } @@ -62,30 +63,33 @@ public: void FinishWritingBinary(); #endif - FilePosition GetFilePosition() const; // Get the file position at the start of the current command + FilePosition GetFilePosition() const noexcept; // Get the file position at the start of the current command - const char* DataStart() const; // Get the start of the current command - size_t DataLength() const; // Get the length of the current command + const char* DataStart() const noexcept; // Get the start of the current command + size_t DataLength() const noexcept; // Get the length of the current command - void PrintCommand(const StringRef& s) const; - void AppendFullCommand(const StringRef &s) const; + void PrintCommand(const StringRef& s) const noexcept; + void AppendFullCommand(const StringRef &s) const noexcept; -private: + ParseException ConstructParseException(const char *str) const; + ParseException ConstructParseException(const char *str, const char *param) const; + ParseException ConstructParseException(const char *str, uint32_t param) const; +private: GCodeBuffer& gb; - void AddToChecksum(char c); + void AddToChecksum(char c) noexcept; void StoreAndAddToChecksum(char c); bool LineFinished(); // Deal with receiving end-of-line and return true if we have a command void DecodeCommand(); - bool InternalGetQuotedString(const StringRef& str) + void InternalGetQuotedString(const StringRef& str) THROWS_PARSE_ERROR pre (readPointer >= 0; gb.buffer[readPointer] == '"'; str.IsEmpty()); - bool InternalGetPossiblyQuotedString(const StringRef& str) + void InternalGetPossiblyQuotedString(const StringRef& str, bool allowEmpty) THROWS_PARSE_ERROR pre (readPointer >= 0); - float ReadFloatValue(const char *p, const char **endptr); - uint32_t ReadUIValue(const char *p, const char **endptr); - int32_t ReadIValue(const char *p, const char **endptr); - DriverId ReadDriverIdValue(const char *p, const char **endptr); + float ReadFloatValue() THROWS_PARSE_ERROR; + uint32_t ReadUIValue() THROWS_PARSE_ERROR; + int32_t ReadIValue() THROWS_PARSE_ERROR; + DriverId ReadDriverIdValue() THROWS_PARSE_ERROR; bool ProcessConditionalGCode(bool skippedIfFalse); // Check for and process a conditional GCode language command returning true if we found one void CreateBlocks(); // Create new code blocks @@ -95,14 +99,14 @@ private: void ProcessWhileCommand(); void ProcessBreakCommand(); void ProcessVarCommand(); - bool EvaluateCondition(const char* keyword); + bool EvaluateCondition(const char* keyword) THROWS_PARSE_ERROR; -#if SUPPORT_OBJECT_MODEL - bool GetStringExpression(const StringRef& str) + void GetStringExpression(const StringRef& str) THROWS_PARSE_ERROR pre (readPointer >= 0; gb.buffer[readPointer] == '{'; str.IsEmpty()); - TypeCode EvaluateExpression(const char *p, const char **endptr, ExpressionValue& rslt) + ExpressionValue EvaluateExpression() THROWS_PARSE_ERROR pre (readPointer >= 0; gb.buffer[readPointer] == '{'); -#endif + ExpressionValue ParseNumber() THROWS_PARSE_ERROR + pre(isdigit(*s)); unsigned int commandStart; // Index in the buffer of the command letter of this command unsigned int parameterStart; diff --git a/src/GCodes/GCodes.cpp b/src/GCodes/GCodes.cpp index 7188e1e0..33295463 100644 --- a/src/GCodes/GCodes.cpp +++ b/src/GCodes/GCodes.cpp @@ -2692,15 +2692,8 @@ GCodeResult GCodes::SaveHeightMap(GCodeBuffer& gb, const StringRef& reply) const if (gb.Seen('P')) { String<MaxFilenameLength> heightMapFileName; - if (gb.GetQuotedString(heightMapFileName.GetRef())) - { - return GetGCodeResultFromError(TrySaveHeightMap(heightMapFileName.c_str(), reply)); - } - else - { - reply.copy("Missing height map file name"); - return GCodeResult::error; - } + gb.GetQuotedString(heightMapFileName.GetRef()); + return GetGCodeResultFromError(TrySaveHeightMap(heightMapFileName.c_str(), reply)); } return GetGCodeResultFromError(TrySaveHeightMap(DefaultHeightMapFile, reply)); } @@ -2991,11 +2984,7 @@ GCodeResult GCodes::ManageTool(GCodeBuffer& gb, const StringRef& reply) String<ToolNameLength> name; if (gb.Seen('S')) { - if (!gb.GetQuotedString(name.GetRef())) - { - reply.copy("Invalid tool name"); - return GCodeResult::error; - } + gb.GetQuotedString(name.GetRef()); seen = true; } @@ -3487,11 +3476,7 @@ GCodeResult GCodes::LoadFilament(GCodeBuffer& gb, const StringRef& reply) if (gb.Seen('S')) { String<FilamentNameLength> filamentName; - if (!gb.GetQuotedString(filamentName.GetRef()) || filamentName.IsEmpty()) - { - reply.copy("Invalid filament name"); - return GCodeResult::error; - } + gb.GetQuotedString(filamentName.GetRef()); if (StringContains(filamentName.c_str(), ",") >= 0) { diff --git a/src/GCodes/GCodes2.cpp b/src/GCodes/GCodes2.cpp index ca2f95e4..a56db99f 100644 --- a/src/GCodes/GCodes2.cpp +++ b/src/GCodes/GCodes2.cpp @@ -10,6 +10,7 @@ #include "GCodes.h" #include "GCodeBuffer/GCodeBuffer.h" +#include "GCodeBuffer/ParseException.h" #include "GCodeQueue.h" #include "Heating/Heat.h" #include "Movement/Move.h" @@ -69,29 +70,39 @@ bool GCodes::ActOnCode(GCodeBuffer& gb, const StringRef& reply) return false; // we should queue this code but we can't, so wait until we can either execute it or queue it } - switch (gb.GetCommandLetter()) + try { - case 'G': - if (gb.HasCommandNumber()) + switch (gb.GetCommandLetter()) { - return HandleGcode(gb, reply); - } - break; + case 'G': + if (gb.HasCommandNumber()) + { + return HandleGcode(gb, reply); + } + break; - case 'M': - if (gb.HasCommandNumber()) - { - return HandleMcode(gb, reply); - } - break; + case 'M': + if (gb.HasCommandNumber()) + { + return HandleMcode(gb, reply); + } + break; - case 'T': - return HandleTcode(gb, reply); + case 'T': + return HandleTcode(gb, reply); - default: - break; + default: + break; + } + } + catch (const ParseException& e) + { + e.GetMessage(reply); + HandleReply(gb, GCodeResult::error, reply.c_str()); + return true; } + // if we get here then we didn't see a command that was worth parsing reply.printf("Bad command: "); gb.AppendFullCommand(reply); HandleReply(gb, GCodeResult::error, reply.c_str()); @@ -387,9 +398,6 @@ bool GCodes::HandleGcode(GCodeBuffer& gb, const StringRef& reply) bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) { - GCodeResult result = GCodeResult::ok; - OutputBuffer *outBuf = nullptr; - const int code = gb.GetCommandNumber(); if ( simulationMode != 0 && (code < 20 || code > 37) @@ -399,351 +407,355 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) return true; // we don't simulate most M codes } - switch (code) + OutputBuffer *outBuf = nullptr; + + try { - case 0: // Stop - case 1: // Sleep - // Don't allow M0 or M1 to stop a print, unless the print is paused or the command comes from the file being printed itself. - if (reprap.GetPrintMonitor().IsPrinting() && &gb != fileGCode && !IsPaused()) - { - reply.copy("Pause the print before attempting to cancel it"); - result = GCodeResult::error; - } - else if ( !LockMovementAndWaitForStandstill(gb) // wait until everything has stopped - || !IsCodeQueueIdle() // must also wait until deferred command queue has caught up - ) + GCodeResult result = GCodeResult::ok; + switch (code) { - return false; - } - else - { - const bool wasPaused = isPaused; // isPaused gets cleared by CancelPrint - const bool wasSimulating = IsSimulating(); // simulationMode may get cleared by CancelPrint - isWaiting = cancelWait = false; // we may have been waiting for temperatures to be reached - StopPrint((&gb == fileGCode) ? StopPrintReason::normalCompletion : StopPrintReason::userCancelled); - - if (!wasSimulating) // don't run any macro files or turn heaters off etc. if we were simulating before we stopped the print + case 0: // Stop + case 1: // Sleep + // Don't allow M0 or M1 to stop a print, unless the print is paused or the command comes from the file being printed itself. + if (reprap.GetPrintMonitor().IsPrinting() && &gb != fileGCode && !IsPaused()) { - // If we are cancelling a paused print with M0 and we are homed and cancel.g exists then run it and do nothing else - if (wasPaused && code == 0 && AllAxesAreHomed() && DoFileMacro(gb, CANCEL_G, false, 0)) + reply.copy("Pause the print before attempting to cancel it"); + result = GCodeResult::error; + } + else if ( !LockMovementAndWaitForStandstill(gb) // wait until everything has stopped + || !IsCodeQueueIdle() // must also wait until deferred command queue has caught up + ) + { + return false; + } + else + { + const bool wasPaused = isPaused; // isPaused gets cleared by CancelPrint + const bool wasSimulating = IsSimulating(); // simulationMode may get cleared by CancelPrint + isWaiting = cancelWait = false; // we may have been waiting for temperatures to be reached + StopPrint((&gb == fileGCode) ? StopPrintReason::normalCompletion : StopPrintReason::userCancelled); + + if (!wasSimulating) // don't run any macro files or turn heaters off etc. if we were simulating before we stopped the print { - break; - } + // If we are cancelling a paused print with M0 and we are homed and cancel.g exists then run it and do nothing else + if (wasPaused && code == 0 && AllAxesAreHomed() && DoFileMacro(gb, CANCEL_G, false, 0)) + { + break; + } - const bool leaveHeatersOn = (gb.Seen('H') && gb.GetIValue() > 0); - gb.SetState((leaveHeatersOn) ? GCodeState::stoppingWithHeatersOn : GCodeState::stoppingWithHeatersOff); - (void)DoFileMacro(gb, (code == 0) ? STOP_G : SLEEP_G, false, code); + const bool leaveHeatersOn = (gb.Seen('H') && gb.GetIValue() > 0); + gb.SetState((leaveHeatersOn) ? GCodeState::stoppingWithHeatersOn : GCodeState::stoppingWithHeatersOff); + (void)DoFileMacro(gb, (code == 0) ? STOP_G : SLEEP_G, false, code); + } } - } - break; + break; - case 3: // Spin spindle clockwise - { - const uint32_t slot = gb.Seen('P') ? gb.GetUIValue() : 0; - if (slot >= MaxSpindles && machineType == MachineType::cnc) - { - reply.copy("Invalid spindle index"); - result = GCodeResult::error; - } - else if (gb.Seen('S')) + case 3: // Spin spindle clockwise { - switch (machineType) + const uint32_t slot = gb.Seen('P') ? gb.GetUIValue() : 0; + if (slot >= MaxSpindles && machineType == MachineType::cnc) { - case MachineType::cnc: - platform.AccessSpindle(slot).SetRpm(gb.GetFValue()); - break; + reply.copy("Invalid spindle index"); + result = GCodeResult::error; + } + else if (gb.Seen('S')) + { + switch (machineType) + { + case MachineType::cnc: + platform.AccessSpindle(slot).SetRpm(gb.GetFValue()); + break; #if SUPPORT_LASER - case MachineType::laser: - moveBuffer.laserPwmOrIoBits.laserPwm = ConvertLaserPwm(gb.GetFValue()); - break; + case MachineType::laser: + moveBuffer.laserPwmOrIoBits.laserPwm = ConvertLaserPwm(gb.GetFValue()); + break; #endif - default: + default: #if SUPPORT_ROLAND - if (reprap.GetRoland()->Active()) + if (reprap.GetRoland()->Active()) + { + result = reprap.GetRoland()->ProcessSpindle(gb.GetFValue()); + } + else +#endif + { + result = GCodeResult::notSupportedInCurrentMode; + } + break; + } + } + else if (machineType == MachineType::cnc && gb.Seen('R')) + { + const unsigned int rpNumber = gb.GetUIValue(); + if (rpNumber >= NumRestorePoints) { - result = reprap.GetRoland()->ProcessSpindle(gb.GetFValue()); + reply.copy("Invalid restore point number"); + result = GCodeResult::error; } else -#endif { - result = GCodeResult::notSupportedInCurrentMode; + platform.AccessSpindle(slot).SetRpm(numberedRestorePoints[rpNumber].spindleSpeeds[slot]); } - break; } } - else if (machineType == MachineType::cnc && gb.Seen('R')) + break; + + case 4: // Spin spindle counter clockwise + if (gb.Seen('S')) { - const unsigned int rpNumber = gb.GetUIValue(); - if (rpNumber >= NumRestorePoints) + if (machineType == MachineType::cnc) { - reply.copy("Invalid restore point number"); - result = GCodeResult::error; + const float rpm = gb.GetFValue(); + const uint32_t slot = gb.Seen('P') ? gb.GetUIValue() : 0; + if (slot >= MaxSpindles) + { + reply.copy("Invalid spindle index"); + result = GCodeResult::error; + } + else + { + platform.AccessSpindle(slot).SetRpm(-rpm); + } } else { - platform.AccessSpindle(slot).SetRpm(numberedRestorePoints[rpNumber].spindleSpeeds[slot]); + result = GCodeResult::notSupportedInCurrentMode; } } - } - break; + break; - case 4: // Spin spindle counter clockwise - if (gb.Seen('S')) - { - if (machineType == MachineType::cnc) + case 5: // Spindle motor off + switch (machineType) { - const float rpm = gb.GetFValue(); - const uint32_t slot = gb.Seen('P') ? gb.GetUIValue() : 0; - if (slot >= MaxSpindles) + case MachineType::cnc: + if (gb.Seen('P')) { - reply.copy("Invalid spindle index"); - result = GCodeResult::error; + // Turn off specific spindle + const uint32_t slot = gb.GetUIValue(); + if (slot >= MaxSpindles) + { + reply.copy("Invalid spindle index"); + result = GCodeResult::error; + } + else + { + platform.AccessSpindle(slot).TurnOff(); + } } else { - platform.AccessSpindle(slot).SetRpm(-rpm); + // Turn off every spindle if no 'P' parameter is present + for (size_t i = 0; i < MaxSpindles; i++) + { + platform.AccessSpindle(i).TurnOff(); + } } - } - else - { - result = GCodeResult::notSupportedInCurrentMode; - } - } - break; + break; - case 5: // Spindle motor off - switch (machineType) - { - case MachineType::cnc: - if (gb.Seen('P')) - { - // Turn off specific spindle - const uint32_t slot = gb.GetUIValue(); - if (slot >= MaxSpindles) + #if SUPPORT_LASER + case MachineType::laser: + moveBuffer.laserPwmOrIoBits.Clear(); + break; +#endif + + default: +#if SUPPORT_ROLAND + if (reprap.GetRoland()->Active()) { - reply.copy("Invalid spindle index"); - result = GCodeResult::error; + result = reprap.GetRoland()->ProcessSpindle(0.0); } else +#endif { - platform.AccessSpindle(slot).TurnOff(); - } - } - else - { - // Turn off every spindle if no 'P' parameter is present - for (size_t i = 0; i < MaxSpindles; i++) - { - platform.AccessSpindle(i).TurnOff(); + result = GCodeResult::notSupportedInCurrentMode; } + break; } break; -#if SUPPORT_LASER - case MachineType::laser: - moveBuffer.laserPwmOrIoBits.Clear(); - break; -#endif - - default: -#if SUPPORT_ROLAND - if (reprap.GetRoland()->Active()) + case 18: // Motors off + case 84: + if (!LockMovementAndWaitForStandstill(gb)) { - result = reprap.GetRoland()->ProcessSpindle(0.0); + return false; } - else -#endif { - result = GCodeResult::notSupportedInCurrentMode; - } - break; - } - break; + bool seen = false; + for (size_t axis = 0; axis < numTotalAxes; axis++) + { + if (gb.Seen(axisLetters[axis])) + { + SetAxisNotHomed(axis); + platform.DisableDrivers(axis); + seen = true; + } + } - case 18: // Motors off - case 84: - if (!LockMovementAndWaitForStandstill(gb)) - { - return false; - } - { - bool seen = false; - for (size_t axis = 0; axis < numTotalAxes; axis++) - { - if (gb.Seen(axisLetters[axis])) + if (gb.Seen(extrudeLetter)) { - SetAxisNotHomed(axis); - platform.DisableDrivers(axis); - seen = true; + uint32_t eDrive[MaxExtruders]; + size_t eCount = numExtruders; + gb.GetUnsignedArray(eDrive, eCount, false); + for (size_t i = 0; i < eCount; i++) + { + seen = true; + if (eDrive[i] >= numExtruders) + { + reply.printf("Invalid extruder number specified: %" PRIu32, eDrive[i]); + result = GCodeResult::error; + break; + } + platform.DisableDrivers(ExtruderToLogicalDrive(eDrive[i])); + } } - } - if (gb.Seen(extrudeLetter)) - { - uint32_t eDrive[MaxExtruders]; - size_t eCount = numExtruders; - gb.GetUnsignedArray(eDrive, eCount, false); - for (size_t i = 0; i < eCount; i++) + if (gb.Seen('S')) { seen = true; - if (eDrive[i] >= numExtruders) + + const float idleTimeout = gb.GetFValue(); + if (idleTimeout < 0.0) { - reply.printf("Invalid extruder number specified: %" PRIu32, eDrive[i]); + reply.copy("Idle timeouts cannot be negative"); result = GCodeResult::error; - break; } - platform.DisableDrivers(ExtruderToLogicalDrive(eDrive[i])); + else + { + reprap.GetMove().SetIdleTimeout(idleTimeout); + } } - } - - if (gb.Seen('S')) - { - seen = true; - const float idleTimeout = gb.GetFValue(); - if (idleTimeout < 0.0) - { - reply.copy("Idle timeouts cannot be negative"); - result = GCodeResult::error; - } - else + if (!seen) { - reprap.GetMove().SetIdleTimeout(idleTimeout); + DisableDrives(); } } - - if (!seen) - { - DisableDrives(); - } - } - break; + break; #if HAS_MASS_STORAGE - case 20: // List files on SD card - if (!LockFileSystem(gb)) // don't allow more than one at a time to avoid contention on output buffers - { - return false; - } - { - const int sparam = (gb.Seen('S')) ? gb.GetIValue() : 0; - const unsigned int rparam = (gb.Seen('R')) ? gb.GetUIValue() : 0; - String<MaxFilenameLength> dir; - if (gb.Seen('P')) - { - gb.GetPossiblyQuotedString(dir.GetRef()); - } - else + case 20: // List files on SD card + if (!LockFileSystem(gb)) // don't allow more than one at a time to avoid contention on output buffers { - dir.copy(platform.GetGCodeDir()); + return false; } - - if (sparam == 2) { - outBuf = reprap.GetFilesResponse(dir.c_str(), rparam, true); // send the file list in JSON format - if (outBuf == nullptr) + const int sparam = (gb.Seen('S')) ? gb.GetIValue() : 0; + const unsigned int rparam = (gb.Seen('R')) ? gb.GetUIValue() : 0; + String<MaxFilenameLength> dir; + if (gb.Seen('P')) { - return false; + gb.GetPossiblyQuotedString(dir.GetRef()); } - outBuf->cat('\n'); - } - else if (sparam == 3) - { - outBuf = reprap.GetFilelistResponse(dir.c_str(), rparam); - if (outBuf == nullptr) + else { - return false; + dir.copy(platform.GetGCodeDir()); } - outBuf->cat('\n'); - } - else - { - if (!OutputBuffer::Allocate(outBuf)) + + if (sparam == 2) { - return false; // cannot allocate an output buffer, try again later + outBuf = reprap.GetFilesResponse(dir.c_str(), rparam, true); // send the file list in JSON format + if (outBuf == nullptr) + { + return false; + } + outBuf->cat('\n'); } - - // To mimic the behaviour of the official RepRapPro firmware: - // If we are emulating RepRap then we print "GCode files:\n" at the start, otherwise we don't. - // If we are emulating Marlin and the code came via the serial/USB interface, then we don't put quotes around the names and we separate them with newline; - // otherwise we put quotes around them and separate them with comma. - if (gb.MachineState().compatibility == Compatibility::me || gb.MachineState().compatibility == Compatibility::reprapFirmware) + else if (sparam == 3) { - outBuf->copy("GCode files:\n"); + outBuf = reprap.GetFilelistResponse(dir.c_str(), rparam); + if (outBuf == nullptr) + { + return false; + } + outBuf->cat('\n'); } - - bool encapsulateList = gb.MachineState().compatibility != Compatibility::marlin; - FileInfo fileInfo; - if (MassStorage::FindFirst(dir.c_str(), fileInfo)) + else { - // iterate through all entries and append each file name - do { + if (!OutputBuffer::Allocate(outBuf)) + { + return false; // cannot allocate an output buffer, try again later + } + + // To mimic the behaviour of the official RepRapPro firmware: + // If we are emulating RepRap then we print "GCode files:\n" at the start, otherwise we don't. + // If we are emulating Marlin and the code came via the serial/USB interface, then we don't put quotes around the names and we separate them with newline; + // otherwise we put quotes around them and separate them with comma. + if (gb.MachineState().compatibility == Compatibility::me || gb.MachineState().compatibility == Compatibility::reprapFirmware) + { + outBuf->copy("GCode files:\n"); + } + + bool encapsulateList = gb.MachineState().compatibility != Compatibility::marlin; + FileInfo fileInfo; + if (MassStorage::FindFirst(dir.c_str(), fileInfo)) + { + // iterate through all entries and append each file name + do { + if (encapsulateList) + { + outBuf->catf("%c%s%c%c", FILE_LIST_BRACKET, fileInfo.fileName.c_str(), FILE_LIST_BRACKET, FILE_LIST_SEPARATOR); + } + else + { + outBuf->catf("%s\n", fileInfo.fileName.c_str()); + } + } while (MassStorage::FindNext(fileInfo)); + if (encapsulateList) { - outBuf->catf("%c%s%c%c", FILE_LIST_BRACKET, fileInfo.fileName.c_str(), FILE_LIST_BRACKET, FILE_LIST_SEPARATOR); + // remove the last separator + (*outBuf)[outBuf->Length() - 1] = 0; } - else - { - outBuf->catf("%s\n", fileInfo.fileName.c_str()); - } - } while (MassStorage::FindNext(fileInfo)); - - if (encapsulateList) + } + else { - // remove the last separator - (*outBuf)[outBuf->Length() - 1] = 0; + outBuf->cat("NONE\n"); } } - else - { - outBuf->cat("NONE\n"); - } } - } - break; - - case 21: // Initialise SD card - if (!LockFileSystem(gb)) // don't allow more than one at a time to avoid contention on output buffers - { - return false; - } - { - const size_t card = (gb.Seen('P')) ? gb.GetIValue() : 0; - result = MassStorage::Mount(card, reply, true); - } - break; + break; - case 22: // Release SD card - if (!LockFileSystem(gb)) // don't allow more than one at a time to avoid contention on output buffers - { - return false; - } - { - const size_t card = (gb.Seen('P')) ? gb.GetIValue() : 0; - result = MassStorage::Unmount(card, reply); - } - break; + case 21: // Initialise SD card + if (!LockFileSystem(gb)) // don't allow more than one at a time to avoid contention on output buffers + { + return false; + } + { + const size_t card = (gb.Seen('P')) ? gb.GetIValue() : 0; + result = MassStorage::Mount(card, reply, true); + } + break; - case 23: // Set file to print - case 32: // Select file and start SD print - // We now allow a file that is being printed to chain to another file. This is required for the resume-after-power-fail functionality. - if (fileGCode->IsDoingFile() && (&gb) != fileGCode) - { - reply.copy("Cannot set file to print, because a file is already being printed"); - result = GCodeResult::error; + case 22: // Release SD card + if (!LockFileSystem(gb)) // don't allow more than one at a time to avoid contention on output buffers + { + return false; + } + { + const size_t card = (gb.Seen('P')) ? gb.GetIValue() : 0; + result = MassStorage::Unmount(card, reply); + } break; - } - if (code == 32 && !LockMovementAndWaitForStandstill(gb)) - { - return false; - } - { - String<MaxFilenameLength> filename; - if (gb.GetUnprecedentedString(filename.GetRef())) + case 23: // Set file to print + case 32: // Select file and start SD print + // We now allow a file that is being printed to chain to another file. This is required for the resume-after-power-fail functionality. + if (fileGCode->IsDoingFile() && (&gb) != fileGCode) { + reply.copy("Cannot set file to print, because a file is already being printed"); + result = GCodeResult::error; + break; + } + + if (code == 32 && !LockMovementAndWaitForStandstill(gb)) + { + return false; + } + { + String<MaxFilenameLength> filename; + gb.GetUnprecedentedString(filename.GetRef()); if (QueueFileToPrint(filename.c_str(), reply)) { reprap.GetPrintMonitor().StartingPrint(filename.c_str()); @@ -767,169 +779,162 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) result = GCodeResult::error; } } - else - { - reply.copy("Filename expected"); - result = GCodeResult::error; - } - } - break; + break; #endif - case 24: // Print/resume-printing the selected file - if (IsPausing() || IsResuming()) - { - // ignore the resume request - } - else - { - if (!LockMovementAndWaitForStandstill(gb)) + case 24: // Print/resume-printing the selected file + if (IsPausing() || IsResuming()) { - return false; + // ignore the resume request } - - if (IsPaused()) + else { + if (!LockMovementAndWaitForStandstill(gb)) + { + return false; + } + + if (IsPaused()) + { #if HAS_VOLTAGE_MONITOR - if (!platform.IsPowerOk()) + if (!platform.IsPowerOk()) + { + reply.copy("Cannot resume while power voltage is low"); + result = GCodeResult::error; + } + else +#endif + { + gb.SetState(GCodeState::resuming1); + if (AllAxesAreHomed()) + { + DoFileMacro(gb, RESUME_G, true, 24); + } + } + } +#if HAS_MASS_STORAGE + else if (!fileToPrint.IsLive()) { - reply.copy("Cannot resume while power voltage is low"); + reply.copy("Cannot print, because no file is selected!"); result = GCodeResult::error; } else -#endif { - gb.SetState(GCodeState::resuming1); - if (AllAxesAreHomed()) +# if HAS_VOLTAGE_MONITOR + if (!platform.IsPowerOk()) { - DoFileMacro(gb, RESUME_G, true, 24); + reply.copy("Cannot start a print while power voltage is low"); + result = GCodeResult::error; + } + else +# endif + { + bool fromStart = (fileOffsetToPrint == 0); + if (!fromStart) + { + // We executed M26 to set the file offset, which normally means that we are executing resurrect.g. + // We need to copy the absolute/relative and volumetric extrusion flags over + fileGCode->OriginalMachineState().CopyStateFrom(gb.MachineState()); + fileToPrint.Seek(fileOffsetToPrint); + moveFractionToSkip = restartMoveFractionDone; + } + StartPrinting(fromStart); } } +#endif } -#if HAS_MASS_STORAGE - else if (!fileToPrint.IsLive()) + break; + + case 226: // Synchronous pause, normally initiated from within the file being printed + if (!isPaused && !IsPausing()) { - reply.copy("Cannot print, because no file is selected!"); - result = GCodeResult::error; + if (gb.IsDoingFileMacro()) + { + pausePending = true; + } + else + { + if (!LockMovementAndWaitForStandstill(gb)) // lock movement before calling DoPause, also wait for movement to complete + { + return false; + } + DoPause(gb, PauseReason::gcode, nullptr); + } } - else + break; + + case 600: // Filament change pause, synchronous + if (!isPaused && !IsPausing()) { -# if HAS_VOLTAGE_MONITOR - if (!platform.IsPowerOk()) + if (gb.IsDoingFileMacro()) { - reply.copy("Cannot start a print while power voltage is low"); - result = GCodeResult::error; + filamentChangePausePending = true; } else -# endif { - bool fromStart = (fileOffsetToPrint == 0); - if (!fromStart) + if (!LockMovementAndWaitForStandstill(gb)) // lock movement before calling DoPause, also wait for movement to complete { - // We executed M26 to set the file offset, which normally means that we are executing resurrect.g. - // We need to copy the absolute/relative and volumetric extrusion flags over - fileGCode->OriginalMachineState().CopyStateFrom(gb.MachineState()); - fileToPrint.Seek(fileOffsetToPrint); - moveFractionToSkip = restartMoveFractionDone; + return false; } - StartPrinting(fromStart); + DoPause(gb, PauseReason::filamentChange, nullptr); } } -#endif - } - break; + break; - case 226: // Synchronous pause, normally initiated from within the file being printed - if (!isPaused && !IsPausing()) - { - if (gb.IsDoingFileMacro()) + case 25: // Pause the print + if (isPaused) { - pausePending = true; + reply.copy("Printing is already paused!!"); + result = GCodeResult::error; } - else + else if (!reprap.GetPrintMonitor().IsPrinting()) { - if (!LockMovementAndWaitForStandstill(gb)) // lock movement before calling DoPause, also wait for movement to complete - { - return false; - } - DoPause(gb, PauseReason::gcode, nullptr); + reply.copy("Cannot pause print, because no file is being printed!"); + result = GCodeResult::error; } - } - break; - - case 600: // Filament change pause, synchronous - if (!isPaused && !IsPausing()) - { - if (gb.IsDoingFileMacro()) + else if (fileGCode->IsDoingFileMacro()) { - filamentChangePausePending = true; + pausePending = true; } else { - if (!LockMovementAndWaitForStandstill(gb)) // lock movement before calling DoPause, also wait for movement to complete + if (!LockMovement(gb)) // lock movement before calling DoPause { return false; } - DoPause(gb, PauseReason::filamentChange, nullptr); + DoPause(gb, PauseReason::user, nullptr); } - } - break; + break; - case 25: // Pause the print - if (isPaused) - { - reply.copy("Printing is already paused!!"); - result = GCodeResult::error; - } - else if (!reprap.GetPrintMonitor().IsPrinting()) - { - reply.copy("Cannot pause print, because no file is being printed!"); - result = GCodeResult::error; - } - else if (fileGCode->IsDoingFileMacro()) - { - pausePending = true; - } - else - { - if (!LockMovement(gb)) // lock movement before calling DoPause +#if HAS_MASS_STORAGE + case 26: // Set SD position + // This is used between executing M23 to set up the file to print, and M25 to print it + if (gb.Seen('S')) { - return false; + fileOffsetToPrint = (FilePosition)gb.GetUIValue(); + restartMoveFractionDone = (gb.Seen('P')) ? constrain<float>(gb.GetFValue(), 0.0, 1.0) : 0.0; + restartInitialUserX = (gb.Seen('X')) ? gb.GetFValue() : 0.0; + restartInitialUserY = (gb.Seen('Y')) ? gb.GetFValue() : 0.0; } - DoPause(gb, PauseReason::user, nullptr); - } - break; - -#if HAS_MASS_STORAGE - case 26: // Set SD position - // This is used between executing M23 to set up the file to print, and M25 to print it - if (gb.Seen('S')) - { - fileOffsetToPrint = (FilePosition)gb.GetUIValue(); - restartMoveFractionDone = (gb.Seen('P')) ? constrain<float>(gb.GetFValue(), 0.0, 1.0) : 0.0; - restartInitialUserX = (gb.Seen('X')) ? gb.GetFValue() : 0.0; - restartInitialUserY = (gb.Seen('Y')) ? gb.GetFValue() : 0.0; - } - break; + break; - case 27: // Report print status - Deprecated - if (reprap.GetPrintMonitor().IsPrinting()) - { - // Pronterface keeps sending M27 commands if "Monitor status" is checked, and it specifically expects the following response syntax - FileData& fileBeingPrinted = fileGCode->OriginalMachineState().fileState; - reply.printf("SD printing byte %lu/%lu", GetFilePosition(), fileBeingPrinted.Length()); - } - else - { - reply.copy("Not SD printing."); - } - break; + case 27: // Report print status - Deprecated + if (reprap.GetPrintMonitor().IsPrinting()) + { + // Pronterface keeps sending M27 commands if "Monitor status" is checked, and it specifically expects the following response syntax + FileData& fileBeingPrinted = fileGCode->OriginalMachineState().fileState; + reply.printf("SD printing byte %lu/%lu", GetFilePosition(), fileBeingPrinted.Length()); + } + else + { + reply.copy("Not SD printing."); + } + break; - case 28: // Write to file - { - String<MaxFilenameLength> filename; - if (gb.GetUnprecedentedString(filename.GetRef())) + case 28: // Write to file { + String<MaxFilenameLength> filename; + gb.GetUnprecedentedString(filename.GetRef()); const bool ok = gb.OpenFileToWrite(platform.GetGCodeDir(), filename.c_str(), 0, false, 0); if (ok) { @@ -941,113 +946,99 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) result = GCodeResult::error; } } - else - { - reply.copy("Filename expected"); - result = GCodeResult::error; - } - } - break; + break; - case 29: // End of file being written; should be intercepted before getting here - reply.copy("GCode end-of-file being interpreted."); - break; + case 29: // End of file being written; should be intercepted before getting here + reply.copy("GCode end-of-file being interpreted."); + break; - case 30: // Delete file - { - String<MaxFilenameLength> filename; - if (gb.GetUnprecedentedString(filename.GetRef())) + case 30: // Delete file { + String<MaxFilenameLength> filename; + gb.GetUnprecedentedString(filename.GetRef()); platform.Delete(platform.GetGCodeDir(), filename.c_str()); } - else - { - reply.copy("Filename expected"); - result = GCodeResult::error; - } - } - break; + break; #endif // For case 32, see case 23 #if HAS_MASS_STORAGE || HAS_LINUX_INTERFACE - case 36: // Return file information + case 36: // Return file information # if HAS_LINUX_INTERFACE - if (reprap.UsingLinuxInterface()) - { - reprap.GetFileInfoResponse(nullptr, outBuf, true); - } - else -# endif - { -# if HAS_MASS_STORAGE - if (!LockFileSystem(gb)) // getting file info takes several calls and isn't reentrant - { - return false; - } - - String<MaxFilenameLength> filename; - const bool gotFilename = gb.GetUnprecedentedString(filename.GetRef()); - const bool done = reprap.GetFileInfoResponse((gotFilename) ? filename.c_str() : nullptr, outBuf, false); - if (outBuf != nullptr) + if (reprap.UsingLinuxInterface()) { - outBuf->cat('\n'); + reprap.GetFileInfoResponse(nullptr, outBuf, true); } - result = (done) ? GCodeResult::ok : GCodeResult::notFinished; + else # endif - } - break; + { +# if HAS_MASS_STORAGE + if (!LockFileSystem(gb)) // getting file info takes several calls and isn't reentrant + { + return false; + } - case 37: // Simulation mode on/off, or simulate a whole file -# if HAS_LINUX_INTERFACE - if (reprap.UsingLinuxInterface() && !gb.IsBinary()) - { - reply.copy("M37 can be only started from the Linux interface"); - result = GCodeResult::error; - } - else + String<MaxFilenameLength> filename; + gb.GetUnprecedentedString(filename.GetRef(), true); + const bool done = reprap.GetFileInfoResponse((filename.IsEmpty()) ? nullptr : filename.c_str(), outBuf, false); + if (outBuf != nullptr) + { + outBuf->cat('\n'); + } + result = (done) ? GCodeResult::ok : GCodeResult::notFinished; # endif - { - bool seen = false; - String<MaxFilenameLength> simFileName; + } + break; - gb.TryGetPossiblyQuotedString('P', simFileName.GetRef(), seen); - if (seen) + case 37: // Simulation mode on/off, or simulate a whole file +# if HAS_LINUX_INTERFACE + if (reprap.UsingLinuxInterface() && !gb.IsBinary()) { - const bool updateFile = !gb.Seen('F') || gb.GetUIValue() == 1; - result = SimulateFile(gb, reply, simFileName.GetRef(), updateFile); + reply.copy("M37 can be only started from the Linux interface"); + result = GCodeResult::error; } else +# endif { - uint32_t newSimulationMode; - gb.TryGetUIValue('S', newSimulationMode, seen); + bool seen = false; + String<MaxFilenameLength> simFileName; + + gb.TryGetPossiblyQuotedString('P', simFileName.GetRef(), seen); if (seen) { - result = ChangeSimulationMode(gb, reply, newSimulationMode); + const bool updateFile = !gb.Seen('F') || gb.GetUIValue() == 1; + result = SimulateFile(gb, reply, simFileName.GetRef(), updateFile); } else { - reply.printf("Simulation mode: %s, move time: %.1f sec, other time: %.1f sec", - (simulationMode != 0) ? "on" : "off", (double)reprap.GetMove().GetSimulationTime(), (double)simulationTime); + uint32_t newSimulationMode; + gb.TryGetUIValue('S', newSimulationMode, seen); + if (seen) + { + result = ChangeSimulationMode(gb, reply, newSimulationMode); + } + else + { + reply.printf("Simulation mode: %s, move time: %.1f sec, other time: %.1f sec", + (simulationMode != 0) ? "on" : "off", (double)reprap.GetMove().GetSimulationTime(), (double)simulationTime); + } } } - } - break; + break; #endif #if HAS_MASS_STORAGE - case 38: // Report SHA1 of file - if (!LockFileSystem(gb)) // getting file hash takes several calls and isn't reentrant - { - return false; - } - if (fileBeingHashed == nullptr) - { - // See if we can open the file and start hashing - String<MaxFilenameLength> filename; - if (gb.GetUnprecedentedString(filename.GetRef())) + case 38: // Report SHA1 of file + if (!LockFileSystem(gb)) // getting file hash takes several calls and isn't reentrant { + return false; + } + if (fileBeingHashed == nullptr) + { + // See if we can open the file and start hashing + String<MaxFilenameLength> filename; + gb.GetUnprecedentedString(filename.GetRef()); if (StartHash(filename.c_str())) { // Hashing is now in progress... @@ -1061,2710 +1052,2704 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) } else { - reply.copy("Filename expected"); - result = GCodeResult::error; + // This can take some time. All the actual heavy lifting is in dedicated methods + result = AdvanceHash(reply); } - } - else - { - // This can take some time. All the actual heavy lifting is in dedicated methods - result = AdvanceHash(reply); - } - break; + break; - case 39: // Return SD card info - { - uint32_t slot = 0; - bool dummy; - gb.TryGetUIValue('P', slot, dummy); - int32_t format = 0; - gb.TryGetIValue('S', format, dummy); - uint64_t capacity, freeSpace; - uint32_t speed; - uint32_t clSize; - const MassStorage::InfoResult res = MassStorage::GetCardInfo(slot, capacity, freeSpace, speed, clSize); - if (format == 2) - { - reply.printf("{\"SDinfo\":{\"slot\":%" PRIu32 ",\"present\":", slot); - if (res == MassStorage::InfoResult::ok) - { - reply.catf("1,\"capacity\":%" PRIu64 ",\"free\":%" PRIu64 ",\"speed\":%" PRIu32 ",\"clsize\":%" PRIu32 "}}", capacity, freeSpace, speed, clSize); - } - else - { - reply.cat("0}}"); - } - } - else + case 39: // Return SD card info { - switch(res) - { - case MassStorage::InfoResult::badSlot: - default: - reply.printf("Bad SD slot number: %" PRIu32, slot); - result = GCodeResult::error; - break; - - case MassStorage::InfoResult::noCard: - reply.printf("No SD card mounted in slot %" PRIu32, slot); - result = GCodeResult::error; - break; - - case MassStorage::InfoResult::ok: - reply.printf("SD card in slot %" PRIu32 ": capacity %.2fGb, free space %.2fGb, speed %.2fMBytes/sec, cluster size ", - slot, (double)capacity/(1000*1000*1000), (double)freeSpace/(1000*1000*1000), (double)speed/(1000*1000)); - if (clSize < 1024) + uint32_t slot = 0; + bool dummy; + gb.TryGetUIValue('P', slot, dummy); + int32_t format = 0; + gb.TryGetIValue('S', format, dummy); + uint64_t capacity, freeSpace; + uint32_t speed; + uint32_t clSize; + const MassStorage::InfoResult res = MassStorage::GetCardInfo(slot, capacity, freeSpace, speed, clSize); + if (format == 2) + { + reply.printf("{\"SDinfo\":{\"slot\":%" PRIu32 ",\"present\":", slot); + if (res == MassStorage::InfoResult::ok) { - reply.catf("%" PRIu32 " bytes", clSize); + reply.catf("1,\"capacity\":%" PRIu64 ",\"free\":%" PRIu64 ",\"speed\":%" PRIu32 ",\"clsize\":%" PRIu32 "}}", capacity, freeSpace, speed, clSize); } else { - reply.catf("%" PRIu32 "kb", clSize/1024); + reply.cat("0}}"); + } + } + else + { + switch(res) + { + case MassStorage::InfoResult::badSlot: + default: + reply.printf("Bad SD slot number: %" PRIu32, slot); + result = GCodeResult::error; + break; + + case MassStorage::InfoResult::noCard: + reply.printf("No SD card mounted in slot %" PRIu32, slot); + result = GCodeResult::error; + break; + + case MassStorage::InfoResult::ok: + reply.printf("SD card in slot %" PRIu32 ": capacity %.2fGb, free space %.2fGb, speed %.2fMBytes/sec, cluster size ", + slot, (double)capacity/(1000*1000*1000), (double)freeSpace/(1000*1000*1000), (double)speed/(1000*1000)); + if (clSize < 1024) + { + reply.catf("%" PRIu32 " bytes", clSize); + } + else + { + reply.catf("%" PRIu32 "kb", clSize/1024); + } + break; } - break; } } - } - break; + break; #endif - case 42: // Turn an output pin on or off - if (gb.Seen('P')) - { - const uint32_t gpioPortNumber = gb.GetUIValue(); - if (gpioPortNumber < MaxGpioPorts) + case 42: // Turn an output pin on or off + if (gb.Seen('P')) { - if (gb.Seen('S')) + const uint32_t gpioPortNumber = gb.GetUIValue(); + if (gpioPortNumber < MaxGpioPorts) { - const float val = gb.GetPwmValue(); - const GpOutputPort& gpPort = platform.GetGpioPort(gpioPortNumber); -#if SUPPORT_CAN_EXPANSION - if (gpPort.boardAddress != CanId::MasterAddress) + if (gb.Seen('S')) { - result = CanInterface::WriteGpio(gpPort.boardAddress, gpioPortNumber, val, false, reply); - break; - } + const float val = gb.GetPwmValue(); + const GpOutputPort& gpPort = platform.GetGpioPort(gpioPortNumber); +#if SUPPORT_CAN_EXPANSION + if (gpPort.boardAddress != CanId::MasterAddress) + { + result = CanInterface::WriteGpio(gpPort.boardAddress, gpioPortNumber, val, false, reply); + break; + } #endif - gpPort.port.WriteAnalog(val); + gpPort.port.WriteAnalog(val); + } + } + else + { + reply.printf("Invalid gpio port %" PRIu32, gpioPortNumber); + result = GCodeResult::error; } } - else + break; + + case 80: // ATX power on + atxPowerControlled = true; + platform.AtxPowerOn(); + break; + + case 81: // ATX power off + atxPowerControlled = true; + if (!LockMovementAndWaitForStandstill(gb)) { - reply.printf("Invalid gpio port %" PRIu32, gpioPortNumber); - result = GCodeResult::error; + return false; } - } - break; - - case 80: // ATX power on - atxPowerControlled = true; - platform.AtxPowerOn(); - break; + platform.AtxPowerOff(gb.Seen('S') && gb.GetUIValue() != 0); + break; - case 81: // ATX power off - atxPowerControlled = true; - if (!LockMovementAndWaitForStandstill(gb)) - { - return false; - } - platform.AtxPowerOff(gb.Seen('S') && gb.GetUIValue() != 0); - break; + case 82: // Use absolute extruder positioning + gb.MachineState().drivesRelative = false; + break; - case 82: // Use absolute extruder positioning - gb.MachineState().drivesRelative = false; - break; + case 83: // Use relative extruder positioning + gb.MachineState().drivesRelative = true; + break; - case 83: // Use relative extruder positioning - gb.MachineState().drivesRelative = true; - break; + // For case 84, see case 18 - // For case 84, see case 18 + case 85: // Set inactive time + break; - case 85: // Set inactive time - break; + case 92: // Set/report steps/mm for some axes + { + bool seenUstepMultiplier = false; + uint32_t ustepMultiplier = 0; + gb.TryGetUIValue('S', ustepMultiplier, seenUstepMultiplier); - case 92: // Set/report steps/mm for some axes - { - bool seenUstepMultiplier = false; - uint32_t ustepMultiplier = 0; - gb.TryGetUIValue('S', ustepMultiplier, seenUstepMultiplier); + bool seen = false; + for (size_t axis = 0; axis < numTotalAxes; axis++) + { + if (gb.Seen(axisLetters[axis])) + { + if (!LockMovementAndWaitForStandstill(gb)) + { + return false; + } + platform.SetDriveStepsPerUnit(axis, gb.GetFValue(), ustepMultiplier); + seen = true; + } + } - bool seen = false; - for (size_t axis = 0; axis < numTotalAxes; axis++) - { - if (gb.Seen(axisLetters[axis])) + if (gb.Seen(extrudeLetter)) { if (!LockMovementAndWaitForStandstill(gb)) { return false; } - platform.SetDriveStepsPerUnit(axis, gb.GetFValue(), ustepMultiplier); seen = true; + float eVals[MaxExtruders]; + size_t eCount = numExtruders; + gb.GetFloatArray(eVals, eCount, true); + + // The user may not have as many extruders as we allow for, so just set the ones for which a value is provided + for (size_t e = 0; e < eCount; e++) + { + platform.SetDriveStepsPerUnit(ExtruderToLogicalDrive(e), eVals[e], ustepMultiplier); + } } - } - if (gb.Seen(extrudeLetter)) - { - if (!LockMovementAndWaitForStandstill(gb)) + if (seen) { - return false; + // On a delta, if we change the drive steps/mm then we need to recalculate the motor positions + reprap.GetMove().SetNewPosition(moveBuffer.coords, true); } - seen = true; - float eVals[MaxExtruders]; - size_t eCount = numExtruders; - gb.GetFloatArray(eVals, eCount, true); - - // The user may not have as many extruders as we allow for, so just set the ones for which a value is provided - for (size_t e = 0; e < eCount; e++) + else { - platform.SetDriveStepsPerUnit(ExtruderToLogicalDrive(e), eVals[e], ustepMultiplier); + reply.copy("Steps/mm: "); + for (size_t axis = 0; axis < numTotalAxes; ++axis) + { + reply.catf("%c: %.3f, ", axisLetters[axis], (double)platform.DriveStepsPerUnit(axis)); + } + reply.catf("E:"); + char sep = ' '; + for (size_t extruder = 0; extruder < numExtruders; extruder++) + { + reply.catf("%c%.3f", sep, (double)platform.DriveStepsPerUnit(ExtruderToLogicalDrive(extruder))); + sep = ':'; + } } } + break; - if (seen) - { - // On a delta, if we change the drive steps/mm then we need to recalculate the motor positions - reprap.GetMove().SetNewPosition(moveBuffer.coords, true); - } - else + case 98: // Call Macro/Subprogram + if (gb.Seen('P')) { - reply.copy("Steps/mm: "); - for (size_t axis = 0; axis < numTotalAxes; ++axis) - { - reply.catf("%c: %.3f, ", axisLetters[axis], (double)platform.DriveStepsPerUnit(axis)); - } - reply.catf("E:"); - char sep = ' '; - for (size_t extruder = 0; extruder < numExtruders; extruder++) +#if HAS_LINUX_INTERFACE + if (reprap.UsingLinuxInterface()) { - reply.catf("%c%.3f", sep, (double)platform.DriveStepsPerUnit(ExtruderToLogicalDrive(extruder))); - sep = ':'; + gb.SetState(GCodeState::doingUserMacro); } - } - } - break; - - case 98: // Call Macro/Subprogram - if (gb.Seen('P')) - { -#if HAS_LINUX_INTERFACE - if (reprap.UsingLinuxInterface()) - { - gb.SetState(GCodeState::doingUserMacro); - } #endif - String<MaxFilenameLength> filename; - gb.GetPossiblyQuotedString(filename.GetRef()); - DoFileMacro(gb, filename.c_str(), true, code); - } - break; - - case 99: // Return from Macro/Subprogram - FileMacroCyclesReturn(gb); - break; + String<MaxFilenameLength> filename; + gb.GetPossiblyQuotedString(filename.GetRef()); + DoFileMacro(gb, filename.c_str(), true, code); + } + break; - case 101: // Un-retract, generated by S3D if "Include M101/101/103" is enabled - result = RetractFilament(gb, false); - break; + case 99: // Return from Macro/Subprogram + FileMacroCyclesReturn(gb); + break; - case 102: - // S3D generates this command just before each explicit retraction command if both explicit retraction and "Include M101/101/103" are enabled. - // Old versions of S3D also generate it once at the start of each print file if "Include M101/101/103" is enabled. - // It's not documented, so we just ignore it rather than generate an error message. - break; + case 101: // Un-retract, generated by S3D if "Include M101/101/103" is enabled + result = RetractFilament(gb, false); + break; - case 103: // Retract, generated by S3D if "Include M101/101/103" is enabled - result = RetractFilament(gb, true); - break; + case 102: + // S3D generates this command just before each explicit retraction command if both explicit retraction and "Include M101/101/103" are enabled. + // Old versions of S3D also generate it once at the start of each print file if "Include M101/101/103" is enabled. + // It's not documented, so we just ignore it rather than generate an error message. + break; - // For case 104, see 109 + case 103: // Retract, generated by S3D if "Include M101/101/103" is enabled + result = RetractFilament(gb, true); + break; - case 105: // Get temperatures - GenerateTemperatureReport(reply); - break; + // For case 104, see 109 - case 106: // Set/report fan values - { - bool seenFanNum = false; - uint32_t fanNum; - gb.TryGetUIValue('P', fanNum, seenFanNum); - bool processed; + case 105: // Get temperatures + GenerateTemperatureReport(reply); + break; - // 2018-08-09: only configure the fan if a fan number was given. - // This avoids M106 Snn failing if we have disabled Fan 0 and mapped the print cooling fan to a different fan. - if (seenFanNum) + case 106: // Set/report fan values { - bool error = false; - processed = reprap.GetFansManager().ConfigureFan(code, fanNum, gb, reply, error); - result = GetGCodeResultFromError(error); - } - else - { - processed = false; - } + bool seenFanNum = false; + uint32_t fanNum; + gb.TryGetUIValue('P', fanNum, seenFanNum); + bool processed; - // ConfigureFan only processes S parameters if there were other parameters to process - if (!processed && gb.Seen('S')) - { - // Convert the parameter to an interval in 0.0..1.0 here so that we save the correct value in lastDefaultFanSpeed - const float f = gb.GetPwmValue(); + // 2018-08-09: only configure the fan if a fan number was given. + // This avoids M106 Snn failing if we have disabled Fan 0 and mapped the print cooling fan to a different fan. if (seenFanNum) { - result = reprap.GetFansManager().SetFanValue(fanNum, f, reply); - if (IsMappedFan(fanNum)) - { - lastDefaultFanSpeed = f; - } + bool error = false; + processed = reprap.GetFansManager().ConfigureFan(code, fanNum, gb, reply, error); + result = GetGCodeResultFromError(error); } else { - // We are processing an M106 S### command with no other recognised parameters and we have a tool selected. - // Apply the fan speed setting to the fans in the fan mapping for the current tool. - SetMappedFanSpeed(f); + processed = false; } - } - // ConfigureFan doesn't process R parameters - if (gb.Seen('R')) - { - // Restore fan speed to value when print was paused - if (seenFanNum) + // ConfigureFan only processes S parameters if there were other parameters to process + if (!processed && gb.Seen('S')) { - result = reprap.GetFansManager().SetFanValue(fanNum, pausedFanSpeeds[fanNum], reply); + // Convert the parameter to an interval in 0.0..1.0 here so that we save the correct value in lastDefaultFanSpeed + const float f = gb.GetPwmValue(); + if (seenFanNum) + { + result = reprap.GetFansManager().SetFanValue(fanNum, f, reply); + if (IsMappedFan(fanNum)) + { + lastDefaultFanSpeed = f; + } + } + else + { + // We are processing an M106 S### command with no other recognised parameters and we have a tool selected. + // Apply the fan speed setting to the fans in the fan mapping for the current tool. + SetMappedFanSpeed(f); + } } - else + + // ConfigureFan doesn't process R parameters + if (gb.Seen('R')) { - SetMappedFanSpeed(pausedDefaultFanSpeed); + // Restore fan speed to value when print was paused + if (seenFanNum) + { + result = reprap.GetFansManager().SetFanValue(fanNum, pausedFanSpeeds[fanNum], reply); + } + else + { + SetMappedFanSpeed(pausedDefaultFanSpeed); + } } } - } - break; - - case 107: // Fan off - deprecated - SetMappedFanSpeed(0.0); - break; - - case 108: // Cancel waiting for temperature - if (isWaiting) - { - cancelWait = true; - } - break; - - case 109: // Deprecated in RRF, but widely generated by slicers - if ( !LockMovementAndWaitForStandstill(gb) // wait until movement has finished - || !IsCodeQueueIdle() // also wait until deferred command queue has caught up to avoid out-of-order execution - ) - { - return false; - } - UnlockMovement(gb); // allow babystepping and pausing while heating - - // no break - case 104: - // New behaviour from 1.20beta12: - // M109 Snnn - // - If no tools are active, set Tool 0 to active - // - Set active tool's active and standby temperatures to Snnn - // - // M109 Tnnn Snnn - // - If no tools are active, set Tnnn to active - // - If another tool is active but Tnnn is off, set Tnnn to standby - // - Set Tnnn's active and standby temperatures to Snnn - // M104 does the same but doesn't ever select a tool - { - // Get the temperature to set - float temperature; - if (gb.Seen('R')) - { - gb.MachineState().waitWhileCooling = true; - temperature = gb.GetFValue(); - } - else if (gb.Seen('S')) - { - gb.MachineState().waitWhileCooling = false; - temperature = gb.GetFValue(); - } - else - { - break; // no target temperature given - } + break; - // Find the tool that the command applies to. - // This is the tool specified in the T parameter, else the current tool if there is one, else the default tool - Tool *applicableTool; - if (gb.Seen('T')) - { - int toolNumber = gb.GetIValue(); - toolNumber += gb.GetToolNumberAdjust(); - applicableTool = reprap.GetTool(toolNumber); - } - else - { - applicableTool = reprap.GetCurrentOrDefaultTool(); - } + case 107: // Fan off - deprecated + SetMappedFanSpeed(0.0); + break; - // Check that we have a tool - if (applicableTool == nullptr) + case 108: // Cancel waiting for temperature + if (isWaiting) { - reply.copy("Invalid tool number"); - result = GCodeResult::error; - break; + cancelWait = true; } + break; - // Set the heater temperatures for that tool. We set the standby temperatures as well as the active ones, - // because any slicer that uses M109 doesn't understand that there are separate active and standby temperatures. - if (simulationMode == 0) + case 109: // Deprecated in RRF, but widely generated by slicers + if ( !LockMovementAndWaitForStandstill(gb) // wait until movement has finished + || !IsCodeQueueIdle() // also wait until deferred command queue has caught up to avoid out-of-order execution + ) { - SetToolHeaters(applicableTool, temperature, true); + return false; } - - Tool * const currentTool = reprap.GetCurrentTool(); - if (code == 109 && currentTool == nullptr) - { - // Switch to the tool - if (!LockMovementAndWaitForStandstill(gb)) + UnlockMovement(gb); // allow babystepping and pausing while heating + + // no break + case 104: + // New behaviour from 1.20beta12: + // M109 Snnn + // - If no tools are active, set Tool 0 to active + // - Set active tool's active and standby temperatures to Snnn + // + // M109 Tnnn Snnn + // - If no tools are active, set Tnnn to active + // - If another tool is active but Tnnn is off, set Tnnn to standby + // - Set Tnnn's active and standby temperatures to Snnn + // M104 does the same but doesn't ever select a tool + { + // Get the temperature to set + float temperature; + if (gb.Seen('R')) { - return false; + gb.MachineState().waitWhileCooling = true; + temperature = gb.GetFValue(); + } + else if (gb.Seen('S')) + { + gb.MachineState().waitWhileCooling = false; + temperature = gb.GetFValue(); + } + else + { + break; // no target temperature given } - gb.MachineState().newToolNumber = applicableTool->Number(); - gb.MachineState().toolChangeParam = (simulationMode != 0) ? 0 : DefaultToolChangeParam; - gb.SetState(GCodeState::m109ToolChange0); - result = GCodeResult::ok; - } - else - { - if (applicableTool == currentTool) + // Find the tool that the command applies to. + // This is the tool specified in the T parameter, else the current tool if there is one, else the default tool + Tool *applicableTool; + if (gb.Seen('T')) { - // Even though the tool is selected, we may have turned it off e.g. when upgrading the WiFi firmware or following a heater fault that has been cleared. - // So make sure the tool heaters are on. - reprap.SelectTool(applicableTool->Number(), simulationMode != 0); + int toolNumber = gb.GetIValue(); + toolNumber += gb.GetToolNumberAdjust(); + applicableTool = reprap.GetTool(toolNumber); } else { - // If we already have an active tool and we are setting temperatures for a different tool, set that tool's heaters to standby in case it is off - reprap.StandbyTool(applicableTool->Number(), simulationMode != 0); + applicableTool = reprap.GetCurrentOrDefaultTool(); + } + + // Check that we have a tool + if (applicableTool == nullptr) + { + reply.copy("Invalid tool number"); + result = GCodeResult::error; + break; + } + + // Set the heater temperatures for that tool. We set the standby temperatures as well as the active ones, + // because any slicer that uses M109 doesn't understand that there are separate active and standby temperatures. + if (simulationMode == 0) + { + SetToolHeaters(applicableTool, temperature, true); } - if (code == 109 && simulationMode == 0) + Tool * const currentTool = reprap.GetCurrentTool(); + if (code == 109 && currentTool == nullptr) { - gb.SetState(GCodeState::m109WaitForTemperature); + // Switch to the tool + if (!LockMovementAndWaitForStandstill(gb)) + { + return false; + } + + gb.MachineState().newToolNumber = applicableTool->Number(); + gb.MachineState().toolChangeParam = (simulationMode != 0) ? 0 : DefaultToolChangeParam; + gb.SetState(GCodeState::m109ToolChange0); result = GCodeResult::ok; } + else + { + if (applicableTool == currentTool) + { + // Even though the tool is selected, we may have turned it off e.g. when upgrading the WiFi firmware or following a heater fault that has been cleared. + // So make sure the tool heaters are on. + reprap.SelectTool(applicableTool->Number(), simulationMode != 0); + } + else + { + // If we already have an active tool and we are setting temperatures for a different tool, set that tool's heaters to standby in case it is off + reprap.StandbyTool(applicableTool->Number(), simulationMode != 0); + } + + if (code == 109 && simulationMode == 0) + { + gb.SetState(GCodeState::m109WaitForTemperature); + result = GCodeResult::ok; + } + } } - } - break; + break; - case 110: // Set line numbers - line numbers are dealt with in the GCodeBuffer class - break; + case 110: // Set line numbers - line numbers are dealt with in the GCodeBuffer class + break; - case 111: // Debug level - if (gb.Seen('S')) - { - const bool dbv = (gb.GetIValue() != 0); - if (gb.Seen('P')) - { - reprap.SetDebug(static_cast<Module>(gb.GetIValue()), dbv); - reprap.PrintDebug(gb.GetResponseMessageType()); - return true; - } - if (dbv) + case 111: // Debug level + if (gb.Seen('S')) { - // Repetier Host sends M111 with various S parameters to enable echo and similar features, which used to turn on all out debugging. - // But it's not useful to enable all debugging anyway. So we no longer allow debugging to be enabled without a P parameter. - reply.copy("Use P parameter to specify which module to debug"); + const bool dbv = (gb.GetIValue() != 0); + if (gb.Seen('P')) + { + reprap.SetDebug(static_cast<Module>(gb.GetIValue()), dbv); + reprap.PrintDebug(gb.GetResponseMessageType()); + return true; + } + if (dbv) + { + // Repetier Host sends M111 with various S parameters to enable echo and similar features, which used to turn on all out debugging. + // But it's not useful to enable all debugging anyway. So we no longer allow debugging to be enabled without a P parameter. + reply.copy("Use P parameter to specify which module to debug"); + } + else + { + // M111 S0 still clears all debugging + reprap.ClearDebug(); + } } else { - // M111 S0 still clears all debugging - reprap.ClearDebug(); + reprap.PrintDebug(gb.GetResponseMessageType()); + return true; } - } - else - { - reprap.PrintDebug(gb.GetResponseMessageType()); - return true; - } - break; + break; - case 112: // Emergency stop - acted upon in Webserver, but also here in case it comes from USB etc. - DoEmergencyStop(); - break; + case 112: // Emergency stop - acted upon in Webserver, but also here in case it comes from USB etc. + DoEmergencyStop(); + break; - case 114: - GetCurrentCoordinates(reply); - break; + case 114: + GetCurrentCoordinates(reply); + break; - case 115: // Print firmware version or set hardware type + case 115: // Print firmware version or set hardware type #if defined(DUET_NG) || defined(DUET_06_85) - if (gb.Seen('P')) - { - if (runningConfigFile) + if (gb.Seen('P')) { - platform.SetBoardType((BoardType)gb.GetIValue()); + if (runningConfigFile) + { + platform.SetBoardType((BoardType)gb.GetIValue()); + } + else + { + reply.copy("Board type can only be set within config.g"); + result = GCodeResult::error; + } } else - { - reply.copy("Board type can only be set within config.g"); - result = GCodeResult::error; - } - } - else #endif - { -#if SUPPORT_CAN_EXPANSION - if (gb.Seen('B')) { - const uint32_t board = gb.GetUIValue(); - if (board != CanId::MasterAddress) +#if SUPPORT_CAN_EXPANSION + if (gb.Seen('B')) { - result = CanInterface::GetRemoteFirmwareDetails(board, gb, reply); - break; + const uint32_t board = gb.GetUIValue(); + if (board != CanId::MasterAddress) + { + result = CanInterface::GetRemoteFirmwareDetails(board, gb, reply); + break; + } } - } #endif - reply.printf("FIRMWARE_NAME: %s FIRMWARE_VERSION: %s ELECTRONICS: %s", FIRMWARE_NAME, VERSION, platform.GetElectronicsString()); + reply.printf("FIRMWARE_NAME: %s FIRMWARE_VERSION: %s ELECTRONICS: %s", FIRMWARE_NAME, VERSION, platform.GetElectronicsString()); #ifdef DUET_NG - const char* const expansionName = DuetExpansion::GetExpansionBoardName(); - if (expansionName != nullptr) - { - reply.catf(" + %s", expansionName); - } - const char* const additionalExpansionName = DuetExpansion::GetAdditionalExpansionBoardName(); - if (additionalExpansionName != nullptr) - { - reply.catf(" + %s", additionalExpansionName); - } -#endif - reply.catf(" FIRMWARE_DATE: %s", DATE); - } - break; - - case 116: // Wait for set temperatures - if ( !LockMovementAndWaitForStandstill(gb) // wait until movement has finished - || !IsCodeQueueIdle() // also wait until deferred command queue has caught up to avoid out-of-order execution - ) - { - return false; - } - - if (!cancelWait) - { - const float tolerance = (gb.Seen('S')) ? max<float>(gb.GetFValue(), 0.1) : TEMPERATURE_CLOSE_ENOUGH; - bool seen = false; - if (gb.Seen('P')) - { - // Wait for the heaters associated with the specified tool to be ready - int toolNumber = gb.GetIValue(); - toolNumber += gb.GetToolNumberAdjust(); - if (!ToolHeatersAtSetTemperatures(reprap.GetTool(toolNumber), true, tolerance)) + const char* const expansionName = DuetExpansion::GetExpansionBoardName(); + if (expansionName != nullptr) { - CheckReportDue(gb, reply); // check whether we need to send a temperature or status report - isWaiting = true; - return false; + reply.catf(" + %s", expansionName); + } + const char* const additionalExpansionName = DuetExpansion::GetAdditionalExpansionBoardName(); + if (additionalExpansionName != nullptr) + { + reply.catf(" + %s", additionalExpansionName); } - seen = true; +#endif + reply.catf(" FIRMWARE_DATE: %s", DATE); } + break; - if (gb.Seen('H')) + case 116: // Wait for set temperatures + if ( !LockMovementAndWaitForStandstill(gb) // wait until movement has finished + || !IsCodeQueueIdle() // also wait until deferred command queue has caught up to avoid out-of-order execution + ) { - // Wait for specified heaters to be ready - uint32_t heaters[MaxHeaters]; - size_t heaterCount = MaxHeaters; - gb.GetUnsignedArray(heaters, heaterCount, false); + return false; + } - for (size_t i = 0; i < heaterCount; i++) + if (!cancelWait) + { + const float tolerance = (gb.Seen('S')) ? max<float>(gb.GetFValue(), 0.1) : TEMPERATURE_CLOSE_ENOUGH; + bool seen = false; + if (gb.Seen('P')) { - if (!reprap.GetHeat().HeaterAtSetTemperature(heaters[i], true, tolerance)) + // Wait for the heaters associated with the specified tool to be ready + int toolNumber = gb.GetIValue(); + toolNumber += gb.GetToolNumberAdjust(); + if (!ToolHeatersAtSetTemperatures(reprap.GetTool(toolNumber), true, tolerance)) { - CheckReportDue(gb, reply); // check whether we need to send a temperature or status report + CheckReportDue(gb, reply); // check whether we need to send a temperature or status report isWaiting = true; return false; } + seen = true; } - seen = true; - } - if (gb.Seen('C')) - { - // Wait for specified chamber(s) to be ready - uint32_t chamberIndices[MaxChamberHeaters]; - size_t chamberCount = MaxChamberHeaters; - gb.GetUnsignedArray(chamberIndices, chamberCount, false); - - if (chamberCount == 0) + if (gb.Seen('H')) { - // If no values are specified, wait for all chamber heaters - for (size_t i = 0; i < MaxChamberHeaters; i++) + // Wait for specified heaters to be ready + uint32_t heaters[MaxHeaters]; + size_t heaterCount = MaxHeaters; + gb.GetUnsignedArray(heaters, heaterCount, false); + + for (size_t i = 0; i < heaterCount; i++) { - const int8_t heater = reprap.GetHeat().GetChamberHeater(i); - if (heater >= 0 && !reprap.GetHeat().HeaterAtSetTemperature(heater, true, tolerance)) + if (!reprap.GetHeat().HeaterAtSetTemperature(heaters[i], true, tolerance)) { - CheckReportDue(gb, reply); // check whether we need to send a temperature or status report + CheckReportDue(gb, reply); // check whether we need to send a temperature or status report isWaiting = true; return false; } } + seen = true; } - else + + if (gb.Seen('C')) { - // Otherwise wait only for the specified chamber heaters - for (size_t i = 0; i < chamberCount; i++) + // Wait for specified chamber(s) to be ready + uint32_t chamberIndices[MaxChamberHeaters]; + size_t chamberCount = MaxChamberHeaters; + gb.GetUnsignedArray(chamberIndices, chamberCount, false); + + if (chamberCount == 0) { - if (chamberIndices[i] >= 0 && chamberIndices[i] < MaxChamberHeaters) + // If no values are specified, wait for all chamber heaters + for (size_t i = 0; i < MaxChamberHeaters; i++) { - const int8_t heater = reprap.GetHeat().GetChamberHeater(chamberIndices[i]); + const int8_t heater = reprap.GetHeat().GetChamberHeater(i); if (heater >= 0 && !reprap.GetHeat().HeaterAtSetTemperature(heater, true, tolerance)) { - CheckReportDue(gb, reply); // check whether we need to send a temperature or status report + CheckReportDue(gb, reply); // check whether we need to send a temperature or status report isWaiting = true; return false; } } } + else + { + // Otherwise wait only for the specified chamber heaters + for (size_t i = 0; i < chamberCount; i++) + { + if (chamberIndices[i] >= 0 && chamberIndices[i] < MaxChamberHeaters) + { + const int8_t heater = reprap.GetHeat().GetChamberHeater(chamberIndices[i]); + if (heater >= 0 && !reprap.GetHeat().HeaterAtSetTemperature(heater, true, tolerance)) + { + CheckReportDue(gb, reply); // check whether we need to send a temperature or status report + isWaiting = true; + return false; + } + } + } + } + seen = true; } - seen = true; - } - // Wait for all heaters except chamber(s) to be ready - if (!seen && !reprap.GetHeat().AllHeatersAtSetTemperatures(true, tolerance)) - { - CheckReportDue(gb, reply); // check whether we need to send a temperature or status report - isWaiting = true; - return false; + // Wait for all heaters except chamber(s) to be ready + if (!seen && !reprap.GetHeat().AllHeatersAtSetTemperatures(true, tolerance)) + { + CheckReportDue(gb, reply); // check whether we need to send a temperature or status report + isWaiting = true; + return false; + } } - } - - // If we get here, there is nothing more to wait for - cancelWait = isWaiting = false; - break; - case 117: // Display message - { - String<MediumStringLength> msg; - gb.GetUnprecedentedString(msg.GetRef()); - reprap.SetMessage(msg.c_str()); - } - break; + // If we get here, there is nothing more to wait for + cancelWait = isWaiting = false; + break; - case 118: // Echo message on host - { - MessageType type = GenericMessage; - if (gb.Seen('P')) + case 117: // Display message { - const int32_t param = gb.GetIValue(); - switch (param) - { - case 0: // Generic (default) - // no need to set it twice - break; - case 1: // USB - type = UsbMessage; - break; - case 2: // UART port - type = DirectAuxMessage; - break; - case 3: // HTTP - type = HttpMessage; - break; - case 4: // Telnet - type = TelnetMessage; - break; - default: - reply.printf("Invalid message type: %" PRIi32, param); - result = GCodeResult::error; - break; - } + String<MediumStringLength> msg; + gb.GetUnprecedentedString(msg.GetRef()); + reprap.SetMessage(msg.c_str()); } + break; - if (result != GCodeResult::error && gb.Seen(('S'))) + case 118: // Echo message on host { - String<GCODE_LENGTH> message; - gb.GetQuotedString(message.GetRef()); - if (type != HttpMessage) + MessageType type = GenericMessage; + if (gb.Seen('P')) { - platform.Message((MessageType)(type | PushFlag), message.c_str()); - platform.Message(type, "\n"); + const int32_t param = gb.GetIValue(); + switch (param) + { + case 0: // Generic (default) + // no need to set it twice + break; + case 1: // USB + type = UsbMessage; + break; + case 2: // UART port + type = DirectAuxMessage; + break; + case 3: // HTTP + type = HttpMessage; + break; + case 4: // Telnet + type = TelnetMessage; + break; + default: + reply.printf("Invalid message type: %" PRIi32, param); + result = GCodeResult::error; + break; + } } - else + + if (result != GCodeResult::error && gb.Seen(('S'))) { - platform.Message(type, message.c_str()); + String<GCODE_LENGTH> message; + gb.GetQuotedString(message.GetRef()); + if (type != HttpMessage) + { + platform.Message((MessageType)(type | PushFlag), message.c_str()); + platform.Message(type, "\n"); + } + else + { + platform.Message(type, message.c_str()); + } } } - } - break; + break; - case 119: - platform.GetEndstops().GetM119report(reply); - break; + case 119: + platform.GetEndstops().GetM119report(reply); + break; - case 120: - Push(gb, true); - break; + case 120: + Push(gb, true); + break; - case 121: - Pop(gb, true); - break; + case 121: + Pop(gb, true); + break; - case 122: - { - const unsigned int type = (gb.Seen('P')) ? gb.GetIValue() : 0; - const MessageType mt = (MessageType)(gb.GetResponseMessageType() | PushFlag); -#if SUPPORT_CAN_EXPANSION - const uint32_t board = (gb.Seen('B')) ? gb.GetUIValue() : 0; - if (board != CanId::MasterAddress) + case 122: { - result = CanInterface::RemoteDiagnostics(mt, board, type, gb, reply); - break; - } + const unsigned int type = (gb.Seen('P')) ? gb.GetIValue() : 0; + const MessageType mt = (MessageType)(gb.GetResponseMessageType() | PushFlag); +#if SUPPORT_CAN_EXPANSION + const uint32_t board = (gb.Seen('B')) ? gb.GetUIValue() : 0; + if (board != CanId::MasterAddress) + { + result = CanInterface::RemoteDiagnostics(mt, board, type, gb, reply); + break; + } #endif - if (type == 0) - { - // Set the Push flag to combine multiple messages into a single OutputBuffer chain - reprap.Diagnostics(mt); - } - else - { - result = platform.DiagnosticTest(gb, reply, type); + if (type == 0) + { + // Set the Push flag to combine multiple messages into a single OutputBuffer chain + reprap.Diagnostics(mt); + } + else + { + result = platform.DiagnosticTest(gb, reply, type); + } } - } - break; - - // M135 (set PID sample interval) is no longer supported + break; - case 140: // Bed temperature - case 141: // Chamber temperature - { - Heat& heat = reprap.GetHeat(); - bool seen = false; + // M135 (set PID sample interval) is no longer supported - // Check if the heater index is passed - int index = gb.Seen('P') ? gb.GetIValue() : 0; - if (index < 0 || index >= (int)((code == 140) ? MaxBedHeaters : MaxChamberHeaters)) + case 140: // Bed temperature + case 141: // Chamber temperature { - reply.printf("Invalid heater index '%d'", index); - result = GCodeResult::error; - break; - } + Heat& heat = reprap.GetHeat(); + bool seen = false; - // See if the heater number is being set - if (gb.Seen('H')) - { - seen = true; - int heater = gb.GetIValue(); - if (heater < 0) + // Check if the heater index is passed + int index = gb.Seen('P') ? gb.GetIValue() : 0; + if (index < 0 || index >= (int)((code == 140) ? MaxBedHeaters : MaxChamberHeaters)) { - heater = -1; - } - else if (heater >= (int)MaxHeaters) - { - reply.printf("Invalid heater number '%d'", heater); + reply.printf("Invalid heater index '%d'", index); result = GCodeResult::error; break; } - if (code == 141) + // See if the heater number is being set + if (gb.Seen('H')) { - heat.SetChamberHeater(index, heater); + seen = true; + int heater = gb.GetIValue(); + if (heater < 0) + { + heater = -1; + } + else if (heater >= (int)MaxHeaters) + { + reply.printf("Invalid heater number '%d'", heater); + result = GCodeResult::error; + break; + } + + if (code == 141) + { + heat.SetChamberHeater(index, heater); + } + else + { + heat.SetBedHeater(index, heater); + } + platform.UpdateConfiguredHeaters(); } - else + + const int8_t currentHeater = (code == 141) ? heat.GetChamberHeater(index) : heat.GetBedHeater(index); + const char* const heaterName = (code == 141) ? "chamber" : "bed"; + + // Active temperature + if (gb.Seen('S')) { - heat.SetBedHeater(index, heater); + seen = true; + const float temperature = gb.GetFValue(); + if (currentHeater < 0) + { + if (temperature > 0.0) // turning off a non-existent bed or chamber heater is not an error + { + reply.printf("No %s heater has been configured for slot %d", heaterName, index); + result = GCodeResult::error; + } + } + else + { + if (temperature < NEARLY_ABS_ZERO) + { + heat.SwitchOff(currentHeater); + } + else + { + heat.SetActiveTemperature(currentHeater, temperature); + result = heat.Activate(currentHeater, reply); + } + } } - platform.UpdateConfiguredHeaters(); - } - - const int8_t currentHeater = (code == 141) ? heat.GetChamberHeater(index) : heat.GetBedHeater(index); - const char* const heaterName = (code == 141) ? "chamber" : "bed"; - // Active temperature - if (gb.Seen('S')) - { - seen = true; - const float temperature = gb.GetFValue(); - if (currentHeater < 0) + // Standby temperature + if (gb.Seen('R')) { - if (temperature > 0.0) // turning off a non-existent bed or chamber heater is not an error + seen = true; + if (currentHeater < 0) { reply.printf("No %s heater has been configured for slot %d", heaterName, index); result = GCodeResult::error; } + else + { + heat.SetStandbyTemperature(currentHeater, gb.GetFValue()); + } } - else + + if (!seen) { - if (temperature < NEARLY_ABS_ZERO) + if (currentHeater < 0) { - heat.SwitchOff(currentHeater); + reply.printf("No %s heater has been configured for slot %d", heaterName, index); } else { - heat.SetActiveTemperature(currentHeater, temperature); - result = heat.Activate(currentHeater, reply); + reply.printf("%c%s heater %d (slot %d) is currently at %.1f" DEGREE_SYMBOL "C", + toupper(heaterName[0]), heaterName + 1, currentHeater, index, (double)reprap.GetHeat().GetHeaterTemperature(currentHeater)); } } } + break; - // Standby temperature - if (gb.Seen('R')) + case 143: // Configure heater protection + result = reprap.GetHeat().SetHeaterProtection(gb, reply); + break; + + case 144: // Set bed to standby, or to active if S1 parameter given { - seen = true; - if (currentHeater < 0) + const unsigned int index = gb.Seen('P') ? gb.GetUIValue() : 0; + if (index >= MaxBedHeaters) { - reply.printf("No %s heater has been configured for slot %d", heaterName, index); + reply.printf("Invalid bed heater index '%u'", index); result = GCodeResult::error; + break; } - else - { - heat.SetStandbyTemperature(currentHeater, gb.GetFValue()); - } - } - if (!seen) - { - if (currentHeater < 0) - { - reply.printf("No %s heater has been configured for slot %d", heaterName, index); - } - else + const int8_t bedHeater = reprap.GetHeat().GetBedHeater(index); + if (bedHeater >= 0) { - reply.printf("%c%s heater %d (slot %d) is currently at %.1f" DEGREE_SYMBOL "C", - toupper(heaterName[0]), heaterName + 1, currentHeater, index, (double)reprap.GetHeat().GetHeaterTemperature(currentHeater)); + if (gb.Seen('S') && gb.GetIValue() == 1) + { + result = reprap.GetHeat().Activate(bedHeater, reply); + } + else + { + reprap.GetHeat().Standby(bedHeater, nullptr); + } } } - } - break; + break; - case 143: // Configure heater protection - result = reprap.GetHeat().SetHeaterProtection(gb, reply); - break; +#if SUPPORT_DOTSTAR_LED + case 150: + result = DotStarLed::SetColours(gb, reply); + break; +#endif - case 144: // Set bed to standby, or to active if S1 parameter given - { - const unsigned int index = gb.Seen('P') ? gb.GetUIValue() : 0; - if (index >= MaxBedHeaters) + case 190: // Set bed temperature and wait + case 191: // Set chamber temperature and wait + if ( !LockMovementAndWaitForStandstill(gb) // wait until movement has finished + || !IsCodeQueueIdle() // also wait until deferred command queue has caught up to avoid out-of-order execution + ) { - reply.printf("Invalid bed heater index '%u'", index); - result = GCodeResult::error; - break; + return false; } - const int8_t bedHeater = reprap.GetHeat().GetBedHeater(index); - if (bedHeater >= 0) + UnlockMovement(gb); // allow babystepping and pausing while heating { - if (gb.Seen('S') && gb.GetIValue() == 1) + // Check if the heater index is passed + const uint32_t index = gb.Seen('P') ? gb.GetUIValue() : 0; + if (index >= ((code == 190) ? MaxBedHeaters : MaxChamberHeaters)) { - result = reprap.GetHeat().Activate(bedHeater, reply); - } - else - { - reprap.GetHeat().Standby(bedHeater, nullptr); + reply.printf("Invalid heater index '%" PRIu32 "'", index); + result = GCodeResult::error; + break; } - } - } - break; -#if SUPPORT_DOTSTAR_LED - case 150: - result = DotStarLed::SetColours(gb, reply); - break; -#endif + const int8_t heater = (code == 191) ? reprap.GetHeat().GetChamberHeater(index) : reprap.GetHeat().GetBedHeater(index); + if (heater >= 0) + { + float temperature; + bool waitWhenCooling; + if (gb.Seen('R')) + { + waitWhenCooling = true; + temperature = gb.GetFValue(); + } + else if (gb.Seen('S')) + { + waitWhenCooling = false; + temperature = gb.GetFValue(); + } + else + { + break; // no target temperature given + } - case 190: // Set bed temperature and wait - case 191: // Set chamber temperature and wait - if ( !LockMovementAndWaitForStandstill(gb) // wait until movement has finished - || !IsCodeQueueIdle() // also wait until deferred command queue has caught up to avoid out-of-order execution - ) - { - return false; - } + reprap.GetHeat().SetActiveTemperature(heater, temperature); + result = reprap.GetHeat().Activate(heater, reply); + if (cancelWait || reprap.GetHeat().HeaterAtSetTemperature(heater, waitWhenCooling, TEMPERATURE_CLOSE_ENOUGH)) + { + cancelWait = isWaiting = false; + break; + } - UnlockMovement(gb); // allow babystepping and pausing while heating - { - // Check if the heater index is passed - const uint32_t index = gb.Seen('P') ? gb.GetUIValue() : 0; - if (index >= ((code == 190) ? MaxBedHeaters : MaxChamberHeaters)) - { - reply.printf("Invalid heater index '%" PRIu32 "'", index); - result = GCodeResult::error; - break; + CheckReportDue(gb, reply); // check whether we need to send a temperature or status report + isWaiting = true; + return false; + } } + break; - const int8_t heater = (code == 191) ? reprap.GetHeat().GetChamberHeater(index) : reprap.GetHeat().GetBedHeater(index); - if (heater >= 0) + case 200: // Set filament diameter for volumetric extrusion and enable/disable volumetric extrusion + if (gb.Seen('D')) { - float temperature; - bool waitWhenCooling; - if (gb.Seen('R')) + float diameters[MaxExtruders]; + size_t len = MaxExtruders; + gb.GetFloatArray(diameters, len, true); + for (size_t i = 0; i < len; ++i) { - waitWhenCooling = true; - temperature = gb.GetFValue(); + const float d = diameters[i]; + volumetricExtrusionFactors[i] = (d <= 0.0) ? 1.0 : 4.0/(fsquare(d) * Pi); } - else if (gb.Seen('S')) - { - waitWhenCooling = false; - temperature = gb.GetFValue(); - } - else - { - break; // no target temperature given - } - - reprap.GetHeat().SetActiveTemperature(heater, temperature); - result = reprap.GetHeat().Activate(heater, reply); - if (cancelWait || reprap.GetHeat().HeaterAtSetTemperature(heater, waitWhenCooling, TEMPERATURE_CLOSE_ENOUGH)) - { - cancelWait = isWaiting = false; - break; - } - - CheckReportDue(gb, reply); // check whether we need to send a temperature or status report - isWaiting = true; - return false; + gb.MachineState().volumetricExtrusion = (diameters[0] > 0.0); } - } - break; - - case 200: // Set filament diameter for volumetric extrusion and enable/disable volumetric extrusion - if (gb.Seen('D')) - { - float diameters[MaxExtruders]; - size_t len = MaxExtruders; - gb.GetFloatArray(diameters, len, true); - for (size_t i = 0; i < len; ++i) + else if (!gb.MachineState().volumetricExtrusion) { - const float d = diameters[i]; - volumetricExtrusionFactors[i] = (d <= 0.0) ? 1.0 : 4.0/(fsquare(d) * Pi); + reply.copy("Volumetric extrusion is disabled for this input source"); } - gb.MachineState().volumetricExtrusion = (diameters[0] > 0.0); - } - else if (!gb.MachineState().volumetricExtrusion) - { - reply.copy("Volumetric extrusion is disabled for this input source"); - } - else - { - reply.copy("Filament diameters for volumetric extrusion:"); - for (size_t i = 0; i < numExtruders; ++i) + else { - const float vef = volumetricExtrusionFactors[i]; - if (vef == 1.0) - { - reply.cat(" n/a"); - } - else + reply.copy("Filament diameters for volumetric extrusion:"); + for (size_t i = 0; i < numExtruders; ++i) { - reply.catf(" %.03f", (double)(2.0/sqrtf(vef * Pi))); + const float vef = volumetricExtrusionFactors[i]; + if (vef == 1.0) + { + reply.cat(" n/a"); + } + else + { + reply.catf(" %.03f", (double)(2.0/sqrtf(vef * Pi))); + } } } - } - break; + break; - case 201: // Set/print axis accelerations - { - bool seen = false; - for (size_t axis = 0; axis < numTotalAxes; axis++) + case 201: // Set/print axis accelerations { - if (gb.Seen(axisLetters[axis])) + bool seen = false; + for (size_t axis = 0; axis < numTotalAxes; axis++) { - platform.SetAcceleration(axis, gb.GetDistance()); - seen = true; + if (gb.Seen(axisLetters[axis])) + { + platform.SetAcceleration(axis, gb.GetDistance()); + seen = true; + } } - } - if (gb.Seen(extrudeLetter)) - { - seen = true; - float eVals[MaxExtruders]; - size_t eCount = numExtruders; - gb.GetFloatArray(eVals, eCount, true); - for (size_t e = 0; e < eCount; e++) + if (gb.Seen(extrudeLetter)) { - platform.SetAcceleration(ExtruderToLogicalDrive(e), gb.ConvertDistance(eVals[e])); + seen = true; + float eVals[MaxExtruders]; + size_t eCount = numExtruders; + gb.GetFloatArray(eVals, eCount, true); + for (size_t e = 0; e < eCount; e++) + { + platform.SetAcceleration(ExtruderToLogicalDrive(e), gb.ConvertDistance(eVals[e])); + } } - } - if (!seen) - { - reply.printf("Accelerations (mm/sec^2): "); - for (size_t axis = 0; axis < numTotalAxes; ++axis) - { - reply.catf("%c: %.1f, ", axisLetters[axis], (double)platform.Acceleration(axis)); - } - reply.cat("E:"); - char sep = ' '; - for (size_t extruder = 0; extruder < numExtruders; extruder++) + if (!seen) { - reply.catf("%c%.1f", sep, (double)platform.Acceleration(ExtruderToLogicalDrive(extruder))); - sep = ':'; + reply.printf("Accelerations (mm/sec^2): "); + for (size_t axis = 0; axis < numTotalAxes; ++axis) + { + reply.catf("%c: %.1f, ", axisLetters[axis], (double)platform.Acceleration(axis)); + } + reply.cat("E:"); + char sep = ' '; + for (size_t extruder = 0; extruder < numExtruders; extruder++) + { + reply.catf("%c%.1f", sep, (double)platform.Acceleration(ExtruderToLogicalDrive(extruder))); + sep = ':'; + } } } - } - break; - - case 203: // Set/print minimum/maximum feedrates - { - bool seen = false; + break; - // Do the minimum first, because we constrain the maximum rates to be no lower than it - if (gb.Seen('I')) + case 203: // Set/print minimum/maximum feedrates { - seen = true; - platform.SetMinMovementSpeed(gb.GetDistance() * SecondsToMinutes); - } + bool seen = false; - for (size_t axis = 0; axis < numTotalAxes; ++axis) - { - if (gb.Seen(axisLetters[axis])) + // Do the minimum first, because we constrain the maximum rates to be no lower than it + if (gb.Seen('I')) { seen = true; - platform.SetMaxFeedrate(axis, gb.GetDistance() * SecondsToMinutes); + platform.SetMinMovementSpeed(gb.GetDistance() * SecondsToMinutes); } - } - if (gb.Seen(extrudeLetter)) - { - seen = true; - float eVals[MaxExtruders]; - size_t eCount = numExtruders; - gb.GetFloatArray(eVals, eCount, true); - for (size_t e = 0; e < eCount; e++) + for (size_t axis = 0; axis < numTotalAxes; ++axis) { - platform.SetMaxFeedrate(ExtruderToLogicalDrive(e), gb.ConvertDistance(eVals[e]) * SecondsToMinutes); + if (gb.Seen(axisLetters[axis])) + { + seen = true; + platform.SetMaxFeedrate(axis, gb.GetDistance() * SecondsToMinutes); + } } - } - if (!seen) - { - reply.copy("Max speeds (mm/sec): "); - for (size_t axis = 0; axis < numTotalAxes; ++axis) + if (gb.Seen(extrudeLetter)) { - reply.catf("%c: %.1f, ", axisLetters[axis], (double)platform.MaxFeedrate(axis)); + seen = true; + float eVals[MaxExtruders]; + size_t eCount = numExtruders; + gb.GetFloatArray(eVals, eCount, true); + for (size_t e = 0; e < eCount; e++) + { + platform.SetMaxFeedrate(ExtruderToLogicalDrive(e), gb.ConvertDistance(eVals[e]) * SecondsToMinutes); + } } - reply.cat("E:"); - char sep = ' '; - for (size_t extruder = 0; extruder < numExtruders; extruder++) + + if (!seen) { - reply.catf("%c%.1f", sep, (double)platform.MaxFeedrate(ExtruderToLogicalDrive(extruder))); - sep = ':'; + reply.copy("Max speeds (mm/sec): "); + for (size_t axis = 0; axis < numTotalAxes; ++axis) + { + reply.catf("%c: %.1f, ", axisLetters[axis], (double)platform.MaxFeedrate(axis)); + } + reply.cat("E:"); + char sep = ' '; + for (size_t extruder = 0; extruder < numExtruders; extruder++) + { + reply.catf("%c%.1f", sep, (double)platform.MaxFeedrate(ExtruderToLogicalDrive(extruder))); + sep = ':'; + } + reply.catf(", min. speed %.2f", (double)platform.MinMovementSpeed()); } - reply.catf(", min. speed %.2f", (double)platform.MinMovementSpeed()); } - } - break; + break; - case 204: // Set max travel and printing accelerations - result = reprap.GetMove().ConfigureAccelerations(gb, reply); - break; + case 204: // Set max travel and printing accelerations + result = reprap.GetMove().ConfigureAccelerations(gb, reply); + break; - // For case 205 see case 566 + // For case 205 see case 566 - case 206: // Offset axes - result = OffsetAxes(gb, reply); - break; + case 206: // Offset axes + result = OffsetAxes(gb, reply); + break; - case 207: // Set firmware retraction details - { - bool seen = false; - if (gb.Seen('S')) - { - retractLength = max<float>(gb.GetFValue(), 0.0); - seen = true; - } - if (gb.Seen('R')) // must do this one after 'S' + case 207: // Set firmware retraction details { - retractExtra = max<float>(gb.GetFValue(), -retractLength); - seen = true; - } - if (gb.Seen('F')) - { - unRetractSpeed = retractSpeed = max<float>(gb.GetFValue(), 60.0) * SecondsToMinutes; - seen = true; - } - if (gb.Seen('T')) // must do this one after 'F' - { - unRetractSpeed = max<float>(gb.GetFValue(), 60.0) * SecondsToMinutes; - seen = true; - } - if (gb.Seen('Z')) - { - retractHop = max<float>(gb.GetFValue(), 0.0); - seen = true; - } - if (!seen) - { - reply.printf("Retraction/un-retraction settings: length %.2f/%.2fmm, speed %d/%dmm/min, Z hop %.2fmm", - (double)retractLength, (double)(retractLength + retractExtra), (int)(retractSpeed * MinutesToSeconds), (int)(unRetractSpeed * MinutesToSeconds), (double)retractHop); + bool seen = false; + if (gb.Seen('S')) + { + retractLength = max<float>(gb.GetFValue(), 0.0); + seen = true; + } + if (gb.Seen('R')) // must do this one after 'S' + { + retractExtra = max<float>(gb.GetFValue(), -retractLength); + seen = true; + } + if (gb.Seen('F')) + { + unRetractSpeed = retractSpeed = max<float>(gb.GetFValue(), 60.0) * SecondsToMinutes; + seen = true; + } + if (gb.Seen('T')) // must do this one after 'F' + { + unRetractSpeed = max<float>(gb.GetFValue(), 60.0) * SecondsToMinutes; + seen = true; + } + if (gb.Seen('Z')) + { + retractHop = max<float>(gb.GetFValue(), 0.0); + seen = true; + } + if (!seen) + { + reply.printf("Retraction/un-retraction settings: length %.2f/%.2fmm, speed %d/%dmm/min, Z hop %.2fmm", + (double)retractLength, (double)(retractLength + retractExtra), (int)(retractSpeed * MinutesToSeconds), (int)(unRetractSpeed * MinutesToSeconds), (double)retractHop); + } } - } - break; + break; - case 208: // Set/print maximum axis lengths. If there is an S parameter with value 1 then we set the min value, else we set the max value. - { - bool setMin = (gb.Seen('S') ? (gb.GetIValue() == 1) : false); - bool seen = false; - for (size_t axis = 0; axis < numTotalAxes; axis++) + case 208: // Set/print maximum axis lengths. If there is an S parameter with value 1 then we set the min value, else we set the max value. { - if (gb.Seen(axisLetters[axis])) + bool setMin = (gb.Seen('S') ? (gb.GetIValue() == 1) : false); + bool seen = false; + for (size_t axis = 0; axis < numTotalAxes; axis++) { - seen = true; - float values[2]; - size_t numValues = 2; - gb.GetFloatArray(values, numValues, false); - bool ok; - if (numValues == 2) - { - ok = values[1] > values[0]; - if (ok) + if (gb.Seen(axisLetters[axis])) + { + seen = true; + float values[2]; + size_t numValues = 2; + gb.GetFloatArray(values, numValues, false); + bool ok; + if (numValues == 2) { - platform.SetAxisMinimum(axis, values[0], gb.MachineState().runningM501); - platform.SetAxisMaximum(axis, values[1], gb.MachineState().runningM501); + ok = values[1] > values[0]; + if (ok) + { + platform.SetAxisMinimum(axis, values[0], gb.MachineState().runningM501); + platform.SetAxisMaximum(axis, values[1], gb.MachineState().runningM501); + } } - } - else if (setMin) - { - ok = platform.AxisMaximum(axis) > values[0]; - if (ok) + else if (setMin) { - platform.SetAxisMinimum(axis, values[0], gb.MachineState().runningM501); + ok = platform.AxisMaximum(axis) > values[0]; + if (ok) + { + platform.SetAxisMinimum(axis, values[0], gb.MachineState().runningM501); + } } - } - else - { - ok = values[0] > platform.AxisMinimum(axis); - if (ok) + else { - platform.SetAxisMaximum(axis, values[0], gb.MachineState().runningM501); + ok = values[0] > platform.AxisMinimum(axis); + if (ok) + { + platform.SetAxisMaximum(axis, values[0], gb.MachineState().runningM501); + } } - } - if (!ok) - { - reply.printf("%c axis maximum must be greater than minimum", axisLetters[axis]); - result = GCodeResult::error; + if (!ok) + { + reply.printf("%c axis maximum must be greater than minimum", axisLetters[axis]); + result = GCodeResult::error; + } } } - } - if (!seen) - { - reply.copy("Axis limit"); - char sep = 's'; - for (size_t axis = 0; axis < numTotalAxes; axis++) + if (!seen) { - reply.catf("%c %c%.1f:%.1f", sep, axisLetters[axis], (double)platform.AxisMinimum(axis), (double)platform.AxisMaximum(axis)); - sep = ','; + reply.copy("Axis limit"); + char sep = 's'; + for (size_t axis = 0; axis < numTotalAxes; axis++) + { + reply.catf("%c %c%.1f:%.1f", sep, axisLetters[axis], (double)platform.AxisMinimum(axis), (double)platform.AxisMaximum(axis)); + sep = ','; + } } } - } - break; + break; - case 210: // Set/print homing feed rates - // This is no longer used, but for backwards compatibility we don't report an error - break; + case 210: // Set/print homing feed rates + // This is no longer used, but for backwards compatibility we don't report an error + break; - case 220: // Set/report speed factor override percentage - if (gb.Seen('S')) - { - float newSpeedFactor = gb.GetFValue(); - if (newSpeedFactor >= 1.0) + case 220: // Set/report speed factor override percentage + if (gb.Seen('S')) { - // Update the feed rate for ALL input sources, and all feed rates on the stack - const float speedFactorRatio = newSpeedFactor / speedFactor; - for (GCodeBuffer *gb2 : gcodeSources) + float newSpeedFactor = gb.GetFValue(); + if (newSpeedFactor >= 1.0) { - if (gb2 != nullptr) + // Update the feed rate for ALL input sources, and all feed rates on the stack + const float speedFactorRatio = newSpeedFactor / speedFactor; + for (GCodeBuffer *gb2 : gcodeSources) { - GCodeMachineState *ms = &gb2->MachineState(); - while (ms != nullptr) + if (gb2 != nullptr) { - ms->feedRate *= speedFactorRatio; - ms = ms->previous; + GCodeMachineState *ms = &gb2->MachineState(); + while (ms != nullptr) + { + ms->feedRate *= speedFactorRatio; + ms = ms->previous; + } } } + // If the last move hasn't gone yet, update its feed rate too if it is not a firmware retraction + if (segmentsLeft != 0 && !moveBuffer.isFirmwareRetraction) + { + moveBuffer.feedRate *= speedFactorRatio; + } + speedFactor = newSpeedFactor; } - // If the last move hasn't gone yet, update its feed rate too if it is not a firmware retraction - if (segmentsLeft != 0 && !moveBuffer.isFirmwareRetraction) + else { - moveBuffer.feedRate *= speedFactorRatio; + reply.copy("Invalid speed factor"); + result = GCodeResult::error; } - speedFactor = newSpeedFactor; } else { - reply.copy("Invalid speed factor"); - result = GCodeResult::error; + reply.printf("Speed factor override: %.1f%%", (double)speedFactor); } - } - else - { - reply.printf("Speed factor override: %.1f%%", (double)speedFactor); - } - break; - - case 221: // Set/report extrusion factor override percentage - { - uint32_t extruder; - bool seenD = false; - gb.TryGetUIValue('D', extruder, seenD); + break; - const Tool * const ct = reprap.GetCurrentTool(); - if (!seenD && ct == nullptr) + case 221: // Set/report extrusion factor override percentage { - reply.copy("No tool selected"); - result = GCodeResult::error; - } - else if (gb.Seen('S')) // S parameter sets the override percentage - { - const float extrusionFactor = gb.GetFValue() / 100.0; - if (extrusionFactor >= 0.0) + uint32_t extruder; + bool seenD = false; + gb.TryGetUIValue('D', extruder, seenD); + + const Tool * const ct = reprap.GetCurrentTool(); + if (!seenD && ct == nullptr) + { + reply.copy("No tool selected"); + result = GCodeResult::error; + } + else if (gb.Seen('S')) // S parameter sets the override percentage { - if (seenD) + const float extrusionFactor = gb.GetFValue() / 100.0; + if (extrusionFactor >= 0.0) { - if (extruder < numExtruders) + if (seenD) { - ChangeExtrusionFactor(extruder, extrusionFactor); + if (extruder < numExtruders) + { + ChangeExtrusionFactor(extruder, extrusionFactor); + } + } + else + { + ct->IterateExtruders([this, extrusionFactor](unsigned int extruder) { ChangeExtrusionFactor(extruder, extrusionFactor); }); } - } - else - { - ct->IterateExtruders([this, extrusionFactor](unsigned int extruder) { ChangeExtrusionFactor(extruder, extrusionFactor); }); } } + else if (seenD) + { + reply.printf("Extrusion factor override for extruder %" PRIu32 ": %.1f%%", extruder, (double)(extrusionFactors[extruder] * 100.0)); + } + else + { + reply.copy("Extrusion factor(s) for current tool:"); + ct->IterateExtruders([reply, this](unsigned int extruder) { reply.catf(" %.1f%%", (double)(extrusionFactors[extruder] * 100.0)); }); + } } - else if (seenD) - { - reply.printf("Extrusion factor override for extruder %" PRIu32 ": %.1f%%", extruder, (double)(extrusionFactors[extruder] * 100.0)); - } - else - { - reply.copy("Extrusion factor(s) for current tool:"); - ct->IterateExtruders([reply, this](unsigned int extruder) { reply.catf(" %.1f%%", (double)(extrusionFactors[extruder] * 100.0)); }); - } - } - break; + break; - // For case 226, see case 25 + // For case 226, see case 25 - case 260: // I2C send - result = SendI2c(gb, reply); - break; + case 260: // I2C send + result = SendI2c(gb, reply); + break; - case 261: // I2C send - result = ReceiveI2c(gb, reply); - break; + case 261: // I2C send + result = ReceiveI2c(gb, reply); + break; - case 280: // Servos - if (gb.Seen('P')) - { - const uint32_t gpioPortNumber = gb.GetUIValue(); - if (gpioPortNumber < MaxGpioPorts) + case 280: // Servos + if (gb.Seen('P')) { - if (gb.Seen('S')) + const uint32_t gpioPortNumber = gb.GetUIValue(); + if (gpioPortNumber < MaxGpioPorts) { - float angleOrWidth = gb.GetFValue(); - if (angleOrWidth < 0.0) + if (gb.Seen('S')) { - // Disable the servo by setting the pulse width to zero - angleOrWidth = 0.0; - } - else if (angleOrWidth < MinServoPulseWidth) - { - // User gave an angle so convert it to a pulse width in microseconds - angleOrWidth = (min<float>(angleOrWidth, 180.0) * ((MaxServoPulseWidth - MinServoPulseWidth) / 180.0)) + MinServoPulseWidth; - } - else if (angleOrWidth > MaxServoPulseWidth) - { - angleOrWidth = MaxServoPulseWidth; - } + float angleOrWidth = gb.GetFValue(); + if (angleOrWidth < 0.0) + { + // Disable the servo by setting the pulse width to zero + angleOrWidth = 0.0; + } + else if (angleOrWidth < MinServoPulseWidth) + { + // User gave an angle so convert it to a pulse width in microseconds + angleOrWidth = (min<float>(angleOrWidth, 180.0) * ((MaxServoPulseWidth - MinServoPulseWidth) / 180.0)) + MinServoPulseWidth; + } + else if (angleOrWidth > MaxServoPulseWidth) + { + angleOrWidth = MaxServoPulseWidth; + } - const GpOutputPort& gpPort = platform.GetGpioPort(gpioPortNumber); - const float pwm = angleOrWidth * (ServoRefreshFrequency/1e6); + const GpOutputPort& gpPort = platform.GetGpioPort(gpioPortNumber); + const float pwm = angleOrWidth * (ServoRefreshFrequency/1e6); #if SUPPORT_CAN_EXPANSION - if (gpPort.boardAddress != CanId::MasterAddress) - { - result = CanInterface::WriteGpio(gpPort.boardAddress, gpioPortNumber, pwm, true, reply); - break; - } + if (gpPort.boardAddress != CanId::MasterAddress) + { + result = CanInterface::WriteGpio(gpPort.boardAddress, gpioPortNumber, pwm, true, reply); + break; + } #endif - gpPort.port.WriteAnalog(pwm); + gpPort.port.WriteAnalog(pwm); + } + // We don't currently allow the servo position to be read back + } + else + { + reply.printf("Invalid gpio port %" PRIu32, gpioPortNumber); + result = GCodeResult::error; } - // We don't currently allow the servo position to be read back - } - else - { - reply.printf("Invalid gpio port %" PRIu32, gpioPortNumber); - result = GCodeResult::error; } - } - break; + break; - case 290: // Baby stepping - { - const bool absolute = (gb.Seen('R') && gb.GetIValue() == 0); - bool seen = false; - float differences[MaxAxes]; - for (size_t axis = 0; axis < numVisibleAxes; ++axis) + case 290: // Baby stepping { - if (gb.Seen(axisLetters[axis]) || (axis == 2 && gb.Seen('S'))) // S is a synonym for Z + const bool absolute = (gb.Seen('R') && gb.GetIValue() == 0); + bool seen = false; + float differences[MaxAxes]; + for (size_t axis = 0; axis < numVisibleAxes; ++axis) { - seen = true; - const float fval = gb.GetFValue(); - if (absolute) + if (gb.Seen(axisLetters[axis]) || (axis == 2 && gb.Seen('S'))) // S is a synonym for Z { - differences[axis] = fval - GetTotalBabyStepOffset(axis); + seen = true; + const float fval = gb.GetFValue(); + if (absolute) + { + differences[axis] = fval - GetTotalBabyStepOffset(axis); + } + else + { + differences[axis] = constrain<float>(fval, -1.0, 1.0); + } } else { - differences[axis] = constrain<float>(fval, -1.0, 1.0); + differences[axis] = 0.0; } } - else - { - differences[axis] = 0.0; - } - } - if (seen) - { - if (!LockMovement(gb)) - { - return false; - } - - // Perform babystepping synchronously with moves - bool haveResidual = false; - for (size_t axis = 0; axis < numVisibleAxes; ++axis) + if (seen) { - currentBabyStepOffsets[axis] += differences[axis]; - const float amountPushed = reprap.GetMove().PushBabyStepping(axis, differences[axis]); - moveBuffer.initialCoords[axis] += amountPushed; + if (!LockMovement(gb)) + { + return false; + } - // The following causes all the remaining baby stepping that we didn't manage to push to be added to the [remainder of the] currently-executing move, if there is one. - // This could result in an abrupt Z movement, however the move will be processed as normal so the jerk limit will be honoured. - moveBuffer.coords[axis] += differences[axis]; - if (amountPushed != differences[axis]) + // Perform babystepping synchronously with moves + bool haveResidual = false; + for (size_t axis = 0; axis < numVisibleAxes; ++axis) { - haveResidual = true; + currentBabyStepOffsets[axis] += differences[axis]; + const float amountPushed = reprap.GetMove().PushBabyStepping(axis, differences[axis]); + moveBuffer.initialCoords[axis] += amountPushed; + + // The following causes all the remaining baby stepping that we didn't manage to push to be added to the [remainder of the] currently-executing move, if there is one. + // This could result in an abrupt Z movement, however the move will be processed as normal so the jerk limit will be honoured. + moveBuffer.coords[axis] += differences[axis]; + if (amountPushed != differences[axis]) + { + haveResidual = true; + } } - } - if (haveResidual && segmentsLeft == 0 && reprap.GetMove().AllMovesAreFinished()) - { - // The pipeline is empty, so execute the babystepping move immediately - SetMoveBufferDefaults(); - moveBuffer.feedRate = DefaultFeedRate; - NewMoveAvailable(1); + if (haveResidual && segmentsLeft == 0 && reprap.GetMove().AllMovesAreFinished()) + { + // The pipeline is empty, so execute the babystepping move immediately + SetMoveBufferDefaults(); + moveBuffer.feedRate = DefaultFeedRate; + NewMoveAvailable(1); + } } - } - else - { - reply.printf("Baby stepping offsets (mm):"); - for (size_t axis = 0; axis < numVisibleAxes; ++axis) + else { - reply.catf(" %c:%.3f", axisLetters[axis], (double)GetTotalBabyStepOffset(axis)); + reply.printf("Baby stepping offsets (mm):"); + for (size_t axis = 0; axis < numVisibleAxes; ++axis) + { + reply.catf(" %c:%.3f", axisLetters[axis], (double)GetTotalBabyStepOffset(axis)); + } } } - } - break; + break; - case 291: // Display message, optionally wait for acknowledgement - { - bool seen = false; - String<MaxMessageLength> title; - gb.TryGetQuotedString('R', title.GetRef(), seen); + case 291: // Display message, optionally wait for acknowledgement + { + bool seen = false; + String<MaxMessageLength> title; + gb.TryGetQuotedString('R', title.GetRef(), seen); - String<MaxMessageLength> message; - gb.TryGetQuotedString('P', message.GetRef(), seen); + String<MaxMessageLength> message; + gb.TryGetQuotedString('P', message.GetRef(), seen); - if (seen) - { - int32_t sParam = 1; - gb.TryGetIValue('S', sParam, seen); - if (sParam < 0 || sParam > 3) + if (seen) { - reply.copy("Invalid message box mode"); - result = GCodeResult::error; - break; - } + int32_t sParam = 1; + gb.TryGetIValue('S', sParam, seen); + if (sParam < 0 || sParam > 3) + { + reply.copy("Invalid message box mode"); + result = GCodeResult::error; + break; + } - float tParam; - if (sParam == 0 || sParam == 1) - { - tParam = DefaultMessageTimeout; - gb.TryGetFValue('T', tParam, seen); - } - else - { - tParam = 0.0; - } + float tParam; + if (sParam == 0 || sParam == 1) + { + tParam = DefaultMessageTimeout; + gb.TryGetFValue('T', tParam, seen); + } + else + { + tParam = 0.0; + } - if (sParam == 0 && tParam <= 0.0) - { - reply.copy("Attempt to create a message box that cannot be dismissed"); - result = GCodeResult::error; - break; - } + if (sParam == 0 && tParam <= 0.0) + { + reply.copy("Attempt to create a message box that cannot be dismissed"); + result = GCodeResult::error; + break; + } - AxesBitmap axisControls = 0; - for (size_t axis = 0; axis < numTotalAxes; axis++) - { - if (gb.Seen(axisLetters[axis]) && gb.GetIValue() > 0) + AxesBitmap axisControls = 0; + for (size_t axis = 0; axis < numTotalAxes; axis++) { - SetBit(axisControls, axis); + if (gb.Seen(axisLetters[axis]) && gb.GetIValue() > 0) + { + SetBit(axisControls, axis); + } } - } - // Don't lock the movement system, because if we do then only the channel that issues the M291 can move the axes + // Don't lock the movement system, because if we do then only the channel that issues the M291 can move the axes - // If we need to wait for an acknowledgement, save the state and set waiting - if ((sParam == 2 || sParam == 3) && Push(gb, true)) // stack the machine state including the file position - { - UnlockMovement(gb); // allow movement so that e.g. an SD card print can call M291 and then DWC or PanelDue can be used to jog axes - gb.MachineState().CloseFile(); // stop reading from file - gb.MachineState().waitingForAcknowledgement = true; // flag that we are waiting for acknowledgement - } + // If we need to wait for an acknowledgement, save the state and set waiting + if ((sParam == 2 || sParam == 3) && Push(gb, true)) // stack the machine state including the file position + { + UnlockMovement(gb); // allow movement so that e.g. an SD card print can call M291 and then DWC or PanelDue can be used to jog axes + gb.MachineState().CloseFile(); // stop reading from file + gb.MachineState().waitingForAcknowledgement = true; // flag that we are waiting for acknowledgement + } - // Display the message box on all relevant devices. Acknowledging any one of them clears them all. - const MessageType mt = GetMessageBoxDevice(gb); // get the display device - platform.SendAlert(mt, message.c_str(), title.c_str(), (int)sParam, tParam, axisControls); + // Display the message box on all relevant devices. Acknowledging any one of them clears them all. + const MessageType mt = GetMessageBoxDevice(gb); // get the display device + platform.SendAlert(mt, message.c_str(), title.c_str(), (int)sParam, tParam, axisControls); + } } - } - break; - - case 292: // Acknowledge message - { - reprap.ClearAlert(); + break; - const bool cancelled = (gb.Seen('P') && gb.GetIValue() == 1); - for (GCodeBuffer* targetGb : gcodeSources) + case 292: // Acknowledge message { - if (targetGb != nullptr) + reprap.ClearAlert(); + + const bool cancelled = (gb.Seen('P') && gb.GetIValue() == 1); + for (GCodeBuffer* targetGb : gcodeSources) { - targetGb->MessageAcknowledged(cancelled); + if (targetGb != nullptr) + { + targetGb->MessageAcknowledged(cancelled); + } } } - } - break; - - case 300: // Beep - { - const unsigned int ms = (gb.Seen('P')) ? gb.GetUIValue() : 1000; // time in milliseconds - const unsigned int freq = (gb.Seen('S')) ? gb.GetUIValue() : 4600; // 4600Hz produces the loudest sound on a PanelDue - reprap.Beep(freq, ms); - } - break; - - case 301: // Set/report hot end PID values - result = reprap.GetHeat().SetPidParameters(1, gb, reply); - break; + break; - case 302: // Allow, deny or report cold extrudes and configure minimum extrusion/retraction temps - { - bool seen = false; - if (gb.Seen('P')) + case 300: // Beep { - if (!LockMovementAndWaitForStandstill(gb)) - { - return false; - } - seen = true; - reprap.GetHeat().AllowColdExtrude(gb.GetIValue() > 0); + const unsigned int ms = (gb.Seen('P')) ? gb.GetUIValue() : 1000; // time in milliseconds + const unsigned int freq = (gb.Seen('S')) ? gb.GetUIValue() : 4600; // 4600Hz produces the loudest sound on a PanelDue + reprap.Beep(freq, ms); } - if (gb.Seen('S')) + break; + + case 301: // Set/report hot end PID values + result = reprap.GetHeat().SetPidParameters(1, gb, reply); + break; + + case 302: // Allow, deny or report cold extrudes and configure minimum extrusion/retraction temps { - if (!LockMovementAndWaitForStandstill(gb)) + bool seen = false; + if (gb.Seen('P')) { - return false; + if (!LockMovementAndWaitForStandstill(gb)) + { + return false; + } + seen = true; + reprap.GetHeat().AllowColdExtrude(gb.GetIValue() > 0); } - seen = true; - reprap.GetHeat().SetExtrusionMinTemp(gb.GetFValue()); - } - if (gb.Seen('R')) - { - if (!LockMovementAndWaitForStandstill(gb)) + if (gb.Seen('S')) { - return false; + if (!LockMovementAndWaitForStandstill(gb)) + { + return false; + } + seen = true; + reprap.GetHeat().SetExtrusionMinTemp(gb.GetFValue()); } - seen = true; - reprap.GetHeat().SetRetractionMinTemp(gb.GetFValue()); - } - if (!seen) - { - if (reprap.GetHeat().ColdExtrude()) + if (gb.Seen('R')) { - reply.copy("Cold extrusion is allowed (use M302 P0 to forbid it)"); + if (!LockMovementAndWaitForStandstill(gb)) + { + return false; + } + seen = true; + reprap.GetHeat().SetRetractionMinTemp(gb.GetFValue()); } - else + if (!seen) { - reply.printf("Cold extrusion is forbidden (use M302 P1 to allow it), min. extrusion temperature %.1fC, min. retraction temperature %.1fC", - (double)reprap.GetHeat().GetExtrusionMinTemp(), (double)reprap.GetHeat().GetRetractionMinTemp()); + if (reprap.GetHeat().ColdExtrude()) + { + reply.copy("Cold extrusion is allowed (use M302 P0 to forbid it)"); + } + else + { + reply.printf("Cold extrusion is forbidden (use M302 P1 to allow it), min. extrusion temperature %.1fC, min. retraction temperature %.1fC", + (double)reprap.GetHeat().GetExtrusionMinTemp(), (double)reprap.GetHeat().GetRetractionMinTemp()); + } } } - } - break; + break; - case 303: // Run PID tuning - result = reprap.GetHeat().TuneHeater(gb, reply); - break; + case 303: // Run PID tuning + result = reprap.GetHeat().TuneHeater(gb, reply); + break; - case 304: // Set/report heated bed PID values - result = reprap.GetHeat().SetPidParameters(0, gb, reply); - break; + case 304: // Set/report heated bed PID values + result = reprap.GetHeat().SetPidParameters(0, gb, reply); + break; - case 305: // Set/report specific heater parameters - reply.copy("M305 has been replaced by M308 and M950 in RepRapFirmware 3"); - result = GCodeResult::error; - break; + case 305: // Set/report specific heater parameters + reply.copy("M305 has been replaced by M308 and M950 in RepRapFirmware 3"); + result = GCodeResult::error; + break; - case 307: // Set heater process model parameters - result = reprap.GetHeat().SetOrReportHeaterModel(gb, reply); - break; + case 307: // Set heater process model parameters + result = reprap.GetHeat().SetOrReportHeaterModel(gb, reply); + break; - case 308: - result = reprap.GetHeat().ConfigureSensor(gb, reply); - break; + case 308: + result = reprap.GetHeat().ConfigureSensor(gb, reply); + break; - case 350: // Set/report microstepping - { - bool interp = (gb.Seen('I') && gb.GetIValue() > 0); - bool seen = false; - for (size_t axis = 0; axis < numTotalAxes; axis++) + case 350: // Set/report microstepping { - if (gb.Seen(axisLetters[axis])) + bool interp = (gb.Seen('I') && gb.GetIValue() > 0); + bool seen = false; + for (size_t axis = 0; axis < numTotalAxes; axis++) + { + if (gb.Seen(axisLetters[axis])) + { + if (!LockMovementAndWaitForStandstill(gb)) + { + return false; + } + seen = true; + const unsigned int microsteps = gb.GetUIValue(); + if (ChangeMicrostepping(axis, microsteps, interp, reply)) + { + SetAxisNotHomed(axis); + } + else + { + result = GCodeResult::error; + } + } + } + + if (gb.Seen(extrudeLetter)) { if (!LockMovementAndWaitForStandstill(gb)) { return false; } seen = true; - const unsigned int microsteps = gb.GetUIValue(); - if (ChangeMicrostepping(axis, microsteps, interp, reply)) - { - SetAxisNotHomed(axis); - } - else + uint32_t eVals[MaxExtruders]; + size_t eCount = numExtruders; + gb.GetUnsignedArray(eVals, eCount, true); + for (size_t e = 0; e < eCount; e++) { - result = GCodeResult::error; + if (!ChangeMicrostepping(ExtruderToLogicalDrive(e), eVals[e], interp, reply)) + { + result = GCodeResult::error; + } } } - } - if (gb.Seen(extrudeLetter)) - { - if (!LockMovementAndWaitForStandstill(gb)) - { - return false; - } - seen = true; - uint32_t eVals[MaxExtruders]; - size_t eCount = numExtruders; - gb.GetUnsignedArray(eVals, eCount, true); - for (size_t e = 0; e < eCount; e++) + if (!seen) { - if (!ChangeMicrostepping(ExtruderToLogicalDrive(e), eVals[e], interp, reply)) + reply.copy("Microstepping - "); + for (size_t axis = 0; axis < numTotalAxes; ++axis) { - result = GCodeResult::error; + bool actualInterp; + const unsigned int microsteps = platform.GetMicrostepping(axis, actualInterp); + reply.catf("%c:%u%s, ", axisLetters[axis], microsteps, (actualInterp) ? "(on)" : ""); + } + reply.cat("E"); + for (size_t extruder = 0; extruder < numExtruders; extruder++) + { + bool actualInterp; + const unsigned int microsteps = platform.GetMicrostepping(ExtruderToLogicalDrive(extruder), actualInterp); + reply.catf(":%u%s", microsteps, (actualInterp) ? "(on)" : ""); } } } + break; + +#if HAS_MASS_STORAGE + case 374: // Save grid and height map to file + result = SaveHeightMap(gb, reply); + break; + + case 375: // Load grid and height map from file and enable compensation + if (!LockMovementAndWaitForStandstill(gb)) + { + return false; + } + result = LoadHeightMap(gb, reply); + break; +#endif - if (!seen) + case 376: // Set taper height { - reply.copy("Microstepping - "); - for (size_t axis = 0; axis < numTotalAxes; ++axis) + Move& move = reprap.GetMove(); + if (gb.Seen('H')) + { + move.SetTaperHeight(gb.GetFValue()); + } + else if (move.GetTaperHeight() > 0.0) { - bool actualInterp; - const unsigned int microsteps = platform.GetMicrostepping(axis, actualInterp); - reply.catf("%c:%u%s, ", axisLetters[axis], microsteps, (actualInterp) ? "(on)" : ""); + reply.printf("Bed compensation taper height is %.1fmm", (double)move.GetTaperHeight()); } - reply.cat("E"); - for (size_t extruder = 0; extruder < numExtruders; extruder++) + else { - bool actualInterp; - const unsigned int microsteps = platform.GetMicrostepping(ExtruderToLogicalDrive(extruder), actualInterp); - reply.catf(":%u%s", microsteps, (actualInterp) ? "(on)" : ""); + reply.copy("Bed compensation is not tapered"); } } - } - break; - -#if HAS_MASS_STORAGE - case 374: // Save grid and height map to file - result = SaveHeightMap(gb, reply); - break; - - case 375: // Load grid and height map from file and enable compensation - if (!LockMovementAndWaitForStandstill(gb)) - { - return false; - } - result = LoadHeightMap(gb, reply); - break; -#endif + break; - case 376: // Set taper height - { - Move& move = reprap.GetMove(); - if (gb.Seen('H')) + case 400: // Wait for current moves to finish + if (!LockMovementAndWaitForStandstill(gb)) { - move.SetTaperHeight(gb.GetFValue()); + return false; } - else if (move.GetTaperHeight() > 0.0) + break; + + case 401: // Deploy Z probe + if (platform.GetCurrentZProbeType() != ZProbeType::none) { - reply.printf("Bed compensation taper height is %.1fmm", (double)move.GetTaperHeight()); + probeIsDeployed = true; + DoFileMacro(gb, DEPLOYPROBE_G, false, 401); } - else + break; + + case 402: // Retract Z probe + if (platform.GetCurrentZProbeType() != ZProbeType::none) { - reply.copy("Bed compensation is not tapered"); + probeIsDeployed = false; + DoFileMacro(gb, RETRACTPROBE_G, false, 402); } - } - break; - - case 400: // Wait for current moves to finish - if (!LockMovementAndWaitForStandstill(gb)) - { - return false; - } - break; - - case 401: // Deploy Z probe - if (platform.GetCurrentZProbeType() != ZProbeType::none) - { - probeIsDeployed = true; - DoFileMacro(gb, DEPLOYPROBE_G, false, 401); - } - break; + break; - case 402: // Retract Z probe - if (platform.GetCurrentZProbeType() != ZProbeType::none) - { - probeIsDeployed = false; - DoFileMacro(gb, RETRACTPROBE_G, false, 402); - } - break; + case 404: // Filament width and nozzle diameter + { + bool seen = false; - case 404: // Filament width and nozzle diameter - { - bool seen = false; + if (gb.Seen('N')) + { + platform.SetFilamentWidth(gb.GetFValue()); + seen = true; + } + if (gb.Seen('D')) + { + platform.SetNozzleDiameter(gb.GetFValue()); + seen = true; + } - if (gb.Seen('N')) - { - platform.SetFilamentWidth(gb.GetFValue()); - seen = true; - } - if (gb.Seen('D')) - { - platform.SetNozzleDiameter(gb.GetFValue()); - seen = true; + if (!seen) + { + reply.printf("Filament width: %.2fmm, nozzle diameter: %.2fmm", (double)platform.GetFilamentWidth(), (double)platform.GetNozzleDiameter()); + } } + break; - if (!seen) + case 408: // Get status in JSON format { - reply.printf("Filament width: %.2fmm, nozzle diameter: %.2fmm", (double)platform.GetFilamentWidth(), (double)platform.GetNozzleDiameter()); - } - } - break; - - case 408: // Get status in JSON format - { - const unsigned int form = (gb.Seen('P')) ? gb.GetUIValue() : 0; - const unsigned int type = gb.Seen('S') ? gb.GetUIValue() : 0; + const unsigned int form = (gb.Seen('P')) ? gb.GetUIValue() : 0; + const unsigned int type = gb.Seen('S') ? gb.GetUIValue() : 0; #if SUPPORT_CAN_EXPANSION - const uint32_t board = (gb.Seen('B')) ? gb.GetUIValue() : 0; - if (board != 0) - { - result = CanInterface::RemoteM408(board, form, type, gb, reply); - break; - } + const uint32_t board = (gb.Seen('B')) ? gb.GetUIValue() : 0; + if (board != 0) + { + result = CanInterface::RemoteM408(board, form, type, gb, reply); + break; + } #endif - switch (form) - { - case 0: + switch (form) { - const int seq = gb.Seen('R') ? gb.GetIValue() : -1; - if (&gb == auxGCode && (type == 0 || type == 2)) + case 0: { - lastAuxStatusReportType = type; - } + const int seq = gb.Seen('R') ? gb.GetIValue() : -1; + if (&gb == auxGCode && (type == 0 || type == 2)) + { + lastAuxStatusReportType = type; + } - outBuf = GenerateJsonStatusResponse(type, seq, (&gb == auxGCode) ? ResponseSource::AUX : ResponseSource::Generic); - if (outBuf == nullptr) - { - result = GCodeResult::notFinished; // we ran out of buffers, so try again later + outBuf = GenerateJsonStatusResponse(type, seq, (&gb == auxGCode) ? ResponseSource::AUX : ResponseSource::Generic); + if (outBuf == nullptr) + { + result = GCodeResult::notFinished; // we ran out of buffers, so try again later + } } - } - break; + break; #if SUPPORT_OBJECT_MODEL - case 1: - { - String<MediumStringLength> filter; - bool dummy; - gb.TryGetQuotedString('F', filter.GetRef(), dummy); - if (!OutputBuffer::Allocate(outBuf)) - { - result = GCodeResult::notFinished; - } - else + case 1: { - reprap.ReportAsJson(outBuf, filter.c_str(), ObjectModel::flagsNone); + String<MediumStringLength> filter; + bool dummy; + gb.TryGetQuotedString('F', filter.GetRef(), dummy); + if (!OutputBuffer::Allocate(outBuf)) + { + result = GCodeResult::notFinished; + } + else + { + reprap.ReportAsJson(outBuf, filter.c_str(), ObjectModel::flagsNone); + } } - } - break; + break; #endif - default: - break; + default: + break; + } } - } - break; - - case 450: // Report printer mode - reply.printf("PrinterMode:%s", GetMachineModeString()); - break; - - case 451: // Select FFF printer mode - if (!LockMovementAndWaitForStandstill(gb)) - { - return false; - } - machineType = MachineType::fff; - break; - -#if SUPPORT_LASER - case 452: // Select laser mode - if (!LockMovementAndWaitForStandstill(gb)) - { - return false; - } + break; - machineType = MachineType::laser; - Move::CreateLaserTask(); + case 450: // Report printer mode + reply.printf("PrinterMode:%s", GetMachineModeString()); + break; - if (gb.Seen('C')) - { - if (platform.AssignLaserPin(gb, reply)) - { - reply.copy("Laser mode selected"); - } - else - { - result = GCodeResult::error; - } - } - if (gb.Seen('F')) - { - platform.SetLaserPwmFrequency(gb.GetPwmFrequency()); - } - if (result == GCodeResult::ok) - { - if (gb.Seen('S')) - { - laserPowerSticky = (gb.GetUIValue() == 1); - } - if (gb.Seen('R')) + case 451: // Select FFF printer mode + if (!LockMovementAndWaitForStandstill(gb)) { - laserMaxPower = max<float>(1.0, gb.GetFValue()); + return false; } - } - break; -#endif + machineType = MachineType::fff; + break; - case 453: // Select CNC mode - if (!LockMovementAndWaitForStandstill(gb)) - { - return false; - } - { - const MachineType oldMachineType = machineType; - machineType = MachineType::cnc; // switch to CNC mode even if the spindle parameter is bad - const uint32_t slot = gb.Seen('S') ? gb.GetUIValue() : 0; - if (slot >= MaxSpindles) +#if SUPPORT_LASER + case 452: // Select laser mode + if (!LockMovementAndWaitForStandstill(gb)) { - reply.copy("Invalid spindle index"); - result = GCodeResult::error; - break; + return false; } - Spindle& spindle = platform.AccessSpindle(slot); + machineType = MachineType::laser; + Move::CreateLaserTask(); + if (gb.Seen('C')) { - if (!spindle.AllocatePins(gb, reply)) + if (platform.AssignLaserPin(gb, reply)) + { + reply.copy("Laser mode selected"); + } + else { result = GCodeResult::error; - break; } } if (gb.Seen('F')) { - spindle.SetFrequency(gb.GetPwmFrequency()); + platform.SetLaserPwmFrequency(gb.GetPwmFrequency()); } - if (gb.Seen('R')) + if (result == GCodeResult::ok) { - spindle.SetMaxRpm(max<float>(1.0, gb.GetFValue())); + if (gb.Seen('S')) + { + laserPowerSticky = (gb.GetUIValue() == 1); + } + if (gb.Seen('R')) + { + laserMaxPower = max<float>(1.0, gb.GetFValue()); + } } - if (gb.Seen('T')) + break; +#endif + + case 453: // Select CNC mode + if (!LockMovementAndWaitForStandstill(gb)) { - spindle.SetToolNumber(gb.GetIValue()); + return false; } - - // M453 may be repeated to set up multiple spindles, so only print the message on the initial switch - if (oldMachineType != MachineType::cnc) { - reply.copy("CNC mode selected"); + const MachineType oldMachineType = machineType; + machineType = MachineType::cnc; // switch to CNC mode even if the spindle parameter is bad + const uint32_t slot = gb.Seen('S') ? gb.GetUIValue() : 0; + if (slot >= MaxSpindles) + { + reply.copy("Invalid spindle index"); + result = GCodeResult::error; + break; + } + + Spindle& spindle = platform.AccessSpindle(slot); + if (gb.Seen('C')) + { + if (!spindle.AllocatePins(gb, reply)) + { + result = GCodeResult::error; + break; + } + } + if (gb.Seen('F')) + { + spindle.SetFrequency(gb.GetPwmFrequency()); + } + if (gb.Seen('R')) + { + spindle.SetMaxRpm(max<float>(1.0, gb.GetFValue())); + } + if (gb.Seen('T')) + { + spindle.SetToolNumber(gb.GetIValue()); + } + + // M453 may be repeated to set up multiple spindles, so only print the message on the initial switch + if (oldMachineType != MachineType::cnc) + { + reply.copy("CNC mode selected"); + } } - } - break; + break; #if HAS_MASS_STORAGE - case 470: // mkdir - { - String<MaxFilenameLength> dirName; - if (!gb.Seen('P') || !gb.GetQuotedString(dirName.GetRef())) + case 470: // mkdir { - reply.copy("Bad or missing P parameter"); - result = GCodeResult::error; - break; + gb.MustSee('P'); + String<MaxFilenameLength> dirName; + gb.GetQuotedString(dirName.GetRef()); + MassStorage::MakeDirectory(dirName.c_str()); } - MassStorage::MakeDirectory(dirName.c_str()); - } - break; + break; - case 471: // move/rename file/directory - { - String<MaxFilenameLength> oldVal; - if (!gb.Seen('S') || !gb.GetQuotedString(oldVal.GetRef())) + case 471: // move/rename file/directory { - reply.copy("Bad or missing S parameter"); - result = GCodeResult::error; - break; - } - String<MaxFilenameLength> newVal; - if (!gb.Seen('T') || !gb.GetQuotedString(newVal.GetRef())) - { - reply.copy("Bad or missing T parameter"); - result = GCodeResult::error; - break; - } - if (gb.Seen('D') && gb.GetUIValue() == 1 && MassStorage::FileExists(oldVal.c_str()) && MassStorage::FileExists(newVal.c_str())) - { - MassStorage::Delete(newVal.c_str()); + gb.MustSee('S'); + String<MaxFilenameLength> oldVal; + gb.GetQuotedString(oldVal.GetRef()); + String<MaxFilenameLength> newVal; + gb.MustSee('T'); + gb.GetQuotedString(newVal.GetRef()); + if (gb.Seen('D') && gb.GetUIValue() == 1 && MassStorage::FileExists(oldVal.c_str()) && MassStorage::FileExists(newVal.c_str())) + { + MassStorage::Delete(newVal.c_str()); + } + MassStorage::Rename(oldVal.c_str(), newVal.c_str()); } - MassStorage::Rename(oldVal.c_str(), newVal.c_str()); - } - break; + break; - case 500: // Store parameters in config-override.g - result = WriteConfigOverrideFile(gb, reply); - break; + case 500: // Store parameters in config-override.g + result = WriteConfigOverrideFile(gb, reply); + break; #endif - case 501: // Load parameters from config-override.g - if (!gb.MachineState().runningM502 && !gb.MachineState().runningM501) // when running M502 we ignore config-override.g - { - if (runningConfigFile) + case 501: // Load parameters from config-override.g + if (!gb.MachineState().runningM502 && !gb.MachineState().runningM501) // when running M502 we ignore config-override.g { - m501SeenInConfigFile = true; + if (runningConfigFile) + { + m501SeenInConfigFile = true; + } + DoFileMacro(gb, CONFIG_OVERRIDE_G, true, code); } - DoFileMacro(gb, CONFIG_OVERRIDE_G, true, code); - } - break; + break; - case 502: // Revert to default "factory settings" ignoring values in config-override.g - if (!gb.MachineState().runningM502) // avoid recursion - { - if (!LockMovementAndWaitForStandstill(gb)) + case 502: // Revert to default "factory settings" ignoring values in config-override.g + if (!gb.MachineState().runningM502) // avoid recursion { - return false; + if (!LockMovementAndWaitForStandstill(gb)) + { + return false; + } + reprap.GetHeat().SwitchOffAll(true); // turn heaters off before changing the models + reprap.GetHeat().ResetHeaterModels(); // in case some heaters have no M307 commands in config.g + reprap.GetMove().GetKinematics().SetCalibrationDefaults(); // in case M665/M666/M667/M669 in config.g don't define all the parameters + platform.GetEndstops().SetZProbeDefaults(); + DoFileMacro(gb, CONFIG_FILE, true, code); } - reprap.GetHeat().SwitchOffAll(true); // turn heaters off before changing the models - reprap.GetHeat().ResetHeaterModels(); // in case some heaters have no M307 commands in config.g - reprap.GetMove().GetKinematics().SetCalibrationDefaults(); // in case M665/M666/M667/M669 in config.g don't define all the parameters - platform.GetEndstops().SetZProbeDefaults(); - DoFileMacro(gb, CONFIG_FILE, true, code); - } - break; + break; #if HAS_MASS_STORAGE - case 503: // List variable settings - { - if (!LockFileSystem(gb)) + case 503: // List variable settings { - return false; - } + if (!LockFileSystem(gb)) + { + return false; + } - // Need a valid output buffer to continue - if (!OutputBuffer::Allocate(outBuf)) - { - // No buffer available, try again later - return false; - } + // Need a valid output buffer to continue + if (!OutputBuffer::Allocate(outBuf)) + { + // No buffer available, try again later + return false; + } - // Read the entire file - FileStore * const f = platform.OpenSysFile(platform.GetConfigFile(), OpenMode::read); - if (f == nullptr) - { - reply.copy("Configuration file not found"); - result = GCodeResult::error; - } - else - { - char fileBuffer[FILE_BUFFER_SIZE]; - size_t bytesRead, - bytesLeftForWriting = OutputBuffer::GetBytesLeft(outBuf); - while ((bytesRead = f->Read(fileBuffer, FILE_BUFFER_SIZE)) > 0 && bytesLeftForWriting > 0) + // Read the entire file + FileStore * const f = platform.OpenSysFile(platform.GetConfigFile(), OpenMode::read); + if (f == nullptr) { - // Don't write more data than we can process - if (bytesRead < bytesLeftForWriting) - { - bytesLeftForWriting -= bytesRead; - } - else + reply.copy("Configuration file not found"); + result = GCodeResult::error; + } + else + { + char fileBuffer[FILE_BUFFER_SIZE]; + size_t bytesRead, + bytesLeftForWriting = OutputBuffer::GetBytesLeft(outBuf); + while ((bytesRead = f->Read(fileBuffer, FILE_BUFFER_SIZE)) > 0 && bytesLeftForWriting > 0) { - bytesRead = bytesLeftForWriting; - bytesLeftForWriting = 0; - } + // Don't write more data than we can process + if (bytesRead < bytesLeftForWriting) + { + bytesLeftForWriting -= bytesRead; + } + else + { + bytesRead = bytesLeftForWriting; + bytesLeftForWriting = 0; + } - // Write it - outBuf->cat(fileBuffer, bytesRead); + // Write it + outBuf->cat(fileBuffer, bytesRead); + } + f->Close(); } - f->Close(); } - } - break; + break; - case 505: // set sys folder - if (gb.Seen('P')) - { - // Lock movement to try to prevent other threads opening system files while we change the system path - if (!LockMovementAndWaitForStandstill(gb)) + case 505: // set sys folder + if (gb.Seen('P')) { - return false; + // Lock movement to try to prevent other threads opening system files while we change the system path + if (!LockMovementAndWaitForStandstill(gb)) + { + return false; + } + String<MaxFilenameLength> path; + gb.GetQuotedString(path.GetRef()); + result = platform.SetSysDir(path.c_str(), reply); } - String<MaxFilenameLength> path; - gb.GetQuotedString(path.GetRef()); - result = platform.SetSysDir(path.c_str(), reply); - } - else - { - String<MaxFilenameLength> path; - platform.GetSysDir(path.GetRef()); - reply.printf("Sys file path is %s", path.c_str()); - } - break; + else + { + String<MaxFilenameLength> path; + platform.GetSysDir(path.GetRef()); + reply.printf("Sys file path is %s", path.c_str()); + } + break; #endif - case 540: // Set/report MAC address - if (!gb.MachineState().runningM502) // when running M502 we don't execute network-related commands - { - const unsigned int interface = (gb.Seen('I') ? gb.GetUIValue() : 0); - if (gb.Seen('P')) + case 540: // Set/report MAC address + if (!gb.MachineState().runningM502) // when running M502 we don't execute network-related commands { - uint8_t mac[6]; - if (gb.GetMacAddress(mac)) + const unsigned int interface = (gb.Seen('I') ? gb.GetUIValue() : 0); + if (gb.Seen('P')) { + uint8_t mac[6]; + gb.GetMacAddress(mac); reprap.GetNetwork().SetMacAddress(interface, mac); } else { - reply.copy("Bad MAC address"); - result = GCodeResult::error; + const uint8_t * const mac = reprap.GetNetwork().GetMacAddress(interface); + reply.printf("MAC: %02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); } } - else - { - const uint8_t * const mac = reprap.GetNetwork().GetMacAddress(interface); - reply.printf("MAC: %02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - } - } - break; + break; - case 550: // Set/report machine name + case 550: // Set/report machine name #if HAS_LINUX_INTERFACE - if (reprap.UsingLinuxInterface() && !gb.IsBinary()) - { - result = GCodeResult::errorNotSupported; - } - else -#endif - { - String<MachineNameLength> name; - bool seen = false; - gb.TryGetPossiblyQuotedString('P', name.GetRef(), seen); - if (seen) + if (reprap.UsingLinuxInterface() && !gb.IsBinary()) { - reprap.SetName(name.c_str()); + result = GCodeResult::errorNotSupported; } else +#endif { - reply.printf("RepRap name: %s", reprap.GetName()); + String<MachineNameLength> name; + bool seen = false; + gb.TryGetPossiblyQuotedString('P', name.GetRef(), seen); + if (seen) + { + reprap.SetName(name.c_str()); + } + else + { + reply.printf("RepRap name: %s", reprap.GetName()); + } } - } - break; + break; - case 551: // Set password (no option to report it) - { - String<RepRapPasswordLength> password; - bool seen = false; - gb.TryGetPossiblyQuotedString('P', password.GetRef(), seen); - if (seen) + case 551: // Set password (no option to report it) { - reprap.SetPassword(password.c_str()); + String<RepRapPasswordLength> password; + bool seen = false; + gb.TryGetPossiblyQuotedString('P', password.GetRef(), seen); + if (seen) + { + reprap.SetPassword(password.c_str()); + } } - } - break; - - case 552: // Enable/Disable network and/or Set/Get IP address - if (!gb.MachineState().runningM502) // when running M502 we don't execute network-related commands - { - bool seen = false; - const unsigned int interface = (gb.Seen('I') ? gb.GetUIValue() : 0); + break; - String<SsidBufferLength> ssid; - if (reprap.GetNetwork().IsWiFiInterface(interface)) + case 552: // Enable/Disable network and/or Set/Get IP address + if (!gb.MachineState().runningM502) // when running M502 we don't execute network-related commands { - if (gb.Seen('S')) // Has the user turned the network on or off? - { - const int enableValue = gb.GetIValue(); - seen = true; + bool seen = false; + const unsigned int interface = (gb.Seen('I') ? gb.GetUIValue() : 0); - if (gb.Seen('P') && !gb.GetQuotedString(ssid.GetRef())) - { - reply.copy("Bad or missing SSID"); - result = GCodeResult::error; - } - else + String<SsidBufferLength> ssid; + if (reprap.GetNetwork().IsWiFiInterface(interface)) + { + if (gb.Seen('S')) // Has the user turned the network on or off? { + const int enableValue = gb.GetIValue(); + seen = true; + + gb.MustSee('P'); + gb.GetQuotedString(ssid.GetRef()); result = reprap.GetNetwork().EnableInterface(interface, enableValue, ssid.GetRef(), reply); } } - } - else - { - if (gb.Seen('P')) + else { - seen = true; - IPAddress eth; - if (gb.GetIPAddress(eth)) + if (gb.Seen('P')) { + seen = true; + IPAddress eth; + gb.GetIPAddress(eth); platform.SetIPAddress(eth); } - else + + // Process this one last in case the IP address is changed and the network enabled in the same command + if (gb.Seen('S')) // Has the user turned the network on or off? { - reply.copy("Bad IP address"); - result = GCodeResult::error; - break; + seen = true; + result = reprap.GetNetwork().EnableInterface(interface, gb.GetIValue(), ssid.GetRef(), reply); } } - // Process this one last in case the IP address is changed and the network enabled in the same command - if (gb.Seen('S')) // Has the user turned the network on or off? + if (!seen) { - seen = true; - result = reprap.GetNetwork().EnableInterface(interface, gb.GetIValue(), ssid.GetRef(), reply); + result = reprap.GetNetwork().GetNetworkState(interface, reply); } } + break; - if (!seen) - { - result = reprap.GetNetwork().GetNetworkState(interface, reply); - } - } - break; - - case 553: // Set/Get netmask - if (!gb.MachineState().runningM502) // when running M502 we don't execute network-related commands - { - if (gb.Seen('P')) + case 553: // Set/Get netmask + if (!gb.MachineState().runningM502) // when running M502 we don't execute network-related commands { - IPAddress eth; - if (gb.GetIPAddress(eth)) + if (gb.Seen('P')) { + IPAddress eth; + gb.GetIPAddress(eth); platform.SetNetMask(eth); } else { - reply.copy("Bad IP address"); - result = GCodeResult::error; + const IPAddress nm = platform.NetMask(); + reply.printf("Net mask: %d.%d.%d.%d ", nm.GetQuad(0), nm.GetQuad(1), nm.GetQuad(2), nm.GetQuad(3)); } } - else - { - const IPAddress nm = platform.NetMask(); - reply.printf("Net mask: %d.%d.%d.%d ", nm.GetQuad(0), nm.GetQuad(1), nm.GetQuad(2), nm.GetQuad(3)); - } - } - break; + break; - case 554: // Set/Get gateway - if (!gb.MachineState().runningM502) // when running M502 we don't execute network-related commands - { - if (gb.Seen('P')) + case 554: // Set/Get gateway + if (!gb.MachineState().runningM502) // when running M502 we don't execute network-related commands { - IPAddress eth; - if (gb.GetIPAddress(eth)) + if (gb.Seen('P')) { + IPAddress eth; + gb.GetIPAddress(eth); platform.SetGateWay(eth); } else { - reply.copy("Bad IP address"); - result = GCodeResult::error; + const IPAddress gw = platform.GateWay(); + reply.printf("Gateway: %d.%d.%d.%d ", gw.GetQuad(0), gw.GetQuad(1), gw.GetQuad(2), gw.GetQuad(3)); } } - else + break; + + case 555: // Set/report firmware type to emulate + if (gb.Seen('P')) { - const IPAddress gw = platform.GateWay(); - reply.printf("Gateway: %d.%d.%d.%d ", gw.GetQuad(0), gw.GetQuad(1), gw.GetQuad(2), gw.GetQuad(3)); + gb.MachineState().compatibility = (Compatibility)gb.GetIValue(); } - } - break; - - case 555: // Set/report firmware type to emulate - if (gb.Seen('P')) - { - gb.MachineState().compatibility = (Compatibility)gb.GetIValue(); - } - else - { - reply.copy("Emulating "); - switch (gb.MachineState().compatibility) + else { - case Compatibility::me: - case Compatibility::reprapFirmware: - reply.cat("RepRapFirmware (i.e. in native mode)"); - break; + reply.copy("Emulating "); + switch (gb.MachineState().compatibility) + { + case Compatibility::me: + case Compatibility::reprapFirmware: + reply.cat("RepRapFirmware (i.e. in native mode)"); + break; - case Compatibility::marlin: - reply.cat("Marlin"); - break; + case Compatibility::marlin: + reply.cat("Marlin"); + break; - case Compatibility::teacup: - reply.cat("Teacup"); - break; + case Compatibility::teacup: + reply.cat("Teacup"); + break; - case Compatibility::sprinter: - reply.cat("Sprinter"); - break; + case Compatibility::sprinter: + reply.cat("Sprinter"); + break; - case Compatibility::repetier: - reply.cat("Repetier"); - break; + case Compatibility::repetier: + reply.cat("Repetier"); + break; - case Compatibility::nanoDLP: - reply.cat("nanoDLP"); - break; + case Compatibility::nanoDLP: + reply.cat("nanoDLP"); + break; - default: - reply.catf("Unknown: (%u)", (unsigned int)gb.MachineState().compatibility); + default: + reply.catf("Unknown: (%u)", (unsigned int)gb.MachineState().compatibility); + } } - } - break; + break; - case 556: // Axis compensation (we support only X, Y, Z) - if (gb.Seen('S')) - { - const float value = gb.GetFValue(); - if (value >= 10.0) // avoid divide by zero and silly results + case 556: // Axis compensation (we support only X, Y, Z) + if (gb.Seen('S')) { - for (size_t axis = 0; axis <= Z_AXIS; axis++) + const float value = gb.GetFValue(); + if (value >= 10.0) // avoid divide by zero and silly results { - if (gb.Seen(axisLetters[axis])) + for (size_t axis = 0; axis <= Z_AXIS; axis++) { - reprap.GetMove().SetAxisCompensation(axis, gb.GetFValue() / value); + if (gb.Seen(axisLetters[axis])) + { + reprap.GetMove().SetAxisCompensation(axis, gb.GetFValue() / value); + } } } } - } - else - { - reply.printf("Axis compensations - XY: %.5f, YZ: %.5f, ZX: %.5f", - (double)reprap.GetMove().AxisCompensation(X_AXIS), (double)reprap.GetMove().AxisCompensation(Y_AXIS), (double)reprap.GetMove().AxisCompensation(Z_AXIS)); - } - break; - - case 557: // Set/report Z probe point coordinates - result = DefineGrid(gb, reply); - break; - - case 558: // Set or report Z probe type and for which axes it is used - result = platform.GetEndstops().HandleM558(gb, reply); - break; - -#if HAS_MASS_STORAGE - case 559: - case 560: // Binary writing - { - String<MaxFilenameLength> sysDir; - const char* defaultFile; - const char *folder; - if (code == 560) - { - folder = platform.GetWebDir(); - defaultFile = INDEX_PAGE_FILE; - } else { - platform.GetSysDir(sysDir.GetRef()); - folder = sysDir.c_str(); - defaultFile = platform.GetConfigFile(); + reply.printf("Axis compensations - XY: %.5f, YZ: %.5f, ZX: %.5f", + (double)reprap.GetMove().AxisCompensation(X_AXIS), (double)reprap.GetMove().AxisCompensation(Y_AXIS), (double)reprap.GetMove().AxisCompensation(Z_AXIS)); } - String<MaxFilenameLength> filename; - if (gb.Seen('P')) - { - gb.GetPossiblyQuotedString(filename.GetRef()); - } - else - { - filename.copy(defaultFile); - } - const FilePosition size = (gb.Seen('S') ? (FilePosition)gb.GetIValue() : 0); - const uint32_t crc32 = (gb.Seen('C') ? gb.GetUIValue() : 0); - const bool ok = gb.OpenFileToWrite(folder, filename.c_str(), size, true, crc32); - if (ok) - { - reply.printf("Writing to file: %s", filename.c_str()); - } - else - { - reply.printf("Can't open file %s for writing.", filename.c_str()); - result = GCodeResult::error; - } - } - break; -#endif - - case 561: // Set identity transform and disable height map - if (!LockMovementAndWaitForStandstill(gb)) - { - return false; - } - ClearBedMapping(); - break; + break; - case 562: // Reset temperature fault - use with great caution - if (gb.Seen('P')) - { - const unsigned int heater = gb.GetUIValue(); - if (heater < MaxHeaters) - { - result = reprap.ClearTemperatureFault(heater, reply); - } - else - { - reply.printf("Invalid heater number '%d'", heater); - result = GCodeResult::error; - } - } - else - { - // Clear all heater faults - for (unsigned int heater = 0; heater < MaxHeaters; ++heater) - { - result = max<GCodeResult>(result, reprap.ClearTemperatureFault(heater, reply)); - } - } - heaterFaultState = HeaterFaultState::noFault; - break; + case 557: // Set/report Z probe point coordinates + result = DefineGrid(gb, reply); + break; - case 563: // Define tool - result = ManageTool(gb, reply); - break; + case 558: // Set or report Z probe type and for which axes it is used + result = platform.GetEndstops().HandleM558(gb, reply); + break; - case 564: // Think outside the box? - { - bool seen = false; - if (gb.Seen('S')) - { - seen = true; - limitAxes = (gb.GetIValue() > 0); - } - if (gb.Seen('H')) +#if HAS_MASS_STORAGE + case 559: + case 560: // Binary writing { - seen = true; - noMovesBeforeHoming = (gb.GetIValue() > 0); + String<MaxFilenameLength> sysDir; + const char* defaultFile; + const char *folder; + if (code == 560) + { + folder = platform.GetWebDir(); + defaultFile = INDEX_PAGE_FILE; + } + else + { + platform.GetSysDir(sysDir.GetRef()); + folder = sysDir.c_str(); + defaultFile = platform.GetConfigFile(); + } + String<MaxFilenameLength> filename; + if (gb.Seen('P')) + { + gb.GetPossiblyQuotedString(filename.GetRef()); + } + else + { + filename.copy(defaultFile); + } + const FilePosition size = (gb.Seen('S') ? (FilePosition)gb.GetIValue() : 0); + const uint32_t crc32 = (gb.Seen('C') ? gb.GetUIValue() : 0); + const bool ok = gb.OpenFileToWrite(folder, filename.c_str(), size, true, crc32); + if (ok) + { + reply.printf("Writing to file: %s", filename.c_str()); + } + else + { + reply.printf("Can't open file %s for writing.", filename.c_str()); + result = GCodeResult::error; + } } - if (!seen) + break; +#endif + + case 561: // Set identity transform and disable height map + if (!LockMovementAndWaitForStandstill(gb)) { - reply.printf("Movement outside the bed is %spermitted, movement before homing is %spermitted", (limitAxes) ? "not " : "", (noMovesBeforeHoming) ? "not " : ""); + return false; } - } - break; + ClearBedMapping(); + break; - case 205: // Set/print maximum jerk speeds in mm/sec - case 566: // Set/print maximum jerk speeds in mm/min - { - const float multiplier1 = (code == 566) ? SecondsToMinutes : 1.0; - bool seen = false; - for (size_t axis = 0; axis < numTotalAxes; axis++) + case 562: // Reset temperature fault - use with great caution + if (gb.Seen('P')) { - if (gb.Seen(axisLetters[axis])) + const unsigned int heater = gb.GetUIValue(); + if (heater < MaxHeaters) { - platform.SetInstantDv(axis, gb.GetDistance() * multiplier1); - seen = true; + result = reprap.ClearTemperatureFault(heater, reply); + } + else + { + reply.printf("Invalid heater number '%d'", heater); + result = GCodeResult::error; } } - - if (gb.Seen(extrudeLetter)) + else { - seen = true; - float eVals[MaxExtruders]; - size_t eCount = numExtruders; - gb.GetFloatArray(eVals, eCount, true); - for (size_t e = 0; e < eCount; e++) + // Clear all heater faults + for (unsigned int heater = 0; heater < MaxHeaters; ++heater) { - platform.SetInstantDv(ExtruderToLogicalDrive(e), eVals[e] * multiplier1); + result = max<GCodeResult>(result, reprap.ClearTemperatureFault(heater, reply)); } } + heaterFaultState = HeaterFaultState::noFault; + break; - if (code == 566 && gb.Seen('P')) - { - seen = true; - reprap.GetMove().SetJerkPolicy(gb.GetUIValue()); - } + case 563: // Define tool + result = ManageTool(gb, reply); + break; - if (!seen) + case 564: // Think outside the box? { - const float multiplier2 = (code == 566) ? MinutesToSeconds : 1.0; - reply.printf("Maximum jerk rates (mm/%s): ", (code == 566) ? "min" : "sec"); - for (size_t axis = 0; axis < numTotalAxes; ++axis) + bool seen = false; + if (gb.Seen('S')) { - reply.catf("%c: %.1f, ", axisLetters[axis], (double)(platform.GetInstantDv(axis) * multiplier2)); + seen = true; + limitAxes = (gb.GetIValue() > 0); } - reply.cat("E:"); - char sep = ' '; - for (size_t extruder = 0; extruder < numExtruders; extruder++) + if (gb.Seen('H')) { - reply.catf("%c%.1f", sep, (double)(platform.GetInstantDv(ExtruderToLogicalDrive(extruder)) * multiplier2)); - sep = ':'; + seen = true; + noMovesBeforeHoming = (gb.GetIValue() > 0); } - if (code == 566) + if (!seen) { - reply.catf(", jerk policy: %u", reprap.GetMove().GetJerkPolicy()); + reply.printf("Movement outside the bed is %spermitted, movement before homing is %spermitted", (limitAxes) ? "not " : "", (noMovesBeforeHoming) ? "not " : ""); } } - } - break; + break; - case 567: // Set/report tool mix ratios - if (gb.Seen('P')) - { - const int8_t tNumber = gb.GetIValue(); - Tool* const tool = reprap.GetTool(tNumber); - if (tool != nullptr) + case 205: // Set/print maximum jerk speeds in mm/sec + case 566: // Set/print maximum jerk speeds in mm/min { - if (gb.Seen(extrudeLetter)) + const float multiplier1 = (code == 566) ? SecondsToMinutes : 1.0; + bool seen = false; + for (size_t axis = 0; axis < numTotalAxes; axis++) { - float eVals[MaxExtruders]; - size_t eCount = tool->DriveCount(); - gb.GetFloatArray(eVals, eCount, false); - if (eCount != tool->DriveCount()) + if (gb.Seen(axisLetters[axis])) { - reply.copy("Setting mix ratios - wrong number of E drives: "); - gb.AppendFullCommand(reply); + platform.SetInstantDv(axis, gb.GetDistance() * multiplier1); + seen = true; } - else + } + + if (gb.Seen(extrudeLetter)) + { + seen = true; + float eVals[MaxExtruders]; + size_t eCount = numExtruders; + gb.GetFloatArray(eVals, eCount, true); + for (size_t e = 0; e < eCount; e++) { - tool->DefineMix(eVals); + platform.SetInstantDv(ExtruderToLogicalDrive(e), eVals[e] * multiplier1); } } - else + + if (code == 566 && gb.Seen('P')) { - reply.printf("Tool %d mix ratios:", tNumber); + seen = true; + reprap.GetMove().SetJerkPolicy(gb.GetUIValue()); + } + + if (!seen) + { + const float multiplier2 = (code == 566) ? MinutesToSeconds : 1.0; + reply.printf("Maximum jerk rates (mm/%s): ", (code == 566) ? "min" : "sec"); + for (size_t axis = 0; axis < numTotalAxes; ++axis) + { + reply.catf("%c: %.1f, ", axisLetters[axis], (double)(platform.GetInstantDv(axis) * multiplier2)); + } + reply.cat("E:"); char sep = ' '; - for (size_t drive = 0; drive < tool->DriveCount(); drive++) + for (size_t extruder = 0; extruder < numExtruders; extruder++) { - reply.catf("%c%.3f", sep, (double)tool->GetMix()[drive]); + reply.catf("%c%.1f", sep, (double)(platform.GetInstantDv(ExtruderToLogicalDrive(extruder)) * multiplier2)); sep = ':'; } + if (code == 566) + { + reply.catf(", jerk policy: %u", reprap.GetMove().GetJerkPolicy()); + } } } - } - break; - - case 568: // Turn on/off automatic tool mixing - reply.copy("The M568 command is no longer needed"); - break; - - case 569: // Set/report axis direction - result = ConfigureDriver(gb, reply); - break; + break; - case 570: // Set/report heater monitoring - { - bool seen = false; - if (gb.Seen('S')) - { - seen = true; - heaterFaultTimeout = gb.GetUIValue() * (60 * 1000); - } - if (gb.Seen('H')) + case 567: // Set/report tool mix ratios + if (gb.Seen('P')) { - seen = true; - result = reprap.GetHeat().ConfigureHeaterMonitoring(gb.GetUIValue(), gb, reply); + const int8_t tNumber = gb.GetIValue(); + Tool* const tool = reprap.GetTool(tNumber); + if (tool != nullptr) + { + if (gb.Seen(extrudeLetter)) + { + float eVals[MaxExtruders]; + size_t eCount = tool->DriveCount(); + gb.GetFloatArray(eVals, eCount, false); + if (eCount != tool->DriveCount()) + { + reply.copy("Setting mix ratios - wrong number of E drives: "); + gb.AppendFullCommand(reply); + } + else + { + tool->DefineMix(eVals); + } + } + else + { + reply.printf("Tool %d mix ratios:", tNumber); + char sep = ' '; + for (size_t drive = 0; drive < tool->DriveCount(); drive++) + { + reply.catf("%c%.3f", sep, (double)tool->GetMix()[drive]); + sep = ':'; + } + } + } } - if (!seen) + break; + + case 568: // Turn on/off automatic tool mixing + reply.copy("The M568 command is no longer needed"); + break; + + case 569: // Set/report axis direction + result = ConfigureDriver(gb, reply); + break; + + case 570: // Set/report heater monitoring { - reply.printf("Print will be terminated if a heater fault is not reset within %" PRIu32 " minutes", heaterFaultTimeout/(60 * 1000)); + bool seen = false; + if (gb.Seen('S')) + { + seen = true; + heaterFaultTimeout = gb.GetUIValue() * (60 * 1000); + } + if (gb.Seen('H')) + { + seen = true; + result = reprap.GetHeat().ConfigureHeaterMonitoring(gb.GetUIValue(), gb, reply); + } + if (!seen) + { + reply.printf("Print will be terminated if a heater fault is not reset within %" PRIu32 " minutes", heaterFaultTimeout/(60 * 1000)); + } } - } - break; + break; - case 571: // Set output on extrude - result = platform.GetSetAncillaryPwm(gb, reply); - break; + case 571: // Set output on extrude + result = platform.GetSetAncillaryPwm(gb, reply); + break; - case 572: // Set/report pressure advance - if (gb.Seen('S')) - { - const float advance = gb.GetFValue(); - if (!LockMovementAndWaitForStandstill(gb)) + case 572: // Set/report pressure advance + if (gb.Seen('S')) { - return false; + const float advance = gb.GetFValue(); + if (!LockMovementAndWaitForStandstill(gb)) + { + return false; + } + result = platform.SetPressureAdvance(advance, gb, reply); } - result = platform.SetPressureAdvance(advance, gb, reply); - } - else - { - reply.copy("Extruder pressure advance"); - char c = ':'; - for (size_t i = 0; i < numExtruders; ++i) + else { - reply.catf("%c %.3f", c, (double)platform.GetPressureAdvance(i)); - c = ','; + reply.copy("Extruder pressure advance"); + char c = ':'; + for (size_t i = 0; i < numExtruders; ++i) + { + reply.catf("%c %.3f", c, (double)platform.GetPressureAdvance(i)); + c = ','; + } } - } - break; + break; - case 573: // Report heater average PWM - if (gb.Seen('P')) - { - const unsigned int heater = gb.GetUIValue(); - if (heater < MaxHeaters) + case 573: // Report heater average PWM + if (gb.Seen('P')) { - reply.printf("Average heater %u PWM: %.3f", heater, (double)reprap.GetHeat().GetAveragePWM(heater)); + const unsigned int heater = gb.GetUIValue(); + if (heater < MaxHeaters) + { + reply.printf("Average heater %u PWM: %.3f", heater, (double)reprap.GetHeat().GetAveragePWM(heater)); + } } - } - break; + break; - case 574: // Set endstop configuration - // We may be about to delete endstops, so make sure we are not executing a move that uses them - if (!LockMovementAndWaitForStandstill(gb)) - { - return false; - } - result = platform.GetEndstops().HandleM574(gb, reply, outBuf); - break; + case 574: // Set endstop configuration + // We may be about to delete endstops, so make sure we are not executing a move that uses them + if (!LockMovementAndWaitForStandstill(gb)) + { + return false; + } + result = platform.GetEndstops().HandleM574(gb, reply, outBuf); + break; - case 575: // Set communications parameters - if (gb.Seen('P')) - { - size_t chan = gb.GetIValue(); - if (chan < NUM_SERIAL_CHANNELS) + case 575: // Set communications parameters { - bool seen = false; - if (gb.Seen('B')) - { - platform.SetBaudRate(chan, gb.GetIValue()); - seen = true; - } - if (gb.Seen('S')) + gb.MustSee('P'); + size_t chan = gb.GetIValue(); + if (chan < NUM_SERIAL_CHANNELS) { - uint32_t val = gb.GetIValue(); - platform.SetCommsProperties(chan, val); - switch (chan) + bool seen = false; + if (gb.Seen('B')) { - case 0: - usbGCode->SetCommsProperties(val); - break; - case 1: - if (auxGCode != nullptr) + platform.SetBaudRate(chan, gb.GetIValue()); + seen = true; + } + if (gb.Seen('S')) + { + uint32_t val = gb.GetIValue(); + platform.SetCommsProperties(chan, val); + switch (chan) { - auxGCode->SetCommsProperties(val); - platform.SetAuxDetected(); + case 0: + usbGCode->SetCommsProperties(val); + break; + case 1: + if (auxGCode != nullptr) + { + auxGCode->SetCommsProperties(val); + platform.SetAuxDetected(); + } + break; + default: + break; } - break; - default: - break; + seen = true; + } + if (!seen) + { + uint32_t cp = platform.GetCommsProperties(chan); + reply.printf("Channel %d: baud rate %" PRIu32 ", %s checksum", chan, platform.GetBaudRate(chan), (cp & 1) ? "requires" : "does not require"); } - seen = true; - } - if (!seen) - { - uint32_t cp = platform.GetCommsProperties(chan); - reply.printf("Channel %d: baud rate %" PRIu32 ", %s checksum", chan, platform.GetBaudRate(chan), (cp & 1) ? "requires" : "does not require"); } } - } - break; + break; - case 577: // Wait until endstop input is triggered - result = WaitForPin(gb, reply); - break; + case 577: // Wait until endstop input is triggered + result = WaitForPin(gb, reply); + break; #if SUPPORT_INKJET - case 578: // Fire Inkjet bits - if (!LockMovementAndWaitForStandstill()) - { - return false; - } - - if (gb.Seen('S')) // Need to handle the 'P' parameter too; see http://reprap.org/wiki/G-code#M578:_Fire_inkjet_bits - { - platform.Inkjet(gb.GetIValue()); - } - break; -#endif + case 578: // Fire Inkjet bits + if (!LockMovementAndWaitForStandstill()) + { + return false; + } - case 579: // Scale Cartesian axes (mostly for Delta configurations) - { - bool seen = false; - for (size_t axis = 0; axis < numVisibleAxes; axis++) + if (gb.Seen('S')) // Need to handle the 'P' parameter too; see http://reprap.org/wiki/G-code#M578:_Fire_inkjet_bits { - gb.TryGetFValue(axisLetters[axis], axisScaleFactors[axis], seen); + platform.Inkjet(gb.GetIValue()); } + break; +#endif - if (!seen) + case 579: // Scale Cartesian axes (mostly for Delta configurations) { - char sep = ':'; - reply.copy("Axis scale factors"); - for(size_t axis = 0; axis < numVisibleAxes; axis++) + bool seen = false; + for (size_t axis = 0; axis < numVisibleAxes; axis++) { - reply.catf("%c %c: %.3f", sep, axisLetters[axis], (double)axisScaleFactors[axis]); - sep = ','; + gb.TryGetFValue(axisLetters[axis], axisScaleFactors[axis], seen); + } + + if (!seen) + { + char sep = ':'; + reply.copy("Axis scale factors"); + for(size_t axis = 0; axis < numVisibleAxes; axis++) + { + reply.catf("%c %c: %.3f", sep, axisLetters[axis], (double)axisScaleFactors[axis]); + sep = ','; + } } } - } - break; + break; #if SUPPORT_ROLAND - case 580: // (De)Select Roland mill - if (gb.Seen('R')) - { - if (gb.GetIValue()) + case 580: // (De)Select Roland mill + if (gb.Seen('R')) { - reprap.GetRoland()->Activate(); - if (gb.Seen('P')) + if (gb.GetIValue()) + { + reprap.GetRoland()->Activate(); + if (gb.Seen('P')) + { + result = reprap.GetRoland()->RawWrite(gb.GetString()); + } + } + else { - result = reprap.GetRoland()->RawWrite(gb.GetString()); + result = reprap.GetRoland()->Deactivate(); } } else { - result = reprap.GetRoland()->Deactivate(); + reply.printf("Roland is %s.", reprap.GetRoland()->Active() ? "active" : "inactive"); } - } - else - { - reply.printf("Roland is %s.", reprap.GetRoland()->Active() ? "active" : "inactive"); - } - break; + break; #endif - case 581: // Configure external trigger - result = ConfigureTrigger(gb, reply, code); - break; - - case 582: // Check external trigger - result = CheckTrigger(gb, reply, code); - break; + case 581: // Configure external trigger + result = ConfigureTrigger(gb, reply, code); + break; - case 584: // Set axis/extruder to stepper driver(s) mapping - result = DoDriveMapping(gb, reply); - break; + case 582: // Check external trigger + result = CheckTrigger(gb, reply, code); + break; - case 585: // Probe Tool - result = ProbeTool(gb, reply); - break; + case 584: // Set axis/extruder to stepper driver(s) mapping + result = DoDriveMapping(gb, reply); + break; - case 586: // Configure network protocols - { - const unsigned int interface = (gb.Seen('I') ? gb.GetUIValue() : 0); + case 585: // Probe Tool + result = ProbeTool(gb, reply); + break; - if (gb.Seen('P')) + case 586: // Configure network protocols { - const unsigned int protocol = gb.GetUIValue(); - if (gb.Seen('S')) + const unsigned int interface = (gb.Seen('I') ? gb.GetUIValue() : 0); + + if (gb.Seen('P')) { - const bool enable = (gb.GetIValue() == 1); - if (enable) + const unsigned int protocol = gb.GetUIValue(); + if (gb.Seen('S')) { - const int port = (gb.Seen('R')) ? gb.GetIValue() : -1; - const int secure = (gb.Seen('T')) ? gb.GetIValue() : -1; - result = reprap.GetNetwork().EnableProtocol(interface, protocol, port, secure, reply); - } - else - { - result = reprap.GetNetwork().DisableProtocol(interface, protocol, reply); + const bool enable = (gb.GetIValue() == 1); + if (enable) + { + const int port = (gb.Seen('R')) ? gb.GetIValue() : -1; + const int secure = (gb.Seen('T')) ? gb.GetIValue() : -1; + result = reprap.GetNetwork().EnableProtocol(interface, protocol, port, secure, reply); + } + else + { + result = reprap.GetNetwork().DisableProtocol(interface, protocol, reply); + } } } + else + { + // Default to reporting current protocols if P or S parameter missing + result = reprap.GetNetwork().ReportProtocols(interface, reply); + } } - else - { - // Default to reporting current protocols if P or S parameter missing - result = reprap.GetNetwork().ReportProtocols(interface, reply); - } - } - break; + break; #if HAS_WIFI_NETWORKING - case 587: // Add WiFi network or list remembered networks - case 588: // Forget WiFi network - case 589: // Configure access point - if (!gb.MachineState().runningM502) // when running M502 we don't execute network-related commands - { - result = reprap.GetNetwork().HandleWiFiCode(code, gb, reply, outBuf); - } - break; + case 587: // Add WiFi network or list remembered networks + case 588: // Forget WiFi network + case 589: // Configure access point + if (!gb.MachineState().runningM502) // when running M502 we don't execute network-related commands + { + result = reprap.GetNetwork().HandleWiFiCode(code, gb, reply, outBuf); + } + break; #endif - case 591: // Configure filament sensor - if (gb.Seen('D')) - { - const unsigned int extruder = gb.GetUIValue(); - if (extruder < numExtruders) + case 591: // Configure filament sensor { - result = FilamentMonitor::Configure(gb, reply, extruder); + gb.MustSee('D'); + const unsigned int extruder = gb.GetUIValue(); + if (extruder < numExtruders) + { + result = FilamentMonitor::Configure(gb, reply, extruder); + } } - } - break; + break; #if SUPPORT_NONLINEAR_EXTRUSION - case 592: // Configure nonlinear extrusion - if (gb.Seen('D')) - { - const unsigned int extruder = gb.GetUIValue(); - bool seen = false; - float a = 0.0, b = 0.0, limit = DefaultNonlinearExtrusionLimit; - gb.TryGetFValue('A', a, seen); - gb.TryGetFValue('B', b, seen); - gb.TryGetFValue('L', limit, seen); - if (seen) + case 592: // Configure nonlinear extrusion { - platform.SetNonlinearExtrusion(extruder, a, b, limit); - } - else - { - platform.GetExtrusionCoefficients(extruder, a, b, limit); - reply.printf("Drive %u nonlinear extrusion coefficients: A=%.3f, B=%.4f, limit=%.2f", extruder, (double)a, (double)b, (double)limit); + gb.MustSee('D'); + const unsigned int extruder = gb.GetUIValue(); + bool seen = false; + float a = 0.0, b = 0.0, limit = DefaultNonlinearExtrusionLimit; + gb.TryGetFValue('A', a, seen); + gb.TryGetFValue('B', b, seen); + gb.TryGetFValue('L', limit, seen); + if (seen) + { + platform.SetNonlinearExtrusion(extruder, a, b, limit); + } + else + { + platform.GetExtrusionCoefficients(extruder, a, b, limit); + reply.printf("Drive %u nonlinear extrusion coefficients: A=%.3f, B=%.4f, limit=%.2f", extruder, (double)a, (double)b, (double)limit); + } } - } - break; + break; #endif - case 593: // Configure dynamic ringing cancellation - result = reprap.GetMove().ConfigureDynamicAcceleration(gb, reply); - break; + case 593: // Configure dynamic ringing cancellation + result = reprap.GetMove().ConfigureDynamicAcceleration(gb, reply); + break; #if SUPPORT_ASYNC_MOVES - case 594: // Enter or leave height following mode - result = reprap.GetMove().StartHeightFollowing(gb, reply); - break; + case 594: // Enter or leave height following mode + result = reprap.GetMove().StartHeightFollowing(gb, reply); + break; #endif - // For case 600, see 226 + // For case 600, see 226 - // M650 (set peel move parameters) and M651 (execute peel move) are no longer handled specially. Use macros to specify what they should do. + // M650 (set peel move parameters) and M651 (execute peel move) are no longer handled specially. Use macros to specify what they should do. - case 665: // Set delta configuration - if (!LockMovementAndWaitForStandstill(gb)) - { - return false; - } - { - Move& move = reprap.GetMove(); - - bool changedMode = false; - if ((gb.Seen('L') || gb.Seen('D')) && move.GetKinematics().GetKinematicsType() != KinematicsType::linearDelta) + case 665: // Set delta configuration + if (!LockMovementAndWaitForStandstill(gb)) { - // Not in delta mode, so switch to it - changedMode = true; - move.SetKinematics(KinematicsType::linearDelta); + return false; } - bool error = false; - const bool changed = move.GetKinematics().Configure(code, gb, reply, error); - if (changedMode) { - move.GetKinematics().GetAssumedInitialPosition(numVisibleAxes, moveBuffer.coords); - ToolOffsetInverseTransform(moveBuffer.coords, currentUserPosition); + Move& move = reprap.GetMove(); + + bool changedMode = false; + if ((gb.Seen('L') || gb.Seen('D')) && move.GetKinematics().GetKinematicsType() != KinematicsType::linearDelta) + { + // Not in delta mode, so switch to it + changedMode = true; + move.SetKinematics(KinematicsType::linearDelta); + } + bool error = false; + const bool changed = move.GetKinematics().Configure(code, gb, reply, error); + if (changedMode) + { + move.GetKinematics().GetAssumedInitialPosition(numVisibleAxes, moveBuffer.coords); + ToolOffsetInverseTransform(moveBuffer.coords, currentUserPosition); + } + if (changed || changedMode) + { + if (reprap.GetMove().GetKinematics().LimitPosition(moveBuffer.coords, nullptr, numVisibleAxes, axesHomed, false, false) != LimitPositionResult::ok) + { + ToolOffsetInverseTransform(moveBuffer.coords, currentUserPosition); // make sure the limits are reflected in the user position + } + reprap.GetMove().SetNewPosition(moveBuffer.coords, true); + SetAllAxesNotHomed(); + } + result = GetGCodeResultFromError(error); + } + break; + + case 666: // Set delta endstop adjustments + if (!LockMovementAndWaitForStandstill(gb)) + { + return false; } - if (changed || changedMode) { - if (reprap.GetMove().GetKinematics().LimitPosition(moveBuffer.coords, nullptr, numVisibleAxes, axesHomed, false, false) != LimitPositionResult::ok) + bool error = false; + const bool changed = reprap.GetMove().GetKinematics().Configure(code, gb, reply, error); + if (changed) { - ToolOffsetInverseTransform(moveBuffer.coords, currentUserPosition); // make sure the limits are reflected in the user position + SetAllAxesNotHomed(); } - reprap.GetMove().SetNewPosition(moveBuffer.coords, true); - SetAllAxesNotHomed(); + result = GetGCodeResultFromError(error); } - result = GetGCodeResultFromError(error); - } - break; + break; - case 666: // Set delta endstop adjustments - if (!LockMovementAndWaitForStandstill(gb)) - { - return false; - } - { - bool error = false; - const bool changed = reprap.GetMove().GetKinematics().Configure(code, gb, reply, error); - if (changed) + case 667: // Set CoreXY mode + if (!LockMovementAndWaitForStandstill(gb)) { - SetAllAxesNotHomed(); + return false; } - result = GetGCodeResultFromError(error); - } - break; - - case 667: // Set CoreXY mode - if (!LockMovementAndWaitForStandstill(gb)) - { - return false; - } - { - Move& move = reprap.GetMove(); - const KinematicsType oldK = move.GetKinematics().GetKinematicsType(); // get the current kinematics type so we can tell whether it changed - - bool seen = false; - if (gb.Seen('S')) { - // Switch to the correct CoreXY mode - const int mode = gb.GetIValue(); - switch (mode) + Move& move = reprap.GetMove(); + const KinematicsType oldK = move.GetKinematics().GetKinematicsType(); // get the current kinematics type so we can tell whether it changed + + bool seen = false; + if (gb.Seen('S')) { - case 0: - move.SetKinematics(KinematicsType::cartesian); - break; + // Switch to the correct CoreXY mode + const int mode = gb.GetIValue(); + switch (mode) + { + case 0: + move.SetKinematics(KinematicsType::cartesian); + break; - case 1: - move.SetKinematics(KinematicsType::coreXY); - break; + case 1: + move.SetKinematics(KinematicsType::coreXY); + break; - case 2: - move.SetKinematics(KinematicsType::coreXZ); - break; + case 2: + move.SetKinematics(KinematicsType::coreXZ); + break; - default: - reply.printf("Mode %d is not valid", mode); - result = GCodeResult::error; - break; + default: + reply.printf("Mode %d is not valid", mode); + result = GCodeResult::error; + break; + } + seen = true; + } + + if (result == GCodeResult::ok) + { + if (gb.Seen('X') || gb.Seen('Y') || gb.Seen('Z')) + { + reply.copy("M667 XYZ parameters are no longer supported, use M669 matrix parameters instead"); + result = GCodeResult::error; + } + + if (seen) + { + // We changed something, so reset the positions and set all axes not homed + if (move.GetKinematics().GetKinematicsType() != oldK) + { + move.GetKinematics().GetAssumedInitialPosition(numVisibleAxes, moveBuffer.coords); + ToolOffsetInverseTransform(moveBuffer.coords, currentUserPosition); + } + if (reprap.GetMove().GetKinematics().LimitPosition(moveBuffer.coords, nullptr, numVisibleAxes, axesHomed, false, false) != LimitPositionResult::ok) + { + ToolOffsetInverseTransform(moveBuffer.coords, currentUserPosition); // make sure the limits are reflected in the user position + } + reprap.GetMove().SetNewPosition(moveBuffer.coords, true); + SetAllAxesNotHomed(); + } } - seen = true; } + break; - if (result == GCodeResult::ok) + case 669: // Set kinematics and parameters for SCARA and other kinematics that don't use M665, M666 or M667 + if (!LockMovementAndWaitForStandstill(gb)) { - if (gb.Seen('X') || gb.Seen('Y') || gb.Seen('Z')) + return false; + } + { + Move& move = reprap.GetMove(); + const KinematicsType oldK = move.GetKinematics().GetKinematicsType(); // get the current kinematics type so we can tell whether it changed + + bool seen = false; + if (gb.Seen('K')) { - reply.copy("M667 XYZ parameters are no longer supported, use M669 matrix parameters instead"); - result = GCodeResult::error; + const int nk = gb.GetIValue(); + if (nk < 0 || nk >= (int)KinematicsType::unknown || !move.SetKinematics(static_cast<KinematicsType>(nk))) + { + reply.printf("Unknown kinematics type %d", nk); + result = GCodeResult::error; + break; + } + seen = true; } + bool error = false; + if (move.GetKinematics().Configure(code, gb, reply, error)) + { + seen = true; + } + result = GetGCodeResultFromError(error); if (seen) { - // We changed something, so reset the positions and set all axes not homed + // We changed something significant, so reset the positions and set all axes not homed if (move.GetKinematics().GetKinematicsType() != oldK) { move.GetKinematics().GetAssumedInitialPosition(numVisibleAxes, moveBuffer.coords); @@ -3778,272 +3763,224 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) SetAllAxesNotHomed(); } } - } - break; + break; - case 669: // Set kinematics and parameters for SCARA and other kinematics that don't use M665, M666 or M667 - if (!LockMovementAndWaitForStandstill(gb)) - { - return false; - } - { - Move& move = reprap.GetMove(); - const KinematicsType oldK = move.GetKinematics().GetKinematicsType(); // get the current kinematics type so we can tell whether it changed +#if SUPPORT_IOBITS + case 670: + Move::CreateLaserTask(); + result = GetGCodeResultFromError(reprap.GetPortControl().Configure(gb, reply)); + break; +#endif - bool seen = false; - if (gb.Seen('K')) + case 671: // Set Z leadscrew positions + if (!LockMovementAndWaitForStandstill(gb)) { - const int nk = gb.GetIValue(); - if (nk < 0 || nk >= (int)KinematicsType::unknown || !move.SetKinematics(static_cast<KinematicsType>(nk))) - { - reply.printf("Unknown kinematics type %d", nk); - result = GCodeResult::error; - break; - } - seen = true; + return false; } - bool error = false; - if (move.GetKinematics().Configure(code, gb, reply, error)) { - seen = true; + bool error = false; + (void)reprap.GetMove().GetKinematics().Configure(code, gb, reply, error); + result = GetGCodeResultFromError(error); } - result = GetGCodeResultFromError(error); + break; + + case 672: // Program Z probe + result = platform.GetEndstops().ProgramZProbe(gb, reply); + break; - if (seen) + case 673: // Align plane on rotary axis + if (numTotalAxes < U_AXIS) { - // We changed something significant, so reset the positions and set all axes not homed - if (move.GetKinematics().GetKinematicsType() != oldK) + reply.copy("Insufficient axes configured"); + result = GCodeResult::error; + } + else if (LockMovementAndWaitForStandstill(gb)) + { + if (reprap.GetMove().GetNumProbedProbePoints() < 2) { - move.GetKinematics().GetAssumedInitialPosition(numVisibleAxes, moveBuffer.coords); - ToolOffsetInverseTransform(moveBuffer.coords, currentUserPosition); + reply.copy("Insufficient probe points"); + result = GCodeResult::error; } - if (reprap.GetMove().GetKinematics().LimitPosition(moveBuffer.coords, nullptr, numVisibleAxes, axesHomed, false, false) != LimitPositionResult::ok) + else if (!AllAxesAreHomed()) { - ToolOffsetInverseTransform(moveBuffer.coords, currentUserPosition); // make sure the limits are reflected in the user position + reply.copy("Home the axes first"); + result = GCodeResult::error; } - reprap.GetMove().SetNewPosition(moveBuffer.coords, true); - SetAllAxesNotHomed(); - } - } - break; - -#if SUPPORT_IOBITS - case 670: - Move::CreateLaserTask(); - result = GetGCodeResultFromError(reprap.GetPortControl().Configure(gb, reply)); - break; -#endif + else + { + // See which rotary axis needs to be compensated (if any) + size_t axisToUse = 0; + for (size_t axis = U_AXIS; axis < numVisibleAxes; axis++) + { + if (gb.Seen(axisLetters[axis])) + { + axisToUse = axis; + break; + } + } - case 671: // Set Z leadscrew positions - if (!LockMovementAndWaitForStandstill(gb)) - { - return false; - } - { - bool error = false; - (void)reprap.GetMove().GetKinematics().Configure(code, gb, reply, error); - result = GetGCodeResultFromError(error); - } - break; + // Get the coordinates of the first two G30 points and calculate how far off the axis is + float x1, y1, x2, y2; + const float z1 = reprap.GetMove().GetProbeCoordinates(0, x1, y1, true); + const float z2 = reprap.GetMove().GetProbeCoordinates(1, x2, y2, true); + const float a1 = (x1 == x2) ? y1 : x1; + const float a2 = (x1 == x2) ? y2 : x2; - case 672: // Program Z probe - result = platform.GetEndstops().ProgramZProbe(gb, reply); - break; + // See what kind of compensation we need to perform + SetMoveBufferDefaults(); + if (axisToUse != 0) + { + // An axis letter is given, so try to level the given axis + const float correctionAngle = atanf((z2 - z1) / (a2 - a1)) * 180.0 / M_PI; + const float correctionFactor = gb.Seen('S') ? gb.GetFValue() : 1.0; + moveBuffer.coords[axisToUse] += correctionAngle * correctionFactor; - case 673: // Align plane on rotary axis - if (numTotalAxes < U_AXIS) - { - reply.copy("Insufficient axes configured"); - result = GCodeResult::error; - } - else if (LockMovementAndWaitForStandstill(gb)) - { - if (reprap.GetMove().GetNumProbedProbePoints() < 2) - { - reply.copy("Insufficient probe points"); - result = GCodeResult::error; - } - else if (!AllAxesAreHomed()) - { - reply.copy("Home the axes first"); - result = GCodeResult::error; - } - else - { - // See which rotary axis needs to be compensated (if any) - size_t axisToUse = 0; - for (size_t axis = U_AXIS; axis < numVisibleAxes; axis++) - { - if (gb.Seen(axisLetters[axis])) + reply.printf("%c axis is off by %.2f deg", axisLetters[axisToUse], (double)correctionAngle); + HandleReply(gb, GCodeResult::notFinished, reply.c_str()); + } + else if (reprap.GetMove().GetNumProbedProbePoints() >= 4) { - axisToUse = axis; + // At least four G30 points are given. This lets us figure out how far off the centre of the axis is + const float z3 = reprap.GetMove().GetProbeCoordinates(2, x1, y1, true); + const float z4 = reprap.GetMove().GetProbeCoordinates(3, x2, y2, true); + const float a3 = (x1 == x2) ? y1 : x1; + const float a4 = (x1 == x2) ? y2 : x2; + + // Calculate intersection points in [XY] and Z directions + const float aS = ((a4 - a3) * (a2 * z1 - a1 * z2) - (a2 - a1) * (a4 * z3 - a3 * z4)) / + ((z4 - z3) * (a2 - a1) - (z2 - z1) * (a4 - a3)); + const float zS = ((z1 - z2) * (a4 * z3 - a3 * z4) - (z3 - z4) * (a2 * z1 - a1 * z2)) / + ((z4 - z3) * (a2 - a1) - (z2 - z1) * (a4 - a3)); + moveBuffer.coords[(x1 == x2) ? Y_AXIS : X_AXIS] += aS; + moveBuffer.coords[Z_AXIS] += zS; + + reply.printf("%c is offset by %.2fmm, Z is offset by %.2fmm", (x2 == x1) ? 'Y' : 'X', (double)aS, (double)zS); + HandleReply(gb, GCodeResult::notFinished, reply.c_str()); + } + else + { + reply.copy("No rotary axis letter and/or not enough probe points for rotary axis alignment"); + result = GCodeResult::error; break; } - } - - // Get the coordinates of the first two G30 points and calculate how far off the axis is - float x1, y1, x2, y2; - const float z1 = reprap.GetMove().GetProbeCoordinates(0, x1, y1, true); - const float z2 = reprap.GetMove().GetProbeCoordinates(1, x2, y2, true); - const float a1 = (x1 == x2) ? y1 : x1; - const float a2 = (x1 == x2) ? y2 : x2; - // See what kind of compensation we need to perform - SetMoveBufferDefaults(); - if (axisToUse != 0) - { - // An axis letter is given, so try to level the given axis - const float correctionAngle = atanf((z2 - z1) / (a2 - a1)) * 180.0 / M_PI; - const float correctionFactor = gb.Seen('S') ? gb.GetFValue() : 1.0; - moveBuffer.coords[axisToUse] += correctionAngle * correctionFactor; + // Get the feedrate (if any) and kick off a new move + if (gb.Seen(feedrateLetter)) + { + const float rate = gb.ConvertDistance(gb.GetFValue()); + gb.MachineState().feedRate = rate * SecondsToMinutes; // don't apply the speed factor + } + moveBuffer.feedRate = gb.MachineState().feedRate; + moveBuffer.usingStandardFeedrate = true; + NewMoveAvailable(1); - reply.printf("%c axis is off by %.2f deg", axisLetters[axisToUse], (double)correctionAngle); - HandleReply(gb, GCodeResult::notFinished, reply.c_str()); + gb.SetState(GCodeState::waitingForSpecialMoveToComplete); } - else if (reprap.GetMove().GetNumProbedProbePoints() >= 4) - { - // At least four G30 points are given. This lets us figure out how far off the centre of the axis is - const float z3 = reprap.GetMove().GetProbeCoordinates(2, x1, y1, true); - const float z4 = reprap.GetMove().GetProbeCoordinates(3, x2, y2, true); - const float a3 = (x1 == x2) ? y1 : x1; - const float a4 = (x1 == x2) ? y2 : x2; - - // Calculate intersection points in [XY] and Z directions - const float aS = ((a4 - a3) * (a2 * z1 - a1 * z2) - (a2 - a1) * (a4 * z3 - a3 * z4)) / - ((z4 - z3) * (a2 - a1) - (z2 - z1) * (a4 - a3)); - const float zS = ((z1 - z2) * (a4 * z3 - a3 * z4) - (z3 - z4) * (a2 * z1 - a1 * z2)) / - ((z4 - z3) * (a2 - a1) - (z2 - z1) * (a4 - a3)); - moveBuffer.coords[(x1 == x2) ? Y_AXIS : X_AXIS] += aS; - moveBuffer.coords[Z_AXIS] += zS; + } + else + { + result = GCodeResult::notFinished; + } + break; - reply.printf("%c is offset by %.2fmm, Z is offset by %.2fmm", (x2 == x1) ? 'Y' : 'X', (double)aS, (double)zS); - HandleReply(gb, GCodeResult::notFinished, reply.c_str()); - } - else +#if false + // This code is not finished yet + case 674: // Set Z to center point + if (LockMovementAndWaitForStandstill(gb)) + { + if (reprap.GetMove().GetNumProbedProbePoints() < 2) { - reply.copy("No rotary axis letter and/or not enough probe points for rotary axis alignment"); + reply.copy("Insufficient probe points"); result = GCodeResult::error; - break; } - - // Get the feedrate (if any) and kick off a new move - if (gb.Seen(feedrateLetter)) + else if (!AllAxesAreHomed()) { - const float rate = gb.ConvertDistance(gb.GetFValue()); - gb.MachineState().feedRate = rate * SecondsToMinutes; // don't apply the speed factor + reply.copy("Home the axes first"); + result = GCodeResult::error; } - moveBuffer.feedRate = gb.MachineState().feedRate; - moveBuffer.usingStandardFeedrate = true; - NewMoveAvailable(1); - - gb.SetState(GCodeState::waitingForSpecialMoveToComplete); - } - } - else - { - result = GCodeResult::notFinished; - } - break; + else + { + float x, y; + const float z1 = reprap.GetMove().GetProbeCoordinates(0, x, y, true); + const float z2 = reprap.GetMove().GetProbeCoordinates(1, x, y, true); + const float offset = gb.Seen('P') ? gb.GetFValue() : 0.0; + currentUserPosition[Z_AXIS] -= (z1 + z2) / 2.0 + offset; -#if false - // This code is not finished yet - case 674: // Set Z to center point - if (LockMovementAndWaitForStandstill(gb)) - { - if (reprap.GetMove().GetNumProbedProbePoints() < 2) - { - reply.copy("Insufficient probe points"); - result = GCodeResult::error; - } - else if (!AllAxesAreHomed()) - { - reply.copy("Home the axes first"); - result = GCodeResult::error; - } - else - { - float x, y; - const float z1 = reprap.GetMove().GetProbeCoordinates(0, x, y, true); - const float z2 = reprap.GetMove().GetProbeCoordinates(1, x, y, true); - const float offset = gb.Seen('P') ? gb.GetFValue() : 0.0; - currentUserPosition[Z_AXIS] -= (z1 + z2) / 2.0 + offset; + ToolOffsetTransform(currentUserPosition, moveBuffer.coords); + if (reprap.GetMove().GetKinematics().LimitPosition(moveBuffer.coords, numVisibleAxes, LowestNBits<AxesBitmap>(numVisibleAxes), false)) // pretend that all axes are homed + { + ToolOffsetInverseTransform(moveBuffer.coords, currentUserPosition); // make sure the limits are reflected in the user position + } + reprap.GetMove().SetNewPosition(moveBuffer.coords, true); + axesHomed |= reprap.GetMove().GetKinematics().AxesAssumedHomed(MakeBitmap<AxesBitmap>(Z_AXIS)); - ToolOffsetTransform(currentUserPosition, moveBuffer.coords); - if (reprap.GetMove().GetKinematics().LimitPosition(moveBuffer.coords, numVisibleAxes, LowestNBits<AxesBitmap>(numVisibleAxes), false)) // pretend that all axes are homed - { - ToolOffsetInverseTransform(moveBuffer.coords, currentUserPosition); // make sure the limits are reflected in the user position + reply.printf("Probe points at %.2f %.2f, setting new Z to %.2f", (double)z1, (double)z2, (double)currentUserPosition[Z_AXIS]); } - reprap.GetMove().SetNewPosition(moveBuffer.coords, true); - axesHomed |= reprap.GetMove().GetKinematics().AxesAssumedHomed(MakeBitmap<AxesBitmap>(Z_AXIS)); - - reply.printf("Probe points at %.2f %.2f, setting new Z to %.2f", (double)z1, (double)z2, (double)currentUserPosition[Z_AXIS]); } - } - break; + break; #endif - case 675: // Find center of cavity - result = FindCenterOfCavity(gb, reply); - break; + case 675: // Find center of cavity + result = FindCenterOfCavity(gb, reply); + break; - case 701: // Load filament - result = LoadFilament(gb, reply); - break; + case 701: // Load filament + result = LoadFilament(gb, reply); + break; - case 702: // Unload filament - result = UnloadFilament(gb, reply); - break; + case 702: // Unload filament + result = UnloadFilament(gb, reply); + break; - case 703: // Configure Filament - if (reprap.GetCurrentTool() != nullptr) - { - const Filament *filament = reprap.GetCurrentTool()->GetFilament(); - if (filament != nullptr && filament->IsLoaded()) + case 703: // Configure Filament + if (reprap.GetCurrentTool() != nullptr) { - String<ScratchStringLength> scratchString; - scratchString.printf("%s%s/%s", FILAMENTS_DIRECTORY, filament->GetName(), CONFIG_FILAMENT_G); - DoFileMacro(gb, scratchString.c_str(), false, 703); + const Filament *filament = reprap.GetCurrentTool()->GetFilament(); + if (filament != nullptr && filament->IsLoaded()) + { + String<ScratchStringLength> scratchString; + scratchString.printf("%s%s/%s", FILAMENTS_DIRECTORY, filament->GetName(), CONFIG_FILAMENT_G); + DoFileMacro(gb, scratchString.c_str(), false, 703); + } } - } - else - { - result = GCodeResult::error; - reply.copy("No tool selected"); - } - break; + else + { + result = GCodeResult::error; + reply.copy("No tool selected"); + } + break; #if SUPPORT_SCANNER - case 750: // Enable 3D scanner extension - reprap.GetScanner().Enable(); - break; + case 750: // Enable 3D scanner extension + reprap.GetScanner().Enable(); + break; - case 751: // Register 3D scanner extension over USB - if (&gb == usbGCode) - { - if (reprap.GetScanner().IsEnabled()) + case 751: // Register 3D scanner extension over USB + if (&gb == usbGCode) { - reprap.GetScanner().Register(); + if (reprap.GetScanner().IsEnabled()) + { + reprap.GetScanner().Register(); + } + else + { + reply.copy("Scanner extension is not enabled"); + result = GCodeResult::error; + } } else { - reply.copy("Scanner extension is not enabled"); + reply.copy("Invalid source"); result = GCodeResult::error; } - } - else - { - reply.copy("Invalid source"); - result = GCodeResult::error; - } - break; + break; - case 752: // Start 3D scan - if (gb.Seen('P')) - { - String<MaxFilenameLength> file; - gb.GetPossiblyQuotedString(file.GetRef()); - if (gb.Seen('S')) + case 752: // Start 3D scan { + gb.MustSee('P'); + String<MaxFilenameLength> file; + gb.GetPossiblyQuotedString(file.GetRef()); + gb.MustSee('S'); const int range = gb.GetIValue(); if (reprap.GetScanner().IsEnabled()) { @@ -4065,402 +4002,397 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) result = GCodeResult::error; } } - else - { - reply.copy("Missing length/degree parameter"); - result = GCodeResult::error; - } - } - else - { - reply.copy("Missing filename"); - result = GCodeResult::error; - } - break; + break; - case 753: // Cancel current 3D scanner action - if (reprap.GetScanner().IsEnabled()) - { - if (reprap.GetScanner().IsRegistered()) + case 753: // Cancel current 3D scanner action + if (reprap.GetScanner().IsEnabled()) { - result = GetGCodeResultFromFinished(reprap.GetScanner().Cancel()); + if (reprap.GetScanner().IsRegistered()) + { + result = GetGCodeResultFromFinished(reprap.GetScanner().Cancel()); + } + else + { + reply.copy("Scanner is not registered"); + result = GCodeResult::error; + } } else { - reply.copy("Scanner is not registered"); + reply.copy("Scanner extension is not enabled"); result = GCodeResult::error; } - } - else - { - reply.copy("Scanner extension is not enabled"); - result = GCodeResult::error; - } - break; + break; - case 754: // Calibrate scanner - if (reprap.GetScanner().IsEnabled()) - { - if (reprap.GetScanner().IsRegistered()) + case 754: // Calibrate scanner + if (reprap.GetScanner().IsEnabled()) { - const int mode = gb.Seen('N') ? gb.GetIValue() : 0; - result = GetGCodeResultFromFinished(reprap.GetScanner().Calibrate(mode)); + if (reprap.GetScanner().IsRegistered()) + { + const int mode = gb.Seen('N') ? gb.GetIValue() : 0; + result = GetGCodeResultFromFinished(reprap.GetScanner().Calibrate(mode)); + } + else + { + reply.copy("Scanner is not registered"); + result = GCodeResult::error; + } } else { - reply.copy("Scanner is not registered"); + reply.copy("Scanner extension is not enabled"); result = GCodeResult::error; } - } - else - { - reply.copy("Scanner extension is not enabled"); - result = GCodeResult::error; - } - break; + break; - case 755: // Set alignment mode for 3D scanner - if (reprap.GetScanner().IsEnabled()) - { - if (reprap.GetScanner().IsRegistered()) + case 755: // Set alignment mode for 3D scanner + if (reprap.GetScanner().IsEnabled()) { - const bool on = (gb.Seen('P') && gb.GetIValue() > 0); - result = GetGCodeResultFromFinished(reprap.GetScanner().SetAlignment(on)); + if (reprap.GetScanner().IsRegistered()) + { + const bool on = (gb.Seen('P') && gb.GetIValue() > 0); + result = GetGCodeResultFromFinished(reprap.GetScanner().SetAlignment(on)); + } + else + { + reply.copy("Scanner is not registered"); + result = GCodeResult::error; + } } else { - reply.copy("Scanner is not registered"); + reply.copy("Scanner extension is not enabled"); result = GCodeResult::error; } - } - else - { - reply.copy("Scanner extension is not enabled"); - result = GCodeResult::error; - } - break; + break; - case 756: // Shutdown 3D scanner - if (reprap.GetScanner().IsEnabled()) - { - if (reprap.GetScanner().IsRegistered()) + case 756: // Shutdown 3D scanner + if (reprap.GetScanner().IsEnabled()) { - result = GetGCodeResultFromFinished(reprap.GetScanner().Shutdown()); + if (reprap.GetScanner().IsRegistered()) + { + result = GetGCodeResultFromFinished(reprap.GetScanner().Shutdown()); + } + else + { + reply.copy("Scanner is not registered"); + result = GCodeResult::error; + } } else { - reply.copy("Scanner is not registered"); + reply.copy("Scanner extension is not enabled"); result = GCodeResult::error; } - } - else - { - reply.copy("Scanner extension is not enabled"); - result = GCodeResult::error; - } - break; + break; #else - case 750: - case 751: - case 752: - case 753: - case 754: - case 755: - case 756: - reply.copy("Scanner support not built-in"); - result = GCodeResult::error; - break; + case 750: + case 751: + case 752: + case 753: + case 754: + case 755: + case 756: + reply.copy("Scanner support not built-in"); + result = GCodeResult::error; + break; #endif - case 851: // Set Z probe offset, only for Marlin compatibility - { - ZProbe& zp = platform.GetCurrentZProbe(); - if (gb.Seen('Z')) - { - zp.SetTriggerHeight(-gb.GetFValue()); - zp.SetSaveToConfigOverride(); - } - else + case 851: // Set Z probe offset, only for Marlin compatibility { - reply.printf("Z probe offset is %.2fmm", (double)(-zp.GetConfiguredTriggerHeight())); + ZProbe& zp = platform.GetCurrentZProbe(); + if (gb.Seen('Z')) + { + zp.SetTriggerHeight(-gb.GetFValue()); + zp.SetSaveToConfigOverride(); + } + else + { + reply.printf("Z probe offset is %.2fmm", (double)(-zp.GetConfiguredTriggerHeight())); + } } - } - break; + break; - case 905: // Set current RTC date and time - result = SetDateTime(gb, reply); - break; + case 905: // Set current RTC date and time + result = SetDateTime(gb, reply); + break; - case 906: // Set/report Motor currents - case 913: // Set/report motor current percent + case 906: // Set/report Motor currents + case 913: // Set/report motor current percent #if HAS_SMART_DRIVERS - case 917: // Set/report standstill motor current percentage + case 917: // Set/report standstill motor current percentage #endif - // Note that we no longer wait for movement to stop. This is so that we can use these commands (in particular, M913) in the M911 power fail script. - { - bool seen = false; - for (size_t axis = 0; axis < numTotalAxes; axis++) + // Note that we no longer wait for movement to stop. This is so that we can use these commands (in particular, M913) in the M911 power fail script. { - if (gb.Seen(axisLetters[axis])) + bool seen = false; + for (size_t axis = 0; axis < numTotalAxes; axis++) { - if (!platform.SetMotorCurrent(axis, gb.GetFValue(), code, reply)) + if (gb.Seen(axisLetters[axis])) { - result = GCodeResult::error; + if (!platform.SetMotorCurrent(axis, gb.GetFValue(), code, reply)) + { + result = GCodeResult::error; + } + seen = true; } - seen = true; } - } - if (gb.Seen(extrudeLetter)) - { - seen = true; - float eVals[MaxExtruders]; - size_t eCount = numExtruders; - gb.GetFloatArray(eVals, eCount, true); - for (size_t e = 0; e < eCount; e++) + if (gb.Seen(extrudeLetter)) { - if (!platform.SetMotorCurrent(ExtruderToLogicalDrive(e), eVals[e], code, reply)) + seen = true; + float eVals[MaxExtruders]; + size_t eCount = numExtruders; + gb.GetFloatArray(eVals, eCount, true); + for (size_t e = 0; e < eCount; e++) { - result = GCodeResult::error; + if (!platform.SetMotorCurrent(ExtruderToLogicalDrive(e), eVals[e], code, reply)) + { + result = GCodeResult::error; + } } } - } - if (code == 906 && gb.Seen('I')) - { - seen = true; - platform.SetIdleCurrentFactor(gb.GetFValue()/100.0); - } + if (code == 906 && gb.Seen('I')) + { + seen = true; + platform.SetIdleCurrentFactor(gb.GetFValue()/100.0); + } - if (!seen) - { - reply.copy( (code == 913) ? "Motor current % of normal - " + if (!seen) + { + reply.copy( (code == 913) ? "Motor current % of normal - " #if HAS_SMART_DRIVERS : (code == 917) ? "Motor standstill current % of normal - " #endif - : "Motor current (mA) - " - ); - for (size_t axis = 0; axis < numTotalAxes; ++axis) - { - reply.catf("%c:%d, ", axisLetters[axis], (int)platform.GetMotorCurrent(axis, code)); - } - reply.cat("E"); - for (size_t extruder = 0; extruder < numExtruders; extruder++) - { - reply.catf(":%d", (int)platform.GetMotorCurrent(ExtruderToLogicalDrive(extruder), code)); - } - if (code == 906) - { - reply.catf(", idle factor %d%%", (int)(platform.GetIdleCurrentFactor() * 100.0)); + : "Motor current (mA) - " + ); + for (size_t axis = 0; axis < numTotalAxes; ++axis) + { + reply.catf("%c:%d, ", axisLetters[axis], (int)platform.GetMotorCurrent(axis, code)); + } + reply.cat("E"); + for (size_t extruder = 0; extruder < numExtruders; extruder++) + { + reply.catf(":%d", (int)platform.GetMotorCurrent(ExtruderToLogicalDrive(extruder), code)); + } + if (code == 906) + { + reply.catf(", idle factor %d%%", (int)(platform.GetIdleCurrentFactor() * 100.0)); + } } } - } - break; + break; #if HAS_VOLTAGE_MONITOR - case 911: // Enable auto save on loss of power - if (gb.Seen('S')) - { - const float saveVoltage = gb.GetFValue(); - if (saveVoltage < 10.0) + case 911: // Enable auto save on loss of power + if (gb.Seen('S')) { - platform.DisableAutoSave(); + const float saveVoltage = gb.GetFValue(); + if (saveVoltage < 10.0) + { + platform.DisableAutoSave(); + } + else + { + float resumeVoltage = saveVoltage + 1.0; // set up default resume voltage + bool dummy; + gb.TryGetFValue('R', resumeVoltage, dummy); + + String<80> powerFailString; + bool seenCommandString = false; + gb.TryGetQuotedString('P', powerFailString.GetRef(), seenCommandString); + if (seenCommandString) + { + // Replace the power fail script atomically + char *newPowerFailScript = new char[powerFailString.strlen() + 1]; + strcpy(newPowerFailScript, powerFailString.c_str()); + std::swap(newPowerFailScript, powerFailScript); + delete[] newPowerFailScript; + } + else if (powerFailScript == nullptr) + { + reply.copy("No power fail script provided"); + result = GCodeResult::error; + break; + } + platform.EnableAutoSave(saveVoltage, resumeVoltage); + } } else { - float resumeVoltage = saveVoltage + 1.0; // set up default resume voltage - bool dummy; - gb.TryGetFValue('R', resumeVoltage, dummy); - - String<80> powerFailString; - bool seenCommandString = false; - gb.TryGetQuotedString('P', powerFailString.GetRef(), seenCommandString); - if (seenCommandString) + float saveVoltage, resumeVoltage; + if (platform.GetAutoSaveSettings(saveVoltage, resumeVoltage)) { - // Replace the power fail script atomically - char *newPowerFailScript = new char[powerFailString.strlen() + 1]; - strcpy(newPowerFailScript, powerFailString.c_str()); - std::swap(newPowerFailScript, powerFailScript); - delete[] newPowerFailScript; + reply.printf("Auto save voltage %.1fV, resume %.1fV, script \"%s\"", (double)saveVoltage, (double)resumeVoltage, (powerFailScript == nullptr) ? "" : powerFailScript); } - else if (powerFailScript == nullptr) + else { - reply.copy("No power fail script provided"); - result = GCodeResult::error; - break; + reply.copy("Auto save is disabled"); } - platform.EnableAutoSave(saveVoltage, resumeVoltage); } - } - else - { - float saveVoltage, resumeVoltage; - if (platform.GetAutoSaveSettings(saveVoltage, resumeVoltage)) + break; +#endif + +#if HAS_CPU_TEMP_SENSOR + case 912: // Set electronics temperature monitor adjustment + // Currently we ignore the P parameter (i.e. temperature measurement channel) + if (gb.Seen('S')) { - reply.printf("Auto save voltage %.1fV, resume %.1fV, script \"%s\"", (double)saveVoltage, (double)resumeVoltage, (powerFailScript == nullptr) ? "" : powerFailScript); + platform.SetMcuTemperatureAdjust(gb.GetFValue()); } else { - reply.copy("Auto save is disabled"); + reply.printf("MCU temperature calibration adjustment is %.1f" DEGREE_SYMBOL "C", (double)platform.GetMcuTemperatureAdjust()); } - } - break; -#endif - -#if HAS_CPU_TEMP_SENSOR - case 912: // Set electronics temperature monitor adjustment - // Currently we ignore the P parameter (i.e. temperature measurement channel) - if (gb.Seen('S')) - { - platform.SetMcuTemperatureAdjust(gb.GetFValue()); - } - else - { - reply.printf("MCU temperature calibration adjustment is %.1f" DEGREE_SYMBOL "C", (double)platform.GetMcuTemperatureAdjust()); - } - break; + break; #endif // For case 913, see 906 #if defined(__ALLIGATOR__) - case 914: // Set/Get J14 Expansion Voltage Level Translator on Port J5, 5.5V or 3.3V - // Get Piggy module presence status - if (gb.Seen('S')) - { - const int voltageValue = gb.GetIValue(); - if (voltageValue != 5 && voltageValue != 3 ) + case 914: // Set/Get J14 Expansion Voltage Level Translator on Port J5, 5.5V or 3.3V + // Get Piggy module presence status + if (gb.Seen('S')) { - reply.printf("The Expansion Voltage Translator does not support %dV. \n Only 5V or 3V are supported.",voltageValue); + const int voltageValue = gb.GetIValue(); + if (voltageValue != 5 && voltageValue != 3 ) + { + reply.printf("The Expansion Voltage Translator does not support %dV. \n Only 5V or 3V are supported.",voltageValue); + } + else + { + // Change Voltage translator level + digitalWrite(ExpansionVoltageLevelPin, voltageValue == 5); + } } else { - // Change Voltage translator level - digitalWrite(ExpansionVoltageLevelPin, voltageValue == 5); + // Change Voltage translator level Status + reply.printf("The Voltage of Expansion Translator is %dV \nPiggy module %s", + digitalRead(ExpansionVoltageLevelPin) ? 5 : 3 , + digitalRead(ExpansionPiggyDetectPin) ? "not detected" : "detected"); } - } - else - { - // Change Voltage translator level Status - reply.printf("The Voltage of Expansion Translator is %dV \nPiggy module %s", - digitalRead(ExpansionVoltageLevelPin) ? 5 : 3 , - digitalRead(ExpansionPiggyDetectPin) ? "not detected" : "detected"); - } - break; + break; #endif #if HAS_STALL_DETECT - case 915: - result = platform.ConfigureStallDetection(gb, reply, outBuf); - break; + case 915: + result = platform.ConfigureStallDetection(gb, reply, outBuf); + break; #endif #if HAS_MASS_STORAGE - case 916: - if (!platform.SysFileExists(RESUME_AFTER_POWER_FAIL_G)) - { - reply.copy("No resume file found"); - result = GCodeResult::error; - } - else if (!platform.SysFileExists(RESUME_PROLOGUE_G)) - { - reply.printf("Resume prologue file '%s' not found", RESUME_PROLOGUE_G); - result = GCodeResult::error; - } - else - { - DoFileMacro(gb, RESUME_AFTER_POWER_FAIL_G, true, 916); - } - break; + case 916: + if (!platform.SysFileExists(RESUME_AFTER_POWER_FAIL_G)) + { + reply.copy("No resume file found"); + result = GCodeResult::error; + } + else if (!platform.SysFileExists(RESUME_PROLOGUE_G)) + { + reply.printf("Resume prologue file '%s' not found", RESUME_PROLOGUE_G); + result = GCodeResult::error; + } + else + { + DoFileMacro(gb, RESUME_AFTER_POWER_FAIL_G, true, 916); + } + break; #endif // For case 917, see 906 #if SUPPORT_12864_LCD - case 918: // Configure direct-connect display - result = reprap.GetDisplay().Configure(gb, reply); - break; + case 918: // Configure direct-connect display + result = reprap.GetDisplay().Configure(gb, reply); + break; #endif - case 929: // Start/stop event logging + case 929: // Start/stop event logging #if HAS_MASS_STORAGE - result = platform.ConfigureLogging(gb, reply); + result = platform.ConfigureLogging(gb, reply); #else - result = GCodeResult::warningNotSupported; + result = GCodeResult::warningNotSupported; #endif - break; + break; - case 950: // configure I/O pins - result = platform.ConfigurePort(gb, reply); - break; + case 950: // configure I/O pins + result = platform.ConfigurePort(gb, reply); + break; #if SUPPORT_ASYNC_MOVES - case 951: // configure height control - result = reprap.GetMove().ConfigureHeightFollowing(gb, reply); - break; + case 951: // configure height control + result = reprap.GetMove().ConfigureHeightFollowing(gb, reply); + break; #endif - case 997: // Perform firmware update - result = UpdateFirmware(gb, reply); - break; + case 997: // Perform firmware update + result = UpdateFirmware(gb, reply); + break; - case 998: - // The input handling code replaces the gcode by this when it detects a checksum error. - // Since we have no way of asking for the line to be re-sent, just report an error. - if (gb.Seen('P')) - { - const int val = gb.GetIValue(); - if (val != 0) + case 998: + // The input handling code replaces the gcode by this when it detects a checksum error. + // Since we have no way of asking for the line to be re-sent, just report an error. + if (gb.Seen('P')) { - reply.printf("Checksum error on line %d", val); + const int val = gb.GetIValue(); + if (val != 0) + { + reply.printf("Checksum error on line %d", val); + } } - } - break; + break; - case 999: - if (!gb.DoDwellTime(1000)) // wait a second to allow the response to be sent back to the web server, otherwise it may retry - { - return false; - } + case 999: + if (!gb.DoDwellTime(1000)) // wait a second to allow the response to be sent back to the web server, otherwise it may retry + { + return false; + } - reprap.EmergencyStop(); // this disables heaters and drives - Duet WiFi pre-production boards need drives disabled here - { - uint16_t reason = (uint16_t)SoftwareResetReason::user; - if (gb.Seen('P')) + reprap.EmergencyStop(); // this disables heaters and drives - Duet WiFi pre-production boards need drives disabled here { - String<StringLength20> eraseString; - gb.GetQuotedString(eraseString.GetRef()); - if (strcmp(eraseString.c_str(), "ERASE") == 0) + uint16_t reason = (uint16_t)SoftwareResetReason::user; + if (gb.Seen('P')) { - reason = (uint16_t)SoftwareResetReason::erase; + String<StringLength20> eraseString; + gb.GetQuotedString(eraseString.GetRef()); + if (strcmp(eraseString.c_str(), "ERASE") == 0) + { + reason = (uint16_t)SoftwareResetReason::erase; + } } + platform.SoftwareReset(reason); // doesn't return } - platform.SoftwareReset(reason); // doesn't return - } - break; + break; - default: - // See if there is a file in /sys named Mxx.g - if (code >= 0 && code < 10000) - { -#if HAS_LINUX_INTERFACE - if (reprap.UsingLinuxInterface()) + default: + // See if there is a file in /sys named Mxx.g + if (code >= 0 && code < 10000) { - gb.SetState(GCodeState::doingUnsupportedCode); - } +#if HAS_LINUX_INTERFACE + if (reprap.UsingLinuxInterface()) + { + gb.SetState(GCodeState::doingUnsupportedCode); + } #endif - String<StringLength20> macroName; - macroName.printf("M%d.g", code); - if (DoFileMacro(gb, macroName.c_str(), false, code)) - { - break; + String<StringLength20> macroName; + macroName.printf("M%d.g", code); + if (DoFileMacro(gb, macroName.c_str(), false, code)) + { + break; + } } + result = GCodeResult::warningNotSupported; + break; } - result = GCodeResult::warningNotSupported; - break; - } - return HandleResult(gb, result, reply, outBuf); + return HandleResult(gb, result, reply, outBuf); + } + catch (const ParseException& e) + { + OutputBuffer::ReleaseAll(outBuf); + throw; + } } bool GCodes::HandleTcode(GCodeBuffer& gb, const StringRef& reply) diff --git a/src/Hardware/IoPorts.cpp b/src/Hardware/IoPorts.cpp index 96838934..4f7bf15a 100644 --- a/src/Hardware/IoPorts.cpp +++ b/src/Hardware/IoPorts.cpp @@ -25,12 +25,7 @@ { // Get the full port names string String<StringLength50> portNames; - if (!gb.GetReducedString(portNames.GetRef())) - { - reply.copy("Missing port name string"); - return 0; - } - + gb.GetReducedString(portNames.GetRef()); return AssignPorts(portNames.c_str(), reply, neededFor, numPorts, ports, access); } diff --git a/src/Heating/Heat.cpp b/src/Heating/Heat.cpp index 8d7fb36f..baaf07e0 100644 --- a/src/Heating/Heat.cpp +++ b/src/Heating/Heat.cpp @@ -518,11 +518,7 @@ GCodeResult Heat::ConfigureHeater(size_t heater, GCodeBuffer& gb, const StringRe if (gb.Seen('C')) { String<StringLength50> pinName; - if (!gb.GetReducedString(pinName.GetRef())) - { - reply.copy("Missing pin name"); - return GCodeResult::error; - } + gb.GetReducedString(pinName.GetRef()); if (StringEqualsIgnoreCase(pinName.c_str(), NoPinName)) { @@ -963,9 +959,15 @@ GCodeResult Heat::ConfigureSensor(GCodeBuffer& gb, const StringRef& reply) noexc // Set boardAddress to the board number that the port is on, or NoAddress if the port was not given CanAddress boardAddress; String<StringLength20> portName; - boardAddress = (gb.Seen('P') && gb.GetReducedString(portName.GetRef())) - ? IoPort::RemoveBoardAddress(portName.GetRef()) - : CanId::NoAddress; + if (gb.Seen('P')) + { + gb.GetReducedString(portName.GetRef()); + boardAddress = IoPort::RemoveBoardAddress(portName.GetRef()); + } + else + { + boardAddress = CanId::NoAddress; + } #endif bool newSensor = gb.Seen('Y'); if (newSensor) @@ -975,11 +977,7 @@ GCodeResult Heat::ConfigureSensor(GCodeBuffer& gb, const StringRef& reply) noexc DeleteSensor(sensorNum); String<StringLength20> typeName; - if (!gb.GetReducedString(typeName.GetRef())) - { - reply.copy("Missing sensor type name"); - return GCodeResult::error; - } + gb.GetReducedString(typeName.GetRef()); #if SUPPORT_CAN_EXPANSION if (boardAddress == CanId::NoAddress) diff --git a/src/Heating/Sensors/AdditionalOutputSensor.cpp b/src/Heating/Sensors/AdditionalOutputSensor.cpp index 496386bf..0b6cd84b 100644 --- a/src/Heating/Sensors/AdditionalOutputSensor.cpp +++ b/src/Heating/Sensors/AdditionalOutputSensor.cpp @@ -27,11 +27,7 @@ GCodeResult AdditionalOutputSensor::Configure(GCodeBuffer& gb, const StringRef& { seen = true; String<StringLength20> pParam; - if (!gb.GetQuotedString(pParam.GetRef())) - { - reply.copy("Missing parent sensor and output number"); - return GCodeResult::error; - } + gb.GetQuotedString(pParam.GetRef()); const char *pn = pParam.c_str(); if (*pn != 'S' && *pn != 's') diff --git a/src/Linux/DataTransfer.cpp b/src/Linux/DataTransfer.cpp index 2604202d..2d2acc35 100644 --- a/src/Linux/DataTransfer.cpp +++ b/src/Linux/DataTransfer.cpp @@ -533,7 +533,7 @@ bool DataTransfer::IsReady() default: // Should never get here. If we do, this probably means that StartNextTransfer has not been called ExchangeHeader(); - INTERNAL_ERROR; + REPORT_INTERNAL_ERROR; break; } } diff --git a/src/Linux/LinuxInterface.cpp b/src/Linux/LinuxInterface.cpp index 3535b60c..2fd40510 100644 --- a/src/Linux/LinuxInterface.cpp +++ b/src/Linux/LinuxInterface.cpp @@ -50,7 +50,7 @@ void LinuxInterface::Spin() if (packet->request >= (uint16_t)LinuxRequest::InvalidRequest) { - INTERNAL_ERROR; + REPORT_INTERNAL_ERROR; return; } const LinuxRequest request = (LinuxRequest)packet->request; @@ -314,7 +314,7 @@ void LinuxInterface::Spin() // Invalid request default: - INTERNAL_ERROR; + REPORT_INTERNAL_ERROR; break; } } diff --git a/src/Networking/ESP8266WiFi/WiFiInterface.cpp b/src/Networking/ESP8266WiFi/WiFiInterface.cpp index a63f70d0..04ffe795 100644 --- a/src/Networking/ESP8266WiFi/WiFiInterface.cpp +++ b/src/Networking/ESP8266WiFi/WiFiInterface.cpp @@ -899,55 +899,38 @@ GCodeResult WiFiInterface::HandleWiFiCode(int mcode, GCodeBuffer &gb, const Stri WirelessConfigurationData config; memset(&config, 0, sizeof(config)); String<ARRAY_SIZE(config.ssid)> ssid; - bool ok = gb.GetQuotedString(ssid.GetRef()); - if (ok) - { - SafeStrncpy(config.ssid, ssid.c_str(), ARRAY_SIZE(config.ssid)); - String<ARRAY_SIZE(config.password)> password; - ok = gb.Seen('P') && gb.GetQuotedString(password.GetRef()); - if (ok) - { - if (password.strlen() < 8 && password.strlen() != 0) // WPA2 passwords must be at least 8 characters - { - reply.copy("WiFi password must be at least 8 characters"); - return GCodeResult::error; - } - SafeStrncpy(config.password, password.c_str(), ARRAY_SIZE(config.password)); - } - } - if (ok && gb.Seen('I')) + gb.GetQuotedString(ssid.GetRef()); + SafeStrncpy(config.ssid, ssid.c_str(), ARRAY_SIZE(config.ssid)); + String<ARRAY_SIZE(config.password)> password; + gb.MustSee('P'); + gb.GetQuotedString(password.GetRef()); + if (gb.Seen('I')) { IPAddress temp; gb.GetIPAddress(temp); config.ip = temp.GetV4LittleEndian(); } - if (ok && gb.Seen('J')) + if (gb.Seen('J')) { IPAddress temp; - ok = gb.GetIPAddress(temp); + gb.GetIPAddress(temp); config.gateway = temp.GetV4LittleEndian(); } - if (ok && gb.Seen('K')) + if (gb.Seen('K')) { IPAddress temp; - ok = gb.GetIPAddress(temp); + gb.GetIPAddress(temp); config.netmask = temp.GetV4LittleEndian(); } - if (ok) + + const int32_t rslt = SendCommand(NetworkCommand::networkAddSsid, 0, 0, &config, sizeof(config), nullptr, 0); + if (rslt == ResponseEmpty) { - const int32_t rslt = SendCommand(NetworkCommand::networkAddSsid, 0, 0, &config, sizeof(config), nullptr, 0); - if (rslt == ResponseEmpty) - { - return GCodeResult::ok; - } - else - { - reply.copy("Failed to add SSID to remembered list"); - } + return GCodeResult::ok; } else { - reply.copy("Bad or missing parameter"); + reply.copy("Failed to add SSID to remembered list"); } } else @@ -993,31 +976,29 @@ GCodeResult WiFiInterface::HandleWiFiCode(int mcode, GCodeBuffer &gb, const Stri if (gb.Seen('S')) { String<SsidLength> ssidText; - if (gb.GetQuotedString(ssidText.GetRef())) + gb.GetQuotedString(ssidText.GetRef()); + if (strcmp(ssidText.c_str(), "*") == 0) { - if (strcmp(ssidText.c_str(), "*") == 0) - { - const int32_t rslt = SendCommand(NetworkCommand::networkFactoryReset, 0, 0, nullptr, 0, nullptr, 0); - if (rslt == ResponseEmpty) - { - return GCodeResult::ok; - } - - reply.copy("Failed to reset the WiFi module to factory settings"); - return GCodeResult::error; - } - - uint32_t ssid32[NumDwords(SsidLength)]; // need a dword-aligned buffer for SendCommand - memcpy(ssid32, ssidText.c_str(), SsidLength); - const int32_t rslt = SendCommand(NetworkCommand::networkDeleteSsid, 0, 0, ssid32, SsidLength, nullptr, 0); + const int32_t rslt = SendCommand(NetworkCommand::networkFactoryReset, 0, 0, nullptr, 0, nullptr, 0); if (rslt == ResponseEmpty) { return GCodeResult::ok; } - reply.copy("Failed to remove SSID from remembered list"); + reply.copy("Failed to reset the WiFi module to factory settings"); return GCodeResult::error; } + + uint32_t ssid32[NumDwords(SsidLength)]; // need a dword-aligned buffer for SendCommand + memcpy(ssid32, ssidText.c_str(), SsidLength); + const int32_t rslt = SendCommand(NetworkCommand::networkDeleteSsid, 0, 0, ssid32, SsidLength, nullptr, 0); + if (rslt == ResponseEmpty) + { + return GCodeResult::ok; + } + + reply.copy("Failed to remove SSID from remembered list"); + return GCodeResult::error; } reply.copy("Bad or missing parameter"); @@ -1030,56 +1011,39 @@ GCodeResult WiFiInterface::HandleWiFiCode(int mcode, GCodeBuffer &gb, const Stri WirelessConfigurationData config; memset(&config, 0, sizeof(config)); String<SsidLength> ssid; - bool ok = gb.GetQuotedString(ssid.GetRef()); - if (ok) + gb.GetQuotedString(ssid.GetRef()); + if (strcmp(ssid.c_str(), "*") == 0) { - if (strcmp(ssid.c_str(), "*") == 0) - { - // Delete the access point details - memset(&config, 0xFF, sizeof(config)); - } - else - { - SafeStrncpy(config.ssid, ssid.c_str(), ARRAY_SIZE(config.ssid)); - String<ARRAY_SIZE(config.password)> password; - ok = gb.Seen('P') && gb.GetQuotedString(password.GetRef()); - if (ok) - { - SafeStrncpy(config.password, password.c_str(), ARRAY_SIZE(config.password)); - if (password.strlen() < 8 && password.strlen() != 0) // WPA2 passwords must be at least 8 characters - { - reply.copy("WiFi password must be at least 8 characters"); - return GCodeResult::error; - } - SafeStrncpy(config.password, password.c_str(), ARRAY_SIZE(config.password)); - if (gb.Seen('I')) - { - IPAddress temp; - ok = gb.GetIPAddress(temp); - config.ip = temp.GetV4LittleEndian(); - config.channel = (gb.Seen('C')) ? gb.GetIValue() : 0; - } - else - { - ok = false; - } - } - } + // Delete the access point details + memset(&config, 0xFF, sizeof(config)); } - if (ok) + else { - const int32_t rslt = SendCommand(NetworkCommand::networkConfigureAccessPoint, 0, 0, &config, sizeof(config), nullptr, 0); - if (rslt == ResponseEmpty) + SafeStrncpy(config.ssid, ssid.c_str(), ARRAY_SIZE(config.ssid)); + String<ARRAY_SIZE(config.password)> password; + gb.MustSee('P'); + gb.GetQuotedString(password.GetRef()); + SafeStrncpy(config.password, password.c_str(), ARRAY_SIZE(config.password)); + if (password.strlen() < 8 && password.strlen() != 0) // WPA2 passwords must be at least 8 characters { - return GCodeResult::ok; + reply.copy("WiFi password must be at least 8 characters"); + return GCodeResult::error; } - - reply.copy("Failed to configure access point parameters"); + SafeStrncpy(config.password, password.c_str(), ARRAY_SIZE(config.password)); + gb.MustSee('I'); + IPAddress temp; + gb.GetIPAddress(temp); + config.ip = temp.GetV4LittleEndian(); + config.channel = (gb.Seen('C')) ? gb.GetIValue() : 0; } - else + + const int32_t rslt = SendCommand(NetworkCommand::networkConfigureAccessPoint, 0, 0, &config, sizeof(config), nullptr, 0); + if (rslt == ResponseEmpty) { - reply.copy("Bad or missing parameter"); + return GCodeResult::ok; } + + reply.copy("Failed to configure access point parameters"); } else { diff --git a/src/Networking/ESP8266WiFi/WiFiInterface.h b/src/Networking/ESP8266WiFi/WiFiInterface.h index 4e090f8b..13f154b7 100644 --- a/src/Networking/ESP8266WiFi/WiFiInterface.h +++ b/src/Networking/ESP8266WiFi/WiFiInterface.h @@ -67,7 +67,7 @@ public: void TerminateDataPort() noexcept override; // The remaining functions are specific to the WiFi version - GCodeResult HandleWiFiCode(int mcode, GCodeBuffer &gb, const StringRef& reply, OutputBuffer*& longReply); + GCodeResult HandleWiFiCode(int mcode, GCodeBuffer &gb, const StringRef& reply, OutputBuffer*& longReply) THROWS_PARSE_ERROR; WifiFirmwareUploader *GetWifiUploader() const noexcept { return uploader; } void StartWiFi() noexcept; void ResetWiFi() noexcept; diff --git a/src/ObjectModel/ObjectModel.cpp b/src/ObjectModel/ObjectModel.cpp index c1d487ec..39620eff 100644 --- a/src/ObjectModel/ObjectModel.cpp +++ b/src/ObjectModel/ObjectModel.cpp @@ -10,6 +10,7 @@ #if SUPPORT_OBJECT_MODEL #include "OutputMemory.h" +#include <GCodes/GCodeBuffer/StringParser.h> #include <cstring> #include <General/SafeStrtod.h> @@ -256,33 +257,35 @@ int ObjectModelTableEntry::IdCompare(const char *id) const } // Get the value of an object when we don't know what its type is -TypeCode ObjectModel::GetObjectValue(ExpressionValue& val, const char *idString) +ExpressionValue ObjectModel::GetObjectValue(const StringParser& sp, const char *idString) { + ExpressionValue val; + const ObjectModelTableEntry *e = FindObjectModelTableEntry(idString); if (e == nullptr) { - return NoType; + throw sp.ConstructParseException("unknown variable %s", idString); } idString = GetNextElement(idString); void * param = e->param(this); - TypeCode tc = e->type; - if ((tc & IsArray) != 0) + val.type = e->type; + if ((val.type & IsArray) != 0) { if (*idString != '[') { - return NoType; // no array index is provided, and we don't currently allow an entire array to be returned + throw sp.ConstructParseException("can't use whole array"); } const char *endptr; - const unsigned long val = SafeStrtoul(idString + 1, &endptr); + const unsigned long index = SafeStrtoul(idString + 1, &endptr); if (endptr == idString + 1 || *endptr != ']') { - return NoType; // invalid syntax + throw sp.ConstructParseException("expected ']'"); } const ObjectModelArrayDescriptor *arr = (const ObjectModelArrayDescriptor*)param; - if (val >= arr->GetNumElements(this)) + if (index >= arr->GetNumElements(this)) { - return NoType; // array index out of range + throw sp.ConstructParseException("array index out of bounds"); } idString = endptr + 1; // skip past the ']' @@ -290,14 +293,14 @@ TypeCode ObjectModel::GetObjectValue(ExpressionValue& val, const char *idString) { ++idString; // skip any '.' after it because it could be an array of objects } - tc &= ~IsArray; // clear the array flag - param = arr->GetElement(this, val); // fetch the pointer to the array element + val.type &= ~IsArray; // clear the array flag + param = arr->GetElement(this, index); // fetch the pointer to the array element } - switch (tc) + switch (val.type) { case TYPE_OF(ObjectModel): - return ((ObjectModel*)param)->GetObjectValue(val, idString); + return ((ObjectModel*)param)->GetObjectValue(sp, idString); case TYPE_OF(float): case TYPE_OF(Float2): @@ -328,9 +331,9 @@ TypeCode ObjectModel::GetObjectValue(ExpressionValue& val, const char *idString) break; default: - return NoType; + throw sp.ConstructParseException("unknown type"); } - return tc; + return val; } // Template specialisations diff --git a/src/ObjectModel/ObjectModel.h b/src/ObjectModel/ObjectModel.h index e1226dd7..5c5e7ea7 100644 --- a/src/ObjectModel/ObjectModel.h +++ b/src/ObjectModel/ObjectModel.h @@ -23,15 +23,20 @@ constexpr TypeCode NoType = 0; // code for an invalid or unknown type // Forward declarations class ObjectModelTableEntry; class ObjectModel; +class StringParser; -union ExpressionValue +struct ExpressionValue { - bool bVal; - float fVal; - int32_t iVal; - uint32_t uVal; - const char *sVal; - const ObjectModel *omVal; + TypeCode type; + union + { + bool bVal; + float fVal; + int32_t iVal; + uint32_t uVal; + const char *sVal; + const ObjectModel *omVal; + }; }; // Dummy types, used to define type codes @@ -58,7 +63,7 @@ public: TypeCode GetObjectType(const char *idString); // Get the value of an object when we don't know what its type is - TypeCode GetObjectValue(ExpressionValue& val, const char *idString); + ExpressionValue GetObjectValue(const StringParser& sp, const char *idString); // Specialisation of above for float, allowing conversion from integer to float bool GetObjectValue(float& val, const char *idString); diff --git a/src/Pccb/Pins_Pccb.h b/src/Pccb/Pins_Pccb.h index e9d3719b..20607b62 100644 --- a/src/Pccb/Pins_Pccb.h +++ b/src/Pccb/Pins_Pccb.h @@ -55,7 +55,6 @@ constexpr uint32_t IAP_IMAGE_END = 0x0047FFFF; // we allow a full 64K on the SA #define HAS_VOLTAGE_MONITOR 1 #define ENFORCE_MAX_VIN 1 #define HAS_VREF_MONITOR 1 -#define ACTIVE_LOW_HEAT_ON 0 // although we have no heaters, this matters because we treat the LEDs as heaters #define SUPPORT_INKJET 0 // set nonzero to support inkjet control #define SUPPORT_ROLAND 0 // set nonzero to support Roland mill @@ -63,6 +62,7 @@ constexpr uint32_t IAP_IMAGE_END = 0x0047FFFF; // we allow a full 64K on the SA #define SUPPORT_IOBITS 0 // set to support P parameter in G0/G1 commands #define SUPPORT_DHT_SENSOR 0 // set nonzero to support DHT temperature/humidity sensors (requires RTOS) #define SUPPORT_WORKPLACE_COORDINATES 1 // set nonzero to support G10 L2 and G53..59 +#define SUPPORT_OBJECT_MODEL 1 #define SUPPORT_12864_LCD 0 // set nonzero to support 12864 LCD and rotary encoder #define SUPPORT_DOTSTAR_LED 1 // set nonzero to support DotStar LED strips #define ALLOCATE_DEFAULT_PORTS 1 diff --git a/src/Platform.cpp b/src/Platform.cpp index 8b1dba6a..0edf770e 100644 --- a/src/Platform.cpp +++ b/src/Platform.cpp @@ -3254,11 +3254,7 @@ GCodeResult Platform::ConfigureLogging(GCodeBuffer& gb, const StringRef& reply) StringRef filename(buf, ARRAY_SIZE(buf)); if (gb.Seen('P')) { - if (!gb.GetQuotedString(filename)) - { - reply.copy("Missing filename in M929 command"); - return GCodeResult::error; - } + gb.GetQuotedString(filename); } else { @@ -4158,11 +4154,7 @@ GCodeResult Platform::ConfigureGpioOrServo(uint32_t gpioNumber, bool isServo, GC if (gb.Seen('C')) { String<StringLength50> pinName; - if (!gb.GetReducedString(pinName.GetRef())) - { - reply.copy("Missing pin name"); - return GCodeResult::error; - } + gb.GetReducedString(pinName.GetRef()); // Remove any existing assignment #if SUPPORT_CAN_EXPANSION diff --git a/src/RADDS/Pins_RADDS.h b/src/RADDS/Pins_RADDS.h index 5ffc7dae..64a32bcc 100644 --- a/src/RADDS/Pins_RADDS.h +++ b/src/RADDS/Pins_RADDS.h @@ -10,31 +10,42 @@ #define HAS_HIGH_SPEED_SD 0 #define HAS_VOLTAGE_MONITOR 0 #define HAS_VREF_MONITOR 0 -#define ACTIVE_LOW_HEAT_ON 0 const size_t NumFirmwareUpdateModules = 1; -#define IAP_UPDATE_FILE "iapradds.bin" #define IAP_FIRMWARE_FILE "RepRapFirmware-RADDS.bin" +#define IAP_IN_RAM 0 + +#if IAP_IN_RAM + +# define IAP_UPDATE_FILE "RaddsIAP.bin" +constexpr uint32_t IAP_IMAGE_START = 0x20008000u; + +#else + +# define IAP_UPDATE_FILE "iapradds.bin" +constexpr uint32_t IAP_IMAGE_START = 0x000F0000; +constexpr uint32_t IAP_IMAGE_END = 0x000FFBFF; // don't touch the last 1KB, it's used for NvData + +#endif + // Default board type #define DEFAULT_BOARD_TYPE BoardType::RADDS_15 #define ELECTRONICS "RADDS" -#define SUPPORT_INKJET 0 // set nonzero to support inkjet control -#define SUPPORT_ROLAND 0 // set nonzero to support Roland mill -#define SUPPORT_SCANNER 0 // set nonzero to support FreeLSS scanners -#define SUPPORT_IOBITS 0 // set to support P parameter in G0/G1 commands -#define SUPPORT_DHT_SENSOR 0 // set nonzero to support DHT temperature/humidity sensors - -#define NO_EXTRUDER_ENDSTOPS 1 // Temporary!!! +#define SUPPORT_INKJET 0 // set nonzero to support inkjet control +#define SUPPORT_ROLAND 0 // set nonzero to support Roland mill +#define SUPPORT_SCANNER 0 // set nonzero to support FreeLSS scanners +#define SUPPORT_IOBITS 0 // set to support P parameter in G0/G1 commands +#define SUPPORT_DHT_SENSOR 0 // set nonzero to support DHT temperature/humidity sensors +#define SUPPORT_OBJECT_MODEL 1 // The physical capabilities of the machine // The number of drives in the machine, including X, Y, and Z plus extruder drives constexpr size_t NumDirectDrivers = 9; -constexpr size_t MaxSensorsInSystem = 32; -typedef uint32_t SensorsBitmap; +constexpr size_t MaxSensors = 32; constexpr size_t MaxHeaters = 3; constexpr size_t MaxExtraHeaterProtections = 4; // The number of extra heater protection instances @@ -238,10 +249,6 @@ constexpr PwmFrequency DefaultFanPwmFrequencies[] = { DefaultFanPwmFreq }; // Function to look up a pin name pass back the corresponding index into the pin table bool LookupPinName(const char *pn, LogicalPin& lpin, bool& hardwareInverted); -// SAM3X Flash locations (may be expanded in the future) -constexpr uint32_t IAP_FLASH_START = 0x000F0000; -constexpr uint32_t IAP_FLASH_END = 0x000FFBFF; // don't touch the last 1KB, it's used for NvData - // Timer allocation #define NETWORK_TC (TC1) #define NETWORK_TC_CHAN (1) diff --git a/src/RepRap.cpp b/src/RepRap.cpp index 53e2c73c..399b0403 100644 --- a/src/RepRap.cpp +++ b/src/RepRap.cpp @@ -2481,7 +2481,7 @@ void RepRap::UpdateFirmware() noexcept # else // SAM3X code - for (uint32_t flashAddr = IAP_FLASH_START; flashAddr < IAP_FLASH_END; flashAddr += IFLASH_PAGE_SIZE) + for (uint32_t flashAddr = IAP_IMAGE_START; flashAddr < IAP_IMAGE_END; flashAddr += IFLASH_PAGE_SIZE) { const int bytesRead = iapFile->Read(data, IFLASH_PAGE_SIZE); @@ -2513,13 +2513,13 @@ void RepRap::UpdateFirmware() noexcept if (rc != FLASH_RC_OK) { - MessageF(FirmwareUpdateErrorMessage, "flash %s failed, code=%" PRIu32 ", address=0x%08" PRIx32 "\n", op, rc, flashAddr); + platform->MessageF(FirmwareUpdateErrorMessage, "flash %s failed, code=%" PRIu32 ", address=0x%08" PRIx32 "\n", op, rc, flashAddr); return; } // Verify written data if (memcmp(reinterpret_cast<void *>(flashAddr), data, bytesRead) != 0) { - MessageF(FirmwareUpdateErrorMessage, "verify during flash write failed, address=0x%08" PRIx32 "\n", flashAddr); + platform->MessageF(FirmwareUpdateErrorMessage, "verify during flash write failed, address=0x%08" PRIx32 "\n", flashAddr); return; } } diff --git a/src/RepRap.h b/src/RepRap.h index 651f1dd3..1f5b75b6 100644 --- a/src/RepRap.h +++ b/src/RepRap.h @@ -243,9 +243,7 @@ inline uint16_t RepRap::GetExtrudersInUse() const noexcept { return activeExtrud inline uint16_t RepRap::GetToolHeatersInUse() const noexcept { return activeToolHeaters; } inline bool RepRap::IsStopped() const noexcept { return stopped; } -#define STRINGIZE(s) #s -#define INTERNAL_ERROR do { reprap.ReportInternalError((__FILE__), (__func__), (__LINE__)); } while(0) -#define INTERNAL_ERROR_MESSAGE "Internal error at " __FILE__ "(" STRINGIZE(__LINE__) ")" +#define REPORT_INTERNAL_ERROR do { reprap.ReportInternalError((__FILE__), (__func__), (__LINE__)); } while(0) #endif diff --git a/src/RepRapFirmware.h b/src/RepRapFirmware.h index e2d020ac..3da8bcd3 100644 --- a/src/RepRapFirmware.h +++ b/src/RepRapFirmware.h @@ -89,7 +89,7 @@ enum class PinUsedBy : uint8_t static_assert(NumNamedPins <= 255 || sizeof(LogicalPin) > 1, "Need 16-bit logical pin numbers"); #if SUPPORT_CAN_EXPANSION -# include "CanId.h" // for type CanAddress +# include "CanId.h" // for type CanAddress #endif #include "General/StringRef.h" @@ -98,6 +98,9 @@ static_assert(NumNamedPins <= 255 || sizeof(LogicalPin) > 1, "Need 16-bit logica #include "General/SafeStrtod.h" #include "General/SafeVsnprintf.h" +#define THROWS_PARSE_ERROR // we tag this on to function declarations to indicate that they may throw parse errors, which must be caught +#define THROW_INTERNAL_ERROR throw ConstructParseException("internal error at file " __FILE__ "(%d)", __LINE__) + // Type of a driver identifier struct DriverId { diff --git a/src/Storage/FileStore.cpp b/src/Storage/FileStore.cpp index adf704d8..d92e5c41 100644 --- a/src/Storage/FileStore.cpp +++ b/src/Storage/FileStore.cpp @@ -140,7 +140,7 @@ void FileStore::Duplicate() switch (usageMode) { case FileUseMode::free: - INTERNAL_ERROR; + REPORT_INTERNAL_ERROR; break; case FileUseMode::readOnly: @@ -166,7 +166,7 @@ bool FileStore::Close() case FileUseMode::free: if (!inInterrupt()) { - INTERNAL_ERROR; + REPORT_INTERNAL_ERROR; } return false; @@ -237,7 +237,7 @@ bool FileStore::Seek(FilePosition pos) switch (usageMode) { case FileUseMode::free: - INTERNAL_ERROR; + REPORT_INTERNAL_ERROR; return false; case FileUseMode::readOnly: @@ -272,7 +272,7 @@ FilePosition FileStore::Length() const switch (usageMode) { case FileUseMode::free: - INTERNAL_ERROR; + REPORT_INTERNAL_ERROR; return 0; case FileUseMode::readOnly: @@ -299,7 +299,7 @@ int FileStore::Read(char* extBuf, size_t nBytes) switch (usageMode) { case FileUseMode::free: - INTERNAL_ERROR; + REPORT_INTERNAL_ERROR; return -1; case FileUseMode::readOnly: @@ -387,7 +387,7 @@ bool FileStore::Write(const char *s, size_t len) switch (usageMode) { case FileUseMode::free: - INTERNAL_ERROR; + REPORT_INTERNAL_ERROR; return false; case FileUseMode::readOnly: @@ -441,7 +441,7 @@ bool FileStore::Flush() switch (usageMode) { case FileUseMode::free: - INTERNAL_ERROR; + REPORT_INTERNAL_ERROR; return false; case FileUseMode::readOnly: @@ -479,7 +479,7 @@ bool FileStore::Truncate() { case FileUseMode::free: case FileUseMode::readOnly: - INTERNAL_ERROR; + REPORT_INTERNAL_ERROR; return false; case FileUseMode::readWrite: |