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.
This commit is contained in:
Phil Hord 2013-11-12 11:30:09 -05:00 committed by Markus Hitter
parent f7ba1e467b
commit 36747e5703
2 changed files with 85 additions and 21 deletions

View File

@ -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:

View File

@ -4,6 +4,9 @@
#include <sys/ioctl.h>
#include <termios.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#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