Skip to content

Commit

Permalink
post-merge tweaks
Browse files Browse the repository at this point in the history
  • Loading branch information
thinkyhead committed Mar 29, 2021
1 parent ee22d10 commit f76d21b
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 35 deletions.
2 changes: 1 addition & 1 deletion Marlin/src/core/serial.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ inline void SERIAL_ECHO(serial_char_t x) { SERIAL_IMPL.write(x.c); }
#define AS_CHAR(C) serial_char_t(C)

// SERIAL_ECHO_F prints a floating point value with optional precision
inline void SERIAL_ECHO_F(EnsureDouble x, int digit = 2) { SERIAL_IMPL.print(x, digit); }
inline void SERIAL_ECHO_F(EnsureDouble x, int digit=2) { SERIAL_IMPL.print(x, digit); }

template <typename T>
void SERIAL_ECHOLN(T x) { SERIAL_IMPL.println(x); }
Expand Down
44 changes: 29 additions & 15 deletions Marlin/src/core/serial_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ CALL_IF_EXISTS_IMPL(void, flushTX);
CALL_IF_EXISTS_IMPL(bool, connected, true);
CALL_IF_EXISTS_IMPL(SerialFeature, features, SerialFeature::None);

// A simple forward struct that prevent the compiler to select print(double, int) as a default overload for
// any type other than double/float. For double/float, a conversion exists so the call will be invisible.
// A simple forward struct to prevent the compiler from selecting print(double, int) as a default overload
// for any type other than double/float. For double/float, a conversion exists so the call will be invisible.
struct EnsureDouble {
double a;
FORCE_INLINE operator double() { return a; }
Expand All @@ -96,30 +96,44 @@ struct SerialBase {
SerialBase(const bool) {}
#endif

#define SerialChild static_cast<Child*>(this)

// Static dispatch methods below:
// The most important method here is where it all ends to:
size_t write(uint8_t c) { return static_cast<Child*>(this)->write(c); }
size_t write(uint8_t c) { return SerialChild->write(c); }

// Called when the parser finished processing an instruction, usually build to nothing
void msgDone() { static_cast<Child*>(this)->msgDone(); }
// Called upon initialization
void begin(const long baudRate) { static_cast<Child*>(this)->begin(baudRate); }
// Called upon destruction
void end() { static_cast<Child*>(this)->end(); }
void msgDone() const { SerialChild->msgDone(); }

// Called on initialization
void begin(const long baudRate) { SerialChild->begin(baudRate); }

// Called on destruction
void end() { SerialChild->end(); }

/** Check for available data from the port
@param index The port index, usually 0 */
int available(serial_index_t index = 0) { return static_cast<Child*>(this)->available(index); }
int available(serial_index_t index=0) const { return SerialChild->available(index); }

/** Read a value from the port
@param index The port index, usually 0 */
int read(serial_index_t index = 0) { return static_cast<Child*>(this)->read(index); }
/** Combine the feature of this serial instance and returns it
int read(serial_index_t index=0) { return SerialChild->read(index); }

/** Combine the features of this serial instance and return it
@param index The port index, usually 0 */
SerialFeature features(serial_index_t index = 0) const { return static_cast<const Child*>(this)->features(index); }
SerialFeature features(serial_index_t index=0) const { return static_cast<const Child*>(this)->features(index); }

// Check if the serial port has a feature
bool has_feature(serial_index_t index, SerialFeature flag) { (features(index) & flag) != 0; }

// Check if the serial port is connected (usually bypassed)
bool connected() { return static_cast<Child*>(this)->connected(); }
bool connected() const { return SerialChild->connected(); }

// Redirect flush
void flush() { static_cast<Child*>(this)->flush(); }
void flush() { SerialChild->flush(); }

// Not all implementation have a flushTX, so let's call them only if the child has the implementation
void flushTX() { CALL_IF_EXISTS(void, static_cast<Child*>(this), flushTX); }
void flushTX() { CALL_IF_EXISTS(void, SerialChild, flushTX); }

// Glue code here
FORCE_INLINE void write(const char* str) { while (*str) write(*str++); }
Expand Down
36 changes: 19 additions & 17 deletions Marlin/src/core/serial_hook.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,12 @@ struct BaseSerial : public SerialBase< BaseSerial<SerialT> >, public SerialT {
void msgDone() {}

// We don't care about indices here, since if one can call us, it's the right index anyway
int available(serial_index_t) { return (int)SerialT::available(); }
int read(serial_index_t) { return (int)SerialT::read(); }
bool connected() { return CALL_IF_EXISTS(bool, static_cast<SerialT*>(this), connected);; }
void flushTX() { CALL_IF_EXISTS(void, static_cast<SerialT*>(this), flushTX); }

SerialFeature features(serial_index_t index) const { return CALL_IF_EXISTS(SerialFeature, static_cast<const SerialT*>(this), features, index); }
int available(serial_index_t) { return (int)SerialT::available(); }
int read(serial_index_t) { return (int)SerialT::read(); }
bool connected() { return CALL_IF_EXISTS(bool, static_cast<SerialT*>(this), connected);; }
void flushTX() { CALL_IF_EXISTS(void, static_cast<SerialT*>(this), flushTX); }

SerialFeature features(serial_index_t index) const { return CALL_IF_EXISTS(SerialFeature, static_cast<const SerialT*>(this), features, index); }

// We have 2 implementation of the same method in both base class, let's say which one we want
using SerialT::available;
Expand Down Expand Up @@ -101,8 +100,8 @@ struct ConditionalSerial : public SerialBase< ConditionalSerial<SerialT> > {
bool connected() { return CALL_IF_EXISTS(bool, &out, connected); }
void flushTX() { CALL_IF_EXISTS(void, &out, flushTX); }

int available(serial_index_t ) { return (int)out.available(); }
int read(serial_index_t ) { return (int)out.read(); }
int available(serial_index_t) { return (int)out.available(); }
int read(serial_index_t) { return (int)out.read(); }
int available() { return (int)out.available(); }
int read() { return (int)out.read(); }
SerialFeature features(serial_index_t index) const { return CALL_IF_EXISTS(SerialFeature, &out, features, index); }
Expand All @@ -123,13 +122,13 @@ struct ForwardSerial : public SerialBase< ForwardSerial<SerialT> > {

void msgDone() {}
// Existing instances implement Arduino's operator bool, so use that if it's available
bool connected() { return Private::HasMember_connected<SerialT>::value ? CALL_IF_EXISTS(bool, &out, connected) : (bool)out; }
void flushTX() { CALL_IF_EXISTS(void, &out, flushTX); }
bool connected() { return Private::HasMember_connected<SerialT>::value ? CALL_IF_EXISTS(bool, &out, connected) : (bool)out; }
void flushTX() { CALL_IF_EXISTS(void, &out, flushTX); }

int available(serial_index_t) { return (int)out.available(); }
int read(serial_index_t) { return (int)out.read(); }
int available() { return (int)out.available(); }
int read() { return (int)out.read(); }
int available(serial_index_t) { return (int)out.available(); }
int read(serial_index_t) { return (int)out.read(); }
int available() { return (int)out.available(); }
int read() { return (int)out.read(); }
SerialFeature features(serial_index_t index) const { return CALL_IF_EXISTS(SerialFeature, &out, features, index); }

ForwardSerial(const bool e, SerialT & out) : BaseClassT(e), out(out) {}
Expand Down Expand Up @@ -168,13 +167,16 @@ struct RuntimeSerial : public SerialBase< RuntimeSerial<SerialT> >, public Seria

// Underlying implementation might use Arduino's bool operator
bool connected() {
return Private::HasMember_connected<SerialT>::value ? CALL_IF_EXISTS(bool, static_cast<SerialT*>(this), connected) : static_cast<SerialT*>(this)->operator bool();
return Private::HasMember_connected<SerialT>::value
? CALL_IF_EXISTS(bool, static_cast<SerialT*>(this), connected)
: static_cast<SerialT*>(this)->operator bool();
}
void flushTX() { CALL_IF_EXISTS(void, static_cast<SerialT*>(this), flushTX); }

void flushTX() { CALL_IF_EXISTS(void, static_cast<SerialT*>(this), flushTX); }

// Append Hookable for this class
SerialFeature features(serial_index_t index) const { return SerialFeature::Hookable | CALL_IF_EXISTS(SerialFeature, static_cast<const SerialT*>(this), features, index); }


void setHook(WriteHook writeHook = 0, EndOfMessageHook eofHook = 0, void * userPointer = 0) {
// Order is important here as serial code can be called inside interrupts
// When setting a hook, the user pointer must be set first so if writeHook is called as soon as it's set, it'll be valid
Expand Down
7 changes: 5 additions & 2 deletions Marlin/src/gcode/host/M115.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ void GcodeSuite::M115() {

#if ENABLED(EXTENDED_CAPABILITIES_REPORT)

// The port that sent M115
serial_index_t port = queue.ring_buffer.command_port();

// PAREN_COMMENTS
TERN_(PAREN_COMMENTS, cap_line(PSTR("PAREN_COMMENTS"), true));

Expand All @@ -71,7 +74,7 @@ void GcodeSuite::M115() {
cap_line(PSTR("SERIAL_XON_XOFF"), ENABLED(SERIAL_XON_XOFF));

// BINARY_FILE_TRANSFER (M28 B1)
cap_line(PSTR("BINARY_FILE_TRANSFER"), ENABLED(BINARY_FILE_TRANSFER)); // TODO: Replace by (SERIAL_IMPL.features(queue.ring_buffer.command_port()) & SerialFeature::BinaryFileTransfer) == SerialFeature::BinaryFileTransfer once it'll be implemented
cap_line(PSTR("BINARY_FILE_TRANSFER"), ENABLED(BINARY_FILE_TRANSFER)); // TODO: Use SERIAL_IMPL.has_feature(port, SerialFeature::BinaryFileTransfer) once implemented

// EEPROM (M500, M501)
cap_line(PSTR("EEPROM"), ENABLED(EEPROM_SETTINGS));
Expand Down Expand Up @@ -150,7 +153,7 @@ void GcodeSuite::M115() {
cap_line(PSTR("COOLER_TEMPERATURE"), ENABLED(HAS_COOLER));

// MEATPACK Compression
cap_line(PSTR("MEATPACK"), (SERIAL_IMPL.features(queue.ring_buffer.command_port()) & SerialFeature::MeatPack) == SerialFeature::MeatPack);
cap_line(PSTR("MEATPACK"), SERIAL_IMPL.has_feature(port, SerialFeature::MeatPack));

// Machine Geometry
#if ENABLED(M115_GEOMETRY_REPORT)
Expand Down

0 comments on commit f76d21b

Please sign in to comment.