/*
 * Весы.c
 * Весы на микроконтроллере atmega8a и ацп HX711
 * Created: 14.02.2016 14:18:17
 * Author : Дмитрий
 */ 



#define F_CPU 4000000UL

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>


#define HX_PORT PORTD
#define HX_DDR  DDRD
#define HX_PIN  PIND 
#define PosPort PORTC
#define SegPort PORTB

#define data 6
#define sck 7



unsigned char  digitbuff[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
uint32_t       adc_value = 0;
unsigned char  indVes[5];
signed long           ves = 0;
signed long           sum = 0;
signed long           popravka = 0;
unsigned int   t;
unsigned char  range=0;


void Init(void)
{
	
	
	 TIMSK=(1<<TOIE0);			              //Прерывание по переполнению	
	 TCCR0=(1<<CS00)|(1<<CS01)|(0<<CS02);	  //Prescaller = /64
	 
	 GICR   |=(1<<INT0);					  //Включаем INT0
	 MCUCR  |=(1<<ISC01);                     //The falling edge of INT0 generates an interrupt request
	
	 
	 HX_DDR |= (1<<sck);                      //sck выход, data - вход
	 HX_DDR &= ~(1<<data);
	 
	 DDRB = 0b11111111;                       //Сегменты
	 DDRC = 0b00011111;                       //Разряды
	
	 
	 HX_PORT |= (1<<data);                    //Подтягиваем data к питанию
	 HX_PORT &= ~(1<<sck);                    //На sck устанавливаем лог.единицу
	                  
	 PORTD |= (1<<2);                         //Подтяжка PD2(INT0) К питанию
	
}

uint32_t Weighing(void)
{
	uint8_t i = 0;
	adc_value = 0;

	HX_PORT &= ~(1<<sck);
	//ждём пока закончится преобразование
	while((HX_PIN & (1<<data)));
	
	for(i=0; i<24; i++)
	{
		//поднимаем строб
		HX_PORT |= (1<<sck);
		//сдвигаем значение АЦП влево, теперь значение АЦП выглядит так .......0
		adc_value <<= 1;
		//опускаем строб
		HX_PORT &= ~(1<<sck);
		//проверяем, что на выводе data, если ноль то самый правый символ так и останется ноль .......0
		//если 1, то самый правый символ будет один .......1
		if(HX_PIN & (1<<data))
		{
			adc_value++;
		}
	}

	//выборки будем брать с канала А, с коэф.усиления 128
	//поэтому стробируем еще один раз
	HX_PORT |= (1<<sck);
	HX_PORT &= ~(1<<sck);
	
	return adc_value;
}

int  main(void)
{

			 Init();    		         //Функция инициализации
	 
			 tare();
	 
			 int_to_mass(ves);   //Преобразуем в массив
	 
			asm("sei");         //Разрешение прерываний
	 
		    while(1)
			 {
		 
					 mesure();
		 
					 _delay_ms(500);
			 }
}

void int_to_mass ( volatile  signed long Temp )
{
	        unsigned int i;
			asm("cli");
			//Преобразуем данные в массив для индикации
		    for(i=0; i<5; i++)   
			{
				indVes[i]=(Temp%10);
				Temp=(Temp/10);
			}
			asm("sei");				
			//
}

void averageValue(void)
{
	sum = 0;
	for (uint8_t i = 0; i < 10; i++)
	{
		sum += Weighing();
	}

	sum / 10;
}

void tare (void)
{
	averageValue();
	popravka = sum;
}

void mesure (void)
{
	averageValue();
	if (!range)
	{
		ves = (sum-popravka)/1557;
	} 
	else
	{
		ves = (sum-popravka)/155;
	}
	
	int_to_mass(ves);
}

ISR (INT0_vect)           //ТАРИРОВКА 
{ 
	GICR   &= ~(1<<INT0); //Выключаем прерывание INT0
	SegPort=0;            //И гасим индикацию 
	tare();               //Запускаем тарировку
	_delay_ms(100);		  //Задержка переждать дребезг 
	GICR   |=(1<<INT0);   //Включаем прерывание обратно
}

 ISR(TIMER0_OVF_vect)	 //индикация 
 {					   
	static uint8_t pos=4,mask=0xFE;
	SegPort=0;
	PosPort=mask;

	
	SegPort=digitbuff[indVes[pos]];
	if (pos==2)
	{
		if (range)
		{
			SegPort |= (1<<7); //на пределе 1 точка во втором разряде.
		
	    }
	}
	if (pos==1)
	{
		if (!range)
		{
			SegPort |= (1<<7); //на пределе 0 точка в первом разряде.
			
		}
	}
	
	
	pos--;
	mask=mask<<1;mask=mask | 1;
	if(mask==0xDF)
	{
		mask=0xFE;
		pos=4;
	}
	TCNT0=0x00;
 }