6
6
7
7
#include < Arduino.h>
8
8
9
+ #define GPIO_MODE_MASK (GPIO_INPUT | GPIO_OUTPUT | GPIO_ACTIVE_LOW | GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN | GPIO_PULL_UP)
10
+ #define DIGITAL_PIN_MAX 256
11
+
12
+ #define dN_gpios (N ) _CONCAT(_CONCAT(d, N), _gpios)
13
+ #define GPIO_ELEM (n,_ ) COND_CODE_1( DT_NODE_HAS_PROP(DT_PATH(zephyr_user), dN_gpios(n)), \
14
+ (DEVICE_DT_GET(DT_GPIO_CTLR_BY_IDX( DT_PATH(zephyr_user), dN_gpios(n), 0 )),), ())
15
+
16
+ #define GPIO_NGPIOS (n,_ ) COND_CODE_1( DT_NODE_HAS_PROP(DT_PATH(zephyr_user), dN_gpios(n)), \
17
+ (DT_PROP(DT_GPIO_CTLR_BY_IDX( DT_PATH(zephyr_user), dN_gpios(n), 0 ), ngpios),), ())
18
+
19
+ namespace {
20
+
21
+ /*
22
+ * Calculate GPIO ports/pins number statically from devicetree configuration
23
+ */
24
+
25
+ template <class First >
26
+ constexpr int count_ngpios (const int sum, const First&) { return sum; }
27
+
28
+ template <class First , class Second , class ... Rest>
29
+ constexpr int count_ngpios (const int max, const First& first, const Second& second, const Rest&... rest)
30
+ {
31
+ return count_ngpios (first == second ? first.ngpios : second, second, rest...);
32
+ }
33
+
34
+ template <class First >
35
+ constexpr int count_groups (const int sum, const First&) { return sum; }
36
+
37
+ template <class First , class Second , class ... Rest>
38
+ constexpr int count_groups (const int sum, const First& first, const Second& second, const Rest&... rest)
39
+ {
40
+ return count_groups (first == second ? sum : sum + 1 , second, rest...);
41
+ }
42
+
43
+ template <class First >
44
+ constexpr int max_in_list (const int max, const First&) { return max; }
45
+
46
+ template <class First , class Second , class ... Rest>
47
+ constexpr int max_in_list (const int max, const First& first, const Second& second, const Rest&... rest)
48
+ {
49
+ return max_in_list (first >= second ? first : second, second, rest...);
50
+ }
51
+
52
+ const int port_num = count_groups(0 , LISTIFY(DIGITAL_PIN_MAX, GPIO_ELEM, ()) nullptr );
53
+ const int max_ngpios = max_in_list(0 , LISTIFY(DIGITAL_PIN_MAX, GPIO_NGPIOS, ()) 0 );
54
+
55
+ /*
56
+ * GPIO callback implementation
57
+ */
58
+
59
+ struct gpio_port_callback {
60
+ struct gpio_callback callback;
61
+ voidFuncPtr handlers[max_ngpios];
62
+ gpio_port_pins_t pins;
63
+ const struct device * dev;
64
+ } port_callback[port_num] = {0 };
65
+
66
+ struct gpio_port_callback * find_gpio_port_callback (const struct device * dev)
67
+ {
68
+ for (size_t i=0 ; i<ARRAY_SIZE (port_callback); i++) {
69
+ if (port_callback[i].dev == dev) {
70
+ return &port_callback[i];
71
+ }
72
+ if (port_callback[i].dev == nullptr ) {
73
+ port_callback[i].dev = dev;
74
+ return &port_callback[i];
75
+ }
76
+ }
77
+
78
+ return nullptr ;
79
+ }
80
+
81
+ void setInterruptHandler (pin_size_t pinNumber, voidFuncPtr func)
82
+ {
83
+ struct gpio_port_callback * pcb = find_gpio_port_callback (arduino_pins[pinNumber]->port );
84
+
85
+ if (pcb) {
86
+ pcb->handlers [BIT (arduino_pins[pinNumber]->pin )] = func;
87
+ }
88
+ }
89
+
90
+ void handleGpioCallback (const struct device *port, struct gpio_callback *cb, uint32_t pins)
91
+ {
92
+ struct gpio_port_callback * pcb = (struct gpio_port_callback *)cb;
93
+
94
+ for (uint32_t i=0 ; i<max_ngpios; i++) {
95
+ if (pins & BIT (i)) {
96
+ pcb->handlers [BIT (i)]();
97
+ }
98
+ }
99
+ }
100
+
101
+ void pinModeImpl (pin_size_t pinNumber, gpio_flags_t pinmode, voidFuncPtr callback, gpio_flags_t intmode)
102
+ {
103
+ /* no use configure_dt to override PinMode config */
104
+ gpio_pin_configure (arduino_pins[pinNumber]->port , arduino_pins[pinNumber]->pin ,
105
+ (arduino_pins[pinNumber]->dt_flags & ~GPIO_MODE_MASK) | pinmode);
106
+
107
+ if (callback) {
108
+ struct gpio_port_callback * pcb = find_gpio_port_callback (arduino_pins[pinNumber]->port );
109
+ __ASSERT (pcb != nullptr , " " );
110
+
111
+ pcb->pins |= BIT (arduino_pins[pinNumber]->pin );
112
+ setInterruptHandler (pinNumber, callback);
113
+
114
+ gpio_pin_interrupt_configure_dt (arduino_pins[pinNumber], intmode);
115
+ gpio_init_callback (&pcb->callback , handleGpioCallback, pcb->pins );
116
+ gpio_add_callback (arduino_pins[pinNumber]->port , &pcb->callback );
117
+ }
118
+ }
119
+
120
+ gpio_flags_t pinMode2flags (PinMode pinMode) {
121
+ if (pinMode == INPUT) {
122
+ return (GPIO_INPUT | GPIO_ACTIVE_HIGH);
123
+ } else if (pinMode == INPUT_PULLUP) {
124
+ return (GPIO_INPUT | GPIO_PULL_UP | GPIO_ACTIVE_HIGH);
125
+ } else if (pinMode == INPUT_PULLDOWN) {
126
+ return (GPIO_INPUT | GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH);
127
+ } else if (pinMode == OUTPUT) {
128
+ return (GPIO_OUTPUT_LOW | GPIO_ACTIVE_HIGH);
129
+ } else if (pinMode == OUTPUT_OPENDRAIN) {
130
+ return (GPIO_OUTPUT_LOW | GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN);
131
+ } else {
132
+ __ASSERT (false , " Unknown PinMode" );
133
+ return 0 ;
134
+ }
135
+ }
136
+
137
+ gpio_flags_t pinStatus2flags (PinStatus status) {
138
+ if (status == LOW) {
139
+ return GPIO_INT_LEVEL_LOW;
140
+ }
141
+ else if (status == HIGH) {
142
+ return GPIO_INT_LEVEL_HIGH;
143
+ }
144
+ else if (status == CHANGE) {
145
+ return GPIO_INT_EDGE_BOTH;
146
+ }
147
+ else if (status == FALLING) {
148
+ return GPIO_INT_EDGE_FALLING;
149
+ }
150
+ else if (status == RISING) {
151
+ return GPIO_INT_EDGE_RISING;
152
+ } else {
153
+ __ASSERT (false , " Unknown PinStatus" );
154
+ return 0 ;
155
+ }
156
+ }
157
+
158
+ } // anonymous namespace
159
+
160
+
161
+ /*
162
+ * APIs
163
+ */
164
+
9
165
void yield (void ) {
10
166
k_yield ();
11
167
}
@@ -16,19 +172,14 @@ void yield(void) {
16
172
* A high physical level will be interpreted as value 1
17
173
*/
18
174
void pinMode (pin_size_t pinNumber, PinMode pinMode) {
19
- if (pinMode == INPUT) { // input mode
20
- gpio_pin_configure_dt (arduino_pins[pinNumber],
21
- GPIO_INPUT | GPIO_ACTIVE_HIGH);
22
- } else if (pinMode == INPUT_PULLUP) { // input with internal pull-up
23
- gpio_pin_configure_dt (arduino_pins[pinNumber],
24
- GPIO_INPUT | GPIO_PULL_UP | GPIO_ACTIVE_HIGH);
25
- } else if (pinMode == INPUT_PULLDOWN) { // input with internal pull-down
26
- gpio_pin_configure_dt (arduino_pins[pinNumber],
27
- GPIO_INPUT | GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH);
28
- } else if (pinMode == OUTPUT) { // output mode
29
- gpio_pin_configure_dt (arduino_pins[pinNumber],
30
- GPIO_OUTPUT_LOW | GPIO_ACTIVE_HIGH);
31
- }
175
+ gpio_flags_t pinstatus = 0 ;
176
+
177
+ #ifdef CONFIG_GPIO_GET_CONFIG
178
+ /* preserve GPIO interrupt configuration */
179
+ gpio_pin_get_config_dt (arduino_pins[pinNumber], &pinstatus);
180
+ #endif
181
+
182
+ pinModeImpl (pinNumber, pinMode2flags (pinMode), nullptr , (pinstatus & ~GPIO_MODE_MASK));
32
183
}
33
184
34
185
void digitalWrite (pin_size_t pinNumber, PinStatus status) {
@@ -49,3 +200,20 @@ unsigned long micros(void) {
49
200
50
201
unsigned long millis (void ) { return k_uptime_get_32 (); }
51
202
203
+ #ifdef CONFIG_GPIO_GET_CONFIG
204
+
205
+ void attachInterrupt (pin_size_t pinNumber, voidFuncPtr callback, PinStatus pinStatus)
206
+ {
207
+ gpio_flags_t pinmode = 0 ;
208
+
209
+ /* preserve GPIO configuration that configured by pinMode()*/
210
+ gpio_pin_get_config_dt (arduino_pins[pinNumber], &pinmode);
211
+ pinModeImpl (pinNumber, (pinmode & ~GPIO_INT_MASK), callback, pinStatus2flags (pinStatus));
212
+ }
213
+
214
+ void detachInterrupt (pin_size_t pinNumber)
215
+ {
216
+ setInterruptHandler (pinNumber, nullptr );
217
+ }
218
+
219
+ #endif
0 commit comments