#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <util/delay.h>
#include "huetabler.h"

void delay_ms(uint32_t time) {
  uint32_t i;
  for (i = 0; i < time; i++) {
    _delay_ms(1);
  }
}

#define NOOP asm volatile("nop" ::)

void SendTick();
void SendAPacket();
void SendBPacket();
void SendCPacket();

static void setup_clock( void )
{
	/*Examine Page 33*/

	CLKPR = 0x80;	/*Setup CLKPCE to be receptive*/
	CLKPR = 0x00;	/*No scalar*/
	OSCCAL = 0xf0; //B8 is bottom E8 is top. 
}

#define WSPORT PORTB
#define WSPIN _BV(3)

#define SEND_WS( var ) \
				mask = 8; \
				v = var; \
				while( mask ) \
				{ \
					if( v & 0x80 )  \
					{ \
						WSPORT |= WSPIN;  mask--; v<<=1; NOOP; /** 6us (CHECK) */  \
						WSPORT &= ~WSPIN;  /* 6us */ \
					} \
					else \
					{ \
						WSPORT |= WSPIN;  /* .3 us */ \
						WSPORT &= ~WSPIN; NOOP; \
						mask--;  v<<=1;  /* loner */ \
					} \
					\
				}



#define HUE(x) pgm_read_byte( &huetable[(x)&0xff] )
#define RAND(x) pgm_read_byte( &rands[(x)&0xff] )
#define ST(x) pgm_read_byte( &sintable[(x)&0xff] )

#define MUX(x,y) ((x*y)>>8)

register uint8_t v asm( "r3" );
register uint8_t mask asm("r4" );

int main( )
{
	int i = 0, j;
	uint8_t k;
	cli();
	setup_clock();
	DDRB = WSPIN;


//#define SLIDER
//#define SHARK
#define FIRE

	uint16_t buffer1[240];

#ifdef FIRE

	while(1)
	{
		uint8_t l;
		i++;

		//Pre-compute 'whiteness'
		for( k = 0; k < 240; k++ )
		{
			buffer1[k] += (((RAND(k)&0xff)+0xf)<<2) + (((RAND(k)&0xff)+0xf)<<1);
			//buffer1[k] = RAND(k)<<8;
		}

//make		uint8_t red = k/32;

		//GREEN, RED, BLUE
//		dtr[i] += randlist[i]*.1;
//		hex = (int)(sin( frame*.01 + dtr[(i+(frame>>2))%(lights)]*2 ) * 100+100.0)&0xff;
//		hex = 0xff | ((hex>>1)<<8) | (hex<<16);

//		l = i>>1;
		l = 0;

		uint8_t index = (buffer1[l])>>8;
		
		for( j = 0; j < 300; j++ )
		{
			uint8_t rs = ST(index)>>3;
			SEND_WS( HUE(rs )>>1 );
			index = (buffer1[l])>>8;
			SEND_WS( HUE(rs + 30) );
			l++; l &= 0x7f;
			SEND_WS( HUE(rs + 190) );
			SEND_WS( 0xff );
		}
		_delay_ms(1);
	}
#endif


#ifdef SHARK
	while(1)
	{
		uint8_t l;
		i++;

		//Pre-compute 'whiteness'
		for( k = 0; k < 240; k++ )
		{
			buffer1[k] += (((RAND(k)&0xff)+0xf)<<2) + (((RAND(k)&0xff)+0xf)<<1);
			//buffer1[k] = RAND(k)<<8;
		}

//make		uint8_t red = k/32;

		//GREEN, RED, BLUE
//		dtr[i] += randlist[i]*.1;
//		hex = (int)(sin( frame*.01 + dtr[(i+(frame>>2))%(lights)]*2 ) * 100+100.0)&0xff;
//		hex = 0xff | ((hex>>1)<<8) | (hex<<16);

//		l = i>>1;
		l = 0;

		uint8_t index = (buffer1[l])>>8;
		
		for( j = 0; j < 300; j++ )
		{
			uint8_t rs = ST(index);
			SEND_WS( rs );
			index = (buffer1[l])>>8;
			SEND_WS( rs>>1 );
			l++; l &= 0x7f;
			SEND_WS( rs | 0xfe );
		}
		_delay_ms(1);
	}
#endif



#ifdef SLIDER
	while(1)
	{
		uint8_t po = (i>>2)&0x3f;
		uint8_t rel = i;
		i++;

		WSPORT &=~WSPIN;
		_delay_us(60);
		for( j = 0; j < 300; j++ )
		{
			po = (po + 1)&0x3f;
			rel ++;
			SEND_WS( MUX( HUE( rel ), po ) );
			SEND_WS( MUX( HUE( rel + 85 ), po ) );
			SEND_WS( MUX( HUE( rel + 170 ), po ) );
			//SEND_WS( 0x01 );
			//SEND_WS( 0x00 );
			//SEND_WS( 0x00 );
			SEND_WS( MUX( HUE( rel + 46), po ) );
		}
	}
#endif


	return 0;
} 
