% *** *** *** *** *** *** *** *** *** Revision 1 *** *** *** *** *** *** *** *** *** *** *** *********************************************************************************************** *** EDUTVFC1.mc: Exerciser for the User Terminal Variable Format Controller and Large Format Display. *** Purpose: This test exercise the User Terminal Variable Format Controller as well as The Large Format (LF) display, the keyboard and the associated hardware *** Minimum Hardware: The standard four CPU boards one 96K storage module and one UTVFC board as well as an LF keyboard, an LF display and an associated power/interface unit and one UTVFC I/O cable. *** Run Time: Defined by the User. The test has passed when the user decides that the appropriate patterns have been displayed. The user stops the test by bugging the "ABORT" item on the Midas menu. *** Written by: J. Katsiroumbas, September 24, 1978 *** Modified by: M. Spaur and J. Kellman, April 10, 1980 to drive the large format display and to standardize the microcode format and install short looping capabilities. ************************************************************************************************ ************************************************************************************************ * SubTest Descriptions * SubTest 0: Initialize the I/O Control Block (IOCB) the Controller Status Block (CSB) * SubTest 1: Shift out 20b controller addresses (CADDR) in decending order and input the * Controller ID from register 0 of all controllers to locate the UTVFC. * SubTest 2: Shift out 20b controller addresses in ascending order to all controllers * except the UTVFC wich recieves an incrementing number from 0 to 17b. * SubTest 3: Shift out Controller addresses of zero to all controllers except the UTVFC * wich receives a CADDR = 5. * SubTest 4: Start the Task 5 firmware driver and select the Next Test to run. * SubTest 5: Increment the checkerboard pattern in the horizontal direction. * SubTest 6: Increment the checkerboard pattern in the verticle direction. * SubTest 7: Invert the checkerboard pattern. * SubTest10: Simulate a mouse command to increment the checkerboard pattern horizontally * for exercise purposes. * SubTest11: Store the checkerboard pattern in the memory buffers. * SubTest12: Send an alternating bar pattern to the memory buffers base on keyboard input * and return to SubTest 7. * SubTest13: Update the cursor position based on keyboard inputs and branch to the next * SubTest base on keyboard inputs ************************************************************************************************ ************************************************************************************************ * BreakPoints: * BEGIN: Change the user-definable registers if you like, and start the test by bugging * the "continue" item on the Midas menu. * BOARD-NOT-FOUND: SubTest 1 did not find a controller with the proper ID number in * register 0. * BAD-ID: After the board was found, SubTest 2 was not able to assign all CADDR's * from 0 to 17b and receive the proper ID from register 0. * * Note that there is no Passed-EDUTVFC1-Test breakpoint because this test ends when the * user bugs the "ABORT" item on the Midas menu. For the UTVFC module to pass this test * the user must observe the appropriate patterns on the LF display screen. ************************************************************************************************ ************************************************************************************************ * ShortLoop Logic Analyzer Sync Points and Control Store Addresses: * BOARD-NOT-FOUND: Control Store Address 1443 * BAD-ID: Control Store Address 1443 ************************************************************************************************ * Special Register Definitions: * ShortLoop: At any breakpoint in the test the register ShortLoop can be set equal to one. This will cause the current test to loop forever. In the default case it is set to zero and no looping occurs. * Exercise: Setting this register to a one will cause the microcode to exercise the UTVFC board without user intervention. This feature can be used for a long run exercise of the user interface. In the default case it is set to zero and no exercising occurs. * NextTest: setting this register to a one will cause SubTest 5 to run first (checkerboard). setting this register to a 2 will cause SubTest 6 (KeyTest) to run first. In the default case it is set to 1 and the checkerboard test runs first. ************************************************************************************************ * Subroutine Definitions: * ACCU: This subroutine runs in Task 5 and accumulates serial keyboard data sent back from the UTVFC via the I/O Attention line. The data is accumulated in two R registers called FCMSGU (most significant) and FCMSGL (least significant). * CURSERW: This subroutine writes a checkerboard pattern in the Curser Image Ram. * HEWRT: This subroutine runs at Task 5 and loads the Horizontal Control Ram of the UTVFC. The starting location is given by the contents of the R register WR0. The number of locations is given by the contents of the R register LINESTORUN. The data that is written into the Horizontal Control Ram is that contents of the R register IOCB1. * INITIALIZE: This subroutine runs in Task 5 and writes zero values in the entire Horizontal Control Ram of the UTVFC. * MSTORE: This subrouine runs in Task 0 and makes the following register assignments: BASE = BASE10 BASE1 = BASE11 BASE2 = BASE12 BASE3 = BASE13 BASE4 = BASE14 BASE5 = BASE15 This subroutine then calls the PMPUT subroutine. * NIBCLK: This subroutine generates Nibble Clock (NClk) pulses in the UTVFC hardware. The number of NClk pulses generated is equal to the value of the R register CREG when the subroutine is entered. This routine runs in Task 5, and is used with the FocreAARLoad feature of the BufStart register on the UTVFC board to Load or increment the Activer Address Register while loading the Horizontal Control Ram or the Cursor Image Ram. * PMPUT: This subroutine runs in Task 0 and stores a variable number of words into the memory buffers or the I/O control blocks. PMPUT uses the BASE registers as follows: BASE = Starting Memory Address (lower half) BASE1 = Starting Memory Address (upper half) BASE2 = Word Count (number of words to be stored) BASE3 = The data word to be stored BASE4 = A modifier, applied consecutively to every data word BASE5 = Function definition: 0 means ADD the modifier to every data word 1 means XOR the modifier with every data word * SHIFTOUT: This subroutine runs in Task 0 and shifts out bits 14, 15, 16 and 17 of the BASE register as a controller address * UTVRETURN: This subroutine runs in Task 5 and sets the AllowWU bit in the Control Register to one to enable wake ups and the restarts (or notifies) the Task 0 microcode at lable EN0. ************************************************************************************************ ************************************************************************************************ % * INITIALIZATION: BUILTIN[INSRT,24]; INSRT[D0LANG]; NOMIDASINIT; TITLE[FDEFS.MC]; **************** Macros and Set Values **************** SET[FTASK,0]; * TASK ASSIGNMENTS SET[RTASK,5]; MC[RTASK.1,LSHIFT[RTASK,14]]; * TASK SHIFTING MC[FTASK.1,LSHIFT[FTASK,14]]; SET[F,1]; * PAGE ASSIGNMENTS SET[F1,2]; SET[F2,3]; SET[F3,4]; SET[RPAGE,5]; SET[RPAGE1,6]; SET[F.1,LSHIFT[F,10]]; * PAGE SHIFTING SET[RPAGE.1,LSHIFT[RPAGE,10]]; SET[RPAGE1.1,LSHIFT[RPAGE1,10]]; SET[RTASK.2,LSHIFT[RTASK,4]]; MC[RPAGE.2,LSHIFT[RPAGE,10]]; MC[F.2,LSHIFT[F,10]]; TITLE[F DEF FILE]; SET TASK[FTASK]; MC[RTASK#,RTASK]; MC[ID,RTASK.2]; MC[TESTS,3]; MC[CSB,100]; * Controller Status Block Address (Low 16 bits) MC[MEMBUFU,0]; * Memory Buffer 0 address (upper half) MC[MEMBUFL,2000]; * Memory Buffer 0 address (lower half) MC[MYIDU,1000]; * Controller ID number (upper half) MC[MYIDL,35]; * Controller ID number (lower half) **************** R-Registers **************** RV[REVISION,4,1]; * Current Revision RV[SUBTEST,5,0]; * Current location of Task 0 microcode RV[SHORTLOOP,6,0]; * For looping on errors in SubTest1, 2 or 3 RV[EXERCISE,7,0]; * This register controls the exercise feature * Exercise = 0 disables the exercise feature. * Exercise # 0 activates the exercise feature. * In the default case the exercise feature is deactivated RV[TESTRUN,40]; * Used in calculating the next test to run. RV[NEXTTEST,41]; * Selects wich test will run first. * Bit 16&17 = 10 the KeyBoard test (SubTest6) runs first * Bit 16&17 # 10 the Checkerboard test (SubTest5) runs first * In the default case (SubTest5) runs first RV[KTIMER,42]; * Software Time out value for input loop of SubTest7 RV[DISPLAY,43]; * Used to select the number of displays to be used. RV[SAVE1,45]; * A general purpose register RV[SAVE3,47]; * A general purpose register RV[WORDCOUNT,53]; * Counts the number of words per scan line. RV[LINECOUNTER,52]; * Counts the number of horizontal scan lines per frame RV[WR10,50]; * General purpose registers RV[WR11,51]; RV[WR14,54]; RV[WR15,55]; RV[WR16,56]; RV[WR17,57]; RV[CADDR,60]; * Current controller address RV[MYID,62]; * UTVFC controller ID hardwired in reg 0 RV[CONTROLLERID,63]; * Controller ID returned by reg 0 of addressed controller RV[MESSU,66]; * Upper byte of Controller Status Block message word RV[MESSL,67]; * Lower byte of Controller Status Block message word RV[BASE,60]; * General purpose registers RV[BASE1,61]; RV[BASE2,62]; RV[BASE3,63]; RV[BASE4,64]; RV[BASE5,65]; RV[BASE10,70]; RV[BASE11,71]; RV[BASE12,72]; RV[BASE13,73]; RV[BASE14,74]; RV[BASE15,75]; RV[BASE16,76]; RV[BASE17,77]; *********************************************************************************************** *** Main Routine ON PAGE[F3]; SET TASK[FTASK]; *** SubTest 0 GO: START: SUBTEST_0C; TESTRUN_TESTS; * TESTRUN HAS TESTS#S TO RUN WR10_CSB; T_WR10_(WR10)+(10C); * SETTING UP IOCB#0 WR11_0C; BASE10_MEMBUFL; * BUFFER 0 ADDRESS BASE11_MEMBUFU; BASE12_10C; BASE12_(BASE12)+(T); BASE13_20000C; TASK; PSTORE4[WR10,BASE10,0]; BASE10_BASE10; * INTERLOCK T_WR10_(WR10)+(10C); * SETTING UP IOCB#1 BASE10_(BASE10)+(100C); * BUFFER 1 ADDRESS BASE12_(BASE12)-(10C); TASK; PSTORE4[WR10,BASE10,0]; BASE10_BASE10; * INTERLOCK T_WR10_(WR10)+(10C); WR11_0C; BASE10_MEMBUFL; BASE12_(BASE12)+(30C); * SETTING UP IOCB#2 T_(400C); BASE10_(BASE10)+(T); * BUFFER 2 ADDRESS BASE11_MEMBUFU; BASE13_(200C); TASK; PSTORE4[WR10,BASE10,0]; BASE10_BASE10; * INTERLOCK T_WR10_(WR10)+(10C); * SETTING UP IOCB#3 BASE10_(BASE10)-(100C); * BUFFER 3 ADDRESS BASE12_(BASE12)+(10C); BASE13_(20C); TASK; PSTORE4[WR10,BASE10,0]; BASE10_BASE10; * INTERLOCK WR10_(WR10)+(10C); * SETTING UP IOCB#4 BASE10_(BASE10)-(100C); * BUFFER 4 ADDRESS BASE12_(BASE12)+(10C); BASE13_(20C); TASK; PSTORE4[WR10,BASE10,0]; BASE10_BASE10; * INTERLOCK WR10_(WR10)+(10C); T_(200C); * SETTING UP IOCB#5 BASE10_(BASE10)+(T); * BUFFER 2 ADDRESS BASE12_CSB; BASE12_(BASE12)+(30C); BASE13_2000C; TASK; PSTORE4[WR10,BASE10,0]; BASE10_BASE10; * INTERLOCK DISPLAY_0C; * SETTING UP CSB T_WR10_CSB; BASE10_10C; * IOCB 0 ADDRESS T_BASE10_(BASE10)+T; BASE12_T; BASE12_(BASE12)+(10C); T_DISPLAY; BASE13_T; TASK; PSTORE4[WR10,BASE10,0]; BASE10_BASE10; * INTERLOCK BASE10_30C; * SETTING UP CSB PART 2 T_300C; TASK,BASE11_1400C; BASE11_(BASE11)OR(T); NEXTTEST_1C; * NEXTTEST HAS NEXT TEST# TO RUN PSTORE2[WR10,BASE10,6]; WORDCOUNT_2C; * WORDCOUNT HAS WORD COUNTER BEGIN: BREAKPOINT; * Set the paramenters you like and LOADPAGE[F2]; * bug CONTINUE to start the test GOTOP[CADD],DISPLAY_0C; *** SubTest 1 ON PAGE[F2]; CADD: NOP; * Resolves a branching conflict CADD0: NOP; * Resolves a branching conflict CADD0A: NOP; * Resolves a branching conflict CADD0B: NOP; * Resolves a branching conflict CADD0C: SUBTEST_1C; BASE2_MYIDU; T_MYIDL; BASE2_(BASE2)+T; BASE_20C; CADD1: BASE_(BASE)-1; * SHIFT OUT 17 TASK#'S CALL[SHIFTOUT]; * CALL TO SHIFT OUT TASK# LU_BASE; GOTO[CADD1,ALU#0]; * GO GET ANOTHER TASK# TO TRY BASE_20C; CADD2: BASE_(BASE)-1; * SHIFT OUT 17 TASK#'S T_BASE; CADDR_T; T_LSH[BASE,4]; INPUT[BASE3]; BASE3_(BASE3)OR(1C); T_BASE3; CONTROLLERID_T; T_BASE2; MYID_T; LU_(BASE3)XORT; GOTO[CADD3,ALU=0],LU_BASE; GOTO[CADD2,ALU#0]; * GO GET ANOTHER TASK# TO TRY LU_SHORTLOOP; GOTO[CADD,ALU#0]; BOARD-NOT-FOUND: BREAKPOINT; * PROPER ID NOT RETURNED FROM ANY SLOT. GOTO[CADD0]; *** SubTest 2 CADD3: SUBTEST_2C; T_BASE; * FOUND MY ID IN POSITION SAVED IN BASE16 BASE16_T; BASE14_20C; CADD4: BASE14_(BASE14)-1; * BASE14=MY SOFT ID # FROM 17 TO 0 CADD5: BASE15_20C; CADD6: T_BASE15_(BASE15)-1; * BASE15= CURRENT POSITION TO BE SHIFTED OUT LU_(BASE16)XOR(T); * DOES CURRENT POSITION= MY POSITION GOTO[CADD7,ALU#0],T_BASE14; BASE_T,GOTO[CADD10]; CADD7: BASE_T; BASE_(BASE)XOR(17C); CADD10: CALL[SHIFTOUT]; LU_BASE15; GOTO[CADD6,ALU#0]; * GO SHIFT ANOTHER TASK# OUT T_LSH[BASE14,4]; * WE SHIFTED ALL 17 OUT NOW CHECK MY ID INPUT[BASE3]; T_BASE14; CADDR_T; BASE3_(BASE3)OR(1C); T_BASE3; CONTROLLERID_T; T_BASE2; MYID_T; LU_(BASE3)XORT; GOTO[CADD10A,ALU#0],LU_BASE14; GOTO[CADD4,ALU#0]; LU_SHORTLOOP; GOTO[CADD0C,ALU#0]; GOTO[CADD25]; CADD10A: LU_SHORTLOOP; GOTO[CADD0A,ALU#0]; BAD-ID: BREAKPOINT; * Could not assign current CADDR to UTVFC and get back MYID GOTO[CADD0B]; *** SubTest 3 CADD25: SUBTEST_3C; BASE15_20C; CADD26: T_BASE15_(BASE15)-1; * BASE15= CURRENT POSITION TO SHIFT OUT LU_(BASE16)XOR(T); * DOES CURRENT POSITION= MY POSITION GOTO[CADD27,ALU#0],T_RTASK#; BASE_T,GOTO[CADD30]; CADD27: BASE_0C; CADD30: CALL[SHIFTOUT]; LU_BASE15; GOTO[CADD26,ALU#0]; * GO SHIFT ANOTHER TASK# OUT LOADPAGE[F]; GOTOP[INIT]; ****** Subroutine SHIFTOUT SHIFTOUT: USECTASK; T_GETRSPEC[143]; SAVE1_T; BASE3_4C; * PUT TASK# INTO T AND SHIFT IT OUT T_(BASE)XOR(17C); BASE4_T; SHIFTOUT1: GENSRCLOCK; TASK,T_BASE4_RSH[BASE4,1]; NOP; BASE3_(BASE3)-1; GOTO[SHIFTOUT1,ALU#0]; APCTASK&APC_SAVE1; RETURN; * QUIT WHEN YOU SHIFT FOUR TIMES ****** Subroutine PMPUT PMPUT: USECTASK; T_GETRSPEC[143]; TASK,SAVE3_T; T_BASE3; WR14_T; * SET FIRST DATA TO MEMORY LU_BASE5; GOTO[PLOG,ALU#0]; T_BASE4; WR14_(WR14)-T; TASK; NOP; PM0$: NOP; * DUMMY ENTRY PM0: BASE2_BASE2; * WORD COUNT <=0 WE ARE DONE GOTO[PMOUT,ALU=0],FREEZERESULT; GOTO[PMOUT$,ALU<0]; LU_BASE5; GOTO[PLOG1,ALU#0]; T_BASE4; TASK,T_WR14_(WR14)+T; * FIRST DATA WORD READY TO GO T_(BASE4)+T; WR15_T; T_(BASE4)+T; WR16_T; T_(BASE4)+T; WR17_T; PCON: T_RSH[BASE2,2]; * SET OF FOUR DATA, QUAD ALIGN AND ARITH MODIFIED GOTO[PUT1,ALU=0]; * IF WORD COUNT LESS THAN 4 DO ONE PUT T_LSH[BASE,16]; * IS MEMORY ADD QUAD ALINE IF NOT DO ONE PUT GOTO[PUT4,ALU=0]; T_T; PUT1: PSTORE1[BASE,WR14,0]; * DATA TO MEMORY TASK; BASE_(BASE)+1; * UP COUNT MEMORY ADD GOTO[PUT10,NOCARRY]; BASE1_(BASE1)+1; * CARRY ONE INTO UPPER ADDRESS PUT10: BASE2_(BASE2)-1; * DOWN COUNT WORD COUNT GOTO[PM0]; PUT4: PSTORE4[BASE,WR14,0]; * COUNT>=TO 4 ADDRESS IS QUAD, PUT 4 INTO MEMORY TASK,T_(WR17); WR14_T; T_4C; BASE2_(BASE2)-T; * DOWN COUNT WORD COUNT BY 4 BASE_(BASE)+T; * UP COUNT MEMORY ADDRESS BY 4 GOTO[PUT40,NOCARRY]; BASE1_(BASE1)+1; * CARRY 1 INTO UPPER ADDRESS PUT40: GOTO[PM0]; T_T; PMOUT: GOTO[PMOUT$]; PMOUT$: APCTASK&APC_SAVE3; RETURN; PLOG: T_BASE4; WR14_(WR14)XORT,GOTO[PM0$]; PLOG1: T_BASE4; TASK,T_WR14_(WR14)XORT; * FIRST DATA WORD READY TO GO T_(BASE4)XORT; WR15_T; T_(BASE4)XORT; WR16_T; T_(BASE4)XORT; WR17_T; GOTO[PCON]; * SET OF FOUR DATA WORDS QUAD ALIGN & LOGICAL MODIFIED ************************************************************************************************ TITLE[F DISPLAY DIAG PROGRAM]; SET TASK[FTASK]; ON PAGE[F]; *** SubTest 4 INIT: SUBTEST_4C; BASE_RPAGE.2; T_RTASK.1; BASE_(BASE)OR(T); APCTASK&APC_BASE; RETURN; * NOTIFIY TASK TO SET ADDRESS EN0: LOADPAGE[F1]; GOTOP[TEST]; *** SubTest 13 SPIN: SUBTEST_13C; * Read MESSU from Task 5 driver GOTO[SPIN2]; SPIN1: GOTO[SPIN2]; SPIN2: WR10_CSB; WR11_0C; TASK,MESSU_0C; PSTORE1[WR10,MESSU,4]; NOP; SPIN3: WR10_CSB; WR11_0C; NOP; PFETCH2[WR10,MESSU,4]; TASK,PFETCH2[WR10,BASE10,6]; NOP; KTIMER_(KTIMER)-1; * Soft Timmer: give the driver time to post MESSU GOTO[SPIN4,ALU>=0],LU_LDF[MESSU,14,3]; GOTO[U+YR,ALU=0]; NOP; U+XR: LU_LDF[MESSU,13,1]; * Update curser position X GOTO[U-XR,ALU=0]; BASE11_(BASE11)+(1C), GOTO[U+YR]; U-XR: BASE11_(BASE11)-(1C), GOTO[U+YR]; U+YR: T_LDF[MESSU,10,3]; * Update curser position Y GOTO[UZR,ALU=0]; LU_LDF[MESSU,7,1]; GOTO[U-YR,ALU#0]; BASE10_(BASE10)+(1C), GOTO[UZR]; U-YR: BASE10_(BASE10)-(1C), GOTO[UZR]; UZR: PSTORE2[WR10,BASE10,6]; TASK; NOP; GOTO[EN1]; EN1: LU_EXERCISE; GOTO[EXERMOUSE,ALU#0]; LU_MESSU; GOTO[SPIN3,ALU=0],WR10_7000C; * SEE IF ANYTHING TO DO KTIMER_200C; T_(MESSU)AND(7000C); T_(WR10)XORT; GOTO[INIT10,ALU=0],T_4C; * TIME TO CHANGE TEST MOUSE=1,2,3 T_(NEXTTEST)ANDT; GOTO[INIT2,ALU=0]; * WE ARE IN THE KEYBOARD TEST IF ALU#0 T_(MESSL)AND(100000C); GOTO[KEY1,ALU#0]; * DO SOMETHING ONLY IF KEY IS DOWN GOTO[SPIN]; INIT2A: NOP; INIT2: DISPATCH[MESSU,4,3]; DISP[MOUSE]; MOUSE: GOTO[SPIN],AT[F.1,100]; * MOUSE=0 GOTO SPIN GOTO[INIT20],AT[F.1,101]; * MOUSE=1 GOTO INIT20 INC WORD COUNT GOTO[INIT30],AT[F.1,102]; * MOUSE=2 GOTO INIT30 INC LINE COUNT GOTO[SPIN],AT[F.1,103]; * MOUSE=3 GOTO TEST GOTO[INIT40],AT[F.1,104]; * MOUSE=4 GOTO TEST GOTO[SPIN],AT[F.1,105]; * MOUSE=5 GOTO INIT21 DEC WORD COUNT GOTO[SPIN],AT[F.1,106]; * MOUSE=6 GOTO INIT31 DEC LINE COUNT GOTO[SPIN],AT[F.1,107]; * MOUSE=7 GOTO TEST SPIN4: GOTO[SPIN3]; *** SubTest 10 EXERMOUSE: SUBTEST_10C; KTIMER_77777C; EXERMOUSEB: T_(KTIMER)+(1C); * Need a soft timer to slow this branch down NOP; KTIMER_T; TASK; LU_KTIMER; GOTO[EXERMOUSEB,ALU#0]; MESSU_1000C; * will cause horizontal increment pattern KTIMER_200C; NOP; EXERMOUSE1: NOP; EXERMOUSE1A: GOTO[INIT2A]; * Go do it *** SubTest 13 (continued) KEY1: LOADPAGE[F1]; GOTOP[KEY10]; INIT10: LOADPAGE[F1]; GOTOP[TEST]; *** SubTest 5 INIT20: SUBTEST_5C; WORDCOUNT_(WORDCOUNT)+1; * INC WORD COUNTER TASK; NOP; LU_(WORDCOUNT)-(77C); GOTO[INIT21,ALU=0]; GOTO[MEM0]; INIT21: WORDCOUNT_0C,GOTO[MEM0]; *** SubTest 6 INIT30: SUBTEST_6C; WR10_CSB; TASK,WR10_(WR10)+(10C); LINECOUNTER_(LINECOUNTER)+1; * INC LINE COUNTER T_400C; LU_(LINECOUNTER)-(T); GOTO[INIT31,ALU=0],WR11_0C; GOTO[INIT32],T_LINECOUNTER; * INC LINE COUNTER INIT31: T_0C; LINECOUNTER_2000C; NOP; INIT32: PSTORE1[WR10,LINECOUNTER,3]; TASK,PSTORE1[WR10,LINECOUNTER,13]; NOP; LINECOUNTER_T,GOTO[SPIN]; *** SubTest 7 INIT40: SUBTEST_7C; * FLIP BACK GROUND WR10_CSB; WR11_0C; TASK; PFETCH1[WR10,BASE17,2]; BASE17_(BASE17)XOR(140C); PSTORE1[WR10,BASE17,2],GOTO[SPIN]; *** SubTest 11 MEM0: SUBTEST_11C; BASE10_MEMBUFL; * BUFFER 0 ADDRESS TASK,BASE11_MEMBUFU; T_WORDCOUNT; BASE12_T; * # OF WORD TO SWAP DATA GOTO[SPIN2,ALU=0],BASE13_0C; * ZERO CASE DO NOTHING BASE14_0C; TASK,BASE15_0C; T_(BASE15)-1; BASE16_T; * ALTERNATING DATA T_100C; WR10_MEMBUFL; * BUFFER SIZE WR10_(WR10)+(T),GOTO[MEP0]; * BUFFER SIZE MEM00: BASE10_MEMBUFL; * BUFFER 1 ADDRESS WR10_MEMBUFL; TASK,T_200C; WR10_(WR10)+(T); * BUFFER SIZE BASE11_MEMBUFU; BASE10_(BASE10)+(100C); * BUFFER 1 ADDRESS BASE16_0C; T_(BASE16)-1; BASE13_T,GOTO[MEP1]; MEM01: T_WR10_CSB; BASE10_10C; * IOCB 0 ADDRESS TASK,T_BASE10_(BASE10)+T; BASE11_0C; WR11_0C; NOP; PSTORE2[WR10,BASE10,0],GOTO[SPIN2];* SETTING UP CSB MEP0: T_T; CALL[MSTORE]; T_WR10; T_(BASE)-T; GOTO[MEM00,ALU>=0],T_BASE; BASE10_T; T_BASE13; BASE17_T; T_BASE16; BASE13_T; T_BASE17; BASE16_T,GOTO[MEP0]; MEP1: T_T; CALL[MSTORE]; T_WR10; T_(BASE)-T; GOTO[MEM01,ALU>=0],T_BASE; BASE10_T; T_BASE13; BASE17_T; T_BASE16; BASE13_T; T_BASE17; BASE16_T,GOTO[MEP1]; *** Subroutine MSTORE MSTORE: USECTASK; T_GETRSPEC[143]; * SAVE CALL RETURN SAVE1_T; T_BASE10; * LOW ADD BASE_T; T_BASE11; * HIGH ADD TASK,BASE1_T; T_BASE12; * WORD COUNT BASE2_T; T_BASE13; * DATA TO BE STORED BASE3_T; T_BASE14; * MODIFIER TO DATA BASE4_T; T_BASE15; * ARITH OR LOGICAL MOD LOADPAGE[F2]; CALLP[PMPUT],BASE5_T; * CALL THE PUTTER APCTASK&APC_SAVE1; * RESTORE THE CALL RETURN RETURN; *** Entry Points to SubTests 0, 4, 11 and 12 THESE ARE ENTRY POINTS FOR TASK SWITCHING GOTO[EN0],AT[F.1,0]; * Try TEST again GOTO[MEM0],AT[F.1,40]; * Pattern Test Entry LOADPAGE[F1],AT[F.1,41]; * Key Test Entry GOTOP[KEY]; LOADPAGE[F3],AT[F.1,377]; * Restart the test GOTOP[START]; *** SubTest 12 ON PAGE[F1]; KEY: SUBTEST_12C; BASE10_MEMBUFL; * BUFFER 0 ADDRESS T_(200C); BASE10_(BASE10)+(T); * BUFFER 0 ADDRESS TASK,BASE11_MEMBUFU; BASE12_60C; * # OF WORD TO SWAP DATA BASE13_0C; * STARTING DATA BASE14_0C; BASE14_(BASE14)-1; * ALTERNATING DATA LOADPAGE[F]; CALLP[MSTORE],BASE15_1C; * LOGICAL MOD T_BASE; TASK,BASE10_T; BASE12_230C; * FINISH BUFFER#0=P,BUFFER#1=0 AND BUFFER#2=0 LOADPAGE[F]; CALLP[MSTORE],BASE14_0C; T_T; * BUFFER 0= TO PROMPT DATA, - - - - ECT 20 BITS KEY10: T_MESSU; WR10_T; * BIT DATA WORD WR11_17C; * # OF BITS BASE10_MEMBUFL; * BUFFER 0 ADDRESS T_(300C); T_BASE10_(BASE10)+(T); * BUFFER 0 ADDRESS BASE_T; * FIRST WORD = TO ZERO BASE12_2C; * COUNT OF WORDS TO STORE BASE13_0C; * FIRST WORD = TO ZERO TASK,BASE11_MEMBUFU; BASE14_0C; BASE15_1C; BASE17_1C; T_BASE17_LSH[BASE17,17]; KEY2: T_(WR10)ANDT; GOTO[KEY3,ALU=0]; T_(BASE13)-1; BASE14_T; * SECOND WORD = TO 177777 KEY3: T_BASE; LOADPAGE[F]; CALLP[MSTORE],BASE10_T; BASE14_0C; TASK,WR10_LSH[WR10,1]; * SHIFT FOR NEXT DATA BIT T_BASE17; WR11_(WR11)-1; * DEC COUNT GOTO[KEY2,ALU>=0]; T_MESSL; WR10_T; * BIT DATA WORD WR11_7C; * # OF BITS KEY4: T_BASE17; T_(WR10)ANDT; GOTO[KEY5,ALU=0]; T_(BASE13)-1; BASE14_T; * SECOND WORD = TO 177777 KEY5: T_BASE; LOADPAGE[F]; CALLP[MSTORE],BASE10_T; BASE14_0C; TASK,WR10_LSH[WR10,1]; * SHIFT FOR NEXT DATA BIT NOP; WR11_(WR11)-1; * DEC COUNT GOTO[KEY4,ALU>=0]; T_BASE; BASE10_T; LOADPAGE[F]; CALLP[MSTORE],BASE12_30C; T_WR10_CSB; BASE10_30C; * IOCB 0 ADDRESS BASE10_(BASE10)+T; BASE11_0C; WR11_0C; NOP; PSTORE2[WR10,BASE10,0]; * SETTING UP CSB LOADPAGE[F]; GOTOP[SPIN2]; *** SubTest 4 (continued) TEST: SUBTEST_4C; LU_NEXTTEST; GOTO[TEST5,ALU=0]; LU_TESTRUN; GOTO[TEST6,ALU=0]; TEST1: T_1C; WR10_0C; TEST2: LU_(NEXTTEST)ANDT; GOTO[TEST3,ALU#0]; WR11_T; TASK; T_LSH[WR11,1]; WR10_(WR10)+1,GOTO[TEST2]; TEST3: LU_(TESTRUN)ANDT; GOTO[TEST4,ALU=0]; NEXTTEST_LSH[NEXTTEST,1]; T_40C; WR10_(WR10)+T; T_F.2; TASK,WR10_(WR10)OR(T); T_FTASK.1; WR10_(WR10)OR(T); APCTASK&APC_WR10; RETURN; TEST4: NEXTTEST_LSH[NEXTTEST,1],GOTO[TEST]; TEST5: NEXTTEST_1C,GOTO[TEST]; TEST6: LOADPAGE[F]; GOTOP[EN0]; ************************************************************************************************ *** This is the Task 5 firmware. It Initializes the UTVFC, loads the data buffers and generates *** the Verticle sync pulse. It also accumulates the serial Keyboard data. TITLE[ TASK FIRMWARE]; SET TASK[RTASK]; SET[RTASK.2,LSHIFT[RTASK,4]]; **************** Macros and Set Values **************** SET[CLKCR,0]; * Control Register number SET[CLKSTART,1]; * Buffer Starting Address Register number SET[HORZLOAD,2]; * Horizontal Control Ram Register number SET[CLKIAR,3]; * Inactive Address Register number SET[CLKCUR0CR,4]; * Curser 0 Control Register number SET[CLKCUR1CR,5]; * Curser 1 Control Register number SET[CUR0WE,6]; * Curser 0 Meomory Register number SET[CUR1WE,7]; * Curser 1 Meomory Register number MC[HECOUNT,400]; * The number of Horizontal Ram locations MC[LINESU,400]; * Number of scan lines per frame (upper byte) MC[LINESL,256]; * Number of scan lines per frame (lower byte) MC[VST,22]; * Verticle Sync Pulse width (in scan lines) MC[UTVCSB,100]; * Controller Status Block Address (lower half) **************** R-Registers **************** RV[IOCB,20]; * IOCB word #0 (low half of Memory Buffer Address) RV[IOCB1,21]; * IOCB word #1 (high half of Memory Buffer Address) RV[BUFP,20]; * IOCB word #0 (low half of Memory Buffer Address) RV[BUFP1,21]; * IOCB word #1 (high half of Memory Buffer Address) RV[NIOCB,22]; * IOCB word #2 (short pointer to next IOCB) RV[LINESTORUN,23]; * IOCB word #3 (number of Lines in this Buffer) RV[WR0,24]; * Memory addressing register (low half) RV[WR1,25]; * Memory addressing register (high half) RV[CREG,26]; * UTVFC control word register RV[DEVICE,27]; * Used to keep track of terminals RV[LINECOUNT,30]; * Used to count horizontal scan lines RV[FCMSGU,32]; * Used to Accumulate serial back channel data (upper half) RV[FCMSGL,33]; * Used to Accumulate serial back channel data (lower half) RV[CURC,31]; * Curser control word RV[CUREG,34]; * Curser position Y RV[CUREG1,35]; * Curser position X RV[STP,36]; * Used for branch selection RV[TEMP,37]; * A general purpose register *********************************************************************************************** *** Driver Routine ON PAGE[RPAGE1]; ENTRY: TASK; ENTRY1: NOP; ENTRY2: DISPATCH[STP,15,3]; DISP[DISP0]; DISP0: GOTO[VS0L],IOCB_UTVCSB,AT[RPAGE1.1,100]; GOTO[VS0T16L],LU_(LINECOUNT)-(VST),AT[RPAGE1.1,101]; GOTO[VS16L],CREG_(CREG)AND(367C),AT[RPAGE1.1,102]; GOTO[VS17L],T_(DEVICE) OR (4C), AT[RPAGE1.1,103]; GOTO[VS0D], IOFETCH20[IOCB,ADD[RTASK.2,10],0], AT[RPAGE1.1,104]; GOTO[EXIT], IOFETCH20[IOCB,ADD[RTASK.2,11],0], AT[RPAGE1.1,105]; GOTO[EXIT], IOFETCH20[IOCB,ADD[RTASK.2,12],0], AT[RPAGE1.1,106]; GOTO[EXIT], IOFETCH20[IOCB,ADD[RTASK.2,13],0], AT[RPAGE1.1,107]; VS0L: IOCB1_0C; TASK,CURC_2000C; PFETCH4[IOCB,WR0,0]; * GET POINTER TO IOCB WR0_WR0; STP_1C; PFETCH4[WR0,IOCB,0]; * GET IOCB LU_LDF[FCMSGL,10,1]; GOTO[VS0L1,ALU=0]; * SEE IF WE POSTED THE MSG FCMSGU_0C; VS0L1: CREG_(CREG)XOR(4C); CREG_(CREG)OR(32C); WR0_UTVCSB; CALL[ACCU],LINECOUNT_0C; PSTORE1[WR0,CREG,2]; OUTPUT[CREG,CLKCR]; PFETCH2[WR0,CUREG,6]; GOTO[EXIT],LINESTORUN_(LINESTORUN)-1; VS0T16L: GOTO[VS0T16L1,ALU#0]; STP_2C; VS0T16L1: LU_LDF[FCMSGL,10,1]; GOTO[VS0T16L2,ALU=0]; * SEE IF WE POSTED THE MSG FCMSGU_0C; VS0T16L2: NOP; CALL[ACCU],OUTPUT[CREG,CLKCR]; GOTO[EXIT],LINESTORUN_(LINESTORUN)-1; VS16L: LU_LDF[FCMSGL,10,1]; GOTO[VS16L1,ALU=0]; * SEE IF WE POSTED THE MSG FCMSGU_0C; VS16L1: STP_3C; CALL[ACCU],OUTPUT[CREG,CLKCR]; GOTO[EXIT],LINESTORUN_(LINESTORUN)-1; VS17L: STP_T; CREG_(CREG) AND (347C); OUTPUT[CREG,CLKCR], GOTO[ENTRY2]; VS0D: IOCB_(IOCB)+(20C); T_CUREG; LU_(LINECOUNT)-(T); GOTO[UTV0CURSER,ALU>=0],T_37C; GOTO[UTV0NOCURSER],TEMP_40C; VS0D1: IOFETCH20[IOCB,ADD[RTASK.2,10],0]; LU_LDF[FCMSGL,10,1]; GOTO[VS0D2,ALU=0]; * SEE IF WE POSTED THE MSG FCMSGU_0C; VS0D2: IOCB_(IOCB)+(20C); CALL[ACCU],IOFETCH20[IOCB,ADD[RTASK.2,10],0]; IOCB_(IOCB)+(20C); IOFETCH20[IOCB,ADD[RTASK.2,10],0]; IOCB_(IOCB)-(60C); GOTO[EXIT],LINESTORUN_(LINESTORUN)-1; UTV0CURSER: LU_(LDF[CURC,0,5])-(T); GOTO[UTV0NOCURSER,ALU=0],TEMP_40C; T_CURC; TEMP_T; T_CUREG1; TEMP_(TEMP)OR(T); OUTPUT[TEMP,CLKCUR0CR]; CURC_(CURC)+(4000C),GOTO[VS0D1]; UTV0NOCURSER: OUTPUT[TEMP,CLKCUR0CR],GOTO[VS0D1]; *** Subroutine ACCU ACCU: T_100000C,GOTO[ACCU2,IOATTEN]; T_0C; ACCU2: LU_LDF[FCMSGU,17,1]; GOTO[ACCU0,ALU=0]; ACCU1: FCMSGL_RSH[FCMSGL,1]; FCMSGL_(FCMSGL)ORT,RETURN; * MERGE BIT ACCU0: FCMSGU_RSH[FCMSGU,1]; FCMSGU_(FCMSGU)ORT; * MERGE BIT RETURN,FCMSGL_100000C; EXIT: GOTO[NEXT,ALU=0],T_LINESU; EXIT1: TEMP_LINESL; T_TEMP_(TEMP)OR(T); LU_(LINECOUNT)-(T); GOTO[EXIT4,ALU>=0]; EXIT2: LU_LDF[FCMSGU,17,1]; GOTO[EXIT5,ALU=0],LINECOUNT_(LINECOUNT)+1; LU_LDF[FCMSGU,0,1]; GOTO[EXIT3,ALU=0], LU_LDF[FCMSGL,10,1]; GOTO[EXIT6,ALU=0]; NOP; EXIT3: FCMSGL_(FCMSGL) OR (200C); PSTORE2[WR0,FCMSGU,4]; EXIT5: GOTO[ENTRY],IOSTROBE; EXIT6: GOTO[ENTRY],IOSTROBE; EXIT4: STP_0C,GOTO[EXIT2]; NEXT: PFETCH4[NIOCB,IOCB,0]; T_LINESU,GOTO[EXIT1]; RUNEN0: CALL[INITIALIZE],AT[RPAGE.1,0]; NOP; CALL[CURSERW]; NOP; CALL[INITIALIZE]; WR0_0C; *ADDRESS LINESTORUN_12C; CALL[HEWRT],IOCB1_0C; LINESTORUN_123C; CALL[HEWRT],IOCB1_4C; LINESTORUN_10C; CALL[HEWRT],IOCB1_0C; LINESTORUN_1C; CALL[HEWRT],IOCB1_2C; LINESTORUN_103C; CALL[HEWRT],IOCB1_0C; LINESTORUN_1C; CALL[HEWRT],IOCB1_1C; LINESTORUN_124C; CALL[HEWRT],IOCB1_0C; LINESTORUN_1C; CALL[HEWRT],IOCB1_10C; LINESTORUN_1C; CALL[HEWRT],IOCB1_0C; LINECOUNT_0C; CURC_2000C; * CURC=CURSER COUNT FCMSGL_0C; STP_0C; * STATEPOINTER FCMSGU_0C; * FCMSGU&FCMSGL= MSG WR0_0C; OUTPUT[WR0,CLKSTART]; OUTPUT[WR0,CLKIAR]; WR0_(WR0)OR(140000C); OUTPUT[WR0,CLKSTART]; * SET DB POINTER TO 0 (HEX) CALL[UTVRETURN]; * UPASSMSGL=SAVE LAST MSG LOADPAGE[RPAGE1]; GOTOP[ENTRY2]; *** Subroutine UTVRETURN UTVRETURN: WR1_2C; OUTPUT[WR1,CLKCR]; * WR1 REG = ENABLE OSC(WAKEUP IS SET) T_F.2; WR1_FTASK.1; WR1_(WR1)OR(T); APCTASK&APC_WR1; RETURN; *** Subroutine NIBCLK NIBCLK: USECTASK; T_GETRSPEC[143]; FCMSGU_T; CREG_LSH[CREG,2]; NIBCLK1: DEVICE_(DEVICE)OR(200C); OUTPUT[DEVICE,CLKCR]; CREG_(CREG)-1; GOTO[NIBCLK1,ALU#0]; APCTASK&APC_FCMSGU; RETURN; *** Subroutine HEWRT HEWRT: USECTASK; T_GETRSPEC[143]; CURC_T; WR1_0C; OUTPUT[WR1,CLKSTART]; CALL[NIBCLK],CREG_2C; * 2 NIBCLK WR1_(WR1)OR(140000C); OUTPUT[WR1,CLKSTART]; WR1_0C; HEWRT1: T_WR0; LU_(WR1)XOR(T); GOTO[HEWRT3,ALU#0]; OUTPUT[IOCB1,HORZLOAD]; LINESTORUN_(LINESTORUN)-1; GOTO[HEWRT2,ALU=0],WR0_(WR0)+1; NOP; HEWRT3: WR1_(WR1)+1; CALL[NIBCLK],CREG_1C; * 1 NIBCLK GOTO[HEWRT1]; HEWRT2: APCTASK&APC_CURC; RETURN; *** Subroutine INITIALIZE INITIALIZE: USECTASK; T_GETRSPEC[143]; LINECOUNT_T; DEVICE_0C; OUTPUT[DEVICE,CLKCR]; CREG_1C; CALL[NIBCLK]; * CLEAR SWITCH IF SET IOCB1_0C; * PATTERN=0 LINESTORUN_HECOUNT; * COUNT CALL[HEWRT],WR0_0C; * CLEAR ALL HEVENTS CONTROL SET IOCB1_7C; * PATTERN=SWITCH,HS,ML LINESTORUN_1C; * COUNT CALL[HEWRT],WR0_0C; * ADDRESS IOCB1_0C; * PATTERN=0 LINESTORUN_1C; * COUNT CALL[HEWRT],WR0_0C; * ADDRESS APCTASK&APC_LINECOUNT; * CONTROL PHASE S/B LOW RETURN; *** Subroutine CERSERW CURSERW: USECTASK; T_GETRSPEC[143]; LINECOUNT_T; WR0_0C; * ADDRESS LINESTORUN_400C; * COUNT CALL[HEWRT],IOCB1_14C; WR0_15C; IOCB1_2000C; IOCB_374C; T_1400C; IOCB_(IOCB)OR(T); CURSERW1: T_IOCB; LINESTORUN_T; CURSERW2: T_LINESTORUN; NIOCB_T; T_IOCB1; NIOCB_(NIOCB)OR(T); OUTPUT[NIOCB,CLKCUR0CR]; OUTPUT[NIOCB,CLKCUR1CR]; CALL[NIBCLK],CREG_1C; * 1 NIBCLK OUTPUT[WR0,CUR0WE]; OUTPUT[WR0,CUR1WE]; LINESTORUN_(LINESTORUN)-(4C); LU_LINESTORUN; GOTO[CURSERW2,ALU>=0]; IOCB1_(IOCB1)+(4000C); CURSERW3: WR0_(WR0)XOR(17C); T_LDF[IOCB1,0,5]; GOTO[CURSERW1,ALU#0]; APCTASK&APC_LINECOUNT; RETURN; END; (2048)