Hi all,
I tried starting to change the Anduril code … but it seems that I’m missing something as it doesn’t work as expected.
Just to see if it’s work, I did the following changes to the 8C-mod changes ( I marked my changes with “WRH”):
I wanted that in case the aux lights are switched on 2 blinks are visible and 1 blink otherwise … but I get always 2 blinks and the aux lights stay off.
What it’s wrong here?
This code does two things which should never happen inside an event handler:
It calls nice_delay_ms(), which can only be used in the main loop, not inside an event handler. The “nice” part means it gives up time slices while it waits… and event handlers have no time slices to give. They are meant to return as quickly as possible.
It attempts to delay for more than 16ms. Events are generated every 16ms, with a very small buffer to queue pending events, so event handlers must return in less time than that. Rare exceptions are made sometimes, but only by small amounts (like maybe up to 32ms), and only when it can guarantee no other long events will happen at the same time.
The main exception is: blink_once() might take 12ms, and if the LEDs were off before, it might also cause FSM to jump-start the LEDs, which can take another 12ms… so it ends up taking maybe 25ms. A couple events pile up in the queue during this, but it’s not enough to overflow… so it clears out the pending events immediately, and usually wraps everything up within 32ms total. Then it’s in its normal state again, ready for more events.
Basically, if an event needs to do something which takes longer than 16ms, it needs to signal the main loop somehow, and let the main loop take care of the slow parts. It ideally should return in 12ms or less, to leave a bit of time to process other things before new events happen.
If you want a delayed blink, set a flag for the main loop to check… and then have the main loop wait (nicely, giving up time slices while it waits) and blink.
To expand on what TK said this, if you need to do long-running waits like TK described, it also means that if the user clicks the button again (after the timeout meaning that it’s a new click sequence), it will interrupt the wait, so you don’t get the light either not responding at all until the second blink (which can cause other loss of state and potentially even a crash that forces a reboot) or it suddenly doing something unexpected after the user has already gone straight into another mode.
For an example, I have a mod where when locked, 1/2C blink the aux 3 times (in red if RGB) ( @ToyKeeper been meaning to suggest this one for a merge actually, or you you can reimplement it in half the code size as as “inspired by/idea by” as seems to happen sometimes ) which uses this paradigm that you might want to use (it’s not perfect, I did some work to make it generic and reusable but I’m still not 100% happy with it as a solution (PRs are welcome ), but I’ve just had enough other stuff going on in my life right now, but it’d be easy to adapt for your use case in a similar way. This works for any use case (I use it for a lot of other stuff in my mod too) and is interruptible if the user starts doing something else and won’t cause events to be dropped.
Thanks!
I’ll take a look on this. I’m just in the phase of trying to learn how to change Anduril so that I get something working … just for me at the moment, but maybe later I can do something useful
Any help is very appreciated!