gcode-interpreter

A gcode interpreter I use to control lasers.
git clone git://git.christianermann.dev/gcode-interpreter
Log | Files | Refs | README | LICENSE

main.c (5902B)


      1 #include "token.h"
      2 #include "command.h"
      3 #include "machine.h"
      4 #include "timing.h"
      5 #include "tui.h"
      6 
      7 #include <assert.h>
      8 #include <string.h>
      9 #include <errno.h>
     10 
     11 void print_state(
     12     const Machine* machine,
     13     const ExecutionResult* execution_result
     14 ) {
     15     type(set_cursor(1, 2));
     16     printf("gcode interpreter");
     17     type(clear_to_end_of_line);
     18 
     19     type(set_cursor(3, 2));
     20     printf("machine state:");
     21     type(clear_to_end_of_line);
     22 
     23     type(set_cursor(4, 6));
     24     printf(
     25         "xyz: [ %4.3f %4.3f %4.3f ] (%s/sec)",
     26         machine->x,
     27         machine->y,
     28         machine->z,
     29         UNITS_STRINGS[machine->units]
     30     );
     31     type(clear_to_end_of_line);
     32 
     33     type(set_cursor(5, 6));
     34     printf(
     35         "feed rate: [ %4.3f ] (%s/min)",
     36         machine->feed_rate,
     37         UNITS_STRINGS[machine->units]
     38     );
     39     type(clear_to_end_of_line);
     40 
     41     type(set_cursor(6, 6));
     42     printf(
     43         "positioning_mode: %s",
     44         POSITIONING_MODE_STRINGS[machine->positioning_mode]
     45     );
     46     type(clear_to_end_of_line);
     47 }
     48 
     49 void print_token_error(const Token* token, unsigned int* error_count) {
     50     type(set_cursor(8, 2));
     51     printf(
     52         "%c [L%d C%d] -- %s\n",
     53         token->type,
     54         token->line_idx,
     55         token->char_idx,
     56         TOKEN_ERROR_STRINGS[token->value.error_value]
     57     );
     58     type(clear_to_end_of_line);
     59 
     60     type(set_cursor(9, 2));
     61     printf("total error count: %d", *error_count);
     62     type(clear_to_end_of_line);
     63 
     64     type(set_cursor(10, 2));
     65     fprintf(
     66         stderr,
     67         "%c [L%d C%d] -- %s\n",
     68         token->type,
     69         token->line_idx,
     70         token->char_idx,
     71         TOKEN_ERROR_STRINGS[token->value.error_value]
     72     );
     73 }
     74 
     75 void print_execution_error(
     76     const Command* command,
     77     const ExecutionResult* result,
     78     unsigned int* error_count
     79 ) {
     80     type(set_cursor(8, 2));
     81     printf(
     82         "! [%c%-3d] -- %s",
     83         command->code.type,
     84         command->code.value,
     85         MACHINE_ERROR_STRINGS[result->status]
     86     );
     87     type(clear_to_end_of_line);
     88 
     89     type(set_cursor(9, 2));
     90     printf("total error count: %d", *error_count);
     91     type(clear_to_end_of_line);
     92 
     93     type(set_cursor(10, 2));
     94     fprintf(
     95         stderr,
     96         "! [%c%-3d] -- %s\n",
     97         command->code.type,
     98         command->code.value,
     99         MACHINE_ERROR_STRINGS[result->status]
    100     );
    101 }
    102 
    103 void save_output(
    104     FILE* file,
    105     const ExecutionResult* result,
    106     const Time* now
    107 ) {
    108     if (!result->has_data) {
    109         return;
    110     }
    111     fprintf(
    112         file,
    113         "%10ld (s) %10ld (ns) - [ %4.3f %4.3f %4.3f ]\n",
    114         now->time_s,
    115         now->time_ns,
    116         result->data.x,
    117         result->data.y,
    118         result->data.z
    119     );
    120 }
    121 
    122 int main(int argc, char** argv) {
    123     freopen("error.log", "w", stderr);
    124     initialize_terminal();
    125 
    126     if (argc < 2) {
    127         fprintf(stderr, "! []: input filename must be provided.\n");
    128         return -1;
    129     }
    130 
    131     FILE* file = fopen(argv[1], "r");
    132     if (file == NULL) {
    133         fprintf(stderr, "! [%s]: %s\n", argv[1], strerror(errno));
    134         return -1;
    135     }
    136 
    137     const char* output_filename = "out";
    138     FILE* output_file = fopen(output_filename, "w");
    139     if (output_file == NULL) {
    140         fprintf(stderr, "! [%s]: %s\n", output_filename, strerror(errno));
    141         return -1;
    142     }
    143 
    144     Cursor cursor;
    145     cursor_init(&cursor, file);
    146 
    147     Command command;
    148     command_init(&command);
    149 
    150     Machine machine;
    151     machine_init(&machine);
    152 
    153     Token token;
    154     CommandStatus command_status = COMMAND_STATUS__NOT_READY;
    155     ExecutionResult execution_result = {
    156         .status = EXECUTE_STATUS__IDLE,
    157         .has_data = false,
    158     };
    159 
    160     unsigned int error_count = 0;
    161 
    162     print_state(&machine, &execution_result);
    163 
    164     Time now;
    165     for (;;) {
    166         now = time_get();
    167 
    168         switch (execution_result.status) {
    169             case EXECUTE_STATUS__IDLE: {
    170                 token = parse_token(&cursor);
    171                 if (token.type == TOKEN_ERROR) {
    172                     error_count += 1;
    173                     print_token_error(&token, &error_count);
    174                     recover_from_error(&cursor, &token);
    175                 }
    176                 if (token.type == TOKEN_EOF) {
    177                     return 0;
    178                 }
    179 
    180                 command_status = command_process_token(&command, &token);
    181                 if (command_status == COMMAND_STATUS__READY) {
    182                     execution_result = machine_execute_command(
    183                         &machine,
    184                         &command,
    185                         &now
    186                     );
    187                     save_output(output_file, &execution_result, &now);
    188                     print_state(&machine, &execution_result);
    189                 }
    190                 break;
    191             }
    192             case EXECUTE_STATUS__IN_PROGRESS: {
    193                 execution_result = machine_execute_command(
    194                     &machine,
    195                     &command,
    196                     &now
    197                 );
    198                 save_output(output_file, &execution_result, &now);
    199                 print_state(&machine, &execution_result);
    200                 break;
    201             }
    202             case EXECUTE_STATUS__UNRECOGNIZED_COMMAND:
    203             case EXECUTE_STATUS__UNRECOGNIZED_MCODE:
    204             case EXECUTE_STATUS__UNRECOGNIZED_GCODE:
    205                 error_count += 1;
    206                 print_execution_error(
    207                     &command,
    208                     &execution_result,
    209                     &error_count
    210                 );
    211             case EXECUTE_STATUS__FINISHED: {
    212                 command_init(&command);
    213                 command_status = command_process_token(&command, &token);
    214                 assert(command_status == COMMAND_STATUS__NOT_READY);
    215                 execution_result.status = EXECUTE_STATUS__IDLE;
    216                 execution_result.has_data = false;
    217                 break;
    218             }
    219             default:
    220                 return 0;
    221         }
    222 
    223     }
    224     return 0;
    225 }
    226