\ RABBIT 2000 RCM2300 VOICE DIRECT 364 SLAVE INTERFACE \ K STATON 2/18/2002 \ RCM2300 PORT E MAPPING \ LED PORT E BIT7 \ SWITCH PORT B BIT3 \ VD364 DATA PE4 bidirectional (default is input!) \ nothing on PE3 \ VD364 RESET PE2 output \ VD364 MHS PE1 output \ VD364 SHS PE0 input VARIABLE DISPLAY \ used for display of result or leave on stack : DLY FOR ( nothing ) NEXT ; : LED_ON 0 7F P! ; : LED_OFF 80 7F P! ; : BLINKLED ( delay -- ) DUP LED_ON DLY LED_OFF DLY ; : NBLINK ( n -- ) BEGIN 8000 BLINKLED 1 - DUP 0 = UNTIL DROP ; : ?PB 40 P@ 8 AND IF -1 ELSE 0 THEN ; : ?DISPLAY DISPLAY @ 0 = IF 0 ELSE -1 THEN ; 1 DISPLAY ! \ init to true : DDRE ( n -- ) 77 P! ; \ 1: OUT 0: IN \ : VDI ( 1XX0 X110 ) EE DDRE ; \ : VDO ( 1XX1 X110 ) FE DDRE ; \ proto board 1K between PE4-PE5 for INT BUG : VDI ( 1X00 X110 ) CE DDRE ; : VDO ( 1X01 X110 ) DE DDRE ; : VD_RST VDI \ default to input \ be sure MHS negated FF 79 P! \ then strobe RESET line 0 7A P! 2000 DLY FF 7A P! ; : ?SHS 78 P@ 1 AND 0 = IF 0 ELSE -1 THEN ; : WR_DATA ( t,f -- ) \ wait for SHS = 1 BEGIN ?SHS UNTIL \ set DATA bit IF FF 7C P! ELSE 0 7C P! THEN \ assert MHS = 0 0 79 P! \ wait for SHS = 0 BEGIN ?SHS NOT UNTIL \ negate MHS = 1 FF 79 P! ; : RD_DATA ( -- b ) \ wait for SHS = 0 BEGIN ?SHS NOT UNTIL \ get bit 7C P@ 10 AND 0 = IF 0 ELSE 1 THEN \ assert MHS = 0 0 79 P! \ wait for SHS = 1 BEGIN ?SHS UNTIL \ negate MHS = 1 FF 79 P! ; \ 8 bits msb first : VDWRB ( n -- ) VDO DUP 80 AND WR_DATA DUP 40 AND WR_DATA DUP 20 AND WR_DATA DUP 10 AND WR_DATA DUP 08 AND WR_DATA DUP 04 AND WR_DATA DUP 02 AND WR_DATA 01 AND WR_DATA VDI ; : VDRDB ( -- n ) RD_DATA 80 * RD_DATA 40 * + RD_DATA 20 * + RD_DATA 10 * + RD_DATA 08 * + RD_DATA 04 * + RD_DATA 02 * + RD_DATA 01 * + ; : WAIT_DONE \ WAIT FOR SHS = 1 BEGIN ?SHS UNTIL ; : GET_RESP \ WAIT FOR SHS = 0 BEGIN ?SHS NOT UNTIL \ THEN GET BYTES UNTIL SHS = 1 VDRDB FF = NOT IF ." Invalid SYNC " EXIT THEN BEGIN ?SHS NOT UNTIL VDRDB ( # bytes to read ) BEGIN BEGIN ?SHS NOT UNTIL VDRDB ?DISPLAY IF . ELSE SWAP ( keep count on top ) THEN 1 - DUP 1 = UNTIL DROP BEGIN ?SHS NOT UNTIL VDRDB DROP \ checksum ; : VDSYNC FF VDWRB ; : CHKSUM ( wwww -- bb ) FF AND ; \ ********** COMMANDS ********** : NOP VDSYNC \ sync 2 VDWRB \ length 0 VDWRB \ command 2 VDWRB \ checksum WAIT_DONE GET_RESP ; : VDVER \ VERSION VDSYNC 2 VDWRB 1 VDWRB 3 VDWRB \ checksum WAIT_DONE GET_RESP ; : PROMPT ( src prpt -- ) VDSYNC 4 VDWRB 30 VDWRB 2DUP VDWRB \ prompt VDWRB \ source 4 30 + + + CHKSUM VDWRB \ checksum WAIT_DONE GET_RESP DROP \ don't care about response ; : BEEP 0 CC PROMPT ; : TRAIN ( n -- ) \ n = 1..60 VDSYNC 5 VDWRB 2 VDWRB ( n ) 3C + DUP VDWRB \ prompt 0 VDWRB \ source 1 VDWRB \ tries 5 2 + + 0 + 1 + CHKSUM VDWRB \ checksum WAIT_DONE GET_RESP ; : DELETEALL VDSYNC 3 VDWRB 28 VDWRB 55 VDWRB 3 28 + 55 + CHKSUM VDWRB WAIT_DONE GET_RESP ; : CL \ CONTINUOUS LISTEN VDSYNC 3 VDWRB 4A VDWRB 01 VDWRB \ always use 01 mask for CL 3 4A + 01 + CHKSUM VDWRB \ interruptable wait until done CR ." Press any key to interrupt... " BEGIN ?SHS ?KEY IF 0 79 P! FF 79 P! -1 ELSE 0 THEN OR UNTIL ; : SD ( mask -- ) \ SPEAKER DEPENDENT VDSYNC 3 VDWRB 4C VDWRB DUP ( mask -- ) VDWRB \ mask 3 4C + + CHKSUM VDWRB WAIT_DONE GET_RESP ; : CLP \ CLEAR CURRENT POINTER VDSYNC 2 VDWRB 20 VDWRB 2 20 + CHKSUM VDWRB WAIT_DONE GET_RESP ; : GP \ GET CURRENT POINTER VDSYNC 2 VDWRB 26 VDWRB 28 VDWRB \ checksum WAIT_DONE GET_RESP ; : QLS \ QUERRY LEXICON STATUS VDSYNC 2 VDWRB 2B VDWRB 2 2B + CHKSUM VDWRB WAIT_DONE GET_RESP ; : SMA ( attr mask -- ) \ SET MASK & ATTRIBUTE VDSYNC 4 VDWRB 29 VDWRB 2DUP + ROT ROT ( mask -- ) VDWRB ( attr -- ) VDWRB 4 29 + + CHKSUM VDWRB WAIT_DONE GET_RESP ; : GET_PARM ( index -- ) VDSYNC 3 VDWRB 42 VDWRB DUP ( index ) VDWRB 3 42 + + CHKSUM VDWRB WAIT_DONE GET_RESP ; : PUT_PARM ( value index -- ) VDSYNC 4 VDWRB 41 VDWRB 2DUP + ROT ROT ( index ) VDWRB ( value ) VDWRB 4 41 + + CHKSUM VDWRB WAIT_DONE GET_RESP ; \ ********** SPOKEN PROMPTS ********** : SAY_WORD 0 79 PROMPT ; : SAY_LOUD 1 9C PROMPT ; : SAY_SOFT 1 9D PROMPT ; : SAY_NREC 1 98 PROMPT ; : SAY_ERRR 1 99 PROMPT ; : SAY_REPT 1 59 PROMPT ; : SAY_ACPT 1 41 PROMPT ; : SAY_REJT 1 42 PROMPT ; : SAY_WORDN ( n -- ) 3C + 0 SWAP PROMPT ; \ n = 1..60 \ ********** MAIN ROUTINES ********** \ A LITTLE MORSE CODE FOR DEBUG I/O : DIT 1 DC PROMPT ; : DAH 1 E2 PROMPT ; : PAUSE 1 EC PROMPT ; : OK DAH DAH DAH PAUSE DAH DIT DAH ; : ON DAH DAH DAH PAUSE DAH DIT ; : OFF DAH DAH DAH PAUSE DIT DIT DAH DIT PAUSE DIT DIT DAH DIT ; : TIME_OUT DAH PAUSE DAH DAH DAH ; \ robust recognition requires fully decoding responses \ 00H success \ 01H timed out \ 03H too noisy \ 04H too softly \ 05H too loudly \ 06H too soon \ 07H NO MATCH \ 08H uncertain \ 09H too similar \ 12H invalid pointer \ 18H too long \ FFH interrupted \ ONLY HANDLE NON-ZERO (ERROR) RESPONSES HERE : RESP_HANDLER ( n -- ) DUP 1 = IF TIME_OUT ELSE DUP 3 = IF ( NOISY ) ELSE DUP 4 = IF SAY_LOUD ELSE DUP 5 = IF SAY_SOFT ELSE DUP 6 = IF ( TOO SOON ) ELSE DUP 7 = IF SAY_NREC ELSE DUP 8 = IF SAY_NREC ELSE DUP 9 = IF SAY_NREC ELSE THEN \ 9 THEN \ 8 THEN \ 7 THEN \ 6 THEN \ 5 THEN \ 4 THEN \ 3 THEN \ 1 DROP ; : TEST \ waits for CL word, then gets pointer # & blinks LED that # times 0 DISPLAY ! \ leave result on stack CL GET_RESP DROP GP ROT DROP CR DUP . 1 + ( don't ZERO base ) NBLINK ; : STOP OFF ( debug ) ; : START ON ( debug ) ; : MODE ( FIXME ) DAH DAH ; : BLINK MODE ; \ DESIGN OF SPEECH INTERFACE FOR PROPELLER CLOCK \ GROUP : RECOGNIZE MODE : MASK : WORD{ptr}[NEXT] WORD{ptr}[NEXT] \ 1 : CL : $01 : PROPELLER{0}[2] STOP{1}[1] \ 2 : SD : $02 : ON{2}[1] MODE{3}[3] \ 3 : SD : $04 : BLINK{4}[4] LESLIE [4] ARTIE [4] \ 4 : SD : $08 : ON{5}[1] \ STRUCTURE FOR ONE PASS THROUGH (DON'T REPEAT HERE) \ TO MAKE IT EASIER TO HANDLE THINGS LIKE TIMEOUT \ AND OTHER ERRORS : LISTEN4 DIT 8 8 SMA DROP \ only SD set 8 8 SD ?DUP IF RESP_HANDLER ELSE GP ( -- resp ptr ) SWAP ?DUP IF RESP_HANDLER ELSE DUP 5 = IF START ELSE THEN \ 5 DROP THEN \ GP response THEN \ SD response ; : LISTEN3 DIT 4 4 SMA DROP \ only SD set 4 4 SD ?DUP IF RESP_HANDLER ELSE GP ( -- resp ptr ) SWAP ?DUP IF RESP_HANDLER ELSE DUP 4 = IF BLINK LISTEN4 ELSE THEN \ 4 DROP THEN \ GP response THEN \ SD response ; : LISTEN2 DIT 2 2 SMA DROP \ only SD set 2 2 SD ?DUP IF RESP_HANDLER ELSE GP ( -- resp ptr ) SWAP ?DUP IF RESP_HANDLER ELSE DUP 2 = IF START ELSE DUP 3 = IF LISTEN3 ELSE THEN \ 3 THEN \ 2 DROP THEN \ GP response THEN \ SD response ; : LISTEN1 1 1 SMA DROP \ only CL set (mask = 1) CL GET_RESP ?DUP IF RESP_HANDLER ELSE GP ( -- resp ptr ) SWAP ?DUP IF RESP_HANDLER ELSE DUP 0 = IF LISTEN2 ELSE DUP 1 = IF STOP ELSE THEN \ 1 THEN \ 0 DROP THEN \ GP response THEN \ CL response ; : LISTEN 0 DISPLAY ! \ leave result on stack LISTEN1 ; VD_RST \ DON'T FORGET THIS!! HAND 2E EMIT