%
****************************************************************************************
*** 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