3 This file is part of the AVR-uart_i.
4 Copyright (C) 2006-2015 Daniel Otte (bg@nerilex.org)
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 * \email bg@nerilex.org
24 * \license GPLv3 or later
26 * \brief implementation of interrupt based uart
30 #include <avr/interrupt.h>
34 #define XON_VALUE 0x11
35 #define XOFF_VALUE 0x13
40 # warning "UART0: using default paraty: 'none'"
41 # define UART0_PARATY UART_PARATY_NONE
44 #ifndef UART0_STOPBITS
45 # warning "UART0: using default ammount of stop bits: '1'"
46 # define UART0_STOPBITS UART_STOPBITS_1
49 #ifndef UART0_DATABITS
50 # warning "UART0: using default ammount of data bits: '8'"
51 # define UART0_DATABITS UART_DATABITS_8
54 #if UART0_DATABITS == UART_DATABITS_9
55 # error "UART0: data bits==9 not supported"
62 # error "can not decide which registernames to use, UDR and UDR0 are defined"
81 uart0_ctx_t uart0_ctx;
82 uint8_t uart0_rxbuffer[UART0_RXBUFFER_SIZE];
83 uint8_t uart0_txbuffer[UART0_TXBUFFER_SIZE];
85 void uart0_init(void){
86 circularbytebuffer_init2(UART0_RXBUFFER_SIZE, &(uart0_ctx.rxb), uart0_rxbuffer);
87 circularbytebuffer_init2(UART0_TXBUFFER_SIZE, &(uart0_ctx.txb), uart0_txbuffer);
89 uart0_ctx.hook = NULL;
90 uart0_ctx.hook_running = 0;
96 #define BAUD UART0_BAUD_RATE
97 #include <util/setbaud.h>
103 UCSR0A &= ~_BV(U2X0);
105 UCSR0C = (UART0_PARATY<<4)|(UART0_STOPBITS<<3)|((UART0_DATABITS&3)<<1);
106 UCSR0B = _BV(RXCIE0) | _BV(UDRIE0) | _BV(RXEN0) | _BV(TXEN0) ; /* enable TX and RX and interrupts */
110 ISR(USART0_UDRE_vect){
112 x = circularbytebuffer_get_fifo(&(uart0_ctx.txb));
114 /* the transmit buffer is empty, disable interrupt */
115 UCSR0B &= (uint8_t)~_BV(UDRIE0);
119 while(!uart0_ctx.txon)
125 void uart0_putc (uint16_t c){
127 while(!uart0_ctx.txon)
130 while(circularbytebuffer_cnt(&(uart0_ctx.txb))==UART0_TXBUFFER_SIZE)
133 circularbytebuffer_append((uint8_t)c, &(uart0_ctx.txb));
135 UCSR0B |= (uint8_t)_BV(UDRIE0);
152 if((!uart0_ctx.hook_running) && uart0_ctx.hook){
153 uart0_ctx.hook_running=1;
157 }while((c=circularbytebuffer_get_fifo(&(uart0_ctx.rxb)))!=0xffff);
158 uart0_ctx.hook_running=0;
162 if(circularbytebuffer_cnt(&(uart0_ctx.rxb))==UART0_RXBUFFER_SIZE)
164 circularbytebuffer_append(c, &(uart0_ctx.rxb));
166 if(circularbytebuffer_cnt(&(uart0_ctx.rxb))>UART0_THRESH_HIGH && uart0_ctx.rxon){
168 circularbytebuffer_push(XOFF_VALUE, &(uart0_ctx.txb));
169 UCSR0B |= (uint8_t)_BV(UDRIE0);
171 if(circularbytebuffer_cnt(&(uart0_ctx.rxb))<UART0_THRESH_LOW && !uart0_ctx.rxon){
173 circularbytebuffer_push(XON_VALUE, &(uart0_ctx.txb));
174 UCSR0B |= (uint8_t)_BV(UDRIE0);
179 uint16_t uart0_getc(void){
181 while(circularbytebuffer_cnt(&(uart0_ctx.rxb))==0)
184 ret = circularbytebuffer_get_fifo(&(uart0_ctx.rxb));
189 uint8_t uart0_dataavail(void){
190 return circularbytebuffer_cnt(&(uart0_ctx.rxb));
194 void uart0_sethook(void(*fpt)(uint8_t)){
195 uart0_ctx.hook = fpt;