RavenEngineImpl.mesa
Copyright (C) Xerox Corporation 1985, 1986. All rights reserved.
last edited by prochaska 14-May-86 14:11:30
Tim Diebert: October 3, 1986 12:07:38 pm PDT
Ruseli Binsol: November 19, 1986 11:39:03 am PST
DIRECTORY
Loader USING [MakeGlobalFrameResident, MakeProcedureResident],
LSEPFace USING [AdvanceBand, SetPageOffsets],
PaperHandling USING [TwoPaperSizes, RavenRegistration, registrationTabSize],
PaperTypes USING [PaperMicaDimension, PaperSize],
PrincOps USING [bitsPerWord, PageCount, wordsPerPage],
PrintingState USING [Type],
Process USING [Detach, Pause, priorityForeground, priorityRealTime, SecondsToTicks, SetPriority],
RavenControl USING [--BandBLTTransferCreatePage, BandBLTTransferReady, --EngineEvent, EngineStatus, EventContext, Feed, GetEngineStatus, GetPaperTraySize, GetPaperTrayStatus, Initialize, PageTransferSet, PaperTray, SendEngineCommand, SetScanLineLength, SetToCurrentEventContext, TransferRelease, unlimitedAvailable, WaitEngineEvent, WaitEngineStatus],
RavenEngine USING [JobHandle, PaperTraySize],
RavenSequence USING [--GetBandlist, --GetPaperStacking, GetPaperTray, pageCount, Set],
RavenStatus USING [Type];
RavenEngineImpl: CEDAR MONITOR
IMPORTS Loader, LSEPFace, PaperTypes, Process, RavenControl, RavenSequence
EXPORTS RavenEngine = BEGIN
TYPEs:
PrintingStateKind: TYPE = MACHINE DEPENDENT {current (0), next (1)};
CONDITIONs:
newPrintingState: ARRAY PrintingStateKind OF CONDITION;
Variables:
debugForceTransferWait: BOOLEANFALSE; -- are we always going to wait for transfer to be ready before feeding
jobInternal: RavenEngine.JobHandle;
printingState: ARRAY PrintingStateKind OF PrintingState.Type;
paperSupply: PaperHandling.TwoPaperSizes;
pageDelivered, pageFeed, pageTransfer, pageTrash: CARDINAL;
engineStatus: RavenControl.EngineStatus ← okay;
paperScanLengths: ARRAY PaperTypes.PaperSize OF CARDINAL; -- number of words in scan line for each kind of paper
PUBLIC PROCEDUREs:
Beep: PUBLIC PROCEDURE = {RavenControl.SendEngineCommand[beepShort]};
DeclarePaperSupply: PUBLIC PROCEDURE [ps: PaperHandling.TwoPaperSizes] =
BEGIN paperSupply ← ps; END;
sets global variable recording type of paper in top and bottom trays
DozeOff: PUBLIC PROCEDURE = BEGIN
"issues" doze-off command to the printer
RavenControl.SendEngineCommand[goToSleep];
END; -- DozeOff
GetPageBalance: PUBLIC PROCEDURE RETURNS [balance: CARDINAL] = BEGIN
returns number of pages remaining to be printed in job
RETURN[
balance:
SELECT GetPrintingStateEntry[kind: current] FROM
completed => 0,
ENDCASE => RavenSequence.pageCount + pageTrash - pageDelivered];
END; -- GetPageBalance
GetPaperTraySizes: PUBLIC PROCEDURE RETURNS [bottom, top: RavenEngine.PaperTraySize] = BEGIN
SELECT RavenControl.GetPaperTraySize[] FROM
[small, small] => RETURN[small, small];
[small, large] => RETURN[small, large];
[large, small] => RETURN[large, small];
[large, large] => RETURN[large, large];
ENDCASE => RETURN[unknown, unknown];
END; -- GetPaperTraySize
GetPrintingState: PUBLIC PROCEDURE RETURNS [state: PrintingState.Type] = BEGIN
returns current state (started, stopped, or completed) of job
RETURN[state: GetPrintingStateEntry[kind: current]];
END; -- GetPrintingState
GetStatus: PUBLIC PROCEDURE RETURNS [status: RavenStatus.Type] = BEGIN
IF engineStatus NOT IN [imageFault1..sequenceFault] THEN
engineStatus ← RavenControl.GetEngineStatus[]; -- "sticky" stauses
status ← SELECT engineStatus FROM
okay => okay,
okayFlushRequired => okay,
tonerLow => tonerLow,
warming => fuserUnderTemperature,
lowPowerMode => aboutToDozeOff,
preRegistrationFault => preRegistrationFault,
postRegistrationJam => postRegistrationJam,
preExitJam => preExitJam,
postExitJam => postExitJam,
outputTrayFull => outputTrayFull,
traysUnlatched => traysUnlatched,
doorOpen => doorOpen,
offline => offLine,
communicationFault => commandStatusFault,
imageFault1 => imageFault,
imageFault2 => imageFault,
imageFault3 => imageFault,
sequenceFault => okay,
ENDCASE => ERROR;
END; -- GetStatus
SetJob: PUBLIC PROCEDURE [job: RavenEngine.JobHandle] = BEGIN
sets the internal job handle to the value of the argument
jobInternal ← job;
END; -- SetJob
SetPrintingState: PUBLIC PROCEDURE [state: PrintingState.Type] = BEGIN
sets next state of job
SetPrintingStateEntry[kind: next, state: state];
END; -- SetPrintingState
SetRegistration: PUBLIC PROCEDURE [registration: PaperHandling.RavenRegistration] = TRUSTED BEGIN
DivideUp: PROCEDURE [divident, divisor: CARDINAL] RETURNS [quotient: CARDINAL] = TRUSTED INLINE BEGIN RETURN[quotient: (divident + divisor - 1) / divisor]; END;
sets up arguments for call which will set page offsets
LSEPFace.SetPageOffsets[
wordsFast: DivideUp[
divident: registration.long * PaperHandling.registrationTabSize,
divisor: PrincOps.bitsPerWord],
linesSlow: registration.short * PaperHandling.registrationTabSize];
END; -- SetRegistration
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: RavenStatus.Type] =
BEGIN [] ← RavenControl.WaitEngineStatus[]; RETURN[GetStatus[]]; END; -- WaitStatus
WakeUp: PUBLIC PROCEDURE = BEGIN
"issues" wake-up command to the printer if it's asleep
IF RavenControl.GetEngineStatus[] = lowPowerMode THEN BEGIN
RavenControl.SendEngineCommand[solicitStatus];
RavenControl.SendEngineCommand[solicitStatus]; -- first one gets lost sometimes
END;
END; -- WakeUp
Initialize: PUBLIC PROCEDURE [bufferSize: PrincOps.PageCount, enableUnlimited: BOOLEAN] = TRUSTED BEGIN
LongDivideUp: PROCEDURE [divident, divisor: CARD] RETURNS [quotient: CARDINAL] = TRUSTED INLINE {RETURN[quotient: (divident + divisor - 1) / divisor]};
The errors are assumed to occur only if the procedures/frames are already resident, and are therefore ignored. The procedures are assumed to exist in the one resident pack per PROGRAM module which is allowed to be resident. Separate calls are provided for each module to allow this code to work (at slightly higher memory expense) in the absence of packaging.
Make LSEPHeadDLion resident
Loader.MakeProcedureResident[LSEPFace.AdvanceBand];
Loader.MakeGlobalFrameResident[LSEPFace.AdvanceBand];
Make RavenControlImpl resident
Loader.MakeGlobalFrameResident[RavenControl.SendEngineCommand];
Loader.MakeProcedureResident[RavenControl.SendEngineCommand];
Initialize RavenControlImpl
RavenControl.Initialize[bufferSize: bufferSize, enableUnlimited: TRUE];
start the printing processes
Process.Detach[FORK Print]; -- priority = 2 (sometimes 5)
FOR paper: PaperTypes.PaperSize IN PaperTypes.PaperSize DO
paperScanLengths[paper] ← MIN[
PrincOps.wordsPerPage, LongDivideUp[
divident: PaperTypes.PaperMicaDimension[paper].long * 300,
divisor: 2540 -- micas per inch -- * PrincOps.bitsPerWord]];
ENDLOOP;
END; -- Initialize
PRIVATE PROCEDUREs:
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;
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-- : RavenControl.EngineEvent;
engineError, transferIsReady: BOOLEAN;
eventContextHandleTransfer: REF RavenControl.EventContext ← NEW[RavenControl.EventContext];
eventContextPrint: REF RavenControl.EventContext ← NEW[RavenControl.EventContext];
GetFeedTray: PROCEDURE [page: CARDINAL] RETURNS [tray: RavenControl.PaperTray] = BEGIN
tray ← RavenSequence.GetPaperTray[page]; -- this is where we want to get paper from
IF NOT RavenControl.GetPaperTrayStatus[tray] THEN --we can't get it from there
IF jobInternal.paperFeed = fromBottomOrTop
OR jobInternal.paperFeed = alternateBottomAndTop -- if it doesn't matter where we get it
AND RavenControl.GetPaperTrayStatus[IF tray = bottom THEN top ELSE bottom] -- and the other tray is okay
AND paperSupply.size1 = paperSupply.size2 THEN -- and has the same kind of paper
tray ← IF tray = bottom THEN top ELSE bottom; -- then feed from there
END; -- GetFeedTray
HandleTransfer: PROCEDURE = BEGIN
unlimitedPage ← TRUE;
RavenControl.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 RavenControl.unlimitedAvailable THEN unlimitedPage ← TRUE
ELSE pageTransfer ← pageTransfer + 1;
idle, timeout => -- should NEVER occur, but...
BEGIN
transferIsReady ← TRUE; -- if timing caused feeding event to clear it
LOOP; -- around again
END;
feedError, softError, hardError => EXIT;
ENDCASE => LOOP;
update BandBLTTable for next page and make bandlists and fontloads resident
IF pageTransfer >= RavenSequence.pageCount THEN EXIT;
RavenControl.SetScanLineLength[paperScanLengths[IF GetFeedTray[pageTransfer] = bottom THEN paperSupply.size1 ELSE paperSupply.size2]];
IF unlimitedPage
THEN BEGIN
BandBLTTransfer.Update[
bandlist: RavenSequence.GetBandlist[page: pageTransfer],
nextBandlist: RavenSequence.GetBandlist[page: pageTransfer]];
RavenControl.BandBLTTransferCreatePage[firstPlate: TRUE]; -- create page bitmap
BandBLTTransfer.Reset[]; -- make bandlists and fontloads swappable
RavenControl.PageTransferSet[]; -- signal that page is ready
unlimitedPage ← FALSE;
END
ELSE BEGIN
BandBLTTransfer.Update[
bandlist: RavenSequence.GetBandlist[page: pageTransfer],
nextBandlist: RavenSequence.GetBandlist[
MIN[RavenSequence.pageCount - 1, pageTransfer + 1]]];
RavenControl.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 RavenSequence.Set[jobInternal] THEN
{Process.Pause[Process.SecondsToTicks[1]]; LOOP};
pageDelivered ← pageTrash ← 0;
forceTransferWait ← TRUE;
DO -- document loop
SetPrintingStateEntry[kind: current, state: GetPrintingStateEntry[next]];
IF WaitPrintingStateEntry[kind: next, targetState: stopped, targetEqual: FALSE] = completed THEN EXIT; -- job aborted
IF engineStatus IN [imageFault1..imageFault3] THEN engineStatus ← okay; -- clear "sticky" status with new job start
reset counters to new starting page
pageTransfer ← pageFeed ← pageDelivered ← pageDelivered - pageTrash;
pageTrash ← 0;
SELECT RavenControl.GetEngineStatus[] FROM
okay, tonerLow => NULL;
okayFlushRequired, IN [imageFault1..imageFault3] => BEGIN
"Flush" the printer with a blank sheet to complete previous unfinished imaging
RavenControl.SetToCurrentEventContext[eventContext: eventContextPrint];
RavenControl.Feed[GetFeedTray[pageFeed], RavenSequence.GetPaperStacking[pageFeed]];
DO -- flush printing loop
SELECT printEvent ← RavenControl.WaitEngineEvent[eventContextPrint] FROM
pageDelivery, idle, feedError, softError, hardError, timeout => EXIT; -- wait for these
ENDCASE => LOOP; -- others are in-process
ENDLOOP; -- flush printing loop
IF RavenControl.GetEngineStatus[] IN [imageFault1..imageFault3] AND GetPrintingStateEntry[next] = started
THEN SetPrintingStateEntry[kind: next, state: stopped];
LOOP; -- flushed one sheet, try again
END;
preRegistrationFault =>
see if we can use the other paper tray
IF RavenControl.GetPaperTrayStatus[GetFeedTray[pageFeed]]
THEN Process.Pause[Process.SecondsToTicks[15]] -- wait for runout
ELSE BEGIN Process.Pause[Process.SecondsToTicks[1]]; LOOP; END;
ENDCASE => BEGIN-- wake up printer / query every second
RavenControl.SendEngineCommand[solicitStatus];
Process.Pause[Process.SecondsToTicks[1]];
LOOP;
END;
set up bandBLTTable and make bandlists and fontloads for first page resident
engineError ← FALSE;
RavenControl.SetScanLineLength[paperScanLengths[IF GetFeedTray[pageTransfer] = bottom THEN paperSupply.size1 ELSE paperSupply.size2]];
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]--;
RavenControl.BandBLTTransferReady[];
RavenControl.PageTransferSet[pageDelivered+1]; -- Build Bitmap.
transferProcess ← FORK HandleTransfer[];
transferIsReady ← TRUE;
Process.SetPriority[Process.priorityRealTime]; -- don't miss events
feedOkay ← FALSE;
RavenControl.SetToCurrentEventContext[eventContext: eventContextPrint];
RavenControl.Feed[GetFeedTray[pageFeed - pageTrash], RavenSequence.GetPaperStacking[pageFeed - pageTrash]];
DO -- page printing loop
SELECT printEvent ← RavenControl.WaitEngineEvent[eventContextPrint] FROM
readyToFeed => BEGIN
feedOkay ← TRUE;
IF transferWait AND NOT transferIsReady THEN LOOP;
END;
feeding =>
BEGIN pageFeed ← pageFeed + 1; transferIsReady ← FALSE; LOOP; END;
transferReady => BEGIN
transferIsReady ← TRUE;
IF (NOT transferWait) OR (NOT feedOkay) THEN LOOP;
END;
imaged => LOOP;
imagedOverrun => BEGIN
IF RavenControl.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 >= RavenSequence.pageCount + pageTrash THEN EXIT;
IF pageDelivered >= pageFeed AND (GetPrintingStateEntry[next] # started) OR engineError THEN EXIT;
LOOP;
END;
idle, timeout =>
IF engineError OR pageTransfer >= RavenSequence.pageCount OR GetPrintingStateEntry[next] # started
THEN EXIT
ELSE IF NOT transferIsReady THEN LOOP; -- assume that feed missed if transferIsReady???
feedError => BEGIN
engineError ← TRUE;
pageFeed ← pageFeed - 1;
IF pageDelivered < pageFeed THEN LOOP ELSE EXIT;
END;
softError => BEGIN
engineError ← TRUE;
IF pageDelivered < pageFeed THEN LOOP ELSE EXIT;
END;
hardError => BEGIN engineError ← TRUE; EXIT; END;
ENDCASE => ERROR;
IF pageFeed < RavenSequence.pageCount + pageTrash AND GetPrintingStateEntry[next] = started THEN BEGIN
transferWait ← forceTransferWait-- OR PredictTransferWait[pageFeed - pageTrash]--;
feedOkay ← FALSE;
RavenControl.Feed[GetFeedTray[pageFeed - pageTrash], RavenSequence.GetPaperStacking[pageFeed - pageTrash]];
END;
ENDLOOP; -- page printing loop
Process.SetPriority[Process.priorityForeground];
IF RavenControl.GetEngineStatus[] IN [imageFault1..imageFault3] AND GetPrintingStateEntry[next] = started THEN
SetPrintingStateEntry[kind: next, state: stopped];
JOIN transferProcess;
deactivate and make swappable bandlists and fontloads spaces
RavenControl.TransferRelease[];
BandBLTTransfer.Reset[];
IF pageDelivered = RavenSequence.pageCount + pageTrash THEN EXIT;
ENDLOOP; -- document loop
ENDLOOP; -- forever
END; -- Print
END.
LOG
When / Who / What.
21-Apr-85 22:48:53 / Strickberger / Created.
28-Jun-85 0:05:34 / Strickberger / Updated for new multi plate unlimited printing. Updated for Pilot 12.0 Incorporated fixes from BansheeEngineImpl.
31-Jul-85 0:41:29 / Strickberger / Update for Euclid interfaces. Merge in Initialize from RavenEngineInitImpl. Fix handling of pageTransfer in HandleTransfer. FixArrows.
26-Aug-85 10:08:30 / Strickberger / Set debugForceTransferWait ← FALSE;
19-Sep-85 19:13:02 / Strickberger / Added enableUnlimited parameter to Initialize. Export GetPaperTraySizes.
4-Oct-85 13:19:37 / Strickberger / Fix race condition with setting transferWait in HandleTransfer by adding feedOkay logic.
19-Dec-85 11:31:36 / Strickberger / Add call to RavenControl.SetScanLineLength for first page of document (AR23370).
21-Feb-86 17:23:32 / Strickberger / Set transferIsReady if idle or timeout event in HandleTransfer (AR3721).
31-Mar-86 23:35:12 / Strickberger / Modify flush logic to not fall through after flush; stop printing if image fault after flush (AR3999).
14-May-86 14:09:22 / Prochaska / Update for new RavenControl, add calls to RavenControl.SetToCurrentEventContext.