summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo C2014-07-27 22:58:42 +0200
committerLeo C2014-07-27 22:58:42 +0200
commit762a42ef835d3692bf0d9bea19f5cfd9cb673a33 (patch)
tree213b38efb598d79d30077555e1ebc12656b3c411
parent4caee1ec599c6d78f5234b218e2ccf5e23eb4bf0 (diff)
downloadz180-stamp-762a42ef835d3692bf0d9bea19f5cfd9cb673a33.zip
Remove flow control, factor out ring buffer
-rw-r--r--avr/ring.h74
-rw-r--r--avr/serial.c126
2 files changed, 87 insertions, 113 deletions
diff --git a/avr/ring.h b/avr/ring.h
new file mode 100644
index 0000000..d57f9aa
--- /dev/null
+++ b/avr/ring.h
@@ -0,0 +1,74 @@
+#ifndef RING_H
+#define RING_H
+
+struct ring {
+ uint8_t *data;
+ uint_fast8_t mask;
+ volatile uint_fast8_t begin;
+ volatile uint_fast8_t end;
+};
+
+
+static inline
+void ring_init(struct ring *ring, uint8_t *buf, int size)
+{
+ ring->data = buf;
+ ring->mask = (size-1) & 0xff;
+ ring->begin = 0;
+ ring->end = 0;
+}
+
+static inline
+int ring_write_ch(struct ring *ring, uint8_t ch)
+{
+ uint_fast8_t ep = ring->end;
+
+ ring->data[ep] = ch;
+ ep = (ep + 1) & ring->mask;
+
+ if ((ep) != ring->begin) {
+ ring->end = ep;
+ return 1;
+ }
+
+ return -1;
+}
+
+#if 0
+static inline
+int ring_write(struct ring *ring, uint8_t *data, int size)
+{
+ int i;
+
+ for (i = 0; i < size; i++) {
+ if (ring_write_ch(ring, data[i]) < 0)
+ return -i;
+ }
+
+ return i;
+}
+#endif
+
+static inline
+int ring_read_ch(struct ring *ring)
+{
+ int ret = -1;
+ uint_fast8_t bp = ring->begin;
+
+ if (bp != ring->end) {
+ ret = ring->data[bp];
+ ring->begin = (bp + 1) & ring->mask;
+ }
+
+ return ret;
+}
+
+
+static inline
+int_fast8_t ring_is_empty(struct ring *ring)
+{
+ return ring->begin == ring->end;
+}
+
+#endif /* RING_H */
+
diff --git a/avr/serial.c b/avr/serial.c
index 4b3cd42..2d2c551 100644
--- a/avr/serial.c
+++ b/avr/serial.c
@@ -7,6 +7,7 @@
#include <errno.h>
#include <stdio.h>
+#include "ring.h"
#include "serial.h"
@@ -14,31 +15,9 @@ static int _write(char c, FILE *stream);
static FILE mystdout = FDEV_SETUP_STREAM(_write,
NULL, _FDEV_SETUP_WRITE);
-#define CTL_S ('S'-'@') /* DC3 (Stop) */
-#define CTL_Q ('Q'-'@') /* DC1 (Start) */
-typedef enum {
- IDLE,
- ACTIVE,
- REQ_STOP,
- REQ_CONT,
- STOPPED
-} xmit_stat_t;
-
-static volatile uint8_t stat_tx;
-static volatile uint8_t stat_rx;
-
-
-struct ring {
- uint8_t *data;
- uint_fast8_t mask;
- volatile uint_fast8_t begin;
- volatile uint_fast8_t end;
-};
-
-
-#define BUFFER_SIZE 256
+#define BUFFER_SIZE 64
#if ((BUFFER_SIZE-1) & BUFFER_SIZE)
# error: BUFFER_SIZE not power of 2
@@ -54,60 +33,6 @@ uint8_t rx_ring_buffer[BUFFER_SIZE];
uint8_t tx_ring_buffer[BUFFER_SIZE];
-static void ring_init(struct ring *ring, uint8_t *buf, int size)
-{
- ring->data = buf;
- ring->mask = (size-1) & 0xff;
- ring->begin = 0;
- ring->end = 0;
-}
-
-static int ring_write_ch(struct ring *ring, uint8_t ch)
-{
- uint_fast8_t ep = (ring->end + 1) & ring->mask;
-
- if ((ep) != ring->begin) {
- ring->data[ring->end] = ch;
- ring->end = ep;
- return 1;
- }
-
- return -1;
-}
-
-#if 0
-static int ring_write(struct ring *ring, uint8_t *data, int size)
-{
- int i;
-
- for (i = 0; i < size; i++) {
- if (ring_write_ch(ring, data[i]) < 0)
- return -i;
- }
-
- return i;
-}
-#endif
-
-static int ring_read_ch(struct ring *ring)
-{
- int ret = -1;
- uint_fast8_t i = ring->begin;
-
- if (i != ring->end) {
- ret = ring->data[i];
- ring->begin = (i +1) & ring->mask;
- }
-
- return ret;
-}
-
-
-static int_fast8_t ring_is_empty(struct ring *ring)
-{
- return ring->begin == ring->end;
-}
-
/* Initialize UART */
@@ -122,17 +47,14 @@ void usart0_setup(void) {
ring_init(&rx_ring, rx_ring_buffer, BUFFER_SIZE);
ring_init(&tx_ring, tx_ring_buffer, BUFFER_SIZE);
- stat_tx = ACTIVE;
- stat_rx = ACTIVE;
-
- UCSR0A = _BV(U2X0);
- UBRR0L = F_CPU / BAUD / 8 - 1;
+ UCSR0A = 0;
+ UBRR0 = F_CPU / BAUD / 16 - 1;
UCSR0B = _BV(RXCIE0) | _BV(RXEN0) | _BV(TXEN0);
UCSR0C = 3 << UCSZ00;
};
}
-
+/*--------------------------------------------------------------------------*/
/* UART RXC interrupt */
@@ -141,41 +63,23 @@ ISR(USART0_RX_vect)
uint8_t d;
d = UDR0;
-
- switch (d) {
- case CTL_S:
- stat_tx = REQ_STOP;
- break;
- case CTL_Q:
- if ((stat_tx == STOPPED) || stat_tx == REQ_STOP) {
- UCSR0B = _BV(RXCIE0) | _BV(RXEN0) | _BV(TXEN0) | _BV(UDRIE0);
- stat_tx = ACTIVE;
- }
- break;
- default:
- ring_write_ch(&rx_ring, d);
- break;
- }
+ ring_write_ch(&rx_ring, d);
}
/* UART UDRE interrupt */
ISR(USART0_UDRE_vect)
{
- uint8_t s;
+ int d = ring_read_ch(&tx_ring);
- s = !ring_is_empty(&tx_ring);
- if ((s == 0) || (stat_tx != ACTIVE)) {
+ if (d < 0) {
+ /* Disable TX empty interrupt. */
UCSR0B = _BV(RXCIE0) | _BV(RXEN0) | _BV(TXEN0);
- if (s)
- stat_tx = STOPPED;
} else {
- UDR0 = ring_read_ch(&tx_ring);
+ UDR0 = d;
}
}
-
-
/*--------------------------------------------------------------------------*/
void serial_setup(void)
@@ -206,12 +110,8 @@ void serial_putc(uint8_t data)
{
while (ring_write_ch(&tx_ring, data) < 0)
;
- switch (stat_tx) {
- case ACTIVE:
- default:
- /* Enable the TXE interrupt. */
- UCSR0B = _BV(RXCIE0) | _BV(RXEN0) | _BV(TXEN0) | _BV(UDRIE0);
- break;
- }
+
+ /* Enable the TXE interrupt. */
+ UCSR0B = _BV(RXCIE0) | _BV(RXEN0) | _BV(TXEN0) | _BV(UDRIE0);
}