First commit
I shall move all this to another branch -> master_vendored or something
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
.pio
|
||||
.clang_complete
|
||||
.gcc-flags.json
|
||||
.ccls
|
||||
@@ -0,0 +1,22 @@
|
||||
# Uncomment lines below if you have problems with $PATH
|
||||
#SHELL := /bin/bash
|
||||
#PATH := /usr/local/bin:$(PATH)
|
||||
|
||||
all:
|
||||
pio -f -c vim run
|
||||
|
||||
upload:
|
||||
pio -f -c vim run --target upload
|
||||
|
||||
clean:
|
||||
pio -f -c vim run --target clean
|
||||
|
||||
program:
|
||||
pio -f -c vim run --target program
|
||||
|
||||
uploadfs:
|
||||
pio -f -c vim run --target uploadfs
|
||||
|
||||
update:
|
||||
pio -f -c vim update
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
RX 18 -> yellow -> green
|
||||
TX 19 -> blue -> white
|
||||
|
||||
### Cool fonts I like:
|
||||
- u8g2_font_bubble_tr (really cool for splash screens)
|
||||
- u8g2_font_helvR10_tr (very readable, should really try this one)
|
||||
- u8g2_font_6x12_tf (monospace)
|
||||
|
||||
### Weird font rendering stuff going on
|
||||
When the cursor is set to a position, the text will actually render
|
||||
from the left bottom corner, so 0,0 will actually render text that
|
||||
can't be viewed.
|
||||
Solution, for now:
|
||||
```cpp
|
||||
U8G2 u8g2;
|
||||
u8g2.setFont(u8g2_font_9x18_tf);
|
||||
int ascent = u8g2.getAscent();
|
||||
// will probably vary from font to font tho, right now I'm using
|
||||
// monospace and that's enough
|
||||
```
|
||||
@@ -0,0 +1,39 @@
|
||||
|
||||
This directory is intended for project header files.
|
||||
|
||||
A header file is a file containing C declarations and macro definitions
|
||||
to be shared between several project source files. You request the use of a
|
||||
header file in your project source file (C, C++, etc) located in `src` folder
|
||||
by including it, with the C preprocessing directive `#include'.
|
||||
|
||||
```src/main.c
|
||||
|
||||
#include "header.h"
|
||||
|
||||
int main (void)
|
||||
{
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
Including a header file produces the same results as copying the header file
|
||||
into each source file that needs it. Such copying would be time-consuming
|
||||
and error-prone. With a header file, the related declarations appear
|
||||
in only one place. If they need to be changed, they can be changed in one
|
||||
place, and programs that include the header file will automatically use the
|
||||
new version when next recompiled. The header file eliminates the labor of
|
||||
finding and changing all the copies as well as the risk that a failure to
|
||||
find one copy will result in inconsistencies within a program.
|
||||
|
||||
In C, the usual convention is to give header files names that end with `.h'.
|
||||
It is most portable to use only letters, digits, dashes, and underscores in
|
||||
header file names, and at most one dot.
|
||||
|
||||
Read more about using header files in official GCC documentation:
|
||||
|
||||
* Include Syntax
|
||||
* Include Operation
|
||||
* Once-Only Headers
|
||||
* Computed Includes
|
||||
|
||||
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
|
||||
@@ -0,0 +1,13 @@
|
||||
/*******************************************************************************
|
||||
* Touch libraries:
|
||||
* FT6X36: https://github.com/strange-v/FT6X36.git
|
||||
* GT911: https://github.com/TAMCTec/gt911-arduino.git
|
||||
* XPT2046: https://github.com/PaulStoffregen/XPT2046_Touchscreen.git
|
||||
******************************************************************************/
|
||||
|
||||
/* uncomment for GT911 */
|
||||
#define TOUCH_GT911
|
||||
#define TOUCH_GT911_SCL 20
|
||||
#define TOUCH_GT911_SDA 19
|
||||
#define TOUCH_GT911_INT -1
|
||||
#define TOUCH_GT911_RST 38
|
||||
@@ -0,0 +1,988 @@
|
||||
/**
|
||||
* @file lv_conf.h
|
||||
* Configuration file for v9.1.0
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copy this file as `lv_conf.h`
|
||||
* 1. simply next to the `lvgl` folder
|
||||
* 2. or any other places and
|
||||
* - define `LV_CONF_INCLUDE_SIMPLE`
|
||||
* - add the path as include path
|
||||
*/
|
||||
|
||||
/* clang-format off */
|
||||
#if 1 /*Set it to "1" to enable content*/
|
||||
|
||||
#ifndef LV_CONF_H
|
||||
#define LV_CONF_H
|
||||
|
||||
/*If you need to include anything here, do it inside the `__ASSEMBLY__` guard */
|
||||
#if 0 && defined(__ASSEMBLY__)
|
||||
#include "my_include.h"
|
||||
#endif
|
||||
|
||||
/*====================
|
||||
COLOR SETTINGS
|
||||
*====================*/
|
||||
|
||||
/*Color depth: 8 (A8), 16 (RGB565), 24 (RGB888), 32 (XRGB8888)*/
|
||||
#define LV_COLOR_DEPTH 16
|
||||
|
||||
/*=========================
|
||||
STDLIB WRAPPER SETTINGS
|
||||
*=========================*/
|
||||
|
||||
/* Possible values
|
||||
* - LV_STDLIB_BUILTIN: LVGL's built in implementation
|
||||
* - LV_STDLIB_CLIB: Standard C functions, like malloc, strlen, etc
|
||||
* - LV_STDLIB_MICROPYTHON: MicroPython implementation
|
||||
* - LV_STDLIB_RTTHREAD: RT-Thread implementation
|
||||
* - LV_STDLIB_CUSTOM: Implement the functions externally
|
||||
*/
|
||||
#define LV_USE_STDLIB_MALLOC LV_STDLIB_BUILTIN
|
||||
#define LV_USE_STDLIB_STRING LV_STDLIB_BUILTIN
|
||||
#define LV_USE_STDLIB_SPRINTF LV_STDLIB_BUILTIN
|
||||
|
||||
|
||||
#if LV_USE_STDLIB_MALLOC == LV_STDLIB_BUILTIN
|
||||
/*Size of the memory available for `lv_malloc()` in bytes (>= 2kB)*/
|
||||
#define LV_MEM_SIZE (64 * 1024U) /*[bytes]*/
|
||||
|
||||
/*Size of the memory expand for `lv_malloc()` in bytes*/
|
||||
#define LV_MEM_POOL_EXPAND_SIZE 0
|
||||
|
||||
/*Set an address for the memory pool instead of allocating it as a normal array. Can be in external SRAM too.*/
|
||||
#define LV_MEM_ADR 0 /*0: unused*/
|
||||
/*Instead of an address give a memory allocator that will be called to get a memory pool for LVGL. E.g. my_malloc*/
|
||||
#if LV_MEM_ADR == 0
|
||||
#undef LV_MEM_POOL_INCLUDE
|
||||
#undef LV_MEM_POOL_ALLOC
|
||||
#endif
|
||||
#endif /*LV_USE_STDLIB_MALLOC == LV_STDLIB_BUILTIN*/
|
||||
|
||||
/*====================
|
||||
HAL SETTINGS
|
||||
*====================*/
|
||||
|
||||
/*Default display refresh, input device read and animation step period.*/
|
||||
#define LV_DEF_REFR_PERIOD 33 /*[ms]*/
|
||||
|
||||
/*Default Dot Per Inch. Used to initialize default sizes such as widgets sized, style paddings.
|
||||
*(Not so important, you can adjust it to modify default sizes and spaces)*/
|
||||
#define LV_DPI_DEF 130 /*[px/inch]*/
|
||||
|
||||
/*=================
|
||||
* OPERATING SYSTEM
|
||||
*=================*/
|
||||
/*Select an operating system to use. Possible options:
|
||||
* - LV_OS_NONE
|
||||
* - LV_OS_PTHREAD
|
||||
* - LV_OS_FREERTOS
|
||||
* - LV_OS_CMSIS_RTOS2
|
||||
* - LV_OS_RTTHREAD
|
||||
* - LV_OS_WINDOWS
|
||||
* - LV_OS_CUSTOM */
|
||||
#define LV_USE_OS LV_OS_NONE
|
||||
|
||||
#if LV_USE_OS == LV_OS_CUSTOM
|
||||
#define LV_OS_CUSTOM_INCLUDE <stdint.h>
|
||||
#endif
|
||||
|
||||
/*========================
|
||||
* RENDERING CONFIGURATION
|
||||
*========================*/
|
||||
|
||||
/*Align the stride of all layers and images to this bytes*/
|
||||
#define LV_DRAW_BUF_STRIDE_ALIGN 1
|
||||
|
||||
/*Align the start address of draw_buf addresses to this bytes*/
|
||||
#define LV_DRAW_BUF_ALIGN 4
|
||||
|
||||
/* If a widget has `style_opa < 255` (not `bg_opa`, `text_opa` etc) or not NORMAL blend mode
|
||||
* it is buffered into a "simple" layer before rendering. The widget can be buffered in smaller chunks.
|
||||
* "Transformed layers" (if `transform_angle/zoom` are set) use larger buffers
|
||||
* and can't be drawn in chunks. */
|
||||
|
||||
/*The target buffer size for simple layer chunks.*/
|
||||
#define LV_DRAW_LAYER_SIMPLE_BUF_SIZE (24 * 1024) /*[bytes]*/
|
||||
|
||||
#define LV_USE_DRAW_SW 1
|
||||
#if LV_USE_DRAW_SW == 1
|
||||
/* Set the number of draw unit.
|
||||
* > 1 requires an operating system enabled in `LV_USE_OS`
|
||||
* > 1 means multiply threads will render the screen in parallel */
|
||||
#define LV_DRAW_SW_DRAW_UNIT_CNT 1
|
||||
|
||||
/* Use Arm-2D to accelerate the sw render */
|
||||
#define LV_USE_DRAW_ARM2D_SYNC 0
|
||||
|
||||
/* Enable native helium assembly to be compiled */
|
||||
#define LV_USE_NATIVE_HELIUM_ASM 0
|
||||
|
||||
/* 0: use a simple renderer capable of drawing only simple rectangles with gradient, images, texts, and straight lines only
|
||||
* 1: use a complex renderer capable of drawing rounded corners, shadow, skew lines, and arcs too */
|
||||
#define LV_DRAW_SW_COMPLEX 1
|
||||
|
||||
#if LV_DRAW_SW_COMPLEX == 1
|
||||
/*Allow buffering some shadow calculation.
|
||||
*LV_DRAW_SW_SHADOW_CACHE_SIZE is the max. shadow size to buffer, where shadow size is `shadow_width + radius`
|
||||
*Caching has LV_DRAW_SW_SHADOW_CACHE_SIZE^2 RAM cost*/
|
||||
#define LV_DRAW_SW_SHADOW_CACHE_SIZE 0
|
||||
|
||||
/* Set number of maximally cached circle data.
|
||||
* The circumference of 1/4 circle are saved for anti-aliasing
|
||||
* radius * 4 bytes are used per circle (the most often used radiuses are saved)
|
||||
* 0: to disable caching */
|
||||
#define LV_DRAW_SW_CIRCLE_CACHE_SIZE 4
|
||||
#endif
|
||||
|
||||
#define LV_USE_DRAW_SW_ASM LV_DRAW_SW_ASM_NONE
|
||||
|
||||
#if LV_USE_DRAW_SW_ASM == LV_DRAW_SW_ASM_CUSTOM
|
||||
#define LV_DRAW_SW_ASM_CUSTOM_INCLUDE ""
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Use NXP's VG-Lite GPU on iMX RTxxx platforms. */
|
||||
#define LV_USE_DRAW_VGLITE 0
|
||||
|
||||
#if LV_USE_DRAW_VGLITE
|
||||
/* Enable blit quality degradation workaround recommended for screen's dimension > 352 pixels. */
|
||||
#define LV_USE_VGLITE_BLIT_SPLIT 0
|
||||
|
||||
#if LV_USE_OS
|
||||
/* Enable VGLite draw async. Queue multiple tasks and flash them once to the GPU. */
|
||||
#define LV_USE_VGLITE_DRAW_ASYNC 1
|
||||
#endif
|
||||
|
||||
/* Enable VGLite asserts. */
|
||||
#define LV_USE_VGLITE_ASSERT 0
|
||||
#endif
|
||||
|
||||
/* Use NXP's PXP on iMX RTxxx platforms. */
|
||||
#define LV_USE_DRAW_PXP 0
|
||||
|
||||
#if LV_USE_DRAW_PXP
|
||||
/* Enable PXP asserts. */
|
||||
#define LV_USE_PXP_ASSERT 0
|
||||
#endif
|
||||
|
||||
/* Use Renesas Dave2D on RA platforms. */
|
||||
#define LV_USE_DRAW_DAVE2D 0
|
||||
|
||||
/* Draw using cached SDL textures*/
|
||||
#define LV_USE_DRAW_SDL 0
|
||||
|
||||
/* Use VG-Lite GPU. */
|
||||
#define LV_USE_DRAW_VG_LITE 0
|
||||
|
||||
#if LV_USE_DRAW_VG_LITE
|
||||
/* Enable VG-Lite custom external 'gpu_init()' function */
|
||||
#define LV_VG_LITE_USE_GPU_INIT 0
|
||||
|
||||
/* Enable VG-Lite assert. */
|
||||
#define LV_VG_LITE_USE_ASSERT 0
|
||||
|
||||
/* VG-Lite flush commit trigger threshold. GPU will try to batch these many draw tasks. */
|
||||
#define LV_VG_LITE_FLUSH_MAX_COUNT 8
|
||||
|
||||
/* Enable border to simulate shadow
|
||||
* NOTE: which usually improves performance,
|
||||
* but does not guarantee the same rendering quality as the software. */
|
||||
#define LV_VG_LITE_USE_BOX_SHADOW 0
|
||||
|
||||
/* VG-Lite gradient image maximum cache number.
|
||||
* NOTE: The memory usage of a single gradient image is 4K bytes.
|
||||
*/
|
||||
#define LV_VG_LITE_GRAD_CACHE_SIZE 32
|
||||
|
||||
#endif
|
||||
|
||||
/*=======================
|
||||
* FEATURE CONFIGURATION
|
||||
*=======================*/
|
||||
|
||||
/*-------------
|
||||
* Logging
|
||||
*-----------*/
|
||||
|
||||
/*Enable the log module*/
|
||||
#define LV_USE_LOG 1
|
||||
#if LV_USE_LOG
|
||||
|
||||
/*How important log should be added:
|
||||
*LV_LOG_LEVEL_TRACE A lot of logs to give detailed information
|
||||
*LV_LOG_LEVEL_INFO Log important events
|
||||
*LV_LOG_LEVEL_WARN Log if something unwanted happened but didn't cause a problem
|
||||
*LV_LOG_LEVEL_ERROR Only critical issue, when the system may fail
|
||||
*LV_LOG_LEVEL_USER Only logs added by the user
|
||||
*LV_LOG_LEVEL_NONE Do not log anything*/
|
||||
#define LV_LOG_LEVEL LV_LOG_LEVEL_USER
|
||||
|
||||
/*1: Print the log with 'printf';
|
||||
*0: User need to register a callback with `lv_log_register_print_cb()`*/
|
||||
#define LV_LOG_PRINTF 0
|
||||
|
||||
/*1: Enable print timestamp;
|
||||
*0: Disable print timestamp*/
|
||||
#define LV_LOG_USE_TIMESTAMP 1
|
||||
|
||||
/*1: Print file and line number of the log;
|
||||
*0: Do not print file and line number of the log*/
|
||||
#define LV_LOG_USE_FILE_LINE 1
|
||||
|
||||
/*Enable/disable LV_LOG_TRACE in modules that produces a huge number of logs*/
|
||||
#define LV_LOG_TRACE_MEM 1
|
||||
#define LV_LOG_TRACE_TIMER 1
|
||||
#define LV_LOG_TRACE_INDEV 1
|
||||
#define LV_LOG_TRACE_DISP_REFR 1
|
||||
#define LV_LOG_TRACE_EVENT 1
|
||||
#define LV_LOG_TRACE_OBJ_CREATE 1
|
||||
#define LV_LOG_TRACE_LAYOUT 1
|
||||
#define LV_LOG_TRACE_ANIM 1
|
||||
#define LV_LOG_TRACE_CACHE 1
|
||||
|
||||
#endif /*LV_USE_LOG*/
|
||||
|
||||
/*-------------
|
||||
* Asserts
|
||||
*-----------*/
|
||||
|
||||
/*Enable asserts if an operation is failed or an invalid data is found.
|
||||
*If LV_USE_LOG is enabled an error message will be printed on failure*/
|
||||
#define LV_USE_ASSERT_NULL 1 /*Check if the parameter is NULL. (Very fast, recommended)*/
|
||||
#define LV_USE_ASSERT_MALLOC 1 /*Checks is the memory is successfully allocated or no. (Very fast, recommended)*/
|
||||
#define LV_USE_ASSERT_STYLE 0 /*Check if the styles are properly initialized. (Very fast, recommended)*/
|
||||
#define LV_USE_ASSERT_MEM_INTEGRITY 0 /*Check the integrity of `lv_mem` after critical operations. (Slow)*/
|
||||
#define LV_USE_ASSERT_OBJ 0 /*Check the object's type and existence (e.g. not deleted). (Slow)*/
|
||||
|
||||
/*Add a custom handler when assert happens e.g. to restart the MCU*/
|
||||
#define LV_ASSERT_HANDLER_INCLUDE <stdint.h>
|
||||
#define LV_ASSERT_HANDLER while(1); /*Halt by default*/
|
||||
|
||||
/*-------------
|
||||
* Debug
|
||||
*-----------*/
|
||||
|
||||
/*1: Draw random colored rectangles over the redrawn areas*/
|
||||
#define LV_USE_REFR_DEBUG 0
|
||||
|
||||
/*1: Draw a red overlay for ARGB layers and a green overlay for RGB layers*/
|
||||
#define LV_USE_LAYER_DEBUG 0
|
||||
|
||||
/*1: Draw overlays with different colors for each draw_unit's tasks.
|
||||
*Also add the index number of the draw unit on white background.
|
||||
*For layers add the index number of the draw unit on black background.*/
|
||||
#define LV_USE_PARALLEL_DRAW_DEBUG 0
|
||||
|
||||
/*-------------
|
||||
* Others
|
||||
*-----------*/
|
||||
|
||||
#define LV_ENABLE_GLOBAL_CUSTOM 0
|
||||
#if LV_ENABLE_GLOBAL_CUSTOM
|
||||
/*Header to include for the custom 'lv_global' function"*/
|
||||
#define LV_GLOBAL_CUSTOM_INCLUDE <stdint.h>
|
||||
#endif
|
||||
|
||||
/*Default cache size in bytes.
|
||||
*Used by image decoders such as `lv_lodepng` to keep the decoded image in the memory.
|
||||
*If size is not set to 0, the decoder will fail to decode when the cache is full.
|
||||
*If size is 0, the cache function is not enabled and the decoded mem will be released immediately after use.*/
|
||||
#define LV_CACHE_DEF_SIZE 0
|
||||
|
||||
/*Default number of image header cache entries. The cache is used to store the headers of images
|
||||
*The main logic is like `LV_CACHE_DEF_SIZE` but for image headers.*/
|
||||
#define LV_IMAGE_HEADER_CACHE_DEF_CNT 0
|
||||
|
||||
/*Number of stops allowed per gradient. Increase this to allow more stops.
|
||||
*This adds (sizeof(lv_color_t) + 1) bytes per additional stop*/
|
||||
#define LV_GRADIENT_MAX_STOPS 2
|
||||
|
||||
/* Adjust color mix functions rounding. GPUs might calculate color mix (blending) differently.
|
||||
* 0: round down, 64: round up from x.75, 128: round up from half, 192: round up from x.25, 254: round up */
|
||||
#define LV_COLOR_MIX_ROUND_OFS 0
|
||||
|
||||
/* Add 2 x 32 bit variables to each lv_obj_t to speed up getting style properties */
|
||||
#define LV_OBJ_STYLE_CACHE 0
|
||||
|
||||
/* Add `id` field to `lv_obj_t` */
|
||||
#define LV_USE_OBJ_ID 0
|
||||
|
||||
/* Use lvgl builtin method for obj ID */
|
||||
#define LV_USE_OBJ_ID_BUILTIN 0
|
||||
|
||||
/*Use obj property set/get API*/
|
||||
#define LV_USE_OBJ_PROPERTY 0
|
||||
|
||||
/* VG-Lite Simulator */
|
||||
/*Requires: LV_USE_THORVG_INTERNAL or LV_USE_THORVG_EXTERNAL */
|
||||
#define LV_USE_VG_LITE_THORVG 0
|
||||
|
||||
#if LV_USE_VG_LITE_THORVG
|
||||
|
||||
/*Enable LVGL's blend mode support*/
|
||||
#define LV_VG_LITE_THORVG_LVGL_BLEND_SUPPORT 0
|
||||
|
||||
/*Enable YUV color format support*/
|
||||
#define LV_VG_LITE_THORVG_YUV_SUPPORT 0
|
||||
|
||||
/*Enable 16 pixels alignment*/
|
||||
#define LV_VG_LITE_THORVG_16PIXELS_ALIGN 1
|
||||
|
||||
/*Buffer address alignment*/
|
||||
#define LV_VG_LITE_THORVG_BUF_ADDR_ALIGN 64
|
||||
|
||||
/*Enable multi-thread render*/
|
||||
#define LV_VG_LITE_THORVG_THREAD_RENDER 0
|
||||
|
||||
#endif
|
||||
|
||||
/*=====================
|
||||
* COMPILER SETTINGS
|
||||
*====================*/
|
||||
|
||||
/*For big endian systems set to 1*/
|
||||
#define LV_BIG_ENDIAN_SYSTEM 0
|
||||
|
||||
/*Define a custom attribute to `lv_tick_inc` function*/
|
||||
#define LV_ATTRIBUTE_TICK_INC
|
||||
|
||||
/*Define a custom attribute to `lv_timer_handler` function*/
|
||||
#define LV_ATTRIBUTE_TIMER_HANDLER
|
||||
|
||||
/*Define a custom attribute to `lv_display_flush_ready` function*/
|
||||
#define LV_ATTRIBUTE_FLUSH_READY
|
||||
|
||||
/*Required alignment size for buffers*/
|
||||
#define LV_ATTRIBUTE_MEM_ALIGN_SIZE 1
|
||||
|
||||
/*Will be added where memories needs to be aligned (with -Os data might not be aligned to boundary by default).
|
||||
* E.g. __attribute__((aligned(4)))*/
|
||||
#define LV_ATTRIBUTE_MEM_ALIGN
|
||||
|
||||
/*Attribute to mark large constant arrays for example font's bitmaps*/
|
||||
#define LV_ATTRIBUTE_LARGE_CONST
|
||||
|
||||
/*Compiler prefix for a big array declaration in RAM*/
|
||||
#define LV_ATTRIBUTE_LARGE_RAM_ARRAY
|
||||
|
||||
/*Place performance critical functions into a faster memory (e.g RAM)*/
|
||||
#define LV_ATTRIBUTE_FAST_MEM
|
||||
|
||||
/*Export integer constant to binding. This macro is used with constants in the form of LV_<CONST> that
|
||||
*should also appear on LVGL binding API such as Micropython.*/
|
||||
#define LV_EXPORT_CONST_INT(int_value) struct _silence_gcc_warning /*The default value just prevents GCC warning*/
|
||||
|
||||
/*Prefix all global extern data with this*/
|
||||
#define LV_ATTRIBUTE_EXTERN_DATA
|
||||
|
||||
/* Use `float` as `lv_value_precise_t` */
|
||||
#define LV_USE_FLOAT 0
|
||||
|
||||
/*==================
|
||||
* FONT USAGE
|
||||
*===================*/
|
||||
|
||||
/*Montserrat fonts with ASCII range and some symbols using bpp = 4
|
||||
*https://fonts.google.com/specimen/Montserrat*/
|
||||
#define LV_FONT_MONTSERRAT_8 0
|
||||
#define LV_FONT_MONTSERRAT_10 0
|
||||
#define LV_FONT_MONTSERRAT_12 0
|
||||
#define LV_FONT_MONTSERRAT_14 1
|
||||
#define LV_FONT_MONTSERRAT_16 0
|
||||
#define LV_FONT_MONTSERRAT_18 0
|
||||
#define LV_FONT_MONTSERRAT_20 1
|
||||
#define LV_FONT_MONTSERRAT_22 0
|
||||
#define LV_FONT_MONTSERRAT_24 0
|
||||
#define LV_FONT_MONTSERRAT_26 0
|
||||
#define LV_FONT_MONTSERRAT_28 0
|
||||
#define LV_FONT_MONTSERRAT_30 0
|
||||
#define LV_FONT_MONTSERRAT_32 0
|
||||
#define LV_FONT_MONTSERRAT_34 0
|
||||
#define LV_FONT_MONTSERRAT_36 0
|
||||
#define LV_FONT_MONTSERRAT_38 0
|
||||
#define LV_FONT_MONTSERRAT_40 0
|
||||
#define LV_FONT_MONTSERRAT_42 0
|
||||
#define LV_FONT_MONTSERRAT_44 0
|
||||
#define LV_FONT_MONTSERRAT_46 0
|
||||
#define LV_FONT_MONTSERRAT_48 0
|
||||
|
||||
/*Demonstrate special features*/
|
||||
#define LV_FONT_MONTSERRAT_28_COMPRESSED 0 /*bpp = 3*/
|
||||
#define LV_FONT_DEJAVU_16_PERSIAN_HEBREW 1 /*Hebrew, Arabic, Persian letters and all their forms*/
|
||||
#define LV_FONT_SIMSUN_16_CJK 0 /*1000 most common CJK radicals*/
|
||||
|
||||
/*Pixel perfect monospace fonts*/
|
||||
#define LV_FONT_UNSCII_8 0
|
||||
#define LV_FONT_UNSCII_16 0
|
||||
|
||||
/*Optionally declare custom fonts here.
|
||||
*You can use these fonts as default font too and they will be available globally.
|
||||
*E.g. #define LV_FONT_CUSTOM_DECLARE LV_FONT_DECLARE(my_font_1) LV_FONT_DECLARE(my_font_2)*/
|
||||
#define LV_FONT_CUSTOM_DECLARE
|
||||
|
||||
/*Always set a default font*/
|
||||
#define LV_FONT_DEFAULT &lv_font_montserrat_20
|
||||
|
||||
/*Enable handling large font and/or fonts with a lot of characters.
|
||||
*The limit depends on the font size, font face and bpp.
|
||||
*Compiler error will be triggered if a font needs it.*/
|
||||
#define LV_FONT_FMT_TXT_LARGE 0
|
||||
|
||||
/*Enables/disables support for compressed fonts.*/
|
||||
#define LV_USE_FONT_COMPRESSED 0
|
||||
|
||||
/*Enable drawing placeholders when glyph dsc is not found*/
|
||||
#define LV_USE_FONT_PLACEHOLDER 1
|
||||
|
||||
/*=================
|
||||
* TEXT SETTINGS
|
||||
*=================*/
|
||||
|
||||
/**
|
||||
* Select a character encoding for strings.
|
||||
* Your IDE or editor should have the same character encoding
|
||||
* - LV_TXT_ENC_UTF8
|
||||
* - LV_TXT_ENC_ASCII
|
||||
*/
|
||||
#define LV_TXT_ENC LV_TXT_ENC_UTF8
|
||||
|
||||
/*Can break (wrap) texts on these chars*/
|
||||
#define LV_TXT_BREAK_CHARS " ,.;:-_)]}"
|
||||
|
||||
/*If a word is at least this long, will break wherever "prettiest"
|
||||
*To disable, set to a value <= 0*/
|
||||
#define LV_TXT_LINE_BREAK_LONG_LEN 0
|
||||
|
||||
/*Minimum number of characters in a long word to put on a line before a break.
|
||||
*Depends on LV_TXT_LINE_BREAK_LONG_LEN.*/
|
||||
#define LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN 3
|
||||
|
||||
/*Minimum number of characters in a long word to put on a line after a break.
|
||||
*Depends on LV_TXT_LINE_BREAK_LONG_LEN.*/
|
||||
#define LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN 3
|
||||
|
||||
/*Support bidirectional texts. Allows mixing Left-to-Right and Right-to-Left texts.
|
||||
*The direction will be processed according to the Unicode Bidirectional Algorithm:
|
||||
*https://www.w3.org/International/articles/inline-bidi-markup/uba-basics*/
|
||||
#define LV_USE_BIDI 1
|
||||
#if LV_USE_BIDI
|
||||
/*Set the default direction. Supported values:
|
||||
*`LV_BASE_DIR_LTR` Left-to-Right
|
||||
*`LV_BASE_DIR_RTL` Right-to-Left
|
||||
*`LV_BASE_DIR_AUTO` detect texts base direction*/
|
||||
#define LV_BIDI_BASE_DIR_DEF LV_BASE_DIR_AUTO
|
||||
#endif
|
||||
|
||||
/*Enable Arabic/Persian processing
|
||||
*In these languages characters should be replaced with an other form based on their position in the text*/
|
||||
#define LV_USE_ARABIC_PERSIAN_CHARS 0
|
||||
|
||||
/*==================
|
||||
* WIDGETS
|
||||
*================*/
|
||||
|
||||
/*Documentation of the widgets: https://docs.lvgl.io/latest/en/html/widgets/index.html*/
|
||||
|
||||
#define LV_WIDGETS_HAS_DEFAULT_VALUE 1
|
||||
|
||||
#define LV_USE_ANIMIMG 1
|
||||
|
||||
#define LV_USE_ARC 1
|
||||
|
||||
#define LV_USE_BAR 1
|
||||
|
||||
#define LV_USE_BUTTON 1
|
||||
|
||||
#define LV_USE_BUTTONMATRIX 1
|
||||
|
||||
#define LV_USE_CALENDAR 1
|
||||
#if LV_USE_CALENDAR
|
||||
#define LV_CALENDAR_WEEK_STARTS_MONDAY 0
|
||||
#if LV_CALENDAR_WEEK_STARTS_MONDAY
|
||||
#define LV_CALENDAR_DEFAULT_DAY_NAMES {"Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"}
|
||||
#else
|
||||
#define LV_CALENDAR_DEFAULT_DAY_NAMES {"Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"}
|
||||
#endif
|
||||
|
||||
#define LV_CALENDAR_DEFAULT_MONTH_NAMES {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}
|
||||
#define LV_USE_CALENDAR_HEADER_ARROW 1
|
||||
#define LV_USE_CALENDAR_HEADER_DROPDOWN 1
|
||||
#endif /*LV_USE_CALENDAR*/
|
||||
|
||||
#define LV_USE_CANVAS 1
|
||||
|
||||
#define LV_USE_CHART 1
|
||||
|
||||
#define LV_USE_CHECKBOX 1
|
||||
|
||||
#define LV_USE_DROPDOWN 1 /*Requires: lv_label*/
|
||||
|
||||
#define LV_USE_IMAGE 1 /*Requires: lv_label*/
|
||||
|
||||
#define LV_USE_IMAGEBUTTON 1
|
||||
|
||||
#define LV_USE_KEYBOARD 1
|
||||
|
||||
#define LV_USE_LABEL 1
|
||||
#if LV_USE_LABEL
|
||||
#define LV_LABEL_TEXT_SELECTION 1 /*Enable selecting text of the label*/
|
||||
#define LV_LABEL_LONG_TXT_HINT 1 /*Store some extra info in labels to speed up drawing of very long texts*/
|
||||
#define LV_LABEL_WAIT_CHAR_COUNT 3 /*The count of wait chart*/
|
||||
#endif
|
||||
|
||||
#define LV_USE_LED 1
|
||||
|
||||
#define LV_USE_LINE 1
|
||||
|
||||
#define LV_USE_LIST 1
|
||||
|
||||
#define LV_USE_MENU 1
|
||||
|
||||
#define LV_USE_MSGBOX 1
|
||||
|
||||
#define LV_USE_ROLLER 1 /*Requires: lv_label*/
|
||||
|
||||
#define LV_USE_SCALE 1
|
||||
|
||||
#define LV_USE_SLIDER 1 /*Requires: lv_bar*/
|
||||
|
||||
#define LV_USE_SPAN 1
|
||||
#if LV_USE_SPAN
|
||||
/*A line text can contain maximum num of span descriptor */
|
||||
#define LV_SPAN_SNIPPET_STACK_SIZE 64
|
||||
#endif
|
||||
|
||||
#define LV_USE_SPINBOX 1
|
||||
|
||||
#define LV_USE_SPINNER 1
|
||||
|
||||
#define LV_USE_SWITCH 1
|
||||
|
||||
#define LV_USE_TEXTAREA 1 /*Requires: lv_label*/
|
||||
#if LV_USE_TEXTAREA != 0
|
||||
#define LV_TEXTAREA_DEF_PWD_SHOW_TIME 1500 /*ms*/
|
||||
#endif
|
||||
|
||||
#define LV_USE_TABLE 1
|
||||
|
||||
#define LV_USE_TABVIEW 1
|
||||
|
||||
#define LV_USE_TILEVIEW 1
|
||||
|
||||
#define LV_USE_WIN 1
|
||||
|
||||
/*==================
|
||||
* THEMES
|
||||
*==================*/
|
||||
|
||||
/*A simple, impressive and very complete theme*/
|
||||
#define LV_USE_THEME_DEFAULT 1
|
||||
#if LV_USE_THEME_DEFAULT
|
||||
|
||||
/*0: Light mode; 1: Dark mode*/
|
||||
#define LV_THEME_DEFAULT_DARK 0
|
||||
|
||||
/*1: Enable grow on press*/
|
||||
#define LV_THEME_DEFAULT_GROW 1
|
||||
|
||||
/*Default transition time in [ms]*/
|
||||
#define LV_THEME_DEFAULT_TRANSITION_TIME 80
|
||||
#endif /*LV_USE_THEME_DEFAULT*/
|
||||
|
||||
/*A very simple theme that is a good starting point for a custom theme*/
|
||||
#define LV_USE_THEME_SIMPLE 1
|
||||
|
||||
/*A theme designed for monochrome displays*/
|
||||
#define LV_USE_THEME_MONO 1
|
||||
|
||||
/*==================
|
||||
* LAYOUTS
|
||||
*==================*/
|
||||
|
||||
/*A layout similar to Flexbox in CSS.*/
|
||||
#define LV_USE_FLEX 1
|
||||
|
||||
/*A layout similar to Grid in CSS.*/
|
||||
#define LV_USE_GRID 1
|
||||
|
||||
/*====================
|
||||
* 3RD PARTS LIBRARIES
|
||||
*====================*/
|
||||
|
||||
/*File system interfaces for common APIs */
|
||||
|
||||
/*API for fopen, fread, etc*/
|
||||
#define LV_USE_FS_STDIO 0
|
||||
#if LV_USE_FS_STDIO
|
||||
#define LV_FS_STDIO_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/
|
||||
#define LV_FS_STDIO_PATH "" /*Set the working directory. File/directory paths will be appended to it.*/
|
||||
#define LV_FS_STDIO_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/
|
||||
#endif
|
||||
|
||||
/*API for open, read, etc*/
|
||||
#define LV_USE_FS_POSIX 0
|
||||
#if LV_USE_FS_POSIX
|
||||
#define LV_FS_POSIX_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/
|
||||
#define LV_FS_POSIX_PATH "" /*Set the working directory. File/directory paths will be appended to it.*/
|
||||
#define LV_FS_POSIX_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/
|
||||
#endif
|
||||
|
||||
/*API for CreateFile, ReadFile, etc*/
|
||||
#define LV_USE_FS_WIN32 0
|
||||
#if LV_USE_FS_WIN32
|
||||
#define LV_FS_WIN32_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/
|
||||
#define LV_FS_WIN32_PATH "" /*Set the working directory. File/directory paths will be appended to it.*/
|
||||
#define LV_FS_WIN32_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/
|
||||
#endif
|
||||
|
||||
/*API for FATFS (needs to be added separately). Uses f_open, f_read, etc*/
|
||||
#define LV_USE_FS_FATFS 0
|
||||
#if LV_USE_FS_FATFS
|
||||
#define LV_FS_FATFS_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/
|
||||
#define LV_FS_FATFS_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/
|
||||
#endif
|
||||
|
||||
/*API for memory-mapped file access. */
|
||||
#define LV_USE_FS_MEMFS 0
|
||||
#if LV_USE_FS_MEMFS
|
||||
#define LV_FS_MEMFS_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/
|
||||
#endif
|
||||
|
||||
/*API for LittleFs. */
|
||||
#define LV_USE_FS_LITTLEFS 0
|
||||
#if LV_USE_FS_LITTLEFS
|
||||
#define LV_FS_LITTLEFS_LETTER '\0' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/
|
||||
#endif
|
||||
|
||||
/*LODEPNG decoder library*/
|
||||
#define LV_USE_LODEPNG 0
|
||||
|
||||
/*PNG decoder(libpng) library*/
|
||||
#define LV_USE_LIBPNG 0
|
||||
|
||||
/*BMP decoder library*/
|
||||
#define LV_USE_BMP 0
|
||||
|
||||
/* JPG + split JPG decoder library.
|
||||
* Split JPG is a custom format optimized for embedded systems. */
|
||||
#define LV_USE_TJPGD 0
|
||||
|
||||
/* libjpeg-turbo decoder library.
|
||||
* Supports complete JPEG specifications and high-performance JPEG decoding. */
|
||||
#define LV_USE_LIBJPEG_TURBO 0
|
||||
|
||||
/*GIF decoder library*/
|
||||
#define LV_USE_GIF 0
|
||||
#if LV_USE_GIF
|
||||
/*GIF decoder accelerate*/
|
||||
#define LV_GIF_CACHE_DECODE_DATA 0
|
||||
#endif
|
||||
|
||||
|
||||
/*Decode bin images to RAM*/
|
||||
#define LV_BIN_DECODER_RAM_LOAD 0
|
||||
|
||||
/*RLE decompress library*/
|
||||
#define LV_USE_RLE 0
|
||||
|
||||
/*QR code library*/
|
||||
#define LV_USE_QRCODE 0
|
||||
|
||||
/*Barcode code library*/
|
||||
#define LV_USE_BARCODE 0
|
||||
|
||||
/*FreeType library*/
|
||||
#define LV_USE_FREETYPE 0
|
||||
#if LV_USE_FREETYPE
|
||||
/*Let FreeType to use LVGL memory and file porting*/
|
||||
#define LV_FREETYPE_USE_LVGL_PORT 0
|
||||
|
||||
/*Cache count of the glyphs in FreeType. It means the number of glyphs that can be cached.
|
||||
*The higher the value, the more memory will be used.*/
|
||||
#define LV_FREETYPE_CACHE_FT_GLYPH_CNT 256
|
||||
#endif
|
||||
|
||||
/* Built-in TTF decoder */
|
||||
#define LV_USE_TINY_TTF 0
|
||||
#if LV_USE_TINY_TTF
|
||||
/* Enable loading TTF data from files */
|
||||
#define LV_TINY_TTF_FILE_SUPPORT 0
|
||||
#endif
|
||||
|
||||
/*Rlottie library*/
|
||||
#define LV_USE_RLOTTIE 0
|
||||
|
||||
/*Enable Vector Graphic APIs*/
|
||||
#define LV_USE_VECTOR_GRAPHIC 0
|
||||
|
||||
/* Enable ThorVG (vector graphics library) from the src/libs folder */
|
||||
#define LV_USE_THORVG_INTERNAL 0
|
||||
|
||||
/* Enable ThorVG by assuming that its installed and linked to the project */
|
||||
#define LV_USE_THORVG_EXTERNAL 0
|
||||
|
||||
/*Use lvgl built-in LZ4 lib*/
|
||||
#define LV_USE_LZ4_INTERNAL 0
|
||||
|
||||
/*Use external LZ4 library*/
|
||||
#define LV_USE_LZ4_EXTERNAL 0
|
||||
|
||||
/*FFmpeg library for image decoding and playing videos
|
||||
*Supports all major image formats so do not enable other image decoder with it*/
|
||||
#define LV_USE_FFMPEG 0
|
||||
#if LV_USE_FFMPEG
|
||||
/*Dump input information to stderr*/
|
||||
#define LV_FFMPEG_DUMP_FORMAT 0
|
||||
#endif
|
||||
|
||||
/*==================
|
||||
* OTHERS
|
||||
*==================*/
|
||||
|
||||
/*1: Enable API to take snapshot for object*/
|
||||
#define LV_USE_SNAPSHOT 0
|
||||
|
||||
/*1: Enable system monitor component*/
|
||||
#define LV_USE_SYSMON 1
|
||||
#if LV_USE_SYSMON
|
||||
/*Get the idle percentage. E.g. uint32_t my_get_idle(void);*/
|
||||
#define LV_SYSMON_GET_IDLE lv_timer_get_idle
|
||||
|
||||
/*1: Show CPU usage and FPS count
|
||||
* Requires `LV_USE_SYSMON = 1`*/
|
||||
#define LV_USE_PERF_MONITOR 1
|
||||
#if LV_USE_PERF_MONITOR
|
||||
#define LV_USE_PERF_MONITOR_POS LV_ALIGN_BOTTOM_RIGHT
|
||||
|
||||
/*0: Displays performance data on the screen, 1: Prints performance data using log.*/
|
||||
#define LV_USE_PERF_MONITOR_LOG_MODE 0
|
||||
#endif
|
||||
|
||||
/*1: Show the used memory and the memory fragmentation
|
||||
* Requires `LV_USE_STDLIB_MALLOC = LV_STDLIB_BUILTIN`
|
||||
* Requires `LV_USE_SYSMON = 1`*/
|
||||
#define LV_USE_MEM_MONITOR 0
|
||||
#if LV_USE_MEM_MONITOR
|
||||
#define LV_USE_MEM_MONITOR_POS LV_ALIGN_TOP_RIGHT
|
||||
#endif
|
||||
|
||||
#endif /*LV_USE_SYSMON*/
|
||||
|
||||
/*1: Enable the runtime performance profiler*/
|
||||
#define LV_USE_PROFILER 0
|
||||
#if LV_USE_PROFILER
|
||||
/*1: Enable the built-in profiler*/
|
||||
#define LV_USE_PROFILER_BUILTIN 1
|
||||
#if LV_USE_PROFILER_BUILTIN
|
||||
/*Default profiler trace buffer size*/
|
||||
#define LV_PROFILER_BUILTIN_BUF_SIZE (16 * 1024) /*[bytes]*/
|
||||
#endif
|
||||
|
||||
/*Header to include for the profiler*/
|
||||
#define LV_PROFILER_INCLUDE "lvgl/src/misc/lv_profiler_builtin.h"
|
||||
|
||||
/*Profiler start point function*/
|
||||
#define LV_PROFILER_BEGIN LV_PROFILER_BUILTIN_BEGIN
|
||||
|
||||
/*Profiler end point function*/
|
||||
#define LV_PROFILER_END LV_PROFILER_BUILTIN_END
|
||||
|
||||
/*Profiler start point function with custom tag*/
|
||||
#define LV_PROFILER_BEGIN_TAG LV_PROFILER_BUILTIN_BEGIN_TAG
|
||||
|
||||
/*Profiler end point function with custom tag*/
|
||||
#define LV_PROFILER_END_TAG LV_PROFILER_BUILTIN_END_TAG
|
||||
#endif
|
||||
|
||||
/*1: Enable Monkey test*/
|
||||
#define LV_USE_MONKEY 0
|
||||
|
||||
/*1: Enable grid navigation*/
|
||||
#define LV_USE_GRIDNAV 0
|
||||
|
||||
/*1: Enable lv_obj fragment*/
|
||||
#define LV_USE_FRAGMENT 0
|
||||
|
||||
/*1: Support using images as font in label or span widgets */
|
||||
#define LV_USE_IMGFONT 0
|
||||
|
||||
/*1: Enable an observer pattern implementation*/
|
||||
#define LV_USE_OBSERVER 1
|
||||
|
||||
/*1: Enable Pinyin input method*/
|
||||
/*Requires: lv_keyboard*/
|
||||
#define LV_USE_IME_PINYIN 0
|
||||
#if LV_USE_IME_PINYIN
|
||||
/*1: Use default thesaurus*/
|
||||
/*If you do not use the default thesaurus, be sure to use `lv_ime_pinyin` after setting the thesauruss*/
|
||||
#define LV_IME_PINYIN_USE_DEFAULT_DICT 1
|
||||
/*Set the maximum number of candidate panels that can be displayed*/
|
||||
/*This needs to be adjusted according to the size of the screen*/
|
||||
#define LV_IME_PINYIN_CAND_TEXT_NUM 6
|
||||
|
||||
/*Use 9 key input(k9)*/
|
||||
#define LV_IME_PINYIN_USE_K9_MODE 1
|
||||
#if LV_IME_PINYIN_USE_K9_MODE == 1
|
||||
#define LV_IME_PINYIN_K9_CAND_TEXT_NUM 3
|
||||
#endif /*LV_IME_PINYIN_USE_K9_MODE*/
|
||||
#endif
|
||||
|
||||
/*1: Enable file explorer*/
|
||||
/*Requires: lv_table*/
|
||||
#define LV_USE_FILE_EXPLORER 0
|
||||
#if LV_USE_FILE_EXPLORER
|
||||
/*Maximum length of path*/
|
||||
#define LV_FILE_EXPLORER_PATH_MAX_LEN (128)
|
||||
/*Quick access bar, 1:use, 0:not use*/
|
||||
/*Requires: lv_list*/
|
||||
#define LV_FILE_EXPLORER_QUICK_ACCESS 1
|
||||
#endif
|
||||
|
||||
/*==================
|
||||
* DEVICES
|
||||
*==================*/
|
||||
|
||||
/*Use SDL to open window on PC and handle mouse and keyboard*/
|
||||
#define LV_USE_SDL 0
|
||||
#if LV_USE_SDL
|
||||
#define LV_SDL_INCLUDE_PATH <SDL2/SDL.h>
|
||||
#define LV_SDL_RENDER_MODE LV_DISPLAY_RENDER_MODE_DIRECT /*LV_DISPLAY_RENDER_MODE_DIRECT is recommended for best performance*/
|
||||
#define LV_SDL_BUF_COUNT 1 /*1 or 2*/
|
||||
#define LV_SDL_FULLSCREEN 0 /*1: Make the window full screen by default*/
|
||||
#define LV_SDL_DIRECT_EXIT 1 /*1: Exit the application when all SDL windows are closed*/
|
||||
#define LV_SDL_MOUSEWHEEL_MODE LV_SDL_MOUSEWHEEL_MODE_ENCODER /*LV_SDL_MOUSEWHEEL_MODE_ENCODER/CROWN*/
|
||||
#endif
|
||||
|
||||
/*Use X11 to open window on Linux desktop and handle mouse and keyboard*/
|
||||
#define LV_USE_X11 0
|
||||
#if LV_USE_X11
|
||||
#define LV_X11_DIRECT_EXIT 1 /*Exit the application when all X11 windows have been closed*/
|
||||
#define LV_X11_DOUBLE_BUFFER 1 /*Use double buffers for endering*/
|
||||
/*select only 1 of the following render modes (LV_X11_RENDER_MODE_PARTIAL preferred!)*/
|
||||
#define LV_X11_RENDER_MODE_PARTIAL 1 /*Partial render mode (preferred)*/
|
||||
#define LV_X11_RENDER_MODE_DIRECT 0 /*direct render mode*/
|
||||
#define LV_X11_RENDER_MODE_FULL 0 /*Full render mode*/
|
||||
#endif
|
||||
|
||||
/*Driver for /dev/fb*/
|
||||
#define LV_USE_LINUX_FBDEV 0
|
||||
#if LV_USE_LINUX_FBDEV
|
||||
#define LV_LINUX_FBDEV_BSD 0
|
||||
#define LV_LINUX_FBDEV_RENDER_MODE LV_DISPLAY_RENDER_MODE_PARTIAL
|
||||
#define LV_LINUX_FBDEV_BUFFER_COUNT 0
|
||||
#define LV_LINUX_FBDEV_BUFFER_SIZE 60
|
||||
#endif
|
||||
|
||||
/*Use Nuttx to open window and handle touchscreen*/
|
||||
#define LV_USE_NUTTX 0
|
||||
|
||||
#if LV_USE_NUTTX
|
||||
#define LV_USE_NUTTX_LIBUV 0
|
||||
|
||||
/*Use Nuttx custom init API to open window and handle touchscreen*/
|
||||
#define LV_USE_NUTTX_CUSTOM_INIT 0
|
||||
|
||||
/*Driver for /dev/lcd*/
|
||||
#define LV_USE_NUTTX_LCD 0
|
||||
#if LV_USE_NUTTX_LCD
|
||||
#define LV_NUTTX_LCD_BUFFER_COUNT 0
|
||||
#define LV_NUTTX_LCD_BUFFER_SIZE 60
|
||||
#endif
|
||||
|
||||
/*Driver for /dev/input*/
|
||||
#define LV_USE_NUTTX_TOUCHSCREEN 0
|
||||
|
||||
#endif
|
||||
|
||||
/*Driver for /dev/dri/card*/
|
||||
#define LV_USE_LINUX_DRM 0
|
||||
|
||||
/*Interface for TFT_eSPI*/
|
||||
#define LV_USE_TFT_ESPI 0
|
||||
|
||||
/*Driver for evdev input devices*/
|
||||
#define LV_USE_EVDEV 0
|
||||
|
||||
/*Driver for libinput input devices*/
|
||||
#define LV_USE_LIBINPUT 0
|
||||
|
||||
#if LV_USE_LIBINPUT
|
||||
#define LV_LIBINPUT_BSD 0
|
||||
|
||||
/*Full keyboard support*/
|
||||
#define LV_LIBINPUT_XKB 0
|
||||
#if LV_LIBINPUT_XKB
|
||||
/*"setxkbmap -query" can help find the right values for your keyboard*/
|
||||
#define LV_LIBINPUT_XKB_KEY_MAP { .rules = NULL, .model = "pc101", .layout = "us", .variant = NULL, .options = NULL }
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*Drivers for LCD devices connected via SPI/parallel port*/
|
||||
#define LV_USE_ST7735 0
|
||||
#define LV_USE_ST7789 0
|
||||
#define LV_USE_ST7796 0
|
||||
#define LV_USE_ILI9341 0
|
||||
|
||||
#define LV_USE_GENERIC_MIPI (LV_USE_ST7735 | LV_USE_ST7789 | LV_USE_ST7796 | LV_USE_ILI9341)
|
||||
|
||||
/* LVGL Windows backend */
|
||||
#define LV_USE_WINDOWS 0
|
||||
|
||||
/*==================
|
||||
* EXAMPLES
|
||||
*==================*/
|
||||
|
||||
/*Enable the examples to be built with the library*/
|
||||
#define LV_BUILD_EXAMPLES 1
|
||||
|
||||
/*===================
|
||||
* DEMO USAGE
|
||||
====================*/
|
||||
|
||||
/*Show some widget. It might be required to increase `LV_MEM_SIZE` */
|
||||
#define LV_USE_DEMO_WIDGETS 0
|
||||
|
||||
/*Demonstrate the usage of encoder and keyboard*/
|
||||
#define LV_USE_DEMO_KEYPAD_AND_ENCODER 0
|
||||
|
||||
/*Benchmark your system*/
|
||||
#define LV_USE_DEMO_BENCHMARK 0
|
||||
|
||||
/*Render test for each primitives. Requires at least 480x272 display*/
|
||||
#define LV_USE_DEMO_RENDER 0
|
||||
|
||||
/*Stress test for LVGL*/
|
||||
#define LV_USE_DEMO_STRESS 0
|
||||
|
||||
/*Music player demo*/
|
||||
#define LV_USE_DEMO_MUSIC 0
|
||||
#if LV_USE_DEMO_MUSIC
|
||||
#define LV_DEMO_MUSIC_SQUARE 0
|
||||
#define LV_DEMO_MUSIC_LANDSCAPE 0
|
||||
#define LV_DEMO_MUSIC_ROUND 0
|
||||
#define LV_DEMO_MUSIC_LARGE 0
|
||||
#define LV_DEMO_MUSIC_AUTO_PLAY 0
|
||||
#endif
|
||||
|
||||
/*Flex layout demo*/
|
||||
#define LV_USE_DEMO_FLEX_LAYOUT 0
|
||||
|
||||
/*Smart-phone like multi-language demo*/
|
||||
#define LV_USE_DEMO_MULTILANG 0
|
||||
|
||||
/*Widget transformation demo*/
|
||||
#define LV_USE_DEMO_TRANSFORM 0
|
||||
|
||||
/*Demonstrate scroll settings*/
|
||||
#define LV_USE_DEMO_SCROLL 0
|
||||
|
||||
/*Vector graphic demo*/
|
||||
#define LV_USE_DEMO_VECTOR_GRAPHIC 0
|
||||
/*--END OF LV_CONF_H--*/
|
||||
|
||||
#endif /*LV_CONF_H*/
|
||||
|
||||
#endif /*End of "Content enable"*/
|
||||
@@ -0,0 +1,497 @@
|
||||
# Arduino_GFX
|
||||
|
||||
Arduino_GFX is a Arduino graphics library supporting various displays with various data bus interfaces.
|
||||
|
||||
This library start rewrite from Adafruit_GFX, LovyanGFX, TFT_eSPI, Ucglib, and more...
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||

|
||||

|
||||
|
||||
## Ease of use
|
||||
|
||||
### Simple Declaration
|
||||
|
||||
```C
|
||||
#include <Arduino_GFX_Library.h>
|
||||
Arduino_DataBus *bus = new Arduino_HWSPI(16 /* DC */, 5 /* CS */);
|
||||
Arduino_GFX *gfx = new Arduino_ILI9341(bus, 17 /* RST */);
|
||||
```
|
||||
|
||||
### And Simple Usage
|
||||
|
||||
```C
|
||||
gfx->begin();
|
||||
gfx->fillScreen(RGB565_BLACK);
|
||||
gfx->setCursor(10, 10);
|
||||
gfx->setTextColor(RGB565_RED);
|
||||
gfx->println("Hello World!");
|
||||
```
|
||||
|
||||
## Get Started
|
||||
|
||||
If you are new on this library, I always recommend try Library Example PDQgraphicstest first. You can find it at Arduino IDE -> File menu -> Examples -> GFX Library for Arduino -> PDQgraphicstest.
|
||||
|
||||
After open the example, you can see many tabs. The first is PDQgraphicstest, the main program. Start from the second tab, it is related header files, Arduino_GFX_databus.h, ... etc.
|
||||
|
||||
### Using supported Dev Device
|
||||
|
||||
If you are using below listed support dev device, simply select the Arduino_GFX_dev_device.h and uncomment the define of your dev device. E.g. if you are using LilyGo T-Deck:
|
||||
|
||||
```C
|
||||
...
|
||||
// #define JC3248W535
|
||||
#define LILYGO_T_DECK
|
||||
// #define LILYGO_T_DISPLAY
|
||||
...
|
||||
```
|
||||
|
||||
### Custom device and display
|
||||
|
||||
If you are not using supported dev device:
|
||||
|
||||
- Default DataBus is using Arduino SPI. Other DataBus can modify in Arduino_GFX_databus.h.
|
||||
|
||||
- Default Display is using ILI9341 LCD. Other Display can modify in Arduino_GFX_display.h.
|
||||
|
||||
## More Details
|
||||
|
||||
<details>
|
||||
|
||||
<summary>U8g2 Font Support</summary>
|
||||
|
||||
[U8g2](https://github.com/olikraus/u8g2.git) provided various font type and stored in compressed format. So U8g2 font gives more UI design possibilities and still can fit in the MCU limited storage space. Using U8g2 font in Arduino_GFX simply include U8g2lib.h before Arduino_GFX_Library.h:
|
||||
|
||||
```C
|
||||
#include <U8g2lib.h>
|
||||
#include <Arduino_GFX_Library.h>
|
||||
```
|
||||
|
||||
And then setfont file to use:
|
||||
|
||||
```C
|
||||
gfx->setCursor(10, 20);
|
||||
gfx->setFont(u8g2_font_maniac_tr);
|
||||
gfx->println("Hello World!");
|
||||
```
|
||||
|
||||
U8g2 font list can be found at: <https://github.com/olikraus/u8g2/wiki/fntlistall>
|
||||
|
||||
### U8g2 Unicode (UTF8) Font Support
|
||||
|
||||
Another U8g2 font advantage is the font support Unicode glyphs. Simply enable setUTF8Print:
|
||||
|
||||
```C
|
||||
gfx->begin();
|
||||
gfx->fillScreen(RGB565_BLACK);
|
||||
gfx->setUTF8Print(true);
|
||||
```
|
||||
|
||||
And then print UTF8 string as usual:
|
||||
|
||||
```C
|
||||
gfx->setCursor(0, 16);
|
||||
|
||||
gfx->setFont(u8g2_font_unifont_tr);
|
||||
gfx->println("Hello World!");
|
||||
|
||||
gfx->setFont(u8g2_font_unifont_t_polish);
|
||||
gfx->println("Witaj świecie!");
|
||||
|
||||
gfx->setFont(u8g2_font_unifont_t_vietnamese1);
|
||||
gfx->println("Chào thế giới!");
|
||||
|
||||
gfx->setFont(u8g2_font_unifont_t_chinese2);
|
||||
gfx->println("世界你好!");
|
||||
|
||||
gfx->setFont(u8g2_font_unifont_t_japanese1);
|
||||
gfx->println("こんにちは世界!");
|
||||
|
||||
gfx->setFont(u8g2_font_unifont_t_korean1);
|
||||
gfx->println("안녕하세요, 세계입니다!");
|
||||
```
|
||||
|
||||
U8g2 Unifont list can be found at: <https://github.com/olikraus/u8g2/wiki/fntgrpunifont>
|
||||
|
||||
### Extra Fonts
|
||||
|
||||
Besides U8g2 generated font, Arduino_GFX also generated some useful font set:
|
||||
|
||||
#### [Chill-Bitmap v2.400](https://github.com/Warren2060/Chill-Bitmap)
|
||||
|
||||
##### u8g2_font_chill7_h_cjk
|
||||
|
||||
* Glyphs: 13478/13478
|
||||
* Size: 254,960
|
||||
* Generation script:
|
||||
|
||||
```console
|
||||
otf2bdf ChillBitmap7x.ttf -p 6 -o ChillBitmap7x.bdf
|
||||
bdfconv -v -f 1 -b 1 -m "0-4294967295" ChillBitmap7x.bdf -o u8g2_font_chill7_h_cjk.h -n u8g2_font_chill7_h_cjk
|
||||
```
|
||||
|
||||
#### [Cubic 11 v1.013](https://github.com/ACh-K/Cubic-11)
|
||||
|
||||
##### u8g2_font_cubic11_h_cjk
|
||||
|
||||
* Glyphs: 10167/10167
|
||||
* Size: 337,650
|
||||
* Generation script:
|
||||
|
||||
```console
|
||||
otf2bdf Cubic_11_1.013_R.ttf -p 9 -o Cubic_11_1.013_R.bdf
|
||||
bdfconv -v -f 1 -b 1 -m "0-4294967295" Cubic_11_1.013_R.bdf -o u8g2_font_cubic11_h_cjk.h -n u8g2_font_cubic11_h_cjk
|
||||
```
|
||||
|
||||
#### [QuanPixel](https://diaowinner.itch.io/galmuri-extended)
|
||||
|
||||
##### u8g2_font_quan7_h_cjk
|
||||
|
||||
* Glyphs: 18082/18082
|
||||
* Size: 335,225
|
||||
* Generation script:
|
||||
|
||||
```console
|
||||
./bdfconv -v -f 1 -b 1 -m "0-4294967295" quan.bdf -o u8g2_font_quan7_h_cjk.h -n u8g2_font_quan7_h_cjk
|
||||
```
|
||||
|
||||
#### [unifont_jp-14.0.02](http://unifoundry.com/pub/unifont/unifont-14.0.02/font-builds/unifont_jp-14.0.02.bdf.gz)
|
||||
|
||||
##### u8g2_font_unifont_h_utf8
|
||||
|
||||
* Glyphs: 57389/57389
|
||||
* Size: 2,250,360
|
||||
* Generation script:
|
||||
|
||||
```console
|
||||
bdfconv -v -f 1 -b 1 -m "0-1114111" unifont_jp-14.0.02.bdf -o u8g2_font_unifont_h_utf8.h -n u8g2_font_unifont_h_utf8
|
||||
```
|
||||
|
||||
##### u8g2_font_unifont_t_chinese
|
||||
|
||||
* Glyphs: 22145/57389
|
||||
* Size: 979,557
|
||||
* Generation script:
|
||||
|
||||
```console
|
||||
bdfconv -v -f 1 -m "32-127,11904-12351,19968-40959,63744-64255,65280-65376" unifont_jp-14.0.02.bdf -o u8g2_font_unifont_t_chinese.h -n u8g2_font_unifont_t_chinese
|
||||
```
|
||||
|
||||
##### u8g2_font_unifont_t_chinese4
|
||||
|
||||
* Glyphs: 7199/57389
|
||||
* Size: 298,564
|
||||
* Traditional Chinese common font list: <https://raw.githubusercontent.com/ButTaiwan/cjktables/master/taiwan/edu_standard_1.txt>
|
||||
* Simplified Chinese common font list: <http://zht.glyphwiki.org/font/gw1197839.source>
|
||||
* extra font list: 32-127,11904-12351,63744-64255,65280-65376
|
||||
* Generation script:
|
||||
|
||||
```console
|
||||
bdfconv -v -f 1 -M chinese4.list unifont_jp-14.0.02.bdf -o u8g2_font_unifont_t_chinese4.h -n u8g2_font_unifont_t_chinese4
|
||||
```
|
||||
|
||||
##### u8g2_font_unifont_t_cjk
|
||||
|
||||
* Glyphs: 41364/57389
|
||||
* Size: 1,704,862
|
||||
* Generation script:
|
||||
|
||||
```console
|
||||
bdfconv -v -f 1 -m "32-127,4352-4607,11904-12255,12288-19903,19968-40943,43360-43391,44032-55203,55216-55295,63744-64255,65072-65103,65280-65519" unifont_jp-14.0.02.bdf -o u8g2_font_unifont_t_cjk.h -n u8g2_font_unifont_t_cjk
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Performance</summary>
|
||||
|
||||
This library is not putting speed at the first priority, but still paid much effort to make the display look smooth.
|
||||
|
||||
### Figures
|
||||
|
||||
Below are some figures compare with other 3 Arduino common display libraries.
|
||||
|
||||
* Arduino IDE: 1.8.15
|
||||
* arduino-esp32: 1.0.6
|
||||
* Dev Board: TTGO T8 v1.8
|
||||
* PSRAM: disable
|
||||
* Display: ILI9341
|
||||
* Interface: SPI
|
||||
* SPI Frequency: 40MHz
|
||||
* Test time: 2021 Jun 16
|
||||
|
||||
| Benchmark | Adafruit_GFX | *Arduino_GFX* | Lovyan_GFX | TFT_eSPI |
|
||||
| ------------------ | ------------- | ------------- | ------------- | ------------- |
|
||||
| Screen fill | 195,782 | *160,094* | 154,341 | 155,938 |
|
||||
| Text | 97,662 | *18,960* | 22,473 | 21,752 |
|
||||
| Pixels | 1,365,211 | *903,549* | 867,702 | 775,781 |
|
||||
| Lines | 1,062,311 | *412,026* | 269,060 | 264,950 |
|
||||
| Horiz/Vert Lines | 17,637 | *14,197* | 13,692 | 13,833 |
|
||||
| Rectangles-filled | 406,817 | *332,696* | 320,761 | 323,908 |
|
||||
| Rectangles | 11,641 | *9,254* | 8,545 | 8,714 |
|
||||
| Triangles-filled | 150,941 | *118,010* | 105,661 | 109,675 |
|
||||
| Triangles | 58,843 | *23,570* | 15,884 | 16,277 |
|
||||
| Circles-filled | 76,739 | *52,170* | 42,787 | 45,827 |
|
||||
| Circles | 118,125 | *40,955* | 25,959 | 25,269 |
|
||||
| Arcs-filled | N/A | *33,381* | 21,546 | N/A |
|
||||
| Arcs | N/A | *66,054* | 47,901 | N/A |
|
||||
| Rounded rects-fill | 408,534 | *338,136* | 318,882 | 323,189 |
|
||||
| Rounded rects | 43,185 | *21,562* | 13,089 | 15,371 |
|
||||
|
||||
### Why Run Fast?
|
||||
|
||||
* No read operation. Since not all display provide read back graphic memories API, Arduino_GFX skip all read operations. It can reduce the library size footprint and sometimes reduce the operation time.
|
||||
* Tailor-made data bus classes. Arduino_GFX decouple data bus operation from display driver, it is more easy to write individual data bus class for each platform.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Supported Interfaces</summary>
|
||||
|
||||
### Various data bus interfaces
|
||||
|
||||
Arduino_GFX utilizes Arduino Built-in SPI class to support 8-bit SPI for most platforms.
|
||||
|
||||
Most tiny displays in hobbyist electronics world support 8-bit SPI, but some require 9-bit SPI. Arduino_GFX should be the first Arduino display library that can use ESP32 SPI to support 9-bit hardware SPI. It is important to support the displays that require 9-bit SPI interface. (e.g. HX8357B, ...)
|
||||
|
||||
Larger displays most likely do not support standalone SPI since it is not fast enough to refresh the full screen details. Most of them support 8-bit/16-bit Parallel interface.
|
||||
|
||||
Some larger display require RGB + 3-bit SPI combo interface, This interface requies at most 3(9-bit SPI) + 4(CS, CD, WR, RD) + 24(RBG888) = 31 pins. Most dev board do not have enough GPIO to support this. Arduino_GFX is stick to RGB565 color, so RGB666 and RGB888 require some connection hack. E.g. RGB666 connect R5 and R6 together, B5 and B6 together to become RGB565. Then the least GPIO requirement can become 3(9-bit SPI) + 2(CD, WR) + 16(RBG565) = 21 pins. **Remember always pull down CS pin and always pull up RD pin.**
|
||||
|
||||
### Currently Supported data bus [[Wiki](https://github.com/moononournation/Arduino_GFX/wiki/Data-Bus-Class)]
|
||||
|
||||
* 8-bit and 9-bit hardware SPI (ESP32SPI)
|
||||
* 8-bit hardware SPI (HWSPI, ESP8266SPI, mbedSPI, NRFXSPI, RPiPicoSPI)
|
||||
* 8-bit and 9-bit software SPI (SWSPI)
|
||||
* 8-bit parallel interface (SWPAR8, AVRPAR8, ESP32LCD8, ESP32PAR8, ESP32S2PAR8, RPiPicoPAR8, RTLPAR8, STM32PAR8)
|
||||
* 16-bit parallel interface (ESP32LCD16, ESP32PAR16, ESP32S2PAR16, RPiPicoPAR16)
|
||||
* RGB565+SPI interface (ESP32RGBPanel)
|
||||
|
||||
#### Note
|
||||
|
||||
ESP32LCD8, ESP32LCD16 and ESP32RGBPanel only supported by arduino-esp32 v2.x and no longer support in v3.0.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Supported Dev Board</summary>
|
||||
|
||||
### Currently Supported Dev Board
|
||||
|
||||
* Ameba RTL8722DM Board (AMB 21)
|
||||
* Ameba RTL8722DM MINI Board (AMB 23)
|
||||
* Arduino Mega 2560 [[demo video](https://youtu.be/Hn2cTNrkOSM)]
|
||||
* Arduino Nano
|
||||
* Arduino Nano BLE 33
|
||||
* Arduino Pro Micro
|
||||
* Arduino UNO
|
||||
* Arduino UNO R4 Minima [[demo video](https://youtu.be/M1TuEU5uPb0)]
|
||||
* Arduino UNO R4 WiFi [[demo video](https://youtu.be/GB90AFSLIFo)]
|
||||
* ESP8266 Series
|
||||
* ESP32 Series
|
||||
* ESP32-C3 Series
|
||||
* ESP32-S2 Series
|
||||
* ESP32-S3 Series
|
||||
* Raspberry Pi Pico
|
||||
* Raspberry Pi Pico W
|
||||
* rtlduino BW16 (by Ai-Thinker)
|
||||
* Sony Spresense
|
||||
* WeAct BlackPill V2.0 (BlackPill F411CE)
|
||||
* [Seeed Studio XIAO SAMD21](https://www.seeedstudio.com/Seeeduino-XIAO-3Pcs-p-4546.html)
|
||||
* [Seeed Studio XIAO ESP32C3](https://www.seeedstudio.com/Seeed-XIAO-ESP32C3-p-5431.html)
|
||||
* [Seeed Studio XIAO ESP32S3](https://www.seeedstudio.com/XIAO-ESP32S3-p-5627.html)
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Supported Dev Device</summary>
|
||||
|
||||
### Currently Supported Dev Device [[Wiki](https://github.com/moononournation/Arduino_GFX/wiki/Dev-Device-Declaration)]
|
||||
|
||||
* [ESP32-1732S019](https://www.aliexpress.com/item/1005005059421229.html) [[demo video](https://youtube.com/shorts/VS4Qb3g2dWk)] [[LVGL demo video](https://youtu.be/V5xib6OnWiM)]
|
||||
* ESP32-2432S028
|
||||
* ESP32-2424012 [[demo video](https://youtu.be/EXw_yEMgug8)]
|
||||
* ESP32-3248S035
|
||||
* ESP32-4827A043 [[demo video](https://youtu.be/pd1DTW9QHkg)] [[LVGL demo video](https://youtu.be/L8iYjiy-DUI)]
|
||||
* [ESP32-4827S043](https://www.aliexpress.com/item/1005004788147691.html) [[demo video 1](https://youtu.be/60rl7QoU4Sc)] [[demo video 2](https://youtube.com/shorts/QY09u37htIk)] [[LVGL demo video](https://youtu.be/VvpILAVyPt8)]
|
||||
* [ESP32-8048S043](https://www.aliexpress.com/item/1005004788147691.html) [[demo video](https://youtu.be/tXBVTAzSf58)]
|
||||
* [ESP32-8048S070](https://www.aliexpress.com/item/1005004952726089.html) [[LVGL demo video](https://youtu.be/7BRGVsnQpgE)]
|
||||
* [ESP32 LCDKIT](https://docs.espressif.com/projects/espressif-esp-dev-kits/en/latest/esp32/esp32-lcdkit/user_guide.html)
|
||||
* [ESP32-S3-EYE](https://github.com/espressif/esp-who/blob/master/docs/en/get-started/ESP32-S3-EYE_Getting_Started_Guide.md)
|
||||
* [ESP32-S3-Box](https://www.espressif.com/en/news/ESP32-S3-BOX_video)
|
||||
* [ESP32-S3-Box-3](https://www.espressif.com/en/news/ESP32-S3-BOX-3)
|
||||
* [ESP32-S3-RGB](https://github.com/W00ng/ESP32-S3-RGB-Panel) [[LVGL demo video](https://youtu.be/d11yUvjh34A)]
|
||||
* ESP32S3-2.1-TP
|
||||
* [ESPboy](https://www.espboy.com) [[demo video](https://youtu.be/Cx82XWrc8-0)]
|
||||
* [Guition JC1060P470](https://www.aliexpress.com/item/1005008328088576.html) [[demo video](https://youtu.be/CF1EDSQDHQ8)] [[LVGL demo](https://youtu.be/CF1EDSQDHQ8)]
|
||||
* [LILYGO T-Deck](https://www.lilygo.cc/products/t-deck?bg_ref=Ts2JN05e23) [[demo video](https://youtube.com/shorts/fXKTVqjUoPM)]
|
||||
* [LILYGO T-Deck Plus](https://www.lilygo.cc/products/t-deck-plus-1?bg_ref=Ts2JN05e23)
|
||||
* [LILYGO T-Display](https://www.lilygo.cc/products/lilygo®-ttgo-t-display-1-14-inch-lcd-esp32-control-board?bg_ref=Ts2JN05e23)
|
||||
* [LILYGO T-Display-S3](https://www.lilygo.cc/products/t-display-s3?bg_ref=Ts2JN05e23) [[demo video](https://youtu.be/kpRC64QNQAo)]
|
||||
* [LILYGO T-Display-S3 AMOLED](https://www.lilygo.cc/products/t-display-s3-amoled?bg_ref=Ts2JN05e23) [[demo video](https://youtu.be/NvOGJAMlh1M)]
|
||||
* [LILYGO T-Display-S3 AMOLED 1.64](https://www.lilygo.cc/products/t-display-s3-amoled-1-64?bg_ref=Ts2JN05e23) [[demo video](https://youtu.be/5O3fQ1xNsrg)][[LVGL demo video](https://youtu.be/6UEaxWfxm9g)]
|
||||
* [LILYGO T-Display S3 Long](https://www.lilygo.cc/products/t-display-s3-long?bg_ref=Ts2JN05e23)[[LVGL demo video](https://youtu.be/OuxLFwxvcVc)]
|
||||
* [LILYGO T-Display S3 Pro](https://www.lilygo.cc/products/t-display-s3-pro?bg_ref=Ts2JN05e23) [[demo video](https://youtube.com/shorts/PE-GKTzbdP8)]
|
||||
* [LILYGO T-QT](https://www.lilygo.cc/products/t-qt-pro?bg_ref=Ts2JN05e23) [[demo video](https://youtube.com/shorts/V1MCQ1tQ8PM)]
|
||||
* [LILYGO T-RGB](https://www.lilygo.cc/products/t-rgb?bg_ref=Ts2JN05e23) [[LVGL demo video](https://youtu.be/BKEl_pWp_qQ)]
|
||||
* [LILYGO T-Track](https://www.lilygo.cc/products/t-track?bg_ref=Ts2JN05e23) [[demo video](https://youtu.be/6wmUhp-5eMg)][[LVGL demo video](https://youtu.be/wQjMu5JZSkg)]
|
||||
* LILYGO T-Watch
|
||||
* [LILYGO T-Watch 2021](https://www.lilygo.cc/products/t-watch-2021?bg_ref=Ts2JN05e23)
|
||||
* [LILYGO T4 S3](https://www.lilygo.cc/products/t4-s3?bg_ref=Ts2JN05e23)[[LVGL demo video](https://youtu.be/h4vXEYrDERM)]
|
||||
* [M5Stack Core Family](https://shop.m5stack.com/collections/m5-controllers/CORE)
|
||||
* [M5Stack AtomS3](https://shop.m5stack.com/products/atoms3-dev-kit-w-0-85-inch-screen)[[demo video](https://youtu.be/8u4TwZHmnN0)]
|
||||
* [Makerfabs ESP32 3.5" TFT Touch with Camera](https://www.makerfabs.com/esp32-3.5-inch-tft-touch-capacitive-with-camera.html)
|
||||
* [Makerfabs ESP32-S3 TFT 4.0"](https://www.makerfabs.com/esp32-s3-parallel-tft-with-touch-4-inch.html) [[demo video](https://youtu.be/Fmxd-Xu97C8)]
|
||||
* [Makerfabs ESP32-S3 TFT 4.3" v1.3](https://www.makerfabs.com/esp32-s3-parallel-tft-with-touch-4-3-inch.html) [[demo video](https://youtu.be/oQ57L2gTHoo)]
|
||||
* [Odroid Go](https://www.hardkernel.com/shop/odroid-go/)
|
||||
* [seeed studio Wio Terminal](https://wiki.seeedstudio.com/Wio-Terminal-Getting-Started/)
|
||||
* [Waveshare RP2040-LCD-0.96](https://www.waveshare.com/rp2040-lcd-0.96.htm?&aff_id=107987)
|
||||
* [Waveshare RP2040-LCD-1.28](https://www.waveshare.com/rp2040-lcd-1.28.htm?&aff_id=107987)
|
||||
* [Waveshare RP2350-LCD-0.96](https://www.waveshare.com/rp2350-lcd-0.96.htm?&aff_id=107987)
|
||||
* [Waveshare ESP32-C6-LCD-1.47](https://www.waveshare.com/esp32-c6-lcd-1.47.htm?&aff_id=107987)
|
||||
* [Waveshare ESP32-S3-Touch-LCD-2.8](https://www.waveshare.com/esp32-s3-touch-lcd-2.8.htm?&aff_id=107987)
|
||||
* [wireless-tag WT-32-SC01](http://www.wireless-tag.com/portfolio/wt32-sc01/)
|
||||
* [Elecrow ESP Terminal with 3.5" parallel RGB display DLC35010R](https://www.elecrow.com/esp-terminal-with-esp32-3-5-inch-parallel-480x320-tft-capacitive-touch-display-rgb-by-chip-ili9488.html) [[demo video](https://youtu.be/QRDVuwayNFw)]
|
||||
* [Elecrow Wizee-ESP32 WZ8048C050](https://www.elecrow.com/esp32-display-5-inch-hmi-display-rgb-tft-lcd-touch-screen-support-lvgl.html)
|
||||
* [wireless-tag ZX2D10GE10R-V4848](https://github.com/wireless-tag-com/ZX2D10GE01R-V4848)
|
||||
* [wireless-tag ZX3D50CE02S](https://github.com/wireless-tag-com/ZX3D50CE02S)
|
||||
* [wireless-tag ZX3D95CE01S-AR](https://github.com/wireless-tag-com/ZX3D95CE01S-AR-4848)
|
||||
* [wireless-tag ZX3D95CE01S-TR](https://github.com/wireless-tag-com/ZX3D95CE01S-TR-4848) [[demo video](https://www.youtube.com/shorts/5u6_C-krK2Q)]
|
||||
* [QM Smart Panlee 7.0 inch serial screen ZX7D00CE01S](http://en.smartpanle.com/product-item-19.html) [[demo video](https://youtu.be/r-zAMUzpkGE)]
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Supported Display</summary>
|
||||
|
||||
### Currently Supported Display [[Wiki](https://github.com/moononournation/Arduino_GFX/wiki/Display-Class)]
|
||||
|
||||
* GC9A01 240x240 round display [[demo video](https://youtu.be/kJrAFm20-zg)]
|
||||
* GC9106 80x160 [[demo video](https://youtu.be/RToGeeb1jxQ)]
|
||||
* GC9107 128x128 [[demo video](https://youtube.com/shorts/V1MCQ1tQ8PM)]
|
||||
* GC9503V 480x480 (RGB) [[demo video](https://youtube.com/shorts/hk7ZMBRCmjI)]
|
||||
* HX8347C 240x320 [[demo video](https://youtu.be/25ymuV51YQM)]
|
||||
* HX8347D 240x320 [[demo video](https://youtu.be/sv6LGkLRZjI)]
|
||||
* HX8352C 240x400 [[demo video](https://youtu.be/m2xWYbS3t7s)]
|
||||
* HX8357A 320x480 [[demo video](https://youtu.be/wJkLO_xCTXA)] (currently only portrait works, i.e. rotation 0 and 2)
|
||||
* HX8357B 320x480 (9-bit SPI) [[demo video](https://youtu.be/pB6_LOCiUqg)]
|
||||
* HX8369A 480x800 [[demo video](https://youtu.be/sXpU8bhtXKQ)] [[LVGL demo video](https://youtu.be/q575lTuVDcU)]
|
||||
* ILI6122 480x800 (RGB)
|
||||
* ILI6485 480x272 (RGB) [[demo video](https://youtu.be/60rl7QoU4Sc)]
|
||||
* ILI9225 176x220 [[demo video](https://youtu.be/jm2UrCG27F4)]
|
||||
* ILI9341 240x320 [[demo video](https://youtu.be/NtlEEL7MkQY)]
|
||||
* ILI9341 240x320 (8-bit/16-bit Parallel) [[demo video](https://youtu.be/xuVx0dzQ7nM)]
|
||||
* ILI9342 320x240 [[demo video](https://youtu.be/UoPpIjVSO5Q)]
|
||||
* ILI9481 320x480 (18 bit color) [[demo video](https://youtu.be/YxjuuCFhlqM)]
|
||||
* ILI9486 320x480 (8-bit/16-bit Parallel) [[demo video](https://youtu.be/GB90AFSLIFo)]
|
||||
* ILI9486 320x480 (18 bit color) [[demo video](https://youtu.be/pZ6izDqmVds)]
|
||||
* ILI9488 320x480 (3 bit color with canvas) [[demo video](https://youtu.be/r7be0WbIBYk)]
|
||||
* ILI9488 320x480 (18 bit color) [[demo video](https://youtu.be/NkE-LhtLHBQ)]
|
||||
* ILI9806 (8-bit/16-bit Parallel) 480x854 [[demo video](https://youtu.be/mYv-wdtWr8s)] [[LVGL demo video](https://youtu.be/PqjV8lovg_c)][[2](https://youtu.be/j31KZoQUKis)]
|
||||
* JBT6K71 240x320 (8-bit Parallel) [[demo video](https://youtu.be/qid3F4Gb0mM)]
|
||||
* NT35310 320x480 [[demo video](https://youtu.be/bvIz5CoYPNk)]
|
||||
* NT35510 480x800 (8-bit/16-bit Parallel) [[demo video](https://youtu.be/C_1ASzUN3bg)]
|
||||
* NT39125 240x376 (8-bit/16-bit Parallel) [[demo video](https://youtu.be/JGMrM18JAFA)]
|
||||
* NV3041A 480x272 [[demo video](https://youtu.be/pd1DTW9QHkg)]
|
||||
* OTM8009A 480x800 (8-bit/16-bit Parallel)
|
||||
* R61529 320x480 (8-bit/16-bit Parallel) [[demo video](https://youtu.be/s93gxjbIAT8)]
|
||||
* Raspberry Pi DPI Display (RPi_DPI_RGBPanel) Any Resolution [[demo video](https://youtube.com/shorts/IqQEq-VLVwI)]
|
||||
* SEPS525 160x128 [[demo video](https://youtu.be/tlmvFBHYv-k)]
|
||||
* SSD1283A 130x130 [[demo video](https://youtu.be/OrIchaRikiQ)]
|
||||
* SSD1331 96x64 [[demo video](https://youtu.be/v20b1A_KDcQ)]
|
||||
* SSD1351 128x128 [[demo video](https://youtu.be/5TIM-qMVBNQ)]
|
||||
* SSD1351 128x96
|
||||
* ST7735 128x160 (various tabs) [[demo video](https://youtu.be/eRBSSD_N9II)]
|
||||
* ST7735 128x128 (various tabs) [[demo video](https://youtu.be/6rueSV2Ee6c)]
|
||||
* ST7735 80x160 [[demo video](https://youtu.be/qESHDuYo_Mk)]
|
||||
* ST7701 480x480 (RGB) [[demo video](https://youtube.com/shorts/JV8Rzxop5EQ)] [[2.1" round display demo video](https://youtube.com/shorts/WLWio1CjBoo?feature=share)] [[2.8" round display demo video](https://youtube.com/shorts/Ih_QlttWTVk?feature=share)]
|
||||
* ST7789 135x240 [[demo video](https://youtu.be/Zk81_T8c20E)]
|
||||
* ST7789 240x240 [[demo video](https://youtu.be/Z27zYg5uAsk)]
|
||||
* ST7789 240x240 [[demo video](https://youtu.be/9AqsXMB8Qbk)]
|
||||
* ST7789 240x280 round corner display [[demo video](https://youtu.be/KzDC02wg8z0)]
|
||||
* ST7789 240x320 [[demo video](https://youtu.be/ZEvc1LkuVuQ)]
|
||||
* ST7796 320x480 [[demo video](https://youtu.be/hUL-RuG4MAQ)]
|
||||
* WEA2012 356x400 [[demo video](https://youtube.com/shorts/neDyijFrfQY)] [[LVGL demo video](https://youtube.com/shorts/z9Z_u0xg_as)]
|
||||
|
||||
### Tobe Support Display (Sponsors can make it happen)
|
||||
|
||||
* Mono display supported by co-operate with Canvas
|
||||
* Multi-color e-ink display supported by co-operate with Canvas
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Canvas (framebuffer)</summary>
|
||||
|
||||
### Canvas Class [[Wiki](https://github.com/moononournation/Arduino_GFX/wiki/Canvas-Class)]
|
||||
|
||||
* Arduino_Canvas (16-bit pixel)
|
||||
* Arduino_Canvas_3bit (1/4 memory space of 16-bit pixel)
|
||||
* Arduino_Canvas_Indexed (half memory space of 16-bit pixel)
|
||||
* Arduino_Canvas_Mono (1/16 memory space of 16-bit pixel)
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
||||
<summary>LVGL Support</summary>
|
||||
|
||||
### 3 LVGL demo in Library Examples
|
||||
|
||||
* LvglBenchmark [[demo video](https://youtu.be/75Qx-UEgabY)]
|
||||
* LvglHelloWorld
|
||||
* LvglWidgets
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Feature Wishlist</summary>
|
||||
|
||||
### Sponsors can make it happen
|
||||
|
||||
* Print color Emoji Characters
|
||||
* Load bitmap font files from flash / SD
|
||||
* Fill Gradient (Discussion #128)
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Using source code come from</summary>
|
||||
|
||||
* <https://github.com/adafruit/Adafruit-GFX-Library.git>
|
||||
* <https://github.com/adafruit/Adafruit_ILI9341.git>
|
||||
* <https://github.com/adafruit/Adafruit-SSD1351-library.git>
|
||||
* <https://github.com/ananevilya/Arduino-ST7789-Library.git>
|
||||
* <https://github.com/BasementCat/arduino-tft-gif.git>
|
||||
* <https://github.com/Bodmer/TFT_eSPI.git>
|
||||
* <https://github.com/daumemo/IPS_LCD_R61529_FT6236_Arduino_eSPI_Test.git>
|
||||
* <https://github.com/espressif/arduino-esp32.git>
|
||||
* <https://github.com/espressif/esp-idf.git>
|
||||
* <https://github.com/gitcnd/LCDWIKI_SPI.git>
|
||||
* <https://github.com/hi631/LCD_NT35510-MRB3971.git>
|
||||
* <https://github.com/lcdwiki/LCDWIKI_SPI.git>
|
||||
* <https://github.com/Xinyuan-LilyGO/T-RGB.git>
|
||||
* <https://github.com/lovyan03/LovyanGFX.git>
|
||||
* <https://github.com/modi12jin/Arduino-ESP32-WEA2012.git>
|
||||
* <https://github.com/nopnop2002/esp-idf-parallel-tft.git>
|
||||
* <https://github.com/olikraus/u8g2.git>
|
||||
|
||||
</details>
|
||||
|
||||
## Sponsorship vs Support
|
||||
|
||||
As you may already aware there are lack of sponsorship in this project. Convert the funding in terms of man power, it is much lower than 1 man hour per month. So don't expect too much on the support. Expecially the features not realted to my planned maker projects ;>
|
||||
|
||||
For the same reason, Arduino_GFX only focus on the Arduino IDE support. Any other IDE, e.g. PlatformIO, if you found an issue at that IDE but normal at Arduino IDE, please direct report to that IDE for better support.
|
||||
@@ -0,0 +1,71 @@
|
||||
#!/usr/bin/perl -w
|
||||
|
||||
# original source: https://gist.github.com/don/5748655
|
||||
|
||||
# Run this from the Arduino library directory to generate keywords.txt
|
||||
# Optionally pass the name of the library as the first argument
|
||||
|
||||
# $ gen_keywords.pl Foo > keywords.txt
|
||||
|
||||
use strict;
|
||||
use File::Find::Rule qw( );
|
||||
|
||||
my $in_public = 0;
|
||||
my %class;
|
||||
my %func;
|
||||
my $curr_class;
|
||||
|
||||
my @h_files = File::Find::Rule->name('*.h')->in("src");
|
||||
|
||||
print <<EOF;
|
||||
#######################################
|
||||
# Syntax Coloring Map For Arduino_GFX
|
||||
#######################################
|
||||
|
||||
EOF
|
||||
|
||||
for my $header (@h_files) {
|
||||
open(my $fh, $header) or die "Couldn't open $header: $!";
|
||||
|
||||
while (<$fh>) {
|
||||
if (/^class (\w+)/) {
|
||||
$class{$1}++;
|
||||
$curr_class = $1;
|
||||
}
|
||||
if (/public:/) {
|
||||
$in_public = 1;
|
||||
}
|
||||
if ($in_public) {
|
||||
if (/private:/ || /};/) {
|
||||
$in_public = 0;
|
||||
} elsif (/(\w+)\(/) {
|
||||
if ($1 ne $curr_class) {
|
||||
$func{$1}++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
print <<EOF;
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
|
||||
EOF
|
||||
|
||||
foreach (sort keys %class) {
|
||||
print "$_ KEYWORD1\n";
|
||||
}
|
||||
|
||||
print <<EOF;
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
|
||||
EOF
|
||||
|
||||
foreach (sort keys %func) {
|
||||
print "$_ KEYWORD2\n";
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
name=GFX Library for Arduino
|
||||
version=1.5.5
|
||||
author=Moon On Our Nation <moononournation@gmail.com>
|
||||
maintainer=Moon On Our Nation <moononournation@gmail.com>
|
||||
sentence=Arduino_GFX is a GFX library for various color displays with various data bus interfaces
|
||||
paragraph=Arduino_GFX is a Arduino graphics library. Currently support GC9A01 round display, GC9106, GC9107, HX8347C, HX8347D, HX8352C, HX8357A, HX8357B, HX8369A, ILI6122, ILI9225, ILI9331, ILI9341, ILI9342(M5Stack, ESP32-S3-BOX), ILI9481, ILI9486, ILI9488, ILI9806, JBT6K71, NT35310, NT35510, NT39125, NV3041A, OTM8009A, R61529, RM67162, SEPS525, SSD1283A, SSD1331, SSD1351, ST7735, ST7789, ST7796 and virtually all Raspberry Pi DPI (RGB) display. Tested RGB display: GC9503V, ILI6485, ST7262, ST7701. Currently support software SPI (8-bit and 9-bit), hardware SPI (8-bit, ESP32 also support 9-bit), 8-bit parallel interface(AVR, ESP32, RPi Pico, RTL8720, STM32), 16-bit parallel interface(ESP32 and RPi Pico) and RGB Panel interface(ESP32S3).
|
||||
url=https://github.com/moononournation/Arduino_GFX
|
||||
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* start rewrite from:
|
||||
* https://github.com/adafruit/Adafruit-GFX-Library.git
|
||||
*/
|
||||
#include "Arduino_DataBus.h"
|
||||
|
||||
Arduino_DataBus::Arduino_DataBus() {}
|
||||
|
||||
void Arduino_DataBus::writeC8D8(uint8_t c, uint8_t d)
|
||||
{
|
||||
writeCommand(c);
|
||||
write(d);
|
||||
}
|
||||
|
||||
void Arduino_DataBus::writeC8D16(uint8_t c, uint16_t d)
|
||||
{
|
||||
writeCommand(c);
|
||||
write16(d);
|
||||
}
|
||||
|
||||
void Arduino_DataBus::writeC16D16(uint16_t c, uint16_t d)
|
||||
{
|
||||
writeCommand16(c);
|
||||
write16(d);
|
||||
}
|
||||
|
||||
void Arduino_DataBus::writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2)
|
||||
{
|
||||
writeCommand(c);
|
||||
write16(d1);
|
||||
write16(d2);
|
||||
}
|
||||
|
||||
void Arduino_DataBus::writeC8D16D16Split(uint8_t c, uint16_t d1, uint16_t d2)
|
||||
{
|
||||
writeCommand(c);
|
||||
_data16.value = d1;
|
||||
write(_data16.msb);
|
||||
write(_data16.lsb);
|
||||
_data16.value = d2;
|
||||
write(_data16.msb);
|
||||
write(_data16.lsb);
|
||||
}
|
||||
|
||||
void Arduino_DataBus::sendCommand(uint8_t c)
|
||||
{
|
||||
beginWrite();
|
||||
writeCommand(c);
|
||||
endWrite();
|
||||
}
|
||||
|
||||
void Arduino_DataBus::sendCommand16(uint16_t c)
|
||||
{
|
||||
beginWrite();
|
||||
writeCommand16(c);
|
||||
endWrite();
|
||||
}
|
||||
|
||||
void Arduino_DataBus::sendData(uint8_t d)
|
||||
{
|
||||
beginWrite();
|
||||
write(d);
|
||||
endWrite();
|
||||
}
|
||||
|
||||
void Arduino_DataBus::sendData16(uint16_t d)
|
||||
{
|
||||
beginWrite();
|
||||
write16(d);
|
||||
endWrite();
|
||||
}
|
||||
|
||||
void Arduino_DataBus::batchOperation(const uint8_t *operations, size_t len)
|
||||
{
|
||||
for (size_t i = 0; i < len; ++i)
|
||||
{
|
||||
uint8_t l = 0;
|
||||
switch (operations[i])
|
||||
{
|
||||
case BEGIN_WRITE:
|
||||
beginWrite();
|
||||
break;
|
||||
case WRITE_C8_D16:
|
||||
l++;
|
||||
/* fall through */
|
||||
case WRITE_C8_D8:
|
||||
l++;
|
||||
/* fall through */
|
||||
case WRITE_COMMAND_8:
|
||||
writeCommand(operations[++i]);
|
||||
break;
|
||||
case WRITE_C16_D16:
|
||||
l = 2;
|
||||
/* fall through */
|
||||
case WRITE_COMMAND_16:
|
||||
_data16.msb = operations[++i];
|
||||
_data16.lsb = operations[++i];
|
||||
writeCommand16(_data16.value);
|
||||
break;
|
||||
case WRITE_COMMAND_BYTES:
|
||||
l = operations[++i];
|
||||
writeCommandBytes((uint8_t *)(operations + i + 1), l);
|
||||
i += l;
|
||||
l = 0;
|
||||
break;
|
||||
case WRITE_DATA_8:
|
||||
l = 1;
|
||||
break;
|
||||
case WRITE_DATA_16:
|
||||
l = 2;
|
||||
break;
|
||||
case WRITE_BYTES:
|
||||
l = operations[++i];
|
||||
break;
|
||||
case WRITE_C8_BYTES:
|
||||
writeCommand(operations[++i]);
|
||||
l = operations[++i];
|
||||
break;
|
||||
case END_WRITE:
|
||||
endWrite();
|
||||
break;
|
||||
case DELAY:
|
||||
delay(operations[++i]);
|
||||
break;
|
||||
default:
|
||||
printf("Unknown operation id at %d: %d\n", i, operations[i]);
|
||||
break;
|
||||
}
|
||||
while (l--)
|
||||
{
|
||||
write(operations[++i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(LITTLE_FOOT_PRINT)
|
||||
void Arduino_DataBus::write16bitBeRGBBitmapR1(uint16_t *bitmap, int16_t w, int16_t h)
|
||||
{
|
||||
uint16_t *p;
|
||||
for (int16_t i = 0; i < w; i++)
|
||||
{
|
||||
p = bitmap + ((h - 1) * w) + i;
|
||||
for (int16_t j = 0; j < h; j++)
|
||||
{
|
||||
_data16.value = *p;
|
||||
write(_data16.lsb);
|
||||
write(_data16.msb);
|
||||
p -= w;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_DataBus::writePattern(uint8_t *data, uint8_t len, uint32_t repeat)
|
||||
{
|
||||
while (repeat--)
|
||||
{
|
||||
writeBytes(data, len);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_DataBus::writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
write16(idx[*(data++)]);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_DataBus::writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len)
|
||||
{
|
||||
uint8_t *d = data;
|
||||
while (len--)
|
||||
{
|
||||
_data16.value = idx[*(d++)];
|
||||
write(_data16.msb);
|
||||
write(_data16.lsb);
|
||||
write(_data16.msb);
|
||||
write(_data16.lsb);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_DataBus::writeYCbCrPixels(uint8_t *yData, uint8_t *cbData, uint8_t *crData, uint16_t w, uint16_t h)
|
||||
{
|
||||
int cols = w >> 1;
|
||||
|
||||
uint8_t pxCb, pxCr;
|
||||
int16_t pxR, pxG, pxB, pxY;
|
||||
|
||||
for (int row = 0; row < h;)
|
||||
{
|
||||
for (int col = 0; col < cols; ++col)
|
||||
{
|
||||
pxCb = *cbData++;
|
||||
pxCr = *crData++;
|
||||
pxR = CR2R16[pxCr];
|
||||
pxG = -CB2G16[pxCb] - CR2G16[pxCr];
|
||||
pxB = CB2B16[pxCb];
|
||||
|
||||
pxY = Y2I16[*yData++];
|
||||
_data16.value = CLIPRBE[pxY + pxR] | CLIPGBE[pxY + pxG] | CLIPBBE[pxY + pxB];
|
||||
write(_data16.lsb);
|
||||
write(_data16.msb);
|
||||
pxY = Y2I16[*yData++];
|
||||
_data16.value = CLIPRBE[pxY + pxR] | CLIPGBE[pxY + pxG] | CLIPBBE[pxY + pxB];
|
||||
write(_data16.lsb);
|
||||
write(_data16.msb);
|
||||
}
|
||||
|
||||
if (++row & 1)
|
||||
{
|
||||
// rollback CbCr data
|
||||
cbData -= cols;
|
||||
crData -= cols;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
@@ -0,0 +1,307 @@
|
||||
/*
|
||||
* start rewrite from:
|
||||
* https://github.com/adafruit/Adafruit-GFX-Library.git
|
||||
*/
|
||||
#ifndef _ARDUINO_DATABUS_H_
|
||||
#define _ARDUINO_DATABUS_H_
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#include "YCbCr2RGB.h"
|
||||
|
||||
#define GFX_SKIP_OUTPUT_BEGIN -2
|
||||
#define GFX_NOT_DEFINED -1
|
||||
#define GFX_STR_HELPER(x) #x
|
||||
#define GFX_STR(x) GFX_STR_HELPER(x)
|
||||
|
||||
#if defined(__AVR__)
|
||||
#define LITTLE_FOOT_PRINT // reduce program size for limited flash MCU
|
||||
#define USE_FAST_PINIO ///< Use direct PORT register access
|
||||
typedef uint8_t ARDUINOGFX_PORT_t;
|
||||
#elif defined(ARDUINO_ARCH_AIRMCU)
|
||||
#define LITTLE_FOOT_PRINT // reduce program size for limited flash MCU
|
||||
#define USE_FAST_PINIO ///< Use direct PORT register access
|
||||
typedef uint32_t ARDUINOGFX_PORT_t;
|
||||
#elif defined(ARDUINO_ARCH_NRF52840)
|
||||
#define USE_FAST_PINIO ///< Use direct PORT register access
|
||||
#define HAS_PORT_SET_CLR ///< PORTs have set & clear registers
|
||||
typedef uint32_t ARDUINOGFX_PORT_t;
|
||||
#elif defined(ARDUINO_UNOR4_MINIMA) || defined(ARDUINO_UNOR4_WIFI)
|
||||
#define USE_FAST_PINIO ///< Use direct PORT register access
|
||||
#define HAS_PORT_SET_CLR ///< PORTs have set & clear registers
|
||||
typedef uint16_t ARDUINOGFX_PORT_t;
|
||||
#elif defined(TARGET_RP2040) || defined(PICO_RP2350)
|
||||
#define USE_FAST_PINIO ///< Use direct PORT register access
|
||||
#define HAS_PORT_SET_CLR ///< PORTs have set & clear registers
|
||||
typedef uint32_t ARDUINOGFX_PORT_t;
|
||||
#elif defined(ESP32)
|
||||
#define USE_FAST_PINIO ///< Use direct PORT register access
|
||||
#define HAS_PORT_SET_CLR ///< PORTs have set & clear registers
|
||||
typedef uint32_t ARDUINOGFX_PORT_t;
|
||||
#elif defined(ESP8266)
|
||||
#define ESP8266SAFEBATCHBITSIZE (2048 * 8 * 9)
|
||||
#define USE_FAST_PINIO ///< Use direct PORT register access
|
||||
typedef uint32_t ARDUINOGFX_PORT_t;
|
||||
#elif defined(ARDUINO_ARCH_STM32)
|
||||
#define USE_FAST_PINIO ///< Use direct PORT register access
|
||||
typedef uint32_t ARDUINOGFX_PORT_t;
|
||||
#elif defined(__arm__)
|
||||
#if defined(ARDUINO_ARCH_SAMD)
|
||||
// Adafruit M0, M4
|
||||
#define USE_FAST_PINIO ///< Use direct PORT register access
|
||||
#define HAS_PORT_SET_CLR ///< PORTs have set & clear registers
|
||||
typedef uint32_t ARDUINOGFX_PORT_t;
|
||||
#elif defined(CONFIG_ARCH_CHIP_CXD56XX) // Sony Spresense
|
||||
#define USE_FAST_PINIO ///< Use direct PORT register access
|
||||
typedef uint8_t ARDUINOGFX_PORT_t;
|
||||
#elif defined(RTL8722DM)
|
||||
#define USE_FAST_PINIO ///< Use direct PORT register access
|
||||
typedef uint32_t ARDUINOGFX_PORT_t;
|
||||
#elif defined(CORE_TEENSY)
|
||||
#define USE_FAST_PINIO ///< Use direct PORT register access
|
||||
#define HAS_PORT_SET_CLR ///< PORTs have set & clear registers
|
||||
#if defined(__IMXRT1052__) || defined(__IMXRT1062__)
|
||||
// PJRC Teensy 4.x
|
||||
typedef uint32_t ARDUINOGFX_PORT_t;
|
||||
#else
|
||||
// PJRC Teensy 3.x
|
||||
typedef uint8_t ARDUINOGFX_PORT_t;
|
||||
#endif
|
||||
#else
|
||||
// Arduino Due?
|
||||
// USE_FAST_PINIO not available here (yet)...Due has a totally different
|
||||
// GPIO register set and will require some changes elsewhere (e.g. in
|
||||
// constructors especially).
|
||||
#endif
|
||||
#else // !ARM
|
||||
// Unknow architecture, USE_FAST_PINIO is not available here (yet)
|
||||
// but don't worry about it too much...the digitalWrite() implementation
|
||||
// on these platforms is reasonably efficient and already RAM-resident,
|
||||
// only gotcha then is no parallel connection support for now.
|
||||
#endif // !ARM
|
||||
|
||||
#ifdef USE_FAST_PINIO
|
||||
typedef volatile ARDUINOGFX_PORT_t *PORTreg_t;
|
||||
#endif
|
||||
|
||||
#if defined(ARDUINO_ARCH_ARC32) || defined(ARDUINO_MAXIM)
|
||||
#define SPI_DEFAULT_FREQ 16000000
|
||||
// Teensy 3.0, 3.1/3.2, 3.5, 3.6
|
||||
#elif defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
|
||||
#define SPI_DEFAULT_FREQ 40000000
|
||||
// Teensy 4.x
|
||||
#elif defined(__IMXRT1052__) || defined(__IMXRT1062__)
|
||||
#define SPI_DEFAULT_FREQ 40000000
|
||||
#elif defined(__AVR__) || defined(TEENSYDUINO)
|
||||
#define SPI_DEFAULT_FREQ 8000000
|
||||
#elif defined(ARDUINO_ARCH_NRF52840)
|
||||
#define SPI_DEFAULT_FREQ 8000000
|
||||
#elif defined(ESP8266) || defined(ESP32)
|
||||
#define SPI_DEFAULT_FREQ 40000000
|
||||
#elif defined(RTL8722DM)
|
||||
#define SPI_DEFAULT_FREQ 20000000
|
||||
#elif defined(RASPI)
|
||||
#define SPI_DEFAULT_FREQ 80000000
|
||||
#elif defined(ARDUINO_ARCH_STM32F1)
|
||||
#define SPI_DEFAULT_FREQ 36000000
|
||||
#elif defined(ARDUINO_BLACKPILL_F411CE)
|
||||
#define SPI_DEFAULT_FREQ 50000000
|
||||
#elif defined(F_CPU)
|
||||
#define SPI_DEFAULT_FREQ (F_CPU / 4)
|
||||
#else
|
||||
#define SPI_DEFAULT_FREQ 24000000 ///< Default SPI data clock frequency
|
||||
#endif
|
||||
|
||||
#ifndef UNUSED
|
||||
#define UNUSED(x) (void)(x)
|
||||
#endif
|
||||
#define ATTR_UNUSED __attribute__((unused))
|
||||
|
||||
#define MSB_16(val) (((val) & 0xFF00) >> 8) | (((val) & 0xFF) << 8)
|
||||
#define MSB_16_SET(var, val) \
|
||||
{ \
|
||||
(var) = MSB_16(val); \
|
||||
}
|
||||
#define MSB_32_SET(var, val) \
|
||||
{ \
|
||||
uint8_t *v = (uint8_t *)&(val); \
|
||||
(var) = v[3] | (v[2] << 8) | (v[1] << 16) | (v[0] << 24); \
|
||||
}
|
||||
#define MSB_32_16_16_SET(var, v1, v2) \
|
||||
{ \
|
||||
(var) = (((uint32_t)v2 & 0xff00) << 8) | (((uint32_t)v2 & 0xff) << 24) | ((v1 & 0xff00) >> 8) | ((v1 & 0xff) << 8); \
|
||||
}
|
||||
#define MSB_32_8_ARRAY_SET(var, a) \
|
||||
{ \
|
||||
(var) = ((uint32_t)a[0] << 8 | a[1] | a[2] << 24 | a[3] << 16); \
|
||||
}
|
||||
|
||||
#if !defined(LITTLE_FOOT_PRINT)
|
||||
#define GFX_INLINE __attribute__((always_inline)) inline
|
||||
#else
|
||||
#define GFX_INLINE inline
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
|
||||
#if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)
|
||||
#if (!defined(ESP_ARDUINO_VERSION_MAJOR)) || (ESP_ARDUINO_VERSION_MAJOR < 3)
|
||||
#include <esp_lcd_panel_io.h>
|
||||
#include <esp_lcd_panel_io_interface.h>
|
||||
#include <esp_pm.h>
|
||||
#include <esp_private/gdma.h>
|
||||
#include <hal/dma_types.h>
|
||||
#include <hal/lcd_hal.h>
|
||||
#include <soc/dport_reg.h>
|
||||
#include <soc/gpio_sig_map.h>
|
||||
#include <soc/lcd_cam_reg.h>
|
||||
#include <soc/lcd_cam_struct.h>
|
||||
|
||||
typedef struct esp_lcd_i80_bus_t esp_lcd_i80_bus_t;
|
||||
typedef struct lcd_panel_io_i80_t lcd_panel_io_i80_t;
|
||||
typedef struct lcd_i80_trans_descriptor_t lcd_i80_trans_descriptor_t;
|
||||
|
||||
struct esp_lcd_i80_bus_t
|
||||
{
|
||||
int bus_id; // Bus ID, index from 0
|
||||
portMUX_TYPE spinlock; // spinlock used to protect i80 bus members(hal, device_list, cur_trans)
|
||||
lcd_hal_context_t hal; // Hal object
|
||||
size_t bus_width; // Number of data lines
|
||||
intr_handle_t intr; // LCD peripheral interrupt handle
|
||||
esp_pm_lock_handle_t pm_lock; // Power management lock
|
||||
size_t num_dma_nodes; // Number of DMA descriptors
|
||||
uint8_t *format_buffer; // The driver allocates an internal buffer for DMA to do data format transformer
|
||||
size_t resolution_hz; // LCD_CLK resolution, determined by selected clock source
|
||||
gdma_channel_handle_t dma_chan; // DMA channel handle
|
||||
size_t psram_trans_align; // DMA transfer alignment for data allocated from PSRAM
|
||||
size_t sram_trans_align; // DMA transfer alignment for data allocated from SRAM
|
||||
lcd_i80_trans_descriptor_t *cur_trans; // Current transaction
|
||||
lcd_panel_io_i80_t *cur_device; // Current working device
|
||||
LIST_HEAD(i80_device_list, lcd_panel_io_i80_t)
|
||||
device_list; // Head of i80 device list
|
||||
struct
|
||||
{
|
||||
unsigned int exclusive : 1; // Indicate whether the I80 bus is owned by one device (whose CS GPIO is not assigned) exclusively
|
||||
} flags;
|
||||
dma_descriptor_t dma_nodes[]; // DMA descriptor pool, the descriptors are shared by all i80 devices
|
||||
};
|
||||
|
||||
struct lcd_i80_trans_descriptor_t
|
||||
{
|
||||
lcd_panel_io_i80_t *i80_device; // i80 device issuing this transaction
|
||||
int cmd_value; // Command value
|
||||
uint32_t cmd_cycles; // Command cycles
|
||||
const void *data; // Data buffer
|
||||
uint32_t data_length; // Data buffer size
|
||||
void *user_ctx; // private data used by trans_done_cb
|
||||
esp_lcd_panel_io_color_trans_done_cb_t trans_done_cb; // transaction done callback
|
||||
};
|
||||
|
||||
struct lcd_panel_io_i80_t
|
||||
{
|
||||
esp_lcd_panel_io_t base; // Base class of generic lcd panel io
|
||||
esp_lcd_i80_bus_t *bus; // Which bus the device is attached to
|
||||
int cs_gpio_num; // GPIO used for CS line
|
||||
unsigned int pclk_hz; // PCLK clock frequency
|
||||
size_t clock_prescale; // Prescaler coefficient, determined by user's configured PCLK frequency
|
||||
QueueHandle_t trans_queue; // Transaction queue, transactions in this queue are pending for scheduler to dispatch
|
||||
QueueHandle_t done_queue; // Transaction done queue, transactions in this queue are finished but not recycled by the caller
|
||||
size_t queue_size; // Size of transaction queue
|
||||
size_t num_trans_inflight; // Number of transactions that are undergoing (the descriptor not recycled yet)
|
||||
int lcd_cmd_bits; // Bit width of LCD command
|
||||
int lcd_param_bits; // Bit width of LCD parameter
|
||||
void *user_ctx; // private data used when transfer color data
|
||||
esp_lcd_panel_io_color_trans_done_cb_t on_color_trans_done; // color data trans done callback
|
||||
LIST_ENTRY(lcd_panel_io_i80_t)
|
||||
device_list_entry; // Entry of i80 device list
|
||||
struct
|
||||
{
|
||||
unsigned int dc_idle_level : 1; // Level of DC line in IDLE phase
|
||||
unsigned int dc_cmd_level : 1; // Level of DC line in CMD phase
|
||||
unsigned int dc_dummy_level : 1; // Level of DC line in DUMMY phase
|
||||
unsigned int dc_data_level : 1; // Level of DC line in DATA phase
|
||||
} dc_levels;
|
||||
struct
|
||||
{
|
||||
unsigned int cs_active_high : 1; // Whether the CS line is active on high level
|
||||
unsigned int reverse_color_bits : 1; // Reverse the data bits, D[N:0] -> D[0:N]
|
||||
unsigned int swap_color_bytes : 1; // Swap adjacent two data bytes before sending out
|
||||
unsigned int pclk_active_neg : 1; // The display will write data lines when there's a falling edge on WR line
|
||||
unsigned int pclk_idle_low : 1; // The WR line keeps at low level in IDLE phase
|
||||
} flags;
|
||||
lcd_i80_trans_descriptor_t trans_pool[]; // Transaction pool
|
||||
};
|
||||
#endif // #if (!defined(ESP_ARDUINO_VERSION_MAJOR)) || (ESP_ARDUINO_VERSION_MAJOR < 3)
|
||||
#endif // #if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)
|
||||
|
||||
typedef enum
|
||||
{
|
||||
BEGIN_WRITE,
|
||||
WRITE_COMMAND_8,
|
||||
WRITE_COMMAND_16,
|
||||
WRITE_COMMAND_BYTES,
|
||||
WRITE_DATA_8,
|
||||
WRITE_DATA_16,
|
||||
WRITE_BYTES,
|
||||
WRITE_C8_D8,
|
||||
WRITE_C8_D16,
|
||||
WRITE_C8_BYTES,
|
||||
WRITE_C16_D16,
|
||||
END_WRITE,
|
||||
DELAY,
|
||||
} spi_operation_type_t;
|
||||
|
||||
union
|
||||
{
|
||||
uint16_t value;
|
||||
struct
|
||||
{
|
||||
uint8_t lsb;
|
||||
uint8_t msb;
|
||||
};
|
||||
} _data16;
|
||||
|
||||
class Arduino_DataBus
|
||||
{
|
||||
public:
|
||||
Arduino_DataBus();
|
||||
|
||||
void unused() { UNUSED(_data16); } // avoid compiler warning
|
||||
|
||||
virtual bool begin(int32_t speed = SPI_DEFAULT_FREQ, int8_t dataMode = GFX_NOT_DEFINED) = 0;
|
||||
virtual void beginWrite() = 0;
|
||||
virtual void endWrite() = 0;
|
||||
virtual void writeCommand(uint8_t c) = 0;
|
||||
virtual void writeCommand16(uint16_t c) = 0;
|
||||
virtual void writeCommandBytes(uint8_t *data, uint32_t len) = 0;
|
||||
virtual void write(uint8_t) = 0;
|
||||
virtual void write16(uint16_t) = 0;
|
||||
virtual void writeC8D8(uint8_t c, uint8_t d);
|
||||
virtual void writeC16D16(uint16_t c, uint16_t d);
|
||||
virtual void writeC8D16(uint8_t c, uint16_t d);
|
||||
virtual void writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2);
|
||||
virtual void writeC8D16D16Split(uint8_t c, uint16_t d1, uint16_t d2);
|
||||
virtual void writeRepeat(uint16_t p, uint32_t len) = 0;
|
||||
virtual void writeBytes(uint8_t *data, uint32_t len) = 0;
|
||||
virtual void writePixels(uint16_t *data, uint32_t len) = 0;
|
||||
|
||||
void sendCommand(uint8_t c);
|
||||
void sendCommand16(uint16_t c);
|
||||
void sendData(uint8_t d);
|
||||
void sendData16(uint16_t d);
|
||||
|
||||
#if !defined(LITTLE_FOOT_PRINT)
|
||||
virtual void write16bitBeRGBBitmapR1(uint16_t *bitmap, int16_t w, int16_t h);
|
||||
virtual void batchOperation(const uint8_t *operations, size_t len);
|
||||
virtual void writePattern(uint8_t *data, uint8_t len, uint32_t repeat);
|
||||
virtual void writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len);
|
||||
virtual void writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len);
|
||||
virtual void writeYCbCrPixels(uint8_t *yData, uint8_t *cbData, uint8_t *crData, uint16_t w, uint16_t h);
|
||||
#else
|
||||
void batchOperation(const uint8_t *operations, size_t len);
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
|
||||
protected:
|
||||
int32_t _speed;
|
||||
int8_t _dataMode;
|
||||
};
|
||||
|
||||
#endif // _ARDUINO_DATABUS_H_
|
||||
@@ -0,0 +1,275 @@
|
||||
#include "Arduino_G.h"
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Instatiate a GFX context for graphics! Can only be done by a superclass
|
||||
@param w Display width, in pixels
|
||||
@param h Display height, in pixels
|
||||
*/
|
||||
/**************************************************************************/
|
||||
Arduino_G::Arduino_G(int16_t w, int16_t h) : WIDTH(w), HEIGHT(h)
|
||||
{
|
||||
}
|
||||
|
||||
// utility functions
|
||||
bool gfx_draw_bitmap_to_framebuffer(
|
||||
uint16_t *from_bitmap, int16_t bitmap_w, int16_t bitmap_h,
|
||||
uint16_t *framebuffer, int16_t x, int16_t y, int16_t framebuffer_w, int16_t framebuffer_h)
|
||||
{
|
||||
int16_t max_X = framebuffer_w - 1;
|
||||
int16_t max_Y = framebuffer_h - 1;
|
||||
if (
|
||||
((x + bitmap_w - 1) < 0) || // Outside left
|
||||
((y + bitmap_h - 1) < 0) || // Outside top
|
||||
(x > max_X) || // Outside right
|
||||
(y > max_Y) // Outside bottom
|
||||
)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
int16_t x_skip = 0;
|
||||
if ((y + bitmap_h - 1) > max_Y)
|
||||
{
|
||||
bitmap_h -= (y + bitmap_h - 1) - max_Y;
|
||||
}
|
||||
if (y < 0)
|
||||
{
|
||||
from_bitmap -= y * bitmap_w;
|
||||
bitmap_h += y;
|
||||
y = 0;
|
||||
}
|
||||
if ((x + bitmap_w - 1) > max_X)
|
||||
{
|
||||
x_skip = (x + bitmap_w - 1) - max_X;
|
||||
bitmap_w -= x_skip;
|
||||
}
|
||||
if (x < 0)
|
||||
{
|
||||
from_bitmap -= x;
|
||||
x_skip -= x;
|
||||
bitmap_w += x;
|
||||
x = 0;
|
||||
}
|
||||
|
||||
uint16_t *row = framebuffer;
|
||||
row += y * framebuffer_w; // shift framebuffer to y offset
|
||||
row += x; // shift framebuffer to x offset
|
||||
if (((framebuffer_w & 1) == 0) && ((x_skip & 1) == 0) && ((bitmap_w & 1) == 0))
|
||||
{
|
||||
uint32_t *row2 = (uint32_t *)row;
|
||||
uint32_t *from_bitmap2 = (uint32_t *)from_bitmap;
|
||||
int16_t framebuffer_w2 = framebuffer_w >> 1;
|
||||
int16_t xskip2 = x_skip >> 1;
|
||||
int16_t w2 = bitmap_w >> 1;
|
||||
|
||||
int16_t j = bitmap_h;
|
||||
while (j--)
|
||||
{
|
||||
for (int16_t i = 0; i < w2; ++i)
|
||||
{
|
||||
row2[i] = *from_bitmap2++;
|
||||
}
|
||||
from_bitmap2 += xskip2;
|
||||
row2 += framebuffer_w2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int16_t j = bitmap_h;
|
||||
while (j--)
|
||||
{
|
||||
for (int i = 0; i < bitmap_w; ++i)
|
||||
{
|
||||
row[i] = *from_bitmap++;
|
||||
}
|
||||
from_bitmap += x_skip;
|
||||
row += framebuffer_w;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool gfx_draw_bitmap_to_framebuffer_rotate_1(
|
||||
uint16_t *from_bitmap, int16_t bitmap_w, int16_t bitmap_h,
|
||||
uint16_t *framebuffer, int16_t x, int16_t y, int16_t framebuffer_w, int16_t framebuffer_h)
|
||||
{
|
||||
int16_t max_X = framebuffer_w - 1;
|
||||
int16_t max_Y = framebuffer_h - 1;
|
||||
if (
|
||||
((x + bitmap_w - 1) < 0) || // Outside left
|
||||
((y + bitmap_h - 1) < 0) || // Outside top
|
||||
(x > max_X) || // Outside right
|
||||
(y > max_Y) // Outside bottom
|
||||
)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
int16_t x_skip = 0;
|
||||
if ((y + bitmap_h - 1) > max_Y)
|
||||
{
|
||||
bitmap_h -= (y + bitmap_h - 1) - max_Y;
|
||||
}
|
||||
if (y < 0)
|
||||
{
|
||||
from_bitmap -= y * bitmap_w;
|
||||
bitmap_h += y;
|
||||
y = 0;
|
||||
}
|
||||
if ((x + bitmap_w - 1) > max_X)
|
||||
{
|
||||
x_skip = (x + bitmap_w - 1) - max_X;
|
||||
bitmap_w -= x_skip;
|
||||
}
|
||||
if (x < 0)
|
||||
{
|
||||
from_bitmap -= x;
|
||||
x_skip -= x;
|
||||
bitmap_w += x;
|
||||
x = 0;
|
||||
}
|
||||
|
||||
uint16_t *p;
|
||||
int16_t i;
|
||||
for (int16_t j = 0; j < bitmap_h; j++)
|
||||
{
|
||||
p = framebuffer;
|
||||
p += (x * framebuffer_h); // shift framebuffer to y offset
|
||||
p += (framebuffer_h - y - j); // shift framebuffer to x offset
|
||||
|
||||
i = bitmap_w;
|
||||
while (i--)
|
||||
{
|
||||
*p = *from_bitmap++;
|
||||
p += framebuffer_h;
|
||||
}
|
||||
from_bitmap += x_skip;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool gfx_draw_bitmap_to_framebuffer_rotate_2(
|
||||
uint16_t *from_bitmap, int16_t bitmap_w, int16_t bitmap_h,
|
||||
uint16_t *framebuffer, int16_t x, int16_t y, int16_t framebuffer_w, int16_t framebuffer_h)
|
||||
{
|
||||
int16_t max_X = framebuffer_w - 1;
|
||||
int16_t max_Y = framebuffer_h - 1;
|
||||
if (
|
||||
((x + bitmap_w - 1) < 0) || // Outside left
|
||||
((y + bitmap_h - 1) < 0) || // Outside top
|
||||
(x > max_X) || // Outside right
|
||||
(y > max_Y) // Outside bottom
|
||||
)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
int16_t x_skip = 0;
|
||||
if ((y + bitmap_h - 1) > max_Y)
|
||||
{
|
||||
bitmap_h -= (y + bitmap_h - 1) - max_Y;
|
||||
}
|
||||
if (y < 0)
|
||||
{
|
||||
from_bitmap -= y * bitmap_w;
|
||||
bitmap_h += y;
|
||||
y = 0;
|
||||
}
|
||||
if ((x + bitmap_w - 1) > max_X)
|
||||
{
|
||||
x_skip = (x + bitmap_w - 1) - max_X;
|
||||
bitmap_w -= x_skip;
|
||||
}
|
||||
if (x < 0)
|
||||
{
|
||||
from_bitmap -= x;
|
||||
x_skip -= x;
|
||||
bitmap_w += x;
|
||||
x = 0;
|
||||
}
|
||||
|
||||
uint16_t *row = framebuffer;
|
||||
row += (max_Y - y) * framebuffer_w; // shift framebuffer to y offset
|
||||
row += framebuffer_w - x - bitmap_w; // shift framebuffer to x offset
|
||||
int16_t i;
|
||||
int16_t j = bitmap_h;
|
||||
while (j--)
|
||||
{
|
||||
i = bitmap_w;
|
||||
while (i--)
|
||||
{
|
||||
row[i] = *from_bitmap++;
|
||||
}
|
||||
from_bitmap += x_skip;
|
||||
row -= framebuffer_w;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool gfx_draw_bitmap_to_framebuffer_rotate_3(
|
||||
uint16_t *from_bitmap, int16_t bitmap_w, int16_t bitmap_h,
|
||||
uint16_t *framebuffer, int16_t x, int16_t y, int16_t framebuffer_w, int16_t framebuffer_h)
|
||||
{
|
||||
int16_t max_X = framebuffer_w - 1;
|
||||
int16_t max_Y = framebuffer_h - 1;
|
||||
if (
|
||||
((x + bitmap_w - 1) < 0) || // Outside left
|
||||
((y + bitmap_h - 1) < 0) || // Outside top
|
||||
(x > max_X) || // Outside right
|
||||
(y > max_Y) // Outside bottom
|
||||
)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
int16_t x_skip = 0;
|
||||
if ((y + bitmap_h - 1) > max_Y)
|
||||
{
|
||||
bitmap_h -= (y + bitmap_h - 1) - max_Y;
|
||||
}
|
||||
if (y < 0)
|
||||
{
|
||||
from_bitmap -= y * bitmap_w;
|
||||
bitmap_h += y;
|
||||
y = 0;
|
||||
}
|
||||
if ((x + bitmap_w - 1) > max_X)
|
||||
{
|
||||
x_skip = (x + bitmap_w - 1) - max_X;
|
||||
bitmap_w -= x_skip;
|
||||
}
|
||||
if (x < 0)
|
||||
{
|
||||
from_bitmap -= x;
|
||||
x_skip -= x;
|
||||
bitmap_w += x;
|
||||
x = 0;
|
||||
}
|
||||
|
||||
uint16_t *p;
|
||||
int16_t i;
|
||||
for (int16_t j = 0; j < bitmap_h; j++)
|
||||
{
|
||||
p = framebuffer;
|
||||
p += ((max_X - x) * framebuffer_h); // shift framebuffer to y offset
|
||||
p += y + j; // shift framebuffer to x offset
|
||||
|
||||
i = bitmap_w;
|
||||
while (i--)
|
||||
{
|
||||
*p = *from_bitmap++;
|
||||
p -= framebuffer_h;
|
||||
}
|
||||
from_bitmap += x_skip;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
#ifndef _ARDUINO_G_H_
|
||||
#define _ARDUINO_G_H_
|
||||
|
||||
#include "Arduino_DataBus.h"
|
||||
|
||||
/// A generic graphics superclass that can handle all sorts of drawing. At a minimum you can subclass and provide drawPixel(). At a maximum you can do a ton of overriding to optimize. Used for any/all Adafruit displays!
|
||||
class Arduino_G
|
||||
{
|
||||
public:
|
||||
Arduino_G(int16_t w, int16_t h); // Constructor
|
||||
|
||||
// This MUST be defined by the subclass:
|
||||
virtual bool begin(int32_t speed = GFX_NOT_DEFINED) = 0;
|
||||
|
||||
virtual void drawBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h, uint16_t color, uint16_t bg) = 0;
|
||||
virtual void drawIndexedBitmap(int16_t x, int16_t y, uint8_t *bitmap, uint16_t *color_index, int16_t w, int16_t h, int16_t x_skip = 0) = 0;
|
||||
virtual void draw3bitRGBBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h) = 0;
|
||||
virtual void draw16bitRGBBitmap(int16_t x, int16_t y, uint16_t *bitmap, int16_t w, int16_t h) = 0;
|
||||
virtual void draw24bitRGBBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h) = 0;
|
||||
|
||||
protected:
|
||||
int16_t
|
||||
WIDTH, ///< This is the 'raw' display width - never changes
|
||||
HEIGHT; ///< This is the 'raw' display height - never changes
|
||||
};
|
||||
|
||||
#endif // _ARDUINO_G_H_
|
||||
|
||||
// utility functions
|
||||
bool gfx_draw_bitmap_to_framebuffer(
|
||||
uint16_t *from_bitmap, int16_t bitmap_w, int16_t bitmap_h,
|
||||
uint16_t *framebuffer, int16_t x, int16_t y, int16_t framebuffer_w, int16_t framebuffer_h);
|
||||
|
||||
bool gfx_draw_bitmap_to_framebuffer_rotate_1(
|
||||
uint16_t *from_bitmap, int16_t bitmap_w, int16_t bitmap_h,
|
||||
uint16_t *framebuffer, int16_t x, int16_t y, int16_t framebuffer_w, int16_t framebuffer_h);
|
||||
|
||||
bool gfx_draw_bitmap_to_framebuffer_rotate_2(
|
||||
uint16_t *from_bitmap, int16_t bitmap_w, int16_t bitmap_h,
|
||||
uint16_t *framebuffer, int16_t x, int16_t y, int16_t framebuffer_w, int16_t framebuffer_h);
|
||||
|
||||
bool gfx_draw_bitmap_to_framebuffer_rotate_3(
|
||||
uint16_t *from_bitmap, int16_t bitmap_w, int16_t bitmap_h,
|
||||
uint16_t *framebuffer, int16_t x, int16_t y, int16_t framebuffer_w, int16_t framebuffer_h);
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,486 @@
|
||||
/*
|
||||
* start rewrite from:
|
||||
* https://github.com/adafruit/Adafruit-GFX-Library.git
|
||||
*/
|
||||
#ifndef _ARDUINO_GFX_H_
|
||||
#define _ARDUINO_GFX_H_
|
||||
|
||||
#include "Arduino_G.h"
|
||||
#include "Arduino_DataBus.h"
|
||||
#include <Print.h>
|
||||
|
||||
#if !defined(ATTINY_CORE)
|
||||
#include "gfxfont.h"
|
||||
#endif // !defined(ATTINY_CORE)
|
||||
|
||||
#ifndef DEGTORAD
|
||||
#define DEGTORAD 0.017453292519943295769236907684886F
|
||||
#endif
|
||||
|
||||
#if __has_include(<U8g2lib.h>)
|
||||
#include <U8g2lib.h>
|
||||
#define U8G2_FONT_SUPPORT
|
||||
#include "font/u8g2_font_chill7_h_cjk.h"
|
||||
#include "font/u8g2_font_cubic11_h_cjk.h"
|
||||
#include "font/u8g2_font_quan7_h_cjk.h"
|
||||
#include "font/u8g2_font_unifont_h_utf8.h"
|
||||
#include "font/u8g2_font_unifont_t_chinese.h"
|
||||
#include "font/u8g2_font_unifont_t_chinese4.h"
|
||||
#include "font/u8g2_font_unifont_t_cjk.h"
|
||||
#endif
|
||||
|
||||
#define RGB565(r, g, b) ((((r) & 0xF8) << 8) | (((g) & 0xFC) << 3) | ((b) >> 3))
|
||||
#define RGB16TO24(c) ((((uint32_t)c & 0xF800) << 8) | ((c & 0x07E0) << 5) | ((c & 0x1F) << 3))
|
||||
|
||||
#define RGB565_BLACK RGB565(0, 0, 0)
|
||||
#define RGB565_NAVY RGB565(0, 0, 123)
|
||||
#define RGB565_DARKGREEN RGB565(0, 125, 0)
|
||||
#define RGB565_DARKCYAN RGB565(0, 125, 123)
|
||||
#define RGB565_MAROON RGB565(123, 0, 0)
|
||||
#define RGB565_PURPLE RGB565(123, 0, 123)
|
||||
#define RGB565_OLIVE RGB565(123, 125, 0)
|
||||
#define RGB565_LIGHTGREY RGB565(198, 195, 198)
|
||||
#define RGB565_DARKGREY RGB565(123, 125, 123)
|
||||
#define RGB565_BLUE RGB565(0, 0, 255)
|
||||
#define RGB565_GREEN RGB565(0, 255, 0)
|
||||
#define RGB565_CYAN RGB565(0, 255, 255)
|
||||
#define RGB565_RED RGB565(255, 0, 0)
|
||||
#define RGB565_MAGENTA RGB565(255, 0, 255)
|
||||
#define RGB565_YELLOW RGB565(255, 255, 0)
|
||||
#define RGB565_WHITE RGB565(255, 255, 255)
|
||||
#define RGB565_ORANGE RGB565(255, 165, 0)
|
||||
#define RGB565_GREENYELLOW RGB565(173, 255, 41)
|
||||
#define RGB565_PALERED RGB565(255, 130, 198)
|
||||
#define RGB565_PINK RGB565(255, 198, 198)
|
||||
|
||||
// Color definitions
|
||||
#ifndef DISABLE_COLOR_DEFINES
|
||||
#define BLACK RGB565_BLACK
|
||||
#define NAVY RGB565_NAVY
|
||||
#define DARKGREEN RGB565_DARKGREEN
|
||||
#define DARKCYAN RGB565_DARKCYAN
|
||||
#define MAROON RGB565_MAROON
|
||||
#define PURPLE RGB565_PURPLE
|
||||
#define OLIVE RGB565_OLIVE
|
||||
#define LIGHTGREY RGB565_LIGHTGREY
|
||||
#define DARKGREY RGB565_DARKGREY
|
||||
#define BLUE RGB565_BLUE
|
||||
#define GREEN RGB565_GREEN
|
||||
#define CYAN RGB565_CYAN
|
||||
#define RED RGB565_RED
|
||||
#define MAGENTA RGB565_MAGENTA
|
||||
#define YELLOW RGB565_YELLOW
|
||||
#define WHITE RGB565_WHITE
|
||||
#define ORANGE RGB565_ORANGE
|
||||
#define GREENYELLOW RGB565_GREENYELLOW
|
||||
#define PALERED RGB565_PALERED
|
||||
#endif
|
||||
|
||||
// Many (but maybe not all) non-AVR board installs define macros
|
||||
// for compatibility with existing PROGMEM-reading AVR code.
|
||||
// Do our own checks and defines here for good measure...
|
||||
|
||||
#ifndef pgm_read_byte
|
||||
#define pgm_read_byte(addr) (*(const unsigned char *)(addr))
|
||||
#endif
|
||||
#ifndef pgm_read_sbyte
|
||||
#define pgm_read_sbyte(addr) (*(const signed char *)(addr))
|
||||
#endif
|
||||
#ifndef pgm_read_word
|
||||
#define pgm_read_word(addr) (*(const unsigned short *)(addr))
|
||||
#endif
|
||||
#ifndef pgm_read_dword
|
||||
#define pgm_read_dword(addr) (*(const unsigned long *)(addr))
|
||||
#endif
|
||||
// workaround of a15 asm compile error
|
||||
#ifdef ESP8266
|
||||
#undef pgm_read_word
|
||||
#define pgm_read_word(addr) (*(const unsigned short *)(addr))
|
||||
#endif
|
||||
|
||||
// Pointers are a peculiar case...typically 16-bit on AVR boards,
|
||||
// 32 bits elsewhere. Try to accommodate both...
|
||||
|
||||
#if !defined(__INT_MAX__) || (__INT_MAX__ > 0xFFFF)
|
||||
#define pgm_read_pointer(addr) ((void *)pgm_read_dword(addr))
|
||||
#else
|
||||
#define pgm_read_pointer(addr) ((void *)pgm_read_word(addr))
|
||||
#endif
|
||||
|
||||
#ifndef _swap_uint8_t
|
||||
#define _swap_uint8_t(a, b) \
|
||||
{ \
|
||||
uint8_t t = a; \
|
||||
a = b; \
|
||||
b = t; \
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef _swap_int16_t
|
||||
#define _swap_int16_t(a, b) \
|
||||
{ \
|
||||
int16_t t = a; \
|
||||
a = b; \
|
||||
b = t; \
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef _diff
|
||||
#define _diff(a, b) ((a > b) ? (a - b) : (b - a))
|
||||
#endif
|
||||
|
||||
#ifndef _ordered_in_range
|
||||
#define _ordered_in_range(v, a, b) ((a <= v) && (v <= b))
|
||||
#endif
|
||||
|
||||
#ifndef _in_range
|
||||
#define _in_range(v, a, b) ((a > b) ? _ordered_in_range(v, b, a) : _ordered_in_range(v, a, b))
|
||||
#endif
|
||||
|
||||
#if !defined(ATTINY_CORE)
|
||||
GFX_INLINE static GFXglyph *pgm_read_glyph_ptr(const GFXfont *gfxFont, uint8_t c)
|
||||
{
|
||||
#ifdef __AVR__
|
||||
return &(((GFXglyph *)pgm_read_pointer(&gfxFont->glyph))[c]);
|
||||
#else
|
||||
// expression in __AVR__ section may generate "dereferencing type-punned pointer will break strict-aliasing rules" warning
|
||||
// In fact, on other platforms (such as STM32) there is no need to do this pointer magic as program memory may be read in a usual way
|
||||
// So expression may be simplified
|
||||
return gfxFont->glyph + c;
|
||||
#endif //__AVR__
|
||||
}
|
||||
|
||||
GFX_INLINE static uint8_t *pgm_read_bitmap_ptr(const GFXfont *gfxFont)
|
||||
{
|
||||
#ifdef __AVR__
|
||||
return (uint8_t *)pgm_read_pointer(&gfxFont->bitmap);
|
||||
#else
|
||||
// expression in __AVR__ section generates "dereferencing type-punned pointer will break strict-aliasing rules" warning
|
||||
// In fact, on other platforms (such as STM32) there is no need to do this pointer magic as program memory may be read in a usual way
|
||||
// So expression may be simplified
|
||||
return gfxFont->bitmap;
|
||||
#endif //__AVR__
|
||||
}
|
||||
#endif // !defined(ATTINY_CORE)
|
||||
|
||||
/// A generic graphics superclass that can handle all sorts of drawing. At a minimum you can subclass and provide drawPixel(). At a maximum you can do a ton of overriding to optimize. Used for any/all Adafruit displays!
|
||||
#if defined(LITTLE_FOOT_PRINT)
|
||||
class Arduino_GFX : public Print
|
||||
#else
|
||||
class Arduino_GFX : public Print, public Arduino_G
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
{
|
||||
public:
|
||||
Arduino_GFX(int16_t w, int16_t h); // Constructor
|
||||
|
||||
// This MUST be defined by the subclass:
|
||||
virtual bool begin(int32_t speed = GFX_NOT_DEFINED) = 0;
|
||||
virtual void writePixelPreclipped(int16_t x, int16_t y, uint16_t color) = 0;
|
||||
|
||||
// TRANSACTION API / CORE DRAW API
|
||||
// These MAY be overridden by the subclass to provide device-specific
|
||||
// optimized code. Otherwise 'generic' versions are used.
|
||||
virtual void startWrite();
|
||||
virtual void writeFillRectPreclipped(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
|
||||
virtual void writeFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color);
|
||||
virtual void writeFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color);
|
||||
virtual void writeLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color);
|
||||
virtual void endWrite(void);
|
||||
|
||||
// CONTROL API
|
||||
// These MAY be overridden by the subclass to provide device-specific
|
||||
// optimized code. Otherwise 'generic' versions are used.
|
||||
virtual void setRotation(uint8_t r);
|
||||
virtual void invertDisplay(bool i);
|
||||
virtual void displayOn();
|
||||
virtual void displayOff();
|
||||
bool enableRoundMode();
|
||||
|
||||
// BASIC DRAW API
|
||||
// These MAY be overridden by the subclass to provide device-specific
|
||||
// optimized code. Otherwise 'generic' versions are used.
|
||||
// It's good to implement those, even if using transaction API
|
||||
void writePixel(int16_t x, int16_t y, uint16_t color);
|
||||
void drawPixel(int16_t x, int16_t y, uint16_t color);
|
||||
void drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color);
|
||||
void drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color);
|
||||
void writeFillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
|
||||
void fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
|
||||
void fillScreen(uint16_t color);
|
||||
void drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color);
|
||||
void drawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
|
||||
void drawCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color);
|
||||
void fillCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color);
|
||||
void drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color);
|
||||
void fillTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color);
|
||||
void drawRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h, int16_t radius, uint16_t color);
|
||||
void fillRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h, int16_t radius, uint16_t color);
|
||||
void drawBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h, uint16_t color);
|
||||
void drawBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h, uint16_t color);
|
||||
void drawXBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h, uint16_t color);
|
||||
void drawGrayscaleBitmap(int16_t x, int16_t y, const uint8_t bitmap[], const uint8_t mask[], int16_t w, int16_t h);
|
||||
void drawGrayscaleBitmap(int16_t x, int16_t y, uint8_t *bitmap, uint8_t *mask, int16_t w, int16_t h);
|
||||
void draw16bitRGBBitmapWithMask(int16_t x, int16_t y, const uint16_t bitmap[], const uint8_t mask[], int16_t w, int16_t h);
|
||||
void draw24bitRGBBitmap(int16_t x, int16_t y, const uint8_t bitmap[], const uint8_t mask[], int16_t w, int16_t h);
|
||||
void draw24bitRGBBitmap(int16_t x, int16_t y, uint8_t *bitmap, uint8_t *mask, int16_t w, int16_t h);
|
||||
void getTextBounds(const char *string, int16_t x, int16_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h);
|
||||
void getTextBounds(const __FlashStringHelper *s, int16_t x, int16_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h);
|
||||
void getTextBounds(const String &str, int16_t x, int16_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h);
|
||||
void setTextSize(uint8_t s);
|
||||
void setTextSize(uint8_t sx, uint8_t sy);
|
||||
void setTextSize(uint8_t sx, uint8_t sy, uint8_t pixel_margin);
|
||||
|
||||
#if !defined(ATTINY_CORE)
|
||||
void setFont(const GFXfont *f = NULL);
|
||||
#if defined(U8G2_FONT_SUPPORT)
|
||||
void setFont(const uint8_t *font);
|
||||
void setUTF8Print(bool isEnable);
|
||||
uint16_t u8g2_font_get_word(const uint8_t *font, uint8_t offset);
|
||||
uint8_t u8g2_font_decode_get_unsigned_bits(uint8_t cnt);
|
||||
int8_t u8g2_font_decode_get_signed_bits(uint8_t cnt);
|
||||
void u8g2_font_decode_len(uint8_t len, uint8_t is_foreground, uint16_t color, uint16_t bg);
|
||||
#endif // defined(U8G2_FONT_SUPPORT)
|
||||
virtual void flush(bool force_flush = false);
|
||||
#endif // !defined(ATTINY_CORE)
|
||||
|
||||
// adopt from LovyanGFX
|
||||
void drawEllipse(int16_t x, int16_t y, int16_t rx, int16_t ry, uint16_t color);
|
||||
void writeEllipseHelper(int32_t x, int32_t y, int32_t rx, int32_t ry, uint8_t cornername, uint16_t color);
|
||||
void fillEllipse(int16_t x, int16_t y, int16_t rx, int16_t ry, uint16_t color);
|
||||
void writeFillEllipseHelper(int32_t x, int32_t y, int32_t rx, int32_t ry, uint8_t cornername, int16_t delta, uint16_t color);
|
||||
void drawArc(int16_t x, int16_t y, int16_t r1, int16_t r2, float start, float end, uint16_t color);
|
||||
void fillArc(int16_t x, int16_t y, int16_t r1, int16_t r2, float start, float end, uint16_t color);
|
||||
void writeFillArcHelper(int16_t cx, int16_t cy, int16_t oradius, int16_t iradius, float start, float end, uint16_t color);
|
||||
|
||||
// TFT optimization code, too big for ATMEL family
|
||||
#if defined(LITTLE_FOOT_PRINT)
|
||||
void writeSlashLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color);
|
||||
void drawBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h, uint16_t color, uint16_t bg);
|
||||
void drawBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h, uint16_t color, uint16_t bg);
|
||||
void drawGrayscaleBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h);
|
||||
void drawGrayscaleBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h);
|
||||
void drawIndexedBitmap(int16_t x, int16_t y, uint8_t *bitmap, uint16_t *color_index, int16_t w, int16_t h, int16_t x_skip = 0);
|
||||
void drawIndexedBitmap(int16_t x, int16_t y, uint8_t *bitmap, uint16_t *color_index, uint8_t chroma_key, int16_t w, int16_t h, int16_t x_skip = 0);
|
||||
void draw3bitRGBBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h);
|
||||
void draw16bitRGBBitmapWithMask(int16_t x, int16_t y, uint16_t *bitmap, uint8_t *mask, int16_t w, int16_t h);
|
||||
void draw16bitRGBBitmap(int16_t x, int16_t y, const uint16_t bitmap[], int16_t w, int16_t h);
|
||||
void draw16bitRGBBitmap(int16_t x, int16_t y, uint16_t *bitmap, int16_t w, int16_t h);
|
||||
void draw16bitRGBBitmapWithTranColor(int16_t x, int16_t y, uint16_t *bitmap, uint16_t transparent_color, int16_t w, int16_t h);
|
||||
void draw16bitBeRGBBitmap(int16_t x, int16_t y, uint16_t *bitmap, int16_t w, int16_t h);
|
||||
void draw24bitRGBBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h);
|
||||
void draw24bitRGBBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h);
|
||||
void drawChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t bg);
|
||||
#else // !defined(LITTLE_FOOT_PRINT)
|
||||
virtual void writeSlashLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color);
|
||||
virtual void drawBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h, uint16_t color, uint16_t bg);
|
||||
virtual void drawBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h, uint16_t color, uint16_t bg);
|
||||
virtual void drawGrayscaleBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h);
|
||||
virtual void drawGrayscaleBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h);
|
||||
virtual void drawIndexedBitmap(int16_t x, int16_t y, uint8_t *bitmap, uint16_t *color_index, int16_t w, int16_t h, int16_t x_skip = 0);
|
||||
virtual void drawIndexedBitmap(int16_t x, int16_t y, uint8_t *bitmap, uint16_t *color_index, uint8_t chroma_key, int16_t w, int16_t h, int16_t x_skip = 0);
|
||||
virtual void draw3bitRGBBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h);
|
||||
virtual void draw16bitRGBBitmapWithMask(int16_t x, int16_t y, uint16_t *bitmap, uint8_t *mask, int16_t w, int16_t h);
|
||||
virtual void draw16bitRGBBitmap(int16_t x, int16_t y, const uint16_t bitmap[], int16_t w, int16_t h);
|
||||
virtual void draw16bitRGBBitmap(int16_t x, int16_t y, uint16_t *bitmap, int16_t w, int16_t h);
|
||||
virtual void draw16bitRGBBitmapWithTranColor(int16_t x, int16_t y, uint16_t *bitmap, uint16_t transparent_color, int16_t w, int16_t h);
|
||||
virtual void draw16bitBeRGBBitmap(int16_t x, int16_t y, uint16_t *bitmap, int16_t w, int16_t h);
|
||||
virtual void draw24bitRGBBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h);
|
||||
virtual void draw24bitRGBBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h);
|
||||
virtual void drawChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t bg);
|
||||
|
||||
virtual void draw16bitBeRGBBitmapR1(int16_t x, int16_t y, uint16_t *bitmap, int16_t w, int16_t h);
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
|
||||
/**********************************************************************/
|
||||
/*!
|
||||
@brief Set text cursor location
|
||||
@param x X coordinate in pixels
|
||||
@param y Y coordinate in pixels
|
||||
*/
|
||||
/**********************************************************************/
|
||||
void setCursor(int16_t x, int16_t y)
|
||||
{
|
||||
cursor_x = x;
|
||||
cursor_y = y;
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
/*!
|
||||
@brief Set text bound for printing
|
||||
@param x X coordinate in pixels
|
||||
@param y Y coordinate in pixels
|
||||
*/
|
||||
void setTextBound(int16_t x, int16_t y, int16_t w, int16_t h)
|
||||
{
|
||||
_min_text_x = x;
|
||||
_min_text_y = y;
|
||||
_max_text_x = x + w - 1;
|
||||
_max_text_y = y + h - 1;
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
/*!
|
||||
@brief Set text font color with transparant background
|
||||
@param c 16-bit 5-6-5 Color to draw text with
|
||||
@note For 'transparent' background, background and foreground
|
||||
are set to same color rather than using a separate flag.
|
||||
*/
|
||||
/**********************************************************************/
|
||||
void setTextColor(uint16_t c) { textcolor = textbgcolor = c; }
|
||||
|
||||
/**********************************************************************/
|
||||
/*!
|
||||
@brief Set text font color with custom background color
|
||||
@param c 16-bit 5-6-5 Color to draw text with
|
||||
@param bg 16-bit 5-6-5 Color to draw background/fill with
|
||||
*/
|
||||
/**********************************************************************/
|
||||
void setTextColor(uint16_t c, uint16_t bg)
|
||||
{
|
||||
textcolor = c;
|
||||
textbgcolor = bg;
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
/*!
|
||||
@brief Set whether text that is too long for the screen width should
|
||||
automatically wrap around to the next line (else clip right).
|
||||
@param w true for wrapping, false for clipping
|
||||
*/
|
||||
/**********************************************************************/
|
||||
void setTextWrap(bool w) { wrap = w; }
|
||||
|
||||
virtual size_t write(uint8_t);
|
||||
|
||||
/************************************************************************/
|
||||
/*!
|
||||
@brief Get width of the display, accounting for current rotation
|
||||
@returns Width in pixels
|
||||
*/
|
||||
/************************************************************************/
|
||||
int16_t width(void) const { return _width; };
|
||||
|
||||
/************************************************************************/
|
||||
/*!
|
||||
@brief Get height of the display, accounting for current rotation
|
||||
@returns Height in pixels
|
||||
*/
|
||||
/************************************************************************/
|
||||
int16_t height(void) const { return _height; }
|
||||
|
||||
/************************************************************************/
|
||||
/*!
|
||||
@brief Get rotation setting for display
|
||||
@returns 0 thru 3 corresponding to 4 cardinal rotations
|
||||
*/
|
||||
/************************************************************************/
|
||||
uint8_t getRotation(void) const { return _rotation; }
|
||||
|
||||
// get current cursor position (get rotation safe maximum values,
|
||||
// using: width() for x, height() for y)
|
||||
/************************************************************************/
|
||||
/*!
|
||||
@brief Get text cursor X location
|
||||
@returns X coordinate in pixels
|
||||
*/
|
||||
/************************************************************************/
|
||||
int16_t getCursorX(void) const { return cursor_x; }
|
||||
|
||||
/************************************************************************/
|
||||
/*!
|
||||
@brief Get text cursor Y location
|
||||
@returns Y coordinate in pixels
|
||||
*/
|
||||
/************************************************************************/
|
||||
int16_t getCursorY(void) const { return cursor_y; };
|
||||
|
||||
/*!
|
||||
@brief Given 8-bit red, green and blue values, return a 'packed'
|
||||
16-bit color value in '565' RGB format (5 bits red, 6 bits
|
||||
green, 5 bits blue). This is just a mathematical operation,
|
||||
no hardware is touched.
|
||||
@param red 8-bit red brightnesss (0 = off, 255 = max).
|
||||
@param green 8-bit green brightnesss (0 = off, 255 = max).
|
||||
@param blue 8-bit blue brightnesss (0 = off, 255 = max).
|
||||
@return 'Packed' 16-bit color value (565 format).
|
||||
*/
|
||||
uint16_t color565(uint8_t red, uint8_t green, uint8_t blue)
|
||||
{
|
||||
return ((red & 0xF8) << 8) | ((green & 0xFC) << 3) | (blue >> 3);
|
||||
}
|
||||
|
||||
protected:
|
||||
void charBounds(char c, int16_t *x, int16_t *y, int16_t *minx, int16_t *miny, int16_t *maxx, int16_t *maxy);
|
||||
int16_t
|
||||
_width, ///< Display width as modified by current rotation
|
||||
_height, ///< Display height as modified by current rotation
|
||||
_max_x, ///< x zero base bound (_width - 1)
|
||||
_max_y, ///< y zero base bound (_height - 1)
|
||||
_min_text_x,
|
||||
_min_text_y,
|
||||
_max_text_x,
|
||||
_max_text_y,
|
||||
cursor_x, ///< x location to start print()ing text
|
||||
cursor_y; ///< y location to start print()ing text
|
||||
uint16_t
|
||||
textcolor, ///< 16-bit background color for print()
|
||||
textbgcolor; ///< 16-bit text color for print()
|
||||
uint8_t
|
||||
textsize_x, ///< Desired magnification in X-axis of text to print()
|
||||
textsize_y, ///< Desired magnification in Y-axis of text to print()
|
||||
text_pixel_margin, ///< Margin for each text pixel
|
||||
_rotation; ///< Display rotation (0 thru 3)
|
||||
bool
|
||||
wrap; ///< If set, 'wrap' text at right edge of display
|
||||
#if !defined(ATTINY_CORE)
|
||||
GFXfont *gfxFont; ///< Pointer to special font
|
||||
#endif // !defined(ATTINY_CORE)
|
||||
|
||||
#if defined(U8G2_FONT_SUPPORT)
|
||||
uint8_t *u8g2Font;
|
||||
bool _enableUTF8Print = false;
|
||||
uint8_t _utf8_state = 0;
|
||||
uint16_t _encoding;
|
||||
|
||||
uint8_t _u8g2_glyph_cnt;
|
||||
uint8_t _u8g2_bits_per_0;
|
||||
uint8_t _u8g2_bits_per_1;
|
||||
uint8_t _u8g2_bits_per_char_width;
|
||||
uint8_t _u8g2_bits_per_char_height;
|
||||
uint8_t _u8g2_bits_per_char_x;
|
||||
uint8_t _u8g2_bits_per_char_y;
|
||||
uint8_t _u8g2_bits_per_delta_x;
|
||||
int8_t _u8g2_max_char_width;
|
||||
int8_t _u8g2_max_char_height;
|
||||
uint16_t _u8g2_start_pos_upper_A;
|
||||
uint16_t _u8g2_start_pos_lower_a;
|
||||
uint16_t _u8g2_start_pos_unicode;
|
||||
uint8_t _u8g2_first_char;
|
||||
|
||||
uint8_t _u8g2_char_width;
|
||||
uint8_t _u8g2_char_height;
|
||||
int8_t _u8g2_char_x;
|
||||
int8_t _u8g2_char_y;
|
||||
int8_t _u8g2_delta_x;
|
||||
|
||||
int8_t _u8g2_dx;
|
||||
int8_t _u8g2_dy;
|
||||
int16_t _u8g2_target_x;
|
||||
int16_t _u8g2_target_y;
|
||||
|
||||
const uint8_t *_u8g2_decode_ptr;
|
||||
uint8_t _u8g2_decode_bit_pos;
|
||||
#endif // defined(U8G2_FONT_SUPPORT)
|
||||
|
||||
#if defined(LITTLE_FOOT_PRINT)
|
||||
int16_t
|
||||
WIDTH, ///< This is the 'raw' display width - never changes
|
||||
HEIGHT; ///< This is the 'raw' display height - never changes
|
||||
#endif // defined(LITTLE_FOOT_PRINT)
|
||||
|
||||
bool _isRoundMode = false;
|
||||
int16_t *_roundMinX;
|
||||
int16_t *_roundMaxX;
|
||||
};
|
||||
|
||||
#endif // _ARDUINO_GFX_H_
|
||||
@@ -0,0 +1,38 @@
|
||||
#include "Arduino_GFX_Library.h"
|
||||
|
||||
Arduino_DataBus *create_default_Arduino_DataBus()
|
||||
{
|
||||
#if defined(ARDUINO_ARCH_NRF52840)
|
||||
return new Arduino_NRFXSPI(DF_GFX_DC, DF_GFX_CS, DF_GFX_SCK, DF_GFX_MOSI, DF_GFX_MISO);
|
||||
#elif defined(TARGET_RP2040) || defined(PICO_RP2350)
|
||||
return new Arduino_RPiPicoSPI(DF_GFX_DC, DF_GFX_CS, DF_GFX_SCK, DF_GFX_MOSI, DF_GFX_MISO, DF_GFX_SPI);
|
||||
#elif defined(ESP32) && (CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3)
|
||||
return new Arduino_ESP32SPI(DF_GFX_DC, DF_GFX_CS, DF_GFX_SCK, DF_GFX_MOSI, DF_GFX_MISO);
|
||||
#elif defined(ESP8266)
|
||||
return new Arduino_ESP8266SPI(DF_GFX_DC, DF_GFX_CS);
|
||||
#else
|
||||
return new Arduino_HWSPI(DF_GFX_DC, DF_GFX_CS);
|
||||
#endif
|
||||
}
|
||||
|
||||
Arduino_GFX *create_default_Arduino_GFX()
|
||||
{
|
||||
Arduino_DataBus *bus = create_default_Arduino_DataBus();
|
||||
#if defined(WIO_TERMINAL)
|
||||
return new Arduino_ILI9341(bus, DF_GFX_RST, 1 /* rotation */);
|
||||
#elif defined(ESP32_S3_BOX)
|
||||
return new Arduino_ILI9342(bus, DF_GFX_RST, 0 /* rotation */);
|
||||
#elif defined(M5STACK_CORE)
|
||||
return new Arduino_ILI9342(bus, DF_GFX_RST, 2 /* rotation */);
|
||||
#elif defined(M5STACK_ATOMS3)
|
||||
return new Arduino_GC9107(bus, 34 /* RST */, 0 /* rotation */, true /* IPS */);
|
||||
#elif defined(ODROID_GO)
|
||||
return new Arduino_ILI9341(bus, DF_GFX_RST, 3 /* rotation */);
|
||||
#elif defined(TTGO_T_WATCH)
|
||||
return new Arduino_ST7789(bus, DF_GFX_RST, 0 /* rotation */, true /* IPS */, 240, 240, 0, 80);
|
||||
#elif defined(WAVESHARE_RP2040_LCD_1_28)
|
||||
return new Arduino_ST7789(bus, DF_GFX_RST, 0 /* rotation */, true /* IPS */, 240, 240, 0, 80);
|
||||
#else
|
||||
return new Arduino_GC9A01(bus, DF_GFX_RST, 0 /* rotation */, true /* IPS */);
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,297 @@
|
||||
#ifndef _ARDUINO_GFX_LIBRARIES_H_
|
||||
#define _ARDUINO_GFX_LIBRARIES_H_
|
||||
|
||||
#include "Arduino_DataBus.h"
|
||||
#include "databus/Arduino_AVRPAR8.h"
|
||||
#include "databus/Arduino_UNOPAR8.h"
|
||||
#include "databus/Arduino_AVRPAR16.h"
|
||||
#include "databus/Arduino_DUEPAR16.h"
|
||||
#include "databus/Arduino_ESP32DSIPanel.h"
|
||||
#include "databus/Arduino_ESP32LCD8.h"
|
||||
#include "databus/Arduino_ESP32LCD16.h"
|
||||
#include "databus/Arduino_ESP32PAR8.h"
|
||||
#include "databus/Arduino_ESP32PAR8Q.h"
|
||||
#include "databus/Arduino_ESP32PAR8QQ.h"
|
||||
#include "databus/Arduino_ESP32PAR8QQQ.h"
|
||||
#include "databus/Arduino_ESP32PAR16.h"
|
||||
#include "databus/Arduino_ESP32PAR16Q.h"
|
||||
#include "databus/Arduino_ESP32PAR16QQ.h"
|
||||
#include "databus/Arduino_ESP32QSPI.h"
|
||||
#include "databus/Arduino_ESP32RGBPanel.h"
|
||||
#include "databus/Arduino_ESP32S2PAR8.h"
|
||||
#include "databus/Arduino_ESP32S2PAR8Q.h"
|
||||
#include "databus/Arduino_ESP32S2PAR16.h"
|
||||
#include "databus/Arduino_ESP32S2PAR16Q.h"
|
||||
#include "databus/Arduino_ESP32SPI.h"
|
||||
#include "databus/Arduino_ESP32SPIDMA.h"
|
||||
#include "databus/Arduino_ESP8266SPI.h"
|
||||
#include "databus/Arduino_HWSPI.h"
|
||||
#include "databus/Arduino_mbedSPI.h"
|
||||
#include "databus/Arduino_NRFXSPI.h"
|
||||
#include "databus/Arduino_RPiPicoPAR8.h"
|
||||
#include "databus/Arduino_RPiPicoPAR16.h"
|
||||
#include "databus/Arduino_RPiPicoSPI.h"
|
||||
#include "databus/Arduino_RTLPAR8.h"
|
||||
#include "databus/Arduino_STM32PAR8.h"
|
||||
#include "databus/Arduino_SWPAR8.h"
|
||||
#include "databus/Arduino_SWPAR16.h"
|
||||
#include "databus/Arduino_SWSPI.h"
|
||||
#include "databus/Arduino_Wire.h"
|
||||
#include "databus/Arduino_XL9535SWSPI.h"
|
||||
#include "databus/Arduino_XCA9554SWSPI.h"
|
||||
|
||||
#include "Arduino_GFX.h" // Core graphics library
|
||||
#if !defined(LITTLE_FOOT_PRINT)
|
||||
#include "canvas/Arduino_Canvas.h"
|
||||
#include "canvas/Arduino_Canvas_Indexed.h"
|
||||
#include "canvas/Arduino_Canvas_3bit.h"
|
||||
#include "canvas/Arduino_Canvas_Mono.h"
|
||||
#include "display/Arduino_ILI9488_3bit.h"
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
|
||||
#include "display/Arduino_AXS15231B.h"
|
||||
#include "display/Arduino_CO5300.h"
|
||||
#include "display/Arduino_DSI_Display.h"
|
||||
#include "display/Arduino_GC9A01.h"
|
||||
#include "display/Arduino_GC9106.h"
|
||||
#include "display/Arduino_GC9107.h"
|
||||
#include "display/Arduino_HX8347C.h"
|
||||
#include "display/Arduino_HX8347D.h"
|
||||
#include "display/Arduino_HX8352C.h"
|
||||
#include "display/Arduino_HX8357A.h"
|
||||
#include "display/Arduino_HX8357B.h"
|
||||
#include "display/Arduino_HX8369A.h"
|
||||
#include "display/Arduino_ILI9225.h"
|
||||
#include "display/Arduino_ILI9331.h"
|
||||
#include "display/Arduino_ILI9341.h"
|
||||
#include "display/Arduino_ILI9342.h"
|
||||
#include "display/Arduino_ILI9481_18bit.h"
|
||||
#include "display/Arduino_ILI9486.h"
|
||||
#include "display/Arduino_ILI9486_18bit.h"
|
||||
#include "display/Arduino_ILI9488.h"
|
||||
#include "display/Arduino_ILI9488_18bit.h"
|
||||
#include "display/Arduino_ILI9806.h"
|
||||
#include "display/Arduino_JBT6K71.h"
|
||||
#include "display/Arduino_JD9613.h"
|
||||
#include "display/Arduino_NT35310.h"
|
||||
#include "display/Arduino_NT35510.h"
|
||||
#include "display/Arduino_NT39125.h"
|
||||
#include "display/Arduino_NV3023.h"
|
||||
#include "display/Arduino_NV3041A.h"
|
||||
#include "display/Arduino_OTM8009A.h"
|
||||
#include "display/Arduino_R61529.h"
|
||||
#include "display/Arduino_RM67162.h"
|
||||
#include "display/Arduino_RM690B0.h"
|
||||
#include "display/Arduino_RGB_Display.h"
|
||||
#include "display/Arduino_SEPS525.h"
|
||||
#include "display/Arduino_SH1106.h"
|
||||
#include "display/Arduino_SSD1283A.h"
|
||||
#include "display/Arduino_SSD1306.h"
|
||||
#include "display/Arduino_SSD1331.h"
|
||||
#include "display/Arduino_SSD1351.h"
|
||||
#include "display/Arduino_ST7735.h"
|
||||
#include "display/Arduino_ST7789.h"
|
||||
#include "display/Arduino_ST77916.h"
|
||||
#include "display/Arduino_ST7796.h"
|
||||
#include "display/Arduino_WEA2012.h"
|
||||
|
||||
#if defined(ARDUINO_ARCH_SAMD) && defined(SEEED_GROVE_UI_WIRELESS)
|
||||
#define DISPLAY_DEV_KIT
|
||||
#define WIO_TERMINAL
|
||||
#define DF_GFX_CS LCD_SS_PIN
|
||||
#define DF_GFX_DC LCD_DC
|
||||
#define DF_GFX_RST GFX_NOT_DEFINED
|
||||
#define DF_GFX_BL LCD_BACKLIGHT
|
||||
#elif defined(ARDUINO_ESP32_S3_BOX)
|
||||
#define DISPLAY_DEV_KIT
|
||||
#define ESP32_S3_BOX
|
||||
#define DF_GFX_SCK TFT_CLK
|
||||
#define DF_GFX_MOSI TFT_MOSI
|
||||
#define DF_GFX_MISO TFT_MISO
|
||||
#define DF_GFX_CS TFT_CS
|
||||
#define DF_GFX_DC TFT_DC
|
||||
#define DF_GFX_RST TFT_RST
|
||||
#define DF_GFX_BL TFT_BL
|
||||
#elif defined(ARDUINO_M5Stack_Core_ESP32) || defined(ARDUINO_M5STACK_FIRE)
|
||||
#define DISPLAY_DEV_KIT
|
||||
#define M5STACK_CORE
|
||||
#define DF_GFX_SCK 18
|
||||
#define DF_GFX_MOSI 23
|
||||
#define DF_GFX_MISO 19
|
||||
#define DF_GFX_CS 14
|
||||
#define DF_GFX_DC 27
|
||||
#define DF_GFX_RST 33
|
||||
#define DF_GFX_BL 32
|
||||
#elif defined(ARDUINO_M5Stack_ATOMS3)
|
||||
#define DISPLAY_DEV_KIT
|
||||
#define M5STACK_ATOMS3
|
||||
#define DF_GFX_SCK 17
|
||||
#define DF_GFX_MOSI 21
|
||||
#define DF_GFX_MISO GFX_NOT_DEFINED
|
||||
#define DF_GFX_CS 15
|
||||
#define DF_GFX_DC 33
|
||||
#define DF_GFX_RST 34
|
||||
#define DF_GFX_BL 16
|
||||
#elif defined(ARDUINO_ODROID_ESP32)
|
||||
#define DISPLAY_DEV_KIT
|
||||
#define ODROID_GO
|
||||
#define DF_GFX_SCK 18
|
||||
#define DF_GFX_MOSI 23
|
||||
#define DF_GFX_MISO 19
|
||||
#define DF_GFX_CS 5
|
||||
#define DF_GFX_DC 21
|
||||
#define DF_GFX_RST GFX_NOT_DEFINED
|
||||
#define DF_GFX_BL 14
|
||||
/* TTGO T-Watch */
|
||||
#elif defined(ARDUINO_T) || defined(ARDUINO_TWATCH_BASE) || defined(ARDUINO_TWATCH_2020_V1) || defined(ARDUINO_TWATCH_2020_V2)
|
||||
#define DISPLAY_DEV_KIT
|
||||
#define TTGO_T_WATCH
|
||||
#define DF_GFX_SCK 18
|
||||
#define DF_GFX_MOSI 19
|
||||
#define DF_GFX_MISO GFX_NOT_DEFINED
|
||||
#define DF_GFX_CS 5
|
||||
#define DF_GFX_DC 27
|
||||
#define DF_GFX_RST GFX_NOT_DEFINED
|
||||
#define DF_GFX_BL 12
|
||||
/* Waveshare RP2040-LCD-1.28 */
|
||||
#elif defined(ARDUINO_WAVESHARE_RP2040_LCD_1_28)
|
||||
#define DISPLAY_DEV_KIT
|
||||
#define WAVESHARE_RP2040_LCD_1_28
|
||||
#define DF_GFX_SCK 10
|
||||
#define DF_GFX_MOSI 11
|
||||
#define DF_GFX_MISO 12
|
||||
#define DF_GFX_CS 9
|
||||
#define DF_GFX_DC 8
|
||||
#define DF_GFX_RST 12
|
||||
#define DF_GFX_BL 25
|
||||
#define DF_GFX_SPI spi1
|
||||
#elif defined(ARDUINO_ARCH_NRF52840)
|
||||
#define DF_GFX_SCK 13
|
||||
#define DF_GFX_MOSI 11
|
||||
#define DF_GFX_MISO 12
|
||||
#define DF_GFX_CS 9
|
||||
#define DF_GFX_DC 8
|
||||
#define DF_GFX_RST 7
|
||||
#define DF_GFX_BL 6
|
||||
#elif defined(__IMXRT1052__) || defined(__IMXRT1062__)
|
||||
// PJRC Teensy 4.x
|
||||
#define DF_GFX_SCK 13
|
||||
#define DF_GFX_MOSI 11
|
||||
#define DF_GFX_MISO 12
|
||||
#define DF_GFX_CS 39 // GFX_NOT_DEFINED for display without CS pin
|
||||
#define DF_GFX_DC 41
|
||||
#define DF_GFX_RST 40
|
||||
#define DF_GFX_BL 22
|
||||
#elif defined(ARDUINO_BLACKPILL_F411CE)
|
||||
#define DF_GFX_SCK 5
|
||||
#define DF_GFX_MOSI 7
|
||||
#define DF_GFX_MISO 6
|
||||
#define DF_GFX_CS 4
|
||||
#define DF_GFX_DC 3
|
||||
#define DF_GFX_RST 2
|
||||
#define DF_GFX_BL 1
|
||||
#elif defined(TARGET_RP2040) || defined(PICO_RP2350)
|
||||
#define DF_GFX_SCK 18
|
||||
#define DF_GFX_MOSI 19
|
||||
#define DF_GFX_MISO 16
|
||||
#define DF_GFX_CS 17
|
||||
#define DF_GFX_DC 27
|
||||
#define DF_GFX_RST 26
|
||||
#define DF_GFX_BL 28
|
||||
#define DF_GFX_SPI spi0
|
||||
#elif defined(ESP32) && (CONFIG_IDF_TARGET_ESP32)
|
||||
#define DF_GFX_SCK 18
|
||||
#define DF_GFX_MOSI 23
|
||||
#define DF_GFX_MISO GFX_NOT_DEFINED
|
||||
#define DF_GFX_CS 5
|
||||
#define DF_GFX_DC 27
|
||||
#define DF_GFX_RST 33
|
||||
#define DF_GFX_BL 22
|
||||
#elif defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S2)
|
||||
#define DF_GFX_SCK 36
|
||||
#define DF_GFX_MOSI 35
|
||||
#define DF_GFX_MISO GFX_NOT_DEFINED
|
||||
#define DF_GFX_CS 34
|
||||
#define DF_GFX_DC 38
|
||||
#define DF_GFX_RST 33
|
||||
#define DF_GFX_BL 21
|
||||
#elif defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)
|
||||
#define DF_GFX_SCK 36
|
||||
#define DF_GFX_MOSI 35
|
||||
#define DF_GFX_MISO GFX_NOT_DEFINED
|
||||
#define DF_GFX_CS 40
|
||||
#define DF_GFX_DC 41
|
||||
#define DF_GFX_RST 42
|
||||
#define DF_GFX_BL 48
|
||||
#elif defined(ESP32) && (CONFIG_IDF_TARGET_ESP32C3)
|
||||
#define DF_GFX_SCK 4
|
||||
#define DF_GFX_MOSI 6
|
||||
#define DF_GFX_MISO GFX_NOT_DEFINED
|
||||
#define DF_GFX_CS 7
|
||||
#define DF_GFX_DC 2
|
||||
#define DF_GFX_RST 1
|
||||
#define DF_GFX_BL 3
|
||||
#elif defined(ESP8266)
|
||||
#define DF_GFX_SCK 14
|
||||
#define DF_GFX_MOSI 13
|
||||
#define DF_GFX_MISO 12
|
||||
#define DF_GFX_CS 15
|
||||
#define DF_GFX_DC 4
|
||||
#define DF_GFX_RST 2
|
||||
#define DF_GFX_BL 5
|
||||
#elif defined(RTL8722DM)
|
||||
#if defined(BOARD_RTL8720DN_BW16)
|
||||
#define DF_GFX_SCK 10
|
||||
#define DF_GFX_MOSI 12
|
||||
#define DF_GFX_MISO 11
|
||||
#define DF_GFX_CS 9
|
||||
#define DF_GFX_DC 8
|
||||
#define DF_GFX_RST 6
|
||||
#define DF_GFX_BL 3
|
||||
#elif defined(BOARD_RTL8722DM)
|
||||
#define DF_GFX_SCK 13
|
||||
#define DF_GFX_MOSI 11
|
||||
#define DF_GFX_MISO 12
|
||||
#define DF_GFX_CS 18
|
||||
#define DF_GFX_DC 17
|
||||
#define DF_GFX_RST 22
|
||||
#define DF_GFX_BL 23
|
||||
#elif defined(BOARD_RTL8722DM_MINI)
|
||||
#define DF_GFX_SCK 11
|
||||
#define DF_GFX_MOSI 9
|
||||
#define DF_GFX_MISO 10
|
||||
#define DF_GFX_CS 12
|
||||
#define DF_GFX_DC 14
|
||||
#define DF_GFX_RST 15
|
||||
#define DF_GFX_BL 13
|
||||
#else // old version
|
||||
#define DF_GFX_SCK 19
|
||||
#define DF_GFX_MOSI 21
|
||||
#define DF_GFX_MISO 20
|
||||
#define DF_GFX_CS 18 // GFX_NOT_DEFINED for display without CS pin
|
||||
#define DF_GFX_DC 17
|
||||
#define DF_GFX_RST 2
|
||||
#define DF_GFX_BL 23
|
||||
#endif
|
||||
#elif defined(SEEED_XIAO_M0)
|
||||
#define DF_GFX_SCK 8
|
||||
#define DF_GFX_MOSI 10
|
||||
#define DF_GFX_MISO 9
|
||||
#define DF_GFX_CS 3 // GFX_NOT_DEFINED for display without CS pin
|
||||
#define DF_GFX_DC 2
|
||||
#define DF_GFX_RST 1
|
||||
#define DF_GFX_BL 0
|
||||
#else // default pins for Arduino Nano, Mini, Micro and more
|
||||
#define DF_GFX_SCK 13
|
||||
#define DF_GFX_MOSI 11
|
||||
#define DF_GFX_MISO 12
|
||||
#define DF_GFX_CS 9
|
||||
#define DF_GFX_DC 8
|
||||
#define DF_GFX_RST 7
|
||||
#define DF_GFX_BL 6
|
||||
#endif
|
||||
|
||||
Arduino_DataBus *create_default_Arduino_DataBus();
|
||||
Arduino_GFX *create_default_Arduino_GFX();
|
||||
|
||||
#endif // _ARDUINO_GFX_LIBRARIES_H_
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* start rewrite from:
|
||||
* https://github.com/adafruit/Adafruit-GFX-Library.git
|
||||
*/
|
||||
#ifndef _ARDUINO_TFT_H_
|
||||
#define _ARDUINO_TFT_H_
|
||||
|
||||
#include "Arduino_DataBus.h"
|
||||
#include "Arduino_GFX.h"
|
||||
|
||||
class Arduino_TFT : public Arduino_GFX
|
||||
{
|
||||
public:
|
||||
Arduino_TFT(Arduino_DataBus *bus, int8_t rst, uint8_t r, bool ips, int16_t w, int16_t h, uint8_t col_offset1, uint8_t row_offset1, uint8_t col_offset2, uint8_t row_offset2);
|
||||
|
||||
// This SHOULD be defined by the subclass:
|
||||
void setRotation(uint8_t r) override;
|
||||
|
||||
// This MUST be defined by the subclass:
|
||||
// and also protected function: tftInit()
|
||||
virtual void writeAddrWindow(int16_t x, int16_t y, uint16_t w, uint16_t h) = 0;
|
||||
|
||||
bool begin(int32_t speed = GFX_NOT_DEFINED);
|
||||
void startWrite(void) override;
|
||||
void endWrite(void) override;
|
||||
void writePixelPreclipped(int16_t x, int16_t y, uint16_t color) override;
|
||||
void writeFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) override;
|
||||
void writeFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color) override;
|
||||
void writeFillRectPreclipped(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) override;
|
||||
|
||||
virtual void writeRepeat(uint16_t color, uint32_t len);
|
||||
|
||||
void setAddrWindow(int16_t x, int16_t y, uint16_t w, uint16_t h);
|
||||
virtual void writeColor(uint16_t color);
|
||||
|
||||
// TFT optimization code, too big for ATMEL family
|
||||
#if !defined(LITTLE_FOOT_PRINT)
|
||||
virtual void writePixels(uint16_t *data, uint32_t size);
|
||||
virtual void writeIndexedPixels(uint8_t *bitmap, uint16_t *color_index, uint32_t len);
|
||||
virtual void writeIndexedPixelsDouble(uint8_t *bitmap, uint16_t *color_index, uint32_t len);
|
||||
|
||||
virtual void drawYCbCrBitmap(int16_t x, int16_t y, uint8_t *yData, uint8_t *cbData, uint8_t *crData, int16_t w, int16_t h);
|
||||
|
||||
void writeBytes(uint8_t *data, uint32_t size);
|
||||
void pushColor(uint16_t color);
|
||||
|
||||
void writeSlashLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color) override;
|
||||
void drawBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h, uint16_t color, uint16_t bg) override;
|
||||
void drawBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h, uint16_t color, uint16_t bg) override;
|
||||
void drawGrayscaleBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h) override;
|
||||
void drawGrayscaleBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h) override;
|
||||
void drawIndexedBitmap(int16_t x, int16_t y, uint8_t *bitmap, uint16_t *color_index, int16_t w, int16_t h, int16_t x_skip = 0) override;
|
||||
void draw16bitRGBBitmapWithMask(int16_t x, int16_t y, uint16_t *bitmap, uint8_t *mask, int16_t w, int16_t h) override;
|
||||
void draw16bitRGBBitmap(int16_t x, int16_t y, const uint16_t bitmap[], int16_t w, int16_t h) override;
|
||||
void draw16bitRGBBitmap(int16_t x, int16_t y, uint16_t *bitmap, int16_t w, int16_t h) override;
|
||||
void draw16bitBeRGBBitmap(int16_t x, int16_t y, uint16_t *bitmap, int16_t w, int16_t h) override;
|
||||
void draw16bitBeRGBBitmapR1(int16_t x, int16_t y, uint16_t *bitmap, int16_t w, int16_t h) override;
|
||||
void draw24bitRGBBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h) override;
|
||||
void draw24bitRGBBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h) override;
|
||||
void drawChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t bg) override;
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
|
||||
protected:
|
||||
virtual void tftInit() = 0;
|
||||
|
||||
Arduino_DataBus *_bus;
|
||||
int8_t _rst;
|
||||
bool _ips;
|
||||
uint8_t COL_OFFSET1, ROW_OFFSET1;
|
||||
uint8_t COL_OFFSET2, ROW_OFFSET2;
|
||||
uint8_t _xStart, _yStart;
|
||||
int16_t _currentX, _currentY;
|
||||
uint16_t _currentW, _currentH;
|
||||
int8_t _override_datamode = GFX_NOT_DEFINED;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,584 @@
|
||||
/*
|
||||
* start rewrite from:
|
||||
* https://github.com/adafruit/Adafruit-GFX-Library.git
|
||||
*/
|
||||
#include "Arduino_DataBus.h"
|
||||
#include "Arduino_GFX.h"
|
||||
#include "Arduino_TFT_18bit.h"
|
||||
|
||||
Arduino_TFT_18bit::Arduino_TFT_18bit(
|
||||
Arduino_DataBus *bus, int8_t rst, uint8_t r,
|
||||
bool ips, int16_t w, int16_t h,
|
||||
uint8_t col_offset1, uint8_t row_offset1, uint8_t col_offset2, uint8_t row_offset2)
|
||||
: Arduino_TFT(bus, rst, r, ips, w, h, col_offset1, row_offset1, col_offset2, row_offset2)
|
||||
{
|
||||
}
|
||||
|
||||
void Arduino_TFT_18bit::writeColor(uint16_t color)
|
||||
{
|
||||
_bus->write((color & 0xF800) >> 8);
|
||||
_bus->write((color & 0x07E0) >> 3);
|
||||
_bus->write(color << 3);
|
||||
}
|
||||
|
||||
void Arduino_TFT_18bit::writePixelPreclipped(int16_t x, int16_t y, uint16_t color)
|
||||
{
|
||||
writeAddrWindow(x, y, 1, 1);
|
||||
_bus->write((color & 0xF800) >> 8);
|
||||
_bus->write((color & 0x07E0) >> 3);
|
||||
_bus->write(color << 3);
|
||||
}
|
||||
|
||||
void Arduino_TFT_18bit::writeRepeat(uint16_t color, uint32_t len)
|
||||
{
|
||||
#if defined(ESP8266) || defined(ESP32)
|
||||
uint8_t c[3] = {(uint8_t)((color & 0xF800) >> 8), (uint8_t)((color & 0x07E0) >> 3), (uint8_t)((color & 0x001F) << 3)};
|
||||
_bus->writePattern(c, 3, len);
|
||||
#else
|
||||
uint8_t c1 = (uint8_t)((color & 0xF800) >> 8);
|
||||
uint8_t c2 = (uint8_t)((color & 0x07E0) >> 3);
|
||||
uint8_t c3 = (uint8_t)((color & 0x001F) << 3);
|
||||
while (len--)
|
||||
{
|
||||
_bus->write(c1);
|
||||
_bus->write(c2);
|
||||
_bus->write(c3);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// TFT optimization code, too big for ATMEL family
|
||||
#if !defined(LITTLE_FOOT_PRINT)
|
||||
|
||||
void Arduino_TFT_18bit::writePixels(uint16_t *data, uint32_t len)
|
||||
{
|
||||
uint16_t d;
|
||||
while (len--)
|
||||
{
|
||||
d = *data++;
|
||||
_bus->write((d & 0xF800) >> 8);
|
||||
_bus->write((d & 0x07E0) >> 3);
|
||||
_bus->write(d << 3);
|
||||
}
|
||||
}
|
||||
|
||||
// TFT tuned BITMAP / XBITMAP / GRAYSCALE / RGB BITMAP FUNCTIONS ---------------------
|
||||
|
||||
void Arduino_TFT_18bit::writeIndexedPixels(uint8_t *bitmap, uint16_t *color_index, uint32_t len)
|
||||
{
|
||||
uint16_t d;
|
||||
while (len--)
|
||||
{
|
||||
d = color_index[*(bitmap++)];
|
||||
_bus->write((d & 0xF800) >> 8);
|
||||
_bus->write((d & 0x07E0) >> 3);
|
||||
_bus->write(d << 3);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_TFT_18bit::writeIndexedPixelsDouble(uint8_t *bitmap, uint16_t *color_index, uint32_t len)
|
||||
{
|
||||
uint8_t r, g, b;
|
||||
uint16_t d;
|
||||
while (len--)
|
||||
{
|
||||
d = color_index[*(bitmap++)];
|
||||
r = (d & 0xF800) >> 8;
|
||||
g = (d & 0x07E0) >> 3;
|
||||
b = d << 3;
|
||||
_bus->write(r);
|
||||
_bus->write(g);
|
||||
_bus->write(b);
|
||||
_bus->write(r);
|
||||
_bus->write(g);
|
||||
_bus->write(b);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_TFT_18bit::drawBitmap(
|
||||
int16_t x, int16_t y,
|
||||
const uint8_t bitmap[], int16_t w, int16_t h, uint16_t color, uint16_t bg)
|
||||
{
|
||||
if (
|
||||
((x + w - 1) < 0) || // Outside left
|
||||
((y + h - 1) < 0) || // Outside top
|
||||
(x > _max_x) || // Outside right
|
||||
(y > _max_y) // Outside bottom
|
||||
)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (
|
||||
(x < 0) || // Clip left
|
||||
(y < 0) || // Clip top
|
||||
((x + w - 1) > _max_x) || // Clip right
|
||||
((y + h - 1) > _max_y) // Clip bottom
|
||||
)
|
||||
{
|
||||
Arduino_GFX::drawBitmap(x, y, bitmap, w, h, color, bg);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint16_t c;
|
||||
int32_t pixels = w * h;
|
||||
uint8_t byte = 0;
|
||||
uint16_t idx = 0;
|
||||
startWrite();
|
||||
writeAddrWindow(x, y, w, h);
|
||||
for (int32_t i = 0; i < pixels; i++)
|
||||
{
|
||||
if (i & 7)
|
||||
{
|
||||
byte <<= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
byte = pgm_read_byte(&bitmap[idx++]);
|
||||
}
|
||||
c = (byte & 0x80) ? color : bg;
|
||||
_bus->write((c & 0xF800) >> 8);
|
||||
_bus->write((c & 0x07E0) >> 3);
|
||||
_bus->write((c & 0x001F) << 3);
|
||||
}
|
||||
endWrite();
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_TFT_18bit::drawBitmap(
|
||||
int16_t x, int16_t y,
|
||||
uint8_t *bitmap, int16_t w, int16_t h, uint16_t color, uint16_t bg)
|
||||
{
|
||||
if (
|
||||
((x + w - 1) < 0) || // Outside left
|
||||
((y + h - 1) < 0) || // Outside top
|
||||
(x > _max_x) || // Outside right
|
||||
(y > _max_y) // Outside bottom
|
||||
)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (
|
||||
(x < 0) || // Clip left
|
||||
(y < 0) || // Clip top
|
||||
((x + w - 1) > _max_x) || // Clip right
|
||||
((y + h - 1) > _max_y) // Clip bottom
|
||||
)
|
||||
{
|
||||
Arduino_GFX::drawBitmap(x, y, bitmap, w, h, color, bg);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint16_t c;
|
||||
int32_t pixels = w * h;
|
||||
uint8_t byte = 0;
|
||||
startWrite();
|
||||
writeAddrWindow(x, y, w, h);
|
||||
for (int32_t i = 0; i < pixels; i++)
|
||||
{
|
||||
if (i & 7)
|
||||
{
|
||||
byte <<= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
byte = *(bitmap++);
|
||||
}
|
||||
c = (byte & 0x80) ? color : bg;
|
||||
_bus->write((c & 0xF800) >> 8);
|
||||
_bus->write((c & 0x07E0) >> 3);
|
||||
_bus->write((c & 0x001F) << 3);
|
||||
}
|
||||
endWrite();
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_TFT_18bit::drawGrayscaleBitmap(
|
||||
int16_t x, int16_t y,
|
||||
const uint8_t bitmap[], int16_t w, int16_t h)
|
||||
{
|
||||
if (
|
||||
((x + w - 1) < 0) || // Outside left
|
||||
((y + h - 1) < 0) || // Outside top
|
||||
(x > _max_x) || // Outside right
|
||||
(y > _max_y) // Outside bottom
|
||||
)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (
|
||||
(x < 0) || // Clip left
|
||||
(y < 0) || // Clip top
|
||||
((x + w - 1) > _max_x) || // Clip right
|
||||
((y + h - 1) > _max_y) // Clip bottom
|
||||
)
|
||||
{
|
||||
Arduino_GFX::drawGrayscaleBitmap(x, y, bitmap, w, h);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t v;
|
||||
startWrite();
|
||||
writeAddrWindow(x, y, w, h);
|
||||
for (int16_t j = 0; j < h; j++, y++)
|
||||
{
|
||||
for (int16_t i = 0; i < w; i++)
|
||||
{
|
||||
v = pgm_read_byte(&bitmap[j * w + i]);
|
||||
_bus->write(v);
|
||||
_bus->write(v);
|
||||
_bus->write(v);
|
||||
}
|
||||
}
|
||||
endWrite();
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_TFT_18bit::drawGrayscaleBitmap(
|
||||
int16_t x, int16_t y,
|
||||
uint8_t *bitmap, int16_t w, int16_t h)
|
||||
{
|
||||
if (
|
||||
((x + w - 1) < 0) || // Outside left
|
||||
((y + h - 1) < 0) || // Outside top
|
||||
(x > _max_x) || // Outside right
|
||||
(y > _max_y) // Outside bottom
|
||||
)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (
|
||||
(x < 0) || // Clip left
|
||||
(y < 0) || // Clip top
|
||||
((x + w - 1) > _max_x) || // Clip right
|
||||
((y + h - 1) > _max_y) // Clip bottom
|
||||
)
|
||||
{
|
||||
Arduino_GFX::drawGrayscaleBitmap(x, y, bitmap, w, h);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t v;
|
||||
startWrite();
|
||||
writeAddrWindow(x, y, w, h);
|
||||
for (int16_t j = 0; j < h; j++, y++)
|
||||
{
|
||||
for (int16_t i = 0; i < w; i++)
|
||||
{
|
||||
v = bitmap[j * w + i];
|
||||
_bus->write(v);
|
||||
_bus->write(v);
|
||||
_bus->write(v);
|
||||
}
|
||||
}
|
||||
endWrite();
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_TFT_18bit::drawIndexedBitmap(
|
||||
int16_t x, int16_t y,
|
||||
uint8_t *bitmap, uint16_t *color_index, int16_t w, int16_t h, int16_t x_skip)
|
||||
{
|
||||
if (
|
||||
((x + w - 1) < 0) || // Outside left
|
||||
((y + h - 1) < 0) || // Outside top
|
||||
(x > _max_x) || // Outside right
|
||||
(y > _max_y) // Outside bottom
|
||||
)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (
|
||||
(x < 0) || // Clip left
|
||||
(y < 0) || // Clip top
|
||||
((x + w - 1) > _max_x) || // Clip right
|
||||
((y + h - 1) > _max_y) // Clip bottom
|
||||
)
|
||||
{
|
||||
Arduino_GFX::drawIndexedBitmap(x, y, bitmap, color_index, w, h, x_skip);
|
||||
}
|
||||
else
|
||||
{
|
||||
startWrite();
|
||||
writeAddrWindow(x, y, w, h);
|
||||
while (h--)
|
||||
{
|
||||
writeIndexedPixels(bitmap, color_index, w);
|
||||
bitmap += w + x_skip;
|
||||
}
|
||||
endWrite();
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_TFT_18bit::draw16bitRGBBitmap(
|
||||
int16_t x, int16_t y,
|
||||
const uint16_t bitmap[], int16_t w, int16_t h)
|
||||
{
|
||||
if (
|
||||
((x + w - 1) < 0) || // Outside left
|
||||
((y + h - 1) < 0) || // Outside top
|
||||
(x > _max_x) || // Outside right
|
||||
(y > _max_y) // Outside bottom
|
||||
)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (
|
||||
(x < 0) || // Clip left
|
||||
(y < 0) || // Clip top
|
||||
((x + w - 1) > _max_x) || // Clip right
|
||||
((y + h - 1) > _max_y) // Clip bottom
|
||||
)
|
||||
{
|
||||
Arduino_GFX::draw16bitRGBBitmap(x, y, bitmap, w, h);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint16_t d;
|
||||
startWrite();
|
||||
writeAddrWindow(x, y, w, h);
|
||||
for (int16_t j = 0; j < h; j++, y++)
|
||||
{
|
||||
for (int16_t i = 0; i < w; i++)
|
||||
{
|
||||
d = pgm_read_word(&bitmap[j * w + i]);
|
||||
_bus->write((d & 0xF800) >> 8);
|
||||
_bus->write((d & 0x07E0) >> 3);
|
||||
_bus->write(d << 3);
|
||||
}
|
||||
}
|
||||
endWrite();
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_TFT_18bit::draw16bitRGBBitmapWithMask(
|
||||
int16_t x, int16_t y,
|
||||
uint16_t *bitmap, uint8_t *mask, int16_t w, int16_t h)
|
||||
{
|
||||
if (
|
||||
((x + w - 1) < 0) || // Outside left
|
||||
((y + h - 1) < 0) || // Outside top
|
||||
(x > _max_x) || // Outside right
|
||||
(y > _max_y) // Outside bottom
|
||||
)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (
|
||||
(x < 0) || // Clip left
|
||||
(y < 0) || // Clip top
|
||||
((x + w - 1) > _max_x) || // Clip right
|
||||
((y + h - 1) > _max_y) // Clip bottom
|
||||
)
|
||||
{
|
||||
Arduino_GFX::draw16bitRGBBitmapWithMask(x, y, bitmap, mask, w, h);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint16_t d;
|
||||
int32_t offset = 0, maskIdx = 0, len = 0;
|
||||
uint8_t byte = 0;
|
||||
startWrite();
|
||||
for (int16_t j = 0; j < h; j++, y++)
|
||||
{
|
||||
for (int16_t i = 0; i < w; i++)
|
||||
{
|
||||
if (i & 7)
|
||||
{
|
||||
byte <<= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
byte = mask[maskIdx++];
|
||||
}
|
||||
if (byte & 0x80)
|
||||
{
|
||||
len++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (len)
|
||||
{
|
||||
writeAddrWindow(x + i - len, y, len, 1);
|
||||
for (int16_t i = len; i > 0; i--)
|
||||
{
|
||||
d = bitmap[offset - i];
|
||||
_bus->write((d & 0xF800) >> 8);
|
||||
_bus->write((d & 0x07E0) >> 3);
|
||||
_bus->write(d << 3);
|
||||
}
|
||||
len = 0;
|
||||
}
|
||||
}
|
||||
offset++;
|
||||
}
|
||||
if (len)
|
||||
{
|
||||
writeAddrWindow(x + w - 1 - len, y, len, 1);
|
||||
for (int16_t i = len; i > 0; i--)
|
||||
{
|
||||
d = bitmap[offset - i];
|
||||
_bus->write((d & 0xF800) >> 8);
|
||||
_bus->write((d & 0x07E0) >> 3);
|
||||
_bus->write(d << 3);
|
||||
}
|
||||
len = 0;
|
||||
}
|
||||
}
|
||||
endWrite();
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_TFT_18bit::draw16bitRGBBitmap(
|
||||
int16_t x, int16_t y,
|
||||
uint16_t *bitmap, int16_t w, int16_t h)
|
||||
{
|
||||
if (
|
||||
((x + w - 1) < 0) || // Outside left
|
||||
((y + h - 1) < 0) || // Outside top
|
||||
(x > _max_x) || // Outside right
|
||||
(y > _max_y) // Outside bottom
|
||||
)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (
|
||||
(x < 0) || // Clip left
|
||||
(y < 0) || // Clip top
|
||||
((x + w - 1) > _max_x) || // Clip right
|
||||
((y + h - 1) > _max_y) // Clip bottom
|
||||
)
|
||||
{
|
||||
Arduino_GFX::draw16bitRGBBitmap(x, y, bitmap, w, h);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint16_t d;
|
||||
startWrite();
|
||||
writeAddrWindow(x, y, w, h);
|
||||
for (int16_t j = 0; j < h; j++, y++)
|
||||
{
|
||||
for (int16_t i = 0; i < w; i++)
|
||||
{
|
||||
d = bitmap[j * w + i];
|
||||
_bus->write((d & 0xF800) >> 8);
|
||||
_bus->write((d & 0x07E0) >> 3);
|
||||
_bus->write(d << 3);
|
||||
}
|
||||
}
|
||||
endWrite();
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_TFT_18bit::draw16bitBeRGBBitmap(
|
||||
int16_t x, int16_t y,
|
||||
uint16_t *bitmap, int16_t w, int16_t h)
|
||||
{
|
||||
if (
|
||||
((x + w - 1) < 0) || // Outside left
|
||||
((y + h - 1) < 0) || // Outside top
|
||||
(x > _max_x) || // Outside right
|
||||
(y > _max_y) // Outside bottom
|
||||
)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (
|
||||
(x < 0) || // Clip left
|
||||
(y < 0) || // Clip top
|
||||
((x + w - 1) > _max_x) || // Clip right
|
||||
((y + h - 1) > _max_y) // Clip bottom
|
||||
)
|
||||
{
|
||||
Arduino_GFX::draw16bitBeRGBBitmap(x, y, bitmap, w, h);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint16_t d;
|
||||
startWrite();
|
||||
writeAddrWindow(x, y, w, h);
|
||||
for (int16_t j = 0; j < h; j++, y++)
|
||||
{
|
||||
for (int16_t i = 0; i < w; i++)
|
||||
{
|
||||
d = bitmap[j * w + i];
|
||||
_bus->write((d & 0x00F8));
|
||||
_bus->write(((d & 0xE000) >> 11) | (d & 0x0007) << 5);
|
||||
_bus->write((d & 0x1F00) >> 5);
|
||||
}
|
||||
}
|
||||
endWrite();
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_TFT_18bit::draw24bitRGBBitmap(
|
||||
int16_t x, int16_t y,
|
||||
const uint8_t bitmap[], int16_t w, int16_t h)
|
||||
{
|
||||
if (
|
||||
((x + w - 1) < 0) || // Outside left
|
||||
((y + h - 1) < 0) || // Outside top
|
||||
(x > _max_x) || // Outside right
|
||||
(y > _max_y) // Outside bottom
|
||||
)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (
|
||||
(x < 0) || // Clip left
|
||||
(y < 0) || // Clip top
|
||||
((x + w - 1) > _max_x) || // Clip right
|
||||
((y + h - 1) > _max_y) // Clip bottom
|
||||
)
|
||||
{
|
||||
Arduino_GFX::draw24bitRGBBitmap(x, y, bitmap, w, h);
|
||||
}
|
||||
else
|
||||
{
|
||||
int16_t offset = 0;
|
||||
startWrite();
|
||||
writeAddrWindow(x, y, w, h);
|
||||
for (int16_t j = 0; j < h; j++, y++)
|
||||
{
|
||||
for (int16_t i = 0; i < w; i++)
|
||||
{
|
||||
_bus->write(pgm_read_byte(&bitmap[offset++]));
|
||||
_bus->write(pgm_read_byte(&bitmap[offset++]));
|
||||
_bus->write(pgm_read_byte(&bitmap[offset++]));
|
||||
}
|
||||
}
|
||||
endWrite();
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_TFT_18bit::draw24bitRGBBitmap(
|
||||
int16_t x, int16_t y,
|
||||
uint8_t *bitmap, int16_t w, int16_t h)
|
||||
{
|
||||
if (
|
||||
((x + w - 1) < 0) || // Outside left
|
||||
((y + h - 1) < 0) || // Outside top
|
||||
(x > _max_x) || // Outside right
|
||||
(y > _max_y) // Outside bottom
|
||||
)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (
|
||||
(x < 0) || // Clip left
|
||||
(y < 0) || // Clip top
|
||||
((x + w - 1) > _max_x) || // Clip right
|
||||
((y + h - 1) > _max_y) // Clip bottom
|
||||
)
|
||||
{
|
||||
Arduino_GFX::draw24bitRGBBitmap(x, y, bitmap, w, h);
|
||||
}
|
||||
else
|
||||
{
|
||||
startWrite();
|
||||
writeAddrWindow(x, y, w, h);
|
||||
_bus->writeBytes(bitmap, w * h * 3);
|
||||
endWrite();
|
||||
}
|
||||
}
|
||||
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* start rewrite from:
|
||||
* https://github.com/adafruit/Adafruit-GFX-Library.git
|
||||
*/
|
||||
#ifndef _ARDUINO_TFT_18BIT_H_
|
||||
#define _ARDUINO_TFT_18BIT_H_
|
||||
|
||||
#include "Arduino_DataBus.h"
|
||||
#include "Arduino_GFX.h"
|
||||
#include "Arduino_TFT.h"
|
||||
|
||||
class Arduino_TFT_18bit : public Arduino_TFT
|
||||
{
|
||||
public:
|
||||
Arduino_TFT_18bit(Arduino_DataBus *bus, int8_t rst, uint8_t r, bool ips, int16_t w, int16_t h, uint8_t col_offset1, uint8_t row_offset1, uint8_t col_offset2, uint8_t row_offset2);
|
||||
|
||||
void writeColor(uint16_t color) override;
|
||||
void writePixelPreclipped(int16_t x, int16_t y, uint16_t color) override;
|
||||
void writeRepeat(uint16_t color, uint32_t len) override;
|
||||
|
||||
// TFT optimization code, too big for ATMEL family
|
||||
#if !defined(LITTLE_FOOT_PRINT)
|
||||
void writePixels(uint16_t *data, uint32_t len) override;
|
||||
void writeIndexedPixels(uint8_t *bitmap, uint16_t *color_index, uint32_t len) override;
|
||||
void writeIndexedPixelsDouble(uint8_t *bitmap, uint16_t *color_index, uint32_t len) override;
|
||||
|
||||
void drawBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h, uint16_t color, uint16_t bg) override;
|
||||
void drawBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h, uint16_t color, uint16_t bg) override;
|
||||
void drawGrayscaleBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h) override;
|
||||
void drawGrayscaleBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h) override;
|
||||
void drawIndexedBitmap(int16_t x, int16_t y, uint8_t *bitmap, uint16_t *color_index, int16_t w, int16_t h, int16_t x_skip = 0) override;
|
||||
void draw16bitRGBBitmapWithMask(int16_t x, int16_t y, uint16_t *bitmap, uint8_t *mask, int16_t w, int16_t h) override;
|
||||
void draw16bitRGBBitmap(int16_t x, int16_t y, const uint16_t bitmap[], int16_t w, int16_t h) override;
|
||||
void draw16bitRGBBitmap(int16_t x, int16_t y, uint16_t *bitmap, int16_t w, int16_t h) override;
|
||||
void draw16bitBeRGBBitmap(int16_t x, int16_t y, uint16_t *bitmap, int16_t w, int16_t h) override;
|
||||
void draw24bitRGBBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h) override;
|
||||
void draw24bitRGBBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h) override;
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
|
||||
protected:
|
||||
private:
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
https://en.wikipedia.org/wiki/YCbCr
|
||||
|
||||
Y2I16 = (Y - 16) * 255 / 219
|
||||
CR2R16 = ((Cr - 128) * 255 / 224 * 1.402) + 223
|
||||
CR2G16 = ((Cr - 128) * 255 / 224 * 1.402 *0.299 / 0.587) - 172
|
||||
CB2G16 = ((Cb - 128) * 255 / 224 * 1.772 * 0.114 / 0.587)
|
||||
CB2B16 = ((Cb - 128) * 255 / 224 * 1.772) + 277
|
||||
|
||||
Note:
|
||||
- The extra CR2R16 + 223, CR2G16 - 172 and CB2B16 + 277 are designed
|
||||
for making the conversion result become zero based integer
|
||||
- CLIP* mapping will clip value to 0-255
|
||||
- CLIP*BE mapping will clip value to 0-255 at the same time shift bit
|
||||
to big endian RGB565 format
|
||||
*/
|
||||
|
||||
static const int16_t Y2I16[] = {-19, -17, -16, -15, -14, -13, -12, -10, -9, -8, -7, -6, -5, -3, -2, -1, 0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 12, 13, 14, 15, 16, 17, 19, 20, 21, 22, 23, 24, 26, 27, 28, 29, 30, 31, 33, 34, 35, 36, 37, 38, 40, 41, 42, 43, 44, 45, 47, 48, 49, 50, 51, 52, 54, 55, 56, 57, 58, 59, 61, 62, 63, 64, 65, 66, 68, 69, 70, 71, 72, 73, 75, 76, 77, 78, 79, 80, 82, 83, 84, 85, 86, 87, 88, 90, 91, 92, 93, 94, 95, 97, 98, 99, 100, 101, 102, 104, 105, 106, 107, 108, 109, 111, 112, 113, 114, 115, 116, 118, 119, 120, 121, 122, 123, 125, 126, 127, 128, 129, 130, 132, 133, 134, 135, 136, 137, 139, 140, 141, 142, 143, 144, 146, 147, 148, 149, 150, 151, 153, 154, 155, 156, 157, 158, 160, 161, 162, 163, 164, 165, 167, 168, 169, 170, 171, 172, 173, 175, 176, 177, 178, 179, 180, 182, 183, 184, 185, 186, 187, 189, 190, 191, 192, 193, 194, 196, 197, 198, 199, 200, 201, 203, 204, 205, 206, 207, 208, 210, 211, 212, 213, 214, 215, 217, 218, 219, 220, 221, 222, 224, 225, 226, 227, 228, 229, 231, 232, 233, 234, 235, 236, 238, 239, 240, 241, 242, 243, 245, 246, 247, 248, 249, 250, 252, 253, 254, 255, 256, 257, 258, 260, 261, 262, 263, 264, 265, 267, 268, 269, 270, 271, 272, 274, 275, 276, 277, 278};
|
||||
static const int16_t CR2R16[] = {19, 20, 22, 23, 25, 27, 28, 30, 31, 33, 35, 36, 38, 39, 41, 43, 44, 46, 47, 49, 51, 52, 54, 55, 57, 59, 60, 62, 63, 65, 67, 68, 70, 71, 73, 75, 76, 78, 79, 81, 83, 84, 86, 87, 89, 91, 92, 94, 95, 97, 99, 100, 102, 103, 105, 106, 108, 110, 111, 113, 114, 116, 118, 119, 121, 122, 124, 126, 127, 129, 130, 132, 134, 135, 137, 138, 140, 142, 143, 145, 146, 148, 150, 151, 153, 154, 156, 158, 159, 161, 162, 164, 166, 167, 169, 170, 172, 174, 175, 177, 178, 180, 182, 183, 185, 186, 188, 189, 191, 193, 194, 196, 197, 199, 201, 202, 204, 205, 207, 209, 210, 212, 213, 215, 217, 218, 220, 221, 223, 225, 226, 228, 229, 231, 233, 234, 236, 237, 239, 241, 242, 244, 245, 247, 249, 250, 252, 253, 255, 257, 258, 260, 261, 263, 264, 266, 268, 269, 271, 272, 274, 276, 277, 279, 280, 282, 284, 285, 287, 288, 290, 292, 293, 295, 296, 298, 300, 301, 303, 304, 306, 308, 309, 311, 312, 314, 316, 317, 319, 320, 322, 324, 325, 327, 328, 330, 332, 333, 335, 336, 338, 340, 341, 343, 344, 346, 347, 349, 351, 352, 354, 355, 357, 359, 360, 362, 363, 365, 367, 368, 370, 371, 373, 375, 376, 378, 379, 381, 383, 384, 386, 387, 389, 391, 392, 394, 395, 397, 399, 400, 402, 403, 405, 407, 408, 410, 411, 413, 415, 416, 418, 419, 421, 423, 424, 426};
|
||||
static const int16_t CR2G16[] = {-276, -275, -274, -274, -273, -272, -271, -270, -270, -269, -268, -267, -266, -265, -265, -264, -263, -262, -261, -261, -260, -259, -258, -257, -257, -256, -255, -254, -253, -252, -252, -251, -250, -249, -248, -248, -247, -246, -245, -244, -244, -243, -242, -241, -240, -239, -239, -238, -237, -236, -235, -235, -234, -233, -232, -231, -231, -230, -229, -228, -227, -226, -226, -225, -224, -223, -222, -222, -221, -220, -219, -218, -218, -217, -216, -215, -214, -213, -213, -212, -211, -210, -209, -209, -208, -207, -206, -205, -205, -204, -203, -202, -201, -200, -200, -199, -198, -197, -196, -196, -195, -194, -193, -192, -192, -191, -190, -189, -188, -187, -187, -186, -185, -184, -183, -183, -182, -181, -180, -179, -179, -178, -177, -176, -175, -174, -174, -173, -172, -171, -170, -170, -169, -168, -167, -166, -165, -165, -164, -163, -162, -161, -161, -160, -159, -158, -157, -157, -156, -155, -154, -153, -152, -152, -151, -150, -149, -148, -148, -147, -146, -145, -144, -144, -143, -142, -141, -140, -139, -139, -138, -137, -136, -135, -135, -134, -133, -132, -131, -131, -130, -129, -128, -127, -126, -126, -125, -124, -123, -122, -122, -121, -120, -119, -118, -118, -117, -116, -115, -114, -113, -113, -112, -111, -110, -109, -109, -108, -107, -106, -105, -105, -104, -103, -102, -101, -100, -100, -99, -98, -97, -96, -96, -95, -94, -93, -92, -92, -91, -90, -89, -88, -87, -87, -86, -85, -84, -83, -83, -82, -81, -80, -79, -79, -78, -77, -76, -75, -74, -74, -73, -72, -71, -70, -70, -69};
|
||||
static const int16_t CB2G16[] = {-50, -50, -49, -49, -49, -48, -48, -47, -47, -47, -46, -46, -45, -45, -45, -44, -44, -43, -43, -43, -42, -42, -42, -41, -41, -40, -40, -40, -39, -39, -38, -38, -38, -37, -37, -36, -36, -36, -35, -35, -34, -34, -34, -33, -33, -33, -32, -32, -31, -31, -31, -30, -30, -29, -29, -29, -28, -28, -27, -27, -27, -26, -26, -25, -25, -25, -24, -24, -24, -23, -23, -22, -22, -22, -21, -21, -20, -20, -20, -19, -19, -18, -18, -18, -17, -17, -16, -16, -16, -15, -15, -14, -14, -14, -13, -13, -13, -12, -12, -11, -11, -11, -10, -10, -9, -9, -9, -8, -8, -7, -7, -7, -6, -6, -5, -5, -5, -4, -4, -4, -3, -3, -2, -2, -2, -1, -1, 0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 7, 7, 7, 8, 8, 9, 9, 9, 10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 14, 15, 15, 16, 16, 16, 17, 17, 18, 18, 18, 19, 19, 20, 20, 20, 21, 21, 22, 22, 22, 23, 23, 24, 24, 24, 25, 25, 25, 26, 26, 27, 27, 27, 28, 28, 29, 29, 29, 30, 30, 31, 31, 31, 32, 32, 33, 33, 33, 34, 34, 34, 35, 35, 36, 36, 36, 37, 37, 38, 38, 38, 39, 39, 40, 40, 40, 41, 41, 42, 42, 42, 43, 43, 43, 44, 44, 45, 45, 45, 46, 46, 47, 47, 47, 48, 48, 49, 49, 49, 50};
|
||||
static const int16_t CB2B16[] = {19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, 97, 99, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 184, 186, 188, 190, 192, 194, 196, 198, 200, 202, 204, 206, 208, 210, 212, 214, 216, 219, 221, 223, 225, 227, 229, 231, 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 255, 257, 259, 261, 263, 265, 267, 269, 271, 273, 275, 277, 279, 281, 283, 285, 287, 289, 291, 293, 295, 297, 299, 301, 303, 305, 307, 309, 311, 313, 315, 317, 319, 321, 323, 325, 327, 329, 331, 333, 335, 338, 340, 342, 344, 346, 348, 350, 352, 354, 356, 358, 360, 362, 364, 366, 368, 370, 372, 374, 376, 378, 380, 382, 384, 386, 388, 390, 392, 394, 396, 398, 400, 402, 404, 406, 408, 410, 412, 414, 416, 418, 420, 422, 424, 426, 428, 430, 432, 434, 436, 438, 440, 442, 444, 446, 448, 450, 452, 455, 457, 459, 461, 463, 465, 467, 469, 471, 473, 475, 477, 479, 481, 483, 485, 487, 489, 491, 493, 495, 497, 499, 501, 503, 505, 507, 509, 511, 513, 515, 517, 519, 521, 523, 525, 527, 529, 531, 533};
|
||||
|
||||
static const uint16_t CLIPR[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 4096, 4096, 4096, 4096, 4096, 4096, 4096, 4096, 6144, 6144, 6144, 6144, 6144, 6144, 6144, 6144, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192, 10240, 10240, 10240, 10240, 10240, 10240, 10240, 10240, 12288, 12288, 12288, 12288, 12288, 12288, 12288, 12288, 14336, 14336, 14336, 14336, 14336, 14336, 14336, 14336, 16384, 16384, 16384, 16384, 16384, 16384, 16384, 16384, 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, 20480, 20480, 20480, 20480, 20480, 20480, 20480, 20480, 22528, 22528, 22528, 22528, 22528, 22528, 22528, 22528, 24576, 24576, 24576, 24576, 24576, 24576, 24576, 24576, 26624, 26624, 26624, 26624, 26624, 26624, 26624, 26624, 28672, 28672, 28672, 28672, 28672, 28672, 28672, 28672, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 30720, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 34816, 34816, 34816, 34816, 34816, 34816, 34816, 34816, 36864, 36864, 36864, 36864, 36864, 36864, 36864, 36864, 38912, 38912, 38912, 38912, 38912, 38912, 38912, 38912, 40960, 40960, 40960, 40960, 40960, 40960, 40960, 40960, 43008, 43008, 43008, 43008, 43008, 43008, 43008, 43008, 45056, 45056, 45056, 45056, 45056, 45056, 45056, 45056, 47104, 47104, 47104, 47104, 47104, 47104, 47104, 47104, 49152, 49152, 49152, 49152, 49152, 49152, 49152, 49152, 51200, 51200, 51200, 51200, 51200, 51200, 51200, 51200, 53248, 53248, 53248, 53248, 53248, 53248, 53248, 53248, 55296, 55296, 55296, 55296, 55296, 55296, 55296, 55296, 57344, 57344, 57344, 57344, 57344, 57344, 57344, 57344, 59392, 59392, 59392, 59392, 59392, 59392, 59392, 59392, 61440, 61440, 61440, 61440, 61440, 61440, 61440, 61440, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488, 63488};
|
||||
static const uint16_t CLIPG[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 32, 32, 32, 64, 64, 64, 64, 96, 96, 96, 96, 128, 128, 128, 128, 160, 160, 160, 160, 192, 192, 192, 192, 224, 224, 224, 224, 256, 256, 256, 256, 288, 288, 288, 288, 320, 320, 320, 320, 352, 352, 352, 352, 384, 384, 384, 384, 416, 416, 416, 416, 448, 448, 448, 448, 480, 480, 480, 480, 512, 512, 512, 512, 544, 544, 544, 544, 576, 576, 576, 576, 608, 608, 608, 608, 640, 640, 640, 640, 672, 672, 672, 672, 704, 704, 704, 704, 736, 736, 736, 736, 768, 768, 768, 768, 800, 800, 800, 800, 832, 832, 832, 832, 864, 864, 864, 864, 896, 896, 896, 896, 928, 928, 928, 928, 960, 960, 960, 960, 992, 992, 992, 992, 1024, 1024, 1024, 1024, 1056, 1056, 1056, 1056, 1088, 1088, 1088, 1088, 1120, 1120, 1120, 1120, 1152, 1152, 1152, 1152, 1184, 1184, 1184, 1184, 1216, 1216, 1216, 1216, 1248, 1248, 1248, 1248, 1280, 1280, 1280, 1280, 1312, 1312, 1312, 1312, 1344, 1344, 1344, 1344, 1376, 1376, 1376, 1376, 1408, 1408, 1408, 1408, 1440, 1440, 1440, 1440, 1472, 1472, 1472, 1472, 1504, 1504, 1504, 1504, 1536, 1536, 1536, 1536, 1568, 1568, 1568, 1568, 1600, 1600, 1600, 1600, 1632, 1632, 1632, 1632, 1664, 1664, 1664, 1664, 1696, 1696, 1696, 1696, 1728, 1728, 1728, 1728, 1760, 1760, 1760, 1760, 1792, 1792, 1792, 1792, 1824, 1824, 1824, 1824, 1856, 1856, 1856, 1856, 1888, 1888, 1888, 1888, 1920, 1920, 1920, 1920, 1952, 1952, 1952, 1952, 1984, 1984, 1984, 1984, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016, 2016};
|
||||
static const uint16_t CLIPB[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 30, 30, 30, 30, 30, 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31};
|
||||
|
||||
static const uint16_t CLIPRBE[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, 16, 16, 16, 16, 16, 16, 16, 16, 24, 24, 24, 24, 24, 24, 24, 24, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40, 48, 48, 48, 48, 48, 48, 48, 48, 56, 56, 56, 56, 56, 56, 56, 56, 64, 64, 64, 64, 64, 64, 64, 64, 72, 72, 72, 72, 72, 72, 72, 72, 80, 80, 80, 80, 80, 80, 80, 80, 88, 88, 88, 88, 88, 88, 88, 88, 96, 96, 96, 96, 96, 96, 96, 96, 104, 104, 104, 104, 104, 104, 104, 104, 112, 112, 112, 112, 112, 112, 112, 112, 120, 120, 120, 120, 120, 120, 120, 120, 128, 128, 128, 128, 128, 128, 128, 128, 136, 136, 136, 136, 136, 136, 136, 136, 144, 144, 144, 144, 144, 144, 144, 144, 152, 152, 152, 152, 152, 152, 152, 152, 160, 160, 160, 160, 160, 160, 160, 160, 168, 168, 168, 168, 168, 168, 168, 168, 176, 176, 176, 176, 176, 176, 176, 176, 184, 184, 184, 184, 184, 184, 184, 184, 192, 192, 192, 192, 192, 192, 192, 192, 200, 200, 200, 200, 200, 200, 200, 200, 208, 208, 208, 208, 208, 208, 208, 208, 216, 216, 216, 216, 216, 216, 216, 216, 224, 224, 224, 224, 224, 224, 224, 224, 232, 232, 232, 232, 232, 232, 232, 232, 240, 240, 240, 240, 240, 240, 240, 240, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248};
|
||||
static const uint16_t CLIPGBE[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8192, 8192, 8192, 8192, 16384, 16384, 16384, 16384, 24576, 24576, 24576, 24576, 32768, 32768, 32768, 32768, 40960, 40960, 40960, 40960, 49152, 49152, 49152, 49152, 57344, 57344, 57344, 57344, 1, 1, 1, 1, 8193, 8193, 8193, 8193, 16385, 16385, 16385, 16385, 24577, 24577, 24577, 24577, 32769, 32769, 32769, 32769, 40961, 40961, 40961, 40961, 49153, 49153, 49153, 49153, 57345, 57345, 57345, 57345, 2, 2, 2, 2, 8194, 8194, 8194, 8194, 16386, 16386, 16386, 16386, 24578, 24578, 24578, 24578, 32770, 32770, 32770, 32770, 40962, 40962, 40962, 40962, 49154, 49154, 49154, 49154, 57346, 57346, 57346, 57346, 3, 3, 3, 3, 8195, 8195, 8195, 8195, 16387, 16387, 16387, 16387, 24579, 24579, 24579, 24579, 32771, 32771, 32771, 32771, 40963, 40963, 40963, 40963, 49155, 49155, 49155, 49155, 57347, 57347, 57347, 57347, 4, 4, 4, 4, 8196, 8196, 8196, 8196, 16388, 16388, 16388, 16388, 24580, 24580, 24580, 24580, 32772, 32772, 32772, 32772, 40964, 40964, 40964, 40964, 49156, 49156, 49156, 49156, 57348, 57348, 57348, 57348, 5, 5, 5, 5, 8197, 8197, 8197, 8197, 16389, 16389, 16389, 16389, 24581, 24581, 24581, 24581, 32773, 32773, 32773, 32773, 40965, 40965, 40965, 40965, 49157, 49157, 49157, 49157, 57349, 57349, 57349, 57349, 6, 6, 6, 6, 8198, 8198, 8198, 8198, 16390, 16390, 16390, 16390, 24582, 24582, 24582, 24582, 32774, 32774, 32774, 32774, 40966, 40966, 40966, 40966, 49158, 49158, 49158, 49158, 57350, 57350, 57350, 57350, 7, 7, 7, 7, 8199, 8199, 8199, 8199, 16391, 16391, 16391, 16391, 24583, 24583, 24583, 24583, 32775, 32775, 32775, 32775, 40967, 40967, 40967, 40967, 49159, 49159, 49159, 49159, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351, 57351};
|
||||
static const uint16_t CLIPBBE[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 256, 256, 256, 256, 256, 256, 256, 256, 512, 512, 512, 512, 512, 512, 512, 512, 768, 768, 768, 768, 768, 768, 768, 768, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1280, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1536, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2304, 2304, 2304, 2304, 2304, 2304, 2304, 2304, 2560, 2560, 2560, 2560, 2560, 2560, 2560, 2560, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 3072, 3072, 3072, 3072, 3072, 3072, 3072, 3072, 3328, 3328, 3328, 3328, 3328, 3328, 3328, 3328, 3584, 3584, 3584, 3584, 3584, 3584, 3584, 3584, 3840, 3840, 3840, 3840, 3840, 3840, 3840, 3840, 4096, 4096, 4096, 4096, 4096, 4096, 4096, 4096, 4352, 4352, 4352, 4352, 4352, 4352, 4352, 4352, 4608, 4608, 4608, 4608, 4608, 4608, 4608, 4608, 4864, 4864, 4864, 4864, 4864, 4864, 4864, 4864, 5120, 5120, 5120, 5120, 5120, 5120, 5120, 5120, 5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, 5632, 5632, 5632, 5632, 5632, 5632, 5632, 5632, 5888, 5888, 5888, 5888, 5888, 5888, 5888, 5888, 6144, 6144, 6144, 6144, 6144, 6144, 6144, 6144, 6400, 6400, 6400, 6400, 6400, 6400, 6400, 6400, 6656, 6656, 6656, 6656, 6656, 6656, 6656, 6656, 6912, 6912, 6912, 6912, 6912, 6912, 6912, 6912, 7168, 7168, 7168, 7168, 7168, 7168, 7168, 7168, 7424, 7424, 7424, 7424, 7424, 7424, 7424, 7424, 7680, 7680, 7680, 7680, 7680, 7680, 7680, 7680, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936, 7936};
|
||||
@@ -0,0 +1,621 @@
|
||||
#include "../Arduino_DataBus.h"
|
||||
#if !defined(LITTLE_FOOT_PRINT)
|
||||
|
||||
#include "../Arduino_GFX.h"
|
||||
#include "Arduino_Canvas.h"
|
||||
|
||||
Arduino_Canvas::Arduino_Canvas(
|
||||
int16_t w, int16_t h, Arduino_G *output, int16_t output_x, int16_t output_y, uint8_t r)
|
||||
: Arduino_GFX(w, h), _output(output), _output_x(output_x), _output_y(output_y)
|
||||
{
|
||||
MAX_X = WIDTH - 1;
|
||||
MAX_Y = HEIGHT - 1;
|
||||
setRotation(r);
|
||||
}
|
||||
|
||||
Arduino_Canvas::~Arduino_Canvas()
|
||||
{
|
||||
if (_framebuffer)
|
||||
{
|
||||
free(_framebuffer);
|
||||
}
|
||||
}
|
||||
|
||||
bool Arduino_Canvas::begin(int32_t speed)
|
||||
{
|
||||
if (
|
||||
(speed != GFX_SKIP_OUTPUT_BEGIN) && (_output))
|
||||
{
|
||||
if (!_output->begin(speed))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_framebuffer)
|
||||
{
|
||||
size_t s = _width * _height * 2;
|
||||
#if defined(ESP32)
|
||||
_framebuffer = (uint16_t *)aligned_alloc(16, s);
|
||||
#else
|
||||
_framebuffer = (uint16_t *)malloc(s);
|
||||
#endif
|
||||
if (!_framebuffer)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Arduino_Canvas::writePixelPreclipped(int16_t x, int16_t y, uint16_t color)
|
||||
{
|
||||
|
||||
uint16_t *fb = _framebuffer;
|
||||
switch (_rotation)
|
||||
{
|
||||
case 1:
|
||||
fb += (int32_t)x * _height;
|
||||
fb += _max_y - y;
|
||||
*fb = color;
|
||||
break;
|
||||
case 2:
|
||||
fb += (int32_t)(_max_y - y) * _width;
|
||||
fb += _max_x - x;
|
||||
*fb = color;
|
||||
break;
|
||||
case 3:
|
||||
fb += (int32_t)(_max_x - x) * _height;
|
||||
fb += y;
|
||||
*fb = color;
|
||||
break;
|
||||
default: // case 0:
|
||||
fb += (int32_t)y * _width;
|
||||
fb += x;
|
||||
*fb = color;
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_Canvas::writeFastVLine(int16_t x, int16_t y,
|
||||
int16_t h, uint16_t color)
|
||||
{
|
||||
switch (_rotation)
|
||||
{
|
||||
case 1:
|
||||
writeFastHLineCore(_height - y - h, x, h, color);
|
||||
break;
|
||||
case 2:
|
||||
writeFastVLineCore(_max_x - x, _height - y - h, h, color);
|
||||
break;
|
||||
case 3:
|
||||
writeFastHLineCore(y, _max_x - x, h, color);
|
||||
break;
|
||||
default: // case 0:
|
||||
writeFastVLineCore(x, y, h, color);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_Canvas::writeFastVLineCore(int16_t x, int16_t y,
|
||||
int16_t h, uint16_t color)
|
||||
{
|
||||
// log_i("writeFastVLineCore(x: %d, y: %d, h: %d)", x, y, h);
|
||||
if (_ordered_in_range(x, 0, MAX_X) && h)
|
||||
{ // X on screen, nonzero height
|
||||
if (h < 0)
|
||||
{ // If negative height...
|
||||
y += h + 1; // Move Y to top edge
|
||||
h = -h; // Use positive height
|
||||
}
|
||||
if (y <= MAX_Y)
|
||||
{ // Not off bottom
|
||||
int16_t y2 = y + h - 1;
|
||||
if (y2 >= 0)
|
||||
{ // Not off top
|
||||
// Line partly or fully overlaps screen
|
||||
if (y < 0)
|
||||
{
|
||||
y = 0;
|
||||
h = y2 + 1;
|
||||
} // Clip top
|
||||
if (y2 > MAX_Y)
|
||||
{
|
||||
h = MAX_Y - y + 1;
|
||||
} // Clip bottom
|
||||
|
||||
uint16_t *fb = _framebuffer + ((int32_t)y * WIDTH) + x;
|
||||
while (h--)
|
||||
{
|
||||
*fb = color;
|
||||
fb += WIDTH;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_Canvas::writeFastHLine(int16_t x, int16_t y,
|
||||
int16_t w, uint16_t color)
|
||||
{
|
||||
// log_i("writeFastHLine(x: %d, y: %d, w: %d)", x, y, w);
|
||||
switch (_rotation)
|
||||
{
|
||||
case 1:
|
||||
writeFastVLineCore(_max_y - y, x, w, color);
|
||||
break;
|
||||
case 2:
|
||||
writeFastHLineCore(_width - x - w, _max_y - y, w, color);
|
||||
break;
|
||||
case 3:
|
||||
writeFastVLineCore(y, _width - x - w, w, color);
|
||||
break;
|
||||
default: // case 0:
|
||||
writeFastHLineCore(x, y, w, color);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_Canvas::writeFastHLineCore(int16_t x, int16_t y,
|
||||
int16_t w, uint16_t color)
|
||||
{
|
||||
// log_i("writeFastHLineCore(x: %d, y: %d, w: %d)", x, y, w);
|
||||
if (_ordered_in_range(y, 0, MAX_Y) && w)
|
||||
{ // Y on screen, nonzero width
|
||||
if (w < 0)
|
||||
{ // If negative width...
|
||||
x += w + 1; // Move X to left edge
|
||||
w = -w; // Use positive width
|
||||
}
|
||||
if (x <= MAX_X)
|
||||
{ // Not off right
|
||||
int16_t x2 = x + w - 1;
|
||||
if (x2 >= 0)
|
||||
{ // Not off left
|
||||
// Line partly or fully overlaps screen
|
||||
if (x < 0)
|
||||
{
|
||||
x = 0;
|
||||
w = x2 + 1;
|
||||
} // Clip left
|
||||
if (x2 > MAX_X)
|
||||
{
|
||||
w = MAX_X - x + 1;
|
||||
} // Clip right
|
||||
|
||||
uint16_t *fb = _framebuffer + ((int32_t)y * WIDTH) + x;
|
||||
while (w--)
|
||||
{
|
||||
*(fb++) = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_Canvas::writeFillRectPreclipped(int16_t x, int16_t y,
|
||||
int16_t w, int16_t h, uint16_t color)
|
||||
{
|
||||
// log_i("writeFillRectPreclipped(x: %d, y: %d, w: %d, h: %d)", x, y, w, h);
|
||||
if (_rotation > 0)
|
||||
{
|
||||
int16_t t = x;
|
||||
switch (_rotation)
|
||||
{
|
||||
case 1:
|
||||
x = WIDTH - y - h;
|
||||
y = t;
|
||||
t = w;
|
||||
w = h;
|
||||
h = t;
|
||||
break;
|
||||
case 2:
|
||||
x = WIDTH - x - w;
|
||||
y = HEIGHT - y - h;
|
||||
break;
|
||||
case 3:
|
||||
x = y;
|
||||
y = HEIGHT - t - w;
|
||||
t = w;
|
||||
w = h;
|
||||
h = t;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// log_i("adjusted writeFillRectPreclipped(x: %d, y: %d, w: %d, h: %d)", x, y, w, h);
|
||||
uint16_t *row = _framebuffer;
|
||||
row += y * WIDTH;
|
||||
row += x;
|
||||
for (int j = 0; j < h; j++)
|
||||
{
|
||||
for (int i = 0; i < w; i++)
|
||||
{
|
||||
row[i] = color;
|
||||
}
|
||||
row += WIDTH;
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_Canvas::drawIndexedBitmap(
|
||||
int16_t x, int16_t y,
|
||||
uint8_t *bitmap, uint16_t *color_index, int16_t w, int16_t h, int16_t x_skip)
|
||||
{
|
||||
if (_rotation > 0)
|
||||
{
|
||||
Arduino_GFX::drawIndexedBitmap(x, y, bitmap, color_index, w, h, x_skip);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (
|
||||
((x + w - 1) < 0) || // Outside left
|
||||
((y + h - 1) < 0) || // Outside top
|
||||
(x > _max_x) || // Outside right
|
||||
(y > _max_y) // Outside bottom
|
||||
)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((y + h - 1) > _max_y)
|
||||
{
|
||||
h -= (y + h - 1) - _max_y;
|
||||
}
|
||||
if (y < 0)
|
||||
{
|
||||
bitmap -= y * (w + x_skip);
|
||||
h += y;
|
||||
y = 0;
|
||||
}
|
||||
if ((x + w - 1) > _max_x)
|
||||
{
|
||||
x_skip += (x + w - 1) - _max_x;
|
||||
w -= (x + w - 1) - _max_x;
|
||||
}
|
||||
if (x < 0)
|
||||
{
|
||||
bitmap -= x;
|
||||
x_skip -= x;
|
||||
w += x;
|
||||
x = 0;
|
||||
}
|
||||
uint16_t *row = _framebuffer;
|
||||
row += y * _width;
|
||||
row += x;
|
||||
int16_t i;
|
||||
int16_t wi;
|
||||
while (h--)
|
||||
{
|
||||
i = 0;
|
||||
wi = w;
|
||||
while (wi >= 4)
|
||||
{
|
||||
uint32_t b32 = *((uint32_t *)bitmap);
|
||||
row[i++] = color_index[(b32 & 0xff)];
|
||||
row[i++] = color_index[(b32 & 0xff00) >> 8];
|
||||
row[i++] = color_index[(b32 & 0xff0000) >> 16];
|
||||
row[i++] = color_index[(b32 & 0xff000000) >> 24];
|
||||
wi -= 4;
|
||||
bitmap += 4;
|
||||
}
|
||||
while (i < w)
|
||||
{
|
||||
row[i++] = color_index[*bitmap++];
|
||||
}
|
||||
bitmap += x_skip;
|
||||
row += _width;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_Canvas::drawIndexedBitmap(
|
||||
int16_t x, int16_t y,
|
||||
uint8_t *bitmap, uint16_t *color_index, uint8_t chroma_key, int16_t w, int16_t h, int16_t x_skip)
|
||||
{
|
||||
if (_rotation > 0)
|
||||
{
|
||||
Arduino_GFX::drawIndexedBitmap(x, y, bitmap, color_index, chroma_key, w, h, x_skip);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (
|
||||
((x + w - 1) < 0) || // Outside left
|
||||
((y + h - 1) < 0) || // Outside top
|
||||
(x > _max_x) || // Outside right
|
||||
(y > _max_y) // Outside bottom
|
||||
)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((y + h - 1) > _max_y)
|
||||
{
|
||||
h -= (y + h - 1) - _max_y;
|
||||
}
|
||||
if (y < 0)
|
||||
{
|
||||
bitmap -= y * (w + x_skip);
|
||||
h += y;
|
||||
y = 0;
|
||||
}
|
||||
if ((x + w - 1) > _max_x)
|
||||
{
|
||||
x_skip += (x + w - 1) - _max_x;
|
||||
w -= (x + w - 1) - _max_x;
|
||||
}
|
||||
if (x < 0)
|
||||
{
|
||||
bitmap -= x;
|
||||
x_skip -= x;
|
||||
w += x;
|
||||
x = 0;
|
||||
}
|
||||
uint16_t *row = _framebuffer;
|
||||
row += y * _width;
|
||||
row += x;
|
||||
int16_t i;
|
||||
int16_t wi;
|
||||
uint8_t color_key;
|
||||
while (h--)
|
||||
{
|
||||
i = 0;
|
||||
wi = w;
|
||||
while (wi >= 4)
|
||||
{
|
||||
uint32_t b32 = *((uint32_t *)bitmap);
|
||||
color_key = (b32 & 0xff);
|
||||
if (color_key != chroma_key)
|
||||
{
|
||||
row[i] = color_index[color_key];
|
||||
}
|
||||
++i;
|
||||
color_key = (b32 & 0xff00) >> 8;
|
||||
if (color_key != chroma_key)
|
||||
{
|
||||
row[i] = color_index[color_key];
|
||||
}
|
||||
++i;
|
||||
color_key = (b32 & 0xff0000) >> 16;
|
||||
if (color_key != chroma_key)
|
||||
{
|
||||
row[i] = color_index[color_key];
|
||||
}
|
||||
++i;
|
||||
color_key = (b32 & 0xff000000) >> 24;
|
||||
if (color_key != chroma_key)
|
||||
{
|
||||
row[i] = color_index[color_key];
|
||||
}
|
||||
++i;
|
||||
wi -= 4;
|
||||
bitmap += 4;
|
||||
}
|
||||
while (i < w)
|
||||
{
|
||||
color_key = *bitmap++;
|
||||
if (color_key != chroma_key)
|
||||
{
|
||||
row[i] = color_index[color_key];
|
||||
}
|
||||
++i;
|
||||
}
|
||||
bitmap += x_skip;
|
||||
row += _width;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_Canvas::draw16bitRGBBitmap(int16_t x, int16_t y,
|
||||
uint16_t *bitmap, int16_t w, int16_t h)
|
||||
{
|
||||
switch (_rotation)
|
||||
{
|
||||
case 1:
|
||||
gfx_draw_bitmap_to_framebuffer_rotate_1(bitmap, w, h, _framebuffer, x, y, _width, _height);
|
||||
break;
|
||||
case 2:
|
||||
gfx_draw_bitmap_to_framebuffer_rotate_2(bitmap, w, h, _framebuffer, x, y, _width, _height);
|
||||
break;
|
||||
case 3:
|
||||
gfx_draw_bitmap_to_framebuffer_rotate_3(bitmap, w, h, _framebuffer, x, y, _width, _height);
|
||||
break;
|
||||
default: // case 0:
|
||||
gfx_draw_bitmap_to_framebuffer(bitmap, w, h, _framebuffer, x, y, _width, _height);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_Canvas::draw16bitRGBBitmapWithTranColor(
|
||||
int16_t x, int16_t y,
|
||||
uint16_t *bitmap, uint16_t transparent_color, int16_t w, int16_t h)
|
||||
{
|
||||
if (_rotation > 0)
|
||||
{
|
||||
Arduino_GFX::draw16bitRGBBitmapWithTranColor(x, y, bitmap, transparent_color, w, h);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (
|
||||
((x + w - 1) < 0) || // Outside left
|
||||
((y + h - 1) < 0) || // Outside top
|
||||
(x > _max_x) || // Outside right
|
||||
(y > _max_y) // Outside bottom
|
||||
)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
int16_t x_skip = 0;
|
||||
if ((y + h - 1) > _max_y)
|
||||
{
|
||||
h -= (y + h - 1) - _max_y;
|
||||
}
|
||||
if (y < 0)
|
||||
{
|
||||
bitmap -= y * w;
|
||||
h += y;
|
||||
y = 0;
|
||||
}
|
||||
if ((x + w - 1) > _max_x)
|
||||
{
|
||||
x_skip = (x + w - 1) - _max_x;
|
||||
w -= x_skip;
|
||||
}
|
||||
if (x < 0)
|
||||
{
|
||||
bitmap -= x;
|
||||
x_skip -= x;
|
||||
w += x;
|
||||
x = 0;
|
||||
}
|
||||
uint16_t *row = _framebuffer;
|
||||
row += y * _width;
|
||||
row += x;
|
||||
int16_t i;
|
||||
int16_t wi;
|
||||
uint16_t p;
|
||||
while (h--)
|
||||
{
|
||||
i = 0;
|
||||
wi = w;
|
||||
while (wi >= 4)
|
||||
{
|
||||
uint32_t b32 = *((uint32_t *)bitmap);
|
||||
p = (b32 & 0xffff);
|
||||
if (p != transparent_color)
|
||||
{
|
||||
row[i] = p;
|
||||
}
|
||||
++i;
|
||||
p = (b32 & 0xffff0000) >> 16;
|
||||
if (p != transparent_color)
|
||||
{
|
||||
row[i] = p;
|
||||
}
|
||||
++i;
|
||||
wi -= 2;
|
||||
bitmap += 2;
|
||||
}
|
||||
while (i < w)
|
||||
{
|
||||
p = *bitmap++;
|
||||
if (p != transparent_color)
|
||||
{
|
||||
row[i] = p;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
bitmap += x_skip;
|
||||
row += _width;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_Canvas::draw16bitBeRGBBitmap(int16_t x, int16_t y,
|
||||
uint16_t *bitmap, int16_t w, int16_t h)
|
||||
{
|
||||
if (_rotation > 0)
|
||||
{
|
||||
Arduino_GFX::draw16bitBeRGBBitmap(x, y, bitmap, w, h);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (
|
||||
((x + w - 1) < 0) || // Outside left
|
||||
((y + h - 1) < 0) || // Outside top
|
||||
(x > _max_x) || // Outside right
|
||||
(y > _max_y) // Outside bottom
|
||||
)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
int16_t x_skip = 0;
|
||||
if ((y + h - 1) > _max_y)
|
||||
{
|
||||
h -= (y + h - 1) - _max_y;
|
||||
}
|
||||
if (y < 0)
|
||||
{
|
||||
bitmap -= y * w;
|
||||
h += y;
|
||||
y = 0;
|
||||
}
|
||||
if ((x + w - 1) > _max_x)
|
||||
{
|
||||
x_skip = (x + w - 1) - _max_x;
|
||||
w -= x_skip;
|
||||
}
|
||||
if (x < 0)
|
||||
{
|
||||
bitmap -= x;
|
||||
x_skip -= x;
|
||||
w += x;
|
||||
x = 0;
|
||||
}
|
||||
uint16_t *row = _framebuffer;
|
||||
row += y * _width;
|
||||
row += x;
|
||||
uint16_t color;
|
||||
for (int j = 0; j < h; j++)
|
||||
{
|
||||
for (int i = 0; i < w; i++)
|
||||
{
|
||||
color = *bitmap++;
|
||||
MSB_16_SET(row[i], color);
|
||||
}
|
||||
bitmap += x_skip;
|
||||
row += _width;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_Canvas::flush(bool force_flush)
|
||||
{
|
||||
if (_output)
|
||||
{
|
||||
_output->draw16bitRGBBitmap(_output_x, _output_y, _framebuffer, WIDTH, HEIGHT);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_Canvas::flushQuad(bool force_flush)
|
||||
{
|
||||
int16_t y = _output_y;
|
||||
uint16_t *row1 = _framebuffer;
|
||||
uint16_t *row2 = _framebuffer + WIDTH;
|
||||
if (_output)
|
||||
{
|
||||
int16_t hQuad = HEIGHT / 2;
|
||||
int16_t wQuad = WIDTH / 2;
|
||||
if (!_rowBuf)
|
||||
{
|
||||
_rowBuf = (uint16_t *)malloc(wQuad * 2);
|
||||
}
|
||||
uint16_t p;
|
||||
while (hQuad--)
|
||||
{
|
||||
for (int16_t i = 0; i < wQuad; ++i)
|
||||
{
|
||||
p = (*row1++ & 0b1110011110011100) >> 2;
|
||||
p += (*row1++ & 0b1110011110011100) >> 2;
|
||||
p += (*row2++ & 0b1110011110011100) >> 2;
|
||||
p += (*row2++ & 0b1110011110011100) >> 2;
|
||||
_rowBuf[i] = p;
|
||||
}
|
||||
_output->draw16bitRGBBitmap(_output_x, _output_y + y++, _rowBuf, wQuad, 1);
|
||||
row1 += WIDTH;
|
||||
row2 += WIDTH;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t *Arduino_Canvas::getFramebuffer()
|
||||
{
|
||||
return _framebuffer;
|
||||
}
|
||||
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
@@ -0,0 +1,46 @@
|
||||
#include "../Arduino_DataBus.h"
|
||||
#if !defined(LITTLE_FOOT_PRINT)
|
||||
|
||||
#ifndef _ARDUINO_CANVAS_H_
|
||||
#define _ARDUINO_CANVAS_H_
|
||||
|
||||
#include "../Arduino_GFX.h"
|
||||
|
||||
class Arduino_Canvas : public Arduino_GFX
|
||||
{
|
||||
public:
|
||||
Arduino_Canvas(int16_t w, int16_t h, Arduino_G *output, int16_t output_x = 0, int16_t output_y = 0, uint8_t rotation = 0);
|
||||
~Arduino_Canvas();
|
||||
|
||||
bool begin(int32_t speed = GFX_NOT_DEFINED) override;
|
||||
void writePixelPreclipped(int16_t x, int16_t y, uint16_t color) override;
|
||||
void writeFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) override;
|
||||
void writeFastVLineCore(int16_t x, int16_t y, int16_t h, uint16_t color);
|
||||
void writeFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color) override;
|
||||
void writeFastHLineCore(int16_t x, int16_t y, int16_t w, uint16_t color);
|
||||
void writeFillRectPreclipped(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) override;
|
||||
void drawIndexedBitmap(int16_t x, int16_t y, uint8_t *bitmap, uint16_t *color_index, int16_t w, int16_t h, int16_t x_skip = 0) override;
|
||||
void drawIndexedBitmap(int16_t x, int16_t y, uint8_t *bitmap, uint16_t *color_index, uint8_t chroma_key, int16_t w, int16_t h, int16_t x_skip = 0) override;
|
||||
void draw16bitRGBBitmap(int16_t x, int16_t y, uint16_t *bitmap, int16_t w, int16_t h) override;
|
||||
void draw16bitRGBBitmapWithTranColor(int16_t x, int16_t y, uint16_t *bitmap, uint16_t transparent_color, int16_t w, int16_t h) override;
|
||||
void draw16bitBeRGBBitmap(int16_t x, int16_t y, uint16_t *bitmap, int16_t w, int16_t h) override;
|
||||
void flush(bool force_flush = false) override;
|
||||
void flushQuad(bool force_flush = false);
|
||||
|
||||
uint16_t *getFramebuffer();
|
||||
|
||||
protected:
|
||||
uint16_t *_framebuffer = nullptr;
|
||||
Arduino_G *_output = nullptr;
|
||||
int16_t _output_x, _output_y;
|
||||
int16_t MAX_X, MAX_Y;
|
||||
|
||||
// for flushQuad() only
|
||||
uint16_t *_rowBuf = nullptr;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
#endif // _ARDUINO_CANVAS_H_
|
||||
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
@@ -0,0 +1,84 @@
|
||||
#include "../Arduino_DataBus.h"
|
||||
#if !defined(LITTLE_FOOT_PRINT)
|
||||
|
||||
#include "../Arduino_GFX.h"
|
||||
#include "Arduino_Canvas_3bit.h"
|
||||
|
||||
Arduino_Canvas_3bit::Arduino_Canvas_3bit(int16_t w, int16_t h, Arduino_G *output, int16_t output_x, int16_t output_y)
|
||||
: Arduino_GFX(w, h), _output(output), _output_x(output_x), _output_y(output_y)
|
||||
{
|
||||
}
|
||||
|
||||
Arduino_Canvas_3bit::~Arduino_Canvas_3bit()
|
||||
{
|
||||
if (_framebuffer)
|
||||
{
|
||||
free(_framebuffer);
|
||||
}
|
||||
}
|
||||
|
||||
bool Arduino_Canvas_3bit::begin(int32_t speed)
|
||||
{
|
||||
if (speed != GFX_SKIP_OUTPUT_BEGIN)
|
||||
{
|
||||
if (!_output->begin(speed))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_framebuffer)
|
||||
{
|
||||
size_t s = (_width * _height + 1) / 2;
|
||||
#if defined(ESP32)
|
||||
if (psramFound())
|
||||
{
|
||||
_framebuffer = (uint8_t *)ps_malloc(s);
|
||||
}
|
||||
else
|
||||
{
|
||||
_framebuffer = (uint8_t *)malloc(s);
|
||||
}
|
||||
#else
|
||||
_framebuffer = (uint8_t *)malloc(s);
|
||||
#endif
|
||||
if (!_framebuffer)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Arduino_Canvas_3bit::writePixelPreclipped(int16_t x, int16_t y, uint16_t color)
|
||||
{
|
||||
int32_t pos = x + (y * _width);
|
||||
int32_t idx = pos >> 1;
|
||||
uint8_t c = (((color & 0b1000000000000000) ? 0b100 : 0) |
|
||||
((color & 0b0000010000000000) ? 0b010 : 0) |
|
||||
((color & 0b0000000000010000) ? 0b001 : 0));
|
||||
if (pos & 1)
|
||||
{
|
||||
_framebuffer[idx] = (_framebuffer[idx] & 0b00111000) | c;
|
||||
}
|
||||
else
|
||||
{
|
||||
_framebuffer[idx] = (_framebuffer[idx] & 0b00000111) | (c << 3);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_Canvas_3bit::flush(bool force_flush)
|
||||
{
|
||||
if (_output)
|
||||
{
|
||||
_output->draw3bitRGBBitmap(_output_x, _output_y, _framebuffer, _width, _height);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t *Arduino_Canvas_3bit::getFramebuffer()
|
||||
{
|
||||
return _framebuffer;
|
||||
}
|
||||
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
@@ -0,0 +1,31 @@
|
||||
#include "../Arduino_DataBus.h"
|
||||
#if !defined(LITTLE_FOOT_PRINT)
|
||||
|
||||
#ifndef _ARDUINO_CANVAS_3BIT_H_
|
||||
#define _ARDUINO_CANVAS_3BIT_H_
|
||||
|
||||
#include "../Arduino_GFX.h"
|
||||
|
||||
class Arduino_Canvas_3bit : public Arduino_GFX
|
||||
{
|
||||
public:
|
||||
Arduino_Canvas_3bit(int16_t w, int16_t h, Arduino_G *output, int16_t output_x = 0, int16_t output_y = 0);
|
||||
~Arduino_Canvas_3bit();
|
||||
|
||||
bool begin(int32_t speed = GFX_NOT_DEFINED) override;
|
||||
void writePixelPreclipped(int16_t x, int16_t y, uint16_t color) override;
|
||||
void flush(bool force_flush = false) override;
|
||||
|
||||
uint8_t *getFramebuffer();
|
||||
|
||||
protected:
|
||||
uint8_t *_framebuffer = nullptr;
|
||||
Arduino_G *_output = nullptr;
|
||||
int16_t _output_x, _output_y;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
#endif // _ARDUINO_CANVAS_3BIT_H_
|
||||
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
@@ -0,0 +1,564 @@
|
||||
#include "../Arduino_DataBus.h"
|
||||
#if !defined(LITTLE_FOOT_PRINT)
|
||||
|
||||
#include "../Arduino_GFX.h"
|
||||
#include "Arduino_Canvas_Indexed.h"
|
||||
|
||||
Arduino_Canvas_Indexed::Arduino_Canvas_Indexed(int16_t w, int16_t h, Arduino_G *output, int16_t output_x, int16_t output_y, uint8_t r, uint8_t mask_level)
|
||||
: Arduino_GFX(w, h), _output(output), _output_x(output_x), _output_y(output_y)
|
||||
{
|
||||
MAX_X = WIDTH - 1;
|
||||
MAX_Y = HEIGHT - 1;
|
||||
setRotation(r);
|
||||
|
||||
if (mask_level >= MAXMASKLEVEL)
|
||||
{
|
||||
mask_level = MAXMASKLEVEL - 1;
|
||||
}
|
||||
_current_mask_level = mask_level;
|
||||
_color_mask = mask_level_list[_current_mask_level];
|
||||
}
|
||||
|
||||
Arduino_Canvas_Indexed::~Arduino_Canvas_Indexed()
|
||||
{
|
||||
if (_framebuffer)
|
||||
{
|
||||
free(_framebuffer);
|
||||
}
|
||||
}
|
||||
|
||||
bool Arduino_Canvas_Indexed::begin(int32_t speed)
|
||||
{
|
||||
if (speed != GFX_SKIP_OUTPUT_BEGIN)
|
||||
{
|
||||
if (!_output->begin(speed))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_framebuffer)
|
||||
{
|
||||
size_t s = _width * _height;
|
||||
#if defined(ESP32)
|
||||
if (psramFound())
|
||||
{
|
||||
_framebuffer = (uint8_t *)ps_malloc(s);
|
||||
}
|
||||
else
|
||||
{
|
||||
_framebuffer = (uint8_t *)malloc(s);
|
||||
}
|
||||
#else
|
||||
_framebuffer = (uint8_t *)malloc(s);
|
||||
#endif
|
||||
if (!_framebuffer)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Arduino_Canvas_Indexed::writePixelPreclipped(int16_t x, int16_t y, uint16_t color)
|
||||
{
|
||||
uint8_t idx;
|
||||
if (_isDirectUseColorIndex)
|
||||
{
|
||||
idx = (uint8_t)color;
|
||||
}
|
||||
else
|
||||
{
|
||||
idx = get_color_index(color);
|
||||
}
|
||||
|
||||
uint8_t *fb = _framebuffer;
|
||||
switch (_rotation)
|
||||
{
|
||||
case 1:
|
||||
fb += (int32_t)x * _height;
|
||||
fb += _max_y - y;
|
||||
*fb = idx;
|
||||
break;
|
||||
case 2:
|
||||
fb += (int32_t)(_max_y - y) * _width;
|
||||
fb += _max_x - x;
|
||||
*fb = idx;
|
||||
break;
|
||||
case 3:
|
||||
fb += (int32_t)(_max_x - x) * _height;
|
||||
fb += y;
|
||||
*fb = idx;
|
||||
break;
|
||||
default: // case 0:
|
||||
fb += (int32_t)y * _width;
|
||||
fb += x;
|
||||
*fb = idx;
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_Canvas_Indexed::writeFastVLine(int16_t x, int16_t y,
|
||||
int16_t h, uint16_t color)
|
||||
{
|
||||
uint8_t idx;
|
||||
if (_isDirectUseColorIndex)
|
||||
{
|
||||
idx = (uint8_t)color;
|
||||
}
|
||||
else
|
||||
{
|
||||
idx = get_color_index(color);
|
||||
}
|
||||
|
||||
switch (_rotation)
|
||||
{
|
||||
case 1:
|
||||
writeFastHLineCore(_height - y - h, x, h, idx);
|
||||
break;
|
||||
case 2:
|
||||
writeFastVLineCore(_max_x - x, _height - y - h, h, idx);
|
||||
break;
|
||||
case 3:
|
||||
writeFastHLineCore(y, _max_x - x, h, idx);
|
||||
break;
|
||||
default: // case 0:
|
||||
writeFastVLineCore(x, y, h, idx);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_Canvas_Indexed::writeFastVLineCore(int16_t x, int16_t y,
|
||||
int16_t h, uint8_t idx)
|
||||
{
|
||||
if (_ordered_in_range(x, 0, MAX_X) && h)
|
||||
{ // X on screen, nonzero height
|
||||
if (h < 0)
|
||||
{ // If negative height...
|
||||
y += h + 1; // Move Y to top edge
|
||||
h = -h; // Use positive height
|
||||
}
|
||||
if (y <= MAX_Y)
|
||||
{ // Not off bottom
|
||||
int16_t y2 = y + h - 1;
|
||||
if (y2 >= 0)
|
||||
{ // Not off top
|
||||
// Line partly or fully overlaps screen
|
||||
if (y < 0)
|
||||
{
|
||||
y = 0;
|
||||
h = y2 + 1;
|
||||
} // Clip top
|
||||
if (y2 > MAX_Y)
|
||||
{
|
||||
h = MAX_Y - y + 1;
|
||||
} // Clip bottom
|
||||
|
||||
uint8_t *fb = _framebuffer + ((int32_t)y * WIDTH) + x;
|
||||
while (h--)
|
||||
{
|
||||
*fb = idx;
|
||||
fb += WIDTH;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_Canvas_Indexed::writeFastHLine(int16_t x, int16_t y,
|
||||
int16_t w, uint16_t color)
|
||||
{
|
||||
uint8_t idx;
|
||||
if (_isDirectUseColorIndex)
|
||||
{
|
||||
idx = (uint8_t)color;
|
||||
}
|
||||
else
|
||||
{
|
||||
idx = get_color_index(color);
|
||||
}
|
||||
|
||||
switch (_rotation)
|
||||
{
|
||||
case 1:
|
||||
writeFastVLineCore(_max_y - y, x, w, idx);
|
||||
break;
|
||||
case 2:
|
||||
writeFastHLineCore(_width - x - w, _max_y - y, w, idx);
|
||||
break;
|
||||
case 3:
|
||||
writeFastVLineCore(y, _width - x - w, w, idx);
|
||||
break;
|
||||
default: // case 0:
|
||||
writeFastHLineCore(x, y, w, idx);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_Canvas_Indexed::writeFastHLineCore(int16_t x, int16_t y,
|
||||
int16_t w, uint8_t idx)
|
||||
{
|
||||
if (_ordered_in_range(y, 0, MAX_Y) && w)
|
||||
{ // Y on screen, nonzero width
|
||||
if (w < 0)
|
||||
{ // If negative width...
|
||||
x += w + 1; // Move X to left edge
|
||||
w = -w; // Use positive width
|
||||
}
|
||||
if (x <= MAX_X)
|
||||
{ // Not off right
|
||||
int16_t x2 = x + w - 1;
|
||||
if (x2 >= 0)
|
||||
{ // Not off left
|
||||
// Line partly or fully overlaps screen
|
||||
if (x < 0)
|
||||
{
|
||||
x = 0;
|
||||
w = x2 + 1;
|
||||
} // Clip left
|
||||
if (x2 > MAX_X)
|
||||
{
|
||||
w = MAX_X - x + 1;
|
||||
} // Clip right
|
||||
|
||||
uint8_t *fb = _framebuffer + ((int32_t)y * WIDTH) + x;
|
||||
while (w--)
|
||||
{
|
||||
*(fb++) = idx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_Canvas_Indexed::writeFillRectPreclipped(int16_t x, int16_t y,
|
||||
int16_t w, int16_t h, uint16_t color)
|
||||
{
|
||||
uint8_t idx;
|
||||
if (_isDirectUseColorIndex)
|
||||
{
|
||||
idx = (uint8_t)color;
|
||||
}
|
||||
else
|
||||
{
|
||||
idx = get_color_index(color);
|
||||
}
|
||||
|
||||
if (_rotation > 0)
|
||||
{
|
||||
int16_t t = x;
|
||||
switch (_rotation)
|
||||
{
|
||||
case 1:
|
||||
x = WIDTH - y - h;
|
||||
y = t;
|
||||
t = w;
|
||||
w = h;
|
||||
h = t;
|
||||
break;
|
||||
case 2:
|
||||
x = WIDTH - x - w;
|
||||
y = HEIGHT - y - h;
|
||||
break;
|
||||
case 3:
|
||||
x = y;
|
||||
y = HEIGHT - t - w;
|
||||
t = w;
|
||||
w = h;
|
||||
h = t;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// log_i("adjusted writeFillRectPreclipped(x: %d, y: %d, w: %d, h: %d)", x, y, w, h);
|
||||
uint8_t *row = _framebuffer;
|
||||
row += y * WIDTH;
|
||||
row += x;
|
||||
for (int j = 0; j < h; j++)
|
||||
{
|
||||
for (int i = 0; i < w; i++)
|
||||
{
|
||||
row[i] = idx;
|
||||
}
|
||||
row += WIDTH;
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_Canvas_Indexed::drawIndexedBitmap(
|
||||
int16_t x, int16_t y,
|
||||
uint8_t *bitmap, uint16_t *color_index, int16_t w, int16_t h, int16_t x_skip)
|
||||
{
|
||||
if (_rotation > 0)
|
||||
{
|
||||
if (!_isDirectUseColorIndex)
|
||||
{
|
||||
Arduino_GFX::drawIndexedBitmap(x, y, bitmap, color_index, w, h, x_skip);
|
||||
}
|
||||
else
|
||||
{
|
||||
int32_t offset = 0;
|
||||
for (int16_t j = 0; j < h; j++, y++)
|
||||
{
|
||||
for (int16_t i = 0; i < w; i++)
|
||||
{
|
||||
writePixel(x + i, y, bitmap[offset++]);
|
||||
}
|
||||
offset += x_skip;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (
|
||||
((x + w - 1) < 0) || // Outside left
|
||||
((y + h - 1) < 0) || // Outside top
|
||||
(x > _max_x) || // Outside right
|
||||
(y > _max_y) // Outside bottom
|
||||
)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((y + h - 1) > _max_y)
|
||||
{
|
||||
h -= (y + h - 1) - _max_y;
|
||||
}
|
||||
if (y < 0)
|
||||
{
|
||||
bitmap -= y * (w + x_skip);
|
||||
h += y;
|
||||
y = 0;
|
||||
}
|
||||
if ((x + w - 1) > _max_x)
|
||||
{
|
||||
x_skip += (x + w - 1) - _max_x;
|
||||
w -= (x + w - 1) - _max_x;
|
||||
}
|
||||
if (x < 0)
|
||||
{
|
||||
bitmap -= x;
|
||||
x_skip -= x;
|
||||
w += x;
|
||||
x = 0;
|
||||
}
|
||||
uint8_t *row = _framebuffer;
|
||||
row += y * _width;
|
||||
row += x;
|
||||
int16_t i;
|
||||
int16_t wi;
|
||||
if (_isDirectUseColorIndex)
|
||||
{
|
||||
while (h--)
|
||||
{
|
||||
i = 0;
|
||||
wi = w;
|
||||
while (wi >= 4)
|
||||
{
|
||||
*((uint32_t *)&row[i]) = *((uint32_t *)bitmap);
|
||||
i += 4;
|
||||
wi -= 4;
|
||||
bitmap += 4;
|
||||
}
|
||||
while (i < w)
|
||||
{
|
||||
row[i++] = *bitmap++;
|
||||
}
|
||||
bitmap += x_skip;
|
||||
row += _width;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (h--)
|
||||
{
|
||||
for (int i = 0; i < w; i++)
|
||||
{
|
||||
row[i] = get_color_index(color_index[*bitmap++]);
|
||||
}
|
||||
bitmap += x_skip;
|
||||
row += _width;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_Canvas_Indexed::drawIndexedBitmap(
|
||||
int16_t x, int16_t y,
|
||||
uint8_t *bitmap, uint16_t *color_index, uint8_t chroma_key, int16_t w, int16_t h, int16_t x_skip)
|
||||
{
|
||||
if (_rotation > 0)
|
||||
{
|
||||
if (!_isDirectUseColorIndex)
|
||||
{
|
||||
Arduino_GFX::drawIndexedBitmap(x, y, bitmap, color_index, chroma_key, w, h, x_skip);
|
||||
}
|
||||
else
|
||||
{
|
||||
int32_t offset = 0;
|
||||
uint8_t color_key;
|
||||
for (int16_t j = 0; j < h; j++, y++)
|
||||
{
|
||||
for (int16_t i = 0; i < w; i++)
|
||||
{
|
||||
color_key = bitmap[offset++];
|
||||
if (color_key != chroma_key)
|
||||
{
|
||||
writePixel(x + i, y, color_key);
|
||||
}
|
||||
}
|
||||
offset += x_skip;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (
|
||||
((x + w - 1) < 0) || // Outside left
|
||||
((y + h - 1) < 0) || // Outside top
|
||||
(x > _max_x) || // Outside right
|
||||
(y > _max_y) // Outside bottom
|
||||
)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((y + h - 1) > _max_y)
|
||||
{
|
||||
h -= (y + h - 1) - _max_y;
|
||||
}
|
||||
if (y < 0)
|
||||
{
|
||||
bitmap -= y * (w + x_skip);
|
||||
h += y;
|
||||
y = 0;
|
||||
}
|
||||
if ((x + w - 1) > _max_x)
|
||||
{
|
||||
x_skip += (x + w - 1) - _max_x;
|
||||
w -= (x + w - 1) - _max_x;
|
||||
}
|
||||
if (x < 0)
|
||||
{
|
||||
bitmap -= x;
|
||||
x_skip -= x;
|
||||
w += x;
|
||||
x = 0;
|
||||
}
|
||||
uint8_t *row = _framebuffer;
|
||||
row += y * _width;
|
||||
row += x;
|
||||
uint8_t color_key;
|
||||
if (_isDirectUseColorIndex)
|
||||
{
|
||||
while (h--)
|
||||
{
|
||||
for (int i = 0; i < w; i++)
|
||||
{
|
||||
color_key = *bitmap++;
|
||||
if (color_key != chroma_key)
|
||||
{
|
||||
row[i] = color_key;
|
||||
}
|
||||
}
|
||||
bitmap += x_skip;
|
||||
row += _width;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (h--)
|
||||
{
|
||||
for (int i = 0; i < w; i++)
|
||||
{
|
||||
color_key = *bitmap++;
|
||||
if (color_key != chroma_key)
|
||||
{
|
||||
row[i] = get_color_index(color_index[color_key]);
|
||||
}
|
||||
}
|
||||
bitmap += x_skip;
|
||||
row += _width;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_Canvas_Indexed::flush(bool force_flush)
|
||||
{
|
||||
if (_output)
|
||||
{
|
||||
_output->drawIndexedBitmap(_output_x, _output_y, _framebuffer, _color_index, WIDTH, HEIGHT);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t *Arduino_Canvas_Indexed::getFramebuffer()
|
||||
{
|
||||
return _framebuffer;
|
||||
}
|
||||
|
||||
uint16_t *Arduino_Canvas_Indexed::getColorIndex()
|
||||
{
|
||||
return _color_index;
|
||||
}
|
||||
|
||||
void Arduino_Canvas_Indexed::setDirectUseColorIndex(bool isEnable)
|
||||
{
|
||||
_isDirectUseColorIndex = isEnable;
|
||||
}
|
||||
|
||||
uint8_t Arduino_Canvas_Indexed::get_color_index(uint16_t color)
|
||||
{
|
||||
color &= _color_mask;
|
||||
for (uint8_t i = 0; i < _indexed_size; i++)
|
||||
{
|
||||
if (_color_index[i] == color)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
if (_indexed_size == (COLOR_IDX_SIZE - 1)) // overflowed
|
||||
{
|
||||
raise_mask_level();
|
||||
}
|
||||
_color_index[_indexed_size] = color;
|
||||
// print("color_index[");
|
||||
// print(_indexed_size);
|
||||
// print("] = ");
|
||||
// println(color);
|
||||
return _indexed_size++;
|
||||
}
|
||||
|
||||
GFX_INLINE uint16_t Arduino_Canvas_Indexed::get_index_color(uint8_t idx)
|
||||
{
|
||||
return _color_index[idx];
|
||||
}
|
||||
|
||||
void Arduino_Canvas_Indexed::raise_mask_level()
|
||||
{
|
||||
if ((_current_mask_level + 1) < MAXMASKLEVEL)
|
||||
{
|
||||
int32_t buffer_size = _width * _height;
|
||||
uint8_t old_indexed_size = _indexed_size;
|
||||
uint8_t new_color;
|
||||
_indexed_size = 0;
|
||||
_color_mask = mask_level_list[++_current_mask_level];
|
||||
// print("Raised mask level: ");
|
||||
// println(_current_mask_level);
|
||||
|
||||
// update _framebuffer color index, it is a time consuming job
|
||||
for (uint8_t old_color = 0; old_color < old_indexed_size; old_color++)
|
||||
{
|
||||
new_color = get_color_index(_color_index[old_color]);
|
||||
for (int32_t i = 0; i < buffer_size; i++)
|
||||
{
|
||||
if (_framebuffer[i] == old_color)
|
||||
{
|
||||
_framebuffer[i] = new_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
@@ -0,0 +1,60 @@
|
||||
#include "../Arduino_DataBus.h"
|
||||
#if !defined(LITTLE_FOOT_PRINT)
|
||||
|
||||
#ifndef _ARDUINO_CANVAS_INDEXED_H_
|
||||
#define _ARDUINO_CANVAS_INDEXED_H_
|
||||
|
||||
#include "../Arduino_GFX.h"
|
||||
|
||||
#define COLOR_IDX_SIZE 256
|
||||
|
||||
class Arduino_Canvas_Indexed : public Arduino_GFX
|
||||
{
|
||||
public:
|
||||
Arduino_Canvas_Indexed(int16_t w, int16_t h, Arduino_G *output, int16_t output_x = 0, int16_t output_y = 0, uint8_t rotation = 0, uint8_t mask_level = 0);
|
||||
~Arduino_Canvas_Indexed();
|
||||
|
||||
bool begin(int32_t speed = GFX_NOT_DEFINED) override;
|
||||
void writePixelPreclipped(int16_t x, int16_t y, uint16_t color) override;
|
||||
void writeFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) override;
|
||||
void writeFastVLineCore(int16_t x, int16_t y, int16_t h, uint8_t idx);
|
||||
void writeFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color) override;
|
||||
void writeFastHLineCore(int16_t x, int16_t y, int16_t w, uint8_t idx);
|
||||
void writeFillRectPreclipped(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) override;
|
||||
void drawIndexedBitmap(int16_t x, int16_t y, uint8_t *bitmap, uint16_t *color_index, int16_t w, int16_t h, int16_t x_skip = 0) override;
|
||||
void drawIndexedBitmap(int16_t x, int16_t y, uint8_t *bitmap, uint16_t *color_index, uint8_t chroma_key, int16_t w, int16_t h, int16_t x_skip = 0) override;
|
||||
void flush(bool force_flush = false) override;
|
||||
|
||||
uint8_t *getFramebuffer();
|
||||
uint16_t *getColorIndex();
|
||||
void setDirectUseColorIndex(bool isEnable);
|
||||
|
||||
uint8_t get_color_index(uint16_t color);
|
||||
uint16_t get_index_color(uint8_t idx);
|
||||
void raise_mask_level();
|
||||
|
||||
protected:
|
||||
uint8_t *_framebuffer = nullptr;
|
||||
Arduino_G *_output = nullptr;
|
||||
int16_t _output_x, _output_y;
|
||||
int16_t MAX_X, MAX_Y;
|
||||
|
||||
uint16_t _color_index[COLOR_IDX_SIZE];
|
||||
uint8_t _indexed_size = 0;
|
||||
bool _isDirectUseColorIndex = false;
|
||||
|
||||
uint8_t _current_mask_level;
|
||||
uint16_t _color_mask;
|
||||
#define MAXMASKLEVEL 3
|
||||
uint16_t mask_level_list[MAXMASKLEVEL] = {
|
||||
0b1111111111111111, // 16-bit, 65536 colors
|
||||
0b1111011110011110, // 12-bit, 4096 colors
|
||||
0b1100011100011000 // 7-bit, 128 colors
|
||||
};
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
#endif // _ARDUINO_CANVAS_INDEXED_H_
|
||||
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
@@ -0,0 +1,116 @@
|
||||
#include "../Arduino_DataBus.h"
|
||||
#if !defined(LITTLE_FOOT_PRINT)
|
||||
|
||||
#include "../Arduino_GFX.h"
|
||||
#include "Arduino_Canvas_Mono.h"
|
||||
|
||||
Arduino_Canvas_Mono::Arduino_Canvas_Mono(int16_t w, int16_t h, Arduino_G *output, int16_t output_x, int16_t output_y, bool verticalByte)
|
||||
: Arduino_GFX(w, h), _output(output), _output_x(output_x), _output_y(output_y), _verticalByte(verticalByte),
|
||||
_canvas_width(w), _canvas_height(h)
|
||||
{
|
||||
}
|
||||
|
||||
Arduino_Canvas_Mono::~Arduino_Canvas_Mono()
|
||||
{
|
||||
if (_framebuffer)
|
||||
{
|
||||
free(_framebuffer);
|
||||
}
|
||||
}
|
||||
|
||||
bool Arduino_Canvas_Mono::begin(int32_t speed)
|
||||
{
|
||||
if (speed != GFX_SKIP_OUTPUT_BEGIN)
|
||||
{
|
||||
if (_output)
|
||||
{
|
||||
if (!_output->begin(speed))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!_framebuffer)
|
||||
{
|
||||
size_t s;
|
||||
|
||||
// allocate memory by full bytes.
|
||||
if (_verticalByte)
|
||||
{
|
||||
s = _canvas_width * (_canvas_height + 7) / 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
s = (_canvas_width + 7) / 8 * _canvas_height;
|
||||
}
|
||||
|
||||
#if defined(ESP32)
|
||||
if (psramFound())
|
||||
{
|
||||
_framebuffer = (uint8_t *)ps_malloc(s);
|
||||
}
|
||||
else
|
||||
{
|
||||
_framebuffer = (uint8_t *)malloc(s);
|
||||
}
|
||||
#else
|
||||
_framebuffer = (uint8_t *)malloc(s);
|
||||
#endif
|
||||
if (!_framebuffer)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Arduino_Canvas_Mono::writePixelPreclipped(int16_t x, int16_t y, uint16_t color)
|
||||
{
|
||||
// change the pixel in the original orientation of the bitmap buffer
|
||||
if (_verticalByte)
|
||||
{
|
||||
// vertical buffer layout: 1 byte in the buffer contains 8 vertical pixels
|
||||
int32_t pos = x + (y / 8) * _canvas_width;
|
||||
|
||||
if (color & 0b1000010000010000)
|
||||
{
|
||||
_framebuffer[pos] |= (1 << (y & 7));
|
||||
}
|
||||
else
|
||||
{
|
||||
_framebuffer[pos] &= ~(1 << (y & 7));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// horizontal buffer layout: 1 byte in the buffer contains 8 horizontal pixels
|
||||
int16_t w = (_canvas_width + 7) / 8;
|
||||
int32_t pos = (y * w) + (x / 8);
|
||||
|
||||
if (color & 0b1000010000010000)
|
||||
{
|
||||
_framebuffer[pos] |= 0x80 >> (x & 7);
|
||||
}
|
||||
else
|
||||
{
|
||||
_framebuffer[pos] &= ~(0x80 >> (x & 7));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_Canvas_Mono::flush(bool force_flush)
|
||||
{
|
||||
if (_output)
|
||||
{
|
||||
_output->drawBitmap(_output_x, _output_y, _framebuffer, _canvas_width, _canvas_height, RGB565_WHITE, RGB565_BLACK);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t *Arduino_Canvas_Mono::getFramebuffer()
|
||||
{
|
||||
return _framebuffer;
|
||||
}
|
||||
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
@@ -0,0 +1,33 @@
|
||||
#include "../Arduino_DataBus.h"
|
||||
#if !defined(LITTLE_FOOT_PRINT)
|
||||
|
||||
#ifndef _ARDUINO_CANVAS_MONO_H_
|
||||
#define _ARDUINO_CANVAS_MONO_H_
|
||||
|
||||
#include "../Arduino_GFX.h"
|
||||
|
||||
class Arduino_Canvas_Mono : public Arduino_GFX
|
||||
{
|
||||
public:
|
||||
Arduino_Canvas_Mono(int16_t w, int16_t h, Arduino_G *output, int16_t output_x = 0, int16_t output_y = 0, bool verticalByte = false);
|
||||
~Arduino_Canvas_Mono();
|
||||
|
||||
bool begin(int32_t speed = GFX_NOT_DEFINED) override;
|
||||
void writePixelPreclipped(int16_t x, int16_t y, uint16_t color) override;
|
||||
void flush(bool force_flush = false) override;
|
||||
|
||||
uint8_t *getFramebuffer();
|
||||
|
||||
protected:
|
||||
uint8_t *_framebuffer = nullptr;
|
||||
Arduino_G *_output = nullptr;
|
||||
int16_t _output_x, _output_y;
|
||||
bool _verticalByte;
|
||||
int16_t _canvas_width, _canvas_height; // width and height of canvas buffer
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
#endif // _ARDUINO_CANVAS_MONO_H_
|
||||
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
@@ -0,0 +1,15 @@
|
||||
# About the canvas mono class of the GFX library
|
||||
|
||||
There are some Display Chips on the market that can display a small amount of graphic data but
|
||||
don't offer much functionality on it's own on other than data transfer. Examples are the OLED
|
||||
Displays Chips SSD1306 or SH1106.
|
||||
|
||||
These displays need an in memory copy of the graphics and updating the display is implemented by
|
||||
a bulk data transfer of the internal memory to the display.
|
||||
|
||||
Therefore the Canvas Mono class must be initialized in a way the internal memory fits to the
|
||||
memory inside the graphic driver chip including the width and height of the display memory and
|
||||
the orientation of a byte to either horizontal or vertical.
|
||||
|
||||
Bei changing the orientation of the canvas the graphics elements like lines or characters are positioned on the display memory accordingly. When the rotating in 90 or 270 degrees der width and height of the logical display will be swapped but not the memory organization.
|
||||
|
||||
@@ -0,0 +1,243 @@
|
||||
#ifdef __AVR__
|
||||
|
||||
#include "Arduino_AVRPAR16.h"
|
||||
|
||||
Arduino_AVRPAR16::Arduino_AVRPAR16(int8_t dc, int8_t cs, int8_t wr, int8_t rd, uint8_t portLow, uint8_t portHigh)
|
||||
: _dc(dc), _cs(cs), _wr(wr), _rd(rd), _portLow(portLow), _portHigh(portHigh)
|
||||
{
|
||||
}
|
||||
|
||||
bool Arduino_AVRPAR16::begin(int32_t, int8_t)
|
||||
{
|
||||
pinMode(_dc, OUTPUT);
|
||||
digitalWrite(_dc, HIGH); // Data mode
|
||||
_dcPort = (PORTreg_t)portOutputRegister(digitalPinToPort(_dc));
|
||||
_dcPinMaskSet = digitalPinToBitMask(_dc);
|
||||
_dcPinMaskClr = ~_dcPinMaskSet;
|
||||
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
pinMode(_cs, OUTPUT);
|
||||
digitalWrite(_cs, HIGH); // Disable chip select
|
||||
_csPort = (PORTreg_t)portOutputRegister(digitalPinToPort(_cs));
|
||||
_csPinMaskSet = digitalPinToBitMask(_cs);
|
||||
}
|
||||
_csPinMaskClr = ~_csPinMaskSet;
|
||||
|
||||
pinMode(_wr, OUTPUT);
|
||||
digitalWrite(_wr, HIGH); // Set write strobe high (inactive)
|
||||
_wrPort = (PORTreg_t)portOutputRegister(digitalPinToPort(_wr));
|
||||
_wrPinMaskSet = digitalPinToBitMask(_wr);
|
||||
_wrPinMaskClr = ~_wrPinMaskSet;
|
||||
|
||||
if (_rd != GFX_NOT_DEFINED)
|
||||
{
|
||||
pinMode(_rd, OUTPUT);
|
||||
digitalWrite(_rd, HIGH); // Disable RD
|
||||
}
|
||||
|
||||
*(portModeRegister(_portLow)) = 0xFF;
|
||||
_dataPortLow = portOutputRegister(_portLow);
|
||||
*_dataPortLow = 0xFF;
|
||||
*(portModeRegister(_portHigh)) = 0xFF;
|
||||
_dataPortHigh = portOutputRegister(_portHigh);
|
||||
*_dataPortHigh = 0xFF;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Arduino_AVRPAR16::beginWrite()
|
||||
{
|
||||
DC_HIGH();
|
||||
CS_LOW();
|
||||
}
|
||||
|
||||
void Arduino_AVRPAR16::endWrite()
|
||||
{
|
||||
CS_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_AVRPAR16::writeCommand(uint8_t c)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE16(c);
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_AVRPAR16::writeCommand16(uint16_t c)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE16(c);
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_AVRPAR16::writeCommandBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
while (len--)
|
||||
{
|
||||
WRITE16(*data++);
|
||||
}
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_AVRPAR16::write(uint8_t d)
|
||||
{
|
||||
WRITE16(d);
|
||||
}
|
||||
|
||||
void Arduino_AVRPAR16::write16(uint16_t d)
|
||||
{
|
||||
WRITE16(d);
|
||||
}
|
||||
|
||||
void Arduino_AVRPAR16::writeRepeat(uint16_t p, uint32_t len)
|
||||
{
|
||||
uint8_t wrMaskBase = *_wrPort & _wrPinMaskClr;
|
||||
uint8_t wrMaskSet = wrMaskBase | _wrPinMaskSet;
|
||||
_data16.value = p;
|
||||
*_dataPortLow = _data16.lsb;
|
||||
*_dataPortHigh = _data16.msb;
|
||||
while (len--)
|
||||
{
|
||||
*_wrPort = wrMaskBase;
|
||||
*_wrPort = wrMaskSet;
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_AVRPAR16::writePixels(uint16_t *data, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
WRITE16(*data++);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_AVRPAR16::writeC8D8(uint8_t c, uint8_t d)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE16(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
WRITE16(d);
|
||||
}
|
||||
|
||||
void Arduino_AVRPAR16::writeC8D16(uint8_t c, uint16_t d)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE16(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
WRITE16(d);
|
||||
}
|
||||
|
||||
void Arduino_AVRPAR16::writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE16(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
WRITE16(d1);
|
||||
WRITE16(d2);
|
||||
}
|
||||
|
||||
void Arduino_AVRPAR16::writeC8D16D16Split(uint8_t c, uint16_t d1, uint16_t d2)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
uint8_t wrMaskBase = *_wrPort & _wrPinMaskClr;
|
||||
_data16.value = c;
|
||||
*_dataPortLow = _data16.lsb;
|
||||
*_dataPortHigh = _data16.msb;
|
||||
*_wrPort = wrMaskBase;
|
||||
*_wrPort = wrMaskBase | _wrPinMaskSet;
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
_data16.value = d1;
|
||||
*_dataPortLow = _data16.msb;
|
||||
*_dataPortHigh = 0;
|
||||
*_wrPort = wrMaskBase;
|
||||
*_wrPort = wrMaskBase | _wrPinMaskSet;
|
||||
*_dataPortLow = _data16.lsb;
|
||||
*_dataPortHigh = 0;
|
||||
*_wrPort = wrMaskBase;
|
||||
*_wrPort = wrMaskBase | _wrPinMaskSet;
|
||||
|
||||
_data16.value = d2;
|
||||
*_dataPortLow = _data16.msb;
|
||||
*_dataPortHigh = 0;
|
||||
*_wrPort = wrMaskBase;
|
||||
*_wrPort = wrMaskBase | _wrPinMaskSet;
|
||||
*_dataPortLow = _data16.lsb;
|
||||
*_dataPortHigh = 0;
|
||||
*_wrPort = wrMaskBase;
|
||||
*_wrPort = wrMaskBase | _wrPinMaskSet;
|
||||
}
|
||||
|
||||
void Arduino_AVRPAR16::writeBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
while (len > 1)
|
||||
{
|
||||
_data16.msb = *data++;
|
||||
_data16.lsb = *data++;
|
||||
WRITE16(_data16.value);
|
||||
len -= 2;
|
||||
}
|
||||
if (len)
|
||||
{
|
||||
WRITE16(*data);
|
||||
}
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_AVRPAR16::WRITE16(uint16_t d)
|
||||
{
|
||||
uint8_t wrMaskBase = *_wrPort & _wrPinMaskClr;
|
||||
_data16.value = d;
|
||||
*_dataPortLow = _data16.lsb;
|
||||
*_dataPortHigh = _data16.msb;
|
||||
*_wrPort = wrMaskBase;
|
||||
*_wrPort = wrMaskBase | _wrPinMaskSet;
|
||||
}
|
||||
|
||||
/******** low level bit twiddling **********/
|
||||
|
||||
GFX_INLINE void Arduino_AVRPAR16::DC_HIGH(void)
|
||||
{
|
||||
*_dcPort |= _dcPinMaskSet;
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_AVRPAR16::DC_LOW(void)
|
||||
{
|
||||
*_dcPort &= _dcPinMaskClr;
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_AVRPAR16::CS_HIGH(void)
|
||||
{
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
*_csPort |= _csPinMaskSet;
|
||||
}
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_AVRPAR16::CS_LOW(void)
|
||||
{
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
*_csPort &= _csPinMaskClr;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // #ifdef __AVR__
|
||||
@@ -0,0 +1,61 @@
|
||||
#ifdef __AVR__
|
||||
|
||||
#ifndef _ARDUINO_AVRPAR16_H_
|
||||
#define _ARDUINO_AVRPAR16_H_
|
||||
|
||||
#include "Arduino_DataBus.h"
|
||||
|
||||
class Arduino_AVRPAR16 : public Arduino_DataBus
|
||||
{
|
||||
public:
|
||||
Arduino_AVRPAR16(int8_t dc, int8_t cs, int8_t wr, int8_t rd, uint8_t portLow, uint8_t portHigh); // Constructor
|
||||
|
||||
bool begin(int32_t speed = GFX_NOT_DEFINED, int8_t dataMode = GFX_NOT_DEFINED) override;
|
||||
void beginWrite() override;
|
||||
void endWrite() override;
|
||||
void writeCommand(uint8_t) override;
|
||||
void writeCommand16(uint16_t) override;
|
||||
void writeCommandBytes(uint8_t *data, uint32_t len) override;
|
||||
void write(uint8_t) override;
|
||||
void write16(uint16_t) override;
|
||||
void writeRepeat(uint16_t p, uint32_t len) override;
|
||||
void writePixels(uint16_t *data, uint32_t len) override;
|
||||
|
||||
void writeC8D8(uint8_t c, uint8_t d) override;
|
||||
void writeC8D16(uint8_t c, uint16_t d) override;
|
||||
void writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2) override;
|
||||
void writeC8D16D16Split(uint8_t c, uint16_t d1, uint16_t d2) override;
|
||||
void writeBytes(uint8_t *data, uint32_t len) override;
|
||||
|
||||
protected:
|
||||
private:
|
||||
GFX_INLINE void WRITE16(uint16_t d);
|
||||
GFX_INLINE void WRITEREPEAT(uint16_t p, uint32_t len);
|
||||
GFX_INLINE void DC_HIGH(void);
|
||||
GFX_INLINE void DC_LOW(void);
|
||||
GFX_INLINE void CS_HIGH(void);
|
||||
GFX_INLINE void CS_LOW(void);
|
||||
|
||||
int8_t _dc, _cs, _wr, _rd;
|
||||
uint8_t _portLow;
|
||||
uint8_t _portHigh;
|
||||
|
||||
PORTreg_t _dcPort; ///< PORT register for data/command
|
||||
ARDUINOGFX_PORT_t _dcPinMaskSet; ///< Bitmask for data/command SET (OR)
|
||||
ARDUINOGFX_PORT_t _dcPinMaskClr; ///< Bitmask for data/command CLEAR (AND)
|
||||
|
||||
PORTreg_t _csPort; ///< PORT register for data/command
|
||||
ARDUINOGFX_PORT_t _csPinMaskSet; ///< Bitmask for data/command SET (OR)
|
||||
ARDUINOGFX_PORT_t _csPinMaskClr; ///< Bitmask for data/command CLEAR (AND)
|
||||
|
||||
PORTreg_t _wrPort; ///< PORT register for data/command
|
||||
ARDUINOGFX_PORT_t _wrPinMaskSet; ///< Bitmask for data/command SET (OR)
|
||||
ARDUINOGFX_PORT_t _wrPinMaskClr; ///< Bitmask for data/command CLEAR (AND)
|
||||
|
||||
PORTreg_t _dataPortLow; ///< PORT register for data/command
|
||||
PORTreg_t _dataPortHigh; ///< PORT register for data/command
|
||||
};
|
||||
|
||||
#endif // _ARDUINO_AVRPAR16_H_
|
||||
|
||||
#endif // #ifdef __AVR__
|
||||
@@ -0,0 +1,227 @@
|
||||
#ifdef __AVR__
|
||||
|
||||
#include "Arduino_AVRPAR8.h"
|
||||
|
||||
Arduino_AVRPAR8::Arduino_AVRPAR8(int8_t dc, int8_t cs, int8_t wr, int8_t rd, uint8_t port)
|
||||
: _dc(dc), _cs(cs), _wr(wr), _rd(rd), _port(port)
|
||||
{
|
||||
}
|
||||
|
||||
bool Arduino_AVRPAR8::begin(int32_t, int8_t)
|
||||
{
|
||||
pinMode(_dc, OUTPUT);
|
||||
digitalWrite(_dc, HIGH); // Data mode
|
||||
_dcPort = (PORTreg_t)portOutputRegister(digitalPinToPort(_dc));
|
||||
_dcPinMaskSet = digitalPinToBitMask(_dc);
|
||||
_dcPinMaskClr = ~_dcPinMaskSet;
|
||||
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
pinMode(_cs, OUTPUT);
|
||||
digitalWrite(_cs, HIGH); // Disable chip select
|
||||
_csPort = (PORTreg_t)portOutputRegister(digitalPinToPort(_cs));
|
||||
_csPinMaskSet = digitalPinToBitMask(_cs);
|
||||
}
|
||||
_csPinMaskClr = ~_csPinMaskSet;
|
||||
|
||||
pinMode(_wr, OUTPUT);
|
||||
digitalWrite(_wr, HIGH); // Set write strobe high (inactive)
|
||||
_wrPort = (PORTreg_t)portOutputRegister(digitalPinToPort(_wr));
|
||||
_wrPinMaskSet = digitalPinToBitMask(_wr);
|
||||
_wrPinMaskClr = ~_wrPinMaskSet;
|
||||
|
||||
if (_rd != GFX_NOT_DEFINED)
|
||||
{
|
||||
pinMode(_rd, OUTPUT);
|
||||
digitalWrite(_rd, HIGH); // Disable RD
|
||||
}
|
||||
|
||||
*(portModeRegister(_port)) = 0xFF;
|
||||
_dataPort = portOutputRegister(_port);
|
||||
*_dataPort = 0xFF;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Arduino_AVRPAR8::beginWrite()
|
||||
{
|
||||
DC_HIGH();
|
||||
CS_LOW();
|
||||
}
|
||||
|
||||
void Arduino_AVRPAR8::endWrite()
|
||||
{
|
||||
CS_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_AVRPAR8::writeCommand(uint8_t c)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_AVRPAR8::writeCommand16(uint16_t c)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
_data16.value = c;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_AVRPAR8::writeCommandBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
while (len--)
|
||||
{
|
||||
WRITE(*data++);
|
||||
}
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_AVRPAR8::write(uint8_t d)
|
||||
{
|
||||
WRITE(d);
|
||||
}
|
||||
|
||||
void Arduino_AVRPAR8::write16(uint16_t d)
|
||||
{
|
||||
_data16.value = d;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
|
||||
void Arduino_AVRPAR8::writeRepeat(uint16_t p, uint32_t len)
|
||||
{
|
||||
uint8_t wrMaskBase = *_wrPort & _wrPinMaskClr;
|
||||
uint8_t wrMaskSet = wrMaskBase | _wrPinMaskSet;
|
||||
_data16.value = p;
|
||||
if (_data16.msb == _data16.lsb)
|
||||
{
|
||||
*_dataPort = _data16.msb;
|
||||
while (len--)
|
||||
{
|
||||
*_wrPort = wrMaskBase;
|
||||
*_wrPort = wrMaskSet;
|
||||
*_wrPort = wrMaskBase;
|
||||
*_wrPort = wrMaskSet;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
*_dataPort = _data16.msb;
|
||||
*_wrPort = wrMaskBase;
|
||||
*_wrPort = wrMaskSet;
|
||||
|
||||
*_dataPort = _data16.lsb;
|
||||
*_wrPort = wrMaskBase;
|
||||
*_wrPort = wrMaskSet;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_AVRPAR8::writePixels(uint16_t *data, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
_data16.value = *data++;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_AVRPAR8::writeC8D8(uint8_t c, uint8_t d)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
WRITE(d);
|
||||
}
|
||||
|
||||
void Arduino_AVRPAR8::writeC8D16(uint8_t c, uint16_t d)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
_data16.value = d;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
|
||||
void Arduino_AVRPAR8::writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
_data16.value = d1;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
|
||||
_data16.value = d2;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
|
||||
void Arduino_AVRPAR8::writeBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
WRITE(*data++);
|
||||
}
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_AVRPAR8::WRITE(uint8_t d)
|
||||
{
|
||||
uint8_t wrMaskBase = *_wrPort & _wrPinMaskClr;
|
||||
*_dataPort = d;
|
||||
*_wrPort = wrMaskBase;
|
||||
*_wrPort = wrMaskBase | _wrPinMaskSet;
|
||||
}
|
||||
|
||||
/******** low level bit twiddling **********/
|
||||
|
||||
GFX_INLINE void Arduino_AVRPAR8::DC_HIGH(void)
|
||||
{
|
||||
*_dcPort |= _dcPinMaskSet;
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_AVRPAR8::DC_LOW(void)
|
||||
{
|
||||
*_dcPort &= _dcPinMaskClr;
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_AVRPAR8::CS_HIGH(void)
|
||||
{
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
*_csPort |= _csPinMaskSet;
|
||||
}
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_AVRPAR8::CS_LOW(void)
|
||||
{
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
*_csPort &= _csPinMaskClr;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // #ifdef __AVR__
|
||||
@@ -0,0 +1,57 @@
|
||||
#ifdef __AVR__
|
||||
|
||||
#ifndef _ARDUINO_AVRPAR8_H_
|
||||
#define _ARDUINO_AVRPAR8_H_
|
||||
|
||||
#include "Arduino_DataBus.h"
|
||||
|
||||
class Arduino_AVRPAR8 : public Arduino_DataBus
|
||||
{
|
||||
public:
|
||||
Arduino_AVRPAR8(int8_t dc, int8_t cs, int8_t wr, int8_t rd, uint8_t port); // Constructor
|
||||
|
||||
bool begin(int32_t speed = GFX_NOT_DEFINED, int8_t dataMode = GFX_NOT_DEFINED) override;
|
||||
void beginWrite() override;
|
||||
void endWrite() override;
|
||||
void writeCommand(uint8_t) override;
|
||||
void writeCommand16(uint16_t) override;
|
||||
void writeCommandBytes(uint8_t *data, uint32_t len) override;
|
||||
void write(uint8_t) override;
|
||||
void write16(uint16_t) override;
|
||||
void writeRepeat(uint16_t p, uint32_t len) override;
|
||||
void writePixels(uint16_t *data, uint32_t len) override;
|
||||
|
||||
void writeC8D8(uint8_t c, uint8_t d) override;
|
||||
void writeC8D16(uint8_t c, uint16_t d) override;
|
||||
void writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2) override;
|
||||
void writeBytes(uint8_t *data, uint32_t len) override;
|
||||
|
||||
protected:
|
||||
private:
|
||||
GFX_INLINE void WRITE(uint8_t d);
|
||||
GFX_INLINE void DC_HIGH(void);
|
||||
GFX_INLINE void DC_LOW(void);
|
||||
GFX_INLINE void CS_HIGH(void);
|
||||
GFX_INLINE void CS_LOW(void);
|
||||
|
||||
int8_t _dc, _cs, _wr, _rd;
|
||||
uint8_t _port;
|
||||
|
||||
PORTreg_t _dcPort; ///< PORT register for data/command
|
||||
ARDUINOGFX_PORT_t _dcPinMaskSet; ///< Bitmask for data/command SET (OR)
|
||||
ARDUINOGFX_PORT_t _dcPinMaskClr; ///< Bitmask for data/command CLEAR (AND)
|
||||
|
||||
PORTreg_t _csPort; ///< PORT register for data/command
|
||||
ARDUINOGFX_PORT_t _csPinMaskSet; ///< Bitmask for data/command SET (OR)
|
||||
ARDUINOGFX_PORT_t _csPinMaskClr; ///< Bitmask for data/command CLEAR (AND)
|
||||
|
||||
PORTreg_t _wrPort; ///< PORT register for data/command
|
||||
ARDUINOGFX_PORT_t _wrPinMaskSet; ///< Bitmask for data/command SET (OR)
|
||||
ARDUINOGFX_PORT_t _wrPinMaskClr; ///< Bitmask for data/command CLEAR (AND)
|
||||
|
||||
PORTreg_t _dataPort; ///< PORT register for data/command
|
||||
};
|
||||
|
||||
#endif // _ARDUINO_AVRPAR8_H_
|
||||
|
||||
#endif // #ifdef __AVR__
|
||||
@@ -0,0 +1,246 @@
|
||||
#if defined(ARDUINO_ARCH_SAM)
|
||||
|
||||
#include "Arduino_DUEPAR16.h"
|
||||
|
||||
Arduino_DUEPAR16::Arduino_DUEPAR16()
|
||||
{
|
||||
}
|
||||
|
||||
bool Arduino_DUEPAR16::begin(int32_t speed, int8_t dataMode)
|
||||
{
|
||||
UNUSED(speed);
|
||||
UNUSED(dataMode);
|
||||
_cs = 40;
|
||||
_dc = 38;
|
||||
_wr = 39;
|
||||
_rd = 43;
|
||||
digitalWrite(_dc, HIGH);
|
||||
digitalWrite(_cs, HIGH);
|
||||
digitalWrite(_wr, HIGH);
|
||||
digitalWrite(_rd, HIGH);
|
||||
pinMode(_dc, OUTPUT);
|
||||
pinMode(_cs, OUTPUT);
|
||||
pinMode(_wr, OUTPUT);
|
||||
pinMode(_rd, OUTPUT);
|
||||
setDataPins(OUTPUT);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Arduino_DUEPAR16::setDataPins(uint8_t mode)
|
||||
{
|
||||
pinMode(29, mode);
|
||||
pinMode(28, mode);
|
||||
pinMode(27, mode);
|
||||
pinMode(26, mode);
|
||||
pinMode(25, mode);
|
||||
pinMode(24, mode);
|
||||
pinMode(23, mode);
|
||||
pinMode(22, mode);
|
||||
pinMode(30, mode);
|
||||
pinMode(31, mode);
|
||||
pinMode(32, mode);
|
||||
pinMode(33, mode);
|
||||
pinMode(34, mode);
|
||||
pinMode(35, mode);
|
||||
pinMode(36, mode);
|
||||
pinMode(37, mode);
|
||||
}
|
||||
|
||||
void Arduino_DUEPAR16::beginWrite()
|
||||
{
|
||||
DC_HIGH();
|
||||
CS_LOW();
|
||||
}
|
||||
|
||||
void Arduino_DUEPAR16::endWrite()
|
||||
{
|
||||
CS_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_DUEPAR16::writeCommand(uint8_t c)
|
||||
{
|
||||
DC_LOW();
|
||||
WRITE16(c);
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_DUEPAR16::writeCommand16(uint16_t c)
|
||||
{
|
||||
DC_LOW();
|
||||
WRITE16(c);
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_DUEPAR16::writeCommandBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
DC_LOW();
|
||||
while (len--)
|
||||
{
|
||||
WRITE16(*data++);
|
||||
}
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_DUEPAR16::write(uint8_t d)
|
||||
{
|
||||
WRITE16(d);
|
||||
}
|
||||
|
||||
void Arduino_DUEPAR16::write16(uint16_t d)
|
||||
{
|
||||
WRITE16(d);
|
||||
}
|
||||
|
||||
void Arduino_DUEPAR16::writeRepeat(uint16_t p, uint32_t len)
|
||||
{
|
||||
writeData16(p, len);
|
||||
}
|
||||
|
||||
void Arduino_DUEPAR16::writePixels(uint16_t *data, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
WRITE16(*data++);
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(LITTLE_FOOT_PRINT)
|
||||
|
||||
void Arduino_DUEPAR16::writeC8D8(uint8_t c, uint8_t d)
|
||||
{
|
||||
DC_LOW();
|
||||
WRITE16(c);
|
||||
DC_HIGH();
|
||||
WRITE16(d);
|
||||
}
|
||||
|
||||
void Arduino_DUEPAR16::writeC8D16(uint8_t c, uint16_t d)
|
||||
{
|
||||
DC_LOW();
|
||||
WRITE16(c);
|
||||
DC_HIGH();
|
||||
WRITE16(d);
|
||||
}
|
||||
|
||||
void Arduino_DUEPAR16::writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2)
|
||||
{
|
||||
DC_LOW();
|
||||
WRITE16(c);
|
||||
DC_HIGH();
|
||||
WRITE16(d1);
|
||||
WRITE16(d2);
|
||||
}
|
||||
|
||||
void Arduino_DUEPAR16::writeC8D16D16Split(uint8_t c, uint16_t d1, uint16_t d2)
|
||||
{
|
||||
DC_LOW();
|
||||
WRITE16(c);
|
||||
DC_HIGH();
|
||||
WRITE16(d1);
|
||||
WRITE16(d2);
|
||||
}
|
||||
|
||||
void Arduino_DUEPAR16::writeBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
while (len > 1)
|
||||
{
|
||||
_data16.msb = *data++;
|
||||
_data16.lsb = *data++;
|
||||
WRITE16(_data16.value);
|
||||
len -= 2;
|
||||
}
|
||||
if (len)
|
||||
{
|
||||
WRITE16(*data);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_DUEPAR16::writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
WRITE16(idx[*data++]);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_DUEPAR16::writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
_data16.value = idx[*data++];
|
||||
WRITE16(_data16.value);
|
||||
WRITE16(_data16.value);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
|
||||
GFX_INLINE void Arduino_DUEPAR16::WRITE16(uint16_t d)
|
||||
{
|
||||
writeData16(d, 1);
|
||||
}
|
||||
|
||||
void Arduino_DUEPAR16::writeData16(uint16_t d, uint32_t num)
|
||||
{
|
||||
// | | | | Ruler for byte MS bits 31, 23, 15 and 7
|
||||
// B AA DD AD DDDD Marker for register bits used
|
||||
REG_PIOA_CODR = 0b00000000000000001100000010000000; // Clear bits
|
||||
REG_PIOB_CODR = 0b00000100000000000000000000000000; // Clear bits
|
||||
// W CCCCC // WR bit
|
||||
REG_PIOC_CODR = 0b00000000000000000000000010111110; // Clear WR bit as well
|
||||
REG_PIOD_CODR = 0b00000000000000000000011001001111; // Clear bits
|
||||
|
||||
// The compiler efficiently codes this
|
||||
// so it is quite quick. Port.bit
|
||||
if (d & 0x8000) REG_PIOD_SODR = 0x1 << 6; // D.6
|
||||
if (d & 0x4000) REG_PIOD_SODR = 0x1 << 3; // D.3
|
||||
if (d & 0x2000) REG_PIOD_SODR = 0x1 << 2; // D.2
|
||||
if (d & 0x1000) REG_PIOD_SODR = 0x1 << 1; // D.1
|
||||
if (d & 0x0800) REG_PIOD_SODR = 0x1 << 0; // D.0
|
||||
if (d & 0x0400) REG_PIOA_SODR = 0x1 << 15; // A.15
|
||||
if (d & 0x0200) REG_PIOA_SODR = 0x1 << 14; // A.14
|
||||
if (d & 0x0100) REG_PIOB_SODR = 0x1 << 26; // B.26
|
||||
|
||||
// so it is quite quick. Port.bit
|
||||
if (d & 0x0080) REG_PIOD_SODR = 0x1 << 9; // D.9
|
||||
if (d & 0x0040) REG_PIOA_SODR = 0x1 << 7; // A.7
|
||||
if (d & 0x0020) REG_PIOD_SODR = 0x1 << 10; // D.10
|
||||
if (d & 0x0010) REG_PIOC_SODR = 0x1 << 1; // C.1
|
||||
if (d & 0x0008) REG_PIOC_SODR = 0x1 << 2; // C.2
|
||||
if (d & 0x0004) REG_PIOC_SODR = 0x1 << 3; // C.3
|
||||
if (d & 0x0002) REG_PIOC_SODR = 0x1 << 4; // C.4
|
||||
if (d & 0x0001) REG_PIOC_SODR = 0x1 << 5; // C.5
|
||||
while (num > 0)
|
||||
{
|
||||
// WR_STB;
|
||||
REG_PIOC_CODR = 0x1 << 7;
|
||||
REG_PIOC_CODR = 0x1 << 7;
|
||||
REG_PIOC_CODR = 0x1 << 7;
|
||||
REG_PIOC_SODR = 0x1 << 7;
|
||||
num--;
|
||||
}
|
||||
}
|
||||
|
||||
/******** low level bit twiddling **********/
|
||||
|
||||
GFX_INLINE void Arduino_DUEPAR16::DC_HIGH(void)
|
||||
{
|
||||
digitalWrite(_dc, HIGH);
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_DUEPAR16::DC_LOW(void)
|
||||
{
|
||||
digitalWrite(_dc, LOW);
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_DUEPAR16::CS_HIGH(void)
|
||||
{
|
||||
digitalWrite(_cs, HIGH);
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_DUEPAR16::CS_LOW(void)
|
||||
{
|
||||
digitalWrite(_cs, LOW);
|
||||
}
|
||||
|
||||
#endif // #if defined(ARDUINO_ARCH_SAM)
|
||||
@@ -0,0 +1,52 @@
|
||||
#if defined(ARDUINO_ARCH_SAM)
|
||||
|
||||
#ifndef _ARDUINO_DUEPAR16_H_
|
||||
#define _ARDUINO_DUEPAR16_H_
|
||||
|
||||
#include "Arduino_DataBus.h"
|
||||
|
||||
// for MCUFriend MEGA kind of shields on Arduino DUE. -jz-
|
||||
|
||||
class Arduino_DUEPAR16 : public Arduino_DataBus
|
||||
{
|
||||
public:
|
||||
Arduino_DUEPAR16(); // Constructor
|
||||
|
||||
bool begin(int32_t speed = GFX_NOT_DEFINED, int8_t dataMode = GFX_NOT_DEFINED) override;
|
||||
void beginWrite() override;
|
||||
void endWrite() override;
|
||||
void writeCommand(uint8_t) override;
|
||||
void writeCommand16(uint16_t) override;
|
||||
void writeCommandBytes(uint8_t *data, uint32_t len) override;
|
||||
void write(uint8_t) override;
|
||||
void write16(uint16_t) override;
|
||||
void writeRepeat(uint16_t p, uint32_t len) override;
|
||||
void writePixels(uint16_t *data, uint32_t len) override;
|
||||
|
||||
#if !defined(LITTLE_FOOT_PRINT)
|
||||
void writeC8D8(uint8_t c, uint8_t d) override;
|
||||
void writeC8D16(uint8_t c, uint16_t d) override;
|
||||
void writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2) override;
|
||||
void writeC8D16D16Split(uint8_t c, uint16_t d1, uint16_t d2) override;
|
||||
void writeBytes(uint8_t *data, uint32_t len) override;
|
||||
|
||||
void writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len) override;
|
||||
void writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len) override;
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
|
||||
protected:
|
||||
private:
|
||||
void setDataPins(uint8_t mode);
|
||||
void writeData16(uint16_t d, uint32_t num = 1);
|
||||
GFX_INLINE void WRITE16(uint16_t d);
|
||||
GFX_INLINE void WRITEREPEAT(uint16_t p, uint32_t len);
|
||||
GFX_INLINE void DC_HIGH(void);
|
||||
GFX_INLINE void DC_LOW(void);
|
||||
GFX_INLINE void CS_HIGH(void);
|
||||
GFX_INLINE void CS_LOW(void);
|
||||
int8_t _cs, _dc, _wr, _rd;
|
||||
};
|
||||
|
||||
#endif // _ARDUINO_DUEPAR16_H_
|
||||
|
||||
#endif // #if defined(ARDUINO_ARCH_SAM)
|
||||
@@ -0,0 +1,107 @@
|
||||
#include "Arduino_ESP32DSIPanel.h"
|
||||
|
||||
#define TAG "Arduino_ESP32DSIPanel"
|
||||
|
||||
#if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32P4)
|
||||
Arduino_ESP32DSIPanel::Arduino_ESP32DSIPanel(
|
||||
uint32_t hsync_pulse_width, uint32_t hsync_back_porch, uint32_t hsync_front_porch,
|
||||
uint32_t vsync_pulse_width, uint32_t vsync_back_porch, uint32_t vsync_front_porch,
|
||||
uint32_t prefer_speed)
|
||||
: _hsync_pulse_width(hsync_pulse_width), _hsync_back_porch(hsync_back_porch), _hsync_front_porch(hsync_front_porch),
|
||||
_vsync_pulse_width(vsync_pulse_width), _vsync_back_porch(vsync_back_porch), _vsync_front_porch(vsync_front_porch),
|
||||
_prefer_speed(prefer_speed)
|
||||
{
|
||||
}
|
||||
|
||||
bool Arduino_ESP32DSIPanel::begin(int16_t w, int16_t h, int32_t speed, const lcd_init_cmd_t *init_operations, size_t init_operations_len)
|
||||
{
|
||||
if (speed == GFX_NOT_DEFINED)
|
||||
{
|
||||
if (_prefer_speed != GFX_NOT_DEFINED)
|
||||
{
|
||||
speed = _prefer_speed;
|
||||
}
|
||||
else
|
||||
{
|
||||
speed = 56000000L;
|
||||
}
|
||||
}
|
||||
|
||||
esp_ldo_channel_handle_t ldo_mipi_phy = NULL;
|
||||
esp_ldo_channel_config_t ldo_mipi_phy_config = {
|
||||
.chan_id = EXAMPLE_MIPI_DSI_PHY_PWR_LDO_CHAN,
|
||||
.voltage_mv = EXAMPLE_MIPI_DSI_PHY_PWR_LDO_VOLTAGE_MV,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_ldo_acquire_channel(&ldo_mipi_phy_config, &ldo_mipi_phy));
|
||||
ESP_LOGI(TAG, "MIPI DSI PHY Powered on");
|
||||
|
||||
esp_lcd_dsi_bus_config_t bus_config = {
|
||||
.bus_id = 0,
|
||||
.num_data_lanes = 2,
|
||||
.phy_clk_src = MIPI_DSI_PHY_CLK_SRC_DEFAULT,
|
||||
.lane_bit_rate_mbps = 750,
|
||||
};
|
||||
esp_lcd_dsi_bus_handle_t mipi_dsi_bus = NULL;
|
||||
|
||||
ESP_ERROR_CHECK(esp_lcd_new_dsi_bus(&bus_config, &mipi_dsi_bus));
|
||||
|
||||
ESP_LOGI(TAG, "Install MIPI DSI LCD control panel");
|
||||
esp_lcd_dbi_io_config_t dbi_config = {
|
||||
.virtual_channel = 0,
|
||||
.lcd_cmd_bits = 8,
|
||||
.lcd_param_bits = 8,
|
||||
};
|
||||
esp_lcd_panel_io_handle_t io_handle = NULL;
|
||||
ESP_ERROR_CHECK(esp_lcd_new_panel_io_dbi(mipi_dsi_bus, &dbi_config, &io_handle));
|
||||
|
||||
esp_lcd_dpi_panel_config_t dpi_config = {
|
||||
.virtual_channel = 0,
|
||||
.dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT,
|
||||
.dpi_clock_freq_mhz = speed / 1000000,
|
||||
.pixel_format = LCD_COLOR_PIXEL_FORMAT_RGB565,
|
||||
.num_fbs = 1,
|
||||
.video_timing = {
|
||||
.h_size = w,
|
||||
.v_size = h,
|
||||
.hsync_pulse_width = _hsync_pulse_width,
|
||||
.hsync_back_porch = _hsync_back_porch,
|
||||
.hsync_front_porch = _hsync_front_porch,
|
||||
.vsync_pulse_width = _vsync_pulse_width,
|
||||
.vsync_back_porch = _vsync_back_porch,
|
||||
.vsync_front_porch = _vsync_front_porch,
|
||||
},
|
||||
.flags = {
|
||||
.use_dma2d = true,
|
||||
},
|
||||
};
|
||||
|
||||
const esp_lcd_panel_dev_config_t panel_config = {
|
||||
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
|
||||
.bits_per_pixel = 16,
|
||||
};
|
||||
|
||||
// Create MIPI DPI panel
|
||||
ESP_ERROR_CHECK(esp_lcd_new_panel_dpi(mipi_dsi_bus, &dpi_config, &_panel_handle));
|
||||
|
||||
for (int i = 0; i < init_operations_len; i++)
|
||||
{
|
||||
// Send command
|
||||
ESP_ERROR_CHECK(esp_lcd_panel_io_tx_param(io_handle, init_operations[i].cmd, init_operations[i].data, init_operations[i].data_bytes));
|
||||
vTaskDelay(pdMS_TO_TICKS(init_operations[i].delay_ms));
|
||||
}
|
||||
ESP_LOGD(TAG, "send init commands success");
|
||||
|
||||
ESP_ERROR_CHECK(esp_lcd_panel_init(_panel_handle));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint16_t *Arduino_ESP32DSIPanel::getFrameBuffer()
|
||||
{
|
||||
void *frame_buffer = nullptr;
|
||||
ESP_ERROR_CHECK(esp_lcd_dpi_panel_get_frame_buffer(_panel_handle, 1, &frame_buffer));
|
||||
|
||||
return ((uint16_t *)frame_buffer);
|
||||
}
|
||||
|
||||
#endif // #if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32P4)
|
||||
@@ -0,0 +1,59 @@
|
||||
#pragma once
|
||||
|
||||
#include "Arduino_DataBus.h"
|
||||
|
||||
#if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32P4)
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sdkconfig.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
#include <freertos/semphr.h>
|
||||
#include <esp_timer.h>
|
||||
#include <esp_check.h>
|
||||
#include <esp_lcd_panel_ops.h>
|
||||
#include <esp_lcd_panel_vendor.h>
|
||||
#include <esp_lcd_mipi_dsi.h>
|
||||
#include <esp_lcd_panel_io.h>
|
||||
#include <esp_ldo_regulator.h>
|
||||
#include <driver/gpio.h>
|
||||
#include <esp_err.h>
|
||||
#include <esp_log.h>
|
||||
|
||||
#define EXAMPLE_MIPI_DSI_PHY_PWR_LDO_CHAN 3 // LDO_VO3 连接至 VDD_MIPI_DPHY
|
||||
#define EXAMPLE_MIPI_DSI_PHY_PWR_LDO_VOLTAGE_MV 2500
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int cmd; /*<! The specific LCD command */
|
||||
const void *data; /*<! Buffer that holds the command specific data */
|
||||
size_t data_bytes; /*<! Size of `data` in memory, in bytes */
|
||||
unsigned int delay_ms; /*<! Delay in milliseconds after this command */
|
||||
} lcd_init_cmd_t;
|
||||
|
||||
class Arduino_ESP32DSIPanel
|
||||
{
|
||||
public:
|
||||
Arduino_ESP32DSIPanel(
|
||||
uint32_t hsync_pulse_width, uint32_t hsync_back_porch, uint32_t hsync_front_porch,
|
||||
uint32_t vsync_pulse_width, uint32_t vsync_back_porch, uint32_t vsync_front_porch,
|
||||
uint32_t prefer_speed = GFX_NOT_DEFINED);
|
||||
|
||||
bool begin(int16_t w, int16_t h, int32_t speed = GFX_NOT_DEFINED, const lcd_init_cmd_t *init_operations = NULL, size_t init_operations_len = GFX_NOT_DEFINED);
|
||||
|
||||
uint16_t *getFrameBuffer();
|
||||
|
||||
protected:
|
||||
private:
|
||||
uint32_t _hsync_pulse_width;
|
||||
uint32_t _hsync_back_porch;
|
||||
uint32_t _hsync_front_porch;
|
||||
uint32_t _vsync_pulse_width;
|
||||
uint32_t _vsync_back_porch;
|
||||
uint32_t _vsync_front_porch;
|
||||
uint32_t _prefer_speed;
|
||||
|
||||
esp_lcd_panel_handle_t _panel_handle = NULL;
|
||||
};
|
||||
|
||||
#endif // #if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32P4)
|
||||
@@ -0,0 +1,600 @@
|
||||
/*
|
||||
* start rewrite from:
|
||||
* https://github.com/lovyan03/LovyanGFX/blob/master/src/lgfx/v0/platforms/LGFX_PARALLEL_ESP32.hpp
|
||||
*/
|
||||
#include "Arduino_ESP32LCD16.h"
|
||||
|
||||
#if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)
|
||||
#if (!defined(ESP_ARDUINO_VERSION_MAJOR)) || (ESP_ARDUINO_VERSION_MAJOR < 3)
|
||||
|
||||
#define WAIT_LCD_NOT_BUSY while (LCD_CAM.lcd_user.val & LCD_CAM_LCD_START)
|
||||
|
||||
Arduino_ESP32LCD16::Arduino_ESP32LCD16(
|
||||
int8_t dc, int8_t cs, int8_t wr, int8_t rd,
|
||||
int8_t d0, int8_t d1, int8_t d2, int8_t d3, int8_t d4, int8_t d5, int8_t d6, int8_t d7,
|
||||
int8_t d8, int8_t d9, int8_t d10, int8_t d11, int8_t d12, int8_t d13, int8_t d14, int8_t d15)
|
||||
: _dc(dc), _cs(cs), _wr(wr), _rd(rd),
|
||||
_d0(d0), _d1(d1), _d2(d2), _d3(d3), _d4(d4), _d5(d5), _d6(d6), _d7(d7),
|
||||
_d8(d8), _d9(d9), _d10(d10), _d11(d11), _d12(d12), _d13(d13), _d14(d14), _d15(d15)
|
||||
{
|
||||
}
|
||||
|
||||
bool Arduino_ESP32LCD16::begin(int32_t speed, int8_t dataMode)
|
||||
{
|
||||
if (speed == GFX_NOT_DEFINED)
|
||||
{
|
||||
_speed = 8000000UL; // safe frequency
|
||||
}
|
||||
else
|
||||
{
|
||||
_speed = speed;
|
||||
}
|
||||
|
||||
pinMode(_dc, OUTPUT);
|
||||
digitalWrite(_dc, HIGH); // Data mode
|
||||
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
pinMode(_cs, OUTPUT);
|
||||
digitalWrite(_cs, HIGH); // disable chip select
|
||||
}
|
||||
if (_cs >= 32)
|
||||
{
|
||||
_csPinMask = digitalPinToBitMask(_cs);
|
||||
_csPortSet = (PORTreg_t)GPIO_OUT1_W1TS_REG;
|
||||
_csPortClr = (PORTreg_t)GPIO_OUT1_W1TC_REG;
|
||||
}
|
||||
else if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
_csPinMask = digitalPinToBitMask(_cs);
|
||||
_csPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_csPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
}
|
||||
|
||||
pinMode(_wr, OUTPUT);
|
||||
digitalWrite(_wr, HIGH); // Set write strobe high (inactive)
|
||||
|
||||
if (_rd != GFX_NOT_DEFINED)
|
||||
{
|
||||
pinMode(_rd, OUTPUT);
|
||||
digitalWrite(_rd, HIGH);
|
||||
}
|
||||
|
||||
esp_lcd_i80_bus_config_t bus_config = {
|
||||
.dc_gpio_num = _dc,
|
||||
.wr_gpio_num = _wr,
|
||||
.clk_src = LCD_CLK_SRC_PLL160M,
|
||||
.data_gpio_nums = {
|
||||
_d0, _d1, _d2, _d3, _d4, _d5, _d6, _d7,
|
||||
_d8, _d9, _d10, _d11, _d12, _d13, _d14, _d15},
|
||||
.bus_width = 16,
|
||||
.max_transfer_bytes = LCD_MAX_PIXELS_AT_ONCE * 2,
|
||||
.psram_trans_align = 0,
|
||||
.sram_trans_align = 0};
|
||||
esp_lcd_new_i80_bus(&bus_config, &_i80_bus);
|
||||
|
||||
uint32_t diff = INT32_MAX;
|
||||
uint32_t div_n = 256;
|
||||
uint32_t div_a = 63;
|
||||
uint32_t div_b = 62;
|
||||
uint32_t clkcnt = 64;
|
||||
uint32_t start_cnt = std::min<uint32_t>(64u, (F_CPU / (_speed * 2) + 1));
|
||||
uint32_t end_cnt = std::max<uint32_t>(2u, F_CPU / 256u / _speed);
|
||||
if (start_cnt <= 2)
|
||||
{
|
||||
end_cnt = 1;
|
||||
}
|
||||
for (uint32_t cnt = start_cnt; diff && cnt >= end_cnt; --cnt)
|
||||
{
|
||||
float fdiv = (float)F_CPU / cnt / _speed;
|
||||
uint32_t n = std::max<uint32_t>(2u, (uint32_t)fdiv);
|
||||
fdiv -= n;
|
||||
|
||||
for (uint32_t a = 63; diff && a > 0; --a)
|
||||
{
|
||||
uint32_t b = roundf(fdiv * a);
|
||||
if (a == b && n == 256)
|
||||
{
|
||||
break;
|
||||
}
|
||||
uint32_t freq = F_CPU / ((n * cnt) + (float)(b * cnt) / (float)a);
|
||||
uint32_t d = abs(_speed - (int)freq);
|
||||
if (diff <= d)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
diff = d;
|
||||
clkcnt = cnt;
|
||||
div_n = n;
|
||||
div_b = b;
|
||||
div_a = a;
|
||||
if (b == 0 || a == b)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (div_a == div_b)
|
||||
{
|
||||
div_b = 0;
|
||||
div_n += 1;
|
||||
}
|
||||
int wait = 24 - (div_n * clkcnt);
|
||||
_fast_wait = (wait < 0) ? 0 : wait;
|
||||
|
||||
lcd_cam_lcd_clock_reg_t lcd_clock;
|
||||
lcd_clock.lcd_clkcnt_n = std::max(1u, clkcnt - 1);
|
||||
lcd_clock.lcd_clk_equ_sysclk = (clkcnt == 1);
|
||||
lcd_clock.lcd_ck_idle_edge = true;
|
||||
lcd_clock.lcd_ck_out_edge = false;
|
||||
lcd_clock.lcd_clkm_div_num = div_n;
|
||||
lcd_clock.lcd_clkm_div_b = div_b;
|
||||
lcd_clock.lcd_clkm_div_a = div_a;
|
||||
lcd_clock.lcd_clk_sel = 2; // clock_select: 1=XTAL CLOCK / 2=240MHz / 3=160MHz
|
||||
lcd_clock.clk_en = true;
|
||||
|
||||
LCD_CAM.lcd_clock.val = lcd_clock.val;
|
||||
|
||||
_dma_chan = _i80_bus->dma_chan;
|
||||
_dmadesc = (dma_descriptor_t *)heap_caps_malloc(sizeof(dma_descriptor_t), MALLOC_CAP_DMA);
|
||||
|
||||
_buffer = (uint8_t *)heap_caps_aligned_alloc(16, LCD_MAX_PIXELS_AT_ONCE * 2, MALLOC_CAP_DMA);
|
||||
if (!_buffer)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
_2nd_buffer = (uint8_t *)heap_caps_aligned_alloc(16, LCD_MAX_PIXELS_AT_ONCE * 2, MALLOC_CAP_DMA);
|
||||
if (!_2nd_buffer)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Arduino_ESP32LCD16::beginWrite()
|
||||
{
|
||||
CS_LOW();
|
||||
|
||||
LCD_CAM.lcd_misc.val = LCD_CAM_LCD_CD_IDLE_EDGE;
|
||||
LCD_CAM.lcd_user.val = 0;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_2BYTE_EN | LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG;
|
||||
}
|
||||
|
||||
void Arduino_ESP32LCD16::endWrite()
|
||||
{
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
|
||||
CS_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_ESP32LCD16::writeCommand(uint8_t c)
|
||||
{
|
||||
WRITECOMMAND16(c);
|
||||
}
|
||||
|
||||
void Arduino_ESP32LCD16::writeCommand16(uint16_t c)
|
||||
{
|
||||
WRITECOMMAND16(c);
|
||||
}
|
||||
|
||||
void Arduino_ESP32LCD16::writeCommandBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
LCD_CAM.lcd_misc.val = LCD_CAM_LCD_CD_IDLE_EDGE | LCD_CAM_LCD_CD_CMD_SET;
|
||||
|
||||
while (len--)
|
||||
{
|
||||
LCD_CAM.lcd_cmd_val.val = *data++;
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_2BYTE_EN | LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
|
||||
}
|
||||
LCD_CAM.lcd_misc.val = LCD_CAM_LCD_CD_IDLE_EDGE;
|
||||
}
|
||||
|
||||
void Arduino_ESP32LCD16::write(uint8_t d)
|
||||
{
|
||||
WRITE16(d);
|
||||
}
|
||||
|
||||
void Arduino_ESP32LCD16::write16(uint16_t d)
|
||||
{
|
||||
WRITE16(d);
|
||||
}
|
||||
|
||||
void Arduino_ESP32LCD16::writeRepeat(uint16_t p, uint32_t len)
|
||||
{
|
||||
if (len < USE_DMA_THRESHOLD)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
WRITE16(p);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t bufLen = (len < LCD_MAX_PIXELS_AT_ONCE) ? len : LCD_MAX_PIXELS_AT_ONCE;
|
||||
uint32_t xferLen, l;
|
||||
uint32_t c32 = p * 0x10001;
|
||||
|
||||
l = (bufLen + 1) / 2;
|
||||
for (uint32_t i = 0; i < l; i++)
|
||||
{
|
||||
_buffer32[i] = c32;
|
||||
}
|
||||
|
||||
while (len) // While pixels remain
|
||||
{
|
||||
xferLen = (bufLen <= len) ? bufLen : len; // How many this pass?
|
||||
|
||||
l = (xferLen - 2) * 2;
|
||||
*(uint32_t *)_dmadesc = ((l + 3) & (~3)) | l << 12 | 0xC0000000;
|
||||
_dmadesc->buffer = _buffer;
|
||||
_dmadesc->next = nullptr;
|
||||
gdma_start(_dma_chan, (intptr_t)(_dmadesc));
|
||||
LCD_CAM.lcd_misc.val = LCD_CAM_LCD_CD_IDLE_EDGE;
|
||||
LCD_CAM.lcd_cmd_val.val = c32;
|
||||
|
||||
uint32_t wait = _fast_wait;
|
||||
if (wait > 0)
|
||||
{
|
||||
do
|
||||
{
|
||||
__asm__ __volatile__("nop");
|
||||
} while (--wait);
|
||||
}
|
||||
|
||||
len -= xferLen;
|
||||
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_ALWAYS_OUT_EN | LCD_CAM_LCD_2BYTE_EN | LCD_CAM_LCD_CMD_2_CYCLE_EN | LCD_CAM_LCD_DOUT | LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
|
||||
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_ESP32LCD16::writePixels(uint16_t *data, uint32_t len)
|
||||
{
|
||||
uint32_t xferLen, l;
|
||||
|
||||
while (len > USE_DMA_THRESHOLD) // While pixels remain
|
||||
{
|
||||
xferLen = (len < LCD_MAX_PIXELS_AT_ONCE) ? len : LCD_MAX_PIXELS_AT_ONCE; // How many this pass?
|
||||
_data32.value16 = *data++;
|
||||
_data32.value16_2 = *data++;
|
||||
|
||||
l = xferLen - 2;
|
||||
l <<= 1;
|
||||
*(uint32_t *)_dmadesc = ((l + 3) & (~3)) | l << 12 | 0xC0000000;
|
||||
_dmadesc->buffer = data;
|
||||
_dmadesc->next = nullptr;
|
||||
gdma_start(_dma_chan, (intptr_t)(_dmadesc));
|
||||
LCD_CAM.lcd_misc.val = LCD_CAM_LCD_CD_IDLE_EDGE;
|
||||
LCD_CAM.lcd_cmd_val.val = _data32.value;
|
||||
|
||||
uint32_t wait = _fast_wait;
|
||||
while (wait--)
|
||||
{
|
||||
__asm__ __volatile__("nop");
|
||||
}
|
||||
|
||||
data += xferLen - 2;
|
||||
len -= xferLen;
|
||||
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_ALWAYS_OUT_EN | LCD_CAM_LCD_2BYTE_EN | LCD_CAM_LCD_CMD_2_CYCLE_EN | LCD_CAM_LCD_DOUT | LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
|
||||
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
}
|
||||
|
||||
while (len--)
|
||||
{
|
||||
WRITE16(*data++);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_ESP32LCD16::writeC8D8(uint8_t c, uint8_t d)
|
||||
{
|
||||
WRITECOMMAND16(c);
|
||||
WRITE16(d);
|
||||
}
|
||||
|
||||
void Arduino_ESP32LCD16::writeC8D16(uint8_t c, uint16_t d)
|
||||
{
|
||||
WRITECOMMAND16(c);
|
||||
WRITE16(d);
|
||||
}
|
||||
|
||||
void Arduino_ESP32LCD16::writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2)
|
||||
{
|
||||
WRITECOMMAND16(c);
|
||||
WRITE16(d1);
|
||||
WRITE16(d2);
|
||||
}
|
||||
|
||||
void Arduino_ESP32LCD16::writeC8D16D16Split(uint8_t c, uint16_t d1, uint16_t d2)
|
||||
{
|
||||
WRITECOMMAND16(c);
|
||||
|
||||
_data16.value = d1;
|
||||
WRITE16(_data16.msb);
|
||||
WRITE16(_data16.lsb);
|
||||
|
||||
_data16.value = d2;
|
||||
WRITE16(_data16.msb);
|
||||
WRITE16(_data16.lsb);
|
||||
}
|
||||
|
||||
void Arduino_ESP32LCD16::writeBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
uint32_t xferLen, l;
|
||||
|
||||
while (len > (USE_DMA_THRESHOLD * 2)) // While pixels remain
|
||||
{
|
||||
xferLen = (len < (LCD_MAX_PIXELS_AT_ONCE * 2)) ? len : (LCD_MAX_PIXELS_AT_ONCE * 2); // How many this pass?
|
||||
_data32.msb = *data++;
|
||||
_data32.lsb = *data++;
|
||||
_data32.msb_2 = *data++;
|
||||
_data32.lsb_2 = *data++;
|
||||
|
||||
l = xferLen - 4;
|
||||
l >>= 1;
|
||||
for (int i = 0; i < l; ++i)
|
||||
{
|
||||
_buffer[(i * 2) + 1] = *data++;
|
||||
_buffer[i * 2] = *data++;
|
||||
}
|
||||
|
||||
l <<= 1;
|
||||
*(uint32_t *)_dmadesc = ((l + 3) & (~3)) | l << 12 | 0xC0000000;
|
||||
_dmadesc->buffer = _buffer;
|
||||
_dmadesc->next = nullptr;
|
||||
gdma_start(_dma_chan, (intptr_t)(_dmadesc));
|
||||
LCD_CAM.lcd_misc.val = LCD_CAM_LCD_CD_IDLE_EDGE;
|
||||
LCD_CAM.lcd_cmd_val.val = _data32.value;
|
||||
|
||||
uint32_t wait = _fast_wait;
|
||||
while (wait--)
|
||||
{
|
||||
__asm__ __volatile__("nop");
|
||||
}
|
||||
|
||||
len -= xferLen;
|
||||
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_ALWAYS_OUT_EN | LCD_CAM_LCD_2BYTE_EN | LCD_CAM_LCD_CMD_2_CYCLE_EN | LCD_CAM_LCD_DOUT | LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
}
|
||||
|
||||
while (len)
|
||||
{
|
||||
if (len == 1)
|
||||
{
|
||||
WRITE16(*data);
|
||||
len--;
|
||||
}
|
||||
else
|
||||
{
|
||||
_data16.lsb = *data++;
|
||||
_data16.msb = *data++;
|
||||
WRITE16(_data16.value);
|
||||
len -= 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_ESP32LCD16::writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len)
|
||||
{
|
||||
uint32_t xferLen, l;
|
||||
uint32_t p;
|
||||
|
||||
while (len > USE_DMA_THRESHOLD) // While pixels remain
|
||||
{
|
||||
xferLen = (len < LCD_MAX_PIXELS_AT_ONCE) ? len : LCD_MAX_PIXELS_AT_ONCE; // How many this pass?
|
||||
l = xferLen - 2;
|
||||
p = idx[*data++];
|
||||
p <<= 16;
|
||||
p |= idx[*data++];
|
||||
|
||||
for (int i = 0; i < l; ++i)
|
||||
{
|
||||
_buffer16[i] = idx[*data++];
|
||||
}
|
||||
|
||||
l <<= 1;
|
||||
*(uint32_t *)_dmadesc = ((l + 3) & (~3)) | l << 12 | 0xC0000000;
|
||||
_dmadesc->buffer = _buffer;
|
||||
_dmadesc->next = nullptr;
|
||||
gdma_start(_dma_chan, (intptr_t)(_dmadesc));
|
||||
LCD_CAM.lcd_misc.val = LCD_CAM_LCD_CD_IDLE_EDGE;
|
||||
LCD_CAM.lcd_cmd_val.val = p;
|
||||
|
||||
uint32_t wait = _fast_wait;
|
||||
while (wait--)
|
||||
{
|
||||
__asm__ __volatile__("nop");
|
||||
}
|
||||
|
||||
len -= xferLen;
|
||||
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_ALWAYS_OUT_EN | LCD_CAM_LCD_2BYTE_EN | LCD_CAM_LCD_CMD_2_CYCLE_EN | LCD_CAM_LCD_DOUT | LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
}
|
||||
|
||||
while (len--)
|
||||
{
|
||||
WRITE16(idx[*data++]);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_ESP32LCD16::writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len)
|
||||
{
|
||||
len <<= 1; // double length
|
||||
uint32_t xferLen, l;
|
||||
uint32_t p;
|
||||
|
||||
while (len > USE_DMA_THRESHOLD) // While pixels remain
|
||||
{
|
||||
xferLen = (len < LCD_MAX_PIXELS_AT_ONCE) ? len : LCD_MAX_PIXELS_AT_ONCE; // How many this pass?
|
||||
l = (xferLen - 2) / 2;
|
||||
p = idx[*data++] * 0x10001;
|
||||
|
||||
for (int i = 0; i < l; ++i)
|
||||
{
|
||||
_buffer32[i] = idx[*data++] * 0x10001;
|
||||
}
|
||||
|
||||
l <<= 2;
|
||||
*(uint32_t *)_dmadesc = ((l + 3) & (~3)) | l << 12 | 0xC0000000;
|
||||
_dmadesc->buffer = _buffer;
|
||||
_dmadesc->next = nullptr;
|
||||
gdma_start(_dma_chan, (intptr_t)(_dmadesc));
|
||||
LCD_CAM.lcd_misc.val = LCD_CAM_LCD_CD_IDLE_EDGE;
|
||||
LCD_CAM.lcd_cmd_val.val = p;
|
||||
|
||||
uint32_t wait = _fast_wait;
|
||||
while (wait--)
|
||||
{
|
||||
__asm__ __volatile__("nop");
|
||||
}
|
||||
|
||||
len -= xferLen;
|
||||
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_ALWAYS_OUT_EN | LCD_CAM_LCD_2BYTE_EN | LCD_CAM_LCD_CMD_2_CYCLE_EN | LCD_CAM_LCD_DOUT | LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
}
|
||||
|
||||
len >>= 1;
|
||||
while (len--)
|
||||
{
|
||||
p = idx[*data++] * 0x10001;
|
||||
WRITE32(p);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_ESP32LCD16::writeYCbCrPixels(uint8_t *yData, uint8_t *cbData, uint8_t *crData, uint16_t w, uint16_t h)
|
||||
{
|
||||
if (w > (LCD_MAX_PIXELS_AT_ONCE / 2))
|
||||
{
|
||||
Arduino_DataBus::writeYCbCrPixels(yData, cbData, crData, w, h);
|
||||
}
|
||||
else
|
||||
{
|
||||
int cols = w >> 1;
|
||||
int rows = h >> 1;
|
||||
uint8_t *yData2 = yData + w;
|
||||
uint16_t *dest = _buffer16;
|
||||
uint16_t *dest2 = dest + w;
|
||||
|
||||
uint8_t pxCb, pxCr;
|
||||
int16_t pxR, pxG, pxB, pxY;
|
||||
|
||||
uint16_t l = (w * 4) - 4;
|
||||
uint32_t out_dmadesc = ((l + 3) & (~3)) | l << 12 | 0xC0000000;
|
||||
bool poll_started = false;
|
||||
for (int row = 0; row < rows; ++row)
|
||||
{
|
||||
for (int col = 0; col < cols; ++col)
|
||||
{
|
||||
pxCb = *cbData++;
|
||||
pxCr = *crData++;
|
||||
pxR = CR2R16[pxCr];
|
||||
pxG = -CB2G16[pxCb] - CR2G16[pxCr];
|
||||
pxB = CB2B16[pxCb];
|
||||
|
||||
pxY = Y2I16[*yData++];
|
||||
*dest++ = CLIPR[pxY + pxR] | CLIPG[pxY + pxG] | CLIPB[pxY + pxB];
|
||||
pxY = Y2I16[*yData++];
|
||||
*dest++ = CLIPR[pxY + pxR] | CLIPG[pxY + pxG] | CLIPB[pxY + pxB];
|
||||
pxY = Y2I16[*yData2++];
|
||||
*dest2++ = CLIPR[pxY + pxR] | CLIPG[pxY + pxG] | CLIPB[pxY + pxB];
|
||||
pxY = Y2I16[*yData2++];
|
||||
*dest2++ = CLIPR[pxY + pxR] | CLIPG[pxY + pxG] | CLIPB[pxY + pxB];
|
||||
}
|
||||
yData += w;
|
||||
yData2 += w;
|
||||
|
||||
if (poll_started)
|
||||
{
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
}
|
||||
else
|
||||
{
|
||||
poll_started = true;
|
||||
}
|
||||
|
||||
*(uint32_t *)_dmadesc = out_dmadesc;
|
||||
if (row & 1)
|
||||
{
|
||||
_dmadesc->buffer = _2nd_buffer32 + 1;
|
||||
_dmadesc->next = nullptr;
|
||||
gdma_start(_dma_chan, (intptr_t)(_dmadesc));
|
||||
LCD_CAM.lcd_misc.val = LCD_CAM_LCD_CD_IDLE_EDGE;
|
||||
LCD_CAM.lcd_cmd_val.val = *_2nd_buffer32;
|
||||
dest = _buffer16;
|
||||
}
|
||||
else
|
||||
{
|
||||
_dmadesc->buffer = _buffer32 + 1;
|
||||
_dmadesc->next = nullptr;
|
||||
gdma_start(_dma_chan, (intptr_t)(_dmadesc));
|
||||
LCD_CAM.lcd_misc.val = LCD_CAM_LCD_CD_IDLE_EDGE;
|
||||
LCD_CAM.lcd_cmd_val.val = *_buffer32;
|
||||
dest = _2nd_buffer16;
|
||||
}
|
||||
|
||||
uint32_t wait = _fast_wait;
|
||||
while (wait--)
|
||||
{
|
||||
__asm__ __volatile__("nop");
|
||||
}
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_ALWAYS_OUT_EN | LCD_CAM_LCD_2BYTE_EN | LCD_CAM_LCD_CMD_2_CYCLE_EN | LCD_CAM_LCD_DOUT | LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
|
||||
|
||||
dest2 = dest + w;
|
||||
}
|
||||
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP32LCD16::WRITECOMMAND16(uint16_t c)
|
||||
{
|
||||
LCD_CAM.lcd_misc.val = LCD_CAM_LCD_CD_IDLE_EDGE | LCD_CAM_LCD_CD_CMD_SET;
|
||||
LCD_CAM.lcd_cmd_val.val = c;
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_2BYTE_EN | LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP32LCD16::WRITE16(uint16_t d)
|
||||
{
|
||||
LCD_CAM.lcd_misc.val = LCD_CAM_LCD_CD_IDLE_EDGE;
|
||||
LCD_CAM.lcd_cmd_val.val = d;
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_2BYTE_EN | LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP32LCD16::WRITE32(uint32_t d)
|
||||
{
|
||||
LCD_CAM.lcd_misc.val = LCD_CAM_LCD_CD_IDLE_EDGE;
|
||||
LCD_CAM.lcd_cmd_val.val = d;
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_CMD_2_CYCLE_EN | LCD_CAM_LCD_2BYTE_EN | LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
|
||||
}
|
||||
|
||||
/******** low level bit twiddling **********/
|
||||
|
||||
GFX_INLINE void Arduino_ESP32LCD16::CS_HIGH(void)
|
||||
{
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
*_csPortSet = _csPinMask;
|
||||
}
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP32LCD16::CS_LOW(void)
|
||||
{
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
*_csPortClr = _csPinMask;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // #if (!defined(ESP_ARDUINO_VERSION_MAJOR)) || (ESP_ARDUINO_VERSION_MAJOR < 3)
|
||||
#endif // #if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)
|
||||
@@ -0,0 +1,98 @@
|
||||
#pragma once
|
||||
|
||||
#include "Arduino_DataBus.h"
|
||||
|
||||
#if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)
|
||||
#if (!defined(ESP_ARDUINO_VERSION_MAJOR)) || (ESP_ARDUINO_VERSION_MAJOR < 3)
|
||||
|
||||
#ifndef LCD_MAX_PIXELS_AT_ONCE
|
||||
#define LCD_MAX_PIXELS_AT_ONCE 2046
|
||||
#endif
|
||||
#ifndef USE_DMA_THRESHOLD
|
||||
#define USE_DMA_THRESHOLD 6
|
||||
#endif
|
||||
|
||||
class Arduino_ESP32LCD16 : public Arduino_DataBus
|
||||
{
|
||||
public:
|
||||
Arduino_ESP32LCD16(
|
||||
int8_t dc, int8_t cs, int8_t wr, int8_t rd,
|
||||
int8_t d0, int8_t d1, int8_t d2, int8_t d3, int8_t d4, int8_t d5, int8_t d6, int8_t d7,
|
||||
int8_t d8, int8_t d9, int8_t d10, int8_t d11, int8_t d12, int8_t d13, int8_t d14, int8_t d15); // Constructor
|
||||
|
||||
bool begin(int32_t speed = GFX_NOT_DEFINED, int8_t dataMode = GFX_NOT_DEFINED) override;
|
||||
void beginWrite() override;
|
||||
void endWrite() override;
|
||||
void writeCommand(uint8_t) override;
|
||||
void writeCommand16(uint16_t) override;
|
||||
void writeCommandBytes(uint8_t *data, uint32_t len) override;
|
||||
void write(uint8_t) override;
|
||||
void write16(uint16_t) override;
|
||||
void writeRepeat(uint16_t p, uint32_t len) override;
|
||||
void writePixels(uint16_t *data, uint32_t len) override;
|
||||
|
||||
void writeC8D8(uint8_t c, uint8_t d) override;
|
||||
void writeC8D16(uint8_t c, uint16_t d) override;
|
||||
void writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2) override;
|
||||
void writeC8D16D16Split(uint8_t c, uint16_t d1, uint16_t d2) override;
|
||||
void writeBytes(uint8_t *data, uint32_t len) override;
|
||||
|
||||
void writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len) override;
|
||||
void writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len) override;
|
||||
void writeYCbCrPixels(uint8_t *yData, uint8_t *cbData, uint8_t *crData, uint16_t w, uint16_t h) override;
|
||||
|
||||
protected:
|
||||
private:
|
||||
GFX_INLINE void WRITECOMMAND16(uint16_t c);
|
||||
GFX_INLINE void WRITE16(uint16_t d);
|
||||
GFX_INLINE void WRITE32(uint32_t d);
|
||||
GFX_INLINE void CS_HIGH(void);
|
||||
GFX_INLINE void CS_LOW(void);
|
||||
|
||||
int8_t _dc, _cs, _wr, _rd;
|
||||
int8_t _d0, _d1, _d2, _d3, _d4, _d5, _d6, _d7;
|
||||
int8_t _d8, _d9, _d10, _d11, _d12, _d13, _d14, _d15;
|
||||
|
||||
PORTreg_t _csPortSet; ///< PORT register SET
|
||||
PORTreg_t _csPortClr; ///< PORT register CLEAR
|
||||
uint32_t _csPinMask; ///< Bitmask
|
||||
|
||||
uint32_t _fast_wait;
|
||||
esp_lcd_i80_bus_handle_t _i80_bus = nullptr;
|
||||
dma_descriptor_t *_dmadesc = nullptr;
|
||||
gdma_channel_handle_t _dma_chan;
|
||||
|
||||
union
|
||||
{
|
||||
uint32_t value;
|
||||
struct
|
||||
{
|
||||
uint16_t value16;
|
||||
uint16_t value16_2;
|
||||
};
|
||||
struct
|
||||
{
|
||||
uint8_t lsb;
|
||||
uint8_t msb;
|
||||
uint8_t lsb_2;
|
||||
uint8_t msb_2;
|
||||
};
|
||||
} _data32;
|
||||
|
||||
union
|
||||
{
|
||||
uint8_t* _buffer;
|
||||
uint16_t* _buffer16;
|
||||
uint32_t* _buffer32;
|
||||
};
|
||||
|
||||
union
|
||||
{
|
||||
uint8_t *_2nd_buffer;
|
||||
uint16_t *_2nd_buffer16;
|
||||
uint32_t *_2nd_buffer32;
|
||||
};
|
||||
};
|
||||
|
||||
#endif // #if (!defined(ESP_ARDUINO_VERSION_MAJOR)) || (ESP_ARDUINO_VERSION_MAJOR < 3)
|
||||
#endif // #if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)
|
||||
@@ -0,0 +1,748 @@
|
||||
/*
|
||||
* start rewrite from:
|
||||
* https://github.com/lovyan03/LovyanGFX/blob/master/src/lgfx/v0/platforms/LGFX_PARALLEL_ESP32.hpp
|
||||
*/
|
||||
#include "Arduino_ESP32LCD8.h"
|
||||
|
||||
#if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)
|
||||
#if (!defined(ESP_ARDUINO_VERSION_MAJOR)) || (ESP_ARDUINO_VERSION_MAJOR < 3)
|
||||
|
||||
#define WAIT_LCD_NOT_BUSY while (LCD_CAM.lcd_user.val & LCD_CAM_LCD_START)
|
||||
|
||||
/**
|
||||
* @brief Construct a new Arduino_ESP32LCD8::Arduino_ESP32LCD8 object
|
||||
*
|
||||
* @param dc
|
||||
* @param cs
|
||||
* @param wr
|
||||
* @param rd
|
||||
* @param d0
|
||||
* @param d1
|
||||
* @param d2
|
||||
* @param d3
|
||||
* @param d4
|
||||
* @param d5
|
||||
* @param d6
|
||||
* @param d7
|
||||
*/
|
||||
Arduino_ESP32LCD8::Arduino_ESP32LCD8(
|
||||
int8_t dc, int8_t cs, int8_t wr, int8_t rd,
|
||||
int8_t d0, int8_t d1, int8_t d2, int8_t d3, int8_t d4, int8_t d5, int8_t d6, int8_t d7)
|
||||
: _dc(dc), _cs(cs), _wr(wr), _rd(rd),
|
||||
_d0(d0), _d1(d1), _d2(d2), _d3(d3), _d4(d4), _d5(d5), _d6(d6), _d7(d7)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief begin
|
||||
*
|
||||
* @param speed
|
||||
* @param dataMode
|
||||
* @return true
|
||||
* @return false
|
||||
*/
|
||||
bool Arduino_ESP32LCD8::begin(int32_t speed, int8_t dataMode)
|
||||
{
|
||||
if (speed == GFX_NOT_DEFINED)
|
||||
{
|
||||
_speed = 40000000UL;
|
||||
}
|
||||
else
|
||||
{
|
||||
_speed = speed;
|
||||
}
|
||||
|
||||
pinMode(_dc, OUTPUT);
|
||||
digitalWrite(_dc, HIGH); // Data mode
|
||||
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
pinMode(_cs, OUTPUT);
|
||||
digitalWrite(_cs, HIGH); // disable chip select
|
||||
}
|
||||
if (_cs >= 32)
|
||||
{
|
||||
_csPinMask = digitalPinToBitMask(_cs);
|
||||
_csPortSet = (PORTreg_t)GPIO_OUT1_W1TS_REG;
|
||||
_csPortClr = (PORTreg_t)GPIO_OUT1_W1TC_REG;
|
||||
}
|
||||
else if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
_csPinMask = digitalPinToBitMask(_cs);
|
||||
_csPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_csPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
}
|
||||
|
||||
pinMode(_wr, OUTPUT);
|
||||
digitalWrite(_wr, HIGH); // Set write strobe high (inactive)
|
||||
|
||||
if (_rd != GFX_NOT_DEFINED)
|
||||
{
|
||||
pinMode(_rd, OUTPUT);
|
||||
digitalWrite(_rd, HIGH);
|
||||
}
|
||||
|
||||
esp_lcd_i80_bus_config_t bus_config = {
|
||||
.dc_gpio_num = _dc,
|
||||
.wr_gpio_num = _wr,
|
||||
.clk_src = LCD_CLK_SRC_PLL160M,
|
||||
.data_gpio_nums = {
|
||||
_d0, _d1, _d2, _d3, _d4, _d5, _d6, _d7},
|
||||
.bus_width = 8,
|
||||
.max_transfer_bytes = LCD_MAX_PIXELS_AT_ONCE * 2,
|
||||
.psram_trans_align = 0,
|
||||
.sram_trans_align = 0};
|
||||
esp_lcd_new_i80_bus(&bus_config, &_i80_bus);
|
||||
|
||||
uint32_t diff = INT32_MAX;
|
||||
uint32_t div_n = 256;
|
||||
uint32_t div_a = 63;
|
||||
uint32_t div_b = 62;
|
||||
uint32_t clkcnt = 64;
|
||||
uint32_t start_cnt = std::min<uint32_t>(64u, (F_CPU / (_speed * 2) + 1));
|
||||
uint32_t end_cnt = std::max<uint32_t>(2u, F_CPU / 256u / _speed);
|
||||
if (start_cnt <= 2)
|
||||
{
|
||||
end_cnt = 1;
|
||||
}
|
||||
for (uint32_t cnt = start_cnt; diff && cnt >= end_cnt; --cnt)
|
||||
{
|
||||
float fdiv = (float)F_CPU / cnt / _speed;
|
||||
uint32_t n = std::max<uint32_t>(2u, (uint32_t)fdiv);
|
||||
fdiv -= n;
|
||||
|
||||
for (uint32_t a = 63; diff && a > 0; --a)
|
||||
{
|
||||
uint32_t b = roundf(fdiv * a);
|
||||
if (a == b && n == 256)
|
||||
{
|
||||
break;
|
||||
}
|
||||
uint32_t freq = F_CPU / ((n * cnt) + (float)(b * cnt) / (float)a);
|
||||
uint32_t d = abs(_speed - (int)freq);
|
||||
if (diff <= d)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
diff = d;
|
||||
clkcnt = cnt;
|
||||
div_n = n;
|
||||
div_b = b;
|
||||
div_a = a;
|
||||
if (b == 0 || a == b)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (div_a == div_b)
|
||||
{
|
||||
div_b = 0;
|
||||
div_n += 1;
|
||||
}
|
||||
|
||||
lcd_cam_lcd_clock_reg_t lcd_clock;
|
||||
lcd_clock.lcd_clkcnt_n = std::max(1u, clkcnt - 1);
|
||||
lcd_clock.lcd_clk_equ_sysclk = (clkcnt == 1);
|
||||
lcd_clock.lcd_ck_idle_edge = true;
|
||||
lcd_clock.lcd_ck_out_edge = false;
|
||||
lcd_clock.lcd_clkm_div_num = div_n;
|
||||
lcd_clock.lcd_clkm_div_b = div_b;
|
||||
lcd_clock.lcd_clkm_div_a = div_a;
|
||||
lcd_clock.lcd_clk_sel = 2; // clock_select: 1=XTAL CLOCK / 2=240MHz / 3=160MHz
|
||||
lcd_clock.clk_en = true;
|
||||
|
||||
LCD_CAM.lcd_clock.val = lcd_clock.val;
|
||||
|
||||
_dma_chan = _i80_bus->dma_chan;
|
||||
_dmadesc = (dma_descriptor_t *)heap_caps_malloc(sizeof(dma_descriptor_t), MALLOC_CAP_DMA);
|
||||
|
||||
_buffer = (uint8_t *)heap_caps_aligned_alloc(16, LCD_MAX_PIXELS_AT_ONCE * 2, MALLOC_CAP_DMA);
|
||||
if (!_buffer)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief beginWrite
|
||||
*
|
||||
*/
|
||||
void Arduino_ESP32LCD8::beginWrite()
|
||||
{
|
||||
CS_LOW();
|
||||
|
||||
LCD_CAM.lcd_misc.val = LCD_CAM_LCD_CD_IDLE_EDGE;
|
||||
LCD_CAM.lcd_user.val = 0;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief endWrite
|
||||
*
|
||||
*/
|
||||
void Arduino_ESP32LCD8::endWrite()
|
||||
{
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
|
||||
CS_HIGH();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief writeCommand
|
||||
*
|
||||
* @param c
|
||||
*/
|
||||
void Arduino_ESP32LCD8::writeCommand(uint8_t c)
|
||||
{
|
||||
LCD_CAM.lcd_misc.val = LCD_CAM_LCD_CD_IDLE_EDGE | LCD_CAM_LCD_CD_CMD_SET;
|
||||
|
||||
LCD_CAM.lcd_cmd_val.lcd_cmd_value = c;
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
|
||||
|
||||
LCD_CAM.lcd_misc.val = LCD_CAM_LCD_CD_IDLE_EDGE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief writeCommand16
|
||||
*
|
||||
* @param c
|
||||
*/
|
||||
void Arduino_ESP32LCD8::writeCommand16(uint16_t c)
|
||||
{
|
||||
LCD_CAM.lcd_misc.val = LCD_CAM_LCD_CD_IDLE_EDGE | LCD_CAM_LCD_CD_CMD_SET;
|
||||
|
||||
_data16.value = c;
|
||||
LCD_CAM.lcd_cmd_val.lcd_cmd_value = _data16.msb;
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
|
||||
LCD_CAM.lcd_cmd_val.lcd_cmd_value = _data16.lsb;
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
|
||||
|
||||
LCD_CAM.lcd_misc.val = LCD_CAM_LCD_CD_IDLE_EDGE;
|
||||
}
|
||||
|
||||
void Arduino_ESP32LCD8::writeCommandBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
LCD_CAM.lcd_misc.val = LCD_CAM_LCD_CD_IDLE_EDGE | LCD_CAM_LCD_CD_CMD_SET;
|
||||
|
||||
while (len--)
|
||||
{
|
||||
_data16.value = *data++;
|
||||
LCD_CAM.lcd_cmd_val.lcd_cmd_value = _data16.msb;
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
|
||||
}
|
||||
|
||||
LCD_CAM.lcd_misc.val = LCD_CAM_LCD_CD_IDLE_EDGE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief write
|
||||
*
|
||||
* @param d
|
||||
*/
|
||||
void Arduino_ESP32LCD8::write(uint8_t d)
|
||||
{
|
||||
LCD_CAM.lcd_cmd_val.lcd_cmd_value = d;
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief write16
|
||||
*
|
||||
* @param d
|
||||
*/
|
||||
void Arduino_ESP32LCD8::write16(uint16_t d)
|
||||
{
|
||||
_data16.value = d;
|
||||
LCD_CAM.lcd_cmd_val.lcd_cmd_value = _data16.msb;
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
|
||||
LCD_CAM.lcd_cmd_val.lcd_cmd_value = _data16.lsb;
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief writeC8D8
|
||||
*
|
||||
* @param c
|
||||
* @param d
|
||||
*/
|
||||
void Arduino_ESP32LCD8::writeC8D8(uint8_t c, uint8_t d)
|
||||
{
|
||||
LCD_CAM.lcd_misc.val = LCD_CAM_LCD_CD_IDLE_EDGE | LCD_CAM_LCD_CD_CMD_SET;
|
||||
|
||||
LCD_CAM.lcd_cmd_val.lcd_cmd_value = c;
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
|
||||
|
||||
LCD_CAM.lcd_misc.val = LCD_CAM_LCD_CD_IDLE_EDGE;
|
||||
|
||||
LCD_CAM.lcd_cmd_val.lcd_cmd_value = d;
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief writeC8D16
|
||||
*
|
||||
* @param c
|
||||
* @param d
|
||||
*/
|
||||
void Arduino_ESP32LCD8::writeC8D16(uint8_t c, uint16_t d)
|
||||
{
|
||||
LCD_CAM.lcd_misc.val = LCD_CAM_LCD_CD_IDLE_EDGE | LCD_CAM_LCD_CD_CMD_SET;
|
||||
|
||||
LCD_CAM.lcd_cmd_val.lcd_cmd_value = c;
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
|
||||
|
||||
LCD_CAM.lcd_misc.val = LCD_CAM_LCD_CD_IDLE_EDGE;
|
||||
|
||||
LCD_CAM.lcd_cmd_val.lcd_cmd_value = d;
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief writeC8D16D16
|
||||
*
|
||||
* @param c
|
||||
* @param d1
|
||||
* @param d2
|
||||
*/
|
||||
void Arduino_ESP32LCD8::writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2)
|
||||
{
|
||||
LCD_CAM.lcd_misc.val = LCD_CAM_LCD_CD_IDLE_EDGE | LCD_CAM_LCD_CD_CMD_SET;
|
||||
|
||||
LCD_CAM.lcd_cmd_val.lcd_cmd_value = c;
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
|
||||
|
||||
LCD_CAM.lcd_misc.val = LCD_CAM_LCD_CD_IDLE_EDGE;
|
||||
|
||||
_data16.value = d1;
|
||||
LCD_CAM.lcd_cmd_val.lcd_cmd_value = _data16.msb;
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
|
||||
LCD_CAM.lcd_cmd_val.lcd_cmd_value = _data16.lsb;
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
|
||||
|
||||
_data16.value = d2;
|
||||
LCD_CAM.lcd_cmd_val.lcd_cmd_value = _data16.msb;
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
|
||||
LCD_CAM.lcd_cmd_val.lcd_cmd_value = _data16.lsb;
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief writeC8D16D16Split
|
||||
*
|
||||
* @param c
|
||||
* @param d1
|
||||
* @param d2
|
||||
*/
|
||||
void Arduino_ESP32LCD8::writeC8D16D16Split(uint8_t c, uint16_t d1, uint16_t d2)
|
||||
{
|
||||
LCD_CAM.lcd_misc.val = LCD_CAM_LCD_CD_IDLE_EDGE | LCD_CAM_LCD_CD_CMD_SET;
|
||||
|
||||
_data16.value = c;
|
||||
LCD_CAM.lcd_cmd_val.lcd_cmd_value = _data16.msb;
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
|
||||
LCD_CAM.lcd_cmd_val.lcd_cmd_value = _data16.lsb;
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
|
||||
|
||||
LCD_CAM.lcd_misc.val = LCD_CAM_LCD_CD_IDLE_EDGE;
|
||||
|
||||
_data16.value = d1;
|
||||
LCD_CAM.lcd_cmd_val.lcd_cmd_value = _data16.msb;
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
|
||||
LCD_CAM.lcd_cmd_val.lcd_cmd_value = _data16.lsb;
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
|
||||
|
||||
_data16.value = d2;
|
||||
LCD_CAM.lcd_cmd_val.lcd_cmd_value = _data16.msb;
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
|
||||
LCD_CAM.lcd_cmd_val.lcd_cmd_value = _data16.lsb;
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief writeRepeat
|
||||
*
|
||||
* @param p
|
||||
* @param len
|
||||
*/
|
||||
void Arduino_ESP32LCD8::writeRepeat(uint16_t p, uint32_t len)
|
||||
{
|
||||
if (len > USE_DMA_THRESHOLD)
|
||||
{
|
||||
uint32_t bufLen = (len < LCD_MAX_PIXELS_AT_ONCE) ? len : LCD_MAX_PIXELS_AT_ONCE;
|
||||
uint32_t xferLen, l;
|
||||
uint32_t c32;
|
||||
MSB_32_16_16_SET(c32, p, p);
|
||||
|
||||
l = (bufLen + 1) / 2;
|
||||
for (uint32_t i = 0; i < l; i++)
|
||||
{
|
||||
_buffer32[i] = c32;
|
||||
}
|
||||
|
||||
_data16.value = p;
|
||||
_data32.value = 0;
|
||||
_data32.lsb = _data16.msb;
|
||||
_data32.lsb_2 = _data16.lsb;
|
||||
|
||||
while (len > USE_DMA_THRESHOLD)
|
||||
{
|
||||
xferLen = (bufLen <= len) ? bufLen : len; // How many this pass?
|
||||
|
||||
LCD_CAM.lcd_cmd_val.val = _data32.value;
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_CMD | LCD_CAM_LCD_CMD_2_CYCLE_EN | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
|
||||
|
||||
l = xferLen - 2;
|
||||
l <<= 1;
|
||||
*(uint32_t *)_dmadesc = ((l + 3) & (~3)) | l << 12 | 0xC0000000;
|
||||
_dmadesc->buffer = _buffer;
|
||||
_dmadesc->next = nullptr;
|
||||
gdma_start(_dma_chan, (intptr_t)(_dmadesc));
|
||||
LCD_CAM.lcd_cmd_val.val = _data32.value;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_ALWAYS_OUT_EN | LCD_CAM_LCD_DOUT | LCD_CAM_LCD_CMD | LCD_CAM_LCD_CMD_2_CYCLE_EN | LCD_CAM_LCD_UPDATE_REG;
|
||||
|
||||
len -= xferLen;
|
||||
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_ALWAYS_OUT_EN | LCD_CAM_LCD_DOUT | LCD_CAM_LCD_CMD | LCD_CAM_LCD_CMD_2_CYCLE_EN | LCD_CAM_LCD_START;
|
||||
}
|
||||
}
|
||||
|
||||
while (len--)
|
||||
{
|
||||
_data16.value = p;
|
||||
LCD_CAM.lcd_cmd_val.lcd_cmd_value = _data16.msb;
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
|
||||
LCD_CAM.lcd_cmd_val.lcd_cmd_value = _data16.lsb;
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief writePixels
|
||||
*
|
||||
* @param data
|
||||
* @param len
|
||||
*/
|
||||
void Arduino_ESP32LCD8::writePixels(uint16_t *data, uint32_t len)
|
||||
{
|
||||
uint32_t xferLen, l;
|
||||
|
||||
while (len > (USE_DMA_THRESHOLD)) // While pixels remain
|
||||
{
|
||||
xferLen = (len >= LCD_MAX_PIXELS_AT_ONCE) ? (LCD_MAX_PIXELS_AT_ONCE) : len; // How many this pass?
|
||||
|
||||
_data16.value = *data++;
|
||||
_data32.value = 0;
|
||||
_data32.lsb = _data16.msb;
|
||||
_data32.lsb_2 = _data16.lsb;
|
||||
|
||||
LCD_CAM.lcd_cmd_val.val = _data32.value;
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_CMD | LCD_CAM_LCD_CMD_2_CYCLE_EN | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
|
||||
|
||||
_data16.value = *data++;
|
||||
_data32.value = 0;
|
||||
_data32.lsb = _data16.msb;
|
||||
_data32.lsb_2 = _data16.lsb;
|
||||
|
||||
l = xferLen - 2;
|
||||
l <<= 1;
|
||||
for (uint32_t i = 0; i < l;)
|
||||
{
|
||||
_data16.value = *data++;
|
||||
_buffer[i++] = _data16.msb;
|
||||
_buffer[i++] = _data16.lsb;
|
||||
}
|
||||
|
||||
*(uint32_t *)_dmadesc = ((l + 3) & (~3)) | l << 12 | 0xC0000000;
|
||||
_dmadesc->buffer = _buffer32;
|
||||
_dmadesc->next = nullptr;
|
||||
gdma_start(_dma_chan, (intptr_t)(_dmadesc));
|
||||
LCD_CAM.lcd_cmd_val.val = _data32.value;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_ALWAYS_OUT_EN | LCD_CAM_LCD_DOUT | LCD_CAM_LCD_CMD | LCD_CAM_LCD_CMD_2_CYCLE_EN | LCD_CAM_LCD_UPDATE_REG;
|
||||
|
||||
len -= xferLen;
|
||||
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_ALWAYS_OUT_EN | LCD_CAM_LCD_DOUT | LCD_CAM_LCD_CMD | LCD_CAM_LCD_CMD_2_CYCLE_EN | LCD_CAM_LCD_START;
|
||||
}
|
||||
|
||||
while (len--)
|
||||
{
|
||||
_data16.value = *data++;
|
||||
LCD_CAM.lcd_cmd_val.lcd_cmd_value = _data16.msb;
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
|
||||
LCD_CAM.lcd_cmd_val.lcd_cmd_value = _data16.lsb;
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief writeBytes
|
||||
*
|
||||
* @param data
|
||||
* @param len
|
||||
*/
|
||||
void Arduino_ESP32LCD8::writeBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
uint32_t xferLen, l;
|
||||
|
||||
if (esp_ptr_dma_capable(data))
|
||||
{
|
||||
while (len > (USE_DMA_THRESHOLD << 1)) // While pixels remain
|
||||
{
|
||||
xferLen = (len >= LCD_MAX_PIXELS_AT_ONCE << 1) ? (LCD_MAX_PIXELS_AT_ONCE << 1) : len; // How many this pass?
|
||||
|
||||
_data32.value = 0;
|
||||
_data32.lsb = *data++;
|
||||
_data32.lsb_2 = *data++;
|
||||
|
||||
LCD_CAM.lcd_cmd_val.val = _data32.value;
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_CMD | LCD_CAM_LCD_CMD_2_CYCLE_EN | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
|
||||
|
||||
_data32.value = 0;
|
||||
_data32.lsb = *data++;
|
||||
_data32.lsb_2 = *data++;
|
||||
|
||||
l = xferLen - 4;
|
||||
*(uint32_t *)_dmadesc = ((l + 3) & (~3)) | l << 12 | 0xC0000000;
|
||||
_dmadesc->buffer = data;
|
||||
_dmadesc->next = nullptr;
|
||||
gdma_start(_dma_chan, (intptr_t)(_dmadesc));
|
||||
LCD_CAM.lcd_cmd_val.val = _data32.value;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_ALWAYS_OUT_EN | LCD_CAM_LCD_DOUT | LCD_CAM_LCD_CMD | LCD_CAM_LCD_CMD_2_CYCLE_EN | LCD_CAM_LCD_UPDATE_REG;
|
||||
|
||||
data += xferLen - 4;
|
||||
len -= xferLen;
|
||||
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_ALWAYS_OUT_EN | LCD_CAM_LCD_DOUT | LCD_CAM_LCD_CMD | LCD_CAM_LCD_CMD_2_CYCLE_EN | LCD_CAM_LCD_START;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t l4;
|
||||
uint32_t *p;
|
||||
while (len > (USE_DMA_THRESHOLD << 1)) // While pixels remain
|
||||
{
|
||||
xferLen = (len >= LCD_MAX_PIXELS_AT_ONCE << 1) ? (LCD_MAX_PIXELS_AT_ONCE << 1) : len; // How many this pass?
|
||||
|
||||
_data32.value = 0;
|
||||
_data32.lsb = *data++;
|
||||
_data32.lsb_2 = *data++;
|
||||
|
||||
LCD_CAM.lcd_cmd_val.val = _data32.value;
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_CMD | LCD_CAM_LCD_CMD_2_CYCLE_EN | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
|
||||
|
||||
_data32.value = 0;
|
||||
_data32.lsb = *data++;
|
||||
_data32.lsb_2 = *data++;
|
||||
|
||||
l = xferLen - 4;
|
||||
|
||||
l4 = (l + 3) >> 2;
|
||||
p = (uint32_t *)data;
|
||||
for (uint32_t i = 0; i < l4; i++)
|
||||
{
|
||||
_buffer32[i] = *p++;
|
||||
}
|
||||
|
||||
*(uint32_t *)_dmadesc = ((l + 3) & (~3)) | l << 12 | 0xC0000000;
|
||||
_dmadesc->buffer = _buffer32;
|
||||
_dmadesc->next = nullptr;
|
||||
gdma_start(_dma_chan, (intptr_t)(_dmadesc));
|
||||
LCD_CAM.lcd_cmd_val.val = _data32.value;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_ALWAYS_OUT_EN | LCD_CAM_LCD_DOUT | LCD_CAM_LCD_CMD | LCD_CAM_LCD_CMD_2_CYCLE_EN | LCD_CAM_LCD_UPDATE_REG;
|
||||
|
||||
data += xferLen - 4;
|
||||
len -= xferLen;
|
||||
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_ALWAYS_OUT_EN | LCD_CAM_LCD_DOUT | LCD_CAM_LCD_CMD | LCD_CAM_LCD_CMD_2_CYCLE_EN | LCD_CAM_LCD_START;
|
||||
}
|
||||
}
|
||||
|
||||
while (len)
|
||||
{
|
||||
if (len == 1)
|
||||
{
|
||||
LCD_CAM.lcd_cmd_val.lcd_cmd_value = *data;
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
|
||||
len--;
|
||||
}
|
||||
else
|
||||
{
|
||||
LCD_CAM.lcd_cmd_val.lcd_cmd_value = *data++;
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
|
||||
LCD_CAM.lcd_cmd_val.lcd_cmd_value = *data++;
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
|
||||
|
||||
len -= 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief writeIndexedPixels
|
||||
*
|
||||
* @param data
|
||||
* @param idx
|
||||
* @param len
|
||||
*/
|
||||
void Arduino_ESP32LCD8::writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len)
|
||||
{
|
||||
if (len > USE_DMA_THRESHOLD)
|
||||
{
|
||||
uint32_t bufLen = (len < LCD_MAX_PIXELS_AT_ONCE) ? len : LCD_MAX_PIXELS_AT_ONCE;
|
||||
uint32_t xferLen, l;
|
||||
|
||||
while (len > USE_DMA_THRESHOLD)
|
||||
{
|
||||
xferLen = (bufLen <= len) ? bufLen : len; // How many this pass?
|
||||
|
||||
_data16.value = idx[*data++];
|
||||
_data32.value = 0;
|
||||
_data32.lsb = _data16.msb;
|
||||
_data32.lsb_2 = _data16.lsb;
|
||||
|
||||
LCD_CAM.lcd_cmd_val.val = _data32.value;
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_CMD | LCD_CAM_LCD_CMD_2_CYCLE_EN | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
|
||||
|
||||
_data16.value = idx[*data++];
|
||||
_data32.value = 0;
|
||||
_data32.lsb = _data16.msb;
|
||||
_data32.lsb_2 = _data16.lsb;
|
||||
|
||||
l = xferLen - 2;
|
||||
l >>= 1;
|
||||
for (uint32_t i = 0; i < l; i++)
|
||||
{
|
||||
_data16.value = idx[*data++];
|
||||
_data32.lsb = _data16.msb;
|
||||
_data32.msb = _data16.lsb;
|
||||
_data16.value = idx[*data++];
|
||||
_data32.lsb_2 = _data16.msb;
|
||||
_data32.msb_2 = _data16.lsb;
|
||||
_buffer32[i] = _data32.value;
|
||||
}
|
||||
|
||||
l <<= 2;
|
||||
*(uint32_t *)_dmadesc = ((l + 3) & (~3)) | l << 12 | 0xC0000000;
|
||||
_dmadesc->buffer = _buffer;
|
||||
_dmadesc->next = nullptr;
|
||||
gdma_start(_dma_chan, (intptr_t)(_dmadesc));
|
||||
LCD_CAM.lcd_cmd_val.val = _data32.value;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_ALWAYS_OUT_EN | LCD_CAM_LCD_DOUT | LCD_CAM_LCD_CMD | LCD_CAM_LCD_CMD_2_CYCLE_EN | LCD_CAM_LCD_UPDATE_REG;
|
||||
|
||||
len -= xferLen;
|
||||
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_ALWAYS_OUT_EN | LCD_CAM_LCD_DOUT | LCD_CAM_LCD_CMD | LCD_CAM_LCD_CMD_2_CYCLE_EN | LCD_CAM_LCD_START;
|
||||
}
|
||||
}
|
||||
|
||||
while (len--)
|
||||
{
|
||||
_data16.value = idx[*data++];
|
||||
LCD_CAM.lcd_cmd_val.lcd_cmd_value = _data16.msb;
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
|
||||
LCD_CAM.lcd_cmd_val.lcd_cmd_value = _data16.lsb;
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief writeIndexedPixelsDouble
|
||||
*
|
||||
* @param data
|
||||
* @param idx
|
||||
* @param len
|
||||
*/
|
||||
void Arduino_ESP32LCD8::writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
_data16.value = idx[*data++];
|
||||
LCD_CAM.lcd_cmd_val.lcd_cmd_value = _data16.msb;
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
|
||||
LCD_CAM.lcd_cmd_val.lcd_cmd_value = _data16.lsb;
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
|
||||
LCD_CAM.lcd_cmd_val.lcd_cmd_value = _data16.msb;
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
|
||||
LCD_CAM.lcd_cmd_val.lcd_cmd_value = _data16.lsb;
|
||||
WAIT_LCD_NOT_BUSY;
|
||||
LCD_CAM.lcd_user.val = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE_REG | LCD_CAM_LCD_START;
|
||||
}
|
||||
}
|
||||
|
||||
/******** low level bit twiddling **********/
|
||||
|
||||
/**
|
||||
* @brief CS_HIGH
|
||||
*
|
||||
* @return GFX_INLINE
|
||||
*/
|
||||
GFX_INLINE void Arduino_ESP32LCD8::CS_HIGH(void)
|
||||
{
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
*_csPortSet = _csPinMask;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief CS_LOW
|
||||
*
|
||||
* @return GFX_INLINE
|
||||
*/
|
||||
GFX_INLINE void Arduino_ESP32LCD8::CS_LOW(void)
|
||||
{
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
*_csPortClr = _csPinMask;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // #if (!defined(ESP_ARDUINO_VERSION_MAJOR)) || (ESP_ARDUINO_VERSION_MAJOR < 3)
|
||||
#endif // #if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)
|
||||
@@ -0,0 +1,86 @@
|
||||
#pragma once
|
||||
|
||||
#include "Arduino_DataBus.h"
|
||||
|
||||
#if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)
|
||||
#if (!defined(ESP_ARDUINO_VERSION_MAJOR)) || (ESP_ARDUINO_VERSION_MAJOR < 3)
|
||||
|
||||
#ifndef LCD_MAX_PIXELS_AT_ONCE
|
||||
#define LCD_MAX_PIXELS_AT_ONCE 2046
|
||||
#endif
|
||||
#ifndef USE_DMA_THRESHOLD
|
||||
#define USE_DMA_THRESHOLD 6
|
||||
#endif
|
||||
|
||||
class Arduino_ESP32LCD8 : public Arduino_DataBus
|
||||
{
|
||||
public:
|
||||
Arduino_ESP32LCD8(
|
||||
int8_t dc, int8_t cs, int8_t wr, int8_t rd,
|
||||
int8_t d0, int8_t d1, int8_t d2, int8_t d3, int8_t d4, int8_t d5, int8_t d6, int8_t d7); // Constructor
|
||||
|
||||
bool begin(int32_t speed = GFX_NOT_DEFINED, int8_t dataMode = GFX_NOT_DEFINED) override;
|
||||
void beginWrite() override;
|
||||
void endWrite() override;
|
||||
void writeCommand(uint8_t) override;
|
||||
void writeCommand16(uint16_t) override;
|
||||
void writeCommandBytes(uint8_t *data, uint32_t len) override;
|
||||
void write(uint8_t) override;
|
||||
void write16(uint16_t) override;
|
||||
|
||||
void writeC8D8(uint8_t c, uint8_t d) override;
|
||||
void writeC8D16(uint8_t c, uint16_t d) override;
|
||||
void writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2) override;
|
||||
void writeC8D16D16Split(uint8_t c, uint16_t d1, uint16_t d2) override;
|
||||
|
||||
void writeRepeat(uint16_t p, uint32_t len) override;
|
||||
void writePixels(uint16_t *data, uint32_t len) override;
|
||||
|
||||
void writeBytes(uint8_t *data, uint32_t len) override;
|
||||
|
||||
void writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len) override;
|
||||
void writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len) override;
|
||||
|
||||
protected:
|
||||
private:
|
||||
GFX_INLINE void CS_HIGH(void);
|
||||
GFX_INLINE void CS_LOW(void);
|
||||
|
||||
int8_t _dc, _cs, _wr, _rd;
|
||||
int8_t _d0, _d1, _d2, _d3, _d4, _d5, _d6, _d7;
|
||||
|
||||
PORTreg_t _csPortSet; ///< PORT register for chip select SET
|
||||
PORTreg_t _csPortClr; ///< PORT register for chip select CLEAR
|
||||
uint32_t _csPinMask; ///< Bitmask for chip select
|
||||
|
||||
esp_lcd_i80_bus_handle_t _i80_bus = nullptr;
|
||||
dma_descriptor_t *_dmadesc = nullptr;
|
||||
gdma_channel_handle_t _dma_chan;
|
||||
|
||||
union
|
||||
{
|
||||
uint32_t value;
|
||||
struct
|
||||
{
|
||||
uint16_t value16;
|
||||
uint16_t value16_2;
|
||||
};
|
||||
struct
|
||||
{
|
||||
uint8_t lsb;
|
||||
uint8_t msb;
|
||||
uint8_t lsb_2;
|
||||
uint8_t msb_2;
|
||||
};
|
||||
} _data32;
|
||||
|
||||
union
|
||||
{
|
||||
uint8_t* _buffer;
|
||||
uint16_t* _buffer16;
|
||||
uint32_t* _buffer32;
|
||||
};
|
||||
};
|
||||
|
||||
#endif // #if (!defined(ESP_ARDUINO_VERSION_MAJOR)) || (ESP_ARDUINO_VERSION_MAJOR < 3)
|
||||
#endif // #if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)
|
||||
@@ -0,0 +1,633 @@
|
||||
#include "Arduino_ESP32PAR16.h"
|
||||
|
||||
#if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
|
||||
|
||||
Arduino_ESP32PAR16::Arduino_ESP32PAR16(
|
||||
int8_t dc, int8_t cs, int8_t wr, int8_t rd,
|
||||
int8_t d0, int8_t d1, int8_t d2, int8_t d3, int8_t d4, int8_t d5, int8_t d6, int8_t d7,
|
||||
int8_t d8, int8_t d9, int8_t d10, int8_t d11, int8_t d12, int8_t d13, int8_t d14, int8_t d15)
|
||||
: _dc(dc), _cs(cs), _wr(wr), _rd(rd),
|
||||
_d0(d0), _d1(d1), _d2(d2), _d3(d3), _d4(d4), _d5(d5), _d6(d6), _d7(d7),
|
||||
_d8(d8), _d9(d9), _d10(d10), _d11(d11), _d12(d12), _d13(d13), _d14(d14), _d15(d15)
|
||||
{
|
||||
}
|
||||
|
||||
bool Arduino_ESP32PAR16::begin(int32_t, int8_t)
|
||||
{
|
||||
pinMode(_dc, OUTPUT);
|
||||
digitalWrite(_dc, HIGH); // Data mode
|
||||
if (_dc >= 32)
|
||||
{
|
||||
_dcPinMask = digitalPinToBitMask(_dc);
|
||||
_dcPortSet = (PORTreg_t)GPIO_OUT1_W1TS_REG;
|
||||
_dcPortClr = (PORTreg_t)GPIO_OUT1_W1TC_REG;
|
||||
}
|
||||
else
|
||||
{
|
||||
_dcPinMask = digitalPinToBitMask(_dc);
|
||||
_dcPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_dcPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
}
|
||||
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
pinMode(_cs, OUTPUT);
|
||||
digitalWrite(_cs, HIGH); // disable chip select
|
||||
}
|
||||
if (_cs >= 32)
|
||||
{
|
||||
_csPinMask = digitalPinToBitMask(_cs);
|
||||
_csPortSet = (PORTreg_t)GPIO_OUT1_W1TS_REG;
|
||||
_csPortClr = (PORTreg_t)GPIO_OUT1_W1TC_REG;
|
||||
}
|
||||
else if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
_csPinMask = digitalPinToBitMask(_cs);
|
||||
_csPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_csPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
}
|
||||
|
||||
pinMode(_wr, OUTPUT);
|
||||
digitalWrite(_wr, HIGH); // Set write strobe high (inactive)
|
||||
if (_wr >= 32)
|
||||
{
|
||||
_wrPinMask = digitalPinToBitMask(_wr);
|
||||
_wrPortSet = (PORTreg_t)GPIO_OUT1_W1TS_REG;
|
||||
_wrPortClr = (PORTreg_t)GPIO_OUT1_W1TC_REG;
|
||||
}
|
||||
else
|
||||
{
|
||||
_wrPinMask = digitalPinToBitMask(_wr);
|
||||
_wrPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_wrPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
}
|
||||
|
||||
if (_rd != GFX_NOT_DEFINED)
|
||||
{
|
||||
pinMode(_rd, OUTPUT);
|
||||
digitalWrite(_rd, HIGH);
|
||||
}
|
||||
|
||||
pinMode(_d0, OUTPUT);
|
||||
pinMode(_d1, OUTPUT);
|
||||
pinMode(_d2, OUTPUT);
|
||||
pinMode(_d3, OUTPUT);
|
||||
pinMode(_d4, OUTPUT);
|
||||
pinMode(_d5, OUTPUT);
|
||||
pinMode(_d6, OUTPUT);
|
||||
pinMode(_d7, OUTPUT);
|
||||
pinMode(_d8, OUTPUT);
|
||||
pinMode(_d9, OUTPUT);
|
||||
pinMode(_d10, OUTPUT);
|
||||
pinMode(_d11, OUTPUT);
|
||||
pinMode(_d12, OUTPUT);
|
||||
pinMode(_d13, OUTPUT);
|
||||
pinMode(_d14, OUTPUT);
|
||||
pinMode(_d15, OUTPUT);
|
||||
|
||||
_data1PortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_data1PortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
_data2PortSet = (PORTreg_t)GPIO_OUT1_W1TS_REG;
|
||||
_data2PortClr = (PORTreg_t)GPIO_OUT1_W1TC_REG;
|
||||
|
||||
// INIT 16-bit mask
|
||||
_data1ClrMask = 0;
|
||||
_data2ClrMask = 0;
|
||||
if (_d0 >= 32)
|
||||
{
|
||||
_data2ClrMask |= digitalPinToBitMask(_d0);
|
||||
}
|
||||
else
|
||||
{
|
||||
_data1ClrMask |= digitalPinToBitMask(_d0);
|
||||
}
|
||||
if (_d1 >= 32)
|
||||
{
|
||||
_data2ClrMask |= digitalPinToBitMask(_d1);
|
||||
}
|
||||
else
|
||||
{
|
||||
_data1ClrMask |= digitalPinToBitMask(_d1);
|
||||
}
|
||||
if (_d2 >= 32)
|
||||
{
|
||||
_data2ClrMask |= digitalPinToBitMask(_d2);
|
||||
}
|
||||
else
|
||||
{
|
||||
_data1ClrMask |= digitalPinToBitMask(_d2);
|
||||
}
|
||||
if (_d3 >= 32)
|
||||
{
|
||||
_data2ClrMask |= digitalPinToBitMask(_d3);
|
||||
}
|
||||
else
|
||||
{
|
||||
_data1ClrMask |= digitalPinToBitMask(_d3);
|
||||
}
|
||||
if (_d4 >= 32)
|
||||
{
|
||||
_data2ClrMask |= digitalPinToBitMask(_d4);
|
||||
}
|
||||
else
|
||||
{
|
||||
_data1ClrMask |= digitalPinToBitMask(_d4);
|
||||
}
|
||||
if (_d5 >= 32)
|
||||
{
|
||||
_data2ClrMask |= digitalPinToBitMask(_d5);
|
||||
}
|
||||
else
|
||||
{
|
||||
_data1ClrMask |= digitalPinToBitMask(_d5);
|
||||
}
|
||||
if (_d6 >= 32)
|
||||
{
|
||||
_data2ClrMask |= digitalPinToBitMask(_d6);
|
||||
}
|
||||
else
|
||||
{
|
||||
_data1ClrMask |= digitalPinToBitMask(_d6);
|
||||
}
|
||||
if (_d7 >= 32)
|
||||
{
|
||||
_data2ClrMask |= digitalPinToBitMask(_d7);
|
||||
}
|
||||
else
|
||||
{
|
||||
_data1ClrMask |= digitalPinToBitMask(_d7);
|
||||
}
|
||||
if (_d8 >= 32)
|
||||
{
|
||||
_data2ClrMask |= digitalPinToBitMask(_d8);
|
||||
}
|
||||
else
|
||||
{
|
||||
_data1ClrMask |= digitalPinToBitMask(_d8);
|
||||
}
|
||||
if (_d9 >= 32)
|
||||
{
|
||||
_data2ClrMask |= digitalPinToBitMask(_d9);
|
||||
}
|
||||
else
|
||||
{
|
||||
_data1ClrMask |= digitalPinToBitMask(_d9);
|
||||
}
|
||||
if (_d10 >= 32)
|
||||
{
|
||||
_data2ClrMask |= digitalPinToBitMask(_d10);
|
||||
}
|
||||
else
|
||||
{
|
||||
_data1ClrMask |= digitalPinToBitMask(_d10);
|
||||
}
|
||||
if (_d11 >= 32)
|
||||
{
|
||||
_data2ClrMask |= digitalPinToBitMask(_d11);
|
||||
}
|
||||
else
|
||||
{
|
||||
_data1ClrMask |= digitalPinToBitMask(_d11);
|
||||
}
|
||||
if (_d12 >= 32)
|
||||
{
|
||||
_data2ClrMask |= digitalPinToBitMask(_d12);
|
||||
}
|
||||
else
|
||||
{
|
||||
_data1ClrMask |= digitalPinToBitMask(_d12);
|
||||
}
|
||||
if (_d13 >= 32)
|
||||
{
|
||||
_data2ClrMask |= digitalPinToBitMask(_d13);
|
||||
}
|
||||
else
|
||||
{
|
||||
_data1ClrMask |= digitalPinToBitMask(_d13);
|
||||
}
|
||||
if (_d14 >= 32)
|
||||
{
|
||||
_data2ClrMask |= digitalPinToBitMask(_d14);
|
||||
}
|
||||
else
|
||||
{
|
||||
_data1ClrMask |= digitalPinToBitMask(_d14);
|
||||
}
|
||||
if (_d15 >= 32)
|
||||
{
|
||||
_data2ClrMask |= digitalPinToBitMask(_d15);
|
||||
}
|
||||
else
|
||||
{
|
||||
_data1ClrMask |= digitalPinToBitMask(_d15);
|
||||
}
|
||||
|
||||
for (int32_t c = 0; c < 256; c++)
|
||||
{
|
||||
_xset_mask1_lo[c] = 0;
|
||||
_xset_mask2_lo[c] = 0;
|
||||
if (c & 0x01)
|
||||
{
|
||||
if (_d0 >= 32)
|
||||
{
|
||||
_xset_mask2_lo[c] |= digitalPinToBitMask(_d0);
|
||||
}
|
||||
else
|
||||
{
|
||||
_xset_mask1_lo[c] |= digitalPinToBitMask(_d0);
|
||||
}
|
||||
}
|
||||
if (c & 0x02)
|
||||
{
|
||||
if (_d1 >= 32)
|
||||
{
|
||||
_xset_mask2_lo[c] |= digitalPinToBitMask(_d1);
|
||||
}
|
||||
else
|
||||
{
|
||||
_xset_mask1_lo[c] |= digitalPinToBitMask(_d1);
|
||||
}
|
||||
}
|
||||
if (c & 0x04)
|
||||
{
|
||||
if (_d2 >= 32)
|
||||
{
|
||||
_xset_mask2_lo[c] |= digitalPinToBitMask(_d2);
|
||||
}
|
||||
else
|
||||
{
|
||||
_xset_mask1_lo[c] |= digitalPinToBitMask(_d2);
|
||||
}
|
||||
}
|
||||
if (c & 0x08)
|
||||
{
|
||||
if (_d3 >= 32)
|
||||
{
|
||||
_xset_mask2_lo[c] |= digitalPinToBitMask(_d3);
|
||||
}
|
||||
else
|
||||
{
|
||||
_xset_mask1_lo[c] |= digitalPinToBitMask(_d3);
|
||||
}
|
||||
}
|
||||
if (c & 0x10)
|
||||
{
|
||||
if (_d4 >= 32)
|
||||
{
|
||||
_xset_mask2_lo[c] |= digitalPinToBitMask(_d4);
|
||||
}
|
||||
else
|
||||
{
|
||||
_xset_mask1_lo[c] |= digitalPinToBitMask(_d4);
|
||||
}
|
||||
}
|
||||
if (c & 0x20)
|
||||
{
|
||||
if (_d5 >= 32)
|
||||
{
|
||||
_xset_mask2_lo[c] |= digitalPinToBitMask(_d5);
|
||||
}
|
||||
else
|
||||
{
|
||||
_xset_mask1_lo[c] |= digitalPinToBitMask(_d5);
|
||||
}
|
||||
}
|
||||
if (c & 0x40)
|
||||
{
|
||||
if (_d6 >= 32)
|
||||
{
|
||||
_xset_mask2_lo[c] |= digitalPinToBitMask(_d6);
|
||||
}
|
||||
else
|
||||
{
|
||||
_xset_mask1_lo[c] |= digitalPinToBitMask(_d6);
|
||||
}
|
||||
}
|
||||
if (c & 0x80)
|
||||
{
|
||||
if (_d7 >= 32)
|
||||
{
|
||||
_xset_mask2_lo[c] |= digitalPinToBitMask(_d7);
|
||||
}
|
||||
else
|
||||
{
|
||||
_xset_mask1_lo[c] |= digitalPinToBitMask(_d7);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int32_t c = 0; c < 256; c++)
|
||||
{
|
||||
_xset_mask1_hi[c] = 0;
|
||||
_xset_mask2_hi[c] = 0;
|
||||
if (c & 0x01)
|
||||
{
|
||||
if (_d8 >= 32)
|
||||
{
|
||||
_xset_mask2_hi[c] |= digitalPinToBitMask(_d8);
|
||||
}
|
||||
else
|
||||
{
|
||||
_xset_mask1_hi[c] |= digitalPinToBitMask(_d8);
|
||||
}
|
||||
}
|
||||
if (c & 0x02)
|
||||
{
|
||||
if (_d9 >= 32)
|
||||
{
|
||||
_xset_mask2_hi[c] |= digitalPinToBitMask(_d9);
|
||||
}
|
||||
else
|
||||
{
|
||||
_xset_mask1_hi[c] |= digitalPinToBitMask(_d9);
|
||||
}
|
||||
}
|
||||
if (c & 0x04)
|
||||
{
|
||||
if (_d10 >= 32)
|
||||
{
|
||||
_xset_mask2_hi[c] |= digitalPinToBitMask(_d10);
|
||||
}
|
||||
else
|
||||
{
|
||||
_xset_mask1_hi[c] |= digitalPinToBitMask(_d10);
|
||||
}
|
||||
}
|
||||
if (c & 0x08)
|
||||
{
|
||||
if (_d11 >= 32)
|
||||
{
|
||||
_xset_mask2_hi[c] |= digitalPinToBitMask(_d11);
|
||||
}
|
||||
else
|
||||
{
|
||||
_xset_mask1_hi[c] |= digitalPinToBitMask(_d11);
|
||||
}
|
||||
}
|
||||
if (c & 0x10)
|
||||
{
|
||||
if (_d12 >= 32)
|
||||
{
|
||||
_xset_mask2_hi[c] |= digitalPinToBitMask(_d12);
|
||||
}
|
||||
else
|
||||
{
|
||||
_xset_mask1_hi[c] |= digitalPinToBitMask(_d12);
|
||||
}
|
||||
}
|
||||
if (c & 0x20)
|
||||
{
|
||||
if (_d13 >= 32)
|
||||
{
|
||||
_xset_mask2_hi[c] |= digitalPinToBitMask(_d13);
|
||||
}
|
||||
else
|
||||
{
|
||||
_xset_mask1_hi[c] |= digitalPinToBitMask(_d13);
|
||||
}
|
||||
}
|
||||
if (c & 0x40)
|
||||
{
|
||||
if (_d14 >= 32)
|
||||
{
|
||||
_xset_mask2_hi[c] |= digitalPinToBitMask(_d14);
|
||||
}
|
||||
else
|
||||
{
|
||||
_xset_mask1_hi[c] |= digitalPinToBitMask(_d14);
|
||||
}
|
||||
}
|
||||
if (c & 0x80)
|
||||
{
|
||||
if (_d15 >= 32)
|
||||
{
|
||||
_xset_mask2_hi[c] |= digitalPinToBitMask(_d15);
|
||||
}
|
||||
else
|
||||
{
|
||||
_xset_mask1_hi[c] |= digitalPinToBitMask(_d15);
|
||||
}
|
||||
}
|
||||
}
|
||||
*_data1PortClr = _data1ClrMask;
|
||||
*_data2PortClr = _data2ClrMask;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR16::beginWrite()
|
||||
{
|
||||
DC_HIGH();
|
||||
CS_LOW();
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR16::endWrite()
|
||||
{
|
||||
CS_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR16::writeCommand(uint8_t c)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR16::writeCommand16(uint16_t c)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE16(c);
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR16::writeCommandBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
while (len--)
|
||||
{
|
||||
WRITE(*data++);
|
||||
}
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR16::write(uint8_t d)
|
||||
{
|
||||
WRITE(d);
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR16::write16(uint16_t d)
|
||||
{
|
||||
WRITE16(d);
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR16::writeRepeat(uint16_t p, uint32_t len)
|
||||
{
|
||||
_data16.value = p;
|
||||
uint32_t d1 = _xset_mask1_hi[_data16.msb] | _xset_mask1_lo[_data16.lsb];
|
||||
uint32_t d2 = _xset_mask2_hi[_data16.msb] | _xset_mask2_lo[_data16.lsb];
|
||||
*_data1PortClr = _data1ClrMask;
|
||||
*_data2PortClr = _data2ClrMask;
|
||||
*_data1PortSet = d1;
|
||||
*_data2PortSet = d2;
|
||||
while (len--)
|
||||
{
|
||||
*_wrPortClr = _wrPinMask;
|
||||
*_wrPortSet = _wrPinMask;
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR16::writePixels(uint16_t *data, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
WRITE16(*data++);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR16::writeC8D8(uint8_t c, uint8_t d)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
WRITE(d);
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR16::writeC8D16(uint8_t c, uint16_t d)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
WRITE16(d);
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR16::writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
WRITE16(d1);
|
||||
WRITE16(d2);
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR16::writeC8D16D16Split(uint8_t c, uint16_t d1, uint16_t d2)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
_data16.value = d1;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
|
||||
_data16.value = d2;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR16::writeBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
while (len > 1)
|
||||
{
|
||||
_data16.msb = *data++;
|
||||
_data16.lsb = *data++;
|
||||
WRITE16(_data16.value);
|
||||
len -= 2;
|
||||
}
|
||||
if (len)
|
||||
{
|
||||
WRITE(*data);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR16::writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
WRITE16(idx[*data++]);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR16::writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
_data16.value = idx[*data++];
|
||||
*_data1PortClr = _data1ClrMask;
|
||||
*_data2PortClr = _data2ClrMask;
|
||||
*_data1PortSet = _xset_mask1_hi[_data16.msb] | _xset_mask1_lo[_data16.lsb];
|
||||
*_data2PortSet = _xset_mask2_hi[_data16.msb] | _xset_mask2_lo[_data16.lsb];
|
||||
*_wrPortClr = _wrPinMask;
|
||||
*_wrPortSet = _wrPinMask;
|
||||
*_wrPortClr = _wrPinMask;
|
||||
*_wrPortSet = _wrPinMask;
|
||||
}
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP32PAR16::WRITE(uint8_t d)
|
||||
{
|
||||
*_data1PortClr = _data1ClrMask;
|
||||
*_data2PortClr = _data2ClrMask;
|
||||
*_data1PortSet = _xset_mask1_lo[d];
|
||||
*_data2PortSet = _xset_mask2_lo[d];
|
||||
*_wrPortClr = _wrPinMask;
|
||||
*_wrPortSet = _wrPinMask;
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP32PAR16::WRITE16(uint16_t d)
|
||||
{
|
||||
_data16.value = d;
|
||||
uint32_t d1 = _xset_mask1_hi[_data16.msb] | _xset_mask1_lo[_data16.lsb];
|
||||
uint32_t d2 = _xset_mask2_hi[_data16.msb] | _xset_mask2_lo[_data16.lsb];
|
||||
*_data1PortClr = _data1ClrMask;
|
||||
*_data2PortClr = _data2ClrMask;
|
||||
*_data1PortSet = d1;
|
||||
*_data2PortSet = d2;
|
||||
*_wrPortClr = _wrPinMask;
|
||||
*_wrPortSet = _wrPinMask;
|
||||
}
|
||||
|
||||
/******** low level bit twiddling **********/
|
||||
|
||||
GFX_INLINE void Arduino_ESP32PAR16::DC_HIGH(void)
|
||||
{
|
||||
*_dcPortSet = _dcPinMask;
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP32PAR16::DC_LOW(void)
|
||||
{
|
||||
*_dcPortClr = _dcPinMask;
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP32PAR16::CS_HIGH(void)
|
||||
{
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
*_csPortSet = _csPinMask;
|
||||
}
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP32PAR16::CS_LOW(void)
|
||||
{
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
*_csPortClr = _csPinMask;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // #if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
|
||||
@@ -0,0 +1,76 @@
|
||||
#include "Arduino_DataBus.h"
|
||||
|
||||
#if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
|
||||
|
||||
#ifndef _ARDUINO_ESP32PAR16_H_
|
||||
#define _ARDUINO_ESP32PAR16_H_
|
||||
|
||||
class Arduino_ESP32PAR16 : public Arduino_DataBus
|
||||
{
|
||||
public:
|
||||
Arduino_ESP32PAR16(
|
||||
int8_t dc, int8_t cs, int8_t wr, int8_t rd,
|
||||
int8_t d0, int8_t d1, int8_t d2, int8_t d3, int8_t d4, int8_t d5, int8_t d6, int8_t d7,
|
||||
int8_t d8, int8_t d9, int8_t d10, int8_t d11, int8_t d12, int8_t d13, int8_t d14, int8_t d15); // Constructor
|
||||
|
||||
bool begin(int32_t speed = GFX_NOT_DEFINED, int8_t dataMode = GFX_NOT_DEFINED) override;
|
||||
void beginWrite() override;
|
||||
void endWrite() override;
|
||||
void writeCommand(uint8_t) override;
|
||||
void writeCommand16(uint16_t) override;
|
||||
void writeCommandBytes(uint8_t *data, uint32_t len) override;
|
||||
void write(uint8_t) override;
|
||||
void write16(uint16_t) override;
|
||||
void writeRepeat(uint16_t p, uint32_t len) override;
|
||||
void writePixels(uint16_t *data, uint32_t len) override;
|
||||
|
||||
void writeC8D8(uint8_t c, uint8_t d) override;
|
||||
void writeC8D16(uint8_t c, uint16_t d) override;
|
||||
void writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2) override;
|
||||
void writeC8D16D16Split(uint8_t c, uint16_t d1, uint16_t d2) override;
|
||||
void writeBytes(uint8_t *data, uint32_t len) override;
|
||||
|
||||
void writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len) override;
|
||||
void writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len) override;
|
||||
|
||||
protected:
|
||||
private:
|
||||
GFX_INLINE void WRITE(uint8_t d);
|
||||
GFX_INLINE void WRITE16(uint16_t d);
|
||||
GFX_INLINE void DC_HIGH(void);
|
||||
GFX_INLINE void DC_LOW(void);
|
||||
GFX_INLINE void CS_HIGH(void);
|
||||
GFX_INLINE void CS_LOW(void);
|
||||
|
||||
int8_t _dc, _cs, _wr, _rd;
|
||||
int8_t _d0, _d1, _d2, _d3, _d4, _d5, _d6, _d7;
|
||||
int8_t _d8, _d9, _d10, _d11, _d12, _d13, _d14, _d15;
|
||||
|
||||
PORTreg_t _dcPortSet; ///< PORT register SET
|
||||
PORTreg_t _dcPortClr; ///< PORT register CLEAR
|
||||
uint32_t _dcPinMask; ///< Bitmask
|
||||
|
||||
PORTreg_t _csPortSet; ///< PORT register SET
|
||||
PORTreg_t _csPortClr; ///< PORT register CLEAR
|
||||
uint32_t _csPinMask; ///< Bitmask
|
||||
|
||||
PORTreg_t _wrPortSet; ///< PORT register SET
|
||||
PORTreg_t _wrPortClr; ///< PORT register CLEAR
|
||||
uint32_t _wrPinMask; ///< Bitmask
|
||||
|
||||
PORTreg_t _data1PortSet;
|
||||
PORTreg_t _data1PortClr;
|
||||
uint32_t _data1ClrMask;
|
||||
PORTreg_t _data2PortSet;
|
||||
PORTreg_t _data2PortClr;
|
||||
uint32_t _data2ClrMask;
|
||||
// Lookup table for ESP32 parallel bus interface uses 4kbyte RAM
|
||||
uint32_t _xset_mask1_lo[256];
|
||||
uint32_t _xset_mask1_hi[256];
|
||||
uint32_t _xset_mask2_lo[256];
|
||||
uint32_t _xset_mask2_hi[256];
|
||||
};
|
||||
|
||||
#endif // _ARDUINO_ESP32PAR16_H_
|
||||
|
||||
#endif // #if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
|
||||
@@ -0,0 +1,375 @@
|
||||
#include "Arduino_ESP32PAR16Q.h"
|
||||
|
||||
#if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
|
||||
|
||||
Arduino_ESP32PAR16Q::Arduino_ESP32PAR16Q(
|
||||
int8_t dc, int8_t cs, int8_t wr, int8_t rd,
|
||||
int8_t d0, int8_t d1, int8_t d2, int8_t d3, int8_t d4, int8_t d5, int8_t d6, int8_t d7,
|
||||
int8_t d8, int8_t d9, int8_t d10, int8_t d11, int8_t d12, int8_t d13, int8_t d14, int8_t d15)
|
||||
: _dc(dc), _cs(cs), _wr(wr), _rd(rd),
|
||||
_d0(d0), _d1(d1), _d2(d2), _d3(d3), _d4(d4), _d5(d5), _d6(d6), _d7(d7),
|
||||
_d8(d8), _d9(d9), _d10(d10), _d11(d11), _d12(d12), _d13(d13), _d14(d14), _d15(d15)
|
||||
{
|
||||
}
|
||||
|
||||
bool Arduino_ESP32PAR16Q::begin(int32_t, int8_t)
|
||||
{
|
||||
pinMode(_dc, OUTPUT);
|
||||
digitalWrite(_dc, HIGH); // Data mode
|
||||
if (_dc >= 32)
|
||||
{
|
||||
_dcPinMask = digitalPinToBitMask(_dc);
|
||||
_dcPortSet = (PORTreg_t)GPIO_OUT1_W1TS_REG;
|
||||
_dcPortClr = (PORTreg_t)GPIO_OUT1_W1TC_REG;
|
||||
}
|
||||
else
|
||||
{
|
||||
_dcPinMask = digitalPinToBitMask(_dc);
|
||||
_dcPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_dcPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
}
|
||||
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
pinMode(_cs, OUTPUT);
|
||||
digitalWrite(_cs, HIGH); // disable chip select
|
||||
}
|
||||
if (_cs >= 32)
|
||||
{
|
||||
_csPinMask = digitalPinToBitMask(_cs);
|
||||
_csPortSet = (PORTreg_t)GPIO_OUT1_W1TS_REG;
|
||||
_csPortClr = (PORTreg_t)GPIO_OUT1_W1TC_REG;
|
||||
}
|
||||
else if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
_csPinMask = digitalPinToBitMask(_cs);
|
||||
_csPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_csPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
}
|
||||
|
||||
pinMode(_wr, OUTPUT);
|
||||
digitalWrite(_wr, HIGH); // Set write strobe high (inactive)
|
||||
if (_wr >= 32)
|
||||
{
|
||||
_wrPinMask = digitalPinToBitMask(_wr);
|
||||
_wrPortSet = (PORTreg_t)GPIO_OUT1_W1TS_REG;
|
||||
_wrPortClr = (PORTreg_t)GPIO_OUT1_W1TC_REG;
|
||||
}
|
||||
else
|
||||
{
|
||||
_wrPinMask = digitalPinToBitMask(_wr);
|
||||
_wrPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_wrPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
}
|
||||
|
||||
if (_rd != GFX_NOT_DEFINED)
|
||||
{
|
||||
pinMode(_rd, OUTPUT);
|
||||
digitalWrite(_rd, HIGH);
|
||||
}
|
||||
|
||||
// TODO: check pin range 0-31
|
||||
pinMode(_d0, OUTPUT);
|
||||
pinMode(_d1, OUTPUT);
|
||||
pinMode(_d2, OUTPUT);
|
||||
pinMode(_d3, OUTPUT);
|
||||
pinMode(_d4, OUTPUT);
|
||||
pinMode(_d5, OUTPUT);
|
||||
pinMode(_d6, OUTPUT);
|
||||
pinMode(_d7, OUTPUT);
|
||||
pinMode(_d8, OUTPUT);
|
||||
pinMode(_d9, OUTPUT);
|
||||
pinMode(_d10, OUTPUT);
|
||||
pinMode(_d11, OUTPUT);
|
||||
pinMode(_d12, OUTPUT);
|
||||
pinMode(_d13, OUTPUT);
|
||||
pinMode(_d14, OUTPUT);
|
||||
pinMode(_d15, OUTPUT);
|
||||
|
||||
_dataPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_dataPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
|
||||
// INIT 16-bit mask
|
||||
_dataClrMask = (1 << _wr) | (1 << _d0) | (1 << _d1) | (1 << _d2) | (1 << _d3) | (1 << _d4) | (1 << _d5) | (1 << _d6) | (1 << _d7) | (1 << _d8) | (1 << _d9) | (1 << _d10) | (1 << _d11) | (1 << _d12) | (1 << _d13) | (1 << _d14) | (1 << _d15);
|
||||
for (int32_t c = 0; c < 256; c++)
|
||||
{
|
||||
_xset_mask_lo[c] = 0;
|
||||
if (c & 0x01)
|
||||
{
|
||||
_xset_mask_lo[c] |= (1 << _d0);
|
||||
}
|
||||
if (c & 0x02)
|
||||
{
|
||||
_xset_mask_lo[c] |= (1 << _d1);
|
||||
}
|
||||
if (c & 0x04)
|
||||
{
|
||||
_xset_mask_lo[c] |= (1 << _d2);
|
||||
}
|
||||
if (c & 0x08)
|
||||
{
|
||||
_xset_mask_lo[c] |= (1 << _d3);
|
||||
}
|
||||
if (c & 0x10)
|
||||
{
|
||||
_xset_mask_lo[c] |= (1 << _d4);
|
||||
}
|
||||
if (c & 0x20)
|
||||
{
|
||||
_xset_mask_lo[c] |= (1 << _d5);
|
||||
}
|
||||
if (c & 0x40)
|
||||
{
|
||||
_xset_mask_lo[c] |= (1 << _d6);
|
||||
}
|
||||
if (c & 0x80)
|
||||
{
|
||||
_xset_mask_lo[c] |= (1 << _d7);
|
||||
}
|
||||
}
|
||||
for (int32_t c = 0; c < 256; c++)
|
||||
{
|
||||
_xset_mask_hi[c] = 0;
|
||||
if (c & 0x01)
|
||||
{
|
||||
_xset_mask_hi[c] |= (1 << _d8);
|
||||
}
|
||||
if (c & 0x02)
|
||||
{
|
||||
_xset_mask_hi[c] |= (1 << _d9);
|
||||
}
|
||||
if (c & 0x04)
|
||||
{
|
||||
_xset_mask_hi[c] |= (1 << _d10);
|
||||
}
|
||||
if (c & 0x08)
|
||||
{
|
||||
_xset_mask_hi[c] |= (1 << _d11);
|
||||
}
|
||||
if (c & 0x10)
|
||||
{
|
||||
_xset_mask_hi[c] |= (1 << _d12);
|
||||
}
|
||||
if (c & 0x20)
|
||||
{
|
||||
_xset_mask_hi[c] |= (1 << _d13);
|
||||
}
|
||||
if (c & 0x40)
|
||||
{
|
||||
_xset_mask_hi[c] |= (1 << _d14);
|
||||
}
|
||||
if (c & 0x80)
|
||||
{
|
||||
_xset_mask_hi[c] |= (1 << _d15);
|
||||
}
|
||||
}
|
||||
_dataPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_dataPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
*_dataPortClr = _dataClrMask;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR16Q::beginWrite()
|
||||
{
|
||||
DC_HIGH();
|
||||
CS_LOW();
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR16Q::endWrite()
|
||||
{
|
||||
CS_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR16Q::writeCommand(uint8_t c)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR16Q::writeCommand16(uint16_t c)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE16(c);
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR16Q::writeCommandBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
while (len--)
|
||||
{
|
||||
WRITE(*data++);
|
||||
}
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR16Q::write(uint8_t d)
|
||||
{
|
||||
WRITE(d);
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR16Q::write16(uint16_t d)
|
||||
{
|
||||
WRITE16(d);
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR16Q::writeRepeat(uint16_t p, uint32_t len)
|
||||
{
|
||||
_data16.value = p;
|
||||
uint32_t d = _xset_mask_hi[_data16.msb] | _xset_mask_lo[_data16.lsb];
|
||||
*_dataPortClr = _dataClrMask;
|
||||
*_dataPortSet = d;
|
||||
while (len--)
|
||||
{
|
||||
*_wrPortClr = _wrPinMask;
|
||||
*_wrPortSet = _wrPinMask;
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR16Q::writePixels(uint16_t *data, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
WRITE16(*data++);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR16Q::writeC8D8(uint8_t c, uint8_t d)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
WRITE(d);
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR16Q::writeC8D16(uint8_t c, uint16_t d)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
WRITE16(d);
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR16Q::writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
WRITE16(d1);
|
||||
WRITE16(d2);
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR16Q::writeC8D16D16Split(uint8_t c, uint16_t d1, uint16_t d2)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
_data16.value = d1;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
|
||||
_data16.value = d2;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR16Q::writeBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
while (len > 1)
|
||||
{
|
||||
_data16.msb = *data++;
|
||||
_data16.lsb = *data++;
|
||||
WRITE16(_data16.value);
|
||||
len -= 2;
|
||||
}
|
||||
if (len)
|
||||
{
|
||||
WRITE(*data);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR16Q::writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
WRITE16(idx[*data++]);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR16Q::writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
_data16.value = idx[*data++];
|
||||
*_dataPortClr = _dataClrMask;
|
||||
*_dataPortSet = _xset_mask_hi[_data16.msb] | _xset_mask_lo[_data16.lsb];
|
||||
*_wrPortSet = _wrPinMask;
|
||||
*_wrPortClr = _wrPinMask;
|
||||
*_wrPortSet = _wrPinMask;
|
||||
}
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP32PAR16Q::WRITE(uint8_t d)
|
||||
{
|
||||
*_dataPortClr = _dataClrMask;
|
||||
*_dataPortSet = _xset_mask_lo[d];
|
||||
*_wrPortSet = _wrPinMask;
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP32PAR16Q::WRITE16(uint16_t d)
|
||||
{
|
||||
_data16.value = d;
|
||||
*_dataPortClr = _dataClrMask;
|
||||
*_dataPortSet = _xset_mask_hi[_data16.msb] | _xset_mask_lo[_data16.lsb];
|
||||
*_wrPortSet = _wrPinMask;
|
||||
}
|
||||
|
||||
/******** low level bit twiddling **********/
|
||||
|
||||
GFX_INLINE void Arduino_ESP32PAR16Q::DC_HIGH(void)
|
||||
{
|
||||
*_dcPortSet = _dcPinMask;
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP32PAR16Q::DC_LOW(void)
|
||||
{
|
||||
*_dcPortClr = _dcPinMask;
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP32PAR16Q::CS_HIGH(void)
|
||||
{
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
*_csPortSet = _csPinMask;
|
||||
}
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP32PAR16Q::CS_LOW(void)
|
||||
{
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
*_csPortClr = _csPinMask;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // #if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
|
||||
@@ -0,0 +1,71 @@
|
||||
#include "Arduino_DataBus.h"
|
||||
|
||||
#if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
|
||||
|
||||
#ifndef _ARDUINO_ESP32PAR16Q_H_
|
||||
#define _ARDUINO_ESP32PAR16Q_H_
|
||||
|
||||
class Arduino_ESP32PAR16Q : public Arduino_DataBus
|
||||
{
|
||||
public:
|
||||
Arduino_ESP32PAR16Q(
|
||||
int8_t dc, int8_t cs, int8_t wr, int8_t rd,
|
||||
int8_t d0, int8_t d1, int8_t d2, int8_t d3, int8_t d4, int8_t d5, int8_t d6, int8_t d7,
|
||||
int8_t d8, int8_t d9, int8_t d10, int8_t d11, int8_t d12, int8_t d13, int8_t d14, int8_t d15); // Constructor
|
||||
|
||||
bool begin(int32_t speed = GFX_NOT_DEFINED, int8_t dataMode = GFX_NOT_DEFINED) override;
|
||||
void beginWrite() override;
|
||||
void endWrite() override;
|
||||
void writeCommand(uint8_t) override;
|
||||
void writeCommand16(uint16_t) override;
|
||||
void writeCommandBytes(uint8_t *data, uint32_t len) override;
|
||||
void write(uint8_t) override;
|
||||
void write16(uint16_t) override;
|
||||
void writeRepeat(uint16_t p, uint32_t len) override;
|
||||
void writePixels(uint16_t *data, uint32_t len) override;
|
||||
|
||||
void writeC8D8(uint8_t c, uint8_t d) override;
|
||||
void writeC8D16(uint8_t c, uint16_t d) override;
|
||||
void writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2) override;
|
||||
void writeC8D16D16Split(uint8_t c, uint16_t d1, uint16_t d2) override;
|
||||
void writeBytes(uint8_t *data, uint32_t len) override;
|
||||
|
||||
void writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len) override;
|
||||
void writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len) override;
|
||||
|
||||
protected:
|
||||
private:
|
||||
GFX_INLINE void WRITE(uint8_t d);
|
||||
GFX_INLINE void WRITE16(uint16_t d);
|
||||
GFX_INLINE void DC_HIGH(void);
|
||||
GFX_INLINE void DC_LOW(void);
|
||||
GFX_INLINE void CS_HIGH(void);
|
||||
GFX_INLINE void CS_LOW(void);
|
||||
|
||||
int8_t _dc, _cs, _wr, _rd;
|
||||
int8_t _d0, _d1, _d2, _d3, _d4, _d5, _d6, _d7;
|
||||
int8_t _d8, _d9, _d10, _d11, _d12, _d13, _d14, _d15;
|
||||
|
||||
PORTreg_t _dcPortSet; ///< PORT register SET
|
||||
PORTreg_t _dcPortClr; ///< PORT register CLEAR
|
||||
uint32_t _dcPinMask; ///< Bitmask
|
||||
|
||||
PORTreg_t _csPortSet; ///< PORT register SET
|
||||
PORTreg_t _csPortClr; ///< PORT register CLEAR
|
||||
uint32_t _csPinMask; ///< Bitmask
|
||||
|
||||
PORTreg_t _wrPortSet; ///< PORT register SET
|
||||
PORTreg_t _wrPortClr; ///< PORT register CLEAR
|
||||
uint32_t _wrPinMask; ///< Bitmask
|
||||
|
||||
PORTreg_t _dataPortSet;
|
||||
PORTreg_t _dataPortClr;
|
||||
uint32_t _dataClrMask;
|
||||
// Lookup table for ESP32 parallel bus interface uses 2kbyte RAM,
|
||||
uint32_t _xset_mask_lo[256];
|
||||
uint32_t _xset_mask_hi[256];
|
||||
};
|
||||
|
||||
#endif // _ARDUINO_ESP32PAR16Q_H_
|
||||
|
||||
#endif // #if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
|
||||
@@ -0,0 +1,370 @@
|
||||
#include "Arduino_ESP32PAR16QQ.h"
|
||||
|
||||
#if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
|
||||
|
||||
Arduino_ESP32PAR16QQ::Arduino_ESP32PAR16QQ(
|
||||
int8_t dc, int8_t cs, int8_t wr, int8_t rd,
|
||||
int8_t d0, int8_t d1, int8_t d2, int8_t d3, int8_t d4, int8_t d5, int8_t d6, int8_t d7,
|
||||
int8_t d8, int8_t d9, int8_t d10, int8_t d11, int8_t d12, int8_t d13, int8_t d14, int8_t d15)
|
||||
: _dc(dc), _cs(cs), _wr(wr), _rd(rd),
|
||||
_d0(d0), _d1(d1), _d2(d2), _d3(d3), _d4(d4), _d5(d5), _d6(d6), _d7(d7),
|
||||
_d8(d8), _d9(d9), _d10(d10), _d11(d11), _d12(d12), _d13(d13), _d14(d14), _d15(d15)
|
||||
{
|
||||
}
|
||||
|
||||
bool Arduino_ESP32PAR16QQ::begin(int32_t, int8_t)
|
||||
{
|
||||
pinMode(_dc, OUTPUT);
|
||||
digitalWrite(_dc, HIGH); // Data mode
|
||||
if (_dc >= 32)
|
||||
{
|
||||
_dcPinMask = digitalPinToBitMask(_dc);
|
||||
_dcPortSet = (PORTreg_t)GPIO_OUT1_W1TS_REG;
|
||||
_dcPortClr = (PORTreg_t)GPIO_OUT1_W1TC_REG;
|
||||
}
|
||||
else
|
||||
{
|
||||
_dcPinMask = digitalPinToBitMask(_dc);
|
||||
_dcPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_dcPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
}
|
||||
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
pinMode(_cs, OUTPUT);
|
||||
digitalWrite(_cs, HIGH); // disable chip select
|
||||
}
|
||||
if (_cs >= 32)
|
||||
{
|
||||
_csPinMask = digitalPinToBitMask(_cs);
|
||||
_csPortSet = (PORTreg_t)GPIO_OUT1_W1TS_REG;
|
||||
_csPortClr = (PORTreg_t)GPIO_OUT1_W1TC_REG;
|
||||
}
|
||||
else if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
_csPinMask = digitalPinToBitMask(_cs);
|
||||
_csPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_csPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
}
|
||||
|
||||
pinMode(_wr, OUTPUT);
|
||||
digitalWrite(_wr, HIGH); // Set write strobe high (inactive)
|
||||
if (_wr >= 32)
|
||||
{
|
||||
_wrPinMask = digitalPinToBitMask(_wr);
|
||||
_wrPortSet = (PORTreg_t)GPIO_OUT1_W1TS_REG;
|
||||
_wrPortClr = (PORTreg_t)GPIO_OUT1_W1TC_REG;
|
||||
}
|
||||
else
|
||||
{
|
||||
_wrPinMask = digitalPinToBitMask(_wr);
|
||||
_wrPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_wrPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
}
|
||||
|
||||
if (_rd != GFX_NOT_DEFINED)
|
||||
{
|
||||
pinMode(_rd, OUTPUT);
|
||||
digitalWrite(_rd, HIGH);
|
||||
}
|
||||
|
||||
// TODO: check pin range 0-31
|
||||
pinMode(_d0, OUTPUT);
|
||||
pinMode(_d1, OUTPUT);
|
||||
pinMode(_d2, OUTPUT);
|
||||
pinMode(_d3, OUTPUT);
|
||||
pinMode(_d4, OUTPUT);
|
||||
pinMode(_d5, OUTPUT);
|
||||
pinMode(_d6, OUTPUT);
|
||||
pinMode(_d7, OUTPUT);
|
||||
pinMode(_d8, OUTPUT);
|
||||
pinMode(_d9, OUTPUT);
|
||||
pinMode(_d10, OUTPUT);
|
||||
pinMode(_d11, OUTPUT);
|
||||
pinMode(_d12, OUTPUT);
|
||||
pinMode(_d13, OUTPUT);
|
||||
pinMode(_d14, OUTPUT);
|
||||
pinMode(_d15, OUTPUT);
|
||||
|
||||
_dataPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_dataPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
|
||||
// INIT 16-bit mask
|
||||
_dataClrMask = (1 << _wr) | (1 << _d0) | (1 << _d1) | (1 << _d2) | (1 << _d3) | (1 << _d4) | (1 << _d5) | (1 << _d6) | (1 << _d7) | (1 << _d8) | (1 << _d9) | (1 << _d10) | (1 << _d11) | (1 << _d12) | (1 << _d13) | (1 << _d14) | (1 << _d15);
|
||||
for (int32_t c = 0; c < 256; c++)
|
||||
{
|
||||
_xset_mask_lo[c] = (1 << _wr);
|
||||
if (c & 0x01)
|
||||
{
|
||||
_xset_mask_lo[c] |= (1 << _d0);
|
||||
}
|
||||
if (c & 0x02)
|
||||
{
|
||||
_xset_mask_lo[c] |= (1 << _d1);
|
||||
}
|
||||
if (c & 0x04)
|
||||
{
|
||||
_xset_mask_lo[c] |= (1 << _d2);
|
||||
}
|
||||
if (c & 0x08)
|
||||
{
|
||||
_xset_mask_lo[c] |= (1 << _d3);
|
||||
}
|
||||
if (c & 0x10)
|
||||
{
|
||||
_xset_mask_lo[c] |= (1 << _d4);
|
||||
}
|
||||
if (c & 0x20)
|
||||
{
|
||||
_xset_mask_lo[c] |= (1 << _d5);
|
||||
}
|
||||
if (c & 0x40)
|
||||
{
|
||||
_xset_mask_lo[c] |= (1 << _d6);
|
||||
}
|
||||
if (c & 0x80)
|
||||
{
|
||||
_xset_mask_lo[c] |= (1 << _d7);
|
||||
}
|
||||
}
|
||||
for (int32_t c = 0; c < 256; c++)
|
||||
{
|
||||
_xset_mask_hi[c] = 0;
|
||||
if (c & 0x01)
|
||||
{
|
||||
_xset_mask_hi[c] |= (1 << _d8);
|
||||
}
|
||||
if (c & 0x02)
|
||||
{
|
||||
_xset_mask_hi[c] |= (1 << _d9);
|
||||
}
|
||||
if (c & 0x04)
|
||||
{
|
||||
_xset_mask_hi[c] |= (1 << _d10);
|
||||
}
|
||||
if (c & 0x08)
|
||||
{
|
||||
_xset_mask_hi[c] |= (1 << _d11);
|
||||
}
|
||||
if (c & 0x10)
|
||||
{
|
||||
_xset_mask_hi[c] |= (1 << _d12);
|
||||
}
|
||||
if (c & 0x20)
|
||||
{
|
||||
_xset_mask_hi[c] |= (1 << _d13);
|
||||
}
|
||||
if (c & 0x40)
|
||||
{
|
||||
_xset_mask_hi[c] |= (1 << _d14);
|
||||
}
|
||||
if (c & 0x80)
|
||||
{
|
||||
_xset_mask_hi[c] |= (1 << _d15);
|
||||
}
|
||||
}
|
||||
_dataPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_dataPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
*_dataPortClr = _dataClrMask;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR16QQ::beginWrite()
|
||||
{
|
||||
DC_HIGH();
|
||||
CS_LOW();
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR16QQ::endWrite()
|
||||
{
|
||||
CS_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR16QQ::writeCommand(uint8_t c)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR16QQ::writeCommand16(uint16_t c)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE16(c);
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR16QQ::writeCommandBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
while (len--)
|
||||
{
|
||||
WRITE(*data++);
|
||||
}
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR16QQ::write(uint8_t d)
|
||||
{
|
||||
WRITE(d);
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR16QQ::write16(uint16_t d)
|
||||
{
|
||||
WRITE16(d);
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR16QQ::writeRepeat(uint16_t p, uint32_t len)
|
||||
{
|
||||
_data16.value = p;
|
||||
uint32_t d = _xset_mask_hi[_data16.msb] | _xset_mask_lo[_data16.lsb];
|
||||
while (len--)
|
||||
{
|
||||
*_dataPortClr = _dataClrMask;
|
||||
*_dataPortSet = d;
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR16QQ::writePixels(uint16_t *data, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
WRITE16(*data++);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR16QQ::writeC8D8(uint8_t c, uint8_t d)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
WRITE(d);
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR16QQ::writeC8D16(uint8_t c, uint16_t d)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
WRITE16(d);
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR16QQ::writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
WRITE16(d1);
|
||||
WRITE16(d2);
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR16QQ::writeC8D16D16Split(uint8_t c, uint16_t d1, uint16_t d2)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
_data16.value = d1;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
|
||||
_data16.value = d2;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR16QQ::writeBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
while (len > 1)
|
||||
{
|
||||
_data16.msb = *data++;
|
||||
_data16.lsb = *data++;
|
||||
WRITE16(_data16.value);
|
||||
len -= 2;
|
||||
}
|
||||
if (len)
|
||||
{
|
||||
WRITE(*data);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR16QQ::writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
WRITE16(idx[*data++]);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR16QQ::writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
_data16.value = idx[*data++];
|
||||
*_dataPortClr = _dataClrMask;
|
||||
*_dataPortSet = _xset_mask_hi[_data16.msb] | _xset_mask_lo[_data16.lsb];
|
||||
*_wrPortClr = _wrPinMask;
|
||||
*_wrPortSet = _wrPinMask;
|
||||
}
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP32PAR16QQ::WRITE(uint8_t d)
|
||||
{
|
||||
*_dataPortClr = _dataClrMask;
|
||||
*_dataPortSet = _xset_mask_lo[d];
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP32PAR16QQ::WRITE16(uint16_t d)
|
||||
{
|
||||
_data16.value = d;
|
||||
*_dataPortClr = _dataClrMask;
|
||||
*_dataPortSet = _xset_mask_hi[_data16.msb] | _xset_mask_lo[_data16.lsb];
|
||||
}
|
||||
|
||||
/******** low level bit twiddling **********/
|
||||
|
||||
GFX_INLINE void Arduino_ESP32PAR16QQ::DC_HIGH(void)
|
||||
{
|
||||
*_dcPortSet = _dcPinMask;
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP32PAR16QQ::DC_LOW(void)
|
||||
{
|
||||
*_dcPortClr = _dcPinMask;
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP32PAR16QQ::CS_HIGH(void)
|
||||
{
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
*_csPortSet = _csPinMask;
|
||||
}
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP32PAR16QQ::CS_LOW(void)
|
||||
{
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
*_csPortClr = _csPinMask;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // #if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
|
||||
@@ -0,0 +1,71 @@
|
||||
#include "Arduino_DataBus.h"
|
||||
|
||||
#if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
|
||||
|
||||
#ifndef _ARDUINO_ESP32PAR16QQ_H_
|
||||
#define _ARDUINO_ESP32PAR16QQ_H_
|
||||
|
||||
class Arduino_ESP32PAR16QQ : public Arduino_DataBus
|
||||
{
|
||||
public:
|
||||
Arduino_ESP32PAR16QQ(
|
||||
int8_t dc, int8_t cs, int8_t wr, int8_t rd,
|
||||
int8_t d0, int8_t d1, int8_t d2, int8_t d3, int8_t d4, int8_t d5, int8_t d6, int8_t d7,
|
||||
int8_t d8, int8_t d9, int8_t d10, int8_t d11, int8_t d12, int8_t d13, int8_t d14, int8_t d15); // Constructor
|
||||
|
||||
bool begin(int32_t speed = GFX_NOT_DEFINED, int8_t dataMode = GFX_NOT_DEFINED) override;
|
||||
void beginWrite() override;
|
||||
void endWrite() override;
|
||||
void writeCommand(uint8_t) override;
|
||||
void writeCommand16(uint16_t) override;
|
||||
void writeCommandBytes(uint8_t *data, uint32_t len) override;
|
||||
void write(uint8_t) override;
|
||||
void write16(uint16_t) override;
|
||||
void writeRepeat(uint16_t p, uint32_t len) override;
|
||||
void writePixels(uint16_t *data, uint32_t len) override;
|
||||
|
||||
void writeC8D8(uint8_t c, uint8_t d) override;
|
||||
void writeC8D16(uint8_t c, uint16_t d) override;
|
||||
void writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2) override;
|
||||
void writeC8D16D16Split(uint8_t c, uint16_t d1, uint16_t d2) override;
|
||||
void writeBytes(uint8_t *data, uint32_t len) override;
|
||||
|
||||
void writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len) override;
|
||||
void writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len) override;
|
||||
|
||||
protected:
|
||||
private:
|
||||
GFX_INLINE void WRITE(uint8_t d);
|
||||
GFX_INLINE void WRITE16(uint16_t d);
|
||||
GFX_INLINE void DC_HIGH(void);
|
||||
GFX_INLINE void DC_LOW(void);
|
||||
GFX_INLINE void CS_HIGH(void);
|
||||
GFX_INLINE void CS_LOW(void);
|
||||
|
||||
int8_t _dc, _cs, _wr, _rd;
|
||||
int8_t _d0, _d1, _d2, _d3, _d4, _d5, _d6, _d7;
|
||||
int8_t _d8, _d9, _d10, _d11, _d12, _d13, _d14, _d15;
|
||||
|
||||
PORTreg_t _dcPortSet; ///< PORT register SET
|
||||
PORTreg_t _dcPortClr; ///< PORT register CLEAR
|
||||
uint32_t _dcPinMask; ///< Bitmask
|
||||
|
||||
PORTreg_t _csPortSet; ///< PORT register SET
|
||||
PORTreg_t _csPortClr; ///< PORT register CLEAR
|
||||
uint32_t _csPinMask; ///< Bitmask
|
||||
|
||||
PORTreg_t _wrPortSet; ///< PORT register SET
|
||||
PORTreg_t _wrPortClr; ///< PORT register CLEAR
|
||||
uint32_t _wrPinMask; ///< Bitmask
|
||||
|
||||
PORTreg_t _dataPortSet;
|
||||
PORTreg_t _dataPortClr;
|
||||
uint32_t _dataClrMask;
|
||||
// Lookup table for ESP32 parallel bus interface uses 2kbyte RAM,
|
||||
uint32_t _xset_mask_lo[256];
|
||||
uint32_t _xset_mask_hi[256];
|
||||
};
|
||||
|
||||
#endif // _ARDUINO_ESP32PAR16QQ_H_
|
||||
|
||||
#endif // #if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
|
||||
@@ -0,0 +1,487 @@
|
||||
#include "Arduino_ESP32PAR8.h"
|
||||
|
||||
#if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
|
||||
|
||||
Arduino_ESP32PAR8::Arduino_ESP32PAR8(
|
||||
int8_t dc, int8_t cs, int8_t wr, int8_t rd,
|
||||
int8_t d0, int8_t d1, int8_t d2, int8_t d3, int8_t d4, int8_t d5, int8_t d6, int8_t d7)
|
||||
: _dc(dc), _cs(cs), _wr(wr), _rd(rd),
|
||||
_d0(d0), _d1(d1), _d2(d2), _d3(d3), _d4(d4), _d5(d5), _d6(d6), _d7(d7)
|
||||
{
|
||||
}
|
||||
|
||||
bool Arduino_ESP32PAR8::begin(int32_t, int8_t)
|
||||
{
|
||||
pinMode(_dc, OUTPUT);
|
||||
digitalWrite(_dc, HIGH); // Data mode
|
||||
if (_dc >= 32)
|
||||
{
|
||||
_dcPinMask = digitalPinToBitMask(_dc);
|
||||
_dcPortSet = (PORTreg_t)GPIO_OUT1_W1TS_REG;
|
||||
_dcPortClr = (PORTreg_t)GPIO_OUT1_W1TC_REG;
|
||||
}
|
||||
else
|
||||
{
|
||||
_dcPinMask = digitalPinToBitMask(_dc);
|
||||
_dcPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_dcPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
}
|
||||
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
pinMode(_cs, OUTPUT);
|
||||
digitalWrite(_cs, HIGH); // disable chip select
|
||||
}
|
||||
if (_cs >= 32)
|
||||
{
|
||||
_csPinMask = digitalPinToBitMask(_cs);
|
||||
_csPortSet = (PORTreg_t)GPIO_OUT1_W1TS_REG;
|
||||
_csPortClr = (PORTreg_t)GPIO_OUT1_W1TC_REG;
|
||||
}
|
||||
else if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
_csPinMask = digitalPinToBitMask(_cs);
|
||||
_csPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_csPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
}
|
||||
|
||||
pinMode(_wr, OUTPUT);
|
||||
digitalWrite(_wr, HIGH); // Set write strobe high (inactive)
|
||||
if (_wr >= 32)
|
||||
{
|
||||
_wrPinMask = digitalPinToBitMask(_wr);
|
||||
_wrPortSet = (PORTreg_t)GPIO_OUT1_W1TS_REG;
|
||||
_wrPortClr = (PORTreg_t)GPIO_OUT1_W1TC_REG;
|
||||
}
|
||||
else
|
||||
{
|
||||
_wrPinMask = digitalPinToBitMask(_wr);
|
||||
_wrPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_wrPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
}
|
||||
|
||||
if (_rd != GFX_NOT_DEFINED)
|
||||
{
|
||||
pinMode(_rd, OUTPUT);
|
||||
digitalWrite(_rd, HIGH);
|
||||
}
|
||||
|
||||
pinMode(_d0, OUTPUT);
|
||||
pinMode(_d1, OUTPUT);
|
||||
pinMode(_d2, OUTPUT);
|
||||
pinMode(_d3, OUTPUT);
|
||||
pinMode(_d4, OUTPUT);
|
||||
pinMode(_d5, OUTPUT);
|
||||
pinMode(_d6, OUTPUT);
|
||||
pinMode(_d7, OUTPUT);
|
||||
|
||||
_data1PortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_data1PortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
_data2PortSet = (PORTreg_t)GPIO_OUT1_W1TS_REG;
|
||||
_data2PortClr = (PORTreg_t)GPIO_OUT1_W1TC_REG;
|
||||
|
||||
// INIT 8-bit mask
|
||||
_data1ClrMask = 0;
|
||||
_data2ClrMask = 0;
|
||||
if (_d0 >= 32)
|
||||
{
|
||||
_data2ClrMask |= digitalPinToBitMask(_d0);
|
||||
}
|
||||
else
|
||||
{
|
||||
_data1ClrMask |= digitalPinToBitMask(_d0);
|
||||
}
|
||||
if (_d1 >= 32)
|
||||
{
|
||||
_data2ClrMask |= digitalPinToBitMask(_d1);
|
||||
}
|
||||
else
|
||||
{
|
||||
_data1ClrMask |= digitalPinToBitMask(_d1);
|
||||
}
|
||||
if (_d2 >= 32)
|
||||
{
|
||||
_data2ClrMask |= digitalPinToBitMask(_d2);
|
||||
}
|
||||
else
|
||||
{
|
||||
_data1ClrMask |= digitalPinToBitMask(_d2);
|
||||
}
|
||||
if (_d3 >= 32)
|
||||
{
|
||||
_data2ClrMask |= digitalPinToBitMask(_d3);
|
||||
}
|
||||
else
|
||||
{
|
||||
_data1ClrMask |= digitalPinToBitMask(_d3);
|
||||
}
|
||||
if (_d4 >= 32)
|
||||
{
|
||||
_data2ClrMask |= digitalPinToBitMask(_d4);
|
||||
}
|
||||
else
|
||||
{
|
||||
_data1ClrMask |= digitalPinToBitMask(_d4);
|
||||
}
|
||||
if (_d5 >= 32)
|
||||
{
|
||||
_data2ClrMask |= digitalPinToBitMask(_d5);
|
||||
}
|
||||
else
|
||||
{
|
||||
_data1ClrMask |= digitalPinToBitMask(_d5);
|
||||
}
|
||||
if (_d6 >= 32)
|
||||
{
|
||||
_data2ClrMask |= digitalPinToBitMask(_d6);
|
||||
}
|
||||
else
|
||||
{
|
||||
_data1ClrMask |= digitalPinToBitMask(_d6);
|
||||
}
|
||||
if (_d7 >= 32)
|
||||
{
|
||||
_data2ClrMask |= digitalPinToBitMask(_d7);
|
||||
}
|
||||
else
|
||||
{
|
||||
_data1ClrMask |= digitalPinToBitMask(_d7);
|
||||
}
|
||||
|
||||
for (int32_t c = 0; c < 256; c++)
|
||||
{
|
||||
_xset_mask1[c] = 0;
|
||||
_xset_mask2[c] = 0;
|
||||
if (c & 0x01)
|
||||
{
|
||||
if (_d0 >= 32)
|
||||
{
|
||||
_xset_mask2[c] |= digitalPinToBitMask(_d0);
|
||||
}
|
||||
else
|
||||
{
|
||||
_xset_mask1[c] |= digitalPinToBitMask(_d0);
|
||||
}
|
||||
}
|
||||
if (c & 0x02)
|
||||
{
|
||||
if (_d1 >= 32)
|
||||
{
|
||||
_xset_mask2[c] |= digitalPinToBitMask(_d1);
|
||||
}
|
||||
else
|
||||
{
|
||||
_xset_mask1[c] |= digitalPinToBitMask(_d1);
|
||||
}
|
||||
}
|
||||
if (c & 0x04)
|
||||
{
|
||||
if (_d2 >= 32)
|
||||
{
|
||||
_xset_mask2[c] |= digitalPinToBitMask(_d2);
|
||||
}
|
||||
else
|
||||
{
|
||||
_xset_mask1[c] |= digitalPinToBitMask(_d2);
|
||||
}
|
||||
}
|
||||
if (c & 0x08)
|
||||
{
|
||||
if (_d3 >= 32)
|
||||
{
|
||||
_xset_mask2[c] |= digitalPinToBitMask(_d3);
|
||||
}
|
||||
else
|
||||
{
|
||||
_xset_mask1[c] |= digitalPinToBitMask(_d3);
|
||||
}
|
||||
}
|
||||
if (c & 0x10)
|
||||
{
|
||||
if (_d4 >= 32)
|
||||
{
|
||||
_xset_mask2[c] |= digitalPinToBitMask(_d4);
|
||||
}
|
||||
else
|
||||
{
|
||||
_xset_mask1[c] |= digitalPinToBitMask(_d4);
|
||||
}
|
||||
}
|
||||
if (c & 0x20)
|
||||
{
|
||||
if (_d5 >= 32)
|
||||
{
|
||||
_xset_mask2[c] |= digitalPinToBitMask(_d5);
|
||||
}
|
||||
else
|
||||
{
|
||||
_xset_mask1[c] |= digitalPinToBitMask(_d5);
|
||||
}
|
||||
}
|
||||
if (c & 0x40)
|
||||
{
|
||||
if (_d6 >= 32)
|
||||
{
|
||||
_xset_mask2[c] |= digitalPinToBitMask(_d6);
|
||||
}
|
||||
else
|
||||
{
|
||||
_xset_mask1[c] |= digitalPinToBitMask(_d6);
|
||||
}
|
||||
}
|
||||
if (c & 0x80)
|
||||
{
|
||||
if (_d7 >= 32)
|
||||
{
|
||||
_xset_mask2[c] |= digitalPinToBitMask(_d7);
|
||||
}
|
||||
else
|
||||
{
|
||||
_xset_mask1[c] |= digitalPinToBitMask(_d7);
|
||||
}
|
||||
}
|
||||
}
|
||||
*_data1PortClr = _data1ClrMask;
|
||||
*_data2PortClr = _data2ClrMask;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8::beginWrite()
|
||||
{
|
||||
DC_HIGH();
|
||||
CS_LOW();
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8::endWrite()
|
||||
{
|
||||
CS_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8::writeCommand(uint8_t c)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8::writeCommand16(uint16_t c)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
_data16.value = c;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8::writeCommandBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
while (len--)
|
||||
{
|
||||
WRITE(*data++);
|
||||
}
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8::write(uint8_t d)
|
||||
{
|
||||
WRITE(d);
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8::write16(uint16_t d)
|
||||
{
|
||||
_data16.value = d;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8::writeRepeat(uint16_t p, uint32_t len)
|
||||
{
|
||||
_data16.value = p;
|
||||
if (_data16.msb == _data16.lsb)
|
||||
{
|
||||
uint32_t setMask1 = _xset_mask1[_data16.msb];
|
||||
uint32_t setMask2 = _xset_mask2[_data16.msb];
|
||||
*_data1PortClr = _data1ClrMask;
|
||||
*_data2PortClr = _data2ClrMask;
|
||||
*_data1PortSet = setMask1;
|
||||
*_data2PortSet = setMask2;
|
||||
while (len--)
|
||||
{
|
||||
*_wrPortClr = _wrPinMask;
|
||||
*_wrPortSet = _wrPinMask;
|
||||
*_wrPortClr = _wrPinMask;
|
||||
*_wrPortSet = _wrPinMask;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t hiMask1 = _xset_mask1[_data16.msb];
|
||||
uint32_t hiMask2 = _xset_mask2[_data16.msb];
|
||||
uint32_t loMask1 = _xset_mask1[_data16.lsb];
|
||||
uint32_t loMask2 = _xset_mask2[_data16.lsb];
|
||||
while (len--)
|
||||
{
|
||||
*_data1PortClr = _data1ClrMask;
|
||||
*_data2PortClr = _data2ClrMask;
|
||||
*_data1PortSet = hiMask1;
|
||||
*_data2PortSet = hiMask2;
|
||||
*_wrPortClr = _wrPinMask;
|
||||
*_wrPortSet = _wrPinMask;
|
||||
|
||||
*_data1PortClr = _data1ClrMask;
|
||||
*_data2PortClr = _data2ClrMask;
|
||||
*_data1PortSet = loMask1;
|
||||
*_data2PortSet = loMask2;
|
||||
*_wrPortClr = _wrPinMask;
|
||||
*_wrPortSet = _wrPinMask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8::writePixels(uint16_t *data, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
_data16.value = *data++;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8::writeC8D8(uint8_t c, uint8_t d)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
WRITE(d);
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8::writeC8D16(uint8_t c, uint16_t d)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
_data16.value = d;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8::writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
_data16.value = d1;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
|
||||
_data16.value = d2;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8::writeC8D16D16Split(uint8_t c, uint16_t d1, uint16_t d2)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
_data16.value = d1;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
|
||||
_data16.value = d2;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8::writeBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
WRITE(*data++);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8::writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
_data16.value = idx[*data++];
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8::writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
_data16.value = idx[*data++];
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP32PAR8::WRITE(uint8_t d)
|
||||
{
|
||||
uint32_t setMask1 = _xset_mask1[d];
|
||||
uint32_t setMask2 = _xset_mask2[d];
|
||||
*_data1PortClr = _data1ClrMask;
|
||||
*_data2PortClr = _data2ClrMask;
|
||||
*_data1PortSet = setMask1;
|
||||
*_data2PortSet = setMask2;
|
||||
*_wrPortClr = _wrPinMask;
|
||||
*_wrPortSet = _wrPinMask;
|
||||
}
|
||||
|
||||
/******** low level bit twiddling **********/
|
||||
|
||||
GFX_INLINE void Arduino_ESP32PAR8::DC_HIGH(void)
|
||||
{
|
||||
*_dcPortSet = _dcPinMask;
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP32PAR8::DC_LOW(void)
|
||||
{
|
||||
*_dcPortClr = _dcPinMask;
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP32PAR8::CS_HIGH(void)
|
||||
{
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
*_csPortSet = _csPinMask;
|
||||
}
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP32PAR8::CS_LOW(void)
|
||||
{
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
*_csPortClr = _csPinMask;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // #if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
|
||||
@@ -0,0 +1,71 @@
|
||||
#include "Arduino_DataBus.h"
|
||||
|
||||
#if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
|
||||
|
||||
#ifndef _ARDUINO_ESP32PAR8_H_
|
||||
#define _ARDUINO_ESP32PAR8_H_
|
||||
|
||||
class Arduino_ESP32PAR8 : public Arduino_DataBus
|
||||
{
|
||||
public:
|
||||
Arduino_ESP32PAR8(
|
||||
int8_t dc, int8_t cs, int8_t wr, int8_t rd,
|
||||
int8_t d0, int8_t d1, int8_t d2, int8_t d3, int8_t d4, int8_t d5, int8_t d6, int8_t d7); // Constructor
|
||||
|
||||
bool begin(int32_t speed = GFX_NOT_DEFINED, int8_t dataMode = GFX_NOT_DEFINED) override;
|
||||
void beginWrite() override;
|
||||
void endWrite() override;
|
||||
void writeCommand(uint8_t) override;
|
||||
void writeCommand16(uint16_t) override;
|
||||
void writeCommandBytes(uint8_t *data, uint32_t len) override;
|
||||
void write(uint8_t) override;
|
||||
void write16(uint16_t) override;
|
||||
void writeRepeat(uint16_t p, uint32_t len) override;
|
||||
void writePixels(uint16_t *data, uint32_t len) override;
|
||||
|
||||
void writeC8D8(uint8_t c, uint8_t d) override;
|
||||
void writeC8D16(uint8_t c, uint16_t d) override;
|
||||
void writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2) override;
|
||||
void writeC8D16D16Split(uint8_t c, uint16_t d1, uint16_t d2) override;
|
||||
void writeBytes(uint8_t *data, uint32_t len) override;
|
||||
|
||||
void writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len) override;
|
||||
void writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len) override;
|
||||
|
||||
protected:
|
||||
private:
|
||||
GFX_INLINE void WRITE(uint8_t d);
|
||||
GFX_INLINE void DC_HIGH(void);
|
||||
GFX_INLINE void DC_LOW(void);
|
||||
GFX_INLINE void CS_HIGH(void);
|
||||
GFX_INLINE void CS_LOW(void);
|
||||
|
||||
int8_t _dc, _cs, _wr, _rd;
|
||||
int8_t _d0, _d1, _d2, _d3, _d4, _d5, _d6, _d7;
|
||||
|
||||
PORTreg_t _dcPortSet; ///< PORT register SET
|
||||
PORTreg_t _dcPortClr; ///< PORT register CLEAR
|
||||
uint32_t _dcPinMask; ///< Bitmask
|
||||
|
||||
PORTreg_t _csPortSet; ///< PORT register SET
|
||||
PORTreg_t _csPortClr; ///< PORT register CLEAR
|
||||
uint32_t _csPinMask; ///< Bitmask
|
||||
|
||||
PORTreg_t _wrPortSet; ///< PORT register SET
|
||||
PORTreg_t _wrPortClr; ///< PORT register CLEAR
|
||||
uint32_t _wrPinMask; ///< Bitmask
|
||||
|
||||
PORTreg_t _data1PortSet;
|
||||
PORTreg_t _data1PortClr;
|
||||
uint32_t _data1ClrMask;
|
||||
PORTreg_t _data2PortSet;
|
||||
PORTreg_t _data2PortClr;
|
||||
uint32_t _data2ClrMask;
|
||||
// Lookup table for ESP32 parallel bus interface uses 1kbyte RAM,
|
||||
uint32_t _xset_mask1[256];
|
||||
uint32_t _xset_mask2[256];
|
||||
};
|
||||
|
||||
#endif // _ARDUINO_ESP32PAR8_H_
|
||||
|
||||
#endif // #if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
|
||||
@@ -0,0 +1,359 @@
|
||||
#include "Arduino_ESP32PAR8Q.h"
|
||||
|
||||
#if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
|
||||
|
||||
Arduino_ESP32PAR8Q::Arduino_ESP32PAR8Q(
|
||||
int8_t dc, int8_t cs, int8_t wr, int8_t rd,
|
||||
int8_t d0, int8_t d1, int8_t d2, int8_t d3, int8_t d4, int8_t d5, int8_t d6, int8_t d7)
|
||||
: _dc(dc), _cs(cs), _wr(wr), _rd(rd),
|
||||
_d0(d0), _d1(d1), _d2(d2), _d3(d3), _d4(d4), _d5(d5), _d6(d6), _d7(d7)
|
||||
{
|
||||
}
|
||||
|
||||
bool Arduino_ESP32PAR8Q::begin(int32_t, int8_t)
|
||||
{
|
||||
pinMode(_dc, OUTPUT);
|
||||
digitalWrite(_dc, HIGH); // Data mode
|
||||
if (_dc >= 32)
|
||||
{
|
||||
_dcPinMask = digitalPinToBitMask(_dc);
|
||||
_dcPortSet = (PORTreg_t)GPIO_OUT1_W1TS_REG;
|
||||
_dcPortClr = (PORTreg_t)GPIO_OUT1_W1TC_REG;
|
||||
}
|
||||
else
|
||||
{
|
||||
_dcPinMask = digitalPinToBitMask(_dc);
|
||||
_dcPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_dcPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
}
|
||||
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
pinMode(_cs, OUTPUT);
|
||||
digitalWrite(_cs, HIGH); // disable chip select
|
||||
}
|
||||
if (_cs >= 32)
|
||||
{
|
||||
_csPinMask = digitalPinToBitMask(_cs);
|
||||
_csPortSet = (PORTreg_t)GPIO_OUT1_W1TS_REG;
|
||||
_csPortClr = (PORTreg_t)GPIO_OUT1_W1TC_REG;
|
||||
}
|
||||
else if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
_csPinMask = digitalPinToBitMask(_cs);
|
||||
_csPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_csPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
}
|
||||
|
||||
pinMode(_wr, OUTPUT);
|
||||
digitalWrite(_wr, HIGH); // Set write strobe high (inactive)
|
||||
if (_wr >= 32)
|
||||
{
|
||||
_wrPinMask = digitalPinToBitMask(_wr);
|
||||
_wrPortSet = (PORTreg_t)GPIO_OUT1_W1TS_REG;
|
||||
_wrPortClr = (PORTreg_t)GPIO_OUT1_W1TC_REG;
|
||||
}
|
||||
else
|
||||
{
|
||||
_wrPinMask = digitalPinToBitMask(_wr);
|
||||
_wrPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_wrPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
}
|
||||
|
||||
if (_rd != GFX_NOT_DEFINED)
|
||||
{
|
||||
pinMode(_rd, OUTPUT);
|
||||
digitalWrite(_rd, HIGH);
|
||||
}
|
||||
|
||||
// TODO: check pin range 0-31
|
||||
pinMode(_d0, OUTPUT);
|
||||
pinMode(_d1, OUTPUT);
|
||||
pinMode(_d2, OUTPUT);
|
||||
pinMode(_d3, OUTPUT);
|
||||
pinMode(_d4, OUTPUT);
|
||||
pinMode(_d5, OUTPUT);
|
||||
pinMode(_d6, OUTPUT);
|
||||
pinMode(_d7, OUTPUT);
|
||||
|
||||
if (_d0 >= 32)
|
||||
{
|
||||
_dataPortSet = (PORTreg_t)GPIO_OUT1_W1TS_REG;
|
||||
_dataPortClr = (PORTreg_t)GPIO_OUT1_W1TC_REG;
|
||||
}
|
||||
else
|
||||
{
|
||||
_dataPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_dataPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
}
|
||||
|
||||
// INIT 8-bit mask
|
||||
_dataClrMask = digitalPinToBitMask(_d0) | digitalPinToBitMask(_d1) | digitalPinToBitMask(_d2) | digitalPinToBitMask(_d3) | digitalPinToBitMask(_d4) | digitalPinToBitMask(_d5) | digitalPinToBitMask(_d6) | digitalPinToBitMask(_d7);
|
||||
|
||||
for (int32_t c = 0; c < 256; c++)
|
||||
{
|
||||
_xset_mask[c] = 0;
|
||||
if (c & 0x01)
|
||||
{
|
||||
_xset_mask[c] |= digitalPinToBitMask(_d0);
|
||||
}
|
||||
if (c & 0x02)
|
||||
{
|
||||
_xset_mask[c] |= digitalPinToBitMask(_d1);
|
||||
}
|
||||
if (c & 0x04)
|
||||
{
|
||||
_xset_mask[c] |= digitalPinToBitMask(_d2);
|
||||
}
|
||||
if (c & 0x08)
|
||||
{
|
||||
_xset_mask[c] |= digitalPinToBitMask(_d3);
|
||||
}
|
||||
if (c & 0x10)
|
||||
{
|
||||
_xset_mask[c] |= digitalPinToBitMask(_d4);
|
||||
}
|
||||
if (c & 0x20)
|
||||
{
|
||||
_xset_mask[c] |= digitalPinToBitMask(_d5);
|
||||
}
|
||||
if (c & 0x40)
|
||||
{
|
||||
_xset_mask[c] |= digitalPinToBitMask(_d6);
|
||||
}
|
||||
if (c & 0x80)
|
||||
{
|
||||
_xset_mask[c] |= digitalPinToBitMask(_d7);
|
||||
}
|
||||
}
|
||||
*_dataPortClr = _dataClrMask;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8Q::beginWrite()
|
||||
{
|
||||
DC_HIGH();
|
||||
CS_LOW();
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8Q::endWrite()
|
||||
{
|
||||
CS_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8Q::writeCommand(uint8_t c)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8Q::writeCommand16(uint16_t c)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
_data16.value = c;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8Q::writeCommandBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
while (len--)
|
||||
{
|
||||
WRITE(*data++);
|
||||
}
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8Q::write(uint8_t d)
|
||||
{
|
||||
WRITE(d);
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8Q::write16(uint16_t d)
|
||||
{
|
||||
_data16.value = d;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8Q::writeRepeat(uint16_t p, uint32_t len)
|
||||
{
|
||||
_data16.value = p;
|
||||
if (_data16.msb == _data16.lsb)
|
||||
{
|
||||
uint32_t setMask = _xset_mask[_data16.msb];
|
||||
*_dataPortClr = _dataClrMask;
|
||||
*_dataPortSet = setMask;
|
||||
while (len--)
|
||||
{
|
||||
*_wrPortClr = _wrPinMask;
|
||||
*_wrPortSet = _wrPinMask;
|
||||
*_wrPortClr = _wrPinMask;
|
||||
*_wrPortSet = _wrPinMask;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t hiMask = _xset_mask[_data16.msb];
|
||||
uint32_t loMask = _xset_mask[_data16.lsb];
|
||||
while (len--)
|
||||
{
|
||||
*_dataPortClr = _dataClrMask;
|
||||
*_dataPortSet = hiMask;
|
||||
*_wrPortClr = _wrPinMask;
|
||||
*_wrPortSet = _wrPinMask;
|
||||
|
||||
*_dataPortClr = _dataClrMask;
|
||||
*_dataPortSet = loMask;
|
||||
*_wrPortClr = _wrPinMask;
|
||||
*_wrPortSet = _wrPinMask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8Q::writePixels(uint16_t *data, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
_data16.value = *data++;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8Q::writeC8D8(uint8_t c, uint8_t d)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
WRITE(d);
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8Q::writeC8D16(uint8_t c, uint16_t d)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
_data16.value = d;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8Q::writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
_data16.value = d1;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
|
||||
_data16.value = d2;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8Q::writeC8D16D16Split(uint8_t c, uint16_t d1, uint16_t d2)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
_data16.value = d1;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
|
||||
_data16.value = d2;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8Q::writeBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
WRITE(*data++);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8Q::writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
_data16.value = idx[*data++];
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8Q::writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
_data16.value = idx[*data++];
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP32PAR8Q::WRITE(uint8_t d)
|
||||
{
|
||||
uint32_t setMask = _xset_mask[d];
|
||||
*_dataPortClr = _dataClrMask;
|
||||
*_dataPortSet = setMask;
|
||||
*_wrPortClr = _wrPinMask;
|
||||
*_wrPortSet = _wrPinMask;
|
||||
}
|
||||
|
||||
/******** low level bit twiddling **********/
|
||||
|
||||
GFX_INLINE void Arduino_ESP32PAR8Q::DC_HIGH(void)
|
||||
{
|
||||
*_dcPortSet = _dcPinMask;
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP32PAR8Q::DC_LOW(void)
|
||||
{
|
||||
*_dcPortClr = _dcPinMask;
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP32PAR8Q::CS_HIGH(void)
|
||||
{
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
*_csPortSet = _csPinMask;
|
||||
}
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP32PAR8Q::CS_LOW(void)
|
||||
{
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
*_csPortClr = _csPinMask;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // #if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
|
||||
@@ -0,0 +1,67 @@
|
||||
#include "Arduino_DataBus.h"
|
||||
|
||||
#if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
|
||||
|
||||
#ifndef _ARDUINO_ESP32PAR8Q_H_
|
||||
#define _ARDUINO_ESP32PAR8Q_H_
|
||||
|
||||
class Arduino_ESP32PAR8Q : public Arduino_DataBus
|
||||
{
|
||||
public:
|
||||
Arduino_ESP32PAR8Q(
|
||||
int8_t dc, int8_t cs, int8_t wr, int8_t rd,
|
||||
int8_t d0, int8_t d1, int8_t d2, int8_t d3, int8_t d4, int8_t d5, int8_t d6, int8_t d7); // Constructor
|
||||
|
||||
bool begin(int32_t speed = GFX_NOT_DEFINED, int8_t dataMode = GFX_NOT_DEFINED) override;
|
||||
void beginWrite() override;
|
||||
void endWrite() override;
|
||||
void writeCommand(uint8_t) override;
|
||||
void writeCommand16(uint16_t) override;
|
||||
void writeCommandBytes(uint8_t *data, uint32_t len) override;
|
||||
void write(uint8_t) override;
|
||||
void write16(uint16_t) override;
|
||||
void writeRepeat(uint16_t p, uint32_t len) override;
|
||||
void writePixels(uint16_t *data, uint32_t len) override;
|
||||
|
||||
void writeC8D8(uint8_t c, uint8_t d) override;
|
||||
void writeC8D16(uint8_t c, uint16_t d) override;
|
||||
void writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2) override;
|
||||
void writeC8D16D16Split(uint8_t c, uint16_t d1, uint16_t d2) override;
|
||||
void writeBytes(uint8_t *data, uint32_t len) override;
|
||||
|
||||
void writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len) override;
|
||||
void writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len) override;
|
||||
|
||||
protected:
|
||||
private:
|
||||
GFX_INLINE void WRITE(uint8_t d);
|
||||
GFX_INLINE void DC_HIGH(void);
|
||||
GFX_INLINE void DC_LOW(void);
|
||||
GFX_INLINE void CS_HIGH(void);
|
||||
GFX_INLINE void CS_LOW(void);
|
||||
|
||||
int8_t _dc, _cs, _wr, _rd;
|
||||
int8_t _d0, _d1, _d2, _d3, _d4, _d5, _d6, _d7;
|
||||
|
||||
PORTreg_t _dcPortSet; ///< PORT register SET
|
||||
PORTreg_t _dcPortClr; ///< PORT register CLEAR
|
||||
uint32_t _dcPinMask; ///< Bitmask
|
||||
|
||||
PORTreg_t _csPortSet; ///< PORT register SET
|
||||
PORTreg_t _csPortClr; ///< PORT register CLEAR
|
||||
uint32_t _csPinMask; ///< Bitmask
|
||||
|
||||
PORTreg_t _wrPortSet; ///< PORT register SET
|
||||
PORTreg_t _wrPortClr; ///< PORT register CLEAR
|
||||
uint32_t _wrPinMask; ///< Bitmask
|
||||
|
||||
PORTreg_t _dataPortSet;
|
||||
PORTreg_t _dataPortClr;
|
||||
uint32_t _dataClrMask;
|
||||
// Lookup table for ESP32 parallel bus interface uses 1kbyte RAM,
|
||||
uint32_t _xset_mask[256];
|
||||
};
|
||||
|
||||
#endif // _ARDUINO_ESP32PAR8Q_H_
|
||||
|
||||
#endif // #if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
|
||||
@@ -0,0 +1,359 @@
|
||||
#include "Arduino_ESP32PAR8QQ.h"
|
||||
|
||||
#if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
|
||||
|
||||
Arduino_ESP32PAR8QQ::Arduino_ESP32PAR8QQ(
|
||||
int8_t dc, int8_t cs, int8_t wr, int8_t rd,
|
||||
int8_t d0, int8_t d1, int8_t d2, int8_t d3, int8_t d4, int8_t d5, int8_t d6, int8_t d7)
|
||||
: _dc(dc), _cs(cs), _wr(wr), _rd(rd),
|
||||
_d0(d0), _d1(d1), _d2(d2), _d3(d3), _d4(d4), _d5(d5), _d6(d6), _d7(d7)
|
||||
{
|
||||
}
|
||||
|
||||
bool Arduino_ESP32PAR8QQ::begin(int32_t, int8_t)
|
||||
{
|
||||
pinMode(_dc, OUTPUT);
|
||||
digitalWrite(_dc, HIGH); // Data mode
|
||||
if (_dc >= 32)
|
||||
{
|
||||
_dcPinMask = digitalPinToBitMask(_dc);
|
||||
_dcPortSet = (PORTreg_t)GPIO_OUT1_W1TS_REG;
|
||||
_dcPortClr = (PORTreg_t)GPIO_OUT1_W1TC_REG;
|
||||
}
|
||||
else
|
||||
{
|
||||
_dcPinMask = digitalPinToBitMask(_dc);
|
||||
_dcPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_dcPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
}
|
||||
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
pinMode(_cs, OUTPUT);
|
||||
digitalWrite(_cs, HIGH); // disable chip select
|
||||
}
|
||||
if (_cs >= 32)
|
||||
{
|
||||
_csPinMask = digitalPinToBitMask(_cs);
|
||||
_csPortSet = (PORTreg_t)GPIO_OUT1_W1TS_REG;
|
||||
_csPortClr = (PORTreg_t)GPIO_OUT1_W1TC_REG;
|
||||
}
|
||||
else if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
_csPinMask = digitalPinToBitMask(_cs);
|
||||
_csPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_csPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
}
|
||||
|
||||
pinMode(_wr, OUTPUT);
|
||||
digitalWrite(_wr, HIGH); // Set write strobe high (inactive)
|
||||
if (_wr >= 32)
|
||||
{
|
||||
_wrPinMask = digitalPinToBitMask(_wr);
|
||||
_wrPortSet = (PORTreg_t)GPIO_OUT1_W1TS_REG;
|
||||
_wrPortClr = (PORTreg_t)GPIO_OUT1_W1TC_REG;
|
||||
}
|
||||
else
|
||||
{
|
||||
_wrPinMask = digitalPinToBitMask(_wr);
|
||||
_wrPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_wrPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
}
|
||||
|
||||
if (_rd != GFX_NOT_DEFINED)
|
||||
{
|
||||
pinMode(_rd, OUTPUT);
|
||||
digitalWrite(_rd, HIGH);
|
||||
}
|
||||
|
||||
// TODO: check pin range 0-31
|
||||
pinMode(_d0, OUTPUT);
|
||||
pinMode(_d1, OUTPUT);
|
||||
pinMode(_d2, OUTPUT);
|
||||
pinMode(_d3, OUTPUT);
|
||||
pinMode(_d4, OUTPUT);
|
||||
pinMode(_d5, OUTPUT);
|
||||
pinMode(_d6, OUTPUT);
|
||||
pinMode(_d7, OUTPUT);
|
||||
|
||||
if (_d0 >= 32)
|
||||
{
|
||||
_dataPortSet = (PORTreg_t)GPIO_OUT1_W1TS_REG;
|
||||
_dataPortClr = (PORTreg_t)GPIO_OUT1_W1TC_REG;
|
||||
}
|
||||
else
|
||||
{
|
||||
_dataPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_dataPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
}
|
||||
|
||||
// INIT 8-bit mask
|
||||
_dataClrMask = digitalPinToBitMask(_d0) | digitalPinToBitMask(_d1) | digitalPinToBitMask(_d2) | digitalPinToBitMask(_d3) | digitalPinToBitMask(_d4) | digitalPinToBitMask(_d5) | digitalPinToBitMask(_d6) | digitalPinToBitMask(_d7);
|
||||
|
||||
for (int32_t c = 0; c < 256; c++)
|
||||
{
|
||||
_xset_mask[c] = 0;
|
||||
if (c & 0x01)
|
||||
{
|
||||
_xset_mask[c] |= digitalPinToBitMask(_d0);
|
||||
}
|
||||
if (c & 0x02)
|
||||
{
|
||||
_xset_mask[c] |= digitalPinToBitMask(_d1);
|
||||
}
|
||||
if (c & 0x04)
|
||||
{
|
||||
_xset_mask[c] |= digitalPinToBitMask(_d2);
|
||||
}
|
||||
if (c & 0x08)
|
||||
{
|
||||
_xset_mask[c] |= digitalPinToBitMask(_d3);
|
||||
}
|
||||
if (c & 0x10)
|
||||
{
|
||||
_xset_mask[c] |= digitalPinToBitMask(_d4);
|
||||
}
|
||||
if (c & 0x20)
|
||||
{
|
||||
_xset_mask[c] |= digitalPinToBitMask(_d5);
|
||||
}
|
||||
if (c & 0x40)
|
||||
{
|
||||
_xset_mask[c] |= digitalPinToBitMask(_d6);
|
||||
}
|
||||
if (c & 0x80)
|
||||
{
|
||||
_xset_mask[c] |= digitalPinToBitMask(_d7);
|
||||
}
|
||||
}
|
||||
*_dataPortClr = _dataClrMask;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8QQ::beginWrite()
|
||||
{
|
||||
DC_HIGH();
|
||||
CS_LOW();
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8QQ::endWrite()
|
||||
{
|
||||
CS_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8QQ::writeCommand(uint8_t c)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8QQ::writeCommand16(uint16_t c)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
_data16.value = c;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8QQ::writeCommandBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
while (len--)
|
||||
{
|
||||
WRITE(*data++);
|
||||
}
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8QQ::write(uint8_t d)
|
||||
{
|
||||
WRITE(d);
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8QQ::write16(uint16_t d)
|
||||
{
|
||||
_data16.value = d;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8QQ::writeRepeat(uint16_t p, uint32_t len)
|
||||
{
|
||||
_data16.value = p;
|
||||
if (_data16.msb == _data16.lsb)
|
||||
{
|
||||
uint32_t setMask = _xset_mask[_data16.msb];
|
||||
*_dataPortClr = _dataClrMask;
|
||||
*_dataPortSet = setMask;
|
||||
*_wrPortSet = _wrPinMask;
|
||||
*_wrPortClr = _wrPinMask;
|
||||
*_wrPortSet = _wrPinMask;
|
||||
while (--len)
|
||||
{
|
||||
*_wrPortClr = _wrPinMask;
|
||||
*_wrPortSet = _wrPinMask;
|
||||
*_wrPortClr = _wrPinMask;
|
||||
*_wrPortSet = _wrPinMask;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t hiMask = _xset_mask[_data16.msb];
|
||||
uint32_t loMask = _xset_mask[_data16.lsb];
|
||||
while (len--)
|
||||
{
|
||||
*_dataPortClr = _dataClrMask;
|
||||
*_dataPortSet = hiMask;
|
||||
*_wrPortSet = _wrPinMask;
|
||||
|
||||
*_dataPortClr = _dataClrMask;
|
||||
*_dataPortSet = loMask;
|
||||
*_wrPortSet = _wrPinMask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8QQ::writePixels(uint16_t *data, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
_data16.value = *data++;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8QQ::writeC8D8(uint8_t c, uint8_t d)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
WRITE(d);
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8QQ::writeC8D16(uint8_t c, uint16_t d)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
_data16.value = d;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8QQ::writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
_data16.value = d1;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
|
||||
_data16.value = d2;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8QQ::writeC8D16D16Split(uint8_t c, uint16_t d1, uint16_t d2)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
_data16.value = d1;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
|
||||
_data16.value = d2;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8QQ::writeBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
WRITE(*data++);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8QQ::writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
_data16.value = idx[*data++];
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8QQ::writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
_data16.value = idx[*data++];
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP32PAR8QQ::WRITE(uint8_t d)
|
||||
{
|
||||
uint32_t setMask = _xset_mask[d];
|
||||
*_dataPortClr = _dataClrMask;
|
||||
*_dataPortSet = setMask;
|
||||
*_wrPortSet = _wrPinMask;
|
||||
}
|
||||
|
||||
/******** low level bit twiddling **********/
|
||||
|
||||
GFX_INLINE void Arduino_ESP32PAR8QQ::DC_HIGH(void)
|
||||
{
|
||||
*_dcPortSet = _dcPinMask;
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP32PAR8QQ::DC_LOW(void)
|
||||
{
|
||||
*_dcPortClr = _dcPinMask;
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP32PAR8QQ::CS_HIGH(void)
|
||||
{
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
*_csPortSet = _csPinMask;
|
||||
}
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP32PAR8QQ::CS_LOW(void)
|
||||
{
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
*_csPortClr = _csPinMask;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // #if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
|
||||
@@ -0,0 +1,67 @@
|
||||
#include "Arduino_DataBus.h"
|
||||
|
||||
#if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
|
||||
|
||||
#ifndef _ARDUINO_ESP32PAR8QQ_H_
|
||||
#define _ARDUINO_ESP32PAR8QQ_H_
|
||||
|
||||
class Arduino_ESP32PAR8QQ : public Arduino_DataBus
|
||||
{
|
||||
public:
|
||||
Arduino_ESP32PAR8QQ(
|
||||
int8_t dc, int8_t cs, int8_t wr, int8_t rd,
|
||||
int8_t d0, int8_t d1, int8_t d2, int8_t d3, int8_t d4, int8_t d5, int8_t d6, int8_t d7); // Constructor
|
||||
|
||||
bool begin(int32_t speed = GFX_NOT_DEFINED, int8_t dataMode = GFX_NOT_DEFINED) override;
|
||||
void beginWrite() override;
|
||||
void endWrite() override;
|
||||
void writeCommand(uint8_t) override;
|
||||
void writeCommand16(uint16_t) override;
|
||||
void writeCommandBytes(uint8_t *data, uint32_t len) override;
|
||||
void write(uint8_t) override;
|
||||
void write16(uint16_t) override;
|
||||
void writeRepeat(uint16_t p, uint32_t len) override;
|
||||
void writePixels(uint16_t *data, uint32_t len) override;
|
||||
|
||||
void writeC8D8(uint8_t c, uint8_t d) override;
|
||||
void writeC8D16(uint8_t c, uint16_t d) override;
|
||||
void writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2) override;
|
||||
void writeC8D16D16Split(uint8_t c, uint16_t d1, uint16_t d2) override;
|
||||
void writeBytes(uint8_t *data, uint32_t len) override;
|
||||
|
||||
void writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len) override;
|
||||
void writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len) override;
|
||||
|
||||
protected:
|
||||
private:
|
||||
GFX_INLINE void WRITE(uint8_t d);
|
||||
GFX_INLINE void DC_HIGH(void);
|
||||
GFX_INLINE void DC_LOW(void);
|
||||
GFX_INLINE void CS_HIGH(void);
|
||||
GFX_INLINE void CS_LOW(void);
|
||||
|
||||
int8_t _dc, _cs, _wr, _rd;
|
||||
int8_t _d0, _d1, _d2, _d3, _d4, _d5, _d6, _d7;
|
||||
|
||||
PORTreg_t _dcPortSet; ///< PORT register SET
|
||||
PORTreg_t _dcPortClr; ///< PORT register CLEAR
|
||||
uint32_t _dcPinMask; ///< Bitmask
|
||||
|
||||
PORTreg_t _csPortSet; ///< PORT register SET
|
||||
PORTreg_t _csPortClr; ///< PORT register CLEAR
|
||||
uint32_t _csPinMask; ///< Bitmask
|
||||
|
||||
PORTreg_t _wrPortSet; ///< PORT register SET
|
||||
PORTreg_t _wrPortClr; ///< PORT register CLEAR
|
||||
uint32_t _wrPinMask; ///< Bitmask
|
||||
|
||||
PORTreg_t _dataPortSet;
|
||||
PORTreg_t _dataPortClr;
|
||||
uint32_t _dataClrMask;
|
||||
// Lookup table for ESP32 parallel bus interface uses 1kbyte RAM,
|
||||
uint32_t _xset_mask[256];
|
||||
};
|
||||
|
||||
#endif // _ARDUINO_ESP32PAR8QQ_H_
|
||||
|
||||
#endif // #if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
|
||||
@@ -0,0 +1,353 @@
|
||||
#include "Arduino_ESP32PAR8QQQ.h"
|
||||
|
||||
#if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
|
||||
|
||||
Arduino_ESP32PAR8QQQ::Arduino_ESP32PAR8QQQ(
|
||||
int8_t dc, int8_t cs, int8_t wr, int8_t rd,
|
||||
int8_t d0, int8_t d1, int8_t d2, int8_t d3, int8_t d4, int8_t d5, int8_t d6, int8_t d7)
|
||||
: _dc(dc), _cs(cs), _wr(wr), _rd(rd),
|
||||
_d0(d0), _d1(d1), _d2(d2), _d3(d3), _d4(d4), _d5(d5), _d6(d6), _d7(d7)
|
||||
{
|
||||
}
|
||||
|
||||
bool Arduino_ESP32PAR8QQQ::begin(int32_t, int8_t)
|
||||
{
|
||||
pinMode(_dc, OUTPUT);
|
||||
digitalWrite(_dc, HIGH); // Data mode
|
||||
if (_dc >= 32)
|
||||
{
|
||||
_dcPinMask = digitalPinToBitMask(_dc);
|
||||
_dcPortSet = (PORTreg_t)GPIO_OUT1_W1TS_REG;
|
||||
_dcPortClr = (PORTreg_t)GPIO_OUT1_W1TC_REG;
|
||||
}
|
||||
else
|
||||
{
|
||||
_dcPinMask = digitalPinToBitMask(_dc);
|
||||
_dcPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_dcPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
}
|
||||
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
pinMode(_cs, OUTPUT);
|
||||
digitalWrite(_cs, HIGH); // disable chip select
|
||||
}
|
||||
if (_cs >= 32)
|
||||
{
|
||||
_csPinMask = digitalPinToBitMask(_cs);
|
||||
_csPortSet = (PORTreg_t)GPIO_OUT1_W1TS_REG;
|
||||
_csPortClr = (PORTreg_t)GPIO_OUT1_W1TC_REG;
|
||||
}
|
||||
else if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
_csPinMask = digitalPinToBitMask(_cs);
|
||||
_csPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_csPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
}
|
||||
|
||||
pinMode(_wr, OUTPUT);
|
||||
digitalWrite(_wr, HIGH); // Set write strobe high (inactive)
|
||||
if (_wr >= 32)
|
||||
{
|
||||
_wrPinMask = digitalPinToBitMask(_wr);
|
||||
_wrPortSet = (PORTreg_t)GPIO_OUT1_W1TS_REG;
|
||||
_wrPortClr = (PORTreg_t)GPIO_OUT1_W1TC_REG;
|
||||
}
|
||||
else
|
||||
{
|
||||
_wrPinMask = digitalPinToBitMask(_wr);
|
||||
_wrPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_wrPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
}
|
||||
|
||||
if (_rd != GFX_NOT_DEFINED)
|
||||
{
|
||||
pinMode(_rd, OUTPUT);
|
||||
digitalWrite(_rd, HIGH);
|
||||
}
|
||||
|
||||
// TODO: check pin range 0-31
|
||||
pinMode(_d0, OUTPUT);
|
||||
pinMode(_d1, OUTPUT);
|
||||
pinMode(_d2, OUTPUT);
|
||||
pinMode(_d3, OUTPUT);
|
||||
pinMode(_d4, OUTPUT);
|
||||
pinMode(_d5, OUTPUT);
|
||||
pinMode(_d6, OUTPUT);
|
||||
pinMode(_d7, OUTPUT);
|
||||
|
||||
if (_d0 >= 32)
|
||||
{
|
||||
_dataPortSet = (PORTreg_t)GPIO_OUT1_W1TS_REG;
|
||||
_dataPortClr = (PORTreg_t)GPIO_OUT1_W1TC_REG;
|
||||
}
|
||||
else
|
||||
{
|
||||
_dataPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_dataPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
}
|
||||
|
||||
// INIT 8-bit mask
|
||||
_dataClrMask = digitalPinToBitMask(_d0) | digitalPinToBitMask(_d1) | digitalPinToBitMask(_d2) | digitalPinToBitMask(_d3) | digitalPinToBitMask(_d4) | digitalPinToBitMask(_d5) | digitalPinToBitMask(_d6) | digitalPinToBitMask(_d7);
|
||||
|
||||
for (int32_t c = 0; c < 256; c++)
|
||||
{
|
||||
_xset_mask[c] = digitalPinToBitMask(_wr);
|
||||
if (c & 0x01)
|
||||
{
|
||||
_xset_mask[c] |= digitalPinToBitMask(_d0);
|
||||
}
|
||||
if (c & 0x02)
|
||||
{
|
||||
_xset_mask[c] |= digitalPinToBitMask(_d1);
|
||||
}
|
||||
if (c & 0x04)
|
||||
{
|
||||
_xset_mask[c] |= digitalPinToBitMask(_d2);
|
||||
}
|
||||
if (c & 0x08)
|
||||
{
|
||||
_xset_mask[c] |= digitalPinToBitMask(_d3);
|
||||
}
|
||||
if (c & 0x10)
|
||||
{
|
||||
_xset_mask[c] |= digitalPinToBitMask(_d4);
|
||||
}
|
||||
if (c & 0x20)
|
||||
{
|
||||
_xset_mask[c] |= digitalPinToBitMask(_d5);
|
||||
}
|
||||
if (c & 0x40)
|
||||
{
|
||||
_xset_mask[c] |= digitalPinToBitMask(_d6);
|
||||
}
|
||||
if (c & 0x80)
|
||||
{
|
||||
_xset_mask[c] |= digitalPinToBitMask(_d7);
|
||||
}
|
||||
}
|
||||
*_dataPortClr = _dataClrMask;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8QQQ::beginWrite()
|
||||
{
|
||||
DC_HIGH();
|
||||
CS_LOW();
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8QQQ::endWrite()
|
||||
{
|
||||
CS_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8QQQ::writeCommand(uint8_t c)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8QQQ::writeCommand16(uint16_t c)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
_data16.value = c;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8QQQ::writeCommandBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
while (len--)
|
||||
{
|
||||
WRITE(*data++);
|
||||
}
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8QQQ::write(uint8_t d)
|
||||
{
|
||||
WRITE(d);
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8QQQ::write16(uint16_t d)
|
||||
{
|
||||
_data16.value = d;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8QQQ::writeRepeat(uint16_t p, uint32_t len)
|
||||
{
|
||||
_data16.value = p;
|
||||
if (_data16.msb == _data16.lsb)
|
||||
{
|
||||
uint32_t setMask = _xset_mask[_data16.msb];
|
||||
*_dataPortClr = _dataClrMask;
|
||||
*_dataPortSet = setMask;
|
||||
while (len--)
|
||||
{
|
||||
*_wrPortClr = _wrPinMask;
|
||||
*_wrPortSet = _wrPinMask;
|
||||
*_wrPortClr = _wrPinMask;
|
||||
*_wrPortSet = _wrPinMask;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t hiMask = _xset_mask[_data16.msb];
|
||||
uint32_t loMask = _xset_mask[_data16.lsb];
|
||||
while (len--)
|
||||
{
|
||||
*_dataPortClr = _dataClrMask;
|
||||
*_dataPortSet = hiMask;
|
||||
|
||||
*_dataPortClr = _dataClrMask;
|
||||
*_dataPortSet = loMask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8QQQ::writePixels(uint16_t *data, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
_data16.value = *data++;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8QQQ::writeC8D8(uint8_t c, uint8_t d)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
WRITE(d);
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8QQQ::writeC8D16(uint8_t c, uint16_t d)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
_data16.value = d;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8QQQ::writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
_data16.value = d1;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
|
||||
_data16.value = d2;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8QQQ::writeC8D16D16Split(uint8_t c, uint16_t d1, uint16_t d2)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
_data16.value = d1;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
|
||||
_data16.value = d2;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8QQQ::writeBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
WRITE(*data++);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8QQQ::writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
_data16.value = idx[*data++];
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_ESP32PAR8QQQ::writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
_data16.value = idx[*data++];
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP32PAR8QQQ::WRITE(uint8_t d)
|
||||
{
|
||||
uint32_t setMask = _xset_mask[d];
|
||||
*_dataPortClr = _dataClrMask;
|
||||
*_dataPortSet = setMask;
|
||||
}
|
||||
|
||||
/******** low level bit twiddling **********/
|
||||
|
||||
GFX_INLINE void Arduino_ESP32PAR8QQQ::DC_HIGH(void)
|
||||
{
|
||||
*_dcPortSet = _dcPinMask;
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP32PAR8QQQ::DC_LOW(void)
|
||||
{
|
||||
*_dcPortClr = _dcPinMask;
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP32PAR8QQQ::CS_HIGH(void)
|
||||
{
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
*_csPortSet = _csPinMask;
|
||||
}
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP32PAR8QQQ::CS_LOW(void)
|
||||
{
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
*_csPortClr = _csPinMask;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // #if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
|
||||
@@ -0,0 +1,67 @@
|
||||
#include "Arduino_DataBus.h"
|
||||
|
||||
#if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
|
||||
|
||||
#ifndef _ARDUINO_ESP32PAR8QQQ_H_
|
||||
#define _ARDUINO_ESP32PAR8QQQ_H_
|
||||
|
||||
class Arduino_ESP32PAR8QQQ : public Arduino_DataBus
|
||||
{
|
||||
public:
|
||||
Arduino_ESP32PAR8QQQ(
|
||||
int8_t dc, int8_t cs, int8_t wr, int8_t rd,
|
||||
int8_t d0, int8_t d1, int8_t d2, int8_t d3, int8_t d4, int8_t d5, int8_t d6, int8_t d7); // Constructor
|
||||
|
||||
bool begin(int32_t speed = GFX_NOT_DEFINED, int8_t dataMode = GFX_NOT_DEFINED) override;
|
||||
void beginWrite() override;
|
||||
void endWrite() override;
|
||||
void writeCommand(uint8_t) override;
|
||||
void writeCommand16(uint16_t) override;
|
||||
void writeCommandBytes(uint8_t *data, uint32_t len) override;
|
||||
void write(uint8_t) override;
|
||||
void write16(uint16_t) override;
|
||||
void writeRepeat(uint16_t p, uint32_t len) override;
|
||||
void writePixels(uint16_t *data, uint32_t len) override;
|
||||
|
||||
void writeC8D8(uint8_t c, uint8_t d) override;
|
||||
void writeC8D16(uint8_t c, uint16_t d) override;
|
||||
void writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2) override;
|
||||
void writeC8D16D16Split(uint8_t c, uint16_t d1, uint16_t d2) override;
|
||||
void writeBytes(uint8_t *data, uint32_t len) override;
|
||||
|
||||
void writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len) override;
|
||||
void writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len) override;
|
||||
|
||||
protected:
|
||||
private:
|
||||
GFX_INLINE void WRITE(uint8_t d);
|
||||
GFX_INLINE void DC_HIGH(void);
|
||||
GFX_INLINE void DC_LOW(void);
|
||||
GFX_INLINE void CS_HIGH(void);
|
||||
GFX_INLINE void CS_LOW(void);
|
||||
|
||||
int8_t _dc, _cs, _wr, _rd;
|
||||
int8_t _d0, _d1, _d2, _d3, _d4, _d5, _d6, _d7;
|
||||
|
||||
PORTreg_t _dcPortSet; ///< PORT register SET
|
||||
PORTreg_t _dcPortClr; ///< PORT register CLEAR
|
||||
uint32_t _dcPinMask; ///< Bitmask
|
||||
|
||||
PORTreg_t _csPortSet; ///< PORT register SET
|
||||
PORTreg_t _csPortClr; ///< PORT register CLEAR
|
||||
uint32_t _csPinMask; ///< Bitmask
|
||||
|
||||
PORTreg_t _wrPortSet; ///< PORT register SET
|
||||
PORTreg_t _wrPortClr; ///< PORT register CLEAR
|
||||
uint32_t _wrPinMask; ///< Bitmask
|
||||
|
||||
PORTreg_t _dataPortSet;
|
||||
PORTreg_t _dataPortClr;
|
||||
uint32_t _dataClrMask;
|
||||
// Lookup table for ESP32 parallel bus interface uses 1kbyte RAM,
|
||||
uint32_t _xset_mask[256];
|
||||
};
|
||||
|
||||
#endif // _ARDUINO_ESP32PAR8QQQ_H_
|
||||
|
||||
#endif // #if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
|
||||
@@ -0,0 +1,824 @@
|
||||
#include "Arduino_ESP32QSPI.h"
|
||||
|
||||
#if defined(ESP32)
|
||||
|
||||
/**
|
||||
* @brief Arduino_ESP32QSPI
|
||||
*
|
||||
*/
|
||||
Arduino_ESP32QSPI::Arduino_ESP32QSPI(
|
||||
int8_t cs, int8_t sck, int8_t mosi, int8_t miso, int8_t quadwp, int8_t quadhd, bool is_shared_interface /* = false */)
|
||||
: _cs(cs), _sck(sck), _mosi(mosi), _miso(miso), _quadwp(quadwp), _quadhd(quadhd), _is_shared_interface(is_shared_interface)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief begin
|
||||
*
|
||||
* @param speed
|
||||
* @param dataMode
|
||||
* @return true
|
||||
* @return false
|
||||
*/
|
||||
bool Arduino_ESP32QSPI::begin(int32_t speed, int8_t dataMode)
|
||||
{
|
||||
// set SPI parameters
|
||||
_speed = (speed == GFX_NOT_DEFINED) ? ESP32QSPI_FREQUENCY : speed;
|
||||
_dataMode = (dataMode == GFX_NOT_DEFINED) ? ESP32QSPI_SPI_MODE : dataMode;
|
||||
|
||||
pinMode(_cs, OUTPUT);
|
||||
digitalWrite(_cs, HIGH); // disable chip select
|
||||
#if (CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
|
||||
if (_cs >= 32)
|
||||
{
|
||||
_csPinMask = digitalPinToBitMask(_cs);
|
||||
_csPortSet = (PORTreg_t)GPIO_OUT1_W1TS_REG;
|
||||
_csPortClr = (PORTreg_t)GPIO_OUT1_W1TC_REG;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
_csPinMask = digitalPinToBitMask(_cs);
|
||||
_csPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_csPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
}
|
||||
|
||||
spi_bus_config_t buscfg = {
|
||||
.mosi_io_num = _mosi,
|
||||
.miso_io_num = _miso,
|
||||
.sclk_io_num = _sck,
|
||||
.quadwp_io_num = _quadwp,
|
||||
.quadhd_io_num = _quadhd,
|
||||
.data4_io_num = -1,
|
||||
.data5_io_num = -1,
|
||||
.data6_io_num = -1,
|
||||
.data7_io_num = -1,
|
||||
.max_transfer_sz = (ESP32QSPI_MAX_PIXELS_AT_ONCE * 16) + 8,
|
||||
.flags = SPICOMMON_BUSFLAG_MASTER | SPICOMMON_BUSFLAG_GPIO_PINS,
|
||||
#if (!defined(ESP_ARDUINO_VERSION_MAJOR)) || (ESP_ARDUINO_VERSION_MAJOR < 3)
|
||||
// skip this
|
||||
#else
|
||||
.isr_cpu_id = ESP_INTR_CPU_AFFINITY_AUTO,
|
||||
#endif
|
||||
.intr_flags = 0};
|
||||
esp_err_t ret = spi_bus_initialize(ESP32QSPI_SPI_HOST, &buscfg, ESP32QSPI_DMA_CHANNEL);
|
||||
if (ret != ESP_OK)
|
||||
{
|
||||
ESP_ERROR_CHECK(ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
spi_device_interface_config_t devcfg = {
|
||||
.command_bits = 8,
|
||||
.address_bits = 24,
|
||||
.dummy_bits = 0,
|
||||
.mode = (uint8_t)_dataMode,
|
||||
#if defined(ESP_ARDUINO_VERSION_MAJOR) && ESP_ARDUINO_VERSION_MAJOR >= 3
|
||||
.clock_source = SPI_CLK_SRC_DEFAULT,
|
||||
#endif
|
||||
.duty_cycle_pos = 0,
|
||||
.cs_ena_pretrans = 0,
|
||||
.cs_ena_posttrans = 0,
|
||||
.clock_speed_hz = _speed,
|
||||
.input_delay_ns = 0,
|
||||
.spics_io_num = -1, // avoid use system CS control
|
||||
.flags = SPI_DEVICE_HALFDUPLEX,
|
||||
.queue_size = 1,
|
||||
.pre_cb = nullptr,
|
||||
.post_cb = nullptr};
|
||||
ret = spi_bus_add_device(ESP32QSPI_SPI_HOST, &devcfg, &_handle);
|
||||
if (ret != ESP_OK)
|
||||
{
|
||||
ESP_ERROR_CHECK(ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!_is_shared_interface)
|
||||
{
|
||||
spi_device_acquire_bus(_handle, portMAX_DELAY);
|
||||
}
|
||||
|
||||
memset(&_spi_tran_ext, 0, sizeof(_spi_tran_ext));
|
||||
_spi_tran = (spi_transaction_t *)&_spi_tran_ext;
|
||||
|
||||
_buffer = (uint8_t *)heap_caps_aligned_alloc(16, ESP32QSPI_MAX_PIXELS_AT_ONCE * 2, MALLOC_CAP_DMA);
|
||||
if (!_buffer)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
_2nd_buffer = (uint8_t *)heap_caps_aligned_alloc(16, ESP32QSPI_MAX_PIXELS_AT_ONCE * 2, MALLOC_CAP_DMA);
|
||||
if (!_2nd_buffer)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief beginWrite
|
||||
*
|
||||
*/
|
||||
void Arduino_ESP32QSPI::beginWrite()
|
||||
{
|
||||
if (_is_shared_interface)
|
||||
{
|
||||
spi_device_acquire_bus(_handle, portMAX_DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief endWrite
|
||||
*
|
||||
*/
|
||||
void Arduino_ESP32QSPI::endWrite()
|
||||
{
|
||||
if (_is_shared_interface)
|
||||
{
|
||||
spi_device_release_bus(_handle);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief writeCommand
|
||||
*
|
||||
* @param c
|
||||
*/
|
||||
void Arduino_ESP32QSPI::writeCommand(uint8_t c)
|
||||
{
|
||||
CS_LOW();
|
||||
_spi_tran_ext.base.flags = SPI_TRANS_MULTILINE_CMD | SPI_TRANS_MULTILINE_ADDR;
|
||||
_spi_tran_ext.base.cmd = 0x02;
|
||||
_spi_tran_ext.base.addr = ((uint32_t)c) << 8;
|
||||
_spi_tran_ext.base.tx_buffer = NULL;
|
||||
_spi_tran_ext.base.length = 0;
|
||||
POLL_START();
|
||||
POLL_END();
|
||||
CS_HIGH();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief writeCommand16
|
||||
*
|
||||
* @param c
|
||||
*/
|
||||
void Arduino_ESP32QSPI::writeCommand16(uint16_t c)
|
||||
{
|
||||
CS_LOW();
|
||||
_spi_tran_ext.base.flags = SPI_TRANS_MULTILINE_CMD | SPI_TRANS_MULTILINE_ADDR;
|
||||
_spi_tran_ext.base.cmd = 0x02;
|
||||
_spi_tran_ext.base.addr = c;
|
||||
_spi_tran_ext.base.tx_buffer = NULL;
|
||||
_spi_tran_ext.base.length = 0;
|
||||
POLL_START();
|
||||
POLL_END();
|
||||
CS_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_ESP32QSPI::writeCommandBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
CS_LOW();
|
||||
uint32_t l;
|
||||
while (len)
|
||||
{
|
||||
l = (len >= (ESP32QSPI_MAX_PIXELS_AT_ONCE << 1)) ? (ESP32QSPI_MAX_PIXELS_AT_ONCE << 1) : len;
|
||||
|
||||
_spi_tran_ext.base.flags = SPI_TRANS_MULTILINE_CMD | SPI_TRANS_MULTILINE_ADDR;
|
||||
_spi_tran_ext.base.tx_buffer = data;
|
||||
_spi_tran_ext.base.length = l << 3;
|
||||
|
||||
POLL_START();
|
||||
POLL_END();
|
||||
|
||||
len -= l;
|
||||
data += l;
|
||||
}
|
||||
CS_HIGH();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief write
|
||||
*
|
||||
* @param d
|
||||
*/
|
||||
void Arduino_ESP32QSPI::write(uint8_t d)
|
||||
{
|
||||
CS_LOW();
|
||||
_spi_tran_ext.base.flags = SPI_TRANS_USE_TXDATA | SPI_TRANS_MODE_QIO;
|
||||
_spi_tran_ext.base.cmd = 0x32;
|
||||
_spi_tran_ext.base.addr = 0x003C00;
|
||||
_spi_tran_ext.base.tx_data[0] = d;
|
||||
_spi_tran_ext.base.length = 8;
|
||||
POLL_START();
|
||||
POLL_END();
|
||||
CS_HIGH();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief write16
|
||||
*
|
||||
* @param d
|
||||
*/
|
||||
void Arduino_ESP32QSPI::write16(uint16_t d)
|
||||
{
|
||||
CS_LOW();
|
||||
_spi_tran_ext.base.flags = SPI_TRANS_USE_TXDATA | SPI_TRANS_MODE_QIO;
|
||||
_spi_tran_ext.base.cmd = 0x32;
|
||||
_spi_tran_ext.base.addr = 0x003C00;
|
||||
_spi_tran_ext.base.tx_data[0] = d >> 8;
|
||||
_spi_tran_ext.base.tx_data[1] = d;
|
||||
_spi_tran_ext.base.length = 16;
|
||||
POLL_START();
|
||||
POLL_END();
|
||||
CS_HIGH();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief writeC8D8
|
||||
*
|
||||
* @param c
|
||||
* @param d
|
||||
*/
|
||||
void Arduino_ESP32QSPI::writeC8D8(uint8_t c, uint8_t d)
|
||||
{
|
||||
CS_LOW();
|
||||
_spi_tran_ext.base.flags = SPI_TRANS_USE_TXDATA | SPI_TRANS_MULTILINE_CMD | SPI_TRANS_MULTILINE_ADDR;
|
||||
_spi_tran_ext.base.cmd = 0x02;
|
||||
_spi_tran_ext.base.addr = ((uint32_t)c) << 8;
|
||||
_spi_tran_ext.base.tx_data[0] = d;
|
||||
_spi_tran_ext.base.length = 8;
|
||||
POLL_START();
|
||||
POLL_END();
|
||||
CS_HIGH();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief writeC8D16D16
|
||||
*
|
||||
* @param c
|
||||
* @param d1
|
||||
* @param d2
|
||||
*/
|
||||
void Arduino_ESP32QSPI::writeC8D16(uint8_t c, uint16_t d)
|
||||
{
|
||||
CS_LOW();
|
||||
_spi_tran_ext.base.flags = SPI_TRANS_USE_TXDATA | SPI_TRANS_MULTILINE_CMD | SPI_TRANS_MULTILINE_ADDR;
|
||||
_spi_tran_ext.base.cmd = 0x02;
|
||||
_spi_tran_ext.base.addr = ((uint32_t)c) << 8;
|
||||
_spi_tran_ext.base.tx_data[0] = d >> 8;
|
||||
_spi_tran_ext.base.tx_data[1] = d;
|
||||
_spi_tran_ext.base.length = 16;
|
||||
POLL_START();
|
||||
POLL_END();
|
||||
CS_HIGH();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief writeC8D16D16
|
||||
*
|
||||
* @param c
|
||||
* @param d1
|
||||
* @param d2
|
||||
*/
|
||||
void Arduino_ESP32QSPI::writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2)
|
||||
{
|
||||
CS_LOW();
|
||||
_spi_tran_ext.base.flags = SPI_TRANS_USE_TXDATA | SPI_TRANS_MULTILINE_CMD | SPI_TRANS_MULTILINE_ADDR;
|
||||
_spi_tran_ext.base.cmd = 0x02;
|
||||
_spi_tran_ext.base.addr = ((uint32_t)c) << 8;
|
||||
_spi_tran_ext.base.tx_data[0] = d1 >> 8;
|
||||
_spi_tran_ext.base.tx_data[1] = d1;
|
||||
_spi_tran_ext.base.tx_data[2] = d2 >> 8;
|
||||
_spi_tran_ext.base.tx_data[3] = d2;
|
||||
_spi_tran_ext.base.length = 32;
|
||||
POLL_START();
|
||||
POLL_END();
|
||||
CS_HIGH();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief writeC8D16D16Split
|
||||
*
|
||||
* @param c
|
||||
* @param d1
|
||||
* @param d2
|
||||
*/
|
||||
void Arduino_ESP32QSPI::writeC8D16D16Split(uint8_t c, uint16_t d1, uint16_t d2)
|
||||
{
|
||||
CS_LOW();
|
||||
_spi_tran_ext.base.flags = SPI_TRANS_USE_TXDATA | SPI_TRANS_MULTILINE_CMD | SPI_TRANS_MULTILINE_ADDR;
|
||||
_spi_tran_ext.base.cmd = 0x02;
|
||||
_spi_tran_ext.base.addr = ((uint32_t)c) << 8;
|
||||
_spi_tran_ext.base.tx_data[0] = d1 >> 8;
|
||||
_spi_tran_ext.base.tx_data[1] = d1;
|
||||
_spi_tran_ext.base.tx_data[2] = d2 >> 8;
|
||||
_spi_tran_ext.base.tx_data[3] = d2;
|
||||
_spi_tran_ext.base.length = 32;
|
||||
POLL_START();
|
||||
POLL_END();
|
||||
CS_HIGH();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief writeC8Bytes
|
||||
*
|
||||
* @param c
|
||||
* @param data
|
||||
* @param len
|
||||
*/
|
||||
void Arduino_ESP32QSPI::writeC8Bytes(uint8_t c, uint8_t *data, uint32_t len)
|
||||
{
|
||||
CS_LOW();
|
||||
_spi_tran_ext.base.flags = SPI_TRANS_MULTILINE_CMD | SPI_TRANS_MULTILINE_ADDR;
|
||||
_spi_tran_ext.base.cmd = 0x02;
|
||||
_spi_tran_ext.base.addr = ((uint32_t)c) << 8;
|
||||
_spi_tran_ext.base.tx_buffer = data;
|
||||
_spi_tran_ext.base.length = len << 3;
|
||||
POLL_START();
|
||||
POLL_END();
|
||||
CS_HIGH();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief writeRepeat
|
||||
*
|
||||
* @param p
|
||||
* @param len
|
||||
*/
|
||||
void Arduino_ESP32QSPI::writeRepeat(uint16_t p, uint32_t len)
|
||||
{
|
||||
bool first_send = true;
|
||||
|
||||
uint16_t bufLen = (len >= ESP32QSPI_MAX_PIXELS_AT_ONCE) ? ESP32QSPI_MAX_PIXELS_AT_ONCE : len;
|
||||
int16_t xferLen, l;
|
||||
uint32_t c32;
|
||||
MSB_32_16_16_SET(c32, p, p);
|
||||
|
||||
l = (bufLen + 1) / 2;
|
||||
for (uint32_t i = 0; i < l; i++)
|
||||
{
|
||||
_buffer32[i] = c32;
|
||||
}
|
||||
|
||||
CS_LOW();
|
||||
// Issue pixels in blocks from temp buffer
|
||||
while (len) // While pixels remain
|
||||
{
|
||||
xferLen = (bufLen <= len) ? bufLen : len; // How many this pass?
|
||||
|
||||
if (first_send)
|
||||
{
|
||||
_spi_tran_ext.base.flags = SPI_TRANS_MODE_QIO;
|
||||
_spi_tran_ext.base.cmd = 0x32;
|
||||
_spi_tran_ext.base.addr = 0x003C00;
|
||||
first_send = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
_spi_tran_ext.base.flags = SPI_TRANS_MODE_QIO | SPI_TRANS_VARIABLE_CMD |
|
||||
SPI_TRANS_VARIABLE_ADDR | SPI_TRANS_VARIABLE_DUMMY;
|
||||
}
|
||||
_spi_tran_ext.base.tx_buffer = _buffer16;
|
||||
_spi_tran_ext.base.length = xferLen << 4;
|
||||
|
||||
POLL_START();
|
||||
POLL_END();
|
||||
|
||||
len -= xferLen;
|
||||
}
|
||||
CS_HIGH();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief writePixels
|
||||
*
|
||||
* @param data
|
||||
* @param len
|
||||
*/
|
||||
void Arduino_ESP32QSPI::writePixels(uint16_t *data, uint32_t len)
|
||||
{
|
||||
|
||||
CS_LOW();
|
||||
uint32_t l, l2;
|
||||
uint16_t p1, p2;
|
||||
bool first_send = true;
|
||||
while (len)
|
||||
{
|
||||
l = (len > ESP32QSPI_MAX_PIXELS_AT_ONCE) ? ESP32QSPI_MAX_PIXELS_AT_ONCE : len;
|
||||
|
||||
if (first_send)
|
||||
{
|
||||
_spi_tran_ext.base.flags = SPI_TRANS_MODE_QIO;
|
||||
_spi_tran_ext.base.cmd = 0x32;
|
||||
_spi_tran_ext.base.addr = 0x003C00;
|
||||
first_send = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
_spi_tran_ext.base.flags = SPI_TRANS_MODE_QIO | SPI_TRANS_VARIABLE_CMD |
|
||||
SPI_TRANS_VARIABLE_ADDR | SPI_TRANS_VARIABLE_DUMMY;
|
||||
}
|
||||
l2 = l >> 1;
|
||||
for (uint32_t i = 0; i < l2; ++i)
|
||||
{
|
||||
p1 = *data++;
|
||||
p2 = *data++;
|
||||
MSB_32_16_16_SET(_buffer32[i], p1, p2);
|
||||
}
|
||||
if (l & 1)
|
||||
{
|
||||
p1 = *data++;
|
||||
MSB_16_SET(_buffer16[l - 1], p1);
|
||||
}
|
||||
|
||||
_spi_tran_ext.base.tx_buffer = _buffer32;
|
||||
_spi_tran_ext.base.length = l << 4;
|
||||
|
||||
POLL_START();
|
||||
POLL_END();
|
||||
|
||||
len -= l;
|
||||
}
|
||||
CS_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_ESP32QSPI::batchOperation(const uint8_t *operations, size_t len)
|
||||
{
|
||||
for (size_t i = 0; i < len; ++i)
|
||||
{
|
||||
uint8_t l = 0;
|
||||
switch (operations[i])
|
||||
{
|
||||
case BEGIN_WRITE:
|
||||
beginWrite();
|
||||
break;
|
||||
case WRITE_COMMAND_8:
|
||||
writeCommand(operations[++i]);
|
||||
break;
|
||||
case WRITE_COMMAND_16:
|
||||
_data16.msb = operations[++i];
|
||||
_data16.lsb = operations[++i];
|
||||
writeCommand16(_data16.value);
|
||||
break;
|
||||
case WRITE_DATA_8:
|
||||
write(operations[++i]);
|
||||
break;
|
||||
case WRITE_DATA_16:
|
||||
_data16.msb = operations[++i];
|
||||
_data16.lsb = operations[++i];
|
||||
write16(_data16.value);
|
||||
break;
|
||||
case WRITE_BYTES:
|
||||
l = operations[++i];
|
||||
memcpy(_buffer, operations + i + 1, l);
|
||||
i += l;
|
||||
writeBytes(_buffer, l);
|
||||
break;
|
||||
case WRITE_C8_D8:
|
||||
l = operations[++i];
|
||||
writeC8D8(l, operations[++i]);
|
||||
break;
|
||||
case WRITE_C8_D16:
|
||||
l = operations[++i];
|
||||
_data16.msb = operations[++i];
|
||||
_data16.lsb = operations[++i];
|
||||
writeC8D16(l, _data16.value);
|
||||
break;
|
||||
case WRITE_C8_BYTES:
|
||||
{
|
||||
uint8_t c = operations[++i];
|
||||
l = operations[++i];
|
||||
memcpy(_buffer, operations + i + 1, l);
|
||||
i += l;
|
||||
writeC8Bytes(c, _buffer, l);
|
||||
}
|
||||
break;
|
||||
case WRITE_C16_D16:
|
||||
break;
|
||||
case END_WRITE:
|
||||
endWrite();
|
||||
break;
|
||||
case DELAY:
|
||||
delay(operations[++i]);
|
||||
break;
|
||||
default:
|
||||
printf("Unknown operation id at %d: %d\n", i, operations[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief writeBytes
|
||||
*
|
||||
* @param data
|
||||
* @param len
|
||||
*/
|
||||
void Arduino_ESP32QSPI::writeBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
CS_LOW();
|
||||
uint32_t l;
|
||||
bool first_send = true;
|
||||
while (len)
|
||||
{
|
||||
l = (len >= (ESP32QSPI_MAX_PIXELS_AT_ONCE << 1)) ? (ESP32QSPI_MAX_PIXELS_AT_ONCE << 1) : len;
|
||||
|
||||
if (first_send)
|
||||
{
|
||||
_spi_tran_ext.base.flags = SPI_TRANS_MODE_QIO;
|
||||
_spi_tran_ext.base.cmd = 0x32;
|
||||
_spi_tran_ext.base.addr = 0x003C00;
|
||||
first_send = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
_spi_tran_ext.base.flags = SPI_TRANS_MODE_QIO | SPI_TRANS_VARIABLE_CMD |
|
||||
SPI_TRANS_VARIABLE_ADDR | SPI_TRANS_VARIABLE_DUMMY;
|
||||
}
|
||||
|
||||
_spi_tran_ext.base.tx_buffer = data;
|
||||
_spi_tran_ext.base.length = l << 3;
|
||||
|
||||
POLL_START();
|
||||
POLL_END();
|
||||
|
||||
len -= l;
|
||||
data += l;
|
||||
}
|
||||
CS_HIGH();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief write16bitBeRGBBitmapR1
|
||||
*
|
||||
* @param bitmap
|
||||
* @param w
|
||||
* @param h
|
||||
*/
|
||||
void Arduino_ESP32QSPI::write16bitBeRGBBitmapR1(uint16_t *bitmap, int16_t w, int16_t h)
|
||||
{
|
||||
if (h > ESP32QSPI_MAX_PIXELS_AT_ONCE)
|
||||
{
|
||||
log_e("h > ESP32QSPI_MAX_PIXELS_AT_ONCE, h: %d", h);
|
||||
}
|
||||
else
|
||||
{
|
||||
CS_LOW();
|
||||
uint32_t l = h << 4;
|
||||
bool first_send = true;
|
||||
uint16_t *p;
|
||||
uint16_t *origin_offset = bitmap + ((h - 1) * w);
|
||||
|
||||
for (int16_t i = 0; i < w; i++)
|
||||
{
|
||||
if (first_send)
|
||||
{
|
||||
_spi_tran_ext.base.flags = SPI_TRANS_MODE_QIO;
|
||||
_spi_tran_ext.base.cmd = 0x32;
|
||||
_spi_tran_ext.base.addr = 0x003C00;
|
||||
first_send = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
POLL_END();
|
||||
_spi_tran_ext.base.flags = SPI_TRANS_MODE_QIO | SPI_TRANS_VARIABLE_CMD |
|
||||
SPI_TRANS_VARIABLE_ADDR | SPI_TRANS_VARIABLE_DUMMY;
|
||||
}
|
||||
|
||||
p = origin_offset + i;
|
||||
for (int16_t j = 0; j < h; j++)
|
||||
{
|
||||
_buffer16[j] = *p;
|
||||
p -= w;
|
||||
}
|
||||
|
||||
_spi_tran_ext.base.tx_buffer = _buffer16;
|
||||
_spi_tran_ext.base.length = l;
|
||||
|
||||
POLL_START();
|
||||
}
|
||||
POLL_END();
|
||||
CS_HIGH();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief writeIndexedPixels
|
||||
*
|
||||
* @param data
|
||||
* @param idx
|
||||
* @param len
|
||||
*/
|
||||
void Arduino_ESP32QSPI::writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len)
|
||||
{
|
||||
CS_LOW();
|
||||
uint32_t l, l2;
|
||||
uint16_t p1, p2;
|
||||
bool first_send = true;
|
||||
while (len)
|
||||
{
|
||||
l = (len > ESP32QSPI_MAX_PIXELS_AT_ONCE) ? ESP32QSPI_MAX_PIXELS_AT_ONCE : len;
|
||||
|
||||
if (first_send)
|
||||
{
|
||||
_spi_tran_ext.base.flags = SPI_TRANS_MODE_QIO;
|
||||
_spi_tran_ext.base.cmd = 0x32;
|
||||
_spi_tran_ext.base.addr = 0x003C00;
|
||||
first_send = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
_spi_tran_ext.base.flags = SPI_TRANS_MODE_QIO | SPI_TRANS_VARIABLE_CMD |
|
||||
SPI_TRANS_VARIABLE_ADDR | SPI_TRANS_VARIABLE_DUMMY;
|
||||
}
|
||||
l2 = l >> 1;
|
||||
for (uint32_t i = 0; i < l2; ++i)
|
||||
{
|
||||
p1 = idx[*data++];
|
||||
p2 = idx[*data++];
|
||||
MSB_32_16_16_SET(_buffer32[i], p1, p2);
|
||||
}
|
||||
if (l & 1)
|
||||
{
|
||||
p1 = idx[*data++];
|
||||
MSB_16_SET(_buffer16[l - 1], p1);
|
||||
}
|
||||
|
||||
_spi_tran_ext.base.tx_buffer = _buffer32;
|
||||
_spi_tran_ext.base.length = l << 4;
|
||||
|
||||
POLL_START();
|
||||
POLL_END();
|
||||
|
||||
len -= l;
|
||||
}
|
||||
CS_HIGH();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief writeIndexedPixelsDouble
|
||||
*
|
||||
* @param data
|
||||
* @param idx
|
||||
* @param len
|
||||
*/
|
||||
void Arduino_ESP32QSPI::writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len)
|
||||
{
|
||||
CS_LOW();
|
||||
uint32_t l;
|
||||
uint16_t p;
|
||||
bool first_send = true;
|
||||
while (len)
|
||||
{
|
||||
l = (len > (ESP32QSPI_MAX_PIXELS_AT_ONCE >> 1)) ? (ESP32QSPI_MAX_PIXELS_AT_ONCE >> 1) : len;
|
||||
|
||||
if (first_send)
|
||||
{
|
||||
_spi_tran_ext.base.flags = SPI_TRANS_MODE_QIO;
|
||||
_spi_tran_ext.base.cmd = 0x32;
|
||||
_spi_tran_ext.base.addr = 0x003C00;
|
||||
first_send = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
_spi_tran_ext.base.flags = SPI_TRANS_MODE_QIO | SPI_TRANS_VARIABLE_CMD |
|
||||
SPI_TRANS_VARIABLE_ADDR | SPI_TRANS_VARIABLE_DUMMY;
|
||||
}
|
||||
for (uint32_t i = 0; i < l; ++i)
|
||||
{
|
||||
p = idx[*data++];
|
||||
MSB_32_16_16_SET(_buffer32[i], p, p);
|
||||
}
|
||||
|
||||
_spi_tran_ext.base.tx_buffer = _buffer32;
|
||||
_spi_tran_ext.base.length = l << 5;
|
||||
|
||||
POLL_START();
|
||||
POLL_END();
|
||||
|
||||
len -= l;
|
||||
}
|
||||
CS_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_ESP32QSPI::writeYCbCrPixels(uint8_t *yData, uint8_t *cbData, uint8_t *crData, uint16_t w, uint16_t h)
|
||||
{
|
||||
if (w > (ESP32QSPI_MAX_PIXELS_AT_ONCE / 2))
|
||||
{
|
||||
Arduino_DataBus::writeYCbCrPixels(yData, cbData, crData, w, h);
|
||||
}
|
||||
else
|
||||
{
|
||||
bool first_send = true;
|
||||
|
||||
int cols = w >> 1;
|
||||
int rows = h >> 1;
|
||||
uint8_t *yData2 = yData + w;
|
||||
uint16_t *dest = _buffer16;
|
||||
uint16_t *dest2 = dest + w;
|
||||
|
||||
uint16_t out_bits = w << 5;
|
||||
|
||||
uint8_t pxCb, pxCr;
|
||||
int16_t pxR, pxG, pxB, pxY;
|
||||
|
||||
CS_LOW();
|
||||
for (int row = 0; row < rows; ++row)
|
||||
{
|
||||
for (int col = 0; col < cols; ++col)
|
||||
{
|
||||
pxCb = *cbData++;
|
||||
pxCr = *crData++;
|
||||
pxR = CR2R16[pxCr];
|
||||
pxG = -CB2G16[pxCb] - CR2G16[pxCr];
|
||||
pxB = CB2B16[pxCb];
|
||||
|
||||
pxY = Y2I16[*yData++];
|
||||
*dest++ = CLIPRBE[pxY + pxR] | CLIPGBE[pxY + pxG] | CLIPBBE[pxY + pxB];
|
||||
pxY = Y2I16[*yData++];
|
||||
*dest++ = CLIPRBE[pxY + pxR] | CLIPGBE[pxY + pxG] | CLIPBBE[pxY + pxB];
|
||||
pxY = Y2I16[*yData2++];
|
||||
*dest2++ = CLIPRBE[pxY + pxR] | CLIPGBE[pxY + pxG] | CLIPBBE[pxY + pxB];
|
||||
pxY = Y2I16[*yData2++];
|
||||
*dest2++ = CLIPRBE[pxY + pxR] | CLIPGBE[pxY + pxG] | CLIPBBE[pxY + pxB];
|
||||
}
|
||||
yData += w;
|
||||
yData2 += w;
|
||||
|
||||
if (first_send)
|
||||
{
|
||||
_spi_tran_ext.base.flags = SPI_TRANS_MODE_QIO;
|
||||
_spi_tran_ext.base.cmd = 0x32;
|
||||
_spi_tran_ext.base.addr = 0x003C00;
|
||||
first_send = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
POLL_END();
|
||||
_spi_tran_ext.base.flags = SPI_TRANS_MODE_QIO | SPI_TRANS_VARIABLE_CMD |
|
||||
SPI_TRANS_VARIABLE_ADDR | SPI_TRANS_VARIABLE_DUMMY;
|
||||
}
|
||||
|
||||
if (row & 1)
|
||||
{
|
||||
_spi_tran_ext.base.tx_buffer = _2nd_buffer32;
|
||||
dest = _buffer16;
|
||||
}
|
||||
else
|
||||
{
|
||||
_spi_tran_ext.base.tx_buffer = _buffer32;
|
||||
dest = _2nd_buffer16;
|
||||
}
|
||||
_spi_tran_ext.base.length = out_bits;
|
||||
|
||||
POLL_START();
|
||||
dest2 = dest + w;
|
||||
}
|
||||
POLL_END();
|
||||
CS_HIGH();
|
||||
}
|
||||
}
|
||||
/******** low level bit twiddling **********/
|
||||
|
||||
/**
|
||||
* @brief CS_HIGH
|
||||
*
|
||||
* @return GFX_INLINE
|
||||
*/
|
||||
GFX_INLINE void Arduino_ESP32QSPI::CS_HIGH(void)
|
||||
{
|
||||
*_csPortSet = _csPinMask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief CS_LOW
|
||||
*
|
||||
* @return GFX_INLINE
|
||||
*/
|
||||
GFX_INLINE void Arduino_ESP32QSPI::CS_LOW(void)
|
||||
{
|
||||
*_csPortClr = _csPinMask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief POLL_START
|
||||
*
|
||||
* @return GFX_INLINE
|
||||
*/
|
||||
GFX_INLINE void Arduino_ESP32QSPI::POLL_START()
|
||||
{
|
||||
spi_device_polling_start(_handle, _spi_tran, portMAX_DELAY);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief POLL_END
|
||||
*
|
||||
* @return GFX_INLINE
|
||||
*/
|
||||
GFX_INLINE void Arduino_ESP32QSPI::POLL_END()
|
||||
{
|
||||
spi_device_polling_end(_handle, portMAX_DELAY);
|
||||
}
|
||||
|
||||
#endif // #if defined(ESP32)
|
||||
@@ -0,0 +1,89 @@
|
||||
#pragma once
|
||||
|
||||
#include "Arduino_DataBus.h"
|
||||
|
||||
#if defined(ESP32)
|
||||
#include <driver/spi_master.h>
|
||||
|
||||
#ifndef ESP32QSPI_MAX_PIXELS_AT_ONCE
|
||||
#define ESP32QSPI_MAX_PIXELS_AT_ONCE 1024
|
||||
#endif
|
||||
#ifndef ESP32QSPI_FREQUENCY
|
||||
#define ESP32QSPI_FREQUENCY 80000000
|
||||
#endif
|
||||
#ifndef ESP32QSPI_SPI_MODE
|
||||
#define ESP32QSPI_SPI_MODE SPI_MODE0
|
||||
#endif
|
||||
#ifndef ESP32QSPI_SPI_HOST
|
||||
#define ESP32QSPI_SPI_HOST SPI2_HOST
|
||||
#endif
|
||||
#ifndef ESP32QSPI_DMA_CHANNEL
|
||||
#define ESP32QSPI_DMA_CHANNEL SPI_DMA_CH_AUTO
|
||||
#endif
|
||||
|
||||
class Arduino_ESP32QSPI : public Arduino_DataBus
|
||||
{
|
||||
public:
|
||||
Arduino_ESP32QSPI(
|
||||
int8_t cs, int8_t sck, int8_t mosi, int8_t miso, int8_t quadwp, int8_t quadhd, bool is_shared_interface = false); // Constructor
|
||||
|
||||
bool begin(int32_t speed = GFX_NOT_DEFINED, int8_t dataMode = GFX_NOT_DEFINED) override;
|
||||
void beginWrite() override;
|
||||
void endWrite() override;
|
||||
void writeCommand(uint8_t) override;
|
||||
void writeCommand16(uint16_t) override;
|
||||
void writeCommandBytes(uint8_t *data, uint32_t len) override;
|
||||
void write(uint8_t) override;
|
||||
void write16(uint16_t) override;
|
||||
|
||||
void writeC8D8(uint8_t c, uint8_t d) override;
|
||||
void writeC8D16(uint8_t c, uint16_t d) override;
|
||||
void writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2) override;
|
||||
void writeC8D16D16Split(uint8_t c, uint16_t d1, uint16_t d2) override;
|
||||
|
||||
void writeC8Bytes(uint8_t c, uint8_t *data, uint32_t len);
|
||||
|
||||
void writeRepeat(uint16_t p, uint32_t len) override;
|
||||
void writePixels(uint16_t *data, uint32_t len) override;
|
||||
void write16bitBeRGBBitmapR1(uint16_t *bitmap, int16_t w, int16_t h) override;
|
||||
|
||||
void batchOperation(const uint8_t *operations, size_t len) override;
|
||||
void writeBytes(uint8_t *data, uint32_t len) override;
|
||||
|
||||
void writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len) override;
|
||||
void writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len) override;
|
||||
void writeYCbCrPixels(uint8_t *yData, uint8_t *cbData, uint8_t *crData, uint16_t w, uint16_t h) override;
|
||||
|
||||
protected:
|
||||
private:
|
||||
GFX_INLINE void CS_HIGH(void);
|
||||
GFX_INLINE void CS_LOW(void);
|
||||
GFX_INLINE void POLL_START();
|
||||
GFX_INLINE void POLL_END();
|
||||
|
||||
int8_t _cs, _sck, _mosi, _miso, _quadwp, _quadhd;
|
||||
bool _is_shared_interface;
|
||||
|
||||
PORTreg_t _csPortSet; ///< PORT register for chip select SET
|
||||
PORTreg_t _csPortClr; ///< PORT register for chip select CLEAR
|
||||
uint32_t _csPinMask; ///< Bitmask for chip select
|
||||
|
||||
spi_device_handle_t _handle;
|
||||
spi_transaction_ext_t _spi_tran_ext;
|
||||
spi_transaction_t *_spi_tran;
|
||||
|
||||
union
|
||||
{
|
||||
uint8_t* _buffer;
|
||||
uint16_t* _buffer16;
|
||||
uint32_t* _buffer32;
|
||||
};
|
||||
union
|
||||
{
|
||||
uint8_t *_2nd_buffer;
|
||||
uint16_t *_2nd_buffer16;
|
||||
uint32_t *_2nd_buffer32;
|
||||
};
|
||||
};
|
||||
|
||||
#endif // #if defined(ESP32)
|
||||
@@ -0,0 +1,158 @@
|
||||
// ESP_LCD_Panel implementation for esp32s3.
|
||||
|
||||
#include "Arduino_ESP32RGBPanel.h"
|
||||
|
||||
#if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)
|
||||
Arduino_ESP32RGBPanel::Arduino_ESP32RGBPanel(
|
||||
int8_t de, int8_t vsync, int8_t hsync, int8_t pclk,
|
||||
int8_t r0, int8_t r1, int8_t r2, int8_t r3, int8_t r4,
|
||||
int8_t g0, int8_t g1, int8_t g2, int8_t g3, int8_t g4, int8_t g5,
|
||||
int8_t b0, int8_t b1, int8_t b2, int8_t b3, int8_t b4,
|
||||
uint16_t hsync_polarity, uint16_t hsync_front_porch, uint16_t hsync_pulse_width, uint16_t hsync_back_porch,
|
||||
uint16_t vsync_polarity, uint16_t vsync_front_porch, uint16_t vsync_pulse_width, uint16_t vsync_back_porch,
|
||||
uint16_t pclk_active_neg, int32_t prefer_speed, bool useBigEndian,
|
||||
uint16_t de_idle_high, uint16_t pclk_idle_high)
|
||||
: _de(de), _vsync(vsync), _hsync(hsync), _pclk(pclk),
|
||||
_r0(r0), _r1(r1), _r2(r2), _r3(r3), _r4(r4),
|
||||
_g0(g0), _g1(g1), _g2(g2), _g3(g3), _g4(g4), _g5(g5),
|
||||
_b0(b0), _b1(b1), _b2(b2), _b3(b3), _b4(b4),
|
||||
_hsync_polarity(hsync_polarity), _hsync_front_porch(hsync_front_porch), _hsync_pulse_width(hsync_pulse_width), _hsync_back_porch(hsync_back_porch),
|
||||
_vsync_polarity(vsync_polarity), _vsync_front_porch(vsync_front_porch), _vsync_pulse_width(vsync_pulse_width), _vsync_back_porch(vsync_back_porch),
|
||||
_pclk_active_neg(pclk_active_neg), _prefer_speed(prefer_speed), _useBigEndian(useBigEndian),
|
||||
_de_idle_high(de_idle_high), _pclk_idle_high(pclk_idle_high)
|
||||
{
|
||||
}
|
||||
|
||||
bool Arduino_ESP32RGBPanel::begin(int32_t speed)
|
||||
{
|
||||
if (speed == GFX_NOT_DEFINED)
|
||||
{
|
||||
#ifdef CONFIG_SPIRAM_MODE_QUAD
|
||||
_speed = 6000000L;
|
||||
#else
|
||||
_speed = 12000000L;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
_speed = speed;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint16_t *Arduino_ESP32RGBPanel::getFrameBuffer(int16_t w, int16_t h)
|
||||
{
|
||||
esp_lcd_rgb_panel_config_t panel_config = {
|
||||
#if (!defined(ESP_ARDUINO_VERSION_MAJOR)) || (ESP_ARDUINO_VERSION_MAJOR < 3)
|
||||
.clk_src = LCD_CLK_SRC_PLL160M,
|
||||
#else
|
||||
.clk_src = LCD_CLK_SRC_DEFAULT,
|
||||
#endif
|
||||
.timings = {
|
||||
.pclk_hz = (uint32_t)((_prefer_speed == GFX_NOT_DEFINED) ? _speed : _prefer_speed),
|
||||
.h_res = (uint32_t)w,
|
||||
.v_res = (uint32_t)h,
|
||||
.hsync_pulse_width = _hsync_pulse_width,
|
||||
.hsync_back_porch = _hsync_back_porch,
|
||||
.hsync_front_porch = _hsync_front_porch,
|
||||
.vsync_pulse_width = _vsync_pulse_width,
|
||||
.vsync_back_porch = _vsync_back_porch,
|
||||
.vsync_front_porch = _vsync_front_porch,
|
||||
.flags = {
|
||||
.hsync_idle_low = (uint32_t)((_hsync_polarity == 0) ? 1 : 0),
|
||||
.vsync_idle_low = (uint32_t)((_vsync_polarity == 0) ? 1 : 0),
|
||||
.de_idle_high = _de_idle_high,
|
||||
.pclk_active_neg = _pclk_active_neg,
|
||||
.pclk_idle_high = _pclk_idle_high,
|
||||
},
|
||||
},
|
||||
.data_width = 16, // RGB565 in parallel mode, thus 16 bits in width
|
||||
#if (!defined(ESP_ARDUINO_VERSION_MAJOR)) || (ESP_ARDUINO_VERSION_MAJOR < 3)
|
||||
#else
|
||||
.bits_per_pixel = 16,
|
||||
.num_fbs = 1,
|
||||
.bounce_buffer_size_px = (size_t)(w * 40),
|
||||
#endif
|
||||
.sram_trans_align = 8,
|
||||
.psram_trans_align = 64,
|
||||
.hsync_gpio_num = _hsync,
|
||||
.vsync_gpio_num = _vsync,
|
||||
.de_gpio_num = _de,
|
||||
.pclk_gpio_num = _pclk,
|
||||
.disp_gpio_num = GPIO_NUM_NC, // -1
|
||||
#if defined(ESP_ARDUINO_VERSION_MAJOR) && ESP_ARDUINO_VERSION_MAJOR >= 3
|
||||
.data_gpio_nums = {0},
|
||||
#endif
|
||||
.flags = {
|
||||
.disp_active_low = true,
|
||||
#if defined(ESP_ARDUINO_VERSION_MAJOR) && ESP_ARDUINO_VERSION_MAJOR >= 3
|
||||
.refresh_on_demand = false,
|
||||
#endif
|
||||
.fb_in_psram = true, // allocate frame buffer from PSRAM
|
||||
#if defined(ESP_ARDUINO_VERSION_MAJOR) && ESP_ARDUINO_VERSION_MAJOR >= 3
|
||||
.double_fb = false,
|
||||
.no_fb = false,
|
||||
.bb_invalidate_cache = false,
|
||||
#endif
|
||||
},
|
||||
};
|
||||
|
||||
if (_useBigEndian)
|
||||
{
|
||||
panel_config.data_gpio_nums[0] = _g3;
|
||||
panel_config.data_gpio_nums[1] = _g4;
|
||||
panel_config.data_gpio_nums[2] = _g5;
|
||||
panel_config.data_gpio_nums[3] = _r0;
|
||||
panel_config.data_gpio_nums[4] = _r1;
|
||||
panel_config.data_gpio_nums[5] = _r2;
|
||||
panel_config.data_gpio_nums[6] = _r3;
|
||||
panel_config.data_gpio_nums[7] = _r4;
|
||||
panel_config.data_gpio_nums[8] = _b0;
|
||||
panel_config.data_gpio_nums[9] = _b1;
|
||||
panel_config.data_gpio_nums[10] = _b2;
|
||||
panel_config.data_gpio_nums[11] = _b3;
|
||||
panel_config.data_gpio_nums[12] = _b4;
|
||||
panel_config.data_gpio_nums[13] = _g0;
|
||||
panel_config.data_gpio_nums[14] = _g1;
|
||||
panel_config.data_gpio_nums[15] = _g2;
|
||||
}
|
||||
else
|
||||
{
|
||||
panel_config.data_gpio_nums[0] = _b0;
|
||||
panel_config.data_gpio_nums[1] = _b1;
|
||||
panel_config.data_gpio_nums[2] = _b2;
|
||||
panel_config.data_gpio_nums[3] = _b3;
|
||||
panel_config.data_gpio_nums[4] = _b4;
|
||||
panel_config.data_gpio_nums[5] = _g0;
|
||||
panel_config.data_gpio_nums[6] = _g1;
|
||||
panel_config.data_gpio_nums[7] = _g2;
|
||||
panel_config.data_gpio_nums[8] = _g3;
|
||||
panel_config.data_gpio_nums[9] = _g4;
|
||||
panel_config.data_gpio_nums[10] = _g5;
|
||||
panel_config.data_gpio_nums[11] = _r0;
|
||||
panel_config.data_gpio_nums[12] = _r1;
|
||||
panel_config.data_gpio_nums[13] = _r2;
|
||||
panel_config.data_gpio_nums[14] = _r3;
|
||||
panel_config.data_gpio_nums[15] = _r4;
|
||||
}
|
||||
|
||||
ESP_ERROR_CHECK(esp_lcd_new_rgb_panel(&panel_config, &_panel_handle));
|
||||
|
||||
ESP_ERROR_CHECK(esp_lcd_panel_reset(_panel_handle));
|
||||
ESP_ERROR_CHECK(esp_lcd_panel_init(_panel_handle));
|
||||
|
||||
#if (!defined(ESP_ARDUINO_VERSION_MAJOR)) || (ESP_ARDUINO_VERSION_MAJOR < 3)
|
||||
esp_rgb_panel_t *_rgb_panel;
|
||||
_rgb_panel = __containerof(_panel_handle, esp_rgb_panel_t, base);
|
||||
|
||||
return (uint16_t *)_rgb_panel->fb;
|
||||
#else
|
||||
void *frame_buffer = nullptr;
|
||||
ESP_ERROR_CHECK(esp_lcd_rgb_panel_get_frame_buffer(_panel_handle, 1, &frame_buffer));
|
||||
|
||||
return ((uint16_t *)frame_buffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // #if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)
|
||||
@@ -0,0 +1,118 @@
|
||||
#pragma once
|
||||
|
||||
// ESP_LCD_Panel implementation for esp32s3.
|
||||
|
||||
// This panel implementation requires a hardware setup with
|
||||
// * RGB LCD peripheral supported (esps3 for now)
|
||||
// * Octal PSRAM onboard
|
||||
// * RGB panel, 16 bit-width, with HSYNC, VSYNC and DE signal
|
||||
//
|
||||
// It uses a Single Frame Buffer in PSRAM
|
||||
//
|
||||
// See: (ESP32 board version 3.x)
|
||||
// * https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/api-reference/peripherals/lcd/rgb_lcd.html
|
||||
// * https://github.com/espressif/esp-idf/blob/master/examples/peripherals/lcd/rgb_panel/README.md
|
||||
//
|
||||
// The prior implementation (ESP32 board version 2.x) was largely undocumented.
|
||||
|
||||
#include "Arduino_DataBus.h"
|
||||
|
||||
#if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)
|
||||
|
||||
#include "esp_lcd_panel_rgb.h"
|
||||
#include "esp_lcd_panel_ops.h"
|
||||
|
||||
#include "esp32s3/rom/cache.h"
|
||||
// This function is located in ROM (also see esp_rom/${target}/ld/${target}.rom.ld)
|
||||
extern int Cache_WriteBack_Addr(uint32_t addr, uint32_t size);
|
||||
|
||||
#if (!defined(ESP_ARDUINO_VERSION_MAJOR)) || (ESP_ARDUINO_VERSION_MAJOR < 3)
|
||||
#include "esp_lcd_panel_io.h"
|
||||
#include "esp_lcd_panel_vendor.h"
|
||||
#include "esp_lcd_panel_interface.h"
|
||||
#include "esp_private/gdma.h"
|
||||
#include "esp_pm.h"
|
||||
#include "hal/dma_types.h"
|
||||
|
||||
#include "hal/lcd_hal.h"
|
||||
#include "hal/lcd_ll.h"
|
||||
|
||||
// extract from esp-idf esp_lcd_rgb_panel.c
|
||||
struct esp_rgb_panel_t
|
||||
{
|
||||
esp_lcd_panel_t base; // Base class of generic lcd panel
|
||||
int panel_id; // LCD panel ID
|
||||
lcd_hal_context_t hal; // Hal layer object
|
||||
size_t data_width; // Number of data lines (e.g. for RGB565, the data width is 16)
|
||||
size_t sram_trans_align; // Alignment for framebuffer that allocated in SRAM
|
||||
size_t psram_trans_align; // Alignment for framebuffer that allocated in PSRAM
|
||||
int disp_gpio_num; // Display control GPIO, which is used to perform action like "disp_off"
|
||||
intr_handle_t intr; // LCD peripheral interrupt handle
|
||||
esp_pm_lock_handle_t pm_lock; // Power management lock
|
||||
size_t num_dma_nodes; // Number of DMA descriptors that used to carry the frame buffer
|
||||
uint8_t *fb; // Frame buffer
|
||||
size_t fb_size; // Size of frame buffer
|
||||
int data_gpio_nums[SOC_LCD_RGB_DATA_WIDTH]; // GPIOs used for data lines, we keep these GPIOs for action like "invert_color"
|
||||
size_t resolution_hz; // Peripheral clock resolution
|
||||
esp_lcd_rgb_timing_t timings; // RGB timing parameters (e.g. pclk, sync pulse, porch width)
|
||||
gdma_channel_handle_t dma_chan; // DMA channel handle
|
||||
esp_lcd_rgb_panel_frame_trans_done_cb_t on_frame_trans_done; // Callback, invoked after frame trans done
|
||||
void *user_ctx; // Reserved user's data of callback functions
|
||||
int x_gap; // Extra gap in x coordinate, it's used when calculate the flush window
|
||||
int y_gap; // Extra gap in y coordinate, it's used when calculate the flush window
|
||||
struct
|
||||
{
|
||||
unsigned int disp_en_level : 1; // The level which can turn on the screen by `disp_gpio_num`
|
||||
unsigned int stream_mode : 1; // If set, the LCD transfers data continuously, otherwise, it stops refreshing the LCD when transaction done
|
||||
unsigned int fb_in_psram : 1; // Whether the frame buffer is in PSRAM
|
||||
} flags;
|
||||
dma_descriptor_t dma_nodes[]; // DMA descriptor pool of size `num_dma_nodes`
|
||||
};
|
||||
#endif // #if (!defined(ESP_ARDUINO_VERSION_MAJOR)) || (ESP_ARDUINO_VERSION_MAJOR < 3)
|
||||
|
||||
class Arduino_ESP32RGBPanel
|
||||
{
|
||||
public:
|
||||
Arduino_ESP32RGBPanel(
|
||||
int8_t de, int8_t vsync, int8_t hsync, int8_t pclk,
|
||||
int8_t r0, int8_t r1, int8_t r2, int8_t r3, int8_t r4,
|
||||
int8_t g0, int8_t g1, int8_t g2, int8_t g3, int8_t g4, int8_t g5,
|
||||
int8_t b0, int8_t b1, int8_t b2, int8_t b3, int8_t b4,
|
||||
uint16_t hsync_polarity, uint16_t hsync_front_porch, uint16_t hsync_pulse_width, uint16_t hsync_back_porch,
|
||||
uint16_t vsync_polarity, uint16_t vsync_front_porch, uint16_t vsync_pulse_width, uint16_t vsync_back_porch,
|
||||
uint16_t pclk_active_neg = 0, int32_t prefer_speed = GFX_NOT_DEFINED, bool useBigEndian = false,
|
||||
uint16_t de_idle_high = 0, uint16_t pclk_idle_high = 0);
|
||||
|
||||
bool begin(int32_t speed = GFX_NOT_DEFINED);
|
||||
|
||||
bool isUseBigEndian() {
|
||||
return _useBigEndian;
|
||||
}
|
||||
|
||||
uint16_t *getFrameBuffer(int16_t w, int16_t h);
|
||||
|
||||
protected:
|
||||
private:
|
||||
int32_t _speed;
|
||||
int8_t _de, _vsync, _hsync, _pclk;
|
||||
int8_t _r0, _r1, _r2, _r3, _r4;
|
||||
int8_t _g0, _g1, _g2, _g3, _g4, _g5;
|
||||
int8_t _b0, _b1, _b2, _b3, _b4;
|
||||
uint16_t _hsync_polarity;
|
||||
uint16_t _hsync_front_porch;
|
||||
uint16_t _hsync_pulse_width;
|
||||
uint16_t _hsync_back_porch;
|
||||
uint16_t _vsync_polarity;
|
||||
uint16_t _vsync_front_porch;
|
||||
uint16_t _vsync_pulse_width;
|
||||
uint16_t _vsync_back_porch;
|
||||
uint16_t _pclk_active_neg;
|
||||
int32_t _prefer_speed;
|
||||
bool _useBigEndian;
|
||||
uint16_t _de_idle_high;
|
||||
uint16_t _pclk_idle_high;
|
||||
|
||||
esp_lcd_panel_handle_t _panel_handle = NULL;
|
||||
};
|
||||
|
||||
#endif // #if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)
|
||||
@@ -0,0 +1,293 @@
|
||||
#include "Arduino_ESP32S2PAR16.h"
|
||||
|
||||
#if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
|
||||
|
||||
Arduino_ESP32S2PAR16::Arduino_ESP32S2PAR16(int8_t dc, int8_t cs, int8_t wr, int8_t rd)
|
||||
: _dc(dc), _cs(cs), _wr(wr), _rd(rd)
|
||||
{
|
||||
}
|
||||
|
||||
bool Arduino_ESP32S2PAR16::begin(int32_t speed, int8_t dataMode)
|
||||
{
|
||||
pinMode(_dc, OUTPUT);
|
||||
digitalWrite(_dc, HIGH); // Data mode
|
||||
if (_dc >= 32)
|
||||
{
|
||||
_dcPinMask = digitalPinToBitMask(_dc);
|
||||
_dcPortSet = (PORTreg_t)GPIO_OUT1_W1TS_REG;
|
||||
_dcPortClr = (PORTreg_t)GPIO_OUT1_W1TC_REG;
|
||||
}
|
||||
else
|
||||
{
|
||||
_dcPinMask = digitalPinToBitMask(_dc);
|
||||
_dcPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_dcPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
}
|
||||
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
pinMode(_cs, OUTPUT);
|
||||
digitalWrite(_cs, HIGH); // disable chip select
|
||||
}
|
||||
if (_cs >= 32)
|
||||
{
|
||||
_csPinMask = digitalPinToBitMask(_cs);
|
||||
_csPortSet = (PORTreg_t)GPIO_OUT1_W1TS_REG;
|
||||
_csPortClr = (PORTreg_t)GPIO_OUT1_W1TC_REG;
|
||||
}
|
||||
else if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
_csPinMask = digitalPinToBitMask(_cs);
|
||||
_csPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_csPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
}
|
||||
|
||||
pinMode(_wr, OUTPUT);
|
||||
digitalWrite(_wr, HIGH); // Set write strobe high (inactive)
|
||||
if (_wr >= 32)
|
||||
{
|
||||
_wrPinMask = digitalPinToBitMask(_wr);
|
||||
_wrPortSet = (PORTreg_t)GPIO_OUT1_W1TS_REG;
|
||||
_wrPortClr = (PORTreg_t)GPIO_OUT1_W1TC_REG;
|
||||
}
|
||||
else
|
||||
{
|
||||
_wrPinMask = digitalPinToBitMask(_wr);
|
||||
_wrPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_wrPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
}
|
||||
|
||||
if (_rd != GFX_NOT_DEFINED)
|
||||
{
|
||||
pinMode(_rd, OUTPUT);
|
||||
digitalWrite(_rd, HIGH);
|
||||
}
|
||||
|
||||
pinMode(0, OUTPUT);
|
||||
pinMode(1, OUTPUT);
|
||||
pinMode(2, OUTPUT);
|
||||
pinMode(3, OUTPUT);
|
||||
pinMode(4, OUTPUT);
|
||||
pinMode(5, OUTPUT);
|
||||
pinMode(6, OUTPUT);
|
||||
pinMode(7, OUTPUT);
|
||||
pinMode(8, OUTPUT);
|
||||
pinMode(9, OUTPUT);
|
||||
pinMode(10, OUTPUT);
|
||||
pinMode(11, OUTPUT);
|
||||
pinMode(12, OUTPUT);
|
||||
pinMode(13, OUTPUT);
|
||||
pinMode(14, OUTPUT);
|
||||
pinMode(15, OUTPUT);
|
||||
|
||||
// INIT 16-bit mask
|
||||
_dataClrMask = 0xFFFF;
|
||||
_dataPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_dataPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
*_dataPortClr = _dataClrMask;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR16::beginWrite()
|
||||
{
|
||||
DC_HIGH();
|
||||
CS_LOW();
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR16::endWrite()
|
||||
{
|
||||
CS_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR16::writeCommand(uint8_t c)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR16::writeCommand16(uint16_t c)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE16(c);
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR16::writeCommandBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
while (len--)
|
||||
{
|
||||
WRITE(*data++);
|
||||
}
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR16::write(uint8_t d)
|
||||
{
|
||||
WRITE(d);
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR16::write16(uint16_t d)
|
||||
{
|
||||
WRITE16(d);
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR16::writeRepeat(uint16_t p, uint32_t len)
|
||||
{
|
||||
*_dataPortClr = _dataClrMask;
|
||||
*_dataPortSet = p;
|
||||
while (len--)
|
||||
{
|
||||
*_wrPortClr = _wrPinMask;
|
||||
*_wrPortSet = _wrPinMask;
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR16::writePixels(uint16_t *data, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
WRITE16(*data++);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR16::writeC8D8(uint8_t c, uint8_t d)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
WRITE(d);
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR16::writeC8D16(uint8_t c, uint16_t d)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
WRITE16(d);
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR16::writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
WRITE16(d1);
|
||||
WRITE16(d2);
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR16::writeC8D16D16Split(uint8_t c, uint16_t d1, uint16_t d2)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
_data16.value = d1;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
|
||||
_data16.value = d2;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR16::writeBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
while (len > 1)
|
||||
{
|
||||
_data16.msb = *data++;
|
||||
_data16.lsb = *data++;
|
||||
WRITE16(_data16.value);
|
||||
len -= 2;
|
||||
}
|
||||
if (len)
|
||||
{
|
||||
WRITE(*data);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR16::writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
WRITE16(idx[*data++]);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR16::writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
*_dataPortClr = _dataClrMask;
|
||||
*_dataPortSet = idx[*data++];
|
||||
*_wrPortClr = _wrPinMask;
|
||||
*_wrPortSet = _wrPinMask;
|
||||
*_wrPortClr = _wrPinMask;
|
||||
*_wrPortSet = _wrPinMask;
|
||||
}
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP32S2PAR16::WRITE(uint8_t d)
|
||||
{
|
||||
*_dataPortClr = _dataClrMask;
|
||||
*_dataPortSet = d;
|
||||
*_wrPortClr = _wrPinMask;
|
||||
*_wrPortSet = _wrPinMask;
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP32S2PAR16::WRITE16(uint16_t d)
|
||||
{
|
||||
*_dataPortClr = _dataClrMask;
|
||||
*_dataPortSet = d;
|
||||
*_wrPortClr = _wrPinMask;
|
||||
*_wrPortSet = _wrPinMask;
|
||||
}
|
||||
|
||||
/******** low level bit twiddling **********/
|
||||
|
||||
GFX_INLINE void Arduino_ESP32S2PAR16::DC_HIGH(void)
|
||||
{
|
||||
*_dcPortSet = _dcPinMask;
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP32S2PAR16::DC_LOW(void)
|
||||
{
|
||||
*_dcPortClr = _dcPinMask;
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP32S2PAR16::CS_HIGH(void)
|
||||
{
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
*_csPortSet = _csPinMask;
|
||||
}
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP32S2PAR16::CS_LOW(void)
|
||||
{
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
*_csPortClr = _csPinMask;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // #if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
|
||||
@@ -0,0 +1,63 @@
|
||||
#include "Arduino_DataBus.h"
|
||||
|
||||
#if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
|
||||
|
||||
#ifndef _ARDUINO_ESP32S2PAR16_H_
|
||||
#define _ARDUINO_ESP32S2PAR16_H_
|
||||
|
||||
class Arduino_ESP32S2PAR16 : public Arduino_DataBus
|
||||
{
|
||||
public:
|
||||
Arduino_ESP32S2PAR16(int8_t dc, int8_t cs, int8_t wr, int8_t rd); // Constructor
|
||||
|
||||
bool begin(int32_t speed = GFX_NOT_DEFINED, int8_t dataMode = GFX_NOT_DEFINED) override;
|
||||
void beginWrite() override;
|
||||
void endWrite() override;
|
||||
void writeCommand(uint8_t) override;
|
||||
void writeCommand16(uint16_t) override;
|
||||
void writeCommandBytes(uint8_t *data, uint32_t len) override;
|
||||
void write(uint8_t) override;
|
||||
void write16(uint16_t) override;
|
||||
void writeRepeat(uint16_t p, uint32_t len) override;
|
||||
void writePixels(uint16_t *data, uint32_t len) override;
|
||||
|
||||
void writeC8D8(uint8_t c, uint8_t d) override;
|
||||
void writeC8D16(uint8_t c, uint16_t d) override;
|
||||
void writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2) override;
|
||||
void writeC8D16D16Split(uint8_t c, uint16_t d1, uint16_t d2) override;
|
||||
void writeBytes(uint8_t *data, uint32_t len) override;
|
||||
|
||||
void writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len) override;
|
||||
void writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len) override;
|
||||
|
||||
protected:
|
||||
private:
|
||||
GFX_INLINE void WRITE(uint8_t d);
|
||||
GFX_INLINE void WRITE16(uint16_t d);
|
||||
GFX_INLINE void DC_HIGH(void);
|
||||
GFX_INLINE void DC_LOW(void);
|
||||
GFX_INLINE void CS_HIGH(void);
|
||||
GFX_INLINE void CS_LOW(void);
|
||||
|
||||
int8_t _dc, _cs, _wr, _rd;
|
||||
|
||||
PORTreg_t _dcPortSet; ///< PORT register SET
|
||||
PORTreg_t _dcPortClr; ///< PORT register CLEAR
|
||||
uint32_t _dcPinMask; ///< Bitmask
|
||||
|
||||
PORTreg_t _csPortSet; ///< PORT register SET
|
||||
PORTreg_t _csPortClr; ///< PORT register CLEAR
|
||||
uint32_t _csPinMask; ///< Bitmask
|
||||
|
||||
PORTreg_t _wrPortSet; ///< PORT register SET
|
||||
PORTreg_t _wrPortClr; ///< PORT register CLEAR
|
||||
uint32_t _wrPinMask; ///< Bitmask
|
||||
|
||||
PORTreg_t _dataPortSet; ///< PORT register SET
|
||||
PORTreg_t _dataPortClr; ///< PORT register CLEAR
|
||||
uint32_t _dataClrMask;
|
||||
};
|
||||
|
||||
#endif // _ARDUINO_ESP32S2PAR16_H_
|
||||
|
||||
#endif // #if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
|
||||
@@ -0,0 +1,290 @@
|
||||
#include "Arduino_ESP32S2PAR16Q.h"
|
||||
|
||||
#if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
|
||||
|
||||
Arduino_ESP32S2PAR16Q::Arduino_ESP32S2PAR16Q(int8_t dc, int8_t cs, int8_t wr, int8_t rd)
|
||||
: _dc(dc), _cs(cs), _wr(wr), _rd(rd)
|
||||
{
|
||||
}
|
||||
|
||||
bool Arduino_ESP32S2PAR16Q::begin(int32_t speed, int8_t dataMode)
|
||||
{
|
||||
pinMode(_dc, OUTPUT);
|
||||
digitalWrite(_dc, HIGH); // Data mode
|
||||
if (_dc >= 32)
|
||||
{
|
||||
_dcPinMask = digitalPinToBitMask(_dc);
|
||||
_dcPortSet = (PORTreg_t)GPIO_OUT1_W1TS_REG;
|
||||
_dcPortClr = (PORTreg_t)GPIO_OUT1_W1TC_REG;
|
||||
}
|
||||
else
|
||||
{
|
||||
_dcPinMask = digitalPinToBitMask(_dc);
|
||||
_dcPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_dcPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
}
|
||||
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
pinMode(_cs, OUTPUT);
|
||||
digitalWrite(_cs, HIGH); // disable chip select
|
||||
}
|
||||
if (_cs >= 32)
|
||||
{
|
||||
_csPinMask = digitalPinToBitMask(_cs);
|
||||
_csPortSet = (PORTreg_t)GPIO_OUT1_W1TS_REG;
|
||||
_csPortClr = (PORTreg_t)GPIO_OUT1_W1TC_REG;
|
||||
}
|
||||
else if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
_csPinMask = digitalPinToBitMask(_cs);
|
||||
_csPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_csPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
}
|
||||
|
||||
pinMode(_wr, OUTPUT);
|
||||
digitalWrite(_wr, HIGH); // Set write strobe high (inactive)
|
||||
if (_wr >= 32)
|
||||
{
|
||||
_wrPinMask = digitalPinToBitMask(_wr);
|
||||
_wrPortSet = (PORTreg_t)GPIO_OUT1_W1TS_REG;
|
||||
_wrPortClr = (PORTreg_t)GPIO_OUT1_W1TC_REG;
|
||||
}
|
||||
else
|
||||
{
|
||||
_wrPinMask = digitalPinToBitMask(_wr);
|
||||
_wrPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_wrPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
}
|
||||
|
||||
if (_rd != GFX_NOT_DEFINED)
|
||||
{
|
||||
pinMode(_rd, OUTPUT);
|
||||
digitalWrite(_rd, HIGH);
|
||||
}
|
||||
|
||||
pinMode(0, OUTPUT);
|
||||
pinMode(1, OUTPUT);
|
||||
pinMode(2, OUTPUT);
|
||||
pinMode(3, OUTPUT);
|
||||
pinMode(4, OUTPUT);
|
||||
pinMode(5, OUTPUT);
|
||||
pinMode(6, OUTPUT);
|
||||
pinMode(7, OUTPUT);
|
||||
pinMode(8, OUTPUT);
|
||||
pinMode(9, OUTPUT);
|
||||
pinMode(10, OUTPUT);
|
||||
pinMode(11, OUTPUT);
|
||||
pinMode(12, OUTPUT);
|
||||
pinMode(13, OUTPUT);
|
||||
pinMode(14, OUTPUT);
|
||||
pinMode(15, OUTPUT);
|
||||
|
||||
// INIT 16-bit mask
|
||||
_dataClrMask = (1 << _wr) | 0xFFFF;
|
||||
_dataPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_dataPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
*_dataPortClr = _dataClrMask;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR16Q::beginWrite()
|
||||
{
|
||||
DC_HIGH();
|
||||
CS_LOW();
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR16Q::endWrite()
|
||||
{
|
||||
CS_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR16Q::writeCommand(uint8_t c)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR16Q::writeCommand16(uint16_t c)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE16(c);
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR16Q::writeCommandBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
while (len--)
|
||||
{
|
||||
WRITE(*data++);
|
||||
}
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR16Q::write(uint8_t d)
|
||||
{
|
||||
WRITE(d);
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR16Q::write16(uint16_t d)
|
||||
{
|
||||
WRITE16(d);
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR16Q::writeRepeat(uint16_t p, uint32_t len)
|
||||
{
|
||||
*_dataPortClr = _dataClrMask;
|
||||
*_dataPortSet = p;
|
||||
while (len--)
|
||||
{
|
||||
*_wrPortClr = _wrPinMask;
|
||||
*_wrPortSet = _wrPinMask;
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR16Q::writePixels(uint16_t *data, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
WRITE16(*data++);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR16Q::writeC8D8(uint8_t c, uint8_t d)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
WRITE(d);
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR16Q::writeC8D16(uint8_t c, uint16_t d)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
WRITE16(d);
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR16Q::writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
WRITE16(d1);
|
||||
WRITE16(d2);
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR16Q::writeC8D16D16Split(uint8_t c, uint16_t d1, uint16_t d2)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
_data16.value = d1;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
|
||||
_data16.value = d2;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR16Q::writeBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
while (len > 1)
|
||||
{
|
||||
_data16.msb = *data++;
|
||||
_data16.lsb = *data++;
|
||||
WRITE16(_data16.value);
|
||||
len -= 2;
|
||||
}
|
||||
if (len)
|
||||
{
|
||||
WRITE(*data);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR16Q::writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
WRITE16(idx[*data++]);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR16Q::writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
*_dataPortClr = _dataClrMask;
|
||||
*_dataPortSet = idx[*data++];
|
||||
*_wrPortSet = _wrPinMask;
|
||||
*_wrPortClr = _wrPinMask;
|
||||
*_wrPortSet = _wrPinMask;
|
||||
}
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP32S2PAR16Q::WRITE(uint8_t d)
|
||||
{
|
||||
*_dataPortClr = _dataClrMask;
|
||||
*_dataPortSet = d;
|
||||
*_wrPortSet = _wrPinMask;
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP32S2PAR16Q::WRITE16(uint16_t d)
|
||||
{
|
||||
*_dataPortClr = _dataClrMask;
|
||||
*_dataPortSet = d;
|
||||
*_wrPortSet = _wrPinMask;
|
||||
}
|
||||
|
||||
/******** low level bit twiddling **********/
|
||||
|
||||
GFX_INLINE void Arduino_ESP32S2PAR16Q::DC_HIGH(void)
|
||||
{
|
||||
*_dcPortSet = _dcPinMask;
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP32S2PAR16Q::DC_LOW(void)
|
||||
{
|
||||
*_dcPortClr = _dcPinMask;
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP32S2PAR16Q::CS_HIGH(void)
|
||||
{
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
*_csPortSet = _csPinMask;
|
||||
}
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP32S2PAR16Q::CS_LOW(void)
|
||||
{
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
*_csPortClr = _csPinMask;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // #if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
|
||||
@@ -0,0 +1,63 @@
|
||||
#include "Arduino_DataBus.h"
|
||||
|
||||
#if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
|
||||
|
||||
#ifndef _ARDUINO_ESP32S2PAR16Q_H_
|
||||
#define _ARDUINO_ESP32S2PAR16Q_H_
|
||||
|
||||
class Arduino_ESP32S2PAR16Q : public Arduino_DataBus
|
||||
{
|
||||
public:
|
||||
Arduino_ESP32S2PAR16Q(int8_t dc, int8_t cs, int8_t wr, int8_t rd); // Constructor
|
||||
|
||||
bool begin(int32_t speed = GFX_NOT_DEFINED, int8_t dataMode = GFX_NOT_DEFINED) override;
|
||||
void beginWrite() override;
|
||||
void endWrite() override;
|
||||
void writeCommand(uint8_t) override;
|
||||
void writeCommand16(uint16_t) override;
|
||||
void writeCommandBytes(uint8_t *data, uint32_t len) override;
|
||||
void write(uint8_t) override;
|
||||
void write16(uint16_t) override;
|
||||
void writeRepeat(uint16_t p, uint32_t len) override;
|
||||
void writePixels(uint16_t *data, uint32_t len) override;
|
||||
|
||||
void writeC8D8(uint8_t c, uint8_t d) override;
|
||||
void writeC8D16(uint8_t c, uint16_t d) override;
|
||||
void writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2) override;
|
||||
void writeC8D16D16Split(uint8_t c, uint16_t d1, uint16_t d2) override;
|
||||
void writeBytes(uint8_t *data, uint32_t len) override;
|
||||
|
||||
void writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len) override;
|
||||
void writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len) override;
|
||||
|
||||
protected:
|
||||
private:
|
||||
GFX_INLINE void WRITE(uint8_t d);
|
||||
GFX_INLINE void WRITE16(uint16_t d);
|
||||
GFX_INLINE void DC_HIGH(void);
|
||||
GFX_INLINE void DC_LOW(void);
|
||||
GFX_INLINE void CS_HIGH(void);
|
||||
GFX_INLINE void CS_LOW(void);
|
||||
|
||||
int8_t _dc, _cs, _wr, _rd;
|
||||
|
||||
PORTreg_t _dcPortSet; ///< PORT register SET
|
||||
PORTreg_t _dcPortClr; ///< PORT register CLEAR
|
||||
uint32_t _dcPinMask; ///< Bitmask
|
||||
|
||||
PORTreg_t _csPortSet; ///< PORT register SET
|
||||
PORTreg_t _csPortClr; ///< PORT register CLEAR
|
||||
uint32_t _csPinMask; ///< Bitmask
|
||||
|
||||
PORTreg_t _wrPortSet; ///< PORT register SET
|
||||
PORTreg_t _wrPortClr; ///< PORT register CLEAR
|
||||
uint32_t _wrPinMask; ///< Bitmask
|
||||
|
||||
PORTreg_t _dataPortSet; ///< PORT register SET
|
||||
PORTreg_t _dataPortClr; ///< PORT register CLEAR
|
||||
uint32_t _dataClrMask;
|
||||
};
|
||||
|
||||
#endif // _ARDUINO_ESP32S2PAR16Q_H_
|
||||
|
||||
#endif // #if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
|
||||
@@ -0,0 +1,288 @@
|
||||
#include "Arduino_ESP32S2PAR8.h"
|
||||
|
||||
#if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
|
||||
|
||||
Arduino_ESP32S2PAR8::Arduino_ESP32S2PAR8(int8_t dc, int8_t cs, int8_t wr, int8_t rd)
|
||||
: _dc(dc), _cs(cs), _wr(wr), _rd(rd)
|
||||
{
|
||||
}
|
||||
|
||||
bool Arduino_ESP32S2PAR8::begin(int32_t speed, int8_t dataMode)
|
||||
{
|
||||
pinMode(_dc, OUTPUT);
|
||||
digitalWrite(_dc, HIGH); // Data mode
|
||||
if (_dc >= 32)
|
||||
{
|
||||
_dcPinMask = digitalPinToBitMask(_dc);
|
||||
_dcPortSet = (PORTreg_t)GPIO_OUT1_W1TS_REG;
|
||||
_dcPortClr = (PORTreg_t)GPIO_OUT1_W1TC_REG;
|
||||
}
|
||||
else if (_dc != GFX_NOT_DEFINED)
|
||||
{
|
||||
_dcPinMask = digitalPinToBitMask(_dc);
|
||||
_dcPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_dcPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
}
|
||||
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
pinMode(_cs, OUTPUT);
|
||||
digitalWrite(_cs, HIGH); // disable chip select
|
||||
}
|
||||
if (_cs >= 32)
|
||||
{
|
||||
_csPinMask = digitalPinToBitMask(_cs);
|
||||
_csPortSet = (PORTreg_t)GPIO_OUT1_W1TS_REG;
|
||||
_csPortClr = (PORTreg_t)GPIO_OUT1_W1TC_REG;
|
||||
}
|
||||
else if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
_csPinMask = digitalPinToBitMask(_cs);
|
||||
_csPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_csPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
}
|
||||
|
||||
pinMode(_wr, OUTPUT);
|
||||
digitalWrite(_wr, HIGH); // Set write strobe high (inactive)
|
||||
if (_wr >= 32)
|
||||
{
|
||||
_wrPinMask = digitalPinToBitMask(_wr);
|
||||
_wrPortSet = (PORTreg_t)GPIO_OUT1_W1TS_REG;
|
||||
_wrPortClr = (PORTreg_t)GPIO_OUT1_W1TC_REG;
|
||||
}
|
||||
else if (_wr != GFX_NOT_DEFINED)
|
||||
{
|
||||
_wrPinMask = digitalPinToBitMask(_wr);
|
||||
_wrPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_wrPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
}
|
||||
|
||||
if (_rd != GFX_NOT_DEFINED)
|
||||
{
|
||||
pinMode(_rd, OUTPUT);
|
||||
digitalWrite(_rd, HIGH);
|
||||
}
|
||||
|
||||
pinMode(0, OUTPUT);
|
||||
pinMode(1, OUTPUT);
|
||||
pinMode(2, OUTPUT);
|
||||
pinMode(3, OUTPUT);
|
||||
pinMode(4, OUTPUT);
|
||||
pinMode(5, OUTPUT);
|
||||
pinMode(6, OUTPUT);
|
||||
pinMode(7, OUTPUT);
|
||||
|
||||
// INIT 8-bit mask
|
||||
_dataClrMask = 0xFF;
|
||||
_dataPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_dataPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
*_dataPortClr = _dataClrMask;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR8::beginWrite()
|
||||
{
|
||||
DC_HIGH();
|
||||
CS_LOW();
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR8::endWrite()
|
||||
{
|
||||
CS_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR8::writeCommand(uint8_t c)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR8::writeCommand16(uint16_t c)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
_data16.value = c;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR8::writeCommandBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
while (len--)
|
||||
{
|
||||
WRITE(*data++);
|
||||
}
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR8::write(uint8_t d)
|
||||
{
|
||||
WRITE(d);
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR8::write16(uint16_t d)
|
||||
{
|
||||
_data16.value = d;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR8::writeRepeat(uint16_t p, uint32_t len)
|
||||
{
|
||||
_data16.value = p;
|
||||
if (_data16.msb == _data16.lsb)
|
||||
{
|
||||
*_dataPortClr = _dataClrMask;
|
||||
*_dataPortSet = p;
|
||||
while (len--)
|
||||
{
|
||||
*_wrPortClr = _wrPinMask;
|
||||
*_wrPortSet = _wrPinMask;
|
||||
*_wrPortClr = _wrPinMask;
|
||||
*_wrPortSet = _wrPinMask;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
*_dataPortClr = _dataClrMask;
|
||||
*_dataPortSet = _data16.msb;
|
||||
*_wrPortClr = _wrPinMask;
|
||||
*_wrPortSet = _wrPinMask;
|
||||
|
||||
*_dataPortClr = _dataClrMask;
|
||||
*_dataPortSet = _data16.lsb;
|
||||
*_wrPortClr = _wrPinMask;
|
||||
*_wrPortSet = _wrPinMask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR8::writePixels(uint16_t *data, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
_data16.value = *data++;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR8::writeC8D8(uint8_t c, uint8_t d)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
WRITE(d);
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR8::writeC8D16(uint8_t c, uint16_t d)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
_data16.value = d;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR8::writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
_data16.value = d1;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
|
||||
_data16.value = d2;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR8::writeBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
WRITE(*data++);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR8::writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
_data16.value = idx[*data++];
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR8::writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
_data16.value = idx[*data++];
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP32S2PAR8::WRITE(uint8_t d)
|
||||
{
|
||||
*_dataPortClr = _dataClrMask;
|
||||
*_dataPortSet = d;
|
||||
*_wrPortClr = _wrPinMask;
|
||||
*_wrPortSet = _wrPinMask;
|
||||
}
|
||||
|
||||
/******** low level bit twiddling **********/
|
||||
|
||||
GFX_INLINE void Arduino_ESP32S2PAR8::DC_HIGH(void)
|
||||
{
|
||||
*_dcPortSet = _dcPinMask;
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP32S2PAR8::DC_LOW(void)
|
||||
{
|
||||
*_dcPortClr = _dcPinMask;
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP32S2PAR8::CS_HIGH(void)
|
||||
{
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
*_csPortSet = _csPinMask;
|
||||
}
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP32S2PAR8::CS_LOW(void)
|
||||
{
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
*_csPortClr = _csPinMask;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // #if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
|
||||
@@ -0,0 +1,61 @@
|
||||
#include "Arduino_DataBus.h"
|
||||
|
||||
#if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
|
||||
|
||||
#ifndef _ARDUINO_ESP32S2PAR8_H_
|
||||
#define _ARDUINO_ESP32S2PAR8_H_
|
||||
|
||||
class Arduino_ESP32S2PAR8 : public Arduino_DataBus
|
||||
{
|
||||
public:
|
||||
Arduino_ESP32S2PAR8(int8_t dc, int8_t cs, int8_t wr, int8_t rd); // Constructor
|
||||
|
||||
bool begin(int32_t speed = GFX_NOT_DEFINED, int8_t dataMode = GFX_NOT_DEFINED) override;
|
||||
void beginWrite() override;
|
||||
void endWrite() override;
|
||||
void writeCommand(uint8_t) override;
|
||||
void writeCommand16(uint16_t) override;
|
||||
void writeCommandBytes(uint8_t *data, uint32_t len) override;
|
||||
void write(uint8_t) override;
|
||||
void write16(uint16_t) override;
|
||||
void writeRepeat(uint16_t p, uint32_t len) override;
|
||||
void writePixels(uint16_t *data, uint32_t len) override;
|
||||
|
||||
void writeC8D8(uint8_t c, uint8_t d) override;
|
||||
void writeC8D16(uint8_t c, uint16_t d) override;
|
||||
void writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2) override;
|
||||
void writeBytes(uint8_t *data, uint32_t len) override;
|
||||
|
||||
void writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len) override;
|
||||
void writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len) override;
|
||||
|
||||
protected:
|
||||
private:
|
||||
GFX_INLINE void WRITE(uint8_t d);
|
||||
GFX_INLINE void DC_HIGH(void);
|
||||
GFX_INLINE void DC_LOW(void);
|
||||
GFX_INLINE void CS_HIGH(void);
|
||||
GFX_INLINE void CS_LOW(void);
|
||||
|
||||
int8_t _dc, _cs, _wr, _rd;
|
||||
|
||||
PORTreg_t _dcPortSet; ///< PORT register SET
|
||||
PORTreg_t _dcPortClr; ///< PORT register CLEAR
|
||||
uint32_t _dcPinMask; ///< Bitmask
|
||||
|
||||
PORTreg_t _csPortSet; ///< PORT register SET
|
||||
PORTreg_t _csPortClr; ///< PORT register CLEAR
|
||||
uint32_t _csPinMask; ///< Bitmask
|
||||
|
||||
PORTreg_t _wrPortSet; ///< PORT register SET
|
||||
PORTreg_t _wrPortClr; ///< PORT register CLEAR
|
||||
uint32_t _wrPinMask; ///< Bitmask
|
||||
|
||||
PORTreg_t _dataPortSet; ///< PORT register SET
|
||||
PORTreg_t _dataPortClr; ///< PORT register CLEAR
|
||||
uint32_t _dataClrMask;
|
||||
};
|
||||
|
||||
#endif // _ARDUINO_ESP32S2PAR8_H_
|
||||
|
||||
#endif // #if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
|
||||
@@ -0,0 +1,288 @@
|
||||
#include "Arduino_ESP32S2PAR8Q.h"
|
||||
|
||||
#if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
|
||||
|
||||
Arduino_ESP32S2PAR8Q::Arduino_ESP32S2PAR8Q(int8_t dc, int8_t cs, int8_t wr, int8_t rd)
|
||||
: _dc(dc), _cs(cs), _wr(wr), _rd(rd)
|
||||
{
|
||||
}
|
||||
|
||||
bool Arduino_ESP32S2PAR8Q::begin(int32_t speed, int8_t dataMode)
|
||||
{
|
||||
pinMode(_dc, OUTPUT);
|
||||
digitalWrite(_dc, HIGH); // Data mode
|
||||
if (_dc >= 32)
|
||||
{
|
||||
_dcPinMask = digitalPinToBitMask(_dc);
|
||||
_dcPortSet = (PORTreg_t)GPIO_OUT1_W1TS_REG;
|
||||
_dcPortClr = (PORTreg_t)GPIO_OUT1_W1TC_REG;
|
||||
}
|
||||
else if (_dc != GFX_NOT_DEFINED)
|
||||
{
|
||||
_dcPinMask = digitalPinToBitMask(_dc);
|
||||
_dcPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_dcPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
}
|
||||
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
pinMode(_cs, OUTPUT);
|
||||
digitalWrite(_cs, HIGH); // disable chip select
|
||||
}
|
||||
if (_cs >= 32)
|
||||
{
|
||||
_csPinMask = digitalPinToBitMask(_cs);
|
||||
_csPortSet = (PORTreg_t)GPIO_OUT1_W1TS_REG;
|
||||
_csPortClr = (PORTreg_t)GPIO_OUT1_W1TC_REG;
|
||||
}
|
||||
else if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
_csPinMask = digitalPinToBitMask(_cs);
|
||||
_csPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_csPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
}
|
||||
|
||||
pinMode(_wr, OUTPUT);
|
||||
digitalWrite(_wr, HIGH); // Set write strobe high (inactive)
|
||||
if (_wr >= 32)
|
||||
{
|
||||
_wrPinMask = digitalPinToBitMask(_wr);
|
||||
_wrPortSet = (PORTreg_t)GPIO_OUT1_W1TS_REG;
|
||||
_wrPortClr = (PORTreg_t)GPIO_OUT1_W1TC_REG;
|
||||
}
|
||||
else
|
||||
{
|
||||
_wrPinMask = digitalPinToBitMask(_wr);
|
||||
_wrPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_wrPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
}
|
||||
|
||||
if (_rd != GFX_NOT_DEFINED)
|
||||
{
|
||||
pinMode(_rd, OUTPUT);
|
||||
digitalWrite(_rd, HIGH);
|
||||
}
|
||||
|
||||
pinMode(0, OUTPUT);
|
||||
pinMode(1, OUTPUT);
|
||||
pinMode(2, OUTPUT);
|
||||
pinMode(3, OUTPUT);
|
||||
pinMode(4, OUTPUT);
|
||||
pinMode(5, OUTPUT);
|
||||
pinMode(6, OUTPUT);
|
||||
pinMode(7, OUTPUT);
|
||||
|
||||
// INIT 8-bit mask
|
||||
_dataClrMask = (1 << _wr) | 0xFF;
|
||||
_dataPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_dataPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
*_dataPortClr = _dataClrMask;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR8Q::beginWrite()
|
||||
{
|
||||
DC_HIGH();
|
||||
CS_LOW();
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR8Q::endWrite()
|
||||
{
|
||||
CS_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR8Q::writeCommand(uint8_t c)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR8Q::writeCommand16(uint16_t c)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
_data16.value = c;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR8Q::writeCommandBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
while (len--)
|
||||
{
|
||||
WRITE(*data++);
|
||||
}
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR8Q::write(uint8_t d)
|
||||
{
|
||||
WRITE(d);
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR8Q::write16(uint16_t d)
|
||||
{
|
||||
_data16.value = d;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR8Q::writeRepeat(uint16_t p, uint32_t len)
|
||||
{
|
||||
_data16.value = p;
|
||||
if (_data16.msb == _data16.lsb)
|
||||
{
|
||||
*_dataPortClr = _dataClrMask;
|
||||
*_dataPortSet = _data16.msb;
|
||||
*_wrPortSet = _wrPinMask;
|
||||
*_wrPortClr = _wrPinMask;
|
||||
*_wrPortSet = _wrPinMask;
|
||||
while (--len)
|
||||
{
|
||||
*_wrPortClr = _wrPinMask;
|
||||
*_wrPortSet = _wrPinMask;
|
||||
*_wrPortClr = _wrPinMask;
|
||||
*_wrPortSet = _wrPinMask;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
*_dataPortClr = _dataClrMask;
|
||||
*_dataPortSet = _data16.msb;
|
||||
*_wrPortSet = _wrPinMask;
|
||||
|
||||
*_dataPortClr = _dataClrMask;
|
||||
*_dataPortSet = _data16.lsb;
|
||||
*_wrPortSet = _wrPinMask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR8Q::writePixels(uint16_t *data, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
_data16.value = *data++;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR8Q::writeC8D8(uint8_t c, uint8_t d)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
WRITE(d);
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR8Q::writeC8D16(uint8_t c, uint16_t d)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
_data16.value = d;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR8Q::writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
_data16.value = d1;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
|
||||
_data16.value = d2;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR8Q::writeBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
WRITE(*data++);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR8Q::writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
_data16.value = idx[*data++];
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_ESP32S2PAR8Q::writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
_data16.value = idx[*data++];
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP32S2PAR8Q::WRITE(uint8_t d)
|
||||
{
|
||||
*_dataPortClr = _dataClrMask;
|
||||
*_dataPortSet = d;
|
||||
*_wrPortSet = _wrPinMask;
|
||||
}
|
||||
|
||||
/******** low level bit twiddling **********/
|
||||
|
||||
GFX_INLINE void Arduino_ESP32S2PAR8Q::DC_HIGH(void)
|
||||
{
|
||||
*_dcPortSet = _dcPinMask;
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP32S2PAR8Q::DC_LOW(void)
|
||||
{
|
||||
*_dcPortClr = _dcPinMask;
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP32S2PAR8Q::CS_HIGH(void)
|
||||
{
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
*_csPortSet = _csPinMask;
|
||||
}
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP32S2PAR8Q::CS_LOW(void)
|
||||
{
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
*_csPortClr = _csPinMask;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // #if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
|
||||
@@ -0,0 +1,61 @@
|
||||
#include "Arduino_DataBus.h"
|
||||
|
||||
#if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
|
||||
|
||||
#ifndef _ARDUINO_ESP32S2PAR8Q_H_
|
||||
#define _ARDUINO_ESP32S2PAR8Q_H_
|
||||
|
||||
class Arduino_ESP32S2PAR8Q : public Arduino_DataBus
|
||||
{
|
||||
public:
|
||||
Arduino_ESP32S2PAR8Q(int8_t dc, int8_t cs, int8_t wr, int8_t rd); // Constructor
|
||||
|
||||
bool begin(int32_t speed = GFX_NOT_DEFINED, int8_t dataMode = GFX_NOT_DEFINED) override;
|
||||
void beginWrite() override;
|
||||
void endWrite() override;
|
||||
void writeCommand(uint8_t) override;
|
||||
void writeCommand16(uint16_t) override;
|
||||
void writeCommandBytes(uint8_t *data, uint32_t len) override;
|
||||
void write(uint8_t) override;
|
||||
void write16(uint16_t) override;
|
||||
void writeRepeat(uint16_t p, uint32_t len) override;
|
||||
void writePixels(uint16_t *data, uint32_t len) override;
|
||||
|
||||
void writeC8D8(uint8_t c, uint8_t d) override;
|
||||
void writeC8D16(uint8_t c, uint16_t d) override;
|
||||
void writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2) override;
|
||||
void writeBytes(uint8_t *data, uint32_t len) override;
|
||||
|
||||
void writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len) override;
|
||||
void writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len) override;
|
||||
|
||||
protected:
|
||||
private:
|
||||
GFX_INLINE void WRITE(uint8_t d);
|
||||
GFX_INLINE void DC_HIGH(void);
|
||||
GFX_INLINE void DC_LOW(void);
|
||||
GFX_INLINE void CS_HIGH(void);
|
||||
GFX_INLINE void CS_LOW(void);
|
||||
|
||||
int8_t _dc, _cs, _wr, _rd;
|
||||
|
||||
PORTreg_t _dcPortSet; ///< PORT register SET
|
||||
PORTreg_t _dcPortClr; ///< PORT register CLEAR
|
||||
uint32_t _dcPinMask; ///< Bitmask
|
||||
|
||||
PORTreg_t _csPortSet; ///< PORT register SET
|
||||
PORTreg_t _csPortClr; ///< PORT register CLEAR
|
||||
uint32_t _csPinMask; ///< Bitmask
|
||||
|
||||
PORTreg_t _wrPortSet; ///< PORT register SET
|
||||
PORTreg_t _wrPortClr; ///< PORT register CLEAR
|
||||
uint32_t _wrPinMask; ///< Bitmask
|
||||
|
||||
PORTreg_t _dataPortSet; ///< PORT register SET
|
||||
PORTreg_t _dataPortClr; ///< PORT register CLEAR
|
||||
uint32_t _dataClrMask;
|
||||
};
|
||||
|
||||
#endif // _ARDUINO_ESP32S2PAR8Q_H_
|
||||
|
||||
#endif // #if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,122 @@
|
||||
#pragma once
|
||||
|
||||
#include "Arduino_DataBus.h"
|
||||
|
||||
#if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3)
|
||||
|
||||
#include "esp32-hal.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "esp_attr.h"
|
||||
#include "soc/spi_reg.h"
|
||||
#include "soc/spi_struct.h"
|
||||
#include "soc/io_mux_reg.h"
|
||||
#include "soc/gpio_sig_map.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "hal/clk_gate_ll.h"
|
||||
|
||||
#include "esp_system.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
|
||||
#include "soc/dport_reg.h"
|
||||
#include "esp32/rom/ets_sys.h"
|
||||
#include "esp32/rom/gpio.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#include "soc/dport_reg.h"
|
||||
#include "esp32s2/rom/ets_sys.h"
|
||||
#include "esp32s2/rom/gpio.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
#include "soc/dport_reg.h"
|
||||
#include "esp32s3/rom/ets_sys.h"
|
||||
#include "esp32s3/rom/gpio.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32C2
|
||||
#include "esp32c2/rom/ets_sys.h"
|
||||
#include "esp32c2/rom/gpio.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||
#include "esp32c3/rom/ets_sys.h"
|
||||
#include "esp32c3/rom/gpio.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32C6
|
||||
#include "esp32c6/rom/ets_sys.h"
|
||||
#include "esp32c6/rom/gpio.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||
#include "esp32h2/rom/ets_sys.h"
|
||||
#include "esp32h2/rom/gpio.h"
|
||||
#else
|
||||
#error Target CONFIG_IDF_TARGET is not supported
|
||||
#endif
|
||||
|
||||
#ifndef ESP32SPI_MAX_PIXELS_AT_ONCE
|
||||
#define ESP32SPI_MAX_PIXELS_AT_ONCE 32
|
||||
#endif
|
||||
|
||||
class Arduino_ESP32SPI : public Arduino_DataBus
|
||||
{
|
||||
public:
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
Arduino_ESP32SPI(int8_t dc = GFX_NOT_DEFINED, int8_t cs = GFX_NOT_DEFINED, int8_t sck = GFX_NOT_DEFINED, int8_t mosi = GFX_NOT_DEFINED, int8_t miso = GFX_NOT_DEFINED, uint8_t spi_num = VSPI, bool is_shared_interface = true); // Constructor
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||
Arduino_ESP32SPI(int8_t dc = GFX_NOT_DEFINED, int8_t cs = GFX_NOT_DEFINED, int8_t sck = GFX_NOT_DEFINED, int8_t mosi = GFX_NOT_DEFINED, int8_t miso = GFX_NOT_DEFINED, uint8_t spi_num = FSPI, bool is_shared_interface = true); // Constructor
|
||||
#else
|
||||
Arduino_ESP32SPI(int8_t dc = GFX_NOT_DEFINED, int8_t cs = GFX_NOT_DEFINED, int8_t sck = GFX_NOT_DEFINED, int8_t mosi = GFX_NOT_DEFINED, int8_t miso = GFX_NOT_DEFINED, uint8_t spi_num = FSPI, bool is_shared_interface = true); // Constructor
|
||||
#endif
|
||||
|
||||
bool begin(int32_t speed = GFX_NOT_DEFINED, int8_t dataMode = SPI_MODE0) override;
|
||||
void beginWrite() override;
|
||||
void endWrite() override;
|
||||
void writeCommand(uint8_t) override;
|
||||
void writeCommand16(uint16_t) override;
|
||||
void writeCommandBytes(uint8_t *data, uint32_t len) override;
|
||||
void write(uint8_t) override;
|
||||
void write16(uint16_t) override;
|
||||
|
||||
void writeC8D8(uint8_t c, uint8_t d) override;
|
||||
void writeC8D16(uint8_t c, uint16_t d) override;
|
||||
void writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2) override;
|
||||
|
||||
void writeRepeat(uint16_t p, uint32_t len) override;
|
||||
void writePixels(uint16_t *data, uint32_t len) override;
|
||||
|
||||
void writeBytes(uint8_t *data, uint32_t len) override;
|
||||
|
||||
void writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len) override;
|
||||
void writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len) override;
|
||||
|
||||
protected:
|
||||
void flush_data_buf();
|
||||
GFX_INLINE void WRITE8BIT(uint8_t d);
|
||||
GFX_INLINE void WRITE9BIT(uint32_t d);
|
||||
GFX_INLINE void DC_HIGH(void);
|
||||
GFX_INLINE void DC_LOW(void);
|
||||
GFX_INLINE void CS_HIGH(void);
|
||||
GFX_INLINE void CS_LOW(void);
|
||||
GFX_INLINE void POLL(uint32_t len);
|
||||
|
||||
private:
|
||||
int8_t _dc, _cs;
|
||||
int8_t _sck, _mosi, _miso;
|
||||
uint8_t _spi_num;
|
||||
bool _is_shared_interface;
|
||||
uint32_t _div = 0;
|
||||
|
||||
PORTreg_t _dcPortSet; ///< PORT register for data/command SET
|
||||
PORTreg_t _dcPortClr; ///< PORT register for data/command CLEAR
|
||||
PORTreg_t _csPortSet; ///< PORT register for chip select SET
|
||||
PORTreg_t _csPortClr; ///< PORT register for chip select CLEAR
|
||||
uint32_t _dcPinMask; ///< Bitmask for data/command
|
||||
uint32_t _csPinMask; ///< Bitmask for chip select
|
||||
|
||||
spi_t *_spi;
|
||||
uint8_t _bitOrder = SPI_MSBFIRST;
|
||||
|
||||
union
|
||||
{
|
||||
uint8_t *_buffer;
|
||||
uint16_t *_buffer16;
|
||||
uint32_t *_buffer32;
|
||||
};
|
||||
|
||||
uint16_t _data_buf_bit_idx = 0;
|
||||
};
|
||||
|
||||
#endif // #if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,97 @@
|
||||
#pragma once
|
||||
|
||||
#include "Arduino_DataBus.h"
|
||||
|
||||
#if defined(ESP32)
|
||||
#include <driver/spi_master.h>
|
||||
#if (ESP_ARDUINO_VERSION_MAJOR >= 3)
|
||||
#include <esp_memory_utils.h>
|
||||
#endif
|
||||
|
||||
#ifndef ESP32SPIDMA_MAX_PIXELS_AT_ONCE
|
||||
#define ESP32SPIDMA_MAX_PIXELS_AT_ONCE 1024
|
||||
#endif
|
||||
#ifndef ESP32SPIDMA_DMA_CHANNEL
|
||||
#define ESP32SPIDMA_DMA_CHANNEL SPI_DMA_CH_AUTO
|
||||
#endif
|
||||
|
||||
class Arduino_ESP32SPIDMA : public Arduino_DataBus
|
||||
{
|
||||
public:
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
Arduino_ESP32SPIDMA(int8_t dc = GFX_NOT_DEFINED, int8_t cs = GFX_NOT_DEFINED, int8_t sck = GFX_NOT_DEFINED, int8_t mosi = GFX_NOT_DEFINED, int8_t miso = GFX_NOT_DEFINED, uint8_t spi_num = VSPI, bool is_shared_interface = false); // Constructor
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||
Arduino_ESP32SPIDMA(int8_t dc = GFX_NOT_DEFINED, int8_t cs = GFX_NOT_DEFINED, int8_t sck = GFX_NOT_DEFINED, int8_t mosi = GFX_NOT_DEFINED, int8_t miso = GFX_NOT_DEFINED, uint8_t spi_num = HSPI, bool is_shared_interface = false); // Constructor
|
||||
#else
|
||||
Arduino_ESP32SPIDMA(int8_t dc = GFX_NOT_DEFINED, int8_t cs = GFX_NOT_DEFINED, int8_t sck = GFX_NOT_DEFINED, int8_t mosi = GFX_NOT_DEFINED, int8_t miso = GFX_NOT_DEFINED, uint8_t spi_num = FSPI, bool is_shared_interface = false); // Constructor
|
||||
#endif
|
||||
|
||||
bool begin(int32_t speed = GFX_NOT_DEFINED, int8_t dataMode = SPI_MODE0) override;
|
||||
void beginWrite() override;
|
||||
void endWrite() override;
|
||||
void writeCommand(uint8_t) override;
|
||||
void writeCommand16(uint16_t) override;
|
||||
void writeCommandBytes(uint8_t *data, uint32_t len) override;
|
||||
void write(uint8_t) override;
|
||||
void write16(uint16_t) override;
|
||||
|
||||
void writeC8D8(uint8_t c, uint8_t d) override;
|
||||
void writeC8D16(uint8_t c, uint16_t d) override;
|
||||
void writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2) override;
|
||||
|
||||
void writeRepeat(uint16_t p, uint32_t len) override;
|
||||
void writePixels(uint16_t *data, uint32_t len) override;
|
||||
|
||||
void writeBytes(uint8_t *data, uint32_t len) override;
|
||||
|
||||
void writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len) override;
|
||||
void writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len) override;
|
||||
void writeYCbCrPixels(uint8_t *yData, uint8_t *cbData, uint8_t *crData, uint16_t w, uint16_t h) override;
|
||||
|
||||
protected:
|
||||
void flush_data_buf();
|
||||
GFX_INLINE void WRITE8BIT(uint8_t d);
|
||||
GFX_INLINE void WRITE9BIT(uint32_t d);
|
||||
GFX_INLINE void DC_HIGH(void);
|
||||
GFX_INLINE void DC_LOW(void);
|
||||
GFX_INLINE void CS_HIGH(void);
|
||||
GFX_INLINE void CS_LOW(void);
|
||||
GFX_INLINE void POLL_START();
|
||||
GFX_INLINE void POLL_END();
|
||||
|
||||
private:
|
||||
int8_t _dc, _cs;
|
||||
int8_t _sck, _mosi, _miso;
|
||||
uint8_t _spi_num;
|
||||
bool _is_shared_interface;
|
||||
uint32_t _div = 0;
|
||||
|
||||
PORTreg_t _dcPortSet; ///< PORT register for data/command SET
|
||||
PORTreg_t _dcPortClr; ///< PORT register for data/command CLEAR
|
||||
PORTreg_t _csPortSet; ///< PORT register for chip select SET
|
||||
PORTreg_t _csPortClr; ///< PORT register for chip select CLEAR
|
||||
uint32_t _dcPinMask; ///< Bitmask for data/command
|
||||
uint32_t _csPinMask; ///< Bitmask for chip select
|
||||
|
||||
spi_device_handle_t _handle;
|
||||
spi_transaction_t _spi_tran;
|
||||
uint8_t _bitOrder = SPI_MSBFIRST;
|
||||
|
||||
union
|
||||
{
|
||||
uint8_t *_buffer;
|
||||
uint16_t *_buffer16;
|
||||
uint32_t *_buffer32;
|
||||
};
|
||||
|
||||
union
|
||||
{
|
||||
uint8_t *_2nd_buffer;
|
||||
uint16_t *_2nd_buffer16;
|
||||
uint32_t *_2nd_buffer32;
|
||||
};
|
||||
|
||||
uint16_t _data_buf_bit_idx = 0;
|
||||
};
|
||||
|
||||
#endif // #if defined(ESP32)
|
||||
@@ -0,0 +1,391 @@
|
||||
/*
|
||||
* start rewrite from:
|
||||
* https://github.com/Bodmer/TFT_eSPI.git
|
||||
*/
|
||||
#ifdef ESP8266
|
||||
|
||||
#include <SPI.h>
|
||||
#include "Arduino_ESP8266SPI.h"
|
||||
|
||||
#define WAIT_SPI_NOT_BUSY while (SPI1CMD & SPIBUSY)
|
||||
|
||||
Arduino_ESP8266SPI::Arduino_ESP8266SPI(int8_t dc, int8_t cs /* = GFX_NOT_DEFINED */)
|
||||
: _dc(dc), _cs(cs)
|
||||
{
|
||||
}
|
||||
|
||||
bool Arduino_ESP8266SPI::begin(int32_t speed, int8_t dataMode)
|
||||
{
|
||||
_speed = (speed == GFX_NOT_DEFINED) ? SPI_DEFAULT_FREQ : speed;
|
||||
_dataMode = (dataMode == GFX_NOT_DEFINED) ? SPI_MODE0 : dataMode;
|
||||
|
||||
pinMode(_dc, OUTPUT);
|
||||
digitalWrite(_dc, HIGH); // Data mode
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
pinMode(_cs, OUTPUT);
|
||||
digitalWrite(_cs, HIGH); // Deselect
|
||||
}
|
||||
|
||||
_dcPort = (PORTreg_t)portOutputRegister(digitalPinToPort(_dc));
|
||||
_dcPinMaskSet = digitalPinToBitMask(_dc);
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
_csPort = (PORTreg_t)portOutputRegister(digitalPinToPort(_cs));
|
||||
_csPinMaskSet = digitalPinToBitMask(_cs);
|
||||
}
|
||||
_csPinMaskClr = ~_csPinMaskSet;
|
||||
_dcPinMaskClr = ~_dcPinMaskSet;
|
||||
|
||||
SPI.begin();
|
||||
if (_dataMode == GFX_NOT_DEFINED)
|
||||
{
|
||||
_dataMode = SPI_MODE0;
|
||||
}
|
||||
SPI.setBitOrder(MSBFIRST);
|
||||
SPI.setDataMode(_dataMode);
|
||||
SPI.setFrequency(_speed);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Arduino_ESP8266SPI::beginWrite()
|
||||
{
|
||||
DC_HIGH();
|
||||
|
||||
CS_LOW();
|
||||
}
|
||||
|
||||
void Arduino_ESP8266SPI::endWrite()
|
||||
{
|
||||
CS_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_ESP8266SPI::writeCommand(uint8_t c)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_ESP8266SPI::writeCommand16(uint16_t c)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE16(c);
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_ESP8266SPI::writeCommandBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
while (len--)
|
||||
{
|
||||
WRITE(*data++);
|
||||
}
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_ESP8266SPI::write(uint8_t d)
|
||||
{
|
||||
WRITE(d);
|
||||
}
|
||||
|
||||
void Arduino_ESP8266SPI::write16(uint16_t d)
|
||||
{
|
||||
WRITE16(d);
|
||||
}
|
||||
|
||||
void Arduino_ESP8266SPI::writeRepeat(uint16_t p, uint32_t len)
|
||||
{
|
||||
_data16.value = p;
|
||||
static uint8_t temp[2];
|
||||
temp[0] = _data16.msb;
|
||||
temp[1] = _data16.lsb;
|
||||
SPI.writePattern((uint8_t *)temp, 2, len);
|
||||
}
|
||||
|
||||
void Arduino_ESP8266SPI::writePixels(uint16_t *data, uint32_t len)
|
||||
{
|
||||
uint8_t *data8 = (uint8_t *)data;
|
||||
uint8_t i;
|
||||
|
||||
if (len > 31)
|
||||
{
|
||||
SPI1U1 = (511 << SPILMOSI);
|
||||
|
||||
while (len > 31)
|
||||
{
|
||||
i = 0;
|
||||
while (i < 16)
|
||||
{
|
||||
MSB_32_8_ARRAY_SET(twoPixelBuf[i++], data8);
|
||||
data8 += 4;
|
||||
}
|
||||
|
||||
len -= 32;
|
||||
|
||||
// ESP8266 wait time here at 40MHz SPI is ~5.45us
|
||||
WAIT_SPI_NOT_BUSY;
|
||||
SPI1W0 = twoPixelBuf[0];
|
||||
SPI1W1 = twoPixelBuf[1];
|
||||
SPI1W2 = twoPixelBuf[2];
|
||||
SPI1W3 = twoPixelBuf[3];
|
||||
SPI1W4 = twoPixelBuf[4];
|
||||
SPI1W5 = twoPixelBuf[5];
|
||||
SPI1W6 = twoPixelBuf[6];
|
||||
SPI1W7 = twoPixelBuf[7];
|
||||
SPI1W8 = twoPixelBuf[8];
|
||||
SPI1W9 = twoPixelBuf[9];
|
||||
SPI1W10 = twoPixelBuf[10];
|
||||
SPI1W11 = twoPixelBuf[11];
|
||||
SPI1W12 = twoPixelBuf[12];
|
||||
SPI1W13 = twoPixelBuf[13];
|
||||
SPI1W14 = twoPixelBuf[14];
|
||||
SPI1W15 = twoPixelBuf[15];
|
||||
SPI1CMD |= SPIBUSY;
|
||||
}
|
||||
}
|
||||
|
||||
if (len)
|
||||
{
|
||||
uint32_t bits = ((len << 4) - 1); // bits left to shift - 1
|
||||
i = 0;
|
||||
len = (len + 1) >> 1;
|
||||
|
||||
WAIT_SPI_NOT_BUSY;
|
||||
SPI1U1 = (bits << SPILMOSI);
|
||||
while (len--)
|
||||
{
|
||||
MSB_32_8_ARRAY_SET(spi1Reg32[i++], data8);
|
||||
data8 += 4;
|
||||
}
|
||||
SPI1CMD |= SPIBUSY;
|
||||
}
|
||||
|
||||
WAIT_SPI_NOT_BUSY;
|
||||
}
|
||||
|
||||
void Arduino_ESP8266SPI::writeC8D8(uint8_t c, uint8_t d)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
WRITE(d);
|
||||
}
|
||||
|
||||
void Arduino_ESP8266SPI::writeC8D16(uint8_t c, uint16_t d)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
WRITE16(d);
|
||||
}
|
||||
|
||||
void Arduino_ESP8266SPI::writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
uint32_t d;
|
||||
MSB_32_16_16_SET(d, d1, d2);
|
||||
|
||||
SPI1U1 = (31 << SPILMOSI);
|
||||
SPI1W0 = d;
|
||||
SPI1CMD |= SPIBUSY;
|
||||
WAIT_SPI_NOT_BUSY;
|
||||
}
|
||||
|
||||
void Arduino_ESP8266SPI::writeBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
SPI.writeBytes(data, len);
|
||||
}
|
||||
|
||||
void Arduino_ESP8266SPI::writePattern(uint8_t *data, uint8_t len, uint32_t repeat)
|
||||
{
|
||||
SPI.writePattern(data, len, repeat);
|
||||
}
|
||||
|
||||
void Arduino_ESP8266SPI::writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len)
|
||||
{
|
||||
uint16_t p1, p2;
|
||||
uint8_t i;
|
||||
|
||||
if (len > 31)
|
||||
{
|
||||
SPI1U1 = (511 << SPILMOSI);
|
||||
|
||||
while (len > 31)
|
||||
{
|
||||
i = 0;
|
||||
while (i < 16)
|
||||
{
|
||||
p1 = idx[*data++];
|
||||
p2 = idx[*data++];
|
||||
MSB_32_16_16_SET(twoPixelBuf[i++], p1, p2);
|
||||
}
|
||||
|
||||
len -= 32;
|
||||
|
||||
// ESP8266 wait time here at 40MHz SPI is ~5.45us
|
||||
WAIT_SPI_NOT_BUSY;
|
||||
SPI1W0 = twoPixelBuf[0];
|
||||
SPI1W1 = twoPixelBuf[1];
|
||||
SPI1W2 = twoPixelBuf[2];
|
||||
SPI1W3 = twoPixelBuf[3];
|
||||
SPI1W4 = twoPixelBuf[4];
|
||||
SPI1W5 = twoPixelBuf[5];
|
||||
SPI1W6 = twoPixelBuf[6];
|
||||
SPI1W7 = twoPixelBuf[7];
|
||||
SPI1W8 = twoPixelBuf[8];
|
||||
SPI1W9 = twoPixelBuf[9];
|
||||
SPI1W10 = twoPixelBuf[10];
|
||||
SPI1W11 = twoPixelBuf[11];
|
||||
SPI1W12 = twoPixelBuf[12];
|
||||
SPI1W13 = twoPixelBuf[13];
|
||||
SPI1W14 = twoPixelBuf[14];
|
||||
SPI1W15 = twoPixelBuf[15];
|
||||
SPI1CMD |= SPIBUSY;
|
||||
}
|
||||
}
|
||||
|
||||
if (len)
|
||||
{
|
||||
uint32_t bits = ((len << 4) - 1); // bits left to shift - 1
|
||||
i = 0;
|
||||
len = (len + 1) >> 1;
|
||||
|
||||
WAIT_SPI_NOT_BUSY;
|
||||
SPI1U1 = (bits << SPILMOSI);
|
||||
while (len--)
|
||||
{
|
||||
p1 = idx[*data++];
|
||||
p2 = idx[*data++];
|
||||
MSB_32_16_16_SET(spi1Reg32[i++], p1, p2);
|
||||
}
|
||||
SPI1CMD |= SPIBUSY;
|
||||
}
|
||||
|
||||
WAIT_SPI_NOT_BUSY;
|
||||
}
|
||||
|
||||
void Arduino_ESP8266SPI::writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len)
|
||||
{
|
||||
uint16_t p;
|
||||
uint8_t i;
|
||||
|
||||
if (len > 15)
|
||||
{
|
||||
SPI1U1 = (511 << SPILMOSI);
|
||||
while (len > 15)
|
||||
{
|
||||
i = 0;
|
||||
while (i < 16)
|
||||
{
|
||||
p = idx[*data++];
|
||||
MSB_32_16_16_SET(twoPixelBuf[i++], p, p);
|
||||
}
|
||||
|
||||
len -= 16;
|
||||
|
||||
// ESP8266 wait time here at 40MHz SPI is ~5.45us
|
||||
WAIT_SPI_NOT_BUSY;
|
||||
SPI1W0 = twoPixelBuf[0];
|
||||
SPI1W1 = twoPixelBuf[1];
|
||||
SPI1W2 = twoPixelBuf[2];
|
||||
SPI1W3 = twoPixelBuf[3];
|
||||
SPI1W4 = twoPixelBuf[4];
|
||||
SPI1W5 = twoPixelBuf[5];
|
||||
SPI1W6 = twoPixelBuf[6];
|
||||
SPI1W7 = twoPixelBuf[7];
|
||||
SPI1W8 = twoPixelBuf[8];
|
||||
SPI1W9 = twoPixelBuf[9];
|
||||
SPI1W10 = twoPixelBuf[10];
|
||||
SPI1W11 = twoPixelBuf[11];
|
||||
SPI1W12 = twoPixelBuf[12];
|
||||
SPI1W13 = twoPixelBuf[13];
|
||||
SPI1W14 = twoPixelBuf[14];
|
||||
SPI1W15 = twoPixelBuf[15];
|
||||
SPI1CMD |= SPIBUSY;
|
||||
}
|
||||
}
|
||||
|
||||
if (len)
|
||||
{
|
||||
uint32_t bits = ((len << 5) - 1); // bits left to shift - 1
|
||||
i = 0;
|
||||
|
||||
WAIT_SPI_NOT_BUSY;
|
||||
SPI1U1 = (bits << SPILMOSI);
|
||||
while (len--)
|
||||
{
|
||||
p = idx[*data++];
|
||||
MSB_32_16_16_SET(spi1Reg32[i++], p, p);
|
||||
}
|
||||
SPI1CMD |= SPIBUSY;
|
||||
}
|
||||
|
||||
WAIT_SPI_NOT_BUSY;
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP8266SPI::WRITE(uint8_t d)
|
||||
{
|
||||
SPI1U1 = (7 << SPILMOSI);
|
||||
SPI1W0 = d;
|
||||
SPI1CMD |= SPIBUSY;
|
||||
WAIT_SPI_NOT_BUSY;
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP8266SPI::WRITE16(uint16_t d)
|
||||
{
|
||||
MSB_16_SET(d, d);
|
||||
|
||||
SPI1U1 = (15 << SPILMOSI);
|
||||
SPI1W0 = d;
|
||||
SPI1CMD |= SPIBUSY;
|
||||
WAIT_SPI_NOT_BUSY;
|
||||
}
|
||||
|
||||
/******** low level bit twiddling **********/
|
||||
|
||||
GFX_INLINE void Arduino_ESP8266SPI::DC_HIGH(void)
|
||||
{
|
||||
*_dcPort |= _dcPinMaskSet;
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP8266SPI::DC_LOW(void)
|
||||
{
|
||||
*_dcPort &= _dcPinMaskClr;
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP8266SPI::CS_HIGH(void)
|
||||
{
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
*_csPort |= _csPinMaskSet;
|
||||
}
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_ESP8266SPI::CS_LOW(void)
|
||||
{
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
*_csPort &= _csPinMaskClr;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // #ifdef ESP8266
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* start rewrite from:
|
||||
* https://github.com/Bodmer/TFT_eSPI.git
|
||||
*/
|
||||
#ifdef ESP8266
|
||||
|
||||
#ifndef _ARDUINO_ESP8266SPI_H_
|
||||
#define _ARDUINO_ESP8266SPI_H_
|
||||
|
||||
#include "Arduino_DataBus.h"
|
||||
|
||||
class Arduino_ESP8266SPI : public Arduino_DataBus
|
||||
{
|
||||
public:
|
||||
Arduino_ESP8266SPI(int8_t dc, int8_t cs = GFX_NOT_DEFINED); // Constructor
|
||||
|
||||
bool begin(int32_t speed = GFX_NOT_DEFINED, int8_t dataMode = GFX_NOT_DEFINED) override;
|
||||
void beginWrite() override;
|
||||
void endWrite() override;
|
||||
void writeCommand(uint8_t) override;
|
||||
void writeCommand16(uint16_t) override;
|
||||
void writeCommandBytes(uint8_t *data, uint32_t len) override;
|
||||
void write(uint8_t) override;
|
||||
void write16(uint16_t) override;
|
||||
void writeRepeat(uint16_t p, uint32_t len) override;
|
||||
void writePixels(uint16_t *data, uint32_t len) override;
|
||||
|
||||
void writeC8D8(uint8_t c, uint8_t d) override;
|
||||
void writeC8D16(uint8_t c, uint16_t d) override;
|
||||
void writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2) override;
|
||||
void writeBytes(uint8_t *data, uint32_t len) override;
|
||||
void writePattern(uint8_t *data, uint8_t len, uint32_t repeat) override;
|
||||
|
||||
void writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len) override;
|
||||
void writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len) override;
|
||||
|
||||
private:
|
||||
GFX_INLINE void WRITE(uint8_t d);
|
||||
GFX_INLINE void WRITE16(uint16_t d);
|
||||
GFX_INLINE void DC_HIGH(void);
|
||||
GFX_INLINE void DC_LOW(void);
|
||||
GFX_INLINE void CS_HIGH(void);
|
||||
GFX_INLINE void CS_LOW(void);
|
||||
|
||||
int8_t _dc, _cs;
|
||||
|
||||
PORTreg_t _csPort; ///< PORT register for chip select
|
||||
PORTreg_t _dcPort; ///< PORT register for data/command
|
||||
ARDUINOGFX_PORT_t _csPinMaskSet; ///< Bitmask for chip select SET (OR)
|
||||
ARDUINOGFX_PORT_t _csPinMaskClr; ///< Bitmask for chip select CLEAR (AND)
|
||||
ARDUINOGFX_PORT_t _dcPinMaskSet; ///< Bitmask for data/command SET (OR)
|
||||
ARDUINOGFX_PORT_t _dcPinMaskClr; ///< Bitmask for data/command CLEAR (AND)
|
||||
|
||||
uint32_t twoPixelBuf[16];
|
||||
volatile uint32_t *spi1Reg32 = (volatile uint32_t *)(0x60000000 + 0x140); // address of SPI1W0
|
||||
};
|
||||
|
||||
#endif // _ARDUINO_ESP8266SPI_H_
|
||||
|
||||
#endif // #ifdef ESP8266
|
||||
@@ -0,0 +1,523 @@
|
||||
/*
|
||||
* start rewrite from:
|
||||
* https://github.com/adafruit/Adafruit-GFX-Library.git
|
||||
*/
|
||||
#include "Arduino_HWSPI.h"
|
||||
|
||||
#if defined(SPI_HAS_TRANSACTION)
|
||||
#define SPI_BEGIN_TRANSACTION() _spi->beginTransaction(mySPISettings)
|
||||
#define SPI_END_TRANSACTION() _spi->endTransaction()
|
||||
#else
|
||||
#define SPI_BEGIN_TRANSACTION() \
|
||||
{ \
|
||||
}
|
||||
#define SPI_END_TRANSACTION() \
|
||||
{ \
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(SPI_HAS_TRANSACTION)
|
||||
static SPISettings mySPISettings;
|
||||
#elif defined(__AVR__) || defined(CORE_TEENSY)
|
||||
static uint8_t SPCRbackup;
|
||||
static uint8_t mySPCR;
|
||||
#endif
|
||||
|
||||
#if defined(ESP32)
|
||||
Arduino_HWSPI::Arduino_HWSPI(int8_t dc, int8_t cs /* = GFX_NOT_DEFINED */, int8_t sck /* = GFX_NOT_DEFINED */, int8_t mosi /* = GFX_NOT_DEFINED */, int8_t miso /* = GFX_NOT_DEFINED */, SPIClass *spi, bool is_shared_interface /* = true */)
|
||||
: _dc(dc), _cs(cs), _sck(sck), _mosi(mosi), _miso(miso), _spi(spi), _is_shared_interface(is_shared_interface)
|
||||
{
|
||||
#else
|
||||
Arduino_HWSPI::Arduino_HWSPI(int8_t dc, int8_t cs /* = GFX_NOT_DEFINED */, SPIClass *spi, bool is_shared_interface /* = true */)
|
||||
: _dc(dc), _cs(cs), _spi(spi), _is_shared_interface(is_shared_interface)
|
||||
{
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Arduino_HWSPI::begin(int32_t speed, int8_t dataMode)
|
||||
{
|
||||
_speed = (speed == GFX_NOT_DEFINED) ? SPI_DEFAULT_FREQ : speed;
|
||||
_dataMode = dataMode;
|
||||
|
||||
pinMode(_dc, OUTPUT);
|
||||
digitalWrite(_dc, HIGH); // Data mode
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
pinMode(_cs, OUTPUT);
|
||||
digitalWrite(_cs, HIGH); // Deselect
|
||||
}
|
||||
|
||||
#if defined(USE_FAST_PINIO)
|
||||
#if defined(HAS_PORT_SET_CLR)
|
||||
#if defined(ARDUINO_ARCH_NRF52840)
|
||||
uint32_t pin = digitalPinToPinName((pin_size_t)_dc);
|
||||
NRF_GPIO_Type *reg = nrf_gpio_pin_port_decode(&pin);
|
||||
_dcPortSet = ®->OUTSET;
|
||||
_dcPortClr = ®->OUTCLR;
|
||||
_dcPinMask = 1UL << pin;
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
pin = digitalPinToPinName((pin_size_t)_cs);
|
||||
reg = nrf_gpio_pin_port_decode(&pin);
|
||||
_csPortSet = ®->OUTSET;
|
||||
_csPortClr = ®->OUTCLR;
|
||||
_csPinMask = 1UL << pin;
|
||||
}
|
||||
#elif defined(ARDUINO_UNOR4_MINIMA) || defined(ARDUINO_UNOR4_WIFI)
|
||||
_dcPinMask = digitalPinToBitMask(_dc);
|
||||
_dcPortSet = (PORTreg_t) & (((R_PORT0_Type *)IOPORT_PRV_PORT_ADDRESS(digitalPinToPort(_dc)))->POSR);
|
||||
_dcPortClr = (PORTreg_t) & (((R_PORT0_Type *)IOPORT_PRV_PORT_ADDRESS(digitalPinToPort(_dc)))->PORR);
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
_csPinMask = digitalPinToBitMask(_cs);
|
||||
_csPortSet = (PORTreg_t) & (((R_PORT0_Type *)IOPORT_PRV_PORT_ADDRESS(digitalPinToPort(_cs)))->POSR);
|
||||
_csPortClr = (PORTreg_t) & (((R_PORT0_Type *)IOPORT_PRV_PORT_ADDRESS(digitalPinToPort(_cs)))->PORR);
|
||||
}
|
||||
#elif defined(TARGET_RP2040) || defined(PICO_RP2350)
|
||||
_dcPinMask = digitalPinToBitMask(_dc);
|
||||
_dcPortSet = (PORTreg_t)&sio_hw->gpio_set;
|
||||
_dcPortClr = (PORTreg_t)&sio_hw->gpio_clr;
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
_csPinMask = digitalPinToBitMask(_cs);
|
||||
_csPortSet = (PORTreg_t)&sio_hw->gpio_set;
|
||||
_csPortClr = (PORTreg_t)&sio_hw->gpio_clr;
|
||||
}
|
||||
#elif defined(ESP32) && (CONFIG_IDF_TARGET_ESP32C3)
|
||||
_dcPinMask = digitalPinToBitMask(_dc);
|
||||
_dcPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_dcPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
_csPinMask = digitalPinToBitMask(_cs);
|
||||
_csPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_csPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
}
|
||||
#elif defined(ESP32)
|
||||
_dcPinMask = digitalPinToBitMask(_dc);
|
||||
if (_dc >= 32)
|
||||
{
|
||||
_dcPortSet = (PORTreg_t)GPIO_OUT1_W1TS_REG;
|
||||
_dcPortClr = (PORTreg_t)GPIO_OUT1_W1TC_REG;
|
||||
}
|
||||
else
|
||||
{
|
||||
_dcPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_dcPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
}
|
||||
if (_cs >= 32)
|
||||
{
|
||||
_csPinMask = digitalPinToBitMask(_cs);
|
||||
_csPortSet = (PORTreg_t)GPIO_OUT1_W1TS_REG;
|
||||
_csPortClr = (PORTreg_t)GPIO_OUT1_W1TC_REG;
|
||||
}
|
||||
else if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
_csPinMask = digitalPinToBitMask(_cs);
|
||||
_csPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_csPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
}
|
||||
#elif defined(CORE_TEENSY)
|
||||
#if !defined(KINETISK)
|
||||
_dcPinMask = digitalPinToBitMask(_dc);
|
||||
#endif
|
||||
_dcPortSet = portSetRegister(_dc);
|
||||
_dcPortClr = portClearRegister(_dc);
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
#if !defined(KINETISK)
|
||||
_csPinMask = digitalPinToBitMask(_cs);
|
||||
#endif
|
||||
_csPortSet = portSetRegister(_cs);
|
||||
_csPortClr = portClearRegister(_cs);
|
||||
}
|
||||
#else // !CORE_TEENSY
|
||||
_dcPinMask = digitalPinToBitMask(_dc);
|
||||
_dcPortSet = &(PORT->Group[g_APinDescription[_dc].ulPort].OUTSET.reg);
|
||||
_dcPortClr = &(PORT->Group[g_APinDescription[_dc].ulPort].OUTCLR.reg);
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
_csPinMask = digitalPinToBitMask(_cs);
|
||||
_csPortSet = &(PORT->Group[g_APinDescription[_cs].ulPort].OUTSET.reg);
|
||||
_csPortClr = &(PORT->Group[g_APinDescription[_cs].ulPort].OUTCLR.reg);
|
||||
}
|
||||
#endif // end !CORE_TEENSY
|
||||
#else // !HAS_PORT_SET_CLR
|
||||
_dcPort = (PORTreg_t)portOutputRegister(digitalPinToPort(_dc));
|
||||
_dcPinMaskSet = digitalPinToBitMask(_dc);
|
||||
_dcPinMaskClr = ~_dcPinMaskSet;
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
_csPort = (PORTreg_t)portOutputRegister(digitalPinToPort(_cs));
|
||||
_csPinMaskSet = digitalPinToBitMask(_cs);
|
||||
}
|
||||
_csPinMaskClr = ~_csPinMaskSet;
|
||||
#endif // !HAS_PORT_SET_CLR
|
||||
#endif // USE_FAST_PINIO
|
||||
|
||||
#if defined(ESP32)
|
||||
_spi->begin(_sck, _miso, _mosi);
|
||||
if (_dataMode == GFX_NOT_DEFINED)
|
||||
{
|
||||
_dataMode = SPI_MODE0;
|
||||
}
|
||||
mySPISettings = SPISettings(_speed, MSBFIRST, _dataMode);
|
||||
#elif defined(ESP8266)
|
||||
_spi->begin();
|
||||
if (_dataMode == GFX_NOT_DEFINED)
|
||||
{
|
||||
_dataMode = SPI_MODE0;
|
||||
}
|
||||
mySPISettings = SPISettings(_speed, MSBFIRST, _dataMode);
|
||||
// Teensy 4.x
|
||||
#elif defined(__IMXRT1052__) || defined(__IMXRT1062__)
|
||||
_spi->begin();
|
||||
if (_dataMode == GFX_NOT_DEFINED)
|
||||
{
|
||||
_dataMode = SPI_MODE0;
|
||||
}
|
||||
mySPISettings = SPISettings(_speed, MSBFIRST, _dataMode);
|
||||
#elif defined(SPI_HAS_TRANSACTION)
|
||||
_spi->begin();
|
||||
if (_dataMode == GFX_NOT_DEFINED)
|
||||
{
|
||||
_dataMode = SPI_MODE2;
|
||||
}
|
||||
mySPISettings = SPISettings(_speed, MSBFIRST, _dataMode);
|
||||
#elif defined(__AVR__) || defined(CORE_TEENSY)
|
||||
SPCRbackup = SPCR;
|
||||
_spi->begin();
|
||||
_spi->setClockDivider(SPI_CLOCK_DIV2);
|
||||
if (_dataMode == GFX_NOT_DEFINED)
|
||||
{
|
||||
_dataMode = SPI_MODE2;
|
||||
}
|
||||
_spi->setDataMode(_dataMode);
|
||||
mySPCR = SPCR; // save our preferred state
|
||||
SPCR = SPCRbackup; // then restore
|
||||
#elif defined(__SAM3X8E__)
|
||||
_spi->begin();
|
||||
_spi->setClockDivider(21); // 4MHz
|
||||
if (_dataMode == GFX_NOT_DEFINED)
|
||||
{
|
||||
_dataMode = SPI_MODE2;
|
||||
}
|
||||
_spi->setDataMode(_dataMode);
|
||||
#elif defined(__arm__)
|
||||
if (_dataMode == GFX_NOT_DEFINED)
|
||||
{
|
||||
_dataMode = SPI_MODE2;
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Arduino_HWSPI::beginWrite()
|
||||
{
|
||||
if (_is_shared_interface)
|
||||
{
|
||||
SPI_BEGIN_TRANSACTION();
|
||||
}
|
||||
|
||||
DC_HIGH();
|
||||
CS_LOW();
|
||||
}
|
||||
|
||||
void Arduino_HWSPI::endWrite()
|
||||
{
|
||||
CS_HIGH();
|
||||
|
||||
if (_is_shared_interface)
|
||||
{
|
||||
SPI_END_TRANSACTION();
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_HWSPI::writeCommand(uint8_t c)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_HWSPI::writeCommand16(uint16_t c)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
#if defined(LITTLE_FOOT_PRINT)
|
||||
_data16.value = c;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
#else // !defined(LITTLE_FOOT_PRINT)
|
||||
WRITE16(c);
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_HWSPI::writeCommandBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
while (len--)
|
||||
{
|
||||
WRITE(*data++);
|
||||
}
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_HWSPI::write(uint8_t d)
|
||||
{
|
||||
WRITE(d);
|
||||
}
|
||||
|
||||
void Arduino_HWSPI::write16(uint16_t d)
|
||||
{
|
||||
#if defined(LITTLE_FOOT_PRINT)
|
||||
_data16.value = d;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
#else // !defined(LITTLE_FOOT_PRINT)
|
||||
WRITE16(d);
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
}
|
||||
|
||||
void Arduino_HWSPI::writeRepeat(uint16_t p, uint32_t len)
|
||||
{
|
||||
#if defined(LITTLE_FOOT_PRINT)
|
||||
_data16.value = p;
|
||||
while (len--)
|
||||
{
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
#elif defined(ESP8266) || defined(CONFIG_ARCH_CHIP_CXD56XX)
|
||||
MSB_16_SET(p, p);
|
||||
uint32_t xferLen = (len < SPI_MAX_PIXELS_AT_ONCE) ? len : SPI_MAX_PIXELS_AT_ONCE;
|
||||
for (uint32_t i = 0; i < xferLen; i++)
|
||||
{
|
||||
_buffer.v16[i] = p;
|
||||
}
|
||||
|
||||
while (len)
|
||||
{
|
||||
xferLen = (len < SPI_MAX_PIXELS_AT_ONCE) ? len : SPI_MAX_PIXELS_AT_ONCE;
|
||||
len -= xferLen;
|
||||
|
||||
xferLen += xferLen;
|
||||
WRITEBUF(_buffer.v8, xferLen);
|
||||
}
|
||||
#else // other arch
|
||||
MSB_16_SET(p, p);
|
||||
uint32_t xferLen;
|
||||
|
||||
while (len)
|
||||
{
|
||||
xferLen = (len < SPI_MAX_PIXELS_AT_ONCE) ? len : SPI_MAX_PIXELS_AT_ONCE;
|
||||
for (uint32_t i = 0; i < xferLen; i++)
|
||||
{
|
||||
_buffer.v16[i] = p;
|
||||
}
|
||||
len -= xferLen;
|
||||
|
||||
xferLen += xferLen;
|
||||
WRITEBUF(_buffer.v8, xferLen);
|
||||
}
|
||||
#endif // other arch
|
||||
}
|
||||
|
||||
void Arduino_HWSPI::writeBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
#if defined(LITTLE_FOOT_PRINT)
|
||||
while (len--)
|
||||
{
|
||||
WRITE(*data++);
|
||||
}
|
||||
#else // !defined(LITTLE_FOOT_PRINT)
|
||||
WRITEBUF(data, len);
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
}
|
||||
|
||||
void Arduino_HWSPI::writePixels(uint16_t *data, uint32_t len)
|
||||
{
|
||||
#if defined(LITTLE_FOOT_PRINT)
|
||||
while (len--)
|
||||
{
|
||||
_data16.value = *data++;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
#else // !defined(LITTLE_FOOT_PRINT)
|
||||
uint32_t xferLen;
|
||||
uint8_t *b;
|
||||
union
|
||||
{
|
||||
uint16_t val;
|
||||
struct
|
||||
{
|
||||
uint8_t lsb;
|
||||
uint8_t msb;
|
||||
};
|
||||
} t;
|
||||
while (len)
|
||||
{
|
||||
xferLen = (len < SPI_MAX_PIXELS_AT_ONCE) ? len : SPI_MAX_PIXELS_AT_ONCE;
|
||||
b = _buffer.v8;
|
||||
for (uint32_t i = 0; i < xferLen; i++)
|
||||
{
|
||||
t.val = *data++;
|
||||
*b++ = t.msb;
|
||||
*b++ = t.lsb;
|
||||
}
|
||||
len -= xferLen;
|
||||
|
||||
xferLen += xferLen; // uint16_t to uint8_t, double length
|
||||
WRITEBUF(_buffer.v8, xferLen);
|
||||
}
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
}
|
||||
|
||||
#if !defined(LITTLE_FOOT_PRINT)
|
||||
void Arduino_HWSPI::writePattern(uint8_t *data, uint8_t len, uint32_t repeat)
|
||||
{
|
||||
#if defined(ESP8266) || defined(ESP32)
|
||||
_spi->writePattern(data, len, repeat);
|
||||
#else // !(defined(ESP8266) || defined(ESP32))
|
||||
while (repeat--)
|
||||
{
|
||||
WRITEBUF(data, len);
|
||||
}
|
||||
#endif // !(defined(ESP8266) || defined(ESP32))
|
||||
}
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
|
||||
GFX_INLINE void Arduino_HWSPI::WRITE(uint8_t d)
|
||||
{
|
||||
#if defined(SPI_HAS_TRANSACTION)
|
||||
_spi->transfer(d);
|
||||
#elif defined(__AVR__) || defined(CORE_TEENSY)
|
||||
SPCRbackup = SPCR;
|
||||
SPCR = mySPCR;
|
||||
_spi->transfer(d);
|
||||
SPCR = SPCRbackup;
|
||||
#elif defined(__arm__)
|
||||
_spi->setClockDivider(21); // 4MHz
|
||||
_spi->setDataMode(_dataMode);
|
||||
_spi->transfer(d);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !defined(LITTLE_FOOT_PRINT)
|
||||
|
||||
GFX_INLINE void Arduino_HWSPI::WRITE16(uint16_t d)
|
||||
{
|
||||
#if defined(ESP8266) || defined(ESP32)
|
||||
_spi->write16(d);
|
||||
#elif defined(SPI_HAS_TRANSACTION)
|
||||
_spi->transfer16(d);
|
||||
#elif defined(__AVR__) || defined(CORE_TEENSY)
|
||||
SPCRbackup = SPCR;
|
||||
SPCR = mySPCR;
|
||||
_spi->transfer16(d);
|
||||
SPCR = SPCRbackup;
|
||||
#elif defined(__arm__)
|
||||
_spi->setClockDivider(21); // 4MHz
|
||||
_spi->setDataMode(_dataMode);
|
||||
_spi->transfer16(d);
|
||||
#else
|
||||
_spi->transfer16(d);
|
||||
#endif
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_HWSPI::WRITEBUF(uint8_t *buf, size_t count)
|
||||
{
|
||||
#if defined(ESP8266) || defined(ESP32)
|
||||
_spi->writeBytes(buf, count);
|
||||
#elif defined(CONFIG_ARCH_CHIP_CXD56XX)
|
||||
_spi->send(buf, count);
|
||||
#else // other arch.
|
||||
_spi->transfer(buf, count);
|
||||
#endif // other arch.
|
||||
}
|
||||
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
|
||||
/******** low level bit twiddling **********/
|
||||
|
||||
GFX_INLINE void Arduino_HWSPI::DC_HIGH(void)
|
||||
{
|
||||
#if defined(USE_FAST_PINIO)
|
||||
#if defined(HAS_PORT_SET_CLR)
|
||||
#if defined(KINETISK)
|
||||
*_dcPortSet = 1;
|
||||
#else // !KINETISK
|
||||
*_dcPortSet = _dcPinMask;
|
||||
#endif // end !KINETISK
|
||||
#else // !HAS_PORT_SET_CLR
|
||||
*_dcPort |= _dcPinMaskSet;
|
||||
#endif // end !HAS_PORT_SET_CLR
|
||||
#else // !USE_FAST_PINIO
|
||||
digitalWrite(_dc, HIGH);
|
||||
#endif // end !USE_FAST_PINIO
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_HWSPI::DC_LOW(void)
|
||||
{
|
||||
#if defined(USE_FAST_PINIO)
|
||||
#if defined(HAS_PORT_SET_CLR)
|
||||
#if defined(KINETISK)
|
||||
*_dcPortClr = 1;
|
||||
#else // !KINETISK
|
||||
*_dcPortClr = _dcPinMask;
|
||||
#endif // end !KINETISK
|
||||
#else // !HAS_PORT_SET_CLR
|
||||
*_dcPort &= _dcPinMaskClr;
|
||||
#endif // end !HAS_PORT_SET_CLR
|
||||
#else // !USE_FAST_PINIO
|
||||
digitalWrite(_dc, LOW);
|
||||
#endif // end !USE_FAST_PINIO
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_HWSPI::CS_HIGH(void)
|
||||
{
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
#if defined(USE_FAST_PINIO)
|
||||
#if defined(HAS_PORT_SET_CLR)
|
||||
#if defined(KINETISK)
|
||||
*_csPortSet = 1;
|
||||
#else // !KINETISK
|
||||
*_csPortSet = _csPinMask;
|
||||
#endif // end !KINETISK
|
||||
#else // !HAS_PORT_SET_CLR
|
||||
*_csPort |= _csPinMaskSet;
|
||||
#endif // end !HAS_PORT_SET_CLR
|
||||
#else // !USE_FAST_PINIO
|
||||
digitalWrite(_cs, HIGH);
|
||||
#endif // end !USE_FAST_PINIO
|
||||
}
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_HWSPI::CS_LOW(void)
|
||||
{
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
#if defined(USE_FAST_PINIO)
|
||||
#if defined(HAS_PORT_SET_CLR)
|
||||
#if defined(KINETISK)
|
||||
*_csPortClr = 1;
|
||||
#else // !KINETISK
|
||||
*_csPortClr = _csPinMask;
|
||||
#endif // end !KINETISK
|
||||
#else // !HAS_PORT_SET_CLR
|
||||
*_csPort &= _csPinMaskClr;
|
||||
#endif // end !HAS_PORT_SET_CLR
|
||||
#else // !USE_FAST_PINIO
|
||||
digitalWrite(_cs, LOW);
|
||||
#endif // end !USE_FAST_PINIO
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* start rewrite from:
|
||||
* https://github.com/adafruit/Adafruit-GFX-Library.git
|
||||
*/
|
||||
#ifndef _ARDUINO_HWSPI_H_
|
||||
#define _ARDUINO_HWSPI_H_
|
||||
|
||||
#include <SPI.h>
|
||||
#include "Arduino_DataBus.h"
|
||||
|
||||
#if !defined(LITTLE_FOOT_PRINT)
|
||||
#ifndef SPI_MAX_PIXELS_AT_ONCE
|
||||
#define SPI_MAX_PIXELS_AT_ONCE 32
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// HARDWARE CONFIG ---------------------------------------------------------
|
||||
|
||||
class Arduino_HWSPI : public Arduino_DataBus
|
||||
{
|
||||
public:
|
||||
#if defined(ESP32)
|
||||
Arduino_HWSPI(int8_t dc, int8_t cs = GFX_NOT_DEFINED, int8_t sck = GFX_NOT_DEFINED, int8_t mosi = GFX_NOT_DEFINED, int8_t miso = GFX_NOT_DEFINED, SPIClass *spi = &SPI, bool is_shared_interface = true); // Constructor
|
||||
#elif defined(ARDUINO_ARCH_SAMD) && defined(SEEED_GROVE_UI_WIRELESS)
|
||||
Arduino_HWSPI(int8_t dc, int8_t cs = GFX_NOT_DEFINED, SPIClass *spi = &LCD_SPI, bool is_shared_interface = true); // Constructor
|
||||
#elif defined(RTL8722DM) && defined(BOARD_RTL8722DM)
|
||||
Arduino_HWSPI(int8_t dc, int8_t cs = GFX_NOT_DEFINED, SPIClass *spi = &SPI1, bool is_shared_interface = true); // Constructor
|
||||
#else
|
||||
Arduino_HWSPI(int8_t dc, int8_t cs = GFX_NOT_DEFINED, SPIClass *spi = &SPI, bool is_shared_interface = true); // Constructor
|
||||
#endif
|
||||
|
||||
bool begin(int32_t speed = GFX_NOT_DEFINED, int8_t dataMode = GFX_NOT_DEFINED) override;
|
||||
void beginWrite() override;
|
||||
void endWrite() override;
|
||||
void writeCommand(uint8_t) override;
|
||||
void writeCommand16(uint16_t) override;
|
||||
void writeCommandBytes(uint8_t *data, uint32_t len) override;
|
||||
void write(uint8_t) override;
|
||||
void write16(uint16_t) override;
|
||||
void writeRepeat(uint16_t p, uint32_t len) override;
|
||||
void writeBytes(uint8_t *data, uint32_t len) override;
|
||||
void writePixels(uint16_t *data, uint32_t len) override;
|
||||
|
||||
#if !defined(LITTLE_FOOT_PRINT)
|
||||
void writePattern(uint8_t *data, uint8_t len, uint32_t repeat) override;
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
|
||||
private:
|
||||
GFX_INLINE void WRITE(uint8_t d);
|
||||
#if !defined(LITTLE_FOOT_PRINT)
|
||||
GFX_INLINE void WRITE16(uint16_t d);
|
||||
GFX_INLINE void WRITEBUF(uint8_t *buf, size_t count);
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
GFX_INLINE void DC_HIGH(void);
|
||||
GFX_INLINE void DC_LOW(void);
|
||||
GFX_INLINE void CS_HIGH(void);
|
||||
GFX_INLINE void CS_LOW(void);
|
||||
|
||||
|
||||
int8_t _dc, _cs;
|
||||
#if defined(ESP32)
|
||||
int8_t _sck, _mosi, _miso;
|
||||
#endif
|
||||
SPIClass *_spi;
|
||||
bool _is_shared_interface;
|
||||
|
||||
// CLASS INSTANCE VARIABLES --------------------------------------------
|
||||
|
||||
// Here be dragons! There's a big union of three structures here --
|
||||
// one each for hardware SPI, software (bitbang) SPI, and parallel
|
||||
// interfaces. This is to save some memory, since a display's connection
|
||||
// will be only one of these. The order of some things is a little weird
|
||||
// in an attempt to get values to align and pack better in RAM.
|
||||
|
||||
#if defined(USE_FAST_PINIO)
|
||||
#if defined(HAS_PORT_SET_CLR)
|
||||
PORTreg_t _csPortSet; ///< PORT register for chip select SET
|
||||
PORTreg_t _csPortClr; ///< PORT register for chip select CLEAR
|
||||
PORTreg_t _dcPortSet; ///< PORT register for data/command SET
|
||||
PORTreg_t _dcPortClr; ///< PORT register for data/command CLEAR
|
||||
#if !defined(KINETISK)
|
||||
ARDUINOGFX_PORT_t _csPinMask; ///< Bitmask for chip select
|
||||
ARDUINOGFX_PORT_t _dcPinMask; ///< Bitmask for data/command
|
||||
#endif // !KINETISK
|
||||
#else // !HAS_PORT_SET_CLR
|
||||
PORTreg_t _csPort; ///< PORT register for chip select
|
||||
PORTreg_t _dcPort; ///< PORT register for data/command
|
||||
ARDUINOGFX_PORT_t _csPinMaskSet; ///< Bitmask for chip select SET (OR)
|
||||
ARDUINOGFX_PORT_t _csPinMaskClr; ///< Bitmask for chip select CLEAR (AND)
|
||||
ARDUINOGFX_PORT_t _dcPinMaskSet; ///< Bitmask for data/command SET (OR)
|
||||
ARDUINOGFX_PORT_t _dcPinMaskClr; ///< Bitmask for data/command CLEAR (AND)
|
||||
#endif // HAS_PORT_SET_CLR
|
||||
#endif // !defined(USE_FAST_PINIO)
|
||||
|
||||
#if !defined(LITTLE_FOOT_PRINT)
|
||||
union
|
||||
{
|
||||
uint8_t v8[SPI_MAX_PIXELS_AT_ONCE * 2] = {0};
|
||||
uint16_t v16[SPI_MAX_PIXELS_AT_ONCE];
|
||||
} _buffer;
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
};
|
||||
|
||||
#endif // _ARDUINO_HWSPI_H_
|
||||
@@ -0,0 +1,292 @@
|
||||
/*
|
||||
* start rewrite from:
|
||||
* https://github.com/arduino/ArduinoCore-mbed/blob/master/libraries/SPI/SPI.cpp
|
||||
*/
|
||||
#ifdef ARDUINO_ARCH_NRF52840
|
||||
|
||||
#include "Arduino_NRFXSPI.h"
|
||||
|
||||
Arduino_NRFXSPI::Arduino_NRFXSPI(int8_t dc, int8_t cs /* = GFX_NOT_DEFINED */, int8_t sck /* = GFX_NOT_DEFINED */, int8_t mosi /* = GFX_NOT_DEFINED */, int8_t miso /* = GFX_NOT_DEFINED */)
|
||||
: _dc(dc), _cs(cs), _sck(sck), _mosi(mosi), _miso(miso)
|
||||
{
|
||||
}
|
||||
|
||||
bool Arduino_NRFXSPI::begin(int32_t speed, int8_t dataMode)
|
||||
{
|
||||
_speed = (speed == GFX_NOT_DEFINED) ? SPI_DEFAULT_FREQ : speed;
|
||||
_dataMode = (dataMode == GFX_NOT_DEFINED) ? SPI_MODE2 : dataMode;
|
||||
|
||||
// init pin mask
|
||||
uint32_t pin = digitalPinToPinName((pin_size_t)_dc);
|
||||
NRF_GPIO_Type *reg = nrf_gpio_pin_port_decode(&pin);
|
||||
nrf_gpio_cfg_output(pin);
|
||||
_dcPortSet = ®->OUTSET;
|
||||
_dcPortClr = ®->OUTCLR;
|
||||
_dcPinMask = 1UL << pin;
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
pin = digitalPinToPinName((pin_size_t)_cs);
|
||||
reg = nrf_gpio_pin_port_decode(&pin);
|
||||
nrf_gpio_cfg_output(pin);
|
||||
_csPortSet = ®->OUTSET;
|
||||
_csPortClr = ®->OUTCLR;
|
||||
_csPinMask = 1UL << pin;
|
||||
}
|
||||
|
||||
// init SPI pins
|
||||
_nrfxSpiConfig.sck_pin = digitalPinToPinName((pin_size_t)_sck);
|
||||
_nrfxSpiConfig.mosi_pin = digitalPinToPinName((pin_size_t)_mosi);
|
||||
if (_miso > 0)
|
||||
{
|
||||
_nrfxSpiConfig.miso_pin = digitalPinToPinName((pin_size_t)_miso);
|
||||
}
|
||||
else
|
||||
{
|
||||
_nrfxSpiConfig.miso_pin = NRFX_SPI_PIN_NOT_USED;
|
||||
}
|
||||
|
||||
// init speed
|
||||
if (_speed >= 8000000)
|
||||
{
|
||||
_nrfxSpiConfig.frequency = NRF_SPI_FREQ_8M;
|
||||
}
|
||||
else if (_speed >= 4000000)
|
||||
{
|
||||
_nrfxSpiConfig.frequency = NRF_SPI_FREQ_4M;
|
||||
}
|
||||
else if (_speed >= 2000000)
|
||||
{
|
||||
_nrfxSpiConfig.frequency = NRF_SPI_FREQ_2M;
|
||||
}
|
||||
else if (_speed >= 1000000)
|
||||
{
|
||||
_nrfxSpiConfig.frequency = NRF_SPI_FREQ_1M;
|
||||
}
|
||||
else if (_speed >= 500000)
|
||||
{
|
||||
_nrfxSpiConfig.frequency = NRF_SPI_FREQ_500K;
|
||||
}
|
||||
else if (_speed >= 250000)
|
||||
{
|
||||
_nrfxSpiConfig.frequency = NRF_SPI_FREQ_250K;
|
||||
}
|
||||
else if (_speed >= 125000)
|
||||
{
|
||||
_nrfxSpiConfig.frequency = NRF_SPI_FREQ_125K;
|
||||
}
|
||||
|
||||
// init data mode
|
||||
if (_dataMode == SPI_MODE1)
|
||||
{
|
||||
_nrfxSpiConfig.mode = NRF_SPI_MODE_1;
|
||||
}
|
||||
else if (_dataMode == SPI_MODE2)
|
||||
{
|
||||
_nrfxSpiConfig.mode = NRF_SPI_MODE_2;
|
||||
}
|
||||
else if (_dataMode == SPI_MODE3)
|
||||
{
|
||||
_nrfxSpiConfig.mode = NRF_SPI_MODE_3;
|
||||
}
|
||||
else
|
||||
{
|
||||
_dataMode = SPI_MODE0;
|
||||
_nrfxSpiConfig.mode = NRF_SPI_MODE_0;
|
||||
}
|
||||
|
||||
// init SPI
|
||||
nrfx_spi_init(&_nrfxSpi, &_nrfxSpiConfig, NULL, NULL);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Arduino_NRFXSPI::beginWrite()
|
||||
{
|
||||
DC_HIGH();
|
||||
|
||||
CS_LOW();
|
||||
}
|
||||
|
||||
void Arduino_NRFXSPI::endWrite()
|
||||
{
|
||||
CS_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_NRFXSPI::writeCommand(uint8_t c)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_NRFXSPI::writeCommand16(uint16_t c)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE16(c);
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_NRFXSPI::writeCommandBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
while (len--)
|
||||
{
|
||||
WRITE(*data++);
|
||||
}
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_NRFXSPI::write(uint8_t d)
|
||||
{
|
||||
WRITE(d);
|
||||
}
|
||||
|
||||
void Arduino_NRFXSPI::write16(uint16_t d)
|
||||
{
|
||||
WRITE16(d);
|
||||
}
|
||||
|
||||
void Arduino_NRFXSPI::writeRepeat(uint16_t p, uint32_t len)
|
||||
{
|
||||
MSB_16_SET(p, p);
|
||||
uint32_t bufLen = (len < NRFXSPI_MAX_PIXELS_AT_ONCE) ? len : NRFXSPI_MAX_PIXELS_AT_ONCE;
|
||||
uint32_t xferLen;
|
||||
for (uint32_t i = 0; i < bufLen; i++)
|
||||
{
|
||||
_buffer16[i] = p;
|
||||
}
|
||||
|
||||
while (len)
|
||||
{
|
||||
xferLen = (bufLen < len) ? bufLen : len;
|
||||
WRITEBUF(_buffer, xferLen * 2);
|
||||
len -= xferLen;
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_NRFXSPI::writePixels(uint16_t *data, uint32_t len)
|
||||
{
|
||||
uint32_t xferLen;
|
||||
uint8_t *p;
|
||||
union
|
||||
{
|
||||
uint16_t val;
|
||||
struct
|
||||
{
|
||||
uint8_t lsb;
|
||||
uint8_t msb;
|
||||
};
|
||||
} t;
|
||||
while (len)
|
||||
{
|
||||
xferLen = (len < NRFXSPI_MAX_PIXELS_AT_ONCE) ? len : NRFXSPI_MAX_PIXELS_AT_ONCE;
|
||||
p = _buffer;
|
||||
for (uint32_t i = 0; i < xferLen; i++)
|
||||
{
|
||||
t.val = *data++;
|
||||
*p++ = t.msb;
|
||||
*p++ = t.lsb;
|
||||
}
|
||||
len -= xferLen;
|
||||
|
||||
xferLen += xferLen; // uint16_t to uint8_t, double length
|
||||
WRITEBUF(_buffer, xferLen);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_NRFXSPI::writeC8D8(uint8_t c, uint8_t d)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
WRITE(d);
|
||||
}
|
||||
|
||||
void Arduino_NRFXSPI::writeC8D16(uint8_t c, uint16_t d)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
WRITE16(d);
|
||||
}
|
||||
|
||||
void Arduino_NRFXSPI::writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
const nrfx_spi_xfer_desc_t xfer_desc1 = NRFX_SPI_SINGLE_XFER(&c, 1, NULL, 0);
|
||||
nrfx_spi_xfer(&_nrfxSpi, &xfer_desc1, 0);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
uint32_t d;
|
||||
MSB_32_16_16_SET(d, d1, d2);
|
||||
const nrfx_spi_xfer_desc_t xfer_desc2 = NRFX_SPI_SINGLE_XFER(&d, 4, NULL, 0);
|
||||
nrfx_spi_xfer(&_nrfxSpi, &xfer_desc2, 0);
|
||||
}
|
||||
|
||||
void Arduino_NRFXSPI::writeBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
WRITEBUF(data, len);
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_NRFXSPI::WRITE(uint8_t d)
|
||||
{
|
||||
const nrfx_spi_xfer_desc_t xfer_desc = NRFX_SPI_SINGLE_XFER(&d, 1, NULL, 0);
|
||||
nrfx_spi_xfer(&_nrfxSpi, &xfer_desc, 0);
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_NRFXSPI::WRITE16(uint16_t d)
|
||||
{
|
||||
MSB_16_SET(d, d);
|
||||
const nrfx_spi_xfer_desc_t xfer_desc = NRFX_SPI_SINGLE_XFER(&d, 2, NULL, 0);
|
||||
nrfx_spi_xfer(&_nrfxSpi, &xfer_desc, 0);
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_NRFXSPI::WRITEBUF(uint8_t *buf, size_t count)
|
||||
{
|
||||
const nrfx_spi_xfer_desc_t xfer_desc = NRFX_SPI_SINGLE_XFER(buf, count, NULL, 0);
|
||||
nrfx_spi_xfer(&_nrfxSpi, &xfer_desc, 0);
|
||||
}
|
||||
|
||||
/******** low level bit twiddling **********/
|
||||
|
||||
GFX_INLINE void Arduino_NRFXSPI::DC_HIGH(void)
|
||||
{
|
||||
*_dcPortSet = _dcPinMask;
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_NRFXSPI::DC_LOW(void)
|
||||
{
|
||||
*_dcPortClr = _dcPinMask;
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_NRFXSPI::CS_HIGH(void)
|
||||
{
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
*_csPortSet = _csPinMask;
|
||||
}
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_NRFXSPI::CS_LOW(void)
|
||||
{
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
*_csPortClr = _csPinMask;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // #ifdef ARDUINO_ARCH_NRF52840
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* start rewrite from:
|
||||
* https://github.com/arduino/ArduinoCore-mbed/blob/master/libraries/SPI/SPI.cpp
|
||||
*/
|
||||
#ifdef ARDUINO_ARCH_NRF52840
|
||||
|
||||
#ifndef _ARDUINO_NRFXSPI_H_
|
||||
#define _ARDUINO_NRFXSPI_H_
|
||||
|
||||
#include <SPI.h>
|
||||
|
||||
#include "Arduino_DataBus.h"
|
||||
|
||||
#ifndef NRFXSPI_MAX_PIXELS_AT_ONCE
|
||||
#define NRFXSPI_MAX_PIXELS_AT_ONCE 32
|
||||
#endif
|
||||
|
||||
class Arduino_NRFXSPI : public Arduino_DataBus
|
||||
{
|
||||
public:
|
||||
Arduino_NRFXSPI(int8_t dc, int8_t cs = GFX_NOT_DEFINED, int8_t sck = GFX_NOT_DEFINED, int8_t mosi = GFX_NOT_DEFINED, int8_t miso = GFX_NOT_DEFINED); // Constructor
|
||||
|
||||
bool begin(int32_t speed = GFX_NOT_DEFINED, int8_t dataMode = GFX_NOT_DEFINED) override;
|
||||
void beginWrite() override;
|
||||
void endWrite() override;
|
||||
void writeCommand(uint8_t) override;
|
||||
void writeCommand16(uint16_t) override;
|
||||
void writeCommandBytes(uint8_t *data, uint32_t len) override;
|
||||
void write(uint8_t) override;
|
||||
void write16(uint16_t) override;
|
||||
void writeRepeat(uint16_t p, uint32_t len) override;
|
||||
void writePixels(uint16_t *data, uint32_t len) override;
|
||||
|
||||
void writeC8D8(uint8_t c, uint8_t d) override;
|
||||
void writeC8D16(uint8_t c, uint16_t d) override;
|
||||
void writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2) override;
|
||||
void writeBytes(uint8_t *data, uint32_t len) override;
|
||||
|
||||
private:
|
||||
GFX_INLINE void WRITE(uint8_t d);
|
||||
GFX_INLINE void WRITE16(uint16_t d);
|
||||
GFX_INLINE void WRITEBUF(uint8_t *buf, size_t count);
|
||||
GFX_INLINE void DC_HIGH(void);
|
||||
GFX_INLINE void DC_LOW(void);
|
||||
GFX_INLINE void CS_HIGH(void);
|
||||
GFX_INLINE void CS_LOW(void);
|
||||
|
||||
int8_t _dc, _cs;
|
||||
int8_t _sck, _mosi, _miso;
|
||||
|
||||
PORTreg_t _csPortSet; ///< PORT register for chip select SET
|
||||
PORTreg_t _csPortClr; ///< PORT register for chip select CLEAR
|
||||
PORTreg_t _dcPortSet; ///< PORT register for data/command SET
|
||||
PORTreg_t _dcPortClr; ///< PORT register for data/command CLEAR
|
||||
ARDUINOGFX_PORT_t _csPinMask; ///< Bitmask for chip select
|
||||
ARDUINOGFX_PORT_t _dcPinMask; ///< Bitmask for data/command
|
||||
|
||||
nrfx_spi_config_t _nrfxSpiConfig = NRFX_SPI_DEFAULT_CONFIG;
|
||||
nrfx_spi_t _nrfxSpi = NRFX_SPI_INSTANCE(0);
|
||||
|
||||
union
|
||||
{
|
||||
uint8_t _buffer[NRFXSPI_MAX_PIXELS_AT_ONCE * 2] = {0};
|
||||
uint16_t _buffer16[NRFXSPI_MAX_PIXELS_AT_ONCE];
|
||||
uint32_t _buffer32[NRFXSPI_MAX_PIXELS_AT_ONCE / 2];
|
||||
};
|
||||
};
|
||||
|
||||
#endif // _ARDUINO_NRFXSPI_H_
|
||||
|
||||
#endif // #ifdef ARDUINO_ARCH_NRF52840
|
||||
@@ -0,0 +1,256 @@
|
||||
#if defined(TARGET_RP2040) || defined(PICO_RP2350)
|
||||
|
||||
#include "Arduino_RPiPicoPAR16.h"
|
||||
|
||||
Arduino_RPiPicoPAR16::Arduino_RPiPicoPAR16(int8_t dc, int8_t cs, int8_t wr, int8_t rd)
|
||||
: _dc(dc), _cs(cs), _wr(wr), _rd(rd)
|
||||
{
|
||||
}
|
||||
|
||||
bool Arduino_RPiPicoPAR16::begin(int32_t speed, int8_t dataMode)
|
||||
{
|
||||
pinMode(_dc, OUTPUT);
|
||||
digitalWrite(_dc, HIGH); // Data mode
|
||||
_dcPinMask = digitalPinToBitMask(_dc);
|
||||
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
pinMode(_cs, OUTPUT);
|
||||
digitalWrite(_cs, HIGH); // disable chip select
|
||||
_csPinMask = digitalPinToBitMask(_cs);
|
||||
}
|
||||
|
||||
pinMode(_wr, OUTPUT);
|
||||
digitalWrite(_wr, HIGH); // Set write strobe high (inactive)
|
||||
_wrPinMask = digitalPinToBitMask(_wr);
|
||||
_dataClrMask = 0xFFFF | _wrPinMask;
|
||||
|
||||
if (_rd != GFX_NOT_DEFINED)
|
||||
{
|
||||
pinMode(_rd, OUTPUT);
|
||||
digitalWrite(_rd, HIGH);
|
||||
}
|
||||
|
||||
pinMode(0, OUTPUT);
|
||||
pinMode(1, OUTPUT);
|
||||
pinMode(2, OUTPUT);
|
||||
pinMode(3, OUTPUT);
|
||||
pinMode(4, OUTPUT);
|
||||
pinMode(5, OUTPUT);
|
||||
pinMode(6, OUTPUT);
|
||||
pinMode(7, OUTPUT);
|
||||
pinMode(8, OUTPUT);
|
||||
pinMode(9, OUTPUT);
|
||||
pinMode(10, OUTPUT);
|
||||
pinMode(11, OUTPUT);
|
||||
pinMode(12, OUTPUT);
|
||||
pinMode(13, OUTPUT);
|
||||
pinMode(14, OUTPUT);
|
||||
pinMode(15, OUTPUT);
|
||||
sio_hw->gpio_clr = 0xFFFF;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Arduino_RPiPicoPAR16::beginWrite()
|
||||
{
|
||||
DC_HIGH();
|
||||
CS_LOW();
|
||||
}
|
||||
|
||||
void Arduino_RPiPicoPAR16::endWrite()
|
||||
{
|
||||
CS_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_RPiPicoPAR16::writeCommand(uint8_t c)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_RPiPicoPAR16::writeCommand16(uint16_t c)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE16(c);
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_RPiPicoPAR16::writeCommandBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
while (len--)
|
||||
{
|
||||
WRITE(*data++);
|
||||
}
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_RPiPicoPAR16::write(uint8_t d)
|
||||
{
|
||||
WRITE(d);
|
||||
}
|
||||
|
||||
void Arduino_RPiPicoPAR16::write16(uint16_t d)
|
||||
{
|
||||
WRITE16(d);
|
||||
}
|
||||
|
||||
void Arduino_RPiPicoPAR16::writeRepeat(uint16_t p, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
sio_hw->gpio_clr = _dataClrMask;
|
||||
sio_hw->gpio_set = p;
|
||||
sio_hw->gpio_set = _wrPinMask;
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_RPiPicoPAR16::writePixels(uint16_t *data, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
sio_hw->gpio_clr = _dataClrMask;
|
||||
sio_hw->gpio_set = *data++;
|
||||
sio_hw->gpio_set = _wrPinMask;
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_RPiPicoPAR16::writeC8D8(uint8_t c, uint8_t d)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
WRITE(d);
|
||||
}
|
||||
|
||||
void Arduino_RPiPicoPAR16::writeC8D16(uint8_t c, uint16_t d)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
WRITE16(d);
|
||||
}
|
||||
|
||||
void Arduino_RPiPicoPAR16::writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
WRITE16(d1);
|
||||
WRITE16(d2);
|
||||
}
|
||||
|
||||
void Arduino_RPiPicoPAR16::writeC8D16D16Split(uint8_t c, uint16_t d1, uint16_t d2)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
_data16.value = d1;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
|
||||
_data16.value = d2;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
|
||||
void Arduino_RPiPicoPAR16::writeBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
while (len > 1)
|
||||
{
|
||||
_data16.msb = *data++;
|
||||
_data16.lsb = *data++;
|
||||
WRITE16(_data16.value);
|
||||
len -= 2;
|
||||
}
|
||||
if (len)
|
||||
{
|
||||
WRITE(*data);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_RPiPicoPAR16::writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
sio_hw->gpio_clr = _dataClrMask;
|
||||
sio_hw->gpio_set = idx[*data++];
|
||||
sio_hw->gpio_set = _wrPinMask;
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_RPiPicoPAR16::writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
sio_hw->gpio_clr = _dataClrMask;
|
||||
sio_hw->gpio_set = idx[*data++];
|
||||
sio_hw->gpio_set = _wrPinMask;
|
||||
sio_hw->gpio_clr = _wrPinMask;
|
||||
sio_hw->gpio_set = _wrPinMask;
|
||||
}
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_RPiPicoPAR16::WRITE(uint8_t d)
|
||||
{
|
||||
sio_hw->gpio_clr = _dataClrMask;
|
||||
sio_hw->gpio_set = d;
|
||||
sio_hw->gpio_set = _wrPinMask;
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_RPiPicoPAR16::WRITE16(uint16_t d)
|
||||
{
|
||||
sio_hw->gpio_clr = _dataClrMask;
|
||||
sio_hw->gpio_set = d;
|
||||
sio_hw->gpio_set = _wrPinMask;
|
||||
}
|
||||
|
||||
/******** low level bit twiddling **********/
|
||||
|
||||
GFX_INLINE void Arduino_RPiPicoPAR16::DC_HIGH(void)
|
||||
{
|
||||
sio_hw->gpio_set = _dcPinMask;
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_RPiPicoPAR16::DC_LOW(void)
|
||||
{
|
||||
sio_hw->gpio_clr = _dcPinMask;
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_RPiPicoPAR16::CS_HIGH(void)
|
||||
{
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
sio_hw->gpio_set = _csPinMask;
|
||||
}
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_RPiPicoPAR16::CS_LOW(void)
|
||||
{
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
sio_hw->gpio_clr = _csPinMask;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // #if defined(TARGET_RP2040) || defined(PICO_RP2350)
|
||||
@@ -0,0 +1,52 @@
|
||||
#if defined(TARGET_RP2040) || defined(PICO_RP2350)
|
||||
|
||||
#ifndef _ARDUINO_RPIPICOPAR16_H_
|
||||
#define _ARDUINO_RPIPICOPAR16_H_
|
||||
|
||||
#include "Arduino_DataBus.h"
|
||||
|
||||
class Arduino_RPiPicoPAR16 : public Arduino_DataBus
|
||||
{
|
||||
public:
|
||||
Arduino_RPiPicoPAR16(int8_t dc, int8_t cs, int8_t wr, int8_t rd); // Constructor
|
||||
|
||||
bool begin(int32_t speed = GFX_NOT_DEFINED, int8_t dataMode = GFX_NOT_DEFINED) override;
|
||||
void beginWrite() override;
|
||||
void endWrite() override;
|
||||
void writeCommand(uint8_t) override;
|
||||
void writeCommand16(uint16_t) override;
|
||||
void writeCommandBytes(uint8_t *data, uint32_t len) override;
|
||||
void write(uint8_t) override;
|
||||
void write16(uint16_t) override;
|
||||
void writeRepeat(uint16_t p, uint32_t len) override;
|
||||
void writePixels(uint16_t *data, uint32_t len) override;
|
||||
|
||||
void writeC8D8(uint8_t c, uint8_t d) override;
|
||||
void writeC8D16(uint8_t c, uint16_t d) override;
|
||||
void writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2) override;
|
||||
void writeC8D16D16Split(uint8_t c, uint16_t d1, uint16_t d2) override;
|
||||
void writeBytes(uint8_t *data, uint32_t len) override;
|
||||
|
||||
void writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len) override;
|
||||
void writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len) override;
|
||||
|
||||
protected:
|
||||
private:
|
||||
GFX_INLINE void WRITE(uint8_t d);
|
||||
GFX_INLINE void WRITE16(uint16_t d);
|
||||
GFX_INLINE void DC_HIGH(void);
|
||||
GFX_INLINE void DC_LOW(void);
|
||||
GFX_INLINE void CS_HIGH(void);
|
||||
GFX_INLINE void CS_LOW(void);
|
||||
|
||||
int8_t _dc, _cs, _wr, _rd;
|
||||
|
||||
uint32_t _dcPinMask; ///< Bitmask
|
||||
uint32_t _csPinMask; ///< Bitmask
|
||||
uint32_t _wrPinMask; ///< Bitmask
|
||||
uint32_t _dataClrMask;
|
||||
};
|
||||
|
||||
#endif // _ARDUINO_RPIPICOPAR16_H_
|
||||
|
||||
#endif // #if defined(TARGET_RP2040) || defined(PICO_RP2350)
|
||||
@@ -0,0 +1,240 @@
|
||||
#if defined(TARGET_RP2040) || defined(PICO_RP2350)
|
||||
|
||||
#include "Arduino_RPiPicoPAR8.h"
|
||||
|
||||
Arduino_RPiPicoPAR8::Arduino_RPiPicoPAR8(int8_t dc, int8_t cs, int8_t wr, int8_t rd)
|
||||
: _dc(dc), _cs(cs), _wr(wr), _rd(rd)
|
||||
{
|
||||
}
|
||||
|
||||
bool Arduino_RPiPicoPAR8::begin(int32_t speed, int8_t dataMode)
|
||||
{
|
||||
pinMode(_dc, OUTPUT);
|
||||
digitalWrite(_dc, HIGH); // Data mode
|
||||
_dcPinMask = digitalPinToBitMask(_dc);
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
pinMode(_cs, OUTPUT);
|
||||
digitalWrite(_cs, HIGH); // disable chip select
|
||||
_csPinMask = digitalPinToBitMask(_cs);
|
||||
}
|
||||
pinMode(_wr, OUTPUT);
|
||||
digitalWrite(_wr, HIGH); // Set write strobe high (inactive)
|
||||
_wrPinMask = digitalPinToBitMask(_wr);
|
||||
_dataClrMask = 0xFF | _wrPinMask;
|
||||
|
||||
pinMode(0, OUTPUT);
|
||||
pinMode(1, OUTPUT);
|
||||
pinMode(2, OUTPUT);
|
||||
pinMode(3, OUTPUT);
|
||||
pinMode(4, OUTPUT);
|
||||
pinMode(5, OUTPUT);
|
||||
pinMode(6, OUTPUT);
|
||||
pinMode(7, OUTPUT);
|
||||
sio_hw->gpio_clr = 0xFF;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Arduino_RPiPicoPAR8::beginWrite()
|
||||
{
|
||||
DC_HIGH();
|
||||
CS_LOW();
|
||||
}
|
||||
|
||||
void Arduino_RPiPicoPAR8::endWrite()
|
||||
{
|
||||
CS_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_RPiPicoPAR8::writeCommand(uint8_t c)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_RPiPicoPAR8::writeCommand16(uint16_t c)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
_data16.value = c;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_RPiPicoPAR8::writeCommandBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
while (len--)
|
||||
{
|
||||
WRITE(*data++);
|
||||
}
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_RPiPicoPAR8::write(uint8_t d)
|
||||
{
|
||||
WRITE(d);
|
||||
}
|
||||
|
||||
void Arduino_RPiPicoPAR8::write16(uint16_t d)
|
||||
{
|
||||
_data16.value = d;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
|
||||
void Arduino_RPiPicoPAR8::writeRepeat(uint16_t p, uint32_t len)
|
||||
{
|
||||
_data16.value = p;
|
||||
if (_data16.msb == _data16.lsb)
|
||||
{
|
||||
sio_hw->gpio_clr = 0xFF;
|
||||
sio_hw->gpio_set = _data16.msb;
|
||||
while (len--)
|
||||
{
|
||||
sio_hw->gpio_clr = _wrPinMask;
|
||||
sio_hw->gpio_set = _wrPinMask;
|
||||
sio_hw->gpio_clr = _wrPinMask;
|
||||
sio_hw->gpio_set = _wrPinMask;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
sio_hw->gpio_clr = _dataClrMask;
|
||||
sio_hw->gpio_set = _data16.msb;
|
||||
sio_hw->gpio_set = _wrPinMask;
|
||||
|
||||
sio_hw->gpio_clr = _dataClrMask;
|
||||
sio_hw->gpio_set = _data16.lsb;
|
||||
sio_hw->gpio_set = _wrPinMask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_RPiPicoPAR8::writePixels(uint16_t *data, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
_data16.value = *data++;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_RPiPicoPAR8::writeC8D8(uint8_t c, uint8_t d)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
WRITE(d);
|
||||
}
|
||||
|
||||
void Arduino_RPiPicoPAR8::writeC8D16(uint8_t c, uint16_t d)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
_data16.value = d;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
|
||||
void Arduino_RPiPicoPAR8::writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
_data16.value = d1;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
|
||||
_data16.value = d2;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
|
||||
void Arduino_RPiPicoPAR8::writeBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
WRITE(*data++);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_RPiPicoPAR8::writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
_data16.value = idx[*data++];
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_RPiPicoPAR8::writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
_data16.value = idx[*data++];
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_RPiPicoPAR8::WRITE(uint8_t d)
|
||||
{
|
||||
sio_hw->gpio_clr = _dataClrMask;
|
||||
sio_hw->gpio_set = d;
|
||||
sio_hw->gpio_set = _wrPinMask;
|
||||
}
|
||||
|
||||
/******** low level bit twiddling **********/
|
||||
|
||||
GFX_INLINE void Arduino_RPiPicoPAR8::DC_HIGH(void)
|
||||
{
|
||||
sio_hw->gpio_set = _dcPinMask;
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_RPiPicoPAR8::DC_LOW(void)
|
||||
{
|
||||
sio_hw->gpio_clr = _dcPinMask;
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_RPiPicoPAR8::CS_HIGH(void)
|
||||
{
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
sio_hw->gpio_set = _csPinMask;
|
||||
}
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_RPiPicoPAR8::CS_LOW(void)
|
||||
{
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
sio_hw->gpio_clr = _csPinMask;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // #if defined(TARGET_RP2040) || defined(PICO_RP2350)
|
||||
@@ -0,0 +1,50 @@
|
||||
#if defined(TARGET_RP2040) || defined(PICO_RP2350)
|
||||
|
||||
#ifndef _ARDUINO_RPIPICOPAR8_H_
|
||||
#define _ARDUINO_RPIPICOPAR8_H_
|
||||
|
||||
#include "Arduino_DataBus.h"
|
||||
|
||||
class Arduino_RPiPicoPAR8 : public Arduino_DataBus
|
||||
{
|
||||
public:
|
||||
Arduino_RPiPicoPAR8(int8_t dc, int8_t cs, int8_t wr, int8_t rd); // Constructor
|
||||
|
||||
bool begin(int32_t speed = GFX_NOT_DEFINED, int8_t dataMode = GFX_NOT_DEFINED) override;
|
||||
void beginWrite() override;
|
||||
void endWrite() override;
|
||||
void writeCommand(uint8_t) override;
|
||||
void writeCommand16(uint16_t) override;
|
||||
void writeCommandBytes(uint8_t *data, uint32_t len) override;
|
||||
void write(uint8_t) override;
|
||||
void write16(uint16_t) override;
|
||||
void writeRepeat(uint16_t p, uint32_t len) override;
|
||||
void writePixels(uint16_t *data, uint32_t len) override;
|
||||
|
||||
void writeC8D8(uint8_t c, uint8_t d) override;
|
||||
void writeC8D16(uint8_t c, uint16_t d) override;
|
||||
void writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2) override;
|
||||
void writeBytes(uint8_t *data, uint32_t len) override;
|
||||
|
||||
void writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len) override;
|
||||
void writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len) override;
|
||||
|
||||
protected:
|
||||
private:
|
||||
GFX_INLINE void WRITE(uint8_t d);
|
||||
GFX_INLINE void DC_HIGH(void);
|
||||
GFX_INLINE void DC_LOW(void);
|
||||
GFX_INLINE void CS_HIGH(void);
|
||||
GFX_INLINE void CS_LOW(void);
|
||||
|
||||
int8_t _dc, _cs, _wr, _rd;
|
||||
|
||||
uint32_t _dcPinMask; ///< Bitmask
|
||||
uint32_t _csPinMask; ///< Bitmask
|
||||
uint32_t _wrPinMask; ///< Bitmask
|
||||
uint32_t _dataClrMask;
|
||||
};
|
||||
|
||||
#endif // _ARDUINO_RPIPICOPAR8_H_
|
||||
|
||||
#endif // #if defined(TARGET_RP2040) || defined(PICO_RP2350)
|
||||
@@ -0,0 +1,231 @@
|
||||
#if defined(TARGET_RP2040) || defined(PICO_RP2350)
|
||||
|
||||
#include "Arduino_DataBus.h"
|
||||
#include "Arduino_RPiPicoSPI.h"
|
||||
|
||||
Arduino_RPiPicoSPI::Arduino_RPiPicoSPI(int8_t dc /* = GFX_NOT_DEFINED */, int8_t cs /* = GFX_NOT_DEFINED */, int8_t sck /* = 18 */, int8_t mosi /* = 19 */, int8_t miso /* = 16 */, spi_inst_t *spi /* = spi0 */)
|
||||
: _dc(dc), _cs(cs), _sck(sck), _mosi(mosi), _miso(miso), _spi(spi)
|
||||
{
|
||||
}
|
||||
|
||||
bool Arduino_RPiPicoSPI::begin(int32_t speed /* = 0 */, int8_t dataMode /* = GFX_NOT_DEFINED */)
|
||||
{
|
||||
// set SPI parameters
|
||||
_speed = (speed == GFX_NOT_DEFINED) ? SPI_DEFAULT_FREQ : speed;
|
||||
_dataMode = (dataMode != GFX_NOT_DEFINED) ? dataMode : SPI_MODE0;
|
||||
_spis = SPISettings(_speed, _bitOrder, _dataMode);
|
||||
|
||||
// set pin mode
|
||||
pinMode(_dc, OUTPUT);
|
||||
digitalWrite(_dc, HIGH); // Data mode
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
pinMode(_cs, OUTPUT);
|
||||
digitalWrite(_cs, HIGH); // disable chip select
|
||||
}
|
||||
|
||||
gpio_set_function(_miso, GPIO_FUNC_SPI);
|
||||
gpio_set_function(_sck, GPIO_FUNC_SPI);
|
||||
gpio_set_function(_mosi, GPIO_FUNC_SPI);
|
||||
|
||||
// set fastIO variables
|
||||
_dcPinMask = digitalPinToBitMask(_dc);
|
||||
_dcPortSet = (PORTreg_t)&sio_hw->gpio_set;
|
||||
_dcPortClr = (PORTreg_t)&sio_hw->gpio_clr;
|
||||
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
_csPinMask = digitalPinToBitMask(_cs);
|
||||
_csPortSet = (PORTreg_t)&sio_hw->gpio_set;
|
||||
_csPortClr = (PORTreg_t)&sio_hw->gpio_clr;
|
||||
}
|
||||
|
||||
spi_init(_spi, _spis.getClockFreq());
|
||||
spi_set_format(_spi, 8, SPI_CPOL_0, SPI_CPHA_0, SPI_MSB_FIRST);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Arduino_RPiPicoSPI::beginWrite()
|
||||
{
|
||||
DC_HIGH();
|
||||
CS_LOW();
|
||||
}
|
||||
|
||||
void Arduino_RPiPicoSPI::endWrite()
|
||||
{
|
||||
CS_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_RPiPicoSPI::writeCommand(uint8_t c)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_RPiPicoSPI::writeCommand16(uint16_t c)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE16(c);
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_RPiPicoSPI::writeCommandBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
while (len--)
|
||||
{
|
||||
WRITE(*data++);
|
||||
}
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_RPiPicoSPI::write(uint8_t d)
|
||||
{
|
||||
WRITE(d);
|
||||
}
|
||||
|
||||
void Arduino_RPiPicoSPI::write16(uint16_t d)
|
||||
{
|
||||
WRITE16(d);
|
||||
}
|
||||
|
||||
void Arduino_RPiPicoSPI::writeRepeat(uint16_t p, uint32_t len)
|
||||
{
|
||||
MSB_16_SET(p, p);
|
||||
uint32_t bufLen = (len < RPIPICOSPI_MAX_PIXELS_AT_ONCE) ? len : RPIPICOSPI_MAX_PIXELS_AT_ONCE;
|
||||
uint32_t xferLen;
|
||||
for (uint32_t i = 0; i < bufLen; i++)
|
||||
{
|
||||
_buffer16[i] = p;
|
||||
}
|
||||
|
||||
while (len)
|
||||
{
|
||||
xferLen = (bufLen < len) ? bufLen : len;
|
||||
WRITEBUF(_buffer, xferLen * 2);
|
||||
len -= xferLen;
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_RPiPicoSPI::writePixels(uint16_t *data, uint32_t len)
|
||||
{
|
||||
uint32_t xferLen;
|
||||
uint8_t *p;
|
||||
union
|
||||
{
|
||||
uint16_t val;
|
||||
struct
|
||||
{
|
||||
uint8_t lsb;
|
||||
uint8_t msb;
|
||||
};
|
||||
} t;
|
||||
while (len)
|
||||
{
|
||||
xferLen = (len < RPIPICOSPI_MAX_PIXELS_AT_ONCE) ? len : RPIPICOSPI_MAX_PIXELS_AT_ONCE;
|
||||
p = _buffer;
|
||||
for (uint32_t i = 0; i < xferLen; i++)
|
||||
{
|
||||
t.val = *data++;
|
||||
*p++ = t.msb;
|
||||
*p++ = t.lsb;
|
||||
}
|
||||
len -= xferLen;
|
||||
|
||||
xferLen += xferLen; // uint16_t to uint8_t, double length
|
||||
WRITEBUF(_buffer, xferLen);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_RPiPicoSPI::writeC8D8(uint8_t c, uint8_t d)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
WRITE(d);
|
||||
}
|
||||
|
||||
void Arduino_RPiPicoSPI::writeC8D16(uint8_t c, uint16_t d)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
WRITE16(d);
|
||||
}
|
||||
|
||||
void Arduino_RPiPicoSPI::writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
WRITE16(d1);
|
||||
WRITE16(d2);
|
||||
}
|
||||
|
||||
void Arduino_RPiPicoSPI::writeBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
WRITEBUF(data, len);
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_RPiPicoSPI::WRITE(uint8_t d)
|
||||
{
|
||||
spi_write_blocking(_spi, (const uint8_t *)&d, 1);
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_RPiPicoSPI::WRITE16(uint16_t d)
|
||||
{
|
||||
MSB_16_SET(d, d);
|
||||
spi_write_blocking(_spi, (const uint8_t *)&d, 2);
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_RPiPicoSPI::WRITEBUF(uint8_t *buf, size_t count)
|
||||
{
|
||||
spi_write_blocking(_spi, (const uint8_t *)buf, count);
|
||||
}
|
||||
|
||||
/******** low level bit twiddling **********/
|
||||
|
||||
GFX_INLINE void Arduino_RPiPicoSPI::DC_HIGH(void)
|
||||
{
|
||||
*_dcPortSet = _dcPinMask;
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_RPiPicoSPI::DC_LOW(void)
|
||||
{
|
||||
*_dcPortClr = _dcPinMask;
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_RPiPicoSPI::CS_HIGH(void)
|
||||
{
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
*_csPortSet = _csPinMask;
|
||||
}
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_RPiPicoSPI::CS_LOW(void)
|
||||
{
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
*_csPortClr = _csPinMask;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // #if defined(TARGET_RP2040) || defined(PICO_RP2350)
|
||||
@@ -0,0 +1,71 @@
|
||||
#if defined(TARGET_RP2040) || defined(PICO_RP2350)
|
||||
|
||||
#ifndef _ARDUINO_RPIPICOSPI_H_
|
||||
#define _ARDUINO_RPIPICOSPI_H_
|
||||
|
||||
#include <api/HardwareSPI.h>
|
||||
#include <hardware/spi.h>
|
||||
|
||||
#include "Arduino_DataBus.h"
|
||||
|
||||
#ifndef RPIPICOSPI_MAX_PIXELS_AT_ONCE
|
||||
#define RPIPICOSPI_MAX_PIXELS_AT_ONCE 32
|
||||
#endif
|
||||
|
||||
class Arduino_RPiPicoSPI : public Arduino_DataBus
|
||||
{
|
||||
public:
|
||||
Arduino_RPiPicoSPI(int8_t dc = GFX_NOT_DEFINED, int8_t cs = GFX_NOT_DEFINED, int8_t sck = 18, int8_t mosi = 19, int8_t miso = 16, spi_inst_t *spi = spi0); // Constructor
|
||||
|
||||
bool begin(int32_t speed = GFX_NOT_DEFINED, int8_t dataMode = GFX_NOT_DEFINED) override;
|
||||
void beginWrite() override;
|
||||
void endWrite() override;
|
||||
void writeCommand(uint8_t) override;
|
||||
void writeCommand16(uint16_t) override;
|
||||
void writeCommandBytes(uint8_t *data, uint32_t len) override;
|
||||
void write(uint8_t) override;
|
||||
void write16(uint16_t) override;
|
||||
void writeRepeat(uint16_t p, uint32_t len) override;
|
||||
void writePixels(uint16_t *data, uint32_t len) override;
|
||||
|
||||
void writeC8D8(uint8_t c, uint8_t d) override;
|
||||
void writeC8D16(uint8_t c, uint16_t d) override;
|
||||
void writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2) override;
|
||||
void writeBytes(uint8_t *data, uint32_t len) override;
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
GFX_INLINE void WRITE(uint8_t d);
|
||||
GFX_INLINE void WRITE16(uint16_t d);
|
||||
GFX_INLINE void WRITEBUF(uint8_t *buf, size_t count);
|
||||
GFX_INLINE void DC_HIGH(void);
|
||||
GFX_INLINE void DC_LOW(void);
|
||||
GFX_INLINE void CS_HIGH(void);
|
||||
GFX_INLINE void CS_LOW(void);
|
||||
|
||||
int8_t _dc, _cs;
|
||||
int8_t _sck, _mosi, _miso;
|
||||
int32_t _speed;
|
||||
|
||||
PORTreg_t _dcPortSet; ///< PORT register for data/command SET
|
||||
PORTreg_t _dcPortClr; ///< PORT register for data/command CLEAR
|
||||
PORTreg_t _csPortSet; ///< PORT register for chip select SET
|
||||
PORTreg_t _csPortClr; ///< PORT register for chip select CLEAR
|
||||
uint32_t _dcPinMask; ///< Bitmask for data/command
|
||||
uint32_t _csPinMask; ///< Bitmask for chip select
|
||||
|
||||
spi_inst_t *_spi;
|
||||
SPISettings _spis;
|
||||
BitOrder _bitOrder = MSBFIRST;
|
||||
|
||||
union
|
||||
{
|
||||
uint8_t _buffer[RPIPICOSPI_MAX_PIXELS_AT_ONCE * 2] = {0};
|
||||
uint16_t _buffer16[RPIPICOSPI_MAX_PIXELS_AT_ONCE];
|
||||
uint32_t _buffer32[RPIPICOSPI_MAX_PIXELS_AT_ONCE / 2];
|
||||
};
|
||||
};
|
||||
|
||||
#endif // _ARDUINO_RPIPICOSPI_H_
|
||||
#endif // #if defined(TARGET_RP2040) || defined(PICO_RP2350)
|
||||
@@ -0,0 +1,347 @@
|
||||
#ifdef RTL8722DM
|
||||
|
||||
#include "Arduino_DataBus.h"
|
||||
#include "Arduino_RTLPAR8.h"
|
||||
|
||||
Arduino_RTLPAR8::Arduino_RTLPAR8(
|
||||
int8_t dc, int8_t cs, int8_t wr, int8_t rd,
|
||||
int8_t d0, int8_t d1, int8_t d2, int8_t d3, int8_t d4, int8_t d5, int8_t d6, int8_t d7)
|
||||
: _dc(dc), _cs(cs), _wr(wr), _rd(rd),
|
||||
_d0(d0), _d1(d1), _d2(d2), _d3(d3), _d4(d4), _d5(d5), _d6(d6), _d7(d7)
|
||||
{
|
||||
}
|
||||
|
||||
bool Arduino_RTLPAR8::begin(int32_t, int8_t)
|
||||
{
|
||||
pinMode(_dc, OUTPUT);
|
||||
digitalWrite(_dc, HIGH); // Data mode
|
||||
_dcPort = (PORTreg_t)portOutputRegister(digitalPinToPort(_dc));
|
||||
_dcPinMaskSet = digitalPinToBitMask(_dc);
|
||||
_dcPinMaskClr = ~_dcPinMaskSet;
|
||||
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
pinMode(_cs, OUTPUT);
|
||||
digitalWrite(_cs, HIGH); // disable chip select
|
||||
_csPort = (PORTreg_t)portOutputRegister(digitalPinToPort(_cs));
|
||||
_csPinMaskSet = digitalPinToBitMask(_cs);
|
||||
}
|
||||
_csPinMaskClr = ~_csPinMaskSet;
|
||||
|
||||
pinMode(_wr, OUTPUT);
|
||||
digitalWrite(_wr, HIGH); // Set write strobe high (inactive)
|
||||
_wrPort = (PORTreg_t)portOutputRegister(digitalPinToPort(_wr));
|
||||
_wrPinMaskSet = digitalPinToBitMask(_wr);
|
||||
_wrPinMaskClr = ~_wrPinMaskSet;
|
||||
|
||||
if (_rd != GFX_NOT_DEFINED)
|
||||
{
|
||||
pinMode(_rd, OUTPUT);
|
||||
digitalWrite(_rd, HIGH);
|
||||
}
|
||||
|
||||
// TODO: check pin in same port
|
||||
pinMode(_d0, OUTPUT);
|
||||
digitalWrite(_d0, HIGH);
|
||||
pinMode(_d1, OUTPUT);
|
||||
digitalWrite(_d1, HIGH);
|
||||
pinMode(_d2, OUTPUT);
|
||||
digitalWrite(_d2, HIGH);
|
||||
pinMode(_d3, OUTPUT);
|
||||
digitalWrite(_d3, HIGH);
|
||||
pinMode(_d4, OUTPUT);
|
||||
digitalWrite(_d4, HIGH);
|
||||
pinMode(_d5, OUTPUT);
|
||||
digitalWrite(_d5, HIGH);
|
||||
pinMode(_d6, OUTPUT);
|
||||
digitalWrite(_d6, HIGH);
|
||||
pinMode(_d7, OUTPUT);
|
||||
digitalWrite(_d7, HIGH);
|
||||
|
||||
// INIT 8-bit mask
|
||||
_dataPort = (PORTreg_t)portOutputRegister(digitalPinToPort(_d0));
|
||||
for (int32_t c = 0; c < 256; c++)
|
||||
{
|
||||
_xset_mask[c] = 0;
|
||||
if (c & 0x01)
|
||||
{
|
||||
_xset_mask[c] |= digitalPinToBitMask(_d0);
|
||||
}
|
||||
if (c & 0x02)
|
||||
{
|
||||
_xset_mask[c] |= digitalPinToBitMask(_d1);
|
||||
}
|
||||
if (c & 0x04)
|
||||
{
|
||||
_xset_mask[c] |= digitalPinToBitMask(_d2);
|
||||
}
|
||||
if (c & 0x08)
|
||||
{
|
||||
_xset_mask[c] |= digitalPinToBitMask(_d3);
|
||||
}
|
||||
if (c & 0x10)
|
||||
{
|
||||
_xset_mask[c] |= digitalPinToBitMask(_d4);
|
||||
}
|
||||
if (c & 0x20)
|
||||
{
|
||||
_xset_mask[c] |= digitalPinToBitMask(_d5);
|
||||
}
|
||||
if (c & 0x40)
|
||||
{
|
||||
_xset_mask[c] |= digitalPinToBitMask(_d6);
|
||||
}
|
||||
if (c & 0x80)
|
||||
{
|
||||
_xset_mask[c] |= digitalPinToBitMask(_d7);
|
||||
}
|
||||
}
|
||||
_dataPinMaskClr = ~_xset_mask[255];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Arduino_RTLPAR8::beginWrite()
|
||||
{
|
||||
DC_HIGH();
|
||||
CS_LOW();
|
||||
}
|
||||
|
||||
void Arduino_RTLPAR8::endWrite()
|
||||
{
|
||||
CS_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_RTLPAR8::writeCommand(uint8_t c)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_RTLPAR8::writeCommand16(uint16_t c)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
_data16.value = c;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_RTLPAR8::writeCommandBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
while (len--)
|
||||
{
|
||||
WRITE(*data++);
|
||||
}
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_RTLPAR8::write(uint8_t d)
|
||||
{
|
||||
WRITE(d);
|
||||
}
|
||||
|
||||
void Arduino_RTLPAR8::write16(uint16_t d)
|
||||
{
|
||||
_data16.value = d;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
|
||||
void Arduino_RTLPAR8::writeRepeat(uint16_t p, uint32_t len)
|
||||
{
|
||||
uint32_t dataMaskBase = *_dataPort & _dataPinMaskClr;
|
||||
uint32_t wrMaskBase = *_wrPort & _wrPinMaskClr;
|
||||
uint32_t wrMaskSet = wrMaskBase | _wrPinMaskSet;
|
||||
_data16.value = p;
|
||||
if (_data16.msb == _data16.lsb)
|
||||
{
|
||||
*_dataPort = dataMaskBase | _xset_mask[_data16.msb];
|
||||
while (len--)
|
||||
{
|
||||
*_wrPort = wrMaskBase;
|
||||
*_wrPort = wrMaskSet;
|
||||
*_wrPort = wrMaskBase;
|
||||
*_wrPort = wrMaskSet;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t hiMask = _xset_mask[_data16.msb];
|
||||
uint32_t loMask = _xset_mask[_data16.lsb];
|
||||
while (len--)
|
||||
{
|
||||
*_dataPort = dataMaskBase | hiMask;
|
||||
*_wrPort = wrMaskBase;
|
||||
*_wrPort = wrMaskSet;
|
||||
|
||||
*_dataPort = dataMaskBase | loMask;
|
||||
*_wrPort = wrMaskBase;
|
||||
*_wrPort = wrMaskSet;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_RTLPAR8::writePixels(uint16_t *data, uint32_t len)
|
||||
{
|
||||
uint32_t dataMaskBase = *_dataPort & _dataPinMaskClr;
|
||||
uint32_t wrMaskBase = *_wrPort & _wrPinMaskClr;
|
||||
uint32_t wrMaskSet = wrMaskBase | _wrPinMaskSet;
|
||||
while (len--)
|
||||
{
|
||||
_data16.value = *(data++);
|
||||
uint32_t hiMask = _xset_mask[_data16.msb];
|
||||
uint32_t loMask = _xset_mask[_data16.lsb];
|
||||
*_dataPort = dataMaskBase | hiMask;
|
||||
*_wrPort = wrMaskBase;
|
||||
*_wrPort = wrMaskSet;
|
||||
|
||||
*_dataPort = dataMaskBase | loMask;
|
||||
*_wrPort = wrMaskBase;
|
||||
*_wrPort = wrMaskSet;
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_RTLPAR8::writeC8D8(uint8_t c, uint8_t d)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
WRITE(d);
|
||||
}
|
||||
|
||||
void Arduino_RTLPAR8::writeC8D16(uint8_t c, uint16_t d)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
_data16.value = d;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
|
||||
void Arduino_RTLPAR8::writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
_data16.value = d1;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
_data16.value = d2;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
|
||||
void Arduino_RTLPAR8::writeBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
WRITE(*data++);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_RTLPAR8::writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len)
|
||||
{
|
||||
uint32_t dataMaskBase = *_dataPort & _dataPinMaskClr;
|
||||
uint32_t wrMaskBase = *_wrPort & _wrPinMaskClr;
|
||||
uint32_t wrMaskSet = wrMaskBase | _wrPinMaskSet;
|
||||
while (len--)
|
||||
{
|
||||
_data16.value = idx[*data++];
|
||||
|
||||
*_dataPort = dataMaskBase | _xset_mask[_data16.msb];
|
||||
*_wrPort = wrMaskBase;
|
||||
*_wrPort = wrMaskSet;
|
||||
|
||||
*_dataPort = dataMaskBase | _xset_mask[_data16.lsb];
|
||||
*_wrPort = wrMaskBase;
|
||||
*_wrPort = wrMaskSet;
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_RTLPAR8::writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len)
|
||||
{
|
||||
uint32_t dataMaskBase = *_dataPort & _dataPinMaskClr;
|
||||
uint32_t wrMaskBase = *_wrPort & _wrPinMaskClr;
|
||||
uint32_t wrMaskSet = wrMaskBase | _wrPinMaskSet;
|
||||
while (len--)
|
||||
{
|
||||
_data16.value = idx[*data++];
|
||||
uint32_t hiMask = _xset_mask[_data16.msb];
|
||||
uint32_t loMask = _xset_mask[_data16.lsb];
|
||||
|
||||
*_dataPort = dataMaskBase | hiMask;
|
||||
*_wrPort = wrMaskBase;
|
||||
*_wrPort = wrMaskSet;
|
||||
|
||||
*_dataPort = dataMaskBase | loMask;
|
||||
*_wrPort = wrMaskBase;
|
||||
*_wrPort = wrMaskSet;
|
||||
|
||||
*_dataPort = dataMaskBase | hiMask;
|
||||
*_wrPort = wrMaskBase;
|
||||
*_wrPort = wrMaskSet;
|
||||
|
||||
*_dataPort = dataMaskBase | loMask;
|
||||
*_wrPort = wrMaskBase;
|
||||
*_wrPort = wrMaskSet;
|
||||
}
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_RTLPAR8::WRITE(uint8_t d)
|
||||
{
|
||||
uint32_t dataMaskBase = *_dataPort & _dataPinMaskClr;
|
||||
uint32_t wrMaskBase = *_wrPort & _wrPinMaskClr;
|
||||
*_dataPort = dataMaskBase | _xset_mask[d];
|
||||
|
||||
*_wrPort = wrMaskBase;
|
||||
*_wrPort = wrMaskBase | _wrPinMaskSet;
|
||||
}
|
||||
|
||||
/******** low level bit twiddling **********/
|
||||
|
||||
GFX_INLINE void Arduino_RTLPAR8::DC_HIGH(void)
|
||||
{
|
||||
*_dcPort |= _dcPinMaskSet;
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_RTLPAR8::DC_LOW(void)
|
||||
{
|
||||
*_dcPort &= _dcPinMaskClr;
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_RTLPAR8::CS_HIGH(void)
|
||||
{
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
*_csPort |= _csPinMaskSet;
|
||||
}
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_RTLPAR8::CS_LOW(void)
|
||||
{
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
*_csPort &= _csPinMaskClr;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // #ifdef RTL8722DM
|
||||
@@ -0,0 +1,66 @@
|
||||
#ifdef RTL8722DM
|
||||
|
||||
#ifndef _ARDUINO_RTLPAR8_H_
|
||||
#define _ARDUINO_RTLPAR8_H_
|
||||
|
||||
#include "Arduino_DataBus.h"
|
||||
|
||||
class Arduino_RTLPAR8 : public Arduino_DataBus
|
||||
{
|
||||
public:
|
||||
Arduino_RTLPAR8(
|
||||
int8_t dc, int8_t cs, int8_t wr, int8_t rd,
|
||||
int8_t d0, int8_t d1, int8_t d2, int8_t d3, int8_t d4, int8_t d5, int8_t d6, int8_t d7); // Constructor
|
||||
|
||||
bool begin(int32_t speed = GFX_NOT_DEFINED, int8_t dataMode = GFX_NOT_DEFINED) override;
|
||||
void beginWrite() override;
|
||||
void endWrite() override;
|
||||
void writeCommand(uint8_t) override;
|
||||
void writeCommand16(uint16_t) override;
|
||||
void writeCommandBytes(uint8_t *data, uint32_t len) override;
|
||||
void write(uint8_t) override;
|
||||
void write16(uint16_t) override;
|
||||
void writeRepeat(uint16_t p, uint32_t len) override;
|
||||
void writePixels(uint16_t *data, uint32_t len) override;
|
||||
|
||||
void writeC8D8(uint8_t c, uint8_t d) override;
|
||||
void writeC8D16(uint8_t c, uint16_t d) override;
|
||||
void writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2) override;
|
||||
void writeBytes(uint8_t *data, uint32_t len) override;
|
||||
|
||||
void writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len) override;
|
||||
void writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len) override;
|
||||
|
||||
protected:
|
||||
private:
|
||||
GFX_INLINE void WRITE(uint8_t d);
|
||||
GFX_INLINE void DC_HIGH(void);
|
||||
GFX_INLINE void DC_LOW(void);
|
||||
GFX_INLINE void CS_HIGH(void);
|
||||
GFX_INLINE void CS_LOW(void);
|
||||
|
||||
int8_t _dc, _cs, _wr, _rd;
|
||||
int8_t _d0, _d1, _d2, _d3, _d4, _d5, _d6, _d7;
|
||||
|
||||
PORTreg_t _dcPort; ///< PORT register for data/command
|
||||
ARDUINOGFX_PORT_t _dcPinMaskSet; ///< Bitmask for data/command SET (OR)
|
||||
ARDUINOGFX_PORT_t _dcPinMaskClr; ///< Bitmask for data/command CLEAR (AND)
|
||||
|
||||
PORTreg_t _csPort; ///< PORT register for data/command
|
||||
ARDUINOGFX_PORT_t _csPinMaskSet; ///< Bitmask for data/command SET (OR)
|
||||
ARDUINOGFX_PORT_t _csPinMaskClr; ///< Bitmask for data/command CLEAR (AND)
|
||||
|
||||
PORTreg_t _wrPort; ///< PORT register for data/command
|
||||
ARDUINOGFX_PORT_t _wrPinMaskSet; ///< Bitmask for data/command SET (OR)
|
||||
ARDUINOGFX_PORT_t _wrPinMaskClr; ///< Bitmask for data/command CLEAR (AND)
|
||||
|
||||
PORTreg_t _dataPort; ///< PORT register for data/command
|
||||
ARDUINOGFX_PORT_t _dataPinMaskClr; ///< Bitmask for data/command CLEAR (AND)
|
||||
|
||||
// Lookup table for ESP32 parallel bus interface uses 1kbyte RAM,
|
||||
uint32_t _xset_mask[256];
|
||||
};
|
||||
|
||||
#endif // _ARDUINO_RTLPAR8_H_
|
||||
|
||||
#endif // #ifdef RTL8722DM
|
||||
@@ -0,0 +1,257 @@
|
||||
#ifdef ARDUINO_ARCH_STM32
|
||||
|
||||
#include "Arduino_STM32PAR8.h"
|
||||
|
||||
Arduino_STM32PAR8::Arduino_STM32PAR8(int8_t dc, int8_t cs, int8_t wr, int8_t rd, GPIO_TypeDef *port)
|
||||
: _dc(dc), _cs(cs), _wr(wr), _rd(rd), _port(port)
|
||||
{
|
||||
}
|
||||
|
||||
bool Arduino_STM32PAR8::begin(int32_t, int8_t)
|
||||
{
|
||||
set_GPIO_Port_Clock(STM_PORT(_port)); // Enable data port
|
||||
pinMode(_dc, OUTPUT);
|
||||
digitalWrite(_dc, HIGH); // Data mode
|
||||
_dcPORT = digitalPinToPort(_dc);
|
||||
_dcPinMaskSet = digitalPinToBitMask(_dc);
|
||||
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
pinMode(_cs, OUTPUT);
|
||||
digitalWrite(_cs, HIGH); // Disable chip select
|
||||
_csPinMaskSet = digitalPinToBitMask(_cs);
|
||||
_csPORT = digitalPinToPort(_cs);
|
||||
}
|
||||
|
||||
pinMode(_wr, OUTPUT);
|
||||
digitalWrite(_wr, HIGH); // Set write strobe high (inactive)
|
||||
_wrPort = (PORTreg_t)portOutputRegister(digitalPinToPort(_wr));
|
||||
_wrPORT = digitalPinToPort(_wr);
|
||||
_wrPinMaskSet = digitalPinToBitMask(_wr);
|
||||
_wrPinMaskClr = ~_wrPinMaskSet;
|
||||
|
||||
if (_rd != GFX_NOT_DEFINED)
|
||||
{
|
||||
pinMode(_rd, OUTPUT);
|
||||
digitalWrite(_rd, HIGH); // Disable RD
|
||||
_rdPinMaskSet = digitalPinToBitMask(_rd);
|
||||
}
|
||||
else
|
||||
{
|
||||
_rdPinMaskSet = 0;
|
||||
}
|
||||
|
||||
*(portModeRegister(_port)) = 0x33333333; // Set data port to output at max speed
|
||||
_port->BSRR = 0xFF << 16; // Clear data port
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Arduino_STM32PAR8::beginWrite()
|
||||
{
|
||||
DC_HIGH();
|
||||
CS_LOW();
|
||||
}
|
||||
|
||||
void Arduino_STM32PAR8::endWrite()
|
||||
{
|
||||
CS_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_STM32PAR8::writeCommand(uint8_t c)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_STM32PAR8::writeCommand16(uint16_t c)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
_data16.value = c;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_STM32PAR8::writeCommandBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
while (len--)
|
||||
{
|
||||
WRITE(*data++);
|
||||
}
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_STM32PAR8::write(uint8_t d)
|
||||
{
|
||||
WRITE(d);
|
||||
}
|
||||
|
||||
void Arduino_STM32PAR8::write16(uint16_t d)
|
||||
{
|
||||
_data16.value = d;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
|
||||
void Arduino_STM32PAR8::writeRepeat(uint16_t p, uint32_t len)
|
||||
{
|
||||
uint8_t wrMaskBase = *_wrPort & _wrPinMaskClr;
|
||||
uint8_t wrMaskSet = wrMaskBase | _wrPinMaskSet;
|
||||
uint32_t wrMASKCLR = _wrPinMaskSet << 16;
|
||||
_data16.value = p;
|
||||
if (_data16.msb == _data16.lsb)
|
||||
{
|
||||
_port->BSRR = 0xFF << 16;
|
||||
_port->BSRR = (_data16.msb) & 0xFF;
|
||||
while (len--)
|
||||
{
|
||||
*_wrPort = wrMaskBase; // For some reason in this case it's faster then BSRR
|
||||
*_wrPort = wrMaskSet;
|
||||
*_wrPort = wrMaskBase;
|
||||
*_wrPort = wrMaskSet;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
_port->BSRR = 0xFF << 16;
|
||||
_port->BSRR = (_data16.msb);
|
||||
*_wrPort = wrMaskBase;
|
||||
*_wrPort = wrMaskSet;
|
||||
|
||||
_port->BSRR = 0xFF << 16;
|
||||
_port->BSRR = (_data16.lsb);
|
||||
*_wrPort = wrMaskBase;
|
||||
*_wrPort = wrMaskSet;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_STM32PAR8::writePixels(uint16_t *data, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
_data16.value = *data++;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_STM32PAR8::writeC8D8(uint8_t c, uint8_t d)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
WRITE(d);
|
||||
}
|
||||
|
||||
void Arduino_STM32PAR8::writeC8D16(uint8_t c, uint16_t d)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
_data16.value = d;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
|
||||
void Arduino_STM32PAR8::writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
|
||||
_data16.value = d1;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
|
||||
_data16.value = d2;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
|
||||
void Arduino_STM32PAR8::writeBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
WRITE(*data++);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_STM32PAR8::writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
_data16.value = idx[*data++];
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_STM32PAR8::writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
_data16.value = idx[*data++];
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_STM32PAR8::WRITE(uint8_t d)
|
||||
{
|
||||
_port->BSRR = 0xFF << 16;
|
||||
_port->BSRR = (d)&0xFF;
|
||||
_wrPORT->BSRR = _wrPinMaskSet << 16; // Set WR LOW
|
||||
_wrPORT->BSRR = _wrPinMaskSet; // Set WR HIGH
|
||||
}
|
||||
|
||||
/******** low level bit twiddling **********/
|
||||
|
||||
GFX_INLINE void Arduino_STM32PAR8::DC_HIGH(void)
|
||||
{
|
||||
_dcPORT->BSRR = _dcPinMaskSet;
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_STM32PAR8::DC_LOW(void)
|
||||
{
|
||||
_dcPORT->BSRR = _dcPinMaskSet << 16;
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_STM32PAR8::CS_HIGH(void)
|
||||
{
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
_csPORT->BSRR = _csPinMaskSet;
|
||||
}
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_STM32PAR8::CS_LOW(void)
|
||||
{
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
_csPORT->BSRR = _csPinMaskSet << 16;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // #ifdef ARDUINO_ARCH_STM32
|
||||
@@ -0,0 +1,57 @@
|
||||
#ifdef ARDUINO_ARCH_STM32
|
||||
|
||||
#ifndef _ARDUINO_STM32PAR8_H_
|
||||
#define _ARDUINO_STM32PAR8_H_
|
||||
|
||||
#include "Arduino_DataBus.h"
|
||||
|
||||
class Arduino_STM32PAR8 : public Arduino_DataBus
|
||||
{
|
||||
public:
|
||||
Arduino_STM32PAR8(int8_t dc, int8_t cs, int8_t wr, int8_t rd, GPIO_TypeDef* port); // Constructor
|
||||
|
||||
bool begin(int32_t speed = GFX_NOT_DEFINED, int8_t dataMode = GFX_NOT_DEFINED) override;
|
||||
void beginWrite() override;
|
||||
void endWrite() override;
|
||||
void writeCommand(uint8_t) override;
|
||||
void writeCommand16(uint16_t) override;
|
||||
void writeCommandBytes(uint8_t *data, uint32_t len) override;
|
||||
void write(uint8_t) override;
|
||||
void write16(uint16_t) override;
|
||||
void writeRepeat(uint16_t p, uint32_t len) override;
|
||||
void writePixels(uint16_t *data, uint32_t len) override;
|
||||
|
||||
void writeC8D8(uint8_t c, uint8_t d) override;
|
||||
void writeC8D16(uint8_t c, uint16_t d) override;
|
||||
void writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2) override;
|
||||
void writeBytes(uint8_t *data, uint32_t len) override;
|
||||
|
||||
void writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len) override;
|
||||
void writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len) override;
|
||||
|
||||
protected:
|
||||
private:
|
||||
GFX_INLINE void WRITE(uint8_t d);
|
||||
GFX_INLINE void DC_HIGH(void);
|
||||
GFX_INLINE void DC_LOW(void);
|
||||
GFX_INLINE void CS_HIGH(void);
|
||||
GFX_INLINE void CS_LOW(void);
|
||||
|
||||
int8_t _dc, _cs, _wr, _rd;
|
||||
GPIO_TypeDef* _port;
|
||||
GPIO_TypeDef* _dcPORT;
|
||||
GPIO_TypeDef* _csPORT;
|
||||
GPIO_TypeDef* _wrPORT;
|
||||
GPIO_TypeDef* _rdPORT;
|
||||
|
||||
ARDUINOGFX_PORT_t _dcPinMaskSet; ///< Bitmask for data/command SET (OR)
|
||||
ARDUINOGFX_PORT_t _csPinMaskSet; ///< Bitmask for data/command SET (OR)
|
||||
PORTreg_t _wrPort; ///< PORT register for data/command
|
||||
ARDUINOGFX_PORT_t _wrPinMaskSet; ///< Bitmask for data/command SET (OR)
|
||||
ARDUINOGFX_PORT_t _wrPinMaskClr; ///< Bitmask for data/command CLEAR (AND)
|
||||
ARDUINOGFX_PORT_t _rdPinMaskSet; ///< Bitmask for data/command SET (OR)
|
||||
};
|
||||
|
||||
#endif // _ARDUINO_STM32PAR8_H_
|
||||
|
||||
#endif // #ifdef ARDUINO_ARCH_STM32
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,220 @@
|
||||
#ifndef _ARDUINO_SWPAR16_H_
|
||||
#define _ARDUINO_SWPAR16_H_
|
||||
|
||||
#include "Arduino_DataBus.h"
|
||||
|
||||
class Arduino_SWPAR16 : public Arduino_DataBus
|
||||
{
|
||||
public:
|
||||
Arduino_SWPAR16(
|
||||
int8_t dc, int8_t cs, int8_t wr, int8_t rd,
|
||||
int8_t d0, int8_t d1, int8_t d2, int8_t d3, int8_t d4, int8_t d5, int8_t d6, int8_t d7,
|
||||
int8_t d8, int8_t d9, int8_t d10, int8_t d11, int8_t d12, int8_t d13, int8_t d14, int8_t d15); // Constructor
|
||||
|
||||
bool begin(int32_t speed = GFX_NOT_DEFINED, int8_t dataMode = GFX_NOT_DEFINED) override;
|
||||
void beginWrite() override;
|
||||
void endWrite() override;
|
||||
void writeCommand(uint8_t) override;
|
||||
void writeCommand16(uint16_t) override;
|
||||
void writeCommandBytes(uint8_t *data, uint32_t len) override;
|
||||
void write(uint8_t) override;
|
||||
void write16(uint16_t) override;
|
||||
void writeRepeat(uint16_t p, uint32_t len) override;
|
||||
void writeBytes(uint8_t *data, uint32_t len) override;
|
||||
void writePixels(uint16_t *data, uint32_t len) override;
|
||||
|
||||
#if !defined(LITTLE_FOOT_PRINT)
|
||||
void writeC8D8(uint8_t c, uint8_t d) override;
|
||||
void writeC8D16(uint8_t c, uint16_t d) override;
|
||||
void writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2) override;
|
||||
void writeC8D16D16Split(uint8_t c, uint16_t d1, uint16_t d2) override;
|
||||
|
||||
void writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len) override;
|
||||
void writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len) override;
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
|
||||
protected:
|
||||
private:
|
||||
GFX_INLINE void WRITE(uint8_t d);
|
||||
GFX_INLINE void WRITE16(uint16_t d);
|
||||
GFX_INLINE void WRITEREPEAT(uint16_t p, uint32_t len);
|
||||
GFX_INLINE void DC_HIGH(void);
|
||||
GFX_INLINE void DC_LOW(void);
|
||||
GFX_INLINE void CS_HIGH(void);
|
||||
GFX_INLINE void CS_LOW(void);
|
||||
GFX_INLINE void WR_HIGH(void);
|
||||
GFX_INLINE void WR_LOW(void);
|
||||
|
||||
GFX_INLINE void D0_HIGH(void);
|
||||
GFX_INLINE void D0_LOW(void);
|
||||
GFX_INLINE void D1_HIGH(void);
|
||||
GFX_INLINE void D1_LOW(void);
|
||||
GFX_INLINE void D2_HIGH(void);
|
||||
GFX_INLINE void D2_LOW(void);
|
||||
GFX_INLINE void D3_HIGH(void);
|
||||
GFX_INLINE void D3_LOW(void);
|
||||
GFX_INLINE void D4_HIGH(void);
|
||||
GFX_INLINE void D4_LOW(void);
|
||||
GFX_INLINE void D5_HIGH(void);
|
||||
GFX_INLINE void D5_LOW(void);
|
||||
GFX_INLINE void D6_HIGH(void);
|
||||
GFX_INLINE void D6_LOW(void);
|
||||
GFX_INLINE void D7_HIGH(void);
|
||||
GFX_INLINE void D7_LOW(void);
|
||||
GFX_INLINE void D8_HIGH(void);
|
||||
GFX_INLINE void D8_LOW(void);
|
||||
GFX_INLINE void D9_HIGH(void);
|
||||
GFX_INLINE void D9_LOW(void);
|
||||
GFX_INLINE void D10_HIGH(void);
|
||||
GFX_INLINE void D10_LOW(void);
|
||||
GFX_INLINE void D11_HIGH(void);
|
||||
GFX_INLINE void D11_LOW(void);
|
||||
GFX_INLINE void D12_HIGH(void);
|
||||
GFX_INLINE void D12_LOW(void);
|
||||
GFX_INLINE void D13_HIGH(void);
|
||||
GFX_INLINE void D13_LOW(void);
|
||||
GFX_INLINE void D14_HIGH(void);
|
||||
GFX_INLINE void D14_LOW(void);
|
||||
GFX_INLINE void D15_HIGH(void);
|
||||
GFX_INLINE void D15_LOW(void);
|
||||
|
||||
int8_t _dc, _cs, _wr, _rd;
|
||||
int8_t _d0, _d1, _d2, _d3, _d4, _d5, _d6, _d7;
|
||||
int8_t _d8, _d9, _d10, _d11, _d12, _d13, _d14, _d15;
|
||||
|
||||
// CLASS INSTANCE VARIABLES --------------------------------------------
|
||||
|
||||
// Here be dragons! There's a big union of three structures here --
|
||||
// one each for hardware SPI, software (bitbang) SPI, and parallel
|
||||
// interfaces. This is to save some memory, since a display's connection
|
||||
// will be only one of these. The order of some things is a little weird
|
||||
// in an attempt to get values to align and pack better in RAM.
|
||||
|
||||
#if defined(USE_FAST_PINIO)
|
||||
#if defined(HAS_PORT_SET_CLR)
|
||||
PORTreg_t _dcPortSet;
|
||||
PORTreg_t _dcPortClr;
|
||||
PORTreg_t _csPortSet;
|
||||
PORTreg_t _csPortClr;
|
||||
PORTreg_t _wrPortSet;
|
||||
PORTreg_t _wrPortClr;
|
||||
PORTreg_t _d0PortSet;
|
||||
PORTreg_t _d0PortClr;
|
||||
PORTreg_t _d1PortSet;
|
||||
PORTreg_t _d1PortClr;
|
||||
PORTreg_t _d2PortSet;
|
||||
PORTreg_t _d2PortClr;
|
||||
PORTreg_t _d3PortSet;
|
||||
PORTreg_t _d3PortClr;
|
||||
PORTreg_t _d4PortSet;
|
||||
PORTreg_t _d4PortClr;
|
||||
PORTreg_t _d5PortSet;
|
||||
PORTreg_t _d5PortClr;
|
||||
PORTreg_t _d6PortSet;
|
||||
PORTreg_t _d6PortClr;
|
||||
PORTreg_t _d7PortSet;
|
||||
PORTreg_t _d7PortClr;
|
||||
PORTreg_t _d8PortSet;
|
||||
PORTreg_t _d8PortClr;
|
||||
PORTreg_t _d9PortSet;
|
||||
PORTreg_t _d9PortClr;
|
||||
PORTreg_t _d10PortSet;
|
||||
PORTreg_t _d10PortClr;
|
||||
PORTreg_t _d11PortSet;
|
||||
PORTreg_t _d11PortClr;
|
||||
PORTreg_t _d12PortSet;
|
||||
PORTreg_t _d12PortClr;
|
||||
PORTreg_t _d13PortSet;
|
||||
PORTreg_t _d13PortClr;
|
||||
PORTreg_t _d14PortSet;
|
||||
PORTreg_t _d14PortClr;
|
||||
PORTreg_t _d15PortSet;
|
||||
PORTreg_t _d15PortClr;
|
||||
#if !defined(KINETISK)
|
||||
ARDUINOGFX_PORT_t _dcPinMask;
|
||||
ARDUINOGFX_PORT_t _csPinMask;
|
||||
ARDUINOGFX_PORT_t _wrPinMask;
|
||||
|
||||
ARDUINOGFX_PORT_t _d0PinMask;
|
||||
ARDUINOGFX_PORT_t _d1PinMask;
|
||||
ARDUINOGFX_PORT_t _d2PinMask;
|
||||
ARDUINOGFX_PORT_t _d3PinMask;
|
||||
ARDUINOGFX_PORT_t _d4PinMask;
|
||||
ARDUINOGFX_PORT_t _d5PinMask;
|
||||
ARDUINOGFX_PORT_t _d6PinMask;
|
||||
ARDUINOGFX_PORT_t _d7PinMask;
|
||||
ARDUINOGFX_PORT_t _d8PinMask;
|
||||
ARDUINOGFX_PORT_t _d9PinMask;
|
||||
ARDUINOGFX_PORT_t _d10PinMask;
|
||||
ARDUINOGFX_PORT_t _d11PinMask;
|
||||
ARDUINOGFX_PORT_t _d12PinMask;
|
||||
ARDUINOGFX_PORT_t _d13PinMask;
|
||||
ARDUINOGFX_PORT_t _d14PinMask;
|
||||
ARDUINOGFX_PORT_t _d15PinMask;
|
||||
#endif // !KINETISK
|
||||
#else // !HAS_PORT_SET_CLR
|
||||
PORTreg_t _dcPort;
|
||||
PORTreg_t _csPort;
|
||||
PORTreg_t _wrPort;
|
||||
|
||||
PORTreg_t _d0Port;
|
||||
PORTreg_t _d1Port;
|
||||
PORTreg_t _d2Port;
|
||||
PORTreg_t _d3Port;
|
||||
PORTreg_t _d4Port;
|
||||
PORTreg_t _d5Port;
|
||||
PORTreg_t _d6Port;
|
||||
PORTreg_t _d7Port;
|
||||
PORTreg_t _d8Port;
|
||||
PORTreg_t _d9Port;
|
||||
PORTreg_t _d10Port;
|
||||
PORTreg_t _d11Port;
|
||||
PORTreg_t _d12Port;
|
||||
PORTreg_t _d13Port;
|
||||
PORTreg_t _d14Port;
|
||||
PORTreg_t _d15Port;
|
||||
ARDUINOGFX_PORT_t _dcPinMaskSet;
|
||||
ARDUINOGFX_PORT_t _dcPinMaskClr;
|
||||
ARDUINOGFX_PORT_t _csPinMaskSet;
|
||||
ARDUINOGFX_PORT_t _csPinMaskClr;
|
||||
ARDUINOGFX_PORT_t _wrPinMaskSet;
|
||||
ARDUINOGFX_PORT_t _wrPinMaskClr;
|
||||
ARDUINOGFX_PORT_t _rdPinMaskSet;
|
||||
ARDUINOGFX_PORT_t _rdPinMaskClr;
|
||||
ARDUINOGFX_PORT_t _d0PinMaskSet;
|
||||
ARDUINOGFX_PORT_t _d0PinMaskClr;
|
||||
ARDUINOGFX_PORT_t _d1PinMaskSet;
|
||||
ARDUINOGFX_PORT_t _d1PinMaskClr;
|
||||
ARDUINOGFX_PORT_t _d2PinMaskSet;
|
||||
ARDUINOGFX_PORT_t _d2PinMaskClr;
|
||||
ARDUINOGFX_PORT_t _d3PinMaskSet;
|
||||
ARDUINOGFX_PORT_t _d3PinMaskClr;
|
||||
ARDUINOGFX_PORT_t _d4PinMaskSet;
|
||||
ARDUINOGFX_PORT_t _d4PinMaskClr;
|
||||
ARDUINOGFX_PORT_t _d5PinMaskSet;
|
||||
ARDUINOGFX_PORT_t _d5PinMaskClr;
|
||||
ARDUINOGFX_PORT_t _d6PinMaskSet;
|
||||
ARDUINOGFX_PORT_t _d6PinMaskClr;
|
||||
ARDUINOGFX_PORT_t _d7PinMaskSet;
|
||||
ARDUINOGFX_PORT_t _d7PinMaskClr;
|
||||
ARDUINOGFX_PORT_t _d8PinMaskSet;
|
||||
ARDUINOGFX_PORT_t _d8PinMaskClr;
|
||||
ARDUINOGFX_PORT_t _d9PinMaskSet;
|
||||
ARDUINOGFX_PORT_t _d9PinMaskClr;
|
||||
ARDUINOGFX_PORT_t _d10PinMaskSet;
|
||||
ARDUINOGFX_PORT_t _d10PinMaskClr;
|
||||
ARDUINOGFX_PORT_t _d11PinMaskSet;
|
||||
ARDUINOGFX_PORT_t _d11PinMaskClr;
|
||||
ARDUINOGFX_PORT_t _d12PinMaskSet;
|
||||
ARDUINOGFX_PORT_t _d12PinMaskClr;
|
||||
ARDUINOGFX_PORT_t _d13PinMaskSet;
|
||||
ARDUINOGFX_PORT_t _d13PinMaskClr;
|
||||
ARDUINOGFX_PORT_t _d14PinMaskSet;
|
||||
ARDUINOGFX_PORT_t _d14PinMaskClr;
|
||||
ARDUINOGFX_PORT_t _d15PinMaskSet;
|
||||
ARDUINOGFX_PORT_t _d15PinMaskClr;
|
||||
#endif // HAS_PORT_SET_CLR
|
||||
#endif // defined(USE_FAST_PINIO)
|
||||
};
|
||||
|
||||
#endif // _ARDUINO_SWPAR16_H_
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,151 @@
|
||||
#ifndef _ARDUINO_SWPAR8_H_
|
||||
#define _ARDUINO_SWPAR8_H_
|
||||
|
||||
#include "Arduino_DataBus.h"
|
||||
|
||||
class Arduino_SWPAR8 : public Arduino_DataBus
|
||||
{
|
||||
public:
|
||||
Arduino_SWPAR8(
|
||||
int8_t dc, int8_t cs, int8_t wr, int8_t rd,
|
||||
int8_t d0, int8_t d1, int8_t d2, int8_t d3, int8_t d4, int8_t d5, int8_t d6, int8_t d7); // Constructor
|
||||
|
||||
bool begin(int32_t speed = GFX_NOT_DEFINED, int8_t dataMode = GFX_NOT_DEFINED) override;
|
||||
void beginWrite() override;
|
||||
void endWrite() override;
|
||||
void writeCommand(uint8_t) override;
|
||||
void writeCommand16(uint16_t) override;
|
||||
void writeCommandBytes(uint8_t *data, uint32_t len) override;
|
||||
void write(uint8_t) override;
|
||||
void write16(uint16_t) override;
|
||||
void writeRepeat(uint16_t p, uint32_t len) override;
|
||||
void writeBytes(uint8_t *data, uint32_t len) override;
|
||||
void writePixels(uint16_t *data, uint32_t len) override;
|
||||
|
||||
#if !defined(LITTLE_FOOT_PRINT)
|
||||
void writeC8D8(uint8_t c, uint8_t d) override;
|
||||
void writeC8D16(uint8_t c, uint16_t d) override;
|
||||
void writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2) override;
|
||||
|
||||
void writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len) override;
|
||||
void writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len) override;
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
|
||||
private:
|
||||
GFX_INLINE void WRITE(uint8_t d);
|
||||
GFX_INLINE void WRITEREPEAT(uint16_t p, uint32_t len);
|
||||
GFX_INLINE void DC_HIGH(void);
|
||||
GFX_INLINE void DC_LOW(void);
|
||||
GFX_INLINE void CS_HIGH(void);
|
||||
GFX_INLINE void CS_LOW(void);
|
||||
GFX_INLINE void WR_HIGH(void);
|
||||
GFX_INLINE void WR_LOW(void);
|
||||
|
||||
GFX_INLINE void D0_HIGH(void);
|
||||
GFX_INLINE void D0_LOW(void);
|
||||
GFX_INLINE void D1_HIGH(void);
|
||||
GFX_INLINE void D1_LOW(void);
|
||||
GFX_INLINE void D2_HIGH(void);
|
||||
GFX_INLINE void D2_LOW(void);
|
||||
GFX_INLINE void D3_HIGH(void);
|
||||
GFX_INLINE void D3_LOW(void);
|
||||
GFX_INLINE void D4_HIGH(void);
|
||||
GFX_INLINE void D4_LOW(void);
|
||||
GFX_INLINE void D5_HIGH(void);
|
||||
GFX_INLINE void D5_LOW(void);
|
||||
GFX_INLINE void D6_HIGH(void);
|
||||
GFX_INLINE void D6_LOW(void);
|
||||
GFX_INLINE void D7_HIGH(void);
|
||||
GFX_INLINE void D7_LOW(void);
|
||||
|
||||
int8_t _dc, _cs, _wr, _rd;
|
||||
int8_t _d0, _d1, _d2, _d3, _d4, _d5, _d6, _d7;
|
||||
|
||||
// CLASS INSTANCE VARIABLES --------------------------------------------
|
||||
|
||||
// Here be dragons! There's a big union of three structures here --
|
||||
// one each for hardware SPI, software (bitbang) SPI, and parallel
|
||||
// interfaces. This is to save some memory, since a display's connection
|
||||
// will be only one of these. The order of some things is a little weird
|
||||
// in an attempt to get values to align and pack better in RAM.
|
||||
|
||||
#if defined(USE_FAST_PINIO)
|
||||
#if defined(HAS_PORT_SET_CLR)
|
||||
PORTreg_t _dcPortSet;
|
||||
PORTreg_t _dcPortClr;
|
||||
PORTreg_t _csPortSet;
|
||||
PORTreg_t _csPortClr;
|
||||
PORTreg_t _wrPortSet;
|
||||
PORTreg_t _wrPortClr;
|
||||
PORTreg_t _d0PortSet;
|
||||
PORTreg_t _d0PortClr;
|
||||
PORTreg_t _d1PortSet;
|
||||
PORTreg_t _d1PortClr;
|
||||
PORTreg_t _d2PortSet;
|
||||
PORTreg_t _d2PortClr;
|
||||
PORTreg_t _d3PortSet;
|
||||
PORTreg_t _d3PortClr;
|
||||
PORTreg_t _d4PortSet;
|
||||
PORTreg_t _d4PortClr;
|
||||
PORTreg_t _d5PortSet;
|
||||
PORTreg_t _d5PortClr;
|
||||
PORTreg_t _d6PortSet;
|
||||
PORTreg_t _d6PortClr;
|
||||
PORTreg_t _d7PortSet;
|
||||
PORTreg_t _d7PortClr;
|
||||
#if !defined(KINETISK)
|
||||
ARDUINOGFX_PORT_t _dcPinMask;
|
||||
ARDUINOGFX_PORT_t _csPinMask;
|
||||
ARDUINOGFX_PORT_t _wrPinMask;
|
||||
|
||||
ARDUINOGFX_PORT_t _d0PinMask;
|
||||
ARDUINOGFX_PORT_t _d1PinMask;
|
||||
ARDUINOGFX_PORT_t _d2PinMask;
|
||||
ARDUINOGFX_PORT_t _d3PinMask;
|
||||
ARDUINOGFX_PORT_t _d4PinMask;
|
||||
ARDUINOGFX_PORT_t _d5PinMask;
|
||||
ARDUINOGFX_PORT_t _d6PinMask;
|
||||
ARDUINOGFX_PORT_t _d7PinMask;
|
||||
#endif // !KINETISK
|
||||
#else // !HAS_PORT_SET_CLR
|
||||
PORTreg_t _dcPort;
|
||||
PORTreg_t _csPort;
|
||||
PORTreg_t _wrPort;
|
||||
|
||||
PORTreg_t _d0Port;
|
||||
PORTreg_t _d1Port;
|
||||
PORTreg_t _d2Port;
|
||||
PORTreg_t _d3Port;
|
||||
PORTreg_t _d4Port;
|
||||
PORTreg_t _d5Port;
|
||||
PORTreg_t _d6Port;
|
||||
PORTreg_t _d7Port;
|
||||
ARDUINOGFX_PORT_t _dcPinMaskSet;
|
||||
ARDUINOGFX_PORT_t _dcPinMaskClr;
|
||||
ARDUINOGFX_PORT_t _csPinMaskSet;
|
||||
ARDUINOGFX_PORT_t _csPinMaskClr;
|
||||
ARDUINOGFX_PORT_t _wrPinMaskSet;
|
||||
ARDUINOGFX_PORT_t _wrPinMaskClr;
|
||||
ARDUINOGFX_PORT_t _rdPinMaskSet;
|
||||
ARDUINOGFX_PORT_t _rdPinMaskClr;
|
||||
ARDUINOGFX_PORT_t _d0PinMaskSet;
|
||||
ARDUINOGFX_PORT_t _d0PinMaskClr;
|
||||
ARDUINOGFX_PORT_t _d1PinMaskSet;
|
||||
ARDUINOGFX_PORT_t _d1PinMaskClr;
|
||||
ARDUINOGFX_PORT_t _d2PinMaskSet;
|
||||
ARDUINOGFX_PORT_t _d2PinMaskClr;
|
||||
ARDUINOGFX_PORT_t _d3PinMaskSet;
|
||||
ARDUINOGFX_PORT_t _d3PinMaskClr;
|
||||
ARDUINOGFX_PORT_t _d4PinMaskSet;
|
||||
ARDUINOGFX_PORT_t _d4PinMaskClr;
|
||||
ARDUINOGFX_PORT_t _d5PinMaskSet;
|
||||
ARDUINOGFX_PORT_t _d5PinMaskClr;
|
||||
ARDUINOGFX_PORT_t _d6PinMaskSet;
|
||||
ARDUINOGFX_PORT_t _d6PinMaskClr;
|
||||
ARDUINOGFX_PORT_t _d7PinMaskSet;
|
||||
ARDUINOGFX_PORT_t _d7PinMaskClr;
|
||||
#endif // HAS_PORT_SET_CLR
|
||||
#endif // defined(USE_FAST_PINIO)
|
||||
};
|
||||
|
||||
#endif // _ARDUINO_SWPAR8_H_
|
||||
@@ -0,0 +1,737 @@
|
||||
/*
|
||||
* start rewrite from:
|
||||
* https://github.com/adafruit/Adafruit-GFX-Library.git
|
||||
*/
|
||||
#include "Arduino_SWSPI.h"
|
||||
|
||||
Arduino_SWSPI::Arduino_SWSPI(int8_t dc, int8_t cs, int8_t sck, int8_t mosi, int8_t miso /* = GFX_NOT_DEFINED */)
|
||||
: _dc(dc), _cs(cs), _sck(sck), _mosi(mosi), _miso(miso)
|
||||
{
|
||||
}
|
||||
|
||||
bool Arduino_SWSPI::begin(int32_t, int8_t)
|
||||
{
|
||||
if (_dc != GFX_NOT_DEFINED)
|
||||
{
|
||||
pinMode(_dc, OUTPUT);
|
||||
digitalWrite(_dc, HIGH); // Data mode
|
||||
}
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
pinMode(_cs, OUTPUT);
|
||||
digitalWrite(_cs, HIGH); // Deselect
|
||||
}
|
||||
pinMode(_sck, OUTPUT);
|
||||
digitalWrite(_sck, LOW);
|
||||
pinMode(_mosi, OUTPUT);
|
||||
digitalWrite(_mosi, LOW);
|
||||
if (_miso != GFX_NOT_DEFINED)
|
||||
{
|
||||
pinMode(_miso, INPUT);
|
||||
}
|
||||
|
||||
#if defined(USE_FAST_PINIO)
|
||||
#if defined(HAS_PORT_SET_CLR)
|
||||
#if defined(ARDUINO_ARCH_NRF52840)
|
||||
uint32_t pin;
|
||||
NRF_GPIO_Type *reg;
|
||||
if (_dc != GFX_NOT_DEFINED)
|
||||
{
|
||||
pin = digitalPinToPinName((pin_size_t)_dc);
|
||||
reg = nrf_gpio_pin_port_decode(&pin);
|
||||
_dcPinMask = 1UL << pin;
|
||||
_dcPortSet = ®->OUTSET;
|
||||
_dcPortClr = ®->OUTCLR;
|
||||
}
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
pin = digitalPinToPinName((pin_size_t)_cs);
|
||||
NRF_GPIO_Type *reg = nrf_gpio_pin_port_decode(&pin);
|
||||
_csPinMask = 1UL << pin;
|
||||
_csPortSet = ®->OUTSET;
|
||||
_csPortClr = ®->OUTCLR;
|
||||
}
|
||||
pin = digitalPinToPinName((pin_size_t)_sck);
|
||||
reg = nrf_gpio_pin_port_decode(&pin);
|
||||
_sckPinMask = 1UL << pin;
|
||||
_sckPortSet = ®->OUTSET;
|
||||
_sckPortClr = ®->OUTCLR;
|
||||
pin = digitalPinToPinName((pin_size_t)_mosi);
|
||||
reg = nrf_gpio_pin_port_decode(&pin);
|
||||
_mosiPinMask = 1UL << pin;
|
||||
_mosiPortSet = ®->OUTSET;
|
||||
_mosiPortClr = ®->OUTCLR;
|
||||
if (_miso != GFX_NOT_DEFINED)
|
||||
{
|
||||
pin = digitalPinToPinName((pin_size_t)_miso);
|
||||
reg = nrf_gpio_pin_port_decode(&pin);
|
||||
_misoPinMask = 1UL << pin;
|
||||
_misoPort = ®->IN;
|
||||
}
|
||||
#elif defined(ARDUINO_UNOR4_MINIMA) || defined(ARDUINO_UNOR4_WIFI)
|
||||
if (_dc != GFX_NOT_DEFINED)
|
||||
{
|
||||
_dcPinMask = digitalPinToBitMask(_dc);
|
||||
_dcPortSet = (PORTreg_t) & (((R_PORT0_Type *)IOPORT_PRV_PORT_ADDRESS(digitalPinToPort(_dc)))->POSR);
|
||||
_dcPortClr = (PORTreg_t) & (((R_PORT0_Type *)IOPORT_PRV_PORT_ADDRESS(digitalPinToPort(_dc)))->PORR);
|
||||
}
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
_csPinMask = digitalPinToBitMask(_cs);
|
||||
_csPortSet = (PORTreg_t) & (((R_PORT0_Type *)IOPORT_PRV_PORT_ADDRESS(digitalPinToPort(_cs)))->POSR);
|
||||
_csPortClr = (PORTreg_t) & (((R_PORT0_Type *)IOPORT_PRV_PORT_ADDRESS(digitalPinToPort(_cs)))->PORR);
|
||||
}
|
||||
_sckPinMask = digitalPinToBitMask(_sck);
|
||||
_sckPortSet = (PORTreg_t) & (((R_PORT0_Type *)IOPORT_PRV_PORT_ADDRESS(digitalPinToPort(_sck)))->POSR);
|
||||
_sckPortClr = (PORTreg_t) & (((R_PORT0_Type *)IOPORT_PRV_PORT_ADDRESS(digitalPinToPort(_sck)))->PORR);
|
||||
_mosiPinMask = digitalPinToBitMask(_mosi);
|
||||
_mosiPortSet = (PORTreg_t) & (((R_PORT0_Type *)IOPORT_PRV_PORT_ADDRESS(digitalPinToPort(_mosi)))->POSR);
|
||||
_mosiPortClr = (PORTreg_t) & (((R_PORT0_Type *)IOPORT_PRV_PORT_ADDRESS(digitalPinToPort(_mosi)))->PORR);
|
||||
if (_miso != GFX_NOT_DEFINED)
|
||||
{
|
||||
_misoPinMask = digitalPinToBitMask(_miso);
|
||||
_misoPort = (PORTreg_t)portInputRegister(digitalPinToPort(_miso));
|
||||
}
|
||||
#elif defined(TARGET_RP2040) || defined(PICO_RP2350)
|
||||
if (_dc != GFX_NOT_DEFINED)
|
||||
{
|
||||
_dcPinMask = digitalPinToBitMask(_dc);
|
||||
_dcPortSet = (PORTreg_t)&sio_hw->gpio_set;
|
||||
_dcPortClr = (PORTreg_t)&sio_hw->gpio_clr;
|
||||
}
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
_csPinMask = digitalPinToBitMask(_cs);
|
||||
_csPortSet = (PORTreg_t)&sio_hw->gpio_set;
|
||||
_csPortClr = (PORTreg_t)&sio_hw->gpio_clr;
|
||||
}
|
||||
_sckPinMask = digitalPinToBitMask(_sck);
|
||||
_sckPortSet = (PORTreg_t)&sio_hw->gpio_set;
|
||||
_sckPortClr = (PORTreg_t)&sio_hw->gpio_clr;
|
||||
_mosiPinMask = digitalPinToBitMask(_mosi);
|
||||
_mosiPortSet = (PORTreg_t)&sio_hw->gpio_set;
|
||||
_mosiPortClr = (PORTreg_t)&sio_hw->gpio_clr;
|
||||
if (_miso != GFX_NOT_DEFINED)
|
||||
{
|
||||
_misoPinMask = digitalPinToBitMask(_miso);
|
||||
_misoPort = (PORTreg_t)portInputRegister(digitalPinToPort(_miso));
|
||||
}
|
||||
#elif defined(ESP32) && (CONFIG_IDF_TARGET_ESP32C3)
|
||||
_dcPinMask = digitalPinToBitMask(_dc);
|
||||
_dcPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_dcPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
_csPinMask = digitalPinToBitMask(_cs);
|
||||
_csPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_csPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
}
|
||||
_sckPinMask = digitalPinToBitMask(_sck);
|
||||
_sckPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_sckPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
_mosiPinMask = digitalPinToBitMask(_mosi);
|
||||
_mosiPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_mosiPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
if (_miso != GFX_NOT_DEFINED)
|
||||
{
|
||||
_misoPinMask = digitalPinToBitMask(_miso);
|
||||
_misoPort = (PORTreg_t)GPIO_IN_REG;
|
||||
}
|
||||
#elif defined(ESP32)
|
||||
_dcPinMask = digitalPinToBitMask(_dc);
|
||||
if (_dc >= 32)
|
||||
{
|
||||
_dcPortSet = (PORTreg_t)GPIO_OUT1_W1TS_REG;
|
||||
_dcPortClr = (PORTreg_t)GPIO_OUT1_W1TC_REG;
|
||||
}
|
||||
else if (_dc != GFX_NOT_DEFINED)
|
||||
{
|
||||
_dcPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_dcPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
}
|
||||
if (_cs >= 32)
|
||||
{
|
||||
_csPinMask = digitalPinToBitMask(_cs);
|
||||
_csPortSet = (PORTreg_t)GPIO_OUT1_W1TS_REG;
|
||||
_csPortClr = (PORTreg_t)GPIO_OUT1_W1TC_REG;
|
||||
}
|
||||
else if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
_csPinMask = digitalPinToBitMask(_cs);
|
||||
_csPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_csPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
}
|
||||
_sckPinMask = digitalPinToBitMask(_sck);
|
||||
_mosiPinMask = digitalPinToBitMask(_mosi);
|
||||
if (_sck >= 32)
|
||||
{
|
||||
_sckPortSet = (PORTreg_t)GPIO_OUT1_W1TS_REG;
|
||||
_sckPortClr = (PORTreg_t)GPIO_OUT1_W1TC_REG;
|
||||
}
|
||||
else
|
||||
{
|
||||
_sckPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_sckPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
}
|
||||
if (_mosi >= 32)
|
||||
{
|
||||
_mosiPortSet = (PORTreg_t)GPIO_OUT1_W1TS_REG;
|
||||
_mosiPortClr = (PORTreg_t)GPIO_OUT1_W1TC_REG;
|
||||
}
|
||||
else
|
||||
{
|
||||
_mosiPortSet = (PORTreg_t)GPIO_OUT_W1TS_REG;
|
||||
_mosiPortClr = (PORTreg_t)GPIO_OUT_W1TC_REG;
|
||||
}
|
||||
if (_miso != GFX_NOT_DEFINED)
|
||||
{
|
||||
_misoPinMask = digitalPinToBitMask(_miso);
|
||||
_misoPort = (PORTreg_t)portInputRegister(digitalPinToPort(_miso));
|
||||
}
|
||||
#elif defined(CORE_TEENSY)
|
||||
if (_dc != GFX_NOT_DEFINED)
|
||||
{
|
||||
#if !defined(KINETISK)
|
||||
_dcPinMask = digitalPinToBitMask(_dc);
|
||||
#endif
|
||||
_dcPortSet = portSetRegister(_dc);
|
||||
_dcPortClr = portClearRegister(_dc);
|
||||
}
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
#if !defined(KINETISK)
|
||||
_csPinMask = digitalPinToBitMask(_cs);
|
||||
#endif
|
||||
_csPortSet = portSetRegister(_cs);
|
||||
_csPortClr = portClearRegister(_cs);
|
||||
}
|
||||
#if !defined(KINETISK)
|
||||
_sckPinMask = digitalPinToBitMask(_sck);
|
||||
#endif
|
||||
_sckPortSet = portSetRegister(_sck);
|
||||
_sckPortClr = portClearRegister(_sck);
|
||||
#if !defined(KINETISK)
|
||||
_mosiPinMask = digitalPinToBitMask(_mosi);
|
||||
#endif
|
||||
_mosiPortSet = portSetRegister(_mosi);
|
||||
_mosiPortClr = portClearRegister(_mosi);
|
||||
if (_miso != GFX_NOT_DEFINED)
|
||||
{
|
||||
#if !defined(KINETISK)
|
||||
_misoPinMask = digitalPinToBitMask(_miso);
|
||||
#endif
|
||||
_misoPort = (PORTreg_t)portInputRegister(digitalPinToPort(_miso));
|
||||
}
|
||||
#else // !CORE_TEENSY
|
||||
if (_dc != GFX_NOT_DEFINED)
|
||||
{
|
||||
_dcPinMask = digitalPinToBitMask(_dc);
|
||||
_dcPortSet = &(PORT->Group[g_APinDescription[_dc].ulPort].OUTSET.reg);
|
||||
_dcPortClr = &(PORT->Group[g_APinDescription[_dc].ulPort].OUTCLR.reg);
|
||||
}
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
_csPinMask = digitalPinToBitMask(_cs);
|
||||
_csPortSet = &(PORT->Group[g_APinDescription[_cs].ulPort].OUTSET.reg);
|
||||
_csPortClr = &(PORT->Group[g_APinDescription[_cs].ulPort].OUTCLR.reg);
|
||||
}
|
||||
_sckPinMask = digitalPinToBitMask(_sck);
|
||||
_sckPortSet = &(PORT->Group[g_APinDescription[_sck].ulPort].OUTSET.reg);
|
||||
_sckPortClr = &(PORT->Group[g_APinDescription[_sck].ulPort].OUTCLR.reg);
|
||||
_mosiPinMask = digitalPinToBitMask(_mosi);
|
||||
_mosiPortSet = &(PORT->Group[g_APinDescription[_mosi].ulPort].OUTSET.reg);
|
||||
_mosiPortClr = &(PORT->Group[g_APinDescription[_mosi].ulPort].OUTCLR.reg);
|
||||
if (_miso != GFX_NOT_DEFINED)
|
||||
{
|
||||
_misoPinMask = digitalPinToBitMask(_miso);
|
||||
_misoPort = (PORTreg_t)portInputRegister(digitalPinToPort(_miso));
|
||||
}
|
||||
#endif // end !CORE_TEENSY
|
||||
#else // !HAS_PORT_SET_CLR
|
||||
if (_dc != GFX_NOT_DEFINED)
|
||||
{
|
||||
_dcPort = (PORTreg_t)portOutputRegister(digitalPinToPort(_dc));
|
||||
_dcPinMaskSet = digitalPinToBitMask(_dc);
|
||||
_dcPinMaskClr = ~_dcPinMaskSet;
|
||||
}
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
_csPort = (PORTreg_t)portOutputRegister(digitalPinToPort(_cs));
|
||||
_csPinMaskSet = digitalPinToBitMask(_cs);
|
||||
_csPinMaskClr = ~_csPinMaskSet;
|
||||
}
|
||||
_sckPort = (PORTreg_t)portOutputRegister(digitalPinToPort(_sck));
|
||||
_sckPinMaskSet = digitalPinToBitMask(_sck);
|
||||
_sckPinMaskClr = ~_sckPinMaskSet;
|
||||
_mosiPort = (PORTreg_t)portOutputRegister(digitalPinToPort(_mosi));
|
||||
_mosiPinMaskSet = digitalPinToBitMask(_mosi);
|
||||
_mosiPinMaskClr = ~_mosiPinMaskSet;
|
||||
if (_miso != GFX_NOT_DEFINED)
|
||||
{
|
||||
_misoPort = (PORTreg_t)portInputRegister(digitalPinToPort(_miso));
|
||||
_misoPinMask = digitalPinToBitMask(_miso);
|
||||
}
|
||||
#endif // !HAS_PORT_SET_CLR
|
||||
#endif // USE_FAST_PINIO
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Arduino_SWSPI::beginWrite()
|
||||
{
|
||||
if (_dc != GFX_NOT_DEFINED)
|
||||
{
|
||||
DC_HIGH();
|
||||
}
|
||||
CS_LOW();
|
||||
}
|
||||
|
||||
void Arduino_SWSPI::endWrite()
|
||||
{
|
||||
CS_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_SWSPI::writeCommand(uint8_t c)
|
||||
{
|
||||
if (_dc == GFX_NOT_DEFINED) // 9-bit SPI
|
||||
{
|
||||
WRITE9BITCOMMAND(c);
|
||||
}
|
||||
else
|
||||
{
|
||||
DC_LOW();
|
||||
WRITE(c);
|
||||
DC_HIGH();
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_SWSPI::writeCommand16(uint16_t c)
|
||||
{
|
||||
if (_dc == GFX_NOT_DEFINED) // 9-bit SPI
|
||||
{
|
||||
_data16.value = c;
|
||||
WRITE9BITCOMMAND(_data16.msb);
|
||||
WRITE9BITCOMMAND(_data16.lsb);
|
||||
}
|
||||
else
|
||||
{
|
||||
DC_LOW();
|
||||
WRITE16(c);
|
||||
DC_HIGH();
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_SWSPI::writeCommandBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
if (_dc == GFX_NOT_DEFINED) // 9-bit SPI
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
WRITE9BITCOMMAND(*data++);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DC_LOW();
|
||||
while (len--)
|
||||
{
|
||||
WRITE(*data++);
|
||||
}
|
||||
DC_HIGH();
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_SWSPI::write(uint8_t d)
|
||||
{
|
||||
if (_dc == GFX_NOT_DEFINED) // 9-bit SPI
|
||||
{
|
||||
WRITE9BITDATA(d);
|
||||
}
|
||||
else
|
||||
{
|
||||
WRITE(d);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_SWSPI::write16(uint16_t d)
|
||||
{
|
||||
if (_dc == GFX_NOT_DEFINED) // 9-bit SPI
|
||||
{
|
||||
_data16.value = d;
|
||||
WRITE9BITDATA(_data16.msb);
|
||||
WRITE9BITDATA(_data16.lsb);
|
||||
}
|
||||
else
|
||||
{
|
||||
WRITE16(d);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_SWSPI::writeRepeat(uint16_t p, uint32_t len)
|
||||
{
|
||||
if (_dc == GFX_NOT_DEFINED) // 9-bit SPI
|
||||
{
|
||||
// ESP8266 avoid trigger watchdog
|
||||
#if defined(ESP8266)
|
||||
while (len > (ESP8266SAFEBATCHBITSIZE / 9))
|
||||
{
|
||||
WRITE9BITREPEAT(p, ESP8266SAFEBATCHBITSIZE / 9);
|
||||
len -= ESP8266SAFEBATCHBITSIZE / 9;
|
||||
yield();
|
||||
}
|
||||
WRITE9BITREPEAT(p, len);
|
||||
#else
|
||||
WRITE9BITREPEAT(p, len);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined(ESP8266)
|
||||
while (len > (ESP8266SAFEBATCHBITSIZE / 8))
|
||||
{
|
||||
WRITEREPEAT(p, ESP8266SAFEBATCHBITSIZE / 8);
|
||||
len -= ESP8266SAFEBATCHBITSIZE / 8;
|
||||
yield();
|
||||
}
|
||||
WRITEREPEAT(p, len);
|
||||
#else
|
||||
WRITEREPEAT(p, len);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_SWSPI::writePixels(uint16_t *data, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
WRITE16(*data++);
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(LITTLE_FOOT_PRINT)
|
||||
void Arduino_SWSPI::writeBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
WRITE(*data++);
|
||||
}
|
||||
}
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
|
||||
GFX_INLINE void Arduino_SWSPI::WRITE9BITCOMMAND(uint8_t c)
|
||||
{
|
||||
// D/C bit, command
|
||||
SPI_MOSI_LOW();
|
||||
SPI_SCK_HIGH();
|
||||
SPI_SCK_LOW();
|
||||
|
||||
uint8_t bit = 0x80;
|
||||
while (bit)
|
||||
{
|
||||
if (c & bit)
|
||||
{
|
||||
SPI_MOSI_HIGH();
|
||||
}
|
||||
else
|
||||
{
|
||||
SPI_MOSI_LOW();
|
||||
}
|
||||
SPI_SCK_HIGH();
|
||||
bit >>= 1;
|
||||
SPI_SCK_LOW();
|
||||
}
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_SWSPI::WRITE9BITDATA(uint8_t d)
|
||||
{
|
||||
// D/C bit, data
|
||||
SPI_MOSI_HIGH();
|
||||
SPI_SCK_HIGH();
|
||||
SPI_SCK_LOW();
|
||||
|
||||
uint8_t bit = 0x80;
|
||||
while (bit)
|
||||
{
|
||||
if (d & bit)
|
||||
{
|
||||
SPI_MOSI_HIGH();
|
||||
}
|
||||
else
|
||||
{
|
||||
SPI_MOSI_LOW();
|
||||
}
|
||||
SPI_SCK_HIGH();
|
||||
bit >>= 1;
|
||||
SPI_SCK_LOW();
|
||||
}
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_SWSPI::WRITE(uint8_t d)
|
||||
{
|
||||
uint8_t bit = 0x80;
|
||||
while (bit)
|
||||
{
|
||||
if (d & bit)
|
||||
{
|
||||
SPI_MOSI_HIGH();
|
||||
}
|
||||
else
|
||||
{
|
||||
SPI_MOSI_LOW();
|
||||
}
|
||||
SPI_SCK_HIGH();
|
||||
bit >>= 1;
|
||||
SPI_SCK_LOW();
|
||||
}
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_SWSPI::WRITE16(uint16_t d)
|
||||
{
|
||||
uint16_t bit = 0x8000;
|
||||
while (bit)
|
||||
{
|
||||
if (d & bit)
|
||||
{
|
||||
SPI_MOSI_HIGH();
|
||||
}
|
||||
else
|
||||
{
|
||||
SPI_MOSI_LOW();
|
||||
}
|
||||
SPI_SCK_HIGH();
|
||||
bit >>= 1;
|
||||
SPI_SCK_LOW();
|
||||
}
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_SWSPI::WRITE9BITREPEAT(uint16_t p, uint32_t len)
|
||||
{
|
||||
if (p == 0xffff) // no need to set MOSI level while filling white
|
||||
{
|
||||
SPI_MOSI_HIGH();
|
||||
len *= 18; // 9-bit * 2
|
||||
while (len--)
|
||||
{
|
||||
SPI_SCK_HIGH();
|
||||
SPI_SCK_LOW();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_data16.value = p;
|
||||
while (len--)
|
||||
{
|
||||
WRITE9BITDATA(_data16.msb);
|
||||
WRITE9BITDATA(_data16.lsb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_SWSPI::WRITEREPEAT(uint16_t p, uint32_t len)
|
||||
{
|
||||
if ((p == 0x0000) || (p == 0xffff)) // no need to set MOSI level while filling black or white
|
||||
{
|
||||
if (p)
|
||||
{
|
||||
SPI_MOSI_HIGH();
|
||||
}
|
||||
else
|
||||
{
|
||||
SPI_MOSI_LOW();
|
||||
}
|
||||
len *= 16;
|
||||
while (len--)
|
||||
{
|
||||
SPI_SCK_HIGH();
|
||||
SPI_SCK_LOW();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
WRITE16(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/******** low level bit twiddling **********/
|
||||
|
||||
GFX_INLINE void Arduino_SWSPI::DC_HIGH(void)
|
||||
{
|
||||
#if defined(USE_FAST_PINIO)
|
||||
#if defined(HAS_PORT_SET_CLR)
|
||||
#if defined(KINETISK)
|
||||
*_dcPortSet = 1;
|
||||
#else // !KINETISK
|
||||
*_dcPortSet = _dcPinMask;
|
||||
#endif // end !KINETISK
|
||||
#else // !HAS_PORT_SET_CLR
|
||||
*_dcPort |= _dcPinMaskSet;
|
||||
#endif // end !HAS_PORT_SET_CLR
|
||||
#else // !USE_FAST_PINIO
|
||||
digitalWrite(_dc, HIGH);
|
||||
#endif // end !USE_FAST_PINIO
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_SWSPI::DC_LOW(void)
|
||||
{
|
||||
#if defined(USE_FAST_PINIO)
|
||||
#if defined(HAS_PORT_SET_CLR)
|
||||
#if defined(KINETISK)
|
||||
*_dcPortClr = 1;
|
||||
#else // !KINETISK
|
||||
*_dcPortClr = _dcPinMask;
|
||||
#endif // end !KINETISK
|
||||
#else // !HAS_PORT_SET_CLR
|
||||
*_dcPort &= _dcPinMaskClr;
|
||||
#endif // end !HAS_PORT_SET_CLR
|
||||
#else // !USE_FAST_PINIO
|
||||
digitalWrite(_dc, LOW);
|
||||
#endif // end !USE_FAST_PINIO
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_SWSPI::CS_HIGH(void)
|
||||
{
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
#if defined(USE_FAST_PINIO)
|
||||
#if defined(HAS_PORT_SET_CLR)
|
||||
#if defined(KINETISK)
|
||||
*_csPortSet = 1;
|
||||
#else // !KINETISK
|
||||
*_csPortSet = _csPinMask;
|
||||
#endif // end !KINETISK
|
||||
#else // !HAS_PORT_SET_CLR
|
||||
*_csPort |= _csPinMaskSet;
|
||||
#endif // end !HAS_PORT_SET_CLR
|
||||
#else // !USE_FAST_PINIO
|
||||
digitalWrite(_cs, HIGH);
|
||||
#endif // end !USE_FAST_PINIO
|
||||
}
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_SWSPI::CS_LOW(void)
|
||||
{
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
#if defined(USE_FAST_PINIO)
|
||||
#if defined(HAS_PORT_SET_CLR)
|
||||
#if defined(KINETISK)
|
||||
*_csPortClr = 1;
|
||||
#else // !KINETISK
|
||||
*_csPortClr = _csPinMask;
|
||||
#endif // end !KINETISK
|
||||
#else // !HAS_PORT_SET_CLR
|
||||
*_csPort &= _csPinMaskClr;
|
||||
#endif // end !HAS_PORT_SET_CLR
|
||||
#else // !USE_FAST_PINIO
|
||||
digitalWrite(_cs, LOW);
|
||||
#endif // end !USE_FAST_PINIO
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Set the software (bitbang) SPI MOSI line HIGH.
|
||||
*/
|
||||
GFX_INLINE void Arduino_SWSPI::SPI_MOSI_HIGH(void)
|
||||
{
|
||||
#if defined(USE_FAST_PINIO)
|
||||
#if defined(HAS_PORT_SET_CLR)
|
||||
#if defined(KINETISK)
|
||||
*_mosiPortSet = 1;
|
||||
#else // !KINETISK
|
||||
*_mosiPortSet = _mosiPinMask;
|
||||
#endif
|
||||
#else // !HAS_PORT_SET_CLR
|
||||
*_mosiPort |= _mosiPinMaskSet;
|
||||
#endif // end !HAS_PORT_SET_CLR
|
||||
#else // !USE_FAST_PINIO
|
||||
digitalWrite(_mosi, HIGH);
|
||||
#endif // end !USE_FAST_PINIO
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Set the software (bitbang) SPI MOSI line LOW.
|
||||
*/
|
||||
GFX_INLINE void Arduino_SWSPI::SPI_MOSI_LOW(void)
|
||||
{
|
||||
#if defined(USE_FAST_PINIO)
|
||||
#if defined(HAS_PORT_SET_CLR)
|
||||
#if defined(KINETISK)
|
||||
*_mosiPortClr = 1;
|
||||
#else // !KINETISK
|
||||
*_mosiPortClr = _mosiPinMask;
|
||||
#endif
|
||||
#else // !HAS_PORT_SET_CLR
|
||||
*_mosiPort &= _mosiPinMaskClr;
|
||||
#endif // end !HAS_PORT_SET_CLR
|
||||
#else // !USE_FAST_PINIO
|
||||
digitalWrite(_mosi, LOW);
|
||||
#endif // end !USE_FAST_PINIO
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Set the software (bitbang) SPI SCK line HIGH.
|
||||
*/
|
||||
GFX_INLINE void Arduino_SWSPI::SPI_SCK_HIGH(void)
|
||||
{
|
||||
#if defined(USE_FAST_PINIO)
|
||||
#if defined(HAS_PORT_SET_CLR)
|
||||
#if defined(KINETISK)
|
||||
*_sckPortSet = 1;
|
||||
#else // !KINETISK
|
||||
*_sckPortSet = _sckPinMask;
|
||||
#if defined(__IMXRT1052__) || defined(__IMXRT1062__) // Teensy 4.x
|
||||
for (volatile uint8_t i = 0; i < 1; i++)
|
||||
;
|
||||
#endif
|
||||
#endif
|
||||
#else // !HAS_PORT_SET_CLR
|
||||
*_sckPort |= _sckPinMaskSet;
|
||||
#endif // end !HAS_PORT_SET_CLR
|
||||
#else // !USE_FAST_PINIO
|
||||
digitalWrite(_sck, HIGH);
|
||||
#endif // end !USE_FAST_PINIO
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Set the software (bitbang) SPI SCK line LOW.
|
||||
*/
|
||||
GFX_INLINE void Arduino_SWSPI::SPI_SCK_LOW(void)
|
||||
{
|
||||
#if defined(USE_FAST_PINIO)
|
||||
#if defined(HAS_PORT_SET_CLR)
|
||||
#if defined(KINETISK)
|
||||
*_sckPortClr = 1;
|
||||
#else // !KINETISK
|
||||
*_sckPortClr = _sckPinMask;
|
||||
#if defined(__IMXRT1052__) || defined(__IMXRT1062__) // Teensy 4.x
|
||||
for (volatile uint8_t i = 0; i < 1; i++)
|
||||
;
|
||||
#endif
|
||||
#endif
|
||||
#else // !HAS_PORT_SET_CLR
|
||||
*_sckPort &= _sckPinMaskClr;
|
||||
#endif // end !HAS_PORT_SET_CLR
|
||||
#else // !USE_FAST_PINIO
|
||||
digitalWrite(_sck, LOW);
|
||||
#endif // end !USE_FAST_PINIO
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Read the state of the software (bitbang) SPI MISO line.
|
||||
@return true if HIGH, false if LOW.
|
||||
*/
|
||||
GFX_INLINE bool Arduino_SWSPI::SPI_MISO_READ(void)
|
||||
{
|
||||
#if defined(USE_FAST_PINIO)
|
||||
#if defined(KINETISK)
|
||||
return *_misoPort;
|
||||
#else // !KINETISK
|
||||
return *_misoPort & _misoPinMask;
|
||||
#endif // end !KINETISK
|
||||
#else // !USE_FAST_PINIO
|
||||
return digitalRead(_miso);
|
||||
#endif // end !USE_FAST_PINIO
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* start rewrite from:
|
||||
* https://github.com/adafruit/Adafruit-GFX-Library.git
|
||||
*/
|
||||
#ifndef _ARDUINO_SWSPI_H_
|
||||
#define _ARDUINO_SWSPI_H_
|
||||
|
||||
#include "Arduino_DataBus.h"
|
||||
|
||||
class Arduino_SWSPI : public Arduino_DataBus
|
||||
{
|
||||
public:
|
||||
Arduino_SWSPI(int8_t dc, int8_t cs, int8_t _sck, int8_t _mosi, int8_t _miso = GFX_NOT_DEFINED); // Constructor
|
||||
|
||||
bool begin(int32_t speed = GFX_NOT_DEFINED, int8_t dataMode = GFX_NOT_DEFINED) override;
|
||||
void beginWrite() override;
|
||||
void endWrite() override;
|
||||
void writeCommand(uint8_t) override;
|
||||
void writeCommand16(uint16_t) override;
|
||||
void writeCommandBytes(uint8_t *data, uint32_t len) override;
|
||||
void write(uint8_t) override;
|
||||
void write16(uint16_t) override;
|
||||
void writeRepeat(uint16_t p, uint32_t len) override;
|
||||
void writePixels(uint16_t *data, uint32_t len) override;
|
||||
|
||||
#if !defined(LITTLE_FOOT_PRINT)
|
||||
void writeBytes(uint8_t *data, uint32_t len) override;
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
|
||||
private:
|
||||
GFX_INLINE void WRITE9BITCOMMAND(uint8_t c);
|
||||
GFX_INLINE void WRITE9BITDATA(uint8_t d);
|
||||
GFX_INLINE void WRITE(uint8_t d);
|
||||
GFX_INLINE void WRITE16(uint16_t d);
|
||||
GFX_INLINE void WRITE9BITREPEAT(uint16_t p, uint32_t len);
|
||||
GFX_INLINE void WRITEREPEAT(uint16_t p, uint32_t len);
|
||||
GFX_INLINE void DC_HIGH(void);
|
||||
GFX_INLINE void DC_LOW(void);
|
||||
GFX_INLINE void CS_HIGH(void);
|
||||
GFX_INLINE void CS_LOW(void);
|
||||
GFX_INLINE void SPI_MOSI_HIGH(void);
|
||||
GFX_INLINE void SPI_MOSI_LOW(void);
|
||||
GFX_INLINE void SPI_SCK_HIGH(void);
|
||||
GFX_INLINE void SPI_SCK_LOW(void);
|
||||
GFX_INLINE bool SPI_MISO_READ(void);
|
||||
|
||||
int8_t _dc, _cs;
|
||||
int8_t _sck, _mosi, _miso;
|
||||
|
||||
// CLASS INSTANCE VARIABLES --------------------------------------------
|
||||
|
||||
// Here be dragons! There's a big union of three structures here --
|
||||
// one each for hardware SPI, software (bitbang) SPI, and parallel
|
||||
// interfaces. This is to save some memory, since a display's connection
|
||||
// will be only one of these. The order of some things is a little weird
|
||||
// in an attempt to get values to align and pack better in RAM.
|
||||
|
||||
#if defined(USE_FAST_PINIO)
|
||||
#if defined(HAS_PORT_SET_CLR)
|
||||
PORTreg_t _csPortSet; ///< PORT register for chip select SET
|
||||
PORTreg_t _csPortClr; ///< PORT register for chip select CLEAR
|
||||
PORTreg_t _dcPortSet; ///< PORT register for data/command SET
|
||||
PORTreg_t _dcPortClr; ///< PORT register for data/command CLEAR
|
||||
PORTreg_t _mosiPortSet; ///< PORT register for MOSI SET
|
||||
PORTreg_t _mosiPortClr; ///< PORT register for MOSI CLEAR
|
||||
PORTreg_t _sckPortSet; ///< PORT register for SCK SET
|
||||
PORTreg_t _sckPortClr; ///< PORT register for SCK CLEAR
|
||||
#if !defined(KINETISK)
|
||||
ARDUINOGFX_PORT_t _csPinMask; ///< Bitmask for chip select
|
||||
ARDUINOGFX_PORT_t _dcPinMask; ///< Bitmask for data/command
|
||||
ARDUINOGFX_PORT_t _mosiPinMask; ///< Bitmask for MOSI
|
||||
ARDUINOGFX_PORT_t _sckPinMask; ///< Bitmask for SCK
|
||||
#endif // !KINETISK
|
||||
#else // !HAS_PORT_SET_CLR
|
||||
PORTreg_t _mosiPort; ///< PORT register for MOSI
|
||||
PORTreg_t _sckPort; ///< PORT register for SCK
|
||||
PORTreg_t _csPort; ///< PORT register for chip select
|
||||
PORTreg_t _dcPort; ///< PORT register for data/command
|
||||
ARDUINOGFX_PORT_t _csPinMaskSet; ///< Bitmask for chip select SET (OR)
|
||||
ARDUINOGFX_PORT_t _csPinMaskClr; ///< Bitmask for chip select CLEAR (AND)
|
||||
ARDUINOGFX_PORT_t _dcPinMaskSet; ///< Bitmask for data/command SET (OR)
|
||||
ARDUINOGFX_PORT_t _dcPinMaskClr; ///< Bitmask for data/command CLEAR (AND)
|
||||
ARDUINOGFX_PORT_t _mosiPinMaskSet; ///< Bitmask for MOSI SET (OR)
|
||||
ARDUINOGFX_PORT_t _mosiPinMaskClr; ///< Bitmask for MOSI CLEAR (AND)
|
||||
ARDUINOGFX_PORT_t _sckPinMaskSet; ///< Bitmask for SCK SET (OR bitmask)
|
||||
ARDUINOGFX_PORT_t _sckPinMaskClr; ///< Bitmask for SCK CLEAR (AND)
|
||||
#endif // HAS_PORT_SET_CLR
|
||||
PORTreg_t _misoPort; ///< PORT (PIN) register for MISO
|
||||
#if !defined(KINETISK)
|
||||
ARDUINOGFX_PORT_t _misoPinMask; ///< Bitmask for MISO
|
||||
#endif // !KINETISK
|
||||
#endif // defined(USE_FAST_PINIO)
|
||||
};
|
||||
|
||||
#endif // _ARDUINO_SWSPI_H_
|
||||
@@ -0,0 +1,249 @@
|
||||
#include "Arduino_UNOPAR8.h"
|
||||
|
||||
// for MCUFriend UNO kind of shields. -jz-
|
||||
#if defined(ARDUINO_AVR_UNO) || defined(ARDUINO_AVR_MEGA2560) || defined(ARDUINO_UNOR4_MINIMA) || defined(ARDUINO_UNOR4_WIFI)
|
||||
|
||||
Arduino_UNOPAR8::Arduino_UNOPAR8()
|
||||
{
|
||||
}
|
||||
|
||||
bool Arduino_UNOPAR8::begin(int32_t, int8_t)
|
||||
{
|
||||
pinMode(A2, OUTPUT); // LCD DC
|
||||
digitalWrite(A2, HIGH); // Data mode
|
||||
|
||||
pinMode(A3, OUTPUT); // LCD CS
|
||||
digitalWrite(A3, HIGH); // Disable chip select
|
||||
|
||||
pinMode(A1, OUTPUT); // LCD WR
|
||||
digitalWrite(A1, HIGH); // Set write strobe high (inactive)
|
||||
|
||||
pinMode(A0, OUTPUT); // LCD RD
|
||||
digitalWrite(A0, HIGH); // Disable RD
|
||||
|
||||
pinMode(8, OUTPUT); // LCD D0
|
||||
pinMode(9, OUTPUT); // LCD D1
|
||||
pinMode(2, OUTPUT); // LCD D2
|
||||
pinMode(3, OUTPUT); // LCD D3
|
||||
pinMode(4, OUTPUT); // LCD D4
|
||||
pinMode(5, OUTPUT); // LCD D5
|
||||
pinMode(6, OUTPUT); // LCD D6
|
||||
pinMode(7, OUTPUT); // LCD D7
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Arduino_UNOPAR8::beginWrite()
|
||||
{
|
||||
DC_HIGH();
|
||||
CS_LOW();
|
||||
}
|
||||
|
||||
void Arduino_UNOPAR8::endWrite()
|
||||
{
|
||||
CS_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_UNOPAR8::writeCommand(uint8_t c)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
WRITE(c);
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_UNOPAR8::writeCommand16(uint16_t c)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
_data16.value = c;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_UNOPAR8::writeCommandBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
DC_LOW();
|
||||
|
||||
while (len--)
|
||||
{
|
||||
WRITE(*data++);
|
||||
}
|
||||
|
||||
DC_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_UNOPAR8::write(uint8_t d)
|
||||
{
|
||||
WRITE(d);
|
||||
}
|
||||
|
||||
void Arduino_UNOPAR8::write16(uint16_t d)
|
||||
{
|
||||
_data16.value = d;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
|
||||
void Arduino_UNOPAR8::writeRepeat(uint16_t p, uint32_t len)
|
||||
{
|
||||
_data16.value = p;
|
||||
if (_data16.msb == _data16.lsb)
|
||||
{
|
||||
#if defined(ARDUINO_AVR_UNO)
|
||||
WRITE(_data16.msb);
|
||||
// WR_STB
|
||||
PORTC &= ~_BV(1);
|
||||
PORTC |= _BV(1);
|
||||
while (--len)
|
||||
{
|
||||
// WR_STB
|
||||
PORTC &= ~_BV(1);
|
||||
PORTC |= _BV(1);
|
||||
// WR_STB
|
||||
PORTC &= ~_BV(1);
|
||||
PORTC |= _BV(1);
|
||||
}
|
||||
#elif defined(ARDUINO_AVR_MEGA2560)
|
||||
WRITE(_data16.msb);
|
||||
// WR_STB
|
||||
PORTF &= ~_BV(1);
|
||||
PORTF |= _BV(1);
|
||||
while (--len)
|
||||
{
|
||||
// WR_STB
|
||||
PORTF &= ~_BV(1);
|
||||
PORTF |= _BV(1);
|
||||
// WR_STB
|
||||
PORTF &= ~_BV(1);
|
||||
PORTF |= _BV(1);
|
||||
}
|
||||
#elif defined(ARDUINO_UNOR4_MINIMA) || defined(ARDUINO_UNOR4_WIFI)
|
||||
WRITE(_data16.msb);
|
||||
// WR_STB
|
||||
R_PORT0->PORR = bit(0);
|
||||
R_PORT0->POSR = bit(0);
|
||||
while (--len)
|
||||
{
|
||||
// WR_STB
|
||||
R_PORT0->PORR = bit(0);
|
||||
R_PORT0->POSR = bit(0);
|
||||
// WR_STB
|
||||
R_PORT0->PORR = bit(0);
|
||||
R_PORT0->POSR = bit(0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_UNOPAR8::writeBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
WRITE(*data++);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_UNOPAR8::writePixels(uint16_t *data, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
_data16.value = *data++;
|
||||
WRITE(_data16.msb);
|
||||
WRITE(_data16.lsb);
|
||||
}
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_UNOPAR8::WRITE(uint8_t d)
|
||||
{
|
||||
#if defined(ARDUINO_AVR_UNO)
|
||||
PORTB = (PORTB & 0xFC) | (d & 0x03); // LCD D0-1
|
||||
PORTD = (PORTD & 0x03) | (d & 0xFC); // LCD D2-7
|
||||
// WR_STB
|
||||
PORTC &= ~_BV(1);
|
||||
PORTC |= _BV(1);
|
||||
#elif defined(ARDUINO_AVR_MEGA2560)
|
||||
PORTH = (PORTH & 0x87) | ((d & 0x03) << 5) | ((d & 0xC0) >> 3); // LCD D0-1, D6-7
|
||||
PORTE = (PORTE & 0xC7) | ((d & 0x0C) << 2) | ((d & 0x20) >> 2); // LCD D2-3, D5
|
||||
(d & 0x10) ? PORTG |= _BV(5) : PORTG &= ~_BV(5); // LCD D4
|
||||
// WR_STB
|
||||
PORTF &= ~_BV(1);
|
||||
PORTF |= _BV(1);
|
||||
#elif defined(ARDUINO_UNOR4_MINIMA)
|
||||
R_PORT3->PORR = 0x18;
|
||||
R_PORT3->POSR = (d & 0x01) << 4; // LCD D0
|
||||
R_PORT3->POSR = (d & 0x02) << 2; // LCD D1
|
||||
R_PORT1->PORR = 0x00FC;
|
||||
R_PORT1->POSR = _xset_mask[d >> 2]; // LCD D2-7
|
||||
// WR_STB
|
||||
R_PORT0->PORR = bit(0);
|
||||
R_PORT0->POSR = bit(0);
|
||||
#elif defined(ARDUINO_UNOR4_WIFI)
|
||||
R_PORT3->PORR = 0x18;
|
||||
R_PORT3->POSR = (d & 0x01) << 4; // LCD D0
|
||||
R_PORT3->POSR = (d & 0x02) << 2; // LCD D1
|
||||
R_PORT1->PORR = 0x18F0;
|
||||
R_PORT1->POSR = ((d & 0x3C) << 2) | ((d & 0xC0) << 5); // LCD D2-7
|
||||
// WR_STB
|
||||
R_PORT0->PORR = bit(0);
|
||||
R_PORT0->POSR = bit(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/******** low level bit twiddling **********/
|
||||
|
||||
GFX_INLINE void Arduino_UNOPAR8::DC_HIGH(void)
|
||||
{
|
||||
#if defined(ARDUINO_AVR_UNO)
|
||||
PORTC |= _BV(2); // RS_H;
|
||||
#elif defined(ARDUINO_AVR_MEGA2560)
|
||||
PORTF |= _BV(2); // RS_H;
|
||||
#elif defined(ARDUINO_UNOR4_MINIMA) || defined(ARDUINO_UNOR4_WIFI)
|
||||
R_PORT0->POSR = bit(1);
|
||||
#endif
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_UNOPAR8::DC_LOW(void)
|
||||
{
|
||||
#if defined(ARDUINO_AVR_UNO)
|
||||
PORTC &= ~_BV(2); // RS_L;
|
||||
#elif defined(ARDUINO_AVR_MEGA2560)
|
||||
PORTF &= ~_BV(2); // RS_L;
|
||||
#elif defined(ARDUINO_UNOR4_MINIMA) || defined(ARDUINO_UNOR4_WIFI)
|
||||
R_PORT0->PORR = bit(1);
|
||||
#endif
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_UNOPAR8::CS_HIGH(void)
|
||||
{
|
||||
#if defined(ARDUINO_AVR_UNO)
|
||||
PORTC |= _BV(3); // CS_H;
|
||||
#elif defined(ARDUINO_AVR_MEGA2560)
|
||||
PORTF |= _BV(3); // CS_H;
|
||||
#elif defined(ARDUINO_UNOR4_MINIMA) || defined(ARDUINO_UNOR4_WIFI)
|
||||
R_PORT0->POSR = bit(2);
|
||||
#endif
|
||||
}
|
||||
|
||||
GFX_INLINE void Arduino_UNOPAR8::CS_LOW(void)
|
||||
{
|
||||
#if defined(ARDUINO_AVR_UNO)
|
||||
PORTC &= ~_BV(3); // CS_L;
|
||||
#elif defined(ARDUINO_AVR_MEGA2560)
|
||||
PORTF &= ~_BV(3); // CS_L;
|
||||
#elif defined(ARDUINO_UNOR4_MINIMA) || defined(ARDUINO_UNOR4_WIFI)
|
||||
R_PORT0->PORR = bit(2);
|
||||
#endif
|
||||
}
|
||||
#endif // #if defined(ARDUINO_AVR_UNO) || defined(ARDUINO_AVR_MEGA2560) || defined(ARDUINO_UNOR4_MINIMA) || defined(ARDUINO_UNOR4_WIFI)
|
||||
@@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
#include "Arduino_DataBus.h"
|
||||
|
||||
// for MCUFriend UNO kind of shields. -jz-
|
||||
#if defined(ARDUINO_AVR_UNO) || defined(ARDUINO_AVR_MEGA2560) || defined(ARDUINO_UNOR4_MINIMA) || defined(ARDUINO_UNOR4_WIFI)
|
||||
|
||||
#if defined(ARDUINO_UNOR4_MINIMA)
|
||||
static const uint16_t _xset_mask[] = {
|
||||
// 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7
|
||||
0x0000, 0x0020, 0x0010, 0x0030, 0x0008, 0x0028, 0x0018, 0x0038,
|
||||
0x0004, 0x0024, 0x0014, 0x0034, 0x000C, 0x002C, 0x001C, 0x003C,
|
||||
0x0040, 0x0060, 0x0050, 0x0070, 0x0048, 0x0068, 0x0058, 0x0078,
|
||||
0x0044, 0x0064, 0x0054, 0x0074, 0x004C, 0x006C, 0x005C, 0x007C,
|
||||
0x0080, 0x00A0, 0x0090, 0x00B0, 0x0088, 0x00A8, 0x0098, 0x00B8,
|
||||
0x0084, 0x00A4, 0x0094, 0x00B4, 0x008C, 0x00AC, 0x009C, 0x00BC,
|
||||
0x00C0, 0x00E0, 0x00D0, 0x00F0, 0x00C8, 0x00E8, 0x00D8, 0x00F8,
|
||||
0x00C4, 0x00E4, 0x00D4, 0x00F4, 0x00CC, 0x00EC, 0x00DC, 0x00FC};
|
||||
#endif
|
||||
|
||||
class Arduino_UNOPAR8 : public Arduino_DataBus
|
||||
{
|
||||
public:
|
||||
Arduino_UNOPAR8(); // Constructor
|
||||
|
||||
bool begin(int32_t speed = GFX_NOT_DEFINED, int8_t dataMode = GFX_NOT_DEFINED) override;
|
||||
void beginWrite() override;
|
||||
void endWrite() override;
|
||||
void writeCommand(uint8_t) override;
|
||||
void writeCommand16(uint16_t) override;
|
||||
void writeCommandBytes(uint8_t *data, uint32_t len) override;
|
||||
void write(uint8_t) override;
|
||||
void write16(uint16_t) override;
|
||||
void writeRepeat(uint16_t p, uint32_t len) override;
|
||||
void writeBytes(uint8_t *data, uint32_t len) override;
|
||||
void writePixels(uint16_t *data, uint32_t len) override;
|
||||
|
||||
private:
|
||||
GFX_INLINE void WRITE(uint8_t d);
|
||||
GFX_INLINE void DC_HIGH(void);
|
||||
GFX_INLINE void DC_LOW(void);
|
||||
GFX_INLINE void CS_HIGH(void);
|
||||
GFX_INLINE void CS_LOW(void);
|
||||
};
|
||||
|
||||
#endif // #if defined(ARDUINO_AVR_UNO) || defined(ARDUINO_AVR_MEGA2560) || defined(ARDUINO_UNOR4_MINIMA) || defined(ARDUINO_UNOR4_WIFI)
|
||||
@@ -0,0 +1,147 @@
|
||||
// Databus Adapter for the Arduino Wire bus (I2C bus)
|
||||
|
||||
#include "Arduino_Wire.h"
|
||||
|
||||
Arduino_Wire::
|
||||
Arduino_Wire(uint8_t i2c_addr, int8_t commandPrefix, int8_t dataPrefix, TwoWire *wire)
|
||||
: _i2c_addr(i2c_addr), _command_prefix(commandPrefix), _data_prefix(dataPrefix), _wire(wire) {}
|
||||
|
||||
bool Arduino_Wire::begin(int32_t speed, int8_t)
|
||||
{
|
||||
// printf("Wire::begin _command_prefix=0x%02x _data_prefix=0x%02x.\n", _command_prefix, _data_prefix);
|
||||
|
||||
if (speed != GFX_NOT_DEFINED)
|
||||
{
|
||||
_speed = speed;
|
||||
_wire->setClock(_speed);
|
||||
}
|
||||
|
||||
_wire->begin();
|
||||
|
||||
// find device
|
||||
_wire->beginTransmission(_i2c_addr);
|
||||
if (_wire->endTransmission())
|
||||
{
|
||||
// printf("Wire::Device not found.\n");
|
||||
is_found = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
is_found = true;
|
||||
}
|
||||
|
||||
return is_found;
|
||||
}
|
||||
|
||||
void Arduino_Wire::beginWrite()
|
||||
{
|
||||
// printf("Wire::beginWrite()\n");
|
||||
if (_speed != GFX_NOT_DEFINED)
|
||||
{
|
||||
_wire->setClock(_speed);
|
||||
}
|
||||
_wire->beginTransmission(_i2c_addr);
|
||||
}
|
||||
|
||||
void Arduino_Wire::endWrite()
|
||||
{
|
||||
// printf("Wire::endWrite()\n");
|
||||
_wire->endTransmission();
|
||||
}
|
||||
|
||||
void Arduino_Wire::write(uint8_t d)
|
||||
{
|
||||
// printf("Wire::write(0x%02x)\n", d);
|
||||
_wire->write(d);
|
||||
}
|
||||
|
||||
void Arduino_Wire::writeCommand(uint8_t c)
|
||||
{
|
||||
// printf("Wire::writeCommand(0x%02x 0x%02x)\n", _command_prefix, c);
|
||||
_wire->write(_command_prefix);
|
||||
_wire->write(c);
|
||||
}
|
||||
|
||||
void Arduino_Wire::writeCommand16(uint16_t)
|
||||
{
|
||||
// printf("Wire::writeCommand16()\n");
|
||||
// not implemented.
|
||||
}
|
||||
|
||||
void Arduino_Wire::writeCommandBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
// printf("Wire::writeCommandBytes(...)\n");
|
||||
uint16_t bytesOut;
|
||||
|
||||
_wire->write(_command_prefix);
|
||||
bytesOut = 1;
|
||||
|
||||
while (len--)
|
||||
{
|
||||
if (bytesOut >= TWI_BUFFER_LENGTH)
|
||||
{
|
||||
// finish this packet and start a new one.
|
||||
_wire->endTransmission();
|
||||
_wire->beginTransmission(_i2c_addr);
|
||||
_wire->write(_command_prefix);
|
||||
bytesOut = 1;
|
||||
}
|
||||
_wire->write(*data++);
|
||||
bytesOut++;
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_Wire::write16(uint16_t)
|
||||
{
|
||||
// printf("Wire::write16()\n");
|
||||
// not implemented
|
||||
}
|
||||
|
||||
void Arduino_Wire::writeRepeat(uint16_t, uint32_t)
|
||||
{
|
||||
// printf("Wire::writeRepeat()\n");
|
||||
// not implemented
|
||||
}
|
||||
|
||||
void Arduino_Wire::writePixels(uint16_t *, uint32_t)
|
||||
{
|
||||
// printf("Wire::writePixels()\n");
|
||||
// not implemented
|
||||
}
|
||||
|
||||
// write data to the bus using the data prefix
|
||||
// when len exceeds the TWI_BUFFER_LENGTH then a new transfer protocol is started.
|
||||
void Arduino_Wire::writeBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
// printf("Wire::writeBytes(...)\n");
|
||||
uint16_t bytesOut = 0;
|
||||
|
||||
_wire->write(_data_prefix);
|
||||
bytesOut++;
|
||||
|
||||
while (len--)
|
||||
{
|
||||
if (bytesOut >= TWI_BUFFER_LENGTH)
|
||||
{
|
||||
// finish this packet and start a new one.
|
||||
_wire->endTransmission();
|
||||
_wire->beginTransmission(_i2c_addr);
|
||||
bytesOut = 0;
|
||||
_wire->write(_data_prefix);
|
||||
bytesOut++;
|
||||
}
|
||||
_wire->write(*data++);
|
||||
bytesOut++;
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_Wire::writeRegister(uint8_t, uint8_t *, size_t)
|
||||
{
|
||||
// printf("Wire::writeRegister()\n");
|
||||
}
|
||||
|
||||
uint8_t Arduino_Wire::readRegister(uint8_t, uint8_t *, size_t)
|
||||
{
|
||||
// printf("Wire::readRegister()\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
// Databus Adapter for the Arduino Wire bus (I2C bus)
|
||||
|
||||
#ifndef _Arduino_Wire_H_
|
||||
#define _Arduino_Wire_H_
|
||||
|
||||
#include "Arduino_DataBus.h"
|
||||
#include <Wire.h>
|
||||
|
||||
#ifndef TWI_BUFFER_LENGTH
|
||||
#if defined(I2C_BUFFER_LENGTH)
|
||||
#define TWI_BUFFER_LENGTH I2C_BUFFER_LENGTH
|
||||
#else
|
||||
#define TWI_BUFFER_LENGTH 32
|
||||
#endif
|
||||
#endif
|
||||
class Arduino_Wire : public Arduino_DataBus
|
||||
{
|
||||
public:
|
||||
Arduino_Wire(uint8_t i2c_addr, int8_t commandPrefix, int8_t dataPrefix, TwoWire *wire = &Wire);
|
||||
|
||||
bool begin(int32_t speed = GFX_NOT_DEFINED, int8_t dataMode = GFX_NOT_DEFINED) override;
|
||||
void beginWrite() override;
|
||||
void endWrite() override;
|
||||
void writeCommand(uint8_t) override;
|
||||
void writeCommand16(uint16_t) override;
|
||||
void writeCommandBytes(uint8_t *data, uint32_t len) override;
|
||||
void write(uint8_t) override;
|
||||
void write16(uint16_t) override;
|
||||
void writeRepeat(uint16_t p, uint32_t len) override;
|
||||
void writeBytes(uint8_t *data, uint32_t len) override;
|
||||
void writePixels(uint16_t *data, uint32_t len) override;
|
||||
|
||||
protected:
|
||||
void writeRegister(uint8_t reg, uint8_t *data, size_t len);
|
||||
uint8_t readRegister(uint8_t reg, uint8_t *data, size_t len);
|
||||
|
||||
uint8_t output_buf = 0;
|
||||
bool is_found;
|
||||
|
||||
uint8_t _i2c_addr;
|
||||
uint8_t _command_prefix;
|
||||
uint8_t _data_prefix;
|
||||
TwoWire *_wire;
|
||||
|
||||
int32_t _speed;
|
||||
private:
|
||||
};
|
||||
|
||||
#endif // _Arduino_Wire_H_
|
||||
@@ -0,0 +1,255 @@
|
||||
#include "Arduino_XCA9554SWSPI.h"
|
||||
|
||||
// #define XCA9554_DEBUG
|
||||
|
||||
Arduino_XCA9554SWSPI::Arduino_XCA9554SWSPI(int8_t rst, int8_t cs, int8_t sck, int8_t mosi, TwoWire *wire, uint8_t i2c_addr)
|
||||
: _rst(rst), _cs(cs), _sck(sck), _mosi(mosi), _wire(wire), _i2c_addr(i2c_addr)
|
||||
{
|
||||
}
|
||||
|
||||
bool Arduino_XCA9554SWSPI::begin(int32_t, int8_t)
|
||||
{
|
||||
_wire->begin();
|
||||
_wire->beginTransmission(_i2c_addr);
|
||||
if (!_wire->endTransmission())
|
||||
{
|
||||
// println("Found xCA9554");
|
||||
is_found = true;
|
||||
|
||||
uint8_t d = 0;
|
||||
writeRegister(XCA9554_INVERSION_PORT_REG, &d, 1); // no invert
|
||||
d = 0xFF;
|
||||
writeRegister(XCA9554_CONFIG_PORT_REG, &d, 1); // all input
|
||||
d = 0x0;
|
||||
writeRegister(XCA9554_OUTPUT_PORT_REG, &d, 1); // all low
|
||||
output_buf = 0;
|
||||
|
||||
if (_rst != GFX_NOT_DEFINED)
|
||||
{
|
||||
this->pinMode(_rst, OUTPUT);
|
||||
this->digitalWrite(_rst, 0);
|
||||
delay(10);
|
||||
this->digitalWrite(_rst, 1);
|
||||
delay(100);
|
||||
}
|
||||
this->pinMode(_cs, OUTPUT);
|
||||
this->digitalWrite(_cs, 1);
|
||||
this->pinMode(_sck, OUTPUT);
|
||||
this->digitalWrite(_sck, 1);
|
||||
this->pinMode(_mosi, OUTPUT);
|
||||
this->digitalWrite(_mosi, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// println("xCA9554 not found");
|
||||
is_found = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Arduino_XCA9554SWSPI::beginWrite()
|
||||
{
|
||||
this->digitalWrite(_cs, 0);
|
||||
}
|
||||
|
||||
void Arduino_XCA9554SWSPI::endWrite()
|
||||
{
|
||||
this->digitalWrite(_cs, 1);
|
||||
}
|
||||
|
||||
void Arduino_XCA9554SWSPI::writeCommand(uint8_t c)
|
||||
{
|
||||
bool last_databit = 0;
|
||||
// D/C bit, command
|
||||
this->digitalWrite(_mosi, last_databit);
|
||||
this->digitalWrite(_sck, 0);
|
||||
this->digitalWrite(_sck, 1);
|
||||
|
||||
uint8_t bit = 0x80;
|
||||
while (bit)
|
||||
{
|
||||
if (c & bit)
|
||||
{
|
||||
if (last_databit != 1)
|
||||
{
|
||||
last_databit = 1;
|
||||
this->digitalWrite(_mosi, last_databit);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (last_databit != 0)
|
||||
{
|
||||
last_databit = 0;
|
||||
this->digitalWrite(_mosi, last_databit);
|
||||
}
|
||||
}
|
||||
this->digitalWrite(_sck, 0);
|
||||
bit >>= 1;
|
||||
this->digitalWrite(_sck, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_XCA9554SWSPI::writeCommand16(uint16_t)
|
||||
{
|
||||
}
|
||||
|
||||
void Arduino_XCA9554SWSPI::writeCommandBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
}
|
||||
|
||||
void Arduino_XCA9554SWSPI::write(uint8_t d)
|
||||
{
|
||||
bool last_databit = 1;
|
||||
// D/C bit, data
|
||||
this->digitalWrite(_mosi, last_databit);
|
||||
this->digitalWrite(_sck, 0);
|
||||
this->digitalWrite(_sck, 1);
|
||||
|
||||
uint8_t bit = 0x80;
|
||||
while (bit)
|
||||
{
|
||||
if (d & bit)
|
||||
{
|
||||
if (last_databit != 1)
|
||||
{
|
||||
last_databit = 1;
|
||||
this->digitalWrite(_mosi, last_databit);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (last_databit != 0)
|
||||
{
|
||||
last_databit = 0;
|
||||
this->digitalWrite(_mosi, last_databit);
|
||||
}
|
||||
}
|
||||
this->digitalWrite(_sck, 0);
|
||||
bit >>= 1;
|
||||
this->digitalWrite(_sck, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_XCA9554SWSPI::write16(uint16_t)
|
||||
{
|
||||
// not implemented
|
||||
}
|
||||
|
||||
void Arduino_XCA9554SWSPI::writeRepeat(uint16_t, uint32_t)
|
||||
{
|
||||
// not implemented
|
||||
}
|
||||
|
||||
void Arduino_XCA9554SWSPI::writeBytes(uint8_t *, uint32_t)
|
||||
{
|
||||
// not implemented
|
||||
}
|
||||
|
||||
void Arduino_XCA9554SWSPI::writePixels(uint16_t *, uint32_t)
|
||||
{
|
||||
// not implemented
|
||||
}
|
||||
|
||||
void Arduino_XCA9554SWSPI::writeRegister(uint8_t reg, uint8_t *data, size_t len)
|
||||
{
|
||||
|
||||
#ifdef XCA9554_DEBUG
|
||||
// printf("Writing to $%02X: ", reg);
|
||||
#endif
|
||||
_wire->beginTransmission(_i2c_addr);
|
||||
_wire->write(reg);
|
||||
for (size_t i = 0; i < len; i++)
|
||||
{
|
||||
_wire->write(data[i]);
|
||||
#ifdef XCA9554_DEBUG
|
||||
// printf("0x%02X, ", data[i]);
|
||||
#endif
|
||||
}
|
||||
#ifdef XCA9554_DEBUG
|
||||
// println();
|
||||
#endif
|
||||
_wire->endTransmission();
|
||||
}
|
||||
|
||||
uint8_t Arduino_XCA9554SWSPI::readRegister(uint8_t reg, uint8_t *data, size_t len)
|
||||
{
|
||||
_wire->beginTransmission(_i2c_addr);
|
||||
_wire->write(reg);
|
||||
#ifdef XCA9554_DEBUG
|
||||
// printf("Read from $%02X: ", reg);
|
||||
#endif
|
||||
_wire->endTransmission();
|
||||
_wire->requestFrom(_i2c_addr, len);
|
||||
size_t index = 0;
|
||||
while (index < len)
|
||||
{
|
||||
data[index++] = _wire->read();
|
||||
#ifdef XCA9554_DEBUG
|
||||
// printf("0x%02X, ", data[index-1]);
|
||||
#endif
|
||||
}
|
||||
#ifdef XCA9554_DEBUG
|
||||
// println();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Arduino_XCA9554SWSPI::pinMode(uint8_t pin, uint8_t mode)
|
||||
{
|
||||
if (is_found)
|
||||
{
|
||||
uint8_t port = 0;
|
||||
this->readRegister(XCA9554_CONFIG_PORT_REG, &port, 1);
|
||||
if (mode == OUTPUT)
|
||||
{
|
||||
port &= ~(1UL << pin);
|
||||
}
|
||||
else
|
||||
{
|
||||
port |= (1UL << pin);
|
||||
}
|
||||
this->writeRegister(XCA9554_CONFIG_PORT_REG, &port, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// println("xCA9554 not found");
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_XCA9554SWSPI::digitalWrite(uint8_t pin, uint8_t val)
|
||||
{
|
||||
if (is_found)
|
||||
{
|
||||
uint8_t reg_data = output_buf;
|
||||
|
||||
reg_data &= ~(1UL << pin);
|
||||
if (val == HIGH)
|
||||
{
|
||||
reg_data |= (1UL << pin);
|
||||
}
|
||||
this->writeRegister(XCA9554_OUTPUT_PORT_REG, ®_data, 1);
|
||||
output_buf = reg_data;
|
||||
}
|
||||
else
|
||||
{
|
||||
// println("xCA9554 not found");
|
||||
}
|
||||
}
|
||||
|
||||
int Arduino_XCA9554SWSPI::digitalRead(uint8_t pin)
|
||||
{
|
||||
if (is_found)
|
||||
{
|
||||
uint8_t port = 0;
|
||||
this->readRegister(XCA9554_INPUT_PORT_REG, &port, 1);
|
||||
// printf("Read 0x%02X\n", port);
|
||||
return (port & (1UL << pin)) ? HIGH : LOW;
|
||||
}
|
||||
else
|
||||
{
|
||||
// println("xCA9554 not found");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user