/*****************************************************************

      SETCLOCK.C

      BL11xx/Little Giant, Tiny Giant, SmartBlock, BL13xx/Protocol Switch
         (with RTC)

    Sample C routine to setup the date and time on the
    EPSON 72421 battery backed clock 
    Press <F4> to make keyboard active (DOS only) and then use
    arrow keys to select field (<- ->) and (^ v ) modify value.
    
***************************************************************/

struct timer72421 
{
    char sec1, sec10, min1, min10, hour1, hour10;
    char day1, day10, mon1, mon10, year1, year10;
    char week;  /* week 0-6 for sunday to saturday */
} timer;

char *days[]={"sun ","mon ","tues","wed ","thur","fri ","sat ","??? "};

int read_timer(struct timer72421 *tim);
void init_timer();

/* Routine to set the Epson 72421 clock chip */

main()  
{
    int xpos,xposold,key,k;

    printf("1) Strike F4 to enable keyboard.(DOS only) \n2) Use arrows (<>) (^v) to set.\n");
    printf("3) Type Q to quit. \n4) Type R to reset (zero) the clock.\n");

    if(!IBIT(TREGF,2) || !IBIT(TREGF,4)) 
    {
        init_timer(); /* initialize timer if not running or not 24 hour*/
    }

    xposold=xpos=0; /* position of arrow */

   while (1)
   {

      read_timer(&timer);
      
      /* print timer contents */
      printf("\x1b= %c",4+' '); /* position cursor */
      printf("yy mm dd hh mm ss day  \n");
      printf("%1d%1d %1d%1d %1d%1d %1d%1d %1d%1d %1d%1d %s\n",
            timer.year10,timer.year1,
            timer.mon10, timer.mon1,
            timer.day10,timer.day1,
            timer.hour10,timer.hour1,timer.min10,timer.min1,
            timer.sec10,timer.sec1,days[timer.week]);

      goxy(xposold,6); printf(" "); /* erase cursor */
      xposold=xpos;
      goxy(xpos,6); printf("^");
    	hitwd();
      if(kbhit())               /* wait for key press */
      {
         key=getchar();
         if(key==0xcd) xpos++;
         if(key==0xcb) xpos--;
         if(xpos>21) xpos=0;
         if(xpos<0 ) xpos=0;
    
         k=0; 

         /* step if cursor moves */
         if(key==0xc8) k=1; 
         if(key==0xd0) k=-1;
        
         if(key=='Q' || key=='q') 
            exit(0);

         if(key=='R' || key=='r') 
         {
            init_timer (); 
            read_timer (&timer);
         }
         
         if(k)
         {
            switch(xpos) 
            {
               case 0:  timer.year10=abs(timer.year10+k) %10; break;
               case 1:  timer.year1= abs(timer.year1+k) %10; break;
               case 3:  timer.mon10= abs(timer.mon10+k) %10; break;
               case 4:  timer.mon1 = abs(timer.mon1 +k) %10; break;
               case 6:  timer.day10= abs(timer.day10+k) %4; break;
               case 7:  timer.day1=  abs(timer.day1+k)   %10; break;
               case 9:  timer.hour10=abs(timer.hour10+k) %6; break;
               case 10: timer.hour1=abs(timer.hour1+k) %10; break;
               case 12: timer.min10=abs(timer.min10+k) %6; break;
               case 13: timer.min1 =abs(timer.min1+k) %10; break;
               case 15: timer.sec10=abs(timer.sec10+k) %6; break;
               case 16: timer.sec1 =abs(timer.sec1+k) %10; break;

               case 18: 
               case 19: 
               case 20: timer.week=abs(timer.week+k) %7; break;
            }
            write_timer (&timer); /* set the timer */
         }
      }
   }
}

/* routine to position cursor */
int goxy(int x,int y)
{ 
    printf("\x1b=%c%c", x + 32, y + 32);
}

/* function to initialize timer */

/* an initial time and date, in order of registers, SEC1, SEC10, MIN1, ... */
char zero_time[]= {1,0,1,0,1,0,1,0,0,1,1,9,0}; /* an initial time and date */

void init_timer()    
{
    int k;
    int ioadr;

    outport(TREGF,7);               /* test=0, 12/24=1, stop=1, rest=1 */
    ioadr = SEC1;

    for (k = 0; k < sizeof (zero_time); k++) 
      outport (ioadr++, zero_time[k]);
    
    outport(TREGE,0);
    outport(TREGD,0);
    outport(TREGF,4);            /* restart 12 hour clock */
}

int read_timer (struct timer72421 *tim)  
{
    int ioadr,errcnt;
    char *ptr;

    errcnt=10; /* max trys */
    while (errcnt--)
    {
        outport (TREGD, 1);      /* set hold bit */
        if (!IBIT (TREGD,2))     /* if busy bit not set */
        {
            ioadr=SEC1;
            ptr=(char*)tim;
            while (ioadr != TREGD)     /* load time structure */
               *(char*)ptr++ = inport (ioadr++) & 0xf;

            outport(TREGD,0);             /* clear hold bit */
            tim->sec10=tim->sec10 & 7;
            tim->hour10=tim->hour10 & 3;  /* ignore am/pm bit */
            tim->day10=tim->day10 & 3;
            tim->mon10=tim->mon10 & 1;
            tim->week=tim->week & 7;
            return 0;                     /* good return */
        }
        else
        {
            outport(TREGD,0); /* busy on, clear hold, delay 200 us, try again */
            for(ioadr=0; ioadr<20; ioadr++) ; /* delay loop */
        }
    }

  return 1;       /* error return clock not responding */
}

int write_timer (struct timer72421 *tim)  
{
    int ioadr,errcnt;
    char *ptr;

    errcnt=10;                /* max trys */
    while(errcnt--)
    {
        outport(TREGD,1);     /* set hold bit */
        if(!IBIT(TREGD,2))    /* if busy bit not set */
        {
            ioadr=SEC1;
            ptr=(char*)tim;
            while(ioadr!=TREGD)
                outport(ioadr++,*ptr++);  /* set the timer */
    
            outport(TREGD,0);             /* clear hold bit */
            return 0;                     /* good return */
        }
        else
        {
            outport(TREGD,0); /* busy on, clear hold, delay 200 us, try again */
            for(ioadr=0; ioadr<20; ioadr++) ; /* delay loop */
        }
    }

    return 1; /* error return clock not responding */
}

/**********************************************End of SETCLOCK.C ****/
