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.
Fork of football_project by
main.cpp@11:d3aa5fca2330, 2015-04-23 (annotated)
- Committer:
- AntonLS
- Date:
- Thu Apr 23 06:36:57 2015 +0000
- Revision:
- 11:d3aa5fca2330
- Parent:
- 10:72ceef287b0f
- Child:
- 12:6d313d575f84
PhoneAppIO class working.
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| AntonLS | 0:28ca4562fe1a | 1 | /* |
| AntonLS | 0:28ca4562fe1a | 2 | * TA test |
| AntonLS | 0:28ca4562fe1a | 3 | * |
| AntonLS | 11:d3aa5fca2330 | 4 | * TODO maybe have a mode where the serial port I/O can be swapped, |
| AntonLS | 11:d3aa5fca2330 | 5 | * such that what the nRF generates is sent out the serial port, |
| AntonLS | 11:d3aa5fca2330 | 6 | * and what comes in the serial port goes into the nRF. |
| AntonLS | 11:d3aa5fca2330 | 7 | * Maybe could use the now-unused CTS pin for that. |
| AntonLS | 0:28ca4562fe1a | 8 | */ |
| AntonLS | 0:28ca4562fe1a | 9 | |
| AntonLS | 0:28ca4562fe1a | 10 | /* mbed Microcontroller Library |
| AntonLS | 0:28ca4562fe1a | 11 | * Copyright (c) 2006-2013 ARM Limited |
| AntonLS | 0:28ca4562fe1a | 12 | * |
| AntonLS | 0:28ca4562fe1a | 13 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| AntonLS | 0:28ca4562fe1a | 14 | * you may not use this file except in compliance with the License. |
| AntonLS | 0:28ca4562fe1a | 15 | * You may obtain a copy of the License at |
| AntonLS | 0:28ca4562fe1a | 16 | * |
| AntonLS | 0:28ca4562fe1a | 17 | * http://www.apache.org/licenses/LICENSE-2.0 |
| AntonLS | 0:28ca4562fe1a | 18 | * |
| AntonLS | 0:28ca4562fe1a | 19 | * Unless required by applicable law or agreed to in writing, software |
| AntonLS | 0:28ca4562fe1a | 20 | * distributed under the License is distributed on an "AS IS" BASIS, |
| AntonLS | 0:28ca4562fe1a | 21 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| AntonLS | 0:28ca4562fe1a | 22 | * See the License for the specific language governing permissions and |
| AntonLS | 0:28ca4562fe1a | 23 | * limitations under the License. |
| AntonLS | 0:28ca4562fe1a | 24 | */ |
| AntonLS | 0:28ca4562fe1a | 25 | |
| AntonLS | 0:28ca4562fe1a | 26 | #include "mbed.h" |
| AntonLS | 0:28ca4562fe1a | 27 | #include "BLEDevice.h" |
| AntonLS | 0:28ca4562fe1a | 28 | |
| AntonLS | 0:28ca4562fe1a | 29 | #include "DFUService.h" |
| AntonLS | 0:28ca4562fe1a | 30 | #include "UARTService.h" |
| AntonLS | 0:28ca4562fe1a | 31 | #include "DeviceInformationService.h" |
| AntonLS | 0:28ca4562fe1a | 32 | |
| AntonLS | 0:28ca4562fe1a | 33 | #include "MTSSerialFlowControl.h" |
| AntonLS | 5:1b9734e68327 | 34 | #include "PhoneAppIO.h" |
| AntonLS | 0:28ca4562fe1a | 35 | |
| AntonLS | 0:28ca4562fe1a | 36 | #define NEED_CONSOLE_OUTPUT 0 /* Set this if you need debug messages on the console; |
| AntonLS | 0:28ca4562fe1a | 37 | * it will have an impact on code-size and power consumption. */ |
| AntonLS | 0:28ca4562fe1a | 38 | |
| AntonLS | 11:d3aa5fca2330 | 39 | #define LOOPBACK_MODE 0 // Loopback mode |
| AntonLS | 4:17b8edf264c3 | 40 | |
| AntonLS | 0:28ca4562fe1a | 41 | #if NEED_CONSOLE_OUTPUT |
| AntonLS | 0:28ca4562fe1a | 42 | #define DEBUG(...) { printf(__VA_ARGS__); } |
| AntonLS | 0:28ca4562fe1a | 43 | #else |
| AntonLS | 0:28ca4562fe1a | 44 | #define DEBUG(...) /* nothing */ |
| AntonLS | 0:28ca4562fe1a | 45 | #endif /* #if NEED_CONSOLE_OUTPUT */ |
| AntonLS | 0:28ca4562fe1a | 46 | |
| AntonLS | 0:28ca4562fe1a | 47 | BLEDevice ble; |
| AntonLS | 0:28ca4562fe1a | 48 | |
| AntonLS | 0:28ca4562fe1a | 49 | extern "C" |
| AntonLS | 0:28ca4562fe1a | 50 | { |
| AntonLS | 2:fe1566cdb6e7 | 51 | // serial_t _my_serial; |
| AntonLS | 0:28ca4562fe1a | 52 | void pin_mode( PinName, PinMode ); |
| AntonLS | 0:28ca4562fe1a | 53 | } |
| AntonLS | 0:28ca4562fe1a | 54 | |
| AntonLS | 1:0ba687d4196f | 55 | // Note: From the datasheet: |
| AntonLS | 1:0ba687d4196f | 56 | // PSELRXD, PSELRTS, PSELTRTS and PSELTXD must only be configured when the UART is disabled. |
| AntonLS | 11:d3aa5fca2330 | 57 | // But a version of serial_init() erroneously enabled the uart before the setting of those, |
| AntonLS | 11:d3aa5fca2330 | 58 | // which messed up flow control. Apparently the setting is ONCE per ON mode. ARGH! |
| AntonLS | 11:d3aa5fca2330 | 59 | // So we made our own versions of Serial and SerialBase (MySerial and MySerialBase) |
| AntonLS | 7:205ef63d311a | 60 | // to not use serial_init() in serial_api.c, so flow control is setup correctly * |
| AntonLS | 7:205ef63d311a | 61 | // MTSSerial now uses our MySerial instead of Serial, and now uses hw flow control by default * |
| AntonLS | 11:d3aa5fca2330 | 62 | // * We can't change the uart interrupt vector, so we comment-out the handler in |
| AntonLS | 11:d3aa5fca2330 | 63 | // serial_api.c, and rebuild the mbed lib for low-level hw flow control to work. |
| AntonLS | 6:ef758ac3c928 | 64 | // MTSSerialFlowControl uses "manual" (non-hardware-low-level) flow control based on its |
| AntonLS | 11:d3aa5fca2330 | 65 | // internal buffer--Rx servicing usually is fast enough not to need hw flow control, so it's okay. |
| AntonLS | 1:0ba687d4196f | 66 | // |
| AntonLS | 7:205ef63d311a | 67 | // mts::MTSSerialFlowControl pcfc( USBTX, USBRX, RTS_PIN_NUMBER, CTS_PIN_NUMBER, 384, 2688 ); |
| AntonLS | 11:d3aa5fca2330 | 68 | mts::MTSSerial pcfc( USBTX, USBRX, 256, 1280, RTS_PIN_NUMBER, NC ); // 256, 2560 |
| AntonLS | 0:28ca4562fe1a | 69 | |
| AntonLS | 0:28ca4562fe1a | 70 | uint8_t txPayload[TXRX_BUF_LEN] = { 0 }; |
| AntonLS | 0:28ca4562fe1a | 71 | |
| AntonLS | 0:28ca4562fe1a | 72 | |
| AntonLS | 11:d3aa5fca2330 | 73 | DigitalOut led1( LED1 ); |
| AntonLS | 9:95dc84e9fb7f | 74 | // DigitalOut rts( RTS_PIN_NUMBER ); |
| AntonLS | 1:0ba687d4196f | 75 | |
| AntonLS | 1:0ba687d4196f | 76 | |
| AntonLS | 5:1b9734e68327 | 77 | char deviceName[6]; // "TAF00"; |
| AntonLS | 5:1b9734e68327 | 78 | Gap::address_t macAddr; |
| AntonLS | 5:1b9734e68327 | 79 | Gap::addr_type_t *pAdType; |
| AntonLS | 5:1b9734e68327 | 80 | |
| AntonLS | 0:28ca4562fe1a | 81 | |
| AntonLS | 0:28ca4562fe1a | 82 | const uint8_t DevInfoServiceUUID_rev[] = |
| AntonLS | 0:28ca4562fe1a | 83 | { |
| AntonLS | 0:28ca4562fe1a | 84 | (uint8_t)(GattService::UUID_DEVICE_INFORMATION_SERVICE & 0xFF), (uint8_t)(GattService::UUID_DEVICE_INFORMATION_SERVICE >> 8) |
| AntonLS | 0:28ca4562fe1a | 85 | }; |
| AntonLS | 0:28ca4562fe1a | 86 | |
| AntonLS | 0:28ca4562fe1a | 87 | UARTService *uartServicePtr; |
| AntonLS | 11:d3aa5fca2330 | 88 | PhoneAppIO *phoneP; |
| AntonLS | 0:28ca4562fe1a | 89 | |
| AntonLS | 11:d3aa5fca2330 | 90 | bool connected = false; |
| AntonLS | 5:1b9734e68327 | 91 | |
| AntonLS | 11:d3aa5fca2330 | 92 | void connectionCallback( Gap::Handle_t, Gap::addr_type_t peerAddrType, |
| AntonLS | 11:d3aa5fca2330 | 93 | const Gap::address_t peerAddr, const Gap::ConnectionParams_t *connParams ) |
| AntonLS | 11:d3aa5fca2330 | 94 | { |
| AntonLS | 11:d3aa5fca2330 | 95 | connected = true; |
| AntonLS | 11:d3aa5fca2330 | 96 | |
| AntonLS | 11:d3aa5fca2330 | 97 | DEBUG( "Connected!\n\r" ); |
| AntonLS | 11:d3aa5fca2330 | 98 | } |
| AntonLS | 5:1b9734e68327 | 99 | |
| AntonLS | 0:28ca4562fe1a | 100 | void disconnectionCallback( Gap::Handle_t handle, Gap::DisconnectionReason_t reason ) |
| AntonLS | 0:28ca4562fe1a | 101 | { |
| AntonLS | 11:d3aa5fca2330 | 102 | connected = false; |
| AntonLS | 11:d3aa5fca2330 | 103 | |
| AntonLS | 0:28ca4562fe1a | 104 | DEBUG( "Disconnected!\n\r" ); |
| AntonLS | 0:28ca4562fe1a | 105 | DEBUG( "Restarting the advertising process\n\r" ); |
| AntonLS | 0:28ca4562fe1a | 106 | ble.startAdvertising(); |
| AntonLS | 0:28ca4562fe1a | 107 | } |
| AntonLS | 0:28ca4562fe1a | 108 | |
| AntonLS | 5:1b9734e68327 | 109 | bool updateCharacteristic( GattAttribute::Handle_t handle, const uint8_t *data, uint16_t bytesRead ) |
| AntonLS | 5:1b9734e68327 | 110 | { |
| AntonLS | 11:d3aa5fca2330 | 111 | ble_error_t err = ble.updateCharacteristicValue( handle, data, bytesRead ); |
| AntonLS | 5:1b9734e68327 | 112 | |
| AntonLS | 5:1b9734e68327 | 113 | if( (err == BLE_ERROR_BUFFER_OVERFLOW) || |
| AntonLS | 5:1b9734e68327 | 114 | (err == BLE_ERROR_PARAM_OUT_OF_RANGE ) ) |
| AntonLS | 7:205ef63d311a | 115 | { |
| AntonLS | 10:72ceef287b0f | 116 | pcfc.printf( "\r\nBLE %d! ", err ); |
| AntonLS | 7:205ef63d311a | 117 | |
| AntonLS | 7:205ef63d311a | 118 | } else if ( err == BLE_STACK_BUSY ) |
| AntonLS | 7:205ef63d311a | 119 | { |
| AntonLS | 11:d3aa5fca2330 | 120 | // Common error when pumping data. |
| AntonLS | 7:205ef63d311a | 121 | } |
| AntonLS | 5:1b9734e68327 | 122 | |
| AntonLS | 5:1b9734e68327 | 123 | return (err != BLE_ERROR_NONE); |
| AntonLS | 5:1b9734e68327 | 124 | } |
| AntonLS | 5:1b9734e68327 | 125 | |
| AntonLS | 0:28ca4562fe1a | 126 | void onDataWritten( const GattCharacteristicWriteCBParams *params ) |
| AntonLS | 0:28ca4562fe1a | 127 | { |
| AntonLS | 11:d3aa5fca2330 | 128 | if( phoneP != NULL ) |
| AntonLS | 0:28ca4562fe1a | 129 | { |
| AntonLS | 11:d3aa5fca2330 | 130 | uint16_t bytesRead = phoneP->maybeHandleRead( params ); // Also writes to txPayload |
| AntonLS | 11:d3aa5fca2330 | 131 | if( 0 != bytesRead ) |
| AntonLS | 11:d3aa5fca2330 | 132 | { |
| AntonLS | 11:d3aa5fca2330 | 133 | DEBUG( "received %u bytes\n\r", bytesRead ); |
| AntonLS | 0:28ca4562fe1a | 134 | |
| AntonLS | 11:d3aa5fca2330 | 135 | // Also write to serial port... |
| AntonLS | 11:d3aa5fca2330 | 136 | // pcfc.printf( "From app: " ); |
| AntonLS | 11:d3aa5fca2330 | 137 | pcfc.write( (char *)txPayload, bytesRead ); |
| AntonLS | 11:d3aa5fca2330 | 138 | // pcfc.printf( "\r\n" ); |
| AntonLS | 5:1b9734e68327 | 139 | |
| AntonLS | 11:d3aa5fca2330 | 140 | return; |
| AntonLS | 11:d3aa5fca2330 | 141 | } |
| AntonLS | 0:28ca4562fe1a | 142 | } |
| AntonLS | 11:d3aa5fca2330 | 143 | |
| AntonLS | 11:d3aa5fca2330 | 144 | // Other Characteristics here. |
| AntonLS | 0:28ca4562fe1a | 145 | } |
| AntonLS | 0:28ca4562fe1a | 146 | |
| AntonLS | 0:28ca4562fe1a | 147 | void onDataSent( unsigned count ) |
| AntonLS | 0:28ca4562fe1a | 148 | { |
| AntonLS | 0:28ca4562fe1a | 149 | } |
| AntonLS | 0:28ca4562fe1a | 150 | |
| AntonLS | 0:28ca4562fe1a | 151 | void periodicCallback( void ) |
| AntonLS | 0:28ca4562fe1a | 152 | { |
| AntonLS | 11:d3aa5fca2330 | 153 | led1 = !led1; |
| AntonLS | 3:388e441be8df | 154 | // rts = !rts; |
| AntonLS | 0:28ca4562fe1a | 155 | } |
| AntonLS | 0:28ca4562fe1a | 156 | |
| AntonLS | 11:d3aa5fca2330 | 157 | void toPhoneChk( void ) |
| AntonLS | 0:28ca4562fe1a | 158 | { |
| AntonLS | 9:95dc84e9fb7f | 159 | // if( 0 != rts.read() ) pcfc.puts( "\r\n!RTS disengaged.\r\n" ); // When not using HWFC. |
| AntonLS | 3:388e441be8df | 160 | |
| AntonLS | 11:d3aa5fca2330 | 161 | if( phoneP != NULL ) |
| AntonLS | 0:28ca4562fe1a | 162 | { |
| AntonLS | 11:d3aa5fca2330 | 163 | char ch; |
| AntonLS | 11:d3aa5fca2330 | 164 | // Get any data from serial port buffer--Full lines if avail--Last line after >= 20 chars. |
| AntonLS | 11:d3aa5fca2330 | 165 | for( int cnt=1; 0 != pcfc.atomicRead( ch ); cnt++ ) |
| AntonLS | 0:28ca4562fe1a | 166 | { |
| AntonLS | 11:d3aa5fca2330 | 167 | if( 0 > phoneP->putchar( ch ) ) |
| AntonLS | 11:d3aa5fca2330 | 168 | { |
| AntonLS | 11:d3aa5fca2330 | 169 | pcfc.printf( " * " ); |
| AntonLS | 11:d3aa5fca2330 | 170 | break; |
| AntonLS | 11:d3aa5fca2330 | 171 | } |
| AntonLS | 11:d3aa5fca2330 | 172 | if( (cnt >= 20) && ('\n' == ch) ) break; |
| AntonLS | 5:1b9734e68327 | 173 | } |
| AntonLS | 11:d3aa5fca2330 | 174 | // Write to outgoing characteristic if anything is pending. |
| AntonLS | 11:d3aa5fca2330 | 175 | if( 0 != phoneP->maybeHandleWrite() ) |
| AntonLS | 5:1b9734e68327 | 176 | { |
| AntonLS | 11:d3aa5fca2330 | 177 | // pcfc.printf( "ToPhoneHandler \r\n" ); |
| AntonLS | 0:28ca4562fe1a | 178 | } |
| AntonLS | 0:28ca4562fe1a | 179 | } |
| AntonLS | 0:28ca4562fe1a | 180 | } |
| AntonLS | 0:28ca4562fe1a | 181 | |
| AntonLS | 0:28ca4562fe1a | 182 | int main( void ) |
| AntonLS | 0:28ca4562fe1a | 183 | { |
| AntonLS | 11:d3aa5fca2330 | 184 | led1 = 1; |
| AntonLS | 0:28ca4562fe1a | 185 | Ticker ticker; |
| AntonLS | 0:28ca4562fe1a | 186 | ticker.attach( periodicCallback, 1 ); |
| AntonLS | 0:28ca4562fe1a | 187 | |
| AntonLS | 0:28ca4562fe1a | 188 | |
| AntonLS | 0:28ca4562fe1a | 189 | pcfc.baud( 57600 ); |
| AntonLS | 0:28ca4562fe1a | 190 | |
| AntonLS | 0:28ca4562fe1a | 191 | DEBUG( "Initialising the nRF51822\n\r" ); |
| AntonLS | 1:0ba687d4196f | 192 | |
| AntonLS | 2:fe1566cdb6e7 | 193 | |
| AntonLS | 0:28ca4562fe1a | 194 | ble.init(); |
| AntonLS | 11:d3aa5fca2330 | 195 | ble.onConnection( connectionCallback ); |
| AntonLS | 0:28ca4562fe1a | 196 | ble.onDisconnection( disconnectionCallback ); |
| AntonLS | 0:28ca4562fe1a | 197 | ble.onDataWritten( onDataWritten ); |
| AntonLS | 0:28ca4562fe1a | 198 | ble.onDataSent( onDataSent ); |
| AntonLS | 0:28ca4562fe1a | 199 | |
| AntonLS | 0:28ca4562fe1a | 200 | /* setup advertising */ |
| AntonLS | 0:28ca4562fe1a | 201 | ble.accumulateAdvertisingPayload( GapAdvertisingData::BREDR_NOT_SUPPORTED ); |
| AntonLS | 0:28ca4562fe1a | 202 | ble.setAdvertisingType( GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED ); |
| AntonLS | 5:1b9734e68327 | 203 | |
| AntonLS | 5:1b9734e68327 | 204 | // Get MAC addr so we can create a device name using it. |
| AntonLS | 5:1b9734e68327 | 205 | ble.getAddress( pAdType, macAddr ); |
| AntonLS | 5:1b9734e68327 | 206 | sprintf( deviceName, "T%02X%02X", macAddr[1], macAddr[0] ); |
| AntonLS | 5:1b9734e68327 | 207 | |
| AntonLS | 5:1b9734e68327 | 208 | pcfc.printf( "\r\nNano nano! I am \"%s\"\r\n", deviceName ); |
| AntonLS | 11:d3aa5fca2330 | 209 | #if LOOPBACK_MODE |
| AntonLS | 5:1b9734e68327 | 210 | pcfc.printf( "\r\nIn BLE Loopback mode.\r\n" ); |
| AntonLS | 5:1b9734e68327 | 211 | #endif |
| AntonLS | 5:1b9734e68327 | 212 | |
| AntonLS | 0:28ca4562fe1a | 213 | ble.accumulateAdvertisingPayload( GapAdvertisingData::COMPLETE_LOCAL_NAME, |
| AntonLS | 0:28ca4562fe1a | 214 | (const uint8_t *)deviceName, strlen(deviceName) ); |
| AntonLS | 0:28ca4562fe1a | 215 | ble.accumulateAdvertisingPayload( GapAdvertisingData::INCOMPLETE_LIST_128BIT_SERVICE_IDS, |
| AntonLS | 0:28ca4562fe1a | 216 | (const uint8_t *)UARTServiceUUID_reversed, sizeof(UARTServiceUUID_reversed) ); |
| AntonLS | 0:28ca4562fe1a | 217 | |
| AntonLS | 0:28ca4562fe1a | 218 | ble.accumulateScanResponse( GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, |
| AntonLS | 0:28ca4562fe1a | 219 | (const uint8_t *)DevInfoServiceUUID_rev, sizeof(DevInfoServiceUUID_rev) ); |
| AntonLS | 0:28ca4562fe1a | 220 | |
| AntonLS | 11:d3aa5fca2330 | 221 | ble.setAdvertisingInterval( Gap::MSEC_TO_ADVERTISEMENT_DURATION_UNITS( 200 ) ); |
| AntonLS | 0:28ca4562fe1a | 222 | ble.startAdvertising(); |
| AntonLS | 0:28ca4562fe1a | 223 | |
| AntonLS | 0:28ca4562fe1a | 224 | DeviceInformationService deviceInfo( ble, "TRX", "TrueAgility", "SN0001", "hw-rev1", "fw-rev1" ); |
| AntonLS | 0:28ca4562fe1a | 225 | |
| AntonLS | 0:28ca4562fe1a | 226 | /* Enable over-the-air firmware updates. Instantiating DFUSservice introduces a |
| AntonLS | 0:28ca4562fe1a | 227 | * control characteristic which can be used to trigger the application to |
| AntonLS | 0:28ca4562fe1a | 228 | * handover control to a resident bootloader. */ |
| AntonLS | 0:28ca4562fe1a | 229 | DFUService dfu( ble ); |
| AntonLS | 0:28ca4562fe1a | 230 | |
| AntonLS | 0:28ca4562fe1a | 231 | UARTService uartService( ble ); |
| AntonLS | 0:28ca4562fe1a | 232 | uartServicePtr = &uartService; |
| AntonLS | 0:28ca4562fe1a | 233 | |
| AntonLS | 11:d3aa5fca2330 | 234 | PhoneAppIO phone( ble, uartService.getRXCharacteristicHandle(), |
| AntonLS | 11:d3aa5fca2330 | 235 | uartService.getTXCharacteristicHandle() ); |
| AntonLS | 11:d3aa5fca2330 | 236 | phone.loopbackMode = LOOPBACK_MODE; |
| AntonLS | 11:d3aa5fca2330 | 237 | phoneP = ☎ |
| AntonLS | 11:d3aa5fca2330 | 238 | |
| AntonLS | 11:d3aa5fca2330 | 239 | Timer tmr; |
| AntonLS | 11:d3aa5fca2330 | 240 | tmr.start(); |
| AntonLS | 11:d3aa5fca2330 | 241 | |
| AntonLS | 11:d3aa5fca2330 | 242 | // Main Loop |
| AntonLS | 11:d3aa5fca2330 | 243 | for( uint32_t loop=1; ;loop++ ) |
| AntonLS | 0:28ca4562fe1a | 244 | { |
| AntonLS | 0:28ca4562fe1a | 245 | ble.waitForEvent(); |
| AntonLS | 0:28ca4562fe1a | 246 | |
| AntonLS | 11:d3aa5fca2330 | 247 | toPhoneChk(); // Write any pending data to phone. |
| AntonLS | 11:d3aa5fca2330 | 248 | |
| AntonLS | 11:d3aa5fca2330 | 249 | while( 0 <= phone.getchar() ); // Eat input. |
| AntonLS | 11:d3aa5fca2330 | 250 | |
| AntonLS | 11:d3aa5fca2330 | 251 | // if( !(loop % 50) ) phone.printf( "Post: %d\r\n", tmr.read_ms() ); |
| AntonLS | 0:28ca4562fe1a | 252 | } |
| AntonLS | 0:28ca4562fe1a | 253 | } |
| AntonLS | 0:28ca4562fe1a | 254 | |
| AntonLS | 0:28ca4562fe1a | 255 | /* EOF */ |
