(FILECREATED "18-Sep-85 11:06:25" {DSK}<DSK>LISPUSERS>PCDAC.;15 63246  

      changes to:  (VARS PCDACTestTogMenuSpecs2 PCDACCOMS PCDACTestMenuItems)
		   (RECORDS PCDAC PCDDIG PCDDMA PCDAD PCDDA)
		   (FNS LevelOut PlayTone DigitalScope \PCDAC.PFS \PCDAC.MFS \PCDAC.DATAOFFSET 
			PCDAC.TEST PCDAC.SHOWSTATUS PCDAC.STOP PCDAC.READERROR ScopeInWindow 
			PCDAC.MAKETEST \PcdDontMove \PcdFakeIt1 \PcdFakeIt2 PCDAC.SETA/DPARAMETERS 
			PCDAC.SETD/APARAMETERS PCDAC.SETDIGITALINPUT PCDAC.SETDIGITALOUTPUT 
			PCDAC.RESET)

      previous date: "16-Sep-85 11:15:35" {DSK}<DSK>LISPUSERS>PCDAC.;6)


(* Copyright (c) 1984, 1985 by Xerox Corporation. All rights reserved.)

(PRETTYCOMPRINT PCDACCOMS)

(RPAQQ PCDACCOMS ((* * board-state record)
	(RECORDS PCDDIG PCDDMA PCDAD PCDDA PCDAC)
	(VARS (PCDAC.BOARD (create PCDAC pcdDMACHANNEL ← 1 pcdIOADDRESS ← 748 pcdTICKDURATION ← 
				   1.25E-6 pcdNAME ← "2801-A" pcdDATAFORMAT ← '12XS
				   pcdBIPOLAR? ← T))
	      (PCDAC.TIMEOUTCOUNT 1000)
	      (PCDAC.ERRORHANDLINGTOC 1000))
	(* * status-register bits)
	(CONSTANTS (PCDACSTATUS.DATAOUTREADY 1)
		   (PCDACSTATUS.DATAINFULL 2)
		   (PCDACSTATUS.READY 4)
		   (PCDACSTATUS.COMMAND 8)
		   (PCDACSTATUS.NOTUSED 112)
		   (PCDACSTATUS.COMPOSITEERROR 128))
	(* * worker -- misc)
	(FNS PCDAC.SETCLOCK PCDAC.SETUPDMA)
	(* * worker -- A/D)
	(FNS PCDAC.READA/DIMMEDIATE PCDAC.SETA/DPARAMETERS PCDAC.STARTREADA/D PCDAC.READA/DDATUM)
	(* * worker -- D/A)
	(FNS PCDAC.WRITED/AIMMEDIATE PCDAC.SETD/APARAMETERS PCDAC.STARTWRITED/A PCDAC.WRITED/ADATUM)
	(* * worker -- digital)
	(FNS PCDAC.SETDIGITALINPUT PCDAC.SETDIGITALOUTPUT PCDAC.READDIGITALIMMEDIATE 
	     PCDAC.WRITEDIGITALIMMEDIATE)
	(* * reset)
	(FNS PCDAC.STOP PCDAC.CLEARERROR PCDAC.RESET PCDAC.HARDRESET)
	(* * status-register handshaking)
	(FNS PCDAC.READYFORCOMMAND PCDAC.READYFORREAD PCDAC.READYFORWRITE)
	(* * error analysis)
	(FNS PCDAC.ERROR? PCDAC.SHOWSTATUS PCDAC.SHOWERROR PCDAC.READERROR)
	(* * internal -- lowest-level register-access functions)
	(FNS PCDAC.READSTATUS PCDAC.WRITECOMMAND PCDAC.READDATABYTE PCDAC.WRITEDATABYTE)
	(* * internal -- error analysis)
	(FNS PCDAC.CHECKEDSTATUS PCDAC.SHOWASTATUS PCDAC.SHOWASTATUS.BITASSIGN PCDAC.SHOWSTATE 
	     PCDAC.SHOWANERROR PCDAC.SHOWANERROR.BITASTEXT)
	(* * internal -- utility)
	(FNS PCDAC.DOCOMMAND PCDAC.COMMANDASTEXT PCDAC.STATUSASTEXT PCDAC.YNQUERY \PCDAC.DATAOFFSET 
	     \PCDAC.MFS \PCDAC.PFS)
	(DECLARE: DONTCOPY (MACROS PCDAC.WRITEBYTES&SYNC?))
	(* * Checkout)
	(FNS PCDAC.MAKETEST PCDAC.TEST LevelOut PlayBack \MakeSinInArray PlayTone PCDACTestRead 
	     DigitalScope PCDACTestWindowButtonFn DoPCDACTest ScopeInWindow)
	(* * hacks because of non-feature in ATTACHWINDOWS)
	(FNS \PcdDontMove \PcdFakeIt1 \PcdFakeIt2)
	(VARS (PCDACTestMenu)
	      (ScopeHTickHeight 5)
	      (ScopeVTickWidth 5)
	      (\PCDACTestBufferStart)
	      PCDACTestMenuItems PCDACTestTogMenuSpecs1 PCDACTestTogMenuSpecs2 PCDACIcon)
	(INITVARS (\SSDataArray (ARRAY 32768 'WORD
				       0 0 128)))
	[DECLARE: DOCOPY (DECLARE: DONTEVAL@LOAD EVAL@COMPILE
				   (ADDVARS (NOFIXFNSLST PCDAC.READA/DIMMEDIATE 
							 PCDAC.SETA/DPARAMETERS PCDAC.STARTREADA/D 
							 PCDAC.READA/DDATUM PCDAC.WRITED/AIMMEDIATE 
							 PCDAC.SETD/APARAMETERS PCDAC.STARTWRITED/A 
							 PCDAC.WRITED/ADATUM]
	(DECLARE: DONTCOPY DONTEVAL@LOAD DOEVAL@COMPILE [P (RESETSAVE DWIMIFYCOMPFLG T)
							   (COND ([NOT (OR (GETP 'ARRAYBASE
										 'DMACRO)
									   (GETP 'ARRAYBASE
										 'MACRO]
								  (HELP 
			       "ARRAYBASE needed - load macro def'n from somewhere and/or RETURN"]
		  (GLOBALVARS \PCDACTestBufferStart PCDAC.BOARD PCDACTestMenuItems 
			      PCDACTestTogMenuSpecs1 PCDACTestTogMenuSpecs2 PCDACIcon PCDACTestMenu 
			      \SSDataArray)
		  (FILES (LOADCOMP)
			 BUSMASTER.DCOM))
	(FILES (SYSLOAD)
	       BUSMASTER)))
(* * board-state record)

[DECLARE: EVAL@COMPILE 

(RECORD PCDDIG (pcdPORT0DIR pcdPORT1DIR)
	       pcdPORT0DIR ← '??
	       pcdPORT1DIR ← '??)

(RECORD PCDDMA (pcdPAGE pcdBASEADDRESS pcdBASENPOINTS pcdWRITETOMEM? pcdAUTOINIT?)
	       pcdPAGE ← '??
	       pcdBASEADDRESS ← '??
	       pcdBASENPOINTS ← '??
	       pcdWRITETOMEM? ← '??
	       pcdAUTOINIT? ← '??)

(RECORD PCDAD (pcdGAINCODE pcdSTARTCHAN pcdENDCHAN pcdNPOINTS)
	      pcdGAINCODE ← '??
	      pcdSTARTCHAN ← '??
	      pcdENDCHAN ← '??
	      pcdNPOINTS ← '??)

(RECORD PCDDA (pcdDACSELECT pcdNPOINTS)
	      pcdDACSELECT ← '??
	      pcdNPOINTS ← '??)

(RECORD PCDAC (pcdNAME pcdDMACHANNEL pcdIOADDRESS pcdSYNCHRONOUS? pcdTICKDURATION pcdCLOCKPERIOD 
		       pcdDIGPORTDIR pcdDMA pcdADPARS pcdDAPARS pcdLASTCOMMAND pcdLASTWORKERCMD 
		       pcdSTOPFLAG pcdQUIETERRORS pcdDATAFORMAT pcdBIPOLAR?)
	      pcdCLOCKPERIOD ← '??
	      pcdDIGPORTDIR ←(create PCDDIG)
	      pcdDMA ←(create PCDDMA)
	      pcdADPARS ←(create PCDAD)
	      pcdDAPARS ←(create PCDDA)
	      pcdLASTCOMMAND ← '??
	      pcdLASTWORKERCMD ← '??
	      pcdSTOPFLAG ← '??)
]

(RPAQ PCDAC.BOARD (create PCDAC pcdDMACHANNEL ← 1 pcdIOADDRESS ← 748 pcdTICKDURATION ← 1.25E-6 
			  pcdNAME ← "2801-A" pcdDATAFORMAT ← '12XS
			  pcdBIPOLAR? ← T))

(RPAQQ PCDAC.TIMEOUTCOUNT 1000)

(RPAQQ PCDAC.ERRORHANDLINGTOC 1000)
(* * status-register bits)

(DECLARE: EVAL@COMPILE 

(RPAQQ PCDACSTATUS.DATAOUTREADY 1)

(RPAQQ PCDACSTATUS.DATAINFULL 2)

(RPAQQ PCDACSTATUS.READY 4)

(RPAQQ PCDACSTATUS.COMMAND 8)

(RPAQQ PCDACSTATUS.NOTUSED 112)

(RPAQQ PCDACSTATUS.COMPOSITEERROR 128)

(CONSTANTS (PCDACSTATUS.DATAOUTREADY 1)
	   (PCDACSTATUS.DATAINFULL 2)
	   (PCDACSTATUS.READY 4)
	   (PCDACSTATUS.COMMAND 8)
	   (PCDACSTATUS.NOTUSED 112)
	   (PCDACSTATUS.COMPOSITEERROR 128))
)
(* * worker -- misc)

(DEFINEQ

(PCDAC.SETCLOCK
  [LAMBDA (N HERTZFLG)                                       (* ht: "16-Sep-85 11:03")

          (* * set DAC board clock period in 1.25 or 2.5 usec ticks)


    (LET ((NTICKS (if HERTZFLG
		      then (FIX (FQUOTIENT (FQUOTIENT 1.0 N)
					   PCDAC.BOARD:pcdTICKDURATION))
		    else N)))
      (if (OR (ILESSP NTICKS 2)
	      (IGREATERP NTICKS 65535))
	  then (HELP "bad NTICKS arg:" NTICKS))
      (PCDAC.DOCOMMAND 3)
      PCDAC.BOARD:pcdCLOCKPERIOD←NTICKS
      (PCDAC.WRITEBYTES&SYNC? NTICKS (LRSH NTICKS 8])

(PCDAC.SETUPDMA
  [LAMBDA (PAGE ADDR NPOINTS WRITEMEM? AUTOINIT?)            (* ht: "16-Sep-85 11:06")

          (* * sets up the DAC%'s dma channel, leaving it unmasked -- presumes BUSDMA is initialized -- assumes BUSDMA checks 
	  its args)


    (PROG ((DMACHANNEL (PCDAC.BOARD:pcdDMACHANNEL))
	   (DMARECORD (PCDAC.BOARD:pcdDMA)))
          (BUSDMA.MASK DMACHANNEL)
          (BUSDMA.SETMODE DMACHANNEL WRITEMEM? AUTOINIT?)
          (DMARECORD:pcdWRITETOMEM?←WRITEMEM?)
          (DMARECORD:pcdAUTOINIT?←AUTOINIT?)
          (BUSDMA.SETPAGE DMACHANNEL PAGE)
          (DMARECORD:pcdPAGE←PAGE)
          (BUSDMA.SETADDRESS DMACHANNEL ADDR)
          (DMARECORD:pcdBASEADDRESS←ADDR)
          (BUSDMA.SETCOUNTER DMACHANNEL (ITIMES NPOINTS 2))
          (DMARECORD:pcdBASENPOINTS←NPOINTS)
          (BUSDMA.UNMASK DMACHANNEL])
)
(* * worker -- A/D)

(DEFINEQ

(PCDAC.READA/DIMMEDIATE
  [LAMBDA (GAINCODE CHAN EXTTRIG?)                           (* ht: "16-Sep-85 10:09")
    (if (BITTEST GAINCODE (LOGNOT 3))
	then (HELP "bad GAINCODE arg:" GAINCODE))
    (if (BITTEST CHAN (LOGNOT 15))
	then (HELP "bad CHAN arg:" CHAN))
    (PCDAC.DOCOMMAND (if EXTTRIG?
			 then 140
		       else 12))
    (PCDAC.WRITEBYTES&SYNC? GAINCODE CHAN])

(PCDAC.SETA/DPARAMETERS
  [LAMBDA (GAINCODE STARTCHAN ENDCHAN NPOINTS)               (* ht: "16-Sep-85 12:08")

          (* * NPOINTS defaults to 64K-1 -- ENDCHAN defaults to STARTCHAN)


    (if (BITTEST GAINCODE (LOGNOT 3))
	then (HELP "bad GAINCODE arg:" GAINCODE))
    (if (BITTEST STARTCHAN (LOGNOT 15))
	then (HELP "bad STARTCHAN arg:" STARTCHAN))
    (if ENDCHAN=NIL
	then ENDCHAN←STARTCHAN
      elseif (BITTEST ENDCHAN (LOGNOT 15))
	then (HELP "bad ENDCHAN arg:" ENDCHAN))
    (if NPOINTS=NIL
	then NPOINTS←65535
      elseif (OR (ILESSP NPOINTS 3)
		 (IGREATERP NPOINTS 65535))
	then (HELP "bad NPOINTS arg:" NPOINTS))
    (PCDAC.DOCOMMAND 13)
    (LET ((datum PCDAC.BOARD:pcdADPARS))
      datum:PCDAD.pcdGAINCODE←GAINCODE
      datum:PCDAD.pcdSTARTCHAN←STARTCHAN
      datum:PCDAD.pcdENDCHAN←ENDCHAN
      datum:PCDAD.pcdNPOINTS←NPOINTS)
    (PCDAC.WRITEBYTES&SYNC? GAINCODE STARTCHAN ENDCHAN NPOINTS (LRSH NPOINTS 8])

(PCDAC.STARTREADA/D
  [LAMBDA (DMA? CONTINUOUS? EXTCLOCK? EXTTRIG?)              (* ht: "16-Sep-85 09:44")
    (PCDAC.DOCOMMAND (LOGOR 14 (if DMA?
				   then 16
				 else 0)
			    (if CONTINUOUS?
				then 32
			      else 0)
			    (if EXTCLOCK?
				then 64
			      else 0)
			    (if EXTTRIG?
				then 128
			      else 0])

(PCDAC.READA/DDATUM
  [LAMBDA NIL                                                (* edited: "22-Oct-84 19:47")
    (PROG (LOWBYTE)
          (PCDAC.READYFORREAD)
          (SETQ LOWBYTE (PCDAC.READDATABYTE))
          (PCDAC.READYFORREAD)
          (RETURN (LOGOR LOWBYTE (LLSH (PCDAC.READDATABYTE)
				       10Q])
)
(* * worker -- D/A)

(DEFINEQ

(PCDAC.WRITED/AIMMEDIATE
  [LAMBDA (DACSELECT DATUM SECONDDATUM EXTTRIG?)             (* ht: "16-Sep-85 11:02")
    (if (OR (MINUSP DACSELECT)
	    (IGREATERP DACSELECT 2))
	then (HELP "bad DACSELECT arg:" DACSELECT))
    (PCDAC.DOCOMMAND (if EXTTRIG?
			 then 136
		       else 8))
    (PCDAC.READYFORWRITE)
    (PCDAC.WRITEDATABYTE DACSELECT)
    (PCDAC.WRITED/ADATUM DATUM)
    (if DACSELECT=2
	then (PCDAC.WRITED/ADATUM SECONDDATUM))
    (if PCDAC.BOARD:pcdSYNCHRONOUS?
	then (PCDAC.READYFORCOMMAND])

(PCDAC.SETD/APARAMETERS
  [LAMBDA (DACSELECT NPOINTS)                                (* ht: "16-Sep-85 11:57")

          (* * NPOINTS defaults to 64K-1)


    (if (OR (MINUSP DACSELECT)
	    (IGREATERP DACSELECT 2))
	then (HELP "bad DACSELECT arg:" DACSELECT))
    (if NPOINTS=NIL
	then NPOINTS←65535
      elseif (OR (ILESSP NPOINTS 3)
		 (IGREATERP NPOINTS 65535))
	then (HELP "bad NPOINTS arg:" NPOINTS))
    (PCDAC.DOCOMMAND 9)
    (LET ((datum PCDAC.BOARD:pcdDAPARS))
      datum:PCDDA.pcdDACSELECT←DACSELECT
      datum:PCDDA.pcdNPOINTS←NPOINTS)
    (PCDAC.WRITEBYTES&SYNC? DACSELECT NPOINTS (LRSH NPOINTS 8])

(PCDAC.STARTWRITED/A
  [LAMBDA (DMA? CONTINUOUS? EXTCLOCK? EXTTRIG?)              (* ht: "16-Sep-85 09:44")
    (PCDAC.DOCOMMAND (LOGOR 10 (if DMA?
				   then 16
				 else 0)
			    (if CONTINUOUS?
				then 32
			      else 0)
			    (if EXTCLOCK?
				then 64
			      else 0)
			    (if EXTTRIG?
				then 128
			      else 0])

(PCDAC.WRITED/ADATUM
  [LAMBDA (DATUM)                                            (* edited: "22-Oct-84 19:47")
    (if (NOT (FIXP DATUM))
	then (HELP "bad DATUM arg:" DATUM))
    (PCDAC.READYFORWRITE)
    (PCDAC.WRITEDATABYTE DATUM)
    (PCDAC.READYFORWRITE)
    (PCDAC.WRITEDATABYTE (LRSH DATUM 10Q])
)
(* * worker -- digital)

(DEFINEQ

(PCDAC.SETDIGITALINPUT
  [LAMBDA (PORTSELECT EXTTRIG?)                              (* ht: "16-Sep-85 11:57")
    (if (OR (MINUSP PORTSELECT)
	    (IGREATERP PORTSELECT 2))
	then (HELP "bad PORTSELECT arg:" PORTSELECT))
    (PCDAC.DOCOMMAND (if EXTTRIG?
			 then 132
		       else 4))
    [LET ((datum PCDAC.BOARD:pcdDIGPORTDIR))
      (if (OR PORTSELECT=0 PORTSELECT=2)
	  then (datum:PCDDIG.pcdPORT0DIR← 'INPUT))
      (if (OR PORTSELECT=0 PORTSELECT=1)
	  then (datum:PCDDIG.pcdPORT1DIR← 'INPUT]
    (PCDAC.WRITEBYTES&SYNC? PORTSELECT])

(PCDAC.SETDIGITALOUTPUT
  [LAMBDA (PORTSELECT EXTTRIG?)                              (* ht: "16-Sep-85 11:58")
    (if (OR (MINUSP PORTSELECT)
	    (IGREATERP PORTSELECT 2))
	then (HELP "bad PORTSELECT arg:" PORTSELECT))
    (PCDAC.DOCOMMAND (if EXTTRIG?
			 then 133
		       else 5))
    [LET ((datum PCDAC.BOARD:pcdDIGPORTDIR))
      (if (OR PORTSELECT=0 PORTSELECT=2)
	  then (datum:PCDDIG.pcdPORT0DIR← 'OUTPUT))
      (if (OR PORTSELECT=0 PORTSELECT=1)
	  then (datum:PCDDIG.pcdPORT1DIR← 'OUTPUT]
    (PCDAC.WRITEBYTES&SYNC? PORTSELECT])

(PCDAC.READDIGITALIMMEDIATE
  [LAMBDA (PORTSELECT EXTTRIG?)                              (* ht: "16-Sep-85 11:02")
    (LET (VALUE)
      (if (OR (MINUSP PORTSELECT)
	      (IGREATERP PORTSELECT 2))
	  then (HELP "bad PORTSELECT arg:" PORTSELECT))
      (PCDAC.DOCOMMAND (if EXTTRIG?
			   then 134
			 else 6))
      (PCDAC.READYFORWRITE)
      (PCDAC.WRITEDATABYTE PORTSELECT)
      (PCDAC.READYFORREAD)
      VALUE←(PCDAC.READDATABYTE)
      [if PORTSELECT=2
	  then (PCDAC.READYFORREAD)
	       (VALUE←(LOGOR VALUE (LLSH (PCDAC.READDATABYTE)
					 8]
      (if PCDAC.BOARD:pcdSYNCHRONOUS?
	  then (PCDAC.READYFORCOMMAND))
      VALUE])

(PCDAC.WRITEDIGITALIMMEDIATE
  [LAMBDA (PORTSELECT DATUM EXTTRIG?)                        (* ht: "16-Sep-85 11:02")
    (if (OR (MINUSP PORTSELECT)
	    (IGREATERP PORTSELECT 2))
	then (HELP "bad PORTSELECT arg:" PORTSELECT))
    (PCDAC.DOCOMMAND (if EXTTRIG?
			 then 135
		       else 7))
    (PCDAC.READYFORWRITE)
    (PCDAC.WRITEDATABYTE PORTSELECT)
    (PCDAC.READYFORWRITE)
    (PCDAC.WRITEDATABYTE DATUM)
    (if PORTSELECT=2
	then (PCDAC.READYFORWRITE)
	     (PCDAC.WRITEDATABYTE DATUM))
    (if PCDAC.BOARD:pcdSYNCHRONOUS?
	then (PCDAC.READYFORCOMMAND])
)
(* * reset)

(DEFINEQ

(PCDAC.STOP
  [LAMBDA (CERROK? ERRORHANDLING? QUERYMESSAGE)              (* ht: "16-Sep-85 17:31")

          (* * issue Stop command sequence, wait for it to take effect, and check if it succeeded -- if it did not then call 
	  PCDAC.SHOWSTATUS (and retry) -- BUT IF QUERYMESSAGE is non-NIL then it is a string describing the purpose for this 
	  PCDAC.STOP call and we only issue the Stop if the Ready bit is not set AND user says it is ok -- NOTE that the 
	  status register has to be looked at before the Stop -- this is done as though CERROK? and ERRORHANDLING? were set)



          (* * BUT IF ERRORHANDLING? -- after PCDAC.SHOWSTATUS immediately return NIL (else return T))



          (* * pcdSTOPFLAG says whether we have caused a "command overrun" error by issuing a Stop command while a command was
	  running -- a value of NIL means that we definitely have not done this, since we have not issued any Stop commands 
	  with a command running since the error register was last successfully cleared -- a value of T means that we 
	  definitely have caused a "command overrun" error, since we issued a Stop command with a command running and the 
	  composite error bit clear -- a value of (QUOTE ??) means that we may have caused a "command overrun" error, since we
	  issued a Stop command while a command was running, but since the composite error bit was set, we can%'t be sure 
	  (we%'d have to Stop to ReadError to look at the "command overrun" bit to be sure!) -- a value of 
	  (QUOTE ??) can also mean: just loaded the package OR Stop found the status register to be trash -- PCDAC.CLEARERROR 
	  and PCDAC.RESET set NIL, PCDAC.STOP sets non-NIL, PCDAC.SHOWANERROR reads)


    (PROG ((COMMAND 15)
	   (STATUS (PCDAC.CHECKEDSTATUS T T))
	   STOPPED?)

          (* * if asked to query then if Ready is set just return T else (Ready is clear or unknown and) query whether to 
	  proceed or return NIL)


          [if QUERYMESSAGE~=NIL
	      then (if (AND STATUS (BITTEST STATUS PCDACSTATUS.READY))
		       then (RETURN T)
		     elseif NOT (PCDAC.BOARD:pcdQUIETERRORS)
		       then (if STATUS~=NIL
				then (printout T "the DAC has a command running" T))
			    (printout T "I want to STOP the DAC " QUERYMESSAGE T)
			    (if (NOT (PCDAC.YNQUERY "shall I do this"))
				then (RETURN NIL]

          (* * we are going to issue Stop command -- set pcdSTOPFLAG accordingly, given current state of Ready and 
	  compositeError bits -- no other action on compositeError bit now, we%'ll leave that for after the Stop, but we do 
	  want a nontrapping message if status register is trash)


          [if STATUS=NIL
	      then (PCDAC.BOARD:pcdSTOPFLAG← '??)
	    elseif (NOT (BITTEST STATUS PCDACSTATUS.READY))
	      then (if (NOT (BITTEST STATUS PCDACSTATUS.COMPOSITEERROR))
		       then (PCDAC.BOARD:pcdSTOPFLAG←T)
		     elseif PCDAC.BOARD:pcdSTOPFLAG=NIL
		       then (PCDAC.BOARD:pcdSTOPFLAG← '??]

          (* * issue Stop command and complete its command sequence)


          (repeatuntil (OR ERRORHANDLING? STOPPED?)
	     do (PCDAC.WRITECOMMAND COMMAND)
		(PCDAC.BOARD:pcdLASTCOMMAND←COMMAND)
		(PCDAC.READDATABYTE) 

          (* * wait for Stop to take effect and check success)


		(STOPPED?←(PCDAC.READYFORCOMMAND CERROK? ERRORHANDLING?)))
          (RETURN STOPPED?])

(PCDAC.CLEARERROR
  [LAMBDA (ERRORHANDLING?)                                   (* ht: "16-Sep-85 11:14")

          (* * issue Clear Error Register command sequence and check if it succeeded -- if not then call PCDAC.SHOWSTATUS 
	  (and retry) -- NOTE ignores CompositeError until final check to see that it cleared, then never ignores it -- NOTE 
	  only STOPs the DAC if Ready bit is clear)



          (* * BUT IF ERRORHANDLING? --after PCDAC.SHOWSTATUS or after PCDAC.STOP returns NIL, immediately returns NIL 
	  (else returns T))


    (bind STATUS (COMMAND ← 1)
       do (if (NOT (PCDAC.STOP T ERRORHANDLING? "to clear the error register"))
	      then (GO FAIL))
	  (PCDAC.WRITECOMMAND COMMAND)
	  (PCDAC.BOARD:pcdLASTCOMMAND←COMMAND)
	  (if (NOT (PCDAC.READYFORCOMMAND T ERRORHANDLING?))
	      then (GO FAIL))
	  (STATUS←(PCDAC.CHECKEDSTATUS T ERRORHANDLING?))
	  (if STATUS=NIL
	      then (GO FAIL)
	    elseif (BITTEST STATUS PCDACSTATUS.COMPOSITEERROR)
	      then (PCDAC.SHOWSTATUS STATUS "PCDAC.CLEARERROR failed to clear error bit" 
				     ERRORHANDLING?)
		   (RETURN NIL)
	    else (PCDAC.BOARD:pcdSTOPFLAG←NIL)
		 (RETURN T))
	  FAIL
	  (printout T "PCDAC.CLEARERROR giving up" T)
	  (RETURN NIL])

(PCDAC.RESET
  [LAMBDA NIL                                                (* ht: "16-Sep-85 12:02")
    (bind STATUS (COMMAND ← 0)
       do (if (NOT (PCDAC.STOP T T))
	      then (GO FAIL))
	  (PCDAC.WRITECOMMAND COMMAND)
	  (PCDAC.BOARD:pcdLASTCOMMAND←COMMAND)
	  (PCDAC.BOARD:pcdCLOCKPERIOD← '4?)
	  (LET ((datum PCDAC.BOARD:pcdDIGPORTDIR))
	    datum:PCDDIG.pcdPORT0DIR←
	    'INPUT?
	    datum:PCDDIG.pcdPORT1DIR←
	    'INPUT?)
	  (LET ((datum PCDAC.BOARD:pcdADPARS))
	    datum:PCDAD.pcdGAINCODE←
	    'BAD?
	    datum:PCDAD.pcdSTARTCHAN←
	    'BAD?
	    datum:PCDAD.pcdENDCHAN←
	    'BAD?
	    datum:PCDAD.pcdNPOINTS←
	    'BAD?)
	  (LET ((datum PCDAC.BOARD:pcdDAPARS))
	    datum:PCDDA.pcdDACSELECT←
	    'BAD?
	    datum:PCDDA.pcdNPOINTS←
	    'BAD?)
	  (PCDAC.READDATABYTE)
	  (if (NOT (PCDAC.READYFORCOMMAND T T))
	      then (GO FAIL))
	  (STATUS←(PCDAC.CHECKEDSTATUS T T))
	  (if STATUS=NIL
	      then (GO FAIL)
	    elseif (BITTEST STATUS PCDACSTATUS.COMPOSITEERROR)
	      then (PCDAC.SHOWSTATUS STATUS "PCDAC.RESET failed to clear error bit" T)
		   (RETURN NIL)
	    else (PCDAC.BOARD:pcdSTOPFLAG←NIL)
		 (RETURN T))
	  FAIL
	  (printout T "PCDAC.RESET giving up" T)
	  (RETURN NIL])

(PCDAC.HARDRESET
  [LAMBDA NIL                                                (* ht: "22-Jun-85 16:46")
    (BUS.RESET)
    (PCDAC.RESET])
)
(* * status-register handshaking)

(DEFINEQ

(PCDAC.READYFORCOMMAND
  [LAMBDA (CERROK? ERRORHANDLING?)                           (* jmh "14-Nov-84 16:22")

          (* * loop until the Ready bit of the status register is set -- BUT if timeout then call PCDAC.SHOWSTATUS 
	  (and restart the loop) -- timeout is controlled by PCDAC.TIMEOUTCOUNT (if FIXP then it is the number of tries before
	  timeout, else never timeout))



          (* * BUT IF ERRORHANDLING? -- after PCDAC.SHOWSTATUS and after PCDAC.CHECKEDSTATUS returns NIL, immediately return 
	  NIL (else return T) -- AND timeout is controlled by PCDAC.ERRORHANDLINGTOC)


    (bind STATUS (COUNTER ← 0)
	  (MAXCOUNT ←(if ERRORHANDLING?
			 then PCDAC.ERRORHANDLINGTOC
		       else PCDAC.TIMEOUTCOUNT))
       do (SETQ STATUS (PCDAC.CHECKEDSTATUS CERROK? ERRORHANDLING?))
	  (if (NULL STATUS)
	      then (RETURN NIL)
	    elseif (BITTEST STATUS PCDACSTATUS.READY)
	      then (RETURN T)
	    elseif (AND (FIXP MAXCOUNT)
			(IGEQ (add COUNTER 1)
			      MAXCOUNT))
	      then (PCDAC.SHOWSTATUS STATUS "timeout waiting for Ready bit" ERRORHANDLING?)
		   (if ERRORHANDLING?
		       then (RETURN NIL)
		     else (SETQ COUNTER 0])

(PCDAC.READYFORREAD
  [LAMBDA (CERROK? ERRORHANDLING?)                           (* jmh "14-Nov-84 16:21")

          (* * loop until the DataOutReady bit of the status register is set -- BUT if the Ready bit is set OR timeout then 
	  call PCDAC.SHOWSTATUS (and restart the loop) -- timeout is controlled by PCDAC.TIMEOUTCOUNT 
	  (if FIXP then it is the number of tries before timeout, else never timeout))



          (* * BUT IF ERRORHANDLING? -- after PCDAC.SHOWSTATUS and after PCDAC.CHECKEDSTATUS returns NIL, immediately return 
	  NIL (else return T) -- AND timeout is controlled by PCDAC.ERRORHANDLINGTOC)


    (bind STATUS (COUNTER ← 0)
	  (MAXCOUNT ←(if ERRORHANDLING?
			 then PCDAC.ERRORHANDLINGTOC
		       else PCDAC.TIMEOUTCOUNT))
       do (SETQ STATUS (PCDAC.CHECKEDSTATUS CERROK? ERRORHANDLING?))
	  (if (NULL STATUS)
	      then (RETURN NIL)
	    elseif (BITTEST STATUS PCDACSTATUS.READY)
	      then (PCDAC.SHOWSTATUS STATUS "Ready bit set before end of command sequence" 
				     ERRORHANDLING?)
		   (if ERRORHANDLING?
		       then (RETURN NIL)
		     else (SETQ COUNTER 0))
	    elseif (BITTEST STATUS PCDACSTATUS.DATAOUTREADY)
	      then (RETURN T)
	    elseif (AND (FIXP MAXCOUNT)
			(IGEQ (add COUNTER 1)
			      MAXCOUNT))
	      then (PCDAC.SHOWSTATUS STATUS "timeout waiting for DataOutReady bit" ERRORHANDLING?)
		   (if ERRORHANDLING?
		       then (RETURN NIL)
		     else (SETQ COUNTER 0])

(PCDAC.READYFORWRITE
  [LAMBDA (CERROK? ERRORHANDLING?)                           (* jmh "14-Nov-84 16:25")

          (* * loop until the DataInFull bit of the status register is clear -- BUT if the Ready bit is set OR timeout then 
	  call PCDAC.SHOWSTATUS (and restart the loop) -- timeout is controlled by PCDAC.TIMEOUTCOUNT 
	  (if FIXP then it is the number of tries before timeout, else never timeout))



          (* * BUT IF ERRORHANDLING? -- after PCDAC.SHOWSTATUS and after PCDAC.CHECKEDSTATUS returns NIL, immediately return 
	  NIL (else return T) -- AND timeout is controlled by PCDAC.ERRORHANDLINGTOC)


    (bind STATUS (COUNTER ← 0)
	  (MAXCOUNT ←(if ERRORHANDLING?
			 then PCDAC.ERRORHANDLINGTOC
		       else PCDAC.TIMEOUTCOUNT))
       do (SETQ STATUS (PCDAC.CHECKEDSTATUS CERROK? ERRORHANDLING?))
	  (if (NULL STATUS)
	      then (RETURN NIL)
	    elseif (BITTEST STATUS PCDACSTATUS.READY)
	      then (PCDAC.SHOWSTATUS STATUS "Ready bit set before end of command sequence" 
				     ERRORHANDLING?)
		   (if ERRORHANDLING?
		       then (RETURN NIL)
		     else (SETQ COUNTER 0))
	    elseif (NOT (BITTEST STATUS PCDACSTATUS.DATAINFULL))
	      then (RETURN T)
	    elseif (AND (FIXP MAXCOUNT)
			(IGEQ (add COUNTER 1)
			      MAXCOUNT))
	      then (PCDAC.SHOWSTATUS STATUS "timeout waiting for DataInFull bit to clear" 
				     ERRORHANDLING?)
		   (if ERRORHANDLING?
		       then (RETURN NIL)
		     else (SETQ COUNTER 0])
)
(* * error analysis)

(DEFINEQ

(PCDAC.ERROR?
  [LAMBDA (CERROK?)                                          (* edited: "22-Oct-84 20:00")

          (* * return= "is the CompositeError bit of the status register set?" -- BUT if not CERROK? then doesn't return T but
	  rather calls PCDAC.SHOWSTATUS (and retries) (this is done inside PCDAC.CHECKEDSTATUS))


    (BITTEST (PCDAC.CHECKEDSTATUS CERROK?)
	     PCDACSTATUS.COMPOSITEERROR])

(PCDAC.SHOWSTATUS
  [LAMBDA (STATUS MESSAGE ERRORHANDLING?)                    (* ht: "17-Sep-85 09:48")

          (* * user should never supply MESSAGE nor ERRORHANDLING? arguments -- either one indicates that we are being called 
	  from within special error-handling or -analysis code in the PCDAC package ** CASE: called from user with STATUS 
	  argument provided -- just explain it -- CASE: called from user without STATUS argument -- fetch status and error 
	  register, explain them, offer facilities -- CASE: called from within error handling but not ERRORHANDLING? -- fetch 
	  status if necessary, error register if possible, explain them, offer facilities -- CASE: called with ERRORHANDLING? 
	  -- briefly describe status ** returns status if returns at all -- current "facilities" trivial)


    [LET (ERRORREG)
      (if (AND MESSAGE PCDAC.BOARD:pcdQUIETERRORS)
	  then 

          (* * BUT if we have a message, meaning this is really an internal error call, and the flag is set in the board 
	  record, then we just raise an error -
	  this is an experiment in trying to hide a bit more from the user.)


	       [if (NOT ERRORHANDLING?)
		   then (if (ERROR "PCDAC problems" (LIST MESSAGE (OR STATUS STATUS←(PCDAC.READSTATUS)
								      )
							  ERRORREG←(PCDAC.READERROR T)))
			    then 

          (* * if the user returns from the error give the standard display)


				 (TERPRI T)
				 (PCDAC.SHOWASTATUS STATUS)
				 (if (STRINGP MESSAGE)
				     then (printout T "!! " MESSAGE " !!" T))
				 (PCDAC.SHOWSTATE)
				 (if (BITTEST STATUS PCDACSTATUS.COMPOSITEERROR)
				     then (PCDAC.SHOWERROR ERRORREG T]
	elseif ERRORHANDLING?
	  then 

          (* * CASE: if called with ERRORHANDLING? then we want to just give the messages that explain why we%'ve been called,
	  and not recurse or go into distracting detail but rather just return NIL)


	       (printout T "PCDAC error within error analysis:" T ".. ")
	       (PCDAC.SHOWASTATUS STATUS)
	       (if (STRINGP MESSAGE)
		   then (printout T "!! " MESSAGE " !!" T))
	       (PCDAC.SHOWSTATE)
	elseif (AND MESSAGE=NIL (FIXP STATUS))
	  then 

          (* * CASE: if called from user and they provided a "status" argument, then presumably they just want it explained)


	       (PCDAC.SHOWASTATUS STATUS)
	else 

          (* * CASE: otherwise we are either analyzing first error or are dynamically analyzing status for interactive user --
	  we fetch/show/explain the status register, get the error register (if we can) and show/explain it, and offer to show
	  it all again or return)


	     (do 

          (* * get status if we don%'t have it, and show and explain it)


		 (if STATUS=NIL
		     then STATUS←(PCDAC.READSTATUS))
		 (PCDAC.SHOWASTATUS STATUS)
		 (if (STRINGP MESSAGE)
		     then (printout T "!! " MESSAGE " !!" T))
		 (PCDAC.SHOWSTATE) 

          (* * if the compositeError bit is set then we want to show and explain the error register)


		 (if (BITTEST STATUS PCDACSTATUS.COMPOSITEERROR)
		     then ERRORREG←(PCDAC.SHOWERROR ERRORREG T))

          (* * now we ask the user if they want to see it again -- we have no "facilities" to offer at this point)


		 repeatuntil (NOT (PCDAC.YNQUERY "type Y=redisplay or N=return or ↑E or etc"]

          (* * in every case return STATUS)


    STATUS])

(PCDAC.SHOWERROR
  [LAMBDA (ERROR ERRORHANDLING?)                             (* jmh "14-Nov-84 18:08")
    (PROG (RFC?)
          (if (NULL ERROR)
	      then (SETQ ERROR (PCDAC.READERROR ERRORHANDLING?)))
          (if ERROR
	      then (PCDAC.SHOWANERROR ERROR))
          (RETURN ERROR])

(PCDAC.READERROR
  [LAMBDA (ERRORHANDLING?)                                   (* ht: "16-Sep-85 17:36")

          (* * read and return the error register -- BUT if the Ready bit is clear then Stop the DAC first 
	  (first asking the user if this is ok) (this is in PCDAC.STOP) -- AND if any problems arise other than the 
	  compositeError bit being set (which is ignored) then just bitch and return NIL -- NOTE does not wait for command 
	  completion -- NOTE acts as though CERROK? were set)


    (PROG ((COMMAND 2))
          (if (NOT (PCDAC.STOP T ERRORHANDLING? "to read the error register"))
	      then (GO FAIL))
          (PCDAC.WRITECOMMAND COMMAND)
          (PCDAC.BOARD:pcdLASTCOMMAND←COMMAND)
          (RETURN (LOGOR (if (NOT (PCDAC.READYFORREAD T ERRORHANDLING?))
			     then (GO FAIL)
			   else (PCDAC.READDATABYTE))
			 (LLSH (if (NOT (PCDAC.READYFORREAD T ERRORHANDLING?))
				   then (GO FAIL)
				 else (PCDAC.READDATABYTE))
			       8)))
      FAIL(if NOT (PCDAC.BOARD:pcdQUIETERRORS)
	      then (printout T "PCDAC.READERROR giving up" T))
          (RETURN NIL])
)
(* * internal -- lowest-level register-access functions)

(DEFINEQ

(PCDAC.READSTATUS
  [LAMBDA NIL                                                (* ht: "16-Sep-85 11:02")
    (PCBUS.INPUT PCDAC.BOARD:pcdIOADDRESS+1])

(PCDAC.WRITECOMMAND
  [LAMBDA (COMMAND)                                          (* ht: "16-Sep-85 11:02")
    (PCBUS.OUTPUT PCDAC.BOARD:pcdIOADDRESS+1 COMMAND])

(PCDAC.READDATABYTE
  [LAMBDA NIL                                                (* ht: "16-Sep-85 11:02")
    (PCBUS.INPUT PCDAC.BOARD:pcdIOADDRESS])

(PCDAC.WRITEDATABYTE
  [LAMBDA (DATUM)                                            (* ht: "16-Sep-85 11:02")
    (PCBUS.OUTPUT PCDAC.BOARD:pcdIOADDRESS DATUM])
)
(* * internal -- error analysis)

(DEFINEQ

(PCDAC.CHECKEDSTATUS
  [LAMBDA (CERROROK? ERRORHANDLING?)                         (* jmh "14-Nov-84 17:38")

          (* * read and return status register -- BUT if unused bits set or (compositeError bit set and not CERROROK?) then 
	  call PCDAC.SHOWSTATUS (and retry))



          (* * BUT IF ERRORHANDLING? -- after PCDAC.SHOWSTATUS immediately return NIL)


    (bind STATUS
       do (SETQ STATUS (PCDAC.READSTATUS))
	  (if (BITTEST STATUS PCDACSTATUS.NOTUSED)
	      then (PCDAC.SHOWSTATUS STATUS T ERRORHANDLING?)
		   (if ERRORHANDLING?
		       then (RETURN NIL))
	    elseif (AND (BITTEST STATUS PCDACSTATUS.COMPOSITEERROR)
			(NOT CERROROK?))
	      then (PCDAC.SHOWSTATUS STATUS "CompositeError bit set" ERRORHANDLING?)
		   (if ERRORHANDLING?
		       then (RETURN NIL))
	    else (RETURN STATUS])

(PCDAC.SHOWASTATUS
  [LAMBDA (STATUS)                                           (* jmh "15-Nov-84 12:13")
    (printout T "PCDAC status " .I3.8.T STATUS "q=" (PCDAC.STATUSASTEXT STATUS)
	      "=" T)
    (printout T ".." -3 (PCDAC.SHOWASTATUS.BITASSIGN STATUS PCDACSTATUS.COMPOSITEERROR)
	      "compositeError  "
	      (PCDAC.SHOWASTATUS.BITASSIGN STATUS PCDACSTATUS.COMMAND)
	      "Command" T)
    (printout T ".." -3 (PCDAC.SHOWASTATUS.BITASSIGN STATUS PCDACSTATUS.READY)
	      "Ready  "
	      (PCDAC.SHOWASTATUS.BITASSIGN STATUS PCDACSTATUS.DATAINFULL)
	      "dataInFull  "
	      (PCDAC.SHOWASTATUS.BITASSIGN STATUS PCDACSTATUS.DATAOUTREADY)
	      "dataOutReady" T)
    (if (BITTEST STATUS PCDACSTATUS.NOTUSED)
	then (printout T "!! Unused status bits set !!" T))
    (if (EQ STATUS 377Q)
	then (printout T "!! READING ALL-ONES !!" T])

(PCDAC.SHOWASTATUS.BITASSIGN
  [LAMBDA (STATUS MASK)                                      (* edited: "29-Sep-84 01:24")

          (* * internal to PCDAC.SHOWSTATUS)


    (if (BITTEST STATUS MASK)
	then "+"
      else "-"])

(PCDAC.SHOWSTATE
  [LAMBDA NIL                                                (* ht: "16-Sep-85 11:03")
    (printout T "last command: " (PCDAC.COMMANDASTEXT PCDAC.BOARD:pcdLASTCOMMAND)
	      T)
    (printout T "last worker command: " (PCDAC.COMMANDASTEXT PCDAC.BOARD:pcdLASTWORKERCMD)
	      T])

(PCDAC.SHOWANERROR
  [LAMBDA (ERROR)                                            (* ht: "16-Sep-85 11:14")

          (* * internal to PCDAC.SHOWERROR -- print messages describing the ERROR register and all the bits of it that are set
	  -- with special case to handle pcdSTOPFLAG -- see PCDAC.STOP about pcdSTOPFLAG)


    (PROG ((STOPFLAG (PCDAC.BOARD:pcdSTOPFLAG))
	   BITNR)
          (printout T "ERROR " .I6.8.T ERROR "q=" T)
          (if ERROR=65535
	      then (printout T ".. (READING ALL BITS AS ONES !?)" T)
	    else (for BITNR from 0 to 15 do (if (BITTEST ERROR (LLSH 1 BITNR))
						then (printout T (PCDAC.SHOWANERROR.BITASTEXT BITNR)
							       T)
						     (if (AND BITNR=1 STOPFLAG~=NIL)
							 then (printout T "..   (this is "
									(if STOPFLAG=T
									    then "probably"
									  else "possibly")
									
							      " from STOPping a running command)"
									T])

(PCDAC.SHOWANERROR.BITASTEXT
  [LAMBDA (BITNR)                                            (* edited: "17-Oct-84 17:45")
    (SELECTQ BITNR
	     (0 "err0: reserved")
	     (1 "err1: command issued while (noncontinuous) command in progress")
	     (2 "err2: attempt to set clock period to illegal value 0 or 1")
	     (3 "err4: attempt to select digital port other than 0..2")
	     (4 "err4: attempt to read digital port set for output or v.v.")
	     (5 "err5: attempt to select DAC other than 0,1,2")
	     (6 "err6: clock signal occurred before DAC ready")
	     (7 "err7: attempt to set D-A #conversions to illegal values 0,1,2")
	     (10Q "err8: attempt to select A-D channel other than 0..7 (s/e) or 0..15 (diff)")
	     (11Q "err9: attempt to set A-D gain other than 0..3")
	     (12Q "err10: clock signal occurred before A-D ready")
	     (13Q "err11: A-D mux error -- clocking too fast")
	     (14Q "err12: attempt to set A-D #conversions to illegal values 0,1,2")
	     (15Q "err13: data written to data register when command expected")
	     (16Q "err14: reserved")
	     (17Q "err15: reserved")
	     (SHOULDNT "bad BITNR"])
)
(* * internal -- utility)

(DEFINEQ

(PCDAC.DOCOMMAND
  [LAMBDA (COMMAND)                                          (* ht: "16-Sep-85 11:03")
    (PCDAC.READYFORCOMMAND)
    (PCDAC.WRITECOMMAND COMMAND)
    PCDAC.BOARD:pcdLASTCOMMAND←COMMAND
    PCDAC.BOARD:pcdLASTWORKERCMD←COMMAND])

(PCDAC.COMMANDASTEXT
  [LAMBDA (COMMAND)                                          (* jmh "14-Nov-84 13:26")

          (* * return a string which names the command and its modifier bits)


    (if (FIXP COMMAND)
	then (PROG (X)
	           (SETQ X (SELECTQ (LOGAND 15 COMMAND)
				    (0 "Reset")
				    (1 "ClrErr")
				    (2 "RdErr")
				    (3 "SetClk")
				    (4 "SelDigIn")
				    (5 "SelDigOut")
				    (6 "RdDigImm")
				    (7 "WrDigImm")
				    (8 "WrD/AImm")
				    (9 "SetD/APars")
				    (10 "WrD/A")
				    (11 "Test")
				    (12 "RdA/DImm")
				    (13 "SetA/DPars")
				    (14 "RdA/D")
				    (15 "Stop")
				    (SHOULDNT "noncommand")))
	           (if (BITTEST COMMAND 240)
		       then (SETQ X (CONCAT X "("))
			    (if (BITTEST COMMAND 16)
				then (SETQ X (CONCAT X "dma ")))
			    (if (BITTEST COMMAND 32)
				then (SETQ X (CONCAT X "cont ")))
			    (if (BITTEST COMMAND 64)
				then (SETQ X (CONCAT X "xClk ")))
			    (if (BITTEST COMMAND 128)
				then (SETQ X (CONCAT X "xTrg ")))
			    (SETQ X (RPLSTRING X -1 ")")))
	           (RETURN X))
      else COMMAND])

(PCDAC.STATUSASTEXT
  [LAMBDA (STATUS)                                           (* edited: "13-Oct-84 01:07")

          (* * return string explaining PCDAC status bits)


    (PROG ((STRING ""))
          (if (BITTEST STATUS PCDACSTATUS.COMPOSITEERROR)
	      then (SETQ STRING (CONCAT STRING "E")))
          (if (BITTEST STATUS PCDACSTATUS.NOTUSED)
	      then (SETQ STRING (CONCAT STRING "XXX")))
          (if (BITTEST STATUS PCDACSTATUS.COMMAND)
	      then (SETQ STRING (CONCAT STRING "C")))
          (if (BITTEST STATUS PCDACSTATUS.READY)
	      then (SETQ STRING (CONCAT STRING "R")))
          (if (BITTEST STATUS PCDACSTATUS.DATAINFULL)
	      then (SETQ STRING (CONCAT STRING "I")))
          (if (BITTEST STATUS PCDACSTATUS.DATAOUTREADY)
	      then (SETQ STRING (CONCAT STRING "O")))
          (RETURN STRING])

(PCDAC.YNQUERY
  [LAMBDA (TEXT)                                             (* edited: "15-Oct-84 14:45")

          (* * get an answer to a Y/N question)


    (PROG (ANSWER)
          [repeatuntil (OR (EQ ANSWER (QUOTE Y))
			   (EQ ANSWER (QUOTE N)))
	     do (printout T TEXT " (Y/N) ? ")
		(SETQ ANSWER (U-CASE (READ]
          (RETURN (EQ ANSWER (QUOTE Y])

(\PCDAC.DATAOFFSET
  [LAMBDA (board)                                            (* ht: "17-Sep-85 17:08")
    (if board:pcdBIPOLAR?
	then (SELECTQ board:pcdDATAFORMAT
		      (12XS 2048)
		      (16TC 0)
		      (SHOULDNT))
      else 0])

(\PCDAC.MFS
  [LAMBDA (board)                                            (* ht: "17-Sep-85 17:13")
    (if board:pcdBIPOLAR?
	then (SELECTQ board:pcdDATAFORMAT
		      (12XS -2048)
		      (16TC -32768)
		      (SHOULDNT))
      else 0])

(\PCDAC.PFS
  [LAMBDA (board)                                            (* ht: "17-Sep-85 17:15")
    (SELECTQ board:pcdDATAFORMAT
	     (12XS (if board:pcdBIPOLAR?
		       then 2048
		     else 4096))
	     (16TC 32768)
	     (SHOULDNT])
)
(DECLARE: DONTCOPY 
(DECLARE: EVAL@COMPILE 

(PUTPROPS PCDAC.WRITEBYTES&SYNC? MACRO [X (BQUOTE (PROGN .,
							 [MAPCONC X
								  (FUNCTION (LAMBDA (byteSpec)
								      (LIST '(PCDAC.READYFORWRITE)
									    (BQUOTE (
PCDAC.WRITEDATABYTE , byteSpec]
							 (if (fetch pcdSYNCHRONOUS? of PCDAC.BOARD)
							     then (PCDAC.READYFORCOMMAND])
)
)
(* * Checkout)

(DEFINEQ

(PCDAC.MAKETEST
  [LAMBDA NIL                                                (* ht: "16-Sep-85 15:01")
    (FILESLOAD (SYSLOAD)
	       TOGMENU)
    (LET ((mw (CREATEW NIL "PC D/A-A/D Test Window")))
      (DSPSCROLL 'ON
		 mw)
      (WINDOWPROP mw 'ICON
		  PCDACIcon)
      (WINDOWPROP mw 'PCDACMenus
		  (NCONC (bind tm tw ttw for tms in PCDACTestTogMenuSpecs1
			    collect (ttw←(TogMenu tm←(MakeTogMenu tms::1)
						  tms:1 NIL 0 0 T))
				    (WINDOWPROP ttw 'MINSIZE
						(FUNCTION \PcdDontMove))
				    (WINDOWPROP ttw 'MAXSIZE
						(FUNCTION \PcdDontMove))
				    (if tw
					then (ATTACHWINDOW ttw tw 'BOTTOM
							   'RIGHT)

          (* * following is a kludge to avoid bug in reshaping chains of fixed size windows -
	  it is really only important on the first window in each column of menus)


					     (WINDOWPROP tw 'DOSHAPEFN
							 (FUNCTION \PcdFakeIt1))
				      else (ATTACHWINDOW ttw mw 'LEFT
							 'TOP))
				    (tw←ttw)
				    (REDISPLAYW ttw)
				    tm)
			 (bind tm tw ttw for tms in PCDACTestTogMenuSpecs2
			    collect (ttw←(TogMenu tm←(MakeTogMenu tms::1)
						  tms:1 NIL 0 0 T))
				    (WINDOWPROP ttw 'MINSIZE
						(FUNCTION \PcdDontMove))
				    (WINDOWPROP ttw 'MAXSIZE
						(FUNCTION \PcdDontMove))
				    (if tw
					then (ATTACHWINDOW ttw tw 'BOTTOM
							   'LEFT)

          (* * following is a kludge to avoid bug in reshaping chains of fixed size windows -
	  it is really only important on the first window in each column of menus)


					     (WINDOWPROP tw 'DOSHAPEFN
							 (FUNCTION \PcdFakeIt2))
				      else (ATTACHWINDOW ttw mw 'RIGHT
							 'TOP))
				    (tw←ttw)
				    (REDISPLAYW ttw)
				    tm)))
      (LET ((pw (CREATEW '(0 0 75 10)
			 NIL NIL T)))
	(ATTACHWINDOW pw mw 'TOP
		      'RIGHT)
	(WINDOWPROP pw 'MAXSIZE
		    (CONS 0 0))
	(WINDOWPROP pw 'MINSIZE
		    (CONS 0 0))
	(DSPFONT '(GACHA 8)
		 pw)
	(DSPSCROLL T pw)
	(WINDOWPROP pw 'PAGEFULLFN
		    'NILL)
	(WINDOWPROP pw 'RESHAPEFN
		    (FUNCTION CLOSEW))
	(WINDOWADDPROP pw 'OPENFN
		       '[LAMBDA (w)
				(COND ((EQ [LET [(pos (STKPOS 'TOTOPW]
						(if pos then (PROG1 (STKNAME (STKNTH -1 pos pos))
								    (RELSTK pos]
					   'TOPATTACHEDWINDOWS)
				       (CLOSEW w]
		       T)
	[WINDOWADDPROP mw 'EXPANDFN
		       '[LAMBDA (w)
				(CLOSEW (CAR (WINDOWPROP WINDOW 'PromptWindow]]

          (* * the reason I do this myself instead of using GETPROMPTWINDOW exclusively is to get the position and width as I 
	  want them)


	(WINDOWPROP mw 'PromptWindow
		    (CONS pw 0))
	pw)
      (WINDOWPROP mw 'BUTTONEVENTFN
		  (FUNCTION PCDACTestWindowButtonFn))
      mw])

(PCDAC.TEST
  [LAMBDA (quietFlg)                                         (* ht: "17-Sep-85 14:46")

          (* * Issue and check the board%'s Test command)


    (PCDAC.DOCOMMAND 11)
    (if (AND (if (BITTEST (PCDAC.CHECKEDSTATUS)
			  PCDACSTATUS.DATAOUTREADY)
	       else (printout T "PCDAC Test command failed to set dataOutReady" T)
		    NIL)
	     (bind byte for i from 1 to 50
		do (PCDAC.ERROR?)
		   (if (NEQ (SETQ byte (PCDAC.READDATABYTE))
			    i)
		       then (printout T "PCDAC Test command failed with value " byte " when " i 
				      " was expected."
				      T)
			    (RETURN))
		finally (RETURN T)))
	then (PCDAC.STOP T)
	     (PCDAC.CLEARERROR T)
	     (if (NOT quietFlg)
		 then (printout T "PCDAC Test command OK" T))
	     T])

(LevelOut
  [LAMBDA (window channel level)                             (* ht: "17-Sep-85 17:05")
    (PCDAC.STOP)
    (PCDAC.WRITED/AIMMEDIATE channel (\PCDAC.DATAOFFSET PCDAC.BOARD)+level NIL NIL])

(PlayBack
  [LAMBDA (window channel sampleRate dontXfer)               (* ht: "16-Sep-85 10:33")
    (PCDAC.STOP)
    (BUSDMA.INIT)
    (PCDAC.SETCLOCK sampleRate T)
    (PCBUS.WRITEARRAY \SSDataArray 0 32768 'SWAP
		      \PCDACTestBufferStart T)
    (PCDAC.SETUPDMA 1 0 32768 NIL T)
    (PCDAC.SETD/APARAMETERS channel)
    (PCDAC.STARTWRITED/A T T])

(\MakeSinInArray
  [LAMBDA (array ampl sampleRate freq nWaves offset)         (* ht: "15-Aug-85 15:21")
    (LET ((period (QUOTIENT sampleRate freq))
       (twoPi 6.283184))
      (bind pv for i from 0 to (SUB1 period)
	 do [SETQ pv (IPLUS offset (FTIMES ampl (SIN (FQUOTIENT (FTIMES twoPi i)
								period)
						     T]
	    (for j from 0 to (SUB1 (OR nWaves 1)) do (SETA array (IPLUS i (ITIMES j period))
							   pv)))
      (ITIMES period (OR nWaves 1])

(PlayTone
  [LAMBDA (window channel sampleRate ampl offset freq)       (* ht: "17-Sep-85 17:06")
    (PCDAC.STOP)
    (BUSDMA.INIT)
    (PCDAC.SETCLOCK sampleRate T)
    (LET [(length (\MakeSinInArray \SSDataArray ampl sampleRate freq 2 (IPLUS offset (
										\PCDAC.DATAOFFSET
										PCDAC.BOARD]
      (PCBUS.WRITEARRAY \SSDataArray 0 length 'SWAP
			0)
      (PCDAC.SETUPDMA 1 0 length NIL T)
      (PCDAC.SETD/APARAMETERS channel)
      (PCDAC.STARTWRITED/A T T])

(PCDACTestRead
  [LAMBDA (msg)                                              (* ht: " 9-Sep-85 11:58")
    (LET ((pw (WINDOWPROP (MAINWINDOW $$TogWindow$$ T)
			  'PromptWindow))
       r v width)
      [SETQ width (PLUS 35 (STRINGWIDTH msg (DSPFONT NIL (CAR pw]
      [SETQ r (APPEND (WINDOWPROP (CAR pw)
				  'REGION]
      (replace LEFT of r with (PLUS (fetch LEFT of r)
				    (DIFFERENCE (fetch WIDTH of r)
						width)))
      (replace WIDTH of r with width)
      [replace HEIGHT of r with (HEIGHTIFWINDOW (MINUS (DSPLINEFEED NIL (CAR pw]
      (RPLACD pw 1)
      (SHAPEW (CAR pw)
	      r)
      (DSPRESET (CAR pw))
      [SETQ v (NLSETQ (RESETLST (RESETSAVE (TTYDISPLAYSTREAM (CAR pw)))
				(RESETSAVE (TTY.PROCESS (THIS.PROCESS)))
				(printout T msg)
				(CLEARBUF T T)
				(READ T]
      (CLOSEW (CAR pw))
      (if v
	  then v:1])

(DigitalScope
  [LAMBDA (window channel sampleRate gain compression maxAmpl midpoint displayEvery)
                                                             (* ht: "17-Sep-85 17:06")
    (RESETLST (RESETSAVE (RECLAIMMIN MAX.SMALLP))
	      (PROG ((vTextWidth (STRINGWIDTH "-2048" (DSPFONT NIL window)))
		     (hTextHeight (FONTPROP (DSPFONT NIL window)
					    'HEIGHT))
		     (midChar ((FONTPROP (DSPFONT NIL window)
					 'ASCENT)/2))
		     (array \SSDataArray)
		     old reg base left height dataWidth dataSize sliceWidth arraySize nSlices 
		     rightEdge correctWidth file sliceSize xferSize estLength nPages device)
		    (reg←(DSPCLIPPINGREGION NIL window))
		    (old←(ATTACHEDWINDOWREGION window))
		    (base←hTextHeight+ScopeHTickHeight)
		    (left←vTextWidth+ScopeVTickWidth)
		    (height←((WINDOWPROP window 'HEIGHT)
		       -(base+midChar))/2)
		    (dataWidth←(WINDOWPROP window 'WIDTH)
		      -left)
		    (CLEARW window)
		    (dataSize←compression*dataWidth)
		    (arraySize←32768)

          (* * the following are derived from disEvery=rPP*sliceWidth + fPP*disEv*sampleRate/1000)


		LP  [while displayEvery=NIL
		       do 

          (* * as fast as possible given the width of the window)



          (* * displayEvery = rPP*sliceWidth*1000/ (1000-fPP*samp))


			  (displayEvery←(FIX (FQUOTIENT 1000.0*1.0*dataWidth 1000.0-.0055*sampleRate))
			    )

          (* * this test is not really right -
	  clearly one can%'t stand to fill the entire buffer -
	  there would then be no time to get it out before being stepped on. But doing better would require a dicey 
	  calculation of how likely we are to be stepped on given the sample rate and the buffer size...)


			  (if (IGREATERP (FIX (FTIMES displayEvery sampleRate)/1000.0)
					 arraySize)
			      then displayEvery←(FIX (FQUOTIENT arraySize*1000.0 sampleRate]

          (* * sliceWidth = number of points we can repaint = disEvery/rPP * (1 -
	  fPP*samp/1000))


		    [sliceWidth←(IMIN dataWidth (FIX (1.0-.0055*sampleRate/1000.0)*displayEvery/1.0)
				      (FIX (FQUOTIENT (FTIMES displayEvery sampleRate)/1000.0 
						      compression]
		    (sliceSize←sliceWidth*compression)
		    (if (IGREATERP xferSize←(FIX (FTIMES displayEvery sampleRate)/1000.0)
				   arraySize)
			then (HELP "too long"))

          (* * make sure there are an integral number of slices in the window)


		    (correctWidth←sliceWidth*(nSlices←dataWidth/sliceWidth))
		    (rightEdge←correctWidth+left)
		    [if (NOT (IEQP dataWidth correctWidth))
			then (SHAPEW window
				     (create REGION
					     LEFT ← old:LEFT
					     BOTTOM ← old:BOTTOM
					     HEIGHT ← old:HEIGHT
					     WIDTH ←(old:WIDTH-(dataWidth-correctWidth]
		    (MOVETO 0 base-midChar window)
		    (printout window .I5 (midpoint-maxAmpl))
		    (MOVETO 0 height+(base-midChar)
			    window)
		    (printout window .I5 midpoint)
		    (MOVETO 0 height+height+(base-midChar)
			    window)
		    (printout window .I5 (midpoint+maxAmpl))
		    (MOVETO left base window)
		    (RELDRAWTO (-ScopeVTickWidth)
			       0 1 NIL window)
		    (MOVETO left base+height window)
		    (RELDRAWTO (-ScopeVTickWidth)
			       0 1 NIL window)
		    (MOVETO left base+height+height window)
		    (RELDRAWTO (-ScopeVTickWidth)
			       0 1 NIL window)
		    (bind index for del from 0 to correctWidth by (SELECTQ sampleRate
									   (27000 27)
									   20)
		       do (MOVETO left+del base window)
			  (RELDRAWTO 0 (-ScopeHTickHeight)
				     1 NIL window)
			  (if (IMOD del (SELECTQ sampleRate
						 (27000 135)
						 100))=0
			      then index←1000*del*compression/sampleRate
				   (MOVETO left+del+(-((STRINGWIDTH index (DSPFONT NIL window))/2))
					   base+(-ScopeHTickHeight)+(DSPLINEFEED NIL window))
				   (PRIN3 index window)))
		    (PCDAC.STOP T)
		    (PCDAC.CLEARERROR)
		    (BUSDMA.INIT)

          (* * the CONSTANT is to fix a DWIMIFY bug)


		    (PCDAC.SETCLOCK sampleRate T)
		    (PCDAC.SETUPDMA 1 0 32768 T T)
		    (PCDAC.SETA/DPARAMETERS gain channel)
		    (TOTOPW window)
		    (RECLAIM)
		    (MOVETO left base+height window)
		    (printout T "Use STOP key or any mouse button to stop:")
		    (PCDAC.STARTREADA/D T T)
		    (ADD.PROCESS (LIST 'ScopeInWindow
				       window xferSize sliceWidth sliceSize compression rightEdge 
				       height maxAmpl (\PCDAC.DATAOFFSET PCDAC.BOARD)+midpoint left 
				       base (DSPYOFFSET NIL window)+base+height height array)
				 'WINDOW
				 window])

(PCDACTestWindowButtonFn
  [LAMBDA (window)                                           (* ht: "19-Jun-85 14:15")
    (DECLARE (SPECVARS window))
    (TOTOPW window)
    (MENU (OR PCDACTestMenu PCDACTestMenu←(create MENU
						  ITEMS ← PCDACTestMenuItems])

(DoPCDACTest
  [LAMBDA (fn window argIndices)                             (* ht: "19-Jun-85 14:38")
    (RESETFORM (TTYDISPLAYSTREAM window)
	       (APPLY fn (CONS window (bind (menus ←(WINDOWPROP window 'PCDACMenus)) for i
					 in argIndices collect (TogMenuValue (CAR (NTH menus i])

(ScopeInWindow
  [LAMBDA (window xferSize sliceWidth sliceSize compression rightEdge scaleNum scaleDenom offset 
		  leftMargin bottomMargin base height array)
                                                             (* ht: "16-Sep-85 15:40")
    (bind (nextBufEnd ← xferSize)
	  (lastArrayPtr ← 0)
	  (redisplayRegion ←(APPEND (DSPCLIPPINGREGION NIL window)))
	  (stream ←(WINDOWPROP window 'DSP))
	  (arrayBase ←(ARRAYBASE array))
	  (arraySize ←(ARRAYSIZE array))
	  (lastAddress ← 32768)
	  (dmaChannel ←(fetch pcdDMACHANNEL of PCDAC.BOARD))
	  bottom destBM top lastBufEnd currentAddress wrapped dispPos truePos left right y
       first (TTYDISPLAYSTREAM window)
	     (replace LEFT of redisplayRegion with leftMargin)
	     (replace WIDTH of redisplayRegion with sliceWidth)
	     (add (fetch BOTTOM of redisplayRegion)
		  bottomMargin)
	     (replace HEIGHT of redisplayRegion with (IDIFFERENCE (fetch HEIGHT of redisplayRegion)
								  bottomMargin))
	     [SETQ bottom (IMAX 0 (IPLUS (fetch BOTTOM of redisplayRegion)
					 (DSPYOFFSET NIL stream]
	     (SETQ destBM (DSPDESTINATION NIL stream))
	     [SETQ top (IMIN (SUB1 SCREENHEIGHT)
			     (IPLUS bottom (fetch HEIGHT of redisplayRegion]
       until (OR (MOUSESTATE (NOT UP))
		 (KEYDOWNP 'STOP))
       do                                                    (* (PCDAC.ERROR?))

          (* * Get the current location of the dma transfer, in words. Open coded for speed)


	  (if (BUSDMA.FASTUPDATEADDR dmaChannel currentAddress wrapped)
	      then (add currentAddress 32768))
	  (if (OR (EQ wrapped 'DoubleWrap)
		  (IGREATERP (IPLUS currentAddress currentAddress (IMINUS lastAddress)
				    -32768)
			     nextBufEnd))
	      then                                           (* falling behind -
							     punt)
		   (FLASHWINDOW window)
		   (SETQ nextBufEnd currentAddress)
		   (SETQ wrapped NIL)
	    elseif (ILESSP currentAddress nextBufEnd)
	      then (GO $$LP))
	  (SETQ lastAddress currentAddress)
	  (if (GREATERP nextBufEnd 32768)
	      then                                           (* slice lies across buffer end)
		   (SETQ wrapped NIL)
		   (SETQ nextBufEnd (IDIFFERENCE nextBufEnd 32768)))
	  (if (MINUSP (SETQ lastBufEnd (IDIFFERENCE nextBufEnd xferSize)))
	      then (PCBUS.READARRAY array (IPLUS 32768 lastBufEnd)
				    (IMINUS lastBufEnd)
				    'SWAP
				    lastArrayPtr T)
		   (PCBUS.READARRAY array 0 nextBufEnd 'SWAP
				    (IMOD (IDIFFERENCE lastArrayPtr lastBufEnd)
					  arraySize)
				    T)
	    else (PCBUS.READARRAY array lastBufEnd xferSize 'SWAP
				  lastArrayPtr T))

          (* * Dont call redisplayw, because it does a resetvars which burns conses which we can%'t afford)


	  (DSPFILL redisplayRegion NIL NIL stream)
	  (SETQ dispPos (IPLUS (fetch LEFT of redisplayRegion)
			       (DSPXOFFSET NIL stream)))
	  (SETQ truePos (IMOD (IDIFFERENCE (IPLUS lastArrayPtr xferSize)
					   sliceSize)
			      arraySize))
	  [SETQ left (IMAX 0 (IPLUS (fetch LEFT of redisplayRegion)
				    (DSPXOFFSET NIL stream]
	  [SETQ right (IMIN (SUB1 SCREENWIDTH)
			    (IPLUS left (fetch WIDTH of redisplayRegion]
	  (SETQ y (IPLUS (IQUOTIENT (ITIMES scaleNum (IDIFFERENCE (ELT array (MAX (IDIFFERENCE 
											  truePos 
										      compression)
										  0))
								  offset))
				    scaleDenom)
			 base))
	  [for i from 1 to (fetch WIDTH of redisplayRegion)
	     do (\CLIPANDDRAWLINE1 (SUB1 dispPos)
				   y dispPos (SETQ y (IPLUS (IQUOTIENT (ITIMES scaleNum
									       (IDIFFERENCE
										 (\GETBASE arrayBase 
											  truePos)
										 offset))
								       scaleDenom)
							    base))
				   'REPLACE
				   destBM left right bottom top stream)
		(add dispPos 1)
		(if (IGEQ (add truePos compression)
			  arraySize)
		    then (SETQ truePos (IDIFFERENCE truePos arraySize]
	  (if (IGEQ (add lastArrayPtr xferSize)
		    arraySize)
	      then (SETQ lastArrayPtr (IDIFFERENCE lastArrayPtr arraySize)))
	  (add nextBufEnd xferSize)
	  (if (EQ (add (fetch LEFT of redisplayRegion)
		       sliceWidth)
		  rightEdge)
	      then (replace LEFT of redisplayRegion with leftMargin))
       finally (PCDAC.STOP)
	       (PCDAC.CLEARERROR)
	       (SETQ \PCDACTestBufferStart lastArrayPtr])
)
(* * hacks because of non-feature in ATTACHWINDOWS)

(DEFINEQ

(\PcdDontMove
  [LAMBDA (w)                                                (* ht: "19-Jun-85 15:41")
    (CONS (fetch WIDTH of (WINDOWPROP w 'REGION))
	  (fetch HEIGHT of (WINDOWPROP w 'REGION])

(\PcdFakeIt1
  [LAMBDA (w r)                                              (* edited: "15-Aug-85 13:34")
    (LET [(wr (WINDOWPROP w 'REGION]
      (MOVEW w r:RIGHT+1+(-wr:WIDTH)
	     r:TOP+1+(-wr:HEIGHT])

(\PcdFakeIt2
  [LAMBDA (w r)                                              (* edited: "15-Aug-85 13:34")
    (LET [(wr (WINDOWPROP w 'REGION]
      (MOVEW w r:LEFT r:TOP+1+(-wr:HEIGHT])
)

(RPAQQ PCDACTestMenu NIL)

(RPAQQ ScopeHTickHeight 5)

(RPAQQ ScopeVTickWidth 5)

(RPAQQ \PCDACTestBufferStart NIL)

(RPAQQ PCDACTestMenuItems ((Scope (DoPCDACTest 'DigitalScope
					       window
					       '(1 3 4 6 7 8 9))
				  "Display a digital oscilliscope trace")
			   ("Level Out" (DoPCDACTest 'LevelOut
						     window
						     '(2 5))
					"Put the designated level value on the given output channel")
			   (Reset (DoPCDACTest 'PCDAC.HARDRESET
					       window NIL)
				  "Reset the PC")
			   ("Playback" (DoPCDACTest 'PlayBack
						    window
						    '(2 3))
				       "Play back the most recently collected buffer")
			   ("Play Tone" (DoPCDACTest 'PlayTone
						     window
						     '(2 3 7 8 10))
					"Play a continuous pure tone")
			   (Quiet (DoPCDACTest (FUNCTION [LAMBDA (w)
								 (PCDAC.STOP])
					       window NIL)
				  "Stop whatever is playing")
			   (Checkout (DoPCDACTest [FUNCTION (LAMBDA (w)
								    (CLEARW window)
								    (AND (PC.CHECKOUT)
									 (PCDAC.RESET)
									 (PCDAC.TEST]
						  window NIL)
				     "Run the preliminary checkout test")))

(RPAQQ PCDACTestTogMenuSpecs1 (("Input Channel" 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)
	("Output Channel" 1 0 (Both 2))
	("Sample Rate" (27K 27000)
		       (10K 10000)
		       (5K 5000)
		       ((TogMenuValue)
			(PCDACTestRead "Sample rate: ")
			NIL "Will prompt and read" Other))
	("Input Gain" (1 0)
		      (2 1)
		      (4 2)
		      (8 3))))

(RPAQQ PCDACTestTogMenuSpecs2 (("Level Datum" (PFS-1 (DIFFERENCE (\PCDAC.PFS PCDAC.BOARD)
								 1))
					      (PFS-2 (DIFFERENCE (\PCDAC.PFS PCDAC.BOARD)
								 2))
					      0
					      (MFS+1 (ADD1 (\PCDAC.MFS PCDAC.BOARD)))
					      (MFS (\PCDAC.MFS PCDAC.BOARD))
					      ((TogMenuValue)
					       (PCDACTestRead "Level value: ")
					       NIL "Will prompt and read" Other))
			       ("Time Compression" 1 2 10 30 ((TogMenuValue)
						    (PCDACTestRead "Compression ratio: ")
						    NIL "Will prompt and read" Other))
			       ("Max Amplitude" 1000 (PFS (\PCDAC.PFS PCDAC.BOARD))
						2 10 ((TogMenuValue)
						 (PCDACTestRead "Max Amplitude: ")
						 NIL "Will prompt and read" Other))
			       ("Midpoint" 0 (PFS-2 (DIFFERENCE (\PCDAC.PFS PCDAC.BOARD)
								2))
					   (MFS+1 (ADD1 (\PCDAC.MFS PCDAC.BOARD)))
					   ((TogMenuValue)
					    (PCDACTestRead "Midpoint value: ")
					    NIL "Will prompt and read" Other))
			       ("Display Every" 100 500 1000 (AFAP (NILL)
								   NIL "As fast as possible")
						((TogMenuValue)
						 (PCDACTestRead "Display every (msec): ")
						 NIL "Will prompt and read" Other))
			       (Frequency 440 880 60 ((TogMenuValue)
					   (PCDACTestRead "Frequency (Hertz): ")
					   NIL "Will prompt and read" Other))))

(RPAQ PCDACIcon (READBITMAP))
(64 64
"OOOOOOOOOOOOOOOO"
"OOOOOOOOOOOOOOOO"
"LBBBBBBBBBBBBB@C"
"LBBBBBBNCOOOOOHC"
"L@HHHHHLKOOOOOHC"
"L@HLIHHLKOOOOOHC"
"LBBNCJBNCOOOOOHC"
"LBBNCJBNCOOOOOHC"
"L@HLIHHLKOOOOOHC"
"L@HNKHHLKOOOOOHC"
"LBBOOJBNCOOOOOHC"
"LBBGOBBNCOOOOOHC"
"L@HKNHHLHHIOHHHC"
"L@HILHHLHHIOHHHC"
"LBBCNBBNBBCOBB@C"
"LBBCNBBNBBCOJB@C"
"L@HKLHHLHHIOHHHC"
"L@HILHHLHHIOHHHC"
"LBBCNBBNBBCOBB@C"
"LBBCNBBNBBCOBB@C"
"L@HILHHLHHIOHHHC"
"L@HILHHLHHIOHHHC"
"LBBCNBBNBBCOBB@C"
"LBBCNBBNBBCOBB@C"
"L@HILHHLHHIOHHHC"
"L@HILHHLHHIOHHHC"
"LBBCNBBNBBCOBB@C"
"LBBCNBBNBBCOBB@C"
"L@HILHHLHHIOHHHC"
"L@HILHHLHHIOHHHC"
"LBBCNBBNBBCOBB@C"
"LBBCNBBNBBCOBB@C"
"L@HILHHLHHIOHHHC"
"L@HILHINHHIOHHHC"
"LBBCNBCOBBCOBB@C"
"LBBCNBGOJBCOBB@C"
"L@HILHOOHHIOHHHC"
"L@HILHOOHHIOHHHC"
"LBBCNBGOJBCOBB@C"
"LBBCNBGOJBCOBB@C"
"L@HILHOOHHIOHHHC"
"L@HKNHOOHHIOHHHC"
"LBBCOBGOJBCOBB@C"
"LBBOOJGOJBCOBB@C"
"L@HOOHOOHHIOHHHC"
"L@HNKHOOHHIOHHHC"
"LBBNCJGOJBCOBB@C"
"LBBNCJGOJBCOBB@C"
"L@HLIHKOHHIOHHHC"
"L@HLIHINHHHHHHHC"
"L@@@@@@@@@@@@@@C"
"L@@@@@@@@@@@@@@C"
"L@@@@@@@@@@@@@@C"
"L@@@@@@@@@@@@@@C"
"L@@@O@OCLA@GH@@C"
"L@@@HI@JBBHHD@@C"
"L@@@HI@BBBHH@@@C"
"L@@@OA@BBDDH@@@C"
"L@@@HA@JBGLHD@@C"
"L@@@H@OCLHBGH@@C"
"L@@@@@@@@@@@@@@C"
"L@@@@@@@@@@@@@@C"
"L@@@@@@@@@@@@@@C"
"OOOOOOOOOOOOOOOO")

(RPAQ? \SSDataArray (ARRAY 32768 'WORD
			   0 0 128))
(DECLARE: DOCOPY 
(DECLARE: DONTEVAL@LOAD EVAL@COMPILE 

(ADDTOVAR NOFIXFNSLST PCDAC.READA/DIMMEDIATE PCDAC.SETA/DPARAMETERS PCDAC.STARTREADA/D 
					     PCDAC.READA/DDATUM PCDAC.WRITED/AIMMEDIATE 
					     PCDAC.SETD/APARAMETERS PCDAC.STARTWRITED/A 
					     PCDAC.WRITED/ADATUM)
)
)
(DECLARE: DONTCOPY DONTEVAL@LOAD DOEVAL@COMPILE 
(RESETSAVE DWIMIFYCOMPFLG T)
(COND ([NOT (OR (GETP 'ARRAYBASE
		      'DMACRO)
		(GETP 'ARRAYBASE
		      'MACRO]
       (HELP "ARRAYBASE needed - load macro def'n from somewhere and/or RETURN")))

(DECLARE: DOEVAL@COMPILE DONTCOPY

(GLOBALVARS \PCDACTestBufferStart PCDAC.BOARD PCDACTestMenuItems PCDACTestTogMenuSpecs1 
	    PCDACTestTogMenuSpecs2 PCDACIcon PCDACTestMenu \SSDataArray)
)

(FILESLOAD (LOADCOMP)
	   BUSMASTER.DCOM)
)
(FILESLOAD (SYSLOAD)
	   BUSMASTER)
(PUTPROPS PCDAC COPYRIGHT ("Xerox Corporation" 1984 1985))
(DECLARE: DONTCOPY
  (FILEMAP (NIL (5752 7243 (PCDAC.SETCLOCK 5762 . 6362) (PCDAC.SETUPDMA 6364 . 7241)) (7270 9524 (
PCDAC.READA/DIMMEDIATE 7280 . 7715) (PCDAC.SETA/DPARAMETERS 7717 . 8768) (PCDAC.STARTREADA/D 8770 . 
9161) (PCDAC.READA/DDATUM 9163 . 9522)) (9551 11591 (PCDAC.WRITED/AIMMEDIATE 9561 . 10149) (
PCDAC.SETD/APARAMETERS 10151 . 10843) (PCDAC.STARTWRITED/A 10845 . 11237) (PCDAC.WRITED/ADATUM 11239
 . 11589)) (11622 14258 (PCDAC.SETDIGITALINPUT 11632 . 12243) (PCDAC.SETDIGITALOUTPUT 12245 . 12859) (
PCDAC.READDIGITALIMMEDIATE 12861 . 13600) (PCDAC.WRITEDIGITALIMMEDIATE 13602 . 14256)) (14277 20686 (
PCDAC.STOP 14287 . 17846) (PCDAC.CLEARERROR 17848 . 19205) (PCDAC.RESET 19207 . 20528) (
PCDAC.HARDRESET 20530 . 20684)) (20727 25258 (PCDAC.READYFORCOMMAND 20737 . 22022) (PCDAC.READYFORREAD
 22024 . 23626) (PCDAC.READYFORWRITE 23628 . 25256)) (25286 30924 (PCDAC.ERROR? 25296 . 25722) (
PCDAC.SHOWSTATUS 25724 . 29344) (PCDAC.SHOWERROR 29346 . 29689) (PCDAC.READERROR 29691 . 30922)) (
30988 31677 (PCDAC.READSTATUS 30998 . 31160) (PCDAC.WRITECOMMAND 31162 . 31339) (PCDAC.READDATABYTE 
31341 . 31503) (PCDAC.WRITEDATABYTE 31505 . 31675)) (31717 36323 (PCDAC.CHECKEDSTATUS 31727 . 32647) (
PCDAC.SHOWASTATUS 32649 . 33571) (PCDAC.SHOWASTATUS.BITASSIGN 33573 . 33825) (PCDAC.SHOWSTATE 33827 . 
34148) (PCDAC.SHOWANERROR 34150 . 35166) (PCDAC.SHOWANERROR.BITASTEXT 35168 . 36321)) (36356 40113 (
PCDAC.DOCOMMAND 36366 . 36632) (PCDAC.COMMANDASTEXT 36634 . 37902) (PCDAC.STATUSASTEXT 37904 . 38870) 
(PCDAC.YNQUERY 38872 . 39306) (\PCDAC.DATAOFFSET 39308 . 39574) (\PCDAC.MFS 39576 . 39841) (\PCDAC.PFS
 39843 . 40111)) (40545 57511 (PCDAC.MAKETEST 40555 . 43450) (PCDAC.TEST 43452 . 44341) (LevelOut 
44343 . 44561) (PlayBack 44563 . 44951) (\MakeSinInArray 44953 . 45518) (PlayTone 45520 . 46045) (
PCDACTestRead 46047 . 47104) (DigitalScope 47106 . 51998) (PCDACTestWindowButtonFn 52000 . 52287) (
DoPCDACTest 52289 . 52631) (ScopeInWindow 52633 . 57509)) (57570 58237 (\PcdDontMove 57580 . 57810) (
\PcdFakeIt1 57812 . 58033) (\PcdFakeIt2 58035 . 58235)))))
STOP