You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

189 lines
5.9 KiB

//-----------------------------------------------------------------------------
// 2023 Ahoy, https://github.com/lumpapu/ahoy
// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/
//-----------------------------------------------------------------------------
#ifndef __ESP32_3WSPI_H__
#define __ESP32_3WSPI_H__
#include "Arduino.h"
#if defined(ESP32)
#include "driver/spi_master.h"
#include "esp_rom_gpio.h" // for esp_rom_gpio_connect_out_signal
#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
#define CLK_PIN 6
#define MOSI_PIN 5
#else
#define CLK_PIN 18
#define MOSI_PIN 23
#endif
#define SPI_CLK 1 * 1000 * 1000 // 1MHz
#define SPI_PARAM_LOCK() \
do { \
} while (xSemaphoreTake(paramLock, portMAX_DELAY) != pdPASS)
#define SPI_PARAM_UNLOCK() xSemaphoreGive(paramLock)
// for ESP32 this is the so-called HSPI
// for ESP32-S2/S3/C3 this nomenclature does not really exist anymore,
// it is simply the first externally usable hardware SPI master controller
#define SPI_CMT SPI2_HOST
template<uint8_t CSB_PIN=5, uint8_t FCSB_PIN=4> //, uint8_t GPIO3_PIN=15>
class esp32_3wSpi {
public:
esp32_3wSpi() {
mInitialized = false;
}
void setup(uint8_t pinCsb = CSB_PIN, uint8_t pinFcsb = FCSB_PIN) { //, uint8_t pinGpio3 = GPIO3_PIN) {
paramLock = xSemaphoreCreateMutex();
spi_bus_config_t buscfg = {
.mosi_io_num = MOSI_PIN,
.miso_io_num = -1, // single wire MOSI/MISO
.sclk_io_num = CLK_PIN,
.quadwp_io_num = -1,
.quadhd_io_num = -1,
.max_transfer_sz = 32,
};
spi_device_interface_config_t devcfg = {
.command_bits = 1,
.address_bits = 7,
.dummy_bits = 0,
.mode = 0,
.cs_ena_pretrans = 1,
.cs_ena_posttrans = 1,
.clock_speed_hz = SPI_CLK,
.spics_io_num = pinCsb,
.flags = SPI_DEVICE_HALFDUPLEX | SPI_DEVICE_3WIRE,
.queue_size = 1,
.pre_cb = NULL,
.post_cb = NULL,
};
ESP_ERROR_CHECK(spi_bus_initialize(SPI_CMT, &buscfg, SPI_DMA_DISABLED));
ESP_ERROR_CHECK(spi_bus_add_device(SPI_CMT, &devcfg, &spi_reg));
// FiFo
spi_device_interface_config_t devcfg2 = {
.command_bits = 0,
.address_bits = 0,
.dummy_bits = 0,
.mode = 0,
.cs_ena_pretrans = 2,
.cs_ena_posttrans = (uint8_t)(1 / (SPI_CLK * 10e6 * 2) + 2), // >2 us
.clock_speed_hz = SPI_CLK,
.spics_io_num = pinFcsb,
.flags = SPI_DEVICE_HALFDUPLEX | SPI_DEVICE_3WIRE,
.queue_size = 1,
.pre_cb = NULL,
.post_cb = NULL,
};
ESP_ERROR_CHECK(spi_bus_add_device(SPI_CMT, &devcfg2, &spi_fifo));
esp_rom_gpio_connect_out_signal(MOSI_PIN, spi_periph_signal[SPI_CMT].spid_out, true, false);
delay(100);
//pinMode(pinGpio3, INPUT);
mInitialized = true;
}
void writeReg(uint8_t addr, uint8_t reg) {
if(!mInitialized)
return;
uint8_t tx_data;
tx_data = ~reg;
spi_transaction_t t = {
.cmd = 1,
.addr = (uint64_t)(~addr),
.length = 8,
.tx_buffer = &tx_data,
.rx_buffer = NULL
};
SPI_PARAM_LOCK();
ESP_ERROR_CHECK(spi_device_polling_transmit(spi_reg, &t));
SPI_PARAM_UNLOCK();
delayMicroseconds(100);
}
uint8_t readReg(uint8_t addr) {
if(!mInitialized)
return 0;
uint8_t rx_data;
spi_transaction_t t = {
.cmd = 0,
.addr = (uint64_t)(~addr),
.length = 8,
.rxlength = 8,
.tx_buffer = NULL,
.rx_buffer = &rx_data
};
SPI_PARAM_LOCK();
ESP_ERROR_CHECK(spi_device_polling_transmit(spi_reg, &t));
SPI_PARAM_UNLOCK();
delayMicroseconds(100);
return rx_data;
}
void writeFifo(uint8_t buf[], uint8_t len) {
if(!mInitialized)
return;
uint8_t tx_data;
spi_transaction_t t = {
.length = 8,
.tx_buffer = &tx_data, // reference to write data
.rx_buffer = NULL
};
SPI_PARAM_LOCK();
for(uint8_t i = 0; i < len; i++) {
tx_data = ~buf[i]; // negate buffer contents
ESP_ERROR_CHECK(spi_device_polling_transmit(spi_fifo, &t));
delayMicroseconds(4); // > 4 us
}
SPI_PARAM_UNLOCK();
}
void readFifo(uint8_t buf[], uint8_t len) {
if(!mInitialized)
return;
uint8_t rx_data;
spi_transaction_t t = {
.length = 8,
.rxlength = 8,
.tx_buffer = NULL,
.rx_buffer = &rx_data
};
SPI_PARAM_LOCK();
for(uint8_t i = 0; i < len; i++) {
ESP_ERROR_CHECK(spi_device_polling_transmit(spi_fifo, &t));
delayMicroseconds(4); // > 4 us
buf[i] = rx_data;
}
SPI_PARAM_UNLOCK();
}
private:
spi_device_handle_t spi_reg, spi_fifo;
bool mInitialized;
SemaphoreHandle_t paramLock = NULL;
};
#else
template<uint8_t CSB_PIN=5, uint8_t FCSB_PIN=4>
class esp32_3wSpi {
public:
esp32_3wSpi() {}
void setup() {}
void loop() {}
};
#endif
#endif /*__ESP32_3WSPI_H__*/