Source:
Code:
'
'***********************************************************************************
'* *
'* Telephony *
'* Rotary to DTMF converter *
'* Microchip Pic 16F628 @ 8MHz *
'* (c) Art 2013 *
'* *
'* [email protected] *
'* *
'***********************************************************************************
'
'
DEFINE OSC 20 ' but we are really using 8 MHz
DEFINE NO_CLRWDT ' watchdog is cleared manually
LCD_DATAUS CON 50 ' LCD timing
LCD_COMMANDUS CON 2000 '
'
DATA " Art 2013 " ' Rotary to DTMF - (c) Brek Martin 2013
'
'
number var byte[18] ' number entry array
fnum var byte[18] ' phone number array
digcnt var byte ' phone number entry counter
fcount var byte ' phone number digit counter
i var byte ' counter
digit var byte ' dtmf digit
pulses var byte ' rotary pulse count
tcount var word ' cycle counter
shiftcount var word ' timer to accept a phone number digit
longcount var word ' timer to dial DTMF number
emergency var bit ' emergency speed dial status
pressed var bit ' hangup button status
donedtmf var bit ' dialed number status
'
'
' execution time!
'
'
'
CMCON = 7 ' set portb to digital
trisb.6 = 0 ' set LCD backlight output
trisb.4 = 0 ' set DTMF output
trisb.5 = 1 ' set button input
portb.6 = 1 ' turn on LCD backlight
'
'
PAUSE 500 'pause for LCD to start
@ clrwdt ; clear watchdog timer manually
PAUSE 500 '
@ clrwdt ;
PAUSE 200 '
'
LCDOUT $FE,$80
LCDOUT " ROTARTY DIAL "
LCDOUT $FE,$C0
LCDOUT " DTMF CONVERTER "
'
PAUSE 500 'pause to display message
@ clrwdt ; clear watchdog timer manually
PAUSE 500 '
@ clrwdt ;
PAUSE 300 '
'
'
resetx:
donedtmf = 0 ' reset status
emergency = 0 ' reset emergency speed dial
reset:
digit = 0 ' reset digit variable
digcnt = 0 ' reset phone number entry counter
pulses = 0 ' reset pulse count
tcount = 0 ' reset cycle counter
fcount = 0 ' reset phone number digit counter
shiftcount = 0 ' reset digit accept timer
longcount = 0 ' reset timer
pressed = 0 ' reset hangup button status
'
FOR i = 0 TO 17 ' reset number arrays
number[i] = 0
fnum[i] = $FF
NEXT i
'
LCDOUT $FE,1 'clear LCD
LCDOUT $FE,$80 'set to start of first line
'
'
cycle: ' main routine - user program
@ clrwdt ; clear watchdog timer manually
'
'
IF pressed = 0 THEN
IF portb.5 = 0 THEN ' reversed
pressed = 1 ' set status
tcount = 0 ' start counter
shiftcount = 0
IF pulses < 10 THEN ' valid count only
pulses = pulses + 1
ENDIF
ENDIF ' button pushed
ENDIF ' ignore if button already down
'
'
'
IF pressed = 1 THEN ' increment counter while button is down
IF tcount < 2500 && portb.5 = 0 THEN ' reversed
tcount = tcount + 1
ENDIF
IF tcount > 2499 && portb.5 = 0 THEN ' reversed
gosub printerror ' hangup held down too long
IF portb.5 = 1 THEN ' wait for off hook again to restart
goto resetx ' restart properly
ENDIF
ENDIF
IF tcount < 2500 && portb.5 = 1 && pressed = 1 THEN ' reversed
IF tcount > 20 THEN 'debounce button
IF pulses < 10 THEN
number[digcnt] = pulses
ELSE
number[digcnt] = 0
ENDIF
gosub senddigit
digcnt = digcnt + 1
tcount = 0
pressed = 0
ENDIF
ENDIF ' debounce
'
ENDIF
'
'
'
IF shiftcount > 0 && digcnt > 0 THEN
IF pressed = 0 THEN
shiftcount = shiftcount + 1
IF shiftcount > 9999 THEN
shiftcount = 0
fnum[fcount] = number[digcnt-1]
gosub acceptdigit
fcount = fcount + 1
longcount = 0
pulses = 0 : digcnt = 0
ENDIF
ENDIF
ENDIF
'
'
IF fcount != 0 && shiftcount = 0 && donedtmf = 0 THEN
longcount = longcount + 1
IF longcount > 65000 THEN
IF donedtmf = 0 THEN
gosub dodtmf
@ clrwdt ; clear watchdog timer manually
PAUSE 500
@ clrwdt ; clear watchdog timer manually
PAUSE 500
donedtmf = 1
goto reset
ENDIF
ENDIF
ENDIF
'
'
'
goto cycle ' end main routine - do the next frame
'
'
senddigit:
LCDOUT $FE,$80
IF fcount > 0 THEN
FOR i = 0 TO fcount-1
LCDOUT " "
NEXT i
ENDIF
LCDOUT #number[digcnt]
shiftcount = 1
return
'
acceptdigit:
LCDOUT $FE,$01
LCDOUT $FE,$C0
FOR i = 0 TO fcount
LCDOUT #fnum[i]
NEXT i
tcount = 0
IF donedtmf = 1 THEN
DTMFOUT portb.4,[fnum[fcount]]
ENDIF
return
'
dodtmf:
IF fnum[0] = 1 && fnum[1] = 1 THEN
IF fnum[2] = 1 && fnum[3] = $FF THEN
fnum[0] = 0 : fnum[1] = 0 : fnum[2] = 0
emergency = 1
ENDIF
ENDIF
LCDOUT $FE,$01
LCDOUT $FE,$80
IF emergency = 0 THEN
LCDOUT " DIALING... "
ELSE
LCDOUT " EMERGENCY! "
ENDIF
LCDOUT $FE,$C0
FOR i = 0 TO fcount-1
LCDOUT #fnum[i]
NEXT i
FOR i = 0 TO fcount-1
@ clrwdt ; clear watchdog timer manually
DTMFOUT portb.4,[fnum[i]]
NEXT i
return
'
printerror:
'LCDOUT $FE,$01
LCDOUT $FE,$80
LCDOUT " "
LCDOUT $FE,$C0
LCDOUT " ON HOOK "
LCDOUT $FE,$80
return
'
'
Cheers, Art.
Bookmarks