'Mike, this one set up to take blocks of 4000 lines. See 'LinesPerBlock Function key 2 will ask for a temperature 'setting. 0.2 will give about -19 C a good place to run 'Pick a value for the temperatre setting that causes ITEC 'to run near the middle of its range. .7 to 1. This will 'assure it has some range to go down as the telescope cools 'down durning the night. Smaller numbers give a more negative 'temperature. i.e. 0.15 gives about -25 C. No need to run 'below -20 or so, as the dark current is well below possible 'sky values there. 'OK Norman, here it is. This code is used to run the triplet, 'but I have tested it with this single unit camera. Unfortunately, 'without chips in place, zero is below -10 volts and so reads out '-32768. I would just write code that follows the addressing scheme 'in this code for camera 1 and camera 3. This version as of '6 April 1996. I have added a few comments, but the really 'commented code is tass1c.bas 'you are asked for a file name and the number of lines to take. 'the program breaks the number of lines selected into 4000 line 'blocks and adds appropriate numbers to indicate the camera and 'block piece from that camera. 'function key 1 does a full clear by doing many horizontal clears and 'many vertical clears. function key 2 sets the temperature command 'does nothing for this unit. 'this will be the working program to take data. straight in 'line code to keep it as simple as possible. '************************************************************** '************************************************************** '***** here set up the necessary conditions DEFINT A-Z SCREEN 9, 0 WIDTH 80, 43 '************************************************************** '***** the following defines a data type for use with the QB 'random file format. TYPE SkyType1 Datex AS STRING * 10 'the date in every line Timex AS STRING * 8 'the time in every line LineSet1(1 TO 796) AS INTEGER 'all the pixels including blank Singlex(1 TO 6) AS SINGLE 'for other measured values Integerx(1 TO 6) AS INTEGER 'some spares END TYPE TYPE SkyType2 Datex AS STRING * 10 'the date in every line Timex AS STRING * 8 'the time in every line LineSet2(1 TO 796) AS INTEGER 'all the pixels including blank Singlex(1 TO 6) AS SINGLE 'for other measured values Integerx(1 TO 6) AS INTEGER 'some spares END TYPE TYPE SkyType3 Datex AS STRING * 10 'the date in every line Timex AS STRING * 8 'the time in every line LineSet3(1 TO 796) AS INTEGER 'all the pixels including blank Singlex(1 TO 6) AS SINGLE 'for other measured values Integerx(1 TO 6) AS INTEGER 'some spares END TYPE DIM kk AS SkyType1 DIM ll AS SkyType2 DIM mm AS SkyType3 DIM LineSet1(1 TO 796) DIM LineSet2(1 TO 796) DIM LineSet3(1 TO 796) DIM Singlex!(1 TO 6) DIM Integerx(1 TO 6) '************************************************************** '***** Port Definitions Basex = &H300 Onex = 1 Twox = 2 Threex = 3 Zerox = 0 PathSetupPort = Basex + Zerox AuxilliaryLoadPort = Basex + Onex DACSetupPort = Basex + Twox DACLoadPort = Basex + Threex DataInPort = Basex + Zerox ReadyInPort = Basex + Onex AuxInPort = Basex + Twox SelectTransferPort = Basex + Threex '************************************************************** '***** here is an alphabetical list of all the constants 'we create specific I/O words here to do the things we want to 'do. for details of the bits see the program tass1c.bas which 'has more than enough information - some of it even correct. AddressDACHighOrderTemp = &H70 AddressDACHighOrderVCO = &HB3 'mid pulse rate range AddressDACLowOrderTemp = &H48 AddressDACLowOrderVCO = &H8B 'mid pulse rate range AddressForClear = &H0 'address to do vertical clear ClearPulses = 1000 CurrentLine = 1 'the working line number Endx = 0 HighBit = 128 LinePixelCount = 794 LinesPerBlock = 4000 FullCount = 794 'read the code in tass1c.bas to figure out how we address the 'cameras. these work no matter what tass1c says. Appropriate 'combinations select the ADC high and low byte, and either 'do a horizontal shift and start the ADC or just start the ADC 'i.e. only do the shift and start for the first channel, after 'that just address the next channel and start the ADC without 'the shift. NoShiftAndStart2 = &H26 NoShiftAndStart3 = &H3E Pixels = 796 ReadLowByte1 = &H33 'C1=&H33 C2=&H23 C3= &H3B ReadLowByte2 = &H23 ReadLowByte3 = &H3B ResetReady = &H1 SelectResetControl = &H1 ScreenScale = 200 ShiftAndStart1 = &H34' 24for camera 3 '&H34 for camera 2 3C for 1' ShiftAndStart2 = &H24 ShiftAndStart3 = &H3C ShortCount = 50 Sumx! = 0 Testx = 128 Valuex& = 0 'use the vco setting marked on the power supply on the control 'card as a starting point. Sorry it is not as stable as I would 'like, so allow the card to warm up thoroughly before fussing with 'this value. A couple of settings, and a few minutes with a stop 'watch will allow getting this to the right value which is 0.916 'seconds per line at the equator. VCOSetting = 15965'15965'15930'15965'10870'17000 10259 is close '10200 =87 '10000=89 '9700 = .92 second period VerticalLine = 0 '************************************************************* '***** here we set up some keys for special functions ON KEY(1) GOSUB ClearCCD KEY 1, "ClrCCD" KEY(1) ON ON KEY(2) GOSUB SetTheTemperature KEY 2, "SetTmp" KEY(2) ON ON KEY(3) GOSUB SetTheVCO KEY 3, "SetVCO" KEY(3) ON ON KEY(4) GOSUB SetBlockLength KEY 4, "Block" KEY(4) ON ON KEY(5) GOSUB StartIt KEY 5, "Start" KEY(5) ON ON KEY(6) GOSUB KillIt KEY 6, "Exit" KEY(6) ON KEY ON StartIt = 0 DO UNTIL StartIt = 1 LOOP '************************************************************** '***** here we ask for input data for this run LOCATE 10, 1 INPUT "Enter File Name With No Extension "; PlotFileName$ LOCATE 11, 1 INPUT "Enter Number of Lines to Take, About 3930 lines per hour "; LinesToTake! LOCATE 12, 1 PRINT "VCO Setting is: "; VCOSetting LOCATE 13, 1 PRINT "Lines Per Block is: "; LinesPerBlock GOSUB ClearCCD 'to clear out any charge 'also turn on the vertical clock '************************************************************** '***** The main loop - wait here for a clock tick 'now ramp up to full signal before taking data Endx = 0 CurrentBlock = 1 PlotFileNameSave$ = PlotFileName$ PlotFileName1$ = PlotFileNameSave$ + "1" + LTRIM$(RTRIM$(STR$(CurrentBlock))) + ".DAT" PlotFileName2$ = PlotFileNameSave$ + "2" + LTRIM$(RTRIM$(STR$(CurrentBlock))) + ".DAT" PlotFileName3$ = PlotFileNameSave$ + "3" + LTRIM$(RTRIM$(STR$(CurrentBlock))) + ".DAT" OPEN PlotFileName1$ FOR RANDOM AS #1 LEN = LEN(kk) OPEN PlotFileName2$ FOR RANDOM AS #2 LEN = LEN(ll) OPEN PlotFileName3$ FOR RANDOM AS #3 LEN = LEN(mm) LinesToTakeSave! = LinesToTake! LinesToTake! = 512 DO UNTIL Endx = 1 'set to 1 when run is complete Testx = INP(ReadyInPort) IF Testx < 128 THEN GOSUB TakeADataLine LOOP LOCATE 2, 1 PRINT "Ramp Up Done" SOUND 1000, 1 CLS CLOSE #1 CLOSE #2 CLOSE #3 'now start taking LinesPerBlock line blocks BlocksToTake = INT(LinesToTakeSave! / LinesPerBlock) LinesToTake! = LinesPerBlock FOR CurrentBlock = 1 TO BlocksToTake PlotFileName1$ = PlotFileNameSave$ + "1" + LTRIM$(RTRIM$(STR$(CurrentBlock))) + ".DAT" PlotFileName2$ = PlotFileNameSave$ + "2" + LTRIM$(RTRIM$(STR$(CurrentBlock))) + ".DAT" PlotFileName3$ = PlotFileNameSave$ + "3" + LTRIM$(RTRIM$(STR$(CurrentBlock))) + ".DAT" OPEN PlotFileName1$ FOR RANDOM AS #1 LEN = LEN(kk) OPEN PlotFileName2$ FOR RANDOM AS #2 LEN = LEN(ll) OPEN PlotFileName3$ FOR RANDOM AS #3 LEN = LEN(mm) CurrentLine = 1 Endx = 0 DO UNTIL Endx = 1 'set to 1 when run is complete Testx = INP(ReadyInPort) IF Testx < 128 THEN GOSUB TakeADataLine LOOP CLOSE #1 CLOSE #2 CLOSE #3 LOCATE 2, 1 PRINT "Done" + STR$(CurrentBlock) NEXT CurrentBlock END '************************************************************** '***** Below are subroutines in alphabetical order ClearCCD: 'takes about 24 seconds LOCATE 1, 1 PRINT "Clearing the CCD - Counts to 1000" LinePixelCount = ShortCount OUT (DACSetupPort), AddressForClear 'setup to do vertical clear FOR ClearIndex = 1 TO ClearPulses a = INP(SelectTransferPort) 'send a vertical shift GOSUB GetALine LOCATE 2, 1 PRINT ClearIndex NEXT ClearIndex 'now restore the vertical clock LinePixelCount = FullCount HighByte = INT(VCOSetting / 256) 'make the high byte LowByte = VCOSetting - (256 * HighByte) 'make the low byte OUT (DACSetupPort), AddressDACLowOrderVCO 'address the low byte OUT (DACLoadPort), LowByte 'send the low byte OUT (DACSetupPort), AddressDACHighOrderVCO 'address the high byte OUT (DACLoadPort), HighByte 'send the high byte RETURN GetALine: dc = 5 PixelCount = 1 DO UNTIL PixelCount > LinePixelCount 'set up the paths OUT (PathSetupPort), ResetReady OUT (AuxilliaryLoadPort), Zerox 'send a reset ready pulse FOR delaycount = 1 TO dc 'because of wait states this produces 'a known delay for ready to reset Testx = INP(ReadyInPort) 'check for ready ff NEXT delaycount OUT (PathSetupPort), ShiftAndStart1 'Set for Horizontal shift and start ADC OUT (AuxilliaryLoadPort), Zerox 'send a horizontal shift and start ADC pulse DO UNTIL Testx < HighBit 'wait until interrupt resets Waitx Testx = INP(ReadyInPort) 'check for ready ff LOOP HighOrder& = INP(DataInPort) 'read the high byte OUT (PathSetupPort), ReadLowByte1 'Set path to read the low byte LowOrder% = INP(DataInPort) 'read the low byte Valuex& = (256 * HighOrder& + LowOrder%) SELECT CASE Valuex& 'convert output to integer CASE IS < 32768 LineSet1(PixelCount) = -Valuex& - 1 CASE ELSE LineSet1(PixelCount) = -(Valuex& - 65535) END SELECT OUT (PathSetupPort), ResetReady OUT (AuxilliaryLoadPort), Zerox 'send a reset ready pulse FOR delaycount = 1 TO dc Testx = INP(ReadyInPort) 'check for ready ff NEXT delaycount OUT (PathSetupPort), NoShiftAndStart2 'Set for no shift and start ADC OUT (AuxilliaryLoadPort), Zerox 'send start ADC pulse DO UNTIL Testx < HighBit 'wait until interrupt resets Waitx Testx = INP(ReadyInPort) 'check for ready ff LOOP HighOrder& = INP(DataInPort) 'read the high byte OUT (PathSetupPort), ReadLowByte2 'Set path to read the low byte LowOrder% = INP(DataInPort) 'read the low byte Valuex& = (256 * HighOrder& + LowOrder%) SELECT CASE Valuex& 'convert output to integer CASE IS < 32768 LineSet2(PixelCount) = -Valuex& - 1 CASE ELSE LineSet2(PixelCount) = -(Valuex& - 65535) END SELECT OUT (PathSetupPort), ResetReady OUT (AuxilliaryLoadPort), Zerox 'send a reset ready pulse FOR delaycount = 1 TO dc Testx = INP(ReadyInPort) 'check for ready ff NEXT delaycount OUT (PathSetupPort), NoShiftAndStart3 'Set for no shift and start ADC OUT (AuxilliaryLoadPort), Zerox 'send a start ADC pulse DO UNTIL Testx < HighBit 'wait until interrupt resets Waitx Testx = INP(ReadyInPort) 'check for ready ff LOOP HighOrder& = INP(DataInPort) 'read the high byte OUT (PathSetupPort), ReadLowByte3 'Set path to read the low byte LowOrder% = INP(DataInPort) 'read the low byte Valuex& = (256 * HighOrder& + LowOrder%) SELECT CASE Valuex& 'convert output to integer CASE IS < 32768 LineSet3(PixelCount) = -Valuex& - 1 CASE ELSE LineSet3(PixelCount) = -(Valuex& - 65535) END SELECT 'picks one pixel of one line set and prints it on the first line to get an 'idea of where the data is sitting. Should be around -25000 with this 'set up. Range is then from -27000 (at -20 C) for dark, to +32767 for full 'scale signal. IF PixelCount = 250 THEN WatchVal = LineSet2(PixelCount) 'watch camera 2 as it is the only one here END IF PixelCount = PixelCount + 1 LOOP RETURN GetOtherStuff: GOSUB WatchTemperatures RETURN LoadUpSkyType: kk.Datex = DATE$ 'the date in every line kk.Timex = TIME$ 'the time in every line FOR I = 1 TO 796 kk.LineSet1(I) = LineSet1(I) 'all the pixels including blank NEXT I FOR I = 1 TO 6 kk.Singlex!(I) = Singlex!(I) 'for other measured values NEXT I FOR I = 1 TO 6 kk.Integerx(I) = Integerx(I) 'some spares NEXT I ll.Datex = DATE$ 'the date in every line ll.Timex = TIME$ 'the time in every line FOR I = 1 TO 796 ll.LineSet2(I) = LineSet2(I) 'all the pixels including blank NEXT I FOR I = 1 TO 6 ll.Singlex!(I) = Singlex!(I) 'for other measured values NEXT I FOR I = 1 TO 6 ll.Integerx(I) = Integerx(I) 'some spares NEXT I mm.Datex = DATE$ 'the date in every line mm.Timex = TIME$ 'the time in every line FOR I = 1 TO 796 mm.LineSet3(I) = LineSet3(I) 'all the pixels including blank NEXT I FOR I = 1 TO 6 ll.Singlex!(I) = Singlex!(I) 'for other measured values NEXT I FOR I = 1 TO 6 ll.Integerx(I) = Integerx(I) 'some spares NEXT I RETURN PlotALine: 'plots each channel on 1/3 of the screen. Might as well change this so 'only channel 2 is plotted. Sumx! = 0 FOR I = 200 TO 399 Sumx! = Sumx! + LineSet1(I) NEXT I Sumx! = Sumx! / 200 'LOCATE 10, 10 'PRINT Sumx! FOR I = 1 TO 640 colorx! = INT((LineSet1(I) - Sumx!) / ScreenScale) IF colorx! < 0 THEN colorx! = 0 PSET (I, VerticalLine + 110), colorx! NEXT I Sumx! = 0 FOR I = 200 TO 399 Sumx! = Sumx! + LineSet2(I) NEXT I Sumx! = Sumx! / 200 'LOCATE 10, 10 'PRINT Sumx! FOR I = 1 TO 640 colorx! = INT((LineSet2(I) - Sumx!) / ScreenScale) IF colorx! < 0 THEN colorx! = 0 PSET (I, VerticalLine + 220), colorx! NEXT I Sumx! = 0 FOR I = 200 TO 399 Sumx! = Sumx! + LineSet3(I) NEXT I Sumx! = Sumx! / 200 'LOCATE 10, 10 'PRINT Sumx! FOR I = 1 TO 640 colorx! = INT((LineSet3(I) - Sumx!) / ScreenScale) IF colorx! < 0 THEN colorx! = 0 PSET (I, VerticalLine + 328), colorx! NEXT I VerticalLine = VerticalLine + 1 IF VerticalLine >= 8 THEN VerticalLine = 0 LOCATE 42, 1 PRINT 'LineSet1(200), Timex$ END IF RETURN ReadTheADC: OUT (PathSetupPort), MxSelect 'Set Mpx address High byte and start ADC OUT (AuxilliaryLoadPort), Zerox 'send a start adc pulse Testx = 128 DO UNTIL Testx < 128 OR GoBack = Onex 'wait until interrupt resets Waitx Testx = INP(ReadyInPort) 'check for ready ff LOOP HighOrder& = INP(DataInPort) 'read the high byte OUT (PathSetupPort), MxLow 'Set path to read the low byte LowOrder% = INP(DataInPort) 'read the low byte Valuex& = (256 * HighOrder& + LowOrder%) SELECT CASE Valuex& CASE IS < 32768 PrintValue& = Valuex& CASE ELSE PrintValue& = Valuex& - 65536 END SELECT RETURN RetrieveALine: GET #1, CurrentLine, kk GET #2, CurrentLine, ll GET #3, CurrentLine, mm RETURN SaveALine: PUT #1, CurrentLine, kk PUT #2, CurrentLine, ll PUT #3, CurrentLine, mm RETURN SetTheTemperature: LOCATE 1, 1 INPUT "Enter Desired CCD Temperature in C"; TempSetting! IF TempSetting! < 0 THEN TempSetting! = 3276.8 * TempSetting! + 65535 ELSE TempSetting! = TempSetting! * 3276.8 END IF HighByte! = INT(TempSetting! / 256) 'make the high byte LowByte! = TempSetting! - (256 * HighByte!) 'make the low byte LowByte = LowByte! HighByte = HighByte! OUT (DACSetupPort), AddressDACLowOrderTemp 'address the low byte OUT (DACLoadPort), LowByte 'send the low byte OUT (DACSetupPort), AddressDACHighOrderTemp'address the high byte OUT (DACLoadPort), HighByte 'send the high byte GOSUB VCOOn 'to restore the clock RETURN TakeADataLine: SOUND 1000, 1 GOSUB TurnReadyOff GOSUB GetALine GOSUB GetOtherStuff GOSUB LoadUpSkyType GOSUB SaveALine 'GOSUB RetrieveALine 'GOSUB UnloadSkyType GOSUB PlotALine LOCATE 1, 1 PRINT USING "Line ## ##### Water ###.# CCD ###.### 2Pix250 ####### ITEC #.#### "; CurrentBlock; CurrentLine; ThT1!; ThT2!; WatchVal; ITEC! IF CurrentLine >= LinesToTake! THEN Endx = 1 CurrentLine = CurrentLine + 1 GOSUB TurnReadyOff RETURN TurnReadyOff: OUT (PathSetupPort), SelectResetControl 'set path to send reset control OUT (AuxilliaryLoadPort), Zerox 'now a pulse resets ready only RETURN UnloadSkyType: Datex$ = kk.Datex 'the date in every line Timex$ = kk.Timex 'the time in every line FOR I = 1 TO 796 LineSet1(I) = kk.LineSet1(I) 'all the pixels including blank LineSet2(I) = ll.LineSet2(I) LineSet3(I) = mm.LineSet3(I) NEXT I FOR I = 1 TO 6 Singlex!(I) = kk.Singlex!(I) 'for other measured values NEXT I FOR I = 1 TO 6 Integerx(I) = kk.Integerx(I) 'some spares NEXT I RETURN VCOOn: 'turn on the VCO clock 'note that the VCO range selection starts continuous vertical 'shift pulses HighByte = INT(VCOSetting / 256) 'make the high byte LowByte = VCOSetting - (256 * HighByte) 'make the low byte OUT (DACSetupPort), AddressDACLowOrderVCO 'address the low byte OUT (DACLoadPort), LowByte 'send the low byte OUT (DACSetupPort), AddressDACHighOrderVCO 'address the high byte OUT (DACLoadPort), HighByte 'send the high byte 'vertical shift pulses should now be coming at the rate set by 'VCOSetting. This has about a 7 to 1 useful range. Large 'VCOSetting values are faster. The above setts the VCO to its 'middle rate range. For other operation, Change the three low 'order bits of AddressDACHighOrderVCO and AddressDACLowOrderVCO 'both bits must be changed together. RETURN WatchTemperatures: MxSelect = &H6 MxLow = &H2 GOSUB ReadTheADC ITEC! = (PrintValue& * .000076 * 2.24) / .2879 - .1 MxSelect = &H16 MxLow = &H12 GOSUB ReadTheADC Th1! = (PrintValue&) * .000076# IF Th1! < .001 THEN Th1! = .001 Th1! = 15 / Th1! - 1 ThT1! = 25 + (223.1 - SQR(49774 - 4 * (13991 - 5967 * LOG(Th1!)))) / 2 Th2Sum! = 0 FOR ii = 1 TO 10 MxSelect = &HE MxLow = &HA GOSUB ReadTheADC Th2! = (PrintValue&) * .000076# Th2Sum! = Th2Sum! + Th2! NEXT ii Th2! = Th2Sum! / 10 IF Th2! < .001 THEN Th2! = .001 Th2! = 15 / Th2! - 1 ThT2! = 25 + (223.1 - SQR(49774 - 4 * (13991 - 5967 * LOG(Th2!)))) / 2 Singlex!(1) = ThT1! Singlex!(2) = ThT2! Singlex!(3) = ITEC! 'LOCATE 25, 1 'PRINT USING "Water Temperature ###.### CCD Temperature ###.##"; ThT1!; ThT2! 'PRINT USING "Water Resistance ###.### CCD Resistance ###.###"; Th1!; Th2! RETURN SetBlockLength: LOCATE 20, 1 PRINT "Block Length is: "; LinesPerBlock; "Enter New Block Length" LOCATE 21, 1 INPUT TempBlock IF TempBlock > 10 THEN LinesPerBlock = TempBlock RETURN SetTheVCO: LOCATE 23, 1 PRINT "VCO Setting is: "; VCOSetting; "Enter VCO Setting" LOCATE 24, 1 INPUT TempVCO IF TempVCO > 100 THEN VCOSetting = TempVCO GOSUB VCOOn RETURN StartIt: StartIt = 1 RETURN KillIt: CLOSE #1 CLOSE #2 CLOSE #3 CLOSE END RETURN