From c5792c2d49d62a777272477a5dc6c73994e08bd3 Mon Sep 17 00:00:00 2001 From: Rob Giseburt Date: Mon, 9 Jan 2017 15:12:13 -0600 Subject: [PATCH] Work on issue #225 - added a `xio_flush_to_command()` and call in in certain conditions --- g2core/canonical_machine.cpp | 1 + g2core/controller.cpp | 2 +- g2core/xio.cpp | 136 +++++++++++++++++++++++++++-------- g2core/xio.h | 1 + 4 files changed, 108 insertions(+), 32 deletions(-) diff --git a/g2core/canonical_machine.cpp b/g2core/canonical_machine.cpp index 1d07d2ae..723705c2 100644 --- a/g2core/canonical_machine.cpp +++ b/g2core/canonical_machine.cpp @@ -823,6 +823,7 @@ void cm_clear() { if (cm.machine_state == MACHINE_ALARM) { cm.machine_state = MACHINE_PROGRAM_STOP; + xio_flush_to_command(); } else if (cm.machine_state == MACHINE_SHUTDOWN) { cm.machine_state = MACHINE_READY; } diff --git a/g2core/controller.cpp b/g2core/controller.cpp index 70fb3378..8ba769ef 100755 --- a/g2core/controller.cpp +++ b/g2core/controller.cpp @@ -236,7 +236,7 @@ static void _dispatch_kernel(const devflags_t flags) // trap single character commands if (*cs.bufp == '!') { cm_request_feedhold(); } - else if (*cs.bufp == '%') { cm_request_queue_flush(); } + else if (*cs.bufp == '%') { cm_request_queue_flush(); xio_flush_to_command(); } else if (*cs.bufp == '~') { cm_request_end_hold(); } else if (*cs.bufp == EOT) { cm_alarm(STAT_KILL_JOB, "EOT Received"); } else if (*cs.bufp == ENQ) { controller_request_enquiry(); } diff --git a/g2core/xio.cpp b/g2core/xio.cpp index 6c2c121d..f0d72670 100755 --- a/g2core/xio.cpp +++ b/g2core/xio.cpp @@ -170,6 +170,7 @@ struct xioDeviceWrapperBase { // C++ base class for device primit virtual int16_t readchar() { return -1; }; virtual void flush() {}; virtual void flushRead() {}; // This should call _flushLine() before flushing the device. + virtual bool flushToCommand() { return false; }; virtual int16_t write(const char *buffer, int16_t len) { return -1; }; virtual char *readline(devflags_t limit_flags, uint16_t &size) { return nullptr; }; @@ -314,6 +315,21 @@ struct xio_t { } } + /* + * flushToCommand() - flush all readable devices' read buffers up to the last returned command + * + * Note that only one device will flush. + * + */ + void flushToCommand() + { + for (int8_t i = 0; i < _dev_count; ++i) { + if (DeviceWrappers[i]->flushToCommand()) { + return; // we only care to flush the one that last returned a control. + } + } + } + /* * readline() - read a complete line from a device * @@ -430,6 +446,8 @@ struct LineRXBuffer : RXBuffer<_size, owner_type, char> { volatile uint16_t _last_scan_offset; // DEBUGGING + bool _last_returned_a_control = false; + LineRXBuffer(owner_type owner) : parent_type{owner} {}; void init() { @@ -678,6 +696,8 @@ struct LineRXBuffer : RXBuffer<_size, owner_type, char> { _restartTransfer(); + _last_returned_a_control = found_control; + char *dst_ptr = _line_buffer; line_size = 0; @@ -729,33 +749,34 @@ struct LineRXBuffer : RXBuffer<_size, owner_type, char> { if (ctrl_is_at_beginning_of_data) { _read_offset = _scan_offset; - } else { - // special case: if the return value is '%' - // then we actually consider everything before it to be read - - if ('%' == _line_buffer[0]) { - // Things that must be managed here: - // * _read_offset -- we're skipping data - // * _lines_found -- we shouldn't have any lines "left" - // * _skip_sections -- there's nothing to skip, we just did - - // Things that won't be changed (further): - // * _scan_offset -- we're not changing past where it's scanned - // * _line_start_offset -- we've already adjusted it - // * _at_start_of_line -- should always be true when we're here - - // move the read buffer up to where we're scanning - _read_offset = _scan_offset; - - // record that we have 0 lines (of data) in the buffer - _lines_found = 0; - - // and clear out any skip sections we have - while (!_skip_sections.is_empty()) { - _skip_sections.pop_skip(); - } - } } +// else { +// // special case: if the return value is '%' +// // then we actually consider everything before it to be read +// +// if ('%' == _line_buffer[0]) { +// // Things that must be managed here: +// // * _read_offset -- we're skipping data +// // * _lines_found -- we shouldn't have any lines "left" +// // * _skip_sections -- there's nothing to skip, we just did +// +// // Things that won't be changed (further): +// // * _scan_offset -- we're not changing past where it's scanned +// // * _line_start_offset -- we've already adjusted it +// // * _at_start_of_line -- should always be true when we're here +// +// // move the read buffer up to where we're scanning +// _read_offset = _scan_offset; +// +// // record that we have 0 lines (of data) in the buffer +// _lines_found = 0; +// +// // and clear out any skip sections we have +// while (!_skip_sections.is_empty()) { +// _skip_sections.pop_skip(); +// } +// } +// } // if (ctrl_is_at_beginning_of_data) { // // attempt to request more data @@ -831,6 +852,7 @@ struct LineRXBuffer : RXBuffer<_size, owner_type, char> { return _line_buffer; }; // readline + // this is called from flushRead() void flush() { parent_type::flush(); @@ -849,6 +871,41 @@ struct LineRXBuffer : RXBuffer<_size, owner_type, char> { } }; // flush + bool flushToCommand() { + if (!_last_returned_a_control) { + return false; + } + + // Things that must be managed here: + // * _read_offset -- we're skipping data + // * _lines_found -- we shouldn't have any lines "left" + // * _skip_sections -- there's nothing to skip, we just did + + // Things that won't be changed (further): + // * _scan_offset -- we're not changing past where it's scanned + // * _line_start_offset -- we've already adjusted it + // * _at_start_of_line -- should always be true when we're here + + // Note that we DO NOT call parent::flush() here. That will toss data + // we haven't scanned yet, beyond where we got the command we want to + // flush to. + + // move the read buffer up to where we ended scanning + _read_offset = _scan_offset; + + // record that we have 0 lines (of data) in the buffer + _lines_found = 0; + + // and clear out any skip sections we have + while (!_skip_sections.is_empty()) { + _skip_sections.pop_skip(); + } + + _last_returned_a_control = false; + + return true; + }; // flush + }; // LineRXBuffer template @@ -888,13 +945,21 @@ struct xioDeviceWrapper : xioDeviceWrapperBase { // describes a device for re return _dev->flush(); } - virtual void flushRead() final { + void flushRead() final { // Flush out any partially or wholly read lines being stored: _rx_buffer.flush(); _flushLine(); return _dev->flushRead(); } + void _flushLine() { + // TODO: Call to flush the RX buffer line structures + }; + + bool flushToCommand() final { + return _rx_buffer.flushToCommand(); + } + virtual int16_t write(const char *buffer, int16_t len) final { if (!isConnected()) { return -1; @@ -911,10 +976,6 @@ struct xioDeviceWrapper : xioDeviceWrapperBase { // describes a device for re return NULL; }; - void _flushLine() { - // TODO: Call to flush the RX buffer line structures - }; - void connectedStateChanged(bool connected) { if (connected) { if (isNotConnected()) { @@ -1127,11 +1188,24 @@ int16_t xio_writeline(const char *buffer, bool only_to_muted /*= false*/) return xio.writeline(buffer, only_to_muted); } +/* + * write() - return true of the device is currently "connected" (there's a fair bit of interpretation) + */ + bool xio_connected() { return xio.connected(); } +/* + * xio_flush_to_command() - clear the last read channel up until the command that was read + */ + +void xio_flush_to_command() { + return xio.flushToCommand(); +} + + /*********************************************************************************** * newlib-nano support functions diff --git a/g2core/xio.h b/g2core/xio.h index b235f7d1..f5c88793 100755 --- a/g2core/xio.h +++ b/g2core/xio.h @@ -119,6 +119,7 @@ size_t xio_write(const char *buffer, size_t size, bool only_to_muted = false); char *xio_readline(devflags_t &flags, uint16_t &size); int16_t xio_writeline(const char *buffer, bool only_to_muted = false); bool xio_connected(); +void xio_flush_to_command(); stat_t xio_set_spi(nvObj_t *nv);