Receiving notification without content and without sendNotification

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Anonymous
Not applicable

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

0 Likes
1 Solution

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;

View solution in original post

0 Likes
11 Replies
Anonymous
Not applicable

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

0 Likes
Anonymous
Not applicable

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

0 Likes
Anonymous
Not applicable

Hello hantron

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.

jamesle1

0 Likes
Anonymous
Not applicable

Hello jamesle1

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] << 😎 + ttl_ble_remote_addr[2],

                (ttl_ble_remote_addr[1] << 😎 + 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] << 😎 + bda[2],

                (bda[1] << 😎 + 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.acked = TRUE;

#else

        sentPackets.acked = FALSE;

#endif

        sentPackets.address = 0xFF;

        sentPackets.wholePacketLength = 0;

        sentPackets.read = FALSE;

        sentPackets.request = FALSE;

        sentPackets.resendCounter = BT_TIMEOUT_MAX_RESENDS;

        sentPackets.sent = FALSE;

        sentPackets.timeoutCounter = 0;

        for (j = 0; j < 23; j++)

        {

            sentPackets.data = 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.acked == FALSE)

            && (sentPackets.request == TRUE)

            && (sentPackets.sent == TRUE)

            && (sentPackets.resendCounter > 0))

        {

            if(sentPackets.timeoutCounter > 1)

            {

                sentPackets.timeoutCounter--;

            } else if(sentPackets.timeoutCounter == 1)

            {

                j = bleprofile_PUARTTx((unsigned char *) sentPackets.data, sentPackets.wholePacketLength);

                resetPacketTimeout(sentPackets.address, FALSE);

            }

        }

    }

#endif

}

static void resetRxBuffers(void)

{

    ble_trace0("resetRxBuffers()");

    unsigned int i;

    for (i = 0; i < BT_UART_BUFFERSIZE; i++)

    {

        rxBuffer = 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 = (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 >> 😎 & 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.bdaddr, 6))

        {

            p_bonded = &p_hostinfo_generated->peer;

            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 >> 😎 & 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 >> 😎 & 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 >> 😎 & 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 >> 😎 & 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 >> 😎 & 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 >> 😎 & 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 >> 😎 & 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 >> 😎 & 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 >> 😎 & 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 >> 😎 & 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 >> 😎 & 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 >> 😎 & 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 >> 😎 & 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

0 Likes
Anonymous
Not applicable

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

0 Likes

hantron

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 j.t 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.

jamesle1

0 Likes
lock attach
Attachments are accessible only for community members.
Anonymous
Not applicable

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

0 Likes
Anonymous
Not applicable

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

0 Likes
lock attach
Attachments are accessible only for community members.
Anonymous
Not applicable

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

0 Likes
lock attach
Attachments are accessible only for community members.
Anonymous
Not applicable

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

0 Likes

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;

0 Likes