#ifndef CONFIG_H
#define CONFIG_H

#include <stdbool.h>
#include <stdint.h>

#define ERASE_PAGE_SIZE 64
#define CONFIG_MAGIC 0x1234ABCD
#define CONFIG_VERSION 1

#define MY_ADDR 0
#define DEFAULT_DMM_ADDR 18  // the HP3478A addr

// Timing Config
#define USB_DEBOUNCE_CONNECT_MS 50
#define USB_DEBOUNCE_DISCONNECT_MS 200

#define ENV_SENSOR_READ_INTERVAL_MS 1000
#define DEFAULT_GPIB_TIMEOUT_MS 1200

// This kind of ass but.. yeah, I don't want to access systick there
// assume if the PC hasn't read after ~5ms it's stalled
#define USB_TIMEOUT_TARGET_MS 5
#define CYCLES_PER_LOOP 50
#define USB_TIMEOUT_LIMIT \
  ((FUNCONF_SYSTEM_CORE_CLOCK / 1000 * USB_TIMEOUT_TARGET_MS) / CYCLES_PER_LOOP)

// Menu Animation Timings
#define MENU_DOT_INTERVAL_MS 500    // Speed of "..." addition
#define MENU_COMMIT_DELAY_MS 2400   // Time to hold before entering mode
#define MENU_SUBLAYER_DELAY_MS 500  // Time to "hover" before dots start
#define MENU_DEBOUNCE_MS 100        // Button press dead-time
#define MENU_LOCKOUT_MS 200  // How long to ignore SRQ for after exiting menu

// Polling
#define POLL_INTERVAL_MS 100        // 10Hz polling when in Passthrough
#define DMM_RECOVERY_DELAY_MS 1000  // Backoff if DMM vanishes

// Diode sound
#define DIODE_TH_SHORT 0.050  // Volts (below this = SHORT)
#define DIODE_TH_OPEN 2.500   // Volts (above this = OPEN/OL)
#define DIODE_STABLE_MS 20    // wait X ms for voltage to settle
#define DIODE_CHIRP_MS 50

// PT1000 (DIN 43760 / IEC 751 Standard)
#define RTD_A 3.9083e-3
#define RTD_B -5.775e-7
#define RTD_R0 1000.0

// Thermocouple
#define CJC_FALLBACK_TEMP 22.0  // used if !app.env_sensor_present
// this is just cursed but.. yeah, the PCB is near a transformer
// ideally, the temp should be measured right at the binding posts..
#define CJC_SELF_HEATING_OFFSET 4.0
#define TYPE_K_SCALE 24390.24  // 1 / 41uV
// dBm
#define DBM_REF_Z 50.0
// Stats
#define STATS_CYCLE_TIME_MS 3000  // time per screen (Live -> Avg -> Min...)
#define STATS_INIT_MIN_VAL 1.0e9
#define STATS_INIT_MAX_VAL -1.0e9

// Autohold
#define AUTOHOLD_THRESHOLD 1.0   // deviation % allowed for stability check
#define AUTOHOLD_CHANGE_REQ 2.0  // % new value must differ by to trigger upd
// XXX: ideally, we should have different sample requirements for diff ranges
// we don't need as many counts at N5 range as at N3
#define AUTOHOLD_STABLE_COUNT 3  // num samples required
#define AUTOHOLD_MIN_VAL 0.05    // noise floor

#define CONT_DISP_UPDATE_MS 150   // display throttling
#define CONT_THRESHOLD_OHMS 10.0  // continuity beep threshold

#define REL_STABLE_COUNT 3  // filter depth for Relative NULL

#define BUZZER_CHIRP_HZ 3000
#define BUZZER_CHIRP_MS 75
#define BUZZER_CONT_HZ 2500
#define BUZZER_ONLINE_TUNE 0  // todo: add to conf

// #define LOCAL_COMMIT 1

typedef struct {
  uint32_t magic;
  uint32_t version;

  // addressing
  uint8_t my_addr;      // controller
  uint8_t dmm_addr;     // hp3478a
  uint8_t target_addr;  // target

  uint8_t eot_char;
  uint8_t eot_enable;
  uint8_t eoi_assert;
  uint8_t eos_mode;
  uint8_t eor_mode;
  uint8_t auto_read;
  uint8_t padding;  // align

  // timings (ms)
  uint32_t gpib_timeout_ms;
  uint32_t poll_interval_ms;
  uint32_t env_sensor_read_interval_ms;
  uint32_t dmm_recovery_delay_ms;
  uint32_t usb_debounce_connect_ms;
  uint32_t usb_debounce_disconnect_ms;
  uint32_t usb_timeout_target_ms;

  // timings
  uint32_t menu_dot_interval_ms;
  uint32_t menu_commit_delay_ms;
  uint32_t menu_sublayer_delay_ms;
  uint32_t menu_debounce_ms;
  uint32_t menu_lockout_ms;
  uint32_t stats_cycle_time_ms;
  uint32_t cont_disp_update_ms;
  uint32_t diode_stable_ms;

  // buzzer
  uint32_t buzzer_chirp_hz;
  uint32_t buzzer_chirp_ms;
  uint32_t buzzer_cont_hz;

  // math & cal
  double rtd_a;
  double rtd_b;
  double rtd_r0;
  double cjc_fallback_temp;
  double cjc_self_heating_offset;
  double type_k_scale;
  double dbm_ref_z;
  double diode_th_short;
  double diode_th_open;

  // thresholds
  double autohold_threshold;
  double autohold_change_req;
  double autohold_min_val;
  double cont_threshold_ohms;

  // logic counts
  uint32_t autohold_stable_count;
  uint32_t rel_stable_count;

} fw_config_t;

typedef enum { CFG_TYPE_UINT8, CFG_TYPE_UINT32, CFG_TYPE_DOUBLE } cfg_type_t;

typedef struct {
  const char* name;
  size_t offset;
  cfg_type_t type;
} cfg_field_t;

#endif  // CONFIG_H