initial commit
This commit is contained in:
commit
b0ab00efa8
167
main.c
Normal file
167
main.c
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
/*
|
||||||
|
* main.c
|
||||||
|
*
|
||||||
|
* Created on: 10.04.2018
|
||||||
|
* Author: julian
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "parser.h"
|
||||||
|
|
||||||
|
char buffer[100];
|
||||||
|
|
||||||
|
// Parser error handler
|
||||||
|
void error(const char * format, ...) {
|
||||||
|
fputs("ERR: ", stderr);
|
||||||
|
|
||||||
|
va_list list;
|
||||||
|
va_start(list, format);
|
||||||
|
vfprintf(stderr, format, list);
|
||||||
|
va_end(list);
|
||||||
|
notok = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** movement related stuff **/
|
||||||
|
enum movement_types {
|
||||||
|
MOVE_ABSOLUTE = 0,
|
||||||
|
MOVE_RELATIVE,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct coordinate_system {
|
||||||
|
float position[2];
|
||||||
|
enum movement_types movement_type;
|
||||||
|
} coordinate_system_t;
|
||||||
|
|
||||||
|
coordinate_system_t coordinate_system;
|
||||||
|
|
||||||
|
void move(const char * start, const char * end) {
|
||||||
|
argument_t arg;
|
||||||
|
float posa = 0, posb = 0;
|
||||||
|
static float feed = 100;
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
// parse all arguments
|
||||||
|
while(nextArgument(&arg, &start, end)) {
|
||||||
|
switch(toUpper(arg.c)) {
|
||||||
|
case 'A':
|
||||||
|
posa = arg.num;
|
||||||
|
break;
|
||||||
|
case 'B':
|
||||||
|
posb = arg.num;
|
||||||
|
break;
|
||||||
|
case 'F':
|
||||||
|
if (arg.num <= 0) {
|
||||||
|
error("F%f: feed must be greater than zero!\n", arg.num);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
feed = arg.num;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!count) {
|
||||||
|
error("no arguments provided! need at least a new position for either A or B axis\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("move A: %f, B: %f, feed %f\n", posa, posb, feed);
|
||||||
|
|
||||||
|
switch (coordinate_system.movement_type) {
|
||||||
|
case MOVE_RELATIVE:
|
||||||
|
coordinate_system.position[0] += posa;
|
||||||
|
coordinate_system.position[1] += posb;
|
||||||
|
break;
|
||||||
|
case MOVE_ABSOLUTE:
|
||||||
|
coordinate_system.position[0] = posa;
|
||||||
|
coordinate_system.position[1] = posb;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void home(const char * start, const char * end) {
|
||||||
|
argument_t arg;
|
||||||
|
while(nextArgument(&arg, &start, end)) {
|
||||||
|
switch(toUpper(arg.c)) {
|
||||||
|
case 'A':
|
||||||
|
coordinate_system.position[0] = 0;
|
||||||
|
break;
|
||||||
|
case 'B':
|
||||||
|
coordinate_system.position[1] = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void state(const char * start, const char * end) {
|
||||||
|
printf("current position: A\t%f, B\t%f\n", coordinate_system.position[0], coordinate_system.position[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Settings **/
|
||||||
|
void set_move_absolute() {
|
||||||
|
coordinate_system.movement_type = MOVE_ABSOLUTE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_move_relative() {
|
||||||
|
coordinate_system.movement_type = MOVE_RELATIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// reads one line of text in
|
||||||
|
// handles overflow
|
||||||
|
void readline(FILE * input) {
|
||||||
|
char * pos = buffer;
|
||||||
|
char * end = buffer + sizeof(buffer);
|
||||||
|
|
||||||
|
while(!feof(input)) {
|
||||||
|
char c = fgetc(input);
|
||||||
|
*pos = c;
|
||||||
|
pos++;
|
||||||
|
|
||||||
|
if (c == '\n') {
|
||||||
|
parse(buffer, pos);
|
||||||
|
pos = buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pos >= end) {
|
||||||
|
printf("buffer overflow!");
|
||||||
|
pos = buffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
int testAsFloat() {
|
||||||
|
float result = 0;
|
||||||
|
const char * str = "10";
|
||||||
|
|
||||||
|
const char * start = str, * end = str + strlen(str);
|
||||||
|
if (!asFloat(&result, &start, end)) return 0;
|
||||||
|
if (result < 9.999 || result > 10.001) return 0;
|
||||||
|
|
||||||
|
str = "0.001";
|
||||||
|
start = str, end = str + strlen(str);
|
||||||
|
if (!asFloat(&result, &start, end)) return 0;
|
||||||
|
if (result < 0.0005 || result > 0.0015) return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
printf("Test Float parsing: ");
|
||||||
|
if (testAsFloat()) {
|
||||||
|
printf(" PASS\n");
|
||||||
|
} else {
|
||||||
|
printf(" FAIL\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
readline(stdin);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
198
parser.c
Normal file
198
parser.c
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
/*
|
||||||
|
* parser.c
|
||||||
|
*
|
||||||
|
* Created on: 10.04.2018
|
||||||
|
* Author: julian
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "parser.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int isWhite(char c) {
|
||||||
|
return c == ' ' || c == '\t' || c == '\r' || c == '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
int isNumber(char c) {
|
||||||
|
return c >= '0' && c <= '9';
|
||||||
|
}
|
||||||
|
|
||||||
|
// point that splits real numbers
|
||||||
|
int isPoint(char c) {
|
||||||
|
return c == '.' || c == ',';
|
||||||
|
}
|
||||||
|
|
||||||
|
char toLower(char in) {
|
||||||
|
if (in >= 'A' && in <= 'Z') {
|
||||||
|
return in - 'A' + 'a';
|
||||||
|
}
|
||||||
|
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
char toUpper(char in) {
|
||||||
|
if (in >= 'a' && in <= 'z') {
|
||||||
|
return in - 'a' + 'A';
|
||||||
|
}
|
||||||
|
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
void skipWhite(const char ** start, const char * end) {
|
||||||
|
if (!start) return;
|
||||||
|
|
||||||
|
while(*start < end && isWhite(**start)) {
|
||||||
|
++*start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns 1 on success
|
||||||
|
int asInt(int * result, const char ** start, const char * end) {
|
||||||
|
if (!result || !start) return 0;
|
||||||
|
|
||||||
|
skipWhite(start, end);
|
||||||
|
if (*start == end) { return 0; }
|
||||||
|
|
||||||
|
int inv = 0;
|
||||||
|
unsigned int count = 0;
|
||||||
|
|
||||||
|
switch(**start) {
|
||||||
|
case '-':
|
||||||
|
inv = 1;
|
||||||
|
case '+':
|
||||||
|
++*start;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
*result = 0;
|
||||||
|
|
||||||
|
for(;*start != end && isNumber(**start); ++*start, count++) {
|
||||||
|
*result *= 10;
|
||||||
|
*result += **start - '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inv) {
|
||||||
|
*result = -*result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return count > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int asFloat(float *result, const char **start, const char * end) {
|
||||||
|
if (!result || !start ) return 0;
|
||||||
|
skipWhite(start, end);
|
||||||
|
if (*start == end) return 0;
|
||||||
|
|
||||||
|
int nominator = 0;
|
||||||
|
float denomiator = 0.f;
|
||||||
|
|
||||||
|
if (!asInt(&nominator, start, end)) return 0;
|
||||||
|
|
||||||
|
if (isPoint(**start)) {
|
||||||
|
const char * denom_end = *start +1;
|
||||||
|
|
||||||
|
while(denom_end < end && isNumber(*denom_end))
|
||||||
|
denom_end++;
|
||||||
|
|
||||||
|
|
||||||
|
while(--denom_end > *start) {
|
||||||
|
denomiator += *denom_end - '0';
|
||||||
|
denomiator /= 10.f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*result = (float)(nominator) + denomiator;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nextArgument(argument_t* result, const char ** start, const char * end) {
|
||||||
|
if (!start | !result) return 0;
|
||||||
|
skipWhite(start, end);
|
||||||
|
if (*start == end) return 0;
|
||||||
|
|
||||||
|
result->c = **start;
|
||||||
|
++*start;
|
||||||
|
asFloat(&result->num, start, end);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
volatile int notok;
|
||||||
|
|
||||||
|
void gcode(const char * start, const char * end) {
|
||||||
|
int code;
|
||||||
|
skipWhite(&start, end);
|
||||||
|
|
||||||
|
if (start == end || !asInt(&code, &start, end)) {
|
||||||
|
error("expected number after G\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(code) {
|
||||||
|
case 0:
|
||||||
|
case 1:
|
||||||
|
// move
|
||||||
|
move(start, end);
|
||||||
|
break;
|
||||||
|
case 28:
|
||||||
|
// home;
|
||||||
|
home(start, end);
|
||||||
|
break;
|
||||||
|
case 90:
|
||||||
|
set_move_absolute();
|
||||||
|
break;
|
||||||
|
case 91:
|
||||||
|
set_move_relative();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
error("unknown gcode: %d\n",code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mcode(const char * start, const char * end) {
|
||||||
|
int code;
|
||||||
|
skipWhite(&start, end);
|
||||||
|
|
||||||
|
if (start == end || !asInt(&code, &start, end)) {
|
||||||
|
printf("expected number after M\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(code) {
|
||||||
|
case 500:
|
||||||
|
// save config data
|
||||||
|
printf("save config data\n");
|
||||||
|
break;
|
||||||
|
case 502:
|
||||||
|
printf("restore default config\n");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
error("no Mcode: %d\n", code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void parse(const char * start, const char * end) {
|
||||||
|
notok = 0;
|
||||||
|
|
||||||
|
skipWhite(&start, end);
|
||||||
|
if (start == end) return;
|
||||||
|
|
||||||
|
switch (toLower(*start)) {
|
||||||
|
case 'g':
|
||||||
|
gcode(++start, end);
|
||||||
|
break;
|
||||||
|
case 'm':
|
||||||
|
mcode(++start, end);
|
||||||
|
break;
|
||||||
|
case '?':
|
||||||
|
state(++start, end);
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
error("expected g or m codes\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (notok) { return; }
|
||||||
|
|
||||||
|
printf("ok\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
56
parser.h
Normal file
56
parser.h
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* parser.h
|
||||||
|
*
|
||||||
|
* Created on: 10.04.2018
|
||||||
|
* Author: julian
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PARSER_H_
|
||||||
|
#define PARSER_H_
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
|
||||||
|
int isWhite(char c);
|
||||||
|
int isNumber(char c);
|
||||||
|
|
||||||
|
// point that splits real numbers
|
||||||
|
int isPoint(char c);
|
||||||
|
|
||||||
|
|
||||||
|
char toLower(char in);
|
||||||
|
char toUpper(char in);
|
||||||
|
|
||||||
|
void skipWhite(const char ** start, const char * end);
|
||||||
|
|
||||||
|
// returns 1 on success
|
||||||
|
int asInt(int * result, const char ** start, const char * end);
|
||||||
|
int asFloat(float *result, const char **start, const char * end);
|
||||||
|
|
||||||
|
typedef struct argument {
|
||||||
|
char c;
|
||||||
|
float num;
|
||||||
|
} argument_t;
|
||||||
|
|
||||||
|
int nextArgument(argument_t* result, const char ** start, const char * end);
|
||||||
|
|
||||||
|
extern volatile int notok;
|
||||||
|
void error(const char * format, ...);
|
||||||
|
|
||||||
|
|
||||||
|
/** system functions **/
|
||||||
|
void move(const char * start, const char * end);
|
||||||
|
void home(const char * start, const char * end);
|
||||||
|
void state(const char * start, const char * end);
|
||||||
|
|
||||||
|
void set_move_absolute();
|
||||||
|
void set_move_relative();
|
||||||
|
|
||||||
|
/** parser functions **/
|
||||||
|
void gcode(const char * start, const char * end);
|
||||||
|
void mcode(const char * start, const char * end);
|
||||||
|
|
||||||
|
void parse(const char * start, const char * end);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* PARSER_H_ */
|
Loading…
Reference in New Issue
Block a user