Beruflich Dokumente
Kultur Dokumente
Introduction
In this project, we demonstrate the 4 line telephone systems with full signaling and switching
functions similar to those of the central office systems. Dial tone, busy tone, and ring tone are
provided during call progress. Ringing is generated at the receiving end of the phone being
called. Switching employs integrated circuit (IC) matrix switches on four buses. Thus, this
system is expandable to 8 lines (4 pairs) if more hardware is added. This system is switching on
the Dual Tone Multi Frequency (DTMF) dialing signal and does not work with pulse dialing
signal founded in some older phones.
Hardware Design
The main circuit for this project is “Phone Line Circuit”. The Phone Line Circuit(s) are
connected to Micro Controller, Decoder, Ring Generator and Telephone. Micro Controller sends
or receives data via Share Data Bus by PORT-C and sends address to the decoder by PORT-A.
The decoder receives the address, decodes the address and sends the control signal (Control
Enable and Control Latch) to each Phone Line Circuit as shown in overall system diagram. The
Phone Line Circuit(s) communicate with MCU by sending or receiving data via Shared Data
Bus. MCU uses time sharing protocol to control each Phone Line Circuit by sending the address
of the Phone Line Circuit to the decoder and sending control data to Phone Line Circuit via Data
Bus.
Each Phone Line Circuit is connected to one telephone line. In this project, there are 4 Shared
Audio Bus so we can expand the switching up to 8 lines.
The Phone Line Circuit supplies DC voltage to telephone. It receives signal from telephone,
check the number by DTMF receiver and send the number to MCU when requested. Tri-State
buffers are used to multiplex data from DTMF receiver and Off-hook detection relay of each
Phone Line Circuit to Shared Data Bus. Tri-State buffer passes through the data when it receives
Control Enable signal from Decoder. Because we use time sharing method the control signals
sent from MCU to each Phone Line Circuit will be latched when the Phone Line Circuit receives
Control Latch signal from Decoder. There are 3 sets of control signals from MCU to the Phone
Line Circuit: 1. Tone Selection, select tone presented to telephone when off-hook (Dial Tone,
Busy Tone, and Ring Tone), 2. Audio Switch Control, control audio switch to connected phone
line together for speaking, and 3. Ring Control, control relay switch ring signal to telephone line.
The Audio Bus is used to link each phone line together when there is calling. Coil and capacitors
are used to separate analog signal from DC Supply voltage. There is one off-hook detection 2-
contact relay in each Phone Line Circuit. When telephone off hook the relay will close and pull
the off-hook detection output down to GND and switch the audio channel from ringing mode to
audio mode.
Block diagram of the Phone Line Circuit can be shown in two sections, Digital/Control Section
and Analog/Audio Section as shown in next diagrams. The circuit detail can be found in
Appendix A) Schematics
Phone Line Circuit
Next time
If we have more time, we will add some feature of this project. Current design can
use only internal phone line. We can modify the Phone Line Circuit to support
external telephone line calling. We want our PBX has ability to connect to external
telephone line.
#include <90s8515.h>
#include <stdio.h> //for debugging using printf, etc
#include <delay.h>
#define TESTPHONE 1
#define t1 10
#define MAXPHONENO 4
#define IDLE 1
#define CALLEROFFHOOK 2
#define WAITBUTTONRELEASE1 3
#define WAITBUTTONRELEASE2 4
#define BUSYTONEGENON 5
#define BUSYTONEGENOFF 6
#define CHECKRECEIVER 7
#define RINGTONEGENON 8
#define RINGTONEGENOFF 9
#define SENDTALKING 10
#define RINGING 11
#define RECTALKING 12
if (time1>0) --time1;
}
void main(void)
{
initialize();
void task1(void)
{
time1 = t1;
if (tmp1 != stateofphone[0] || tmp2 != stateofphone[1] || tmp3 !=
stateofphone[2]) {
printf("P1=%d P2=%d P3=%d
\n\r",stateofphone[0],stateofphone[1],stateofphone[2]);
tmp1= stateofphone[0];
tmp2= stateofphone[1];
tmp3= stateofphone[2];
}
if (stateofphone[phoneindex] == IDLE) {
checkhookswreg();
phoneoffhook = hookswreg & phonemsk[phoneindex];
phonering = ringerswreg & phonemsk[phoneindex];
if ((phoneoffhook != 0) && (phonering != 0))
stateofphone[phoneindex] = RECTALKING;
else if ((phoneoffhook != 0) && (phonering == 0)) {
enabledialtone();
stateofphone[phoneindex] = CALLEROFFHOOK;
}
else if ((phoneoffhook == 0) && (phonering != 0))
stateofphone[phoneindex] = RINGING;
}
else if (stateofphone[phoneindex] == CALLEROFFHOOK) {
checkhookswreg();
phoneoffhook = hookswreg & phonemsk[phoneindex];
if (phoneoffhook == 0) {
disabledialtone();
stateofphone[phoneindex] = IDLE;
}
else {
checkDTMFreg();
if (DTMFvalid == 1) {
DTMFno[phoneindex] = DTMFreg[phoneindex] &
DTMFnomsk;
checkhookswreg();
phoneoffhook = hookswreg & phonemsk[phoneindex];
if (phoneoffhook == 0)
stateofphone[phoneindex] = IDLE;
else {
checkDTMFreg();
if (DTMFvalid == 0) stateofphone[phoneindex] = CHECKRECEIVER;
}
}
else if (stateofphone[phoneindex] == WAITBUTTONRELEASE2) {
// if (phoneindex == TESTPHONE)
printf("WAITBUTTONRELEASE2\n\r");
checkhookswreg();
phoneoffhook = hookswreg & phonemsk[phoneindex];
if (phoneoffhook == 0)
stateofphone[phoneindex] = IDLE;
else {
checkDTMFreg();
if (DTMFvalid == 0) {
oninterval[phoneindex] = BUSYTONEON;
enablebusytone();
stateofphone[phoneindex] = BUSYTONEGENON;
}
}
}
else if (stateofphone[phoneindex] == BUSYTONEGENON) {
checkhookswreg();
phoneoffhook = hookswreg & phonemsk[phoneindex];
if (phoneoffhook == 0) {
disablebusytone();
stateofphone[phoneindex] = IDLE;
}
else {
oninterval[phoneindex]--;
if (oninterval[phoneindex] == 0) {
offinterval[phoneindex] = BUSYTONEOFF;
disablebusytone();
stateofphone[phoneindex] = BUSYTONEGENOFF;
}
}
}
else if (stateofphone[phoneindex] == BUSYTONEGENOFF) {
checkhookswreg();
phoneoffhook = hookswreg & phonemsk[phoneindex];
if (phoneoffhook == 0)
stateofphone[phoneindex] = IDLE;
else {
offinterval[phoneindex]--;
if (offinterval[phoneindex] == 0) {
oninterval[phoneindex] = BUSYTONEON;
enablebusytone();
stateofphone[phoneindex] = BUSYTONEGENON;
}
}
}
else if (stateofphone[phoneindex] == CHECKRECEIVER) {
checkhookswreg();
phoneoffhook = hookswreg & phonemsk[phoneindex];
if (phoneoffhook == 0)
stateofphone[phoneindex] = IDLE;
else
if (stateofphone[DTMFno[phoneindex] - 1] != IDLE) {
oninterval[phoneindex] = BUSYTONEON;
enablebusytone();
stateofphone[phoneindex] = BUSYTONEGENON;
}
else {
oninterval[phoneindex] = RINGTONEON;
ringerswreg = ringerswreg |
phonemsk[DTMFno[phoneindex] - 1];
enableringer();
enableringtone();
stateofphone[phoneindex] = RINGTONEGENON;
}
}
else if (stateofphone[phoneindex] == RINGTONEGENON) {
checkhookswreg();
phoneoffhook = hookswreg & phonemsk[phoneindex];
recphoneoffhook = hookswreg & phonemsk[DTMFno[phoneindex] -
1];
if (phoneoffhook == 0) {
disableringer();
disableringtone();
ringerswreg = ringerswreg &
~phonemsk[DTMFno[phoneindex] - 1];
stateofphone[phoneindex] = IDLE;
stateofphone[DTMFno[phoneindex] - 1] = IDLE;
}
else {
if (recphoneoffhook == 0) {
oninterval[phoneindex]--;
if (oninterval[phoneindex] == 0) {
offinterval[phoneindex] = RINGTONEOFF;
disableringer();
disableringtone();
stateofphone[phoneindex] =
RINGTONEGENOFF;
}
}
else {
disableringer();
disableringtone();
enableswitching();
ringerswreg = ringerswreg &
~phonemsk[DTMFno[phoneindex] - 1];
stateofphone[phoneindex] = SENDTALKING;
}
}
}
else if (stateofphone[phoneindex] == RINGTONEGENOFF) {
checkhookswreg();
phoneoffhook = hookswreg & phonemsk[phoneindex];
recphoneoffhook = hookswreg & phonemsk[DTMFno[phoneindex] -
1];
if (phoneoffhook == 0) {
stateofphone[phoneindex] = IDLE;
// if (phoneindex == TESTPHONE) printf("call to %d
(ringoff)\n\r",DTMFno[phoneindex] - 1);
stateofphone[DTMFno[phoneindex] - 1] = IDLE;
ringerswreg = ringerswreg &
~phonemsk[DTMFno[phoneindex] - 1];
}
else {
if (recphoneoffhook == 0) {
offinterval[phoneindex]--;
if (offinterval[phoneindex] == 0) {
oninterval[phoneindex] = RINGTONEON;
enableringer();
enableringtone();
stateofphone[phoneindex] =
RINGTONEGENON;
}
}
else {
enableswitching();
ringerswreg = ringerswreg &
~phonemsk[DTMFno[phoneindex] - 1];
stateofphone[phoneindex] = SENDTALKING;
}
}
}
else if (stateofphone[phoneindex] == SENDTALKING) {
checkhookswreg();
phoneoffhook = hookswreg & phonemsk[phoneindex];
if (phoneoffhook == 0) {
disableswitching();
stateofphone[phoneindex] = IDLE;
stateofphone[DTMFno[phoneindex] - 1] = IDLE;
}
}
else if (stateofphone[phoneindex] == RINGING) {
checkhookswreg();
phoneoffhook = hookswreg & phonemsk[phoneindex];
if (phoneoffhook != 0)
stateofphone[phoneindex] = RECTALKING;
}
else if (stateofphone[phoneindex] == RECTALKING) {
}
}
void checkhookswreg(void)
{
DDRA = 0xf0;
PORTA = 0x0f;
delay_us(10);
temp2 = PINA;
hookswreg = ~temp2;
// if (phoneindex == TESTPHONE) printf("hoowswreg = %d", hookswreg);
}
void enabledialtone(void)
{
DDRC = 0xff;
PORTC = DIALTONEPATTERN;
delay_us(5);
PORTA = addrofphlatch[phoneindex];
delay_us(5);
PORTC = ACTIVATEDIALTONE;
delay_us(5);
PORTA = NULLADDRESS;
}
void disabledialtone(void)
{
DDRC = 0xff;
PORTC = DEACTIVATEDIALTONE;
delay_us(5);
PORTA = addrofphlatch[phoneindex];
delay_us(5);
PORTA = NULLADDRESS;
}
void enablebusytone(void)
{
DDRC = 0xff;
PORTC = BUSYTONEPATTERN;
delay_us(5);
PORTA = addrofphlatch[phoneindex];
delay_us(5);
PORTC = ACTIVATEBUSYTONE;
delay_us(5);
PORTA = NULLADDRESS;
}
void disablebusytone(void)
{
DDRC = 0xff;
PORTC = DEACTIVATEBUSYTONE;
delay_us(5);
PORTA = addrofphlatch[phoneindex];
delay_us(5);
PORTA = NULLADDRESS;
}
void enableringtone(void)
{
DDRC = 0xff;
PORTC = RINGTONEPATTERN;
delay_us(5);
PORTA = addrofphlatch[phoneindex];
delay_us(5);
PORTC = ACTIVATERINGTONE;
delay_us(5);
PORTA = NULLADDRESS;
}
void disableringtone(void)
{
DDRC = 0xff;
PORTC = DEACTIVATERINGTONE;
delay_us(5);
PORTA = addrofphlatch[phoneindex];
delay_us(5);
PORTA = NULLADDRESS;
void enableringer(void)
{
PORTB = ~ringerswreg;
}
void disableringer(void)
{
temp1 = ringerswreg & ~phonemsk[DTMFno[phoneindex] - 1];
PORTB = ~temp1;
}
void enableswitching(void)
{
DDRC = 0xff;
PORTC = switchtable[phoneindex];
delay_us(5);
PORTA = addrofphlatch[phoneindex];
delay_us(5);
PORTA = addrofphlatch[DTMFno[phoneindex] - 1];
delay_us(5);
PORTA = NULLADDRESS;
}
void disableswitching(void)
{
DDRC = 0xff;
PORTC = NULLLATCH;
delay_us(5);
PORTA = addrofphlatch[phoneindex];
delay_us(5);
PORTA = addrofphlatch[DTMFno[phoneindex] - 1];
delay_us(5);
PORTA = NULLADDRESS;
}
void checkDTMFreg(void)
{
DDRC = 0x00;
PORTC = 0x00;
PORTA = addrofDTMF[phoneindex];
delay_us(10);
if (PINC.4 == 1) {
DTMFvalid = 1;
DTMFreg[phoneindex] = PINC;
}
else
DTMFvalid = 0;
delay_us(5);
PORTA = NULLADDRESS;
}
void initialize(void)
{
//serial port set up
UCR = 0x10 + 0x08;
UBRR = 25;
DDRA = 0xf0;
PORTA = 0x0f;
//set up timer 0
reload=256-62; //value for 1 Msec
TCNT0=reload; //preload timer 1 so that is interrupts after 1 mSec.
TCCR0=3; //prescalar to 64
TIMSK=2; //turn on timer 0 overflow ISR
hookswreg = 0x00;
ringerswreg = 0x00;
for (phoneindex = 0; phoneindex < MAXPHONENO; phoneindex++) {
stateofphone[phoneindex] = IDLE;
DDRC = 0xff;
PORTC = NULLLATCH;
delay_us(5);
PORTA = addrofphlatch[phoneindex];
delay_us(5);
PORTA = NULLADDRESS;
}
//initialize ringer
DDRB = 0xff;
PORTB = 0xff;
phoneindex = 0;
DTMFvalid = 0;