(FILECREATED " 9-Jan-85 13:14:38" {ERIS}<SPEECH>MAILREADER>COMMUNICARD.;1 14503  

      previous date: "20-Dec-84 17:27:14" {DSK}<DSK>BURWELL>COMMUNICARD.;1)


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

(PRETTYCOMPRINT COMMUNICARDCOMS)

(RPAQQ COMMUNICARDCOMS ((* The variables CTRL DATA DTMF and RST contain the i/o location addresses of 
			   the Communicard in the PC's i/o space)
	(VARS CTRL DATA DTMF RST)
	(* Variables identifying the different bits in the CTRL register)
	(VARS HAND LINE MONITOR OH PHONE RDY TONE)
	(VARS BACKWARDS.LIMIT BANK BEEP.LIMIT ENB FAST.LIMIT RESPONSE.LIMIT SLOW.LIMIT SMEAR.LIMIT 
	      SPEECH.THRESHOLD SPEECH1.LIMIT SPEECH2.LIMIT SPEECH3.LIMIT)
	(* Utility functions)
	(FNS BINARY BINSTAT C.PEEK C.SETUP CORRECT HEX HEXCHAR INP OUT POLL START.CTRL.MONITOR 
	     TEST.PORT)
	(FNS ANSWERING.MACHINE COMMUNICARD.SETUP DIAL DIAL.DIGIT INIT.ANSWERING.MACHINE MAKE.REG.MENU 
	     OFF.HAND OFF.HOOK OFF.LINE OFF.PHONE ON.HAND ON.HOOK ON.LINE ON.PHONE PLAYIT RECORDIT 
	     REG.MENU.FN RINGING? STATUS STORE.MESSAGE TEST TEST.PLAY.FILE TEST.TONE TONE? 
	     WAIT.FOR.CALL)
	(P (FILESLOAD BUSEXTENDER BUSMASTER))))



(* The variables CTRL DATA DTMF and RST contain the i/o location addresses of the Communicard 
in the PC's i/o space)


(RPAQQ CTRL 630)

(RPAQQ DATA 631)

(RPAQQ DTMF 628)

(RPAQQ RST 629)



(* Variables identifying the different bits in the CTRL register)


(RPAQQ HAND 16)

(RPAQQ LINE 4)

(RPAQQ MONITOR 32)

(RPAQQ OH 1)

(RPAQQ PHONE 2)

(RPAQQ RDY 128)

(RPAQQ TONE 64)

(RPAQQ BACKWARDS.LIMIT 5000)

(RPAQQ BANK 4)

(RPAQQ BEEP.LIMIT 2000)

(RPAQQ ENB 8)

(RPAQQ FAST.LIMIT 5000)

(RPAQQ RESPONSE.LIMIT 30000)

(RPAQQ SLOW.LIMIT 5000)

(RPAQQ SMEAR.LIMIT 5000)

(RPAQQ SPEECH.THRESHOLD 128)

(RPAQQ SPEECH1.LIMIT 30000)

(RPAQQ SPEECH2.LIMIT 5000)

(RPAQQ SPEECH3.LIMIT 5000)



(* Utility functions)

(DEFINEQ

(BINARY
  [LAMBDA (INT)                                              (* pkh: "12-Dec-84 10:51")
                                                             (* Takes a decimal input number and converts it into a 
							     binary number which is printed out;
							     returns nothing)
    (PRINTNUM (QUOTE (FIX NIL 2))
	      INT)
    (PACK])

(BINSTAT
  [LAMBDA NIL                                                (* pkh: "20-Dec-84 12:32")
    (BINARY (BUS.INPUT CTRL])

(C.PEEK
  [LAMBDA NIL                                                (* pkh: "12-Dec-84 10:53")
                                                             (* Adds a process which reads the CTRL register of the 
							     Communicard at frequent intervals and prints out the 
							     register status)
    (ADD.PROCESS (QUOTE (while T do (BLOCK 250)
			       (printout T (POLL CTRL)
					 T])

(C.SETUP
  [LAMBDA NIL                                                (* pkh: "20-Dec-84 14:26")
    (BUS.RESET)
    (OFF.LINE)
    (ON.HAND)
    (OFF.HOOK)
    (ON.PHONE)
    (BINSTAT])

(CORRECT
  [LAMBDA (DATUM)                                            (* hdj " 1-Dec-84 17:21")
    (if (IGREATERP DATUM 127)
	then (IDIFFERENCE DATUM 128)
      else DATUM])

(HEX
  [LAMBDA (STR)                                              (* hdj "30-Nov-84 16:37")
    (PROG (LENGTH STRING)
          (SETQ STRING (SUBSTRING STR 1))
          (SETQ LENGTH (NCHARS STRING))
          (RETURN (for X from 1 to LENGTH sum (TIMES (EXPT 16 (IDIFFERENCE LENGTH X))
						     (HEXCHAR (GNC STRING])

(HEXCHAR
  [LAMBDA (CHAR)                                             (* hdj "30-Nov-84 16:36")
    (SELECTQ CHAR
	     ((0 1 2 3 4 5 6 7 8 9)
	       CHAR)
	     (A 10)
	     (B 11)
	     (C 12)
	     (D 13)
	     (E 14)
	     (F 15)
	     NIL])

(INP
  [LAMBDA (A)                                                (* hdj "30-Nov-84 17:14")
    (BUS.INPUT A])

(OUT
  [LAMBDA (A D)                                              (* hdj "30-Nov-84 17:14")
    (BUS.OUTPUT A D])

(POLL
  [LAMBDA (ADDR)                                             (* pkh: "12-Dec-84 10:54")

          (* Causes the byte at this address to be printed out. Notice that BINARY does not return the binary digit but rather
	  PACK of NIL)


    (BINARY (BUS.INPUT ADDR])

(START.CTRL.MONITOR
  [LAMBDA NIL                                                (* pkh: "19-Dec-84 17:58")
    (ADD.PROCESS (QUOTE (while T do (printout T (BINARY (BUS.INPUT CTRL))
					      T)
			       (BLOCK 100])

(TEST.PORT
  [LAMBDA NIL                                                (* pkh: "20-Dec-84 12:12")
    (while T
       do (BUS.OUTPUT DATA 32)
	  (BLOCK 1)
	  (BUS.OUTPUT DATA 128])
)
(DEFINEQ

(ANSWERING.MACHINE
  [LAMBDA NIL                                                (* hdj " 2-Dec-84 13:27")
    (PROG (PHONEMESSAGESTREAM)
          (SETQ PHONEMESSAGESTREAM (OPENSTREAM (QUOTE {DSK}<SPEECH>MESSAGES.SPEECH)
					       (QUOTE APPEND)))
          (printout STATUSSTREAM "-- Started at " (DATE)
		    " --" T)
          (while (WAIT.FOR.CALL)
	     do (OFF.HOOK)
		(printout STATUSSTREAM "call at " (DATE)
			  T)
		(PLAYIT SPEECH1.ARRAY)
		(PLAYIT BEEP.ARRAY)
		(RECORDIT RESPONSE.ARRAY)
		(PLAYIT SPEECH2.ARRAY)
		(PLAYIT RESPONSE.ARRAY)
		(PLAYIT BACKWARDS.ARRAY)
		(PLAYIT RESPONSE.ARRAY (QUOTE BACKWARDS))
		(PLAYIT SLOW.ARRAY)
		(PLAYIT RESPONSE.ARRAY (QUOTE SLOW))
		(PLAYIT FAST.ARRAY)
		(PLAYIT RESPONSE.ARRAY (QUOTE FAST))
		(PLAYIT SMEAR.ARRAY)
		(PLAYIT RESPONSE.ARRAY (QUOTE SMEAR))
		(PLAYIT SPEECH3.ARRAY)
		(BLOCK 2000)
		(ON.HOOK)
		(STORE.MESSAGE PHONEMESSAGESTREAM RESPONSE.ARRAY))
          (CLOSEF PHONEMESSAGESTREAM])

(COMMUNICARD.SETUP
  [LAMBDA NIL                                                (* pkh: "19-Dec-84 17:45")
    (BUS.RESET)
    (ON.LINE)
    (ON.HOOK])

(DIAL
  [LAMBDA (PHONE.NUMBER)                                     (* hdj " 2-Dec-84 11:46")
    (PROG ((STRING (SUBSTRING PHONE.NUMBER 1)))
          (for X from 1 to (NCHARS STRING) do (DIAL.DIGIT (GNC STRING])

(DIAL.DIGIT
  [LAMBDA (DIGIT)                                            (* hdj " 2-Dec-84 12:07")
    (if (ZEROP DIGIT)
	then (SETQ DIGIT 10))
    (if (NUMBERP DIGIT)
	then (for X from 1 to DIGIT
		do (PRIN3 ".")
		   (ON.HOOK)
		   (BLOCK 200)
		   (OFF.HOOK)
		   (BLOCK 100))
	     (TERPRI)
	     (BLOCK 2000])

(INIT.ANSWERING.MACHINE
  [LAMBDA NIL                                                (* hdj " 1-Dec-84 17:33")

          (* * comment)


    (PROG NIL
          (SETQ SPEECH1.ARRAY (ARRAY SPEECH1.LIMIT (QUOTE BYTE)
				     0 0))
          (SETQ SPEECH2.ARRAY (ARRAY SPEECH2.LIMIT (QUOTE BYTE)
				     0 0))
          (SETQ SPEECH3.ARRAY (ARRAY SPEECH3.LIMIT (QUOTE BYTE)
				     0 0))
          (SETQ RESPONSE.ARRAY (ARRAY RESPONSE.LIMIT (QUOTE BYTE)
				      0 0))
          (SETQ BACKWARDS.ARRAY (ARRAY BACKWARDS.LIMIT (QUOTE BYTE)
				       0 0))
          (printout T 
"now run TEST.RECORD on SPEECH1.ARRAY, SPEECH2.ARRAY, SPEECH3.ARRAY, RESPONSE.ARRAY, and BACKWARDS.ARRAY."
		    T])

(MAKE.REG.MENU
  [LAMBDA NIL                                                (* pkh: " 3-Dec-84 17:49")
    (ADDMENU (create MENU
		     ITEMS ← (APPEND (QUOTE (7 6 5 4 3 2 1 0))
				     (QUOTE (0 0 0 0 0 0 0 0)))
		     MENUCOLUMNS ← 8
		     WHENSELECTEDFN ← (QUOTE REG.MENU.FN])

(OFF.HAND
  [LAMBDA NIL                                                (* hdj " 2-Dec-84 11:27")
    (BUS.OUTPUT CTRL (LOGAND (LOGNOT HAND)
			     (BUS.INPUT CTRL])

(OFF.HOOK
  [LAMBDA NIL                                                (* hdj " 2-Dec-84 11:27")
    (BUS.OUTPUT CTRL (LOGOR (BUS.INPUT CTRL)
			    OH])

(OFF.LINE
  [LAMBDA NIL                                                (* hdj " 2-Dec-84 11:27")
    (BUS.OUTPUT CTRL (LOGAND (LOGNOT LINE)
			     (BUS.INPUT CTRL])

(OFF.PHONE
  [LAMBDA NIL                                                (* hdj " 2-Dec-84 11:27")
    (BUS.OUTPUT CTRL (LOGOR PHONE (BUS.INPUT CTRL])

(ON.HAND
  [LAMBDA NIL                                                (* hdj " 2-Dec-84 11:27")
    (BUS.OUTPUT CTRL (LOGOR HAND (BUS.INPUT CTRL])

(ON.HOOK
  [LAMBDA NIL                                                (* hdj " 2-Dec-84 11:27")
    (BUS.OUTPUT CTRL (LOGAND (BUS.INPUT CTRL)
			     (LOGNOT OH])

(ON.LINE
  [LAMBDA NIL                                                (* hdj " 2-Dec-84 11:27")
    (BUS.OUTPUT CTRL (LOGOR LINE (BUS.INPUT CTRL])

(ON.PHONE
  [LAMBDA NIL                                                (* hdj " 2-Dec-84 11:27")
    (BUS.OUTPUT CTRL (LOGAND (LOGNOT PHONE)
			     (BUS.INPUT CTRL])

(PLAYIT
  [LAMBDA (ARRAY OPTION)                                     (* hdj " 2-Dec-84 12:32")
    (LET [(LIMIT (SUB1 (ARRAYSIZE ARRAY]
      (SELECTQ OPTION
	       [SLOW (for DATUM from 0 to LIMIT
			do (BUS.OUTPUT DATA (ELT ARRAY DATUM))
			   (BUS.OUTPUT DATA (ELT ARRAY DATUM]
	       [FAST (for DATUM from 0 to LIMIT by 2 do (BUS.OUTPUT
							  DATA
							  (LRSH (IPLUS (ELT ARRAY DATUM)
								       (ELT ARRAY (ADD1 DATUM)))
								1]
	       [BACKWARDS (for DATUM from LIMIT to 0 by -1 do (BUS.OUTPUT DATA (ELT ARRAY DATUM]
	       [SMEAR (for DATUM from 0 to (IDIFFERENCE LIMIT 3)
			 do (BUS.OUTPUT DATA (ELT ARRAY (IPLUS DATUM 2)))
			    (BUS.OUTPUT DATA (ELT ARRAY (IPLUS DATUM 1)))
			    (BUS.OUTPUT DATA (ELT ARRAY DATUM]
	       (for DATUM from 0 to LIMIT do (BUS.OUTPUT DATA (ELT ARRAY DATUM])

(RECORDIT
  [LAMBDA (ARRAY)                                            (* hdj " 1-Dec-84 17:00")
    (BUS.OUTPUT DATA SPEECH.THRESHOLD)
    (for DATUM from 0 to (SUB1 (ARRAYSIZE ARRAY)) do (SETA ARRAY DATUM (BUS.INPUT DATA])

(REG.MENU.FN
  [LAMBDA (ITEM FROMMENU BUTTON)                             (* pkh: " 3-Dec-84 17:49")
    (IF ITEM = 0
	THEN NIL])

(RINGING?
  [LAMBDA NIL                                                (* pkh: "12-Dec-84 11:09")
                                                             (* Determines whether the phone is ringing by checking 
							     the MONITOR bit in the CTRL register.
							     Returns T when a ringing has been detected)
    (ZEROP (LOGAND MONITOR (BUS.INPUT CTRL])

(STATUS
  [LAMBDA NIL                                                (* pkh: "20-Dec-84 13:27")
    (PROG (STATUS)
          (SETQ STATUS (BUS.INPUT CTRL))
          (printout T "Status: ")
          (printout T (COND
		      ((ZEROP (LOGAND OH STATUS))
			"on")
		      (T "off"))
		    "hook/"
		    (COND
		      ((ZEROP (LOGAND PHONE STATUS))
			"")
		      (T "no "))
		    "phone/"
		    (COND
		      ((ZEROP (LOGAND LINE STATUS))
			"off")
		      (T "on"))
		    "line/"
		    (COND
		      ((ZEROP (LOGAND HAND STATUS))
			"off")
		      (T "on"))
		    "hand/"
		    (COND
		      ((ZEROP (LOGAND MONITOR STATUS))
			"")
		      (T "not "))
		    "ringing/"
		    (COND
		      ((ZEROP (LOGAND TONE STATUS))
			"no ")
		      (T ""))
		    "tone " T])

(STORE.MESSAGE
  [LAMBDA (FILE SAMPLE)                                      (* hdj " 2-Dec-84 13:31")
    (\BOUTS FILE (fetch (ARRAYP BASE) of SAMPLE)
	    0
	    (ARRAYSIZE SAMPLE])

(TEST
  [LAMBDA NIL                                                (* hdj " 2-Dec-84 11:27")
    (while T do (if (RINGING?)
		    then (OFF.HOOK)
			 (BUS.OUTPUT DATA SPEECH.THRESHOLD)
			 (for DATUM from 0 to (SUB1 SPEECH.LIMIT) do (SETA SPEECHARRAY DATUM
									   (BUS.INPUT DATA)))
			 (ON.HOOK])

(TEST.PLAY.FILE
  [LAMBDA (FILE)                                             (* hdj " 1-Dec-84 17:13")
    (while T do (if (RINGING?)
		    then (OFF.HOOK)
			 (for DATUM from 0 to (SUB1 SPEECH.LIMIT) do (BUS.OUTPUT DATA (BIN FILE)))
			 (ON.HOOK])

(TEST.TONE
  [LAMBDA NIL                                                (* pkh: "12-Dec-84 11:34")
    (PROG (THE.TONE)
          (while T
	     do (COND
		  ((RINGING?)
		    (OFF.HOOK)
		    (BLOCK 2000)))
		(COND
		  ((NOT (ZEROP (LOGAND (BUS.INPUT CTRL)
				       TONE)))
		    (printout T "tone " (LOGAND 15 (BUS.INPUT DTMF))
			      T)
		    (BUS.OUTPUT DTMF 0])

(TONE?
  [LAMBDA NIL                                                (* hdj " 2-Dec-84 12:10")
    (COND
      ((ZEROP (LOGAND (BUS.INPUT CTRL)
		      TONE))
	NIL)
      (T (PROG1 (LOGAND 15 (BUS.INPUT DTMF))
		(BUS.OUTPUT DTMF 0])

(WAIT.FOR.CALL
  [LAMBDA NIL                                                (* pkh: "12-Dec-84 11:12")

          (* Causes a block whenever both the phone is not ringing and no one is pressing the STOP (key; returns T when the 
	  phone is ringing provided the stop key is not depressed; if it is depressed it returns NIL))


    (while [AND (NOT (RINGING?))
		(NOT (KEYDOWNP (QUOTE STOP]
       do (BLOCK))
    (NOT (KEYDOWNP (QUOTE STOP])
)
(FILESLOAD BUSEXTENDER BUSMASTER)
(PUTPROPS COMMUNICARD COPYRIGHT ("Xerox Corporation" 1984 1985))
(DECLARE: DONTCOPY
  (FILEMAP (NIL (2007 5073 (BINARY 2017 . 2400) (BINSTAT 2402 . 2544) (C.PEEK 2546 . 2985) (C.SETUP 2987
 . 3205) (CORRECT 3207 . 3409) (HEX 3411 . 3802) (HEXCHAR 3804 . 4062) (INP 4064 . 4186) (OUT 4188 . 
4313) (POLL 4315 . 4608) (START.CTRL.MONITOR 4610 . 4860) (TEST.PORT 4862 . 5071)) (5074 14382 (
ANSWERING.MACHINE 5084 . 6183) (COMMUNICARD.SETUP 6185 . 6356) (DIAL 6358 . 6614) (DIAL.DIGIT 6616 . 
7010) (INIT.ANSWERING.MACHINE 7012 . 7787) (MAKE.REG.MENU 7789 . 8102) (OFF.HAND 8104 . 8293) (
OFF.HOOK 8295 . 8468) (OFF.LINE 8470 . 8659) (OFF.PHONE 8661 . 8830) (ON.HAND 8832 . 8998) (ON.HOOK 
9000 . 9186) (ON.LINE 9188 . 9354) (ON.PHONE 9356 . 9546) (PLAYIT 9548 . 10570) (RECORDIT 10572 . 
10844) (REG.MENU.FN 10846 . 10991) (RINGING? 10993 . 11390) (STATUS 11392 . 12258) (STORE.MESSAGE 
12260 . 12470) (TEST 12472 . 12842) (TEST.PLAY.FILE 12844 . 13156) (TEST.TONE 13158 . 13600) (TONE? 
13602 . 13873) (WAIT.FOR.CALL 13875 . 14380)))))
STOP