mbed Phone Platform
Dependencies: ulaw mbed ConfigFile
main.cpp@6:bd62b12de751, 2011-01-21 (annotated)
- Committer:
- okini3939
- Date:
- Fri Jan 21 16:06:15 2011 +0000
- Revision:
- 6:bd62b12de751
- Parent:
- 5:30e2847d241b
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
okini3939 | 0:f18953137cb4 | 1 | /* |
okini3939 | 0:f18953137cb4 | 2 | * mbed Phone Platform |
okini3939 | 0:f18953137cb4 | 3 | * Copyright (c) 2010 Hiroshi Suga |
okini3939 | 0:f18953137cb4 | 4 | * Released under the MIT License: http://mbed.org/license/mit |
okini3939 | 0:f18953137cb4 | 5 | */ |
okini3939 | 0:f18953137cb4 | 6 | |
okini3939 | 2:e37117117e79 | 7 | /** @file main.cpp |
okini3939 | 0:f18953137cb4 | 8 | * @brief mbed Phone Platform |
okini3939 | 0:f18953137cb4 | 9 | */ |
okini3939 | 2:e37117117e79 | 10 | |
okini3939 | 0:f18953137cb4 | 11 | #include "mbed.h" |
okini3939 | 6:bd62b12de751 | 12 | #include "EthernetNetIf.h" |
okini3939 | 1:0f82c574096f | 13 | #include "phone.h" |
okini3939 | 0:f18953137cb4 | 14 | #include "Line.h" |
okini3939 | 1:0f82c574096f | 15 | #include "IpLine.h" |
okini3939 | 0:f18953137cb4 | 16 | |
okini3939 | 6:bd62b12de751 | 17 | EthernetNetIf *eth; |
okini3939 | 6:bd62b12de751 | 18 | |
okini3939 | 0:f18953137cb4 | 19 | Serial pc(USBTX, USBRX); |
okini3939 | 0:f18953137cb4 | 20 | Ticker ticker; |
okini3939 | 0:f18953137cb4 | 21 | |
okini3939 | 0:f18953137cb4 | 22 | DigitalOut led1(LED1), led2(LED2), led3(LED3), led4(LED4); |
okini3939 | 0:f18953137cb4 | 23 | |
okini3939 | 0:f18953137cb4 | 24 | AnalogIn adc(p17); |
okini3939 | 0:f18953137cb4 | 25 | AnalogOut dac(p18); |
okini3939 | 0:f18953137cb4 | 26 | DigitalOut mixlocal(p21), mixline(p22), micsp(p23); |
okini3939 | 0:f18953137cb4 | 27 | Line line1(p12, p13, p11, dac); |
okini3939 | 0:f18953137cb4 | 28 | Line line2(p14, p15, p16, dac); |
okini3939 | 6:bd62b12de751 | 29 | IpLine *ipline; |
okini3939 | 0:f18953137cb4 | 30 | |
okini3939 | 6:bd62b12de751 | 31 | volatile int timeout, dialcount, useipline; |
okini3939 | 6:bd62b12de751 | 32 | volatile enum PhoneType activesrc, activedest; |
okini3939 | 6:bd62b12de751 | 33 | char dial[DIAL_SIZE]; |
okini3939 | 6:bd62b12de751 | 34 | struct PhoneBook phonebook[PB_SIZE]; |
okini3939 | 1:0f82c574096f | 35 | |
okini3939 | 0:f18953137cb4 | 36 | void int_sample () { |
okini3939 | 2:e37117117e79 | 37 | line1.intr(); |
okini3939 | 2:e37117117e79 | 38 | line2.intr(); |
okini3939 | 6:bd62b12de751 | 39 | if (useipline) { |
okini3939 | 6:bd62b12de751 | 40 | ipline->intr(); |
okini3939 | 6:bd62b12de751 | 41 | } |
okini3939 | 2:e37117117e79 | 42 | |
okini3939 | 0:f18953137cb4 | 43 | if (timeout) timeout --; |
okini3939 | 0:f18953137cb4 | 44 | } |
okini3939 | 0:f18953137cb4 | 45 | |
okini3939 | 1:0f82c574096f | 46 | int getpb (enum PhoneType *target, char *hostname) { |
okini3939 | 1:0f82c574096f | 47 | int i, j; |
okini3939 | 1:0f82c574096f | 48 | |
okini3939 | 6:bd62b12de751 | 49 | if (dial[0] == 11 && dial[1] >= 1 && dial[1] <= 3) { |
okini3939 | 6:bd62b12de751 | 50 | *target = (enum PhoneType)dial[1]; |
okini3939 | 6:bd62b12de751 | 51 | hostname[0] = 0; |
okini3939 | 6:bd62b12de751 | 52 | return 1; |
okini3939 | 6:bd62b12de751 | 53 | } |
okini3939 | 6:bd62b12de751 | 54 | |
okini3939 | 1:0f82c574096f | 55 | for (i = 0; i < PB_SIZE; i ++) { |
okini3939 | 1:0f82c574096f | 56 | for (j = 0; j < DIAL_SIZE; j ++) { |
okini3939 | 6:bd62b12de751 | 57 | if (phonebook[i].dial[j] == 0 && dial[j] == 0) { |
okini3939 | 1:0f82c574096f | 58 | *target = phonebook[i].target; |
okini3939 | 3:1d5dc4107558 | 59 | strncpy(hostname, phonebook[i].hostname, HOSTNAME_SIZE); |
okini3939 | 1:0f82c574096f | 60 | return 1; |
okini3939 | 1:0f82c574096f | 61 | } |
okini3939 | 6:bd62b12de751 | 62 | if (phonebook[i].dial[j] == 0 || dial[j] == 0 || |
okini3939 | 6:bd62b12de751 | 63 | j >= dialcount || phonebook[i].dial[j] != dial[j]) break; |
okini3939 | 1:0f82c574096f | 64 | } |
okini3939 | 1:0f82c574096f | 65 | } |
okini3939 | 1:0f82c574096f | 66 | |
okini3939 | 1:0f82c574096f | 67 | return 0; |
okini3939 | 0:f18953137cb4 | 68 | } |
okini3939 | 0:f18953137cb4 | 69 | |
okini3939 | 0:f18953137cb4 | 70 | void enteranalog (enum PhoneType target) { |
okini3939 | 0:f18953137cb4 | 71 | |
okini3939 | 0:f18953137cb4 | 72 | micsp = 0; |
okini3939 | 0:f18953137cb4 | 73 | mixlocal = 0; |
okini3939 | 0:f18953137cb4 | 74 | mixline = 0; |
okini3939 | 0:f18953137cb4 | 75 | |
okini3939 | 0:f18953137cb4 | 76 | wait_ms(1); |
okini3939 | 5:30e2847d241b | 77 | dac.write_u16(0x7fff); |
okini3939 | 0:f18953137cb4 | 78 | |
okini3939 | 0:f18953137cb4 | 79 | switch (target) { |
okini3939 | 0:f18953137cb4 | 80 | case PhoneLine1: |
okini3939 | 0:f18953137cb4 | 81 | case PhoneLine2: |
okini3939 | 2:e37117117e79 | 82 | case PhoneIpLine: |
okini3939 | 0:f18953137cb4 | 83 | mixline = 1; |
okini3939 | 0:f18953137cb4 | 84 | break; |
okini3939 | 0:f18953137cb4 | 85 | case PhoneMicSp: |
okini3939 | 0:f18953137cb4 | 86 | micsp = 1; |
okini3939 | 0:f18953137cb4 | 87 | mixlocal = 1; |
okini3939 | 0:f18953137cb4 | 88 | break; |
okini3939 | 0:f18953137cb4 | 89 | } |
okini3939 | 0:f18953137cb4 | 90 | } |
okini3939 | 0:f18953137cb4 | 91 | |
okini3939 | 0:f18953137cb4 | 92 | int enterline (enum PhoneType target, enum Mode mode) { |
okini3939 | 0:f18953137cb4 | 93 | |
okini3939 | 0:f18953137cb4 | 94 | switch (target) { |
okini3939 | 0:f18953137cb4 | 95 | case PhoneLine1: |
okini3939 | 0:f18953137cb4 | 96 | return line1.enter(mode); |
okini3939 | 0:f18953137cb4 | 97 | case PhoneLine2: |
okini3939 | 0:f18953137cb4 | 98 | return line2.enter(mode); |
okini3939 | 0:f18953137cb4 | 99 | /* |
okini3939 | 0:f18953137cb4 | 100 | case PhoneMicSp: |
okini3939 | 0:f18953137cb4 | 101 | return micsp.enter(mode); |
okini3939 | 2:e37117117e79 | 102 | */ |
okini3939 | 0:f18953137cb4 | 103 | case PhoneIpLine: |
okini3939 | 6:bd62b12de751 | 104 | return ipline->enter(mode); |
okini3939 | 0:f18953137cb4 | 105 | } |
okini3939 | 0:f18953137cb4 | 106 | return 0; |
okini3939 | 0:f18953137cb4 | 107 | } |
okini3939 | 0:f18953137cb4 | 108 | |
okini3939 | 0:f18953137cb4 | 109 | int scanline (enum PhoneType target, enum Scan type) { |
okini3939 | 0:f18953137cb4 | 110 | |
okini3939 | 0:f18953137cb4 | 111 | switch (target) { |
okini3939 | 0:f18953137cb4 | 112 | case PhoneLine1: |
okini3939 | 0:f18953137cb4 | 113 | return line1.scan(type); |
okini3939 | 0:f18953137cb4 | 114 | case PhoneLine2: |
okini3939 | 0:f18953137cb4 | 115 | return line2.scan(type); |
okini3939 | 0:f18953137cb4 | 116 | /* |
okini3939 | 0:f18953137cb4 | 117 | case PhoneMicSp: |
okini3939 | 0:f18953137cb4 | 118 | return micsp.scan(type); |
okini3939 | 2:e37117117e79 | 119 | */ |
okini3939 | 0:f18953137cb4 | 120 | case PhoneIpLine: |
okini3939 | 6:bd62b12de751 | 121 | return ipline->scan(type); |
okini3939 | 0:f18953137cb4 | 122 | } |
okini3939 | 0:f18953137cb4 | 123 | return 0; |
okini3939 | 0:f18953137cb4 | 124 | } |
okini3939 | 0:f18953137cb4 | 125 | |
okini3939 | 0:f18953137cb4 | 126 | void checkline (enum PhoneType num) { |
okini3939 | 0:f18953137cb4 | 127 | int i; |
okini3939 | 0:f18953137cb4 | 128 | |
okini3939 | 0:f18953137cb4 | 129 | switch ((enum Mode)scanline(num, ScanMode)) { |
okini3939 | 0:f18953137cb4 | 130 | case ModeReady: |
okini3939 | 0:f18953137cb4 | 131 | if (scanline(num, ScanHook) == HookOn && activesrc == PhoneNone) { |
okini3939 | 0:f18953137cb4 | 132 | // on hook, dial tone |
okini3939 | 0:f18953137cb4 | 133 | dialcount = 0; |
okini3939 | 0:f18953137cb4 | 134 | enteranalog(num); |
okini3939 | 0:f18953137cb4 | 135 | enterline(num, ModeDT); |
okini3939 | 0:f18953137cb4 | 136 | activesrc = num; |
okini3939 | 0:f18953137cb4 | 137 | } |
okini3939 | 0:f18953137cb4 | 138 | break; |
okini3939 | 0:f18953137cb4 | 139 | |
okini3939 | 0:f18953137cb4 | 140 | case ModeDT: |
okini3939 | 0:f18953137cb4 | 141 | case ModeDial: |
okini3939 | 0:f18953137cb4 | 142 | if (scanline(num, ScanHook) == HookOff) { |
okini3939 | 0:f18953137cb4 | 143 | // off hook, exit |
okini3939 | 0:f18953137cb4 | 144 | enterline(num, ModeReady); |
okini3939 | 0:f18953137cb4 | 145 | activesrc = PhoneNone; |
okini3939 | 0:f18953137cb4 | 146 | break; |
okini3939 | 0:f18953137cb4 | 147 | } |
okini3939 | 0:f18953137cb4 | 148 | i = scanline(num, ScanDial); |
okini3939 | 2:e37117117e79 | 149 | if (i > 0 && i < 12) { |
okini3939 | 0:f18953137cb4 | 150 | // detect dial |
okini3939 | 0:f18953137cb4 | 151 | dial[dialcount] = i; |
okini3939 | 0:f18953137cb4 | 152 | dialcount ++; |
okini3939 | 3:1d5dc4107558 | 153 | pc.printf("Dial [%d]\r\n", i); |
okini3939 | 0:f18953137cb4 | 154 | if (scanline(num, ScanMode) == ModeDT) enterline(num, ModeDial); |
okini3939 | 2:e37117117e79 | 155 | timeout = DIAL_TIMEOUT; |
okini3939 | 0:f18953137cb4 | 156 | } |
okini3939 | 2:e37117117e79 | 157 | if ((! timeout && dialcount > 0) || dialcount >= DIAL_SIZE || i >= 12) { |
okini3939 | 3:1d5dc4107558 | 158 | char buf[HOSTNAME_SIZE]; |
okini3939 | 1:0f82c574096f | 159 | enum PhoneType p; |
okini3939 | 0:f18953137cb4 | 160 | // call |
okini3939 | 6:bd62b12de751 | 161 | dial[dialcount] = 0; |
okini3939 | 1:0f82c574096f | 162 | if (getpb(&p, buf)) { |
okini3939 | 6:bd62b12de751 | 163 | printf("-> %d %s\r\n", p, buf); |
okini3939 | 1:0f82c574096f | 164 | if (buf[0] == 0) { |
okini3939 | 1:0f82c574096f | 165 | activedest = p; |
okini3939 | 6:bd62b12de751 | 166 | } else |
okini3939 | 6:bd62b12de751 | 167 | if (useipline) { |
okini3939 | 1:0f82c574096f | 168 | activedest = PhoneIpLine; |
okini3939 | 6:bd62b12de751 | 169 | ipline->settarget(p, buf); |
okini3939 | 1:0f82c574096f | 170 | } |
okini3939 | 1:0f82c574096f | 171 | enterline(num, ModeCall); |
okini3939 | 1:0f82c574096f | 172 | enterline(activedest, ModeRing); |
okini3939 | 2:e37117117e79 | 173 | timeout = CALL_TIMEOUT; |
okini3939 | 1:0f82c574096f | 174 | } else { |
okini3939 | 1:0f82c574096f | 175 | enterline(num, ModeBT); |
okini3939 | 1:0f82c574096f | 176 | } |
okini3939 | 0:f18953137cb4 | 177 | } |
okini3939 | 0:f18953137cb4 | 178 | break; |
okini3939 | 0:f18953137cb4 | 179 | |
okini3939 | 0:f18953137cb4 | 180 | case ModeCall: |
okini3939 | 0:f18953137cb4 | 181 | if (scanline(num, ScanHook) == HookOff) { |
okini3939 | 0:f18953137cb4 | 182 | // off hook, exit |
okini3939 | 0:f18953137cb4 | 183 | enterline(num, ModeReady); |
okini3939 | 0:f18953137cb4 | 184 | enterline(activedest, ModeDisconnect); |
okini3939 | 0:f18953137cb4 | 185 | activesrc = PhoneNone; |
okini3939 | 0:f18953137cb4 | 186 | break; |
okini3939 | 0:f18953137cb4 | 187 | } |
okini3939 | 2:e37117117e79 | 188 | i = scanline(activedest, ScanStatus); |
okini3939 | 2:e37117117e79 | 189 | if (i == StatusOk) { |
okini3939 | 2:e37117117e79 | 190 | // ok call, ring back tone |
okini3939 | 2:e37117117e79 | 191 | enterline(num, ModeRBT); |
okini3939 | 2:e37117117e79 | 192 | } |
okini3939 | 2:e37117117e79 | 193 | if (timeout == 0 || i == StatusNg) { |
okini3939 | 0:f18953137cb4 | 194 | // timeout, busy |
okini3939 | 0:f18953137cb4 | 195 | enterline(num, ModeBT); |
okini3939 | 0:f18953137cb4 | 196 | enterline(activedest, ModeDisconnect); |
okini3939 | 0:f18953137cb4 | 197 | break; |
okini3939 | 0:f18953137cb4 | 198 | } |
okini3939 | 0:f18953137cb4 | 199 | break; |
okini3939 | 0:f18953137cb4 | 200 | |
okini3939 | 0:f18953137cb4 | 201 | case ModeRBT: |
okini3939 | 0:f18953137cb4 | 202 | if (scanline(num, ScanHook) == HookOff) { |
okini3939 | 0:f18953137cb4 | 203 | // off hook, exit |
okini3939 | 0:f18953137cb4 | 204 | enterline(num, ModeReady); |
okini3939 | 0:f18953137cb4 | 205 | enterline(activedest, ModeDisconnect); |
okini3939 | 0:f18953137cb4 | 206 | activesrc = PhoneNone; |
okini3939 | 0:f18953137cb4 | 207 | } |
okini3939 | 0:f18953137cb4 | 208 | break; |
okini3939 | 0:f18953137cb4 | 209 | |
okini3939 | 0:f18953137cb4 | 210 | case ModeRing: |
okini3939 | 0:f18953137cb4 | 211 | if (scanline(num, ScanHook) == HookOn) { |
okini3939 | 0:f18953137cb4 | 212 | // on hook, connect |
okini3939 | 0:f18953137cb4 | 213 | if (num == PhoneIpLine || activesrc == PhoneIpLine) { |
okini3939 | 2:e37117117e79 | 214 | enteranalog(PhoneIpLine); |
okini3939 | 0:f18953137cb4 | 215 | } else { |
okini3939 | 0:f18953137cb4 | 216 | enteranalog(PhoneNone); |
okini3939 | 0:f18953137cb4 | 217 | } |
okini3939 | 0:f18953137cb4 | 218 | enterline(num, ModeTalk); |
okini3939 | 0:f18953137cb4 | 219 | enterline(activesrc, ModeTalk); |
okini3939 | 0:f18953137cb4 | 220 | } |
okini3939 | 0:f18953137cb4 | 221 | break; |
okini3939 | 0:f18953137cb4 | 222 | |
okini3939 | 0:f18953137cb4 | 223 | case ModeTalk: |
okini3939 | 0:f18953137cb4 | 224 | if (scanline(num, ScanHook) == HookOff) { |
okini3939 | 0:f18953137cb4 | 225 | // off hook, exit |
okini3939 | 0:f18953137cb4 | 226 | enterline(num, ModeReady); |
okini3939 | 0:f18953137cb4 | 227 | enterline(num == activesrc ? activedest : activesrc, ModeDisconnect); |
okini3939 | 0:f18953137cb4 | 228 | activesrc = PhoneNone; |
okini3939 | 0:f18953137cb4 | 229 | break; |
okini3939 | 0:f18953137cb4 | 230 | } |
okini3939 | 1:0f82c574096f | 231 | if (scanline(activedest, ScanStatus) == StatusNg) { |
okini3939 | 0:f18953137cb4 | 232 | // disconnect |
okini3939 | 0:f18953137cb4 | 233 | enterline(num, ModeBT); |
okini3939 | 0:f18953137cb4 | 234 | } |
okini3939 | 0:f18953137cb4 | 235 | break; |
okini3939 | 0:f18953137cb4 | 236 | |
okini3939 | 0:f18953137cb4 | 237 | case ModeBT: |
okini3939 | 0:f18953137cb4 | 238 | if (scanline(num, ScanHook) == HookOff) { |
okini3939 | 0:f18953137cb4 | 239 | // off hook, exit |
okini3939 | 0:f18953137cb4 | 240 | enterline(num, ModeReady); |
okini3939 | 0:f18953137cb4 | 241 | if (activesrc == num) activesrc = PhoneNone; |
okini3939 | 0:f18953137cb4 | 242 | if (activedest == num) activedest = PhoneNone; |
okini3939 | 0:f18953137cb4 | 243 | } |
okini3939 | 0:f18953137cb4 | 244 | break; |
okini3939 | 0:f18953137cb4 | 245 | |
okini3939 | 0:f18953137cb4 | 246 | case ModeDisconnect: |
okini3939 | 0:f18953137cb4 | 247 | enterline(num, ModeBT); |
okini3939 | 0:f18953137cb4 | 248 | break; |
okini3939 | 0:f18953137cb4 | 249 | |
okini3939 | 0:f18953137cb4 | 250 | } |
okini3939 | 0:f18953137cb4 | 251 | |
okini3939 | 0:f18953137cb4 | 252 | } |
okini3939 | 0:f18953137cb4 | 253 | |
okini3939 | 0:f18953137cb4 | 254 | |
okini3939 | 0:f18953137cb4 | 255 | int main () { |
okini3939 | 2:e37117117e79 | 256 | int i; |
okini3939 | 2:e37117117e79 | 257 | |
okini3939 | 0:f18953137cb4 | 258 | timeout = 0; |
okini3939 | 6:bd62b12de751 | 259 | useipline = 0; |
okini3939 | 0:f18953137cb4 | 260 | dialcount = 0; |
okini3939 | 0:f18953137cb4 | 261 | activesrc = PhoneNone; |
okini3939 | 0:f18953137cb4 | 262 | activedest = PhoneNone; |
okini3939 | 6:bd62b12de751 | 263 | |
okini3939 | 6:bd62b12de751 | 264 | config(); |
okini3939 | 6:bd62b12de751 | 265 | |
okini3939 | 0:f18953137cb4 | 266 | line1.enter(ModeReady); |
okini3939 | 0:f18953137cb4 | 267 | line2.enter(ModeReady); |
okini3939 | 6:bd62b12de751 | 268 | if (useipline) { |
okini3939 | 6:bd62b12de751 | 269 | ipline = new IpLine(eth, dac, adc); |
okini3939 | 6:bd62b12de751 | 270 | ipline->enter(ModeReady); |
okini3939 | 6:bd62b12de751 | 271 | } |
okini3939 | 0:f18953137cb4 | 272 | |
okini3939 | 5:30e2847d241b | 273 | // NVIC_SetPriority(TIMER3_IRQn, 0); // preemption=1, sub-priority=1 |
okini3939 | 0:f18953137cb4 | 274 | ticker.attach_us(&int_sample, 1000000 / FREQ); |
okini3939 | 0:f18953137cb4 | 275 | |
okini3939 | 0:f18953137cb4 | 276 | for (;;) { |
okini3939 | 6:bd62b12de751 | 277 | if (useipline) { |
okini3939 | 6:bd62b12de751 | 278 | led1 = 1; |
okini3939 | 6:bd62b12de751 | 279 | ipline->poll(); |
okini3939 | 6:bd62b12de751 | 280 | led1 = 0; |
okini3939 | 6:bd62b12de751 | 281 | } |
okini3939 | 5:30e2847d241b | 282 | led2 = 1; |
okini3939 | 4:41a3534d085f | 283 | line1.poll(); |
okini3939 | 5:30e2847d241b | 284 | led2 = 0; |
okini3939 | 5:30e2847d241b | 285 | led3 = 1; |
okini3939 | 4:41a3534d085f | 286 | line2.poll(); |
okini3939 | 5:30e2847d241b | 287 | led3 = 0; |
okini3939 | 2:e37117117e79 | 288 | |
okini3939 | 2:e37117117e79 | 289 | i = scanline(PhoneLine1, ScanMode); |
okini3939 | 0:f18953137cb4 | 290 | checkline(PhoneLine1); |
okini3939 | 2:e37117117e79 | 291 | if (i != scanline(PhoneLine1, ScanMode)) |
okini3939 | 2:e37117117e79 | 292 | pc.printf("(1) %d -> %d\r\n", i, scanline(PhoneLine1, ScanMode)); |
okini3939 | 2:e37117117e79 | 293 | |
okini3939 | 2:e37117117e79 | 294 | i = scanline(PhoneLine2, ScanMode); |
okini3939 | 0:f18953137cb4 | 295 | checkline(PhoneLine2); |
okini3939 | 2:e37117117e79 | 296 | if (i != scanline(PhoneLine2, ScanMode)) |
okini3939 | 2:e37117117e79 | 297 | pc.printf("(2) %d -> %d\r\n", i, scanline(PhoneLine2, ScanMode)); |
okini3939 | 2:e37117117e79 | 298 | |
okini3939 | 6:bd62b12de751 | 299 | if (useipline) { |
okini3939 | 6:bd62b12de751 | 300 | i = scanline(PhoneIpLine, ScanMode); |
okini3939 | 6:bd62b12de751 | 301 | checkline(PhoneIpLine); |
okini3939 | 6:bd62b12de751 | 302 | if (i != scanline(PhoneIpLine, ScanMode)) |
okini3939 | 6:bd62b12de751 | 303 | pc.printf("(3) %d -> %d\r\n", i, scanline(PhoneIpLine, ScanMode)); |
okini3939 | 6:bd62b12de751 | 304 | } |
okini3939 | 2:e37117117e79 | 305 | |
okini3939 | 0:f18953137cb4 | 306 | } |
okini3939 | 0:f18953137cb4 | 307 | } |