按规划继续工作
结论:接入 vendored LinuxCNC tooldata_common.cc 负责刀具表解析与保存,WASM/SDK/OPFS/UI 仅做运行时边界搬运;native、WASM、OPFS 和浏览器 smoke 验证已通过。
This commit is contained in:
423
wasm-port/vendor/linuxcnc/src/emc/tooldata/tooldata_common.cc
vendored
Normal file
423
wasm-port/vendor/linuxcnc/src/emc/tooldata/tooldata_common.cc
vendored
Normal file
@@ -0,0 +1,423 @@
|
||||
/*
|
||||
** This file is part of a refactor of internal tool data management
|
||||
** and incorporates work from removed files:
|
||||
** src/emc/ini/initool.cc
|
||||
** src/emc/rs274ngc/tool_parse.cc
|
||||
**
|
||||
** Copyright: 2021
|
||||
** Author: Dewey Garrett <dgarrett@panix.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation; either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program; if not, write to the Free Software
|
||||
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <rtapi_string.h>
|
||||
#include "tooldata.hh"
|
||||
|
||||
#define UNEXPECTED_MSG fprintf(stderr,"UNEXPECTED %s %d\n",__FILE__,__LINE__);
|
||||
|
||||
static bool is_random_toolchanger = 0;
|
||||
static int nonrandom_idx = 0; // 'fakepocket' counter
|
||||
static bool add_init_initialized = 0;
|
||||
static tooldb_t db_mode = DB_NOTUSED;
|
||||
|
||||
void tooldata_init(bool random_toolchanger)
|
||||
{
|
||||
is_random_toolchanger = random_toolchanger;
|
||||
} // tooldata_init
|
||||
|
||||
struct CANON_TOOL_TABLE tooldata_entry_init()
|
||||
{
|
||||
struct CANON_TOOL_TABLE tdata;
|
||||
tdata.toolno = -1;
|
||||
tdata.pocketno = -1;
|
||||
tdata.diameter = 0;
|
||||
tdata.frontangle = 0;
|
||||
tdata.backangle = 0;
|
||||
tdata.orientation = 0;
|
||||
ZERO_EMC_POSE(tdata.offset);
|
||||
tdata.comment[0] = 0;
|
||||
|
||||
return tdata;
|
||||
} // tooldata_entry_init()
|
||||
|
||||
void tooldata_set_db(tooldb_t mode)
|
||||
{
|
||||
db_mode = mode;
|
||||
return;
|
||||
} //tooldata_set_db()
|
||||
|
||||
void tooldata_add_init(int nonrandom_start_idx)
|
||||
{
|
||||
// initialize file-static vars need for tooldata_add_line()
|
||||
nonrandom_idx = nonrandom_start_idx;
|
||||
add_init_initialized = 1;
|
||||
return;
|
||||
} // tooldata_add_init()
|
||||
|
||||
int tooldata_read_entry(const char *input_line)
|
||||
{
|
||||
char work_line[CANON_TOOL_ENTRY_LEN];
|
||||
const char *token;
|
||||
char *buff, *comment;
|
||||
int toolno,orientation,valid=1;
|
||||
EmcPose offset; //tlo
|
||||
double diameter, frontangle, backangle;
|
||||
int idx = 0;
|
||||
int realpocket = 0;
|
||||
|
||||
if (!add_init_initialized) {
|
||||
fprintf(stderr,"!!! PROBLEM no init %s\n",__FILE__);
|
||||
return -1;
|
||||
}
|
||||
if (input_line[0] == ';') {return 0;} //ignore leading ';'
|
||||
strncpy(work_line, input_line, sizeof(work_line)-1);
|
||||
work_line[sizeof(work_line)-1] = 0;
|
||||
|
||||
CANON_TOOL_TABLE empty = tooldata_entry_init();
|
||||
toolno = empty.toolno;
|
||||
diameter = empty.diameter;
|
||||
frontangle = empty.frontangle;
|
||||
backangle = empty.backangle;
|
||||
orientation = empty.orientation;
|
||||
offset = empty.offset;
|
||||
|
||||
char* saveptr;
|
||||
buff = strtok_r(work_line, ";", &saveptr);
|
||||
if (strlen(buff) <=1) {
|
||||
//fprintf(stderr,"skip blankline %s\n",__FILE__);
|
||||
return 0;
|
||||
}
|
||||
comment = strtok_r(NULL, "\n", &saveptr);
|
||||
|
||||
token = strtok_r(buff, " ", &saveptr);
|
||||
while (token != NULL) {
|
||||
switch (toupper(token[0])) {
|
||||
case 'T':
|
||||
if (sscanf(&token[1], "%d", &toolno) != 1)
|
||||
valid = 0;
|
||||
break;
|
||||
case 'P':
|
||||
if (sscanf(&token[1], "%d", &idx) != 1) {
|
||||
valid = 0;
|
||||
break;
|
||||
}
|
||||
realpocket = idx; //random toolchanger
|
||||
if (!is_random_toolchanger) {
|
||||
if ( (nonrandom_idx <= 0)
|
||||
|| (nonrandom_idx >= CANON_POCKETS_MAX) ) {
|
||||
printf("Out-of-range nonrandom_idx=%d. Skipping tool=%d\n",
|
||||
nonrandom_idx,toolno);
|
||||
valid = 0;
|
||||
break;
|
||||
}
|
||||
idx = nonrandom_idx; // nonrandom toolchanger
|
||||
(nonrandom_idx)++;
|
||||
}
|
||||
if (idx < 0 || idx >= CANON_POCKETS_MAX) {
|
||||
printf("max pocket number is %d. skipping tool %d\n",
|
||||
CANON_POCKETS_MAX - 1, toolno);
|
||||
valid = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'D':
|
||||
if (sscanf(&token[1], "%lf", &diameter) != 1)
|
||||
valid = 0;
|
||||
break;
|
||||
case 'X':
|
||||
if (sscanf(&token[1], "%lf", &offset.tran.x) != 1)
|
||||
valid = 0;
|
||||
break;
|
||||
case 'Y':
|
||||
if (sscanf(&token[1], "%lf", &offset.tran.y) != 1)
|
||||
valid = 0;
|
||||
break;
|
||||
case 'Z':
|
||||
if (sscanf(&token[1], "%lf", &offset.tran.z) != 1)
|
||||
valid = 0;
|
||||
break;
|
||||
case 'A':
|
||||
if (sscanf(&token[1], "%lf", &offset.a) != 1)
|
||||
valid = 0;
|
||||
break;
|
||||
case 'B':
|
||||
if (sscanf(&token[1], "%lf", &offset.b) != 1)
|
||||
valid = 0;
|
||||
break;
|
||||
case 'C':
|
||||
if (sscanf(&token[1], "%lf", &offset.c) != 1)
|
||||
valid = 0;
|
||||
break;
|
||||
case 'U':
|
||||
if (sscanf(&token[1], "%lf", &offset.u) != 1)
|
||||
valid = 0;
|
||||
break;
|
||||
case 'V':
|
||||
if (sscanf(&token[1], "%lf", &offset.v) != 1)
|
||||
valid = 0;
|
||||
break;
|
||||
case 'W':
|
||||
if (sscanf(&token[1], "%lf", &offset.w) != 1)
|
||||
valid = 0;
|
||||
break;
|
||||
case 'I':
|
||||
if (sscanf(&token[1], "%lf", &frontangle) != 1)
|
||||
valid = 0;
|
||||
break;
|
||||
case 'J':
|
||||
if (sscanf(&token[1], "%lf", &backangle) != 1)
|
||||
valid = 0;
|
||||
break;
|
||||
case 'Q':
|
||||
if (sscanf(&token[1], "%d", &orientation) != 1)
|
||||
valid = 0;
|
||||
break;
|
||||
default:
|
||||
if (strncmp(token, "\n", 1) != 0)
|
||||
valid = 0;
|
||||
break;
|
||||
}
|
||||
token = strtok_r(NULL, " ", &saveptr);
|
||||
} // while token
|
||||
|
||||
if (valid) {
|
||||
CANON_TOOL_TABLE tdata = tooldata_entry_init();
|
||||
// verify no prior tool in pocket
|
||||
if (tooldata_get(&tdata,idx) != IDX_OK) { UNEXPECTED_MSG; }
|
||||
if (is_random_toolchanger && tdata.toolno != -1) {
|
||||
fprintf(stderr,"WARNING: Attempt to assign multiple toolno.s to pocket %d\n",realpocket);
|
||||
fprintf(stderr," %s %s()\n",__FILE__,__FUNCTION__);
|
||||
fprintf(stderr," WAS: pocket=%3d toolno=%3d\n",tdata.pocketno,tdata.toolno);
|
||||
fprintf(stderr," IS: pocket=%3d toolno=%3d\n",realpocket,toolno);
|
||||
}
|
||||
tdata.toolno = toolno;
|
||||
tdata.pocketno = realpocket;
|
||||
tdata.offset = offset;
|
||||
tdata.diameter = diameter;
|
||||
tdata.frontangle = frontangle;
|
||||
tdata.backangle = backangle;
|
||||
tdata.orientation = orientation;
|
||||
if (comment) {
|
||||
strncpy(tdata.comment,comment,CANON_TOOL_COMMENT_SIZE-1);
|
||||
tdata.comment[CANON_TOOL_COMMENT_SIZE-1] = 0;
|
||||
if (strlen(comment) > (CANON_TOOL_COMMENT_SIZE-1) ) {
|
||||
fprintf(stderr,"%s():comment for toolno %d truncated to %d chars:\n <%s>\n"
|
||||
,__FUNCTION__
|
||||
,tdata.toolno
|
||||
,CANON_TOOL_COMMENT_SIZE-1
|
||||
,tdata.comment
|
||||
);
|
||||
}
|
||||
}
|
||||
if (tooldata_put(tdata,idx) == IDX_FAIL) {
|
||||
UNEXPECTED_MSG;
|
||||
}
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
return idx;
|
||||
} // tooldata_read_entry()
|
||||
|
||||
void tooldata_format_toolline (int idx,
|
||||
bool ignore_zero_values,
|
||||
CANON_TOOL_TABLE tdata,
|
||||
char formatted_line[CANON_TOOL_ENTRY_LEN]
|
||||
)
|
||||
{
|
||||
char tmp[CANON_TOOL_ENTRY_LEN-1] = {0};
|
||||
int space = sizeof(tmp);
|
||||
int len;
|
||||
len = snprintf(tmp,sizeof(tmp),"T%-3d P%-3d"
|
||||
,tdata.toolno
|
||||
,is_random_toolchanger ? idx : tdata.pocketno);
|
||||
strncat(formatted_line,tmp,space);
|
||||
space -= len;
|
||||
// format zero float values as %.0f for brevity
|
||||
#define F_ITEM(item,letter) if (!ignore_zero_values || tdata.item) { \
|
||||
char local_tmp[64] = {}; \
|
||||
if (tdata.item) { \
|
||||
len = snprintf(local_tmp,sizeof(local_tmp)," " letter "%+f", tdata.item); \
|
||||
} else { \
|
||||
len = snprintf(local_tmp,sizeof(local_tmp)," " letter "%.0f",tdata.item); \
|
||||
} \
|
||||
strncat(formatted_line,local_tmp,space); \
|
||||
space -= len; \
|
||||
}
|
||||
#define I_ITEM(item,letter) if (!ignore_zero_values || tdata.item) { \
|
||||
len = snprintf(tmp,sizeof(tmp)," " letter "%d",tdata.item); \
|
||||
strncat(formatted_line,tmp,space); \
|
||||
space -= len; \
|
||||
}
|
||||
|
||||
F_ITEM(diameter, "D");
|
||||
F_ITEM(offset.tran.x, "X");
|
||||
F_ITEM(offset.tran.y, "Y");
|
||||
F_ITEM(offset.tran.z, "Z");
|
||||
F_ITEM(offset.a, "A");
|
||||
F_ITEM(offset.b, "B");
|
||||
F_ITEM(offset.c, "C");
|
||||
F_ITEM(offset.u, "U");
|
||||
F_ITEM(offset.v, "V");
|
||||
F_ITEM(offset.w, "W");
|
||||
F_ITEM(frontangle, "I");
|
||||
F_ITEM(backangle, "J");
|
||||
I_ITEM(orientation, "Q");
|
||||
#undef F_ITEM
|
||||
#undef I_ITEM
|
||||
// Stop tracking len and space here for current tool table format
|
||||
if (tdata.comment[0]) {
|
||||
snprintf(tmp,space," ;%s\n",tdata.comment);
|
||||
} else {
|
||||
snprintf(tmp,space,"\n");
|
||||
}
|
||||
strncat(formatted_line,tmp,space);
|
||||
return;
|
||||
} // tooldata_format_toolline()
|
||||
|
||||
int tooldata_load(const char *filename)
|
||||
{
|
||||
FILE *fp;
|
||||
char input_line[CANON_TOOL_ENTRY_LEN];
|
||||
char orig_line[CANON_TOOL_ENTRY_LEN];
|
||||
|
||||
if (db_mode == DB_ACTIVE) { //expect data loaded from db
|
||||
if (tooldata_db_getall()) {
|
||||
fprintf(stderr,
|
||||
"\ntooldata_load: Failed to load tooldata from database\n\n");
|
||||
db_mode = DB_NOTUSED;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!filename) return -1;
|
||||
|
||||
// clear out tool table
|
||||
// (Set vars to indicate no tool in pocket):
|
||||
tooldata_reset();
|
||||
|
||||
// open tool table file
|
||||
if (NULL == (fp = fopen(filename, "r"))) {
|
||||
fprintf(stderr, "%s, %d: Failed to open tool table file '%s': %s\n",
|
||||
__FILE__, __LINE__, filename, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
// after initializing all available pockets,
|
||||
// subsequent read from filename will update the last_index
|
||||
// which becomes available by tooldata_last_index_get()
|
||||
tooldata_last_index_set(0); // (only mmap uses)
|
||||
|
||||
const int nonrandom_start_idx = 1; // when reading file start at 0
|
||||
tooldata_add_init(nonrandom_start_idx);
|
||||
|
||||
while (!feof(fp)) {
|
||||
// for nonrandom machines, just read the tools into pockets 1..n
|
||||
// no matter their tool numbers. NB leave the spindle pocket 0
|
||||
// unchanged/empty.
|
||||
if (NULL == fgets(input_line, CANON_TOOL_ENTRY_LEN, fp)) {
|
||||
break;
|
||||
}
|
||||
strcpy(orig_line, input_line);
|
||||
|
||||
// parse and store one line from tool table file
|
||||
int entry_idx = tooldata_read_entry(input_line);
|
||||
if (entry_idx <0) {
|
||||
printf("File: %s Unrecognized line skipped:\n %s",filename, orig_line);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!is_random_toolchanger) {
|
||||
CANON_TOOL_TABLE spindletool;
|
||||
if (tooldata_get(&spindletool,0) != IDX_OK) {
|
||||
continue;
|
||||
}
|
||||
CANON_TOOL_TABLE edata; // just added
|
||||
if (tooldata_get(&edata,entry_idx) != IDX_OK) {
|
||||
UNEXPECTED_MSG;
|
||||
}
|
||||
if (!is_random_toolchanger && spindletool.toolno == edata.toolno) {
|
||||
spindletool = edata;
|
||||
tooldata_put(spindletool,0);
|
||||
}
|
||||
}
|
||||
} // while
|
||||
|
||||
// close the file
|
||||
fclose(fp);
|
||||
|
||||
return 0;
|
||||
} // tooldata_load()
|
||||
|
||||
static void write_tool_line(FILE* fp,int idx)
|
||||
{
|
||||
CANON_TOOL_TABLE tdata;
|
||||
if (tooldata_get(&tdata,idx) != IDX_OK) {return;}
|
||||
if (db_mode == DB_ACTIVE && idx != 0 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (tdata.toolno != -1) {
|
||||
char theline[CANON_TOOL_ENTRY_LEN] = {0};
|
||||
tooldata_format_toolline (idx,
|
||||
1, // ignore_zero_values
|
||||
tdata,theline);
|
||||
fprintf(fp,"%s",theline);
|
||||
}
|
||||
return;
|
||||
} // write_tool_line()
|
||||
|
||||
int tooldata_save(const char *filename)
|
||||
{
|
||||
int idx;
|
||||
FILE *fp;
|
||||
int start_idx;
|
||||
|
||||
if (db_mode == DB_ACTIVE) {
|
||||
if (!is_random_toolchanger) {return 0;}
|
||||
filename = DB_SPINDLE_SAVE; //one entry tbl (nonran only)
|
||||
} else {
|
||||
// filename == NULL happens without ini entry [EMCIO]TOOL_TABLE
|
||||
// and a Task::emcToolSetOffset is performed.
|
||||
if (!filename) {
|
||||
fprintf(stderr, "%s: No filename. Are you missing INI-entry [EMCIO]TOOL_TABLE?\n",
|
||||
__PRETTY_FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
if (filename[0] == 0) {
|
||||
UNEXPECTED_MSG;
|
||||
}
|
||||
}
|
||||
|
||||
// open tool table file
|
||||
if (NULL == (fp = fopen(filename, "w"))) {
|
||||
fprintf(stderr, "%s, %d: Failed to open tool table file '%s': %s\n",
|
||||
__FILE__, __LINE__, filename, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (db_mode == DB_ACTIVE) {
|
||||
int spindle_idx = 0;
|
||||
write_tool_line(fp,spindle_idx);
|
||||
} else {
|
||||
start_idx = is_random_toolchanger ? 0 : 1;
|
||||
for (idx = start_idx; idx < CANON_POCKETS_MAX; idx++) {
|
||||
write_tool_line(fp,idx);
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
return 0;
|
||||
} //tooldata_save()
|
||||
Reference in New Issue
Block a user