mbed Phone Platform
Dependencies: ulaw mbed ConfigFile
IpLine.cpp
- Committer:
- okini3939
- Date:
- 2011-01-21
- Revision:
- 6:bd62b12de751
- Parent:
- 5:30e2847d241b
File content as of revision 6:bd62b12de751:
/** @file IpLine.cpp * @brief IP Line Controller (mbed Phone Platform) */ #include "IpLine.h" #define NET_RETRY (FREQ) #define NET_TIMEOUT (FREQ * 3) #define PACKET_IDENT 0x6465626d // "mbed" IpLine::IpLine (EthernetNetIf *p_eth, AnalogOut p_dac, AnalogIn p_adc) : dac(p_dac), adc(p_adc), dial(DIAL_SIZE), dabuf(DATA_SIZE * 4), adbuf(DATA_SIZE * 2) , led_y(p25), led_g(p26), eth_link(P1_25), eth_speed(P1_26) { mode = ModeOff; status = StatusNone; timeout = 0; packet_num = 1; dataskip = 0; timerled = 0; eth = p_eth; led_g = eth_link ? 0 : 1; 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); dac.write_u16(ulaw2pcm(c)); dabuf.get(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 if (wait) { wait --; } else { adbuf.put(pcm2ulaw(adc.read_u16())); // adbuf.put(adc.read_u16() >> 8); } } if (timeout > 1) timeout --; if (timerled > 0) timerled --; } /// network void IpLine::poll () { Net::poll(); led_g = eth_link ? 0 : 1; if (! timerled) led_y = 0; 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); } } if (timeout == 1) { if (last.target != PhoneNone) { // re-try send(&last); timeout = NET_TIMEOUT; last.target = PhoneNone; } else { // timeout status = StatusNg; } timeout = 0; } } /// 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(struct ipline_packet), &recv); led_y = 1; timerled = FREQ / 10; if (packet.header.ident != PACKET_IDENT) return; 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 && len > sizeof(struct ipline_header)) { // data if (packet.len <= len - sizeof(struct ipline_header) - 2) { 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(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); for (int i = 0; i < len; i ++) { printf(" %02x", ((char *)&packet)[i]); } printf("\r\n"); } } /// send packet (header only) void IpLine::send (struct ipline_header *header) { led_y = 1; timerled = FREQ / 10; header->ident = PACKET_IDENT; 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)); } /// send packet void IpLine::send (struct ipline_packet *packet) { led_y = 1; timerled = FREQ / 10; packet->header.ident = PACKET_IDENT; 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; if (eth_link) return -1; // link down mode = newmode; status = StatusOk; switch (mode) { case ModeReady: hook = HookOff; adbuf.clear(); dabuf.clear(); wait = FREQ / 2; 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); } unsigned long IpLine::xor128 () { static unsigned long x = 123456789; static unsigned long y = 362436069, z = 521288629, w = 88675123; unsigned long t; t = (x ^ (x << 11)); x = y; y = z; z = w; return (w = (w ^ (w >> 19)) ^ (t ^ (t >> 8)) ); } int IpLine::gaussian () { int i, j; j = 0; for (i = 0; i < 12; i ++) { j = j + (xor128() >> 16); } j = (j - 0x60000) & 0xffff; return 0x3fff + (j >> 2); }