// Mimicking Arduino's pulseIn function // return how long it takes a pin to go from HIGH to LOW or LOW to HIGH static uint32_t ppd42ns_pulse_in(const ppd42ns_context dev, bool high_low_value) { assert(dev != NULL); // we run for no more than 1 second at a time upm_clock_t max_time; upm_clock_t pulse_time; uint32_t total_pulse_time = 0; upm_clock_init(&max_time); bool pin_level; bool is_timing = false; do { pin_level = (bool)mraa_gpio_read(dev->gpio); if (!is_timing && pin_level == high_low_value) { // level is desired level, but not currently timing upm_clock_init(&pulse_time); is_timing = true; } else if (is_timing && pin_level != high_low_value) { // we started timing, but level changed total_pulse_time += upm_elapsed_us(&pulse_time); is_timing = false; } else { // not timing and/or level is not equal to desired level // so we "wait". upm_delay_us(10); } } while (upm_elapsed_ms(&max_time) < 1000); // 1 second if (is_timing) { // if we were still timing when the loop expired, add the // accumulated time. total_pulse_time += upm_elapsed_us(&pulse_time); } return total_pulse_time; }
void upm_delay_us(unsigned int time) { if (time <= 0) time = 1; #if defined(UPM_PLATFORM_LINUX) struct timespec delay_time; delay_time.tv_sec = time / 1000000; delay_time.tv_nsec = (time % 1000000) * 1000; // here we spin until the delay is complete - detecting signals // and continuing where we left off while (nanosleep(&delay_time, &delay_time) && errno == EINTR) ; // loop #elif defined(UPM_PLATFORM_ZEPHYR) # if KERNEL_VERSION_MAJOR == 1 && KERNEL_VERSION_MINOR >= 6 // we will use a upm_clock to do microsecond timings here as k_timer has // only a millisecond resolution. So we init a clock and spin. upm_clock_t timer; upm_clock_init(&timer); while (upm_elapsed_us(&timer) < time) ; // spin # else struct nano_timer timer; void *timer_data[1]; nano_timer_init(&timer, timer_data); nano_timer_start(&timer, USEC(time) + 1); nano_timer_test(&timer, TICKS_UNLIMITED); # endif #endif }