summaryrefslogtreecommitdiffstats
path: root/uart.c
diff options
context:
space:
mode:
authorroot <root@no.no.james.local>2014-12-08 18:39:07 +0000
committerroot <root@no.no.james.local>2014-12-08 18:39:07 +0000
commit804820fe687affa38a52e302179e4a2293cb1ffb (patch)
treeacb784fd60af24d8c389e366d74409c75802dfa0 /uart.c
downloadrgb_ring-804820fe687affa38a52e302179e4a2293cb1ffb.tar.gz
rgb_ring-804820fe687affa38a52e302179e4a2293cb1ffb.tar.bz2
rgb_ring-804820fe687affa38a52e302179e4a2293cb1ffb.zip
fish
Diffstat (limited to 'uart.c')
-rw-r--r--uart.c686
1 files changed, 686 insertions, 0 deletions
diff --git a/uart.c b/uart.c
new file mode 100644
index 0000000..eb21b6b
--- /dev/null
+++ b/uart.c
@@ -0,0 +1,686 @@
+/*************************************************************************
+Title: Interrupt UART library with receive/transmit circular buffers
+Author: Peter Fleury <pfleury@gmx.ch> http://jump.to/fleury
+File: $Id: uart.c,v 1.10 2013/06/02 07:27:04 peter Exp $
+Software: AVR-GCC 4.1, AVR Libc 1.4.6 or higher
+Hardware: any AVR with built-in UART,
+License: GNU General Public License
+
+DESCRIPTION:
+ An interrupt is generated when the UART has finished transmitting or
+ receiving a byte. The interrupt handling routines use circular buffers
+ for buffering received and transmitted data.
+
+ The UART_RX_BUFFER_SIZE and UART_TX_BUFFER_SIZE variables define
+ the buffer size in bytes. Note that these variables must be a
+ power of 2.
+
+USAGE:
+ Refere to the header file uart.h for a description of the routines.
+ See also example test_uart.c.
+
+NOTES:
+ Based on Atmel Application Note AVR306
+
+LICENSE:
+ Copyright (C) 2006 Peter Fleury
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+*************************************************************************/
+#include "project.h"
+
+
+/*
+ * constants and macros
+ */
+
+/* size of RX/TX buffers */
+#define UART_RX_BUFFER_MASK ( UART_RX_BUFFER_SIZE - 1)
+#define UART_TX_BUFFER_MASK ( UART_TX_BUFFER_SIZE - 1)
+
+#if ( UART_RX_BUFFER_SIZE & UART_RX_BUFFER_MASK )
+#error RX buffer size is not a power of 2
+#endif
+#if ( UART_TX_BUFFER_SIZE & UART_TX_BUFFER_MASK )
+#error TX buffer size is not a power of 2
+#endif
+
+#if defined(__AVR_AT90S2313__) \
+ || defined(__AVR_AT90S4414__) || defined(__AVR_AT90S4434__) \
+ || defined(__AVR_AT90S8515__) || defined(__AVR_AT90S8535__) \
+ || defined(__AVR_ATmega103__)
+ /* old AVR classic or ATmega103 with one UART */
+#define AT90_UART
+#define UART0_RECEIVE_INTERRUPT UART_RX_vect
+#define UART0_TRANSMIT_INTERRUPT UART_UDRE_vect
+#define UART0_STATUS USR
+#define UART0_CONTROL UCR
+#define UART0_DATA UDR
+#define UART0_UDRIE UDRIE
+#elif defined(__AVR_AT90S2333__) || defined(__AVR_AT90S4433__)
+ /* old AVR classic with one UART */
+#define AT90_UART
+#define UART0_RECEIVE_INTERRUPT UART_RX_vect
+#define UART0_TRANSMIT_INTERRUPT UART_UDRE_vect
+#define UART0_STATUS UCSRA
+#define UART0_CONTROL UCSRB
+#define UART0_DATA UDR
+#define UART0_UDRIE UDRIE
+#elif defined(__AVR_ATmega8__) || defined(__AVR_ATmega16__) || defined(__AVR_ATmega32__) \
+ || defined(__AVR_ATmega323__)
+ /* ATmega with one USART */
+#define ATMEGA_USART
+#define UART0_RECEIVE_INTERRUPT USART_RXC_vect
+#define UART0_TRANSMIT_INTERRUPT USART_UDRE_vect
+#define UART0_STATUS UCSRA
+#define UART0_CONTROL UCSRB
+#define UART0_DATA UDR
+#define UART0_UDRIE UDRIE
+#elif defined (__AVR_ATmega8515__) || defined(__AVR_ATmega8535__)
+#define ATMEGA_USART
+#define UART0_RECEIVE_INTERRUPT USART_RX_vect
+#define UART0_TRANSMIT_INTERRUPT USART_UDRE_vect
+#define UART0_STATUS UCSRA
+#define UART0_CONTROL UCSRB
+#define UART0_DATA UDR
+#define UART0_UDRIE UDRIE
+#elif defined(__AVR_ATmega163__)
+ /* ATmega163 with one UART */
+#define ATMEGA_UART
+#define UART0_RECEIVE_INTERRUPT UART_RX_vect
+#define UART0_TRANSMIT_INTERRUPT UART_UDRE_vect
+#define UART0_STATUS UCSRA
+#define UART0_CONTROL UCSRB
+#define UART0_DATA UDR
+#define UART0_UDRIE UDRIE
+#elif defined(__AVR_ATmega162__)
+ /* ATmega with two USART */
+#define ATMEGA_USART0
+#define ATMEGA_USART1
+#define UART0_RECEIVE_INTERRUPT USART0_RXC_vect
+#define UART1_RECEIVE_INTERRUPT USART1_RXC_vect
+#define UART0_TRANSMIT_INTERRUPT USART0_UDRE_vect
+#define UART1_TRANSMIT_INTERRUPT USART1_UDRE_vect
+#define UART0_STATUS UCSR0A
+#define UART0_CONTROL UCSR0B
+#define UART0_DATA UDR0
+#define UART0_UDRIE UDRIE0
+#define UART1_STATUS UCSR1A
+#define UART1_CONTROL UCSR1B
+#define UART1_DATA UDR1
+#define UART1_UDRIE UDRIE1
+#elif defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__)
+ /* ATmega with two USART */
+#define ATMEGA_USART0
+#define ATMEGA_USART1
+#define UART0_RECEIVE_INTERRUPT USART0_RX_vect
+#define UART1_RECEIVE_INTERRUPT USART1_RX_vect
+#define UART0_TRANSMIT_INTERRUPT USART0_UDRE_vect
+#define UART1_TRANSMIT_INTERRUPT USART1_UDRE_vect
+#define UART0_STATUS UCSR0A
+#define UART0_CONTROL UCSR0B
+#define UART0_DATA UDR0
+#define UART0_UDRIE UDRIE0
+#define UART1_STATUS UCSR1A
+#define UART1_CONTROL UCSR1B
+#define UART1_DATA UDR1
+#define UART1_UDRIE UDRIE1
+#elif defined(__AVR_ATmega161__)
+ /* ATmega with UART */
+#error "AVR ATmega161 currently not supported by this libaray !"
+#elif defined(__AVR_ATmega169__)
+ /* ATmega with one USART */
+#define ATMEGA_USART
+#define UART0_RECEIVE_INTERRUPT USART0_RX_vect
+#define UART0_TRANSMIT_INTERRUPT USART0_UDRE_vect
+#define UART0_STATUS UCSRA
+#define UART0_CONTROL UCSRB
+#define UART0_DATA UDR
+#define UART0_UDRIE UDRIE
+#elif defined(__AVR_ATmega48__) || defined(__AVR_ATmega88__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega48P__) || defined(__AVR_ATmega88P__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__) \
+ || defined(__AVR_ATmega3250__) || defined(__AVR_ATmega3290__) ||defined(__AVR_ATmega6450__) || defined(__AVR_ATmega6490__)
+ /* ATmega with one USART */
+#define ATMEGA_USART0
+#define UART0_RECEIVE_INTERRUPT USART_RX_vect
+#define UART0_TRANSMIT_INTERRUPT USART_UDRE_vect
+#define UART0_STATUS UCSR0A
+#define UART0_CONTROL UCSR0B
+#define UART0_DATA UDR0
+#define UART0_UDRIE UDRIE0
+#elif defined(__AVR_ATtiny2313__)
+#define ATMEGA_USART
+#define UART0_RECEIVE_INTERRUPT USART_RX_vect
+#define UART0_TRANSMIT_INTERRUPT USART_UDRE_vect
+#define UART0_STATUS UCSRA
+#define UART0_CONTROL UCSRB
+#define UART0_DATA UDR
+#define UART0_UDRIE UDRIE
+#elif defined(__AVR_ATmega329__) || \
+ defined(__AVR_ATmega649__) || \
+ defined(__AVR_ATmega325__) || \
+ defined(__AVR_ATmega645__)
+ /* ATmega with one USART */
+#define ATMEGA_USART0
+#define UART0_RECEIVE_INTERRUPT USART0_RX_vect
+#define UART0_TRANSMIT_INTERRUPT USART0_UDRE_vect
+#define UART0_STATUS UCSR0A
+#define UART0_CONTROL UCSR0B
+#define UART0_DATA UDR0
+#define UART0_UDRIE UDRIE0
+#elif defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega640__)
+/* ATmega with two USART */
+#define ATMEGA_USART0
+#define ATMEGA_USART1
+#define UART0_RECEIVE_INTERRUPT USART0_RX_vect
+#define UART1_RECEIVE_INTERRUPT USART1_RX_vect
+#define UART0_TRANSMIT_INTERRUPT USART0_UDRE_vect
+#define UART1_TRANSMIT_INTERRUPT USART1_UDRE_vect
+#define UART0_STATUS UCSR0A
+#define UART0_CONTROL UCSR0B
+#define UART0_DATA UDR0
+#define UART0_UDRIE UDRIE0
+#define UART1_STATUS UCSR1A
+#define UART1_CONTROL UCSR1B
+#define UART1_DATA UDR1
+#define UART1_UDRIE UDRIE1
+#elif defined(__AVR_ATmega644__)
+ /* ATmega with one USART */
+#define ATMEGA_USART0
+#define UART0_RECEIVE_INTERRUPT USART0_RX_vect
+#define UART0_TRANSMIT_INTERRUPT USART0_UDRE_vect
+#define UART0_STATUS UCSR0A
+#define UART0_CONTROL UCSR0B
+#define UART0_DATA UDR0
+#define UART0_UDRIE UDRIE0
+#elif defined(__AVR_ATmega164P__) || defined(__AVR_ATmega324P__) || defined(__AVR_ATmega644P__)
+ /* ATmega with two USART */
+#define ATMEGA_USART0
+#define ATMEGA_USART1
+#define UART0_RECEIVE_INTERRUPT USART0_RX_vect
+#define UART1_RECEIVE_INTERRUPT USART1_RX_vect
+#define UART0_TRANSMIT_INTERRUPT USART0_UDRE_vect
+#define UART1_TRANSMIT_INTERRUPT USART1_UDRE_vect
+#define UART0_STATUS UCSR0A
+#define UART0_CONTROL UCSR0B
+#define UART0_DATA UDR0
+#define UART0_UDRIE UDRIE0
+#define UART1_STATUS UCSR1A
+#define UART1_CONTROL UCSR1B
+#define UART1_DATA UDR1
+#define UART1_UDRIE UDRIE1
+#else
+#error "no UART definition for MCU available"
+#endif
+
+
+/*
+ * module global variables
+ */
+static volatile unsigned char UART_TxBuf[UART_TX_BUFFER_SIZE];
+static volatile unsigned char UART_RxBuf[UART_RX_BUFFER_SIZE];
+static volatile unsigned char UART_TxHead;
+static volatile unsigned char UART_TxTail;
+static volatile unsigned char UART_RxHead;
+static volatile unsigned char UART_RxTail;
+static volatile unsigned char UART_LastRxError;
+
+#if defined( ATMEGA_USART1 )
+static volatile unsigned char UART1_TxBuf[UART_TX_BUFFER_SIZE];
+static volatile unsigned char UART1_RxBuf[UART_RX_BUFFER_SIZE];
+static volatile unsigned char UART1_TxHead;
+static volatile unsigned char UART1_TxTail;
+static volatile unsigned char UART1_RxHead;
+static volatile unsigned char UART1_RxTail;
+static volatile unsigned char UART1_LastRxError;
+#endif
+
+
+
+ISR (NOPROTO UART0_RECEIVE_INTERRUPT)
+/*************************************************************************
+Function: UART Receive Complete interrupt
+Purpose: called when the UART has received a character
+**************************************************************************/
+{
+ unsigned char tmphead;
+ unsigned char data;
+ unsigned char usr;
+ unsigned char lastRxError;
+
+
+ /* read UART status register and UART data register */
+ usr = UART0_STATUS;
+ data = UART0_DATA;
+
+ /* */
+#if defined( AT90_UART )
+ lastRxError = (usr & (_BV (FE) | _BV (DOR)));
+#elif defined( ATMEGA_USART )
+ lastRxError = (usr & (_BV (FE) | _BV (DOR)));
+#elif defined( ATMEGA_USART0 )
+ lastRxError = (usr & (_BV (FE0) | _BV (DOR0)));
+#elif defined ( ATMEGA_UART )
+ lastRxError = (usr & (_BV (FE) | _BV (DOR)));
+#endif
+
+ /* calculate buffer index */
+ tmphead = (UART_RxHead + 1) & UART_RX_BUFFER_MASK;
+
+ if (tmphead == UART_RxTail)
+ {
+ /* error: receive buffer overflow */
+ lastRxError = UART_BUFFER_OVERFLOW >> 8;
+ }
+ else
+ {
+ /* store new index */
+ UART_RxHead = tmphead;
+ /* store received data in buffer */
+ UART_RxBuf[tmphead] = data;
+ }
+ UART_LastRxError |= lastRxError;
+}
+
+
+ISR (NOPROTO UART0_TRANSMIT_INTERRUPT)
+/*************************************************************************
+Function: UART Data Register Empty interrupt
+Purpose: called when the UART is ready to transmit the next byte
+**************************************************************************/
+{
+ unsigned char tmptail;
+
+
+ if (UART_TxHead != UART_TxTail)
+ {
+ /* calculate and store new buffer index */
+ tmptail = (UART_TxTail + 1) & UART_TX_BUFFER_MASK;
+ UART_TxTail = tmptail;
+ /* get one byte from buffer and write it to UART */
+ UART0_DATA = UART_TxBuf[tmptail]; /* start transmission */
+ }
+ else
+ {
+ /* tx buffer empty, disable UDRE interrupt */
+ UART0_CONTROL &= ~_BV (UART0_UDRIE);
+ }
+}
+
+
+/*************************************************************************
+Function: uart_init()
+Purpose: initialize UART and set baudrate
+Input: baudrate using macro UART_BAUD_SELECT()
+Returns: none
+**************************************************************************/
+void
+uart_init (unsigned int baudrate)
+{
+ UART_TxHead = 0;
+ UART_TxTail = 0;
+ UART_RxHead = 0;
+ UART_RxTail = 0;
+
+#if defined( AT90_UART )
+ /* set baud rate */
+ UBRR = (unsigned char) baudrate;
+
+ /* enable UART receiver and transmmitter and receive complete interrupt */
+ UART0_CONTROL = _BV (RXCIE) | _BV (RXEN) | _BV (TXEN);
+
+#elif defined (ATMEGA_USART)
+ /* Set baud rate */
+ if (baudrate & 0x8000)
+ {
+ UART0_STATUS = (1 << U2X); //Enable 2x speed
+ baudrate &= ~0x8000;
+ }
+ UBRRH = (unsigned char) (baudrate >> 8);
+ UBRRL = (unsigned char) baudrate;
+
+ /* Enable USART receiver and transmitter and receive complete interrupt */
+ UART0_CONTROL = _BV (RXCIE) | (1 << RXEN) | (1 << TXEN);
+
+ /* Set frame format: asynchronous, 8data, no parity, 1stop bit */
+#ifdef URSEL
+ UCSRC = (1 << URSEL) | (3 << UCSZ0);
+#else
+ UCSRC = (3 << UCSZ0);
+#endif
+
+#elif defined (ATMEGA_USART0 )
+ /* Set baud rate */
+ if (baudrate & 0x8000)
+ {
+ UART0_STATUS = (1 << U2X0); //Enable 2x speed
+ baudrate &= ~0x8000;
+ }
+ UBRR0H = (unsigned char) (baudrate >> 8);
+ UBRR0L = (unsigned char) baudrate;
+
+ /* Enable USART receiver and transmitter and receive complete interrupt */
+ UART0_CONTROL = _BV (RXCIE0) | (1 << RXEN0) | (1 << TXEN0);
+
+ /* Set frame format: asynchronous, 8data, no parity, 1stop bit */
+#ifdef URSEL0
+ UCSR0C = (1 << URSEL0) | (3 << UCSZ00);
+#else
+ UCSR0C = (3 << UCSZ00);
+#endif
+
+#elif defined ( ATMEGA_UART )
+ /* set baud rate */
+ if (baudrate & 0x8000)
+ {
+ UART0_STATUS = (1 << U2X); //Enable 2x speed
+ baudrate &= ~0x8000;
+ }
+ UBRRHI = (unsigned char) (baudrate >> 8);
+ UBRR = (unsigned char) baudrate;
+
+ /* Enable UART receiver and transmitter and receive complete interrupt */
+ UART0_CONTROL = _BV (RXCIE) | (1 << RXEN) | (1 << TXEN);
+
+#endif
+
+} /* uart_init */
+
+
+/*************************************************************************
+Function: uart_getc()
+Purpose: return byte from ringbuffer
+Returns: lower byte: received byte from ringbuffer
+ higher byte: last receive error
+**************************************************************************/
+unsigned int
+uart_getc (void)
+{
+ unsigned char tmptail;
+ unsigned char data;
+
+
+ if (UART_RxHead == UART_RxTail)
+ {
+ return UART_NO_DATA; /* no data available */
+ }
+
+ /* calculate /store buffer index */
+ tmptail = (UART_RxTail + 1) & UART_RX_BUFFER_MASK;
+ UART_RxTail = tmptail;
+
+ /* get data from receive buffer */
+ data = UART_RxBuf[tmptail];
+
+ data = (UART_LastRxError << 8) + data;
+ UART_LastRxError = 0;
+ return data;
+
+} /* uart_getc */
+
+
+/*************************************************************************
+Function: uart_putc()
+Purpose: write byte to ringbuffer for transmitting via UART
+Input: byte to be transmitted
+Returns: none
+**************************************************************************/
+void
+uart_putc (unsigned char data)
+{
+ unsigned char tmphead;
+
+
+ tmphead = (UART_TxHead + 1) & UART_TX_BUFFER_MASK;
+
+ while (tmphead == UART_TxTail)
+ {
+ ; /* wait for free space in buffer */
+ }
+
+ UART_TxBuf[tmphead] = data;
+ UART_TxHead = tmphead;
+
+ /* enable UDRE interrupt */
+ UART0_CONTROL |= _BV (UART0_UDRIE);
+
+} /* uart_putc */
+
+
+/*************************************************************************
+Function: uart_puts()
+Purpose: transmit string to UART
+Input: string to be transmitted
+Returns: none
+**************************************************************************/
+void
+uart_puts (const char *s)
+{
+ while (*s)
+ uart_putc (*s++);
+
+} /* uart_puts */
+
+
+/*************************************************************************
+Function: uart_puts_p()
+Purpose: transmit string from program memory to UART
+Input: program memory string to be transmitted
+Returns: none
+**************************************************************************/
+void
+uart_puts_p (const char *progmem_s)
+{
+ register char c;
+
+ while ((c = pgm_read_byte (progmem_s++)))
+ uart_putc (c);
+
+} /* uart_puts_p */
+
+
+/*
+ * these functions are only for ATmegas with two USART
+ */
+#if defined( ATMEGA_USART1 )
+
+ISR (NOPROTO UART1_RECEIVE_INTERRUPT)
+/*************************************************************************
+Function: UART1 Receive Complete interrupt
+Purpose: called when the UART1 has received a character
+**************************************************************************/
+{
+ unsigned char tmphead;
+ unsigned char data;
+ unsigned char usr;
+ unsigned char lastRxError;
+
+
+ /* read UART status register and UART data register */
+ usr = UART1_STATUS;
+ data = UART1_DATA;
+
+ /* */
+ lastRxError = (usr & (_BV (FE1) | _BV (DOR1)));
+
+ /* calculate buffer index */
+ tmphead = (UART1_RxHead + 1) & UART_RX_BUFFER_MASK;
+
+ if (tmphead == UART1_RxTail)
+ {
+ /* error: receive buffer overflow */
+ lastRxError = UART_BUFFER_OVERFLOW >> 8;
+ }
+ else
+ {
+ /* store new index */
+ UART1_RxHead = tmphead;
+ /* store received data in buffer */
+ UART1_RxBuf[tmphead] = data;
+ }
+ UART1_LastRxError |= lastRxError;
+}
+
+
+ISR (NOPROTO UART1_TRANSMIT_INTERRUPT)
+/*************************************************************************
+Function: UART1 Data Register Empty interrupt
+Purpose: called when the UART1 is ready to transmit the next byte
+**************************************************************************/
+{
+ unsigned char tmptail;
+
+
+ if (UART1_TxHead != UART1_TxTail)
+ {
+ /* calculate and store new buffer index */
+ tmptail = (UART1_TxTail + 1) & UART_TX_BUFFER_MASK;
+ UART1_TxTail = tmptail;
+ /* get one byte from buffer and write it to UART */
+ UART1_DATA = UART1_TxBuf[tmptail]; /* start transmission */
+ }
+ else
+ {
+ /* tx buffer empty, disable UDRE interrupt */
+ UART1_CONTROL &= ~_BV (UART1_UDRIE);
+ }
+}
+
+
+/*************************************************************************
+Function: uart1_init()
+Purpose: initialize UART1 and set baudrate
+Input: baudrate using macro UART_BAUD_SELECT()
+Returns: none
+**************************************************************************/
+void
+uart1_init (unsigned int baudrate)
+{
+ UART1_TxHead = 0;
+ UART1_TxTail = 0;
+ UART1_RxHead = 0;
+ UART1_RxTail = 0;
+
+
+ /* Set baud rate */
+ if (baudrate & 0x8000)
+ {
+ UART1_STATUS = (1 << U2X1); //Enable 2x speed
+ baudrate &= ~0x8000;
+ }
+ UBRR1H = (unsigned char) (baudrate >> 8);
+ UBRR1L = (unsigned char) baudrate;
+
+ /* Enable USART receiver and transmitter and receive complete interrupt */
+ UART1_CONTROL = _BV (RXCIE1) | (1 << RXEN1) | (1 << TXEN1);
+
+ /* Set frame format: asynchronous, 8data, no parity, 1stop bit */
+#ifdef URSEL1
+ UCSR1C = (1 << URSEL1) | (3 << UCSZ10);
+#else
+ UCSR1C = (3 << UCSZ10);
+#endif
+} /* uart_init */
+
+
+/*************************************************************************
+Function: uart1_getc()
+Purpose: return byte from ringbuffer
+Returns: lower byte: received byte from ringbuffer
+ higher byte: last receive error
+**************************************************************************/
+unsigned int
+uart1_getc (void)
+{
+ unsigned char tmptail;
+ unsigned char data;
+
+
+ if (UART1_RxHead == UART1_RxTail)
+ {
+ return UART_NO_DATA; /* no data available */
+ }
+
+ /* calculate /store buffer index */
+ tmptail = (UART1_RxTail + 1) & UART_RX_BUFFER_MASK;
+ UART1_RxTail = tmptail;
+
+ /* get data from receive buffer */
+ data = UART1_RxBuf[tmptail];
+
+ data = (UART1_LastRxError << 8) + data;
+ UART1_LastRxError = 0;
+ return data;
+
+} /* uart1_getc */
+
+
+/*************************************************************************
+Function: uart1_putc()
+Purpose: write byte to ringbuffer for transmitting via UART
+Input: byte to be transmitted
+Returns: none
+**************************************************************************/
+void
+uart1_putc (unsigned char data)
+{
+ unsigned char tmphead;
+
+
+ tmphead = (UART1_TxHead + 1) & UART_TX_BUFFER_MASK;
+
+ while (tmphead == UART1_TxTail)
+ {
+ ; /* wait for free space in buffer */
+ }
+
+ UART1_TxBuf[tmphead] = data;
+ UART1_TxHead = tmphead;
+
+ /* enable UDRE interrupt */
+ UART1_CONTROL |= _BV (UART1_UDRIE);
+
+} /* uart1_putc */
+
+
+/*************************************************************************
+Function: uart1_puts()
+Purpose: transmit string to UART1
+Input: string to be transmitted
+Returns: none
+**************************************************************************/
+void
+uart1_puts (const char *s)
+{
+ while (*s)
+ uart1_putc (*s++);
+
+} /* uart1_puts */
+
+
+/*************************************************************************
+Function: uart1_puts_p()
+Purpose: transmit string from program memory to UART1
+Input: program memory string to be transmitted
+Returns: none
+**************************************************************************/
+void
+uart1_puts_p (const char *progmem_s)
+{
+ register char c;
+
+ while ((c = pgm_read_byte (progmem_s++)))
+ uart1_putc (c);
+
+} /* uart1_puts_p */
+
+
+#endif