Support a third serial port (#21784)
This commit is contained in:
parent
be6fbc76a1
commit
02405add76
|
@ -111,6 +111,13 @@
|
||||||
*/
|
*/
|
||||||
//#define SERIAL_PORT_2 -1
|
//#define SERIAL_PORT_2 -1
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Select a third serial port on the board to use for communication with the host.
|
||||||
|
* Currently only supported for AVR, DUE, LPC1768/9 and STM32/STM32F1
|
||||||
|
* :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
|
||||||
|
*/
|
||||||
|
//#define SERIAL_PORT_3 1
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This setting determines the communication speed of the printer.
|
* This setting determines the communication speed of the printer.
|
||||||
*
|
*
|
||||||
|
|
|
@ -103,6 +103,13 @@ typedef int8_t pin_t;
|
||||||
#endif
|
#endif
|
||||||
#define MYSERIAL2 customizedSerial2
|
#define MYSERIAL2 customizedSerial2
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef SERIAL_PORT_3
|
||||||
|
#if !WITHIN(SERIAL_PORT_3, -1, 3)
|
||||||
|
#error "SERIAL_PORT_3 must be from 0 to 3, or -1 for USB Serial."
|
||||||
|
#endif
|
||||||
|
#define MYSERIAL3 customizedSerial3
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef MMU2_SERIAL_PORT
|
#ifdef MMU2_SERIAL_PORT
|
||||||
|
|
|
@ -585,6 +585,22 @@ MSerialT1 customizedSerial1(MSerialT1::HasEmergencyParser);
|
||||||
|
|
||||||
#endif // SERIAL_PORT_2
|
#endif // SERIAL_PORT_2
|
||||||
|
|
||||||
|
#ifdef SERIAL_PORT_3
|
||||||
|
|
||||||
|
// Hookup ISR handlers
|
||||||
|
ISR(SERIAL_REGNAME(USART, SERIAL_PORT_3, _RX_vect)) {
|
||||||
|
MarlinSerial<MarlinSerialCfg<SERIAL_PORT_3>>::store_rxd_char();
|
||||||
|
}
|
||||||
|
|
||||||
|
ISR(SERIAL_REGNAME(USART, SERIAL_PORT_3, _UDRE_vect)) {
|
||||||
|
MarlinSerial<MarlinSerialCfg<SERIAL_PORT_3>>::_tx_udr_empty_irq();
|
||||||
|
}
|
||||||
|
|
||||||
|
template class MarlinSerial< MarlinSerialCfg<SERIAL_PORT_3> >;
|
||||||
|
MSerialT3 customizedSerial3(MSerialT3::HasEmergencyParser);
|
||||||
|
|
||||||
|
#endif // SERIAL_PORT_3
|
||||||
|
|
||||||
#ifdef MMU2_SERIAL_PORT
|
#ifdef MMU2_SERIAL_PORT
|
||||||
|
|
||||||
ISR(SERIAL_REGNAME(USART, MMU2_SERIAL_PORT, _RX_vect)) {
|
ISR(SERIAL_REGNAME(USART, MMU2_SERIAL_PORT, _RX_vect)) {
|
||||||
|
|
|
@ -246,6 +246,11 @@
|
||||||
extern MSerialT2 customizedSerial2;
|
extern MSerialT2 customizedSerial2;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef SERIAL_PORT_3
|
||||||
|
typedef Serial1Class< MarlinSerial< MarlinSerialCfg<SERIAL_PORT_3> > > MSerialT3;
|
||||||
|
extern MSerialT3 customizedSerial3;
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // !USBCON
|
#endif // !USBCON
|
||||||
|
|
||||||
#ifdef MMU2_SERIAL_PORT
|
#ifdef MMU2_SERIAL_PORT
|
||||||
|
|
|
@ -68,6 +68,16 @@ extern DefaultSerial4 MSerial3;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef SERIAL_PORT_3
|
||||||
|
#if SERIAL_PORT_3 == -1 || ENABLED(EMERGENCY_PARSER)
|
||||||
|
#define MYSERIAL3 customizedSerial3
|
||||||
|
#elif WITHIN(SERIAL_PORT_3, 0, 3)
|
||||||
|
#define MYSERIAL3 MSERIAL(SERIAL_PORT_3)
|
||||||
|
#else
|
||||||
|
#error "SERIAL_PORT_3 must be from 0 to 3, or -1 for USB Serial."
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef MMU2_SERIAL_PORT
|
#ifdef MMU2_SERIAL_PORT
|
||||||
#if WITHIN(MMU2_SERIAL_PORT, 0, 3)
|
#if WITHIN(MMU2_SERIAL_PORT, 0, 3)
|
||||||
#define MMU2_SERIAL MSERIAL(MMU2_SERIAL_PORT)
|
#define MMU2_SERIAL MSERIAL(MMU2_SERIAL_PORT)
|
||||||
|
|
|
@ -486,4 +486,9 @@ void MarlinSerial<Cfg>::flushTX() {
|
||||||
MSerialT2 customizedSerial2(MarlinSerialCfg<SERIAL_PORT_2>::EMERGENCYPARSER);
|
MSerialT2 customizedSerial2(MarlinSerialCfg<SERIAL_PORT_2>::EMERGENCYPARSER);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(SERIAL_PORT_3) && SERIAL_PORT_3 >= 0
|
||||||
|
template class MarlinSerial< MarlinSerialCfg<SERIAL_PORT_3> >;
|
||||||
|
MSerialT3 customizedSerial3(MarlinSerialCfg<SERIAL_PORT_3>::EMERGENCYPARSER);
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // ARDUINO_ARCH_SAM
|
#endif // ARDUINO_ARCH_SAM
|
||||||
|
|
|
@ -149,3 +149,8 @@ struct MarlinSerialCfg {
|
||||||
typedef Serial1Class< MarlinSerial< MarlinSerialCfg<SERIAL_PORT_2> > > MSerialT2;
|
typedef Serial1Class< MarlinSerial< MarlinSerialCfg<SERIAL_PORT_2> > > MSerialT2;
|
||||||
extern MSerialT2 customizedSerial2;
|
extern MSerialT2 customizedSerial2;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(SERIAL_PORT_3) && SERIAL_PORT_3 >= 0
|
||||||
|
typedef Serial1Class< MarlinSerial< MarlinSerialCfg<SERIAL_PORT_3> > > MSerialT3;
|
||||||
|
extern MSerialT3 customizedSerial3;
|
||||||
|
#endif
|
||||||
|
|
|
@ -134,6 +134,9 @@ size_t MarlinSerialUSB::write(const uint8_t c) {
|
||||||
#if SERIAL_PORT_2 == -1
|
#if SERIAL_PORT_2 == -1
|
||||||
MSerialT2 customizedSerial2(TERN0(EMERGENCY_PARSER, true));
|
MSerialT2 customizedSerial2(TERN0(EMERGENCY_PARSER, true));
|
||||||
#endif
|
#endif
|
||||||
|
#if SERIAL_PORT_3 == -1
|
||||||
|
MSerialT3 customizedSerial3(TERN0(EMERGENCY_PARSER, true));
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // HAS_USB_SERIAL
|
#endif // HAS_USB_SERIAL
|
||||||
#endif // ARDUINO_ARCH_SAM
|
#endif // ARDUINO_ARCH_SAM
|
||||||
|
|
|
@ -59,3 +59,7 @@ struct MarlinSerialUSB {
|
||||||
extern MSerialT2 customizedSerial2;
|
extern MSerialT2 customizedSerial2;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if SERIAL_PORT_3 == -1
|
||||||
|
typedef Serial1Class<MarlinSerialUSB> MSerialT3;
|
||||||
|
extern MSerialT3 customizedSerial3;
|
||||||
|
#endif
|
||||||
|
|
|
@ -84,6 +84,16 @@ extern DefaultSerial1 USBSerial;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef SERIAL_PORT_3
|
||||||
|
#if SERIAL_PORT_3 == -1
|
||||||
|
#define MYSERIAL3 USBSerial
|
||||||
|
#elif WITHIN(SERIAL_PORT_3, 0, 3)
|
||||||
|
#define MYSERIAL3 MSERIAL(SERIAL_PORT_3)
|
||||||
|
#else
|
||||||
|
#error "SERIAL_PORT_3 must be from 0 to 3. You can also use -1 if the board supports Native USB."
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef MMU2_SERIAL_PORT
|
#ifdef MMU2_SERIAL_PORT
|
||||||
#if MMU2_SERIAL_PORT == -1
|
#if MMU2_SERIAL_PORT == -1
|
||||||
#define MMU2_SERIAL USBSerial
|
#define MMU2_SERIAL USBSerial
|
||||||
|
|
|
@ -68,6 +68,16 @@
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef SERIAL_PORT_3
|
||||||
|
#if SERIAL_PORT_3 == -1
|
||||||
|
#define MYSERIAL3 MSerial0
|
||||||
|
#elif WITHIN(SERIAL_PORT_3, 1, 6)
|
||||||
|
#define MYSERIAL3 MSERIAL(SERIAL_PORT_3)
|
||||||
|
#else
|
||||||
|
#error "SERIAL_PORT_3 must be from 1 to 6. You can also use -1 if the board supports Native USB."
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef MMU2_SERIAL_PORT
|
#ifdef MMU2_SERIAL_PORT
|
||||||
#if MMU2_SERIAL_PORT == -1
|
#if MMU2_SERIAL_PORT == -1
|
||||||
#define MMU2_SERIAL MSerial0
|
#define MMU2_SERIAL MSerial0
|
||||||
|
|
|
@ -98,6 +98,17 @@
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef SERIAL_PORT_3
|
||||||
|
#if SERIAL_PORT_3 == -1
|
||||||
|
#define MYSERIAL3 UsbSerial
|
||||||
|
#elif WITHIN(SERIAL_PORT_3, 1, NUM_UARTS)
|
||||||
|
#define MYSERIAL3 MSERIAL(SERIAL_PORT_3)
|
||||||
|
#else
|
||||||
|
#define MYSERIAL3 MSERIAL(1) // dummy port
|
||||||
|
static_assert(false, "SERIAL_PORT_3 must be from 1 to " STRINGIFY(NUM_UARTS) ". You can also use -1 if the board supports Native USB.")
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef MMU2_SERIAL_PORT
|
#ifdef MMU2_SERIAL_PORT
|
||||||
#if MMU2_SERIAL_PORT == -1
|
#if MMU2_SERIAL_PORT == -1
|
||||||
#define MMU2_SERIAL UsbSerial
|
#define MMU2_SERIAL UsbSerial
|
||||||
|
|
|
@ -1075,6 +1075,11 @@ void setup() {
|
||||||
MYSERIAL2.begin(BAUDRATE);
|
MYSERIAL2.begin(BAUDRATE);
|
||||||
serial_connect_timeout = millis() + 1000UL;
|
serial_connect_timeout = millis() + 1000UL;
|
||||||
while (!MYSERIAL2.connected() && PENDING(millis(), serial_connect_timeout)) { /*nada*/ }
|
while (!MYSERIAL2.connected() && PENDING(millis(), serial_connect_timeout)) { /*nada*/ }
|
||||||
|
#ifdef SERIAL_PORT_3
|
||||||
|
MYSERIAL3.begin(BAUDRATE);
|
||||||
|
serial_connect_timeout = millis() + 1000UL;
|
||||||
|
while (!MYSERIAL3.connected() && PENDING(millis(), serial_connect_timeout)) { /*nada*/ }
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
SERIAL_ECHOLNPGM("start");
|
SERIAL_ECHOLNPGM("start");
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,9 @@ PGMSTR(SP_X_LBL, " X:"); PGMSTR(SP_Y_LBL, " Y:"); PGMSTR(SP_Z_LBL, " Z:"); PGMST
|
||||||
#if ENABLED(MEATPACK_ON_SERIAL_PORT_2)
|
#if ENABLED(MEATPACK_ON_SERIAL_PORT_2)
|
||||||
SerialLeafT2 mpSerial2(false, _SERIAL_LEAF_2);
|
SerialLeafT2 mpSerial2(false, _SERIAL_LEAF_2);
|
||||||
#endif
|
#endif
|
||||||
|
#if ENABLED(MEATPACK_ON_SERIAL_PORT_3)
|
||||||
|
SerialLeafT3 mpSerial3(false, _SERIAL_LEAF_3);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Step 2: For multiserial, handle the second serial port as well
|
// Step 2: For multiserial, handle the second serial port as well
|
||||||
#if HAS_MULTI_SERIAL
|
#if HAS_MULTI_SERIAL
|
||||||
|
@ -52,7 +55,14 @@ PGMSTR(SP_X_LBL, " X:"); PGMSTR(SP_Y_LBL, " Y:"); PGMSTR(SP_Z_LBL, " Z:"); PGMST
|
||||||
SerialLeafT2 msSerial2(ethernet.have_telnet_client, MYSERIAL2, false);
|
SerialLeafT2 msSerial2(ethernet.have_telnet_client, MYSERIAL2, false);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
SerialOutputT multiSerial(SERIAL_LEAF_1, SERIAL_LEAF_2);
|
#define __S_LEAF(N) ,SERIAL_LEAF_##N
|
||||||
|
#define _S_LEAF(N) __S_LEAF(N)
|
||||||
|
|
||||||
|
SerialOutputT multiSerial( SERIAL_LEAF_1 REPEAT_S(2, INCREMENT(NUM_SERIAL), _S_LEAF) );
|
||||||
|
|
||||||
|
#undef __S_LEAF
|
||||||
|
#undef _S_LEAF
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void serialprintPGM(PGM_P str) {
|
void serialprintPGM(PGM_P str) {
|
||||||
|
|
|
@ -95,6 +95,9 @@ extern uint8_t marlin_debug_flags;
|
||||||
#define _SERIAL_LEAF_2 MYSERIAL2 // Don't create a useless instance here, directly use the existing instance
|
#define _SERIAL_LEAF_2 MYSERIAL2 // Don't create a useless instance here, directly use the existing instance
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Nothing complicated here
|
||||||
|
#define _SERIAL_LEAF_3 MYSERIAL3
|
||||||
|
|
||||||
// Hook Meatpack if it's enabled on the second leaf
|
// Hook Meatpack if it's enabled on the second leaf
|
||||||
#if ENABLED(MEATPACK_ON_SERIAL_PORT_2)
|
#if ENABLED(MEATPACK_ON_SERIAL_PORT_2)
|
||||||
typedef MeatpackSerial<decltype(_SERIAL_LEAF_2)> SerialLeafT2;
|
typedef MeatpackSerial<decltype(_SERIAL_LEAF_2)> SerialLeafT2;
|
||||||
|
@ -104,7 +107,23 @@ extern uint8_t marlin_debug_flags;
|
||||||
#define SERIAL_LEAF_2 _SERIAL_LEAF_2
|
#define SERIAL_LEAF_2 _SERIAL_LEAF_2
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef MultiSerial<decltype(SERIAL_LEAF_1), decltype(SERIAL_LEAF_2), 0> SerialOutputT;
|
// Hook Meatpack if it's enabled on the third leaf
|
||||||
|
#if ENABLED(MEATPACK_ON_SERIAL_PORT_3)
|
||||||
|
typedef MeatpackSerial<decltype(_SERIAL_LEAF_3)> SerialLeafT3;
|
||||||
|
extern SerialLeafT3 mpSerial3;
|
||||||
|
#define SERIAL_LEAF_3 mpSerial3
|
||||||
|
#else
|
||||||
|
#define SERIAL_LEAF_3 _SERIAL_LEAF_3
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define __S_MULTI(N) decltype(SERIAL_LEAF_##N),
|
||||||
|
#define _S_MULTI(N) __S_MULTI(N)
|
||||||
|
|
||||||
|
typedef MultiSerial< REPEAT_S(1, INCREMENT(NUM_SERIAL), _S_MULTI) 0> SerialOutputT;
|
||||||
|
|
||||||
|
#undef __S_MULTI
|
||||||
|
#undef _S_MULTI
|
||||||
|
|
||||||
extern SerialOutputT multiSerial;
|
extern SerialOutputT multiSerial;
|
||||||
#define SERIAL_IMPL multiSerial
|
#define SERIAL_IMPL multiSerial
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -195,54 +195,71 @@ struct RuntimeSerial : public SerialBase< RuntimeSerial<SerialT> >, public Seria
|
||||||
RuntimeSerial(const bool e, Args... args) : BaseClassT(e), SerialT(args...), writeHook(0), eofHook(0), userPointer(0) {}
|
RuntimeSerial(const bool e, Args... args) : BaseClassT(e), SerialT(args...), writeHook(0), eofHook(0), userPointer(0) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// A class that duplicates its output conditionally to 2 serial interfaces
|
#define _S_CLASS(N) class Serial##N##T,
|
||||||
template <class Serial0T, class Serial1T, const uint8_t offset = 0, const uint8_t step = 1>
|
#define _S_NAME(N) Serial##N##T,
|
||||||
struct MultiSerial : public SerialBase< MultiSerial<Serial0T, Serial1T, offset, step> > {
|
|
||||||
typedef SerialBase< MultiSerial<Serial0T, Serial1T, offset, step> > BaseClassT;
|
template < REPEAT(NUM_SERIAL, _S_CLASS) const uint8_t offset=0, const uint8_t step=1 >
|
||||||
|
struct MultiSerial : public SerialBase< MultiSerial< REPEAT(NUM_SERIAL, _S_NAME) offset, step > > {
|
||||||
|
typedef SerialBase< MultiSerial< REPEAT(NUM_SERIAL, _S_NAME) offset, step > > BaseClassT;
|
||||||
|
|
||||||
|
#undef _S_CLASS
|
||||||
|
#undef _S_NAME
|
||||||
|
|
||||||
SerialMask portMask;
|
SerialMask portMask;
|
||||||
Serial0T & serial0;
|
|
||||||
Serial1T & serial1;
|
|
||||||
|
|
||||||
static constexpr uint8_t Usage = ((1 << step) - 1); // A bit mask containing as many bits as step
|
#define _S_DECLARE(N) Serial##N##T & serial##N;
|
||||||
static constexpr uint8_t FirstOutput = (Usage << offset);
|
REPEAT(NUM_SERIAL, _S_DECLARE);
|
||||||
static constexpr uint8_t SecondOutput = (Usage << (offset + step));
|
#undef _S_DECLARE
|
||||||
static constexpr uint8_t Both = FirstOutput | SecondOutput;
|
|
||||||
|
static constexpr uint8_t Usage = _BV(step) - 1; // A bit mask containing 'step' bits
|
||||||
|
|
||||||
|
#define _OUT_PORT(N) (Usage << (offset + (step * N))),
|
||||||
|
static constexpr uint8_t output[] = { REPEAT(NUM_SERIAL, _OUT_PORT) };
|
||||||
|
#undef _OUT_PORT
|
||||||
|
|
||||||
|
#define _OUT_MASK(N) | output[N]
|
||||||
|
static constexpr uint8_t ALL = 0 REPEAT(NUM_SERIAL, _OUT_MASK);
|
||||||
|
#undef _OUT_MASK
|
||||||
|
|
||||||
NO_INLINE void write(uint8_t c) {
|
NO_INLINE void write(uint8_t c) {
|
||||||
if (portMask.enabled(FirstOutput)) serial0.write(c);
|
#define _S_WRITE(N) if (portMask.enabled(output[N])) serial##N.write(c);
|
||||||
if (portMask.enabled(SecondOutput)) serial1.write(c);
|
REPEAT(NUM_SERIAL, _S_WRITE);
|
||||||
|
#undef _S_WRITE
|
||||||
}
|
}
|
||||||
NO_INLINE void msgDone() {
|
NO_INLINE void msgDone() {
|
||||||
if (portMask.enabled(FirstOutput)) serial0.msgDone();
|
#define _S_DONE(N) if (portMask.enabled(output[N])) serial##N.msgDone();
|
||||||
if (portMask.enabled(SecondOutput)) serial1.msgDone();
|
REPEAT(NUM_SERIAL, _S_DONE);
|
||||||
|
#undef _S_DONE
|
||||||
}
|
}
|
||||||
int available(serial_index_t index) {
|
int available(serial_index_t index) {
|
||||||
if (index.within(0 + offset, step + offset - 1))
|
uint8_t pos = offset;
|
||||||
return serial0.available(index);
|
#define _S_AVAILABLE(N) if (index.within(pos, pos + step - 1)) return serial##N.available(index); else pos += step;
|
||||||
else if (index.within(step + offset, 2 * step + offset - 1))
|
REPEAT(NUM_SERIAL, _S_AVAILABLE);
|
||||||
return serial1.available(index);
|
#undef _S_AVAILABLE
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int read(serial_index_t index) {
|
int read(serial_index_t index) {
|
||||||
if (index.within(0 + offset, step + offset - 1))
|
uint8_t pos = offset;
|
||||||
return serial0.read(index);
|
#define _S_READ(N) if (index.within(pos, pos + step - 1)) return serial##N.read(index); else pos += step;
|
||||||
else if (index.within(step + offset, 2 * step + offset - 1))
|
REPEAT(NUM_SERIAL, _S_READ);
|
||||||
return serial1.read(index);
|
#undef _S_READ
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
void begin(const long br) {
|
void begin(const long br) {
|
||||||
if (portMask.enabled(FirstOutput)) serial0.begin(br);
|
#define _S_BEGIN(N) if (portMask.enabled(output[N])) serial##N.begin(br);
|
||||||
if (portMask.enabled(SecondOutput)) serial1.begin(br);
|
REPEAT(NUM_SERIAL, _S_BEGIN);
|
||||||
|
#undef _S_BEGIN
|
||||||
}
|
}
|
||||||
void end() {
|
void end() {
|
||||||
if (portMask.enabled(FirstOutput)) serial0.end();
|
#define _S_END(N) if (portMask.enabled(output[N])) serial##N.end();
|
||||||
if (portMask.enabled(SecondOutput)) serial1.end();
|
REPEAT(NUM_SERIAL, _S_END);
|
||||||
|
#undef _S_END
|
||||||
}
|
}
|
||||||
bool connected() {
|
bool connected() {
|
||||||
bool ret = true;
|
bool ret = true;
|
||||||
if (portMask.enabled(FirstOutput)) ret = CALL_IF_EXISTS(bool, &serial0, connected);
|
#define _S_CONNECTED(N) if (portMask.enabled(output[N]) && !CALL_IF_EXISTS(bool, &serial##N, connected)) ret = false;
|
||||||
if (portMask.enabled(SecondOutput)) ret = ret && CALL_IF_EXISTS(bool, &serial1, connected);
|
REPEAT(NUM_SERIAL, _S_CONNECTED);
|
||||||
|
#undef _S_CONNECTED
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,27 +267,32 @@ struct MultiSerial : public SerialBase< MultiSerial<Serial0T, Serial1T, offset,
|
||||||
using BaseClassT::read;
|
using BaseClassT::read;
|
||||||
|
|
||||||
// Redirect flush
|
// Redirect flush
|
||||||
NO_INLINE void flush() {
|
NO_INLINE void flush() {
|
||||||
if (portMask.enabled(FirstOutput)) serial0.flush();
|
#define _S_FLUSH(N) if (portMask.enabled(output[N])) serial##N.flush();
|
||||||
if (portMask.enabled(SecondOutput)) serial1.flush();
|
REPEAT(NUM_SERIAL, _S_FLUSH);
|
||||||
|
#undef _S_FLUSH
|
||||||
}
|
}
|
||||||
NO_INLINE void flushTX() {
|
NO_INLINE void flushTX() {
|
||||||
if (portMask.enabled(FirstOutput)) CALL_IF_EXISTS(void, &serial0, flushTX);
|
#define _S_FLUSHTX(N) if (portMask.enabled(output[N])) CALL_IF_EXISTS(void, &serial0, flushTX);
|
||||||
if (portMask.enabled(SecondOutput)) CALL_IF_EXISTS(void, &serial1, flushTX);
|
REPEAT(NUM_SERIAL, _S_FLUSHTX);
|
||||||
|
#undef _S_FLUSHTX
|
||||||
}
|
}
|
||||||
|
|
||||||
// Forward feature queries
|
// Forward feature queries
|
||||||
SerialFeature features(serial_index_t index) const {
|
SerialFeature features(serial_index_t index) const {
|
||||||
if (index.within(0 + offset, step + offset - 1))
|
uint8_t pos = offset;
|
||||||
return serial0.features(index);
|
#define _S_FEATURES(N) if (index.within(pos, pos + step - 1)) return serial##N.features(index); else pos += step;
|
||||||
else if (index.within(step + offset, 2 * step + offset - 1))
|
REPEAT(NUM_SERIAL, _S_FEATURES);
|
||||||
return serial1.features(index);
|
#undef _S_FEATURES
|
||||||
return SerialFeature::None;
|
return SerialFeature::None;
|
||||||
}
|
}
|
||||||
|
|
||||||
MultiSerial(Serial0T & serial0, Serial1T & serial1, const SerialMask mask = Both, const bool e = false) :
|
#define _S_REFS(N) Serial##N##T & serial##N,
|
||||||
BaseClassT(e),
|
#define _S_INIT(N) ,serial##N (serial##N)
|
||||||
portMask(mask), serial0(serial0), serial1(serial1) {}
|
|
||||||
|
MultiSerial(REPEAT(NUM_SERIAL, _S_REFS) const SerialMask mask = ALL, const bool e = false)
|
||||||
|
: BaseClassT(e), portMask(mask) REPEAT(NUM_SERIAL, _S_INIT) {}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Build the actual serial object depending on current configuration
|
// Build the actual serial object depending on current configuration
|
||||||
|
@ -278,4 +300,7 @@ struct MultiSerial : public SerialBase< MultiSerial<Serial0T, Serial1T, offset,
|
||||||
#define ForwardSerial1Class TERN(SERIAL_RUNTIME_HOOK, RuntimeSerial, ForwardSerial)
|
#define ForwardSerial1Class TERN(SERIAL_RUNTIME_HOOK, RuntimeSerial, ForwardSerial)
|
||||||
#ifdef HAS_MULTI_SERIAL
|
#ifdef HAS_MULTI_SERIAL
|
||||||
#define Serial2Class ConditionalSerial
|
#define Serial2Class ConditionalSerial
|
||||||
|
#if NUM_SERIAL >= 3
|
||||||
|
#define Serial3Class ConditionalSerial
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -955,15 +955,19 @@
|
||||||
// Serial Port Info
|
// Serial Port Info
|
||||||
//
|
//
|
||||||
#ifdef SERIAL_PORT_2
|
#ifdef SERIAL_PORT_2
|
||||||
#define NUM_SERIAL 2
|
|
||||||
#define HAS_MULTI_SERIAL 1
|
#define HAS_MULTI_SERIAL 1
|
||||||
|
#ifdef SERIAL_PORT_3
|
||||||
|
#define NUM_SERIAL 3
|
||||||
|
#else
|
||||||
|
#define NUM_SERIAL 2
|
||||||
|
#endif
|
||||||
#elif defined(SERIAL_PORT)
|
#elif defined(SERIAL_PORT)
|
||||||
#define NUM_SERIAL 1
|
#define NUM_SERIAL 1
|
||||||
#else
|
#else
|
||||||
#define NUM_SERIAL 0
|
#define NUM_SERIAL 0
|
||||||
#undef BAUD_RATE_GCODE
|
#undef BAUD_RATE_GCODE
|
||||||
#endif
|
#endif
|
||||||
#if SERIAL_PORT == -1 || SERIAL_PORT_2 == -1
|
#if SERIAL_PORT == -1 || SERIAL_PORT_2 == -1 || SERIAL_PORT_3 == -1
|
||||||
#define HAS_USB_SERIAL 1
|
#define HAS_USB_SERIAL 1
|
||||||
#endif
|
#endif
|
||||||
#if SERIAL_PORT_2 == -2
|
#if SERIAL_PORT_2 == -2
|
||||||
|
|
|
@ -1859,6 +1859,7 @@
|
||||||
// Flag the indexed hardware serial ports in use
|
// Flag the indexed hardware serial ports in use
|
||||||
#define CONF_SERIAL_IS(N) ( (defined(SERIAL_PORT) && SERIAL_PORT == N) \
|
#define CONF_SERIAL_IS(N) ( (defined(SERIAL_PORT) && SERIAL_PORT == N) \
|
||||||
|| (defined(SERIAL_PORT_2) && SERIAL_PORT_2 == N) \
|
|| (defined(SERIAL_PORT_2) && SERIAL_PORT_2 == N) \
|
||||||
|
|| (defined(SERIAL_PORT_3) && SERIAL_PORT_3 == N) \
|
||||||
|| (defined(MMU2_SERIAL_PORT) && MMU2_SERIAL_PORT == N) \
|
|| (defined(MMU2_SERIAL_PORT) && MMU2_SERIAL_PORT == N) \
|
||||||
|| (defined(LCD_SERIAL_PORT) && LCD_SERIAL_PORT == N) )
|
|| (defined(LCD_SERIAL_PORT) && LCD_SERIAL_PORT == N) )
|
||||||
|
|
||||||
|
|
|
@ -607,6 +607,14 @@
|
||||||
#error "SERIAL_PORT must be defined."
|
#error "SERIAL_PORT must be defined."
|
||||||
#elif defined(SERIAL_PORT_2) && SERIAL_PORT_2 == SERIAL_PORT
|
#elif defined(SERIAL_PORT_2) && SERIAL_PORT_2 == SERIAL_PORT
|
||||||
#error "SERIAL_PORT_2 cannot be the same as SERIAL_PORT."
|
#error "SERIAL_PORT_2 cannot be the same as SERIAL_PORT."
|
||||||
|
#elif defined(SERIAL_PORT_3)
|
||||||
|
#ifndef SERIAL_PORT_2
|
||||||
|
#error "Use SERIAL_PORT_2 before using SERIAL_PORT_3"
|
||||||
|
#elif SERIAL_PORT_3 == SERIAL_PORT
|
||||||
|
#error "SERIAL_PORT_3 cannot be the same as SERIAL_PORT."
|
||||||
|
#elif SERIAL_PORT_3 == SERIAL_PORT_2
|
||||||
|
#error "SERIAL_PORT_3 cannot be the same as SERIAL_PORT_2."
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#if !(defined(__AVR__) && defined(USBCON))
|
#if !(defined(__AVR__) && defined(USBCON))
|
||||||
#if ENABLED(SERIAL_XON_XOFF) && RX_BUFFER_SIZE < 1024
|
#if ENABLED(SERIAL_XON_XOFF) && RX_BUFFER_SIZE < 1024
|
||||||
|
|
|
@ -14,7 +14,7 @@ set -e
|
||||||
#exec_test $1 $2 "Default Configuration" "$3"
|
#exec_test $1 $2 "Default Configuration" "$3"
|
||||||
|
|
||||||
restore_configs
|
restore_configs
|
||||||
opt_set MOTHERBOARD BOARD_RAMPS_14_RE_ARM_EFB NEOPIXEL_PIN P1_16
|
opt_set MOTHERBOARD BOARD_RAMPS_14_RE_ARM_EFB NEOPIXEL_PIN P1_16 SERIAL_PORT_3 3
|
||||||
opt_enable VIKI2 SDSUPPORT SDCARD_READONLY SERIAL_PORT_2 NEOPIXEL_LED
|
opt_enable VIKI2 SDSUPPORT SDCARD_READONLY SERIAL_PORT_2 NEOPIXEL_LED
|
||||||
exec_test $1 $2 "ReARM EFB VIKI2, SDSUPPORT, 2 Serial ports (USB CDC + UART0), NeoPixel" "$3"
|
exec_test $1 $2 "ReARM EFB VIKI2, SDSUPPORT, 2 Serial ports (USB CDC + UART0), NeoPixel" "$3"
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue