/* Program CANDLE LED (embers glowing variation)
 * 
 * This program simulates the smooth and faint glowing of embers
 *
 * LED should be connected to pin GPIO2 (pin 5)
 * PIC12 should be configured to work with IntOSC + PWRT + BODEN 
 *
 * 2011/09 (c) Joao Figueiredo
 *
 */

#include<pic.h>
 
// ----- Fuses -----
__CONFIG(MCLRDIS & PWRTEN & PWRTEN & WDTDIS & INTIO);
//__CONFIG(MCLREN & PWRTEN & PWRTEN & WDTDIS & INTIO);

// ----- Globals -----
unsigned int t1value = 65535-(100+99*1)+1; // inicial de 1%

// ----- Interrupt service routine -----
void interrupt isr(void)
{
	if(T0IF)
	{
		TMR0 = 217;
		TMR1H = (t1value>>8)&0xFF;
		TMR1L = (t1value&0xFF);
		GPIO2 = 1;	// Pin on
		TMR1ON = 1;
		T0IF = 0;
	}
	if(TMR1IF)
	{
		TMR1ON = 0;
		GPIO2 = 0;	// pin off
		TMR1IF = 0;
	}
}

// ----- Random bit generator -----

char getRandomBit(void)
{
	static unsigned short shiftregister = 0x9500;

	unsigned short value;
	char output;

	/* feedback based on 1+x10+x11 polynomial function */
	value = (shiftregister&0x0200)>>9 ^ (shiftregister&0x0400)>>10;

	/* feedback */
	shiftregister <<= 1;
	shiftregister |= value;

	output = (value^1) & 0x01;
	return output;
}


// ----- Main Program -----
void main(void)
{
	char i=65;
	int  pause;

	GIE = 0;
	PEIE = 0;

	// IO
	TRISIO = 0x3B;		// Configure GP2 0b 0011 1011

#ifdef _12F675
	// disable the ADC pins (all digital IO)	
	ANSEL = 0;
#endif
	
	// Timer 0
	OPTION = 0xD7;		// 0b 1101 0111  T0CS=0, PSA=0, 1:256
	TMR0 = 217;		// (Fosc/4)/(256*39) = 100Hz
	T0IF = 0;
	T0IE = 1;

	// Timer 1
	T1CON = 0x00;			// 0b 0000 0000
	TMR1H = (t1value>>8)&0xFF;	//  Timer for 10KHz multiples
	TMR1L = (t1value&0xFF);
	TMR1IF = 0;
	TMR1IE = 1;
	
	PEIE = 1;
	GIE  = 1;

	while(1)
	{
		if(getRandomBit())
			i += 3; // if bit is 1 increment 10
		else
			i -= 3; // if bit is 0 decrement 10;

		/* protect i within 0...100 limit */
		if( i<50 ) i=50;	// not too low so the LED doesn't go off completely
		if( i>80 ) i=80;	// not too high to obfuscate the surroundings

		/* configure t1value for pwm generation and pause */
		t1value = 65535-(100+99*i)+1; 
		for(pause=0; pause<6000; pause++);
	}
}

