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:
parent
f7ba1e467b
commit
36747e5703
15
README.sim
15
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:
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue