11 Replies Latest reply on Nov 25, 2015 10:17 AM by VictorZ_46

    Receiving notification without content and without sendNotification

      Hello everybody,

       

      I'm working on SDK 2.2.1 and with the BCM20736S BLE module.

      It's working as a BLE/PUART-bridge connected to a host MCU.

       

      We have several custom characteristics and services, that are all found via Smart WICED Smart Explorer on Android and by our own App on iOS.

      We can receive and send on two characteristics that contain 5 bytes payload for each direction. For larger data transfer we also have four writable and four notifyable characteristics with 20 bytes each. All characteristics have the same set of properties, descriptors and permissions and only differ in size.

       

      Writing from iPhone into the four writable characteristics with 20 bytes works flawlessly and the data also appears on PUART.

      But after that the app receives the four notifyable characteristics with 20 bytes payload without any payload and without a sendNotification on the BLE module.

      Without payload means you'll get an update event issued by the iPhone bluetooth API that contains just NULL instead of an array containing the payload. We didn't find these strange notification with a BLE sniffer (Peryton BLE).

       

      Thanks for any help and suggestions!

       

      Best regards

      Hannes Baumgart

        • 1. Re: Receiving notification without content and without sendNotification

          userc_16716 can you provide us with some traces? I think that would help us understand you problem a little better. 

          • 2. Re: Receiving notification without content and without sendNotification

            Hi Kevin,

             

            I'd like to do that.

            What traces do you need?

            Traces from ble_trace(), traces from the BLE sniffer or traces from our Xamarin/Monkey,Robotics cross-platform toolkit?

             

            Is there a possibility to output timing information except the fine timer?

             

            Best regards,

            Hannes

            • 3. Re: Receiving notification without content and without sendNotification

              Hello userc_16716

              Any traces that you think will help us understand what is going on will be helpful.

              Also it would be more helpful for us if you post parts of the source code of the firmware on the BLE module.

               

              If you are using SDK 2.x, you can use another timer with resolution of 1.25mS.

              Here's a link for it: Re: FineTimer

               

              Let me know if this helps.

               

              Thanks.

               

              userc_19497

              • 4. Re: Receiving notification without content and without sendNotification

                Hello userc_19497

                 

                I was quite busy with other parts of the ongoing project, but have now found time to return to BLE.

                Hopefully meaningful traces have been collected and I have revised the code to post it online.

                 

                The traces were produced with one run of our iPhone app. But first the relevant sources:

                ble_ttl.h
                #ifndef __BLE_TTL_H__
                #define __BLE_TTL_H__
                
                #define BLE_TTL_MAX_CONNECTION                    8
                #define L2CAP_CID                                 0x0004 //Vol 3, Part G, 5.2.2
                
                #define GPIO_PIN_WP              1
                #define GPIO_SETTINGS_WP         (GPIO_OUTPUT | GPIO_INIT_LOW  | GPIO_WP)
                #define GPIO_SETTINGS_SW_2V8    (GPIO_OUTPUT | GPIO_INIT_HIGH)
                #define GPIO_SETTINGS_SW_3V7    (GPIO_OUTPUT | GPIO_INIT_HIGH)
                #define GPIO_SETTINGS_PA0_WKUP  (GPIO_OUTPUT | GPIO_INIT_LOW)
                #define GPIO_SETTINGS_EN_3V3    (GPIO_OUTPUT | GPIO_INIT_HIGH)
                #define GPIO_SETTINGS_LED_BL    (GPIO_OUTPUT | GPIO_INIT_HIGH)
                
                #endif
                
                
                
                
                
                

                 

                ble_ttl.c
                //BLE includes
                #include "bleprofile.h"
                #include "bleapp.h"
                #include "gpiodriver.h"
                #include "platform.h"
                #include "spar_utils.h"
                #include "types.h"
                
                #include "ttl_db.h"
                #include "puart.h"
                #include "ble_ttl.h"
                #include "gpio_ttl.h"
                #include "devicelpm.h"
                #include "bt_uart_protocol.h"
                
                
                /******************************************************
                *                     Constants
                ******************************************************/
                
                #define TTL_BLE_FINE_TIMER           12
                #define TTL_BLE_DEVICE_NAME          "TTL_Test"
                #define TTL_BLE_DEVICE_APPEARENCE    APPEARANCE_GENERIC_COMPUTER
                #define TTL_BLE_MAIN_SERVICE_UUID    0
                #define TTL_BLE_MAIN_CHAR_UUID       0
                #define TTL_BLE_MAIN_CHAR_HANDLE     0
                #define GPIO_PIN_UART_TX 32
                #define GPIO_PIN_UART_RX 33
                
                /******************************************************
                *                     Structures
                ******************************************************/
                
                #pragma pack(1)
                //host information for NVRAM
                typedef PACKED struct
                {
                    //part of HOSTINFO generated by wizard
                    __HOSTINFO generated;
                    // ToDo: add your variables here which need to be saved in the NVRAM
                }  HOSTINFO;
                #pragma pack()
                
                /******************************************************
                *               Function Prototypes
                ******************************************************/
                
                extern void *memcpy(void *dest, const void *src, size_t n); //get rid of implicit declaration warning
                
                static void ttl_ble_connection_up( void );
                static void ttl_ble_connection_down( void );
                static void ttl_ble_advertisement_stopped( void );
                static void ttl_ble_smp_bond_result( LESMP_PARING_RESULT result );
                static void ttl_ble_encryption_changed( HCI_EVT_HDR *evt );
                static int  ttl_ble_write_handler( LEGATTDB_ENTRY_HDR *p );
                static void ttl_ble_interrupt_handler( UINT8 value );
                
                static void   ttl_ble_create(void);
                static void   ttl_ble_puart_init(UINT8 rxPortPin, UINT8 txPortPin, UINT32 bdRate);
                static UINT32 ttl_ble_device_lpm_queriable(LowPowerModePollType type, UINT32 context);
                
                /******************************************************
                *               Variables Definitions
                ******************************************************/
                /*
                * This is the GATT database for the PUART CONTROL device.  Only mandatory
                * GAP and GATT services are present
                */
                
                const BLE_PROFILE_CFG ttl_ble_cfg =
                {
                    /*.fine_timer_interval            =*/ 12, // ms
                    /*.default_adv                    =*/ HIGH_UNDIRECTED_DISCOVERABLE,
                    /*.button_adv_toggle              =*/ 0,    // pairing button make adv toggle (if 1) or always on (if 0)
                    /*.high_undirect_adv_interval     =*/ 32,   // slots
                    /*.low_undirect_adv_interval      =*/ 2048, // slots
                    /*.high_undirect_adv_duration     =*/ 30,   // seconds
                    /*.low_undirect_adv_duration      =*/ 300,  // seconds
                    /*.high_direct_adv_interval       =*/ 1,    // seconds
                    /*.low_direct_adv_interval        =*/ 1,    // seconds
                    /*.high_direct_adv_duration       =*/ 1,    // seconds
                    /*.low_direct_adv_duration        =*/ 1,    // seconds
                    /*.local_name                     =*/ "TTL_Test", // [LOCAL_NAME_LEN_MAX];
                    /*.cod                            =*/ BIT16_TO_8(APPEARANCE_GENERIC_TAG),0x00, // [COD_LEN];
                    /*.ver                            =*/ "1.00",         // [VERSION_LEN];
                    /*.encr_required                  =*/ 0, // (SECURITY_ENABLED | SECURITY_REQUEST),    // data encrypted and device sends security request on every connection
                    /*.disc_required                  =*/ 0,    // if 1, disconnection after confirmation
                    /*.test_enable                    =*/ 0,    // TEST MODE is enabled when 1
                    /*.tx_power_level                 =*/ 4,    // dbm
                    /*.con_idle_timeout               =*/ 0,    // second  0-> no timeout
                    /*.powersave_timeout              =*/ 0,    // second  0-> no timeout
                    /*.hdl                            =*/ {0x00, 0x00, 0x00, 0x00, 0x00}, // [HANDLE_NUM_MAX];
                    /*.serv                           =*/ {0x00, 0x00, 0x00, 0x00, 0x00},
                    /*.cha                            =*/ {0x00, 0x00, 0x00, 0x00, 0x00},
                    /*.findme_locator_enable          =*/ 0,    // if 1 Find me locator is enable
                    /*.findme_alert_level             =*/ 0,    // alert level of find me
                    /*.client_grouptype_enable        =*/ 0,    // if 1 grouptype read can be used
                    /*.linkloss_button_enable         =*/ 0,    // if 1 linkloss button is enable
                    /*.pathloss_check_interval        =*/ 0,    // second
                    /*.alert_interval                 =*/ 0,    // interval of alert
                    /*.high_alert_num                 =*/ 0,    // number of alert for each interval
                    /*.mild_alert_num                 =*/ 0,    // number of alert for each interval
                    /*.status_led_enable              =*/ 0,    // if 1 status LED is enable
                    /*.status_led_interval            =*/ 0,    // second
                    /*.status_led_con_blink           =*/ 0,    // blink num of connection
                    /*.status_led_dir_adv_blink       =*/ 0,    // blink num of dir adv
                    /*.status_led_un_adv_blink        =*/ 0,    // blink num of undir adv
                    /*.led_on_ms                      =*/ 0,    // led blink on duration in ms
                    /*.led_off_ms                     =*/ 0,    // led blink off duration in ms
                    /*.buz_on_ms                      =*/ 0,    // buzzer on duration in ms
                    /*.button_power_timeout           =*/ 0,    // seconds
                    /*.button_client_timeout          =*/ 0,    // seconds
                    /*.button_discover_timeout        =*/ 0,    // seconds
                    /*.button_filter_timeout          =*/ 0,    // seconds
                };
                
                // Following structure defines GPIO configuration used by the application
                const BLE_PROFILE_GPIO_CFG ttl_ble_gpio_cfg =
                {
                    /*.gpio_pin =*/
                    {
                        GPIO_PIN_WP,
                        SW_2V8_PIN,
                        SW_3V7_PIN,
                        PA0_WKUP_PIN,
                        EN_3V3_PIN,
                        LED_BL_PIN,
                        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 // other GPIOs are not used
                    },
                    /*.gpio_flag =*/
                    {
                        GPIO_SETTINGS_WP,
                        GPIO_SETTINGS_SW_2V8,
                        GPIO_SETTINGS_SW_3V7,
                        GPIO_SETTINGS_PA0_WKUP,
                        GPIO_SETTINGS_EN_3V3,
                        GPIO_SETTINGS_LED_BL,
                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0
                    }
                };
                
                // Following structure defines UART configuration
                const BLE_PROFILE_PUART_CFG ttl_ble_puart_cfg =
                {
                    /*.baudrate   =*/ 115200,
                    /*.txpin      =*/  GPIO_PIN_UART_TX,
                    /*.rxpin      =*/  GPIO_PIN_UART_RX,
                };
                
                // this is the general header for L2CAP.
                #pragma pack(1)
                typedef PACKED struct
                {
                    UINT16 length;
                    UINT16 cid;
                } LEL2CAP_HDR;
                #pragma pack()
                
                // NVRAM save area
                HOSTINFO ttl_ble_hostinfo;
                //pointer to the generated part of hostinfo assuming it is the beginning of the hostinfo
                __HOSTINFO *p_hostinfo_generated = &ttl_ble_hostinfo.generated;
                
                UINT16     ttl_ble_connection_handle      = 0;                  // HCI handle of connection, not zero when connected
                BD_ADDR ttl_ble_remote_addr            = {0, 0, 0, 0, 0, 0}; // Address of currently connected client
                
                // Application initialization
                APPLICATION_INIT()
                {
                    bleapp_set_cfg((UINT8 *)gatt_database,
                                   gatt_database_len,
                                   (void *)&ttl_ble_cfg,
                                   (void *)&ttl_ble_puart_cfg,
                                   (void *)&ttl_ble_gpio_cfg,
                                   ttl_ble_create);
                }
                
                // Create router
                void ttl_ble_create(void)
                {
                    extern UINT8 bleprofile_adv_num;
                    extern UINT8 bleprofile_scanrsp_num;
                    ble_trace0("ttl_ble_create() enter");
                    bleprofile_adv_num = 0x0;
                    bleprofile_scanrsp_num = 0x0;
                
                    // dump the database to debug uart.
                    ble_trace0("legattdb_dumpDb():");
                    legattdb_dumpDb();
                    bleprofile_Init(bleprofile_p_cfg);
                    bleprofile_GPIOInit(bleprofile_gpio_p_cfg);
                
                    // Initialized ROM code which will monitor the battery
                    blebat_Init();
                
                    // Read NVRAM
                    bleprofile_ReadNVRAM(VS_BLE_HOST_LIST,
                            sizeof(ttl_ble_hostinfo),
                            (UINT8 *)&ttl_ble_hostinfo);
                
                    // register connection up and connection down handler.
                    bleprofile_regAppEvtHandler(BLECM_APP_EVT_LINK_UP, ttl_ble_connection_up);
                    bleprofile_regAppEvtHandler(BLECM_APP_EVT_LINK_DOWN, ttl_ble_connection_down);
                    bleprofile_regAppEvtHandler(BLECM_APP_EVT_ADV_TIMEOUT, ttl_ble_advertisement_stopped);
                
                    // handler for Encryption changed.
                    blecm_regEncryptionChangedHandler(ttl_ble_encryption_changed);
                
                    // handler for Bond result
                    lesmp_regSMPResultCb((LESMP_SINGLE_PARAM_CB) ttl_ble_smp_bond_result);
                
                    // register to process client writes
                    legattdb_regWriteHandleCb((LEGATTDB_WRITE_CB)ttl_ble_write_handler);
                
                    // register interrupt handler
                    //bleprofile_regIntCb((BLEPROFILE_SINGLE_PARAM_CB) ttl_ble_interrupt_handler);
                
                    //registers timer
                    ttl_ble_reg_timer();
                
                    // advertise first vendor specific service
                    if(sizeof(ttl_ble_uuid_main_vsc_service) == 16)
                    {
                        // total length should be less than 31 bytes
                        BLE_ADV_FIELD adv[3];
                        BLE_ADV_FIELD scr[1];
                
                        // flags
                        adv[0].len     = 1 + 1;
                        adv[0].val     = ADV_FLAGS;
                        adv[0].data[0] = LE_LIMITED_DISCOVERABLE | BR_EDR_NOT_SUPPORTED;
                
                        adv[1].len     = 16 + 1;
                        adv[1].val     = ADV_SERVICE_UUID128_COMP;
                        memcpy(adv[1].data, &ttl_ble_uuid_main_vsc_service[0], 16);
                
                        // Tx power level
                        adv[2].len     = TX_POWER_LEN+1;
                        adv[2].val     = ADV_TX_POWER_LEVEL;
                        adv[2].data[0] = bleprofile_p_cfg->tx_power_level;
                
                        // name
                        scr[0].len      = strlen(bleprofile_p_cfg->local_name) + 1;
                        scr[0].val      = ADV_LOCAL_NAME_COMP;
                        memcpy(scr[0].data, bleprofile_p_cfg->local_name, scr[0].len - 1);
                
                        bleprofile_GenerateADVData(adv, 3);
                        bleprofile_GenerateScanRspData(scr, 1);
                    }
                
                    //blecm_setTxPowerInADV(0);
                
                    // start device advertisements.  By default Advertisements will contain flags, device name,
                    // appearance and main service UUID.
                    bleprofile_Discoverable(HIGH_UNDIRECTED_DISCOVERABLE, NULL);
                
                    // ToDo: Do your initialization on app startup
                    ttl_ble_puart_init(GPIO_PIN_UART_RX, GPIO_PIN_UART_TX, 115200);
                    btup_init();
                }
                
                static void   ttl_ble_puart_init(UINT8 rxPortPin, UINT8 txPortPin, UINT32 bdRate)
                {
                    extern puart_UartConfig puart_config;
                    ble_trace1("ttl_ble_puart_init(GPIO_PIN_UART_RX, GPIO_PIN_UART_TX, %u)", bdRate);
                    // Set the baud rate we want to use. Default is 115200.
                    puart_config.baudrate = bdRate;
                
                    // Select the uart pins for RXD, TXD and optionally CTS and RTS.
                    // If hardware flow control is not required like here, set these
                    // pins to 0x00. See Table 1 and Table 2 for valid options.
                    puart_selectUartPads(rxPortPin, txPortPin, 0x00, 0x00);
                
                    // Initialize the peripheral uart driver
                    puart_init();
                
                    // Since we are not configuring CTS and RTS here, turn off
                    // hardware flow control. If HW flow control is used, then
                    // puart_flowOff should not be invoked.
                    puart_flowOff();
                
                    // Since we are not using any flow control, disable sleep.
                    // If HW flow control is configured or app uses its own flow control mechanism,
                    // this is not required.
                    devlpm_registerForLowPowerQueries(ttl_ble_device_lpm_queriable, 0);
                
                    // BEGIN - puart interrupt
                    //  The following lines enable interrupt when one (or more) bytes
                    //  are received over the peripheral uart interface. This is optional.
                    //  In the absense of this, the app is expected to poll the peripheral
                    //  uart to pull out received bytes.
                
                    // clear interrupt
                    P_UART_INT_CLEAR(P_UART_ISR_RX_AFF_MASK);
                
                    // set watermark to 1 byte - will interrupt on every byte received.
                    P_UART_WATER_MARK_RX_LEVEL(1);
                
                    // enable UART interrupt in the Main Interrupt Controller and RX Almost Full in the UART
                    // Interrupt Controller
                    P_UART_INT_ENABLE |= P_UART_ISR_RX_AFF_MASK;
                
                    // Set callback function to app callback function.
                    puart_rxCb = btup_receiveDataCallback;
                
                    puart_enableTx();
                
                    // Enable the CPU level interrupt
                    puart_enableInterrupt();
                    /* END - puart interrupt */
                }
                
                // Callback called by the FW when ready to sleep/deep-sleep. Disable both by returning 0
                // when there is an active download ongoing.
                static UINT32 ttl_ble_device_lpm_queriable(LowPowerModePollType type, UINT32 context)
                {
                    /*
                    if(type == LOW_POWER_MODE_POLL_TYPE_SLEEP)
                    {
                        ble_trace1("ttl_ble_device_lpm_queriable(LOW_POWER_MODE_POLL_TYPE_SLEEP, %u)", context);
                    } else
                    {
                        ble_trace1("ttl_ble_device_lpm_queriable(LOW_POWER_MODE_POLL_TYPE_POWER_OFF, %u)", context);
                    }
                    */
                    // Disable sleep.
                    return 0;
                }
                
                // Connection up callback function is called on every connection establishment
                void ttl_ble_connection_up(void)
                {
                    UINT8 *bda = (UINT8 *)emconninfo_getPeerPubAddr();
                    ttl_ble_connection_handle = (UINT16)emconinfo_getConnHandle();
                
                    // Save address of the connected device and print it out.
                    memcpy(ttl_ble_remote_addr, bda, sizeof(ttl_ble_remote_addr));
                
                    ble_trace3("connection_up: %08x%04x h=%d",
                                (ttl_ble_remote_addr[5] << 24) + (ttl_ble_remote_addr[4] << 16) +
                                (ttl_ble_remote_addr[3] << 8) + ttl_ble_remote_addr[2],
                                (ttl_ble_remote_addr[1] << 8) + ttl_ble_remote_addr[0],
                                ttl_ble_connection_handle);
                
                    // Prepare generated code for connection - write persistent values from __HOSTINFO to GATT DB
                    __on_connection_up();
                
                    // ToDo: Write custom persistent values into GATT database using functions
                    // changed_<service_name>_<char_name>() generated by smart designer
                
                    // If device supports a single connection, stop advertising
                    bleprofile_Discoverable(NO_DISCOVERABLE, NULL);
                
                    // If security is required for every connection following function will start bonding or
                    // will setup encryption.  No indications or notifications should be sent until
                    // encryption is not done.
                    if (bleprofile_p_cfg->encr_required & SECURITY_REQUEST)
                    {
                        if (emconninfo_deviceBonded())
                        {
                            ble_trace0("device bonded");
                        }
                        else
                        {
                            ble_trace0("device not bonded");
                            lesmp_sendSecurityRequest();
                        }
                    }
                }
                
                // Connection down callback
                void ttl_ble_connection_down(void)
                {
                    ttl_ble_connection_handle = 0;
                
                    // If disconnection was caused by the peer, start low advertisements
                    bleprofile_Discoverable(LOW_UNDIRECTED_DISCOVERABLE, NULL);
                
                    ble_trace2("ADV start: %08x%04x",
                                  (ttl_ble_remote_addr[5] << 24 ) + (ttl_ble_remote_addr[4] <<16) +
                                  (ttl_ble_remote_addr[3] << 8 ) + ttl_ble_remote_addr[2],
                                  (ttl_ble_remote_addr[1] << 8 ) + ttl_ble_remote_addr[0]);
                }
                
                // Callback function indicates to the application that advertising has stopped.
                // restart advertisement if needed
                void ttl_ble_advertisement_stopped(void)
                {
                    ble_trace0("ADV stop!");
                
                    // If disconnection was caused by the peer, start low advertisements
                    bleprofile_Discoverable(LOW_UNDIRECTED_DISCOVERABLE, NULL);
                }
                
                // Process SMP bonding result.  If pairing is successful with the central device,
                // save its BDADDR in the NVRAM and initialize associated data
                void ttl_ble_smp_bond_result(LESMP_PARING_RESULT  result)
                {
                    ble_trace1("smp_bond_result %02x", result);
                
                    if (result == LESMP_PAIRING_RESULT_BONDED)
                    {
                        // saving bd_addr in nvram
                        UINT8 *bda;
                        UINT8 writtenbyte;
                
                        bda = (UINT8 *)emconninfo_getPeerPubAddr();
                
                        // initialize persistent values in the hostinfo to add bonded peer
                        ttl_ble_add_bond(bda);
                
                        // ToDo: initialize persistent variables in HOSTINFO
                
                        //now write hostinfo into NVRAM
                        writtenbyte = bleprofile_WriteNVRAM(VS_BLE_HOST_LIST, sizeof(ttl_ble_hostinfo), (UINT8 *)&ttl_ble_hostinfo);
                        ble_trace1("ttl_ble_smp_bond_result: NVRAM write:%04x", writtenbyte);
                    }
                }
                
                // Notification from the stack that encryption has been set.
                void ttl_ble_encryption_changed(HCI_EVT_HDR *evt)
                {
                    UINT8 *bda = emconninfo_getPeerPubAddr();
                
                /*    ble_trace2("encryption changed %08x%04x",
                                (bda[5] << 24) + (bda[4] << 16) +
                                (bda[3] << 8) + bda[2],
                                (bda[1] << 8) + bda[0]);*/
                
                    ble_trace0("encryption changed!");
                
                    // ToDo: do your on-encryption-change actions here.
                
                    // Slow down the pace of master polls to save power.  Following request asks
                    // host to setup polling every 100-500 msec, with link supervision timeout 5 seconds.
                    bleprofile_SendConnParamUpdateReq(80, 400, 0, 500);
                }
                
                // Process write request or command from peer device
                int ttl_ble_write_handler(LEGATTDB_ENTRY_HDR *p)
                {
                    UINT8  writtenbyte;
                    UINT16 handle   = legattdb_getHandle(p);
                    int    len      = legattdb_getAttrValueLen(p);
                    UINT8  *attrPtr = legattdb_getAttrValue(p);
                    BOOL changed;
                    ble_trace2("ttl_ble_write_handler(): handle = %#06x, len = %u", handle, len);
                    changed = __write_handler(handle, len, attrPtr);
                
                    // Save update to NVRAM if it has been changed.
                    if (changed)
                    {
                        //ble_trace1("ttl_ble_write_handler: NVRAM write:%04x", writtenbyte);
                        writtenbyte = bleprofile_WriteNVRAM(VS_BLE_HOST_LIST, sizeof(ttl_ble_hostinfo), (UINT8 *)&ttl_ble_hostinfo);
                    }
                    return 0;
                }
                
                // Three Interrupt inputs (Buttons) can be handled here.
                // If the following value == 1, Button is pressed. Different than initial value.
                // If the following value == 0, Button is depressed. Same as initial value.
                // Button1 : value&0x01
                // Button2 : (value&0x02)>>1
                // Button3 : (value&0x04)>>2
                void ttl_ble_interrupt_handler(UINT8 value)
                {
                    ble_trace1("ttl_ble_interrupt_handler(%u)", value);
                    // ToDo: handle the interrupts here.
                }
                
                // It will be called every 1 sec
                void ttl_ble_timer_1s()
                {
                    //Todo: do you actions here every 1 second
                }
                
                // It will be called every fine timer tick
                void ttl_ble_timer_fine()
                {
                    //Todo: do you actions here every fine timer tick
                }
                
                
                
                
                
                

                 

                bt_uart_protocol.h
                #ifndef __BT_UART_PROTOCOL_H__
                #define __BT_UART_PROTOCOL_H__
                
                #include "types.h"
                
                #define BT_UART_BUFFERSIZE 64
                #define BT_RESPONSE_TIMEOUT 8        //Timeout after a single packet/second dual packet transfer, multiple of fine timer tick (12ms)
                #define BT_REMAINING_BYTES_TIMEOUT 4 //Timeout after the first of a dual packet transfer, multiple of fine timer tick (12ms)
                #define BT_TIMEOUT_MAX_RESENDS 5     //Maximum number of resends after timeout
                #define BT_NO_ACK_NO_RESEND    1     //If defined, no ACKs will be sent or expected; will also disable resends!
                //#define BT_NO_CRC              1     //If defined no CRC calculations will be made and received CRCs are always assumed correct
                
                typedef enum address_types //size of characteristic, data direction seen from BLE module, i.e. write means send only to MCU
                {
                    ADDR_ACK = 0,
                    ADDR_COMMAND,
                    ADDR_CHAR_GLOBAL_STATUS, //3 bytes, read
                    ADDR_CHAR_TCAS_SECOND_PACKET, //20 bytes, read/write/write no response
                    ADDR_CHAR_FDAMS_SECOND_PACKET, //18 bytes, read
                    ADDR_CHAR_SSMC, //1 byte, read/write/write no response
                    ADDR_CHAR_DATA_WRITE_TO_BLE_0, //20 bytes, write
                    ADDR_CHAR_DATA_WRITE_TO_BLE_1, //20 bytes, write
                    ADDR_CHAR_DATA_WRITE_TO_BLE_2, //20 bytes, write
                    ADDR_CHAR_DATA_WRITE_TO_BLE_3, //20 bytes, write
                    ADDR_CHAR_DATA_READ_FROM_BLE_0_SECOND_PACKET, //20 bytes, read
                    ADDR_CHAR_DATA_READ_FROM_BLE_1_SECOND_PACKET, //20 bytes, read
                    ADDR_CHAR_DATA_READ_FROM_BLE_2_SECOND_PACKET, //20 bytes, read
                    ADDR_CHAR_DATA_READ_FROM_BLE_3_SECOND_PACKET, //20 bytes, read
                    ADDR_CHAR_COMMAND_WRITE_TO_BLE, //5 bytes, write
                    ADDR_CHAR_COMMAND_READ_FROM_BLE, //5 bytes, read
                    ADDR_CHAR_TCAS = 0x23, //20 bytes, read/write/write no response, first packet
                    ADDR_CHAR_FDAMS = 0x24, //18 bytes, read, first packet
                    ADDR_CHAR_DATA_READ_FROM_BLE_0 = 0x2A, //20 bytes, read, first packet
                    ADDR_CHAR_DATA_READ_FROM_BLE_1 = 0x2B, //20 bytes, read, first packet
                    ADDR_CHAR_DATA_READ_FROM_BLE_2 = 0x2C, //20 bytes, read, first packet
                    ADDR_CHAR_DATA_READ_FROM_BLE_3 = 0x2D//20 bytes, read, first packet
                } ADDRESS_TYPE;
                
                void btup_init(void);
                void btup_sendData(BOOL read, BOOL request, ADDRESS_TYPE address, unsigned char length, unsigned char *data);
                void btup_receiveDataCallback(void* unused);
                void btup_timeOutCallback(UINT32 arg);
                
                #endif
                
                
                
                
                
                

                 

                bt_uart_protocol.c
                #include "devicelpm.h"
                #include "bleprofile.h"
                #include "bt_uart_protocol.h"
                #include "crc.h"
                #include "gpio_ttl.h"
                #include "puart.h"
                #include "ttl_db.h"
                #include "bleapp.h"
                #include "blecm.h"
                
                #include <string.h>
                extern void *memset(void *s, int c, size_t n);
                
                
                typedef struct //used for received data packets (addresses 0x02..0x09)
                {
                    unsigned char firstByte; //save the first received byte for easier decoding
                    BOOL read;
                    BOOL request;
                    ADDRESS_TYPE address;
                    unsigned char dataAndCRCLength; //this is the length of data trailing after first byte including CRC
                    unsigned char oldLengthDataAndCRC; //as length but from previous packet
                    unsigned char data[14]; //contains data and crc as last byte
                    unsigned char oldData[14]; //dito but from previous packet
                    unsigned char crc8;
                    BOOL crcMatches;
                } DATA_PACKET_RECEIVE_STRUCT;
                
                typedef struct //used for transmitted data packets, if request is TRUE it needs to be ACKed!
                {
                    BOOL acked;
                    ADDRESS_TYPE address;
                    BOOL read;
                    BOOL request;
                    BOOL sent;
                    unsigned char timeoutCounter;
                    unsigned char resendCounter;
                    unsigned char data[23]; //note that this contains the whole packet including first byte and crc sum
                    unsigned char wholePacketLength; //that's why this is longer!
                } DATA_PACKET_TRANSMIT_STRUCT;
                
                typedef enum uart_protocol_states
                {
                    UART_IDLE_DECODE_IDLE,
                    UART_IDLE_RECEIVED_FIRST_BYTE
                //    UART_WAIT_FOR_RESPONSE
                //    UART_WAIT_FOR_RESPONSE_FIRST_BYTE
                } UART_STATE;
                
                typedef enum address_type_associated_length //trailing bytes including crc after address type byte, i.e. char length + 1
                {
                    LEN_ACK = 3, LEN_COMMAND = 3, LEN_CHAR_GLOBAL_STATUS = 4, //3 bytes, read
                    LEN_CHAR_TCAS_SECOND_PACKET = 7, //20 bytes, read/write/write no response
                    LEN_CHAR_FDAMS_SECOND_PACKET = 5, //18 bytes, read
                    LEN_CHAR_SSMC = 2, //1 byte, read/write/write no response
                    LEN_CHAR_DATA_WRITE_TO_BLE_0 = 21, //20 bytes, write
                    LEN_CHAR_DATA_WRITE_TO_BLE_1 = 21, //20 bytes, write
                    LEN_CHAR_DATA_WRITE_TO_BLE_2 = 21, //20 bytes, write
                    LEN_CHAR_DATA_WRITE_TO_BLE_3 = 21, //20 bytes, write
                    LEN_CHAR_DATA_READ_FROM_BLE_0_SECOND_PACKET = 7, //20 bytes, read
                    LEN_CHAR_DATA_READ_FROM_BLE_1_SECOND_PACKET = 7, //20 bytes, read
                    LEN_CHAR_DATA_READ_FROM_BLE_2_SECOND_PACKET = 7, //20 bytes, read
                    LEN_CHAR_DATA_READ_FROM_BLE_3_SECOND_PACKET = 7, //20 bytes, read
                    LEN_CHAR_COMMAND_WRITE_TO_BLE = 6, //5 bytes, write
                    LEN_CHAR_COMMAND_READ_FROM_BLE = 6, //5 bytes, read
                    LEN_CHAR_TCAS = 15, //20 bytes, read/write/write no response, first packet
                    LEN_CHAR_FDAMS = 15, //18 bytes, read, first packet
                    LEN_CHAR_DATA_READ_FROM_BLE_0 = 15, //20 bytes, read, first packet
                    LEN_CHAR_DATA_READ_FROM_BLE_1 = 15, //20 bytes, read, first packet
                    LEN_CHAR_DATA_READ_FROM_BLE_2 = 15, //20 bytes, read, first packet
                    LEN_CHAR_DATA_READ_FROM_BLE_3 = 15 //20 bytes, read, first packet
                } LEN_ADDR;
                
                typedef enum command_types
                {
                    CMD_3V7_SW_STATUS,
                    CMD_2V8_SW_STATUS,
                    CMD_3V3_EN_STATUS,
                    CMD_LED_STATUS,
                    CMD_M4_WKUP_STATUS,
                    CMD_BLE_SLEEP_FINE_TIMEOUT,
                    CMD_BLE_SLEEP_COARSE_TIMEOUT,
                    CMD_ADV_STATUS
                } COMMAND_TYPE;
                
                static volatile unsigned char rxBuffer[BT_UART_BUFFERSIZE];
                static volatile unsigned char rxReadPointer;
                static volatile unsigned char rxWritePointer;
                static volatile unsigned char rxCount;
                static volatile UART_STATE uartState;
                static volatile DATA_PACKET_RECEIVE_STRUCT lastReceivedPacket;
                static volatile DATA_PACKET_TRANSMIT_STRUCT sentPackets[22];
                static void resetRxBuffers(void);
                static signed int readFromRxBuffer(void);
                static inline void transferUartToRxBuffer(void);
                static void decodeFirstByteToLastReceivedPacket(unsigned char firstByte);
                static void decodeRemainingBytesOfLastReceivedPacket(void);
                static void resetLastReceivedPacket(BOOL saveToOldData);
                static inline unsigned char getExpectedLength(unsigned char data);
                static inline void enableRxInterrupt(BOOL enable);
                static void executeSinglePacketChar(void);
                static void executeDoublePacketChar(void);
                static void executeCommand(void);
                static void resetPacketTimeout(ADDRESS_TYPE addr, BOOL resetResendCounter);
                static inline unsigned char getSentPacketByAddress(ADDRESS_TYPE addr);
                static inline void sendACK(unsigned char firstByteLastPacket, unsigned char ackData);
                static inline void receivedACK(void);
                static void notificationWithDB(UINT16 handle, unsigned char *data, unsigned char length, BOOL notify, BOOL writeToDB);
                static void traceAddress(ADDRESS_TYPE addr);
                static void traceHandle(unsigned int handle);
                
                void btup_init(void)
                {
                    ble_trace0("btup_init()");
                    unsigned char i, j;
                    enableRxInterrupt(FALSE);
                    resetRxBuffers();
                    uartState = UART_IDLE_DECODE_IDLE;
                    resetLastReceivedPacket(FALSE);
                    for (i = 0; i < 22; i++)
                    {
                #ifdef BT_NO_ACK_NO_RESEND
                        sentPackets[i].acked = TRUE;
                #else
                        sentPackets[i].acked = FALSE;
                #endif
                        sentPackets[i].address = 0xFF;
                        sentPackets[i].wholePacketLength = 0;
                        sentPackets[i].read = FALSE;
                        sentPackets[i].request = FALSE;
                        sentPackets[i].resendCounter = BT_TIMEOUT_MAX_RESENDS;
                        sentPackets[i].sent = FALSE;
                        sentPackets[i].timeoutCounter = 0;
                        for (j = 0; j < 23; j++)
                        {
                            sentPackets[i].data[j] = 0;
                        }
                    }
                    bleprofile_PUARTSetRxWaterlevel(1);
                    enableRxInterrupt(TRUE);
                }
                
                void btup_sendData(BOOL read, BOOL request, ADDRESS_TYPE address,
                        unsigned char dataLength, unsigned char *data)
                {
                    if(read == TRUE)
                    {
                        if(request == TRUE)
                        {
                            ble_trace2("btup_sendData(TRUE, TRUE, %#04x, %u)", address, dataLength);
                        }
                        else
                        {
                            ble_trace2("btup_sendData(TRUE, FALSE, %#04x, %u)", address, dataLength);
                        }
                    } else
                    {
                        if(request == TRUE)
                        {
                            ble_trace2("btup_sendData(FALSE, TRUE, %#04x, %u)", address, dataLength);
                        }
                        else
                        {
                            ble_trace2("btup_sendData(FALSE, FALSE, %#04x, %u)", address, dataLength);
                        }
                    }
                    unsigned char i;
                    unsigned char packNum = 0;
                    if (dataLength <= 20)
                    {
                        //copy data to sentPackets
                        packNum = getSentPacketByAddress(address);
                        sentPackets[packNum].data[0] = address & 0x3F;
                        if (read == TRUE)
                        {
                            sentPackets[packNum].data[0] |= 0x80;
                        }
                        if (request == TRUE)
                        {
                            sentPackets[packNum].data[0] |= 0x40;
                        }
                        sentPackets[packNum].read = read;
                        sentPackets[packNum].request = request;
                        sentPackets[packNum].address = address;
                        sentPackets[packNum].wholePacketLength = dataLength + 2;
                        memcpy((unsigned char *) (sentPackets[packNum].data + 1), data, dataLength);
                #ifdef BT_NO_CRC
                        sentPackets[packNum].data[dataLength + 1] = 0xAA; //bogus CRC
                #else
                        //calculate CRC
                        sentPackets[packNum].data[dataLength + 1] = (unsigned char) crc_calc((uint8_t *) sentPackets[packNum].data, dataLength + 1);
                #endif
                        //send data via puart_write
                        i = bleprofile_PUARTTx((unsigned char *) sentPackets[packNum].data, sentPackets[packNum].wholePacketLength);
                        sentPackets[packNum].sent = TRUE;
                #ifndef BT_NO_ACK_NO_RESEND
                        if ((request == TRUE) && (address != ADDR_ACK))
                        {
                            sentPackets[packNum].acked = FALSE;
                        }
                        else
                #endif
                        { //don't ack an ACK and don't wait for ACKs on replies
                            sentPackets[packNum].acked = TRUE;
                        }
                        //after sending we must set uartState accordingly
                        uartState = UART_IDLE_DECODE_IDLE;
                #ifndef BT_NO_ACK_NO_RESEND
                        //don't forget to set the right timeoutCounter afterwards!
                        resetPacketTimeout(address, TRUE);
                #else
                        sentPackets[packNum].resendCounter = 0;
                        sentPackets[packNum].timeoutCounter = 0;
                #endif
                    }
                }
                
                void btup_receiveDataCallback(void* unused)
                {
                    ble_trace0("btup_receiveDataCallback() entered");
                    signed int tempBuffer = 0;
                    transferUartToRxBuffer();
                    if (rxCount > 0) //sometimes we get trailing interrupts that should be ignored
                    {
                        switch (uartState)
                        {
                        case UART_IDLE_DECODE_IDLE:
                            tempBuffer = readFromRxBuffer();
                            if (tempBuffer >= 0) //rxBuffer not empty
                            {
                                decodeFirstByteToLastReceivedPacket((unsigned char) tempBuffer);
                                if (lastReceivedPacket.dataAndCRCLength - 1 < rxCount) //wait for all bytes
                                { //TODO: Is it the right WATER_MARK_LEVEL?
                                    //bleprofile_PUARTSetRxWaterlevel(lastReceivedPacket.dataAndCRCLength);
                                    //P_UART_WATER_MARK_RX_LEVEL(lastReceivedPacket.length);
                                    uartState = UART_IDLE_RECEIVED_FIRST_BYTE;
                                }
                                else if (lastReceivedPacket.dataAndCRCLength >= rxCount) //whole packet already received
                                {
                                    decodeRemainingBytesOfLastReceivedPacket();
                                }
                            }
                            break;
                        case UART_IDLE_RECEIVED_FIRST_BYTE: //are all bytes received yet?
                            if (rxCount >= lastReceivedPacket.dataAndCRCLength)
                            {
                                bleprofile_PUARTSetRxWaterlevel(1);
                                //P_UART_WATER_MARK_RX_LEVEL(1);
                                uartState = UART_IDLE_DECODE_IDLE;
                                decodeRemainingBytesOfLastReceivedPacket();
                            }
                            break;
                        }
                    } else
                    {
                        ble_trace0("cb no data");
                        uartState = UART_IDLE_DECODE_IDLE;
                    }
                }
                
                void btup_timeOutCallback(UINT32 arg)
                {
                    unsigned char i, j;
                #ifndef BT_NO_ACK_NO_RESEND
                    for(i=0; i<22; i++) //test all possible packets
                    {
                        if((sentPackets[i].acked == FALSE)
                            && (sentPackets[i].request == TRUE)
                            && (sentPackets[i].sent == TRUE)
                            && (sentPackets[i].resendCounter > 0))
                        {
                            if(sentPackets[i].timeoutCounter > 1)
                            {
                                sentPackets[i].timeoutCounter--;
                            } else if(sentPackets[i].timeoutCounter == 1)
                            {
                                j = bleprofile_PUARTTx((unsigned char *) sentPackets[i].data, sentPackets[i].wholePacketLength);
                                resetPacketTimeout(sentPackets[i].address, FALSE);
                            }
                        }
                    }
                #endif
                }
                
                static void resetRxBuffers(void)
                {
                    ble_trace0("resetRxBuffers()");
                    unsigned int i;
                    for (i = 0; i < BT_UART_BUFFERSIZE; i++)
                    {
                        rxBuffer[i] = 0;
                    }
                    rxReadPointer = 0;
                    rxWritePointer = 0;
                    rxCount = 0;
                }
                
                static signed int readFromRxBuffer(void)
                {
                    ble_trace0("readFromRxBuffer()");
                    signed int buffer = -1;
                    if (rxCount > 0)
                    {
                        buffer = rxBuffer[rxReadPointer++];
                        rxCount--;
                        if (rxReadPointer >= BT_UART_BUFFERSIZE)
                        {
                            rxReadPointer = 0;
                        }
                    }
                    return buffer;
                }
                
                static inline void transferUartToRxBuffer(void)
                {
                    ble_trace0("transferUartToRxBuffer()");
                    unsigned char readByte;
                    enableRxInterrupt(FALSE);
                    while (puart_rxFifoNotEmpty() && puart_read(&readByte)
                            && (rxCount < BT_UART_BUFFERSIZE))
                    {
                        rxBuffer[rxWritePointer++] = readByte;
                        rxCount++;
                        if (rxWritePointer >= BT_UART_BUFFERSIZE)
                        {
                            rxWritePointer = 0;
                        }
                    }
                    enableRxInterrupt(TRUE);
                }
                
                static void decodeFirstByteToLastReceivedPacket(unsigned char firstByte)
                {
                    ble_trace1("decodeFirstByteToLastReceivedPacket(%#04x)", firstByte);
                    lastReceivedPacket.firstByte = firstByte;
                    if ((firstByte & 0x80) == 0)
                    {
                        lastReceivedPacket.read = FALSE;
                    }
                    else
                    {
                        lastReceivedPacket.read = TRUE;
                    }
                    if ((firstByte & 0x40) == 0)
                    {
                        lastReceivedPacket.request = FALSE;
                    }
                    else
                    {
                        lastReceivedPacket.request = TRUE;
                    }
                    lastReceivedPacket.address = (firstByte & 0x3F);
                    lastReceivedPacket.dataAndCRCLength = getExpectedLength(lastReceivedPacket.address);
                }
                
                //all bytes of this packet must already be received and are transferred into the rxBuffer
                static void decodeRemainingBytesOfLastReceivedPacket(void)
                {
                    ble_trace0("decodeRemainingBytesOfLastReceivedPacket()");
                    unsigned char i, computedCRC;
                    unsigned char crcData[16];
                    enableRxInterrupt(FALSE);
                    //let's transfer the missing bytes into the lastReceivedByte-struct
                    for (i = 0; i < lastReceivedPacket.dataAndCRCLength - 1; i++)
                    {
                        //we should test on error (-1), but if there is one, it's already occurred before
                        lastReceivedPacket.data[i] = (unsigned char) readFromRxBuffer();
                    }
                    lastReceivedPacket.crc8 = (unsigned char) readFromRxBuffer();
                #ifndef BT_NO_CRC
                    //now calculate CRC
                    crcData[0] = lastReceivedPacket.firstByte;
                    memcpy((crcData + 1), (unsigned char *) lastReceivedPacket.data, (lastReceivedPacket.dataAndCRCLength - 1));
                    computedCRC = (unsigned char) crc_calc(crcData, lastReceivedPacket.dataAndCRCLength);
                #else
                    computedCRC = lastReceivedPacket.crc8; //ignore CRC
                #endif
                    if (computedCRC == lastReceivedPacket.crc8)
                    {
                        lastReceivedPacket.crcMatches = TRUE;
                        if (lastReceivedPacket.address == ADDR_COMMAND)
                        {
                            executeCommand(); //it's ugly, but this one must ACK itself
                        }
                        else if ((lastReceivedPacket.address == ADDR_CHAR_TCAS) //double packet first packet
                                || (lastReceivedPacket.address == ADDR_CHAR_FDAMS)
                                || (lastReceivedPacket.address == ADDR_CHAR_DATA_WRITE_TO_BLE_0)
                                || (lastReceivedPacket.address == ADDR_CHAR_DATA_WRITE_TO_BLE_1)
                                || (lastReceivedPacket.address == ADDR_CHAR_DATA_WRITE_TO_BLE_2)
                                || (lastReceivedPacket.address == ADDR_CHAR_DATA_WRITE_TO_BLE_3)
                                || (lastReceivedPacket.address == ADDR_CHAR_DATA_READ_FROM_BLE_0)
                                || (lastReceivedPacket.address == ADDR_CHAR_DATA_READ_FROM_BLE_1)
                                || (lastReceivedPacket.address == ADDR_CHAR_DATA_READ_FROM_BLE_2)
                                || (lastReceivedPacket.address == ADDR_CHAR_DATA_READ_FROM_BLE_3))
                        {
                            //we must ACK this and wait for the second packet
                #ifndef BT_NO_ACK_NO_RESEND
                            sendACK(lastReceivedPacket.firstByte, 0);
                #endif
                            resetLastReceivedPacket(TRUE); //save oldData and reset the rest
                        }
                        else if ((lastReceivedPacket.address == ADDR_CHAR_GLOBAL_STATUS)
                                || (lastReceivedPacket.address
                                        == ADDR_CHAR_SSMC)
                                || (lastReceivedPacket.address == ADDR_CHAR_COMMAND_WRITE_TO_BLE)
                                || (lastReceivedPacket.address
                                        == ADDR_CHAR_COMMAND_READ_FROM_BLE))
                        {
                #ifndef BT_NO_ACK_NO_RESEND
                            //we must ACK this and do the appropriate, but remember to call resetLastReceivedPacket *after* executeSinglePacketChar
                            sendACK(lastReceivedPacket.firstByte, 0);
                #endif
                            executeSinglePacketChar();
                            resetLastReceivedPacket(FALSE);
                        }
                        else if ((lastReceivedPacket.address
                                == ADDR_CHAR_TCAS_SECOND_PACKET) //double packet second packet
                                || (lastReceivedPacket.address
                                        == ADDR_CHAR_FDAMS_SECOND_PACKET)
                                || (lastReceivedPacket.address
                                        == ADDR_CHAR_DATA_READ_FROM_BLE_0_SECOND_PACKET)
                                || (lastReceivedPacket.address
                                        == ADDR_CHAR_DATA_READ_FROM_BLE_1_SECOND_PACKET)
                                || (lastReceivedPacket.address
                                        == ADDR_CHAR_DATA_READ_FROM_BLE_2_SECOND_PACKET)
                                || (lastReceivedPacket.address
                                        == ADDR_CHAR_DATA_READ_FROM_BLE_3_SECOND_PACKET))
                        {
                #ifndef BT_NO_ACK_NO_RESEND
                            //we must ACK this and do the appropriate
                            sendACK(lastReceivedPacket.firstByte, 0);
                #endif
                            executeDoublePacketChar();
                            resetLastReceivedPacket(FALSE);
                        }
                        else if (lastReceivedPacket.address == ADDR_ACK)
                        {
                            receivedACK();
                        }
                    }
                    else
                    {
                #ifndef BT_NO_CRC
                        lastReceivedPacket.crcMatches = FALSE;
                #else
                        lastReceivedPacket.crcMatches = TRUE;
                #endif
                        resetLastReceivedPacket(FALSE);
                    }
                    enableRxInterrupt(TRUE);
                }
                
                static void resetLastReceivedPacket(BOOL saveToOldData)
                {
                    static const unsigned char zeroPad[14] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0};
                    unsigned int i;
                    if(saveToOldData == TRUE)
                    {
                        ble_trace0("resetLastReceivedPacket(TRUE)");
                    } else
                    {
                        ble_trace0("resetLastReceivedPacket(FALSE)");
                    }
                
                    lastReceivedPacket.firstByte = 0;
                    lastReceivedPacket.read = FALSE;
                    lastReceivedPacket.request = FALSE;
                    lastReceivedPacket.address = 0xff;
                    if (saveToOldData == TRUE)
                    {
                        lastReceivedPacket.oldLengthDataAndCRC = lastReceivedPacket.dataAndCRCLength;
                    }
                    else
                    {
                        lastReceivedPacket.oldLengthDataAndCRC = 0;
                    }
                    lastReceivedPacket.dataAndCRCLength = 0;
                    lastReceivedPacket.crc8 = 0x00;
                    lastReceivedPacket.crcMatches = FALSE;
                    if (saveToOldData == TRUE)
                    {
                        memcpy((unsigned char *) lastReceivedPacket.oldData, (unsigned char *) lastReceivedPacket.data, 14); //backup actual data to oldData
                    }
                    else
                    {
                        memcpy((unsigned char *) lastReceivedPacket.oldData, zeroPad, 14);
                    }
                    memcpy((unsigned char *) lastReceivedPacket.data, zeroPad, 14);
                }
                
                static inline unsigned char getExpectedLength(unsigned char data)
                {
                    ble_trace1("getExpectedLength(%u)", data);
                    int iData = (int) (data & 0x3F);
                    switch (iData)
                    {
                    case ADDR_ACK:
                        return LEN_ACK;
                        break;
                    case ADDR_COMMAND:
                        return LEN_COMMAND;
                        break;
                    case ADDR_CHAR_GLOBAL_STATUS:
                        return LEN_CHAR_GLOBAL_STATUS;
                        break;
                    case ADDR_CHAR_TCAS_SECOND_PACKET:
                        return LEN_CHAR_TCAS_SECOND_PACKET;
                        break;
                    case ADDR_CHAR_FDAMS_SECOND_PACKET:
                        return LEN_CHAR_FDAMS_SECOND_PACKET;
                        break;
                    case ADDR_CHAR_SSMC:
                        return LEN_CHAR_SSMC;
                        break;
                    case ADDR_CHAR_DATA_WRITE_TO_BLE_0:
                        return LEN_CHAR_DATA_WRITE_TO_BLE_0;
                        break;
                    case ADDR_CHAR_DATA_WRITE_TO_BLE_1:
                        return LEN_CHAR_DATA_WRITE_TO_BLE_1;
                        break;
                    case ADDR_CHAR_DATA_WRITE_TO_BLE_2:
                        return LEN_CHAR_DATA_WRITE_TO_BLE_2;
                        break;
                    case ADDR_CHAR_DATA_WRITE_TO_BLE_3:
                        return LEN_CHAR_DATA_WRITE_TO_BLE_3;
                        break;
                    case ADDR_CHAR_DATA_READ_FROM_BLE_0_SECOND_PACKET:
                        return LEN_CHAR_DATA_READ_FROM_BLE_0_SECOND_PACKET;
                        break;
                    case ADDR_CHAR_DATA_READ_FROM_BLE_1_SECOND_PACKET:
                        return LEN_CHAR_DATA_READ_FROM_BLE_1_SECOND_PACKET;
                        break;
                    case ADDR_CHAR_DATA_READ_FROM_BLE_2_SECOND_PACKET:
                        return LEN_CHAR_DATA_READ_FROM_BLE_2_SECOND_PACKET;
                        break;
                    case ADDR_CHAR_DATA_READ_FROM_BLE_3_SECOND_PACKET:
                        return LEN_CHAR_DATA_READ_FROM_BLE_3_SECOND_PACKET;
                        break;
                    case ADDR_CHAR_COMMAND_WRITE_TO_BLE:
                        return LEN_CHAR_COMMAND_WRITE_TO_BLE;
                        break;
                    case ADDR_CHAR_COMMAND_READ_FROM_BLE:
                        return LEN_CHAR_COMMAND_READ_FROM_BLE;
                        break;
                    case ADDR_CHAR_TCAS:
                        return LEN_CHAR_TCAS;
                        break;
                    case ADDR_CHAR_FDAMS:
                        return LEN_CHAR_FDAMS;
                        break;
                    case ADDR_CHAR_DATA_READ_FROM_BLE_0:
                        return LEN_CHAR_DATA_READ_FROM_BLE_0;
                        break;
                    case ADDR_CHAR_DATA_READ_FROM_BLE_1:
                        return LEN_CHAR_DATA_READ_FROM_BLE_1;
                        break;
                    case ADDR_CHAR_DATA_READ_FROM_BLE_2:
                        return LEN_CHAR_DATA_READ_FROM_BLE_2;
                        break;
                    case ADDR_CHAR_DATA_READ_FROM_BLE_3:
                        return LEN_CHAR_DATA_READ_FROM_BLE_3;
                        break;
                    default:
                        ble_trace1("Expected length: unknown command %#04x", data);
                        break;
                    }
                    return 0;
                }
                
                static inline void enableRxInterrupt(BOOL enable)
                {
                    if(enable == TRUE)
                    {
                        ble_trace0("enableRxInterrupt(TRUE)");
                    } else
                    {
                        ble_trace0("enableRxInterrupt(FALSE)");
                    }
                
                    if (enable == TRUE)
                    {
                        // set watermark to 1 byte - will interrupt on every byte received.
                        //bleprofile_PUARTSetRxWaterlevel(waterMark);
                        //P_UART_WATER_MARK_RX_LEVEL(waterMark);
                
                        // enable UART interrupt in the Main Interrupt Controller and RX Almost Full in the UART
                        // Interrupt Controller
                        P_UART_INT_ENABLE |= P_UART_ISR_RX_AFF_MASK;
                    }
                    else
                    {
                        P_UART_INT_CLEAR(P_UART_ISR_RX_AFF_MASK);
                    }
                }
                
                static void executeSinglePacketChar(void)
                {
                    ble_trace0("executeSinglePacketChar()");
                    unsigned int i;
                    BLEPROFILE_DB_PDU tempPDU;
                    int address = (int) lastReceivedPacket.address;
                    BOOL writeIt;
                    if(lastReceivedPacket.read == TRUE)
                    {
                        writeIt = FALSE;
                    } else
                    {
                        writeIt = TRUE;
                    }
                    switch (address)
                    {
                    case ADDR_CHAR_GLOBAL_STATUS:
                        if (lastReceivedPacket.read == FALSE) //write
                        {
                            notificationWithDB(HDLC_TTL_SERVICE_GLOBAL_STATUS_VALUE, (unsigned char *) lastReceivedPacket.data, (lastReceivedPacket.dataAndCRCLength - 1), TRUE, FALSE);
                        }
                        else //read
                        {
                            i = bleprofile_ReadHandle(
                                    HDLC_TTL_SERVICE_GLOBAL_STATUS_VALUE, &tempPDU);
                            btup_sendData(FALSE, FALSE, ADDR_CHAR_GLOBAL_STATUS, tempPDU.len,
                                    tempPDU.pdu);
                        }
                
                        break;
                    case ADDR_CHAR_SSMC:
                        if (lastReceivedPacket.read == FALSE)
                        {
                            notificationWithDB(HDLC_TTL_SERVICE_SSMC_VALUE, (unsigned char *) lastReceivedPacket.data, (lastReceivedPacket.dataAndCRCLength - 1), TRUE, FALSE);
                        }
                        else
                        {
                            i = bleprofile_ReadHandle(
                                    HDLC_TTL_SERVICE_SSMC_VALUE,
                                    &tempPDU);
                            btup_sendData(FALSE, FALSE, ADDR_CHAR_SSMC,
                                    tempPDU.len, tempPDU.pdu);
                        }
                
                        break;
                    case ADDR_CHAR_COMMAND_WRITE_TO_BLE:
                        if (lastReceivedPacket.read == FALSE)
                        {
                            notificationWithDB(HDLC_TTL_ENHANCEMENT_SERVICE_COMMAND_WRITE_TO_BLE_VALUE, (unsigned char *) lastReceivedPacket.data, (lastReceivedPacket.dataAndCRCLength - 1), TRUE, FALSE);
                        }
                        else
                        {
                            i =
                                    bleprofile_ReadHandle(
                                            HDLC_TTL_ENHANCEMENT_SERVICE_COMMAND_WRITE_TO_BLE_VALUE,
                                            &tempPDU);
                            btup_sendData(FALSE, FALSE, ADDR_CHAR_COMMAND_WRITE_TO_BLE,
                                    tempPDU.len, tempPDU.pdu);
                        }
                
                        break;
                    case ADDR_CHAR_COMMAND_READ_FROM_BLE:
                        if (lastReceivedPacket.read == FALSE)
                        {
                            notificationWithDB(HDLC_TTL_ENHANCEMENT_SERVICE_COMMAND_READ_FROM_BLE_VALUE, (unsigned char *) lastReceivedPacket.data, (lastReceivedPacket.dataAndCRCLength - 1), TRUE, FALSE);
                        }
                        else
                        {
                            i =    bleprofile_ReadHandle(HDLC_TTL_ENHANCEMENT_SERVICE_COMMAND_READ_FROM_BLE_VALUE, &tempPDU);
                            btup_sendData(FALSE, FALSE, ADDR_CHAR_COMMAND_READ_FROM_BLE,
                                    tempPDU.len, tempPDU.pdu);
                        }
                
                        break;
                    }
                }
                
                static void executeDoublePacketChar(void)
                {
                    ble_trace0("executeDoublePacketChar()");
                    BOOL writeIt;
                    unsigned int i;
                    unsigned char totalLength = lastReceivedPacket.oldLengthDataAndCRC + lastReceivedPacket.dataAndCRCLength - 2; //less two crc sums
                    unsigned char data[40];
                    BLEPROFILE_DB_PDU tempPDU;
                    int address = (int) lastReceivedPacket.address; //used for switch statement only
                    //now copy the whole first packet and second packet less crc into the data array
                    memcpy(data, (unsigned char *) lastReceivedPacket.oldData, lastReceivedPacket.oldLengthDataAndCRC - 1);
                    memcpy(data + lastReceivedPacket.oldLengthDataAndCRC, (unsigned char *) lastReceivedPacket.data, lastReceivedPacket.dataAndCRCLength - 1);
                    if(lastReceivedPacket.read == TRUE)
                    {
                        writeIt = FALSE;
                    } else
                    {
                        writeIt = TRUE;
                    }
                    switch (address)
                    {
                    case ADDR_CHAR_TCAS_SECOND_PACKET:
                        if (lastReceivedPacket.read == FALSE) //write
                        {
                            notificationWithDB(HDLC_TTL_SERVICE_TCAS_VALUE, data, totalLength, TRUE, FALSE);
                        }
                        else //read
                        {
                            i = bleprofile_ReadHandle(
                                    HDLC_TTL_SERVICE_TCAS_VALUE,
                                    &tempPDU);
                            btup_sendData(FALSE, FALSE, ADDR_CHAR_TCAS,
                                    tempPDU.len, tempPDU.pdu);
                        }
                
                        break;
                    case ADDR_CHAR_FDAMS_SECOND_PACKET:
                        if (lastReceivedPacket.read == FALSE) //write
                        {
                            notificationWithDB(HDLC_TTL_SERVICE_FDAMS_VALUE, data, totalLength, TRUE, FALSE);
                        }
                        else //read
                        {
                            i =    bleprofile_ReadHandle(HDLC_TTL_SERVICE_FDAMS_VALUE, &tempPDU);
                            btup_sendData(FALSE, FALSE,
                                    ADDR_CHAR_FDAMS_SECOND_PACKET,
                                    tempPDU.len, tempPDU.pdu);
                        }
                
                        break;
                    case ADDR_CHAR_DATA_READ_FROM_BLE_0_SECOND_PACKET:
                        if (lastReceivedPacket.read == FALSE) //write
                        {
                            notificationWithDB(HDLC_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_0_VALUE, data, totalLength, TRUE, FALSE);
                        }
                        else //read
                        {
                            i =
                                    bleprofile_ReadHandle(
                                            HDLC_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_0_VALUE,
                                            &tempPDU);
                            btup_sendData(FALSE, FALSE,
                                    ADDR_CHAR_DATA_READ_FROM_BLE_0_SECOND_PACKET, tempPDU.len,
                                    tempPDU.pdu);
                        }
                
                        break;
                    case ADDR_CHAR_DATA_READ_FROM_BLE_1_SECOND_PACKET:
                        if (lastReceivedPacket.read == FALSE) //write
                        {
                            notificationWithDB(HDLC_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_1_VALUE, data, totalLength, TRUE, FALSE);
                        }
                        else //read
                        {
                            i =
                                    bleprofile_ReadHandle(
                                            HDLC_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_1_VALUE,
                                            &tempPDU);
                            btup_sendData(FALSE, FALSE,
                                    ADDR_CHAR_DATA_READ_FROM_BLE_1_SECOND_PACKET, tempPDU.len,
                                    tempPDU.pdu);
                        }
                
                        break;
                    case ADDR_CHAR_DATA_READ_FROM_BLE_2_SECOND_PACKET:
                        if (lastReceivedPacket.read == FALSE) //write
                        {
                            notificationWithDB(HDLC_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_2_VALUE, data, totalLength, TRUE, FALSE);
                        }
                        else //read
                        {
                            i =
                                    bleprofile_ReadHandle(
                                            HDLC_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_2_VALUE,
                                            &tempPDU);
                            btup_sendData(FALSE, FALSE,
                                    ADDR_CHAR_DATA_READ_FROM_BLE_2_SECOND_PACKET, tempPDU.len,
                                    tempPDU.pdu);
                        }
                
                        break;
                    case ADDR_CHAR_DATA_READ_FROM_BLE_3_SECOND_PACKET:
                        if (lastReceivedPacket.read == FALSE) //write
                        {
                            notificationWithDB(HDLC_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_3_VALUE, data, totalLength, TRUE, FALSE);
                        }
                        else //read
                        {
                            i =
                                    bleprofile_ReadHandle(
                                            HDLC_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_3_VALUE,
                                            &tempPDU);
                            btup_sendData(FALSE, FALSE,
                                    ADDR_CHAR_DATA_READ_FROM_BLE_3_SECOND_PACKET, tempPDU.len,
                                    tempPDU.pdu);
                        }
                
                        break;
                    }
                }
                
                static void executeCommand(void)
                {
                    ble_trace0("executeCommand()");
                    unsigned char data[2];
                    int command = (int) lastReceivedPacket.data[0];
                    if (lastReceivedPacket.read == FALSE) //write mode
                    {
                        switch (command)
                        {
                        case CMD_3V7_SW_STATUS:
                            enable3V7_SW((BOOL) lastReceivedPacket.data[1]);
                            break;
                        case CMD_2V8_SW_STATUS:
                            enable2V8_SW((BOOL) lastReceivedPacket.data[1]);
                            break;
                        case CMD_3V3_EN_STATUS:
                            enable3V3((BOOL) lastReceivedPacket.data[1]);
                            break;
                        case CMD_LED_STATUS:
                            enableLED((BOOL) lastReceivedPacket.data[1]);
                            break;
                        case CMD_M4_WKUP_STATUS:
                            enableWKUP(lastReceivedPacket.data[1]);
                            break;
                        case CMD_BLE_SLEEP_FINE_TIMEOUT:
                            break;
                        case CMD_BLE_SLEEP_COARSE_TIMEOUT:
                            break;
                        case CMD_ADV_STATUS:
                            break;
                        }
                        sendACK(lastReceivedPacket.firstByte, 0);
                    }
                    else //read mode
                    {
                        switch (command)
                        {
                        case CMD_3V7_SW_STATUS:
                            if (getStatus3V7_SW() == TRUE)
                            {
                                sendACK(lastReceivedPacket.firstByte, 1);
                            }
                            else
                            {
                                sendACK(lastReceivedPacket.firstByte, 0);
                            }
                            break;
                        case CMD_2V8_SW_STATUS:
                            if (getStatus2V8_SW() == TRUE)
                            {
                                sendACK(lastReceivedPacket.firstByte, 1);
                            }
                            else
                            {
                                sendACK(lastReceivedPacket.firstByte, 0);
                            }
                            break;
                        case CMD_3V3_EN_STATUS:
                            if (getStatus3V3() == TRUE)
                            {
                                sendACK(lastReceivedPacket.firstByte, 1);
                            }
                            else
                            {
                                sendACK(lastReceivedPacket.firstByte, 0);
                            }
                            break;
                        case CMD_LED_STATUS:
                            if (getStatusLED() == TRUE)
                            {
                                sendACK(lastReceivedPacket.firstByte, 1);
                            }
                            else
                            {
                                sendACK(lastReceivedPacket.firstByte, 0);
                            }
                            break;
                        case CMD_M4_WKUP_STATUS:
                            break;
                        case CMD_BLE_SLEEP_FINE_TIMEOUT:
                            break;
                        case CMD_BLE_SLEEP_COARSE_TIMEOUT:
                            break;
                        case CMD_ADV_STATUS:
                            break;
                        }
                    }
                }
                
                static void resetPacketTimeout(ADDRESS_TYPE addr, BOOL resetResendCounter)
                {
                    if(resetResendCounter == TRUE)
                    {
                        ble_trace1("resetPacketTimeout(%04x, TRUE)", addr);
                    }
                    else
                    {
                        ble_trace1("resetPacketTimeout(%04x, FALSE)", addr);
                    }
                    if (addr == ADDR_ACK) //never ever timeout ACKs
                    {
                        sentPackets[addr].timeoutCounter = 0;
                        sentPackets[addr].resendCounter = 0;
                        sentPackets[addr].acked = TRUE;
                    }
                    else if ((addr == ADDR_CHAR_TCAS) //first of dual packets
                            || (addr == ADDR_CHAR_FDAMS)
                            || (addr == ADDR_CHAR_DATA_READ_FROM_BLE_0)
                            || (addr == ADDR_CHAR_DATA_READ_FROM_BLE_1)
                            || (addr == ADDR_CHAR_DATA_READ_FROM_BLE_2)
                            || (addr == ADDR_CHAR_DATA_READ_FROM_BLE_3))
                    {
                        if(resetResendCounter == TRUE)
                        {
                            sentPackets[addr - 19].timeoutCounter = BT_REMAINING_BYTES_TIMEOUT + 1;
                            sentPackets[addr - 19].resendCounter = BT_TIMEOUT_MAX_RESENDS;
                        } else
                        {
                            if(sentPackets[addr - 19].resendCounter > 0)
                            {
                                sentPackets[addr - 19].timeoutCounter = BT_REMAINING_BYTES_TIMEOUT + 1;
                                sentPackets[addr - 19].resendCounter--;
                            } else
                            {
                                sentPackets[addr - 19].timeoutCounter = 0;
                                sentPackets[addr - 19].sent = FALSE; //sending failed
                            }
                        }
                    }
                    else //second of dual packets or single packets
                    {
                        if(resetResendCounter == TRUE)
                        {
                            sentPackets[addr].timeoutCounter = BT_RESPONSE_TIMEOUT + 1;
                            sentPackets[addr].resendCounter = BT_TIMEOUT_MAX_RESENDS;
                        } else
                        {
                            if(sentPackets[addr].resendCounter > 0)
                            {
                                sentPackets[addr].timeoutCounter = BT_RESPONSE_TIMEOUT + 1;
                                sentPackets[addr].resendCounter--;
                            } else
                            {
                                sentPackets[addr].timeoutCounter = 0;
                                sentPackets[addr].sent = FALSE; //sending failed
                            }
                        }
                    }
                }
                
                static inline unsigned char getSentPacketByAddress(ADDRESS_TYPE addr)
                {
                    ble_trace1("getSentPacketByAddress(%04x)", addr);
                    unsigned char retVal = 0;
                    if (addr < 16)
                    {
                        retVal = (unsigned char) addr;
                    }
                    else if ((addr > 0x22) && (addr < 0x2E))
                    {
                        retVal = (unsigned char) (addr - 19);
                    }
                    return retVal;
                }
                
                static inline void sendACK(unsigned char firstByteLastPacket, unsigned char ackData)
                {
                    ble_trace2("sendACK(%04x, %04x)", firstByteLastPacket, ackData);
                    unsigned char data[2];
                    data[0] = lastReceivedPacket.firstByte;
                    data[1] = ackData;
                    btup_sendData(FALSE, FALSE, ADDR_ACK, 2, data);
                    uartState = UART_IDLE_DECODE_IDLE;
                    bleprofile_PUARTSetRxWaterlevel(1);
                }
                
                static inline void receivedACK(void)
                {
                    ble_trace0("receivedACK()");
                    //the data has already been transferred to lastReceivedByte
                    //let's check if it acked a packet sent and awaiting ACK - if not, just discard it
                    unsigned char packetACKed = getSentPacketByAddress(lastReceivedPacket.address);
                #ifndef BT_NO_ACK_NO_RESEND
                    if((sentPackets[packetACKed].sent == TRUE) && (sentPackets[packetACKed].acked == FALSE))
                #endif
                    {
                        sentPackets[packetACKed].acked = TRUE;
                        sentPackets[packetACKed].sent = FALSE;
                        sentPackets[packetACKed].resendCounter = 0;
                        sentPackets[packetACKed].timeoutCounter = 0;
                    }
                    resetLastReceivedPacket(FALSE);
                    uartState = UART_IDLE_DECODE_IDLE;
                    bleprofile_PUARTSetRxWaterlevel(1);
                }
                
                static void notificationWithDB(UINT16 handle, unsigned char *data, unsigned char length, BOOL notify, BOOL writeToDB)
                {
                    unsigned int i;
                    BLEPROFILE_DB_PDU tempPDU;
                    if((notify == TRUE) && (writeToDB == TRUE))
                    {
                        ble_trace2("notificationWithDB(%#04x, *data, %u, TRUE, TRUE)", handle, length);
                    } else if((notify == FALSE) && (writeToDB == TRUE))
                    {
                        ble_trace2("notificationWithDB(%#04x, *data, %u, FALSE, TRUE)", handle, length);
                    } else if((notify == TRUE) && (writeToDB == FALSE))
                    {
                        ble_trace2("notificationWithDB(%#04x, *data, %u, TRUE, FALSE)", handle, length);
                    } else if((notify == FALSE) && (writeToDB == FALSE))
                    {
                        ble_trace2("notificationWithDB(%#04x, *data, %u, FALSE, FALSE)", handle, length);
                    }
                    if(length > 0)
                    {
                        if(writeToDB == TRUE)
                        {
                            memset(&tempPDU, 0, sizeof(tempPDU)); //init/zero pad tempPDU
                            i = bleprofile_ReadHandle(handle, &tempPDU); //load tempPDU from actual handle
                            if(length > tempPDU.len)
                            {
                                memcpy(tempPDU.pdu, data, tempPDU.len); //truncate data
                            } else
                            {
                                memcpy(tempPDU.pdu, data, length);
                            }
                            bleprofile_WriteHandle(handle, &tempPDU);
                        }
                        if ((notify == TRUE) && (blecm_getAvailableTxBuffers() > 0))
                        {
                            bleprofile_sendNotification(handle, data, (INT32) length);
                        }
                    }
                }
                
                static void traceAddress(ADDRESS_TYPE addr)
                {
                    switch(addr)
                    {
                    case ADDR_ACK:
                        ble_trace1("%#04x is ADDR_ACK", addr);
                        break;
                    case ADDR_COMMAND:
                        ble_trace1("%#04x is ADDR_COMMAND", addr);
                        break;
                    case ADDR_CHAR_GLOBAL_STATUS:
                        ble_trace1("%#04x is ADDR_CHAR_GLOBAL_STATUS", addr);
                        break;
                    case ADDR_CHAR_TCAS_SECOND_PACKET:
                        ble_trace1("%#04x is ADDR_CHAR_TCAS_SECOND_PACKET", addr);
                        break;
                    case ADDR_CHAR_FDAMS_SECOND_PACKET:
                        ble_trace1("%#04x is ADDR_CHAR_FDAMS_SECOND_PACKET", addr);
                        break;
                    case ADDR_CHAR_SSMC:
                        ble_trace1("%#04x is ADDR_CHAR_SSMC", addr);
                        break;
                    case ADDR_CHAR_DATA_WRITE_TO_BLE_0:
                        ble_trace1("%#04x is ADDR_CHAR_DATA_WRITE_TO_BLE_0", addr);
                        break;
                    case ADDR_CHAR_DATA_WRITE_TO_BLE_1:
                        ble_trace1("%#04x is ADDR_CHAR_DATA_WRITE_TO_BLE_1", addr);
                        break;
                    case ADDR_CHAR_DATA_WRITE_TO_BLE_2:
                        ble_trace1("%#04x is ADDR_CHAR_DATA_WRITE_TO_BLE_2", addr);
                        break;
                    case ADDR_CHAR_DATA_WRITE_TO_BLE_3:
                        ble_trace1("%#04x is ADDR_CHAR_DATA_WRITE_TO_BLE_3", addr);
                        break;
                    case ADDR_CHAR_DATA_READ_FROM_BLE_0_SECOND_PACKET:
                        ble_trace1("%#04x is ADDR_CHAR_DATA_READ_FROM_BLE_0_SECOND_PACKET", addr);
                        break;
                    case ADDR_CHAR_DATA_READ_FROM_BLE_1_SECOND_PACKET:
                        ble_trace1("%#04x is ADDR_CHAR_DATA_READ_FROM_BLE_1_SECOND_PACKET", addr);
                        break;
                    case ADDR_CHAR_DATA_READ_FROM_BLE_2_SECOND_PACKET:
                        ble_trace1("%#04x is ADDR_CHAR_DATA_READ_FROM_BLE_2_SECOND_PACKET", addr);
                        break;
                    case ADDR_CHAR_DATA_READ_FROM_BLE_3_SECOND_PACKET:
                        ble_trace1("%#04x is ADDR_CHAR_DATA_READ_FROM_BLE_3_SECOND_PACKET", addr);
                        break;
                    case ADDR_CHAR_COMMAND_WRITE_TO_BLE:
                        ble_trace1("%#04x is ADDR_CHAR_COMMAND_WRITE_TO_BLE", addr);
                        break;
                    case ADDR_CHAR_COMMAND_READ_FROM_BLE:
                        ble_trace1("%#04x is ADDR_CHAR_COMMAND_READ_FROM_BLE", addr);
                        break;
                    case ADDR_CHAR_TCAS:
                        ble_trace1("%#04x is ADDR_CHAR_TCAS", addr);
                        break;
                    case ADDR_CHAR_FDAMS:
                        ble_trace1("%#04x is ADDR_CHAR_FDAMS", addr);
                        break;
                    case ADDR_CHAR_DATA_READ_FROM_BLE_0:
                        ble_trace1("%#04x is ADDR_CHAR_DATA_READ_FROM_BLE_0", addr);
                        break;
                    case ADDR_CHAR_DATA_READ_FROM_BLE_1:
                        ble_trace1("%#04x is ADDR_CHAR_DATA_READ_FROM_BLE_1", addr);
                        break;
                    case ADDR_CHAR_DATA_READ_FROM_BLE_2:
                        ble_trace1("%#04x is ADDR_CHAR_DATA_READ_FROM_BLE_2", addr);
                        break;
                    case ADDR_CHAR_DATA_READ_FROM_BLE_3:
                        ble_trace1("%#04x is ADDR_CHAR_DATA_READ_FROM_BLE_3", addr);
                        break;
                    }
                }
                
                static void traceHandle(unsigned int handle)
                {
                    switch(handle)
                    {
                    case HDLC_GENERIC_ACCESS_DEVICE_NAME_VALUE:
                        ble_trace1("%#05x is HDLC_GENERIC_ACCESS_DEVICE_NAME_VALUE", handle);
                        break;
                    case HDLC_GENERIC_ACCESS_APPEARANCE_VALUE:
                        ble_trace1("%#05x is HDLC_GENERIC_ACCESS_APPEARANCE_VALUE", handle);
                        break;
                    case HDLC_TTL_SERVICE_GLOBAL_STATUS_VALUE:
                        ble_trace1("%#05x is HDLC_TTL_SERVICE_GLOBAL_STATUS_VALUE", handle);
                        break;
                    case HDLC_TTL_SERVICE_TCAS_VALUE:
                        ble_trace1("%#05x is HDLC_TTL_SERVICE_TCAS_VALUE", handle);
                        break;
                    case HDLC_TTL_SERVICE_FDAMS_VALUE:
                        ble_trace1("%#05x is HDLC_TTL_SERVICE_FDAMS_VALUE", handle);
                        break;
                    case HDLC_TTL_SERVICE_SSMC_VALUE:
                        ble_trace1("%#05x is HDLC_TTL_SERVICE_SSMC_VALUE", handle);
                        break;
                    case HDLC_TTL_ENHANCEMENT_SERVICE_DATA_WRITE_TO_BLE_0_VALUE:
                        ble_trace1("%#05x is HDLC_TTL_ENHANCEMENT_SERVICE_DATA_WRITE_TO_BLE_0_VALUE", handle);
                        break;
                    case HDLC_TTL_ENHANCEMENT_SERVICE_DATA_WRITE_TO_BLE_1_VALUE:
                        ble_trace1("%#05x is HDLC_TTL_ENHANCEMENT_SERVICE_DATA_WRITE_TO_BLE_1_VALUE", handle);
                        break;
                    case HDLC_TTL_ENHANCEMENT_SERVICE_DATA_WRITE_TO_BLE_2_VALUE:
                        ble_trace1("%#05x is HDLC_TTL_ENHANCEMENT_SERVICE_DATA_WRITE_TO_BLE_2_VALUE", handle);
                        break;
                    case HDLC_TTL_ENHANCEMENT_SERVICE_DATA_WRITE_TO_BLE_3_VALUE:
                        ble_trace1("%#05x is HDLC_TTL_ENHANCEMENT_SERVICE_DATA_WRITE_TO_BLE_3_VALUE", handle);
                        break;
                    case HDLC_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_0_VALUE:
                        ble_trace1("%#05x is HDLC_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_0_VALUE", handle);
                        break;
                    case HDLC_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_1_VALUE:
                        ble_trace1("%#05x is HDLC_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_1_VALUE", handle);
                        break;
                    case HDLC_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_2_VALUE:
                        ble_trace1("%#05x is HDLC_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_2_VALUE", handle);
                        break;
                    case HDLC_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_3_VALUE:
                        ble_trace1("%#05x is HDLC_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_3_VALUE", handle);
                        break;
                    case HDLC_TTL_ENHANCEMENT_SERVICE_COMMAND_WRITE_TO_BLE_VALUE:
                        ble_trace1("%#05x is HDLC_TTL_ENHANCEMENT_SERVICE_COMMAND_WRITE_TO_BLE_VALUE", handle);
                        break;
                    case HDLC_TTL_ENHANCEMENT_SERVICE_COMMAND_READ_FROM_BLE_VALUE:
                        ble_trace1("%#05x is HDLC_TTL_ENHANCEMENT_SERVICE_COMMAND_READ_FROM_BLE_VALUE", handle);
                        break;
                    case HDLC_TTL_OTA_UPDATE_SERVICE_CONTROL_POINT_VALUE:
                        ble_trace1("%#05x is HDLC_TTL_OTA_UPDATE_SERVICE_CONTROL_POINT_VALUE", handle);
                        break;
                    case HDLC_TTL_OTA_UPDATE_SERVICE_DATA_VALUE:
                        ble_trace1("%#05x is HDLC_TTL_OTA_UPDATE_SERVICE_DATA_VALUE", handle);
                        break;
                    case HDLC_TTL_OTA_UPDATE_SERVICE_UPDATE_APP_INFO_VALUE:
                        ble_trace1("%#05x is HDLC_TTL_OTA_UPDATE_SERVICE_UPDATE_APP_INFO_VALUE", handle);
                        break;
                    }
                }
                
                
                
                
                
                

                 

                crc.h
                /*
                * crc.h
                *
                * Code generated by universal_crc by Danjel McGougan
                *
                * CRC parameters used:
                *   bits:       8
                *   poly:       0x9c
                *   init:       0x5a
                *   xor:        0x00
                *   reverse:    false
                *   non-direct: false
                *
                * CRC of the string "123456789" is 0x18
                */
                
                #ifndef CRC_H_
                #define CRC_H_
                
                #include <stddef.h>
                #include <stdint.h>
                
                uint8_t crc_calc(const uint8_t *data, size_t len);
                
                extern const uint8_t crc_table[1024];
                
                static inline uint8_t crc_init(void)
                {
                    return 0x5a;
                }
                
                static inline uint8_t crc_next(uint8_t crc, uint8_t data)
                {
                    return crc_table[crc ^ data];
                }
                
                /*
                * Process 4 bytes in one go
                * The data parameter must contain all 4 bytes;
                */
                static inline uint8_t crc_next4(uint8_t crc, uint32_t data)
                {
                    crc ^= data & 0xff;
                    crc =
                        crc_table[(crc & 0xff) + 0x300] ^
                        crc_table[((data >> 8) & 0xff) + 0x200] ^
                        crc_table[((data >> 16) & 0xff) + 0x100] ^
                        crc_table[data >> 24];
                    return crc;
                }
                
                static inline uint8_t crc_final(uint8_t crc)
                {
                    return crc;
                }
                
                #endif
                
                
                
                
                
                

                 

                crc.c
                #include "crc.h"
                
                const uint8_t crc_table[1024] = {
                    0x00, 0x9c, 0xa4, 0x38, 0xd4, 0x48, 0x70, 0xec,
                    0x34, 0xa8, 0x90, 0x0c, 0xe0, 0x7c, 0x44, 0xd8,
                    0x68, 0xf4, 0xcc, 0x50, 0xbc, 0x20, 0x18, 0x84,
                    0x5c, 0xc0, 0xf8, 0x64, 0x88, 0x14, 0x2c, 0xb0,
                    0xd0, 0x4c, 0x74, 0xe8, 0x04, 0x98, 0xa0, 0x3c,
                    0xe4, 0x78, 0x40, 0xdc, 0x30, 0xac, 0x94, 0x08,
                    0xb8, 0x24, 0x1c, 0x80, 0x6c, 0xf0, 0xc8, 0x54,
                    0x8c, 0x10, 0x28, 0xb4, 0x58, 0xc4, 0xfc, 0x60,
                    0x3c, 0xa0, 0x98, 0x04, 0xe8, 0x74, 0x4c, 0xd0,
                    0x08, 0x94, 0xac, 0x30, 0xdc, 0x40, 0x78, 0xe4,
                    0x54, 0xc8, 0xf0, 0x6c, 0x80, 0x1c, 0x24, 0xb8,
                    0x60, 0xfc, 0xc4, 0x58, 0xb4, 0x28, 0x10, 0x8c,
                    0xec, 0x70, 0x48, 0xd4, 0x38, 0xa4, 0x9c, 0x00,
                    0xd8, 0x44, 0x7c, 0xe0, 0x0c, 0x90, 0xa8, 0x34,
                    0x84, 0x18, 0x20, 0xbc, 0x50, 0xcc, 0xf4, 0x68,
                    0xb0, 0x2c, 0x14, 0x88, 0x64, 0xf8, 0xc0, 0x5c,
                    0x78, 0xe4, 0xdc, 0x40, 0xac, 0x30, 0x08, 0x94,
                    0x4c, 0xd0, 0xe8, 0x74, 0x98, 0x04, 0x3c, 0xa0,
                    0x10, 0x8c, 0xb4, 0x28, 0xc4, 0x58, 0x60, 0xfc,
                    0x24, 0xb8, 0x80, 0x1c, 0xf0, 0x6c, 0x54, 0xc8,
                    0xa8, 0x34, 0x0c, 0x90, 0x7c, 0xe0, 0xd8, 0x44,
                    0x9c, 0x00, 0x38, 0xa4, 0x48, 0xd4, 0xec, 0x70,
                    0xc0, 0x5c, 0x64, 0xf8, 0x14, 0x88, 0xb0, 0x2c,
                    0xf4, 0x68, 0x50, 0xcc, 0x20, 0xbc, 0x84, 0x18,
                    0x44, 0xd8, 0xe0, 0x7c, 0x90, 0x0c, 0x34, 0xa8,
                    0x70, 0xec, 0xd4, 0x48, 0xa4, 0x38, 0x00, 0x9c,
                    0x2c, 0xb0, 0x88, 0x14, 0xf8, 0x64, 0x5c, 0xc0,
                    0x18, 0x84, 0xbc, 0x20, 0xcc, 0x50, 0x68, 0xf4,
                    0x94, 0x08, 0x30, 0xac, 0x40, 0xdc, 0xe4, 0x78,
                    0xa0, 0x3c, 0x04, 0x98, 0x74, 0xe8, 0xd0, 0x4c,
                    0xfc, 0x60, 0x58, 0xc4, 0x28, 0xb4, 0x8c, 0x10,
                    0xc8, 0x54, 0x6c, 0xf0, 0x1c, 0x80, 0xb8, 0x24,
                    0x00, 0xf0, 0x7c, 0x8c, 0xf8, 0x08, 0x84, 0x74,
                    0x6c, 0x9c, 0x10, 0xe0, 0x94, 0x64, 0xe8, 0x18,
                    0xd8, 0x28, 0xa4, 0x54, 0x20, 0xd0, 0x5c, 0xac,
                    0xb4, 0x44, 0xc8, 0x38, 0x4c, 0xbc, 0x30, 0xc0,
                    0x2c, 0xdc, 0x50, 0xa0, 0xd4, 0x24, 0xa8, 0x58,
                    0x40, 0xb0, 0x3c, 0xcc, 0xb8, 0x48, 0xc4, 0x34,
                    0xf4, 0x04, 0x88, 0x78, 0x0c, 0xfc, 0x70, 0x80,
                    0x98, 0x68, 0xe4, 0x14, 0x60, 0x90, 0x1c, 0xec,
                    0x58, 0xa8, 0x24, 0xd4, 0xa0, 0x50, 0xdc, 0x2c,
                    0x34, 0xc4, 0x48, 0xb8, 0xcc, 0x3c, 0xb0, 0x40,
                    0x80, 0x70, 0xfc, 0x0c, 0x78, 0x88, 0x04, 0xf4,
                    0xec, 0x1c, 0x90, 0x60, 0x14, 0xe4, 0x68, 0x98,
                    0x74, 0x84, 0x08, 0xf8, 0x8c, 0x7c, 0xf0, 0x00,
                    0x18, 0xe8, 0x64, 0x94, 0xe0, 0x10, 0x9c, 0x6c,
                    0xac, 0x5c, 0xd0, 0x20, 0x54, 0xa4, 0x28, 0xd8,
                    0xc0, 0x30, 0xbc, 0x4c, 0x38, 0xc8, 0x44, 0xb4,
                    0xb0, 0x40, 0xcc, 0x3c, 0x48, 0xb8, 0x34, 0xc4,
                    0xdc, 0x2c, 0xa0, 0x50, 0x24, 0xd4, 0x58, 0xa8,
                    0x68, 0x98, 0x14, 0xe4, 0x90, 0x60, 0xec, 0x1c,
                    0x04, 0xf4, 0x78, 0x88, 0xfc, 0x0c, 0x80, 0x70,
                    0x9c, 0x6c, 0xe0, 0x10, 0x64, 0x94, 0x18, 0xe8,
                    0xf0, 0x00, 0x8c, 0x7c, 0x08, 0xf8, 0x74, 0x84,
                    0x44, 0xb4, 0x38, 0xc8, 0xbc, 0x4c, 0xc0, 0x30,
                    0x28, 0xd8, 0x54, 0xa4, 0xd0, 0x20, 0xac, 0x5c,
                    0xe8, 0x18, 0x94, 0x64, 0x10, 0xe0, 0x6c, 0x9c,
                    0x84, 0x74, 0xf8, 0x08, 0x7c, 0x8c, 0x00, 0xf0,
                    0x30, 0xc0, 0x4c, 0xbc, 0xc8, 0x38, 0xb4, 0x44,
                    0x5c, 0xac, 0x20, 0xd0, 0xa4, 0x54, 0xd8, 0x28,
                    0xc4, 0x34, 0xb8, 0x48, 0x3c, 0xcc, 0x40, 0xb0,
                    0xa8, 0x58, 0xd4, 0x24, 0x50, 0xa0, 0x2c, 0xdc,
                    0x1c, 0xec, 0x60, 0x90, 0xe4, 0x14, 0x98, 0x68,
                    0x70, 0x80, 0x0c, 0xfc, 0x88, 0x78, 0xf4, 0x04,
                    0x00, 0xfc, 0x64, 0x98, 0xc8, 0x34, 0xac, 0x50,
                    0x0c, 0xf0, 0x68, 0x94, 0xc4, 0x38, 0xa0, 0x5c,
                    0x18, 0xe4, 0x7c, 0x80, 0xd0, 0x2c, 0xb4, 0x48,
                    0x14, 0xe8, 0x70, 0x8c, 0xdc, 0x20, 0xb8, 0x44,
                    0x30, 0xcc, 0x54, 0xa8, 0xf8, 0x04, 0x9c, 0x60,
                    0x3c, 0xc0, 0x58, 0xa4, 0xf4, 0x08, 0x90, 0x6c,
                    0x28, 0xd4, 0x4c, 0xb0, 0xe0, 0x1c, 0x84, 0x78,
                    0x24, 0xd8, 0x40, 0xbc, 0xec, 0x10, 0x88, 0x74,
                    0x60, 0x9c, 0x04, 0xf8, 0xa8, 0x54, 0xcc, 0x30,
                    0x6c, 0x90, 0x08, 0xf4, 0xa4, 0x58, 0xc0, 0x3c,
                    0x78, 0x84, 0x1c, 0xe0, 0xb0, 0x4c, 0xd4, 0x28,
                    0x74, 0x88, 0x10, 0xec, 0xbc, 0x40, 0xd8, 0x24,
                    0x50, 0xac, 0x34, 0xc8, 0x98, 0x64, 0xfc, 0x00,
                    0x5c, 0xa0, 0x38, 0xc4, 0x94, 0x68, 0xf0, 0x0c,
                    0x48, 0xb4, 0x2c, 0xd0, 0x80, 0x7c, 0xe4, 0x18,
                    0x44, 0xb8, 0x20, 0xdc, 0x8c, 0x70, 0xe8, 0x14,
                    0xc0, 0x3c, 0xa4, 0x58, 0x08, 0xf4, 0x6c, 0x90,
                    0xcc, 0x30, 0xa8, 0x54, 0x04, 0xf8, 0x60, 0x9c,
                    0xd8, 0x24, 0xbc, 0x40, 0x10, 0xec, 0x74, 0x88,
                    0xd4, 0x28, 0xb0, 0x4c, 0x1c, 0xe0, 0x78, 0x84,
                    0xf0, 0x0c, 0x94, 0x68, 0x38, 0xc4, 0x5c, 0xa0,
                    0xfc, 0x00, 0x98, 0x64, 0x34, 0xc8, 0x50, 0xac,
                    0xe8, 0x14, 0x8c, 0x70, 0x20, 0xdc, 0x44, 0xb8,
                    0xe4, 0x18, 0x80, 0x7c, 0x2c, 0xd0, 0x48, 0xb4,
                    0xa0, 0x5c, 0xc4, 0x38, 0x68, 0x94, 0x0c, 0xf0,
                    0xac, 0x50, 0xc8, 0x34, 0x64, 0x98, 0x00, 0xfc,
                    0xb8, 0x44, 0xdc, 0x20, 0x70, 0x8c, 0x14, 0xe8,
                    0xb4, 0x48, 0xd0, 0x2c, 0x7c, 0x80, 0x18, 0xe4,
                    0x90, 0x6c, 0xf4, 0x08, 0x58, 0xa4, 0x3c, 0xc0,
                    0x9c, 0x60, 0xf8, 0x04, 0x54, 0xa8, 0x30, 0xcc,
                    0x88, 0x74, 0xec, 0x10, 0x40, 0xbc, 0x24, 0xd8,
                    0x84, 0x78, 0xe0, 0x1c, 0x4c, 0xb0, 0x28, 0xd4,
                    0x00, 0x1c, 0x38, 0x24, 0x70, 0x6c, 0x48, 0x54,
                    0xe0, 0xfc, 0xd8, 0xc4, 0x90, 0x8c, 0xa8, 0xb4,
                    0x5c, 0x40, 0x64, 0x78, 0x2c, 0x30, 0x14, 0x08,
                    0xbc, 0xa0, 0x84, 0x98, 0xcc, 0xd0, 0xf4, 0xe8,
                    0xb8, 0xa4, 0x80, 0x9c, 0xc8, 0xd4, 0xf0, 0xec,
                    0x58, 0x44, 0x60, 0x7c, 0x28, 0x34, 0x10, 0x0c,
                    0xe4, 0xf8, 0xdc, 0xc0, 0x94, 0x88, 0xac, 0xb0,
                    0x04, 0x18, 0x3c, 0x20, 0x74, 0x68, 0x4c, 0x50,
                    0xec, 0xf0, 0xd4, 0xc8, 0x9c, 0x80, 0xa4, 0xb8,
                    0x0c, 0x10, 0x34, 0x28, 0x7c, 0x60, 0x44, 0x58,
                    0xb0, 0xac, 0x88, 0x94, 0xc0, 0xdc, 0xf8, 0xe4,
                    0x50, 0x4c, 0x68, 0x74, 0x20, 0x3c, 0x18, 0x04,
                    0x54, 0x48, 0x6c, 0x70, 0x24, 0x38, 0x1c, 0x00,
                    0xb4, 0xa8, 0x8c, 0x90, 0xc4, 0xd8, 0xfc, 0xe0,
                    0x08, 0x14, 0x30, 0x2c, 0x78, 0x64, 0x40, 0x5c,
                    0xe8, 0xf4, 0xd0, 0xcc, 0x98, 0x84, 0xa0, 0xbc,
                    0x44, 0x58, 0x7c, 0x60, 0x34, 0x28, 0x0c, 0x10,
                    0xa4, 0xb8, 0x9c, 0x80, 0xd4, 0xc8, 0xec, 0xf0,
                    0x18, 0x04, 0x20, 0x3c, 0x68, 0x74, 0x50, 0x4c,
                    0xf8, 0xe4, 0xc0, 0xdc, 0x88, 0x94, 0xb0, 0xac,
                    0xfc, 0xe0, 0xc4, 0xd8, 0x8c, 0x90, 0xb4, 0xa8,
                    0x1c, 0x00, 0x24, 0x38, 0x6c, 0x70, 0x54, 0x48,
                    0xa0, 0xbc, 0x98, 0x84, 0xd0, 0xcc, 0xe8, 0xf4,
                    0x40, 0x5c, 0x78, 0x64, 0x30, 0x2c, 0x08, 0x14,
                    0xa8, 0xb4, 0x90, 0x8c, 0xd8, 0xc4, 0xe0, 0xfc,
                    0x48, 0x54, 0x70, 0x6c, 0x38, 0x24, 0x00, 0x1c,
                    0xf4, 0xe8, 0xcc, 0xd0, 0x84, 0x98, 0xbc, 0xa0,
                    0x14, 0x08, 0x2c, 0x30, 0x64, 0x78, 0x5c, 0x40,
                    0x10, 0x0c, 0x28, 0x34, 0x60, 0x7c, 0x58, 0x44,
                    0xf0, 0xec, 0xc8, 0xd4, 0x80, 0x9c, 0xb8, 0xa4,
                    0x4c, 0x50, 0x74, 0x68, 0x3c, 0x20, 0x04, 0x18,
                    0xac, 0xb0, 0x94, 0x88, 0xdc, 0xc0, 0xe4, 0xf8
                };
                
                uint8_t crc_calc(const uint8_t *data, size_t len)
                {
                    uint8_t crc;
                
                    crc = crc_init();
                
                    while (((uintptr_t)data & 3) && len) {
                        crc = crc_next(crc, *data++);
                        len--;
                    }
                
                    while (len >= 16) {
                        len -= 16;
                        crc = crc_next4(crc, ((uint32_t *)data)[0]);
                        crc = crc_next4(crc, ((uint32_t *)data)[1]);
                        crc = crc_next4(crc, ((uint32_t *)data)[2]);
                        crc = crc_next4(crc, ((uint32_t *)data)[3]);
                        data += 16;
                    }
                
                    while (len--) {
                        crc = crc_next(crc, *data++);
                    }
                
                    return crc_final(crc);
                }
                
                
                
                
                
                

                 

                gpio_ttl.h
                #ifndef __GPIO_TTL_H__
                #define __GPIO_TTL_H__
                
                #include "types.h"
                
                //GPIO pin number
                #define GPIO_P1_PIN             (1)
                #define GPIO_P2_PIN             (2)
                #define GPIO_P3_PIN             (3)
                #define GPIO_P4_PIN             (4)
                #define GPIO_P8_PIN             (8)
                #define GPIO_P11_PIN        (11)
                #define GPIO_P12_PIN        (12)
                #define GPIO_P13_P28_PIN    (13) //16mA
                #define GPIO_P14_P38_PIN    (14)
                #define GPIO_P15_PIN        (15)
                #define GPIO_P24_PIN         (8)
                #define GPIO_P25_PIN         (9)
                #define GPIO_P26_PIN        (10) //16mA
                #define GPIO_P27_PIN        (11) //16mA
                #define GPIO_P28_P13_PIN    (12) //16mA
                #define GPIO_P32_PIN         (0) //PUART_TX
                #define GPIO_P33_PIN         (1) //PUART_RX
                #define GPIO_P38_P14_PIN     (6)
                
                //GPIO bit mask
                #define GPIO_P1_BIT            (0x0002)
                #define GPIO_P2_BIT            (0x0004)
                #define GPIO_P3_BIT            (0x0008)
                #define GPIO_P4_BIT            (0x0010)
                #define GPIO_P8_BIT            (0x0100)
                #define GPIO_P11_BIT        (0x0800)
                #define GPIO_P12_BIT        (0x1000)
                #define GPIO_P13_P28_BIT    (0x2000) //16mA
                #define GPIO_P14_P38_BIT    (0x4000)
                #define GPIO_P15_BIT        (0x8000)
                #define GPIO_P24_BIT        (0x0100)
                #define GPIO_P25_BIT        (0x0200)
                #define GPIO_P26_BIT        (0x0400) //16mA
                #define GPIO_P27_BIT        (0x0800) //16mA
                #define GPIO_P28_P13_BIT    (0x1000) //16mA
                #define GPIO_P32_BIT        (0x0001) //PUART_TX
                #define GPIO_P33_BIT        (0x0002) //PUART_RX
                #define GPIO_P38_P14_BIT    (0x0040)
                
                //GPIO port number
                #define GPIO_P1_PORT         (0)
                #define GPIO_P2_PORT         (0)
                #define GPIO_P3_PORT         (0)
                #define GPIO_P4_PORT         (0)
                #define GPIO_P8_PORT         (0)
                #define GPIO_P11_PORT         (0)
                #define GPIO_P12_PORT         (0)
                #define GPIO_P13_P28_PORT     (0)
                #define GPIO_P14_P38_PORT     (0)
                #define GPIO_P15_PORT         (0)
                #define GPIO_P24_PORT         (1)
                #define GPIO_P25_PORT         (1)
                #define GPIO_P26_PORT         (1)
                #define GPIO_P27_PORT         (1)
                #define GPIO_P28_P13_PORT     (1)
                #define GPIO_P32_PORT         (2)
                #define GPIO_P33_PORT         (2)
                #define GPIO_P38_P14_PORT     (2)
                
                #define SW_2V8_PIN      (GPIO_P4_PIN)
                #define SW_3V7_PIN      (GPIO_P3_PIN)
                #define PA0_WKUP_PIN    (GPIO_P8_PIN)
                #define EN_3V3_PIN      (GPIO_P15_PIN)
                #define LED_BL_PIN      (GPIO_P13_P28_PIN)
                #define SPI2_SCK_PIN    (GPIO_P24_PIN)
                #define SPI2_CS_PIN     (GPIO_P26_PIN)
                #define SPI2_MISO_PIN   (GPIO_P25_PIN)
                #define SPI2_MOSI_PIN   (GPIO_P27_PIN)
                
                #define SW_2V8_BIT      (GPIO_P4_BIT)
                #define SW_3V7_BIT      (GPIO_P3_BIT)
                #define PA0_WKUP_BIT    (GPIO_P8_BIT)
                #define EN_3V3_BIT      (GPIO_P15_BIT)
                #define LED_BL_BIT      (GPIO_P13_P28_BIT)
                #define SPI2_SCK_BIT    (GPIO_P24_BIT)
                #define SPI2_CS_BIT     (GPIO_P26_BIT)
                #define SPI2_MISO_BIT   (GPIO_P25_BIT)
                #define SPI2_MOSI_BIT   (GPIO_P27_BIT)
                
                #define SW_2V8_PORT     (GPIO_P4_PORT)
                #define SW_3V7_PORT     (GPIO_P3_PORT)
                #define PA0_WKUP_PORT   (GPIO_P25_PORT)
                #define EN_3V3_PORT     (GPIO_P15_PORT)
                #define LED_BL_PORT     (GPIO_P13_P28_PORT)
                #define SPI2_SCK_PORT   (GPIO_P24_PORT)
                #define SPI2_CS_PORT    (GPIO_P26_PORT)
                #define SPI2_MISO_PORT  (GPIO_P25_PORT)
                #define SPI2_MOSI_PORT  (GPIO_P27_PORT)
                
                void enableLED(BOOL enable);
                void enable3V7_SW(BOOL enable);
                void enable2V8_SW(BOOL enable);
                void enable3V3(BOOL enable);
                void enableWKUP(BOOL enable);
                
                BOOL getStatusLED(void);
                BOOL getStatus3V7_SW(void);
                BOOL getStatus2V8_SW(void);
                BOOL getStatus3V3(void);
                
                #endif
                
                
                
                
                
                

                 

                gpio_ttl.c
                #include "gpiodriver.h"
                #include "gpio_ttl.h"
                #include "types.h"
                
                void enableLED(BOOL enable)
                {
                    UINT16 tempPortOutput = gpio_getPortOutput(LED_BL_PORT);
                    if(enable == FALSE)
                    {
                        tempPortOutput &= ~(LED_BL_BIT);
                        gpio_setPortOutput(LED_BL_PORT, tempPortOutput);
                    } else
                    {
                        tempPortOutput |= LED_BL_BIT;
                        gpio_setPortOutput(LED_BL_PORT, tempPortOutput);
                    }
                }
                
                void enable3V7_SW(BOOL enable)
                {
                    UINT16 tempPortOutput = gpio_getPortOutput(SW_3V7_PORT);
                    if(enable == FALSE)
                    {
                        tempPortOutput &= ~(SW_3V7_BIT);
                        gpio_setPortOutput(SW_3V7_PORT, tempPortOutput);
                    } else
                    {
                        tempPortOutput |= SW_3V7_BIT;
                        gpio_setPortOutput(SW_3V7_PORT, tempPortOutput);
                    }
                }
                
                void enable2V8_SW(BOOL enable)
                {
                    UINT16 tempPortOutput = gpio_getPortOutput(SW_2V8_PORT);
                    if(enable == FALSE)
                    {
                        tempPortOutput &= ~(SW_2V8_BIT);
                        gpio_setPortOutput(SW_2V8_PORT, tempPortOutput);
                    } else
                    {
                        tempPortOutput |= SW_2V8_BIT;
                        gpio_setPortOutput(SW_2V8_PORT, tempPortOutput);
                    }
                }
                
                void enable3V3(BOOL enable)
                {
                    UINT16 tempPortOutput = gpio_getPortOutput(EN_3V3_PORT);
                    if(enable == FALSE)
                    {
                        tempPortOutput &= ~(EN_3V3_BIT);
                        gpio_setPortOutput(EN_3V3_PORT, tempPortOutput);
                    } else
                    {
                        tempPortOutput |= EN_3V3_BIT;
                        gpio_setPortOutput(EN_3V3_PORT, tempPortOutput);
                    }
                }
                
                void enableWKUP(BOOL enable)
                {
                    UINT16 tempPortOutput = gpio_getPortOutput(PA0_WKUP_PORT);
                    if(enable == FALSE)
                    {
                        tempPortOutput &= ~(PA0_WKUP_PIN);
                        gpio_setPortOutput(PA0_WKUP_PORT, tempPortOutput);
                    } else
                    {
                        tempPortOutput |= PA0_WKUP_PIN;
                        gpio_setPortOutput(PA0_WKUP_PORT, tempPortOutput);
                    }
                }
                
                BOOL getStatusLED(void)
                {
                    UINT16 tempPortOutput = gpio_getPortOutput(LED_BL_PORT);
                    if(tempPortOutput & LED_BL_BIT == 0)
                    {
                        return FALSE;
                    } else
                    {
                        return TRUE;
                    }
                }
                
                BOOL getStatus3V7_SW(void)
                {
                    UINT16 tempPortOutput = gpio_getPortOutput(SW_3V7_PORT);
                    if(tempPortOutput & SW_3V7_BIT == 0)
                    {
                        return FALSE;
                    } else
                    {
                        return TRUE;
                    }
                }
                
                BOOL getStatus2V8_SW(void)
                {
                    UINT16 tempPortOutput = gpio_getPortOutput(SW_2V8_PORT);
                    if(tempPortOutput & SW_2V8_BIT == 0)
                    {
                        return FALSE;
                    } else
                    {
                        return TRUE;
                    }
                }
                
                BOOL getStatus3V3(void)
                {
                    UINT16 tempPortOutput = gpio_getPortOutput(EN_3V3_PORT);
                    if(tempPortOutput & EN_3V3_BIT == 0)
                    {
                        return FALSE;
                    } else
                    {
                        return TRUE;
                    }
                }
                
                
                
                
                
                

                 

                ttl_db.h
                /*
                * This file has been automatically generated by the WICED Smart Designer.
                * Definitions for constants used in the device's GATT database and function
                * prototypes that can be used to send notifications
                *
                */
                
                // ttl_db.h
                
                // Maximum number of bonded peers
                #define GATT_DB_MAX_BONDED_PEERS 5
                // ***** Primary service 'Generic Access'
                #define HDLS_GENERIC_ACCESS                                                                  0x0100
                #define UUID_SERVICE_GAP                                                                     0x1800
                // ----- Characteristic 'Device Name'
                #define HDLC_GENERIC_ACCESS_DEVICE_NAME                                                      0x0110
                #define HDLC_GENERIC_ACCESS_DEVICE_NAME_VALUE                                                0x0111
                #define UUID_CHARACTERISTIC_DEVICE_NAME                                                      0x2A00
                // ----- Characteristic 'Appearance'
                #define HDLC_GENERIC_ACCESS_APPEARANCE                                                       0x0120
                #define HDLC_GENERIC_ACCESS_APPEARANCE_VALUE                                                 0x0121
                #define UUID_CHARACTERISTIC_APPEARANCE                                                       0x2A01
                // ***** Primary service 'Generic Attribute'
                #define HDLS_GENERIC_ATTRIBUTE                                                               0x0200
                #define UUID_SERVICE_GATT                                                                    0x1801
                // ***** Primary service 'TTL Service'
                #define HDLS_TTL_SERVICE                                                           0x0300
                #define __UUID_TTL_SERVICE                                                         0xe6, 0xcf, 0x1d, 0x95, 0x41, 0xd1, 0xb7, 0xb1, 0xed, 0x4f, 0xc0, 0xa7, 0x00, 0x00, 0x00, 0x00
                // ----- Characteristic 'Global Status'
                #define HDLC_TTL_SERVICE_GLOBAL_STATUS                                             0x0310
                #define HDLC_TTL_SERVICE_GLOBAL_STATUS_VALUE                                       0x0311
                #define __UUID_TTL_SERVICE_GLOBAL_STATUS                                           0xe6, 0xcf, 0x1d, 0x95, 0x41, 0xd1, 0xb7, 0xb1, 0xed, 0x4f, 0xc0, 0xa7, 0x01, 0x00, 0x00, 0x00
                // Client Configuration
                #define HDLD_TTL_SERVICE_GLOBAL_STATUS_CLIENT_CONFIGURATION                        0x0320
                // ----- Characteristic 'TCAS'
                #define HDLC_TTL_SERVICE_TCAS                                 0x0330
                #define HDLC_TTL_SERVICE_TCAS_VALUE                           0x0331
                #define __UUID_TTL_SERVICE_TCAS                               0xe6, 0xcf, 0x1d, 0x95, 0x41, 0xd1, 0xb7, 0xb1, 0xed, 0x4f, 0xc0, 0xa7, 0x02, 0x00, 0x00, 0x00
                // ----- Characteristic 'FDAMS'
                #define HDLC_TTL_SERVICE_FDAMS                      0x0340
                #define HDLC_TTL_SERVICE_FDAMS_VALUE                0x0341
                #define __UUID_TTL_SERVICE_FDAMS                    0xe6, 0xcf, 0x1d, 0x95, 0x41, 0xd1, 0xb7, 0xb1, 0xed, 0x4f, 0xc0, 0xa7, 0x03, 0x00, 0x00, 0x00
                // Client Configuration
                #define HDLD_TTL_SERVICE_FDAMS_CLIENT_CONFIGURATION 0x0350
                // ----- Characteristic 'SSMC'
                #define HDLC_TTL_SERVICE_SSMC                                0x0360
                #define HDLC_TTL_SERVICE_SSMC_VALUE                          0x0361
                #define __UUID_TTL_SERVICE_SSMC                              0xe6, 0xcf, 0x1d, 0x95, 0x41, 0xd1, 0xb7, 0xb1, 0xed, 0x4f, 0xc0, 0xa7, 0x04, 0x00, 0x00, 0x00
                // ***** Primary service 'TTL Enhancement Service'
                #define HDLS_TTL_ENHANCEMENT_SERVICE                                               0x0400
                #define __UUID_TTL_ENHANCEMENT_SERVICE                                             0x45, 0x4c, 0xdb, 0xc3, 0x17, 0x7f, 0x56, 0x82, 0x60, 0x40, 0xaa, 0x4d, 0x00, 0x00, 0x00, 0x00
                // ----- Characteristic 'Data Write to BLE 0'
                #define HDLC_TTL_ENHANCEMENT_SERVICE_DATA_WRITE_TO_BLE_0                           0x0410
                #define HDLC_TTL_ENHANCEMENT_SERVICE_DATA_WRITE_TO_BLE_0_VALUE                     0x0411
                #define __UUID_TTL_ENHANCEMENT_SERVICE_DATA_WRITE_TO_BLE_0                         0x45, 0x4c, 0xdb, 0xc3, 0x17, 0x7f, 0x56, 0x82, 0x60, 0x40, 0xaa, 0x4d, 0x01, 0x00, 0x00, 0x00
                // Client Configuration
                #define HDLD_TTL_ENHANCEMENT_SERVICE_DATA_WRITE_TO_BLE_0_CLIENT_CONFIGURATION      0x0420
                // ----- Characteristic 'Data Write to BLE 1'
                #define HDLC_TTL_ENHANCEMENT_SERVICE_DATA_WRITE_TO_BLE_1                           0x0430
                #define HDLC_TTL_ENHANCEMENT_SERVICE_DATA_WRITE_TO_BLE_1_VALUE                     0x0431
                #define __UUID_TTL_ENHANCEMENT_SERVICE_DATA_WRITE_TO_BLE_1                         0x45, 0x4c, 0xdb, 0xc3, 0x17, 0x7f, 0x56, 0x82, 0x60, 0x40, 0xaa, 0x4d, 0x02, 0x00, 0x00, 0x00
                // Client Configuration
                #define HDLD_TTL_ENHANCEMENT_SERVICE_DATA_WRITE_TO_BLE_1_CLIENT_CONFIGURATION      0x0440
                // ----- Characteristic 'Data Write to BLE 2'
                #define HDLC_TTL_ENHANCEMENT_SERVICE_DATA_WRITE_TO_BLE_2                           0x0450
                #define HDLC_TTL_ENHANCEMENT_SERVICE_DATA_WRITE_TO_BLE_2_VALUE                     0x0451
                #define __UUID_TTL_ENHANCEMENT_SERVICE_DATA_WRITE_TO_BLE_2                         0x45, 0x4c, 0xdb, 0xc3, 0x17, 0x7f, 0x56, 0x82, 0x60, 0x40, 0xaa, 0x4d, 0x03, 0x00, 0x00, 0x00
                // Client Configuration
                #define HDLD_TTL_ENHANCEMENT_SERVICE_DATA_WRITE_TO_BLE_2_CLIENT_CONFIGURATION      0x0460
                // ----- Characteristic 'Data Write to BLE 3'
                #define HDLC_TTL_ENHANCEMENT_SERVICE_DATA_WRITE_TO_BLE_3                           0x0470
                #define HDLC_TTL_ENHANCEMENT_SERVICE_DATA_WRITE_TO_BLE_3_VALUE                     0x0471
                #define __UUID_TTL_ENHANCEMENT_SERVICE_DATA_WRITE_TO_BLE_3                         0x45, 0x4c, 0xdb, 0xc3, 0x17, 0x7f, 0x56, 0x82, 0x60, 0x40, 0xaa, 0x4d, 0x04, 0x00, 0x00, 0x00
                // Client Configuration
                #define HDLD_TTL_ENHANCEMENT_SERVICE_DATA_WRITE_TO_BLE_3_CLIENT_CONFIGURATION      0x0480
                // ----- Characteristic 'Data Read from BLE 0'
                #define HDLC_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_0                          0x0490
                #define HDLC_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_0_VALUE                    0x0491
                #define __UUID_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_0                        0x45, 0x4c, 0xdb, 0xc3, 0x17, 0x7f, 0x56, 0x82, 0x60, 0x40, 0xaa, 0x4d, 0x05, 0x00, 0x00, 0x00
                // Client Configuration
                #define HDLD_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_0_CLIENT_CONFIGURATION     0x04a0
                // ----- Characteristic 'Data Read from BLE 1'
                #define HDLC_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_1                          0x04b0
                #define HDLC_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_1_VALUE                    0x04b1
                #define __UUID_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_1                        0x45, 0x4c, 0xdb, 0xc3, 0x17, 0x7f, 0x56, 0x82, 0x60, 0x40, 0xaa, 0x4d, 0x06, 0x00, 0x00, 0x00
                // Client Configuration
                #define HDLD_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_1_CLIENT_CONFIGURATION     0x04c0
                // ----- Characteristic 'Data Read from BLE 2'
                #define HDLC_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_2                          0x04d0
                #define HDLC_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_2_VALUE                    0x04d1
                #define __UUID_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_2                        0x45, 0x4c, 0xdb, 0xc3, 0x17, 0x7f, 0x56, 0x82, 0x60, 0x40, 0xaa, 0x4d, 0x07, 0x00, 0x00, 0x00
                // Client Configuration
                #define HDLD_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_2_CLIENT_CONFIGURATION     0x04e0
                // ----- Characteristic 'Data Read from BLE 3'
                #define HDLC_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_3                          0x04f0
                #define HDLC_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_3_VALUE                    0x04f1
                #define __UUID_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_3                        0x45, 0x4c, 0xdb, 0xc3, 0x17, 0x7f, 0x56, 0x82, 0x60, 0x40, 0xaa, 0x4d, 0x08, 0x00, 0x00, 0x00
                // Client Configuration
                #define HDLD_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_3_CLIENT_CONFIGURATION     0x0500
                // ----- Characteristic 'Command Write to BLE'
                #define HDLC_TTL_ENHANCEMENT_SERVICE_COMMAND_WRITE_TO_BLE                          0x0510
                #define HDLC_TTL_ENHANCEMENT_SERVICE_COMMAND_WRITE_TO_BLE_VALUE                    0x0511
                #define __UUID_TTL_ENHANCEMENT_SERVICE_COMMAND_WRITE_TO_BLE                        0x45, 0x4c, 0xdb, 0xc3, 0x17, 0x7f, 0x56, 0x82, 0x60, 0x40, 0xaa, 0x4d, 0x09, 0x00, 0x00, 0x00
                // Client Configuration
                #define HDLD_TTL_ENHANCEMENT_SERVICE_COMMAND_WRITE_TO_BLE_CLIENT_CONFIGURATION     0x0520
                // ----- Characteristic 'Command Read from BLE'
                #define HDLC_TTL_ENHANCEMENT_SERVICE_COMMAND_READ_FROM_BLE                         0x0530
                #define HDLC_TTL_ENHANCEMENT_SERVICE_COMMAND_READ_FROM_BLE_VALUE                   0x0531
                #define __UUID_TTL_ENHANCEMENT_SERVICE_COMMAND_READ_FROM_BLE                       0x45, 0x4c, 0xdb, 0xc3, 0x17, 0x7f, 0x56, 0x82, 0x60, 0x40, 0xaa, 0x4d, 0x0a, 0x00, 0x00, 0x00
                // Client Configuration
                #define HDLD_TTL_ENHANCEMENT_SERVICE_COMMAND_READ_FROM_BLE_CLIENT_CONFIGURATION    0x0540
                // ***** Primary service 'TTL OTA Update Service'
                #define HDLS_TTL_OTA_UPDATE_SERVICE                                                0xff00
                #define __UUID_TTL_OTA_UPDATE_SERVICE                                              0x6a, 0x45, 0x7b, 0xdc, 0x64, 0x78, 0xdd, 0xb2, 0xec, 0x4f, 0x87, 0xc6, 0x00, 0x00, 0x00, 0x00
                // ----- Characteristic 'Control Point'
                #define HDLC_TTL_OTA_UPDATE_SERVICE_CONTROL_POINT                                  0xff01
                #define HDLC_TTL_OTA_UPDATE_SERVICE_CONTROL_POINT_VALUE                            0xff02
                #define __UUID_TTL_OTA_UPDATE_SERVICE_CONTROL_POINT                                0x6a, 0x45, 0x7b, 0xdc, 0x64, 0x78, 0xdd, 0xb2, 0xec, 0x4f, 0x87, 0xc6, 0x01, 0x00, 0x00, 0x00
                // Client Configuration
                #define HDLD_TTL_OTA_UPDATE_SERVICE_CONTROL_POINT_CLIENT_CONFIGURATION             0xff03
                // ----- Characteristic 'Data'
                #define HDLC_TTL_OTA_UPDATE_SERVICE_DATA                                           0xff04
                #define HDLC_TTL_OTA_UPDATE_SERVICE_DATA_VALUE                                     0xff05
                #define __UUID_TTL_OTA_UPDATE_SERVICE_DATA                                         0x6a, 0x45, 0x7b, 0xdc, 0x64, 0x78, 0xdd, 0xb2, 0xec, 0x4f, 0x87, 0xc6, 0x02, 0x00, 0x00, 0x00
                // ----- Characteristic 'Update App Info'
                #define HDLC_TTL_OTA_UPDATE_SERVICE_UPDATE_APP_INFO                                0xff06
                #define HDLC_TTL_OTA_UPDATE_SERVICE_UPDATE_APP_INFO_VALUE                          0xff07
                #define __UUID_TTL_OTA_UPDATE_SERVICE_UPDATE_APP_INFO                              0x6a, 0x45, 0x7b, 0xdc, 0x64, 0x78, 0xdd, 0xb2, 0xec, 0x4f, 0x87, 0xc6, 0x03, 0x00, 0x00, 0x00
                
                #pragma pack(1)
                // Host information for NVRAM
                typedef PACKED struct
                {
                    // BD address of the bonded host
                    BD_ADDR  bdaddr;
                
                    // Current value of the client configuration descriptor for characteristic 'Global Status'
                    UINT16 ttl_ble_service_global_status_client_configuration;
                
                    // Current value of the client configuration descriptor for characteristic 'FDAMS'
                    UINT16 ttl_ble_service_f_d_a_m_s_client_configuration;
                
                    // Current value of the client configuration descriptor for characteristic 'Data Write to BLE 0'
                    UINT16 ttl_ble_enhancement_service_data_write_to_ble_0_client_configuration;
                
                    // Current value of the client configuration descriptor for characteristic 'Data Write to BLE 1'
                    UINT16 ttl_ble_enhancement_service_data_write_to_ble_1_client_configuration;
                
                    // Current value of the client configuration descriptor for characteristic 'Data Write to BLE 2'
                    UINT16 ttl_ble_enhancement_service_data_write_to_ble_2_client_configuration;
                
                    // Current value of the client configuration descriptor for characteristic 'Data Write to BLE 3'
                    UINT16 ttl_ble_enhancement_service_data_write_to_ble_3_client_configuration;
                
                    // Current value of the client configuration descriptor for characteristic 'Data Read from BLE 0'
                    UINT16 ttl_ble_enhancement_service_data_read_from_ble_0_client_configuration;
                
                    // Current value of the client configuration descriptor for characteristic 'Data Read from BLE 1'
                    UINT16 ttl_ble_enhancement_service_data_read_from_ble_1_client_configuration;
                
                    // Current value of the client configuration descriptor for characteristic 'Data Read from BLE 2'
                    UINT16 ttl_ble_enhancement_service_data_read_from_ble_2_client_configuration;
                
                    // Current value of the client configuration descriptor for characteristic 'Data Read from BLE 3'
                    UINT16 ttl_ble_enhancement_service_data_read_from_ble_3_client_configuration;
                
                    // Current value of the client configuration descriptor for characteristic 'Command Write to BLE'
                    UINT16 ttl_ble_enhancement_service_command_write_to_ble_client_configuration;
                
                    // Current value of the client configuration descriptor for characteristic 'Command Read from BLE'
                    UINT16 ttl_ble_enhancement_service_command_read_from_ble_client_configuration;
                
                    // Current value of the client configuration descriptor for characteristic 'Control Point'
                    UINT16 ttl_ble_ota_update_service_control_point_client_configuration;
                }  __HOSTINFO_PEER;
                
                // Host information for NVRAM
                typedef PACKED struct
                {
                    // Part of HOSTINFO generated by wizard for every bonded peer
                    __HOSTINFO_PEER peer[GATT_DB_MAX_BONDED_PEERS];
                } __HOSTINFO;
                #pragma pack()
                
                // External definitions
                extern const UINT8  gatt_database[];
                extern const UINT16 gatt_database_len;
                extern UINT8        ttl_ble_indication_sent;           // 1 means waiting for ack
                extern UINT16       ttl_ble_connection_handle;         // HCI handle of connection, not zero when connected
                extern const BLE_PROFILE_GPIO_CFG
                                    ttl_ble_gpio_cfg;                  // Defines GPIO configuration used by the application
                extern BD_ADDR      ttl_ble_remote_addr;               // Address of currently connected client
                extern UINT8        ttl_ble_uuid_main_vsc_service[16]; // Main vendor specific service
                // Pointer to the generated part of hostinfo
                extern __HOSTINFO   *p_hostinfo_generated;
                
                // Functions definitions
                
                // Will be called on indication conformation
                //extern void ttl_ble_indication_cfm();
                // Registers timer. Should be called from ttl_ble_create()
                extern void ttl_ble_reg_timer();
                // Initializes persistent values in the hostinfo to add bonded peer
                extern void ttl_ble_add_bond(UINT8 *bda);
                // Prepares generated code for connection - writes persistent values from __HOSTINFO to GATT DB
                extern void __on_connection_up();
                // Sends notifications or/and indications for every client configuration descriptor
                // Updates __HOSTINFO by the value written by peer.
                // Returns true if any persistent value is changed
                extern BOOL __write_handler(UINT16 handle, int len, UINT8 *attrPtr);
                
                
                // ------------------- You have to implement these functions ----------------
                
                // Custom function to be called every fine timer tick
                extern void ttl_ble_timer_fine();
                
                // Custom function to be called every 1 s
                extern void ttl_ble_timer_1s();
                
                
                
                
                
                

                 

                ttl_db.c
                /*
                * This file has been automatically generated by the WICED Smart Designer.
                * BLE device's GATT database, device configuration, function that can be used
                * to send notifications and indications.
                *
                */
                
                // ttl_db.c
                
                #include "bleprofile.h"
                #include "bleapp.h"
                #include "gpiodriver.h"
                #include "string.h"
                #include "stdio.h"
                #include "platform.h"
                #include "ttl_db.h"
                #include "ble_ttl.h"
                #include "bt_uart_protocol.h"
                
                extern void *memcpy(void *dest, const void *src, size_t n); //get rid of implicit declaration warning
                
                const UINT8 gatt_database[]= // Define GATT database
                {
                // ***** Primary service 'Generic Access'
                    //<Name>Generic Access</Name>
                    //<Uuid>1800</Uuid>
                    //Service handle: HDLS_GENERIC_ACCESS
                    //Service UUID: UUID_SERVICE_GAP
                    PRIMARY_SERVICE_UUID16 (HDLS_GENERIC_ACCESS, UUID_SERVICE_GAP),
                
                    //<Name>Device Name</Name>
                    //<Uuid>2A00</Uuid>
                    CHARACTERISTIC_UUID16 (HDLC_GENERIC_ACCESS_DEVICE_NAME,
                                           HDLC_GENERIC_ACCESS_DEVICE_NAME_VALUE,
                                           UUID_CHARACTERISTIC_DEVICE_NAME,
                                           LEGATTDB_CHAR_PROP_READ,
                                           LEGATTDB_PERM_READABLE,
                                           8),
                    'T', 'T', 'L', '_', 'T', 'e', 's', 't',
                
                    //<Name>Appearance</Name>
                    //<Uuid>2A01</Uuid>
                    CHARACTERISTIC_UUID16 (HDLC_GENERIC_ACCESS_APPEARANCE,
                                           HDLC_GENERIC_ACCESS_APPEARANCE_VALUE,
                                           UUID_CHARACTERISTIC_APPEARANCE,
                                           LEGATTDB_CHAR_PROP_READ,
                                           LEGATTDB_PERM_READABLE,
                                           2),
                    BIT16_TO_8(APPEARANCE_GENERIC_COMPUTER),
                
                // ***** Primary service 'Generic Attribute'
                    //<Name>Generic Attribute</Name>
                    //<Uuid>1801</Uuid>
                    //Service handle: HDLS_GENERIC_ATTRIBUTE
                    //Service UUID: UUID_SERVICE_GATT
                    PRIMARY_SERVICE_UUID16 (HDLS_GENERIC_ATTRIBUTE, UUID_SERVICE_GATT),
                
                // ***** Primary service 'TTL Service'
                    //<Name>TTL Service</Name>
                    //<Uuid>e6 cf 1d 95 41 d1 b7 b1 ed 4f c0 a7 00 00 00 00</Uuid>
                    //Service handle: HDLS_TTL_SERVICE
                    //Service UUID: __UUID_TTL_SERVICE
                    PRIMARY_SERVICE_UUID128 (HDLS_TTL_SERVICE, __UUID_TTL_SERVICE),
                
                    //<Name>Global Status</Name>
                    //<Uuid>e6 cf 1d 95 41 d1 b7 b1 ed 4f c0 a7 01 00 00 00</Uuid>
                    CHARACTERISTIC_UUID128 (HDLC_TTL_SERVICE_GLOBAL_STATUS,
                                           HDLC_TTL_SERVICE_GLOBAL_STATUS_VALUE,
                                           __UUID_TTL_SERVICE_GLOBAL_STATUS,
                                           LEGATTDB_CHAR_PROP_READ | LEGATTDB_CHAR_PROP_NOTIFY | LEGATTDB_CHAR_PROP_INDICATE,
                                           LEGATTDB_PERM_READABLE,
                                           3),
                    0x00,0x00,0x00,
                
                    //<ClientConfiguration>
                    //<Notification>false</Notification>
                    //<Indication>false</Indication>
                    CHAR_DESCRIPTOR_UUID16_WRITABLE (HDLD_TTL_SERVICE_GLOBAL_STATUS_CLIENT_CONFIGURATION,
                                                     UUID_DESCRIPTOR_CLIENT_CHARACTERISTIC_CONFIGURATION,
                                                     LEGATTDB_PERM_READABLE | LEGATTDB_PERM_WRITE_CMD | LEGATTDB_PERM_WRITE_REQ | LEGATTDB_PERM_RELIABLE_WRITE | LEGATTDB_PERM_AUTH_WRITABLE,
                                                     2),
                    BIT16_TO_8 (CCC_NONE),
                
                    //<Name>TCAS</Name>
                    //<Uuid>e6 cf 1d 95 41 d1 b7 b1 ed 4f c0 a7 02 00 00 00</Uuid>
                    CHARACTERISTIC_UUID128_WRITABLE (HDLC_TTL_SERVICE_TCAS,
                                           HDLC_TTL_SERVICE_TCAS_VALUE,
                                           __UUID_TTL_SERVICE_TCAS,
                                           LEGATTDB_CHAR_PROP_READ | LEGATTDB_CHAR_PROP_WRITE,
                                           LEGATTDB_PERM_READABLE | LEGATTDB_PERM_WRITE_REQ,
                                           20),
                    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
                
                    //<Name>FDAMS</Name>
                    //<Uuid>e6 cf 1d 95 41 d1 b7 b1 ed 4f c0 a7 03 00 00 00</Uuid>
                    CHARACTERISTIC_UUID128 (HDLC_TTL_SERVICE_FDAMS,
                                           HDLC_TTL_SERVICE_FDAMS_VALUE,
                                           __UUID_TTL_SERVICE_FDAMS,
                                           LEGATTDB_CHAR_PROP_READ | LEGATTDB_CHAR_PROP_NOTIFY | LEGATTDB_CHAR_PROP_INDICATE,
                                           LEGATTDB_PERM_READABLE,
                                           18),
                                           0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
                
                    //<ClientConfiguration>
                    //<Notification>false</Notification>
                    //<Indication>false</Indication>
                    CHAR_DESCRIPTOR_UUID16_WRITABLE (HDLD_TTL_SERVICE_FDAMS_CLIENT_CONFIGURATION,
                                                     UUID_DESCRIPTOR_CLIENT_CHARACTERISTIC_CONFIGURATION,
                                                     LEGATTDB_PERM_READABLE | LEGATTDB_PERM_WRITE_CMD | LEGATTDB_PERM_WRITE_REQ | LEGATTDB_PERM_RELIABLE_WRITE | LEGATTDB_PERM_AUTH_WRITABLE,
                                                     2),
                    BIT16_TO_8 (CCC_NONE),
                
                    //<Name>SSMC</Name>
                    //<Uuid>e6 cf 1d 95 41 d1 b7 b1 ed 4f c0 a7 04 00 00 00</Uuid>
                    CHARACTERISTIC_UUID128_WRITABLE (HDLC_TTL_SERVICE_SSMC,
                                           HDLC_TTL_SERVICE_SSMC_VALUE,
                                           __UUID_TTL_SERVICE_SSMC,
                                           LEGATTDB_CHAR_PROP_READ | LEGATTDB_CHAR_PROP_WRITE,
                                           LEGATTDB_PERM_READABLE | LEGATTDB_PERM_WRITE_REQ,
                                           1),
                                           0x00,
                
                // ***** Primary service 'TTL Enhancement Service'
                    //<Name>TTL Enhancement Service</Name>
                    //<Uuid>45 4c db c3 17 7f 56 82 60 40 aa 4d 00 00 00 00</Uuid>
                    //Service handle: HDLS_TTL_ENHANCEMENT_SERVICE
                    //Service UUID: __UUID_TTL_ENHANCEMENT_SERVICE
                    PRIMARY_SERVICE_UUID128 (HDLS_TTL_ENHANCEMENT_SERVICE, __UUID_TTL_ENHANCEMENT_SERVICE),
                
                    //<Name>Data Write to BLE 0</Name>
                    //<Uuid>45 4c db c3 17 7f 56 82 60 40 aa 4d 01 00 00 00</Uuid>
                    CHARACTERISTIC_UUID128_WRITABLE (HDLC_TTL_ENHANCEMENT_SERVICE_DATA_WRITE_TO_BLE_0,
                                           HDLC_TTL_ENHANCEMENT_SERVICE_DATA_WRITE_TO_BLE_0_VALUE,
                                           __UUID_TTL_ENHANCEMENT_SERVICE_DATA_WRITE_TO_BLE_0,
                                           LEGATTDB_CHAR_PROP_WRITE_NO_RESPONSE | LEGATTDB_CHAR_PROP_NOTIFY,
                                           LEGATTDB_PERM_WRITE_CMD,
                                           20),
                                           0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
                
                    //<ClientConfiguration>
                    //<Notification>false</Notification>
                    //<Indication>false</Indication>
                    CHAR_DESCRIPTOR_UUID16_WRITABLE (HDLD_TTL_ENHANCEMENT_SERVICE_DATA_WRITE_TO_BLE_0_CLIENT_CONFIGURATION,
                                                     UUID_DESCRIPTOR_CLIENT_CHARACTERISTIC_CONFIGURATION,
                                                     LEGATTDB_PERM_READABLE | LEGATTDB_PERM_WRITE_CMD | LEGATTDB_PERM_WRITE_REQ | LEGATTDB_PERM_RELIABLE_WRITE | LEGATTDB_PERM_AUTH_WRITABLE,
                                                     2),
                    BIT16_TO_8 (CCC_NONE),
                
                    //<Name>Data Write to BLE 1</Name>
                    //<Uuid>45 4c db c3 17 7f 56 82 60 40 aa 4d 02 00 00 00</Uuid>
                    CHARACTERISTIC_UUID128_WRITABLE (HDLC_TTL_ENHANCEMENT_SERVICE_DATA_WRITE_TO_BLE_1,
                                           HDLC_TTL_ENHANCEMENT_SERVICE_DATA_WRITE_TO_BLE_1_VALUE,
                                           __UUID_TTL_ENHANCEMENT_SERVICE_DATA_WRITE_TO_BLE_1,
                                           LEGATTDB_CHAR_PROP_WRITE_NO_RESPONSE | LEGATTDB_CHAR_PROP_NOTIFY,
                                           LEGATTDB_PERM_WRITE_CMD,
                                           20),
                                           0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
                
                    //<ClientConfiguration>
                    //<Notification>false</Notification>
                    //<Indication>false</Indication>
                    CHAR_DESCRIPTOR_UUID16_WRITABLE (HDLD_TTL_ENHANCEMENT_SERVICE_DATA_WRITE_TO_BLE_1_CLIENT_CONFIGURATION,
                                                     UUID_DESCRIPTOR_CLIENT_CHARACTERISTIC_CONFIGURATION,
                                                     LEGATTDB_PERM_READABLE | LEGATTDB_PERM_WRITE_CMD | LEGATTDB_PERM_WRITE_REQ | LEGATTDB_PERM_RELIABLE_WRITE | LEGATTDB_PERM_AUTH_WRITABLE,
                                                     2),
                    BIT16_TO_8 (CCC_NONE),
                
                    //<Name>Data Write to BLE 2</Name>
                    //<Uuid>45 4c db c3 17 7f 56 82 60 40 aa 4d 03 00 00 00</Uuid>
                    CHARACTERISTIC_UUID128_WRITABLE (HDLC_TTL_ENHANCEMENT_SERVICE_DATA_WRITE_TO_BLE_2,
                                           HDLC_TTL_ENHANCEMENT_SERVICE_DATA_WRITE_TO_BLE_2_VALUE,
                                           __UUID_TTL_ENHANCEMENT_SERVICE_DATA_WRITE_TO_BLE_2,
                                           LEGATTDB_CHAR_PROP_WRITE_NO_RESPONSE | LEGATTDB_CHAR_PROP_NOTIFY,
                                           LEGATTDB_PERM_WRITE_CMD,
                                           20),
                                           0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
                
                    //<ClientConfiguration>
                    //<Notification>false</Notification>
                    //<Indication>false</Indication>
                    CHAR_DESCRIPTOR_UUID16_WRITABLE (HDLD_TTL_ENHANCEMENT_SERVICE_DATA_WRITE_TO_BLE_2_CLIENT_CONFIGURATION,
                                                     UUID_DESCRIPTOR_CLIENT_CHARACTERISTIC_CONFIGURATION,
                                                     LEGATTDB_PERM_READABLE | LEGATTDB_PERM_WRITE_CMD | LEGATTDB_PERM_WRITE_REQ | LEGATTDB_PERM_RELIABLE_WRITE | LEGATTDB_PERM_AUTH_WRITABLE,
                                                     2),
                    BIT16_TO_8 (CCC_NONE),
                
                    //<Name>Data Write to BLE 3</Name>
                    //<Uuid>45 4c db c3 17 7f 56 82 60 40 aa 4d 04 00 00 00</Uuid>
                    CHARACTERISTIC_UUID128_WRITABLE (HDLC_TTL_ENHANCEMENT_SERVICE_DATA_WRITE_TO_BLE_3,
                                           HDLC_TTL_ENHANCEMENT_SERVICE_DATA_WRITE_TO_BLE_3_VALUE,
                                           __UUID_TTL_ENHANCEMENT_SERVICE_DATA_WRITE_TO_BLE_3,
                                           LEGATTDB_CHAR_PROP_WRITE_NO_RESPONSE | LEGATTDB_CHAR_PROP_NOTIFY,
                                           LEGATTDB_PERM_WRITE_CMD,
                                           20),
                                           0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
                
                    //<ClientConfiguration>
                    //<Notification>false</Notification>
                    //<Indication>false</Indication>
                    CHAR_DESCRIPTOR_UUID16_WRITABLE (HDLD_TTL_ENHANCEMENT_SERVICE_DATA_WRITE_TO_BLE_3_CLIENT_CONFIGURATION,
                                                     UUID_DESCRIPTOR_CLIENT_CHARACTERISTIC_CONFIGURATION,
                                                     LEGATTDB_PERM_READABLE | LEGATTDB_PERM_WRITE_CMD | LEGATTDB_PERM_WRITE_REQ | LEGATTDB_PERM_RELIABLE_WRITE | LEGATTDB_PERM_AUTH_WRITABLE,
                                                     2),
                    BIT16_TO_8 (CCC_NONE),
                
                    //<Name>Data Read from BLE 0</Name>
                    //<Uuid>45 4c db c3 17 7f 56 82 60 40 aa 4d 05 00 00 00</Uuid>
                    CHARACTERISTIC_UUID128 (HDLC_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_0,
                                           HDLC_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_0_VALUE,
                                           __UUID_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_0,
                                           /*LEGATTDB_CHAR_PROP_READ |*/ LEGATTDB_CHAR_PROP_NOTIFY,
                                           LEGATTDB_PERM_NONE, //LEGATTDB_PERM_READABLE,
                                           20),
                                           0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
                
                    //<ClientConfiguration>
                    //<Notification>false</Notification>
                    //<Indication>false</Indication>
                    CHAR_DESCRIPTOR_UUID16_WRITABLE (HDLD_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_0_CLIENT_CONFIGURATION,
                                                     UUID_DESCRIPTOR_CLIENT_CHARACTERISTIC_CONFIGURATION,
                                                     LEGATTDB_PERM_READABLE | LEGATTDB_PERM_WRITE_CMD | LEGATTDB_PERM_WRITE_REQ | LEGATTDB_PERM_RELIABLE_WRITE | LEGATTDB_PERM_AUTH_WRITABLE,
                                                     2),
                    BIT16_TO_8 (CCC_NONE),
                
                    //<Name>Data Read from BLE 1</Name>
                    //<Uuid>45 4c db c3 17 7f 56 82 60 40 aa 4d 06 00 00 00</Uuid>
                    CHARACTERISTIC_UUID128 (HDLC_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_1,
                                           HDLC_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_1_VALUE,
                                           __UUID_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_1,
                                           /*LEGATTDB_CHAR_PROP_READ |*/ LEGATTDB_CHAR_PROP_NOTIFY,
                                           LEGATTDB_PERM_NONE, //LEGATTDB_PERM_READABLE,
                                           20),
                                           0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
                
                    //<ClientConfiguration>
                    //<Notification>false</Notification>
                    //<Indication>false</Indication>
                    CHAR_DESCRIPTOR_UUID16_WRITABLE (HDLD_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_1_CLIENT_CONFIGURATION,
                                                     UUID_DESCRIPTOR_CLIENT_CHARACTERISTIC_CONFIGURATION,
                                                     LEGATTDB_PERM_READABLE | LEGATTDB_PERM_WRITE_CMD | LEGATTDB_PERM_WRITE_REQ | LEGATTDB_PERM_RELIABLE_WRITE | LEGATTDB_PERM_AUTH_WRITABLE,
                                                     2),
                    BIT16_TO_8 (CCC_NONE),
                
                    //<Name>Data Read from BLE 2</Name>
                    //<Uuid>45 4c db c3 17 7f 56 82 60 40 aa 4d 07 00 00 00</Uuid>
                    CHARACTERISTIC_UUID128 (HDLC_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_2,
                                           HDLC_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_2_VALUE,
                                           __UUID_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_2,
                                           /*LEGATTDB_CHAR_PROP_READ |*/ LEGATTDB_CHAR_PROP_NOTIFY,
                                           LEGATTDB_PERM_NONE, //LEGATTDB_PERM_READABLE,
                                           20),
                                           0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
                
                    //<ClientConfiguration>
                    //<Notification>false</Notification>
                    //<Indication>false</Indication>
                    CHAR_DESCRIPTOR_UUID16_WRITABLE (HDLD_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_2_CLIENT_CONFIGURATION,
                                                     UUID_DESCRIPTOR_CLIENT_CHARACTERISTIC_CONFIGURATION,
                                                     LEGATTDB_PERM_READABLE | LEGATTDB_PERM_WRITE_CMD | LEGATTDB_PERM_WRITE_REQ | LEGATTDB_PERM_RELIABLE_WRITE | LEGATTDB_PERM_AUTH_WRITABLE,
                                                     2),
                    BIT16_TO_8 (CCC_NONE),
                
                    //<Name>Data Read from BLE 3</Name>
                    //<Uuid>45 4c db c3 17 7f 56 82 60 40 aa 4d 08 00 00 00</Uuid>
                    CHARACTERISTIC_UUID128 (HDLC_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_3,
                                           HDLC_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_3_VALUE,
                                           __UUID_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_3,
                                           /*LEGATTDB_CHAR_PROP_READ |*/ LEGATTDB_CHAR_PROP_NOTIFY,
                                           LEGATTDB_PERM_NONE, //LEGATTDB_PERM_READABLE,
                                           20),
                                           0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
                
                    //<ClientConfiguration>
                    //<Notification>false</Notification>
                    //<Indication>false</Indication>
                    CHAR_DESCRIPTOR_UUID16_WRITABLE (HDLD_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_3_CLIENT_CONFIGURATION,
                                                     UUID_DESCRIPTOR_CLIENT_CHARACTERISTIC_CONFIGURATION,
                                                     LEGATTDB_PERM_READABLE | LEGATTDB_PERM_WRITE_CMD | LEGATTDB_PERM_WRITE_REQ | LEGATTDB_PERM_RELIABLE_WRITE | LEGATTDB_PERM_AUTH_WRITABLE,
                                                     2),
                    BIT16_TO_8 (CCC_NONE),
                
                    //<Name>Command Write to BLE</Name>
                    //<Uuid>45 4c db c3 17 7f 56 82 60 40 aa 4d 06 00 00 00</Uuid>
                    CHARACTERISTIC_UUID128_WRITABLE (HDLC_TTL_ENHANCEMENT_SERVICE_COMMAND_WRITE_TO_BLE,
                                           HDLC_TTL_ENHANCEMENT_SERVICE_COMMAND_WRITE_TO_BLE_VALUE,
                                           __UUID_TTL_ENHANCEMENT_SERVICE_COMMAND_WRITE_TO_BLE,
                                           LEGATTDB_CHAR_PROP_WRITE_NO_RESPONSE | LEGATTDB_CHAR_PROP_NOTIFY,
                                           LEGATTDB_PERM_WRITE_CMD,
                                           5),
                                           0x00,0x00,0x00,0x00,0x00,
                
                    //<ClientConfiguration>
                    //<Notification>false</Notification>
                    //<Indication>false</Indication>
                    CHAR_DESCRIPTOR_UUID16_WRITABLE (HDLD_TTL_ENHANCEMENT_SERVICE_COMMAND_WRITE_TO_BLE_CLIENT_CONFIGURATION,
                                                     UUID_DESCRIPTOR_CLIENT_CHARACTERISTIC_CONFIGURATION,
                                                     LEGATTDB_PERM_READABLE | LEGATTDB_PERM_WRITE_CMD | LEGATTDB_PERM_WRITE_REQ | LEGATTDB_PERM_RELIABLE_WRITE | LEGATTDB_PERM_AUTH_WRITABLE,
                                                     2),
                    BIT16_TO_8 (CCC_NONE),
                
                    //<Name>Command Read from BLE</Name>
                    //<Uuid>45 4c db c3 17 7f 56 82 60 40 aa 4d 07 00 00 00</Uuid>
                    CHARACTERISTIC_UUID128 (HDLC_TTL_ENHANCEMENT_SERVICE_COMMAND_READ_FROM_BLE,
                                           HDLC_TTL_ENHANCEMENT_SERVICE_COMMAND_READ_FROM_BLE_VALUE,
                                           __UUID_TTL_ENHANCEMENT_SERVICE_COMMAND_READ_FROM_BLE,
                                           /*LEGATTDB_CHAR_PROP_READ |*/ LEGATTDB_CHAR_PROP_NOTIFY,
                                           LEGATTDB_PERM_NONE, //LEGATTDB_PERM_READABLE,
                                           5),
                                           0x00,0x00,0x00,0x00,0x00,
                
                    //<ClientConfiguration>
                    //<Notification>false</Notification>
                    //<Indication>false</Indication>
                    CHAR_DESCRIPTOR_UUID16_WRITABLE (HDLD_TTL_ENHANCEMENT_SERVICE_COMMAND_READ_FROM_BLE_CLIENT_CONFIGURATION,
                                                     UUID_DESCRIPTOR_CLIENT_CHARACTERISTIC_CONFIGURATION,
                                                     LEGATTDB_PERM_READABLE | LEGATTDB_PERM_WRITE_CMD | LEGATTDB_PERM_WRITE_REQ | LEGATTDB_PERM_RELIABLE_WRITE | LEGATTDB_PERM_AUTH_WRITABLE,
                                                     2),
                    BIT16_TO_8 (CCC_NONE),
                
                // ***** Primary service 'TTL OTA Update Service'
                    //<Name>TTL OTA Update Service</Name>
                    //<Uuid>6a 45 7b dc 64 78 dd b2 ec 4f 87 c6 00 00 00 00</Uuid>
                    //Service handle: HDLS_TTL_OTA_UPDATE_SERVICE
                    //Service UUID: __UUID_TTL_OTA_UPDATE_SERVICE
                    PRIMARY_SERVICE_UUID128 (HDLS_TTL_OTA_UPDATE_SERVICE, __UUID_TTL_OTA_UPDATE_SERVICE),
                
                    //<Name>Control Point</Name>
                    //<Uuid>6a 45 7b dc 64 78 dd b2 ec 4f 87 c6 01 00 00 00</Uuid>
                    CHARACTERISTIC_UUID128_WRITABLE (HDLC_TTL_OTA_UPDATE_SERVICE_CONTROL_POINT,
                                           HDLC_TTL_OTA_UPDATE_SERVICE_CONTROL_POINT_VALUE,
                                           __UUID_TTL_OTA_UPDATE_SERVICE_CONTROL_POINT,
                                           LEGATTDB_CHAR_PROP_WRITE | LEGATTDB_CHAR_PROP_NOTIFY | LEGATTDB_CHAR_PROP_INDICATE,
                                           LEGATTDB_PERM_WRITE_REQ,
                                           3),
                                           0x00,0x00,0x00,
                
                    //<ClientConfiguration>
                    //<Notification>false</Notification>
                    //<Indication>false</Indication>
                    CHAR_DESCRIPTOR_UUID16_WRITABLE (HDLD_TTL_OTA_UPDATE_SERVICE_CONTROL_POINT_CLIENT_CONFIGURATION,
                                                     UUID_DESCRIPTOR_CLIENT_CHARACTERISTIC_CONFIGURATION,
                                                     LEGATTDB_PERM_READABLE | LEGATTDB_PERM_WRITE_CMD | LEGATTDB_PERM_WRITE_REQ | LEGATTDB_PERM_RELIABLE_WRITE | LEGATTDB_PERM_AUTH_WRITABLE,
                                                     2),
                    BIT16_TO_8 (CCC_NONE),
                
                    //<Name>Data</Name>
                    //<Uuid>6a 45 7b dc 64 78 dd b2 ec 4f 87 c6 02 00 00 00</Uuid>
                    CHARACTERISTIC_UUID128_WRITABLE (HDLC_TTL_OTA_UPDATE_SERVICE_DATA,
                                           HDLC_TTL_OTA_UPDATE_SERVICE_DATA_VALUE,
                                           __UUID_TTL_OTA_UPDATE_SERVICE_DATA,
                                           LEGATTDB_CHAR_PROP_WRITE,
                                           LEGATTDB_PERM_VARIABLE_LENGTH | LEGATTDB_PERM_WRITE_REQ,
                                           20),
                                           0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
                
                    //<Name>Update App Info</Name>
                    //<Uuid>6a 45 7b dc 64 78 dd b2 ec 4f 87 c6 03 00 00 00</Uuid>
                    CHARACTERISTIC_UUID128 (HDLC_TTL_OTA_UPDATE_SERVICE_UPDATE_APP_INFO,
                                           HDLC_TTL_OTA_UPDATE_SERVICE_UPDATE_APP_INFO_VALUE,
                                           __UUID_TTL_OTA_UPDATE_SERVICE_UPDATE_APP_INFO,
                                           LEGATTDB_CHAR_PROP_READ,
                                           LEGATTDB_PERM_READABLE,
                                           4),
                                           0x00,0x00,0x00,0x00,
                
                };
                
                // Indication sent, waiting for ack
                UINT8 ttl_ble_indication_sent = 0;
                // Length of the GATT database
                const UINT16 gatt_database_len = sizeof(gatt_database);
                // Pointer to the bonded peer info or NULL if not bonded
                __HOSTINFO_PEER *p_bonded = NULL;
                // Main vendor specific service
                UINT8 ttl_ble_uuid_main_vsc_service[16] = {__UUID_TTL_SERVICE};
                // Timer counter (for the trace)
                UINT32 __timer_count = 0;
                // Indication confirmation callback
                static void __indication_cfm()
                {
                    ttl_ble_indication_sent = 0;
                    //ttl_ble_indication_cfm();
                }
                
                // Timer callback function for ttl_ble_reg_timer
                void ttl_ble_timeout(UINT32 arg)
                {
                    if (arg == BLEPROFILE_GENERIC_APP_TIMER)
                    {
                        ttl_ble_timer_1s();
                    }
                }
                // Timer callback function for ttl_ble_reg_timer
                void ttl_ble_fine_timeout(UINT32 arg)
                {
                    ttl_ble_timer_fine();
                }
                
                // Registers timer. Should be called from ttl_ble_create()
                void ttl_ble_reg_timer()
                {
                    //bleprofile_regTimerCb(ttl_ble_fine_timeout, ttl_ble_timeout);
                    bleprofile_regTimerCb(btup_timeOutCallback, ttl_ble_timeout);
                    bleprofile_StartTimer();
                }
                
                // Finds bonded peer in the hostinfo. On exit p_bonded points on bonded peer or NULL
                __HOSTINFO_PEER *__find_bonded_peer(UINT8 *bda)
                {
                    ble_trace1("__find_bonded_peer(%u)", (UINT32) bda);
                    int i;
                    p_bonded = NULL;
                    // Check if that peer is bonded and get its pointer
                    for (i=0; i<GATT_DB_MAX_BONDED_PEERS; i++)
                    {
                        if (0 == memcmp(bda, p_hostinfo_generated->peer[i].bdaddr, 6))
                        {
                            p_bonded = &p_hostinfo_generated->peer[i];
                            break;
                        }
                    }
                    return p_bonded;
                }
                
                // initializes persistent values in the hostinfo to add bonded peer
                void ttl_ble_add_bond(UINT8 *bda)
                {
                    ble_trace1("ttl_ble_add_bond(%u) entered", (UINT32) bda);
                    // Find this peer among bonded peers in the p_hostinfo_generated
                    if (!__find_bonded_peer(bda))
                    {
                        // Peer is not found. Remember new one.
                        memcpy(&p_hostinfo_generated->peer[GATT_DB_MAX_BONDED_PEERS-1], &p_hostinfo_generated->peer[GATT_DB_MAX_BONDED_PEERS-2], sizeof(__HOSTINFO_PEER) * (GATT_DB_MAX_BONDED_PEERS - 1));
                        p_bonded = &p_hostinfo_generated->peer[0];
                        memcpy(p_bonded->bdaddr, bda, 6);
                    }
                
                    // Clear persistent generated values in the hostinfo for just bonded peer
                
                    // Set the initial value of the client configuration descriptor for value 'Global Status'
                    p_bonded->ttl_ble_service_global_status_client_configuration = 0;
                
                    // Set the initial value of the client configuration descriptor for value 'FDAMS'
                    p_bonded->ttl_ble_service_f_d_a_m_s_client_configuration = 0;
                
                    // Set the initial value of the client configuration descriptor for value 'Data Write to BLE 0'
                    p_bonded->ttl_ble_enhancement_service_data_write_to_ble_0_client_configuration = 0;
                
                    // Set the initial value of the client configuration descriptor for value 'Data Write to BLE 1'
                    p_bonded->ttl_ble_enhancement_service_data_write_to_ble_1_client_configuration = 0;
                
                    // Set the initial value of the client configuration descriptor for value 'Data Write to BLE 2'
                    p_bonded->ttl_ble_enhancement_service_data_write_to_ble_2_client_configuration = 0;
                
                    // Set the initial value of the client configuration descriptor for value 'Data Write to BLE 3'
                    p_bonded->ttl_ble_enhancement_service_data_write_to_ble_3_client_configuration = 0;
                
                    // Set the initial value of the client configuration descriptor for value 'Data Read from BLE 0'
                    p_bonded->ttl_ble_enhancement_service_data_read_from_ble_0_client_configuration = 0;
                
                    // Set the initial value of the client configuration descriptor for value 'Data Read from BLE 1'
                    p_bonded->ttl_ble_enhancement_service_data_read_from_ble_1_client_configuration = 0;
                
                    // Set the initial value of the client configuration descriptor for value 'Data Read from BLE 2'
                    p_bonded->ttl_ble_enhancement_service_data_read_from_ble_2_client_configuration = 0;
                
                    // Set the initial value of the client configuration descriptor for value 'Data Read from BLE 3'
                    p_bonded->ttl_ble_enhancement_service_data_read_from_ble_3_client_configuration = 0;
                
                    // Set the initial value of the client configuration descriptor for value 'Command Write to BLE'
                    p_bonded->ttl_ble_enhancement_service_command_write_to_ble_client_configuration = 0;
                
                    // Set the initial value of the client configuration descriptor for value 'Command Read from BLE'
                    p_bonded->ttl_ble_enhancement_service_command_read_from_ble_client_configuration = 0;
                
                    // Set the initial value of the client configuration descriptor for value 'Control Point'
                    p_bonded->ttl_ble_ota_update_service_control_point_client_configuration = 0;
                    ble_trace0("ttl_ble_add_bond() exit");
                }
                
                // Prepares generated code for connection - writes persistent values from __HOSTINFO to GATT DB
                void __on_connection_up()
                {
                    ttl_ble_indication_sent = 0;
                    ble_trace0("__on_connection_up() entered");
                    // Find this peer among bonded peers in the p_hostinfo_generated
                //    if (__find_bonded_peer(ttl_ble_remote_addr))
                    {
                        BLEPROFILE_DB_PDU db_pdu;
                        // Write the value of the client configuration descriptor for value 'Global Status'
                        db_pdu.len = 2;
                        db_pdu.pdu[0] = p_bonded->ttl_ble_service_global_status_client_configuration & 0xff;
                        db_pdu.pdu[1] = (p_bonded->ttl_ble_service_global_status_client_configuration >> 8) & 0xff;
                        bleprofile_WriteHandle(HDLD_TTL_SERVICE_GLOBAL_STATUS_CLIENT_CONFIGURATION, &db_pdu);
                
                        // Write the value of the client configuration descriptor for value 'FDAMS'
                        db_pdu.len = 2;
                        db_pdu.pdu[0] = p_bonded->ttl_ble_service_f_d_a_m_s_client_configuration & 0xff;
                        db_pdu.pdu[1] = (p_bonded->ttl_ble_service_f_d_a_m_s_client_configuration >> 8) & 0xff;
                        bleprofile_WriteHandle(HDLD_TTL_SERVICE_FDAMS_CLIENT_CONFIGURATION, &db_pdu);
                
                        // Write the value of the client configuration descriptor for value 'Data Write to BLE 0'
                        db_pdu.len = 2;
                        db_pdu.pdu[0] = p_bonded->ttl_ble_enhancement_service_data_write_to_ble_0_client_configuration & 0xff;
                        db_pdu.pdu[1] = (p_bonded->ttl_ble_enhancement_service_data_write_to_ble_0_client_configuration >> 8) & 0xff;
                        bleprofile_WriteHandle(HDLD_TTL_ENHANCEMENT_SERVICE_DATA_WRITE_TO_BLE_0_CLIENT_CONFIGURATION, &db_pdu);
                
                        // Write the value of the client configuration descriptor for value 'Data Write to BLE 1'
                        db_pdu.len = 2;
                        db_pdu.pdu[0] = p_bonded->ttl_ble_enhancement_service_data_write_to_ble_1_client_configuration & 0xff;
                        db_pdu.pdu[1] = (p_bonded->ttl_ble_enhancement_service_data_write_to_ble_1_client_configuration >> 8) & 0xff;
                        bleprofile_WriteHandle(HDLD_TTL_ENHANCEMENT_SERVICE_DATA_WRITE_TO_BLE_1_CLIENT_CONFIGURATION, &db_pdu);
                
                        // Write the value of the client configuration descriptor for value 'Data Write to BLE 2'
                        db_pdu.len = 2;
                        db_pdu.pdu[0] = p_bonded->ttl_ble_enhancement_service_data_write_to_ble_2_client_configuration & 0xff;
                        db_pdu.pdu[1] = (p_bonded->ttl_ble_enhancement_service_data_write_to_ble_2_client_configuration >> 8) & 0xff;
                        bleprofile_WriteHandle(HDLD_TTL_ENHANCEMENT_SERVICE_DATA_WRITE_TO_BLE_2_CLIENT_CONFIGURATION, &db_pdu);
                
                        // Write the value of the client configuration descriptor for value 'Data Write to BLE 3'
                        db_pdu.len = 2;
                        db_pdu.pdu[0] = p_bonded->ttl_ble_enhancement_service_data_write_to_ble_3_client_configuration & 0xff;
                        db_pdu.pdu[1] = (p_bonded->ttl_ble_enhancement_service_data_write_to_ble_3_client_configuration >> 8) & 0xff;
                        bleprofile_WriteHandle(HDLD_TTL_ENHANCEMENT_SERVICE_DATA_WRITE_TO_BLE_3_CLIENT_CONFIGURATION, &db_pdu);
                
                        // Write the value of the client configuration descriptor for value 'Data Read from BLE'
                        db_pdu.len = 2;
                        db_pdu.pdu[0] = p_bonded->ttl_ble_enhancement_service_data_read_from_ble_0_client_configuration & 0xff;
                        db_pdu.pdu[1] = (p_bonded->ttl_ble_enhancement_service_data_read_from_ble_0_client_configuration >> 8) & 0xff;
                        bleprofile_WriteHandle(HDLD_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_0_CLIENT_CONFIGURATION, &db_pdu);
                
                        // Write the value of the client configuration descriptor for value 'Data Read from BLE 1'
                        db_pdu.len = 2;
                        db_pdu.pdu[0] = p_bonded->ttl_ble_enhancement_service_data_read_from_ble_1_client_configuration & 0xff;
                        db_pdu.pdu[1] = (p_bonded->ttl_ble_enhancement_service_data_read_from_ble_1_client_configuration >> 8) & 0xff;
                        bleprofile_WriteHandle(HDLD_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_1_CLIENT_CONFIGURATION, &db_pdu);
                
                        // Write the value of the client configuration descriptor for value 'Data Read from BLE 2'
                        db_pdu.len = 2;
                        db_pdu.pdu[0] = p_bonded->ttl_ble_enhancement_service_data_read_from_ble_2_client_configuration & 0xff;
                        db_pdu.pdu[1] = (p_bonded->ttl_ble_enhancement_service_data_read_from_ble_2_client_configuration >> 8) & 0xff;
                        bleprofile_WriteHandle(HDLD_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_2_CLIENT_CONFIGURATION, &db_pdu);
                
                        // Write the value of the client configuration descriptor for value 'Data Read from BLE 3'
                        db_pdu.len = 2;
                        db_pdu.pdu[0] = p_bonded->ttl_ble_enhancement_service_data_read_from_ble_3_client_configuration & 0xff;
                        db_pdu.pdu[1] = (p_bonded->ttl_ble_enhancement_service_data_read_from_ble_3_client_configuration >> 8) & 0xff;
                        bleprofile_WriteHandle(HDLD_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_3_CLIENT_CONFIGURATION, &db_pdu);
                
                        // Write the value of the client configuration descriptor for value 'Command Write to BLE'
                        db_pdu.len = 2;
                        db_pdu.pdu[0] = p_bonded->ttl_ble_enhancement_service_command_write_to_ble_client_configuration & 0xff;
                        db_pdu.pdu[1] = (p_bonded->ttl_ble_enhancement_service_command_write_to_ble_client_configuration >> 8) & 0xff;
                        bleprofile_WriteHandle(HDLD_TTL_ENHANCEMENT_SERVICE_COMMAND_WRITE_TO_BLE_CLIENT_CONFIGURATION, &db_pdu);
                
                        // Write the value of the client configuration descriptor for value 'Command Read from BLE'
                        db_pdu.len = 2;
                        db_pdu.pdu[0] = p_bonded->ttl_ble_enhancement_service_command_read_from_ble_client_configuration & 0xff;
                        db_pdu.pdu[1] = (p_bonded->ttl_ble_enhancement_service_command_read_from_ble_client_configuration >> 8) & 0xff;
                        bleprofile_WriteHandle(HDLD_TTL_ENHANCEMENT_SERVICE_COMMAND_READ_FROM_BLE_CLIENT_CONFIGURATION, &db_pdu);
                
                        // Write the value of the client configuration descriptor for value 'Control Point'
                        db_pdu.len = 2;
                        db_pdu.pdu[0] = p_bonded->ttl_ble_ota_update_service_control_point_client_configuration & 0xff;
                        db_pdu.pdu[1] = (p_bonded->ttl_ble_ota_update_service_control_point_client_configuration >> 8) & 0xff;
                        bleprofile_WriteHandle(HDLD_TTL_OTA_UPDATE_SERVICE_CONTROL_POINT_CLIENT_CONFIGURATION, &db_pdu);
                    }
                }
                
                // Updates __HOSTINFO by the value written by peer.
                // Returns true if any persistent value is changed
                BOOL __write_handler(UINT16 handle, int len, UINT8 *attrPtr)
                {
                    ble_trace2("__write_handler(%#06x, %i, *attrPtr) entered", handle, len);
                    BOOL res = FALSE;
                    if(len == 0)
                    {
                        return res;
                    }
                    if ((len == 2) && (handle == HDLD_TTL_SERVICE_GLOBAL_STATUS_CLIENT_CONFIGURATION))
                    {
                        // find this peer among bonded peers in the p_hostinfo_generated
                        if (__find_bonded_peer(ttl_ble_remote_addr))
                        {
                            p_bonded->ttl_ble_service_global_status_client_configuration = attrPtr[0] + (attrPtr[1] << 8);
                            ble_trace2("handle:%#06x val:%#04x", handle, p_bonded->ttl_ble_service_global_status_client_configuration);
                            res = TRUE;
                        }
                    }
                    if (handle == HDLC_TTL_SERVICE_TCAS_VALUE)
                    {
                        if (len > 20)
                        {
                            ble_trace2("bad length:%d handle:%#06x", len, handle);
                        }
                        else
                        {
                            //call custom on_write function
                            ble_trace1("write handle:%#06x", handle);
                            btup_sendData(FALSE, TRUE, ADDR_CHAR_TCAS_SECOND_PACKET, len, attrPtr);
                            res = TRUE;
                        }
                    }
                    if ((len == 2) && (handle == HDLD_TTL_SERVICE_FDAMS_CLIENT_CONFIGURATION))
                    {
                        // find this peer among bonded peers in the p_hostinfo_generated
                        if (__find_bonded_peer(ttl_ble_remote_addr))
                        {
                            p_bonded->ttl_ble_service_f_d_a_m_s_client_configuration = attrPtr[0] + (attrPtr[1] << 8);
                            ble_trace2("handle:%#06x val:%#04x", handle, p_bonded->ttl_ble_service_f_d_a_m_s_client_configuration);
                            res = TRUE;
                        }
                    }
                    if (handle == HDLC_TTL_SERVICE_SSMC_VALUE)
                    {
                        if (len > 1)
                        {
                            ble_trace2("bad length:%d handle:%#06x", len, handle);
                        }
                        else
                        {
                            //call custom on_write function
                            ble_trace1("write handle:%#06x", handle);
                            btup_sendData(FALSE, TRUE, ADDR_CHAR_SSMC, len, attrPtr);
                            res = TRUE;
                        }
                    }
                    if (handle == HDLC_TTL_ENHANCEMENT_SERVICE_DATA_WRITE_TO_BLE_0_VALUE)
                    {
                        if (len > 20)
                        {
                            ble_trace2("bad length:%d handle:%#06x", len, handle);
                        }
                        else
                        {
                            //call custom on_write function
                            ble_trace1("write handle:%#06x", handle);
                            btup_sendData(FALSE, TRUE, ADDR_CHAR_DATA_WRITE_TO_BLE_0, len, attrPtr);
                            res = TRUE;
                        }
                    }
                    if ((len == 2) && (handle == HDLD_TTL_ENHANCEMENT_SERVICE_DATA_WRITE_TO_BLE_0_CLIENT_CONFIGURATION))
                    {
                        // find this peer among bonded peers in the p_hostinfo_generated
                        {
                        if (__find_bonded_peer(ttl_ble_remote_addr))
                            p_bonded->ttl_ble_enhancement_service_data_write_to_ble_0_client_configuration = attrPtr[0] + (attrPtr[1] << 8);
                            ble_trace2("handle:%#06x val:%04x", handle, p_bonded->ttl_ble_enhancement_service_data_write_to_ble_0_client_configuration);
                            res = TRUE;
                        }
                    }
                    if (handle == HDLC_TTL_ENHANCEMENT_SERVICE_DATA_WRITE_TO_BLE_1_VALUE)
                    {
                        if (len > 20)
                        {
                            ble_trace2("bad length:%d handle:%#06x", len, handle);
                        }
                        else
                        {
                            //call custom on_write function
                            ble_trace1("write handle:%#06x", handle);
                            btup_sendData(FALSE, TRUE, ADDR_CHAR_DATA_WRITE_TO_BLE_1, len, attrPtr);
                            res = TRUE;
                        }
                    }
                    if ((len == 2) && (handle == HDLD_TTL_ENHANCEMENT_SERVICE_DATA_WRITE_TO_BLE_1_CLIENT_CONFIGURATION))
                    {
                        // find this peer among bonded peers in the p_hostinfo_generated
                        if (__find_bonded_peer(ttl_ble_remote_addr))
                        {
                            p_bonded->ttl_ble_enhancement_service_data_write_to_ble_1_client_configuration = attrPtr[0] + (attrPtr[1] << 8);
                            ble_trace2("handle:%#06x val:%04x", handle, p_bonded->ttl_ble_enhancement_service_data_write_to_ble_1_client_configuration);
                            res = TRUE;
                        }
                    }
                    if (handle == HDLC_TTL_ENHANCEMENT_SERVICE_DATA_WRITE_TO_BLE_2_VALUE)
                    {
                        if (len > 20)
                        {
                            ble_trace2("bad length:%d handle:%#06x", len, handle);
                        }
                        else
                        {
                            //call custom on_write function
                            ble_trace1("write handle:%#06x", handle);
                            btup_sendData(FALSE, TRUE, ADDR_CHAR_DATA_WRITE_TO_BLE_2, len, attrPtr);
                            res = TRUE;
                        }
                    }
                    if ((len == 2) && (handle == HDLD_TTL_ENHANCEMENT_SERVICE_DATA_WRITE_TO_BLE_2_CLIENT_CONFIGURATION))
                    {
                        // find this peer among bonded peers in the p_hostinfo_generated
                        if (__find_bonded_peer(ttl_ble_remote_addr))
                        {
                            p_bonded->ttl_ble_enhancement_service_data_write_to_ble_2_client_configuration = attrPtr[0] + (attrPtr[1] << 8);
                            ble_trace2("handle:%#06x val:%04x", handle, p_bonded->ttl_ble_enhancement_service_data_write_to_ble_2_client_configuration);
                            res = TRUE;
                        }
                    }
                    if (handle == HDLC_TTL_ENHANCEMENT_SERVICE_DATA_WRITE_TO_BLE_3_VALUE)
                    {
                        if (len > 20)
                        {
                            ble_trace2("bad length:%d handle:%#06x", len, handle);
                        }
                        else
                        {
                            //call custom on_write function
                            ble_trace1("write handle:%#06x", handle);
                            btup_sendData(FALSE, TRUE, ADDR_CHAR_DATA_WRITE_TO_BLE_3, len, attrPtr);
                            res = TRUE;
                        }
                    }
                    if ((len == 2) && (handle == HDLD_TTL_ENHANCEMENT_SERVICE_DATA_WRITE_TO_BLE_3_CLIENT_CONFIGURATION))
                    {
                        // find this peer among bonded peers in the p_hostinfo_generated
                        if (__find_bonded_peer(ttl_ble_remote_addr))
                        {
                            p_bonded->ttl_ble_enhancement_service_data_write_to_ble_3_client_configuration = attrPtr[0] + (attrPtr[1] << 8);
                            ble_trace2("handle:%#06x val:%04x", handle, p_bonded->ttl_ble_enhancement_service_data_write_to_ble_3_client_configuration);
                            res = TRUE;
                        }
                    }
                    if ((len == 2) && (handle == HDLD_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_0_CLIENT_CONFIGURATION))
                    {
                        // find this peer among bonded peers in the p_hostinfo_generated
                        if (__find_bonded_peer(ttl_ble_remote_addr))
                        {
                            p_bonded->ttl_ble_enhancement_service_data_read_from_ble_0_client_configuration = attrPtr[0] + (attrPtr[1] << 8);
                            ble_trace2("handle:%#06x val:%04x", handle, p_bonded->ttl_ble_enhancement_service_data_read_from_ble_0_client_configuration);
                            res = TRUE;
                        }
                    }
                    if ((len == 2) && (handle == HDLD_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_1_CLIENT_CONFIGURATION))
                    {
                        // find this peer among bonded peers in the p_hostinfo_generated
                        if (__find_bonded_peer(ttl_ble_remote_addr))
                        {
                            p_bonded->ttl_ble_enhancement_service_data_read_from_ble_1_client_configuration = attrPtr[0] + (attrPtr[1] << 8);
                            ble_trace2("handle:%#06x val:%04x", handle, p_bonded->ttl_ble_enhancement_service_data_read_from_ble_1_client_configuration);
                            res = TRUE;
                        }
                    }
                    if ((len == 2) && (handle == HDLD_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_2_CLIENT_CONFIGURATION))
                    {
                        // find this peer among bonded peers in the p_hostinfo_generated
                        if (__find_bonded_peer(ttl_ble_remote_addr))
                        {
                            p_bonded->ttl_ble_enhancement_service_data_read_from_ble_2_client_configuration = attrPtr[0] + (attrPtr[1] << 8);
                            ble_trace2("handle:%#06x val:%04x", handle, p_bonded->ttl_ble_enhancement_service_data_read_from_ble_2_client_configuration);
                            res = TRUE;
                        }
                    }
                    if ((len == 2) && (handle == HDLD_TTL_ENHANCEMENT_SERVICE_DATA_READ_FROM_BLE_3_CLIENT_CONFIGURATION))
                    {
                        // find this peer among bonded peers in the p_hostinfo_generated
                        if (__find_bonded_peer(ttl_ble_remote_addr))
                        {
                            p_bonded->ttl_ble_enhancement_service_data_read_from_ble_3_client_configuration = attrPtr[0] + (attrPtr[1] << 8);
                            ble_trace2("handle:%#06x val:%04x", handle, p_bonded->ttl_ble_enhancement_service_data_read_from_ble_3_client_configuration);
                            res = TRUE;
                        }
                    }
                    if (handle == HDLC_TTL_ENHANCEMENT_SERVICE_COMMAND_WRITE_TO_BLE_VALUE)
                    {
                        if (len > 5)
                        {
                            ble_trace2("bad length:%d handle:%#06x", len, handle);
                        }
                        else
                        {
                            //call custom on_write function
                            ble_trace1("write handle:%#06x", handle);
                            btup_sendData(FALSE, TRUE, ADDR_CHAR_COMMAND_WRITE_TO_BLE, len, attrPtr);
                            res = TRUE;
                        }
                    }
                    if ((len == 2) && (handle == HDLD_TTL_ENHANCEMENT_SERVICE_COMMAND_WRITE_TO_BLE_CLIENT_CONFIGURATION))
                    {
                        // find this peer among bonded peers in the p_hostinfo_generated
                        if (__find_bonded_peer(ttl_ble_remote_addr))
                        {
                            p_bonded->ttl_ble_enhancement_service_command_write_to_ble_client_configuration = attrPtr[0] + (attrPtr[1] << 8);
                            ble_trace2("handle:%#06x val:%04x", handle, p_bonded->ttl_ble_enhancement_service_command_write_to_ble_client_configuration);
                            res = TRUE;
                        }
                    }
                    if ((len == 2) && (handle == HDLD_TTL_ENHANCEMENT_SERVICE_COMMAND_READ_FROM_BLE_CLIENT_CONFIGURATION))
                    {
                        // find this peer among bonded peers in the p_hostinfo_generated
                        if (__find_bonded_peer(ttl_ble_remote_addr))
                        {
                            p_bonded->ttl_ble_enhancement_service_command_read_from_ble_client_configuration = attrPtr[0] + (attrPtr[1] << 8);
                            ble_trace2("handle:%#06x val:%04x", handle, p_bonded->ttl_ble_enhancement_service_command_read_from_ble_client_configuration);
                            res = TRUE;
                        }
                    }
                    if (handle == HDLC_TTL_OTA_UPDATE_SERVICE_CONTROL_POINT_VALUE)
                    {
                        if (len > 3)
                        {
                            ble_trace2("bad length:%d handle:%#06x", len, handle);
                        }
                        else
                        {
                            //call custom on_write function
                            ble_trace1("write handle:%#06x", handle);
                            res = FALSE;
                        }
                    }
                    if ((len == 2) && (handle == HDLD_TTL_OTA_UPDATE_SERVICE_CONTROL_POINT_CLIENT_CONFIGURATION))
                    {
                        // find this peer among bonded peers in the p_hostinfo_generated
                        if (__find_bonded_peer(ttl_ble_remote_addr))
                        {
                            p_bonded->ttl_ble_ota_update_service_control_point_client_configuration = attrPtr[0] + (attrPtr[1] << 8);
                            ble_trace2("handle:%#06x val:%04x", handle, p_bonded->ttl_ble_ota_update_service_control_point_client_configuration);
                            res = TRUE;
                        }
                    }
                    if (handle == HDLC_TTL_OTA_UPDATE_SERVICE_DATA_VALUE)
                    {
                        if (len > 20)
                        {
                            ble_trace2("bad length:%d handle:%#06x", len, handle);
                        }
                        else
                        {
                            //call custom on_write function
                            ble_trace1("write handle:%#06x", handle);
                            res = FALSE;
                        }
                    }
                    return res;
                }
                
                
                
                
                
                

                 

                And now the preliminary traces:

                ttl_ble_create() enter

                legattdb_dumpDb():

                0018

                021101002a

                54544c5f54657374

                022101012a

                8000

                0118

                e6cf1d9541d1b7b1ed4fc0a700000000

                321103e6cf1d9541d1b7b1ed4fc0a701

                000000

                000000

                0000

                0a3103e6cf1d9541d1b7b1ed4fc0a702

                000000

                00000000000000000000000000000000

                00000000

                324103e6cf1d9541d1b7b1ed4fc0a703

                000000

                00000000000000000000000000000000

                0000

                0000

                0a6103e6cf1d9541d1b7b1ed4fc0a704

                000000

                00

                454cdbc3177f56826040aa4d00000000

                141104454cdbc3177f56826040aa4d01

                000000

                00000000000000000000000000000000

                00000000

                0000

                143104454cdbc3177f56826040aa4d02

                000000

                00000000000000000000000000000000

                00000000

                0000

                145104454cdbc3177f56826040aa4d03

                000000

                00000000000000000000000000000000

                00000000

                0000

                147104454cdbc3177f56826040aa4d04

                000000

                00000000000000000000000000000000

                00000000

                0000

                109104454cdbc3177f56826040aa4d05

                000000

                00000000000000000000000000000000

                00000000

                0000

                10b104454cdbc3177f56826040aa4d06

                000000

                00000000000000000000000000000000

                00000000

                0000

                10d104454cdbc3177f56826040aa4d07

                000000

                00000000000000000000000000000000

                00000000

                0000

                10f104454cdbc3177f56826040aa4d08

                000000

                00000000000000000000000000000000

                00000000

                0000

                141105454cdbc3177f56826040aa4d09

                000000

                0000000000

                0000

                103105454cdbc3177f56826040aa4d0a

                000000

                0000000000

                0000

                6a457bdc6478ddb2ec4f87c600000000

                3802ff6a457bdc6478ddb2ec4f87c601

                000000

                000000

                0000

                0805ff6a457bdc6478ddb2ec4f87c602

                000000

                00000000000000000000000000000000

                00000000

                0207ff6a457bdc6478ddb2ec4f87c603

                000000

                00000000

                21

                2100

                0201051107e6cf1d9541d1b7b1ed4fc0

                a700000000020a04

                090954544c5f54657374

                ttl_ble_puart_init(GPIO_PIN_UART_RX, GPIO_PIN_UART_TX, 115200)

                btup_init()

                enableRxInterrupt(FALSE)

                resetRxBuffers()

                resetLastReceivedPacket(FALSE)

                enableRxInterrupt(TRUE)

                @$*#04FFF6F70092011E0300C1E804090100008003BA1A032800008003BE1A000000008003AE1A05FF00008003B21A890000008003B61A140014008003BA1A000000008003BE1A000000008003AE1A06FF00008003B21A020000008003B61A130013008003BA1A032800008003BE1A000000008003AE1A07FF00008003B21A820000008003B61A040004008003BA1A000000008003BE1A000000008003DA1A0000000000074A05106A732000074E05CF01000000078206110001000007820603000400000782060300030000078206010008000007820603000F000007820603000D000007D2070000000000E5490B210000000007362A50000C00@$*#04FF1EF7009201030000073A2A010000000007522A500001000007021F01000000connection_up: 020100200400 h=64

                __on_connection_up() entered

                @$*#04FF2EF700920105000002FA240000000000078633000000000007E6200000000000078E1E0000000000078E1E00000000ttl_ble_write_handler(): handle = 0x0511, len = 5

                __write_handler(0x0511, 5, *attrPtr) entered

                write handle:0x0511

                btup_sendData(FALSE, TRUE, 0x0e, 5)

                getSentPacketByAddress(000e)

                btup_receiveDataCallback() entered

                transferUartToRxBuffer()

                enableRxInterrupt(FALSE)

                enableRxInterrupt(TRUE)

                readFromRxBuffer()

                decodeFirstByteToLastReceivedPacket(0x4f)

                getExpectedLength(15)

                btup_receiveDataCallback() entered

                transferUartToRxBuffer()

                enableRxInterrupt(FALSE)

                enableRxInterrupt(TRUE)

                decodeRemainingBytesOfLastReceivedPacket()

                enableRxInterrupt(FALSE)

                readFromRxBuffer()

                readFromRxBuffer()

                readFromRxBuffer()

                readFromRxBuffer()

                readFromRxBuffer()

                readFromRxBuffer()

                executeSinglePacketChar()

                notificationWithDB(0x531, *data, 5, TRUE, FALSE)

                resetLastReceivedPacket(FALSE)

                enableRxInterrupt(TRUE)

                @$*#04FF0EF7009201010000E5750411050000ADV start: 020100200400

                 

                The UART protocol was devised to allow communication between an iPhone app, the BLE module and a host MCU. In this implementation, the test app writes into one characteristic (0x0511), which gets transfered to the host MCU. As a response, a notification is send (0x0531), originated from the MCU.

                I'll add further traces in the next days.

                 

                Hopefully this will lead to a solution.

                If this post is too messy, I can also attach the source files.

                 

                Best regards

                Hannes Baumgart

                • 5. Re: Receiving notification without content and without sendNotification

                  Hello Hannes,

                   

                  This is a lot to digest.

                   

                  We were able to compile your by commenting out whole bunch of things that we think were unrelated to your problems.

                  But when we run the app, it resets by itself and calls the app_create function multiple times.

                   

                  You need to narrow it down - We don't have the MCU communication so that is very limiting.

                   

                  Let us know if you can isolate the issue.

                   

                  Thanks

                  JT

                  • 6. Re: Receiving notification without content and without sendNotification
                    MichaelF_56

                    userc_16716

                     

                    It would really help if you could recreate the specific issue using one of the sample applications/TAG3 board with a minimal number of changes (i.e. enough to re-create the issue). The internal apps team can then revisit. As jota_1939431 mentions, there is simply too much there for the apps team to debug the specific problem.

                     

                    We need your help narrowing down what needs to be tested.

                     

                    userc_19497

                    • 7. Re: Receiving notification without content and without sendNotification

                      Hi JT,

                       

                      thanks for your reply!

                      We created a lean modification of your speed test app, that also shows an erronous behavior. It is reduced compared to our goal configuration in that next to 1 "write-no-response" and 1 "notify" characteristic for exchanging control data, only one big 20-byte characteristic per direction is used, instead of four per direction.
                      In a test we just ran, the behavior is slightly different between those two configurations:

                      With 4 20-byte-sized characteristics, no reception of notifications was possible: In the debug traces of the iPhone app the characteristics contained no data, but the 5-byte-sized ones did work.

                      Now with only one 20-byte-sized characteristic, some receptions do work and contain the expected data, but there are still those with no data in between.

                      Find a debug trace from the iPhone app attached (tested with only one 20-bytes-sized characteristic per direction (i.e. one notification, one write no response):

                      2015-10-30 15:16:52.551 XamarinRoboticsBluetoothLEExplorerFormsiOS[2003:372133] dev: name=Speed-Test-Ext, id=e2760f8c-c0d6-1401-6141-862f269264cf

                      2015-10-30 15:16:55.409 XamarinRoboticsBluetoothLEExplorerFormsiOS[2003:372133] No services, attempting to connect to device

                      2015-10-30 15:16:55.675 XamarinRoboticsBluetoothLEExplorerFormsiOS[2003:372133] ConnectedPeripheral: Speed-Test-Ext

                      2015-10-30 15:16:55.836 XamarinRoboticsBluetoothLEExplorerFormsiOS[2003:372133] Device.Discovered Service: <CBService: 0x165891a0, isPrimary = YES, UUID = 00000000-4DAA-4060-8256-7F17C3DB4C45>

                      2015-10-30 15:16:56.471 XamarinRoboticsBluetoothLEExplorerFormsiOS[2003:372133] Device.Discovered Characteristics.

                      2015-10-30 15:16:56.484 XamarinRoboticsBluetoothLEExplorerFormsiOS[2003:372133] Characteristic: <CBCharacteristic: 0x16779380, UUID = 00000001-4DAA-4060-8256-7F17C3DB4C45, properties = 0x4, value = <00010203 04050607 08090a0b 0c0d0e0f 10111213>, notifying = NO>

                      2015-10-30 15:16:56.485 XamarinRoboticsBluetoothLEExplorerFormsiOS[2003:372133] Characteristic: <CBCharacteristic: 0x16779470, UUID = 00000005-4DAA-4060-8256-7F17C3DB4C45, properties = 0x10, value = (null), notifying = NO>

                      2015-10-30 15:16:56.486 XamarinRoboticsBluetoothLEExplorerFormsiOS[2003:372133] Characteristic: <CBCharacteristic: 0x16779510, UUID = 00000009-4DAA-4060-8256-7F17C3DB4C45, properties = 0x4, value = (null), notifying = NO>

                      2015-10-30 15:16:56.487 XamarinRoboticsBluetoothLEExplorerFormsiOS[2003:372133] Characteristic: <CBCharacteristic: 0x167795f0, UUID = 0000000A-4DAA-4060-8256-7F17C3DB4C45, properties = 0x10, value = <02000000 00>, notifying = NO>

                      2015-10-30 15:16:56.488 XamarinRoboticsBluetoothLEExplorerFormsiOS[2003:372133] Device.

                      Discovered Characteristics.

                      [0:] 

                      2015-10-30 15:16:57.950 XamarinRoboticsBluetoothLEExplorerFormsiOS[2003:372133] invalid notification/indication (uid=00000005-4daa-4060-8256-7f17c3db4c45): Value == null

                      2015-10-30 15:16:58.351 XamarinRoboticsBluetoothLEExplorerFormsiOS[2003:372133] readControlCharacteristic notification, packet = {,1,0,0,0,0}

                      [0:] 

                      2015-10-30 15:16:58.756 XamarinRoboticsBluetoothLEExplorerFormsiOS[2003:372167] received 'bootloader reset'

                      2015-10-30 15:17:03.484 XamarinRoboticsBluetoothLEExplorerFormsiOS[2003:372133] ** Characteristic.RequestValue, PropertyType = Notify, requesting updates

                      [0:] 

                      2015-10-30 15:17:03.486 XamarinRoboticsBluetoothLEExplorerFormsiOS[2003:372133] ** RequestValue, Succesful: True

                      2015-10-30 15:17:03.486 XamarinRoboticsBluetoothLEExplorerFormsiOS[2003:372133] ** Characteristic.RequestValue, PropertyType = Notify, requesting updates

                      2015-10-30 15:17:03.659 XamarinRoboticsBluetoothLEExplorerFormsiOS[2003:372133] invalid notification/indication (uid=00000005-4daa-4060-8256-7f17c3db4c45): Value == null

                      [0:] 

                      2015-10-30 15:17:04.064 XamarinRoboticsBluetoothLEExplorerFormsiOS[2003:372133] invalid notification/indication (uid=00000005-4daa-4060-8256-7f17c3db4c45): Value == null

                      [0:] 

                      2015-10-30 15:17:04.466 XamarinRoboticsBluetoothLEExplorerFormsiOS[2003:372133] !!! readControlCharacteristic unexpected notification, packet = {,2,0,0,0,0}

                      [0:] 

                      2015-10-30 15:17:04.877 XamarinRoboticsBluetoothLEExplorerFormsiOS[2003:372133] readControlCharacteristic notification, packet = {,2,0,0,0,0}

                      [0:] 

                      2015-10-30 15:17:05.289 XamarinRoboticsBluetoothLEExplorerFormsiOS[2003:372133] invalid notification/indication (uid=00000005-4daa-4060-8256-7f17c3db4c45): Value == null

                      [0:] 

                      2015-10-30 15:17:05.701 XamarinRoboticsBluetoothLEExplorerFormsiOS[2003:372133] invalid notification/indication (uid=00000005-4daa-4060-8256-7f17c3db4c45): Value == null

                      [0:] 

                      2015-10-30 15:17:06.104 XamarinRoboticsBluetoothLEExplorerFormsiOS[2003:372133] !!! readControlCharacteristic unexpected notification, packet = {,2,0,0,0,0}

                      [0:] 

                      2015-10-30 15:17:06.507 XamarinRoboticsBluetoothLEExplorerFormsiOS[2003:372133] !!! readControlCharacteristic unexpected notification, packet = {,2,0,0,0,0}

                       

                      We used this modified speed test app, the files are attached to this post.

                       

                      I hope this will clarify our problems.

                       

                      Thanks for your help!

                       

                      Best regards

                      Hannes Baumgart

                      • 8. Re: Receiving notification without content and without sendNotification

                        Hello. Sorry it took so long to get back to you.

                         

                        I looked at your code, and I found a mistake that might cause your problems.

                        I noticed that you are sending notifications with HANDLE_SPEED_TEST_CHARACTERISTIC_DATA_W0_VALUE.

                        However, when we look at the GATT database, this characteristic doesn't have notification permission. So it shouldn't be sending any notifications.

                         

                        Notice in the log:

                        "invalid notification/indication (uid=00000005-4daa-4060-8256-7f17c3db4c45): Value == null"

                        is paired with

                        "!!! readControlCharacteristic unexpected notification, packet = {,2,0,0,0,0}".

                        This happens when you write to the write characteristic.

                        When you handle the write callback to this write characteristic, you send two notifications using HANDLE_SPEED_TEST_CHARACTERISTIC_DATA_W0_VALUE and HANDLE_SPEED_TEST_CHARACTERISTIC_CONTROL_R_VALUE.

                        So one can only assume the problem occurs because of this notification.

                         

                        It seems like you are trying to send notifications with write characteristic and receive notifications with read characteristic.

                        Notifications doesn't work like that. You need to send notifications with the characteristic that has notification permission and on your client side, you should be expecting notifications for that characteristic.

                         

                        To do what you are trying to do (i.e. write a value to BLE using write characteristic, and receive notification using read characteristic. at least that is my understanding of what you are trying to do; please correct me if I'm wrong), you will need to handle the behavior of write response a little bit differently. When you write with the write characteristic, you will want to write that value to the read characteristic using bleprofile_WriteHandle in the write_handler callback. Then you can send notification using HANDLE_SPEED_TEST_CHARACTERISTIC_DATA_R0_VALUE.

                         

                        Please let me know if these changes make the problem go away.

                        I'm not sure if this is related to your original problem.

                        I couldn't simulate your original problem, because I couldn't mimic the UART communication with the host MCU.

                        Please let us know the status on your original problem too.

                        Thank you.

                         

                        James

                        • 9. Re: Receiving notification without content and without sendNotification

                          Hello James,

                           

                          thank you very much for your time and effort.

                          The bug you found has been fixed and sadly the problem persists.

                          Please find attached the new source code, trace file and makefile.

                           

                          Best regards

                          Hannes Baumgart

                          • 10. Re: Receiving notification without content and without sendNotification

                            Hello everybody,

                             

                            we modified the speed_test software with a bigger GATT DB containing four readable and writable characteristics so it's even more resembling to our target application.

                            Comparing to our example posted before, we now get not only unexpected but also invalid notifications. We traced these down to the iPhone-API, so it's not caused by the Xamarin-Libs we use.

                            Please find source code, makefile and log attached as zip.

                             

                            Thanks for investigating!

                             

                            Best regards

                            Hannes Baumgart

                            • 11. Re: Receiving notification without content and without sendNotification
                              VictorZ_46

                              I looked briefly at the code, and it looks that when you receive a Write Command on one of the characteristics, you send 5 notifications.  This should work fine as long as you do not send your Write Commands too often.  If you send Write Command every connection interval, it might not work well even if there is no interference and no need for retransmissions.  By default there are 4 notifications that you can squeeze in the connection interval.  You can try to increase this number to 6 by calling blecm_setMaxTxRxPair (6).  I am not sure if it is a well tested scenario though.

                               

                              There is a limited number of tx buffers.  If you are after high performance, it is a good idea to check blecm_getAvailableTxBuffers() before sending the next notification.

                               

                              Please add following 2 lines to your create function.  Setup for the UART trace in the console window of the IDE, repro the problem and attach trace here.

                              extern UINT32 blecm_configFlag ;

                              blecm_configFlag |= BLECM_DBGUART_LOG | BLECM_DBGUART_LOG_L2CAP | BLECM_DBGUART_LOG_SMP;