;;; -*- Mode: LISP; Syntax: Common-Lisp -*- ;Code written by Jonathan H. Connell ;Copyright 1990-1992, IBM Corporation, All Rights Reserved ;-------------------------------------------------------------------------------- ;Simple code to control V8601 Speech Synthesizer ;Commands supported: ; ; #x0 - Transfer characters to V8601 up to and including carriage return ; ;================================================================================ (progn (declare (special *download?*)) (defprog TALK :machine 6811 :start #xF800 :code ((splice *6811-defs*) ;high speed serial link parameters (=c s-format #b00011000) ;9 bits, wake-up on top bit (=c s-baudrate #b00000000) ;128 kilobaud (=c s-interrupt #b00100110) ;rx int, rx on, sleep now (=c s-trans-bit #b00001000) ;turn on/off transmitter (=c s-wake-bit #b00000010) ;sleep until next packet (=c s-tx-rdy-bit #b10000000) ;okay to write another byte (=c s-tx-mark-bit #b01000000) ;ninth bit of character out (=c s-rx-mark-bit #b10000000) ;ninth bit of character in ;parallel port masks (=c write-bit #b01000000) ;goes low to write V8601 (A6) (=c read-bit #b00100000) ;goes low to read V8601 (A5) (=c rw-bits #b01100000) (=c sp-ready-bit #b00010000) ;V8601 working (C4) ;speech synthesizer communication (=c command-char #x01) (=c cr-char #.(mod (char-code #\return) 128)) (=c zero-char #.(mod (char-code #\0) 128)) (=c nine-char #.(mod (char-code #\9) 128)) ;incoming HASL commands (=c echo-cmd #x0) ;internal memory (var-decl ( my-address ;network ID of processor (packet-fill 2) ;where to put next new byte (packet-show 2) ;next byte for co-processor (packet-base 20))) ;space for saving packet contents ;================================================================================ START (lds ! ram-top) ;down from top of internal RAM (ldaa ! rw-bits) ;neither reading nor writing (staa porta) (jsr serial-init) ;fire up HASL communicator (ldx ! 0) ;let V8601 clear memory init-wait (dex) (bne init-wait) (ldy ! init-string) ;standard speech parameters (jsr voice-params) (ldy ! sass-string) ;say something at start (jsr voice-string) MAIN (ldy packet-show) ;see if any new characters (cpy packet-fill) (bcc main) (cpy ! packet-base) ;see if first byte (beq xfer-next) (ldaa &y 0) ;get byte from queue (anda ! #b01111111) ;only 7 real bits (jsr voice-char) ;send byte to speech-board (cmpa ! cr-char) ;end of packet if first CR (bne xfer-next) (jsr serial-end) ;send acknowledgment xfer-next (iny) ;bump pointer for next time (sty packet-show) (bra main) ;high pitched voice with long pauses between words init-string (!sstring "7F9V1X") ;what to say on initial power-up sass-string (!sstring "I am tired, do not bother me!") ;-------------------------------------------------------------------------------- ;take the sized string Y points to, add a CR, and send it to the V8601 VOICE-STRING (ldab &y 0) ;get number of chars (iny) ;point to first real char talk-loop (ldaa &y 0) ;send next byte to V8601 (jsr voice-char) (iny) ;advance pointer (decb) ;decrement character count (bne talk-loop) ;see if all chars sent string-done (ldaa ! cr-char) ;tack on a carriage return (jsr voice-char) (rts) ;take the sized string Y points to and interpret it as a V8601 command string VOICE-PARAMS (ldab &y 0) ;get number of chars (iny) ;point to first real char cmd-prefix (ldaa ! command-char) ;start a new command (jsr voice-char) cmd-value (ldaa &y 0) ;send next byte to V8601 (jsr voice-char) (iny) ;advance pointer (decb) ;decrement character count (beq params-done) ;see if all chars sent (cmpa ! zero-char) ;see if non-number just sent (blo cmd-prefix) (cmpa ! nine-char) (bhi cmd-prefix) (bra cmd-value) ;if number no prefix needed params-done (rts) ;send ASCII character in A out to synthesizer (busy waits - bashes X) VOICE-CHAR (ldx ! port-area) (bset &x iporta read-bit) ;finish any old read pulse (bclr &x iporta read-bit) ;start read pulse (brclr &x iportc sp-ready-bit voice-char) ;see if V8601 is ready yet (bset &x iporta read-bit) ;finish this read pulse (staa portc) (bset &x iddrc #xFF) ;enable outputs (bclr &x iporta write-bit) ;generate write pulse (bset &x iporta write-bit) (bclr &x iddrc #xFF) ;disable outputs char-ack (bset &x iporta read-bit) ;finish any old read pulse (bclr &x iporta read-bit) ;start read pulse (brset &x iportc sp-ready-bit char-ack) ;see if V8601 got character (bset &x iporta read-bit) ;finish this read pulse (rts) ;-------------------------------------------------------------------------------- ;set up serial parameters SERIAL-INIT (ldaa ! s-format) ;how many bits per character (staa sccr1) (ldaa ! s-baudrate) ;how fast to send (staa baud) (ldaa ! s-interrupt) ;which interrupts are on (staa sccr2) (ldx ! packet-base) ;initialize pointers (stx packet-fill) (stx packet-show) (ldab portd) ;get own address (aslb) (aslb) (andb ! #b11110000) (stab my-address) ;and save for future reference (cli) ;turn on interrupts (rts) ;Sends out byte in A with bit 8 clear, uses busy waiting (bashes X) SERIAL-XMIT (ldx ! port-area) (bset &x isccr2 s-trans-bit) ;grab slave line xmit-wait (brclr &x iscsr s-tx-rdy-bit xmit-wait) ;wait for last byte to go (bclr &x isccr1 s-tx-mark-bit) ;clear bit 8 in general (staa scdr) ;queue for transmission (rts) ;Sends out byte in A with bit 8 set, uses busy waiting (bashes X) ;Turns transmitter off at end of packet. SERIAL-END (ldx ! port-area) (bset &x isccr2 s-trans-bit) ;grab slave line mark-wait (brclr &x iscsr s-tx-rdy-bit mark-wait) ;wait for last byte to go (bset &x isccr1 s-tx-mark-bit) ;set bit 8 for end of packet (staa scdr) ;queue for transmission end-wait (brclr &x iscsr s-tx-rdy-bit end-wait) ;wait for last byte to go (bclr &x isccr2 s-trans-bit) ;relinquish slave line (rts) ;decodes interrupt, but only deals with incoming packets ;save incoming packet for transfer (only 50 instructions between bytes) ;when initial byte comes, whack packet pointers to base address SERIAL-HANDLER (ldaa scsr) ;clear interrupt (ldaa scdr) ;get incoming byte in A (ldy packet-fill) ;where to put byte (ldx ! port-area) ;for indirection (brclr &x isccr1 s-rx-mark-bit s-continue) ;see if first byte of packet s-compare (tab) ;make a copy of command (andb ! #b11110000) ;extract destination number (cmpb my-address) (beq s-restart) ;if msg for this box (bset &x isccr2 s-wake-bit) ;else ignore rest of packet (rti) s-restart (ldy ! packet-base) ;initialize pointer (sty packet-show) ;too bad if not finished! s-continue ;int only if packet accepted (staa &y 0) ;record byte (iny) ;advance pointer (sty packet-fill) (rti) ;-------------------------------------------------------------------------------- ;vectors (= #xFFD6) ;serial port interrupt (!16 serial-handler) (= #xFFF8) ;illegal opcode (!16 start) (= #xFFFE) ;reset (!16 start))) ;automatically load processor on compile or eval of buffer (if *download?* (dl talk #x06)) )