]> git.cryptolib.org Git - avr-crypto-lib.git/blob - uart.c
insereated GPLv3 stub
[avr-crypto-lib.git] / uart.c
1 /* uart.c */
2 /*
3     This file is part of the Crypto-avr-lib/microcrypt-lib.
4     Copyright (C) 2008  Daniel Otte (daniel.otte@rub.de)
5
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.
10
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.
15
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/>.
18 */
19 /* USART-Init beim ATmegaXX */
20
21 #include "config.h"
22
23 #include <avr/io.h>
24 #include <avr/interrupt.h>
25 #include <stdlib.h>
26
27 #include "uart.h"
28
29 #ifdef ATMEGA128
30 #define UCSRB UCSR0B
31 #define UCSRC UCSR0C
32 #define UDR UDR0
33 #define UBRRH UBRR0H
34 #define UBRRL UBRR0L
35 #define URSEL UMSEL
36 #endif
37
38 #ifdef ATMEGA644
39 #define UCSRB UCSR0B
40 #define UCSRC UCSR0C
41 #define UDR UDR0
42 #define UBRRH UBRR0H
43 #define UBRRL UBRR0L
44 #define URSEL UMSEL00
45 #define USART_UDRE_vect USART0_UDRE_vect
46 #define USART_RXC_vect USART0_RX_vect
47 #define UDRIE UDRIE0
48 #define TXEN TXEN0
49 #define UMSEL UMSEL0
50 #define RXEN RXEN0
51 #define RXCIE RXCIE0
52 #define UCSZ0 UCSZ00
53 #define UCSRA UCSR0A
54 #define UDRE UDRE0
55 #define RXC RXC0
56 #endif
57
58
59 #ifdef UART_XON_XOFF
60  #ifdef UART_INTERRUPT
61   void uart_insertc(char c);
62  #else
63   #define uart_insertc uart_putc
64  #endif /* UART_INTERRUPT */
65 #endif
66
67 #define UART_BAUD_CALC(UART_BAUD_RATE,F_OSC) ((F_OSC)/((UART_BAUD_RATE)*16L)-1)
68
69 #ifdef UART_XON_XOFF
70         typedef enum{go=1,nogo=0} gonogo;
71         static gonogo txon=go;
72         static gonogo rxon=go;
73 #endif
74
75 #ifdef UART_INTERRUPT
76 volatile static char rxbuf[UART_RXBUFSIZE];
77 volatile static char txbuf[UART_TXBUFSIZE];
78 volatile static char *volatile rxhead, *volatile rxtail;
79 volatile static char *volatile txhead, *volatile txtail;
80
81 #ifdef UART_HOOK        
82          void (*uart_hook) (uint8_t) = (void*)0;        /* this is a pointer to a function ;-) */
83 #endif
84
85 ISR(USART_UDRE_vect) {
86 #ifdef UART_LEDS        
87         PORTC ^= 0x01;
88 #endif
89         
90         if ( txhead == txtail ) {
91                 UCSRB &= ~(1 << UDRIE);         /* disable data register empty IRQ */
92         } else {
93                 #ifdef UART_XON_XOFF
94                         while(txon==nogo)
95                                 ;
96                 #endif
97                 UDR = *txtail;                  /* schreibt das Zeichen x auf die Schnittstelle */
98                 if (++txtail == (txbuf + UART_TXBUFSIZE)) txtail = txbuf;
99         }
100 }
101
102 ISR(USART_RXC_vect) {
103         int diff; 
104         char c;
105 #ifdef UART_HOOK        
106         static volatile uint8_t hook_running=0;
107 #endif
108 #ifdef UART_LEDS
109         PORTC ^= 0x02;
110 #endif
111         c=UDR;
112         #ifdef UART_XON_XOFF
113          if (c==XON){
114                   txon=go;
115                   return;
116          }
117          if (c==XOFF){
118                  txon=nogo;
119                  return;
120          }
121         #endif
122         /* buffer full? */
123         diff = rxhead - rxtail;
124         if (diff < 0) diff += UART_RXBUFSIZE; /* diff is the amount of bytes in buffer */
125         if (diff < UART_RXBUFSIZE -1) {
126                 // buffer NOT full
127 #ifdef UART_HOOK
128                 if(!hook_running && uart_hook){
129                         uint8_t t=c;    
130                         hook_running = 1;
131                         sei(); /* reenable interrupts, avoid recursion!!! */
132                         do {
133                                 uart_hook(t);
134                         } while(uart_getc_nb((char*)&t));
135                         hook_running = 0;
136                 } else {
137                         *rxhead = c;
138                         ++rxhead;
139                         if (rxhead == (rxbuf + UART_RXBUFSIZE)) rxhead = rxbuf;
140                 }
141 #else   
142                 *rxhead = c;
143                 ++rxhead;
144                 if (rxhead == (rxbuf + UART_RXBUFSIZE))
145                         rxhead = rxbuf;
146 #endif
147         } else {
148                                                 //reads the buffer to clear the interrupt condition
149         }
150 #ifdef UART_XON_XOFF    
151         if((diff > UART_XON_XOFF_THRESHOLD_1) && (rxon==go)){
152                 rxon=nogo;
153                 uart_insertc(XOFF);
154         }
155         if((diff < UART_XON_XOFF_THRESHOLD_2) && (rxon==nogo)){
156                 rxon=go;
157                 uart_insertc(XON);
158         }
159 #endif
160 }
161
162 #endif // UART_INTERRUPT
163
164
165 void uart_init() {
166         PORTD |= 0x01;                          //Pullup an RXD an
167         
168         UCSRB |= (1<<TXEN);                     //UART TX einschalten
169 #ifdef ATMEGA644
170         UCSRA = 0;
171         UCSRC = (3<<UCSZ0);                 //Asynchron 8N1
172 #else   
173     UCSRA = 0;
174         UCSRC |= (1<<URSEL)|(3<<UCSZ0);         //Asynchron 8N1
175 #endif
176         UCSRB |= ( 1 << RXEN );                 //Uart RX einschalten
177
178         UBRRH=(uint8_t)(UART_BAUD_CALC(UART_BAUD_RATE,F_CPU)>>8);
179         UBRRL=(uint8_t)(UART_BAUD_CALC(UART_BAUD_RATE,F_CPU));
180
181 #ifdef UART_INTERRUPT
182         // init buffers
183         rxhead = rxtail = rxbuf;
184         txhead = txtail = txbuf;
185
186         // activate rx IRQ
187         UCSRB |= _BV(RXCIE) | _BV(UDRIE);
188         sei();
189 //      #ifdef ATMEGA644
190 //      UCSRB |= _BV(UDRIE);
191 //      #endif
192 #endif // UART_INTERRUPT
193 }
194
195 #ifdef UART_INTERRUPT
196 #ifdef UART_XON_XOFF
197
198 void uart_insertc(char c){
199         volatile int diff;
200         do {
201                 diff = txhead - txtail;
202                 if ( diff < 0 ) diff += UART_TXBUFSIZE;
203         } while ( diff >= UART_TXBUFSIZE -1 );
204
205         cli();
206         if (--txtail == (txbuf-1)) txtail += UART_TXBUFSIZE;
207         *txtail = c;
208         
209         UCSRB |= (1 << UDRIE);          /* enable data register empty IRQ */
210         sei();
211 }
212 #endif /* UART_XON_XOFF */
213 void uart_putc(char c) {
214         volatile int diff;
215
216         /* buffer full? */
217         do {
218                 diff = txhead - txtail;
219                 if ( diff < 0 ) diff += UART_TXBUFSIZE;
220         } while ( diff >= UART_TXBUFSIZE -1 );
221
222         cli();
223         *txhead = c;
224         if (++txhead == (txbuf + UART_TXBUFSIZE)) txhead = txbuf;
225
226         UCSRB |= (1 << UDRIE);          /* enable data register empty IRQ */
227         sei();
228 }
229 #else  // WITHOUT INTERRUPT
230 void uart_putc(char c) {
231         while (!(UCSRA & (1<<UDRE))) /* warten bis Senden moeglich */
232                 ; 
233         #ifdef UART_XON_XOFF
234         while (txon==nogo)                       /* warte bis XON empfangen */
235                 ;
236         #endif
237         UDR = c;                  /* schreibt das Zeichen x auf die Schnittstelle */
238 }
239 #endif // UART_INTERRUPT
240
241
242 void uart_putstr(char *str) {
243         while(*str) {
244                 uart_putc(*str++);
245         }
246 }
247
248 void uart_putstr_P(PGM_P str) {
249         char tmp;
250         while((tmp = pgm_read_byte(str))) {
251                 uart_putc(tmp);
252                 str++;
253         }
254 }
255
256 void uart_hexdump(const void* buf, int len)
257 {
258         unsigned char table[]={'0','1','2','3','4','5','6','7',
259                                    '8','9','a','b','c','d','e','f'};
260         while(len--){
261                 uart_putc(table[((*((char*)buf))>>4)&0xf]);
262                 uart_putc(table[(*((char*)buf))&0xf]);
263                 uart_putc(' ');
264                 buf=(uint8_t*)buf+1;
265         }
266 }
267
268
269 #ifdef UART_INTERRUPT
270 char uart_getc(void)
271 {
272         char val;
273
274         while(rxhead==rxtail)
275                 ;
276
277         val = *rxtail;
278         ++rxtail;
279         if (rxtail == (rxbuf + UART_RXBUFSIZE))
280                 rxtail = rxbuf;
281
282         return val;
283 }
284 #else  // WITHOUT INTERRUPT
285 char uart_getc(void)
286 {
287         char t;
288         while (!(UCSRA & (1<<RXC)))
289                 ;       // warten bis Zeichen verfuegbar
290         t=UDR;
291         #ifdef UART_XON_XOFF
292         if (t==XON)  txon=go;
293         if (t==XOFF) txon=nogo;
294         #endif
295         return t;                       // Zeichen aus UDR zurueckgeben
296 }
297 #endif // UART_INTERRUPT
298
299 // returns 1 on success
300 #ifdef UART_INTERRUPT
301 char uart_getc_nb(char *c)
302 {
303         if (rxhead==rxtail) return 0;
304
305         *c = *rxtail;
306         if (++rxtail == (rxbuf + UART_RXBUFSIZE)) rxtail = rxbuf;
307
308         return 1;
309 }
310 #else  // WITHOUT INTERRUPT
311 char uart_getc_nb(char *c)
312 {
313         if (UCSRA & (1<<RXC)) {         // Zeichen verfuegbar
314                 *c = UDR;
315                 #ifdef UART_XON_XOFF
316                         if (*c==XON)  txon=go;
317                         if (*c==XOFF) txon=nogo;
318                 #endif
319                 return 1;
320         }
321
322         return 0;
323 }
324 #endif // UART_INTERRUPT