/**
 * ESP32-S3 port for AD5940 — mirrors the RP2040 port as closely as possible.
 * Kept minimal: SPI init, GPIO init, ReadWriteNBytes, CS/RST/Delay.
 */
#include "esp32s3_port.h"
#include "ad5940.h"
#include "driver/gpio.h"
#include "driver/spi_master.h"
#include "esp_log.h"
#include "esp_rom_sys.h"
#include <string.h>

static spi_device_handle_t spi;
static volatile uint32_t ucInterrupted = 0;

static void IRAM_ATTR gpio_isr_handler(void *arg) { ucInterrupted = 1; }

/**
 * Mirrors RP2040 setup_pins():
 *   spi_init(spi0, 16000000);
 *   gpio_set_function(MISO/SCK/MOSI, GPIO_FUNC_SPI);
 *   gpio_init(CS/RST) as output high;
 *   gpio_init(INT) as input with pull-up;
 */
uint32_t AD5940_MCUResourceInit(void *pCfg) {
  // --- SPI at 16 MHz, Mode 0 ---
  spi_bus_config_t buscfg = {
      .miso_io_num = AD5940_MISO_PIN,
      .mosi_io_num = AD5940_MOSI_PIN,
      .sclk_io_num = AD5940_SCK_PIN,
      .quadwp_io_num = -1,
      .quadhd_io_num = -1,
      .max_transfer_sz = 64,
  };
  spi_device_interface_config_t devcfg = {
      .clock_speed_hz = 16 * 1000 * 1000,
      .mode = 0,
      .spics_io_num = -1, // Manual CS
      .queue_size = 1,
  };
  ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_DISABLED));
  ESP_ERROR_CHECK(spi_bus_add_device(SPI2_HOST, &devcfg, &spi));

  // --- CS pin: output, high ---
  gpio_reset_pin(AD5940_CS_PIN);
  gpio_set_direction(AD5940_CS_PIN, GPIO_MODE_OUTPUT);
  gpio_set_level(AD5940_CS_PIN, 1);

  // --- RST pin: output, high ---
  gpio_reset_pin(AD5940_RST_PIN);
  gpio_set_direction(AD5940_RST_PIN, GPIO_MODE_OUTPUT);
  gpio_set_level(AD5940_RST_PIN, 1);

  // --- INT pin: input, pull-up ---
  gpio_reset_pin(AD5940_GP0INT_PIN);
  gpio_set_direction(AD5940_GP0INT_PIN, GPIO_MODE_INPUT);
  gpio_pullup_en(AD5940_GP0INT_PIN);
  gpio_install_isr_service(0);
  gpio_set_intr_type(AD5940_GP0INT_PIN, GPIO_INTR_NEGEDGE);
  gpio_isr_handler_add(AD5940_GP0INT_PIN, gpio_isr_handler,
                       (void *)AD5940_GP0INT_PIN);

  return 0;
}

// --- Platform Interface (same signatures as RP2040 port) ---

void AD5940_CsClr(void) { gpio_set_level(AD5940_CS_PIN, 0); }
void AD5940_CsSet(void) { gpio_set_level(AD5940_CS_PIN, 1); }
void AD5940_RstClr(void) { gpio_set_level(AD5940_RST_PIN, 0); }
void AD5940_RstSet(void) { gpio_set_level(AD5940_RST_PIN, 1); }
void AD5940_Delay10us(uint32_t time) { esp_rom_delay_us(time * 10); }

void AD5940_ReadWriteNBytes(unsigned char *pSendBuffer,
                            unsigned char *pRecvBuff, unsigned long length) {
  spi_transaction_t t = {
      .length = length * 8,
      .tx_buffer = pSendBuffer,
      .rx_buffer = pRecvBuff,
  };
  spi_device_polling_transmit(spi, &t);
}

uint32_t AD5940_GetMCUIntFlag(void) { return ucInterrupted; }

uint32_t AD5940_ClrMCUIntFlag(void) {
  ucInterrupted = 0;
  return 1;
}

void AD5940_MCUGpioWrite(uint32_t data) { (void)data; }
uint32_t AD5940_MCUGpioRead(uint32_t pin) {
  (void)pin;
  return 0;
}
void AD5940_MCUGpioCtrl(uint32_t pin, BoolFlag enable) {
  (void)pin;
  (void)enable;
}
