midilab / uClock

A tight BPM clock generator for Arduino and PlatformIO using hardware timer interruption. AVR, Teensy, STM32xx, ESP32 and RP2040 support
https://midilab.co/umodular
MIT License
153 stars 19 forks source link

initial working proof-of-concept of rp2040 support #33

Closed doctea closed 3 months ago

doctea commented 5 months ago

Examples seem to be working in the basic case (of flashing LED). Tested on a Seeed XIAO RP2040

vanzuiden commented 5 months ago

Hi @doctea, nice to see this development going on. I'm very interested in running uClock on a Pi Pico.

I've tested your branch on my Pi Pico. My code runs but I ran into the same problem i now see you reported yourself:

I have to use the BOOTSEL button to run new code on the pico.

Can you elaborate on this issue?

Edit: Let me know if there's anything i can do to help getting this into a production-ready state!

doctea commented 5 months ago

Hi @vanzuiden , thanks for giving this a try and commenting!

  • Doing a 'soft reboot' (eg from reflashing) seems to crash on startup, but starting from cold and powering on works fine. I have to use the BOOTSEL button to run new code on the pico.

Indeed, thanks for confirming this isn't just me. May need to find someone who knows more about the Pico/SDK/the earlphilhower core to take a look at why this could be..

  • Tick ticking may be off due to repeating_timer following from the end of previous tick, rather than following the start of the previous tick. Can you elaborate on this issue?

Sure, so the _add_repeating_timerus function that sets up the interrupt-based timer can take either a positive or a negative number for the timer interval value. If its a positive value then the next timer will trigger interval us after the timer callback function returns. If its a negative value, then its meant to trigger interval us after the last trigger happens.

Currently the RP2040 implementation uses a positive value and so the repeating timers will actually be triggering late every time, depending on how long your callback function takes each tick. This means that the BPM will probably be a bit lower than it really should be.

Changing the interval it to a negative value seems to crash completely on startup for me. This is another problem where someone with more expertise on the inner workings of the Pico/SDK/core should be able to help! (a possibly related ticket.. https://github.com/raspberrypi/pico-sdk/issues/737)

What I can try next myself is to get my debug probe working again, and see if I can find some useful information about where exactly these freezes are occurring, or if its getting stuck in a deadlock etc. I'll see if I can get somewhere with that this week.

Edit: Let me know if there's anything i can do to help getting this into a production-ready state!

Your testing is helpful & much appreciated and if you have anything else to contribute or other thoughts then please let us know! :D

doctea commented 5 months ago

Hm, so I've just tried this out and using the 'negative interval' _add_repeatingtimer actually works fine in this test sketch: https://gist.github.com/doctea/a7b4b401a9169ca555b020b3dcc15d95

So maybe its something else that is causing a problem with it in uClock.

Also got my debug probe working, and when trying to use an RP2040ClockBlink sketch and a 'negative interval' version of uClock, I can see that FreeRTOS/loop() is actually still running, but the interrupt never fires..

ichingxs4all commented 5 months ago

I'm also testing this Rp2040 branch because I'm trying to swap my existing Teensy 3.2 / LC projects to Rp2040 based micro's. I ran in to a puzzling problem. When I use the hardware Serial1 and Arduino MIDI library the BPM is like the half of the tempo and not stable . ( I test this with an external drumcomputer in slave mode ). But when I use usb midi it is stable minus 1 bpm. If I use hardware Serial 1 and NOT use the MIDI library but directly send midi clock/start/stop commands at 31250 baud with serial1.write..it is stable ..minus 1 bpm. The reason why I need the MIDI library is because of the very nice midi receive handles.

midilab commented 5 months ago

hey, good to see so many people involved, looks like rp2040 is realy growing in popularity.

so i've just order one for my self so i can run proper tests and debug too.

seeing so many new dual core with arduino freetos support makes me thinking about give uClock a separate way for those who want to make use of it instead of classic interrupt method.

something like add a new include file #include for special freertos support on those platforms that supports it. soon i will come up with this schema to separate the implementations and give programmers more freedom to chose the implementation.

using freertos is realy the way to go if it is avaliable, speacialy for sequencers, samplers or synths, but there are tradeoffs, its harder to program but far way better results in terms of overwal system stability and precissiness, the interrupt method is more easy to handle and program on most of scenarios, but the main problem is that you can't fill interrupts with tons of code, its not even advisable to do shorter processing on ISR(rule of thumb, ISR should go in, and as soon as it can go out), so theres is a safe limit here too where you will start to loss presicion of the clock because of late running ISR and will start to happen the most esoteric and unpredictable behaviours of your code(from freezing to crazyness).

current the freertos implmenetation for esp32 uses the same ATOMIC macro to keep compatible, but in a scenario of multithread and multi shared resources, each shared resource should have his own mutex of semaphore depends on your code needs. So ATOMIC should be ok if you are using over a single shared resource like one Serial interface.

So the correct way should be separate both implementations and let the programmer create his own mutexes and/or semaphores outside uClock scope if he pickup the freertos implementation.

by the way thanks everyone for all the research, debug and tests so far, lots of usefull information for me to start debug and test.

doctea commented 4 months ago

I ran in to a puzzling problem. When I use the hardware Serial1 and Arduino MIDI library the BPM is like the half of the tempo and not stable .

Testing my own project to try and figure out why my clock is ~10bpm slow at 120bpm, I disabled some parts of my code that were also sending MIDI (through hardware serial, I think with PIO serial...) expecting to see a small increase in clock rate but was surprised to see the clock now ticking at half-speed, around 60bpm instead of the set 120bpm, which reminded me of this comment.

Very strange indeed! More investigation and testing required.

midilab commented 3 months ago

Tested from my side on rpi2040 zero from waveshare. No troubles so far, thanks @doctea for this great contribution!

I've just update the example and removed the FreeRTOS version(so far seens to have some troubles along with tinyUSB for midi over USB... so lets avoid it for now)