/**
 * @file cal_tables_rom.c (families/T06215/compact_src)
 * @brief ROM-decoded T06215 calibration.
 *
 * Source ROM:        424026.bin (Bosch P/N 167002X9001494060200)
 * Calibration base:  RWA4 = 0x9BD8
 * Flash anchor:      0x9618
 * Generated:         2026-04-29 (hand-extracted via Ghidra MCP + ROM readback)
 *
 * Field name → ROM-address binding lives in pwm_addr_map.h. Boot-derived
 * values that previously lived as hard-coded literals in pwm.c's
 * runtime_reset are now in `init_*` fields here so each variant carries
 * its own values without code edits.
 *
 * Cal-offset deltas vs t06211:
 *   - PI body thresholds (0x10E, 0x110, 0x116) — same offsets.
 *   - target/pi clamps (-512) live at cal+0x128 / cal+0x12A in T06215
 *     (vs t06211's cal+0x120 / cal+0x122).
 *   - pwm_y_table_ptr at cal+0x15C; shape_y_table_ptr at cal+0x166.
 *   - PWM RPM-window block 0xEE..0x104 — UNCHANGED offsets.
 *   - setpoint_offset = cal+0x4c - cal+0x4e = 3499 - 4147 = -648.
 *   - s_recovery RPM gate at cal+0x126 (t06211 used cal+0x11E).
 */
#include "pwm.h"

/* ── Submap x/y arrays ──────────────────────────────────────────────── */

static const int16_t setpoint_x[6] = { 8389, 5872, 3775, 2726, 1426, 0 };
static const int16_t setpoint_y[6] = { 1707, 1707, 1195,  768,  427, 427 };

static const int16_t pwm_A_x[9] = { 25166, 18455, 13841, 8389, 5872, 3775, 2726, 1426, 0 };
static const int16_t pwm_A_y[9] = {  1707,  1365,  1195,  768,  427,   85,    0, -171, -469 };

static const int16_t pwm_B_x[10] = { 1707, 1365, 1195, 768, 427, 85, 0, -171, -469, -512 };
static const int16_t pwm_B_y[10] = {  819,  737,  492,   0,  41, 49, 82,  102,  205,  205 };

static const int16_t shape_x[4] = { 819, 737, 492, 0 };
static const int16_t shape_y[4] = {  41,  49,  82, 102 };

/* ── Y-tables ────────────────────────────────────────────────────────── */

static const int16_t shape_y_table_rom[4] = { 41, 49, 82, 102 };

/* PWM bilinear Y-table at flash 0x9E30 — 10 rows × 9 cols (90 entries). */
static const int16_t pwm_y_table_rom[90] = {
    /* row 0 */   205,   205,   205,   205,   205,   205,   205,   205,     0,
    /* row 1 */  1568,  1433,  1355,  1065,   799,   205,   205,   205,     0,
    /* row 2 */  1716,  1679,  1556,  1290,   983,   205,   205,   205,     0,
    /* row 3 */  2219,  2129,  2052,  1925,  1679,   880,   205,   205,     0,
    /* row 4 */  2744,  2580,  2518,  2477,  2355,  1740,  1310,   205,     0,
    /* row 5 */  3210,  3071,  3030,  3194,  3194,  3018,  2867,   737,   205,
    /* row 6 */  3702,  3493,  3403,  3583,  3583,  3493,  3071,  1192,   483,
    /* row 7 */  3890,  3890,  3890,  3890,  3890,  3890,  3890,  2076,  1229,
    /* row 8 */  3890,  3890,  3890,  3890,  3890,  3890,  3890,  3890,  3481,
    /* row 9 */  3890,  3890,  3890,  3890,  3890,  3890,  3890,  3890,  4095,
};

/* ── Descriptors ────────────────────────────────────────────────────── */

pwm_submap_descr_t pwm_submap_descrs[PWM_SUBMAP_COUNT] = {
    [PWM_SUBMAP_SETPOINT_INTERP] = {
        .flags = 0, .input_ptr = NULL, .count = 6,
        .x = setpoint_x, .input_addr = 0x0040,
    },
    [PWM_SUBMAP_PWM_A] = {
        .flags = 0, .input_ptr = NULL, .count = 9,
        .x = pwm_A_x, .input_addr = 0x0040,
    },
    [PWM_SUBMAP_PWM_B] = {
        .flags = 0, .input_ptr = NULL, .count = 10,
        .x = pwm_B_x, .input_addr = 0x0046,
    },
    [PWM_SUBMAP_SHAPE_EVAL] = {
        .flags = 0, .input_ptr = NULL, .count = 4,
        .x = shape_x, .input_addr = 0x0142,
    },
};

const int16_t *pwm_submap_y_of(uint16_t idx)
{
    switch (idx) {
    case PWM_SUBMAP_SETPOINT_INTERP: return setpoint_y;
    case PWM_SUBMAP_PWM_A:           return pwm_A_y;
    case PWM_SUBMAP_PWM_B:           return pwm_B_y;
    case PWM_SUBMAP_SHAPE_EVAL:      return shape_y;
    default:                         return NULL;
    }
}

/* ── Scalars ────────────────────────────────────────────────────────── */

const pwm_calibration_t pwm_cal_rom = {
    /* PI controller error-band thresholds */
    .large_pos_error_thresh = 128,             /* cal+0x10E */
    .large_neg_error_thresh = (int16_t)0xFF00, /* cal+0x110 = -256 */
    .pi_low_clamp           = (int16_t)0xFE00, /* cal+0x128 = -512 */
    .pi_high_clamp          = 1707,            /* fallback; runtime uses pi_high_clamp_ceiling */

    /* CAN-decoded setpoint cal constants */
    .b_fb_kw_upper_bound    = 7680,            /* cal+0x004 */
    .b_fb_kw_lower_bound    = (int16_t)0xFD00, /* cal+0x006 */
    .setpoint_offset        = -648,            /* cal+0x4c − cal+0x4e */
    .target_5e_min_clamp    = (int16_t)0xFE00, /* cal+0x12A */
    .can_aux_12e_max        = 1451,            /* cal+0x002 */

    /* Recovery / sustained-error machinery */
    .pi_state_c2_reload     = 100,             /* cal+0x114 (ROM 0x9CEC = 0x0064) */
    .inj_qty_thresh         = 96,              /* cal+0x116 (ROM 0x9CEE = 0x0060) */
    .pi_sat_count_threshold = 800,             /* cal+0x112 (ROM 0x9CEA = 0x0320) */
    .rpm_threshold_recovery = 2936,            /* cal+0x126 (ROM 0x9CFE = 0x0B78) — was wrong (256, t06211 holdover) */
    .pi_cl_rpm_floor        = 420,             /* flash[0x605C] = 0x01A4 */

    /* PI runtime-reset values (ROM-extracted from t06215 cal block at
     * RWA4=0x9BD8 + offset). Boot multipliers DAT_0410..0416 are
     * uninitialized RAM (no writers anywhere in ROM), so they default
     * to 0 — the boot equation `(trim_byte << N) + cal_value` resolves
     * to cal_value. Earlier defaults of ±853 / 480 / etc. were t06211
     * holdovers from the original fork; corrected 2026-04-29 against
     * the actual t06215 ROM bytes. */
    .init_p_shape_bound_pos    = +107,         /* cal+0x10A (ROM 0x9CE2 = 0x006B) → DAT_0450 */
    .init_p_shape_bound_neg    = -107,         /* cal+0x10C (ROM 0x9CE4 = 0xFF95) → DAT_0452 */
    .init_p_gain_normal        = +336,         /* cal+0x118 (ROM 0x9CF0 = 0x0150) → DAT_0454 */
    .init_p_slope_large_pos    = +1792,        /* cal+0x11A (ROM 0x9CF2 = 0x0700) → DAT_027e */
    .init_p_slope_large_neg    = +512,         /* cal+0x11C (ROM 0x9CF4 = 0x0200) → DAT_0280 */
    .init_integ_step_normal    = +256,         /* cal+0x11E (ROM 0x9CF6 = 0x0100) → DAT_0456 */
    .init_integ_step_large_pos = +512,         /* cal+0x120 (ROM 0x9CF8 = 0x0200) → DAT_0282 */
    .init_integ_step_large_neg = +256,         /* cal+0x122 (ROM 0x9CFA = 0x0100) → DAT_0284 */
    .init_open_loop_p_gain     = +6,           /* cal+0x124 (ROM 0x9CFC = 0x06, byte, clamped to 15) → DAT_033e */

    /* CL correction normalizers — boot-cached at DAT_0340/DAT_0342 in
     * the ROM (NOT 0x0332/0x0334 — that was a t06211 holdover). Source
     * cal offsets are 0x108 (pos) and 0x106 (neg); both equal 350 in
     * this ROM. */
    .init_pos_error_normalizer = 350,          /* cal+0x108 (ROM 0x9CE0 = 0x015E) → DAT_0340 */
    .init_neg_error_normalizer = 350,          /* cal+0x106 (ROM 0x9CDE = 0x015E) → DAT_0342 */

    /* PWM stage scalars */
    .pwm_detail_x0          = (int16_t)0x9C40,
    .pwm_detail_x1          = (int16_t)0x8235,
    .pwm_cached_ptr_0F2     = 5662,
    .pwm_cached_ptr_102     = 168,
    .pwm_const_104          = 354,

    .pwm_rpm_windows        = { 5662, 6837, 8808, 10486, 11954, 13422, 18036, 19713 },
    .pwm_window_halfwidth   = 168,
    .pwm_slew_step          = 354,

    .pwm_y_table            = pwm_y_table_rom,
    .shape_y_table          = shape_y_table_rom,

    .closed_loop_gain_const = 10,

    .pwm_period_min         = 33333,
    .pwm_period_max         = 40000,

    .pwm_min                = 0x00CD,
    .pwm_max                = 0x0F32,
};

const pwm_flash_t pwm_flash_rom = { 0 };
