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