mbed Phone Platform

Dependencies:   ulaw mbed ConfigFile

main.cpp

Committer:
okini3939
Date:
2011-01-21
Revision:
6:bd62b12de751
Parent:
5:30e2847d241b

File content as of revision 6:bd62b12de751:

/*
 * mbed Phone Platform
 * Copyright (c) 2010 Hiroshi Suga
 * Released under the MIT License: http://mbed.org/license/mit
 */

/** @file main.cpp
 * @brief mbed Phone Platform
 */

#include "mbed.h"
#include "EthernetNetIf.h"
#include "phone.h"
#include "Line.h"
#include "IpLine.h"

EthernetNetIf *eth;

Serial pc(USBTX, USBRX);
Ticker ticker;

DigitalOut led1(LED1), led2(LED2), led3(LED3), led4(LED4);

AnalogIn adc(p17);
AnalogOut dac(p18);
DigitalOut mixlocal(p21), mixline(p22), micsp(p23);
Line line1(p12, p13, p11, dac);
Line line2(p14, p15, p16, dac);
IpLine *ipline;

volatile int timeout, dialcount, useipline;
volatile enum PhoneType activesrc, activedest;
char dial[DIAL_SIZE];
struct PhoneBook phonebook[PB_SIZE];

void int_sample () {
    line1.intr();
    line2.intr();
    if (useipline) {
        ipline->intr();
    }

    if (timeout) timeout --;
}

int getpb (enum PhoneType *target, char *hostname) {
    int i, j;

    if (dial[0] == 11 && dial[1] >= 1 && dial[1] <= 3) {
        *target = (enum PhoneType)dial[1];
        hostname[0] = 0;
        return 1;
    }

    for (i = 0; i < PB_SIZE; i ++) {
        for (j = 0; j < DIAL_SIZE; j ++) {
            if (phonebook[i].dial[j] == 0 && dial[j] == 0) {
                *target = phonebook[i].target;
                strncpy(hostname, phonebook[i].hostname, HOSTNAME_SIZE);
                return 1;
            }
            if (phonebook[i].dial[j] == 0 || dial[j] == 0 ||
              j >= dialcount || phonebook[i].dial[j] != dial[j]) break;
        }
    }

    return 0;
}

void enteranalog (enum PhoneType target) {

    micsp = 0;
    mixlocal = 0;
    mixline = 0;

    wait_ms(1);
    dac.write_u16(0x7fff);

    switch (target) {
    case PhoneLine1:
    case PhoneLine2:
    case PhoneIpLine:
        mixline = 1;
        break;
    case PhoneMicSp:
        micsp = 1;
        mixlocal = 1;
        break;
    }
}

int enterline (enum PhoneType target, enum Mode mode) {

    switch (target) {
    case PhoneLine1:
        return line1.enter(mode);
    case PhoneLine2:
        return line2.enter(mode);
/*
    case PhoneMicSp:
        return micsp.enter(mode);
*/
    case PhoneIpLine:
        return ipline->enter(mode);
    }
    return 0;
}

int scanline (enum PhoneType target, enum Scan type) {

    switch (target) {
    case PhoneLine1:
        return line1.scan(type);
    case PhoneLine2:
        return line2.scan(type);
/*
    case PhoneMicSp:
        return micsp.scan(type);
*/
    case PhoneIpLine:
        return ipline->scan(type);
    }
    return 0;
}

void checkline (enum PhoneType num) {
    int i;

    switch ((enum Mode)scanline(num, ScanMode)) {
    case ModeReady:
        if (scanline(num, ScanHook) == HookOn && activesrc == PhoneNone) {
            // on hook, dial tone
            dialcount = 0;
            enteranalog(num);
            enterline(num, ModeDT);
            activesrc = num;
        }
        break;

    case ModeDT:
    case ModeDial:
        if (scanline(num, ScanHook) == HookOff) {
            // off hook, exit
            enterline(num, ModeReady);
            activesrc = PhoneNone;
            break;
        }
        i = scanline(num, ScanDial);
        if (i > 0 && i < 12) {
            // detect dial
            dial[dialcount] = i;
            dialcount ++;
pc.printf("Dial [%d]\r\n", i);
            if (scanline(num, ScanMode) == ModeDT) enterline(num, ModeDial);
            timeout = DIAL_TIMEOUT;
        }
        if ((! timeout && dialcount > 0) || dialcount >= DIAL_SIZE || i >= 12) {
            char buf[HOSTNAME_SIZE];
            enum PhoneType p;
            // call
            dial[dialcount] = 0;
            if (getpb(&p, buf)) {
printf("-> %d %s\r\n", p, buf);
                if (buf[0] == 0) {
                    activedest = p;
                } else
                if (useipline) {
                    activedest = PhoneIpLine;
                    ipline->settarget(p, buf);
                }
                enterline(num, ModeCall);
                enterline(activedest, ModeRing);
                timeout = CALL_TIMEOUT;
            } else {
                enterline(num, ModeBT);
            }
        }
        break;

    case ModeCall:
        if (scanline(num, ScanHook) == HookOff) {
            // off hook, exit
            enterline(num, ModeReady);
            enterline(activedest, ModeDisconnect);
            activesrc = PhoneNone;
            break;
        }
        i = scanline(activedest, ScanStatus);
        if (i == StatusOk) {
            // ok call, ring back tone
            enterline(num, ModeRBT);
        }
        if (timeout == 0 || i == StatusNg) {
            // timeout, busy
            enterline(num, ModeBT);
            enterline(activedest, ModeDisconnect);
            break;
        }
        break;

    case ModeRBT:
        if (scanline(num, ScanHook) == HookOff) {
            // off hook, exit
            enterline(num, ModeReady);
            enterline(activedest, ModeDisconnect);
            activesrc = PhoneNone;
        }
        break;

    case ModeRing:
        if (scanline(num, ScanHook) == HookOn) {
            // on hook, connect
            if (num == PhoneIpLine || activesrc == PhoneIpLine) {
                enteranalog(PhoneIpLine);
            } else {
                enteranalog(PhoneNone);
            }
            enterline(num, ModeTalk);
            enterline(activesrc, ModeTalk);
        }
        break;

    case ModeTalk:
        if (scanline(num, ScanHook) == HookOff) {
            // off hook, exit
            enterline(num, ModeReady);
            enterline(num == activesrc ? activedest : activesrc, ModeDisconnect);
            activesrc = PhoneNone;
            break;
        }
        if (scanline(activedest, ScanStatus) == StatusNg) {
            // disconnect
            enterline(num, ModeBT);
        }
        break;

    case ModeBT:
        if (scanline(num, ScanHook) == HookOff) {
            // off hook, exit
            enterline(num, ModeReady);
            if (activesrc == num) activesrc = PhoneNone;
            if (activedest == num) activedest = PhoneNone;
        }
        break;

    case ModeDisconnect:
        enterline(num, ModeBT);
        break;

    }

}


int main () {
    int i;
    
    timeout = 0;
    useipline = 0;
    dialcount = 0;
    activesrc = PhoneNone;
    activedest = PhoneNone;

    config();

    line1.enter(ModeReady);
    line2.enter(ModeReady);
    if (useipline) {
        ipline = new IpLine(eth, dac, adc);
        ipline->enter(ModeReady);
    }

//    NVIC_SetPriority(TIMER3_IRQn, 0); // preemption=1, sub-priority=1
    ticker.attach_us(&int_sample, 1000000 / FREQ);

    for (;;) {
        if (useipline) {
            led1 = 1;
            ipline->poll();
            led1 = 0;
        }
        led2 = 1;
        line1.poll();
        led2 = 0;
        led3 = 1;
        line2.poll();
        led3 = 0;

        i = scanline(PhoneLine1, ScanMode);
        checkline(PhoneLine1);
        if (i != scanline(PhoneLine1, ScanMode))
            pc.printf("(1) %d -> %d\r\n", i, scanline(PhoneLine1, ScanMode));
        
        i = scanline(PhoneLine2, ScanMode);
        checkline(PhoneLine2);
        if (i != scanline(PhoneLine2, ScanMode))
            pc.printf("(2) %d -> %d\r\n", i, scanline(PhoneLine2, ScanMode));
        
        if (useipline) {
            i = scanline(PhoneIpLine, ScanMode);
            checkline(PhoneIpLine);
            if (i != scanline(PhoneIpLine, ScanMode))
                pc.printf("(3) %d -> %d\r\n", i, scanline(PhoneIpLine, ScanMode));
        }
        
    }
}