// components/peripherals/src/adc121s021_dma.c
#include "driver/spi_master.h"
#include "esp_log.h"
#include "esp_err.h"

#include "adc121s021_dma.h"
#include "spi_bus_manager.h"

#define TAG "adc_dma"

// Pino de chip-select do ADC121S021 (ajusta se necessário)
#define PIN_NUM_CS 5

// ADC é 12-bit, mas transferimos 16 bits via SPI
#define ADC_BITS 12

// Clock SPI: 1 MHz → ~16 µs de transferência por amostra.
// Com um pequeno delay entre leituras, 100 amostras ficam em ~2–3 ms,
// o que é perfeito para analisar um PWM de 1 kHz a cada 100 ms.
#define SPI_CLOCK_HZ (1 * 1000 * 1000)

static spi_device_handle_t adc_spi = NULL;

void adc121s021_dma_init(void)
{
    if (adc_spi)
    {
        ESP_LOGW(TAG, "ADC121S021 já foi inicializado.");
        return;
    }

    // Garante que o SPI bus partilhado está configurado
    if (!spi_bus_manager_is_initialized())
    {
        ESP_LOGI(TAG, "SPI bus não inicializado. Inicializando...");
        esp_err_t err = spi_bus_manager_init();
        if (err != ESP_OK)
        {
            ESP_LOGE(TAG, "Falha ao inicializar o SPI bus: %s", esp_err_to_name(err));
            return;
        }
    }

    spi_device_interface_config_t devcfg = {
        .clock_speed_hz = SPI_CLOCK_HZ,
        .mode = 0,
        .spics_io_num = PIN_NUM_CS,
        .queue_size = 2, // suficiente para uso em burst
        .flags = SPI_DEVICE_NO_DUMMY,
        .pre_cb = NULL,
        .post_cb = NULL,
    };

    esp_err_t err = spi_bus_add_device(spi_bus_manager_get_host(), &devcfg, &adc_spi);
    if (err != ESP_OK)
    {
        ESP_LOGE(TAG, "Falha ao registrar ADC121S021 no SPI: %s", esp_err_to_name(err));
        adc_spi = NULL;
        return;
    }

    ESP_LOGI(TAG, "ADC121S021 registrado no SPI (CS=%d, fSPI=%d Hz).",
             PIN_NUM_CS, SPI_CLOCK_HZ);
}

bool adc121s021_dma_get_sample(uint16_t *sample)
{
    if (!sample)
    {
        return false;
    }

    if (!adc_spi)
    {
        ESP_LOGE(TAG, "ADC SPI não inicializado! Chama adc121s021_dma_init() primeiro.");
        return false;
    }

    uint8_t tx_buffer[2] = {0x00, 0x00}; // Dummy (ADC só precisa de clock)
    uint8_t rx_buffer[2] = {0};

    spi_transaction_t t = {
        .length = 16, // 16 bits
        .tx_buffer = tx_buffer,
        .rx_buffer = rx_buffer,
        .flags = 0};

    // Polling transmit → menor overhead que fila + espera.
    esp_err_t err = spi_device_polling_transmit(adc_spi, &t);
    if (err != ESP_OK)
    {
        ESP_LOGE(TAG, "Erro na transmissão SPI: %s", esp_err_to_name(err));
        return false;
    }

    // ADC121S021 devolve os 12 bits mais significativos em 16 bits.
    *sample = (uint16_t)(((rx_buffer[0] << 8) | rx_buffer[1]) & 0x0FFF);
    return true;
}
