This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CC1352P: BLE 5.0 communication setting for proper communication

Part Number: CC1352P
Other Parts Discussed in Thread: SYSCONFIG,

Hi Support,

I am facing issues in receiving data on BLE 5.0 while other device is sending beacon ( broadcasting data), I can able to receive 6 out of 10 broadcast. I have tried to change  Min Max time  at broadcaster and changed scan window and interval at observer side but it does not help me to achieve 100 % communication rate. 

Does some help or doc available that guide me to do correct setting of parameter for proper communication in beacon ( broadcast mode)

I am using multirole sample application for testing. below is my setting for Adv parameters. 

GapAdv_params_t advParams1 = {
.eventProps = GAP_ADV_PROP_CONNECTABLE,// | GAP_ADV_PROP_LEGACY | GAP_ADV_PROP_SCANNABLE,
.primIntMin = 160,//240,
.primIntMax = 176,//280,
.primChanMap = GAP_ADV_CHAN_ALL,
.peerAddrType = PEER_ADDRTYPE_PUBLIC_OR_PUBLIC_ID,
.peerAddr = { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa },
.filterPolicy = GAP_ADV_WL_POLICY_ANY_REQ,
.txPower = 16,//GAP_ADV_TX_POWER_NO_PREFERENCE,
.primPhy = GAP_ADV_PRIM_PHY_1_MBPS,//GAP_ADV_PRIM_PHY_1_MBPS,
.secPhy = GAP_ADV_SEC_PHY_CODED_S8,//GAP_ADV_SEC_PHY_CODED_S8,
.sid = 0
};

below is my scan code

#define SCAN_PARAM_DFLT_INTERVAL 560 //800
/// Default scan window (in 625 us ticks)
#define SCAN_PARAM_DFLT_WINDOW 528 //800

void multi_role_enableScan( void )
{
uint8_t temp8;

// Setup scanning

// Register callback to process Scanner events
GapScan_registerCb(multi_role_scanCB, NULL);

// Set Scanner Event Mask
GapScan_setEventMask(GAP_EVT_SCAN_ENABLED | GAP_EVT_SCAN_DISABLED |
GAP_EVT_ADV_REPORT);

// Set Scan PHY parameters
GapScan_setPhyParams(DEFAULT_SCAN_PHY| SCAN_PRIM_PHY_CODED, SCAN_TYPE_PASSIVE,
SCAN_PARAM_DFLT_INTERVAL, SCAN_PARAM_DFLT_WINDOW);

temp8 = SCAN_FLT_DUP_ENABLE;
GapScan_setParam(SCAN_PARAM_FLT_DUP, &temp8);
}

  • Do you mean to do continuous scan in multi_role example?

  • No,

    my objective is to receive data at 100% rate, I have tried it by changing all scan parameters (window and interval), I have tried with continious scan enable too.

    I have used below API for continuous scan

    (void)GapScan_enable(0, 0, 0); 

     

  • Do you mean BLE broadcaster send 100 advertising and you want multi-role can scan them 100% ?

  • Nearly,  

    I want to configure setting in both broadcaster and multirole scan to something that improve my communication between broadcaster and scanner.

    at this moment my broadcaster is sending data with

    min = 100mS

    max = 110 mS

    Duration = 1100mS 

    and my scanner is scanning for more then 1500mS.

    In terms of time its a large value, my objective is 

    1. reliable communication

    2. Reduce Broadcast and Scan time, as my application is battery based.

  • Since advertising is broadcast based message and it broadcasts on different channels, I don't think you can receive it 100% by just adjusting those parameters.

  • Hi Yk,

    At the moment I am targeting 100% but anything better with my present state will help me, and I want to reduce my scan and Tx time as well. As per my experiment I understood  by change in  min max, duration and interval  parameter communication can be improved as I do improve it. But as I don't know what should be the correct setting. so I am looking for some guideline that help me to figure out values of these parameters for proper communication.

    can some one share me some document that will explain values of that parameter for effective communication.

  • Since you cannot control advertising of 3rd party devices, I suppose you can only extend scan time to collect as many advertising as possible.

  • Hi Chen,

    you are getting it wrong,

    please note:- both adverting device and scanning device are mine, I am not testing with any third party device.

    what I want is what should be set in advertiser and what is set in scanner, so that my probability of reliable communication between these two increases.

    I can do any change in any firmware both are mine only.

  • Maybe try to do advertising and scan on single channel to see it that works for your application.

  • how to configure for advertising and scan on single channel.

    Please don't take it otherwise, but your answer are more generic, I am not getting anything out of it. I want something that really help me something specific.

    what should i set from where I got information etc

  • Hi Jai,

    I've added a member from the team to help you with your inquiry. During your scan for these broadcasts, are you also in any connections or advertising at all during this time? Have you enabled the RF Debug Output to take a logic trace to view the RX and TX of the device and understand if your scanner is scanning for the entire time you have set?

    The guide for output your RX and TX onto debug pins can be found here 

    Do you see any different behavior when increase your scan interval / window to larger amounts of the duration?

  • I would say you can try to use "GAP_SetParamValue(GAP_PARAM_SET_SCAN_CHAN, GAP_ADV_CHAN_37)" to scan only on channel 37 and also revise your advertising device to only do advertising on channel 37 by setting primChanMap to GAP_ADV_CHAN_37 in  gap_advertiser.h.

  • Jai,

    I will be helping you to resolve your issue. 

    I agree with Evan's suggestion: please enable the RF debug output and use a logic analyzer to capture your RX and TX lines. They will give you clarity on when and how often each of the devices in the setup activate the radio to transmit and to receive. It's going to be very revealing.

    In general, I believe that your expectation is to receive 100% of the advertisements may not be realistic. I guess it depends on the application and the environment; but in general, radio packets will be lost due to many factors. Among those are noise, reflection, etc. More importantly, attempting to receive 100% of the beacons would imply to enable your reception (i.e. scanning) 100% of the time on the peer device (that is, continuous scanning). For what you said, this might not be feasible if another important consideration of your system is power consumption. 

    Therefore, I believe you will need to evaluate the trade-offs of your system design. In particular, power vs reception percentage. You'll probably need to account for packet loss.

    I don't believe we have any documents that show empirical, measured data for adjusting scan and advertisement parameters. However, we are considering publishing this in the future.

    I hope this helps, but let me know if you have other specific questions.

    -Luis

  • hi can anyone help me on this,  thank you in advance

  • Jai,

    I'm sorry for the delay. I'd be happy to continue helping.

    To get started, please see our SimpleLink Academy lab on Scanning and Advertising and try to run all the lab's tasks. 

    And, please help me understand:

    • What is your setup: HW, SW? For example, are you running on custom hardware or on our LaunchPads? If so, which LaunchPad? Are both your projects running MultiRole?
    • What SDK version are you using?
    • Is your intent that one device only advertises and the other one only scans? Or are you attempting to advertise and scan at the same time on both devices? Please help me understand what your application is trying to accomplish.
    • What are the values of SCAN_PARAM_DFLT_INTERVAL and SCAN_PARAM_DFLT_WINDOW?
    • Did you try enabling the TX/RX IO as we suggested before? If so, what did you find or learn? If not, please take time to do it.

    Finally and more importantly, in the code you shared it looks like you commented out some important values for eventProps. Please leave the default:

    GapAdv_params_t advParams1 = {
      .eventProps =   GAP_ADV_PROP_CONNECTABLE | GAP_ADV_PROP_LEGACY | GAP_ADV_PROP_SCANNABLE,
      .primIntMin =   160,
      .primIntMax =   160,
      .primChanMap =  GAP_ADV_CHAN_ALL,
      .peerAddrType = PEER_ADDRTYPE_PUBLIC_OR_PUBLIC_ID,
      .peerAddr =     { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa },
      .filterPolicy = GAP_ADV_WL_POLICY_ANY_REQ,
      .txPower =      GAP_ADV_TX_POWER_NO_PREFERENCE,
      .primPhy =      GAP_ADV_PRIM_PHY_1_MBPS,
      .secPhy =       GAP_ADV_SEC_PHY_1_MBPS,
      .sid =          0
    };
    

    I look forward to hear from you.

    Thanks,

    Luis

  • Hi Luis,

    thanks for sharing link I will visit it.

    We have migrated our code to newer SDK "simplelink_cc13x2_26x2_sdk_4_20_01_03" from simplelink_cc13x2_26x2_sdk_3_30_00_03

    below are ans of your quries

    • What is your setup: HW, SW? For example, are you running on custom hardware or on our LaunchPads? If so, which LaunchPad? Are both your projects running MultiRole?
    • Jai:- we have our on custom Hardware, and I have generated I/O mapping as per our hardware, using sysconfig too. 
    • What SDK version are you using?
    • Jai:- We have migrated our code to newer SDK "simplelink_cc13x2_26x2_sdk_4_20_01_03" from simplelink_cc13x2_26x2_sdk_3_30_00_03
    • Is your intent that one device only advertises and the other one only scans? Or are you attempting to advertise and scan at the same time on both devices? Please help me understand what your application is trying to accomplish.
    • Jai:- At the moment we transmit first then wait for response and it took seconds, but we would like to do it within few mS. If we could able transmit and receiver at same time it will help us to save our overall communication time and we prefer this, but our top most priority to have 100% effective communication. 
    • What are the values of SCAN_PARAM_DFLT_INTERVAL and SCAN_PARAM_DFLT_WINDOW?
    • Jag:- 

      GapScan_setPhyParams(DEFAULT_SCAN_PHY| SCAN_PRIM_PHY_CODED, SCAN_TYPE_PASSIVE,
      DEFAULT_SCAN_INTERVAL, DEFAULT_SCAN_WINDOW);

      // Default scan interval (in 625 us ticks)
      #define DEFAULT_SCAN_INTERVAL 560

      // Default scan window (in 625 us ticks)
      #define DEFAULT_SCAN_WINDOW 528

    • Did you try enabling the TX/RX IO as we suggested before? If so, what did you find or learn? If not, please take time to do it.
    • jai:- can you please brief this point again.

    Finally and more importantly, in the code you shared it looks like you commented out some important values for eventProps. Please leave the default:

    Jai:- can you please suggest us what is required and must for broadcast and scan feature, as we do not want to have connection feature thus we have commented some part of code which is related to this. 

  • Hi Jai,

    1) Since the CC1352P device only has one radio it's not possible to do Rx and Tx at the same time. However, since both scanning and advertising operations are periodic, it's possible to set the device in scanning and advertising mode. For this to work the advertising interval must be long enough to allow scanning to happen between advertising events and vice versa.

    2) You can find instructions for enabling Rx/Tx pins for debugging purposes here:

    3) It sounds like you want to advertise non-connectable. Please use the following GapAdv_params_t definition: 

    GapAdv_params_t advParams1 = {
      .eventProps =   GAP_ADV_PROP_LEGACY | GAP_ADV_PROP_SCANNABLE,
      .primIntMin =   160,
      .primIntMax =   160,
      .primChanMap =  GAP_ADV_CHAN_ALL,
      .peerAddrType = PEER_ADDRTYPE_PUBLIC_OR_PUBLIC_ID,
      .peerAddr =     { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa },
      .filterPolicy = GAP_ADV_WL_POLICY_ANY_REQ,
      .txPower =      GAP_ADV_TX_POWER_NO_PREFERENCE,
      .primPhy =      GAP_ADV_PRIM_PHY_1_MBPS,
      .secPhy =       GAP_ADV_SEC_PHY_1_MBPS,
      .sid =          0
    };

  • Part Number: CC1352P

    Hello Team,

    We are using simplelink_cc13x2_26x2_sdk_4_20_01_03 and advertising at BLE5.0 for long ranges with below settings:-

    advParams.eventProps = GAP_ADV_PROP_CONNECTABLE;
    advParams.primIntMin = 160u;
    advParams.primIntMax = 176u;
    advParams.primChanMap = GAP_ADV_CHAN_ALL;
    advParams.peerAddrType = PEER_ADDRTYPE_PUBLIC_OR_PUBLIC_ID;
    advParams.peerAddr[0] = 0x00u;
    advParams.peerAddr[1] = 0x00u;
    advParams.peerAddr[2] = 0x00u;
    advParams.peerAddr[3] = 0x00u;
    advParams.peerAddr[4] = 0x00u;
    advParams.peerAddr[5] = 0x00u;
    advParams.filterPolicy = GAP_ADV_WL_POLICY_ANY_REQ;
    advParams.txPower = GAP_ADV_TX_POWER_NO_PREFERENCE;
    advParams.primPhy = GAP_ADV_PRIM_PHY_1_MBPS;

    advParams.secPhy = GAP_ADV_SEC_PHY_CODED_S8;

    Please share the best suitable Advertise parameters for same.

    Regards,

    Vijendra

  • Hi Vijendra,

    Depending on what kind of use-case you have, different advertising parameters can be recommended. Can you share some details about your use-case?

    Thanks, 
    Elin

  • Hi Elin,

    We are working on BLE HAN system in which all devices are communicating in Broadcasting mode.

    So we need best advertise and scanning settings on BLE5 long range.

    Regards,

    Vijendra

  • Hi Marie,

    thanks for providing your feedback on provided code, I will make all necessary change in our code, and let you know the improvements.

    I would also want to explain why we kept above advertise setting.

    we would like to do communication over ble 5.0 long range, all of our device are working in broadcast mode (beacon mode). for this we come to know above setting somewhere on T2E forum.

    I think the setting provided by you are either for Ble 4.2 or its not for Ble 5.0 long range, can you share some docs that help us to understand how to configure best settings ( adv, scan parameters) for BLE 5.0 long range communication.

    my team also asked same question on below ticket, you can merge that ticket here. 

    e2e.ti.com/.../939889

  • Hi Jai, Vijendra,

    As far as I understood for your application, the device should advertise and scan but never enter into a connection. Based on this I recommend the following advertisement settings:

    .eventProps = 0,
    .primIntMin = 160,
    .primIntMax = 176,
    .primChanMap = GAP_ADV_CHAN_ALL,
    .peerAddrType = PEER_ADDRTYPE_PUBLIC_OR_PUBLIC_ID,
    .peerAddr = { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa },
    .filterPolicy = GAP_ADV_WL_POLICY_ANY_REQ,
    .txPower = GAP_ADV_TX_POWER_NO_PREFERENCE,
    .primPhy = GAP_ADV_PRIM_PHY_1_MBPS,
    .secPhy = GAP_ADV_SEC_PHY_CODED_S8,
    .sid = 0

    You also asked me about using scan requests and scan responses to exchange information. If you want to use this you can use the following settings:

    .eventProps = GAP_ADV_PROP_SCANNABLE,
    .primIntMin = 160,
    .primIntMax = 176,
    .primChanMap = GAP_ADV_CHAN_ALL,
    .peerAddrType = PEER_ADDRTYPE_PUBLIC_OR_PUBLIC_ID,
    .peerAddr = { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa },
    .filterPolicy = GAP_ADV_WL_POLICY_ANY_REQ,
    .txPower = GAP_ADV_TX_POWER_NO_PREFERENCE,
    .primPhy = GAP_ADV_PRIM_PHY_1_MBPS,
    .secPhy = GAP_ADV_SEC_PHY_CODED_S8,
    .sid = 0

    Two notes:

    1) I would recommend using a faster (higher data rate) PHY, this would save you time and energy consumption. Preferably 2M PHY.

    2) Note that the advertisement interval is given in units of 0.625 ms, so if you want to advertise with 160 ms interval you will need to set primIntMin  = 256 .

  • Marie,

    Thanks for your reply, on this my understanding is, our setting for advParams1 was correct and we can ignore all the feedback provided by TI on this. If not please correct me.

    On you below feedback on email, I have a query.

    " Can you have one "initiate advertising" function which is only called once, and then a different function to enable advertising? (You should only call GapAdv_create() once. )"

    on this my understanding is

    1. "initiate_advertising function will be called once at first time when device power up, and will have only GapAdv_create().

    2. Other function will be TransmitData that will be called when data transmission required, and will have following things in given order only

    a. GapAdv_disable

    b. GapAdv_prepareLoadByHandle()

    c GapAdv_loadByHandle

    d. GapAdv_setEventMask

    e.GapAdv_enable

    I have tried to conclude all of your inputs in this, if I have missed anything please let me know. 

    1. I have one query on this approach, since my seeps and wakeup regularly then, will it be ok calling "initiate advertising" once, or it must be called at every wakeup .

    2. your sample multirole application also not have single method for transmission, I would like to know what is a idea behind separating things into two parts.

    I request you to please comment on every line in detail

  • Hi Jai,

    You can consider changing the eventProps value but it's not necessary.

    2.d. I don't expect you to need to change the event mask, I would recommend calling GapAdv_setEventMask() in the "initiate_advertising" function. 

    1. No, just every power up (after device has been in shutdon). Not necessary to call after every sleep.

    2. As far as I understood you use-case, you have two different situations for when to advertise. (One periodic, one is triggered by a button.) In this case it could make sense to have two different advertisement sets that handles the two different situations. If I misunderstood then I apologize. 

  • Hi Marie,

    based on your reply I assumed my understanding mentioned above is correct I will do further changes in code and test it again.

    regarding below point

    1. No, just every power up (after device has been in shutdon). Not necessary to call after every sleep.

    Jai:- by power up I mean, when Vcc applied to device, but are you saying when device wakeup from shutdown then also I have to do it? But I could I identify this, as I just enabled power policy in code. I don't know when device goes to shutdown, when it goes to sleep. Is there some mechanism to identify this??

    thanks

    Jai.

  • Hi Jai,

    In both cases (power up and after shutdown) the device will start running code at the entry point, i.e. at main(). So you don't have to change your code.

  • Hi Marie,

    Thanks for the inputs, it really helps.

    Now my next query is how I can put my device in shutdown mode, as i mentioned I just enabled power policy but I did not found anything to put device in shutdown mode. 

    as we are having a use case where we have to kept out product of the self so I will prefer to keep it in shutdown mode, it will only wakeup when someone pressed button which is on exti interrupts.

    Thanks 

    Jai

  • Hi Marie,

    can you please review "multi_role_init function in provided files, can you tell me what all things I can remove from this considering my use case. I think it initialize GATT client as well which is not my use case.

    I would like to remove / comment all code which is not related to my application, just to make sure it is not interfering with my code and creating any chance for device hang.

    thanks

    Jai

  • Hi Marie,

    can you please reply to above quires along with this one.

    As suggested by you I have divided advertise code in below two part 

    1. "initiate_advertising function will be called once at first time when device power up, and will have only GapAdv_create().

    2. Other function will be TransmitData that will be called when data transmission required, and will have following things in given order only

    a. GapAdv_disable

    b. GapAdv_prepareLoadByHandle()

    c GapAdv_loadByHandle

    //d. GapAdv_setEventMask

    e.GapAdv_enable

    But when I am calling method  GapAdv_create from multi_role_init it give me status 0x12 (Not setup properly to perform that task), can you suggest me the correct location from where I should call method.

    can you please review attached file to make sure it is inline to above changes.

    0333.multi_role.c

     

  • Hi Jai,

    1) We have an example called Pin Shutdown where you can see how to implement this:

    2) It sounds like you want to remove all code related to being in a connection? Did you take a look at the simple broadcaster example?
     

    3) Let me take a look at your file.

  • Hi Jai,

    Looking at the multi_role.c file I have the following feed-back:

    gapadv_create must be called after GAP_DeviceInit() has returned. I would suggest you move the multi_role_CreateAdv() call into the GAP_DEVICE_INIT_DONE_EVENT in multi_role_processGapMsg().

  • Hi Marie,

    I have modified the adv code as below and it observe working, it is transmitting data.

    void multi_role_enableAdvert(
    uint8_t aData_p[],
    uint8_t nLen_p,
    uint8_t nRetry_p,
    uint16_t nDuration,
    uint8_t IsScanEn )
    {
    static uint8_t IsAdvCreated = cFalse;
    uint8_t status = FAILURE;

    if( IsAdvCreated == cFalse )
    {
    IsAdvCreated = cTrue;
    status = GapAdv_create(&multi_role_advCB, &advParams1,&advHandle);
    DebugPrint_g( "AdvCreate=", status );
    }
    else
    {
    status = GapAdv_disable(advHandle);
    DebugPrint_g( "AdvDis=", status );

    status = GapAdv_prepareLoadByHandle(advHandle, GAP_ADV_FREE_OPTION_ADV_DATA );
    DebugPrint_g( "PLdByHndl=", status );
    }
    /* Copy data in send buffer */
    UTIL_MemCpy( TxDataBuffer, aData_p, nLen_p );
    status = GapAdv_loadByHandle(advHandle, GAP_ADV_DATA_TYPE_ADV, nLen_p,
    TxDataBuffer);
    DebugPrint_g( "LdByHndl=", status );

    // Set event mask for set #1
    GapAdv_setEventMask(advHandle,
    GAP_ADV_EVT_MASK_START_AFTER_ENABLE |
    GAP_ADV_EVT_MASK_END_AFTER_DISABLE |
    GAP_ADV_EVT_MASK_SET_TERMINATED);
    // Enable legacy advertising for set #1
    status = GapAdv_enable(advHandle, GAP_ADV_ENABLE_OPTIONS_USE_DURATION , 90u);
    }

    I feel similarly I should change below scan code as well as there are some fixed changes that needs to be done once after boot, and then only GapScan_enable(0, 0, 0); or GapScan_disable(); is required, what's your view,

     

    below is my code for enabling scan.

    void multi_role_enableScan( void )
    {
    uint8_t temp8;

    // Setup scanning

    // Register callback to process Scanner events
    GapScan_registerCb(multi_role_scanCB, NULL);

    // Set Scanner Event Mask
    GapScan_setEventMask(GAP_EVT_SCAN_ENABLED | GAP_EVT_SCAN_DISABLED |
    GAP_EVT_ADV_REPORT);

    // Set Scan PHY parameters
    #ifdef cConfigChngByUart
    GapScan_setPhyParams(DEFAULT_SCAN_PHY| SCAN_PRIM_PHY_CODED, (GapScan_ScanType_t)(nScanType),
    nScanInterval, nScanWindow);
    #else
    GapScan_setPhyParams(DEFAULT_SCAN_PHY| SCAN_PRIM_PHY_CODED, DEFAULT_SCAN_TYPE,
    DEFAULT_SCAN_INTERVAL, DEFAULT_SCAN_WINDOW);
    #endif
    temp8 = SCAN_FLT_DUP_ENABLE;
    GapScan_setParam(SCAN_PARAM_FLT_DUP, &temp8);
    }

  • Hi Marie,

    with above adv code I could able to advertise data, but after some time my events stopped coming, on analysis I observed . ICall_malloc method return null pointer in below method, and as a result no event enqueues. It looks like with this modification my code is running out of Heap, while this is not happening if I revert back to previous Advertise code.

    Any Idea what is causing this, and what correction/modification required in this latest code. 

    static status_t multi_role_enqueueMsg(uint8_t event, void *pData)
    {
    uint8_t success;
    mrEvt_t *pMsg = ICall_malloc(sizeof(mrEvt_t));

  • Hi Marie,

    When I have changed code as below things start working, but it is not as per your recommendation. can you please look into this and suggest what went wrong. You can email me on jagdish.kushwaha@securemeters.com to quickly resolve this. Its urgent now to fix this.

    {
    static uint8_t IsAdvCreated = cFalse;
    uint8_t status = FAILURE;

    // if( IsAdvCreated == cFalse )
    // {
    // IsAdvCreated = cTrue;
    status = GapAdv_create(&multi_role_advCB, &advParams1,&advHandle);
    DebugPrint_g( "AdvCreate=", status );
    // }
    // else
    {
    // TOJLFSDJFLKS CHECK THIS TOMORROW.
    // status = GapAdv_disable(advHandle);
    // DebugPrint_g( "AdvDis=", status );
    //
    // status = GapAdv_prepareLoadByHandle(advHandle, GAP_ADV_FREE_OPTION_ADV_DATA );
    // DebugPrint_g( "PLdByHndl=", status );
    }
    status = GapAdv_prepareLoadByHandle(advHandle, GAP_ADV_FREE_OPTION_ADV_DATA );
    DebugPrint_g( "PLdByHndl=", status );

    /* Copy data in send buffer */
    UTIL_MemCpy( TxDataBuff, aData_p, nLen_p );
    status = GapAdv_loadByHandle(advHandle, GAP_ADV_DATA_TYPE_ADV, nLen_p,
    TxDataBuff);
    DebugPrint_g( "LdByHndl=", status );

    // Set event mask for set #1
    GapAdv_setEventMask(advHandle,
    GAP_ADV_EVT_MASK_START_AFTER_ENABLE |
    GAP_ADV_EVT_MASK_END_AFTER_DISABLE |
    GAP_ADV_EVT_MASK_SET_TERMINATED);
    // Enable legacy advertising for set #1
    status = GapAdv_enable(advHandle, GAP_ADV_ENABLE_OPTIONS_USE_DURATION , 90u);
    DebugPrint_g( "AdvEnabl=", status );
    }

  • Hi Jai,

    Regarding gap scanner: There is no init or create function you need to call. If you wish, you can collect the following API calls in one function that is only called once:

    - GapScan_registerCb()

    - GapScan_setEventMask()

    - all GapScan_setParam()

    - all GapScan_setPhyParams()

    Jai, could you send me the version of multi_role.c where you see the memory leak?

  • hi Marie,

    thanks for your reply, the multi_role.c file is same as I have sent earlier, only below function is changed rest code is same 

    void multi_role_enableAdvert(
    uint8_t aData_p[],
    uint8_t nLen_p,
    uint8_t nRetry_p,
    uint16_t nDuration,
    uint8_t IsScanEn )
    {
      static uint8_t IsAdvCreated = cFalse;
      uint8_t status = FAILURE;
    
      if( IsAdvCreated == cFalse )
      {
        IsAdvCreated = cTrue;
        status = GapAdv_create(&multi_role_advCB, &advParams1,&advHandle);
        DebugPrint_g( "AdvCreate=", status );
      }
      else
      {
        status = GapAdv_disable(advHandle);
        DebugPrint_g( "AdvDis=", status );
    
        status = GapAdv_prepareLoadByHandle(advHandle, GAP_ADV_FREE_OPTION_ADV_DATA );
        DebugPrint_g( "PLdByHndl=", status );
      }
      /* Copy data in send buffer */
      UTIL_MemCpy( TxDataBuffer, aData_p, nLen_p );
      status = GapAdv_loadByHandle(advHandle, GAP_ADV_DATA_TYPE_ADV, nLen_p, TxDataBuffer);
      DebugPrint_g( "LdByHndl=", status );
    
      // Set event mask for set #1
      GapAdv_setEventMask(advHandle,
      GAP_ADV_EVT_MASK_START_AFTER_ENABLE |
      GAP_ADV_EVT_MASK_END_AFTER_DISABLE |
      GAP_ADV_EVT_MASK_SET_TERMINATED);
      // Enable legacy advertising for set #1
      status = GapAdv_enable(advHandle, GAP_ADV_ENABLE_OPTIONS_USE_DURATION , 90u);
    }

    Please note if I comment below line from code I observed memory leak problem does not come and my device do transmission, at the moment data transmitted is same as I want but it is not as per your recommendation, I don't  know why this is happening??

    status = GapAdv_prepareLoadByHandle(advHandle, GAP_ADV_FREE_OPTION_ADV_DATA );
    DebugPrint_g( "PLdByHndl=", status );

    I also come to know, each of these API have associated events, in my code I am not taking any action on any of these events, do I have wait till next event come?? but I did not find any such recommendation.

    One more help required Marie,

    I want to receive message from a specific MAC address only, I want to white list few Mac address how can I do this, Please let me know the API that do this. in sample application some HCI api is used but it is give compilation error with my code.

    thanks

    Jai

  • Hi Jai,

    The variable IsAdvCreated will always be cFalse since it's reset every time you call multi_role_enableAdvert(). If you want to use this variable it should be implemented as a global variable. 

    If you use the free option GAP_ADV_FREE_OPTION_ADV_DATA you should allocate a new advertisement data buffer (since it has been freed).

    GapAdv_prepareLoadByHandle() will disable advertising (if enabled) so it is not necessary to call GapAdv_disable() first. 

    I think in your case it might me better to use GapAdv_prepareLoadByBuffer and GapAdv_loadByBuffer. Let me know what you think.

    On the second topic: You can use what is called an Accept list (previously white list). There are several stages where you can check peer device against an Accept list. I suggest you implement only accepting connections from peer device on the Accept list. 

    During device initiation you can make the Accept list by adding the addresses of the peer devices. The command is HCI_LE_AddWhiteListCmd() Link:

    Then when you set up advertising you can set the filter policy to only accept requests from devices on the Accept list.

    https://dev.ti.com/tirex/content/simplelink_cc13x2_26x2_sdk_4_20_01_04/docs/ble5stack/ble_user_guide/doxygen/ble/html/group___gap_adv___constants.html#gab808d7d2d87b7ca5f358959986f85112 

  • Hi Marie,

    By now I assume you have better understanding on my application, and your each answers are inline to that and specific to my application, not any generic.

    We are trying to fix for a long time, but it still taking time as its have a latency of 1 day, I have to wait for a day to get your reply. can we look some other way of communication to speed up this, like a meeting request on daily basis or some messenger chat.

    Here are my comments and question  on your reply, I would request you to comment on all of them.

    1.  IsAdvCreated is a static variable, so it will be cfalse once  on power up, not on every function call . I will make it global but it will not make any difference.

    2. GapAdv_prepareLoadByHandle as per your earlier suggestion, I don't know which option I should use with this, as in my application we are only using advertisement so I though to use GAP_ADV_FREE_OPTION_ADV_DATA. please note I am doing what you are suggesting, so please suggest things in detail and in full, i wont mind reading a long reply, rather then a short and incomplete one. let me know what is a correct option with this API.

    3. As mentioned in my code "TxDataBuffer" is my global buffer that is used to fill with the data that needs to be advertise, I don't know which one is the correct API. My only requirement is to advertise different data as per my application need, I hope you are now understand my use case and you know it better which API ( GapAdv_prepareLoadByBuffer and GapAdv_loadByBuffer. or something else) suits my requirement to please suggest accordingly, I can do experiment for you, but I need a firm solution.

    4. Any guess on memory leak, and why my application work if I comment below  lines in the above code in

    multi_role_enableAdvert method , you did not responded to this question earlier. Please respond this time.

    status = GapAdv_prepareLoadByHandle(advHandle, GAP_ADV_FREE_OPTION_ADV_DATA );
    DebugPrint_g( "PLdByHndl=", status );

    5. Regarding white list my query was, as I broadcast data and after that I start scan to listen data, but I want to listen data from a specific MAC address, not from any MAC address, so what I can do to enable this filter in my application, I would appreciate if you write few lines of code in multirole application, compile it and then give it to me, as I mentioned in my earlier post I could find some HCI api's but those are giving me compilation errors. 

    6. You also did not respond to below question, as I requested may time please comment on every points, if you did not understand my  question please ask? 

    I also come to know, each of these API have associated events, in my code I am not taking any action on any of these events, do I have wait till next event come?? but I did not find any such recommendation.

  • Hi Marie,

    Is it possible for you to modify multirole.c file, according to the suggestions your are giving to meet my requirement of Advertisement and then scanning. I will test that and revert back to you.

    regards

    Jai.  

  • Hi Marie,

    regarding Point 2.

    yes your understanding is correct, my application do two thing periodic and on button press, but in both advertise data is not fixed it keep on changing. Let me explain in periodic advertise application advertise temperature data, which changes on every measurements.

    on button press, my application send data according to which button is pressed.

    so my application need is to advertise different data each time, not like as used in multirole sample application, it always broadcast same data, so I am looking for setting for this requirement, 

    I hope it help to eliminate few confusions.

  • hi Marie,

    above reply is a response to the last point of below post of 23 sep 2020

    In reply to jai kushwaha:

    Hi Jai,

    You can consider changing the eventProps value but it's not necessary.

    2.d. I don't expect you to need to change the event mask, I would recommend calling GapAdv_setEventMask() in the "initiate_advertising" function. 

    1. No, just every power up (after device has been in shutdon). Not necessary to call after every sleep.

    2. As far as I understood you use-case, you have two different situations for when to advertise. (One periodic, one is triggered by a button.) In this case it could make sense to have two different advertisement sets that handles the two different situations. If I misunderstood then I apologize. 

    Cheers,
    Marie H.

  • Hi Jai,

    I understand your frustration. If you wish we can set up a call. Please ask Chander to set it up. We can move the communication to e-mail if you prefer. I am confident that we can work through all the things you are seeing

    On my side I feel it would be easier for me if you keep posting the newest version of your source files. This helps me understand where you are at, what code changes you have made etc.

    On to your questions and comments.

    1.  IsAdvCreated is a static variable, so it will be cfalse once  on power up, not on every function call . I will make it global but it will not make any difference.

    [Marie] Ok.

    2. GapAdv_prepareLoadByHandle as per your earlier suggestion, I don't know which option I should use with this, as in my application we are only using advertisement so I though to use GAP_ADV_FREE_OPTION_ADV_DATA. please note I am doing what you are suggesting, so please suggest things in detail and in full, i wont mind reading a long reply, rather then a short and incomplete one. let me know what is a correct option with this API.

    [Marie] If you look into the GapAdv_prepareLoadByHandle() documentation you will see that there is a double-copying when you only have one advertisement set. This is why I suggested you use GapAdv_prepareLoadByBuffer(). If you look in the documentation for this API you will see that there is a note on double-copying there as well.

    3.  As mentioned in my code "TxDataBuffer" is my global buffer that is used to fill with the data that needs to be advertise, I don't know which one is the correct API. My only requirement is to advertise different data as per my application need, I hope you are now understand my use case and you know it better which API ( GapAdv_prepareLoadByBuffer and GapAdv_loadByBuffer. or something else) suits my requirement to please suggest accordingly, I can do experiment for you, but I need a firm solution.

    [Marie] I tried to explain to you that I think you should have two different buffers: 

    - I think you should have a dedicated buffer that holds the advertising data at every point in time, e.g. let's call it advertData. Use this instead of the pointer aData_p. 

    - You can use txDataBuffer to hold the advertising data with the most up to date temperature data.

    - When there is a new temperature reading you can update the temperature data in txDataBuffer

    - When you are ready to update the advertisement data you can copy he data from txDataBuffer to advertData.

    4. Any guess on memory leak, and why my application work if I comment below  lines in the above code in multi_role_enableAdvert method , you did not responded to this question earlier. Please respond this time.

    status = GapAdv_prepareLoadByHandle(advHandle, GAP_ADV_FREE_OPTION_ADV_DATA );
    DebugPrint_g( "PLdByHndl=", status );

    [Marie] Yes. Please see the documentation for GapAdv_prepareLoadByHandle().

    5. Regarding white list my query was, as I broadcast data and after that I start scan to listen data, but I want to listen data from a specific MAC address, not from any MAC address, so what I can do to enable this filter in my application, I would appreciate if you write few lines of code in multirole application, compile it and then give it to me, as I mentioned in my earlier post I could find some HCI api's but those are giving me compilation errors. 

    [Marie] I can help you debug your compile errors. As I said you can use the HCI_LE_AddWhiteListCmd(). There are full instructions in the SimpleLink Academy lab Advanced Security features, task 3:

    6. You also did not respond to below question, as I requested may time please comment on every points, if you did not understand my  question please ask? 

    I also come to know, each of these API have associated events, in my code I am not taking any action on any of these events, do I have wait till next event come?? but I did not find any such recommendation.

    [Marie] It depends on the situation. If it's not mentioned in the documentation you should be ok moving on with the code. If you disable advertising I would recommend you wait for the GAP_EVT_ADV_END_AFTER_DISABLE event.

    7. so my application need is to advertise different data each time, not like as used in multirole sample application, it always broadcast same data, so I am looking for setting for this requirement, 

    [Marie] Just so you know this is a slightly unusual way of writing a BLE application. Normally I would recommend forming a connection with the BLE central device and transmit the data through a GATT service. I do think your approach can work.

  • Thanks Marie for your continued support on the issues in this project.

    I have invited all team members on txn.box.com for easy and safe file sharing.

    Regards,

    Chander 

  • Hi Marie,

    Thanks for your detailed reply, 

    I have few more question on few of your replies.\

    1. [Marie] If you look into the GapAdv_prepareLoadByHandle() documentation you will see that there is a double-copying when you only have one advertisement set. This is why I suggested you use GapAdv_prepareLoadByBuffer(). If you look in the documentation for this API you will see that there is a note on double-copying there as well.

    Jag:- can you please explain what values of  arguments passed in GapAdv_prepareLoadByBuffer() API, I have TxDataBuff that is copied with the content that needs to be transmitted, I assume its address, will  first argument, I am not sure what value should be passed in freeOldData.

    2. [Marie] I tried to explain to you that I think you should have two different buffers: 

    - I think you should have a dedicated buffer that holds the advertising data at every point in time, e.g. let's call it advertData. Use this instead of the pointer aData_p. 

    Jag. My TxDataBuff is same as you explain like advertData buff, whenever I want to transmit data using multi_role_enableAdvert the data is copied to TxDataBuff  from aData_p. I could not understand what do you mean by having two buffer please explain.

    3. [Marie] Yes. Please see the documentation for GapAdv_prepareLoadByHandle().

    Jag: I did read documentation, but couldn't get why is result in memory leak, and why my code works when I have commented above mentioned line, can you elaborate it more.

    4.[Marie] It depends on the situation. If it's not mentioned in the documentation you should be ok moving on with the code. If you disable advertising I would recommend you wait for the GAP_EVT_ADV_END_AFTER_DISABLE event.

    Jag:- If i use either of any API, _preparebyHandle, or _preparebyBuffer both will disable Adv, so in this case too I have to wait for above event or not. 

    5. I have done some modification in the multirole file (please refer attached files) and it observe working for now, it is under testing.  can you review attached file and modify it according to whatever you feel correct. I think it will be a good option if you spend some time to modify my code. I will test it and let you know

    6. In this modified code whenever multi_role_enableAdvert called first time after boot (power up), GapAdv_prepareLoadByHandle give bleGAPNotFound  I can understand this come, but can it create some issue, as in next advertisement it give success.

    7. If you feel above code is ok, then I do not need to do any experiment with preparedLoadbyBuffer or do you still think loadbyBuffer is the only option??ToShareWithTi.rar

  • Hi Jai,

    1. Jag:- can you please explain what values of  arguments passed in GapAdv_prepareLoadByBuffer() API, I have TxDataBuff that is copied with the content that needs to be transmitted, I assume its address, will  first argument, I am not sure what value should be passed in freeOldData.

    [Marie] Since you have only one advertising set you can use GAP_ADV_FREE_OPTION_DONT_FREE for freeOldData. 

    2. Jag. My TxDataBuff is same as you explain like advertData buff, whenever I want to transmit data using multi_role_enableAdvert the data is copied to TxDataBuff  from aData_p. I could not understand what do you mean by having two buffer please explain.

    [Marie] My concern is that TxDataBuff is used several places in the code for several different things. I woul prefer that you have control over the advertising data buffer and just control it with the gapadv APIs.

    3. Jag: I did read documentation, but couldn't get why is result in memory leak, and why my code works when I have commented above mentioned line, can you elaborate it more.

    [Marie] This is the passe I am referring to:

    For case 2, in order to prevent double-copying, the data that was being used by the advertising set should be freed before calling GapAdv_loadByHandle. It is recommended that this is done by setting the freeOptions of GapAdv_prepareLoadByHandle . This will prompt the host to search through other advertising sets to ensure that the data buffer is not being used elsewhere. If the data is being used elsewhere, the free will not occur and bleGAPBufferInUse will be returned. In this case, there are now two options to update this advertising data.

    4. Jag:- If i use either of any API, _preparebyHandle, or _preparebyBuffer both will disable Adv, so in this case too I have to wait for above event or not. 

    Yes, you should wait for the GAP_EVT_ADV_END_AFTER_DISABLE event before proceding.

    5. I have done some modification in the multirole file (please refer attached files) and it observe working for now, it is under testing.  can you review attached file and modify it according to whatever you feel correct. I think it will be a good option if you spend some time to modify my code. I will test it and let you know

    [Marie] I couldn't find where you inserted the accept list (previously white list) command.

    6. In this modified code whenever multi_role_enableAdvert called first time after boot (power up), GapAdv_prepareLoadByHandle give bleGAPNotFound  I can understand this come, but can it create some issue, as in next advertisement it give success.

    [Marie] bleGAPNotFound is returned when you call GapAdv_prepareLoadByHandle() before GapAdv_create(). To avoid this I would load advertising data in multi_role_advertInit(). (Using just GapAdv_loadByHandle(), not any prepare function.)

    7. If you feel above code is ok, then I do not need to do any experiment with preparedLoadbyBuffer or do you still think loadbyBuffer is the only option??

    [Marie] I would modify as explained in 6. and retest.

  • Hi Marie,

    Thanks for your reply,

    I want more clarification on below some points

    1. [Marie] bleGAPNotFound is returned when you call GapAdv_prepareLoadByHandle() before GapAdv_create(). To avoid this I would load advertising data in multi_role_advertInit(). (Using just GapAdv_loadByHandle(), not any prepare function.)

    Jag:- GapAdv_prepareLoadByHandle is called after GapAdv_create as, GapAdv_create is called when my device powered up in multi_role_advertInit(). Please re-review my multirole file and suggest modificatin.

    I will add  GapAdv_loadByHandle(), in  multi_role_advertInit(), and test it again. I assume rest things is OK in  multi_role_advertInit().

    2. [Marie] I couldn't find where you inserted the accept list (previously white list) command.

    Jag:- I will test accept list later on, as of now I am concerned about adv data.

    with the conversation above I assume you are OK with to use, lodebyhandle, and not loadbybuffer. Please give your views.

     3. [Marie] My concern is that TxDataBuff is used several places in the code for several different things. I woul prefer that you have control over the advertising data buffer and just control it with the gapadv APIs.

    Jag:- I think I am not able to explain you, or I am not getting what you are trying to explain.

    If you see my recent multiroll.c file TxDataBuff  is a global buffer, that is filled with the data I want to transmitt, and this is done after calling prepareloadbyHandle API.

    TxDataBuff  is having different data each time, and it is loaded in multi_role_enableAdvert method, from aData_p. 

    4. Yes, you should wait for the GAP_EVT_ADV_END_AFTER_DISABLE event before proceding.

    Jag:- with this I understand after calling GapAdv_prepareLoadByHandle in  multi_role_enableAdvert ( line no 1009 in multirole.c)

    I should not proceed with below swithch case.

    UTIL_MemCpy( TxDataBuff, aData_p, nLen_p );
    status = GapAdv_loadByHandle(advHandle, GAP_ADV_DATA_TYPE_ADV, nLen_p,
    TxDataBuff);
    status = GapAdv_enable(advHandle, GAP_ADV_ENABLE_OPTIONS_USE_DURATION , 90u);

    this code should be written in 

    static void multi_role_processAdvEvent(mrGapAdvEventData_t *pEventData)
    {
    switch (pEventData->event)
    {
    case GAP_EVT_ADV_START_AFTER_ENABLE:
    break;

    5. I will appreciate if you write few lines of code, that have suggestion your are recommending for point 4 above.

    thank you

    Jai 

  • Hi Jai,

    1. Jag:- GapAdv_prepareLoadByHandle is called after GapAdv_create as, GapAdv_create is called when my device powered up in multi_role_advertInit(). Please re-review my multirole file and suggest modificatin.

    I will add  GapAdv_loadByHandle(), in  multi_role_advertInit(), and test it again. I assume rest things is OK in  multi_role_advertInit().

    [Marie] GapAdv_prepareLoadByHandle() will only return bleGAPNotFound if it cannot find an advertiser set with the handle you passed. Can you pause a debug session when this appens and check the advertisement set handle?

    2. Jag:- I will test accept list later on, as of now I am concerned about adv data.

    with the conversation above I assume you are OK with to use, lodebyhandle, and not loadbybuffer. Please give your views.

    [Marie] That's fine.

    3. Jag:- I think I am not able to explain you, or I am not getting what you are trying to explain.

    If you see my recent multiroll.c file TxDataBuff  is a global buffer, that is filled with the data I want to transmitt, and this is done after calling prepareloadbyHandle API.

    TxDataBuff  is having different data each time, and it is loaded in multi_role_enableAdvert method, from aData_p. 

    [Marie] As long as there is no danger of this buffer being used by several sources when itæs also used for advertisements.

    4. this code should be written in 

    static void multi_role_processAdvEvent(mrGapAdvEventData_t *pEventData)
    {
    switch (pEventData->event)
    {
    case GAP_EVT_ADV_START_AFTER_ENABLE:
    break;

    [Marie] Yes, if this is the only scenario where advertisements are being disabled.

    5. I will appreciate if you write few lines of code, that have suggestion your are recommending for point 4 above.

    [Marie] For advertising handle you can use pEventData->pBuf (you can cast it to uint8_t).

  • Hi Marie,

    I am facing an issue with sleep mechanism. my application is configured to go in sleep but sometimes I observed it does not goes in sleep and continuously consume 1 mA current .

    Can you suggest all possible reasons by my application does not goes to sleep. Please note once it reset my application by giving reset pulse to reset pin or power off my device then it goes to sleep and sleep current comes less then 2uA( micro Amp ) current.

     

    I have release constraint using below API and both reruns success, 

    Power_releaseConstraint(PowerCC26XX_SB_DISALLOW);

    Power_releaseConstraint(PowerCC26XX_IDLE_PD_DISALLOW); 

    Please find my attached source code file. It calls "PTD_ReadyForSleep_g" to put  everything according to device sleep state.

    /** @file           PTD_main.c
    *   @copyright      Copyright (c) 2016 Secure International Holdings Pte. Ltd.
    *   @author         Written by: Jagdish Kushwaha
    *   @date           Started on:  20/05/2020
    *   @brief          This is a PTD application main file 
    */
    /* *********************************************************************** */
    /* included files */
    #include "util.h"
    #include "Typedef.h"
    #include "PTD_main.h"
    #include "PTDTimer.h"
    #include <ti_drivers_config.h>
    #include <ti/drivers/GPIO.h>
    #include <ti/drivers/rf/RF.h>
    #include "ti_drivers_config.h"
    #include <ti/drivers/PIN.h>
    #include <ti/drivers/pin/PINCC26XX.h>
    
    #include "Commissioning.h"
    #include "Data.h"
    #include "Flash.h"
    #include "Aes128.h"
    #include "LCD.h"
    #include "Ble.h"
    #include "Production.h"
    #include "PTDScreen.h"
    #include "HDCSensor.h"
    #include "Schedular.h"
    #include "multi_role.h"
    #include <ti/sysbios/knl/Task.h>
    #include "ll_common.h"
    #include <ti/drivers/Power.h>
    #include <ti/drivers/power/PowerCC26XX.h>
    #include <unistd.h>
    #include "keypad.h"
    #include "TimeSetting.h"
    #include "UserInterface.h"
    #include "SmlUtil.h"
    #include "DisplayLCD.h"
    #include <ti/drivers/Watchdog.h>
    /* ======================================================================= */
    
    /* #defines */
    /* ----------------------------------------------------------------------- */
    
    /* type definitions */
    
    /* ----------------------------------------------------------------------- */
    
    /* definitions of static (local) variables */
    /** 
     PTD state machine clock comes at every 10ms
    */
    static Clock_Struct PtdCommissionClock;
    static tePtdState PtdTaskState;
    Watchdog_Handle watchdogHandle;
    tUI8 IsDeviceInSleep = cFalse;
    tUI8 CommissioningTimer;        /* decrement at every cCommissioningFreq  */
    tUI32 nTimTick;
    
    /* ----------------------------------------------------------------------- */
    
    /* definitions of external (global)variables(Use of global is Not recommended)*/
    
    /* ----------------------------------------------------------------------- */
    
    /* definitions of constant data tables */
    
    /* ----------------------------------------------------------------------- */
    
    /* prototypes of local (static) functions */
    void initRfFrontendCustom(void);
    void watchdogCallback(uintptr_t watchdogHandle);
    void PTD_InitWatchDog( void );
    static void PTD_CommissionHandler(UArg a0);
    /* ======================================================================= */
    
    /* ----------------------------------------------------------------------- */
    void PTD_Init_g( void )
    {
      PTD_InitWatchDog( );
      Data_Init_g( );
      GPIO_init( );
      Lcd_Init_g( );
      Ble_Init_g( );
      HDC_Init_g( );
      Flash_Init_g( );
      Screen_InitParam_g( );
      Schedular_InitParam_g( );
      Commissioning_PowerOnInit_g( );
      DateInit_g( );
      UX_ResetAllVariable_g( );
      PtdTaskState = ePtdState_Init;
      Util_constructClock(&PtdCommissionClock, PTD_CommissionHandler,
                          cCommissioningFreq, cCommissioningFreq, false, 0);  
        /* If Top button pressd  enter in production test mode */
    #if cAlwaysProductionMode 
      PtdTaskState = ePtdState_ProductTest;
      Production_TaskInit_g();
    #else /* cAlwaysProductionMode */
    
    #if cDebugUartEnable
      Production_TaskInit_g();
    #endif
      
      if( Flash_IsPtdCommissioned_g( ) == cPtdCommissioned ) 
      { /* Configure HDC sensor if PTD commissioned else not */
        HDC_ConfigSensor_g();
      }else{}
      
      if (PIN_getInputValue(CONFIG_PIN_0) == 0)
      {
        /* Giving 100 Ms Delay Checking Debounce to avoide false production mode */
        Task_sleep(100*100);
        if (PIN_getInputValue(CONFIG_PIN_0) == 0)
        {
          PtdTaskState = ePtdState_ProductTest; 
          Production_TaskInit_g();
        }else{}  
      }else{}
    #endif  /* cAlwaysProductionMode */
      PTD_StartTask_g();
    
    #ifdef cTestEnable  
      #include "Testing.h"
      PtdTaskState = ePtdState_Normal;
      HDC_ConfigSensor_g( );
      LoadDefaultData();
    #endif
    
    #ifdef cDisableSleep  
      Power_disablePolicy();
    #endif  
    }
    
    static void PTD_CommissionHandler(UArg a0)
    {
      if( CommissioningTimer > 0 )
      {
        CommissioningTimer--;
        PTD_StartTask_g();
      }  
    }
    /* ----------------------------------------------------------------------- */
    void PTD_Task_g( void )
    {
      tUI8 aBuff[ 2u ];
      tCommissioningStatus CommissStatus;
      static tUI32 PtdTaskTick;
      
      IsDeviceInSleep = cFalse;
      PTD_FeedWatchDog();
      Lcd_Task_g();
      Timer_UpdateTick_g();
      (void) BLE_CommsFsm_g( );
    
    #ifdef cConfigChngByUart
      Production_TaskRun_g();
    #endif
      
    #if defined( cTestEnable ) || defined( cPacketSniffer )  
      #include "Testing.h"  
      #ifdef cPacketSniffer  
        static tUI8 blEnableScan = cTrue;
          if( blEnableScan )
          {
            blEnableScan = cFalse;
            BLE_EnableScan_g();
            tUI8 status;
            status = HCI_LE_ClearWhiteListCmd();        
          }
      #else
        Testing_g( );    
      #endif
    #else  
      switch( PtdTaskState )
      {
        case ePtdState_Init:
          /* PTD will wakeup from deep sleep */
          if( cPtdCommissioned == Flash_IsPtdCommissioned_g( ) )
          {
            Ble_ReadData_g( eDataReqUpdate );
            PtdTaskState = ePtdState_Normal; 
          }  
          else
          {
            Lcd_AllOff_g( );
            Display_UpdateGuidingArea2Text_g( "TO SETUP    ",12u, cFlashDisable );
            Display_UpdateGuidingArea1_g( "HOLD MENU BUTTON", cFlashDisable );
            Lcd_Update_g( );    
            PtdTaskState = ePtdState_WaitToStart;
            PtdTaskTick = Timer_GetTick_g( );
          }
          break;
      case ePtdState_WaitToStart:
          if( Keypad_GetEvent_g( cKey_Top ) == eKeyEvent_Hold )
          {
            Keypad_GetEvent_g( cKey_ClearAllEvt );
            PtdTaskState = ePtdState_Commissioning;
            Commissioning_InitParam_g( eDevTypePTD );
            if (!Util_isActive(&PtdCommissionClock))
            {
             Util_startClock(&PtdCommissionClock);
             CommissioningTimer = cCommissioningTout;
            }
            else{}       
          }else if( cTrue == Timer_IsOver_g( PtdTaskTick, cStartCommissionTimeout ))
          {
            PtdTaskState = ePtdState_Sleep;
          }
          else{}  
          break;
          
        case ePtdState_ProductTest:
          if( cTrue == Production_TaskRun_g() )
          {
            Production_Sleep_g();
            PtdTaskState = ePtdState_Sleep;
            if( Flash_IsPtdCommissioned_g( ) == cPtdCommissioned ) 
            { /* Configure HDC sensor if PTD commissioned else not */
              HDC_ConfigSensor_g();
            }
            else{}
          }else{}
          break;
        case ePtdState_Commissioning:
          CommissStatus = Commissioning_Task_g( );
          if( CommissStatus == eStatus_Success )
          {
            Screen_ResetTick_g( );
            aBuff[ 0u ] = cPtdCommissioned;
            Flash_WriteData( eFlashCommissFlag, 1u, aBuff );
            Screen_CreateMenu_g( cScreenDefault );
            if (Util_isActive(&PtdCommissionClock))
            {
              Util_stopClock(&PtdCommissionClock);
            }        
            PtdTaskState = ePtdState_Normal;
          }
          else if( CommissStatus == eStatus_Back )
          { /* If commissioning duration expire go to sleep */
            if( CommissioningTimer == 0u )
            {  
              PtdTaskState = ePtdState_Sleep;
              if (Util_isActive(&PtdCommissionClock))
              {
                Util_stopClock(&PtdCommissionClock);
              }
            }
            else
            {/* Sleep here Commissioning clock will wakeup */
              Util_restartClock(&PtdCommissionClock, cCommissioningFreq);
              PTD_ReadyForSleep_g();
            }                       
          }      
          else{}
          if( Keypad_GetEvent_g( cKeyBack ) == eKeyEvent_Pressed )
          {
            (void)Keypad_GetEvent_g( cKey_ClearAllEvt );
            Screen_CreateMenu_g( cScreenFactoryReset );
            PtdTaskState = ePtdState_Normal;
          }else{}
          break;
        case ePtdState_Normal:
          if( cTrue == Screen_Display_g( ) )
          {
            PtdTaskState = ePtdState_Sleep; 
          }
          break;
          
        case ePtdState_Sleep:
        /* If any key is pressed */
          if(Keypad_IsKeyPressed_g() == cTrue )
          {/* Clear all key event after wake up */
            Keypad_GetEvent_g( cKey_ClearAllEvt );
            PtdTaskState = ePtdState_Init; 
          }else if (BLE_CommsFsm_g() == cTrue ) /* Safe to sleep */
          {
            PTD_ReadyForSleep_g();
          }else{}
          break;      
        default:
          PtdTaskState = ePtdState_Sleep;
          break;
      }
    #endif
    }
    /* ----------------------------------------------------------------------- */
    void PTD_Task_NextStage( void )
    {
      if( Flash_IsPtdCommissioned_g( ) != cPtdCommissioned ) 
      {
        PtdTaskState = ePtdState_Commissioning;
        Commissioning_InitParam_g( eDevTypePTD );
      }
      else
      {
        PtdTaskState = ePtdState_Normal;
      }            
    }  
    /* ----------------------------------------------------------------------- */
    void PTD_ReadyForSleep_g( void )
    {
      tUI8 aBuf_p[16u ];
        
      tUI8 Status;
      BLE_DisableScan_g();
      PTD_StopTask_g();
      Screen_ResetAll_g( );
      BLE_StopSensorBroadCast_g( cFalse );
      Keypad_Sleep_g();    
      Commissioning_InitVariableOnSleep_g( );
      UX_ResetAllVariable_g( );
      Status = Power_releaseConstraint(PowerCC26XX_SB_DISALLOW);
      UTIL_CnvrtHexToAscii( Status, aBuf_p );  
      Lcd_AllOff_g( );
      Display_UpdateGuidingArea2Text_g( aBuf_p,2u, cFlashDisable );
      Lcd_Update_g( );      
      Task_sleep(2000*100);
      Status = Power_releaseConstraint(PowerCC26XX_IDLE_PD_DISALLOW); 
      UTIL_CnvrtHexToAscii( Status, aBuf_p );  
      Lcd_AllOff_g( );
      Display_UpdateGuidingArea2Text_g( aBuf_p,2u, cFlashDisable );
      Lcd_Update_g( );
      Task_sleep(2000*100);
      Lcd_Sleep_g();
      IsDeviceInSleep = cTrue;
      Rtc_Sleep_g();
    }
    /* ----------------------------------------------------------------------- */
    /*
     * ======== Antenna switching ========
     */
    /*
     * ======== rfDriverCallbackAntennaSwitching ========
     * Function to handle antenna switching.
     */
    void rfDriverCallbackAntennaSwitching(RF_Handle client, RF_GlobalEvent events, void *arg)
    {
    
        static PIN_Handle antennaPins;
        static PIN_State antennaState;
        /* Protect against repeated RF_init */
        static bool initialized = false;
    
        /* Local variable. */
        bool    sub1GHz   = false;
        uint8_t loDivider = 0;
    
        if (!initialized && events & RF_GlobalEventInit) 
        {
          /* Don't do it again */
          initialized = true;
          PIN_Config antennaConfig[] = {
          CONFIG_RF_24GHZ | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,      /* Path disabled */
          CONFIG_RF_HIGH_PA | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,      /* Path disabled */
          CONFIG_RF_SUB1GHZ | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,      /* Path disabled */
          PIN_TERMINATE
          };
          antennaPins = PIN_open(&antennaState, antennaConfig);
        }
        else if (events & RF_GlobalEventRadioSetup) 
        {
          /* Switch off all paths. */
          PINCC26XX_setOutputValue(CONFIG_RF_24GHZ, 0);
          PINCC26XX_setOutputValue(CONFIG_RF_HIGH_PA, 0);
          PINCC26XX_setOutputValue(CONFIG_RF_SUB1GHZ, 0);
    
          /* Decode the current PA configuration. */
          RF_TxPowerTable_PAType paType = (RF_TxPowerTable_PAType)RF_getTxPower(client).paType;
    
          /* Decode the generic argument as a setup command. */
          RF_RadioSetup* setupCommand = (RF_RadioSetup*)arg;
    
          switch (setupCommand->common.commandNo) 
          {
            case (CMD_RADIO_SETUP):
            case (CMD_BLE5_RADIO_SETUP):
                loDivider = RF_LODIVIDER_MASK & setupCommand->common.loDivider;
    
                /* Sub-1GHz front-end. */
                if (loDivider != 0) {
                    sub1GHz = true;
                }
                break;
            case (CMD_PROP_RADIO_DIV_SETUP):
                loDivider = RF_LODIVIDER_MASK & setupCommand->prop_div.loDivider;
    
                /* Sub-1GHz front-end. */
                if (loDivider != 0) {
                    sub1GHz = true;
                }
                break;
            default:break;
          }
    
          if (sub1GHz) 
          {
              /* Sub-1 GHz */
              if (paType == RF_TxPowerTable_HighPA) {
                  /* PA enable --> HIGH PA
                   * LNA enable --> Sub-1 GHz
                   */
                  PINCC26XX_setMux(antennaPins, CONFIG_RF_24GHZ, PINCC26XX_MUX_GPIO);
                  /* Note: RFC_GPO3 is a work-around because the RFC_GPO1 (PA enable signal) is sometimes not
                           de-asserted on CC1352 Rev A. */
                  PINCC26XX_setMux(antennaPins, CONFIG_RF_HIGH_PA, PINCC26XX_MUX_RFC_GPO3);
                  PINCC26XX_setMux(antennaPins, CONFIG_RF_SUB1GHZ, PINCC26XX_MUX_RFC_GPO0);
              } else {
                  /* RF core active --> Sub-1 GHz */
                  PINCC26XX_setMux(antennaPins, CONFIG_RF_24GHZ, PINCC26XX_MUX_GPIO);
                  PINCC26XX_setMux(antennaPins, CONFIG_RF_HIGH_PA, PINCC26XX_MUX_GPIO);
                  PINCC26XX_setMux(antennaPins, CONFIG_RF_SUB1GHZ, PINCC26XX_MUX_GPIO);
                  PINCC26XX_setOutputValue(CONFIG_RF_SUB1GHZ, 1);
              }
          } else {
              /* 2.4 GHz */
              if (paType == RF_TxPowerTable_HighPA)
              {
                  /* PA enable --> HIGH PA
                   * LNA enable --> 2.4 GHz
                   */
                  PINCC26XX_setMux(antennaPins, CONFIG_RF_24GHZ, PINCC26XX_MUX_RFC_GPO0);
                  /* Note: RFC_GPO3 is a work-around because the RFC_GPO1 (PA enable signal) is sometimes not
                           de-asserted on CC1352 Rev A. */
                  PINCC26XX_setMux(antennaPins, CONFIG_RF_HIGH_PA, PINCC26XX_MUX_RFC_GPO3);
                  PINCC26XX_setMux(antennaPins, CONFIG_RF_SUB1GHZ, PINCC26XX_MUX_GPIO);
              } else {
                  /* RF core active --> 2.4 GHz */
                  PINCC26XX_setMux(antennaPins, CONFIG_RF_24GHZ, PINCC26XX_MUX_GPIO);
                  PINCC26XX_setMux(antennaPins, CONFIG_RF_HIGH_PA, PINCC26XX_MUX_GPIO);
                  PINCC26XX_setMux(antennaPins, CONFIG_RF_SUB1GHZ, PINCC26XX_MUX_GPIO);
                  PINCC26XX_setOutputValue(CONFIG_RF_24GHZ, 1);
              }
          }
        }
        else if (events & RF_GlobalEventRadioPowerDown) {
            /* Switch off all paths. */
            PINCC26XX_setOutputValue(CONFIG_RF_24GHZ, 0);
            PINCC26XX_setOutputValue(CONFIG_RF_HIGH_PA, 0);
            PINCC26XX_setOutputValue(CONFIG_RF_SUB1GHZ, 0);
    
            /* Reset the IO multiplexer to GPIO functionality */
            PINCC26XX_setMux(antennaPins, CONFIG_RF_24GHZ, PINCC26XX_MUX_GPIO);
            PINCC26XX_setMux(antennaPins, CONFIG_RF_HIGH_PA, PINCC26XX_MUX_GPIO);
            PINCC26XX_setMux(antennaPins, CONFIG_RF_SUB1GHZ, PINCC26XX_MUX_GPIO);
        }
    }
    
    #ifdef cEnableWatchDog
    /* ----------------------------------------------------------------------- */
    void PTD_InitWatchDog( void )
    {
      uint32_t        reloadValue;
      Watchdog_Params params;  
      Watchdog_init();
      /* Open a Watchdog driver instance */
      Watchdog_Params_init(&params);
      params.callbackFxn = (Watchdog_Callback) watchdogCallback;
      params.debugStallMode = Watchdog_DEBUG_STALL_ON;
    
      params.resetMode = Watchdog_RESET_ON;
      watchdogHandle = Watchdog_open(CONFIG_WATCHDOG_0, &params);
      if (watchdogHandle == NULL) {
        /* Error opening Watchdog */
        while (1) {}
      }  
      
    //  Watchdog_close(watchdogHandle);
          /*
         * The watchdog reload value is initialized during the
         * Watchdog_open() call. The reload value can also be
         * set dynamically during runtime.
         *
         * Converts TIMEOUT_MS to watchdog clock ticks.
         * This API is not applicable for all devices.
         * See the device specific watchdog driver documentation
         * for your device.
         */
        /* Watchdog reset value is 10 minutes */
        /* Put this value to 70 sec and temperature read rutine called at every 60 sec */
        reloadValue = Watchdog_convertMsToTicks(watchdogHandle, 70*1000);
        /*
         * A value of zero (0) indicates the converted value exceeds 32 bits
         * OR that the API is not applicable for this specific device.
         */
        if (reloadValue != 0) 
        {
            Watchdog_setReload(watchdogHandle, reloadValue);
        }
    }
    /* ----------------------------------------------------------------------- */
    /*
     *  ======== watchdogCallback ========
     */
    void watchdogCallback(uintptr_t watchdogHandle_p)
    {
      /*
       * If the Watchdog Non-Maskable Interrupt (NMI) is called,
       * loop until the device resets. Some devices will invoke
       * this callback upon watchdog expiration while others will
       * reset. See the device specific watchdog driver documentation
       * for your device.
       */
    //  Lcd_AllOff_g();
    //  Display_UpdateGuidingArea1_g("WATCHDOG EXPIRE", 0);
    //  Lcd_Update_g( );
    //  Task_sleep(1000*100);  
      
    #ifdef  cTestWatchDogRst
      #include "SmlUtil.h"
      tUI8 aBuffer[ 16u ];
      tUI32 PresentRstCnt;
      Flash_GetData( eFlashMfgSr, aBuffer );
      PresentRstCnt = UTIL_StrToInt( aBuffer );
      PresentRstCnt++;
      UTIL_MemSet( aBuffer, 0x30, 16u ); /* Making all zero */
      UTIL_IntToStr( PresentRstCnt, aBuffer );
      Flash_WriteData( eFlashMfgSr, 8u, aBuffer );
    #endif
      while (1) {}
    }
    
    /* ----------------------------------------------------------------------- */
    void PTD_FeedWatchDog( void )
    {
      Watchdog_clear(watchdogHandle);
    }
    #else
    /* Dummy methods */
    void PTD_FeedWatchDog( void )
    {
    }
    void PTD_InitWatchDog( void )
    {
    }  
    #endif
    
    tUI8 PTD_GetSleepStatus( void )
    {
      return (IsDeviceInSleep );
    }
    
    /* *********************************************************************** */
    #if ChangeHistory
    /* 
    $Log$
    */
    #endif
    /* End =================================================================== */
    

  • Hi Jai,

    I haven't heard about this issue before. Could you post a screen shot of the power consumption timeline? I am very curious to know what the device is doing just before it fails to go to sleep.

    Can you attach a debugger when this happens and pause the debug session, then post a screen shot of the call stack?

    The power module for CC1352P is not meant to be called explicitly. When nothing else is happening, the device will go to sleep. There is no API you can call to send the device to sleep.

  • Hi Marie,

    This issue is coming in some different situation, when my device receive something from other device, else everything works as desired and sleep current comes below 1uA. But once this problem comes my sleep current stays at ~2mA ( active current). This give me a doubt that it is not going to sleep.

    Please note as I can measure sleep current while device is in debug mode it will be difficult to provide you debug log. But I have captured current log attached with this Ticket.

    Can you tell me what can cause that device does not goes to sleep, I observe a case when it does receiver something from  other device in some specific condition this problem observe. It does not observe when device receive data in normal condition.

    Refer attached files for your kind attention.

    CurrentConsumptionDetails.docx

    /** @file           Ble.c
    *   @copyright      Copyright (c) 2016 Secure International Holdings Pte. Ltd.
    *   @author         Written by: Jagdish Kushwaha
    *   @date           Started on:  06/05/2020
    *   @brief          This file deal with BLE communication 
    */
    /* ======================================================================= */
    /* Includes -------------------------------------------------------------- */
    #include "Ble.h"
    #include "Typedef.h"
    #include "SmlUtil.h"
    #include "Data.h"
    #include "Aes128.h"
    #include "Flash.h"
    #include "ll.h"
    #include "UtilCrcChkSum.h"
    #include "multi_role.h"
    #include "Commissioning.h"
    #include <icall_ble_api.h>
    #include "Production.h"
    #include "PTDTimer.h"
    #include "PTDScreen.h"
    #include "MenuStrings.h"
    #include "TimeSetting.h"
    #include "DisplayLCD.h"
    #include "LCD.h"
    #include "onboard.h"
    /* Defines  -------------------------------------------------------------- */
    
    /* Private typedef ------------------------------------------------------- */
    typedef enum
    {
      eBleRx_Wait,
      eBleRx_Received
    }teBleRx;
    
    typedef struct
    {
      tUI8 nStateId;  
      tUI8 nTxLen;
      tUI8 nRetryCnt;
      tUI8 nWriteCmdRspnc;
      tUI8 nCommsTimeOut;
      teCmd nCmdType;
      teBleRx nRxState;
      teComms_State CommsState;
      tUI8 aSendBuff[ 256u ];
      tUI32 nRcvdMsgTick;
      tUI32 nFsmTick;
    }tBle;
    
    /* Private definition ---------------------------------------------------- */
    typedef enum
    {
      eBle_Idle,
      eBle_WaitBeforeTx,
      eBle_WaitforTx,
      eBle_WaitForRx,
    }teBle_Fsm;
    
    /* Constants -------------------------------------------------------------- */
    static tUI8 caPRT[3] = { 0x50u, 0x52u, 0x54u }; //{ 'P', 'R', 'T' };
    static tUI8 caSCS[3] = { 0x53u, 0x43u, 0x53u };
    
    static tUI8 caBroadcastHeader[cBLE_BroadCastHeaderSize] = 
                 { 2, 1, 6, 4, 9, 'P', 'T', 'D' };
    
    /* Macros ----------------------------------------------------------------- */
    
    /* Private variables ------------------------------------------------------ */
    static tUI32 nHAN_MsgRxCounter;
    static tUI32 nHAN_MsgTxCounter;
    static tUI8  PtdMac[ cMACLen ];
    //static tUI8  ReceiverMac[ cMACLen ] = {0xFFu,0xFFu,0xFFu,0xFFu,0xFFu,0xFFu };
    static tUI8 blStopBroadcast = cFalse;
    tBle Ble;
    tUI8 IsScanEnable = cFalse;
    /* Private function prototypes ------------------------------------------- */
    void Ble_ProcessResponse(  
      tUI16 nMsgLen_p,
      tUI8 aBuff_p[ ] );
    tUI8 BLE_CheckSeqNo( tUI32 nReceivedSeqNo_p );
    void Ble_SendData(tUI8 Data_p[],tUI8 nLength_p,teCmd CmdType_p);
    static tUI8 BLE_GetScanStatus( void );
    static void BLE_SetScanStatus( tUI8 State_p );
    void Ble_ProcessAck(
      tUI8 nDataLength_p,                         
      tUI8 AckData_p[] );
    /* ======================================================================= */
    /* Private functions ----------------------------------------------------- */
    /* ----------------------------------------------------------------------- */
    void Ble_Init_g( void )
    {
      //tUI8 aMac[ cMACLen ];
      nHAN_MsgRxCounter = 0;
      nHAN_MsgTxCounter = 0;
      if ( LL_ReadBDADDR( PtdMac ) != LL_STATUS_SUCCESS )
      {
        PTD_ASSERT(8);
      }else{}
      Ble.CommsState = eComms_Idle;
      Ble.nWriteCmdRspnc = cFalse;
      Ble.nStateId = eBle_Idle;
    }
    /* ----------------------------------------------------------------------- */
    /**
      Retrive data from various tags and store it in data file 
      @param  nMsgLen_p    Total lenght of received data
      @param  aBuff_p      Received Msg buffer
    */
    void Ble_ProcessResponse(  
      tUI16 nMsgLen_p,
      tUI8 aBuff_p[ ] )
    {
      tUI8 nBLE_DataTagId;
      tUI8 nBLE_DataTagLen;
      tUI8 iCount = 0u;
      tUI8 nChannelNum;
    //  tUI32 Temp;
      
      /*Communication successful clear comms error */
      Screen_RegisterWarning_g( eWarning_RxError, cFalse );
      while( iCount < nMsgLen_p )
      {
        if( (nMsgLen_p - iCount) < cBLE_MinDataPayLoadSize )
        {
          break;
        }      
        nBLE_DataTagLen = aBuff_p[ iCount ];
        iCount++;
        nBLE_DataTagId = aBuff_p[ iCount ];
        iCount++;
        nBLE_DataTagLen--;
        
        switch( nBLE_DataTagId )
        {
          case (tUI8)eTagSchedule:
            nChannelNum = aBuff_p[ iCount ];
            iCount++;
            nBLE_DataTagLen--;
            Data_WriteSchedule_g( nBLE_DataTagLen, nChannelNum, &aBuff_p[ iCount ] );
            break;
          case (tUI8)eTagTime: 
            Rtc_update_g(&aBuff_p[ iCount ]);
            break;
          case (tUI8)eTagAwayModeSetPoint:
            Data_UpdateAwaySp_g(aBuff_p[ iCount ]);
            break;
          case (tUI8)eTagMinMaxLimit:
            nChannelNum = aBuff_p[ iCount ];
            iCount++;
            nBLE_DataTagLen--;
            Data_SetMinSp_g( nChannelNum, aBuff_p[ iCount ]);
            iCount ++;
            nBLE_DataTagLen--;
            Data_SetMaxSp_g( nChannelNum, aBuff_p[ iCount ]);	
            break;
          case (tUI8)eTagZoneData:
            Data_UpdateZoneData_g(nBLE_DataTagLen, &aBuff_p[ iCount ] );
            break;
          case (tUI8)eTagAcknowledgment:
    		Ble_ProcessAck(nBLE_DataTagLen, &aBuff_p[ iCount ] );
            break;
          case (tUI8)eTagFuelType:
            Data_UpdateFuelType_g((teFuelType)aBuff_p[ iCount ] );
            break;
          case (tUI8)eTagOptimumStart:
            Data_UpdateSmartCntrl_g( eSmrtCntrlOptimuStrt, aBuff_p[ iCount ] );
            break;
            
          case (tUI8)eTagOptimumStop:  
            Data_UpdateSmartCntrl_g( eSmrtCntrlOptimuStop, aBuff_p[ iCount ] );
            break;
    
          case (tUI8)eTagFrostSetPoint:
            Data_UpdateFrostSetPt_g(aBuff_p[ iCount ] );
            break;
          default: 
            /* MISRA */
            break;
        }
        iCount += nBLE_DataTagLen;
      }
    }
    /* ----------------------------------------------------------------------- */
    void Ble_ProcessAck(
      tUI8 nDataLength_p,                         
      tUI8 AckData_p[] )
    {
      tUI8 iIdx = 0;
      Ble.nWriteCmdRspnc = cTrue;
    	/* Make sure length must be multiple of 3 */
      if(nDataLength_p % 3u == 0u)
      {
        while( nDataLength_p > 0u)
        {
          /* Just check success received or not ignore previous values as for any case 
                   we are going to get all values */
          iIdx += 2;
          if( cTrue != AckData_p[iIdx++] )
          {
            Ble.nWriteCmdRspnc = cFalse; /* At least one NACK received */
          }else{}
          nDataLength_p -= 3u;
        }
    	}else{PTD_ASSERT(0xA1);}
    }                       
    /* ----------------------------------------------------------------------- */
    void Ble_ProcessData_g( 
      tUI16 nMsgLen_p, 
      tUI8 aDataBuf_p[ ] )
    {
      tUI8 BLE_CommandtType;
      tUI16 nPayLoadSize;
      tUI8 nReceivedMsgLen;
      tUI8 aDeviceData[ 256u ];
      tUI32 nMsgRxCounter;
      
      BLE_CommandtType = aDataBuf_p[ cOffset_CommandType ];
      /* cOffset_MfgDataLenth doesn't include itself  */
      nReceivedMsgLen =  aDataBuf_p[ cOffset_MfgDataLenth ] + 
                         cBLE_BroadCastHeaderSize + 1u; 
      
      nPayLoadSize = (aDataBuf_p[ cOffset_MfgDataLenth ] - cBLE_HeaderSize ) + 1; 
      
      if( cTrue == Commissioning_IsTsCommissEnable_g( ) )
      {
        if( //(nMsgLen_p == nReceivedMsgLen) && 
            (nPayLoadSize > cBLE_MinDataPayLoadSize) && 
            (aDataBuf_p[ cOffset_MfgTag ] == 0xFFu) &&
            /* Is Msg from Receiver */  
            (UTIL_MemCmp( caSCS, &aDataBuf_p[ cOffset_DeviceInitial ], 3u ) == 0 ) // &&  
            /* Message for PTD */  
    //        (UTIL_MemCmp( aTxBroadCastMac, &aDataBuf_p[ cOffset_DesMacAddress ], 
    //            cMACLen ) == 0 )  
          )
        {
          Ble.nRcvdMsgTick = Timer_GetTick_g( );
          if( (BLE_CommandtType & eCmd_Commissioning) == eCmd_Commissioning )
          {
            nMsgRxCounter = UTIL_ConvBiToU32( &aDataBuf_p[
                cOffset_PayloadStart ] );
            
            #if cUartLogEnable
              Production_SendUartLog_g(2, "RX" );
              /* Logging data payload only */
              Production_SendUartLog_g(nPayLoadSize, &aDataBuf_p[ cOffset_PayloadStart ] );
            #endif
            
    //        if( 0u == ESL_CRC_CalcV41( 0u, &aDataBuf_p[ cBLE_HeaderSize + 
    //            cBLE_BroadCastHeaderSize ], nPayLoadSize ) )
    //        {
              Commissioning_DecodeDataFromRx_g( nPayLoadSize, 
                  &aDataBuf_p[ cOffset_SrcMacAddress ] );
    //        }else{}
          }
          else{}
        }else{}
      }
      else
      {
        if( (nMsgLen_p == nReceivedMsgLen) && 
            (nPayLoadSize > cBLE_MinDataPayLoadSize) && 
          (aDataBuf_p[ cOffset_MfgTag ] == 0xFFu) &&
          /* Is Msg from Receiver */  
          (UTIL_MemCmp( caPRT, &aDataBuf_p[ cOffset_DeviceInitial ], 3u ) == 0 )&&  
          /* Message for PTD */  
          (UTIL_MemCmp( PtdMac, &aDataBuf_p[ cOffset_DesMacAddress ], cMACLen ) == 0 )  
        )    
      {
        Ble.nRcvdMsgTick = Timer_GetTick_g( );
        /* Round Trip Test  */
        if( (BLE_CommandtType & eCmd_RoundTrip) == eCmd_RoundTrip )
        {
          Production_Chk_RoundTrip_g(&aDataBuf_p[cOffset_SrcMacAddress]);
        }
      
        /* Device commissioning command */
        else if( (BLE_CommandtType & eCmd_Commissioning) == eCmd_Commissioning )
        {
          nMsgRxCounter = UTIL_ConvBiToU32( &aDataBuf_p[
              cOffset_PayloadStart ] );
          
          #if cUartLogEnable
            Production_SendUartLog_g(2, "RX" );
            /* Logging data payload only */
            Production_SendUartLog_g(nPayLoadSize, &aDataBuf_p[ cOffset_PayloadStart ] );
          #endif
          
          if( BLE_CheckSeqNo(nMsgRxCounter ) == cTrue)
          {
            if( 0u == ESL_CRC_CalcV41( 0u, &aDataBuf_p[ cBLE_HeaderSize + 
                cBLE_BroadCastHeaderSize ], nPayLoadSize ) )
            {
              Commissioning_DecodeDataFromRx_g( nPayLoadSize, 
                  &aDataBuf_p[ cOffset_SrcMacAddress ] );
            }
          }
          else{}
        }
        else
        {
    #ifdef cNoEncription 
          UTIL_MemCpy( aDeviceData, &aDataBuf_p[cOffset_PayloadStart], nPayLoadSize );      
    #else      
          /* Decrypte the Message and remove AES padding if any */
          nPayLoadSize = Aes_DecryptBuff_g( cUseHAN_Key, nPayLoadSize, 
              &aDataBuf_p[cOffset_PayloadStart], aDeviceData, cTrue );
    #endif          
          #if cUartLogEnable
            Production_SendUartLog_g(2, "RX" );
            /* Logging data payload only */
            Production_SendUartLog_g(nPayLoadSize, aDeviceData );
          #endif
      
          if( 0u == ESL_CRC_CalcV41( 0u, aDeviceData, nPayLoadSize ) )
          {
            nPayLoadSize -= 2u; /* Removing 2 byte CRC */
            nPayLoadSize -= 4u; /* Removing Rx Counter size */
            
            /* PTD will only receive Response or Ack from Receiver */
            if( (BLE_CommandtType & eCmd_ResponseOrAck) == eCmd_ResponseOrAck )
            {
              nMsgRxCounter = UTIL_ConvBiToU32( &aDeviceData[ 0u ] );          
              if( BLE_CheckSeqNo(nMsgRxCounter ) == cTrue )
              {
                Ble_ProcessResponse( nPayLoadSize, &aDeviceData[ 4u ] );
                /* is this a last packet */  
                if( (BLE_CommandtType & eCmd_FragmentedPacket) == 0u )
                {
                   BLE_DisableScan_g( );
                      Ble.nRxState = eBleRx_Received;
                  }else{}
                }  
              }
            }
          }
        }else{}
      }    
    }
    /* ----------------------------------------------------------------------- */
    /**
      Validate received Message Seq no 
      @param  nReceivedSeqNo_p        Received sequence no
      @Return Status                  Valid Sequence or not       
    */
    tUI8 BLE_CheckSeqNo( tUI32 nReceivedSeqNo_p )
    {
      tUI8 Status = cFalse;
      nReceivedSeqNo_p = 0u;
      if( (nReceivedSeqNo_p == 0u) || (nHAN_MsgRxCounter == 0u) ||
          (nReceivedSeqNo_p > nHAN_MsgRxCounter) )
      {
        nHAN_MsgRxCounter = nReceivedSeqNo_p;
        Status = cTrue;
      }
      else{PTD_ASSERT(9);}
      return Status;
    }
    /* ----------------------------------------------------------------------- */
    void BLE_StartTransmission_g( 
        tUI8 nLen_p, 
        tUI8 aData[], 
        tUI8 nRetry_p,
        tUI8 IsScanEnable_p,
        tUI8 IsReceiverAdv_p )
    {
      tUI8 aSendBuff[ 256u ];
      tUI8 nDataLen = 0;
      
      /* Adding Broadcast header */
      UTIL_MemCpy( aSendBuff, caBroadcastHeader, cBLE_BroadCastHeaderSize );
      UTIL_MemCpy( &aSendBuff[ cBLE_BroadCastHeaderSize ], aData, nLen_p );
      nDataLen = nLen_p + cBLE_BroadCastHeaderSize;
      
      multi_role_enableAdvert( aSendBuff, nDataLen, nRetry_p, IsReceiverAdv_p, IsScanEnable );
      
      if( IsScanEnable_p == cTrue )
      {
        BLE_EnableScan_g();
      }
      else{}
      //multi_role_enableAdvert( aSendBuff, nDataLen, nRetry_p, IsReceiverAdv_p );
    }
    /* ----------------------------------------------------------------------- */
    void BLE_EnableScan_g( void )
    {
      
    //  AckReceived = cFalse; /* When Ack received from Receiver this will become True */      
      /* Start scanning */
    //  multi_role_enableScan( );
      //IsScanEnable = GapScan_enable(0, cBLE_ScanTime, 0);    
      IsScanEnable = GapScan_enable(0, 0, 0);
      DebugPrint_g( "Scan_Enable=", IsScanEnable );
      IsScanEnable = cTrue;
    }
    /* ----------------------------------------------------------------------- */
    tUI8 Ble_BroadcastSensorData_g( void )
    {
      tUI8 aBuff[ 256u ];
      tUI8 iCount = 0;
      tUI8 nStatus = cFalse;
      tPtdInfo DataCpy;
    
      Data_GetZoneData_g((tUI8*)&DataCpy);
      
      /* Temperature */
      aBuff[ iCount++ ] = 0x03;
      aBuff[ iCount++ ] = eTagTemperature;
      /* Converting data to 0.01 resolution for receiver */
      UTIL_ConvU16ToBi(DataCpy.ReceiverInfo.ChannelInfo[DataCpy.ZoneNo - 1].
                       Temperature * 10, &aBuff[ iCount ] );
      iCount += 2u;
      /* Battery Level */
      aBuff[ iCount++ ] = 0x02;
      aBuff[ iCount++ ] = eTagBatteryLevel;
      aBuff[ iCount++ ] = DataCpy.BatteryVoltage;
      
      /* Low Battery Alarm */
      aBuff[ iCount++ ] = 0x02;
      aBuff[ iCount++ ] = eTagLowBatteryAlarm;
      aBuff[ iCount++ ] = DataCpy.ReceiverInfo.ChannelInfo[DataCpy.ZoneNo - 1].LowBattAlarm;
      
      /* Humidity Level */
      aBuff[ iCount++ ] = 0x02;
      aBuff[ iCount++ ] = eTagHumidity;
      aBuff[ iCount++ ] = DataCpy.ReceiverInfo.ChannelInfo[DataCpy.ZoneNo - 1].Humidity; 
      
    #ifdef cTestEnable
      Ble_SendData(aBuff,iCount,eCmd_BroadcastData);
    #else
      if(( blStopBroadcast == cFalse ) && (Ble.CommsState != eComms_Transmitting))
      {
        PTD_StartTask_g();
        Ble_SendRequest_g(aBuff,iCount,eCmd_BroadcastData);
    //    Ble_SendData(aBuff,iCount,eCmd_BroadcastData);
        nStatus = cTrue;
      }
    #endif    
      return nStatus;  
    }
    /* ----------------------------------------------------------------------- */
    void Ble_SendCommissionConfig_g( 
        tUI8 aBuff_p[], 
        tUI8 nLength_p )
    {
      Ble_SendRequest_g(aBuff_p,nLength_p,eCmd_WriteData);
    }
    /* ----------------------------------------------------------------------- */
    /**
      Send data request to receiver
      @param  teReadReq      read all or updated data
    */
    void Ble_ReadData_g( 
      teReadReq cRequestType_p
      )  
    {
      tUI8 aBuff[ 256u ];
      Ble_SendRequest_g(aBuff,0u,(teCmd)cRequestType_p);
    }  
    /* ----------------------------------------------------------------------- */
    void Ble_SendOverrideInfo_g(
      tUI8 iChannelNum_p,
      tOverRide nOverrideType,
      tUI8 OverRideSetPoint,
      tUI8 OverRideDuration
      )
    {
      tUI8 iCount = 1u;
      tUI8 aBuff[ 256u ];
      /* Updated own data use to populate GUI next time */
    //  Data_Update_Override_g(iChannelNum_p, nOverrideType, OverRideValue );
      
      aBuff[ iCount++ ] = eTagOverRide;     /* Tag */
      aBuff[ iCount++ ] = iChannelNum_p;    /* Channel Number */
      aBuff[ iCount++ ] = (tUI8)(nOverrideType);
      aBuff[ iCount++ ] = OverRideSetPoint; /* Dont care for Timer and Hot water */
      aBuff[ iCount++ ] = OverRideDuration; /* Applicable for boost and hold */
      aBuff[ 0 ] = iCount - 1;
      Ble_SendRequest_g(aBuff,iCount,eCmd_WriteData);
    }  
    /* ----------------------------------------------------------------------- */
    void Ble_SendScheduleData_g(
      tUI8 iChannelNum_p )
    {
      tUI8 iCount = 1u;
      tUI8 aBuff[ 256u ];
      tUI8 iIdx;
      tUI8 iIdx2;
      tChannelSch ThisChSchedule;
    	
      aBuff[ iCount++ ] = eTagSchedule;
      aBuff[ iCount++ ] = (iChannelNum_p);  
    
      Data_GetSchedule_g(iChannelNum_p,(tUI8*)&ThisChSchedule);
      
      for(iIdx = 0; iIdx < cDaysInWeek; iIdx++ )
      {
        for(iIdx2 = 0; iIdx2 < cPeriodsInDay; iIdx2++ )
        {
          aBuff[iCount++] = (tUI8)(ThisChSchedule.DayInfo[iIdx].
                               PeriodInfo[iIdx2].PeriodStartTime >> 8u );
          aBuff[iCount++] = (tUI8)(ThisChSchedule.DayInfo[iIdx].
                               PeriodInfo[iIdx2].PeriodStartTime);      
          aBuff[iCount++] =  ThisChSchedule.DayInfo[iIdx].
                               PeriodInfo[iIdx2].PeriodValue;
        }
      }
      aBuff[ 0 ] = iCount - 1;
      Ble_SendRequest_g(aBuff,iCount,eCmd_WriteData);
    }
    /* ----------------------------------------------------------------------- */
    void Ble_SendTime_g(
      teTimeType iTimeFormate_p,
      tUI32 nTime_p)
    {
      tUI8 iCount = 1u;
      tUI8 aBuff[ 256u ];
      aBuff[ iCount++ ] = eTagTime;    /* Tag */
      aBuff[ iCount++ ] = iTimeFormate_p;
      aBuff[ iCount++ ] = cDefaultTimeZone; /* Time Zone not required */
      UTIL_ConvU32ToBi( nTime_p, &aBuff[ iCount ] );
      iCount += 4;
      aBuff[ 0 ] = iCount - 1;
      Ble_SendRequest_g(aBuff,iCount,eCmd_WriteData);
    }
    
    /* ----------------------------------------------------------------------- */
    void Ble_SendAck_g( void )
    {
      tUI8 iCount = 1u;
      tUI8 aBuff[ 256u ];
      aBuff[ iCount++ ] = eTagAcknowledgment;    /* Tag */
      UTIL_ConvU32ToBi( nHAN_MsgRxCounter, &aBuff[ iCount ] );
      iCount += 4;
      aBuff[ 0 ] = iCount - 1;
      Ble_SendRequest_g(aBuff,iCount,eCmd_WriteData);
    }
    
    /* ----------------------------------------------------------------------- */
    void Ble_SendDeviceModeInfo_g(
      teMode iDeviceMode_p )
    {
      tUI8 iCount = 1u;
      tUI8 aBuff[ 256u ];
      /* Updated own data use to populate GUI next time */
    //  Data_UpdateDeviceMode_g( iDeviceMode_p );
      aBuff[ iCount++ ] = eTagDeviceMode;    /* Tag */
      aBuff[ iCount++ ] = (tUI8)(iDeviceMode_p);
      aBuff[ 0 ] = iCount - 1;
      Ble_SendRequest_g(aBuff,iCount,eCmd_WriteData);
    }
    
    /* ----------------------------------------------------------------------- */
    void Ble_SendUserOverride_g(
      tUI8 iChannelNum_p,
      tUI8 OverRideSetPoint,
      teMode iDeviceMode_p )
    {
      tUI8 iCount = 0u;
      tUI8 aBuff[ 256u ];
      
      /* Temperature Override */
      aBuff[ iCount++ ] = 5u;               /* Length */
      aBuff[ iCount++ ] = eTagOverRide;     /* Tag */
      aBuff[ iCount++ ] = iChannelNum_p;    /* Channel Number */
      aBuff[ iCount++ ] = (tUI8)(eOverrideTemperature);
      aBuff[ iCount++ ] = OverRideSetPoint; /* Dont care for Timer and Hot water */
      aBuff[ iCount++ ] = 0u; /* for Hold and Boost Dont care for rest */
    
      /* Mode change */
      aBuff[ iCount++ ] = 0x02;             /* Length */
      aBuff[ iCount++ ] = eTagDeviceMode;   /* Tag */
      aBuff[ iCount++ ] = (tUI8)(iDeviceMode_p);  
      
      Ble_SendRequest_g(aBuff,iCount,eCmd_WriteData);
    }
    
    /* ----------------------------------------------------------------------- */
    void Ble_SendAwaySp_g(
      tUI8 iSetPoint_p )
    {
      tUI8 iCount = 1u;
      tUI8 aBuff[ 256u ];
      /* Updated own data use to populate GUI next time */
      Data_UpdateAwaySp_g( iSetPoint_p );
      aBuff[ iCount++ ] = eTagAwayModeSetPoint;    /* Tag */
      aBuff[ iCount++ ] = iSetPoint_p;
      aBuff[ 0 ] = iCount - 1;
      Ble_SendRequest_g(aBuff,iCount,eCmd_WriteData);
    }
    
    /* ----------------------------------------------------------------------- */
    void Ble_SendMinMaxSp_g(
      tUI8 iChannelNo_p,                        
      tUI8 iSetPointMin_p,
      tUI8 iSetPointMax_p )
    {
      tUI8 iCount = 1u;
      tUI8 aBuff[ 256u ];
      /* Updated own data use to populate GUI next time */
      Data_SetMinSp_g( iChannelNo_p, iSetPointMin_p );
      Data_SetMaxSp_g( iChannelNo_p, iSetPointMax_p );
      
      aBuff[ iCount++ ] = eTagMinMaxLimit;    /* Tag */
      aBuff[ iCount++ ] = iChannelNo_p;
      aBuff[ iCount++ ] = iSetPointMin_p;
      aBuff[ iCount++ ] = iSetPointMax_p;
      aBuff[ 0 ] = iCount - 1;
      Ble_SendRequest_g(aBuff,iCount,eCmd_WriteData);
    }
    
    /* ----------------------------------------------------------------------- */
    void Ble_SendLocalControlState_g(
      tUI8 iChannelNo_p,                        
      teControl iState_p )
    {
      tUI8 iCount = 1u;
      tUI8 aBuff[ 256u ];
      /* Updated own data use to populate GUI next time */
      Data_Update_LocalCntrlState_g( iChannelNo_p, iState_p );
      
      aBuff[ iCount++ ] = eTagLocalControll;    /* Tag */
      aBuff[ iCount++ ] = iChannelNo_p;
      aBuff[ iCount++ ] = (tUI8)iState_p;
      aBuff[ 0 ] = iCount - 1;
      Ble_SendRequest_g(aBuff,iCount,eCmd_WriteData);
    }
    
    /* ----------------------------------------------------------------------- */
    void Ble_SendFuelType_g(
      teFuelType nFuelType_p )
    {
      tUI8 iCount = 1u;
      tUI8 aBuff[ 256u ];
      /* Updated own data use to populate GUI next time */
      Data_UpdateFuelType_g( nFuelType_p );
      
      aBuff[ iCount++ ] = eTagFuelType;    /* Tag */
      aBuff[ iCount++ ] = nFuelType_p;
      aBuff[ 0 ] = iCount - 1;
      Ble_SendRequest_g(aBuff,iCount,eCmd_WriteData);
    }
    
    /* ----------------------------------------------------------------------- */
    void Ble_SendSmartCntrl_g(
      teSmrtCntrl nControlType_p,
      teControl iState_p,
      tUI8 nChNum_p
      )
    {
      tUI8 iCount = 1u;
      tUI8 aBuff[ 256u ];
      tUI8 nValue = 0u; 
      /* Updated own data use to populate GUI next time */
    
      nValue = nChNum_p << cSmrtCntrlChannelPosi;
      
      if( iState_p == eControl_Enable )  
      {
        nValue |= 1u;
      }else{}
      
      if( nControlType_p == eSmrtCntrlOptimuStrt )
      {
        aBuff[ iCount++ ] = eTagOptimumStart;    /* Tag */
      }
      else
      {
        aBuff[ iCount++ ] = eTagOptimumStop;    /* Tag */
      }
      Data_UpdateSmartCntrl_g( nControlType_p, nValue );
      aBuff[ iCount++ ] = nValue;
      aBuff[ 0 ] = iCount - 1;
      Ble_SendRequest_g(aBuff,iCount,eCmd_WriteData);
    }
    /* ----------------------------------------------------------------------- */
    void Ble_SendFrostSetPt_g(
      tUI8 iSetPoint_p )
    {
      tUI8 iCount = 1u;
      tUI8 aBuff[ 256u ];
      /* Updated own data use to populate GUI next time */
      Data_UpdateFrostSetPt_g( iSetPoint_p );
      
      aBuff[ iCount++ ] = eTagFrostSetPoint;    /* Tag */
      aBuff[ iCount++ ] = iSetPoint_p;
      aBuff[ 0 ] = iCount - 1;
      Ble_SendRequest_g(aBuff,iCount,eCmd_WriteData);
    }
    
    /* ----------------------------------------------------------------------- */
    void Ble_SendFactoryReset_g( void )
    {
      tUI8 iCount = 1u;
      tUI8 aBuff[ 256u ];
      aBuff[ iCount++ ] = eTagFactoryReset;    /* Tag */
      aBuff[ iCount++ ] = 0xA1;                /* Factory rest Key */     
      aBuff[ iCount++ ] = 0xB2;
      aBuff[ iCount++ ] = 0xC3;
      aBuff[ iCount++ ] = 0xD4;
      aBuff[ 0 ] = iCount - 1;
      Ble_SendRequest_g(aBuff,iCount,eCmd_WriteData);
    }
    /* ----------------------------------------------------------------------- */
    void Ble_SendServiceInterval_g(
      teControl iState_p,                              
      tUI16 nCycleDays_p,                           
      tUI8 nWarningDays_p,
      teRestriction nRestrictionType_p,
      tUI8 aMobNo_p[ ],  
      tUI8 nSetPoint_p ) 
    {
      tUI8 iCount = 1u;
      tUI8 aBuff[ 256u ];
      
      aBuff[ iCount++ ] = eTagServiceInterval;    /* Tag */
      aBuff[ iCount++ ] = (tUI8)iState_p;
      UTIL_ConvU16ToBi( nCycleDays_p, &aBuff[ iCount ] );
      iCount += 2u;
      aBuff[ iCount++ ] = nWarningDays_p;
      aBuff[ iCount++ ] = nRestrictionType_p;
      UTIL_MemCpy( &aBuff[ iCount ], aMobNo_p, cMobileNumLen );
      iCount += cMobileNumLen;
      aBuff[ iCount++ ] = nSetPoint_p;
      aBuff[ 0 ] = iCount - 1;
      Ble_SendRequest_g(aBuff,iCount,eCmd_WriteData);  
    }
    /* ----------------------------------------------------------------------- */
    void Ble_SendRoundTripCmd_g(
      tUI8 aMac_p[ ] )
    {
      tUI8 iCount = 0u;
      tUI8 aBuff[ 64u ];
       
      /* Prepare BLE header */
      aBuff[ iCount++ ] =  cSrNumLen + cBLE_HeaderSize; /* Total Msg Length */
      aBuff[ iCount++ ] = 0xFF;                             /* BLE  Mfg Tag */
      UTIL_MemCpy( &aBuff[ iCount ], PtdMac, cMACLen );     /* Source Mac */      
      iCount += cMACLen;
      UTIL_MemCpy( &aBuff[ iCount ], aMac_p, cMACLen );     /* Destination Mac */
      iCount += cMACLen;
      aBuff[ iCount++ ] = eCmd_RoundTrip;                   /* Command Type */
      
      aBuff[iCount] = 0x00u;                                /* Round trip request */
      iCount += 1;
      /* Get Dut Serial Number */
      Flash_GetData( eFlashMfgSr, &aBuff[iCount] );
      iCount += cSrNumLen;
      BLE_StartTransmission_g( iCount, aBuff, cBLE_MaxRetryCount, cTrue, cFalse );
    }
    /* ----------------------------------------------------------------------- */
    /**
      Prepare data as per IPD and then send it over Ble
      @param  Data_p         Data Buffer to be sent
      @param  nLength_p      Length of Payload excluding Sequence No
      @param  teCmd          Command type for data send 
    */
    void Ble_SendRequest_g(tUI8 Data_p[],tUI8 nLength_p,teCmd CmdType_p) 
    {
      UTIL_MemCpy( Ble.aSendBuff, Data_p, nLength_p );
      Ble.nTxLen   = nLength_p; 
      Ble.nCmdType = CmdType_p;
      Ble.nStateId = eBle_WaitBeforeTx;
      Ble.nRetryCnt = 3u;
      Ble.CommsState = eComms_Transmitting;
      Ble.nWriteCmdRspnc = cFalse;
    }
    /* ----------------------------------------------------------------------- */
    tUI8 BLE_CommsFsm_g( void )
    {
      tUI8 Status = cFalse;
      static tUI8 CommsErrorCnt = 0u; 
      switch( Ble.nStateId )
      {
        case eBle_Idle:
          Status = cTrue;
          break;
        case eBle_WaitBeforeTx: /* Wait before Starting Tx after receiving msg so Receiver complete its transmission */
          /* Tick in 10ms resolution */
          /* 1200ms Delay added as per Vikram sir's sugestion  */
          if( cTrue == Timer_IsOver_g( Ble.nRcvdMsgTick,cWaitBeforeTx )) 
          {
            Ble.nStateId = eBle_WaitforTx;
            Ble.nFsmTick = Timer_GetTick_g( );
            Ble_SendData(Ble.aSendBuff, Ble.nTxLen, Ble.nCmdType);
            /* Init tick here to wait for previous broadcast complition */
            Ble.nRcvdMsgTick = Timer_GetTick_g( );
          }else{}  
          break;
        case eBle_WaitforTx:   /* Wait till PTD finish its Transmission */
          /* Come in reciving mode befor Receiver start Tx, as per Vikram Sir's sugestion */
          if( cTrue == Timer_IsOver_g( Ble.nFsmTick, cWaitForTx ))
          {
            if(Ble.nCmdType == eCmd_BroadcastData)
            {
              Ble.nStateId = eBle_Idle;
              Ble.CommsState = eCmd_Sucess;
            }
            else
            {
              BLE_EnableScan_g();
              Ble.nStateId = eBle_WaitForRx;
              Ble.nRxState = eBleRx_Wait;
              Ble.nFsmTick = Timer_GetTick_g( );
              if(Ble.nCmdType == eCmd_ReadAll)
              {
                if( Data_GetNoOfChUsed_g() >= 3u )
                { /* If number of used channel is 3 or more Receiver respond with 4 packets */
                  Ble.nCommsTimeOut = cRxTimeFourPackets;
                }
                else
                {
                  Ble.nCommsTimeOut = cRxTimeTwoPackets;  
                }
              }  
              else
              {
                Ble.nCommsTimeOut = cRxTimeOnePacket;
              }  
            }  
          }else{}      
          break;
        case eBle_WaitForRx:   /* Wait till data received from receiver  */
          if( Ble.nRxState == eBleRx_Received )
          {
            /*As discussed with Dharmpal sir, Receiver will always respond with data of requested cmd */ 
            if( Ble.nCmdType == eCmd_WriteData ) /* On reception of Ack communication is complete */
            {
              if( Ble.nWriteCmdRspnc == cTrue)
              {
                Ble.CommsState = eCmd_Sucess;
                Ble.nStateId = eBle_Idle;
              }
              else /* Receiver is rejected write data cmd, PTD have to sync with receiver by performing read all */
              {
              /* Ble.CommsState and Ble.nStateId is not changed here it will automatically updated after eDataReqAll request */
                Ble_ReadData_g( eDataReqAll );
              }
            }
            else /* response for read commands */
            {
              Ble.CommsState = eCmd_Sucess;
              Ble.nStateId = eBle_Idle;
            }
            /*Communication successful clear comms error */
            Screen_RegisterWarning_g( eWarning_RxError, cFalse );
          }
          /* Retry after 3 seconds */
          else if( cTrue == Timer_IsOver_g( Ble.nFsmTick, Ble.nCommsTimeOut ))
          {
            BLE_DisableScan_g( ); /* Stop scan after Rx timeout */
            if( Ble.nRetryCnt )
            {
              Ble.nRetryCnt--;
              Ble.nStateId = eBle_WaitBeforeTx;
            }  
            else
            {
              Ble.nStateId = eBle_Idle;
              Ble.CommsState = eCmd_Error;
              /* Register communication error */
              Screen_RegisterWarning_g( eWarning_RxError, cTrue );				
              /* Reset sequence number if first command response is not received */
              if( nHAN_MsgTxCounter == 1u )
              {
                nHAN_MsgTxCounter = 0u;
              }else{}
              CommsErrorCnt++;
              if(CommsErrorCnt >= 1u )
              { 
                CommsErrorCnt = 0u;
    #ifdef cCommsTestWithRec            
                #include "SmlUtil.h"
                tUI8 aBuffer[ 16u ];
                tUI32 PresentRstCnt;
                Flash_GetData( eFlashMfgSr, aBuffer );
                PresentRstCnt = UTIL_StrToInt( aBuffer );
                PresentRstCnt++;
                DebugPrint_g( "CommsErCnt=", (tUI8)(PresentRstCnt));
                UTIL_MemSet( aBuffer, 0x30, 16u ); /* Making all zero */
                UTIL_IntToStr( PresentRstCnt, aBuffer );
                Flash_WriteData( eFlashMfgSr, 8u, aBuffer );          
    #endif            
                /* Reset device, workaround to fix adv /Scan issue */            
    //            SystemReset();
              }
            }  
          }else{}  
          break;      
        default: 
          Ble.nStateId = eBle_Idle;
          break;
      }
      return (Status);
    }
    /* ----------------------------------------------------------------------- */
    teComms_State BLE_Get_CommsState_g( void )
    {
      return(Ble.CommsState);
    }  
    /* ----------------------------------------------------------------------- */
    /**
      Prepare data as per IPD and then send it over Ble
      @param  Data_p         Data Buffer to be sent
      @param  nLength_p      Length of Payload excluding Sequence No
      @param  teCmd          Command type for data send 
    */
    //void Ble_SendRequest_g(tUI8 Data_p[],tUI8 nLength_p,teCmd CmdType_p)
    void Ble_SendData(tUI8 Data_p[],tUI8 nLength_p,teCmd CmdType_p)
    {
      
      tUI8 iCount = 0u;
      tUI8 nMsgLen;
      tUI8 aBuff[ 256u ];
      tUI8 aCmdBuff[ 256u ];
      tFlashInfo FlashData;
    	
      tUI16 DataCrc;
    	
      UTIL_ConvU32ToBi( nHAN_MsgTxCounter, &aBuff[ iCount ] );
      iCount += 4u; /* seq no  */
      nHAN_MsgTxCounter++;
      /* commissiong was done with msgcntr always 0 */
      if( CmdType_p == eCmd_Commissioning )
      {
        nHAN_MsgTxCounter = 0u;  
      }else{}
      UTIL_MemCpy( &aBuff[ iCount ], Data_p, nLength_p );
        
      iCount += nLength_p;
      DataCrc = ESL_CRC_CalcV41( 0u, aBuff, (tUI16)iCount );
      UTIL_ConvU16ToBi( DataCrc, &aBuff[ iCount ] );
      iCount += 2u;
     
    #ifdef cUartLogEnable
      Production_SendUartLog_g(2, "TX" );
      Production_SendUartLog_g(iCount, aBuff );
    #endif  
    #ifdef cNoEncription
      nMsgLen = iCount;
      UTIL_MemCpy( aCmdBuff, aBuff, nMsgLen );
    #else
      if( CmdType_p == eCmd_Commissioning )
      {
        nMsgLen = iCount;
        UTIL_MemCpy( aCmdBuff, aBuff, nMsgLen );  
      }
      else
      { 
        nMsgLen = Aes_EncryptBuff_g( cUseHAN_Key, iCount, aBuff, aCmdBuff, cTrue );
      }  
    #endif  
      /* Prepare BLE header */
      iCount = 0;
      aBuff[ iCount++ ] =  nMsgLen + (cBLE_HeaderSize - 1); /* Total Msg Length */
      aBuff[ iCount++ ] = 0xFF;                             /* BLE  Mfg Tag */
      UTIL_MemCpy( &aBuff[ iCount ], PtdMac, cMACLen );     /* Source Mac */      
      iCount += cMACLen;
      
      Flash_ReadBuffer_g( (tUI8*)&FlashData );
      UTIL_MemCpy( &aBuff[ iCount ], FlashData.RxMAC, cMACLen ); /* Receiver Mac */    
      iCount += cMACLen;
      aBuff[ iCount++ ] = CmdType_p;                        /* Command Type */
      
      UTIL_MemCpy( &aBuff[iCount], aCmdBuff, nMsgLen );
      nMsgLen += iCount;
      BLE_StartTransmission_g(nMsgLen, aBuff,cBLE_MaxRetryCount, cFalse, cTrue );
    }
    /* ----------------------------------------------------------------------- */
    tUI32 BLE_GetSeqNo_g( void )
    {
      return nHAN_MsgTxCounter;
    }
    /* ----------------------------------------------------------------------- */
    void BLE_StopSensorBroadCast_g( tUI8 nState_p )
    {
      blStopBroadcast = nState_p;
    }
    /* ----------------------------------------------------------------------- */
    static tUI8 BLE_GetScanStatus( void )
    {
      return IsScanEnable;
    }
    /* ----------------------------------------------------------------------- */
    static void BLE_SetScanStatus( tUI8 State_p )
    {
      IsScanEnable = State_p;
    }
    /* ----------------------------------------------------------------------- */
    void BLE_DisableScan_g( void )
    {
      tUI8 Status;
      if( cTrue == BLE_GetScanStatus( ) )
      {
        BLE_SetScanStatus( cFalse );
        Status = GapScan_disable();
        DebugPrint_g( "Scan_Disable=", Status );
      }else{}  
    }
    /* ----------------------------------------------------------------------- */
    void BLE_SetRxStateRcvd_g( void )
    {
      Ble.nRxState = eBleRx_Received;
    }
    /* *********************************************************************** */
    #if ChangeHistory
    
    #endif
    /* End =================================================================== */
    
    /** @file           PTD_main.c
    *   @copyright      Copyright (c) 2016 Secure International Holdings Pte. Ltd.
    *   @author         Written by: Jagdish Kushwaha
    *   @date           Started on:  20/05/2020
    *   @brief          This is a PTD application main file 
    */
    /* *********************************************************************** */
    /* included files */
    #include "util.h"
    #include "Typedef.h"
    #include "PTD_main.h"
    #include "PTDTimer.h"
    #include <ti_drivers_config.h>
    #include <ti/drivers/GPIO.h>
    #include <ti/drivers/rf/RF.h>
    #include "ti_drivers_config.h"
    #include <ti/drivers/PIN.h>
    #include <ti/drivers/pin/PINCC26XX.h>
    
    #include "Commissioning.h"
    #include "Data.h"
    #include "Flash.h"
    #include "Aes128.h"
    #include "LCD.h"
    #include "Ble.h"
    #include "Production.h"
    #include "PTDScreen.h"
    #include "HDCSensor.h"
    #include "Schedular.h"
    #include "multi_role.h"
    #include <ti/sysbios/knl/Task.h>
    #include "ll_common.h"
    #include <ti/drivers/Power.h>
    #include <ti/drivers/power/PowerCC26XX.h>
    #include <unistd.h>
    #include "keypad.h"
    #include "TimeSetting.h"
    #include "UserInterface.h"
    #include "SmlUtil.h"
    #include "DisplayLCD.h"
    #include <ti/drivers/Watchdog.h>
    /* ======================================================================= */
    
    /* #defines */
    /* ----------------------------------------------------------------------- */
    
    /* type definitions */
    
    /* ----------------------------------------------------------------------- */
    
    /* definitions of static (local) variables */
    /** 
     PTD state machine clock comes at every 10ms
    */
    static Clock_Struct PtdCommissionClock;
    static tePtdState PtdTaskState;
    Watchdog_Handle watchdogHandle;
    tUI8 IsDeviceInSleep = cFalse;
    tUI8 CommissioningTimer;        /* decrement at every cCommissioningFreq  */
    tUI32 nTimTick;
    
    /* ----------------------------------------------------------------------- */
    
    /* definitions of external (global)variables(Use of global is Not recommended)*/
    
    /* ----------------------------------------------------------------------- */
    
    /* definitions of constant data tables */
    
    /* ----------------------------------------------------------------------- */
    
    /* prototypes of local (static) functions */
    void initRfFrontendCustom(void);
    void watchdogCallback(uintptr_t watchdogHandle);
    void PTD_InitWatchDog( void );
    static void PTD_CommissionHandler(UArg a0);
    /* ======================================================================= */
    
    /* ----------------------------------------------------------------------- */
    void PTD_Init_g( void )
    {
      PTD_InitWatchDog( );
      Data_Init_g( );
      GPIO_init( );
      Lcd_Init_g( );
      Ble_Init_g( );
      HDC_Init_g( );
      Flash_Init_g( );
      Screen_InitParam_g( );
      Schedular_InitParam_g( );
      Commissioning_PowerOnInit_g( );
      DateInit_g( );
      UX_ResetAllVariable_g( );
      PtdTaskState = ePtdState_Init;
      Util_constructClock(&PtdCommissionClock, PTD_CommissionHandler,
                          cCommissioningFreq, cCommissioningFreq, false, 0);  
        /* If Top button pressd  enter in production test mode */
    #if cAlwaysProductionMode 
      PtdTaskState = ePtdState_ProductTest;
      Production_TaskInit_g();
    #else /* cAlwaysProductionMode */
    
    #if cDebugUartEnable
      Production_TaskInit_g();
    #endif
      
      if( Flash_IsPtdCommissioned_g( ) == cPtdCommissioned ) 
      { /* Configure HDC sensor if PTD commissioned else not */
        HDC_ConfigSensor_g();
      }else{}
      
      if (PIN_getInputValue(CONFIG_PIN_0) == 0)
      {
        /* Giving 100 Ms Delay Checking Debounce to avoide false production mode */
        Task_sleep(100*100);
        if (PIN_getInputValue(CONFIG_PIN_0) == 0)
        {
          PtdTaskState = ePtdState_ProductTest; 
          Production_TaskInit_g();
        }else{}  
      }else{}
    #endif  /* cAlwaysProductionMode */
      PTD_StartTask_g();
    
    #ifdef cTestEnable  
      #include "Testing.h"
      PtdTaskState = ePtdState_Normal;
      HDC_ConfigSensor_g( );
      LoadDefaultData();
    #endif
    
    #ifdef cDisableSleep  
      Power_disablePolicy();
    #endif  
    }
    
    static void PTD_CommissionHandler(UArg a0)
    {
      if( CommissioningTimer > 0 )
      {
        CommissioningTimer--;
        PTD_StartTask_g();
      }  
    }
    /* ----------------------------------------------------------------------- */
    void PTD_Task_g( void )
    {
      tUI8 aBuff[ 2u ];
      tCommissioningStatus CommissStatus;
      static tUI32 PtdTaskTick;
      
      IsDeviceInSleep = cFalse;
      PTD_FeedWatchDog();
      Lcd_Task_g();
      Timer_UpdateTick_g();
      (void) BLE_CommsFsm_g( );
    
    #ifdef cConfigChngByUart
      Production_TaskRun_g();
    #endif
      
    #if defined( cTestEnable ) || defined( cPacketSniffer )  
      #include "Testing.h"  
      #ifdef cPacketSniffer  
        static tUI8 blEnableScan = cTrue;
          if( blEnableScan )
          {
            blEnableScan = cFalse;
            BLE_EnableScan_g();
            tUI8 status;
            status = HCI_LE_ClearWhiteListCmd();        
          }
      #else
        Testing_g( );    
      #endif
    #else  
      switch( PtdTaskState )
      {
        case ePtdState_Init:
          /* PTD will wakeup from deep sleep */
          if( cPtdCommissioned == Flash_IsPtdCommissioned_g( ) )
          {
            Ble_ReadData_g( eDataReqUpdate );
            PtdTaskState = ePtdState_Normal; 
          }  
          else
          {
            Lcd_AllOff_g( );
            Display_UpdateGuidingArea2Text_g( "TO SETUP    ",12u, cFlashDisable );
            Display_UpdateGuidingArea1_g( "HOLD MENU BUTTON", cFlashDisable );
            Lcd_Update_g( );    
            PtdTaskState = ePtdState_WaitToStart;
            PtdTaskTick = Timer_GetTick_g( );
          }
          break;
      case ePtdState_WaitToStart:
          if( Keypad_GetEvent_g( cKey_Top ) == eKeyEvent_Hold )
          {
            Keypad_GetEvent_g( cKey_ClearAllEvt );
            PtdTaskState = ePtdState_Commissioning;
            Commissioning_InitParam_g( eDevTypePTD );
            if (!Util_isActive(&PtdCommissionClock))
            {
             Util_startClock(&PtdCommissionClock);
             CommissioningTimer = cCommissioningTout;
            }
            else{}       
          }else if( cTrue == Timer_IsOver_g( PtdTaskTick, cStartCommissionTimeout ))
          {
            PtdTaskState = ePtdState_Sleep;
          }
          else{}  
          break;
          
        case ePtdState_ProductTest:
          if( cTrue == Production_TaskRun_g() )
          {
            Production_Sleep_g();
            PtdTaskState = ePtdState_Sleep;
            if( Flash_IsPtdCommissioned_g( ) == cPtdCommissioned ) 
            { /* Configure HDC sensor if PTD commissioned else not */
              HDC_ConfigSensor_g();
            }
            else{}
          }else{}
          break;
        case ePtdState_Commissioning:
          CommissStatus = Commissioning_Task_g( );
          if( CommissStatus == eStatus_Success )
          {
            Screen_ResetTick_g( );
            aBuff[ 0u ] = cPtdCommissioned;
            Flash_WriteData( eFlashCommissFlag, 1u, aBuff );
            Screen_CreateMenu_g( cScreenDefault );
            if (Util_isActive(&PtdCommissionClock))
            {
              Util_stopClock(&PtdCommissionClock);
            }        
            PtdTaskState = ePtdState_Normal;
          }
          else if( CommissStatus == eStatus_Back )
          { /* If commissioning duration expire go to sleep */
            if( CommissioningTimer == 0u )
            {  
              PtdTaskState = ePtdState_Sleep;
              if (Util_isActive(&PtdCommissionClock))
              {
                Util_stopClock(&PtdCommissionClock);
              }
            }
            else
            {/* Sleep here Commissioning clock will wakeup */
    //          Util_restartClock(&PtdCommissionClock, cCommissioningFreq);
              PTD_ReadyForSleep_g();
            }                       
          }      
          else{}
          if( Keypad_GetEvent_g( cKeyBack ) == eKeyEvent_Pressed )
          {
            (void)Keypad_GetEvent_g( cKey_ClearAllEvt );
            Screen_CreateMenu_g( cScreenFactoryReset );
            PtdTaskState = ePtdState_Normal;
          }else{}
          break;
        case ePtdState_Normal:
          if( cTrue == Screen_Display_g( ) )
          {
            PtdTaskState = ePtdState_Sleep; 
          }
          break;
          
        case ePtdState_Sleep:
        /* If any key is pressed */
          if(Keypad_IsKeyPressed_g() == cTrue )
          {/* Clear all key event after wake up */
            Keypad_GetEvent_g( cKey_ClearAllEvt );
            PtdTaskState = ePtdState_Init; 
          }else if (BLE_CommsFsm_g() == cTrue ) /* Safe to sleep */
          {
            PTD_ReadyForSleep_g();
          }else{}
          break;      
        default:
          PtdTaskState = ePtdState_Sleep;
          break;
      }
    #endif
    }
    /* ----------------------------------------------------------------------- */
    void PTD_Task_NextStage( void )
    {
      if( Flash_IsPtdCommissioned_g( ) != cPtdCommissioned ) 
      {
        PtdTaskState = ePtdState_Commissioning;
        Commissioning_InitParam_g( eDevTypePTD );
      }
      else
      {
        PtdTaskState = ePtdState_Normal;
      }            
    }  
    /* ----------------------------------------------------------------------- */
    void PTD_ReadyForSleep_g( void )
    {
      tUI8 aBuf_p[16u ];
        
      tUI8 Status;
    //  multi_AdvDisable();
      BLE_DisableScan_g();
      PTD_StopTask_g();
      Screen_ResetAll_g( );
      BLE_StopSensorBroadCast_g( cFalse );
      Keypad_Sleep_g();    
      Commissioning_InitVariableOnSleep_g( );
      UX_ResetAllVariable_g( );
      Status = Power_releaseConstraint(PowerCC26XX_SB_DISALLOW);
      UTIL_CnvrtHexToAscii( Status, aBuf_p );  
      Lcd_AllOff_g( );
      Display_UpdateGuidingArea2Text_g( aBuf_p,2u, cFlashDisable );
      Lcd_Update_g( );      
      Task_sleep(2000*100);
      Status = Power_releaseConstraint(PowerCC26XX_IDLE_PD_DISALLOW); 
      UTIL_CnvrtHexToAscii( Status, aBuf_p );  
      Lcd_AllOff_g( );
      Display_UpdateGuidingArea2Text_g( aBuf_p,2u, cFlashDisable );
      Lcd_Update_g( );
      Task_sleep(2000*100);
      Lcd_Sleep_g();
      IsDeviceInSleep = cTrue;
      Rtc_Sleep_g();
    }
    /* ----------------------------------------------------------------------- */
    /*
     * ======== Antenna switching ========
     */
    /*
     * ======== rfDriverCallbackAntennaSwitching ========
     * Function to handle antenna switching.
     */
    void rfDriverCallbackAntennaSwitching(RF_Handle client, RF_GlobalEvent events, void *arg)
    {
    
        static PIN_Handle antennaPins;
        static PIN_State antennaState;
        /* Protect against repeated RF_init */
        static bool initialized = false;
    
        /* Local variable. */
        bool    sub1GHz   = false;
        uint8_t loDivider = 0;
    
        if (!initialized && events & RF_GlobalEventInit) 
        {
          /* Don't do it again */
          initialized = true;
          PIN_Config antennaConfig[] = {
          CONFIG_RF_24GHZ | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,      /* Path disabled */
          CONFIG_RF_HIGH_PA | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,      /* Path disabled */
          CONFIG_RF_SUB1GHZ | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,      /* Path disabled */
          PIN_TERMINATE
          };
          antennaPins = PIN_open(&antennaState, antennaConfig);
        }
        else if (events & RF_GlobalEventRadioSetup) 
        {
          /* Switch off all paths. */
          PINCC26XX_setOutputValue(CONFIG_RF_24GHZ, 0);
          PINCC26XX_setOutputValue(CONFIG_RF_HIGH_PA, 0);
          PINCC26XX_setOutputValue(CONFIG_RF_SUB1GHZ, 0);
    
          /* Decode the current PA configuration. */
          RF_TxPowerTable_PAType paType = (RF_TxPowerTable_PAType)RF_getTxPower(client).paType;
    
          /* Decode the generic argument as a setup command. */
          RF_RadioSetup* setupCommand = (RF_RadioSetup*)arg;
    
          switch (setupCommand->common.commandNo) 
          {
            case (CMD_RADIO_SETUP):
            case (CMD_BLE5_RADIO_SETUP):
                loDivider = RF_LODIVIDER_MASK & setupCommand->common.loDivider;
    
                /* Sub-1GHz front-end. */
                if (loDivider != 0) {
                    sub1GHz = true;
                }
                break;
            case (CMD_PROP_RADIO_DIV_SETUP):
                loDivider = RF_LODIVIDER_MASK & setupCommand->prop_div.loDivider;
    
                /* Sub-1GHz front-end. */
                if (loDivider != 0) {
                    sub1GHz = true;
                }
                break;
            default:break;
          }
    
          if (sub1GHz) 
          {
              /* Sub-1 GHz */
              if (paType == RF_TxPowerTable_HighPA) {
                  /* PA enable --> HIGH PA
                   * LNA enable --> Sub-1 GHz
                   */
                  PINCC26XX_setMux(antennaPins, CONFIG_RF_24GHZ, PINCC26XX_MUX_GPIO);
                  /* Note: RFC_GPO3 is a work-around because the RFC_GPO1 (PA enable signal) is sometimes not
                           de-asserted on CC1352 Rev A. */
                  PINCC26XX_setMux(antennaPins, CONFIG_RF_HIGH_PA, PINCC26XX_MUX_RFC_GPO3);
                  PINCC26XX_setMux(antennaPins, CONFIG_RF_SUB1GHZ, PINCC26XX_MUX_RFC_GPO0);
              } else {
                  /* RF core active --> Sub-1 GHz */
                  PINCC26XX_setMux(antennaPins, CONFIG_RF_24GHZ, PINCC26XX_MUX_GPIO);
                  PINCC26XX_setMux(antennaPins, CONFIG_RF_HIGH_PA, PINCC26XX_MUX_GPIO);
                  PINCC26XX_setMux(antennaPins, CONFIG_RF_SUB1GHZ, PINCC26XX_MUX_GPIO);
                  PINCC26XX_setOutputValue(CONFIG_RF_SUB1GHZ, 1);
              }
          } else {
              /* 2.4 GHz */
              if (paType == RF_TxPowerTable_HighPA)
              {
                  /* PA enable --> HIGH PA
                   * LNA enable --> 2.4 GHz
                   */
                  PINCC26XX_setMux(antennaPins, CONFIG_RF_24GHZ, PINCC26XX_MUX_RFC_GPO0);
                  /* Note: RFC_GPO3 is a work-around because the RFC_GPO1 (PA enable signal) is sometimes not
                           de-asserted on CC1352 Rev A. */
                  PINCC26XX_setMux(antennaPins, CONFIG_RF_HIGH_PA, PINCC26XX_MUX_RFC_GPO3);
                  PINCC26XX_setMux(antennaPins, CONFIG_RF_SUB1GHZ, PINCC26XX_MUX_GPIO);
              } else {
                  /* RF core active --> 2.4 GHz */
                  PINCC26XX_setMux(antennaPins, CONFIG_RF_24GHZ, PINCC26XX_MUX_GPIO);
                  PINCC26XX_setMux(antennaPins, CONFIG_RF_HIGH_PA, PINCC26XX_MUX_GPIO);
                  PINCC26XX_setMux(antennaPins, CONFIG_RF_SUB1GHZ, PINCC26XX_MUX_GPIO);
                  PINCC26XX_setOutputValue(CONFIG_RF_24GHZ, 1);
              }
          }
        }
        else if (events & RF_GlobalEventRadioPowerDown) {
            /* Switch off all paths. */
            PINCC26XX_setOutputValue(CONFIG_RF_24GHZ, 0);
            PINCC26XX_setOutputValue(CONFIG_RF_HIGH_PA, 0);
            PINCC26XX_setOutputValue(CONFIG_RF_SUB1GHZ, 0);
    
            /* Reset the IO multiplexer to GPIO functionality */
            PINCC26XX_setMux(antennaPins, CONFIG_RF_24GHZ, PINCC26XX_MUX_GPIO);
            PINCC26XX_setMux(antennaPins, CONFIG_RF_HIGH_PA, PINCC26XX_MUX_GPIO);
            PINCC26XX_setMux(antennaPins, CONFIG_RF_SUB1GHZ, PINCC26XX_MUX_GPIO);
        }
    }
    
    #ifdef cEnableWatchDog
    /* ----------------------------------------------------------------------- */
    void PTD_InitWatchDog( void )
    {
      uint32_t        reloadValue;
      Watchdog_Params params;  
      Watchdog_init();
      /* Open a Watchdog driver instance */
      Watchdog_Params_init(&params);
      params.callbackFxn = (Watchdog_Callback) watchdogCallback;
      params.debugStallMode = Watchdog_DEBUG_STALL_ON;
    
      params.resetMode = Watchdog_RESET_ON;
      watchdogHandle = Watchdog_open(CONFIG_WATCHDOG_0, &params);
      if (watchdogHandle == NULL) {
        /* Error opening Watchdog */
        while (1) {}
      }  
      
    //  Watchdog_close(watchdogHandle);
          /*
         * The watchdog reload value is initialized during the
         * Watchdog_open() call. The reload value can also be
         * set dynamically during runtime.
         *
         * Converts TIMEOUT_MS to watchdog clock ticks.
         * This API is not applicable for all devices.
         * See the device specific watchdog driver documentation
         * for your device.
         */
        /* Watchdog reset value is 10 minutes */
        /* Put this value to 70 sec and temperature read rutine called at every 60 sec */
        reloadValue = Watchdog_convertMsToTicks(watchdogHandle, 70*1000);
        /*
         * A value of zero (0) indicates the converted value exceeds 32 bits
         * OR that the API is not applicable for this specific device.
         */
        if (reloadValue != 0) 
        {
            Watchdog_setReload(watchdogHandle, reloadValue);
        }
    }
    /* ----------------------------------------------------------------------- */
    /*
     *  ======== watchdogCallback ========
     */
    void watchdogCallback(uintptr_t watchdogHandle_p)
    {
      /*
       * If the Watchdog Non-Maskable Interrupt (NMI) is called,
       * loop until the device resets. Some devices will invoke
       * this callback upon watchdog expiration while others will
       * reset. See the device specific watchdog driver documentation
       * for your device.
       */
    //  Lcd_AllOff_g();
    //  Display_UpdateGuidingArea1_g("WATCHDOG EXPIRE", 0);
    //  Lcd_Update_g( );
    //  Task_sleep(1000*100);  
      
    #ifdef  cTestWatchDogRst
      #include "SmlUtil.h"
      tUI8 aBuffer[ 16u ];
      tUI32 PresentRstCnt;
      Flash_GetData( eFlashMfgSr, aBuffer );
      PresentRstCnt = UTIL_StrToInt( aBuffer );
      PresentRstCnt++;
      UTIL_MemSet( aBuffer, 0x30, 16u ); /* Making all zero */
      UTIL_IntToStr( PresentRstCnt, aBuffer );
      Flash_WriteData( eFlashMfgSr, 8u, aBuffer );
    #endif
      while (1) {}
    }
    
    /* ----------------------------------------------------------------------- */
    void PTD_FeedWatchDog( void )
    {
      Watchdog_clear(watchdogHandle);
    }
    #else
    /* Dummy methods */
    void PTD_FeedWatchDog( void )
    {
    }
    void PTD_InitWatchDog( void )
    {
    }  
    #endif
    
    tUI8 PTD_GetSleepStatus( void )
    {
      return (IsDeviceInSleep );
    }
    
    /* *********************************************************************** */
    #if ChangeHistory
    /* 
    $Log$
    */
    #endif
    /* End =================================================================== */
    
    8204.multi_role.c