I am trying to time a capacitor discharge through different resistance sensors for greater resolution than an ADC. I did this using the GPIO functions initially but the SD will sometimes interfere and cause the readings to be off. I have decided to try this via PPI and I have it just about working. The only issue I am having is the GPIOTE IN event does not seem to be triggering the timer capture task. I can use the IN Event callback to manually capture the value which does work but I really want to do it via PPI to avoid interference from the SD. I have included an annotated example; hopefully I am just missing something really simple:
#define TEMP_COMP_LINE 11
#define TEMP_THERM_LINE 12
#define TEMP_SENSE_LINE 13
// Use a counter so we can manually increment it and start the PPI chain
nrf_drv_timer_t start_counter = NRF_DRV_TIMER_INSTANCE(2);
// Timer for capacitor discharge
nrf_drv_timer_t discharge_timer = NRF_DRV_TIMER_INSTANCE(3);
// PPI Channels
nrf_ppi_channel_t ppi_1, ppi_2;
uint32_t line_discharge_time = 0;
void timer_event_handler(nrf_timer_event_t event_type, void * p_context){}
void sense_dummy_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action) {
// Uncommenting this will allow timer capture on IN event!
//line_discharge_time = nrf_drv_timer_capture(&discharge_timer, NRF_TIMER_CC_CHANNEL0);
__NOP();
}
uint32_t do_thermistor_ppi(uint32_t line) {
// Disable unused lines
uint32_t other_line = TEMP_THERM_LINE;
if (line == TEMP_THERM_LINE) {
other_line = TEMP_COMP_LINE;
}
// GPIOTEs
nrf_drv_gpiote_out_config_t line_cfg = GPIOTE_CONFIG_OUT_TASK_LOW;
nrf_drv_gpiote_out_init(line, &line_cfg);
nrf_drv_gpiote_out_clear(line);
nrf_drv_gpiote_in_config_t sense_cfg = GPIOTE_CONFIG_IN_SENSE_HITOLO(true);
// Init Manual Start Counter
nrf_drv_timer_config_t sc_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
sc_cfg.mode = NRF_TIMER_MODE_COUNTER;
sc_cfg.bit_width = NRF_TIMER_BIT_WIDTH_8;
nrf_drv_timer_init(&start_counter, &sc_cfg, timer_event_handler);
// Cause counter to trigger compare[0] on count of 1
nrf_drv_timer_compare(&start_counter, NRF_TIMER_CC_CHANNEL0, 1, true);
// Init Discharge timer
nrf_drv_timer_config_t dt_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
dt_cfg.mode = NRF_TIMER_MODE_TIMER;
dt_cfg.bit_width = NRF_TIMER_BIT_WIDTH_32;
dt_cfg.frequency = NRF_TIMER_FREQ_8MHz;
nrf_drv_timer_init(&discharge_timer, &dt_cfg, timer_event_handler);
// Configure a PPI channel to start the discharge timer for static compare
// line when manual count is incremented to 1.
nrf_drv_ppi_channel_alloc(&ppi_1);
nrf_drv_ppi_channel_assign(ppi_1,
nrf_drv_timer_event_address_get(&start_counter, NRF_TIMER_EVENT_COMPARE0),
nrf_drv_timer_task_address_get(&discharge_timer, NRF_TIMER_TASK_START));
// Set the capacitor to discharge at the same moment the timer starts for count 1
nrf_drv_ppi_channel_fork_assign(ppi_1, nrf_drv_gpiote_out_task_addr_get(line));
// Configure a PPI channel to stop the discharge timer whenever a sense line goes low
nrf_drv_ppi_channel_alloc(&ppi_2);
nrf_drv_ppi_channel_assign(ppi_2,
nrf_drv_gpiote_in_event_addr_get(TEMP_SENSE_LINE),
nrf_drv_timer_task_address_get(&discharge_timer, NRF_TIMER_TASK_CAPTURE0));
nrf_drv_ppi_channel_enable(ppi_1);
nrf_drv_ppi_channel_enable(ppi_2);
// Make sure both timers are enabled and cleared
nrf_drv_timer_clear(&start_counter);
nrf_drv_timer_enable(&start_counter);
nrf_drv_timer_clear(&discharge_timer);
// This will start the timer... whoops!
//nrf_drv_timer_enable(&discharge_timer);
// Other line not used. set to input
nrf_gpio_cfg_input(other_line, NRF_GPIO_PIN_NOPULL);
// Charge the capacitor via line
nrf_drv_gpiote_out_set(line);
nrf_delay_ms(600);
// Initialize and enable the out task (high to low)
nrf_drv_gpiote_out_task_enable(line);
// Initialize and enable then sense line (high to low)
sense_cfg.pull = NRF_GPIO_PIN_NOPULL;
nrf_drv_gpiote_in_init(TEMP_SENSE_LINE, &sense_cfg, sense_dummy_handler);
nrf_drv_gpiote_in_event_enable(TEMP_SENSE_LINE, true);
// Start the PPI tasks
nrf_drv_timer_increment(&start_counter);
nrf_delay_ms(600);
// PROBLEM! ->
// Register only valid if we capture from Event IN callback!
line_discharge_time = discharge_timer.p_reg->CC[0];
uint32_t count = nrf_drv_timer_capture(&start_counter, NRF_TIMER_CC_CHANNEL0);
// TODO: Cleanup
return line_discharge_time;
}
uint32_t system_thermistor_resistance_ppi() {
uint32_t compare_line = do_thermistor_ppi(TEMP_COMP_LINE);
//uint32_t thermistor_line = do_thermistor_ppi(TEMP_THERM_LINE);
return 0;
}
Using nRF5_SDK_12.2.0_f012efa with s132_nrf52_3.0.0_softdevice
Any ideas?
Thanks in advance,