Regulus Berdin's  PIC DTMF Encoder

;********************************************************************** 
;DTMF GENERATION 
; by Regulus Berdin 
; W holds the key to send 
; 10-A  11-B  12-C  13-D  14-*  15-# 
; uses 18 cycles per count optimized for 4MHz crystal 
; 
;DTMF                           ERROR 
;TONE   DELAY   TONE GENERATED  (Hx)    % 
;697    40      694.4444444     2.56    0.37 
;770    36      771.6049383     1.60    0.21 
;852    33      841.7508418     10.25   1.20 
;941    30      925.9259259     15.07   1.60 
;1209   23      1207.729469     1.27    0.11 
;1336   21      1322.751323     13.25   0.99 
;1477   19      1461.988304     15.01   1.02 
;1633   17      1633.986928     0.99    0.06 
        cblock  LASTVAR 
                lowcnt 
                highcnt 
                slowcnt 
                shighcnt 
                hdcnt 
                ldcnt 
        endc 

tlowcnt 
        addwf   PCL,f 
        dt      30, 40, 40, 40 
        dt      36, 36, 36, 33 
        dt      33, 33, 40, 36 
        dt      33, 30, 30, 30 

thighcnt 
        addwf   PCL,f 
        dt      21, 23, 21, 19 
        dt      23, 21, 19, 23 
        dt      21, 19, 17, 17 
        dt      17, 17, 23, 19 

dtmfsend: 
        andlw   0x0f 
        movwf   tmp 
        call    tlowcnt 
        movwf   slowcnt 
        movwf   lowcnt 

        movf    tmp,w 
        call    thighcnt 
        movwf   shighcnt 
        movwf   highcnt 

        clrf    ldcnt 
;       movlw   .22                     ;adjust here for delay 
        movlw   MTXLENGTH 
        call    EE_read 
        addlw   1 
        movwf   hdcnt                   ;approx. 100 ms 

dloop0  clrwdt                          ;2 
        nop                             ; 
dloop   movlw   (DHI_PIN + DLOW_PIN) 
        decfsz  lowcnt,f 
         andlw  DHI_PIN 
        decfsz  highcnt,f 
         andlw  DLOW_PIN 
        movwf   tmp 
        xorwf   PORTB,f 

        movf    slowcnt,w 
        btfsc   tmp,0 
         movwf  lowcnt 

        movf    shighcnt,w 
        btfsc   tmp,1 
         movwf  highcnt                 ;13 

        IF      DTMFTESTING 
        nop 
        goto    dloop0 
        ENDIF 

        decfsz  ldcnt,f                 ;2/1 
         goto   dloop0                  ;2 
        decfsz  hdcnt,f                 ;2/1 
         goto   dloop                   ;2      ;5 

        return 

This routine uses 2 pic pins for high and low tones.  Just add 2 stage 
low pass filters the each of the pins and combine both.  This works well 
and has a low error less than dtmf receiver specs.