blob: cf5f35e2e37444138526014f13dd8b79e6745465 [file] [log] [blame]
Luigi Santivetti69972f92019-11-12 22:55:40 +00001/*
2 serial.c - Low level functions for sending and recieving bytes via the serial port
3 Part of Grbl
4
5 Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC
6 Copyright (c) 2009-2011 Simen Svale Skogsrud
7
8 Grbl is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 Grbl is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with Grbl. If not, see <http://www.gnu.org/licenses/>.
20*/
21
22#include "grbl.h"
23
24#define RX_RING_BUFFER (RX_BUFFER_SIZE+1)
25#define TX_RING_BUFFER (TX_BUFFER_SIZE+1)
26
27uint8_t serial_rx_buffer[RX_RING_BUFFER];
28uint8_t serial_rx_buffer_head = 0;
29volatile uint8_t serial_rx_buffer_tail = 0;
30
31uint8_t serial_tx_buffer[TX_RING_BUFFER];
32uint8_t serial_tx_buffer_head = 0;
33volatile uint8_t serial_tx_buffer_tail = 0;
34
35
36// Returns the number of bytes available in the RX serial buffer.
37uint8_t serial_get_rx_buffer_available()
38{
39 uint8_t rtail = serial_rx_buffer_tail; // Copy to limit multiple calls to volatile
40 if (serial_rx_buffer_head >= rtail) { return(RX_BUFFER_SIZE - (serial_rx_buffer_head-rtail)); }
41 return((rtail-serial_rx_buffer_head-1));
42}
43
44
45// Returns the number of bytes used in the RX serial buffer.
46// NOTE: Deprecated. Not used unless classic status reports are enabled in config.h.
47uint8_t serial_get_rx_buffer_count()
48{
49 uint8_t rtail = serial_rx_buffer_tail; // Copy to limit multiple calls to volatile
50 if (serial_rx_buffer_head >= rtail) { return(serial_rx_buffer_head-rtail); }
51 return (RX_BUFFER_SIZE - (rtail-serial_rx_buffer_head));
52}
53
54
55// Returns the number of bytes used in the TX serial buffer.
56// NOTE: Not used except for debugging and ensuring no TX bottlenecks.
57uint8_t serial_get_tx_buffer_count()
58{
59 uint8_t ttail = serial_tx_buffer_tail; // Copy to limit multiple calls to volatile
60 if (serial_tx_buffer_head >= ttail) { return(serial_tx_buffer_head-ttail); }
61 return (TX_RING_BUFFER - (ttail-serial_tx_buffer_head));
62}
63
64
65void serial_init()
66{
67 // Set baud rate
68 #if BAUD_RATE < 57600
69 uint16_t UBRR0_value = ((F_CPU / (8L * BAUD_RATE)) - 1)/2 ;
70 UCSR0A &= ~(1 << U2X0); // baud doubler off - Only needed on Uno XXX
71 #else
72 uint16_t UBRR0_value = ((F_CPU / (4L * BAUD_RATE)) - 1)/2;
73 UCSR0A |= (1 << U2X0); // baud doubler on for high baud rates, i.e. 115200
74 #endif
75 UBRR0H = UBRR0_value >> 8;
76 UBRR0L = UBRR0_value;
77
78 // enable rx, tx, and interrupt on complete reception of a byte
79 UCSR0B |= (1<<RXEN0 | 1<<TXEN0 | 1<<RXCIE0);
80
81 // defaults to 8-bit, no parity, 1 stop bit
82}
83
84
85// Writes one byte to the TX serial buffer. Called by main program.
86void serial_write(uint8_t data) {
87 // Calculate next head
88 uint8_t next_head = serial_tx_buffer_head + 1;
89 if (next_head == TX_RING_BUFFER) { next_head = 0; }
90
91 // Wait until there is space in the buffer
92 while (next_head == serial_tx_buffer_tail) {
93 // TODO: Restructure st_prep_buffer() calls to be executed here during a long print.
94 if (sys_rt_exec_state & EXEC_RESET) { return; } // Only check for abort to avoid an endless loop.
95 }
96
97 // Store data and advance head
98 serial_tx_buffer[serial_tx_buffer_head] = data;
99 serial_tx_buffer_head = next_head;
100
101 // Enable Data Register Empty Interrupt to make sure tx-streaming is running
102 UCSR0B |= (1 << UDRIE0);
103}
104
105
106// Data Register Empty Interrupt handler
107ISR(SERIAL_UDRE)
108{
109 uint8_t tail = serial_tx_buffer_tail; // Temporary serial_tx_buffer_tail (to optimize for volatile)
110
111 // Send a byte from the buffer
112 UDR0 = serial_tx_buffer[tail];
113
114 // Update tail position
115 tail++;
116 if (tail == TX_RING_BUFFER) { tail = 0; }
117
118 serial_tx_buffer_tail = tail;
119
120 // Turn off Data Register Empty Interrupt to stop tx-streaming if this concludes the transfer
121 if (tail == serial_tx_buffer_head) { UCSR0B &= ~(1 << UDRIE0); }
122}
123
124
125// Fetches the first byte in the serial read buffer. Called by main program.
126uint8_t serial_read()
127{
128 uint8_t tail = serial_rx_buffer_tail; // Temporary serial_rx_buffer_tail (to optimize for volatile)
129 if (serial_rx_buffer_head == tail) {
130 return SERIAL_NO_DATA;
131 } else {
132 uint8_t data = serial_rx_buffer[tail];
133
134 tail++;
135 if (tail == RX_RING_BUFFER) { tail = 0; }
136 serial_rx_buffer_tail = tail;
137
138 return data;
139 }
140}
141
142
143ISR(SERIAL_RX)
144{
145 uint8_t data = UDR0;
146 uint8_t next_head;
147
148 // Pick off realtime command characters directly from the serial stream. These characters are
149 // not passed into the main buffer, but these set system state flag bits for realtime execution.
150 switch (data) {
151 case CMD_RESET: mc_reset(); break; // Call motion control reset routine.
152 case CMD_STATUS_REPORT: system_set_exec_state_flag(EXEC_STATUS_REPORT); break; // Set as true
153 case CMD_CYCLE_START: system_set_exec_state_flag(EXEC_CYCLE_START); break; // Set as true
154 case CMD_FEED_HOLD: system_set_exec_state_flag(EXEC_FEED_HOLD); break; // Set as true
155 default :
156 if (data > 0x7F) { // Real-time control characters are extended ACSII only.
157 switch(data) {
158 case CMD_SAFETY_DOOR: system_set_exec_state_flag(EXEC_SAFETY_DOOR); break; // Set as true
159 case CMD_JOG_CANCEL:
160 if (sys.state & STATE_JOG) { // Block all other states from invoking motion cancel.
161 system_set_exec_state_flag(EXEC_MOTION_CANCEL);
162 }
163 break;
164 #ifdef DEBUG
165 case CMD_DEBUG_REPORT: {uint8_t sreg = SREG; cli(); bit_true(sys_rt_exec_debug,EXEC_DEBUG_REPORT); SREG = sreg;} break;
166 #endif
167 case CMD_FEED_OVR_RESET: system_set_exec_motion_override_flag(EXEC_FEED_OVR_RESET); break;
168 case CMD_FEED_OVR_COARSE_PLUS: system_set_exec_motion_override_flag(EXEC_FEED_OVR_COARSE_PLUS); break;
169 case CMD_FEED_OVR_COARSE_MINUS: system_set_exec_motion_override_flag(EXEC_FEED_OVR_COARSE_MINUS); break;
170 case CMD_FEED_OVR_FINE_PLUS: system_set_exec_motion_override_flag(EXEC_FEED_OVR_FINE_PLUS); break;
171 case CMD_FEED_OVR_FINE_MINUS: system_set_exec_motion_override_flag(EXEC_FEED_OVR_FINE_MINUS); break;
172 case CMD_RAPID_OVR_RESET: system_set_exec_motion_override_flag(EXEC_RAPID_OVR_RESET); break;
173 case CMD_RAPID_OVR_MEDIUM: system_set_exec_motion_override_flag(EXEC_RAPID_OVR_MEDIUM); break;
174 case CMD_RAPID_OVR_LOW: system_set_exec_motion_override_flag(EXEC_RAPID_OVR_LOW); break;
175 case CMD_SPINDLE_OVR_RESET: system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_RESET); break;
176 case CMD_SPINDLE_OVR_COARSE_PLUS: system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_COARSE_PLUS); break;
177 case CMD_SPINDLE_OVR_COARSE_MINUS: system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_COARSE_MINUS); break;
178 case CMD_SPINDLE_OVR_FINE_PLUS: system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_FINE_PLUS); break;
179 case CMD_SPINDLE_OVR_FINE_MINUS: system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_FINE_MINUS); break;
180 case CMD_SPINDLE_OVR_STOP: system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_STOP); break;
181 case CMD_COOLANT_FLOOD_OVR_TOGGLE: system_set_exec_accessory_override_flag(EXEC_COOLANT_FLOOD_OVR_TOGGLE); break;
182 #ifdef ENABLE_M7
183 case CMD_COOLANT_MIST_OVR_TOGGLE: system_set_exec_accessory_override_flag(EXEC_COOLANT_MIST_OVR_TOGGLE); break;
184 #endif
185 }
186 // Throw away any unfound extended-ASCII character by not passing it to the serial buffer.
187 } else { // Write character to buffer
188 next_head = serial_rx_buffer_head + 1;
189 if (next_head == RX_RING_BUFFER) { next_head = 0; }
190
191 // Write data to buffer unless it is full.
192 if (next_head != serial_rx_buffer_tail) {
193 serial_rx_buffer[serial_rx_buffer_head] = data;
194 serial_rx_buffer_head = next_head;
195 }
196 }
197 }
198}
199
200
201void serial_reset_read_buffer()
202{
203 serial_rx_buffer_tail = serial_rx_buffer_head;
204}