/*
 * kline_ring.c
 * ISR-safe ring buffer for K-Line UART1 RX.
 *
 * Producer: HAL_UART_RxCpltCallback (ISR context) via KLine_Ring_ISR_PushByte()
 * Consumer: KLine_FSM_Run()          (main-loop context)
 *
 * No locking needed: head written only by ISR, tail written only by main.
 */

#include "kline_ring.h"
#include "main.h"   /* for huart1 */

volatile uint8_t kline_rx_staging = 0;

static volatile uint8_t  ring_buf[KLINE_RING_SIZE];
static volatile uint32_t ring_head = 0;   /* written by ISR   */
static volatile uint32_t ring_tail = 0;   /* written by main  */

void KLine_Ring_Init(void)
{
    ring_head = 0;
    ring_tail = 0;
    HAL_UART_Receive_IT(&huart1, (uint8_t*)&kline_rx_staging, 1);
}

/* ---- ISR context ---- */
void KLine_Ring_ISR_PushByte(uint8_t b)
{
    uint32_t next = (ring_head + 1u) & KLINE_RING_MASK;
    if (next != ring_tail)          /* drop byte on overflow rather than corrupt */
    {
        ring_buf[ring_head] = b;
        ring_head = next;
    }
    /* Re-arm immediately – this is the ONLY place we call Receive_IT for UART1 */
    HAL_UART_Receive_IT(&huart1, (uint8_t*)&kline_rx_staging, 1);
}

/* ---- Main-loop context ---- */
uint8_t KLine_Ring_Available(void)
{
    return ring_head != ring_tail;
}

uint8_t KLine_Ring_Pop(void)
{
    uint8_t b = ring_buf[ring_tail];
    ring_tail = (ring_tail + 1u) & KLINE_RING_MASK;
    return b;
}

void KLine_Ring_Flush(void)
{
    ring_tail = ring_head;
}
