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