/*
 * LedModul.c
 *
 * Created: 10.4.2012 10:47:24
 *  Author: JIRKO
 */ 

#include <avr/io.h>
#include <avr/interrupt.h>		// Prerusenia
#include <string.h>				// praca so stringom
#include <avr/eeprom.h>			// pracas s eeprom
#include <stdio.h>				// sprintf
#include <util/delay.h>	

#include "deff_eeprom_lib.h"	// Definicia premennych a makier pre pracu s EEProm
#include "deff_packet_lib.h"	// Definicia konstant a makier, struktur pre pracu s packetom 
#include "DeffLedModulLib.h"		// Definicia vseobecnych konstant a makier pouzitich v projekte
#include "RS485_lib.h"			// kniznica pre riadenie zbernice RS485

//***************************************************************************************************
//****************   Definicia globalnych premennych   ***********************************************
volatile uint8_t PWMactualSettings[8];
volatile uint8_t LEDmodulMode;
//--------------------------------------------------------------------------------------------------

const uint8_t linear[256] = { 
    0,   0,   0,   0,   0,   0,   0,   0, 
    0,   0,   0,   0,   0,   0,   0,   0, 
    0,   0,   1,   1,   1,   1,   1,   1, 
    1,   1,   1,   1,   1,   1,   1,   1, 
    1,   1,   1,   1,   1,   1,   1,   1, 
    1,   1,   2,   2,   2,   2,   2,   2, 
    2,   2,   2,   2,   2,   2,   2,   2, 
    2,   3,   3,   3,   3,   3,   3,   3, 
    3,   3,   3,   3,   3,   4,   4,   4, 
    4,   4,   4,   4,   4,   4,   5,   5, 
    5,   5,   5,   5,   5,   5,   6,   6, 
    6,   6,   6,   6,   6,   7,   7,   7, 
    7,   7,   8,   8,   8,   8,   8,   9, 
    9,   9,   9,   9,  10,  10,  10,  10, 
   11,  11,  11,  11,  12,  12,  12,  12, 
   13,  13,  13,  14,  14,  14,  15,  15, 
   15,  16,  16,  16,  17,  17,  18,  18, 
   18,  19,  19,  20,  20,  21,  21,  22, 
   22,  23,  23,  24,  24,  25,  25,  26, 
   26,  27,  28,  28,  29,  30,  30,  31, 
   32,  32,  33,  34,  35,  35,  36,  37, 
   38,  39,  40,  40,  41,  42,  43,  44, 
   45,  46,  47,  48,  49,  51,  52,  53, 
   54,  55,  56,  58,  59,  60,  62,  63, 
   64,  66,  67,  69,  70,  72,  73,  75, 
   77,  78,  80,  82,  84,  86,  88,  90, 
   91,  94,  96,  98, 100, 102, 104, 107, 
  109, 111, 114, 116, 119, 122, 124, 127, 
  130, 133, 136, 139, 142, 145, 148, 151, 
  155, 158, 161, 165, 169, 172, 176, 180, 
  184, 188, 192, 196, 201, 205, 210, 214, 
  219, 224, 229, 234, 239, 244, 250, 255 
};


//***************************************************************************************************
//************************************   Prerusenia   ***********************************************
// prerusenie od Timer 0 200us
ISR(TIMER0_OVF_vect)				// prerusenie kazdich 200us
{									// prerusenie pri preteceni
	SET_TCNT0;					// prerusenie T0 za 200us
	I_TIMER0_RS485();				// funkcia sa vola pri viprsani casovaca TIMER 0 zabespeceuje detkciu konca packetu a prori kolizni cas 
}

	volatile uint8_t time;
	
#define MAXPWM_DEMO1	250
#define MINPWM_DEMO1	80
#define MAXPWM_DEMO2	250
#define MINPWM_DEMO2	80
#define MAXPWM_DEMO3	150
#define MINPWM_DEMO3	90

// prerusenie od Timer 2 10ms
ISR(TIMER1_OVF_vect)
{
	static uint8_t citac=60, /*smer=0,*/ stav=0;
	switch (LEDmodulMode)
	{
	case 1:
	TCNT1= 0xcd00;
	/// DEMO 1 *********************************************
 		switch (stav)
		{
			case 0:
				citac= citac+5;
				PWMactualSettings[0]= linear[citac];	// rozsvecuje sa vrch 1
				PWMactualSettings[1]= linear[citac];	// rozsvecuje sa vrch 2
				if (citac>MAXPWM_DEMO1)
				{
					stav= 1;
					citac= MINPWM_DEMO1;
				}	
				break;
			case 1:
				citac++;
				if(citac<(MAXPWM_DEMO1-40))
				{
					PWMactualSettings[2]= linear[citac];		// rozsvecujem roh 1
					PWMactualSettings[3]= linear[citac];		// rozsvecujem roh 2
					PWMactualSettings[4]= linear[citac];		// rozsvecujem roh 3
					PWMactualSettings[5]= linear[citac];		// rozsvecujem roh 4
				}					
				PWMactualSettings[0]= linear[(MAXPWM_DEMO1-citac)+MINPWM_DEMO1];	// zhasina sa vrch 1
				PWMactualSettings[1]= linear[(MAXPWM_DEMO1-citac)+MINPWM_DEMO1];	// zhasina sa vrch 2
				if (citac>MAXPWM_DEMO1)
				{
					stav= 2;
				}
				break;	
			case 2:
				citac= citac-8;
				if(citac<(MAXPWM_DEMO1-40))
				{
					PWMactualSettings[2]= linear[citac];		// zhasinam roh 1
					PWMactualSettings[3]= linear[citac];		// zhasinam roh 2
					PWMactualSettings[4]= linear[citac];		// zhasinam roh 3
					PWMactualSettings[5]= linear[citac];		// zhasinam roh 4
				}
				if (citac<=MINPWM_DEMO1)
				{
					citac=MINPWM_DEMO1;
					stav= 0;
				}
				break;
			default:
				stav= 0;
				citac= MINPWM_DEMO1;
				break;
		}	
		break;
	case 2:
	TCNT1= 0xdd00;		// pre demo 2
	/// DEMO 2 *********************************************
		switch (stav)
		{
			case 0:
				citac++;
				PWMactualSettings[0]= linear[citac];	// rozsvecuje sa vrch 1
				PWMactualSettings[1]= linear[citac];	// rozsvecuje sa vrch 2
				PWMactualSettings[2]= linear[(MAXPWM_DEMO1-citac)+MINPWM_DEMO1]; // zhasinam roh 1
				PWMactualSettings[4]= linear[(MAXPWM_DEMO1-citac)+MINPWM_DEMO1]; // zhasinam roh 3				

				if (citac>MAXPWM_DEMO1)
				{
					stav= 1;
					citac= MINPWM_DEMO1;
				}	
				break;
			case 1:
				citac++;
				PWMactualSettings[0]= linear[(MAXPWM_DEMO1-citac)+MINPWM_DEMO1];	// zhasina sa vrch 1
				PWMactualSettings[1]= linear[(MAXPWM_DEMO1-citac)+MINPWM_DEMO1];	// zhasina sa vrch 2
				
				PWMactualSettings[3]= linear[citac];	// rozsvecujem roh 2
				PWMactualSettings[5]= linear[citac];	// rozsvecujem roh 4
				if (citac>MAXPWM_DEMO1)
				{
					stav= 2;
					citac= MINPWM_DEMO1;
				}
				break;	
			case 2:
				citac++;
				PWMactualSettings[2]= linear[citac];	// rozsvecujem roh 1
				PWMactualSettings[4]= linear[citac];	// rozsvecujem roh 3
				
				PWMactualSettings[3]= linear[(MAXPWM_DEMO1-citac)+MINPWM_DEMO1]; // zhasinam roh 2
				PWMactualSettings[5]= linear[(MAXPWM_DEMO1-citac)+MINPWM_DEMO1]; // zhasinam roh 4
				if (citac>MAXPWM_DEMO1)
				{
					stav= 0;
					citac=MINPWM_DEMO1;
				}
				break;
			default:
				stav= 0;
				citac= MINPWM_DEMO1;
				break;
		}
		break;	
	case 3:
	TCNT1= 0xbd00;		// pre demo 2
	/// DEMO 2 *********************************************
		switch (stav)
		{
			case 0:
				citac++;
				PWMactualSettings[0]= linear[citac];	// rozsvecuje sa vrch 1
				PWMactualSettings[1]= linear[citac];	// rozsvecuje sa vrch 2
				PWMactualSettings[2]= linear[citac];	// rozsvecujem roh 1
				PWMactualSettings[3]= linear[citac];	// rozsvecujem roh 2
				PWMactualSettings[4]= linear[citac];	// rozsvecujem roh 3
				PWMactualSettings[5]= linear[citac];	// rozsvecujem roh 4
				if (citac>MAXPWM_DEMO3)
				{
					stav= 1;
				}	
				break;
			case 1:
				citac--;
				PWMactualSettings[0]= linear[citac];	// zhasina sa vrch 1
				PWMactualSettings[1]= linear[citac];	// zhasina sa vrch 2
				PWMactualSettings[2]= linear[citac];	// zhasinam roh 1
				PWMactualSettings[3]= linear[citac];	// zhasinam roh 2
				PWMactualSettings[4]= linear[citac];	// zhasinam roh 3
				PWMactualSettings[5]= linear[citac];	// zhasinam roh 4
				if (citac<MINPWM_DEMO3)
				{
					stav= 0;
					citac= MINPWM_DEMO1;
				}
				break;	
			default:
				stav= 0;
				citac= MINPWM_DEMO3;
				break;
		}
		break;	
	}
}
// prerusenie od Timer 2 10ms
ISR(TIMER2_OVF_vect)
{
	TCNT2= 0x1a;

	if (time >= PWMactualSettings[0] )
	{
		T0_OFF;		//zapni
	}
	else T0_ON;
	if (time >= PWMactualSettings[1] )
	{
		T1_OFF;		//zapni
	}
	else T1_ON;
	if (time >= PWMactualSettings[2] )
	{
		T2_OFF;		//zapni
	}	
	else T2_ON;
	if (time >= PWMactualSettings[3] )
	{
		T3_OFF;		//zapni
	}	
	else T3_ON;
	if (time >= PWMactualSettings[4] )
	{
		T4_OFF;		//zapni
	}	
	else T4_ON;
	if (time >= PWMactualSettings[5] )
	{
		T5_OFF;		//zapni
	}	
	else T5_ON;
	if (time >= PWMactualSettings[6] )
	{
		T6_OFF;		//zapni
	}	
	else T6_ON;
	if (time >= PWMactualSettings[7] )
	{
		T7_OFF;		//zapni
	}		
	else T7_ON;
	time++;	
}
	
// prerusenie pri vyprazneni registru UDR
ISR(USART_UDRE_vect)
{					
	I_USART_UDRE_vect();				// funkcia sa vola pri vyprazdneni UDR a zabespecuje odosielanie dat
}	

	// prerusenie pri dokonceni vysielania
ISR(USART_TXC_vect)
{
	I_USART_TXC_vect();
}

// prerusenie ked USART prime byte
ISR(USART_RXC_vect)
{	
	I_USART_RXC_vect();				// funkcia sa vola pri priati byte a zabespecuje priem dat
}	

int main(void)
{
//--------------------------------------------------------------------------------------------------

	//****************   definicia premennych  ***********************************************

	volatile uint8_t actualSettings[8];
		
	//--------------------------------------------------------------------------------------------------
	
	//****************   Inicializacia globalnych premenych  ***********************************************
	//save_master_ID(1);
	//save_my_ID(3);			// prvotne ulozenie ID	
	init_packet_lib();					// inicializacia kniznice packet_lib

	
	//****************   Nastavenia portov   ***********************************************

	DDRB=	0x01;		// Port B je cely ako vstup 
	sbi(DDRB,0);			// okrem PB0 Vystup OE
	PORTB=	0xff;		// Port B ma vsade Pullup 
	
	DDRC=	0x0f;		// Port C je cely ako vstup 
	PORTC=	0xff;		// Port C ma vsade Pullup 
	
	PORTD=	0b11100011;
	//PORTD=	0b00000001;
	DDRD=	0b11111110;

	//--------------------------------------------------------------------------------------------------
	
	//****************   Nastavenia USARTU   ***********************************************
				
	RS485_init();
	
	//--------------------------------------------------------------------------------------------------
	
////****************   Nastavenia Casovaca1 na kazdich 10ms ***********************************************
	
	//nastavenie C1			pre kristal 7.3728MHz
	TCCR1B= 0b00000010;//001;			//rezim normalny s preddelickou /1024
	TIMSK= TIMSK|(1<<TOIE1);
	TCNT1= 0xdc00;		
	
// 	////****************   Nastavenia Casovaca2 na 32Khz kazdich 31.2us ***********************************************
// 	
	//nastavenie C2			pre kristal 7.3728MHz
	TCCR2= 0b00000001;//001;			//rezim normalny s preddelickou /1024
	TIMSK= TIMSK|(1<<TOIE2);			//povolene prerusenie pri preteceni
	TCNT2= 0x1a;				//prerusenie kazdich 10ms
	
	////--------------------------------------------------------------------------------------------------
	
	LED_ON;

uint8_t		temp_buff_in_packet[MAX_PACKET_LENGHT];		// sem sa uklada priaty paket aby sa uvolnil rx buffer
uint8_t		temp_buff_out_packet[MAX_PACKET_LENGHT];	// tu sa vytvara TX packet 

uint8_t temp;

t_packet	*temp_in_packet;				// vsobecna definicia packetu 
t_packet	*temp_out_packet;
			
temp_in_packet= (t_packet *)temp_buff_in_packet;
temp_out_packet= (t_packet *)temp_buff_out_packet;

	for (temp=0; temp<8;temp++)
	{
		actualSettings[temp]= 0;
		PWMactualSettings[temp]= 0;
	}
	sei();	//Vsetky prerusenia povolene
	
    while(1)
    {
 		if( isPacketAccepted( temp_buff_in_packet ) == 0 )		// bol priaty packet 
 		{
 			
 			if ( temp_in_packet->dest_ID == BROCAST_PACKET )	// spracovanie brocastoveho packetu
 			{
 				LED_NEG;
 				switch(temp_in_packet->comand)
 				{
 					case  C_WISO_PACKET:			// who is online vo verzii ci som online						
 						temp= snprintf((char *)temp_out_packet->data, PACKET_DATA_MAX_LENGHT, "LED modul Online");					
 						fill_out_packet( temp_out_packet, temp_in_packet->sorce_ID, my_ID(), (PACKET_LENGHT_WITHAUT_DATA + temp + 1), temp_in_packet->packet_number, C_OK_PACKET, temp_in_packet->comand );
 						send_packet(temp_out_packet);			//odosielam packet ako odpoved packet _ok_packet
 						break;
 						
//  					case C_SET_ID_PACKET:			// nastav nove ID zariadenia id je v data
//  						temp= snprintf((char *)temp_out_packet->data, PACKET_DATA_MAX_LENGHT, "Zmena ID z %d na %d prebehla uspesne", temp_in_packet->dest_ID, temp_in_packet->data[0]);	// generujem spravu do data					
//  						save_my_ID(temp_in_packet->data[0]);					// menim ID
//  						fill_out_packet( temp_out_packet, temp_in_packet->sorce_ID, my_ID(), (PACKET_LENGHT_WITHAUT_DATA + temp), temp_in_packet->packet_number, C_OK_PACKET, temp_in_packet->comand);		// odpovedam uz s novym ID
//  						send_packet(temp_out_packet);			//odosielam packet ako odpoved packet _ok_packet	
//  						break;
 						
 					//default:						// neznamy packet
 					/////! neznami packet ignorujem 	
 						//break;
						 
 				}			
 			}
 			if ( temp_in_packet->dest_ID == my_ID() )	// spracovenie normalneho packetu
 			{
 				LED_NEG;
 				switch(temp_in_packet->comand)
 				{
 					case C_SET_OUTPUTS_PACKET:			// nastav vystupy na pozadovanu hodnotu	
 						temp= snprintf((char *)temp_out_packet->data, PACKET_DATA_MAX_LENGHT, "LED modul request accepted",temp_in_packet->sign);										
 						fill_out_packet( temp_out_packet, temp_in_packet->sorce_ID, my_ID(), (PACKET_LENGHT_WITHAUT_DATA + temp + 1), temp_in_packet->packet_number, C_OK_PACKET, temp_in_packet->comand);

						switch(temp_in_packet->sign)
						{
							case 0:			// nastav aktual
								LEDmodulMode= 0;
								for (temp=0; temp<8; temp++)
								{
									actualSettings[temp]= temp_in_packet->data[temp];
									PWMactualSettings[temp]= linear[temp_in_packet->data[temp]];
								}							
								break;
							case 1:			// uloz do eeprom Settings 1
								eeprom_write_block((void*)(temp_in_packet->data), (void*)EEADR_SET_OUTPUTS, LENGHT_OUTPUTS_DATA); // zapisem do eeprom EEADR_SEL_OUTPUTS(temp_in_packet->sign - 1)
								break;
						}						
 						send_packet(temp_out_packet);			//odosielam packet ako odpoved packet t_ok_packet
 						break;
 						
 					case C_SEL_SETTINGS_PACKET:			// nastav vystupy na pozadovanu hodnotu	
 						temp= snprintf((char *)temp_out_packet->data, PACKET_DATA_MAX_LENGHT, "LED modul set accepted");										
 						fill_out_packet( temp_out_packet, temp_in_packet->sorce_ID, my_ID(), (PACKET_LENGHT_WITHAUT_DATA + temp + 1), temp_in_packet->packet_number, C_OK_PACKET, temp_in_packet->comand);
						 switch(temp_in_packet->sign)
						 {
							case 1:
								LEDmodulMode= 0;
								eeprom_read_block((void*)actualSettings, (const void*)EEADR_SET_OUTPUTS, LENGHT_OUTPUTS_DATA);
								for (temp=0; temp<8; temp++)
								{
									PWMactualSettings[temp]= linear[actualSettings[temp]];
								}	
								break;
							case 2:			// nastavi demo 1
								LEDmodulMode= 1;
								break;
							case 3:			// nastavi demo 2
								LEDmodulMode= 2;
								break;
							case 4:			// nastavi demo 3 
								LEDmodulMode= 3;
								break;
						 }								
 						send_packet(temp_out_packet);			//odosielam packet ako odpoved packet t_ok_packet	
 
 						break;
 						
 					case C_SEND_DEVICE_SETTINGS:		// dotaz na aktualny stav 
 						fill_out_packet( temp_out_packet, temp_in_packet->sorce_ID, my_ID(), (PACKET_LENGHT_WITHAUT_DATA + (2*LENGHT_OUTPUTS_DATA)), temp_in_packet->packet_number, C_MY_SETTINGS, temp_in_packet->comand);
 						memcpy(temp_out_packet->data, actualSettings, LENGHT_OUTPUTS_DATA);
 						eeprom_read_block((void*)&(temp_out_packet->data[8]), (const void*)EEADR_SET_OUTPUTS, LENGHT_OUTPUTS_DATA);
 						send_packet(temp_out_packet);			//odosielam packet ako odpoved packet _my_stat_packet
 						break;
 						
 					case C_SET_ID_PACKET:			// nastav nove ID zariadenia id je v data
 						temp= snprintf((char *)temp_out_packet->data, PACKET_DATA_MAX_LENGHT, "Zmena ID z %d na %d ", temp_in_packet->dest_ID, temp_in_packet->data[0]);	// generujem spravu do data					
 						save_my_ID(temp_in_packet->data[0]);					// menim ID
 						fill_out_packet( temp_out_packet, temp_in_packet->sorce_ID, my_ID(), (PACKET_LENGHT_WITHAUT_DATA + temp), temp_in_packet->packet_number, C_OK_PACKET, temp_in_packet->comand);		// odpovedam uz s novym ID
 						send_packet(temp_out_packet);			//odosielam packet ako odpoved packet _ok_packet	
 						break;
 					
//  					case C_SET_MASTER_ID_PACKET:		// nastav masterID pre dane zariadenie
//  						temp= snprintf((char *)temp_out_packet->data, PACKET_DATA_MAX_LENGHT, "Zmena master ID prebehla uspesne");					
//  						save_master_ID(temp_in_packet->data[0]);					// menim ID
//  						fill_out_packet( temp_out_packet, temp_in_packet->sorce_ID, my_ID(), (PACKET_LENGHT_WITHAUT_DATA + temp), temp_in_packet->packet_number, C_OK_PACKET, temp_in_packet->comand);					// odpovedam uz s novym ID
//  						send_packet(temp_out_packet);			//odosielam packet ako odpoved packet 	_ok_packet
//  						break;
//  						
//  					case  C_WISO_PACKET:			// who is online vo verzii ci som online						
//  						temp= snprintf((char *)temp_out_packet->data, PACKET_DATA_MAX_LENGHT, "LED modul Online");					
//  						fill_out_packet( temp_out_packet, temp_in_packet->sorce_ID, my_ID(), (PACKET_LENGHT_WITHAUT_DATA + temp + 1), temp_in_packet->packet_number, C_OK_PACKET, my_ID());
//  						send_packet(temp_out_packet);			//odosielam packet ako odpoved packet _ok_packet
//  						break;
 						
 					default:						// ine packety
 													// neznamy packet odoslem err packet					
 							temp= snprintf((char *)temp_out_packet->data, PACKET_DATA_MAX_LENGHT, "Neznamy packet\n\r");					
 							fill_out_packet( temp_out_packet, temp_in_packet->sorce_ID, my_ID(), (PACKET_LENGHT_WITHAUT_DATA + temp + 1), temp_in_packet->packet_number, C_NACK_ERR_PACKET, my_ID());
 							send_packet(temp_out_packet);			//odosielam packet ako odpoved packet _nack_err_packet
 						break;
 				}				
 			}
 		}	
 		// ************* Sparava odosielania RS485 *********************************************************
 		
 		I_check_TX_RS485();
 		//--------------------------------------------------------------------------------------------------
 		
	}
}

