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_ESP32LCD8.cpp (7036B)

      1 /*
      2  * start rewrite from:
      3  * https://github.com/lovyan03/LovyanGFX/blob/master/src/lgfx/v0/platforms/LGFX_PARALLEL_ESP32.hpp
      4  */
      5 #include "Arduino_ESP32LCD8.h"
      6 
      7 #if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)
      8 
      9 #define WAIT_LCD_NOT_BUSY while (LCD_CAM.lcd_user.val & LCD_CAM_LCD_START)
     10 
     11 Arduino_ESP32LCD8::Arduino_ESP32LCD8(
     12     int8_t dc, int8_t cs, int8_t wr, int8_t rd,
     13     int8_t d0, int8_t d1, int8_t d2, int8_t d3, int8_t d4, int8_t d5, int8_t d6, int8_t d7)
     14     : _dc(dc), _cs(cs), _wr(wr), _rd(rd),
     15       _d0(d0), _d1(d1), _d2(d2), _d3(d3), _d4(d4), _d5(d5), _d6(d6), _d7(d7)
     16 {
     17 }
     18 
     19 bool Arduino_ESP32LCD8::begin(int32_t speed, int8_t dataMode)
     20 {
     21   if (speed == GFX_NOT_DEFINED)
     22   {
     23     _speed = 24000000UL;
     24   }
     25   else
     26   {
     27     _speed = speed;
     28   }
     29   pinMode(_dc, OUTPUT);
     30   digitalWrite(_dc, HIGH);
     31 
     32   if (_cs != GFX_NOT_DEFINED)
     33   {
     34     pinMode(_cs, OUTPUT);
     35     digitalWrite(_cs, HIGH); // disable chip select
     36   }
     37   if (_cs >= 32)
     38   {
     39     _csPinMask = digitalPinToBitMask(_cs);
     40     _csPortSet = (PORTreg_t)&GPIO.out1_w1ts.val;
     41     _csPortClr = (PORTreg_t)&GPIO.out1_w1tc.val;
     42   }
     43   else if (_cs != GFX_NOT_DEFINED)
     44   {
     45     _csPinMask = digitalPinToBitMask(_cs);
     46     _csPortSet = (PORTreg_t)&GPIO.out_w1ts;
     47     _csPortClr = (PORTreg_t)&GPIO.out_w1tc;
     48   }
     49 
     50   pinMode(_wr, OUTPUT);
     51   digitalWrite(_wr, HIGH);
     52 
     53   if (_rd != GFX_NOT_DEFINED)
     54   {
     55     pinMode(_rd, OUTPUT);
     56     digitalWrite(_rd, HIGH);
     57   }
     58 
     59   esp_lcd_i80_bus_config_t bus_config = {
     60       .dc_gpio_num = _dc,
     61       .wr_gpio_num = _wr,
     62       .clk_src = LCD_CLK_SRC_PLL160M,
     63       .data_gpio_nums = {
     64           _d0, _d1, _d2, _d3, _d4, _d5, _d6, _d7},
     65       .bus_width = 8,
     66       .max_transfer_bytes = 2,
     67       .psram_trans_align = 0,
     68       .sram_trans_align = 0};
     69   esp_lcd_new_i80_bus(&bus_config, &_i80_bus);
     70 
     71   uint32_t diff = INT32_MAX;
     72   uint32_t div_n = 256;
     73   uint32_t div_a = 63;
     74   uint32_t div_b = 62;
     75   uint32_t clkcnt = 64;
     76   uint32_t start_cnt = std::min<uint32_t>(64u, (F_CPU / (_speed * 2) + 1));
     77   uint32_t end_cnt = std::max<uint32_t>(2u, F_CPU / 256u / _speed);
     78   if (start_cnt <= 2)
     79   {
     80     end_cnt = 1;
     81   }
     82   for (uint32_t cnt = start_cnt; diff && cnt >= end_cnt; --cnt)
     83   {
     84     float fdiv = (float)F_CPU / cnt / _speed;
     85     uint32_t n = std::max<uint32_t>(2u, (uint32_t)fdiv);
     86     fdiv -= n;
     87 
     88     for (uint32_t a = 63; diff && a > 0; --a)
     89     {
     90       uint32_t b = roundf(fdiv * a);
     91       if (a == b && n == 256)
     92       {
     93         break;
     94       }
     95       uint32_t freq = F_CPU / ((n * cnt) + (float)(b * cnt) / (float)a);
     96       uint32_t d = abs(_speed - (int)freq);
     97       if (diff <= d)
     98       {
     99         continue;
    100       }
    101       diff = d;
    102       clkcnt = cnt;
    103       div_n = n;
    104       div_b = b;
    105       div_a = a;
    106       if (b == 0 || a == b)
    107       {
    108         break;
    109       }
    110     }
    111   }
    112   if (div_a == div_b)
    113   {
    114     div_b = 0;
    115     div_n += 1;
    116   }
    117 
    118   lcd_cam_lcd_clock_reg_t lcd_clock;
    119   lcd_clock.lcd_clkcnt_n = std::max(1u, clkcnt - 1);
    120   lcd_clock.lcd_clk_equ_sysclk = (clkcnt == 1);
    121   lcd_clock.lcd_ck_idle_edge = true;
    122   lcd_clock.lcd_ck_out_edge = false;
    123   lcd_clock.lcd_clkm_div_num = div_n;
    124   lcd_clock.lcd_clkm_div_b = div_b;
    125   lcd_clock.lcd_clkm_div_a = div_a;
    126   lcd_clock.lcd_clk_sel = 2; // clock_select: 1=XTAL CLOCK / 2=240MHz / 3=160MHz
    127   lcd_clock.clk_en = true;
    128 
    129   LCD_CAM.lcd_clock.val = lcd_clock.val;
    130 
    131   return true;
    132 }
    133 
    134 void Arduino_ESP32LCD8::beginWrite()
    135 {
    136   CS_LOW();
    137 
    138   LCD_CAM.lcd_misc.val = LCD_CAM_LCD_CD_IDLE_EDGE;
    139   LCD_CAM.lcd_user.val = 0;
    140   LCD_CAM.lcd_user.val = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG;
    141 }
    142 
    143 void Arduino_ESP32LCD8::endWrite()
    144 {
    145   WAIT_LCD_NOT_BUSY;
    146 
    147   CS_HIGH();
    148 }
    149 
    150 void Arduino_ESP32LCD8::writeCommand(uint8_t c)
    151 {
    152   WRITECOMMAND(c);
    153 }
    154 
    155 void Arduino_ESP32LCD8::writeCommand16(uint16_t c)
    156 {
    157   WRITECOMMAND16(c);
    158 }
    159 
    160 void Arduino_ESP32LCD8::write(uint8_t d)
    161 {
    162   WRITE(d);
    163 }
    164 
    165 void Arduino_ESP32LCD8::write16(uint16_t d)
    166 {
    167   WRITE16(d);
    168 }
    169 
    170 void Arduino_ESP32LCD8::writeRepeat(uint16_t p, uint32_t len)
    171 {
    172   while (len--)
    173   {
    174     WRITE16(p);
    175   }
    176 }
    177 
    178 void Arduino_ESP32LCD8::writePixels(uint16_t *data, uint32_t len)
    179 {
    180   LCD_CAM.lcd_misc.val = LCD_CAM_LCD_CD_IDLE_EDGE;
    181   while (len--)
    182   {
    183     _data16.value = *data++;
    184     LCD_CAM.lcd_cmd_val.lcd_cmd_value = _data16.msb;
    185     WAIT_LCD_NOT_BUSY;
    186     LCD_CAM.lcd_user.val = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
    187     LCD_CAM.lcd_cmd_val.lcd_cmd_value = _data16.lsb;
    188     WAIT_LCD_NOT_BUSY;
    189     LCD_CAM.lcd_user.val = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
    190   }
    191 }
    192 
    193 void Arduino_ESP32LCD8::writeBytes(uint8_t *data, uint32_t len)
    194 {
    195   LCD_CAM.lcd_misc.val = LCD_CAM_LCD_CD_IDLE_EDGE;
    196   while (len--)
    197   {
    198     LCD_CAM.lcd_cmd_val.lcd_cmd_value = *data++;
    199     WAIT_LCD_NOT_BUSY;
    200     LCD_CAM.lcd_user.val = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
    201   }
    202 }
    203 
    204 void Arduino_ESP32LCD8::writePattern(uint8_t *data, uint8_t len, uint32_t repeat)
    205 {
    206   while (repeat--)
    207   {
    208     writeBytes(data, len);
    209   }
    210 }
    211 
    212 void Arduino_ESP32LCD8::writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len)
    213 {
    214   while (len--)
    215   {
    216     WRITE16(idx[*data++]);
    217   }
    218 }
    219 
    220 void Arduino_ESP32LCD8::writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len)
    221 {
    222   while (len--)
    223   {
    224     WRITE16(idx[*data]);
    225     WRITE16(idx[*data++]);
    226   }
    227 }
    228 
    229 INLINE void Arduino_ESP32LCD8::WRITECOMMAND(uint8_t c)
    230 {
    231   LCD_CAM.lcd_misc.val = LCD_CAM_LCD_CD_IDLE_EDGE | LCD_CAM_LCD_CD_CMD_SET;
    232   LCD_CAM.lcd_cmd_val.lcd_cmd_value = c;
    233   WAIT_LCD_NOT_BUSY;
    234   LCD_CAM.lcd_user.val = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
    235 }
    236 
    237 INLINE void Arduino_ESP32LCD8::WRITECOMMAND16(uint16_t c)
    238 {
    239   _data16.value = c;
    240   LCD_CAM.lcd_misc.val = LCD_CAM_LCD_CD_IDLE_EDGE | LCD_CAM_LCD_CD_CMD_SET;
    241   LCD_CAM.lcd_cmd_val.lcd_cmd_value = _data16.msb;
    242   WAIT_LCD_NOT_BUSY;
    243   LCD_CAM.lcd_user.val = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
    244   LCD_CAM.lcd_cmd_val.lcd_cmd_value = _data16.lsb;
    245   WAIT_LCD_NOT_BUSY;
    246   LCD_CAM.lcd_user.val = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
    247 }
    248 
    249 INLINE void Arduino_ESP32LCD8::WRITE(uint8_t d)
    250 {
    251   LCD_CAM.lcd_misc.val = LCD_CAM_LCD_CD_IDLE_EDGE;
    252   LCD_CAM.lcd_cmd_val.lcd_cmd_value = d;
    253   WAIT_LCD_NOT_BUSY;
    254   LCD_CAM.lcd_user.val = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
    255 }
    256 
    257 INLINE void Arduino_ESP32LCD8::WRITE16(uint16_t d)
    258 {
    259   _data16.value = d;
    260   LCD_CAM.lcd_misc.val = LCD_CAM_LCD_CD_IDLE_EDGE;
    261   LCD_CAM.lcd_cmd_val.lcd_cmd_value = _data16.msb;
    262   WAIT_LCD_NOT_BUSY;
    263   LCD_CAM.lcd_user.val = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
    264   LCD_CAM.lcd_cmd_val.lcd_cmd_value = _data16.lsb;
    265   WAIT_LCD_NOT_BUSY;
    266   LCD_CAM.lcd_user.val = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
    267 }
    268 
    269 /******** low level bit twiddling **********/
    270 
    271 INLINE void Arduino_ESP32LCD8::CS_HIGH(void)
    272 {
    273   if (_cs != GFX_NOT_DEFINED)
    274   {
    275     *_csPortSet = _csPinMask;
    276   }
    277 }
    278 
    279 INLINE void Arduino_ESP32LCD8::CS_LOW(void)
    280 {
    281   if (_cs != GFX_NOT_DEFINED)
    282   {
    283     *_csPortClr = _csPinMask;
    284   }
    285 }
    286 
    287 #endif // #if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)