@@ -34,6 +34,7 @@ enum serial_mode_e{
3434 UART0 = 0 ,
3535 UART1 ,
3636 UART2 ,
37+ UART3 ,
3738} current_uart = UART0 ;
3839
3940
@@ -119,7 +120,24 @@ void serial_init()
119120 // enable interrupt on complete reception of a byte
120121 UCSR2B |= 1 <<RXCIE2 ;
121122
122-
123+ /******************** uart3 ********************/
124+ // Set baud rate
125+ #if BAUD_RATE < 57600
126+ uint16_t UBRR3_value = ((F_CPU / (8L * BAUD_RATE )) - 1 )/2 ;
127+ UCSR3A &= ~(1 << U2X3 ); // baud doubler off - Only needed on Uno XXX
128+ #else
129+ uint16_t UBRR3_value = ((F_CPU / (4L * BAUD_RATE )) - 1 )/2 ;
130+ UCSR3A |= (1 << U2X3 ); // baud doubler on for high baud rates, i.e. 115200
131+ #endif
132+ UBRR3H = UBRR3_value >> 8 ;
133+ UBRR3L = UBRR3_value ;
134+
135+ // enable rx and tx
136+ UCSR3B |= 1 <<RXEN3 ;
137+ UCSR3B |= 1 <<TXEN3 ;
138+
139+ // enable interrupt on complete reception of a byte
140+ UCSR3B |= 1 <<RXCIE3 ;
123141 // defaults to 8-bit, no parity, 1 stop bit
124142}
125143
@@ -152,6 +170,9 @@ void serial_write(uint8_t data) {
152170 case UART2 :
153171 UCSR2B |= (1 << UDRIE2 );
154172 break ;
173+ case UART3 :
174+ UCSR3B |= (1 << UDRIE3 );
175+ break ;
155176 }
156177
157178}
@@ -243,6 +264,34 @@ ISR(USART2_UDRE_vect)
243264 if (tail == serial_tx_buffer_head ) { UCSR2B &= ~(1 << UDRIE2 ); }
244265}
245266
267+ ISR (USART3_UDRE_vect )
268+ {
269+ uint8_t tail = serial_tx_buffer_tail ; // Temporary serial_tx_buffer_tail (to optimize for volatile)
270+
271+ #ifdef ENABLE_XONXOFF
272+ if (flow_ctrl == SEND_XOFF ) {
273+ UDR3 = XOFF_CHAR ;
274+ flow_ctrl = XOFF_SENT ;
275+ } else if (flow_ctrl == SEND_XON ) {
276+ UDR3 = XON_CHAR ;
277+ flow_ctrl = XON_SENT ;
278+ } else
279+ #endif
280+ {
281+ // Send a byte from the buffer
282+ UDR3 = serial_tx_buffer [tail ];
283+
284+ // Update tail position
285+ tail ++ ;
286+ if (tail == TX_BUFFER_SIZE ) { tail = 0 ; }
287+
288+ serial_tx_buffer_tail = tail ;
289+ }
290+
291+ // Turn off Data Register Empty Interrupt to stop tx-streaming if this concludes the transfer
292+ if (tail == serial_tx_buffer_head ) { UCSR3B &= ~(1 << UDRIE3 ); }
293+ }
294+
246295
247296// Fetches the first byte in the serial read buffer. Called by main program.
248297uint8_t serial_read ()
@@ -267,6 +316,8 @@ uint8_t serial_read()
267316 break ;
268317 case UART2 : UCSR2B |= (1 << UDRIE2 ); // Force TX
269318 break ;
319+ case UART3 : UCSR3B |= (1 << UDRIE3 ); // Force TX
320+ break ;
270321 }
271322 }
272323 #endif
@@ -381,6 +432,42 @@ ISR(USART2_RX_vect)
381432 }
382433}
383434
435+ ISR (USART3_RX_vect )
436+ {
437+ uint8_t data = UDR3 ;
438+ uint8_t next_head ;
439+ current_uart = UART3 ;
440+
441+ // Pick off realtime command characters directly from the serial stream. These characters are
442+ // not passed into the buffer, but these set system state flag bits for realtime execution.
443+ switch (data ) {
444+ case CMD_STATUS_REPORT : bit_true_atomic (sys_rt_exec_state , EXEC_STATUS_REPORT ); break ; // Set as true
445+ case CMD_CYCLE_START : bit_true_atomic (sys_rt_exec_state , EXEC_CYCLE_START ); break ; // Set as true
446+ case CMD_FEED_HOLD : bit_true_atomic (sys_rt_exec_state , EXEC_FEED_HOLD ); break ; // Set as true
447+ case CMD_SAFETY_DOOR : bit_true_atomic (sys_rt_exec_state , EXEC_SAFETY_DOOR ); break ; // Set as true
448+ case CMD_RESET : mc_reset (); break ; // Call motion control reset routine.
449+ default : // Write character to buffer
450+ next_head = serial_rx_buffer_head + 1 ;
451+ if (next_head == RX_BUFFER_SIZE ) { next_head = 0 ; }
452+
453+ // Write data to buffer unless it is full.
454+ if (next_head != serial_rx_buffer_tail ) {
455+ serial_rx_buffer [serial_rx_buffer_head ] = data ;
456+ serial_rx_buffer_head = next_head ;
457+
458+ #ifdef ENABLE_XONXOFF
459+ if ((serial_get_rx_buffer_count () >= RX_BUFFER_FULL ) && flow_ctrl == XON_SENT ) {
460+ flow_ctrl = SEND_XOFF ;
461+ UCSR3B |= (1 << UDRIE3 ); // Force TX
462+ }
463+ #endif
464+
465+ }
466+ //TODO: else alarm on overflow?
467+ }
468+ }
469+
470+
384471
385472void serial_reset_read_buffer ()
386473{
0 commit comments