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