(FILECREATED "25-Feb-85 19:02:08" {ERIS}<SPEECH>MAILREADER>COMMUNICARD.;3 14510  

      previous date: "17-Jan-85 18:16:24" {ERIS}<SPEECH>MAILREADER>COMMUNICARD.;2)


(* 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 (2014 5080 (BINARY 2024 . 2407) (BINSTAT 2409 . 2551) (C.PEEK 2553 . 2992) (C.SETUP 2994
 . 3212) (CORRECT 3214 . 3416) (HEX 3418 . 3809) (HEXCHAR 3811 . 4069) (INP 4071 . 4193) (OUT 4195 . 
4320) (POLL 4322 . 4615) (START.CTRL.MONITOR 4617 . 4867) (TEST.PORT 4869 . 5078)) (5081 14389 (
ANSWERING.MACHINE 5091 . 6190) (COMMUNICARD.SETUP 6192 . 6363) (DIAL 6365 . 6621) (DIAL.DIGIT 6623 . 
7017) (INIT.ANSWERING.MACHINE 7019 . 7794) (MAKE.REG.MENU 7796 . 8109) (OFF.HAND 8111 . 8300) (
OFF.HOOK 8302 . 8475) (OFF.LINE 8477 . 8666) (OFF.PHONE 8668 . 8837) (ON.HAND 8839 . 9005) (ON.HOOK 
9007 . 9193) (ON.LINE 9195 . 9361) (ON.PHONE 9363 . 9553) (PLAYIT 9555 . 10577) (RECORDIT 10579 . 
10851) (REG.MENU.FN 10853 . 10998) (RINGING? 11000 . 11397) (STATUS 11399 . 12265) (STORE.MESSAGE 
12267 . 12477) (TEST 12479 . 12849) (TEST.PLAY.FILE 12851 . 13163) (TEST.TONE 13165 . 13607) (TONE? 
13609 . 13880) (WAIT.FOR.CALL 13882 . 14387)))))
STOP