101 lines
2.6 KiB
C++
101 lines
2.6 KiB
C++
// Enable pin remapping in this file, so pin constants are meaningful
|
|
#undef ARDUINO_CORE_BUILD
|
|
|
|
#include "Arduino.h"
|
|
|
|
#include "double_tap.h"
|
|
|
|
#include <esp_system.h>
|
|
#include <esp_ota_ops.h>
|
|
#include <esp_partition.h>
|
|
|
|
extern "C" {
|
|
void initVariant() {
|
|
// nothing to do
|
|
}
|
|
}
|
|
|
|
// global, accessible from recovery sketch
|
|
bool _recovery_marker_found; // double tap detected
|
|
bool _recovery_active; // running from factory partition
|
|
|
|
#define DELAY_US 10000
|
|
#define FADESTEP 8
|
|
static void rgb_pulse_delay(void) {
|
|
// Bv R^ G x
|
|
int widths[4] = {192, 64, 0, 0};
|
|
int dec_led = 0;
|
|
|
|
// initialize RGB signals from weak pinstraps
|
|
pinMode(LED_RED, OUTPUT);
|
|
pinMode(LED_GREEN, OUTPUT);
|
|
pinMode(LED_BLUE, OUTPUT);
|
|
while (dec_led < 3) {
|
|
widths[dec_led] -= FADESTEP;
|
|
widths[dec_led + 1] += FADESTEP;
|
|
if (widths[dec_led] <= 0) {
|
|
widths[dec_led] = 0;
|
|
dec_led = dec_led + 1;
|
|
widths[dec_led] = 255;
|
|
}
|
|
|
|
analogWrite(LED_RED, 255 - widths[1]);
|
|
analogWrite(LED_GREEN, 255 - widths[2]);
|
|
analogWrite(LED_BLUE, 255 - widths[0]);
|
|
delayMicroseconds(DELAY_US);
|
|
}
|
|
|
|
// reset pins to digital HIGH before leaving
|
|
digitalWrite(LED_RED, HIGH);
|
|
digitalWrite(LED_GREEN, HIGH);
|
|
digitalWrite(LED_BLUE, HIGH);
|
|
}
|
|
|
|
static void NANO_ESP32_enter_bootloader(void) {
|
|
if (!_recovery_active) {
|
|
// check for valid partition scheme
|
|
const esp_partition_t *ota_part = esp_ota_get_next_update_partition(NULL);
|
|
const esp_partition_t *fact_part = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, NULL);
|
|
if (ota_part && fact_part) {
|
|
// set tokens so the recovery FW will find them
|
|
double_tap_mark();
|
|
// invalidate other OTA image
|
|
esp_partition_erase_range(ota_part, 0, 4096);
|
|
// activate factory partition
|
|
esp_ota_set_boot_partition(fact_part);
|
|
}
|
|
}
|
|
|
|
esp_restart();
|
|
}
|
|
|
|
static void boot_double_tap_logic() {
|
|
const esp_partition_t *part = esp_ota_get_running_partition();
|
|
_recovery_active = (part->subtype == ESP_PARTITION_SUBTYPE_APP_FACTORY);
|
|
|
|
double_tap_init();
|
|
|
|
_recovery_marker_found = double_tap_check_match();
|
|
if (_recovery_marker_found && !_recovery_active) {
|
|
// double tap detected in user application, reboot to factory
|
|
NANO_ESP32_enter_bootloader();
|
|
}
|
|
|
|
// delay with mark set then proceed
|
|
// - for normal startup, to detect first double tap
|
|
// - in recovery mode, to ignore several short presses
|
|
double_tap_mark();
|
|
rgb_pulse_delay();
|
|
double_tap_invalidate();
|
|
}
|
|
|
|
namespace {
|
|
class DoubleTap {
|
|
public:
|
|
DoubleTap() {
|
|
boot_double_tap_logic();
|
|
}
|
|
};
|
|
|
|
DoubleTap dt __attribute__((init_priority(101)));
|
|
} // namespace
|