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
Band: TYPE = ARRAY [0 .. bandBufferSize * PrincOps.wordsPerPage) OF WORD;
EventContext: PUBLIC TYPE = CARDINAL;
ScanLine: TYPE = [0..bandBufferSize); -- scan line index into a band
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;
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 BOOLEAN ← ALL[TRUE]; -- status of paper trays
paperSizeInternal: RavenCodes.PrinterStatus;
abortImaging: BOOLEAN ← FALSE;
flushPrinter: BOOLEAN ← FALSE;
lastBand: BOOLEAN;
imagingActive: BOOLEAN ← FALSE;
statusQuery: BOOLEAN ← FALSE; -- did we send a solicitStatus command
loopbackMode: BOOLEAN ← FALSE; -- 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: BOOL ← FALSE;
pageMapStatusChange: CONDITION;
for debugging
EventLogIndex: TYPE = [0..32);
eventLogIndex: EventLogIndex ← 0;
eventLog: ARRAY EventLogIndex OF RavenControl.EngineEvent ← ALL[idle];
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;
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: CARD ← LONG[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;
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: BOOLEAN ← FALSE; -- 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
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[].