@@ -45,26 +45,40 @@ extern "C" void noInterrupts() {
4545// Only 1 GPIO IRQ callback for all pins, so we need to look at the pin it's for and
4646// dispatch to the real callback manually
4747auto_init_mutex (_irqMutex);
48- static std::map<pin_size_t , voidFuncPtr> _map;
48+ class CBInfo {
49+ public:
50+ CBInfo (voidFuncPtr cb) : _cb(cb), _useParam(false ), _param(nullptr ) { };
51+ CBInfo (voidFuncPtrParam cbParam, void *param) : _cbParam(cbParam), _useParam(true ), _param(param) { };
52+ void callback () {
53+ if (_useParam && _cbParam) {
54+ _cbParam (_param);
55+ } else if (_cb) {
56+ _cb ();
57+ }
58+ }
59+ private:
60+ union {
61+ voidFuncPtr _cb;
62+ voidFuncPtrParam _cbParam;
63+ };
64+ bool _useParam;
65+ void *_param;
66+ };
67+
68+
69+ static std::map<pin_size_t , CBInfo> _map;
4970
5071void _gpioInterruptDispatcher (uint gpio, uint32_t events) {
5172 (void ) events;
5273 // Only need to lock around the std::map check, not the whole IRQ callback
53- voidFuncPtr cb = nullptr ;
54- {
55- CoreMutex m (&_irqMutex);
56- if (m) {
57- auto irq = _map.find (gpio);
58- if (irq != _map.end ()) {
59- cb = irq->second ;
60- }
74+ CoreMutex m (&_irqMutex);
75+ if (m) {
76+ auto irq = _map.find (gpio);
77+ if (irq != _map.end ()) {
78+ auto cb = irq->second ;
79+ cb.callback ();
6180 }
6281 }
63- if (cb) {
64- cb (); // Do the callback
65- } else {
66- // ERROR, but we're in an IRQ so do nothing
67- }
6882}
6983
7084extern " C" void attachInterrupt (pin_size_t pin, voidFuncPtr callback, PinStatus mode) {
@@ -84,7 +98,31 @@ extern "C" void attachInterrupt(pin_size_t pin, voidFuncPtr callback, PinStatus
8498 }
8599 noInterrupts ();
86100 detachInterrupt (pin);
87- _map.insert ({pin, callback});
101+ CBInfo cb (callback);
102+ _map.insert ({pin, cb});
103+ gpio_set_irq_enabled_with_callback (pin, events, true , _gpioInterruptDispatcher);
104+ interrupts ();
105+ }
106+
107+ void attachInterruptParam (pin_size_t pin, voidFuncPtrParam callback, PinStatus mode, void *param) {
108+ CoreMutex m (&_irqMutex);
109+ if (!m) {
110+ return ;
111+ }
112+
113+ uint32_t events;
114+ switch (mode) {
115+ case LOW: events = 1 ; break ;
116+ case HIGH: events = 2 ; break ;
117+ case FALLING: events = 4 ; break ;
118+ case RISING: events = 8 ; break ;
119+ case CHANGE: events = 4 | 8 ; break ;
120+ default : return ; // ERROR
121+ }
122+ noInterrupts ();
123+ detachInterrupt (pin);
124+ CBInfo cb (callback, param);
125+ _map.insert ({pin, cb});
88126 gpio_set_irq_enabled_with_callback (pin, events, true , _gpioInterruptDispatcher);
89127 interrupts ();
90128}
0 commit comments