Measuring frequency from a remote control is a really nasty issue on the RP2xxx. The above code does work, for some protocols.
The problem: all of these methods work fairly well for a constant frequency, but the IR remove control uses bursts of pulses. Without a hardware method to trigger the pulse counter, we are at the mercy of interrupt latency to catch the pulse at the right place.
if(!gpio_get(bio2bufiopin[BIO1])){
freq_counter_start();
while (!freq_counter_value_ready());
printf("Frequency %uHz\r\n", edge_counter_frequency());
//gpio_set_irq_enabled_with_callback(bio2bufiopin[BIO1], GPIO_IRQ_EDGE_FALL, true, &gpio_fall_irq_handler);
}
I’m using a tight loop for testing, and you can see above we get 40khz when we should get around 36khz. If this was triggered on interrupt it would get even dodgier.
After some study, I have an idea that may not pan out:
- A PIO program that waits for pin to 0, then pushes a work into the PIO FIFO
- The PIO FIFO can create a dreq (data request) over DMA
- A PWM is used as a gating timer, which down counts our sample interval when the PIO FIFO dreq fires
- One B slice is the pulse counter, which counts until the gating timer times out and fires a DREQ.
The unknown: is it possible to do pwm_set_mask_enabled((1 << counter_slice) | (1 << gate_slice)); with a single register write with DMA? It looks like yes, it is a single register write.
Another possibility is to use the DMA pacing timer to control the pulse count timer, I believe?
I’m going to let the frequency bit set for a while and finish building out the raw and AnalysIR RX/TX stuff.