163 lines
6.9 KiB
C++
163 lines
6.9 KiB
C++
#pragma once
|
|
|
|
#include <Arduino.h>
|
|
|
|
// ------------------------- Hardware configuration -------------------------
|
|
// Enabled for the hand-wired prototype. Comment out for the production PCB.
|
|
// Both profiles map S3 signals by physical header position with 5V/GND aligned.
|
|
#define MAKETKA
|
|
|
|
// Additionally log raw GPIO_RX level changes while no test is running.
|
|
//#define RX_PIN_CHANGE_TEST
|
|
|
|
// Standalone PWM output check. While enabled, the normal application is not
|
|
// started: GPIO_PWM continuously outputs the frequency and duty below.
|
|
// Comment this define out after the hardware check.
|
|
//#define PWM_OUTPUT_TEST
|
|
constexpr uint32_t PWM_OUTPUT_TEST_FREQUENCY_HZ = 1000;
|
|
constexpr uint32_t PWM_OUTPUT_TEST_SWEEP_PERIOD_MS = 2000;
|
|
constexpr uint32_t PWM_OUTPUT_TEST_UPDATE_MS = 10;
|
|
constexpr uint32_t PWM_OUTPUT_TEST_MIN_PULSE_NS = 1000;
|
|
constexpr uint32_t PWM_OUTPUT_TEST_MAX_PULSE_NS = 10000;
|
|
|
|
#if CONFIG_IDF_TARGET_ESP32C3
|
|
constexpr bool TARGET_IS_C3 = true;
|
|
constexpr uint8_t GPIO_PWM = 3;
|
|
constexpr uint8_t GPIO_RX = 4;
|
|
#ifdef MAKETKA
|
|
constexpr uint8_t GPIO_BUTTON_MODE = 0;
|
|
constexpr uint8_t GPIO_BUTTON_START = 1;
|
|
#else
|
|
constexpr uint8_t GPIO_BUTTON_MODE = 20;
|
|
constexpr uint8_t GPIO_BUTTON_START = 10;
|
|
constexpr uint8_t GPIO_VBAT = 2;
|
|
constexpr uint8_t GPIO_ANALOG_RX = 0;
|
|
#endif
|
|
constexpr uint8_t GPIO_SDA = 6;
|
|
constexpr uint8_t GPIO_SCL = 7;
|
|
#elif CONFIG_IDF_TARGET_ESP32S3
|
|
constexpr bool TARGET_IS_C3 = false;
|
|
#ifdef MAKETKA
|
|
// Same physical header contacts as the C3 MAKETKA profile when 5V/GND align.
|
|
constexpr uint8_t GPIO_PWM = 12;
|
|
constexpr uint8_t GPIO_RX = 13;
|
|
constexpr uint8_t GPIO_BUTTON_MODE = 9;
|
|
constexpr uint8_t GPIO_BUTTON_START = 10;
|
|
constexpr uint8_t GPIO_SDA = 44;
|
|
constexpr uint8_t GPIO_SCL = 1;
|
|
#else
|
|
// The S3 SuperMini is fitted so its 5V and GND pins occupy the same PCB
|
|
// contacts as on the C3 SuperMini. Signals therefore follow header position.
|
|
constexpr uint8_t GPIO_PWM = 12;
|
|
constexpr uint8_t GPIO_RX = 13;
|
|
constexpr uint8_t GPIO_BUTTON_MODE = 5;
|
|
constexpr uint8_t GPIO_BUTTON_START = 4;
|
|
constexpr uint8_t GPIO_SDA = 44;
|
|
constexpr uint8_t GPIO_SCL = 1;
|
|
constexpr uint8_t GPIO_VBAT = 11;
|
|
constexpr uint8_t GPIO_ANALOG_RX = 9;
|
|
#endif
|
|
#else
|
|
#error "Only ESP32-C3 and ESP32-S3 are supported"
|
|
#endif
|
|
|
|
constexpr uint8_t OLED_ROTATION = 0;
|
|
|
|
constexpr uint8_t OLED_ADDRESS = 0x3C;
|
|
constexpr uint8_t ESPNOW_WIFI_CHANNEL = 6;
|
|
constexpr uint32_t SERIAL_BAUD = 115200;
|
|
// Native USB CDC may keep a stale "connected" state after light sleep. Keep
|
|
// logging non-blocking so a missing host can never delay button polling.
|
|
constexpr uint32_t SERIAL_TX_TIMEOUT_MS = 2;
|
|
constexpr bool SERIAL_ACTION_LOG = true;
|
|
constexpr bool SERIAL_LOG_TIMESTAMPS = true;
|
|
constexpr bool SERIAL_MINIMAL_LOG = true;
|
|
|
|
#define BUTTON_ACTIVE_LEVEL LOW
|
|
// Raw GPIO_RX level that means the optical receiver is active.
|
|
#define RX_ACTIVE_LEVEL HIGH
|
|
// PWM_ACTIVE_LEVEL is the electrical level of the active test pulse and is
|
|
// also used for the constant active output while awake outside a test. During
|
|
// the remainder of a running PWM period the output is !PWM_ACTIVE_LEVEL.
|
|
// PWM_SAFE_LEVEL is used only while PWM is stopped and during sleep; it is
|
|
// independent of the PWM inactive level and may equal PWM_ACTIVE_LEVEL.
|
|
#define PWM_SAFE_LEVEL HIGH
|
|
#define PWM_ACTIVE_LEVEL LOW
|
|
#define PWM_SETTLE_CYCLES 5U
|
|
|
|
constexpr uint32_t BUTTON_DEBOUNCE_MS = 30;
|
|
constexpr uint32_t BUTTON_LONG_PRESS_MS = 500;
|
|
constexpr uint32_t BUTTON_REPEAT_DELAY_MS = 600;
|
|
constexpr uint32_t BUTTON_REPEAT_MS = 180;
|
|
constexpr uint32_t FACTORY_RESET_HOLD_MS = 1500;
|
|
|
|
constexpr uint32_t LINK_REPLY_TIMEOUT_MS = 1500;
|
|
constexpr uint8_t LINK_PACKET_RETRIES = 10;
|
|
constexpr uint32_t LINK_RETRY_INTERVAL_MS = 1000;
|
|
constexpr uint32_t DISCOVERY_RETRY_INTERVAL_MS = 20;
|
|
// During discovery Master alternates PWM_ACTIVE_LEVEL and PWM_SAFE_LEVEL to
|
|
// wake a sleeping Slave through the optical channel.
|
|
constexpr uint32_t OPTICAL_WAKE_HALF_PERIOD_MS = 50;
|
|
constexpr uint32_t LINK_HEARTBEAT_INTERVAL_MS = 500;
|
|
constexpr uint32_t LINK_HEARTBEAT_TIMEOUT_MS = 2500;
|
|
constexpr uint32_t FINAL_ACK_RETRY_INTERVAL_MS = 50;
|
|
constexpr uint8_t FINAL_ACK_RETRIES = 2;
|
|
constexpr uint8_t NO_SIGNAL_TIMEOUT_PERIODS = 8;
|
|
constexpr uint16_t PERIOD_BATCH_SIZE = 128;
|
|
// Retained as the minimum statistical depth used by the hardware-resolution
|
|
// calculation and diagnostics. PASS/FAIL is evaluated for every complete
|
|
// pulse independently; accumulated values are used only for display.
|
|
constexpr uint16_t MEASUREMENT_AVERAGING_PERIODS = 100;
|
|
static_assert(MEASUREMENT_AVERAGING_PERIODS > 0,
|
|
"Averaging window must contain at least one period");
|
|
constexpr uint8_t MEASUREMENT_PROGRESS_STEPS = 10;
|
|
constexpr uint32_t OLED_PROGRESS_UPDATE_MS = 15;
|
|
|
|
constexpr uint32_t IDLE_POWER_SAVE_TIMEOUT_MS = 60000;
|
|
constexpr uint16_t SLAVE_LISTEN_INTERVAL_MS = 100;
|
|
constexpr uint16_t SLAVE_LISTEN_WINDOW_MS = 20;
|
|
static_assert(SLAVE_LISTEN_WINDOW_MS < SLAVE_LISTEN_INTERVAL_MS,
|
|
"Slave listen window must be shorter than its interval");
|
|
// Conservative sustained validation rate calibrated from real C3 logs.
|
|
constexpr uint32_t RX_PROCESSING_PERIODS_PER_SECOND = 300000;
|
|
|
|
constexpr uint32_t C3_STRICT_MAX_HZ = 1000000;
|
|
constexpr uint32_t S3_STRICT_MAX_HZ = 1000000;
|
|
// S3 MCPWM Capture uses one 32-bit 80 MHz timer for both edges. Unlike RMT,
|
|
// its width does not constrain long LOW/HIGH intervals, so capture precision
|
|
// stays at 12.5 ns for every selectable PWM frequency and pulse length.
|
|
constexpr uint32_t MCPWM_CAPTURE_RESOLUTION_HZ = 80000000;
|
|
// C3 uses the 40 MHz crystal as the LEDC clock.
|
|
// Keep this explicit so the resolution calculation never asks LEDC for an
|
|
// impossible frequency/resolution combination.
|
|
constexpr uint32_t LEDC_SOURCE_CLOCK_HZ = 40000000;
|
|
constexpr uint8_t LEDC_CHANNEL = 0;
|
|
constexpr uint8_t LEDC_MAX_BITS = 14;
|
|
// S3 uses the dedicated MCPWM peripheral. A 20 MHz timer clock keeps the
|
|
// selectable 500 Hz period within the S3's 16-bit counter while retaining
|
|
// 50 ns pulse resolution and exact periods for every menu frequency.
|
|
constexpr uint32_t MCPWM_RESOLUTION_HZ = 20000000;
|
|
constexpr uint32_t MCPWM_MAX_PERIOD_TICKS = 65535;
|
|
|
|
// -------------------------- Menu value arrays -----------------------------
|
|
// The test uses one selected PWM frequency and walks the pulse-width list from
|
|
// the selected maximum down to the selected minimum. Widths are stored in
|
|
// nanoseconds so sub-microsecond pulses remain representable without floats.
|
|
constexpr uint32_t PWM_FREQUENCY_OPTIONS_HZ[] = {
|
|
500, 1000, 2000, 5000, 10000, 25000,
|
|
};
|
|
constexpr uint32_t MAX_PULSE_OPTIONS_NS[] = {
|
|
20000, 50000, 100000, 200000, 500000
|
|
};
|
|
constexpr uint32_t MIN_PULSE_OPTIONS_NS[] = {
|
|
250, 500, 1000, 2000, 5000, 10000
|
|
};
|
|
constexpr uint32_t TEST_PULSE_WIDTHS_NS[] = {
|
|
250, 500, 1000, 2000, 5000, 10000, 20000, 50000,
|
|
100000, 200000, 500000, 1000000
|
|
};
|
|
constexpr float ACCURACY_OPTIONS_PCT[] = {1.0f, 2.0f, 5.0f, 10.0f};
|
|
constexpr uint32_t TEST_TIME_OPTIONS_MS[] = {100, 250, 500, 1000, 2000, 5000};
|
|
|
|
template <typename T, size_t N> constexpr size_t countOf(const T (&)[N]) { return N; }
|