Program Listing for File spi3w-esp32.cpp

Return to documentation for file (src/framework/arduino/pal/spi3w-esp32.cpp)

/*
 * \file        spi3w-esp32-ino.cpp
 * \brief       ESP32 3wire SPI cover
 * \author      Infineon Technologies AG
 * \version     4.0.0
 * \copyright   2020-2024 Infineon Technologies AG
 *
 * \attention   This code is normally not needed for ESP32 its clones.
 * Under certain circumstances it might be usefull as this code uses the third
 * SPI channel under VSPI. It only works on ESP32s up to the C2 version, but not
 * for S2/S3 and higher.
 * Before you use this code, try to set the correct SPI pin settings in pal-types-pin.hpp
 * and the 1kOhm resistor between MISO and MOSI (see documentation) to get it running.
 *
 * SPDX-License-Identifier: MIT
 */

#include "spi3w-ino.hpp"
#include "pal-pin-types.hpp"

#if (SPI3W_INO == SPI3W_ESP32)

#include <driver/spi_master.h>
#include "sdkconfig.h"
#include "esp_system.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"

using namespace tle5012;

uint16_t tle5012b_spi_send_and_recv_uint16(spi_device_handle_t spi, uint16_t senddata)
{
    uint8_t temp = 0;
    esp_err_t ret;
    spi_transaction_t t;
    memset(&t, 0, sizeof(t));

    uint8_t p_data[2];
    p_data[0] = senddata >> 8;
    p_data[1] = senddata;

    t.length = 8 * 2;
    t.tx_buffer = p_data;
    t.flags = SPI_TRANS_USE_RXDATA;
    ret = spi_device_polling_transmit(spi, &t);
    assert(ret == ESP_OK);

    temp = *t.rx_data;
    *t.rx_data = *(t.rx_data + 1);
    *(t.rx_data + 1) = temp;

    return *(uint16_t*)t.rx_data;
}


SPIClass3W::SPIClass3W(uint8_t spiNum):SPIClass()
{
    this->mCS = SS;
    this->mMISO = MISO;
    this->mMOSI = MOSI;
    this->mSCK = SCK;
    this->mSpiNum = spiNum;
    spi_device_handle_t esp3Wire = NULL; // Some C structure and
    this->e3Wire = &esp3Wire;            // void pointer magic
}

SPIClass3W::~SPIClass3W()
{
}

void SPIClass3W::begin(uint8_t miso, uint8_t mosi, uint8_t sck, uint8_t cs)
{
    setCSPin(cs);
    this->mMOSI = mosi;
    this->mMISO = miso;
    this->mSCK = sck;

    esp_err_t intError;
    // bus config for the ESP-IDF driver
    spi_bus_config_t bus_config = {};
    bus_config.sclk_io_num = this->mSCK;                            // CLK
    bus_config.mosi_io_num = this->mMOSI;                           // MOSI
    bus_config.miso_io_num = this->mMISO;                           // no MISO setting for 3Wire but we use 4Wire
    bus_config.quadwp_io_num = -1;                                  // Not used
    bus_config.quadhd_io_num = -1;                                  // Not used
    intError = spi_bus_initialize(SPI3_HOST, &bus_config, false);   // use the VSPI of the ESP32 which is SPI3

    // add device for the ESP-IDF driver
    spi_device_interface_config_t dev_config = {}; // initializes all field to 0
    dev_config.address_bits = 0;
    dev_config.command_bits = 0;
    dev_config.dummy_bits = 0;
    dev_config.mode = 1;
    dev_config.clock_speed_hz = SPEED;
    dev_config.spics_io_num = -1;                                   // we set CS external
   // dev_config.flags = SPI_DEVICE_3WIRE;
    dev_config.queue_size = 7;
    dev_config.pre_cb = NULL;
    dev_config.post_cb = NULL;
    intError = spi_bus_add_device(SPI3_HOST, &dev_config, &(*(spi_device_handle_t*)this->e3Wire));
    ESP_ERROR_CHECK(intError);

    gpio_set_direction((gpio_num_t)this->mMOSI, GPIO_MODE_INPUT_OUTPUT_OD); // set the MOSI for INPUT and OUTPUT
    gpio_set_pull_mode((gpio_num_t)this->mMOSI, GPIO_PULLUP_ONLY);

    pinMode(this->mCS, OUTPUT);
    digitalWrite(this->mCS, HIGH);
}

void SPIClass3W::setCSPin(uint8_t cs)
{
    this->mCS = cs;
}

void SPIClass3W::sendReceiveSpi(uint16_t *sent_data, uint16_t size_of_sent_data, uint16_t *received_data, uint16_t size_of_received_data)
{
    uint32_t data_index = 0;
    // Command send
    digitalWrite(this->mCS, LOW);

    for (data_index = 0; data_index < size_of_sent_data; data_index++)
    {
        received_data[0] = tle5012b_spi_send_and_recv_uint16( (*(spi_device_handle_t*)this->e3Wire), sent_data[data_index]);
    }

    // Receive result
    for(data_index = 0; data_index < size_of_received_data; data_index++)
    {
      received_data[data_index] = tle5012b_spi_send_and_recv_uint16( (*(spi_device_handle_t*)this->e3Wire), 0x0000);
    }

    digitalWrite(this->mCS, HIGH);
}

#endif /* SPI3W_INO */