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