/*! \file a2d.c \brief Analog-to-Digital converter function library. */
//*****************************************************************************
//
// File Name	: 'a2d.c'
// Title		: Analog-to-digital converter functions
// Author		: Pascal Stang - Copyright (C) 2002
// Created		: 2002-04-08
// Revised		: 2002-09-30
// Version		: 1.1
// Target MCU	: Atmel AVR series
// Editor Tabs	: 4
//
// This code is distributed under the GNU Public License
//		which can be found at http://www.gnu.org/licenses/gpl.txt
//
//*****************************************************************************

#include <avr/io.h>
#include <avr/interrupt.h>

#include "conf/global.h"
#include "a2d.h"

// global variables

//! Software flag used to indicate when
/// the a2d conversion is complete.
volatile unsigned char a2dCompleteFlag;

// functions

// initialize a2d converter
void a2dInit(void)
{
	sbi(ADCSR, ADEN);				// enable ADC (turn on ADC power)
	cbi(ADCSR, ADFR);				// default to single sample convert mode
	a2dSetPrescaler(ADC_PRESCALE);	// set default prescaler
	a2dSetReference(ADC_REFERENCE);	// set default reference
	cbi(ADMUX, ADLAR);				// set to right-adjusted result

	sbi(ADCSR, ADIE);				// enable ADC interrupts

	a2dCompleteFlag = FALSE;		// clear conversion complete flag
	sei();							// turn on interrupts (if not already on)
}

// turn off a2d converter
void a2dOff(void)
{
	cbi(ADCSR, ADIE);				// disable ADC interrupts
	cbi(ADCSR, ADEN);				// disable ADC (turn off ADC power)
}

// configure A2D converter clock division (prescaling)
void a2dSetPrescaler(unsigned char prescale)
{
	outb(ADCSR, ((inb(ADCSR) & ~ADC_PRESCALE_MASK) | prescale));
}

// configure A2D converter voltage reference
void a2dSetReference(unsigned char ref)
{
	outb(ADMUX, ((inb(ADMUX) & ~ADC_REFERENCE_MASK) | (ref<<6)));
}

// sets the a2d input channel
void a2dSetChannel(unsigned char ch)
{
	outb(ADMUX, (inb(ADMUX) & ~ADC_MUX_MASK) | (ch & ADC_MUX_MASK));	// set channel
}

// start a conversion on the current a2d input channel
void a2dStartConvert(void)
{
	sbi(ADCSR, ADIF);	// clear hardware "conversion complete" flag 
	sbi(ADCSR, ADSC);	// start conversion
}

// return TRUE if conversion is complete
u08 a2dIsComplete(void)
{
	return bit_is_set(ADCSR, ADSC);
}

// Perform a 10-bit conversion
// starts conversion, waits until conversion is done, and returns result
unsigned short a2dConvert10bit(unsigned char ch)
{
	a2dCompleteFlag = FALSE;				// clear conversion complete flag
	outb(ADMUX, (inb(ADMUX) & ~ADC_MUX_MASK) | (ch & ADC_MUX_MASK));	// set channel
	sbi(ADCSR, ADIF);						// clear hardware "conversion complete" flag 
	sbi(ADCSR, ADSC);						// start conversion
	//while(!a2dCompleteFlag);				// wait until conversion complete
	//while( bit_is_clear(ADCSR, ADIF) );		// wait until conversion complete
	while( bit_is_set(ADCSR, ADSC) );		// wait until conversion complete

	// CAUTION: MUST READ ADCL BEFORE ADCH!!!
	return (inb(ADCL) | (inb(ADCH)<<8));	// read ADC (full 10 bits);
}

// Perform a 8-bit conversion.
// starts conversion, waits until conversion is done, and returns result
unsigned char a2dConvert8bit(unsigned char ch)
{
	// do 10-bit conversion and return highest 8 bits
	return a2dConvert10bit(ch)>>2;			// return ADC MSB byte
}

unsigned char chanid = 0;
signed int aresult[3] = {512,512,512};
signed int amax[3] = {512,512,512};
signed int amin[3] = {512,512,512};
unsigned char bylNaraz = 0;

//! Interrupt handler for ADC complete interrupt.
SIGNAL(SIG_ADC)
{
	aresult[chanid] = (inb(ADCL) | (inb(ADCH)<<8));	// cteni ADC (10 bits);

	if (aresult[chanid] > amax[chanid])  amax[chanid]=aresult[chanid];
	if (aresult[chanid] < amin[chanid])  amin[chanid]=aresult[chanid];

	chanid++;
	if (chanid>2) {
		chanid = 0;

		//vyhodnoceni narazu

		if (aresult[0] > 560 || aresult[0] < 490 ||
			aresult[1] > 560 || aresult[1] < 450 ||
			aresult[2] > 560 || aresult[2] < 490
		) {
			if (!bylNaraz) {
				//nulovani pameti maxim
				amin[0]=amax[0]=aresult[0];
				amin[1]=amax[1]=aresult[1];
				amin[2]=amax[2]=aresult[2];
				bylNaraz = 1;
			}
			
		}

	
	}	

	outb(ADMUX, (inb(ADMUX) & ~ADC_MUX_MASK) | (chanid & ADC_MUX_MASK));	// set channel
	sbi(ADCSR, ADIF);						// clear hardware "conversion complete" flag 
	sbi(ADCSR, ADSC);		// start conversion


	a2dCompleteFlag = TRUE;
}

