;
; DTMF GENERATION WITH A 3.58 MHZ      VERNE H. WILSON
;        CRYSTAL FOR COP820C/840C         10/28/89
;
; DTMF - DUAL TONE MULTIPLE FREQUENCY
;
; PROGRAM NAME: DTMF35.MAC  
;
; EDITTED MAY 11, 1994 - REVISED FOR NEW ASSEMBLER (ASMCOP v4.2) 

          .TITLE DTMF35
          .CHIP 840
          .SECT MAIN,ROM,ABS=0
;
;
; THIS DTMF PROGRAM IS BASED ON A COP820C/840C RUNNING
; WITH A CKI CLOCK OF 3.579545 MHZ (TV COLOR CRYSTAL
; FREQUENCY) IN DIVIDE BY 10 MODE, FOR AN INSTRUCTION
; CYCLE TIME OF 2.7936511 MICROSECONDS.
;
; THIS PROGRAM CONTAINS THREE SUBROUTINES, ONE FOR A
; LOW TRUE ROW/COLUMN DTMF KEYBOARD DECODING (KBRDEC),
; AND THE OTHER TWO (DTMFGP, DTMFLP) FOR ALTERNATE
; METHODS OF DTMF GENERATION.
;
; KEYBOARD INPUT DATA IS IN ACCUMULATOR WITH A
;    LOW TRUE FORMAT AS FOLLOWS:
;        BITS 7 TO 4 : LOW TRUE COLUMN VALUE (E,D,B,7)
;        BITS 3 TO 0 : LOW TRUE ROW VALUE (E,D,B,7)
;
; ASSUMPTION MADE THAT COLUMN STROBES (LOW TRUE) ARE
;    OUTPUT, WHILE ROW VALUES (LOW TRUE) ARE INPUT.
;
; THE FIRST METHOD OF DTMF GENERATION CONSISTS OF
; GENERATING TWO PWM OUTPUTS ON THE G PORT G2 AND G3
; OUTPUT PINS. THESE TWO OUTPUTS NEED TO BE MIXED
; EXTERNALLY WITH AN APPROPIATE LM324 OP AMP FEEDBACK
; CIRCUIT TO GENERATE THE DTMF.
;
; THE SECOND METHOD OF DTMF GENERATION USES ROM LOOKUP
; TABLES TO SIMULATE THE TWO DTMF SINE WAVES AND
; COMBINES THEM ARITHMETICALLY. THE RESULT IS OUTPUT ON
; THE LOWER SIX BITS OF THE L PORT (L0 - L5). THESE SIX
; OUTPUTS ARE COMBINED EXTERNALLY WITH A LADDER NETWORK
; TO GENERATE THE DTMF.
;
; THE SECOND DTMF GENERATION METHOD USES APPROXIMATELY
; THREE TIMES AS MUCH ROM CODE (INCLUDING PROGRAM CODE
; AND ROM TABLES) AS THE FIRST METHOD, BUT HAS THE 
; ADVANTAGE OF ELIMINATING THE COST OF THE EXTERNAL
; ACTIVE COMPONENT (LM324 OR EQUIVALENT).
;
; BOTH OF THE DTMF SUBROUTINES GENERATE THEIR OUTPUTS
; FOR A PERIOD OF 100 MILLISECONDS.
;
; DECLARATIONS:
;
          KDATA  = 0            ; *** KEYBOARD DATA ***
Š          PORTLD = 0D0          ; PORTL DATA REG       
          PORTLC = 0D1          ; PORTL CONFIG REG
          PORTGD = 0D4          ; PORTG DATA REG
          PORTGC = 0D5          ; PORTG CONFIG REG
           PORTI = 0D7          ; PORTI INPUT PINS
           PORTD = 0DC          ; PORTD REG
           TMRLO = 0EA          ; TIMER LOW COUNTER
           TMRHI = 0EB          ; TIMER HIGH COUNTER
           TAULO = 0EC          ; TMR AUTORELOAD REG LO
           TAUHI = 0ED          ; TMR AUTORELOAD REG HI
           CNTRL = 0EE          ; CONTROL REG
             PSW = 0EF          ; PROC STATUS WORD
              R0 = 0F0          ; LB FREQ LOOP COUNTER
              R1 = 0F1          ; LB FREQ LOOP COUNT
              R2 = 0F2          ; LB FREQ Q COUNT
              R3 = 0F3          ; LB FREQ R COUNT
;
START:    LD        SP,#02F     ; INITIALIZE STACK PTR
;
;                           KEYBOARD HEX DIGIT MATRIX
;                                    1  2  3  A
          LD        B,#PORTD  ;      4  5  6  B
          LD        [B],#0    ;      7  8  9  C
LOOP:     RC                  ;      *  0  #  D
          LD        A,[B]     ; DTMF TEST LOOP
          ADD       A,#5      ; SEQUENCE IS 1,5,9,D,4,
          X         A,[B]     ; 8,#,A,7,0,3,B,*,2,6,C
          RBIT      4,[B]     ; HEX MATRIX TO LOOKUP
          ADD       A,#020    ;    TABLE FOR LOW TRUE 
          LAID                ;    COLUMN/ROW INPUT TO
          JSR       KBRDEC    ;    KBRDEC SUBROUTINE
          SC                  ; SET C IF NOT SINGLE KEY
          LD        B,#PORTI  ; TEST BIT 0 OF PORTI TO
          IFBIT     0,[B]     ;    DETERMINE WHICH
          JP        BYPA      ;    DTMF SUBROUTIINE
          JSR       DTMFGP    ; TWO PWM OUTPUTS ON
          JP        BYPB      ;    G PORT PINS G2,G3
BYPA:     JSR       DTMFLP    ; SIX LADDER OUTPUTS ON
                              ;    L PORT PINS L0 - L5
BYPB:     LD        B,#PORTD  ; D0 WILL TOGGLE FOR EACH
          JP        LOOP      ;    CALL OF SUBROUTINE
;
;
;
               .FORM
;
; KEYBOARD DIGIT MATRIX TABLE
;
               . = 020
;
;                   1   5   9   D   4   8   #   A
          .BYTE    0EE,0DD,0BB,077,0ED,0DB,0B7,07E
;                   7   0   3   B   *   2   6   C
          .BYTE    0EB,0D7,0BE,07D,0E7,0DE,0BD,07B
;
Š;
;
;
; 
; FIRST DTMF SUBROUTINE (DTMFGP) PRODUCES TWO PWM
;     (PULSE WIDTH MODULATION) OUTPUTS ON PINS G3, G2
;
; 
; G PORT IS USED FOR THE TWO OUTPUTS
;     -    HIGH BAND (HB) FREQUENCY OUTPUT ON G3
;     -    LOW BAND (LB) FREQUENCY OUTPUT ON G2
;
; TIMER COUNTS OUT
;     -    HB FREQUENCIES 
;
; PROGRAM COUNTS OUT  
;     -    LB FREQUENCIES 
;     -    100 MSEC DIVIDED BY LB HALF PERIOD QUOTIENT
;     -    100 MSEC DIVIDED BY LB HALF PERIOD REMAINDER
;
; NOTE THAT ALL COUNTS MUST BE NORMALIZED TO THE
;     2.7936511 MICROSECOND INSTRUCTION CYCLE Tc
;
; 100 MSEC REPRESENTS 35796 Tc's
;
;
;
;
; HALF PERIODS FOR THE 8 DTMF FREQUENCIES (697,770,852,
;     941,1209,1336,1477, AND 1633 KHZ) ARE 257,232,
;     210,190,148,134,121, AND 110 Tc's RESPECTIVELY
;
; THE 100 MSEC DIVIDED BY HALF PERIOD QUOTIENTS ARE
;     139,154,170,188,241,267,295, AND 325 RESPECTIVELY
;
; THE 100 MSEC DIVIDED BY HALF PERIOD REMAINDERS ARE
;     72,67,95,75,127,17,100, AND 45 RESPECTIVELY
;
;          
;
; 
; BINARY FORMAT FOR THE HEX DIGIT KEY VALUE FROM THE
;    KBRDEC SUBROUTINE IS 0000RRCC,
;       WHERE  -  RR IS ROW SELECT (LB FREQUENCIES)
;              -  CC IS COLUMN SELECT (HB FREQUENCIES)
;
; FREQUENCY VECTORS (HB & LB) FOR FREQ PARAMETER TABLE
;    MADE FROM KEY VALUE
;                                                 
; HB FREQ VECTORS (4) END WITH 00 FOR TIMER COUNTS,
;    WHERE VECTOR FORMAT IS 0011CC00
;
; LB FREQUENCY VECTORS (12) END WITH:
;    11 FOR HALF PERIOD LOOP COUNTS, 
;         WHERE VECTOR FORMAT IS 0011RR11
Š;    10 FOR 100 MSEC DIVIDED BY HALF PERIOD QUOTIENTS,
;         WHERE VECTOR FORMAT IS 0011RR10
;    01 FOR 100 MSEC DIVIDED BY HALF PERIOD REMAINDERS,
;         WHERE VECTOR FORMAT IS 0011RR01
;              
; FREQ PARAMETER TABLE AT HEX 003*  (REQUIRED LOCATION)
;
;
;
;              KEY VALUE
;               0000RRCC
;
;    TIMER     T    CCOO
;    R1        F    RR11
;    R2        Q    RR10
;    R3        R    RR01
;
;
;                    
               .FORM
; 
;
;FREQUENCY AND 100 MSEC PARAMETER TABLE
;
          .BYTE     147            ; T
          .BYTE      10            ; R
          .BYTE     140            ; Q
          .BYTE      38            ; F
          .BYTE     133            ; T
          .BYTE       9            ; R
          .BYTE     155            ; Q
          .BYTE      33            ; F
          .BYTE     120            ; T
          .BYTE      14            ; R
          .BYTE     171            ; Q
          .BYTE      31            ; F
          .BYTE     109            ; T
          .BYTE      10            ; R
          .BYTE     189            ; Q
          .BYTE      26            ; F
;             
;
;
DTMFGP:   LD        B,#PORTGC   ; CONFIGURE G PORT
          LD        [B-],#03F   ;    FOR OUTPUTS
          RBIT      3,[B]       ; OPTIONAL HB RESET
          RBIT      2,[B]       ; OPTIONAL LB RESET
          LD        B,#KDATA
          X         A,[B]       ; STORE KEY VALUE
          LD        A,[B]       ; KEY VALUE TO ACC
          OR        A,#033      ; CREATE LB FREQ VECTOR
          LD        B,#R1       ;    FROM KEY VALUE
LUP:      X         A,[B]
          LD        A,[B]       ; THREE PARAMETERS
          LAID                  ;    FROM LOW BAND
Š          X         A,[B+]      ;    FREQ ROM TABLE
          DEC       A           ;    TO R1,R2,R3
          IFBNE     #4
          JP        LUP
          LD        B,#KDATA    
          LD        A,[B]       ; KEY VALUE TO ACC
          SWAP      A           ; CREATE HB FREQ VECTOR
          RC                    ;    FROM KEY VALUE
          RRC       A
          RRC       A
          OR        A,#030
          LAID                  ; HB FREQ TABLE
          LD        B,#TMRLO    ;   (1 PARAMETER)
          LD        [B+],#15    ; INSTRUCTION CYCLE
          LD        [B+],#0     ;   TIME UNTIL TOGGLE
          X         A,[B+]      ; HB FREQ PARAMETER TO
          LD        [B+],#0     ;   AUTORELOAD REGISTER
          LD        [B],#0B0    ; START TIMER PWM
          LD        B,#PORTGD
          LD        X,#R1
LUP1:     LD        A,[X-]
          IFBIT     2,[B]       ; TEST LB OUTPUT
          JP        BYP1
          X         A,[X+]
          SBIT      2,[B]       ; SET LB OUTPUT
          JP        BYP2
BYP1:     NOP
          RBIT      2,[B]       ; RESET LB OUTPUT
          X         A,[X+]
BYP2:     DRSZ      R2          ; DECR. QUOT. COUNT
          JP        LUP2 
          JP        FINI        ; Q COUNT FINISHED
LUP2:     DRSZ      R0          ; DECR. F COUNT
          JP        LUP2        ; LB (HALF PERIOD)
;
          LD        A,[X]       ; ******************
          IFEQ      A,#31       ; BALANCE        ***
          JP        LUP1        ; LOW BAND       ***
          NOP                   ; FREQUENCY      ***   
          NOP                   ; RESIDUE        ***
          IFEQ      A,#38       ; DELAY FOR      ***
          JP        LUP1        ; EACH OF THE    ***
          LAID                  ; FOUR LOW BAND  ***
          NOP                   ; FREQUENCIES    ***
          JP        LUP1        ; ******************
FINI:     DRSZ      R3        ; DECR. REMAINDER COUNT
          JP        FINI      ; REM. COUNT NOT FINISHED
          RBIT      4,CNTRL   ; STOP TIMER
          RBIT      3,[B]     ; OPTIONAL CLR HB OUTPUT
          RBIT      2,[B]     ; OPTIONAL CLR LB OUTPUT
          RET                 ; RETURN FROM SUBROUTINE
;
;
;
          .FORM
Š;
; SECOND DTMF SUBROUTINE (DTMFLP) PRODUCES SIX
;     COMBINED LOW BAND AND HIGH BAND FREQUENCY
;     SINE WAVE OUTPUTS ON PINS L0 - L5
;
; SIX L PORT OUTPUTS (L0 - L5) FEED INTO AN EXTERNAL
; RESISTOR LADDER NETWORK TO CREATE THE DTMF OUTPUT.
;
; FOUR VALUES FROM A KEYBOARD ROM TABLE ARE LOADED
; INTO LFTBSZ (LOW FREQ TABLE SIZE), LFTADR (LOW
; FREQ TABLE ADDRESS), HFTBSZ (HIGH FREQ TABLE SIZE),
; AND HFTADR (HIGH FREQ TABLE ADDRESS).
;
; LUP42 USES THE LFPTR (LOW FREQ POINTER) AND HFPTR
; (HIGH FREQ POINTER) TO ACCESS THE SINE DATA TABLES
; FOR THE SELECTED FREQUENCIES ONCE PER LOOP. THESE
; POINTERS ARE BOTH INCREMENTED ONCE PER LUP42.
;
; LUP42 PROGRAM LOOP UPDATES THE OUTPUT VALUE EVERY
; 117 1/3 uSEC BY SELECTING AND THEN COMBINING NEW
; VALUES FROM THE SELECTED LOW BAND AND HIGH BAND
; FREQUENCY ROM TABLES WHICH SIMULATE THE SINE WAVES
; FOR THE TWO FREQUENCIES.
;
; MULTIPLES OF THE MAGIC NUMBER OF APPROXIMATELY
; 118 uSEC ARE CLOSE APPROXIMATIONS TO ALL EIGHT OF
; THE DTMF FREQUENCIES.
;
; COP820C/840C TIMER USED TO INTERRUPT THE DTMF LUP42
; PROGRAM LOOP AFTER 100 MSEC TO FINISH THE DTMF
; OUTPUT AND RETURN FROM THE DTMFLP SUBROUTINE. NOTE
; THAT THE STACK POINTER (SP) MUST BE ADJUSTED AFTER
; THE INTERRUPT BEFORE RETURNING FROM THE SUBROUTINE.
;
;
;
;
;
; DECLARATIONS:
; 
          LFPTR   =  05            ; LOW FREQ POINTER
          TEMP    =  06            ; TEMPORARY
          HFPTR   =  07            ; HIGH FREQ POINTER
          LFTBSZ  =  08            ; LO FREQ TABLE SIZE
          LFTADR  =  09            ; LO FREQ TABLE ADDR
          HFTBSZ  =  0A            ; HI FREQ TABLE SIZE
          HFTADR  =  0B            ; HI FREQ TABLE ADDR
;
          TRUN    =  04  
;
;
DTMFLP:   LD        PORTLC,#0FF    ; INITIALIZE PORT L
          LD        PORTLD,#29     ;    FOR NO TONE OUT
          LD        LFPTR,#0       ; INITIALIZE OFFSET
          LD        B,#HFPTR       ;    POINTERS FOR
Š          LD        [B+],#0        ;    DTMF SINE WAVE
          RC                       ;    TABLE LOOKUP
          SWAP      A              ; QUADRUPLE KEY
          RRC       A              ;    VALUE AND ADD
          RRC       A              ;    OFFSET FOR KEY
          ADD       A,#0B8         ;    TABLE LOOKUP
FRLUP:    X         A,[B]          ; LOAD FOUR VALUES
          LD        A,[B]          ;    FROM ROM KEY
          LAID                     ;    TABLE INTO LOW
          X         A,[B+]         ;    FREQ LFTBSZ,
          INC       A              ;    LFTADR, AND HI
          IFBNE     #0C            ;    FREQ HFTBSZ,
          JP        FRLUP          ;    HFTADR
          LD        B,#TMRLO       ; INITIALIZE TIMER
          LD        [B+],#0        ;    WITH A tC COUNT
          LD        [B+],#140      ;    EQUIVALENT TO
          LD        [B+],#0        ;    100 MSEC PLUS  
          LD        [B+],#140      ;    A LUP42 TIME
          LD        [B+],#080      ; TIMER PWM, NO OUT
          LD        [B-],#011      ; ENABLE TMR INTRPT
          SBIT      TRUN,[B]       ; START TIMER
          JMP       LUP42         
;            
;
;          
;
; TELEPHONE KEY TABLE:
;
;    TABLE FORMAT:
;         PARAMETER 1:  # 0F LOW FREQ TABLE VALUES 
;         PARAMETER 2:  BASE ADDR. OF LOW FREQ VALUES
;         PARAMETER 3:  # OF HIGH FREQ TABLE VALUES 
;         PARAMETER 4:  BASE ADDR. OF HIGH FREQ VALUES
;
; KEY 1
          .BYTE     49,02D,7,07C
;
; KEY 2
          .BYTE     49,02D,19,083
;
; KEY 3
          .BYTE     49,02D,23,096
;
; KEY A
          .BYTE     49,02D,21,0AD
;
; KEY 4
          .BYTE     11,05E,7,07C
;
; KEY 5
          .BYTE     11,05E,19,083
;
; KEY 6
          .BYTE     11,05E,23,096
;
Š; KEY B
          .BYTE     11,05E,21,0AD
;
; KEY 7
          .BYTE     10,069,7,07C
;
; KEY 8
          .BYTE     10,069,19,083
;
; KEY 9
          .BYTE     10,069,23,096 
;
; KEY C
          .BYTE     10,069,21,0AD
;
; KEY *
          .BYTE     9,073,7,083
;
; KEY 0
          .BYTE     9,073,19,07C
;
; KEY #
          .BYTE     9,073,23,096
;
; KEY D
          .BYTE     9,073,21,0AD  
;
;
;
;            
          .=00FF
;
INTRPT:   LD        PORTLD,#29     ; BASE LINE VALUE
          LD        B,#PSW         ; 100 MSEC INTERRUPT
          LD        [B-],#0        ;    FROM TIMER
          LD        [B],#0         ; CLR PSW AND CNTRL
          LD        B,#SP          ; RESTORE STACK
          LD        A,[B]          ;    POINTER (SP)
          INC       A              ;    TO ITS VALUE
          INC       A              ;    BEFORE THE
          X         A,[B]          ;    INTERRUPT
          RET                      ; RETURN FROM 
                                   ;    SUBROUTINE
;
;
          .FORM
;
; LUP42 CONSISTS OF 42 COP840C INSTRUCTION CYCLE TIMES
; LUP42 TIMING LOOP IS 42 / 0.3579545 = 117 1/3 uSEC
;
;
LUP42:    LD        B,#LFPTR      
          LD        A,[B]          ; INCREMENT LOW FREQ
          INC       A              ;    OFFSET POINTER
          LD        B,#LFTBSZ      ; TEST IF LFPTR
Š          IFEQ      A,[B]          ;    BEYOND LIMIT
          CLR       A              ; REINITIALIZE LFPTR
          LD        B,#LFPTR       ;    FOR NEXT TIME
          X         A,[B]
          LD        B,#LFTADR      ; ADD PTR TO LO FREQ
          ADD       A,[B]          ;    TABLE ADDRESS
          LAID                     ; LOW FREQ COMPONENT
          LD        B,#TEMP        ; RESULT TO TEMP
          X         A,[B+]
          LD        A,[B]          ; INCREMENT HI FREQ
          INC       A              ;    OFFSET POINTER
          LD        B,#HFTBSZ      ; TEST IF HFPTR
          IFEQ      A,[B]          ;    BEYOND LIMIT
          CLR       A              ; REINITIALIZE HFPTR
          LD        B,#HFPTR       ;    FOR NEXT TIME
          X         A,[B]
          LD        B,#HFTADR      ; ADD PTR TO HI FREQ
          ADD       A,[B]          ;    TABLE ADDRESS
          LAID                     ; HI FREQ COMPONENT
          LD        B,#TEMP        ; ADD LOW FREQ VALUE
          ADD       A,[B]          ;   TO HI FREQ VALUE
          X         A,PORTLD       ; RESULT TO PORT L
          LAID                     ; EQUIVALENT OF
          LAID                     ;    SIX NOP'S
          JP        LUP42          ; TIMING LOOP OF 
                                   ;    117 1/3 uSEC 
;
;
;
;
          .FORM
;
; THE FREQUENCY APPROXIMATION IS EQUAL TO THE NUMBER OF
; CYCLES OF SINE WAVE DIVIDED BY THE TIME IN THE TOTAL
; NUMBER OF LUP42 CYCLES BEFORE THE REPETITION OF THE
; ROM TABLE. AS AN EXAMPLE, CONSIDER THE THREE CYCLES
; OF SINE WAVE AND 19 VALUES IN THE ASSOCIATED 1336 HZ
; ROM TABLE. THE 19 CYCLES OF LUP42 TIMES THE LUP42
; TIME OF 117 1/3 uSEC IS DIVIDED INTO THE THREE CYCLES
; OF SINE WAVE TO YIELD A VALUE OF 1345.69 HZ AS THE
; 1336 HZ APPROXIMATION.
;
; THE VALUES IN THE ROM TABLES FOR THE DTMF SINE WAVES
; SHOULD WRAP AROUND END TO END IN EITHER DIRECTION TO
; FORM A SYMETRICAL LOOP. THE FIRST VALUE IN THE ROM
; TABLE REPRESENTS THE BASE LINE FOR THAT FREQUENCY.
;
; THE HIGH BAND DTMF FREQUENCIES HAVE A BASE LINE VALUE
; OF 16 AND A MAXIMUM VALUE OF 32. THE LOW BAND DTMF 
; FREQUENCIES HAVE A BASE LINE VALUE OF 13 AND A 
; MAXIMUM VALUE OF 26. THIS DIFFERENCE IN BASE LINE
; VALUES IS NECESSARY TO SATISFY THE REQUIREMENT OF THE
; HIGH BAND FREQUENCIES NEEDING A LEVEL 2 dB ABOVE THE 
; LEVEL OF THE LOW BAND FREQUENCIES TO COMPENSATE FOR
; LOSSES IN TRANSMISSION. THE SUM OF THE TWO BASE LINE
Š; VALUES YIELDS A BASE LINE VALUE OF 29, WHILE THE SUM
; OF THE TWO MAXIMUM VALUES YIELDS A MAXIMUM VALUE OF
; 58. THUS THE SIX BIT DTMF OUTPUT FROM THE L PORT TO
; THE LADDER NETWORK RANGES FROM 0 TO 58, WITH A BASE
; LINE VALUE OF 29.
;
; THE VALUES IN THE DTMF SINE WAVE TABLES ARE 
; CALCULATED BY COMPUTING THE SINE VALUE AT THE
; APPROPIATE POINTS, SCALING THE SINE VALUE UP TO THE 
; BASE LINE VALUE, AND THEN ADDING THE RESULT TO THE
; BASE LINE VALUE. THE FOLLOWING EXAMPLE WILL HELP TO
; CLARIFY THIS CALCULATION.
;
; CONSIDER THE THREE CYCLES OF SINE WAVE ACROSS 19 
; DATA POINTS FOR THE 1336 HZ DTMF HIGH BAND FREQUENCY.
; THE FIRST VALUE IN THE TABLE IS THE BASE LINE VALUE
; OF 16. WITH 2 PI RADIANS PER SINE WAVE CYCLE,
; THE SUCCEEDING VALUES IN THE TABLE REPRESENT THE
; SINE VALUES OF 1 X (6 PI / 19), 2 X (6 PI / 19),
; 3 X (6 PI / 19), . . . . , UP TO 18 X (6 PI / 19).
; LET US NOW CONSIDER THE SEVENTH AND EIGHTH VALUES
; IN THE TABLE, REPRESENTING THE SINE VALUES OF
; 6 X (6 PI / 19) AND 7 X (6 PI / 19) RESPECTIVELY.
; THE CALCULATIONS OF 16 X SIN [6 X (6 PI / 19)] AND
; 16 X SIN [7 X (6 PI / 19)] YIELD VALUES OF - 5.20 AND
; 9.83 RESPECTIVELY. ROUNDED TO THE NEAREST INTEGER 
; GIVES VALUES OF - 5 AND 10. WHEN ADDED TO THE BASE
; LINE VALUE OF 16, THESE VALUES YIELD THE RESULTS
; 11 AND 26 FOR THE SEVENTH AND EIGHTH VALUES IN THE 
; 1336 HZ DTMF TABLE. SYMMETRY IN THE LOOP OF 19 VALUES
; IN THE DTMF TABLE DICTATES THAT THE FOURTEENTH AND
; THIRTEENTH VALUES IN THE TABLE ARE 21 AND 6,
; REPRESENTING VALUES OF 5 AND - 10 FROM THE
; CALCULATIONS.  
;
; THE AREA UNDER A HALF CYCLE OF SINE WAVE RELATIVE TO
; THE AREA OF THE SURROUNDING RECTANGLE IS 2/PI, WHERE
; PI RADIANS REPRESENT THE SINE WAVE HALF CYCLE. THIS
; SURROUNDING RECTANGLE HAS A LENGTH OF PI AND A HEIGHT
; OF 1, WITH THE HEIGHT REPRESENTING THE MAXIMUM SINE
; VALUE. CONSEQUENTLY, THE AREA OF THIS SURROUNDING   
; RECTANGLE IS PI. THE INTEGRAL OF THE AREA UNDER THE
; HALF SINE WAVE FROM 0 TO PI IS EQUAL TO 2. THE RATIO
; OF 2/PI IS EQUAL TO 63.66 % , SO THAT THE TOTAL OF
; THE VALUES FOR EACH HALF SINE WAVE SHOULD APPROXIMATE
; 63.66 % OF THE SUM OF THE MAX VALUES. THE MAXIMUM 
; VALUES (RELATIVE TO THE BASE LINE) ARE 13 AND 16
; RESPECTIVELY, FOR THE LOW AND HIGH BAND FREQUENCIES.
;  
;
;
; 
;
; LF697:   4 CYCLES OF SINE WAVE SPREAD
;                  ACROSS 49 TIMING LOOP (LUP42) CYCLES
Š;
;          FREQ. = 4 / (49 X 117 1/3) = 695.73 HZ
;          ERROR = (697 - 695.73) / 697  = - 0.18 %
;        
          .BYTE     13,19,24,26,25,20,14,7,2,0
          .BYTE     1,5,11,18,23,26,25,21,15,9
          .BYTE     3,0,1,4,10,16,22,25,26,23
          .BYTE     17,11,5,1,0,3,8,15,21,25   
          .BYTE     26,24,19,12,6,1,0,2,7
;
;
; LF770:   1 CYCLE OF SINE WAVE SPREAD
;                  ACROSS 11 TIMING LOOP (LUP42) CYCLES
;
;          FREQ. = 1 / (11 X 117 1/3) = 774.79 HZ
;          ERROR = (774.79 - 770) / 770  = + 0.62 %
; 
          .BYTE     13,20,25,26,23,17,9,3,0,1 
          .BYTE     6     
;
;
; LF852:   1 CYCLE OF SINE WAVE SPREAD
;                  ACROSS 10 TIMING LOOP (LUP42) CYCLES
;
;          FREQ. = 1 / (10 X 117 1/3) = 852.27 HZ
;          ERROR = (852.27 - 852) / 852  = + 0.03 %
;               
          .BYTE     13,21,25,26,21,13,5,1,0,5  
;
;
; LF941:   1 CYCLE OF SINE WAVE SPREAD
;                  ACROSS 9 TIMING LOOP (LUP42) CYCLES
;
;          FREQ. = 1 / (9 X 117 1/3) = 946.97 HZ
;          ERROR = (946.97 - 941) / 941  = + 0.63 %
; 
          .BYTE     13,21,26,24,18,8,2,0,5   
;
;
;
; HF1209:  1 CYCLE OF SINE WAVE SPREAD
;                  ACROSS 7 TIMING LOOP (LUP42) CYCLES
;
;          FREQ. = 1 / (7 X 117 1/3) = 1217.53 HZ
;          ERROR = (1217.53 - 1209) / 1209  = + 0.71 %
; 
          .BYTE     16,29,32,23,9,0,3          
;
;
; HF1336:  3 CYCLES OF SINE WAVE SPREAD
;                  ACROSS 19 TIMING LOOP (LUP42) CYCLES
;
;          FREQ. = 3 / (19 X 117 1/3) = 1345.69 HZ
;          ERROR = (1345.69 - 1336) / 1336  = + 0.73 %
; 
Š          .BYTE     16,29,31,19,4,0,11,26,32,24
          .BYTE     8,0,6,21,32,28,13,1,3
;
;
; HF1477:  4 CYCLES OF SINE WAVE SPREAD
;                  ACROSS 23 TIMING LOOP (LUP42) CYCLES
;
;          FREQ. = 4 / (23 X 117 1/3) = 1482.21 HZ
;          ERROR = (1482.21 - 1477) / 1477  = + 0.35 %
; 
          .BYTE     16,30,29,14,1,4,20,32,26,10
          .BYTE     0,8,24,32,22,6,0,12,28,31
          .BYTE     18,3,2             
;
;
; HF1633:  4 CYCLES OF SINE WAVE SPREAD
;                  ACROSS 21 TIMING LOOP (LUP42) CYCLES
;
;          FREQ. = 4 / (21 X 117 1/3) = 1623.38 HZ
;          ERROR = (1633 - 1623.38) / 1633  = - 0.59 %
;
          .BYTE     16,31,27,9,0,11,29,30,14,0
          .BYTE     7,25,32,18,2,3,21,32,23,5
          .BYTE     1
;
;
;
          .FORM
;
; DTMF KEYBOARD DECODE SUBROUTINE (KBRDEC) 
;     
; KEYBOARD INPUT DATA IS IN ACCUMULATOR WITH A
;    LOW TRUE FORMAT AS FOLLOWS:
;        BITS 7 TO 4 : LOW TRUE COLUMN VALUE (E,D,B,7)
;        BITS 3 TO 0 : LOW TRUE ROW VALUE (E,D,B,7)
;
; ASSUMPTION MADE THAT COLUMN STROBES (LOW TRUE) ARE
;    OUTPUT, WHILE ROW VALUES (LOW TRUE) ARE INPUT. 
;
; LOW TRUE COLUMN/ROW INPUT DIGIT IN ACCUMULATOR IS
;     TRANSFORMED INTO A DTMF HEX DIGIT KEY VALUE
;
; TABLE LOOKUP TRANSFORMATION CHECKS FOR MULTIPLE KEYS,
;     NO KEY, OR NO COLUMN SELECT, AND THEN PRODUCES
;     A DTMF HEX DIGIT KEY VALUE WITH A BINARY FORMAT
;     OF 0000RRCC FOR A SINGLE KEY INPUT,
;     WHERE   -  RR IS LOW BAND (LB) FREQUENCY SELECT
;             -  CC IS HIGH BAND (HB) FREQUENCY SELECT
;
; KBRDEC SUBROUTINE IS EXITED WITH A RETURN (RET)
;     COMMAND TO INDICATE MULTIPLE KEYS, NO KEY,
;     OR NO COLUMN SELECT  
;
; KBRDEC SUBROUTINE IS EXITED WITH A RETURN AND SKIP
;     (RETSK) COMMAND TO INDICATE A SINGLE KEY ENTRY
Š;
;
          .=0200
;
; LOW TRUE TRANSLATION TABLE  - ONLY E,D,B,7 ACCEPTABLE
;
          .BYTE  0C0,0C0,0C0,0C0,0C0,0C0,0C0,0C
          .BYTE  0C0,0C0,0C0,8,0C0,4,0,0C0
;
;
KBRDEC:   LD        B,#KDATA   
          X         A,[B]    ; STORE LOW TRUE
          LD        A,[B]    ;   COLUMN/ROW VALUE
          AND       A,#0F0   ; EXTRACT LOW TRUE COLUMN
          SWAP      A        ;   & PUT IN LOWER NIBBLE
          LAID               ; 0000CC00 FROM TABLE
          RC                 ; SHIFT TABLE VALUE DOWN
          RRC       A        ;   TWO BITS TO PRODUCE
          RRC       A        ;   000000CC
          X         A,[B]    ; STORE RESULT
          AND       A,#0F    ; EXTRACT LOW TRUE ROW
          LAID               ; 0000RR00 FROM TABLE 
          ADD       A,[B]    ; ADD TO PRODUCE 0000RRCC
          IFGT      A,#0F    ; RETURN IF MULTIPLE KEYS,
          RET                ;    NO KEYS, OR NO COLUMN
          RETSK              ; RETURN AND SKIP 
                             ;    IF SINGLE KEY 
;              
;
;
          .END
