@@ -40,24 +40,10 @@ void gpio_mode(pinnum_t pin, bool input, bool output, bool pullup, bool pulldown
4040 }
4141 gpio_config (&conf);
4242}
43- void IRAM_ATTR gpio_set_interrupt_type (pinnum_t pin, int mode) {
44- gpio_int_type_t type = GPIO_INTR_DISABLE;
45- // Do not use switch here because it is not IRAM_ATTR safe
46- if (mode == Pin::RISING_EDGE) {
47- type = GPIO_INTR_POSEDGE;
48- } else if (mode == Pin::FALLING_EDGE) {
49- type = GPIO_INTR_NEGEDGE;
50- } else if (mode == Pin::EITHER_EDGE) {
51- type = GPIO_INTR_ANYEDGE;
52- }
53- gpio_set_intr_type ((gpio_num_t )pin, type);
54- }
55-
43+ #if 0
5644void gpio_add_interrupt(pinnum_t pin, int mode, void (*callback)(void*), void* arg) {
5745 gpio_install_isr_service(ESP_INTR_FLAG_IRAM); // Will return an err if already called
5846
59- gpio_set_interrupt_type (pin, mode);
60-
6147 gpio_num_t gpio = (gpio_num_t)pin;
6248 gpio_isr_handler_add(gpio, callback, arg);
6349
@@ -81,6 +67,100 @@ void gpio_route(pinnum_t pin, uint32_t signal) {
8167 gpio_set_direction(gpio, (gpio_mode_t)GPIO_MODE_DEF_OUTPUT);
8268 gpio_matrix_out(gpio, signal, 0, 0);
8369}
70+ #endif
71+
72+ typedef uint64_t gpio_mask_t ;
73+
74+ // Can be used to display gpio_mask_t data for debugging
75+ static const char * g_to_hex (gpio_mask_t n) {
76+ static char hexstr[24 ];
77+ snprintf (hexstr, 22 , " 0x%llx" , n);
78+ return hexstr;
79+ }
80+
81+ static gpio_mask_t gpios_inverted = 0 ; // GPIOs that are active low
82+ static gpio_mask_t gpios_interest = 0 ; // GPIOs with an action
83+ static gpio_mask_t gpios_current = 0 ; // The last GPIO action events that were sent
84+
85+ static int32_t gpio_next_event_ticks[GPIO_NUM_MAX + 1 ] = { 0 };
86+ static int32_t gpio_deltat_ticks[GPIO_NUM_MAX + 1 ] = { 0 };
87+
88+ // Do not send events for changes that occur too soon
89+ static void gpio_set_rate_limit (int gpio_num, uint32_t ms) {
90+ gpio_deltat_ticks[gpio_num] = ms * portTICK_PERIOD_MS;
91+ }
92+
93+ static inline gpio_mask_t get_gpios () {
94+ return ((((uint64_t )REG_READ (GPIO_IN1_REG)) << 32 ) | REG_READ (GPIO_IN_REG)) ^ gpios_inverted;
95+ }
96+ static gpio_mask_t gpio_mask (int gpio_num) {
97+ return 1ULL << gpio_num;
98+ }
99+ static inline bool gpio_is_active (int gpio_num) {
100+ return get_gpios () & gpio_mask (gpio_num);
101+ }
102+ static void gpios_update (gpio_mask_t & gpios, int gpio_num, bool active) {
103+ if (active) {
104+ gpios |= gpio_mask (gpio_num);
105+ } else {
106+ gpios &= ~gpio_mask (gpio_num);
107+ }
108+ }
109+
110+ static gpio_dispatch_t gpioActions[GPIO_NUM_MAX + 1 ] = { nullptr };
111+ static void * gpioArgs[GPIO_NUM_MAX + 1 ];
112+
113+ void gpio_set_action (int gpio_num, gpio_dispatch_t action, void * arg, bool invert) {
114+ gpioActions[gpio_num] = action;
115+ gpioArgs[gpio_num] = arg;
116+ gpio_mask_t mask = gpio_mask (gpio_num);
117+ gpios_update (gpios_interest, gpio_num, true );
118+ gpios_update (gpios_inverted, gpio_num, invert);
119+ gpio_set_rate_limit (gpio_num, 5 );
120+ bool active = gpio_is_active (gpio_num);
121+
122+ // Set current to the opposite of the current state so the first poll will send the current state
123+ gpios_update (gpios_current, gpio_num, !active);
124+ }
125+ void gpio_clear_action (int gpio_num) {
126+ gpioActions[gpio_num] = nullptr ;
127+ gpioArgs[gpio_num] = nullptr ;
128+ gpios_update (gpios_interest, gpio_num, false );
129+ }
130+
131+ static void gpio_send_action (int gpio_num, bool active) {
132+ auto end_ticks = gpio_next_event_ticks[gpio_num];
133+ int32_t this_ticks = int32_t (xTaskGetTickCount ());
134+ if (end_ticks == 0 || ((this_ticks - end_ticks) > 0 )) {
135+ end_ticks = this_ticks + gpio_deltat_ticks[gpio_num];
136+ if (end_ticks == 0 ) {
137+ end_ticks = 1 ;
138+ }
139+ gpio_next_event_ticks[gpio_num] = end_ticks;
140+
141+ gpio_dispatch_t action = gpioActions[gpio_num];
142+ if (action) {
143+ action (gpio_num, gpioArgs[gpio_num], active);
144+ }
145+ gpios_update (gpios_current, gpio_num, active);
146+ }
147+ }
148+
149+ void poll_gpios () {
150+ gpio_mask_t gpios_active = get_gpios ();
151+ gpio_mask_t gpios_changed = (gpios_active ^ gpios_current) & gpios_interest;
152+ if (gpios_changed) {
153+ int zeros;
154+ while ((zeros = __builtin_clzll (gpios_changed)) != 64 ) {
155+ int gpio_num = 63 - zeros;
156+ gpio_send_action (gpio_num, gpios_active & gpio_mask (gpio_num));
157+ // Remove bit from mask so clzll will find the next one
158+ gpios_update (gpios_changed, gpio_num, false );
159+ }
160+ }
161+ }
162+
163+ // Support functions for gpio_dump
84164static bool exists (gpio_num_t gpio) {
85165 if (gpio == 20 ) {
86166 // GPIO20 is listed in GPIO_PIN_MUX_REG[] but it is only
@@ -378,7 +458,7 @@ struct gpio_matrix_t {
378458 { 228 , " " , " ig_in_func228" , false },
379459 { -1 , " " , " " , false } };
380460
381- const char * out_sel_name (int function) {
461+ static const char * out_sel_name (int function) {
382462 gpio_matrix_t * p;
383463 for (p = gpio_matrix; p->num != -1 ; ++p) {
384464 if (p->num == function) {
@@ -388,7 +468,7 @@ const char* out_sel_name(int function) {
388468 return " " ;
389469}
390470
391- void show_matrix (Print& out) {
471+ static void show_matrix (Print& out) {
392472 gpio_matrix_t * p;
393473 for (p = gpio_matrix; p->num != -1 ; ++p) {
394474 uint32_t in_sel = gpio_in_sel (p->num );
@@ -432,63 +512,3 @@ void gpio_dump(Print& out) {
432512 out << " Input Matrix\n " ;
433513 show_matrix (out);
434514}
435-
436- typedef uint64_t gpio_mask_t ;
437- static gpio_mask_t gpio_inverts = 0 ;
438- static gpio_mask_t gpio_interest = 0 ;
439- static gpio_mask_t gpio_current = 0 ;
440- void IRAM_ATTR check_switches () {
441- gpio_mask_t gpio_this = (((uint64_t )REG_READ (GPIO_IN_REG)) << 32 ) | REG_READ (GPIO_IN1_REG);
442- if (gpio_this != gpio_current) {
443- gpio_mask_t gpio_changes = (gpio_this ^ gpio_current) & gpio_interest;
444- int bitno;
445- while (bitno = __builtin_ffsll (gpio_changes)) {
446- --bitno;
447- bool isActive = (gpio_this ^ gpio_inverts) & (1ULL << bitno);
448- // protocol_send_event_from_ISR(&pin_changes, (void*)(isActive ? bitno : -bitno));
449- protocol_send_event_from_ISR (&motionCancelEvent, (void *)(isActive ? bitno : -bitno));
450- }
451- gpio_current = gpio_this;
452- }
453- ++gpio_interest;
454- }
455- static gpio_dispatch_t gpioActions[GPIO_NUM_MAX + 1 ];
456- static void * gpioArgs[GPIO_NUM_MAX + 1 ];
457- void gpio_set_action (int gpio_num, gpio_dispatch_t action, void * arg, bool invert) {
458- gpioActions[gpio_num] = action;
459- gpioArgs[gpio_num] = arg;
460- gpio_mask_t mask = 1ULL << gpio_num;
461- gpio_interest |= mask;
462- if (invert) {
463- gpio_inverts |= mask;
464- } else {
465- gpio_inverts &= ~mask;
466- }
467- }
468- void gpio_clear_action (int gpio_num) {
469- gpioActions[gpio_num] = nullptr ;
470- gpioArgs[gpio_num] = nullptr ;
471- gpio_mask_t mask = 1ULL << gpio_num;
472- gpio_interest &= ~mask;
473- }
474- void poll_gpios () {
475- gpio_mask_t gpio_this = (((uint64_t )REG_READ (GPIO_IN1_REG)) << 32 ) | REG_READ (GPIO_IN_REG);
476-
477- gpio_mask_t gpio_changes = (gpio_this ^ gpio_current) & gpio_interest;
478- if (gpio_changes) {
479- gpio_mask_t gpio_active = gpio_this ^ gpio_inverts;
480- int zeros;
481- while ((zeros = __builtin_clzll (gpio_changes)) != 64 ) {
482- int gpio_num = 63 - zeros;
483- gpio_mask_t mask = 1ULL << gpio_num;
484- bool isActive = gpio_active & mask;
485- // Uart0 << gpio_num << " " << isActive << "\n";
486- gpio_dispatch_t action = gpioActions[gpio_num];
487- if (action) {
488- action (gpio_num, gpioArgs[gpio_num], isActive);
489- }
490- gpio_changes &= ~mask;
491- }
492- }
493- gpio_current = gpio_this;
494- }
0 commit comments