ME Labs, Inc.
719-520-5323
 
Home:
  Developer Resources:

Programming Clues
    Sample Programs
   
    PICBASIC PRO™
Compiler Manual
    PICBASIC™ Compiler
Manual
    Serin2/Serout2 Modes
    ASCII Character Set
    Number Conversion
    Floating Point
Routines
    PBP Debug Monitor
    Articles and Tutorials

Hardware Clues
    Parts / Vendor List
    PICPROTO™ Boards
    LAB-X1 Docs
    LAB-X2 Docs
    LAB-X20 Docs
    LAB-X3 Docs
    LAB-X4 Docs
    LAB-XUSB Docs
    LAB-XT Docs
     
 

ME Labs, Inc. | 1-719-520-5323 | Example Program - PHONE1XT.pbp

PICBASIC PRO program for simple telephone. Press keys for on-hook, off-hook, and to dial. Incoming call sounds ringer and flashes LED. Watches for loop-current wink when off-hook.
' Name        : PHONE1XT.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
' Description : PICBASIC PRO program for simple telephone.
' Press keys for on-hook, off-hook, and to dial. Incoming call 
' sounds ringer and flashes LED. Watches for loop-current wink 
' when off-hook.
'

' 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
sieze        Var PORTD.1  ' Relay control pin (sieze line)
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
tone_detect  Var PORTA.1  ' Indicates audio signal present on line
speaker      Var PORTC.2  ' Speaker output pin

' Define program variables
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
ring_freq Var Word      ' Frequency of ring signal (speaker PWM)

   ADCON1 = 7           ' Set PORTA and PORTE to digital
   TRISD = %11110000    ' Set low bits of PORTD to output
   PORTD = 0            ' Intialize output state of PORTD
   OPTION_REG.7 = 0     ' Enable PORTB pullups (16F877)
   'INTCON2.7 = 0       ' Enable PORTB pullups (18F452)

initialize:
   key = $FF            ' Set key value to $FF (cleared)
   sieze = 0            ' Deactivate the line-sieze relay (Hang Up)
   Pause 250
   LCDOut $fe, 1, "Press A for Off-Hook", $FE, $C0  ' Display sign-on message

mainloop:
   ' If Off Hook and the loop_current drops, Hang-Up the phone 
   ' and initialize variables.  
   IF (sieze = 1) AND (loop_current = 1) Then initialize
   
   GoSub getkey          ' Check for user keypad entry

   ' Take action based on user keypad entry
   Select Case key                              
          Case 12                      ' User entry "A" - Off Hook
               sieze = 1               ' Activate sieze relay
               Pause 250               ' Pause 250mS to establish loop current
               LCDOut $FE, 1, "Press B to Hang Up", $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 Is < 12                 ' User pressed number or *# key
               LCDOut $FE, $C0, 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
   End Select                          ' Continue program

   ' Check for incoming call
   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:
      High led3                        ' 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
      Low led3                         ' Shut off the LED
   EndIF     
   GoTo mainloop                       ' Repeat main loop

' Subroutine to get a key from keypad
getkey:
   ' 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

   End

           

Download the program file.