From b0ab00efa8673493dff89e7caf29acee7bee4017 Mon Sep 17 00:00:00 2001 From: Julian Daube Date: Fri, 13 Apr 2018 09:47:22 +0200 Subject: [PATCH] initial commit --- main.c | 167 ++++++++++++++++++++++++++++++++++++++++++++++ parser.c | 198 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ parser.h | 56 ++++++++++++++++ 3 files changed, 421 insertions(+) create mode 100644 main.c create mode 100644 parser.c create mode 100644 parser.h diff --git a/main.c b/main.c new file mode 100644 index 0000000..5636366 --- /dev/null +++ b/main.c @@ -0,0 +1,167 @@ +/* + * main.c + * + * Created on: 10.04.2018 + * Author: julian + */ + + +#include +#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 + +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; +} + + diff --git a/parser.c b/parser.c new file mode 100644 index 0000000..d589211 --- /dev/null +++ b/parser.c @@ -0,0 +1,198 @@ +/* + * parser.c + * + * Created on: 10.04.2018 + * Author: julian + */ + +#include "parser.h" +#include + +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"); +} + + + diff --git a/parser.h b/parser.h new file mode 100644 index 0000000..6d81552 --- /dev/null +++ b/parser.h @@ -0,0 +1,56 @@ +/* + * parser.h + * + * Created on: 10.04.2018 + * Author: julian + */ + +#ifndef PARSER_H_ +#define PARSER_H_ + +#include + + +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_ */