2021-04-11 11:30:50 +01:00
# ifndef _UDISP_
# define _UDISP_
# include <Adafruit_GFX.h>
# include <renderer.h>
2021-04-16 18:36:45 +01:00
# include <Wire.h>
# include <SPI.h>
2022-10-03 11:24:27 +01:00
# ifdef ESP32
# ifdef CONFIG_IDF_TARGET_ESP32S3
# define USE_ESP32_S3
# endif
# endif
2021-04-26 10:41:01 +01:00
# ifdef ESP32
2021-04-26 09:20:14 +01:00
# include "driver/spi_master.h"
2021-04-26 10:41:01 +01:00
# endif
2021-04-11 11:30:50 +01:00
2022-10-03 11:24:27 +01:00
# ifdef USE_ESP32_S3
# include <esp_lcd_panel_io.h>
# include "esp_private/gdma.h"
# include <hal/gpio_ll.h>
# include <hal/lcd_hal.h>
# include <soc/lcd_cam_reg.h>
# include <soc/lcd_cam_struct.h>
static inline volatile uint32_t * get_gpio_hi_reg ( int_fast8_t pin ) { return ( pin & 32 ) ? & GPIO . out1_w1ts . val : & GPIO . out_w1ts ; }
//static inline volatile uint32_t* get_gpio_hi_reg(int_fast8_t pin) { return (volatile uint32_t*)((pin & 32) ? 0x60004014 : 0x60004008) ; } // workaround Eratta
static inline volatile uint32_t * get_gpio_lo_reg ( int_fast8_t pin ) { return ( pin & 32 ) ? & GPIO . out1_w1tc . val : & GPIO . out_w1tc ; }
//static inline volatile uint32_t* get_gpio_lo_reg(int_fast8_t pin) { return (volatile uint32_t*)((pin & 32) ? 0x60004018 : 0x6000400C) ; }
static inline bool gpio_in ( int_fast8_t pin ) { return ( ( pin & 32 ) ? GPIO . in1 . data : GPIO . in ) & ( 1 < < ( pin & 31 ) ) ; }
static inline void gpio_hi ( int_fast8_t pin ) { if ( pin > = 0 ) * get_gpio_hi_reg ( pin ) = 1 < < ( pin & 31 ) ; } // ESP_LOGI("LGFX", "gpio_hi: %d", pin); }
static inline void gpio_lo ( int_fast8_t pin ) { if ( pin > = 0 ) * get_gpio_lo_reg ( pin ) = 1 < < ( pin & 31 ) ; } // ESP_LOGI("LGFX", "gpio_lo: %d", pin); }
2022-12-18 13:06:04 +00:00
# include "esp_lcd_panel_interface.h"
# include "esp_lcd_panel_rgb.h"
# include "esp_pm.h"
# include "esp_lcd_panel_ops.h"
# include <hal/dma_types.h>
# include <rom/cache.h>
# endif // USE_ESP32_S3
2022-10-03 11:24:27 +01:00
2021-04-11 11:30:50 +01:00
# define _UDSP_I2C 1
# define _UDSP_SPI 2
2022-10-03 11:24:27 +01:00
# define _UDSP_PAR8 3
# define _UDSP_PAR16 4
2022-12-18 13:06:04 +00:00
# define _UDSP_RGB 5
2021-04-11 11:30:50 +01:00
# define UDISP1_WHITE 1
# define UDISP1_BLACK 0
2021-04-16 18:36:45 +01:00
# define DISPLAY_INIT_MODE 0
# define DISPLAY_INIT_PARTIAL 1
# define DISPLAY_INIT_FULL 2
2021-04-14 13:26:59 +01:00
enum uColorType { uCOLOR_BW , uCOLOR_COLOR } ;
2021-04-11 11:30:50 +01:00
// Color definitions
# define UDISP_BLACK 0x0000 /* 0, 0, 0 */
# define UDISP_NAVY 0x000F /* 0, 0, 128 */
# define UDISP_DARKGREEN 0x03E0 /* 0, 128, 0 */
# define UDISP_DARKCYAN 0x03EF /* 0, 128, 128 */
# define UDISP_MAROON 0x7800 /* 128, 0, 0 */
# define UDISP_PURPLE 0x780F /* 128, 0, 128 */
# define UDISP_OLIVE 0x7BE0 /* 128, 128, 0 */
# define UDISP_LIGHTGREY 0xC618 /* 192, 192, 192 */
# define UDISP_DARKGREY 0x7BEF /* 128, 128, 128 */
# define UDISP_BLUE 0x001F /* 0, 0, 255 */
# define UDISP_GREEN 0x07E0 /* 0, 255, 0 */
# define UDISP_CYAN 0x07FF /* 0, 255, 255 */
# define UDISP_RED 0xF800 /* 255, 0, 0 */
# define UDISP_MAGENTA 0xF81F /* 255, 0, 255 */
# define UDISP_YELLOW 0xFFE0 /* 255, 255, 0 */
# define UDISP_WHITE 0xFFFF /* 255, 255, 255 */
# define UDISP_ORANGE 0xFD20 /* 255, 165, 0 */
# define UDISP_GREENYELLOW 0xAFE5 /* 173, 255, 47 */
# define UDISP_PINK 0xF81F
2021-04-14 13:26:59 +01:00
# ifdef ESP8266
# define PIN_OUT_SET 0x60000304
# define PIN_OUT_CLEAR 0x60000308
# define GPIO_SET(A) WRITE_PERI_REG( PIN_OUT_SET, 1 << A)
# define GPIO_CLR(A) WRITE_PERI_REG( PIN_OUT_CLEAR, 1 << A)
2021-04-19 16:01:33 +01:00
# define GPIO_CLR_SLOW(A) digitalWrite(A, LOW)
# define GPIO_SET_SLOW(A) digitalWrite(A, HIGH)
2021-04-14 13:26:59 +01:00
# else
# undef GPIO_SET
# undef GPIO_CLR
2021-04-19 16:01:33 +01:00
# undef GPIO_SET_SLOW
# undef GPIO_CLR_SLOW
2021-06-10 18:07:20 +01:00
# if CONFIG_IDF_TARGET_ESP32C3
# define GPIO_CLR(A) GPIO.out_w1tc.val = (1 << A)
# define GPIO_SET(A) GPIO.out_w1ts.val = (1 << A)
# else // plain ESP32
2021-04-14 13:26:59 +01:00
# define GPIO_CLR(A) GPIO.out_w1tc = (1 << A)
2021-04-19 16:01:33 +01:00
# define GPIO_SET(A) GPIO.out_w1ts = (1 << A)
2021-06-10 18:07:20 +01:00
# endif
2021-04-19 16:01:33 +01:00
# define GPIO_CLR_SLOW(A) digitalWrite(A, LOW)
# define GPIO_SET_SLOW(A) digitalWrite(A, HIGH)
2021-04-14 13:26:59 +01:00
# endif
2021-04-26 09:20:14 +01:00
# define SPI_BEGIN_TRANSACTION if (spi_nr <= 2) beginTransaction(spiSettings);
# define SPI_END_TRANSACTION if (spi_nr <= 2) endTransaction();
2021-11-16 07:09:04 +00:00
# define SPI_CS_LOW if (spi_cs >= 0) GPIO_CLR_SLOW(spi_cs);
# define SPI_CS_HIGH if (spi_cs >= 0) GPIO_SET_SLOW(spi_cs);
# define SPI_DC_LOW if (spi_dc >= 0) GPIO_CLR_SLOW(spi_dc);
# define SPI_DC_HIGH if (spi_dc >= 0) GPIO_SET_SLOW(spi_dc);
2021-04-19 16:01:33 +01:00
# define LUTMAXSIZE 64
2022-10-03 11:24:27 +01:00
# ifdef USE_ESP32_S3
struct esp_lcd_i80_bus_t {
int bus_id ; // Bus ID, index from 0
portMUX_TYPE spinlock ; // spinlock used to protect i80 bus members(hal, device_list, cur_trans)
lcd_hal_context_t hal ; // Hal object
size_t bus_width ; // Number of data lines
intr_handle_t intr ; // LCD peripheral interrupt handle
void * pm_lock ; // Power management lock
size_t num_dma_nodes ; // Number of DMA descriptors
uint8_t * format_buffer ; // The driver allocates an internal buffer for DMA to do data format transformer
size_t resolution_hz ; // LCD_CLK resolution, determined by selected clock source
gdma_channel_handle_t dma_chan ; // DMA channel handle
} ;
2022-12-18 13:06:04 +00:00
// extract from esp-idf esp_lcd_rgb_panel.c
struct esp_rgb_panel_t
{
esp_lcd_panel_t base ; // Base class of generic lcd panel
int panel_id ; // LCD panel ID
lcd_hal_context_t hal ; // Hal layer object
size_t data_width ; // Number of data lines (e.g. for RGB565, the data width is 16)
size_t sram_trans_align ; // Alignment for framebuffer that allocated in SRAM
size_t psram_trans_align ; // Alignment for framebuffer that allocated in PSRAM
int disp_gpio_num ; // Display control GPIO, which is used to perform action like "disp_off"
intr_handle_t intr ; // LCD peripheral interrupt handle
esp_pm_lock_handle_t pm_lock ; // Power management lock
size_t num_dma_nodes ; // Number of DMA descriptors that used to carry the frame buffer
uint8_t * fb ; // Frame buffer
size_t fb_size ; // Size of frame buffer
int data_gpio_nums [ SOC_LCD_RGB_DATA_WIDTH ] ; // GPIOs used for data lines, we keep these GPIOs for action like "invert_color"
size_t resolution_hz ; // Peripheral clock resolution
esp_lcd_rgb_timing_t timings ; // RGB timing parameters (e.g. pclk, sync pulse, porch width)
gdma_channel_handle_t dma_chan ; // DMA channel handle
esp_lcd_rgb_panel_frame_trans_done_cb_t on_frame_trans_done ; // Callback, invoked after frame trans done
void * user_ctx ; // Reserved user's data of callback functions
int x_gap ; // Extra gap in x coordinate, it's used when calculate the flush window
int y_gap ; // Extra gap in y coordinate, it's used when calculate the flush window
struct
{
unsigned int disp_en_level : 1 ; // The level which can turn on the screen by `disp_gpio_num`
unsigned int stream_mode : 1 ; // If set, the LCD transfers data continuously, otherwise, it stops refreshing the LCD when transaction done
unsigned int fb_in_psram : 1 ; // Whether the frame buffer is in PSRAM
} flags ;
dma_descriptor_t dma_nodes [ ] ; // DMA descriptor pool of size `num_dma_nodes`
} ;
2022-10-03 11:24:27 +01:00
# endif
2021-04-11 11:30:50 +01:00
class uDisplay : public Renderer {
public :
uDisplay ( char * ) ;
2021-04-21 10:10:59 +01:00
~ uDisplay ( void ) ;
2021-04-11 11:30:50 +01:00
Renderer * Init ( void ) ;
void DisplayInit ( int8_t p , int8_t size , int8_t rot , int8_t font ) ;
void Updateframe ( ) ;
void DisplayOnff ( int8_t on ) ;
void Splash ( void ) ;
char * devname ( void ) ;
2021-04-24 11:29:05 +01:00
uint16_t fgcol ( void ) ;
uint16_t bgcol ( void ) ;
int8_t color_type ( void ) ;
2021-09-14 21:40:26 +01:00
// void dim(uint8_t dim); // original version with 4 bits resolution 0..15
2022-01-27 20:30:05 +00:00
virtual void dim10 ( uint8_t dim , uint16_t dim_gamma ) ; // dimmer with 8 bits resolution, 0..255. Gamma correction must be done by caller with 10 bits resolution
2021-04-11 11:30:50 +01:00
uint16_t GetColorFromIndex ( uint8_t index ) ;
void setRotation ( uint8_t m ) ;
void fillScreen ( uint16_t color ) ;
void fillRect ( int16_t x , int16_t y , int16_t w , int16_t h , uint16_t color ) ;
void pushColors ( uint16_t * data , uint16_t len , boolean first ) ;
2021-04-14 13:26:59 +01:00
void TS_RotConvert ( int16_t * x , int16_t * y ) ;
void invertDisplay ( boolean i ) ;
2021-04-24 11:29:05 +01:00
void SetPwrCB ( pwr_cb cb ) { pwr_cbp = cb ; } ;
void SetDimCB ( dim_cb cb ) { dim_cbp = cb ; } ;
2021-04-11 11:30:50 +01:00
private :
2021-04-26 09:20:14 +01:00
void beginTransaction ( SPISettings s ) ;
void endTransaction ( void ) ;
2021-04-11 11:30:50 +01:00
void setAddrWindow ( uint16_t x0 , uint16_t y0 , uint16_t x1 , uint16_t y1 ) ;
void drawPixel ( int16_t x , int16_t y , uint16_t color ) ;
void drawFastHLine ( int16_t x , int16_t y , int16_t w , uint16_t color ) ;
void drawFastVLine ( int16_t x , int16_t y , int16_t h , uint16_t color ) ;
uint32_t str2c ( char * * sp , char * vp , uint32_t len ) ;
void i2c_command ( uint8_t val ) ;
2022-10-03 11:24:27 +01:00
void ulcd_command_one ( uint8_t val ) ;
void ulcd_command ( uint8_t val ) ;
void ulcd_data8 ( uint8_t val ) ;
void ulcd_data16 ( uint16_t val ) ;
void ulcd_data32 ( uint32_t val ) ;
2021-04-14 13:26:59 +01:00
void write8 ( uint8_t val ) ;
2021-04-19 16:01:33 +01:00
void write8_slow ( uint8_t val ) ;
2021-04-14 13:26:59 +01:00
void write9 ( uint8_t val , uint8_t dc ) ;
2021-04-19 16:01:33 +01:00
void write9_slow ( uint8_t val , uint8_t dc ) ;
2021-04-14 13:26:59 +01:00
void hw_write9 ( uint8_t val , uint8_t dc ) ;
void write16 ( uint16_t val ) ;
void write32 ( uint32_t val ) ;
void spi_data9 ( uint8_t d , uint8_t dc ) ;
void WriteColor ( uint16_t color ) ;
2021-04-16 18:36:45 +01:00
void SetLut ( const unsigned char * lut ) ;
2021-04-19 16:01:33 +01:00
void SetLuts ( void ) ;
void DisplayFrame_29 ( void ) ;
2021-04-16 18:36:45 +01:00
void Updateframe_EPD ( ) ;
2021-04-19 16:01:33 +01:00
//void DisplayFrame_42(const unsigned char* frame_buffer);
2021-04-16 18:36:45 +01:00
void SetFrameMemory ( const unsigned char * image_buffer ) ;
void SetFrameMemory ( const unsigned char * image_buffer , uint16_t x , uint16_t y , uint16_t image_width , uint16_t image_height ) ;
void SetMemoryArea ( int x_start , int y_start , int x_end , int y_end ) ;
void SetMemoryPointer ( int x , int y ) ;
void DrawAbsolutePixel ( int x , int y , int16_t color ) ;
void drawPixel_EPD ( int16_t x , int16_t y , uint16_t color ) ;
void fillRect_EPD ( int16_t x , int16_t y , int16_t w , int16_t h , uint16_t color ) ;
void drawFastVLine_EPD ( int16_t x , int16_t y , int16_t h , uint16_t color ) ;
void drawFastHLine_EPD ( int16_t x , int16_t y , int16_t w , uint16_t color ) ;
void Init_EPD ( int8_t p ) ;
void spi_command_EPD ( uint8_t val ) ;
void spi_data8_EPD ( uint8_t val ) ;
2021-04-19 16:01:33 +01:00
//void SetPartialWindow_42(uint8_t* frame_buffer, int16_t x, int16_t y, int16_t w, int16_t l, int16_t dtm);
2021-04-16 18:36:45 +01:00
void ClearFrameMemory ( unsigned char color ) ;
2021-04-19 16:01:33 +01:00
void ClearFrame_42 ( void ) ;
void DisplayFrame_42 ( void ) ;
2021-04-11 11:30:50 +01:00
uint8_t strlen_ln ( char * str ) ;
int32_t next_val ( char * * sp ) ;
uint32_t next_hex ( char * * sp ) ;
void setAddrWindow_int ( uint16_t x , uint16_t y , uint16_t w , uint16_t h ) ;
char dname [ 16 ] ;
int8_t bpp ;
2021-04-21 10:10:59 +01:00
uint8_t col_type ;
2021-04-11 11:30:50 +01:00
uint8_t interface ;
uint8_t i2caddr ;
int8_t i2c_scl ;
2021-04-16 18:36:45 +01:00
TwoWire * wire ;
2021-04-21 10:10:59 +01:00
int8_t wire_n ;
2021-04-11 11:30:50 +01:00
int8_t i2c_sda ;
2021-04-16 18:36:45 +01:00
uint8_t i2c_col_start ;
uint8_t i2c_col_end ;
uint8_t i2c_page_start ;
uint8_t i2c_page_end ;
2021-04-11 11:30:50 +01:00
int8_t reset ;
uint8_t dsp_cmds [ 128 ] ;
uint8_t dsp_ncmds ;
uint8_t dsp_on ;
uint8_t dsp_off ;
2021-04-18 08:20:54 +01:00
uint8_t allcmd_mode ;
2021-04-26 14:05:17 +01:00
int8_t splash_font ;
uint8_t splash_size ;
2021-04-11 11:30:50 +01:00
uint16_t splash_xp ;
uint16_t splash_yp ;
uint16_t fg_col ;
uint16_t bg_col ;
uint16_t gxs ;
uint16_t gys ;
2022-07-07 12:31:52 +01:00
int8_t bpmode ;
2021-04-11 11:30:50 +01:00
int8_t spi_cs ;
int8_t spi_clk ;
int8_t spi_mosi ;
int8_t spi_dc ;
2021-09-14 21:40:26 +01:00
int8_t bpanel ; // backbanel GPIO, -1 if none
2021-04-11 11:30:50 +01:00
int8_t spi_miso ;
2021-09-14 21:40:26 +01:00
uint8_t dimmer8 ; // 8 bits resolution, 0..255
2022-01-27 20:30:05 +00:00
uint16_t dimmer10_gamma ; // 10 bits resolution, 0..1023, gamma corrected
2021-04-11 11:30:50 +01:00
SPIClass * uspi ;
2021-04-14 13:26:59 +01:00
uint8_t sspi ;
2021-04-11 11:30:50 +01:00
SPISettings spiSettings ;
2021-04-14 13:26:59 +01:00
uint8_t spi_speed ;
2021-04-11 11:30:50 +01:00
uint8_t spi_nr = 1 ;
2021-04-14 13:26:59 +01:00
uint8_t madctrl ;
uint8_t startline ;
uint8_t rot [ 4 ] ;
uint8_t rot_t [ 4 ] ;
uint16_t x_addr_offs [ 4 ] ;
uint16_t y_addr_offs [ 4 ] ;
2021-04-11 11:30:50 +01:00
uint8_t saw_1 ;
uint8_t saw_2 ;
uint8_t saw_3 ;
2021-04-14 13:26:59 +01:00
uint8_t cur_rot ;
uint8_t col_mode ;
uint8_t inv_on ;
uint8_t inv_off ;
uint8_t sa_mode ;
uint8_t dim_op ;
2021-04-16 18:36:45 +01:00
uint8_t lutfsize ;
uint8_t lutpsize ;
uint16_t lutftime ;
uint16_t lutptime ;
uint16_t lut3time ;
2021-04-19 16:01:33 +01:00
uint16_t lut_num ;
2021-04-16 18:36:45 +01:00
uint8_t ep_mode ;
2021-04-19 16:01:33 +01:00
uint8_t lut_full [ LUTMAXSIZE ] ;
uint8_t lut_partial [ LUTMAXSIZE ] ;
uint8_t lut_array [ LUTMAXSIZE ] [ 5 ] ;
uint8_t lut_cnt [ 5 ] ;
uint8_t lut_cmd [ 5 ] ;
2021-04-25 07:24:07 +01:00
uint16_t seta_xp1 ;
uint16_t seta_xp2 ;
uint16_t seta_yp1 ;
uint16_t seta_yp2 ;
2021-05-10 21:26:59 +01:00
int16_t rotmap_xmin ;
int16_t rotmap_xmax ;
int16_t rotmap_ymin ;
int16_t rotmap_ymax ;
2021-05-30 18:06:23 +01:00
void pushColorsMono ( uint16_t * data , uint16_t len , bool rgb16_swap = false ) ;
2022-10-03 11:24:27 +01:00
# ifdef USE_ESP32_S3
int8_t par_cs ;
int8_t par_rs ;
int8_t par_wr ;
int8_t par_rd ;
int8_t par_dbl [ 8 ] ;
int8_t par_dbh [ 8 ] ;
2022-12-18 13:06:04 +00:00
int8_t de ;
int8_t vsync ;
int8_t hsync ;
int8_t pclk ;
uint16_t hsync_polarity ;
uint16_t hsync_front_porch ;
uint16_t hsync_pulse_width ;
uint16_t hsync_back_porch ;
uint16_t vsync_polarity ;
uint16_t vsync_front_porch ;
uint16_t vsync_pulse_width ;
uint16_t vsync_back_porch ;
uint16_t pclk_active_neg ;
esp_lcd_panel_handle_t _panel_handle = NULL ;
esp_rgb_panel_t * _rgb_panel ;
uint16_t * rgb_fb ;
2022-10-03 11:24:27 +01:00
esp_lcd_i80_bus_handle_t _i80_bus = nullptr ;
gdma_channel_handle_t _dma_chan ;
lldesc_t * _dmadesc = nullptr ;
uint32_t _dmadesc_size = 0 ;
uint32_t _clock_reg_value ;
void calcClockDiv ( uint32_t * div_a , uint32_t * div_b , uint32_t * div_n , uint32_t * clkcnt , uint32_t baseClock , uint32_t targetFreq ) ;
void _alloc_dmadesc ( size_t len ) ;
void _setup_dma_desc_links ( const uint8_t * data , int32_t len ) ;
void pb_beginTransaction ( void ) ;
void pb_endTransaction ( void ) ;
void pb_wait ( void ) ;
bool pb_busy ( void ) ;
void _pb_init_pin ( bool ) ;
bool pb_writeCommand ( uint32_t data , uint_fast8_t bit_length ) ;
void pb_writeData ( uint32_t data , uint_fast8_t bit_length ) ;
void pb_pushPixels ( uint16_t * data , uint32_t length , bool swap_bytes , bool use_dma ) ;
void pb_writeBytes ( const uint8_t * data , uint32_t length , bool use_dma ) ;
void _send_align_data ( void ) ;
volatile lcd_cam_dev_t * _dev ;
uint32_t * _cache_flip ;
static constexpr size_t CACHE_SIZE = 256 ;
uint32_t _cache [ 2 ] [ CACHE_SIZE / sizeof ( uint32_t ) ] ;
bool _has_align_data ;
uint8_t _align_data ;
void cs_control ( bool level ) ;
uint32_t get_sr_touch ( uint32_t xp , uint32_t xm , uint32_t yp , uint32_t ym ) ;
2022-12-18 13:06:04 +00:00
void drawPixel_RGB ( int16_t x , int16_t y , uint16_t color ) ;
2022-10-03 11:24:27 +01:00
# endif
2021-04-26 09:20:14 +01:00
# ifdef ESP32
// dma section
bool DMA_Enabled = false ;
uint8_t spiBusyCheck = 0 ;
spi_transaction_t trans ;
spi_device_handle_t dmaHAL ;
spi_host_device_t spi_host = VSPI_HOST ;
// spi_host_device_t spi_host = VSPI_HOST;
2022-04-17 21:47:26 +01:00
bool initDMA ( int32_t ctrl_cs ) ;
2021-04-26 09:20:14 +01:00
void deInitDMA ( void ) ;
bool dmaBusy ( void ) ;
void dmaWait ( void ) ;
void pushPixelsDMA ( uint16_t * image , uint32_t len ) ;
2021-05-01 08:54:49 +01:00
void pushPixels3DMA ( uint8_t * image , uint32_t len ) ;
2021-04-26 09:20:14 +01:00
# endif // ESP32
2021-04-11 11:30:50 +01:00
} ;
2021-04-14 13:26:59 +01:00
2021-04-11 11:30:50 +01:00
# endif // _UDISP_