|
ME Labs, Inc. 719-520-5323 |
|
|
|
ME Labs, Inc. | 1-719-520-5323 | Example Program - PHONE2XT.pbpPICBASIC PRO program the same as phone1xt.pbp, but with Caller ID display.' Name : PHONE2XT.pbp
' Compiler : PICBASIC PRO Compiler 2.6
' Assembler : PM or MPASM
' Target PIC : PIC16F877-20, PIC18F452 or similar type
' Hardware : LAB-XT Experimenter Board
' Oscillator : 20MHz external
' Keywords : DCD, HPWM, LCDOUT, LOOKUP, NCD, SELECT CASE
' Description : PICBASIC PRO program the same as phone1xt.pbp, but
' with Caller ID display.
'
' MeLabs PIC programmer should not be connected to the ICSP header
' when running this code. It may interfere with the operation
' of the keypad.
Define LOADER_USED 1 ' Only required for melabs Loader
Define OSC 20 ' Match the crystal on the board
' Define LCD registers and bits
Define LCD_DREG PORTD
Define LCD_DBIT 4
Define LCD_RSREG PORTE
Define LCD_RSBIT 0
Define LCD_EREG PORTE
Define LCD_EBIT 1
led3 Var PORTC.0 ' LED3 output pin
led4 Var PORTC.1 ' LED4 output pin
sieze Var PORTD.1 ' Relay control pin (sieze line)
dtmf_ready Var PORTA.4 ' Data ready signal from MT8870
voice_int Var PORTA.5 ' End of Message signal from voice chip
select_dtmf Var PORTD.3 ' Data output enable to MT8870
loop_current Var PORTA.3 ' Loop current present (active low)
ring_detect Var PORTA.2 ' Ring detect pin (active low, square wave)
dtmf_out Var PORTE.2 ' DTMF signal output pin
cid_serial_data Var PORTA.0 ' Caller ID data from FSK chip
tone_detect Var PORTA.1 ' Indicates audio signal present on line
speaker Var PORTC.2 ' Speaker output pin
select_voice Var PORTD.2 ' Chip select for voice recorder
serial_mcu_out Var PORTC.5 ' SPI data output
serial_clk Var PORTC.3 ' SPI clock pin
' Define program variables
h Var Byte ' Loop counter, misc
i Var Byte ' Loop counter, misc
j Var Byte ' Loop counter, misc
col Var Byte ' Keypad column
row Var Byte ' Keypad row
key Var Byte ' Key value
disp_key Var Byte ' Key label
entry_string Var Byte[20] ' Array for storing user keyboard entry
ring_freq Var Word ' Frequency of ring signal (speaker PWM)
length Var Byte ' Length of caller id string
cid_string Var Byte[96] ' Array for storing caller id string
ADCON1 = 7 ' Set PORTA and PORTE to digital
TRISD = %11110000 ' Set low bits of PORTD to output
TRISC = %11111000 ' Set LED and Speaker pins to output
PORTD = 0 ' Intialize output state of PORTD
Pause 100 ' Wait for LCD to start up
LCDOut $fe,1 ' Clear display
OPTION_REG.7 = 0 ' Enable PORTB pullups
'INTCON2.7 = 0
initialize:
For i = 0 TO 19 ' Clear the user-entry array variable
entry_string[i] = $FF ' Store $FF in each location of array
Next i
led3 = 0
i = 0 ' Set user-entry to location 0
key = $FF ' Set key value to $FF (cleared)
sieze = 0 ' Deactivate the line-sieze relay (Hang Up)
Pause 250
LCDOut $fe, 1, "A=Off Hook D=Dial", $FE, $C0 ' Display sign-on message
mainloop:
GoSub getkey ' Check for user keypad entry
IF (ring_detect = 0) Then ' Check for ring-detect (incoming call, active low)
j = 0 ' Clear j variable (time elapsed since last ring-detect)
ring_cycle:
led3 = 1 ' Light LED to indicate incoming call
Pause 1 ' Pause 1mS so we can time this loop
GoSub getkey ' Check for user entry
j = j + 1 ' Each count of j represents 1mS of time
' If user pressed "A", he wants to answer the call. Ignore other keys.
' If 60mS has elapsed without a ring-detect, the ring has ended
IF (j > 60) OR (key = 12) Then stop_ringing
IF ring_detect = 1 Then ring_cycle ' Stay in this loop if no ring-detect (60mS max)
IF ring_freq = 2150 Then ' On each ring detect, change the speaker frequency.
ring_freq = 2500 ' This gives us the familiar 20Hz warble tone. The
Else ' frequencies used (2150 and 2500) gave the most
ring_freq = 2150 ' speaker volume when tested.
EndIF
HPwm 1,127,ring_freq ' Initiate the speaker tone using HPWM. The output will continue until silenced.
led3 = 0
Pause 30 ' Pause 30mS. (Low period of ring-detect)
j = 30 ' Set j to 30 (30mS)
GoTo ring_cycle ' Loop to keep monitoring the ring-detect
stop_ringing: ' Jump here at end of ring or to answer call
HPwm 1,0,0 ' Silence the speaker
led3 = 0 ' Shut off the LED
IF key = $FF Then GoSub caller_id ' If end of ring, check for caller id
EndIF
Select Case key ' Take action based on user keypad entry
Case 12 ' User entry "A" - Off Hook
sieze = 1 ' Activate sieze relay
Pause 250 ' Pause 250mS to establish loop current
LCDOut $FE, 2, "B=Hang Up, Dial #'s", $FE, $C0 ' New prompt on LCD
Case 13,14 ' User entries "B" or "C" - Hang Up or Clear
GoTo initialize ' Hang Up and initialize variables
Case 15 ' User entry "D" - Dial user-entered string
LCDOut $FE, 2, "Dial Tone Detect... " ' Indicate status on LCD
IF sieze = 1 Then ' If already Off Hook, get new dial tone
sieze = 0 ' Deactivate sieze relay (hang up)
Pause 750 ' Pause 750mS to drop line
EndIF
sieze = 1 ' Activate sieze relay (off hook)
Pause 150 ' Pause 150mS to establish loop current
j = 0 ' Clear j (number of tone-detect attempts)
detect: ' Jump here to try again
h = 0 ' Clear h (tone cycles)
Count tone_detect,150,h ' Count tone cycles for 150mS
j = j+1 ' Increment number of tries
IF (j < 50) AND (h < 50) Then detect ' Were there 50 tone cycles in 150mS? (>333Hz)
' If tone detected or no tone for 50 tries, continue
LCDOut $FE, 2, "Dialing: " 'Indicate status on LCD
For i = 0 TO 19 ' Loop through the user-entry array
IF entry_string[i] = $FF Then end_string ' $FF in array indicates end-of-string
DTMFOut dtmf_out,100,100,[entry_string[i]] ' Dial the DTMF digit in each location
entry_string[i] = $FF ' Clear the location after dialed
Next i ' Next location
end_string: ' Jump here is end-of-string
i = 0 ' Set user-entry location back to 0
LCDOut $FE, 1, "B=Hang Up, Dial #'s", $FE, $C0 ' Display prompt on LCD
Case Is < 12 ' User pressed number or *# key
IF i = 0 Then
LCDOut $FE,$C0, REP 32\20,$FE,$C0
EndIF
LCDOut disp_key ' Display key label on LCD
IF sieze = 1 Then ' If Off Hook, dial the digit
DTMFOut dtmf_out,200,10,[key] ' Dial DTMF for user-entered digit
EndIF
entry_string[i] = key ' Save digit in current location
i = i + 1 ' Increment location
End Select ' Continue program
GoTo mainloop ' Repeat main loop
' Subroutine to get a key from keypad
getkey:
' If Off Hook and the loop_current drops, Hang-Up the phone
' and initialize variables. Placed here because getkey is
' frequently called, and we want to avoid delays that hold
' the line off-hook.
IF (sieze = 1) AND (loop_current = 1) Then initialize
' Check for keypress
For row = 0 TO 3 ' Loop for 4 rows in keypad
PORTB = 0 ' All output pins low
TRISB = ~(DCD row) ' Set one row pin to output
'@ NOP ' Fudge for 18F452
col = PORTB >> 4 ' Read column pins
IF col != $0F Then ' Check if key is pressed
HPwm 1,127,7500 ' Begin speaker tick
GoTo gotkey ' If any keydown, exit
EndIF
Next row ' Repeat for the next row
key = $FF ' No keys down, set key to $FF
Return ' Return to main loop
gotkey: ' Change row and column to key number 0 - 15
Pause 15 ' Debounce
HPwm 1,0,0 ' End speaker tick
' Wait for all keys up
PORTB = 0 ' All output pins low
TRISB = $F0 ' Least significant 4 pins out, top 4 pins in
IF ((PORTB >> 4) != $0F) Then gotkey ' If any keys down, loop
key = (row * 4) + (NCD (col^$0F)) - 1 ' Combine row and column into numeric value
' Translate key to display label:
' 1 2 3 A
' 4 5 6 B
' 7 8 9 C
' * 0 # D
LookUp key,["123A456B789C*0#D"],disp_key
' Translate key to DTMFOUT tone
' 1 2 3 12
' 4 5 6 13
' 7 8 9 14
' 10 0 11 15
LookUp key,[1,2,3,12,4,5,6,13,7,8,9,14,10,0,11,15],key
Return ' Return to main loop
caller_id:
Pause 200 ' Wait 200mS for line to settle
' Look for CID data, abort if no data for 500mS
SerIn2 cid_serial_data, 813, 500, mainloop, [wait($80),length,STR cid_string\length]
LCDOut $fe,1 ' Clear the display
For i = 0 TO length ' Begin loop, each count represents a character
' in the recorded CID data.
Select Case cid_string[i] ' For each character, check for known parameter types
Case $01 ' Parameter type 01 (hex) is date and time.
i = i + 1 ' Move index pointer to parameter length character.
' This avoids the length character being mistaken for
' a parameter type code.
LCDOut $fe,$80,cid_string[i+1],cid_string[i+2],_ ' Display date and time
$FE,$C0, cid_string[i+3],cid_string[i+4], " ",_
$FE,$83, cid_string[i+5],cid_string[i+6],":",_
cid_string[i+7],cid_string[i+8]
Case $02, $04 ' Parameter type 02 is the phone number.
' Parameter type 04 is the reason, if there is no number
LCDOut $FE,$89 ' Move the LCD cursor to position 9 on line 1
GoSub disp_string ' Display the number string
Case $07, $08 ' Parameter type 07 is the caller's name.
' Parameter type 08 is the reason, if there is no name
LCDOut $FE,$C3 ' Move the LCD cursor to position 4, line 2
GoSub disp_string ' Display the name string
End Select
Next i
' Because the caller id information overwrites the user-entry on the display,
' we must reset the user-entry array and pointer.
For i = 0 TO 19 ' Clear the user-entry array variable
entry_string[i] = $FF ' Store $FF in each location of array
Next i
i = 0 ' Set user-entry to location 0
Return
disp_string:
i = i + 1 ' Move the index pointer to the parameter-length byte
IF cid_string[i]=1 Then ' If the parameter is only 1 character long, then display a reason
IF cid_string[i+1] = "O" Then LCDOut "Out Of Area" ' "O" is Out Of Area
IF cid_string[i+1] = "P" Then LCDOut "Blocked" ' "P" is Private Caller
Else ' If the parameter is longer than 1 character
For h = 1 TO cid_string[i] ' Loop from 1 to the length of the parameter
LCDOut cid_string[i+h] ' Display each character in the parameter
Next h ' Do it for the next character
EndIF
Return
End
Download the program file. |
|
Copyright 2022 ME Labs, Inc. PO Box 8250 Asheville NC 28814 (719) 520-5323 (719) 520-1867 fax email: support@melabs.com |
|