Add Memory Controllers for SP and PP, add Instruction Set

This commit is contained in:
Joop Schilder 2020-05-10 21:17:12 +02:00
parent ee896160b3
commit fda22052b8
17 changed files with 189 additions and 141 deletions

View File

@ -1,14 +1,16 @@
<?php <?php
use Automata\Machine; use Automata\Machine;
use Automata\Tool; use Automata\ToolData;
require_once __DIR__ . '/../vendor/autoload.php'; require_once __DIR__ . '/../vendor/autoload.php';
$machine = new Machine(); $machine = new Machine();
$machine->toolMemory->save(new Tool(1, 5500, 2)); $machine->TM->write(new ToolData(1, 5500, 2));
$machine->toolMemory->save(new Tool(2, 3000, 61379)); $machine->TM->write(new ToolData(2, 3000, 61379));
(new ProgramLoader)->loadPrograms($machine); (new ProgramLoader)->loadPrograms($machine);
$machine->loadProgram(9002); $machine->loadProgram(9002);
$machine->start(); while ($machine->PPMC->ready()) {
$machine->step();
}

BIN
ref/block_structure.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 KiB

BIN
ref/program_code_1.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 KiB

BIN
ref/program_code_2.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

BIN
ref/program_code_3.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB

BIN
ref/programmable_words.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

BIN
ref/spindle_speeds.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

View File

@ -2,7 +2,7 @@
namespace Automata; namespace Automata;
class Registers class DataRegisters
{ {
public int $B = 0; // Traverse information public int $B = 0; // Traverse information
public int $X = 0; // Dimension along X-axis public int $X = 0; // Dimension along X-axis
@ -17,5 +17,14 @@ class Registers
public int $T = 0; // Tool number public int $T = 0; // Tool number
public int $H = 0; // Additional functions (unused) public int $H = 0; // Additional functions (unused)
public int $M = 0; // Auxiliary functions public int $M = 0; // Auxiliary functions
public int $E = 0; // Number of repetitions / multiple meanins 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)
} }

View File

@ -0,0 +1,41 @@
<?php
namespace Automata;
use Program\Block;
class InstructionSet
{
private Machine $machine;
/** @var callable<Machine>[] */
private array $map;
public function __construct(Machine $machine)
{
$this->machine = $machine;
$this->map = [];
}
public function apply(Block $block): void
{
$words = $block->words;
while ($word = array_shift($words)) {
$method = "{$word}";
if (!method_exists($this, $method)) {
continue;
}
$this->{$method}($block);
break;
}
}
public function G22(Block $block): void
{
$number = $block->valueOf('X');
$this->machine->SPMC->loadProgram($number);
$this->machine->AMC = $this->machine->SPMC;
}
}

View File

@ -2,79 +2,57 @@
namespace Automata; namespace Automata;
use Automata\Storage\ProgramMemory; use Automata\Memory\MemoryController;
use Automata\Storage\ToolMemory; use Automata\Memory\ProgramMemory;
use Program\Block; use Automata\Memory\ToolMemory;
use Program\Program;
use Program\Word;
use RuntimeException;
use SplStack;
/*
* executing a program:
* - load parts program
* - execute line by line
* - load sub program
* - execute lines from subprogram
* - back to parts program
*/
class Machine class Machine
{ {
public State $state; public DataRegisters $DR;
public ToolMemory $toolMemory; public InstructionSet $IS;
public ProgramMemory $subProgramMemory; public ToolMemory $TM;
public ProgramMemory $partProgramMemory; public ProgramMemory $SPM;
/** @var SplStack|Program[] */ public ProgramMemory $PPM;
private SplStack $programStack; public MemoryController $SPMC;
private ?Program $activeProgram = null; public MemoryController $PPMC;
private Definitions $definitions; public ?MemoryController $AMC;
public function __construct() public function __construct()
{ {
$this->state = new State(); $this->DR = new DataRegisters();
$this->definitions = new Definitions(); $this->IS = new InstructionSet($this);
$this->toolMemory = new ToolMemory(); $this->TM = new ToolMemory();
$this->subProgramMemory = new ProgramMemory(); $this->SPM = new ProgramMemory();
$this->partProgramMemory = new ProgramMemory(); $this->PPM = new ProgramMemory();
$this->programStack = new SplStack(); $this->SPMC = new MemoryController($this->SPM);
$this->PPMC = new MemoryController($this->PPM);
$this->AMC = $this->PPMC;
} }
public function loadProgram(int $N): void public function loadProgram(int $N): void
{ {
$this->programStack = new SplStack(); $this->PPMC->loadProgram($N);
$program = $this->partProgramMemory->read($N); $this->AMC = $this->PPMC;
$this->programStack->push($program);
} }
public function start(): void public function step(): void
{ {
$this->activeProgram = $this->programStack->pop(); $block = $this->AMC->next();
if (is_null($this->activeProgram)) { if (is_null($block) && $this->AMC === $this->SPMC) {
throw new RuntimeException('No program loaded'); // SP ended, back to PP
} $this->AMC = $this->PPMC;
foreach ($this->activeProgram as $block) { $block = $this->AMC->next();
$this->executeBlock($block);
}
}
private function executeBlock(Block $block): void
{
/** @var Word[] $words */
$words = $block->words;
while ($word = array_shift($words)) {
$this->state->apply($word);
system('clear');
dump($this->state);
readline();
} }
$this->IS->apply($block);
} }
public function reset(): void public function reset(): void
{ {
$this->activeProgram = null; $this->PPMC->reset();
$this->SPMC->reset();
} }
} }

View File

@ -0,0 +1,66 @@
<?php
namespace Automata\Memory;
use Countable;
use InvalidArgumentException;
use Program\Block;
use RuntimeException;
class MemoryController implements Countable
{
private ProgramMemory $memory;
/** @var Block[]|null */
private ?array $blocks;
public function __construct(ProgramMemory $memory)
{
$this->memory = $memory;
$this->blocks = null;
}
public function loadProgram(int $N): void
{
$program = $this->memory->read($N);
if (!$program) {
throw new InvalidArgumentException("Program N{$N} not found");
}
$this->blocks = $program->getIterator()->getArrayCopy();
}
public function reset(): void
{
$this->blocks = null;
}
public function count()
{
return count($this->blocks);
}
public function next(): ?Block
{
$this->guardNoProgramLoaded();
return array_shift($this->blocks);
}
public function ready(): bool
{
return !empty($this->blocks);
}
private function guardNoProgramLoaded(): void
{
if (is_null($this->blocks)) {
throw new RuntimeException('No program loaded in memory');
}
}
}

View File

@ -1,6 +1,6 @@
<?php <?php
namespace Automata\Storage; namespace Automata\Memory;
use InvalidArgumentException; use InvalidArgumentException;
use Program\Program; use Program\Program;
@ -11,7 +11,7 @@ class ProgramMemory
private array $memory = []; private array $memory = [];
public function save(Program $program): void public function write(Program $program): void
{ {
$this->guardInvalidProgramNumber($program->N); $this->guardInvalidProgramNumber($program->N);
$this->memory[$program->N] = $program; $this->memory[$program->N] = $program;
@ -30,5 +30,4 @@ class ProgramMemory
throw new InvalidArgumentException('Program number must be in range 9001 - 9998'); throw new InvalidArgumentException('Program number must be in range 9001 - 9998');
} }
} }
} }

View File

@ -1,24 +1,24 @@
<?php <?php
namespace Automata\Storage; namespace Automata\Memory;
use Automata\Tool; use Automata\ToolData;
use InvalidArgumentException; use InvalidArgumentException;
class ToolMemory class ToolMemory
{ {
/** @var Tool[] */ /** @var ToolData[] */
private array $memory = []; private array $memory = [];
public function save(Tool $tool): void public function write(ToolData $tool): void
{ {
$this->guardInvalidToolNumber($tool->T); $this->guardInvalidToolNumber($tool->T);
$this->memory[$tool->T] = $tool; $this->memory[$tool->T] = $tool;
} }
public function read(int $T): ?Tool public function read(int $T): ?ToolData
{ {
return @$this->memory[$T]; return @$this->memory[$T];
} }
@ -30,5 +30,4 @@ class ToolMemory
throw new InvalidArgumentException('Tool number must be in range 1 - 64'); throw new InvalidArgumentException('Tool number must be in range 1 - 64');
} }
} }
} }

View File

@ -1,71 +0,0 @@
<?php
namespace Automata;
use Automata\Modes\G\DimensionMode;
use Automata\Modes\G\PlaneSelection;
use Automata\Modes\G\RadiusCompensation;
use Automata\Modes\G\TraverseMode;
use Automata\Modes\G\WorkCycle;
use Automata\Modes\M\CoolantMode;
use Automata\Modes\M\SpindleMode;
use Automata\Modes\M\TableClampingMode;
use Program\Word;
class State
{
public Registers $registers;
// G
public TraverseMode $traverseMode;
public PlaneSelection $planeSelection;
public RadiusCompensation $radiusCompensation;
public DimensionMode $dimensionMode;
public WorkCycle $workCycleSelection;
// M
public CoolantMode $coolantMode;
public SpindleMode $spindleMode;
public TableClampingMode $tableClamping;
public function __construct()
{
$this->registers = new Registers();
$this->traverseMode = new TraverseMode(0);
$this->planeSelection = new PlaneSelection(17);
$this->radiusCompensation = new RadiusCompensation(40);
$this->dimensionMode = new DimensionMode(90);
$this->workCycleSelection = new WorkCycle(0);
$this->coolantMode = new CoolantMode(9);
$this->spindleMode = new SpindleMode(5);
$this->tableClamping = new TableClampingMode(10);
}
public function apply(Word $word): void
{
if ($word->register === 'G') {
$this->traverseMode->apply($word->value);
$this->planeSelection->apply($word->value);
$this->radiusCompensation->apply($word->value);
$this->dimensionMode->apply($word->value);
$this->workCycleSelection->apply($word->value);
// TODO Handle other G commands
return;
}
if ($word->register === 'M') {
$this->coolantMode->apply($word->value);
$this->spindleMode->apply($word->value);
$this->tableClamping->apply($word->value);
// TODO Handle other M commands
return;
}
if (property_exists($this->registers, $word->register)) {
$this->registers->{$word->register} = $word->value;
}
}
}

View File

@ -2,7 +2,7 @@
namespace Automata; namespace Automata;
class Tool class ToolData
{ {
public int $T; // Tool number public int $T; // Tool number
public int $X; // Radius in 0.001 mm public int $X; // Radius in 0.001 mm

View File

@ -2,6 +2,8 @@
namespace Program; namespace Program;
use RuntimeException;
class Block class Block
{ {
public string $N; public string $N;
@ -20,4 +22,27 @@ class Block
{ {
$this->words[] = $word; $this->words[] = $word;
} }
public function valueOf(string $register): int
{
foreach ($this->words as $word) {
if ($word->register === $register) {
return $word->value;
}
}
throw new RuntimeException("No word in block for register '$register'");
}
public function __toString()
{
$buffer = "$this->N\t";
foreach ($this->words as $word) {
$buffer .= "$word\t";
}
return $buffer;
}
} }

View File

@ -11,12 +11,12 @@ class ProgramLoader
foreach (glob(__DIR__ . '/../programs/part/*') as $partProgramFile) { foreach (glob(__DIR__ . '/../programs/part/*') as $partProgramFile) {
$partProgram = $parser->parseFile($partProgramFile); $partProgram = $parser->parseFile($partProgramFile);
$machine->partProgramMemory->save($partProgram); $machine->PPM->write($partProgram);
} }
foreach (glob(__DIR__ . '/../programs/sub/*') as $subProgramFile) { foreach (glob(__DIR__ . '/../programs/sub/*') as $subProgramFile) {
$subProgram = $parser->parseFile($subProgramFile); $subProgram = $parser->parseFile($subProgramFile);
$machine->subProgramMemory->save($subProgram); $machine->SPM->write($subProgram);
} }
} }
} }