From 63fd73f98c731db89b47acfe0fada824f5a924ea Mon Sep 17 00:00:00 2001 From: Joop Schilder Date: Sun, 10 May 2020 23:46:44 +0200 Subject: [PATCH] Initial implementation of instruction set --- bin/app.php | 17 +- src/Automata/DataRegisters.php | 22 +- src/Automata/InstructionSet.php | 319 +++++++++++++++++++- src/Automata/Memory/MemoryController.php | 32 +- src/Automata/Modes/G/DimensionMode.php | 11 - src/Automata/Modes/G/G.php | 24 -- src/Automata/Modes/G/PlaneSelection.php | 11 - src/Automata/Modes/G/RadiusCompensation.php | 11 - src/Automata/Modes/G/TraverseMode.php | 11 - src/Automata/Modes/G/WorkCycle.php | 17 -- src/Automata/Modes/M/CoolantMode.php | 29 -- src/Automata/Modes/M/M.php | 24 -- src/Automata/Modes/M/SpindleMode.php | 26 -- src/Automata/Modes/M/TableClampingMode.php | 11 - src/Automata/{Machine.php => NC.php} | 12 +- src/Program/Block.php | 30 +- src/ProgramLoader.php | 4 +- 17 files changed, 389 insertions(+), 222 deletions(-) delete mode 100644 src/Automata/Modes/G/DimensionMode.php delete mode 100644 src/Automata/Modes/G/G.php delete mode 100644 src/Automata/Modes/G/PlaneSelection.php delete mode 100644 src/Automata/Modes/G/RadiusCompensation.php delete mode 100644 src/Automata/Modes/G/TraverseMode.php delete mode 100644 src/Automata/Modes/G/WorkCycle.php delete mode 100644 src/Automata/Modes/M/CoolantMode.php delete mode 100644 src/Automata/Modes/M/M.php delete mode 100644 src/Automata/Modes/M/SpindleMode.php delete mode 100644 src/Automata/Modes/M/TableClampingMode.php rename src/Automata/{Machine.php => NC.php} (89%) diff --git a/bin/app.php b/bin/app.php index c024861..26fb8dd 100644 --- a/bin/app.php +++ b/bin/app.php @@ -1,16 +1,15 @@ TM->write(new ToolData(1, 5500, 2)); -$machine->TM->write(new ToolData(2, 3000, 61379)); -(new ProgramLoader)->loadPrograms($machine); +$nc = new NC(); +$nc->TM->write(new ToolData(1, 5500, 2)); +$nc->TM->write(new ToolData(2, 3000, 61379)); +(new ProgramLoader)->loadPrograms($nc); + +$nc->loadProgram(9002); +$nc->run(); -$machine->loadProgram(9002); -while ($machine->PPMC->ready()) { - $machine->step(); -} diff --git a/src/Automata/DataRegisters.php b/src/Automata/DataRegisters.php index a59a876..0851a5c 100644 --- a/src/Automata/DataRegisters.php +++ b/src/Automata/DataRegisters.php @@ -16,15 +16,19 @@ class DataRegisters public int $S = 0; // Spindle speed in RPM public int $T = 0; // Tool number public int $H = 0; // Additional functions (unused) - public int $M = 0; // Auxiliary functions public int $E = 0; // Number of repetitions / multiple meanings // Modals - public int $TM = 0; // Traverse (0, 1, 2, 3) - public int $PS = 18; // Plane Selection (18, 19, 20) - public int $RC = 40; // Radius Compensation - public int $DM = 90; // Dimension (90, 91) - public int $WC = 0; // Work Cycle (null, 81, 84, 85, 86) - public int $CM = 8; // Coolant (8, 9) - public int $SM = 5; // Spindle (3, 4, 5) - public int $TC = 10; // Table Clamping (10, 11) + public int $G_TRAVERSE = 0; + public int $G_PLANE_SELECTION = 18; + public int $G_RADIUS_COMPENSATION = 40; + public int $G_DIMENSION_PROGRAMMING = 90; + public int $G_WORKCYCLE = 0; + public int $X_WORKCYCLE = 0; + public int $Y_WORKCYCLE = 0; + public int $Z_WORKCYCLE = 0; + public int $B_WORKCYCLE = 0; + public int $M_PROGRAM = 0; + public int $M_COOLANT = 8; + public int $M_SPINDLE = 5; + public int $M_TABLE_CLAMPING = 10; } diff --git a/src/Automata/InstructionSet.php b/src/Automata/InstructionSet.php index 8b4cef5..2d3495c 100644 --- a/src/Automata/InstructionSet.php +++ b/src/Automata/InstructionSet.php @@ -2,41 +2,330 @@ namespace Automata; +use InvalidArgumentException; use Program\Block; +use RuntimeException; class InstructionSet { - private Machine $machine; - /** @var callable[] */ - private array $map; + private const SPEEDS = [0, 40, 50, 63, 80, 100, 125, 160, 200, 250, 315, 400, 500, 630, 800, 1000, 1250, 1600, 2000]; + + private NC $machine; - public function __construct(Machine $machine) + public function __construct(NC $machine) { $this->machine = $machine; - $this->map = []; } public function apply(Block $block): void { - print("$block\n"); - $words = $block->words; - while ($word = array_shift($words)) { - $method = "{$word}"; - if (!method_exists($this, $method)) { - continue; + system('clear'); + print("\n$block\n\n"); + foreach ($block->words as $word) { + if (method_exists($this, "$word")) { + // There's a method dedicated to handling the full word (eg G22) + $this->{"$word"}($block); + @$block->pop($word->register); + } + if (method_exists($this, $word->register)) { + // There's a method dedicated to handling data for the given register (eg T, S) + $this->{$word->register}($block->pop($word->register)); } - $this->{$method}($block); - break; } + foreach ($block->words as $word) { + // The word value may be put into the machine registers directly + if (property_exists($this->machine->DR, $word->register)) { + $this->machine->DR->{$word->register} = $block->pop($word->register); + } else { + print("WARNING: No method or register for word '{$word}'\n"); + } + } + dump($this->machine->DR); + readline(); + } + + + protected function E(int $value): void + { + print("WARNING: Line repetitions are not implemented yet"); + } + + + protected function T(int $value): void + { + // Triggers an exception if not found, good enough for now. + // Might implement compensations and more explicit tool registers later on + $this->machine->TM->read($value); + $this->machine->DR->T = $value; + } + + + protected function S(int $value): void + { + if (!in_array($value, self::SPEEDS)) { + throw new InvalidArgumentException(sprintf( + "Speed not supported: '$value'. Supported are: \n%s\n", + implode(', ', self::SPEEDS) + )); + } + $this->machine->DR->S = $value; + } + + + protected function G0(Block $block): void + { + $this->machine->DR->G_TRAVERSE = $block->read('G'); + } + + + protected function G1(Block $block): void + { + $this->machine->DR->G_TRAVERSE = $block->read('G'); + } + + + protected function G2(Block $block): void + { + $this->machine->DR->G_TRAVERSE = $block->read('G'); + } + + + protected function G3(Block $block): void + { + $this->machine->DR->G_TRAVERSE = $block->read('G'); + } + + + protected function G4(Block $block): void + { + print("Ignoring dwell setting: {$block->pop('X')}\n"); + } + + + protected function G17(Block $block): void + { + $this->machine->DR->G_PLANE_SELECTION = $block->read('G'); + } + + + protected function G18(Block $block): void + { + $this->machine->DR->G_PLANE_SELECTION = $block->read('G'); + } + + + protected function G19(Block $block): void + { + $this->machine->DR->G_PLANE_SELECTION = $block->read('G'); } protected function G22(Block $block): void { - $number = $block->valueOf('X'); - $this->machine->SPMC->loadProgram($number); + $N = $block->pop('X'); + $this->machine->SPMC->loadProgram($N); $this->machine->AMC = $this->machine->SPMC; } + + + protected function G40(Block $block): void + { + $this->machine->DR->G_RADIUS_COMPENSATION = $block->read('G'); + } + + + protected function G41(Block $block): void + { + $this->machine->DR->G_RADIUS_COMPENSATION = $block->read('G'); + } + + + protected function G42(Block $block): void + { + $this->machine->DR->G_RADIUS_COMPENSATION = $block->read('G'); + } + + + protected function G43(Block $block): void + { + $this->machine->DR->G_RADIUS_COMPENSATION = $block->read('G'); + } + + + protected function G44(Block $block): void + { + $this->machine->DR->G_RADIUS_COMPENSATION = $block->read('G'); + } + + + protected function G79(Block $block): void + { + // Ignore... ?? The action will be executed on set location + if ($this->machine->DR->B_WORKCYCLE === 0) { + throw new RuntimeException('No workcycle prepared!'); + } + } + + + protected function G81(Block $block): void + { + $this->machine->DR->G_WORKCYCLE = $block->read('G'); + $this->getWorkcycleParameters($block); + } + + + protected function G84(Block $block): void + { + $this->machine->DR->G_WORKCYCLE = $block->read('G'); + $this->getWorkcycleParameters($block); + } + + + protected function G85(Block $block): void + { + $this->machine->DR->G_WORKCYCLE = $block->read('G'); + $this->getWorkcycleParameters($block); + } + + + protected function G86(Block $block): void + { + $this->machine->DR->G_WORKCYCLE = $block->read('G'); + $this->getWorkcycleParameters($block); + } + + + private function getWorkcycleParameters(Block $block): void + { + $this->machine->DR->X_WORKCYCLE = $block->has('X') ? $block->pop('X') : 0; + $this->machine->DR->Y_WORKCYCLE = $block->has('Y') ? $block->pop('Y') : 0; + $this->machine->DR->Z_WORKCYCLE = $block->has('Z') ? $block->pop('Z') : 0; + $this->machine->DR->B_WORKCYCLE = $block->has('B') ? $block->pop('B') : 0; + } + + + protected function G90(Block $block): void + { + $this->machine->DR->G_DIMENSION_PROGRAMMING = $block->read('G'); + } + + + protected function G91(Block $block): void + { + $this->machine->DR->G_DIMENSION_PROGRAMMING = $block->read('G'); + } + + + protected function G92(Block $block): void + { + // Incremental + foreach (['X', 'Y', 'Z'] as $R) { + if ($block->has($R)) { + $this->machine->DR->{$R} = -$block->pop($R); + } + } + } + + + protected function G93(Block $block): void + { + // Absolute zero datum shift + foreach (['X', 'Y', 'Z'] as $R) { + if ($block->has($R)) { + $this->machine->DR->{$R} -= $block->pop($R); + } + } + } + + + protected function G98(Block $block): void + { + // Automatic positioning to reference datum point + print("Ignoring automatic positioning to zero datum point\n"); + } + + + protected function M0(Block $block): void + { + $this->machine->DR->M_PROGRAM = 0; + $this->machine->DR->M_SPINDLE = 5; + $this->machine->DR->M_COOLANT = 9; + } + + + protected function M2(Block $block): void + { + $this->machine->DR->M_PROGRAM = 2; + $this->machine->DR->M_SPINDLE = 5; + $this->machine->DR->M_COOLANT = 9; + } + + + protected function M3(Block $block): void + { + $this->machine->DR->M_SPINDLE = 3; + } + + + protected function M4(Block $block): void + { + $this->machine->DR->M_SPINDLE = 4; + } + + + protected function M5(Block $block): void + { + $this->machine->DR->M_SPINDLE = 5; + } + + + protected function M6(Block $block): void + { + $this->machine->DR->M_SPINDLE = 5; + $this->machine->DR->M_COOLANT = 9; + } + + + protected function M8(Block $block): void + { + $this->machine->DR->M_COOLANT = 8; + } + + + protected function M9(Block $block): void + { + $this->machine->DR->M_COOLANT = 9; + } + + + protected function M10(Block $block): void + { + $this->machine->DR->M_TABLE_CLAMPING = 10; + } + + + protected function M11(Block $block): void + { + $this->machine->DR->M_TABLE_CLAMPING = 11; + } + + + protected function M30(Block $block): void + { + $this->machine->DR->M_SPINDLE = 5; + $this->machine->DR->M_COOLANT = 9; + $N = $this->machine->PPMC->N; + $this->machine->PPMC->reset(); + $this->machine->SPMC->reset(); + $this->machine->PPMC->loadProgram($N); + $this->machine->AMC = $this->machine->PPMC; + } + + + protected function M67(Block $block): void + { + throw new RuntimeException('[Enter new tool information without machine stop] is not implemented'); + } } diff --git a/src/Automata/Memory/MemoryController.php b/src/Automata/Memory/MemoryController.php index 7e44363..f99213e 100644 --- a/src/Automata/Memory/MemoryController.php +++ b/src/Automata/Memory/MemoryController.php @@ -10,14 +10,16 @@ use RuntimeException; class MemoryController implements Countable { private ProgramMemory $memory; + public ?int $N = null; /** @var Block[]|null */ - private ?array $blocks; + private ?array $blockBuffer; + private int $index; public function __construct(ProgramMemory $memory) { $this->memory = $memory; - $this->blocks = null; + $this->blockBuffer = null; } @@ -27,39 +29,53 @@ class MemoryController implements Countable if (!$program) { throw new InvalidArgumentException("Program N{$N} not found"); } - $this->blocks = $program->getIterator()->getArrayCopy(); + $this->N = $N; + $this->blockBuffer = $program->getIterator()->getArrayCopy(); + $this->index = 0; } public function reset(): void { - $this->blocks = null; + $this->N = null; + $this->blockBuffer = null; + $this->index = 0; } public function count() { - return count($this->blocks); + return count($this->blockBuffer) - $this->index; + } + + + public function previous(): ?Block + { + $this->guardNoProgramLoaded(); + $block = $this->blockBuffer[$this->index--]; + + return $block ? clone $block : null; } public function next(): ?Block { $this->guardNoProgramLoaded(); + $block = $this->blockBuffer[$this->index++]; - return array_shift($this->blocks); + return $block ? clone $block : null; } public function ready(): bool { - return !empty($this->blocks); + return $this->count() > 0; } private function guardNoProgramLoaded(): void { - if (is_null($this->blocks)) { + if (is_null($this->blockBuffer)) { throw new RuntimeException('No program loaded in memory'); } } diff --git a/src/Automata/Modes/G/DimensionMode.php b/src/Automata/Modes/G/DimensionMode.php deleted file mode 100644 index 3556e3c..0000000 --- a/src/Automata/Modes/G/DimensionMode.php +++ /dev/null @@ -1,11 +0,0 @@ -G = $G; - } - - - public final function apply(int $G): void - { - if ($this->supports($G)) { - $this->G = $G; - } - } - - - public abstract function supports(int $G): bool; -} diff --git a/src/Automata/Modes/G/PlaneSelection.php b/src/Automata/Modes/G/PlaneSelection.php deleted file mode 100644 index 02cb3a2..0000000 --- a/src/Automata/Modes/G/PlaneSelection.php +++ /dev/null @@ -1,11 +0,0 @@ -supports($M)) { - return; - } - if (in_array($M, [0, 2, 6, 30])) { - $this->M = 9; - - return; - } - - // 8 or 9 - $this->M = $M; - } - -} diff --git a/src/Automata/Modes/M/M.php b/src/Automata/Modes/M/M.php deleted file mode 100644 index bee8211..0000000 --- a/src/Automata/Modes/M/M.php +++ /dev/null @@ -1,24 +0,0 @@ -M = $M; - } - - - public function apply(int $M): void - { - if ($this->supports($M)) { - $this->M = $M; - } - } - - - public abstract function supports(int $M): bool; -} diff --git a/src/Automata/Modes/M/SpindleMode.php b/src/Automata/Modes/M/SpindleMode.php deleted file mode 100644 index 95bdb04..0000000 --- a/src/Automata/Modes/M/SpindleMode.php +++ /dev/null @@ -1,26 +0,0 @@ -supports($M)) { - return; - } - if (in_array($M, [0, 2, 6, 30])) { - $this->M = 5; - - return; - } - // 3, 4 or 5 - $this->M = $M; - } -} diff --git a/src/Automata/Modes/M/TableClampingMode.php b/src/Automata/Modes/M/TableClampingMode.php deleted file mode 100644 index 93e087d..0000000 --- a/src/Automata/Modes/M/TableClampingMode.php +++ /dev/null @@ -1,11 +0,0 @@ -PPMC->ready()) { + $this->step(); + } + } + + public function reset(): void { $this->PPMC->reset(); diff --git a/src/Program/Block.php b/src/Program/Block.php index db9c5ac..d6cc3a0 100644 --- a/src/Program/Block.php +++ b/src/Program/Block.php @@ -24,10 +24,36 @@ class Block } - public function valueOf(string $register): int + public function has(string $register): bool { foreach ($this->words as $word) { if ($word->register === $register) { + return true; + } + } + + return false; + } + + + public function read(string $register): int + { + foreach ($this->words as $index => $word) { + if ($word->register === $register) { + return $word->value; + } + } + + throw new RuntimeException("No word in block for register '$register'"); + } + + + public function pop(string $register): int + { + foreach ($this->words as $index => $word) { + if ($word->register === $register) { + unset($this->words[$index]); + return $word->value; } } @@ -38,7 +64,7 @@ class Block public function __toString() { - $buffer = "$this->N\t"; + $buffer = "N$this->N\t\t"; foreach ($this->words as $word) { $buffer .= "$word\t"; } diff --git a/src/ProgramLoader.php b/src/ProgramLoader.php index d615479..73aaa64 100644 --- a/src/ProgramLoader.php +++ b/src/ProgramLoader.php @@ -1,11 +1,11 @@