From ab9d1830245406d46bd6faada7df39ae17fef504 Mon Sep 17 00:00:00 2001 From: Robert F-C Date: Mon, 5 Nov 2012 21:34:27 +1100 Subject: [PATCH] Make serial port configurable. This change makes the choice of serial port configurable so that wireless capability can be easily added by connecting Bluetooth modules (such as BlueSmirf or JY-MCU) to the expansion port pins. --- Marlin/Configuration.h | 7 ++++++ Marlin/MarlinSerial.cpp | 42 +++++++++++++++------------------- Marlin/MarlinSerial.h | 50 ++++++++++++++++++++++++++++++++++++----- 3 files changed, 69 insertions(+), 30 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 1d2bb292a0..12f2624621 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -331,6 +331,13 @@ const bool Z_ENDSTOPS_INVERTING = true; // set to true to invert the logic of th // SF send wrong arc g-codes when using Arc Point as fillet procedure //#define SF_ARC_FIX + +// SERIAL_PORT selects which serial port should be used for communication with the host. +// This allows the use of wireless adapters (for instance) which are connected to +// non-default serial port pins. +#define SERIAL_PORT 2 + + #include "Configuration_adv.h" #include "thermistortables.h" diff --git a/Marlin/MarlinSerial.cpp b/Marlin/MarlinSerial.cpp index e369800b89..0d2aceb3f2 100644 --- a/Marlin/MarlinSerial.cpp +++ b/Marlin/MarlinSerial.cpp @@ -28,7 +28,7 @@ // this is so I can support Attiny series and any other chip without a uart #if defined(UBRRH) || defined(UBRR0H) || defined(UBRR1H) || defined(UBRR2H) || defined(UBRR3H) -#if defined(UBRRH) || defined(UBRR0H) +#if UART_PRESENT(SERIAL_PORT) ring_buffer rx_buffer = { { 0 }, 0, 0 }; #endif @@ -48,18 +48,12 @@ FORCE_INLINE void store_char(unsigned char c) //#elif defined(SIG_USART_RECV) -#if defined(USART0_RX_vect) +#if defined(M_USARTx_RX_vect) // fixed by Mark Sproul this is on the 644/644p //SIGNAL(SIG_USART_RECV) - SIGNAL(USART0_RX_vect) + SIGNAL(M_USARTx_RX_vect) { - #if defined(UDR0) - unsigned char c = UDR0; - #elif defined(UDR) - unsigned char c = UDR; // atmega8, atmega32 - #else - #error UDR not defined - #endif + unsigned char c = M_UDRx; store_char(c); } #endif @@ -76,39 +70,39 @@ MarlinSerial::MarlinSerial() void MarlinSerial::begin(long baud) { uint16_t baud_setting; - bool useU2X0 = true; + bool useU2X = true; -#if F_CPU == 16000000UL +#if F_CPU == 16000000UL && SERIAL_PORT == 0 // hardcoded exception for compatibility with the bootloader shipped // with the Duemilanove and previous boards and the firmware on the 8U2 // on the Uno and Mega 2560. if (baud == 57600) { - useU2X0 = false; + useU2X = false; } #endif - if (useU2X0) { - UCSR0A = 1 << U2X0; + if (useU2X) { + M_UCSRxA = 1 << M_U2Xx; baud_setting = (F_CPU / 4 / baud - 1) / 2; } else { - UCSR0A = 0; + M_UCSRxA = 0; baud_setting = (F_CPU / 8 / baud - 1) / 2; } // assign the baud_setting, a.k.a. ubbr (USART Baud Rate Register) - UBRR0H = baud_setting >> 8; - UBRR0L = baud_setting; + M_UBRRxH = baud_setting >> 8; + M_UBRRxL = baud_setting; - sbi(UCSR0B, RXEN0); - sbi(UCSR0B, TXEN0); - sbi(UCSR0B, RXCIE0); + sbi(M_UCSRxB, M_RXENx); + sbi(M_UCSRxB, M_TXENx); + sbi(M_UCSRxB, M_RXCIEx); } void MarlinSerial::end() { - cbi(UCSR0B, RXEN0); - cbi(UCSR0B, TXEN0); - cbi(UCSR0B, RXCIE0); + cbi(M_UCSRxB, M_RXENx); + cbi(M_UCSRxB, M_TXENx); + cbi(M_UCSRxB, M_RXCIEx); } diff --git a/Marlin/MarlinSerial.h b/Marlin/MarlinSerial.h index 8525cba288..c17f4719f0 100644 --- a/Marlin/MarlinSerial.h +++ b/Marlin/MarlinSerial.h @@ -23,6 +23,44 @@ #define MarlinSerial_h #include "Marlin.h" +#if !defined(SERIAL_PORT) +#error SERIAL_PORT not set +#endif + +// The presence of the UBRRH register is used to detect a UART. +#define UART_PRESENT(port) ((port == 0 && (defined(UBRRH) || defined(UBRR0H))) || \ + (port == 1 && defined(UBRR1H)) || (port == 2 && defined(UBRR2H)) || \ + (port == 3 && defined(UBRR3H))) + +// These are macros to build serial port register names for the selected SERIAL_PORT (C preprocessor +// requires two levels of indirection to expand macro values properly) +#define SERIAL_REGNAME(registerbase,number,suffix) SERIAL_REGNAME_INTERNAL(registerbase,number,suffix) +#define SERIAL_REGNAME_INTERNAL(registerbase,number,suffix) registerbase##number##suffix + +// Registers used by MarlinSerial class (these are expanded +// depending on selected serial port +#define M_UCSRxA SERIAL_REGNAME(UCSR,SERIAL_PORT,A) // defines M_UCSRxA to be UCSRxA where x is the serial port number +#define M_UCSRxB SERIAL_REGNAME(UCSR,SERIAL_PORT,B) +#define M_RXENx SERIAL_REGNAME(RXEN,SERIAL_PORT,) +#define M_TXENx SERIAL_REGNAME(TXEN,SERIAL_PORT,) +#define M_RXCIEx SERIAL_REGNAME(RXCIE,SERIAL_PORT,) +#define M_UDREx SERIAL_REGNAME(UDRE,SERIAL_PORT,) +#if SERIAL_PORT == 0 && !defined(UDR0) + #if defined(UDR) + #define M_UDRx UDR // atmega8, atmega32 + #else + #error UDR not defined + #endif +#else + #define M_UDRx SERIAL_REGNAME(UDR,SERIAL_PORT,) +#endif +#define M_UBRRxH SERIAL_REGNAME(UBRR,SERIAL_PORT,H) +#define M_UBRRxL SERIAL_REGNAME(UBRR,SERIAL_PORT,L) +#define M_RXCx SERIAL_REGNAME(RXC,SERIAL_PORT,) +#define M_USARTx_RX_vect SERIAL_REGNAME(USART,SERIAL_PORT,_RX_vect) +#define M_U2Xx SERIAL_REGNAME(U2X,SERIAL_PORT,) + + #define DEC 10 #define HEX 16 @@ -46,7 +84,7 @@ struct ring_buffer int tail; }; -#if defined(UBRRH) || defined(UBRR0H) +#if UART_PRESENT(SERIAL_PORT) extern ring_buffer rx_buffer; #endif @@ -68,17 +106,17 @@ class MarlinSerial //: public Stream FORCE_INLINE void write(uint8_t c) { - while (!((UCSR0A) & (1 << UDRE0))) + while (!((M_UCSRxA) & (1 << M_UDREx))) ; - UDR0 = c; + M_UDRx = c; } FORCE_INLINE void checkRx(void) { - if((UCSR0A & (1<