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_DataBus.h (11941B)

      1 /*
      2  * start rewrite from:
      3  * https://github.com/adafruit/Adafruit-GFX-Library.git
      4  */
      5 #ifndef _ARDUINO_DATABUS_H_
      6 #define _ARDUINO_DATABUS_H_
      7 
      8 #include <Arduino.h>
      9 
     10 #define GFX_SKIP_OUTPUT_BEGIN -2
     11 #define GFX_NOT_DEFINED -1
     12 #define GFX_STR_HELPER(x) #x
     13 #define GFX_STR(x) GFX_STR_HELPER(x)
     14 
     15 #if defined(__AVR__)
     16 #define LITTLE_FOOT_PRINT // reduce program size for limited flash MCU
     17 #define USE_FAST_PINIO    ///< Use direct PORT register access
     18 typedef uint8_t ARDUINOGFX_PORT_t;
     19 #elif defined(ARDUINO_ARCH_NRF52840)
     20 #define USE_FAST_PINIO   ///< Use direct PORT register access
     21 #define HAS_PORT_SET_CLR ///< PORTs have set & clear registers
     22 typedef uint32_t ARDUINOGFX_PORT_t;
     23 #elif defined(TARGET_RP2040)
     24 #define USE_FAST_PINIO   ///< Use direct PORT register access
     25 #define HAS_PORT_SET_CLR ///< PORTs have set & clear registers
     26 typedef uint32_t ARDUINOGFX_PORT_t;
     27 #elif defined(ESP32)
     28 #define USE_FAST_PINIO   ///< Use direct PORT register access
     29 #define HAS_PORT_SET_CLR ///< PORTs have set & clear registers
     30 typedef uint32_t ARDUINOGFX_PORT_t;
     31 #elif defined(ESP8266)
     32 #define ESP8266SAFEBATCHBITSIZE (2048 * 8 * 9)
     33 #define USE_FAST_PINIO ///< Use direct PORT register access
     34 typedef uint32_t ARDUINOGFX_PORT_t;
     35 #elif defined(ARDUINO_ARCH_STM32)
     36 #define USE_FAST_PINIO ///< Use direct PORT register access
     37 typedef uint32_t ARDUINOGFX_PORT_t;
     38 #elif defined(__arm__)
     39 #if defined(ARDUINO_ARCH_SAMD)
     40 // Adafruit M0, M4
     41 #define USE_FAST_PINIO                  ///< Use direct PORT register access
     42 #define HAS_PORT_SET_CLR                ///< PORTs have set & clear registers
     43 typedef uint32_t ARDUINOGFX_PORT_t;
     44 #elif defined(CONFIG_ARCH_CHIP_CXD56XX) // Sony Spresense
     45 #define USE_FAST_PINIO                  ///< Use direct PORT register access
     46 typedef uint8_t ARDUINOGFX_PORT_t;
     47 #elif defined(RTL8722DM)
     48 #define USE_FAST_PINIO ///< Use direct PORT register access
     49 typedef uint32_t ARDUINOGFX_PORT_t;
     50 #elif defined(CORE_TEENSY)
     51 #define USE_FAST_PINIO   ///< Use direct PORT register access
     52 #define HAS_PORT_SET_CLR ///< PORTs have set & clear registers
     53 #if defined(__IMXRT1052__) || defined(__IMXRT1062__)
     54 // PJRC Teensy 4.x
     55 typedef uint32_t ARDUINOGFX_PORT_t;
     56 #else
     57 // PJRC Teensy 3.x
     58 typedef uint8_t ARDUINOGFX_PORT_t;
     59 #endif
     60 #else
     61 // Arduino Due?
     62 // USE_FAST_PINIO not available here (yet)...Due has a totally different
     63 // GPIO register set and will require some changes elsewhere (e.g. in
     64 // constructors especially).
     65 #endif
     66 #else  // !ARM
     67 // Unknow architecture, USE_FAST_PINIO is not available here (yet)
     68 // but don't worry about it too much...the digitalWrite() implementation
     69 // on these platforms is reasonably efficient and already RAM-resident,
     70 // only gotcha then is no parallel connection support for now.
     71 #endif // !ARM
     72 
     73 #ifdef USE_FAST_PINIO
     74 typedef volatile ARDUINOGFX_PORT_t *PORTreg_t;
     75 #endif
     76 
     77 #if defined(ARDUINO_ARCH_ARC32) || defined(ARDUINO_MAXIM)
     78 #define SPI_DEFAULT_FREQ 16000000
     79 // Teensy 3.0, 3.1/3.2, 3.5, 3.6
     80 #elif defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
     81 #define SPI_DEFAULT_FREQ 40000000
     82 // Teensy 4.x
     83 #elif defined(__IMXRT1052__) || defined(__IMXRT1062__)
     84 #define SPI_DEFAULT_FREQ 40000000
     85 #elif defined(__AVR__) || defined(TEENSYDUINO)
     86 #define SPI_DEFAULT_FREQ 8000000
     87 #elif defined(ARDUINO_ARCH_NRF52840)
     88 #define SPI_DEFAULT_FREQ 8000000
     89 #elif defined(ESP8266) || defined(ESP32)
     90 #define SPI_DEFAULT_FREQ 40000000
     91 #elif defined(RTL8722DM)
     92 #define SPI_DEFAULT_FREQ 20000000
     93 #elif defined(RASPI)
     94 #define SPI_DEFAULT_FREQ 80000000
     95 #elif defined(ARDUINO_ARCH_STM32F1)
     96 #define SPI_DEFAULT_FREQ 36000000
     97 #elif defined(ARDUINO_BLACKPILL_F411CE)
     98 #define SPI_DEFAULT_FREQ 50000000
     99 #elif defined(F_CPU)
    100 #define SPI_DEFAULT_FREQ (F_CPU / 4)
    101 #else
    102 #define SPI_DEFAULT_FREQ 24000000 ///< Default SPI data clock frequency
    103 #endif
    104 
    105 #ifndef UNUSED
    106 #define UNUSED(x) (void)(x)
    107 #endif
    108 #define ATTR_UNUSED __attribute__((unused))
    109 
    110 #define MSB_16_SET(var, val)                             \
    111   {                                                      \
    112     (var) = (((val)&0xFF00) >> 8) | (((val)&0xFF) << 8); \
    113   }
    114 #define MSB_32_SET(var, val)                                  \
    115   {                                                           \
    116     uint8_t *v = (uint8_t *)&(val);                           \
    117     (var) = v[3] | (v[2] << 8) | (v[1] << 16) | (v[0] << 24); \
    118   }
    119 #define MSB_32_16_16_SET(var, v1, v2)                                                                                   \
    120   {                                                                                                                     \
    121     (var) = (((uint32_t)v2 & 0xff00) << 8) | (((uint32_t)v2 & 0xff) << 24) | ((v1 & 0xff00) >> 8) | ((v1 & 0xff) << 8); \
    122   }
    123 #define MSB_32_8_ARRAY_SET(var, a)                                  \
    124   {                                                                 \
    125     (var) = ((uint32_t)a[0] << 8 | a[1] | a[2] << 24 | a[3] << 16); \
    126   }
    127 
    128 #if defined(ESP32)
    129 #define INLINE __attribute__((always_inline)) inline
    130 #else
    131 #define INLINE inline
    132 #endif
    133 
    134 #if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)
    135 #include <esp_lcd_panel_io.h>
    136 #include <esp_lcd_panel_io_interface.h>
    137 #include <esp_pm.h>
    138 #include <esp_private/gdma.h>
    139 #include <hal/dma_types.h>
    140 #include <hal/lcd_hal.h>
    141 #include <soc/dport_reg.h>
    142 #include <soc/gpio_sig_map.h>
    143 #include <soc/lcd_cam_reg.h>
    144 #include <soc/lcd_cam_struct.h>
    145 
    146 typedef struct esp_lcd_i80_bus_t esp_lcd_i80_bus_t;
    147 typedef struct lcd_panel_io_i80_t lcd_panel_io_i80_t;
    148 typedef struct lcd_i80_trans_descriptor_t lcd_i80_trans_descriptor_t;
    149 
    150 struct esp_lcd_i80_bus_t
    151 {
    152   int bus_id;                            // Bus ID, index from 0
    153   portMUX_TYPE spinlock;                 // spinlock used to protect i80 bus members(hal, device_list, cur_trans)
    154   lcd_hal_context_t hal;                 // Hal object
    155   size_t bus_width;                      // Number of data lines
    156   intr_handle_t intr;                    // LCD peripheral interrupt handle
    157   esp_pm_lock_handle_t pm_lock;          // Power management lock
    158   size_t num_dma_nodes;                  // Number of DMA descriptors
    159   uint8_t *format_buffer;                // The driver allocates an internal buffer for DMA to do data format transformer
    160   size_t resolution_hz;                  // LCD_CLK resolution, determined by selected clock source
    161   gdma_channel_handle_t dma_chan;        // DMA channel handle
    162   size_t psram_trans_align;              // DMA transfer alignment for data allocated from PSRAM
    163   size_t sram_trans_align;               // DMA transfer alignment for data allocated from SRAM
    164   lcd_i80_trans_descriptor_t *cur_trans; // Current transaction
    165   lcd_panel_io_i80_t *cur_device;        // Current working device
    166   LIST_HEAD(i80_device_list, lcd_panel_io_i80_t)
    167   device_list; // Head of i80 device list
    168   struct
    169   {
    170     unsigned int exclusive : 1; // Indicate whether the I80 bus is owned by one device (whose CS GPIO is not assigned) exclusively
    171   } flags;
    172   dma_descriptor_t dma_nodes[]; // DMA descriptor pool, the descriptors are shared by all i80 devices
    173 };
    174 
    175 struct lcd_i80_trans_descriptor_t
    176 {
    177   lcd_panel_io_i80_t *i80_device;                       // i80 device issuing this transaction
    178   int cmd_value;                                        // Command value
    179   uint32_t cmd_cycles;                                  // Command cycles
    180   const void *data;                                     // Data buffer
    181   uint32_t data_length;                                 // Data buffer size
    182   void *user_ctx;                                       // private data used by trans_done_cb
    183   esp_lcd_panel_io_color_trans_done_cb_t trans_done_cb; // transaction done callback
    184 };
    185 
    186 struct lcd_panel_io_i80_t
    187 {
    188   esp_lcd_panel_io_t base;                                    // Base class of generic lcd panel io
    189   esp_lcd_i80_bus_t *bus;                                     // Which bus the device is attached to
    190   int cs_gpio_num;                                            // GPIO used for CS line
    191   unsigned int pclk_hz;                                       // PCLK clock frequency
    192   size_t clock_prescale;                                      // Prescaler coefficient, determined by user's configured PCLK frequency
    193   QueueHandle_t trans_queue;                                  // Transaction queue, transactions in this queue are pending for scheduler to dispatch
    194   QueueHandle_t done_queue;                                   // Transaction done queue, transactions in this queue are finished but not recycled by the caller
    195   size_t queue_size;                                          // Size of transaction queue
    196   size_t num_trans_inflight;                                  // Number of transactions that are undergoing (the descriptor not recycled yet)
    197   int lcd_cmd_bits;                                           // Bit width of LCD command
    198   int lcd_param_bits;                                         // Bit width of LCD parameter
    199   void *user_ctx;                                             // private data used when transfer color data
    200   esp_lcd_panel_io_color_trans_done_cb_t on_color_trans_done; // color data trans done callback
    201   LIST_ENTRY(lcd_panel_io_i80_t)
    202   device_list_entry; // Entry of i80 device list
    203   struct
    204   {
    205     unsigned int dc_idle_level : 1;  // Level of DC line in IDLE phase
    206     unsigned int dc_cmd_level : 1;   // Level of DC line in CMD phase
    207     unsigned int dc_dummy_level : 1; // Level of DC line in DUMMY phase
    208     unsigned int dc_data_level : 1;  // Level of DC line in DATA phase
    209   } dc_levels;
    210   struct
    211   {
    212     unsigned int cs_active_high : 1;     // Whether the CS line is active on high level
    213     unsigned int reverse_color_bits : 1; // Reverse the data bits, D[N:0] -> D[0:N]
    214     unsigned int swap_color_bytes : 1;   // Swap adjacent two data bytes before sending out
    215     unsigned int pclk_active_neg : 1;    // The display will write data lines when there's a falling edge on WR line
    216     unsigned int pclk_idle_low : 1;      // The WR line keeps at low level in IDLE phase
    217   } flags;
    218   lcd_i80_trans_descriptor_t trans_pool[]; // Transaction pool
    219 };
    220 #endif // #if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)
    221 
    222 typedef enum
    223 {
    224   BEGIN_WRITE,
    225   WRITE_COMMAND_8,
    226   WRITE_COMMAND_16,
    227   WRITE_DATA_8,
    228   WRITE_DATA_16,
    229   WRITE_BYTES,
    230   WRITE_C8_D8,
    231   WRITE_C8_D16,
    232   WRITE_C16_D16,
    233   END_WRITE,
    234   DELAY,
    235 } spi_operation_type_t;
    236 
    237 union
    238 {
    239   uint16_t value;
    240   struct
    241   {
    242     uint8_t lsb;
    243     uint8_t msb;
    244   };
    245 } _data16;
    246 
    247 class Arduino_DataBus
    248 {
    249 public:
    250   Arduino_DataBus();
    251 
    252   void unused() { UNUSED(_data16); } // avoid compiler warning
    253 
    254   virtual bool begin(int32_t speed = SPI_DEFAULT_FREQ, int8_t dataMode = GFX_NOT_DEFINED) = 0;
    255   virtual void beginWrite() = 0;
    256   virtual void endWrite() = 0;
    257   virtual void writeCommand(uint8_t c) = 0;
    258   virtual void writeCommand16(uint16_t c) = 0;
    259   virtual void write(uint8_t) = 0;
    260   virtual void write16(uint16_t) = 0;
    261   virtual void writeC8D8(uint8_t c, uint8_t d);
    262   virtual void writeC16D16(uint16_t c, uint16_t d);
    263   virtual void writeC8D16(uint8_t c, uint16_t d);
    264   virtual void writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2);
    265   virtual void writeC8D16D16Split(uint8_t c, uint16_t d1, uint16_t d2);
    266   virtual void writeRepeat(uint16_t p, uint32_t len) = 0;
    267   virtual void writePixels(uint16_t *data, uint32_t len) = 0;
    268 
    269   void sendCommand(uint8_t c);
    270   void sendCommand16(uint16_t c);
    271   void sendData(uint8_t d);
    272   void sendData16(uint16_t d);
    273 
    274   void batchOperation(const uint8_t *operations, size_t len);
    275 
    276 #if !defined(LITTLE_FOOT_PRINT)
    277   virtual void writeBytes(uint8_t *data, uint32_t len) = 0;
    278   virtual void writePattern(uint8_t *data, uint8_t len, uint32_t repeat) = 0;
    279   virtual void writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len);
    280   virtual void writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len);
    281 #endif // !defined(LITTLE_FOOT_PRINT)
    282 
    283 protected:
    284   int32_t _speed;
    285   int8_t _dataMode;
    286 };
    287 
    288 #endif // _ARDUINO_DATABUS_H_