// ─── Paste this as a standalone sketch to audit all memory regions ───────────
#include "esp_heap_caps.h"
#include "esp_system.h"
#include "esp_chip_info.h"
#include "esp_flash.h"
// spi_flash_mmap.h removed — not available in all ESP32 Arduino cores

void setup() {
  Serial.begin(115200);
  delay(1500);

  // ── Chip info ──────────────────────────────────────────────────────────────
  esp_chip_info_t chip;
  esp_chip_info(&chip);
  Serial.println("\n========= ESP32 FULL MEMORY AUDIT =========");
  Serial.printf("  Chip model  : ESP32 rev %d\n", chip.revision);
  Serial.printf("  CPU cores   : %d\n", chip.cores);
  Serial.printf("  Features    : WiFi=%d  BT=%d  BLE=%d\n",
    (chip.features & CHIP_FEATURE_WIFI_BGN) != 0,
    (chip.features & CHIP_FEATURE_BT)       != 0,
    (chip.features & CHIP_FEATURE_BLE)      != 0);

  // ── Flash ──────────────────────────────────────────────────────────────────
  uint32_t flash_size = 0;
  esp_flash_get_size(NULL, &flash_size);
  Serial.println("\n--- Flash ---");
  Serial.printf("  Total flash         : %u bytes  (%.1f MB)\n",
    flash_size, flash_size / (1024.0f * 1024.0f));

  // ── Internal RAM — all capability buckets ──────────────────────────────────
  Serial.println("\n--- Internal RAM ---");
  size_t total_8bit   = heap_caps_get_total_size(MALLOC_CAP_8BIT);
  size_t free_8bit    = heap_caps_get_free_size(MALLOC_CAP_8BIT);
  size_t lgst_8bit    = heap_caps_get_largest_free_block(MALLOC_CAP_8BIT);

  size_t total_32bit  = heap_caps_get_total_size(MALLOC_CAP_32BIT);
  size_t free_32bit   = heap_caps_get_free_size(MALLOC_CAP_32BIT);

  size_t total_dma    = heap_caps_get_total_size(MALLOC_CAP_DMA);
  size_t free_dma     = heap_caps_get_free_size(MALLOC_CAP_DMA);
  size_t lgst_dma     = heap_caps_get_largest_free_block(MALLOC_CAP_DMA);

  Serial.printf("  8BIT  total/free    : %6u / %6u bytes  (lgst block: %u)\n",
    total_8bit,  free_8bit,  lgst_8bit);
  Serial.printf("  32BIT total/free    : %6u / %6u bytes\n",
    total_32bit, free_32bit);
  Serial.printf("  DMA   total/free    : %6u / %6u bytes  (lgst block: %u)\n",
    total_dma,   free_dma,   lgst_dma);

  // ── IRAM (instruction RAM) — not allocatable but good to know ─────────────
  Serial.println("\n--- IRAM (execution memory) ---");
  size_t total_iram = heap_caps_get_total_size(MALLOC_CAP_EXEC);
  size_t free_iram  = heap_caps_get_free_size(MALLOC_CAP_EXEC);
  Serial.printf("  EXEC  total/free    : %6u / %6u bytes\n",
    total_iram, free_iram);

  // ── PSRAM ──────────────────────────────────────────────────────────────────
  Serial.println("\n--- PSRAM (external SPI RAM) ---");
  bool has_psram = (chip.features & CHIP_FEATURE_EMB_PSRAM) != 0;
  Serial.printf("  Chip reports PSRAM  : %s\n", has_psram ? "YES" : "NO");

  size_t total_psram = heap_caps_get_total_size(MALLOC_CAP_SPIRAM);
  size_t free_psram  = heap_caps_get_free_size(MALLOC_CAP_SPIRAM);
  size_t lgst_psram  = heap_caps_get_largest_free_block(MALLOC_CAP_SPIRAM);
  Serial.printf("  SPIRAM total/free   : %6u / %6u bytes  (%.1f / %.1f KB)\n",
    total_psram, free_psram,
    total_psram / 1024.0f, free_psram / 1024.0f);
  Serial.printf("  SPIRAM lgst block   : %6u bytes  (%.1f KB)\n",
    lgst_psram, lgst_psram / 1024.0f);

  // ── Verdict ────────────────────────────────────────────────────────────────
  Serial.println("\n--- Verdict ---");
  if (total_psram == 0) {
    Serial.println("  !! NO PSRAM detected — you are on a plain ESP32 (no WROVER)");
    Serial.println("     Max contiguous arena will be ~100 KB internal only.");
  } else {
    Serial.printf("  PSRAM available: %.2f MB total, %.2f MB free\n",
      total_psram / (1024.0f*1024.0f), free_psram / (1024.0f*1024.0f));
    Serial.println("  Arena can safely use PSRAM block above.");
  }
  Serial.println("===========================================\n");
}

void loop() {}