@ -40,32 +40,32 @@
# if !defined(USBCON) && (defined(UBRRH) || defined(UBRR0H) || defined(UBRR1H) || defined(UBRR2H) || defined(UBRR3H))
# include "MarlinSerial.h"
# include "../../MarlinCore.h"
# include "MarlinSerial.h"
# include "../../MarlinCore.h"
# if ENABLED(DIRECT_STEPPING)
# if ENABLED(DIRECT_STEPPING)
# include "../../feature/direct_stepping.h"
# endif
template < typename Cfg > typename MarlinSerial < Cfg > : : ring_buffer_r MarlinSerial < Cfg > : : rx_buffer = { 0 , 0 , { 0 } } ;
template < typename Cfg > typename MarlinSerial < Cfg > : : ring_buffer_t MarlinSerial < Cfg > : : tx_buffer = { 0 } ;
template < typename Cfg > bool MarlinSerial < Cfg > : : _written = false ;
template < typename Cfg > uint8_t MarlinSerial < Cfg > : : xon_xoff_state = MarlinSerial < Cfg > : : XON_XOFF_CHAR_SENT | MarlinSerial < Cfg > : : XON_CHAR ;
template < typename Cfg > uint8_t MarlinSerial < Cfg > : : rx_dropped_bytes = 0 ;
template < typename Cfg > uint8_t MarlinSerial < Cfg > : : rx_buffer_overruns = 0 ;
template < typename Cfg > uint8_t MarlinSerial < Cfg > : : rx_framing_errors = 0 ;
template < typename Cfg > typename MarlinSerial < Cfg > : : ring_buffer_pos_t MarlinSerial < Cfg > : : rx_max_enqueued = 0 ;
// A SW memory barrier, to ensure GCC does not overoptimize loops
# define sw_barrier() asm volatile("": : :"memory");
# include "../../feature/e_parser.h"
# endif
// "Atomically" read the RX head index value without disabling interrupts:
// This MUST be called with RX interrupts enabled, and CAN'T be called
// from the RX ISR itself!
template < typename Cfg >
FORCE_INLINE typename MarlinSerial < Cfg > : : ring_buffer_pos_t MarlinSerial < Cfg > : : atomic_read_rx_head ( ) {
template < typename Cfg > typename MarlinSerial < Cfg > : : ring_buffer_r MarlinSerial < Cfg > : : rx_buffer = { 0 , 0 , { 0 } } ;
template < typename Cfg > typename MarlinSerial < Cfg > : : ring_buffer_t MarlinSerial < Cfg > : : tx_buffer = { 0 } ;
template < typename Cfg > bool MarlinSerial < Cfg > : : _written = false ;
template < typename Cfg > uint8_t MarlinSerial < Cfg > : : xon_xoff_state = MarlinSerial < Cfg > : : XON_XOFF_CHAR_SENT | MarlinSerial < Cfg > : : XON_CHAR ;
template < typename Cfg > uint8_t MarlinSerial < Cfg > : : rx_dropped_bytes = 0 ;
template < typename Cfg > uint8_t MarlinSerial < Cfg > : : rx_buffer_overruns = 0 ;
template < typename Cfg > uint8_t MarlinSerial < Cfg > : : rx_framing_errors = 0 ;
template < typename Cfg > typename MarlinSerial < Cfg > : : ring_buffer_pos_t MarlinSerial < Cfg > : : rx_max_enqueued = 0 ;
// A SW memory barrier, to ensure GCC does not overoptimize loops
# define sw_barrier() asm volatile("": : :"memory");
# include "../../feature/e_parser.h"
// "Atomically" read the RX head index value without disabling interrupts:
// This MUST be called with RX interrupts enabled, and CAN'T be called
// from the RX ISR itself!
template < typename Cfg >
FORCE_INLINE typename MarlinSerial < Cfg > : : ring_buffer_pos_t MarlinSerial < Cfg > : : atomic_read_rx_head ( ) {
if ( Cfg : : RX_SIZE > 256 ) {
// Keep reading until 2 consecutive reads return the same value,
// meaning there was no update in-between caused by an interrupt.
@ -85,19 +85,19 @@
// With an 8bit index, reads are always atomic. No need for special handling
return rx_buffer . head ;
}
}
}
template < typename Cfg >
volatile bool MarlinSerial < Cfg > : : rx_tail_value_not_stable = false ;
template < typename Cfg >
volatile uint16_t MarlinSerial < Cfg > : : rx_tail_value_backup = 0 ;
template < typename Cfg >
volatile bool MarlinSerial < Cfg > : : rx_tail_value_not_stable = false ;
template < typename Cfg >
volatile uint16_t MarlinSerial < Cfg > : : rx_tail_value_backup = 0 ;
// Set RX tail index, taking into account the RX ISR could interrupt
// the write to this variable in the middle - So a backup strategy
// is used to ensure reads of the correct values.
// -Must NOT be called from the RX ISR -
template < typename Cfg >
FORCE_INLINE void MarlinSerial < Cfg > : : atomic_set_rx_tail ( typename MarlinSerial < Cfg > : : ring_buffer_pos_t value ) {
// Set RX tail index, taking into account the RX ISR could interrupt
// the write to this variable in the middle - So a backup strategy
// is used to ensure reads of the correct values.
// -Must NOT be called from the RX ISR -
template < typename Cfg >
FORCE_INLINE void MarlinSerial < Cfg > : : atomic_set_rx_tail ( typename MarlinSerial < Cfg > : : ring_buffer_pos_t value ) {
if ( Cfg : : RX_SIZE > 256 ) {
// Store the new value in the backup
rx_tail_value_backup = value ;
@ -114,24 +114,24 @@
}
else
rx_buffer . tail = value ;
}
}
// Get the RX tail index, taking into account the read could be
// interrupting in the middle of the update of that index value
// -Called from the RX ISR -
template < typename Cfg >
FORCE_INLINE typename MarlinSerial < Cfg > : : ring_buffer_pos_t MarlinSerial < Cfg > : : atomic_read_rx_tail ( ) {
// Get the RX tail index, taking into account the read could be
// interrupting in the middle of the update of that index value
// -Called from the RX ISR -
template < typename Cfg >
FORCE_INLINE typename MarlinSerial < Cfg > : : ring_buffer_pos_t MarlinSerial < Cfg > : : atomic_read_rx_tail ( ) {
if ( Cfg : : RX_SIZE > 256 ) {
// If the true index is being modified, return the backup value
if ( rx_tail_value_not_stable ) return rx_tail_value_backup ;
}
// The true index is stable, return it
return rx_buffer . tail ;
}
}
// (called with RX interrupts disabled)
template < typename Cfg >
FORCE_INLINE void MarlinSerial < Cfg > : : store_rxd_char ( ) {
// (called with RX interrupts disabled)
template < typename Cfg >
FORCE_INLINE void MarlinSerial < Cfg > : : store_rxd_char ( ) {
static EmergencyParser : : State emergency_state ; // = EP_RESET
@ -275,11 +275,11 @@
// Store the new head value - The main loop will retry until the value is stable
rx_buffer . head = h ;
}
}
// (called with TX irqs disabled)
template < typename Cfg >
FORCE_INLINE void MarlinSerial < Cfg > : : _tx_udr_empty_irq ( ) {
// (called with TX irqs disabled)
template < typename Cfg >
FORCE_INLINE void MarlinSerial < Cfg > : : _tx_udr_empty_irq ( ) {
if ( Cfg : : TX_SIZE > 0 ) {
// Read positions
uint8_t t = tx_buffer . tail ;
@ -328,11 +328,11 @@
// Disable interrupts if there is nothing to transmit following this byte
if ( h = = t ) B_UDRIE = 0 ; // (Non-atomic, could be reenabled by the main program, but eventually this will succeed)
}
}
}
// Public Methods
template < typename Cfg >
void MarlinSerial < Cfg > : : begin ( const long baud ) {
// Public Methods
template < typename Cfg >
void MarlinSerial < Cfg > : : begin ( const long baud ) {
uint16_t baud_setting ;
bool useU2X = true ;
@ -360,24 +360,24 @@
B_RXCIE = 1 ;
if ( Cfg : : TX_SIZE > 0 ) B_UDRIE = 0 ;
_written = false ;
}
}
template < typename Cfg >
void MarlinSerial < Cfg > : : end ( ) {
template < typename Cfg >
void MarlinSerial < Cfg > : : end ( ) {
B_RXEN = 0 ;
B_TXEN = 0 ;
B_RXCIE = 0 ;
B_UDRIE = 0 ;
}
}
template < typename Cfg >
int MarlinSerial < Cfg > : : peek ( ) {
template < typename Cfg >
int MarlinSerial < Cfg > : : peek ( ) {
const ring_buffer_pos_t h = atomic_read_rx_head ( ) , t = rx_buffer . tail ;
return h = = t ? - 1 : rx_buffer . buffer [ t ] ;
}
}
template < typename Cfg >
int MarlinSerial < Cfg > : : read ( ) {
template < typename Cfg >
int MarlinSerial < Cfg > : : read ( ) {
const ring_buffer_pos_t h = atomic_read_rx_head ( ) ;
// Read the tail. Main thread owns it, so it is safe to directly read it
@ -417,16 +417,16 @@
}
return v ;
}
}
template < typename Cfg >
typename MarlinSerial < Cfg > : : ring_buffer_pos_t MarlinSerial < Cfg > : : available ( ) {
template < typename Cfg >
typename MarlinSerial < Cfg > : : ring_buffer_pos_t MarlinSerial < Cfg > : : available ( ) {
const ring_buffer_pos_t h = atomic_read_rx_head ( ) , t = rx_buffer . tail ;
return ( ring_buffer_pos_t ) ( Cfg : : RX_SIZE + h - t ) & ( Cfg : : RX_SIZE - 1 ) ;
}
}
template < typename Cfg >
void MarlinSerial < Cfg > : : flush ( ) {
template < typename Cfg >
void MarlinSerial < Cfg > : : flush ( ) {
// Set the tail to the head:
// - Read the RX head index in a safe way. (See atomic_read_rx_head.)
@ -451,10 +451,10 @@
}
}
}
}
}
template < typename Cfg >
void MarlinSerial < Cfg > : : write ( const uint8_t c ) {
template < typename Cfg >
void MarlinSerial < Cfg > : : write ( const uint8_t c ) {
if ( Cfg : : TX_SIZE = = 0 ) {
_written = true ;
@ -510,10 +510,10 @@
// Enable TX ISR - Non atomic, but it will eventually enable TX ISR
B_UDRIE = 1 ;
}
}
}
template < typename Cfg >
void MarlinSerial < Cfg > : : flushTX ( ) {
template < typename Cfg >
void MarlinSerial < Cfg > : : flushTX ( ) {
if ( Cfg : : TX_SIZE = = 0 ) {
// No bytes written, no need to flush. This special case is needed since there's
@ -554,34 +554,34 @@
// At this point nothing is queued anymore (DRIE is disabled) and
// the hardware finished transmission (TXC is set).
}
}
}
/**
/**
* Imports from print . h
*/
template < typename Cfg >
void MarlinSerial < Cfg > : : print ( char c , int base ) {
template < typename Cfg >
void MarlinSerial < Cfg > : : print ( char c , int base ) {
print ( ( long ) c , base ) ;
}
}
template < typename Cfg >
void MarlinSerial < Cfg > : : print ( unsigned char b , int base ) {
template < typename Cfg >
void MarlinSerial < Cfg > : : print ( unsigned char b , int base ) {
print ( ( unsigned long ) b , base ) ;
}
}
template < typename Cfg >
void MarlinSerial < Cfg > : : print ( int n , int base ) {
template < typename Cfg >
void MarlinSerial < Cfg > : : print ( int n , int base ) {
print ( ( long ) n , base ) ;
}
}
template < typename Cfg >
void MarlinSerial < Cfg > : : print ( unsigned int n , int base ) {
template < typename Cfg >
void MarlinSerial < Cfg > : : print ( unsigned int n , int base ) {
print ( ( unsigned long ) n , base ) ;
}
}
template < typename Cfg >
void MarlinSerial < Cfg > : : print ( long n , int base ) {
template < typename Cfg >
void MarlinSerial < Cfg > : : print ( long n , int base ) {
if ( base = = 0 ) write ( n ) ;
else if ( base = = 10 ) {
if ( n < 0 ) { print ( ' - ' ) ; n = - n ; }
@ -589,83 +589,83 @@
}
else
printNumber ( n , base ) ;
}
}
template < typename Cfg >
void MarlinSerial < Cfg > : : print ( unsigned long n , int base ) {
template < typename Cfg >
void MarlinSerial < Cfg > : : print ( unsigned long n , int base ) {
if ( base = = 0 ) write ( n ) ;
else printNumber ( n , base ) ;
}
}
template < typename Cfg >
void MarlinSerial < Cfg > : : print ( double n , int digits ) {
template < typename Cfg >
void MarlinSerial < Cfg > : : print ( double n , int digits ) {
printFloat ( n , digits ) ;
}
}
template < typename Cfg >
void MarlinSerial < Cfg > : : println ( ) {
template < typename Cfg >
void MarlinSerial < Cfg > : : println ( ) {
print ( ' \r ' ) ;
print ( ' \n ' ) ;
}
}
template < typename Cfg >
void MarlinSerial < Cfg > : : println ( const String & s ) {
template < typename Cfg >
void MarlinSerial < Cfg > : : println ( const String & s ) {
print ( s ) ;
println ( ) ;
}
}
template < typename Cfg >
void MarlinSerial < Cfg > : : println ( const char c [ ] ) {
template < typename Cfg >
void MarlinSerial < Cfg > : : println ( const char c [ ] ) {
print ( c ) ;
println ( ) ;
}
}
template < typename Cfg >
void MarlinSerial < Cfg > : : println ( char c , int base ) {
template < typename Cfg >
void MarlinSerial < Cfg > : : println ( char c , int base ) {
print ( c , base ) ;
println ( ) ;
}
}
template < typename Cfg >
void MarlinSerial < Cfg > : : println ( unsigned char b , int base ) {
template < typename Cfg >
void MarlinSerial < Cfg > : : println ( unsigned char b , int base ) {
print ( b , base ) ;
println ( ) ;
}
}
template < typename Cfg >
void MarlinSerial < Cfg > : : println ( int n , int base ) {
template < typename Cfg >
void MarlinSerial < Cfg > : : println ( int n , int base ) {
print ( n , base ) ;
println ( ) ;
}
}
template < typename Cfg >
void MarlinSerial < Cfg > : : println ( unsigned int n , int base ) {
template < typename Cfg >
void MarlinSerial < Cfg > : : println ( unsigned int n , int base ) {
print ( n , base ) ;
println ( ) ;
}
}
template < typename Cfg >
void MarlinSerial < Cfg > : : println ( long n , int base ) {
template < typename Cfg >
void MarlinSerial < Cfg > : : println ( long n , int base ) {
print ( n , base ) ;
println ( ) ;
}
}
template < typename Cfg >
void MarlinSerial < Cfg > : : println ( unsigned long n , int base ) {
template < typename Cfg >
void MarlinSerial < Cfg > : : println ( unsigned long n , int base ) {
print ( n , base ) ;
println ( ) ;
}
}
template < typename Cfg >
void MarlinSerial < Cfg > : : println ( double n , int digits ) {
template < typename Cfg >
void MarlinSerial < Cfg > : : println ( double n , int digits ) {
print ( n , digits ) ;
println ( ) ;
}
}
// Private Methods
// Private Methods
template < typename Cfg >
void MarlinSerial < Cfg > : : printNumber ( unsigned long n , uint8_t base ) {
template < typename Cfg >
void MarlinSerial < Cfg > : : printNumber ( unsigned long n , uint8_t base ) {
if ( n ) {
unsigned char buf [ 8 * sizeof ( long ) ] ; // Enough space for base 2
int8_t i = 0 ;
@ -678,10 +678,10 @@
}
else
print ( ' 0 ' ) ;
}
}
template < typename Cfg >
void MarlinSerial < Cfg > : : printFloat ( double number , uint8_t digits ) {
template < typename Cfg >
void MarlinSerial < Cfg > : : printFloat ( double number , uint8_t digits ) {
// Handle negative numbers
if ( number < 0.0 ) {
print ( ' - ' ) ;
@ -709,24 +709,24 @@
remainder - = toPrint ;
}
}
}
}
// Hookup ISR handlers
ISR ( SERIAL_REGNAME ( USART , SERIAL_PORT , _RX_vect ) ) {
// Hookup ISR handlers
ISR ( SERIAL_REGNAME ( USART , SERIAL_PORT , _RX_vect ) ) {
MarlinSerial < MarlinSerialCfg < SERIAL_PORT > > : : store_rxd_char ( ) ;
}
}
ISR ( SERIAL_REGNAME ( USART , SERIAL_PORT , _UDRE_vect ) ) {
ISR ( SERIAL_REGNAME ( USART , SERIAL_PORT , _UDRE_vect ) ) {
MarlinSerial < MarlinSerialCfg < SERIAL_PORT > > : : _tx_udr_empty_irq ( ) ;
}
}
// Preinstantiate
template class MarlinSerial < MarlinSerialCfg < SERIAL_PORT > > ;
// Preinstantiate
template class MarlinSerial < MarlinSerialCfg < SERIAL_PORT > > ;
// Instantiate
MarlinSerial < MarlinSerialCfg < SERIAL_PORT > > customizedSerial1 ;
// Instantiate
MarlinSerial < MarlinSerialCfg < SERIAL_PORT > > customizedSerial1 ;
# ifdef SERIAL_PORT_2
# ifdef SERIAL_PORT_2
// Hookup ISR handlers
ISR ( SERIAL_REGNAME ( USART , SERIAL_PORT_2 , _RX_vect ) ) {
@ -743,73 +743,57 @@
// Instantiate
MarlinSerial < MarlinSerialCfg < SERIAL_PORT_2 > > customizedSerial2 ;
# endif
# endif // !USBCON && (UBRRH || UBRR0H || UBRR1H || UBRR2H || UBRR3H)
# endif
# ifdef INTERNAL _SERIAL_PORT
# ifdef MMU2_SERIAL_PORT
ISR ( SERIAL_REGNAME ( USART , INTERNAL _SERIAL_PORT, _RX_vect ) ) {
MarlinSerial < MarlinInternalSerialCfg < INTERNAL _SERIAL_PORT > > : : store_rxd_char ( ) ;
ISR ( SERIAL_REGNAME ( USART , MMU2 _SERIAL_PORT, _RX_vect ) ) {
MarlinSerial < MMU2SerialCfg < MMU2 _SERIAL_PORT > > : : store_rxd_char ( ) ;
}
ISR ( SERIAL_REGNAME ( USART , INTERNAL _SERIAL_PORT, _UDRE_vect ) ) {
MarlinSerial < MarlinInternalSerialCfg < INTERNAL _SERIAL_PORT > > : : _tx_udr_empty_irq ( ) ;
ISR ( SERIAL_REGNAME ( USART , MMU2 _SERIAL_PORT, _UDRE_vect ) ) {
MarlinSerial < MMU2SerialCfg < MMU2 _SERIAL_PORT > > : : _tx_udr_empty_irq ( ) ;
}
// Preinstantiate
template class MarlinSerial < MarlinInternalSerialCfg < INTERNAL _SERIAL_PORT > > ;
template class MarlinSerial < MMU2SerialCfg < MMU2 _SERIAL_PORT > > ;
// Instantiate
MarlinSerial < MarlinInternalSerialCfg < INTERNAL_SERIAL_PORT > > internal Serial ;
MarlinSerial < MMU2SerialCfg < MMU2_SERIAL_PORT > > mmu Serial ;
# endif
# ifdef DGUS _SERIAL_PORT
# ifdef LC D_SERIAL_PORT
template < typename Cfg >
typename MarlinSerial < Cfg > : : ring_buffer_pos_t MarlinSerial < Cfg > : : get_tx_buffer_free ( ) {
const ring_buffer_pos_t t = tx_buffer . tail , // next byte to send.
h = tx_buffer . head ; // next pos for queue.
int ret = t - h - 1 ;
if ( ret < 0 ) ret + = Cfg : : TX_SIZE + 1 ;
return ret ;
}
ISR ( SERIAL_REGNAME ( USART , DGUS_SERIAL_PORT , _RX_vect ) ) {
MarlinSerial < MarlinInternalSerialCfg < DGUS_SERIAL_PORT > > : : store_rxd_char ( ) ;
ISR ( SERIAL_REGNAME ( USART , LCD_SERIAL_PORT , _RX_vect ) ) {
MarlinSerial < LCDSerialCfg < LCD_SERIAL_PORT > > : : store_rxd_char ( ) ;
}
ISR ( SERIAL_REGNAME ( USART , DGUS _SERIAL_PORT , _UDRE_vect ) ) {
MarlinSerial < MarlinInternal SerialCfg< DGUS _SERIAL_PORT > > : : _tx_udr_empty_irq ( ) ;
ISR ( SERIAL_REGNAME ( USART , LCD_SERIAL_PORT , _UDRE_vect ) ) {
MarlinSerial < LCDSerialCfg < LCD_SERIAL_PORT > > : : _tx_udr_empty_irq ( ) ;
}
// Preinstantiate
template class MarlinSerial < MarlinInternal SerialCfg< DGUS _SERIAL_PORT > > ;
template class MarlinSerial < LCDSerialCfg < LCD_SERIAL_PORT > > ;
// Instantiate
MarlinSerial < MarlinInternalSerialCfg < DGUS_SERIAL_PORT > > internalDgusSerial ;
# endif
# ifdef ANYCUBIC_LCD_SERIAL_PORT
MarlinSerial < LCDSerialCfg < LCD_SERIAL_PORT > > lcdSerial ;
ISR ( SERIAL_REGNAME ( USART , ANYCUBIC_LCD_SERIAL_PORT , _RX_vect ) ) {
MarlinSerial < AnycubicLcdSerialCfg < ANYCUBIC_LCD_SERIAL_PORT > > : : store_rxd_char ( ) ;
}
ISR ( SERIAL_REGNAME ( USART , ANYCUBIC_LCD_SERIAL_PORT , _UDRE_vect ) ) {
MarlinSerial < AnycubicLcdSerialCfg < ANYCUBIC_LCD_SERIAL_PORT > > : : _tx_udr_empty_irq ( ) ;
# if HAS_DGUS_LCD
template < typename Cfg >
typename MarlinSerial < Cfg > : : ring_buffer_pos_t MarlinSerial < Cfg > : : get_tx_buffer_free ( ) {
const ring_buffer_pos_t t = tx_buffer . tail , // next byte to send.
h = tx_buffer . head ; // next pos for queue.
int ret = t - h - 1 ;
if ( ret < 0 ) ret + = Cfg : : TX_SIZE + 1 ;
return ret ;
}
// Preinstantiate
template class MarlinSerial < AnycubicLcdSerialCfg < ANYCUBIC_LCD_SERIAL_PORT > > ;
// Instantiate
MarlinSerial < AnycubicLcdSerialCfg < ANYCUBIC_LCD_SERIAL_PORT > > anycubicLcdSerial ;
# endif
# endif
# endif // !USBCON && (UBRRH || UBRR0H || UBRR1H || UBRR2H || UBRR3H)
// For AT90USB targets use the UART for BT interfacing
# if defined(USBCON) && ENABLED(BLUETOOTH)
HardwareSerial bluetoothSerial ;