mbed Phone Platform
Dependencies: ulaw mbed ConfigFile
IpLine.cpp@1:0f82c574096f, 2010-12-26 (annotated)
- Committer:
- okini3939
- Date:
- Sun Dec 26 15:49:07 2010 +0000
- Revision:
- 1:0f82c574096f
- Child:
- 2:e37117117e79
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
okini3939 | 1:0f82c574096f | 1 | #include "IpLine.h" |
okini3939 | 1:0f82c574096f | 2 | |
okini3939 | 1:0f82c574096f | 3 | |
okini3939 | 1:0f82c574096f | 4 | 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 | 1:0f82c574096f | 5 | EthernetErr r; |
okini3939 | 1:0f82c574096f | 6 | |
okini3939 | 1:0f82c574096f | 7 | mode = ModeOff; |
okini3939 | 1:0f82c574096f | 8 | status = StatusOk; |
okini3939 | 1:0f82c574096f | 9 | timeout = 0; |
okini3939 | 1:0f82c574096f | 10 | packet_num = 0; |
okini3939 | 1:0f82c574096f | 11 | dataskip = 0; |
okini3939 | 1:0f82c574096f | 12 | |
okini3939 | 1:0f82c574096f | 13 | // dhcp |
okini3939 | 1:0f82c574096f | 14 | eth = new EthernetNetIf; |
okini3939 | 1:0f82c574096f | 15 | r = eth->setup(); |
okini3939 | 1:0f82c574096f | 16 | if (r) { |
okini3939 | 1:0f82c574096f | 17 | printf("Error %d in setup.\n", r); |
okini3939 | 1:0f82c574096f | 18 | return; |
okini3939 | 1:0f82c574096f | 19 | } |
okini3939 | 1:0f82c574096f | 20 | |
okini3939 | 1:0f82c574096f | 21 | udpsock = new UDPSocket; |
okini3939 | 1:0f82c574096f | 22 | udpsock->setOnEvent(this, &IpLine::onLisnerEvent); |
okini3939 | 1:0f82c574096f | 23 | udpsock->bind(Host(eth->getIp(), UDPPORT)); |
okini3939 | 1:0f82c574096f | 24 | } |
okini3939 | 1:0f82c574096f | 25 | |
okini3939 | 1:0f82c574096f | 26 | /// 8KHz interrupt |
okini3939 | 1:0f82c574096f | 27 | void IpLine::poll () { |
okini3939 | 1:0f82c574096f | 28 | char c; |
okini3939 | 1:0f82c574096f | 29 | |
okini3939 | 1:0f82c574096f | 30 | if (mode == ModeTalk && hook) { |
okini3939 | 1:0f82c574096f | 31 | // dac |
okini3939 | 1:0f82c574096f | 32 | if (dabuf.available() < DATA_SIZE) { |
okini3939 | 1:0f82c574096f | 33 | // down sample |
okini3939 | 1:0f82c574096f | 34 | dabuf.get(c); |
okini3939 | 1:0f82c574096f | 35 | dabuf.get(c); |
okini3939 | 1:0f82c574096f | 36 | dac.write_u16(ulaw2pcm(c)); |
okini3939 | 1:0f82c574096f | 37 | } else |
okini3939 | 1:0f82c574096f | 38 | if (dabuf.use() < DATA_SIZE) { |
okini3939 | 1:0f82c574096f | 39 | // over sample |
okini3939 | 1:0f82c574096f | 40 | if (dataskip) { |
okini3939 | 1:0f82c574096f | 41 | dataskip = 0; |
okini3939 | 1:0f82c574096f | 42 | } else { |
okini3939 | 1:0f82c574096f | 43 | if (! dabuf.get(c)) { |
okini3939 | 1:0f82c574096f | 44 | dac.write_u16(ulaw2pcm(c)); |
okini3939 | 1:0f82c574096f | 45 | } else { |
okini3939 | 1:0f82c574096f | 46 | // dac.write_u16(gaussian()); |
okini3939 | 1:0f82c574096f | 47 | } |
okini3939 | 1:0f82c574096f | 48 | dataskip = 1; |
okini3939 | 1:0f82c574096f | 49 | } |
okini3939 | 1:0f82c574096f | 50 | } else { |
okini3939 | 1:0f82c574096f | 51 | // normal |
okini3939 | 1:0f82c574096f | 52 | dabuf.get(c); |
okini3939 | 1:0f82c574096f | 53 | dac.write_u16(ulaw2pcm(c)); |
okini3939 | 1:0f82c574096f | 54 | } |
okini3939 | 1:0f82c574096f | 55 | |
okini3939 | 1:0f82c574096f | 56 | // adc |
okini3939 | 1:0f82c574096f | 57 | adbuf.put(pcm2ulaw(adc.read_u16())); |
okini3939 | 1:0f82c574096f | 58 | } |
okini3939 | 1:0f82c574096f | 59 | |
okini3939 | 1:0f82c574096f | 60 | if (timeout) { |
okini3939 | 1:0f82c574096f | 61 | timeout --; |
okini3939 | 1:0f82c574096f | 62 | |
okini3939 | 1:0f82c574096f | 63 | if (timeout == 0) { |
okini3939 | 1:0f82c574096f | 64 | if (last.target) { |
okini3939 | 1:0f82c574096f | 65 | // re-try |
okini3939 | 1:0f82c574096f | 66 | send(last); |
okini3939 | 1:0f82c574096f | 67 | timeout = FREQ; |
okini3939 | 1:0f82c574096f | 68 | last.target = PhoneNone; |
okini3939 | 1:0f82c574096f | 69 | } else { |
okini3939 | 1:0f82c574096f | 70 | // timeout |
okini3939 | 1:0f82c574096f | 71 | status = StatusNg; |
okini3939 | 1:0f82c574096f | 72 | } |
okini3939 | 1:0f82c574096f | 73 | } |
okini3939 | 1:0f82c574096f | 74 | } |
okini3939 | 1:0f82c574096f | 75 | } |
okini3939 | 1:0f82c574096f | 76 | |
okini3939 | 1:0f82c574096f | 77 | /// network |
okini3939 | 1:0f82c574096f | 78 | void IpLine::netpoll () { |
okini3939 | 1:0f82c574096f | 79 | |
okini3939 | 1:0f82c574096f | 80 | if (mode == ModeTalk && adbuf.use() >= DATA_SIZE) { |
okini3939 | 1:0f82c574096f | 81 | // send |
okini3939 | 1:0f82c574096f | 82 | struct ipline_packet packet; |
okini3939 | 1:0f82c574096f | 83 | |
okini3939 | 1:0f82c574096f | 84 | packet.len = adbuf.get(packet.data, sizeof(packet.data)); |
okini3939 | 1:0f82c574096f | 85 | if (packet.len > 0) { |
okini3939 | 1:0f82c574096f | 86 | packet.header.target = remotetarget; |
okini3939 | 1:0f82c574096f | 87 | packet.header.mode = ModeData; |
okini3939 | 1:0f82c574096f | 88 | packet.header.status = StatusNone; |
okini3939 | 1:0f82c574096f | 89 | send(packet); |
okini3939 | 1:0f82c574096f | 90 | } |
okini3939 | 1:0f82c574096f | 91 | } |
okini3939 | 1:0f82c574096f | 92 | |
okini3939 | 1:0f82c574096f | 93 | Net::poll(); |
okini3939 | 1:0f82c574096f | 94 | } |
okini3939 | 1:0f82c574096f | 95 | |
okini3939 | 1:0f82c574096f | 96 | /// recv packet |
okini3939 | 1:0f82c574096f | 97 | void IpLine::onLisnerEvent (UDPSocketEvent e) { |
okini3939 | 1:0f82c574096f | 98 | int len; |
okini3939 | 1:0f82c574096f | 99 | struct ipline_packet packet; |
okini3939 | 1:0f82c574096f | 100 | Host recv; |
okini3939 | 1:0f82c574096f | 101 | |
okini3939 | 1:0f82c574096f | 102 | if (e != UDPSOCKET_READABLE) return; |
okini3939 | 1:0f82c574096f | 103 | |
okini3939 | 1:0f82c574096f | 104 | // get data |
okini3939 | 1:0f82c574096f | 105 | len = udpsock->recvfrom((char *)&packet, sizeof(packet), &recv); |
okini3939 | 1:0f82c574096f | 106 | |
okini3939 | 1:0f82c574096f | 107 | if (packet.header.status != StatusNone) { |
okini3939 | 1:0f82c574096f | 108 | // recv ack |
okini3939 | 1:0f82c574096f | 109 | if (packet.header.num == last.num) { |
okini3939 | 1:0f82c574096f | 110 | status = packet.header.status; |
okini3939 | 1:0f82c574096f | 111 | timeout = 0; |
okini3939 | 1:0f82c574096f | 112 | } |
okini3939 | 1:0f82c574096f | 113 | |
okini3939 | 1:0f82c574096f | 114 | } else |
okini3939 | 1:0f82c574096f | 115 | if (packet.header.mode == ModeData) { |
okini3939 | 1:0f82c574096f | 116 | // data |
okini3939 | 1:0f82c574096f | 117 | |
okini3939 | 1:0f82c574096f | 118 | dabuf.put(packet.data, packet.len); |
okini3939 | 1:0f82c574096f | 119 | |
okini3939 | 1:0f82c574096f | 120 | } else |
okini3939 | 1:0f82c574096f | 121 | if (mode == ModeTalk && len > sizeof(struct ipline_header)) { |
okini3939 | 1:0f82c574096f | 122 | // enter |
okini3939 | 1:0f82c574096f | 123 | packet.header.status = StatusNg; |
okini3939 | 1:0f82c574096f | 124 | |
okini3939 | 1:0f82c574096f | 125 | switch (packet.header.mode) { |
okini3939 | 1:0f82c574096f | 126 | case ModeRing: |
okini3939 | 1:0f82c574096f | 127 | // ring --> onhook, dial |
okini3939 | 1:0f82c574096f | 128 | if (mode == ModeReady) { |
okini3939 | 1:0f82c574096f | 129 | dial.put(11); |
okini3939 | 1:0f82c574096f | 130 | dial.put(packet.header.target); |
okini3939 | 1:0f82c574096f | 131 | dial.put(12); |
okini3939 | 1:0f82c574096f | 132 | hook = HookOn; |
okini3939 | 1:0f82c574096f | 133 | remote = recv; |
okini3939 | 1:0f82c574096f | 134 | packet.header.status = StatusOk; |
okini3939 | 1:0f82c574096f | 135 | } |
okini3939 | 1:0f82c574096f | 136 | break; |
okini3939 | 1:0f82c574096f | 137 | case ModeBT: |
okini3939 | 1:0f82c574096f | 138 | case ModeDisconnect: |
okini3939 | 1:0f82c574096f | 139 | if (recv.getIp() == remote.getIp()) { |
okini3939 | 1:0f82c574096f | 140 | hook = HookOff; |
okini3939 | 1:0f82c574096f | 141 | packet.header.status = StatusOk; |
okini3939 | 1:0f82c574096f | 142 | } |
okini3939 | 1:0f82c574096f | 143 | break; |
okini3939 | 1:0f82c574096f | 144 | case ModeTalk: |
okini3939 | 1:0f82c574096f | 145 | if (recv.getIp() == remote.getIp()) { |
okini3939 | 1:0f82c574096f | 146 | hook = HookOn; |
okini3939 | 1:0f82c574096f | 147 | packet.header.status = StatusOk; |
okini3939 | 1:0f82c574096f | 148 | } |
okini3939 | 1:0f82c574096f | 149 | break; |
okini3939 | 1:0f82c574096f | 150 | } |
okini3939 | 1:0f82c574096f | 151 | |
okini3939 | 1:0f82c574096f | 152 | // send ack |
okini3939 | 1:0f82c574096f | 153 | send(packet.header); |
okini3939 | 1:0f82c574096f | 154 | timeout = FREQ; |
okini3939 | 1:0f82c574096f | 155 | } |
okini3939 | 1:0f82c574096f | 156 | } |
okini3939 | 1:0f82c574096f | 157 | |
okini3939 | 1:0f82c574096f | 158 | |
okini3939 | 1:0f82c574096f | 159 | /// send packet (header only) |
okini3939 | 1:0f82c574096f | 160 | void IpLine::send (struct ipline_header &header) { |
okini3939 | 1:0f82c574096f | 161 | |
okini3939 | 1:0f82c574096f | 162 | header.num = packet_num; |
okini3939 | 1:0f82c574096f | 163 | udpsock->sendto((char *)&header, sizeof(header), &remote); |
okini3939 | 1:0f82c574096f | 164 | memcpy(&last, &header, sizeof(last)); |
okini3939 | 1:0f82c574096f | 165 | |
okini3939 | 1:0f82c574096f | 166 | packet_num ++; |
okini3939 | 1:0f82c574096f | 167 | if (packet_num >= 65536) packet_num = 1; |
okini3939 | 1:0f82c574096f | 168 | } |
okini3939 | 1:0f82c574096f | 169 | |
okini3939 | 1:0f82c574096f | 170 | /// send packet |
okini3939 | 1:0f82c574096f | 171 | void IpLine::send (struct ipline_packet &packet) { |
okini3939 | 1:0f82c574096f | 172 | |
okini3939 | 1:0f82c574096f | 173 | packet.header.num = packet_num; |
okini3939 | 1:0f82c574096f | 174 | udpsock->sendto((char *)&packet, sizeof(packet), &remote); |
okini3939 | 1:0f82c574096f | 175 | |
okini3939 | 1:0f82c574096f | 176 | packet_num ++; |
okini3939 | 1:0f82c574096f | 177 | if (packet_num >= 256) packet_num = 0; |
okini3939 | 1:0f82c574096f | 178 | } |
okini3939 | 1:0f82c574096f | 179 | |
okini3939 | 1:0f82c574096f | 180 | /// change mode |
okini3939 | 1:0f82c574096f | 181 | int IpLine::enter (enum Mode newmode) { |
okini3939 | 1:0f82c574096f | 182 | struct ipline_header header; |
okini3939 | 1:0f82c574096f | 183 | |
okini3939 | 1:0f82c574096f | 184 | mode = newmode; |
okini3939 | 1:0f82c574096f | 185 | status = StatusOk; |
okini3939 | 1:0f82c574096f | 186 | |
okini3939 | 1:0f82c574096f | 187 | switch (mode) { |
okini3939 | 1:0f82c574096f | 188 | case ModeReady: |
okini3939 | 1:0f82c574096f | 189 | hook = HookOff; |
okini3939 | 1:0f82c574096f | 190 | break; |
okini3939 | 1:0f82c574096f | 191 | case ModeRing: |
okini3939 | 1:0f82c574096f | 192 | case ModeTalk: |
okini3939 | 1:0f82c574096f | 193 | case ModeBT: |
okini3939 | 1:0f82c574096f | 194 | case ModeDisconnect: |
okini3939 | 1:0f82c574096f | 195 | status = StatusNone; |
okini3939 | 1:0f82c574096f | 196 | header.target = remotetarget; |
okini3939 | 1:0f82c574096f | 197 | header.mode = mode; |
okini3939 | 1:0f82c574096f | 198 | header.status = status; |
okini3939 | 1:0f82c574096f | 199 | send(header); |
okini3939 | 1:0f82c574096f | 200 | timeout = FREQ; |
okini3939 | 1:0f82c574096f | 201 | break; |
okini3939 | 1:0f82c574096f | 202 | } |
okini3939 | 1:0f82c574096f | 203 | |
okini3939 | 1:0f82c574096f | 204 | return 0; |
okini3939 | 1:0f82c574096f | 205 | } |
okini3939 | 1:0f82c574096f | 206 | |
okini3939 | 1:0f82c574096f | 207 | /// return status |
okini3939 | 1:0f82c574096f | 208 | int IpLine::scan (enum Scan type) { |
okini3939 | 1:0f82c574096f | 209 | |
okini3939 | 1:0f82c574096f | 210 | switch (type) { |
okini3939 | 1:0f82c574096f | 211 | case ScanMode: |
okini3939 | 1:0f82c574096f | 212 | return mode; |
okini3939 | 1:0f82c574096f | 213 | |
okini3939 | 1:0f82c574096f | 214 | case ScanStatus: |
okini3939 | 1:0f82c574096f | 215 | return status; |
okini3939 | 1:0f82c574096f | 216 | |
okini3939 | 1:0f82c574096f | 217 | case ScanHook: |
okini3939 | 1:0f82c574096f | 218 | return hook; |
okini3939 | 1:0f82c574096f | 219 | |
okini3939 | 1:0f82c574096f | 220 | case ScanDial: |
okini3939 | 1:0f82c574096f | 221 | char c; |
okini3939 | 1:0f82c574096f | 222 | if (dial.get(c) == 0) |
okini3939 | 1:0f82c574096f | 223 | return c; |
okini3939 | 1:0f82c574096f | 224 | break; |
okini3939 | 1:0f82c574096f | 225 | |
okini3939 | 1:0f82c574096f | 226 | } |
okini3939 | 1:0f82c574096f | 227 | |
okini3939 | 1:0f82c574096f | 228 | return -1; |
okini3939 | 1:0f82c574096f | 229 | } |
okini3939 | 1:0f82c574096f | 230 | |
okini3939 | 1:0f82c574096f | 231 | /// set target |
okini3939 | 1:0f82c574096f | 232 | void IpLine::settarget (enum PhoneType target, char *host) { |
okini3939 | 1:0f82c574096f | 233 | int ip0, ip1, ip2, ip3; |
okini3939 | 1:0f82c574096f | 234 | |
okini3939 | 1:0f82c574096f | 235 | remotetarget = target; |
okini3939 | 1:0f82c574096f | 236 | if (host[0] >= '0' && host[0] <= '9') { |
okini3939 | 1:0f82c574096f | 237 | sscanf(host, "%d.%d.%d.%d", &ip0, &ip1, &ip2, &ip3); |
okini3939 | 1:0f82c574096f | 238 | remote.setIp(IpAddr(ip0, ip1, ip2, ip3)); |
okini3939 | 1:0f82c574096f | 239 | remote.setName(NULL); |
okini3939 | 1:0f82c574096f | 240 | } else { |
okini3939 | 1:0f82c574096f | 241 | remote.setIp(NULL); |
okini3939 | 1:0f82c574096f | 242 | remote.setName(host); |
okini3939 | 1:0f82c574096f | 243 | } |
okini3939 | 1:0f82c574096f | 244 | remote.setPort(UDPPORT); |
okini3939 | 1:0f82c574096f | 245 | } |