/*
 * debug_protocol.h
 *
 *  Created on: Mar 5, 2026
 *      Author: janik
 */

#ifndef INC_DEBUG_PROTOCOL_H_
#define INC_DEBUG_PROTOCOL_H_

#include "stm32g4xx_hal.h"
#include <stdint.h>

/* Frame format: [0xAA] [CMD_ID] [PAYLOAD_LEN] [PAYLOAD...] [CRC8] */
#define PROTO_SYNC_BYTE     0xAA
#define PROTO_HEADER_SIZE   3   /* sync + cmd + len */
#define PROTO_MAX_PAYLOAD   128
#define PROTO_RX_BUF_SIZE   144

/* Command IDs */
#define CMD_TELEMETRY       0x01  /* STM32 -> PC */
#define CMD_PARAM_WRITE     0x02  /* PC -> STM32 */
#define CMD_PARAM_WRITE_ACK 0x03  /* STM32 -> PC */
#define CMD_PARAM_READ_ALL  0x04  /* PC -> STM32 (no payload) */
#define CMD_PARAM_VALUE     0x05  /* STM32 -> PC (same layout as ParamWritePayload) */
#define CMD_PING            0x10  /* PC -> STM32 */
#define CMD_PONG            0x11  /* STM32 -> PC */
#define CMD_ERROR_MSG       0xE0  /* STM32 -> PC (text string payload) */

/* Parameter type codes */
#define PTYPE_FLOAT         0
#define PTYPE_UINT16        1
#define PTYPE_UINT8         2
#define PTYPE_INT32         3

/* Parameter IDs — Vfly controller 0x20-0x2F */
#define PID_VFLY_KP                   0x20
#define PID_VFLY_KI                   0x21
#define PID_VFLY_CLAMP                0x22
#define PID_VFLY_LOOP_COUNTER_TRIGGER 0x23
#define PID_VFLY_ACTIVE               0x24
#define PID_VREF                      0x25

/* Parameter IDs — CC controller 0x30-0x3F */
#define PID_CC_TARGET                 0x30
#define PID_CC_GAIN                   0x31
#define PID_CC_MIN_STEP               0x32
#define PID_CC_MAX_STEP               0x33
#define PID_CC_LOOP_COUNTER_TRIGGER   0x34
#define PID_CC_ACTIVE                 0x35

/* Parameter IDs — MPPT controller 0x40-0x4F */
#define PID_MPPT_STEP                 0x40
#define PID_MPPT_IREF_MIN             0x41
#define PID_MPPT_IREF_MAX             0x42
#define PID_MPPT_DV_THRESHOLD         0x43
#define PID_MPPT_LOOP_COUNTER_TRIGGER 0x44
#define PID_MPPT_ACTIVE               0x45
#define PID_MPPT_INITIAL_IREF         0x46
#define PID_MPPT_DEADBAND             0x47
#define PID_VIN_MIN_CTRL              0x50

/* Parameter IDs — Deadtime 0x60-0x6F */
#define PID_DT_SEG0   0x60  /* 0–3 A */
#define PID_DT_SEG1   0x61  /* 3–5 A */
#define PID_DT_SEG2   0x62  /* 5–10 A */
#define PID_DT_SEG3   0x63  /* 10–20 A */
#define PID_DT_SEG4   0x64  /* 20–30 A */
#define PID_DT_SEG5   0x65  /* 30–45 A */

/* Telemetry payload — 68 bytes */
typedef struct __attribute__((packed)) {
    float    vin;
    float    vout;
    float    iin;
    float    iout;
    float    vfly;
    float    etemp;
    int16_t  last_tmp;
    uint16_t VREF;
    int16_t  vfly_correction;
    int16_t  _pad0;
    float    vfly_integral;
    float    vfly_avg_debug;
    float    cc_output_f;
    float    mppt_iref;
    float    mppt_last_vin;
    float    mppt_last_iin;
    float    p_in;
    float    p_out;
    uint8_t  seq;
    uint8_t  _pad1[3];
} TelemetryPayload;

/* Parameter write payload — 8 bytes */
typedef struct __attribute__((packed)) {
    uint8_t  param_id;
    uint8_t  param_type;
    uint8_t  _pad[2];
    union {
        float    f;
        uint32_t u32;
        int32_t  i32;
        uint16_t u16;
        uint8_t  u8;
    } value;
} ParamWritePayload;

/* Parameter table entry */
typedef struct {
    uint8_t  id;
    uint8_t  type;       /* PTYPE_* */
    void    *ptr;
    float    min_val;
    float    max_val;
} ParamEntry;

/* RX parser states */
typedef enum {
    RX_WAIT_SYNC,
    RX_WAIT_CMD,
    RX_WAIT_LEN,
    RX_WAIT_PAYLOAD,
    RX_WAIT_CRC
} ProtoRxState;

/* Protocol context */
typedef struct {
    UART_HandleTypeDef *huart;

    /* TX double buffer — sized for max payload, not just telemetry */
    uint8_t tx_buf[2][PROTO_HEADER_SIZE + PROTO_MAX_PAYLOAD + 1];
    uint8_t tx_active;    /* which buffer is being sent */
    volatile uint8_t tx_busy;

    /* RX */
    uint8_t rx_byte;
    ProtoRxState rx_state;
    uint8_t rx_cmd;
    uint8_t rx_len;
    uint8_t rx_idx;
    uint8_t rx_buf[PROTO_RX_BUF_SIZE];

    /* Telemetry sequence counter */
    uint8_t seq;

    /* Error tracking */
    uint32_t uart_errors;
} ProtoCtx;

/* Public API */
void Proto_Init(UART_HandleTypeDef *huart);
void Proto_SendTelemetry(void);
void Proto_SendError(const char *msg);
void Proto_SendDiagDump(const char *reason);

/* Called from HAL callbacks */
void Proto_RxCpltCallback(UART_HandleTypeDef *huart);
void Proto_TxCpltCallback(UART_HandleTypeDef *huart);
void Proto_ErrorCallback(UART_HandleTypeDef *huart);

/* Global protocol context */
extern ProtoCtx proto;

#endif /* INC_DEBUG_PROTOCOL_H_ */
