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_groups (const int sum, const First&) { return sum; }
27
+
28
+ template <class First , class Second , class ... Rest>
29
+ constexpr int count_groups (const int sum, const First& first, const Second& second, const Rest&... rest)
30
+ {
31
+ return count_groups (first == second ? sum : sum + 1 , second, rest...);
32
+ }
33
+
34
+ template <class First >
35
+ constexpr int max_in_list (const int max, const First&) { return max; }
36
+
37
+ template <class First , class ... Rest>
38
+ constexpr int max_in_list (const int max, const First& first, const Rest&... rest)
39
+ {
40
+ return max_in_list ((max >= first) ? max : first, rest...);
41
+ }
42
+
43
+ const int port_num = count_groups(0 , LISTIFY(DIGITAL_PIN_MAX, GPIO_ELEM, ()) nullptr );
44
+ const int max_ngpios = max_in_list(0 , LISTIFY(DIGITAL_PIN_MAX, GPIO_NGPIOS, ()) 0 );
45
+
46
+ /*
47
+ * GPIO callback implementation
48
+ */
49
+
50
+ struct gpio_port_callback {
51
+ struct gpio_callback callback;
52
+ voidFuncPtr handlers[max_ngpios];
53
+ gpio_port_pins_t pins;
54
+ const struct device * dev;
55
+ } port_callback[port_num] = {0 };
56
+
57
+ struct gpio_port_callback * find_gpio_port_callback (const struct device * dev)
58
+ {
59
+ for (size_t i=0 ; i<ARRAY_SIZE (port_callback); i++) {
60
+ if (port_callback[i].dev == dev) {
61
+ return &port_callback[i];
62
+ }
63
+ if (port_callback[i].dev == nullptr ) {
64
+ port_callback[i].dev = dev;
65
+ return &port_callback[i];
66
+ }
67
+ }
68
+
69
+ return nullptr ;
70
+ }
71
+
72
+ void setInterruptHandler (pin_size_t pinNumber, voidFuncPtr func)
73
+ {
74
+ struct gpio_port_callback * pcb = find_gpio_port_callback (arduino_pins[pinNumber]->port );
75
+
76
+ if (pcb) {
77
+ pcb->handlers [BIT (arduino_pins[pinNumber]->pin )] = func;
78
+ }
79
+ }
80
+
81
+ void handleGpioCallback (const struct device *port, struct gpio_callback *cb, uint32_t pins)
82
+ {
83
+ struct gpio_port_callback * pcb = (struct gpio_port_callback *)cb;
84
+
85
+ for (uint32_t i=0 ; i<max_ngpios; i++) {
86
+ if (pins & BIT (i)) {
87
+ pcb->handlers [BIT (i)]();
88
+ }
89
+ }
90
+ }
91
+
92
+ void pinModeImpl (pin_size_t pinNumber, gpio_flags_t pinmode, voidFuncPtr callback, gpio_flags_t intmode)
93
+ {
94
+ /* no use configure_dt to override PinMode config */
95
+ gpio_pin_configure (arduino_pins[pinNumber]->port , arduino_pins[pinNumber]->pin ,
96
+ (arduino_pins[pinNumber]->dt_flags & ~GPIO_MODE_MASK) | pinmode);
97
+
98
+ if (callback) {
99
+ struct gpio_port_callback * pcb = find_gpio_port_callback (arduino_pins[pinNumber]->port );
100
+ __ASSERT (pcb != nullptr , " " );
101
+
102
+ pcb->pins |= BIT (arduino_pins[pinNumber]->pin );
103
+ setInterruptHandler (pinNumber, callback);
104
+
105
+ gpio_pin_interrupt_configure_dt (arduino_pins[pinNumber], intmode);
106
+ gpio_init_callback (&pcb->callback , handleGpioCallback, pcb->pins );
107
+ gpio_add_callback (arduino_pins[pinNumber]->port , &pcb->callback );
108
+ }
109
+ }
110
+
111
+ gpio_flags_t pinMode2flags (PinMode pinMode) {
112
+ if (pinMode == INPUT) {
113
+ return (GPIO_INPUT | GPIO_ACTIVE_HIGH);
114
+ } else if (pinMode == INPUT_PULLUP) {
115
+ return (GPIO_INPUT | GPIO_PULL_UP | GPIO_ACTIVE_HIGH);
116
+ } else if (pinMode == INPUT_PULLDOWN) {
117
+ return (GPIO_INPUT | GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH);
118
+ } else if (pinMode == OUTPUT) {
119
+ return (GPIO_OUTPUT_LOW | GPIO_ACTIVE_HIGH);
120
+ } else if (pinMode == OUTPUT_OPENDRAIN) {
121
+ return (GPIO_OUTPUT_LOW | GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN);
122
+ } else {
123
+ __ASSERT (false , " Unknown PinMode" );
124
+ return 0 ;
125
+ }
126
+ }
127
+
128
+ gpio_flags_t pinStatus2flags (PinStatus status) {
129
+ if (status == LOW) {
130
+ return GPIO_INT_LEVEL_LOW;
131
+ }
132
+ else if (status == HIGH) {
133
+ return GPIO_INT_LEVEL_HIGH;
134
+ }
135
+ else if (status == CHANGE) {
136
+ return GPIO_INT_EDGE_BOTH;
137
+ }
138
+ else if (status == FALLING) {
139
+ return GPIO_INT_EDGE_FALLING;
140
+ }
141
+ else if (status == RISING) {
142
+ return GPIO_INT_EDGE_RISING;
143
+ } else {
144
+ __ASSERT (false , " Unknown PinStatus" );
145
+ return 0 ;
146
+ }
147
+ }
148
+
149
+ } // anonymous namespace
150
+
151
+
152
+ /*
153
+ * APIs
154
+ */
155
+
9
156
void yield (void ) {
10
157
k_yield ();
11
158
}
@@ -16,19 +163,14 @@ void yield(void) {
16
163
* A high physical level will be interpreted as value 1
17
164
*/
18
165
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
- }
166
+ gpio_flags_t pinstatus = 0 ;
167
+
168
+ #ifdef CONFIG_GPIO_GET_CONFIG
169
+ /* preserve GPIO interrupt configuration */
170
+ gpio_pin_get_config_dt (arduino_pins[pinNumber], &pinstatus);
171
+ #endif
172
+
173
+ pinModeImpl (pinNumber, pinMode2flags (pinMode), nullptr , (pinstatus & ~GPIO_MODE_MASK));
32
174
}
33
175
34
176
void digitalWrite (pin_size_t pinNumber, PinStatus status) {
@@ -49,3 +191,20 @@ unsigned long micros(void) {
49
191
50
192
unsigned long millis (void ) { return k_uptime_get_32 (); }
51
193
194
+ #ifdef CONFIG_GPIO_GET_CONFIG
195
+
196
+ void attachInterrupt (pin_size_t pinNumber, voidFuncPtr callback, PinStatus pinStatus)
197
+ {
198
+ gpio_flags_t pinmode = 0 ;
199
+
200
+ /* preserve GPIO configuration that configured by pinMode()*/
201
+ gpio_pin_get_config_dt (arduino_pins[pinNumber], &pinmode);
202
+ pinModeImpl (pinNumber, (pinmode & ~GPIO_INT_MASK), callback, pinStatus2flags (pinStatus));
203
+ }
204
+
205
+ void detachInterrupt (pin_size_t pinNumber)
206
+ {
207
+ setInterruptHandler (pinNumber, nullptr );
208
+ }
209
+
210
+ #endif
0 commit comments