acid-drop

- Hacking the planet from a LilyGo T-Deck using custom firmware
git clone git://git.acid.vegas/acid-drop.git
Log | Files | Refs | Archive | README | LICENSE

Arduino_ESP32SPI.cpp (24632B)

      1 /*
      2  * start rewrite from:
      3  * https://github.com/espressif/arduino-esp32.git
      4  */
      5 #include "Arduino_ESP32SPI.h"
      6 
      7 #if defined(ESP32)
      8 
      9 #define WAIT_SPI_NOT_BUSY while (_spi->dev->cmd.usr)
     10 
     11 struct spi_struct_t
     12 {
     13   spi_dev_t *dev;
     14 #if !CONFIG_DISABLE_HAL_LOCKS
     15   xSemaphoreHandle lock;
     16 #endif
     17   uint8_t num;
     18 };
     19 
     20 #if CONFIG_DISABLE_HAL_LOCKS
     21 #define SPI_MUTEX_LOCK()
     22 #define SPI_MUTEX_UNLOCK()
     23 
     24 static spi_t _spi_bus_array[] = {
     25 #if CONFIG_IDF_TARGET_ESP32S2
     26     {(volatile spi_dev_t *)(DR_REG_SPI1_BASE), 0},
     27     {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), 1},
     28     {(volatile spi_dev_t *)(DR_REG_SPI3_BASE), 2}
     29 #elif CONFIG_IDF_TARGET_ESP32S3
     30     {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), 0},
     31     {(volatile spi_dev_t *)(DR_REG_SPI3_BASE), 1}
     32 #else
     33     {(volatile spi_dev_t *)(DR_REG_SPI0_BASE), 0},
     34     {(volatile spi_dev_t *)(DR_REG_SPI1_BASE), 1},
     35     {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), 2},
     36     {(volatile spi_dev_t *)(DR_REG_SPI3_BASE), 3}
     37 #endif
     38 };
     39 #else // !CONFIG_DISABLE_HAL_LOCKS
     40 #define SPI_MUTEX_LOCK() \
     41   do                     \
     42   {                      \
     43   } while (xSemaphoreTake(_spi->lock, portMAX_DELAY) != pdPASS)
     44 #define SPI_MUTEX_UNLOCK() xSemaphoreGive(_spi->lock)
     45 
     46 static spi_t _spi_bus_array[] = {
     47 #if CONFIG_IDF_TARGET_ESP32S2
     48     {(volatile spi_dev_t *)(DR_REG_SPI1_BASE), NULL, 0},
     49     {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), NULL, 1},
     50     {(volatile spi_dev_t *)(DR_REG_SPI3_BASE), NULL, 2}
     51 #elif CONFIG_IDF_TARGET_ESP32S3
     52     {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), NULL, 0},
     53     {(volatile spi_dev_t *)(DR_REG_SPI3_BASE), NULL, 1}
     54 #elif CONFIG_IDF_TARGET_ESP32C3
     55     {(volatile spi_dev_t *)(&GPSPI2), NULL, FSPI}
     56 #else
     57     {(volatile spi_dev_t *)(DR_REG_SPI0_BASE), NULL, 0},
     58     {(volatile spi_dev_t *)(DR_REG_SPI1_BASE), NULL, 1},
     59     {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), NULL, 2},
     60     {(volatile spi_dev_t *)(DR_REG_SPI3_BASE), NULL, 3}
     61 #endif
     62 };
     63 #endif // CONFIG_DISABLE_HAL_LOCKS
     64 
     65 Arduino_ESP32SPI::Arduino_ESP32SPI(int8_t dc /* = GFX_NOT_DEFINED */, int8_t cs /* = GFX_NOT_DEFINED */, int8_t sck /* = GFX_NOT_DEFINED */, int8_t mosi /* = GFX_NOT_DEFINED */, int8_t miso /* = GFX_NOT_DEFINED */, uint8_t spi_num /* = VSPI for ESP32, FSPI for S2 & C3 */, bool is_shared_interface /* = true */)
     66     : _dc(dc), _spi_num(spi_num), _is_shared_interface(is_shared_interface)
     67 {
     68 #if CONFIG_IDF_TARGET_ESP32
     69   if (
     70       sck == GFX_NOT_DEFINED && miso == GFX_NOT_DEFINED && mosi == GFX_NOT_DEFINED && cs == GFX_NOT_DEFINED)
     71   {
     72     _sck = (_spi_num == VSPI) ? SCK : 14;
     73     _miso = (_spi_num == VSPI) ? MISO : 12;
     74     _mosi = (_spi_num == VSPI) ? MOSI : 13;
     75     _cs = (_spi_num == VSPI) ? SS : 15;
     76   }
     77   else
     78   {
     79     _sck = sck;
     80     _miso = miso;
     81     _mosi = mosi;
     82     _cs = cs;
     83   }
     84 #else
     85   if (sck == GFX_NOT_DEFINED && miso == GFX_NOT_DEFINED && mosi == GFX_NOT_DEFINED && cs == GFX_NOT_DEFINED)
     86   {
     87     _sck = SCK;
     88     _miso = MISO;
     89     _mosi = MOSI;
     90     _cs = SS;
     91   }
     92   else
     93   {
     94     _sck = sck;
     95     _miso = miso;
     96     _mosi = mosi;
     97     _cs = cs;
     98   }
     99 #endif
    100 }
    101 
    102 static void _on_apb_change(void *arg, apb_change_ev_t ev_type, uint32_t old_apb, uint32_t new_apb)
    103 {
    104   spi_t *_spi = (spi_t *)arg;
    105   if (ev_type == APB_BEFORE_CHANGE)
    106   {
    107     SPI_MUTEX_LOCK();
    108     WAIT_SPI_NOT_BUSY;
    109   }
    110   else
    111   {
    112     _spi->dev->clock.val = spiFrequencyToClockDiv(old_apb / ((_spi->dev->clock.clkdiv_pre + 1) * (_spi->dev->clock.clkcnt_n + 1)));
    113     SPI_MUTEX_UNLOCK();
    114   }
    115 }
    116 
    117 static void spiInitBus(spi_t *spi)
    118 {
    119 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32
    120   spi->dev->slave.trans_done = 0;
    121 #endif
    122   spi->dev->slave.val = 0;
    123 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3
    124   spi->dev->misc.val = 0;
    125 #else
    126   spi->dev->pin.val = 0;
    127 #endif
    128   spi->dev->user.val = 0;
    129   spi->dev->user1.val = 0;
    130   spi->dev->ctrl.val = 0;
    131 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32
    132   spi->dev->ctrl1.val = 0;
    133   spi->dev->ctrl2.val = 0;
    134 #else
    135   spi->dev->clk_gate.val = 0;
    136   spi->dev->dma_conf.val = 0;
    137   spi->dev->dma_conf.rx_afifo_rst = 1;
    138   spi->dev->dma_conf.buf_afifo_rst = 1;
    139 #endif
    140   spi->dev->clock.val = 0;
    141 }
    142 
    143 bool Arduino_ESP32SPI::begin(int32_t speed, int8_t dataMode)
    144 {
    145   // set SPI parameters
    146   _speed = (speed == GFX_NOT_DEFINED) ? SPI_DEFAULT_FREQ : speed;
    147   _dataMode = (dataMode == GFX_NOT_DEFINED) ? SPI_MODE0 : dataMode;
    148 
    149   if (!_div)
    150   {
    151     _div = spiFrequencyToClockDiv(_speed);
    152   }
    153 
    154   // set pin mode
    155   if (_dc != GFX_NOT_DEFINED)
    156   {
    157     pinMode(_dc, OUTPUT);
    158     digitalWrite(_dc, HIGH); // Data mode
    159   }
    160   if (_cs != GFX_NOT_DEFINED)
    161   {
    162     pinMode(_cs, OUTPUT);
    163     digitalWrite(_cs, HIGH); // disable chip select
    164   }
    165 
    166 #if (CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
    167   // set fastIO variables
    168   if (_dc >= 32)
    169   {
    170     _dcPinMask = digitalPinToBitMask(_dc);
    171     _dcPortSet = (PORTreg_t)&GPIO.out1_w1ts.val;
    172     _dcPortClr = (PORTreg_t)&GPIO.out1_w1tc.val;
    173   }
    174   else
    175 #endif
    176       if (_dc != GFX_NOT_DEFINED)
    177   {
    178     _dcPinMask = digitalPinToBitMask(_dc);
    179     _dcPortSet = (PORTreg_t)&GPIO.out_w1ts;
    180     _dcPortClr = (PORTreg_t)&GPIO.out_w1tc;
    181   }
    182 
    183 #if (CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
    184   if (_cs >= 32)
    185   {
    186     _csPinMask = digitalPinToBitMask(_cs);
    187     _csPortSet = (PORTreg_t)&GPIO.out1_w1ts.val;
    188     _csPortClr = (PORTreg_t)&GPIO.out1_w1tc.val;
    189   }
    190   else
    191 #endif
    192       if (_cs != GFX_NOT_DEFINED)
    193   {
    194     _csPinMask = digitalPinToBitMask(_cs);
    195     _csPortSet = (PORTreg_t)&GPIO.out_w1ts;
    196     _csPortClr = (PORTreg_t)&GPIO.out_w1tc;
    197   }
    198 
    199   // SPI.begin(_sck, _miso, _mosi);
    200   // _spi = spiStartBus(_spi_num, _div, SPI_MODE0, SPI_MSBFIRST);
    201   _spi = &_spi_bus_array[_spi_num];
    202 
    203 #if !CONFIG_DISABLE_HAL_LOCKS
    204   if (_spi->lock == NULL)
    205   {
    206     _spi->lock = xSemaphoreCreateMutex();
    207   }
    208 #endif
    209 
    210 #if CONFIG_IDF_TARGET_ESP32S2
    211   if (_spi_num == FSPI)
    212   {
    213     DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI2_CLK_EN);
    214     DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI2_RST);
    215   }
    216   else if (_spi_num == HSPI)
    217   {
    218     DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI3_CLK_EN);
    219     DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI3_RST);
    220   }
    221   else
    222   {
    223     DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI01_CLK_EN);
    224     DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI01_RST);
    225   }
    226 #elif CONFIG_IDF_TARGET_ESP32S3
    227   if (_spi_num == FSPI)
    228   {
    229     periph_module_reset(PERIPH_SPI2_MODULE);
    230     periph_module_enable(PERIPH_SPI2_MODULE);
    231   }
    232   else if (_spi_num == HSPI)
    233   {
    234     periph_module_reset(PERIPH_SPI3_MODULE);
    235     periph_module_enable(PERIPH_SPI3_MODULE);
    236   }
    237 #elif CONFIG_IDF_TARGET_ESP32
    238   if (_spi_num == HSPI)
    239   {
    240     DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI2_CLK_EN);
    241     DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI2_RST);
    242   }
    243   else if (_spi_num == VSPI)
    244   {
    245     DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI3_CLK_EN);
    246     DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI3_RST);
    247   }
    248   else
    249   {
    250     DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI01_CLK_EN);
    251     DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI01_RST);
    252   }
    253 #elif CONFIG_IDF_TARGET_ESP32C3
    254   periph_module_reset(PERIPH_SPI2_MODULE);
    255   periph_module_enable(PERIPH_SPI2_MODULE);
    256 #endif
    257 
    258   SPI_MUTEX_LOCK();
    259   spiInitBus(_spi);
    260 #if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3
    261   _spi->dev->clk_gate.clk_en = 1;
    262   _spi->dev->clk_gate.mst_clk_sel = 1;
    263   _spi->dev->clk_gate.mst_clk_active = 1;
    264   _spi->dev->dma_conf.tx_seg_trans_clr_en = 1;
    265   _spi->dev->dma_conf.rx_seg_trans_clr_en = 1;
    266   _spi->dev->dma_conf.dma_seg_trans_en = 0;
    267 #endif
    268   _spi->dev->user.usr_mosi = 1;
    269   if (_miso < 0)
    270   {
    271     _spi->dev->user.usr_miso = 0;
    272     _spi->dev->user.doutdin = 0;
    273   }
    274   else
    275   {
    276     _spi->dev->user.usr_miso = 1;
    277     _spi->dev->user.doutdin = 1;
    278   }
    279 
    280   for (uint8_t i = 0; i < 16; i++)
    281   {
    282     _spi->dev->data_buf[i] = 0x00000000;
    283   }
    284   SPI_MUTEX_UNLOCK();
    285 
    286   spiSetDataMode(_spi, _dataMode);
    287   spiSetBitOrder(_spi, _bitOrder);
    288   spiSetClockDiv(_spi, _div);
    289 
    290   addApbChangeCallback(_spi, _on_apb_change);
    291 
    292   spiAttachSCK(_spi, _sck);
    293 
    294   if (_miso != GFX_NOT_DEFINED)
    295   {
    296     spiAttachMISO(_spi, _miso);
    297   }
    298 
    299   spiAttachMOSI(_spi, _mosi);
    300 
    301   if (!_is_shared_interface)
    302   {
    303     spiTransaction(_spi, _div, _dataMode, _bitOrder);
    304   }
    305 
    306   return true;
    307 }
    308 
    309 void Arduino_ESP32SPI::beginWrite()
    310 {
    311   _data_buf_bit_idx = 0;
    312   _buffer[0] = 0;
    313 
    314   if (_is_shared_interface)
    315   {
    316     spiTransaction(_spi, _div, _dataMode, _bitOrder);
    317   }
    318 
    319   if (_dc != GFX_NOT_DEFINED)
    320   {
    321     DC_HIGH();
    322   }
    323   CS_LOW();
    324 }
    325 
    326 void Arduino_ESP32SPI::endWrite()
    327 {
    328   if (_data_buf_bit_idx > 0)
    329   {
    330     flush_data_buf();
    331   }
    332 
    333   if (_is_shared_interface)
    334   {
    335     spiEndTransaction(_spi);
    336   }
    337 
    338   CS_HIGH();
    339 }
    340 
    341 void Arduino_ESP32SPI::writeCommand(uint8_t c)
    342 {
    343   if (_dc < 0) // 9-bit SPI
    344   {
    345     WRITE9BIT(c);
    346   }
    347   else
    348   {
    349     if (_data_buf_bit_idx > 0)
    350     {
    351       flush_data_buf();
    352     }
    353 
    354     DC_LOW();
    355 
    356     MOSI_BIT_LEN = 7;
    357 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32
    358     MISO_BIT_LEN = 0;
    359 #endif
    360     _spi->dev->data_buf[0] = c;
    361 #if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3
    362     _spi->dev->cmd.update = 1;
    363     while (_spi->dev->cmd.update)
    364       ;
    365 #endif
    366     _spi->dev->cmd.usr = 1;
    367     WAIT_SPI_NOT_BUSY;
    368 
    369     DC_HIGH();
    370   }
    371 }
    372 
    373 void Arduino_ESP32SPI::writeCommand16(uint16_t c)
    374 {
    375   if (_dc < 0) // 9-bit SPI
    376   {
    377     _data16.value = c;
    378     WRITE9BIT(_data16.msb);
    379     WRITE9BIT(_data16.lsb);
    380   }
    381   else
    382   {
    383     if (_data_buf_bit_idx > 0)
    384     {
    385       flush_data_buf();
    386     }
    387 
    388     DC_LOW();
    389 
    390     MOSI_BIT_LEN = 15;
    391 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32
    392     MISO_BIT_LEN = 0;
    393 #endif
    394     MSB_16_SET(_spi->dev->data_buf[0], c);
    395 #if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3
    396     _spi->dev->cmd.update = 1;
    397     while (_spi->dev->cmd.update)
    398       ;
    399 #endif
    400     _spi->dev->cmd.usr = 1;
    401     WAIT_SPI_NOT_BUSY;
    402 
    403     DC_HIGH();
    404   }
    405 }
    406 
    407 void Arduino_ESP32SPI::write(uint8_t d)
    408 {
    409   if (_dc < 0) // 9-bit SPI
    410   {
    411     WRITE9BIT(0x100 | d);
    412   }
    413   else
    414   {
    415     WRITE8BIT(d);
    416   }
    417 }
    418 
    419 void Arduino_ESP32SPI::write16(uint16_t d)
    420 {
    421   _data16.value = d;
    422   if (_dc < 0) // 9-bit SPI
    423   {
    424     WRITE9BIT(0x100 | _data16.msb);
    425     WRITE9BIT(0x100 | _data16.lsb);
    426   }
    427   else
    428   {
    429     WRITE8BIT(_data16.msb);
    430     WRITE8BIT(_data16.lsb);
    431   }
    432 }
    433 
    434 void Arduino_ESP32SPI::writeRepeat(uint16_t p, uint32_t len)
    435 {
    436   if (_data_buf_bit_idx > 0)
    437   {
    438     flush_data_buf();
    439   }
    440 
    441   if (_dc < 0) // 9-bit SPI
    442   {
    443     _data16.value = p;
    444     uint32_t hi = 0x100 | _data16.msb;
    445     uint32_t lo = 0x100 | _data16.lsb;
    446     uint16_t idx;
    447     uint8_t shift;
    448     uint32_t l;
    449     uint16_t bufLen = (len <= 28) ? len : 28;
    450     int16_t xferLen;
    451     for (uint32_t t = 0; t < bufLen; t++)
    452     {
    453       idx = _data_buf_bit_idx >> 3;
    454       shift = (_data_buf_bit_idx % 8);
    455       if (shift)
    456       {
    457         _buffer[idx++] |= hi >> (shift + 1);
    458         _buffer[idx] = hi << (7 - shift);
    459       }
    460       else
    461       {
    462         _buffer[idx++] = hi >> 1;
    463         _buffer[idx] = hi << 7;
    464       }
    465       _data_buf_bit_idx += 9;
    466 
    467       idx = _data_buf_bit_idx >> 3;
    468       shift = (_data_buf_bit_idx % 8);
    469       if (shift)
    470       {
    471         _buffer[idx++] |= lo >> (shift + 1);
    472         _buffer[idx] = lo << (7 - shift);
    473       }
    474       else
    475       {
    476         _buffer[idx++] = lo >> 1;
    477         _buffer[idx] = lo << 7;
    478       }
    479       _data_buf_bit_idx += 9;
    480     }
    481 
    482     if (_miso < 0)
    483     {
    484       l = (_data_buf_bit_idx + 31) / 32;
    485       for (uint32_t i = 0; i < l; i++)
    486       {
    487         _spi->dev->data_buf[i] = _buffer32[i];
    488       }
    489     }
    490 
    491     // Issue pixels in blocks from temp buffer
    492     while (len) // While pixels remain
    493     {
    494       xferLen = (bufLen < len) ? bufLen : len; // How many this pass?
    495       _data_buf_bit_idx = xferLen * 18;
    496       MOSI_BIT_LEN = _data_buf_bit_idx - 1;
    497 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32
    498       MISO_BIT_LEN = 0;
    499 #endif
    500       if (_miso != GFX_NOT_DEFINED)
    501       {
    502         l = (_data_buf_bit_idx + 31) / 32;
    503         for (uint32_t i = 0; i < l; i++)
    504         {
    505           _spi->dev->data_buf[i] = _buffer32[i];
    506         }
    507       }
    508 #if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3
    509       _spi->dev->cmd.update = 1;
    510       while (_spi->dev->cmd.update)
    511         ;
    512 #endif
    513       _spi->dev->cmd.usr = 1;
    514       WAIT_SPI_NOT_BUSY;
    515 
    516       len -= xferLen;
    517     }
    518   }
    519   else // 8-bit SPI
    520   {
    521     uint16_t bufLen = (len < 32) ? len : 32;
    522     int16_t xferLen, l;
    523     uint32_t c32;
    524     MSB_32_16_16_SET(c32, p, p);
    525 
    526     if (_miso < 0)
    527     {
    528       l = (bufLen + 1) / 2;
    529       for (uint32_t i = 0; i < l; i++)
    530       {
    531         _spi->dev->data_buf[i] = c32;
    532       }
    533     }
    534 
    535     // Issue pixels in blocks from temp buffer
    536     while (len) // While pixels remain
    537     {
    538       xferLen = (bufLen <= len) ? bufLen : len; // How many this pass?
    539       MOSI_BIT_LEN = (xferLen * 16) - 1;
    540 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32
    541       MISO_BIT_LEN = 0;
    542 #endif
    543       if (_miso != GFX_NOT_DEFINED)
    544       {
    545         l = (xferLen + 1) / 2;
    546         for (uint32_t i = 0; i < l; i++)
    547         {
    548           _spi->dev->data_buf[i] = c32;
    549         }
    550       }
    551 #if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3
    552       _spi->dev->cmd.update = 1;
    553       while (_spi->dev->cmd.update)
    554         ;
    555 #endif
    556       _spi->dev->cmd.usr = 1;
    557       WAIT_SPI_NOT_BUSY;
    558 
    559       len -= xferLen;
    560     }
    561   }
    562 
    563   _data_buf_bit_idx = 0;
    564 }
    565 
    566 void Arduino_ESP32SPI::writePixels(uint16_t *data, uint32_t len)
    567 {
    568   if (_dc < 0) // 9-bit SPI
    569   {
    570     while (len--)
    571     {
    572       write16(*data++);
    573     }
    574   }
    575   else // 8-bit SPI
    576   {
    577     uint16_t p1, p2;
    578     if (len >= 32)
    579     {
    580       if (_data_buf_bit_idx > 0)
    581       {
    582         flush_data_buf();
    583       }
    584 
    585       MOSI_BIT_LEN = 511;
    586 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32
    587       MISO_BIT_LEN = 0;
    588 #endif
    589       while (len >= 32)
    590       {
    591         for (uint8_t i = 0; i < 16; i++)
    592         {
    593           p1 = *data++;
    594           p2 = *data++;
    595           MSB_32_16_16_SET(_spi->dev->data_buf[i], p1, p2);
    596         }
    597 #if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3
    598         _spi->dev->cmd.update = 1;
    599         while (_spi->dev->cmd.update)
    600           ;
    601 #endif
    602         _spi->dev->cmd.usr = 1;
    603         WAIT_SPI_NOT_BUSY;
    604 
    605         len -= 32;
    606       }
    607     }
    608 
    609     if ((len > 0) && ((len % 2) == 0))
    610     {
    611       if (_data_buf_bit_idx > 0)
    612       {
    613         flush_data_buf();
    614       }
    615 
    616       MOSI_BIT_LEN = (len * 16) - 1;
    617 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32
    618       MISO_BIT_LEN = 0;
    619 #endif
    620       len >>= 1; // 2 pixels to a 32-bit data
    621       for (uint32_t i = 0; i < len; i++)
    622       {
    623         p1 = *data++;
    624         p2 = *data++;
    625         MSB_32_16_16_SET(_spi->dev->data_buf[i], p1, p2);
    626       }
    627 #if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3
    628       _spi->dev->cmd.update = 1;
    629       while (_spi->dev->cmd.update)
    630         ;
    631 #endif
    632       _spi->dev->cmd.usr = 1;
    633       WAIT_SPI_NOT_BUSY;
    634     }
    635     else
    636     {
    637       while (len--)
    638       {
    639         write16(*data++);
    640       }
    641     }
    642   }
    643 }
    644 
    645 void Arduino_ESP32SPI::writeC8D8(uint8_t c, uint8_t d)
    646 {
    647   if (_dc < 0) // 9-bit SPI
    648   {
    649     WRITE9BIT(c);
    650     WRITE9BIT(0x100 | d);
    651   }
    652   else
    653   {
    654     if (_data_buf_bit_idx > 0)
    655     {
    656       flush_data_buf();
    657     }
    658 
    659     DC_LOW();
    660 
    661     MOSI_BIT_LEN = 7;
    662 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32
    663     MISO_BIT_LEN = 0;
    664 #endif
    665     _spi->dev->data_buf[0] = c;
    666 #if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3
    667     _spi->dev->cmd.update = 1;
    668     while (_spi->dev->cmd.update)
    669       ;
    670 #endif
    671     _spi->dev->cmd.usr = 1;
    672     WAIT_SPI_NOT_BUSY;
    673 
    674     DC_HIGH();
    675 
    676     MOSI_BIT_LEN = 7;
    677 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32
    678     MISO_BIT_LEN = 0;
    679 #endif
    680     _spi->dev->data_buf[0] = d;
    681 #if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3
    682     _spi->dev->cmd.update = 1;
    683     while (_spi->dev->cmd.update)
    684       ;
    685 #endif
    686     _spi->dev->cmd.usr = 1;
    687     WAIT_SPI_NOT_BUSY;
    688   }
    689 }
    690 
    691 void Arduino_ESP32SPI::writeC8D16(uint8_t c, uint16_t d)
    692 {
    693   if (_dc < 0) // 9-bit SPI
    694   {
    695     WRITE9BIT(c);
    696     _data16.value = d;
    697     WRITE9BIT(0x100 | _data16.msb);
    698     WRITE9BIT(0x100 | _data16.lsb);
    699   }
    700   else
    701   {
    702     if (_data_buf_bit_idx > 0)
    703     {
    704       flush_data_buf();
    705     }
    706 
    707     DC_LOW();
    708 
    709     MOSI_BIT_LEN = 7;
    710 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32
    711     MISO_BIT_LEN = 0;
    712 #endif
    713     _spi->dev->data_buf[0] = c;
    714 #if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3
    715     _spi->dev->cmd.update = 1;
    716     while (_spi->dev->cmd.update)
    717       ;
    718 #endif
    719     _spi->dev->cmd.usr = 1;
    720     WAIT_SPI_NOT_BUSY;
    721 
    722     DC_HIGH();
    723 
    724     MOSI_BIT_LEN = 15;
    725 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32
    726     MISO_BIT_LEN = 0;
    727 #endif
    728     MSB_16_SET(_spi->dev->data_buf[0], d);
    729 #if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3
    730     _spi->dev->cmd.update = 1;
    731     while (_spi->dev->cmd.update)
    732       ;
    733 #endif
    734     _spi->dev->cmd.usr = 1;
    735     WAIT_SPI_NOT_BUSY;
    736   }
    737 }
    738 
    739 void Arduino_ESP32SPI::writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2)
    740 {
    741   if (_dc < 0) // 9-bit SPI
    742   {
    743     WRITE9BIT(c);
    744     _data16.value = d1;
    745     WRITE9BIT(0x100 | _data16.msb);
    746     WRITE9BIT(0x100 | _data16.lsb);
    747     _data16.value = d2;
    748     WRITE9BIT(0x100 | _data16.msb);
    749     WRITE9BIT(0x100 | _data16.lsb);
    750   }
    751   else
    752   {
    753     if (_data_buf_bit_idx > 0)
    754     {
    755       flush_data_buf();
    756     }
    757 
    758     DC_LOW();
    759 
    760     MOSI_BIT_LEN = 7;
    761 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32
    762     MISO_BIT_LEN = 0;
    763 #endif
    764     _spi->dev->data_buf[0] = c;
    765 #if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3
    766     _spi->dev->cmd.update = 1;
    767     while (_spi->dev->cmd.update)
    768       ;
    769 #endif
    770     _spi->dev->cmd.usr = 1;
    771     WAIT_SPI_NOT_BUSY;
    772 
    773     DC_HIGH();
    774 
    775     MOSI_BIT_LEN = 31;
    776 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32
    777     MISO_BIT_LEN = 0;
    778 #endif
    779     MSB_32_16_16_SET(_spi->dev->data_buf[0], d1, d2);
    780 #if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3
    781     _spi->dev->cmd.update = 1;
    782     while (_spi->dev->cmd.update)
    783       ;
    784 #endif
    785     _spi->dev->cmd.usr = 1;
    786     WAIT_SPI_NOT_BUSY;
    787   }
    788 }
    789 
    790 void Arduino_ESP32SPI::writeBytes(uint8_t *data, uint32_t len)
    791 {
    792   if (_dc < 0) // 9-bit SPI
    793   {
    794     while (len--)
    795     {
    796       write(*data++);
    797     }
    798   }
    799   else // 8-bit SPI
    800   {
    801     uint32_t *p = (uint32_t *)data;
    802     if (len >= 64)
    803     {
    804       if (_data_buf_bit_idx > 0)
    805       {
    806         flush_data_buf();
    807       }
    808       MOSI_BIT_LEN = 511;
    809 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32
    810       MISO_BIT_LEN = 0;
    811 #endif
    812       while (len >= 64)
    813       {
    814         for (uint32_t i = 0; i < 16; i++)
    815         {
    816           _spi->dev->data_buf[i] = *p++;
    817         }
    818 #if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3
    819         _spi->dev->cmd.update = 1;
    820         while (_spi->dev->cmd.update)
    821           ;
    822 #endif
    823         _spi->dev->cmd.usr = 1;
    824         WAIT_SPI_NOT_BUSY;
    825 
    826         len -= 64;
    827         data += 64;
    828       }
    829     }
    830 
    831     if ((len > 0) && ((len % 4) == 0))
    832     {
    833       if (_data_buf_bit_idx > 0)
    834       {
    835         flush_data_buf();
    836       }
    837 
    838       MOSI_BIT_LEN = (len * 8) - 1;
    839 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32
    840       MISO_BIT_LEN = 0;
    841 #endif
    842       len >>= 2; // 4 bytes to a 32-bit data
    843       for (uint32_t i = 0; i < len; i++)
    844       {
    845         _spi->dev->data_buf[i] = *p++;
    846       }
    847 #if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3
    848       _spi->dev->cmd.update = 1;
    849       while (_spi->dev->cmd.update)
    850         ;
    851 #endif
    852       _spi->dev->cmd.usr = 1;
    853       WAIT_SPI_NOT_BUSY;
    854     }
    855     else
    856     {
    857       while (len--)
    858       {
    859         write(*data++);
    860       }
    861     }
    862   }
    863 }
    864 
    865 void Arduino_ESP32SPI::writePattern(uint8_t *data, uint8_t len, uint32_t repeat)
    866 {
    867   while (repeat--)
    868   {
    869     writeBytes(data, len);
    870   }
    871 }
    872 
    873 void Arduino_ESP32SPI::writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len)
    874 {
    875   if (_dc < 0) // 9-bit SPI
    876   {
    877     while (len--)
    878     {
    879       write16(idx[*data++]);
    880     }
    881   }
    882   else // 8-bit SPI
    883   {
    884     uint16_t p1, p2;
    885     if (len >= 32)
    886     {
    887       if (_data_buf_bit_idx > 0)
    888       {
    889         flush_data_buf();
    890       }
    891 
    892       MOSI_BIT_LEN = 511;
    893 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32
    894       MISO_BIT_LEN = 0;
    895 #endif
    896       while (len >= 32)
    897       {
    898         for (uint8_t i = 0; i < 16; i++)
    899         {
    900           p1 = idx[*data++];
    901           p2 = idx[*data++];
    902           MSB_32_16_16_SET(_spi->dev->data_buf[i], p1, p2);
    903         }
    904 #if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3
    905         _spi->dev->cmd.update = 1;
    906         while (_spi->dev->cmd.update)
    907           ;
    908 #endif
    909         _spi->dev->cmd.usr = 1;
    910         WAIT_SPI_NOT_BUSY;
    911 
    912         len -= 32;
    913       }
    914     }
    915 
    916     if ((len > 0) && ((len % 2) == 0))
    917     {
    918       if (_data_buf_bit_idx > 0)
    919       {
    920         flush_data_buf();
    921       }
    922 
    923       MOSI_BIT_LEN = (len * 16) - 1;
    924 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32
    925       MISO_BIT_LEN = 0;
    926 #endif
    927       len >>= 1; // 2 pixels to a 32-bit data
    928       for (uint32_t i = 0; i < len; i++)
    929       {
    930         p1 = *data++;
    931         p2 = *data++;
    932         MSB_32_16_16_SET(_spi->dev->data_buf[i], p1, p2);
    933       }
    934 #if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3
    935       _spi->dev->cmd.update = 1;
    936       while (_spi->dev->cmd.update)
    937         ;
    938 #endif
    939       _spi->dev->cmd.usr = 1;
    940       WAIT_SPI_NOT_BUSY;
    941     }
    942     else
    943     {
    944       while (len--)
    945       {
    946         write16(*data++);
    947       }
    948     }
    949   }
    950 }
    951 
    952 void Arduino_ESP32SPI::writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len)
    953 {
    954   uint16_t p;
    955   if (_dc < 0) // 9-bit SPI
    956   {
    957     uint16_t hi, lo;
    958     while (len--)
    959     {
    960       _data16.value = idx[*data++];
    961       hi = 0x100 | _data16.msb;
    962       lo = 0x100 | _data16.lsb;
    963       WRITE9BIT(hi);
    964       WRITE9BIT(lo);
    965       WRITE9BIT(hi);
    966       WRITE9BIT(lo);
    967     }
    968   }
    969   else // 8-bit SPI
    970   {
    971     if (len >= 16)
    972     {
    973       if (_data_buf_bit_idx > 0)
    974       {
    975         flush_data_buf();
    976       }
    977 
    978       MOSI_BIT_LEN = 511;
    979 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32
    980       MISO_BIT_LEN = 0;
    981 #endif
    982       while (len >= 16)
    983       {
    984         for (uint8_t i = 0; i < 16; i++)
    985         {
    986           p = idx[*data++];
    987           MSB_32_16_16_SET(_spi->dev->data_buf[i], p, p);
    988         }
    989 #if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3
    990         _spi->dev->cmd.update = 1;
    991         while (_spi->dev->cmd.update)
    992           ;
    993 #endif
    994         _spi->dev->cmd.usr = 1;
    995         WAIT_SPI_NOT_BUSY;
    996 
    997         len -= 16;
    998       }
    999     }
   1000 
   1001     if ((len > 0) && ((len % 2) == 0))
   1002     {
   1003       if (_data_buf_bit_idx > 0)
   1004       {
   1005         flush_data_buf();
   1006       }
   1007 
   1008       MOSI_BIT_LEN = (len * 16) - 1;
   1009 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32
   1010       MISO_BIT_LEN = 0;
   1011 #endif
   1012       for (uint32_t i = 0; i < len; i++)
   1013       {
   1014         p = idx[*data++];
   1015         MSB_32_16_16_SET(_spi->dev->data_buf[i], p, p);
   1016       }
   1017 #if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3
   1018       _spi->dev->cmd.update = 1;
   1019       while (_spi->dev->cmd.update)
   1020         ;
   1021 #endif
   1022       _spi->dev->cmd.usr = 1;
   1023       WAIT_SPI_NOT_BUSY;
   1024     }
   1025     else
   1026     {
   1027       while (len--)
   1028       {
   1029         write16(*data++);
   1030       }
   1031     }
   1032   }
   1033 }
   1034 
   1035 void Arduino_ESP32SPI::flush_data_buf()
   1036 {
   1037   MOSI_BIT_LEN = _data_buf_bit_idx - 1;
   1038 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32
   1039   MISO_BIT_LEN = 0;
   1040 #endif
   1041   uint32_t len = (_data_buf_bit_idx + 31) / 32;
   1042   for (uint32_t i = 0; i < len; i++)
   1043   {
   1044     _spi->dev->data_buf[i] = _buffer32[i];
   1045   }
   1046 #if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3
   1047   _spi->dev->cmd.update = 1;
   1048   while (_spi->dev->cmd.update)
   1049     ;
   1050 #endif
   1051   _spi->dev->cmd.usr = 1;
   1052   WAIT_SPI_NOT_BUSY;
   1053 
   1054   _data_buf_bit_idx = 0;
   1055 }
   1056 
   1057 INLINE void Arduino_ESP32SPI::WRITE8BIT(uint8_t d)
   1058 {
   1059   uint16_t idx = _data_buf_bit_idx >> 3;
   1060   _buffer[idx] = d;
   1061   _data_buf_bit_idx += 8;
   1062   if (_data_buf_bit_idx >= 512)
   1063   {
   1064     flush_data_buf();
   1065   }
   1066 }
   1067 
   1068 INLINE void Arduino_ESP32SPI::WRITE9BIT(uint32_t d)
   1069 {
   1070   uint16_t idx = _data_buf_bit_idx >> 3;
   1071   uint8_t shift = (_data_buf_bit_idx % 8);
   1072   if (shift)
   1073   {
   1074     _buffer[idx++] |= d >> (shift + 1);
   1075     _buffer[idx] = d << (7 - shift);
   1076   }
   1077   else
   1078   {
   1079     _buffer[idx++] = d >> 1;
   1080     _buffer[idx] = d << 7;
   1081   }
   1082   _data_buf_bit_idx += 9;
   1083   if (_data_buf_bit_idx >= 504) // 56 bytes * 9 bits
   1084   {
   1085     flush_data_buf();
   1086   }
   1087 }
   1088 
   1089 /******** low level bit twiddling **********/
   1090 
   1091 INLINE void Arduino_ESP32SPI::DC_HIGH(void)
   1092 {
   1093   *_dcPortSet = _dcPinMask;
   1094 }
   1095 
   1096 INLINE void Arduino_ESP32SPI::DC_LOW(void)
   1097 {
   1098   *_dcPortClr = _dcPinMask;
   1099 }
   1100 
   1101 INLINE void Arduino_ESP32SPI::CS_HIGH(void)
   1102 {
   1103   if (_cs != GFX_NOT_DEFINED)
   1104   {
   1105     *_csPortSet = _csPinMask;
   1106   }
   1107 }
   1108 
   1109 INLINE void Arduino_ESP32SPI::CS_LOW(void)
   1110 {
   1111   if (_cs != GFX_NOT_DEFINED)
   1112   {
   1113     *_csPortClr = _csPinMask;
   1114   }
   1115 }
   1116 
   1117 #endif // #if defined(ESP32)