mbed Phone Platform
Dependencies: ulaw mbed ConfigFile
Revision 0:f18953137cb4, committed 2010-12-20
- Comitter:
- okini3939
- Date:
- Mon Dec 20 22:55:29 2010 +0000
- Child:
- 1:0f82c574096f
- Commit message:
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Line.cpp Mon Dec 20 22:55:29 2010 +0000 @@ -0,0 +1,214 @@ +#include "Line.h" + +#define RING_ON FREQ +#define RING_OFF (FREQ * 3) +#define RING_PULSE (FREQ / 16) +#define TONE_DT (FREQ / 400) +#define TONE_RBT_ON FREQ +#define TONE_RBT_OFF (FREQ * 3) +#define TONE_BT_ON (FREQ / 2) +#define TONE_BT_OFF FREQ +#define HOOK_TIME FREQ +#define DIAL_TIME (FREQ / 2) + +const unsigned short tonetable[TONE_DT] = { + 0x7fff, 0x98f4, 0xaf78, 0xc156, 0xcccf, 0xd0c3, 0xcccf, 0xc156, 0xaf78, 0x98f4, + 0x7fff, 0x6709, 0x5085, 0x3ea7, 0x332e, 0x2f3a, 0x332e, 0x3ea7, 0x5085, 0x6709 +}; + +Line::Line (PinName p_line, PinName p_xline, PinName p_hook, AnalogOut p_dac) : line(p_line), xline(p_xline), hook(p_hook), dac(p_dac), dial(DIAL_SIZE) { + hook.mode(PullUp); + mode = ModeOff; + status = StatusOk; + dialtimer = 0; + dialcount = 0; + hooktimer = 0; + tonecount = 0; + hook_last = hook; +} + +/// 8KHz interrupt +void Line::poll () { + + switch (mode) { + case ModeRing: + ring(); + break; + + case ModeDT: + tone(DialTone); + break; + + case ModeRBT: + tone(RingBackTone); + break; + + case ModeDisconnect: + tone(BusyTone); + break; + + } + + if (hook) { + // off hook + if (hooktimer) hooktimer --; + + if (! hook_last) { + // dial trigger + dialtimer = DIAL_TIME; + dialcount ++; + } + } else { + // on hook + hooktimer = HOOK_TIME; + } + hook_last = hook; + + if (dialtimer) { + dialtimer --; + + if (dialtimer == 0 && dialcount && ! hook) { + // dial detected + dial.put(dialcount); + dialcount = 0; + } + } else { + dialcount = 0; + } +} + +/// change mode +int Line::enter (enum Mode newmode) { + + // cleanup + switch (mode) { + case ModeRing: + case ModeOff: + power(1); + break; + + case ModeDT: + case ModeRBT: + case ModeBT: + dac = 0x7fff; + break; + + } + + mode = newmode; + + switch (mode) { + case ModeReady: + // ready + power(1); + status = StatusOk; + break; + + case ModeDT: + case ModeRBT: + case ModeBT: + // tone + tonecount = 0; + status = StatusOk; + break; + + case ModeOff: + // suspend + power(0); + status = StatusOk; + break; + + default: + status = StatusOk; + break; + + } + + return 0; +} + +/// return status +int Line::scan (enum Scan type) { + + switch (type) { + case ScanMode: + return (int)mode; + + case ScanStatus: + return (int)status; + + case ScanHook: + return hooktimer ? HookOn : HookOff; + + case ScanDial: + char c; + if (! dial.get(c)) { + return c; + } + break; + + } + + return -1; +} + +/// controll power +void Line::power (int flg) { + if (flg > 0) { + xline = 0; + wait_ms(1); + line = 1; + } else + if (flg < 0) { + line = 0; + wait_ms(1); + xline = 1; + } else { + line = 0; + xline = 0; + } +} + +/// ring +void Line::ring () { + if (hook && tonecount < RING_ON) { + // off hook + switch (tonecount % RING_PULSE) { + case 0: + Line::power(0); + break; + case RING_PULSE / 10: + Line::power(-1); + break; + case RING_PULSE / 2: + Line::power(0); + break; + case RING_PULSE / 2 + RING_PULSE / 10: + Line::power(1); + break; + } + } + + tonecount ++; + if (tonecount >= RING_OFF) tonecount = 0; +} + +/// tone +void Line::tone (enum Tone type) { + if (! hook && ( type == DialTone || + (type == RingBackTone && tonecount < TONE_RBT_ON) || + (type == BusyTone && tonecount < TONE_BT_ON) ) ) { + // on hook + dac.write_u16(tonetable[tonecount % TONE_DT]); + } else { + // off hook + dac.write_u16(0x7fff); + } + + tonecount ++; + if ( (type == DialTone && tonecount >= TONE_DT) || + (type == RingBackTone && tonecount >= TONE_RBT_OFF) || + (type == BusyTone && tonecount >= TONE_BT_OFF) ) { + tonecount = 0; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Line.h Mon Dec 20 22:55:29 2010 +0000 @@ -0,0 +1,26 @@ +#include "main.h" +#include "mbed.h" +#include "RingBuffer.h" + +class Line { +public: + Line (PinName p_line, PinName p_xline, PinName p_hook, AnalogOut p_dac); + + void poll (); + int enter (enum Mode); + int scan (enum Scan); + +private: + enum Mode mode; + enum Status status; + int dialtimer, dialcount, hooktimer, tonecount; + int hook_last; + DigitalOut line, xline; + DigitalIn hook; + AnalogOut dac; + RingBuffer dial; + + void power (int); + void ring (); + void tone (enum Tone); +};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/RingBuffer.lib Mon Dec 20 22:55:29 2010 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/okini3939/code/RingBuffer/#ea0c0a46dbdd
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Mon Dec 20 22:55:29 2010 +0000 @@ -0,0 +1,236 @@ +/* + * mbed Phone Platform + * Copyright (c) 2010 Hiroshi Suga + * Released under the MIT License: http://mbed.org/license/mit + */ + +/** @file + * @brief mbed Phone Platform + */ +#include "mbed.h" +#include "Line.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); + +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; + +void int_sample () { + if (timeout) timeout --; + line1.poll(); + line2.poll(); +// Net::poll(); +} + +int dialbook () { + return PhoneLine2; +} + +void enteranalog (enum PhoneType target) { + + micsp = 0; + mixlocal = 0; + mixline = 0; + + wait_ms(1); + dac = 0x7fff; + + switch (target) { + case PhoneLine1: + case PhoneLine2: + 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: + ipline.target(dial[1]); + 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: + ipline.target(dial[1]); + 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) { + // detect dial + dial[dialcount] = i; + dialcount ++; +pc.printf(" [ %d ] ", i); + if (scanline(num, ScanMode) == ModeDT) enterline(num, ModeDial); + timeout = FREQ * 5; + } + if ((! timeout && dialcount > 0) || dialcount >= DIAL_SIZE) { + // call + activedest = (enum PhoneType)dialbook(); + enterline(num, ModeCall); + enterline(activedest, ModeRing); + timeout = FREQ * 10; + } + break; + + case ModeCall: + if (scanline(num, ScanHook) == HookOff) { + // off hook, exit + enterline(num, ModeReady); + enterline(activedest, ModeDisconnect); + activesrc = PhoneNone; + break; + } + if (timeout == 0) { + // timeout, busy + enterline(num, ModeBT); + enterline(activedest, ModeDisconnect); + break; + } + if (scanline(num, ScanStatus) == StatusOk) { + // ok call, ring back tone + enterline(num, ModeRBT); + } + 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(activesrc); + } 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(num, 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, len; + char buf[MTU]; + + timeout = 0; + dialcount = 0; + activesrc = PhoneNone; + activedest = PhoneNone; + line1.enter(ModeReady); + line2.enter(ModeReady); + + ticker.attach_us(&int_sample, 1000000 / FREQ); + + for (;;) { + pc.printf("1: %d - ", scanline(PhoneLine1, ScanMode)); + checkline(PhoneLine1); + pc.printf("%d / ", scanline(PhoneLine1, ScanMode)); + pc.printf("2: %d - ", scanline(PhoneLine2, ScanMode)); + checkline(PhoneLine2); + pc.printf("%d\r\n", scanline(PhoneLine2, ScanMode)); + wait(0.2); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.h Mon Dec 20 22:55:29 2010 +0000 @@ -0,0 +1,54 @@ +#ifndef MAIN_H +#define MAIN_H + +#define FREQ 8000 +#define MTU 720 +#define UDPSIZE 720 +#define BUFSIZE (UDPSIZE * 2) +#define UDPPORT 20080 +#define DIAL_SIZE 10 + +enum PhoneType { + PhoneNone, + PhoneLine1, + PhoneLine2, + PhoneMicSp, + PhoneIpLine, +}; + +enum Status { + StatusNone, + StatusOk, + StatusNg, +}; + +enum Mode { + ModeOff, + ModeReady, + ModeDT, + ModeDial, + ModeCall, + ModeRing, + ModeRBT, + ModeTalk, + ModeBT, + ModeDisconnect, +}; + +enum Scan { + ScanMode, + ScanStatus, + ScanHook, + ScanDial, +}; + +enum Tone { + DialTone, + RingBackTone, + BusyTone, +}; + +#define HookOff 0 +#define HookOn 1 + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Mon Dec 20 22:55:29 2010 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/e2ac27c8e93e
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ulaw.lib Mon Dec 20 22:55:29 2010 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/okini3939/code/ulaw/#546b99dee7bb