Several fixes to GCodeSender, including compilation on older OS X and DTR reset
This commit is contained in:
parent
e50bbc0245
commit
21a5d6e137
@ -60,7 +60,7 @@ sub new {
|
||||
my ($pos) = @_;
|
||||
|
||||
# delete any pending commands to get a smoother movement
|
||||
$self->purge_queue(1);
|
||||
$self->sender->purge_queue(1);
|
||||
$self->abs_xy_move($pos);
|
||||
});
|
||||
$bed_sizer->Add($canvas, 0, wxEXPAND | wxRIGHT, 3);
|
||||
@ -97,6 +97,7 @@ sub new {
|
||||
my $main_sizer = Wx::BoxSizer->new(wxVERTICAL);
|
||||
$main_sizer->Add($bed_sizer, 1, wxEXPAND | wxALL, 10);
|
||||
$main_sizer->Add($self->CreateButtonSizer(wxCLOSE), 0, wxEXPAND);
|
||||
EVT_BUTTON($self, wxID_CLOSE, sub { $self->Close });
|
||||
|
||||
$self->SetSizer($main_sizer);
|
||||
$self->SetMinSize($self->GetSize);
|
||||
|
@ -10,7 +10,8 @@ use Module::Build::WithXSpp;
|
||||
# _GLIBCXX_USE_C99 : to get the long long type for g++
|
||||
# HAS_BOOL : stops Perl/lib/CORE/handy.h from doing "# define bool char" for MSVC
|
||||
# NOGDI : prevents inclusion of wingdi.h which defines functions Polygon() and Polyline() in global namespace
|
||||
my @cflags = qw(-D_GLIBCXX_USE_C99 -DHAS_BOOL -DNOGDI -DSLIC3RXS);
|
||||
# BOOST_ASIO_DISABLE_KQUEUE : prevents a Boost ASIO bug on OS X: https://svn.boost.org/trac/boost/ticket/5339
|
||||
my @cflags = qw(-D_GLIBCXX_USE_C99 -DHAS_BOOL -DNOGDI -DSLIC3RXS -DBOOST_ASIO_DISABLE_KQUEUE);
|
||||
|
||||
my @INC = qw();
|
||||
my @LIBS = qw();
|
||||
|
@ -36,6 +36,8 @@ GCodeSender::~GCodeSender()
|
||||
bool
|
||||
GCodeSender::connect(std::string devname, unsigned int baud_rate)
|
||||
{
|
||||
this->disconnect();
|
||||
|
||||
this->set_error_status(false);
|
||||
try {
|
||||
this->serial.open(devname);
|
||||
@ -57,6 +59,7 @@ GCodeSender::connect(std::string devname, unsigned int baud_rate)
|
||||
// set baud rate again because set_option overwrote it
|
||||
this->set_baud_rate(baud_rate);
|
||||
this->open = true;
|
||||
this->reset();
|
||||
|
||||
// this gives some work to the io_service before it is started
|
||||
// (post() runs the supplied function in its thread)
|
||||
@ -117,7 +120,6 @@ void
|
||||
GCodeSender::disconnect()
|
||||
{
|
||||
if (!this->open) return;
|
||||
|
||||
this->open = false;
|
||||
this->connected = false;
|
||||
this->io.post(boost::bind(&GCodeSender::do_close, this));
|
||||
@ -262,73 +264,81 @@ GCodeSender::on_read(const boost::system::error_code& error,
|
||||
{
|
||||
this->set_error_status(false);
|
||||
if (error) {
|
||||
// error can be true even because the serial port was closed.
|
||||
// In this case it is not a real error, so ignore.
|
||||
if (this->open) {
|
||||
this->do_close();
|
||||
this->set_error_status(true);
|
||||
if (error.value() == 45) {
|
||||
// OS X bug: http://osdir.com/ml/lib.boost.asio.user/2008-08/msg00004.html
|
||||
this->do_read();
|
||||
} else {
|
||||
// printf("ERROR: [%d] %s\n", error.value(), error.message().c_str());
|
||||
// error can be true even because the serial port was closed.
|
||||
// In this case it is not a real error, so ignore.
|
||||
if (this->open) {
|
||||
this->do_close();
|
||||
this->set_error_status(true);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// copy the read buffer into string
|
||||
std::istream is(&this->read_buffer);
|
||||
std::string line;
|
||||
std::getline(is, line);
|
||||
// note that line might contain \r at its end
|
||||
|
||||
// parse incoming line
|
||||
if (!this->connected
|
||||
&& (boost::starts_with(line, "start")
|
||||
|| boost::starts_with(line, "Grbl "))) {
|
||||
this->connected = true;
|
||||
{
|
||||
boost::lock_guard<boost::mutex> l(this->queue_mutex);
|
||||
this->can_send = true;
|
||||
}
|
||||
this->send();
|
||||
} else if (boost::starts_with(line, "ok")) {
|
||||
{
|
||||
boost::lock_guard<boost::mutex> l(this->queue_mutex);
|
||||
this->can_send = true;
|
||||
}
|
||||
this->send();
|
||||
} else if (boost::istarts_with(line, "resend") // Marlin uses "Resend: "
|
||||
|| boost::istarts_with(line, "rs")) {
|
||||
// extract the first number from line
|
||||
boost::algorithm::trim_left_if(line, !boost::algorithm::is_digit());
|
||||
size_t toresend = boost::lexical_cast<size_t>(line.substr(0, line.find_first_not_of("0123456789")));
|
||||
if (toresend == this->sent) {
|
||||
if (!line.empty()) {
|
||||
// note that line might contain \r at its end
|
||||
// parse incoming line
|
||||
if (!this->connected
|
||||
&& (boost::starts_with(line, "start")
|
||||
|| boost::starts_with(line, "Grbl ")
|
||||
|| boost::starts_with(line, "ok")
|
||||
|| boost::contains(line, "T:"))) {
|
||||
this->connected = true;
|
||||
{
|
||||
boost::lock_guard<boost::mutex> l(this->queue_mutex);
|
||||
this->priqueue.push(this->last_sent);
|
||||
this->sent--; // resend it with the same line number
|
||||
this->can_send = true;
|
||||
}
|
||||
this->send();
|
||||
} else if (boost::starts_with(line, "ok")) {
|
||||
{
|
||||
boost::lock_guard<boost::mutex> l(this->queue_mutex);
|
||||
this->can_send = true;
|
||||
}
|
||||
this->send();
|
||||
} else if (boost::istarts_with(line, "resend") // Marlin uses "Resend: "
|
||||
|| boost::istarts_with(line, "rs")) {
|
||||
// extract the first number from line
|
||||
boost::algorithm::trim_left_if(line, !boost::algorithm::is_digit());
|
||||
size_t toresend = boost::lexical_cast<size_t>(line.substr(0, line.find_first_not_of("0123456789")));
|
||||
if (toresend == this->sent) {
|
||||
{
|
||||
boost::lock_guard<boost::mutex> l(this->queue_mutex);
|
||||
this->priqueue.push(this->last_sent);
|
||||
this->sent--; // resend it with the same line number
|
||||
this->can_send = true;
|
||||
}
|
||||
this->send();
|
||||
} else {
|
||||
printf("Cannot resend %lu (last was %lu)\n", toresend, this->sent);
|
||||
}
|
||||
} else if (boost::starts_with(line, "wait")) {
|
||||
// ignore
|
||||
} else {
|
||||
printf("Cannot resend %lu (last was %lu)\n", toresend, this->sent);
|
||||
}
|
||||
} else if (boost::starts_with(line, "wait")) {
|
||||
// ignore
|
||||
} else {
|
||||
// push any other line into the log
|
||||
boost::lock_guard<boost::mutex> l(this->log_mutex);
|
||||
this->log.push(line);
|
||||
}
|
||||
|
||||
// parse temperature info
|
||||
{
|
||||
size_t pos = line.find("T:");
|
||||
if (pos != std::string::npos && line.size() > pos + 2) {
|
||||
// we got temperature info
|
||||
// push any other line into the log
|
||||
boost::lock_guard<boost::mutex> l(this->log_mutex);
|
||||
this->T = line.substr(pos+2, line.find_first_not_of("0123456789.", pos+2) - (pos+2));
|
||||
|
||||
pos = line.find("B:");
|
||||
this->log.push(line);
|
||||
}
|
||||
|
||||
// parse temperature info
|
||||
{
|
||||
size_t pos = line.find("T:");
|
||||
if (pos != std::string::npos && line.size() > pos + 2) {
|
||||
// we got bed temperature info
|
||||
this->B = line.substr(pos+2, line.find_first_not_of("0123456789.", pos+2) - (pos+2));
|
||||
// we got temperature info
|
||||
boost::lock_guard<boost::mutex> l(this->log_mutex);
|
||||
this->T = line.substr(pos+2, line.find_first_not_of("0123456789.", pos+2) - (pos+2));
|
||||
|
||||
pos = line.find("B:");
|
||||
if (pos != std::string::npos && line.size() > pos + 2) {
|
||||
// we got bed temperature info
|
||||
this->B = line.substr(pos+2, line.find_first_not_of("0123456789.", pos+2) - (pos+2));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -370,6 +380,12 @@ GCodeSender::send(const std::string &line, bool priority)
|
||||
|
||||
void
|
||||
GCodeSender::send()
|
||||
{
|
||||
this->io.post(boost::bind(&GCodeSender::do_send, this));
|
||||
}
|
||||
|
||||
void
|
||||
GCodeSender::do_send()
|
||||
{
|
||||
boost::lock_guard<boost::mutex> l(this->queue_mutex);
|
||||
|
||||
@ -414,15 +430,47 @@ GCodeSender::do_send(const std::string &line)
|
||||
cs = cs ^ *it;
|
||||
|
||||
// write line to device
|
||||
asio::streambuf b;
|
||||
std::ostream os(&b);
|
||||
os << full_line << "*" << cs << "\n";
|
||||
asio::write(this->serial, b);
|
||||
full_line += "*";
|
||||
full_line += boost::lexical_cast<std::string>(cs);
|
||||
full_line += "\n";
|
||||
asio::async_write(this->serial, asio::buffer(full_line), boost::bind(&GCodeSender::do_send, this));
|
||||
|
||||
this->last_sent = line;
|
||||
this->can_send = false;
|
||||
}
|
||||
|
||||
void
|
||||
GCodeSender::set_DTR(bool on)
|
||||
{
|
||||
#if defined(_WIN32) && !defined(__SYMBIAN32__)
|
||||
asio::serial_port_service::native_handle_type handle = this->serial.native_handle();
|
||||
if (on)
|
||||
EscapeCommFunction(handle, SETDTR);
|
||||
else
|
||||
EscapeCommFunction(handle, CLRDTR);
|
||||
#else
|
||||
int fd = this->serial.native_handle();
|
||||
int status;
|
||||
ioctl(fd, TIOCMGET, &status);
|
||||
if (on)
|
||||
status |= TIOCM_DTR;
|
||||
else
|
||||
status &= ~TIOCM_DTR;
|
||||
ioctl(fd, TIOCMSET, &status);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
GCodeSender::reset()
|
||||
{
|
||||
this->set_DTR(false);
|
||||
boost::this_thread::sleep(boost::posix_time::milliseconds(200));
|
||||
this->set_DTR(true);
|
||||
boost::this_thread::sleep(boost::posix_time::milliseconds(200));
|
||||
this->set_DTR(false);
|
||||
boost::this_thread::sleep(boost::posix_time::milliseconds(1000));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#ifdef SLIC3RXS
|
||||
|
@ -32,6 +32,8 @@ class GCodeSender : private boost::noncopyable {
|
||||
std::vector<std::string> purge_log();
|
||||
std::string getT() const;
|
||||
std::string getB() const;
|
||||
void set_DTR(bool on);
|
||||
void reset();
|
||||
|
||||
private:
|
||||
asio::io_service io;
|
||||
@ -58,6 +60,7 @@ class GCodeSender : private boost::noncopyable {
|
||||
|
||||
void set_baud_rate(unsigned int baud_rate);
|
||||
void set_error_status(bool e);
|
||||
void do_send();
|
||||
void do_send(const std::string &line);
|
||||
void do_close();
|
||||
void do_read();
|
||||
|
Loading…
Reference in New Issue
Block a user