BansheeEngineImpl.mesa
Copyright (C) Xerox Corporation 1985, 1986. All rights reserved.
Edited by prochaska 14-May-86 14:11:30
Ruseli Binsol: October 13, 1986 3:24:15 pm PDT
DIRECTORY
BansheeControl USING [--BandBLTTransferCreatePage, BandBLTTransferReady, --Display, EngineEvent, EngineStatus, EventContext, GetEnginePaper, GetEngineStatus, Initialize, PageTransferSet, SendEngineCommand, SetToCurrentEventContext, TransferRelease,
unlimitedAvailable, WaitEngineStatus, WaitEngineEvent],
BansheeEngine USING [DisplayDigit, JobHandle],
BansheeSequence USING [--GetBandlist, --pageCount, Set],
BansheeStatus USING [Type],
PrincOps USING [PageCount],
LSEPFace USING [AdvanceBand],
PaperTypes USING [Paper],
PrintingState USING [Type],
Process USING [Detach, Pause, priorityForeground, priorityRealTime, SecondsToTicks, SetPriority],
Loader USING [MakeGlobalFrameResident, MakeProcedureResident];
BansheeEngineImpl: CEDAR MONITOR
IMPORTS BansheeControl, BansheeSequence, Loader, LSEPFace, Process
EXPORTS BansheeEngine = BEGIN
PrintingStateKind: TYPE = {current, next};
newPrintingState: ARRAY PrintingStateKind OF CONDITION;
debugForceTransferWait: BOOLEANFALSE; -- are we always going to wait for transfer to be ready before feeding
jobInternal: BansheeEngine.JobHandle;
printingState: ARRAY PrintingStateKind OF PrintingState.Type;
pageDelivered, pageFeed, pageTransfer, pageTrash: CARDINAL;
stickyEngineStatus: BansheeControl.EngineStatus ← okay;
Beep: PUBLIC PROCEDURE = BEGIN BansheeControl.SendEngineCommand[chime]; END;
Display: PUBLIC PROCEDURE [digitLS, digitMS: BansheeEngine.DisplayDigit] = BEGIN BansheeControl.Display[LOOPHOLE[digitLS], LOOPHOLE[digitMS]]; END;
GetPageBalance: PUBLIC PROCEDURE RETURNS [balance: CARDINAL] = BEGIN
RETURN[balance: SELECT GetPrintingStateEntry[kind: current] FROM completed => 0,
ENDCASE => BansheeSequence.pageCount + pageTrash - pageDelivered];
END; -- GetPageBalance
GetPaperSize: PUBLIC PROCEDURE RETURNS [paperSize: PaperTypes.Paper] = BEGIN
RETURN[SELECT BansheeControl.GetEnginePaper[] FROM
paperLetter => [knownSize: letter],
paperLegal => [knownSize: legal],
paperA4 => [knownSize: a4],
paper215X330 => [knownSize: legal],
paperEnvelope10 => [knownSize: other, otherSize: [114, 254]], -- 4.5x10"
paperEnvelopeRX => [knownSize: other, otherSize: [114, 254]],
ENDCASE => ERROR];
END; -- GetPaperSize
GetPrintingState: PUBLIC PROCEDURE RETURNS [state: PrintingState.Type] = BEGIN
RETURN[state: GetPrintingStateEntry[kind: current]];
END; -- GetPrintingState
GetStatus: PUBLIC PROCEDURE RETURNS [status: BansheeStatus.Type] = BEGIN
IF stickyEngineStatus NOT IN [imageFault1..sequenceFault] THEN
stickyEngineStatus ← BansheeControl.GetEngineStatus[]; -- "sticky" stauses
status ← SELECT stickyEngineStatus FROM
okay => okay,
okayFlushRequired => okay,
diagnosticOkay => repairMode,
noPaper => noPaper,
preregistrationJam => preRegistrationJam,
fuserJam => fuserJam,
noExit => exitJam,
outputTrayFull => outputTrayFull,
feedTrayNotEngaged => paperCassetteRemoved,
clamShellOpen => clamshellOpen,
copyModeOn => copyMode,
noToner => noToner,
callForService => callForService,
diagnosticNotReady => repairMode,
offline => offLine,
communicationFault => communicationFault,
imageFault1 => imageFault1,
imageFault2 => imageFault2,
imageFault3 => imageFault2,
sequenceFault => sequenceFault,
ENDCASE => ERROR;
END; -- GetStatus
Initialize: PUBLIC PROCEDURE [bufferSize: PrincOps.PageCount, enableUnlimited: BOOLEAN] = TRUSTED BEGIN
Make LSEPHeadDLion resident
Loader.MakeProcedureResident[LSEPFace.AdvanceBand];
Loader.MakeGlobalFrameResident[LSEPFace.AdvanceBand];
Make BansheeControlImpl resident
Loader.MakeGlobalFrameResident[BansheeControl.SendEngineCommand];
Loader.MakeProcedureResident[BansheeControl.SendEngineCommand];
Initialize BansheeControlImpl
BansheeControl.Initialize[bufferSize: bufferSize, enableUnlimited: TRUE];
start the printing processes
Process.Detach[FORK Print]; -- priority = 2 (sometimes 5)
END; -- Initialize
SetJob: PUBLIC PROCEDURE [job: BansheeEngine.JobHandle] = BEGIN
jobInternal ← job;
END; -- SetJob
SetPrintingState: PUBLIC PROCEDURE [state: PrintingState.Type] = BEGIN
sets next state of job
SetPrintingStateEntry[kind: next, state: state];
END; -- SetPrintingState
WaitPrintingState: PUBLIC PROCEDURE [targetState: PrintingState.Type, targetEqual: BOOLEAN]
RETURNS [state: PrintingState.Type] = BEGIN
returns when current job achieves desired relationship (equal or not equal) with the target state
RETURN[state: WaitPrintingStateEntry[kind: current, targetState: targetState, targetEqual: targetEqual]];
END; -- WaitPrintingState
WaitStatus: PUBLIC PROCEDURE RETURNS [status: BansheeStatus.Type] = BEGIN
[] ← BansheeControl.WaitEngineStatus[]; RETURN[GetStatus[]]; END; -- WaitStatus
GetPrintingStateEntry: ENTRY PROCEDURE [kind: PrintingStateKind]
RETURNS [state: PrintingState.Type] =
BEGIN RETURN[state: printingState[kind]]; END;
SetPrintingStateEntry: ENTRY PROCEDURE [kind: PrintingStateKind, state:
PrintingState.Type] = BEGIN
printingState[kind] ← state; BROADCAST newPrintingState[kind]; END;
WaitPrintingStateEntry: ENTRY PROCEDURE [kind: PrintingStateKind,
targetState: PrintingState.Type, targetEqual: BOOLEAN]
RETURNS [state: PrintingState.Type] = BEGIN
wait until desired relationship is achieved with targetState
UNTIL targetEqual = (printingState[kind] = targetState) DO
WAIT newPrintingState[kind]; ENDLOOP;
RETURN[state: printingState[kind]];
END; -- WaitPrintingStateEntry
Print: PROCEDURE = BEGIN
transferProcess: PROCESS;
diagnosticPrint: BOOLEANFALSE; -- wait for pageDelivery before feeding
forceTransferWait: BOOLEAN; -- Always wait for transfer if page sync miss.
transferWait: BOOLEAN; -- Should we wait for transfer to be ready before feed
feedOkay: BOOLEAN; -- Will engine accept feed command
unlimitedPage: BOOLEANFALSE; -- print this page in unlimited mode
printEvent --, transferEvent-- : BansheeControl.EngineEvent;
engineError, transferIsReady: BOOLEAN;
beeperActive: BOOLEANFALSE;
eventContextHandleTransfer: REF BansheeControl.EventContext ← NEW[BansheeControl.EventContext];
eventContextPrint: REF BansheeControl.EventContext ← NEW[BansheeControl.EventContext];
DisplayFault: PROCEDURE = TRUSTED BEGIN
Beeper: PROCEDURE = TRUSTED BEGIN
THROUGH [1..5] DO
BansheeControl.SendEngineCommand[chime];
Process.Pause[Process.SecondsToTicks[2]];
ENDLOOP;
beeperActive ← FALSE;
END; -- Beeper
SELECT BansheeControl.GetEngineStatus[] FROM
imageFault1, imageFault2, imageFault3, sequenceFault => BEGIN BansheeControl.SendEngineCommand[SELECT BansheeControl.GetEngineStatus[] FROM
imageFault1 => displayP1,
imageFault2 => displayP2,
imageFault3 => displayP3,
ENDCASE => displayP5];
IF NOT beeperActive THEN BEGIN
beeperActive ← TRUE;
Process.Detach[FORK Beeper]; -- beep, then go away
END;
END;
ENDCASE => Display[blank, blank];
END; -- DisplayFault
HandleTransfer: PROCEDURE = BEGIN
unlimitedPage ← False;
BansheeControl.SetToCurrentEventContext[eventContext: eventContextHandleTransfer];
DO
IF engineError THEN EXIT;
transferEvent ← RavenControl.WaitEngineEvent[eventContextHandleTransfer];
IF engineError OR GetPrintingStateEntry[next] # started THEN EXIT;
SELECT transferEvent FROM
imaged => pageTransfer ← pageTransfer + 1; -- and fall through
imagedOverrun =>
IF BansheeControl.unlimitedAvailable THEN unlimitedPage ← TRUE
ELSE pageTransfer ← pageTransfer + 1;
feederror, softerror, harderror => EXIT;
ENDCASE => LOOP;
-- update BandBLTTable for next page and make bandlists and fontloads resident
IF pageTransfer >= BansheeSequence.pageCount THEN EXIT;
IF unlimitedPage THEN
BEGIN
BandBLTTransfer.Update[
bandlist: BansheeSequence.GetBandlist[page: pageTransfer],
nextBandlist: BansheeSequence.GetBandlist[page: pageTransfer]];
BansheeControl.BandBLTTransferCreatePage[firstPlate: TRUE]; -- create page bitmap
BandBLTTransfer.Reset[]; -- make bandlists and fontloads swappable
BansheeControl.PageTransferSet[]; -- signal that page is ready
unlimitedPage ← FALSE;
END
ELSE BEGIN
BandBLTTransfer.Update[
bandlist: BansheeSequence.GetBandlist[page: pageTransfer],
nextBandlist: BansheeSequence.GetBandlist[
MIN[BansheeSequence.pageCount - 1, pageTransfer + 1]]];
BansheeControl.BandBLTTransferReady[]; -- signal that bands are ready
END;
transferIsReady ← TRUE; -- insurance if transferReady event missed in page printing loop
ENDLOOP;
END; -- HandleTransfer
Print mainline code
Process.SetPriority[Process.priorityForeground];
DO -- forever
SetPrintingStateEntry[kind: next, state: completed];
SetPrintingStateEntry[kind: current, state: completed];
wait till a "request" is made to start a job
[] ← WaitPrintingStateEntry[kind: next, targetState: started, targetEqual: TRUE];
IF NOT BansheeSequence.Set[jobInternal] THEN BEGIN Process.Pause[Process.SecondsToTicks[1]]; LOOP; END;
pageDelivered ← pageTrash ← 0;
forceTransferWait ← TRUE; -- this document has not missed a page sync (yet)
DO -- document loop
SetPrintingStateEntry[kind: current, state: GetPrintingStateEntry[next]];
IF WaitPrintingStateEntry[kind: next, targetState: stopped, targetEqual: FALSE] = completed THEN EXIT; -- job aborted
SetPrintingStateEntry[kind: current, state: started];
IF stickyEngineStatus IN [imageFault1..sequenceFault] THEN stickyEngineStatus ← okay; -- clear "sticky" status with new job start
SELECT BansheeControl.GetEngineStatus[] FROM
okay, diagnosticOkay => NULL; -- no problem
okayFlushRequired, IN [imageFault1..imageFault3] => BEGIN
BansheeControl.SetToCurrentEventContext[eventContextPrint];
"Flush" the printer with a blank sheet to complete previous unfinished imaging
BansheeControl.SendEngineCommand[feed];
DO -- flush printing loop
SELECT printEvent ← BansheeControl.WaitEngineEvent[eventContextPrint] FROM
pageDelivery, feedError, softError, hardError, timeout => EXIT; -- wait for these
ENDCASE => LOOP; -- others are in-process
ENDLOOP; -- flush printing loop
IF BansheeControl.GetEngineStatus[] IN [imageFault1..sequenceFault] AND
GetPrintingStateEntry[next] = started THEN
SetPrintingStateEntry[kind: next, state: stopped]; -- restarted by BansheeMarkerControlImpl
DisplayFault[];
LOOP; -- flushed one sheet, try again
END;
ENDCASE => BEGIN Process.Pause[Process.SecondsToTicks[1]]; LOOP; END;
diagnosticPrint ← BansheeControl.GetEngineStatus[] = diagnosticOkay;
reset counters to new starting page
pageTransfer ← pageFeed ← pageDelivered ← pageDelivered - pageTrash;
pageTrash ← 0;
engineError ← FALSE;
set up bandBLTTable and make bandlists and fontloads for first page resident
BandBLTTransfer.Set[
transfer: jobInternal.document,
bandlist: RavenSequence.GetBandlist[page: pageTransfer],
nextBandlist: RavenSequence.GetBandlist[
page: MIN[RavenSequence.pageCount - 1, pageTransfer + 1]]];
transferWait ← forceTransferWait -- OR PredictTransferWait[pageTransfer]--;
BansheeControl.BandBLTTransferReady[];
BansheeControl.PageTransferSet[pageDelivered+1]; -- Build Bitmap.
transferProcess ← FORK HandleTransfer[];
transferIsReady ← TRUE;
Process.SetPriority[Process.priorityRealTime]; -- don't miss events
feedOkay ← FALSE;
BansheeControl.SetToCurrentEventContext[eventContext: eventContextPrint];
BansheeControl.SendEngineCommand[feed];
DO -- page printing loop
SELECT printEvent ← BansheeControl.WaitEngineEvent[eventContextPrint] FROM
readyToFeed => BEGIN
feedOkay ← TRUE;
IF (transferWait AND NOT transferIsReady) OR diagnosticPrint THEN LOOP; END;
feeding => BEGIN
pageFeed ← pageFeed + 1;
transferIsReady ← FALSE;
Display[LOOPHOLE[(pageFeed - pageTrash) MOD 10], LOOPHOLE[((pageFeed - pageTrash) / 10) MOD 10]]; LOOP; END;
transferReady => BEGIN
transferIsReady ← TRUE;
IF (NOT transferWait) OR (NOT feedOkay) OR diagnosticPrint THEN LOOP; END;
imaged => LOOP;
imagedOverrun => BEGIN
IF BansheeControl.unlimitedAvailable THEN BEGIN pageTrash ← pageTrash + 1; transferWait ← TRUE; END; LOOP;
END;
pageSyncMiss => BEGIN
pageTrash ← pageTrash + 1;
IF NOT unlimitedPage THEN -- don't set forceTransferWait if unlimitedPage
forceTransferWait ← transferWait ← TRUE;
LOOP;
END;
pageDelivery => BEGIN
pageDelivered ← pageDelivered + 1;
IF pageDelivered >= BansheeSequence.pageCount + pageTrash THEN EXIT;
IF pageDelivered >= pageFeed AND (GetPrintingStateEntry[next] # started OR engineError) THEN EXIT;
IF NOT diagnosticPrint THEN LOOP; -- feed next page if diagnostic
END;
feedError => BEGIN
IF NOT engineError THEN -- feedError should only occur once
pageFeed ← pageFeed - 1; -- but occurs lots, so decrement pageFeed if not previous error
engineError ← TRUE;
IF pageDelivered >= pageFeed THEN EXIT ELSE LOOP;
END;
softError => BEGIN
engineError ← TRUE;
IF pageDelivered >= pageFeed THEN EXIT ELSE LOOP;
END;
hardError => BEGIN engineError ← TRUE; EXIT; END;
timeout => IF engineError OR pageTransfer >= BansheeSequence.pageCount OR GetPrintingStateEntry[next] # started THEN EXIT -- these should only occur when waiting for transferReady
ELSE IF NOT transferIsReady THEN LOOP; -- else we missed transferReady event
ENDCASE => ERROR;
IF pageFeed < BansheeSequence.pageCount + pageTrash AND GetPrintingStateEntry[next] = started THEN BEGIN
transferWait ← forceTransferWait -- OR PredictTransferWait[pageFeed - pageTrash]--;
feedOkay ← FALSE;
BansheeControl.SendEngineCommand[feed];
END;
ENDLOOP; -- page printing loop
Process.SetPriority[Process.priorityForeground];
IF BansheeControl.GetEngineStatus[] IN [imageFault1..sequenceFault] AND GetPrintingStateEntry[next] = started THEN
SetPrintingStateEntry[kind: next, state: stopped]; -- restarted by BansheeMarkerControlImpl
DisplayFault[];
JOIN transferProcess;
BansheeControl.TransferRelease[];
BandBLTTransfer.Resset[];
IF pageDelivered = BansheeSequence.pageCount + pageTrash THEN EXIT;
ENDLOOP; -- document loop
ENDLOOP; -- forever
END; -- Print
END.
LOG
When / Who / What.
12-Dec-84 23:29:22 / Strickberger / Created.
28-Jan-85 16:12:59 / Strickberger / Update to new BansheeFace.
14-Feb-85 17:24:42 / Strickberger / Add offline mode handling.
25-Feb-85 23:08:49 / Strickberger / Add prediction logic to wait for transfer ready if a new fontload will be required.
1-Apr-85 23:13:01 / Strickberger / Stop printing if image fault. Flush printer control moved to this module - part of ImageFault fix (AR13951). Display image fault/sequence fault code display.
13-May-85 0:12:46 / Strickberger / Fix pageDelivered pageMissed initialization before page printing loop. Check pageTransfer limit and printingState at Idle event in page printing loop. Check engineState at Idle event in HandleTransfer.
23-May-85 22:53:10 / Strickberger / Decrement pageFeed only once in page printing loop if feedError event by checking engineError.
28-May-85 17:56:42 / Strickberger / Check engineError, pageTransfer >= BansheeSequence.pageCount, GetPrintingStateEntry[next] # started before SELECTing on transferEvent in HandleTransfer (AR15492).
31-Jul-85 21:07:12 / Strickberger / Do not call debugger if timeout event in HandleTransfer, fall through if timeout event and transferIsReady in page printing loop of Print (AR15541). Run page printing loop of Print at priorityIOLow.
12-Aug-85 23:45:06 / Strickberger / Add unlimited printing. Update for Euclid. FixArrows.
25-Aug-85 20:55:57 / Strickberger / Feed next page at pageDelivery in diagnostic mode.
19-Sep-85 19:15:44 / Strickberger / Added enableUnlimited parameter to Initialize.
3-Oct-85 2:56:25 / Strickberger / Fix race condition with setting transferWait in HandleTransfer by adding feedOkay logic.
14-Oct-85 17:26:44 / Strickberger / Add envelope handling to GetPaperSize.
24-Feb-86 12:12:12 / Strickberger / Add Beeper to chime for software detected faults (AR3107).
1-Apr-86 22:57:21 / Strickberger / Set debugForceTransferWait ← TRUE if 192kW server (AR3752). Modified flush logic to not fall through after flush; stop printing if image fault after flush.
4-May-86 23:59:08 / Strickberger / Modify pageDelivery case in Print to not subtract pageTrash from pageDelivered, avoids hang after imagedOverrun print (AR4225).
14-May-86 20:04:14 / Prochaska / Update for new BansheeControl, add calls to BansheeControl.SetToCurrentEventContext.