/*
   Night Lamp Saver V5.0
   89C2051(ext.oscillator 680kHz) + MAC97A6 + no battery backup
   demonstration of using Micro-C and ATMEL89C2051 to build a device
   used for controlling night lamp that turn on and off night lamp
   with preset time on/off.
   After reset or power failure occured, high blink rate of led will show,
   user should press P3.0 to reset time to 18:00, low blink rate will show
   indicating normal operation.

   The Saver V4.0 using Xtal 11.0592MHz produces EMI that interfere TV reception
   This version the Xtal oscillator has changed to RC oscillator 680kHz.
   cputick incremental was derived from 50Hz or 20ms main frequency.

   Copyright (c) 1999 W.SIRICHOTE
*/

#include c:\mc51\8051io.h
#include c:\mc51\8051reg.h

/*-------- turn lamp on/off after reset time to 18:00 ---------*/

#define onHour1  18   /* 18:00 turn lamp on */
#define onMin1   00
#define offHour1 18   /* 18:01 turn off */
#define offMin1  01

/* every day turn on at 19:00 and and off at 22:00 */

#define onHour2  19
#define onMin2   00
#define offHour2 22
#define offMin2  00

/* set clock to 18:00 when press P3.0 */

#define setHour  18
#define setMin   00
 
/*-------------------------------------------------------------*/

extern register char cputick;
unsigned register char sec25,sec50,sec,sec5,min,hour,flag1,temp,led,blink_rate;
/* above must be defined as register for tiny model */

/* variables description
cputick increments by one every 20ms
sec25   half second counter
sec50   2*25Hz counter
sec     current second
sec5    5 second counter
min     current min
hour    current hour
temp    temp register
led     counter for led on duration (times cputick)
blink_rate 0 = high blink rate, 10 low blink rate

flag1   intertask signaling                     mask byte

flag1.0 set every 1 second                         0x01
flag1.1 set every 1 min                            0x02
flag1.2 not use                                    0x04
flag1.3 set every 0.5 second                       0x08
flag1.4 set after P3.2 has been pressed            0x10
flag1.5 disable turn on/off 18:00-18:01 if set     0x20
flag1.6-7 not use
*/

main()
{
  cputick = 0;
  hour = 18;
  min = 0;
  sec = 0;
  sec25 = 0;
  sec50 = 0;
  flag1 = 0;
  blink_rate = 0;    /* indicate reset time to 18:00 is needed */

  asm "LAMP EQU $97"; /* P1.7 */
  asm{
         SETB $AF  /* setb EA */
         SETB $A8  /* enable external interrupt */
         SETB $88  /* negative edge triggering */
     }
  while(1)
  {
     while ( cputick < 1); 
        cputick = 0;     /* 20ms has elapsed */

/*------------- the following tasks execute every 10ms ------*/

        time();
        comparetime();
        cpubeat();
        settime();
  /*      waithigh();    */
   }

/*-----------------------------------------------------------*/
}

time ()
/* update real-time clock, date */
{
    sec25++;
    if (sec25 >= 25) /* now 25 times means half second */
    {sec25 = 0;
      flag1 |= 0x08; /* set bit 3 every 0.5 s */
   sec50++;
   if (sec50 >= 2)   /* 2 * 25 * 20 ms = 1 s */
   {sec50 = 0;
    flag1 |= 0x01;   /* set bit 0 */
    sec++;
    if (sec >= 60)
    {sec = 0;
     flag1 |= 0x02; /* set bit 1 */
     min++;
     if (min >= 60)
     {min = 0;
     hour++;
     if (hour >= 24)
     {hour = 0;
    }

    }
  }
 }
}
}

comparetime()
{
    if ((flag1 & 0x10) != 0) /* enabled only after P3.2 has been pressed */
    {
        compareTimeOn_Off();
    }
}

compareTimeOn_Off()
{
   if ((flag1 & 0x01)!=0)
   {
    testOnOff();
    if(hour == onHour2 && min == onMin2)
            asm" CLR LAMP";
    if(hour == offHour2 && min == offMin2)
            asm" SETB LAMP";
    }
}

testOnOff()
{
    if ((flag1 & 0x20) == 0)
    {
        if(hour == onHour1 && min == onMin1)
            asm" CLR LAMP";
        if(hour == offHour1 && min == offMin1)
            {
             asm" SETB LAMP";
             flag1 |= 0x20; /* disable further test on off */
            }
    }
}

   

cpubeat()
{
    beat5sec();
    livecpu();

}

beat5sec()  /* clear P3.7 every blink rate */

{
    if ((flag1 & 0x08)!=0)
        {
         flag1 &= ~0x08;    /* clear bit 3 of flag1 */
         sec5++;
        if (sec5 > blink_rate)
          {sec5 = 0;
            flag1 |= 0x40; /* set bit 6 of flag1 to signal livecpu task */
           asm " clr P3.7"; /* make led on */
           led = 2;        /* load time on duration times cputick  */
          }
        }

}

livecpu()

{
    if ((flag1 & 0x40) != 0)
      {
        led--;
        if (led == 0)
           {
           asm " setb P3.7";
           flag1 &= ~0x40;
           }
    }
}

settime()
{
    if ((P3 & 0x01) == 0) /* reset time to 18:00 if P3.1 low */
    {
        hour = setHour;
        min = setMin;
        sec = 0;
        sec50 = 0;
        flag1 |= 0x10; /* enable compare time on/off */
        flag1 &= ~0x20; /* reenable testOnOff after pressing set clock to 18:00 */
        blink_rate = 10;
    }
}

/*
waithigh()
{
        asm" jnb P3.2,*";
        pause(2);
        asm" jnb P3.2,*";
        pause(2);
}

pause(j)
int j;
{
    int i;
    for (i=0;i<j;i++)
    ;
}
*/
