#include "mcp2521_hardware_handle.hpp"

#ifdef ESP_PLATFORM
#include "mcp2521_hardware_esp.hpp"
#include "driver/gpio.h"
#include <string.h>

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

MCP2521_HardwareHandle_ESP::MCP2521_HardwareHandle_ESP(
    spi_host_device_t spi_host,
    spi_bus_config_t *bus_config,
    gpio_num_t mosi, 
    gpio_num_t miso, 
    gpio_num_t sclk, 
    gpio_num_t cs, 
    gpio_num_t int_pin
) {
    initPins(int_pin);
    initSPIBus(spi_host, mosi, miso, sclk, bus_config);
    this->spi_bus_config = bus_config;
    initSPIDevice(spi_host, cs);
}

MCP2521_HardwareHandle_ESP::MCP2521_HardwareHandle_ESP(
    spi_host_device_t spi_host,
    spi_bus_config_t *bus_config,
    gpio_num_t cs, 
    gpio_num_t int_pin
) {
    initPins(int_pin);
    this->spi_bus_config = bus_config;
    initSPIDevice(spi_host, cs);
}

MCP2521_HardwareHandle_ESP::~MCP2521_HardwareHandle_ESP() {

}

void MCP2521_HardwareHandle_ESP::initSPIBus(
    spi_host_device_t spi_host,
    gpio_num_t mosi, 
    gpio_num_t miso, 
    gpio_num_t sclk, 
    spi_bus_config_t *bus_config
) {
    memset(bus_config, 0, sizeof(spi_bus_config_t));
    bus_config->mosi_io_num = mosi;
    bus_config->miso_io_num = miso;
    bus_config->sclk_io_num = sclk;

    bus_config->quadwp_io_num = -1;
    bus_config->quadhd_io_num = -1;

    bus_config->flags = SPICOMMON_BUSFLAG_MASTER;
    spi_bus_initialize(spi_host, bus_config, SPI_DMA_CH_AUTO);
}

void MCP2521_HardwareHandle_ESP::initSPIDevice(
    spi_host_device_t spi_host,
    gpio_num_t cs
) {
    memset(&this->spi_device_config, 0, sizeof(spi_device_interface_config_t));
    this->spi_device_config = {
        .command_bits = 8,
        .address_bits = 0,
        .dummy_bits = 0,

        .mode = 0,
        .duty_cycle_pos = 128,
        // cs_ena_pretrans = 0 and cs_ena_posttrans = 0 need to be set to zero, if not its not compatible with full-duplex mode
        // Learned this the hard way
        .cs_ena_pretrans = 0,
        .cs_ena_posttrans = 0,
        .clock_speed_hz = 2000,

        .spics_io_num = cs,
        .flags = SPI_DEVICE_NO_DUMMY,
        .queue_size = 5,
    };

    spi_bus_add_device(spi_host, &this->spi_device_config, &this->spi_device_handle);

    spiMutex = xSemaphoreCreateMutex();
}

spi_bus_config_t * MCP2521_HardwareHandle_ESP::getSPI_bus_config() {
    return this->spi_bus_config;
}

#endif
