grbl-LPC-CoreXY/serial.c

190 lines
6.1 KiB
C
Raw Normal View History

2009-01-25 00:48:56 +01:00
/*
serial.c - Low level functions for sending and recieving bytes via the serial port
Part of Grbl
2009-01-25 00:48:56 +01:00
2014-05-18 18:01:05 +02:00
The MIT License (MIT)
GRBL(tm) - Embedded CNC g-code interpreter and motion-controller
Copyright (c) 2009-2011 Simen Svale Skogsrud
Copyright (c) 2011-2012 Sungeun K. Jeon
2009-01-25 00:48:56 +01:00
2014-05-18 18:01:05 +02:00
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
2009-01-25 00:48:56 +01:00
*/
2011-02-04 21:10:17 +01:00
#include <avr/interrupt.h>
#include "serial.h"
#include "config.h"
#include "motion_control.h"
#include "protocol.h"
2009-01-25 00:48:56 +01:00
uint8_t serial_rx_buffer[RX_BUFFER_SIZE];
uint8_t serial_rx_buffer_head = 0;
volatile uint8_t serial_rx_buffer_tail = 0;
uint8_t serial_tx_buffer[RX_BUFFER_SIZE];
uint8_t serial_tx_buffer_head = 0;
volatile uint8_t serial_tx_buffer_tail = 0;
2009-01-25 00:48:56 +01:00
#ifdef ENABLE_XONXOFF
volatile uint8_t flow_ctrl = XON_SENT; // Flow control state variable
// Returns the number of bytes in the RX buffer. This replaces a typical byte counter to prevent
// the interrupt and main programs from writing to the counter at the same time.
static uint8_t get_serial_rx_buffer_count()
{
if (serial_rx_buffer_head == serial_rx_buffer_tail) { return(0); }
if (serial_rx_buffer_head < serial_rx_buffer_tail) { return(serial_rx_buffer_tail-serial_rx_buffer_head); }
return (RX_BUFFER_SIZE - (serial_rx_buffer_head-serial_rx_buffer_tail));
}
#endif
Re-factored system states and alarm management. Serial baud support greater than 57600. - Refactored system states to be more clear and concise. Alarm locks processes when position is unknown to indicate to user something has gone wrong. - Changed mc_alarm to mc_reset, which now manages the system reset function. Centralizes it. - Renamed '$X' kill homing lock to kill alarm lock. - Created an alarm error reporting method to clear up what is an alarm: message vs a status error: message. For GUIs mainly. Alarm codes are negative. Status codes are positive. - Serial baud support upto 115200. Previous baudrate calc was unstable for 57600 and above. - Alarm state locks out all g-code blocks, including startup scripts, but allows user to access settings and internal commands. For example, to disable hard limits, if they are problematic. - Hard limits do not respond in an alarm state. - Fixed a problem with the hard limit interrupt during the homing cycle. The interrupt register is still active during the homing cycle and still signal the interrupt to trigger when re-enabled. Instead, just disabled the register. - Homing rate adjusted. All axes move at homing seek rate, regardless of how many axes move at the same time. This is unlike how the stepper module does it as a point to point rate. - New config.h settings to disable the homing rate adjustment and the force homing upon powerup. - Reduced the number of startup lines back down to 2 from 3. This discourages users from placing motion block in there, which can be very dangerous. - Startup blocks now run only after an alarm-free reset or after a homing cycle. Does not run when $X kill is called. For satefy reasons
2012-11-15 01:36:29 +01:00
void serial_init()
{
// Set baud rate
#if BAUD_RATE < 57600
uint16_t UBRR0_value = ((F_CPU / (8L * BAUD_RATE)) - 1)/2 ;
UCSR0A &= ~(1 << U2X0); // baud doubler off - Only needed on Uno XXX
#else
uint16_t UBRR0_value = ((F_CPU / (4L * BAUD_RATE)) - 1)/2;
UCSR0A |= (1 << U2X0); // baud doubler on for high baud rates, i.e. 115200
#endif
UBRR0H = UBRR0_value >> 8;
UBRR0L = UBRR0_value;
Re-factored system states and alarm management. Serial baud support greater than 57600. - Refactored system states to be more clear and concise. Alarm locks processes when position is unknown to indicate to user something has gone wrong. - Changed mc_alarm to mc_reset, which now manages the system reset function. Centralizes it. - Renamed '$X' kill homing lock to kill alarm lock. - Created an alarm error reporting method to clear up what is an alarm: message vs a status error: message. For GUIs mainly. Alarm codes are negative. Status codes are positive. - Serial baud support upto 115200. Previous baudrate calc was unstable for 57600 and above. - Alarm state locks out all g-code blocks, including startup scripts, but allows user to access settings and internal commands. For example, to disable hard limits, if they are problematic. - Hard limits do not respond in an alarm state. - Fixed a problem with the hard limit interrupt during the homing cycle. The interrupt register is still active during the homing cycle and still signal the interrupt to trigger when re-enabled. Instead, just disabled the register. - Homing rate adjusted. All axes move at homing seek rate, regardless of how many axes move at the same time. This is unlike how the stepper module does it as a point to point rate. - New config.h settings to disable the homing rate adjustment and the force homing upon powerup. - Reduced the number of startup lines back down to 2 from 3. This discourages users from placing motion block in there, which can be very dangerous. - Startup blocks now run only after an alarm-free reset or after a homing cycle. Does not run when $X kill is called. For satefy reasons
2012-11-15 01:36:29 +01:00
// enable rx and tx
2011-02-04 21:10:17 +01:00
UCSR0B |= 1<<RXEN0;
UCSR0B |= 1<<TXEN0;
2009-01-25 00:48:56 +01:00
// enable interrupt on complete reception of a byte
2011-02-04 21:10:17 +01:00
UCSR0B |= 1<<RXCIE0;
// defaults to 8-bit, no parity, 1 stop bit
2009-01-25 00:48:56 +01:00
}
void serial_write(uint8_t data) {
// Calculate next head
uint8_t next_head = serial_tx_buffer_head + 1;
if (next_head == TX_BUFFER_SIZE) { next_head = 0; }
2009-01-25 00:48:56 +01:00
// Wait until there is space in the buffer
while (next_head == serial_tx_buffer_tail) {
if (sys.execute & EXEC_RESET) { return; } // Only check for abort to avoid an endless loop.
}
// Store data and advance head
serial_tx_buffer[serial_tx_buffer_head] = data;
serial_tx_buffer_head = next_head;
2011-06-03 15:42:28 +02:00
// Enable Data Register Empty Interrupt to make sure tx-streaming is running
UCSR0B |= (1 << UDRIE0);
}
// Data Register Empty Interrupt handler
2013-08-21 04:05:16 +02:00
ISR(SERIAL_UDRE)
{
// Temporary serial_tx_buffer_tail (to optimize for volatile)
uint8_t tail = serial_tx_buffer_tail;
#ifdef ENABLE_XONXOFF
if (flow_ctrl == SEND_XOFF) {
UDR0 = XOFF_CHAR;
flow_ctrl = XOFF_SENT;
} else if (flow_ctrl == SEND_XON) {
UDR0 = XON_CHAR;
flow_ctrl = XON_SENT;
} else
#endif
{
// Send a byte from the buffer
UDR0 = serial_tx_buffer[tail];
// Update tail position
tail++;
if (tail == TX_BUFFER_SIZE) { tail = 0; }
serial_tx_buffer_tail = tail;
}
2011-06-03 15:42:28 +02:00
// Turn off Data Register Empty Interrupt to stop tx-streaming if this concludes the transfer
if (tail == serial_tx_buffer_head) { UCSR0B &= ~(1 << UDRIE0); }
2009-01-25 00:48:56 +01:00
}
uint8_t serial_read()
2009-01-25 00:48:56 +01:00
{
uint8_t tail = serial_rx_buffer_tail; // Temporary serial_rx_buffer_tail (to optimize for volatile)
if (serial_rx_buffer_head == tail) {
return SERIAL_NO_DATA;
} else {
uint8_t data = serial_rx_buffer[tail];
tail++;
if (tail == RX_BUFFER_SIZE) { tail = 0; }
serial_rx_buffer_tail = tail;
#ifdef ENABLE_XONXOFF
if ((get_serial_rx_buffer_count() < serial_rx_buffer_LOW) && flow_ctrl == XOFF_SENT) {
flow_ctrl = SEND_XON;
UCSR0B |= (1 << UDRIE0); // Force TX
}
#endif
return data;
}
2009-01-25 00:48:56 +01:00
}
2013-08-21 04:05:16 +02:00
ISR(SERIAL_RX)
2009-01-25 00:48:56 +01:00
{
uint8_t data = UDR0;
uint8_t next_head;
// Pick off runtime command characters directly from the serial stream. These characters are
// not passed into the buffer, but these set system state flag bits for runtime execution.
switch (data) {
case CMD_STATUS_REPORT: sys.execute |= EXEC_STATUS_REPORT; break; // Set as true
case CMD_CYCLE_START: sys.execute |= EXEC_CYCLE_START; break; // Set as true
case CMD_FEED_HOLD: sys.execute |= EXEC_FEED_HOLD; break; // Set as true
Re-factored system states and alarm management. Serial baud support greater than 57600. - Refactored system states to be more clear and concise. Alarm locks processes when position is unknown to indicate to user something has gone wrong. - Changed mc_alarm to mc_reset, which now manages the system reset function. Centralizes it. - Renamed '$X' kill homing lock to kill alarm lock. - Created an alarm error reporting method to clear up what is an alarm: message vs a status error: message. For GUIs mainly. Alarm codes are negative. Status codes are positive. - Serial baud support upto 115200. Previous baudrate calc was unstable for 57600 and above. - Alarm state locks out all g-code blocks, including startup scripts, but allows user to access settings and internal commands. For example, to disable hard limits, if they are problematic. - Hard limits do not respond in an alarm state. - Fixed a problem with the hard limit interrupt during the homing cycle. The interrupt register is still active during the homing cycle and still signal the interrupt to trigger when re-enabled. Instead, just disabled the register. - Homing rate adjusted. All axes move at homing seek rate, regardless of how many axes move at the same time. This is unlike how the stepper module does it as a point to point rate. - New config.h settings to disable the homing rate adjustment and the force homing upon powerup. - Reduced the number of startup lines back down to 2 from 3. This discourages users from placing motion block in there, which can be very dangerous. - Startup blocks now run only after an alarm-free reset or after a homing cycle. Does not run when $X kill is called. For satefy reasons
2012-11-15 01:36:29 +01:00
case CMD_RESET: mc_reset(); break; // Call motion control reset routine.
default: // Write character to buffer
next_head = serial_rx_buffer_head + 1;
if (next_head == RX_BUFFER_SIZE) { next_head = 0; }
// Write data to buffer unless it is full.
if (next_head != serial_rx_buffer_tail) {
serial_rx_buffer[serial_rx_buffer_head] = data;
serial_rx_buffer_head = next_head;
#ifdef ENABLE_XONXOFF
if ((get_serial_rx_buffer_count() >= serial_rx_buffer_FULL) && flow_ctrl == XON_SENT) {
flow_ctrl = SEND_XOFF;
UCSR0B |= (1 << UDRIE0); // Force TX
}
#endif
}
}
2009-01-25 00:48:56 +01:00
}
void serial_reset_read_buffer()
{
serial_rx_buffer_tail = serial_rx_buffer_head;
#ifdef ENABLE_XONXOFF
flow_ctrl = XON_SENT;
#endif
}