
/*###################################################################################
#   AVR-Voltmeter (OHG-Version 06/2007), Autor:     Dirk Wiebel (dirk@wiebel.de)    #
#                                                                                   #
# Veröffentlicht unter der Beerware-Lizenz (http://de.wikipedia.org/wiki/Beerware)  #
#                                                                                   #
###################################################################################*/
#
#
#include <avr/io.h>
#include <stdint.h>
#include <stdlib.h>
#include <inttypes.h>
#include <avr/sleep.h>
#include <avr/interrupt.h>

#define F_CPU = 20000000	// bei 256-Teiler müssen 78125 Durchgänge für 1 sec erfolgen = 625*125

char version[14] = "Proto 0.04 - ";

void display_all(void);
void display(void);
void display_freq(void);
void display_chan(unsigned char channel);
void uart_init(unsigned int ubrr);
void uart_send(uint8_t);
void uart_send_string(char *datastring);
void delay(unsigned int millisec);
unsigned int uart_receive(void);
unsigned int adc_capture(unsigned char mux,unsigned char ref);

char tempout[10];
unsigned int dirktest,timer;
unsigned long frequency;
unsigned long freqtemp=0;
unsigned char i,newsec,zehntel,hour,min,sec;
unsigned char befehl=0;

//Planung:
unsigned char intervall=0; // intervall0=1sec; intervall1=0.1sec; intervall2=Bedarf; intervall3=Menu
unsigned char status=0;    // status0=Alles; status1=AIN4; status2=AIN3; status3...;


void menu(void)
{
	uart_send(0x0C);
	uart_send(0x0D);
	uart_send_string(version);

	if(hour<10) uart_send_string("0"); 
	utoa(hour,tempout,10); uart_send_string(tempout);uart_send_string(":");
	if(min<10) uart_send_string("0"); 
	utoa(min,tempout,10); uart_send_string(tempout);uart_send_string(":");
	if(sec<10) uart_send_string("0"); 
	utoa(sec,tempout,10); uart_send_string(tempout);

	uart_send_string("\n\n\rHilfe:");
	uart_send_string("\n\n\rn normaler Modus (1 sec)");
	uart_send_string("\n\rs schneller Modus (1/10 sec)");
	uart_send_string("\n\rb Bedarfsmodus\n");

	uart_send_string("\n\r0 Alle Kanaele"); if(status==0) uart_send_string("*");
	uart_send_string("\n\r1 Nur Kanal1");if(status==1) uart_send_string("*");
	uart_send_string("\n\r2 Nur Kanal2");if(status==2) uart_send_string("*");
	uart_send_string("\n\r3 Nur Kanal3");if(status==3) uart_send_string("*");
	uart_send_string("\n\r4 Nur Kanal4");if(status==4) uart_send_string("*");
	uart_send_string("\n\r5 Nur Kanal5");if(status==5) uart_send_string("*");
	uart_send_string("\n\r6 Nur Frequenz");if(status==6) uart_send_string("*");

	uart_send_string("\n\n\r? Diese Hilfeseite\n\r\n\r");
}




int main(void)
{
	OSCCAL=0xD3;
	uart_init(51);
	uart_send(0x0C);
	uart_send(0x0D);

	TCCR0B |= (1<<CS02); 	// Vorteiler: 256
	TCNT0  = 0xFF-125;	// 125 Schritte bis Overflow
	TIMSK0 |= (1<<TOIE0);	// Overflow-Interrupt

	TCCR1B |= (1<<CS02)|(1<<CS01)|(1<<CS00);	// Externe Quelle, steigende Flanke
	TIMSK1 |= (1<<TOIE1);	// Overflow-Interrupt für Timer1 (Frequenzzählung)
	TCNT1  = 0;


	sei();
	
	   
      
	for (;;)                            /* loop forever */
	{


	if(sec==60){ min++; sec=0;}
	if(min==60){ hour++; min=0;}
	

	if(befehl ==48){  	// wenn "0" gesendet
		status=0;

	}else if(befehl ==49){  	// wenn "1" gesendet
		status=1;

	}else if(befehl ==50){  	// wenn "2" gesendet
		status=2;

	}else if(befehl ==51){  	// wenn "3" gesendet
		status=3;

	}else if(befehl ==52){  	// wenn "4" gesendet
		status=4;

	}else if(befehl ==53){  	// wenn "5" gesendet
		status=5;

	}else if(befehl ==54){  	// wenn "6" gesendet
		status=6;

	}else if(befehl==110){	// wenn "n" gesendet

		intervall=0;

	}else if(befehl==115){	// wenn "s" gesendet

		intervall=1;

	}else if(befehl==98){	// wenn "b" gesendet

		intervall=2;
		
	}else if(befehl==63){	// wenn "?" gesendet

		intervall=3;	

	}else{
		uart_send_string("");
	}
	


	if(newsec==1 && intervall==0){
		newsec=0;
		display(); 
	}

	if(zehntel==1 && intervall==1){
		zehntel=0;
		display(); 
	}

	if(zehntel==1 && intervall==2){
		if(befehl>47 && befehl<55) display();
		befehl=0;
		zehntel=0;
	}

	if(newsec ==1 && intervall==3){
		newsec=0;
		menu();
	}


	}

	return 0;
}


void display_all(void)
{

		uart_send_string("A ;");

		for(i=5; i>0 ;i--){
		dirktest=(adc_capture(i-1,5));
		utoa(dirktest,tempout,10);
		if(dirktest<1000) uart_send_string("0");
		if(dirktest<100) uart_send_string("0");
		if(dirktest<10) uart_send_string("0");
           	uart_send_string(tempout);
		uart_send_string(";");
		}
		ultoa(frequency,tempout,10);
		if(frequency<10000) uart_send_string("0");
		if(frequency<1000) uart_send_string("0");
		if(frequency<100) uart_send_string("0");
		if(frequency<10) uart_send_string("0");
           	uart_send_string(tempout);
		

		uart_send_string("\n");
		uart_send(0x0D);
}


void display_freq(void)
{
		uart_send_string("F ;");
		ultoa(frequency,tempout,10);
		if(frequency<10000) uart_send_string("0");
		if(frequency<1000) uart_send_string("0");
		if(frequency<100) uart_send_string("0");
		if(frequency<10) uart_send_string("0");
           	uart_send_string(tempout);
		
		uart_send_string("\n");
		uart_send(0x0D);
}

void display_chan(unsigned char channel)
{
		uart_send(channel+48);
		uart_send_string(" ;");
		dirktest=(adc_capture(5-channel,5));
		utoa(dirktest,tempout,10);
		if(dirktest<1000) uart_send_string("0");
		if(dirktest<100) uart_send_string("0");
		if(dirktest<10) uart_send_string("0");
           	uart_send_string(tempout);
		uart_send_string(";");
		
		uart_send_string("\n");
		uart_send(0x0D);
}




void display(void)
{
	if(status==0)display_all();
	if(status==1)display_chan(1);
	if(status==2)display_chan(2);
	if(status==3)display_chan(3);
	if(status==4)display_chan(4);
	if(status==5)display_chan(5);
	if(status==6)display_freq();


}




void delay(unsigned int millisec)
{
	uint8_t i;
    
	while (millisec--)
 		for (i=0; i<250; i++) asm volatile ("nop"::);
                for (i=0; i<250; i++) asm volatile ("nop"::);
                for (i=0; i<250; i++) asm volatile ("nop"::);
}



void uart_init(unsigned int ubrr)
{
  UBRR0H= 0;
  UBRR0L= 10; //20Mhz, 115.200

  UCSR0B = (1<<TXEN0)|(1<<RXEN0)|(1<<RXCIE0);
  UCSR0C = (1<<UCSZ01)|(1<<UCSZ00); // 8data, 1stopbit
}

unsigned int uart_receive(void)
{
    while (!(UCSR0A & (1<<RXC0)));  // warten bis Zeichen verfuegbar
    return UDR0;                   // Zeichen aus UDR an Aufrufer zurueckgeben
}

void uart_send(unsigned char data)
{
  loop_until_bit_is_set(UCSR0A, UDRE0);
  UDR0 = data;
}


void uart_send_string(char *datastring)
{
        for (;*datastring !='\0';datastring++){
	  loop_until_bit_is_set(UCSR0A, UDRE0);
	  UDR0=*datastring;
	}
}

unsigned int adc_capture(unsigned char mux,unsigned char ref)
{
  unsigned int i;
  unsigned long result = 0;
  ADCSRA = (1<<ADEN) | (1<<ADPS2) |(1<<ADPS1) | (1<<ADPS0);    // Frequenzvorteiler 
								// setzen auf 128 (1) und ADC aktivieren (1)
 
  	ADMUX = mux;						// Kanal waehlen
  
	if(ref==1){ ADMUX |= (1<<REFS1); ADMUX |= (1<<REFS0); } // 1,1V als Referenzspannung nutzen
	if(ref==5){ ADMUX &= ~(1<<REFS1); ADMUX |= (1<<REFS0);} // VCC(5V) als Ref nutzen 

 
  /* 1x Dummy-Read */
  ADCSRA |= (1<<ADSC);	
  while ( ADCSRA & (1<<ADSC) ) {
     ;
  }
 
  /* Eigentliche Messung - Mittelwert aus 4 aufeinanderfolgenden Wandlungen */
  for(i=0;i<4;i++)
  {
    ADCSRA |= (1<<ADSC);	// eine Wandlung "single conversion"
    while ( ADCSRA & (1<<ADSC) ) {
      ;						// auf Abschluss der Konvertierung warten
    }
    result += ADCW;			// Wandlungsergebnisse aufaddieren
  }
  //ADCSRA &= ~(1<<ADEN);	// ADC deaktivieren (2)

  // result /= 4;  //Resultat: 0-4096 bei 0-5000mV
  result = 5000*result/4096;

  return result;
}

SIGNAL(SIG_OVERFLOW1)
{
  freqtemp++;
}

SIGNAL(SIG_OVERFLOW0)
{

TCNT0  = 0xFF-124;	// 125 Schritte bis Overflow
timer++;

if(timer==62 || timer==125 || timer==187 || timer==250  || timer==312 || timer==375 || timer==437 || timer==500  || 

timer==562 || timer==625) zehntel=1;
if(timer==625){timer=0; sec++; newsec=1; frequency=TCNT1; frequency+=(freqtemp*256*256); TCNT1=0; freqtemp=0;}
}

SIGNAL(SIG_USART_RECV)
{
  befehl=UDR0;
}

