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

Reading WS2812b leftover data through I2S

Hello there,

I am currently trying to read the leftover WS2812b LED strip data which was sent using a single channel I2S. The data sent from the board (through I2S) looks like this:

with around 34 mV for high and around 2~6 mV on low. I decided not to send FFF, but 888 instead.

I am aiming to calculate the length of the LED strip. Each LED chip will read the first 24 bits of the data, cascade (discard) it, then pass it to the next one. Therefore, the strategy is to get the data after being cascaded by the last chip and calculate the length of it (which later will be divided by 24 to see how many are left).

The question is: How will I be able to read those data? I tried reading as usual (set a buffer for the i2s, start it, listen for it (delay), stop it, then check its buffer), but I got my buffer filled with all FFF instead. and a thing is that... when I tried to read anything from the pin, although I am not sending any data (the LED strip is not powered on, but connected to other's ground), there will be data, which should not happen. I assigned pin 22, 23, 24, 25 to be the i2s input pin (which will be assigned and unassigned when used or unused), and they are configured as follows:

nrf_gpio_cfg_sense_input(DIN1_PIN, NRF_GPIO_PIN_PULLDOWN, NRF_GPIO_PIN_SENSE_HIGH);

Thank you in advance.

  • Hi,

    Sorry about that. It was supposed to link back to one older post in this thread, but it is not important. The point is that I am 99% certain that you have hooked up something in a different way than what it seems, as PPI cannot behave as you describe. However, I am not able to understand how it is hooked up, as I do not get it to match. Perhaps you can try to do the same think using only a single DK (with external wires connecting different GPIO pins)? Then if you can reproduce in that setting, perhaps you can upload here so I can test on my side as well?

  • Oh, okay,

    here is my current setup. hope it's more visible now

  • Perfect. Now I guess we just need to look at two pins to see if there is any unexpected delay in PPI. Which input pin has the signal that controls which output pin via PPI? Can you upload a plot that shows those two signals and the code snippet that produces it? (Having all information in the same post would be beneficial, so that we know what there has not been any relevant changes in between possibly making the information inconsistent.)

  • Okay,

    Pin 13 has the signal that controls Pin 17 through PPI.

    Here's the plot:

    It may be observed better by opening this capture file inside this archive: Cap6.zip with its app, DSView.

    I believe that to set this up, we'll need to enable the event through setting it as a GPIOTE object. therefore,

    // Init the GPIOTE
    static void gpio_init(void) {
    	ret_code_t err_code;
    
    	err_code = nrf_drv_gpiote_init();
    	APP_ERROR_CHECK(err_code);
    
    	nrf_drv_gpiote_out_config_t out_config = GPIOTE_CONFIG_OUT_TASK_TOGGLE(false);
    
    	err_code = nrf_drv_gpiote_out_init(PIN_OUT, &out_config);
    	APP_ERROR_CHECK(err_code);
    
    	nrf_drv_gpiote_in_config_t in_config = GPIOTE_CONFIG_IN_SENSE_TOGGLE(true);
    	//nrf_drv_gpiote_in_config_t in_config = GPIOTE_CONFIG_IN_SENSE_HITOLO(true);
    	in_config.pull = NRF_GPIO_PIN_PULLUP;
    	
    	err_code = nrf_drv_gpiote_in_init(PIN_IN, &in_config, in_pin_handler);
    	//err_code = nrf_drv_gpiote_in_init(PIN_IN, &in_config, null_handler);
        APP_ERROR_CHECK(err_code);
    
        nrf_drv_gpiote_in_event_enable(PIN_IN, true);
    	nrf_drv_gpiote_out_task_enable(PIN_OUT);
    }
    
    // Init PPI
    static nrf_ppi_channel_t m_ppi_channel1;
    static void ppi_init(void) {
        uint32_t err_code = NRF_SUCCESS;
    	err_code = nrf_drv_ppi_init();
    	APP_ERROR_CHECK(err_code);
        // Configure 1st available PPI channel to stop TIMER0 counter on TIMER1 COMPARE[0] match,
        // which is every even number of seconds.
    	
        err_code = nrf_drv_ppi_channel_alloc(&m_ppi_channel1);
        APP_ERROR_CHECK(err_code);
    	//ppi_enable_channel(FC_PPI_CH, &NRF_GPIOTE->EVENTS_IN[FC_GPIOTE_CH], &FC_TIMER->TASKS_COUNT);
        err_code = nrf_drv_ppi_channel_assign(m_ppi_channel1, \
    										  nrf_drv_gpiote_in_event_addr_get(PIN_IN), \
    										  nrf_drv_gpiote_out_task_addr_get(PIN_OUT));
    										  
    	//err_code = nrf_drv_ppi_channel_assign(m_ppi_channel1, \
    										  nrf_drv_gpiote_in_event_addr_get(PIN_IN), \
    										  (uint32_t)&(NRF_TIMER1->TASKS_COUNT));
        APP_ERROR_CHECK(err_code);
    
        // Enable both configured PPI channels
        err_code = nrf_drv_ppi_channel_enable(m_ppi_channel1);
        APP_ERROR_CHECK(err_code);
    }

    and then called them on main:

    int main() {
        gpio_init();
        ppi_init();
    }

  • I am still having problems here. None of the signals relationship match what I would expect with the code snippet, though I have had to guess which of the three signals in the plot match the two signals in your code (PIN_IN and PIN_OUT). Can you upload the full source code use in this test, full plot, and full description in a single post so that all is of are from the same test and I know they make sense together? Also, if you can make the example code run on a DK without any external HW that would be great, as that would allow me to test on my side as well.

Related