From 6f11fafbefc44d5c109eb6ca4c2cfad7682c8940 Mon Sep 17 00:00:00 2001 From: Mika Tuupola Date: Fri, 13 Jan 2012 23:41:19 +0200 Subject: [PATCH] Sync Triple-A libraries. --- tpic6b595_shiftout/pins/arduino.h | 72 +++++++++ tpic6b595_shiftout/pins/digital.h | 33 ++++ tpic6b595_shiftout/pins/pins.h | 228 +++++++++++++++++++++++++++ tpic6b595_shiftout/uart/uart.c | 90 +++++++++++ tpic6b595_shiftout/uart/uart.h | 23 +++ tpic6b595_shiftout/uart/uart_async.c | 155 ++++++++++++++++++ 6 files changed, 601 insertions(+) create mode 100644 tpic6b595_shiftout/pins/arduino.h create mode 100644 tpic6b595_shiftout/pins/digital.h create mode 100644 tpic6b595_shiftout/pins/pins.h create mode 100644 tpic6b595_shiftout/uart/uart.c create mode 100644 tpic6b595_shiftout/uart/uart.h create mode 100644 tpic6b595_shiftout/uart/uart_async.c diff --git a/tpic6b595_shiftout/pins/arduino.h b/tpic6b595_shiftout/pins/arduino.h new file mode 100644 index 0000000..b5089b8 --- /dev/null +++ b/tpic6b595_shiftout/pins/arduino.h @@ -0,0 +1,72 @@ +/* + * arduino.h + * + * Lightweight macro implementation of Arduino style pin numbering + * for accessing Atmel digital and analog pins. + * + * pin_mode(1, OUTPUT); + * digital_write(1, HIGH); + * pin_mode(2, INPUT); + * digital_read(2); + * + * This file is based on Arduino project. + * https://github.com/arduino/Arduino/ + * + * Copyright (c) 2007-2011 David A. Mellis, Mika tuupola + * + * Licensed under the LGPL 2.1 license: + * http://www.opensource.org/licenses/lgpl-2.1.php + */ + +#ifndef ARDUINO_H +#define ARDUINO_H + +/* atmega328 */ +#define PORT_AT_PIN_0 PortD +#define PORT_AT_PIN_1 PortD +#define PORT_AT_PIN_2 PortD +#define PORT_AT_PIN_3 PortD +#define PORT_AT_PIN_4 PortD +#define PORT_AT_PIN_5 PortD +#define PORT_AT_PIN_6 PortD +#define PORT_AT_PIN_7 PortD +#define PORT_AT_PIN_8 PortB +#define PORT_AT_PIN_9 PortB +#define PORT_AT_PIN_10 PortB +#define PORT_AT_PIN_11 PortB +#define PORT_AT_PIN_12 PortB +#define PORT_AT_PIN_13 PortB +#define PORT_AT_PIN_14 PortC +#define PORT_AT_PIN_15 PortC +#define PORT_AT_PIN_16 PortC +#define PORT_AT_PIN_17 PortC +#define PORT_AT_PIN_18 PortC +#define PORT_AT_PIN_19 PortC + +#define PORT_AT_PIN_20 PortB +#define PORT_AT_PIN_21 PortB + +#define MASK_AT_PIN_0 _BV(0) +#define MASK_AT_PIN_1 _BV(1) +#define MASK_AT_PIN_2 _BV(2) +#define MASK_AT_PIN_3 _BV(3) +#define MASK_AT_PIN_4 _BV(4) +#define MASK_AT_PIN_5 _BV(5) +#define MASK_AT_PIN_6 _BV(6) +#define MASK_AT_PIN_7 _BV(7) +#define MASK_AT_PIN_8 _BV(0) +#define MASK_AT_PIN_9 _BV(1) +#define MASK_AT_PIN_10 _BV(2) +#define MASK_AT_PIN_11 _BV(3) +#define MASK_AT_PIN_12 _BV(4) +#define MASK_AT_PIN_13 _BV(5) +#define MASK_AT_PIN_14 _BV(0) +#define MASK_AT_PIN_15 _BV(1) +#define MASK_AT_PIN_16 _BV(2) +#define MASK_AT_PIN_17 _BV(3) +#define MASK_AT_PIN_18 _BV(4) +#define MASK_AT_PIN_19 _BV(5) +#define MASK_AT_PIN_20 _BV(6) +#define MASK_AT_PIN_21 _BV(7) + +#endif /* ARDUINO_H */ diff --git a/tpic6b595_shiftout/pins/digital.h b/tpic6b595_shiftout/pins/digital.h new file mode 100644 index 0000000..82da4e4 --- /dev/null +++ b/tpic6b595_shiftout/pins/digital.h @@ -0,0 +1,33 @@ +/* + * digital.h + * + * Lightweight macro implementation of AVR pin numbering for + * accessing Atmel digital and analog pins. + * + * pin_mode(A1, OUTPUT); + * digital_write(A1, HIGH); + * pin_mode(A2, INPUT); + * digital_read(A2); + * + * This file is based on the excellent ArduinoLite project by + * Shikai Chen . + * + * http://code.google.com/p/arduino-lite/ + * http://www.csksoft.net/ + * + * Copyright (c) 2010-2011 Shikai Chen, Mika Tuupola + * + * Licensed under the LGPL 2.1 license: + * http://www.opensource.org/licenses/lgpl-2.1.php + */ + +#ifndef DIGITAL_H +#define DIGITAL_H +#include "pins.h" + +#define digital_read(pin) EXPAND_WRAPPER(_DIGITAL_READ, PIN_TO_PORT(pin), PIN_TO_MASK(pin)) +#define digital_read_raw(pin) EXPAND_WRAPPER(_DIGITAL_READ_RAW, PIN_TO_PORT(pin), PIN_TO_MASK(pin)) +#define digital_write(pin, val) DIGITAL_WRITE_##val(pin) +#define digital_toggle(pin) EXPAND_WRAPPER(_DIGITAL_TOGGLE, PIN_TO_PORT(pin), PIN_TO_MASK(pin)) + +#endif /* DIGITAL_H */ \ No newline at end of file diff --git a/tpic6b595_shiftout/pins/pins.h b/tpic6b595_shiftout/pins/pins.h new file mode 100644 index 0000000..1cce133 --- /dev/null +++ b/tpic6b595_shiftout/pins/pins.h @@ -0,0 +1,228 @@ +/* + * pins.h + * + * Lightweight macro implementation of AVR pin numbering for + * accessing Atmel digital and analog pins. + * + * pin_mode(A1, OUTPUT); + * digital_write(A1, HIGH); + * pin_mode(A2, INPUT); + * digital_read(A2); + * + * This file is based on the excellent ArduinoLite project by + * Shikai Chen . + * + * http://code.google.com/p/arduino-lite/ + * http://www.csksoft.net/ + * + * Copyright (c) 2010-2011 Shikai Chen, Mika Tuupola + * + * Licensed under the LGPL 2.1 license: + * http://www.opensource.org/licenses/lgpl-2.1.php + */ + +#ifndef PINS_H +#define PINS_H + +#include +#include + +#include "arduino.h" + +#define HIGH 0x1 +#define LOW 0x0 + +#define INPUT 0x0 +#define OUTPUT 0x1 + +#define ENABLE 0x1 +#define DISABLE 0x0 + +#define PIN_TO_PORT(x) PORT_AT_PIN_##x +#define PIN_TO_MASK(x) MASK_AT_PIN_##x + +#define PORT_TO_DIRECTION_REGISTER(x) DIRECTION_REGISTER_AT_##x +#define PORT_TO_OUTPUT_REGISTER(x) OUTPUT_REGISTER_AT_##x +#define PORT_TO_INPUT_REGISTER(x) INPUT_REGISTER_AT_##x + +#ifdef PORTA +#define DIRECTION_REGISTER_AT_PortA DDRA +#define OUTPUT_REGISTER_AT_PortA PORTA +#define INPUT_REGISTER_AT_PortA PINA + +#define PORT_AT_PIN_A0 PortA +#define PORT_AT_PIN_A1 PortA +#define PORT_AT_PIN_A2 PortA +#define PORT_AT_PIN_A3 PortA +#define PORT_AT_PIN_A4 PortA +#define PORT_AT_PIN_A5 PortA +#define PORT_AT_PIN_A6 PortA +#define PORT_AT_PIN_A7 PortA + +#define MASK_AT_PIN_A0 _BV(0) +#define MASK_AT_PIN_A1 _BV(1) +#define MASK_AT_PIN_A2 _BV(2) +#define MASK_AT_PIN_A3 _BV(3) +#define MASK_AT_PIN_A4 _BV(4) +#define MASK_AT_PIN_A5 _BV(5) +#define MASK_AT_PIN_A6 _BV(6) +#define MASK_AT_PIN_A7 _BV(7) +#endif + +#ifdef PORTB +#define DIRECTION_REGISTER_AT_PortB DDRB +#define OUTPUT_REGISTER_AT_PortB PORTB +#define INPUT_REGISTER_AT_PortB PINB + +#define PORT_AT_PIN_B0 PortB +#define PORT_AT_PIN_B1 PortB +#define PORT_AT_PIN_B2 PortB +#define PORT_AT_PIN_B3 PortB +#define PORT_AT_PIN_B4 PortB +#define PORT_AT_PIN_B5 PortB +#define PORT_AT_PIN_B6 PortB +#define PORT_AT_PIN_B7 PortB + +#define MASK_AT_PIN_B0 _BV(0) +#define MASK_AT_PIN_B1 _BV(1) +#define MASK_AT_PIN_B2 _BV(2) +#define MASK_AT_PIN_B3 _BV(3) +#define MASK_AT_PIN_B4 _BV(4) +#define MASK_AT_PIN_B5 _BV(5) +#define MASK_AT_PIN_B6 _BV(6) +#define MASK_AT_PIN_B7 _BV(7) +#endif + +#ifdef PORTC +#define DIRECTION_REGISTER_AT_PortC DDRC +#define OUTPUT_REGISTER_AT_PortC PORTC +#define INPUT_REGISTER_AT_PortC PINC + +#define PORT_AT_PIN_C0 PortC +#define PORT_AT_PIN_C1 PortC +#define PORT_AT_PIN_C2 PortC +#define PORT_AT_PIN_C3 PortC +#define PORT_AT_PIN_C4 PortC +#define PORT_AT_PIN_C5 PortC +#define PORT_AT_PIN_C6 PortC +#define PORT_AT_PIN_C7 PortC + +#define MASK_AT_PIN_C0 _BV(0) +#define MASK_AT_PIN_C1 _BV(1) +#define MASK_AT_PIN_C2 _BV(2) +#define MASK_AT_PIN_C3 _BV(3) +#define MASK_AT_PIN_C4 _BV(4) +#define MASK_AT_PIN_C5 _BV(5) +#define MASK_AT_PIN_C6 _BV(6) +#define MASK_AT_PIN_C7 _BV(7) +#endif + +#ifdef PORTD +#define DIRECTION_REGISTER_AT_PortD DDRD +#define OUTPUT_REGISTER_AT_PortD PORTD +#define INPUT_REGISTER_AT_PortD PIND +#define PORT_AT_PIN_D0 PortD +#define PORT_AT_PIN_D1 PortD +#define PORT_AT_PIN_D2 PortD +#define PORT_AT_PIN_D3 PortD +#define PORT_AT_PIN_D4 PortD +#define PORT_AT_PIN_D5 PortD +#define PORT_AT_PIN_D6 PortD +#define PORT_AT_PIN_D7 PortD +#define MASK_AT_PIN_D0 _BV(0) +#define MASK_AT_PIN_D1 _BV(1) +#define MASK_AT_PIN_D2 _BV(2) +#define MASK_AT_PIN_D3 _BV(3) +#define MASK_AT_PIN_D4 _BV(4) +#define MASK_AT_PIN_D5 _BV(5) +#define MASK_AT_PIN_D6 _BV(6) +#define MASK_AT_PIN_D7 _BV(7) +#endif + +#ifdef PORTE +#define DIRECTION_REGISTER_AT_PortE DDRE +#define OUTPUT_REGISTER_AT_PortE PORTE +#define INPUT_REGISTER_AT_PortE PINE + +#define PORT_AT_PIN_E0 PortE +#define PORT_AT_PIN_E1 PortE +#define PORT_AT_PIN_E2 PortE +#define PORT_AT_PIN_E3 PortE +#define PORT_AT_PIN_E4 PortE +#define PORT_AT_PIN_E5 PortE +#define PORT_AT_PIN_E6 PortE +#define PORT_AT_PIN_E7 PortE + +#define MASK_AT_PIN_E0 _BV(0) +#define MASK_AT_PIN_E1 _BV(1) +#define MASK_AT_PIN_E2 _BV(2) +#define MASK_AT_PIN_E3 _BV(3) +#define MASK_AT_PIN_E4 _BV(4) +#define MASK_AT_PIN_E5 _BV(5) +#define MASK_AT_PIN_E6 _BV(6) +#define MASK_AT_PIN_E7 _BV(7) +#endif + +#ifdef PORTF +#define DIRECTION_REGISTER_AT_PortF DDRF +#define OUTPUT_REGISTER_AT_PortF PORTF +#define INPUT_REGISTER_AT_PortF PINF + +#define PORT_AT_PIN_F0 PortF +#define PORT_AT_PIN_F1 PortF +#define PORT_AT_PIN_F2 PortF +#define PORT_AT_PIN_F3 PortF +#define PORT_AT_PIN_F4 PortF +#define PORT_AT_PIN_F5 PortF +#define PORT_AT_PIN_F6 PortF +#define PORT_AT_PIN_F7 PortF + +#define MASK_AT_PIN_F0 _BV(0) +#define MASK_AT_PIN_F1 _BV(1) +#define MASK_AT_PIN_F2 _BV(2) +#define MASK_AT_PIN_F3 _BV(3) +#define MASK_AT_PIN_F4 _BV(4) +#define MASK_AT_PIN_F5 _BV(5) +#define MASK_AT_PIN_F6 _BV(6) +#define MASK_AT_PIN_F7 _BV(7) +#endif + +#define MERGE_TO_FUNC(prefix, id) prefix##_##id +#define EXPAND_WRAPPER(NEXTLEVEL, ...) NEXTLEVEL(__VA_ARGS__) + +#define _SET_OUTPUT(port_id, msk) PORT_TO_DIRECTION_REGISTER(port_id) |= (msk) +#define _SET_INPUT(port_id, msk) PORT_TO_DIRECTION_REGISTER(port_id) &= ~(msk) + +#define _DIGITAL_WRITE_HIGH(port_id, msk) PORT_TO_OUTPUT_REGISTER(port_id) |= (msk) +#define _DIGITAL_WRITE_LOW(port_id, msk) PORT_TO_OUTPUT_REGISTER(port_id) &= ~(msk) + +#define _DIGITAL_READ_RAW(port_id, msk) ((PORT_TO_INPUT_REGISTER(port_id)) & (msk)) +#define _DIGITAL_READ(port_id, msk) (((PORT_TO_INPUT_REGISTER(port_id)) & (msk)) != 0 ? 1 : 0) + +#define _DIGITAL_TOGGLE(port_id, msk) PORT_TO_OUTPUT_REGISTER(port_id) ^= (msk) + +#define SET_1(pin) SET_OUTPUT(pin) +#define SET_0(pin) SET_INPUT(pin) + +#define SET_0x1(pin) SET_OUTPUT(pin) +#define SET_0x0(pin) SET_INPUT(pin) + +#define DIGITAL_WRITE_HIGH(pin) EXPAND_WRAPPER(_DIGITAL_WRITE_HIGH, PIN_TO_PORT(pin), PIN_TO_MASK(pin)) +#define DIGITAL_WRITE_LOW(pin) EXPAND_WRAPPER(_DIGITAL_WRITE_LOW, PIN_TO_PORT(pin), PIN_TO_MASK(pin)) + +#define DIGITAL_WRITE_1(pin) DIGITAL_WRITE_HIGH(pin) +#define DIGITAL_WRITE_0(pin) DIGITAL_WRITE_LOW(pin) + +#define DIGITAL_WRITE_0x1(pin) DIGITAL_WRITE_HIGH(pin) +#define DIGITAL_WRITE_0x0(pin) DIGITAL_WRITE_LOW(pin) + +#define DIGITAL_WRITE_ENABLE(pin) DIGITAL_WRITE_HIGH(pin) +#define DIGITAL_WRITE_DISABLE(pin) DIGITAL_WRITE_LOW(pin) + +#define SET_OUTPUT(pin) EXPAND_WRAPPER(_SET_OUTPUT, PIN_TO_PORT(pin), PIN_TO_MASK(pin)) +#define SET_INPUT(pin) EXPAND_WRAPPER(_SET_INPUT, PIN_TO_PORT(pin), PIN_TO_MASK(pin)) + +#define pin_mode(pin, mode) SET_##mode(pin) +#define pin_pullup(pin, val) DIGITAL_WRITE_##val(pin) + +#endif /* PINS_H */ diff --git a/tpic6b595_shiftout/uart/uart.c b/tpic6b595_shiftout/uart/uart.c new file mode 100644 index 0000000..3faf5e5 --- /dev/null +++ b/tpic6b595_shiftout/uart/uart.c @@ -0,0 +1,90 @@ +/* + * Copyright 2011 Mika Tuupola + * + * Licensed under the MIT license: + * http://www.opensource.org/licenses/mit-license.php + * + */ + +#include +#include + +#ifndef F_CPU +#define F_CPU 16000000UL +#endif + +#ifndef BAUD +#define BAUD 9600 +#endif +#include + +#if defined (UBRR0H) + +#warning UART0 +#define UBRRxH UBRR0H +#define UBRRxL UBRR0L +#define UCSRxA UCSR0A +#define U2Xx U2X0 +#define UCSRxC UCSR0C +#define UCSZx1 UCSZ01 +#define UCSZx0 UCSZ00 +#define UCSRxB UCSR0B +#define RXENx RXEN0 +#define TXENx TXEN0 +#define UDREx UDRE0 +#define RXCx RXC0 +#define UDRx UDR0 +#define UDRIEx UDRIE0 + +#elif defined (UBRR1H) + +#warning UART1 +#define UBRRxH UBRR1H +#define UBRRxL UBRR1L +#define UCSRxA UCSR1A +#define U2Xx U2X1 +#define UCSRxC UCSR1C +#define UCSZx1 UCSZ11 +#define UCSZx0 UCSZ10 +#define UCSRxB UCSR1B +#define RXENx RXEN1 +#define TXENx TXEN1 +#define UDREx UDRE1 +#define RXCx RXC1 +#define UDRx UDR1 +#define UDRIEx UDRIE1 + +#else +#error No UART? +#endif + +/* http://www.cs.mun.ca/~rod/Winter2007/4723/notes/serial/serial.html */ + +void uart_init(void) { + UBRRxH = UBRRH_VALUE; + UBRRxL = UBRRL_VALUE; + +#if USE_2X + UCSRxA |= _BV(U2Xx); +#else + UCSRxA &= ~(_BV(U2Xx)); +#endif + + UCSRxC = _BV(UCSZx1) | _BV(UCSZx0); /* 8-bit data */ + UCSRxB = _BV(RXENx) | _BV(TXENx); /* Enable RX and TX */ +} + +int uart_putchar(char c, FILE *stream) { + if (c == '\n') { + uart_putchar('\r', stream); + } + loop_until_bit_is_set(UCSRxA, UDREx); + UDRx = c; + + return 0; +} + +int uart_getchar(FILE *stream) { + loop_until_bit_is_set(UCSRxA, RXCx); + return UDRx; +} diff --git a/tpic6b595_shiftout/uart/uart.h b/tpic6b595_shiftout/uart/uart.h new file mode 100644 index 0000000..15ed4b2 --- /dev/null +++ b/tpic6b595_shiftout/uart/uart.h @@ -0,0 +1,23 @@ +/* + * Copyright 2011 Mika Tuupola + * + * Licensed under the MIT license: + * http://www.opensource.org/licenses/mit-license.php + * + */ + +#ifndef UART_H +#define UART_H + +int uart_putchar(char c, FILE *stream); +int uart_getchar(FILE *stream); + +void uart_init(void); + +/* http://www.ermicro.com/blog/?p=325 */ + +FILE uart_output = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE); +FILE uart_input = FDEV_SETUP_STREAM(NULL, uart_getchar, _FDEV_SETUP_READ); + +#endif /* UART_H */ + diff --git a/tpic6b595_shiftout/uart/uart_async.c b/tpic6b595_shiftout/uart/uart_async.c new file mode 100644 index 0000000..7de6cfb --- /dev/null +++ b/tpic6b595_shiftout/uart/uart_async.c @@ -0,0 +1,155 @@ +/* + * Copyright 2011 Mika Tuupola + * + * Licensed under the MIT license: + * http://www.opensource.org/licenses/mit-license.php + * + */ + +/* Based on Atmel Application Note AVR 306 */ + +#include +#include +#include + +#ifndef BAUD +#define BAUD 9600 +#endif +#include + +#ifndef UART_RX_BUFFER_SIZE +#define UART_RX_BUFFER_SIZE 64 +#endif + +#ifndef UART_TX_BUFFER_SIZE +#define UART_TX_BUFFER_SIZE 64 +#endif + +#if defined (UBRR0H) + +#warning Using UART0 +#define UBRRxH UBRR0H +#define UBRRxL UBRR0L +#define UCSRxA UCSR0A +#define U2Xx U2X0 +#define UCSRxC UCSR0C +#define UCSZx1 UCSZ01 +#define UCSZx0 UCSZ00 +#define UCSRxB UCSR0B +#define RXENx RXEN0 +#define TXENx TXEN0 +#define UDREx UDRE0 +#define RXCx RXC0 +#define UDRx UDR0 +#define UDRIEx UDRIE0 + +#define USARTx_RX_vect USART_RX_vect +#define USARTx_UDRE_vect USART_UDRE_vect +#elif defined (UBRR1H) + +#warning Using UART1 +#define UBRRxH UBRR1H +#define UBRRxL UBRR1L +#define UCSRxA UCSR1A +#define U2Xx U2X1 +#define UCSRxC UCSR1C +#define UCSZx1 UCSZ11 +#define UCSZx0 UCSZ10 +#define UCSRxB UCSR1B +#define RXENx RXEN1 +#define TXENx TXEN1 +#define UDREx UDRE1 +#define RXCx RXC1 +#define UDRx UDR1 +#define UDRIEx UDRIE1 + +#define USARTx_RX_vect USART1_RX_vect +#define USARTx_UDRE_vect USART1_UDRE_vect + +#else +#error No UART? +#endif + +struct tx_ring { + int buffer[UART_TX_BUFFER_SIZE]; + int start; + int end; +}; + +struct rx_ring { + int buffer[UART_RX_BUFFER_SIZE]; + int start; + int end; +}; + +static struct tx_ring tx_buffer; +static struct rx_ring rx_buffer; + +/* http://www.cs.mun.ca/~rod/Winter2007/4723/notes/serial/serial.html */ + +void uart_init(void) { + + tx_buffer.start = 0; + tx_buffer.end = 0; + + rx_buffer.start = 0; + rx_buffer.end = 0; + + UBRRxH = UBRRH_VALUE; + UBRRxL = UBRRL_VALUE; + + UCSRxC = _BV(UCSZx1) | _BV(UCSZx0); /* 8-bit data */ + UCSRxB = _BV(RXENx) | _BV(TXENx); /* Enable RX and TX */ + + sei(); +} + +int uart_putchar(char c, FILE *stream) { + if (c == '\n') { + uart_putchar('\r', stream); + } + + int write_pointer = (tx_buffer.end + 1) % UART_TX_BUFFER_SIZE; + + if (write_pointer != tx_buffer.start){ + tx_buffer.buffer[tx_buffer.end] = c; + tx_buffer.end = write_pointer; + + /* Data available. Enable the transmit interrupt for serial port 0. */ + UCSRxB |= _BV(UDRIEx); + } + + return 0; +} + +int uart_getchar(FILE *stream) { + int read_pointer = (rx_buffer.start + 1) % UART_RX_BUFFER_SIZE; + + rx_buffer.start = read_pointer; + return rx_buffer.buffer[read_pointer]; +} + +ISR(USARTx_RX_vect) { + int write_pointer = (rx_buffer.end + 1) % UART_RX_BUFFER_SIZE; + + /* Add next byte to ringbuffer if it has space available. */ + if (write_pointer != rx_buffer.start){ + rx_buffer.buffer[rx_buffer.end] = UDRx; + rx_buffer.end = write_pointer; + } +} + +ISR(USARTx_UDRE_vect){ + int read_pointer = (tx_buffer.start + 1) % UART_TX_BUFFER_SIZE; + + /* Transmit next byte if data available in ringbuffer. */ + if (read_pointer != tx_buffer.end) { + UDRx = tx_buffer.buffer[read_pointer]; + tx_buffer.start = read_pointer; + } else { + /* Nothing to send. Disable the transmit interrupt for serial port x. */ + UCSRxB &= ~_BV(UDRIEx); + } +} + +