/*
 * MCU_code.c
 *
 * Created: 1.1.2017 01:00:00
 * Author : Tomas Musil
 */ 

//***Clock***
#define F_CPU 8000000UL

//***Libraries***
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/sfr_defs.h>
#include <stdio.h>

//***Inputs***
#define	SW_Power	PA0
#define	SW_Phantom	PA1

//***Outputs***

#define	LED_StandBy	PB0
#define	LED_Ready	PB1
#define	LED_Phantom	PB2
#define	OUT_Phantom	PA4
#define	OUT_Output	PA5
#define	OUT_Anode	PA6
#define	OUT_Heating	PA7

//***Global***
volatile char Power_STATE;
volatile char LED_StandBy_ON;
volatile char Switch_ON;
volatile char Switch_OFF;
volatile char Phantom_STATE;
volatile char Phantom_ON;
volatile char LED_Phantom_ON;
volatile char SW_Phantom_Pushed;
volatile char TimeCounter;
volatile uint8_t Changed_Bits = 0x00;
volatile uint8_t PortA_Previous_State = 0x00;

ISR(PCINT0_vect)
{
	Changed_Bits = PINA ^ PortA_Previous_State;
	PortA_Previous_State = PINA;
	
	if (Power_STATE == 0)
	{
		if (Changed_Bits & (1 << SW_Power))
		{
			if (PINA & (1 << SW_Power))
			{
				GIMSK &= ~(1 << PCIE0);
				LED_StandBy_ON = 0;
				PORTA |= (1 << OUT_Heating);
				TCNT1 = 0;
				TCCR1B |= ((1 << CS12) | (1 << CS10));
			}
		}
	}
	
	if (Power_STATE == 1)
	{
		if (Changed_Bits & (1 << SW_Power))
		{
			if (PINA & (1 << SW_Power))
			{
				GIMSK &= ~(1 << PCIE0);
				Switch_OFF = 1;
			}
		}

		if (Changed_Bits & (1 << SW_Phantom))
		{
			if (PINA & (1 << SW_Phantom))
			{
				LED_Phantom_ON = 1;
				SW_Phantom_Pushed = 1;
				TCNT1 = 0;
				TCCR1B |= ((1 << CS12) | (1 << CS10));
			}
		
			else
			{
				TCCR1B &= ~((1 << CS12) | (1 << CS10));
				LED_Phantom_ON = 0;
				SW_Phantom_Pushed = 0;
			}
		}
	}
}

ISR(TIM1_COMPA_vect)
{
	if (Power_STATE == 0)
	{
		TimeCounter++;
		
		if (TimeCounter == 50)
		{
			TCCR1B &= ~((1 << CS12) | (1 << CS10));
			Switch_ON = 1;
		}

		else
		{
			Switch_ON = 0;
		}
	}
	
	if (Power_STATE == 1)
	{
		if (SW_Phantom_Pushed & ~Phantom_ON)
		{
			TCCR1B &= ~((1 << CS12) | (1 << CS10));
			Phantom_STATE = 1;
		}

		if (SW_Phantom_Pushed & Phantom_ON)
		{
			TCCR1B &= ~((1 << CS12) | (1 << CS10));
			Phantom_STATE = 0;
		}
	}
}

int main(void)
{
	// Inputs, Outputs
	DDRA &= ~((1 << SW_Phantom) | (1 << SW_Power));												// Inputs
	DDRA |= ((1 << OUT_Phantom) | (1 << OUT_Output) | (1 << OUT_Anode) | (1 << OUT_Heating));	// Outputs
	DDRB |= ((1 << LED_StandBy) | (1 << LED_Ready) | (1 << LED_Phantom));						// Outputs
	PORTA &= ~((1 << SW_Phantom) | (1 << SW_Power));											// Pull-Up resistor off
	
	// Interrupts
	GIMSK |= (1 << PCIE0);																		// Pin Change Interrupt Enable 0
	PCMSK0 |= ((1 << PCINT1) | (1 << PCINT0));													// Pin Change Enable Mask for PCINT0, PCINT1
	sei();																						// SREG Global Interrupt Enable (I-bit)
	
	// Timer 0 (8-bit)
	TCCR0A |= ((1 << COM0A1) | (1 << WGM00));													// Non-inverted Phase Correct PWM mode (15.686 kHz)
	TCCR0B |= (1 << CS00);
	OCR1A = 0;
	
	// Timer 1 (16-bit)
	TCCR1B |= (1 << WGM12);																		// CTC mode
	OCR1A = 9375;																				// Compared A value = 1.2 sec. for Clock = 8 MHz, Prescaler = 1024
	TIMSK1 |= (1 << OCIE1A);																	// Output Compare Match A and B Interrupt Enable
	
	Power_STATE			= 0;
	LED_StandBy_ON	 	= 1;
	Switch_ON			= 0;
	Switch_OFF			= 0;
	Phantom_STATE		= 0;
	Phantom_ON			= 0;
	LED_Phantom_ON		= 0;
	SW_Phantom_Pushed	= 0;
	TimeCounter			= 0;


    while (1)
    {
		if (Power_STATE == 0)
		{
			if (LED_StandBy_ON == 1)
			{
				PORTB |= (1 << LED_StandBy);
			}
			
			else
			{
				PORTB &= ~(1 << LED_StandBy);
			}

			if (Switch_ON == 1)
			{
				PORTA |= (1 << OUT_Anode);
				_delay_ms(2000);
				PORTA |= (1 << OUT_Output);
				PORTB |= (1 << LED_Ready);
				Power_STATE = 1;
				GIMSK |= (1 << PCIE0);
			}
		}
		
		if (Power_STATE == 1)
		{
			if (LED_Phantom_ON == 1)
			{
				if (Phantom_ON == 0)
				{
					OCR0A = 10;
				}
				
				if (Phantom_ON == 1)
				{
					OCR0A = 160;
				}
			}
			
			else
			{
			
				if (Phantom_ON == 1)
				{
					OCR0A = 160;
				}

				else
				{
					OCR0A = 0;
				}
			}

			if (Phantom_STATE & ~Phantom_ON)
			{
				GIMSK &= ~(1 << PCIE0);

				while (OCR0A < 160)
				{
					OCR0A++;
					_delay_ms(8);
				}
				
				GIMSK |= (1 << PCIE0);
				Phantom_ON = 1;
				PORTA |= (1 << OUT_Phantom);
			}

			if (~Phantom_STATE & Phantom_ON)
			{
				GIMSK &= ~(1 << PCIE0);

				while (OCR0A > 0)
				{
					OCR0A--;
					_delay_ms(8);
				}

				GIMSK |= (1 << PCIE0);
				Phantom_ON = 0;
				PORTA &= ~(1 << OUT_Phantom);
			}

			if (Switch_OFF == 1)
			{
				PORTB &= ~(1 << LED_Ready);
				PORTA &= ~(1 << OUT_Output);
				_delay_ms(1000);

				if (Phantom_ON == 1)
				{
					while (OCR0A > 0)
					{
						OCR0A--;
						_delay_ms(8);
					}

					PORTA &= ~(1 << OUT_Phantom);
				}

				OCR0A = 0;
				_delay_ms(1000);
				PORTA &= ~(1 << OUT_Anode);
				_delay_ms(5000);
				PORTA &= ~(1 << OUT_Heating);
				
				Power_STATE			= 0;
				LED_StandBy_ON	 	= 1;
				Switch_ON			= 0;
				Switch_OFF			= 0;
				Phantom_STATE		= 0;
				Phantom_ON			= 0;
				LED_Phantom_ON		= 0;
				SW_Phantom_Pushed	= 0;
				TimeCounter			= 0;

				GIMSK |= (1 << PCIE0);
			}
		}
	}
}
