mbed Phone Platform

Dependencies:   ulaw mbed ConfigFile

Committer:
okini3939
Date:
Thu Jan 20 13:50:10 2011 +0000
Revision:
5:30e2847d241b
Parent:
4:41a3534d085f
Child:
6:bd62b12de751

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
okini3939 2:e37117117e79 1 /** @file IpLine.cpp
okini3939 2:e37117117e79 2 * @brief IP Line Controller (mbed Phone Platform)
okini3939 2:e37117117e79 3 */
okini3939 2:e37117117e79 4
okini3939 2:e37117117e79 5 #include "IpLine.h"
okini3939 2:e37117117e79 6
okini3939 4:41a3534d085f 7 #define NET_RETRY (FREQ)
okini3939 4:41a3534d085f 8 #define NET_TIMEOUT (FREQ * 3)
okini3939 4:41a3534d085f 9 #define PACKET_IDENT 0x6465626d // "mbed"
okini3939 4:41a3534d085f 10
okini3939 3:1d5dc4107558 11 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)
okini3939 5:30e2847d241b 12 , led_y(p25), led_g(p26), eth_link(P1_25), eth_speed(P1_26) {
okini3939 2:e37117117e79 13 EthernetErr r;
okini3939 2:e37117117e79 14
okini3939 2:e37117117e79 15 mode = ModeOff;
okini3939 3:1d5dc4107558 16 status = StatusNone;
okini3939 2:e37117117e79 17 timeout = 0;
okini3939 3:1d5dc4107558 18 packet_num = 1;
okini3939 2:e37117117e79 19 dataskip = 0;
okini3939 2:e37117117e79 20
okini3939 2:e37117117e79 21 // dhcp
okini3939 2:e37117117e79 22 eth = new EthernetNetIf;
okini3939 2:e37117117e79 23 // eth = new EthernetNetIf(IpAddr(192,168,10,200), IpAddr(255,255,255,0), IpAddr(0,0,0,0), IpAddr(0,0,0,0));
okini3939 5:30e2847d241b 24 led_g = eth_link ? 0 : 1;
okini3939 2:e37117117e79 25 r = eth->setup();
okini3939 2:e37117117e79 26 if (r) {
okini3939 2:e37117117e79 27 printf("Error %d in setup.\n", r);
okini3939 2:e37117117e79 28 return;
okini3939 2:e37117117e79 29 }
okini3939 2:e37117117e79 30
okini3939 2:e37117117e79 31 udpsock = new UDPSocket;
okini3939 2:e37117117e79 32 udpsock->setOnEvent(this, &IpLine::onLisnerEvent);
okini3939 2:e37117117e79 33 udpsock->bind(Host(eth->getIp(), UDPPORT));
okini3939 2:e37117117e79 34 }
okini3939 2:e37117117e79 35
okini3939 2:e37117117e79 36 /// 8KHz interrupt
okini3939 2:e37117117e79 37 void IpLine::intr () {
okini3939 2:e37117117e79 38 char c;
okini3939 2:e37117117e79 39
okini3939 2:e37117117e79 40 if (mode == ModeTalk && hook == HookOn) {
okini3939 2:e37117117e79 41 // dac
okini3939 5:30e2847d241b 42
okini3939 2:e37117117e79 43 if (dabuf.available() < DATA_SIZE) {
okini3939 2:e37117117e79 44 // down sample
okini3939 2:e37117117e79 45 dabuf.get(c);
okini3939 5:30e2847d241b 46 dac.write_u16(ulaw2pcm(c));
okini3939 2:e37117117e79 47 dabuf.get(c);
okini3939 2:e37117117e79 48 } else
okini3939 2:e37117117e79 49 if (dabuf.use() < DATA_SIZE) {
okini3939 2:e37117117e79 50 // over sample
okini3939 2:e37117117e79 51 if (dataskip) {
okini3939 2:e37117117e79 52 dataskip = 0;
okini3939 2:e37117117e79 53 } else {
okini3939 2:e37117117e79 54 if (! dabuf.get(c)) {
okini3939 2:e37117117e79 55 dac.write_u16(ulaw2pcm(c));
okini3939 2:e37117117e79 56 } else {
okini3939 4:41a3534d085f 57 dac.write_u16(gaussian());
okini3939 2:e37117117e79 58 }
okini3939 2:e37117117e79 59 dataskip = 1;
okini3939 2:e37117117e79 60 }
okini3939 2:e37117117e79 61 } else {
okini3939 2:e37117117e79 62 // normal
okini3939 2:e37117117e79 63 dabuf.get(c);
okini3939 2:e37117117e79 64 dac.write_u16(ulaw2pcm(c));
okini3939 2:e37117117e79 65 }
okini3939 2:e37117117e79 66
okini3939 2:e37117117e79 67 // adc
okini3939 5:30e2847d241b 68 adbuf.put(pcm2ulaw(adc.read_u16()));
okini3939 5:30e2847d241b 69 // adbuf.put(adc.read_u16() >> 8);
okini3939 2:e37117117e79 70 }
okini3939 2:e37117117e79 71
okini3939 5:30e2847d241b 72 if (timeout > 1) timeout --;
okini3939 2:e37117117e79 73 }
okini3939 2:e37117117e79 74
okini3939 2:e37117117e79 75 /// network
okini3939 2:e37117117e79 76 void IpLine::poll () {
okini3939 2:e37117117e79 77
okini3939 2:e37117117e79 78 Net::poll();
okini3939 2:e37117117e79 79
okini3939 5:30e2847d241b 80 led_g = eth_link ? 0 : 1;
okini3939 5:30e2847d241b 81 led_y = 0;
okini3939 5:30e2847d241b 82
okini3939 2:e37117117e79 83 if (mode == ModeTalk && adbuf.use() >= DATA_SIZE) {
okini3939 2:e37117117e79 84 // send
okini3939 2:e37117117e79 85 struct ipline_packet packet;
okini3939 2:e37117117e79 86
okini3939 2:e37117117e79 87 packet.len = adbuf.get(packet.data, DATA_SIZE);
okini3939 2:e37117117e79 88 if (packet.len > 0) {
okini3939 2:e37117117e79 89 packet.header.num = 0;
okini3939 2:e37117117e79 90 packet.header.target = remotetarget;
okini3939 2:e37117117e79 91 packet.header.mode = ModeData;
okini3939 2:e37117117e79 92 packet.header.status = StatusNone;
okini3939 2:e37117117e79 93 send(&packet);
okini3939 2:e37117117e79 94 }
okini3939 2:e37117117e79 95 }
okini3939 5:30e2847d241b 96
okini3939 5:30e2847d241b 97 if (timeout == 1) {
okini3939 5:30e2847d241b 98 if (last.target != PhoneNone) {
okini3939 5:30e2847d241b 99 // re-try
okini3939 5:30e2847d241b 100 send(&last);
okini3939 5:30e2847d241b 101 timeout = NET_TIMEOUT;
okini3939 5:30e2847d241b 102 last.target = PhoneNone;
okini3939 5:30e2847d241b 103 } else {
okini3939 5:30e2847d241b 104 // timeout
okini3939 5:30e2847d241b 105 status = StatusNg;
okini3939 5:30e2847d241b 106 }
okini3939 5:30e2847d241b 107 timeout = 0;
okini3939 5:30e2847d241b 108 }
okini3939 2:e37117117e79 109 }
okini3939 2:e37117117e79 110
okini3939 2:e37117117e79 111 /// recv packet
okini3939 2:e37117117e79 112 void IpLine::onLisnerEvent (UDPSocketEvent e) {
okini3939 2:e37117117e79 113 int len;
okini3939 2:e37117117e79 114 struct ipline_packet packet;
okini3939 2:e37117117e79 115 Host recv;
okini3939 2:e37117117e79 116
okini3939 2:e37117117e79 117 if (e != UDPSOCKET_READABLE) return;
okini3939 2:e37117117e79 118
okini3939 2:e37117117e79 119 // get data
okini3939 5:30e2847d241b 120 led_g = 0;
okini3939 3:1d5dc4107558 121 len = udpsock->recvfrom((char *)&packet, sizeof(struct ipline_packet), &recv);
okini3939 2:e37117117e79 122
okini3939 4:41a3534d085f 123 if (packet.header.ident != PACKET_IDENT) return;
okini3939 3:1d5dc4107558 124
okini3939 2:e37117117e79 125 if (packet.header.status != StatusNone) {
okini3939 2:e37117117e79 126 // recv ack
okini3939 2:e37117117e79 127 if (packet.header.num == last.num) {
okini3939 2:e37117117e79 128 status = packet.header.status;
okini3939 2:e37117117e79 129 timeout = 0;
okini3939 2:e37117117e79 130 }
okini3939 2:e37117117e79 131
okini3939 2:e37117117e79 132 } else
okini3939 2:e37117117e79 133 if (packet.header.mode == ModeData && len > sizeof(struct ipline_header)) {
okini3939 2:e37117117e79 134 // data
okini3939 2:e37117117e79 135
okini3939 5:30e2847d241b 136 if (packet.len <= len - sizeof(struct ipline_header) - 2) {
okini3939 5:30e2847d241b 137 dabuf.put(packet.data, packet.len);
okini3939 5:30e2847d241b 138 }
okini3939 2:e37117117e79 139
okini3939 2:e37117117e79 140 } else
okini3939 2:e37117117e79 141 if (len == sizeof(struct ipline_header)) {
okini3939 2:e37117117e79 142 // enter
okini3939 2:e37117117e79 143 packet.header.status = StatusNg;
okini3939 2:e37117117e79 144
okini3939 2:e37117117e79 145 switch (packet.header.mode) {
okini3939 2:e37117117e79 146 case ModeRing:
okini3939 2:e37117117e79 147 // ring --> onhook, dial
okini3939 2:e37117117e79 148 if (mode == ModeReady) {
okini3939 2:e37117117e79 149 dial.put(1);
okini3939 2:e37117117e79 150 dial.put(10);
okini3939 2:e37117117e79 151 dial.put(packet.header.target);
okini3939 2:e37117117e79 152 dial.put(12);
okini3939 2:e37117117e79 153 hook = HookOn;
okini3939 2:e37117117e79 154 remote = recv;
okini3939 2:e37117117e79 155 packet.header.status = StatusOk;
okini3939 2:e37117117e79 156 }
okini3939 2:e37117117e79 157 break;
okini3939 2:e37117117e79 158
okini3939 2:e37117117e79 159 case ModeBT:
okini3939 2:e37117117e79 160 case ModeDisconnect:
okini3939 2:e37117117e79 161 if (recv.getIp() == remote.getIp()) {
okini3939 2:e37117117e79 162 hook = HookOff;
okini3939 2:e37117117e79 163 packet.header.status = StatusOk;
okini3939 2:e37117117e79 164 }
okini3939 2:e37117117e79 165 break;
okini3939 2:e37117117e79 166
okini3939 2:e37117117e79 167 case ModeTalk:
okini3939 2:e37117117e79 168 if (recv.getIp() == remote.getIp()) {
okini3939 2:e37117117e79 169 hook = HookOn;
okini3939 2:e37117117e79 170 packet.header.status = StatusOk;
okini3939 2:e37117117e79 171 }
okini3939 2:e37117117e79 172 break;
okini3939 2:e37117117e79 173 }
okini3939 2:e37117117e79 174
okini3939 2:e37117117e79 175 // send ack
okini3939 2:e37117117e79 176 send(&packet.header);
okini3939 3:1d5dc4107558 177 /*
okini3939 2:e37117117e79 178 for (int i = 0; i < len; i ++) {
okini3939 2:e37117117e79 179 printf(" %02x", ((char *)&packet)[i]);
okini3939 2:e37117117e79 180 }
okini3939 3:1d5dc4107558 181 */
okini3939 2:e37117117e79 182 }
okini3939 2:e37117117e79 183 }
okini3939 2:e37117117e79 184
okini3939 2:e37117117e79 185
okini3939 2:e37117117e79 186 /// send packet (header only)
okini3939 2:e37117117e79 187 void IpLine::send (struct ipline_header *header) {
okini3939 2:e37117117e79 188
okini3939 5:30e2847d241b 189 led_y = 1;
okini3939 4:41a3534d085f 190 header->ident = PACKET_IDENT;
okini3939 2:e37117117e79 191 if (! header->num) {
okini3939 2:e37117117e79 192 header->num = packet_num;
okini3939 2:e37117117e79 193 packet_num ++;
okini3939 2:e37117117e79 194 if (packet_num >= 65536) packet_num = 1;
okini3939 2:e37117117e79 195 }
okini3939 2:e37117117e79 196 udpsock->sendto((char *)header, sizeof(struct ipline_header), &remote);
okini3939 2:e37117117e79 197 memcpy(&last, header, sizeof(struct ipline_header));
okini3939 2:e37117117e79 198 }
okini3939 2:e37117117e79 199
okini3939 2:e37117117e79 200 /// send packet
okini3939 2:e37117117e79 201 void IpLine::send (struct ipline_packet *packet) {
okini3939 2:e37117117e79 202
okini3939 5:30e2847d241b 203 led_y = 1;
okini3939 4:41a3534d085f 204 packet->header.ident = PACKET_IDENT;
okini3939 2:e37117117e79 205 if (! packet->header.num) {
okini3939 2:e37117117e79 206 packet->header.num = packet_num;
okini3939 2:e37117117e79 207 packet_num ++;
okini3939 2:e37117117e79 208 if (packet_num >= 65536) packet_num = 1;
okini3939 2:e37117117e79 209 }
okini3939 2:e37117117e79 210 udpsock->sendto((char *)packet, sizeof(struct ipline_packet), &remote);
okini3939 2:e37117117e79 211 }
okini3939 2:e37117117e79 212
okini3939 2:e37117117e79 213 /// change mode
okini3939 2:e37117117e79 214 int IpLine::enter (enum Mode newmode) {
okini3939 2:e37117117e79 215 struct ipline_header header;
okini3939 2:e37117117e79 216
okini3939 2:e37117117e79 217 mode = newmode;
okini3939 2:e37117117e79 218 status = StatusOk;
okini3939 2:e37117117e79 219
okini3939 2:e37117117e79 220 switch (mode) {
okini3939 2:e37117117e79 221 case ModeReady:
okini3939 2:e37117117e79 222 hook = HookOff;
okini3939 5:30e2847d241b 223 adbuf.clear();
okini3939 5:30e2847d241b 224 dabuf.clear();
okini3939 2:e37117117e79 225 break;
okini3939 2:e37117117e79 226
okini3939 2:e37117117e79 227 case ModeBT:
okini3939 2:e37117117e79 228 case ModeDisconnect:
okini3939 2:e37117117e79 229 hook = HookOff;
okini3939 2:e37117117e79 230 case ModeRing:
okini3939 2:e37117117e79 231 case ModeTalk:
okini3939 2:e37117117e79 232 status = StatusNone;
okini3939 2:e37117117e79 233 header.num = 0;
okini3939 2:e37117117e79 234 header.target = remotetarget;
okini3939 2:e37117117e79 235 header.mode = mode;
okini3939 2:e37117117e79 236 header.status = status;
okini3939 2:e37117117e79 237 send(&header);
okini3939 2:e37117117e79 238 timeout = NET_RETRY;
okini3939 2:e37117117e79 239 break;
okini3939 2:e37117117e79 240 }
okini3939 2:e37117117e79 241
okini3939 2:e37117117e79 242 return 0;
okini3939 2:e37117117e79 243 }
okini3939 2:e37117117e79 244
okini3939 2:e37117117e79 245 /// return status
okini3939 2:e37117117e79 246 int IpLine::scan (enum Scan type) {
okini3939 2:e37117117e79 247
okini3939 2:e37117117e79 248 switch (type) {
okini3939 2:e37117117e79 249 case ScanMode:
okini3939 2:e37117117e79 250 return mode;
okini3939 2:e37117117e79 251
okini3939 2:e37117117e79 252 case ScanStatus:
okini3939 2:e37117117e79 253 return status;
okini3939 2:e37117117e79 254
okini3939 2:e37117117e79 255 case ScanHook:
okini3939 2:e37117117e79 256 return hook;
okini3939 2:e37117117e79 257
okini3939 2:e37117117e79 258 case ScanDial:
okini3939 2:e37117117e79 259 char c;
okini3939 2:e37117117e79 260 if (dial.get(c) == 0)
okini3939 2:e37117117e79 261 return c;
okini3939 2:e37117117e79 262 break;
okini3939 2:e37117117e79 263
okini3939 2:e37117117e79 264 }
okini3939 2:e37117117e79 265
okini3939 2:e37117117e79 266 return -1;
okini3939 2:e37117117e79 267 }
okini3939 2:e37117117e79 268
okini3939 2:e37117117e79 269 /// set target
okini3939 2:e37117117e79 270 void IpLine::settarget (enum PhoneType target, char *host) {
okini3939 2:e37117117e79 271 int ip0, ip1, ip2, ip3;
okini3939 2:e37117117e79 272
okini3939 2:e37117117e79 273 remotetarget = target;
okini3939 2:e37117117e79 274 if (host[0] >= '0' && host[0] <= '9') {
okini3939 2:e37117117e79 275 sscanf(host, "%d.%d.%d.%d", &ip0, &ip1, &ip2, &ip3);
okini3939 2:e37117117e79 276 remote.setIp(IpAddr(ip0, ip1, ip2, ip3));
okini3939 2:e37117117e79 277 remote.setName(NULL);
okini3939 2:e37117117e79 278 } else {
okini3939 2:e37117117e79 279 remote.setIp(NULL);
okini3939 2:e37117117e79 280 remote.setName(host);
okini3939 2:e37117117e79 281 }
okini3939 2:e37117117e79 282 remote.setPort(UDPPORT);
okini3939 2:e37117117e79 283 }
okini3939 4:41a3534d085f 284
okini3939 4:41a3534d085f 285 unsigned long IpLine::xor128 () {
okini3939 4:41a3534d085f 286 static unsigned long x = 123456789;
okini3939 4:41a3534d085f 287 static unsigned long y = 362436069, z = 521288629, w = 88675123;
okini3939 4:41a3534d085f 288 unsigned long t;
okini3939 4:41a3534d085f 289 t = (x ^ (x << 11));
okini3939 4:41a3534d085f 290 x = y; y = z; z = w;
okini3939 4:41a3534d085f 291 return (w = (w ^ (w >> 19)) ^ (t ^ (t >> 8)) );
okini3939 4:41a3534d085f 292 }
okini3939 4:41a3534d085f 293
okini3939 4:41a3534d085f 294 int IpLine::gaussian () {
okini3939 4:41a3534d085f 295 int i, j;
okini3939 4:41a3534d085f 296
okini3939 4:41a3534d085f 297 j = 0;
okini3939 4:41a3534d085f 298 for (i = 0; i < 12; i ++) {
okini3939 4:41a3534d085f 299 j = j + (xor128() >> 16);
okini3939 4:41a3534d085f 300 }
okini3939 4:41a3534d085f 301 j = (j - 0x60000) & 0xffff;
okini3939 5:30e2847d241b 302 return 0x3fff + (j >> 2);
okini3939 4:41a3534d085f 303 }