]> git.cryptolib.org Git - avr-crypto-lib.git/blob - test_src/uart.c
extended HFAL
[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
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         unsigned char table[]={'0','1','2','3','4','5','6','7',
283                                    '8','9','a','b','c','d','e','f'};
284         while(len--){
285                 uart_putc(table[((*((char*)buf))>>4)&0xf]);
286                 uart_putc(table[(*((char*)buf))&0xf]);
287                 uart_putc(' ');
288                 buf=(uint8_t*)buf+1;
289         }
290 }
291
292
293 #ifdef UART_INTERRUPT
294 char uart_getc(void)
295 {
296         char val;
297
298         while(rxhead==rxtail)
299                 ;
300
301         val = *rxtail;
302         ++rxtail;
303         if (rxtail == (rxbuf + UART_RXBUFSIZE))
304                 rxtail = rxbuf;
305
306         return val;
307 }
308 #else  // WITHOUT INTERRUPT
309 char uart_getc(void)
310 {
311         char t;
312         while (!(UCSRA & (1<<RXC)))
313                 ;       // warten bis Zeichen verfuegbar
314         t=UDR;
315         #ifdef UART_XON_XOFF
316         if (t==XON)  txon=go;
317         if (t==XOFF) txon=nogo;
318         #endif
319         return t;                       // Zeichen aus UDR zurueckgeben
320 }
321 #endif // UART_INTERRUPT
322
323 // returns 1 on success
324 #ifdef UART_INTERRUPT
325 char uart_getc_nb(char *c)
326 {
327         if (rxhead==rxtail) return 0;
328
329         *c = *rxtail;
330         if (++rxtail == (rxbuf + UART_RXBUFSIZE)) rxtail = rxbuf;
331
332         return 1;
333 }
334 #else  // WITHOUT INTERRUPT
335 char uart_getc_nb(char *c)
336 {
337         if (UCSRA & (1<<RXC)) {         // Zeichen verfuegbar
338                 *c = UDR;
339                 #ifdef UART_XON_XOFF
340                         if (*c==XON)  txon=go;
341                         if (*c==XOFF) txon=nogo;
342                 #endif
343                 return 1;
344         }
345
346         return 0;
347 }
348 #endif // UART_INTERRUPT