//デジタル時計プログラム
//製作者　KK
/*
使用PICマイコン	PIC16F84A
使用コンパイラ	HI-TECH C Compiler
使用ヘッダファイル
pic.h		HI-TECH C付属

最初は時刻を表示。
時刻変更の際は、時刻表示中に赤スイッチを押す。
設定中青スイッチで値＋１。赤スイッチで次の設定へ。
*/

#include<pic.h>

#define	BL_SW	RA3		//青色タクトスイッチ
#define	RE_SW	RA4		//赤色タクトスイッチ

/*=====関数宣言=====*/
void main(void);

/*=====変数宣言=====*/
unsigned char timer1,timer2,timer3;	//時間計測カウンタ
unsigned char cnt_32ms;	//32ms計測用カウンタ
unsigned int cnt_1s;	//1s計測用カウンタ
//スイッチ関連変数
unsigned char bsw=0,rsw=0,red=0,blue=0,i=0;
unsigned char cnt1=0,cnt2=0;
//表示用数値保存変数
unsigned char mode[6]={0x00,0x00,0x00,0x00,0x00,0x00};
//7セグメント指定
unsigned char dat[6]={0x00,0x01,0x02,0x03,0x04,0x05};
//7セグメント数値表示	
const unsigned char disp[10]={
0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x27,0x7f,0x67
};
//ダイナミック点灯用
unsigned char d;

/*=====pic初期化=====*/
__CONFIG(HS & WDTDIS & PWRTDIS & UNPROTECT);

/*=====メインプログラム=====*/
void main(void){
	//ポートすべて出力
	TRISA = 0x18;
	TRISB = 0x00;
	//ポートの初期化
	PORTA = 0x00;
	PORTB = 0x00;
	//timer0割り込み設定
	//320us毎の割り込み　3125回割り込みで1s
	OPTION = 0b0001;	//プリスケーラ値設定 1:4
	//タイマ割り込み・全体割り込みの許可
	INTCON = 0b10100000;
	
	//変数初期化	
	cnt_1s=0;
	timer1=timer2=timer3=0;
	i=0;
	
	
	while(1){

/*=====時刻計算=====*/
		if(!red){	//時刻設定中は停止
			if(timer1>=60){	//60秒になったら1分追加
				timer1 = 0;
				timer2++;
			}
			
			if(timer2>=60){	//60分になったら1時間追加
				timer2 = 0;
				timer3++;
			}
		
			if(timer3>=24){	//24時になったら0時にする
				timer3 = 0;
			}
		}
		
/*=====7セグ表示分岐=====*/
		switch(red){
			//時刻表示
			case 0:
				mode[4] = disp[timer1/10];
				mode[5] = disp[timer1%10];
				mode[2] = disp[timer2/10];
				mode[3] = disp[timer2%10];
				mode[0] = disp[timer3/10];
				mode[1] = disp[timer3%10];
				i=0;
				break;
				
			//時刻設定	時→分→秒
			case 1:		//時設定
				mode[4] = 0x00;
				mode[5] = 0x00;
				mode[2] = 0x00;
				mode[3] = 0x00;
				mode[0] = disp[timer3/10];
				mode[1] = disp[timer3%10];
				
				if(i){	//青スイッチ押すと＋１
					timer3++;
					if(timer3>=24){
						timer3=0;
					}
					i=0;
				}
				break;
				
			case 2:		//分設定
				mode[2] = disp[timer2/10];
				mode[3] = disp[timer2%10];
				mode[0] = 0x00;
				mode[1] = 0x00;
				
				if(i){	//青スイッチ押すと＋１
					timer2++;
					if(timer2>99){
						timer2=0;
					}
					i=0;
				}
				break;
				
			case 3:		//秒設定
				mode[4] = disp[timer1/10];
				mode[5] = disp[timer1%10];
				mode[2] = 0x00;
				mode[3] = 0x00;
				
				if(i){	//青スイッチ押すと＋１
					timer1++;
					if(timer1>=60){
						timer1=0;
					}
					i=0;
				}
				break;
		}

/*=====タクトスイッチ（赤）状態確認=====*/
	switch(rsw){
		case 0:		//押していない状態
			if(!RE_SW)rsw=1;
			cnt1=0;
			break;

		case 1:		//押している状態
			if(RE_SW)rsw=2;
			cnt1=0;
			break;
	
		case 2:		//ﾁｬﾀﾘﾝｸﾞ対策
			if(cnt1<=1 && !RE_SW)rsw=1;
			else if(cnt1>1 && RE_SW)rsw=3;
			break;
	
		case 3:		//押した後の動作
			rsw=0;
			red++;
			if(red>3){
				red=0;
			}
			break;		
	}	
	
/*=====タクトスイッチ（青）状態確認=====*/
	switch(bsw){
		case 0:		//押していない状態
			if(!BL_SW)bsw=1;
			break;

		case 1:		//押している状態
			if(BL_SW)bsw=2;
			break;

		case 2:		//押した後の動作
			bsw=0;
			blue++;
			if(blue>1)blue=0;
			i=1;
			break;
	}	
	}
	
}
		
/*=====割り込み処理=====*/
void interrupt timer(void){
	if(INTCON&0x04){	//割り込みフラグの検出
		INTCON=0b10100000;	//割り込みフラグのクリア
		cnt_32ms++;	//32msカウンタカウント
		cnt_1s++;	//1sカウンタカウント

		//7セグメント表示
		//セグメントへmodeの値を順々に出力
		PORTA = 0x07 & dat[d];	//７セグメント指定
		PORTB = 0x7f & mode[d];	//７セグメント出力
		d++;
		if(d>5)d=0;	
		
		/*32msカウンタ*/
		if(cnt_32ms == 100){
			cnt_32ms=0;
			//カウント
			cnt1++;
			cnt2++;
		}
			
		/*1sカウンタ*/
		if(cnt_1s==3125){
			cnt_1s=0;
			//カウント
			if(!red)timer1++;
		}	
	}
}
