/* 
Kleines Barometer mit dem Tiny26

Neue Version mit zusätzlichem LT1286

D. Sperling 2005
*/

#include "lcd.h"
#include <stdlib.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>

#define SETBIT(p, b) (p) |=BIT(b)
#define CLRBIT(p, b) (p) &= ~BIT(b)
#define TOGGLE(p, b) (p) ^=BIT(b)
#define BIT(x) (1<<(x))

#define AREF 5065							//Referenzspannung in mV
#define OFFSET 115 							//Offset MP4115 in mBar*10
#define MPX 4954 							//VSS Drucksensor in mV

unsigned long druck, summe;
unsigned int zaehler, trend, wert, alt;
char output[5];

uint32_t volt(void); 						//Prototype

SIGNAL(SIG_OVERFLOW0)     					//Handler für Timer Interrupt
{
zaehler++;
}

//Delay Funktion
int delay_count=250; 						//Prozessortakt in Hz geteilt durch 4000

void delay(uint8_t ms)
{
	uint16_t cnt;
	asm volatile (
		"\n"
		"L_dl1%=:" "\n\t"
		"mov %A0, %A2" "\n\t"
		"mov %B0, %B2" "\n"
		"L_dl2%=:" "\n\t"
		"sbiw %A0, 1" "\n\t"
		"brne L_dl2%=" "\n\t"
		"dec %1" "\n\t"
		"brne L_dl1%=" "\n\t"
		: "=&w" (cnt)
		: "r" (ms), "r" (delay_count)
		);
}
	
// Ende Delay Funktion

//ADC Ansteuerung
int adc(void)
{
	int abfrage=0;
	
	CLRBIT(PORTA,0);						//CS auf 0
	asm volatile ("nop");
	asm volatile ("nop");
	
	for(int i=0;i<14;i++)
	{
		
		SETBIT(PORTB,2);					//CLK auf 1
		asm volatile ("nop");
		asm volatile ("nop");
		asm volatile ("nop");
		asm volatile ("nop");
		asm volatile ("nop");
		asm volatile ("nop");
		asm volatile ("nop");
		asm volatile ("nop");
		asm volatile ("nop");
		CLRBIT(PORTB,2);					//CLK auf 0
		abfrage=(abfrage<<1);
		asm volatile ("nop");
		asm volatile ("nop");
		asm volatile ("nop");
		if (bit_is_set(PINB,0)) abfrage|=1;	//DATA abfragen
	}
	SETBIT(PORTA,0);						//CS auf 1
	
	return(abfrage);
}
//Ende ADC


int main (void)
{
	TCCR0= (1<<CS02) | !(1<<CS01) | (1<<CS00);	//Timer aktivieren
	
	MCUCR = (1<<SE) | !(1<<SM1) | !(1<<SM0);		//Idle Mode bei sleep
	
	ACSR = (1<<ACD);								//Analog Comparator Disable	
	
	DDRA=0x13; 							//Pin 0, 1 und 4 als Output
	DDRB=0x04;							//Pin 2 als Output
	sei();								//Global Interupt Enable
	TIMSK= (1<<TOIE0);					//Timer0 Interupt Enable
	
	trend=2000;
	
	lcd_init (LCD_DISP_ON);
	lcd_clrscr ();

	while(zaehler<10)
	{
		lcd_gotoxy(0,0);
		lcd_puts("BaroV3.3");
	}
	lcd_gotoxy(0,0);
	lcd_puts("     hPa");
	zaehler=0;
	
	for(;;)
	{
		if (zaehler==8)										//pro Zählschritt etwa 0,25s
		{
			summe=0;
			SETBIT(PORTA,1);									//Drucksensor an
			delay(150);											//WarmUp
			for(int i=0;i<10;i++) 
			{
				(unsigned long) druck=adc()-8192;								//Korrektur des Wandler-Ergebnis
				(unsigned long) summe=summe+druck;
			}
			CLRBIT(PORTA,1);														//Druckensor aus
			(unsigned long) druck=summe/10;
			(unsigned long) druck=(((druck*10000)/4095)*AREF)/10000;				//Vout in mV
			(unsigned long) druck=(((druck*100000/MPX)+9500)/9)+OFFSET;			//Druck in mBar*10
			(unsigned int) wert=druck;
			
			utoa(wert,output,10);
			
			lcd_gotoxy(0,0);
			if (wert<10000) 
			{
				lcd_putc(' ');
				lcd_gotoxy(1,0);
			}
			lcd_puts(output);
			zaehler=0;
			
			trend++;
			
			lcd_gotoxy(4,0);
			if (trend>800)				//Gibt an wie weit die Messwerte für den Trend auseinander liegen
			{
				if (trend>1000) alt=wert;
				trend=(alt+wert);
				alt=trend/2;
				trend=0;
			}
			
			if (alt>wert+5) lcd_putc('-');
			else if (alt<wert-5) lcd_putc('+');
			else lcd_putc('*');
		}
		
		if (bit_is_clear(PINA,2)) 
		{
			SETBIT(PORTA,4);
			delay(255);
			delay(255);
			delay(255);
			delay(255);
			delay(255);
			CLRBIT(PORTA,4);
		}
		
		asm volatile ("sleep");
	}
}


