; SlotMc.mu - Microcode for Slot, TriCon ;MICROCODE FOR 64K SLOT CARD ; ; This stuff uses task 1; BLV 177775 (bit 14) ; (disk uses 3,15; BLV 77767 (bits 0, 12)) ; Auto-Boot feature means start emulator in RAM BLV 177776 ; "and" all these together to get 77764 ;Put in packed RAM format with BLV as version: ; PackMu SlotMc.Mb SlotMc.Br 77764 ; %0, 1777, 1, LOC1; Slot start $LREG $R40; #TriConMc.Mu; ; Location 720 points to a control block: ; ;0 blank bit 14; COM bit 2 ; COM: BeamOn=0, Status=1, Reset=2, Print=3 ;1 BlowUp bit -- for factor of 2 increase in each direction ; LastPage bit -- marks this command as the last page ; invert bit -- inverts the page ; bitsPerLine bit 13 -- for servoing the scan motor ; ;2 bottomMargin word -- # bits at bottom margin: divides by 16 ;3 scanLineWc word -- # words in scan line /2 ;4 leftMargin word -- # scans before imaging ;5 scansPerPage word -- total number of scan lines of data ;6 bufferPtr word -- pointer to first buffer -- must be even ; buffers are linked by next=current!-1 ;7 scanLineWcInc -- how far (in words) to advance within buffer to find ; next scan line -- must be even ;10 scansPerBuf word -- number of scan lines in each buffer ;11 currentBuff word -- points to current buffer ;12 currentLine -- counts up to scansPerPage ;13 status: ; blank bit 9 ; Wait bit -- 0 true ; PaperJam bit -- 0 true ; AddPaper bit -- 0 true ; SelectB bit ; Ready bit ; LineSync bit ; PageSync bit -- 0 true ;So processing of buffer pointed to by b is: ; currentBuff=b ; for i=0 to scansPerBuff-1 do ; Send data starting at b+i*scanLineWcInc for scanLineWc*2 words ; b=b!-1 ; REGISTER DEFINITIONS FOR SLOT ; SLOT DEVICE DEFINITIONS ;F1's $SLOTResetDone $L16015, 00000, 000000; non-data $SLOTSTOP $L16016, 00000, 000000; non-data $SLOTBEAM $L16017, 00000, 000000; non-data ;F2's $SLOTBLOCK $L24010, 00000, 000000; non-data $SLOTDATA $L26011, 00000, 124000; non-data $SLOTADDR $L26012, 00000, 124000; destination $SLOTSERVO $L26013, 00000, 124000; destination $SLOTPRINT $L24014, 00000, 000000; non-data $SLOTRESET $L24015, 00000, 000000; non-data $SLOTDISABLE $L24016, 00000, 000000; non-data $SLOTSTATUS $L24017, 00000, 000000; non-data $DCBADDR$R41; Normally points to currentLine entry $PBM $R42; Bottom margin $PDWC $R43; scanLineWc (in double words) $LM $R44; Left margin $MSL $R45; scansPerPage $PBBA $R46; Current print buffer address $PBSLI $R47; scanLineWcInc $PBL $R50; Scan lines/buffer $InitOnesPairs $R51; How many pairs of ones to init the buffers with $CSA $R53; CURRENT SCAN ADDRESS $CRC $R54; FIRST SERVO COUNT THEN CURRENT RING COUNT $CLA $R55; CURRENT LAST ADDRESS $CSBA $R52; CURRENT SCAN BASE ADDRESS $InitReturn $R52; Init return BUS byte with sign bit for which buffer $Command $R56; $InitPairs $R56; InitBuffers' pair counter ; Constants known elsewhere by other names: $600 $600; $12 $12; ; PREDEFINITIONS !3,4,BEAMON,SLOTSTAT,RESETSLOT,PRINT; !1,2,Invert,InitBuffers; !1,2,LOC1+1,CKPAGE; !1,2,STARTPG,PAGESYNC; !1,2,MARWAIT,MARDONE; !1,2,MOREWORDS,LASTWORDS; !1,2,InvertNextWord,NEXTWORD; !1,2,InvertMoreWords,InvertLastWords; !1,2,BUFFEROK,RESETBUFFER; !1,2,NEXTLINE,LINESDONE; !1,2,InitZeroLoop,InitBufferDone; !1,2,InitDone,InitSecond; !1,2,PAGEWAIT,PAGEDONE; !1,2,RET0,RET1; !1,2,InitOnes,InitZero; ; THE CODE LOC1: T_600; Task starts here on StartIO LOC1+1: L_100+T,TASK; DCBADDR_L; ** Manufacture #720 ; T_20; MAR_L_DCBADDR+T; Get pointer to DCB from @(720) NOP; L_MD,TASK; DCBADDR_L; ; MAR_DCBADDR; T_3; L_MD AND T; Mask command to 2 bits T_MD; Command_L,L_T,TASK; Get command CRC_L; Get servo count etc. ; MAR_T_DCBADDR; Clear command to indicate taken L_2+T; DCBADDR_L,TASK; MD_0; ; MAR_T_DCBADDR; @(#720)+2 L_2+T; DCBADDR_L; T_MD; Get bottomMargin L_MD; Get scanLineWc PDWC_L; L_177777-T,TASK; PBM_L; ; T_2; L_PDWC-T,TASK; PDWC_L; ; MAR_T_DCBADDR; @(#720)+4 L_2+T; DCBADDR_L; L_MD; Get leftMargin T_MD; Get scansPerPage LM_L,L_T,TASK; MSL_L; ; MAR_T_DCBADDR; @(#720)+6 L_2+T; DCBADDR_L; L_MD; Get bufferPtr T_MD; Get scanLineWcInc PBBA_L,L_T,TASK; PBSLI_L; ; MAR_T_DCBADDR; @(#720)+10 L_2+T; DCBADDR_L; L_MD,TASK; Get scansPerBuff PBL_L; ; SINK_Command,BUS; Branch on command T_ CRC, :BEAMON; [BEAMON,SLOTSTAT,RESETSLOT,PRINT] ; (T_ CRC is for PRINT - reduces time between TASKs) ; ; BEAMON: SLOTSERVO_CRC; SLOTBEAM; SLOTResetDone, :SLOTSTAT; ; RESETSLOT: SLOTRESET; SLOTSTOP,:SLOTSTAT; Stop printing ; SLOTSTAT: MAR_DCBADDR+1,SLOTDISABLE; Return status L_377,SLOTSTATUS; TASK; MD_LREG,:LOC1; ** Task stops here until new StartIO ; ; PRINT: L_ 20000 AND T; T has CRC, Test the Invert bit SLOTBEAM, SH=0; InitOnesPairs_ L, SLOTPRINT, TASK, :Invert; [Invert, InitBuffers] Invert: NOP; T_ CRC; T_ 177577 +T+1; i.e. T_ CRC - 128 L_ 17777 ANDT; Just bitsPerLine - 128 MTEMP_ L RSH 1; divide by 32, truncating L_ MTEMP, TASK; InitOnesPairs_ L; L_ InitOnesPairs; MTEMP_ L RSH 1; L_ MTEMP; MTEMP_ L RSH 1; L_ MTEMP, TASK; InitOnesPairs_ L; L_ InitOnesPairs; MTEMP_ L RSH 1; L_ MTEMP; T_ 0, MTEMP_ L RSH 1; L_ MTEMP; L_ T, InitOnesPairs_ L, TASK, :InitBuffers; (L_ 0) ; RET0: SLOTSERVO_CRC; ; PAGESYNC: T_12,SLOTBLOCK; MAR_DCBADDR-T; WAIT FOR PAGE SYNC & MARGIN T_ONE; L_ONE AND T,SLOTSTATUS; SINK_MD,BUS=0; TEST FOR NO NEW COMMAND T_600,:LOC1+1; IFSO GOTO CKPAGE ; CKPAGE: SH=0,TASK; CHECK PAGE NOT STARTED :STARTPG; IFSO GOTO PAGESYNC ; STARTPG: NOP; MARWAIT: L_LM-1,SLOTBLOCK; WAIT FOR MARGIN NOP; LM_L,TASK,SH<0; TEST FOR MARGIN SENT :MARWAIT; IFSO GOTO MARDONE ; MARDONE: SLOTSTOP, L_PBBA; Initialize current scan base address CSBA_L; L_PBL,TASK; CRC_L; INITIALIZE CURRENT RING COUNT ; NEXTLINE: SLOTADDR_PBM; RESET LEFT MARGIN L_CSBA; RESET CURRENT SCAN ADDRESS CSA_L; T_PDWC; RESET LAST ADDRESS L_PDWC+T; CLA_L; T_CLA; L_CSA+T,TASK; CLA_L; SINK_ InitOnesPairs, BUS=0, TASK; Check if we're inverting :InvertNextWord; [InvertNextWord, NEXTWORD] ; ; MAIN WORD TRANSFER LOOP ; NEXTWORD: MAR_T_CSA; **SLOT HDWARE REQUIRES 3 INS. AFTER MAR_ L_CLA-T; L_2+T,SH<0; TEST FOR WORDS SENT CSA_L,:MOREWORDS;IFSO GOTO LASTWORDS ; MOREWORDS: SLOTDATA_MD,TASK; SINK_MD,:NEXTWORD ; ; Inverting Word Transfer Loop ; InvertNextWord: MAR_ T_ CSA; **SLOT HDWARE REQUIRES 3 INS. AFTER MAR_ ; I take the previous comment to mean that the clock cannot stop ; for the two cycles following the SLOTDATA - Butterfield - 10/6 L_ CLA -T; L_ 2 +T, SH<0; TEST FOR WORDS SENT CSA_ L, :InvertMoreWords; [InvertMoreWords, InvertLastWords] ; InvertMoreWords: T_ MD; L_ MD; L_ 0 -T-1, MTEMP_ L; T_ MTEMP; L_ 0 -T-1, MTEMP_ L; SLOTDATA_ MTEMP, TASK; SINK_ LREG, :InvertNextWord; ; InvertLastWords: T_ MD; L_ MD; L_ 0 -T-1, MTEMP_ L; T_ MTEMP; L_ 0 -T-1, MTEMP_ L; SLOTDATA_ MTEMP, TASK; SINK_ LREG, :FinishScanLine; ; ; LASTWORDS: SLOTDATA_MD,TASK; SINK_MD; ; ; ; FINISH SCANLINE ; FinishScanLine: T_PBSLI; INC CURRENT SCAN BASE ADDR L_CSBA+T; CSBA_L; L_CRC-1; CRC_L,SH=0,TASK; CHECK FOR BUFFER COMPLETED :BUFFEROK,SLOTBLOCK; IFSO GOTO RESETBUFFER ; RESETBUFFER: MAR_PBBA-1; GET POINTER FOR NEXT BUFF ADDR L_PBL; AND GET FIRST BUFFER ADDR CRC_L; L_MD; MAR_DCBADDR-1; PBBA_L; CSBA_L; MD_PBBA; ; BUFFEROK:L_MSL-1; MSL_L,TASK,SH=0; TEST FOR LAST SCAN LINE OF PAGE :NEXTLINE; IFSO GOTO LINESDONE ; LINESDONE: L_ONE,:InitBuffers,TASK; ZERO BOTH BUFFERS ; RET1: NOP; PAGEWAIT: T_ONE,SLOTBLOCK; L_ONE AND T,SLOTSTATUS; SH=0,TASK; TEST FOR END OF PAGE :PAGEWAIT; IFSO GOTO PAGEDONE ; PAGEDONE: :SLOTSTAT; ; ; Subroutine to initialize the buffers. Returns to RET0 or RET1 ; InitBuffers: InitReturn_ L; Save return index and initialize buffer bit InitSecond: SLOTADDR_ 177777; Start at the beginning SLOTDATA_ 0; with 64 zero bits SINK_ 0; SLOTDATA_ 0; SINK_ 0; L_ InitOnesPairs, TASK; Now for InitOnesPairs pair of ones InitPairs_ L; InitOnesLoop: L_ InitPairs -1, BUS=0, TASK; InitPairs_ L, :InitOnes; [InitOnes, InitZero] InitOnes: L_ 177777; see if using L helps put in the ones SLOTDATA_ LREG; SINK_ LREG, :InitOnesLoop; InitZero: T _ InitOnesPairs +1; L_ 377 -T-1, TASK; i.e. 253 - InitOnesPairs InitPairs_ L; (this can get squeezed out if necessary) InitZeroLoop: SLOTDATA_ 0; SINK_ 0; L_ InitPairs -1, BUS=0, TASK; InitPairs_ L, :InitZeroLoop; [InitZeroLoop, InitBufferDone] InitBufferDone: T_ 100000, SLOTBLOCK; L_ InitReturn XORT; InitReturn_ L, SH<0, TASK; Test for last buffer :InitDone; [InitDone, InitSecond] InitDone: SINK_ InitReturn, BUS, TASK; :RET0; [RET0, RET1]