<?xml version="1.0" encoding="utf-8"?>
<div id="popup_content" title="KmaxNT Code" last_modified="2011-07-24T17:07:25+00:00">

	<pre>

<span class="comment">
;*************************************
;	made by Leif
;	array001 (back: tdc07 with discr &amp; adc)
;	14 Feb 2002
;	&gt; remove all usage of TDCs (just the ADC now)
;*************************************

; NOTES:

; 1) If gate width is too large (adc has a max allowed: ~2 microseconds, they say),
;	adc freezes and run must be stopped. The adc must be cleared. (EnableADC does a clear module.)



; ____________________________________________________________________
; event "prototypes" (declarations)
; "$" before name indicates event can be called via toolsheet widget (my design decision)</span>

DECLARE WriteFileHeader AS EVENT	<span class="comment">; MUST be first to match edf2txt code (event type = 6)</span>
DECLARE WaitForRoundSecond AS EVENT
DECLARE INIT AS EVENT
DECLARE INITcc AS EVENT
DECLARE $MainSwitch AS EVENT
DECLARE ResetTimer AS EVENT
DECLARE $SetAutoHalt AS EVENT
DECLARE $RefreshIncr AS EVENT
DECLARE IncTimer AS EVENT
DECLARE UpdateCounters AS EVENT
DECLARE UpdateAutoHalt AS EVENT
DECLARE $5minGateAvgSelect AS EVENT
DECLARE $TotalGateAvgSelect AS EVENT
DECLARE WriteTime AS EVENT
DECLARE GetCurrTime AS EVENT
DECLARE BeepAgain AS EVENT
DECLARE $CLEARsheet AS EVENT
DECLARE $CLEARdisp AS EVENT
DECLARE ClearStatusDisplay AS EVENT

DECLARE INITadc AS EVENT
DECLARE EnableADC AS EVENT
DECLARE DisableADC AS EVENT
DECLARE ADC_READ AS EVENT
DECLARE WriteADC1header AS EVENT
DECLARE WriteADC1data AS EVENT
DECLARE $CLEARhist AS EVENT
DECLARE ClearHistograms AS EVENT
DECLARE $SetBinSize AS EVENT
DECLARE $LogLinToggle AS EVENT
DECLARE $HistZoomIn AS EVENT
DECLARE $HistZoomOut AS EVENT
DECLARE UpdateHist AS EVENT
DECLARE $ShowCh0 AS EVENT
DECLARE $ShowCh1 AS EVENT
DECLARE $ShowCh2 AS EVENT
DECLARE $ShowCh3 AS EVENT
DECLARE $ShowCh4 AS EVENT
DECLARE $ShowCh5 AS EVENT
DECLARE $ShowCh6 AS EVENT
DECLARE $ShowCh7 AS EVENT
DECLARE $ShowCh8 AS EVENT
DECLARE $ShowCh9 AS EVENT
DECLARE $ShowCh10 AS EVENT
DECLARE $ShowCh11 AS EVENT
DECLARE UpdateADCDisplays AS EVENT

DECLARE INITdiscr AS EVENT
DECLARE EnableDiscr AS EVENT
DECLARE DisableDiscr AS EVENT
DECLARE $LocRem1 AS EVENT
DECLARE $LocRem2 AS EVENT
DECLARE ReadThresh1 AS EVENT
DECLARE ReadThresh2 AS EVENT
DECLARE $Discr1_CustomThresh AS EVENT
DECLARE $Discr1_10mV AS EVENT
DECLARE $Discr1_15mV AS EVENT
DECLARE $Discr1_20mV AS EVENT
DECLARE $Discr1_30mV AS EVENT
DECLARE $Discr2_CustomThresh AS EVENT
DECLARE $Discr2_1fold AS EVENT
DECLARE $Discr2_2fold AS EVENT
DECLARE $Discr2_3fold AS EVENT
DECLARE $Discr2_4fold AS EVENT


<span class="comment">; ____________________________________________________________________
; variables treated as constants

; slots for each module (initialized in GO)</span>
DECLARE ADC1 AS INTEGER
DECLARE DISCR1 AS INTEGER
DECLARE DISCR2 AS INTEGER
<span class="comment">; module number (e.g., 2249 for LeCroy's ADC)</span>
DECLARE ADC1number AS INTEGER
DECLARE DISCR1number AS INTEGER
DECLARE DISCR2number AS INTEGER

DECLARE MAXINT AS INTEGER			<span class="comment">; really big positive 32-bit number used as "Refresh Never" value</span>
DECLARE HISTMAX AS INTEGER		<span class="comment">; treated as const (init'd in GO); number of bins in hist arrays and widget

; ____________________________________________________________________
; variables</span>

DECLARE timeCounter AS INTEGER		<span class="comment">; seconds counter for the run</span>
DECLARE gateCounter AS INTEGER		<span class="comment">; gates counter for the run</span>
DECLARE timer5min AS INTEGER			<span class="comment">; counter of seconds for 5-minute adc trigger freq average</span>
DECLARE gateCount5min AS INTEGER		<span class="comment">; counter of gates for 5-minute adc trigger freq average</span>
DECLARE refreshIncrSize AS INTEGER		<span class="comment">; number of events between hist and ADC data updates (of display)</span>
DECLARE refreshCount AS INTEGER		<span class="comment">; counter for updating displays
;</span>
DECLARE I AS INTEGER			<span class="comment">; for loop counter variable, usually for channel number or histogram bin</span>
DECLARE J AS INTEGER			<span class="comment">; for loop counter variable, usually for channel number or histogram bin</span>
DECLARE tempData AS INTEGER			<span class="comment">; used as all-purpose integer</span>
DECLARE widget AS STRING			<span class="comment">; used to build toolsheet widget names when inside loops</span>
DECLARE num1 AS INTEGER			<span class="comment">; used as all-purpose integer</span>
DECLARE num2 AS INTEGER			<span class="comment">; used as all-purpose integer</span>
DECLARE tempStr AS STRING			<span class="comment">; used as all-purpose string</span>
DECLARE tempStr2 AS STRING			<span class="comment">; used as all-purpose cleanser (uh... string)</span>
DECLARE tempReal AS REAL			<span class="comment">; used as all-purpose real</span>
DECLARE bin AS INTEGER			<span class="comment">; used in the 11 $ShowChX events for histogram stuff</span>
DECLARE BIT AS INTEGER			<span class="comment">; used when masking with bitwise logic operations</span>
DECLARE ok AS BOOLEAN			<span class="comment">; used as all-purpose boolean</span>
DECLARE startTime_ms AS INTEGER		<span class="comment">; start of run in milliseconds</span>
DECLARE lastSecInt AS INTEGER			<span class="comment">; used for IncTimer to correct 4.3% error of SET...TIMER</span>
DECLARE fileHeaderDone AS BOOLEAN		<span class="comment">; init'd in GO, and set in WriteFileHeader, checked in SRQ</span>
DECLARE moduleReadOutInProgress AS BOOLEAN	<span class="comment">; for use in SRQ and last module read event</span>
DECLARE beepCount AS INTEGER		<span class="comment">; used for errors in adc counts (ADC_READ)</span>
DECLARE adcDataReadIn AS INTEGER		<span class="comment">; data from ADC read
; histogramming events</span>
DECLARE BINSIZE AS INTEGER			<span class="comment">; treated as semi-const (init'd in GO, changed in $SetBinSize); hist widget's bin size</span>
DECLARE running AS BOOLEAN			<span class="comment">; true if $MainSwitch set to run toolsheet (adc stuff) (CC is not inhibited)</span>
DECLARE updateHist AS BOOLEAN		<span class="comment">; set to get into $ShowChX from UpdateHist event (IF stmt would otherwise stop it)</span>
DECLARE showingHistCh AS INTEGER		<span class="comment">; presently displayed histogram channel on toolsheet, set in INIT and $ShowChX
; AutoHalt feature</span>
DECLARE endTimeSetAt AS STRING		<span class="comment">; time and date that AutoHalt feature was set</span>
DECLARE hoursSetForEnd AS REAL		<span class="comment">; num of hours Autohalt set for (does not count down)</span>
DECLARE secsToEnd AS INTEGER		<span class="comment">; countdown in seconds before HALTing toolsheet
; read and write capabilites (set in GetCurrTime, used for parameter WRITEs)</span>
DECLARE yearInt AS INTEGER
DECLARE monthInt AS INTEGER
DECLARE dayInt AS INTEGER
DECLARE hourInt AS INTEGER
DECLARE minuteInt AS INTEGER
DECLARE secondInt AS INTEGER
<span class="comment">; ADC_READ</span>
DECLARE adc1Data[12] AS INTEGER
<span class="comment">; array for storing each ADC channel's histogram for viewing (automatically init'd to 0)</span>
DECLARE histCh[13680] AS INTEGER		<span class="comment">; 13680 = 12 channels * 1140 bins
; $WriteThreshReg1</span>
DECLARE TDACin AS REAL
DECLARE TDACout AS INTEGER

<span class="comment">; ____________________________________________________________________



;\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

; GO =&gt; entry point to toolsheet; initialize everything (without starting run)</span>
ON GO DO
	HISTMAX = 1140		<span class="comment">; if changing HISTMAX, must change array sizes for histCh[ ] and histogram widget "Display &gt; X Length"</span>
	BINSIZE = 1		<span class="comment">; histogram widget's bin size (changeable through toolsheet)</span>

	MAXINT = 2147483647		<span class="comment">; maximum positive integer for 32 bits</span>

	<span class="comment">; set constants for module SLOT numbers
	; (I highly recommend using these variables for non-CC WRDIO instead of integer constants!)</span>
	DISCR1 = 1
	DISCR2 = 2
	ADC1 = 6

	<span class="comment">; set constants for module numbers
	; (for output to edf file, id purposes)</span>
	ADC1number = 2249
	DISCR1number = 7106
	DISCR2number = 7106

	CALL INIT				<span class="comment">; initialize variables and toolsheet</span>
	CALL INITcc			<span class="comment">; init, clear, load LAM mask</span>
	CALL INITadc			<span class="comment">; init adc's and prepare adc part of toolsheet</span>
	CALL INITdiscr			<span class="comment">; init discr's and prepare discr part of toolsheet</span>

	fileHeaderDone = FALSE		<span class="comment">; boolean for writing file head, REQUESTed from SRQ only once (also set in $MainSwitch)</span>
	moduleReadOutInProgress = FALSE	<span class="comment">; for use in SRQ and last module read event</span>

	CALL ResetTimer
END

<span class="comment">; __________________________________________

; HALT =&gt; exit point of toolsheet; disable and finalize everything</span>
ON HALT DO
	WRDIO &lt; "setup1"[30], 30, 9, 26 &gt;    <span class="comment">;SCM301_Controller;Set CAMAC Inhibit.</span>
	WRDIO &lt; "setup1"[28], 28, 9, 26 &gt;    <span class="comment">;SCM301_Controller;CAMAC Clear.</span>
	IF (running) THEN
		SET "$MainSwitch" CONTROL TO "run / STOP"
		SET IncTimer TIMER TO 0 SECS		<span class="comment">; stop timer</span>
	END IF

	CALL DisableDiscr
	CALL DisableADC

	CALL UpdateCounters	<span class="comment">; to update text fields with fresh data</span>
END

<span class="comment">; __________________________________________

; SRQ =&gt; called by KmaxNT when a LAM occurs</span>
ON SRQ DO
	<span class="comment">; if modules haven't finished with their read out of data, exit SRQ
	; [the last module's code for writing data should set this to variable FALSE  (e.g., in ADC_READ)]</span>
	IF (moduleReadOutInProgress) THEN
		EXIT
	END IF

	<span class="comment">; only write file header once per run (set to FALSE in GO and $MainSwitch; set to TRUE in WriteFileHeader)</span>
	IF (fileHeaderDone=FALSE) THEN
		REQUEST WriteFileHeader
	END IF

	<span class="comment">; "If the #FCode# specified is a literal value and is 0-5, the data that is read is inserted into the event data stream."</span>
	I = 0
	WRDIO &lt; "setup1"[30], 30, 0, I &gt;    <span class="comment">;SCM301_Controller;Read LAM Pattern.
	; data written to %_DATA when no var is explicitly present</span>

	num2 = 2**(ADC1-1)			<span class="comment">; expected LAM pattern</span>
	num1 = %_DATA &amp; num2	<span class="comment">; actual LAM pattern ANDed with expected</span>

	<span class="comment">; must have actual ADC LAM</span>
	IF (num1 = num2) THEN			<span class="comment">; if ADC LAM is present</span>
		moduleReadOutInProgress = TRUE

		<span class="comment">; increment gate counters here instead of a CALLed event</span>
		gateCounter = gateCounter + 1
		gateCount5min = gateCount5min + 1
		refreshCount = refreshCount + 1

		<span class="comment">; DO THE REAL WORK</span>
		REQUEST WriteTime
		REQUEST ADC_READ

		<span class="comment">; refresh displays that change often</span>
		IF (refreshCount=refreshIncrSize) THEN
			REQUEST UpdateADCDisplays		<span class="comment">; REQUEST because don't have ADC data yet
			; include other display refreshing stuff here</span>

			refreshCount = 0
		END IF
	ELSE		<span class="comment">; if not both TDC and ADC LAMs
		;	IF (moduleReadOutInProgress=FALSE) THEN</span>
		WRDIO &lt; "setup1"[ADC1], ADC1, 0, 9 &gt;    <span class="comment">;LRS2249_ADC;Clear Module and LAM (A=0-11).
		;	END IF</span>
	END IF
END

<span class="comment">;===========================================

; WriteFileHeader =&gt; write format code to edf file
;	- REQUESTed by SRQ
;	- MUST be first user event (type = 6) to agree with edf2txt code</span>
ON WriteFileHeader DO
	WRITE -5 AS PARAMETER		<span class="comment">; header for edf file to identify edf format</span>
	fileHeaderDone = TRUE		<span class="comment">; this variable is set here because WriteFileheader was REQUESTed, not CALLed</span>
END

<span class="comment">; __________________________________________

; WaitForRoundSecond =&gt; wait to set startTime_ms to 0 ms (when the second changes value)
;	- CALLed by $MainSwitch
;	- done to make sense of parameter write of current ms in relation to start of run (the only place absolute time is written)</span>
ON WaitForRoundSecond DO
	CALL GetCurrTime
	tempData = secondInt

	REPEAT
		CALL GetCurrTime
	UNTIL (tempData&lt;&gt;secondInt)

	startTime_ms = %_TICKS		<span class="comment">; set start ms when second changes to set start time to a round second</span>
END

<span class="comment">;===========================================

; INIT =&gt; initialize general display portion of toolsheet and variables
;	- CALLed by GO and $CLEARSheet</span>
ON INIT DO
	SET "$MainSwitch" CONTROL TO "run / STOP"
	running = FALSE
	SET "$StartDisplay" CONTROL TO " "		<span class="comment">; static text field displaying start of run

	; AutoHalt variables</span>
	SET HALT TIMER TO 0 SECS			<span class="comment">; stop timer for HALTing</span>
	SET endTimeSetAt TO "Not Set"
	hoursSetForEnd = -1
	secsToEnd = -1

	<span class="comment">; refresh display stuff</span>
	GET "$RefreshIncr" CONTROL IN %_DATA
	CALL $RefreshIncr				<span class="comment">; $RefreshIncr needs value in %_DATA</span>
END

<span class="comment">; __________________________________________

; INITcc =&gt; initialize crate controller and set LAM mask
;	- CALLed by GO</span>
ON INITcc DO
	WRDIO &lt; "setup1"[28], 28, 8, 26 &gt;    <span class="comment">;SCM301_Controller;CAMAC Initialize.</span>
	WRDIO &lt; "setup1"[28], 28, 9, 26 &gt;    <span class="comment">;SCM301_Controller;CAMAC Clear.</span>
	WRDIO &lt; "setup1"[30], 30, 9, 26 &gt;    <span class="comment">;SCM301_Controller;Set CAMAC Inhibit.

	; set LAM mask in CC
	; example:
	;	slot 9 = 256	2**(TDC1-1)	slot 6 = 32		2**(ADC1-1)
	;	256 + 32 = 288	; binary: 100100000 (only slot 6's and 9's LAMs are enabled)</span>
	%_DATA = 2**(ADC1-1)

	WRDIO &lt; "setup1"[30], 30, 0, 16 &gt; (%_DATA)    <span class="comment">;SCM301_Controller;Load LAM Mask.</span>
END

<span class="comment">; __________________________________________

; $MainSwitch =&gt; start/stop data run by initializing variables and enabling/disabling modules</span>
ON $MainSwitch DO
	<span class="comment">; if stopped, then run</span>
	IF (running=FALSE) THEN
		WRDIO &lt; "setup1"[30], 30, 9, 24 &gt;    <span class="comment">;SCM301_Controller;Remove CAMAC Inhibit.</span>
		SET "$MainSwitch" CONTROL TO "RUN / stop"
		running = TRUE

		<span class="comment">; display run start date &amp; time</span>
		CALL GetCurrTime
		SET %_TEXT TO yearInt
		ADD "." TO %_TEXT
		SET tempStr TO monthInt
		ADD tempStr TO %_TEXT
		ADD "." TO %_TEXT
		SET tempStr TO dayInt
		ADD tempStr TO %_TEXT
		ADD "   " TO %_TEXT
		SET tempStr TO %_TIME
		ADD tempStr TO %_TEXT
		SET "$StartDisplay" CONTROL TO %_TEXT

		<span class="comment">; display gate freq for total</span>
		CALL $TotalGateAvgSelect

		lastSecInt = -1				<span class="comment">; variable used in IncTimer (presently just needs to be &lt;= 0)</span>
		moduleReadOutInProgress = FALSE		<span class="comment">; for use in SRQ and last module read event</span>
		fileHeaderDone = FALSE			<span class="comment">; file header to identify our format for the edf</span>

		CALL WaitForRoundSecond			<span class="comment">; to be able to reset timer on the next round second (more or less)</span>
		CALL ResetTimer				<span class="comment">; to make everything 0 along with ms</span>
		SET IncTimer TIMER TO 1 SECS			<span class="comment">; start timer

		; set-up modules to accept data input</span>
		CALL EnableDiscr
		CALL EnableADC

	ELSE		<span class="comment">; if running, then stop</span>
		WRDIO &lt; "setup1"[30], 30, 9, 26 &gt;    <span class="comment">;SCM301_Controller;Set CAMAC Inhibit.</span>
		SET "$MainSwitch" CONTROL TO "run / STOP"
		running = FALSE

		CALL UpdateCounters			<span class="comment">; to update text fields with fresh data</span>
		SET IncTimer TIMER TO 0 SECS		<span class="comment">; stop timer

		; set modules to stop allowing data to come in</span>
		CALL DisableDiscr
		CALL DisableADC
	END IF
END

<span class="comment">; __________________________________________

; ResetTimer =&gt; reinitialize counting variables and widgets
;	- CALLed by GO, $MainSwitch, and $CLEARsheet</span>
ON ResetTimer DO
	timeCounter = 0
	gateCounter = 0
	refreshCount = 0		<span class="comment">; event count for refreshing displays</span>

	SET "$TIMER" CONTROL TO 0
	SET "$GATEcounter" CONTROL TO 0
	SET "$FREQ" CONTROL TO "0.0000"
	timer5min = 0
	gateCount5min = 0
END

<span class="comment">; __________________________________________

; $SetAutoHalt =&gt; inform user when AutoHalt is set for and ask user for time (in hours) to automatically HALT the toolsheet</span>
ON $SetAutoHalt DO
	SET %_TEXT TO ""
	IF (hoursSetForEnd&gt;0) THEN
		SET tempStr TO "The present run is set to halt in "
		IF (secsToEnd&lt;60) THEN
			SET %_TEXT TO secsToEnd
			ADD " seconds." TO %_TEXT
		ELSE
			IF (secsToEnd&lt;3600) THEN
				tempReal = secsToEnd/60
				SET %_TEXT TO tempReal
				ADD " minutes." TO %_TEXT
			ELSE
				tempReal = secsToEnd/3600
				SET %_TEXT TO tempReal
				ADD " hours." TO %_TEXT
			END IF
		END IF
		ADD %_TEXT TO tempStr
	ELSE
		SET tempStr TO "The present run has no halt time set."
	END IF

	ADD "\nDo you want to set the halt time?" TO tempStr
	ALERT WITH tempStr

	IF (%_OK) THEN
		SET tempStr TO "How many hours until AutoHalt? (-1 to remove or &gt;0.017)"
		SET %_TEXT TO ""
		PROMPT WITH tempStr

		IF (%_OK) THEN
			SET tempReal TO %_TEXT
			IF ((tempReal*60)&gt;=1) THEN		<span class="comment">; if valid hours (greater than 1 minute)</span>
				hoursSetForEnd = tempReal
				SET endTimeSetAt TO %_TIME
				SET %_TEXT TO %_DATE
				ADD " " TO endTimeSetAt
				ADD %_TEXT TO endTimeSetAt
				DISPLAY "Halt Timer set to " hoursSetForEnd " hours."
				SET ClearStatusDisplay TIMER TO 10 SECS
				tempData = hoursSetForEnd*60

				<span class="comment">; this next line is the whole point to this event!</span>
				SET HALT TIMER TO tempData MINS

				SET UpdateAutoHalt TIMER TO 30 SECS
				secsToEnd = hoursSetForEnd*3600

			ELSE							<span class="comment">; if less than 1 minute</span>
				IF (tempReal&gt;=0) THEN
					DISPLAY "Halt Timer not changed."
					SET ClearStatusDisplay TIMER TO 10 SECS
				ELSE						<span class="comment">; if less than 0</span>
					hoursSetForEnd = -1
					SET HALT TIMER TO 0 SECS			<span class="comment">; stop timer for HALTing</span>
					DISPLAY "Halt Timer stopped."
					SET ClearStatusDisplay TIMER TO 10 SECS
					secsToEnd = -1
				END IF
			END IF

		ELSE
			DISPLAY "Halt Timer not changed."
			SET ClearStatusDisplay TIMER TO 10 SECS
		END IF
	END IF
END

<span class="comment">; __________________________________________

; $RefreshIncr =&gt; set the number of events between updating the frequently changing display (to cut I/O time)</span>
ON $RefreshIncr DO
	refreshCount = 0

	<span class="comment">; %_DATA will be 1..8</span>
	IF (%_DATA=1) THEN
		refreshIncrSize = 1
	ELSE
		IF (%_DATA=2) THEN
			refreshIncrSize = 5
		ELSE
			IF (%_DATA=3) THEN
				refreshIncrSize = 10
			ELSE
				IF (%_DATA=4) THEN
					refreshIncrSize = 50
				ELSE
					IF (%_DATA=5) THEN
						refreshIncrSize = 100
					ELSE
						IF (%_DATA=6) THEN
							refreshIncrSize = 500
						ELSE
							IF (%_DATA=7) THEN
								refreshIncrSize = 1000
							ELSE
								refreshIncrSize = MAXINT
							END IF
						END IF
					END IF
				END IF
			END IF
		END IF
	END IF
END

<span class="comment">; __________________________________________

; IncTimer =&gt; executes every second; heartbeat of DAQ
;	- posted to event queue in 1 sec from the BEGINNING of this event</span>
ON IncTimer DO
	SET IncTimer TIMER TO 1 SECS		<span class="comment">; do this event again in 1 second</span>

	num2 = %_TICKS - startTime_ms		<span class="comment">; time since run started in milliseconds</span>
	secondInt = num2 / 1000		<span class="comment">; time in seconds</span>

	num1 = secondInt - lastSecInt

	IF (num1&lt;1) THEN
		BEEP
		RECORDLN "IncTimer Warning!\t" %_TIME IN "$DISPLAY"
		RECORDLN %_DATE IN "$DISPLAY"
		RECORDLN "timer changed by " num1 " sec\n" IN "$DISPLAY"
	END IF

	lastSecInt = secondInt

	timeCounter = timeCounter + num1
	timer5min = timer5min + num1

	CALL UpdateCounters	<span class="comment">; to update counter text fields with fresh data

	; to bypass needing a queue (array) to keep track of gates over last 5 minutes, the 5min counter is reset every 5 min
	; also: when timer5min = 0, $FREQ has already (just) been updated</span>
	IF (MOD(timer5min,300)=0) THEN		<span class="comment">; if 5 minute interval ending, then reset 5-minute stats (300 seconds)</span>
		timer5min = 0
		gateCount5min = 0
	END IF
END

<span class="comment">; __________________________________________

; UpdateCounters =&gt; refresh counter widgets
;	- CALLed by IncTimer and $MainSwitch</span>
ON UpdateCounters DO
	GET "$TotalGateAvgSelect" CONTROL IN tempData
	IF (tempData=1) THEN			<span class="comment">; if set to display total gate average then...</span>
		num1 = gateCounter
		num2 = timeCounter
	ELSE				<span class="comment">; if set to display 5-minute gate average then...</span>
		num1 = gateCount5min
		num2 = timer5min
	END IF

	IF (num2=0) THEN
		tempReal = 0
	ELSE
		tempReal = num1 / num2
	END IF

	SET tempStr TO tempReal
	SET "$FREQ" CONTROL TO tempStr

	SET "$TIMER" CONTROL TO timeCounter
	SET "$GATEcounter" CONTROL TO gateCounter
END

<span class="comment">; __________________________________________

; UpdateAutoHalt =&gt; update AutoHalt variable (seconds counter for informing user when HALT occurs)</span>
ON UpdateAutoHalt DO
	IF (secsToEnd&gt;0) THEN
		secsToEnd = secsToEnd - 30
		SET UpdateAutoHalt TIMER TO 30 SECS
	END IF
END

<span class="comment">; __________________________________________

; $5minGateAvgSelect =&gt; change freq display to freq for 5 minutes</span>
ON $5minGateAvgSelect DO
	SET "$5minGateAvgSelect" CONTROL TO 1
	SET "$TotalGateAvgSelect" CONTROL TO 0

	IF (timer5min = 0) THEN
		tempReal = 0
	ELSE
		tempReal = gateCount5min / timer5min
	END IF
	SET tempStr TO tempReal
	SET "$FREQ" CONTROL TO tempStr
END

<span class="comment">; __________________________________________

; $TotalGateAvgSelect =&gt; change freq display to freq for all of run</span>
ON $TotalGateAvgSelect DO
	SET "$5minGateAvgSelect" CONTROL TO 0
	SET "$TotalGateAvgSelect" CONTROL TO 1

	IF (timeCounter = 0) THEN
		tempReal = 0
	ELSE
		tempReal = gateCounter / timeCounter
	END IF
	SET tempStr TO tempReal
	SET "$FREQ" CONTROL TO tempStr
END

<span class="comment">;===========================================

; __________________________________________

; WriteTime =&gt; write stuff to event data stream (file, if one is open)
;	- REQUESTed by SRQ</span>
ON WriteTime DO
	WRITE -1 AS PARAMETER		<span class="comment">; starts SRQ block collection in edf</span>

	num2 = %_TICKS - startTime_ms		<span class="comment">; time since run started, in milliseconds</span>
	WRITE num2 AS PARAMETER

	CALL GetCurrTime
	WRITE yearInt AS PARAMETER
	WRITE monthInt AS PARAMETER
	WRITE dayInt AS PARAMETER
	WRITE hourInt AS PARAMETER
	WRITE minuteInt AS PARAMETER
	WRITE secondInt AS PARAMETER
END

<span class="comment">; __________________________________________

; GetCurrTime =&gt; extract date &amp; time from KmaxNT variables %_DATE &amp; %_TIME
;	- executes in ~0.8 ms</span>
ON GetCurrTime DO
	SET tempStr TO ""
	SET %_TEXT TO %_DATE		<span class="comment">; store the current time as a REWRITABLE string</span>

	MOVE WORD FROM %_TEXT TO tempStr		<span class="comment">; remove day</span>
	MOVE WORD FROM %_TEXT TO tempStr		<span class="comment">; remove comma</span>

	SET tempStr TO ""
	MOVE WORD FROM %_TEXT TO tempStr
	IF (tempStr = "January") THEN
		monthInt = 1
	ELSE
		IF (tempStr = "February") THEN
			monthInt = 2
		ELSE
			IF (tempStr = "March") THEN
				monthInt = 3
			ELSE
				IF (tempStr = "April") THEN
					monthInt = 4
				ELSE
					IF (tempStr = "May") THEN
						monthInt = 5
					ELSE
						IF (tempStr = "June") THEN
							monthInt = 6
						ELSE
							IF (tempStr = "July") THEN
								monthInt = 7
							ELSE
								IF (tempStr = "August") THEN
									monthInt = 8
								ELSE
									IF (tempStr = "September") THEN
										monthInt = 9
									ELSE
										IF (tempStr = "October") THEN
											monthInt = 10
										ELSE
											IF (tempStr = "November") THEN
												monthInt = 11
											ELSE
												IF (tempStr = "December") THEN
													monthInt = 12
												END IF
											END IF
										END IF
									END IF
								END IF
							END IF
						END IF
					END IF
				END IF
			END IF
		END IF
	END IF

	SET tempStr TO ""
	MOVE CHAR FROM %_TEXT TO tempStr		<span class="comment">; start getting date</span>
	IF (tempStr = "0") THEN
		SET tempStr TO ""			<span class="comment">; to avoid being treated like an octal with SET...TO...</span>
	END IF
	MOVE CHAR FROM %_TEXT TO tempStr		<span class="comment">; continue getting date</span>
	SET dayInt TO tempStr

	MOVE WORD FROM %_TEXT TO tempStr		<span class="comment">; remove comma</span>
	SET tempStr TO ""
	MOVE WORD FROM %_TEXT TO tempStr		<span class="comment">; get year</span>
	SET yearInt TO tempStr

	SET %_TEXT TO %_TIME			<span class="comment">; store the current time as a string</span>
	SET tempStr TO ""
	MOVE CHAR FROM %_TEXT TO tempStr		<span class="comment">; get hours 1</span>
	IF (tempStr = "0") THEN
		SET tempStr TO ""			<span class="comment">; to avoid being treated like an octal with SET...TO...</span>
	END IF
	MOVE CHAR FROM %_TEXT TO tempStr		<span class="comment">; get hours 2</span>
	SET hourInt TO tempStr
	MOVE CHAR FROM %_TEXT TO tempStr		<span class="comment">; get colon</span>

	SET tempStr TO ""
	MOVE CHAR FROM %_TEXT TO tempStr		<span class="comment">; get minutes 1</span>
	IF (tempStr = "0") THEN
		SET tempStr TO ""			<span class="comment">; to avoid being treated like an octal with SET...TO...</span>
	END IF
	MOVE CHAR FROM %_TEXT TO tempStr		<span class="comment">; get minutes 2</span>
	SET minuteInt TO tempStr
	MOVE CHAR FROM %_TEXT TO tempStr		<span class="comment">; get colon</span>

	SET tempStr TO ""
	MOVE CHAR FROM %_TEXT TO tempStr		<span class="comment">; get seconds 1</span>
	IF (tempStr = "0") THEN
		SET tempStr TO ""			<span class="comment">; to avoid being treated like an octal with SET...TO...</span>
	END IF
	MOVE CHAR FROM %_TEXT TO tempStr		<span class="comment">; get seconds 2</span>
	SET secondInt TO tempStr
END

<span class="comment">; __________________________________________

; BeepAgain =&gt; used for warnings that need repeated beeps</span>
ON BeepAgain DO
	IF (beepCount = 0) THEN
		SET BeepAgain TIMER TO 0 SECS
	ELSE
		BEEP		<span class="comment">; uses the current Windows Default Sound (which is now ~180 ms long)</span>
		beepCount = beepCount - 1
		SET BeepAgain TIMER TO 250 MSECS
	END IF
END

<span class="comment">; __________________________________________

; $CLEARsheet =&gt; clear displays and modules (if not running)</span>
ON $CLEARsheet DO
	IF (running = FALSE) THEN
		CLEAR "$DISPLAY"
		CALL ResetTimer
		CALL INIT		<span class="comment">; clears histograms, AutoHalt</span>
		CALL INITadc	<span class="comment">; apparently need this to avoid problems (clear module and LAMs?)
		; want to keep discr settings, so no INITdiscr:
		;		CALL INITdiscr
		;		CALL INITtdc</span>
	ELSE
		ALERT WITH "This will clear the display, all histograms, timers, and counters (but not AutoHalt). Continue?"
		IF (%_OK) THEN
			CLEAR "$DISPLAY"
			CALL ResetTimer
			CALL ClearHistograms
		END IF
	END IF
END

<span class="comment">; __________________________________________

; $CLEARdisp =&gt; clear main display</span>
ON $CLEARdisp DO
	IF (running = FALSE) THEN
		CLEAR "$DISPLAY"
	ELSE
		ALERT WITH "This will clear the display. Continue?"
		IF (%_OK) THEN
			CLEAR "$DISPLAY"
		END IF
	END IF
END

<span class="comment">; __________________________________________

; ClearStatusDisplay =&gt; clear status bar at bottom of KmaxNT window</span>
ON ClearStatusDisplay DO
	DISPLAY ""
END

<span class="comment">;============================================



;***********************************************************************
;***********************************************************************
;***********************************************************************
;***********************************************************************
;***********************************************************************

;______#________#####_______#####
;_____#_#_______#____#_____#_____#
;____#___#______#_____#___#
;___#######_____#_____#___#
;__#_______#____#____#_____#_____#
;_#_________#___#####_______#####


; INITadc =&gt; init module and adc display widgets</span>
ON INITadc DO
	WRDIO &lt; "setup1"[ADC1], ADC1, 0, 9 &gt;    <span class="comment">;LRS2249_ADC;Clear Module and LAM (A=0-11).</span>

	FOR I = 0 TO 11
		SET widget TO "$ADC"
		SET tempStr TO I
		ADD tempStr TO widget
		SET widget CONTROL TO -1	<span class="comment">; channel data field</span>
	END FOR

	SET "$CurrChHist" CONTROL TO "Showing Ch 2 --&gt;"
	showingHistCh = 2			<span class="comment">; arbitrary channel</span>
	CALL ClearHistograms
	updateHist = FALSE
	CALL $LogLinToggle			<span class="comment">; for histogram vertical axis</span>
END

<span class="comment">; __________________________________________

; EnableADC =&gt; clear module and enable LAMs</span>
ON EnableADC DO
	WRDIO &lt; "setup1"[ADC1], ADC1, 0, 9 &gt;    <span class="comment">;LRS2249_ADC;Clear Module and LAM (A=0-11).</span>
	WRDIO &lt; "setup1"[ADC1], ADC1, 0, 26 &gt;    <span class="comment">;LRS2249_ADC;Enable LAM (A=0-11).</span>
END

<span class="comment">; __________________________________________

; DisableADC =&gt; clear module and disable LAMs</span>
ON DisableADC DO
	WRDIO &lt; "setup1"[ADC1], ADC1, 0, 9 &gt;    <span class="comment">;LRS2249_ADC;Clear Module and LAM (A=0-11).</span>
	WRDIO &lt; "setup1"[ADC1], ADC1, 0, 24 &gt;    <span class="comment">;LRS2249_ADC;Disable LAM (A=0-11).</span>
END

<span class="comment">; __________________________________________

; ADC_READ =&gt; read data from ADCs (right now, only 1 ADC)</span>
ON ADC_READ DO
	FOR I = 0 TO 11
		WRDIO &lt; "setup1"[ADC1], ADC1, I, 2 &gt; (adc1Data[I])    <span class="comment">;LRS2249_ADC;Read Registers Clear Module and LAM (Clears on A=11 only).</span>

		adcDataReadIn = adc1Data[I]

		<span class="comment">; save adc1Data[I] in histogram array</span>
		%_DATA = adcDataReadIn
		IF (%_DATA&lt;HISTMAX) THEN
			%_DATA = (I*HISTMAX)+%_DATA	<span class="comment">; offset to correct channel in 1-D array</span>
			histCh[%_DATA] = histCh[%_DATA] + 1
		END IF

		<span class="comment">; display any error (weird number of counts)</span>
		IF (adcDataReadIn&lt;10) THEN
			beepCount = 2
			BEEP
			SET BeepAgain TIMER TO 250 MSECS
			RECORD "\B\n&gt; CH" I " is low: " adcDataReadIn "\n   " %_DATE "\n   " %_TIME IN "$DISPLAY"
			RECORDLN "    timer: " timeCounter " sec" IN "$DISPLAY"
		ELSE
			IF (adcDataReadIn&gt;=HISTMAX) THEN
				BEEP
				RECORD "\B\n&gt; CH" I " is high: " adcDataReadIn "\n   " %_DATE "\n   " %_TIME IN "$DISPLAY"
				RECORDLN "    timer: " timeCounter " sec" IN "$DISPLAY"
			END IF
		END IF

		<span class="comment">; histogram if in range of hist bins</span>
		IF ((adcDataReadIn&lt;HISTMAX) &amp;&amp; (I=showingHistCh)) THEN			<span class="comment">; showingHistCh in $ShowChX event</span>
			adcDataReadIn = adcDataReadIn / BINSIZE		<span class="comment">; integer math to force into integer bin with size BINSIZE</span>
			adcDataReadIn = adcDataReadIn * BINSIZE
			{"ADC_Counts"}[adcDataReadIn] = {"ADC_Counts"}[adcDataReadIn] + 1
		END IF
	END FOR

	REQUEST WriteADC1header
	REQUEST WriteADC1data
END

<span class="comment">; __________________________________________

; WriteADC1header =&gt; write module header to event data stream
;	- REQUESTed by ADC_READ</span>
ON WriteADC1header DO
	WRITE ADC1number AS PARAMETER		<span class="comment">; module number</span>
	WRITE ADC1 AS PARAMETER			<span class="comment">; slot number</span>
END

<span class="comment">; __________________________________________

; WriteADC1data =&gt; write adc1 data to event data stream
;	- REQUESTed by ADC_READ</span>
ON WriteADC1data(12) DO
	FOR I = 0 TO 11
		WRITE adc1Data[I] AS PARAMETER
	END FOR

	moduleReadOutInProgress = FALSE
END

<span class="comment">; __________________________________________

; $CLEARhist =&gt; safety buffer for calling a clear of adc1 histogram widget</span>
ON $CLEARhist DO
	IF (running = FALSE) THEN
		CALL ClearHistograms
	ELSE
		ALERT WITH "This will clear the histograms. Continue?"
		IF (%_OK) THEN
			CALL ClearHistograms
		END IF
	END IF
END

<span class="comment">; __________________________________________

; ClearHistograms =&gt; clear adc1 histogram widget &amp; arrays</span>
ON ClearHistograms DO
	CLEAR "ADC_Counts"			<span class="comment">; clear histogram widget</span>
	num1 = HISTMAX - 1
	FOR J = 0 TO 11
		FOR I = 0 TO num1			<span class="comment">; time-consuming loops!</span>
			%_DATA = (HISTMAX * J) + I
			histCh[%_DATA] = 0
		END FOR
	END FOR
END

<span class="comment">; __________________________________________

;$SetBinSize =&gt; ask user to change adc1 histograms bin size</span>
ON $SetBinSize DO
	SET %_TEXT TO BINSIZE			<span class="comment">; default is 1</span>
	PROMPT WITH "Enter new histogram bin size:"
	IF (%_OK) THEN
		SET tempData TO  %_TEXT
		IF ((tempData&gt;0)&amp;&amp;(tempData&lt;=HISTMAX)) THEN
			SET BINSIZE TO tempData
		END IF
	END IF
	DISPLAY "Bin Size: " BINSIZE
	SET ClearStatusDisplay TIMER TO 10 SECS
	REQUEST UpdateHist
END

<span class="comment">; __________________________________________

; $LogLinToggle =&gt; switch between log and linear y-axis for adc1 histogram widget</span>
ON $LogLinToggle DO
	GET "$LogLinToggle" CONTROL IN %_DATA
	IF (%_DATA = 0) THEN					<span class="comment">; if set to LINEAR then...</span>
		SET "ADC_Counts" VALUE_SCALE TO "LINEAR"
	ELSE							<span class="comment">; if set to log then...</span>
		SET "ADC_Counts" VALUE_SCALE TO "LOG"
	END IF
	UPDATE "ADC_Counts"
END

<span class="comment">; __________________________________________

; $HistZoomIn =&gt; zoom adc1 histogram widget to what's between widget cursors</span>
ON $HistZoomIn DO
	EXPAND "ADC_Counts"
END

<span class="comment">; __________________________________________

; $HistZoomOut =&gt; display complete range of adc1 histogram widget</span>
ON $HistZoomOut DO
	%_DATA = HISTMAX-1
	SET "ADC_Counts" CURSORS TO 0, %_DATA
	EXPAND "ADC_Counts"
END

<span class="comment">; __________________________________________

; UpdateHist =&gt; load hist array into adc1 hist widget
;	- REQUESTed from $SetBinSize or from $ShowChX
;	- showingHistCh is present channel that is showing (if from $SetBinSize) or new channel to show (if from $ShowChX)</span>
ON UpdateHist DO
	CLEAR "ADC_Counts"
	num1 = (HISTMAX/BINSIZE) - 1

	FOR I = 0 TO num1				<span class="comment">; 0 to number of bins used in hist</span>
		bin = I * BINSIZE			<span class="comment">; hist bin actually used</span>
		{"ADC_Counts"}[bin] = 0
		num2 = BINSIZE - 1 + bin		<span class="comment">; last array bin counted in hist bin of BINSIZE</span>
		FOR J = bin TO num2
			%_DATA = HISTMAX*showingHistCh + J
			{"ADC_Counts"}[bin] = {"ADC_Counts"}[bin] + histCh[%_DATA]
		END FOR
	END FOR
	UPDATE "ADC_Counts"

	<span class="comment">; update display text for what adc channel is now being shown</span>
	SET %_TEXT TO "Showing Ch "
	SET tempStr TO showingHistCh
	ADD tempStr TO %_TEXT
	ADD " --&gt;" TO %_TEXT
	SET "$CurrChHist" CONTROL TO %_TEXT
END

<span class="comment">; __________________________________________

; $ShowChX =&gt; set variable and request a hist update
;	- X = 0..11
;	- CALLed by toolsheet buttons only</span>

ON $ShowCh0 DO
	showingHistCh = 0
	REQUEST UpdateHist	<span class="comment">; REQUEST or CALL? (either)</span>
END
<span class="comment">;---------------------------------------------------------</span>
ON $ShowCh1 DO
	showingHistCh = 1
	REQUEST UpdateHist
END
<span class="comment">;---------------------------------------------------------</span>
ON $ShowCh2 DO
	showingHistCh = 2
	REQUEST UpdateHist
END
<span class="comment">;---------------------------------------------------------</span>
ON $ShowCh3 DO
	showingHistCh = 3
	REQUEST UpdateHist
END
<span class="comment">;---------------------------------------------------------</span>
ON $ShowCh4 DO
	showingHistCh = 4
	REQUEST UpdateHist
END
<span class="comment">;---------------------------------------------------------</span>
ON $ShowCh5 DO
	showingHistCh = 5
	REQUEST UpdateHist
END
<span class="comment">;---------------------------------------------------------</span>
ON $ShowCh6 DO
	showingHistCh = 6
	REQUEST UpdateHist
END
<span class="comment">;---------------------------------------------------------</span>
ON $ShowCh7 DO
	showingHistCh = 7
	REQUEST UpdateHist
END
<span class="comment">;---------------------------------------------------------</span>
ON $ShowCh8 DO
	showingHistCh = 8
	REQUEST UpdateHist
END
<span class="comment">;---------------------------------------------------------</span>
ON $ShowCh9 DO
	showingHistCh = 9
	REQUEST UpdateHist
END
<span class="comment">;---------------------------------------------------------</span>
ON $ShowCh10 DO
	showingHistCh = 10
	REQUEST UpdateHist
END
<span class="comment">;---------------------------------------------------------</span>
ON $ShowCh11 DO
	showingHistCh = 11
	REQUEST UpdateHist
END

<span class="comment">; __________________________________________

; UpdateADCDisplays =&gt; refresh text fields and histograms for ADCs
;	- REQUESTed by SRQ</span>
ON UpdateADCDisplays DO
	FOR I = 0 TO 11
		SET widget TO "$ADC"
		SET tempStr TO I
		ADD tempStr TO widget		<span class="comment">; widget = "$ADCx"</span>
		SET widget CONTROL TO adc1Data[I]	<span class="comment">; display channel's register data in text field</span>
	END FOR
	UPDATE "ADC_Counts"			<span class="comment">; update histogram</span>
END
<span class="comment">; __________________________________________




;***********************************************************************
;***********************************************************************
;***********************************************************************
;***********************************************************************
;***********************************************************************

;_#####_____#####____####_____####____#####
;_#____#______#_____#________#____#___#____#
;_#_____#_____#______####___#_________#____#
;_#_____#_____#__________#__#_________#####
;_#____#______#_____#____#___#____#___#___#
;_#####_____#####____####_____####____#____#


; INITdiscr =&gt; init module and its display toolsheet widgets
;	- CALLed by GO</span>
ON INITdiscr DO
	SET "$LocRem1" CONTROL TO 0		<span class="comment">; set to LOCAL</span>
	SET "$LocRem2" CONTROL TO 0		<span class="comment">; set to LOCAL</span>
	%_DATA = 0
	CALL $LocRem1		<span class="comment">; $LocRem1 needs value in %_DATA</span>
	%_DATA = 0
	CALL $LocRem2		<span class="comment">; $LocRem2 needs value in %_DATA

	; set default thresholds</span>
	CALL $Discr1_10mV
	CALL $Discr2_3fold		<span class="comment">; default is 3-fold coincidence</span>

	<span class="comment">; allow all channels to accept data input</span>
	WRDIO &lt; "setup1"[DISCR1], DISCR1, 0, 16 &gt; ($FFFF)    <span class="comment">;PS7106_Discr;Write Mask register.</span>
	WRDIO &lt; "setup1"[DISCR2], DISCR2, 0, 16 &gt; ($FFFF)    <span class="comment">;PS7106_Discr;Write Mask register.</span>
END

<span class="comment">; __________________________________________

; EnableDiscr =&gt; allow discr modules to accept data input
;	- CALLed by $MainSwitch</span>
ON EnableDiscr DO
	SET "$LocRem1" CONTROL TO 1		<span class="comment">; set to REMOTE</span>
	SET "$LocRem2" CONTROL TO 1		<span class="comment">; set to REMOTE</span>
	%_DATA = 1			<span class="comment">; needed because this is value of slider widget when toolsheet calls $LocRem1</span>
	CALL $LocRem1
	%_DATA = 1
	CALL $LocRem2
END

<span class="comment">; __________________________________________

; DisableDiscr =&gt; disallow data input into discr modules</span>
ON DisableDiscr DO
	SET "$LocRem1" CONTROL TO 0		<span class="comment">; set to LOCAL</span>
	SET "$LocRem2" CONTROL TO 0		<span class="comment">; set to LOCAL</span>
	%_DATA = 0
	CALL $LocRem1
	%_DATA = 0
	CALL $LocRem2
END

<span class="comment">; __________________________________________

; $LocRem1 =&gt; local / remote switch for discr1</span>
ON $LocRem1 DO
	<span class="comment">; value of widget automatically passed in %_DATA from toolsheet</span>
	IF (%_DATA = 1) THEN			<span class="comment">; REMOTE</span>
		WRDIO &lt; "setup1"[DISCR1], DISCR1, 0, 26 &gt;    <span class="comment">;PS7106_Discr ; Set internal mode bit (go to Remote).</span>
	ELSE					<span class="comment">; LOCAL</span>
		WRDIO &lt; "setup1"[DISCR1], DISCR1, 0, 24 &gt;    <span class="comment">;PS7106_Discr ; Clear internal mode bit (go to LOCAL).</span>
	END IF

	CALL ReadThresh1
END

<span class="comment">; __________________________________________

; $LocRem2 =&gt; local / remote switch for discr2</span>
ON $LocRem2 DO
	<span class="comment">; value of widget automatically passed in %_DATA from toolsheet</span>
	IF (%_DATA = 1) THEN			<span class="comment">; REMOTE</span>
		WRDIO &lt; "setup1"[DISCR2], DISCR2, 0, 26 &gt;    <span class="comment">;PS7106_Discr ; Set internal mode bit (go to Remote).</span>
	ELSE					<span class="comment">; LOCAL</span>
		WRDIO &lt; "setup1"[DISCR2], DISCR2, 0, 24 &gt;    <span class="comment">;PS7106_Discr ; Clear internal mode bit (go to LOCAL).</span>
	END IF

	CALL ReadThresh2
END

<span class="comment">; __________________________________________

; ReadThresh1 =&gt; display thresholds for discr1 on toolsheet</span>
ON ReadThresh1 DO
	<span class="comment">; first, display what threshold would be if Discr1 were in REMOTE mode</span>
	I = 1
	WRDIO &lt; "setup1"[DISCR1], DISCR1, 0, I &gt;    <span class="comment">;PS7106_Discr;Read Threshold DAC.</span>
	tempReal = (%_DATA &amp; (2**10-1))
	tempReal = tempReal/(-1000) - 0.01		<span class="comment">; convert to voltage; -0.01 is largest (least neg.) voltage</span>
	tempReal = tempReal*1000		<span class="comment">; to display in mV</span>
	SET num2 TO tempReal			<span class="comment">; integer-ify the value</span>
	SET "$Discr1ThreshSetFor" CONTROL TO num2

	<span class="comment">; figure out what mode Discr1 is in</span>
	I = 1
	WRDIO &lt; "setup1"[DISCR1], DISCR1, 1, I &gt;    <span class="comment">;PS7106_Discr;Read Threshold Level.</span>
	num1 = (%_DATA &amp; (2**15))&gt;&gt;15		<span class="comment">; remote or local mode

	; treat each mode differently because the first way is the only way to read the thresh in LOCAL mode
	; and is off by ~10 mV (hence the 2nd way when in REMOTE)</span>
	IF (num1 = 1) THEN	<span class="comment">; LOCAL mode</span>
		FOR I = 1 TO 10
			<span class="comment">; this loop is silly but is used because changes aren't immediately readable and it is not time-dependent:
			; that is, one can't wait before the WRDIO for the register to "settle"</span>
			WRDIO &lt; "setup1"[DISCR1], DISCR1, 1, 1 &gt;    <span class="comment">;PS7106_Discr;Read Threshold Level.</span>
		END FOR

		<span class="comment">; R1-R10: ADC reading,-1 mV/bit conversion</span>
		tempReal = (%_DATA &amp; (2**10-1))
		tempReal = tempReal/(-1000) - 0.01		<span class="comment">; convert to voltage; -0.01 is largest (least neg.) voltage</span>

		tempReal = tempReal*1000		<span class="comment">; to display in mV</span>
		SET num1 TO tempReal			<span class="comment">; integer-ify the value</span>
	ELSE					<span class="comment">; REMOTE mode</span>
		<span class="comment">; already read in threshold for REMOTE mode</span>
		num1 = num2
	END IF

	SET "$Discr1Thresh" CONTROL TO num1
END

<span class="comment">; __________________________________________

; ReadThresh2 =&gt; display thresholds for discr2 on toolsheet</span>
ON ReadThresh2 DO
	<span class="comment">; first, display what threshold would be if Discr2 were in REMOTE mode</span>
	I = 1
	WRDIO &lt; "setup1"[DISCR2], DISCR2, 0, I &gt;    <span class="comment">;PS7106_Discr;Read Threshold DAC.</span>
	tempReal = (%_DATA &amp; (2**10-1))
	tempReal = tempReal/(-1000) - 0.01		<span class="comment">; convert to voltage; -0.01 is largest (least neg.) voltage</span>
	tempReal = tempReal*1000		<span class="comment">; to display in mV</span>
	SET num2 TO tempReal			<span class="comment">; integer-ify the value</span>
	SET "$Discr2ThreshSetFor" CONTROL TO num2

	<span class="comment">; figure out what mode Discr2 is in</span>
	I = 1
	WRDIO &lt; "setup1"[DISCR2], DISCR2, 1, I &gt;    <span class="comment">;PS7106_Discr;Read Threshold Level.</span>
	num1 = (%_DATA &amp; (2**15))&gt;&gt;15		<span class="comment">; remote or local mode</span>

	<span class="comment">; treat each mode differently because the first way is the only way to read the thresh in LOCAL mode
	; and is off by ~10 mV (hence the 2nd way when in REMOTE)</span>
	IF (num1 = 1) THEN	<span class="comment">; LOCAL mode</span>
		FOR I = 1 TO 10
			<span class="comment">; this loop is silly but is used because changes aren't immediately readable and it is not time-dependent:
			; that is, one can't wait before the WRDIO for the register to "settle"</span>
			WRDIO &lt; "setup1"[DISCR2], DISCR2, 1, 1 &gt;    <span class="comment">;PS7106_Discr;Read Threshold Level.</span>
		END FOR

		<span class="comment">; R1-R10: ADC reading,-1 mV/bit conversion</span>
		tempReal = (%_DATA &amp; (2**10-1))
		tempReal = tempReal/(-1000) - 0.01		<span class="comment">; convert to voltage; -0.01 is largest (least neg.) voltage</span>

		tempReal = tempReal*1000		<span class="comment">; to display in mV</span>
		SET num1 TO tempReal			<span class="comment">; integer-ify the value</span>
	ELSE		<span class="comment">; REMOTE mode
		; already read in threshold for REMOTE mode</span>
		num1 = num2
	END IF

	SET "$Discr2Thresh" CONTROL TO num1
END

<span class="comment">; __________________________________________

; $Discr1_CustomThresh =&gt; get discr1 threshold from user</span>
ON $Discr1_CustomThresh DO
	SET %_TEXT TO ""
	SET tempStr TO "Enter new threshold for slot"
	SET tempStr2 TO DISCR1
	ADD tempStr2 TO tempStr
	ADD " in negative mV (1034 &gt; x &gt; 9):" TO tempStr
	PROMPT WITH tempStr

	SET TDACin TO %_TEXT
	IF (%_OK) THEN
		TDACout = (TDACin - 10)			<span class="comment">; convert voltage to data for WRDIO</span>
		IF ((TDACout &gt; -1) &amp;&amp; (TDACout &lt; 1024)) THEN
			WRDIO &lt; "setup1"[DISCR1], DISCR1, 0, 17 &gt; (TDACout)    <span class="comment">;PS7106_Discr;Write Threshold DAC.</span>
			CALL ReadThresh1			<span class="comment">; to update threshold display</span>

			SET "$Discr1_10mV" CONTROL TO 0
			SET "$Discr1_15mV" CONTROL TO 0
			SET "$Discr1_20mV" CONTROL TO 0
			SET "$Discr1_30mV" CONTROL TO 0
		ELSE
			DISPLAY "Threshold not changed."
			SET ClearStatusDisplay TIMER TO 10 SECS
		END IF
	END IF
END

<span class="comment">; __________________________________________

; $Discr1_10mV =&gt; preset for discr1 threshold</span>
ON $Discr1_10mV DO
	SET "$Discr1_10mV" CONTROL TO 1
	SET "$Discr1_15mV" CONTROL TO 0
	SET "$Discr1_20mV" CONTROL TO 0
	SET "$Discr1_30mV" CONTROL TO 0

	TDACin = -0.01
	TDACout = (TDACin + 0.01) * (-1000)		<span class="comment">; convert voltage to data for WRDIO</span>

	WRDIO &lt; "setup1"[DISCR1], DISCR1, 0, 17 &gt; (TDACout)    <span class="comment">;PS7106_Discr;Write Threshold DAC.</span>
	CALL ReadThresh1				<span class="comment">; to update threshold display</span>
END

<span class="comment">; __________________________________________

; $Discr1_15mV =&gt; preset for discr1 threshold</span>
ON $Discr1_15mV DO
	SET "$Discr1_10mV" CONTROL TO 0
	SET "$Discr1_15mV" CONTROL TO 1
	SET "$Discr1_20mV" CONTROL TO 0
	SET "$Discr1_30mV" CONTROL TO 0

	TDACin = -0.015
	TDACout = (TDACin + 0.01) * (-1000)		<span class="comment">; convert voltage to data for WRDIO</span>

	WRDIO &lt; "setup1"[DISCR1], DISCR1, 0, 17 &gt; (TDACout)    <span class="comment">;PS7106_Discr;Write Threshold DAC.</span>
	CALL ReadThresh1				<span class="comment">; to update threshold display</span>
END
<span class="comment">; __________________________________________

; $Discr1_20mV =&gt; preset for discr1 threshold</span>
ON $Discr1_20mV DO
	SET "$Discr1_10mV" CONTROL TO 0
	SET "$Discr1_15mV" CONTROL TO 0
	SET "$Discr1_20mV" CONTROL TO 1
	SET "$Discr1_30mV" CONTROL TO 0

	TDACin = -0.02
	TDACout = (TDACin + 0.01) * (-1000)		<span class="comment">; convert voltage to data for WRDIO</span>

	WRDIO &lt; "setup1"[DISCR1], DISCR1, 0, 17 &gt; (TDACout)    <span class="comment">;PS7106_Discr;Write Threshold DAC.</span>
	CALL ReadThresh1				<span class="comment">; to update threshold display</span>
END
<span class="comment">; __________________________________________

; $Discr1_30mV =&gt; preset for discr1 threshold</span>
ON $Discr1_30mV DO
	SET "$Discr1_10mV" CONTROL TO 0
	SET "$Discr1_15mV" CONTROL TO 0
	SET "$Discr1_20mV" CONTROL TO 0
	SET "$Discr1_30mV" CONTROL TO 1

	TDACin = -0.03
	TDACout = (TDACin + 0.01) * (-1000)		<span class="comment">; convert voltage to data for WRDIO</span>

	WRDIO &lt; "setup1"[DISCR1], DISCR1, 0, 17 &gt; (TDACout)    <span class="comment">;PS7106_Discr;Write Threshold DAC.</span>
	CALL ReadThresh1				<span class="comment">; to update threshold display</span>
END
<span class="comment">; __________________________________________

; $Discr2_CustomThresh =&gt; get discr2 threshold from user</span>
ON $Discr2_CustomThresh DO
	SET %_TEXT TO ""
	SET tempStr TO "Enter new threshold for slot"
	SET tempStr2 TO DISCR2
	ADD tempStr2 TO tempStr
	ADD " in negative mV (1034 &gt; x &gt; 9):" TO tempStr

	PROMPT WITH tempStr

	SET TDACin TO %_TEXT
	IF (%_OK) THEN
		TDACout = (TDACin - 10)		<span class="comment">; convert voltage to data for WRDIO</span>
		IF ((TDACout &gt; -1) &amp;&amp; (TDACout &lt; 1024)) THEN
			WRDIO &lt; "setup1"[DISCR2], DISCR2, 0, 17 &gt; (TDACout)    <span class="comment">;PS7106_Discr;Write Threshold DAC.</span>
			CALL ReadThresh2		<span class="comment">; to update threshold display</span>

			SET "$Discr2_1fold" CONTROL TO 0
			SET "$Discr2_2fold" CONTROL TO 0
			SET "$Discr2_3fold" CONTROL TO 0
			SET "$Discr2_4fold" CONTROL TO 0
		ELSE
			DISPLAY "Threshold not changed."
			SET ClearStatusDisplay TIMER TO 10 SECS
		END IF
	END IF
END

<span class="comment">; __________________________________________

; $Discr2_1fold =&gt; preset for discr2 threshold</span>
ON $Discr2_1fold DO
	SET "$Discr2_1fold" CONTROL TO 1
	SET "$Discr2_2fold" CONTROL TO 0
	SET "$Discr2_3fold" CONTROL TO 0
	SET "$Discr2_4fold" CONTROL TO 0

	TDACin = -0.01
	TDACout = (TDACin + 0.01) * (-1000)		<span class="comment">; convert voltage to data for WRDIO</span>

	WRDIO &lt; "setup1"[DISCR2], DISCR2, 0, 17 &gt; (TDACout)    <span class="comment">;PS7106_Discr;Write Threshold DAC.</span>
	CALL ReadThresh2				<span class="comment">; to update threshold display</span>
END

<span class="comment">; __________________________________________

; $Discr2_2fold =&gt; preset for discr2 threshold</span>
ON $Discr2_2fold DO
	SET "$Discr2_1fold" CONTROL TO 0
	SET "$Discr2_2fold" CONTROL TO 1
	SET "$Discr2_3fold" CONTROL TO 0
	SET "$Discr2_4fold" CONTROL TO 0

	TDACin = -0.07
	TDACout = (TDACin + 0.01) * (-1000)		<span class="comment">; convert voltage to data for WRDIO</span>

	WRDIO &lt; "setup1"[DISCR2], DISCR2, 0, 17 &gt; (TDACout)    <span class="comment">;PS7106_Discr;Write Threshold DAC.</span>
	CALL ReadThresh2				<span class="comment">; to update threshold display</span>
END

<span class="comment">; __________________________________________

; $Discr2_3fold =&gt; preset for discr2 threshold</span>
ON $Discr2_3fold DO
	SET "$Discr2_1fold" CONTROL TO 0
	SET "$Discr2_2fold" CONTROL TO 0
	SET "$Discr2_3fold" CONTROL TO 1
	SET "$Discr2_4fold" CONTROL TO 0

	TDACin = -0.12
	TDACout = (TDACin + 0.01) * (-1000)		<span class="comment">; convert voltage to data for WRDIO</span>

	WRDIO &lt; "setup1"[DISCR2], DISCR2, 0, 17 &gt; (TDACout)    <span class="comment">;PS7106_Discr;Write Threshold DAC.</span>
	CALL ReadThresh2				<span class="comment">; to update threshold display</span>
END

<span class="comment">; __________________________________________

; $Discr2_4fold =&gt; preset for discr2 threshold</span>
ON $Discr2_4fold DO
	SET "$Discr2_1fold" CONTROL TO 0
	SET "$Discr2_2fold" CONTROL TO 0
	SET "$Discr2_3fold" CONTROL TO 0
	SET "$Discr2_4fold" CONTROL TO 1

	TDACin = -0.17
	TDACout = (TDACin + 0.01) * (-1000)		<span class="comment">; convert voltage to data for WRDIO</span>

	WRDIO &lt; "setup1"[DISCR2], DISCR2, 0, 17 &gt; (TDACout)    <span class="comment">;PS7106_Discr;Write Threshold DAC.</span>
	CALL ReadThresh2				<span class="comment">; to update threshold display</span>
END



<span class="comment">;===========================================</span>

	</pre>
</div>
