pic12C508 DTMF dialer

Publisher:不染尘埃Latest update time:2017-12-04 Source: eefocusKeywords:pic12C508  DTMF Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

p IC 12C508 DTMF Dialer
; | Name: MAIN.ASM |

; | Description:  DTMF -> RS232 converter (for use with PC NummerViser)| 
; |               Detects DTMF and ringing, and transmits to a std.    | 
; |               RS232 port, at 2400 baud.                            | 
; |                                                                    |                                            |
; +--------------------------------------------------------------------+ 
; | Platform:     PIC12C508(A) (using internal 4MHz RC-oscillator)     | 
; | Uses:         90-342W/512W program-mem (all ’switches’ set to 0/1) | 
; |               6B/25B data-mem                                      | 
; | Assembler:      MPASM 2.20 (MPLAB 4.00.00)                           | 
; | Comments:     -                                                    | 
; +====================================================================+ 

    TITLE        ’DTMF to RS232 converter’ 

    PROCESSOR    12C508 

     __CONFIG    _CP_OFF & _MCLRE_OFF & _IntRC_OSC & _WDT_ON 
    INCLUDE         

    RADIX        DEC 
    __IDLOCS    h’0104’ 


OTP    SET    1    ;Use factory-stored cal.-value (on OneTimeProgrammable) 

TMR0CLK    SET    1    ;Use TMR0 external clock at 3,579545MHz (instead of IntRC). 
PARITY    SET    1    ;Use even parity-bit when transmitting to the serial port. 
CLIONLY    SET    1    ;Transmits CLI (A-numbers) only. 
RING    SET    1    ;Transmits ringing. 
IDENTTX    SET    1    ;Transmits ’ident’ when pressing ’***’ (DTMF). 
PWRUPID    SET    1    ;Transmits short ’ident’ at powerup. 
ASCII    SET    1    ;Transmits ASCII-chars instead of binary: 
            ;Digit    ASCII    Binary        Digit    ASCII    Binary 
            ;0    0 (48d)    00000000    9    9 (57d)    00001001 
            ;1    1 (49d)    00000001    A    A (65d)    00001010 
            ;2    2 (50d)    00000010    B    B (66d)    00001011 
            ;3    3 (51d)    00000011    C    C (67d)    00001100 
            ;4    4 (52d)    00000100    D    D (68d)    00001101 
            ;5    5 (53d)    00000101    *    * (42d)    00001110 
            ;6    6 (54d)    00000110    #    # (35d)    00001111 
            ;7    7 (55d)    00000111    Ring    R (82d)    00010000 
            ;8    8 (56d)    00001000 


;---+++***  Constants  ***+++--- 

    IF    TMR0CLK == 0        ;Internal oscillator 
OPTION_REG    equ b’10000001’        ;’Default’ timer/prescaler setup 
    ENDIF 

    IF    TMR0CLK == 1        ;External TMR0 source (3,579545MHz) 
OPTION_REG    equ b’10100011’        ;’Default’ timer/prescaler setup 
    ENDIF 

#define    DTMF0    GPIO, 0            ;Bit0 (LSB) from MT8870 
#define    DTMF1    GPIO, 1            ;Bit1 from MT8870 
#define    DTMF2    GPIO, 3            ;Bit2 from MT8870 / _Ring-detector 
#define DTMF3    GPIO, 4            ;Bit3 from MT8870 / TxD-output (high = sPACe) 
#define    DTMFOK    GPIO, 5            ;DTMF detected, and ready at DTMF0-3 


;---+++***  Variable declaration  ***+++--- 
    cblock    0Ch 
     DTMFval 
     identval 
     misc 
     temp1, temp2, teMP3        ;Temp-variables 
    endc 

#define    CLIP    misc, 0            ;Set when CLIP detected 
#define    CLIPend    misc, 1            ;Set by CLIPdet when # received 
#define    IdentOK    misc, 2            ;Set when ’ident’ detected (***) 


;---+++***  Reset vector  ***+++--- 
    ORG    0h 
rst_vector: 
    MOVwf    OSCCAL            ;Set oscillator calibration. 

    call    init 

    IF    PWRUPID == 1 
     goto    pwrupident 
pwrupidentreturn: 
    ENDIF 

    goto    main 



;---+++***  Identity (located ’low’ because of no CP < 64b)  ***+++--- 
identtable: 
    IF    IDENTTX == 1 
     addwf    PCL, F 
     dt    " +++ PC NummerViser +++ ", 13 
     dt    "     Firmware v1.04     ", 13, 13 
     dt    "  JaCOB BlichfELDt ’98  ", 13, 13, 13, 0 
    ENDIF 

pwrupidenttable: 
    IF    PWRUPID == 1 
     addwf    PCL, F 
     dt    "DTMFTORS232", 60, "0104", 62, 0 
    ENDIF 


;---+++***  Initialization  ***+++--- 
init: 
; Setup I/O-direction (GP0-3, 5 = input, GP4 = output) 
    MOVlw    b’11101111’ 
    tris    GPIO 

; TxD = Space (GP4 = low) 
    MOVlw    b’00000000’ 
    MOVwf    GPIO 

; Enable port B pull-up, dISAble wake-up on PIN change 
; Setup T0 = inc. on either OSC. or TMR0, prescaler = 4/16 (depends on TMR0CLK) 
    clrwdt 
    MOVlw    OPTION_REG 
    option 

    clrf    misc 
    clrf    identval 

    retlw    0 


;---+++***  Power-up identity transmission  ***+++--- 
    IF    PWRUPID == 1 
pwrupident: 

     MOVlw    4                ;wait approx. 1 second 
     MOVwf    temp3 
pwrup11: clrf    temp2 
pwrup12     clrf    temp1 
pwrup13: clrwdt 
     decfsz    temp1, F 
     goto    pwrup13 
     decfsz    temp2, F 
     goto    pwrup12 
     decfsz    temp3, F 
     goto    pwrup11 

     MOVlw    h’0FF’ 
     MOVwf    temp3 
pwrup2:     clrwdt 
     incf    temp3, F 
     MOVf    temp3, W 

     call    pwrupidenttable            ;Fetch text 

     clrf    temp2 
     subwf    temp2, F 
     btfsc    STATUS, Z            ;End of table? 
     goto    pwrupend 
     call    txser 
     goto    pwrup2 

pwrupend: 
     goto    pwrupidentreturn 
    ENDIF 


;---+++***  Main  ***+++--- 
main:    goto    DTMFdet 
DTMFdetreturn: 
    goto    ringdet 
ringdetreturn: 
    goto    main            ;Repeat main 


; Read DTMF-bits from 8870, converts to nibble, and returns in W. 
readDTMF: 
    MOVf    GPIO, W 
    andlw    b’00000011’            ;Get bit0-1 
    MOVwf    DTMFval 

    bsf    DTMFval, 2            ;Get bit 2 
    btfss    DTMF2 
    bcf    DTMFval, 2 

    MOVlw    b’11111111’            ;Get bit 3 (DTMF3 = input) 
    bcf    DTMFval, 3 
    tris    GPIO 
    MOVlw    b’11101111’ 
    btfsc    DTMF3 
    bsf    DTMFval, 3 
    tris    GPIO                ;DTMF3 = Output 
    bcf    DTMF3 

    MOVf    DTMFval, W            ;Convert from 8870 -> ’normal’ 
    andlw    b’00001111’ 
    call    DTMFtable 
    MOVwf    DTMFval 
    retlw    0 

DTMFtable: 
    addwf    PCL, F 
    retlw    b’00001101’            ;DTMF ’D’ 
    retlw    b’00000001’            ;DTMF ’1’ 
    retlw    b’00000010’            ;DTMF ’2’ 
    retlw    b’00000011’            ;DTMF ’3’ 
    retlw    b’00000100’            ;DTMF ’4’ 
    retlw    b’00000101’            ;DTMF ’5’ 
    retlw    b’00000110’            ;DTMF ’6’ 
    retlw    b’00000111’            ;DTMF ’7’ 
    retlw    b’00001000’            ;DTMF ’8’ 
    retlw    b’00001001’            ;DTMF ’9’ 
    retlw    b’00000000’            ;DTMF ’0’ 
    retlw    b’00001110’            ;DTMF ’*’ 
    retlw    b’00001111’            ;DTMF ’#’ 
    retlw    b’00001010’            ;DTMF ’A’ 
    retlw    b’00001011’            ;DTMF ’B’ 
    retlw    b’00001100’            ;DTMF ’C’ 


; Converts received DTMF to ASCII (returns in W) 
conASCII: 
    IF    ASCII == 1 
     addwf    PCL, F 
     retlw    A’0’ 
     retlw    A’1’ 
     retlw    A’2’ 
     retlw    A’3’ 
     retlw    A’4’ 
     retlw    A’5’ 
     retlw    A’6’ 
     retlw    A’7’ 
     retlw    A’8’ 
     retlw    A’9’ 
     retlw    A’A’ 
     retlw    A’B’ 
     retlw    A’C’ 
     retlw    A’D’ 
     retlw    A’*’ 
     retlw    A’#’ 
    ENDIF 


; Tests for 3 subsequent ’*’. 
ident:     
    IF     IDENTTX == 1 
     bcf    IdentOK 
     MOVlw    b’00001110’            ;DTMF ’*’ 
     subwf    DTMFval, W 
     btfss    STATUS, Z 
     goto    ident1 
     incf    identval, F 

     MOVlw    d’3’ 
     subwf    identval, W 
     btfss    STATUS, Z 
     goto    identend 
     bsf    IdentOK 
ident1:     clrf    identval 

identend: 
     retlw    0 
    ENDIF 


; Transmits W at 2400bps/std. RS232. Calculates parity-bit. Returns when done. 
txser:     
    MOVwf    temp1 

    bcf    STATUS, C            ;Transmit start-bit 
    call    txcarry 

    MOVlw    d’8’                ;Transmit 8 databits 
    MOVwf    temp2 
txbits:    clrwdt 
    rrf    temp1, F 
    call    txcarry 
    decfsz    temp2, F 
    goto    txbits 

    IF    PARITY == 1 
     rrf    temp1, F            ;calculate parity (even) 
     swapf    temp1, W 
     xorwf    temp1, W 
     MOVwf    temp1 
     rrf    temp1, F 
     rrf    temp1, F 
     xorwf    temp1, F 
     rrf    temp1, W 
     xorwf    temp1, F 
     bcf    STATUS, C 
     btfsc    temp1, 0 
     bsf    STATUS, C 
     call    txcarry 
    ENDIF 

    bsf    STATUS, C            ;Transmit 2*stop-bit 
    call    txcarry 
    bsf    STATUS, C 
    call    txcarry 
     
    retlw    0 

;transmit carry-flag 
    IF    TMR0CLK == 0 
txcarry:MOVlw    (256-104)            ;2400 = 416,666us = 1666,666c/16 = 104,17 
    ENDIF 

    IF    TMR0CLK == 1 
txcarry:MOVlw    (256-93)            ;2400 = 416,666us = 1491,477c/16 = 93,22 
    ENDIF 


txndone:btfsc    TMR0, 7                ;Last bit transmitted (TMR0 ovfl.)? 
    goto    txndone 

    bsf    DTMF3                ;Space 
    btfsc    STATUS,C            ;Set to mark (-12 V) if Carry = 1 
                        ;(RS232 inverts output) 
    bcf    DTMF3                ;Mark 

    MOVwf    TMR0 

    retlw    0 


; Recognizes CLIP (DTMF received in A), and sets/clears CLIP. 

    IF    CLIONLY == 1 
CLIPdet: 
     MOVwf    temp1 
     MOVlw    b’00001010’            ;DTMF ’A’ 
     subwf    temp1, W 
     btfss    STATUS, Z 
     goto    CLIPdet2 
     bsf    CLIP 
     goto    CLIPdetend 

CLIPdet2:MOVlw    b’00001101’            ;DTMF ’D’ 
     subwf    temp1, W 
     btfss    STATUS, Z 
     goto    CLIPdet3 
     bsf    CLIP 
     goto    CLIPdetend 

CLIPdet3:btfss    CLIP 
     goto    CLIPdetend 
     MOVlw    b’00001111’            ;DTMF ’#’ 
     subwf    temp1, W 
     btfss    STATUS, Z 
     goto    CLIPdetend 
     bcf    CLIP 
     bsf    CLIPend 

CLIPdetend: 
     retlw    0 
    ENDIF 


; DTMF-detection - Calls readDTMF, CLIPdet, conASCII and txser if DTMF is present. 
;                  Returns when DTMF is reMOVed. 
DTMFdet:clrwdt 
    btfss    DTMFOK 
    goto    DTMFdetreturn 
    goto    $+1                ;Double nop 
    btfss    DTMFOK 
    goto    DTMFdetreturn 

    call    readDTMF            ;DTMF present, read! 

    IF    IDENTTX == 1            ;Transmit ident if ’***’ received 
     call    ident 
     btfss    IdentOK 
     goto    DTMFdet2 

     MOVlw    h’0FF’ 
     MOVwf    temp3 

DTMFdet1:clrwdt 
     incf    temp3, F 
     MOVf    temp3, W 

     call    identtable            ;Fetch text 

     clrf    temp2 
     subwf    temp2, F 
     btfsc    STATUS, Z            ;End of table? 
     goto    DTMFdet2 
     call    txser 
     goto    DTMFdet1 
    ENDIF 

DTMFdet2: 
    MOVf    DTMFval, W 
    IF    CLIONLY == 1            ;Transmit only CLI 
     call    CLIPdet 
     btfss    CLIPend                ;Last digit in CLI (#)? 
     goto    DTMFdet21 
     bcf    CLIPend 
     goto    DTMFdet22 
DTMFdet21: 
     btfss    CLIP 
     goto    DTMFoff 
DTMFdet22: 
     MOVf    DTMFval, W 
    ENDIF 

    IF    ASCII == 1            ;Convert to ASCII 
     MOVf    DTMFval, W 
     call    conASCII 
    ENDIF 

    call    txser                ;Transmit to serial port 

DTMFoff:clrwdt                    ;Wait for DTMF to stop 
    btfsc    DTMFOK 
    goto    DTMFoff 

DTMFend:goto    DTMFdetreturn 



; Ring-detection - If ringing is present, calls txser with W = (ascii) ’R’. 
;                  Returns when ringing ends or DTMF is present. 
ringdet:clrwdt 
    IF    RING == 1 
     btfsc    DTMF2 
     goto    ringend 

ringdet2:                    ;Wait for ringing-pulse to  
     clrwdt                    ;stop (or DTMF present). 
     btfsc    DTMFOK 
     goto    ringend 
     btfss    DTMF2 
     goto    ringdet2 

     MOVlw    b’10000111’            ;Setup timer: 50ms before overflow. 
     option 
     MOVlw    d’50’ 
     MOVwf    TMR0 

ringdet3:clrwdt                    ;Wait for new ringing-pulse 
     MOVlw    0 
     subwf    TMR0, W 
     btfsc    STATUS, Z 
     goto    ringend 
     btfsc    DTMF2 
     goto    ringdet3 
                        ;New pulse present. 
     MOVlw    OPTION_REG            ;Restore old prescaler 
     option 
     MOVlw    A’R’                ;Transmit ’R’ 
     call    txser 
     bcf    CLIP                ;Terminate CLIP-sequence (ring det.) 
     MOVlw    b’10000111’            ;Setup timer: 50ms before overflow. 
     option 

ringdet4:MOVlw    d’50’ 
     MOVwf    TMR0 

ringdet5:clrwdt                    ;Wait for ringing to end 
     btfss    DTMF2 
     goto    ringdet4 

     MOVlw    0 
     subwf    TMR0, W 
     btfsc    STATUS, Z 
     goto    ringend 
     btfss    DTMFOK 
     goto    ringdet5 

ringend: MOVlw    OPTION_REG            ;Restore old prescaler 
     option 
    ENDIF 
    goto    ringdetreturn 



    IF    OTP == 0 
     ORG    h’1FF’                ;(old 12C508 calibration-val.) 
     MOVlw    h’0A0’ 
    ENDIF 

    END 


  +---------------------------------------------------------------------+ 
  | History                                | 
  +---------------------------------------------------------------------+ 

Rev.    Change                    Reason            Date 
-------------------------------------------------------------------------------- 
0.0a    Source-file created.            -            24.03.98 

0.5a    Hierarchisch diagram finished.        -            25.03.98 

1.0a    Everything implemented, ready for test.    -            26.03.98 

1.0b    Tested in ’real life’... Everything ok,    -            27.03.98 
     (minor bugs reMOVed). 

1.0    First version, ’in use’.        -            27.03.98 

1.01    Fixed ’#’ not transmitted when CLIP=1.    -            29.03.98 
    Fixed ’D’-sequences not recognized as 
     CLIP (not transmitted when CLIP=1). 
    Implemented PwrUpIdent.            Gives possibility of 
                         auto-detection, and 
                         FW-version detection. 

1.02    Implemented possibility of using ext.    More precise than    09.04.98 
     TMR0 source, as timebase for RS232-     internal RC-oscillator. 
     communication. 
    Bugfixed CLIPdet.            ASCII-table located in 
                         upper page when all 
                         switches = 1. 

1.03r    +++ First ’public’ release. +++        In case the CLI-    02.05.98 
    Break CLIP-sequence if ring detected.     sequence is not termi- 
                         nated probably (because 
                         of linenoise etc.) 
     

1.04r    Minor changes/bugfixes:                        18.03.99 
     Changed TX-timing.            Transmitted at ~2325bps. 
     Changed format from 8E1 to 8E2        Enables receiver to re- 
      (2 stopbits).                 syncronize between each 
                         byte, thereby supressing 
                         framing-errors. 
     Minimized ’read-DTMF’ timing.        ReMOVes unwanted 10us 
                         glitch on TX just before 
                         transmitting a digit. 


Ideas/future changes: 
------------------------------------------------------------------------------- 
Add EEPROM and change power-supply, to enable reception/storing of DTMF, when  
 the PC is turned off. 

Add offhook detector, to enable ’length of conversation’, and ’answered/not  
 answered call’ logging. 


Keywords:pic12C508  DTMF Reference address:pic12C508 DTMF dialer

Previous article:Infrared remote control receiving program made by PIC
Next article:pic16f874 stepper motor program

Recommended ReadingLatest update time:2024-11-17 14:25

Design of a hospital nursing call intercom system
O Introduction The hospital nursing call system is an important part of the information and modern management of modern hospitals. It can effectively enhance the hospital image, strengthen institutional management, and ensure service quality. How to use advanced information technology to serve the hospital
[Medical Electronics]
Design of a hospital nursing call intercom system
Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号