mbed Phone Platform
Dependencies: ulaw mbed ConfigFile
IpLine.cpp
- Committer:
- okini3939
- Date:
- 2011-01-05
- Revision:
- 2:e37117117e79
- Parent:
- 1:0f82c574096f
- Child:
- 3:1d5dc4107558
File content as of revision 2:e37117117e79:
/** @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); }