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_RGB_Display.cpp (10878B)

      1 #include "../Arduino_DataBus.h"
      2 
      3 #if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)
      4 
      5 #include "../Arduino_GFX.h"
      6 #include "Arduino_RGB_Display.h"
      7 
      8 Arduino_RGB_Display::Arduino_RGB_Display(
      9     int16_t w, int16_t h, Arduino_ESP32RGBPanel *rgbpanel, uint8_t r, bool auto_flush,
     10     Arduino_DataBus *bus, int8_t rst, const uint8_t *init_operations, size_t init_operations_len)
     11     : Arduino_GFX(w, h), _rgbpanel(rgbpanel), _auto_flush(auto_flush),
     12       _bus(bus), _rst(rst), _init_operations(init_operations), _init_operations_len(init_operations_len)
     13 {
     14   _framebuffer_size = w * h * 2;
     15   MAX_X = WIDTH - 1;
     16   MAX_Y = HEIGHT - 1;
     17   setRotation(r);
     18 }
     19 
     20 bool Arduino_RGB_Display::begin(int32_t speed)
     21 {
     22   if (_bus)
     23   {
     24     if (!_bus->begin())
     25     {
     26       return false;
     27     }
     28   }
     29 
     30   if (_rst != GFX_NOT_DEFINED)
     31   {
     32     pinMode(_rst, OUTPUT);
     33     digitalWrite(_rst, HIGH);
     34     delay(100);
     35     digitalWrite(_rst, LOW);
     36     delay(120);
     37     digitalWrite(_rst, HIGH);
     38     delay(120);
     39   }
     40   else
     41   {
     42     if (_bus)
     43     {
     44       // Software Rest
     45       _bus->sendCommand(0x01);
     46       delay(120);
     47     }
     48   }
     49 
     50   if (_bus)
     51   {
     52     if (_init_operations_len > 0)
     53     {
     54       _bus->batchOperation((uint8_t *)_init_operations, _init_operations_len);
     55     }
     56   }
     57 
     58   _rgbpanel->begin(speed);
     59   _framebuffer = _rgbpanel->getFrameBuffer(WIDTH, HEIGHT);
     60 
     61   if (!_framebuffer)
     62   {
     63     return false;
     64   }
     65 
     66   return true;
     67 }
     68 
     69 void Arduino_RGB_Display::writePixelPreclipped(int16_t x, int16_t y, uint16_t color)
     70 {
     71   uint16_t *fb = _framebuffer;
     72   switch (_rotation)
     73   {
     74   case 1:
     75     fb += (int32_t)x * _height;
     76     fb += _max_y - y;
     77     *fb = color;
     78     if (_auto_flush)
     79     {
     80       Cache_WriteBack_Addr((uint32_t)fb, 2);
     81     }
     82     break;
     83   case 2:
     84     fb += (int32_t)(_max_y - y) * _width;
     85     fb += _max_x - x;
     86     *fb = color;
     87     if (_auto_flush)
     88     {
     89       Cache_WriteBack_Addr((uint32_t)fb, 2);
     90     }
     91     break;
     92   case 3:
     93     fb += (int32_t)(_max_x - x) * _height;
     94     fb += y;
     95     *fb = color;
     96     if (_auto_flush)
     97     {
     98       Cache_WriteBack_Addr((uint32_t)fb, 2);
     99     }
    100     break;
    101   default: // case 0:
    102     fb += (int32_t)y * _width;
    103     fb += x;
    104     *fb = color;
    105     if (_auto_flush)
    106     {
    107       Cache_WriteBack_Addr((uint32_t)fb, 2);
    108     }
    109   }
    110 }
    111 
    112 void Arduino_RGB_Display::writeFastVLine(int16_t x, int16_t y,
    113                                          int16_t h, uint16_t color)
    114 {
    115   // log_i("writeFastVLine(x: %d, y: %d, h: %d)", x, y, h);
    116   switch (_rotation)
    117   {
    118   case 1:
    119     writeFastHLineCore(_height - y - h, x, h, color);
    120     break;
    121   case 2:
    122     writeFastVLineCore(_max_x - x, _height - y - h, h, color);
    123     break;
    124   case 3:
    125     writeFastHLineCore(y, _max_x - x, h, color);
    126     break;
    127   default: // case 0:
    128     writeFastVLineCore(x, y, h, color);
    129   }
    130 }
    131 
    132 void Arduino_RGB_Display::writeFastVLineCore(int16_t x, int16_t y,
    133                                              int16_t h, uint16_t color)
    134 {
    135   // log_i("writeFastVLineCore(x: %d, y: %d, h: %d)", x, y, h);
    136   if (_ordered_in_range(x, 0, MAX_X) && h)
    137   { // X on screen, nonzero height
    138     if (h < 0)
    139     {             // If negative height...
    140       y += h + 1; //   Move Y to top edge
    141       h = -h;     //   Use positive height
    142     }
    143     if (y <= MAX_Y)
    144     { // Not off bottom
    145       int16_t y2 = y + h - 1;
    146       if (y2 >= 0)
    147       { // Not off top
    148         // Line partly or fully overlaps screen
    149         if (y < 0)
    150         {
    151           y = 0;
    152           h = y2 + 1;
    153         } // Clip top
    154         if (y2 > MAX_Y)
    155         {
    156           h = MAX_Y - y + 1;
    157         } // Clip bottom
    158 
    159         uint16_t *fb = _framebuffer + ((int32_t)y * WIDTH) + x;
    160         if (_auto_flush)
    161         {
    162           while (h--)
    163           {
    164             *fb = color;
    165             Cache_WriteBack_Addr((uint32_t)fb, 2);
    166             fb += WIDTH;
    167           }
    168         }
    169         else
    170         {
    171           while (h--)
    172           {
    173             *fb = color;
    174             fb += WIDTH;
    175           }
    176         }
    177       }
    178     }
    179   }
    180 }
    181 
    182 void Arduino_RGB_Display::writeFastHLine(int16_t x, int16_t y,
    183                                          int16_t w, uint16_t color)
    184 {
    185   // log_i("writeFastHLine(x: %d, y: %d, w: %d)", x, y, w);
    186   switch (_rotation)
    187   {
    188   case 1:
    189     writeFastVLineCore(_max_y - y, x, w, color);
    190     break;
    191   case 2:
    192     writeFastHLineCore(_width - x - w, _max_y - y, w, color);
    193     break;
    194   case 3:
    195     writeFastVLineCore(y, _width - x - w, w, color);
    196     break;
    197   default: // case 0:
    198     writeFastHLineCore(x, y, w, color);
    199   }
    200 }
    201 
    202 void Arduino_RGB_Display::writeFastHLineCore(int16_t x, int16_t y,
    203                                              int16_t w, uint16_t color)
    204 {
    205   // log_i("writeFastHLineCore(x: %d, y: %d, w: %d)", x, y, w);
    206   if (_ordered_in_range(y, 0, MAX_Y) && w)
    207   { // Y on screen, nonzero width
    208     if (w < 0)
    209     {             // If negative width...
    210       x += w + 1; //   Move X to left edge
    211       w = -w;     //   Use positive width
    212     }
    213     if (x <= MAX_X)
    214     { // Not off right
    215       int16_t x2 = x + w - 1;
    216       if (x2 >= 0)
    217       { // Not off left
    218         // Line partly or fully overlaps screen
    219         if (x < 0)
    220         {
    221           x = 0;
    222           w = x2 + 1;
    223         } // Clip left
    224         if (x2 > MAX_X)
    225         {
    226           w = MAX_X - x + 1;
    227         } // Clip right
    228 
    229         uint16_t *fb = _framebuffer + ((int32_t)y * WIDTH) + x;
    230         uint32_t cachePos = (uint32_t)fb;
    231         int16_t writeSize = w * 2;
    232         while (w--)
    233         {
    234           *(fb++) = color;
    235         }
    236         if (_auto_flush)
    237         {
    238           Cache_WriteBack_Addr(cachePos, writeSize);
    239         }
    240       }
    241     }
    242   }
    243 }
    244 
    245 void Arduino_RGB_Display::writeFillRectPreclipped(int16_t x, int16_t y,
    246                                                   int16_t w, int16_t h, uint16_t color)
    247 {
    248   // log_i("writeFillRectPreclipped(x: %d, y: %d, w: %d, h: %d)", x, y, w, h);
    249   if (_rotation > 0)
    250   {
    251     int16_t t = x;
    252     switch (_rotation)
    253     {
    254     case 1:
    255       x = WIDTH - y - h;
    256       y = t;
    257       t = w;
    258       w = h;
    259       h = t;
    260       break;
    261     case 2:
    262       x = WIDTH - x - w;
    263       y = HEIGHT - y - h;
    264       break;
    265     case 3:
    266       x = y;
    267       y = HEIGHT - t - w;
    268       t = w;
    269       w = h;
    270       h = t;
    271       break;
    272     }
    273   }
    274   // log_i("adjusted writeFillRectPreclipped(x: %d, y: %d, w: %d, h: %d)", x, y, w, h);
    275   uint16_t *row = _framebuffer;
    276   row += y * WIDTH;
    277   uint32_t cachePos = (uint32_t)row;
    278   row += x;
    279   for (int j = 0; j < h; j++)
    280   {
    281     for (int i = 0; i < w; i++)
    282     {
    283       row[i] = color;
    284     }
    285     row += WIDTH;
    286   }
    287   if (_auto_flush)
    288   {
    289     Cache_WriteBack_Addr(cachePos, WIDTH * h * 2);
    290   }
    291 }
    292 
    293 void Arduino_RGB_Display::drawIndexedBitmap(int16_t x, int16_t y, uint8_t *bitmap, uint16_t *color_index, int16_t w, int16_t h)
    294 {
    295   if (
    296       ((x + w - 1) < 0) || // Outside left
    297       ((y + h - 1) < 0) || // Outside top
    298       (x > _max_x) ||      // Outside right
    299       (y > _max_y)         // Outside bottom
    300   )
    301   {
    302     return;
    303   }
    304   else
    305   {
    306     if (_rotation > 0)
    307     {
    308       Arduino_GFX::drawIndexedBitmap(x, y, bitmap, color_index, w, h);
    309     }
    310     else
    311     {
    312       int16_t xskip = 0;
    313       if ((y + h - 1) > _max_y)
    314       {
    315         h -= (y + h - 1) - _max_y;
    316       }
    317       if (y < 0)
    318       {
    319         bitmap -= y * w;
    320         h += y;
    321         y = 0;
    322       }
    323       if ((x + w - 1) > _max_x)
    324       {
    325         xskip = (x + w - 1) - _max_x;
    326         w -= xskip;
    327       }
    328       if (x < 0)
    329       {
    330         bitmap -= x;
    331         xskip -= x;
    332         w += x;
    333         x = 0;
    334       }
    335       uint16_t *row = _framebuffer;
    336       row += y * _width;
    337       uint32_t cachePos = (uint32_t)row;
    338       row += x;
    339       for (int j = 0; j < h; j++)
    340       {
    341         for (int i = 0; i < w; i++)
    342         {
    343           row[i] = color_index[*bitmap++];
    344         }
    345         bitmap += xskip;
    346         row += _width;
    347       }
    348       if (_auto_flush)
    349       {
    350         Cache_WriteBack_Addr(cachePos, _width * h * 2);
    351       }
    352     }
    353   }
    354 }
    355 
    356 void Arduino_RGB_Display::draw16bitRGBBitmap(int16_t x, int16_t y,
    357                                              uint16_t *bitmap, int16_t w, int16_t h)
    358 {
    359   bool result;
    360 
    361   switch (_rotation)
    362   {
    363   case 1:
    364     result = gfx_draw_bitmap_to_framebuffer_rotate_1(bitmap, w, h, _framebuffer, x, y, _width, _height);
    365     break;
    366   case 2:
    367     result = gfx_draw_bitmap_to_framebuffer_rotate_2(bitmap, w, h, _framebuffer, x, y, _width, _height);
    368     break;
    369   case 3:
    370     result = gfx_draw_bitmap_to_framebuffer_rotate_3(bitmap, w, h, _framebuffer, x, y, _width, _height);
    371     break;
    372   default: // case 0:
    373     result = gfx_draw_bitmap_to_framebuffer(bitmap, w, h, _framebuffer, x, y, _width, _height);
    374   }
    375 
    376   if (result)
    377   {
    378     if (_auto_flush)
    379     {
    380       uint32_t cachePos;
    381       size_t cache_size;
    382       switch (_rotation)
    383       {
    384       case 1:
    385         cachePos = (uint32_t)(_framebuffer + (x * WIDTH));
    386         cache_size = HEIGHT * w * 2;
    387         break;
    388       case 2:
    389         cachePos = (uint32_t)(_framebuffer + ((MAX_Y - y) * WIDTH));
    390         cache_size = HEIGHT * h * 2;
    391         break;
    392       case 3:
    393         cachePos = (uint32_t)(_framebuffer + ((MAX_Y - x) * WIDTH));
    394         cache_size = HEIGHT * w * 2;
    395         break;
    396       default: // case 0:
    397         cachePos = (uint32_t)(_framebuffer + (y * WIDTH));
    398         cache_size = HEIGHT * h * 2;
    399       }
    400       Cache_WriteBack_Addr(cachePos, cache_size);
    401     }
    402   }
    403 }
    404 
    405 void Arduino_RGB_Display::draw16bitBeRGBBitmap(int16_t x, int16_t y,
    406                                                uint16_t *bitmap, int16_t w, int16_t h)
    407 {
    408   if (
    409       ((x + w - 1) < 0) || // Outside left
    410       ((y + h - 1) < 0) || // Outside top
    411       (x > _max_x) ||      // Outside right
    412       (y > _max_y)         // Outside bottom
    413   )
    414   {
    415     return;
    416   }
    417   else
    418   {
    419     if (_rotation > 0)
    420     {
    421       Arduino_GFX::draw16bitBeRGBBitmap(x, y, bitmap, w, h);
    422     }
    423     else
    424     {
    425       int16_t xskip = 0;
    426       if ((y + h - 1) > _max_y)
    427       {
    428         h -= (y + h - 1) - _max_y;
    429       }
    430       if (y < 0)
    431       {
    432         bitmap -= y * w;
    433         h += y;
    434         y = 0;
    435       }
    436       if ((x + w - 1) > _max_x)
    437       {
    438         xskip = (x + w - 1) - _max_x;
    439         w -= xskip;
    440       }
    441       if (x < 0)
    442       {
    443         bitmap -= x;
    444         xskip -= x;
    445         w += x;
    446         x = 0;
    447       }
    448       uint16_t *row = _framebuffer;
    449       row += y * _width;
    450       uint32_t cachePos = (uint32_t)row;
    451       row += x;
    452       uint16_t color;
    453       for (int j = 0; j < h; j++)
    454       {
    455         for (int i = 0; i < w; i++)
    456         {
    457           color = *bitmap++;
    458           MSB_16_SET(row[i], color);
    459         }
    460         bitmap += xskip;
    461         row += _width;
    462       }
    463       if (_auto_flush)
    464       {
    465         Cache_WriteBack_Addr(cachePos, _width * h * 2);
    466       }
    467     }
    468   }
    469 }
    470 
    471 void Arduino_RGB_Display::flush(void)
    472 {
    473   if (!_auto_flush)
    474   {
    475     Cache_WriteBack_Addr((uint32_t)_framebuffer, _framebuffer_size);
    476   }
    477 }
    478 
    479 uint16_t *Arduino_RGB_Display::getFramebuffer()
    480 {
    481   return _framebuffer;
    482 }
    483 
    484 #endif // #if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)