Refactor, add extensive README.md, add future planning
This commit is contained in:
30
src/Loader/ProgramLoader.php
Normal file
30
src/Loader/ProgramLoader.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Loader;
|
||||
|
||||
use Machine\Memory\ProgramMemory;
|
||||
use Program\Builder\ProgramBuilder;
|
||||
use Program\Parser\WordParser;
|
||||
|
||||
class ProgramLoader
|
||||
{
|
||||
private WordParser $parser;
|
||||
private ProgramBuilder $builder;
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->parser = new WordParser();
|
||||
$this->builder = new ProgramBuilder();
|
||||
}
|
||||
|
||||
|
||||
public function load(ProgramMemory $memory, string $globPattern): void
|
||||
{
|
||||
foreach (glob($globPattern) as $file) {
|
||||
$words = $this->parser->parseFile($file);
|
||||
$program = $this->builder->build($words);
|
||||
$memory->write($program);
|
||||
}
|
||||
}
|
||||
}
|
||||
26
src/Loader/ToolLoader.php
Normal file
26
src/Loader/ToolLoader.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace Loader;
|
||||
|
||||
use Machine\Memory\ToolMemory;
|
||||
use Tool\Parser\ToolParser;
|
||||
|
||||
class ToolLoader
|
||||
{
|
||||
private ToolParser $parser;
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->parser = new ToolParser();
|
||||
}
|
||||
|
||||
|
||||
public function load(ToolMemory $toolMemory, string $yamlFile): void
|
||||
{
|
||||
$tools = $this->parser->parseFile($yamlFile);
|
||||
foreach ($tools as $toolData) {
|
||||
$toolMemory->write($toolData);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace Automata;
|
||||
namespace Machine;
|
||||
|
||||
use Automata\Memory\MemoryController;
|
||||
use Automata\Memory\ProgramMemory;
|
||||
use Automata\Memory\ToolMemory;
|
||||
use Machine\Memory\DataRegisters;
|
||||
use Machine\Memory\MemoryController;
|
||||
use Machine\Memory\ProgramMemory;
|
||||
use Machine\Memory\ToolMemory;
|
||||
|
||||
class NC
|
||||
class CNC6600
|
||||
{
|
||||
public DataRegisters $DR;
|
||||
public InstructionSet $IS;
|
||||
@@ -15,7 +16,7 @@ class NC
|
||||
public ProgramMemory $PPM;
|
||||
public MemoryController $SPMC;
|
||||
public MemoryController $PPMC;
|
||||
public MemoryController $AMC;
|
||||
public MemoryController $_AMC;
|
||||
|
||||
|
||||
public function __construct()
|
||||
@@ -27,28 +28,28 @@ class NC
|
||||
$this->PPM = new ProgramMemory();
|
||||
$this->SPMC = new MemoryController($this->SPM);
|
||||
$this->PPMC = new MemoryController($this->PPM);
|
||||
$this->AMC = $this->PPMC;
|
||||
$this->_AMC = $this->PPMC;
|
||||
}
|
||||
|
||||
|
||||
public function loadProgram(int $N): void
|
||||
{
|
||||
$this->PPMC->loadProgram($N);
|
||||
$this->AMC = $this->PPMC;
|
||||
$this->_AMC = $this->PPMC;
|
||||
}
|
||||
|
||||
|
||||
public function step(): void
|
||||
{
|
||||
if ($this->AMC === $this->SPMC && count($this->AMC) === 0) {
|
||||
$this->AMC = $this->PPMC;
|
||||
if ($this->_AMC === $this->SPMC && count($this->_AMC) === 0) {
|
||||
$this->_AMC = $this->PPMC;
|
||||
}
|
||||
$block = $this->AMC->next();
|
||||
$block = $this->_AMC->next();
|
||||
$this->IS->apply($block);
|
||||
}
|
||||
|
||||
|
||||
public function run(): void
|
||||
public function execute(): void
|
||||
{
|
||||
while ($this->PPMC->ready()) {
|
||||
$this->step();
|
||||
@@ -1,20 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Automata;
|
||||
|
||||
use Program\Word;
|
||||
namespace Machine;
|
||||
|
||||
class Definitions
|
||||
{
|
||||
private array $G = [
|
||||
public const G = [
|
||||
// traverse mode
|
||||
0 => 'Rapid traverse', // Default
|
||||
1 => 'Linear interpolation',
|
||||
2 => 'Circular interpolation (CW)',
|
||||
3 => 'Circular interpolation (CCW)',
|
||||
0 => 'Rapid traverse', // Default
|
||||
1 => 'Linear interpolation',
|
||||
2 => 'Circular interpolation (CW)',
|
||||
3 => 'Circular interpolation (CCW)',
|
||||
|
||||
// quest-ce-que c'est?
|
||||
4 => 'Dwell',
|
||||
4 => 'Dwell',
|
||||
|
||||
// plane selection mode
|
||||
17 => 'Plane selection (XY-plane)', // Default
|
||||
@@ -57,17 +55,18 @@ class Definitions
|
||||
// reference to zero
|
||||
98 => 'Automatic positioning to reference datum point',
|
||||
];
|
||||
private array $M = [
|
||||
0 => 'Programmed stop (Sets M5 and M9)',
|
||||
2 => 'End of program (Sets M5 and M9)',
|
||||
3 => 'Spindle start CW (CCW in G18)',
|
||||
4 => 'Spindle start CCW (CW in G18)',
|
||||
5 => 'Spindle stop',
|
||||
6 => 'Tool change (Sets M5 and M9)',
|
||||
|
||||
public const M = [
|
||||
0 => 'Programmed stop (Sets M5 and M9)',
|
||||
2 => 'End of program (Sets M5 and M9)',
|
||||
3 => 'Spindle start CW (CCW in G18)',
|
||||
4 => 'Spindle start CCW (CW in G18)',
|
||||
5 => 'Spindle stop',
|
||||
6 => 'Tool change (Sets M5 and M9)',
|
||||
|
||||
// coolant control
|
||||
8 => 'Coolant on',
|
||||
9 => 'Coolant off',
|
||||
8 => 'Coolant on',
|
||||
9 => 'Coolant off',
|
||||
|
||||
// table clamping (unsupported)
|
||||
10 => 'Table clamping - close',
|
||||
@@ -76,19 +75,4 @@ class Definitions
|
||||
30 => 'End of program with skip back to start (Sets M5 and M9)',
|
||||
67 => 'Enter new tool information without machine stop',
|
||||
];
|
||||
private array $S = [
|
||||
0, 40, 50, 63, 80, 100, 125, 160, 200, 250,
|
||||
315, 400, 500, 630, 800, 1000, 1250, 1600, 2000,
|
||||
];
|
||||
|
||||
public function hasPredefinedValue(Word $word): bool
|
||||
{
|
||||
return in_array($word->register, ['G', 'M']);
|
||||
}
|
||||
|
||||
|
||||
public function translatePredefinedValue(Word $word): ?string
|
||||
{
|
||||
return @$this->{$word->register}[$word->value];
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Automata;
|
||||
namespace Machine;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use Program\Block;
|
||||
@@ -10,12 +10,12 @@ class InstructionSet
|
||||
{
|
||||
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;
|
||||
private CNC6600 $CNC6600;
|
||||
|
||||
|
||||
public function __construct(NC $machine)
|
||||
public function __construct(CNC6600 $CNC6600)
|
||||
{
|
||||
$this->machine = $machine;
|
||||
$this->CNC6600 = $CNC6600;
|
||||
}
|
||||
|
||||
|
||||
@@ -36,13 +36,13 @@ class InstructionSet
|
||||
}
|
||||
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);
|
||||
if (property_exists($this->CNC6600->DR, $word->register)) {
|
||||
$this->CNC6600->DR->{$word->register} = $block->pop($word->register);
|
||||
} else {
|
||||
print("WARNING: No method or register for word '{$word}'\n");
|
||||
}
|
||||
}
|
||||
dump($this->machine->DR);
|
||||
dump($this->CNC6600->DR);
|
||||
readline();
|
||||
}
|
||||
|
||||
@@ -57,8 +57,8 @@ class InstructionSet
|
||||
{
|
||||
// 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;
|
||||
$this->CNC6600->TM->read($value);
|
||||
$this->CNC6600->DR->T = $value;
|
||||
}
|
||||
|
||||
|
||||
@@ -70,31 +70,31 @@ class InstructionSet
|
||||
implode(', ', self::SPEEDS)
|
||||
));
|
||||
}
|
||||
$this->machine->DR->S = $value;
|
||||
$this->CNC6600->DR->S = $value;
|
||||
}
|
||||
|
||||
|
||||
protected function G0(Block $block): void
|
||||
{
|
||||
$this->machine->DR->G_TRAVERSE = $block->read('G');
|
||||
$this->CNC6600->DR->G_TRAVERSE = $block->read('G');
|
||||
}
|
||||
|
||||
|
||||
protected function G1(Block $block): void
|
||||
{
|
||||
$this->machine->DR->G_TRAVERSE = $block->read('G');
|
||||
$this->CNC6600->DR->G_TRAVERSE = $block->read('G');
|
||||
}
|
||||
|
||||
|
||||
protected function G2(Block $block): void
|
||||
{
|
||||
$this->machine->DR->G_TRAVERSE = $block->read('G');
|
||||
$this->CNC6600->DR->G_TRAVERSE = $block->read('G');
|
||||
}
|
||||
|
||||
|
||||
protected function G3(Block $block): void
|
||||
{
|
||||
$this->machine->DR->G_TRAVERSE = $block->read('G');
|
||||
$this->CNC6600->DR->G_TRAVERSE = $block->read('G');
|
||||
}
|
||||
|
||||
|
||||
@@ -106,115 +106,115 @@ class InstructionSet
|
||||
|
||||
protected function G17(Block $block): void
|
||||
{
|
||||
$this->machine->DR->G_PLANE_SELECTION = $block->read('G');
|
||||
$this->CNC6600->DR->G_PLANE_SELECTION = $block->read('G');
|
||||
}
|
||||
|
||||
|
||||
protected function G18(Block $block): void
|
||||
{
|
||||
$this->machine->DR->G_PLANE_SELECTION = $block->read('G');
|
||||
$this->CNC6600->DR->G_PLANE_SELECTION = $block->read('G');
|
||||
}
|
||||
|
||||
|
||||
protected function G19(Block $block): void
|
||||
{
|
||||
$this->machine->DR->G_PLANE_SELECTION = $block->read('G');
|
||||
$this->CNC6600->DR->G_PLANE_SELECTION = $block->read('G');
|
||||
}
|
||||
|
||||
|
||||
protected function G22(Block $block): void
|
||||
{
|
||||
$N = $block->pop('X');
|
||||
$this->machine->SPMC->loadProgram($N);
|
||||
$this->machine->AMC = $this->machine->SPMC;
|
||||
$this->CNC6600->SPMC->loadProgram($N);
|
||||
$this->CNC6600->_AMC = $this->CNC6600->SPMC;
|
||||
}
|
||||
|
||||
|
||||
protected function G40(Block $block): void
|
||||
{
|
||||
$this->machine->DR->G_RADIUS_COMPENSATION = $block->read('G');
|
||||
$this->CNC6600->DR->G_RADIUS_COMPENSATION = $block->read('G');
|
||||
}
|
||||
|
||||
|
||||
protected function G41(Block $block): void
|
||||
{
|
||||
$this->machine->DR->G_RADIUS_COMPENSATION = $block->read('G');
|
||||
$this->CNC6600->DR->G_RADIUS_COMPENSATION = $block->read('G');
|
||||
}
|
||||
|
||||
|
||||
protected function G42(Block $block): void
|
||||
{
|
||||
$this->machine->DR->G_RADIUS_COMPENSATION = $block->read('G');
|
||||
$this->CNC6600->DR->G_RADIUS_COMPENSATION = $block->read('G');
|
||||
}
|
||||
|
||||
|
||||
protected function G43(Block $block): void
|
||||
{
|
||||
$this->machine->DR->G_RADIUS_COMPENSATION = $block->read('G');
|
||||
$this->CNC6600->DR->G_RADIUS_COMPENSATION = $block->read('G');
|
||||
}
|
||||
|
||||
|
||||
protected function G44(Block $block): void
|
||||
{
|
||||
$this->machine->DR->G_RADIUS_COMPENSATION = $block->read('G');
|
||||
$this->CNC6600->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) {
|
||||
if ($this->CNC6600->DR->B_WORKCYCLE === 0) {
|
||||
throw new RuntimeException('No workcycle prepared!');
|
||||
}
|
||||
// TODO verify active workcycle, execute it?
|
||||
}
|
||||
|
||||
|
||||
protected function G81(Block $block): void
|
||||
{
|
||||
$this->machine->DR->G_WORKCYCLE = $block->read('G');
|
||||
$this->CNC6600->DR->G_WORKCYCLE = $block->read('G');
|
||||
$this->getWorkcycleParameters($block);
|
||||
}
|
||||
|
||||
|
||||
protected function G84(Block $block): void
|
||||
{
|
||||
$this->machine->DR->G_WORKCYCLE = $block->read('G');
|
||||
$this->CNC6600->DR->G_WORKCYCLE = $block->read('G');
|
||||
$this->getWorkcycleParameters($block);
|
||||
}
|
||||
|
||||
|
||||
protected function G85(Block $block): void
|
||||
{
|
||||
$this->machine->DR->G_WORKCYCLE = $block->read('G');
|
||||
$this->CNC6600->DR->G_WORKCYCLE = $block->read('G');
|
||||
$this->getWorkcycleParameters($block);
|
||||
}
|
||||
|
||||
|
||||
protected function G86(Block $block): void
|
||||
{
|
||||
$this->machine->DR->G_WORKCYCLE = $block->read('G');
|
||||
$this->CNC6600->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;
|
||||
$this->CNC6600->DR->X_WORKCYCLE = $block->has('X') ? $block->pop('X') : 0;
|
||||
$this->CNC6600->DR->Y_WORKCYCLE = $block->has('Y') ? $block->pop('Y') : 0;
|
||||
$this->CNC6600->DR->Z_WORKCYCLE = $block->has('Z') ? $block->pop('Z') : 0;
|
||||
$this->CNC6600->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');
|
||||
$this->CNC6600->DR->G_DIMENSION_PROGRAMMING = $block->read('G');
|
||||
}
|
||||
|
||||
|
||||
protected function G91(Block $block): void
|
||||
{
|
||||
$this->machine->DR->G_DIMENSION_PROGRAMMING = $block->read('G');
|
||||
$this->CNC6600->DR->G_DIMENSION_PROGRAMMING = $block->read('G');
|
||||
}
|
||||
|
||||
|
||||
@@ -223,7 +223,7 @@ class InstructionSet
|
||||
// Incremental
|
||||
foreach (['X', 'Y', 'Z'] as $R) {
|
||||
if ($block->has($R)) {
|
||||
$this->machine->DR->{$R} = -$block->pop($R);
|
||||
$this->CNC6600->DR->{$R} = -$block->pop($R);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -234,7 +234,7 @@ class InstructionSet
|
||||
// Absolute zero datum shift
|
||||
foreach (['X', 'Y', 'Z'] as $R) {
|
||||
if ($block->has($R)) {
|
||||
$this->machine->DR->{$R} -= $block->pop($R);
|
||||
$this->CNC6600->DR->{$R} -= $block->pop($R);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -249,78 +249,78 @@ class InstructionSet
|
||||
|
||||
protected function M0(Block $block): void
|
||||
{
|
||||
$this->machine->DR->M_PROGRAM = 0;
|
||||
$this->machine->DR->M_SPINDLE = 5;
|
||||
$this->machine->DR->M_COOLANT = 9;
|
||||
$this->CNC6600->DR->M_PROGRAM = $block->read('M');
|
||||
$this->CNC6600->DR->M_SPINDLE = 5;
|
||||
$this->CNC6600->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;
|
||||
$this->CNC6600->DR->M_PROGRAM = $block->read('M');
|
||||
$this->CNC6600->DR->M_SPINDLE = 5;
|
||||
$this->CNC6600->DR->M_COOLANT = 9;
|
||||
}
|
||||
|
||||
|
||||
protected function M3(Block $block): void
|
||||
{
|
||||
$this->machine->DR->M_SPINDLE = 3;
|
||||
$this->CNC6600->DR->M_SPINDLE = $block->read('M');
|
||||
}
|
||||
|
||||
|
||||
protected function M4(Block $block): void
|
||||
{
|
||||
$this->machine->DR->M_SPINDLE = 4;
|
||||
$this->CNC6600->DR->M_SPINDLE = $block->read('M');
|
||||
}
|
||||
|
||||
|
||||
protected function M5(Block $block): void
|
||||
{
|
||||
$this->machine->DR->M_SPINDLE = 5;
|
||||
$this->CNC6600->DR->M_SPINDLE = $block->read('M');
|
||||
}
|
||||
|
||||
|
||||
protected function M6(Block $block): void
|
||||
{
|
||||
$this->machine->DR->M_SPINDLE = 5;
|
||||
$this->machine->DR->M_COOLANT = 9;
|
||||
$this->CNC6600->DR->M_SPINDLE = 5;
|
||||
$this->CNC6600->DR->M_COOLANT = 9;
|
||||
}
|
||||
|
||||
|
||||
protected function M8(Block $block): void
|
||||
{
|
||||
$this->machine->DR->M_COOLANT = 8;
|
||||
$this->CNC6600->DR->M_COOLANT = $block->read('M');
|
||||
}
|
||||
|
||||
|
||||
protected function M9(Block $block): void
|
||||
{
|
||||
$this->machine->DR->M_COOLANT = 9;
|
||||
$this->CNC6600->DR->M_COOLANT = $block->read('M');
|
||||
}
|
||||
|
||||
|
||||
protected function M10(Block $block): void
|
||||
{
|
||||
$this->machine->DR->M_TABLE_CLAMPING = 10;
|
||||
$this->CNC6600->DR->M_TABLE_CLAMPING = $block->read('M');
|
||||
}
|
||||
|
||||
|
||||
protected function M11(Block $block): void
|
||||
{
|
||||
$this->machine->DR->M_TABLE_CLAMPING = 11;
|
||||
$this->CNC6600->DR->M_TABLE_CLAMPING = $block->read('M');
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
$this->CNC6600->DR->M_SPINDLE = 5;
|
||||
$this->CNC6600->DR->M_COOLANT = 9;
|
||||
$N = $this->CNC6600->PPMC->N;
|
||||
$this->CNC6600->PPMC->reset();
|
||||
$this->CNC6600->SPMC->reset();
|
||||
$this->CNC6600->PPMC->loadProgram($N);
|
||||
$this->CNC6600->_AMC = $this->CNC6600->PPMC;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Automata;
|
||||
namespace Machine\Memory;
|
||||
|
||||
class DataRegisters
|
||||
{
|
||||
@@ -17,7 +17,7 @@ class DataRegisters
|
||||
public int $T = 0; // Tool number
|
||||
public int $H = 0; // Additional functions (unused)
|
||||
public int $E = 0; // Number of repetitions / multiple meanings
|
||||
// Modals
|
||||
// modals
|
||||
public int $G_TRAVERSE = 0;
|
||||
public int $G_PLANE_SELECTION = 18;
|
||||
public int $G_RADIUS_COMPENSATION = 40;
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Automata\Memory;
|
||||
namespace Machine\Memory;
|
||||
|
||||
use Countable;
|
||||
use InvalidArgumentException;
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Automata\Memory;
|
||||
namespace Machine\Memory;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use Program\Program;
|
||||
@@ -1,24 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Automata\Memory;
|
||||
namespace Machine\Memory;
|
||||
|
||||
use Automata\ToolData;
|
||||
use InvalidArgumentException;
|
||||
use Tool\Tool;
|
||||
|
||||
class ToolMemory
|
||||
{
|
||||
/** @var ToolData[] */
|
||||
/** @var Tool[] */
|
||||
private array $memory = [];
|
||||
|
||||
|
||||
public function write(ToolData $tool): void
|
||||
public function write(Tool $tool): void
|
||||
{
|
||||
$this->guardInvalidToolNumber($tool->T);
|
||||
$this->memory[$tool->T] = $tool;
|
||||
}
|
||||
|
||||
|
||||
public function read(int $T): ?ToolData
|
||||
public function read(int $T): ?Tool
|
||||
{
|
||||
return @$this->memory[$T];
|
||||
}
|
||||
42
src/Program/Builder/ProgramBuilder.php
Normal file
42
src/Program/Builder/ProgramBuilder.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace Program\Builder;
|
||||
|
||||
use Program\Block;
|
||||
use Program\Program;
|
||||
use Program\Word;
|
||||
use RuntimeException;
|
||||
|
||||
class ProgramBuilder
|
||||
{
|
||||
/**
|
||||
* @param Word[] $words
|
||||
* @return Program
|
||||
*/
|
||||
public function build(array $words): Program
|
||||
{
|
||||
$firstWord = array_shift($words);
|
||||
if (!preg_match('/^N9\d\d\d$/i', $firstWord)) {
|
||||
throw new RuntimeException('Expected program number (N9xxx), got ' . $firstWord);
|
||||
}
|
||||
|
||||
$program = new Program($firstWord->value);
|
||||
|
||||
$blockBuffer = null;
|
||||
while ($word = array_shift($words)) {
|
||||
if ($word->register === 'N') {
|
||||
if (!is_null($blockBuffer)) {
|
||||
$program->addBlock($blockBuffer);
|
||||
}
|
||||
$blockBuffer = new Block($word->value);
|
||||
continue;
|
||||
}
|
||||
$blockBuffer->addWord($word);
|
||||
}
|
||||
if (!is_null($blockBuffer)) {
|
||||
$program->addBlock($blockBuffer);
|
||||
}
|
||||
|
||||
return $program;
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Program;
|
||||
namespace Program\Parser;
|
||||
|
||||
use RuntimeException;
|
||||
use Program\Word;
|
||||
|
||||
class ProgramParser
|
||||
class WordParser
|
||||
{
|
||||
public function parseFile(string $filename): Program
|
||||
/**
|
||||
* @param string $filename
|
||||
* @return Word[]
|
||||
*/
|
||||
public function parseFile(string $filename): array
|
||||
{
|
||||
$lines = explode(PHP_EOL, file_get_contents($filename));
|
||||
$lines = array_filter($lines);
|
||||
@@ -15,9 +19,12 @@ class ProgramParser
|
||||
}
|
||||
|
||||
|
||||
public function parse(array $lines): Program
|
||||
/**
|
||||
* @param string[] $lines
|
||||
* @return Word[]
|
||||
*/
|
||||
public function parse(array $lines): array
|
||||
{
|
||||
// In the first parsing stage, all words are parsed from the file.
|
||||
/** @var Word[] $words */
|
||||
$words = [];
|
||||
foreach ($lines as $line) {
|
||||
@@ -34,7 +41,6 @@ class ProgramParser
|
||||
$words[] = new Word($wordBuffer['register'], $wordBuffer['value']);
|
||||
$wordBuffer = [];
|
||||
$state = 'NONE';
|
||||
continue;
|
||||
}
|
||||
|
||||
if ('NONE' === $state && ctype_alpha($character)) {
|
||||
@@ -43,7 +49,7 @@ class ProgramParser
|
||||
continue;
|
||||
}
|
||||
|
||||
if (stripos($line, 'EOF') !== false) {
|
||||
if (strpos($line, 'EOF') !== false) {
|
||||
break 2; // End of program reached
|
||||
}
|
||||
|
||||
@@ -53,28 +59,6 @@ class ProgramParser
|
||||
}
|
||||
}
|
||||
|
||||
// In the second stage, the words are ordered by N numbers
|
||||
// and shaped into a program
|
||||
$firstWord = array_shift($words);
|
||||
if (!preg_match('/^N9\d\d\d$/i', $firstWord)) {
|
||||
throw new RuntimeException('Expected program number, got ' . $firstWord);
|
||||
}
|
||||
$program = new Program($firstWord->value);
|
||||
$lineBuffer = null;
|
||||
while ($word = array_shift($words)) {
|
||||
if ($word->register === 'N') {
|
||||
if (!is_null($lineBuffer)) {
|
||||
$program->addBlock($lineBuffer);
|
||||
}
|
||||
$lineBuffer = new Block($word->value);
|
||||
continue;
|
||||
}
|
||||
$lineBuffer->addWord($word);
|
||||
}
|
||||
if (!is_null($lineBuffer)) {
|
||||
$program->addBlock($lineBuffer);
|
||||
}
|
||||
|
||||
return $program;
|
||||
return $words;
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
<?php
|
||||
|
||||
use Automata\NC;
|
||||
use Program\ProgramParser;
|
||||
|
||||
class ProgramLoader
|
||||
{
|
||||
public function loadPrograms(NC $machine): void
|
||||
{
|
||||
$parser = new ProgramParser();
|
||||
|
||||
foreach (glob(__DIR__ . '/../programs/part/*') as $partProgramFile) {
|
||||
$partProgram = $parser->parseFile($partProgramFile);
|
||||
$machine->PPM->write($partProgram);
|
||||
}
|
||||
|
||||
foreach (glob(__DIR__ . '/../programs/sub/*') as $subProgramFile) {
|
||||
$subProgram = $parser->parseFile($subProgramFile);
|
||||
$machine->SPM->write($subProgram);
|
||||
}
|
||||
}
|
||||
}
|
||||
49
src/State/Persister.php
Normal file
49
src/State/Persister.php
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace State;
|
||||
|
||||
use Machine\CNC6600;
|
||||
use RuntimeException;
|
||||
|
||||
class Persister
|
||||
{
|
||||
private const WORKING_DIR = __DIR__ . '/../../var';
|
||||
|
||||
|
||||
public function persist(string $identifier, CNC6600 $CNC6600): void
|
||||
{
|
||||
$filename = $this->getFilename($identifier);
|
||||
$state = serialize($CNC6600);
|
||||
$state = gzcompress($state, 6);
|
||||
@file_put_contents($filename, $state);
|
||||
}
|
||||
|
||||
|
||||
public function load(string $identifier): CNC6600
|
||||
{
|
||||
$filename = $this->getFilename($identifier);
|
||||
$this->guardStateFileDoesNotExist($filename);
|
||||
$state = file_get_contents($filename);
|
||||
$state = gzuncompress($state);
|
||||
|
||||
return unserialize($state);
|
||||
}
|
||||
|
||||
|
||||
public function getFilename(string $identifier): string
|
||||
{
|
||||
$identifier = md5("machine_state_$identifier");
|
||||
|
||||
return self::WORKING_DIR . "/$identifier";
|
||||
}
|
||||
|
||||
|
||||
private function guardStateFileDoesNotExist(string $filename): void
|
||||
{
|
||||
if (!file_exists($filename)) {
|
||||
throw new RuntimeException('State not found');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
39
src/Tool/Parser/ToolParser.php
Normal file
39
src/Tool/Parser/ToolParser.php
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace Tool\Parser;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
use Tool\Tool;
|
||||
|
||||
class ToolParser
|
||||
{
|
||||
/**
|
||||
* @param string $yamlFile
|
||||
* @return Tool[]
|
||||
*/
|
||||
public function parseFile(string $yamlFile): array
|
||||
{
|
||||
$data = @Yaml::parseFile($yamlFile);
|
||||
if (is_null($data)) {
|
||||
throw new InvalidArgumentException('Yaml file not found: ' . $yamlFile);
|
||||
}
|
||||
return $this->parse($data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @return Tool[]
|
||||
*/
|
||||
public function parse(array $data): array
|
||||
{
|
||||
$tools = [];
|
||||
foreach ($data as $T => $tool) {
|
||||
$T = (int)filter_var($T, FILTER_SANITIZE_NUMBER_INT);
|
||||
$tools[] = new Tool($T, $tool['X'], $tool['Z']);
|
||||
}
|
||||
|
||||
return $tools;
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Automata;
|
||||
namespace Tool;
|
||||
|
||||
class ToolData
|
||||
class Tool
|
||||
{
|
||||
public int $T; // Tool number
|
||||
public int $X; // Radius in 0.001 mm
|
||||
Reference in New Issue
Block a user