// P R I N T O R B I T H D W F N S // errors 3400,3500 get "PDInternals.d" get "Orbit.d" // outgoing procedures external [ InitializeHardware DoFunc ROSCommand AdCommand SetupAdapter AddQEntry FeedASheet AwaitPageSync ROSCheck ] // outgoing statics external [ Func ] static [ Func ] // incoming procedures external [ MoveBlock StartIO ] // incoming statics external [ printerDevice useStandardQueue nPrinterColors Debug //PRINT ORBIT debugTrail //PRINTORBITINIT BitScale MotorScale BitClock MotorSpeed LineSyncDelay PageSyncDelay VideoGate ] //internal statics static [ rosCount = 0 //P,Pimlico command count rosSyncError = false // Pimlico -- sync problem jogT1 = 10*27 jogT2 = 6*27 ] // File-wide structure and manifest declarations. manifest [ RTC=#430 ] // ROSCheck values structure CT: [ invert bit 1 failureCode bit 7 wordIndex bit 4 bitIndex bit 4 ] 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 (these are simply pseudo malFunction codes) Pwarmup=#301 Pstandby=#302 Pprinting=#303 Pendofrun=#304 Plowpaper=#305 Pbadfeed=#306 Pbadstrip=#307 Pclearing=#310 PmalfClear=#311 Pillegal1=#312 Pillegal2=#313 ] // ----------------------------------------- // Low-level Orbit functions. // ----------------------------------------- let InitializeHardware(stop) be [ if Debug return DoFunc(fControl, 1) //Reset Orbit switchon printerDevice into [ case printerDover: ROSCommand(adExternalCommand1); endcase case printerPimlico: case printerPuffin: ROSCommand(#60000, false) // Reset command count if stop then ROSCommand(#63040) // Stop now. rosSyncError = false ROSCommand(#60000, false) // Reset command count ROSCommand(#63050) // Read out malfunction data, clear malf. // ROSCommand(#63217) // SetPageSyncEvent to 25 endcase ] ] and DoFunc(function, arg1, arg2, arg3, arg4, arg5, nil,nil,nil,nil,nil) = valof [ compileif DebugSw then [ DebugEnter(function, arg1) ] if Debug then resultis 0 if Func eq 0 then [ Func= table [ 0;0;0;0;0;0;0;0;0;0;0;0;0;0 ] Func=(Func+1)&(-2) ] MoveBlock(Func, lv function, 11) if function eq fStatus then Func!0=fDBCWIDIn // if refreshIdle then @Func=(@Func)%#100000 // Give pointer to microcode stuff. @#720=Func // Wake up microcode StartIO(#4) // Wait for microcode to complete if function ne fSlot then while @#720 ne 0 do loop if function eq fStatus then resultis Func!9 resultis Func!8 ] 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 ugr debugTrail!1 then m=1 debugTrail!0=m ] ] and ROSStatus(w) = DoFunc(fROSStatus, w*(4*256)) and ROSCommand(x, sync; numargs na) be switchon printerDevice into [ case printerPuffin: na=2;sync=1;//endcase intentionally omitted case printerPimlico: [ if na<2 then sync = 4 test x eq #60000 then rosCount=0 or if printerDevice eq printerPuffin then rosCount=(rosCount+1) rem 256 let good = true for i = 1 to sync? sync, 1 do [ DoFunc(fROSCommand, x) unless sync break let tim = @RTC; good = false while (@RTC-tim) le 25 do if rosCount eq (ROSStatus(12)Ź) then [ good = true; break ] if good then break ROSCommand(#60000, false) rosSyncError = false ] unless good do rosSyncError = true unless printerDevice eq printerPuffin do rosCount = (rosCount+1) rem 256 endcase ] default: DoFunc(fROSCommand, x) ] and AdCommand(x) be DoFunc(fROSCommand, x) // ----------------------------------------- // Initialize adapter. // ----------------------------------------- and SetupAdapter() be [ DoFunc(fControl, 1) //Reset Orbit for i=0 to 15 do //Set inkwell [ DoFunc(fXY, i lshift 12) DoFunc(fInk, -1) ] AdCommand(adBufferReset) AdCommand(adSetScales+BitScale lshift 9+MotorScale lshift 6) AdCommand(adBitClock+BitClock) AdCommand(adMotorSpeed+MotorSpeed) AdCommand(adLineSyncDelay+LineSyncDelay) AdCommand(adPageSyncDelay+PageSyncDelay) AdCommand(adVideoGate+VideoGate) // Try to empty Orbit buffers to clear them. This is to minimize // toner dumping on first (blank) page. let dump=vec 256 for i=0 to 31 do DoFunc(fReadBlock, 256, dump) ] // ----------------------------------------- // Utility functions. // ----------------------------------------- and AddQEntry(color, paperAction) be [ ROSCommand(PAppendQueueEntry) ROSCommand(PSetVideo) ROSCommand(color) ROSCommand(paperAction) ] and FeedASheet() be switchon printerDevice into [ case printerDover: ROSCommand(adExternalCommand1+1) ROSCommand(adExternalCommand1) endcase case printerSequoia: ROSCommand(60000b) ROSCommand(60001b) endcase case printerPimlico: case printerPuffin: if useStandardQueue then //Use standard 3 or 4 color queue ROSCommand((nPrinterColors eq 3? #63346,#63306)) endcase ] //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<<STATUS.ROSStatusBit0 eq ps then resultis true ] repeat ] // ----------------------------------------------------------------- // FailureCode = ROSCheck(running) // ------------------------------------------------------------------ // Analyze ROS status // FailureCode = 0 if there are no malfunctions, ROS is ready to print // otherwise, an error code (see below) // running true if caller thinks main drive is allowed to be on for "ready" // result, false otherwise (waiting for ready). // ROSCheck first screens the current status for any malfunction indications, and // returns right away if there are none. Otherwise, it applies the current status // against a printer-dependent table of possible conditions, yielding a failure // code and a new page value -- the last page certain to have been reliably // printed. One possible condition is "no malfunction detected", which will only // be issued for printers that give no positive indication when they are merely // busy doing normal things. // The failure codes divide into ranges: // 1-9 Not ready, but no indication of problems or will clear up automatically // (includes fuser cold, warmup mode, clearing revolutions, etc.) // 10-19 Manual intervention required before machine can become ready // (paper low, power not there, etc.) // 20-99 Jams and other operational malfunctions (many codes provided so that // each device can report machine-dependent jam explanations) // 100-149 Inherent problems (e.g., insufficient bandwidth somewhere) that are // not curable by mere mortals. Attempts to improve the situation should be // abandoned. // 150-199 Inherent problems encountered, but they did not terminate printing. One // should expect that one or more pages were improperly imaged. // The machine-dependent control table is constructed using the // CT structure. // invert means that the bit is on when the condition is not a problem (e.g., "Ready") // failureCode should be reported when the condition specified by the bitIndex'th // bit inROS status word wordIndex is a problem. // (Pimlico uses a different format: right byte is status code returned from machine, // left byte is status code returned from ROSCheck // ROSCheck (cont) and ROSCheck(running) = valof [ let ros8 = ROSStatus(8) let ros9 = ROSStatus(9) let ros12 = ROSStatus(12) let ros13 = ROSStatus(13) // Following stuff is for Pimlico, Puffin let malFnStatus=ros13Ź let seqStatus = ros13 rshift 8 let subSeq=seqStatus&7 let mainSeq = (seqStatus rshift 3)&7 let mode = seqStatus rshift 6 let printSeq=selecton mainSeq into [ case 1: case 2: Pwarmup case 3: Pstandby case 4: selecton subSeq into [ case 0: Pprinting case 1: Pendofrun case 2: Plowpaper case 3: Pbadfeed case 4: Pbadstrip case 5: Pclearing default: Pillegal1 ] case 5: PmalfClear default: Pillegal2 ] if printerDevice eq printerPimlico then printSeq=selecton seqStatus into [ case 1: case 2: Pwarmup case 3: Pstandby case 4: Pprinting case 5: Pendofrun case 6: Plowpaper case 7: Pbadfeed case 8: Pbadstrip case 9: Pclearing case 10: PmalfClear default: Pillegal2 ] let ready = selecton printerDevice into [ // Power on, no malfunction, paper tray OK, fuser warm case printerDover: (ros9࠴) eq #2000 & (ros8ߔ) eq 4 // Ready, no malfunction or no malfunction (depends on running) case printerSequoia: (ros9&(running? #100, #300)) eq 0 // Standby or no malfunction (depends on running) case printerPimlico: ros12 ge 0 & malFnStatus eq 0 & (printSeq eq Pstandby % (running & (printSeq eq Pprinting % printSeq eq Pclearing))) case printerPuffin: valof [ //if running, expect Pstandby //else, either Pprinting or Pendofrun let expected=running? ((printSeq eq Pendofrun)%(printSeq eq Pprinting)), (printSeq eq Pstandby) let rdy=expected&//Puffin in right place (malFnStatus eq 0)&//no malfunction ((ros12䏡) eq rosCount)&//no queue problems (mode eq 1) //remote print mode unless rdy do resultis false if printSeq ne Pstandby then resultis true //we're ready, and in standby: check for scanning let lineCount = ROSStatus(7)𩠐 let rtc=@RTC let scanTicks=32//# of ticks in 4 scans until (@RTC-rtc) ge scanTicks do [ ] resultis (ROSStatus(7)𩠐) ne lineCount ] default: true ] if ready % Debug resultis 0 // Analyze tables to identify the problem or condition preventing ready let tab = selecton printerDevice into [ case printerDover: table [ 10*Code + 8*Word + 5*Bit // PTDisorder-H Check paper tray 20*Code + 8*Word + 10*Bit // 27LS-H Jam -- paper feed 21*Code + 8*Word + 14*Bit // LostPower-H Lost engine power 22*Code + 9*Word + 1*Bit // PhotoCellOut-H Jam--paper on drum 23*Code + 9*Word + 2*Bit // PreSeq-H Jam -- startup sequence 24*Code + 9*Word + 6*Bit // 38LS-H Jam--paper on fuser roll 25*Code + 9*Word + 10*Bit // 3LS-H Jam--paper on drum 1*Code + 8*Word + 13*Bit + Invert // ReadyTemp-H Fuser not warm 26*Code + 9*Word + 5*Bit + Invert // ACMonitor-H Engine not powered up 27*Code + 9*Word + 9*Bit // Malfunction-H unexplained malfunction 0 ] case printerSequoia: table [ 2*Code + 8*Word + 13*Bit // Fuser not warm 11*Code + 8*Word + 5*Bit // Check paper tray 30*Code + 9*Word + 2*Bit // Jam 31*Code + 9*Word + 9*Bit // Unexplained Malfunction 3*Code + 9*Word + 8*Bit // Not ready 0 ] case printerPuffin: case printerPimlico: table [ // error code,, machine code 13 lshift 8 + #32 // 1A 2/2 low paper. // 50 -- M6800 is in wait state (see below) // 51 -- command sync count error (see below) 52 lshift 8 + #00 // 00 X missed. 53 lshift 8 + #04 // 04 malfunction memory set. 54 lshift 8 + #10 // 08 1/1 FIRE!!!!!!!! 55 lshift 8 + #16 // 0E 1/4 Transport A. 56 lshift 8 + #34 // 1C 2/3 Paper grip. 57 lshift 8 + #36 // 1E 2/4 Transport B. 58 lshift 8 + #50 // 28 3/1 Fuser interlock open. 59 lshift 8 + #54 // 2C 3/3 Bottom tray interlock open. 60 lshift 8 + #56 // 2E 3/4 Transport C jam. 61 lshift 8 + #74 // 3C 4/3 Front door open. 62 lshift 8 + #116// 4E 5/4 Toner call. 63 lshift 8 + #150// 68 7/1 Functional interlock open. 6 lshift 8 + Pwarmup // PrintSequence = poweron or warmup 14 lshift 8 + Plowpaper // PrintSequence = low paper 64 lshift 8 + Pbadfeed // PrintSequence = bad feed 65 lshift 8 + Pbadstrip // PrintSequence = bad strip 66 lshift 8 + PmalfClear // PrintSequence = malfunction clearing 67 lshift 8 + Pillegal2 // Illegal print sequence code 68 lshift 8 + Pillegal1 // Illegal print subsequence code // 69 -- T events missed (see below) 0 + Pprinting //Will set code=0 0 + Pendofrun 0 + Pclearing 0 + Pstandby 0 ] default: table [ 0 ] // Codes generated elsewhere: // 8 -- no specific malfunction detected, but something is wrong // 18 -- Orbit timed out -- page sync never arrived, or engine died or got behind // 97 -- (Dover) page did not arrive at Count-H // 98 -- Orbit invalid band entry // 99 -- Timeout of unknown origin // 100 -- Disk got behind // 101 -- Orbit got behind, but page terminated normally // 102 -- Orbit got behind, had to quit early // 103 -- Left over table got too large. Please report to fixer. ] let bits = table [ #100000; #40000; #20000; #10000 #4000; #2000; #1000 #400; #200; #100 #40; #20; #10 #4; #2; #1 ] // ROSCheck (cont) // Condition interpreter let code = 0 let pDevice=(printerDevice eq printerPimlico % printerDevice eq printerPuffin) if pDevice then test rosSyncError then code = 51 or test ROSStatus(12) < 0 then code = 50 or test malFnStatus eq 0 then malFnStatus=printSeq or if #200 le malFnStatus & malFnStatus le #240 then code = 69 // 80-A0 T events missed unless code while @tab do [ let entry = @tab test pDevice ne 0 ifnot if ( ( ROSStatus(entry<<CT.wordIndex) & (bits!(entry<<CT.bitIndex)) ) xor entry<<CT.invert ) ne 0 then [ code = entry<<CT.failureCode; break ] ifso if malFnStatus eq (entryŹ) then [ code = entry rshift 8; break ] tab = tab+1 ] // Perhaps this condition ought to be promoted to a higher value unless code do code = 8 // No specific malfunction found -- what's happening? resultis code ]