/* (set tabs to 4)

   Project;
	BinClock.c
	"Black-standard binary clock" using PIC 16F628
	v1.2 (converted to C code on 16 June 2009)
	www.RomanBlack.com
	
	This is code to make a binary clock that displays;
		quarter hours   **
		hours          ****
		minutes        ****
	using 10 leds. It was converted from and is basically the
	same operation as my .ASM version of the clock.
	
	This binary clock is a little unusual as it only has hours and mins
	variables, BUT the hours is also "quarter hours" shown as 2 leds
	in the lower 2 bits of the hours variable.

	For info on the "Black-standard for binary clock faces"
	and schematic etc see my web page;
	www.RomanBlack.com
*/
//----------------------------------------------------------------------

	// config for 16F628 (setup these in C compiler)
	// use _XT_OSC for 4Mhz, use _HS_OSC for higher xtals.
	//__CONFIG   _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC & _MCLRE_ON & _BODEN_ON & _LVP_OFF
	// include <p16f628.inc>


// define the main 1-second timer constant (is xtal / 4)
// you can also "trim" this value to finely calibrate clock speed;
// (increasing the value makes the clock run slower)
#define SECOND 1000000		// 4Mhz xtal
//#define SECOND 2000000		// 8Mhz xtal
//#define SECOND 2500000		// 10Mhz xtal
//#define SECOND 4000000		// 16Mhz xtal
//#define SECOND 5000000		// 20Mhz xtal

// define the debounce count, controls clock "setting" speed.
// use a higher value to slow down the clock setting buttons
#define DEB_COUNT 5			// 4MHz xtal
//#define DEB_COUNT 10		// 8MHz xtal
//#define DEB_COUNT 12		// 10MHz xtal
//#define DEB_COUNT 20		// 16MHz xtal
//#define DEB_COUNT 25		// 20MHz xtal

// variables
unsigned long bres;			// used for bresenham 1second timer

unsigned char secs;			// 3 vars, binary clock data
unsigned char mins;			//
unsigned char hours;		//

unsigned char debounce;		// counter to time button debounce


//----------------------------------------------------------------------
void main()
{
	//---------------------------------------------
	// setup the PIC registers etc
	CMCON = 0b00000111;     // set all pins to digital, comparators off

	PORTA  = 0;
	TRISA  = 0b00000000;  	// PORTA all outs

	PORTB  = 0;
	TRISB  = 0b11000000;   	// RB7 is "set mins", RB6 is "set hours"

	OPTION_REG = 0b00000111;    // pullups ON, TMR0 prescaled at 256:1

	VRCON = 0;              // turn off stuff we don't use
	PIE1 = 0;
	T1CON = 0;
	T2CON = 0;
	CCP1CON = 0;

	INTCON = 0; 			// no interrupts used

	//---------------------------------------------
	// setup variables
	
	bres = SECOND;  	// so clock start immediately
	
	secs = 0;
	mins = 0;
	hours = 4;	// is also quarter hours, so 4 = 1:00 when clock starts
	
	//---------------------------------------------
	// main running loop here
	// all we do is wait for TMR0 to overflow, then use a
	// bresenham clock system to generate 1 second events.
	// TMR0 is at 256:1 prescaler
	// and also check the clock set buttons.

	while(1)
	{
	    if(INTCON.T0IF) 	// if TMR0 overflowed
	    {
			INTCON.T0IF = 0;
			
			bres += 65536;    // add 65536 ticks (256*256 ticks)

	        if(bres >= SECOND)  // if we reached 1 second!
	        {
	            bres -= SECOND; 	// subtract a second
	
	            // gets here every second, so update clock.
	            secs++;
	            if(secs >= 60)
	            {
					secs = 0;
					mins++;
	                if(mins >= 15)   // if >= quarter hour
	                {
						mins = 0;
						hours++;		// this var is quarters AND hours
	                    if(hours >= 52) // if >= 13:00
	                    {
	                        hours = 4;    // reset back to 1:00
						}
 					}
	            }
				// display the new clock value
				PORTA = mins;
				PORTB = hours;
			}
	
			// gets here every 65536 ticks, so check the "set" buttons
	        debounce++;
	        if(debounce >= DEB_COUNT)   // DEB_COUNT sets the update speed
	        {
				debounce = 0;
				
				// "set hours" button
	            if(!PORTB.F6)	// lo = pressed
	            {
	                hours++;     	// so inc the hours
	                if(hours >= 52) hours = 4;
					PORTB = hours;	// display the new hours
	            }
	            // "set minutes" button
	            if(!PORTB.F7)	// lo = pressed
	            {
	                mins++;     	// so inc the mins
	                if(mins >= 15) mins = 0;
					secs = 0;		// also reset the seconds
					PORTA = mins;	// display the new mins
	            }
	        }
		}
	}
}
//----------------------------------------------------------------------
