% **************************************************************************************** *** EDTMP.mc : Test Maintenance Panel microcode *** Revision 1.1 *** *** Purpose : This test checks D0 START/OFF switches and display logic in the Maintenance Panel. *** Minimum Hardware : Standard 4 CPU boards and Maintenance Panel with four-digit display. *** Approximate Run Time : defined by user, needs human interaction. (normally takes about 5 minutes.) *** Written by : K. Mayekawa, March 26, 1980 *** Modified by : K. Mayekawa, April 8, 1980 Added the capability to check TMS1000 chip *** Modified by : C. Thacker, May 3, 1980 Standardized assembly with tmp.cm, fixed for new d0lang. **************************************************************************************** **************************************************************************************** *SubTest Description: * SubTest 0: Check TimeOfDay routine (Task 0) Checks if TimeOfDay is set and incremented correct. * SubTest 1: Check D0 Switch routine (Task 0) Checks if turning off D0 by the program works. Also checks if D0 is turned on by Alarm from TMS1000. * SubTest 2: Check Maintenance Panel routine (Task 0) Clears and increments Maintenance Panel and checks if the display is correct. * SubTest 3: Check CS-ParErr routine (Task 0) Enables CS-ParErr and checks if the display shows 8880. * SubTest 4: Fault Handling routine (Task 15d) When CS-ParErr causes fault, this routine takes over. It goes through a delay loop so that there is a enough time to check the display, then resets errors and returns to Task 0. **************************************************************************************** *BreakPoints: * SubTest 0 * CorrectTOD : TimeOfDay is set and incremented correctly. * FastTOD : TimeOfDay is incremented too fast. * SlowTOD : TimeOfDay is not incremented or incremented too slow. * Wait1min : Wait 1 minute, then CONTINUE. * WrongTOD : TimeOfDay is not set correct or not incremented correct. * * SubTest 2 * CheckMaxNumber : Check if display is 9999 or user-defined maximum number. * CheckMPanel : Check if display is incremented by a value of Interval. * Display9 : Check if the digit is 9. * When WhichDigit = 0, display should be 0009 * When WhichDigit = 1, display should be 0090 * When WhichDigit = 2, display should be 0900 * When WhichDigit = 3, display should be 9000 * Disp0000 : Check if display is 0000. * SetValues : Set Interval and/or MaxNumber if other than default values * are desired. * * SubTest 3 * CSPETestDone : The program comes back here after Fault Handling routine. * Disp8880 : After this breakpoint, the display should show 8880. * NotCatchCSPE : Fault Handler has not been enabled. * Passed-EDTMP-Test: Passed all tests. * * Subroutine SampleTMS * WrongData : Sampled data of TMS1000 is wrong. **************************************************************************************** *BreakPoint Logic Analyzer Sync Points: * There is no short looping capability for this exerciser. **************************************************************************************** *Special Reg. Definition: *Task 0 Registers * CS1: Contains bit 16d-31d of the instruction 'NOP' at address 1077b. Bit 15d (31d of the instruction) is a parity bit and is complemented in SUBTEST 2. Then contents of CS1 is put back to Control Store at address 1077 so that CS-ParErr is caused when this instruction is executed. * CSwdAddr: Contains the address of the instruction 'NOP' (=1077b). * CurrentLoopNum: A counter for IncMPTest2 routine. Each time through IncLoop2, Maintenance Panel is incremented by the value of Interval and CurrentLoopNum is incremented by 1. When CurrentLoopNum = MaxLoopNum IncLoop2 terminates. * MaxLoopNum : Maxixmum value for CurrentLoopNum. Calculated from Interval and MaxNumber (= MaxNumber/Interval). When default values are used (Interval = 1111d, MaxNumber = 9999d), MaxLoopNum = 9d. * TMSdata0: Contains a passowrd to be sent to TMS1000. Set to hex A1F5(=120765b). * TMSdata1: Contains a command to be sent to TMS1000. Only high 8 bits are significant. (a command is 8-bit long) * TMSdata2: Contains a high data to be sent to TMS1000. * TMSdata3: Contains a low data to be sent to TMS1000. * TODword0: Stores bit[ 1:16] of data from TMS1000. (garbage) * TODword1: Stores bit[17:24] of data from TMS1000. (garbage) * TODword2: Stores bit[25:40] of data from TMS1000. (high data) * TODword3: Stores bit[41:56] of data from TMS1000. (low data) * TODword4: Stores 16d stop bits from TMS1000. If this register does not equal 0, sampled data is incorrect. *Task 15d Registers * DelayFlag: If DelayFlag=1, Fault Handling routine goes through a delay loop. If DelayFlag=0, Fault Handling routine goes through a normal sequence without delay. * FFault: If FFault<0 and PARITY#0, control goes to User Fault Handler at [120]. **************************************************************************************** *Subroutine Description: * DelayHalfms : Provides delay of 0.5 ms to be used for waiting 0.5 ms after * the start bit is found. * Delay1ms : Provides delay of 1 ms for sending and sampling data for TMS1000. * Delay100ms : Provides delay of 100 ms to be used to locate the start bit. * IncMP : Increments Maintenance Panel display by the value stored in IncMPCount. * IncMPTest1 : Increments Maintenance Panel display by 1's, 10's, 100's and 1000's. Breaks at count 0009, 0090, 0900 and 9000 so that the operator can check the unit's, 10's, 100's and 1000's digit display. * IncMPTest2 : Increments Maintenance Panel display by dafault value 1111d or by user-defined constant. Breaks each time the panel is incremented by that amount so that the operator can check the display. Returns when the display reaches 9999d or user-defined maximum number. * MultByTen : Multiplies a value stored in IncMPCount by 10d and stores a new value in IncMPCount. * SampleTMS : Samples 56d-bit data and the following 16d stop bits from TMS1000. Sampled data is stored in TODword0, TODword1, TODword2, TODword3 and TODword4. * SetTMS : Sends a command and data to TMS1000. Send 56d bits stored in TMSdata0, TMSdata1, TMSdata2 and TMSdata3. **************************************************************************************** *Starting the program after D0 is turned off * * When D0 is turned off and turned on back again by Alarm in SubTest 1, * the operator has to restart the program by the following method: * * 1. Hit Boot in midas display. * 2. Load EDTMP2. This is done by either; * a. Hitting Run-Prog, then hitting EDTMP2. * b. Typing EDTMP2, then hitting Read-Cmds. * * Command file EDTMP2 loads EDTMP.mb and starts the program at D0PowerOn * which is the next instruction after 'D0Off, GOTO[.]'. **************************************************************************************** *Sending a Message to TMS1000 * * A message to TMS1000 consists of 56d bits which divided into as follows: * * Bit 1-16: a password (= hex A1F5) - 16d bits * Bit 17-24: a command - 8d bits * Bit 25-40: higher 16 bits of data - 16d bits * Bit 41-56: lower 16 bits of data - 16d bits * * A message is sent bit serially (one bit per millisecond) through SetTime * input of TMS1000. TMS1000 samples input data at the end of a bit time (i.e. * TMS1000 sets the output, waits 1 millisecond, then samples the input data). * If input data contains a valid password, a command field is acted upon, * otherwise it reverts to sending TimeOfDay. **************************************************************************************** *Commands for TMS1000 * * A command field of a message sent to TMS1000 is 8-bit long and is * interpreted as follows: * * Bit 0: TimeOfDay _ Data * Bit 1: PowerOnHours _ Data * Bit 2: AlarmClockTime _ Data * Bit 3: Fudge _ Data (low 16d bits) * Bit 4: Clear AlarmClockLatch * Bit 5: Transmit PowerOnTime instead of TimeOfDay * Bit 6: Transmit AlarmClockTime instead of TimeOfDay * Bit 7: Clear PowerOnLatch (obsolete function) **************************************************************************************** *Outputs from TMS1000 * * TMS1000 broadcasts TimeOfDay (or AlarmClockTime or PowerOnTime depending on * the command received) once each second. * Output data consists of 1000d bits which is sent out bit serially (one bit * per millisecond). Bits are interpreted as follows: * * one start bit (a 1) * 56d data bits (only 32d bits are significant) * 943d stop bits (0s) **************************************************************************************** *Registers in TMS1000 * * TMS1000 contains three 32-bit registers. Each register can be set by a command. * Three registers are; * * AlarmClockTime: When TimeOfDay=AlarmClockTime, TMS1000 sends AlarmClockOn * signal to turn on D0. * PowerOnTime : incremented by 1 each second if D0 power is on. * TimeOfDay : incremented by 1 each second regardless of D0 power. **************************************************************************************** % **************************************************************************************** *INITIALIZATION: TITLE[Test Maintenance Panel]; Set[FTask, 17]; Set[MainPage, 1]; Set[SecondPage, 2]; Set[WordLoc,add[lshift[MainPage,10],100]]; ********** R-Registers: ********** * Task 0 Registers SETTASK[0]; RV[Rlink0, 20]; *subroutine return link RV[Rlink1, 21]; *subroutine return link RV[SubTest, 22]; RV[Revision, 23, 1]; *Revision 1 RV[Run-Time, 24, 454]; *Run-Time is approximately 5 min=300d sec=454b sec RV[TMSdata0, 25, 120765]; *a password (=hex A1F5) to be sent to TMS1000 RV[TMSdata1, 26]; *a command to be sent to TMS1000 RV[TMSdata2, 27]; *high data to be sent to TMS1000 RV[TMSdata3, 30]; *low data to be sent to TMS1000 RV[WhichWord, 31]; *indicates which of the 4 words to be sent to TMS1000 RV[LastWord, 32, 4]; RV[BitCount, 33]; RV[MaxBitCount, 34]; *maximum number of bits in each word RV[OutputWd, 35]; *contains a bit to be sent to RS232 output register RV[TODword0, 36]; *TODword0 stores bit[ 1:16] of data (garbage) RV[TODword1, 37]; *TODword1 stores bit[17:24] of data (garbage) RV[TODword2, 40]; *TODword2 stores bit[25:40] of data (high data) RV[TODword3, 41]; *TODword3 stores bit[41:56] of data (low data) RV[TODword4, 42]; *TODword4 stores 16 stop bits RV[BitNum, 43]; RV[BitValue, 44]; *contains a value for a bit from TMS1000 RV[DCount1, 45]; *a counter for delay loop of 0.5 ms RV[MaxDCount1, 46, 1154]; *maximum value of DCount1 RV[DCount2, 47]; *a counter for delay loop of 1 ms RV[MaxDCount2, 50, 2116]; *maximum value of DCount2 RV[DCount3, 51]; *a counter for delay loop of 100 ms RV[DCount4, 52]; *a counter for delay loop of 100 ms RV[MaxDCount4, 53, 4]; *maximum value of DCount4 RV[CurrentMPCount, 54]; *a counter for IncMP routine RV[IncMPCount, 55]; *a maximum value for CurrentMPCount RV[WhichDigit, 56]; *a counter for CheckDigit loop in IncMPTest1 routine RV[LastDigit, 57, 4]; *there are 4 digit displays on Mainteenance Panel RV[Interval, 60]; *MPanel is incremented by value of Interval at a time RV[MaxNumber, 61]; *MPanel is incremented up to this number in IncMPTest2 RV[CurrentLoopNum, 62, 0]; *a counter for IncMPTest2 routine RV[MaxLoopNum, 63, 11]; *a maximum value for CurrentLoopNum (defaults to 9d) RV[CS1, 64]; *bit 16d-31d of an instruction read from Control Store RV[CSwdAddr, 65, 1077]; *address of instruction which contains a bad parity RV[Temp, 66]; *temporary register * Task 15d Registers SETTASK[FTask]; RV[FFault, 66, 100000]; *>=0 midas overlay handles faults. <0 user does. RV[RTMP, 71]; *temporary register RV[DelayFlag, 20, 0]; *1 = delay, 0 = do not delay RV[DCount, 21, 0]; *counter for delay loop RV[DTest, 22, 0]; *to test the end of delay *The following registers hold the volatile state of the processor on a fault: RV[RXSTK,72]; *Stackpointer RV[RXPPB,73]; *Page,Parity,BootReason RV[RXCTASK,74]; *CTASK.NCIA RV[RXAPC,75]; *APCTask&APC RV[RXALU,76]; *ALU result and SALUF **************************************************************************************** *** MAIN routine: *SUBTEST 0 (Check TMS1000 routine) SETTASK[0]; ONPAGE[MainPage]; start: go: SubTest _ 0C; SendFudge: TMSdata1 _ 10000C; *send Fudge to TMS1000 TMSdata2 _ 0C; TMSdata3 _ 100000C; CALL[SetTMS]; SetAlarm1: TMSdata1 _ 20000C; *set Alarm to 0 sec TMSdata2 _ 0C; TMSdata3 _ 0C; CALL[SetTMS]; TMSdata1 _ 100000C; *TimeOfDay is first set to 0 sec TMSdata2 _ 0C; TMSdata3 _ 0C; SetTOD1: CALL[SetTMS]; Wait1min: BREAKPOINT; *OPERATOR: wait here 1 minute, then CONTINUE CheckTOD: CALL[SampleTMS]; *sample the output from TMS1000 T _ TMSdata2; *start checking if TimeOfDay is correct LU _ (TODword2) - (T); SKIP[ALU=0]; *TODword2 = TMSdata2 ? WrongTOD: GOTO[TestAgain1], BREAKPOINT; *TimeOfDay is wrong T _ TMSdata3; Temp _ T; Temp _ T _ (Temp) + (74C); LU _ (TODword3) - (T); SKIP[ALU>=0]; *TODword3 >= (TMSdata3) + (60d sec) ? SlowTOD: GOTO[TestAgain2], BREAKPOINT; *TimeOfDay not incremented or incremented too slow Temp _ T _ (Temp) + (12C); LU _ (TODword3) - (T); SKIP[ALU<0]; *TODword3 < (TMSdata3) + (60d sec) + (10d sec) ? FastTOD: GOTO[TestAgain3], BREAKPOINT; *TimeOfDay was incremented too fast CorrectTOD: BREAKPOINT; *TimeOfDay is correct LU _ TMSdata2; GOTO[SetAlarm2, ALU#0]; *TimeOfDay tested twice ? TMSdata2 _ 125C; *set TimeOfDay to 12525252525b sec and TMSdata2 _ (TMSdata2)OR(52400C); *do the test again TMSdata3 _ 125C; TMSdata3 _ (TMSdata3)OR(52400C); TestAgain1: NOP; TestAgain2: NOP; TestAgain3: GOTO[SetTOD1]; *SUBTEST 1 (Check D0 Switch routine) SubTest _ 1C; SetAlarm2: TMSdata1 _ 20000C; *set Alarm to 60 sec TMSdata2 _ 0C; TMSdata3 _ 74C; CALL[SetTMS]; SetTOD2: TMSdata1 _ 100000C; *set TimeOfDay to 0 sec TMSdata2 _ 0C; TMSdata3 _ 0C; CALL[SetTMS]; D0PowerOff: D0Off, GOTO[.]; *turn off D0 *OPERATOR: check if D0 is turned off; * D0 should be turned on by Alarm in * about 1 minutes. If turned on, boot, * then load EDTMP2 from midas *EDTMP2 makes the program restart at D0PowerOn D0PowerOn: NOP; LOADPAGE[SecondPage]; GOTOP[ResetMPanel]; *SUBTEST 2 (Check Maintenance Panel routine) ONPAGE[SecondPage]; ResetMPanel: SubTest _ 2C; CLEARMPANEL; NOP; NOP; Disp0000: BREAKPOINT; *OPERATOR: check if display is 0000, then CONTINUE CALL[IncMPTest1]; CALL[IncMPTest2]; *SUBTEST 3 (Check CS-ParErr routine) CSPETest: SubTest _ 3C; T _ 1C; *read CS1 (CS1 contains a parity bit) APC&APCTASK _ CSwdAddr; readCS; T _ CSdata; CS1 _ T; CS1 _ (CS1) XOR (1C); *complement parity bit (bit 15 of CS1) LU _ CS1; *write CS1 back to Control Store APC&APCTASK _ CSwdAddr; writeCS1; Disp8880: BREAKPOINT; *OPERATOR: after hitting CONTINUE, check if * display shows 8880 Temp _ 320C; *set DelayFlag to 1 T _ STKP; Temp _ T, STKP _ Temp; Temp _ (Temp) XOR (377C); STACK _ 1C; STKP _ Temp; SubTest _ 4C; CALL[ReadBadParity]; SubTest _ 3C; *come back here after Fault Handling routine CSPETestDone: BREAKPOINT; CS1 _ (CS1) XOR (1C); *put a good parity back LU _ CS1; APC&APCTASK _ CSwdAddr; writeCS1; GOTO[GoNextPage]; ReadBadParity: NOP, AT[1077]; *this instruction contains a bad parity, *should raise CS-ParErr signal NOP; NOP; NOP; NOP; NOP; NotCatchCSPE: BREAKPOINT, GOTO[CSPETest]; *Fault Handler has not been enabled, start *CSPETest again GoNextPage: LOADPAGE[MainPage]; Passed-EDTMP-Test: GOTOP[go], BREAKPOINT; *passed all tests *SubTest 4 (Fault Handling Routine) SETTASK[FTask]; ONPAGE[0]; RXPPB _ T, AT[112]; TestFlag: DelayFlag _ DelayFlag, goto[Normal, R EVEN], AT[121]; *test for delay NOP, AT[123]; StartDelay: NOP, AT[132]; IncCount: DelayFlag _ (DelayFlag) + (1C), AT[126]; *increment DelayFlag by 1 for delay T _ (LDF[DelayFlag,0,1]), AT[124]; *get the msb of DelayFlag DTest _ T, AT[137]; DTest _ DTest, GOTO[IncCount, R EVEN], AT[125]; *DelayFlag overflew ? DelayFlag _ 0C, AT[127]; *reset DelayFlag DCount _ (DCount) + (1C), AT[134]; *increment DCount by 1 for delay T _ (LDF[DCount,7,1]), AT[135]; *get a bit 7b of DCount DTest _ T, AT[140]; DTest _ DTest, GOTO[StartDelay, R EVEN], AT[131]; *DCount reached the maximum ? NOP, AT[133]; DCount _ 0C, AT[136]; *reset DCount Normal: RESETERRORS, AT[122]; *reset errors *Notify Task 17, address 7505 (breakpoint communication) RTMP _ (177400C), AT[113]; RTMP _ (RTMP) OR (105C), AT[114]; APC&APCTASK _ RTMP, AT[115]; RETURN, AT[116]; *The midas overlay will send control to UserFault (120) if PARITY # 0 and FFAULT<0 UserFault: RETURN, AT[120]; ********** SUBROUTINE: DelayHalfms ********** * * Delay loop of 0.5 ms * To provide 0.5 ms delay after start bit SETTASK[0]; ONPAGE[MainPage]; DelayHalfms: USECTASK; T _ APC&APCTASK; Rlink1 _ T; DCount1 _ 0C; *reset DCount1 DLoop1: DCount1 _ T _ (DCount1) + (1C); *increment DCount1 LU _ (MaxDCount1) - (T); SKIP[ALU=0]; GOTO[DLoop1]; *the end of DLoop1 ? NOP; NOP; NOP; APC&APCTASK _ Rlink1; RETURN; ********** SUBROUTINE: Delay1ms ********** * * Delay loop of 1 ms * To provide 1 ms interval for bit sampling Delay1ms: USECTASK; T _ APC&APCTASK; Rlink1 _ T; DCount2 _ 0C; *reset DCount2 DLoop2: DCount2 _ T _ (DCount2) + (1C); *increment DCount2 LU _ (MaxDCount2) - (T); SKIP[ALU=0]; GOTO[DLoop2]; *the end of DLoop2 ? NOP; NOP; NOP; APC&APCTASK _ Rlink1; RETURN; ********** SUBROUTINE: Delay100ms ********** * * Delay loop of 100 ms * To provide 100 ms delay to locate the start bit Delay100ms: USECTASK; T _ APC&APCTASK; Rlink1 _ T; DCount3 _ 0C; *reset DCount3 DCount4 _ 0C; *reset DCount4 DLoop3: DCount3 _ T _ (DCount3) + (1C); *increment DCount3 T _ (LDF[DCount3,0,1]); *get the msb of DCount3 Temp _ T; Temp _ Temp, GOTO[DLoop3, R EVEN]; *DCount3 overflew ? DCount3 _ 0C; *reset DCount3 DCount4 _ T _ (DCount4) + (1C); *increment DCount4 LU _ (MaxDCount4) - (T); SKIP[ALU=0]; *the end of DLoop1 ? GOTO[DLoop3]; APC&APCTASK _ Rlink1; RETURN; ********** SUBROUTINE: IncMP ********** * * to increment Maintenance Panel by value of IncMPCount ONPAGE[SecondPage]; IncMP: USECTASK; T _ APC&APCTASK; Rlink1 _ T; CurrentMPCount _ 0C; *reset count register IncLoop: IncMPanel; CurrentMPCount _ T _ (CurrentMPCount) + (1C); *increment CurrentMPCount LU _ (IncMPCount) - (T); GOTO[IncLoop, ALU#0]; *incremented by value of IncMPCount? APC&APCTASK _ Rlink1; RETURN; ********** SUBROUTINE: IncMPTest1 ********** * * to increment Maintenance Panel by 1's, 10's, 100's and 1000's, * Breakpoints at 0009, 0090, 0900 and 9000 to check the display: IncMPTest1: USECTASK; T _ APC&APCTASK; Rlink0 _ T; CLEARMPANEL; *reset Maintenance Panel to 0000 WhichDigit _ 0C; *reset WhichDigit IncMPCount _ 11C; *initialize IncMPCount IncLoop1: CALL[IncMP]; Display9: BREAKPOINT; *check if display is 0009, 0090, 0900 or 9000 CLEARMPANEL; CALL[MultByTen]; *multiply IncMPCount by 10d WhichDigit _ T _ (WhichDigit) + (1C); *increment WhichDigit LU _ (LastDigit) - (T); GOTO[IncLoop1, ALU#0]; *finished all digits? APC&APCTASK _ Rlink0; RETURN; ********** SUBROUTINE: IncMPTest2 ********** * * to increment Maintenance Panel by default value 1111d or * by user-defined constant up to 9999d or to user-defined * maximum number IncMPTest2: USECTASK; T _ APC&APCTASK; Rlink0 _ T; CLEARMPANEL; *reset Maintenance Panel to 0000 MaxLoopNum _ 0C; *reset MaxLoopNum CurrentLoopNum _ 0C; *reset CurrentLoopNum Interval _ 127C; *set default value for Interval (=1111d) Interval _ (Interval) OR (2000C); MaxNumber _ 17C; *set default value for MaxNumber (=9999d) MaxNumber _ (MaxNumber) OR (23400C); SetValues: BREAKPOINT; *OPERATOR: set Interval and MaxNumber here * if other than default values are * desired SetMaxLoopNum: MaxLoopNum _ (MaxLoopNum) + (1C); *increment MaxLoopNum T _ Interval; MaxNumber _ (MaxNumber) - (T); LU _ (MaxNumber) - (T); GOTO[SetMaxLoopNum, ALU>=0]; *MaxLoopNum = maximum number/Interval ? T _ (Interval); *set IncMPCount for IncMP routine IncMPCount _ (T); IncLoop2: CALL[IncMP]; CheckMPanel: BREAKPOINT; *check if display is incremented by Interval CurrentLoopNum _ T _ (CurrentLoopNum) + (1C); *increment CurrentLoopNum LU _ (MaxLoopNum) - (T); GOTO[IncLoop2, ALU#0]; *finished IncLoop2 ? LU _ (MaxNumber); *more than Interval left ? GOTO[Ret, ALU=0]; T _ (MaxNumber); IncMPCount _ (T); CALL[IncMP]; CheckMaxNumber: BREAKPOINT; *check if display shows maximum number Ret: APC&APCTASK _ Rlink0; RETURN; ********** SUBROUTINE: MultByTen ********** * * to multiply IncMPCount by 10d MultByTen: USECTASK; T _ APC&APCTASK; Rlink1 _ T; T _ LSH[IncMPCount, 3]; *multiply IncMPCount by 8d IncMPCount _ (LSH[IncMPCount, 1]) + (T); *multiply IncMPCount by 2 and add to T APC&APCTASK _ Rlink1; RETURN; ********** SUBROUTINE: SampleTMS ********** * * to sample data on TimeOut output from TMS1000 ONPAGE[MainPage]; SampleTMS: USECTASK; T _ APC&APCTASK; Rlink0 _ T; StartSample: BitNum _ 0C; *reset BitNum BitValue _ 0C; *reset BitValue TODword0 _ 0C; *TODword0 stores bit[ 1:16] of data TODword1 _ 0C; *TODword1 stores bit[17:24] of data TODword2 _ 0C; *TODword2 stores bit[25:40] of data TODword3 _ 0C; *TODword3 stores bit[41:56] of data TODword4 _ 0C; *TODword4 stores 16d stop bits Search1: GOTO[Got1, TimeOut]; *look for 1 GOTO[Search1]; Got1: CALL[Delay100ms]; *wait 100d ms Another1: GOTO[GotStartBit, TimeOut]; *look for another 1 (start bit) GOTO[Another1]; GotStartBit: CALL[DelayHalfms]; *wait 0.5 ms NOP; BitLoop: CALL[Delay1ms]; *wait 1 ms SKIP[TimeOut]; *sample a bit GOTO[IncBitNum]; BitValue _ 1C; IncBitNum: BitNum _ (BitNum) + (1C); *increment BitNum LU _ (BitNum) - (21C); GOTO[Data0, ALU<0]; *is this bit 1d-16d of data (garbage) ? LU _ (BitNum) - (31C); GOTO[Data1, ALU<0]; *is this bit 17d-24d of data (garbage) ? LU _ (BitNum) - (51C); GOTO[Data2, ALU<0]; *is this bit 25d-40d of data (high data) ? LU _ (BitNum) - (71C); DBLGOTO[Data3, Data4, ALU<0]; *is this bit 41d-56d of data (low data) ? *if not, this is a stop bit Data0: TODword0 _ LSH[TODword0, 1]; T _ BitValue; TODword0 _ (TODword0) + (T); NOP; NOP; NOP; NOP; NOP; GOTO[NextWord1]; Data1: TODword1 _ LSH[TODword1, 1]; T _ BitValue; TODword1 _ (TODword1) + (T); NOP; NOP; NOP; NOP; NextWord1: GOTO[NextWord2]; Data2: TODword2 _ LSH[TODword2, 1]; T _ BitValue; TODword2 _ (TODword2) + (T); NOP; NOP; NOP; NextWord2: GOTO[NextWord3]; Data3: TODword3 _ LSH[TODword3, 1]; T _ BitValue; TODword3 _ (TODword3) + (T); NOP; NOP; NextWord3: GOTO[ResetBit]; Data4: TODword4 _ LSH[TODword4, 1]; T _ BitValue; TODword4 _ (TODword4) + (T); LU _ (BitNum) - (110C); GOTO[SampleDone, ALU=0]; NOP; ResetBit: BitValue _ 0C; *reset BitValue to prepare another sampling GOTO[BitLoop]; SampleDone: LU _ TODword4; SKIP[ALU=0]; *got 16d stop bits ? WrongData: GOTO[StartSample], BREAKPOINT; *data is wrong APC&APCTASK _ Rlink0; RETURN; ********** SUBROUTINE: SetTMS ********** * * to send a command and data to TMS1000 SetTMS: USECTASK; T _ APC&APCTASK; Rlink0 _ T; WhichWord _ 0C; *reset WhichWord Find1: GOTO[Found1, TimeOut]; *look for 1 GOTO[Find1]; Found1: CALL[Delay100ms]; *wait 100d ms OneMore1: GOTO[FoundStart, TimeOut]; *look for another 1 (start bit) GOTO[OneMore1]; FoundStart: CALL[DelayHalfms]; *wait 0.5 ms NOP; WordLoop: DISPATCH[WhichWord, 16, 2]; *decide which word to transmit DISP[word0]; Word0: GOTO[XmitWord], T_TMSdata0, AT[WordLoc, 0]; Word1: GOTO[XmitWord], T_TMSdata1, AT[WordLoc, 1]; Word2: GOTO[XmitWord], T_TMSdata2, AT[WordLoc, 2]; Word3: GOTO[XmitWord], T_TMSdata3, AT[WordLoc, 3]; XmitWord: OutputWd _ T; BitCount _ 0C; *reset CurrentBitCount lu _ (WhichWord) - (1C); GOTO[CommandWord, ALU=0]; *is it a command word ? DataWord: MaxBitCount _ 20C; *data word is 16d-bit long GOTO[XmitBitLoop]; CommandWord: MaxBitCount _ 10C; *command word is 8d-bit long XmitBitLoop: CALL[Delay1ms]; *wait 1 ms T _ RSH[OutputWd, 13]; *load OutputWd[0] into RS232OUT[13b] Temp _ T; Temp _ T _ (Temp) AND (20C); RS232 _ T; OutputWd _ LSH[OutputWd, 1]; *get next bit BitCount _ T _ (BitCount) + (1C); *increment BitCount lu _ (MaxBitCount) - (T); GOTO[XmitBitLoop, ALU#0]; *all bits of a word transmitted ? WhichWord _ T _ (WhichWord) + (1C); *increment WhichWord lu _ (LastWord) - (T); GOTO[WordLoop, ALU#0]; *all 4 words transmitted ? APC&APCTASK _ Rlink0; RETURN; END; *to end the MAIN routine (1270)