2 * Loosely modelled after AVR-RS485 by Yoshinori Kohyama (http://algobit.jp/),
3 * available at https://github.com/kohyama/AVR-RS485/
5 * All bugs by Jan "Yenya" Kasprzak <kas@fi.muni.cz> :-)
9 #include <avr/interrupt.h>
10 #include <util/delay.h>
12 #define BUFSIZE 128 // must be a power of two
14 // configure the control pin
15 #define ctl_pin_setup() do { DDRD |= _BV(PD2); } while (0)
16 #define ctl_pin_on() do { PORTD |= _BV(PD2); } while (0)
17 #define ctl_pin_off() do { PORTD &= ~_BV(PD2); } while (0)
19 #define BUFMASK (BUFSIZE-1)
20 #if (BUFSIZE & BUFMASK)
21 #error BUFSIZE must be a power of two
25 typedef uint16_t bufptr_t;
27 typedef uint8_t bufptr_t;
30 #define bufptr_inc(x) ((x + 1) & BUFMASK)
32 static volatile bufptr_t rx_head, rx_tail, tx_head, tx_tail;
33 static volatile char rxbuf[BUFSIZE], txbuf[BUFSIZE];
35 #define UART_BAUD 9600
36 #define UBRR_VAL ((F_CPU + 8UL * UART_BAUD) / (16UL*UART_BAUD) - 1)
37 #define wait_one_byte() _delay_us(10*1000000/UART_BAUD)
41 rx_head = rx_tail = 0;
42 tx_head = tx_tail = 0;
49 UCSR0B = _BV(RXCIE0)|_BV(RXEN0)|_BV(TXEN0);
50 UCSR0C = _BV(UCSZ01)|_BV(UCSZ00);
53 void rs485_send(char *p)
62 next = bufptr_inc(tx_head);
63 while (next != tx_tail && *p != '\0') {
64 txbuf[tx_head] = *p++;
66 next = bufptr_inc(tx_head);
69 UCSR0B |= _BV(UDRIE0);
73 bufptr_t rs485_readln(char *buf, bufptr_t size)
79 while (rx_head != rx_tail && n + 1 < size) {
80 buf[n++] = rxbuf[rx_tail];
81 rx_tail = bufptr_inc(rx_tail);
84 } while (n == 0 || buf[n - 1] != 0x0a);
95 next = bufptr_inc(rx_head);
96 rxbuf[rx_head] = UDR0;
105 if (tx_head == tx_tail) {
106 UCSR0B &= ~_BV(UDRIE0);
110 UDR0 = txbuf[tx_tail];
111 tx_tail = bufptr_inc(tx_tail);