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_HWSPI.cpp (11851B)

      1 /*
      2  * start rewrite from:
      3  * https://github.com/adafruit/Adafruit-GFX-Library.git
      4  */
      5 #include "Arduino_HWSPI.h"
      6 
      7 #if defined(SPI_HAS_TRANSACTION)
      8 #define SPI_BEGIN_TRANSACTION() _spi->beginTransaction(mySPISettings)
      9 #define SPI_END_TRANSACTION() _spi->endTransaction()
     10 #else
     11 #define SPI_BEGIN_TRANSACTION() \
     12   {                             \
     13   }
     14 #define SPI_END_TRANSACTION() \
     15   {                           \
     16   }
     17 #endif
     18 
     19 #if defined(SPI_HAS_TRANSACTION)
     20 static SPISettings mySPISettings;
     21 #elif defined(__AVR__) || defined(CORE_TEENSY)
     22 static uint8_t SPCRbackup;
     23 static uint8_t mySPCR;
     24 #endif
     25 
     26 #if defined(ESP32)
     27 Arduino_HWSPI::Arduino_HWSPI(int8_t dc, int8_t cs /* = GFX_NOT_DEFINED */, int8_t sck /* = GFX_NOT_DEFINED */, int8_t mosi /* = GFX_NOT_DEFINED */, int8_t miso /* = GFX_NOT_DEFINED */, SPIClass *spi, bool is_shared_interface /* = true */)
     28     : _dc(dc), _cs(cs), _sck(sck), _mosi(mosi), _miso(miso), _spi(spi), _is_shared_interface(is_shared_interface)
     29 {
     30 #else
     31 Arduino_HWSPI::Arduino_HWSPI(int8_t dc, int8_t cs /* = GFX_NOT_DEFINED */, SPIClass *spi, bool is_shared_interface /* = true */)
     32     : _dc(dc), _cs(cs), _spi(spi), _is_shared_interface(is_shared_interface)
     33 {
     34 #endif
     35 }
     36 
     37 bool Arduino_HWSPI::begin(int32_t speed, int8_t dataMode)
     38 {
     39   _speed = (speed == GFX_NOT_DEFINED) ? SPI_DEFAULT_FREQ : speed;
     40   _dataMode = dataMode;
     41 
     42   pinMode(_dc, OUTPUT);
     43   digitalWrite(_dc, HIGH); // Data mode
     44   if (_cs != GFX_NOT_DEFINED)
     45   {
     46     pinMode(_cs, OUTPUT);
     47     digitalWrite(_cs, HIGH); // Deselect
     48   }
     49 
     50 #if defined(USE_FAST_PINIO)
     51 #if defined(HAS_PORT_SET_CLR)
     52 #if defined(ARDUINO_ARCH_NRF52840)
     53   uint32_t pin = digitalPinToPinName((pin_size_t)_dc);
     54   NRF_GPIO_Type *reg = nrf_gpio_pin_port_decode(&pin);
     55   _dcPortSet = &reg->OUTSET;
     56   _dcPortClr = &reg->OUTCLR;
     57   _dcPinMask = 1UL << pin;
     58   if (_cs != GFX_NOT_DEFINED)
     59   {
     60     pin = digitalPinToPinName((pin_size_t)_cs);
     61     reg = nrf_gpio_pin_port_decode(&pin);
     62     _csPortSet = &reg->OUTSET;
     63     _csPortClr = &reg->OUTCLR;
     64     _csPinMask = 1UL << pin;
     65   }
     66 #elif defined(TARGET_RP2040)
     67   _dcPinMask = digitalPinToBitMask(_dc);
     68   _dcPortSet = (PORTreg_t)&sio_hw->gpio_set;
     69   _dcPortClr = (PORTreg_t)&sio_hw->gpio_clr;
     70   if (_cs != GFX_NOT_DEFINED)
     71   {
     72     _csPinMask = digitalPinToBitMask(_cs);
     73     _csPortSet = (PORTreg_t)&sio_hw->gpio_set;
     74     _csPortClr = (PORTreg_t)&sio_hw->gpio_clr;
     75   }
     76 #elif defined(ESP32) && (CONFIG_IDF_TARGET_ESP32C3)
     77   _dcPinMask = digitalPinToBitMask(_dc);
     78   _dcPortSet = (PORTreg_t)&GPIO.out_w1ts;
     79   _dcPortClr = (PORTreg_t)&GPIO.out_w1tc;
     80   if (_cs != GFX_NOT_DEFINED)
     81   {
     82     _csPinMask = digitalPinToBitMask(_cs);
     83     _csPortSet = (PORTreg_t)&GPIO.out_w1ts;
     84     _csPortClr = (PORTreg_t)&GPIO.out_w1tc;
     85   }
     86 #elif defined(ESP32)
     87   _dcPinMask = digitalPinToBitMask(_dc);
     88   if (_dc >= 32)
     89   {
     90     _dcPortSet = (PORTreg_t)&GPIO.out1_w1ts.val;
     91     _dcPortClr = (PORTreg_t)&GPIO.out1_w1tc.val;
     92   }
     93   else
     94   {
     95     _dcPortSet = (PORTreg_t)&GPIO.out_w1ts;
     96     _dcPortClr = (PORTreg_t)&GPIO.out_w1tc;
     97   }
     98   if (_cs >= 32)
     99   {
    100     _csPinMask = digitalPinToBitMask(_cs);
    101     _csPortSet = (PORTreg_t)&GPIO.out1_w1ts.val;
    102     _csPortClr = (PORTreg_t)&GPIO.out1_w1tc.val;
    103   }
    104   else if (_cs != GFX_NOT_DEFINED)
    105   {
    106     _csPinMask = digitalPinToBitMask(_cs);
    107     _csPortSet = (PORTreg_t)&GPIO.out_w1ts;
    108     _csPortClr = (PORTreg_t)&GPIO.out_w1tc;
    109   }
    110 #elif defined(CORE_TEENSY)
    111 #if !defined(KINETISK)
    112   _dcPinMask = digitalPinToBitMask(_dc);
    113 #endif
    114   _dcPortSet = portSetRegister(_dc);
    115   _dcPortClr = portClearRegister(_dc);
    116   if (_cs != GFX_NOT_DEFINED)
    117   {
    118 #if !defined(KINETISK)
    119     _csPinMask = digitalPinToBitMask(_cs);
    120 #endif
    121     _csPortSet = portSetRegister(_cs);
    122     _csPortClr = portClearRegister(_cs);
    123   }
    124 #else  // !CORE_TEENSY
    125   _dcPinMask = digitalPinToBitMask(_dc);
    126   _dcPortSet = &(PORT->Group[g_APinDescription[_dc].ulPort].OUTSET.reg);
    127   _dcPortClr = &(PORT->Group[g_APinDescription[_dc].ulPort].OUTCLR.reg);
    128   if (_cs != GFX_NOT_DEFINED)
    129   {
    130     _csPinMask = digitalPinToBitMask(_cs);
    131     _csPortSet = &(PORT->Group[g_APinDescription[_cs].ulPort].OUTSET.reg);
    132     _csPortClr = &(PORT->Group[g_APinDescription[_cs].ulPort].OUTCLR.reg);
    133   }
    134 #endif // end !CORE_TEENSY
    135 #else  // !HAS_PORT_SET_CLR
    136   _dcPort = (PORTreg_t)portOutputRegister(digitalPinToPort(_dc));
    137   _dcPinMaskSet = digitalPinToBitMask(_dc);
    138   _dcPinMaskClr = ~_dcPinMaskSet;
    139   if (_cs != GFX_NOT_DEFINED)
    140   {
    141     _csPort = (PORTreg_t)portOutputRegister(digitalPinToPort(_cs));
    142     _csPinMaskSet = digitalPinToBitMask(_cs);
    143   }
    144   _csPinMaskClr = ~_csPinMaskSet;
    145 #endif // !HAS_PORT_SET_CLR
    146 #endif // USE_FAST_PINIO
    147 
    148 #if defined(ESP32)
    149   _spi->begin(_sck, _miso, _mosi);
    150   if (_dataMode == GFX_NOT_DEFINED)
    151   {
    152     _dataMode = SPI_MODE0;
    153   }
    154   mySPISettings = SPISettings(_speed, MSBFIRST, _dataMode);
    155 #elif defined(ESP8266)
    156   _spi->begin();
    157   if (_dataMode == GFX_NOT_DEFINED)
    158   {
    159     _dataMode = SPI_MODE0;
    160   }
    161   mySPISettings = SPISettings(_speed, MSBFIRST, _dataMode);
    162 // Teensy 4.x
    163 #elif defined(__IMXRT1052__) || defined(__IMXRT1062__)
    164   _spi->begin();
    165   if (_dataMode == GFX_NOT_DEFINED)
    166   {
    167     _dataMode = SPI_MODE0;
    168   }
    169   mySPISettings = SPISettings(_speed, MSBFIRST, _dataMode);
    170 #elif defined(SPI_HAS_TRANSACTION)
    171   _spi->begin();
    172   if (_dataMode == GFX_NOT_DEFINED)
    173   {
    174     _dataMode = SPI_MODE2;
    175   }
    176   mySPISettings = SPISettings(_speed, MSBFIRST, _dataMode);
    177 #elif defined(__AVR__) || defined(CORE_TEENSY)
    178   SPCRbackup = SPCR;
    179   _spi->begin();
    180   _spi->setClockDivider(SPI_CLOCK_DIV2);
    181   if (_dataMode == GFX_NOT_DEFINED)
    182   {
    183     _dataMode = SPI_MODE2;
    184   }
    185   _spi->setDataMode(_dataMode);
    186   mySPCR = SPCR;     // save our preferred state
    187   SPCR = SPCRbackup; // then restore
    188 #elif defined(__SAM3X8E__)
    189   _spi->begin();
    190   _spi->setClockDivider(21); // 4MHz
    191   if (_dataMode == GFX_NOT_DEFINED)
    192   {
    193     _dataMode = SPI_MODE2;
    194   }
    195   _spi->setDataMode(_dataMode);
    196 #elif defined(__arm__)
    197   if (_dataMode == GFX_NOT_DEFINED)
    198   {
    199     _dataMode = SPI_MODE2;
    200   }
    201 #endif
    202 
    203   return true;
    204 }
    205 
    206 void Arduino_HWSPI::beginWrite()
    207 {
    208   if (_is_shared_interface)
    209   {
    210     SPI_BEGIN_TRANSACTION();
    211   }
    212 
    213   DC_HIGH();
    214   CS_LOW();
    215 }
    216 
    217 void Arduino_HWSPI::endWrite()
    218 {
    219   CS_HIGH();
    220 
    221   if (_is_shared_interface)
    222   {
    223     SPI_END_TRANSACTION();
    224   }
    225 }
    226 
    227 void Arduino_HWSPI::writeCommand(uint8_t c)
    228 {
    229   DC_LOW();
    230 
    231   WRITE(c);
    232 
    233   DC_HIGH();
    234 }
    235 
    236 void Arduino_HWSPI::writeCommand16(uint16_t c)
    237 {
    238   DC_LOW();
    239 
    240 #if defined(LITTLE_FOOT_PRINT)
    241   _data16.value = c;
    242   WRITE(_data16.msb);
    243   WRITE(_data16.lsb);
    244 #else  // !defined(LITTLE_FOOT_PRINT)
    245   WRITE16(c);
    246 #endif // !defined(LITTLE_FOOT_PRINT)
    247 
    248   DC_HIGH();
    249 }
    250 
    251 void Arduino_HWSPI::write(uint8_t d)
    252 {
    253   WRITE(d);
    254 }
    255 
    256 void Arduino_HWSPI::write16(uint16_t d)
    257 {
    258 #if defined(LITTLE_FOOT_PRINT)
    259   _data16.value = d;
    260   WRITE(_data16.msb);
    261   WRITE(_data16.lsb);
    262 #else  // !defined(LITTLE_FOOT_PRINT)
    263   WRITE16(d);
    264 #endif // !defined(LITTLE_FOOT_PRINT)
    265 }
    266 
    267 void Arduino_HWSPI::writeRepeat(uint16_t p, uint32_t len)
    268 {
    269 #if defined(LITTLE_FOOT_PRINT)
    270   _data16.value = p;
    271   while (len--)
    272   {
    273     WRITE(_data16.msb);
    274     WRITE(_data16.lsb);
    275   }
    276 #elif defined(ESP8266) || defined(CONFIG_ARCH_CHIP_CXD56XX)
    277   MSB_16_SET(p, p);
    278   uint32_t xferLen = (len < SPI_MAX_PIXELS_AT_ONCE) ? len : SPI_MAX_PIXELS_AT_ONCE;
    279   for (uint32_t i = 0; i < xferLen; i++)
    280   {
    281     _buffer.v16[i] = p;
    282   }
    283 
    284   while (len)
    285   {
    286     xferLen = (len < SPI_MAX_PIXELS_AT_ONCE) ? len : SPI_MAX_PIXELS_AT_ONCE;
    287     len -= xferLen;
    288 
    289     xferLen += xferLen;
    290     WRITEBUF(_buffer.v8, xferLen);
    291   }
    292 #else  // other arch
    293   MSB_16_SET(p, p);
    294   uint32_t xferLen;
    295 
    296   while (len)
    297   {
    298     xferLen = (len < SPI_MAX_PIXELS_AT_ONCE) ? len : SPI_MAX_PIXELS_AT_ONCE;
    299     for (uint32_t i = 0; i < xferLen; i++)
    300     {
    301       _buffer.v16[i] = p;
    302     }
    303     len -= xferLen;
    304 
    305     xferLen += xferLen;
    306     WRITEBUF(_buffer.v8, xferLen);
    307   }
    308 #endif // other arch
    309 }
    310 
    311 void Arduino_HWSPI::writePixels(uint16_t *data, uint32_t len)
    312 {
    313 #if defined(LITTLE_FOOT_PRINT)
    314   while (len--)
    315   {
    316     _data16.value = *data++;
    317     WRITE(_data16.msb);
    318     WRITE(_data16.lsb);
    319   }
    320 #else  // !defined(LITTLE_FOOT_PRINT)
    321   uint32_t xferLen;
    322   uint8_t *b;
    323   union
    324   {
    325     uint16_t val;
    326     struct
    327     {
    328       uint8_t lsb;
    329       uint8_t msb;
    330     };
    331   } t;
    332   while (len)
    333   {
    334     xferLen = (len < SPI_MAX_PIXELS_AT_ONCE) ? len : SPI_MAX_PIXELS_AT_ONCE;
    335     b = _buffer.v8;
    336     for (uint32_t i = 0; i < xferLen; i++)
    337     {
    338       t.val = *data++;
    339       *b++ = t.msb;
    340       *b++ = t.lsb;
    341     }
    342     len -= xferLen;
    343 
    344     xferLen += xferLen; // uint16_t to uint8_t, double length
    345     WRITEBUF(_buffer.v8, xferLen);
    346   }
    347 #endif // !defined(LITTLE_FOOT_PRINT)
    348 }
    349 
    350 #if !defined(LITTLE_FOOT_PRINT)
    351 void Arduino_HWSPI::writeBytes(uint8_t *data, uint32_t len)
    352 {
    353   WRITEBUF(data, len);
    354 }
    355 
    356 void Arduino_HWSPI::writePattern(uint8_t *data, uint8_t len, uint32_t repeat)
    357 {
    358 #if defined(ESP8266) || defined(ESP32)
    359   _spi->writePattern(data, len, repeat);
    360 #else  // !(defined(ESP8266) || defined(ESP32))
    361   while (repeat--)
    362   {
    363     WRITEBUF(data, len);
    364   }
    365 #endif // !(defined(ESP8266) || defined(ESP32))
    366 }
    367 #endif // !defined(LITTLE_FOOT_PRINT)
    368 
    369 INLINE void Arduino_HWSPI::WRITE(uint8_t d)
    370 {
    371 #if defined(SPI_HAS_TRANSACTION)
    372   _spi->transfer(d);
    373 #elif defined(__AVR__) || defined(CORE_TEENSY)
    374   SPCRbackup = SPCR;
    375   SPCR = mySPCR;
    376   _spi->transfer(d);
    377   SPCR = SPCRbackup;
    378 #elif defined(__arm__)
    379   _spi->setClockDivider(21); // 4MHz
    380   _spi->setDataMode(_dataMode);
    381   _spi->transfer(d);
    382 #endif
    383 }
    384 
    385 #if !defined(LITTLE_FOOT_PRINT)
    386 
    387 INLINE void Arduino_HWSPI::WRITE16(uint16_t d)
    388 {
    389 #if defined(ESP8266) || defined(ESP32)
    390   _spi->write16(d);
    391 #elif defined(SPI_HAS_TRANSACTION)
    392   _spi->transfer16(d);
    393 #elif defined(__AVR__) || defined(CORE_TEENSY)
    394   SPCRbackup = SPCR;
    395   SPCR = mySPCR;
    396   _spi->transfer16(d);
    397   SPCR = SPCRbackup;
    398 #elif defined(__arm__)
    399   _spi->setClockDivider(21); // 4MHz
    400   _spi->setDataMode(_dataMode);
    401   _spi->transfer16(d);
    402 #else
    403   _spi->transfer16(d);
    404 #endif
    405 }
    406 
    407 INLINE void Arduino_HWSPI::WRITEBUF(uint8_t *buf, size_t count)
    408 {
    409 #if defined(ESP8266) || defined(ESP32)
    410   _spi->writeBytes(buf, count);
    411 #elif defined(CONFIG_ARCH_CHIP_CXD56XX)
    412   _spi->send(buf, count);
    413 #else  // other arch.
    414   _spi->transfer(buf, count);
    415 #endif // other arch.
    416 }
    417 
    418 #endif // !defined(LITTLE_FOOT_PRINT)
    419 
    420 /******** low level bit twiddling **********/
    421 
    422 INLINE void Arduino_HWSPI::DC_HIGH(void)
    423 {
    424 #if defined(USE_FAST_PINIO)
    425 #if defined(HAS_PORT_SET_CLR)
    426 #if defined(KINETISK)
    427   *_dcPortSet = 1;
    428 #else  // !KINETISK
    429   *_dcPortSet = _dcPinMask;
    430 #endif // end !KINETISK
    431 #else  // !HAS_PORT_SET_CLR
    432   *_dcPort |= _dcPinMaskSet;
    433 #endif // end !HAS_PORT_SET_CLR
    434 #else  // !USE_FAST_PINIO
    435   digitalWrite(_dc, HIGH);
    436 #endif // end !USE_FAST_PINIO
    437 }
    438 
    439 INLINE void Arduino_HWSPI::DC_LOW(void)
    440 {
    441 #if defined(USE_FAST_PINIO)
    442 #if defined(HAS_PORT_SET_CLR)
    443 #if defined(KINETISK)
    444   *_dcPortClr = 1;
    445 #else  // !KINETISK
    446   *_dcPortClr = _dcPinMask;
    447 #endif // end !KINETISK
    448 #else  // !HAS_PORT_SET_CLR
    449   *_dcPort &= _dcPinMaskClr;
    450 #endif // end !HAS_PORT_SET_CLR
    451 #else  // !USE_FAST_PINIO
    452   digitalWrite(_dc, LOW);
    453 #endif // end !USE_FAST_PINIO
    454 }
    455 
    456 INLINE void Arduino_HWSPI::CS_HIGH(void)
    457 {
    458   if (_cs != GFX_NOT_DEFINED)
    459   {
    460 #if defined(USE_FAST_PINIO)
    461 #if defined(HAS_PORT_SET_CLR)
    462 #if defined(KINETISK)
    463     *_csPortSet = 1;
    464 #else  // !KINETISK
    465     *_csPortSet = _csPinMask;
    466 #endif // end !KINETISK
    467 #else  // !HAS_PORT_SET_CLR
    468     *_csPort |= _csPinMaskSet;
    469 #endif // end !HAS_PORT_SET_CLR
    470 #else  // !USE_FAST_PINIO
    471     digitalWrite(_cs, HIGH);
    472 #endif // end !USE_FAST_PINIO
    473   }
    474 }
    475 
    476 INLINE void Arduino_HWSPI::CS_LOW(void)
    477 {
    478   if (_cs != GFX_NOT_DEFINED)
    479   {
    480 #if defined(USE_FAST_PINIO)
    481 #if defined(HAS_PORT_SET_CLR)
    482 #if defined(KINETISK)
    483     *_csPortClr = 1;
    484 #else  // !KINETISK
    485     *_csPortClr = _csPinMask;
    486 #endif // end !KINETISK
    487 #else  // !HAS_PORT_SET_CLR
    488     *_csPort &= _csPinMaskClr;
    489 #endif // end !HAS_PORT_SET_CLR
    490 #else  // !USE_FAST_PINIO
    491     digitalWrite(_cs, LOW);
    492 #endif // end !USE_FAST_PINIO
    493   }
    494 }