This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Analyzing a Demodulated Signal using Interrupt, capture and PPI

Hi,

I need to capture a demodulated, manchester encoded signal (16 bits long). The data rate is about 50kHz (give or take). Currently, I am configuring a PPI with timer1 and the pin interrupt. When the interrupt routine is generated, I retrieve the value stored in the capture. I am aware that this will only work if I retrieve the stored value before the next interrupt is generated. The problem is that the signal is faster than the interrupt.

Here is my code:

// Interrupt Routine void in_pin_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action) { nrf_drv_gpiote_out_toggle(TP1); }

void init_sig_anal(void){ uint32_t err_code; uint32_t gpiote_evt_addr; uint32_t capture_task_addr;

// Initialise GPIO if not already done so
	if(!nrf_drv_gpiote_is_init()){
		err_code = nrf_drv_gpiote_init();
		APP_ERROR_CHECK(err_code);
	}
	
	// Set pin TP1 as output
	nrf_gpio_cfg_output(TP1);
	
	// Set interrupt to trigger on both rising and falling edge
	nrf_drv_gpiote_in_config_t in_config = GPIOTE_CONFIG_IN_SENSE_TOGGLE(true);
	
	// Set internal pullup resistor
in_config.pull = NRF_GPIO_PIN_PULLUP;

err_code = nrf_drv_gpiote_in_init(TAG_TX, &in_config, in_pin_handler);
APP_ERROR_CHECK(err_code);

	// Initialise the PPI
	err_code = nrf_drv_ppi_init();
	APP_ERROR_CHECK(err_code);
	
	// Allocate ppi_channel_1 and check that it is available
	err_code = nrf_drv_ppi_channel_alloc(&ppi_channel1);
APP_ERROR_CHECK(err_code);
	
	// Get the timer task address for NRF_TIMER_TASK_CAPTURE1
	capture_task_addr = nrf_drv_timer_task_address_get(&timer, NRF_TIMER_TASK_CAPTURE1);
	
	// Get the interrupt address for pin TAG_TX
	gpiote_evt_addr = nrf_drv_gpiote_in_event_addr_get(TAG_TX);
	
	// Assign the capture and interrupt to the PPI channel
	err_code = nrf_drv_ppi_channel_assign(ppi_channel1, gpiote_evt_addr, capture_task_addr);
	APP_ERROR_CHECK(err_code);
	
	// Enable the PPI channel
	err_code = nrf_drv_ppi_channel_enable(ppi_channel1);
	APP_ERROR_CHECK(err_code);

}

Does anyone know how I could capture all the edges and the time difference between edge captures or speed up the interrupt?

Thanks, James

Parents
  • Hi James

    Do you put the chip in system ON sleep mode while the data capture is occurring? If so you might want to enable constant latency mode before entering sleep, and you should see quicker event response (at the cost of higher sleep current).

    Another trick to give you some more time is to set up individual events on rising and falling flank. Then you should have twice as long time (on average) to process the events.

    Would you say that the system is too slow consistently, or is it only during higher priority interrupts that you get issues (such as those generated by the SoftDevice during radio activity)?

    Best regards
    Torbjørn

Reply
  • Hi James

    Do you put the chip in system ON sleep mode while the data capture is occurring? If so you might want to enable constant latency mode before entering sleep, and you should see quicker event response (at the cost of higher sleep current).

    Another trick to give you some more time is to set up individual events on rising and falling flank. Then you should have twice as long time (on average) to process the events.

    Would you say that the system is too slow consistently, or is it only during higher priority interrupts that you get issues (such as those generated by the SoftDevice during radio activity)?

    Best regards
    Torbjørn

Children
  • When I call the function:

    nrf_drv_timer_capture_get(&timer, NRF_TIMER_CC_CHANNEL1);

    the delay in my ISR is too long and thus causing timing issues but I need the stored value before the next falling or rising edge (depending on the edge that triggered the interrupt).

    Thanks

  • Hi James

    You actually don't need to use two separate GPIO's, just separate GPIOTE channels on the same pin. I am also unsure how using two timers will help. I would assume just having one free running timer, and capture continuously to two different CC registers, should be equally efficient.

    Have you measured the worst case (minimum) time interval between two rising or falling edges?
    Once the first edge is detected, do you always exit the interrupt, or do hang inside the interrupt waiting for more edges?
    What is the typical activity rate of the interface in your application. Is it running continuously, or in bursts?

    I am suspecting that the nrf_drv_gpiote library is adding too much overhead, and not a good option in your case. Most likely you should just use the NRF_GPIOTE hardware directly, to keep the latency to an absolute minimum.

Related