Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

CAN I Customize my adv packet Absolutely?

I think this is a very weird requirement

Normally , I use manufacturer data to do this like picture below

it's easy and quick

but it contains len and type occupying 2 bytes

I'm wondering if there is a way to make my packet have no len and type

I know that Texas's chip can do this like picture below

it will shows malformed packet

Thanks

Parents
  • Hello,

    but it contains len and type occupying 2 bytes

    I'm wondering if there is a way to make my packet have no len and type

    Yes, and no. Type and Len is requires for each new datafield as per the BLE specification. Leaving out these two fields violated the specification, and as such the SoftDevice has checks to ensure this does not happen. If you would like to do this, you may use the Radio peripheral directly, to communicate using your own proprietary protocol. You may implement this prorprietary protocol by using timeslots to combine with using the SoftDevice. This way, the SoftDevice will release the control of the radio peripheral, so that you may do whatever you want in the time that the SoftDevice does not require the radio for BLE.
    If you want to look into implementing your own radio protocol there are many posts on the forum about this already, and I highly recommend scrolling through these to get a better understanding of what this would entail.

    I know that Texas's chip can do this like picture below

    Any chip with access to a 2.4 GHz radio peripheral can do this - but this is not BLE - which is why the sniffer displays the packet as malformed.
    Non-sniffer devices will discard any malformed packets, so unless you control both sides of the link this is not a possibility.

    Please do not hesitate to ask if anything should be unclear.

    Best regards,
    Karl

  • Hi Karl,

    thanks for reply

    I've tried timeslot according to this tutorial with nrf52832DK ,SDK_15.3

    and i successfully made the led blink by the timeslot

    So now i would want to know how to use radio peripheral to make a malformed packet or proprietary protocol

    Is there any example or document or keyword to search?

    thanks

  • Hello Aku,

    Aku said:

    thanks for reply

    I've tried timeslot according to this tutorial with nrf52832DK ,SDK_15.3

    and i successfully made the led blink by the timeslot

    No problem at all, I am happy to help! Great to hear that you found the tutorial useful, and that you have succeeded in setting up a timeslot.

    Aku said:
    Is there any example or document or keyword to search?

    Just to make sure, could you describe to me why you would want to or need to make use of a proprietary protocol? I assume it is because you are unable to fit all your data into an advertising packet's 31 Byte limit, is this correct?
    As mentioned, it is a lot more work to implement a proprietary radio protocol, so if you tell me more about your application and its requirements, perhaps we are able to find a easier method to achieve the same functionality.
    The most central question is; How many bytes do you need to advertise each advertisement?
    For example, have you exhausted the option of using the scan response data to increase the effective number of advertising bytes? Perhaps this could save you a lot of work.

    Best regards,
    Karl

Reply
  • Hello Aku,

    Aku said:

    thanks for reply

    I've tried timeslot according to this tutorial with nrf52832DK ,SDK_15.3

    and i successfully made the led blink by the timeslot

    No problem at all, I am happy to help! Great to hear that you found the tutorial useful, and that you have succeeded in setting up a timeslot.

    Aku said:
    Is there any example or document or keyword to search?

    Just to make sure, could you describe to me why you would want to or need to make use of a proprietary protocol? I assume it is because you are unable to fit all your data into an advertising packet's 31 Byte limit, is this correct?
    As mentioned, it is a lot more work to implement a proprietary radio protocol, so if you tell me more about your application and its requirements, perhaps we are able to find a easier method to achieve the same functionality.
    The most central question is; How many bytes do you need to advertise each advertisement?
    For example, have you exhausted the option of using the scan response data to increase the effective number of advertising bytes? Perhaps this could save you a lot of work.

    Best regards,
    Karl

Children
  • HI Karl

    the reason is

    My boss bought a Bluetooth Gateway system that only accept it's own protocal

    And I have to make a device to send data through by broadcast

     

    Actually,I have tried Srdata and Extend ADV already but the gateway didn't accept

    because of the len and type

    it only accepts packets that start with 0x24C3 like i circle in the picture below

    so i think proprietary protocol it's the only way

    or if there is an easier way to do that?

  • Hello Aku,

    Aku said:

    the reason is

    My boss bought a Bluetooth Gateway system that only accept it's own protocal

    And I have to make a device to send data through by broadcast

    Thank you for clarifying, this makes it much easier to understand you intentions and sought-after functionality.

    Aku said:
    Actually,I have tried Srdata and Extend ADV already but the gateway didn't accept

    I am happy to hear that you have already looked into these options!
    If it requires a non-BLE protocol then this is likely documented in the gateway's datasheet if they intend for others to create customer devices that can interact with it.

    Aku said:

    so i think proprietary protocol it's the only way

    or if there is an easier way to do that?

    Yes, if it is the case that the gateway only accepts packets that does not start with a type and length byte, this is proprietary(no longer BLE protocol), and thus you would have to use this protocol to communicate with the device. Since the SoftDevice is strictly BLE, it wont transmit / process packets that violate the BLE specification, and therefore you will have to implement this proprietary protocol yourself.

    In order to do this, you will need to setup a timeslot (like you have done already), and then use the radio peripheral directly during this time - like you would do with any other peripheral. While we do not provide any tutorials on how to do this, you could take a look at the Thingy52's source code for its eddystone advertising.
    Particularly, if you look at the functions m_get_adv_packet and m_configure_radio, in the former the non-BLE packet is setup, and in the latter the radio is configured to broadcast it. You could use this code as a starting point - substituting out the payload with that of your own.

    Best regards,
    Karl

  • hi,

    I tried but failed,

    i combine the RADIO part into my original timeslot.c

    here is my new timeslot.c

    #include <stdint.h>
    #include <stdbool.h>
    #include "nrf.h"
    #include "app_error.h"
    #include "nrf_gpio.h"
    #include "boards.h"
    #include "nrf_delay.h"
    #define PACKET_LENGTH 4
    static uint8_t packet[PACKET_LENGTH] = {1};
    /**Constants for timeslot API
    */
    static nrf_radio_request_t  m_timeslot_request;
    static uint32_t             m_slot_length;
    
    static nrf_radio_signal_callback_return_param_t signal_callback_return_param;
    
    
    void radio_configure()
    {
        // Radio config
        NRF_RADIO->TXPOWER   = (RADIO_TXPOWER_TXPOWER_0dBm << RADIO_TXPOWER_TXPOWER_Pos);
        NRF_RADIO->FREQUENCY = 80UL;                // Frequency bin 7, 2407MHz
        NRF_RADIO->MODE      = (RADIO_MODE_MODE_Nrf_2Mbit << RADIO_MODE_MODE_Pos);
        // Radio address config
        NRF_RADIO->PREFIX0     = 0x4c494c49;  // Prefix byte of addresses 3 to 0
        NRF_RADIO->PREFIX1     = 0x4c494c49;  // Prefix byte of addresses 7 to 4
        NRF_RADIO->BASE0       = 0x44444444;  // Base address for prefix 0
        NRF_RADIO->BASE1       = 0x44444444;  // Base address for prefix 1-7
        NRF_RADIO->TXADDRESS   = 0x00UL;        // Set device address 0 to use when transmitting
        NRF_RADIO->RXADDRESSES = 0x01UL;        // Enable device address 0 to use which receiving
        // Packet configuration
        NRF_RADIO->PCNF0 = (1 << RADIO_PCNF0_S1LEN_Pos) |
                           (2 << RADIO_PCNF0_S0LEN_Pos) |
                           (6 << RADIO_PCNF0_LFLEN_Pos); //lint !e845 "The right argument to operator '|' is certain to be 0"
        // Packet configuration
        NRF_RADIO->PCNF1 = (RADIO_PCNF1_WHITEEN_Disabled << RADIO_PCNF1_WHITEEN_Pos) |
                           (RADIO_PCNF1_ENDIAN_Big << RADIO_PCNF1_ENDIAN_Pos)        |
                           (2 << RADIO_PCNF1_BALEN_Pos)                              |
                           ((PACKET_LENGTH) << RADIO_PCNF1_STATLEN_Pos)              |
                           ((PACKET_LENGTH) << RADIO_PCNF1_MAXLEN_Pos); //lint !e845 "The right argument to operator '|' is certain to be 0"
        // CRC Config
        NRF_RADIO->CRCCNF = (RADIO_CRCCNF_LEN_Two << RADIO_CRCCNF_LEN_Pos); // Number of checksum bits
        if ((NRF_RADIO->CRCCNF & RADIO_CRCCNF_LEN_Msk) == (RADIO_CRCCNF_LEN_Two << RADIO_CRCCNF_LEN_Pos))
        {
            NRF_RADIO->CRCINIT = 0xFFFFUL;   // Initial value      
            NRF_RADIO->CRCPOLY = 0x11021UL;  // CRC poly: x^16+x^12^x^5+1
        }
        else if ((NRF_RADIO->CRCCNF & RADIO_CRCCNF_LEN_Msk) == (RADIO_CRCCNF_LEN_One << RADIO_CRCCNF_LEN_Pos))
        {
            NRF_RADIO->CRCINIT = 0xFFUL;   // Initial value
            NRF_RADIO->CRCPOLY = 0x107UL;  // CRC poly: x^8+x^2^x^1+1
        }
        nrf_delay_ms(3);
    }
    
    
    
    /**@brief Request next timeslot event in earliest configuration
     */
    uint32_t request_next_event_earliest(void)
    {
        m_slot_length                                  = 25000;
        m_timeslot_request.request_type                = NRF_RADIO_REQ_TYPE_EARLIEST;
        m_timeslot_request.params.earliest.hfclk       = NRF_RADIO_HFCLK_CFG_XTAL_GUARANTEED;
        m_timeslot_request.params.earliest.priority    = NRF_RADIO_PRIORITY_NORMAL;
        m_timeslot_request.params.earliest.length_us   = m_slot_length;
        m_timeslot_request.params.earliest.timeout_us  = 1000000;
        return sd_radio_request(&m_timeslot_request);
    }
    
    
    /**@brief Configure next timeslot event in earliest configuration
     */
    void configure_next_event_earliest(void)
    {
        m_slot_length                                  = 25000;
        m_timeslot_request.request_type                = NRF_RADIO_REQ_TYPE_EARLIEST;
        m_timeslot_request.params.earliest.hfclk       = NRF_RADIO_HFCLK_CFG_XTAL_GUARANTEED;
        m_timeslot_request.params.earliest.priority    = NRF_RADIO_PRIORITY_NORMAL;
        m_timeslot_request.params.earliest.length_us   = m_slot_length;
        m_timeslot_request.params.earliest.timeout_us  = 1000000;
    }
    
    
    /**@brief Configure next timeslot event in normal configuration
     */
    void configure_next_event_normal(void)
    {
        m_slot_length                                 = 25000;
        m_timeslot_request.request_type               = NRF_RADIO_REQ_TYPE_NORMAL;
        m_timeslot_request.params.normal.hfclk        = NRF_RADIO_HFCLK_CFG_XTAL_GUARANTEED;
        m_timeslot_request.params.normal.priority     = NRF_RADIO_PRIORITY_HIGH;
        m_timeslot_request.params.normal.distance_us  = 300000;
        m_timeslot_request.params.normal.length_us    = m_slot_length;
    }
    
    
    /**@brief Timeslot signal handler
     */
    void nrf_evt_signal_handler(uint32_t evt_id)
    {
        uint32_t err_code;
        
        switch (evt_id)
        {
            case NRF_EVT_RADIO_SIGNAL_CALLBACK_INVALID_RETURN:
                //No implementation needed
                break;
            case NRF_EVT_RADIO_SESSION_IDLE:
                //No implementation needed
                break;
            case NRF_EVT_RADIO_SESSION_CLOSED:
                //No implementation needed, session ended
                break;
            case NRF_EVT_RADIO_BLOCKED:
                //Fall through
            case NRF_EVT_RADIO_CANCELED:
                err_code = request_next_event_earliest();
                APP_ERROR_CHECK(err_code);
                break;
            default:
                break;
        }
    }
    
    
    /**@brief Timeslot event handler
     */
    nrf_radio_signal_callback_return_param_t * radio_callback(uint8_t signal_type)
    {
        switch(signal_type)
        {
            case NRF_RADIO_CALLBACK_SIGNAL_TYPE_START:
                //Start of the timeslot - set up timer interrupt
                signal_callback_return_param.params.request.p_next = NULL;
                signal_callback_return_param.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_NONE;
    
    #if 1            
                NRF_TIMER0->TASKS_STOP          = 1;
                NRF_TIMER0->TASKS_CLEAR         = 1;
                NRF_TIMER0->MODE                = (TIMER_MODE_MODE_Timer << TIMER_MODE_MODE_Pos);
                NRF_TIMER0->EVENTS_COMPARE[0]   = 0;
                NRF_TIMER0->INTENSET            = TIMER_INTENSET_COMPARE0_Msk ;
                NRF_TIMER0->CC[0]               = m_slot_length - 1000;
                NRF_TIMER0->BITMODE             = (TIMER_BITMODE_BITMODE_24Bit << TIMER_BITMODE_BITMODE_Pos);
                NRF_TIMER0->TASKS_START         = 1;
                //非常重要,    reset all status in the radio peripheral
                radio_configure();
                NRF_RADIO->POWER                = (RADIO_POWER_POWER_Enabled << RADIO_POWER_POWER_Pos);
    #else
                NRF_TIMER0->INTENSET = TIMER_INTENSET_COMPARE0_Msk;
                NRF_TIMER0->CC[0] = m_slot_length - 1000;
    #endif
                NVIC_EnableIRQ(TIMER0_IRQn);
                NRF_RADIO->EVENTS_DISABLED = 0;
                NRF_RADIO->TASKS_DISABLE = 1;
                while( NRF_RADIO->EVENTS_DISABLED == 0 );
                NRF_RADIO->PACKETPTR = (uint32_t)&packet;
                        NRF_RADIO->EVENTS_READY = 0U;  				
                        NRF_RADIO->TASKS_TXEN   = 1;
                        while (NRF_RADIO->EVENTS_READY == 0U)
                       {
                       }
                       NRF_RADIO->TASKS_START = 1U;
                       NRF_RADIO->EVENTS_END  = 0U;  
                       while (NRF_RADIO->EVENTS_END == 0U)
                       {
                       }
                       NRF_RADIO->EVENTS_DISABLED = 0U;
                       // Disable radio
                       NRF_RADIO->TASKS_DISABLE = 1U;
                       while (NRF_RADIO->EVENTS_DISABLED == 0U)
                       {
                       }		 
                       NRF_RADIO->POWER = 0;
                
                nrf_gpio_pin_toggle(20); //Toggle LED4
                break;
    
            case NRF_RADIO_CALLBACK_SIGNAL_TYPE_RADIO:
                signal_callback_return_param.params.request.p_next = NULL;
                signal_callback_return_param.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_NONE;
                break;
    
            case NRF_RADIO_CALLBACK_SIGNAL_TYPE_TIMER0:
                //Timer interrupt - do graceful shutdown - schedule next timeslot
                configure_next_event_normal();
                signal_callback_return_param.params.request.p_next = &m_timeslot_request;
                signal_callback_return_param.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_REQUEST_AND_END;
                break;
            case NRF_RADIO_CALLBACK_SIGNAL_TYPE_EXTEND_SUCCEEDED:
                //No implementation needed
                break;
            case NRF_RADIO_CALLBACK_SIGNAL_TYPE_EXTEND_FAILED:
                //Try scheduling a new timeslot
                configure_next_event_earliest();
                signal_callback_return_param.params.request.p_next = &m_timeslot_request;
                signal_callback_return_param.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_REQUEST_AND_END;
                break;
            default:
                //No implementation needed
                break;
        }
        return (&signal_callback_return_param);
    }
    
    
    /**@brief Function for initializing the timeslot API.
     */
    uint32_t timeslot_sd_init(void)
    {
        uint32_t err_code;
        
        err_code = sd_radio_session_open(radio_callback);
        if (err_code != NRF_SUCCESS)
        {
            return err_code;
        }
        
        err_code = request_next_event_earliest();
        if (err_code != NRF_SUCCESS)
        {
            (void)sd_radio_session_close();
            return err_code;
        }
        return NRF_SUCCESS;
    }
    
    
    
    

    it can still request a timeslot to blink the led,

    but it seems that RADIO is not working

    and i am so confused about some of the settings(registers),even i read the product specification

     Any suggestions will be appreciated

  • Hello,

    Thank you for your patience!

    Aku said:
    I tried but failed,

    I am sorry to hear that! Lets see if we cant resolve this issue together.

    Aku said:

    it can still request a timeslot to blink the led,

    but it seems that RADIO is not working

    Then we know that the device is not resetting, or otherwise failing, at least.
    How have you verified that the radio is not working? 

    Aku said:
    and i am so confused about some of the settings(registers),even i read the product specification

    Do you mean that you read the nRF52832 RADIO peripheral's documentation, but you are still confused about some of the configurations? Is there any register / configuration in particular you would like me to explain?

    You could use the nrf_radio_event_check function to see whether a certain event has occurred, or nrf_radio_state_get to check whether the configuration was a success, or in general which state the radio is in at that time. The transmit sequence diagram indicates how the state-transitions should be during a transfer.
    Could you these conditional checks, so that you are sure not to proceed to start the next RADIO TASK, before the radio is ready?

    Best regards,
    Karl

Related