//bldr xjas jasmc jasswat loadram get "bcpl.head" //outgoing procedures external [ JasmineInit JasmineSetDelay //(delay=0 to 15) JasmineSetResolution //(skips=0 to 15) JasmineSetTime //(ticks = 38usecond units) JasmineLoadRam //(array, len) JasmineScanInit //(block,nWords) returns scanHead JasmineScanClose //(scanHead) JasmineReadLine //(scanHead) returns pointer to scan line JasmineSetReadMode //readOnly=1, readAndStep=2, readStepAndDelay=3 JasmineStep //(nSteps,forward) JasmineSetWindow //(xstart,xlen) in full resolution coords (250 microns) JasmineCoord //(coord) returns # samples JasmineNewPage //(pageLen) (>100 = 250u, <100=inches) JasmineEject //eject current page JasmineMotorOff ] //incoming procedures external [ LoadRam JasmineSwatContextProc ] //incoming statics external RamImage //internal statics static [ SetBLV savedEmulatorX;savedDWTX ] manifest [ SafeLoc=#177022 StepLoc=#177020 Outport=#177016 ITQUAN=#422 ITIBITS=#423 ITTIME=#525 ScanTime=#526 ScanCBHead=#736 StartCommand=#737 ] manifest [ START=7 LOAD=6 MOTORCTL=5 WE1=3 WE2=2 WE3=1 SETDELAY=0 StatusINUSE = 1 //in general, all positive numbers are "in use" flags StatusFREE = 0 StatusDONE = -1 StatusDATALATE = -2 CommandREAD = 0 CommandDELAY = 1 CommandFORWARD = 2 CommandBACK = 3 ] structure dataOut : [ blank byte enable bit command bit 3 data bit 4 ] structure ScanCB : [ link word command word status word buffer word ] structure ScanHead : [ firstCB word nBlocks word nextBlock word nCBsPerBlock word nScanLines word ] structure ramVal : [ q1 bit 4 q2 bit 4 q3 bit 4 q4 bit 4 ] structure Array : [ pixel^0,1000 byte ] static [ DelaySetting=15;SkipSamples=0;ArraySize=1024 Time=656 //38 usec ticks = 1/40 sec forward = true; StepCommand Late=0;Bad=0 Bug=0 maxNumBlocks=10 ReadMode=2 //Read,Step,Delay savedUFP;savedSCP ScannerTaskBits=#177376 StepTime=130 //200 steps/second //StepperSlip=6//direction reversal causes this many slip steps on old model StepperSlip=0 TopBlank=120 nDiscardElements=0 nElements=1024 currentScanLine=-1 //not active firstScanLine=-1 nScanLines=#77777 ] manifest Reverse=false //mirror reversal; to switch Reverse, also use different ucode let JasmineInit() be [ savedUFP=@lvUserFinishProc @lvUserFinishProc=JasmineFinish savedSCP=@lvSwatContextProc @lvSwatContextProc=JasmineSwatContextProc Init() SendCommand(SETDELAY,DelaySetting) @ScanCBHead=0 LoadRam(RamImage,true) @#335 = RamImage InitStartCommand() @ScanTime=Time SetBLV=table [ #70002;#1401] ] and JasmineSetDelay(delay) be [ DelaySetting=delay ScannerOff() SendCommand(SETDELAY,DelaySetting) ScannerOn() ] and JasmineSetResolution(skips) be [ SkipSamples=skips InitStartCommand() ] and JasmineSetReadMode(mode) be [ ReadMode=mode ] and JasmineNewPage(length) be [ JasmineStep(TopBlank,true) forward=true currentScanLine=0 ] and JasmineEject() be [ if (firstScanLine ge 0) then [ JasmineStep(currentScanLine,false) JasmineStep(TopBlank+50,false) firstScanLine=-1 ] ] and JasmineCoord(c) = c/(SkipSamples+1) and JasmineSetWindow(xStart,xLen,yStart,yLen;numargs na) be [ if na ge 4 then [ firstScanLine=yStart nScanLines=yLen ] compiletest Reverse then [ nDiscardElements=ArraySize-(xStart+xLen) ] or [ nDiscardElements=xStart ] nElements=xLen ] and JasmineSetTime(ticks) be [ Time=ticks @ScanTime=Time ] and JasmineLoadRam(ramVec,nElements;numargs n) be [ if n ls 2 then nElements=1024 ScannerOff() SendCommand(SETDELAY,0) //enable addr counting during load Init() //for i=1 to 32 do SendCommand(LOAD);Init() //to fix delay count?? //bug in jasminepromgen: never get to first ram loc //for i=1 to 1000 do [ ] //wait for start pulse to finish (4 msec) let load=0;load<>ScanHead.firstCB=block+(size ScanHead/16) block>>ScanHead.nBlocks=nBlocks block>>ScanHead.nextBlock=0 block>>ScanHead.nCBsPerBlock=ReadMode+SkipSamples+nDiscardCommands block>>ScanHead.nScanLines=nScanLines if (firstScanLine ge 0) & (currentScanLine ne firstScanLine) then [ JasmineStep(firstScanLine-currentScanLine,forward) currentScanLine=firstScanLine ] let blockBase=block+(size ScanHead/16) @ScanCBHead=0 @ScanTime=Time StepCommand=forward?CommandFORWARD,CommandBACK let scanHead=table [ 0;CommandDELAY;0] //funny first time bug scanHead!0=0 scanHead!2=StatusINUSE for i=0 to nBlocks-1 do NewReadCommand(block,i,lv scanHead) @ScanCBHead=scanHead resultis block ] and JasmineScanClose(s) be [ @ScanTime=0 [ @ScanCBHead=0] repeatuntil JasmineReadLine(s,false) eq 0 @ScanCBHead=0 //this is foolish, but be safe @ScanTime=Time ] and JasmineReadLine(s,continue;numargs na) = valof [ if na ls 2 then continue=true if s>>ScanHead.nScanLines le 0 then continue=false let thisBlock=s>>ScanHead.nextBlock let lastBlock=(thisBlock eq 0)?(s>>ScanHead.nBlocks-1),thisBlock-1 let nCBsPerBlock=s>>ScanHead.nCBsPerBlock let lastBlockptr=s>>ScanHead.firstCB+lastBlock*nCBsPerBlock*(size ScanCB/16) if lastBlockptr>>ScanCB.status eq StatusFREE then //queue up new command if continue then NewReadCommand(s,lastBlock) let thisBlockptr=s>>ScanHead.firstCB+thisBlock*nCBsPerBlock*(size ScanCB/16) let thisBlockend=thisBlockptr+(nCBsPerBlock-1)*(size ScanCB/16) while (thisBlockend>>ScanCB.status ge 0)& (@ScanCBHead ne 0) do Idle() let nDiscards = 0 if thisBlockptr>>ScanCB.buffer eq 0 then //was a discard [ thisBlockptr>>ScanCB.status=StatusFREE thisBlockptr=thisBlockptr + (size ScanCB/16) nDiscards=1 ] //if user has changed ReadMode or SkipSamples or Window without calling //JasmineScanInit, then we're in trouble if nCBsPerBlock ne (ReadMode+SkipSamples+nDiscards) then CallSwat("missing JasmineScanInit") let blockStatus=thisBlockptr>>ScanCB.status s>>ScanHead.nextBlock=(thisBlock eq (s>>ScanHead.nBlocks-1))?0,thisBlock+1 thisBlockptr>>ScanCB.status = StatusFREE if blockStatus eq StatusDONE then [ if firstScanLine ge 0 then currentScanLine=currentScanLine+SkipSamples+1 s>>ScanHead.nScanLines=s>>ScanHead.nScanLines-(SkipSamples+1) resultis thisBlockptr>>ScanCB.buffer ] unless continue do resultis 0 if blockStatus eq StatusDATALATE then [ Late=Late+1 //CallSwat("DataLate") JasmineSetDelay(DelaySetting); // @ScanCBHead=thisBlockend>>ScanCB.link let dummy = table[ 0;CommandDELAY;0] //funny first time bug dummy!0=thisBlockend>>ScanCB.link dummy!2=StatusINUSE @ScanCBHead=dummy resultis JasmineReadLine(s) //thisBlockptr>>ScanCB.buffer // resultis thisBlockptr>>ScanCB.buffer ] Bad=Bad+1 //CallSwat("Bad") resultis 0 //NextScanLine(s) ] and ScannerOn() be [ let savedEmu=@#177740;let savedDWT=@#177751 SetBLV(ScannerTaskBits);StartIO(#100000) @#177740=savedEmu;@#177751=savedDWT ] and ScannerOff() be [ let savedEmu=@#177740;let savedDWT=@#177751 SetBLV(#177776);StartIO(#100000) @#177740=savedEmu;@#177751=savedDWT ] and JasmineFinish(code) be [ ScannerOff() @lvUserFinishProc=savedUFP @lvSwatContextProc=savedSCP for i=0 to 15 do #177740!i = 0 finish ] and NewReadCommand(block,num,scanHead;numargs na) be [ if na ls 3 then scanHead = ScanCBHead let nDiscardBytes=(nDiscardElements/(SkipSamples+1))𫙰 //even let nBytes = ((nElements+SkipSamples)/(SkipSamples + 1)+1)𫙰 //even let nWords = (nBytes+1)/2 let nCBsPerBlock=block>>ScanHead.nCBsPerBlock let base=block>>ScanHead.firstCB + num*nCBsPerBlock*(size ScanCB/16) let bufferBase = block>>ScanHead.firstCB + (block>>ScanHead.nBlocks)*nCBsPerBlock*(size ScanCB/16) let thisCB=base if nDiscardBytes gr 0 then [ thisCB>>ScanCB.link = thisCB + (size ScanCB/16) thisCB>>ScanCB.command = CommandREAD thisCB>>ScanCB.status = nDiscardBytes thisCB>>ScanCB.buffer = 0 thisCB=thisCB + (size ScanCB/16) ] thisCB>>ScanCB.link = thisCB + (size ScanCB/16) thisCB>>ScanCB.command = CommandREAD thisCB>>ScanCB.status = nBytes thisCB>>ScanCB.buffer = bufferBase + num*nWords if ReadMode gr 1 then [ for y=0 to SkipSamples do [ thisCB=thisCB + (size ScanCB/16) thisCB>>ScanCB.link = thisCB + (size ScanCB/16) thisCB>>ScanCB.command = StepCommand thisCB>>ScanCB.status = StatusINUSE ] if ReadMode gr 2 then [ thisCB=thisCB + (size ScanCB/16) thisCB>>ScanCB.link = thisCB + (size ScanCB/16) thisCB>>ScanCB.command = CommandDELAY thisCB>>ScanCB.status = StatusINUSE ] ] thisCB>>ScanCB.link = 0 let link=scanHead //the following code doesn't work: // until @link eq 0 do link = @link //because if link eq scanHead, then //between the test for "eq 0" and the assignment, scanHead may be zeroed //by the ucode, causing us to add a chain through 77400 (@0) [ let newLink=@link if newLink eq 0 then break if newLink!2 ls 0 then //possible infinite loop bug [ let first=@scanHead let link = first [ let newLink = @link if newLink eq 0 then break if newLink eq first then [ CallSwat("Bug") Bug=Bug+1 @link=0 break ] link = newLink ] repeat ] link=newLink ] repeat @link = base if @scanHead eq 0 then @scanHead=base ] and JasmineStep(nSteps,forwardBoolean) be [ let reversed=nSteps ls 0 if reversed then [ forwardBoolean = not forwardBoolean nSteps=-nSteps ] let v=vec (size ScanCB/16) v>>ScanCB.link=0 if forward ne forwardBoolean then nSteps=nSteps+StepperSlip v>>ScanCB.command=forwardBoolean?CommandFORWARD,CommandBACK until @ScanCBHead eq 0 do [ ] @ScanTime=StepTime for i=1 to nSteps do [ v>>ScanCB.status = StatusINUSE @ScanCBHead=v until v>>ScanCB.status eq StatusDONE do [ ] ] if reversed then //set forward, take up slack for i=1 to StepperSlip do [ v>>ScanCB.command=forwardBoolean?CommandBACK,CommandFORWARD v>>ScanCB.status = StatusINUSE @ScanCBHead=v until v>>ScanCB.status eq StatusDONE do [ ] ] forward=reversed?(not forwardBoolean),forwardBoolean @ScanTime=Time ] and Init() be [ SendCommand(LOAD);SendCommand(START)] and JasmineMotorOff() be SendCommand(MOTORCTL,4) and InitStartCommand() be [ @StartCommand=0 StartCommand>>dataOut.command=START StartCommand>>dataOut.data=SkipSamples ] and SendCommand(command,value;numargs na) be [ if na ls 2 then value=0 let dataWord=0 dataWord<