diff options
author | David Crocker <dcrocker@eschertech.com> | 2020-01-13 01:59:32 +0300 |
---|---|---|
committer | David Crocker <dcrocker@eschertech.com> | 2020-01-13 01:59:32 +0300 |
commit | 13084f6566c536df08430cce6c584f5e5c06b5a8 (patch) | |
tree | 44765c911f8a5850ee3d18147658b29b0eba0726 | |
parent | d935cc8c828e44430f6a4dc2eacf53c04268fe96 (diff) |
Various
Refactored how GCode blocks and indentation are tracked
Fixed lack of motor movement on Duet 3
Create path recursively if needed when creating a directory or renaming
a file
-rw-r--r-- | src/GCodes/GCodeBuffer/StringParser.cpp | 66 | ||||
-rw-r--r-- | src/GCodes/GCodeBuffer/StringParser.h | 2 | ||||
-rw-r--r-- | src/GCodes/GCodeMachineState.cpp | 25 | ||||
-rw-r--r-- | src/GCodes/GCodeMachineState.h | 26 | ||||
-rw-r--r-- | src/Hardware/IoPorts.cpp | 22 | ||||
-rw-r--r-- | src/Movement/StepTimer.cpp | 2 | ||||
-rw-r--r-- | src/Movement/StepperDrivers/TMC51xx.cpp | 2 | ||||
-rw-r--r-- | src/RepRap.cpp | 2 | ||||
-rw-r--r-- | src/Storage/FileStore.cpp | 24 | ||||
-rw-r--r-- | src/Storage/MassStorage.cpp | 48 | ||||
-rw-r--r-- | src/Storage/MassStorage.h | 2 | ||||
-rw-r--r-- | src/Version.h | 4 |
12 files changed, 111 insertions, 114 deletions
diff --git a/src/GCodes/GCodeBuffer/StringParser.cpp b/src/GCodes/GCodeBuffer/StringParser.cpp index 8c5dcb3e..cefaab89 100644 --- a/src/GCodes/GCodeBuffer/StringParser.cpp +++ b/src/GCodes/GCodeBuffer/StringParser.cpp @@ -297,18 +297,27 @@ bool StringParser::CheckMetaCommand(const StringRef& reply) indentToSkipTo = NoIndentSkip; // no longer skipping } - if (commandIndent > gb.machineState->indentLevel) + while (commandIndent < gb.machineState->CurrentBlockIndent()) { - CreateBlocks(); // indentation has increased so start new block(s) - } - else if (commandIndent < gb.machineState->indentLevel) - { - if (EndBlocks()) + gb.machineState->EndBlock(); + if (gb.machineState->CurrentBlockState().GetType() == BlockType::loop) { + // Go back to the start of the loop and re-evaluate the while-part + gb.machineState->lineNumber = gb.machineState->CurrentBlockState().GetLineNumber(); + gb.RestartFrom(gb.machineState->CurrentBlockState().GetFilePosition()); Init(); return true; } } + + if (commandIndent > gb.machineState->CurrentBlockIndent()) + { + // indentation has increased so start new block(s) + if (!gb.machineState->CreateBlock(commandIndent)) + { + throw ConstructParseException("blocks nested too deeply"); + } + } } const bool b = ProcessConditionalGCode(reply, previousBlockType, doingFile); // this may throw a ParseException @@ -419,35 +428,6 @@ bool StringParser::ProcessConditionalGCode(const StringRef& reply, BlockType pre return false; } -// Create new code blocks -void StringParser::CreateBlocks() -{ - while (gb.machineState->indentLevel < commandIndent) - { - if (!gb.machineState->CreateBlock()) - { - throw ConstructParseException("blocks nested too deeply"); - } - } -} - -// End blocks returning true if nothing more to process on this line -bool StringParser::EndBlocks() noexcept -{ - while (gb.machineState->indentLevel > commandIndent) - { - gb.machineState->EndBlock(); - if (gb.machineState->CurrentBlockState().GetType() == BlockType::loop) - { - // Go back to the start of the loop and re-evaluate the while-part - gb.machineState->lineNumber = gb.machineState->CurrentBlockState().GetLineNumber(); - gb.RestartFrom(gb.machineState->CurrentBlockState().GetFilePosition()); - return true; - } - } - return false; -} - void StringParser::ProcessIfCommand() { if (EvaluateCondition()) @@ -457,7 +437,7 @@ void StringParser::ProcessIfCommand() else { gb.machineState->CurrentBlockState().SetIfFalseNoneTrueBlock(); - indentToSkipTo = gb.machineState->indentLevel; // skip forwards to the end of the block + indentToSkipTo = gb.machineState->CurrentBlockIndent(); // skip forwards to the end of the block } } @@ -469,7 +449,7 @@ void StringParser::ProcessElseCommand(BlockType previousBlockType) } else if (gb.machineState->CurrentBlockState().GetType() == BlockType::ifTrue || gb.machineState->CurrentBlockState().GetType() == BlockType::ifFalseHadTrue) { - indentToSkipTo = gb.machineState->indentLevel; // skip forwards to the end of the if-block + indentToSkipTo = gb.machineState->CurrentBlockIndent(); // skip forwards to the end of the if-block gb.machineState->CurrentBlockState().SetPlainBlock(); // so that we get an error if there is another 'else' part } else @@ -488,13 +468,13 @@ void StringParser::ProcessElifCommand(BlockType previousBlockType) } else { - indentToSkipTo = gb.machineState->indentLevel; // skip forwards to the end of the elif-block + indentToSkipTo = gb.machineState->CurrentBlockIndent(); // skip forwards to the end of the elif-block gb.machineState->CurrentBlockState().SetIfFalseNoneTrueBlock(); } } else if (gb.machineState->CurrentBlockState().GetType() == BlockType::ifTrue || gb.machineState->CurrentBlockState().GetType() == BlockType::ifFalseHadTrue) { - indentToSkipTo = gb.machineState->indentLevel; // skip forwards to the end of the if-block + indentToSkipTo = gb.machineState->CurrentBlockIndent(); // skip forwards to the end of the if-block gb.machineState->CurrentBlockState().SetIfFalseHadTrueBlock(); } else @@ -518,7 +498,7 @@ void StringParser::ProcessWhileCommand() if (!EvaluateCondition()) { gb.machineState->CurrentBlockState().SetPlainBlock(); - indentToSkipTo = gb.machineState->indentLevel; // skip forwards to the end of the block + indentToSkipTo = gb.machineState->CurrentBlockIndent(); // skip forwards to the end of the block } } @@ -526,21 +506,21 @@ void StringParser::ProcessBreakCommand() { do { - if (gb.machineState->indentLevel == 0) + if (gb.machineState->CurrentBlockIndent() == 0) { throw ConstructParseException("'break' was not inside a loop"); } gb.machineState->EndBlock(); } while (gb.machineState->CurrentBlockState().GetType() != BlockType::loop); gb.machineState->CurrentBlockState().SetPlainBlock(); - indentToSkipTo = gb.machineState->indentLevel; // skip forwards to the end of the loop + indentToSkipTo = gb.machineState->CurrentBlockIndent(); // skip forwards to the end of the loop } void StringParser::ProcessContinueCommand() { do { - if (gb.machineState->indentLevel == 0) + if (gb.machineState->CurrentBlockIndent() == 0) { throw ConstructParseException("'continue' was not inside a loop"); } diff --git a/src/GCodes/GCodeBuffer/StringParser.h b/src/GCodes/GCodeBuffer/StringParser.h index bc5236f5..c767baba 100644 --- a/src/GCodes/GCodeBuffer/StringParser.h +++ b/src/GCodes/GCodeBuffer/StringParser.h @@ -100,8 +100,6 @@ private: bool ProcessConditionalGCode(const StringRef& reply, BlockType previousBlockType, bool doingFile) THROWS_GCODE_EXCEPTION; // Check for and process a conditional GCode language command returning true if we found one - void CreateBlocks() THROWS_GCODE_EXCEPTION; // Create new code blocks - bool EndBlocks() noexcept; // End blocks returning true if nothing more to process on this line void ProcessIfCommand() THROWS_GCODE_EXCEPTION; void ProcessElseCommand(BlockType previousBlockType) THROWS_GCODE_EXCEPTION; void ProcessElifCommand(BlockType previousBlockType) THROWS_GCODE_EXCEPTION; diff --git a/src/GCodes/GCodeMachineState.cpp b/src/GCodes/GCodeMachineState.cpp index 36aa4e14..f243de2f 100644 --- a/src/GCodes/GCodeMachineState.cpp +++ b/src/GCodes/GCodeMachineState.cpp @@ -22,13 +22,13 @@ GCodeMachineState::GCodeMachineState() noexcept : previous(nullptr), feedRate(DefaultFeedRate * SecondsToMinutes), lockedResources(0), errorMessage(nullptr), lineNumber(0), compatibility(Compatibility::reprapFirmware), drivesRelative(false), axesRelative(false), doingFileMacro(false), runningM501(false), runningM502(false), volumetricExtrusion(false), g53Active(false), runningSystemMacro(false), usingInches(false), - waitingForAcknowledgement(false), messageAcknowledged(false), indentLevel(0), state(GCodeState::normal) + waitingForAcknowledgement(false), messageAcknowledged(false), blockNesting(0), state(GCodeState::normal) { #if HAS_LINUX_INTERFACE fileId = 0; isFileFinished = fileError = false; #endif - blockStates[0].SetPlainBlock(); + blockStates[0].SetPlainBlock(0); } #if HAS_LINUX_INTERFACE @@ -147,13 +147,18 @@ void GCodeMachineState::CopyStateFrom(const GCodeMachineState& other) noexcept GCodeMachineState::BlockState& GCodeMachineState::CurrentBlockState() noexcept { - return blockStates[indentLevel]; + return blockStates[blockNesting]; +} + +const GCodeMachineState::BlockState& GCodeMachineState::CurrentBlockState() const noexcept +{ + return blockStates[blockNesting]; } // Get the number of iterations of the closest enclosing loop in the current file, or -1 if there is on enclosing loop int32_t GCodeMachineState::GetIterations() const noexcept { - uint8_t i = indentLevel; + uint8_t i = blockNesting; while (true) { if (blockStates[i].GetType() == BlockType::loop) @@ -169,23 +174,23 @@ int32_t GCodeMachineState::GetIterations() const noexcept } // Create a new block returning true if successful, false if maximum indent level exceeded -bool GCodeMachineState::CreateBlock() noexcept +bool GCodeMachineState::CreateBlock(uint16_t indentLevel) noexcept { - if (indentLevel + 1 == ARRAY_SIZE(blockStates)) + if (blockNesting + 1 == ARRAY_SIZE(blockStates)) { return false; } - ++indentLevel; - CurrentBlockState().SetPlainBlock(); + ++blockNesting; + CurrentBlockState().SetPlainBlock(indentLevel); return true; } void GCodeMachineState::EndBlock() noexcept { - if (indentLevel != 0) + if (blockNesting != 0) { - --indentLevel; + --blockNesting; } } diff --git a/src/GCodes/GCodeMachineState.h b/src/GCodes/GCodeMachineState.h index 8ace3eff..b63e9b18 100644 --- a/src/GCodes/GCodeMachineState.h +++ b/src/GCodes/GCodeMachineState.h @@ -137,24 +137,27 @@ public: class BlockState { public: - BlockType GetType() const noexcept { return (BlockType) blockType; } + BlockType GetType() const noexcept { return blockType; } uint32_t GetIterations() const noexcept { return iterationsDone; } uint32_t GetLineNumber() const noexcept { return lineNumber; } FilePosition GetFilePosition() const noexcept { return fpos; } + uint16_t GetIndent() const noexcept { return indentLevel; } - void SetLoopBlock(FilePosition filePos, uint32_t lineNum) noexcept { blockType = (uint32_t)BlockType::loop; fpos = filePos; lineNumber = lineNum; iterationsDone = 0; } - void SetPlainBlock() noexcept { blockType = (uint32_t)BlockType::plain; iterationsDone = 0; } - void SetIfTrueBlock() noexcept { blockType = (uint32_t)BlockType::ifTrue; iterationsDone = 0; } - void SetIfFalseNoneTrueBlock() noexcept { blockType = (uint32_t)BlockType::ifFalseNoneTrue; iterationsDone = 0; } - void SetIfFalseHadTrueBlock() noexcept { blockType = (uint32_t)BlockType::ifFalseHadTrue; iterationsDone = 0; } + void SetLoopBlock(FilePosition filePos, uint32_t lineNum) noexcept { blockType = BlockType::loop; fpos = filePos; lineNumber = lineNum; iterationsDone = 0; } + void SetPlainBlock() noexcept { blockType = BlockType::plain; iterationsDone = 0; } + void SetPlainBlock(uint16_t p_indentLevel) noexcept { blockType = BlockType::plain; iterationsDone = 0; indentLevel = p_indentLevel; } + void SetIfTrueBlock() noexcept { blockType = BlockType::ifTrue; iterationsDone = 0; } + void SetIfFalseNoneTrueBlock() noexcept { blockType = BlockType::ifFalseNoneTrue; iterationsDone = 0; } + void SetIfFalseHadTrueBlock() noexcept { blockType = BlockType::ifFalseHadTrue; iterationsDone = 0; } void IncrementIterations() noexcept { ++iterationsDone; } private: FilePosition fpos; // the file offset at which the current block started - uint32_t lineNumber : 29, // the line number at which the current block started - blockType : 3; // the type of this block + uint32_t lineNumber; // the line number at which the current block started uint32_t iterationsDone; + uint16_t indentLevel; // the indentation of this block + BlockType blockType; // the type of this block }; GCodeMachineState() noexcept; @@ -192,7 +195,8 @@ public: waitingForAcknowledgement : 1, messageAcknowledged : 1, messageCancelled : 1; - uint8_t indentLevel; + + uint8_t blockNesting; GCodeState state; uint8_t toolChangeParam; @@ -214,9 +218,11 @@ public: void CopyStateFrom(const GCodeMachineState& other) noexcept; BlockState& CurrentBlockState() noexcept; + const BlockState& CurrentBlockState() const noexcept; int32_t GetIterations() const noexcept; + uint16_t CurrentBlockIndent() const noexcept { return CurrentBlockState().GetIndent(); } - bool CreateBlock() noexcept; + bool CreateBlock(uint16_t indentLevel) noexcept; void EndBlock() noexcept; static void Release(GCodeMachineState *ms) noexcept; diff --git a/src/Hardware/IoPorts.cpp b/src/Hardware/IoPorts.cpp index 5f024ed3..7bef2981 100644 --- a/src/Hardware/IoPorts.cpp +++ b/src/Hardware/IoPorts.cpp @@ -138,17 +138,17 @@ void IoPort::Release() noexcept if (IsValid() && !isSharedInput) { #ifdef __LPC17xx__ - //Release PWM/Servo from pin if needed - if(logicalPinModes[logicalPin] == OUTPUT_SERVO_HIGH || logicalPinModes[logicalPin] == OUTPUT_SERVO_LOW) - { - ReleaseServoPin(PinTable[logicalPin].pin); - } - if(logicalPinModes[logicalPin] == OUTPUT_PWM_HIGH || logicalPinModes[logicalPin] == OUTPUT_PWM_LOW) - { - ReleasePWMPin(PinTable[logicalPin].pin); - } + // Release PWM/Servo from pin if needed + if (logicalPinModes[logicalPin] == OUTPUT_SERVO_HIGH || logicalPinModes[logicalPin] == OUTPUT_SERVO_LOW) + { + ReleaseServoPin(PinTable[logicalPin].pin); + } + if (logicalPinModes[logicalPin] == OUTPUT_PWM_HIGH || logicalPinModes[logicalPin] == OUTPUT_PWM_LOW) + { + ReleasePWMPin(PinTable[logicalPin].pin); + } #endif - detachInterrupt(PinTable[logicalPin].pin); + detachInterrupt(PinTable[logicalPin].pin); portUsedBy[logicalPin] = PinUsedBy::unused; logicalPinModes[logicalPin] = PIN_MODE_NOT_CONFIGURED; } @@ -342,7 +342,7 @@ bool IoPort::SetMode(PinAccess access) noexcept } } #endif - IoPort::SetPinMode(PinTable[logicalPin].pin, desiredMode); + IoPort::SetPinMode(PinTable[logicalPin].pin, desiredMode); logicalPinModes[logicalPin] = (int8_t)desiredMode; } return true; diff --git a/src/Movement/StepTimer.cpp b/src/Movement/StepTimer.cpp index 1f9e92a4..092900a2 100644 --- a/src/Movement/StepTimer.cpp +++ b/src/Movement/StepTimer.cpp @@ -279,10 +279,10 @@ void StepTimer::CancelCallbackFromIsr() noexcept if (*ppst == this) { *ppst = this->next; // unlink this from the pending list - active = false; break; } } + active = false; } void StepTimer::CancelCallback() noexcept diff --git a/src/Movement/StepperDrivers/TMC51xx.cpp b/src/Movement/StepperDrivers/TMC51xx.cpp index d05bc7a6..798b27ea 100644 --- a/src/Movement/StepperDrivers/TMC51xx.cpp +++ b/src/Movement/StepperDrivers/TMC51xx.cpp @@ -1183,7 +1183,7 @@ extern "C" [[noreturn]] void TmcLoop(void *) noexcept } // Wait for the end-of-transfer interrupt - timedOut = (TaskBase::Take(TransferTimeout) == 0); + timedOut = TaskBase::Take(TransferTimeout); DisableEndOfTransferInterrupt(); DisableDma(); diff --git a/src/RepRap.cpp b/src/RepRap.cpp index a5d0fde7..d40e9561 100644 --- a/src/RepRap.cpp +++ b/src/RepRap.cpp @@ -106,7 +106,7 @@ extern "C" void hsmciIdle(uint32_t stBits, uint32_t dmaBits) noexcept XDMAC->XDMAC_CHID[DmacChanHsmci].XDMAC_CIE = dmaBits; XDMAC->XDMAC_GIE = 1u << DmacChanHsmci; #endif - if (TaskBase::Take(200) == 0) + if (TaskBase::Take(200)) { // We timed out waiting for the HSMCI operation to complete reprap.GetPlatform().LogError(ErrorCode::HsmciTimeout); diff --git a/src/Storage/FileStore.cpp b/src/Storage/FileStore.cpp index 284aa956..c3d2643d 100644 --- a/src/Storage/FileStore.cpp +++ b/src/Storage/FileStore.cpp @@ -64,29 +64,9 @@ bool FileStore::Open(const char* filePath, OpenMode mode, uint32_t preAllocSize) if (writing) { - // Try to create the path of this file if we want to write to it - String<MaxFilenameLength> filePathCopy; - filePathCopy.copy(filePath); - - size_t i = (isdigit(filePathCopy[0]) && filePathCopy[1] == ':') ? 2 : 0; - if (filePathCopy[i] == '/') + if (!MassStorage::EnsurePath(filePath)) { - ++i; - } - - while (i < filePathCopy.strlen()) - { - if (filePathCopy[i] == '/') - { - filePathCopy[i] = 0; - if (!MassStorage::DirectoryExists(filePathCopy.GetRef()) && !MassStorage::MakeDirectory(filePathCopy.c_str())) - { - reprap.GetPlatform().MessageF(ErrorMessage, "Failed to create folder %s while trying to open file %s\n", filePathCopy.c_str(), filePath); - return false; - } - filePathCopy[i] = '/'; - } - ++i; + return false; } // Also try to allocate a write buffer so we can perform faster writes diff --git a/src/Storage/MassStorage.cpp b/src/Storage/MassStorage.cpp index e3d8e6b9..52a94e0b 100644 --- a/src/Storage/MassStorage.cpp +++ b/src/Storage/MassStorage.cpp @@ -374,27 +374,51 @@ bool MassStorage::Delete(const char* filePath) noexcept return true; } -// Create a new directory -bool MassStorage::MakeDirectory(const char *parentDir, const char *dirName) noexcept +// Ensure that the path up to the last '/' (excluding trailing '/' characters) in filePath exists, returning true if successful +bool MassStorage::EnsurePath(const char* filePath) noexcept { - String<MaxFilenameLength> location; - if (!CombineName(location.GetRef(), parentDir, dirName)) + // Try to create the path of this file if we want to write to it + String<MaxFilenameLength> filePathCopy; + filePathCopy.copy(filePath); + + size_t i = (isdigit(filePathCopy[0]) && filePathCopy[1] == ':') ? 2 : 0; + if (filePathCopy[i] == '/') { - return false; + ++i; } - if (f_mkdir(location.c_str()) != FR_OK) + + size_t limit = filePathCopy.strlen(); + while (limit != 0 && filePath[limit - 1] == '/') { - reprap.GetPlatform().MessageF(ErrorMessage, "Failed to create directory %s\n", location.c_str()); - return false; + --limit; + } + while (i < limit) + { + if (filePathCopy[i] == '/') + { + filePathCopy[i] = 0; + if (!MassStorage::DirectoryExists(filePathCopy.GetRef()) && f_mkdir(filePathCopy.c_str()) != FR_OK) + { + reprap.GetPlatform().MessageF(ErrorMessage, "Failed to create folder %s in path %s\n", filePathCopy.c_str(), filePath); + return false; + } + filePathCopy[i] = '/'; + } + ++i; } return true; } +// Create a new directory bool MassStorage::MakeDirectory(const char *directory) noexcept { + if (!EnsurePath(directory)) + { + return false; + } if (f_mkdir(directory) != FR_OK) { - reprap.GetPlatform().MessageF(ErrorMessage, "Failed to create directory %s\n", directory); + reprap.GetPlatform().MessageF(ErrorMessage, "Failed to create folder %s\n", directory); return false; } return true; @@ -405,11 +429,15 @@ bool MassStorage::Rename(const char *oldFilename, const char *newFilename) noexc { if (newFilename[0] >= '0' && newFilename[0] <= '9' && newFilename[1] == ':') { - // Workaround for DWC 1.13 which send a volume specification at the start of the new path. + // Workaround for DWC 1.13 which sends a volume specification at the start of the new path. // f_rename can't handle this, so skip past the volume specification. // We are assuming that the user isn't really trying to rename across volumes. This is a safe assumption when the client is DWC. newFilename += 2; } + if (!EnsurePath(newFilename)) + { + return false; + } if (f_rename(oldFilename, newFilename) != FR_OK) { reprap.GetPlatform().MessageF(ErrorMessage, "Failed to rename file or directory %s to %s\n", oldFilename, newFilename); diff --git a/src/Storage/MassStorage.h b/src/Storage/MassStorage.h index c18438f2..603b871c 100644 --- a/src/Storage/MassStorage.h +++ b/src/Storage/MassStorage.h @@ -33,7 +33,7 @@ namespace MassStorage bool FindNext(FileInfo &file_info) noexcept; void AbandonFindNext() noexcept; bool Delete(const char* filePath) noexcept; - bool MakeDirectory(const char *parentDir, const char *dirName) noexcept; + bool EnsurePath(const char* filePath) noexcept; bool MakeDirectory(const char *directory) noexcept; bool Rename(const char *oldFilePath, const char *newFilePath) noexcept; bool FileExists(const char *filePath) noexcept; diff --git a/src/Version.h b/src/Version.h index 6028f701..0e8c0874 100644 --- a/src/Version.h +++ b/src/Version.h @@ -10,7 +10,7 @@ #ifndef VERSION -# define MAIN_VERSION "3.1alpha" +# define MAIN_VERSION "3.1beta1" # ifdef USE_CAN0 # define VERSION_SUFFIX " (CAN0)" # else @@ -20,7 +20,7 @@ #endif #ifndef DATE -# define DATE "2020-01-12b2" +# define DATE "2020-01-12b3" #endif #define AUTHORS "reprappro, dc42, chrishamm, t3p3, dnewman, printm3d" |