/*
 * kl_transport.h
 * Transport layer: packet framing, byte-by-byte complement ack, counter.
 */

#ifndef KL_TRANSPORT_H
#define KL_TRANSPORT_H

#include "kl_protocol.h"

/* ================================================================
 * TX state machine
 * ================================================================ */
typedef enum {
    KL_TL_TX_IDLE,
    KL_TL_TX_SEND_BYTE,        /* Submitting data byte to PHY       */
    KL_TL_TX_WAIT_PHY,         /* Waiting for PHY TX+echo done      */
    KL_TL_TX_WAIT_COMPLEMENT,  /* Waiting for master's ~byte        */
    KL_TL_TX_SEND_TERM,        /* Sending 0x03 terminator           */
    KL_TL_TX_WAIT_TERM_PHY,    /* Waiting for terminator echo       */
    KL_TL_TX_DONE,
    KL_TL_TX_ERROR
} KL_TlTxState;

/* ================================================================
 * RX state machine
 * ================================================================ */
typedef enum {
    KL_TL_RX_IDLE,
    KL_TL_RX_WAIT_LEN,         /* Waiting for LENGTH byte           */
    KL_TL_RX_COMPL_LEN,        /* Sending complement for LENGTH     */
    KL_TL_RX_WAIT_CNT,         /* Waiting for COUNTER byte          */
    KL_TL_RX_COMPL_CNT,        /* Sending complement for COUNTER    */
    KL_TL_RX_WAIT_BYTE,        /* Waiting for CMD/DATA byte         */
    KL_TL_RX_COMPL_BYTE,       /* Sending complement for CMD/DATA   */
    KL_TL_RX_WAIT_COMPL_PHY,   /* Waiting for complement echo       */
    KL_TL_RX_WAIT_TERM,        /* Waiting for 0x03 terminator       */
    KL_TL_RX_DONE,
    KL_TL_RX_ERROR
} KL_TlRxState;

/* ================================================================
 * Raw-byte TX state (for handshake bytes, no framing)
 * ================================================================ */
typedef enum {
    KL_TL_RAW_IDLE,
    KL_TL_RAW_WAIT_PHY,
    KL_TL_RAW_DONE
} KL_TlRawState;

/* ================================================================
 * Transport context
 * ================================================================ */
typedef struct {
    uint8_t  pkt_counter;
    uint8_t  counter_initialized;

    /* TX engine */
    KL_TlTxState  tx_state;
    uint8_t       tx_buf[KL_MAX_PACKET_RAW];
    uint8_t       tx_len;               /* Bytes in tx_buf (excl. 0x03) */
    uint8_t       tx_idx;
    uint8_t       tx_last_byte;
    uint32_t      tx_deadline;
    uint32_t      tx_next_tick;         /* Inter-byte gap timing        */

    /* RX engine */
    KL_TlRxState  rx_state;
    uint8_t       rx_buf[KL_MAX_PACKET_RAW];
    uint8_t       rx_idx;
    uint8_t       rx_expected_total;    /* LENGTH field value + 1 (for 0x03) */
    uint8_t       rx_pkt_len;           /* LENGTH field value           */
    uint8_t       rx_last_byte;         /* Last received byte (for complement send) */
    uint32_t      rx_deadline;
    uint32_t      rx_byte_deadline;
    KL_Packet     rx_packet;

    /* Raw byte TX */
    KL_TlRawState raw_state;
} KL_Transport;

/* ================================================================
 * API
 * ================================================================ */
void            KL_Transport_Init(void);
void            KL_Transport_Service(void);
void            KL_Transport_ResetCounter(void);

/* Packet TX (non-blocking) */
int             KL_Transport_SendPacket(const uint8_t *payload, uint8_t payload_len);
int             KL_Transport_TxBusy(void);
int             KL_Transport_TxDone(void);
int             KL_Transport_TxError(void);
void            KL_Transport_TxReset(void);

/* Packet RX (non-blocking) */
int             KL_Transport_StartReceive(uint32_t timeout_ms);
int             KL_Transport_RxBusy(void);
int             KL_Transport_RxDone(void);
int             KL_Transport_RxError(void);
const KL_Packet* KL_Transport_GetRxPacket(void);
void            KL_Transport_RxReset(void);

/* Diagnostics */
int             KL_Transport_RxHadData(void);   /* True if RX consumed any bytes before error */

/* Convenience */
void            KL_Transport_SendAck(void);
void            KL_Transport_SendNak(void);

/* Raw byte TX for handshake (no framing, no complement) */
int             KL_Transport_SendRawByte(uint8_t byte);
int             KL_Transport_RawTxDone(void);
void            KL_Transport_RawTxReset(void);

#endif /* KL_TRANSPORT_H */
