Source:
Cheers, Art.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 ' '






Bookmarks