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