;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!; ; COPYRIGHT (C) 1994 KEN STATON ; ; ALL RIGHTS RESERVED ; ;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!; ; ;************************************************************************* ; ; INPUT ACC = relative index number of digitized speech block ; ; MODIFIES REGISTERS: R3, R5, R6, ACC, PSW:C ; MODIFIES Variables: SP_INDX, SPSTRT_H, SPSTRT_L, SPSTOP_H, SPSTOP_L, ; BLK_IDX, PREV, TMP1 ; ; 2Feb94 Fixed time variation between output values ; ;MAKESOUND JB SPEAK,DO_SAYIT ;Check if talking turned on/off RET ;Return from MAKESOUND if OFF DO_SAYIT CLR INT_EN ;DISABLE INTS! PUSH DPL ; SAVE DPTR PUSH DPH ; MULT BY 4 TO INDEX INTO ARRAY WITH 4 BYTE ENTRIES... CLR C RLC A ; MULT BY 2 CLR C RLC A ; MULT BY 2 MOV SP_INDX,A ; SAVE INDEX*4 (ea entry is 4 bytes) ; SET DPTR TO START OF ARRAY... MOV DPTR,#SPCH_TBL ; BUILD START & STOP... MOVC A,@A+DPTR MOV SPSTRT_H,A ; KEEP HIGH START MOV A,SP_INDX INC A ; MOVE TO LOW BYTE OF START MOVC A,@A+DPTR MOV SPSTRT_L,A ; KEEP LOW START MOV A,SP_INDX INC A ; MOVE TO HIGH BYTE OF STOP INC A MOVC A,@A+DPTR MOV SPSTOP_H,A ; KEEP HIGH STOP MOV A,SP_INDX INC A ; MOVE TO LOW BYTE OF STOP INC A INC A MOVC A,@A+DPTR MOV SPSTOP_L,A ; KEEP LOW STOP ; NOW SET DPTR TO START... MOV DPL,SPSTRT_L ; SET DPTR LOW MOV DPH,SPSTRT_H ; SET DPTR HIGH MOV BLK_IDX,#0 ; RESET BLOCK COUNTER MOV PREV,#REL_DC ; START AT RELATIVE! DC LEVEL ; ; SPEAK LOOP ; ; START WITH TEST FOR END OF SPEECH BLOCK ; SAYLOOP MOV A,SPSTOP_L ; TEST IF DONE CJNE A,DPL,SAYHIGHL MOV A,SPSTOP_H CJNE A,DPH,SAYHIGHH ;DONE! MOV P1,#ABS_DC ; SET OUTPUT TO DC LEVEL WHEN DONE POP DPH ; CLEANUP - RESTORE DPTR POP DPL SETB INT_EN ; ENABLE INTS RET ; DONE SPEAKING ; ; Speak HIGH NYBBLE ; SAYHIGHL NOP ;delay for high mov equiv NOP ;delay for high cjne equiv NOP SAYHIGHH MOV A,BLK_IDX ; TEST FOR END OF BLOCK CJNE A,#HALFBLK,NOBLKRST MOV BLK_IDX,#0 ; RESET BLOCK COUNTER FOR NEXT BLOCK NOBLKRST CLR A MOVC A,@A+DPTR ; GET BYTE SWAP A ; SHIFT UPPER NYBBLE TO LOW 4 BITS ANL A,#0FH ; MASK OUT UPPER 4 BITS MOV TMP1,A ; TEMP SAVE HIGH DATA NYBBLE MOV A,BLK_IDX ; TEST IF Qfn CJNE A,#0,NOTQFNH MOV R3,TMP1 ;SET QFN FROM SAVED HIGH NYBBLE SJMP SAYLOW NOTQFNH MOV A,TMP1 ; RESTORE HIGH DATA NYBBLE LCALL INVQFN CLR C ADDC A,PREV ; A=A+C+PREV MOV PREV,A ; SO, PREV=PREV+A LCALL REL2ABS ; CONVERT TO UNSIGNED ABS MOV P1,A ; OUTPUT BYTE ; MOV R6,#SP_DLY ; SP_WAIT SPLOOPH DJNZ R6,SPLOOPH ; ; ; NOW Speak LOW NYBBLE... NOP NOP NOP NOP NOP ; delay for next byte equiv SAYLOW CLR A MOVC A,@A+DPTR ; GET BYTE NOP ; delay for high swap equiv ANL A,#0FH ; MASK OUT UPPER 4 BITS NOP NOP NOP NOP NOP ; delay for high qfn test equiv LCALL INVQFN CLR C ADDC A,PREV ; A=A+C+PREV MOV PREV,A ; SO, PREV=PREV+A LCALL REL2ABS ; CONVERT TO UNSIGNED ABS MOV P1,A ; OUTPUT BYTE ; MOV R6,#SP_DLY ; SP_WAIT SPLOOPL DJNZ R6,SPLOOPL ; ; ; GET NEXT TWO NYBBLES (BYTE) INC BLK_IDX INC DPTR ; MUST INC PTR, > 256 BYTES LJMP SAYLOOP ; REPEAT ;**************************************************************** ; ; SPEAK SUPPORT SUBROUTINES.... ; ;**************************************************************** ; ; REL2ABS ; ; CONVERTS RELATIVE (SIGNED) NUMBERS TO ABSOLUTE (UNSIGNED) ; DPCM IS DONE USING SIGNED NUMBERS (2's complement) ; SPEECH DIGITIZATION IS DONE USING UNSIGNED NUMBERS ; INPUT IS IN ACC ; OUTPUT IS IN ACC ; ; Signed (DEC) Signed (HEX) UNSigned ; -1 $FF $7F ; -2 $FE $7E ; . . ; . . ; -127 $81 $01 ; -128 $80 $00 ; +127 $7F $FF ; +126 $7E $FE ; . . ; . . ; +1 $01 $81 ; 0 $00 $80 ; REL2ABS CLR C ADDC A,#128 RET ; ; INVERSE QUANTIZATION FUNCTION ; INPUT IN ACC ; OUTPUT IN ACC ; INVQFN INC A ; TABLE INDEX 0 = RET, SO OFFSET BY 1 CJNE R3,#7,TRY6 NOP ;1 NOP ;2 NOP ;3 NOP ;4 NOP ;5 NOP ;6 NOP ;7 NOP ;8 NOP ;9 NOP ;10 LCALL IQBASE7 RET TRY6 CJNE R3,#6,TRY5 NOP ;1 NOP ;2 NOP ;3 NOP ;4 NOP ;5 NOP ;6 NOP ;7 NOP ;8 LCALL IQBASE6 RET TRY5 CJNE R3,#5,TRY4 NOP ;1 NOP ;2 NOP ;3 NOP ;4 NOP ;5 NOP ;6 LCALL IQBASE5 RET TRY4 CJNE R3,#4,TRY3 NOP ;1 NOP ;2 NOP ;3 NOP ;4 LCALL IQBASE4 RET TRY3 CJNE R3,#3,TRY2 NOP ;1 NOP ;2 LCALL IQBASE3 RET TRY2 CJNE R3,#2,TRY1 LCALL IQBASE2 RET TRY1 LCALL IQBASE1 RET IQBASE1 MOVC A,@A+PC RET .DB 0 .DB 1 .DB 2 .DB 3 .DB 4 .DB 5 .DB 6 .DB 7 .DB -8 ; 1111 1000 .DB -7 ; 1111 1001 .DB -6 ; 1111 1010 .DB -5 ; 1111 1011 .DB -4 ; 1111 1100 .DB -3 ; 1111 1101 .DB -2 ; 1111 1110 .DB -1 ; 1111 1111 IQBASE2 MOVC A,@A+PC RET .DB 0 .DB 1 .DB 2 .DB 3 .DB 4 .DB 6 .DB 8 .DB 12 .DB -13 .DB -10 .DB -7 .DB -5 .DB -4 .DB -3 .DB -2 .DB -1 IQBASE3 MOVC A,@A+PC RET .DB 0 .DB 1 .DB 2 .DB 3 .DB 6 .DB 9 .DB 15 .DB 24 .DB -26 .DB -17 .DB -11 .DB -7 .DB -5 .DB -3 .DB -2 .DB -1 IQBASE4 MOVC A,@A+PC RET .DB 0 .DB 1 .DB 2 .DB 4 .DB 7 .DB 12 .DB 21 .DB 36 .DB -38 .DB -23 .DB -14 .DB -9 .DB -5 .DB -3 .DB -2 .DB -1 IQBASE5 MOVC A,@A+PC RET .DB 0 .DB 1 .DB 2 .DB 4 .DB 8 .DB 14 .DB 26 .DB 47 .DB -49 .DB -29 .DB -17 .DB -10 .DB -6 .DB -4 .DB -2 .DB -1 IQBASE6 MOVC A,@A+PC RET .DB 0 .DB 1 .DB 3 .DB 5 .DB 10 .DB 19 .DB 36 .DB 69 .DB -72 .DB -41 .DB -23 .DB -13 .DB -7 .DB -4 .DB -2 .DB -1 IQBASE7 MOVC A,@A+PC RET .DB 0 .DB 1 .DB 3 .DB 6 .DB 11 .DB 23 .DB 45 .DB 90 .DB -95 .DB -52 .DB -28 .DB -15 .DB -8 .DB -5 .DB -2 .DB -1 ; ; SPEECH TABLE. *** MUST *** have the same order as CODE_TBL. ; 26+10+3+5=44 ENTRIES @ 4 BYTES EACH = 176 BYTES TOTAL. ; SPEECH.TXT is compiled from a text source file into a text ; assembler source file and a binary data file using SPCH_LIB.C ; SPCH_TBL #INCLUDE "SPEECH.TXT"