; BCPL Microcode for running Diablo Port Audio Terminal
; Last modified by L. Stewart: March 15, 1980 3:25 PM
; Microcode command file for Audio Terminal
; MU/l ATmc.mu
; PackMu ATmc.mb ATmc.br 160376 // Alto II
; PackMu ATmc.mb ATmc.br 177376 // Alto I
; Task assignments and BCPL emulator-routine entry points.
; Alto II version
%17,1777,0, Novem, L1, L2, L3, L4, L5, L6, L7, MRT, DWT, CURT, DHT, DVT, L15;
; Alto I version
; %17,1777,0, Novem, L1, L2, L3, L4, L5, L6, L7, MRT, L11, L12, L13, L14, L15;
%1,1777,20,Start;
%1,1777,21,AudioInit;
%1,1777,22,AudioStart;
%1,1777,23,AudioEnqueue;
#AltoConsts23.mu;
L1: TASK, :L1;
L2: TASK, :L2;
L3: TASK, :L3;
L4: TASK, :L4;
L5: TASK, :L5;
L6: TASK, :L6;
L7: TASK, :L7;
; L10: TASK, :L10;Memory refresh task
; For Alto II, comment out L11, L12, L13, and L 14
; L11: TASK, :L11;Display Word Task
; L12: TASK, :L12;Cursor Task
; L13: TASK, :L13;Display horizontal task
; L14: TASK, :L14;Display Vertical Task
L15: TASK, :L15;
; For Alto I
; #CATMRT.mu;contains MRT
; For Alto II
#CATIIMRT.mu;contains MRT
#GateDisplay.mu;contains DHT, DVT, CURT, DWT
;BCPL Emulator routines (via JMPRAM)
; Arg1 in AC0
; Ram LocationRoutine
;20SetBLV -- Silent boot code (doesn’t do the StartIO) for BCPL
;21AudioInit
;22AudioStart
;23AudioEnqueue
; Register definitions
$AC0$R3;
$AC3$R0;
$LastL$R40;
$IACB$R71;input Audio Control Block
$IPtr$R72;data block pointer
$ICount$R73;word count
$RData$R14;input assembly register
$OACB$R74;output Audio Control Block
$OPtr$R75;
$OCount$R76;
$WData$R15;output word register
$NCount$R60;
; Temporaries
$Temp2$R63;
$Temp$R16;In Data
; Constants
$OREMask$4000;
$DataMask$170000;
$Strobe$1;command word strobe
; Silent boot interface
TStart:TASK;
NStart:NOP;
Novem:SWMODE;
1Start::Start;
Start:RMR ← AC0, :Novem;Set RMR -- classical location for it
; This must run with MRT disabled (i.e. running in ROM)
AudioInit:L ← 0;
NCount ← L;
IACB ← L;
OACB ← L;
OCount ← L;
ICount ← L,TASK;
WData ← L;
T ← 177000;Clear ready bit in hardware
MAR ← 16 + T;
L ← Strobe;
MD ← LastL;
MAR ← 16 + T;
L ← 0, TASK;
MD ← LastL,:NStart;
; On entry to AudioEnqueue, AC0 points to the new ACB, AC3 to the old
!1,2,Fail, Link;
AudioEnqueue:
MAR ← AC3;
L ← 0;
SINK ← MD,BUS=0;
MAR ← AC3+1,:Fail;!1,2,Fail, Link;
Link:NOP;
MD ← AC0,TASK,:NStart;
Fail:AC0 ← L,TASK,:NStart;
; AudioStart expects AC0 to be IACB and AC3 to be OACB.
; n. b. A 0 starting value means none...
;
; Format of an ACB (Even word aligned)
; word 0: FlagsGoes non-zero on completion
; word 1: Next ACBpointer to next ACB
; word 2:Pointerpointer to data block
; word 3:Countsize of block (in words)
AudioStart:L ← AC0;
IACB ← L;
L ← AC3;
OACB ← L;
L ← 0;
ICount ← L,TASK;
OCount ← L,:Novem;
; This code runs as part of MRT
!1,2,Ready,NotYet;
AudioTest:T ← 177000;
MAR ← 30 + T;
T ← OREMask;two cycles here! (compute portout?)
L ← T ← MD AND T;
L ← DataMask AND T, SH=0;
Temp2 ← L,:Ready;!1,2,Ready,NotYet;
NotYet:TASK;
NOP,:ATDone;back to MRT
!1,2,RightB,LeftB;
!1,2,IBMore,IBDone;
!1,2,ICMore,ICDone;
!1,2,OBMore,OBDone;
!1,2,OCMore,OCDone;
Ready:; write data
T ← 177000;
MAR ← 16 + T;
T ← 177400;
L ← WData AND T;
MD ← LastL, TASK;
Temp ← L;
; Strobe it in
T ← 177000;
MAR ← 16 + T;
L ← Temp + 1;we know 1 is Strobe
MD ← LastL;
; Now read next nibble
MAR ← 30 + T;#177030
T ← DataMask;
L ← MD AND T,TASK;
Temp ← L;
; Turn off strobe
T ← 177000;
MAR ← 16 + T;
T ← 177400;
L ← WData AND T, TASK;
MD ← LastL;
L ← Temp, TASK;
Temp ← L RSH 1;
L ← Temp, TASK;
Temp ← L RSH 1;
L ← Temp, TASK;
Temp ← L RSH 1;
L ← Temp, TASK;
Temp ← L RSH 1;
T ← Temp;
L ← Temp2 OR T, TASK;
Temp ← L;
; Now input byte is left justified in Temp
SINK ← NCount, BUS=0;
L ← 0,:RightB;!1,2,RightB,LeftB;
;Assume Temp holds left justified nibble.
; Left Byte
LeftB:L ← ALLONES;
NCount ← L;
L ← Temp, TASK;
RData ← L LCY 8;
L ← WData,TASK;swab WData
WData ← L LCY 8,:ATDone;
; Right byte
RightB:NCount ← L;
T ← RData;
L ← Temp OR T, TASK;
RData ← L LCY 8,:WTIn;
; Once per word code (250 microseconds)
WTIn:L ← ICount-1, BUS=0, TASK;decrement input count
ICount ← L,:IBMore;!1,2,IBMore,IBDone; (input block)
; Block completion, input
IBDone:MAR ← L ← IACB,BUS=0;
T ← 2,:ICMore;!1,2,ICMore,ICDone; (input chain)
ICMore:MD ← LastL;
L ← MD;
MAR ← LastL+T;
IACB ← L;
;predecrement ptr because we increment it before use
L ← MD - 1;
;we test count for zero before decrementing it
;since we are starting a new block, ICount must be decremented
;to account for the store in IBMore below.
T ← MD - 1;
IPtr ← L, L ← T, TASK;
ICount ← L,: IBMore;
ICDone:L ← 0, TASK;leave count at 0
ICount ← L,:WTOut;
IBMore:MAR ← L ← IPtr+1;we increment ptr before use
IPtr ← L;
L ← RData, TASK;
MD ← LastL,:WTOut;
WTOut:L ← OCount-1, BUS=0, TASK;decrement output count
OCount ← L,:OBMore;!1,2,OBMore,OBDone;
; Block completion, output
OBDone:MAR ← L ← OACB,BUS=0;
T ← 2,:OCMore;!1,2,OCMore,OCDone;
OCMore:MD ← LastL;
L ← MD;
MAR ← LastL+T;
OACB ← L;
;predecrement ptr because we increment it before use
L ← MD - 1;
;we test count for zero before decrementing it
;OCount must be decremented to account for the fetch in
;OBMore below.
T ← MD - 1;
OPtr ← L, L ← T, TASK;
OCount ← L,: OBMore;
OCDone:L ← 0;
WData ← 0, TASK;
OCount ← L,:ATDone;leave count at 0
OBMore:MAR ← L ← OPtr+1;
OPtr ← L;
L ← MD, TASK;
WData ← L,:ATDone;
;; December 24, 1979 5:59 PM L. Stewart. created file
;; December 25, 1979 8:18 PM L. Stewart. task code
;; December 28, 1979 10:43 PM L. Stewart. new design