DIRECTORY
IODefs: FROM "IODefs",
JasmineDefs: FROM "JasmineDefs",
MiscDefs: FROM "MiscDefs" USING [Zero,SetBlock],
SystemDefs: FROM "SystemDefs";

JasmineCalibrate: PROGRAM IMPORTS IODefs, MiscDefs, JasmineDefs, SystemDefs EXPORTS JasmineDefs =
BEGIN OPEN JasmineDefs;

JasmineRam: TYPE = RECORD
[
blank: [0..17B],
Offset: [0..77B],
Gain: [0..77B]
];

A: INTEGER ← 4;
B: INTEGER ← 3;

p420: POINTER TO UNSPECIFIED = LOOPHOLE[420B];
nAverages: CARDINAL ← 8;

JasmineCalibrate: PUBLIC PROCEDURE =
BEGIN
saved420: POINTER TO POINTER ← p420↑;
targetGain,targetOffset: CARDINAL ← 0;
scanHead: POINTER TO ScanHead;
scanLine: POINTER TO PACKED ARRAY OF [0..377B];
x: CARDINAL;
ramVal: JasmineRam ← [0,64-10,0];
ramvals: POINTER TO ARRAY [0..1024) OF JasmineRam ←
SystemDefs.AllocateSegment[1024];
inputArray
: POINTER TO ARRAY [0..1024) OF CARDINAL ←
SystemDefs.AllocateSegment[1024];
min,max,lastCorrection,newCorrection: CARDINAL;
currentVal: CARDINAL;
correction,newVal: INTEGER;

--turn off display
p420↑ ← saved420↑;

--first, initialize
MiscDefs.SetBlock[ramvals,ramVal,1024];
JasmineLoadRam[LOOPHOLE[ramvals]];
--JasmineSetDelay[14];
JasmineSetResolution[0];
--JasmineSetTime[656];


lastCorrection←0;
JasmineSetWindow[0,1024,100,300];
JasmineSetReadMode[3];
--read, step, and delay [for constant integration time]
DO --white repeat loop
scanHead ← JasmineScanInit[];
MiscDefs.Zero[inputArray,1024];
THROUGH[1..nAverages] DO
scanLine ← JasmineReadLine[scanHead];
FOR x IN [0..1024) DO
inputArray[x] ← inputArray[x] + scanLine[x];
ENDLOOP;
ENDLOOP;
JasmineScanClose[scanHead];
max←0;min←256;
FOR x IN [1..1024) DO
inputArray[x] ← inputArray[x]/nAverages;
IF inputArray[x] < min THEN min ← inputArray[x];
IF inputArray[x] > max THEN max ← inputArray[x];
ENDLOOP;
IODefs.WriteString["Min: "];IODefs.WriteDecimal[min];
IODefs.WriteString[" Max: "];IODefs.WriteDecimal[max];
IF targetGain = 0 THEN targetGain ← max;
IF ABS[INTEGER[targetGain-max]] > 3 THEN A ← MAX[1,A-1];
newCorrection ← 0;
FOR x IN [1..1024) DO
currentVal ← ramvals[x].Gain;
correction ← targetGain - inputArray[x];
IF inputArray[x] < 10 THEN correction ← correction-256;
IF correction < 100 THEN newCorrection ← newCorrection+ABS[correction];
IF correction<0 THEN newVal←currentVal+correction ELSE
newVal←currentVal + (correction*A)/B;
IF newVal < 0 THEN newVal←0;
IF newVal > 63 THEN newVal←63;
ramvals[x].Gain←newVal;
ENDLOOP;
IODefs.WriteString[" ["];IODefs.WriteDecimal[newCorrection];
IODefs.WriteString["] "];
IF (lastCorrection # 0) AND (newCorrection > lastCorrection) THEN EXIT;
JasmineLoadRam[LOOPHOLE[ramvals]];
lastCorrection ← newCorrection;
ENDLOOP;
--white repeat loop

JasmineSetReadMode[2];
p420↑ ← saved420;
END;

END.