mirror of https://github.com/lumapu/ahoy.git
3 changed files with 195 additions and 2 deletions
@ -0,0 +1,183 @@ |
|||
//-----------------------------------------------------------------------------
|
|||
// 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 |
|||
|
|||
#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 |
|||
|
|||
class esp32_3wSpi { |
|||
public: |
|||
esp32_3wSpi() { |
|||
mInitialized = false; |
|||
} |
|||
|
|||
void init(uint8_t pinSdio = DEF_CMT_SDIO, uint8_t pinSclk = DEF_CMT_SCLK, uint8_t pinCsb = DEF_CMT_CSB, uint8_t pinFcsb = DEF_CMT_FCSB) { |
|||
paramLock = xSemaphoreCreateMutex(); |
|||
spi_bus_config_t buscfg = { |
|||
.mosi_io_num = pinSdio, |
|||
.miso_io_num = -1, // single wire MOSI/MISO
|
|||
.sclk_io_num = pinSclk, |
|||
.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(pinSdio, 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, uint8_t maxlen) { |
|||
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 < maxlen; i++) { |
|||
ESP_ERROR_CHECK(spi_device_polling_transmit(spi_fifo, &t)); |
|||
delayMicroseconds(4); // > 4 us
|
|||
if(0 == i) |
|||
*len = rx_data; |
|||
else |
|||
buf[i-1] = 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__*/ |
Loading…
Reference in new issue