<?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>PWM Sequence from HAL to NRFX</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/91908/pwm-sequence-from-hal-to-nrfx</link><description>Hello 
 
 I am trying to change the code from the HAL code up to NRFX in order to make it event-based instead of using infinite while loops. 
 
 I am using 52840 on a custom PCA with goal in mind to create a half-duplex-half-UART communication. 
 Working</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Mon, 19 Sep 2022 13:54:33 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/91908/pwm-sequence-from-hal-to-nrfx" /><item><title>RE: PWM Sequence from HAL to NRFX</title><link>https://devzone.nordicsemi.com/thread/386924?ContentTypeID=1</link><pubDate>Mon, 19 Sep 2022 13:54:33 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:022b8f35-0d88-412c-a619-473bd3f38052</guid><dc:creator>hmolesworth</dc:creator><description>&lt;p&gt;Not sure I understand your duty cycle comments; can you sketch a wavefor of a specific character?&lt;/p&gt;
&lt;p&gt;The frequence is set by&amp;nbsp;LL_BAUDRATE =1200, which is 1.2kHz; 32kHz is set by&amp;nbsp;LL_BAUDRATE =32000&lt;/p&gt;
&lt;p&gt;To get crystal-stable frequency with no jitter add this code at the start:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;    // Start accurate HFCLK (XOSC)
    NRF_CLOCK-&amp;gt;TASKS_HFCLKSTART = 1;
    while (NRF_CLOCK-&amp;gt;EVENTS_HFCLKSTARTED == 0)
        ;
    NRF_CLOCK-&amp;gt;EVENTS_HFCLKSTARTED = 0;
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Standard UART:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;// Standard Uart character 0x21
//
//        |     |     |     |     |     |     |     |     |     |     |
//  Idle   Start   0     1     2     3     4     5     6     7   Stop    Idle
// -------+     +-----+                       +-----+           +-----+-------
//        |     |     |                       |     |           |
//        |     |     |                       |     |           |       Normal
//        +-----+     +-----+-----+-----+-----+     +-----+-----+
//
//        +-----+     +-----+-----+-----+-----+     +-----+-----+
//        |     |     |                       |     |           |       Invert
//        |     |     |                       |     |           |
// -------+     +-----+                       +-----+           +-----+-------&lt;/pre&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: PWM Sequence from HAL to NRFX</title><link>https://devzone.nordicsemi.com/thread/386883?ContentTypeID=1</link><pubDate>Mon, 19 Sep 2022 12:51:25 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:01ec32aa-bcd0-4560-9cfa-e79305a72fab</guid><dc:creator>falcuun</dc:creator><description>&lt;p&gt;Hi, Thank you so much for working the solution out and testing it!&amp;nbsp;&lt;br /&gt;I have adapted your solution to my code and managed to get a similar output to the one that I need. But I still have one small issue: The Frequency is ~1KHz, I need 32.&amp;nbsp;&lt;br /&gt;Duty cycle keeps varrying from 20-80% where as I need it on 50% (As fixed as possible). I&amp;#39;ve tried changing some values in the code you provided, but I&amp;#39;m having no luck with getting the wanted result.&amp;nbsp;&lt;br /&gt;If you have a fix for that as well, that&amp;#39;ll have solved my issue.&amp;nbsp;&lt;br /&gt;And if not, I am beyond grateful for the help thus far, it&amp;#39;s helped me get a little deeper understanding of how the new API is working.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: PWM Sequence from HAL to NRFX</title><link>https://devzone.nordicsemi.com/thread/386724?ContentTypeID=1</link><pubDate>Sat, 17 Sep 2022 00:52:49 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:0885ca03-7b11-4e46-b66a-e1c3cd9fe8df</guid><dc:creator>hmolesworth</dc:creator><description>&lt;p&gt;Ok couldn&amp;#39;t resist testing further, so here&amp;#39;s a working example using the 4-byte data you specified:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;// PWM Half-Duplex UART - nrfx drivers
// ===================================
// Requirements
//  10 bit bytes (Start - 8xData - Stop)
//  single char or burst (packet) transmission
//  Differential output using 2 pins
//  No level change on pins outside transmitted data to avoid spurious character detection
#include &amp;quot;nrf_pwm.h&amp;quot;

#define LL_BAUDRATE      1200
#define F_CLK        16000000              // nRF52832/nRF52840 fixed at 16MHz
#define F_PRESCALER  (PWM_PRESCALER_PRESCALER_DIV_1)  // Divide by 1, 16MHz clock
#define COUNTER_TOP  ((F_CLK+(LL_BAUDRATE/2)) / LL_BAUDRATE)
STATIC_ASSERT(COUNTER_TOP &amp;lt; 32768, &amp;quot;COUNTER_TOP value too large for 15-bit register&amp;quot;);
STATIC_ASSERT(COUNTER_TOP &amp;gt;= 3, &amp;quot;COUNTER_TOP value too small for correct operation&amp;quot;);
#define BIT_LOW               0           // Normal encoding
#define BIT_HIGH    (COUNTER_TOP)         // Normal encoding
//#define BIT_LOW   ((2*COUNTER_TOP)/3)   // Manchester encoding 2/3 bit
//#define BIT_HIGH  (COUNTER_TOP/3)       // Manchester encoding 1/3 bit
#define PWM_NEG (PIN_FEATHER_D6)          // Low level outside transmission
#define PWM_POS (PIN_FEATHER_D9)          // High level outside transmission

typedef struct TX_BYTE_T {
    nrf_pwm_values_grouped_t StartBit;
    nrf_pwm_values_grouped_t DataBits[8];
    nrf_pwm_values_grouped_t StopBit;
} TxByte_t;

TxByte_t TxPacket[4];
const uint16_t TxPacketSize = (sizeof(TxPacket)/sizeof(uint16_t));

void encodeByte(TxByte_t* pBuffer, const uint8_t ch)
{
    // Encode byte in little-endian format with start and stop bits
    pBuffer-&amp;gt;StartBit.group_0 = pBuffer-&amp;gt;StartBit.group_1 = (BIT_LOW);  pBuffer-&amp;gt;StartBit.group_0 |= 0x8000; // 0 Start bit
    pBuffer-&amp;gt;StopBit.group_0  = pBuffer-&amp;gt;StopBit.group_1  = (BIT_HIGH); pBuffer-&amp;gt;StopBit.group_0  |= 0x8000; // 0 Stop bit
    for(uint32_t i=0; i&amp;lt;8; i++)
    {
        pBuffer-&amp;gt;DataBits[i].group_0 = pBuffer-&amp;gt;DataBits[i].group_1 = (((ch&amp;gt;&amp;gt;i) &amp;amp; 0x01) ? BIT_HIGH : BIT_LOW);
        pBuffer-&amp;gt;DataBits[i].group_0 |= 0x8000; // inverted pin
    }
}

buildMessage(void)
{
    TxByte_t *pTx = TxPacket;
    uint8_t STX         = 0x82;
    uint8_t signal_id   = 0x64 | 0x80;
    uint8_t data_byte_0 = 0x03 | 0x80;
    uint8_t checksum    = (signal_id) + (data_byte_0);
    checksum &amp;amp;= 0x7F;
    encodeByte(pTx++, STX);
    encodeByte(pTx++, signal_id);
    encodeByte(pTx++, data_byte_0);
    encodeByte(pTx++, checksum);
}

void TestPWM_Uart(void)
{
    static nrfx_pwm_t m_pwm0 = NRFX_PWM_INSTANCE(0);
    uint32_t err_code;
    // Declare a configuration structure and use a macro to instantiate it with default parameters.
    nrfx_pwm_config_t pwm_config = NRFX_PWM_DEFAULT_CONFIG;
    //    .irq_priority = NRFX_PWM_DEFAULT_CONFIG_IRQ_PRIORITY,                  \
    //    .base_clock   = (nrf_pwm_clk_t)NRFX_PWM_DEFAULT_CONFIG_BASE_CLOCK,     \
    //    .count_mode   = (nrf_pwm_mode_t)NRFX_PWM_DEFAULT_CONFIG_COUNT_MODE,    \
    //    .top_value    = NRFX_PWM_DEFAULT_CONFIG_TOP_VALUE,                     \
    //    .load_mode    = (nrf_pwm_dec_load_t)NRFX_PWM_DEFAULT_CONFIG_LOAD_MODE, \
    //    .step_mode    = (nrf_pwm_dec_step_t)NRFX_PWM_DEFAULT_CONFIG_STEP_MODE
   static nrf_pwm_sequence_t pwm_sequence;

    // Override some of the default parameters:
    pwm_config.output_pins[0] = PWM_NEG | NRFX_PWM_PIN_INVERTED;
    pwm_config.output_pins[1] = NRFX_PWM_PIN_NOT_USED;
    pwm_config.output_pins[2] = PWM_POS;
    pwm_config.output_pins[3] = NRFX_PWM_PIN_NOT_USED;

    pwm_config.load_mode      = NRF_PWM_LOAD_GROUPED;   // 1 == 1st half word (16-bit) used in channels 0 and 1; 2nd word in channels 2 and 3
    pwm_config.base_clock     = F_PRESCALER;            // 0 == divide by 1 for 16MHz clock
    pwm_config.step_mode      = NRFX_PWM_DEFAULT_CONFIG_STEP_MODE; // 0 == Count Up
    pwm_config.top_value      = COUNTER_TOP;

    // Pass config structure into driver init() function
    err_code = nrfx_pwm_init(&amp;amp;m_pwm0, &amp;amp;pwm_config, NULL);
    APP_ERROR_CHECK(err_code);
    // Boost differential pwm driver pins to high drive - this is optional
    nrf_gpio_cfg(PWM_NEG, NRF_GPIO_PIN_DIR_OUTPUT, NRF_GPIO_PIN_INPUT_DISCONNECT, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_H0H1, NRF_GPIO_PIN_NOSENSE);
    nrf_gpio_cfg(PWM_POS, NRF_GPIO_PIN_DIR_OUTPUT, NRF_GPIO_PIN_INPUT_DISCONNECT, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_H0H1, NRF_GPIO_PIN_NOSENSE);
    // Encode the 4-byte test message
    buildMessage();
    pwm_sequence.values.p_grouped = (uint32_t)TxPacket;
    pwm_sequence.length           = TxPacketSize;
    pwm_sequence.repeats          = 0;
    nrfx_pwm_simple_playback(&amp;amp;m_pwm0, &amp;amp;pwm_sequence, 1, NRFX_PWM_FLAG_STOP); // Send once
    while (1)
    {
        __WFE();
    }
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Usually would add an interrupt to signify end-of-transmission&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: PWM Sequence from HAL to NRFX</title><link>https://devzone.nordicsemi.com/thread/386469?ContentTypeID=1</link><pubDate>Thu, 15 Sep 2022 22:29:18 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:b6bb454d-d638-442f-ad21-7ba9df7053d5</guid><dc:creator>hmolesworth</dc:creator><description>&lt;p&gt;So I have solutions for you, but rather than edit the code just posted I just wrote the simplest which does the job (hopefully). There are a&amp;nbsp;few&amp;nbsp;requirements (my interpretation):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;10 bit bytes (Start - 8xData - Stop)&lt;/li&gt;
&lt;li&gt;single char or burst (packet) transmission&lt;/li&gt;
&lt;li&gt;Differential output using 2 pins&lt;/li&gt;
&lt;li&gt;No level change on pins outside transmitted data to avoid spurious character detection&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;First example is low-level, just to show the register requirements (I tested this code, transmits a 2-byte packet):&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;// PWM Half-Duplex UART
// ====================
#include &amp;quot;nrf_delay.h&amp;quot;
#include &amp;quot;nrf_pwm.h&amp;quot;

#define LL_BAUDRATE      1200
#define F_CLK        16000000              // nRF52832/nRF52840 fixed at 16MHz
#define F_PRESCALER  (PWM_PRESCALER_PRESCALER_DIV_1)  // Divide by 1, 16MHz clock
#define COUNTER_TOP  ((F_CLK+(LL_BAUDRATE/2)) / LL_BAUDRATE)
STATIC_ASSERT(COUNTER_TOP &amp;lt; 32768, &amp;quot;COUNTER_TOP value too large for 15-bit register&amp;quot;);
STATIC_ASSERT(COUNTER_TOP &amp;gt;= 3, &amp;quot;COUNTER_TOP value too small for correct operation&amp;quot;);
#define BIT_LOW               0           // Normal encoding
#define BIT_HIGH    (COUNTER_TOP)         // Normal encoding
#define PWM_NEG (PIN_FEATHER_D6)          // Low level outside transmission
#define PWM_POS (PIN_FEATHER_D9)          // High level outside transmission
#define STX_BYTE 0x02 // Example start character: STX (^B)
#define ETX_BYTE 0x03 // Example end character:   ETX (^C)

// Example STX byte in little-endian format
#define STX_BIT_0 (((STX_BYTE&amp;gt;&amp;gt;0) &amp;amp; 0x01) ? BIT_HIGH : BIT_LOW)
#define STX_BIT_1 (((STX_BYTE&amp;gt;&amp;gt;1) &amp;amp; 0x01) ? BIT_HIGH : BIT_LOW)
#define STX_BIT_2 (((STX_BYTE&amp;gt;&amp;gt;2) &amp;amp; 0x01) ? BIT_HIGH : BIT_LOW)
#define STX_BIT_3 (((STX_BYTE&amp;gt;&amp;gt;3) &amp;amp; 0x01) ? BIT_HIGH : BIT_LOW)
#define STX_BIT_4 (((STX_BYTE&amp;gt;&amp;gt;4) &amp;amp; 0x01) ? BIT_HIGH : BIT_LOW)
#define STX_BIT_5 (((STX_BYTE&amp;gt;&amp;gt;5) &amp;amp; 0x01) ? BIT_HIGH : BIT_LOW)
#define STX_BIT_6 (((STX_BYTE&amp;gt;&amp;gt;6) &amp;amp; 0x01) ? BIT_HIGH : BIT_LOW)
#define STX_BIT_7 (((STX_BYTE&amp;gt;&amp;gt;7) &amp;amp; 0x01) ? BIT_HIGH : BIT_LOW)
// Example ETX byte in little-endian format
#define ETX_BIT_0 (((ETX_BYTE&amp;gt;&amp;gt;0) &amp;amp; 0x01) ? BIT_HIGH : BIT_LOW)
#define ETX_BIT_1 (((ETX_BYTE&amp;gt;&amp;gt;1) &amp;amp; 0x01) ? BIT_HIGH : BIT_LOW)
#define ETX_BIT_2 (((ETX_BYTE&amp;gt;&amp;gt;2) &amp;amp; 0x01) ? BIT_HIGH : BIT_LOW)
#define ETX_BIT_3 (((ETX_BYTE&amp;gt;&amp;gt;3) &amp;amp; 0x01) ? BIT_HIGH : BIT_LOW)
#define ETX_BIT_4 (((ETX_BYTE&amp;gt;&amp;gt;4) &amp;amp; 0x01) ? BIT_HIGH : BIT_LOW)
#define ETX_BIT_5 (((ETX_BYTE&amp;gt;&amp;gt;5) &amp;amp; 0x01) ? BIT_HIGH : BIT_LOW)
#define ETX_BIT_6 (((ETX_BYTE&amp;gt;&amp;gt;6) &amp;amp; 0x01) ? BIT_HIGH : BIT_LOW)
#define ETX_BIT_7 (((ETX_BYTE&amp;gt;&amp;gt;7) &amp;amp; 0x01) ? BIT_HIGH : BIT_LOW)

// Example using grouped, note uses pin channels 0 and 2 not 0 and 1
nrf_pwm_values_grouped_t halfDuplexUartMsg[] = {
  //   Index   Normal pin 0        Inverted pin 2
  //   =====   =================== ==============
  { /* 0:0  */ 0x8000|(BIT_LOW),   (BIT_LOW),  }, // Start bit
  { /* 0:1  */ 0x8000|(STX_BIT_0), (STX_BIT_0) },
  { /* 0:2  */ 0x8000|(STX_BIT_1), (STX_BIT_1) },
  { /* 0:3  */ 0x8000|(STX_BIT_2), (STX_BIT_2) },
  { /* 0:4  */ 0x8000|(STX_BIT_3), (STX_BIT_3) },
  { /* 0:5  */ 0x8000|(STX_BIT_4), (STX_BIT_4) },
  { /* 0:6  */ 0x8000|(STX_BIT_5), (STX_BIT_5) },
  { /* 0:7  */ 0x8000|(STX_BIT_6), (STX_BIT_6) },
  { /* 0:8  */ 0x8000|(STX_BIT_7), (STX_BIT_7) },
  { /* 0:9  */ 0x8000|(BIT_HIGH),  (BIT_HIGH), }, // Stop bit 1

  { /* 1:0  */ 0x8000|(BIT_LOW),   (BIT_LOW),  }, // Start bit
  { /* 1:1  */ 0x8000|(ETX_BIT_0), (ETX_BIT_0) },
  { /* 1:2  */ 0x8000|(ETX_BIT_1), (ETX_BIT_1) },
  { /* 1:3  */ 0x8000|(ETX_BIT_2), (ETX_BIT_2) },
  { /* 1:4  */ 0x8000|(ETX_BIT_3), (ETX_BIT_3) },
  { /* 1:5  */ 0x8000|(ETX_BIT_4), (ETX_BIT_4) },
  { /* 1:6  */ 0x8000|(ETX_BIT_5), (ETX_BIT_5) },
  { /* 1:7  */ 0x8000|(ETX_BIT_6), (ETX_BIT_6) },
  { /* 1:8  */ 0x8000|(ETX_BIT_7), (ETX_BIT_7) },
  { /* 1:9  */ 0x8000|(BIT_HIGH),  (BIT_HIGH), }, // Stop bit 1
};
#define NUM_PWM_ITERATIONS  ( sizeof(halfDuplexUartMsg)/sizeof(halfDuplexUartMsg[0].group_0) )
#define NUM_PWM_TABLE_LINES ( sizeof(halfDuplexUartMsg)/sizeof(halfDuplexUartMsg[0]) )
STATIC_ASSERT(sizeof(nrf_pwm_values_grouped_t) == sizeof(halfDuplexUartMsg[0]), &amp;quot;halfDuplexUart line size&amp;quot;);
STATIC_ASSERT((NUM_PWM_ITERATIONS) == 40, &amp;quot;iterations&amp;quot;);

void TestPWM_Uart(void)
{
    // Start accurate HFCLK (XOSC)
    NRF_CLOCK-&amp;gt;TASKS_HFCLKSTART = 1;
    while (NRF_CLOCK-&amp;gt;EVENTS_HFCLKSTARTED == 0)
        ;
    NRF_CLOCK-&amp;gt;EVENTS_HFCLKSTARTED = 0;
    // Configure PWM pins as outputs, drive low or high
    NRF_GPIO-&amp;gt;DIRSET = (1 &amp;lt;&amp;lt; PWM_NEG);
    NRF_GPIO-&amp;gt;OUTSET = (1 &amp;lt;&amp;lt; PWM_NEG);  // Normal, stays low outside message
    NRF_GPIO-&amp;gt;DIRSET = (1 &amp;lt;&amp;lt; PWM_POS);
    NRF_GPIO-&amp;gt;OUTCLR = (1 &amp;lt;&amp;lt; PWM_POS);  // Inverted, stays high outside message
    nrf_delay_ms(10);                   // Pause so can see initial condition on &amp;#39;scope single=shot
    NRF_PWM0-&amp;gt;PRESCALER = F_PRESCALER;
    NRF_PWM0-&amp;gt;PSEL.OUT[0] = PWM_NEG;
    NRF_PWM0-&amp;gt;PSEL.OUT[1] = 0x80000000; // Disconnected
    NRF_PWM0-&amp;gt;PSEL.OUT[2] = PWM_POS;
    NRF_PWM0-&amp;gt;PSEL.OUT[3] = 0x80000000; // Disconnected
    NRF_PWM0-&amp;gt;MODE = (PWM_MODE_UPDOWN_Up &amp;lt;&amp;lt; PWM_MODE_UPDOWN_Pos);
    NRF_PWM0-&amp;gt;DECODER = (PWM_DECODER_LOAD_Grouped &amp;lt;&amp;lt; PWM_DECODER_LOAD_Pos) | (PWM_DECODER_MODE_RefreshCount &amp;lt;&amp;lt; PWM_DECODER_MODE_Pos);
    NRF_PWM0-&amp;gt;LOOP = 0;
    NRF_PWM0-&amp;gt;COUNTERTOP = COUNTER_TOP;
    NRF_PWM0-&amp;gt;SEQ[0].CNT = (NUM_PWM_ITERATIONS) &amp;lt;&amp;lt; PWM_SEQ_CNT_CNT_Pos;
    NRF_PWM0-&amp;gt;SEQ[0].PTR = (uint32_t)halfDuplexUartMsg;
    NRF_PWM0-&amp;gt;SEQ[0].ENDDELAY = 0;
    NRF_PWM0-&amp;gt;SEQ[0].REFRESH = 0;
    NRF_PWM0-&amp;gt;SEQ[1].CNT = (NUM_PWM_ITERATIONS) &amp;lt;&amp;lt; PWM_SEQ_CNT_CNT_Pos;
    NRF_PWM0-&amp;gt;SEQ[1].PTR = (uint32_t)halfDuplexUartMsg;
    NRF_PWM0-&amp;gt;SEQ[1].ENDDELAY = 0;
    NRF_PWM0-&amp;gt;SEQ[1].REFRESH = 0;
    NRF_PWM0-&amp;gt;SHORTS = NRF_PWM_SHORT_LOOPSDONE_STOP_MASK;
    NRF_PWM0-&amp;gt;ENABLE = 1;
    // Stop after burst
    NRF_PWM0-&amp;gt;SHORTS = NRF_PWM_SHORT_SEQEND0_STOP_MASK;
    NRF_PWM0-&amp;gt;TASKS_SEQSTART[0] = 1;
    while (1)
    {
        __WFE();
    }
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Second example provides an identical waveform on the &amp;#39;scope, which is actually what you are looking for. It addresses a number of issues in the code you posted (I tested this code also, same 2-byte packet):&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;// PWM Half-Duplex UART
// ====================
#include &amp;quot;nrf_pwm.h&amp;quot;

#define LL_BAUDRATE      1200
#define F_CLK        16000000              // nRF52832/nRF52840 fixed at 16MHz
#define F_PRESCALER  (PWM_PRESCALER_PRESCALER_DIV_1)  // Divide by 1, 16MHz clock
#define COUNTER_TOP  ((F_CLK+(LL_BAUDRATE/2)) / LL_BAUDRATE)
STATIC_ASSERT(COUNTER_TOP &amp;lt; 32768, &amp;quot;COUNTER_TOP value too large for 15-bit register&amp;quot;);
STATIC_ASSERT(COUNTER_TOP &amp;gt;= 3, &amp;quot;COUNTER_TOP value too small for correct operation&amp;quot;);
#define BIT_LOW               0           // Normal encoding
#define BIT_HIGH    (COUNTER_TOP)         // Normal encoding
#define PWM_NEG (PIN_FEATHER_D6)          // Low level outside transmission
#define PWM_POS (PIN_FEATHER_D9)          // High level outside transmission
#define STX_BYTE 0x02 // Example start character: STX (^B)
#define ETX_BYTE 0x03 // Example end character:   ETX (^C)

// Example STX byte in little-endian format
#define STX_BIT_0 (((STX_BYTE&amp;gt;&amp;gt;0) &amp;amp; 0x01) ? BIT_HIGH : BIT_LOW)
#define STX_BIT_1 (((STX_BYTE&amp;gt;&amp;gt;1) &amp;amp; 0x01) ? BIT_HIGH : BIT_LOW)
#define STX_BIT_2 (((STX_BYTE&amp;gt;&amp;gt;2) &amp;amp; 0x01) ? BIT_HIGH : BIT_LOW)
#define STX_BIT_3 (((STX_BYTE&amp;gt;&amp;gt;3) &amp;amp; 0x01) ? BIT_HIGH : BIT_LOW)
#define STX_BIT_4 (((STX_BYTE&amp;gt;&amp;gt;4) &amp;amp; 0x01) ? BIT_HIGH : BIT_LOW)
#define STX_BIT_5 (((STX_BYTE&amp;gt;&amp;gt;5) &amp;amp; 0x01) ? BIT_HIGH : BIT_LOW)
#define STX_BIT_6 (((STX_BYTE&amp;gt;&amp;gt;6) &amp;amp; 0x01) ? BIT_HIGH : BIT_LOW)
#define STX_BIT_7 (((STX_BYTE&amp;gt;&amp;gt;7) &amp;amp; 0x01) ? BIT_HIGH : BIT_LOW)
// Example ETX byte in little-endian format
#define ETX_BIT_0 (((ETX_BYTE&amp;gt;&amp;gt;0) &amp;amp; 0x01) ? BIT_HIGH : BIT_LOW)
#define ETX_BIT_1 (((ETX_BYTE&amp;gt;&amp;gt;1) &amp;amp; 0x01) ? BIT_HIGH : BIT_LOW)
#define ETX_BIT_2 (((ETX_BYTE&amp;gt;&amp;gt;2) &amp;amp; 0x01) ? BIT_HIGH : BIT_LOW)
#define ETX_BIT_3 (((ETX_BYTE&amp;gt;&amp;gt;3) &amp;amp; 0x01) ? BIT_HIGH : BIT_LOW)
#define ETX_BIT_4 (((ETX_BYTE&amp;gt;&amp;gt;4) &amp;amp; 0x01) ? BIT_HIGH : BIT_LOW)
#define ETX_BIT_5 (((ETX_BYTE&amp;gt;&amp;gt;5) &amp;amp; 0x01) ? BIT_HIGH : BIT_LOW)
#define ETX_BIT_6 (((ETX_BYTE&amp;gt;&amp;gt;6) &amp;amp; 0x01) ? BIT_HIGH : BIT_LOW)
#define ETX_BIT_7 (((ETX_BYTE&amp;gt;&amp;gt;7) &amp;amp; 0x01) ? BIT_HIGH : BIT_LOW)

// Example using grouped, note uses pin channels 0 and 2 not 0 and 1
nrf_pwm_values_grouped_t halfDuplexUartMsg[] = {
  //   Index   Normal pin 0        Inverted pin 2
  //   =====   =================== ==============
  { /* 0:0  */ 0x8000|(BIT_LOW),   (BIT_LOW),  }, // Start bit
  { /* 0:1  */ 0x8000|(STX_BIT_0), (STX_BIT_0) },
  { /* 0:2  */ 0x8000|(STX_BIT_1), (STX_BIT_1) },
  { /* 0:3  */ 0x8000|(STX_BIT_2), (STX_BIT_2) },
  { /* 0:4  */ 0x8000|(STX_BIT_3), (STX_BIT_3) },
  { /* 0:5  */ 0x8000|(STX_BIT_4), (STX_BIT_4) },
  { /* 0:6  */ 0x8000|(STX_BIT_5), (STX_BIT_5) },
  { /* 0:7  */ 0x8000|(STX_BIT_6), (STX_BIT_6) },
  { /* 0:8  */ 0x8000|(STX_BIT_7), (STX_BIT_7) },
  { /* 0:9  */ 0x8000|(BIT_HIGH),  (BIT_HIGH), }, // Stop bit 1

  { /* 1:0  */ 0x8000|(BIT_LOW),   (BIT_LOW),  }, // Start bit
  { /* 1:1  */ 0x8000|(ETX_BIT_0), (ETX_BIT_0) },
  { /* 1:2  */ 0x8000|(ETX_BIT_1), (ETX_BIT_1) },
  { /* 1:3  */ 0x8000|(ETX_BIT_2), (ETX_BIT_2) },
  { /* 1:4  */ 0x8000|(ETX_BIT_3), (ETX_BIT_3) },
  { /* 1:5  */ 0x8000|(ETX_BIT_4), (ETX_BIT_4) },
  { /* 1:6  */ 0x8000|(ETX_BIT_5), (ETX_BIT_5) },
  { /* 1:7  */ 0x8000|(ETX_BIT_6), (ETX_BIT_6) },
  { /* 1:8  */ 0x8000|(ETX_BIT_7), (ETX_BIT_7) },
  { /* 1:9  */ 0x8000|(BIT_HIGH),  (BIT_HIGH), }, // Stop bit 1
};
#define NUM_PWM_ITERATIONS  ( sizeof(halfDuplexUartMsg)/sizeof(halfDuplexUartMsg[0].group_0) )
#define NUM_PWM_TABLE_LINES ( sizeof(halfDuplexUartMsg)/sizeof(halfDuplexUartMsg[0]) )
STATIC_ASSERT(sizeof(nrf_pwm_values_grouped_t) == sizeof(halfDuplexUartMsg[0]), &amp;quot;halfDuplexUart line size&amp;quot;);
STATIC_ASSERT((NUM_PWM_ITERATIONS) == 40, &amp;quot;iterations&amp;quot;);

void TestPWM_Uart(void)
{
    // Start accurate HFCLK (XOSC)
    NRF_CLOCK-&amp;gt;TASKS_HFCLKSTART = 1;
    while (NRF_CLOCK-&amp;gt;EVENTS_HFCLKSTARTED == 0)
        ;
    NRF_CLOCK-&amp;gt;EVENTS_HFCLKSTARTED = 0;
    static nrfx_pwm_t m_pwm0 = NRFX_PWM_INSTANCE(0);

    uint32_t err_code;
    // Declare a configuration structure and use a macro to instantiate it with default parameters.
    nrfx_pwm_config_t pwm_config = NRFX_PWM_DEFAULT_CONFIG;
    //    .irq_priority = NRFX_PWM_DEFAULT_CONFIG_IRQ_PRIORITY,                  \
    //    .base_clock   = (nrf_pwm_clk_t)NRFX_PWM_DEFAULT_CONFIG_BASE_CLOCK,     \
    //    .count_mode   = (nrf_pwm_mode_t)NRFX_PWM_DEFAULT_CONFIG_COUNT_MODE,    \
    //    .top_value    = NRFX_PWM_DEFAULT_CONFIG_TOP_VALUE,                     \
    //    .load_mode    = (nrf_pwm_dec_load_t)NRFX_PWM_DEFAULT_CONFIG_LOAD_MODE, \
    //    .step_mode    = (nrf_pwm_dec_step_t)NRFX_PWM_DEFAULT_CONFIG_STEP_MODE
   static nrf_pwm_sequence_t pwm_sequence;

    // Override some of the default parameters:
    pwm_config.output_pins[0] = PWM_NEG | NRFX_PWM_PIN_INVERTED;
    pwm_config.output_pins[1] = NRFX_PWM_PIN_NOT_USED;
    pwm_config.output_pins[2] = PWM_POS;
    pwm_config.output_pins[3] = NRFX_PWM_PIN_NOT_USED;
    pwm_config.load_mode      = NRF_PWM_LOAD_GROUPED;   // 1 == 1st half word (16-bit) used in channels 0 and 1; 2nd word in channels 2 and 3
    pwm_config.base_clock     = F_PRESCALER;            // 0 == divide by 1 for 16MHz clock
    pwm_config.step_mode      = NRFX_PWM_DEFAULT_CONFIG_STEP_MODE; // 0 == Count Up
    pwm_config.top_value      = COUNTER_TOP;

    // Pass config structure into driver init() function 
    err_code = nrfx_pwm_init(&amp;amp;m_pwm0, &amp;amp;pwm_config, NULL);
    APP_ERROR_CHECK(err_code);
    pwm_sequence.values.p_grouped = (uint32_t)halfDuplexUartMsg;
    pwm_sequence.length           = NUM_PWM_ITERATIONS;
    pwm_sequence.repeats          = 0;
    nrfx_pwm_simple_playback(&amp;amp;m_pwm0, &amp;amp;pwm_sequence, 1, NRFX_PWM_FLAG_STOP);
    while (1)
    {
        __WFE();
    }
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Note the second example relies on nrfx to set the initial pins but to get the default &amp;#39;parking&amp;#39; high level before any transmission needs to take place usually the same port init code would be run at power-up (maybe not an issue ..)&lt;/p&gt;
&lt;p&gt;Edit: Max baud rate is 16MHz/3, or 5.33MHz, using the minimum allowed value of TOPCOUNT of 3; pretty nice. Finally worked out that by shrinking screen with &lt;em&gt;ctrl-minus&lt;/em&gt; a refresh then shows all the &lt;em&gt;Reply&lt;/em&gt; buttons&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: PWM Sequence from HAL to NRFX</title><link>https://devzone.nordicsemi.com/thread/386330?ContentTypeID=1</link><pubDate>Thu, 15 Sep 2022 09:02:16 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:26857cc5-5b51-4134-a376-2c947cf2a940</guid><dc:creator>falcuun</dc:creator><description>&lt;p&gt;Here&amp;#39;s the current code in NRFX:&amp;nbsp;&lt;pre class="ui-code" data-mode="c_cpp"&gt;void pwm_transmit_evt_handler(nrfx_pwm_evt_type_t event_type, void *p_context)
{
    switch (event_type)
    {
    case NRFX_PWM_EVT_FINISHED:
        LOG_INF(&amp;quot;PWM EVENT! NRFX_PWM_EVT_FINISHED&amp;quot;);
        break;
    case NRFX_PWM_EVT_END_SEQ0:
        LOG_INF(&amp;quot;PWM EVENT! NRFX_PWM_EVT_END_SEQ0&amp;quot;);
        break;
    case NRFX_PWM_EVT_END_SEQ1:
        LOG_INF(&amp;quot;PWM EVENT! NRFX_PWM_EVT_END_SEQ1&amp;quot;);
        break;
    case NRFX_PWM_EVT_STOPPED:
        LOG_INF(&amp;quot;PWM EVENT! NRFX_PWM_EVT_STOPPED&amp;quot;);
        break;
    }
}

void pwm_tx_init()
{
    uint16_t CounterTopRegister;
    CounterTopRegister = F_CLK / F_PWM;
    nrfx_pwm_config_t pwm_config;

    pwm_config.output_pins[0] = PIN_POS;
    pwm_config.output_pins[1] = PIN_NEG;
    pwm_config.output_pins[2] = NRFX_PWM_PIN_NOT_USED;
    pwm_config.output_pins[3] = NRFX_PWM_PIN_NOT_USED;

    pwm_config.base_clock = NRF_PWM_CLK_16MHz ;
    pwm_config.count_mode = NRF_PWM_MODE_UP;
    pwm_config.top_value = CounterTopRegister;
    pwm_config.load_mode = NRF_PWM_LOAD_INDIVIDUAL;
    pwm_config.step_mode = NRF_PWM_STEP_AUTO;
    pwm_config.skip_gpio_cfg = false;
    pwm_config.skip_psel_cfg = false;
    pwm_config.irq_priority = 5;

    nrfx_pwm_init(&amp;amp;pwm, &amp;amp;pwm_config, pwm_transmit_evt_handler, 0);
    IRQ_DIRECT_CONNECT(COMP_LPCOMP_IRQn, 5, nrfx_pwm_2_irq_handler, 0);
}

void set_sequence(uint8_t txVal)
{
    uint16_t P_PWM_HIGH;
    uint16_t P_PWM_LOW;
    uint16_t N_PWM_HIGH;
    uint16_t N_PWM_LOW;
    P_PWM_HIGH = (F_CLK / F_PWM);
    P_PWM_LOW = (int)(0.5 * (F_CLK / F_PWM));
    N_PWM_HIGH = P_PWM_HIGH + 0x8000;
    N_PWM_LOW = P_PWM_LOW + 0x8000;

    int i;

    // Generate the Startbit (LOW)
    initialSequence[0] = P_PWM_LOW;
    initialSequence[1] = N_PWM_LOW;
    initialSequence[2] = 0;
    initialSequence[3] = 0;
    //  LOG_INF(&amp;quot;S&amp;quot;);

    // Generate the 8 databits
    for (i = 1; i &amp;lt; 9; i++)
    {
        if (txVal &amp;amp; 1)
        {
            // Bit is HIGH
            //  LOG_INF(&amp;quot;1&amp;quot;);
            initialSequence[4 * i + 0] = P_PWM_HIGH;
            initialSequence[4 * i + 1] = N_PWM_HIGH;
        }
        else
        {
            // Bit is LOW
            //  LOG_INF(&amp;quot;0&amp;quot;);
            initialSequence[4 * i + 0] = P_PWM_LOW;
            initialSequence[4 * i + 1] = N_PWM_LOW;
        }
        initialSequence[4 * i + 2] = 0;
        initialSequence[4 * i + 3] = 0;
        txVal = txVal &amp;gt;&amp;gt; 1;
    }

    // Generate the Stopbit (HIGH)
    initialSequence[36] = P_PWM_HIGH;
    initialSequence[37] = N_PWM_HIGH;
    initialSequence[38] = 0;
    initialSequence[39] = 0;
    initialSequence[40] = P_PWM_HIGH;
    initialSequence[41] = N_PWM_HIGH;
    initialSequence[42] = 0;
    initialSequence[43] = 0;
}


nrf_pwm_sequence_t pwm_sequence;

void make_sequence()
{
    pwm_sequence.values.p_raw = initialSequence;
    pwm_sequence.length = 44;
    pwm_sequence.repeats = 18;
    pwm_sequence.end_delay = 0;

    nrfx_pwm_simple_playback(&amp;amp;pwm, &amp;amp;pwm_sequence, 0, 0);
}

void pwm_tx_transmit(uint8_t msg)
{
    set_sequence(msg);
    make_sequence();
}

int TxMessage(uint8_t *msg, uint8_t len)
{
    nrfx_lpcomp_disable();

    NRFX_IRQ_DISABLE(SAADC_IRQn);
    for (int i = 0; i &amp;lt; len; i++)
    {
        pwm_tx_transmit(msg[i]);
    }
    lpcomp_event_count = 0;
    is_carrier_found = 0;
    NRFX_IRQ_ENABLE(COMP_LPCOMP_IRQn);
    nrfx_lpcomp_enable();
    return 0;
}


// Elsewhere in Code:
void Init()
{
    pwm_tx_init();
    initLpComp();
}

request_data()
{
    uint8_t STX = 0x82;
    uint8_t signal_id = 0x64 | 0x80;
    uint8_t data_byte_0 = 0x03 | 0x80;

    uint8_t checksum = (signal_id) + (data_byte_0);
    checksum &amp;amp;= 0x7F;

    uint8_t message[4] = {STX, signal_id, data_byte_0, checksum};
    TxMessage(message, 4);
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;After trying and implementing your method of constructing the message, the result was no different. Following your advice on pins being set/cleared. I&amp;#39;ve specifically set the pin, but no cigar.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Here is the Screengrab of the registers. On the left side is the current code (NOT WORKING)&amp;nbsp;&lt;br /&gt;On the right side is the Bare-metal/HAL Code (WORKING).&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img style="max-height:155px;max-width:558px;" alt=" " height="155" src="https://devzone.nordicsemi.com/resized-image/__size/1116x310/__key/communityserver-discussions-components-files/4/Screenshot-2022_2D00_09_2D00_15-105656.png" width="558" /&gt;&lt;/p&gt;
&lt;p&gt;One thing I&amp;#39;ve noticed, that keeps being obvious, is that no matter what I do&amp;nbsp; to the top_value, the countertop doesn&amp;#39;t change in any way. Likewise, the DECODER register keeps being missmatched, no matter which one I try. Also for some reason with the NRFX code there is value on PTR_1, CNT_1, REFRESH_1. Unlike the Bare Metal approach.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Here is the Scope screen grab of the Current NRFX approach. The bare metal approach still looks like in the image provided earlier.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img style="max-height:240px;max-width:320px;" alt=" " src="https://devzone.nordicsemi.com/resized-image/__size/640x480/__key/communityserver-discussions-components-files/4/pastedimage1663232466865v1.jpeg" /&gt;&lt;/p&gt;
&lt;p&gt;If you have any clue as to what is causing this issue, that&amp;#39;d be amazing.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;I have edited the code according to the bare-metal code trying to match as many registers as possible. But it does not seem to work for me in any approach.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;Thank you so much for taking your time to try and help me out!&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: PWM Sequence from HAL to NRFX</title><link>https://devzone.nordicsemi.com/thread/386239?ContentTypeID=1</link><pubDate>Wed, 14 Sep 2022 15:20:46 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:519fb7a2-a0a0-4891-947c-3b60ad9a7c75</guid><dc:creator>hmolesworth</dc:creator><description>&lt;p&gt;Not sure the api drivers correctly handle the pins, but looking at the &amp;#39;scope seems the pins aren&amp;#39;t configured so try adding this after the init:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;// Boost differential pwm driver pins to high drive
nrf_gpio_cfg(PIN_POS, NRF_GPIO_PIN_DIR_OUTPUT, NRF_GPIO_PIN_INPUT_DISCONNECT, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_H0H1, NRF_GPIO_PIN_NOSENSE);
nrf_gpio_cfg(PIN_NEG, NRF_GPIO_PIN_DIR_OUTPUT, NRF_GPIO_PIN_INPUT_DISCONNECT, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_H0H1, NRF_GPIO_PIN_NOSENSE);
&lt;/pre&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: PWM Sequence from HAL to NRFX</title><link>https://devzone.nordicsemi.com/thread/386236?ContentTypeID=1</link><pubDate>Wed, 14 Sep 2022 15:07:54 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:88c2a442-c647-4c26-8ad0-660a9166a165</guid><dc:creator>hmolesworth</dc:creator><description>&lt;p&gt;1, not 0, for the repeats - sorry my typo. Maybe post the current code you are using, the earlier code is a little hard to follow with some unused code. Also include the main sequence if possible. I sometimes use the same api without any issues, though often use the bare metal drivers. A screen shot of the PWM registers might help in debug to confirm actual values loaded are not being obfuscated by the library code.&lt;/p&gt;
&lt;p&gt;REFRESH&amp;nbsp;is a way of using more clock cycles per PWM value step, so typically set to 0.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: PWM Sequence from HAL to NRFX</title><link>https://devzone.nordicsemi.com/thread/386232?ContentTypeID=1</link><pubDate>Wed, 14 Sep 2022 14:54:25 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:5b665bff-0f12-4655-82ce-96820840006c</guid><dc:creator>falcuun</dc:creator><description>&lt;p&gt;Still no Cigar.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;I thought that LOOPS are actually the &amp;quot;playback Count&amp;quot; in the arguments of simple_playback.&amp;nbsp;&lt;br /&gt;And the Repeats was the same as SEQ[n].REFRESH?&amp;nbsp;&lt;/p&gt;
&lt;p&gt;My assumption is that something in the API is not properly configured, or I am not doign something in the right order.&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: PWM Sequence from HAL to NRFX</title><link>https://devzone.nordicsemi.com/thread/386227?ContentTypeID=1</link><pubDate>Wed, 14 Sep 2022 14:36:57 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:282887b8-ed91-474a-8025-56ccc29e308f</guid><dc:creator>hmolesworth</dc:creator><description>&lt;p&gt;Oh, maybe try changing the LOOPS (disguised as repeats):&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;    uint32_t repeats = (F_PWM / LL_BAUDRATE) - 1;
    uint32_t repeats = 0;&lt;/pre&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: PWM Sequence from HAL to NRFX</title><link>https://devzone.nordicsemi.com/thread/386222?ContentTypeID=1</link><pubDate>Wed, 14 Sep 2022 14:24:31 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:1f902ea6-08a9-440f-a463-ed4f123da34e</guid><dc:creator>falcuun</dc:creator><description>&lt;p&gt;Replies seem to have issues for some reason.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;But regarding the issue, I think you misunderstood me, I have issue actually setting up the PWM ( I Think).&lt;/p&gt;
&lt;p&gt;I call &amp;quot;nrfx_pwm_simple_playback(&amp;amp;pwm, &amp;amp;pwm_sequence, 1,&amp;nbsp;NRFX_PWM_FLAG_STOP);&amp;quot;&lt;br /&gt;And this is what drives my sequence. I no longer want to have direct registry access, unless absolutely needed. I wonder what, from the provided code, is wrong with the way I&amp;#39;m using NRFX API. And what do I need to modify in the code for it to execute the same function that my HAL code does.&amp;nbsp;&lt;br /&gt;The best I can achieve with NRFX is making PWM output a loop of repeating peak values at a defined duty cycle.&amp;nbsp;&lt;br /&gt;And it keeps being stuck on 1khz, where the HAL code works on 32Khz.&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: PWM Sequence from HAL to NRFX</title><link>https://devzone.nordicsemi.com/thread/386216?ContentTypeID=1</link><pubDate>Wed, 14 Sep 2022 14:11:15 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:d3a3a9ef-e120-4681-a523-b869a47c5f96</guid><dc:creator>hmolesworth</dc:creator><description>&lt;p&gt;I can&amp;#39;t get this reply to line up, but anyway I see your issue. The PWM continues to play the last (maybe only)&amp;nbsp; cycle indefinitely until you issue a STOP TASK and wait for the STOPPED Event. This can be automated by setting SHORTS:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;   NRF_PWM_Type * const pNRF_PWM = NRF_PWM2;
   // PWM_SHORTS_SEQEND0_STOP_Msk         Shortcut between SEQEND[0] event and STOP task.
   // PWM_SHORTS_SEQEND1_STOP_Msk         Shortcut between SEQEND[1] event and STOP task.
   // PWM_SHORTS_LOOPSDONE_SEQSTART0_Msk  Shortcut between LOOPSDONE event and SEQSTART[0] task.
   // PWM_SHORTS_LOOPSDONE_SEQSTART1_Msk  Shortcut between LOOPSDONE event and SEQSTART[1] task.
   // PWM_SHORTS_LOOPSDONE_STOP_Msk        Shortcut between LOOPSDONE event and STOP task.
   pNRF_PWM-&amp;gt;SHORTS = NRF_PWM_SHORT_LOOPSDONE_STOP_MASK;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;&amp;quot;After the last value in the sequence has been loaded&amp;nbsp;and started executing, a SEQEND[n] event is generated. The PWM generation will then continue with the last loaded value.&amp;quot;&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: PWM Sequence from HAL to NRFX</title><link>https://devzone.nordicsemi.com/thread/386112?ContentTypeID=1</link><pubDate>Wed, 14 Sep 2022 09:04:46 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:52b97c64-ce81-4919-9018-53e3b950bb39</guid><dc:creator>falcuun</dc:creator><description>&lt;p&gt;Hi, thank you for the response!&lt;br /&gt;Unfortunaetly, your assumption is correct. I cannot just use the UART.&amp;nbsp;&lt;br /&gt;You may notice that in my code the table is being populated in a loop, because it allows for a more dynamic way of constructing a message. (Or it did in this case). I am unsure it&amp;#39;s the best way of doing it, but it&amp;#39;s what worked at the time.&lt;/p&gt;
&lt;p&gt;There is an extra limitation to the system, and that&amp;#39;s the receiving end, which has FW that cannot be changed at this time, so Manchester Encoding is also not an option. The same limitation prevents burst sending.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;I appreciate the way you&amp;#39;ve constructed the message, but it still doesn&amp;#39;t answer the question of: How do I actually send it, so that it mimics the behavior of the HAL version? With the current way my PWM instance is set up, even with your message, I still get the same gitter-y output.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;If you have any comments on what is wrong with the current set up of the PWM sequence, or the PWM config, that&amp;#39;d be great!&amp;nbsp;&lt;br /&gt;Thus far, I&amp;#39;ve tried both the wave form and the groupped values. Each mode provides the same output signal, and sadly it&amp;#39;s not the correct one.&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: PWM Sequence from HAL to NRFX</title><link>https://devzone.nordicsemi.com/thread/386047?ContentTypeID=1</link><pubDate>Tue, 13 Sep 2022 16:44:40 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:b0a4ddf1-fbdb-4725-a5e6-6975da9af69d</guid><dc:creator>hmolesworth</dc:creator><description>&lt;p&gt;Assuming you can&amp;#39;t just use the nRF52840 UART, typically using the PWM would involve constructing the complete message sequence in a table then just transmit the table as a single operation. Here is a pedantic example &amp;lt;STX&amp;gt;&amp;lt;ETX&amp;gt;, using waveform mode although since all the countertop values are the same wavefom mode is not strictly necessary but allows controlling the hardware direction with the 3rd output pin (DE /RE)). Grouped Mode could be used to save space, but Waveform is the example I show here. I personally would encode all possible 256 bytes in 256 separate tables in Flash and simply copy the character sequences to RAM to construct a message, then send the entire message in one PWM burst, more efficient long-term in terms of power consumption. Note for greatest accuracy (unless you switch to Manchester encoding, easily done) the HFCLK has to stay active for the duration of transmission. With Manchester encoding that is not required, leading to power savings.&amp;nbsp;&lt;a href="https://en.wikipedia.org/wiki/Manchester_code"&gt;Manchester_code&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;#define LL_BAUDRATE      1200
#define F_PWM           32400
#define F_CLK        16000000
#define COUNTER_TOP  ((F_CLK+(F_PWM/2)) / F_PWM) // F_CLK = 16000000
#define BIT_LOW            0              // Normal encoding
#define BIT_HIGH   (COUNTER_TOP)          // Normal encoding
//#define BIT_LOW    ((2*COUNTER_TOP)/3)  // Manchester encoding 2/3 bit
//#define BIT_HIGH   (COUNTER_TOP/3)      // Manchester encoding 1/3 bit
#define STX_BYTE 0x02 // Example start character: STX (^B)
#define ETX_BYTE 0x03 // Example start character: ETX (^C)

// Example STX byte in little-endian format
#define STX_BIT_0 (((STX_BYTE&amp;gt;&amp;gt;0) &amp;amp; 0x01) ? BIT_HIGH : BIT_LOW)
#define STX_BIT_1 (((STX_BYTE&amp;gt;&amp;gt;1) &amp;amp; 0x01) ? BIT_HIGH : BIT_LOW)
#define STX_BIT_2 (((STX_BYTE&amp;gt;&amp;gt;2) &amp;amp; 0x01) ? BIT_HIGH : BIT_LOW)
#define STX_BIT_3 (((STX_BYTE&amp;gt;&amp;gt;3) &amp;amp; 0x01) ? BIT_HIGH : BIT_LOW)
#define STX_BIT_4 (((STX_BYTE&amp;gt;&amp;gt;4) &amp;amp; 0x01) ? BIT_HIGH : BIT_LOW)
#define STX_BIT_5 (((STX_BYTE&amp;gt;&amp;gt;5) &amp;amp; 0x01) ? BIT_HIGH : BIT_LOW)
#define STX_BIT_6 (((STX_BYTE&amp;gt;&amp;gt;6) &amp;amp; 0x01) ? BIT_HIGH : BIT_LOW)
#define STX_BIT_7 (((STX_BYTE&amp;gt;&amp;gt;7) &amp;amp; 0x01) ? BIT_HIGH : BIT_LOW)
// Example ETX byte in little-endian format
#define ETX_BIT_0 (((ETX_BYTE&amp;gt;&amp;gt;0) &amp;amp; 0x01) ? BIT_HIGH : BIT_LOW)
#define ETX_BIT_1 (((ETX_BYTE&amp;gt;&amp;gt;1) &amp;amp; 0x01) ? BIT_HIGH : BIT_LOW)
#define ETX_BIT_2 (((ETX_BYTE&amp;gt;&amp;gt;2) &amp;amp; 0x01) ? BIT_HIGH : BIT_LOW)
#define ETX_BIT_3 (((ETX_BYTE&amp;gt;&amp;gt;3) &amp;amp; 0x01) ? BIT_HIGH : BIT_LOW)
#define ETX_BIT_4 (((ETX_BYTE&amp;gt;&amp;gt;4) &amp;amp; 0x01) ? BIT_HIGH : BIT_LOW)
#define ETX_BIT_5 (((ETX_BYTE&amp;gt;&amp;gt;5) &amp;amp; 0x01) ? BIT_HIGH : BIT_LOW)
#define ETX_BIT_6 (((ETX_BYTE&amp;gt;&amp;gt;6) &amp;amp; 0x01) ? BIT_HIGH : BIT_LOW)
#define ETX_BIT_7 (((ETX_BYTE&amp;gt;&amp;gt;7) &amp;amp; 0x01) ? BIT_HIGH : BIT_LOW)

nrf_pwm_values_wave_form_t halfDuplexUartMsg[] = {
  //   Index   Normal pin          Inverted     (DE/RE)  Top Value
  //   =====   =================== ==========   =======  =========
//{ /* -:-  */ 0x8000|(BIT_HIGH),  (BIT_HIGH),  BIT_HIGH, COUNTER_TOP }, // RS485 start-of-packet pre-drive (optional, 1st byte only)
  { /* 0:0  */ 0x8000|(BIT_LOW),   (BIT_LOW),   BIT_HIGH, COUNTER_TOP }, // Start bit
  { /* 0:1  */ 0x8000|(STX_BIT_0), (STX_BIT_0), BIT_HIGH, COUNTER_TOP },
  { /* 0:2  */ 0x8000|(STX_BIT_1), (STX_BIT_1), BIT_HIGH, COUNTER_TOP },
  { /* 0:3  */ 0x8000|(STX_BIT_2), (STX_BIT_2), BIT_HIGH, COUNTER_TOP },
  { /* 0:4  */ 0x8000|(STX_BIT_3), (STX_BIT_3), BIT_HIGH, COUNTER_TOP },
  { /* 0:5  */ 0x8000|(STX_BIT_4), (STX_BIT_4), BIT_HIGH, COUNTER_TOP },
  { /* 0:6  */ 0x8000|(STX_BIT_5), (STX_BIT_5), BIT_HIGH, COUNTER_TOP },
  { /* 0:7  */ 0x8000|(STX_BIT_6), (STX_BIT_6), BIT_HIGH, COUNTER_TOP },
  { /* 0:8  */ 0x8000|(STX_BIT_7), (STX_BIT_7), BIT_HIGH, COUNTER_TOP },
  { /* 0:9  */ 0x8000|(BIT_HIGH),  (BIT_HIGH),  BIT_HIGH, COUNTER_TOP }, // Stop bit 1

  { /* 1:0  */ 0x8000|(BIT_LOW),   (BIT_LOW),   BIT_HIGH, COUNTER_TOP }, // Start bit
  { /* 1:1  */ 0x8000|(ETX_BIT_0), (ETX_BIT_0), BIT_HIGH, COUNTER_TOP },
  { /* 1:2  */ 0x8000|(ETX_BIT_1), (ETX_BIT_1), BIT_HIGH, COUNTER_TOP },
  { /* 1:3  */ 0x8000|(ETX_BIT_2), (ETX_BIT_2), BIT_HIGH, COUNTER_TOP },
  { /* 1:4  */ 0x8000|(ETX_BIT_3), (ETX_BIT_3), BIT_HIGH, COUNTER_TOP },
  { /* 1:5  */ 0x8000|(ETX_BIT_4), (ETX_BIT_4), BIT_HIGH, COUNTER_TOP },
  { /* 1:6  */ 0x8000|(ETX_BIT_5), (ETX_BIT_5), BIT_HIGH, COUNTER_TOP },
  { /* 1:7  */ 0x8000|(ETX_BIT_6), (ETX_BIT_6), BIT_HIGH, COUNTER_TOP },
  { /* 1:8  */ 0x8000|(ETX_BIT_7), (ETX_BIT_7), BIT_HIGH, COUNTER_TOP },
  { /* 1:9  */ 0x8000|(BIT_HIGH),  (BIT_HIGH),  BIT_HIGH, COUNTER_TOP }, // Stop bit 1

  { /* 1:10 */ 0x8000|(BIT_HIGH),  (BIT_HIGH),  BIT_LOW,  COUNTER_TOP }, // Stop bit 2 (optional, drive RS483 DE/RE lo here)
};
#define NUM_PWM_ITERATIONS  ( sizeof(halfDuplexUartMsg)/sizeof(halfDuplexUartMsg[0].channel_0) )
#define NUM_PWM_TABLE_LINES ( sizeof(halfDuplexUartMsg)/sizeof(halfDuplexUartMsg[0]) )
STATIC_ASSERT(sizeof(nrf_pwm_values_wave_form_t) == sizeof(halfDuplexUartMsg[0]), &amp;quot;halfDuplexUartMsg line size&amp;quot;);

//  NUM_PWM_ITERATIONS WaveLength (.CNT) is 15-bit Amount of values (duty cycles) in this sequence&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;If this is an RS485 application such as Modbus or similar it is helpful to embed the RS485 control pin in the table as above then timing of enable/disable of the driver is deterministic.&lt;/p&gt;
&lt;p&gt;Edit: Adding the Grouped Mode table:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;// Example using grouped, notes uses pin channels 0 and 2
nrf_pwm_values_grouped_t halfDuplexUartMsg[] = {
  //   Index   Normal pin 0        Inverted pin 2   
  //   =====   =================== ============== 
  { /* 0:0  */ 0x8000|(BIT_LOW),   (BIT_LOW),  }, // Start bit
  { /* 0:1  */ 0x8000|(STX_BIT_0), (STX_BIT_0) },
  { /* 0:2  */ 0x8000|(STX_BIT_1), (STX_BIT_1) },
  { /* 0:3  */ 0x8000|(STX_BIT_2), (STX_BIT_2) },
  { /* 0:4  */ 0x8000|(STX_BIT_3), (STX_BIT_3) },
  { /* 0:5  */ 0x8000|(STX_BIT_4), (STX_BIT_4) },
  { /* 0:6  */ 0x8000|(STX_BIT_5), (STX_BIT_5) },
  { /* 0:7  */ 0x8000|(STX_BIT_6), (STX_BIT_6) },
  { /* 0:8  */ 0x8000|(STX_BIT_7), (STX_BIT_7) },
  { /* 0:9  */ 0x8000|(BIT_HIGH),  (BIT_HIGH), }, // Stop bit 1

  { /* 1:0  */ 0x8000|(BIT_LOW),   (BIT_LOW),  }, // Start bit
  { /* 1:1  */ 0x8000|(ETX_BIT_0), (ETX_BIT_0) },
  { /* 1:2  */ 0x8000|(ETX_BIT_1), (ETX_BIT_1) },
  { /* 1:3  */ 0x8000|(ETX_BIT_2), (ETX_BIT_2) },
  { /* 1:4  */ 0x8000|(ETX_BIT_3), (ETX_BIT_3) },
  { /* 1:5  */ 0x8000|(ETX_BIT_4), (ETX_BIT_4) },
  { /* 1:6  */ 0x8000|(ETX_BIT_5), (ETX_BIT_5) },
  { /* 1:7  */ 0x8000|(ETX_BIT_6), (ETX_BIT_6) },
  { /* 1:8  */ 0x8000|(ETX_BIT_7), (ETX_BIT_7) },
  { /* 1:9  */ 0x8000|(BIT_HIGH),  (BIT_HIGH), }, // Stop bit 1
};
#define NUM_PWM_ITERATIONS  ( sizeof(halfDuplexUartMsg)/sizeof(halfDuplexUartMsg[0].channel_0) )
#define NUM_PWM_TABLE_LINES ( sizeof(halfDuplexUartMsg)/sizeof(halfDuplexUartMsg[0]) )
STATIC_ASSERT(sizeof(nrf_pwm_values_grouped_t) == sizeof(halfDuplexUartMsg[0]), &amp;quot;halfDuplexUart line size&amp;quot;);
&lt;/pre&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: PWM Sequence from HAL to NRFX</title><link>https://devzone.nordicsemi.com/thread/385953?ContentTypeID=1</link><pubDate>Tue, 13 Sep 2022 12:10:46 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:e3e65bcc-da52-4f90-91df-f398f06e6e56</guid><dc:creator>falcuun</dc:creator><description>&lt;p&gt;&lt;img height="149" src="https://devzone.nordicsemi.com/resized-image/__size/440x298/__key/communityserver-discussions-components-files/4/e1499601_2D00_8d53_2D00_4e51_2D00_85b4_2D00_47a6e0bc4831.jpg" width="220" alt=" " /&gt;&amp;nbsp; I feel I should add the way the signal looks as well with HAL(first picture) and&amp;nbsp;&lt;img style="max-height:152px;max-width:220px;" height="152" src="https://devzone.nordicsemi.com/resized-image/__size/440x304/__key/communityserver-discussions-components-files/4/615126fd_2D00_a07d_2D00_4302_2D00_b2c0_2D00_99c305ad43c4.jpg" width="220" alt=" " /&gt;&amp;nbsp;NRFX (Second picture)&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: PWM Sequence from HAL to NRFX</title><link>https://devzone.nordicsemi.com/thread/385938?ContentTypeID=1</link><pubDate>Tue, 13 Sep 2022 11:34:32 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:b425f472-149b-4251-afb7-53e110fb0f01</guid><dc:creator>falcuun</dc:creator><description>&lt;p&gt;I should add the current (latest) attempt at implementing, so maybe that could be corrected in the right way:&lt;br /&gt;&lt;pre class="ui-code" data-mode="text"&gt;nrfx_pwm_t pwm = NRFX_PWM_INSTANCE(2);
static nrf_pwm_values_individual_t pwm_values[2];
nrf_pwm_sequence_t pwm_sequence;

void pwm_tx_init()
{
    nrfx_pwm_config_t pwm_config;

    pwm_config.output_pins[0] = PIN_POS;
    pwm_config.output_pins[1] = PIN_NEG;
    pwm_config.output_pins[2] = NRFX_PWM_PIN_NOT_USED;
    pwm_config.output_pins[3] = NRFX_PWM_PIN_NOT_USED;

    pwm_config.base_clock = NRF_PWM_CLK_16MHz;
    pwm_config.count_mode = NRF_PWM_MODE_UP;
    pwm_config.top_value = (F_CLK / F_PWM);
    pwm_config.load_mode = NRF_PWM_LOAD_WAVE_FORM;
    pwm_config.step_mode = NRF_PWM_STEP_AUTO;
    pwm_config.skip_gpio_cfg = false;
    pwm_config.skip_psel_cfg = false;
    pwm_config.irq_priority = 5;

    nrfx_pwm_init(&amp;amp;pwm, &amp;amp;pwm_config, pwm_transmit_evt_handler, 0);
    IRQ_DIRECT_CONNECT(COMP_LPCOMP_IRQn, 5, nrfx_pwm_2_irq_handler, 0);
}


void pwm_tx_transmit(uint8_t *msg)
{
    set_sequence(0x80);
    nrf_pwm_values_t sequence_values;
    sequence_values.p_raw = initialSequence;
    nrf_pwm_sequence_t sequence1;
    sequence1.repeats = (F_PWM / LL_BAUDRATE) - 1;
    sequence1.length = 44;
    sequence1.end_delay = 0;
    sequence1.values = sequence_values;
   
}
void make_sequence(uint16_t duty_p_p, uint16_t duty_p_n, uint16_t duty_n_p, uint16_t duty_n_n)
{

    pwm_sequence.values.p_individual = pwm_values;
    pwm_sequence.length = NRF_PWM_VALUES_LENGTH(pwm_values);
    uint32_t repeats = (F_PWM / LL_BAUDRATE) - 1;
    pwm_sequence.repeats = repeats;
    pwm_sequence.end_delay = 0;

    pwm_values[0].channel_0 = duty_p_p;
    pwm_values[0].channel_1 = duty_p_n;

    pwm_values[1].channel_0 = duty_n_p;
    pwm_values[1].channel_1 = duty_n_n;
    nrfx_pwm_simple_playback(&amp;amp;pwm, &amp;amp;pwm_sequence, 1, NRFX_PWM_FLAG_STOP);
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;This is just a few itterations after, at this point I&amp;#39;m unsure if it has any relation to my initial sequence anyway.&amp;nbsp;&lt;br /&gt;The &amp;quot;initialSequence&amp;quot; array is filled in the same way as in the HAL implementation.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>