RavenControlImpl.mesa
Copyright Ó Xerox Corporation 1985, 1986, 1987. All rights reserved.
Tim Diebert: April 2, 1987 9:49:45 am PST
DIRECTORY
Basics USING [bitsPerWord, LongMult],
CountedVM USING [Handle, SimpleAllocate],
ImagerSample USING [Clear, GetBox, GetBitsPerLine, GetBase, MapFromVM, RasterSampleMap],
Interrupt USING [Initialize, Object, Wait],
LSEPFace USING [AdvanceBand, AllocateBands, BandBufferCount, BandFull, BandOverrun, GetStatus, Index, InitializeCleanUp, LastBand, PutCommand, SetInterruptMasks, SetScanLineLength, StartImage, ResetBands],
PrincOps USING [BBptr, BBTableSpace, PageCount, wordsPerPage],
PrincOpsUtils USING [AlignedBBTable, BITBLT],
Process USING [Detach, MsecToTicks, Pause, priorityFaultHandlers, priorityRealTime, SetPriority, SetTimeout],
Queue USING [Initialize, Object, Pop, Push],
RavenCodes USING [PrinterCommand, PrinterStatus],
RavenControl USING [ConsoleKey, EngineEvent, EngineStatus, LogItem, PlateStatus, PaperTray, PaperTraySize, PaperStacking],
SharedQueue USING [GetCurrentHead, Initialize, Object, Pop, Push],
Synchronizer USING [Broadcast, Initialize, Notify, Object, Wait],
VM USING [Allocate, Interval, PagesForWords, Pin],
VMSideDoor USING [AssignSpecialRealMemory];
RavenControlImpl: MONITOR
IMPORTS Basics, CountedVM, ImagerSample, Interrupt, LSEPFace, PrincOpsUtils, Process, Queue, SharedQueue, Synchronizer, VM, VMSideDoor
EXPORTS RavenControl = BEGIN
TYPEs:
Band: TYPE = ARRAY [0 .. bandBufferSize * PrincOps.wordsPerPage) OF WORD;
EventContext: PUBLIC TYPE = CARDINAL;
ScanLine: TYPE = [0..bandBufferSize); -- scan line index into a band
Constants:
bandBufferSize: PrincOps.PageCount = 16; -- From BandBLT
maxBands: CARDINAL = 160; -- 8.5" * 300BitsPer" / 16BitsPerWord
activeLength: (0..PrincOps.wordsPerPage] ← ((11*300)+15)/16;
bandBufferPadding: PrincOps.PageCount = 1; -- to allow for overwrite when copying due to offset of short scan lines
Synchronizer Objects (monitored records used as conditions):
commandSent, engineEvent, newStatus, pageSync, statusReceived, imagingComplete:
Synchronizer.Object;
Interrupt Objects (monitored records used as interrupt conditions):
controlInt, imageInt, statusInt: Interrupt.Object;
Queue Objects (monitored records used as queues):
commandQ, consoleQ, logQ, turnaroundQ: Queue.Object;
eventQ: SharedQueue.Object;
Variables:
engineState: {okay, error} ← okay;
transferStatus: {ready, notReady} ← notReady;
statusInternal: RavenControl.EngineStatus ← communicationFault;
paperTrayLast: RavenControl.PaperTray ← bottom; -- last tray fed from
paperTrayOk: ARRAY RavenControl.PaperTray OF BOOLEANALL[TRUE]; -- status of paper trays
paperSizeInternal: RavenCodes.PrinterStatus;
abortImaging: BOOLEANFALSE;
flushPrinter: BOOLEANFALSE;
lastBand: BOOLEAN;
imagingActive: BOOLEANFALSE;
statusQuery: BOOLEANFALSE; -- did we send a solicitStatus command
loopbackMode: BOOLEANFALSE; -- server Loop Back diagnostic test
band, bandFirst, bandLast: LSEPFace.Index;
bandBufferCount: LSEPFace.BandBufferCount;
bandLowCore: VM.Interval;
wordsPerScanLine: (0..PrincOps.wordsPerPage]; -- current words per scan line
pagesPerBand: CARDINAL; -- number of pages in each page buffer band
pageBufferIndex: CARDINAL; -- index to current band in page buffer
pageBufferIndexLast: CARDINAL; -- last meaningful band in page buffer
pageBufferBandBuffer: LONG POINTER; -- band buffer virtual address
sampleMap: ImagerSample.RasterSampleMap;
pageMapInUse: BOOLFALSE;
pageMapStatusChange: CONDITION;
for debugging
EventLogIndex: TYPE = [0..32);
eventLogIndex: EventLogIndex ← 0;
eventLog: ARRAY EventLogIndex OF RavenControl.EngineEvent ← ALL[idle];
PUBLIC PROCEDUREs:
Initialize: PUBLIC SAFE PROCEDURE [bufferSize: PrincOps.PageCount] = TRUSTED BEGIN
initialize interrupt objects for LSEPFace's interrupt masks
controlMask: WORD = Interrupt.Initialize[
interrupt: @controlInt, enableAbort: TRUE, enableTimeout: FALSE];
imageMask: WORD = Interrupt.Initialize[
interrupt: @imageInt, enableAbort: TRUE, enableTimeout: FALSE];
statusMask: WORD = Interrupt.Initialize[
interrupt: @statusInt, enableAbort: TRUE, enableTimeout: FALSE];
start the cleanup proc
Process.Detach[FORK LSEPFace.InitializeCleanUp];
set up the interrupt interface to the head
LSEPFace.SetInterruptMasks[control: controlMask, status: statusMask, data: imageMask];
initialize queue objects
Queue.Initialize[@commandQ];
Queue.Initialize[@logQ];
Queue.Initialize[@turnaroundQ];
Queue.Initialize[@consoleQ];
SharedQueue.Initialize[queue: @eventQ, enableAbort: TRUE, enableTimeout: TRUE, lapse: 20000]; -- event timeout 20 seconds
initialize synchronizer objects
Synchronizer.Initialize[synchronizer: @commandSent, enableAbort: TRUE, enableTimeout: FALSE];
Synchronizer.Initialize[synchronizer: @engineEvent, enableAbort: TRUE, enableTimeout: TRUE, lapse: 30000];
Synchronizer.Initialize[synchronizer: @newStatus, enableAbort: TRUE, enableTimeout: FALSE];
Synchronizer.Initialize[synchronizer: @pageSync, enableAbort: TRUE, enableTimeout: FALSE];
Synchronizer.Initialize[synchronizer: @statusReceived, enableAbort: TRUE, enableTimeout: TRUE, lapse: 6000]; -- commands should respond within 5 seconds
Synchronizer.Initialize[synchronizer: @imagingComplete, enableAbort: TRUE, enableTimeout: TRUE, lapse: 12000];
set up band buffers, etc.
bandBufferCount ← bufferSize / bandBufferSize; -- the number of bands in low core
bandLowCore ← VM.Allocate[bufferSize + bandBufferPadding];
VMSideDoor.AssignSpecialRealMemory[bandLowCore]; -- Move to low core and Pin
LSEPFace.AllocateBands[bandVirtualPageNumber: bandLowCore.page,
nBands: bandBufferCount, sizeEachBand: bandBufferSize, slop: 1];
create the full page buffer SampleMap
sampleMap ← MakePrinterSampleMap[];
start the printing processes
Process.Detach[FORK HandleCommand]; -- priority = 6
Process.Detach[FORK HandleImage]; -- priority = 5
Process.Detach[FORK HandleStatus]; -- priority = 6
Process.Detach[FORK WatchCommandStatus]; -- priority = 6
Process.Detach[FORK WatchImaging]; -- priority = 6
do a get status to querry the printer
SendEngineCommand[solicitStatus];
SendEngineCommand[solicitPaperSize];
END; -- Initialize
GetEngineStatus: PUBLIC SAFE PROCEDURE RETURNS [RavenControl.EngineStatus] = TRUSTED BEGIN
returns current Raven engine status
RETURN[IF (statusInternal = okay OR statusInternal = tonerLow) AND flushPrinter THEN okayFlushRequired ELSE statusInternal];
END; -- GetEngineStatus
WaitEngineStatus: PUBLIC SAFE PROCEDURE RETURNS [RavenControl.EngineStatus] =
TRUSTED {[] ← Synchronizer.Wait[@newStatus]; RETURN[GetEngineStatus[]]}; -- WaitEngineStatus
GetPaperTrayStatus: PUBLIC SAFE PROCEDURE [tray: RavenControl.PaperTray]
RETURNS [okay: BOOLEAN] = TRUSTED BEGIN
returns the status of paper in the desired paper tray
RETURN[okay: paperTrayOk[tray]];
END;
GetPaperTraySize: PUBLIC SAFE PROC RETURNS [bottom, top: RavenControl.PaperTraySize] = TRUSTED BEGIN
returns the staus of the desired paper tray
SELECT paperSizeInternal FROM
paperSmallSmall => RETURN[small, small];
paperSmallLarge => RETURN[small, large];
paperLargeSmall => RETURN[large, small];
paperLargeLarge => RETURN[large, large];
ENDCASE => RETURN[unknown, unknown];
END;
WaitEngineEvent: PUBLIC SAFE PROCEDURE [eventContext: REF EventContext]
RETURNS [event: RavenControl.EngineEvent] = TRUSTED BEGIN
event ← LOOPHOLE[SharedQueue.Pop[@eventQ, eventContext]];
IF event = LOOPHOLE[LAST[CARDINAL]] THEN event ← timeout;
END; -- WaitEngineEvent
SetToCurrentEventContext: PUBLIC SAFE PROCEDURE [eventContext: REF EventContext] = TRUSTED BEGIN
SharedQueue.GetCurrentHead[@eventQ, eventContext]
END;
WaitConsoleKey: PUBLIC SAFE PROC RETURNS [key: RavenControl.ConsoleKey] = TRUSTED {RETURN[Queue.Pop[@consoleQ]]};
WaitLogItem: PUBLIC SAFE PROCEDURE RETURNS [RavenControl.LogItem] = TRUSTED {RETURN[Queue.Pop[@logQ]]};
Feed: PUBLIC SAFE PROCEDURE [tray: RavenControl.PaperTray, stacking: RavenControl.PaperStacking] = TRUSTED BEGIN
SendEngineCommand[SELECT TRUE FROM
tray = bottom AND stacking = aligned => feed,
tray = top AND stacking = aligned => feedTop,
tray = bottom AND stacking = offset => feedOffset,
tray = top AND stacking = offset => feedTopOffset,
ENDCASE => ERROR];
END; -- Feed
SendEngineCommand: PUBLIC SAFE PROCEDURE [cmd: RavenCodes.PrinterCommand] =
TRUSTED BEGIN Queue.Push[@commandQ, cmd]; END; -- SendEngineCommand
SetScanLineLength: PUBLIC SAFE PROCEDURE [scanLineLength: (0..PrincOps.wordsPerPage]] = TRUSTED BEGIN
LSEPFace.SetScanLineLength[scanLineLength];
wordsPerScanLine ← scanLineLength;
pagesPerBand ← ((scanLineLength * 16) + PrincOps.wordsPerPage - 1) / PrincOps.wordsPerPage;
END;
GetPageMap: PUBLIC ENTRY SAFE PROC []
RETURNS [pageMap: ImagerSample.RasterSampleMap] = TRUSTED BEGIN
UNTIL NOT pageMapInUse DO WAIT pageMapStatusChange; ENDLOOP;
pageMapInUse ← TRUE;
RETURN[sampleMap];
END;
PageTransferSet: PUBLIC SAFE PROCEDURE[pageMap: ImagerSample.RasterSampleMap] = TRUSTED BEGIN
pageBufferIndex ← 0;
pageBufferIndexLast ← ImagerSample.GetBox[pageMap].max.s/16-1;
prefill band buffers from page
[firstBand: band, firstBandAddress: pageBufferBandBuffer] ← LSEPFace.ResetBands[];
bandFirst ← band;
pageBufferIndex ← 0;
lastBand ← FALSE;
THROUGH [0..bandBufferCount) UNTIL lastBand DO BandCopyInternal[pageMap]; ENDLOOP;
transferStatus ← ready;
BroadcastEngineEvent[transferReady];
END; -- PageTransferSet
TransferRelease: PUBLIC ENTRY SAFE PROC [pageMap: ImagerSample.RasterSampleMap] = TRUSTED BEGIN
IF imagingActive THEN abortImaging ← TRUE;
transferStatus ← notReady;
pageMapInUse ← FALSE;
BROADCAST pageMapStatusChange;
END; -- TransferRelease
RunTurnaroundTest: PUBLIC SAFE PROCEDURE RETURNS [ok: BOOLEAN] = TRUSTED BEGIN
codeOut, codeIn: CARDINAL [0..177B];
ok ← TRUE;
loopbackMode ← TRUE;
FOR codeOut IN [1..177B] DO -- send each code and check recieve (avoid Head problems with 0)
SendEngineCommand[LOOPHOLE[codeOut]];
codeIn ← Queue.Pop[queue: @turnaroundQ];
IF codeIn # codeOut THEN BEGIN ok ← FALSE; EXIT; END;
ENDLOOP;
loopbackMode ← FALSE;
SendEngineCommand[solicitStatus]; -- make sure command/status polling continues
Process.Pause[Process.MsecToTicks[200]]; -- wait for command to be sent
END;
PRIVATE PROCEDUREs:
bbTableSpace: PrincOps.BBTableSpace;
bb: PrincOps.BBptr ~ PrincOpsUtils.AlignedBBTable[@bbTableSpace];
dstBpl: INTEGER ~ PrincOps.wordsPerPage*Basics.bitsPerWord;
BandCopyInternal: PROCEDURE [sm: ImagerSample.RasterSampleMap] = INLINE BEGIN
copy from page buffer to imaging band, by scan line scan lines in the buffer are each wordsPerScanLine words scan lines in the imaging band are each 256 words, offset ahead by 256 words-wordsPerScanLine
bandOffset: CARDLONG[pageBufferIndex] * LONG[pm.rast] *
LONG[LAST[ScanLine]];
sourceAddr: LONG POINTER ← ImagerSample.GetBase[sm].word + Basics.LongMult[pageBufferIndex,
(ImagerSample.GetBitsPerLine[sm] / Basics.bitsPerWord) * bandBufferSize];
bb^ ← [
dst: [word: pageBufferBandBuffer, bit: 0],
dstBpl: dstBpl,
src: [word: sourceAddr, bit: 0],
srcDesc: [srcBpl[ImagerSample.GetBitsPerLine[sm]]],
height: bandBufferSize,
width: ImagerSample.GetBox[sm].max.f,
flags: [direction: forward, disjoint: TRUE, disjointItems: TRUE, gray: FALSE, srcFunc: null, dstFunc: null]
];
PrincOpsUtils.BITBLT[bb];
IF (pageBufferIndex ← pageBufferIndex + 1) > pageBufferIndexLast THEN
{lastBand ← TRUE; bandLast ← band};
mark current band ready for imaging and get address and index of next
[nextBand: band, nextBandAddress: pageBufferBandBuffer] ← LSEPFace.AdvanceBand[currentBand: band];
END; -- BandCopyInternal
BroadcastEngineEvent: PROCEDURE [event: RavenControl.EngineEvent] = BEGIN
IF event IN [feedError..hardError] THEN engineState ← error; -- set to okay by HandleStatus
SharedQueue.Push[@eventQ, LOOPHOLE[event]];
eventLog[eventLogIndex] ← event;
eventLogIndex ← (eventLogIndex + 1) MOD LAST[EventLogIndex];
END; -- BroadcastEngineEvent
SetEngineStatus: PROCEDURE [status: RavenControl.EngineStatus] = BEGIN
IF statusInternal # status OR status = okay THEN
{statusInternal ← status; Synchronizer.Broadcast[@newStatus]};
END; -- SetEngineStatus
MakePrinterSampleMap: PROC RETURNS [pixelMap: ImagerSample.RasterSampleMap] = BEGIN
numBands: NAT = ((85*30)+15)/16;
numLines: CARDINAL = numBands * bandBufferSize;
wordsPerLine: NAT ~ activeLength;
words: LONG CARDINAL ~ Basics.LongMult[wordsPerLine, numLines];
pages: CARDINAL = VM.PagesForWords[words];
vm: CountedVM.Handle ← CountedVM.SimpleAllocate[words];
interval: VM.Interval ~ vm.interval;
pixelMap ← ImagerSample.MapFromVM[
vm: vm,
box: [min: [0, 0], max: [numLines, (11*300)]],
bitsPerSample: 1, bitsPerLine: wordsPerLine*Basics.bitsPerWord];
FOR i: INT ← 0, i+400 UNTIL i >= interval.count DO -- only pin about 100K each time
VM.Pin[[page: interval.page+i, count: MIN[interval.count-i, 400]]];
Process.Pause[Process.MsecToTicks[500]]; -- wait a half second for Laundry process
ENDLOOP;
ImagerSample.Clear[pixelMap];
END;
FORKed PROCEDUREs
HandleCommand: PROCEDURE = BEGIN
pops a command and acts on it, and notifies WatchCommandStatus that command has been sent if a response is expected.
cmd: RavenCodes.PrinterCommand;
Process.SetPriority[Process.priorityRealTime];
DO -- forever
cmd ← Queue.Pop[@commandQ]; -- waits till queue is non-empty
IF loopbackMode
THEN Synchronizer.Notify[@commandSent]
ELSE BEGIN
SELECT cmd FROM
beepShort, beepLong => NULL; -- no response
goToSleep => BEGIN
Queue.Push[@consoleQ, RavenCodes.PrinterStatus.key1];
Queue.Push[@consoleQ, RavenCodes.PrinterStatus.key2];
Queue.Push[@consoleQ, RavenCodes.PrinterStatus.keyTest]; -- ADP AR 4030
SetEngineStatus[lowPowerMode]; -- no response, post new status
END;
ENDCASE => Synchronizer.Notify[@commandSent];
SELECT cmd FROM
solicitStatus => statusQuery ← TRUE;
feed, feedOffset => paperTrayLast ← bottom;
feedTop, feedTopOffset => paperTrayLast ← top;
solicitPaperSize => paperSizeInternal ← LOOPHOLE[0]; -- reset paper tray sizes to unknown
ENDCASE => NULL;
Queue.Push[@logQ, RavenControl.LogItem[command[cmd]]];
END;
LSEPFace.PutCommand[LOOPHOLE[cmd]]; -- send the command
Interrupt.Wait[@controlInt]; -- wait for IOP to send
IF NOT loopbackMode THEN Process.Pause[Process.MsecToTicks[100]]; -- allow IOT time to think
ENDLOOP; -- forever
END; -- HandleCommand
HandleImage: PROCEDURE = BEGIN
waits until a plate is ready, then calls for bands to be filled and imaged
WaitBandEmpty: PROCEDURE [thisBand: LSEPFace.Index] = INLINE BEGIN
WHILE LSEPFace.BandFull[thisBand] DO Interrupt.Wait[@imageInt]; ENDLOOP;
wait for band to be imaged
END;
Process.SetPriority[Process.priorityFaultHandlers];
DO -- forever
wait till notified by HandleStatus of pageSync
[] ← Synchronizer.Wait[@pageSync];
IF transferStatus = notReady THEN BEGIN -- page sync missed
Process.Pause[Process.MsecToTicks[100]]; -- insure that this event is not missed
Synchronizer.Broadcast[@imagingComplete]; -- for WatchImaging
BroadcastEngineEvent[pageSyncMiss];
Queue.Push[@logQ, RavenControl.LogItem[plateStatus[pageSyncMiss]]];
LOOP;
END;
imagingActive ← TRUE;
LSEPFace.StartImage[bandFirst];
refill bands when they have been imaged until input is exhausted
UNTIL lastBand DO WaitBandEmpty[band]; BandCopyInternal[sampleMap]; ENDLOOP;
LSEPFace.LastBand[bandLast]; -- indicate that last band has been filled
WaitBandEmpty[bandLast]; -- wait till last band has been imaged
IF statusInternal = imageFault1 OR flushPrinter THEN BEGIN -- the image fault is cleared or the flush completed
flushPrinter ← FALSE; -- flush (if) is done, back to normal marking
SetEngineStatus[okay]; -- tell upper levels status has changed
END;
imagingActive ← abortImaging ← FALSE;
Synchronizer.Broadcast[@imagingComplete]; -- for WatchImaging
TransferRelease[];
IF LSEPFace.BandOverrun[]
THEN BEGIN
imaging got ahead of filling
BroadcastEngineEvent[imagedOverrun];
Queue.Push[@logQ, RavenControl.LogItem[plateStatus[bandOverrun]]];
END
ELSE BroadcastEngineEvent[imaged];
ENDLOOP; -- forever
END; -- HandleImage
HandleStatus: PROCEDURE = BEGIN
wait for status to be set and act accordingly
sts: RavenCodes.PrinterStatus;
loopbackPlug: BOOLEANFALSE; -- to avoid trashing loopback test
Process.SetPriority[Process.priorityRealTime];
DO -- forever
Interrupt.Wait[@statusInt]; -- wait for status from IOT
sts ← LOOPHOLE[LSEPFace.GetStatus[]]; -- get received status
IF loopbackMode THEN BEGIN
Synchronizer.Notify[@statusReceived]; -- something was received
Queue.Push[@turnaroundQ, sts];
LOOP;
END;
SELECT sts FROM
noStatus, statusError, statusOverRun => -- not legit status
IF statusInternal = lowPowerMode THEN LOOP; -- ignore completely if printer is off
LOOPHOLE[RavenCodes.PrinterCommand[solicitStatus]] => loopbackPlug ← TRUE;
IN [key0..LOOPHOLE[RavenCodes.PrinterCommand[displayBlank]]] => NULL; -- not responses to commands
ENDCASE => Synchronizer.Notify[@statusReceived]; -- WatchCommandStatus waiting on it
IF NOT statusQuery THEN -- events are only if we didn't ask
SELECT sts FROM
pageSync => BEGIN -- handle this status first for better performance
Synchronizer.Broadcast[@pageSync];
BroadcastEngineEvent[feeding]; -- also used as the feeding status
IF imagingActive AND transferStatus = ready THEN BEGIN -- band overrun, still imaging
BroadcastEngineEvent[pageSyncMiss];
Queue.Push[@logQ, RavenControl.LogItem[plateStatus[pageSyncMiss]]];
END;
END;
standBy => BEGIN -- printer is okay or after last page
BroadcastEngineEvent[idle];
IF engineState = error THEN -- state was error, now okay
SendEngineCommand[solicitPaperSize]; -- get paper size
engineState ← okay; -- set to error in BroadcastEngineEvent
END;
readyToFeed => BroadcastEngineEvent[readyToFeed];
pageAtOutputTray => BroadcastEngineEvent[pageDelivery];
feederFault => BEGIN
IF imagingActive THEN abortImaging ← TRUE;
paperTrayOk[paperTrayLast] ← FALSE;
BroadcastEngineEvent[feedError];
END;
fuserCold, goingOffLine, outputTrayFull => BroadcastEngineEvent[softError];
registrationJam, fuserJam, noExit, interlockOpen, aboutToDozeOff => BEGIN
IF imagingActive THEN abortImaging ← TRUE;
BroadcastEngineEvent[hardError];
END;
feedTraysNotEngaged => BroadcastEngineEvent[softError];
ENDCASE => NULL;
SELECT sts FROM
noStatus, keyOnLine, parityError, unrecognizedCommand, illegalSequence,
LOOPHOLE[57H], -- B1 online
statusError, statusOverRun => -- read status and try again
SendEngineCommand[solicitStatus];
standBy => BEGIN-- printer is okay or after last page
IF imagingActive THEN BEGIN -- flush required to finish imaging
abortImaging ← TRUE;
flushPrinter ← TRUE;
END;
END;
interlockOpen, feedTraysNotEngaged => paperTrayOk ← ALL[TRUE];
IN [paperSmallSmall..paperLargeLarge] => paperSizeInternal ← sts;
IN [key0..keyOffLine] =>
IF NOT loopbackPlug THEN Queue.Push[@consoleQ, sts];
ENDCASE => NULL;
log the status
Queue.Push[@logQ, RavenControl.LogItem[printerStatus[sts]]];
SELECT sts FROM
warming, standBy, feederFault, registrationJam, fuserJam, noExit, interlockOpen, fuserCold, feedTraysNotEngaged, tonerLow, goingOffLine, offLine, outputTrayFull, aboutToDozeOff => BEGIN
meaningful engine statuses
loopbackPlug ← FALSE; -- not from loopback plug
IF statusInternal = communicationFault THEN SendEngineCommand[displayBlank];
IF sts = aboutToDozeOff THEN BEGIN -- force engine out of repair mode
Queue.Push[@consoleQ, RavenCodes.PrinterStatus.key1];
Queue.Push[@consoleQ, RavenCodes.PrinterStatus.key2];
Queue.Push[@consoleQ, RavenCodes.PrinterStatus.keyTest];
END; -- ADP AR 4030
SetEngineStatus[
SELECT sts FROM
warming => warming,
standBy => okay,
feederFault => preRegistrationFault,
registrationJam => postRegistrationJam,
fuserJam => preExitJam,
noExit => postExitJam,
interlockOpen => doorOpen,
fuserCold => warming,
feedTraysNotEngaged => traysUnlatched,
tonerLow => tonerLow,
goingOffLine, offLine => offline,
outputTrayFull => outputTrayFull,
aboutToDozeOff => lowPowerMode,
ENDCASE => ERROR];
END;
ENDCASE => NULL;
statusQuery ← FALSE;
ENDLOOP; -- forever
END; -- HandleStatus
WatchCommandStatus: PROCEDURE = BEGIN
commandStatusTimeout: BOOLEAN;
wait for notification of command being sent, then wait for a timeout
or notification on status received
Process.SetPriority[Process.priorityRealTime];
DO -- forever
[] ← Synchronizer.Wait[@commandSent]; -- notification by HandleCommand
commandStatusTimeout ← Synchronizer.Wait[@statusReceived]; -- notification by HandleStatus
IF commandStatusTimeout THEN
IF loopbackMode
THEN Queue.Push[@turnaroundQ, 200B] -- make turnaround test fail
ELSE BEGIN
SendEngineCommand[solicitStatus];
display L4 on printer panel (if possible)
SendEngineCommand[displayL];
SendEngineCommand[display4];
IF statusInternal # communicationFault THEN BEGIN
SetEngineStatus[communicationFault];
BroadcastEngineEvent[hardError];
Queue.Push[@logQ, RavenControl.LogItem[softwareStatus[communicationFault]]];
END;
END;
ENDLOOP; -- forever
END; -- WatchCommandStatus
WatchImaging: PROCEDURE = BEGIN
Process.SetPriority[Process.priorityRealTime];
DO -- forever
wait till notified by HandleStatus of pageSync
[] ← Synchronizer.Wait[@pageSync];
wait for completion of imaging
IF Synchronizer.Wait[@imagingComplete] -- notification by HandleImage
AND imagingActive THEN BEGIN
abortImaging ← TRUE; -- abort BandBLT or BandCopy loop
IF engineState = okay THEN BEGIN-- image fault only if no engine error
SetEngineStatus[imageFault1];
BroadcastEngineEvent[hardError];
Queue.Push[@logQ, RavenControl.LogItem[softwareStatus[imageFault1]]];
END;
END;
ENDLOOP; -- forever
END; -- WatchImaging
END.
LOG
When / Who / What.
21-Apr-85 22:02:59 / Strickberger / Created for Raven engine driver redesign (compatable with old RavenFace).
27-Jun-85 17:52:24 / Strickberger / Updated for multi-plate unlimited printing. Updated for Pilot 12.0. Always broadcast newStatus if status = okay. Don't notify statusRecieived if bad status. Fix priority usage. Make event timeout 30 seconds. Fix TransferRelease to not keep last band resident.
12-Aug-85 23:02:26 / Strickberger / Divide pageBuffer into scan lines to save RM on 8.5x11 pages. Update for Euclid interfaces. FixArrows.
19-Sep-85 18:58:22 / Strickberger / Added enableUnlimited parameter to Initialize. Properly handle Volume.InsufficientSpace and Space.InsufficientSpace in Initialize.
16-Oct-85 23:45:19 / Strickberger / Initialize paperTrayLast to avoid Address Fault if startup with feederFault status (AR22059).
2-Dec-85 1:29:52 / Strickberger / Abort imaging if feederFault status - B1 printers turn off laser (AR23075). Don't send solicitPaperSize if statusQuery (AR23076). Don't send solicitStatus or put stuff on console queue if loopbackPlug - avoid trashing loopback test (AR23112). Send solicitStatus if B1 onLine (57H) (AR23113).
19-Dec-85 11:26:46 / Strickberger / Clear imagingActive and abortImaging before broadcasting imagingComplete, possible race conditions (AR23371). Send solicitStatus after turnaround test (AR23115).
21-Feb-86 17:13:40 / Strickberger / Use pageSync status to BroadcastEngineEvent[feeding] instead of feeding status (AR3721).
11-Apr-86 16:48:44 / Strickberger / Clear imageFault status and flushPrinter in HandleImage, not in HandleStatus (pageAtOutputTray); don't care about flushPrinter or transferStatus or BandOverrun in WatchImaging; pause before broadcasting imagingComplete and pageSyncMiss event in HandleImage to avoid missed notifys. (AR3999).
5-May-86 0:38:26 / Strickberger / Increase imagingComplete timeout to 12 seconds to avoid image faults on band overrun pages (AR4155). Broadcast pageSyncMiss if page still imaging at pageSync.
14-May-86 14:00:10 / Prochaska / Modified WaitEngineEvent[], BroadcastEngineEvent[] to use SharedQueue; Added SetToCurrentEventContext[].