Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: ulaw mbed ConfigFile
IpLine.cpp
00001 /** @file IpLine.cpp 00002 * @brief IP Line Controller (mbed Phone Platform) 00003 */ 00004 00005 #include "IpLine.h" 00006 00007 #define NET_RETRY (FREQ) 00008 #define NET_TIMEOUT (FREQ * 3) 00009 #define PACKET_IDENT 0x6465626d // "mbed" 00010 00011 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) 00012 , led_y(p25), led_g(p26), eth_link(P1_25), eth_speed(P1_26) { 00013 00014 mode = ModeOff; 00015 status = StatusNone; 00016 timeout = 0; 00017 packet_num = 1; 00018 dataskip = 0; 00019 timerled = 0; 00020 00021 eth = p_eth; 00022 led_g = eth_link ? 0 : 1; 00023 00024 udpsock = new UDPSocket; 00025 udpsock->setOnEvent(this, &IpLine::onLisnerEvent); 00026 udpsock->bind(Host(eth->getIp(), UDPPORT)); 00027 } 00028 00029 /// 8KHz interrupt 00030 void IpLine::intr () { 00031 char c; 00032 00033 if (mode == ModeTalk && hook == HookOn) { 00034 // dac 00035 00036 if (dabuf.available() < DATA_SIZE) { 00037 // down sample 00038 dabuf.get(c); 00039 dac.write_u16(ulaw2pcm(c)); 00040 dabuf.get(c); 00041 } else 00042 if (dabuf.use() < DATA_SIZE) { 00043 // over sample 00044 if (dataskip) { 00045 dataskip = 0; 00046 } else { 00047 if (! dabuf.get(c)) { 00048 dac.write_u16(ulaw2pcm(c)); 00049 } else { 00050 //dac.write_u16(gaussian()); 00051 } 00052 dataskip = 1; 00053 } 00054 } else { 00055 // normal 00056 dabuf.get(c); 00057 dac.write_u16(ulaw2pcm(c)); 00058 } 00059 00060 // adc 00061 if (wait) { 00062 wait --; 00063 } else { 00064 adbuf.put(pcm2ulaw(adc.read_u16())); 00065 // adbuf.put(adc.read_u16() >> 8); 00066 } 00067 } 00068 00069 if (timeout > 1) timeout --; 00070 if (timerled > 0) timerled --; 00071 } 00072 00073 /// network 00074 void IpLine::poll () { 00075 00076 Net::poll(); 00077 00078 led_g = eth_link ? 0 : 1; 00079 if (! timerled) led_y = 0; 00080 00081 if (mode == ModeTalk && adbuf.use() >= DATA_SIZE) { 00082 // send 00083 struct ipline_packet packet; 00084 00085 packet.len = adbuf.get(packet.data, DATA_SIZE); 00086 if (packet.len > 0) { 00087 packet.header.num = 0; 00088 packet.header.target = remotetarget; 00089 packet.header.mode = ModeData; 00090 packet.header.status = StatusNone; 00091 send(&packet); 00092 } 00093 } 00094 00095 if (timeout == 1) { 00096 if (last.target != PhoneNone) { 00097 // re-try 00098 send(&last); 00099 timeout = NET_TIMEOUT; 00100 last.target = PhoneNone; 00101 } else { 00102 // timeout 00103 status = StatusNg; 00104 } 00105 timeout = 0; 00106 } 00107 } 00108 00109 /// recv packet 00110 void IpLine::onLisnerEvent (UDPSocketEvent e) { 00111 int len; 00112 struct ipline_packet packet; 00113 Host recv; 00114 00115 if (e != UDPSOCKET_READABLE) return; 00116 00117 // get data 00118 len = udpsock->recvfrom((char *)&packet, sizeof(struct ipline_packet), &recv); 00119 led_y = 1; 00120 timerled = FREQ / 10; 00121 00122 if (packet.header.ident != PACKET_IDENT) return; 00123 00124 if (packet.header.status != StatusNone) { 00125 // recv ack 00126 if (packet.header.num == last.num) { 00127 status = packet.header.status; 00128 timeout = 0; 00129 } 00130 00131 } else 00132 if (packet.header.mode == ModeData && len > sizeof(struct ipline_header)) { 00133 // data 00134 00135 if (packet.len <= len - sizeof(struct ipline_header) - 2) { 00136 dabuf.put(packet.data, packet.len); 00137 } 00138 00139 } else 00140 if (len == sizeof(struct ipline_header)) { 00141 // enter 00142 packet.header.status = StatusNg; 00143 00144 switch (packet.header.mode) { 00145 case ModeRing: 00146 // ring --> onhook, dial 00147 if (mode == ModeReady) { 00148 dial.put(11); 00149 dial.put(packet.header.target); 00150 dial.put(12); 00151 hook = HookOn; 00152 remote = recv; 00153 packet.header.status = StatusOk; 00154 } 00155 break; 00156 00157 case ModeBT: 00158 case ModeDisconnect: 00159 if (recv.getIp() == remote.getIp()) { 00160 hook = HookOff; 00161 packet.header.status = StatusOk; 00162 } 00163 break; 00164 00165 case ModeTalk: 00166 if (recv.getIp() == remote.getIp()) { 00167 hook = HookOn; 00168 packet.header.status = StatusOk; 00169 } 00170 break; 00171 } 00172 00173 // send ack 00174 send(&packet.header); 00175 00176 for (int i = 0; i < len; i ++) { 00177 printf(" %02x", ((char *)&packet)[i]); 00178 } 00179 printf("\r\n"); 00180 00181 } 00182 } 00183 00184 00185 /// send packet (header only) 00186 void IpLine::send (struct ipline_header *header) { 00187 00188 led_y = 1; 00189 timerled = FREQ / 10; 00190 header->ident = PACKET_IDENT; 00191 if (! header->num) { 00192 header->num = packet_num; 00193 packet_num ++; 00194 if (packet_num >= 65536) packet_num = 1; 00195 } 00196 udpsock->sendto((char *)header, sizeof(struct ipline_header), &remote); 00197 memcpy(&last, header, sizeof(struct ipline_header)); 00198 } 00199 00200 /// send packet 00201 void IpLine::send (struct ipline_packet *packet) { 00202 00203 led_y = 1; 00204 timerled = FREQ / 10; 00205 packet->header.ident = PACKET_IDENT; 00206 if (! packet->header.num) { 00207 packet->header.num = packet_num; 00208 packet_num ++; 00209 if (packet_num >= 65536) packet_num = 1; 00210 } 00211 udpsock->sendto((char *)packet, sizeof(struct ipline_packet), &remote); 00212 } 00213 00214 /// change mode 00215 int IpLine::enter (enum Mode newmode) { 00216 struct ipline_header header; 00217 00218 if (eth_link) return -1; // link down 00219 00220 mode = newmode; 00221 status = StatusOk; 00222 00223 switch (mode) { 00224 case ModeReady: 00225 hook = HookOff; 00226 adbuf.clear(); 00227 dabuf.clear(); 00228 wait = FREQ / 2; 00229 break; 00230 00231 case ModeBT: 00232 case ModeDisconnect: 00233 hook = HookOff; 00234 case ModeRing: 00235 case ModeTalk: 00236 status = StatusNone; 00237 header.num = 0; 00238 header.target = remotetarget; 00239 header.mode = mode; 00240 header.status = status; 00241 send(&header); 00242 timeout = NET_RETRY; 00243 break; 00244 } 00245 00246 return 0; 00247 } 00248 00249 /// return status 00250 int IpLine::scan (enum Scan type) { 00251 00252 switch (type) { 00253 case ScanMode: 00254 return mode; 00255 00256 case ScanStatus: 00257 return status; 00258 00259 case ScanHook: 00260 return hook; 00261 00262 case ScanDial: 00263 char c; 00264 if (dial.get(c) == 0) 00265 return c; 00266 break; 00267 00268 } 00269 00270 return -1; 00271 } 00272 00273 /// set target 00274 void IpLine::settarget (enum PhoneType target, char *host) { 00275 int ip0, ip1, ip2, ip3; 00276 00277 remotetarget = target; 00278 if (host[0] >= '0' && host[0] <= '9') { 00279 sscanf(host, "%d.%d.%d.%d", &ip0, &ip1, &ip2, &ip3); 00280 remote.setIp(IpAddr(ip0, ip1, ip2, ip3)); 00281 remote.setName(NULL); 00282 } else { 00283 remote.setIp(NULL); 00284 remote.setName(host); 00285 } 00286 remote.setPort(UDPPORT); 00287 } 00288 00289 unsigned long IpLine::xor128 () { 00290 static unsigned long x = 123456789; 00291 static unsigned long y = 362436069, z = 521288629, w = 88675123; 00292 unsigned long t; 00293 t = (x ^ (x << 11)); 00294 x = y; y = z; z = w; 00295 return (w = (w ^ (w >> 19)) ^ (t ^ (t >> 8)) ); 00296 } 00297 00298 int IpLine::gaussian () { 00299 int i, j; 00300 00301 j = 0; 00302 for (i = 0; i < 12; i ++) { 00303 j = j + (xor128() >> 16); 00304 } 00305 j = (j - 0x60000) & 0xffff; 00306 return 0x3fff + (j >> 2); 00307 }
Generated on Wed Jul 13 2022 04:31:14 by
1.7.2