/*
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Project : Музончик
Version : 0.1.1
Date    : 29.03.2005
Author  : Pavel Sirotkin

Chip type           : ATtiny2313
Clock frequency     : 4,000000 MHz
Memory model        : Tiny
Internal SRAM size  : 128
Data Stack size     : 0x20
Return Adress Stack : 16
Compiler			: IAR EWAVR 4.10A

Note :	По большому счету глубоко пофигу для какого чипа эта программа.
		Для какой частоты и прочее.
		Главное,чтоб было два внешних прерывания и таймер щелкал на частоте 31,250 КГц.
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
*/

#include <ioavr.h>
#include <inavr.h>

#define XTALL			8.0
#define delay_us(us)	__delay_cycles (XTALL * us);
#define delay_ms(ms)	delay_us (1000 * ms)
#define Button1			PIND_Bit2	// Воспроизвести еще раз
#define Button2			PIND_Bit3	// Следующая песня
#define	Out				PORTB_Bit0	// Speaker

/*
----------------------------------------------------------------------------------------------
	Глобальные переменные
----------------------------------------------------------------------------------------------
*/
#include		"Muson.c"
unsigned char	T1Reload;
unsigned char	Play = 1;
unsigned char	Song = 0;
unsigned char	index;


/*
==============================================================================================
	Прерывание по переполнению Timer 0
==============================================================================================
*/
#pragma vector = TIMER0_OVF0_vect
__interrupt void timer0_ovf_isr (void)
{
	/* Перезагрузка значения Timer 0 */
	TCNT0 = T1Reload;
	if (T1Reload != Silence && Play)
	{
			Out = !Out;		// Смена полярности выхода
	}
	else
	{
		Out = 0;
	}
}

/*
==============================================================================================
	Внешнее прерывание 0
	
	=> Запуск воспроизведения еще раз
==============================================================================================
*/
#pragma vector = INT0_vect
__interrupt void ext_int0_isr(void)
{
	T1Reload = Silence;
	Play = 1;
	index = 0;
	
	/*	Отключаем нафиг внешние прерывания,чтоб не реагировало на кнопки	*/
	GIMSK=0x00;
	MCUCR=0x00;
	EIFR=0x00;
}

/*
==============================================================================================
	Внешнее прерывание 1
	
	=> Переход к следующей песне
==============================================================================================
*/
#pragma vector = INT1_vect
__interrupt void ext_int1_isr(void)
{
	Song++;
	T1Reload = Silence;
	index = 0;
	Play = 1;
	
	/*	И снова отключаем внешние прерывания	*/
	GIMSK=0x00;
	MCUCR=0x00;
	EIFR=0x00;
}

/*
===============================================================================================
	Инициализация внешних прерываний
	INT0:		On
	INT0 Mode:	Falling Edge
	INT1:		On
	INT1 Mode:	Falling Edge
	INT2:		Off
	Interrupt on any change on pins PCINT0-7: Off
==============================================================================================
*/
void ExtIntEnable (void)
{
	GIMSK=0xC0;
	MCUCR=0x2F;
	EIFR=0xC0;
}

/*
==============================================================================================
	MAIN
==============================================================================================
*/
void main (void)
{
	/*~~~~~~~~~~~~~~~~~~*/
	unsigned int	lang; 
	/*~~~~~~~~~~~~~~~~~~*/
	
	// Crystal Oscillator division factor: 2
	//CLKPR=0x80;
	//CLKPR=0x01;

	// Инициализация портов
	// Port D
	PORTD=0x0C;
	DDRD=0x00;

	// Port B
	PORTB=0x00;
	DDRB=0x01;

	// Инициализация Timer 0
	// Clock source: System Clock
	// Clock value: 31,250 kHz
	// Mode: Normal top=FFh
	// OC0A output: Disconnected
	// OC0B output: Disconnected
	TCCR0A=0x00;
	TCCR0B=0x03;
	TCNT0=0x00;
	OCR0A=0x00;
	OCR0B=0x00;

	/* Разрещение прерывания по переполнению Timer 0 */
	TIMSK=0x02;
	
	ExtIntEnable ();

	/* Разрешение прерываний */
	asm("sei");

	while (1)
	{
		if (!Play)
		{
			index = 0;
			asm ("Sleep");// Дрыхнем,если нет воспроизведения. Экономим электричество :-)
		};

		switch (Song)
		{
		/* "Листья" */
		case 0:
			if (index >= LIST_LAENGE)
			{
				Play = 0;
				ExtIntEnable ();
				break;
			};
			T1Reload = List[index][0];
			lang = List[index][1];
			break;
		
		/* "Бумер" */
		case 1:
			if (index >= BUMER_LAENGE)
			{
				Play = 0;
				ExtIntEnable ();
				break;
			};
			T1Reload = Bumer[index][0];
			lang = Bumer[index][1];
			break;
			
		/* "Служебный роман" */
		case 2:
			if (index >= ROMAN_LAENGE)
			{
				Play = 0;
				ExtIntEnable ();
				break;
			};
			T1Reload = Roman[index][0];
			lang = Roman[index][1];
			break;
		
		/* "Ва Банк" */
		case 3:
			if (index >= BANK_LAENGE)
			{
				Play = 0;
				ExtIntEnable ();
				break;
			};
			T1Reload = Bank[index][0];
			lang = Bank[index][1];
			break;
		
		/* "Джентельмены у Дачи" */
		case 4:
			if (index >= DJEN_LAENGE)
			{
				Play = 0;
				ExtIntEnable ();
				break;
			};
			T1Reload = Djen[index][0];
			lang = Djen[index][1];
			break;
		
		default:
			Song = 0;
			break;
		}

		/*	Цикл ожидания пока выводится текущая нота	*/
		for (lang; lang; lang--)
		{
			delay_ms(25);
		};

		/*	Следующая нота	*/
		index++;

		/*	Пауза,чтоб не было щелчков	*/
		T1Reload = Silence;
		delay_ms(20);
	};
}
