/* This program reads the WWV clock and corrects the system clock based on the WWV clock. It will wake up once an hour in order to check the clock. If the clock has lost sync, it aborts. Planned improvement: if timesync has been lost, it will call the NIST or Nautical Observatory phone line to check the time. */ #include #include #include #include #include #include #include double juliandate(); /******************************************************************/ /* Setup the interupts, timezone, etc. */ /******************************************************************/ int setup() { int i; for (i=1; i<10; i++) cts10_flush(); cts10_write( (int) 0x1B); cts10_write( (int) 0x13); /* The null command - to force into command state */ cts10_flush(); cts10_write( (int) 0x1B); cts10_write( (int) 0x07); cts10_write( (int) 0x00); cts10_read(); /* Disable interupt requests */ for (i=1; i<100; i++) cts10_flush(); cts10_write( (int) 0x1B); cts10_write( (int) 0x05); cts10_write( (int) 0x00); cts10_read(); /* Set IRQ interval to zero */ for (i=1; i<100; i++) cts10_flush(); cts10_write( (int) 0x1B); cts10_write( (int) 0x09); cts10_write( (int) 0x00); cts10_read(); /* Disable messages on signal loss intervals */ for (i=1; i<100; i++) cts10_flush(); setzone(); } /********************************************************************/ /* Setzone sets the timezone and no DST */ /********************************************************************/ setzone() { int i; cts10_write( (int) 0x1B); cts10_write( (int) 0x11); cts10_write( (int) 0x01); cts10_read(); /* Set NO DST */ for (i=1; i<100; i++) cts10_flush(); cts10_write( (int) 0x1B); cts10_write( (int) 0x0B); cts10_write( (int) 0x01); cts10_read(); /* Twenty Four Hour Time */ for (i=1; i<100; i++) cts10_flush(); cts10_write( (int) 0x1B); cts10_write( (int) 0x0F); /* Set time zone to */ cts10_write( (int) 0X00); /* UTC */ for (i=1; i<100; i++) cts10_flush(); } /********************************************************************/ /* getcode reads in two bytes in BCD using the designated call code */ /* It interprets the resulting code as bcd and puts it in an int. */ /********************************************************************/ int bcdgetcode( code ) int code; { char c; int i,answer; for (i=1; i<100; i++) cts10_flush(); cts10_write( (int) 0x1B); /* The lead in */ cts10_write( code ); /* The actual command */ answer= 10 * (int) cts10_read(); /* Read in the appropriate code */ answer += (int) cts10_read(); return answer; } /******************************************************************/ /* The set_date command sets the computer date */ /******************************************************************/ int set_date() { struct tm tmWWV; double y,m,B,JD,M,tmp; char setstring[100],yn; cts10_write( (int) 0x1B); /* capture time in buffer on CTS10 */ cts10_write( (int) 0x01); cts10_read(); /* Read the system clock */ tmWWV.tm_sec = bcdgetcode( (int) 0x1E ); /* Set the second */ tmWWV.tm_min = bcdgetcode( (int) 0x1D ); tmWWV.tm_hour = bcdgetcode( (int) 0x1C ); tmWWV.tm_mday = bcdgetcode( (int) 0x1A ); tmWWV.tm_mon = bcdgetcode( (int) 0x19 ); tmWWV.tm_year = bcdgetcode( (int) 0x18 ); sprintf(setstring,"date -d1 %02d%02d%02d%02d%02d\n", tmWWV.tm_year, tmWWV.tm_mon, tmWWV.tm_mday, tmWWV.tm_hour, tmWWV.tm_min); /* printf( " %s %lf is the time from the WWV clock - OK to set?\n", setstring, juliandate(tmWWV.tm_year, tmWWV.tm_mon, tmWWV.tm_mday)); scanf("%c",&yn); if ( yn = 'y' ) */ system(setstring); return 0; } /********************************************************/ /* This reads the cmos clock and sets the board year. */ /********************************************************/ year_from_cmos() { struct tm *cmostime; time_t *rawtime; time(&rawtime); cmostime = (struct tm*) gmtime(&rawtime); cts10_write( (int) 0x1B); cts10_write( (int) 0x17); cts10_write( (int) cmostime->tm_year / 10); cts10_write( (int) (cmostime->tm_year % 10)); } /******************************************************************/ /* This samples the system clock, the WWV clock, and updates. */ /******************************************************************/ int set_time(arg) int arg; { struct tm tmWWV; struct timeval timeSys,timeClock; struct timezone zoneSys; int hundreths; double secClock, secSys, secError; pid_t pidOld; pidOld = getprio(getpid()); setprio( getpid(), 29); /* Lock out other processes for a sec */ cts10_write( (int) 0x1B); /* capture time in buffer on CTS10 */ cts10_write( (int) 0x01); cts10_read(); /* Read the system clock */ gettimeofday(&timeSys, &zoneSys); /* Get system time */ secSys = timeSys.tv_sec + timeSys.tv_usec / 1000000.0; setprio( getpid(), pidOld); /* Ok, back down in priority */ hundreths = bcdgetcode( (int) 0x1F ); tmWWV.tm_sec = bcdgetcode( (int) 0x1E ); /* Set the second */ tmWWV.tm_min = bcdgetcode( (int) 0x1D ); tmWWV.tm_hour = bcdgetcode( (int) 0x1C ); tmWWV.tm_mday = bcdgetcode( (int) 0x1A ); tmWWV.tm_mon = bcdgetcode( (int) 0x19 ); tmWWV.tm_year = bcdgetcode( (int) 0x18 ); if (hundreths > 97) return(1); /* To close to a second - the clock board is apt to give us an incorrect time */ secClock = 3600.0 * (double) tmWWV.tm_hour + 60.0 * (double) tmWWV.tm_min + (double) tmWWV.tm_sec + 0.01 * (double) hundreths + 24 * 3600 * (juliandate(tmWWV.tm_year, tmWWV.tm_mon, tmWWV.tm_mday) - juliandate( 70, 1, 1)); secError = secSys - secClock; if ( (( secError > 6.0) || (secError < -6.0 )) && (arg==1) ) { printf("The clock has run amok! Reset it!\n"); exit(1); } if ( ( secError > 0.005 ) || ( secError < -0.005) ) { setprio( getpid(), 29); /* Lock out other processes for a sec */ gettimeofday(&timeSys, &zoneSys); /* Get system time */ secSys = (double) timeSys.tv_sec + (double ) timeSys.tv_usec / 1000000.0; timeSys.tv_usec -= 1000000.0 * ((double) secError - floor( (double) secError )); while ( timeSys.tv_usec < 0 ) { timeSys.tv_usec += 1000000.0; timeSys.tv_sec -= 1.0; } while ( timeSys.tv_usec > 1000000.0 ) { timeSys.tv_usec -= 1000000.0; timeSys.tv_sec += 1.0; } timeSys.tv_sec -= floor( secError ); settimeofday(&timeSys, &zoneSys); setprio( getpid(), pidOld); /* Let 'em back. */ } return(0); } int showtime() { int i; char c; int doneflag=0; for (i=1; i<10; i++) cts10_flush(); cts10_write( (int) 0x1B); cts10_write( (int) 0x13); /* The null command - to force into command state */ cts10_flush(); cts10_write( (int) 0x1B); /* Capture buffer read */ cts10_write( (int) 0x01); cts10_read(); printf(">>"); for (i=1; i<30; i++) cts10_flush(); cts10_write((int) 0x1B); /* escape character lead in to command */ cts10_write((int) 0x02); /* Ask for formatted time and date */ while ( NULL != (c = cts10_read() ) ) { if ( c == '/' ) doneflag=1; printf("%c",c); } printf("<<\n "); fflush(stdout); return(doneflag); } main() { int i,j; char c,str[100]; /* setup(); Set the card as we'ld like it. */ system("date -u\n"); printf("\n Is this time correct within an minute (y/n)?"); if ('n' == getc(stdin)) { printf("Please set the system clock using the command\n"); printf("date -u yymmddhhmm.ss\n"); printf("and run clock again.\n"); exit(1); }; getc(stdin); /* Catch the CR */ year_from_cmos(); /* Grab year from cmos clock, set board */ /* set_date(); */ start: /* printf("We will now read the clock from WWV a few times - please\n"); printf("check the time to see that it is accurate to a couple of secs! \n"); for (j=0;j<10;j++) { showtime(); sleep(1); } printf("Was that time accurate enough (y/n)?"); if ('y' != getc(stdin)) { getc(stdin); choose: printf("CHOOSE an option: \n"); printf("a: Try to sync the CTS-10 to WWV; the most exact option\n"); printf("b: Synchronize from the PSTI clock (in the rack)\n"); printf("Choose a/b>>"); c = getc(stdin); getc(stdin); if (c == 'a') { printf("OK, we will now try to re-set the clock from WWV\n"); cts10_write((int) 0x1B); cts10_write((int) 0x20); setup(); printf("The card is now reading WWV. It will exit when\n"); printf("it has synchronized. ^C to give up. \n"); while ( 1 != showtime()) { setzone(); sleep(1); } goto start; } else if (c == 'b') { printf("Be sure that serial port /dev/amp2 is plugged into the clock!\n"); printf("Hit y to continue."); if ( 'y' != (c = getc(stdin))) exit(1); getc(stdin); */ printf("\n Synchronizing system clock from PSTI (rack) Clock\n"); printf(" The task number is "); fflush(stdout); system("ptsisync &"); printf("\n\n"); logf( "clock" ); exit(1); /* } else goto choose; goto start; } printf("\n Starting ctssync in background to synchronize system clock \n"); printf("\n The job number is "); fflush(stdout); system("ctssync &"); printf("\n\n"); */ /* set_time(0); sleep(5); set_time(0); while(1) { sleep(5); set_time(1); fflush(stdout); } */ exit(0); }