pic12C508 DTMF dialing program

EL-C1600N100013-B

PIC12C508 DTMF Dialing Program
;|Name: MAIN.ASM |
;|Description: DTMF -> RS232 converter (for use with PC Number Viser) |
;|Detects DTMF and ringing, and transmits to a standard. |
;|RS232 port, at 2400 baud. |
;|||
;+------------------------------------------------ --------------------+
;|Platform: PIC12C508 (using internal 4MHz RC oscillator) |
;|Uses: 90-342W / 512W program memory (all 'switches' set to 0/1) |
;|6B / 25B data memory |
;|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'


OTPSET1; Use factory-stored cal.-value (on One Time Programmable)

TMR0CLKSET1; Use TMR0 external clock at 3,579545 MHz (instead of IntRC).
PARITYSET1; Use even parity-bit when transmitting to the serial port.
CLIONLYSET1; Transmits CLI (A-numbers) only.
RINGSET1; Transmits ringing.
IDENTTXSET1; Transmits 'ident' when pressing '***' (DTMF).
PWRUPIDSET1; Transmits short 'ident' at power-up.
ASCIISET1; 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 ***+++---

IFTMR0CLK == 0; Internal oscillator
OPTION_REG equ b'10000001'; 'Default' timer/prescaler setup
ENDIF

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

#define DTMF0 GPIO, 0; Bit 0 (LSB) from MT8870
#define DTMF1 GPIO, 1; Bit 1 from MT8870
#define DTMF2 GPIO, 3; Bit 2 from MT8870 / Ring-detector
#define DTMF3 GPIO, 4; Bit 3 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 CLI misc, 0; Set when CLI detected
#define CLIend misc, 1; Set by CLI det 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
Pwrupident return:
ENDIF

Goto main



;---+++*** Identity (located 'low' because of no CP < 64b) ***+++---

Identtable:
IF IDENTTX == 1
addwf PCL, F
Dt "+++PCNummerViser+++", 13
Dt "Firmware v1.04", 13, 13
Dt "Ja COBBlich fELDt'98", 13, 13, 13, 0
ENDIF

Pwrupidenttable:
IF PWRUPID == 1
addwf PCL, F
Dt "DTMF to RS232", 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 = in 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: clrftemp2
Pwrup12 clrftemp1
Pwrup13: clrwdt
Decfsz temp1, F
Goto pwrup13
Decfsz temp2, F
Goto pwrup12
Decfsz temp3, F
Goto pwrup11

MOVlw h'FF'
MOVwf temp3
Pwrup2: clrwdt
Incf temp3, F
MOVf temp3, W

Call pwrupidenttable; Fetch text

Clrftemp2
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, convert to nibble, and return in W.
readDTMF:
MOVf GPIO, W
Andlw b'00000011'; Get bit 0-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 '0'
retlw '1'
retlw '2'
retlw '3'
retlw '4'
retlw '5'
retlw '6'
retlw '7'
retlw '8'
retlw '9'
retlw 'A'
retlw 'B'
retlw 'C'
retlw 'D'
retlw '*'
retlw '#'
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 2400 bps / std. RS232. Calculates parity-bit. Returns when done.
Txser:
MOVwf temp1

bcf STATUS, C; Transmit start-bit
Call txcarry

MOVlw d'8'; Transmit 8 data bits
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
Btfsctemp1, 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 overflow)?
Goto txndone

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

MOVwf TMR0

Retlw 0


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

IF CLIONLY == 1
CLIPdet:
MOVwf temp1
MOVlw b'00001010'; DTMF 'A'
Subwf temp1, W
btfss STATUS, Z
goto CLIPdet2
bsf CLI
goto CLIPdetend

CLIPdet2: MOVlw b'00001101'; DTMF 'D'
Subwf temp1, W
btfss STATUS, Z
goto CLIPdet3
bsf CLI
goto CLIPdetend

CLIPdet3: btfss CLI
goto CLIPdetend
MOVlw b'00001111'; DTMF '#'
Subwf temp1, W
btfss STATUS, Z
goto CLIPdetend
bcf CLI
bsf CLIend

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'FF'
MOVwf temp3

DTMFdet1: clrwdt
Incf temp3, F
MOVf temp3, W

Call identtable; Fetch text

Clrftemp2
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 CLIend; Last digit in CLI (#)?
goto DTMFdet21
bcf CLIend
goto DTMFdet22
DTMFdet21:
btfss CLI
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:; Way for for ringing-pulse to
Crlwdt; 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 'R'; Transmit 'R'
Call txser
bcf CLI; Terminate CLI-sequence (ringdet.)
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'A0'
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 CLI=1. - 29.03.98
Fixed 'D'-sequences not recognized as
CLI (not transmitted when CLI=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 time base for RS232 - internal RC oscillator.
Communication.
Bug fixed CLI det. ASCII-table located in
Upper page when all
Switches=1.

1.03r +++ First 'public' release. +++ In case the CLI-02.05.98
Break CLI-sequence if ringdetected. sequence is not terminated
probably (because
Off-line noise etc.)


1.04r Minor changes/bug fixes: 18.03.99
Changed TX timing. Transmitted at ~2325bps.
Changed format from 8E1 to 8E2 Enables receiver to re-
(2 stop bits). synchronize between each
Byte, the by by suppressing
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
Answer call' logging.


Solid-state capacitors / Motor starting capacitors

Solid - state capacitors are all called: solid - state Aluminum Electrolytic Capacitors.It with the ordinary capacitance (that is, the liquid aluminum electrolytic capacitors) the biggest difference is that use different dielectric material, liquid aluminum capacitor dielectric material as the electrolyte, and solid-state capacitor dielectric material is conductive polymer materials.Solid-state Capacitors / Motor Starting Capacitors

Solid-state capacitors,Motor starting capacitors,Solid-State Capacitors,Solid-State Small Size Capacitors,Solid-State Low Impedance Capacitors,Long Life Solid-State Capacitors

YANGZHOU POSITIONING TECH CO., LTD. , https://www.yzpst.com

Posted on