-
Notifications
You must be signed in to change notification settings - Fork 1k
Added functionality to pass custom parameter to HardwareTimer callback #892
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
I cherry picked the changes from the older version of arduino_core that platformio uses so I haven't been able to test the changes for current version. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @ramboerik ,
Thank you for this pull request. I run HardwareTimer non regression test and it is passed. 👍
Just missing few comments to keep code coherent and easy to read/maintain.
Also there is an issue returned by travis/Astyle. Can you run astyle: https://github.com/stm32duino/wiki/wiki/Astyle
By the way, can you also update wiki page with the new API you added:
https://github.com/stm32duino/wiki/wiki/HardwareTimer-library#API
All comments fixed and wiki is updated. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ramboerik , thanks for the update.
But still missing few comments.
Also for wiki update, you added new API, but you keep the old prototypes for attachInterrupt(..) without the new parameter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a lot @ramboerik.
LGTM
Hi @uzi18 is this a request? I could of course add an example usage somewhere, maybe on the wiki page? |
@ramboerik , if you go for a new example, it can be added here: |
How is this parameter to be used? Normally, such a parameter is passed to the callback, but that does not seem to happen here (which would also have some complications for backward compatibility, of course). It seems these "arguments" can be accessed using |
@matthijskooijman This was originally designed for the rollover interrupt which doesn't have the channel parameter and the you can just use Example: #include <Arduino.h>
HardwareTimer t1(TIM1);
HardwareTimer t2(TIM2);
HardwareTimer t3(TIM3);
enum {
CHANNEL_1 = 1,
CHANNEL_2 = 2,
CHANNEL_3 = 3,
CHANNEL_4 = 4,
};
class CParam{
public:
int pin = 0;
CParam(int pin) : pin(pin) {
pinMode(pin, OUTPUT);
}
};
void rollover_cb(HardwareTimer *timer){
CParam* arg = (CParam*)timer->getArg();
if(arg == nullptr) return;
digitalWrite(arg->pin, !digitalRead(arg->pin));
}
void channel_cb1(HardwareTimer *timer){
CParam* arg = (CParam*)timer->getArg(CHANNEL_1);
if(arg == nullptr) return;
digitalWrite(arg->pin, !digitalRead(arg->pin));
}
void channel_cb2(HardwareTimer *timer){
CParam* arg = (CParam*)timer->getArg(CHANNEL_2);
if(arg == nullptr) return;
digitalWrite(arg->pin, !digitalRead(arg->pin));
}
void setup(){
// heap alloc, scope will disappear
CParam* param1 = new CParam(LED_BUILTIN);
CParam* param2 = new CParam(LED_BLUE);
CParam* param3 = new CParam(LED_RED);
t1.attachInterrupt(rollover_cb, param1);
t1.attachInterrupt(CHANNEL_1, channel_cb1, param2);
t1.attachInterrupt(CHANNEL_2, channel_cb2, param3);
t1.setOverflow(5, HERTZ_FORMAT);
t1.setCaptureCompare(CHANNEL_1, 20, PERCENT_COMPARE_FORMAT);
t1.setCaptureCompare(CHANNEL_2, 40, PERCENT_COMPARE_FORMAT);
t1.resume();
}
void loop(){}
A bit cumbersome to use? yes. |
@ramboerik |
I agree with you if the solution is truly intelligent, better to do it well than to be forced by compatibility. |
Ok for me to pass the param in the callback prototype. It is clearer even if it breaks the compatibility. |
@ramboerik Thanks in advance |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ramboerik
could you udapte your PR to pass parameter to the callback?
Thanks in advance
okay, it's on my todo list! shall i open a new PR or continue on this one? |
Thanks @ramboerik |
@fpistm sorry, I was away for some job interviews. I agree with you too. |
No worries @LinoBarreca 😉 |
ArduinoCore-API also contains some implementation to allow passing not just void* arguments, but references to any object (which will be internally converted to void* and then back to a reference on the call), but I do not like the implementation much (it uses dynamic memory which I think is not really needed, and without a good way to clean up) and I'm not so sure that implicitly passing references to arbitrary objects is a good idea (it hides pointer complexity, but makes it easy for users to pass references to short-lived objects with all of the hard to debug fallout from that). Of all these options, I would bed inclined to use option 5, using |
I went with a minimal change in line with # 5 described above. I changed the interrupt callback from being a raw pointer into std::function. If anyone want to pass arguments to the callbacks it's easy to wrap with std::bind. class abc{
private:
std::function<void(int)> cb_with_args = [&](int freq) {
blink_red_led(freq);
}
callback_function_t cb_without_args = []() {
blink_blue_led();
}
public:
abc(){
attachInterrupt(std::bind(cb_with_args, 500));
attachInterrupt(cb_without_args);
}
}; |
Hi @ramboerik,
There is also the HardwareTimer examples and NonReg, but I propose to handle that part on my side. |
…erial.cpp/Tone.cpp
Update example following implementation of stm32duino/Arduino_Core_STM32#892 And add a new examplek to show how to use parameter.
Update example following implementation of stm32duino/Arduino_Core_STM32#892 And add a new example to show how to use parameter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Thanks @ramboerik . |
This would be fine to also update the Wiki, to warn about API change btw core version. |
@matthijskooijman |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code looks great to me, nice and clean diff. I left one nitpick inline.
The commit history is a bit of a mess, though, so this should probably be squashed into a single commit during merge.
cores/arduino/HardwareTimer.cpp
Outdated
{ | ||
if (callbacks[0] != NULL) { | ||
if (callbacks[0] != nullptr) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would remove the !- nullptr
here, just let the callback be implicitly converted to bool
by the if. This does exactly the same, but is a bit more future-proof (support for != null
will be removed in C++20 for some reason) and does not suggest that the callback is actually a pointer (which it is not, though it sort of works like one).
Yes it will be squashed. |
Like advised in stm32duino#892 Already started in this stm32duino#892
Like advised in stm32duino#892 Already started in this stm32duino#892
Closes #891