From 36747e570356e1f08766683e2887f552eae85045 Mon Sep 17 00:00:00 2001 From: Phil Hord Date: Tue, 12 Nov 2013 11:30:09 -0500 Subject: [PATCH] Teach simulator to process gcode files directly The simulator runs as a device simulator complete with serial port so it can communicate with printer software like pronterface. But often we just want to stream it a file of gcode commands and get some output. Teach the simulator to take a regular file as input and process it as a file of gcode commands if it is not a device. --- README.sim | 15 +++++++ simulator/serial_sim.c | 91 ++++++++++++++++++++++++++++++++---------- 2 files changed, 85 insertions(+), 21 deletions(-) diff --git a/README.sim b/README.sim index 31f2649..da300e0 100644 --- a/README.sim +++ b/README.sim @@ -8,6 +8,21 @@ To compile the simulation code, use $ make -f Makefile-SIM +The simulator can run in one of two modes. It can connect to a serial port +in order to simulate a real printer or it can read in a file of gcodes as if +they were provided over the serial port. + +=== Gcode file === + +Run the simulator with the name of one or more the gcode files as the command +arguments. The simulator will read gcodes from each file in turn until all +commands are exhausted. Responses normally sent to the serial port will only +be written to the console. + + $ ./sim testcases/curves.gcode + +=== Serial port === + The simulator will open a serial port for communication. If you don't want to connect a null modem cable, you can use 'socat' to connect two serial ports: diff --git a/simulator/serial_sim.c b/simulator/serial_sim.c index 2285ffc..152d023 100644 --- a/simulator/serial_sim.c +++ b/simulator/serial_sim.c @@ -4,6 +4,9 @@ #include #include #include +#include +#include +#include #include "serial.h" #include "simulator.h" @@ -13,17 +16,47 @@ static bool serial_initialised = false; extern int g_argc; extern char ** g_argv; +static int gcode_fd; + +static void open_tty(const char *devname); +static void open_file(void); void serial_init(void) { + sim_assert(g_argc >= 2, "please specify a serial port device name or gcode file to process"); + + open_file(); + serial_initialised = true; +} + +static void open_file() { + struct stat st; + static int i=1; + const char * filename = g_argv[i++]; + + // Close previous file + if (gcode_fd) close(gcode_fd); + gcode_fd = 0; + + // No more files + if (i > g_argc) return; + + sim_info("opening %s", filename); + sim_assert(!stat(filename, &st), "Could not stat file."); + + if (!st.st_rdev) { + // Normal file + gcode_fd = open(filename, O_RDONLY ); + sim_assert(gcode_fd, "Could not open file."); + } else { + // Some kind of device (treat as TTY) + open_tty(filename); + } +} + +static void open_tty(const char *devname) +{ struct termios options; - - int argc = g_argc; - char **argv = g_argv; - - sim_assert(argc >= 2, "please specify a serial port device name"); - - sim_info("opening serial port %s", argv[1]); - serial_fd = open(argv[1], O_RDWR | O_NOCTTY | O_NDELAY); + serial_fd = open(devname, O_RDWR | O_NOCTTY | O_NDELAY); sim_assert(serial_fd != -1, "couldn't open serial port"); sim_assert(isatty(serial_fd), "not a TTY"); @@ -52,48 +85,64 @@ void serial_init(void) { // flush tx and rx buffers tcflush(serial_fd, TCIOFLUSH); - - serial_initialised = true; } // return number of characters in the receive buffer uint8_t serial_rxchars(void) { - int rx_chars_nb; - sim_assert(serial_initialised, "serial interface not initialised"); - ioctl(serial_fd, FIONREAD, &rx_chars_nb); - return rx_chars_nb; + if (serial_fd) { + int rx_chars_nb; + + ioctl(serial_fd, FIONREAD, &rx_chars_nb); + return rx_chars_nb; + } + // File always has more data + return 1; } // read one character uint8_t serial_popchar(void) { uint8_t c; ssize_t count; + int fd = serial_fd ? serial_fd : gcode_fd; sim_assert(serial_initialised, "serial interface not initialised"); sim_assert(serial_rxchars() > 0, "no chars to read"); - count = read(serial_fd, &c, 1); + count = read(fd, &c, 1); + if (gcode_fd && !count) { + // EOF: try to open next file + open_file(); + if (gcode_fd || serial_fd) + return serial_popchar(); + + sim_info("Gcode processing completed."); + exit(0); + } sim_assert(count == 1, "no character in serial RX buffer"); return c; } // send one character void serial_writechar(uint8_t data) { - ssize_t count; sim_assert(serial_initialised, "serial interface not initialised"); putchar(data); - count = write(serial_fd, &data, 1); - sim_assert(count == 1, "could not write to serial port"); + if (serial_fd) { + ssize_t count; + count = write(serial_fd, &data, 1); + sim_assert(count == 1, "could not write to serial port"); + } } // read/write many characters void serial_writestr(uint8_t *data) { - ssize_t count; const char *str = (char *)data; sim_assert(serial_initialised, "serial interface not initialised"); puts(str); - count = write(serial_fd, str, strlen(str)); - sim_assert(count == strlen(str), "could not write to serial port"); + if (serial_fd) { + ssize_t count; + count = write(serial_fd, str, strlen(str)); + sim_assert(count == strlen(str), "could not write to serial port"); + } } // write from flash