From 61d867bcba0c20452dfac5a76fbef0a67e82b873 Mon Sep 17 00:00:00 2001
From: Luca Burelli <l.burelli@arduino.cc>
Date: Mon, 7 Aug 2023 16:41:29 +0200
Subject: [PATCH 1/5] io_pin_remap: additional bugfixes

- FunctionalInterrupt.h: prevent macro expansion in declaration
- io_pin_remap.h: fix remaining pin-remapped functions whose API
  allow a variable number of parameters
---
 cores/esp32/FunctionalInterrupt.h |  7 ++++---
 cores/esp32/io_pin_remap.h        | 10 +++++-----
 2 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/cores/esp32/FunctionalInterrupt.h b/cores/esp32/FunctionalInterrupt.h
index 69bb5aee7b3..a6d083b9594 100644
--- a/cores/esp32/FunctionalInterrupt.h
+++ b/cores/esp32/FunctionalInterrupt.h
@@ -12,10 +12,11 @@
 #include <stdint.h>
 
 struct InterruptArgStructure {
-	std::function<void(void)> interruptFunction;
+    std::function<void(void)> interruptFunction;
 };
 
-void attachInterrupt(uint8_t pin, std::function<void(void)> intRoutine, int mode);
-
+// The extra set of parentheses here prevents macros defined
+// in io_pin_remap.h from applying to this declaration.
+void (attachInterrupt)(uint8_t pin, std::function<void(void)> intRoutine, int mode);
 
 #endif /* CORE_CORE_FUNCTIONALINTERRUPT_H_ */
diff --git a/cores/esp32/io_pin_remap.h b/cores/esp32/io_pin_remap.h
index cd5c93f8737..8c23fb443d4 100644
--- a/cores/esp32/io_pin_remap.h
+++ b/cores/esp32/io_pin_remap.h
@@ -7,7 +7,7 @@
 
 // Pin remapping functions
 int8_t digitalPinToGPIONumber(int8_t digitalPin);
-int8_t digitalPinFromGPIONumber(int8_t gpioPin);
+int8_t digitalPinFromGPIONumber(int8_t gpioNumber);
 
 // Apply pin remapping to API only when building libraries and user sketch
 #ifndef ARDUINO_CORE_BUILD
@@ -15,10 +15,10 @@ int8_t digitalPinFromGPIONumber(int8_t gpioPin);
 // Override APIs requiring pin remapping
 
 // cores/esp32/Arduino.h
-#define pulseInLong(pin, state, timeout)    pulseInLong(digitalPinToGPIONumber(pin), state, timeout)
-#define pulseIn(pin, state, timeout)        pulseIn(digitalPinToGPIONumber(pin), state, timeout)
-#define noTone(_pin)                        noTone(digitalPinToGPIONumber(_pin))
-#define tone(_pin, args...)                 tone(digitalPinToGPIONumber(_pin), args)
+#define pulseInLong(pin, args...)   pulseInLong(digitalPinToGPIONumber(pin), args)
+#define pulseIn(pin, args...)       pulseIn(digitalPinToGPIONumber(pin), args)
+#define noTone(_pin)                noTone(digitalPinToGPIONumber(_pin))
+#define tone(_pin, args...)         tone(digitalPinToGPIONumber(_pin), args)
 
 // cores/esp32/esp32-hal.h
 #define analogGetChannel(pin)       analogGetChannel(digitalPinToGPIONumber(pin))

From 758a6e4d9f8e0ace82ec3c680020706891ec3c65 Mon Sep 17 00:00:00 2001
From: Luca Burelli <l.burelli@arduino.cc>
Date: Thu, 24 Aug 2023 17:55:12 +0200
Subject: [PATCH 2/5] Nano ESP32: make GPIO matrix reset robust to pin mode
 choice

---
 variants/arduino_nano_nora/io_pin_remap.cpp | 91 ++++++++++++++-------
 variants/arduino_nano_nora/variant.cpp      | 25 +-----
 2 files changed, 67 insertions(+), 49 deletions(-)

diff --git a/variants/arduino_nano_nora/io_pin_remap.cpp b/variants/arduino_nano_nora/io_pin_remap.cpp
index 2a18e029df2..e9c01d79ab4 100644
--- a/variants/arduino_nano_nora/io_pin_remap.cpp
+++ b/variants/arduino_nano_nora/io_pin_remap.cpp
@@ -14,38 +14,73 @@
 #warning The Arduino API will use GPIO numbers for this build.
 #endif
 
-#if defined(BOARD_HAS_PIN_REMAP) && !defined(BOARD_USES_HW_GPIO_NUMBERS)
-
 #include "Arduino.h"
 
-static const int8_t TO_GPIO_NUMBER[NUM_DIGITAL_PINS] = {
-    [D0]        = 44, // RX
-    [D1]        = 43, // TX
-    [D2]        = 5,
-    [D3]        = 6,  // CTS
-    [D4]        = 7,  // DSR
-    [D5]        = 8,
-    [D6]        = 9,
-    [D7]        = 10,
-    [D8]        = 17,
-    [D9]        = 18,
-    [D10]       = 21, // SS
-    [D11]       = 38, // MOSI
-    [D12]       = 47, // MISO
-    [D13]       = 48, // SCK, LED_BUILTIN
-    [LED_RED]   = 46,
-    [LED_GREEN] = 0,
-    [LED_BLUE]  = 45, // RTS
-    [A0]        = 1,  // DTR
-    [A1]        = 2,
-    [A2]        = 3,
-    [A3]        = 4,
-    [A4]        = 11, // SDA
-    [A5]        = 12, // SCL
-    [A6]        = 13,
-    [A7]        = 14,
+// NOTE: This must match with the remapped pin sequence in pins_arduino.h
+static const int8_t TO_GPIO_NUMBER[] = {
+    44, // [ 0] D0, RX
+    43, // [ 1] D1, TX
+    5,  // [ 2] D2
+    6,  // [ 3] D3, CTS
+    7,  // [ 4] D4, DSR
+    8,  // [ 5] D5
+    9,  // [ 6] D6
+    10, // [ 7] D7
+    17, // [ 8] D8
+    18, // [ 9] D9
+    21, // [10] D10, SS
+    38, // [11] D11, MOSI
+    47, // [12] D12, MISO
+    48, // [13] D13, SCK, LED_BUILTIN
+    46, // [14] LED_RED
+    0,  // [15] LED_GREEN
+    45, // [16] LED_BLUE, RTS
+    1,  // [17] A0, DTR
+    2,  // [18] A1
+    3,  // [19] A2
+    4,  // [20] A3
+    11, // [21] A4, SDA
+    12, // [22] A5, SCL
+    13, // [23] A6
+    14, // [24] A7
 };
 
+void _nano_nora_reset_gpio_matrix(void)
+{
+    // In this core file pin mapping is _not_ applied, so the API is
+    // always GPIO-based, but the constants can be either.
+    for (int pin = 0; pin < sizeof(TO_GPIO_NUMBER); ++pin) {
+        int gpio = TO_GPIO_NUMBER[pin];
+#if defined(BOARD_HAS_PIN_REMAP) && !defined(BOARD_USES_HW_GPIO_NUMBERS)
+        // Pin remapping in effect, constants = indexes
+        switch (pin) {
+#else
+        // Pin remapping disabled, constants = GPIO numbers
+        switch (gpio) {
+#endif
+            case LED_RED:
+            case LED_GREEN:
+            case LED_BLUE:
+                // set RGB pins to dig outputs, HIGH=off
+                pinMode(gpio, OUTPUT);
+                digitalWrite(gpio, HIGH);
+                break;
+
+            case TX:
+            case RX:
+                // leave UART pins alone
+                break;
+
+            default:
+                // initialize other pins to dig inputs
+                pinMode(gpio, INPUT);
+                break;
+        }
+    }
+}
+
+#if defined(BOARD_HAS_PIN_REMAP) && !defined(BOARD_USES_HW_GPIO_NUMBERS)
+
 int8_t digitalPinToGPIONumber(int8_t digitalPin)
 {
     if ((digitalPin < 0) || (digitalPin >= NUM_DIGITAL_PINS))
diff --git a/variants/arduino_nano_nora/variant.cpp b/variants/arduino_nano_nora/variant.cpp
index a693f4e0762..7fd5fd989dd 100644
--- a/variants/arduino_nano_nora/variant.cpp
+++ b/variants/arduino_nano_nora/variant.cpp
@@ -9,30 +9,13 @@
 #include <esp_ota_ops.h>
 #include <esp_partition.h>
 
+// defined in io_pin_remap.cpp
+extern void _nano_nora_reset_gpio_matrix(void);
+
 extern "C" {
     void initVariant() {
         // FIXME: fix issues with GPIO matrix not being soft reset properly
-        for (int pin = 0; pin<NUM_DIGITAL_PINS; ++pin) {
-            switch (pin) {
-                case LED_RED:
-                case LED_GREEN:
-                case LED_BLUE:
-                    // set RGB pins to dig outputs, HIGH=off
-                    pinMode(pin, OUTPUT);
-                    digitalWrite(pin, HIGH);
-                    break;
-
-                case TX:
-                case RX:
-                    // leave UART pins alone
-                    break;
-
-                default:
-                    // initialize other pins to dig inputs
-                    pinMode(pin, INPUT);
-                    break;
-            }
-        }
+        _nano_nora_reset_gpio_matrix();
     }
 }
 

From c5161a026da451b6ae12704504a09df3741d613b Mon Sep 17 00:00:00 2001
From: Luca Burelli <l.burelli@arduino.cc>
Date: Mon, 14 Aug 2023 15:45:44 +0200
Subject: [PATCH 3/5] Nano ESP32: add backwards-compatible pin definitions

---
 boards.txt                                |  8 ++-
 variants/arduino_nano_nora/pins_arduino.h | 61 ++++++++++++++++++++---
 2 files changed, 60 insertions(+), 9 deletions(-)

diff --git a/boards.txt b/boards.txt
index c6f61851cf2..d86fe66ee99 100644
--- a/boards.txt
+++ b/boards.txt
@@ -17,6 +17,7 @@ menu.EventsCore=Events Run On
 menu.MemoryType=Memory Type
 menu.EraseFlash=Erase All Flash Before Sketch Upload
 menu.JTAGAdapter=JTAG Adapter
+menu.PinNumbers=Pin Numbering
 
 # Custom options
 menu.Revision=Board Revision
@@ -24154,12 +24155,17 @@ nano_nora.build.flash_mode=dio
 nano_nora.build.boot=qio
 nano_nora.build.boot_freq=80m
 nano_nora.build.partitions=app3M_fat9M_fact512k_16MB
-nano_nora.build.defines=-DBOARD_HAS_PIN_REMAP -DBOARD_HAS_PSRAM '-DUSB_MANUFACTURER="Arduino"' '-DUSB_PRODUCT="Nano ESP32"'
+nano_nora.build.defines=-DBOARD_HAS_PIN_REMAP {build.disable_pin_remap} -DBOARD_HAS_PSRAM '-DUSB_MANUFACTURER="Arduino"' '-DUSB_PRODUCT="Nano ESP32"'
 nano_nora.build.loop_core=-DARDUINO_RUNNING_CORE=1
 nano_nora.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1
 nano_nora.build.psram_type=opi
 nano_nora.build.memory_type={build.boot}_{build.psram_type}
+nano_nora.build.disable_pin_remap=
 
 nano_nora.tools.esptool_py.program.pattern_args=--chip {build.mcu} --port "{serial.port}" --before default_reset --after hard_reset write_flash -z --flash_mode {build.flash_mode} --flash_freq {build.flash_freq} --flash_size {build.flash_size} {build.bootloader_addr} "{build.path}/{build.project_name}.bootloader.bin" 0x8000 "{build.path}/{build.project_name}.partitions.bin" 0xe000 "{runtime.platform.path}/tools/partitions/boot_app0.bin" 0xf70000 "{build.variant.path}/extra/nora_recovery/nora_recovery.ino.bin" 0x10000 "{build.path}/{build.project_name}.bin"
 
+nano_nora.menu.PinNumbers.default=By Arduino pin (default)
+nano_nora.menu.PinNumbers.byGPIONumber=By GPIO number (legacy)
+nano_nora.menu.PinNumbers.byGPIONumber.build.disable_pin_remap=-DBOARD_USES_HW_GPIO_NUMBERS
+
 ##############################################################
diff --git a/variants/arduino_nano_nora/pins_arduino.h b/variants/arduino_nano_nora/pins_arduino.h
index 79a94ec4ae9..115185b2145 100644
--- a/variants/arduino_nano_nora/pins_arduino.h
+++ b/variants/arduino_nano_nora/pins_arduino.h
@@ -7,20 +7,24 @@
 #define USB_VID 0x2341
 #define USB_PID 0x0070
 
-#define EXTERNAL_NUM_INTERRUPTS 46
-#define NUM_DIGITAL_PINS        25
-#define NUM_ANALOG_INPUTS       8
-
-#define analogInputToDigitalPin(p)  (p)
-#define digitalPinToInterrupt(p)    ((((uint8_t)digitalPinToGPIONumber(p)) < 48)? digitalPinToGPIONumber(p) : -1)
-#define digitalPinHasPWM(p)         (((uint8_t)digitalPinToGPIONumber(p)) < 46)
-
 #ifndef __cplusplus
 #define constexpr const
 #endif
 
 // primary pin names
 
+#if defined(BOARD_HAS_PIN_REMAP) && !defined(BOARD_USES_HW_GPIO_NUMBERS)
+
+// Arduino style definitions (API uses Dx)
+
+#define analogInputToDigitalPin(p)  (p)
+#define digitalPinToInterrupt(p)    ((((uint8_t)digitalPinToGPIONumber(p)) < 48)? digitalPinToGPIONumber(p) : -1)
+#define digitalPinHasPWM(p)         (((uint8_t)digitalPinToGPIONumber(p)) < 46)
+
+#define EXTERNAL_NUM_INTERRUPTS 46
+#define NUM_DIGITAL_PINS        25
+#define NUM_ANALOG_INPUTS       8
+
 static constexpr uint8_t D0         = 0; // also RX
 static constexpr uint8_t D1         = 1; // also TX
 static constexpr uint8_t D2         = 2;
@@ -48,6 +52,47 @@ static constexpr uint8_t A5         = 22; // also SCL
 static constexpr uint8_t A6         = 23;
 static constexpr uint8_t A7         = 24;
 
+#else
+
+// ESP32-style definitions (API uses GPIOx)
+
+#define EXTERNAL_NUM_INTERRUPTS 46
+#define NUM_DIGITAL_PINS        48
+#define NUM_ANALOG_INPUTS       20
+
+#define analogInputToDigitalPin(p)  (((p)<20)?(analogChannelToDigitalPin(p)):-1)
+#define digitalPinToInterrupt(p)    (((p)<48)?(p):-1)
+#define digitalPinHasPWM(p)         (p < 46)
+
+static constexpr uint8_t D0         = 44; // also RX
+static constexpr uint8_t D1         = 43; // also TX
+static constexpr uint8_t D2         = 5;
+static constexpr uint8_t D3         = 6;  // also CTS
+static constexpr uint8_t D4         = 7;  // also DSR
+static constexpr uint8_t D5         = 8;
+static constexpr uint8_t D6         = 9;
+static constexpr uint8_t D7         = 10;
+static constexpr uint8_t D8         = 17;
+static constexpr uint8_t D9         = 18;
+static constexpr uint8_t D10        = 21; // also SS
+static constexpr uint8_t D11        = 38; // also MOSI
+static constexpr uint8_t D12        = 47; // also MISO
+static constexpr uint8_t D13        = 48; // also SCK, LED_BUILTIN
+static constexpr uint8_t LED_RED    = 46;
+static constexpr uint8_t LED_GREEN  = 0;
+static constexpr uint8_t LED_BLUE   = 45; // also RTS
+
+static constexpr uint8_t A0         = 1;  // also DTR
+static constexpr uint8_t A1         = 2;
+static constexpr uint8_t A2         = 3;
+static constexpr uint8_t A3         = 4;
+static constexpr uint8_t A4         = 11; // also SDA
+static constexpr uint8_t A5         = 12; // also SCL
+static constexpr uint8_t A6         = 13;
+static constexpr uint8_t A7         = 14;
+
+#endif
+
 // alternate pin functions
 
 static constexpr uint8_t LED_BUILTIN = D13;

From 2578081433302d63840340bd80bd53daeb563e3e Mon Sep 17 00:00:00 2001
From: Luca Burelli <l.burelli@arduino.cc>
Date: Thu, 24 Aug 2023 11:06:30 +0200
Subject: [PATCH 4/5] Nano ESP32: erase flash when running "Burn Bootloader"

---
 boards.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/boards.txt b/boards.txt
index d86fe66ee99..a6764164211 100644
--- a/boards.txt
+++ b/boards.txt
@@ -24163,6 +24163,7 @@ nano_nora.build.memory_type={build.boot}_{build.psram_type}
 nano_nora.build.disable_pin_remap=
 
 nano_nora.tools.esptool_py.program.pattern_args=--chip {build.mcu} --port "{serial.port}" --before default_reset --after hard_reset write_flash -z --flash_mode {build.flash_mode} --flash_freq {build.flash_freq} --flash_size {build.flash_size} {build.bootloader_addr} "{build.path}/{build.project_name}.bootloader.bin" 0x8000 "{build.path}/{build.project_name}.partitions.bin" 0xe000 "{runtime.platform.path}/tools/partitions/boot_app0.bin" 0xf70000 "{build.variant.path}/extra/nora_recovery/nora_recovery.ino.bin" 0x10000 "{build.path}/{build.project_name}.bin"
+nano_nora.tools.esptool_py.erase.pattern_args=--chip {build.mcu} --port "{serial.port}" --before default_reset --after hard_reset erase_flash
 
 nano_nora.menu.PinNumbers.default=By Arduino pin (default)
 nano_nora.menu.PinNumbers.byGPIONumber=By GPIO number (legacy)

From b3342a7f65d29c4387de3775cc5a4d2b2ae412e6 Mon Sep 17 00:00:00 2001
From: Luca Burelli <l.burelli@arduino.cc>
Date: Thu, 24 Aug 2023 11:07:11 +0200
Subject: [PATCH 5/5] Nano ESP32: add filesystem type selection

---
 boards.txt                                        | 4 ++++
 tools/partitions/app3M_spiffs9M_fact512k_16MB.csv | 8 ++++++++
 2 files changed, 12 insertions(+)
 create mode 100644 tools/partitions/app3M_spiffs9M_fact512k_16MB.csv

diff --git a/boards.txt b/boards.txt
index a6764164211..12ef4887d05 100644
--- a/boards.txt
+++ b/boards.txt
@@ -24165,6 +24165,10 @@ nano_nora.build.disable_pin_remap=
 nano_nora.tools.esptool_py.program.pattern_args=--chip {build.mcu} --port "{serial.port}" --before default_reset --after hard_reset write_flash -z --flash_mode {build.flash_mode} --flash_freq {build.flash_freq} --flash_size {build.flash_size} {build.bootloader_addr} "{build.path}/{build.project_name}.bootloader.bin" 0x8000 "{build.path}/{build.project_name}.partitions.bin" 0xe000 "{runtime.platform.path}/tools/partitions/boot_app0.bin" 0xf70000 "{build.variant.path}/extra/nora_recovery/nora_recovery.ino.bin" 0x10000 "{build.path}/{build.project_name}.bin"
 nano_nora.tools.esptool_py.erase.pattern_args=--chip {build.mcu} --port "{serial.port}" --before default_reset --after hard_reset erase_flash
 
+nano_nora.menu.PartitionScheme.default=With FAT partition (default)
+nano_nora.menu.PartitionScheme.spiffs=With SPIFFS partition (advanced)
+nano_nora.menu.PartitionScheme.spiffs.build.partitions=app3M_spiffs9M_fact512k_16MB
+
 nano_nora.menu.PinNumbers.default=By Arduino pin (default)
 nano_nora.menu.PinNumbers.byGPIONumber=By GPIO number (legacy)
 nano_nora.menu.PinNumbers.byGPIONumber.build.disable_pin_remap=-DBOARD_USES_HW_GPIO_NUMBERS
diff --git a/tools/partitions/app3M_spiffs9M_fact512k_16MB.csv b/tools/partitions/app3M_spiffs9M_fact512k_16MB.csv
new file mode 100644
index 00000000000..3b8909da325
--- /dev/null
+++ b/tools/partitions/app3M_spiffs9M_fact512k_16MB.csv
@@ -0,0 +1,8 @@
+# Name,   Type, SubType,  Offset,   Size,     Flags
+nvs,      data, nvs,        0x9000,   0x5000,
+otadata,  data, ota,        0xe000,   0x2000,
+app0,     app,  ota_0,     0x10000, 0x300000,
+app1,     app,  ota_1,    0x310000, 0x300000,
+spiffs,   data, spiffs,   0x610000, 0x960000,
+factory,  app,  factory,  0xF70000,  0x80000,
+coredump, data, coredump, 0xFF0000,  0x10000,