PlatemakerControlImpl.mesa
Copyright Ó 1987 by Xerox Corporation. All rights reserved.
Tim Diebert: April 21, 1987 9:40:44 am PDT
DIRECTORY
Basics USING [BITAND, bitsPerWord, LongMult],
CountedVM USING [Free, Handle, SimpleAllocate],
DoradoInputOutput USING [ExternalInput, StopEventCounters],
FontTune USING [CreateFontTuner],
Imager USING [Context],
ImagerBitmapContext USING [Brick, Create, SetBitmap, SetBrick],
ImagerBrick USING [Brick, BrickFromDotScreen],
ImagerDevice USING [FontTuner],
ImagerSample USING [Clear, GetBase, GetBitsPerLine, GetBitsPerSample, GetRef, GetSize, MapFromVM, RasterSampleMap],
Loader USING [MakeProcedureResident, MakeGlobalFrameResident],
PlatemakerControl USING [PrinterParameters, PrinterParametersRec],
PrincOps USING [bitsPerWord],
PrincOpsUtils USING [LongZero],
Process USING [CheckForAbort, MsecToTicks, Pause, priorityForeground, priorityNormal, SetPriority, Yield],
RasterControllerDorado,
RasterControllerFace,
Rope USING [Cat, ROPE],
StorageAccounting USING [CollectionInterval],
SafeStorage USING [SetCollectionInterval],
UserProfile USING [Boolean, CallWhenProfileChanges, Number, ProfileChanged, ProfileChangedProc],
VM USING [AddressForPageNumber, Free, Interval, Pin, SimpleAllocate, Unpin, PagesForWords];
PlatemakerControlImpl: CEDAR PROGRAM
IMPORTS Basics, CountedVM, DoradoInputOutput, -- FontTune, -- ImagerBitmapContext, ImagerBrick, ImagerSample, Loader, PrincOpsUtils, Process, RasterControllerFace, Rope, SafeStorage, StorageAccounting, UserProfile, VM
EXPORTS PlatemakerControl
~ BEGIN OPEN RasterControllerDorado, RasterControllerFace;
ROPE: TYPE ~ Rope.ROPE;
MakePrinterSampleMap: PUBLIC PROC RETURNS [pixelMap: ImagerSample.RasterSampleMap] = BEGIN
fBits: NAT ← currentParameters.fSize;
sSize: NAT ← currentParameters.sSize;
wordsPerLine: NAT ~ ((fBits+255)/256) * 16; -- Integral number of munches.
words: LONG CARDINAL ~ Basics.LongMult[wordsPerLine, sSize];
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: [sSize, fBits]],
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;
FreePrinterSampleMap: PUBLIC PROC [pixelMap: ImagerSample.RasterSampleMap] = BEGIN
vm: CountedVM.Handle ← NARROW[ImagerSample.GetRef[pixelMap]];
interval: VM.Interval ~ vm.interval;
VM.Unpin[interval];
TRUSTED {CountedVM.Free[vm]};
END;
ContextFromSampleMap: PUBLIC PROC [sampleMap: ImagerSample.RasterSampleMap,
fontTunerParms: Rope.ROPENIL] RETURNS [context: Imager.Context] = BEGIN
fontTuner: ImagerDevice.FontTuner ← NIL;
IF fontTunerParms # NIL THEN fontTuner ← FontTune.CreateFontTuner[fontTunerParms];
context ← ImagerBitmapContext.Create[deviceSpaceSize: ImagerSample.GetSize[sampleMap], scanMode: [slow: down, fast: right], surfaceUnitsPerInch: [1200, 1200], pixelUnits: FALSE, fontCacheName: $PrinterBitmap, fontTuner: NIL];
ImagerBitmapContext.SetBitmap[context, sampleMap];
ImagerBitmapContext.SetBrick[context, brick];
ImagerSample.Clear[sampleMap];
END;
brick: ImagerBitmapContext.Brick;
PrintMap: PUBLIC PROC [sampleMap: ImagerSample.RasterSampleMap]
RETURNS [succeeded: BOOLEANTRUE] ~ TRUSTED {
Sends the n SampleMaps to the printer hardware, in order. Printer parameters are based on the printer parameter passed in during the GetMaps call. Fails if the id doesn't match the one currently in control.
ENABLE UNWIND => NULL;
oldGC: INT ← StorageAccounting.CollectionInterval;
IF NOT CheckConfig[].rastAHere THEN ERROR; -- PrinterTrouble["RastA board not present."];
{
ENABLE
UNWIND => {
ShutupMicrocode[];
[]← SafeStorage.SetCollectionInterval[oldGC];
Process.SetPriority[Process.priorityNormal];
succeeded ← FALSE;
FlushQueue[];
};
InitializeRCBChain: PROC [
bitmap: LONG POINTER,
words: CARDINAL,
lines: CARDINAL,
fMargin: CARDINAL ← 0,
sMargin: INTEGER ← 2700,
sRepeat, fRepeat: INTEGER ← 0,
sReverse, fReverse: BOOLEANFALSE,
fMosaic: BOOLEANFALSE,
sSkip: CARDINAL ← 0,
bitsPerSample: [0..bitsPerWord] ← 1,
invert: BOOLFALSE] ~ TRUSTED {
InitializeRCB[rcb: tailRCB];
InitializeCCB[ccb: tailCCB, halftoneCtl: [invertMask: ~invert]];
InitializeRCB[
rcb: mainRCB,
next: tailRCB,
bitmap: bitmap,
activeWordsPerLine: words,
wordsPerLine: words*(sSkip+1),
lines: lines,
fMargin: fMargin,
sRepeat: sRepeat,
fRepeat: fRepeat,
sReverse: sReverse,
fReverse: fReverse,
mosaic: fMosaic,
bitsPerSample: bitsPerSample
];
InitializeCCB[
ccb: mainCCB,
next: tailCCB,
lines: lines,
halftoneCtl: [invertMask: ~invert]
];
IF sMargin > 0 THEN {
InitializeRCB[rcb: leadRCB, next: mainRCB, lines: sMargin];
InitializeCCB[ccb: leadCCB, next: mainCCB, lines: sMargin, halftoneCtl: [invertMask: ~invert]];
mrb.rcb[A] ← leadRCB;
mrb.ccb ← leadCCB;
}
ELSE {mrb.rcb[A] ← mainRCB; mrb.ccb ← mainCCB};
};
i: VM.Interval ← VM.SimpleAllocate[1];
leadRCB: RCBPointer ← LOOPHOLE[VM.AddressForPageNumber[i.page]];
i2: VM.Interval ← VM.SimpleAllocate[1];
mainRCB: RCBPointer ← LOOPHOLE[VM.AddressForPageNumber[i2.page]];
i3: VM.Interval ← VM.SimpleAllocate[1];
tailRCB: RCBPointer ← LOOPHOLE[VM.AddressForPageNumber[i3.page]];
i4: VM.Interval ← VM.SimpleAllocate[1];
leadCCB: CCBPointer ← LOOPHOLE[VM.AddressForPageNumber[i4.page]];
i5: VM.Interval ← VM.SimpleAllocate[1];
mainCCB: CCBPointer ← LOOPHOLE[VM.AddressForPageNumber[i5.page]];
i6: VM.Interval ← VM.SimpleAllocate[1];
tailCCB: CCBPointer ← LOOPHOLE[VM.AddressForPageNumber[i6.page]];
ib: VM.Interval ← VM.SimpleAllocate[2 * hardwareScanlinePages];
zeros: LONG POINTERVM.AddressForPageNumber[ib.page];
repCnt: INTEGER ← currentParameters.sRepeat;
copyCnt: INT ← 0;
VM.Pin[ib];
PrincOpsUtils.LongZero[zeros, 2 * hardwareScanlineWords]; -- fill the scan line with zeros
VM.Pin[i]; VM.Pin[i2]; VM.Pin[i3]; VM.Pin[i4]; VM.Pin[i5]; VM.Pin[i6];
InitializeRCBChain[bitmap: zeros, words: hardwareScanlineWords, lines: 2, sMargin: 0];
ResetMicrocode[];
SetUpForRosClock[];
SetUpForRealLineSync[];
[] ← StartMicrocode[mrb];
Process.Pause[Process.MsecToTicks[1000]]; -- wait for microcode to transfer data
ShutupMicrocode[];
zeros ← NIL;
InitializeRCBChain[
bitmap: ImagerSample.GetBase[sampleMap].word,
words: ImagerSample.GetBitsPerLine[sampleMap]/PrincOps.bitsPerWord,
lines: ImagerSample.GetSize[sampleMap].s/(currentParameters.sSkip+1),
fMargin: currentParameters.fMargin,
sMargin: currentParameters.sMargin,
sRepeat: repCnt,
fRepeat: currentParameters.fRepeat,
sReverse: currentParameters.sReverse,
fReverse: currentParameters.fReverse,
sSkip: currentParameters.sSkip,
fMosaic: currentParameters.fMosaic,
bitsPerSample: ImagerSample.GetBitsPerSample[sampleMap]
];
[] ← SafeStorage.SetCollectionInterval[LAST[INT]/4];
Process.SetPriority[Process.priorityForeground];
FOR timer: INT ← 0, timer+1 DO
IF GetPageSync[] THEN EXIT;
Process.CheckForAbort[];
ENDLOOP;
[] ← StartMicrocode[mrb];
Process.SetPriority[Process.priorityNormal];
[] ← SafeStorage.SetCollectionInterval[oldGC];
Process.CheckForAbort[];
FOR timer: INT ← 0, timer+1 DO
IF NOT GetPageSync[] THEN EXIT;
Process.CheckForAbort[];
Process.Yield[];
ENDLOOP;
ShutupMicrocode[];
VM.Unpin[i]; VM.Unpin[i2]; VM.Unpin[i3]; VM.Unpin[i4]; VM.Unpin[i5]; VM.Unpin[i6];
VM.Unpin[ib];
VM.Free[i]; VM.Free[i2]; VM.Free[i3]; VM.Free[i4]; VM.Free[i5]; VM.Free[i6];
VM.Free[ib];
mrb.rcb[A] ← leadRCB ← mainRCB ← tailRCB ← NIL;
mrb.ccb ← leadCCB ← mainCCB ← tailCCB ← NIL;
};
};
ParseProfile: UserProfile.ProfileChangedProc = {
[reason: UserProfile.ProfileChangeReason]
ENABLE UNWIND => NULL;
currentParameters ← GetParameters[];
};
currentParameters: PlatemakerControl.PrinterParameters ← NEW[PlatemakerControl.PrinterParametersRec];
UpdateParameters: PUBLIC PROC [] = BEGIN
currentParameters ← GetParameters[];
END;
SetSMargin: PUBLIC PROC [sMargin: CARDINAL] = BEGIN
currentParameters.sMargin ← sMargin;
END;
SetFMargin: PUBLIC PROC [fMargin: CARDINAL] = BEGIN
currentParameters.fMargin ← fMargin;
END;
MakeNewBrick: PROC [pixelsPerDot: REAL ← 9, degrees: REAL ← 45.0] = BEGIN
localBrick: ImagerBrick.Brick ← ImagerBrick.BrickFromDotScreen[pixelsPerDot, degrees];
brick.maxSample ← localBrick.maxSample;
brick.sampleMap ← localBrick.sampleMap;
brick.phase ← localBrick.phase;
END;
GetParameters: PROC [] RETURNS [PlatemakerControl.PrinterParameters] ~ {
prefix: ROPE ← "Platemaker.";
pp: PlatemakerControl.PrinterParameters ← NEW[PlatemakerControl.PrinterParametersRec];
pp.fMargin ← UserProfile.Number[Rope.Cat[prefix, "fMargin"], 100];
pp.sMargin ← UserProfile.Number[Rope.Cat[prefix, "sMargin"], 1400];
pp.fSize ← UserProfile.Number[Rope.Cat[prefix, "fSize"], 12000];
pp.sSize ← UserProfile.Number[Rope.Cat[prefix, "sSize"], 13500];
pp.fDPI ← UserProfile.Number[Rope.Cat[prefix, "fDPI"], 1200];
pp.sDPI ← UserProfile.Number[Rope.Cat[prefix, "sDPI"], 1200];
pp.fRepeat ← UserProfile.Number[Rope.Cat[prefix, "fRepeat"], 0];
pp.sRepeat ← UserProfile.Number[Rope.Cat[prefix, "sRepeat"], 0];
pp.fReverse ← UserProfile.Boolean[key: Rope.Cat[prefix, "fReverse"], default: FALSE];
pp.sReverse ← UserProfile.Boolean[key: Rope.Cat[prefix, "sReverse"], default: FALSE];
pp.fMosaic ← UserProfile.Boolean[key: Rope.Cat[prefix, "fMosaic"], default: FALSE];
pp.sSkip ← UserProfile.Number[Rope.Cat[prefix, "sSkip"], 0];
pp.bpp ← UserProfile.Number[Rope.Cat[prefix, "bpp"], 1];
pp.background ← UserProfile.Number[Rope.Cat[prefix, "background"], 0];
RETURN [pp];
};
Stuff for the hardware.
The genI/O port stuff;
pageSyncMask: WORD = 100000B;
Stuff for controlling the printer engine:
GetPageSync: PROC RETURNS [pageSync: BOOL] ~ TRUSTED {
printerStatus: WORDLOOPHOLE [DoradoInputOutput.ExternalInput[]];
RETURN [Basics.BITAND[printerStatus, pageSyncMask] # 0];
};
mrbInterval: VM.Interval ~ VM.SimpleAllocate[1];
mrb: MRBPointer ← LOOPHOLE[VM.AddressForPageNumber[mrbInterval.page]];
VM.Pin[mrbInterval];
InitializeMRB[mrb];
UserProfile.CallWhenProfileChanges[proc: ParseProfile];
UserProfile.ProfileChanged[reason: firstTime];
Loader.MakeProcedureResident[PrintMap];
Loader.MakeGlobalFrameResident[PrintMap];
TRUSTED {DoradoInputOutput.StopEventCounters[]};
END.