/**
 * @file cal_tables_rom.c (variant/T06235/compact_src)
 * @brief ROM-decoded T06235 calibration.
 *
 * Source ROM:        rom_eeprom_dump_0000-9FFF_504042.bin
 * Bosch P/N header:  '16700 69T63\0' (24-byte ASCII header at flash 0x9BA0)
 * Calibration base:  RWA4 = 0x9BB8
 * Flash anchor:      0x9618
 * Generated:         2026-05-01 (extracted via tools/extract_calibration.py
 *                                 + direct flash readback per Step 7)
 *
 * Field-name → ROM-address binding lives in pwm_addr_map.h. T06235 is a
 * recompile of T06215 with a uniform +0x14 cal-block insertion above
 * ~cal+0x9E (the new ADR-SV-* / KW_SIM_UMSCHALTUNG diagnostic fields per
 * doc.txt 30.08.02). All T06215 cal field roles map to T06235 with the
 * +0x14 offset; the actual values were re-extracted from this ROM.
 * NOTE: there is also a +0x02 shift in the lower region — at minimum
 * cal+0x4c → cal+0x4e and cal+0xa0 → cal+0xa2 (both confirmed in FUN_6a4b
 * @ 0x6a4b). Lower-region scalars must be re-checked, not assumed unchanged.
 *
 * Notable value deltas vs T06215:
 *   - setpoint_offset = cal+0x4e − cal+0x50 = 3499 − 4228 = -729 (T06215 cal+0x4c−cal+0x4e = -648).
 *     Cal-block +0x02 shift in this lower region; T06215's cal+0xa0 modulo
 *     also moves to cal+0xa2 in T06235 (verified in FUN_6a4b @ 0x6a4b).
 *   - init_p_gain_normal       = +368  (T06215: +336)
 *   - init_p_slope_large_pos   = +2047 (T06215: +1792)
 *   - init_integ_step_normal   = +320  (T06215: +256)
 *   - init_integ_step_large_pos= +831  (T06215: +512)
 *   - init_integ_step_large_neg= +255  (T06215: +256)
 *   - rpm_threshold_recovery   = 2726  (T06215: 2936)
 *   - pwm_rpm_windows[1]       = 6795  (T06215: 6837)
 *   - setpoint_y[]             = [1707,1707,1707,1195,768,427]
 *                                 (T06215: [1707,1707,1195,768,427,427])
 *   - pwm Y-table values mostly re-tuned (90 entries); see arrays below.
 *
 * All other scalars match T06215 exactly.
 */
#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, 1707, 1195,  768, 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 };

/* T06215 inferred shape map kept verbatim — needs Step 7 follow-up to
 * re-extract from T06235 for accuracy if shape stage is exercised. */
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 0x9E20 (T06235; T06215 was 0x9E30) —
 * 10 rows × 9 cols (90 entries). Re-extracted 2026-05-01 from this
 * ROM; values differ from T06215 (recalibrated). */
static const int16_t pwm_y_table_rom[90] = {
    /* row 0 */   205,   205,   205,   205,   205,   205,   205,   205,     0,
    /* row 1 */  1638,  1433,  1229,  1024,   819,   205,   205,   205,     0,
    /* row 2 */  1843,  1658,  1474,  1229,  1024,   205,   205,   205,     0,
    /* row 3 */  2375,  2211,  2068,  1802,  1577,  1167,   205,   205,     0,
    /* row 4 */  2744,  2621,  2580,  2457,  2273,  1904,  1372,   205,     0,
    /* row 5 */  3358,  3276,  3235,  3194,  3092,  2867,  2539,  1351,   205,
    /* row 6 */  3686,  3604,  3522,  3440,  3358,  3215,  2867,  1761,   614,
    /* row 7 */  3890,  3890,  3890,  3890,  3890,  3890,  3890,  2518,  1527,
    /* 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 (T06235 cal+0x122/0x124 = T06215 +0x14) */
    .large_pos_error_thresh = 128,             /* cal+0x122 (was T06215 cal+0x10E) */
    .large_neg_error_thresh = (int16_t)0xFF00, /* cal+0x124 = -256 */
    .pi_low_clamp           = (int16_t)0xFE00, /* cal+0x13C = -512 */
    .pi_high_clamp          = 1707,            /* fallback; runtime uses pi_high_clamp_ceiling */

    /* CAN-decoded setpoint cal constants (lower region — invariant offsets) */
    .b_fb_kw_upper_bound    = 7680,            /* cal+0x004 */
    .b_fb_kw_lower_bound    = (int16_t)0xFD00, /* cal+0x006 */
    .setpoint_offset        = -729,            /* cal+0x4e − cal+0x50 = 3499 − 4228 = -729 (T06215 cal+0x4c−cal+0x4e = -648) */
    .target_5e_min_clamp    = (int16_t)0xFE00, /* cal+0x13E = -512 (T06215 cal+0x12A +0x14) */
    .can_aux_12e_max        = 1451,            /* cal+0x002 */

    /* CKP-zero acquisition (FUN_55e0 + FUN_6a4b chain) — values read from
     * rom_eeprom_dump_0000-9FFF_504042.bin at RWA4 + offset. */
    .ckp_zero_anchor        = 4228,            /* cal+0x050 @ 0x9C08 = 0x1084 */
    .can_dckp_offset_bias   = 0,               /* cal+0x052 @ 0x9C0A = 0x0000 */
    .ckp_modulus            = 7680,            /* cal+0x0A2 @ 0x9C5A = 0x1E00 (90° at 256/3°/unit) */

    /* CKP process-tooth derivation (FUN_6c70 — feeds get_ckp_process_tooth()).
     * Read direct from rom_eeprom_dump_0000-9FFF_504042.bin at RWA4=0x9BB8
     * + offset; default-family analogs are at cal+0x120/0x0A3/0x0A4. */
    .ckp_advance_per_tick   = 1707,            /* cal+0x140 @ 0x9CF8 = 0x06AB (= 20° per tick;
                                                *   t06211 cal+0x124, T06215 cal+0x12C, default cal+0x120 = 1536 = 18°) */
    .ckp_seg_wrap_threshold = 29,              /* cal+0x09F @ 0x9C57 (default cal+0x0A3) */
    .ckp_teeth_per_seg      = 26,              /* cal+0x0A0 @ 0x9C58 (default cal+0x0A4; same value across all variants) */

    /* Recovery / sustained-error machinery */
    .pi_state_c2_reload     = 100,             /* cal+0x128 (was T06215 cal+0x114) */
    .inj_qty_thresh         = 96,              /* cal+0x12A (was T06215 cal+0x116) */
    .pi_sat_count_threshold = 800,             /* cal+0x126 (was T06215 cal+0x112) */
    .rpm_threshold_recovery = 2726,            /* cal+0x13A (was T06215 cal+0x126; T06215 = 2936 — value Δ) */
    .pi_cl_rpm_floor        = 420,             /* flash[0x605C] = 0x01A4 — invariant */

    /* PI runtime-reset values (T06235-extracted from cal block at RWA4=0x9BB8 + offset). */
    .init_p_shape_bound_pos    = +107,         /* cal+0x11E (T06215 cal+0x10A) */
    .init_p_shape_bound_neg    = -107,         /* cal+0x120 (T06215 cal+0x10C) */
    .init_p_gain_normal        = +368,         /* cal+0x12C (T06215 cal+0x118; was +336 — value Δ) */
    .init_p_slope_large_pos    = +2047,        /* cal+0x12E (T06215 cal+0x11A; was +1792 — value Δ) */
    .init_p_slope_large_neg    = +512,         /* cal+0x130 (T06215 cal+0x11C) */
    .init_integ_step_normal    = +320,         /* cal+0x132 (T06215 cal+0x11E; was +256 — value Δ) */
    .init_integ_step_large_pos = +831,         /* cal+0x134 (T06215 cal+0x120; was +512 — value Δ) */
    .init_integ_step_large_neg = +255,         /* cal+0x136 (T06215 cal+0x122; was +256 — value Δ) */
    .init_open_loop_p_gain     = +6,           /* cal+0x138 byte (T06215 cal+0x124; same value, clamped to 15) */

    /* CL correction normalizers — boot-cached at DAT_0340/DAT_0342. */
    .init_pos_error_normalizer = 350,          /* cal+0x11C (T06215 cal+0x108) */
    .init_neg_error_normalizer = 350,          /* cal+0x11A (T06215 cal+0x106) */

    /* PWM stage scalars — entire block shifted +0x14 in T06235 */
    .pwm_detail_x0          = (int16_t)0x9C40, /* cal+0x102 = 40000 unsigned (period_max) */
    .pwm_detail_x1          = (int16_t)0x8235, /* cal+0x104 = 33333 unsigned (period_min) */
    .pwm_cached_ptr_0F2     = 5662,            /* cal+0x106 (T06215 cal+0x0F2) */
    .pwm_cached_ptr_102     = 168,             /* cal+0x116 = halfwidth (T06215 cal+0x102) */
    .pwm_const_104          = 354,             /* cal+0x118 = slew_step (T06215 cal+0x104) */

    /* RPM-window block — index 1 differs (6795 vs T06215 6837) */
    .pwm_rpm_windows        = { 5662, 6795, 8808, 10486, 11954, 13422, 18036, 19713 },
    .pwm_window_halfwidth   = 168,             /* cal+0x116 */
    .pwm_slew_step          = 354,             /* cal+0x118 */

    .pwm_y_table            = pwm_y_table_rom,
    .shape_y_table          = shape_y_table_rom,

    .closed_loop_gain_const = 10,              /* flash[0x6056] = 0x000A — invariant */

    .pwm_period_min         = 33333,           /* cal+0x104 = 60.0 Hz */
    .pwm_period_max         = 40000,           /* cal+0x102 = 50.0 Hz */

    .pwm_min                = 0x00CD,          /* flash[0x6058] = 205 */
    .pwm_max                = 0x0F32,          /* flash[0x605A] = 3890 */
};

const pwm_flash_t pwm_flash_rom = { 0 };
