#include "spi.h"

#define USE_SPI_HOST SPI2_HOST

static const char *TAG = "SPI_2";

spi_device_handle_t spi2;

void spi_init()
{
    ESP_LOGI(TAG, "初始化SPI IO总线");
    esp_err_t ret;

    // 1. SPI 总线配置
    spi_bus_config_t buscfg = {
        .miso_io_num = VSPI_MISO,         // MISO 引脚
        .mosi_io_num = VSPI_MOSI,         // MOSI 引脚
        .sclk_io_num = VSPI_SCLK,         // 时钟引脚
        .quadwp_io_num = -1,              // 不使用 QWP
        .quadhd_io_num = -1,              // 不使用 QHD
        .max_transfer_sz = 9600, // 最大传输大小
        // .flags = 0,
        // .intr_flags = 0,
    };

    // 2. 初始化 SPI 总线
    ret = spi_bus_initialize(USE_SPI_HOST, &buscfg, SPI_DMA_CH_AUTO);
    if (ret != ESP_OK)
    {
        ESP_LOGE(TAG, "IO总线初始化失败");
        return;
    }

    ESP_LOGI(TAG, "SPI IO总线初始化成功");

    ESP_LOGI(TAG, "SPI 设备配置");

    spi_device_interface_config_t devcfg = {
        .command_bits = 0,            // 无命令位
        .address_bits = 0,            // 无地址位
        .dummy_bits = 0,
        .mode = 0,                  // SPI 模式 0
        .clock_speed_hz = 4000000, //
        .spics_io_num = -1,
        .queue_size = 1,              // 队列深度,因为有几个设备共用了这个SPI，而有的设备有busy信号，准备整个专门的线程去控制如果有busy信号先跳过这次传输
        .flags = SPI_DEVICE_NO_DUMMY, // 禁用 dummy 周期
        .input_delay_ns = 0,
        .pre_cb = NULL,
        .post_cb = NULL,

    };

    ret = spi_bus_add_device(USE_SPI_HOST, &devcfg, &spi2);
    if (ret != ESP_OK)
    {
        ESP_LOGE(TAG, "SPI 设备配置失败");
        return;
    }
}


esp_err_t spi_send_sync_fullduplex(const uint8_t *tx_data, uint8_t *rx_data, size_t len)
{
    esp_err_t ret;
    // ret = spi_device_set_speed(spi2, speed * 1000 * 1000);
    // if (ret == ESP_OK) {
    //     ESP_LOGI(TAG, "EPD speed changed to 4MHz");
    // }else
    // {
    //     ESP_LOGE(TAG, "EPD speed changed ERROR");
    //     return ESP_ERR_INVALID_ARG;
    // }

    // 入参校验：长度为0 或 收发缓冲区同时为NULL
    if (len == 0 || (tx_data == NULL && rx_data == NULL)) {
        ESP_LOGE(TAG, "Invalid args: len=%d, tx=%p, rx=%p", len, tx_data, rx_data);
        return ESP_ERR_INVALID_ARG;
    }

    // 1. 初始化SPI传输结构体（全双工配置核心）
    spi_transaction_t t = {
        .length = len * 8,                // 传输位数（1字节=8位，收发长度一致）
        .tx_buffer = tx_data,             // 发送缓冲区（NULL则发送0x00）
        .rx_buffer = rx_data,             // 接收缓冲区（NULL则丢弃接收数据）
        //.flags = SPI_TRANS_USE_TXDATA | SPI_TRANS_USE_RXDATA,  // 强制使用本地缓冲区
        // 全双工关键：无需额外flag，只要同时配置tx/rx_buffer即启用全双工
    };

    // 2. 同步传输（无队列，阻塞等待硬件完成）
    ret = spi_device_transmit(spi2, &t);

    if (ret != ESP_OK) {
        ESP_LOGE(TAG, "SPI full duplex transmit failed: %s", esp_err_to_name(ret));
    } else {
        ESP_LOGD(TAG, "SPI full duplex transmit success, len=%d", len);
    }

    return ret;
}

// SPI 写数据
esp_err_t spi_send_data_8(uint8_t data)
{
  spi_transaction_t trans = {
      .length = 8,                   // 数据位数
      .flags = SPI_TRANS_USE_TXDATA, // 必须加这个标志
  };
  trans.tx_data[0] = (data);

  esp_err_t err = spi_device_transmit(spi2, &trans);

  return err;
}