4444#include "shared-bindings/pulseio/PulseIn.h"
4545#include "supervisor/shared/tick.h"
4646#include "supervisor/shared/translate.h"
47+ #include "supervisor/port.h"
4748
4849// This timer is shared amongst all PulseIn objects as a higher resolution clock.
4950static uint8_t refcount = 0 ;
5051static uint8_t pulsein_tc_index = 0xff ;
5152
5253volatile static uint32_t overflow_count = 0 ;
54+ volatile static uint32_t start_overflow = 0 ;
5355
5456void pulsein_timer_interrupt_handler (uint8_t index ) {
5557 if (index != pulsein_tc_index ) return ;
@@ -77,6 +79,8 @@ static void pulsein_set_config(pulseio_pulsein_obj_t* self, bool first_edge) {
7779}
7880
7981void pulsein_interrupt_handler (uint8_t channel ) {
82+ // Turn off interrupts while in handler
83+ common_hal_mcu_disable_interrupts ();
8084 // Grab the current time first.
8185 uint32_t current_overflow = overflow_count ;
8286 Tc * tc = tc_insts [pulsein_tc_index ];
@@ -88,10 +92,8 @@ void pulsein_interrupt_handler(uint8_t channel) {
8892 uint32_t current_count = tc -> COUNT16 .COUNT .reg ;
8993
9094 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 ;
9597 }
9698 if (self -> first_edge ) {
9799 self -> first_edge = false;
@@ -112,6 +114,13 @@ void pulsein_interrupt_handler(uint8_t channel) {
112114 if (total_diff < duration ) {
113115 duration = total_diff ;
114116 }
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+ }
115124
116125 uint16_t i = (self -> start + self -> len ) % self -> maxlen ;
117126 self -> buffer [i ] = duration ;
@@ -123,6 +132,7 @@ void pulsein_interrupt_handler(uint8_t channel) {
123132 }
124133 self -> last_overflow = current_overflow ;
125134 self -> last_count = current_count ;
135+ common_hal_mcu_enable_interrupts ();
126136}
127137
128138void pulsein_reset () {
@@ -264,9 +274,6 @@ void common_hal_pulseio_pulsein_resume(pulseio_pulsein_obj_t* self,
264274 // Make sure we're paused.
265275 common_hal_pulseio_pulsein_pause (self );
266276
267- // Reset erroring
268- self -> errored_too_fast = false;
269-
270277 // Send the trigger pulse.
271278 if (trigger_duration > 0 ) {
272279 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,
280287 self -> first_edge = true;
281288 self -> last_overflow = 0 ;
282289 self -> last_count = 0 ;
290+ self -> errored_too_fast = false;
283291 gpio_set_pin_function (self -> pin , GPIO_PIN_FUNCTION_A );
284292 uint32_t mask = 1 << self -> channel ;
285293 // Clear previous interrupt state and re-enable it.
@@ -300,12 +308,15 @@ uint16_t common_hal_pulseio_pulsein_popleft(pulseio_pulsein_obj_t* self) {
300308 if (self -> len == 0 ) {
301309 mp_raise_IndexError_varg (translate ("pop from empty %q" ), MP_QSTR_PulseIn );
302310 }
311+ if (self -> errored_too_fast ) {
312+ self -> errored_too_fast = 0 ;
313+ mp_raise_RuntimeError (translate ("Input taking too long" ));
314+ }
303315 common_hal_mcu_disable_interrupts ();
304316 uint16_t value = self -> buffer [self -> start ];
305317 self -> start = (self -> start + 1 ) % self -> maxlen ;
306318 self -> len -- ;
307319 common_hal_mcu_enable_interrupts ();
308-
309320 return value ;
310321}
311322
0 commit comments