/**
 * @file uart_ring_buffer.h
 * @brief 简单高效的环形接收缓冲区（字节队列）接口声明。
 * @details 提供字节写入/读取、可读长度查询、清空与丢弃统计等 API，
 *          适用于中断接收（写）与主循环解析（读）的典型嵌入式串口场景。
 */
#ifndef UART_RING_BUFFER_H
#define UART_RING_BUFFER_H

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

/**
 * @def UART_RX_BUFFER_SIZE
 * @brief 接收环形缓冲区容量（单位：字节）。
 * @note 采用“预留一格”区分空/满策略，最大可用容量为 UART_RX_BUFFER_SIZE-1。
 */
#define UART_RX_BUFFER_SIZE 64

/**
 * @defgroup RingBuffer 环形缓冲区
 * @brief 字节环形缓冲区（接收端）
 * @{
 */

/**
 * @section RingBuffer_Usage 使用说明
 * 典型用法：中断接收（写入环形缓冲）、主循环解析（读取环形缓冲）。
 *
 * 并发访问约束（SPSC，无锁单写单读）：
 * - ISR 生产者：仅调用 uart_ring_buffer_put() 写入数据。
 * - 主循环消费者：仅调用 uart_ring_buffer_get()/uart_ring_buffer_available() 读取数据。
 * - uart_ring_buffer_init()/uart_ring_buffer_clear() 会同时修改读写索引，内部使用最小临界区保护。
 * - 建议在主循环调用 clear/init 前先暂停 UART RX 中断，完成后再恢复，避免与 ISR 竞争。
 *
 * 1) 初始化
 * @code{.c}
 * uart_ring_buffer_init();
 * @endcode
 *
 * 2) 使能串口接收非空中断（RBNE）并开启中断（以 USART0 为例）
 * @code{.c}
 * usart_interrupt_enable(USART0, USART_INT_RBNE);
 * nvic_irq_enable(USART0_IRQn, 2, 0); // 根据工程需要设置优先级
 * @endcode
 *
 * 3) 在中断服务函数中写入环形缓冲（参考你当前工程的写法）
 * @code{.c}
 * void USART0_IRQHandler(void) {
 *     if (RESET != usart_interrupt_flag_get(USART0, USART_INT_FLAG_RBNE)) {
 *         uint8_t data = usart_data_receive(USART0);
 *         (void)uart_ring_buffer_put(data); // 缓冲满时丢弃并计数
 *     }
 * }
 * @endcode
 *
 * 4) 在主循环中读取处理
 * @code{.c}
 * while (uart_ring_buffer_available() > 0) {
 *     int b = uart_ring_buffer_get();
 *     if (b >= 0) {
 *         // 处理字节 b
 *     }
 * }
 * @endcode
 *
 * @note 缓冲区满时新字节会被丢弃，可用 uart_ring_buffer_drop_count() 查看累计丢弃数。
 * @note 采用“预留一格”区分空/满，最大可用容量为 UART_RX_BUFFER_SIZE-1。
 */

/**
 * @brief 初始化环形缓冲区。
 * @details 复位读/写索引与丢弃计数，准备接收数据。
 * @note 若在中断环境使用，初始化前建议关闭相关接收中断以避免并发竞争。
 * @ingroup RingBuffer
 */
void uart_ring_buffer_init(void);

/**
 * @brief 获取当前可读的字节数。
 * @details 返回范围为 [0, UART_RX_BUFFER_SIZE-1]。
 * @return 可读字节数（uint8_t）。
 * @note 预留一个空槽区分“空/满”，因此满时返回 UART_RX_BUFFER_SIZE-1。
 * @ingroup RingBuffer
 */
uint8_t uart_ring_buffer_available(void);

/**
 * @brief 从环形缓冲区读取一个字节。
 * @details 若缓冲区非空，返回队头字节并推进读指针；若为空，返回 -1。
 * @return 读取到的字节（0..255），或 -1 表示缓冲区为空。
 * @retval -1 缓冲区为空，无数据可读。
 * @ingroup RingBuffer
 */
int uart_ring_buffer_get(void);

/**
 * @brief 向环形缓冲区写入一个字节。
 * @param data 待写入的字节。
 * @return 是否写入成功。
 * @retval true  写入成功。
 * @retval false 写入失败（缓冲区已满，数据被丢弃并计数）。
 * @note 如需改为“覆盖写入”策略，可在满时先推进读指针再写入。
 * @ingroup RingBuffer
 */
bool uart_ring_buffer_put(uint8_t data);

/**
 * @brief 清空环形缓冲区。
 * @details 复位读/写索引与丢弃计数，相当于逻辑上丢弃所有已接收数据，不擦除数据区内容。
 * @ingroup RingBuffer
 */
void uart_ring_buffer_clear(void);

/**
 * @brief 获取因缓冲区满而被丢弃的字节累计数量。
 * @details 该计数在 init/clear 时清零。
 * @return 丢弃的累计字节数。
 * @ingroup RingBuffer
 */
uint32_t uart_ring_buffer_drop_count(void);

/** @} */

#endif // UART_RING_BUFFER_H
