;;; Copyright (c) 1999 Massachusetts Institute of Technology ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License as ;;; published by the Free Software Foundation; either version 3 of the ;;; License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;;; General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ;I T S .OPERS RELEVANT TO REAL TIME ;.PDTIME AC, ;RETURNS PDUPS*<# SECS SINCE BEGINNING OF YEAR> APDTIM: PUSHJ P,GPDTIM JRST RETM1 ;-1 IF NOT KNOWN JRST APTUAJ ;.RDATE AC, ;RETURNS SIXBIT YYMMDD IN AC ARDATE: PUSHJ P,GLPDTM ;GET LOCALIZED PDTIME JRST RETM1 ;NOT AVAILABLE IDIVI A,SPD ;GET # DAYS SINCE BEGINNING OF YEAR PUSHJ P,RDATE ;GET THE ANSWER JRST APTUAJ ;RETURN IT ;.RTIME AC, ;RETURNS SIXBIT HHMMSS (24 HOUR TIME) IN AC ARTIME: PUSHJ P,GLPDTM ;GET LOCALIZED PDTIME JRST RETM1 ;NOT AVAILABLE IDIVI A,SPD ;GET # SECS SINCE MIDNIGHT IN B PUSHJ P,RTIME ;CONVERT TO SIXBIT HHMMSS JRST APTUAJ ;RETURN IT ;.RDATIM AC, ;DOES .RTIME TO AC, .RDATE TO AC+1 ARDATI: PUSHJ P,GLPDTM ;GET CRUD JRST RETM1 ;NO LUCK (THIS IS GETTING BORING) IDIVI A,SPD ;CONVERT TO DAYS AND SECONDS HRLM A,(P) ;SAVE DAYS ON PDL PUSHJ P,RTIME ;GET TIME (HHMMSS) UMOVEM A,(J) ;GIVE TO USER HLRZ A,(P) ;GET DAYS AGAIN PUSHJ P,RDATE ;CONVERT TO SIXBIT AOJA J,APTUAJ ;GIVE TO USER AND RETURN ;.RYEAR AC, ;PUSHJ'S TO RYEAR AND MOVEM'S E TO AC ARYEAR: PUSHJ P,RYEAR ;GET THE CRUFT UMOVEM E,(J) ;STORE YEAR AND CRUD POPJ P, ;.RLPDT AC, ;DOES .RYEAR AC+1, AND ALSO MOVEM'S A TO AC ARLPDT: PUSHJ P,RYEAR ;GET THE CRUFT UMOVEM E,1(J) ;STORE YEAR AND CRUD JRST APTUAJ ;STORE TIME AND RETURN ;ROUTINE TO RETURN -1 ON AN OPER RETM1: XCTR XRW,[SETOM (J)] POPJ P, ;GET THE CORRECTED PDUPS*<# SECS SINCE BEGINNING OF YEAR> IN A ;SKIP IF OFFSET AVAILABLE AND CLOCK ON GPDTIM: IFN PDCLKP,[ SKIPN A,PDTIME ;GET THE OFFSET JRST GPDTM2 ;NOT AVAILABLE DATAI PDCLK,B ;GET WHAT THE CLOCK IS SAYING TLZ B,600000 JUMPE B,GPDTM2 ;POWER PROBABLY (BUT NOT NECESSARILY) TURNED OFF SUBM B,A ;DO THE CORRECTION JUMPL A,CPOPJ ;LOST, DON'T RETURN A NEGATIVE NUMBER! JRST POPJ1 ;EXIT SKIPPING (SUCCESS) ] ;PDCLKP IFN KS10P,[ SKIPN PDTIME ; Offset available? JRST GPDTM2 ; No: Try backup RDTIM A ; Read clock into A!B TLC A,1729. ; "A most interesting number" TLNE A,-1 ; Does the clock look like it has been set? JRST GPDTM2 ; Must have been reset DIVI A,KSFREQ ; Convert to 60ths SUB A,PDTIME ; Subtract offset JUMPL A,CPOPJ ; Wooops, don't return a negative number! (Why ; don't we use the backup in this case?) JRST POPJ1 ] ;KS10P GPDTM2: SKIPGE A,PDYTIM ;CLOCK NOT ON, TRY BACKUP POPJ P, ;SORRY, NOT AVAILABLE IMULI A,30. ;CONVERT TO SIXTIETHS OF A SECOND JRST POPJ1 ;CALL IT CORRECT AND AVAILABLE ;GET SIXBIT YYMMDD (DATE) IN A (LOCALIZED PDTIME/SPD IN A, YEAR IN RH(E)) RDATE: PUSHJ P,RDATE1 ;GET DAY IN C, MONTH IN B MOVE T,[1400,,A];SET UP BYTE POINTER FOR OUTPUT PUSHJ P,RDATM1 ;DEPOSIT DAY MOVE C,B ;GET MONTH PUSHJ P,RDATM1 ;DEPOSIT MONTH MOVEI B,(E) ;GET YEAR IDIVI B,100. ;GET LAST TWO DIGITS IN C ARTIMX: PUSHJ P,RDATM1 ;DEPOSIT YEAR (ENTRY FROM RTIME TO DEPOSIT HOUR) IOR A,[SIXBIT /000000/] ;CONVERT TO REAL SIXBIT POPJ P, ;GET MONTH (1 => JAN) IN B, DAY (1 => THE FIRST) IN C RDATE1: AOS C,A ;GET DAY OF YEAR (LOCALIZED) (1 => THE FIRST) MOVEI B,12. ;INITIALLY ASSUME DECEMBER FOR MONTH CAMG C,LMNTBL-1(B) ;IF DAY IN YEAR .LE. DAY IN YEAR AT BEGINNING OF THIS MONTH, SOJA B,.-1 ;THEN DECREMENT TO PREVIOUS MONTH AND TRY AGAIN SUB C,LMNTBL-1(B) ;C(C) := DAY OF MONTH POPJ P, LMNTBL: MNIRP [] ;TABLE OF DAYS GONE BY AT BEGINNING OF MONTH ;GET THE SIXBIT TIME IN A (# SECS SINCE MIDNIGHT IN B) RTIME: MOVE T,[1400,,A];SET UP BYTE POINTER FOR OUTPUT IDIVI B,60. ;GET SECONDS IN C PUSHJ P,RDATM1 ;DEPOSIT INTO A IDIVI B,60. ;GET HOURS IN B, MINUTES IN C PUSHJ P,RDATM1 ;DEPOSIT MINUTES MOVE C,B ;GET HOURS IN C JRST ARTIMX ;DEPOSIT HOURS, CONVERT TO SIXBIT, AND RETURN ;DEPOSIT C(C) AS TWO SIX BIT (AS OPPOSED TO SIXBIT) DECIMAL DIGITS ; VIA T (INTO A) THEN DECREMENT T RDATM1: IDIVI C,10. ;SEPARATE DIGITS DPB C,[60600,,D] ;DEPOSIT FIRST DIGIT TO GIVE 12 BITS DPB D,T ;OUTPUT BYTE ADD T,[140000,,] ;DECREMENT BYTE POINTER POPJ P, ;THAT'S ALL ;DO A PUSHJ P,GLPDTM THEN HACK AROUND ;DO THOSE THINGS TO E COMMENTED IN GLPDTM AS BEING DONE BY RYEAR ;TRY TO GET YEAR EVEN IF GLPDTM DOESN'T SKIP, BUT IN THAT CASE CLOBBER A TO -1 RYEAR: PUSHJ P,GLPDTM ;GET THE CRUFT JRST RYEAR2 ;DIDN'T SKIP, SEE WHAT CAN BE SALVAGED RYEAR1: PUSH P,A ;PROTECT A FROM FUTURE CLOBBERAGE IDIVI A,SPD ;GET LOCALIZED # DAYS SINCE BEGINNING OF YEAR JUMPL E,[SOJA A,.+1] ;DE-LOCALIZE LDB B,[270300,,E] ;DAY OF WEEK OF BEGINNING OF YEAR ADD A,B ;ADD IN IDIVI A,7 ;GET TODAY'S DAY OF WEEK (0 => SUNDAY) IN B DPB B,[320300,,E] ;DEPOSIT IN E TLO E,40000 ;DOCUMENT FACT THAT TIME OF YEAR KNOWN JRST POPAJ ;RESTORE A AND RETURN RYEAR2: PUSHJ P,GDWOBY ;GLPDTM DIDN'T SKIP, TRY TO SALVAGE CRUFT: FIRST DOWOBY MOVNI A,1 ;DOCUMENT FACT THAT TIME OF YEAR NOT KNOWN JUMPE E,CPOPJ ;RETURN IF YEAR NOT KNOWN EITHER DPB B,[270300,,E] ;DAY OF WEEK OF BEGINNING OF YEAR JRST CMPF29 ;SEE IF LEAP YEAR, AND RETURN ;NOTE: THE SYMS JAN, FEB, MAR, ETC. ARE DEFINED AFTER (AND BY) MNIRP (A MACRO) ;INCREMENT YEAR NUPDT: TLNN E,200000 ;SEE IF LEAP YEAR SKIPA A,[<365.*SPD*PDUPS>] ;NORMAL YEAR MOVE A,[<366.*SPD*PDUPS>] ;LEAP YEAR ADDM A,PDTIME ;UPDATE PDCLK OFFSET IDIVI A,30. ;CONVERT TO HALF-SECONDS EXCH A,PDYTIM ;ALSO UPDATE BACKUP SYSTEM SUBM A,PDYTIM AOS FYEAR ;INCREMENT YEAR ;INSERT OTHER CRUFT HERE IF DESIRED ;DROPS THROUGH ;CODING DROPS THROUGH FROM PREVIOUS PAGE ;GET "LOCALIZED" NUMBER OF SECONDS SINCE BEGINNING OF YEAR IN A ;IF DIVIDED BY # SECONDS IN A DAY, ;GIVES REMAINDER OF # SECONDS SINCE MIDNIGHT LOCAL TIME ;QUOTIENT WHEN FED TO DATE GENERATOR ROUTINE ASSUMING LEAP YEAR GIVES CORRECT DATE ;ALSO GET YEAR AND FLAGS (AS RETURNED BY .RYEAR) IN E ;1.1-2.9 => YEAR (E.G. 1969.) ;3.1-3.5 ZERO ;3.6-3.8 => DAY OF WEEK OF BEGINNING OF YEAR (0 => SUNDAY) ;3.9-4.2 ZERO (RYEAR SETS THIS BYTE TO TODAY'S DAY OF WEEK IF TIME OF YEAR KNOWN) ;4.6 ZERO (RYEAR SETS IT TO 1 IF TIME OF YEAR KNOWN) ;4.7 ONE => DAYLIGHT SAVINGS TIME IN EFFECT ;4.8 ONE => LEAP YEAR ;4.9 ONE => 365 DAY YEAR AND AFTER FEB 28 ;SKIPS IF PDCLK ON AND BOTH PDTIME AND FYEAR NON-ZERO (IN OTHER WORDS IF SUCCESSFUL) ;PREVIOUS CODING DROPS THROUGH ON YEAR INCREMENT GLPDTM: CONO PI,CLKOFF ;AVOID DOUBLE YEAR INCREMENT SKIPE E,FYEAR ;GET YEAR IN E, SKIP IF NOT AVAILABLE PUSHJ P,GPDTIM ;GET PDTIME, SHOULD SKIP JRST CLKONJ ;SOMETHING NOT AVAILABLE, DON'T SKIP IDIVI A,60. ;CONVERT TO SECONDS PUSHJ P,CMPF29 ;MAYBE SET BIT 4.8 OR 4.9 OF E, IF 4.9 SET THEN ADD SPD TO A CAML A,[366.*SPD] ;IF MORE THAN A YEAR HAS GONE, JRST NUPDT ;THEN INCREMENT YEAR CONO PI,CLKON ;TIMIMG ERROR PROBLEM GONE PUSH P,A ;SAVE # SECONDS DURING NEXT CALL PUSHJ P,GDWOBY ;GET DAY OF WEEK OF BEGINNING OF YEAR (0 => SUNDAY) DPB B,[270300,,E] ;DEPOSIT IN RIGHT PLACE POP P,A ;RESTORE A AOS (P) ;CAUSE RETURN TO SKIP ;IF DAYLIGHT SAVINGS TIME THEN ADD 3600. TO A AND SET BIT 4.7 IN E GLPDT2: JFCL ;POPJ FOR STD TIME ;JRST CRDDST FOR DAY LIGHT TIME ;JFCL "NORMAL" CAML A,[*SPD+7200.] ;IF BEFORE 2AM APR 1, CAML A,[*SPD+3600.] ;OR IF AFTER 1AM STANDARD TIME OCT 31, POPJ P, ;THEN OBVIOUSLY STANDARD TIME IS IN EFFECT CAML A,[*SPD+7200.] ;IF BEFORE 2AM APR 7 STANDARD TIME, CAML A,[*SPD+3600.] ;OR IF AFTER 1AM STANDARD TIME OCTOBER 25, JRST GLPDT3 ;THEN NOT OBVIOUS CRDDST: TLO E,100000 ;DAYLIGHT SAVINGS TIME, SET BIT IN E ADDI A,3600. ;CONTINUE TO LOCALIZE THE TIME THAT WILL BE RETURNED POPJ P, ;IT IS NOW SOMETIME DURING THE WEEKS IN APR AND OCTOBER ;WHEN IT MAY BE EITHER STANDARD OR DAYLIGHT SAVINGS TIME GLPDT3: PUSH P,A ;SAVE # SECS CAMG A,[JUL*SPD] ;IF NOT YET JULY, TDZA D,D ;THEN IT MUST BE APR, SET INDEX MOVEI D,1 ;OCTOBER, SET INDEX SUB A,CRDSB(D) ;COMPENSATE FOR 2AM OR 1AM IDIVI A,SPD ;FLUSH SECONDS, LEAVE ONLY DAYS (IT LOOKS LIKE A LEAP YEAR, REMEMBER) LDB C,[270300,,E] ;GET DAY OF WEEK OF BEGINNING OF YEAR IN C JUMPGE E,.+3 ;IF REGULAR YEAR, SOJGE C,.+2 ;THEN DE-LOCALIZE SO IT WILL RE-LOCALIZE LATER... MOVEI C,6 ;MOD 7 ADD A,C ;ADD TO NUMBER OF DAYS IDIVI A,7 IMULI A,7 SUB A,C ;C(A) := NUMBER OF DAYS IN YEAR BEFORE LAST SUNDAY (MAYBE TODAY) ;IF LAST SUNDAY (AS DEFINED ABOVE) IS BELOW THE "REGION OF AMBIGUITY", ;THEN IT HAS NOT YET CHANGED TO THE LATER TIME XCT CRDTST(D) ;SKIP IF DAYLIGHT SAVINGS TIME JRST POPAJ ;STANDARD TIME, NO CHANGES NECESSARY POP P,A ;DAYLIGHT SAVINGS TIME, RESTORE A JRST CRDDST ;MUNG A AND E AND RETURN CRDSB: 7200. ;IN APR CHANGES AT 2AM EST 3600. ;IN OCTOBER CHANGES AT 1AM EST CRDTST: CAIGE A, CAIL A, ;IF LEAP YEAR THEN SET BIT 4.8 OF E ;IF NOT LEAP YEAR THEN IF AFTER FEB 28 THEN SET BIT 4.9 OF E AND ADD SPD TO A CMPF29: TRNN E,3 ;IF LEAP YEAR, (HOPEFULLY THIS ONLY PLACE WHERE DIRECTLY CHECKED FOR LEAP YEAR) TLOA E,200000 ;THEN SET BIT 4.8 OF E AND RETURN CAMGE A,[<-1>*SPD] ;365 DAY YEAR, IF BEFORE MARCH FIRST, POPJ P, ;THEN RETURN TLO E,400000 ;365 DAY YEAR AFTER FEB 28, SET BIT 4.9 OF E ADDI A,SPD ;INCREMENT A ONE DAY POPJ P, ;GET DAY OF WEEK OF BEGINNING OF YEAR (IN E) (0 => SUNDAY) IN B ;FOLLOWING ROUTINE HAS BEEN EXHAUSTIVELY CHECKED GDWOBY: MOVEI A,-1(E) IDIVI A,400. MOVEI A,1(B) IDIVI B,4 ADD A,B IDIVI B,25. SUB A,B IDIVI A,7 POPJ P, ;SLOW CLOCK ROUTINE TO CHECK ON REAL-TIME CLOCK SYSTEM PDCCHK: SKIPL PDYTIM ;IF BACKUP TIME (SINCE BEGINNING OF YEAR) CALCULATED, AOS PDYTIM ;THEN UPDATE IT SKIPGE TIMOFF ;IF TIMOFF NOT CALCULATED, POPJ P, ;THEN RETURN AOS A,TIMOFF ;UPDATE TIMOFF CAMGE A,[2*SPD] ;Incremented beyond length of day? JRST PDCCH1 SETZB A,TIMOFF ;Yes - reset it. MOVEM A,RSWTIM ;Also reset last-resource-warning timestamp. PDCCH1: TRNE A,64.*2-1 ;Is this a 64. second (based on TIMOFF) clock break? POPJ P, ; No, so return. INITIM: IFN PDCLKP,[ SKIPN A,PDTIME ;MAYBE UPDATE BACKUP SYSTEM JRST INITM2 ;PDTIME NOT AVAILABLE, DON'T DATAI PDCLK,B TLZ B,600000 JUMPE B,INITM2 ;JUMP IF CLOCK OFF SUBM B,A JUMPL A,CPOPJ IDIVI A,30. ;CONVERT TO HALF-SECONDS SINCE BEGINNING OF YEAR MOVEM A,PDYTIM ;STORE RE-CALCULATED BACKUP TIME ] ;PDCLKP IFN KS10P,[ SKIPN PDTIME ; Update backup system? JRST INITM2 ; Not without offset RDTIM A TLC A,1729. TLNE A,-1 JRST INITM2 ; Not if clock reset DIVI A,KSFREQ SUB A,PDTIME ; 60ths since Jan 1 JUMPL A,CPOPJ IDIVI A,30. ; halfs since Jan 1 MOVEM A,PDYTIM ; Store backup ] ;KS10P INITM2: PUSHJ P,GLPDTM ;GET LOCALIZED PDTIME POPJ P, ;SOMETHING'S MISSING IDIVI A,SPD ;SEPARATE INTO DAYS AND SECONDS LSH B,1 ;CONVERT TIME SINCE MIDNIGHT TO HALF-SECONDS MOVEM B,TIMOFF ;STORE RE-CALCULATED NUMBER OF HALF-SECONDS SINCE MIDNIGHT PUSHJ P,CLCQDT ;GET QDATE,,TIMOFF IN A CONO PI,UTCOFF ;INHIBIT INTERRUPTS DURING THIS RITUAL SKIPGE A,QMDRO ;GET ORIGIN OF MASTER DSK DIRECTORY JRST UTCONJ ;DIRECTORY LOCKED MOVE B,QACTB ;DIRECTORY CHANGED BIT FOR DSK DIRECTORY SKIPE T,PDTIME ;GET OFFSET FOR DECORIOLIS CLOCK CAMN T,MPDOFF(A) ;SEE IF IT MATCHES RELEVANT WORD IN DSKDIR JRST .+3 ;MATCHES OR PDTIME NOT AVAILABLE MOVEM T,MPDOFF(A) ;NO MATCH, CORRECT THE DSKDIR ONE IORM B,QMDRO ;SET DIRECTORY CHANGED BIT SKIPE T,FYEAR ;NOW DO THE SAME FOR THE YEAR, CAMN T,MDYEAR(A) ;AND THE RELEVANT WORD IN DSKDIR JRST .+3 MOVEM T,MDYEAR(A) IORM B,QMDRO JRST UTCONJ ;THAT'S ALL CLCQDT: PUSHJ P,RDATE1 ;GET DAY OF MONTH IN C, MONTH IN B SETZM QDATE ;INITIALIZE FOR FOLLOWING PUSH P,E-1 PUSH P,E MOVE E-1,FYEAR IDIVI E-1,100. DPB E,[330700,,QDATE] ;YEAR POP P,E POP P,E-1 DPB B,[270400,,QDATE] ;MONTH DPB C,[220500,,QDATE] ;DAY MOVE C,QDATE ;THE FIRST TIME QDATE IS SET UP, HRR C,TIMOFF ;SET UP QDATEI = TIME SYSTEM CAME UP. SKIPGE QDATEI MOVEM C,QDATEI ;MECHANISM IS, SET QDATEI UNLESS ALREADY SET. POPJ P,