44
44
#include "shared-bindings/pulseio/PulseIn.h"
45
45
#include "supervisor/shared/tick.h"
46
46
#include "supervisor/shared/translate.h"
47
+ #include "supervisor/port.h"
47
48
48
49
// This timer is shared amongst all PulseIn objects as a higher resolution clock.
49
50
static uint8_t refcount = 0 ;
50
51
static uint8_t pulsein_tc_index = 0xff ;
51
52
52
53
volatile static uint32_t overflow_count = 0 ;
54
+ volatile static uint32_t start_overflow = 0 ;
53
55
54
56
void pulsein_timer_interrupt_handler (uint8_t index ) {
55
57
if (index != pulsein_tc_index ) return ;
@@ -77,6 +79,8 @@ static void pulsein_set_config(pulseio_pulsein_obj_t* self, bool first_edge) {
77
79
}
78
80
79
81
void pulsein_interrupt_handler (uint8_t channel ) {
82
+ // Turn off interrupts while in handler
83
+ common_hal_mcu_disable_interrupts ();
80
84
// Grab the current time first.
81
85
uint32_t current_overflow = overflow_count ;
82
86
Tc * tc = tc_insts [pulsein_tc_index ];
@@ -88,10 +92,8 @@ void pulsein_interrupt_handler(uint8_t channel) {
88
92
uint32_t current_count = tc -> COUNT16 .COUNT .reg ;
89
93
90
94
pulseio_pulsein_obj_t * self = get_eic_channel_data (channel );
91
- if (!supervisor_background_tasks_ok () || self -> errored_too_fast ) {
92
- self -> errored_too_fast = true;
93
- common_hal_pulseio_pulsein_pause (self );
94
- return ;
95
+ if (self -> len == 0 ) {
96
+ start_overflow = overflow_count ;
95
97
}
96
98
if (self -> first_edge ) {
97
99
self -> first_edge = false;
@@ -112,6 +114,13 @@ void pulsein_interrupt_handler(uint8_t channel) {
112
114
if (total_diff < duration ) {
113
115
duration = total_diff ;
114
116
}
117
+ //check if the input is taking too long, 15 timer overflows is approx 1 second
118
+ if (current_overflow - start_overflow > 15 ) {
119
+ self -> errored_too_fast = true;
120
+ common_hal_pulseio_pulsein_pause (self );
121
+ common_hal_mcu_enable_interrupts ();
122
+ return ;
123
+ }
115
124
116
125
uint16_t i = (self -> start + self -> len ) % self -> maxlen ;
117
126
self -> buffer [i ] = duration ;
@@ -123,6 +132,7 @@ void pulsein_interrupt_handler(uint8_t channel) {
123
132
}
124
133
self -> last_overflow = current_overflow ;
125
134
self -> last_count = current_count ;
135
+ common_hal_mcu_enable_interrupts ();
126
136
}
127
137
128
138
void pulsein_reset () {
@@ -264,9 +274,6 @@ void common_hal_pulseio_pulsein_resume(pulseio_pulsein_obj_t* self,
264
274
// Make sure we're paused.
265
275
common_hal_pulseio_pulsein_pause (self );
266
276
267
- // Reset erroring
268
- self -> errored_too_fast = false;
269
-
270
277
// Send the trigger pulse.
271
278
if (trigger_duration > 0 ) {
272
279
gpio_set_pin_pull_mode (self -> pin , GPIO_PULL_OFF );
@@ -280,6 +287,7 @@ void common_hal_pulseio_pulsein_resume(pulseio_pulsein_obj_t* self,
280
287
self -> first_edge = true;
281
288
self -> last_overflow = 0 ;
282
289
self -> last_count = 0 ;
290
+ self -> errored_too_fast = false;
283
291
gpio_set_pin_function (self -> pin , GPIO_PIN_FUNCTION_A );
284
292
uint32_t mask = 1 << self -> channel ;
285
293
// Clear previous interrupt state and re-enable it.
@@ -300,12 +308,15 @@ uint16_t common_hal_pulseio_pulsein_popleft(pulseio_pulsein_obj_t* self) {
300
308
if (self -> len == 0 ) {
301
309
mp_raise_IndexError_varg (translate ("pop from empty %q" ), MP_QSTR_PulseIn );
302
310
}
311
+ if (self -> errored_too_fast ) {
312
+ self -> errored_too_fast = 0 ;
313
+ mp_raise_RuntimeError (translate ("Input taking too long" ));
314
+ }
303
315
common_hal_mcu_disable_interrupts ();
304
316
uint16_t value = self -> buffer [self -> start ];
305
317
self -> start = (self -> start + 1 ) % self -> maxlen ;
306
318
self -> len -- ;
307
319
common_hal_mcu_enable_interrupts ();
308
-
309
320
return value ;
310
321
}
311
322
0 commit comments