]> git.cryptolib.org Git - avr-crypto-lib.git/blobdiff - uart.c
insereated GPLv3 stub
[avr-crypto-lib.git] / uart.c
diff --git a/uart.c b/uart.c
index c0365e7114a29cf8455e3cd27615fbcca4799037..e35106cf816ae683822a74712dcee12d654ca973 100644 (file)
--- a/uart.c
+++ b/uart.c
@@ -1,9 +1,26 @@
+/* uart.c */
+/*
+    This file is part of the Crypto-avr-lib/microcrypt-lib.
+    Copyright (C) 2008  Daniel Otte (daniel.otte@rub.de)
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
 /* USART-Init beim ATmegaXX */
 
 #include "config.h"
 
 #include <avr/io.h>
-//#include <avr/signal.h>
 #include <avr/interrupt.h>
 #include <stdlib.h>
 
 #define URSEL UMSEL
 #endif
 
+#ifdef ATMEGA644
+#define UCSRB UCSR0B
+#define UCSRC UCSR0C
+#define UDR UDR0
+#define UBRRH UBRR0H
+#define UBRRL UBRR0L
+#define URSEL UMSEL00
+#define USART_UDRE_vect USART0_UDRE_vect
+#define USART_RXC_vect USART0_RX_vect
+#define UDRIE UDRIE0
+#define TXEN TXEN0
+#define UMSEL UMSEL0
+#define RXEN RXEN0
+#define RXCIE RXCIE0
+#define UCSZ0 UCSZ00
+#define UCSRA UCSR0A
+#define UDRE UDRE0
+#define RXC RXC0
+#endif
+
 
-#define UART_BAUD_CALC(UART_BAUD_RATE,F_OSC) ((F_CPU)/((UART_BAUD_RATE)*16L)-1)
+#ifdef UART_XON_XOFF
+ #ifdef UART_INTERRUPT
+  void uart_insertc(char c);
+ #else
+  #define uart_insertc uart_putc
+ #endif /* UART_INTERRUPT */
+#endif
 
+#define UART_BAUD_CALC(UART_BAUD_RATE,F_OSC) ((F_OSC)/((UART_BAUD_RATE)*16L)-1)
+
+#ifdef UART_XON_XOFF
+       typedef enum{go=1,nogo=0} gonogo;
+       static gonogo txon=go;
+       static gonogo rxon=go;
+#endif
 
 #ifdef UART_INTERRUPT
 volatile static char rxbuf[UART_RXBUFSIZE];
@@ -28,8 +78,11 @@ volatile static char txbuf[UART_TXBUFSIZE];
 volatile static char *volatile rxhead, *volatile rxtail;
 volatile static char *volatile txhead, *volatile txtail;
 
+#ifdef UART_HOOK       
+        void (*uart_hook) (uint8_t) = (void*)0;        /* this is a pointer to a function ;-) */
+#endif
 
-SIGNAL(SIG_UART_DATA) {
+ISR(USART_UDRE_vect) {
 #ifdef UART_LEDS       
        PORTC ^= 0x01;
 #endif
@@ -37,39 +90,89 @@ SIGNAL(SIG_UART_DATA) {
        if ( txhead == txtail ) {
                UCSRB &= ~(1 << UDRIE);         /* disable data register empty IRQ */
        } else {
+               #ifdef UART_XON_XOFF
+                       while(txon==nogo)
+                               ;
+               #endif
                UDR = *txtail;                  /* schreibt das Zeichen x auf die Schnittstelle */
                if (++txtail == (txbuf + UART_TXBUFSIZE)) txtail = txbuf;
        }
 }
 
-SIGNAL(SIG_UART_RECV) {
+ISR(USART_RXC_vect) {
        int diff; 
-
+       char c;
+#ifdef UART_HOOK       
+       static volatile uint8_t hook_running=0;
+#endif
 #ifdef UART_LEDS
        PORTC ^= 0x02;
 #endif
-       
+       c=UDR;
+       #ifdef UART_XON_XOFF
+        if (c==XON){
+                 txon=go;
+                 return;
+        }
+        if (c==XOFF){
+                txon=nogo;
+                return;
+        }
+       #endif
        /* buffer full? */
        diff = rxhead - rxtail;
-       if ( diff < 0 ) diff += UART_RXBUFSIZE;
+       if (diff < 0) diff += UART_RXBUFSIZE; /* diff is the amount of bytes in buffer */
        if (diff < UART_RXBUFSIZE -1) {
                // buffer NOT full
-               *rxhead = UDR;
-               if (++rxhead == (rxbuf + UART_RXBUFSIZE)) rxhead = rxbuf;
+#ifdef UART_HOOK
+               if(!hook_running && uart_hook){
+                       uint8_t t=c;    
+                       hook_running = 1;
+                       sei(); /* reenable interrupts, avoid recursion!!! */
+                       do {
+                               uart_hook(t);
+                       } while(uart_getc_nb((char*)&t));
+                       hook_running = 0;
+               } else {
+                       *rxhead = c;
+                       ++rxhead;
+                       if (rxhead == (rxbuf + UART_RXBUFSIZE)) rxhead = rxbuf;
+               }
+#else  
+               *rxhead = c;
+               ++rxhead;
+               if (rxhead == (rxbuf + UART_RXBUFSIZE))
+                       rxhead = rxbuf;
+#endif
        } else {
-               UDR;                            //reads the buffer to clear the interrupt condition
+                                               //reads the buffer to clear the interrupt condition
        }
+#ifdef UART_XON_XOFF   
+       if((diff > UART_XON_XOFF_THRESHOLD_1) && (rxon==go)){
+               rxon=nogo;
+               uart_insertc(XOFF);
+       }
+       if((diff < UART_XON_XOFF_THRESHOLD_2) && (rxon==nogo)){
+               rxon=go;
+               uart_insertc(XON);
+       }
+#endif
 }
 
 #endif // UART_INTERRUPT
 
 
-void uart_init(void) {
+void uart_init() {
        PORTD |= 0x01;                          //Pullup an RXD an
-
+       
        UCSRB |= (1<<TXEN);                     //UART TX einschalten
+#ifdef ATMEGA644
+       UCSRA = 0;
+       UCSRC = (3<<UCSZ0);                 //Asynchron 8N1
+#else  
+    UCSRA = 0;
        UCSRC |= (1<<URSEL)|(3<<UCSZ0);         //Asynchron 8N1
-
+#endif
        UCSRB |= ( 1 << RXEN );                 //Uart RX einschalten
 
        UBRRH=(uint8_t)(UART_BAUD_CALC(UART_BAUD_RATE,F_CPU)>>8);
@@ -81,11 +184,32 @@ void uart_init(void) {
        txhead = txtail = txbuf;
 
        // activate rx IRQ
-       UCSRB |= (1 << RXCIE);
+       UCSRB |= _BV(RXCIE) | _BV(UDRIE);
+       sei();
+//     #ifdef ATMEGA644
+//     UCSRB |= _BV(UDRIE);
+//     #endif
 #endif // UART_INTERRUPT
 }
 
 #ifdef UART_INTERRUPT
+#ifdef UART_XON_XOFF
+
+void uart_insertc(char c){
+       volatile int diff;
+       do {
+               diff = txhead - txtail;
+               if ( diff < 0 ) diff += UART_TXBUFSIZE;
+       } while ( diff >= UART_TXBUFSIZE -1 );
+
+       cli();
+       if (--txtail == (txbuf-1)) txtail += UART_TXBUFSIZE;
+       *txtail = c;
+       
+       UCSRB |= (1 << UDRIE);          /* enable data register empty IRQ */
+       sei();
+}
+#endif /* UART_XON_XOFF */
 void uart_putc(char c) {
        volatile int diff;
 
@@ -104,8 +228,13 @@ void uart_putc(char c) {
 }
 #else  // WITHOUT INTERRUPT
 void uart_putc(char c) {
-       while (!(UCSRA & (1<<UDRE))); /* warten bis Senden moeglich                   */
-       UDR = c;                      /* schreibt das Zeichen x auf die Schnittstelle */
+       while (!(UCSRA & (1<<UDRE))) /* warten bis Senden moeglich */
+               ; 
+       #ifdef UART_XON_XOFF
+       while (txon==nogo)                       /* warte bis XON empfangen */
+               ;
+       #endif
+       UDR = c;                  /* schreibt das Zeichen x auf die Schnittstelle */
 }
 #endif // UART_INTERRUPT
 
@@ -124,15 +253,15 @@ void uart_putstr_P(PGM_P str) {
        }
 }
 
-void uart_hexdump(void* buf, int len)
+void uart_hexdump(const void* buf, int len)
 {
-       unsigned char table[]={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
-       
+       unsigned char table[]={'0','1','2','3','4','5','6','7',
+                                  '8','9','a','b','c','d','e','f'};
        while(len--){
                uart_putc(table[((*((char*)buf))>>4)&0xf]);
                uart_putc(table[(*((char*)buf))&0xf]);
                uart_putc(' ');
-               ++buf;
+               buf=(uint8_t*)buf+1;
        }
 }
 
@@ -142,18 +271,28 @@ char uart_getc(void)
 {
        char val;
 
-       while(rxhead==rxtail) ;
+       while(rxhead==rxtail)
+               ;
 
        val = *rxtail;
-       if (++rxtail == (rxbuf + UART_RXBUFSIZE)) rxtail = rxbuf;
+       ++rxtail;
+       if (rxtail == (rxbuf + UART_RXBUFSIZE))
+               rxtail = rxbuf;
 
        return val;
 }
 #else  // WITHOUT INTERRUPT
 char uart_getc(void)
 {
-       while (!(UCSRA & (1<<RXC)));    // warten bis Zeichen verfuegbar
-       return UDR;                     // Zeichen aus UDR zurueckgeben
+       char t;
+       while (!(UCSRA & (1<<RXC)))
+               ;       // warten bis Zeichen verfuegbar
+       t=UDR;
+       #ifdef UART_XON_XOFF
+       if (t==XON)  txon=go;
+       if (t==XOFF) txon=nogo;
+       #endif
+       return t;                       // Zeichen aus UDR zurueckgeben
 }
 #endif // UART_INTERRUPT
 
@@ -173,6 +312,10 @@ char uart_getc_nb(char *c)
 {
        if (UCSRA & (1<<RXC)) {         // Zeichen verfuegbar
                *c = UDR;
+               #ifdef UART_XON_XOFF
+                       if (*c==XON)  txon=go;
+                       if (*c==XOFF) txon=nogo;
+               #endif
                return 1;
        }