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