From ffdd6d2f005e614a37359a21a2e5e5d24a1b14c6 Mon Sep 17 00:00:00 2001 From: Kiveisha Yevgeniy Date: Wed, 13 Aug 2014 11:49:33 +0000 Subject: [PATCH] nrf8001: added helloworld example (communicating with nrf UART application Signed-off-by: Kiveisha Yevgeniy --- examples/CMakeLists.txt | 2 + examples/nrf8001_helloworld.cxx | 362 ++++++++++++++++++++++++++++++++++++++++ examples/nrf8001_helloworld.h | 254 ++++++++++++++++++++++++++++ 3 files changed, 618 insertions(+) create mode 100644 examples/nrf8001_helloworld.cxx create mode 100644 examples/nrf8001_helloworld.h diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 6c0b6fe..4a57948 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -25,6 +25,7 @@ add_executable (maxds3231m-example maxds3231m.cxx) add_executable (max31723-example max31723.cxx) add_executable (max5487-example max5487.cxx) add_executable (nrf8001-broadcast-example nrf8001_broadcast.cxx) +add_executable (nrf8001-helloworld-example nrf8001_helloworld.cxx) include_directories (${PROJECT_SOURCE_DIR}/src/hmc5883l) include_directories (${PROJECT_SOURCE_DIR}/src/grove) @@ -76,3 +77,4 @@ target_link_libraries (maxds3231m-example maxds3231m ${CMAKE_THREAD_LIBS_INIT}) target_link_libraries (max31723-example max31723 ${CMAKE_THREAD_LIBS_INIT}) target_link_libraries (max5487-example max5487 ${CMAKE_THREAD_LIBS_INIT}) target_link_libraries (nrf8001-broadcast-example nrf8001 ${CMAKE_THREAD_LIBS_INIT}) +target_link_libraries (nrf8001-helloworld-example nrf8001 ${CMAKE_THREAD_LIBS_INIT}) diff --git a/examples/nrf8001_helloworld.cxx b/examples/nrf8001_helloworld.cxx new file mode 100644 index 0000000..e650415 --- /dev/null +++ b/examples/nrf8001_helloworld.cxx @@ -0,0 +1,362 @@ +/* + * Author: Yevgeniy Kiveisha + * Copyright (c) 2014 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include "nrf8001.h" +#include "nrf8001_helloworld.h" +#include +#include +#include +#include "uart_over_ble.h" + +/* + * You can use the nRF UART app in the Apple iOS app store and Google Play for Android 4.3 for Samsung Galaxy S4 +* with this helloworld application + */ + +#ifdef SERVICES_PIPE_TYPE_MAPPING_CONTENT + static services_pipe_type_mapping_t + services_pipe_type_mapping[NUMBER_OF_PIPES] = SERVICES_PIPE_TYPE_MAPPING_CONTENT; +#else + #define NUMBER_OF_PIPES 0 + static services_pipe_type_mapping_t * services_pipe_type_mapping = NULL; +#endif + +/** + * Store the setup for the nRF8001 in the flash of the AVR to save on RAM + */ +static hal_aci_data_t setup_msgs[NB_SETUP_MESSAGES] = SETUP_MESSAGES_CONTENT; + +/** + * aci_struct that will contain + * total initial credits + * current credit + * current state of the aci (setup/standby/active/sleep) + * open remote pipe pending + * close remote pipe pending + * Current pipe available bitmap + * Current pipe closed bitmap + * Current connection interval, slave latency and link supervision timeout + * Current State of the the GATT client (Service Discovery) + * Status of the bond (R) Peer address + */ +static struct aci_state_t aci_state; + +/** + * Temporary buffers for sending ACI commands + */ +static hal_aci_evt_t aci_data; + +/* +Timing change state variable +*/ +static bool timing_change_done = false; + +/* +Used to test the UART TX characteristic notification +*/ +static uart_over_ble_t uart_over_ble; +static uint8_t uart_buffer[20]; +static uint8_t uart_buffer_len = 0; +static uint8_t dummychar = 0; + +void +sig_handler(int signo) +{ + printf("got signal\n"); + if (signo == SIGINT) { + printf("exiting application\n"); + } +} + +void +init_aci_setup () { + /** + * Point ACI data structures to the the setup data that the nRFgo studio generated for the nRF8001 + */ + if (NULL != services_pipe_type_mapping) { + aci_state.aci_setup_info.services_pipe_type_mapping = &services_pipe_type_mapping[0]; + } else { + aci_state.aci_setup_info.services_pipe_type_mapping = NULL; + } + + aci_state.aci_setup_info.number_of_pipes = NUMBER_OF_PIPES; + aci_state.aci_setup_info.setup_msgs = setup_msgs; + aci_state.aci_setup_info.num_setup_msgs = NB_SETUP_MESSAGES; +} + +void +uart_over_ble_init (void) { + uart_over_ble.uart_rts_local = true; +} + +bool +uart_tx (uint8_t *buffer, uint8_t buffer_len) { + bool status = false; + + if (lib_aci_is_pipe_available(&aci_state, PIPE_UART_OVER_BTLE_UART_TX_TX) && + (aci_state.data_credit_available >= 1)) { + status = lib_aci_send_data(PIPE_UART_OVER_BTLE_UART_TX_TX, buffer, buffer_len); + if (status) { + aci_state.data_credit_available--; + } + } + + return status; +} + +bool +uart_process_control_point_rx(uint8_t *byte, uint8_t length) { + bool status = false; + aci_ll_conn_params_t *conn_params; + + if (lib_aci_is_pipe_available(&aci_state, PIPE_UART_OVER_BTLE_UART_CONTROL_POINT_TX) ) { + switch (*byte) { + /* + Queues a ACI Disconnect to the nRF8001 when this packet is received. + May cause some of the UART packets being sent to be dropped + */ + case UART_OVER_BLE_DISCONNECT: + /* + Parameters: + None + */ + lib_aci_disconnect(&aci_state, ACI_REASON_TERMINATE); + status = true; + break; + + /* + Queues an ACI Change Timing to the nRF8001 + */ + case UART_OVER_BLE_LINK_TIMING_REQ: + /* + Parameters: + Connection interval min: 2 bytes + Connection interval max: 2 bytes + Slave latency: 2 bytes + Timeout: 2 bytes + Same format as Peripheral Preferred Connection Parameters (See nRFgo studio -> nRF8001 Configuration -> GAP Settings + Refer to the ACI Change Timing Request in the nRF8001 Product Specifications + */ + conn_params = (aci_ll_conn_params_t *)(byte+1); + lib_aci_change_timing( conn_params->min_conn_interval, + conn_params->max_conn_interval, + conn_params->slave_latency, + conn_params->timeout_mult); + status = true; + break; + + /* + Clears the RTS of the UART over BLE + */ + case UART_OVER_BLE_TRANSMIT_STOP: + /* + Parameters: + None + */ + uart_over_ble.uart_rts_local = false; + status = true; + break; + + + /* + Set the RTS of the UART over BLE + */ + case UART_OVER_BLE_TRANSMIT_OK: + /* + Parameters: + None + */ + uart_over_ble.uart_rts_local = true; + status = true; + break; + } + } + + return status; +} + +int +main(int argc, char **argv) +{ + //! [Interesting] + + init_aci_setup (); + init_local_interfaces (&aci_state, 10, 8, 4); + + while (1) { + static bool setup_required = false; + + // We enter the if statement only when there is a ACI event available to be processed + if (lib_aci_event_get(&aci_state, &aci_data)) { + aci_evt_t * aci_evt; + aci_evt = &aci_data.evt; + switch(aci_evt->evt_opcode) { + /** + As soon as you reset the nRF8001 you will get an ACI Device Started Event + */ + case ACI_EVT_DEVICE_STARTED: { + aci_state.data_credit_total = aci_evt->params.device_started.credit_available; + switch(aci_evt->params.device_started.device_mode) { + case ACI_DEVICE_SETUP: + /** + When the device is in the setup mode + */ + printf ("Evt Device Started: Setup \n"); + setup_required = true; + break; + + case ACI_DEVICE_STANDBY: + printf ("Evt Device Started: Standby \n"); + // Looking for an iPhone by sending radio advertisements + // When an iPhone connects to us we will get an ACI_EVT_CONNECTED event from the nRF8001 + if (aci_evt->params.device_started.hw_error) { + usleep (20000); //Handle the HW error event correctly. + } else { + lib_aci_connect(0/* in seconds : 0 means forever */, 0x0050 /* advertising interval 50ms*/); + printf ("Advertising started \n"); + } + break; + } + } + break; // ACI Device Started Event + + case ACI_EVT_CMD_RSP: + //If an ACI command response event comes with an error -> stop + if (ACI_STATUS_SUCCESS != aci_evt->params.cmd_rsp.cmd_status) { + //ACI ReadDynamicData and ACI WriteDynamicData will have status codes of + //TRANSACTION_CONTINUE and TRANSACTION_COMPLETE + //all other ACI commands will have status code of ACI_STATUS_SCUCCESS for a successful command + printf ("ACI_EVT_CMD_RSP \n"); + } + if (ACI_CMD_GET_DEVICE_VERSION == aci_evt->params.cmd_rsp.cmd_opcode) { + //Store the version and configuration information of the nRF8001 in the Hardware Revision String Characteristic + lib_aci_set_local_data(&aci_state, PIPE_DEVICE_INFORMATION_HARDWARE_REVISION_STRING_SET, + (uint8_t *)&(aci_evt->params.cmd_rsp.params.get_device_version), sizeof(aci_evt_cmd_rsp_params_get_device_version_t)); + } + break; + + case ACI_EVT_CONNECTED: + printf ("ACI_EVT_CONNECTED"); + uart_over_ble_init (); + timing_change_done = false; + aci_state.data_credit_available = aci_state.data_credit_total; + + /* + Get the device version of the nRF8001 and store it in the Hardware Revision String + */ + lib_aci_device_version(); + break; + + case ACI_EVT_PIPE_STATUS: + printf ("ACI_EVT_PIPE_STATUS \n"); + if (lib_aci_is_pipe_available(&aci_state, PIPE_UART_OVER_BTLE_UART_TX_TX) && (false == timing_change_done)) { + lib_aci_change_timing_GAP_PPCP(); // change the timing on the link as specified in the nRFgo studio -> nRF8001 conf. -> GAP. + // Used to increase or decrease bandwidth + timing_change_done = true; + + char hello[]="Hello World, works"; + uart_tx((uint8_t *)&hello[0], strlen(hello)); + } + break; + + case ACI_EVT_TIMING: + printf ("Evt link connection interval changed \n"); + lib_aci_set_local_data(&aci_state, + PIPE_UART_OVER_BTLE_UART_LINK_TIMING_CURRENT_SET, + (uint8_t *)&(aci_evt->params.timing.conn_rf_interval), /* Byte aligned */ + PIPE_UART_OVER_BTLE_UART_LINK_TIMING_CURRENT_SET_MAX_SIZE); + break; + + case ACI_EVT_DISCONNECTED: + printf ("ACI_EVT_DISCONNECTED \n"); + lib_aci_connect(0/* in seconds : 0 means forever */, 0x0050 /* advertising interval 50ms*/); + printf ("Advertising started \n"); + break; + + case ACI_EVT_DATA_RECEIVED: + if (PIPE_UART_OVER_BTLE_UART_RX_RX == aci_evt->params.data_received.rx_data.pipe_number) { + for(int i=0; ilen - 2; i++) { + uart_buffer[i] = aci_evt->params.data_received.rx_data.aci_data[i]; + } + + uart_buffer_len = aci_evt->len - 2; + if (lib_aci_is_pipe_available(&aci_state, PIPE_UART_OVER_BTLE_UART_TX_TX)) { + } + } + + if (PIPE_UART_OVER_BTLE_UART_CONTROL_POINT_RX == aci_evt->params.data_received.rx_data.pipe_number) { + //Subtract for Opcode and Pipe number + uart_process_control_point_rx(&aci_evt->params.data_received.rx_data.aci_data[0], aci_evt->len - 2); + } + + printf ("Incomming data - %s\n", uart_buffer); + break; + + case ACI_EVT_DATA_CREDIT: + printf ("ACI_EVT_DATA_CREDIT \n"); + aci_state.data_credit_available = aci_state.data_credit_available + aci_evt->params.data_credit.credit; + break; + + case ACI_EVT_PIPE_ERROR: + printf ("ACI_EVT_PIPE_ERROR \n"); + //Increment the credit available as the data packet was not sent. + //The pipe error also represents the Attribute protocol Error Response sent from the peer and that should not be counted + //for the credit. + if (ACI_STATUS_ERROR_PEER_ATT_ERROR != aci_evt->params.pipe_error.error_code) { + aci_state.data_credit_available++; + } + break; + + case ACI_EVT_HW_ERROR: + printf ("ACI_EVT_HW_ERROR \n"); + lib_aci_connect(0/* in seconds, 0 means forever */, 0x0050 /* advertising interval 50ms*/); + printf ("Advertising started \n"); + break; + + } + } + + /* setup_required is set to true when the device starts up and enters setup mode. + * It indicates that do_aci_setup() should be called. The flag should be cleared if + * do_aci_setup() returns ACI_STATUS_TRANSACTION_COMPLETE. + */ + if(setup_required) { + if (SETUP_SUCCESS == do_aci_setup(&aci_state)) { + setup_required = false; + } + } + + usleep (100); + } + + close_local_interfaces (&aci_state); + + //! [Interesting] + + std::cout << "exiting application" << std::endl; + + return 0; +} diff --git a/examples/nrf8001_helloworld.h b/examples/nrf8001_helloworld.h new file mode 100644 index 0000000..ec566b5 --- /dev/null +++ b/examples/nrf8001_helloworld.h @@ -0,0 +1,254 @@ +#include "hal_platform.h" +#include "aci.h" + +#pragma once + +#define SETUP_ID 0 +#define SETUP_FORMAT 2 /** nRF8001 Cx */ +#define ACI_DYNAMIC_DATA_SIZE 263 + +/* Service: GATT - Characteristic: Service Changed - Pipe: TX_ACK */ +#define PIPE_GATT_SERVICE_CHANGED_TX_ACK 1 +#define PIPE_GATT_SERVICE_CHANGED_TX_ACK_MAX_SIZE 4 + +/* Service: Device Information - Characteristic: Hardware Revision String - Pipe: SET */ +#define PIPE_DEVICE_INFORMATION_HARDWARE_REVISION_STRING_SET 2 +#define PIPE_DEVICE_INFORMATION_HARDWARE_REVISION_STRING_SET_MAX_SIZE 9 + +/* Service: Device Information - Characteristic: Manufacturer Name String - Pipe: SET */ +#define PIPE_DEVICE_INFORMATION_MANUFACTURER_NAME_STRING_SET 3 +#define PIPE_DEVICE_INFORMATION_MANUFACTURER_NAME_STRING_SET_MAX_SIZE 20 + +/* Service: Device Information - Characteristic: Model Number String - Pipe: SET */ +#define PIPE_DEVICE_INFORMATION_MODEL_NUMBER_STRING_SET 4 +#define PIPE_DEVICE_INFORMATION_MODEL_NUMBER_STRING_SET_MAX_SIZE 8 + +/* Service: Device Information - Characteristic: Firmware Revision String - Pipe: SET */ +#define PIPE_DEVICE_INFORMATION_FIRMWARE_REVISION_STRING_SET 5 +#define PIPE_DEVICE_INFORMATION_FIRMWARE_REVISION_STRING_SET_MAX_SIZE 4 + +/* Service: Device Information - Characteristic: PNP_ID - Pipe: SET */ +#define PIPE_DEVICE_INFORMATION_PNP_ID_SET 6 +#define PIPE_DEVICE_INFORMATION_PNP_ID_SET_MAX_SIZE 7 + +/* Service: UART over BTLE - Characteristic: UART RX - Pipe: RX */ +#define PIPE_UART_OVER_BTLE_UART_RX_RX 7 +#define PIPE_UART_OVER_BTLE_UART_RX_RX_MAX_SIZE 20 + +/* Service: UART over BTLE - Characteristic: UART TX - Pipe: TX */ +#define PIPE_UART_OVER_BTLE_UART_TX_TX 8 +#define PIPE_UART_OVER_BTLE_UART_TX_TX_MAX_SIZE 20 + +/* Service: UART over BTLE - Characteristic: UART Control Point - Pipe: TX */ +#define PIPE_UART_OVER_BTLE_UART_CONTROL_POINT_TX 9 +#define PIPE_UART_OVER_BTLE_UART_CONTROL_POINT_TX_MAX_SIZE 9 + +/* Service: UART over BTLE - Characteristic: UART Control Point - Pipe: RX */ +#define PIPE_UART_OVER_BTLE_UART_CONTROL_POINT_RX 10 +#define PIPE_UART_OVER_BTLE_UART_CONTROL_POINT_RX_MAX_SIZE 9 + +/* Service: UART over BTLE - Characteristic: UART Link Timing Current - Pipe: SET */ +#define PIPE_UART_OVER_BTLE_UART_LINK_TIMING_CURRENT_SET 11 +#define PIPE_UART_OVER_BTLE_UART_LINK_TIMING_CURRENT_SET_MAX_SIZE 6 + + +#define NUMBER_OF_PIPES 11 + +#define SERVICES_PIPE_TYPE_MAPPING_CONTENT {\ + {ACI_STORE_LOCAL, ACI_TX_ACK}, \ + {ACI_STORE_LOCAL, ACI_SET}, \ + {ACI_STORE_LOCAL, ACI_SET}, \ + {ACI_STORE_LOCAL, ACI_SET}, \ + {ACI_STORE_LOCAL, ACI_SET}, \ + {ACI_STORE_LOCAL, ACI_SET}, \ + {ACI_STORE_LOCAL, ACI_RX}, \ + {ACI_STORE_LOCAL, ACI_TX}, \ + {ACI_STORE_LOCAL, ACI_TX}, \ + {ACI_STORE_LOCAL, ACI_RX}, \ + {ACI_STORE_LOCAL, ACI_SET}, \ +} + +#define GAP_PPCP_MAX_CONN_INT 0x12 /**< Maximum connection interval as a multiple of 1.25 msec , 0xFFFF means no specific value requested */ +#define GAP_PPCP_MIN_CONN_INT 0xa /**< Minimum connection interval as a multiple of 1.25 msec , 0xFFFF means no specific value requested */ +#define GAP_PPCP_SLAVE_LATENCY 0 +#define GAP_PPCP_CONN_TIMEOUT 0xa /** Connection Supervision timeout multiplier as a multiple of 10msec, 0xFFFF means no specific value requested */ + +#define NB_SETUP_MESSAGES 30 +#define SETUP_MESSAGES_CONTENT {\ + {0x00,\ + {\ + 0x07,0x06,0x00,0x00,0x02,0x02,0x41,0xfe,\ + },\ + },\ + {0x00,\ + {\ + 0x1f,0x06,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x00,0x0b,0x01,0x01,0x00,0x00,0x06,0x00,0x00,\ + 0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ + },\ + },\ + {0x00,\ + {\ + 0x1e,0x06,0x10,0x1c,0x01,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ + 0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x14,0x03,0x90,0x01,\ + },\ + },\ + {0x00,\ + {\ + 0x1f,0x06,0x20,0x00,0x04,0x04,0x02,0x02,0x00,0x01,0x28,0x00,0x01,0x00,0x18,0x04,0x04,0x05,0x05,0x00,\ + 0x02,0x28,0x03,0x01,0x02,0x03,0x00,0x00,0x2a,0x04,0x04,0x14,\ + },\ + },\ + {0x00,\ + {\ + 0x1f,0x06,0x20,0x1c,0x05,0x00,0x03,0x2a,0x00,0x01,0x48,0x65,0x6c,0x6c,0x6f,0x63,0x73,0x65,0x6d,0x69,\ + 0x2e,0x63,0x6f,0x6d,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x04,\ + },\ + },\ + {0x00,\ + {\ + 0x1f,0x06,0x20,0x38,0x05,0x05,0x00,0x04,0x28,0x03,0x01,0x02,0x05,0x00,0x01,0x2a,0x06,0x04,0x03,0x02,\ + 0x00,0x05,0x2a,0x01,0x01,0x80,0x00,0x04,0x04,0x05,0x05,0x00,\ + },\ + },\ + {0x00,\ + {\ + 0x1f,0x06,0x20,0x54,0x06,0x28,0x03,0x01,0x02,0x07,0x00,0x04,0x2a,0x06,0x04,0x09,0x08,0x00,0x07,0x2a,\ + 0x04,0x01,0x0a,0x00,0x12,0x00,0x00,0x00,0x0a,0x00,0x04,0x04,\ + },\ + },\ + {0x00,\ + {\ + 0x1f,0x06,0x20,0x70,0x02,0x02,0x00,0x08,0x28,0x00,0x01,0x01,0x18,0x04,0x04,0x05,0x05,0x00,0x09,0x28,\ + 0x03,0x01,0x22,0x0a,0x00,0x05,0x2a,0x26,0x04,0x05,0x04,0x00,\ + },\ + },\ + {0x00,\ + {\ + 0x1f,0x06,0x20,0x8c,0x0a,0x2a,0x05,0x01,0x00,0x00,0x00,0x00,0x46,0x14,0x03,0x02,0x00,0x0b,0x29,0x02,\ + 0x01,0x00,0x00,0x04,0x04,0x02,0x02,0x00,0x0c,0x28,0x00,0x01,\ + },\ + },\ + {0x00,\ + {\ + 0x1f,0x06,0x20,0xa8,0x0a,0x18,0x04,0x04,0x05,0x05,0x00,0x0d,0x28,0x03,0x01,0x02,0x0e,0x00,0x27,0x2a,\ + 0x04,0x04,0x09,0x01,0x00,0x0e,0x2a,0x27,0x01,0x0a,0x00,0x00,\ + },\ + },\ + {0x00,\ + {\ + 0x1f,0x06,0x20,0xc4,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x04,0x05,0x05,0x00,0x0f,0x28,0x03,0x01,0x02,\ + 0x10,0x00,0x29,0x2a,0x04,0x04,0x14,0x02,0x00,0x10,0x2a,0x29,\ + },\ + },\ + {0x00,\ + {\ + 0x1f,0x06,0x20,0xe0,0x01,0x30,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ + 0x00,0x00,0x00,0x00,0x00,0x04,0x04,0x05,0x05,0x00,0x11,0x28,\ + },\ + },\ + {0x00,\ + {\ + 0x1f,0x06,0x20,0xfc,0x03,0x01,0x02,0x12,0x00,0x24,0x2a,0x04,0x04,0x08,0x02,0x00,0x12,0x2a,0x24,0x01,\ + 0x31,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x04,0x05,0x05,\ + },\ + },\ + {0x00,\ + {\ + 0x1f,0x06,0x21,0x18,0x00,0x13,0x28,0x03,0x01,0x02,0x14,0x00,0x26,0x2a,0x04,0x04,0x04,0x02,0x00,0x14,\ + 0x2a,0x26,0x01,0x33,0x34,0x00,0x00,0x04,0x04,0x05,0x05,0x00,\ + },\ + },\ + {0x00,\ + {\ + 0x1f,0x06,0x21,0x34,0x15,0x28,0x03,0x01,0x02,0x16,0x00,0x50,0x2a,0x06,0x04,0x08,0x07,0x00,0x16,0x2a,\ + 0x50,0x01,0x02,0x00,0x00,0xaa,0xaa,0xcc,0xcc,0x04,0x04,0x10,\ + },\ + },\ + {0x00,\ + {\ + 0x1f,0x06,0x21,0x50,0x10,0x00,0x17,0x28,0x00,0x01,0x9e,0xca,0xdc,0x24,0x0e,0xe5,0xa9,0xe0,0x93,0xf3,\ + 0xa3,0xb5,0x01,0x00,0x40,0x6e,0x04,0x04,0x13,0x13,0x00,0x18,\ + },\ + },\ + {0x00,\ + {\ + 0x1f,0x06,0x21,0x6c,0x28,0x03,0x01,0x04,0x19,0x00,0x9e,0xca,0xdc,0x24,0x0e,0xe5,0xa9,0xe0,0x93,0xf3,\ + 0xa3,0xb5,0x02,0x00,0x40,0x6e,0x44,0x10,0x14,0x00,0x00,0x19,\ + },\ + },\ + {0x00,\ + {\ + 0x1f,0x06,0x21,0x88,0x00,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x04,0x13,0x13,0x00,\ + },\ + },\ + {0x00,\ + {\ + 0x1f,0x06,0x21,0xa4,0x1a,0x28,0x03,0x01,0x10,0x1b,0x00,0x9e,0xca,0xdc,0x24,0x0e,0xe5,0xa9,0xe0,0x93,\ + 0xf3,0xa3,0xb5,0x03,0x00,0x40,0x6e,0x14,0x00,0x14,0x00,0x00,\ + },\ + },\ + {0x00,\ + {\ + 0x1f,0x06,0x21,0xc0,0x1b,0x00,0x03,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x14,0x03,0x02,\ + },\ + },\ + {0x00,\ + {\ + 0x1f,0x06,0x21,0xdc,0x00,0x1c,0x29,0x02,0x01,0x00,0x00,0x04,0x04,0x13,0x13,0x00,0x1d,0x28,0x03,0x01,\ + 0x14,0x1e,0x00,0x9e,0xca,0xdc,0x24,0x0e,0xe5,0xa9,0xe0,0x93,\ + },\ + },\ + {0x00,\ + {\ + 0x1f,0x06,0x21,0xf8,0xf3,0xa3,0xb5,0x04,0x00,0x40,0x6e,0x54,0x10,0x09,0x00,0x00,0x1e,0x00,0x04,0x02,\ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x14,0x03,\ + },\ + },\ + {0x00,\ + {\ + 0x1f,0x06,0x22,0x14,0x02,0x00,0x1f,0x29,0x02,0x01,0x00,0x00,0x04,0x04,0x13,0x13,0x00,0x20,0x28,0x03,\ + 0x01,0x02,0x21,0x00,0x9e,0xca,0xdc,0x24,0x0e,0xe5,0xa9,0xe0,\ + },\ + },\ + {0x00,\ + {\ + 0x1b,0x06,0x22,0x30,0x93,0xf3,0xa3,0xb5,0x05,0x00,0x40,0x6e,0x06,0x04,0x07,0x06,0x00,0x21,0x00,0x05,\ + 0x02,0xff,0xff,0xff,0xff,0xff,0xff,0x00,\ + },\ + },\ + {0x00,\ + {\ + 0x1f,0x06,0x40,0x00,0x2a,0x05,0x01,0x00,0x04,0x04,0x00,0x0a,0x00,0x0b,0x2a,0x27,0x01,0x00,0x80,0x04,\ + 0x00,0x0e,0x00,0x00,0x2a,0x29,0x01,0x00,0x80,0x04,0x00,0x10,\ + },\ + },\ + {0x00,\ + {\ + 0x1f,0x06,0x40,0x1c,0x00,0x00,0x2a,0x24,0x01,0x00,0x80,0x04,0x00,0x12,0x00,0x00,0x2a,0x26,0x01,0x00,\ + 0x80,0x04,0x00,0x14,0x00,0x00,0x2a,0x50,0x01,0x00,0x80,0x04,\ + },\ + },\ + {0x00,\ + {\ + 0x1f,0x06,0x40,0x38,0x00,0x16,0x00,0x00,0x00,0x02,0x02,0x00,0x08,0x04,0x00,0x19,0x00,0x00,0x00,0x03,\ + 0x02,0x00,0x02,0x04,0x00,0x1b,0x00,0x1c,0x00,0x04,0x02,0x00,\ + },\ + },\ + {0x00,\ + {\ + 0x13,0x06,0x40,0x54,0x0a,0x04,0x00,0x1e,0x00,0x1f,0x00,0x05,0x02,0x00,0x80,0x04,0x00,0x21,0x00,0x00,\ + },\ + },\ + {0x00,\ + {\ + 0x13,0x06,0x50,0x00,0x9e,0xca,0xdc,0x24,0x0e,0xe5,0xa9,0xe0,0x93,0xf3,0xa3,0xb5,0x00,0x00,0x40,0x6e,\ + },\ + },\ + {0x00,\ + {\ + 0x06,0x06,0xf0,0x00,0x02,0xb2,0xd1,\ + },\ + },\ +} -- 2.7.4