.TITLE MJCLOK .IDENT /V02 / ;April 25,1983 .NLIST CND,TOC .ENABLE LC ; ; Author: Stephen C. Cribbs ; Technical Services Branch ; Whiteshell Nuclear Research Establishment ; Atomic Energy of Canada Limited ; Pinawa, Manitoba ; Canada R0E1L0 ; ; The user must **** SET TT NOCRLF **** ; ---- ; CONDITIONAL ASSEMBLY SYMBOLS ; Remove the leading semi-colon to request inclusion of the feature EIS = 1 ;Use EIS hardware MUL & DIV YMD = 1 ;Year/month/day date format ; MSGDSP = 1 ;Display message lines JBWTCH = 1 ;Watch background job SINGLL = 1 ;Single line display .IF NDF YMD .GLOBL DATE ; EXTERNAL .ENDC ;NDF YMD .GLOBL TIMASC ; EXTERNAL .MCALL .DATE,.EXIT,.GTIM,.GTJB,.GVAL,.INTEN .MCALL .MTPS,.PRINT,.SYNCH,.TTINR,.TWAIT JSW = 44 ;Job Status Word CONFIG = 300 ;Offset to Monitor CONFIGURATION word .IF DF JBWTCH SYSGEN = 372 ;Offset to Monitor's SYSGEN word SYSJOB = 40000 ;System Job flag in SYSGEN word .ENDC ;DF JBWTCH START: .GVAL #EMT,#CONFIG ;Get Monitor's Configration word ROR R0 ;Rotate bit zero into carry BCS 1$ ;Jump if FB or XM monitor .PRINT #NORUN ;Tell user - we don't run as SJ .EXIT ;Abort 1$: .IF DF JBWTCH .GTJB #EMT,#JOBBLK,#0 ;Get BG job configuration info. MOV JOBBLK+10,R1 ;Locate pointer to impure area MOV 22(R1),R1 ;Create pointer to I.JID ADD #12,R1 ;Offset to I.NAME+2 (ignore device) .GVAL #EMT,#SYSGEN ;Get monitor's System Generation word BIT #SYSJOB,R0 ;Is this a system job monitor? BEQ 2$ ;Jump if not ADD #12,R1 ;If so, we require additional offset 2$: MOV R1,BJBNME ;Save as pointer to BG job file name CLRB JBMTCH ;-Init. flag .ENDC ;DF JBWTCH CLRB DFORCE ;-Init. flag .IF DF MSGDSP CLRB MSGCUR ;-Init. flag .ENDC ;DF MSGDSP CLRB STATE ;-Init. flag MOV #TBUF,R0 ;Point to time data buffer MOV R0,RTP ;Save pointer to reference time value CMP (R0)+,(R0)+ ;Point to next two word slot MOV R0,NTP ;Save as pointer to new time reading .GTIM #EMT,RTP ;Load reference (ensures proper date) CALL INISCN ;Set up display screen BIS #10100,@#JSW ;Enable real-time terminal input UPDATE: .GTIM #EMT,NTP ;Obtain current time of day MOV #TARGS,R5 ;Build arg. block pointer MOV NTP,2(R5) ;Load time of day value CALL TIMASC ;Call encode routine .IF NDF SINGLL JSR R5,COPYF ;Duplicate the ASCII string .WORD TSTRNG+10. .WORD TSTRNG+25. .WORD 8. .ENDC MOV #TSTRNG,R0 ;Point to string to be output MOV #TSYNCH,R1 ; and to the .SYNCH block to be used CALL DSPLAY ;Ask the BG job to display it for us TSTB DFORCE ;Look at Date force flag BNE 1$ ;Display Date & Day if not zero CMP @NTP,@RTP ;Compare H.O. time values BPL EVNTST ;Jump if no day roll over 1$: MOV #DARGS,R5 ;Build a pointer to argument block .IF DF YMD CALL ENCDTE ;Return date in Canadian format .IFF CALL DATE ;Return date in American format BISB #40,DSTRNG+13. ;Convert month name letters two BISB #40,DSTRNG+14. ; and three to lowercase .ENDC ;DF YMD .IF NDF SINGLL JSR R5,COPYF ;Duplicate the field .WORD DSTRNG+9. .WORD DSTRNG+38. .WORD 9. .ENDC .IF DF MSGDSP MOV #EVNTBL,ETP ;Initialize event table pointer .ENDC ;DF MSGDSP CALL DOW ;Determine the Day-of-week MOV DAYP,R1 ;Get day-of-week pointer ASL R1 ;Convert to byte offset ADD #DAYNT,R1 ;Create table pointer MOV @R1,2$ ;Load pointer to day-of-week string JSR R5,COPYF ;Store day-of-week in output string 2$: .BLKW 1 .WORD DSTRNG+23. .WORD 9. .IF NDF SINGLL JSR R5,COPYF ;Duplicate the field .WORD DSTRNG+23. .WORD DSTRNG+52. .WORD 9. .ENDC MOV #DSTRNG,R0 ;Point to string to be displayed MOV #DSYNCH,R1 ; and to the .SYNCH block to be used CALL DSPLAY ;Ask BG job to do our I/O INCB DFORCE ;Assume failure TST R0 ; but check anyway BNE EVNTST ;If it did fail, we'll try again CLRB DFORCE ; else report the success EVNTST: .IF DF MSGDSP MOV ETP,R0 ;Get pointer to event table TSTB MSGCUR ;Is there a message current? BNE 7$ ;Skip turn_on check if so MOV (R0)+,R1 ;Test first word of table entry BEQ LOKCMD ;If zero, reached end-of-table BMI 2$ ;Negative means a Day_type message SUB #2,R1 ;Convert day_of_week to program range BPL 1$ ;Jump if positive or zero MOV #6,R1 ;Perform a Sunday wrap-around 1$: CMP DAYP,R1 ;Is this a message for today? BEQ 4$ ;Yes, queue it up BR 9$ ;No, ignore it 2$: ADD #2,R1 ;Adjust code for testing ease BEQ 4$ ;Jump if it's an always message BPL 3$ ;Jump if a weekday message CMP #4,DAYP ;Is today part of a weekend? BHIS 9$ ;Look at next table entry if not BR 4$ ;Yes, prepare to display it 3$: CMP #4,DAYP ;Is today a weekday (mon.-fri.)? BLO 9$ ;Look at next table entry if not 4$: MOV NTP,R1 ;Point to new time value CMP (R0)+,(R1)+ ; H.O. table element - H.O. time BHI LOKCMD ;Jump if no high order match BLO 5$ ;Look at next table entry if time past CMP (R0)+,(R1)+ ;L.O. table element - L.O. time BHI LOKCMD ;Jump if haven't reached event yet 5$: MOV ETP,R0 ;Get another copy of table pointer MOV NTP,R1 ;Reset pointer to new time value CMP 6(R0),(R1)+ ;Test against H.O. turn_off time BHI 6$ ;Do nothing if still within interval BLO 7$ ;Else, Update pointer to next element CMP 10(R0),(R1)+ ;Test against L.O. turn-off time BLOS 9$ ;If time is past, look at next message 6$: MOV 12(R0),MSGPTR ;Preserve a pointer to message text INCB MSGCUR ;Set flag: Message current INCB MFORCE ;Cause message to be displayed BR 10$ ;Display it 7$: MOV NTP,R1 ;Reset pointer to new time value CMP 6(R0),(R1)+ ;Test against H.O. turn_off time BHI 10$ ;Do nothing if still within interval BLO 8$ ;Kill current message if time past CMP 10(R0),(R1)+ ;Test against L.O. turn-off time BHI 10$ ;Do nothing if still within interval 8$: CLRB MSGCUR ;Indicate message display period over MOV #MKILL,MSGPTR ;Queue the clean_up sequence INCB MFORCE ;Cause it to be written to terminal 9$: ADD #12.,ETP ;Update table pointer to next message 10$: TSTB MFORCE ;Request to display a message? BEQ LOKCMD ;Jump if not CLRB MFORCE ;Assume successful display attempt MOV MSGPTR,R0 ;Point to test string BEQ LOKCMD ;Preserve us from programming errors MOV #MSYNCH,R1 ; and to message .SYNCH block CALL DSPLAY ;Output to screen TST R0 ;Assume success, but check to be sure BEQ LOKCMD ;Jump if message actually displayed INCB MFORCE ;Set flag to call for new attempt .ENDC ;DF MSGDSP LOKCMD: .TTINR ;Look for a user command BCS 2$ ;Jump if no request received BIC #^C177,R0 ;Keep just the ASCII code CMPB #'S,R0 ;SUSPEND request? BNE 1$ ;Jump if not INCB STATE ;Flag the state change BR 2$ ;Process it 1$: CMPB #'R,R0 ;RESUME request? BNE 2$ ;Ignore invalid commands CLRB STATE ;Reset the state flag CALL INISCN ;Re-initialize the display 2$: .TWAIT #EMT,#INTVAL ;Sleep for a while TSTB STATE ;Are we supposed to be dormant? BNE LOKCMD ;Yup, go back to sleep .IF DF JBWTCH MOV #JOBTBL,R1 ;Point to first job in table 3$: TST @R1 ;Is the table empty? BEQ 5$ ;If so, skip the test MOV BJBNME,R0 ;Form pointer to current BG job name CMP (R0)+,@R1 ;H.O. file names match? BNE 4$ ;No, go check next table entry CMP (R0)+,2(R1) ;Yes, do L.O. file names match? BNE 4$ ;No, go check next table entry CMP (R0)+,4(R1) ;Do the file types match BNE 4$ ;No, go check next table entry INCB JBMTCH ;Yes, set flag: Job match found BR 2$ ; and now put ourself back to sleep 4$: ADD #6,R1 ;Update to next Job table entry BR 3$ ;Repeat the test procedure 5$: TSTB JBMTCH ;Was a match found last pass? BEQ 6$ ;Jump if not CALL INISCN ;Re-initialize the display CLRB JBMTCH ;Indicate we are back in operation .ENDC ;DF JBWTCH 6$: MOV NTP,R0 ;Prepare to swap time pointers MOV RTP,NTP ;Swap them MOV R0,RTP ;properly JMP UPDATE ;Update the display .SBTTL Utility Routines ; Subroutine COPYF -Copy a byte field COPYF: MOV (R5)+,R1 ;Load address of source field MOV (R5)+,R2 ; and destination field address MOV (R5)+,R0 ; and the number of bytes to copy 1$: MOVB (R1)+,(R2)+ ;Copy a byte .IF DF EIS SOB R0,1$ ;Count down # bytes left to move .IFF DEC R0 ;+Count down # bytes left to move BNE 1$ ;+NHD equivalent of SOB instruction .ENDC ;DF EIS RTS R5 ;Return to caller ; Subroutine DSPLAY -Text string ouput rouitne DSPLAY: TST 14(R1) ;Be sure that .SYNCH block is free BNE 1$ ;Quick exit if not MOV R0,10(R1) ;Preserve address of display string CLR R0 ;Now indicate queue attempt success MOV R1,SBNME ;Load pointer to the .SYNCH block MOV @SP,-(SP) ;-Make room on stack CLR 2(SP) ;-Fake interrupt .MTPS #340 ;-Priority = 7 .INTEN 0 ;;;-Enter System state .SYNCH SBNME ;;Become BG job completion routine RTI ;Ignore failures (Doesn't everyone??) .PRINT ;Output the text string 1$: RETURN ;to caller ; Subroutine INISCN -Initialize display screen INISCN: MOV #INISTR,R0 ;Point to initialization string MOV #ISYNCH,R1 ; and to .SYNCH block CALL DSPLAY ;Get BG job to talk to terminal for us INCB DFORCE ;Insist Date-Day string be displayed .IF DF MSGDSP TSTB MSGCUR ;Is there a message to be displayed BEQ 1$ ;Jump if not INCB MFORCE ; and the current message 1$: .ENDC ;DF MSGDSP .TWAIT #EMT,#INTVAL ;Sleep for a while RETURN ;to caller ; Subroutine DOW -Determine day_of_week DOW: .DATE ;Get current date from monitor MOV R0,R1 ;Take a copy for days calculation BEQ 7$ ;Flag no-date situation MOV #^C37,R2 ;Construct a useful field mask ASL R1 ;+Shift days value into high byte ASL R1 ;+ ASL R1 ;+ SWAB R1 ;Get days value into low byte BIC R2,R1 ;Isolate days value MOV R1,-(SP) ;Preserve it on the stack MOV R0,R1 ;Take a copy of date for month calc. SWAB R1 ;Get month value in low byte ASR R1 ;+Right justify it ASR R1 ;+ BIC R2,R1 ;Isolate months value MOV R1,-(SP) ;Preserve it on the stack BIC R2,R0 ;Isolate year value (since 1972) MOV R0,-(SP) ;Preserve it on the stack .IF DF EIS MOV @SP,R1 ;Copy years value from stack MUL #365.,R1 ;Convert years to days (since 1972) .IFF MOV @SP,R0 ;Copy years value from stack CLR R1 ;Convert years to days (since 1972) 1$: ADD #365.,R1 ;+ simple NHD multiply DEC R0 ;+ years * 365. days/year BNE 1$ ;+ .ENDC ;DF EIS MOV @SP,R0 ;Remove years value from stack ASR R0 ;+Divide by four to get the ASR R0 ;+ number of extra days in leap years ADD R0,R1 ;Sum with days (since 1972) MOV (SP)+,R0 ;Is this year 1972? BEQ 2$ ;Yes, (it's a leap year) BIT #3,R0 ;No, but is this a leap year? BNE 2$ ;Jump if not CMP @SP,#2 ;Is month later than February? BGT 2$ ;Jump if so DEC R1 ;Subtract one from accumulated sum 2$: MOV #NDPM,R3 ;Get pointer to Days/Month table MOV (SP)+,R2 ;Get months value from stack 3$: DEC R2 ;Count it down BEQ 4$ ;Skip from loop when zero MOVB (R3)+,R0 ;Obtain # of days in a month ADD R0,R1 ;Add to accumulated sum BR 3$ ;Loop back for another month 4$: ADD (SP)+,R1 ;Include days value in sum .IF DF EIS CLR R0 ;Zero high register for divide DIV #7,R0 ;Determine the # of weeks since 1972 .IFF MOV #7,R0 ;Determine the # of weeks since 1972 5$: SUB R0,R1 ;+ simple NHD divide BPL 5$ ;+ total # days / 7 days per week ADD R0,R1 ;+ we only want the remainder .ENDC ;DF EIS SUB #2,R1 ;Adjust to make Monday=day#1 BGE 6$ ;Catch negative table pointers ADD #7,R1 ; and perform fix-up 6$: MOV R1,DAYP ;Store as a pointer to day_of_week RETURN ;to caller 7$: MOV #7.,DAYP ;Indicate no valid date in monitor RETURN ;to caller .IF DF YMD ; Subroutine ENCDTE -Encode date ; (Canadian Government format) ENCDTE: TST (R5)+ ;Skip over the FORTRAN argument count MOV @R5,R3 ;Save address of output text buffer .DATE ;Get the current date from the monitor MOV R0,-(SP) ;Preserve it BEQ 3$ ;Flag no-date situation MOV #^C37,R4 ;Construct a useful field mask BIC R4,R0 ;Isolate year value (since 1972) ADD #72.,R0 ;Convert to years since 1900 CALL CVT10 ;Encode the years value MOVB #'/,(R3)+ ;Insert field delimiter MOV @SP,R0 ;Take a copy of date for months calc. SWAB R0 ;Get month value in low byte ASR R0 ;+Right justify it ASR R0 ;+ BIC R4,R0 ;Isolate months value CMP R0,#10. ;Two digit number? BGE 1$ ;Yup, no fix up necessary MOVB #'0,(R3)+ ;Insert an ASCII zero character 1$: CALL CVT10 ;Encode the months value MOVB #'/,(R3)+ ;Insert field delimiter MOV (SP)+,R0 ;Take a copy for days calculation ASL R0 ;+Shift days value into high byte ASL R0 ;+ ASL R0 ;+ SWAB R0 ;Get days value into low byte BIC R4,R0 ;Isolate days value CMP R0,#10. ;Two digit number? BGE 2$ ;Yup, no fix up necessary MOVB #'0,(R3)+ ;Insert an ASCII zero character 2$: CALL CVT10 ;Encode the day value RETURN ;to user 3$: MOV #NODATE,R0 ;Point to Error condition string 4$: MOVB (R0)+,(R3)+ ;Copy a character to user's buffer BNE 4$ ;Loop till null located TST (SP)+ ;Clear off the stack RETURN ;to user ; Subroutine CVT10 ; Inputs: - R0 contains the number to be encoded ; R3 points to user's ASCII buffer for output CVT10: MOV #10.,R2 ;Do base 10 encode CVT: MOV R0,R1 ;Copy number to convert .IF DF EIS CLR R0 DIV R2,R0 ;Divide by ten .IFF MOV #-1,R0 ;+NHD algorithm to divide DIV: INC R0 ;+ the value in registers R0 & R1 SUB R2,R1 ;+ by the value (10) in R2 BPL DIV ;+The quotient will be left in R0 ADD R2,R1 ;+ the remainder will be left in R1 .ENDC ;DF EIS MOV R1,-(SP) ;Save remainder TST R0 ;Anything left to convert? BEQ 1$ ;If EQ no CALL CVT ;Else recur 1$: MOVB (SP)+,@R3 ;Move binary byte to output area BISB #'0,(R3)+ ;And make ASCII RETURN .ENDC ;DF YMD .SBTTL Workspace & Data Storage ISYNCH: .BLKW 1 ;+Initialization .SYNCH block .WORD 0 ;+Execute as a background routine .BLKW 3 ;+ .WORD -1,0 ;+Monitor must be values TSYNCH: .BLKW 1 ;+Time .SYNCH block .WORD 0 ;+Execute as a background routine .BLKW 3 ;+ .WORD -1,0 ;+Monitor must be values DSYNCH: .BLKW 1 ;+Date .SYNCH block .WORD 0 ;+Execute as a background routine .BLKW 3 ;+ .WORD -1,0 ;+Monitor must be values .IF DF MSGDSP MSYNCH: .BLKW 1 ;+Message .SYNCH block .WORD 0 ;+Execute as a background routine .BLKW 3 ;+ .WORD -1,0 ;+Monitor must be values .ENDC ;DF MSGDSP SBNME: .BLKW 1 ;Pointer to a .SYNCH block TARGS: .WORD 2 ;TIMASC argument block .BLKW 1 .WORD TSTRNG+10. DARGS: .WORD 1 ;DATE argument block .WORD DSTRNG+9. EMT: .BLKW 5 ;Monitor work space INTVAL: .WORD 0,60. ;Sleep time interval (ticks) .IF DF JBWTCH JOBBLK: ;-.GTJB work area (12. words) BJBNME: .BLKW 1 ;-Pointer to I.NAME in BG impure area .ENDC ;DF JBWTCH NTP: .BLKW 1 ;-New time pointer RTP: .BLKW 1 ;-Reference time pointer TBUF: .BLKW 4 ;-Time data buffers (two words each) DAYP: .BLKW 1 ;-Day pointer ETP: .BLKW 1 ;-Event table pointer .IF DF MSGDSP MSGPTR: .BLKW 1 ;-Point to current message string MSGCUR: .BLKB 1 ;-Indicates when there is an message active MFORCE: .BLKB 1 ;-MESSAGE force display flag .IFF .BLKW 2 ;- .ENDC ;DF MSGDSP DFORCE: .BLKB 1 ;-DATE force display flag STATE: .BLKB 1 ;-Program state [0=Active, >0=Dormant] .IF DF JBWTCH JBMTCH: .BLKB 1 ;FLAG: matched a job from JOBTBL .ENDC ;DF JBWTCH .EVEN .NLIST BEX NDPM: .BYTE 31.,28.,31.,30.,31.,30.,31.,31.,30.,31.,30.,31 DAYNT: .WORD MON,TUE,WED,THUR,FRI,SAT,SUN,NODATE MON: .ASCIZ / Monday / TUE: .ASCIZ / Tuesday / WED: .ASCIZ /Wednesday/ THUR: .ASCIZ /Thursday / FRI: .ASCIZ / Friday / SAT: .ASCIZ /Saturday / SUN: .ASCIZ / Sunday / NODATE: .ASCIZ /No date / .IF DF SINGLL BGNSCL = '2 ;First line of scrolling region .IFF BGNSCL = '3 ;First line of scrolling region .ENDC .IF DF MSGDSP BGNSCL = BGNSCL+1 ;First line of scrolling region .ENDC ;DF MSGDSP INISTR: .ASCII <23><33>/7/<33>/[//;80H/<33>/[1J/ .ASCII <33>/[//;24r/<33>/[1;1H/ .IF DF SINGLL .ASCII <33>/#6/ .IFF .ASCII <33>/#3/<33>/D/<33>/#4/ .ENDC .ASCII <33>/8/<21><200> TSTRNG: .ASCII <23><33>/7/<33>/[1;30H / .IF NDF SINGLL .ASCII <33>/[2;30H / .ENDC .ASCII <33>/8/<21><200> DSTRNG: .ASCII <23><33>/7/<33>/[1;1H / <33>/[06C / .IF NDF SINGLL .ASCII <33>/[2;1H / <33>/[06C / .ENDC .ASCII <33>/8/<21><200> NORUN: .ASCIZ /This program is not designed to execute under the SJ Monitor./ .EVEN .IIF DF JBWTCH ! MSGDSP, .IF DF JBWTCH JOBTBL: .RAD50 /KED/ ;+List of files where MJCLOK must be dormant .RAD50 / / ;+ .RAD50 /SAV/ ;+ .WORD 0 ;+End of JOBTBL .ENDC ;DF JBWTCH .IF DF MSGDSP EVNTBL: .WORD -3,32,122120,66,15620,MGDAY ; 8:05 - 16:25 Good day .WORD -2,32,122120,33,30360,MGM ; 8:05 - 8:15 Good morning .WORD 2,33,30360,33,73500,MGWND ; 8:15 - 8:20 Good weekend? .WORD -1,40,127460,42,7300,MCOF ; 9:55 - 10:20 Coffee time .WORD -1,47,140,52,2720,MLUN ;11:50 - 12:45 Lunch time .WORD -1,61,24760,62,104600,MCOF ;14:55 - 15:20 Coffee time .WORD 6,63,13040,64,136000,MBKUP ;15:30 - 16:00 Backup system .WORD -2,66,15620,110,101200,MGE ;16:25 - 22:00 Good evening .WORD 0 ;End-of-list MGDAY: .ASCII <23><33>/7/<33>/[//;29H/ .ASCII <33>/[7mHave a good day, eh!/ .ASCII <33>/[0m/<7><7><33>/8/<21><200> MGM: .ASCII <23><33>/7/<33>/[//;33H/<33>/[7mGood morning/ .ASCII <33>/[0m/<7><7><33>/8/<21><200> MGWND: .ASCII <23><33>/7/<33>/[//;29H/ .ASCII <33>/[7mHad a good weekend?/ .ASCII <33>/[0m/<7><7><33>/8/<21><200> MCOF: .ASCII <23><33>/7/<33>/[//;33H/<33>/[7mCoffee time/ .ASCII <33>/[0m/<7><7><33>/8/<21><200> MLUN: .ASCII <23><33>/7/<33>/[//;34H/<33>/[7mLunch time/ .ASCII <33>/[0m/<7><7><33>/8/<21><200> MBKUP: .ASCII <23><33>/7/<33>/[//;26H/ .ASCII <33>/[7mTime to backup the system/ .ASCII <33>/[0m/<7><7><33>/8/<21><200> MGE: .ASCII <23><33>/7/<33>/[//;33H/<33>/[7mGood evening/ .ASCII <33>/[0m/<7><7><33>/8/<21><200> MKILL: .ASCII <23><33>/7/<33>/[//;1H/ .ASCII <33>/[0K/<7><33>/8/<21><200> .EVEN .ENDC ;DF MSGDSP .END START