//J A S M I N E C A L I B R A T E

get "bcpl.head"

//outgoing procedures
external JasmineCalibrate

//incoming procedures
external
[
JasmineLoadRam
JasmineCoord
JasmineScanInit
JasmineReadLine
JasmineSetDelay//(delay=0 to 15)
JasmineSetTime//(ticks = 38usecond units)
JasmineSetResolution//(skips=0 to 15)
JasmineSetReadMode//readOnly=1, readAndStep=2, readStepAndDelay=3
JasmineSetWindow
JasmineScanClose

//from GP
SetupReadParam;ReadParam

//from PressML
MulFull;DoubleAddV;MulDiv;DoubleShr
]


structure Array :
[ pixel↑0,1000
byte
]

structure JasmineRam :
[
blankbit 4
Offsetbit 6
Gainbit 6
]

manifest ArraySize = 1024


static
[
nAverages=8;
A=7;B=8//threshold for page edge detection
mulA=4;mulB=3 //factor for setting gain multiplier
]

//calibrate routine returns a block with:
//
xstart,xlen of page
//
min,max for 656 time, skip 0
//
min,max for 219 time, skip 1
let JasmineCalibrate() = valof
[
let resultThingy = table [ 0;0;0;0;0;0]
let saved420=@#420
@#420=@saved420
let ramvals = vec ArraySize
let block=vec 512*4
let targetGain=0;let targetOffset=0
let ramVal=0;
ramVal<<JasmineRam.Offset=64-10//targetOffset
ramVal<<JasmineRam.Gain=targetGain
SetBlock(ramvals,ramVal,ArraySize)

JasmineLoadRam(ramvals,ArraySize)
JasmineSetDelay(15)
JasmineSetResolution(0)
JasmineSetTime(656)//1/40 sec

let inputArray=vec ArraySize
let min,max=nil,nil

let lastCorrection=0
JasmineSetWindow(0,1024,100,300)
JasmineSetReadMode(3)//read, step, and delay (for constant integration time)
[ //white repeat loop
let scanHead = JasmineScanInit(block,512*4)
for i=1 to 4 do JasmineReadLine(scanHead) //first few lines seem to be garbage...
Zero(inputArray,ArraySize)
for average=1 to nAverages do
[let scanLine=JasmineReadLine(scanHead)
for x=0 to ArraySize-1 do
inputArray!x=inputArray!x+scanLine>>Array.pixel↑x
]
JasmineScanClose(scanHead)
max=0;min=256
for x=0 to ArraySize-2 do//-2 for Prom bug
[let val=(inputArray!x)/nAverages
inputArray!x=val
if val ls min then min=val
if val gr max then max=val
]
Ws("Min: ");Wns(dsp,min);Ws(" Max: ");Wns(dsp,max)
if targetGain eq 0 then targetGain=max
let newCorrection=0
for x=0 to ArraySize-1 do
[let currentVal=(ramvals!x)<<JasmineRam.Gain
let correction=targetGain - inputArray!x
if inputArray!x ls 10 then correction=correction-256//wrap around
if correction ls 100 then newCorrection=newCorrection+abs(correction)
let newVal=currentVal + (correction*mulA)/mulB
if newVal ls 0 then newVal=0
if newVal gr 63 then newVal=63
(ramvals!x)<<JasmineRam.Gain=newVal
]
Ws(" [");Wns(dsp,newCorrection);Ws("] ")
if (lastCorrection ne 0)&(newCorrection gr lastCorrection) then break
JasmineLoadRam(ramvals,ArraySize)

lastCorrection=newCorrection
] repeat//white repeat loop

//now, calculate xstart, xend for 8.5 inches
let thresh = min + ((max-min)*A)/B
for x=1 to 1000 do if inputArray!x gr thresh then [ resultThingy!0=x;break]
for x=1000 to 1 by -1 do if inputArray!x gr thresh then
[ resultThingy!1=x-resultThingy!0;break]
resultThingy!2=min
resultThingy!3=max
//and high speed chase
JasmineSetDelay(4)
JasmineSetResolution(1)
JasmineSetTime(219)
let scanHead = JasmineScanInit(block,512*4)
for i=1 to 20 do JasmineReadLine(scanHead)
min=256;max=0
inputArray=JasmineReadLine(scanHead)
JasmineScanClose(scanHead)
for x=1 to 500 do
[let val=inputArray>>Array.pixel↑x
if val ls min then min=val
if val gr max then max=val
]
JasmineSetDelay(15)
JasmineSetResolution(0)
JasmineSetTime(656)
JasmineSetReadMode(2)
resultThingy!4=min
resultThingy!5=max
@#420=saved420
resultis resultThingy
]

and abs(x)=(x ge 0)?x,-x