Refactor, add extensive README.md, add future planning
This commit is contained in:
parent
63fd73f98c
commit
9002db40aa
4
.gitignore
vendored
4
.gitignore
vendored
@ -1,6 +1,8 @@
|
|||||||
/.idea/
|
/.idea/
|
||||||
/vendor/
|
/vendor/
|
||||||
/programs/*/*
|
/config/part_programs/*
|
||||||
|
/config/sub_programs/*
|
||||||
|
/config/tools.yaml
|
||||||
!.gitignore
|
!.gitignore
|
||||||
|
|
||||||
|
|
||||||
|
123
README.md
123
README.md
@ -1,13 +1,122 @@
|
|||||||
### Philips CNC6600 NC System Interpreter
|
# Philips CNC6600 NC System Interpreter
|
||||||
|
|
||||||
|
## Description
|
||||||
|
|
||||||
This is an interpreter for programs written for the MAHO MH-C 700.
|
This is an interpreter for programs written for the MAHO MH-C 700.
|
||||||
It basically creates a state-machine that represents the Philips NC system.
|
It basically creates a state-machine that represents the Philips CNC6600 NC system.
|
||||||
|
|
||||||
Written in PHP, because why not?
|
## Requirements
|
||||||
|
|
||||||
#### Usage
|
- `PHP7.4`
|
||||||
Put parts programs (plain text) in `/programs/part`, put subpart programs (plain text) in `/programs/sub`.
|
- `composer` ([get it here](https://getcomposer.org/download/))
|
||||||
|
|
||||||
To see what's working so far; run
|
## Usage
|
||||||
|
|
||||||
|
### Installation
|
||||||
```bash
|
```bash
|
||||||
php bin/app.php
|
## install dependencies and autoloader
|
||||||
|
$ composer install
|
||||||
|
|
||||||
|
## copy tool configuration data and edit it
|
||||||
|
$ cp config/tools.yaml.dist config/tools.yaml
|
||||||
|
$ nano config/tools.yaml
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Tool data
|
||||||
|
|
||||||
|
Tools are loaded from `config/tools.yaml`.
|
||||||
|
A tool configuration example would be:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# config/tools.yaml
|
||||||
|
|
||||||
|
T1:
|
||||||
|
X: 5500 # radius in 0.001mm
|
||||||
|
Z: 2500 # length in 0.001mm
|
||||||
|
|
||||||
|
T2:
|
||||||
|
X: 3000
|
||||||
|
Z: 61379
|
||||||
|
```
|
||||||
|
|
||||||
|
### Programs
|
||||||
|
|
||||||
|
The application loads programs from `config/part_programs` and `config/sub_programs`.
|
||||||
|
The programs are stored in the memory of the machine.
|
||||||
|
|
||||||
|
- A file containing a program _may_ have any name (a program is identified by its program number)
|
||||||
|
- A program _must_ have a program number as the first block
|
||||||
|
- A program is terminated either by a comment containing 'EOF' (case sensitive) or by a physical EOF
|
||||||
|
- A comment is denoted by `;`, anything after this character on the same line is ignored
|
||||||
|
|
||||||
|
An example of a program would be:
|
||||||
|
|
||||||
|
```text
|
||||||
|
; config/part_programs/some_name
|
||||||
|
|
||||||
|
;; Some program that drills two holes
|
||||||
|
N9045
|
||||||
|
|
||||||
|
; and yes, comments are fully supported,
|
||||||
|
; or rather, detected and ignored by the parser
|
||||||
|
N10 G18 T2 M6
|
||||||
|
N20 G1 F1500 S1250
|
||||||
|
N30 M4
|
||||||
|
|
||||||
|
; prepare and execute drill cycle
|
||||||
|
N40 G81 Y2000 Z-7000 B48000
|
||||||
|
|
||||||
|
; the parser also understands this
|
||||||
|
N50G79X-20000Y0Z-15000
|
||||||
|
|
||||||
|
; hell, you may even put multiple blocks on one line:
|
||||||
|
; N50G0X2N60G1Y20
|
||||||
|
; though it's good practice to align your program:
|
||||||
|
N60 G79 X20000 Y0 Z15000
|
||||||
|
|
||||||
|
N70 G0 Y150000 ; safely retract
|
||||||
|
N80 M2 ; turn off spindle, no return
|
||||||
|
|
||||||
|
;; EOF
|
||||||
|
```
|
||||||
|
|
||||||
|
Executing program `9045` from the example:
|
||||||
|
```bash
|
||||||
|
## execute the example program
|
||||||
|
$ bin/run_program 9045
|
||||||
|
|
||||||
|
## or
|
||||||
|
$ php bin/run_program 9045
|
||||||
|
```
|
||||||
|
|
||||||
|
- calling a subprogram (`G22 X9...`) is supported
|
||||||
|
- line repetitions (`E0302`) are _not_ supported yet
|
||||||
|
- parameter programming is _not_ supported yet
|
||||||
|
|
||||||
|
### Machine State
|
||||||
|
|
||||||
|
The machine state can be saved to a file to continue later on by using `State\Persister`.
|
||||||
|
|
||||||
|
```php
|
||||||
|
use Machine\CNC6600;
|
||||||
|
use State\Persister;
|
||||||
|
|
||||||
|
$CNC6600 = new CNC6600();
|
||||||
|
|
||||||
|
// Do some things with the machine...
|
||||||
|
|
||||||
|
// Saving the machine state
|
||||||
|
$persister = new Persister();
|
||||||
|
$persister->persist('some_state_identifier', $CNC6600);
|
||||||
|
|
||||||
|
// Retrieving the saved state
|
||||||
|
$CNC6600 = $persister->load('some_state_identifier');
|
||||||
|
```
|
||||||
|
|
||||||
|
## Future
|
||||||
|
|
||||||
|
- Tool path simulation
|
||||||
|
- Manual Data Input (_MDI_) mode
|
||||||
|
- Proper tool compensation
|
||||||
|
- Line repetitions
|
||||||
|
- Parameter programming
|
||||||
|
15
bin/app.php
15
bin/app.php
@ -1,15 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
use Automata\NC;
|
|
||||||
use Automata\ToolData;
|
|
||||||
|
|
||||||
require_once __DIR__ . '/../vendor/autoload.php';
|
|
||||||
|
|
||||||
$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();
|
|
||||||
|
|
18
bin/bootstrap.php
Normal file
18
bin/bootstrap.php
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Loader\ProgramLoader;
|
||||||
|
use Loader\ToolLoader;
|
||||||
|
use Machine\CNC6600;
|
||||||
|
|
||||||
|
require_once __DIR__ . '/../vendor/autoload.php';
|
||||||
|
|
||||||
|
$CNC6600 = new CNC6600();
|
||||||
|
|
||||||
|
$programLoader = new ProgramLoader();
|
||||||
|
$programLoader->load($CNC6600->PPM, __DIR__ . '/../config/part_programs/*');
|
||||||
|
$programLoader->load($CNC6600->SPM, __DIR__ . '/../config/sub_programs/*');
|
||||||
|
|
||||||
|
$toolLoader = new ToolLoader();
|
||||||
|
$toolLoader->load($CNC6600->TM, __DIR__ . '/../config/tools.yaml');
|
||||||
|
|
||||||
|
return $CNC6600;
|
13
bin/run_program
Executable file
13
bin/run_program
Executable file
@ -0,0 +1,13 @@
|
|||||||
|
#!/usr/bin/env php7.4
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require_once __DIR__ . '/../vendor/autoload.php';
|
||||||
|
|
||||||
|
if (!isset($argv[1])) {
|
||||||
|
print("Usage: bin/run_program <program number>\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
$CNC6600 = require_once __DIR__ . '/bootstrap.php';
|
||||||
|
$CNC6600->loadProgram($argv[1]);
|
||||||
|
$CNC6600->execute();
|
@ -15,7 +15,9 @@
|
|||||||
"ext-ctype": "*",
|
"ext-ctype": "*",
|
||||||
"ext-json": "*",
|
"ext-json": "*",
|
||||||
"ext-readline": "*",
|
"ext-readline": "*",
|
||||||
|
"ext-zlib": "*",
|
||||||
"symfony/var-dumper": "^5.0",
|
"symfony/var-dumper": "^5.0",
|
||||||
"illuminate/support": "^7.10"
|
"illuminate/support": "^7.10",
|
||||||
|
"symfony/yaml": "^5.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
229
composer.lock
generated
229
composer.lock
generated
@ -4,37 +4,41 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "1e9e0fcf3c3cc215c6ab1cd71d6bb903",
|
"content-hash": "add2ead9d9a8adb0a79475f10b111470",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "doctrine/inflector",
|
"name": "doctrine/inflector",
|
||||||
"version": "1.3.1",
|
"version": "2.0.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/doctrine/inflector.git",
|
"url": "https://github.com/doctrine/inflector.git",
|
||||||
"reference": "ec3a55242203ffa6a4b27c58176da97ff0a7aec1"
|
"reference": "18b995743e7ec8b15fd6efc594f0fa3de4bfe6d7"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/doctrine/inflector/zipball/ec3a55242203ffa6a4b27c58176da97ff0a7aec1",
|
"url": "https://api.github.com/repos/doctrine/inflector/zipball/18b995743e7ec8b15fd6efc594f0fa3de4bfe6d7",
|
||||||
"reference": "ec3a55242203ffa6a4b27c58176da97ff0a7aec1",
|
"reference": "18b995743e7ec8b15fd6efc594f0fa3de4bfe6d7",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": "^7.1"
|
"php": "^7.2"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"phpunit/phpunit": "^6.2"
|
"doctrine/coding-standard": "^7.0",
|
||||||
|
"phpstan/phpstan": "^0.11",
|
||||||
|
"phpstan/phpstan-phpunit": "^0.11",
|
||||||
|
"phpstan/phpstan-strict-rules": "^0.11",
|
||||||
|
"phpunit/phpunit": "^7.0 || ^8.0 || ^9.0"
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-master": "1.3.x-dev"
|
"dev-master": "2.0.x-dev"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"Doctrine\\Common\\Inflector\\": "lib/Doctrine/Common/Inflector"
|
"Doctrine\\Inflector\\": "lib/Doctrine/Inflector"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
@ -63,19 +67,39 @@
|
|||||||
"email": "schmittjoh@gmail.com"
|
"email": "schmittjoh@gmail.com"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Common String Manipulations with regard to casing and singular/plural rules.",
|
"description": "PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.",
|
||||||
"homepage": "http://www.doctrine-project.org",
|
"homepage": "https://www.doctrine-project.org/projects/inflector.html",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"inflection",
|
"inflection",
|
||||||
"pluralize",
|
"inflector",
|
||||||
"singularize",
|
"lowercase",
|
||||||
"string"
|
"manipulation",
|
||||||
|
"php",
|
||||||
|
"plural",
|
||||||
|
"singular",
|
||||||
|
"strings",
|
||||||
|
"uppercase",
|
||||||
|
"words"
|
||||||
],
|
],
|
||||||
"time": "2019-10-30T19:59:35+00:00"
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://www.doctrine-project.org/sponsorship.html",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://www.patreon.com/phpdoctrine",
|
||||||
|
"type": "patreon"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/doctrine%2Finflector",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2020-05-11T11:25:59+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "illuminate/contracts",
|
"name": "illuminate/contracts",
|
||||||
"version": "v7.10.3",
|
"version": "v7.11.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/illuminate/contracts.git",
|
"url": "https://github.com/illuminate/contracts.git",
|
||||||
@ -119,20 +143,20 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "illuminate/support",
|
"name": "illuminate/support",
|
||||||
"version": "v7.10.3",
|
"version": "v7.11.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/illuminate/support.git",
|
"url": "https://github.com/illuminate/support.git",
|
||||||
"reference": "cd11fa914c52a2249c48cde08d03a871597e8781"
|
"reference": "5458d0d0048f185b3d4a911e5d21d2bb2fb336ca"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/illuminate/support/zipball/cd11fa914c52a2249c48cde08d03a871597e8781",
|
"url": "https://api.github.com/repos/illuminate/support/zipball/5458d0d0048f185b3d4a911e5d21d2bb2fb336ca",
|
||||||
"reference": "cd11fa914c52a2249c48cde08d03a871597e8781",
|
"reference": "5458d0d0048f185b3d4a911e5d21d2bb2fb336ca",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"doctrine/inflector": "^1.1",
|
"doctrine/inflector": "^1.4|^2.0",
|
||||||
"ext-json": "*",
|
"ext-json": "*",
|
||||||
"ext-mbstring": "*",
|
"ext-mbstring": "*",
|
||||||
"illuminate/contracts": "^7.0",
|
"illuminate/contracts": "^7.0",
|
||||||
@ -177,7 +201,7 @@
|
|||||||
],
|
],
|
||||||
"description": "The Illuminate Support package.",
|
"description": "The Illuminate Support package.",
|
||||||
"homepage": "https://laravel.com",
|
"homepage": "https://laravel.com",
|
||||||
"time": "2020-05-05T16:21:56+00:00"
|
"time": "2020-05-12T14:31:35+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "nesbot/carbon",
|
"name": "nesbot/carbon",
|
||||||
@ -359,17 +383,89 @@
|
|||||||
"time": "2017-10-23T01:57:42+00:00"
|
"time": "2017-10-23T01:57:42+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/polyfill-mbstring",
|
"name": "symfony/polyfill-ctype",
|
||||||
"version": "v1.15.0",
|
"version": "v1.17.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/polyfill-mbstring.git",
|
"url": "https://github.com/symfony/polyfill-ctype.git",
|
||||||
"reference": "81ffd3a9c6d707be22e3012b827de1c9775fc5ac"
|
"reference": "e94c8b1bbe2bc77507a1056cdb06451c75b427f9"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/81ffd3a9c6d707be22e3012b827de1c9775fc5ac",
|
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/e94c8b1bbe2bc77507a1056cdb06451c75b427f9",
|
||||||
"reference": "81ffd3a9c6d707be22e3012b827de1c9775fc5ac",
|
"reference": "e94c8b1bbe2bc77507a1056cdb06451c75b427f9",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=5.3.3"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"ext-ctype": "For best performance"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "1.17-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Symfony\\Polyfill\\Ctype\\": ""
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"bootstrap.php"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Gert de Pagter",
|
||||||
|
"email": "BackEndTea@gmail.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Symfony Community",
|
||||||
|
"homepage": "https://symfony.com/contributors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Symfony polyfill for ctype functions",
|
||||||
|
"homepage": "https://symfony.com",
|
||||||
|
"keywords": [
|
||||||
|
"compatibility",
|
||||||
|
"ctype",
|
||||||
|
"polyfill",
|
||||||
|
"portable"
|
||||||
|
],
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://symfony.com/sponsor",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/fabpot",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2020-05-12T16:14:59+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/polyfill-mbstring",
|
||||||
|
"version": "v1.17.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/symfony/polyfill-mbstring.git",
|
||||||
|
"reference": "fa79b11539418b02fc5e1897267673ba2c19419c"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fa79b11539418b02fc5e1897267673ba2c19419c",
|
||||||
|
"reference": "fa79b11539418b02fc5e1897267673ba2c19419c",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -381,7 +477,7 @@
|
|||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-master": "1.15-dev"
|
"dev-master": "1.17-dev"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
@ -429,7 +525,7 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2020-03-09T19:04:49+00:00"
|
"time": "2020-05-12T16:47:27+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/translation",
|
"name": "symfony/translation",
|
||||||
@ -668,6 +764,79 @@
|
|||||||
],
|
],
|
||||||
"time": "2020-04-12T16:45:47+00:00"
|
"time": "2020-04-12T16:45:47+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/yaml",
|
||||||
|
"version": "v5.0.8",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/symfony/yaml.git",
|
||||||
|
"reference": "482fb4e710e5af3e0e78015f19aa716ad953392f"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/symfony/yaml/zipball/482fb4e710e5af3e0e78015f19aa716ad953392f",
|
||||||
|
"reference": "482fb4e710e5af3e0e78015f19aa716ad953392f",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": "^7.2.5",
|
||||||
|
"symfony/polyfill-ctype": "~1.8"
|
||||||
|
},
|
||||||
|
"conflict": {
|
||||||
|
"symfony/console": "<4.4"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"symfony/console": "^4.4|^5.0"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"symfony/console": "For validating YAML files using the lint command"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "5.0-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Symfony\\Component\\Yaml\\": ""
|
||||||
|
},
|
||||||
|
"exclude-from-classmap": [
|
||||||
|
"/Tests/"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Fabien Potencier",
|
||||||
|
"email": "fabien@symfony.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Symfony Community",
|
||||||
|
"homepage": "https://symfony.com/contributors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Symfony Yaml Component",
|
||||||
|
"homepage": "https://symfony.com",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://symfony.com/sponsor",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/fabpot",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2020-04-28T17:58:55+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "voku/portable-ascii",
|
"name": "voku/portable-ascii",
|
||||||
"version": "1.4.10",
|
"version": "1.4.10",
|
||||||
|
9
config/tools.yaml.dist
Normal file
9
config/tools.yaml.dist
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# config/tools.yaml
|
||||||
|
|
||||||
|
#T<num>:
|
||||||
|
# X: <radius in 0.001mm>
|
||||||
|
# Z: <length in 0.001mm>
|
||||||
|
|
||||||
|
#T<num>:
|
||||||
|
# X: <radius in 0.001mm>
|
||||||
|
# Z: <length in 0.001mm>
|
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
|
<?php
|
||||||
|
|
||||||
namespace Automata;
|
namespace Machine;
|
||||||
|
|
||||||
use Automata\Memory\MemoryController;
|
use Machine\Memory\DataRegisters;
|
||||||
use Automata\Memory\ProgramMemory;
|
use Machine\Memory\MemoryController;
|
||||||
use Automata\Memory\ToolMemory;
|
use Machine\Memory\ProgramMemory;
|
||||||
|
use Machine\Memory\ToolMemory;
|
||||||
|
|
||||||
class NC
|
class CNC6600
|
||||||
{
|
{
|
||||||
public DataRegisters $DR;
|
public DataRegisters $DR;
|
||||||
public InstructionSet $IS;
|
public InstructionSet $IS;
|
||||||
@ -15,7 +16,7 @@ class NC
|
|||||||
public ProgramMemory $PPM;
|
public ProgramMemory $PPM;
|
||||||
public MemoryController $SPMC;
|
public MemoryController $SPMC;
|
||||||
public MemoryController $PPMC;
|
public MemoryController $PPMC;
|
||||||
public MemoryController $AMC;
|
public MemoryController $_AMC;
|
||||||
|
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
@ -27,28 +28,28 @@ class NC
|
|||||||
$this->PPM = new ProgramMemory();
|
$this->PPM = new ProgramMemory();
|
||||||
$this->SPMC = new MemoryController($this->SPM);
|
$this->SPMC = new MemoryController($this->SPM);
|
||||||
$this->PPMC = new MemoryController($this->PPM);
|
$this->PPMC = new MemoryController($this->PPM);
|
||||||
$this->AMC = $this->PPMC;
|
$this->_AMC = $this->PPMC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function loadProgram(int $N): void
|
public function loadProgram(int $N): void
|
||||||
{
|
{
|
||||||
$this->PPMC->loadProgram($N);
|
$this->PPMC->loadProgram($N);
|
||||||
$this->AMC = $this->PPMC;
|
$this->_AMC = $this->PPMC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function step(): void
|
public function step(): void
|
||||||
{
|
{
|
||||||
if ($this->AMC === $this->SPMC && count($this->AMC) === 0) {
|
if ($this->_AMC === $this->SPMC && count($this->_AMC) === 0) {
|
||||||
$this->AMC = $this->PPMC;
|
$this->_AMC = $this->PPMC;
|
||||||
}
|
}
|
||||||
$block = $this->AMC->next();
|
$block = $this->_AMC->next();
|
||||||
$this->IS->apply($block);
|
$this->IS->apply($block);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function run(): void
|
public function execute(): void
|
||||||
{
|
{
|
||||||
while ($this->PPMC->ready()) {
|
while ($this->PPMC->ready()) {
|
||||||
$this->step();
|
$this->step();
|
@ -1,12 +1,10 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Automata;
|
namespace Machine;
|
||||||
|
|
||||||
use Program\Word;
|
|
||||||
|
|
||||||
class Definitions
|
class Definitions
|
||||||
{
|
{
|
||||||
private array $G = [
|
public const G = [
|
||||||
// traverse mode
|
// traverse mode
|
||||||
0 => 'Rapid traverse', // Default
|
0 => 'Rapid traverse', // Default
|
||||||
1 => 'Linear interpolation',
|
1 => 'Linear interpolation',
|
||||||
@ -57,7 +55,8 @@ class Definitions
|
|||||||
// reference to zero
|
// reference to zero
|
||||||
98 => 'Automatic positioning to reference datum point',
|
98 => 'Automatic positioning to reference datum point',
|
||||||
];
|
];
|
||||||
private array $M = [
|
|
||||||
|
public const M = [
|
||||||
0 => 'Programmed stop (Sets M5 and M9)',
|
0 => 'Programmed stop (Sets M5 and M9)',
|
||||||
2 => 'End of program (Sets M5 and M9)',
|
2 => 'End of program (Sets M5 and M9)',
|
||||||
3 => 'Spindle start CW (CCW in G18)',
|
3 => 'Spindle start CW (CCW in G18)',
|
||||||
@ -76,19 +75,4 @@ class Definitions
|
|||||||
30 => 'End of program with skip back to start (Sets M5 and M9)',
|
30 => 'End of program with skip back to start (Sets M5 and M9)',
|
||||||
67 => 'Enter new tool information without machine stop',
|
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
|
<?php
|
||||||
|
|
||||||
namespace Automata;
|
namespace Machine;
|
||||||
|
|
||||||
use InvalidArgumentException;
|
use InvalidArgumentException;
|
||||||
use Program\Block;
|
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 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) {
|
foreach ($block->words as $word) {
|
||||||
// The word value may be put into the machine registers directly
|
// The word value may be put into the machine registers directly
|
||||||
if (property_exists($this->machine->DR, $word->register)) {
|
if (property_exists($this->CNC6600->DR, $word->register)) {
|
||||||
$this->machine->DR->{$word->register} = $block->pop($word->register);
|
$this->CNC6600->DR->{$word->register} = $block->pop($word->register);
|
||||||
} else {
|
} else {
|
||||||
print("WARNING: No method or register for word '{$word}'\n");
|
print("WARNING: No method or register for word '{$word}'\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dump($this->machine->DR);
|
dump($this->CNC6600->DR);
|
||||||
readline();
|
readline();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,8 +57,8 @@ class InstructionSet
|
|||||||
{
|
{
|
||||||
// Triggers an exception if not found, good enough for now.
|
// Triggers an exception if not found, good enough for now.
|
||||||
// Might implement compensations and more explicit tool registers later on
|
// Might implement compensations and more explicit tool registers later on
|
||||||
$this->machine->TM->read($value);
|
$this->CNC6600->TM->read($value);
|
||||||
$this->machine->DR->T = $value;
|
$this->CNC6600->DR->T = $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -70,31 +70,31 @@ class InstructionSet
|
|||||||
implode(', ', self::SPEEDS)
|
implode(', ', self::SPEEDS)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
$this->machine->DR->S = $value;
|
$this->CNC6600->DR->S = $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected function G0(Block $block): void
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
protected function G22(Block $block): void
|
||||||
{
|
{
|
||||||
$N = $block->pop('X');
|
$N = $block->pop('X');
|
||||||
$this->machine->SPMC->loadProgram($N);
|
$this->CNC6600->SPMC->loadProgram($N);
|
||||||
$this->machine->AMC = $this->machine->SPMC;
|
$this->CNC6600->_AMC = $this->CNC6600->SPMC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected function G40(Block $block): void
|
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
|
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
|
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
|
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
|
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
|
protected function G79(Block $block): void
|
||||||
{
|
{
|
||||||
// Ignore... ?? The action will be executed on set location
|
if ($this->CNC6600->DR->B_WORKCYCLE === 0) {
|
||||||
if ($this->machine->DR->B_WORKCYCLE === 0) {
|
|
||||||
throw new RuntimeException('No workcycle prepared!');
|
throw new RuntimeException('No workcycle prepared!');
|
||||||
}
|
}
|
||||||
|
// TODO verify active workcycle, execute it?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected function G81(Block $block): void
|
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);
|
$this->getWorkcycleParameters($block);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected function G84(Block $block): void
|
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);
|
$this->getWorkcycleParameters($block);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected function G85(Block $block): void
|
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);
|
$this->getWorkcycleParameters($block);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected function G86(Block $block): void
|
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);
|
$this->getWorkcycleParameters($block);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private function getWorkcycleParameters(Block $block): void
|
private function getWorkcycleParameters(Block $block): void
|
||||||
{
|
{
|
||||||
$this->machine->DR->X_WORKCYCLE = $block->has('X') ? $block->pop('X') : 0;
|
$this->CNC6600->DR->X_WORKCYCLE = $block->has('X') ? $block->pop('X') : 0;
|
||||||
$this->machine->DR->Y_WORKCYCLE = $block->has('Y') ? $block->pop('Y') : 0;
|
$this->CNC6600->DR->Y_WORKCYCLE = $block->has('Y') ? $block->pop('Y') : 0;
|
||||||
$this->machine->DR->Z_WORKCYCLE = $block->has('Z') ? $block->pop('Z') : 0;
|
$this->CNC6600->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->B_WORKCYCLE = $block->has('B') ? $block->pop('B') : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected function G90(Block $block): void
|
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
|
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
|
// Incremental
|
||||||
foreach (['X', 'Y', 'Z'] as $R) {
|
foreach (['X', 'Y', 'Z'] as $R) {
|
||||||
if ($block->has($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
|
// Absolute zero datum shift
|
||||||
foreach (['X', 'Y', 'Z'] as $R) {
|
foreach (['X', 'Y', 'Z'] as $R) {
|
||||||
if ($block->has($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
|
protected function M0(Block $block): void
|
||||||
{
|
{
|
||||||
$this->machine->DR->M_PROGRAM = 0;
|
$this->CNC6600->DR->M_PROGRAM = $block->read('M');
|
||||||
$this->machine->DR->M_SPINDLE = 5;
|
$this->CNC6600->DR->M_SPINDLE = 5;
|
||||||
$this->machine->DR->M_COOLANT = 9;
|
$this->CNC6600->DR->M_COOLANT = 9;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected function M2(Block $block): void
|
protected function M2(Block $block): void
|
||||||
{
|
{
|
||||||
$this->machine->DR->M_PROGRAM = 2;
|
$this->CNC6600->DR->M_PROGRAM = $block->read('M');
|
||||||
$this->machine->DR->M_SPINDLE = 5;
|
$this->CNC6600->DR->M_SPINDLE = 5;
|
||||||
$this->machine->DR->M_COOLANT = 9;
|
$this->CNC6600->DR->M_COOLANT = 9;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected function M3(Block $block): void
|
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
|
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
|
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
|
protected function M6(Block $block): void
|
||||||
{
|
{
|
||||||
$this->machine->DR->M_SPINDLE = 5;
|
$this->CNC6600->DR->M_SPINDLE = 5;
|
||||||
$this->machine->DR->M_COOLANT = 9;
|
$this->CNC6600->DR->M_COOLANT = 9;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected function M8(Block $block): void
|
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
|
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
|
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
|
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
|
protected function M30(Block $block): void
|
||||||
{
|
{
|
||||||
$this->machine->DR->M_SPINDLE = 5;
|
$this->CNC6600->DR->M_SPINDLE = 5;
|
||||||
$this->machine->DR->M_COOLANT = 9;
|
$this->CNC6600->DR->M_COOLANT = 9;
|
||||||
$N = $this->machine->PPMC->N;
|
$N = $this->CNC6600->PPMC->N;
|
||||||
$this->machine->PPMC->reset();
|
$this->CNC6600->PPMC->reset();
|
||||||
$this->machine->SPMC->reset();
|
$this->CNC6600->SPMC->reset();
|
||||||
$this->machine->PPMC->loadProgram($N);
|
$this->CNC6600->PPMC->loadProgram($N);
|
||||||
$this->machine->AMC = $this->machine->PPMC;
|
$this->CNC6600->_AMC = $this->CNC6600->PPMC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Automata;
|
namespace Machine\Memory;
|
||||||
|
|
||||||
class DataRegisters
|
class DataRegisters
|
||||||
{
|
{
|
||||||
@ -17,7 +17,7 @@ class DataRegisters
|
|||||||
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 $E = 0; // Number of repetitions / multiple meanings
|
public int $E = 0; // Number of repetitions / multiple meanings
|
||||||
// Modals
|
// modals
|
||||||
public int $G_TRAVERSE = 0;
|
public int $G_TRAVERSE = 0;
|
||||||
public int $G_PLANE_SELECTION = 18;
|
public int $G_PLANE_SELECTION = 18;
|
||||||
public int $G_RADIUS_COMPENSATION = 40;
|
public int $G_RADIUS_COMPENSATION = 40;
|
@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Automata\Memory;
|
namespace Machine\Memory;
|
||||||
|
|
||||||
use Countable;
|
use Countable;
|
||||||
use InvalidArgumentException;
|
use InvalidArgumentException;
|
@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Automata\Memory;
|
namespace Machine\Memory;
|
||||||
|
|
||||||
use InvalidArgumentException;
|
use InvalidArgumentException;
|
||||||
use Program\Program;
|
use Program\Program;
|
@ -1,24 +1,24 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Automata\Memory;
|
namespace Machine\Memory;
|
||||||
|
|
||||||
use Automata\ToolData;
|
|
||||||
use InvalidArgumentException;
|
use InvalidArgumentException;
|
||||||
|
use Tool\Tool;
|
||||||
|
|
||||||
class ToolMemory
|
class ToolMemory
|
||||||
{
|
{
|
||||||
/** @var ToolData[] */
|
/** @var Tool[] */
|
||||||
private array $memory = [];
|
private array $memory = [];
|
||||||
|
|
||||||
|
|
||||||
public function write(ToolData $tool): void
|
public function write(Tool $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): ?ToolData
|
public function read(int $T): ?Tool
|
||||||
{
|
{
|
||||||
return @$this->memory[$T];
|
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
|
<?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 = explode(PHP_EOL, file_get_contents($filename));
|
||||||
$lines = array_filter($lines);
|
$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 */
|
/** @var Word[] $words */
|
||||||
$words = [];
|
$words = [];
|
||||||
foreach ($lines as $line) {
|
foreach ($lines as $line) {
|
||||||
@ -34,7 +41,6 @@ class ProgramParser
|
|||||||
$words[] = new Word($wordBuffer['register'], $wordBuffer['value']);
|
$words[] = new Word($wordBuffer['register'], $wordBuffer['value']);
|
||||||
$wordBuffer = [];
|
$wordBuffer = [];
|
||||||
$state = 'NONE';
|
$state = 'NONE';
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ('NONE' === $state && ctype_alpha($character)) {
|
if ('NONE' === $state && ctype_alpha($character)) {
|
||||||
@ -43,7 +49,7 @@ class ProgramParser
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stripos($line, 'EOF') !== false) {
|
if (strpos($line, 'EOF') !== false) {
|
||||||
break 2; // End of program reached
|
break 2; // End of program reached
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,28 +59,6 @@ class ProgramParser
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// In the second stage, the words are ordered by N numbers
|
return $words;
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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
|
<?php
|
||||||
|
|
||||||
namespace Automata;
|
namespace Tool;
|
||||||
|
|
||||||
class ToolData
|
class Tool
|
||||||
{
|
{
|
||||||
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
|
0
var/.gitignore
vendored
Normal file
0
var/.gitignore
vendored
Normal file
Loading…
Reference in New Issue
Block a user