summaryrefslogtreecommitdiff
path: root/n/avr
diff options
context:
space:
mode:
authorschodet2004-06-28 20:44:13 +0000
committerschodet2004-06-28 20:44:13 +0000
commit7b0df2649af57d4a1ac019cda5eb0e261b5d97de (patch)
treecd62245b1bc472085f97a5520af2378da5a7a02e /n/avr
parent5f511221ebe3991fc1084eb979474857e45df2b1 (diff)
Add: gestion d'un ring buffer par interruptions.
Diffstat (limited to 'n/avr')
-rw-r--r--n/avr/rs232/avrconfig.h20
-rw-r--r--n/avr/rs232/rs232.c189
2 files changed, 191 insertions, 18 deletions
diff --git a/n/avr/rs232/avrconfig.h b/n/avr/rs232/avrconfig.h
index a497a22..b661fe9 100644
--- a/n/avr/rs232/avrconfig.h
+++ b/n/avr/rs232/avrconfig.h
@@ -33,13 +33,27 @@
/** Baudrate : 2400, 4800, 9600, 14400, 19200, 28800, 38400, 57600, 76800,
* 115200, 230400, 250000, 500000, 1000000. */
#define AC_RS232_BAUDRATE 115200
-/** Choose between interrupt (1) or polling (0). */
-#define AC_RS232_INTERRUPT 0
+/** Send mode :
+ * - POLLING : no interrupts;
+ * - RING : interrupts, ring buffer;
+ * - PACKETS : interrupts, by packets delimited by SOP and EOP
+ * (unimplemented). */
+#define AC_RS232_SEND_MODE POLLING
+/** Recv mode, same as send mode. */
+#define AC_RS232_RECV_MODE POLLING
/** Parity : ODD, EVEN, NONE. */
#define AC_RS232_PARITY ODD
/** Stop bits : 1, 2. */
#define AC_RS232_STOP_BITS 2
-/** Character size : 5, 6, 7, 8, 9. */
+/** Character size : 5, 6, 7, 8, 9 (only 8 implemented). */
#define AC_RS232_CHAR_SIZE 8
+/** SOP (Start of packet) caracter. */
+#define AC_RS232_SOP(c) ((c) == '!')
+/** EOP (End of packet) caracter. */
+#define AC_RS232_EOP(c) ((c) == '\r')
+/** Send buffer size, should be power of 2 for RING mode. */
+#define AC_RS232_SEND_BUFFER_SIZE 32
+/** Recv buffer size, should be power of 2 for RING mode. */
+#define AC_RS232_RECV_BUFFER_SIZE 32
#endif /* avrconfig_h */
diff --git a/n/avr/rs232/rs232.c b/n/avr/rs232/rs232.c
index 91efa44..6022aa0 100644
--- a/n/avr/rs232/rs232.c
+++ b/n/avr/rs232/rs232.c
@@ -24,29 +24,42 @@
#include "rs232.h"
#include <avr/io.h>
+#include <avr/signal.h>
+#include <inttypes.h>
/* Tested AVR check. */
#if defined (__AVR_ATmega8__)
-# define SELECTOR _BV (URSEL)
#elif defined (__AVR_ATmega8535__)
-# define SELECTOR _BV (URSEL)
#elif defined (__AVR_ATmega128__)
-# define UBRRH UBRR0H
-# define UBRRL UBRR0L
-# define UCSRA UCSR0A
-# define UCSRB UCSR0B
-# define UCSRC UCSR0C
-# define UDR UDR0
-# define SELECTOR 0
#else
# warning "rs232: not tested on this chip."
#endif
-/* Unimplemented features. */
-#if AC_RS232_INTERRUPT
-# error "rs232: interrupts to be implemented."
+/* UART number. */
+#if !defined (UBRRH)
+# if defined (UBRR0H)
+# define UBRRH UBRR0H
+# define UBRRL UBRR0L
+# define UCSRA UCSR0A
+# define UCSRB UCSR0B
+# define UCSRC UCSR0C
+# define UDR UDR0
+# define SIG_UART_RECV SIG_UART0_RECV
+# define SIG_UART_DATA SIG_UART0_DATA
+# define PE UPE
+# else
+# error "rs232: canot find UBRR."
+# endif
+#endif
+
+/* UR selector. */
+#if defined (URSEL)
+# define SELECTOR _BV (URSEL)
+#else
+# define SELECTOR 0
#endif
+/* Unimplemented features. */
#if AC_RS232_CHAR_SIZE != 8
# error "rs232: char size != 8 not implemented."
#endif
@@ -63,6 +76,21 @@
#warning "rs232: baud rate error > 0."
#endif
+/* Mode. */
+#define POLLING 0
+#define RING 1
+#define PACKETS 2
+#define SEND_MODE AC_RS232_SEND_MODE
+#define RECV_MODE AC_RS232_RECV_MODE
+#if RECV_MODE == POLLING
+# define RECV_IE 0
+#else
+# define RECV_IE _BV (RXCIE)
+#endif
+#if SEND_MODE == PACKETS || RECV_MODE == PACKETS
+# error "rs232: packet mode not implemented."
+#endif
+
/* Parity. */
#define ODD (_BV (UPM1) | _BV (UPM0))
#define EVEN _BV (UPM1)
@@ -81,6 +109,46 @@
/* Character size. */
#define CHAR_SIZE (_BV (UCSZ1) | _BV (UCSZ0))
+/* Buffers. */
+#if SEND_MODE == RING || SEND_MODE == PACKETS
+# define SEND_BUFFER_SIZE AC_RS232_SEND_BUFFER_SIZE
+#endif
+#if SEND_MODE == RING
+# define SEND_BUFFER_MASK (SEND_BUFFER_SIZE - 1)
+# if SEND_BUFFER_SIZE & SEND_BUFFER_MASK
+# error "rs232: send buffer size must be a power of 2."
+# endif
+#endif
+#if RECV_MODE == RING || RECV_MODE == PACKETS
+# define RECV_BUFFER_SIZE AC_RS232_RECV_BUFFER_SIZE
+#endif
+#if RECV_MODE == RING
+# define RECV_BUFFER_MASK (RECV_BUFFER_SIZE - 1)
+# if RECV_BUFFER_SIZE & RECV_BUFFER_MASK
+# error "rs232: recv buffer size must be a power of 2."
+# endif
+#endif
+
+/* Send buffer. */
+#if SEND_MODE != POLLING
+uint8_t rs232_send_buffer[SEND_BUFFER_SIZE];
+#endif
+#if SEND_MODE == RING
+volatile uint8_t rs232_send_head, rs232_send_tail;
+#endif
+
+/* Recv buffer. */
+#if RECV_MODE != POLLING
+uint8_t rs232_recv_buffer[RECV_BUFFER_SIZE];
+#endif
+#if RECV_MODE == RING
+volatile uint8_t rs232_recv_head, rs232_recv_tail;
+#endif
+
+/* Last error code. */
+#define ERROR_BITS (_BV (FE) | _BV (DOR) | _BV (PE))
+volatile uint8_t rs232_error_code;
+
/* +AutoDec */
/* -AutoDec */
@@ -94,22 +162,113 @@ rs232_init (void)
UCSRA = 0;
/* Set format and enable rs232. */
UCSRC = SELECTOR | PARITY | STOP_BITS | CHAR_SIZE;
- UCSRB = _BV (RXEN) | _BV (TXEN);
+ UCSRB = RECV_IE | _BV (RXEN) | _BV (TXEN);
+#if RECV_MODE == RING
+ rs232_recv_head = 0;
+ rs232_recv_tail = 0;
+#endif
+#if SEND_MODE == RING
+ rs232_send_head = 0;
+ rs232_send_tail = 0;
+#endif
+ rs232_error_code = 0;
}
/** Read a char. */
-unsigned char
+uint8_t
rs232_getc (void)
{
+#if RECV_MODE == POLLING
+ uint8_t tmperr;
loop_until_bit_is_set (UCSRA, RXC);
+ tmperr = UCSRA & ERROR_BITS;
+ if (tmperr)
+ rs232_error_code = tmperr;
return UDR;
+#elif RECV_MODE == RING
+ uint8_t tmptail = rs232_recv_tail;
+ while (rs232_recv_head == tmptail)
+ ;
+ tmptail = (tmptail + 1) & RECV_BUFFER_MASK;
+ rs232_recv_tail = tmptail;
+ return rs232_recv_buffer[tmptail];
+#endif
}
/** Write a char. */
void
-rs232_putc (unsigned char c)
+rs232_putc (uint8_t c)
{
+#if SEND_MODE == POLLING
loop_until_bit_is_set (UCSRA, UDRE);
UDR = c;
+#elif SEND_MODE == RING
+ uint8_t tmphead;
+ tmphead = (rs232_send_head + 1) & SEND_BUFFER_MASK;
+ while (tmphead == rs232_send_tail)
+ ;
+ rs232_send_buffer[tmphead] = c;
+ rs232_send_head = tmphead;
+ UCSRB |= _BV (UDRIE);
+#endif
+}
+
+/** Retrieve error condition, 0 if no error. */
+uint8_t
+rs232_error (void)
+{
+ return rs232_error_code;
+}
+
+/** Retrieve availlable chars. */
+uint8_t
+rs232_poll (void)
+{
+#if RECV_MODE == POLLING
+ return UCSRA & RXC;
+#elif RECV_MODE == RING
+ return (rs232_recv_head - rs232_recv_tail) & RECV_BUFFER_MASK;
+#endif
+}
+
+#if RECV_MODE == RING
+
+/* Handle received char for ring buffer. */
+INTERRUPT (SIG_UART_RECV)
+{
+ uint8_t c;
+ uint8_t tmphead;
+ uint8_t tmperr;
+ tmperr = UCSRA & ERROR_BITS;
+ if (tmperr)
+ rs232_error_code = tmperr;
+ c = UDR;
+ tmphead = (rs232_recv_head + 1) & RECV_BUFFER_MASK;
+ rs232_recv_head = tmphead;
+ /* If overflowed, clear the receive buffer. */
+ if (tmphead == rs232_recv_tail)
+ rs232_error_code = 0xff;
+ rs232_recv_buffer[tmphead] = c;
+}
+
+#endif /* RECV_MODE == RING */
+
+#if SEND_MODE == RING
+
+/** Handle data register empty for ring buffer. */
+INTERRUPT (SIG_UART_DATA)
+{
+ uint8_t tmptail;
+ if (rs232_send_head != rs232_send_tail)
+ {
+ tmptail = (rs232_send_tail + 1) & SEND_BUFFER_MASK;
+ rs232_send_tail = tmptail;
+ UDR = rs232_send_buffer[tmptail];
+ }
+ else
+ {
+ UCSRB &= ~_BV (UDRIE);
+ }
}
+#endif /* SEND_MODE == RING */