Skip to content

Commit 606ce76

Browse files
committed
add gpio interrupts
also restructured a little bit
1 parent 5a52867 commit 606ce76

File tree

5 files changed

+320
-3
lines changed

5 files changed

+320
-3
lines changed

Arduino.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,16 @@ SOFTWARE.
2323
// The "Arduino.h" header file is intended to only be included by C++ sources.
2424

2525
#ifndef _ARDUINO_MBED_BRIDGE_ARDUINO_H_
26-
#define _ARDUINO_H_
26+
#define _ARDUINO_MBED_BRIDGE_ARDUINO_H_
2727

2828
#include "mbed.h"
2929

3030
#define PinMode Arduino_PinMode // note: this changes the Arduino API for mbed compatibility - use Arduino_PinMode where PinMode was specified in the Arduino API
3131
#include "core-api/api/ArduinoAPI.h"
3232
#undef PinMode
3333

34+
#include "core-extend/ArduinoAPI.h"
35+
3436
#include "bridge/pins.h"
3537

3638
#include "variant.h" // user-supplied

bridge/pins.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ SOFTWARE.
2828
typedef struct _PinState {
2929
PinName name;
3030
pin_size_t number;
31-
InterruptIn* irq;
31+
arduino::InterruptInParam* irq;
3232
// PwmOut* pwm; // todo: implement this
3333
// AnalogOut* dac; // todo: implement this
3434
// AnalogIn* adc; // todo: implement this

core-extend/ArduinoAPI.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
Copyright (c) 2020 SparkFun Electronics
3+
4+
Permission is hereby granted, free of charge, to any person obtaining a copy
5+
of this software and associated documentation files (the "Software"), to deal
6+
in the Software without restriction, including without limitation the rights
7+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
copies of the Software, and to permit persons to whom the Software is
9+
furnished to do so, subject to the following conditions:
10+
11+
The above copyright notice and this permission notice shall be included in all
12+
copies or substantial portions of the Software.
13+
14+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20+
SOFTWARE.
21+
*/
22+
23+
#ifndef _ARDUINO_MBED_BRIDGE_CORE_EXTEND_ARDUINOAPI_H_
24+
#define _ARDUINO_MBED_BRIDGE_CORE_EXTEND_ARDUINOAPI_H_
25+
26+
#include "core-extend/Common.h"
27+
28+
#endif // _ARDUINO_MBED_BRIDGE_CORE_EXTEND_ARDUINOAPI_H_

core-extend/Common.h

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,11 @@ SOFTWARE.
2323
#ifndef _ARDUINO_MBED_BRIDGE_CORE_EXTEND_COMMON_H_
2424
#define _ARDUINO_MBED_BRIDGE_CORE_EXTEND_COMMON_H_
2525

26-
#include "Arduino.h"
26+
#include "mbed.h"
27+
28+
#define PinMode Arduino_PinMode // note: this changes the Arduino API for mbed compatibility - use Arduino_PinMode where PinMode was specified in the Arduino API
29+
#include "core-api/api/Common.h"
30+
#undef PinMode
2731

2832
void indexPinMode(pin_size_t index, Arduino_PinMode pinMode);
2933
void pinMode(PinName pinName, Arduino_PinMode pinMode);
@@ -50,6 +54,15 @@ void shiftOut(PinName dataPinName, PinName clockPinName, BitOrder bitOrder, uint
5054
pin_size_t indexShiftIn(pin_size_t data_index, pin_size_t clock_index, BitOrder bitOrder);
5155
pin_size_t shiftIn(PinName dataPinName, PinName clockPinName, BitOrder bitOrder);
5256

57+
void indexAttachInterrupt(pin_size_t index, voidFuncPtr callback, PinStatus mode);
58+
void attachInterrupt(PinName pinName, voidFuncPtr callback, PinStatus mode);
59+
60+
void indexAttachInterruptParam(pin_size_t index, voidFuncPtrParam callback, PinStatus mode, void* param);
61+
void attachInterruptParam(PinName pinName, voidFuncPtrParam callback, PinStatus mode, void* param);
62+
63+
void indexDetachInterrupt(pin_size_t index);
64+
void detachInterrupt(PinName pinName);
65+
5366
#ifdef __cplusplus
5467

5568
void indexTone(pin_size_t index, unsigned int frequency, unsigned long duration = 0);
@@ -58,6 +71,73 @@ unsigned long pulseIn(PinName pinName, uint8_t state, unsigned long timeout =
5871
unsigned long indexPulseInLong(pin_size_t index, uint8_t state, unsigned long timeout = 1000000L);
5972
unsigned long pulseInLong(PinName pinName, uint8_t state, unsigned long timeout = 1000000L);
6073

74+
#if DEVICE_INTERRUPTIN
75+
76+
namespace arduino {
77+
78+
class InterruptInParam : public mbed::InterruptIn {
79+
private:
80+
protected:
81+
public:
82+
/** Create an InterruptIn connected to the specified pin
83+
*
84+
* @param pin InterruptIn pin to connect to
85+
*/
86+
InterruptInParam(PinName pin);
87+
88+
/** Create an InterruptIn connected to the specified pin,
89+
* and the pin configured to the specified mode.
90+
*
91+
* @param pin InterruptIn pin to connect to
92+
* @param mode Desired Pin mode configuration.
93+
* (Valid values could be PullNone, PullDown, PullUp and PullDefault.
94+
* See PinNames.h for your target for definitions)
95+
*
96+
*/
97+
InterruptInParam(PinName pin, PinMode mode);
98+
99+
virtual ~InterruptInParam();
100+
101+
/** Attach a function to call when a rising edge occurs on the input
102+
*
103+
* @param func A pointer to a void function with argument, or 0 to set as none
104+
*/
105+
void rise(Callback<void(void*)> func, void* param);
106+
107+
/** Attach a function to call when a rising edge occurs on the input
108+
*
109+
* @param func A pointer to a void function, or 0 to set as none
110+
*/
111+
void rise(Callback<void()> func); // shadows InterruptIn::rise
112+
113+
/** Attach a function to call when a falling edge occurs on the input
114+
*
115+
* @param func A pointer to a void function with argument, or 0 to set as none
116+
*/
117+
void fall(Callback<void(void*)> func, void* param);
118+
119+
/** Attach a function to call when a falling edge occurs on the input
120+
*
121+
* @param func A pointer to a void function, or 0 to set as none
122+
*/
123+
void fall(Callback<void()> func); // shadows InterruptIn::fall
124+
125+
static void _irq_handler(uint32_t id, gpio_irq_event event);
126+
127+
protected:
128+
Callback<void(void*)> _rise; // shadows InterruptIn::_rise
129+
Callback<void(void*)> _fall; // shadows InterruptIn::_fall
130+
131+
void* _rise_param = nullptr;
132+
void* _fall_param = nullptr;
133+
134+
void irq_init(PinName pin); // shadows InterruptIn::irq_init
135+
};
136+
137+
} // namespace arduio
138+
139+
#endif //DEVICE_INTERRUPTIN
140+
61141
#endif // __cplusplus
62142

63143
#endif // _ARDUINO_MBED_BRIDGE_CORE_EXTEND_COMMON_H_

core-implement/CommonInterrupt.cpp

Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
/*
2+
Copyright (c) 2020 SparkFun Electronics
3+
4+
Permission is hereby granted, free of charge, to any person obtaining a copy
5+
of this software and associated documentation files (the "Software"), to deal
6+
in the Software without restriction, including without limitation the rights
7+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
copies of the Software, and to permit persons to whom the Software is
9+
furnished to do so, subject to the following conditions:
10+
11+
The above copyright notice and this permission notice shall be included in all
12+
copies or substantial portions of the Software.
13+
14+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20+
SOFTWARE.
21+
*/
22+
23+
#include "mbed.h"
24+
25+
#define PinMode Arduino_PinMode
26+
#include "core-api/api/Common.h"
27+
#undef PinMode
28+
29+
#include "core-extend/Common.h"
30+
#include "bridge/pins.h"
31+
32+
#define standInFunc() printf("Stand-In for '%s' [file: %s, line: %d]\n", __FUNCTION__, __FILE__, __LINE__)
33+
34+
void indexAttachInterruptParam(pin_size_t index, voidFuncPtrParam callback, PinStatus mode, void* param){
35+
indexDetachInterrupt(index);
36+
arduino::InterruptInParam* irq = pinIRQByIndex(index);
37+
if(!irq){
38+
irq = new arduino::InterruptInParam(pinNameByIndex(index));
39+
}
40+
pinIRQByIndex(index) = irq;
41+
switch (mode) {
42+
case CHANGE :
43+
irq->rise(mbed::callback(callback), param);
44+
irq->fall(mbed::callback(callback), param);
45+
break;
46+
case FALLING :
47+
irq->fall(mbed::callback(callback), param);
48+
break;
49+
case RISING :
50+
default :
51+
irq->rise(mbed::callback(callback), param);
52+
break;
53+
}
54+
if(!pinGPIOByIndex(index)){ // Give a default pullup for the pin, since calling InterruptIn with PinMode is impossible
55+
switch (mode) {
56+
case FALLING :
57+
indexPinMode(index, INPUT_PULLUP);
58+
break;
59+
case RISING :
60+
indexPinMode(index, INPUT_PULLDOWN);
61+
break;
62+
case CHANGE :
63+
default:
64+
indexPinMode(index, INPUT);
65+
break;
66+
}
67+
}
68+
}
69+
70+
void attachInterruptParam(pin_size_t pinNumber, voidFuncPtrParam callback, PinStatus mode, void* param){
71+
pin_size_t index = pinIndexByNumber(pinNumber);
72+
if( index == variantPinCount ){ return; }
73+
indexAttachInterruptParam(index, callback, mode, param);
74+
}
75+
76+
void attachInterruptParam(PinName pinName, voidFuncPtrParam callback, PinStatus mode, void* param){
77+
pin_size_t index = pinIndexByName(pinName);
78+
if( index == variantPinCount ){ return; }
79+
indexAttachInterruptParam(index, callback, mode, param);
80+
}
81+
82+
void indexAttachInterrupt(pin_size_t index, voidFuncPtr callback, PinStatus mode){
83+
indexAttachInterruptParam(index, (voidFuncPtrParam)callback, mode, NULL);
84+
}
85+
86+
void attachInterrupt(pin_size_t pinNumber, voidFuncPtr callback, PinStatus mode){
87+
pin_size_t index = pinIndexByNumber(pinNumber);
88+
if( index == variantPinCount ){ return; }
89+
indexAttachInterrupt(index, callback, mode);
90+
}
91+
92+
void attachInterrupt(PinName pinName, voidFuncPtr callback, PinStatus mode){
93+
pin_size_t index = pinIndexByName(pinName);
94+
if( index == variantPinCount ){ return; }
95+
indexAttachInterrupt(index, callback, mode);
96+
}
97+
98+
void indexDetachInterrupt(pin_size_t index){
99+
arduino::InterruptInParam* irq = pinIRQByIndex(index);
100+
if(!irq){ return; }
101+
irq->rise(NULL, NULL);
102+
irq->fall(NULL, NULL);
103+
}
104+
105+
void detachInterrupt(pin_size_t pinNumber){
106+
pin_size_t index = pinIndexByNumber(pinNumber);
107+
if( index == variantPinCount ){ return; }
108+
indexDetachInterrupt(index);
109+
}
110+
111+
void detachInterrupt(PinName pinName){
112+
pin_size_t index = pinIndexByName(pinName);
113+
if( index == variantPinCount ){ return; }
114+
indexDetachInterrupt(index);
115+
}
116+
117+
//
118+
// InterruptInParam implementation
119+
120+
// Note: This single-parameter constructor exists to maintain binary
121+
// compatibility.
122+
// If not for that, we could simplify by having only the 2-param
123+
// constructor, with a default value for the PinMode.
124+
InterruptInParam::InterruptInParam(PinName pin) :
125+
InterruptIn(pin)
126+
{
127+
irq_init(pin);
128+
}
129+
130+
InterruptInParam::InterruptInParam(PinName pin, PinMode mode) :
131+
InterruptIn(pin, mode)
132+
{
133+
irq_init(pin);
134+
}
135+
136+
InterruptInParam::~InterruptInParam()
137+
{
138+
139+
}
140+
141+
void InterruptInParam::irq_init(PinName pin)
142+
{
143+
gpio_irq_init(&gpio_irq, pin, (&InterruptInParam::_irq_handler), (uint32_t)this);
144+
}
145+
146+
void InterruptInParam::rise(Callback<void(void*)> func, void* param)
147+
{
148+
core_util_critical_section_enter();
149+
if (func) {
150+
_rise = func;
151+
gpio_irq_set(&gpio_irq, IRQ_RISE, 1);
152+
} else {
153+
_rise = nullptr;
154+
gpio_irq_set(&gpio_irq, IRQ_RISE, 0);
155+
}
156+
if (param) {
157+
_rise_param = param;
158+
} else {
159+
_rise_param = nullptr;
160+
}
161+
core_util_critical_section_exit();
162+
}
163+
164+
void InterruptInParam::rise(Callback<void()> func){
165+
error("InterruptInParam.rise called with 'void(void)' callback (should be 'void(void*)')\r\n");
166+
}
167+
168+
void InterruptInParam::fall(Callback<void(void*)> func, void* param)
169+
{
170+
core_util_critical_section_enter();
171+
if (func) {
172+
_fall = func;
173+
gpio_irq_set(&gpio_irq, IRQ_FALL, 1);
174+
} else {
175+
_fall = nullptr;
176+
gpio_irq_set(&gpio_irq, IRQ_FALL, 0);
177+
}
178+
if (param) {
179+
_fall_param = param;
180+
} else {
181+
_fall_param = nullptr;
182+
}
183+
core_util_critical_section_exit();
184+
}
185+
186+
void InterruptInParam::fall(Callback<void()> func){
187+
error("InterruptInParam.fall called with 'void(void)' callback (should be 'void(void*)')\r\n");
188+
}
189+
190+
void InterruptInParam::_irq_handler(uint32_t id, gpio_irq_event event)
191+
{
192+
InterruptInParam *handler = (InterruptInParam *)id;
193+
switch (event) {
194+
case IRQ_RISE:
195+
if (handler->_rise) {
196+
handler->_rise(handler->_rise_param);
197+
}
198+
break;
199+
case IRQ_FALL:
200+
if (handler->_fall) {
201+
handler->_fall(handler->_fall_param);
202+
}
203+
break;
204+
case IRQ_NONE:
205+
break;
206+
}
207+
}

0 commit comments

Comments
 (0)