; 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]