Digital pin interrupt

Can someone point me at the documentation/API for using pin interrupts with LibDaisy, I can’t seem to find any. Basically the equivalent of attachInterrupt() on Arduino, so I can trigger an interrupt whenever a pin goes high. Thanks!

You can’t find it because there’s no support for EXTI in there. The rationale is probably that software polling is generally good enough for applications where Daisy gets used. So if you actually need them, you would have to use STM32 HAL directly to configure them yourself and add an interrupt callback. You should be aware that:

  1. They’re not available on every pin, you’ll have to search in the reference manual or somewhere else to find on which ones are they supported

  2. Regarding interrupt priorities, libDaisy sets everything with highest priority (0) except timer interrupts (15). So you should consider how you want EXTI to behave when configuring them, but I imagine you could just set it to 0 too.

Thanks for the reply! I may just use polling for now then. It’s only to trap triggers on a Eurorack module. Hopefully the pulse width of most clocks is wider than my main loop time.

I’m revisiting this because it turned out polling wasn’t fast enough (I’m using this to control a looper and so if the loop start/stop are slightly out the timing will drift over time). From what you are saying, the audio interrupt is set to 0 priority, so even if I implement a pin interrupt at priority 0 it will never pre-empt the audio interrupt?

My pin interrupt will be very fast (just setting a flag), so I had hoped I would be able to pre-empt the audio interrupt, set the flag, and jump right back into audio, without causing any issues with the audio output.

I can thing of 2 reasonable approaches to avoid this sort of jitter issue:

  1. Use a smaller audio buffer size to make it acceptable

  2. Override libDaisy interrupt priority to preempt audio callback with EXTI interrupt. In this case your interrupt handler should read DMA counter for SAI to find out how many bytes where transferred using __HAL_DMA_GET_COUNTER macro. Then you can synchronize EXTI event with audio at sample precision.

Thanks for your reply! Some comments on your points

  1. I had considered this, but even with a small buffer size (64 samples), there’s still going to be 1ms of latency or so, which over many iterations of the loop will cause drift.
  2. a.) Is there an interface to change lib daisy interrupt priority, or did you mean I would need to change the lib daisy code myself?
    b.) When you refer to __HAL_DMA_GET_COUNTER, do you mean as a way to measure the time between the start/stop triggers in order to trim the loop to the sample correct size? I was going to use processor cycles for this (or daisy::System::GetTick()) is there a reason that wouldn’t be sufficient?

Thanks again!

Sorry, it looks like you will have to figure out what works and what doesn’t on your own. That said, I don’t think libDaisy has support for overriding default interrupt priorities for SAI IRQ. People don’t normally mess with audio interrupts, so it’s better to actually reproduce the problem before trying to solve it.

I’ve suggested looking at DMA transfer because what you’re trying to do is synchronize SAI and EXTI, so it makes sense to deal with DMA transfer counter directly instead of using another reference source. With clock cycles you will have to do some extra maths to arrive to the same value.

Also, it looks like your understanding of what is a “small” buffer is incorrect - the default value used by libDaisy is less than what you’ve mentioned (it’s 48 sample to give exactly 1ms buffer duration) and people have used less than that. I think someone brought it down to 1 sample (which I would consider unreasonable for most use cases).

1 Like

Interesting, thanks! I’m currently using a 128 buffer (as I’d previously used Teensy Audio and that was the default). I’ll try a smaller buffer size first as that’s definitely easier. But I think even a 1ms discrepancy will lead the loop to sound out of sync after a few iterations.

Having tried to quickly implement this, it seems my understanding of what you were saying was wrong, I assumed that __HAL_DMA_GET_COUNTER was the total number of bytes transmitted since the audio started, but from the docs it says:

The number of remaining data units in the current DMA Stream transfer

So I assume that’s the remaining data from the previous audio interrupt? In which case I need to calculate the number of samples that have played since the trigger point, within the audio interrupt, like this:

total_samples_since_trigger = (audio_interrupts_since_trigger * audio_block_size) - (__HAL_DMA_GET_COUNTER / sample_size_in_bytes)

Is that what you were suggesting? Thanks in advance!