/*
Titel:   ADC
Autor:   Andreas Mund
Datum:   2001/11/12
Zweck:   Verwendung des AT90S2333 als 6*ADC

Benoetigte Software:
         AVR-GCC zum Kompilieren

Benötigte Hardware:
         6*ADC Board, oder AT90S2333 in einer anderen Schaltung mit 6 frei
         zugaenglichen ADC-Eingaengen
Note:    Bei Fragen oder Anregungen: avr_[_at_]_endi-online.de
         eventuell finden Sie weitere Informationen zum 6*ADC auf
         http:\\www.endi-online.de
         dort findet man auch einen Vorschlag für ein passendes
         Platinenlayout, und weitere Tipps
*/
/*
     Copyright (C) 2001 Andreas Mund, endi-online.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 2
     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, write to the Free Software
     Foundation, Inc., 59 Temple Place - Suite 330, Boston,
     MA  02111-1307, USA.
*/

#include <io.h>
#include <stdlib.h>
#include <interrupt.h>
#include <signal.h>
#include <string.h>


#define F_CPU          4000000
#define UART_BAUD_RATE   9600
#define UART_BAUD_SELECT (F_CPU/(UART_BAUD_RATE*16l)-1)


typedef unsigned char  u08;
typedef          char  s08;
typedef unsigned short u16;
typedef          short s16;

char*pdata;
chardata[8];

u08uart_counter;
u08 adc_act;// ADC ist aktiv
s08 adc_mux;// Nummer des aktuellen Messwertes


// wird nach dem Senden eines Zeichens aufgerufen
SIGNAL(SIG_UART_TRANS)
{

  pdata++;
  uart_counter--;

  if (uart_counter>0)
  {
   outp(*pdata, UDR);
  }
  else
  {
   adc_act = 0;
  }
}


// wird nach der Analog-Wandlung aufgerufen
SIGNAL(SIG_ADC)
{
  memset(data,0,sizeof(data));
  itoa(__inw(ADC),data,10);
  if(adc_mux == 5)
   strcat(data, ";\n\r");
  else
   strcat(data, ";");

  uart_counter = strlen(data);
  pdata = data;

  outp(*pdata, UDR);
}


int main(void)
{

  // aktiviere RxD/TxD und Interrupts
  outp((1<<RXCIE)|(1<<TXCIE)|(1<<TXEN),UCR);
  // Baudrate setzen
  outp((u08)UART_BAUD_SELECT, UBRR);
  // ADC auf Wandlung vorbereiten
  outp((1<<ADEN)|(0<<ADSC)|(1<<ADIE)|(1<<ADPS0)|(1<<ADPS1)|(1<<ADPS2),ADCSR);
  // Sleep-Modus freigeben, um "noise Canceler" zu nutzen
  outp((1<<SE) | (0<<SM),MCUCR);

  // Interrupts freigeben
  sei();

  uart_counter = 0;
  adc_act = 0;
  adc_mux = -1;
  while(1)
  {
   if(!adc_act)
   {
     adc_act = 1;
     // Kanal waehlen
     if((++adc_mux) == 6)
       adc_mux = 0;
     outp(adc_mux, ADMUX);

     asm("sleep");
     // naechsten Eingang lesen
   } // if
  }
}