;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!; ; COPYRIGHT (C) 1994 KEN STATON ; ; ALL RIGHTS RESERVED ; ;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!; #INCLUDE "GLOBALS.TXT" .MSFIRST ; MOST SIGNIFICANT BYTE FIRST! ; ; Ken Staton ; Feb 9, 1993 First coding ; Apr 3, 1993 Added DAC support ; ~44K of digitized speech: ; A-Z = 26 + 0-9 = 10 + {.,?} = 3 total = 39 ; {sk,bt,ar,dn,kn} = 5; 39 + 5 = 44 ; could implement {sk,bt,ar,dn,kn} as ; concatenations of letters ; Jun 3, 1993 Added ADPCM digitized speech ; Aug 17, 1993 Cleanup. Removed Debug & RS232. ; Aug 25, 1993 Changed 4Mc->3.2768Mc ; Fixed interrupt problem (not re-entrant) ; by disabling INTS in speak & morse ; Jan 25, 1994 Added BUILDIT speech mode in preparation ; for allophone based speech. Currently ; used for concatenating sounds of prosigns. ; Feb 1, 1994 Changed 3.2768Mc->6.0Mc to support 8KHz data rate. ; Mar 19, 1994 Added SET Option. Commented out to disable. ; Apr 16, 1994 Fixed char rate bug when changed from default. ; Apr 20, 1994 Added programmed delay before and after speaking ; Apr 22, 1994 Version 1.0 ; ;--------------------------------------------------------------------- ; ; Select options using ext_int0 ; Options are: ; Speed ; 5@16 ; 13@18 ; 20@23 ; Toggle ; SPEECH ; Random Chars ; Random Groups of five chars ; Sequence Chars ; Toggle Set (see SUBSET; not enabled) ; LETTERS ; NUMBERS ; PROSIGNS ; PUNCTUATION ;** PROGRESSIONS ;** COMPLEMENTS ; ** = not yet implemented... ; ; #INCLUDE "ISR_INIT.TXT" ;************************************************************** ; ; MAIN LOOP ; MAIN CJNE R4,#RAN,MODE0 ;if R4=Random then JMP RCHARS LJMP RCHARS MODE0 CJNE R4,#SEQ,MODE1 ;if R4=Sequence then JMP CYCLE LJMP CYCLE MODE1 CJNE R4,#GRP,MODE2 ;if R4=Group then JMP RGRP LJMP RGRP MODE2 SJMP MAIN ;************************************************************** ; ; RCHARS - Random Characters ; RCHARS LCALL RANDOM ; GENERATE RANDOM INDEX TRUNC MOV A,PH RR A RR A RR A MOV COUNT,A ; SAVE INDEX CLR C SUBB A,#SETSIZE ; A <- A - C - #data JNC RCHARS ; C=0 -> A>=SETSIZE ; for INDEX: 0..SETSIZE-1 MOV A,COUNT LCALL SUBSET JZ RCHARS JNB CODE,RCPO1 MOV A,COUNT ; restore index LCALL MORSE ; sound code RCPO1 JNB SPEAK,RCPO2 MOV A,COUNT ; restore index LCALL SPEECH ; speak code RCPO2 LJMP MAIN ; RESTART MAIN LOOP ;************************************************************** ; ; RGRP - Random Groups ; RGRP PUSH RH PUSH RL LCALL RCODE LCALL RCODE LCALL RCODE LCALL RCODE LCALL RCODE LCALL WORD_DLY POP RL ; Restore seed. psuedorandom, POP RH ; so sequence will be the same... LCALL RTALK LCALL RTALK LCALL RTALK LCALL RTALK LCALL RTALK LJMP MAIN ; RESTART MAIN LOOP ;************************************************************** ; ; RCODE - Random Code SUBROUTINE for RGRP ; RCODE LCALL RANDOM ; GENERATE RANDOM INDEX MOV A,PH RR A RR A RR A MOV COUNT,A ; SAVE INDEX CLR C SUBB A,#SETSIZE JNC RCODE ;C=0 -> A>=SETSIZE ; for INDEX: 0..43 ; for INDEX: 0..SETSIZE-1 MOV A,COUNT LCALL SUBSET JZ RCODE MOV A,COUNT ; RESTORE INDEX LCALL MORSE ; sound code RET ; DONE ;************************************************************** ; ; RTALK - Random Talk SUBROUTINE for RGRP ; RTALK LCALL RANDOM ; GENERATE RANDOM INDEX MOV A,PH RR A RR A RR A MOV COUNT,A ; SAVE INDEX CLR C SUBB A,#SETSIZE JNC RTALK ; C=0 -> A>=SETSIZE ; for INDEX: 0..SETSIZE-1 MOV A,COUNT LCALL SUBSET JZ RTALK MOV A,COUNT ; RESTORE INDEX JNB SPEAK,RTDONE LCALL SPEECH ; speak code RTDONE RET ; DONE ;************************************************************** ; ; CYCLE - Cycle sequentially through character set ; CYCLE MOV COUNT,#0 NEXT_C MOV A,COUNT LCALL SUBSET JZ NEXT_C MOV A,COUNT JNB CODE,CYC1 LCALL MORSE ; sound code CYC1 JNB SPEAK,CYC2 ; test if speak on MOV A,COUNT ; restore index LCALL SPEECH ; speak code CYC2 INC COUNT MOV A,COUNT CJNE A,#SETSIZE,NEXT_C LJMP MAIN ; RESTART MAIN LOOP ; ;************************************************************************* ; ; RANDOM ; ; RANDOM NUMBERS BETWEEN 0 AND {26+10+3+4 = 43}-1 = 42 ; i.e. mod 42 ; ; Best bet is to generate seed by having 16 bit counter that ; increments until input at power up...this requires setting ; mode, or maybe just indicating when to start... ; ; Some external asyncronous event must establish seed. ; See EXT0 in INIT_ISR. ; ; Algorithm described in: ; The Art of Computer Programming Volume 2, Seminumerical Algorithms ; Donald Knuth ; ; X <- (aX + c) mod m ; ; m = 65536 ; c/m ~ 0.2113248654 ; c odd ; 13.85 -> c = 13 ; a > sqrt(m), a > m/100, a < m - sqrt(m) ; 256 < 655 < a < 65280 ; a = 31415 {= 122*256 + 183} ; ; X <- (31415 * X + 13) mod 65536 ; ; NOTE: that the arithmetic done in a 16 bit word ; is mod 2^16 = 65536 ; ; A * B = (AL + 2^8 * AH) * (BL + 2^8 * BH) ; = AL * BL + 2^8(AL * BH + AH * BL) + 2^16(AH * BH) ; A * 31415 = AL * 183 + 2^8(AL * 122 + AH * 183) + 2^16(AH * 122) ; RANDOM MOV A,RL MOV B,#183 MUL AB ; A[7..0],B[15..8] product bits MOV PL,A MOV PH,B MOV A,RL MOV B,#122 MUL AB ADD A,PH MOV PH,A MOV A,RH MOV B,#183 MUL AB ADD A,PH MOV PH,A CLR C ; NOW ADD c MOV A,PL ADDC A,#13 MOV PL,A JNC NOCARRY INC PH NOCARRY MOV RL,PL MOV RH,PH RET ; DONE RANDOM ; ;************************************************************************* ; ; Define code for MORSE SUBROUTINE ; ; ; numbers 5 bits ; punctuation 6 bits ; letters <= 4 bits ; ; b7 b6 b5 | b[4:0] -> group ;---------------|-------------------------- ; 0 0 d | number or prosign ; 0 1 d | punctuation or prosign ; 1 0 0 | 1 element letter ; 1 0 1 | 2 element letter ; 1 1 0 | 3 element letter ; 1 1 1 | 4 element letter ; | ; d => don't | 1 => dah ; care | 0 => dit ; CODE_TBL LETTERS MCA .DB 10100001B MCB .DB 11101000B MCC .DB 11101010B MCD .DB 11000100B MCE .DB 10000000B MCF .DB 11100010B MCG .DB 11000110B MCH .DB 11100000B MCI .DB 10100000B MCJ .DB 11100111B MCK .DB 11000101B MCL .DB 11100100B MCM .DB 10100011B MCN .DB 10100010B MCO .DB 11000111B MCP .DB 11100110B MCQ .DB 11101101B MCR .DB 11000010B MCS .DB 11000000B MCT .DB 10000001B MCU .DB 11000001B MCV .DB 11100001B MCW .DB 11000011B MCX .DB 11101001B MCY .DB 11101011B MCZ .DB 11101100B NUMBERS MC1 .DB 00001111B MC2 .DB 00000111B MC3 .DB 00000011B MC4 .DB 00000001B MC5 .DB 00000000B MC6 .DB 00010000B MC7 .DB 00011000B MC8 .DB 00011100B MC9 .DB 00011110B MC0 .DB 00011111B PUNCTUATION MCPP .DB 01010101B MCPC .DB 01110011B MCPQ .DB 01001100B PROSIGNS MCSDN .DB 00010010B MCSSK .DB 01000101B MCSBT .DB 00010001B MCSAR .DB 00001010B MCSKN .DB 00010110B ; <<< NOT PART OF TEST SET! SUBSET ; ; CHECKS IF CHARACTER INDEX IS IN AN ENABLED SUBSET ; RETURNS ACC=0 IF NOT ENABLED ; RETURNS ACC=1 IF ENABLED ; ; CLR C ; SUBB A,#CONST ; C=0 -> A>=CONST ; ; CLR C ; SUBB A,#26 ; A={0..25} -> LETTER ; JC IN_GL ; C=1 -> A<26 ; MOV A,COUNT ; SUBB A,#36 ; A={26..35} -> NUMBER ; JC IN_GN ; C=1 -> 26<=A<36 ; MOV A,COUNT ; SUBB A,#39 ; A={36..38} -> PUNCTUATION ; JC IN_GP ; C=1 -> 36<=A<39 ; MOV A,COUNT ; SUBB A,#43 ; A={39..42} -> PRO-SIGN ; JC IN_GS ; C=1 -> 39<=A<43 ;IN_GL ; JNB GL,NOT_IN_SET ; MOV A,#YES ; RET ;IN_GN ; JNB GN,NOT_IN_SET ; MOV A,#YES ; RET ;IN_GP ; JNB GP,NOT_IN_SET ; MOV A,#YES ; RET ;IN_GS ; JNB GS,NOT_IN_SET ; MOV A,#YES ; RET ;NOT_IN_SET ; MOV A,#NO ; RET MOV A,#YES ; always enabled for now... RET SPEECH ; ; INPUT ACC = index for sound table, which must match ; order of code table CLR C RLC A ;MUL BY 2 for 2 byte address entries in table MOV TMP2,A ;save index by 2 MOV DPTR,#SOUND_TBL MOVC A,@A+DPTR MOV ADDR_H,A ;save addrh MOV A,TMP2 ;restore index by 2 INC A ;get rest of addr MOVC A,@A+DPTR MOV DPL,A MOV DPH,ADDR_H ; ; delay after code - before speaking ; MOV R7,DLY_B4 LCALL DELAY MOV R7,DLY_B4 LCALL DELAY MOV R7,DLY_B4 LCALL DELAY MOV R7,DLY_B4 LCALL DELAY MOV TMP2,#0 ;start at entry 0 BLD_LOOP MOV A,TMP2 MOVC A,@A+DPTR CJNE A,#PA1,TP2 ;test if 1mS pause SJMP PAUSE1 TP2 CJNE A,#PA10,TP3 ;test if 10mS pause SJMP PAUSE2 TP3 CJNE A,#PA100,TP4 ;test if 100mS pause SJMP PAUSE3 TP4 CJNE A,#PA300,TP5 ;test if 500mS pause SJMP PAUSE4 TP5 CJNE A,#PA500,TTERM ;test if terminator (0FFH) SJMP PAUSE5 TTERM CJNE A,#0FFH,BLD_MORE ; ; delay after speaking - before next code ; MOV R7,DLY_AR LCALL DELAY MOV R7,DLY_AR LCALL DELAY MOV R7,DLY_AR LCALL DELAY MOV R7,DLY_AR LCALL DELAY RET ; DONE BLD_MORE LCALL MAKESOUND BMORE INC TMP2 SJMP BLD_LOOP ; ; These pauses are used in speech concatenation ; PAUSE1 MOV R7,#1 LCALL DELAY SJMP BMORE PAUSE2 MOV R7,#10 LCALL DELAY SJMP BMORE PAUSE3 MOV R7,#100 LCALL DELAY SJMP BMORE PAUSE4 MOV R7,#150 LCALL DELAY MOV R7,#150 LCALL DELAY SJMP BMORE PAUSE5 MOV R7,#250 LCALL DELAY MOV R7,#250 LCALL DELAY SJMP BMORE SOUND_TBL #INCLUDE "TABLE02.TXT" ; Defines contatenations MAKESOUND #INCLUDE "SPEAK.TXT" MORSE #INCLUDE "MORSE.TXT" .ORG (0FFFFH-51) .TEXT "COPYRIGHT (C) 1994 KEN STATON. ALL RIGHTS RESERVED" .ORG 0FFFFH .DB 0FFH .END