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

  • 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

  • Hi, Thanks for the response. I have enabled constant latency mode. I have removed any visible sleep function in my code.

    I have tried setting up individual events on rising and falling edge. I have the data stream going to two pins on the nrf52 (one set to interrupt on PosEdge and the other on NegEdge) in hopes that this would solve the issue.

    The system seems too slow consistently. The response time from the level changing to the ISR is about 8.5uS. Can you think of any other way I can speed this up? Any workaround ideas would also be greatly appreciated.

    Regards, James

    ...small update.

    I am using two PPI's , two GPIO interrupts and two timers with capture enabled. One GPIO interrupt is generated on rising edge, the other on negative edge. Each interrupt generates a capture event using their respective PPI's. The problem I now have is trying to get the data from these captures...

  • 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