<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="https://devzone.nordicsemi.com/cfs-file/__key/system/syndication/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Implementing ACK in software ESB</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/58709/implementing-ack-in-software-esb</link><description>Hello, 
 I have to implement ESB on nRF52 bare metal (using the RADIO peripheral). I can receive packets from the nRF24, but I need to implement the ACK, and I&amp;#39;m not sure what this looks like. From the nrf24l01+ datasheet, I know a packet has a preamble</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Thu, 05 Mar 2020 15:04:17 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/58709/implementing-ack-in-software-esb" /><item><title>RE: Implementing ACK in software ESB</title><link>https://devzone.nordicsemi.com/thread/238348?ContentTypeID=1</link><pubDate>Thu, 05 Mar 2020 15:04:17 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:451579cb-70c2-4ec1-bf4e-b34505993566</guid><dc:creator>bjorn-spockeli</dc:creator><description>&lt;p&gt;Hi&amp;nbsp;Cwmoreiras,&lt;/p&gt;
&lt;p&gt;just out of curiosity, why can&amp;#39;t you use the ESB implementation in our SDK?&amp;nbsp; It is backwards compatible with the nRF24, see&amp;nbsp;&lt;a title="Backward compatibility" href="https://infocenter.nordicsemi.com/topic/sdk_nrf5_v16.0.0/esb_users_guide.html?cp=7_1_5_2_2#esb_backwards"&gt;Backward compatibility&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Looking at our ESB implementation I found the following functions&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;static void update_rf_payload_format_esb_dpl(uint32_t payload_length)
{
#if (NRF_ESB_MAX_PAYLOAD_LENGTH &amp;lt;= 32)
    // Using 6 bits for length
    NRF_RADIO-&amp;gt;PCNF0 = (0 &amp;lt;&amp;lt; RADIO_PCNF0_S0LEN_Pos) |
                       (6 &amp;lt;&amp;lt; RADIO_PCNF0_LFLEN_Pos) |
                       (3 &amp;lt;&amp;lt; RADIO_PCNF0_S1LEN_Pos) ;
#else
    // Using 8 bits for length
    NRF_RADIO-&amp;gt;PCNF0 = (0 &amp;lt;&amp;lt; RADIO_PCNF0_S0LEN_Pos) |
                       (8 &amp;lt;&amp;lt; RADIO_PCNF0_LFLEN_Pos) |
                       (3 &amp;lt;&amp;lt; RADIO_PCNF0_S1LEN_Pos) ;
#endif
    NRF_RADIO-&amp;gt;PCNF1 = (RADIO_PCNF1_WHITEEN_Disabled    &amp;lt;&amp;lt; RADIO_PCNF1_WHITEEN_Pos) |
                       (RADIO_PCNF1_ENDIAN_Big          &amp;lt;&amp;lt; RADIO_PCNF1_ENDIAN_Pos)  |
                       ((m_esb_addr.addr_length - 1)    &amp;lt;&amp;lt; RADIO_PCNF1_BALEN_Pos)   |
                       (0                               &amp;lt;&amp;lt; RADIO_PCNF1_STATLEN_Pos) |
                       (NRF_ESB_MAX_PAYLOAD_LENGTH      &amp;lt;&amp;lt; RADIO_PCNF1_MAXLEN_Pos);
}


static void update_rf_payload_format_esb(uint32_t payload_length)
{
    NRF_RADIO-&amp;gt;PCNF0 = (1 &amp;lt;&amp;lt; RADIO_PCNF0_S0LEN_Pos) |
                       (0 &amp;lt;&amp;lt; RADIO_PCNF0_LFLEN_Pos) |
                       (1 &amp;lt;&amp;lt; RADIO_PCNF0_S1LEN_Pos);

    NRF_RADIO-&amp;gt;PCNF1 = (RADIO_PCNF1_WHITEEN_Disabled    &amp;lt;&amp;lt; RADIO_PCNF1_WHITEEN_Pos) |
                       (RADIO_PCNF1_ENDIAN_Big          &amp;lt;&amp;lt; RADIO_PCNF1_ENDIAN_Pos)  |
                       ((m_esb_addr.addr_length - 1)    &amp;lt;&amp;lt; RADIO_PCNF1_BALEN_Pos)   |
                       (payload_length                  &amp;lt;&amp;lt; RADIO_PCNF1_STATLEN_Pos) |
                       (payload_length                  &amp;lt;&amp;lt; RADIO_PCNF1_MAXLEN_Pos);
}
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Also looking at the&amp;nbsp;NRF_ESB_PROTOCOL_ESB_DPL case in&amp;nbsp;start_tx_transaction() might offer some clues.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;static void start_tx_transaction()
{
    bool ack;

    m_last_tx_attempts = 1;
    // Prepare the payload
    mp_current_payload = m_tx_fifo.p_payload[m_tx_fifo.exit_point];


    switch (m_config_local.protocol)
    {
        case NRF_ESB_PROTOCOL_ESB:
            update_rf_payload_format(mp_current_payload-&amp;gt;length);
            m_tx_payload_buffer[0] = mp_current_payload-&amp;gt;pid;
            m_tx_payload_buffer[1] = 0;
            memcpy(&amp;amp;m_tx_payload_buffer[2], mp_current_payload-&amp;gt;data, mp_current_payload-&amp;gt;length);

            NRF_RADIO-&amp;gt;SHORTS   = m_radio_shorts_common | RADIO_SHORTS_DISABLED_RXEN_Msk;
            NRF_RADIO-&amp;gt;INTENSET = RADIO_INTENSET_DISABLED_Msk | RADIO_INTENSET_READY_Msk;

            // Configure the retransmit counter
            m_retransmits_remaining = m_config_local.retransmit_count;
            on_radio_disabled = on_radio_disabled_tx;
            m_nrf_esb_mainstate = NRF_ESB_STATE_PTX_TX_ACK;
            break;

        case NRF_ESB_PROTOCOL_ESB_DPL:
            ack = !mp_current_payload-&amp;gt;noack || !m_config_local.selective_auto_ack;
            m_tx_payload_buffer[0] = mp_current_payload-&amp;gt;length;
            m_tx_payload_buffer[1] = mp_current_payload-&amp;gt;pid &amp;lt;&amp;lt; 1;
            m_tx_payload_buffer[1] |= mp_current_payload-&amp;gt;noack ? 0x00 : 0x01;
            memcpy(&amp;amp;m_tx_payload_buffer[2], mp_current_payload-&amp;gt;data, mp_current_payload-&amp;gt;length);

            // Handling ack if noack is set to false or if selective auto ack is turned off
            if (ack)
            {
                NRF_RADIO-&amp;gt;SHORTS   = m_radio_shorts_common | RADIO_SHORTS_DISABLED_RXEN_Msk;
                NRF_RADIO-&amp;gt;INTENSET = RADIO_INTENSET_DISABLED_Msk | RADIO_INTENSET_READY_Msk;

                // Configure the retransmit counter
                m_retransmits_remaining = m_config_local.retransmit_count;
                on_radio_disabled = on_radio_disabled_tx;
                m_nrf_esb_mainstate = NRF_ESB_STATE_PTX_TX_ACK;
            }
            else
            {
                NRF_RADIO-&amp;gt;SHORTS   = m_radio_shorts_common;
                NRF_RADIO-&amp;gt;INTENSET = RADIO_INTENSET_DISABLED_Msk;
                on_radio_disabled   = on_radio_disabled_tx_noack;
                m_nrf_esb_mainstate = NRF_ESB_STATE_PTX_TX;
            }
            break;

        default:
            // Should not be reached
            break;
    }

    NRF_RADIO-&amp;gt;TXADDRESS    = mp_current_payload-&amp;gt;pipe;
    NRF_RADIO-&amp;gt;RXADDRESSES  = 1 &amp;lt;&amp;lt; mp_current_payload-&amp;gt;pipe;

    NRF_RADIO-&amp;gt;FREQUENCY    = m_esb_addr.rf_channel;
    NRF_RADIO-&amp;gt;PACKETPTR    = (uint32_t)m_tx_payload_buffer;

    NVIC_ClearPendingIRQ(RADIO_IRQn);
    NVIC_EnableIRQ(RADIO_IRQn);

    NRF_RADIO-&amp;gt;EVENTS_ADDRESS = 0;
    NRF_RADIO-&amp;gt;EVENTS_PAYLOAD = 0;
    NRF_RADIO-&amp;gt;EVENTS_DISABLED = 0;

    DEBUG_PIN_SET(DEBUGPIN4);
    NRF_RADIO-&amp;gt;TASKS_TXEN  = 1;
}
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Best regards&lt;/p&gt;
&lt;p&gt;Bjørn&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>