#ifndef HARDSPI_H #define HARDSPI_H #include "../Debug.h" #include "driver/spi_master.h" #include #include //static spi_transaction_t trans[2]; #define PIN_NUM_MISO GPIO_NUM_19 #define PIN_NUM_MOSI GPIO_NUM_23 #define PIN_NUM_CLK GPIO_NUM_18 #define PIN_NUM_CS GPIO_NUM_2 template class HardSPI { //class HardSPI { static constexpr int MAX_LEN = 4000; spi_device_handle_t spi; spi_bus_config_t buscfg; spi_device_interface_config_t devcfg; static constexpr const char* TAG = "hwSPI"; public: // can be called before every transmit // static void IRAM_ATTR pre_transfer_callback(spi_transaction_t *t) { // } /** ctor */ HardSPI() { init(); } private: void init() { int ret; // BUS specific options memset(&buscfg, 0, sizeof(buscfg)); buscfg.miso_io_num = PIN_NUM_MISO; buscfg.mosi_io_num = PIN_NUM_MOSI; buscfg.sclk_io_num = PIN_NUM_CLK; buscfg.quadwp_io_num = -1; buscfg.quadhd_io_num = -1; buscfg.max_transfer_sz = MAX_LEN;//320*240*2; buscfg.flags = 0; buscfg.intr_flags = 0; // DEVICE specific options memset(&devcfg, 0, sizeof(devcfg)); devcfg.clock_speed_hz = 10 * 1000 * 1000; devcfg.mode = 0; devcfg.spics_io_num = -1;//PIN_NUM_CS; // currently not used devcfg.queue_size = 2; devcfg.pre_cb = nullptr; //devcfg.pre_cb = pre_transfer_callback; // can be called before every transmit // Initialize the SPI bus ret = spi_bus_initialize(HSPI_HOST, &buscfg, 1); ESP_ERROR_CHECK(ret); // Attach the device to the SPI bus ret = spi_bus_add_device(HSPI_HOST, &devcfg, &spi); ESP_ERROR_CHECK(ret); } public: /** blocking transmit the given bytes */ void write(const uint8_t* data, size_t len) { spi_transaction_t t; memset(&t, 0, sizeof(spi_transaction_t)); while(len > 0) { const size_t chunkLen = min(MAX_LEN, (len)); t.length = 8 * chunkLen; // in bits t.tx_buffer = data; // MOSI only t.flags = 0; // blocking transfer esp_err_t ret = spi_device_polling_transmit(spi, &t); ESP_ERROR_CHECK(ret); // update remaining length and data pointer len -= chunkLen; data += chunkLen; } } void read(uint8_t* dst, size_t len) { // sanity check { const size_t addr = reinterpret_cast(dst); if ((addr % 4) != 0) { ESP_LOGE(TAG, "read-buffer must be 32-bit aligned"); } } spi_transaction_t t; memset(&t, 0, sizeof(spi_transaction_t)); //debugMod1(TAG, "read %d bytes", len); while(len > 0) { const size_t chunkLen = min(MAX_LEN, (len)); //ESP_LOGI(TAG, "- read %d byte chunk", chunkLen); t.length = 8 * chunkLen; // in bits t.rx_buffer = dst; // MISO only t.flags = 0; // blocking transfer esp_err_t ret = spi_device_polling_transmit(spi, &t); ESP_ERROR_CHECK(ret); // update remaining length and destination-data pointer len -= chunkLen; dst += chunkLen; } } /** send 4 bytes onto the bus while reading 4 bytes response */ uint32_t readWriteQuad(uint32_t write) { spi_transaction_t t; memset(&t, 0, sizeof(spi_transaction_t)); t.length = 8*4; t.rxlength = 8*4; t.tx_data[0] = (write >> 24) & 0xFF; t.tx_data[1] = (write >> 16) & 0xFF; t.tx_data[2] = (write >> 8) & 0xFF; t.tx_data[3] = (write >> 0) & 0xFF; t.flags = SPI_TRANS_USE_RXDATA | SPI_TRANS_USE_TXDATA; esp_err_t ret = spi_device_polling_transmit(spi, &t); ESP_ERROR_CHECK(ret); return (static_cast(t.rx_data[0]) << 24) | (static_cast(t.rx_data[1]) << 16) | (static_cast(t.rx_data[2]) << 8) | (static_cast(t.rx_data[3]) << 0); } /** read one byte from the bus */ uint8_t readByte() { spi_transaction_t t; memset(&t, 0, sizeof(spi_transaction_t)); t.length = 8*1; t.flags = SPI_TRANS_USE_RXDATA; esp_err_t ret = spi_device_polling_transmit(spi, &t); ESP_ERROR_CHECK(ret); return t.rx_data[0]; } void writeByte(const uint8_t byte) { spi_transaction_t t; memset(&t, 0, sizeof(spi_transaction_t)); t.length = 8*1; t.tx_data[0] = byte; t.flags = SPI_TRANS_USE_TXDATA; esp_err_t ret = spi_device_polling_transmit(spi, &t); ESP_ERROR_CHECK(ret); } void writeWord(const uint16_t word) { spi_transaction_t t; memset(&t, 0, sizeof(spi_transaction_t)); t.length = 8*2; t.tx_data[0] = static_cast(word>>8); t.tx_data[1] = static_cast(word>>0); t.flags = SPI_TRANS_USE_TXDATA; esp_err_t ret = spi_device_polling_transmit(spi, &t); ESP_ERROR_CHECK(ret); } void writeQuad(const uint32_t quad) { spi_transaction_t t; memset(&t, 0, sizeof(spi_transaction_t)); t.length = 8*4; t.tx_data[0] = static_cast(quad>>24); t.tx_data[1] = static_cast(quad>>16); t.tx_data[2] = static_cast(quad>>8); t.tx_data[3] = static_cast(quad>>0); t.flags = SPI_TRANS_USE_TXDATA; esp_err_t ret = spi_device_polling_transmit(spi, &t); ESP_ERROR_CHECK(ret); } }; #endif // HARDSPI_H