Make XON/XOFF flow control actually work. Still disabled by default.

This commit is contained in:
Markus Hitter 2010-09-08 19:10:54 +02:00
parent b2e1cfd8b5
commit 8b5e21be51
2 changed files with 25 additions and 11 deletions

View File

@ -21,6 +21,10 @@ uint8_t queue_empty() {
return ((mb_tail == mb_head) && (movebuffer[mb_tail].live == 0))?255:0;
}
// -------------------------------------------------------
// This is the one function called by the timer interrupt.
// It calls a few other functions, though.
// -------------------------------------------------------
void queue_step() {
disableTimerInterrupt();
@ -71,8 +75,9 @@ void enqueue(TARGET *t) {
mb_head = h;
#ifdef XONXOFF
// if queue is full, stop transmission
if (queue_full())
// If the queue has only two slots remaining, stop transmission. More
// characters might come in until the stop takes effect.
if (((mb_tail - mb_head - 1) & (MOVEBUFFER_SIZE - 1)) < (MOVEBUFFER_SIZE - 2))
xoff();
#endif
@ -105,8 +110,7 @@ void enqueue_temp_wait() {
mb_head = h;
#ifdef XONXOFF
// if queue is full, stop transmission
if (queue_full())
if (((mb_tail - mb_head - 1) & (MOVEBUFFER_SIZE - 1)) < (MOVEBUFFER_SIZE - 2))
xoff();
#endif

View File

@ -48,8 +48,7 @@ volatile uint8_t txbuf[BUFSIZE];
#ifdef XONXOFF
#define FLOWFLAG_SEND_XON 1
#define FLOWFLAG_SEND_XOFF 2
#define FLOWFLAG_SENT_XON 4
#define FLOWFLAG_SENT_XOFF 8
#define FLOWFLAG_STATE_XON 4
// initially, send an XON
volatile uint8_t flowflags = FLOWFLAG_SEND_XON;
#endif
@ -88,11 +87,11 @@ ISR(USART_UDRE_vect)
#ifdef XONXOFF
if (flowflags & FLOWFLAG_SEND_XON) {
UDR0 = ASCII_XON;
flowflags = (flowflags & ~FLOWFLAG_SEND_XON) | FLOWFLAG_SENT_XON;
flowflags = FLOWFLAG_STATE_XON;
}
else if (flowflags & FLOWFLAG_SEND_XOFF) {
UDR0 = ASCII_XOFF;
flowflags = (flowflags & ~FLOWFLAG_SEND_XOFF) | FLOWFLAG_SENT_XOFF;
flowflags = 0;
}
else
#endif
@ -193,15 +192,26 @@ void serial_writestr_P(PGM_P data)
#ifdef XONXOFF
void xon() {
if (flowflags & FLOWFLAG_SENT_XOFF)
// disable TX interrupt
UCSR0B &= ~MASK(UDRIE0);
if ((flowflags & FLOWFLAG_STATE_XON) == 0)
flowflags = FLOWFLAG_SEND_XON;
else
flowflags = FLOWFLAG_STATE_XON; // purge a possible FLOWFLAG_SEND_XOFF
// enable TX interrupt so we can send this character
UCSR0B |= MASK(UDRIE0);
}
void xoff() {
flowflags = FLOWFLAG_SEND_XOFF;
// enable TX interrupt so we can send this character
UCSR0B &= ~MASK(UDRIE0);
if (flowflags & FLOWFLAG_STATE_XON)
flowflags = FLOWFLAG_SEND_XOFF | FLOWFLAG_STATE_XON;
else
flowflags = 0;
UCSR0B |= MASK(UDRIE0);
}
#endif