/*  Filename     MKIT2.C
    Description  MKIT-2 Digital Clock
    Hardware     MKIT-2
    Clock        11.0592 Mhz
    Compiler     Keil PK51 v7.10
    Engineer     Kriangsak B.
    Company      Sila Research Co.,Ltd. 
*/

#include <reg51.h>
#include <absacc.h>
#include <assert.h>
#include <ctype.h>
#include <intrins.h>
#include <math.h>
#include <setjmp.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define  TOUTV     5800
#define  FLASHV    25

/********** I/O PORT **********/

sbit     IRDAT   = P1^0;
sbit     MXDAT   = P1^1;
sbit     MXLDB   = P1^2;
sbit     MXCLK   = P1^3;
sbit     LEDAL   = P1^4;
sbit     SOUNDB  = P1^5;
sbit     IRSDA   = P1^6;
sbit     IRSCL   = P1^7;

sbit     KADJ    = P3^0;
sbit     KSET    = P3^1;

/********** INT-RAM WORKING AREA **********/

unsigned char      DISBUF[8] _at_ 0x08;     // display buffer
unsigned char      TIMBUF[8] _at_ 0x10;     // ss,mm,hh,ww,dd,mm,yy,cc 

unsigned char      HEXBUF[4];               // hex(bcd) buffer
unsigned char      STRBUF[3];               // string buffer
unsigned int       TOUT;                    // time out var.
unsigned char      LINE;                    // line memu
unsigned char      TIMERM;                  // timer mm:ss
unsigned char      TIMERS;
unsigned char      ALARMC;                  // alarm counter
unsigned char      IRKADJ[16];              // ir remote memory
unsigned char      IRKBUF[16];

         bit       PRESSF;                  // key press flag 
		 bit       TOUTF;                   // time out flag
		 bit       TIMERF;                  // timer alarm flag
		 bit       IRFLAG;                  // ir remote flag

                                            // **** backup area (DS1307) ****
unsigned char      SPCDAY[8];               // special day 1-4
unsigned char      ALARMD[8];               // alarm data 1-4
unsigned char      ALARMF;                  // alarm flag

/********** BASIC FUNCTION **********/

void dmsec (unsigned int count) {           // mSec Delay
    unsigned int i;                         // for Keil CA51 (Speed x 1)
    while (count) {
        i = 115; while (i>0) i--;
        count--;
    }
}

void disclear (void) {                      // clear DISBUF
    unsigned char i;
    for (i=0;i<=7;i++) {
        DISBUF[i] = 0;
    }
}

void disclear4 (void) {                     // clear green DISBUF
    DISBUF[4] = 0;
    DISBUF[5] = 0;
    DISBUF[6] = 0;
    DISBUF[7] = 0;
}

void beepok (void) {SOUNDB = 0; dmsec (500); SOUNDB = 1;}
void beepky (void) {SOUNDB = 0; dmsec (50); SOUNDB = 1;}

void mxbyte (unsigned char add,dat) {
    unsigned char i;
    for (i=1;i<=8;i++) {               // 8 bit address
        MXDAT = add & 0x80;
        add = add << 1;
        MXCLK = 1;
        MXCLK = 0;
    }
    for (i=1;i<=8;i++) {               // 8 bit data
        MXDAT = dat & 0x80;
        dat = dat << 1;
        MXCLK = 1;
        MXCLK = 0;
    }
    MXLDB = 1;                         // load clock
    MXLDB = 0;
}

void mxset (void) {                    // max7219 setup
    MXCLK = 0;
    MXLDB = 0;
    mxbyte (0x0f,0);                   // display - normal
    mxbyte (0x0c,1);                   // shutdown - normal
    mxbyte (0x09,0);                   // decode - no decode
    mxbyte (0x0a,15);                  // intensity
    mxbyte (0x0b,7);                   // scan limit - 8 digit
}

void mxload (void) {                   // max7219 load to display
    mxset ();
    mxbyte (1,DISBUF[0]);
    mxbyte (2,DISBUF[1]);
    mxbyte (3,DISBUF[2]);
    mxbyte (4,DISBUF[3]);
    mxbyte (5,DISBUF[4]);
    mxbyte (6,DISBUF[5]);
    mxbyte (7,DISBUF[6]);
    mxbyte (8,DISBUF[7]);
}

void irdel (void) {                    // I2C delay 
    _nop_ ();
    _nop_ ();
    _nop_ ();
    _nop_ ();
    _nop_ ();
    _nop_ ();
    _nop_ ();
    _nop_ ();
}

void irchigh (void) {                  // I2C clock high 
    IRSCL = 1;
    irdel ();
}

void irclow (void) {                   // I2C clock low 
    IRSCL = 0;
    irdel ();
}

void irstart (void) {                  // start condition 
    IRSDA = 1;
    IRSCL = 1;
    IRSDA = 0;
    irdel ();
    IRSCL = 0;
    IRSDA = 1;
}
                                        
void irstop (void) {                   // stop condition 
    IRSDA = 0;
    IRSCL = 1;
    irdel ();
    IRSDA = 1;
}

bit irwrbyte (unsigned dat) {          // write one byte for ds1307
    unsigned char i;                   // return 0 = ok 
    bit outbit;                        // return 1 = error 
    for (i=1;i<=8;i++) {
        outbit = dat & 0x80;
        IRSDA = outbit;
        dat = dat << 1;
        irchigh ();
        irclow ();
    }
    IRSDA = 1;
    irchigh ();
    outbit = IRSDA;
    irclow ();
    return (outbit);
}

unsigned char irrdbyte () {       // read one byte for ds1307 (last byte) 
    unsigned char i,dat;          // return 0xff = error 
    bit inbit;
    dat = 0;
    for (i=1;i<=8;i++) {
        irchigh ();
        inbit = IRSDA;
        dat = dat << 1;
        dat = dat | inbit;
        irclow ();
    }
    IRSDA = 1;
    irchigh ();
    inbit = IRSDA;
    irclow ();
    if (~inbit) dat = 0xff;
    return (dat);
}

unsigned char irrdbytez () {      // read one byte ack=0 for DS1307 
    unsigned char i,dat;         
    bit inbit;
    dat = 0;
    for (i=1;i<=8;i++) {
        irchigh ();
        inbit = IRSDA;
        dat = dat << 1;
        dat = dat | inbit;
        irclow ();
    }
    IRSDA = 0;
    irchigh ();
    irclow ();
    IRSDA = 1;
    return (dat);
}

void rtset (void) {                    // set RTC status bit 
    TIMBUF[0] = TIMBUF[0] & 0x7f;      // clear CH (clock halt) 
    TIMBUF[2] = TIMBUF[2] & 0xbf;      // set 24 hour 
    TIMBUF[7] = TIMBUF[7] & 0xec;      // b7=out b4=sqwe b1,b0=rs 
}

void rtwr (void) {                     // ds1307 rtc write 
    unsigned char i;                   
    irstart ();
    irwrbyte (0xd0);                   // address & r/w bit 
    irwrbyte (0x00);                   // start register addr=0 
    for (i=0;i<=7;i++) 
        irwrbyte (TIMBUF[i]);
    irstop ();
}

void rtrd (void) {                     // ds1307 rtc read 
    unsigned char i,dat;               
    irstart ();
    irwrbyte (0xd0);                   // address & r/w bit 
    irwrbyte (0x00);                   // start register addr=0 
    irstop ();
    irdel ();

    irstart ();
    irwrbyte (0xd1);                   // address & r/w bit 
    for (i=0;i<=6;i++) {
        dat = irrdbytez ();
        TIMBUF[i] = dat;
    }
    dat = irrdbyte ();                 // last byte 
    TIMBUF[7] = dat;                   // if TIMBUF[7]=0xff error
    irstop ();
}

void rtwrram (void) {                  // ds1307 write ram
    unsigned char i;
    irstart ();
    irwrbyte (0xd0);                   // address & r/w bit
    irwrbyte (0x08);                   // start register addr=08

	for (i=0;i<=7;i++) irwrbyte (SPCDAY[i]);
    for (i=0;i<=7;i++) irwrbyte (ALARMD[i]);
    irwrbyte (ALARMF);
    irstop ();
}

void rtrdram (void) {                  // ds1307 read ram
    unsigned char i;
    irstart ();
    irwrbyte (0xd0);                   // address & r/w bit
    irwrbyte (0x08);                   // start register addr=0
    irstop ();
    irdel ();
    irstart ();
    irwrbyte (0xd1);                   // address & r/w bit

	for (i=0;i<=7;i++) SPCDAY[i] = irrdbytez ();
	for (i=0;i<=7;i++) ALARMD[i] = irrdbytez ();
    ALARMF = irrdbyte ();                             // last byte (no z)
    irstop ();
}

unsigned char code SEGTAB[16] = {0x7E,0x30,0x6D,0x79,0x33,0x5B,0x5F,0x70,
                                 0x7F,0x7B,0x77,0x1F,0x4E,0x3D,0x4F,0x01};
                                 // max7219 segment code (F='-')

unsigned char htosx (unsigned char hex) {        // change hex to segment
    return (SEGTAB[hex]);
}
                         
unsigned char stohx (unsigned char segm) {       // change segment to hex
    unsigned char i;                             // 0xff = Error
    for (i=0;i<=15;i++)
        if (segm==SEGTAB[i]) return (i);
    return (0xff);
}

void htos (void) {                               // change hex(bcd) to segment
    DISBUF[0] = htosx ((HEXBUF[0] & 0xf0) >> 4); 
    DISBUF[1] = htosx (HEXBUF[0] & 0x0f);
    DISBUF[2] = htosx ((HEXBUF[1] & 0xf0) >> 4);
    DISBUF[3] = htosx (HEXBUF[1] & 0x0f);
    DISBUF[4] = htosx ((HEXBUF[2] & 0xf0) >> 4); 
    DISBUF[5] = htosx (HEXBUF[2] & 0x0f);
    DISBUF[6] = htosx ((HEXBUF[3] & 0xf0) >> 4);
    DISBUF[7] = htosx (HEXBUF[3] & 0x0f);
}

void stoh (void) {                               // change segment to hex(bcd)

    HEXBUF[0] = (stohx (DISBUF[0]) << 4) | stohx (DISBUF[1]);
    HEXBUF[1] = (stohx (DISBUF[2]) << 4) | stohx (DISBUF[3]);
    HEXBUF[2] = (stohx (DISBUF[4]) << 4) | stohx (DISBUF[5]);
    HEXBUF[3] = (stohx (DISBUF[6]) << 4) | stohx (DISBUF[7]);
}

void setweek (unsigned char x) {       // set week led
    unsigned char i;
	for (i=0;i<=6;i++) DISBUF[i] = DISBUF[i] & 0x7f;
	switch (x) {
        case 1: DISBUF[0] = DISBUF[0] | 0x80; break;
        case 2: DISBUF[1] = DISBUF[1] | 0x80; break;
        case 3: DISBUF[2] = DISBUF[2] | 0x80; break;
        case 4: DISBUF[3] = DISBUF[3] | 0x80; break;
        case 5: DISBUF[4] = DISBUF[4] | 0x80; break;
        case 6: DISBUF[5] = DISBUF[5] | 0x80; break;
        case 7: DISBUF[6] = DISBUF[6] | 0x80; break;
	}
}

void ttos (void) {                     // time to segment          
    HEXBUF[0] = TIMBUF[2];
	HEXBUF[1] = TIMBUF[1];
	HEXBUF[2] = TIMBUF[4];
	HEXBUF[3] = TIMBUF[5];
    htos ();
}

void stot (void) {                     // segment to time 
    stoh ();
	TIMBUF[2] = HEXBUF[0];
	TIMBUF[1] = HEXBUF[1];
	TIMBUF[4] = HEXBUF[2];
	TIMBUF[5] = HEXBUF[3];
}

unsigned char pulse (void) {           // pulse count          
    unsigned char i,x;
    x = 0;
	while (IRDAT==0) {
	    i = 20;
		while (i>0) i--;
	    x++; 
    }
	while (IRDAT==1) {
        i = 20;
		while (i>0) i--;
		x++;
		if (x==0xff) return (x);       // pulse end
	}
	return (x);
}

unsigned char gremote (void) {         // get & check remote
    unsigned char x,i,a,b;

    for (i=0;i<=15;i++) IRKBUF[i] = 0; // clear buffer
	pulse ();                          // don't care first 4 pulse
	pulse ();
	pulse ();
	pulse ();
    while (1) {
        x = pulse ();
  	    if (x==0xff) break;
        IRKBUF[0] = IRKBUF[1];
        IRKBUF[1] = IRKBUF[2];
        IRKBUF[2] = IRKBUF[3];
        IRKBUF[3] = IRKBUF[4];
        IRKBUF[4] = IRKBUF[5];
        IRKBUF[5] = IRKBUF[6];
        IRKBUF[6] = IRKBUF[7];
        IRKBUF[7] = IRKBUF[8];
        IRKBUF[8] = IRKBUF[9];
        IRKBUF[9] = IRKBUF[10];
        IRKBUF[10] = IRKBUF[11];
        IRKBUF[11] = IRKBUF[12];
        IRKBUF[12] = IRKBUF[13];
        IRKBUF[13] = IRKBUF[14];
        IRKBUF[14] = IRKBUF[15];
        IRKBUF[15] = x;
	}

    a = 0xff;                                              // check ir error
	for (i=0;i<=15;i++) {                                  // find min
        if (IRKBUF[i]<a) a = IRKBUF[i];
	}
	b = (a * 2) + 4;                                       // a = short pulse - 4 , b = long pulse + 4
    a = a - 4;                                           
    for (i=0;i<=15;i++) {
        x = IRKBUF[i];
		if (x<a || x>b) return (0);                        // do nothing (error)
	}

    beepky ();                                             // shure ... is ir remote
    TOUT = TOUTV;
  	TOUTF = 0;
    dmsec (50);
    if (IRFLAG==0) {                                       // first key (adj)
        for (i=0;i<=15;i++) IRKADJ[i] = IRKBUF[i];
		IRFLAG = 1;
		return (2);
	}
    else {                                                 // compare second key
        for (i=0;i<=15;i++) {
            x = IRKBUF[i];
			a = IRKADJ[i] - 4;
			b = IRKADJ[i] + 4;
			if (x<a || x>b) return (1);                    // key set
		}
		return (2);                                        // key adj
	}
/*
    a = 0;
    for (i=0;i<=3;i++) {                                   // display ir data 
        disclear ();
    	HEXBUF[0] = IRKBUF[a++];
    	HEXBUF[1] = IRKBUF[a++];
	    HEXBUF[2] = IRKBUF[a++];
    	HEXBUF[3] = IRKBUF[a++];
    	htos ();
	    mxload ();
    	beepky ();
	    dmsec (2500);
	}
	return (0);
*/
}

unsigned char gkey2 (void) {                     // gkey 2 keys
    unsigned char x;
	dmsec (5);
	if (IRDAT==0) return (gremote ());
    if (KSET==0 || KADJ==0) {                    // out = 1,2 (0 nothing)
        if (PRESSF==0) {
            if (KSET==0) x = 1; else x = 2;
            beepky (); 
			PRESSF = 1; 
			TOUT = TOUTV;
			TOUTF = 0;
			return (x);
        }
        else return (0);
    }
	else PRESSF = 0;

    if (TOUT>0) {                                // check time out 
        TOUT--;
		if (TOUT==0) TOUTF = 1;
	}
    return (0);
}

bit getdigit (unsigned char digit,unsigned char max) {
    bit f;
    unsigned char i,mem;
    unsigned int j;
    j = 0; mem = stohx (DISBUF[digit]);
    while (1) {
        i = gkey2 ();
        if (i==2) {mem++; if (mem>max) mem=0;}   // adj key
        else if (i==1) {                         // set key
            DISBUF[digit] = htosx (mem);
			mxload ();
            return (0);
        }
        else {                                   // flash on digit
            j++;
            if (j==FLASHV) {
                j = 0; f = ~f;
                if (f) DISBUF[digit] = htosx (mem);
                else DISBUF[digit] = 0;
				mxload ();
            }
        }
		if (TOUTF) return (1);
    }
}

bit getdigitx (unsigned char digit,unsigned char max) {    
    bit f;
    unsigned char i,mem;
    unsigned int j;
    j = 0; mem = stohx (DISBUF[digit]);
    while (1) {
        i = gkey2 ();
        if (i==2) {                              // adj key 
		    if (mem==0xf) mem = 0;
		    else mem++; 
			if (mem>max) mem = 0xf;
		} 
        else if (i==1) {                         // set key
            DISBUF[digit] = htosx (mem);
			mxload ();
            return (0);
        }
        else {                                   // flash on digit
            j++;
            if (j==FLASHV) {
                j = 0; f = ~f;
                if (f) DISBUF[digit] = htosx (mem);
                else DISBUF[digit] = 0;
				mxload ();
            }
        }
		if (TOUTF) return (1);
    }
}

bit getweek (void) {
    bit f;
    unsigned char i,mem;
    unsigned int j;
    j = 0; mem = stohx (DISBUF[3]);
    while (1) {
        i = gkey2 ();
        if (i==2) {mem++; if (mem>7) mem=1;}     // adj key
        else if (i==1) {                         // set key
            DISBUF[3] = htosx (mem);
			mxload ();
            return (0);
        }
        else {                                   // flash on digit
            j++;
            if (j==FLASHV) {
                j = 0; f = ~f;
                if (f) {
				    DISBUF[3] = htosx (mem);
					setweek (mem);
				}
                else {
				    DISBUF[3] = 0;
					setweek (0xff);              // clear week led
				}
				mxload ();
            }
        }
		if (TOUTF) return (1);
    }
}

void disline (void) {
    DISBUF[2] = 0x08;
	DISBUF[3] = 0x08;
    if (LINE==0) {           // tM__
        DISBUF[0] = 0x0f;
		DISBUF[1] = 0x76;
	}
	else if (LINE==1) {      // CL__
        DISBUF[0] = 0x4e;   
		DISBUF[1] = 0x0e;
	}
	else if (LINE<6) {       // AL_x 
        DISBUF[0] = 0x77;
		DISBUF[1] = 0x0e;
		DISBUF[3] = SEGTAB[LINE-1];
	}
	else {                   // Sd_x
        DISBUF[0] = 0x5b;
		DISBUF[1] = 0x3d;
		DISBUF[3] = SEGTAB[LINE-5];
	}
}

bit getline (void) {
    bit f;
    unsigned char i;
    unsigned int j;
    j = 0; 
    while (1) {
        i = gkey2 ();
        if (i==2) {LINE++; if (LINE>9) return (1);}   // adj key
        else if (i==1) {                              // set key
            disline ();
			mxload ();
            return (0);
        }
        else {                                        // flash on digit
            j++;
            if (j==FLASHV) {
                j = 0; f = ~f;
                if (f) disline ();
                else disclear ();
				mxload ();
            }
        }
		if (TOUTF) return (1);
    }
}

/********** SETUP **********/

void settimer (void) {                 // set timer
    unsigned char s;
    DISBUF[0] = SEGTAB[0];    
    DISBUF[1] = SEGTAB[0];    
    DISBUF[2] = SEGTAB[0];    
    DISBUF[3] = SEGTAB[0];    
    if (getdigit (0,5)) return;
	if (getdigit (1,9)) return;
	if (getdigit (2,5)) return;
	if (getdigit (3,9)) return;

    STRBUF[0] = stohx (DISBUF[0]) | 0x30;
    STRBUF[1] = stohx (DISBUF[1]) | 0x30;
    STRBUF[2] = 0;                              
    TIMERM = atol (STRBUF);                    
    STRBUF[0] = stohx (DISBUF[2]) | 0x30;
    STRBUF[1] = stohx (DISBUF[3]) | 0x30;
    STRBUF[2] = 0;                              
    TIMERS = atol (STRBUF);                    

	rtrd ();
	s = TIMBUF[0];
    while (1) {                        // start new second
	    dmsec (20);
        rtrd ();
        if (TIMBUF[0]!=s) return;
	}
}

void setclock (void) {                 // set clock
    ttos ();
	if (getdigit (0,2)) return;
	if (getdigit (1,9)) return;
	if (getdigit (2,5)) return;
	if (getdigit (3,9)) return;
	if (getdigit (4,3)) return;
	if (getdigit (5,9)) return;
	if (getdigit (6,1)) return;
	if (getdigit (7,9)) return;
	stot ();

	DISBUF[0] = 0x3e;                  // Wd_
	DISBUF[1] = 0x3d;
	DISBUF[2] = 0x08;
	DISBUF[3] = htosx (TIMBUF[3]);
	if (getweek ()) return;
    TIMBUF[3] = stohx (DISBUF[3]);

	DISBUF[0] = 0x3b;                  // Y_
	DISBUF[1] = 0x08;
	DISBUF[2] = htosx ((TIMBUF[6] & 0xf0) >> 4);
	DISBUF[3] = htosx (TIMBUF[6] & 0x0f);
	if (getdigit (2,9)) return;
	if (getdigit (3,9)) return;
    TIMBUF[6] = (stohx (DISBUF[2]) << 4) | stohx (DISBUF[3]);

	TIMBUF[0] = 0;                     // second = 0
	rtset ();
	rtwr ();
}

void setalarm (unsigned char x) {      // set alarm 1-4
    unsigned char y;
	y = (x - 1) * 2;
    HEXBUF[0] = ALARMD[y];
	HEXBUF[1] = ALARMD[y+1];
	htos ();
    DISBUF[4] = 0x77;                  // AL_
    DISBUF[5] = 0x0e;
	DISBUF[6] = 0x08;
	DISBUF[7] = htosx (x);
    if (getdigitx (0,2)) return;
	if (getdigitx (1,9)) return;
	if (getdigitx (2,5)) return;
	if (getdigitx (3,9)) return;
    stoh ();
	ALARMD[y] = HEXBUF[0];
    ALARMD[y+1] = HEXBUF[1];
	ALARMF = 1;
	rtwrram ();
}

void setspc (unsigned char x) {        // set special day 1-4
    unsigned char y;
	y = (x - 1) * 2;
    HEXBUF[0] = SPCDAY[y];
	HEXBUF[1] = SPCDAY[y+1];
	htos ();
    DISBUF[4] = 0x5b;                  // Sd_  
    DISBUF[5] = 0x3d;
	DISBUF[6] = 0x08;
	DISBUF[7] = htosx (x);
    if (getdigitx (0,3)) return;
	if (getdigitx (1,9)) return;
	if (getdigitx (2,1)) return;
	if (getdigitx (3,9)) return;
    stoh ();
	SPCDAY[y] = HEXBUF[0];
    SPCDAY[y+1] = HEXBUF[1];
	rtwrram ();
}

void setup (void) {                    // setup menu
    disclear ();
    LINE = 0;
	while (1) {
    	if (getline ()) return;
	    else {
            switch (LINE) {
                case 0: settimer (); return;
                case 1: setclock (); break;
	    		case 2: setalarm (1); break;
		    	case 3: setalarm (2); break;
			    case 4: setalarm (3); break;
    			case 5: setalarm (4); break;
                case 6: setspc (1); break;
                case 7: setspc (2); break;
                case 8: setspc (3); break;
                case 9: setspc (4); break;
	    	}
		}
	}
}

/********** MAIN **********/

void start (void) {                    // power up start
    dmsec (100);
    disclear ();
    mxload ();
	beepok ();
	rtrdram ();
	dmsec (400);
}

void stest (void) {                         // self-test (clear ram backup)
    unsigned char a,i,x;
    while (KADJ==0);                        // key release  
  
    for (i=0;i<=7;i++) SPCDAY[i] = 0xff;    // default data 
    for (i=0;i<=7;i++) ALARMD[i] = 0xff;
    ALARMF = 0;
	rtwrram ();

    a = 0x01;
    while (1) {
        LEDAL = ~LEDAL;
        for (i=0;i<=7;i++) DISBUF[i] = a;
        mxload ();
        while ((x = gkey2 ())==0);
        if (x==1) {         
            a >>= 1;
            if (a==0) a = 0x80; 
        }
        else { 
            a <<= 1;
            if (a==0) a = 0x01; 
        }
    }
}

void secyear (void) {                  // display second & year
    disclear ();
    while (KSET==0) {
        rtrd ();
		HEXBUF[1] = TIMBUF[0];
		HEXBUF[3] = TIMBUF[6];
		htos ();
		DISBUF[0] = 0;
		DISBUF[1] = 0;
		DISBUF[4] = 0x3b;              // y_
		DISBUF[5] = 0x08;
		setweek (TIMBUF[3]);
		mxload ();
		dmsec (100);
    }
}

void checktimer (void) {               // check timer running
    unsigned char a;
    if (TIMERM==0 && TIMERS==0 && TIMERF==0) return;
	else {
	    a = TIMERM;
        DISBUF[5] = htosx (a % 10); a = a / 10;
        DISBUF[4] = htosx (a % 10); 
        a = TIMERS;
        DISBUF[7] = htosx (a % 10); a = a / 10;
        DISBUF[6] = htosx (a % 10); 
        if (DISBUF[4]==SEGTAB[0]) DISBUF[4] = 0;

		if (TIMERM>0 || TIMERS>0) {                   // timer down
            if (TIMERS==0) {             
                TIMERM--;
                TIMERS = 59;
            }
	    	else TIMERS--;
            if (TIMERM==0 && TIMERS==0) {             // start alarm 
			    TIMERF = 1;
			    ALARMC = 10;  
			}
		} 
 	}
}

void checkalarm (void) {               // check alarm 1-4
    unsigned char x,y;
    if (ALARMF==1 && TIMBUF[0]==0) {   // alarm flag = on & check second=0 only
    	for (x=1;x<=4;x++) {
            y = (x - 1) * 2;
		    if (ALARMD[y]==TIMBUF[2] && ALARMD[y+1]==TIMBUF[1]) ALARMC = 30;
    	}
	}
}

void checkspc (void) {                 // check special day 1-4
    unsigned char x,y;
	for (x=1;x<=4;x++) {
        y = (x - 1) * 2;
		if (SPCDAY[y]==TIMBUF[4] && SPCDAY[y+1]==TIMBUF[5]) {
		    disclear4 ();
			setweek (TIMBUF[3]);
		}
	}
}

void main (void) {                     
	unsigned int d;
	unsigned char s,e,x;
	d = 0; 
	s = 0xff;
	start ();
    if (KADJ==0) stest ();
    while (1) {
	    if (d==0) {
		    d = 5;
            rtrd ();
			if (TIMBUF[0]!=s) {                            // every second
			    s = TIMBUF[0];
				IRFLAG = 0;
			    ttos ();
                if (DISBUF[0]==SEGTAB[0]) DISBUF[0] = 0;   // zero cut
                if (DISBUF[4]==SEGTAB[0]) DISBUF[4] = 0;
                if (ALARMC>0) {SOUNDB = 0; ALARMC--;}      // alarm beep
				checktimer ();
				if (ALARMC==0) TIMERF = 0;
				checkalarm ();
				e = 0;                      
                DISBUF[7] = DISBUF[7] | 0x80;              // colon
                setweek (TIMBUF[3]);
				if (ALARMF==1) LEDAL = 0; else LEDAL = 1;
				mxload ();
		    }
			e++;                            
			if (e>12) {                                    // clear colon
                DISBUF[7] = DISBUF[7] & 0x7f;
                SOUNDB = 1;
				if (TIMERM>0 || TIMERS>0 || ALARMC>0) {    // clear green display
				    disclear4 ();
					setweek (TIMBUF[3]);
				}
				checkspc ();
				mxload ();
			}
		}
		else d--;
		x = gkey2 ();
        if (x!=0 && ALARMC>0) ALARMC = 0;                  // reset alarm
        else if (x==2) {setup (); s = 0xff;}
		else if (x==1) {                                   // display second & year (on/off alarm)
		    if (TIMERM==0 && TIMERS==0) {                  // no timer mode 
				if (ALARMF==0) ALARMF = 1; else ALARMF = 0;
				if (ALARMF==1) LEDAL = 0; else LEDAL = 1;
				rtwrram ();
    		    secyear (); 
	    		s = 0xff;
			}
		}
    }
}


