* WARNING: * LOADTIMERs must be 7 instructions apart insert[JasHalftone]; *which inserts d0lang and GlobalDefs TITLE [JasMC -- May 19, 1980 10:07 AM]; * NOTE: labels are named to match Alto microcode labels * Three timers are used: * ScanStartTimer: ticks once per scanline, STARTs ScanCBTimer * ScanCBTimer: processes a control block, STARTs PixelTimer * PixelTimer: reads in bytes, STARTs ScanCBTimer SET TASK[TTask]; * Registers in Timer Task * 44-56,67-70 available RV[ScanTime,44]; *526 (contains wait count in ticks) RV[ScanTimeHi,45]; *0 RV[ScanCBHead,46]; *736; and 737 is StartCommand RV[ScanCBHeadHi,47]; RV[TimerData,51]; *general temporary RV[PrinterControl,52]; *used in ScanStartTimer,PixelTimer *ScanStartTimer names RV[ScanWait,50]; *temporary used at top of ScanStartTimer RV[StatusReg,53]; *used in ScanCBTimer *PixelTimer names RV[ScanData,50]; *used in PixelTimer RV[ScanBuffer,54]; RV[ScanBufferHi,55]; RV[StoreCount,56]; RV[StepperState,70]; RV[PixelTimerSet,67]; *used in PixelTimer,ScanCBTimer * At locations SET [JasmineOn,ADD[LSHIFT[InitPage,10],010]]; * Starting location SET [JasmineOff,ADD[LSHIFT[InitPage,10],011]]; * Starting location SET [JasminePulse,ADD[LSHIFT[InitPage,10],012]]; * Starting location SET [StorePrinter,ADD[LSHIFT[InitPage,10],013]]; * Starting location SET [ReadPrinter,ADD[LSHIFT[InitPage,10],014]]; * Starting location SET [bLoc,ADD[LSHIFT[InitPage,10],200]]; SET [cLoc,ADD[LSHIFT[InitPage,10],220]]; SET [fLoc,ADD[LSHIFT[InitPage,10],240]]; SET [tLoc,ADD[LSHIFT[InitPage,10],260]]; ONPAGE[InitPage]; * EMULATOR LEVEL STUFF (can't use Timer registers!!!!) RV[EmulatorTemp,40]; *initialization: start up InitTimer, state: 5,data: 2, slot: 10B; AT[JasmineOn], EmulatorTemp _ (50000C); EmulatorTemp _ (EmulatorTemp) + (50C); LOADTIMER[EmulatorTemp]; NNNopReturn: NOP; NNopReturn: NOP; NopReturn: NOP; RETURN; *shut down all timers AT[JasmineOff],EmulatorTemp _ (12C),GOTOP[JasmineOff2]; JasmineOff2: DISPATCH[EmulatorTemp,13,1]; EmulatorTemp _ (EmulatorTemp) OR (40000C),DISP[timer0]; timer0: LOADTIMER[EmulatorTemp],GOTO[TurnOff],AT[tLoc,0]; timer1: RETURN,AT[tLoc,1]; TurnOff: EmulatorTemp _ (EmulatorTemp) + (2C); NOP; NOP; NOP; GOTO[JasmineOff2]; AT[JasminePulse],Stack _ (Stack) XOR (177C); PRINTER _ Stack; Stack _ (Stack) XOR (1000C); PRINTER _ Stack; Stack _ (Stack) XOR (1000C); AT[StorePrinter],PRINTER _ Stack&-1,RETURN; AT[ReadPrinter],T_PRINTER; Stack&+1 _ T,RETURN; * 1 alto tick = 38.08 usec * 1 D0 tick = 6.4 usec * approx conversion: D0Ticks = 6*AltoTicks - (3*AltoTicks)/64 * timer format: state: 0-3, data: 4-11, slot: 12-15 MRTloop: PFetch1[ScanTime,ScanWait,0]; *this runs 25 instrs = 5 usecs *load up ScanCBTimer with state: 5,data: 2,slot: 14B TimerData _ 50000C; *state=5, highdata=0 TimerData _ (TimerData)+(54C); *lowdata = 2,slot=14B 5 instrs T _ ScanWait; LOADTIMER[TimerData]; ScanWait _ (LSH[ScanWait,1])+T; *3 T _ (RSH[ScanWait,6]); ScanWait _ (LSH[ScanWait,1])-T; * load slow timer with high 7 bits T _ (160400C); *slot=16B,state=1 15 instrs T _ (LDF[ScanWait,1,7]) + T; TimerData _ T; TimerData _ (LCY[TimerData,4]); *get into appropriate fields LOADTIMER[TimerData]; PFetch1[ScanCBHead,PrinterControl,1]; *read PrinterControl; * load fast timer with low 8 bits T _ (154400C); *slot=15B,state=11B T _ (LDF[ScanWait,10,10]) + T;*10 instrs TimerData _ T; TimerData _ (LCY[TimerData,4]); *get into appropriate fields PrinterControl _ (PrinterControl) XOR (177C); *invert command bits PRINTER _ PrinterControl; *<0> 20 instrs ADDTOTIMER[TimerData]; *command output format: * 0-5) don't care, 6) command enable, 7) 0, 8) don't care, 9-15) command startScan: *quick like a bunny pulse start, then (whew!) you can TASK PrinterControl _ (PrinterControl) XOR (1000C); PRINTER _ PrinterControl; *<1> PrinterControl _ (PrinterControl) XOR (1000C); PRINTER _ PrinterControl,RETURN; *<0> 25 instrs * PrinterControl _ (400C); *FIFOShift=0,Alto8=0,EnableInput=1 * PRINTER _ PrinterControl,RETURN; *ScanCBTimer starts here * started by ScanStartTimer * started by PixelTimer when StoreCount goes to 0 ScanCBLoop: LU _ ScanBuffer; StatusReg _ (zero) - 1,GOTO[noCurrent,ALU=0]; *there is a current scan buffer: * assign status and dequeue * if DataLate, clear CB queue haveCurrent: PFetch1[ScanCBHead,ScanBuffer,0];* 5 instrs LU _ StoreCount; LU _ ScanBuffer,GOTO[pixelTimerEntry,ALU=0]; *interlock PStore1[ScanBuffer,StoreCount,1]; StatusReg _ (StatusReg)-1; *StatusDATALATE; *smash PixelTimer, so it won't run PixelTimerSet _ 40000C; *state=4(idle),highdata=0 PixelTimerSet _ (PixelTimerSet)+(12C); *lowdata = 0,slot=12B LOADTIMER[PixelTimerSet]; PStore1[ScanBuffer,StatusReg,2]; ScanBuffer _ (0C); StoreCount _ (0C); PStore1[ScanCBHead,ScanBuffer,0],RETURN; pixelTimerEntry: *no error: pixel task has completed *if emulator has stored 0 into ScanCBHead, just return GOTO[NNNopReturn,ALU=0]; *already set to idle PStore1[ScanBuffer,StatusReg,2]; *StatusReg = StatusDONE PFetch1[ScanBuffer,ScanBuffer,0]; LU _ ScanBuffer; PStore1[ScanCBHead,ScanBuffer,0],DBLGOTO[haveHead,noHead,ALU#0]; *check for available input buffer noCurrent: PFetch1[ScanCBHead,ScanBuffer,0]; LU _ ScanBuffer; StoreCount _ 0C,DBLGOTO[haveHead,noHead,ALU#0]; * 10 instrs noHead: RETURN; %dummy code for recording PC value when ScanCBHead^=0 LOADPAGE[TimerInitPage]; T _ STKP,GOTOP[noHeadFinish]; ONPAGE[TimerInitPage]; noHeadFinish: *store mesa PC in bank 4 TimerData _ T; *T has STKP ScanBuffer _ (30C); *mesa PC STKP _ ScanBuffer; ScanTimeHi _ T _ (4C); ScanTimeHi _ (LSH[ScanTimeHi,10]) + T; T _ Stack&+1; ScanBuffer _ T; PFetch1[ScanTimeHi,ScanWait,0]; T _ Stack; ScanBufferHi _ T; ScanWait _ T _ (ScanWait) + (2C); PStore1[ScanTimeHi,ScanWait,0]; NOP; PStore2[ScanTimeHi,ScanBuffer]; TimerData _ (TimerData) XOR (377C); STKP _ TimerData; ScanBuffer _ (0C); ScanBufferHi _ (0C); ScanTimeHi _ (0C); TimerData _ (24C); T _ (TimerData)+(400C); PFetch1[ScanBuffer,TimerData]; TimerData _ (TimerData) XOR (10C); PStore1[ScanBuffer,TimerData],RETURN; *won't always work, but who cares? ONPAGE[InitPage]; % *ScanCB structure: * link * command (Read,Delay,Forward,Back) * status/count (negative = status, pos=count) * buffer haveHead: LU _ ScanBuffer;*prev may have been PStore1[ScanCBHead,ScanBuffer,0] PFetch1[ScanBuffer,TimerData,1]; LU _ DISPATCH[TimerData,16,2]; DISP[CommandREAD]; CommandREAD: *load PixelTimer with state: 5,data: 2, slot: 12B PixelTimerSet _ 50000C,AT[cLoc,0]; *state=5 highdata = 0; *15 instrs PixelTimerSet _ (PixelTimerSet)+(52C); *lowdata=2,slot=12; LOADTIMER[PixelTimerSet]; PFetch1[ScanBuffer,StoreCount,2]; PFetch1[ScanBuffer,ScanBuffer,3]; PrinterControl _ (400C); *enable input PRINTER _ PrinterControl,RETURN; * MOTORCTL=5 *<000000><00> *0101xxxx = disabled = 120 *BUT: we need to invert the low order 7 bits (a la Alto) CommandBACK: DISPATCH[StepperState,16,2],AT[cLoc,3]; *15 instrs DISP[bstep0];*FIFOShft=0,Alto8=0,EnableInput=0 *inverted sequence is: 2,3,1,0 bstep0: StepperState _ (56C),GOTO[stepDone],AT[bLoc,0]; bstep1: StepperState _ (54C),GOTO[stepDone],AT[bLoc,1]; bstep2: StepperState _ (57C),GOTO[stepDone],AT[bLoc,2]; bstep3: StepperState _ (55C),GOTO[stepDone],AT[bLoc,3]; CommandFORWARD: DISPATCH[StepperState,16,2],AT[cLoc,2]; *15 instrs DISP[fstep0];*FIFOShft=0,Alto8=0,EnableInput=0 *inverted sequence is: 0,1,3,2 fstep0: StepperState _ (55C),GOTO[stepDone],AT[fLoc,0]; fstep1: StepperState _ (57C),GOTO[stepDone],AT[fLoc,1]; fstep2: StepperState _ (54C),GOTO[stepDone],AT[fLoc,2]; fstep3: StepperState _ (56C),GOTO[stepDone],AT[fLoc,3]; stepDone: PRINTER _ StepperState; *<0> StepperState _ (StepperState) XOR (1000C); PRINTER _ StepperState; *<1> 20 instrs StepperState _ (StepperState) XOR (1000C); PRINTER _ StepperState; *<0> * PRINTER _ PrinterControl; *EnableInput=1 *take CB off queue, mark DONE *DELAY: wait until next start pulse (just throw command away) CommandDELAY: AT[cLoc,1],PStore1[ScanBuffer,StatusReg,2];*StatusReg=StatusDONE PFetch1[ScanBuffer,TimerData,0]; *link ScanBuffer _ 0C; LU _ TimerData; PStore1[ScanCBHead,TimerData,0],RETURN; *25 instrs JasmineInit: *set up ScanStartTimer to run TimerData _ (50000C); *state=5, highdata=0 TimerData _ (TimerData) + (56C); *lowdata=2,slot=16 LOADTIMER[TimerData]; *first time initialization (min of 4 instructions) T _ (10000C); FFault _ (FFault) AND NOT T; ScanTimeHi _ (0C); ScanTime _ 400C; ScanTime _ (ScanTime) + (126C); ScanCBHeadHi _ 0C; ScanCBHead _ 400C; ScanCBHead _ (ScanCBHead) + (336C); ScanBuffer _ (0C); StoreCount _ (0C),RETURN; *PixelTimer starts here *between shift out pulse and data read, leave a minimum of 850 nsecs * PRINTER input format is normally: * 0) FIFOShift=0, 1-5)unused, 6)Alto8=0, 7)InputEnable=1, 8-15) FIFOData * shift out by dropping FIFOShift to 0, and then back high checkInput: LU _ (StoreCount)-1,DBLGOTO[oddByte,evenByte,R ODD]; evenByte: T _ PRINTER,GOTO[noCount,ALU<0];*really StoreCount<=0 PrinterControl _ (100400C),GOTO[doWord,ALU<0]; noWord: ADDTOTIMER[PixelTimerSet],GOTO[NNNopReturn]; doWord: PRINTER _ PrinterControl; *5 instrs PrinterControl _ (400C); PRINTER _ PrinterControl; ScanData _ T; StoreCount _ (StoreCount)-1; ScanData _ LSH[ScanData,10],GOTO[read1,ALU#0];*10 instrs done1: ADDTOTIMER[PixelTimerSet],GOTO[NNNopReturn]; oddByte: NOP; read1: T _ PRINTER; PrinterControl _ (100400C),GOTO[doWord1,ALU<0]; noWord1: ADDTOTIMER[PixelTimerSet],GOTO[NNNopReturn]; doWord1: PRINTER _ PrinterControl; PrinterControl _ (400C); PRINTER _ PrinterControl; TimerData _ (377C); T _ (TimerData) AND T; *15 instrs ADDTOTIMER[PixelTimerSet]; LU _ ScanBuffer; ScanData _ (ScanData) + T,GOTO[noBuffer1,ALU=0]; T _ (zero) - 1; ScanData _ (ScanData) XOR T; PStore1[ScanBuffer,ScanData,0]; *20 instrs ScanBuffer _ (ScanBuffer) + 1; noBuffer1: StoreCount _ (StoreCount)-1,RETURN; *come here when storecount is exhausted: * process next CB *need to do something if requested read was odd number of bytes noCount: StatusReg _ (zero)-1,GOTOP[haveCurrent]; * catching the wakeup * slot 17 (AT[x,0]) = refresh * slot 6 (AT[x,11]) = ether LOADPAGE[InitPage], AT[TimerTable,01]; *slot 16=ScanStartTimer GOTOP[MRTloop], AT[TimerTable,12]; *slot 5 (unused) LOADPAGE[InitPage], AT[TimerTable,03]; *slot 14=ScanCBTimer GOTOP[ScanCBloop], AT[TimerTable,04]; *slot 13 (unused) LOADPAGE[InitPage], AT[TimerTable,05]; *slot 12=PixelTimer GOTOP[checkInput], AT[TimerTable,06]; *slot 11 (unused) LOADPAGE[InitPage], AT[TimerTable,07]; *slot 10=InitTimer GOTOP[JasmineInit], AT[TimerTable,10]; *slot 7 (unused) END; e6(0,4384)(1,11968)\f1 1114b10B57b12B57b12B57b11B259b29B255b22B470b12B32b11B421b8B17b9B177b9B110b9B176b10B197b10B1b10B353b6B24b10B1b97B1b104B217b10B156b35B820i710b34B19I265b1B69b1B71b10B35b1B14b1B361b10B2b10B355b10B2b10B1b1B463b9B96b43B107b10B171b10B2b13B201b43B196b25B424b31B11b1B36b9B146b10B8b31B11b1B96b31B11b1B135b10B2b28B146b11B72b6B2b1B173b1B121b22B95b19B99b18B99b17B (1795)\f1