c c c FORTRAN entry for clock service c routine -- Magellan telescope control. c -------------------------------------- c subroutine clock2 c implicit none c real*8 utime, jtime, tzero, tstep, tzset, tsset integer*4 mjday, clkct, savct integer*4 i, ictr, peek integer*4 timer1, timer2, timer3, timer4 logical*4 here, setfl c common / clkcom / utime, jtime, mjday common / clkvar / tzset, tsset, setfl, savct c common / timcom / timer1, timer2, timer3, timer4 c data ictr / 1 /, here / .false. / data tzero / 0.d0 /, tstep / 0.d0 /, clkct / 0 / c c c Check for re-entrance and set semaphore. c c Actually, the stack for the clock routine is c static storage. It has the old stack pointer, c the coprocessor state, and the return to the c assembly-language clock routine stored on it. c So, if you get this far, the coprocessor state c and the old stack pointer will probably be c corrupted. It would be better to check for c re-entrance in the assembly-language routine. c ---------------------------------------------- c if (here) then return endif here = .true. c c c If the set flag is true, set the clock. Then, c update the time. UTIME is the universal time in c units of 1 day. JTIME is time expressed as the c modified julian date. MJDAY is the modified c julian day number. c c If you need the modified julian date, use JTIME. c It is not safe to add UTIME + MJDAY in the c foreground, because there is a tiny chance that c the interrupt could occur and change the values c at just the wrong instant. c c NOTE: On program startup, mjday is set by the c the foreground. Then tzset is fed to the c background. Since tzero, tstep and clkct are c all initialized to zero, there is NO WAY that c mjday can roll over during the interrupt or two c that might occur before the set flag is set and c processed. c ------------------------------------------------ c if (setfl) then setfl = .false. tzero = utime + tzset if (tzero .lt. 0.d0) then mjday = mjday - 1 tzero = tzero + 1.d0 endif tstep = tsset savct = clkct clkct = 0 endif c clkct = clkct + 1 utime = tzero + (clkct * tstep) if (utime .ge. 1.d0) then mjday = mjday + 1 utime = utime - 1.d0 tzero = tzero - 1.d0 savct = clkct clkct = 0 endif jtime = utime + mjday c c c Update timers for main program. c The allocation of timers is CRITICAL: c timer1: Counts up to 1 000 000 000 c clock ticks, then resets c timer2: Cycle counter for timer1 c timer3: c timer4: Watchdog timer c ------------------------------- c timer1 = timer1 + 1 if (timer1 .gt. 1000000000) then timer1 = 0 timer2 = timer2 + 1 endif timer3 = timer3 + 1 if (timer3 .gt. 10000) timer3 = 0 c c c Timer4 is set to zero every time the foreground c program completes a loop. Address the watchdog c timer whenever timer4 is zero. This way, both c the foreground AND background tasks must be c running in order to keep the watchdog timer going. c -------------------------------------------------- c if (timer4 .eq. 0) then call outp (x'247', x'FF') timer4 = 1 endif c if (timer4 .lt. 10000) then timer4 = timer4 + 1 endif c c c Check the serial ports. c ----------------------- c call serchk1 call serchk2 call serchk3 call serchk4 call serchk5 call serchk6 call serchk7 c c c Call the BIOS time-of-day clock. Do this only c once for every 32 times the clock interrupt c occurs. The other 31 times, just issue an end- c of-interrupt command to the interrupt controller. c ------------------------------------------------- c if (ictr .ge. 32) then ictr = 1 call int162 else ictr = ictr + 1 call outp (x'20', x'20') endif c here = .false. return end c