MP3(DFR0534)+BLE(TYBLE16)
Dependencies: MP3_DFR0534 mbed-os_TYBLE16
see /users/kenjiArai/notebook/mp3--voice-module-dfr0534/
main.cpp@10:5d2299daf831, 2020-02-04 (annotated)
- Committer:
- kenjiArai
- Date:
- Tue Feb 04 08:23:56 2020 +0000
- Revision:
- 10:5d2299daf831
- Parent:
- 9:8c9e6e270b67
MP3(DFR0534)+BLE(TYBLE16)
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
kenjiArai | 6:a3238e93f694 | 1 | /* |
kenjiArai | 10:5d2299daf831 | 2 | * December 31st, 2015 Modified by Kenji Arai |
kenjiArai | 10:5d2299daf831 | 3 | * January 19th, 2016 |
kenjiArai | 10:5d2299daf831 | 4 | * October 12th, 2017 !! Run on Mbed-os5 |
kenjiArai | 10:5d2299daf831 | 5 | * http://www.page.sannet.ne.jp/kenjia/index.html |
kenjiArai | 10:5d2299daf831 | 6 | * https://os.mbed.com/users/kenjiArai/ |
kenjiArai | 10:5d2299daf831 | 7 | * April 14th, 2018 run on TYBLE16 |
kenjiArai | 10:5d2299daf831 | 8 | * January 23rd, 2020 TYBLE16(mbed-os5.1.5.0) |
kenjiArai | 6:a3238e93f694 | 9 | * |
kenjiArai | 10:5d2299daf831 | 10 | * Original: |
kenjiArai | 10:5d2299daf831 | 11 | * BLE_RCBController2_Motor |
kenjiArai | 10:5d2299daf831 | 12 | * https://developer.mbed.org/users/robo8080/code/BLE_RCBController2_Motor/ |
kenjiArai | 10:5d2299daf831 | 13 | * Tested Controller Device: |
kenjiArai | 10:5d2299daf831 | 14 | * iPhone6 RCBController (Ver1.4.0) |
kenjiArai | 10:5d2299daf831 | 15 | * https://itunes.apple.com/jp/app/rcbcontroller/id689724127?mt=8 |
kenjiArai | 6:a3238e93f694 | 16 | */ |
kenjiArai | 6:a3238e93f694 | 17 | |
kenjiArai | 6:a3238e93f694 | 18 | #include "mbed.h" |
kenjiArai | 10:5d2299daf831 | 19 | #include "BLE.h" |
kenjiArai | 10:5d2299daf831 | 20 | #include "RCBController.h" |
kenjiArai | 6:a3238e93f694 | 21 | #include "TYBLE16_BASE.h" |
kenjiArai | 10:5d2299daf831 | 22 | #include "drf0534.h" |
kenjiArai | 10:5d2299daf831 | 23 | |
kenjiArai | 10:5d2299daf831 | 24 | #define NEED_CONSOLE_OUTPUT 0 // Keep 1 |
kenjiArai | 6:a3238e93f694 | 25 | |
kenjiArai | 10:5d2299daf831 | 26 | #if NEED_CONSOLE_OUTPUT |
kenjiArai | 10:5d2299daf831 | 27 | #define DEBUG(...) { pc.printf(__VA_ARGS__); } |
kenjiArai | 10:5d2299daf831 | 28 | #else |
kenjiArai | 10:5d2299daf831 | 29 | #define DEBUG(...) |
kenjiArai | 10:5d2299daf831 | 30 | #endif |
kenjiArai | 6:a3238e93f694 | 31 | |
kenjiArai | 10:5d2299daf831 | 32 | //BLE ble_rcb; |
kenjiArai | 10:5d2299daf831 | 33 | BLE &ble_rcb = BLE::Instance(); |
kenjiArai | 10:5d2299daf831 | 34 | #if NEED_CONSOLE_OUTPUT |
kenjiArai | 6:a3238e93f694 | 35 | Serial pc(USBTX, USBRX); |
kenjiArai | 10:5d2299daf831 | 36 | #else |
kenjiArai | 10:5d2299daf831 | 37 | DFR0534 mp3(USBTX, USBRX, A0); // tx, rx, busy |
kenjiArai | 10:5d2299daf831 | 38 | #endif |
kenjiArai | 6:a3238e93f694 | 39 | |
kenjiArai | 10:5d2299daf831 | 40 | uint8_t RCBControllerPayload[10] = {0,}; |
kenjiArai | 10:5d2299daf831 | 41 | RCBController controller; |
kenjiArai | 6:a3238e93f694 | 42 | |
kenjiArai | 10:5d2299daf831 | 43 | // RCBController Service |
kenjiArai | 10:5d2299daf831 | 44 | static const uint16_t RCBController_service_uuid = 0xFFF0; |
kenjiArai | 10:5d2299daf831 | 45 | static const uint16_t RCBController_Characteristic_uuid = 0xFFF1; |
kenjiArai | 10:5d2299daf831 | 46 | const char *deviceName = "Mbed-BLE"; |
kenjiArai | 10:5d2299daf831 | 47 | const char *const opngmsg = |
kenjiArai | 10:5d2299daf831 | 48 | "\x1b[2J\x1b[H" __FILE__ "\r\n" __DATE__ " " __TIME__ " (UTC)\r\n""\r\n"; |
kenjiArai | 8:7e42f8dc42a2 | 49 | |
kenjiArai | 10:5d2299daf831 | 50 | GattCharacteristic ControllerChar ( |
kenjiArai | 10:5d2299daf831 | 51 | RCBController_Characteristic_uuid,RCBControllerPayload,10, 10, |
kenjiArai | 10:5d2299daf831 | 52 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE | |
kenjiArai | 10:5d2299daf831 | 53 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE |
kenjiArai | 10:5d2299daf831 | 54 | ); |
kenjiArai | 10:5d2299daf831 | 55 | GattCharacteristic *ControllerChars[] = {&ControllerChar}; |
kenjiArai | 10:5d2299daf831 | 56 | GattService RCBControllerService( |
kenjiArai | 10:5d2299daf831 | 57 | RCBController_service_uuid, |
kenjiArai | 10:5d2299daf831 | 58 | ControllerChars, |
kenjiArai | 10:5d2299daf831 | 59 | sizeof(ControllerChars) / sizeof(GattCharacteristic *) |
kenjiArai | 10:5d2299daf831 | 60 | ); |
kenjiArai | 6:a3238e93f694 | 61 | |
kenjiArai | 6:a3238e93f694 | 62 | //------------------------------------------------------------------------------ |
kenjiArai | 6:a3238e93f694 | 63 | // Control Program |
kenjiArai | 6:a3238e93f694 | 64 | //------------------------------------------------------------------------------ |
kenjiArai | 10:5d2299daf831 | 65 | void data_analysis(void) |
kenjiArai | 6:a3238e93f694 | 66 | { |
kenjiArai | 10:5d2299daf831 | 67 | static uint8_t key = 0; |
kenjiArai | 10:5d2299daf831 | 68 | static bool idle = true; |
kenjiArai | 10:5d2299daf831 | 69 | static bool previous_key = 0; |
kenjiArai | 6:a3238e93f694 | 70 | |
kenjiArai | 10:5d2299daf831 | 71 | uint16_t key_data = (controller.data[0] << 8) + controller.data[1]; |
kenjiArai | 10:5d2299daf831 | 72 | switch(key_data) { |
kenjiArai | 10:5d2299daf831 | 73 | case 0: |
kenjiArai | 10:5d2299daf831 | 74 | key = 0; |
kenjiArai | 10:5d2299daf831 | 75 | idle = true; |
kenjiArai | 10:5d2299daf831 | 76 | break; |
kenjiArai | 10:5d2299daf831 | 77 | case 1: |
kenjiArai | 10:5d2299daf831 | 78 | key = 11; |
kenjiArai | 10:5d2299daf831 | 79 | if (idle == true) { |
kenjiArai | 10:5d2299daf831 | 80 | idle = false; |
kenjiArai | 10:5d2299daf831 | 81 | mp3.play_one(key); |
kenjiArai | 10:5d2299daf831 | 82 | } |
kenjiArai | 10:5d2299daf831 | 83 | break; |
kenjiArai | 10:5d2299daf831 | 84 | case 2: |
kenjiArai | 10:5d2299daf831 | 85 | key = 15; |
kenjiArai | 10:5d2299daf831 | 86 | break; |
kenjiArai | 10:5d2299daf831 | 87 | case 4: |
kenjiArai | 10:5d2299daf831 | 88 | key = 16; |
kenjiArai | 10:5d2299daf831 | 89 | break; |
kenjiArai | 10:5d2299daf831 | 90 | case 5: |
kenjiArai | 10:5d2299daf831 | 91 | key = 12; |
kenjiArai | 10:5d2299daf831 | 92 | if (idle == true) { |
kenjiArai | 10:5d2299daf831 | 93 | idle = false; |
kenjiArai | 10:5d2299daf831 | 94 | mp3.play_one(key); |
kenjiArai | 10:5d2299daf831 | 95 | } |
kenjiArai | 10:5d2299daf831 | 96 | break; |
kenjiArai | 10:5d2299daf831 | 97 | case 6: |
kenjiArai | 10:5d2299daf831 | 98 | key = 17; |
kenjiArai | 10:5d2299daf831 | 99 | break; |
kenjiArai | 10:5d2299daf831 | 100 | case 8: |
kenjiArai | 10:5d2299daf831 | 101 | key = 13; |
kenjiArai | 10:5d2299daf831 | 102 | if (idle == true) { |
kenjiArai | 10:5d2299daf831 | 103 | idle = false; |
kenjiArai | 10:5d2299daf831 | 104 | mp3.volume_increase(); |
kenjiArai | 10:5d2299daf831 | 105 | } |
kenjiArai | 10:5d2299daf831 | 106 | break; |
kenjiArai | 10:5d2299daf831 | 107 | case 9: |
kenjiArai | 10:5d2299daf831 | 108 | key = 10; |
kenjiArai | 10:5d2299daf831 | 109 | if (idle == true) { |
kenjiArai | 10:5d2299daf831 | 110 | idle = false; |
kenjiArai | 10:5d2299daf831 | 111 | mp3.play_one(key); |
kenjiArai | 10:5d2299daf831 | 112 | } |
kenjiArai | 10:5d2299daf831 | 113 | break; |
kenjiArai | 10:5d2299daf831 | 114 | case 10: |
kenjiArai | 10:5d2299daf831 | 115 | key = 14; |
kenjiArai | 10:5d2299daf831 | 116 | if (idle == true) { |
kenjiArai | 10:5d2299daf831 | 117 | idle = false; |
kenjiArai | 10:5d2299daf831 | 118 | mp3.volume_decrease(); |
kenjiArai | 10:5d2299daf831 | 119 | } |
kenjiArai | 10:5d2299daf831 | 120 | break; |
kenjiArai | 10:5d2299daf831 | 121 | case 16: |
kenjiArai | 10:5d2299daf831 | 122 | key = 2; |
kenjiArai | 10:5d2299daf831 | 123 | if (idle == true) { |
kenjiArai | 10:5d2299daf831 | 124 | idle = false; |
kenjiArai | 10:5d2299daf831 | 125 | mp3.play_one(key); |
kenjiArai | 10:5d2299daf831 | 126 | } |
kenjiArai | 10:5d2299daf831 | 127 | break; |
kenjiArai | 10:5d2299daf831 | 128 | case 32: |
kenjiArai | 10:5d2299daf831 | 129 | key = 8; |
kenjiArai | 10:5d2299daf831 | 130 | if (idle == true) { |
kenjiArai | 10:5d2299daf831 | 131 | idle = false; |
kenjiArai | 10:5d2299daf831 | 132 | mp3.play_one(key); |
kenjiArai | 10:5d2299daf831 | 133 | } |
kenjiArai | 10:5d2299daf831 | 134 | break; |
kenjiArai | 10:5d2299daf831 | 135 | case 64: |
kenjiArai | 10:5d2299daf831 | 136 | key = 6; |
kenjiArai | 10:5d2299daf831 | 137 | if (idle == true) { |
kenjiArai | 10:5d2299daf831 | 138 | idle = false; |
kenjiArai | 10:5d2299daf831 | 139 | mp3.play_one(key); |
kenjiArai | 10:5d2299daf831 | 140 | } |
kenjiArai | 10:5d2299daf831 | 141 | break; |
kenjiArai | 10:5d2299daf831 | 142 | case 80: |
kenjiArai | 10:5d2299daf831 | 143 | key = 3; |
kenjiArai | 10:5d2299daf831 | 144 | if (idle == true) { |
kenjiArai | 10:5d2299daf831 | 145 | idle = false; |
kenjiArai | 10:5d2299daf831 | 146 | mp3.play_one(key); |
kenjiArai | 10:5d2299daf831 | 147 | } |
kenjiArai | 10:5d2299daf831 | 148 | break; |
kenjiArai | 10:5d2299daf831 | 149 | case 96: |
kenjiArai | 10:5d2299daf831 | 150 | key = 9; |
kenjiArai | 10:5d2299daf831 | 151 | if (idle == true) { |
kenjiArai | 10:5d2299daf831 | 152 | idle = false; |
kenjiArai | 10:5d2299daf831 | 153 | mp3.play_one(key); |
kenjiArai | 10:5d2299daf831 | 154 | } |
kenjiArai | 10:5d2299daf831 | 155 | break; |
kenjiArai | 10:5d2299daf831 | 156 | case 128: |
kenjiArai | 10:5d2299daf831 | 157 | key = 5; |
kenjiArai | 10:5d2299daf831 | 158 | if (idle == true) { |
kenjiArai | 10:5d2299daf831 | 159 | idle = false; |
kenjiArai | 10:5d2299daf831 | 160 | mp3.play_one(key); |
kenjiArai | 10:5d2299daf831 | 161 | } |
kenjiArai | 10:5d2299daf831 | 162 | break; |
kenjiArai | 10:5d2299daf831 | 163 | case 256: |
kenjiArai | 10:5d2299daf831 | 164 | key = 4; |
kenjiArai | 10:5d2299daf831 | 165 | if (idle == true) { |
kenjiArai | 10:5d2299daf831 | 166 | idle = false; |
kenjiArai | 10:5d2299daf831 | 167 | mp3.play_one(key); |
kenjiArai | 10:5d2299daf831 | 168 | } |
kenjiArai | 10:5d2299daf831 | 169 | break; |
kenjiArai | 10:5d2299daf831 | 170 | case 272: |
kenjiArai | 10:5d2299daf831 | 171 | key = 1; |
kenjiArai | 10:5d2299daf831 | 172 | if (idle == true) { |
kenjiArai | 10:5d2299daf831 | 173 | idle = false; |
kenjiArai | 10:5d2299daf831 | 174 | mp3.play_one(key); |
kenjiArai | 10:5d2299daf831 | 175 | } |
kenjiArai | 10:5d2299daf831 | 176 | break; |
kenjiArai | 10:5d2299daf831 | 177 | case 288: |
kenjiArai | 10:5d2299daf831 | 178 | key = 7; |
kenjiArai | 10:5d2299daf831 | 179 | if (idle == true) { |
kenjiArai | 10:5d2299daf831 | 180 | idle = false; |
kenjiArai | 10:5d2299daf831 | 181 | mp3.play_one(key); |
kenjiArai | 10:5d2299daf831 | 182 | } |
kenjiArai | 10:5d2299daf831 | 183 | break; |
kenjiArai | 10:5d2299daf831 | 184 | case 512: |
kenjiArai | 10:5d2299daf831 | 185 | key = 18; |
kenjiArai | 10:5d2299daf831 | 186 | if (idle == true) { |
kenjiArai | 10:5d2299daf831 | 187 | idle = false; |
kenjiArai | 10:5d2299daf831 | 188 | mp3.command(Prev_Audio); |
kenjiArai | 10:5d2299daf831 | 189 | } |
kenjiArai | 10:5d2299daf831 | 190 | break; |
kenjiArai | 10:5d2299daf831 | 191 | case 1024: |
kenjiArai | 10:5d2299daf831 | 192 | key = 19; |
kenjiArai | 10:5d2299daf831 | 193 | if (idle == true) { |
kenjiArai | 10:5d2299daf831 | 194 | idle = false; |
kenjiArai | 10:5d2299daf831 | 195 | mp3.command(Play); |
kenjiArai | 10:5d2299daf831 | 196 | } |
kenjiArai | 10:5d2299daf831 | 197 | break; |
kenjiArai | 10:5d2299daf831 | 198 | case 2048: |
kenjiArai | 10:5d2299daf831 | 199 | key = 21; |
kenjiArai | 10:5d2299daf831 | 200 | if (idle == true) { |
kenjiArai | 10:5d2299daf831 | 201 | idle = false; |
kenjiArai | 10:5d2299daf831 | 202 | uint32_t num = mp3.total_num_of_audio(); |
kenjiArai | 10:5d2299daf831 | 203 | for (uint32_t i = 1; i < num + 1; i++) { |
kenjiArai | 10:5d2299daf831 | 204 | mp3.play_one(i); |
kenjiArai | 10:5d2299daf831 | 205 | } |
kenjiArai | 10:5d2299daf831 | 206 | } |
kenjiArai | 10:5d2299daf831 | 207 | break; |
kenjiArai | 10:5d2299daf831 | 208 | case 4096: |
kenjiArai | 10:5d2299daf831 | 209 | key = 20; |
kenjiArai | 10:5d2299daf831 | 210 | if (idle == true) { |
kenjiArai | 10:5d2299daf831 | 211 | idle = false; |
kenjiArai | 10:5d2299daf831 | 212 | mp3.command(Next_Audio); |
kenjiArai | 10:5d2299daf831 | 213 | } |
kenjiArai | 10:5d2299daf831 | 214 | break; |
kenjiArai | 10:5d2299daf831 | 215 | default: |
kenjiArai | 10:5d2299daf831 | 216 | key = 0; |
kenjiArai | 6:a3238e93f694 | 217 | } |
kenjiArai | 10:5d2299daf831 | 218 | DEBUG("DATA:%d\r\n", key); |
kenjiArai | 9:8c9e6e270b67 | 219 | } |
kenjiArai | 9:8c9e6e270b67 | 220 | |
kenjiArai | 10:5d2299daf831 | 221 | void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params) |
kenjiArai | 10:5d2299daf831 | 222 | { |
kenjiArai | 10:5d2299daf831 | 223 | DEBUG("Disconnected!\r\n"); |
kenjiArai | 10:5d2299daf831 | 224 | DEBUG("Restarting the advertising process\r\n"); |
kenjiArai | 10:5d2299daf831 | 225 | ble_rcb.gap().startAdvertising(); |
kenjiArai | 10:5d2299daf831 | 226 | } |
kenjiArai | 10:5d2299daf831 | 227 | |
kenjiArai | 10:5d2299daf831 | 228 | void onDataWritten(const GattWriteCallbackParams *params) |
kenjiArai | 9:8c9e6e270b67 | 229 | { |
kenjiArai | 10:5d2299daf831 | 230 | if (params->handle == ControllerChar.getValueAttribute().getHandle()) { |
kenjiArai | 10:5d2299daf831 | 231 | uint16_t bytesRead; |
kenjiArai | 10:5d2299daf831 | 232 | ble_rcb.gattServer().read( |
kenjiArai | 10:5d2299daf831 | 233 | //ble_rcb.readCharacteristicValue( |
kenjiArai | 10:5d2299daf831 | 234 | ControllerChar.getValueAttribute().getHandle(), |
kenjiArai | 10:5d2299daf831 | 235 | RCBControllerPayload, &bytesRead |
kenjiArai | 10:5d2299daf831 | 236 | ); |
kenjiArai | 10:5d2299daf831 | 237 | memcpy( &controller.data[0], RCBControllerPayload, sizeof(controller)); |
kenjiArai | 10:5d2299daf831 | 238 | DEBUG("DATA:0x%02x 0x%02x %d %d %d %d %d %d %d 0x%02x\r\n", |
kenjiArai | 10:5d2299daf831 | 239 | controller.data[0],controller.data[1], |
kenjiArai | 10:5d2299daf831 | 240 | controller.data[2],controller.data[3], |
kenjiArai | 10:5d2299daf831 | 241 | controller.data[4],controller.data[5], |
kenjiArai | 10:5d2299daf831 | 242 | controller.data[6],controller.data[7], |
kenjiArai | 10:5d2299daf831 | 243 | controller.data[8],controller.data[9] |
kenjiArai | 10:5d2299daf831 | 244 | ); |
kenjiArai | 10:5d2299daf831 | 245 | uint16_t key_data = (controller.data[0] << 8) + controller.data[1]; |
kenjiArai | 10:5d2299daf831 | 246 | DEBUG("DATA:%d\r\n", key_data); |
kenjiArai | 10:5d2299daf831 | 247 | data_analysis(); |
kenjiArai | 10:5d2299daf831 | 248 | } |
kenjiArai | 6:a3238e93f694 | 249 | } |
kenjiArai | 6:a3238e93f694 | 250 | |
kenjiArai | 10:5d2299daf831 | 251 | int main(void) |
kenjiArai | 6:a3238e93f694 | 252 | { |
kenjiArai | 10:5d2299daf831 | 253 | mp3.volume_setting(0); |
kenjiArai | 10:5d2299daf831 | 254 | DEBUG("%s", opngmsg); |
kenjiArai | 10:5d2299daf831 | 255 | DEBUG("\r\nInitialising the nRF51822\r\n"); |
kenjiArai | 10:5d2299daf831 | 256 | // Check TYBLE-16 configuration |
kenjiArai | 10:5d2299daf831 | 257 | //cpu_sys(); |
kenjiArai | 10:5d2299daf831 | 258 | //compile_condition(); |
kenjiArai | 8:7e42f8dc42a2 | 259 | |
kenjiArai | 10:5d2299daf831 | 260 | ble_rcb.init(); |
kenjiArai | 10:5d2299daf831 | 261 | ble_rcb.gap().setDeviceName((const uint8_t *)deviceName); |
kenjiArai | 10:5d2299daf831 | 262 | ble_rcb.gap().onDisconnection(disconnectionCallback); |
kenjiArai | 10:5d2299daf831 | 263 | ble_rcb.gattServer().onDataWritten(onDataWritten); |
kenjiArai | 10:5d2299daf831 | 264 | DEBUG("Start RCB Controller\r\n"); |
kenjiArai | 10:5d2299daf831 | 265 | /* setup advertising */ |
kenjiArai | 10:5d2299daf831 | 266 | ble_rcb.gap().accumulateAdvertisingPayload( |
kenjiArai | 10:5d2299daf831 | 267 | GapAdvertisingData::BREDR_NOT_SUPPORTED |
kenjiArai | 10:5d2299daf831 | 268 | ); |
kenjiArai | 10:5d2299daf831 | 269 | ble_rcb.gap().setAdvertisingType( |
kenjiArai | 10:5d2299daf831 | 270 | GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED |
kenjiArai | 10:5d2299daf831 | 271 | ); |
kenjiArai | 10:5d2299daf831 | 272 | ble_rcb.gap().accumulateAdvertisingPayload( |
kenjiArai | 10:5d2299daf831 | 273 | GapAdvertisingData::SHORTENED_LOCAL_NAME, |
kenjiArai | 10:5d2299daf831 | 274 | (const uint8_t *)deviceName, strlen(deviceName) |
kenjiArai | 10:5d2299daf831 | 275 | ); |
kenjiArai | 10:5d2299daf831 | 276 | ble_rcb.gap().accumulateAdvertisingPayload( |
kenjiArai | 10:5d2299daf831 | 277 | GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, |
kenjiArai | 10:5d2299daf831 | 278 | (const uint8_t *)RCBController_service_uuid, |
kenjiArai | 10:5d2299daf831 | 279 | sizeof(RCBController_service_uuid) |
kenjiArai | 10:5d2299daf831 | 280 | ); |
kenjiArai | 10:5d2299daf831 | 281 | ble_rcb.gap().setAdvertisingInterval(160); /* 100ms; in multiples of 0.625ms. */ |
kenjiArai | 10:5d2299daf831 | 282 | ble_rcb.gap().startAdvertising(); |
kenjiArai | 10:5d2299daf831 | 283 | ble_rcb.gattServer().addService(RCBControllerService); |
kenjiArai | 10:5d2299daf831 | 284 | while (true) { |
kenjiArai | 10:5d2299daf831 | 285 | ble_rcb.waitForEvent(); |
kenjiArai | 6:a3238e93f694 | 286 | } |
kenjiArai | 6:a3238e93f694 | 287 | } |