#ifndef MOTOR_CURRENT_H
#define MOTOR_CURRENT_H

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

/*
 * motor_current — ADC-based motor current monitoring and overload protection
 * for Issue #584.
 *
 * Hardware:
 *   ADC3 IN13 (PC3, ADC_CURR_PIN) is already sampled by battery_adc.c via
 *   DMA2_Stream0 circular.  This module reads battery_adc_get_current_ma()
 *   each tick rather than running a second ADC, since total discharge current
 *   on this single-motor balance bot equals motor current plus ~30 mA overhead.
 *
 * Behaviour:
 *   MC_NORMAL     : current_ma <  MOTOR_CURR_SOFT_MA  — full output
 *   MC_SOFT_LIMIT : current_ma in [SOFT_MA, HARD_MA)  — linear PWM reduction
 *   MC_COOLDOWN   : hard cutoff latched after HARD_MA sustained for
 *                   MOTOR_CURR_OVERLOAD_MS (2 s) — zero output for
 *                   MOTOR_CURR_COOLDOWN_MS (10 s), then MC_NORMAL
 *
 * Soft limit formula (MC_SOFT_LIMIT):
 *   scale = (HARD_MA - current_ma) / (HARD_MA - SOFT_MA)   [0..1]
 *   limited_cmd = (int16_t)(cmd * scale)
 *
 * Fault event:
 *   On each hard-cutoff trip, s_fault_count is incremented (saturates at 255)
 *   and motor_current_fault_pending() returns true for one main-loop tick so
 *   the caller can append a fault log entry.
 *
 * Main-loop integration (pseudo-code):
 *
 *   void main_loop_tick(uint32_t now_ms) {
 *       battery_adc_tick(now_ms);
 *       motor_current_tick(now_ms);
 *
 *       if (motor_current_fault_pending())
 *           fault_log_append(FAULT_MOTOR_OVERCURRENT);
 *
 *       int16_t cmd = balance_pid_output();
 *       cmd = motor_current_apply_limit(cmd);
 *       motor_driver_update(&g_motor, cmd, steer, now_ms);
 *
 *       motor_current_send_tlm(now_ms);  // rate-limited to MOTOR_CURR_TLM_HZ
 *   }
 */

/* ---- Thresholds ---- */
#define MOTOR_CURR_HARD_MA       5000u  /* 5 A — hard cutoff level            */
#define MOTOR_CURR_SOFT_MA       4000u  /* 4 A — soft-limit onset (80% of hard) */
#define MOTOR_CURR_OVERLOAD_MS   2000u  /* sustained over HARD_MA before fault */
#define MOTOR_CURR_COOLDOWN_MS  10000u  /* zero-output recovery period (ms)    */
#define MOTOR_CURR_TLM_HZ           5u  /* JLINK_TLM_MOTOR_CURRENT publish rate */

/* ---- State enum ---- */
typedef enum {
    MC_NORMAL     = 0,
    MC_SOFT_LIMIT = 1,
    MC_COOLDOWN   = 2,
} MotorCurrentState;

/* ---- API ---- */

/*
 * motor_current_init() — reset all state.
 * Call once during system init, after battery_adc_init().
 */
void motor_current_init(void);

/*
 * motor_current_tick(now_ms) — evaluate ADC reading, update state machine.
 * Call from main loop after battery_adc_tick(), at any rate ≥ 10 Hz.
 * Non-blocking (<1 µs).
 */
void motor_current_tick(uint32_t now_ms);

/*
 * motor_current_apply_limit(cmd) — scale motor command by current-limit factor.
 *   MC_NORMAL:     returns cmd unchanged.
 *   MC_SOFT_LIMIT: returns cmd scaled down linearly.
 *   MC_COOLDOWN:   returns 0.
 * Call after motor_current_tick() each loop iteration.
 */
int16_t motor_current_apply_limit(int16_t cmd);

/*
 * motor_current_is_faulted() — true while in MC_COOLDOWN (output zeroed).
 */
bool motor_current_is_faulted(void);

/*
 * motor_current_state() — current state machine state.
 */
MotorCurrentState motor_current_state(void);

/*
 * motor_current_ma() — most recent ADC reading used by the state machine (mA).
 */
int32_t motor_current_ma(void);

/*
 * motor_current_fault_count() — lifetime hard-cutoff trip counter (0..255).
 */
uint8_t motor_current_fault_count(void);

/*
 * motor_current_fault_pending() — true for exactly one tick after a hard
 * cutoff trip fires.  Main loop should append a fault log entry and then the
 * flag clears automatically on the next call.
 */
bool motor_current_fault_pending(void);

/*
 * motor_current_send_tlm(now_ms) — transmit JLINK_TLM_MOTOR_CURRENT (0x86)
 * frame to Jetson.  Rate-limited to MOTOR_CURR_TLM_HZ; safe to call every tick.
 */
void motor_current_send_tlm(uint32_t now_ms);

#endif /* MOTOR_CURRENT_H */
