#include <avr/interrupt.h>
#include <inttypes.h>
#include <avr/io.h>
#include <stdlib.h>
#include <math.h>

void delayms(uint16_t millis);

unsigned int Phase_Minimum[] = {0,0,0,0,0,0,0,0};
unsigned int Phase_Maximum[] = {0,0,0,0,0,0,0,0};
unsigned long Note_Minimum[] = {0,0,0,0,0,0,0,0};
unsigned long Note_Maximum[] = {0,0,0,0,0,0,0,0};

unsigned char Selected_Channels[] = {0,0,0,0,0,0,0,0};
unsigned char Powers[] = {1,2,4,8,16,32,64, 128};
unsigned char Total_Channels = 8;
unsigned char Channel = 0;
unsigned char Input = 0;
unsigned char Output = 0;
unsigned char Last_Output = 0;
unsigned char LED_Offset = 0;
unsigned char LED_Note_Offset = 0;

unsigned const int The_Salmon_Of_Knowledge = 0;
unsigned const int Speaker = 1;
unsigned const int The_Bull_Of_Cooley = 2;
unsigned const int Deirdre_Of_The_Sorrows = 3;	
unsigned const int The_Fir_Bolg = 4;					
unsigned const int The_Children_Of_Lir = 5;
unsigned const int The_Leprechaun = 6;
unsigned const int The_Merrow_Folk = 7;

unsigned char New_Challenger = 0;
unsigned char Last_Challenger = 0;
unsigned char Challengers[] = {0,0,0,0,0,0,0,0};
unsigned long Special_Moves[] = {0,0,0,0,0,0,0,0};

unsigned char Phase[] = {0,0,0,0,0,0,0,0};	
unsigned int Phase_Frame[] = {0,0,0,0,0,0,0,0};
unsigned int Phase_On_Duration[] = {0,0,0,0,0,0,0,0};
unsigned int Phase_Off_Duration[] = {0,0,0,0,0,0,0,0};

unsigned char Note[] = {0,0,0,0,0,0,0,0};
unsigned long Note_Frame[] = {0,0,0,0,0,0,0,0};
unsigned long Note_On_Duration[] = {0,0,0,0,0,0,0,0};
unsigned long Note_Off_Duration[] = {0,0,0,0,0,0,0,0};

unsigned long Jostle_Frame = 0;
unsigned long Jostle_Duration = 3000;
unsigned long Jostle_Random = 0;

unsigned char Current_Channels = 0;
unsigned char Max_Channels = 2;
unsigned char Channel_Inner = 0;


int main()
{
	DDRD = 255;
	PORTD = 0;
	
	DDRB = 255;
	PORTB = 0;
	
	Last_Output = PORTD;
	
	Jostle_Random = rand();
	Current_Channels = 0;
	// Set up derivative 1!
	for (Channel = 0; Channel < Total_Channels; Channel++)
	{
	
		// Set up derivative 1!	
		Phase_Minimum[Channel] = (Channel % 4) * 5 + 1;
		Phase_Maximum[Channel] = Phase_Minimum[Channel]  * 10;
		Note_Minimum[Channel] = Phase_Maximum[Channel] * 2;
		Note_Maximum[Channel] = Phase_Maximum[Channel] * 100;
	
		
		// Set up derivative 2!
		Phase_On_Duration[Channel] = rand() * Phase_Maximum[Channel] / RAND_MAX + Phase_Minimum[Channel];
		Phase_Off_Duration[Channel] = Phase_On_Duration[Channel];
		Note_On_Duration[Channel] = rand() * Note_Maximum[Channel] / RAND_MAX + Note_Minimum[Channel];
		Note_Off_Duration[Channel] = Note_On_Duration[Channel];
	
		// Set up derivative 3!			
		if (Jostle_Random & Powers[Channel] && Current_Channels < Max_Channels)
		{
			Current_Channels++;
			Selected_Channels[Channel] = 1;
			Last_Challenger = Channel;
		}
		else
			Selected_Channels[Channel] = 0;
		
	}
		
	while (1)
	{	
		Output = 0;
		// Keep phase time.
		for (Channel = 0; Channel < Total_Channels; Channel++)
		{
			Phase_Frame[Channel]++;
			if (Note[Channel] && ((Phase[Channel] && Phase_Frame[Channel] > Phase_On_Duration[Channel]) || Phase_Frame[Channel] > Phase_Off_Duration[Channel]))
			{
				Phase[Channel] = 1 - Phase[Channel];				
				Phase_Frame[Channel] = 0;
			}
			
			Note_Frame[Channel]++;
			if ((Note[Channel] && Note_Frame[Channel] > Note_On_Duration[Channel]) || Note_Frame[Channel] > Note_Off_Duration[Channel])
			{
				Note[Channel] = 1 - Note[Channel];
				// Reset phase duration for a new note.
				if (Note[Channel] == 1)
				{
					Phase_On_Duration[Channel] = rand() * Phase_Maximum[Channel] / RAND_MAX + Phase_Minimum[Channel];
					Phase_Off_Duration[Channel] = Phase_On_Duration[Channel];
				}
				
				Phase_Frame[Channel] = 0;
				Note_Frame[Channel] = 0;
			}	
			
			//Mixing
			if (Selected_Channels[Channel] == 1)
			{
				Output ^= Phase[Channel];
			}
		}	
		
		
		/*
		// Every so often JOSTLE
		Jostle_Frame++;			
		if (Jostle_Frame > Jostle_Duration)
		{
			Jostle_Random = rand();
			for (Channel = 0; Channel < Deirdre_Of_The_Sorrows; Channel++)
			{				
				if (Jostle_Random & Powers[Channel])
				{
					Selected_Channels[Channel] = 1;
					Phase_On_Duration[Channel] = rand() * Phase_Maximum[Channel] / RAND_MAX + Phase_Minimum[Channel];
					Phase_Off_Duration[Channel] = Phase_On_Duration[Channel];
					Note_On_Duration[Channel] = rand() * Note_Maximum[Channel] / RAND_MAX + Note_Minimum[Channel];
					Note_Off_Duration[Channel] = rand() * Note_Maximum[Channel] / RAND_MAX + Note_Minimum[Channel];					
				}
				else 
					Selected_Channels[Channel] = 0;				
			}
			Jostle_Frame = 0;
			//Jostle_Duration = rand() / 2;
		}
		*/
		
		// Mixer 
				
		Input = PIND ^ Last_Output;
		
		New_Challenger = 0;
		for (Channel = 0; Channel < Total_Channels; Channel++)
		{
			if (Input & Powers[Channel])
			{
				New_Challenger = 1;
				Last_Challenger = Channel;				
				Challengers[Channel] = 1;
				Special_Moves[Channel]++;							
			}
			else
			{
				Challengers[Channel] = 0;				
			}
			
			// Special Moves
			switch (Channel)
			{
				case 0: //The_Salmon_Of_Knowledge:	
				
					// THE SALMON OF KNOWLEDGE STOPS TO PONDER
					if (Special_Moves[Channel]  > 3000)
					{
						Special_Moves[Channel] = 0;
						for (Channel_Inner = 0; Channel_Inner < Total_Channels; Channel_Inner++)
						{
							Phase_On_Duration[Channel_Inner] = rand() * Phase_Maximum[Channel_Inner] / RAND_MAX + Phase_Minimum[Channel];
							Phase_Off_Duration[Channel_Inner] = Phase_On_Duration[Channel_Inner];
							Note_On_Duration[Channel_Inner] = rand() * Note_Maximum[Channel_Inner] / RAND_MAX + Note_Minimum[Channel];
							Note_Off_Duration[Channel_Inner] = Note_On_Duration[Channel_Inner];
						}
						LED_Note_Offset = (LED_Note_Offset + 1)  % 4;
					}
					
					break;
				case 1: //Speaker:
					break;
				case 2: //The_Bull_Of_Cooley:
					// THE BULL OF COOLEY FOLLOWS THE RAINBOW
					if (Special_Moves[Channel]  > 50)
					{
						Special_Moves[Channel] = 0;
						for (Channel_Inner = 0; Channel_Inner < Total_Channels; Channel_Inner++)
						{
							Note_Off_Duration[Channel_Inner] = rand() * Note_Maximum[Channel_Inner] / RAND_MAX + Note_Minimum[Channel];
						}
					}
					break;
				case 3: //Deirdre_Of_The_Sorrows
					// DEIRDRE OF THE SORROWS WEEPS INTO THE SKY
					if (Special_Moves[Channel]  > 100 )
					{
							for (Channel_Inner = 0; Channel_Inner < Total_Channels; Channel_Inner++)
							{
								Phase_Off_Duration[Channel_Inner] = Phase_Off_Duration[Channel_Inner] - 1  % Phase_On_Duration[Channel_Inner];
							}
							Special_Moves[Channel] = 0;		
					}
					break;
				case 4: //The_Fir_Bolg
					// THE FIR BOLG RAVAGE THE PLAINS					
					if (Special_Moves[Channel]  > 2000)
					{					
						Special_Moves[Channel] = 0;
						for (Channel_Inner = 0; Channel_Inner < Total_Channels; Channel_Inner++)
						{
							Phase_On_Duration[Channel_Inner] = rand() * Phase_Maximum[Channel_Inner] / RAND_MAX + Phase_Minimum[Channel];
							Phase_Off_Duration[Channel_Inner] = rand() * Phase_Maximum[Channel_Inner] / RAND_MAX + Phase_Minimum[Channel];
							Note_On_Duration[Channel_Inner] = rand() * Note_Maximum[Channel_Inner] / RAND_MAX + Note_Minimum[Channel];
							Note_Off_Duration[Channel_Inner] = rand() * Note_Maximum[Channel_Inner] / RAND_MAX + Note_Minimum[Channel];
						}
						LED_Offset = (LED_Offset + 1) % 2;
					}
					
					break;
				case 5: // The_Children_Of_Lir
					// THE CHILDREN OF LIR GATHER IN THE FOREST
					if (Special_Moves[Channel] > 0)
					{
						Jostle_Random = rand();
						Max_Channels = rand() % 2;
						for (Channel_Inner = 0; Channel_Inner < Total_Channels; Channel_Inner++)
						{
							if (Jostle_Random & Powers[Channel] && Current_Channels < Max_Channels)
							{
								Current_Channels++;
								Challengers[Channel] = 1;
							}
							else
								Challengers[Channel] = 0;
						}
						Special_Moves[Channel] = 0;		
					}
					break;
				case 6: //The_Leprechaun
					// THE LEPRECHAUN GIGGLES NIMBLY
					if (Special_Moves[Channel] > 1)
					{
							for (Channel_Inner = 0; Channel_Inner < Total_Channels; Channel_Inner++)
							{							
								Note_Off_Duration[Channel_Inner] = 100;
							}
							Special_Moves[Channel] = 0;		
					}
					break;
				case 7: //The_Merrow_Folk
					// THE MERROW FOLK GLIMMER CALMLY
					if (Special_Moves[Channel] > 1000)
					{
						LED_Offset = (LED_Offset + 1) % 2;
						LED_Note_Offset = (LED_Note_Offset + 1)  % 4;
						Special_Moves[Channel] = 0;
					}
					break;
			}
		}
		
		// Reset mixer on change		
		if (New_Challenger )
		{		
			for (Channel = 0; Channel < Total_Channels; Channel++)
			{
				if (Challengers[Channel])
				{
					Selected_Channels[Channel] = 1;
					Note[Channel] = 1;
				}
				else
					Selected_Channels[Channel] = 0;
			}			
			
			// Preserve one channel for continuity!
			Selected_Channels[Last_Challenger] = 1;
		}	
					
		// Output and capture output.
		// SPEAKER : 1 
		// WARRIORS : 0,2,3,4,5,6,7
		PORTD = (Phase[0] << 0) | (Output << 1 ) | (Phase[1] << 2) | (Phase[2] << 3) | (Phase[3] << 4) | (Phase[4] << 5) | (Phase[5] << 6) | (Output << 7);
		Last_Output = PORTD;
		
		// Output LEDs
		//LED_Offset = 0;
		PORTB = (Note[0 + LED_Note_Offset] << (0 + LED_Offset)) | (Note[1 + LED_Note_Offset] << (1 + LED_Offset)) | (Note[2 + LED_Note_Offset] << (2 + LED_Offset));
	}
	return 0;
}


/* at 8 MHz we get 1us per 8 instructions */
inline void delayus() { asm volatile("nop\nnop\nnop\nnop\n"
                                     "nop\nnop\nnop\nnop"); }


// Resources 

void delayms(uint16_t millis) {
  uint16_t loop;
  while ( millis ) {
    loop = 100;
    while (loop) {
      /* 20us of delays */
      delayus(); delayus(); delayus(); delayus(); delayus();
      delayus(); delayus(); delayus(); delayus(); delayus();
      loop --;
    }
    millis--;
  }
}


