mbed Phone Platform
Dependencies: ulaw mbed ConfigFile
Diff: IpLine.cpp
- 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); +}