(FILECREATED " 4-Jan-86 13:03:11" {IVY}<HTHOMPSON>LISP>SP>PCDAC.;9 67635  

      changes to:  (FNS DigitalScope ScopeInWindow)
		   (MACROS PCDAC.WRITEBYTES&SYNC?)
		   (VARS PCDACCOMS)

      previous date: " 4-Jan-86 10:45:00" {IVY}<HTHOMPSON>LISP>SP>PCDAC.;7)


(* Copyright (c) 1984, 1985, 1986 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)
	      (\SmallTArray)
	      (\FloatTArray)
	      (\SArray)
	      (\SOArray)
	      (\PermArray)
	      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 {IVY}<HTHOMPSON>LISP>SP>RAW)
		  (MACROS \CheapFix))
	(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: " 4-Jan-86 13:02")
    (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←(FQUOTIENT 1000.0*.75*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 (FTIMES displayEvery sampleRate)/1000.0 
						   arraySize)
				    then displayEvery←(FQUOTIENT arraySize*1000.0 sampleRate)))

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


		        [sliceWidth←(IMIN dataWidth (FIX (FQUOTIENT (1.0-.0055*sampleRate/1000.0
									    )*displayEvery .75))
					    (FIX (FQUOTIENT (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]
		        (RESETSAVE (DSPRIGHTMARGIN MAX.SMALLP window)
				     (LIST 'DSPRIGHTMARGIN
					     (DSPRIGHTMARGIN NIL window)
					     window))
		        (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:")
		        (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: " 4-Jan-86 13:02")
    (DECLARE (LOCALVARS . T)
	       (GLOBALVARS \LASTKEYSTATE \SmallTArray \FloatTArray \SArray \SOArray \PermArray))
    (bind (nextBufEnd ← xferSize)
	    (lastArrayPtr ← 0)
	    (redisplayRegion ←(APPEND (DSPCLIPPINGREGION NIL window)))
	    (stream ←(WINDOWPROP window 'DSP))
	    (arraySize ←(ARRAYSIZE array))
	    (lastAddress ← 32768)
	    (dmaChannel ←(fetch pcdDMACHANNEL of PCDAC.BOARD))
	    (scale ←(FQUOTIENT scaleNum scaleDenom))
	    bottom destBM top lastBufEnd currentAddress wrapped firstPart dispPos truePos left right 
	    y scopeTimes scaledOffset arrayBase
       first (TTYDISPLAYSTREAM window)
	       (scaledOffset←(FDIFFERENCE base (FTIMES scale offset)))
	       (if (NOT (ARRAYP \SmallTArray))
		   then \SmallTArray←(ARRAY SCREENWIDTH 'SMALLP
						NIL 0))
	       (if (NOT (ARRAYP \FloatTArray))
		   then \FloatTArray←(ARRAY SCREENWIDTH 'FLOATP
						NIL 0))
	       (arrayBase←(ARRAYBASE \FloatTArray))
	       (if (NOT (ARRAYP \SArray))
		   then \SArray←(ARRAY SCREENWIDTH 'FLOATP
					   scale 0)
		 elseif (NOT (EQP (ELT \SArray 0)
					scale))
		   then (for i from 0 to SCREENWIDTH-1 do (SETA \SArray i scale)))
	       (if (NOT (ARRAYP \SOArray))
		   then \SOArray←(ARRAY SCREENWIDTH 'FLOATP
					    scaledOffset 0)
		 elseif (NOT (EQP (ELT \SOArray 0)
					scaledOffset))
		   then (for i from 0 to SCREENWIDTH-1 do (SETA \SOArray i scaledOffset)))
	       (if (NOT (ARRAYP \PermArray))
		   then \PermArray←(ARRAY SCREENWIDTH 'SMALLP
					      NIL 0))
	       (if (NOT (EQP (ELT \PermArray 1)
				   compression))
		   then (for i from 0 to SCREENWIDTH-1 as j from 0 by compression
			     do (SETA \PermArray i j)))
	       (redisplayRegion:LEFT←leftMargin)
	       (redisplayRegion:WIDTH←sliceWidth)
	       (add redisplayRegion:BOTTOM bottomMargin)
	       (redisplayRegion:HEIGHT←(IDIFFERENCE redisplayRegion:HEIGHT bottomMargin))
	       [bottom←(IMAX 0 (IPLUS redisplayRegion:BOTTOM (DSPYOFFSET NIL stream]
	       (destBM←(DSPDESTINATION NIL stream))
	       (top←(IMIN (IPLUS SCREENHEIGHT -1)
			    (IPLUS bottom redisplayRegion:HEIGHT)))
	       (PCDAC.STARTREADA/D T T)
       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))

          (* * the IGREATERP check is actually on currentAddress+currentAddress-lastAddress-32768, but the computation is 
	  done in the way it actually is to avoid building any boxes)


	    (if (OR wrapped= 'DoubleWrap
			(IGREATERP (IPLUS (IDIFFERENCE currentAddress lastAddress)
					      (IDIFFERENCE currentAddress 32768))
				     nextBufEnd))
		then                                       (* falling behind -
							     punt)
		       (FLASHWINDOW window)
		       (nextBufEnd←currentAddress)
		       (wrapped←NIL)
	      elseif (ILESSP currentAddress nextBufEnd)
		then (GO $$LP))
	    (lastAddress←currentAddress)
	    (if (GREATERP nextBufEnd 32768)
		then                                       (* slice lies across buffer end)
		       (wrapped←NIL)
		       (nextBufEnd←(IDIFFERENCE nextBufEnd 32768)))
	    (if (MINUSP 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)



          (* * (if \TimeScope then (push scopeTimes (CLOCK 2))))


	    (DSPFILL redisplayRegion NIL NIL stream)
	    (dispPos←(IPLUS redisplayRegion:LEFT (DSPXOFFSET NIL stream)))
	    (truePos←(IMOD (IDIFFERENCE (IPLUS lastArrayPtr xferSize)
					    sliceSize)
			     arraySize))
	    [left←(IMAX 0 (IPLUS redisplayRegion:LEFT (DSPXOFFSET NIL stream]
	    (right←(IMIN (IPLUS SCREENWIDTH -1)
			   (IPLUS left sliceWidth)))

          (* * first produce a dense smallp set of points)


	    (if (IGREATERP (ITIMES compression (IPLUS sliceWidth -1))
			       arraySize-truePos)
		then (\RawPermArray array truePos \PermArray 0 \SmallTArray 0 firstPart←(IPLUS
					  (IQUOTIENT arraySize-truePos compression)
					  1))
		       (\RawPermArray array (IDIFFERENCE (IPLUS truePos (ITIMES compression 
											firstPart))
							     arraySize)
					\PermArray 0 \SmallTArray firstPart (IDIFFERENCE sliceWidth 
											firstPart))
	      else (\RawPermArray array truePos \PermArray 0 \SmallTArray 0 sliceWidth))

          (* * float the points)


	    (\RawFloatArray \SmallTArray 0 \FloatTArray 0 sliceWidth) 

          (* * scale the points)


	    (\RawFTimesArrays \FloatTArray 0 \SArray 0 \FloatTArray 0 sliceWidth) 

          (* * add in the scaled offset and base (base-scale*offset))


	    (\RawFPlusArrays \FloatTArray 0 \SOArray 0 \FloatTArray 0 sliceWidth)
	    (y←(\CheapFix arrayBase))
	    (for i from 2 to (LLSH (IPLUS sliceWidth -1)
					   1)
	       by 2
	       do (\CLIPANDDRAWLINE1 dispPos y (IPLUS dispPos 1)
					 y←(\CheapFix (\ADDBASE arrayBase i))
					 'REPLACE
					 destBM left right bottom top stream)
		    (add dispPos 1))

          (* * (if \TimeScope then (push scopeTimes (CLOCK 2))))


	    (if (IGEQ (add lastArrayPtr xferSize)
			  arraySize)
		then lastArrayPtr←(IDIFFERENCE lastArrayPtr arraySize))
	    (add nextBufEnd xferSize)
	    (if (add redisplayRegion:LEFT sliceWidth)=rightEdge
		then (redisplayRegion:LEFT←leftMargin))
       finally (PCDAC.STOP)
		 (PCDAC.CLEARERROR)
		 (\PCDACTestBufferStart←lastArrayPtr)
		 (if scopeTimes
		     then (LET ((n (LRSH (LENGTH scopeTimes)
					     1))
				  avTime)
			         (printout T T n " loops, average time " avTime←(FQUOTIENT
					     (for tp on scopeTimes by CDDR sum (IABS 
											tp:2-tp:1))
					     n)
					   ", time per point "
					   (FQUOTIENT avTime sliceWidth])
)
(* * 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 \SmallTArray NIL)

(RPAQQ \FloatTArray NIL)

(RPAQQ \SArray NIL)

(RPAQQ \SOArray NIL)

(RPAQQ \PermArray 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 {IVY}<HTHOMPSON>LISP>SP>RAW)

(DECLARE: EVAL@COMPILE 
[PUTPROPS \CheapFix MACRO ((expr)
	   (LET ((X expr))
		(* ht: " 3-Jan-86 11:06")
		(PROG ((SIGN (FETCHFIELD '(NIL 0 (BITS . 0))
					 X))
		       (LO (FETCHFIELD '(NIL 1 (BITS . 15))
				       X))
		       (HI (FETCHFIELD '(NIL 0 (BITS . 150))
				       X))
		       (EXP (FETCHFIELD '(NIL 0 (BITS . 23))
					X)))
		      (* * HTs hack of \FIXP.FROM.FLOATP - only works for SMALLP results)
		      (* Unpacks a floating point number X into its components. (GO RETZERO)
			 is evaluated if the number is true zero. The fraction is unpacked into HI 
			 and LO, with the binary point implicitly between bits 0 and 1 of HI. If NIL 
			 is true, the fraction is left in its original state, with 8 bits in HI and 
			 16 in LO. If X is not floating, it is coerced.)
		      [COND [(EQ 0 EXP)
			     (* zero or a de-normalized number from underflow)
			     (COND ((AND (EQ 0 HI)
					 (EQ 0 LO))
				    (* A zero, regardless of the sign bit zero)
				    (RETURN 0))
				   (T (* need bias adjust to account for lack of hidden bit)
				      (SETQ EXP 1]
			    ((NEQ EXP 255)
			     (* might want to check for NaN's here if EXP = \MAX.EXPONENT)
			     (* OR in the implicit high bit of fraction)
			     (SETQ HI (IPLUS HI 128]
		      (SETQ EXP (IDIFFERENCE EXP (SUB1 127)))
		      (* number of bits to left of binary point)
		      [COND ((ILESSP EXP 0)
			     (RETURN 0))
			    ((IGREATERP EXP 16)
			     (SETQ LO MAX.SMALLP))
			    [(IGEQ (SETQ EXP (IDIFFERENCE 24 EXP))
				   16)
			     (SETQ LO HI)
			     (FRPTQ (IDIFFERENCE EXP 16)
				    (SETQ LO (LRSH LO 1]
			    (T (SETQ LO (IPLUS (LLSH HI 8)
					       (LRSH LO 8)))
			       (FRPTQ (IDIFFERENCE EXP 8)
				      (SETQ LO (LRSH LO 1]
		      (RETURN (COND ((EQ SIGN 1)
				     (IMINUS LO))
				    (T LO]
)
)
(FILESLOAD (SYSLOAD)
	   BUSMASTER)
(PUTPROPS PCDAC COPYRIGHT ("Xerox Corporation" 1984 1985 1986))
(DECLARE: DONTCOPY
  (FILEMAP (NIL (5468 6959 (PCDAC.SETCLOCK 5478 . 6078) (PCDAC.SETUPDMA 6080 . 6957)) (6986 9240 (
PCDAC.READA/DIMMEDIATE 6996 . 7431) (PCDAC.SETA/DPARAMETERS 7433 . 8484) (PCDAC.STARTREADA/D 8486 . 
8877) (PCDAC.READA/DDATUM 8879 . 9238)) (9267 11307 (PCDAC.WRITED/AIMMEDIATE 9277 . 9865) (
PCDAC.SETD/APARAMETERS 9867 . 10559) (PCDAC.STARTWRITED/A 10561 . 10953) (PCDAC.WRITED/ADATUM 10955 . 
11305)) (11338 13974 (PCDAC.SETDIGITALINPUT 11348 . 11959) (PCDAC.SETDIGITALOUTPUT 11961 . 12575) (
PCDAC.READDIGITALIMMEDIATE 12577 . 13316) (PCDAC.WRITEDIGITALIMMEDIATE 13318 . 13972)) (13993 20402 (
PCDAC.STOP 14003 . 17562) (PCDAC.CLEARERROR 17564 . 18921) (PCDAC.RESET 18923 . 20244) (
PCDAC.HARDRESET 20246 . 20400)) (20443 24974 (PCDAC.READYFORCOMMAND 20453 . 21738) (PCDAC.READYFORREAD
 21740 . 23342) (PCDAC.READYFORWRITE 23344 . 24972)) (25002 30640 (PCDAC.ERROR? 25012 . 25438) (
PCDAC.SHOWSTATUS 25440 . 29060) (PCDAC.SHOWERROR 29062 . 29405) (PCDAC.READERROR 29407 . 30638)) (
30704 31393 (PCDAC.READSTATUS 30714 . 30876) (PCDAC.WRITECOMMAND 30878 . 31055) (PCDAC.READDATABYTE 
31057 . 31219) (PCDAC.WRITEDATABYTE 31221 . 31391)) (31433 36039 (PCDAC.CHECKEDSTATUS 31443 . 32363) (
PCDAC.SHOWASTATUS 32365 . 33287) (PCDAC.SHOWASTATUS.BITASSIGN 33289 . 33541) (PCDAC.SHOWSTATE 33543 . 
33864) (PCDAC.SHOWANERROR 33866 . 34882) (PCDAC.SHOWANERROR.BITASTEXT 34884 . 36037)) (36072 39829 (
PCDAC.DOCOMMAND 36082 . 36348) (PCDAC.COMMANDASTEXT 36350 . 37618) (PCDAC.STATUSASTEXT 37620 . 38586) 
(PCDAC.YNQUERY 38588 . 39022) (\PCDAC.DATAOFFSET 39024 . 39290) (\PCDAC.MFS 39292 . 39557) (\PCDAC.PFS
 39559 . 39827)) (40193 59898 (PCDAC.MAKETEST 40203 . 43098) (PCDAC.TEST 43100 . 43989) (LevelOut 
43991 . 44209) (PlayBack 44211 . 44599) (\MakeSinInArray 44601 . 45166) (PlayTone 45168 . 45693) (
PCDACTestRead 45695 . 46752) (DigitalScope 46754 . 52041) (PCDACTestWindowButtonFn 52043 . 52330) (
DoPCDACTest 52332 . 52674) (ScopeInWindow 52676 . 59896)) (59957 60624 (\PcdDontMove 59967 . 60197) (
\PcdFakeIt1 60199 . 60420) (\PcdFakeIt2 60422 . 60622)))))
STOP