mbed Phone Platform

Dependencies:   ulaw mbed ConfigFile

Revision:
2:e37117117e79
Parent:
1:0f82c574096f
Child:
3:1d5dc4107558
--- a/IpLine.cpp	Sun Dec 26 15:49:07 2010 +0000
+++ b/IpLine.cpp	Wed Jan 05 15:43:53 2011 +0000
@@ -1,245 +1,270 @@
-#include "IpLine.h"
-
-
-IpLine::IpLine (AnalogOut p_dac, AnalogIn p_adc) : dac(p_dac), adc(p_adc), dial(DIAL_SIZE), dabuf(DATA_SIZE * 4), adbuf(DATA_SIZE * 2) {
-	EthernetErr r;
-
-	mode = ModeOff;
-	status = StatusOk;
-	timeout = 0;
-	packet_num = 0;
-	dataskip = 0;
-
-	// dhcp
-	eth = new EthernetNetIf;
-	r = eth->setup();
-	if (r) {
-		printf("Error %d in setup.\n", r);
-		return;
-	}
-
-	udpsock = new UDPSocket;
-	udpsock->setOnEvent(this, &IpLine::onLisnerEvent);
-	udpsock->bind(Host(eth->getIp(), UDPPORT));
-}
-
-/// 8KHz interrupt
-void IpLine::poll () {
-	char c;
-
-	if (mode == ModeTalk && hook) {
-		// dac
-		if (dabuf.available() < DATA_SIZE) {
-			// down sample
-			dabuf.get(c);
-			dabuf.get(c);
-			dac.write_u16(ulaw2pcm(c));
-		} else
-		if (dabuf.use() < DATA_SIZE) {
-			// over sample
-			if (dataskip) {
-				dataskip = 0;
-			} else {
-				if (! dabuf.get(c)) {
-					dac.write_u16(ulaw2pcm(c));
-				} else {
-//					dac.write_u16(gaussian());
-				}
-				dataskip = 1;
-			}
-		} else {
-			// normal
-			dabuf.get(c);
-			dac.write_u16(ulaw2pcm(c));
-		}
-
-		// adc
-		adbuf.put(pcm2ulaw(adc.read_u16()));
-	}
-
-	if (timeout) {
-		timeout --;
-
-		if (timeout == 0) {
-			if (last.target) {
-				// re-try
-				send(last);
-				timeout = FREQ;
-				last.target = PhoneNone;
-			} else {
-				// timeout
-				status = StatusNg;
-			}
-		}
-	}
-}
-
-/// network
-void IpLine::netpoll () {
-
-	if (mode == ModeTalk && adbuf.use() >= DATA_SIZE) {
-		// send
-		struct ipline_packet packet;
-
-		packet.len = adbuf.get(packet.data, sizeof(packet.data));
-		if (packet.len > 0) {
-			packet.header.target = remotetarget;
-			packet.header.mode = ModeData;
-			packet.header.status = StatusNone;
-			send(packet);
-		}
-	}
-
-	Net::poll();
-}
-
-/// recv packet
-void IpLine::onLisnerEvent (UDPSocketEvent e) {
-	int len;
-	struct ipline_packet packet;
-	Host recv;
-
-	if (e != UDPSOCKET_READABLE) return;
-
-	// get data
-	len = udpsock->recvfrom((char *)&packet, sizeof(packet), &recv);
-
-	if (packet.header.status != StatusNone) {
-		// recv ack
-		if (packet.header.num == last.num) {
-			status = packet.header.status;
-			timeout = 0;
-		}
-
-	} else
-	if (packet.header.mode == ModeData) {
-		// data
-
-		dabuf.put(packet.data, packet.len);
-
-	} else
-	if (mode == ModeTalk && len > sizeof(struct ipline_header)) {
-		// enter
-		packet.header.status = StatusNg;
-
-		switch (packet.header.mode) {
-		case ModeRing:
-			// ring --> onhook, dial
-			if (mode == ModeReady) {
-				dial.put(11);
-				dial.put(packet.header.target);
-				dial.put(12);
-				hook = HookOn;
-				remote = recv;
-				packet.header.status = StatusOk;
-			}
-			break;
-		case ModeBT:
-		case ModeDisconnect:
-			if (recv.getIp() == remote.getIp()) {
-				hook = HookOff;
-				packet.header.status = StatusOk;
-			}
-			break;
-		case ModeTalk:
-			if (recv.getIp() == remote.getIp()) {
-				hook = HookOn;
-				packet.header.status = StatusOk;
-			}
-			break;
-		}
-
-		// send ack
-		send(packet.header);
-		timeout = FREQ;
-	}
-}
-
-
-/// send packet (header only)
-void IpLine::send (struct ipline_header &header) {
-
-	header.num = packet_num;
-	udpsock->sendto((char *)&header, sizeof(header), &remote);
-	memcpy(&last, &header, sizeof(last));
-
-	packet_num ++;
-	if (packet_num >= 65536) packet_num = 1;
-}
-
-/// send packet
-void IpLine::send (struct ipline_packet &packet) {
-
-	packet.header.num = packet_num;
-	udpsock->sendto((char *)&packet, sizeof(packet), &remote);
-
-	packet_num ++;
-	if (packet_num >= 256) packet_num = 0;
-}
-
-/// change mode
-int IpLine::enter (enum Mode newmode) {
-	struct ipline_header header;
-
-	mode = newmode;
-	status = StatusOk;
-
-	switch (mode) {
-	case ModeReady:
-		hook = HookOff;
-		break;
-	case ModeRing:
-	case ModeTalk:
-	case ModeBT:
-	case ModeDisconnect:
-		status = StatusNone;
-		header.target = remotetarget;
-		header.mode = mode;
-		header.status = status;
-		send(header);
-		timeout = FREQ;
-		break;
-	}
-
-	return 0;
-}
-
-/// return status
-int IpLine::scan (enum Scan type) {
-
-	switch (type) {
-	case ScanMode:
-		return mode;
-
-	case ScanStatus:
-		return status;
-
-	case ScanHook:
-		return hook;
-
-	case ScanDial:
-		char c;
-		if (dial.get(c) == 0)
-			return c;
-		break;
-
-	}
-
-	return -1;
-}
-
-/// set target
-void IpLine::settarget (enum PhoneType target, char *host) {
-    int ip0, ip1, ip2, ip3;
-
-	remotetarget = target;
-	if (host[0] >= '0' && host[0] <= '9') {
-		sscanf(host, "%d.%d.%d.%d", &ip0, &ip1, &ip2, &ip3);
-		remote.setIp(IpAddr(ip0, ip1, ip2, ip3));
-		remote.setName(NULL);
-	} else {
-		remote.setIp(NULL);
-		remote.setName(host);
-	}
-	remote.setPort(UDPPORT);
-}
+/** @file IpLine.cpp
+ * @brief IP Line Controller (mbed Phone Platform)
+ */
+
+#include "IpLine.h"
+
+IpLine::IpLine (AnalogOut p_dac, AnalogIn p_adc) : dac(p_dac), adc(p_adc), dial(DIAL_SIZE), dabuf(DATA_SIZE * 4), adbuf(DATA_SIZE * 2) {
+    EthernetErr r;
+
+    mode = ModeOff;
+    status = StatusOk;
+    timeout = 0;
+    packet_num = 0;
+    dataskip = 0;
+
+    // dhcp
+    eth = new EthernetNetIf;
+//    eth = new EthernetNetIf(IpAddr(192,168,10,200), IpAddr(255,255,255,0), IpAddr(0,0,0,0), IpAddr(0,0,0,0));
+    r = eth->setup();
+    if (r) {
+        printf("Error %d in setup.\n", r);
+        return;
+    }
+
+    udpsock = new UDPSocket;
+    udpsock->setOnEvent(this, &IpLine::onLisnerEvent);
+    udpsock->bind(Host(eth->getIp(), UDPPORT));
+}
+
+/// 8KHz interrupt
+void IpLine::intr () {
+    char c;
+
+    if (mode == ModeTalk && hook == HookOn) {
+        // dac
+        if (dabuf.available() < DATA_SIZE) {
+            // down sample
+            dabuf.get(c);
+            dabuf.get(c);
+            dac.write_u16(ulaw2pcm(c));
+        } else
+        if (dabuf.use() < DATA_SIZE) {
+            // over sample
+            if (dataskip) {
+                dataskip = 0;
+            } else {
+                if (! dabuf.get(c)) {
+                    dac.write_u16(ulaw2pcm(c));
+                } else {
+//                    dac.write_u16(gaussian());
+                }
+                dataskip = 1;
+            }
+        } else {
+            // normal
+            dabuf.get(c);
+            dac.write_u16(ulaw2pcm(c));
+        }
+
+        // adc
+//        adbuf.put(pcm2ulaw(adc.read_u16()));
+        adbuf.put(adc.read_u16() >> 8);
+    }
+
+    if (timeout) {
+        timeout --;
+
+        if (timeout == 0) {
+            if (last.target) {
+                // re-try
+                send(&last);
+                timeout = NET_TIMEOUT;
+                last.target = PhoneNone;
+            } else {
+                // timeout
+                status = StatusNg;
+            }
+        }
+    }
+}
+
+/// network
+void IpLine::poll () {
+
+    Net::poll();
+
+    if (mode == ModeTalk && adbuf.use() >= DATA_SIZE) {
+        // send
+        struct ipline_packet packet;
+
+        packet.len = adbuf.get(packet.data, DATA_SIZE);
+        if (packet.len > 0) {
+            packet.header.num = 0;
+            packet.header.target = remotetarget;
+            packet.header.mode = ModeData;
+            packet.header.status = StatusNone;
+            send(&packet);
+        }
+    }
+}
+
+/// recv packet
+void IpLine::onLisnerEvent (UDPSocketEvent e) {
+    int len;
+    struct ipline_packet packet;
+    Host recv;
+
+    if (e != UDPSOCKET_READABLE) return;
+
+    // get data
+    len = udpsock->recvfrom((char *)&packet, sizeof(packet), &recv);
+
+    if (packet.header.status != StatusNone) {
+        // recv ack
+        if (packet.header.num == last.num) {
+            status = packet.header.status;
+            timeout = 0;
+printf("(ack %d)\r\n", status);
+        }
+
+    } else
+    if (packet.header.mode == ModeData && len > sizeof(struct ipline_header)) {
+        // data
+
+        dabuf.put(packet.data, packet.len);
+
+    } else
+    if (len == sizeof(struct ipline_header)) {
+        // enter
+        packet.header.status = StatusNg;
+
+        switch (packet.header.mode) {
+        case ModeRing:
+            // ring --> onhook, dial
+            if (mode == ModeReady) {
+                dial.put(1);
+                dial.put(10);
+                dial.put(packet.header.target);
+                dial.put(12);
+                hook = HookOn;
+                remote = recv;
+                packet.header.status = StatusOk;
+            }
+            break;
+            
+        case ModeBT:
+        case ModeDisconnect:
+            if (recv.getIp() == remote.getIp()) {
+                hook = HookOff;
+                packet.header.status = StatusOk;
+            }
+            break;
+            
+        case ModeTalk:
+            if (recv.getIp() == remote.getIp()) {
+                hook = HookOn;
+                packet.header.status = StatusOk;
+            }
+            break;
+        }
+
+        // send ack
+        send(&packet.header);
+        timeout = NET_RETRY;
+
+      for (int i = 0; i < len; i ++) {
+        printf(" %02x", ((char *)&packet)[i]);
+      }
+      printf("(R)\r\n");
+    }
+}
+
+
+/// send packet (header only)
+void IpLine::send (struct ipline_header *header) {
+
+    if (! header->num) {
+        header->num = packet_num;
+        packet_num ++;
+        if (packet_num >= 65536) packet_num = 1;
+    }
+    udpsock->sendto((char *)header, sizeof(struct ipline_header), &remote);
+    memcpy(&last, header, sizeof(struct ipline_header));
+
+    for (int i = 0; i < sizeof(struct ipline_header); i ++) {
+        printf(" %02x", ((char *)header)[i]);
+    }
+    printf("(H)\r\n");
+}
+
+/// send packet
+void IpLine::send (struct ipline_packet *packet) {
+
+    if (! packet->header.num) {
+        packet->header.num = packet_num;
+        packet_num ++;
+        if (packet_num >= 65536) packet_num = 1;
+    }
+    udpsock->sendto((char *)packet, sizeof(struct ipline_packet), &remote);
+}
+
+/// change mode
+int IpLine::enter (enum Mode newmode) {
+    struct ipline_header header;
+
+    mode = newmode;
+    status = StatusOk;
+
+    switch (mode) {
+    case ModeReady:
+        hook = HookOff;
+        break;
+
+    case ModeBT:
+    case ModeDisconnect:
+        hook = HookOff;
+    case ModeRing:
+    case ModeTalk:
+        status = StatusNone;
+        header.num = 0;
+        header.target = remotetarget;
+        header.mode = mode;
+        header.status = status;
+        send(&header);
+        timeout = NET_RETRY;
+        break;
+    }
+
+    return 0;
+}
+
+/// return status
+int IpLine::scan (enum Scan type) {
+
+    switch (type) {
+    case ScanMode:
+        return mode;
+
+    case ScanStatus:
+        return status;
+
+    case ScanHook:
+        return hook;
+
+    case ScanDial:
+        char c;
+        if (dial.get(c) == 0)
+            return c;
+        break;
+
+    }
+
+    return -1;
+}
+
+/// set target
+void IpLine::settarget (enum PhoneType target, char *host) {
+    int ip0, ip1, ip2, ip3;
+
+    remotetarget = target;
+    if (host[0] >= '0' && host[0] <= '9') {
+        sscanf(host, "%d.%d.%d.%d", &ip0, &ip1, &ip2, &ip3);
+        remote.setIp(IpAddr(ip0, ip1, ip2, ip3));
+        remote.setName(NULL);
+    } else {
+        remote.setIp(NULL);
+        remote.setName(host);
+    }
+    remote.setPort(UDPPORT);
+}