X-Git-Url: https://git.cryptolib.org/?a=blobdiff_plain;f=uart.c;h=e35106cf816ae683822a74712dcee12d654ca973;hb=37d550b5d03ebe6cc51c6e7bbc897f9520ea7422;hp=68aaac48e006d7ee48bbc3248586e1f42ba45453;hpb=79c9a6582ba071646a3062175715f59ebe210603;p=avr-crypto-lib.git
diff --git a/uart.c b/uart.c
index 68aaac4..e35106c 100644
--- 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 .
+*/
/* USART-Init beim ATmegaXX */
#include "config.h"
#include
-//#include
#include
#include
@@ -18,9 +35,42 @@
#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
+
+
+#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<>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<>4)&0xf]);
uart_putc(table[(*((char*)buf))&0xf]);
uart_putc(' ');
- buf=(char*)buf+1;
+ 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<