Esp32 + ulp + vl53l0x

Доброго времени суток читающим. Сразу к сути. Есть ESP32 и VL53L0X. Преследую цель сделать счетчик посетителей с работой от АКБ с помощью этих компонентов. Так вот наткнулся на проблему: работа пина gpio1 (он же пин перырвания или int), при переходе в спящий режим ESP32. Логика работы проста: включаем все, настраиваем VL53L0X, отправляем основные ядра спать, а с помощью ULP ядра опрашиваем GPIO1 от датчика. Когда ловим высокий или низкий уровень, то инкрементируем некий счетчик внутри RTC памяти. Спустя n-ое кол-во времени просыпаемся и выводим эта значение на oled/serial/web платформу. Загвоздка в том, что при появлении какой-либо уровя на GPIO1 он не сбрасывается (прим.: Подставил руку → получил высокий уровень на GPIO1 → убрал руку, а высокий уровень остался (а должен был сброситься)). Пишу в среде arduino IDE, для лидара использую библиотеку от adafruit (тк она единственная поддерживает работу с GPIO1). Прошу помощи/совета как это исправить или натыкать носом что я не так сделал. API от лидара уже всю прочитал в доль и поперек, там ответа не нашел. Гугление так же не привело к желаемом результату. Код прилагаю:

#include <sys/time.h>
#include <Adafruit_VL53L0X.h>
#include <Adafruit_SSD1306.h>
#include <Wire.h>
#include "esp32/ulp.h"
#include "esp_sleep.h"
#include "driver/rtc_io.h"
#include "nvs.h"
#include "nvs_flash.h"

#define WAKE_UP_TIME 30   // Wake up time for main cpu (s)
#define WORKING_TIME 10   // Working time for main cpu (s)
#define ULP_UP_TIME  10   // Wake up time for ULP (ms)
#define VL53LOX_ShutdownPin 16
#define VL53LOX_InterruptPin 14

uint16_t distanceStr;
VL53L0X_RangingMeasurementData_t measure;

static RTC_DATA_ATTR struct timeval sleep_enter_time;
int32_t cpuCount = 0;     // Суммарные данные со счетчика воды
int32_t ulp_count = 0;      // Данные, посчитанные ULP сопроцессором
uint32_t timer1;

volatile byte VL53LOX_State = LOW;
Adafruit_VL53L0X lox = Adafruit_VL53L0X();
Adafruit_VL53L0X::VL53L0X_Sense_config_t long_range = Adafruit_VL53L0X::VL53L0X_SENSE_LONG_RANGE;
TwoWire *i2c = &Wire;


Adafruit_SSD1306 display(128, 32, &Wire, -1);

// Код для ULP процессора (бесконечный цикл)
const ulp_insn_t program[] = {
  I_MOVI(R0, 0),      // Сброс значения регистра R0
  I_MOVI(R1, 0),      // Сброс значения регистра R1
  I_MOVI(R3, 0),      // Сброс значения регистра R3
  M_LABEL(1),         // Метка №1
  I_RD_REG(RTC_GPIO_IN_REG, 25, 25),  // Чтение состояния ножки входа
  I_SUBR(R2, R1, R0), // Находим разность между новым состоянием ножки и предыдущим
  M_BXZ(2),           // Если АЛУ - 0, то переходим в конец цикла, иначе инкрементируем счетчик импульсов
  I_ADDI(R3, R3, 1),  // Увеличиваем на 1 счетчик импульсов
  M_LABEL(2),         // Метка №2
  I_MOVR(R1, R0),     // Сохраняем значение состояния ножки
  I_MOVI(R2, 16),     // Устанавливаем адрес памяти, куда будем выводить значение счетчика
  I_ST(R3, R2, 0),    // Выводим в память RTC значения счетчика
  M_BX(1),            // Возвращаемся в начало цикла программы
  I_HALT()
};

void sensInit(){
  pinMode(VL53LOX_ShutdownPin, INPUT_PULLUP);
  pinMode(VL53LOX_InterruptPin, INPUT_PULLUP);
  digitalWrite(VL53LOX_InterruptPin, LOW);
  //attachInterrupt(digitalPinToInterrupt(VL53LOX_InterruptPin), VL53LOXISR,
  //                CHANGE);
  //pinMode(LED_BUILTIN, OUTPUT);
  //digitalWrite(LED_BUILTIN, LOW);

  // if lox.begin failes its becasue it was a warm boot and the VL53LOX is in
  // continues mesurement mode we can use an IO pin to reset the device in case
  // we get stuck in this mode

  while (!lox.begin(0x29,false, i2c, long_range) ) {
    Serial.println(F("Failed to boot VL53L0X"));
    Serial.println("Adafruit VL53L0X XShut set Low to Force HW Reset");
    digitalWrite(VL53LOX_ShutdownPin, LOW);
    delay(100);
    digitalWrite(VL53LOX_ShutdownPin, HIGH);
    Serial.println("Adafruit VL53L0X XShut set high to Allow Boot");
    delay(100);
  }

  lox.setGpioConfig(VL53L0X_DEVICEMODE_SINGLE_RANGING,
                    VL53L0X_GPIOFUNCTIONALITY_THRESHOLD_CROSSED_LOW,
                    VL53L0X_INTERRUPTPOLARITY_HIGH);
  
  FixPoint1616_t LowThreashHold = (1000 * 65536.0);
  lox.setInterruptThresholds(LowThreashHold, true);

  // Enable Continous Measurement Mode
  lox.setDeviceMode(VL53L0X_DEVICEMODE_CONTINUOUS_RANGING, false);
  lox.clearInterruptMask(true);
  
  Serial.println("StartMeasurement... ");
  lox.startMeasurement();

  
}

void setup() {
 // Инициализация UART
  Serial.begin(115200);
  delay(500);
  Wire.begin(5,4);

  gpio_num_t gpio_num = GPIO_NUM_14;
  rtc_gpio_set_direction(gpio_num, RTC_GPIO_MODE_INPUT_ONLY);
  rtc_gpio_pulldown_dis(gpio_num);
  rtc_gpio_pullup_dis(gpio_num);
  rtc_gpio_pullup_en(gpio_num);
  //rtc_gpio_hold_en(gpio_num);


  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.display();

  // Измерение времени сна
  struct timeval now;
  gettimeofday(&now, NULL);
  int sleep_time_ms = (now.tv_sec - sleep_enter_time.tv_sec) * 1000 + (now.tv_usec - sleep_enter_time.tv_usec) / 1000;

  // Определение, по какому событию проснулись
  switch (esp_sleep_get_wakeup_cause()) {
    case ESP_SLEEP_WAKEUP_TIMER: {
        Serial.println();
        Serial.print("Wake up from timer. Time spent in deep sleep: ");
        Serial.print(sleep_time_ms);
        Serial.println(" ms");
        Serial.println();
        break;
      }
    case ESP_SLEEP_WAKEUP_UNDEFINED:
    default: {
        Serial.println();
        Serial.println("Not a deep sleep reset");
        Serial.println();
        memset(RTC_SLOW_MEM, 0, CONFIG_ULP_COPROC_RESERVE_MEM);
      }
  }

  // Считывание показаний из ULP сопроцессора
  ulp_count = (RTC_SLOW_MEM[16] & 0xffff) / 2;

  // Очистка памяти RTC для ULP сопроцессора
  memset(RTC_SLOW_MEM, 0, CONFIG_ULP_COPROC_RESERVE_MEM);

  // Новый запуск выполнения программы в ULP сопроцессоре
  size_t load_addr = 0;
  size_t size = sizeof(program) / sizeof(ulp_insn_t);
  ulp_process_macros_and_load(load_addr, program, &size);
  ulp_run(load_addr);

  // Инициализация NVS памяти
  esp_err_t err = nvs_flash_init();
  if (err == ESP_ERR_NVS_NO_FREE_PAGES) {
    ESP_ERROR_CHECK(nvs_flash_erase());
    err = nvs_flash_init();
  }
  ESP_ERROR_CHECK(err);

  // Считывание последних данных их NVS памяти, сложение с новыми данными и запись в NVS
  cpuCount = 0;
  nvs_handle my_nvs_handle;
  Serial.print("Opening Non-Volatile Storage (NVS) handle... ");

  // "Открытие" NVS памяти для чтения/записи
  err = nvs_open("storage", NVS_READWRITE, &my_nvs_handle);
  if (err != ESP_OK) {
    Serial.print("Error opening NVS handle: ");
    Serial.println(err);
  } else {
    Serial.println("Done");
    Serial.print("Reading cpu counter from NVS ... ");

    // Считывание поля из NVS памяти
    err = nvs_get_i32(my_nvs_handle, "cpuCount", &cpuCount);
    switch (err) {
      case ESP_OK:
        Serial.println("Done");
        Serial.print("cpu counter = ");
        Serial.println(cpuCount);
        break;
      case ESP_ERR_NVS_NOT_FOUND:
        Serial.println("The value is not initialized yet!");
        break;
      default :
        Serial.print("Error reading: ");
        Serial.println(err);
    }

    // Сложение данных из памяти и из ULP
    cpuCount = cpuCount + ulp_count;

    // Запись поля данных в NVS память
    Serial.print("Updating restart counter in NVS ... ");
    err = nvs_set_i32(my_nvs_handle, "cpuCount", cpuCount);
    if (err != ESP_OK) {
      Serial.print("Error: ");
      Serial.println(err);
    } else {
      Serial.println("Done");
    }
    err = nvs_commit(my_nvs_handle);
    if (err != ESP_OK) {
      Serial.print("Error: ");
      Serial.println(err);
    } else {
      Serial.println("Done");
    }

    // Закрытие дескриптора NVS памяти
    nvs_close(my_nvs_handle);
  }

  Serial.print("cpu counter: ");
  Serial.println(cpuCount);

  // Чтение значения счетчика из разделяемой памяти после пробуждения
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 0);
  display.println("Count:");
  display.println(cpuCount);
  Serial.println(cpuCount);
  display.display();

  sensInit();

  //if (VL53LOX_State == LOW) {
    
    // Serial.print("Reading a measurement... ");
    // lox.getRangingMeasurement(
    //     &measure, false); // pass in 'true' to get debug data printout!
    
    // if (measure.RangeStatus != 4) {
    //   distanceStr = measure.RangeMilliMeter; // phase failures have incorrect data
    //   Serial.print("Distance (mm): ");
    //   Serial.println(distanceStr);
    // } else {
    //   Serial.println(" out of range ");
    // }
    // // you have to clear the interrupt to get triggered again
    // lox.clearInterruptMask(false);

  //} 


  // Задержка перед уходом в спящий режим (только для тестов)
  delay(WORKING_TIME * 1000);

  // Установка таймера сна
  Serial.print("Enabling timer wakeup: ");
  Serial.println(WAKE_UP_TIME);
  esp_sleep_enable_timer_wakeup(WAKE_UP_TIME * 1000000);

  // Входим в режим сна
  Serial.println("Entering deep sleep");
  gettimeofday(&sleep_enter_time, NULL);
  esp_deep_sleep_start();
  
}

void loop() {
  //if (digitalRead(VL53LOX_InterruptPin) == HIGH){
  //  Serial.println("Handled sensor GPIO");
  //}
  // Этот код никогда не выполнится, так как после 10 секунд микроконтроллер переходит в режим сна
}```

А снимать прерывание в датчике кто будет? Тут библиотекой не обойдешься, придется читать доку.
И я бы искренне посоветовал брать есп серии C, где ulp программируется на нормальном языке.

мне казалось я видел в доках, что прерывание само снимается, когда результат измерения готов на датчике. или я ошибаюсь?
Да и в доках почему-то не написано, в какой регистр че записывать надо чтоб сделать то или иное действие.
На счет С версии понимаю, что использовать RISC-V ULP куда приятнее, однако достать ее затруднительно мне в данный момент.
Может быть знаете альтернативы используемому датчику, чтоб не гемороиться?

с чего бы ему сниматься в тот момент, когда он должен установиться, когда нужно вмешательство проца