mbed Phone Platform

Dependencies:   ulaw mbed ConfigFile

Files at this revision

API Documentation at this revision

Comitter:
okini3939
Date:
Mon Dec 20 22:55:29 2010 +0000
Child:
1:0f82c574096f
Commit message:

Changed in this revision

Line.cpp Show annotated file Show diff for this revision Revisions of this file
Line.h Show annotated file Show diff for this revision Revisions of this file
RingBuffer.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
main.h Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
ulaw.lib Show annotated file Show diff for this revision Revisions of this file
--- /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