// PrintOrbit.bcpl // last modified by Butterfield, July 8, 1980 3:03 PM // - POrbit, live with ScanConvert's and Orbit.mu's imprecision - 7/8/80 // errors 1000 // get "PressInternals.df" get "PressParams.df" get "Orbit.D" manifest lKCB=10+4 //4 is fudge, 10 is right; should be: get "bfs.d" // outgoing procedures external [ POrbit;POrbitInit DoFunc Max ] // outgoing statics external [ signalBand ] static [ signalBand ] // incoming procedures external [ //PrintOrbitHdwFns AddQEntry;AdCommand;IFunc;ROSCheck FeedASheet;InitializeHardware;ROSCommand;ROSStatus;ReadAdapterStatus JogReady PressError //CURSOR CursorChar CursorDigit CursorToggle //OS Zero MoveBlock StartIO CallSwat DisableInterrupts EnableInterrupts //PRESSML Ugt DoubleCop //PRESS DblShift //WINDOWS,FILE FileReadPage FileVDA WindowInit WindowSetPosition WindowReadBlock //PrintDisk31 ReadBuffer31 PrintBuffer31 InitBuffers31 //PrintTrident ReadBufferTrident PrintBufferTrident InitBuffersTrident ] // incoming statics external [ BitsFile sysDisk BandFile printerDevice printerForward Debug breakPage pFonts ICCtot //PRINTORBITINIT nVisibleBands nLeadingBands nTrailingBands FA maxPrintPassRecs BitScale MotorScale BitClock MotorSpeed LineSyncDelay PageSyncDelay VideoGate Tadapter nPrinterColors ] //outgoing statics external [ FontTable;nextBogusChar;nDCBs] static [ FontTable;nextBogusChar;nDCBs=3] // internal statics static [ Func nPagesPrinted timeOut=15*27 debugTrail simLateDisk //for debugging simulation of late disk //if true, then every other ReadBands will //set proceedcode=4 (no sheet in pipe) //sequoia fix ~~ At present, Sequoia "not ready" bit never presents itself // Some rint sequences require an engine runout, followed // by a restart -- this delay waits for shutdown before continuing readyTimeOut //set 0 at start, non-zero for outler loop continuation sReadyTimeOut=2*27+20 //can tune this from SWAT until right ] // File-wide structure and manifest declarations. manifest [ RTC=#430 loSize=1200 //Enough for 300 left-over characters or lines debugTrailSize=20*3 // Failure Code ranges -- see ROSCheck maxNotReady = 9 // not ready, but probably will be soon maxManual = 19 // Manual intervention required maxJam = 99 // Error during operation minDocumentError = 300 // Document inherently hard to print ] manifest // factors for creating table entries [ Invert = #100000 Code = 256 Word = 16 Bit = 1 ] manifest [ //P commands PResetRemoteQueue=#63010 PStartRemoteQueue=#63006 PStart3ColorVideo=#63346 PStart3ColorScan=#63246 PStart4ColorVideo=#63306 PStart4ColorScan=#63206 PAppendQueueEntry=#63020 PSetVideo=#63204 PNoPaperAction=#63003 PFeedPaper=#63203 PReleasePaper=#63103 PSinglePass=#63303 PNoColor=#63001 PSetColor6=#63201 //usually black PSetColor7=#63101 //usually cyan PSetColor9=#63041 //usually magenta PSetColor11=#63021 //usually yellow //P printSeq states Pwarmup=1 Pstandby=2 Pprinting=3 Pendofrun=4 Plowpaper=5 Pbadfeed=6 Pbadstrip=7 Pclearing=8 PmalfClear=9 ] // ----------------------------------------------------------- // Print Initialization // ----------------------------------------------------------- // Returns -1 if printing is successfully completed, else // nPagesPrinted, so can pick up where we left off. let POrbitInit(pg,nPages,nCopies;numargs na) be [ IFunc(fControl, 1) //Reset Orbit for i=0 to 15 do //Set inkwell [ IFunc(fXY, i lshift 12) IFunc(fInk, -1) ] AdCommand(adBufferReset) AdCommand(adSetScales+BitScale lshift 9+MotorScale lshift 6) AdCommand(adBitClock+BitClock) AdCommand(adMotorSpeed+MotorSpeed) AdCommand(adLineSyncDelay+LineSyncDelay) AdCommand(adPageSyncDelay+PageSyncDelay) if Tadapter then AdCommand(adVideoGate+VideoGate) if na eq 0 then return //do P machine queue creation //establish queue entries: first, a null entry, and then the real entries InitializeHardware(true) ROSCommand(PResetRemoteQueue) ROSCommand(PAppendQueueEntry) //null rev for i=0 to nCopies do [ let np=nPages let p=pg until np eq 0 do [ test (nPrinterColors eq 3)% ((p>>PageG.ColorUsed)&(nPrinterColors gr 1)) then [ AddQEntry(PSetColor9,PFeedPaper) //magenta AddQEntry(PSetColor11,PNoPaperAction) //yellow test nPrinterColors eq 3 then AddQEntry(PSetColor7,PReleasePaper) //cyan or [ AddQEntry(PSetColor7,PNoPaperAction) //cyan AddQEntry(PSetColor6,PReleasePaper) //black ] ] or AddQEntry(PSetColor6,PSinglePass) p=p+nPrinterColors*(size PageG/16) np=np-nPrinterColors ] //for all pages ] //for all copies ROSCommand(PStartRemoteQueue) ] and POrbit(pg, lowAdr, highAdr, nPagesAlreadyPrinted,lvFailureCode,last) = valof [ CursorChar($P) @lvFailureCode = 0 readyTimeOut=0 nPagesPrinted=nPagesAlreadyPrinted let debugTrailVec=vec debugTrailSize compileif DebugSw then [ debugTrail=debugTrailVec;debugTrail!0=0] lowAdr=lowAdr+(lowAdr&1) let nRecs=(highAdr-lowAdr-4) rshift BandFile>>F.LogPagesize // if nRecs ls maxPrintPassRecs then PressError(1000) let nBands=nLeadingBands+nVisibleBands+nTrailingBands let LeftOver=vec loSize+1 LeftOver=(LeftOver+1)&(-2) let LeftOverGuard=LeftOver+(loSize&(-4))-4 let CommTabNoFeed=vec 3 CommTabNoFeed=(CommTabNoFeed+1)&(-2) CommTabNoFeed!0=-1 let CommTabFeed=vec 10 CommTabFeed=(CommTabFeed+1)&(-2) let funcTab=vec 20 Func=(funcTab+1)&(-2) let FAvalue=FA lshift 8 let coldStart=printerDevice eq printerDover let consecutiveErrors=0 let printerSimple = printerDevice eq printerSequoia let stopPrint, okPrint = nil, nil test printerDevice eq printerSequoia then stopPrint, okPrint = #60000, #60001 // PimlicoAlt assumed or stopPrint, okPrint = #60005, #60001 // stop print, lamp inhibit let newRp=nil //Read in font and relocate the pointers to characters let font=pFonts+pg>>PageG.fontLoad*(size FontG/16) ReadFont(font,lowAdr) FontTable=lowAdr+font>>FontG.fontLength for i=0 to ICCtot+nVisibleBands do FontTable!i=FontTable!i+lowAdr //Figure out where buffers are let nfRecs=(nRecs-font>>FontG.nRecords)/2 newRp=lowAdr+(font>>FontG.nRecords lshift BandFile>>F.LogPagesize) //Now read in the bands for this page let nextBuffFreeList=ReadBands(pg,newRp,nfRecs*2)-BandFile>>F.Pagesize let firstBuff=(nextBuffFreeList+BandFile>>F.Pagesize+1)&-2 let nBuffs=0 let page=pg>>PageG.BitPage nextBogusChar=ICCtot let doneFlag=true let nextBuffFreeIndex=0 let DCBs=vec 2 let v=vec lKCB*16*3+1 DCBs!0=(v+1)&-2 DCBs!1=DCBs!0+lKCB*16 DCBs!2=DCBs!1+lKCB*16 let InitBuffers,ReadBuffer,PrintBuffer=nil,nil,nil test BitsFile>>F.Device ge DISKT80 then [ InitBuffers=InitBuffersTrident;ReadBuffer=ReadBufferTrident PrintBuffer=PrintBufferTrident ] or [ InitBuffers=InitBuffers31;ReadBuffer=ReadBuffer31;PrintBuffer=PrintBuffer31 ] let headerBuff=vec 2 let labelBuff=vec 10 unless pg>>PageG.SimplePage do [ //Set up initial bogus character buffers // doneFlag=false // let myBands=pg>>PageG.LastBand-pg>>PageG.FirstBand+1 // let da=nil // Make an effort to print blank pages. Otherwise, color sync // on 6500 will be screwed up. // test myBands gr 0 then da=FileVDA(BitsFile, pg>>PageG.BitPage) // or [ // da=-1 // pg>>PageG.FirstBand=10 // pg>>PageG.BitMargin=16*10 // pg>>PageG.BitWc=4 // nBands=1 // ] nBuffs=((highAdr rshift 1)-(firstBuff rshift 1))/(4096/2) doneFlag=InitBuffers(DCBs,firstBuff,nBuffs,headerBuff,labelBuff,lv page) ] //end of "unless simplePage" // Initialize the Orbit, Dover, etc. InitializeHardware(false) let np = nil let tim = @RTC // Check for problems, wait for ready indication // wait for ready or some serious condition or for long enough unless Debug do [ //sequoia Fix ~~ possibly wait for shutdown while (@RTC-tim) < readyTimeOut do [ ] if printerDevice eq printerSequoia then readyTimeOut=sReadyTimeOut [ let running=printerDevice eq printerPuffin np=ROSCheck(lvFailureCode,nPagesAlreadyPrinted,running, nPagesPrinted) if np eq -1 break // ready if @lvFailureCode>maxNotReady % (@RTC-tim) > timeOut resultis np ] repeat ] //end of "unless Debug" with sequoia fix // Try to empty Orbit buffers to clear them. This is to minimize // toner dumping on first (blank) page. compileif loSize ls 256 then [ foo=nil ] for i=0 to 31 do DoFunc(fReadBlock, 256, LeftOver) unless printerDevice eq printerPuffin do //feed first sheet: [ DoFunc(fControl, 21b) ROSCommand(adBufferReset) // If Dover is already running, this StartPrint may not do the right // thing, because it may be sent during the "dead" time near // CS-5. FeedASheet() ] Announce(15) // ~~ Delays PimlicoAlt long enough? unless AwaitPageSync(0) do CallSwat("1") //Wait for sendVideo to go off. [RunningLoop // Calculate a ROS command table for the device: let CommTab=nil switchon printerDevice into [ case printerDover: CommTab=CommTabFeed CommTab!0=signalBand+2 CommTab!1=adExternalCommand1 //No feed yet CommTab!2=signalBand+1 CommTab!3=adExternalCommand1 CommTab!4=10000b+signalBand CommTab!5=32 *256 //Status bits 0-3 of word 8 CommTab!6=-1 endcase case printerDurango: CommTab=CommTabNoFeed FeedASheet() endcase case printerSequoia: case printerPimlicoAlt: CommTab=CommTabFeed CommTab!0=signalBand CommTab!1=last?stopPrint,okPrint //Stop unless proven otherwise (below) CommTab!2=-1 endcase case printerPuffin: CommTab=CommTabNoFeed;endcase case printerPimlico: [ CommTab = CommTabNoFeed let nC = nil if last do ROSCommand(#63030) // Stop Print (at end of copy) endcase ] ] //cold start for test if printerDevice eq printerDover then [ AwaitPageSync(1) FeedASheet() AwaitPageSync(0) ] // Start Orbit working on the present page. DoFunc(fControl, #21) //Reset, clear behind ROSCommand(adBufferReset) LeftOver!0=0 //Initialize LeftOver table LeftOverGuard!1=-1 tim=@RTC // Start the microcode!!!! DoFunc(fSlot, CommTab, 20000,pg>>PageG.LastBand+1, FAvalue, LeftOver, FontTable+#100000, newRp-1, nil, nil, 1) // Proceed code: // 0: Charge on ahead, full speed // 1: Pause because cannot fit bands or font for next page, // or because printing is done. // 2: Reprint this page, due to misfeed (Dover only). // 4: No sheet in pipe (Dover only) // Assume the page we are printing will be OK: // unless coldStart then // [ // nPagesPrinted=nPagesPrinted+1 // CursorDigit(nPagesPrinted) // ] // Find next page to work on: // let proceedCode=1 // let nextbuf=curbuf xor buf1 xor buf2 // let nextPage=PrintNext(pDoc,lv copy) // if nextPage & (nextPage>>PageG.fontLoad eq page>>PageG.fontLoad) & // (nextPage>>PageG.nRecords le nfRecs) then proceedCode = 0 // PollEther() // ~~ later, if print request then proceedCode = 1 // Read in the bands for the next page: // if proceedCode eq 0 then let proceedCode=nil //TEST //if false then //TEST ONLY // [ // if printerSimple then CommTab!1=okPrint // don't stop ////TEST ReadBands(nextPage, nextbuf, coldStart? nfRecs*2, nfRecs) // if printerDevice eq printerDover then // [ // if simLateDisk then // [ // simLateDisk=simLateDisk xor 1 // if (simLateDisk&1) eq 0 then Func!3=-1 // ] // DisableInterrupts() // test Func!3 gr signalBand+3 then // CommTab!1=adExternalCommand1+1 // or proceedCode=4 // EnableInterrupts() // ] // ] // Now see if we actually printed this page properly. First, // wait for Orbit to announce it is finished. let imageTimeout = (printerDevice eq printerDover? 4, 10)*27 let readCount=0 let printCount=0 while @#720 ne 0 do [ if (@RTC-tim) gr imageTimeout then [ Blast() // clear hardware, #720 test printerDevice eq printerPimlicoAlt & JogReady() ne 0 then proceedCode = 2 // counted out, equiv. to misfeed. // Machine dead or Orbit got behind and it wasn't detected // Will generally be overriden by more specific analysis or @lvFailureCode = 19 // Manual intervention required break ] // (Notes: ScanConvert processes bands FirstBand to LastBand. When // writing out band b it checks to see if the nWordsToWrite will fit. // If they will not, it writes the Bit page and sets the // nextBuffFreeList entry for that page to b+1, which is two too many. // Orbit.mu only decrements Func!3 upon starting the next band, and // the emulator is run only when a band is on it's way out. // currentBand below, then, is the band just processed. // Writing over a page used to wait until currentBand ge // nextBuffFreeList!nextBuffFreeIndex. Subtracting 2 lets the disk // get (further) ahead.) let currentBand=pg>>PageG.LastBand+1-Func!3 unless doneFlag do [ if (currentBand ge nextBuffFreeList!nextBuffFreeIndex - 2) then [ //diskIO let adr=firstBuff+4096*(readCount rem nBuffs) ReadBuffer(page,adr,DCBs!(readCount rem nDCBs)) readCount=readCount+1 if (readCount-printCount) ge nDCBs then [ until PrintBuffer(DCBs!(printCount rem nDCBs), lv doneFlag) do [ ] printCount=printCount+1 ] page=page+4096/1024 nextBuffFreeIndex=nextBuffFreeIndex+1 ] if readCount gr printCount then if PrintBuffer(DCBs!(printCount rem nDCBs), lv doneFlag) then printCount=printCount+1 ] ] // Check Orbit status @#521=0 let debugValue=readCount-printCount StatusLabel: let nonF = 0 let stat=Func!9 //Orbit printing status. // ********** Debugging stuff //if stat<>DocG.nPages //TEST let nBreaks = breakPage eq 0? 0, printerDevice eq printerPimlicoAlt? 3, 1 //TEST nPages=nPages-nBreaks //TEST let nCopies=pDoc>>DocG.nCopies //TEST let copy = (printerForward? n-nBreaks+nPages, n)/nPages //TEST @lvCopyNo = printerForward? copy, nCopies-copy //TEST let totPages=nCopies*nPages+nBreaks //TEST if n ge totPages then resultis 0 //All finished //TEST // Transform to forward sequence: //TEST unless printerForward then n=totPages-n-1 //TEST n=n-nBreaks //TEST let p=n rem nPages //TEST if breakPage ne 0 & n ls 0 then p=nPages+nBreaks+n //Print break page //TEST resultis p*(size PageG/16)+pDoc>>DocG.Pages //TEST] //Horrible stuff added to avoid understanding band merge pass (shame) and ReadBands(page, buf, nRecs) = (page eq 0)?0,valof [ let readRecs=page>>PageG.nRecords if nRecs ls readRecs then PressError(1001) let firstBand=page>>PageG.FirstBand let lastBand=page>>PageG.LastBand Zero(buf,firstBand*2) buf=buf+firstBand*2 let pos=vec 1 DoubleCop(pos,lv page>>PageG.BandPos) let wordOffset=(pos!1)&(BandFile>>F.Pagesize-1) let firstPage=DblShift(pos,BandFile>>F.LogPagesize) FileReadPage(BandFile,firstPage,buf) MoveBlock(buf,buf+wordOffset,BandFile>>F.Pagesize-wordOffset) firstPage=firstPage+1 buf=buf+BandFile>>F.Pagesize-wordOffset until readRecs le 48 do [ FileReadPage(BandFile,firstPage,buf,48) firstPage=firstPage+48 buf=buf+48*BandFile>>F.Pagesize readRecs=readRecs-48 ] FileReadPage(BandFile,firstPage,buf,readRecs) resultis buf+readRecs*BandFile>>F.Pagesize ] and ReadFont(font, buf) be [ let count=font>>FontG.nRecords let page=font>>FontG.bandPos until count le 48 do [ FileReadPage(BandFile,page,buf,48) page=page+48 buf=buf+48*BandFile>>F.Pagesize count=count-48 ] FileReadPage(BandFile,page,buf,count) ] and Max(a,b)=(a gr b)?a,b and Announce(n) be [ CursorChar((n ge 16? $K,$P)) for i=0 to 3 do [ if (n&10b) ne 0 then CursorToggle(i) n=n lshift 1 ] ] and Blast() be InitializeHardware(false) and SetRMR(x) = ( table [ #61010; #1401 ] )(x, #20) and DebugEnter(a, b) be [ compileif DebugSw then [ let m=debugTrail!0 let dm=debugTrail+m dm!1=a; dm!2=b; dm!3=@RTC //Time m=m+3; if m ge debugTrailSize-4 then m=0 debugTrail!0=m ] ] // ----------------------------------------- // Engine controls of various sorts. // ----------------------------------------- //Wait for page sync to equal given value. // Returns true if there was nothing unexpected and AwaitPageSync(ps) = valof [ if Debug then resultis true let tim=@RTC [ if (@RTC-tim) gr 5*27 then resultis false DoFunc(fControl, 0) //Read ROS special status (1st four bits of status word 0) let f=Func!9 if f<