├── .gitignore ├── .readthedocs.yml ├── LICENSE ├── README.md ├── docs ├── .gitignore ├── Makefile ├── en │ ├── COPYRIGHT.rst │ ├── api-reference │ │ ├── lcd.DPI.rst │ │ ├── lcd.I8080.rst │ │ ├── lcd.ILI9488.rst │ │ ├── lcd.QSPIPanel.rst │ │ ├── lcd.RM67162.rst │ │ ├── lcd.SPIPanel.rst │ │ ├── lcd.ST7735.rst │ │ ├── lcd.ST7789.rst │ │ └── lcd.rst │ ├── conf.py │ ├── index.rst │ └── screen │ │ ├── ILI9488.rst │ │ ├── RM67162.rst │ │ ├── ST7701S.rst │ │ ├── ST7735.rst │ │ ├── ST7789.rst │ │ └── index.rst ├── make.bat ├── requirements.txt └── zh_CN │ ├── COPYRIGHT.rst │ ├── api-reference │ ├── lcd.DPI.rst │ ├── lcd.I8080.rst │ ├── lcd.ILI9488.rst │ ├── lcd.QSPIPanel.rst │ ├── lcd.RM67162.rst │ ├── lcd.SPIPanel.rst │ ├── lcd.ST7735.rst │ ├── lcd.ST7789.rst │ └── lcd.rst │ ├── conf.py │ ├── index.rst │ └── screen │ ├── ILI9488.rst │ ├── RM67162.rst │ ├── ST7701S.rst │ ├── ST7735.rst │ ├── ST7789.rst │ └── index.rst ├── examples ├── color_loop │ └── color_loop.py ├── feathers │ └── feathers.py ├── framebuf │ └── use_framebuf.py ├── image_bitmap │ ├── image_bitmap.py │ ├── logo.mpy │ └── logo.py ├── scroll │ └── scroll.py └── tft_config │ ├── Air10x_LCD │ ├── README.md │ └── tft_config.py │ ├── ili9488 │ ├── README.md │ ├── image2lcd_setting.png │ └── tft_config.py │ ├── t-display │ └── tft_config.py │ ├── t-displays3-amoled │ └── tft_config.py │ ├── t-displays3 │ └── tft_config.py │ ├── t-rgb │ ├── tft_config.py │ └── xl9535.py │ ├── t-wristband │ ├── image2lcd_setting.png │ └── tft_config.py │ ├── waveshare_0.96inch_LCD_Module │ └── tft_config.py │ └── waveshare_1.28inch_LCD_Module │ └── tft_config.py └── lcd ├── bus ├── common │ └── lcd_panel.h ├── dpi │ ├── dpi_panel.c │ └── dpi_panel.h ├── i80 │ ├── i80_panel.c │ └── i80_panel.h ├── qspi │ ├── qspi_panel.c │ └── qspi_panel.h └── spi │ ├── spi_panel.c │ └── spi_panel.h ├── driver ├── common │ ├── lcd_panel_commands.h │ ├── lcd_panel_rotation.h │ ├── lcd_panel_types.c │ └── lcd_panel_types.h ├── gc9a01 │ ├── gc9a01.c │ ├── gc9a01.h │ └── gc9a01_rotation.h ├── ili9488 │ ├── ili9488.c │ ├── ili9488.h │ └── ili9488_rotation.h ├── rm67162 │ ├── rm67162.c │ ├── rm67162.h │ └── rm67162_rotation.h ├── st7735 │ ├── st7735.c │ ├── st7735.h │ └── st7735_rotation.h └── st7789 │ ├── st7789.c │ ├── st7789.h │ └── st7789_rotation.h ├── hal ├── common │ ├── soft8080.c │ ├── soft8080.h │ ├── softspi.c │ └── softspi.h └── esp32 │ ├── esp32.c │ └── esp32.h ├── micropython.cmake └── modlcd.c /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | lcd_binding_micropython.code-workspace -------------------------------------------------------------------------------- /.readthedocs.yml: -------------------------------------------------------------------------------- 1 | # .readthedocs.yml 2 | # Read the Docs configuration file 3 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 4 | 5 | # Required 6 | version: 2 7 | 8 | # Optionally build your docs in additional formats such as PDF and ePub 9 | formats: all 10 | 11 | # Optionally set the version of Python and requirements required to build your docs 12 | python: 13 | version: 3.7 14 | install: 15 | - requirements: docs/requirements.txt -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 lbuque 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | LCD Driver for MicroPython 2 | ------------------------------ 3 | 4 | Contents: 5 | 6 | - [LCD Driver for MicroPython](#lcd-driver-for-micropython) 7 | - [Introduction](#introduction) 8 | - [Features](#features) 9 | - [Documentation](#documentation) 10 | - [References](#references) 11 | - [Future plans](#future-plans) 12 | 13 | ## Introduction 14 | 15 | This driver is based on [esp_lcd](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/lcd.html). 16 | 17 | Currently only some basic functions are supported.It will be compatible with [st7789_mpy](https://github.com/russhughes/st7789_mpy) in the future. 18 | 19 | ## Features 20 | 21 | The following display driver ICs are supported: 22 | 23 | - Support for ST7789 displays 24 | - Support for ST7701 displays (based on [esp_lcd](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/lcd.html)) 25 | - Support for ST7735 displays 26 | - Support for ILI9488 displays 27 | - Support for RM67162 displays 28 | 29 | Supported boards: 30 | 31 | - [LILYGO T-DisplayS3](https://github.com/Xinyuan-LilyGO/T-Display-S3) 32 | - [LILYGO T-RGB](https://github.com/Xinyuan-LilyGO/T-RGB) 33 | - [LILYGO T-Display](https://github.com/Xinyuan-LilyGO/TTGO-T-Display) 34 | - [LILYGO T-Wristband](https://github.com/Xinyuan-LilyGO/T-Wristband) 35 | - [LILYGO T-DisplayS3-AMOLED](https://github.com/Xinyuan-LilyGO/T-Display-S3-AMOLED) 36 | 37 | | Driver IC | Hardware SPI | Software SPI | Hardware QSPI | I8080 | DPI(RGB) | 38 | | --------- | ---------------- | ---------------- | ---------------- | ---------------- | ---------------- | 39 | | ESP32 | ![alt text][1] | ![alt text][1] | ![alt text][1] | ![alt text][1] | ![alt text][2] | 40 | | ESP32-C3 | ![alt text][4] | ![alt text][4] | ![alt text][4] | ![alt text][2] | ![alt text][2] | 41 | | ESP32-S2 | ![alt text][4] | ![alt text][4] | ![alt text][4] | ![alt text][4] | ![alt text][2] | 42 | | ESP32-S3 | ![alt text][1] | ![alt text][1] | ![alt text][1] | ![alt text][1] | ![alt text][1] | 43 | 44 | [1]: https://camo.githubusercontent.com/bd5f5f82b920744ff961517942e99a46699fee58737cd9b31bf56e5ca41b781b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f2d737570706f727465642d677265656e 45 | [2]: https://img.shields.io/badge/-not%20support-lightgrey 46 | [3]: https://img.shields.io/badge/-untested-red 47 | [4]: https://img.shields.io/badge/-todo-blue 48 | 49 | ## Documentation 50 | 51 | API documentation for this library can be found on [Read the Docs](https://lcd-binding-micropython.readthedocs.io/en/latest/). 52 | 53 | ## More 54 | 55 | If you need to support more screens, please provide corresponding hardware. 56 | 57 | # Related Repositories 58 | 59 | - [framebuf-plus](https://github.com/lbuque/framebuf-plus) 60 | 61 | ## References 62 | 63 | - [st7789s3_mpy](https://github.com/russhughes/st7789s3_mpy) 64 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | build -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = zh_CN 9 | BUILDDIR = build/$(SOURCEDIR) 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | doxygen: 16 | doxygen 17 | 18 | .PHONY: help Makefile #doxygen 19 | 20 | # Catch-all target: route all unknown targets to Sphinx using the new 21 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 22 | %: Makefile #doxygen 23 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) -------------------------------------------------------------------------------- /docs/en/COPYRIGHT.rst: -------------------------------------------------------------------------------- 1 | ************************ 2 | Copyrights and Licenses 3 | ************************ 4 | 5 | Software Copyrights 6 | ==================== 7 | 8 | All original source code in this repository is Copyright (C) 2023 lbuque. This source code is licensed under the MIT license as described in the file LICENSE. 9 | 10 | Documentation 11 | ============== 12 | 13 | * HTML version of API documentation uses the Sphinx theme sphinx_idf_theme, which is Copyright (c) 2013-2020 Dave Snider, Read the Docs. It is licensed under the MIT license. -------------------------------------------------------------------------------- /docs/en/api-reference/lcd.DPI.rst: -------------------------------------------------------------------------------- 1 | class DPI -- DPI Interface 2 | =========================== 3 | 4 | The DPI(RGB) class is the DPI(RGB) parallel interface hardware abstract class, which implements some common interfaces of DPI. 5 | 6 | Constructors 7 | ------------ 8 | 9 | .. class:: DPI(data: tuple, hsync: Pin, vsync: Pin, de: Pin, pclk_pin: Pin, timings: tuple, disp: Pin=None, backlight: Pin=None, pclk: int=8000000, width: int=480, height: int=480) 10 | 11 | Create an DPI hardware abstract class. 12 | 13 | These parameters are: 14 | 15 | - ``data``: Tuple of data bus, currently only supports 16-bit RGB interface 16 | - ``hsync``: Pin used for hsync signal 17 | - ``vsync``: Pin used for vsync signal 18 | - ``de``: Pin used for DE signal, set to None if it’s not used 19 | - ``pclk_pin``: Pin used for PCLK signal 20 | - ``timings``: RGB timing parameters 21 | - ``disp``: Pin used for display control signal, set to None if it’s not used 22 | - ``backlight``: Pin used for backlight signal 23 | - ``pclk``: Frequency of pixel clock 24 | - ``width``: Horizontal resolution, i.e. the number of pixels in a line 25 | - ``height``: Vertical resolution, i.e. the number of lines in the frame 26 | 27 | 28 | The ``timing`` must be a 6-tuple in the following format: 29 | 30 | (hsync_pulse_width, hsync_back_porch, hsync_front_porch, vsync_pulse_width, vsync_back_porch, vsync_front_porch) 31 | 32 | - ``hsync_pulse_width``: Horizontal sync width, unit: PCLK period 33 | - ``hsync_back_porch``: Horizontal back porch, number of PCLK between hsync and start of line active data 34 | - ``hsync_front_porch``: Horizontal front porch, number of PCLK between the end of active data and the next hsync 35 | - ``vsync_pulse_width``: Vertical sync width, unit: number of lines 36 | - ``vsync_back_porch``: Vertical back porch, number of invalid lines between vsync and start of frame 37 | - ``vsync_front_porch``: Vertical front porch, number of invalid lines between the end of frame and the next vsync 38 | 39 | Methods 40 | ------- 41 | 42 | .. method:: DPI.reset() 43 | 44 | Reset LCD panel. 45 | 46 | .. method:: DPI.init() 47 | 48 | Initialize LCD panel. 49 | 50 | .. note:: 51 | 52 | Before calling this method, make sure the LCD panel has finished the reset stage by DPI.reset(). 53 | 54 | .. method:: DPI.bitmap(x_start, y_start, x_end, y_end, color_data) 55 | 56 | Draw bitmap on LCD panel. 57 | 58 | The arguments are: 59 | 60 | - ``x_start`` - Start index on x-axis (x_start included) 61 | - ``y_start`` - Start index on y-axis (y_start included) 62 | - ``x_end`` - End index on x-axis (x_end not included) 63 | - ``y_end`` - End index on y-axis (y_end not included) 64 | - ``color_data`` - RGB color data that will be dumped to the specific window range 65 | 66 | .. method:: DPI.mirror(mirror_x: bool, mirror_y: bool) 67 | 68 | Mirror the LCD panel on specific axis. 69 | 70 | The arguments are: 71 | 72 | - ``mirror_x`` - Whether the panel will be mirrored about the x axis 73 | - ``mirror_y`` - Whether the panel will be mirrored about the y axis 74 | 75 | .. note:: 76 | 77 | Combined with DPI.swap_xy(), one can realize screen rotation 78 | 79 | .. method:: DPI.swap_xy(swap_axes: bool) 80 | 81 | Swap/Exchange x and y axis. 82 | 83 | - ``swap_axes`` - Whether to swap the x and y axis 84 | 85 | .. note:: 86 | 87 | Combined with DPI.mirror(), one can realize screen rotation 88 | 89 | .. method:: DPI.set_gap(x_gap: int, y_gap: int) 90 | 91 | Set extra gap in x and y axis. 92 | 93 | The gap is the space (in pixels) between the left/top sides of the LCD panel and the first row/column respectively of the actual contents displayed. 94 | 95 | The arguments are: 96 | 97 | - ``x_gap`` - Extra gap on x axis, in pixels 98 | - ``y_gap`` - Extra gap on y axis, in pixels 99 | 100 | .. note:: 101 | 102 | Setting a gap is useful when positioning or centering a frame that is smaller than the LCD. 103 | 104 | .. method:: DPI.invert_color(invert_color_data: bool) 105 | 106 | Invert the color (bit-wise invert the color data line) 107 | 108 | - ``invert_color_data`` - Whether to invert the color data 109 | 110 | .. method:: DPI.disp_off(off: bool) 111 | 112 | Turn off the display. 113 | 114 | - ``off`` - Whether to turn off the screen 115 | 116 | .. method:: DPI.backlight_on() 117 | 118 | Turn on the backlight. 119 | 120 | .. method:: DPI.backlight_off() 121 | 122 | turn off the backlight. 123 | 124 | .. method:: DPI.deint() 125 | 126 | Deinitialize the LCD panel. 127 | -------------------------------------------------------------------------------- /docs/en/api-reference/lcd.I8080.rst: -------------------------------------------------------------------------------- 1 | class I8080 -- Intel 8080 parallel LCD 2 | ======================================= 3 | 4 | The I8080 class implements the general control and access interface of the I8080 parallel bus, and can interact with the LCD driver chip through it. 5 | 6 | Constructors 7 | ------------ 8 | 9 | .. class:: I8080(data: tuple=None, dc: Pin=None, write: Pin=None, read: Pin=None, cs: Pin=None, pclk: int= 10000000, width: int=240, height: int=240, swap_color_bytes: bool=False, cmd_bits: int=8, param_bits: int=8) 10 | 11 | Create an Intel 8080 object. 12 | 13 | These parameters are: 14 | 15 | - ``data``: Pins used for data lines 16 | - ``dc``: Pin used for D/C line 17 | - ``write``: Pin used for WR line 18 | - ``read``: Pin used for RD line, set to None if it’s not used 19 | - ``cs``: Pin used for CS line, set to None if it’s not used 20 | - ``pclk``: Frequency of pixel clock 21 | - ``width``: Horizontal resolution, i.e. the number of pixels in a line 22 | - ``height``: Vertical resolution, i.e. the number of lines in the frame 23 | - ``swap_color_bytes``: Swap adjacent two color bytes 24 | - ``cmd_bits``: Bit-width of LCD command 25 | - ``param_bits``: Bit-width of LCD parameter 26 | 27 | Methods 28 | ------- 29 | 30 | .. method:: I8080.tx_param(cmd: int, param: bytes=None) 31 | 32 | Transmit LCD command and corresponding parameters. 33 | 34 | - cmd - The specific LCD command 35 | - param - Buffer that holds the command specific parameters 36 | 37 | .. method:: I8080.tx_color(cmd: int, color: bytes=None) 38 | 39 | Transmit LCD RGB data. 40 | 41 | - cmd - The specific LCD command 42 | - param - Buffer that holds the RGB color data 43 | 44 | .. method:: I8080.deinit() 45 | 46 | Destroys the Intel 8080 bus object. 47 | -------------------------------------------------------------------------------- /docs/en/api-reference/lcd.ILI9488.rst: -------------------------------------------------------------------------------- 1 | class ILI9488 -- ILITEK ILI9488 abstract classes 2 | ================================================= 3 | 4 | The ILI9488 class is the ILITEK ILI9488 hardware abstraction class, which implements some common interfaces of the ILI9488. 5 | 6 | Constructors 7 | ------------ 8 | 9 | .. class:: ILI9488(bus: I8080, reset: Pin=None, backlight: Pin=None, reset_level: bool=false, color_space: int=RGB, bpp: int=16) 10 | 11 | Create an ILI9488 hardware abstraction class. 12 | 13 | These parameters are: 14 | 15 | - ``bus``: I8080 obj 16 | - ``reset``: Pin used to reset the LCD panel, set to None if it’s not used 17 | - ``backlight``: Pin used for backlight signal 18 | - ``reset_level``: Setting this if the panel reset is high level active 19 | - ``color_space``: Set the color space used by the LCD panel 20 | - ``bpp``: Color depth, in bpp 21 | 22 | Methods 23 | ------- 24 | 25 | .. method:: ILI9488.reset() 26 | 27 | Reset LCD panel. 28 | 29 | .. method:: ILI9488.init() 30 | 31 | Initialize LCD panel. 32 | 33 | .. note:: 34 | 35 | Before calling this method, make sure the LCD panel has finished the reset stage by ILI9488.reset(). 36 | 37 | .. method:: ILI9488.bitmap(x_start: int, y_start: int, x_end: int, y_end: int, color_data: bytes=None) 38 | 39 | Draw bitmap on LCD panel. 40 | 41 | The arguments are: 42 | 43 | - ``x_start`` - Start index on x-axis (x_start included) 44 | - ``y_start`` - Start index on y-axis (y_start included) 45 | - ``x_end`` - End index on x-axis (x_end not included) 46 | - ``y_end`` - End index on y-axis (y_end not included) 47 | - ``color_data`` - RGB color data that will be dumped to the specific window range 48 | 49 | .. method:: ILI9488.mirror(mirror_x: bool, mirror_y: bool) 50 | 51 | Mirror the LCD panel on specific axis. 52 | 53 | The arguments are: 54 | 55 | - ``mirror_x`` - Whether the panel will be mirrored about the x axis 56 | - ``mirror_y`` - Whether the panel will be mirrored about the y axis 57 | 58 | .. note:: 59 | 60 | Combined with ILI9488.swap_xy(), one can realize screen rotation 61 | 62 | .. method:: ILI9488.swap_xy(swap_axes: bool) 63 | 64 | Swap/Exchange x and y axis. 65 | 66 | - ``swap_axes`` - Whether to swap the x and y axis 67 | 68 | .. note:: 69 | 70 | Combined with ILI9488.mirror(), one can realize screen rotation 71 | 72 | .. method:: ILI9488.set_gap(x_gap: int, y_gap: int) 73 | 74 | Set extra gap in x and y axis. 75 | 76 | The gap is the space (in pixels) between the left/top sides of the LCD panel and the first row/column respectively of the actual contents displayed. 77 | 78 | The arguments are: 79 | 80 | - ``x_gap`` - Extra gap on x axis, in pixels 81 | - ``y_gap`` - Extra gap on y axis, in pixels 82 | 83 | .. note:: 84 | 85 | Setting a gap is useful when positioning or centering a frame that is smaller than the LCD. 86 | 87 | .. method:: ILI9488.invert_color(invert_color_data: bool) 88 | 89 | Invert the color (bit-wise invert the color data line) 90 | 91 | - ``invert_color_data`` - Whether to invert the color data 92 | 93 | .. method:: ILI9488.disp_off(off: bool) 94 | 95 | Turn off the display. 96 | 97 | - ``off`` - Whether to turn off the screen 98 | 99 | .. method:: ILI9488.backlight_on() 100 | 101 | Turn on the backlight 102 | 103 | .. method:: ILI9488.backlight_off() 104 | 105 | turn off the backlight. 106 | 107 | .. method:: ILI9488.deint() 108 | 109 | Deinitialize the LCD panel. 110 | 111 | .. method:: ILI9488.rotation(r: int) 112 | 113 | Set the rotates the logical display in a counter-clockwise direction. 114 | 115 | The ``r`` parameter accepts only the following values: 116 | 117 | - ``0``: Portrait (0 degrees) 118 | - ``1``: Landscape (90 degrees) 119 | - ``2``: Inverse Portrait (180 degrees) 120 | - ``3``: Inverse Landscape (270 degrees) 121 | 122 | ``rotations`` sets the orientation table. The orientation table is a list of 123 | tuples for each ``rotation`` used to set the MADCTL register, display width, 124 | display height, start_x, and start_y values. 125 | 126 | +---------+----------------------------------------------------------------------------------------------------------+ 127 | | Display | Default Orientation Tables | 128 | +=========+==========================================================================================================+ 129 | | other | ((0x40, 0, 0, 0, 0), (0x20, 0, 0, 0, 0), (0x80, 0, 0, 0, 0), (0xE0, 0, 0, 0, 0)) | 130 | +---------+----------------------------------------------------------------------------------------------------------+ 131 | 132 | .. method:: ILI9488.vscroll_area(tfa: int, height: int, bfa: int) 133 | 134 | Set the vertical scrolling parameters. 135 | 136 | - ``tfa`` is the top fixed area in pixels. The top fixed area is the upper portion of the display frame buffer that will not be scrolled. 137 | 138 | - ``height`` is the total height in pixels of the area scrolled. 139 | 140 | - ``bfa`` is the bottom fixed area in pixels. The bottom fixed area is the lower portion of the display frame buffer that will not be scrolled. 141 | 142 | .. method:: ILI9488.vscroll_start(address: int, order: bool=False) 143 | 144 | Set the vertical scroll address. 145 | 146 | - ``address`` is the vertical scroll start address in pixels. The vertical scroll start address is the line in the frame buffer will be the first line shown after the TFA. 147 | - ``order`` is the Vertical Refresh Order. When ``order`` == ``False``, LCD vertical refresh Top to Bottom; When ``order`` == ``False``, LCD vertical refresh Bottom to Top. 148 | -------------------------------------------------------------------------------- /docs/en/api-reference/lcd.QSPIPanel.rst: -------------------------------------------------------------------------------- 1 | class QSPIPanel -- SPI Interfaced LCD 2 | ===================================== 3 | 4 | The QSPIPanel class implements the general control and access interface of the SPI serial bus, and can interact with the LCD driver chip through it. 5 | 6 | Constructors 7 | ------------ 8 | 9 | .. class:: QSPIPanel(spi: machine.SPI, data: tuple, dc: Pin, cs: Pin=None, pclk: int=10000000, width: int=240, height: int=240, cmd_bits: int=8, param_bits: int=8) 10 | 11 | Create an QSPIPanel object. 12 | 13 | These parameters are: 14 | 15 | - ``spi``: SPI object 16 | - ``data``: Pins used for data lines 17 | - ``dc``: Pins used for data lines 18 | - ``cs``: Pin used for CS line, set to None if it’s not used 19 | - ``pclk``: Frequency of pixel clock 20 | - ``width``: Horizontal resolution, i.e. the number of pixels in a line 21 | - ``height``: Vertical resolution, i.e. the number of lines in the frame 22 | - ``cmd_bits``: Bit-width of LCD command 23 | - ``param_bits``: Bit-width of LCD parameter 24 | 25 | Methods 26 | ------- 27 | 28 | .. method:: QSPIPanel.tx_param(cmd: int, param: bytes=None) 29 | 30 | Transmit LCD command and corresponding parameters. 31 | 32 | - cmd - The specific LCD command 33 | - param - Buffer that holds the command specific parameters 34 | 35 | .. method:: QSPIPanel.tx_color(cmd: int, color: bytes=None) 36 | 37 | Transmit LCD RGB data. 38 | 39 | - cmd - The specific LCD command 40 | - param - Buffer that holds the RGB color data 41 | 42 | .. method:: QSPIPanel.deinit() 43 | 44 | Destroys QSPIPanel object. 45 | -------------------------------------------------------------------------------- /docs/en/api-reference/lcd.RM67162.rst: -------------------------------------------------------------------------------- 1 | class RM67162 -- Raydium RM67162 abstract classes 2 | ================================================= 3 | 4 | The RM67162 class is the Raydium RM67162 hardware abstraction class, which implements some common interfaces of the RM67162. 5 | 6 | Constructors 7 | ------------ 8 | 9 | .. class:: RM67162(bus: I8080, reset: Pin=None, backlight: Pin=None, reset_level: bool=false, color_space: int=RGB, bpp: int=16) 10 | 11 | Create an RM67162 hardware abstraction class. 12 | 13 | These parameters are: 14 | 15 | - ``bus``: I8080 obj 16 | - ``reset``: Pin used to reset the LCD panel, set to None if it’s not used 17 | - ``backlight``: Pin used for backlight signal 18 | - ``reset_level``: Setting this if the panel reset is high level active 19 | - ``color_space``: Set the color space used by the LCD panel 20 | - ``bpp``: Color depth, in bpp 21 | 22 | Methods 23 | ------- 24 | 25 | .. method:: RM67162.reset() 26 | 27 | Reset LCD panel. 28 | 29 | .. method:: RM67162.init() 30 | 31 | Initialize LCD panel. 32 | 33 | .. note:: 34 | 35 | Before calling this method, make sure the LCD panel has finished the reset stage by RM67162.reset(). 36 | 37 | .. method:: RM67162.bitmap(x_start: int, y_start: int, x_end: int, y_end: int, color_data: bytes=None) 38 | 39 | Draw bitmap on LCD panel. 40 | 41 | The arguments are: 42 | 43 | - ``x_start`` - Start index on x-axis (x_start included) 44 | - ``y_start`` - Start index on y-axis (y_start included) 45 | - ``x_end`` - End index on x-axis (x_end not included) 46 | - ``y_end`` - End index on y-axis (y_end not included) 47 | - ``color_data`` - RGB color data that will be dumped to the specific window range 48 | 49 | .. method:: RM67162.mirror(mirror_x: bool, mirror_y: bool) 50 | 51 | Mirror the LCD panel on specific axis. 52 | 53 | The arguments are: 54 | 55 | - ``mirror_x`` - Whether the panel will be mirrored about the x axis 56 | - ``mirror_y`` - Whether the panel will be mirrored about the y axis 57 | 58 | .. note:: 59 | 60 | Combined with RM67162.swap_xy(), one can realize screen rotation 61 | 62 | .. method:: RM67162.swap_xy(swap_axes: bool) 63 | 64 | Swap/Exchange x and y axis. 65 | 66 | - ``swap_axes`` - Whether to swap the x and y axis 67 | 68 | .. note:: 69 | 70 | Combined with RM67162.mirror(), one can realize screen rotation 71 | 72 | .. method:: RM67162.set_gap(x_gap: int, y_gap: int) 73 | 74 | Set extra gap in x and y axis. 75 | 76 | The gap is the space (in pixels) between the left/top sides of the LCD panel and the first row/column respectively of the actual contents displayed. 77 | 78 | The arguments are: 79 | 80 | - ``x_gap`` - Extra gap on x axis, in pixels 81 | - ``y_gap`` - Extra gap on y axis, in pixels 82 | 83 | .. note:: 84 | 85 | Setting a gap is useful when positioning or centering a frame that is smaller than the LCD. 86 | 87 | .. method:: RM67162.invert_color(invert_color_data: bool) 88 | 89 | Invert the color (bit-wise invert the color data line) 90 | 91 | - ``invert_color_data`` - Whether to invert the color data 92 | 93 | .. method:: RM67162.disp_off(off: bool) 94 | 95 | Turn off the display. 96 | 97 | - ``off`` - Whether to turn off the screen 98 | 99 | .. method:: RM67162.backlight_on() 100 | 101 | Turn on the backlight 102 | 103 | .. method:: RM67162.backlight_off() 104 | 105 | turn off the backlight. 106 | 107 | .. method:: RM67162.backlight(brightness: int) 108 | 109 | Adjust the brightness of the backlight. 110 | 111 | .. method:: RM67162.deint() 112 | 113 | Deinitialize the LCD panel. 114 | 115 | .. method:: RM67162.rotation(r: int) 116 | 117 | Set the rotates the logical display in a counter-clockwise direction. 118 | 119 | The ``r`` parameter accepts only the following values: 120 | 121 | - ``0``: Portrait (0 degrees) 122 | - ``1``: Landscape (90 degrees) 123 | - ``2``: Inverse Portrait (180 degrees) 124 | - ``3``: Inverse Landscape (270 degrees) 125 | 126 | ``rotations`` sets the orientation table. The orientation table is a list of 127 | tuples for each ``rotation`` used to set the MADCTL register, display width, 128 | display height, start_x, and start_y values. 129 | 130 | +---------+----------------------------------------------------------------------------------------------------------+ 131 | | Display | Default Orientation Tables | 132 | +=========+==========================================================================================================+ 133 | | 240x536 | ((0x00, 240, 536, 0, 0), (0x60, 536, 240, 0, 0), (0xC0, 240, 536, 0, 0), (0xA0, 536, 240, 0, 0)) | 134 | +---------+----------------------------------------------------------------------------------------------------------+ 135 | | other | ((0x00, 0, 0, 0, 0), (0x60, 0, 0, 0, 0), (0xC0, 0, 0, 0, 0), (0xA0, 0, 0, 0, 0)) | 136 | +---------+----------------------------------------------------------------------------------------------------------+ 137 | 138 | .. method:: RM67162.vscroll_area(tfa: int, height: int, bfa: int) 139 | 140 | Set the vertical scrolling parameters. 141 | 142 | - ``tfa`` is the top fixed area in pixels. The top fixed area is the upper portion of the display frame buffer that will not be scrolled. 143 | 144 | - ``height`` is the total height in pixels of the area scrolled. 145 | 146 | - ``bfa`` is the bottom fixed area in pixels. The bottom fixed area is the lower portion of the display frame buffer that will not be scrolled. 147 | 148 | .. method:: RM67162.vscroll_start(address: int, order: bool=False) 149 | 150 | Set the vertical scroll address. 151 | 152 | - ``address`` is the vertical scroll start address in pixels. The vertical scroll start address is the line in the frame buffer will be the first line shown after the TFA. 153 | - ``order`` is the Vertical Refresh Order. When ``order`` == ``False``, LCD vertical refresh Top to Bottom; When ``order`` == ``False``, LCD vertical refresh Bottom to Top. 154 | -------------------------------------------------------------------------------- /docs/en/api-reference/lcd.SPIPanel.rst: -------------------------------------------------------------------------------- 1 | class SPIPanel -- SPI Interfaced LCD 2 | ===================================== 3 | 4 | The SPIPanel class implements the general control and access interface of the SPI serial bus, and can interact with the LCD driver chip through it. 5 | 6 | Constructors 7 | ------------ 8 | 9 | .. class:: SPIPanel(spi: machine.SPI, dc: Pin, cs: Pin=None, pclk: int=10000000, width: int=240, height: int=240, cmd_bits: int=8, param_bits: int=8) 10 | 11 | Create an SPIPanel object. 12 | 13 | These parameters are: 14 | 15 | - ``spi``: SPI object 16 | - ``dc``: Pins used for data lines 17 | - ``cs``: Pin used for CS line, set to None if it’s not used 18 | - ``pclk``: Frequency of pixel clock 19 | - ``width``: Horizontal resolution, i.e. the number of pixels in a line 20 | - ``height``: Vertical resolution, i.e. the number of lines in the frame 21 | - ``cmd_bits``: Bit-width of LCD command 22 | - ``param_bits``: Bit-width of LCD parameter 23 | 24 | Methods 25 | ------- 26 | 27 | .. method:: SPIPanel.tx_param(cmd: int, param: bytes=None) 28 | 29 | Transmit LCD command and corresponding parameters. 30 | 31 | - cmd - The specific LCD command 32 | - param - Buffer that holds the command specific parameters 33 | 34 | .. method:: SPIPanel.tx_color(cmd: int, color: bytes=None) 35 | 36 | Transmit LCD RGB data. 37 | 38 | - cmd - The specific LCD command 39 | - param - Buffer that holds the RGB color data 40 | 41 | .. method:: SPIPanel.deinit() 42 | 43 | Destroys SPIPanel object. 44 | -------------------------------------------------------------------------------- /docs/en/api-reference/lcd.ST7735.rst: -------------------------------------------------------------------------------- 1 | class ST7735 -- Sitronix ST7735 abstract classes 2 | ================================================= 3 | 4 | The ST7735 class is the Sitronix ST7735 hardware abstraction class, which implements some common interfaces of the ST7735. 5 | 6 | Constructors 7 | ------------ 8 | 9 | .. class:: ST7735(bus: I8080, reset: Pin=None, backlight: Pin=None, reset_level: bool=false, color_space: int=RGB, bpp: int=16) 10 | 11 | Create an ST7735 hardware abstraction class. 12 | 13 | These parameters are: 14 | 15 | - ``bus``: I8080 obj 16 | - ``reset``: Pin used to reset the LCD panel, set to None if it’s not used 17 | - ``backlight``: Pin used for backlight signal 18 | - ``reset_level``: Setting this if the panel reset is high level active 19 | - ``color_space``: Set the color space used by the LCD panel 20 | - ``bpp``: Color depth, in bpp 21 | 22 | Methods 23 | ------- 24 | 25 | .. method:: ST7735.reset() 26 | 27 | Reset LCD panel. 28 | 29 | .. method:: ST7735.init() 30 | 31 | Initialize LCD panel. 32 | 33 | .. note:: 34 | 35 | Before calling this method, make sure the LCD panel has finished the reset stage by ST7735.reset(). 36 | 37 | .. method:: ST7735.bitmap(x_start: int, y_start: int, x_end: int, y_end: int, color_data: bytes=None) 38 | 39 | Draw bitmap on LCD panel. 40 | 41 | The arguments are: 42 | 43 | - ``x_start`` - Start index on x-axis (x_start included) 44 | - ``y_start`` - Start index on y-axis (y_start included) 45 | - ``x_end`` - End index on x-axis (x_end not included) 46 | - ``y_end`` - End index on y-axis (y_end not included) 47 | - ``color_data`` - RGB color data that will be dumped to the specific window range 48 | 49 | .. method:: ST7735.mirror(mirror_x: bool, mirror_y: bool) 50 | 51 | Mirror the LCD panel on specific axis. 52 | 53 | The arguments are: 54 | 55 | - ``mirror_x`` - Whether the panel will be mirrored about the x axis 56 | - ``mirror_y`` - Whether the panel will be mirrored about the y axis 57 | 58 | .. note:: 59 | 60 | Combined with ST7735.swap_xy(), one can realize screen rotation 61 | 62 | .. method:: ST7735.swap_xy(swap_axes: bool) 63 | 64 | Swap/Exchange x and y axis. 65 | 66 | - ``swap_axes`` - Whether to swap the x and y axis 67 | 68 | .. note:: 69 | 70 | Combined with ST7735.mirror(), one can realize screen rotation 71 | 72 | .. method:: ST7735.set_gap(x_gap: int, y_gap: int) 73 | 74 | Set extra gap in x and y axis. 75 | 76 | The gap is the space (in pixels) between the left/top sides of the LCD panel and the first row/column respectively of the actual contents displayed. 77 | 78 | The arguments are: 79 | 80 | - ``x_gap`` - Extra gap on x axis, in pixels 81 | - ``y_gap`` - Extra gap on y axis, in pixels 82 | 83 | .. note:: 84 | 85 | Setting a gap is useful when positioning or centering a frame that is smaller than the LCD. 86 | 87 | .. method:: ST7735.invert_color(invert_color_data: bool) 88 | 89 | Invert the color (bit-wise invert the color data line) 90 | 91 | - ``invert_color_data`` - Whether to invert the color data 92 | 93 | .. method:: ST7735.disp_off(off: bool) 94 | 95 | Turn off the display. 96 | 97 | - ``off`` - Whether to turn off the screen 98 | 99 | .. method:: ST7735.backlight_on() 100 | 101 | Turn on the backlight 102 | 103 | .. method:: ST7735.backlight_off() 104 | 105 | turn off the backlight. 106 | 107 | .. method:: ST7735.deint() 108 | 109 | Deinitialize the LCD panel. 110 | 111 | .. method:: ST7735.rotation(r: int) 112 | 113 | Set the rotates the logical display in a counter-clockwise direction. 114 | 115 | The ``r`` parameter accepts only the following values: 116 | 117 | - ``0``: Portrait (0 degrees) 118 | - ``1``: Landscape (90 degrees) 119 | - ``2``: Inverse Portrait (180 degrees) 120 | - ``3``: Inverse Landscape (270 degrees) 121 | 122 | ``rotations`` sets the orientation table. The orientation table is a list of 123 | tuples for each ``rotation`` used to set the MADCTL register, display width, 124 | display height, start_x, and start_y values. 125 | 126 | +---------+----------------------------------------------------------------------------------------------------------+ 127 | | Display | Default Orientation Tables | 128 | +=========+==========================================================================================================+ 129 | | 160x80 | ((0x00, 80, 160, 26, 1), (0x60, 160, 80, 1, 26), (0xC0, 80, 160, 26, 1), (0xA0, 160, 80, 1, 26)) | 130 | +---------+----------------------------------------------------------------------------------------------------------+ 131 | | 160x80 | ((0x00, 80, 160, 24, 0), (0x60, 160, 80, 0, 24), (0xC0, 80, 160, 24, 0), (0xA0, 160, 80, 0, 24)) | 132 | +---------+----------------------------------------------------------------------------------------------------------+ 133 | | other | ((0x00, 0, 0, 0, 0), (0x60, 0, 0, 0, 0), (0xC0, 0, 0, 0, 0), (0xA0, 0, 0, 0, 0)) | 134 | +---------+----------------------------------------------------------------------------------------------------------+ 135 | 136 | .. method:: ST7735.vscroll_area(tfa: int, height: int, bfa: int) 137 | 138 | Set the vertical scrolling parameters. 139 | 140 | - ``tfa`` is the top fixed area in pixels. The top fixed area is the upper portion of the display frame buffer that will not be scrolled. 141 | 142 | - ``height`` is the total height in pixels of the area scrolled. 143 | 144 | - ``bfa`` is the bottom fixed area in pixels. The bottom fixed area is the lower portion of the display frame buffer that will not be scrolled. 145 | 146 | .. method:: ST7735.vscroll_start(address: int, order: bool=False) 147 | 148 | Set the vertical scroll address. 149 | 150 | - ``address`` is the vertical scroll start address in pixels. The vertical scroll start address is the line in the frame buffer will be the first line shown after the TFA. 151 | - ``order`` is the Vertical Refresh Order. When ``order`` == ``False``, LCD vertical refresh Top to Bottom; When ``order`` == ``False``, LCD vertical refresh Bottom to Top. 152 | -------------------------------------------------------------------------------- /docs/en/api-reference/lcd.ST7789.rst: -------------------------------------------------------------------------------- 1 | class ST7789 -- Sitronix ST7789 abstract classes 2 | ================================================= 3 | 4 | The ST7789 class is the Sitronix ST7789 hardware abstraction class, which implements some common interfaces of the ST7789. 5 | 6 | Constructors 7 | ------------ 8 | 9 | .. class:: ST7789(bus: I8080, reset: Pin=None, backlight: Pin=None, reset_level: bool=false, color_space: int=RGB, bpp: int=16) 10 | 11 | Create an ST7789 hardware abstraction class. 12 | 13 | These parameters are: 14 | 15 | - ``bus``: I8080 obj 16 | - ``reset``: Pin used to reset the LCD panel, set to None if it’s not used 17 | - ``backlight``: Pin used for backlight signal 18 | - ``reset_level``: Setting this if the panel reset is high level active 19 | - ``color_space``: Set the color space used by the LCD panel 20 | - ``bpp``: Color depth, in bpp 21 | 22 | Methods 23 | ------- 24 | 25 | .. method:: ST7789.reset() 26 | 27 | Reset LCD panel. 28 | 29 | .. method:: ST7789.init() 30 | 31 | Initialize LCD panel. 32 | 33 | .. note:: 34 | 35 | Before calling this method, make sure the LCD panel has finished the reset stage by ST7789.reset(). 36 | 37 | .. method:: ST7789.bitmap(x_start: int, y_start: int, x_end: int, y_end: int, color_data: bytes=None) 38 | 39 | Draw bitmap on LCD panel. 40 | 41 | The arguments are: 42 | 43 | - ``x_start`` - Start index on x-axis (x_start included) 44 | - ``y_start`` - Start index on y-axis (y_start included) 45 | - ``x_end`` - End index on x-axis (x_end not included) 46 | - ``y_end`` - End index on y-axis (y_end not included) 47 | - ``color_data`` - RGB color data that will be dumped to the specific window range 48 | 49 | .. method:: ST7789.mirror(mirror_x: bool, mirror_y: bool) 50 | 51 | Mirror the LCD panel on specific axis. 52 | 53 | The arguments are: 54 | 55 | - ``mirror_x`` - Whether the panel will be mirrored about the x axis 56 | - ``mirror_y`` - Whether the panel will be mirrored about the y axis 57 | 58 | .. note:: 59 | 60 | Combined with ST7789.swap_xy(), one can realize screen rotation 61 | 62 | .. method:: ST7789.swap_xy(swap_axes: bool) 63 | 64 | Swap/Exchange x and y axis. 65 | 66 | - ``swap_axes`` - Whether to swap the x and y axis 67 | 68 | .. note:: 69 | 70 | Combined with ST7789.mirror(), one can realize screen rotation 71 | 72 | .. method:: ST7789.set_gap(x_gap: int, y_gap: int) 73 | 74 | Set extra gap in x and y axis. 75 | 76 | The gap is the space (in pixels) between the left/top sides of the LCD panel and the first row/column respectively of the actual contents displayed. 77 | 78 | The arguments are: 79 | 80 | - ``x_gap`` - Extra gap on x axis, in pixels 81 | - ``y_gap`` - Extra gap on y axis, in pixels 82 | 83 | .. note:: 84 | 85 | Setting a gap is useful when positioning or centering a frame that is smaller than the LCD. 86 | 87 | .. method:: ST7789.invert_color(invert_color_data: bool) 88 | 89 | Invert the color (bit-wise invert the color data line) 90 | 91 | - ``invert_color_data`` - Whether to invert the color data 92 | 93 | .. method:: ST7789.disp_off(off: bool) 94 | 95 | Turn off the display. 96 | 97 | - ``off`` - Whether to turn off the screen 98 | 99 | .. method:: ST7789.backlight_on() 100 | 101 | Turn on the backlight 102 | 103 | .. method:: ST7789.backlight_off() 104 | 105 | turn off the backlight. 106 | 107 | .. method:: ST7789.deint() 108 | 109 | Deinitialize the LCD panel. 110 | 111 | .. method:: ST7789.rotation(r: int) 112 | 113 | Set the rotates the logical display in a counter-clockwise direction. 114 | 115 | The ``r`` parameter accepts only the following values: 116 | 117 | - ``0``: Portrait (0 degrees) 118 | - ``1``: Landscape (90 degrees) 119 | - ``2``: Inverse Portrait (180 degrees) 120 | - ``3``: Inverse Landscape (270 degrees) 121 | 122 | ``rotations`` sets the orientation table. The orientation table is a list of 123 | tuples for each ``rotation`` used to set the MADCTL register, display width, 124 | display height, start_x, and start_y values. 125 | 126 | +---------+----------------------------------------------------------------------------------------------------------+ 127 | | Display | Default Orientation Tables | 128 | +=========+==========================================================================================================+ 129 | | 240x320 | ((0x00, 240, 320, 0, 0), (0x60, 320, 240, 0, 0), (0xC0, 240, 320, 0, 0), (0xA0, 320, 240, 0, 0)) | 130 | +---------+----------------------------------------------------------------------------------------------------------+ 131 | | 170x320 | ((0x00, 170, 320, 35, 0), (0x60, 320, 170, 0, 35), (0xC0, 170, 320, 35, 0), (0xA0, 320, 170, 0, 35)) | 132 | +---------+----------------------------------------------------------------------------------------------------------+ 133 | | 240x240 | ((0x00, 240, 240, 0, 0), (0x60, 240, 240, 0, 0), (0xC0, 240, 240, 0, 80), (0xA0, 240, 240, 80, 0)) | 134 | +---------+----------------------------------------------------------------------------------------------------------+ 135 | | 135x240 | ((0x00, 135, 240, 52, 40), (0x60, 240, 135, 40, 53), (0xC0, 135, 240, 53, 40), (0xA0, 240, 135, 40, 52)) | 136 | +---------+----------------------------------------------------------------------------------------------------------+ 137 | | 128x160 | ((0x00, 128, 160, 0, 0), (0x60, 160, 128, 0, 0), (0xC0, 128, 160, 0, 0), (0xA0, 160, 128, 0, 0)) | 138 | +---------+----------------------------------------------------------------------------------------------------------+ 139 | | 128x128 | ((0x00, 128, 128, 2, 1), (0x60, 128, 128, 1, 2), (0xC0, 128, 128, 2, 3), (0xA0, 128, 128, 3, 2)) | 140 | +---------+----------------------------------------------------------------------------------------------------------+ 141 | | other | ((0x00, 0, 0, 0, 0), (0x60, 0, 0, 0, 0), (0xC0, 0, 0, 0, 0), (0xA0, 0, 0, 0, 0)) | 142 | +---------+----------------------------------------------------------------------------------------------------------+ 143 | 144 | .. method:: ST7789.vscroll_area(tfa: int, height: int, bfa: int) 145 | 146 | Set the vertical scrolling parameters. 147 | 148 | - ``tfa`` is the top fixed area in pixels. The top fixed area is the upper portion of the display frame buffer that will not be scrolled. 149 | 150 | - ``height`` is the total height in pixels of the area scrolled. 151 | 152 | - ``bfa`` is the bottom fixed area in pixels. The bottom fixed area is the lower portion of the display frame buffer that will not be scrolled. 153 | 154 | .. method:: ST7789.vscroll_start(address: int, order: bool=False) 155 | 156 | Set the vertical scroll address. 157 | 158 | - ``address`` is the vertical scroll start address in pixels. The vertical scroll start address is the line in the frame buffer will be the first line shown after the TFA. 159 | - ``order`` is the Vertical Refresh Order. When ``order`` == ``False``, LCD vertical refresh Top to Bottom; When ``order`` == ``False``, LCD vertical refresh Bottom to Top. 160 | -------------------------------------------------------------------------------- /docs/en/api-reference/lcd.rst: -------------------------------------------------------------------------------- 1 | :mod:`lcd` --- LCD Driver library 2 | ================================== 3 | 4 | .. module:: lcd 5 | :synopsis: LCD Driver library 6 | 7 | This module contains common LCD drivers on the market, such as SPI LCD, I80 LCD (aka Intel 8080 Parallel LCD), RGB LCD, etc. 8 | 9 | Currently SPI LCD is still in preparation. 10 | 11 | Classes 12 | -------- 13 | 14 | .. toctree:: 15 | :maxdepth: 1 16 | 17 | lcd.SPIPanel.rst 18 | lcd.QSPIPanel.rst 19 | lcd.I8080.rst 20 | lcd.DPI.rst 21 | lcd.ST7789.rst 22 | lcd.ST7735.rst 23 | lcd.ILI9488.rst 24 | lcd.RM67162.rst 25 | 26 | Constants 27 | --------- 28 | 29 | .. data:: RGB 30 | 31 | Color space: RGB 32 | 33 | .. data:: BGR 34 | 35 | Color space: BGR 36 | 37 | .. data:: MONOCHROME 38 | 39 | Color space: monochrome 40 | -------------------------------------------------------------------------------- /docs/en/conf.py: -------------------------------------------------------------------------------- 1 | # Configuration file for the Sphinx documentation builder. 2 | # 3 | # This file only contains a selection of the most common options. For a full 4 | # list see the documentation: 5 | # https://www.sphinx-doc.org/en/master/usage/configuration.html 6 | 7 | # -- Path setup -------------------------------------------------------------- 8 | 9 | # If extensions (or modules to document with autodoc) are in another directory, 10 | # add these directories to sys.path here. If the directory is relative to the 11 | # documentation root, use os.path.abspath to make it absolute, like shown here. 12 | # 13 | # import os 14 | # import sys 15 | # sys.path.insert(0, os.path.abspath('.')) 16 | import subprocess, os 17 | 18 | # -- Project information ----------------------------------------------------- 19 | 20 | project = 'Micropython LCD Library' 21 | copyright = '2022, lbuque' 22 | author = 'lbuque' 23 | 24 | # The full version, including alpha/beta/rc tags 25 | release = 'master' 26 | 27 | 28 | # -- General configuration --------------------------------------------------- 29 | 30 | # Add any Sphinx extension module names here, as strings. They can be 31 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 32 | # ones. 33 | extensions = [ 34 | 'breathe', 35 | 'recommonmark', 36 | 'sphinx_markdown_tables' 37 | ] 38 | 39 | # Add any paths that contain templates here, relative to this directory. 40 | templates_path = ['_templates'] 41 | 42 | # List of patterns, relative to source directory, that match files and 43 | # directories to ignore when looking for source files. 44 | # This pattern also affects html_static_path and html_extra_path. 45 | exclude_patterns = [] 46 | 47 | 48 | # -- Options for HTML output ------------------------------------------------- 49 | 50 | # The theme to use for HTML and HTML Help pages. See the documentation for 51 | # a list of builtin themes. 52 | # 53 | html_theme = 'sphinx_rtd_theme' 54 | 55 | # Add any paths that contain custom static files (such as style sheets) here, 56 | # relative to this directory. They are copied after the builtin static files, 57 | # so a file named "default.css" will overwrite the builtin "default.css". 58 | html_static_path = ['../_static'] 59 | 60 | breathe_projects = { "zbhci": "../build/xml/" } 61 | 62 | breathe_default_project = "zbhci" 63 | 64 | breathe_domain_by_extension = { 65 | "h" : "c", 66 | "c" : "c", 67 | } 68 | 69 | read_the_docs_build = os.environ.get('READTHEDOCS', None) == 'True' 70 | 71 | 72 | if read_the_docs_build: 73 | 74 | subprocess.call('cd ../; doxygen', shell=True) 75 | -------------------------------------------------------------------------------- /docs/en/index.rst: -------------------------------------------------------------------------------- 1 | ************ 2 | Get Started 3 | ************ 4 | 5 | Introduction 6 | ============= 7 | 8 | This driver is based on `esp_lcd`_. 9 | 10 | Currently only some basic functions are supported.It will be compatible with `st7789_mpy`_ in the future. 11 | 12 | .. _esp_lcd: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/lcd.html 13 | .. _st7789_mpy: https://github.com/russhughes/st7789_mpy 14 | 15 | Supported LCD Types 16 | ==================== 17 | 18 | - Intel 8080 parallel LCD 19 | - DPI(RGB) LCD 20 | - SPI LCD 21 | - QSPI LCD 22 | 23 | Supported driver ICs 24 | ===================== 25 | 26 | - ST7789 27 | - ST7701s 28 | - ST7735 29 | - ILI9488 30 | - RM67162 31 | 32 | Compiling guide 33 | ================ 34 | 35 | Get the source code 36 | -------------------- 37 | 38 | .. code-block:: shell 39 | 40 | cd micropython 41 | git clone https://github.com/lbuque/lcd_binding_micropython.git extmod/lcd_binding_micropython 42 | 43 | esp32 44 | ------ 45 | 46 | micropython <= v1.20.0 47 | ^^^^^^^^^^^^^^^^^^^^^^ 48 | 49 | .. note:: 50 | 51 | Please prepare `esp-idf release/v4.4 `_ before compiling 52 | 53 | For more detailed compilation of esp32, please refer to https://github.com/micropython/micropython/tree/master/ports/esp32 54 | 55 | modify ``micropython/ports/esp32/main/CMakeLists.txt``: 56 | 57 | .. code-block:: diff 58 | 59 | diff --git a/ports/esp32/main/CMakeLists.txt b/ports/esp32/main/CMakeLists.txt 60 | index f8acfa905..209547892 100644 61 | --- a/ports/esp32/main/CMakeLists.txt 62 | +++ b/ports/esp32/main/CMakeLists.txt 63 | @@ -124,6 +124,7 @@ set(IDF_COMPONENTS 64 | ulp 65 | vfs 66 | xtensa 67 | + esp_lcd 68 | ) 69 | 70 | if(IDF_VERSION_MINOR GREATER_EQUAL 1 OR IDF_VERSION_MAJOR GREATER_EQUAL 5) 71 | 72 | build: 73 | 74 | .. code-block:: shell 75 | 76 | cd ports/esp32/ 77 | make USER_C_MODULES=../../../extmod/lcd_binding_micropython/lcd/micropython.cmake 78 | 79 | micropython == master 80 | ^^^^^^^^^^^^^^^^^^^^^ 81 | 82 | .. note:: 83 | 84 | Please prepare `esp-idf v5.0.2 `_ before compiling 85 | 86 | For more detailed compilation of esp32, please refer to https://github.com/micropython/micropython/tree/master/ports/esp32 87 | 88 | modify ``lcd_binding_micropython/lcd/hal/esp32/esp32.c`` : 89 | 90 | .. code-block:: diff 91 | 92 | diff --git a/lcd/hal/esp32/esp32.c b/lcd/hal/esp32/esp32.c 93 | index b100971..907feeb 100644 94 | --- a/lcd/hal/esp32/esp32.c 95 | +++ b/lcd/hal/esp32/esp32.c 96 | @@ -119,8 +119,8 @@ inline void hal_lcd_spi_panel_deinit(mp_obj_base_t *self) 97 | 98 | for (int i = 0; i < 3; i++) { 99 | if (pins[i] != -1) { 100 | - gpio_pad_select_gpio(pins[i]); 101 | - gpio_matrix_out(pins[i], SIG_GPIO_OUT_IDX, false, false); 102 | + esp_rom_gpio_pad_select_gpio(pins[i]); 103 | + gpio_iomux_out(pins[i], SIG_GPIO_OUT_IDX, false); 104 | gpio_set_direction(pins[i], GPIO_MODE_INPUT); 105 | } 106 | } 107 | 108 | modify ``micropython/ports/esp32/esp32_common.cmake`` : 109 | 110 | .. code-block:: diff 111 | 112 | diff --git a/ports/esp32/esp32_common.cmake b/ports/esp32/esp32_common.cmake 113 | index 37a19316b..6be95ddf5 100644 114 | --- a/ports/esp32/esp32_common.cmake 115 | +++ b/ports/esp32/esp32_common.cmake 116 | @@ -136,6 +136,7 @@ list(APPEND IDF_COMPONENTS 117 | ulp 118 | vfs 119 | xtensa 120 | + esp_lcd 121 | ) 122 | 123 | # Register the main IDF component. 124 | 125 | build: 126 | 127 | .. code-block:: shell 128 | 129 | cd ports/esp32/ 130 | make USER_C_MODULES=../../../extmod/lcd_binding_micropython/lcd/micropython.cmake 131 | 132 | .. toctree:: 133 | :maxdepth: 1 134 | :hidden: 135 | 136 | self 137 | API Reference 138 | LCD WiKi 139 | Copyrights 140 | -------------------------------------------------------------------------------- /docs/en/screen/ILI9488.rst: -------------------------------------------------------------------------------- 1 | ILI9488 2 | ======== 3 | 4 | - `MSP3520 `_ 5 | -------------------------------------------------------------------------------- /docs/en/screen/RM67162.rst: -------------------------------------------------------------------------------- 1 | RM67162 2 | ======== 3 | 4 | - `LILYGO T-DisplayS3-AMOLED `_ 5 | -------------------------------------------------------------------------------- /docs/en/screen/ST7701S.rst: -------------------------------------------------------------------------------- 1 | ST7701S 2 | ======== 3 | 4 | - `LILYGO T-RGB `_ 5 | -------------------------------------------------------------------------------- /docs/en/screen/ST7735.rst: -------------------------------------------------------------------------------- 1 | ST7735 2 | ======= 3 | 4 | - `LILYGO T-Wristband `_ 5 | -------------------------------------------------------------------------------- /docs/en/screen/ST7789.rst: -------------------------------------------------------------------------------- 1 | ST7789 2 | ======= 3 | 4 | - `LILYGO T-DisplayS3 `_ 5 | - `LILYGO T-Display `_ 6 | -------------------------------------------------------------------------------- /docs/en/screen/index.rst: -------------------------------------------------------------------------------- 1 | LCD WiKi 2 | ========= 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | 7 | ST7735.rst 8 | ST7789.rst 9 | ST7701S.rst 10 | ILI9488.rst 11 | RM67162.rst 12 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=zh_CN 11 | set BUILDDIR=build 12 | 13 | if "%1" == "" goto help 14 | 15 | %SPHINXBUILD% >NUL 2>NUL 16 | if errorlevel 9009 ( 17 | echo. 18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 19 | echo.installed, then set the SPHINXBUILD environment variable to point 20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 21 | echo.may add the Sphinx directory to PATH. 22 | echo. 23 | echo.If you don't have Sphinx installed, grab it from 24 | echo.http://sphinx-doc.org/ 25 | exit /b 1 26 | ) 27 | 28 | doxygen.exe 29 | 30 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 31 | goto end 32 | 33 | :help 34 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 35 | 36 | :end 37 | popd 38 | -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | breathe>=4 2 | Sphinx>=3 3 | sphinx-rtd-theme>=0.5.2 4 | recommonmark 5 | sphinx_markdown_tables -------------------------------------------------------------------------------- /docs/zh_CN/COPYRIGHT.rst: -------------------------------------------------------------------------------- 1 | ************************ 2 | Copyrights and Licenses 3 | ************************ 4 | 5 | Software Copyrights 6 | ==================== 7 | 8 | All original source code in this repository is Copyright (C) 2023 lbuque. This source code is licensed under the MIT license as described in the file LICENSE. 9 | 10 | Documentation 11 | ============== 12 | 13 | * HTML version of API documentation uses the Sphinx theme sphinx_idf_theme, which is Copyright (c) 2013-2020 Dave Snider, Read the Docs. It is licensed under the MIT license. -------------------------------------------------------------------------------- /docs/zh_CN/api-reference/lcd.DPI.rst: -------------------------------------------------------------------------------- 1 | class DPI -- DPI Interface 2 | =========================== 3 | 4 | DPI 类是DPI(RGB)并行接口硬件抽象类,它实现了DPI的一些通用接口。 5 | 6 | Constructors 7 | ------------ 8 | 9 | .. class:: DPI(data: tuple, hsync: Pin, vsync: Pin, de: Pin, pclk_pin: Pin, timings: tuple, disp: Pin=None, backlight: Pin=None, pclk: int=8000000, width: int=480, height: int=480) 10 | 11 | 创建一个 DPI 硬件抽象类。 12 | 13 | 这些参数是: 14 | 15 | - ``data``: 数据总线的元组,目前只支持 16-bit DPI 接口 16 | - ``hsync``: 垂直同步引脚对象 17 | - ``vsync``: 水平同步引脚对象 18 | - ``de``: 用于 DE 信号的引脚,如果不使用则设置为 None 19 | - ``pclk_pin``: 用于 PCLK 信号的引脚对象 20 | - ``timings``: DPI时序参数 21 | - ``disp``: 用于显示控制信号的引脚对象,如果不使用则设置为 None 22 | - ``backlight``: 背光控制引脚对象 23 | - ``pclk``: 像素时钟频率 24 | - ``width``: 水平分辨率,即一行中的像素数 25 | - ``height``: 垂直分辨率,即帧中的行数 26 | 27 | 28 | ``timing`` 必须是以下格式的 6 元组: 29 | 30 | (hsync_pulse_width, hsync_back_porch, hsync_front_porch, vsync_pulse_width, vsync_back_porch, vsync_front_porch) 31 | 32 | - ``hsync_pulse_width``: 水平同步宽度,单位:PCLK 周期 33 | - ``hsync_back_porch``: 水平后沿,hsync 和行活动数据开始之间的 PCLK 数 34 | - ``hsync_front_porch``: 水平前沿,活动数据结束和下一个 hsync 之间的 PCLK 数 35 | - ``vsync_pulse_width``: 垂直同步宽度,单位:行数 36 | - ``vsync_back_porch``: 垂直后廊,垂直同步和帧开始之间的无效行数 37 | - ``vsync_front_porch``: 垂直前沿,帧结束和下一个垂直同步之间的无效行数 38 | 39 | Methods 40 | ------- 41 | 42 | .. method:: DPI.reset() 43 | 44 | 重置液晶面板。 45 | 46 | .. method:: DPI.init() 47 | 48 | 初始化液晶面板。 49 | 50 | .. note:: 51 | 52 | 在调用此方法之前,请确保 LCD 面板已通过 DPI.reset() 完成重置阶段。 53 | 54 | .. method:: DPI.bitmap(x_start, y_start, x_end, y_end, color_data) 55 | 56 | 在 LCD 面板上绘制位图。 57 | 58 | 参数如下: 59 | 60 | - ``x_start`` - x 轴上的起始索引(包括 x_start) 61 | - ``y_start`` - y 轴上的起始索引(包括 y_start) 62 | - ``x_end`` - x 轴上的结束索引(不包括 x_end) 63 | - ``y_end`` - y 轴上的结束索引(不包括 y_end) 64 | - ``color_data`` - 将转储到特定窗口范围的 DPI 颜色数据 65 | 66 | .. method:: DPI.mirror(mirror_x: bool, mirror_y: bool) 67 | 68 | 在特定轴上镜像 LCD 面板。 69 | 70 | 参数如下: 71 | 72 | - ``mirror_x`` - 面板是否将围绕 x 轴镜像 73 | - ``mirror_y`` - 面板是否将围绕 y 轴镜像 74 | 75 | .. note:: 76 | 77 | 结合DPI.swap_xy(),可以实现屏幕旋转 78 | 79 | .. method:: DPI.swap_xy(swap_axes: bool) 80 | 81 | 交换 x 和 y 轴。 82 | 83 | - ``swap_axes`` - 是否交换x和y轴 84 | 85 | .. note:: 86 | 87 | 结合DPI.mirror(),可以实现屏幕旋转 88 | 89 | .. method:: DPI.set_gap(x_gap: int, y_gap: int) 90 | 91 | 在 x 和 y 轴上设置额外的间隙。 92 | 93 | 间隙是液晶面板左侧/顶部与实际显示内容的第一行/列之间的空间(以像素为单位)。 94 | 95 | 参数如下: 96 | 97 | - ``x_gap`` - x 轴上的额外间隙,以像素为单位 98 | - ``y_gap`` - y 轴上的额外间隙,以像素为单位 99 | 100 | .. note:: 101 | 102 | 在定位或居中小于 LCD 的框架时,设置间隙非常有用。 103 | 104 | .. method:: DPI.invert_color(invert_color_data: bool) 105 | 106 | 反转颜色(按位反转颜色数据线) 107 | 108 | - ``invert_color_data`` - 是否反转颜色数据 109 | 110 | .. method:: DPI.disp_off(off: bool) 111 | 112 | 关闭显示器。 113 | 114 | - ``off`` - 是否关闭屏幕 115 | 116 | .. method:: DPI.backlight_on() 117 | 118 | 打开背光 119 | 120 | .. method:: DPI.backlight_off() 121 | 122 | 关闭背光 123 | 124 | .. method:: DPI.deint() 125 | 126 | 去初始化 LCD 面板。 127 | -------------------------------------------------------------------------------- /docs/zh_CN/api-reference/lcd.I8080.rst: -------------------------------------------------------------------------------- 1 | class I8080 -- Intel 8080 parallel LCD 2 | ======================================= 3 | 4 | I8080类实现了 I8080 并行总线的通用控制和访问接口,可以通过它和LCD驱动芯片进行交互。 5 | 6 | Constructors 7 | ------------ 8 | 9 | .. class:: I8080(data: tuple=None, dc: Pin=None, write: Pin=None, read: Pin=None, cs: Pin=None, pclk: int= 10000000, width: int=240, height: int=240, swap_color_bytes: bool=False, cmd_bits: int=8, param_bits: int=8) 10 | 11 | 创建一个Intel 8080的对象。 12 | 13 | 这些参数是: 14 | 15 | - ``data``: 用于数据线的引脚对象元组 16 | - ``dc``: 用于 D/C 线的引脚对象 17 | - ``write``: 用于 WR 线的引脚对象 18 | - ``read``: RD 线使用的引脚对象,如果不使用则设置为None 19 | - ``cs``: 用于 CS 线的引脚对象,如果不使用则设置为 None 20 | - ``pclk``: 像素时钟频率 21 | - ``width``: 水平分辨率,即一行中的像素数 22 | - ``height``: 垂直分辨率,即帧中的行数 23 | - ``swap_color_bytes``: 交换相邻的两个颜色字节 24 | - ``cmd_bits``: LCD 命令的位宽 25 | - ``param_bits``: LCD参数位宽 26 | 27 | Methods 28 | ------- 29 | 30 | .. method:: I8080.tx_param(cmd: int, param: bytes=None) 31 | 32 | 发送 LCD 命令和相应的参数。 33 | 34 | - cmd - 具体的 LCD 命令 35 | - param - 保存命令特定参数的缓冲区,如果命令不需要参数,则不需要传入 36 | 37 | .. method:: I8080.tx_color(cmd: int, color: bytes=None) 38 | 39 | 发送 LCD RGB 数据。 40 | 41 | - cmd - 具体的 LCD 命令 42 | - param - 保存 RGB 颜色数据的缓冲区 43 | 44 | .. method:: I8080.deinit() 45 | 46 | 销毁 Intel 8080总线对象。 47 | -------------------------------------------------------------------------------- /docs/zh_CN/api-reference/lcd.ILI9488.rst: -------------------------------------------------------------------------------- 1 | class ILI9488 -- Sitronix ILI9488 abstract classes 2 | ================================================== 3 | 4 | ILI9488 类是 ILITEK ILI9488 硬件抽象类,它实现了ILI9488的一些通用接口。 5 | 6 | Constructors 7 | ------------ 8 | 9 | .. class:: ILI9488(bus: I8080, reset: Pin=None, backlight: Pin=None, reset_level: bool=false, color_space: int=RGB, bpp: int=16) 10 | 11 | 创建一个ILI9488硬件抽象类。 12 | 13 | 这些参数是: 14 | 15 | - ``bus``: I8080 对象 16 | - ``reset``: 用于重置 LCD 面板的引脚,如果不使用则设置为 None 17 | - ``backlight``: 背光控制引脚 18 | - ``reset_level``: 如果面板复位为高电平有效,则设置此项 19 | - ``color_space``: 设置 LCD 面板使用的色彩空间 20 | - ``bpp``: 颜色深度,以 bpp 为单位 21 | 22 | Methods 23 | ------- 24 | 25 | .. method:: ILI9488.reset() 26 | 27 | 重置液晶面板。 28 | 29 | .. method:: ILI9488.init() 30 | 31 | 初始化液晶面板。 32 | 33 | .. note:: 34 | 35 | 在调用此方法之前,请确保 LCD 面板已通过 RGB.reset() 完成重置阶段。 36 | 37 | .. method:: ILI9488.bitmap(x_start: int, y_start: int, x_end: int, y_end: int, color_data: bytes=None) 38 | 39 | 在 LCD 面板上绘制位图。 40 | 41 | 参数如下: 42 | 43 | - ``x_start`` - x 轴上的起始索引(包括 x_start) 44 | - ``y_start`` - y 轴上的起始索引(包括 y_start) 45 | - ``x_end`` - x 轴上的结束索引(不包括 x_end) 46 | - ``y_end`` - y 轴上的结束索引(不包括 y_end) 47 | - ``color_data`` - 将转储到特定窗口范围的 RGB 颜色数据 48 | 49 | .. method:: ILI9488.mirror(mirror_x: bool, mirror_y: bool) 50 | 51 | 在特定轴上镜像 LCD 面板。 52 | 53 | 参数如下: 54 | 55 | - ``mirror_x`` - 面板是否将围绕 x 轴镜像 56 | - ``mirror_y`` - 面板是否将围绕 y 轴镜像 57 | 58 | .. note:: 59 | 60 | 结合RGB.swap_xy(),可以实现屏幕旋转 61 | 62 | .. method:: ILI9488.swap_xy(swap_axes: bool) 63 | 64 | 交换 x 和 y 轴。 65 | 66 | - ``swap_axes`` - 是否交换x和y轴 67 | 68 | .. note:: 69 | 70 | 结合RGB.mirror(),可以实现屏幕旋转 71 | 72 | .. method:: ILI9488.set_gap(x_gap: int, y_gap: int) 73 | 74 | 在 x 和 y 轴上设置额外的间隙。 75 | 76 | 间隙是液晶面板左侧/顶部与实际显示内容的第一行/列之间的空间(以像素为单位)。 77 | 78 | 参数如下: 79 | 80 | - ``x_gap`` - x 轴上的额外间隙,以像素为单位 81 | - ``y_gap`` - y 轴上的额外间隙,以像素为单位 82 | 83 | .. note:: 84 | 85 | 在定位或居中小于 LCD 的框架时,设置间隙非常有用。 86 | 87 | .. method:: ILI9488.invert_color(invert_color_data: bool) 88 | 89 | 反转颜色(按位反转颜色数据线) 90 | 91 | - ``invert_color_data`` - 是否反转颜色数据 92 | 93 | .. method:: ILI9488.disp_off(off: bool) 94 | 95 | 关闭显示器。 96 | 97 | - ``off`` - 是否关闭屏幕 98 | 99 | .. method:: ILI9488.backlight_on() 100 | 101 | 打开背光 102 | 103 | .. method:: ILI9488.backlight_off() 104 | 105 | 关闭背光 106 | 107 | .. method:: ILI9488.deint() 108 | 109 | 初始化 LCD 面板。 110 | 111 | .. method:: ILI9488.rotation(r: int, rotations: None | tuple) 112 | 113 | 设置以逆时针方向旋转逻辑显示。 114 | 115 | ``r`` 参数只接受以下的值: 116 | 117 | - ``0``: Portrait (0°C) 118 | - ``1``: Landscape (90°C) 119 | - ``2``: Inverse Portrait (180°C) 120 | - ``3``: Inverse Landscape (270°C) 121 | 122 | ``rotations`` 设置方向表。 方向表是用于设置 MADCTL 寄存器、显示宽度、显示高度、start_x 和 start_y 值的每个“旋转”的元组列表。 123 | 124 | +---------+----------------------------------------------------------------------------------------------------------+ 125 | | Display | Default Orientation Tables | 126 | +=========+==========================================================================================================+ 127 | | other | ((0x40, 0, 0, 0, 0), (0x20, 0, 0, 0, 0), (0x80, 0, 0, 0, 0), (0xE0, 0, 0, 0, 0)) | 128 | +---------+----------------------------------------------------------------------------------------------------------+ 129 | 130 | .. method:: ILI9488.vscroll_area(tfa: int, height: int, bfa: int) 131 | 132 | 设置垂直滚动参数。 133 | 134 | - ``tfa`` 是以像素为单位的顶部固定区域。 顶部固定区域是不会滚动的显示帧缓冲区的上部。 135 | 136 | - ``height`` 是滚动区域的总高度(以像素为单位)。 137 | 138 | - ``bfa`` 是以像素为单位的底部固定区域。 底部固定区域是显示帧缓冲区的下部,不会滚动。 139 | 140 | .. method:: ILI9488.vscroll_start(address: int, order: bool=False) 141 | 142 | 设置垂直滚动地址。 143 | 144 | - ``address`` 是以像素为单位的垂直滚动起始地址。 垂直滚动起始地址是帧缓冲区中的行,将是 TFA 之后显示的第一行。 145 | - ``order`` 是垂直刷新顺序。 当``order`` == ``False``时,LCD垂直刷新从上到下; 当``order`` == ``False``时,LCD垂直刷新从下到上。 146 | -------------------------------------------------------------------------------- /docs/zh_CN/api-reference/lcd.QSPIPanel.rst: -------------------------------------------------------------------------------- 1 | class QSPIPanel -- QSPI Interfaced LCD 2 | ======================================= 3 | 4 | QSPIPanel 类实现了 QSPI 串行行总线的通用控制和访问接口,可以通过它和LCD驱动芯片进行交互。 5 | 6 | Constructors 7 | ------------ 8 | 9 | .. class:: QSPIPanel(spi: machine.SPI, data: tuple, dc: Pin, cs: Pin=None, pclk: int=10000000, width: int=240, height: int=240, swap_color_bytes: bool=False, cmd_bits: int=8, param_bits: int=8) 10 | 11 | 创建一个 QSPIPanel 的对象。 12 | 13 | 这些参数是: 14 | 15 | - ``spi``: SPI 对象 16 | - ``data``: 用于数据线的引脚对象元组 17 | - ``dc``: 用于 D/C 线的引脚对象 18 | - ``cs``: 用于 CS 线的引脚对象,如果不使用则设置为 None 19 | - ``pclk``: 像素时钟频率 20 | - ``width``: 水平分辨率,即一行中的像素数 21 | - ``height``: 垂直分辨率,即帧中的行数 22 | - ``swap_color_bytes``: 交换相邻的两个颜色字节 23 | - ``cmd_bits``: LCD 命令的位宽 24 | - ``param_bits``: LCD参数位宽 25 | 26 | Methods 27 | ------- 28 | 29 | .. method:: QSPIPanel.tx_param(cmd: int, param: bytes=None) 30 | 31 | 发送 LCD 命令和相应的参数。 32 | 33 | - cmd - 具体的 LCD 命令 34 | - param - 保存命令特定参数的缓冲区,如果命令不需要参数,则不需要传入 35 | 36 | .. method:: QSPIPanel.tx_color(cmd: int, color: bytes=None) 37 | 38 | 发送 LCD RGB 数据。 39 | 40 | - cmd - 具体的 LCD 命令 41 | - param - 保存 RGB 颜色数据的缓冲区 42 | 43 | .. method:: QSPIPanel.deinit() 44 | 45 | 销毁 QSPIPanel 对象。 46 | -------------------------------------------------------------------------------- /docs/zh_CN/api-reference/lcd.RM67162.rst: -------------------------------------------------------------------------------- 1 | class RM67162 -- Raydium RM67162 abstract classes 2 | ================================================== 3 | 4 | RM67162 类是 Raydium RM67162 硬件抽象类,它实现了RM67162的一些通用接口。 5 | 6 | Constructors 7 | ------------ 8 | 9 | .. class:: RM67162(bus: I8080, reset: Pin=None, backlight: Pin=None, reset_level: bool=false, color_space: int=RGB, bpp: int=16) 10 | 11 | 创建一个RM67162硬件抽象类。 12 | 13 | 这些参数是: 14 | 15 | - ``bus``: I8080 对象 16 | - ``reset``: 用于重置 LCD 面板的引脚,如果不使用则设置为 None 17 | - ``backlight``: 背光控制引脚 18 | - ``reset_level``: 如果面板复位为高电平有效,则设置此项 19 | - ``color_space``: 设置 LCD 面板使用的色彩空间 20 | - ``bpp``: 颜色深度,以 bpp 为单位 21 | 22 | Methods 23 | ------- 24 | 25 | .. method:: RM67162.reset() 26 | 27 | 重置液晶面板。 28 | 29 | .. method:: RM67162.init() 30 | 31 | 初始化液晶面板。 32 | 33 | .. note:: 34 | 35 | 在调用此方法之前,请确保 LCD 面板已通过 RGB.reset() 完成重置阶段。 36 | 37 | .. method:: RM67162.bitmap(x_start: int, y_start: int, x_end: int, y_end: int, color_data: bytes=None) 38 | 39 | 在 LCD 面板上绘制位图。 40 | 41 | 参数如下: 42 | 43 | - ``x_start`` - x 轴上的起始索引(包括 x_start) 44 | - ``y_start`` - y 轴上的起始索引(包括 y_start) 45 | - ``x_end`` - x 轴上的结束索引(不包括 x_end) 46 | - ``y_end`` - y 轴上的结束索引(不包括 y_end) 47 | - ``color_data`` - 将转储到特定窗口范围的 RGB 颜色数据 48 | 49 | .. method:: RM67162.mirror(mirror_x: bool, mirror_y: bool) 50 | 51 | 在特定轴上镜像 LCD 面板。 52 | 53 | 参数如下: 54 | 55 | - ``mirror_x`` - 面板是否将围绕 x 轴镜像 56 | - ``mirror_y`` - 面板是否将围绕 y 轴镜像 57 | 58 | .. note:: 59 | 60 | 结合RGB.swap_xy(),可以实现屏幕旋转 61 | 62 | .. method:: RM67162.swap_xy(swap_axes: bool) 63 | 64 | 交换 x 和 y 轴。 65 | 66 | - ``swap_axes`` - 是否交换x和y轴 67 | 68 | .. note:: 69 | 70 | 结合RGB.mirror(),可以实现屏幕旋转 71 | 72 | .. method:: RM67162.set_gap(x_gap: int, y_gap: int) 73 | 74 | 在 x 和 y 轴上设置额外的间隙。 75 | 76 | 间隙是液晶面板左侧/顶部与实际显示内容的第一行/列之间的空间(以像素为单位)。 77 | 78 | 参数如下: 79 | 80 | - ``x_gap`` - x 轴上的额外间隙,以像素为单位 81 | - ``y_gap`` - y 轴上的额外间隙,以像素为单位 82 | 83 | .. note:: 84 | 85 | 在定位或居中小于 LCD 的框架时,设置间隙非常有用。 86 | 87 | .. method:: RM67162.invert_color(invert_color_data: bool) 88 | 89 | 反转颜色(按位反转颜色数据线) 90 | 91 | - ``invert_color_data`` - 是否反转颜色数据 92 | 93 | .. method:: RM67162.disp_off(off: bool) 94 | 95 | 关闭显示器。 96 | 97 | - ``off`` - 是否关闭屏幕 98 | 99 | .. method:: RM67162.backlight_on() 100 | 101 | 打开背光 102 | 103 | .. method:: RM67162.backlight_off() 104 | 105 | 关闭背光 106 | 107 | .. method:: RM67162.backlight(brightness: int) 108 | 109 | 调节背光亮度。 110 | 111 | .. method:: RM67162.deint() 112 | 113 | 初始化 LCD 面板。 114 | 115 | .. method:: RM67162.rotation(r: int, rotations: None | tuple) 116 | 117 | 设置以逆时针方向旋转逻辑显示。 118 | 119 | ``r`` 参数只接受以下的值: 120 | 121 | - ``0``: Portrait (0°C) 122 | - ``1``: Landscape (90°C) 123 | - ``2``: Inverse Portrait (180°C) 124 | - ``3``: Inverse Landscape (270°C) 125 | 126 | ``rotations`` 设置方向表。 方向表是用于设置 MADCTL 寄存器、显示宽度、显示高度、start_x 和 start_y 值的每个“旋转”的元组列表。 127 | 128 | +---------+----------------------------------------------------------------------------------------------------------+ 129 | | Display | Default Orientation Tables | 130 | +=========+==========================================================================================================+ 131 | | 240x536 | ((0x00, 240, 536, 0, 0), (0x60, 536, 240, 0, 0), (0xC0, 240, 536, 0, 0), (0xA0, 536, 240, 0, 0)) | 132 | +---------+----------------------------------------------------------------------------------------------------------+ 133 | | other | ((0x00, 0, 0, 0, 0), (0x60, 0, 0, 0, 0), (0xC0, 0, 0, 0, 0), (0xA0, 0, 0, 0, 0)) | 134 | +---------+----------------------------------------------------------------------------------------------------------+ 135 | 136 | .. method:: RM67162.vscroll_area(tfa: int, height: int, bfa: int) 137 | 138 | 设置垂直滚动参数。 139 | 140 | - ``tfa`` 是以像素为单位的顶部固定区域。 顶部固定区域是不会滚动的显示帧缓冲区的上部。 141 | 142 | - ``height`` 是滚动区域的总高度(以像素为单位)。 143 | 144 | - ``bfa`` 是以像素为单位的底部固定区域。 底部固定区域是显示帧缓冲区的下部,不会滚动。 145 | 146 | .. method:: RM67162.vscroll_start(address: int, order: bool=False) 147 | 148 | 设置垂直滚动地址。 149 | 150 | - ``address`` 是以像素为单位的垂直滚动起始地址。 垂直滚动起始地址是帧缓冲区中的行,将是 TFA 之后显示的第一行。 151 | - ``order`` 是垂直刷新顺序。 当 ``order`` == ``False`` 时,LCD垂直刷新从上到下; 当 ``order`` == ``False`` 时,LCD垂直刷新从下到上。 152 | -------------------------------------------------------------------------------- /docs/zh_CN/api-reference/lcd.SPIPanel.rst: -------------------------------------------------------------------------------- 1 | class SPIPanel -- SPI Interfaced LCD 2 | ===================================== 3 | 4 | SPIPanel 类实现了 SPI 串行行总线的通用控制和访问接口,可以通过它和LCD驱动芯片进行交互。 5 | 6 | Constructors 7 | ------------ 8 | 9 | .. class:: SPIPanel(spi: machine.SPI, dc: Pin, cs: Pin=None, pclk: int=10000000, width: int=240, height: int=240, swap_color_bytes: bool=False, cmd_bits: int=8, param_bits: int=8) 10 | 11 | 创建一个 SPIPanel 的对象。 12 | 13 | 这些参数是: 14 | 15 | - ``spi``: SPI 对象 16 | - ``dc``: 用于 D/C 线的引脚对象 17 | - ``cs``: 用于 CS 线的引脚对象,如果不使用则设置为 None 18 | - ``pclk``: 像素时钟频率 19 | - ``width``: 水平分辨率,即一行中的像素数 20 | - ``height``: 垂直分辨率,即帧中的行数 21 | - ``swap_color_bytes``: 交换相邻的两个颜色字节 22 | - ``cmd_bits``: LCD 命令的位宽 23 | - ``param_bits``: LCD参数位宽 24 | 25 | Methods 26 | ------- 27 | 28 | .. method:: SPIPanel.tx_param(cmd: int, param: bytes=None) 29 | 30 | 发送 LCD 命令和相应的参数。 31 | 32 | - cmd - 具体的 LCD 命令 33 | - param - 保存命令特定参数的缓冲区,如果命令不需要参数,则不需要传入 34 | 35 | .. method:: SPIPanel.tx_color(cmd: int, color: bytes=None) 36 | 37 | 发送 LCD RGB 数据。 38 | 39 | - cmd - 具体的 LCD 命令 40 | - param - 保存 RGB 颜色数据的缓冲区 41 | 42 | .. method:: SPIPanel.deinit() 43 | 44 | 销毁 SPIPanel 对象。 45 | -------------------------------------------------------------------------------- /docs/zh_CN/api-reference/lcd.ST7735.rst: -------------------------------------------------------------------------------- 1 | class ST7735 -- Sitronix ST7735 abstract classes 2 | ================================================= 3 | 4 | ST7735 类是 Sitronix ST7735 硬件抽象类,它实现了ST7735的一些通用接口。 5 | 6 | Constructors 7 | ------------ 8 | 9 | .. class:: ST7735(bus: I8080, reset: Pin=None, backlight: Pin=None, reset_level: bool=false, color_space: int=RGB, bpp: int=16) 10 | 11 | 创建一个ST7735硬件抽象类。 12 | 13 | 这些参数是: 14 | 15 | - ``bus``: I8080 对象 16 | - ``reset``: 用于重置 LCD 面板的引脚,如果不使用则设置为 None 17 | - ``backlight``: 背光控制引脚 18 | - ``reset_level``: 如果面板复位为高电平有效,则设置此项 19 | - ``color_space``: 设置 LCD 面板使用的色彩空间 20 | - ``bpp``: 颜色深度,以 bpp 为单位 21 | 22 | Methods 23 | ------- 24 | 25 | .. method:: ST7735.reset() 26 | 27 | 重置液晶面板。 28 | 29 | .. method:: ST7735.init() 30 | 31 | 初始化液晶面板。 32 | 33 | .. note:: 34 | 35 | 在调用此方法之前,请确保 LCD 面板已通过 RGB.reset() 完成重置阶段。 36 | 37 | .. method:: ST7735.bitmap(x_start: int, y_start: int, x_end: int, y_end: int, color_data: bytes=None) 38 | 39 | 在 LCD 面板上绘制位图。 40 | 41 | 参数如下: 42 | 43 | - ``x_start`` - x 轴上的起始索引(包括 x_start) 44 | - ``y_start`` - y 轴上的起始索引(包括 y_start) 45 | - ``x_end`` - x 轴上的结束索引(不包括 x_end) 46 | - ``y_end`` - y 轴上的结束索引(不包括 y_end) 47 | - ``color_data`` - 将转储到特定窗口范围的 RGB 颜色数据 48 | 49 | .. method:: ST7735.mirror(mirror_x: bool, mirror_y: bool) 50 | 51 | 在特定轴上镜像 LCD 面板。 52 | 53 | 参数如下: 54 | 55 | - ``mirror_x`` - 面板是否将围绕 x 轴镜像 56 | - ``mirror_y`` - 面板是否将围绕 y 轴镜像 57 | 58 | .. note:: 59 | 60 | 结合RGB.swap_xy(),可以实现屏幕旋转 61 | 62 | .. method:: ST7735.swap_xy(swap_axes: bool) 63 | 64 | 交换 x 和 y 轴。 65 | 66 | - ``swap_axes`` - 是否交换x和y轴 67 | 68 | .. note:: 69 | 70 | 结合RGB.mirror(),可以实现屏幕旋转 71 | 72 | .. method:: ST7735.set_gap(x_gap: int, y_gap: int) 73 | 74 | 在 x 和 y 轴上设置额外的间隙。 75 | 76 | 间隙是液晶面板左侧/顶部与实际显示内容的第一行/列之间的空间(以像素为单位)。 77 | 78 | 参数如下: 79 | 80 | - ``x_gap`` - x 轴上的额外间隙,以像素为单位 81 | - ``y_gap`` - y 轴上的额外间隙,以像素为单位 82 | 83 | .. note:: 84 | 85 | 在定位或居中小于 LCD 的框架时,设置间隙非常有用。 86 | 87 | .. method:: ST7735.invert_color(invert_color_data: bool) 88 | 89 | 反转颜色(按位反转颜色数据线) 90 | 91 | - ``invert_color_data`` - 是否反转颜色数据 92 | 93 | .. method:: ST7735.disp_off(off: bool) 94 | 95 | 关闭显示器。 96 | 97 | - ``off`` - 是否关闭屏幕 98 | 99 | .. method:: ST7735.backlight_on() 100 | 101 | 打开背光 102 | 103 | .. method:: ST7735.backlight_off() 104 | 105 | 关闭背光 106 | 107 | .. method:: ST7735.deint() 108 | 109 | 初始化 LCD 面板。 110 | 111 | .. method:: ST7735.rotation(r: int, rotations: None | tuple) 112 | 113 | 设置以逆时针方向旋转逻辑显示。 114 | 115 | ``r`` 参数只接受以下的值: 116 | 117 | - ``0``: Portrait (0°C) 118 | - ``1``: Landscape (90°C) 119 | - ``2``: Inverse Portrait (180°C) 120 | - ``3``: Inverse Landscape (270°C) 121 | 122 | ``rotations`` 设置方向表。 方向表是用于设置 MADCTL 寄存器、显示宽度、显示高度、start_x 和 start_y 值的每个“旋转”的元组列表。 123 | 124 | +---------+----------------------------------------------------------------------------------------------------------+ 125 | | Display | Default Orientation Tables | 126 | +=========+==========================================================================================================+ 127 | | 160x80 | ((0x00, 80, 160, 26, 1), (0x60, 160, 80, 1, 26), (0xC0, 80, 160, 26, 1), (0xA0, 160, 80, 1, 26)) | 128 | +---------+----------------------------------------------------------------------------------------------------------+ 129 | | 160x80 | ((0x00, 80, 160, 24, 0), (0x60, 160, 80, 0, 24), (0xC0, 80, 160, 24, 0), (0xA0, 160, 80, 0, 24)) | 130 | +---------+----------------------------------------------------------------------------------------------------------+ 131 | | other | ((0x00, 0, 0, 0, 0), (0x60, 0, 0, 0, 0), (0xC0, 0, 0, 0, 0), (0xA0, 0, 0, 0, 0)) | 132 | +---------+----------------------------------------------------------------------------------------------------------+ 133 | 134 | .. method:: ILI9488.vscroll_area(tfa: int, height: int, bfa: int) 135 | 136 | 设置垂直滚动参数。 137 | 138 | - ``tfa`` 是以像素为单位的顶部固定区域。 顶部固定区域是不会滚动的显示帧缓冲区的上部。 139 | 140 | - ``height`` 是滚动区域的总高度(以像素为单位)。 141 | 142 | - ``bfa`` 是以像素为单位的底部固定区域。 底部固定区域是显示帧缓冲区的下部,不会滚动。 143 | 144 | .. method:: ILI9488.vscroll_start(address: int, order: bool=False) 145 | 146 | 设置垂直滚动地址。 147 | 148 | - ``address`` 是以像素为单位的垂直滚动起始地址。 垂直滚动起始地址是帧缓冲区中的行,将是 TFA 之后显示的第一行。 149 | - ``order`` 是垂直刷新顺序。 当``order`` == ``False``时,LCD垂直刷新从上到下; 当``order`` == ``False``时,LCD垂直刷新从下到上。 150 | -------------------------------------------------------------------------------- /docs/zh_CN/api-reference/lcd.ST7789.rst: -------------------------------------------------------------------------------- 1 | class ST7789 -- Sitronix ST7789 abstract classes 2 | ================================================= 3 | 4 | ST7789 类是 Sitronix ST7789 硬件抽象类,它实现了ST7789的一些通用接口。 5 | 6 | Constructors 7 | ------------ 8 | 9 | .. class:: ST7789(bus: I8080, reset: Pin=None, backlight: Pin=None, reset_level: bool=false, color_space: int=RGB, bpp: int=16) 10 | 11 | 创建一个ST7789硬件抽象类。 12 | 13 | 这些参数是: 14 | 15 | - ``bus``: I8080 对象 16 | - ``reset``: 用于重置 LCD 面板的引脚,如果不使用则设置为 None 17 | - ``backlight``: 背光控制引脚 18 | - ``reset_level``: 如果面板复位为高电平有效,则设置此项 19 | - ``color_space``: 设置 LCD 面板使用的色彩空间 20 | - ``bpp``: 颜色深度,以 bpp 为单位 21 | 22 | Methods 23 | ------- 24 | 25 | .. method:: ST7789.reset() 26 | 27 | 重置液晶面板。 28 | 29 | .. method:: ST7789.init() 30 | 31 | 初始化液晶面板。 32 | 33 | .. note:: 34 | 35 | 在调用此方法之前,请确保 LCD 面板已通过 RGB.reset() 完成重置阶段。 36 | 37 | .. method:: ST7789.bitmap(x_start: int, y_start: int, x_end: int, y_end: int, color_data: bytes=None) 38 | 39 | 在 LCD 面板上绘制位图。 40 | 41 | 参数如下: 42 | 43 | - ``x_start`` - x 轴上的起始索引(包括 x_start) 44 | - ``y_start`` - y 轴上的起始索引(包括 y_start) 45 | - ``x_end`` - x 轴上的结束索引(不包括 x_end) 46 | - ``y_end`` - y 轴上的结束索引(不包括 y_end) 47 | - ``color_data`` - 将转储到特定窗口范围的 RGB 颜色数据 48 | 49 | .. method:: ST7789.mirror(mirror_x: bool, mirror_y: bool) 50 | 51 | 在特定轴上镜像 LCD 面板。 52 | 53 | 参数如下: 54 | 55 | - ``mirror_x`` - 面板是否将围绕 x 轴镜像 56 | - ``mirror_y`` - 面板是否将围绕 y 轴镜像 57 | 58 | .. note:: 59 | 60 | 结合RGB.swap_xy(),可以实现屏幕旋转 61 | 62 | .. method:: ST7789.swap_xy(swap_axes: bool) 63 | 64 | 交换 x 和 y 轴。 65 | 66 | - ``swap_axes`` - 是否交换x和y轴 67 | 68 | .. note:: 69 | 70 | 结合RGB.mirror(),可以实现屏幕旋转 71 | 72 | .. method:: ST7789.set_gap(x_gap: int, y_gap: int) 73 | 74 | 在 x 和 y 轴上设置额外的间隙。 75 | 76 | 间隙是液晶面板左侧/顶部与实际显示内容的第一行/列之间的空间(以像素为单位)。 77 | 78 | 参数如下: 79 | 80 | - ``x_gap`` - x 轴上的额外间隙,以像素为单位 81 | - ``y_gap`` - y 轴上的额外间隙,以像素为单位 82 | 83 | .. note:: 84 | 85 | 在定位或居中小于 LCD 的框架时,设置间隙非常有用。 86 | 87 | .. method:: ST7789.invert_color(invert_color_data: bool) 88 | 89 | 反转颜色(按位反转颜色数据线) 90 | 91 | - ``invert_color_data`` - 是否反转颜色数据 92 | 93 | .. method:: ST7789.disp_off(off: bool) 94 | 95 | 关闭显示器。 96 | 97 | - ``off`` - 是否关闭屏幕 98 | 99 | .. method:: ST7789.backlight_on() 100 | 101 | 打开背光 102 | 103 | .. method:: ST7789.backlight_off() 104 | 105 | 关闭背光 106 | 107 | .. method:: ST7789.deint() 108 | 109 | 初始化 LCD 面板。 110 | 111 | .. method:: ST7789.rotation(r: int, rotations: None | tuple) 112 | 113 | 设置以逆时针方向旋转逻辑显示。 114 | 115 | ``r`` 参数只接受以下的值: 116 | 117 | - ``0``: Portrait (0°C) 118 | - ``1``: Landscape (90°C) 119 | - ``2``: Inverse Portrait (180°C) 120 | - ``3``: Inverse Landscape (270°C) 121 | 122 | ``rotations`` 设置方向表。 方向表是用于设置 MADCTL 寄存器、显示宽度、显示高度、start_x 和 start_y 值的每个“旋转”的元组列表。 123 | 124 | +---------+----------------------------------------------------------------------------------------------------------+ 125 | | Display | Default Orientation Tables | 126 | +=========+==========================================================================================================+ 127 | | 240x320 | ((0x00, 240, 320, 0, 0), (0x60, 320, 240, 0, 0), (0xC0, 240, 320, 0, 0), (0xA0, 320, 240, 0, 0)) | 128 | +---------+----------------------------------------------------------------------------------------------------------+ 129 | | 170x320 | ((0x00, 170, 320, 35, 0), (0x60, 320, 170, 0, 35), (0xC0, 170, 320, 35, 0), (0xA0, 320, 170, 0, 35)) | 130 | +---------+----------------------------------------------------------------------------------------------------------+ 131 | | 240x240 | ((0x00, 240, 240, 0, 0), (0x60, 240, 240, 0, 0), (0xC0, 240, 240, 0, 80), (0xA0, 240, 240, 80, 0)) | 132 | +---------+----------------------------------------------------------------------------------------------------------+ 133 | | 135x240 | ((0x00, 135, 240, 52, 40), (0x60, 240, 135, 40, 53), (0xC0, 135, 240, 53, 40), (0xA0, 240, 135, 40, 52)) | 134 | +---------+----------------------------------------------------------------------------------------------------------+ 135 | | 128x160 | ((0x00, 128, 160, 0, 0), (0x60, 160, 128, 0, 0), (0xC0, 128, 160, 0, 0), (0xA0, 160, 128, 0, 0)) | 136 | +---------+----------------------------------------------------------------------------------------------------------+ 137 | | 128x128 | ((0x00, 128, 128, 2, 1), (0x60, 128, 128, 1, 2), (0xC0, 128, 128, 2, 3), (0xA0, 128, 128, 3, 2)) | 138 | +---------+----------------------------------------------------------------------------------------------------------+ 139 | | other | ((0x00, 0, 0, 0, 0), (0x60, 0, 0, 0, 0), (0xC0, 0, 0, 0, 0), (0xA0, 0, 0, 0, 0)) | 140 | +---------+----------------------------------------------------------------------------------------------------------+ 141 | 142 | .. method:: ILI9488.vscroll_area(tfa: int, height: int, bfa: int) 143 | 144 | 设置垂直滚动参数。 145 | 146 | - ``tfa`` 是以像素为单位的顶部固定区域。 顶部固定区域是不会滚动的显示帧缓冲区的上部。 147 | 148 | - ``height`` 是滚动区域的总高度(以像素为单位)。 149 | 150 | - ``bfa`` 是以像素为单位的底部固定区域。 底部固定区域是显示帧缓冲区的下部,不会滚动。 151 | 152 | .. method:: ILI9488.vscroll_start(address: int, order: bool=False) 153 | 154 | 设置垂直滚动地址。 155 | 156 | - ``address`` 是以像素为单位的垂直滚动起始地址。 垂直滚动起始地址是帧缓冲区中的行,将是 TFA 之后显示的第一行。 157 | - ``order`` 是垂直刷新顺序。 当``order`` == ``False``时,LCD垂直刷新从上到下; 当``order`` == ``False``时,LCD垂直刷新从下到上。 158 | -------------------------------------------------------------------------------- /docs/zh_CN/api-reference/lcd.rst: -------------------------------------------------------------------------------- 1 | :mod:`lcd` --- LCD Driver library 2 | ================================== 3 | 4 | .. module:: lcd 5 | :synopsis: LCD Driver library 6 | 7 | 该模块包含市面上常见的 LCD 驱动,如 SPI LCD、I80 LCD(又名 Intel 8080并行LCD)、RGB LCD等。 8 | 9 | Classes 10 | -------- 11 | 12 | .. toctree:: 13 | :maxdepth: 1 14 | 15 | lcd.SPIPanel.rst 16 | lcd.QSPIPanel.rst 17 | lcd.I8080.rst 18 | lcd.DPI.rst 19 | lcd.ST7789.rst 20 | lcd.ST7735.rst 21 | lcd.ILI9488.rst 22 | lcd.RM67162.rst 23 | 24 | Constants 25 | --------- 26 | 27 | .. data:: RGB 28 | 29 | 色彩空间顺序: RGB 30 | 31 | .. data:: BGR 32 | 33 | 色彩空间顺序: BGR 34 | 35 | .. data:: MONOCHROME 36 | 37 | 色彩空间顺序: monochrome 38 | -------------------------------------------------------------------------------- /docs/zh_CN/conf.py: -------------------------------------------------------------------------------- 1 | # Configuration file for the Sphinx documentation builder. 2 | # 3 | # This file only contains a selection of the most common options. For a full 4 | # list see the documentation: 5 | # https://www.sphinx-doc.org/en/master/usage/configuration.html 6 | 7 | # -- Path setup -------------------------------------------------------------- 8 | 9 | # If extensions (or modules to document with autodoc) are in another directory, 10 | # add these directories to sys.path here. If the directory is relative to the 11 | # documentation root, use os.path.abspath to make it absolute, like shown here. 12 | # 13 | # import os 14 | # import sys 15 | # sys.path.insert(0, os.path.abspath('.')) 16 | import subprocess, os 17 | 18 | # -- Project information ----------------------------------------------------- 19 | 20 | project = 'Micropython LCD Library' 21 | copyright = '2022, lbuque' 22 | author = 'lbuque' 23 | 24 | # The full version, including alpha/beta/rc tags 25 | release = 'master' 26 | 27 | 28 | # -- General configuration --------------------------------------------------- 29 | 30 | # Add any Sphinx extension module names here, as strings. They can be 31 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 32 | # ones. 33 | extensions = [ 34 | 'breathe', 35 | 'recommonmark', 36 | 'sphinx_markdown_tables' 37 | ] 38 | 39 | # Add any paths that contain templates here, relative to this directory. 40 | templates_path = ['_templates'] 41 | 42 | # List of patterns, relative to source directory, that match files and 43 | # directories to ignore when looking for source files. 44 | # This pattern also affects html_static_path and html_extra_path. 45 | exclude_patterns = [] 46 | 47 | 48 | # -- Options for HTML output ------------------------------------------------- 49 | 50 | # The theme to use for HTML and HTML Help pages. See the documentation for 51 | # a list of builtin themes. 52 | # 53 | html_theme = 'sphinx_rtd_theme' 54 | 55 | # Add any paths that contain custom static files (such as style sheets) here, 56 | # relative to this directory. They are copied after the builtin static files, 57 | # so a file named "default.css" will overwrite the builtin "default.css". 58 | html_static_path = ['../_static'] 59 | 60 | breathe_projects = { "zbhci": "../build/xml/" } 61 | 62 | breathe_default_project = "zbhci" 63 | 64 | breathe_domain_by_extension = { 65 | "h" : "c", 66 | "c" : "c", 67 | } 68 | 69 | read_the_docs_build = os.environ.get('READTHEDOCS', None) == 'True' 70 | 71 | 72 | if read_the_docs_build: 73 | 74 | subprocess.call('cd ../; doxygen', shell=True) 75 | -------------------------------------------------------------------------------- /docs/zh_CN/index.rst: -------------------------------------------------------------------------------- 1 | ********* 2 | 快速开始 3 | ********* 4 | 5 | 概况 6 | ==== 7 | 8 | 此驱动程序基于 `esp_lcd`_。 9 | 10 | 目前只支持部分基本功能,未来会兼容 `st7789_mpy`_。 11 | 12 | .. _esp_lcd: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/lcd.html 13 | .. _st7789_mpy: https://github.com/russhughes/st7789_mpy 14 | 15 | 已支持的LCD类型 16 | =============== 17 | 18 | - Intel 8080并行LCD 19 | - DPI(RGB) LCD 20 | - SPI LCD 21 | - QSPI LCD 22 | 23 | 已支持的驱动IC 24 | ============== 25 | 26 | - ST7789 27 | - ST7701s 28 | - ST7735 29 | - ILI9488 30 | - RM67162 31 | 32 | 编译指南 33 | ======== 34 | 35 | 获取源码 36 | --------- 37 | 38 | .. code-block:: shell 39 | 40 | cd micropython 41 | git clone https://github.com/lbuque/lcd_binding_micropython.git extmod/lcd_binding_micropython 42 | 43 | esp32 44 | ------ 45 | 46 | micropython <= v1.20.0 47 | ^^^^^^^^^^^^^^^^^^^^^^ 48 | 49 | .. note:: 50 | 51 | 编译前请准备好`esp-idf release/v4.4 `_ 52 | 53 | 关于esp32更详细的编译说明,请参考 https://github.com/micropython/micropython/tree/master/ports/esp32 54 | 55 | 修改 ``micropython/ports/esp32/main/CMakeLists.txt`` : 56 | 57 | .. code-block:: diff 58 | 59 | diff --git a/ports/esp32/main/CMakeLists.txt b/ports/esp32/main/CMakeLists.txt 60 | index f8acfa905..209547892 100644 61 | --- a/ports/esp32/main/CMakeLists.txt 62 | +++ b/ports/esp32/main/CMakeLists.txt 63 | @@ -124,6 +124,7 @@ set(IDF_COMPONENTS 64 | ulp 65 | vfs 66 | xtensa 67 | + esp_lcd 68 | ) 69 | 70 | if(IDF_VERSION_MINOR GREATER_EQUAL 1 OR IDF_VERSION_MAJOR GREATER_EQUAL 5) 71 | 72 | 编译: 73 | 74 | .. code-block:: shell 75 | 76 | cd ports/esp32/ 77 | make USER_C_MODULES=../../../extmod/lcd_binding_micropython/lcd/micropython.cmake 78 | 79 | micropython == master 80 | ^^^^^^^^^^^^^^^^^^^^^ 81 | 82 | .. note:: 83 | 84 | 编译前请准备好`esp-idf v5.0.2 `_ 85 | 86 | 关于esp32更详细的编译说明,请参考 https://github.com/micropython/micropython/tree/master/ports/esp32 87 | 88 | 修改 ``lcd_binding_micropython/lcd/hal/esp32/esp32.c`` : 89 | 90 | .. code-block:: diff 91 | 92 | diff --git a/lcd/hal/esp32/esp32.c b/lcd/hal/esp32/esp32.c 93 | index b100971..907feeb 100644 94 | --- a/lcd/hal/esp32/esp32.c 95 | +++ b/lcd/hal/esp32/esp32.c 96 | @@ -119,8 +119,8 @@ inline void hal_lcd_spi_panel_deinit(mp_obj_base_t *self) 97 | 98 | for (int i = 0; i < 3; i++) { 99 | if (pins[i] != -1) { 100 | - gpio_pad_select_gpio(pins[i]); 101 | - gpio_matrix_out(pins[i], SIG_GPIO_OUT_IDX, false, false); 102 | + esp_rom_gpio_pad_select_gpio(pins[i]); 103 | + gpio_iomux_out(pins[i], SIG_GPIO_OUT_IDX, false); 104 | gpio_set_direction(pins[i], GPIO_MODE_INPUT); 105 | } 106 | } 107 | 108 | 修改 ``micropython/ports/esp32/esp32_common.cmake`` : 109 | 110 | .. code-block:: diff 111 | 112 | diff --git a/ports/esp32/esp32_common.cmake b/ports/esp32/esp32_common.cmake 113 | index 37a19316b..6be95ddf5 100644 114 | --- a/ports/esp32/esp32_common.cmake 115 | +++ b/ports/esp32/esp32_common.cmake 116 | @@ -136,6 +136,7 @@ list(APPEND IDF_COMPONENTS 117 | ulp 118 | vfs 119 | xtensa 120 | + esp_lcd 121 | ) 122 | 123 | # Register the main IDF component. 124 | 125 | 编译: 126 | 127 | .. code-block:: shell 128 | 129 | cd ports/esp32/ 130 | make USER_C_MODULES=../../../extmod/lcd_binding_micropython/lcd/micropython.cmake 131 | 132 | .. toctree:: 133 | :maxdepth: 1 134 | :hidden: 135 | 136 | self 137 | API 参考 138 | 屏幕 WiKi 139 | 版权 140 | -------------------------------------------------------------------------------- /docs/zh_CN/screen/ILI9488.rst: -------------------------------------------------------------------------------- 1 | ILI9488 2 | ======== 3 | 4 | - `MSP3520 `_ 5 | -------------------------------------------------------------------------------- /docs/zh_CN/screen/RM67162.rst: -------------------------------------------------------------------------------- 1 | RM67162 2 | ======== 3 | 4 | - `LILYGO T-DisplayS3-AMOLED `_ 5 | -------------------------------------------------------------------------------- /docs/zh_CN/screen/ST7701S.rst: -------------------------------------------------------------------------------- 1 | ST7701S 2 | ======== 3 | 4 | - `LILYGO T-RGB `_ 5 | -------------------------------------------------------------------------------- /docs/zh_CN/screen/ST7735.rst: -------------------------------------------------------------------------------- 1 | ST7735 2 | ======= 3 | 4 | - `LILYGO T-Wristband `_ 5 | -------------------------------------------------------------------------------- /docs/zh_CN/screen/ST7789.rst: -------------------------------------------------------------------------------- 1 | ST7789 2 | ======= 3 | 4 | - `LILYGO T-DisplayS3 `_ 5 | - `LILYGO T-Display `_ 6 | -------------------------------------------------------------------------------- /docs/zh_CN/screen/index.rst: -------------------------------------------------------------------------------- 1 | LCD WiKi 2 | ========= 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | 7 | ST7735.rst 8 | ST7789.rst 9 | ST7701S.rst 10 | ILI9488.rst 11 | RM67162.rst 12 | -------------------------------------------------------------------------------- /examples/color_loop/color_loop.py: -------------------------------------------------------------------------------- 1 | import tft_config 2 | import framebuf 3 | try: 4 | from tft_config import color565 5 | except: 6 | def color565(r, g, b): 7 | c = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3) 8 | return c 9 | 10 | 11 | def hsv2rgb(hue, sat, val): 12 | '''The conversion algorithm comes from https://blog.csdn.net/lly_3485390095/article/details/104570885''' 13 | C = 0.0 14 | X = 0.0 15 | Y = 0.0 16 | Z = 0.0 17 | i = 0 18 | H = float(hue) 19 | S = sat / 100.0 20 | V = val / 100.0 21 | if int(S) == 0: 22 | return int(V*255), int(V*255), int(V*255) 23 | else: 24 | H = H / 60 25 | i = int(H) 26 | C = H - i 27 | 28 | X = V * (1 - S) 29 | Y = V * (1 - S * C) 30 | Z = V * (1 -S * (1 - C)) 31 | if i == 0: 32 | return int(V * 255), int(Z * 255), int(X * 255) 33 | elif i == 1: 34 | return int(Y * 255), int(V * 255), int(X * 255) 35 | elif i == 2: 36 | return int(X * 255), int(V * 255), int(Z * 255) 37 | elif i == 3: 38 | return int(X * 255), int(Y * 255), int(V * 255) 39 | elif i == 4: 40 | return int(Z * 255), int(X * 255), int(V * 255) 41 | elif i == 5: 42 | return int(V * 255), int(X * 255), int(Y * 255) 43 | 44 | 45 | def hsv_wheel(): 46 | while True: 47 | for i in range(0, 360): 48 | yield hsv2rgb(i, 255, 100) 49 | 50 | 51 | def main(): 52 | tft = tft_config.config() 53 | width = tft.width() 54 | height = tft.height() 55 | buf = bytearray(tft.width() * 10 * 2) 56 | fbuf = framebuf.FrameBuffer(buf, tft.width(), 10, framebuf.RGB565) 57 | color = hsv_wheel() 58 | while True: 59 | r, g, b = next(color) 60 | fbuf.fill(color565(r, g, b)) 61 | for j in range(0, height, 10): 62 | tft.bitmap(0, j, width, j + 10, buf) 63 | if height % 10 != 0: 64 | tft.bitmap( 65 | 0, 66 | height - height % 10, 67 | width, 68 | height, 69 | buf 70 | ) 71 | 72 | main() 73 | -------------------------------------------------------------------------------- /examples/feathers/feathers.py: -------------------------------------------------------------------------------- 1 | import framebuf 2 | import random 3 | import math 4 | import utime 5 | import tft_config 6 | 7 | try: 8 | from tft_config import color565 9 | except: 10 | def color565(r, g, b): 11 | c = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3) 12 | return c 13 | 14 | def between(left, right, along): 15 | """returns a point along the curve from left to right""" 16 | dist = (1 - math.cos(along * math.pi)) / 2 17 | return left * (1 - dist) + right * dist 18 | 19 | def color_wheel(position): 20 | """returns a 565 color from the given position of the color wheel""" 21 | position = (255 - position) % 255 22 | 23 | if position < 85: 24 | return color565(255 - position * 3, 0, position * 3) 25 | 26 | if position < 170: 27 | position -= 85 28 | return color565(0, position * 3, 255 - position * 3) 29 | 30 | position -= 170 31 | return color565(position * 3, 255 - position * 3, 0) 32 | 33 | def main(): 34 | ''' 35 | The big show! 36 | ''' 37 | tft = tft_config.config() 38 | tft.rotation(1) 39 | buf = bytearray(1 * tft.height() * 2) 40 | fbuf = framebuf.FrameBuffer(buf, 1, tft.height(), framebuf.RGB565) 41 | height = tft.height() # height of display in pixels 42 | width = tft.width() # width if display in pixels 43 | 44 | tfa = tft_config.TFA # top free area when scrolling 45 | bfa = tft_config.BFA # bottom free area when scrolling 46 | 47 | scroll = 0 # scroll position 48 | wheel = 0 # color wheel position 49 | 50 | tft.vscroll_area(tfa, width, bfa) # set scroll area 51 | tft.vscroll_start(scroll + tfa) # set scroll position 52 | fbuf.fill(color565(0, 0, 0)) 53 | for i in range(0, tft.width()): 54 | tft.bitmap(i, 0, i + 1, tft.height(), buf) 55 | 56 | half = (height >> 1) - 1 # half the height of the dislay 57 | interval = 0 # steps between new points 58 | increment = 0 # increment per step 59 | counter = 1 # step counter, overflow to start 60 | current_y = 0 # current_y value (right point) 61 | last_y = 0 # last_y value (left point) 62 | 63 | # segment offsets 64 | x_offsets = [x * (width // 8) -1 for x in range(2,9)] 65 | 66 | while True: 67 | # when the counter exceeds the interval, save current_y to last_y, 68 | # choose a new random value for current_y between 0 and 1/2 the 69 | # height of the display, choose a new random interval then reset 70 | # the counter to 0 71 | 72 | if counter > interval: 73 | last_y = current_y 74 | current_y = random.randint(0, half) 75 | counter = 0 76 | interval = random.randint(10, 100) 77 | increment = 1 / interval 78 | 79 | # clear the first column of the display and scroll it 80 | fbuf.fill(color565(0, 0, 0)) 81 | tft.bitmap(scroll, 0, scroll + 1, height, buf) 82 | tft.vscroll_start(scroll + tfa, False) 83 | 84 | # get the next point between last_y and current_y 85 | tween = int(between(last_y, current_y, counter * increment)) 86 | 87 | # draw mirrored pixels across the display at the offsets using the color_wheel effect 88 | for i, x_offset in enumerate(x_offsets): 89 | c = color_wheel(wheel+(i<<2)).to_bytes(2, 'little') 90 | tft.bitmap( 91 | (scroll + x_offset) % width, 92 | half + tween, 93 | ((scroll + x_offset) % width) + 1, 94 | half + tween + 1, 95 | c 96 | ) 97 | tft.bitmap( 98 | (scroll + x_offset) % width, 99 | half - tween, 100 | ((scroll + x_offset) % width) + 1, 101 | half - tween + 1, 102 | c 103 | ) 104 | 105 | # increment scroll, counter, and wheel 106 | scroll = (scroll + 1) % width 107 | wheel = (wheel + 1) % 256 108 | counter += 1 109 | 110 | # pause to slow down scrolling 111 | # utime.sleep(0.01) 112 | 113 | main() 114 | -------------------------------------------------------------------------------- /examples/framebuf/use_framebuf.py: -------------------------------------------------------------------------------- 1 | import tft_config 2 | import time 3 | import framebuf 4 | try: 5 | from tft_config import color565 6 | except: 7 | def color565(r, g, b): 8 | c = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3) 9 | return c 10 | 11 | 12 | def render(tft, x, y, w, h, buf): 13 | for i in range(0, h, 10): 14 | tft.bitmap(0, i, w, i + 10, buf) 15 | if h % 10 != 0: 16 | tft.bitmap(0, h - h % 10, w, h, buf) 17 | 18 | 19 | def main(): 20 | tft = tft_config.config() 21 | width = tft.width() 22 | height = tft.height() 23 | buf = bytearray(width * 10 * 2) 24 | fbuf = framebuf.FrameBuffer(buf, width, 10, framebuf.RGB565) 25 | 26 | while True: 27 | fbuf.fill(color565(255, 0, 0)) 28 | render(tft, 0, 0,width, height, buf) 29 | time.sleep(0.5) 30 | 31 | fbuf.fill(color565(0, 255, 0)) 32 | render(tft, 0, 0, width, height, buf) 33 | time.sleep(0.5) 34 | 35 | fbuf.fill(color565(0, 0, 255)) 36 | render(tft, 0, 0, width, height, buf) 37 | time.sleep(0.5) 38 | 39 | 40 | main() 41 | 42 | -------------------------------------------------------------------------------- /examples/image_bitmap/image_bitmap.py: -------------------------------------------------------------------------------- 1 | import tft_config 2 | import logo 3 | import gc 4 | import time 5 | 6 | def main(): 7 | tft = tft_config.config() 8 | tft.bitmap(0, 0, logo.WIDTH, logo.HEIGHT, logo.BITMAP) 9 | time.sleep(0.1) 10 | del tft 11 | 12 | gc.enable() 13 | main() 14 | gc.collect() -------------------------------------------------------------------------------- /examples/image_bitmap/logo.mpy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lbuque/lcd_binding_micropython/4291a76331e38fa5c468258e0f5a41306c439d0a/examples/image_bitmap/logo.mpy -------------------------------------------------------------------------------- /examples/scroll/scroll.py: -------------------------------------------------------------------------------- 1 | """ 2 | scroll.py 3 | Smoothly scroll all characters of a font up the display. 4 | Fonts heights must be even multiples of the screen height 5 | (i.e. 8 or 16 pixels high). 6 | 7 | This example is from the following code: 8 | 9 | https://github.com/russhughes/st7789_mpy/blob/master/examples/scroll.py 10 | """ 11 | 12 | import utime 13 | import tft_config 14 | import framebuf 15 | 16 | def cycle(p): 17 | try: 18 | len(p) 19 | except TypeError: 20 | cache = [] 21 | for i in p: 22 | yield i 23 | cache.append(i) 24 | p = cache 25 | while p: 26 | yield from p 27 | 28 | def main(): 29 | colors = cycle([0xe000, 0xece0, 0xe7e0, 0x5e0, 0x00d3, 0x7030]) 30 | # colors = cycle([0x00e0, 0xe0ec, 0xe0e7, 0x005e, 0xd300, 0x3070]) 31 | foreground = next(colors) 32 | background = 0x0000 33 | 34 | tft = tft_config.config() 35 | tft.rotation(0) 36 | 37 | '''The font height of the framebuf is 8 pixels.''' 38 | font_height = const(8) 39 | 40 | buf = bytearray(tft.width() * font_height * 2) 41 | fbuf = framebuf.FrameBuffer(buf, tft.width(), font_height, framebuf.RGB565) 42 | 43 | fbuf.fill(background) 44 | for i in range(0, tft.height(), font_height): 45 | tft.bitmap(0, i, tft.width(), i + font_height, buf) 46 | 47 | width = tft.width() 48 | height = tft.height() 49 | last_line = height - font_height 50 | 51 | tfa = tft_config.TFA # top free area 52 | bfa = tft_config.BFA # bottom free area 53 | 54 | tft.vscroll_area(tfa, height, bfa) 55 | 56 | scroll = 0 57 | character = 0x20 58 | 59 | while True: 60 | '''clear top line before scrolling off display''' 61 | # fbuf.fill_rect(0, 0, width, 1, background) 62 | # tft.bitmap(0, scroll, width, scroll + 1, buf) 63 | 64 | '''Write new line when we have scrolled the height of a character''' 65 | if scroll % font_height == 0: 66 | # line = (height - scroll) % height 67 | line = (scroll + last_line) % height 68 | fbuf.fill(background) 69 | '''write character hex value as a string''' 70 | fbuf.text( 71 | '0x{:02x} {}'.format(character, chr(character)), 72 | 16, 73 | 0, 74 | foreground 75 | ) 76 | 77 | '''write character using a integer (could be > 0x7f)''' 78 | tft.bitmap(0, line, width, line + font_height, buf) 79 | 80 | '''change color for next line''' 81 | foreground = next(colors) 82 | 83 | '''next character with rollover at 256''' 84 | character += 1 85 | if character > 0x7f: 86 | character = 0x20 87 | 88 | '''scroll the screen up 1 row''' 89 | tft.vscroll_start(scroll + tfa, False) 90 | scroll += 1 91 | scroll %= height 92 | 93 | '''!!! Scrolling too fast can make you lose sight of things.''' 94 | utime.sleep(0.01) 95 | 96 | main() 97 | -------------------------------------------------------------------------------- /examples/tft_config/Air10x_LCD/README.md: -------------------------------------------------------------------------------- 1 | https://wiki.luatos.com/peripherals/lcd_air10x/index.html 2 | -------------------------------------------------------------------------------- /examples/tft_config/Air10x_LCD/tft_config.py: -------------------------------------------------------------------------------- 1 | from machine import Pin, SPI, SoftSPI 2 | import lcd 3 | 4 | TFA = const(1) 5 | BFA = const(1) 6 | 7 | # init_cmd 8 | # cmd(int) args(bytes) delay(ms) 9 | _init_cmd = ( 10 | (0x11, b'', 120), 11 | 12 | (0x20, b'', 0), # lcd_inv_off如果颜色错了就用0x21 13 | 14 | (0xB1, b'\x05\x3A\x3A', 0), 15 | 16 | (0xB2, b'\x05\x3A\x3A', 0), 17 | 18 | (0xB3, b'\x05\x3A\x3A\x05\x3A\x3A', 0), 19 | 20 | (0xB4, b'\x03', 0), # Dotinversion 21 | 22 | (0xC0, b'\x62\x02\x04', 0), 23 | 24 | (0xC1, b'\xC0', 0), 25 | 26 | (0xC2, b'\x0D\x00', 0), 27 | 28 | (0xC3, b'\x8D\x6A', 0), 29 | 30 | (0xC4, b'\x8D\xEE', 0), 31 | 32 | (0xC5, b'\x0E', 0), # VCOM 33 | 34 | (0xE0, b'\x10\x0E\x02\x03\x0E\x07\x02\x07\x0A\x12\x27\x37\x00\x0D\x0E\x10', 0), 35 | 36 | (0xE1, b'\x10\x0E\x03\x03\x0F\x06\x02\x08\x0A\x13\x26\x36\x00\x0D\x0E\x10', 0), 37 | 38 | (0x3A, b'\x05', 0), 39 | 40 | (0x36, b'\x78', 0), # direction 41 | 42 | (0x29, b'', 0), 43 | ) 44 | 45 | def config(): 46 | hspi = SPI(2, sck=Pin(18), mosi=Pin(17), miso=None) 47 | # hspi = SoftSPI(baudrate=80 * 1000* 1000, polarity=0, phase=0, sck=Pin(14), mosi=Pin(13), miso=Pin(12)) 48 | panel = lcd.SPIPanel(spi=hspi, dc=Pin(15), cs=Pin(14), pclk=60000000, width=80, height=160) 49 | st = lcd.ST7735(panel, reset=Pin(16), backlight=Pin(13), color_space=lcd.BGR) 50 | st.backlight_on() 51 | st.reset() 52 | # st.custom_init(_init_cmd) 53 | st.init() 54 | st.invert_color(False) 55 | st.rotation(0, ( 56 | (0x00, 80, 160, 24, 0), 57 | (0x60, 160, 80, 0, 24), 58 | (0xC0, 80, 160, 24, 0), 59 | (0xA0, 160, 80, 0, 24) 60 | ) 61 | ) 62 | return st 63 | 64 | 65 | def color565(r, g, b): 66 | c = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3) 67 | c = (c >> 8) | (c << 8) & 0xFFFF 68 | return c 69 | -------------------------------------------------------------------------------- /examples/tft_config/ili9488/README.md: -------------------------------------------------------------------------------- 1 | lcd: http://www.lcdwiki.com/zh/3.5inch_SPI_Module_ILI9488_SKU:MSP3520#.E5.B8.B8.E7.94.A8.E8.BD.AF.E4.BB.B6 -------------------------------------------------------------------------------- /examples/tft_config/ili9488/image2lcd_setting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lbuque/lcd_binding_micropython/4291a76331e38fa5c468258e0f5a41306c439d0a/examples/tft_config/ili9488/image2lcd_setting.png -------------------------------------------------------------------------------- /examples/tft_config/ili9488/tft_config.py: -------------------------------------------------------------------------------- 1 | from machine import Pin, SPI 2 | import lcd 3 | 4 | TFA = const(0) 5 | BFA = const(0) 6 | 7 | def config(): 8 | hspi = SPI(2, sck=Pin(19), mosi=Pin(23), miso=None) 9 | panel = lcd.SPIPanel(spi=hspi, dc=Pin(21), cs=Pin(22), pclk=60 * 1000 * 1000, width=320, height=480) 10 | ili = lcd.ILI9488(panel, reset=Pin(18), backlight=Pin(5), color_space=lcd.ILI9488.BGR, bpp=18) 11 | ili.backlight_on() 12 | ili.reset() 13 | ili.init() 14 | ili.invert_color(False) 15 | return ili 16 | 17 | 18 | def color565(r, g, b): 19 | c = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3) 20 | return c 21 | -------------------------------------------------------------------------------- /examples/tft_config/t-display/tft_config.py: -------------------------------------------------------------------------------- 1 | from machine import Pin, SPI 2 | import lcd 3 | 4 | TFA = const(40) 5 | BFA = const(40) 6 | 7 | def config(): 8 | hspi = SPI(2, sck=Pin(18), mosi=Pin(19), miso=None) 9 | panel = lcd.SPIPanel(spi=hspi, dc=Pin(16), cs=Pin(5), pclk=60000000, width=135, height=240) 10 | st = lcd.ST7789(panel, reset=Pin(23), backlight=Pin(4)) 11 | st.backlight_on() 12 | st.reset() 13 | st.init() 14 | st.invert_color(True) 15 | return st 16 | 17 | 18 | def color565(r, g, b): 19 | c = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3) 20 | return c 21 | -------------------------------------------------------------------------------- /examples/tft_config/t-displays3-amoled/tft_config.py: -------------------------------------------------------------------------------- 1 | import lcd 2 | from machine import Pin, SPI 3 | 4 | rm67162_spi_init = ( 5 | (0xFE, b'\x00', 0), # PAGE 6 | (0x36, b'\x00', 0), # Scan Direction Control 7 | (0x3A, b'\x75', 0), # Interface Pixel Format 16bit/pixel 8 | (0x51, b'\x00', 0), # Write Display Brightness MAX_VAL=0XFF 9 | (0x11, b'\x00', 120), # Sleep Out 10 | (0x29, b'\x00', 120), # Display on 11 | (0x51, b'\xD0', 0), # Write Display Brightness MAX_VAL=0XFF 12 | ) 13 | 14 | rm67162_qspi_init = ( 15 | (0x11, b'\x00', 120), # Sleep Out 16 | (0x3A, b'\x55', 0), # Interface Pixel Format 16bit/pixel 17 | (0x51, b'\x00', 0), # Write Display Brightness MAX_VAL=0XFF 18 | (0x29, b'\x00', 120), # Display on 19 | (0x51, b'\xD0', 0), # Write Display Brightness MAX_VAL=0XFF 20 | ) 21 | 22 | 23 | def config(): 24 | hspi = SPI(2, sck=Pin(47), mosi=None, miso=None, polarity=0, phase=0) 25 | panel = lcd.QSPIPanel( 26 | spi=hspi, 27 | data=(Pin(18), Pin(7), Pin(48), Pin(5)), 28 | dc=Pin(7), 29 | cs=Pin(6), 30 | pclk=80 * 1000 * 1000, 31 | width=240, 32 | height=536 33 | ) 34 | rm = lcd.RM67162(panel, reset=Pin(17), bpp=16) 35 | rm.reset() 36 | rm.init() 37 | # rm.custom_init(rm67162_qspi_init) 38 | rm.rotation(0) 39 | rm.backlight_on() 40 | return rm 41 | 42 | 43 | def color565(r, g, b): 44 | c = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3) 45 | return (c >> 8) | (c << 8) 46 | -------------------------------------------------------------------------------- /examples/tft_config/t-displays3/tft_config.py: -------------------------------------------------------------------------------- 1 | import lcd 2 | from machine import Pin 3 | 4 | TFA = const(0) 5 | BFA = const(0) 6 | 7 | def config(): 8 | i8080 = lcd.I8080(data=(Pin(39), Pin(40), Pin(41), Pin(42), Pin(45), Pin(46), Pin(47), Pin(48)), 9 | dc=Pin(7), 10 | write=Pin(8), 11 | read=Pin(9), 12 | cs=Pin(6), 13 | pclk=4 * 1000 * 1000, 14 | width=320, 15 | height=170, 16 | # swap_color_bytes=True, 17 | cmd_bits=8, 18 | param_bits=8) 19 | st = lcd.ST7789(i8080, reset=Pin(5), backlight=Pin(38)) 20 | st.reset() 21 | st.init() 22 | st.invert_color(True) 23 | st.rotation(0) 24 | st.backlight_on() 25 | return st 26 | 27 | 28 | def color565(r, g, b): 29 | c = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3) 30 | return (c >> 8) | (c << 8) 31 | 32 | -------------------------------------------------------------------------------- /examples/tft_config/t-rgb/tft_config.py: -------------------------------------------------------------------------------- 1 | import machine 2 | import xl9535 3 | import time 4 | from collections import namedtuple 5 | import lcd 6 | import gc 7 | 8 | __TP_RES_PIN = const(1) 9 | __PWR_EN_PIN = const(2) 10 | __LCD_CS_PIN = const(3) 11 | __LCD_SDA_PIN = const(4) 12 | __LCD_CLK_PIN = const(5) 13 | __LCD_RST_PIN = const(6) 14 | __SD_CS_PIN = const(7) 15 | 16 | InitData = namedtuple("InitData", ["cmd", "data", "delay"]) 17 | 18 | st_init_cmds = [ 19 | InitData(cmd=0xFF, data=b'\x77\x01\x00\x00\x10', delay=0), 20 | InitData(cmd=0xC0, data=b'\x3b\x00', delay=0), 21 | InitData(cmd=0xC1, data=b'\x0b\x02', delay=0), 22 | InitData(cmd=0xC2, data=b'\x07\x02', delay=0), 23 | InitData(cmd=0xCC, data=b'\x10', delay=0), 24 | InitData(cmd=0xCD, data=b'\x08', delay=0), # 用565时屏蔽 666打开 25 | InitData(cmd=0xb0, data=b'\x00\x11\x16\x0e\x11\x06\x05\x09\x08\x21\x06\x13\x10\x29\x31\x18', delay=0), 26 | InitData(cmd=0xb1, data=b'\x00\x11\x16\x0e\x11\x07\x05\x09\x09\x21\x05\x13\x11\x2a\x31\x18', delay=0), 27 | InitData(cmd=0xFF, data=b'\x77\x01\x00\x00\x11', delay=0), 28 | InitData(cmd=0xb0, data=b'\x6d', delay=0), 29 | InitData(cmd=0xb1, data=b'\x37', delay=0), 30 | InitData(cmd=0xb2, data=b'\x81', delay=0), 31 | InitData(cmd=0xb3, data=b'\x80', delay=0), 32 | InitData(cmd=0xb5, data=b'\x43', delay=0), 33 | InitData(cmd=0xb7, data=b'\x85', delay=0), 34 | InitData(cmd=0xb8, data=b'\x20', delay=0), 35 | InitData(cmd=0xc1, data=b'\x78', delay=0), 36 | InitData(cmd=0xc2, data=b'\x78', delay=0), 37 | InitData(cmd=0xc3, data=b'\x8c', delay=0), 38 | InitData(cmd=0xd0, data=b'\x88', delay=0), 39 | InitData(cmd=0xe0, data=b'\x00\x00\x02', delay=0), 40 | InitData(cmd=0xe1, data=b'\x03\xa0\x00\x00\x04\xa0\x00\x00\x00\x20\x20', delay=0), 41 | InitData(cmd=0xe2, data=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', delay=0), 42 | InitData(cmd=0xe3, data=b'\x00\x00\x11\x00', delay=0), 43 | InitData(cmd=0xe4, data=b'\x22\x00', delay=0), 44 | InitData(cmd=0xe5, data=b'\x05\xec\xa0\xa0\x07\xee\xa0\xa0\x00\x00\x00\x00\x00\x00\x00\x00', delay=0), 45 | InitData(cmd=0xe6, data=b'\x00\x00\x11\x00', delay=0), 46 | InitData(cmd=0xe7, data=b'\x22\x00', delay=0), 47 | InitData(cmd=0xe8, data=b'\x06\xed\xa0\xa0\x08\xef\xa0\xa0\x00\x00\x00\x00\x00\x00\x00\x00', delay=0), 48 | InitData(cmd=0xeb, data=b'\x00\x00\x40\x40\x00\x00\x00', delay=0), 49 | InitData(cmd=0xed, data=b'\xff\xff\xff\xba\x0a\xbf\x45\xff\xff\x54\xfb\xa0\xab\xff\xff\xff', delay=0), 50 | InitData(cmd=0xef, data=b'\x10\x0d\x04\x08\x3f\x1f', delay=0), 51 | InitData(cmd=0xFF, data=b'\x77\x01\x00\x00\x13', delay=0), 52 | InitData(cmd=0xef, data=b'\x08', delay=0), 53 | InitData(cmd=0xFF, data=b'\x77\x01\x00\x00\x00', delay=0), 54 | InitData(cmd=0x36, data=b'\x08', delay=0), 55 | InitData(cmd=0x3a, data=b'\x66', delay=0), 56 | InitData(cmd=0x11, data=b'\x00', delay=100), 57 | # InitData(cmd=0xFF, data=b'\x77\x01\x00\x00\x12', delay=0), 58 | # InitData(cmd=0xd1, data=b'\x81', delay=0), 59 | # InitData(cmd=0xd2, data=b'\x06', delay=0), 60 | InitData(cmd=0x29, data=b'\x00', delay=100) 61 | ] 62 | 63 | 64 | def __lcd_send_data(xl, data): 65 | for _ in range(8): 66 | if (data & 0x80): 67 | xl.digitalWrite(__LCD_SDA_PIN, 1); 68 | else: 69 | xl.digitalWrite(__LCD_SDA_PIN, 0); 70 | data <<= 1; 71 | xl.digitalWrite(__LCD_CLK_PIN, 0); 72 | xl.digitalWrite(__LCD_CLK_PIN, 1); 73 | 74 | def __lcd_cmd(xl, cmd): 75 | xl.digitalWrite(__LCD_CS_PIN, 0) 76 | xl.digitalWrite(__LCD_SDA_PIN, 0) 77 | xl.digitalWrite(__LCD_CLK_PIN, 0) 78 | xl.digitalWrite(__LCD_CLK_PIN, 1) 79 | __lcd_send_data(xl, cmd) 80 | xl.digitalWrite(__LCD_CS_PIN, 1) 81 | 82 | def __lcd_data(xl, data): 83 | for i in range(len(data)): 84 | xl.digitalWrite(__LCD_CS_PIN, 0) 85 | xl.digitalWrite(__LCD_SDA_PIN, 1) 86 | xl.digitalWrite(__LCD_CLK_PIN, 0) 87 | xl.digitalWrite(__LCD_CLK_PIN, 1) 88 | __lcd_send_data(xl, data[i]) 89 | xl.digitalWrite(__LCD_CS_PIN, 1) 90 | 91 | def tft_init(xl): 92 | xl.digitalWrite(__LCD_CS_PIN, 1) 93 | xl.digitalWrite(__LCD_SDA_PIN, 1) 94 | xl.digitalWrite(__LCD_CLK_PIN, 1) 95 | 96 | # Reset the display 97 | xl.digitalWrite(__LCD_RST_PIN, 1) 98 | time.sleep(0.2) 99 | xl.digitalWrite(__LCD_RST_PIN, 0) 100 | time.sleep(0.2) 101 | xl.digitalWrite(__LCD_RST_PIN, 1) 102 | time.sleep(0.2) 103 | for i in st_init_cmds: 104 | __lcd_cmd(xl, i.cmd) 105 | __lcd_data(xl, i.data) 106 | if i.delay != 0: 107 | time.sleep(0.1) 108 | # print("Register setup complete") 109 | 110 | 111 | def config(): 112 | i2c = machine.I2C(0, scl=machine.Pin(48), sda=machine.Pin(8)) 113 | xl = xl9535.XL9535(i2c) 114 | pin = (1 << __PWR_EN_PIN) | \ 115 | (1 << __LCD_CS_PIN) | \ 116 | (1 << __TP_RES_PIN) | \ 117 | (1 << __LCD_SDA_PIN) | \ 118 | (1 << __LCD_CLK_PIN) | \ 119 | (1 << __LCD_RST_PIN) | \ 120 | (1 << __SD_CS_PIN) 121 | xl.pinMode8(0, pin, xl.OUT) 122 | xl.digitalWrite(__PWR_EN_PIN, 1) 123 | tft_init(xl) 124 | del i2c 125 | del xl 126 | gc.collect() 127 | tft = lcd.DPI( 128 | data = ( 129 | machine.Pin(7), \ 130 | machine.Pin(6), \ 131 | machine.Pin(5), \ 132 | machine.Pin(3), \ 133 | machine.Pin(2), \ 134 | machine.Pin(14), \ 135 | machine.Pin(13), \ 136 | machine.Pin(12), \ 137 | machine.Pin(11), \ 138 | machine.Pin(10), \ 139 | machine.Pin(9), \ 140 | machine.Pin(21), \ 141 | machine.Pin(18), \ 142 | machine.Pin(17), \ 143 | machine.Pin(16), \ 144 | machine.Pin(15), \ 145 | ), \ 146 | hsync = machine.Pin(47), \ 147 | vsync = machine.Pin(41), \ 148 | de = machine.Pin(45), \ 149 | pclk_pin = machine.Pin(42), \ 150 | timings = (1, 30, 50, 1, 30, 20), \ 151 | backlight = machine.Pin(46), \ 152 | pclk = 10 * 1000 * 1000, \ 153 | width = 480, \ 154 | height = 480 155 | ) 156 | tft.backlight_on() 157 | return tft 158 | 159 | 160 | def color565(r, g, b): 161 | c = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3) 162 | return c 163 | -------------------------------------------------------------------------------- /examples/tft_config/t-rgb/xl9535.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | __XL9535_IIC_ADDRESS = const(0X20) 4 | 5 | __XL9535_INPUT_PORT_0_REG = const(0X00) 6 | __XL9535_INPUT_PORT_1_REG = const(0X01) 7 | __XL9535_OUTPUT_PORT_0_REG = const(0X02) 8 | __XL9535_OUTPUT_PORT_1_REG = const(0X03) 9 | __XL9535_INVERSION_PORT_0_REG = const(0X04) 10 | __XL9535_INVERSION_PORT_1_REG = const(0X05) 11 | __XL9535_CONFIG_PORT_0_REG = const(0X06) 12 | __XL9535_CONFIG_PORT_1_REG = const(0X07) 13 | 14 | 15 | class XL9535(): 16 | OUT = const(3) 17 | IN = const(1) 18 | def __init__(self, bus: I2C, a0: bool = False, a1: bool = False, a2: bool = False): 19 | self.__bus = bus 20 | self.__address = __XL9535_IIC_ADDRESS | \ 21 | (int(a2) << 3) | \ 22 | (int(a1) << 2) | \ 23 | (int(a0) << 1) 24 | self.__buf = bytearray(1) 25 | try: 26 | self.__bus.scan().index(self.__address) 27 | except: 28 | raise Exception("XL9535 not found") 29 | 30 | def pinMode(self, pin, mode): 31 | if pin > 7: 32 | self.__bus.readfrom_mem_into(self.__address, 33 | __XL9535_CONFIG_PORT_1_REG, 34 | self.__buf) 35 | if mode == self.OUT: 36 | self.__buf[0] = self.__buf[0] & (~(1 << (pin - 10))) 37 | else: 38 | self.__buf[0] = self.__buf[0] | (1 << (pin - 10)) 39 | self.__bus.writeto_mem(self.__address, 40 | __XL9535_CONFIG_PORT_1_REG, 41 | self.__buf) 42 | else: 43 | self.__bus.readfrom_mem_into(self.__address, 44 | __XL9535_CONFIG_PORT_0_REG, 45 | self.__buf) 46 | if mode == self.OUT: 47 | self.__buf[0] = self.__buf[0] & (~(1 << pin)) 48 | else: 49 | self.__buf[0] = self.__buf[0] | (1 << pin) 50 | self.__bus.writeto_mem(self.__address, 51 | __XL9535_CONFIG_PORT_0_REG, 52 | self.__buf) 53 | 54 | def pinMode8(self, port, pin, mode): 55 | self.__buf[0] = pin if mode != self.OUT else ~pin 56 | if port: 57 | self.__bus.writeto_mem(self.__address, 58 | __XL9535_CONFIG_PORT_1_REG, 59 | self.__buf) 60 | else: 61 | self.__bus.writeto_mem(self.__address, 62 | __XL9535_CONFIG_PORT_0_REG, 63 | self.__buf) 64 | 65 | def digitalWrite(self, pin, val): 66 | if pin > 7: 67 | self.__bus.readfrom_mem_into(self.__address, 68 | __XL9535_CONFIG_PORT_1_REG, 69 | self.__buf) 70 | self.__buf[0] = self.__buf[0] & (~(1 << (pin - 10))) 71 | self.__buf[0] = self.__buf[0] | val << (pin - 10) 72 | self.__bus.writeto_mem(self.__address, 73 | __XL9535_CONFIG_PORT_1_REG, 74 | bytes(self.__buf)) 75 | else: 76 | self.__bus.readfrom_mem_into(self.__address, 77 | __XL9535_OUTPUT_PORT_0_REG, 78 | self.__buf) 79 | self.__buf[0] = self.__buf[0] & (~(1 << pin)) 80 | self.__buf[0] = self.__buf[0] | val << pin 81 | self.__bus.writeto_mem(self.__address, 82 | __XL9535_OUTPUT_PORT_0_REG, 83 | self.__buf) 84 | -------------------------------------------------------------------------------- /examples/tft_config/t-wristband/image2lcd_setting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lbuque/lcd_binding_micropython/4291a76331e38fa5c468258e0f5a41306c439d0a/examples/tft_config/t-wristband/image2lcd_setting.png -------------------------------------------------------------------------------- /examples/tft_config/t-wristband/tft_config.py: -------------------------------------------------------------------------------- 1 | from machine import Pin, SPI, SoftSPI 2 | import time 3 | import lcd 4 | 5 | TFA = const(1) 6 | BFA = const(1) 7 | 8 | # waveshare 9 | # cmd(int) args(bytes) delay(ms) 10 | init_waveshare = ( 11 | (0x11, b'', 120), 12 | (0x21, b'', 0), 13 | (0xB1, b'\x05\x3A\x3A', 0), 14 | (0xB2, b'\x05\x3A\x3A', 0), 15 | (0xB3, b'\x05\x3A\x3A\x05\x3A\x3A', 0), 16 | (0xB4, b'\x03', 0), 17 | (0xC0, b'\x62\x02\x04', 0), 18 | (0xC1, b'\xC0', 0), 19 | (0xC2, b'\x0D\x00', 0), 20 | (0xC3, b'\x8D\x6A', 0), 21 | (0xC4, b'\x8D\xEE', 0), 22 | (0xC5, b'\x0E', 0), 23 | (0xE0, b'\x10\x0E\x02\x03\x0E\x07\x02\x07\x0A\x12\x27\x37\x00\x0D\x0E\x10', 0), 24 | (0xE1, b'\x10\x0E\x03\x03\x0F\x06\x02\x08\x0A\x13\x26\x36\x00\x0D\x0E\x10', 0), 25 | (0x3A, b'\x05', 0), 26 | (0x36, b'\xA8', 0), 27 | (0x29, b'', 0) 28 | ) 29 | 30 | 31 | # tft_espi 1 32 | # cmd(int) args(bytes) delay(ms) 33 | init_tft_espi_1 = ( 34 | (0x11, b'', 500), 35 | (0xB1, b'\x01\x2C\x2D', 0), 36 | (0xB2, b'\x01\x2C\x2D', 0), 37 | (0xB3, b'\x01\x2C\x2D\x01\x2C\x2D', 0), 38 | (0xB4, b'\x07', 0), 39 | (0xC0, b'\xA2\x02\x84', 0), 40 | (0xC1, b'\xC5', 0), 41 | (0xC2, b'\x0A\x00', 0), 42 | (0xC3, b'\x8A\x2A', 0), 43 | (0xC4, b'\x8A\xEE', 0), 44 | (0xC5, b'\x0E', 0), 45 | (0x20, b'', 0), 46 | (0x36, b'\xC8', 0), 47 | (0x3A, b'\x05', 0), 48 | (0x2A, b'\x00\x02\x00\x81', 0), 49 | (0x2B, b'\x00\x01\x00\xA0', 0), 50 | (0xE0, b'\x02\x1c\x07\x12\x37\x32\x29\x2d\x29\x25\x2B\x39\x00\x01\x03\x10', 0), 51 | (0xE1, b'\x03\x1d\x07\x06\x2E\x2C\x29\x2D\x2E\x2E\x37\x3F\x00\x00\x02\x10', 0), 52 | (0x13, b'', 100), 53 | (0x29, b'', 100) 54 | ) 55 | 56 | # tft_espi 2 57 | # cmd(int) args(bytes) delay(ms) 58 | init_tft_espi_2 = ( 59 | (0x11, b'', 500), 60 | (0xB1, b'\x01\x2C\x2D', 0), 61 | (0xB2, b'\x01\x2C\x2D', 0), 62 | (0xB3, b'\x01\x2C\x2D\x01\x2C\x2D', 0), 63 | (0xB4, b'\x07', 0), 64 | (0xC0, b'\xA2\x02\x84', 0), 65 | (0xC1, b'\xC5', 0), 66 | (0xC2, b'\x0A\x00', 0), 67 | (0xC3, b'\x8A\x2A', 0), 68 | (0xC4, b'\x8A\xEE', 0), 69 | (0xC5, b'\x0E', 0), 70 | (0x20, b'', 0), 71 | (0x36, b'\xC8', 0), 72 | (0x3A, b'\x05', 0), 73 | (0x2A, b'\x00\x02\x00\x81', 0), 74 | (0x2B, b'\x00\x01\x00\xA0', 0), 75 | (0xE0, b'\x02\x1c\x07\x12\x37\x32\x29\x2d\x29\x25\x2B\x39\x00\x01\x03\x10', 0), 76 | (0xE1, b'\x03\x1d\x07\x06\x2E\x2C\x29\x2D\x2E\x2E\x37\x3F\x00\x00\x02\x10', 0), 77 | (0x13, b'', 100), 78 | (0x29, b'', 100) 79 | ) 80 | 81 | def config(): 82 | hspi = SPI(2, sck=Pin(18), mosi=Pin(19), miso=None) 83 | # hspi = SoftSPI(baudrate=80 * 1000* 1000, polarity=0, phase=0, sck=Pin(18), mosi=Pin(19), miso=Pin(4)) 84 | panel = lcd.SPIPanel(spi=hspi, dc=Pin(23), cs=Pin(5), pclk=60000000, width=80, height=160) 85 | st = lcd.ST7735(panel, reset=Pin(26), backlight=Pin(27)) 86 | st.backlight_on() 87 | st.reset() 88 | st.custom_init(init_tft_espi_2) 89 | st.invert_color(True) 90 | st.rotation(3) 91 | return st 92 | 93 | 94 | def color565(r, g, b): 95 | c = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3) 96 | return c -------------------------------------------------------------------------------- /examples/tft_config/waveshare_0.96inch_LCD_Module/tft_config.py: -------------------------------------------------------------------------------- 1 | from machine import Pin, SPI, SoftSPI 2 | import lcd 3 | 4 | TFA = const(1) 5 | BFA = const(1) 6 | 7 | # waveshare 8 | # cmd(int) args(bytes) delay(ms) 9 | __init_waveshare = ( 10 | (0x11, b'', 120), 11 | (0x21, b'', 0), 12 | (0xB1, b'\x05\x3A\x3A', 0), 13 | (0xB2, b'\x05\x3A\x3A', 0), 14 | (0xB3, b'\x05\x3A\x3A\x05\x3A\x3A', 0), 15 | (0xB4, b'\x03', 0), 16 | (0xC0, b'\x62\x02\x04', 0), 17 | (0xC1, b'\xC0', 0), 18 | (0xC2, b'\x0D\x00', 0), 19 | (0xC3, b'\x8D\x6A', 0), 20 | (0xC4, b'\x8D\xEE', 0), 21 | (0xC5, b'\x0E', 0), 22 | (0xE0, b'\x10\x0E\x02\x03\x0E\x07\x02\x07\x0A\x12\x27\x37\x00\x0D\x0E\x10', 0), 23 | (0xE1, b'\x10\x0E\x03\x03\x0F\x06\x02\x08\x0A\x13\x26\x36\x00\x0D\x0E\x10', 0), 24 | (0x3A, b'\x05', 0), 25 | (0x36, b'\xA8', 0), 26 | (0x13, b'', 0), 27 | (0x29, b'', 0) 28 | ) 29 | 30 | 31 | def config(): 32 | hspi = SPI(2, sck=Pin(14), mosi=Pin(13), miso=None) 33 | # hspi = SoftSPI(baudrate=80 * 1000* 1000, polarity=0, phase=0, sck=Pin(14), mosi=Pin(13), miso=Pin(12)) 34 | panel = lcd.SPIPanel(spi=hspi, dc=Pin(16), cs=Pin(15), pclk=60000000, width=80, height=160) 35 | st = lcd.ST7735(panel, reset=Pin(17), backlight=Pin(18), color_space=lcd.BGR) 36 | st.backlight_on() 37 | st.reset() 38 | # st.custom_init(init_waveshare) 39 | st.init() 40 | st.invert_color(True) 41 | return st 42 | 43 | 44 | def color565(r, g, b): 45 | c = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3) 46 | return c 47 | -------------------------------------------------------------------------------- /examples/tft_config/waveshare_1.28inch_LCD_Module/tft_config.py: -------------------------------------------------------------------------------- 1 | from machine import Pin, SPI 2 | import lcd 3 | 4 | TFA = const(0) 5 | BFA = const(0) 6 | 7 | 8 | # This is the command sequence that initialises the GC9A01 driver 9 | # cmd(int) args(bytes) delay(ms) 10 | init_tft_esp = ( 11 | (0xEF, b'', 0), 12 | (0xEB, b'\x14', 0), 13 | (0xFE, b'', 0), 14 | (0xEF, b'', 0), 15 | (0xEB, b'\x14', 0), 16 | (0x84, b'\x40', 0), 17 | (0x85, b'\xFF', 0), 18 | (0x86, b'\xFF', 0), 19 | (0x87, b'\xFF', 0), 20 | (0x88, b'\x0A', 0), 21 | (0x89, b'\x21', 0), 22 | (0x8A, b'\x00', 0), 23 | (0x8B, b'\x80', 0), 24 | (0x8C, b'\x01', 0), 25 | (0x8D, b'\x01', 0), 26 | (0x8E, b'\xFF', 0), 27 | (0x8F, b'\xFF', 0), 28 | (0xB6, b'\x00\x20', 0), 29 | (0x90, b'\x08\x08\x08\x08', 0), 30 | (0xBD, b'\x06', 0), 31 | (0xBC, b'\x00', 0), 32 | (0xFF, b'\x60\x01\x04', 0), 33 | (0xC3, b'\x13\xC4\x13', 0), 34 | (0xC9, b'\x22', 0), 35 | (0xBE, b'\x11', 0), 36 | (0xE1, b'\x10\x0E', 0), 37 | (0xDF, b'\x21\x0c\x02', 0), 38 | (0xF0, b'\x45\x09\x08\x08\x26\x2A', 0), 39 | (0xF1, b'\x43\x70\x72\x36\x37\x6F', 0), 40 | (0xF2, b'\x45\x09\x08\x08\x26\x2A', 0), 41 | (0xF3, b'\x43\x70\x72\x36\x37\x6F', 0), 42 | (0xED, b'\x1B\x0B', 0), 43 | (0xAE, b'\x77', 0), 44 | (0xCD, b'\x63', 0), 45 | (0x70, b'\x07\x07\x04\x0E\x0F\x09\x07\x08\x03', 0), 46 | (0xE8, b'\x34', 0), 47 | (0x62, b'\x18\x0D\x71\xED\x70\x70\x18\x0F\x71\xEF\x70\x70', 0), 48 | (0x63, b'\x18\x11\x71\xF1\x70\x70\x18\x13\x71\xF3\x70\x70', 0), 49 | (0x64, b'\x28\x29\xF1\x01\xF1\x00\x07', 0), 50 | (0x66, b'\x3C\x00\xCD\x67\x45\x45\x10\x00\x00\x00', 0), 51 | (0x67, b'\x00\x3C\x00\x00\x00\x01\x54\x10\x32\x98', 0), 52 | (0x74, b'\x10\x85\x80\x00\x00\x4E\x00', 0), 53 | (0x98, b'\x3E\x07', 0), 54 | (0x35, b'', 0), 55 | 56 | # (0x21, b'', 0), 57 | # (0x36, b'\x08', 0), 58 | # (0x3A, b'\x05', 0), 59 | # (0x11, b'', 120), 60 | # (0x29, b'', 20), 61 | ) 62 | 63 | def config(): 64 | hspi = SPI(2, sck=Pin(14), mosi=Pin(13), miso=None) 65 | panel = lcd.SPIPanel(spi=hspi, dc=Pin(16), cs=Pin(15), pclk=60000000, width=240, height=240) 66 | st = lcd.GC9A01(panel, reset=Pin(17), backlight=Pin(18), color_space=lcd.BGR) 67 | st.backlight_on() 68 | st.reset() 69 | st.custom_init(init_tft_esp) 70 | st.init() 71 | st.invert_color(True) 72 | return st 73 | 74 | 75 | def color565(r, g, b): 76 | c = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3) 77 | return (c >> 8) | (c << 8) 78 | -------------------------------------------------------------------------------- /lcd/bus/common/lcd_panel.h: -------------------------------------------------------------------------------- 1 | #ifndef _LCD_PANEL_H_ 2 | #define _LCD_PANEL_H_ 3 | 4 | #include "py/obj.h" 5 | 6 | typedef struct _mp_lcd_panel_p_t { 7 | void (*tx_param)(mp_obj_base_t *self, int lcd_cmd, const void *param, size_t param_size); 8 | void (*tx_color)(mp_obj_base_t *self, int lcd_cmd, const void *color, size_t color_size); 9 | void (*deinit)(mp_obj_base_t *self); 10 | } mp_lcd_panel_p_t; 11 | 12 | #endif -------------------------------------------------------------------------------- /lcd/bus/dpi/dpi_panel.c: -------------------------------------------------------------------------------- 1 | #include "dpi_panel.h" 2 | 3 | #if USE_ESP_LCD 4 | #include "esp32.h" 5 | #endif 6 | 7 | #include "py/obj.h" 8 | #include "py/runtime.h" 9 | 10 | #include "mphalport.h" 11 | #include "py/gc.h" 12 | 13 | #include 14 | 15 | STATIC void mp_lcd_dpi_print(const mp_print_t *print, 16 | mp_obj_t self_in, 17 | mp_print_kind_t kind) 18 | { 19 | (void) kind; 20 | mp_lcd_dpi_obj_t *self = MP_OBJ_TO_PTR(self_in); 21 | mp_printf( 22 | print, 23 | "", 24 | self->pclk, 25 | self->width, 26 | self->height 27 | ); 28 | } 29 | 30 | 31 | mp_obj_t mp_lcd_dpi_make_new(const mp_obj_type_t *type, 32 | size_t n_args, 33 | size_t n_kw, 34 | const mp_obj_t *all_args) 35 | { 36 | enum { 37 | ARG_data, 38 | ARG_hsync, 39 | ARG_vsync, 40 | ARG_de, 41 | ARG_pclk_pin, 42 | ARG_timings, 43 | ARG_disp, 44 | ARG_backlight, 45 | ARG_pclk, 46 | ARG_width, 47 | ARG_height, 48 | }; 49 | const mp_arg_t allowed_args[] = { 50 | { MP_QSTR_data, MP_ARG_OBJ | MP_ARG_REQUIRED | MP_ARG_KW_ONLY, {.u_obj = MP_OBJ_NULL} }, 51 | { MP_QSTR_hsync, MP_ARG_OBJ | MP_ARG_REQUIRED | MP_ARG_KW_ONLY, {.u_obj = MP_OBJ_NULL} }, 52 | { MP_QSTR_vsync, MP_ARG_OBJ | MP_ARG_REQUIRED | MP_ARG_KW_ONLY, {.u_obj = MP_OBJ_NULL} }, 53 | { MP_QSTR_de, MP_ARG_OBJ | MP_ARG_REQUIRED | MP_ARG_KW_ONLY, {.u_obj = MP_OBJ_NULL} }, 54 | { MP_QSTR_pclk_pin, MP_ARG_OBJ | MP_ARG_REQUIRED | MP_ARG_KW_ONLY, {.u_obj = MP_OBJ_NULL} }, 55 | { MP_QSTR_timings, MP_ARG_OBJ | MP_ARG_REQUIRED | MP_ARG_KW_ONLY, {.u_obj = MP_OBJ_NULL} }, 56 | { MP_QSTR_disp, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_OBJ_NULL} }, 57 | { MP_QSTR_backlight, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_OBJ_NULL} }, 58 | { MP_QSTR_pclk, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 8000000 } }, 59 | { MP_QSTR_width, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 480 } }, 60 | { MP_QSTR_height, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 480 } }, 61 | 62 | }; 63 | mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; 64 | mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); 65 | 66 | // create new object 67 | mp_lcd_dpi_obj_t *self = m_new_obj(mp_lcd_dpi_obj_t); 68 | self->base.type = &mp_lcd_dpi_type; 69 | 70 | // data bus 71 | mp_obj_tuple_t *t = MP_OBJ_TO_PTR(args[ARG_data].u_obj); 72 | self->bus_width = t->len; 73 | for (size_t i = 0; i < t->len; i++) { 74 | self->databus_obj[i] = t->items[i]; 75 | } 76 | 77 | self->hsync_obj = args[ARG_hsync].u_obj; 78 | self->vsync_obj = args[ARG_vsync].u_obj; 79 | self->de_obj = args[ARG_de].u_obj; 80 | self->pclk_obj = args[ARG_pclk_pin].u_obj; 81 | 82 | // timings 83 | t = MP_OBJ_TO_PTR(args[ARG_timings].u_obj); 84 | self->timings.hsync_pulse_width = mp_obj_get_int(t->items[0]); 85 | self->timings.hsync_back_porch = mp_obj_get_int(t->items[1]); 86 | self->timings.hsync_front_porch = mp_obj_get_int(t->items[2]); 87 | self->timings.vsync_pulse_width = mp_obj_get_int(t->items[3]); 88 | self->timings.vsync_back_porch = mp_obj_get_int(t->items[4]); 89 | self->timings.vsync_front_porch = mp_obj_get_int(t->items[5]); 90 | 91 | // disp gpio 92 | self->disp_obj = args[ARG_disp].u_obj; 93 | if (self->disp_obj != MP_OBJ_NULL) { 94 | self->disp_pin = mp_hal_get_pin_obj(self->disp_obj); 95 | } else { 96 | self->disp_pin = -1; 97 | } 98 | 99 | // init backlight 100 | self->backlight = args[ARG_backlight].u_obj; 101 | if (self->backlight != MP_OBJ_NULL) { 102 | mp_hal_pin_obj_t backlight_pin = mp_hal_get_pin_obj(self->backlight); 103 | mp_hal_pin_output(backlight_pin); 104 | } 105 | 106 | self->pclk = args[ARG_pclk].u_int; 107 | self->width = args[ARG_width].u_int; 108 | self->height = args[ARG_height].u_int; 109 | 110 | hal_lcd_dpi_construct(&self->base); 111 | return MP_OBJ_FROM_PTR(self); 112 | } 113 | 114 | 115 | STATIC mp_obj_t mp_lcd_dpi_deinit(mp_obj_t self_in) 116 | { 117 | mp_lcd_dpi_obj_t *self = MP_OBJ_TO_PTR(self_in); 118 | // m_del_obj(mp_lcd_dpi_obj_t, self); 119 | hal_lcd_dpi_del(&self->base); 120 | return mp_const_none; 121 | } 122 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_lcd_dpi_deinit_obj, mp_lcd_dpi_deinit); 123 | 124 | 125 | STATIC mp_obj_t mp_lcd_dpi_reset(mp_obj_t self_in) 126 | { 127 | mp_lcd_dpi_obj_t *self = MP_OBJ_TO_PTR(self_in); 128 | 129 | hal_lcd_dpi_reset(&self->base); 130 | 131 | return mp_const_none; 132 | } 133 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_lcd_dpi_reset_obj, mp_lcd_dpi_reset); 134 | 135 | 136 | STATIC mp_obj_t mp_lcd_dpi_init(mp_obj_t self_in) 137 | { 138 | mp_lcd_dpi_obj_t *self = MP_OBJ_TO_PTR(self_in); 139 | 140 | hal_lcd_dpi_init(&self->base); 141 | 142 | return mp_const_none; 143 | } 144 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_lcd_dpi_init_obj, mp_lcd_dpi_init); 145 | 146 | 147 | STATIC mp_obj_t mp_lcd_dpi_bitmap(size_t n_args, const mp_obj_t *args_in) 148 | { 149 | mp_lcd_dpi_obj_t *self = MP_OBJ_TO_PTR(args_in[0]); 150 | mp_buffer_info_t bufinfo; 151 | mp_get_buffer_raise(args_in[5], &bufinfo, MP_BUFFER_READ); 152 | 153 | hal_lcd_dpi_bitmap( 154 | &self->base, 155 | mp_obj_get_int(args_in[1]), 156 | mp_obj_get_int(args_in[2]), 157 | mp_obj_get_int(args_in[3]), 158 | mp_obj_get_int(args_in[4]), 159 | bufinfo.buf 160 | ); 161 | 162 | return mp_const_none; 163 | } 164 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_lcd_dpi_bitmap_obj, 6, 6, mp_lcd_dpi_bitmap); 165 | 166 | 167 | STATIC mp_obj_t mp_lcd_dpi_mirror(mp_obj_t self_in, 168 | mp_obj_t mirror_x_in, 169 | mp_obj_t mirror_y_in) 170 | { 171 | mp_lcd_dpi_obj_t *self = MP_OBJ_TO_PTR(self_in); 172 | 173 | hal_lcd_dpi_mirror( 174 | &self->base, 175 | mp_obj_is_true(mirror_x_in), 176 | mp_obj_is_true(mirror_y_in) 177 | ); 178 | 179 | return mp_const_none; 180 | } 181 | STATIC MP_DEFINE_CONST_FUN_OBJ_3(mp_lcd_dpi_mirror_obj, mp_lcd_dpi_mirror); 182 | 183 | 184 | STATIC mp_obj_t mp_lcd_dpi_swap_xy(mp_obj_t self_in, mp_obj_t swap_axes_in) 185 | { 186 | mp_lcd_dpi_obj_t *self = MP_OBJ_TO_PTR(self_in); 187 | 188 | hal_lcd_dpi_swap_xy(&self->base, mp_obj_is_true(swap_axes_in)); 189 | 190 | return mp_const_none; 191 | } 192 | STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_lcd_dpi_swap_xy_obj, mp_lcd_dpi_swap_xy); 193 | 194 | 195 | STATIC mp_obj_t mp_lcd_dpi_set_gap(mp_obj_t self_in, 196 | mp_obj_t x_gap_in, 197 | mp_obj_t y_gap_in) 198 | { 199 | mp_lcd_dpi_obj_t *self = MP_OBJ_TO_PTR(self_in); 200 | 201 | hal_lcd_dpi_set_gap( 202 | &self->base, 203 | mp_obj_get_int(x_gap_in), 204 | mp_obj_get_int(y_gap_in) 205 | ); 206 | 207 | return mp_const_none; 208 | } 209 | STATIC MP_DEFINE_CONST_FUN_OBJ_3(mp_lcd_dpi_set_gap_obj, mp_lcd_dpi_set_gap); 210 | 211 | 212 | STATIC mp_obj_t mp_lcd_dpi_invert_color(mp_obj_t self_in, mp_obj_t invert_in) 213 | { 214 | mp_lcd_dpi_obj_t *self = MP_OBJ_TO_PTR(self_in); 215 | 216 | hal_lcd_dpi_invert_color(&self->base, mp_obj_is_true(invert_in)); 217 | 218 | return mp_const_none; 219 | } 220 | STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_lcd_dpi_invert_color_obj, mp_lcd_dpi_invert_color); 221 | 222 | 223 | STATIC mp_obj_t mp_lcd_dpi_disp_off(mp_obj_t self_in, mp_obj_t off_in) 224 | { 225 | mp_lcd_dpi_obj_t *self = MP_OBJ_TO_PTR(self_in); 226 | 227 | hal_lcd_dpi_disp_off(&self->base, mp_obj_is_true(off_in)); 228 | 229 | return mp_const_none; 230 | } 231 | STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_lcd_dpi_disp_off_obj, mp_lcd_dpi_disp_off); 232 | 233 | 234 | STATIC mp_obj_t mp_lcd_dpi_backlight_on(mp_obj_t self_in) 235 | { 236 | mp_lcd_dpi_obj_t *self = MP_OBJ_TO_PTR(self_in); 237 | 238 | if (self->backlight != MP_OBJ_NULL) { 239 | mp_hal_pin_obj_t backlight_pin = mp_hal_get_pin_obj(self->backlight); 240 | mp_hal_pin_write(backlight_pin, 1); 241 | mp_hal_delay_us(10 * 1000); 242 | } 243 | 244 | return mp_const_none; 245 | } 246 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_lcd_dpi_backlight_on_obj, mp_lcd_dpi_backlight_on); 247 | 248 | 249 | STATIC mp_obj_t mp_lcd_dpi_backlight_off(mp_obj_t self_in) 250 | { 251 | mp_lcd_dpi_obj_t *self = MP_OBJ_TO_PTR(self_in); 252 | 253 | if (self->backlight != MP_OBJ_NULL) { 254 | mp_hal_pin_obj_t backlight_pin = mp_hal_get_pin_obj(self->backlight); 255 | mp_hal_pin_write(backlight_pin, 0); 256 | mp_hal_delay_us(10 * 1000); 257 | } 258 | 259 | return mp_const_none; 260 | } 261 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_lcd_dpi_backlight_off_obj, mp_lcd_dpi_backlight_off); 262 | 263 | 264 | STATIC const mp_rom_map_elem_t mp_lcd_dpi_locals_dict_table[] = { 265 | { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&mp_lcd_dpi_deinit_obj) }, 266 | { MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&mp_lcd_dpi_reset_obj) }, 267 | { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&mp_lcd_dpi_init_obj) }, 268 | { MP_ROM_QSTR(MP_QSTR_bitmap), MP_ROM_PTR(&mp_lcd_dpi_bitmap_obj) }, 269 | { MP_ROM_QSTR(MP_QSTR_mirror), MP_ROM_PTR(&mp_lcd_dpi_mirror_obj) }, 270 | { MP_ROM_QSTR(MP_QSTR_swap_xy), MP_ROM_PTR(&mp_lcd_dpi_swap_xy_obj) }, 271 | { MP_ROM_QSTR(MP_QSTR_set_gap), MP_ROM_PTR(&mp_lcd_dpi_set_gap_obj) }, 272 | { MP_ROM_QSTR(MP_QSTR_invert_color), MP_ROM_PTR(&mp_lcd_dpi_invert_color_obj) }, 273 | { MP_ROM_QSTR(MP_QSTR_disp_off), MP_ROM_PTR(&mp_lcd_dpi_disp_off_obj) }, 274 | { MP_ROM_QSTR(MP_QSTR_backlight_on), MP_ROM_PTR(&mp_lcd_dpi_backlight_on_obj) }, 275 | { MP_ROM_QSTR(MP_QSTR_backlight_off), MP_ROM_PTR(&mp_lcd_dpi_backlight_off_obj) }, 276 | { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_lcd_dpi_deinit_obj) }, 277 | }; 278 | STATIC MP_DEFINE_CONST_DICT(mp_lcd_dpi_locals_dict, mp_lcd_dpi_locals_dict_table); 279 | 280 | #ifdef MP_OBJ_TYPE_GET_SLOT 281 | MP_DEFINE_CONST_OBJ_TYPE( 282 | mp_lcd_dpi_type, 283 | MP_QSTR_DPI, 284 | MP_TYPE_FLAG_NONE, 285 | print, mp_lcd_dpi_print, 286 | make_new, mp_lcd_dpi_make_new, 287 | locals_dict, (mp_obj_dict_t *)&mp_lcd_dpi_locals_dict 288 | ); 289 | #else 290 | const mp_obj_type_t mp_lcd_dpi_type = { 291 | { &mp_type_type }, 292 | .name = MP_QSTR_DPI, 293 | .print = mp_lcd_dpi_print, 294 | .make_new = mp_lcd_dpi_make_new, 295 | .locals_dict = (mp_obj_dict_t *)&mp_lcd_dpi_locals_dict, 296 | }; 297 | #endif 298 | -------------------------------------------------------------------------------- /lcd/bus/dpi/dpi_panel.h: -------------------------------------------------------------------------------- 1 | #ifndef LCD_DPI_H_ 2 | #define LCD_DPI_H_ 3 | 4 | #include "py/obj.h" 5 | #include "mphalport.h" 6 | #if USE_ESP_LCD 7 | #include "esp_lcd_panel_io.h" 8 | #endif 9 | 10 | typedef struct _mp_lcd_dpi_obj_t { 11 | mp_obj_base_t base; 12 | 13 | uint16_t width; 14 | uint16_t height; 15 | 16 | mp_obj_t databus_obj[18]; 17 | mp_obj_t hsync_obj; 18 | mp_obj_t vsync_obj; 19 | mp_obj_t de_obj; 20 | mp_obj_t pclk_obj; 21 | mp_obj_t disp_obj; 22 | mp_obj_t backlight; 23 | 24 | mp_hal_pin_obj_t databus_pins[16]; 25 | mp_hal_pin_obj_t hsync_pin; 26 | mp_hal_pin_obj_t vsync_pin; 27 | mp_hal_pin_obj_t de_pin; 28 | mp_hal_pin_obj_t pclk_pin; 29 | mp_hal_pin_obj_t disp_pin; 30 | 31 | uint32_t pclk; 32 | size_t bus_width; 33 | 34 | struct { 35 | uint32_t pclk_hz; /*!< Frequency of pixel clock */ 36 | uint32_t h_res; /*!< Horizontal resolution, i.e. the number of pixels in a line */ 37 | uint32_t v_res; /*!< Vertical resolution, i.e. the number of lines in the frame */ 38 | uint32_t hsync_pulse_width; /*!< Horizontal sync width, unit: PCLK period */ 39 | uint32_t hsync_back_porch; /*!< Horizontal back porch, number of PCLK between hsync and start of line active data */ 40 | uint32_t hsync_front_porch; /*!< Horizontal front porch, number of PCLK between the end of active data and the next hsync */ 41 | uint32_t vsync_pulse_width; /*!< Vertical sync width, unit: number of lines */ 42 | uint32_t vsync_back_porch; /*!< Vertical back porch, number of invalid lines between vsync and start of frame */ 43 | uint32_t vsync_front_porch; /*!< Vertical front porch, number of invalid lines between the end of frame and the next vsync */ 44 | struct { 45 | uint32_t hsync_idle_low: 1; /*!< The hsync signal is low in IDLE state */ 46 | uint32_t vsync_idle_low: 1; /*!< The vsync signal is low in IDLE state */ 47 | uint32_t de_idle_high: 1; /*!< The de signal is high in IDLE state */ 48 | uint32_t pclk_active_neg: 1; /*!< Whether the display data is clocked out at the falling edge of PCLK */ 49 | uint32_t pclk_idle_high: 1; /*!< The PCLK stays at high level in IDLE phase */ 50 | } flags; /*!< LCD RGB timing flags */ 51 | } timings; 52 | 53 | #if USE_ESP_LCD 54 | esp_lcd_panel_handle_t panel_handle; 55 | #endif 56 | } mp_lcd_dpi_obj_t; 57 | 58 | extern const mp_obj_type_t mp_lcd_dpi_type; 59 | 60 | #endif -------------------------------------------------------------------------------- /lcd/bus/i80/i80_panel.c: -------------------------------------------------------------------------------- 1 | #include "i80_panel.h" 2 | #include "lcd_panel.h" 3 | 4 | #if USE_ESP_LCD 5 | #include "esp32.h" 6 | #else 7 | #include "soft8080.h" 8 | #endif 9 | 10 | #include "mphalport.h" 11 | 12 | #include "py/obj.h" 13 | #include "py/runtime.h" 14 | #include "py/gc.h" 15 | 16 | #include 17 | 18 | 19 | STATIC void mp_lcd_i80_print(const mp_print_t *print, 20 | mp_obj_t self_in, 21 | mp_print_kind_t kind) 22 | { 23 | (void) kind; 24 | mp_lcd_i80_obj_t *self = MP_OBJ_TO_PTR(self_in); 25 | mp_printf( 26 | print, 27 | "", 28 | self->databus, 29 | self->dc, 30 | self->wr, 31 | self->rd, 32 | self->cs, 33 | self->width, 34 | self->height, 35 | self->cmd_bits, 36 | self->param_bits 37 | ); 38 | } 39 | 40 | 41 | STATIC mp_obj_t mp_lcd_i80_make_new(const mp_obj_type_t *type, 42 | size_t n_args, 43 | size_t n_kw, 44 | const mp_obj_t *all_args) 45 | { 46 | enum { 47 | ARG_data, 48 | ARG_dc, 49 | ARG_write, 50 | ARG_read, 51 | ARG_cs, 52 | ARG_pclk, 53 | ARG_width, 54 | ARG_height, 55 | ARG_swap_color_bytes, 56 | ARG_cmd_bits, 57 | ARG_param_bits 58 | }; 59 | const mp_arg_t make_new_args[] = { 60 | { MP_QSTR_data, MP_ARG_OBJ | MP_ARG_KW_ONLY | MP_ARG_REQUIRED }, 61 | { MP_QSTR_dc, MP_ARG_OBJ | MP_ARG_KW_ONLY | MP_ARG_REQUIRED }, 62 | { MP_QSTR_write, MP_ARG_OBJ | MP_ARG_KW_ONLY | MP_ARG_REQUIRED }, 63 | { MP_QSTR_read, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_OBJ_NULL} }, 64 | { MP_QSTR_cs, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_OBJ_NULL} }, 65 | { MP_QSTR_pclk, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 10000000 } }, 66 | { MP_QSTR_width, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 240 } }, 67 | { MP_QSTR_height, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 240 } }, 68 | { MP_QSTR_swap_color_bytes, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false } }, 69 | { MP_QSTR_cmd_bits, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 8 } }, 70 | { MP_QSTR_param_bits, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 8 } }, 71 | }; 72 | mp_arg_val_t args[MP_ARRAY_SIZE(make_new_args)]; 73 | mp_arg_parse_all_kw_array( 74 | n_args, n_kw, 75 | all_args, 76 | MP_ARRAY_SIZE(make_new_args), 77 | make_new_args, 78 | args 79 | ); 80 | 81 | // create new object 82 | mp_lcd_i80_obj_t *self = m_new_obj(mp_lcd_i80_obj_t); 83 | self->base.type = &mp_lcd_i80_type; 84 | 85 | // data bus 86 | mp_obj_tuple_t *t = MP_OBJ_TO_PTR(args[ARG_data].u_obj); 87 | self->bus_width = t->len; 88 | for (size_t i = 0; i < t->len; i++) { 89 | self->databus[i] = t->items[i]; 90 | } 91 | 92 | self->dc = args[ARG_dc].u_obj; 93 | self->wr = args[ARG_write].u_obj; 94 | self->rd = args[ARG_read].u_obj; 95 | self->cs = args[ARG_cs].u_obj; 96 | self->pclk = args[ARG_pclk].u_int; 97 | self->width = args[ARG_width].u_int; 98 | self->height = args[ARG_height].u_int; 99 | self->swap_color_bytes = args[ARG_swap_color_bytes].u_bool; 100 | self->cmd_bits = args[ARG_cmd_bits].u_int; 101 | self->param_bits = args[ARG_param_bits].u_int; 102 | 103 | if (self->rd != MP_OBJ_NULL) { 104 | mp_hal_pin_obj_t rd_pin = mp_hal_get_pin_obj(self->rd); 105 | mp_hal_pin_output(rd_pin); 106 | mp_hal_pin_write(rd_pin, 1); 107 | } 108 | 109 | hal_lcd_i80_construct(&self->base); 110 | return MP_OBJ_FROM_PTR(self); 111 | } 112 | 113 | 114 | STATIC mp_obj_t mp_lcd_i80_tx_param(size_t n_args, const mp_obj_t *args_in) 115 | { 116 | mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(args_in[0]); 117 | int cmd = mp_obj_get_int(args_in[1]); 118 | if (n_args == 3) { 119 | mp_buffer_info_t bufinfo; 120 | mp_get_buffer_raise(args_in[2], &bufinfo, MP_BUFFER_READ); 121 | hal_lcd_i80_tx_param(self, cmd, bufinfo.buf, bufinfo.len); 122 | } else { 123 | hal_lcd_i80_tx_param(self, cmd, NULL, 0); 124 | } 125 | 126 | return mp_const_none; 127 | } 128 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_lcd_i80_tx_param_obj, 2, 3, mp_lcd_i80_tx_param); 129 | 130 | 131 | STATIC mp_obj_t mp_lcd_i80_tx_color(size_t n_args, const mp_obj_t *args_in) 132 | { 133 | mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(args_in[0]); 134 | int cmd = mp_obj_get_int(args_in[1]); 135 | 136 | if (n_args == 3) { 137 | mp_buffer_info_t bufinfo; 138 | mp_get_buffer_raise(args_in[2], &bufinfo, MP_BUFFER_READ); 139 | hal_lcd_i80_tx_color(self, cmd, bufinfo.buf, bufinfo.len); 140 | } else { 141 | hal_lcd_i80_tx_color(self, cmd, NULL, 0); 142 | } 143 | 144 | gc_collect(); 145 | return mp_const_none; 146 | } 147 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_lcd_i80_tx_color_obj, 2, 3, mp_lcd_i80_tx_color); 148 | 149 | 150 | STATIC mp_obj_t mp_lcd_i80_deinit(mp_obj_t self_in) 151 | { 152 | mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(self_in); 153 | 154 | hal_lcd_i80_deinit(self); 155 | 156 | return mp_const_none; 157 | } 158 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_lcd_i80_deinit_obj, mp_lcd_i80_deinit); 159 | 160 | 161 | STATIC const mp_rom_map_elem_t mp_lcd_i80_locals_dict_table[] = { 162 | { MP_ROM_QSTR(MP_QSTR_tx_param), MP_ROM_PTR(&mp_lcd_i80_tx_param_obj) }, 163 | { MP_ROM_QSTR(MP_QSTR_tx_color), MP_ROM_PTR(&mp_lcd_i80_tx_color_obj) }, 164 | { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&mp_lcd_i80_deinit_obj) }, 165 | { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_lcd_i80_deinit_obj) }, 166 | }; 167 | STATIC MP_DEFINE_CONST_DICT(mp_lcd_i80_locals_dict, mp_lcd_i80_locals_dict_table); 168 | 169 | 170 | STATIC const mp_lcd_panel_p_t mp_lcd_panel_p = { 171 | .tx_param = hal_lcd_i80_tx_param, 172 | .tx_color = hal_lcd_i80_tx_color, 173 | .deinit = hal_lcd_i80_deinit 174 | }; 175 | 176 | #ifdef MP_OBJ_TYPE_GET_SLOT 177 | MP_DEFINE_CONST_OBJ_TYPE( 178 | mp_lcd_i80_type, 179 | MP_QSTR_I8080, 180 | MP_TYPE_FLAG_NONE, 181 | print, mp_lcd_i80_print, 182 | make_new, mp_lcd_i80_make_new, 183 | protocol, &mp_lcd_panel_p, 184 | locals_dict, (mp_obj_dict_t *)&mp_lcd_i80_locals_dict 185 | ); 186 | #else 187 | const mp_obj_type_t mp_lcd_i80_type = { 188 | { &mp_type_type }, 189 | .name = MP_QSTR_I8080, 190 | .print = mp_lcd_i80_print, 191 | .make_new = mp_lcd_i80_make_new, 192 | .protocol = &mp_lcd_panel_p, 193 | .locals_dict = (mp_obj_dict_t *)&mp_lcd_i80_locals_dict, 194 | }; 195 | #endif 196 | -------------------------------------------------------------------------------- /lcd/bus/i80/i80_panel.h: -------------------------------------------------------------------------------- 1 | #ifndef LCD_I80_H_ 2 | #define LCD_I80_H_ 3 | 4 | #include "mphalport.h" 5 | #include "py/obj.h" 6 | #if USE_ESP_LCD 7 | #include "esp_lcd_panel_io.h" 8 | #endif 9 | 10 | typedef struct _mp_lcd_i80_obj_t { 11 | mp_obj_base_t base; 12 | 13 | uint16_t width; 14 | uint16_t height; 15 | 16 | mp_obj_t databus[8]; 17 | mp_obj_t dc; 18 | mp_obj_t wr; 19 | mp_obj_t rd; 20 | mp_obj_t reset; 21 | mp_obj_t cs; 22 | // mp_obj_t backlight; 23 | 24 | mp_hal_pin_obj_t databus_pins[8]; 25 | mp_hal_pin_obj_t dc_pin; 26 | mp_hal_pin_obj_t wr_pin; 27 | mp_hal_pin_obj_t rd_pin; 28 | mp_hal_pin_obj_t reset_pin; 29 | mp_hal_pin_obj_t cs_pin; 30 | mp_hal_pin_obj_t backlight_pin; 31 | 32 | uint32_t pclk; 33 | size_t bus_width; 34 | bool swap_color_bytes; 35 | int cmd_bits; 36 | int param_bits; 37 | 38 | esp_lcd_i80_bus_handle_t i80_bus; 39 | esp_lcd_panel_io_handle_t io_handle; 40 | void (*write_color)(mp_hal_pin_obj_t *databus, mp_hal_pin_obj_t wr, const uint8_t *buf, int len); 41 | 42 | } mp_lcd_i80_obj_t; 43 | 44 | extern const mp_obj_type_t mp_lcd_i80_type; 45 | 46 | #endif -------------------------------------------------------------------------------- /lcd/bus/qspi/qspi_panel.c: -------------------------------------------------------------------------------- 1 | #include "qspi_panel.h" 2 | #include "lcd_panel.h" 3 | 4 | #if USE_ESP_LCD 5 | #include "esp32.h" 6 | #else 7 | #include "soft8080.h" 8 | #endif 9 | 10 | #include "mphalport.h" 11 | 12 | #include "py/obj.h" 13 | #include "py/runtime.h" 14 | #include "py/gc.h" 15 | 16 | #include 17 | 18 | 19 | STATIC void mp_lcd_qspi_panel_print(const mp_print_t *print, 20 | mp_obj_t self_in, 21 | mp_print_kind_t kind) 22 | { 23 | (void) kind; 24 | mp_lcd_qspi_panel_obj_t *self = MP_OBJ_TO_PTR(self_in); 25 | mp_printf( 26 | print, 27 | "", 28 | self->spi_obj, 29 | self->dc, 30 | self->wr, 31 | self->cs, 32 | self->width, 33 | self->height, 34 | self->cmd_bits, 35 | self->param_bits 36 | ); 37 | } 38 | 39 | 40 | STATIC mp_obj_t mp_lcd_qspi_panel_make_new(const mp_obj_type_t *type, 41 | size_t n_args, 42 | size_t n_kw, 43 | const mp_obj_t *all_args) 44 | { 45 | enum { 46 | ARG_spi, 47 | ARG_data, 48 | ARG_dc, 49 | ARG_cs, 50 | ARG_pclk, 51 | ARG_width, 52 | ARG_height, 53 | ARG_cmd_bits, 54 | ARG_param_bits 55 | }; 56 | const mp_arg_t make_new_args[] = { 57 | { MP_QSTR_spi, MP_ARG_OBJ | MP_ARG_KW_ONLY | MP_ARG_REQUIRED }, 58 | { MP_QSTR_data, MP_ARG_OBJ | MP_ARG_KW_ONLY | MP_ARG_REQUIRED }, 59 | { MP_QSTR_dc, MP_ARG_OBJ | MP_ARG_KW_ONLY | MP_ARG_REQUIRED }, 60 | { MP_QSTR_cs, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_OBJ_NULL} }, 61 | { MP_QSTR_pclk, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 10000000 } }, 62 | { MP_QSTR_width, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 240 } }, 63 | { MP_QSTR_height, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 240 } }, 64 | { MP_QSTR_cmd_bits, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 8 } }, 65 | { MP_QSTR_param_bits, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 8 } }, 66 | }; 67 | mp_arg_val_t args[MP_ARRAY_SIZE(make_new_args)]; 68 | mp_arg_parse_all_kw_array( 69 | n_args, 70 | n_kw, 71 | all_args, 72 | MP_ARRAY_SIZE(make_new_args), 73 | make_new_args, args 74 | ); 75 | 76 | // create new object 77 | mp_lcd_qspi_panel_obj_t *self = m_new_obj(mp_lcd_qspi_panel_obj_t); 78 | self->base.type = &mp_lcd_qspi_panel_type; 79 | self->spi_obj = (mp_obj_base_t *)MP_OBJ_TO_PTR(args[ARG_spi].u_obj); 80 | // data bus 81 | mp_obj_tuple_t *t = MP_OBJ_TO_PTR(args[ARG_data].u_obj); 82 | for (size_t i = 0; i < t->len; i++) { 83 | if (i < 4) { 84 | self->databus_pins[i] = mp_hal_get_pin_obj(t->items[i]); 85 | } 86 | } 87 | self->dc_pin = mp_hal_get_pin_obj(args[ARG_dc].u_obj); 88 | self->cs_pin = mp_hal_get_pin_obj(args[ARG_cs].u_obj); 89 | self->pclk = args[ARG_pclk].u_int; 90 | self->width = args[ARG_width].u_int; 91 | self->height = args[ARG_height].u_int; 92 | self->cmd_bits = args[ARG_cmd_bits].u_int; 93 | self->param_bits = args[ARG_param_bits].u_int; 94 | 95 | hal_lcd_qspi_panel_construct(&self->base); 96 | return MP_OBJ_FROM_PTR(self); 97 | } 98 | 99 | 100 | STATIC mp_obj_t mp_lcd_qspi_panel_tx_param(size_t n_args, const mp_obj_t *args_in) 101 | { 102 | mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(args_in[0]); 103 | int cmd = mp_obj_get_int(args_in[1]); 104 | if (n_args == 3) { 105 | mp_buffer_info_t bufinfo; 106 | mp_get_buffer_raise(args_in[2], &bufinfo, MP_BUFFER_READ); 107 | hal_lcd_qspi_panel_tx_param(self, cmd, bufinfo.buf, bufinfo.len); 108 | } else { 109 | hal_lcd_qspi_panel_tx_param(self, cmd, NULL, 0); 110 | } 111 | 112 | return mp_const_none; 113 | } 114 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_lcd_qspi_panel_tx_param_obj, 2, 3, mp_lcd_qspi_panel_tx_param); 115 | 116 | 117 | STATIC mp_obj_t mp_lcd_qspi_panel_tx_color(size_t n_args, const mp_obj_t *args_in) 118 | { 119 | mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(args_in[0]); 120 | int cmd = mp_obj_get_int(args_in[1]); 121 | 122 | if (n_args == 3) { 123 | mp_buffer_info_t bufinfo; 124 | mp_get_buffer_raise(args_in[2], &bufinfo, MP_BUFFER_READ); 125 | hal_lcd_qspi_panel_tx_color(self, cmd, bufinfo.buf, bufinfo.len); 126 | } else { 127 | hal_lcd_qspi_panel_tx_color(self, cmd, NULL, 0); 128 | } 129 | 130 | gc_collect(); 131 | return mp_const_none; 132 | } 133 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_lcd_qspi_panel_tx_color_obj, 2, 3, mp_lcd_qspi_panel_tx_color); 134 | 135 | 136 | STATIC mp_obj_t mp_lcd_qspi_panel_deinit(mp_obj_t self_in) 137 | { 138 | mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(self_in); 139 | 140 | hal_lcd_qspi_panel_deinit(self); 141 | // m_del_obj(mp_lcd_spi_panel_obj_t, self); 142 | return mp_const_none; 143 | } 144 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_lcd_qspi_panel_deinit_obj, mp_lcd_qspi_panel_deinit); 145 | 146 | 147 | STATIC const mp_rom_map_elem_t mp_lcd_qspi_panel_locals_dict_table[] = { 148 | { MP_ROM_QSTR(MP_QSTR_tx_param), MP_ROM_PTR(&mp_lcd_qspi_panel_tx_param_obj) }, 149 | { MP_ROM_QSTR(MP_QSTR_tx_color), MP_ROM_PTR(&mp_lcd_qspi_panel_tx_color_obj) }, 150 | { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&mp_lcd_qspi_panel_deinit_obj) }, 151 | { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_lcd_qspi_panel_deinit_obj) }, 152 | }; 153 | STATIC MP_DEFINE_CONST_DICT(mp_lcd_qspi_panel_locals_dict, mp_lcd_qspi_panel_locals_dict_table); 154 | 155 | 156 | STATIC const mp_lcd_panel_p_t mp_lcd_panel_p = { 157 | .tx_param = hal_lcd_qspi_panel_tx_param, 158 | .tx_color = hal_lcd_qspi_panel_tx_color, 159 | .deinit = hal_lcd_qspi_panel_deinit 160 | }; 161 | 162 | 163 | #ifdef MP_OBJ_TYPE_GET_SLOT 164 | MP_DEFINE_CONST_OBJ_TYPE( 165 | mp_lcd_qspi_panel_type, 166 | MP_QSTR_QSPI_Panel, 167 | MP_TYPE_FLAG_NONE, 168 | print, mp_lcd_qspi_panel_print, 169 | make_new, mp_lcd_qspi_panel_make_new, 170 | protocol, &mp_lcd_panel_p, 171 | locals_dict, (mp_obj_dict_t *)&mp_lcd_qspi_panel_locals_dict 172 | ); 173 | #else 174 | const mp_obj_type_t mp_lcd_qspi_panel_type = { 175 | { &mp_type_type }, 176 | .name = MP_QSTR_QSPI_Panel, 177 | .print = mp_lcd_qspi_panel_print, 178 | .make_new = mp_lcd_qspi_panel_make_new, 179 | .protocol = &mp_lcd_panel_p, 180 | .locals_dict = (mp_obj_dict_t *)&mp_lcd_qspi_panel_locals_dict, 181 | }; 182 | #endif 183 | -------------------------------------------------------------------------------- /lcd/bus/qspi/qspi_panel.h: -------------------------------------------------------------------------------- 1 | #ifndef LCD_QSPI_PANEL_H_ 2 | #define LCD_QSPI_PANEL_H_ 3 | 4 | #include "mphalport.h" 5 | #include "py/obj.h" 6 | #if USE_ESP_LCD 7 | #include "esp_lcd_panel_io.h" 8 | #include "driver/spi_master.h" 9 | #endif 10 | 11 | typedef struct _mp_lcd_qspi_panel_obj_t { 12 | mp_obj_base_t base; 13 | mp_obj_base_t *spi_obj; 14 | uint16_t width; 15 | uint16_t height; 16 | 17 | mp_hal_pin_obj_t databus_pins[4]; 18 | mp_hal_pin_obj_t dc_pin; 19 | mp_hal_pin_obj_t wr_pin; 20 | mp_hal_pin_obj_t cs_pin; 21 | 22 | mp_obj_t databus[4]; 23 | mp_obj_t dc; 24 | mp_obj_t wr; 25 | mp_obj_t cs; 26 | 27 | uint32_t pclk; 28 | int cmd_bits; 29 | int param_bits; 30 | // bool swap_color_bytes; 31 | #if USE_ESP_LCD 32 | spi_device_handle_t io_handle; 33 | #else 34 | void (*write_color)(mp_hal_pin_obj_t *databus, mp_hal_pin_obj_t wr, const uint8_t *buf, int len); 35 | #endif 36 | } mp_lcd_qspi_panel_obj_t; 37 | 38 | extern const mp_obj_type_t mp_lcd_qspi_panel_type; 39 | 40 | #endif -------------------------------------------------------------------------------- /lcd/bus/spi/spi_panel.c: -------------------------------------------------------------------------------- 1 | #include "spi_panel.h" 2 | #include "lcd_panel.h" 3 | 4 | #include "modmachine.h" 5 | #include "extmod/machine_spi.h" 6 | #include "esp32.h" 7 | #include "softspi.h" 8 | 9 | #include "mphalport.h" 10 | 11 | #include "py/obj.h" 12 | #include "py/runtime.h" 13 | #include "py/gc.h" 14 | 15 | #include 16 | 17 | 18 | STATIC void mp_lcd_spi_panel_print(const mp_print_t *print, 19 | mp_obj_t self_in, 20 | mp_print_kind_t kind) 21 | { 22 | (void) kind; 23 | mp_lcd_spi_panel_obj_t *self = MP_OBJ_TO_PTR(self_in); 24 | mp_printf( 25 | print, 26 | "", 27 | self->spi_obj, 28 | self->dc, 29 | self->cs, 30 | self->width, 31 | self->height, 32 | self->cmd_bits, 33 | self->param_bits 34 | ); 35 | } 36 | 37 | 38 | STATIC mp_obj_t mp_lcd_spi_panel_make_new(const mp_obj_type_t *type, 39 | size_t n_args, 40 | size_t n_kw, 41 | const mp_obj_t *all_args) 42 | { 43 | enum { 44 | ARG_spi, 45 | ARG_dc, 46 | ARG_cs, 47 | ARG_pclk, 48 | ARG_width, 49 | ARG_height, 50 | ARG_cmd_bits, 51 | ARG_param_bits 52 | }; 53 | const mp_arg_t make_new_args[] = { 54 | { MP_QSTR_spi, MP_ARG_OBJ | MP_ARG_KW_ONLY | MP_ARG_REQUIRED }, 55 | { MP_QSTR_dc, MP_ARG_OBJ | MP_ARG_KW_ONLY | MP_ARG_REQUIRED }, 56 | { MP_QSTR_cs, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_OBJ_NULL} }, 57 | { MP_QSTR_pclk, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 10000000 } }, 58 | { MP_QSTR_width, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 240 } }, 59 | { MP_QSTR_height, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 240 } }, 60 | { MP_QSTR_cmd_bits, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 8 } }, 61 | { MP_QSTR_param_bits, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 8 } }, 62 | }; 63 | mp_arg_val_t args[MP_ARRAY_SIZE(make_new_args)]; 64 | mp_arg_parse_all_kw_array( 65 | n_args, 66 | n_kw, 67 | all_args, 68 | MP_ARRAY_SIZE(make_new_args), 69 | make_new_args, args 70 | ); 71 | 72 | // create new object 73 | mp_lcd_spi_panel_obj_t *self = m_new_obj(mp_lcd_spi_panel_obj_t); 74 | self->base.type = &mp_lcd_spi_panel_type; 75 | 76 | self->spi_obj = (mp_obj_base_t *)MP_OBJ_TO_PTR(args[ARG_spi].u_obj); 77 | self->dc = args[ARG_dc].u_obj; 78 | self->cs = args[ARG_cs].u_obj; 79 | self->pclk = args[ARG_pclk].u_int; 80 | self->width = args[ARG_width].u_int; 81 | self->height = args[ARG_height].u_int; 82 | self->cmd_bits = args[ARG_cmd_bits].u_int; 83 | self->param_bits = args[ARG_param_bits].u_int; 84 | 85 | #if (MICROPY_VERSION_MAJOR == 1) && (MICROPY_VERSION_MINOR >= 20) 86 | if (mp_obj_is_type(self->spi_obj, &machine_spi_type)) { 87 | #else 88 | if (mp_obj_is_type(self->spi_obj, &machine_hw_spi_type)) { 89 | #endif 90 | hal_lcd_spi_panel_construct(&self->base); 91 | } else if (mp_obj_is_type(self->spi_obj, &mp_machine_soft_spi_type)) { 92 | hal_lcd_softspi_panel_construct(&self->base); 93 | } 94 | 95 | return MP_OBJ_FROM_PTR(self); 96 | } 97 | 98 | 99 | STATIC mp_obj_t mp_lcd_spi_panel_tx_param(size_t n_args, const mp_obj_t *args_in) 100 | { 101 | mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(args_in[0]); 102 | int cmd = mp_obj_get_int(args_in[1]); 103 | if (n_args == 3) { 104 | mp_buffer_info_t bufinfo; 105 | mp_get_buffer_raise(args_in[2], &bufinfo, MP_BUFFER_READ); 106 | hal_lcd_spi_panel_tx_param(self, cmd, bufinfo.buf, bufinfo.len); 107 | } else { 108 | hal_lcd_spi_panel_tx_param(self, cmd, NULL, 0); 109 | } 110 | 111 | return mp_const_none; 112 | } 113 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_lcd_spi_panel_tx_param_obj, 2, 3, mp_lcd_spi_panel_tx_param); 114 | 115 | 116 | STATIC mp_obj_t mp_lcd_spi_panel_tx_color(size_t n_args, const mp_obj_t *args_in) 117 | { 118 | mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(args_in[0]); 119 | int cmd = mp_obj_get_int(args_in[1]); 120 | 121 | if (n_args == 3) { 122 | mp_buffer_info_t bufinfo; 123 | mp_get_buffer_raise(args_in[2], &bufinfo, MP_BUFFER_READ); 124 | hal_lcd_spi_panel_tx_color(self, cmd, bufinfo.buf, bufinfo.len); 125 | } else { 126 | hal_lcd_spi_panel_tx_color(self, cmd, NULL, 0); 127 | } 128 | 129 | gc_collect(); 130 | return mp_const_none; 131 | } 132 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_lcd_spi_panel_tx_color_obj, 2, 3, mp_lcd_spi_panel_tx_color); 133 | 134 | 135 | STATIC mp_obj_t mp_lcd_spi_panel_deinit(mp_obj_t self_in) 136 | { 137 | mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(self_in); 138 | 139 | hal_lcd_spi_panel_deinit(self); 140 | 141 | return mp_const_none; 142 | } 143 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_lcd_spi_panel_deinit_obj, mp_lcd_spi_panel_deinit); 144 | 145 | 146 | STATIC const mp_rom_map_elem_t mp_lcd_spi_panel_locals_dict_table[] = { 147 | { MP_ROM_QSTR(MP_QSTR_tx_param), MP_ROM_PTR(&mp_lcd_spi_panel_tx_param_obj) }, 148 | { MP_ROM_QSTR(MP_QSTR_tx_color), MP_ROM_PTR(&mp_lcd_spi_panel_tx_color_obj) }, 149 | { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&mp_lcd_spi_panel_deinit_obj) }, 150 | { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_lcd_spi_panel_deinit_obj) }, 151 | }; 152 | STATIC MP_DEFINE_CONST_DICT(mp_lcd_spi_panel_locals_dict, mp_lcd_spi_panel_locals_dict_table); 153 | 154 | 155 | STATIC inline void mp_lcd_spi_panel_p_tx_param(mp_obj_base_t *self, 156 | int lcd_cmd, 157 | const void *param, 158 | size_t param_size) 159 | { 160 | mp_lcd_spi_panel_obj_t *spi_panel_obj = (mp_lcd_spi_panel_obj_t *)self; 161 | #if (MICROPY_VERSION_MAJOR == 1) && (MICROPY_VERSION_MINOR >= 20) 162 | if (mp_obj_is_type(spi_panel_obj->spi_obj, &machine_spi_type)) { 163 | #else 164 | if (mp_obj_is_type(spi_panel_obj->spi_obj, &machine_hw_spi_type)) { 165 | #endif 166 | hal_lcd_spi_panel_tx_param(self, lcd_cmd, param, param_size); 167 | } else if (mp_obj_is_type(spi_panel_obj->spi_obj, &mp_machine_soft_spi_type)) { 168 | hal_lcd_softspi_panel_tx_param(self, lcd_cmd, param, param_size); 169 | } 170 | } 171 | 172 | 173 | STATIC inline void mp_lcd_spi_panel_p_tx_color(mp_obj_base_t *self, 174 | int lcd_cmd, 175 | const void *color, 176 | size_t color_size) 177 | { 178 | mp_lcd_spi_panel_obj_t *spi_panel_obj = (mp_lcd_spi_panel_obj_t *)self; 179 | #if (MICROPY_VERSION_MAJOR == 1) && (MICROPY_VERSION_MINOR >= 20) 180 | if (mp_obj_is_type(spi_panel_obj->spi_obj, &machine_spi_type)) { 181 | #else 182 | if (mp_obj_is_type(spi_panel_obj->spi_obj, &machine_hw_spi_type)) { 183 | #endif 184 | hal_lcd_spi_panel_tx_color(self, lcd_cmd, color, color_size); 185 | } else if (mp_obj_is_type(spi_panel_obj->spi_obj, &mp_machine_soft_spi_type)) { 186 | hal_lcd_softspi_panel_tx_color(self, lcd_cmd, color, color_size); 187 | } 188 | } 189 | 190 | 191 | STATIC inline void mp_lcd_spi_panel_p_deinit(mp_obj_base_t *self) 192 | { 193 | mp_lcd_spi_panel_obj_t *spi_panel_obj = (mp_lcd_spi_panel_obj_t *)self; 194 | #if (MICROPY_VERSION_MAJOR == 1) && (MICROPY_VERSION_MINOR >= 20) 195 | if (mp_obj_is_type(spi_panel_obj->spi_obj, &machine_spi_type)) { 196 | #else 197 | if (mp_obj_is_type(spi_panel_obj->spi_obj, &machine_hw_spi_type)) { 198 | #endif 199 | hal_lcd_spi_panel_deinit(self); 200 | } else if (mp_obj_is_type(spi_panel_obj->spi_obj, &mp_machine_soft_spi_type)) { 201 | hal_lcd_softspi_panel_deinit(self); 202 | } 203 | } 204 | 205 | 206 | STATIC const mp_lcd_panel_p_t mp_lcd_panel_p = { 207 | .tx_param = mp_lcd_spi_panel_p_tx_param, 208 | .tx_color = mp_lcd_spi_panel_p_tx_color, 209 | .deinit = mp_lcd_spi_panel_p_deinit 210 | }; 211 | 212 | #ifdef MP_OBJ_TYPE_GET_SLOT 213 | MP_DEFINE_CONST_OBJ_TYPE( 214 | mp_lcd_spi_panel_type, 215 | MP_QSTR_SPI_Panel, 216 | MP_TYPE_FLAG_NONE, 217 | print, mp_lcd_spi_panel_print, 218 | make_new, mp_lcd_spi_panel_make_new, 219 | protocol, &mp_lcd_panel_p, 220 | locals_dict, (mp_obj_dict_t *)&mp_lcd_spi_panel_locals_dict 221 | ); 222 | #else 223 | const mp_obj_type_t mp_lcd_spi_panel_type = { 224 | { &mp_type_type }, 225 | .name = MP_QSTR_SPI_Panel, 226 | .print = mp_lcd_spi_panel_print, 227 | .make_new = mp_lcd_spi_panel_make_new, 228 | .protocol = &mp_lcd_panel_p, 229 | .locals_dict = (mp_obj_dict_t *)&mp_lcd_spi_panel_locals_dict, 230 | }; 231 | #endif 232 | -------------------------------------------------------------------------------- /lcd/bus/spi/spi_panel.h: -------------------------------------------------------------------------------- 1 | #ifndef LCD_SPI_PANEL_H_ 2 | #define LCD_SPI_PANEL_H_ 3 | 4 | #include "mphalport.h" 5 | #include "py/obj.h" 6 | #if USE_ESP_LCD 7 | #include "esp_lcd_panel_io.h" 8 | #endif 9 | 10 | typedef struct _mp_lcd_spi_panel_obj_t { 11 | mp_obj_base_t base; 12 | 13 | mp_obj_base_t *spi_obj; 14 | uint16_t width; 15 | uint16_t height; 16 | 17 | mp_obj_t dc; 18 | mp_obj_t cs; 19 | mp_hal_pin_obj_t dc_pin; 20 | mp_hal_pin_obj_t cs_pin; 21 | 22 | uint32_t pclk; 23 | int cmd_bits; 24 | int param_bits; 25 | // bool swap_color_bytes; 26 | #if USE_ESP_LCD 27 | esp_lcd_panel_io_handle_t io_handle; 28 | #else 29 | void (*write_color)(mp_hal_pin_obj_t *databus, mp_hal_pin_obj_t wr, const uint8_t *buf, int len); 30 | #endif 31 | 32 | enum { 33 | LCD_SPI_PANEL_STATE_NONE, 34 | LCD_SPI_PANEL_STATE_INIT, 35 | LCD_SPI_PANEL_STATE_DEINIT 36 | } state; 37 | } mp_lcd_spi_panel_obj_t; 38 | 39 | extern const mp_obj_type_t mp_lcd_spi_panel_type; 40 | 41 | #endif -------------------------------------------------------------------------------- /lcd/driver/common/lcd_panel_commands.h: -------------------------------------------------------------------------------- 1 | #ifndef _LCD_PANEL_COMMANDS_H_ 2 | #define _LCD_PANEL_COMMANDS_H_ 3 | 4 | /* Common LCD panel commands */ 5 | #define LCD_CMD_NOP 0x00 // This command is empty command 6 | #define LCD_CMD_SWRESET 0x01 // Software reset registers (the built-in frame buffer is not affected) 7 | #define LCD_CMD_RDDID 0x04 // Read 24-bit display ID 8 | #define LCD_CMD_RDDST 0x09 // Read display status 9 | #define LCD_CMD_RDDPM 0x0A // Read display power mode 10 | #define LCD_CMD_RDD_MADCTL 0x0B // Read display MADCTL 11 | #define LCD_CMD_RDD_COLMOD 0x0C // Read display pixel format 12 | #define LCD_CMD_RDDIM 0x0D // Read display image mode 13 | #define LCD_CMD_RDDSM 0x0E // Read display signal mode 14 | #define LCD_CMD_RDDSR 0x0F // Read display self-diagnostic result 15 | #define LCD_CMD_SLPIN 0x10 // Go into sleep mode (DC/DC, oscillator, scanning stopped, but memory keeps content) 16 | #define LCD_CMD_SLPOUT 0x11 // Exit sleep mode 17 | #define LCD_CMD_PTLON 0x12 // Turns on partial display mode 18 | #define LCD_CMD_NORON 0x13 // Turns on normal display mode 19 | #define LCD_CMD_INVOFF 0x20 // Recover from display inversion mode 20 | #define LCD_CMD_INVON 0x21 // Go into display inversion mode 21 | #define LCD_CMD_GAMSET 0x26 // Select Gamma curve for current display 22 | #define LCD_CMD_DISPOFF 0x28 // Display off (disable frame buffer output) 23 | #define LCD_CMD_DISPON 0x29 // Display on (enable frame buffer output) 24 | #define LCD_CMD_CASET 0x2A // Set column address 25 | #define LCD_CMD_RASET 0x2B // Set row address 26 | #define LCD_CMD_RAMWR 0x2C // Write frame memory 27 | #define LCD_CMD_RAMRD 0x2E // Read frame memory 28 | #define LCD_CMD_PTLAR 0x30 // Define the partial area 29 | #define LCD_CMD_VSCRDEF 0x33 // Vertical scrolling definition 30 | #define LCD_CMD_TEOFF 0x34 // Turns of tearing effect 31 | #define LCD_CMD_TEON 0x35 // Turns on tearing effect 32 | 33 | #define LCD_CMD_MADCTL 0x36 // Memory data access control 34 | #define LCD_CMD_MH_BIT (1 << 2) // Display data latch order, 0: refresh left to right, 1: refresh right to left 35 | #define LCD_CMD_BGR_BIT (1 << 3) // RGB/BGR order, 0: RGB, 1: BGR 36 | #define LCD_CMD_ML_BIT (1 << 4) // Line address order, 0: refresh top to bottom, 1: refresh bottom to top 37 | #define LCD_CMD_MV_BIT (1 << 5) // Row/Column order, 0: normal mode, 1: reverse mode 38 | #define LCD_CMD_MX_BIT (1 << 6) // Column address order, 0: left to right, 1: right to left 39 | #define LCD_CMD_MY_BIT (1 << 7) // Row address order, 0: top to bottom, 1: bottom to top 40 | 41 | #define LCD_CMD_VSCSAD 0x37 // Vertical scroll start address 42 | #define LCD_CMD_IDMOFF 0x38 // Recover from IDLE mode 43 | #define LCD_CMD_IDMON 0x39 // Fall into IDLE mode (8 color depth is displayed) 44 | #define LCD_CMD_COLMOD 0x3A // Defines the format of RGB picture data 45 | #define LCD_CMD_RAMWRC 0x3C // Memory write continue 46 | #define LCD_CMD_RAMRDC 0x3E // Memory read continue 47 | #define LCD_CMD_STE 0x44 // Set tear scanline, tearing effect output signal when display module reaches line N 48 | #define LCD_CMD_GDCAN 0x45 // Get scanline 49 | #define LCD_CMD_WRDISBV 0x51 // Write display brightness 50 | #define LCD_CMD_RDDISBV 0x52 // Read display brightness value 51 | 52 | #endif -------------------------------------------------------------------------------- /lcd/driver/common/lcd_panel_rotation.h: -------------------------------------------------------------------------------- 1 | #ifndef _LCD_PANEL_ROTATION_H_ 2 | #define _LCD_PANEL_ROTATION_H_ 3 | 4 | #include 5 | 6 | typedef struct _lcd_panel_rotation_t { 7 | uint8_t madctl; 8 | uint16_t width; 9 | uint16_t height; 10 | uint16_t colstart; 11 | uint16_t rowstart; 12 | } lcd_panel_rotation_t; 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /lcd/driver/common/lcd_panel_types.c: -------------------------------------------------------------------------------- 1 | #include "lcd_panel_types.h" 2 | 3 | const char* color_space_desc[] = { 4 | "RGB", 5 | "BGR", 6 | "MONOCHROME" 7 | }; 8 | -------------------------------------------------------------------------------- /lcd/driver/common/lcd_panel_types.h: -------------------------------------------------------------------------------- 1 | #ifndef _LCD_PANEL_TYPES_H_ 2 | #define _LCD_PANEL_TYPES_H_ 3 | 4 | #define COLOR_SPACE_RGB (0) 5 | #define COLOR_SPACE_BGR (1) 6 | #define COLOR_SPACE_MONOCHROME (2) 7 | 8 | extern const char* color_space_desc[]; 9 | 10 | #endif -------------------------------------------------------------------------------- /lcd/driver/gc9a01/gc9a01.h: -------------------------------------------------------------------------------- 1 | #ifndef LCD_GC9A01_H_ 2 | #define LCD_GC9A01_H_ 3 | 4 | #include "py/obj.h" 5 | 6 | extern const mp_obj_type_t mp_lcd_gc9a01_type; 7 | 8 | #endif -------------------------------------------------------------------------------- /lcd/driver/gc9a01/gc9a01_rotation.h: -------------------------------------------------------------------------------- 1 | #ifndef _ST7789_ROTATION_H_ 2 | #define _ST7789_ROTATION_H_ 3 | 4 | #include "lcd_panel_rotation.h" 5 | 6 | 7 | // 8 | // Default st7789 and st7735 display orientation tables 9 | // can be overridden during init(), madctl values 10 | // will be combined with color_mode 11 | // 12 | //{ madctl, width, height, colstart, rowstart } 13 | // 14 | STATIC const lcd_panel_rotation_t ORIENTATIONS_GENERAL[4] = { 15 | { 0x00, 0, 0, 0, 0}, 16 | { 0x60, 0, 0, 0, 0}, 17 | { 0xC0, 0, 0, 0, 0}, 18 | { 0xA0, 0, 0, 0, 0} 19 | }; 20 | 21 | 22 | STATIC const lcd_panel_rotation_t ORIENTATIONS_240x240[4] = { 23 | {0x00, 240, 240, 0, 0}, 24 | {0x60, 240, 240, 0, 0}, 25 | {0xC0, 240, 240, 0, 0}, 26 | {0xA0, 240, 240, 0, 0} 27 | }; 28 | 29 | #endif -------------------------------------------------------------------------------- /lcd/driver/ili9488/ili9488.h: -------------------------------------------------------------------------------- 1 | #ifndef LCD_ILI9488_H_ 2 | #define LCD_ILI9488_H_ 3 | 4 | #include "py/obj.h" 5 | 6 | extern const mp_obj_type_t mp_lcd_ili9488_type; 7 | 8 | #endif -------------------------------------------------------------------------------- /lcd/driver/ili9488/ili9488_rotation.h: -------------------------------------------------------------------------------- 1 | #ifndef _ILI9488_ROTATION_H_ 2 | #define _ILI9488_ROTATION_H_ 3 | 4 | #include "lcd_panel_rotation.h" 5 | 6 | // 7 | // Default ili9488 display orientation tables 8 | // can be overridden during init(), madctl values 9 | // will be combined with color_mode 10 | // 11 | STATIC const lcd_panel_rotation_t ORIENTATIONS_GENERAL[4] = { 12 | { 0x40, 0, 0, 0, 0}, 13 | { 0x20, 0, 0, 0, 0}, 14 | { 0x80, 0, 0, 0, 0}, 15 | { 0xE0, 0, 0, 0, 0} 16 | }; 17 | 18 | 19 | #endif -------------------------------------------------------------------------------- /lcd/driver/rm67162/rm67162.h: -------------------------------------------------------------------------------- 1 | #ifndef LCD_RM67162_H_ 2 | #define LCD_RM67162_H_ 3 | 4 | #include "py/obj.h" 5 | 6 | extern const mp_obj_type_t mp_lcd_rm67162_type; 7 | 8 | #endif -------------------------------------------------------------------------------- /lcd/driver/rm67162/rm67162_rotation.h: -------------------------------------------------------------------------------- 1 | #ifndef _RM67162_ROTATION_H_ 2 | #define _RM67162_ROTATION_H_ 3 | 4 | #include "lcd_panel_rotation.h" 5 | 6 | // 7 | // Default rm67162 display orientation tables 8 | // can be overridden during init(), madctl values 9 | // will be combined with color_mode 10 | // 11 | 12 | STATIC const lcd_panel_rotation_t ORIENTATIONS_GENERAL[4] = { 13 | { 0x00, 0, 0, 0, 0}, // { madctl, width, height, colstart, rowstart } 14 | { 0x60, 0, 0, 0, 0}, 15 | { 0xC0, 0, 0, 0, 0}, 16 | { 0xA0, 0, 0, 0, 0} 17 | }; 18 | 19 | STATIC const lcd_panel_rotation_t ORIENTATIONS_240x536[4] = { 20 | { 0x00, 240, 536, 0, 0 }, 21 | { 0x60, 536, 240, 0, 0 }, 22 | { 0xC0, 240, 160, 0, 0 }, 23 | { 0xA0, 536, 240, 0, 0 } 24 | }; 25 | 26 | #endif -------------------------------------------------------------------------------- /lcd/driver/st7735/st7735.h: -------------------------------------------------------------------------------- 1 | #ifndef LCD_ST7735_H_ 2 | #define LCD_ST7735_H_ 3 | 4 | #include "py/obj.h" 5 | 6 | extern const mp_obj_type_t mp_lcd_st7735_type; 7 | 8 | #endif -------------------------------------------------------------------------------- /lcd/driver/st7735/st7735_rotation.h: -------------------------------------------------------------------------------- 1 | #ifndef _ST7735_ROTATION_H_ 2 | #define _ST7735_ROTATION_H_ 3 | 4 | #include "lcd_panel_rotation.h" 5 | 6 | // 7 | // Default st7735 display orientation tables 8 | // can be overridden during init(), madctl values 9 | // will be combined with color_mode 10 | // 11 | 12 | STATIC const lcd_panel_rotation_t ORIENTATIONS_GENERAL[4] = { 13 | { 0x00, 0, 0, 0, 0}, // { madctl, width, height, colstart, rowstart } 14 | { 0x60, 0, 0, 0, 0}, 15 | { 0xC0, 0, 0, 0, 0}, 16 | { 0xA0, 0, 0, 0, 0} 17 | }; 18 | 19 | STATIC const lcd_panel_rotation_t ORIENTATIONS_160x80[4] = { 20 | { 0x00, 80, 160, 26, 1 }, // { madctl, width, height, colstart, rowstart } 21 | { 0x60, 160, 80, 1, 26 }, 22 | { 0xC0, 80, 160, 26, 1 }, 23 | { 0xA0, 160, 80, 1, 26 } 24 | }; 25 | 26 | #endif -------------------------------------------------------------------------------- /lcd/driver/st7789/st7789.h: -------------------------------------------------------------------------------- 1 | #ifndef LCD_ST7789_H_ 2 | #define LCD_ST7789_H_ 3 | 4 | #include "py/obj.h" 5 | 6 | extern const mp_obj_type_t mp_lcd_st7789_type; 7 | 8 | #endif -------------------------------------------------------------------------------- /lcd/driver/st7789/st7789_rotation.h: -------------------------------------------------------------------------------- 1 | #ifndef _ST7789_ROTATION_H_ 2 | #define _ST7789_ROTATION_H_ 3 | 4 | #include "lcd_panel_rotation.h" 5 | 6 | 7 | // 8 | // Default st7789 and st7735 display orientation tables 9 | // can be overridden during init(), madctl values 10 | // will be combined with color_mode 11 | // 12 | //{ madctl, width, height, colstart, rowstart } 13 | // 14 | STATIC const lcd_panel_rotation_t ORIENTATIONS_GENERAL[4] = { 15 | { 0x00, 0, 0, 0, 0}, 16 | { 0x60, 0, 0, 0, 0}, 17 | { 0xC0, 0, 0, 0, 0}, 18 | { 0xA0, 0, 0, 0, 0} 19 | }; 20 | 21 | STATIC const lcd_panel_rotation_t ORIENTATIONS_240x320[4] = { 22 | { 0x00, 240, 320, 0, 0}, 23 | { 0x60, 320, 240, 0, 0}, 24 | { 0xC0, 240, 320, 0, 0}, 25 | { 0xA0, 320, 240, 0, 0} 26 | }; 27 | 28 | STATIC const lcd_panel_rotation_t ORIENTATIONS_170x320[4] = { 29 | {0x00, 170, 320, 35, 0}, 30 | {0x60, 320, 170, 0, 35}, 31 | {0xC0, 170, 320, 35, 0}, 32 | {0xA0, 320, 170, 0, 35} 33 | }; 34 | 35 | STATIC const lcd_panel_rotation_t ORIENTATIONS_240x240[4] = { 36 | {0x00, 240, 240, 0, 0}, 37 | {0x60, 240, 240, 0, 0}, 38 | {0xC0, 240, 240, 0, 80}, 39 | {0xA0, 240, 240, 80, 0} 40 | }; 41 | 42 | STATIC const lcd_panel_rotation_t ORIENTATIONS_135x240[4] = { 43 | {0x00, 135, 240, 52, 40}, 44 | {0x60, 240, 135, 40, 53}, 45 | {0xC0, 135, 240, 53, 40}, 46 | {0xA0, 240, 135, 40, 52} 47 | }; 48 | 49 | STATIC const lcd_panel_rotation_t ORIENTATIONS_128x160[4] = { 50 | {0x00, 128, 160, 0, 0}, 51 | {0x60, 160, 128, 0, 0}, 52 | {0xC0, 128, 160, 0, 0}, 53 | {0xA0, 160, 128, 0, 0} 54 | }; 55 | 56 | STATIC const lcd_panel_rotation_t ORIENTATIONS_128x128[4] = { 57 | {0x00, 128, 128, 2, 1}, 58 | {0x60, 128, 128, 1, 2}, 59 | {0xC0, 128, 128, 2, 3}, 60 | {0xA0, 128, 128, 3, 2} 61 | }; 62 | 63 | #endif -------------------------------------------------------------------------------- /lcd/hal/common/soft8080.c: -------------------------------------------------------------------------------- 1 | #include "soft8080.h" 2 | 3 | #include "mphalport.h" 4 | 5 | #define DEBUG_printf(...) // mp_printf(&mp_plat_print, __VA_ARGS__); 6 | 7 | #define CS_LOW() \ 8 | { \ 9 | if (self->cs_pin != -1) { \ 10 | mp_hal_pin_write(self->cs_pin, 0); \ 11 | } \ 12 | } 13 | 14 | #define CS_HIGH() \ 15 | { \ 16 | if (self->cs_pin != -1) { \ 17 | mp_hal_pin_write(self->cs_pin, 1); \ 18 | } \ 19 | } 20 | 21 | #define DC_LOW() (mp_hal_pin_write(self->dc_pin, 0)) 22 | #define DC_HIGH() (mp_hal_pin_write(self->dc_pin, 1)) 23 | 24 | #define WR_LOW() (mp_hal_pin_write(self->wr_pin, 0)) 25 | #define WR_HIGH() (mp_hal_pin_write(self->wr_pin, 1)) 26 | 27 | STATIC void write_bus(mp_lcd_i80_obj_t *self, const uint8_t *buf, int len) 28 | { 29 | static uint8_t last = 0; 30 | uint8_t b; 31 | 32 | for (int i = 0; i < len; i++) { 33 | b = buf[i]; 34 | if (b != last) { 35 | mp_hal_pin_write(self->databus_pins[7], (b >> 7) & 1); 36 | mp_hal_pin_write(self->databus_pins[6], (b >> 6) & 1); 37 | mp_hal_pin_write(self->databus_pins[5], (b >> 5) & 1); 38 | mp_hal_pin_write(self->databus_pins[4], (b >> 4) & 1); 39 | mp_hal_pin_write(self->databus_pins[3], (b >> 3) & 1); 40 | mp_hal_pin_write(self->databus_pins[2], (b >> 2) & 1); 41 | mp_hal_pin_write(self->databus_pins[1], (b >> 1) & 1); 42 | mp_hal_pin_write(self->databus_pins[0], b & 1); 43 | last = b; 44 | } 45 | WR_LOW(); 46 | WR_HIGH(); 47 | } 48 | } 49 | 50 | 51 | STATIC void write_color(mp_hal_pin_obj_t *databus, mp_hal_pin_obj_t wr, const uint8_t *buf, int len) 52 | { 53 | static uint8_t last = 0; 54 | uint8_t b; 55 | 56 | for (int i = 0; i < len; i++) { 57 | b = buf[i]; 58 | if (b != last) { 59 | mp_hal_pin_write(databus[7], (b >> 7) & 1); 60 | mp_hal_pin_write(databus[6], (b >> 6) & 1); 61 | mp_hal_pin_write(databus[5], (b >> 5) & 1); 62 | mp_hal_pin_write(databus[4], (b >> 4) & 1); 63 | mp_hal_pin_write(databus[3], (b >> 3) & 1); 64 | mp_hal_pin_write(databus[2], (b >> 2) & 1); 65 | mp_hal_pin_write(databus[1], (b >> 1) & 1); 66 | mp_hal_pin_write(databus[0], b & 1); 67 | last = b; 68 | } 69 | mp_hal_pin_write(wr, 0); 70 | mp_hal_pin_write(wr, 1); 71 | } 72 | } 73 | 74 | 75 | STATIC void write_color_swap_bytes(mp_hal_pin_obj_t *databus, mp_hal_pin_obj_t wr, const uint8_t *buf, int len) 76 | { 77 | static int last = 0; 78 | uint8_t b; 79 | 80 | for (int i = 0; i < len / 2; i++) { 81 | b = buf[i * 2 + 1]; 82 | if (b != last) { 83 | mp_hal_pin_write(databus[7], (b >> 7) & 1); 84 | mp_hal_pin_write(databus[6], (b >> 6) & 1); 85 | mp_hal_pin_write(databus[5], (b >> 5) & 1); 86 | mp_hal_pin_write(databus[4], (b >> 4) & 1); 87 | mp_hal_pin_write(databus[3], (b >> 3) & 1); 88 | mp_hal_pin_write(databus[2], (b >> 2) & 1); 89 | mp_hal_pin_write(databus[1], (b >> 1) & 1); 90 | mp_hal_pin_write(databus[0], b & 1); 91 | last = b; 92 | } 93 | mp_hal_pin_write(wr, 0); 94 | mp_hal_pin_write(wr, 1); 95 | 96 | b = buf[i * 2]; 97 | 98 | if (b != last) { 99 | mp_hal_pin_write(databus[7], (b >> 7) & 1); 100 | mp_hal_pin_write(databus[6], (b >> 6) & 1); 101 | mp_hal_pin_write(databus[5], (b >> 5) & 1); 102 | mp_hal_pin_write(databus[4], (b >> 4) & 1); 103 | mp_hal_pin_write(databus[3], (b >> 3) & 1); 104 | mp_hal_pin_write(databus[2], (b >> 2) & 1); 105 | mp_hal_pin_write(databus[1], (b >> 1) & 1); 106 | mp_hal_pin_write(databus[0], b & 1); 107 | last = b; 108 | } 109 | mp_hal_pin_write(wr, 0); 110 | mp_hal_pin_write(wr, 1); 111 | } 112 | } 113 | 114 | 115 | void hal_lcd_i80_construct(mp_lcd_i80_obj_t *self) { 116 | for (size_t i = 0; i < self->bus_width; i++) 117 | { 118 | self->databus_pins[i] = mp_hal_get_pin_obj(self->databus[i]); 119 | mp_hal_pin_output(self->databus_pins[i]); 120 | } 121 | 122 | self->dc_pin = mp_hal_get_pin_obj(self->dc); 123 | mp_hal_pin_output(self->dc_pin); 124 | 125 | self->wr_pin = mp_hal_get_pin_obj(self->wr); 126 | mp_hal_pin_output(self->wr_pin); 127 | 128 | if (self->cs != MP_OBJ_NULL) { 129 | self->cs_pin = mp_hal_get_pin_obj(self->cs); 130 | mp_hal_pin_output(self->cs_pin); 131 | } else { 132 | self->cs_pin = -1; 133 | } 134 | 135 | if (self->swap_color_bytes) { 136 | self->write_color = write_color_swap_bytes; 137 | } else { 138 | self->write_color = write_color; 139 | } 140 | 141 | CS_HIGH(); 142 | DC_HIGH(); 143 | WR_HIGH(); 144 | // RD_HIGH(); 145 | 146 | mp_hal_pin_write(self->databus_pins[0], 0); 147 | mp_hal_pin_write(self->databus_pins[1], 0); 148 | mp_hal_pin_write(self->databus_pins[2], 0); 149 | mp_hal_pin_write(self->databus_pins[3], 0); 150 | mp_hal_pin_write(self->databus_pins[4], 0); 151 | mp_hal_pin_write(self->databus_pins[5], 0); 152 | mp_hal_pin_write(self->databus_pins[6], 0); 153 | mp_hal_pin_write(self->databus_pins[7], 0); 154 | } 155 | 156 | 157 | void hal_lcd_i80_tx_param(mp_lcd_i80_obj_t *self, int lcd_cmd, const void *param, size_t param_size) { 158 | DEBUG_printf("tx_param cmd: %x, param_size: %u\n", lcd_cmd, param_size); 159 | CS_LOW() 160 | if (lcd_cmd) { 161 | DC_LOW(); 162 | write_bus(self, (uint8_t[]) { lcd_cmd & 0xFF}, 1); 163 | } 164 | 165 | DC_HIGH(); 166 | write_bus(self, param, param_size); 167 | CS_HIGH() 168 | } 169 | 170 | 171 | void hal_lcd_i80_tx_color(mp_lcd_i80_obj_t *self, int lcd_cmd, const void *color, size_t color_size) { 172 | DEBUG_printf("tx_color cmd: %x, color_size: %u\n", lcd_cmd, color_size); 173 | CS_LOW() 174 | if (lcd_cmd) { 175 | DC_LOW(); 176 | write_bus(self, (uint8_t[]) { lcd_cmd & 0xFF }, 1); 177 | } 178 | 179 | DC_HIGH(); 180 | self->write_color(self->databus_pins, self->wr_pin, color, color_size); 181 | CS_HIGH() 182 | } 183 | 184 | 185 | void hal_lcd_i80_deinit(mp_lcd_i80_obj_t *self) { 186 | // esp_lcd_panel_io_del(self->io_handle); 187 | // esp_lcd_del_i80_bus(self->i80_bus); 188 | } 189 | -------------------------------------------------------------------------------- /lcd/hal/common/soft8080.h: -------------------------------------------------------------------------------- 1 | #ifndef SOFT8080_H_ 2 | #define SOFT8080_H_ 3 | 4 | #include "i80_panel.h" 5 | 6 | void hal_lcd_i80_construct(mp_lcd_i80_obj_t *self); 7 | 8 | void hal_lcd_i80_tx_param(mp_lcd_i80_obj_t *self, int lcd_cmd, const void *param, size_t param_size); 9 | 10 | void hal_lcd_i80_tx_color(mp_lcd_i80_obj_t *self, int lcd_cmd, const void *color, size_t color_size); 11 | 12 | void hal_lcd_i80_deinit(mp_lcd_i80_obj_t *self); 13 | 14 | #endif -------------------------------------------------------------------------------- /lcd/hal/common/softspi.c: -------------------------------------------------------------------------------- 1 | #include "softspi.h" 2 | #include "spi_panel.h" 3 | 4 | #include "extmod/machine_spi.h" 5 | #include "py/runtime.h" 6 | 7 | #define DEBUG_printf(...) // mp_printf(&mp_plat_print, __VA_ARGS__); 8 | 9 | #define CS_LOW() \ 10 | { \ 11 | if (spi_panel_obj->cs_pin) { \ 12 | mp_hal_pin_write(spi_panel_obj->cs_pin, 0); \ 13 | } \ 14 | } 15 | 16 | #define CS_HIGH() \ 17 | { \ 18 | if (spi_panel_obj->cs_pin) { \ 19 | mp_hal_pin_write(spi_panel_obj->cs_pin, 1); \ 20 | } \ 21 | } 22 | 23 | #define DC_LOW() \ 24 | { \ 25 | if (spi_panel_obj->dc_pin) { \ 26 | mp_hal_pin_write(spi_panel_obj->dc_pin, 0); \ 27 | } \ 28 | } 29 | 30 | #define DC_HIGH() \ 31 | { \ 32 | if (spi_panel_obj->dc_pin) { \ 33 | mp_hal_pin_write(spi_panel_obj->dc_pin, 1); \ 34 | } \ 35 | } 36 | 37 | void hal_lcd_softspi_panel_construct(mp_obj_base_t *self) 38 | { 39 | mp_lcd_spi_panel_obj_t *spi_panel_obj = (mp_lcd_spi_panel_obj_t *)self; 40 | if (spi_panel_obj->dc != MP_OBJ_NULL) { 41 | spi_panel_obj->dc_pin = mp_hal_get_pin_obj(spi_panel_obj->dc); 42 | mp_hal_pin_output(spi_panel_obj->dc_pin); 43 | } else { 44 | spi_panel_obj->dc_pin = 0; 45 | } 46 | 47 | if (spi_panel_obj->cs != MP_OBJ_NULL) { 48 | spi_panel_obj->cs_pin = mp_hal_get_pin_obj(spi_panel_obj->cs); 49 | mp_hal_pin_output(spi_panel_obj->cs_pin); 50 | } else { 51 | spi_panel_obj->cs_pin = 0; 52 | } 53 | 54 | DC_HIGH(); 55 | CS_HIGH(); 56 | } 57 | 58 | 59 | void hal_lcd_softspi_panel_tx_param(mp_obj_base_t *self, 60 | int lcd_cmd, 61 | const void *param, 62 | size_t param_size) 63 | { 64 | DEBUG_printf("hal_lcd_qspi_panel_tx_param cmd: %x, param_size: %u\n", lcd_cmd, param_size); 65 | 66 | mp_lcd_spi_panel_obj_t *spi_panel_obj = (mp_lcd_spi_panel_obj_t *)self; 67 | #ifdef MP_OBJ_TYPE_GET_SLOT 68 | mp_machine_spi_p_t *spi_p = (mp_machine_spi_p_t *) MP_OBJ_TYPE_GET_SLOT(spi_panel_obj->spi_obj->type, protocol); 69 | #else 70 | mp_machine_spi_p_t *spi_p = (mp_machine_spi_p_t *) spi_panel_obj->spi_obj->type->protocol; 71 | #endif 72 | 73 | CS_LOW() 74 | if (lcd_cmd != -1) { 75 | DC_LOW(); 76 | spi_p->transfer(spi_panel_obj->spi_obj, 1, (uint8_t []) {lcd_cmd & 0xFF}, NULL); 77 | } 78 | if (param_size > 0) { 79 | DC_HIGH(); 80 | spi_p->transfer(spi_panel_obj->spi_obj, param_size, param, NULL); 81 | } 82 | CS_HIGH() 83 | } 84 | 85 | 86 | void hal_lcd_softspi_panel_tx_color(mp_obj_base_t *self, 87 | int lcd_cmd, 88 | const void *color, 89 | size_t color_size) 90 | { 91 | DEBUG_printf("hal_lcd_softspi_panel_tx_color cmd: %x, color_size: %u\n", lcd_cmd, color_size); 92 | 93 | mp_lcd_spi_panel_obj_t *spi_panel_obj = (mp_lcd_spi_panel_obj_t *)self; 94 | #ifdef MP_OBJ_TYPE_GET_SLOT 95 | mp_machine_spi_p_t *spi_p = (mp_machine_spi_p_t *) MP_OBJ_TYPE_GET_SLOT(spi_panel_obj->spi_obj->type, protocol); 96 | #else 97 | mp_machine_spi_p_t *spi_p = (mp_machine_spi_p_t *) spi_panel_obj->spi_obj->type->protocol; 98 | #endif 99 | 100 | CS_LOW() 101 | if (lcd_cmd != -1) { 102 | DC_LOW(); 103 | spi_p->transfer(spi_panel_obj->spi_obj, 1, (uint8_t []) {lcd_cmd & 0xFF}, NULL); 104 | } 105 | if (color_size > 0) { 106 | DC_HIGH(); 107 | spi_p->transfer(spi_panel_obj->spi_obj, color_size, color, NULL); 108 | } 109 | CS_HIGH() 110 | } 111 | 112 | 113 | void hal_lcd_softspi_panel_deinit(mp_obj_base_t *self) 114 | { 115 | 116 | } 117 | -------------------------------------------------------------------------------- /lcd/hal/common/softspi.h: -------------------------------------------------------------------------------- 1 | #ifndef _LCD_SOFTSPI_H_ 2 | #define _LCD_SOFTSPI_H_ 3 | 4 | #include "py/obj.h" 5 | 6 | void hal_lcd_softspi_panel_construct(mp_obj_base_t *self); 7 | 8 | void hal_lcd_softspi_panel_tx_param(mp_obj_base_t *self, 9 | int lcd_cmd, 10 | const void *param, 11 | size_t param_size); 12 | 13 | void hal_lcd_softspi_panel_tx_color(mp_obj_base_t *self, 14 | int lcd_cmd, 15 | const void *color, 16 | size_t color_size); 17 | 18 | void hal_lcd_softspi_panel_deinit(mp_obj_base_t *self); 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /lcd/hal/esp32/esp32.c: -------------------------------------------------------------------------------- 1 | #include "esp32.h" 2 | 3 | #include "spi_panel.h" 4 | #include "qspi_panel.h" 5 | #include "i80_panel.h" 6 | #if DPI_LCD_SUPPORTED 7 | #include "dpi_panel.h" 8 | #endif 9 | 10 | #include "esp_lcd_panel_io.h" 11 | #include "esp_lcd_panel_vendor.h" 12 | #include "esp_lcd_panel_ops.h" 13 | #include "esp_lcd_panel_rgb.h" 14 | 15 | #include "machine_hw_spi.c" 16 | #include "py/runtime.h" 17 | 18 | #define DEBUG_printf(...) // mp_printf(&mp_plat_print, __VA_ARGS__); 19 | 20 | 21 | void hal_lcd_spi_panel_construct(mp_obj_base_t *self) 22 | { 23 | mp_lcd_spi_panel_obj_t *spi_panel_obj = (mp_lcd_spi_panel_obj_t *)self; 24 | machine_hw_spi_obj_t *spi_obj = ((machine_hw_spi_obj_t *)spi_panel_obj->spi_obj); 25 | machine_hw_spi_obj_t old_self = *spi_obj; 26 | if (spi_obj->state == MACHINE_HW_SPI_STATE_INIT) { 27 | spi_obj->state = MACHINE_HW_SPI_STATE_DEINIT; 28 | machine_hw_spi_deinit_internal(&old_self); 29 | } 30 | 31 | spi_bus_config_t buscfg = { 32 | .sclk_io_num = spi_obj->sck, 33 | .mosi_io_num = spi_obj->mosi, 34 | .miso_io_num = -1, 35 | .quadwp_io_num = -1, 36 | .quadhd_io_num = -1, 37 | // .max_transfer_sz = spi_panel_obj->width * spi_panel_obj->height * 2 + 8, 38 | .max_transfer_sz = 0x4000 * 2 + 8, 39 | }; 40 | esp_err_t ret = spi_bus_initialize(spi_obj->host, &buscfg, SPI_DMA_CH_AUTO); 41 | if (ret != 0) { 42 | mp_raise_msg_varg(&mp_type_OSError, "%d(spi_bus_initialize)", ret); 43 | } 44 | spi_obj->state = MACHINE_HW_SPI_STATE_INIT; 45 | 46 | esp_lcd_panel_io_spi_config_t io_config = { 47 | .dc_gpio_num = mp_hal_get_pin_obj(spi_panel_obj->dc), 48 | .cs_gpio_num = mp_hal_get_pin_obj(spi_panel_obj->cs), 49 | .pclk_hz = spi_panel_obj->pclk, 50 | .lcd_cmd_bits = spi_panel_obj->cmd_bits, 51 | .lcd_param_bits = spi_panel_obj->param_bits, 52 | .spi_mode = spi_obj->phase | (spi_obj->polarity << 1), 53 | .flags.lsb_first = spi_obj->firstbit == MICROPY_PY_MACHINE_SPI_LSB ? SPI_DEVICE_TXBIT_LSBFIRST | SPI_DEVICE_RXBIT_LSBFIRST : 0, 54 | .trans_queue_depth = 10, 55 | // .on_color_trans_done = example_notify_lvgl_flush_ready, 56 | .user_ctx = self, 57 | }; 58 | 59 | // Attach the LCD to the SPI bus 60 | ret = esp_lcd_new_panel_io_spi( 61 | (esp_lcd_spi_bus_handle_t)spi_obj->host, 62 | &io_config, 63 | &spi_panel_obj->io_handle 64 | ); 65 | if (ret != 0) { 66 | mp_raise_msg_varg(&mp_type_OSError, "%d(esp_lcd_new_panel_io_spi)", ret); 67 | } 68 | spi_panel_obj->state = LCD_SPI_PANEL_STATE_INIT; 69 | } 70 | 71 | 72 | inline void hal_lcd_spi_panel_tx_param(mp_obj_base_t *self, 73 | int lcd_cmd, 74 | const void *param, 75 | size_t param_size) 76 | { 77 | DEBUG_printf("tx_param cmd: %x, param_size: %u\n", lcd_cmd, param_size); 78 | 79 | mp_lcd_spi_panel_obj_t *spi_panel_obj = (mp_lcd_spi_panel_obj_t *)self; 80 | esp_lcd_panel_io_tx_param(spi_panel_obj->io_handle, lcd_cmd, param, param_size); 81 | } 82 | 83 | 84 | inline void hal_lcd_spi_panel_tx_color(mp_obj_base_t *self, 85 | int lcd_cmd, 86 | const void *color, 87 | size_t color_size) 88 | { 89 | DEBUG_printf("tx_color cmd: %x, color_size: %u\n", lcd_cmd, color_size); 90 | mp_lcd_spi_panel_obj_t *spi_panel_obj = (mp_lcd_spi_panel_obj_t *)self; 91 | esp_lcd_panel_io_tx_color(spi_panel_obj->io_handle, lcd_cmd, color, color_size); 92 | } 93 | 94 | 95 | inline void hal_lcd_spi_panel_deinit(mp_obj_base_t *self) 96 | { 97 | mp_lcd_spi_panel_obj_t *spi_panel_obj = (mp_lcd_spi_panel_obj_t *)self; 98 | if (spi_panel_obj->state == LCD_SPI_PANEL_STATE_INIT) { 99 | spi_panel_obj->state = LCD_SPI_PANEL_STATE_DEINIT; 100 | esp_lcd_panel_io_del(spi_panel_obj->io_handle); 101 | 102 | // esp_lcd_panel_io_del has already executed the operation of spi_bus_remove_device, 103 | // so only need to execute spi_bus_free here. 104 | machine_hw_spi_obj_t *spi_obj = ((machine_hw_spi_obj_t *)spi_panel_obj->spi_obj); 105 | if (spi_obj->state == MACHINE_HW_SPI_STATE_INIT) { 106 | spi_obj->state = MACHINE_HW_SPI_STATE_DEINIT; 107 | 108 | switch (spi_bus_free(spi_obj->host)) { 109 | case ESP_ERR_INVALID_ARG: 110 | mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("invalid configuration")); 111 | return; 112 | 113 | case ESP_ERR_INVALID_STATE: 114 | mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("SPI bus already freed")); 115 | return; 116 | } 117 | 118 | int8_t pins[3] = {spi_obj->miso, spi_obj->mosi, spi_obj->sck}; 119 | 120 | for (int i = 0; i < 3; i++) { 121 | if (pins[i] != -1) { 122 | gpio_pad_select_gpio(pins[i]); 123 | gpio_matrix_out(pins[i], SIG_GPIO_OUT_IDX, false, false); 124 | gpio_set_direction(pins[i], GPIO_MODE_INPUT); 125 | } 126 | } 127 | } 128 | } 129 | } 130 | 131 | 132 | // qspi 133 | void hal_lcd_qspi_panel_construct(mp_obj_base_t *self) 134 | { 135 | mp_lcd_qspi_panel_obj_t *qspi_panel_obj = (mp_lcd_qspi_panel_obj_t *)self; 136 | machine_hw_spi_obj_t *spi_obj = ((machine_hw_spi_obj_t *)qspi_panel_obj->spi_obj); 137 | machine_hw_spi_obj_t old_spi_obj = *spi_obj; 138 | if (spi_obj->state == MACHINE_HW_SPI_STATE_INIT) { 139 | spi_obj->state = MACHINE_HW_SPI_STATE_DEINIT; 140 | machine_hw_spi_deinit_internal(&old_spi_obj); 141 | } 142 | 143 | mp_hal_pin_output(qspi_panel_obj->cs_pin); 144 | mp_hal_pin_od_high(qspi_panel_obj->cs_pin); 145 | 146 | spi_bus_config_t buscfg = { 147 | .data0_io_num = qspi_panel_obj->databus_pins[0], 148 | .data1_io_num = qspi_panel_obj->databus_pins[1], 149 | .sclk_io_num = spi_obj->sck, 150 | .data2_io_num = qspi_panel_obj->databus_pins[2], 151 | .data3_io_num = qspi_panel_obj->databus_pins[3], 152 | .max_transfer_sz = (0x4000 * 16) + 8, 153 | .flags = SPICOMMON_BUSFLAG_MASTER | SPICOMMON_BUSFLAG_GPIO_PINS, 154 | }; 155 | esp_err_t ret = spi_bus_initialize(spi_obj->host, &buscfg, SPI_DMA_CH_AUTO); 156 | if (ret != 0) { 157 | mp_raise_msg_varg(&mp_type_OSError, "%d(spi_bus_initialize)", ret); 158 | } 159 | spi_obj->state = MACHINE_HW_SPI_STATE_INIT; 160 | 161 | spi_device_interface_config_t devcfg = { 162 | .command_bits = qspi_panel_obj->cmd_bits, 163 | .address_bits = 24, 164 | .mode = spi_obj->phase | (spi_obj->polarity << 1), 165 | .clock_speed_hz = qspi_panel_obj->pclk, 166 | .spics_io_num = -1, 167 | .flags = SPI_DEVICE_HALFDUPLEX, 168 | .queue_size = 10, 169 | }; 170 | 171 | ret = spi_bus_add_device(spi_obj->host, &devcfg, &qspi_panel_obj->io_handle); 172 | if (ret != 0) { 173 | mp_raise_msg_varg(&mp_type_OSError, "%d(spi_bus_add_device)", ret); 174 | } 175 | } 176 | 177 | 178 | inline void hal_lcd_qspi_panel_tx_param(mp_obj_base_t *self, 179 | int lcd_cmd, 180 | const void *param, 181 | size_t param_size) 182 | { 183 | DEBUG_printf("hal_lcd_qspi_panel_tx_param cmd: %x, param_size: %u\n", lcd_cmd, param_size); 184 | 185 | mp_lcd_qspi_panel_obj_t *qspi_panel_obj = (mp_lcd_qspi_panel_obj_t *)self; 186 | spi_transaction_t t; 187 | memset(&t, 0, sizeof(t)); 188 | t.flags = (SPI_TRANS_MULTILINE_CMD | SPI_TRANS_MULTILINE_ADDR); 189 | t.cmd = 0x02; 190 | t.addr = lcd_cmd << 8; 191 | if (param_size != 0) { 192 | t.tx_buffer = param; 193 | t.length = qspi_panel_obj->cmd_bits * param_size; 194 | } else { 195 | t.tx_buffer = NULL; 196 | t.length = 0; 197 | } 198 | mp_hal_pin_od_low(qspi_panel_obj->cs_pin); 199 | spi_device_polling_transmit(qspi_panel_obj->io_handle, &t); 200 | mp_hal_pin_od_high(qspi_panel_obj->cs_pin); 201 | } 202 | 203 | 204 | inline void hal_lcd_qspi_panel_tx_color(mp_obj_base_t *self, 205 | int lcd_cmd, 206 | const void *color, 207 | size_t color_size) 208 | { 209 | DEBUG_printf("hal_lcd_qspi_panel_tx_color cmd: %x, color_size: %u\n", lcd_cmd, color_size); 210 | 211 | mp_lcd_qspi_panel_obj_t *qspi_panel_obj = (mp_lcd_qspi_panel_obj_t *)self; 212 | spi_transaction_ext_t t; 213 | 214 | mp_hal_pin_od_low(qspi_panel_obj->cs_pin); 215 | memset(&t, 0, sizeof(t)); 216 | t.base.flags = SPI_TRANS_MODE_QIO; 217 | t.base.cmd = 0x32; 218 | t.base.addr = 0x002C00; 219 | spi_device_polling_transmit(qspi_panel_obj->io_handle, (spi_transaction_t *)&t); 220 | 221 | uint8_t *p_color = (uint8_t *)color; 222 | size_t chunk_size; 223 | size_t len = color_size; 224 | memset(&t, 0, sizeof(t)); 225 | t.base.flags = SPI_TRANS_MODE_QIO | \ 226 | SPI_TRANS_VARIABLE_CMD | \ 227 | SPI_TRANS_VARIABLE_ADDR | \ 228 | SPI_TRANS_VARIABLE_DUMMY; 229 | t.command_bits = 0; 230 | t.address_bits = 0; 231 | t.dummy_bits = 0; 232 | do { 233 | if (len > 0x8000) { 234 | chunk_size = 0x8000; 235 | } else { 236 | chunk_size = len; 237 | } 238 | t.base.tx_buffer = p_color; 239 | t.base.length = chunk_size * 8; 240 | spi_device_polling_transmit(qspi_panel_obj->io_handle, (spi_transaction_t *)&t); 241 | len -= chunk_size; 242 | p_color += chunk_size; 243 | } while (len > 0); 244 | 245 | mp_hal_pin_od_high(qspi_panel_obj->cs_pin); 246 | } 247 | 248 | 249 | inline void hal_lcd_qspi_panel_deinit(mp_obj_base_t *self) 250 | { 251 | // mp_lcd_qspi_panel_obj_t *qspi_panel_obj = (mp_lcd_qspi_panel_obj_t *)self; 252 | // esp_lcd_panel_io_del(qspi_panel_obj->io_handle); 253 | } 254 | 255 | 256 | void hal_lcd_i80_construct(mp_obj_base_t *self) { 257 | mp_lcd_i80_obj_t *i80_obj = (mp_lcd_i80_obj_t *)self; 258 | esp_lcd_i80_bus_config_t bus_config = { 259 | .dc_gpio_num = mp_hal_get_pin_obj(i80_obj->dc), 260 | .wr_gpio_num = mp_hal_get_pin_obj(i80_obj->wr), 261 | .clk_src = LCD_CLK_SRC_PLL160M, 262 | .data_gpio_nums = { 263 | mp_hal_get_pin_obj(i80_obj->databus[0]), 264 | mp_hal_get_pin_obj(i80_obj->databus[1]), 265 | mp_hal_get_pin_obj(i80_obj->databus[2]), 266 | mp_hal_get_pin_obj(i80_obj->databus[3]), 267 | mp_hal_get_pin_obj(i80_obj->databus[4]), 268 | mp_hal_get_pin_obj(i80_obj->databus[5]), 269 | mp_hal_get_pin_obj(i80_obj->databus[6]), 270 | mp_hal_get_pin_obj(i80_obj->databus[7]), 271 | }, 272 | .bus_width = i80_obj->bus_width, 273 | .max_transfer_bytes = i80_obj->width * i80_obj->height * sizeof(uint16_t) 274 | }; 275 | esp_err_t ret = esp_lcd_new_i80_bus(&bus_config, &i80_obj->i80_bus); 276 | if (ret != 0) { 277 | mp_raise_msg_varg(&mp_type_OSError, "%d(esp_lcd_new_i80_bus)", ret); 278 | } 279 | esp_lcd_panel_io_i80_config_t io_config = { 280 | .pclk_hz = i80_obj->pclk, 281 | .trans_queue_depth = 10, 282 | .dc_levels = { 283 | .dc_idle_level = 0, 284 | .dc_cmd_level = 0, 285 | .dc_dummy_level = 0, 286 | .dc_data_level = 1, 287 | }, 288 | .flags = { 289 | .swap_color_bytes = i80_obj->swap_color_bytes, 290 | }, 291 | .lcd_cmd_bits = i80_obj->cmd_bits, 292 | .lcd_param_bits = i80_obj->param_bits, 293 | }; 294 | if (i80_obj->cs != MP_OBJ_NULL) { 295 | io_config.cs_gpio_num = mp_hal_get_pin_obj(i80_obj->cs); 296 | } else { 297 | io_config.cs_gpio_num = -1; 298 | } 299 | ret = esp_lcd_new_panel_io_i80(i80_obj->i80_bus, &io_config, &i80_obj->io_handle); 300 | if (ret != 0) { 301 | mp_raise_msg_varg(&mp_type_OSError, "%d(esp_lcd_new_panel_io_i80)", ret); 302 | } 303 | } 304 | 305 | 306 | inline void hal_lcd_i80_tx_param( 307 | mp_obj_base_t *self, 308 | int lcd_cmd, 309 | const void *param, 310 | size_t param_size 311 | ) { 312 | DEBUG_printf("tx_param cmd: %x, param_size: %u\n", lcd_cmd, param_size); 313 | 314 | mp_lcd_i80_obj_t *i80_obj = (mp_lcd_i80_obj_t *)self; 315 | esp_lcd_panel_io_tx_param(i80_obj->io_handle, lcd_cmd, param, param_size); 316 | } 317 | 318 | 319 | inline void hal_lcd_i80_tx_color( 320 | mp_obj_base_t *self, 321 | int lcd_cmd, 322 | const void *color, 323 | size_t color_size 324 | ) { 325 | DEBUG_printf("tx_color cmd: %x, color_size: %u\n", lcd_cmd, color_size); 326 | 327 | mp_lcd_i80_obj_t *i80_obj = (mp_lcd_i80_obj_t *)self; 328 | esp_lcd_panel_io_tx_color(i80_obj->io_handle, lcd_cmd, color, color_size); 329 | } 330 | 331 | 332 | inline void hal_lcd_i80_deinit(mp_obj_base_t *self) { 333 | mp_lcd_i80_obj_t *i80_obj = (mp_lcd_i80_obj_t *)self; 334 | esp_lcd_panel_io_del(i80_obj->io_handle); 335 | esp_lcd_del_i80_bus(i80_obj->i80_bus); 336 | } 337 | 338 | 339 | #if DPI_LCD_SUPPORTED 340 | void hal_lcd_dpi_construct(mp_obj_base_t *self) 341 | { 342 | mp_lcd_dpi_obj_t *dpi_obj = (mp_lcd_dpi_obj_t *)self; 343 | esp_lcd_rgb_panel_config_t panel_config = { 344 | .clk_src = LCD_CLK_SRC_PLL160M, 345 | .timings = { 346 | .pclk_hz = dpi_obj->pclk, 347 | .h_res = dpi_obj->width, 348 | .v_res = dpi_obj->height, 349 | // The following parameters should refer to LCD spec 350 | .hsync_pulse_width = dpi_obj->timings.hsync_pulse_width, 351 | .hsync_back_porch = dpi_obj->timings.hsync_back_porch, 352 | .hsync_front_porch = dpi_obj->timings.hsync_front_porch, 353 | .vsync_pulse_width = dpi_obj->timings.vsync_pulse_width, 354 | .vsync_back_porch = dpi_obj->timings.vsync_back_porch, 355 | .vsync_front_porch = dpi_obj->timings.vsync_front_porch, 356 | .flags = { 357 | .pclk_active_neg = 1, 358 | }, 359 | }, 360 | .data_width = dpi_obj->bus_width, // RGB565 in parallel mode, thus 16bit in width 361 | .psram_trans_align = 64, 362 | .hsync_gpio_num = mp_hal_get_pin_obj(dpi_obj->hsync_obj), 363 | .vsync_gpio_num = mp_hal_get_pin_obj(dpi_obj->vsync_obj), 364 | .de_gpio_num = mp_hal_get_pin_obj(dpi_obj->de_obj), 365 | .pclk_gpio_num = mp_hal_get_pin_obj(dpi_obj->pclk_obj), 366 | .data_gpio_nums = { 367 | mp_hal_get_pin_obj(dpi_obj->databus_obj[0]), 368 | mp_hal_get_pin_obj(dpi_obj->databus_obj[1]), 369 | mp_hal_get_pin_obj(dpi_obj->databus_obj[2]), 370 | mp_hal_get_pin_obj(dpi_obj->databus_obj[3]), 371 | mp_hal_get_pin_obj(dpi_obj->databus_obj[4]), 372 | mp_hal_get_pin_obj(dpi_obj->databus_obj[5]), 373 | mp_hal_get_pin_obj(dpi_obj->databus_obj[6]), 374 | mp_hal_get_pin_obj(dpi_obj->databus_obj[7]), 375 | mp_hal_get_pin_obj(dpi_obj->databus_obj[8]), 376 | mp_hal_get_pin_obj(dpi_obj->databus_obj[9]), 377 | mp_hal_get_pin_obj(dpi_obj->databus_obj[10]), 378 | mp_hal_get_pin_obj(dpi_obj->databus_obj[11]), 379 | mp_hal_get_pin_obj(dpi_obj->databus_obj[12]), 380 | mp_hal_get_pin_obj(dpi_obj->databus_obj[13]), 381 | mp_hal_get_pin_obj(dpi_obj->databus_obj[14]), 382 | mp_hal_get_pin_obj(dpi_obj->databus_obj[15]), 383 | }, 384 | .disp_gpio_num = dpi_obj->disp_pin, 385 | .on_frame_trans_done = NULL, 386 | .user_ctx = NULL, 387 | .flags = { 388 | .fb_in_psram = 1, // allocate frame buffer in PSRAM 389 | }, 390 | }; 391 | esp_err_t ret = esp_lcd_new_rgb_panel(&panel_config, &dpi_obj->panel_handle); 392 | if (ret != 0) { 393 | mp_raise_msg_varg(&mp_type_OSError, "%d(esp_lcd_new_rgb_panel)", ret); 394 | } 395 | ret = esp_lcd_panel_reset(dpi_obj->panel_handle); 396 | if (ret != 0) { 397 | mp_raise_msg_varg(&mp_type_OSError, "%d(esp_lcd_panel_reset)", ret); 398 | } 399 | ret = esp_lcd_panel_init(dpi_obj->panel_handle); 400 | if (ret != 0) { 401 | mp_raise_msg_varg(&mp_type_OSError, "%d(esp_lcd_panel_init)", ret); 402 | } 403 | } 404 | 405 | 406 | inline void hal_lcd_dpi_reset(mp_obj_base_t *self) 407 | { 408 | mp_lcd_dpi_obj_t *dpi_obj = (mp_lcd_dpi_obj_t *)self; 409 | esp_lcd_panel_reset(dpi_obj->panel_handle); 410 | } 411 | 412 | 413 | inline void hal_lcd_dpi_init(mp_obj_base_t *self) 414 | { 415 | mp_lcd_dpi_obj_t *dpi_obj = (mp_lcd_dpi_obj_t *)self; 416 | esp_lcd_panel_init(dpi_obj->panel_handle); 417 | } 418 | 419 | 420 | inline void hal_lcd_dpi_del(mp_obj_base_t *self) 421 | { 422 | mp_lcd_dpi_obj_t *dpi_obj = (mp_lcd_dpi_obj_t *)self; 423 | esp_lcd_panel_del(dpi_obj->panel_handle); 424 | } 425 | 426 | 427 | inline void hal_lcd_dpi_bitmap(mp_obj_base_t *self, 428 | int x_start, 429 | int y_start, 430 | int x_end, 431 | int y_end, 432 | const void *color_data) 433 | { 434 | mp_lcd_dpi_obj_t *dpi_obj = (mp_lcd_dpi_obj_t *)self; 435 | esp_lcd_panel_draw_bitmap( 436 | dpi_obj->panel_handle, 437 | x_start, 438 | y_start, 439 | x_end, 440 | y_end, 441 | color_data 442 | ); 443 | } 444 | 445 | 446 | inline void hal_lcd_dpi_mirror(mp_obj_base_t *self, 447 | bool mirror_x, 448 | bool mirror_y) 449 | { 450 | mp_lcd_dpi_obj_t *dpi_obj = (mp_lcd_dpi_obj_t *)self; 451 | esp_lcd_panel_mirror(dpi_obj->panel_handle, mirror_x, mirror_y); 452 | } 453 | 454 | 455 | inline void hal_lcd_dpi_swap_xy(mp_obj_base_t *self, bool swap_axes) 456 | { 457 | mp_lcd_dpi_obj_t *dpi_obj = (mp_lcd_dpi_obj_t *)self; 458 | esp_lcd_panel_swap_xy(dpi_obj->panel_handle, swap_axes); 459 | } 460 | 461 | 462 | inline void hal_lcd_dpi_set_gap(mp_obj_base_t *self, int x_gap, int y_gap) 463 | { 464 | mp_lcd_dpi_obj_t *dpi_obj = (mp_lcd_dpi_obj_t *)self; 465 | esp_lcd_panel_set_gap(dpi_obj->panel_handle, x_gap, y_gap); 466 | } 467 | 468 | 469 | inline void hal_lcd_dpi_invert_color(mp_obj_base_t *self, bool invert_color_data) 470 | { 471 | mp_lcd_dpi_obj_t *dpi_obj = (mp_lcd_dpi_obj_t *)self; 472 | esp_lcd_panel_invert_color(dpi_obj->panel_handle, invert_color_data); 473 | } 474 | 475 | 476 | inline void hal_lcd_dpi_disp_off(mp_obj_base_t *self, bool off) 477 | { 478 | mp_lcd_dpi_obj_t *dpi_obj = (mp_lcd_dpi_obj_t *)self; 479 | esp_lcd_panel_disp_off(dpi_obj->panel_handle, off); 480 | } 481 | #endif -------------------------------------------------------------------------------- /lcd/hal/esp32/esp32.h: -------------------------------------------------------------------------------- 1 | #ifndef _ESP32_H_ 2 | #define _ESP32_H_ 3 | 4 | #include "py/obj.h" 5 | 6 | // spi 7 | void hal_lcd_spi_panel_construct(mp_obj_base_t *self); 8 | 9 | void hal_lcd_spi_panel_tx_param( 10 | mp_obj_base_t *self, 11 | int lcd_cmd, 12 | const void *param, 13 | size_t param_size 14 | ); 15 | 16 | void hal_lcd_spi_panel_tx_color( 17 | mp_obj_base_t *self, 18 | int lcd_cmd, 19 | const void *color, 20 | size_t color_size 21 | ); 22 | 23 | void hal_lcd_spi_panel_deinit(mp_obj_base_t *self); 24 | 25 | // qspi 26 | void hal_lcd_qspi_panel_construct(mp_obj_base_t *self); 27 | 28 | void hal_lcd_qspi_panel_tx_param( 29 | mp_obj_base_t *self, 30 | int lcd_cmd, 31 | const void *param, 32 | size_t param_size 33 | ); 34 | 35 | void hal_lcd_qspi_panel_tx_color( 36 | mp_obj_base_t *self, 37 | int lcd_cmd, 38 | const void *color, 39 | size_t color_size 40 | ); 41 | 42 | void hal_lcd_qspi_panel_deinit(mp_obj_base_t *self); 43 | 44 | // i8080 45 | void hal_lcd_i80_construct(mp_obj_base_t *self); 46 | 47 | void hal_lcd_i80_tx_param( 48 | mp_obj_base_t *self, 49 | int lcd_cmd, 50 | const void *param, 51 | size_t param_size 52 | ); 53 | 54 | void hal_lcd_i80_tx_color( 55 | mp_obj_base_t *self, 56 | int lcd_cmd, 57 | const void *color, 58 | size_t color_size 59 | ); 60 | 61 | void hal_lcd_i80_deinit(mp_obj_base_t *self); 62 | 63 | // dpi 64 | void hal_lcd_dpi_construct(mp_obj_base_t *self); 65 | 66 | void hal_lcd_dpi_reset(mp_obj_base_t *self); 67 | 68 | void hal_lcd_dpi_init(mp_obj_base_t *self); 69 | 70 | void hal_lcd_dpi_del(mp_obj_base_t *self); 71 | 72 | void hal_lcd_dpi_bitmap( 73 | mp_obj_base_t *self, 74 | int x_start, 75 | int y_start, 76 | int x_end, 77 | int y_end, 78 | const void *color_data 79 | ); 80 | 81 | void hal_lcd_dpi_mirror(mp_obj_base_t *self, bool mirror_x, bool mirror_y); 82 | 83 | void hal_lcd_dpi_swap_xy(mp_obj_base_t *self, bool swap_axes); 84 | 85 | void hal_lcd_dpi_set_gap(mp_obj_base_t *self, int x_gap, int y_gap); 86 | 87 | void hal_lcd_dpi_invert_color(mp_obj_base_t *self, bool invert_color_data); 88 | 89 | void hal_lcd_dpi_disp_off(mp_obj_base_t *self, bool off); 90 | 91 | #endif -------------------------------------------------------------------------------- /lcd/micropython.cmake: -------------------------------------------------------------------------------- 1 | 2 | # Create an INTERFACE library for our C module. 3 | add_library(usermod_lcd INTERFACE) 4 | 5 | # user configure 6 | set(set CONFIG_LCD_BUS_SPI 1) 7 | set(set CONFIG_LCD_BUS_QSPI 1) 8 | set(set CONFIG_LCD_BUS_I80 1) 9 | set(set CONFIG_LCD_BUS_DPI 1) 10 | set(set CONFIG_LCD_DRIVER_ILI9488 1) 11 | set(set CONFIG_LCD_DRIVER_RM67162 1) 12 | set(set CONFIG_LCD_DRIVER_ST7735 1) 13 | set(set CONFIG_LCD_DRIVER_ST7789 1) 14 | 15 | # hal layer 16 | set(HAL_DIR ${CMAKE_CURRENT_LIST_DIR}/hal) 17 | set(ESP32_HAL_SRC ${HAL_DIR}/esp32/esp32.c) 18 | set(ESP32_HAL_INC ${HAL_DIR}/esp32) 19 | set(COMMON_HAL_SRC ${HAL_DIR}/common/softspi.c) 20 | set(COMMON_HAL_INC ${HAL_DIR}/common) 21 | 22 | # bus layer 23 | set(BUS_DIR ${CMAKE_CURRENT_LIST_DIR}/bus) 24 | set(COMMON_BUS_INC ${BUS_DIR}/common) 25 | set(SPI_BUS_SRC ${BUS_DIR}/spi/spi_panel.c) 26 | set(SPI_BUS_INC ${BUS_DIR}/spi) 27 | set(QSPI_BUS_SRC ${BUS_DIR}/qspi/qspi_panel.c) 28 | set(QSPI_BUS_INC ${BUS_DIR}/qspi) 29 | set(I8080_BUS_SRC ${BUS_DIR}/i80/i80_panel.c) 30 | set(I8080_BUS_INC ${BUS_DIR}/i80) 31 | set(DPI_BUS_SRC ${BUS_DIR}/dpi/dpi_panel.c) 32 | set(DPI_BUS_INC ${BUS_DIR}/dpi) 33 | 34 | # driver layer 35 | set(DRIVER_DIR ${CMAKE_CURRENT_LIST_DIR}/driver) 36 | set(DRIVER_COMMON_SRC ${DRIVER_DIR}/common/lcd_panel_types.c) 37 | set(DRIVER_COMMON_INC ${DRIVER_DIR}/common) 38 | set(ST7735_DRIVER_SRC ${DRIVER_DIR}/st7735/st7735.c) 39 | set(ST7735_DRIVER_INC ${DRIVER_DIR}/st7735) 40 | set(ST7789_DRIVER_SRC ${DRIVER_DIR}/st7789/st7789.c) 41 | set(ST7789_DRIVER_INC ${DRIVER_DIR}/st7789) 42 | set(ILI9488_DRIVER_SRC ${DRIVER_DIR}/ili9488/ili9488.c) 43 | set(ILI9488_DRIVER_INC ${DRIVER_DIR}/ili9488) 44 | set(RM67162_DRIVER_SRC ${DRIVER_DIR}/rm67162/rm67162.c) 45 | set(RM67162_DRIVER_INC ${DRIVER_DIR}/rm67162) 46 | set(GC9A01_DRIVER_SRC ${DRIVER_DIR}/gc9a01/gc9a01.c) 47 | set(GC9A01_DRIVER_INC ${DRIVER_DIR}/gc9a01) 48 | 49 | # Add our source files to the lib 50 | set(SRC ${CMAKE_CURRENT_LIST_DIR}/modlcd.c) 51 | LIST(APPEND SRC ${ESP32_HAL_SRC}) 52 | LIST(APPEND SRC ${COMMON_HAL_SRC}) 53 | LIST(APPEND SRC ${SPI_BUS_SRC}) 54 | LIST(APPEND SRC ${QSPI_BUS_SRC}) 55 | LIST(APPEND SRC ${I8080_BUS_SRC}) 56 | LIST(APPEND SRC ${DRIVER_COMMON_SRC}) 57 | LIST(APPEND SRC ${ST7735_DRIVER_SRC}) 58 | LIST(APPEND SRC ${ST7789_DRIVER_SRC}) 59 | LIST(APPEND SRC ${ILI9488_DRIVER_SRC}) 60 | LIST(APPEND SRC ${RM67162_DRIVER_SRC}) 61 | LIST(APPEND SRC ${GC9A01_DRIVER_SRC}) 62 | 63 | set(INC ${CMAKE_CURRENT_LIST_DIR} ${HAL_DIR}/esp32) 64 | LIST(APPEND INC ${ESP32_HAL_INC}) 65 | LIST(APPEND INC ${COMMON_HAL_INC}) 66 | LIST(APPEND INC ${COMMON_BUS_INC}) 67 | LIST(APPEND INC ${SPI_BUS_INC}) 68 | LIST(APPEND INC ${QSPI_BUS_INC}) 69 | LIST(APPEND INC ${I8080_BUS_INC}) 70 | LIST(APPEND INC ${DRIVER_COMMON_INC}) 71 | LIST(APPEND INC ${ST7735_DRIVER_INC}) 72 | LIST(APPEND INC ${ST7789_DRIVER_INC}) 73 | LIST(APPEND INC ${ILI9488_DRIVER_INC}) 74 | LIST(APPEND INC ${RM67162_DRIVER_INC}) 75 | LIST(APPEND INC ${GC9A01_DRIVER_INC}) 76 | 77 | if (CONFIG_IDF_TARGET_ESP32 OR CONFIG_IDF_TARGET_ESP32S3) 78 | target_compile_definitions(usermod_lcd INTERFACE USE_ESP_LCD=1) 79 | if (CONFIG_IDF_TARGET_ESP32S3) 80 | LIST(APPEND SRC ${DPI_BUS_SRC}) 81 | LIST(APPEND INC ${DPI_BUS_INC}) 82 | target_compile_definitions(usermod_lcd INTERFACE DPI_LCD_SUPPORTED=1) 83 | endif() 84 | endif() 85 | 86 | target_sources(usermod_lcd INTERFACE ${SRC}) 87 | target_compile_options(usermod_lcd INTERFACE "-g") 88 | # Add the current directory as an include directory. 89 | target_include_directories(usermod_lcd INTERFACE ${INC}) 90 | 91 | # Link our INTERFACE library to the usermod target. 92 | target_link_libraries(usermod INTERFACE usermod_lcd) 93 | -------------------------------------------------------------------------------- /lcd/modlcd.c: -------------------------------------------------------------------------------- 1 | 2 | #include "st7789.h" 3 | #include "st7735.h" 4 | #include "ili9488.h" 5 | #include "rm67162.h" 6 | #include "gc9a01.h" 7 | #include "spi_panel.h" 8 | #include "qspi_panel.h" 9 | #include "i80_panel.h" 10 | #if DPI_LCD_SUPPORTED 11 | #include "dpi_panel.h" 12 | #endif 13 | #include "lcd_panel_types.h" 14 | 15 | #include "py/obj.h" 16 | 17 | STATIC const mp_map_elem_t mp_module_lcd_globals_table[] = { 18 | { MP_ROM_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_lcd) }, 19 | { MP_ROM_QSTR(MP_QSTR_ST7789), (mp_obj_t)&mp_lcd_st7789_type }, 20 | { MP_ROM_QSTR(MP_QSTR_ST7735), (mp_obj_t)&mp_lcd_st7735_type }, 21 | { MP_ROM_QSTR(MP_QSTR_ILI9488), (mp_obj_t)&mp_lcd_ili9488_type }, 22 | { MP_ROM_QSTR(MP_QSTR_RM67162), (mp_obj_t)&mp_lcd_rm67162_type }, 23 | { MP_ROM_QSTR(MP_QSTR_GC9A01), (mp_obj_t)&mp_lcd_gc9a01_type }, 24 | { MP_ROM_QSTR(MP_QSTR_I8080), (mp_obj_t)&mp_lcd_i80_type }, 25 | { MP_ROM_QSTR(MP_QSTR_SPIPanel), (mp_obj_t)&mp_lcd_spi_panel_type }, 26 | { MP_ROM_QSTR(MP_QSTR_QSPIPanel), (mp_obj_t)&mp_lcd_qspi_panel_type }, 27 | #if DPI_LCD_SUPPORTED 28 | { MP_ROM_QSTR(MP_QSTR_DPI), (mp_obj_t)&mp_lcd_dpi_type }, 29 | #endif 30 | 31 | { MP_ROM_QSTR(MP_QSTR_RGB), MP_ROM_INT(COLOR_SPACE_RGB) }, 32 | { MP_ROM_QSTR(MP_QSTR_BGR), MP_ROM_INT(COLOR_SPACE_BGR) }, 33 | { MP_ROM_QSTR(MP_QSTR_MONOCHROME), MP_ROM_INT(COLOR_SPACE_MONOCHROME) }, 34 | }; 35 | STATIC MP_DEFINE_CONST_DICT(mp_module_lcd_globals, mp_module_lcd_globals_table); 36 | 37 | 38 | const mp_obj_module_t mp_module_lcd = { 39 | .base = {&mp_type_module}, 40 | .globals = (mp_obj_dict_t *)&mp_module_lcd_globals, 41 | }; 42 | 43 | 44 | #if MICROPY_VERSION >= 0x011300 // MicroPython 1.19 or later 45 | MP_REGISTER_MODULE(MP_QSTR_lcd, mp_module_lcd); 46 | #else 47 | MP_REGISTER_MODULE(MP_QSTR_lcd, mp_module_lcd, MODULE_LCD_ENABLE); 48 | #endif 49 | --------------------------------------------------------------------------------