mbed Phone Platform

Dependencies:   ulaw mbed ConfigFile

main.cpp

Committer:
okini3939
Date:
2011-01-07
Revision:
4:41a3534d085f
Parent:
3:1d5dc4107558
Child:
5:30e2847d241b

File content as of revision 4:41a3534d085f:

/*
 * 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 "phone.h"
#include "Line.h"
#include "IpLine.h"

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(dac, adc);

DigitalOut led_y(p25), led_g(p26);
DigitalIn eth_link(P1_25), eth_speed(P1_26);

volatile int timeout;
int dialcount;
char dial[DIAL_SIZE];
enum PhoneType activesrc, activedest;

struct PhoneBook phonebook[PB_SIZE] = {
    {{1, 10, 1}, PhoneLine1, ""},
    {{1, 10, 2}, PhoneLine2, ""},
    {{1, 10, 3}, PhoneMicSp, ""},
    {{2, 10, 1}, PhoneLine1, "192.168.0.2"},
    {{2, 10, 2}, PhoneLine2, "192.168.0.2"},
    {{2, 10, 3}, PhoneMicSp, "192.168.0.2"}
/*
    {{2, 10, 1}, PhoneLine1, "192.168.10.100"},
    {{2, 10, 2}, PhoneLine2, "192.168.10.100"},
    {{2, 10, 3}, PhoneMicSp, "192.168.10.100"}
*/
};


void int_sample () {
    line1.intr();
    line2.intr();
    ipline.intr();

    if (timeout) timeout --;
}

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

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

    return 0;
}

void enteranalog (enum PhoneType target) {

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

    wait_ms(1);
    dac = 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
            if (getpb(&p, buf)) {
                if (buf[0] == 0) {
                    activedest = p;
                } else {
                    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;
    dialcount = 0;
    activesrc = PhoneNone;
    activedest = PhoneNone;
    line1.enter(ModeReady);
    line2.enter(ModeReady);
    ipline.enter(ModeReady);

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

    for (;;) {
        ipline.poll();
        line1.poll();
        line2.poll();

        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));
        
        i = scanline(PhoneIpLine, ScanMode);
        checkline(PhoneIpLine);
        if (i != scanline(PhoneIpLine, ScanMode))
            pc.printf("(3) %d -> %d\r\n", i, scanline(PhoneIpLine, ScanMode));

        // debug        
        if(pc.readable()) {
            if (pc.getc() == 'a') {
              char buf[30];
              enum PhoneType p;
              dial[0] = 2;
              dial[1] = 10;
              dial[2] = 1;
              dialcount = 3;
              if (getpb(&p, buf)) {
                if (buf[0] != 0) {
                    activedest = PhoneIpLine;
                    ipline.settarget(p, buf);
                    enterline(PhoneLine1, ModeCall);
                    enterline(activedest, ModeRing);
                }
              }
            }
        }
        
    }
}