Compare commits

...

59 commits

Author SHA1 Message Date
Zhou Li
feeeb6b98e Merge branch 'bugfix/adc_cal' into 'master'
button: fix ADC changes for IDF version >= 5.

See merge request ae_group/esp-iot-solution!601
2022-08-04 11:00:47 +08:00
Vilem Zavodny
8ccd278a7e button: fix ADC changes for IDF version >= 5. Closes https://github.com/espressif/esp-iot-solution/pull/204 2022-08-02 14:20:32 +08:00
Zhou Li
b25236bff2 Merge branch 'feature/add_decompress_directory_and_decompressed_ota_example' into 'master'
Feat: add decompress directory and decompressed ota example

See merge request ae_group/esp-iot-solution!590
2022-07-11 19:28:38 +08:00
Wang Yu Xin
5e1e715395 feat: add decompress directory and examples 2022-07-11 10:15:40 +08:00
Zhou Li
fbf56a4c37 Merge branch 'feature/add_user_data_for_callbacks_of_button' into 'master'
button: rename usr_data to hardware_data && allow user to pass arbitrary data...

See merge request ae_group/esp-iot-solution!597
2022-07-05 10:37:58 +08:00
bennettbe
8aefe2dea3 button: rename usr_data to hardware_data && allow user to pass arbitrary data through callback. Closes https://github.com/espressif/esp-iot-solution/pull/200 2022-07-04 20:40:56 +08:00
Li Bo
4e481f0ee6 Merge branch 'docs/fix_doc_build_error' into 'master'
docs: fix doc build error in CI

See merge request ae_group/esp-iot-solution!596
2022-07-04 15:54:25 +08:00
Wang Fang
c18cf2ee8d docs: fix doc build error in CI 2022-07-04 14:16:02 +08:00
Zhou Li
a444d89f2b Merge branch 'docs/add_supported_socs_for_en_document_of_pwm_audio' into 'master'
docs: add supported socs for pwm audio

See merge request ae_group/esp-iot-solution!592
2022-06-17 16:39:57 +08:00
Zhou Li
7ccf82a262 Merge branch 'feature/add_camera_avi_recorder_example' into 'master'
feat: add camera avi video recorder example

See merge request ae_group/esp-iot-solution!584
2022-06-17 16:25:58 +08:00
zhouli
d6967b5f23 docs: add supported socs for pwm audio 2022-06-17 15:26:54 +08:00
Zhou Li
47df7d1205 Merge branch 'bugfix/update_for_idf_v5.0' into 'master'
bugfix: update components for compatible with idf 5.0

See merge request ae_group/esp-iot-solution!591
2022-06-17 11:47:27 +08:00
zhouli
b63def61df pwm_audio: fix the issue that does no sound on esp32c3 and esp32s3 && add script to upload to idf-component-manager 2022-06-16 20:22:33 +08:00
zhouli
b1a3bea83e fix(lvgl_gui): add mutex for lvgl thread-safe 2022-06-16 20:22:33 +08:00
zhouli
7a0eee234e bugfix: update components for compatible with idf 5.0 2022-06-16 20:21:47 +08:00
Wang Yu Xin
4fa6a72bd4 feat: add camera avi video recorder example 2022-06-14 14:41:33 +08:00
Zhou Li
5e5c4aa34c Merge branch 'fix/button-idf-v5' into 'master'
button: fix build on IDF version >= 5

See merge request ae_group/esp-iot-solution!586
2022-05-06 16:32:38 +08:00
Tomas Rezucha
fd38b168d6 button: fix build on IDF version >= 5. Closes https://github.com/espressif/esp-iot-solution/pull/184 2022-05-06 15:12:18 +08:00
Zhou Li
a5e1f94299 Merge branch 'feature/add_camera_basic_examples' into 'master'
feature(camera): add camera basic examples

See merge request ae_group/esp-iot-solution!577
2022-04-19 17:23:37 +08:00
Wang Yu Xin
39ddd5dd99 feature(camera): add camera basic examples 2022-04-19 17:23:37 +08:00
Zhou Li
ff6da11453 Merge branch 'feature/upload_cmps_gh_action' into 'master'
ci: Upload GH action

See merge request ae_group/esp-iot-solution!582
2022-04-14 16:18:59 +08:00
Tomas Rezucha
2961285a8e ci: Upload GH action; Closes https://github.com/espressif/esp-iot-solution/pull/173 2022-04-14 15:20:07 +08:00
Zhou Li
ce1d460938 Merge branch 'feature/button-component-manager' into 'master'
button: Add idf-component-manager files

See merge request ae_group/esp-iot-solution!574
2022-03-08 14:08:54 +08:00
Tomas Rezucha
fae526efcd button: Add idf-component-manager files
Closes https://github.com/espressif/esp-iot-solution/pull/138
2022-03-08 13:25:53 +08:00
Zhou Li
8607a04658 Merge branch 'docs/fix_display_example_code' into 'master'
docs: screen: function return before error is logged.

See merge request ae_group/esp-iot-solution!575
2022-03-08 11:22:31 +08:00
Zhou Li
1ffd999ac7 Merge branch 'feature/support_m5stack_lcd_for_screen_example' into 'master'
screen: Add support for M5Stack with ILI9342 display

See merge request ae_group/esp-iot-solution!576
2022-03-08 11:21:55 +08:00
Zhou Li
7133529944 Merge branch 'ssd1306-fix-no-cs-pin' into 'master'
screen: allow spi interface ignore CS wire

See merge request ae_group/esp-iot-solution!572
2022-03-07 22:51:34 +08:00
Zhou Li
1a913daf7a Merge branch 'feature/add_register_description_for_NT35510' into 'master'
screen: Add register description for NT35510 initial registers

See merge request ae_group/esp-iot-solution!573
2022-03-07 22:12:00 +08:00
Alex J Lennon
a49b22308f screen: Add support for M5Stack with ILI9342 display
- ILI9342 is 320x240 rather than 240x320 as ILI9341
- screen display needs to be inverted

Closes https://github.com/espressif/esp-iot-solution/pull/128
2022-03-07 22:05:51 +08:00
mei
bbdb938242 docs: screen: function return before error is logged.
Closes https://github.com/espressif/esp-iot-solution/pull/137
2022-03-07 21:47:55 +08:00
Duco Sebel
5e224b0939 screen: Add register description for NT35510 initial registers
Closes https://github.com/espressif/esp-iot-solution/pull/135
2022-03-07 21:21:35 +08:00
GitforZhangXL
47a494a356 screen: allow spi interface ignore CS wire
Closes https://github.com/espressif/esp-iot-solution/pull/158
2022-03-07 20:55:32 +08:00
Li Bo
611cca278a Merge branch 'doc/add_feedback_link' into 'master'
docs:add feedback links

See merge request rd/esp-iot-solution!568
2022-01-21 02:55:40 +00:00
Hao Ning
239cac6c75 docs:add feedback links 2022-01-20 17:32:16 +08:00
Zhou Li
ecd5e3247d Merge branch 'feature/add_8080_lcd_interface_for_s3' into 'master'
add screen 8080 interface for esp32s3

See merge request rd/esp-iot-solution!528
2022-01-20 05:44:29 +00:00
zhouli
0caa2de556 bus: add screen 8080 interface for esp32s3; closes #136 2022-01-19 13:58:46 +08:00
Zhou Li
527c817da0 Merge branch 'ci/update' into 'master'
replace master with v4.4

See merge request rd/esp-iot-solution!567
2022-01-18 12:29:30 +00:00
zhouli
67bc36471a replace master with v4.4 2022-01-18 19:34:07 +08:00
Zhou Li
8d917a8065 Merge branch 'feature/update_ci' into 'master'
update CI to check different chips and IDF version

See merge request rd/esp-iot-solution!535
2021-10-26 06:08:26 +00:00
zhouli
21350012e9 ci: update configuration 2021-10-20 19:40:37 +08:00
zhouli
63421202d6 fix: fix compatibility issues checked by ci; closes #133 2021-10-20 19:39:19 +08:00
zhouli
f26cfdcea2 ci: update ci to check all targets and idf 2021-10-20 19:38:56 +08:00
Zhan Zhaocheng
87e76fd295 Merge branch 'bugfix/docs_build' into 'master'
docs: pin setuptools<58 to resolve build failure due to removal of support for 2to3 during builds

See merge request rd/esp-iot-solution!543
2021-09-28 02:51:09 +00:00
Krzysztof
1f566dd957 docs: pin setuptools<58 to resolve build failure due to removal of support for 2to3 during builds 2021-09-18 17:34:55 +08:00
Li Qing Qiao
9849ac04ed Merge branch 'docs/fix_compilation_failure' into 'master'
add docutils to requirements.txt

See merge request rd/esp-iot-solution!542
2021-09-07 06:25:52 +00:00
zhouli
783b67ab24 add docutils to requirements.txt 2021-09-07 12:08:29 +08:00
Li Qing Qiao
2be68ac9bc Merge branch 'bugfix/optimize_touch_panel_display' into 'master'
touch_panel: revise calibration prompt

See merge request rd/esp-iot-solution!537
2021-08-23 02:58:37 +00:00
zhouli
68bfe795f9 touch_panel: revise calibration prompt; closes #108, closes #109 2021-08-20 19:46:52 +08:00
Zhan Zhaocheng
1770f425f8 Merge branch 'bugfix/revise_spi_dma_channel' into 'master'
bus: revise spi dma channel for idf v4.3

See merge request rd/esp-iot-solution!529
2021-08-16 11:54:44 +00:00
Zhan Zhaocheng
6b0b1c4cd4 Merge branch 'docs/update_screen_supported_table' into 'master'
docs: update doc for screen

See merge request rd/esp-iot-solution!516
2021-08-16 11:54:09 +00:00
Zhan Zhaocheng
db53a62a7a Merge branch 'bugfix/fix_dac_audio_compilation_error' into 'master'
dac_audio: fix compilation failure

See merge request rd/esp-iot-solution!527
2021-08-16 11:54:06 +00:00
zhouli
f664e8ed24 dac_audio: fix compilation failure 2021-08-12 20:49:16 +08:00
zhouli
e412568b84 revise spi dma channel for idf v4.3 2021-07-28 12:59:07 +08:00
TDA2030
c23ceeba00 docs: update doc for screen 2021-07-28 00:55:48 +08:00
Li Qing Qiao
e4672a5208 Merge branch 'bugfix/led_blink_switch_issue' into 'master'
bugfix(led_indicator): fix led blink switch bug

See merge request rd/esp-iot-solution!511
2021-06-11 11:10:07 +00:00
Li Qing Qiao
bd0702ddb6 Merge branch 'feature/add_ssd1963_screen' into 'master'
display: add ssd1963 ili9488 driver

See merge request rd/esp-iot-solution!506
2021-06-11 11:00:24 +00:00
Zhou Li
0f47c1d04a display: add ssd1963 ili9488 driver 2021-06-11 19:00:21 +08:00
Li Bo
34591c45d8 led(indicator): fix interference when stop blink 2021-05-14 20:17:32 +08:00
Li Bo
af4cd0980e led(indicator): fix dead when blink swith 2021-05-14 20:17:32 +08:00
192 changed files with 15352 additions and 1414 deletions

20
.github/workflows/upload_component.yml vendored Normal file
View file

@ -0,0 +1,20 @@
name: Push components to Espressif Component Service
on:
push:
branches:
- master
jobs:
upload_components:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
with:
submodules: 'recursive'
- name: Upload components to component service
uses: espressif/github-actions/upload_components@master
with:
directories: "components/button;components/audio/pwm_audio"
namespace: "espressif"
api_token: ${{ secrets.IDF_COMPONENT_API_TOKEN }}

82
.gitignore vendored
View file

@ -1,19 +1,19 @@
build/
.settings
.config
*.o
*.pyc
*.d
*.old
*.cproject
# gtags
GTAGS
GRTAGS
GPATH
# vscode setting
.vscode/
# emacs
.dir-locals.el
# emacs temp file suffixes
*~
.#*
\#*#
# eclipse setting
.settings
@ -21,6 +21,16 @@ GPATH
# MacOS directory files
.DS_Store
# Components Unit Test Apps files
components/**/build
components/**/sdkconfig
components/**/sdkconfig.old
# Example project files
examples/**/sdkconfig
examples/**/sdkconfig.old
examples/**/build
# Doc build artifacts
docs/**/_build/
docs/**/doxygen-warning-log.txt
@ -29,12 +39,10 @@ docs/**/sphinx-warning-log-sanitized.txt
docs/**/xml/
docs/**/xml_in/
docs/**/man/
docs/doxygen_sqlite3.db
# Example project files
examples/**/sdkconfig
examples/**/sdkconfig.old
examples/**/build
# Downloaded font files
docs/_static/DejaVuSans.ttf
docs/_static/NotoSansSC-Regular.otf
# Unit test app files
tools/unit-test-app/sdkconfig
@ -42,6 +50,52 @@ tools/unit-test-app/sdkconfig.old
tools/unit-test-app/build
tools/unit-test-app/builds
tools/unit-test-app/output
tools/unit-test-app/test_configs
# ESP-IDF library
build
# Unit Test CMake compile log folder
log_ut_cmake
# test application build files
tools/test_apps/**/build
tools/test_apps/**/sdkconfig
tools/test_apps/**/sdkconfig.old
# IDF monitor test
tools/test_idf_monitor/outputs
TEST_LOGS
# gcov coverage reports
*.gcda
*.gcno
coverage.info
coverage_report/
test_multi_heap_host
# VS Code Settings
.vscode/
# VIM files
*.swp
*.swo
# Clion IDE CMake build & config
.idea/
cmake-build-*/
# Results for the checking of the Python coding style and static analysis
.mypy_cache
flake8_output.txt
# ESP-IDF default build directory name
build
# lock files for examples and components
dependencies.lock
# managed_components for examples
managed_components
# pytest log
pytest_embedded_log/

View file

@ -30,28 +30,38 @@ before_script:
artifacts:
when: always
paths:
- $BUILD_PATH/*/*/build/*.bin
- $BUILD_PATH/*/*/build/*.elf
- $BUILD_PATH/*/*/build/*.map
- $BUILD_PATH/*/*/build/download.config
- $BUILD_PATH/*/*/build/bootloader/*.bin
- $LOG_PATH
- $BUILD_PATH/*/*/*/build/*.bin
- $BUILD_PATH/*/*/*/build/*/*.bin
- $BUILD_PATH/*/*/*/build/*.json
- $BUILD_PATH/*.json
- $LOG_PATH/*
expire_in: 1 week
variables:
IDF_CI_BUILD: "1"
LOG_PATH: "$CI_PROJECT_DIR/log_examples"
BUILD_PATH: "$CI_PROJECT_DIR/build_examples"
SIZE_INFO_LOCATION: "$CI_PROJECT_DIR/log_examples/size_info.txt"
PEDANTIC_CFLAGS: ""
PEDANTIC_CXXFLAGS: ""
script:
# it's not possible to build 100% out-of-tree and have the "artifacts"
# mechanism work, but this is the next best thing
- rm -rf ${BUILD_PATH}
- mkdir ${BUILD_PATH}
- mkdir -p ${LOG_PATH}
# build some of examples
- ${IOT_SOLUTION_PATH}/tools/ci/build_examples.sh "${CI_JOB_NAME}"
- python ${IOT_SOLUTION_PATH}/tools/ci/genarate_build_json.py
- ${IOT_SOLUTION_PATH}/tools/ci/build_examples.sh
build_examples_00:
build_examples_00_with_idf_v4.2:
<<: *build_examples_template
image: espressif/idf:release-v4.2
build_examples_00_with_idf_v4.3:
<<: *build_examples_template
image: espressif/idf:release-v4.3
build_examples_00_with_idf_v4.4:
<<: *build_examples_template
image: espressif/idf:release-v4.4
build_docs:
stage: build
@ -74,6 +84,8 @@ build_docs:
expire_in: 1 mos
script:
- source /opt/pyenv/activate && pyenv global 3.6.10
- pip install "setuptools<57.5.0"
- pip install "funcparserlib==0.3.6"
- /opt/pyenv/pyenv-1.2.16/versions/3.6.10/bin/python -m pip install --user -r docs/requirements.txt
- cd docs
- ./check_lang_folder_sync.sh

6
.gitmodules vendored
View file

@ -4,3 +4,9 @@
[submodule "examples/hmi/lvgl_example/components/lv_examples/lv_examples"]
path = examples/hmi/lvgl_example/components/lv_examples/lv_examples
url = https://github.com/lvgl/lv_examples.git
[submodule "examples/camera/camera_components/esp32-camera"]
path = examples/camera/camera_components/esp32-camera
url = https://github.com/espressif/esp32-camera
[submodule "examples/decompress/xz_compressed_ota/bootloader_components"]
path = examples/decompress/xz_compressed_ota/bootloader_components
url = https://github.com/espressif/esp-bootloader-plus.git

View file

@ -14,4 +14,5 @@ formats:
python:
version: 3.7
install:
- requirements: docs/setuptools.requirements.txt
- requirements: docs/requirements.txt

View file

@ -1,3 +1,3 @@
idf_component_register(SRCS "dac_audio.c"
INCLUDE_DIRS "include"
)
REQUIRES driver)

View file

@ -12,17 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include "sdkconfig.h"
#ifdef CONFIG_IDF_TARGET_ESP32
#include <stdio.h>
#include <string.h>
#include "esp_log.h"
#include "driver/i2s.h"
#include "dac_audio.h"
#include "sdkconfig.h"
/**
* @attention "I2S DAC only support ESP32"
*/
#ifdef CONFIG_IDF_TARGET_ESP32
static const char *TAG = "DAC audio";
#define DAC_AUDIO_CHECK(a, str, ret_val) \
@ -156,7 +154,11 @@ esp_err_t dac_audio_init(dac_audio_config_t *cfg)
i2s_config.mode = I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN;
i2s_config.sample_rate = cfg->sample_rate;
i2s_config.bits_per_sample = cfg->bits_per_sample;
#if (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 2, 0))
i2s_config.communication_format = I2S_COMM_FORMAT_I2S_MSB;
#else
i2s_config.communication_format = I2S_COMM_FORMAT_STAND_MSB;
#endif
if (I2S_DAC_CHANNEL_RIGHT_EN == cfg->dac_mode) {
i2s_config.channel_format = I2S_CHANNEL_FMT_ALL_RIGHT;
} else if (I2S_DAC_CHANNEL_LEFT_EN == cfg->dac_mode) {

View file

@ -1,5 +1,3 @@
set(pwm_audio_srcs "pwm_audio.c")
idf_component_register(SRCS "${pwm_audio_srcs}"
INCLUDE_DIRS "include")
idf_component_register(SRCS "pwm_audio.c"
INCLUDE_DIRS "include"
REQUIRES driver)

View file

@ -0,0 +1,13 @@
# Component: Button
[documentation](https://docs.espressif.com/projects/espressif-esp-iot-solution/en/latest/audio/pwm_audio.html)
The PWM audio function uses the internal LEDC peripheral in ESP32 to generate PWM audio, which does not need an external audio Codec chip.
## Features
- Allows any GIPO with output capability as an audio output pin
- Supports 8-bit ~ 10-bit PWM resolution
- Supports stereo
- Supports 8 48 KHz sampling rate
[Here](https://github.com/espressif/esp-iot-solution/tree/master/examples/audio/wav_player) is a simple player example that uses PWM to output audio.

View file

@ -0,0 +1,5 @@
version: "1.0.0"
description: PWM audio output driver for ESP32 series Socs
url: https://github.com/espressif/esp-iot-solution/tree/master/components/audio/pwm_audio
dependencies:
idf: ">=4.0"

View file

@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View file

@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#define _SOC_TIMG_STRUCT_H_ // to exclude `timer_group_struct.h` file
#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
@ -19,18 +21,25 @@
#include "freertos/task.h"
#include "driver/ledc.h"
#include "esp_err.h"
#include "esp_timer.h"
#include "esp_log.h"
#include "esp_heap_caps.h"
#include "driver/timer.h"
#include "soc/timer_group_struct.h"
#include "soc/ledc_struct.h"
#include "soc/ledc_reg.h"
#include "pwm_audio.h"
#include "sdkconfig.h"
#if (CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32)
#if (CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3)
#ifdef CONFIG_IDF_TARGET_ESP32
#include "reg_struct/esp32_timer_group_struct.h"
#elif defined CONFIG_IDF_TARGET_ESP32S2
#include "reg_struct/esp32s2_timer_group_struct.h"
#elif defined CONFIG_IDF_TARGET_ESP32S3
#include "reg_struct/esp32s3_timer_group_struct.h"
#elif defined CONFIG_IDF_TARGET_ESP32C3
#include "reg_struct/esp32c3_timer_group_struct.h"
#endif
static const char *TAG = "pwm_audio";
#define PWM_AUDIO_CHECK(a, str, ret_val) \
@ -58,6 +67,10 @@ static const char *PWM_AUDIO_NOT_INITIALIZED = "PWM AUDIO Uninitialized";
#define CHANNEL_RIGHT_MASK (0x02)
#define VOLUME_0DB (16)
#ifndef TIMER_BASE_CLK
#define TIMER_BASE_CLK 80000000
#endif
/**
* Debug Configuration
**/
@ -77,7 +90,7 @@ typedef struct {
pwm_audio_config_t config; /**< pwm audio config struct */
ledc_channel_config_t ledc_channel[PWM_AUDIO_CH_MAX]; /**< ledc channel config */
ledc_timer_config_t ledc_timer; /**< ledc timer config */
timg_dev_t *timg_dev; /**< timer group register pointer */
_timg_dev_t *timg_dev; /**< timer group register pointer */
ringbuf_handle_t *ringbuf; /**< audio ringbuffer pointer */
uint32_t channel_mask; /**< channel gpio mask */
uint32_t channel_set_num; /**< channel audio set number */
@ -121,7 +134,7 @@ static esp_err_t rb_destroy(ringbuf_handle_t *rb)
rb = NULL;
return ESP_OK;
}
static ringbuf_handle_t* rb_create(uint32_t size)
static ringbuf_handle_t *rb_create(uint32_t size)
{
if (size < (BUFFER_MIN_SIZE << 2)) {
ESP_LOGE(TAG, "Invalid buffer size, Minimum = %d", (int32_t)(BUFFER_MIN_SIZE << 2));
@ -249,7 +262,6 @@ static inline void ledc_set_right_duty_fast(uint32_t duty_val)
*g_ledc_right_conf1_val |= 0x80000000;
}
/*
* Timer group ISR handler
*/
@ -260,31 +272,14 @@ static void IRAM_ATTR timer_group_isr(void *para)
if (handle == NULL) {
return;
}
#ifdef CONFIG_IDF_TARGET_ESP32S2
/* Clear the interrupt */
if ((handle->timg_dev)->int_st.val & BIT(handle->config.timer_num)) {
(handle->timg_dev)->int_clr.val |= (1UL << handle->config.timer_num);
}
// uint32_t st = timer_ll_get_intr_status(handle->timg_dev);
// if (st & (1UL << handle->config.timer_num)) {
timer_ll_clear_intr_status(handle->timg_dev, handle->config.timer_num);
// }
/* After the alarm has been triggered
we need enable it again, so it is triggered the next time */
handle->timg_dev->hw_timer[handle->config.timer_num].config.alarm_en = TIMER_ALARM_EN;
#endif /**< CONFIG_IDF_TARGET_ESP32S2 */
#ifdef CONFIG_IDF_TARGET_ESP32
/* Clear the interrupt */
if (handle->timg_dev->int_st_timers.val & BIT(handle->config.timer_num)) {
handle->timg_dev->int_clr_timers.val |= (1UL << handle->config.timer_num);
}
/* After the alarm has been triggered
we need enable it again, so it is triggered the next time */
handle->timg_dev->hw_timer[handle->config.timer_num].config.alarm_en = TIMER_ALARM_EN;
#endif /**< CONFIG_IDF_TARGET_ESP32 */
we need enable it again, so it is triggered the next time */
timer_ll_enable_alarm(handle->timg_dev, handle->config.timer_num, 1);
static uint8_t wave_h, wave_l;
static uint16_t value;
@ -441,9 +436,9 @@ esp_err_t pwm_audio_init(const pwm_audio_config_t *cfg)
/**< Get timer group register pointer */
if (cfg->tg_num == TIMER_GROUP_0) {
handle->timg_dev = &TIMERG0;
handle->timg_dev = TIMERG0;
} else {
handle->timg_dev = &TIMERG1;
handle->timg_dev = TIMERG1;
}
/**
@ -557,7 +552,7 @@ esp_err_t pwm_audio_set_param(int rate, ledc_timer_bit_t bits, int ch)
timer_set_counter_value(handle->config.tg_num, handle->config.timer_num, 0x00000000ULL);
/* Configure the alarm value and the interrupt on alarm. */
uint32_t divider = handle->timg_dev->hw_timer[handle->config.timer_num].config.divider;
uint32_t divider = timer_ll_get_clock_prescale(handle->timg_dev, handle->config.timer_num);
timer_set_alarm_value(handle->config.tg_num, handle->config.timer_num, (TIMER_BASE_CLK / divider) / handle->framerate);
// timer_enable_intr(handle->config.tg_num, handle->config.timer_num);
return res;
@ -572,7 +567,7 @@ esp_err_t pwm_audio_set_sample_rate(int rate)
pwm_audio_data_t *handle = g_pwm_audio_handle;
handle->framerate = rate;
uint32_t divider = handle->timg_dev->hw_timer[handle->config.timer_num].config.divider;
uint32_t divider = timer_ll_get_clock_prescale(handle->timg_dev, handle->config.timer_num);
res = timer_set_alarm_value(handle->config.tg_num, handle->config.timer_num, (TIMER_BASE_CLK / divider) / handle->framerate);
return res;
}
@ -751,10 +746,9 @@ esp_err_t pwm_audio_start(void)
/**< timer enable interrupt */
portENTER_CRITICAL_SAFE(&timer_spinlock);
handle->timg_dev->int_ena.val |= BIT(handle->config.timer_num);
handle->timg_dev->hw_timer[handle->config.timer_num].config.enable = 1;
handle->timg_dev->hw_timer[handle->config.timer_num].config.alarm_en = TIMER_ALARM_EN; /** Make sure the interrupt is enabled*/
handle->timg_dev->hw_timer[handle->config.timer_num].config.level_int_en = 1;
timer_ll_enable_intr(handle->timg_dev, handle->config.timer_num, 1);
timer_ll_enable_counter(handle->timg_dev, handle->config.timer_num, 1);
timer_ll_enable_alarm(handle->timg_dev, handle->config.timer_num, 1); /** Make sure the interrupt is enabled*/
portEXIT_CRITICAL_SAFE(&timer_spinlock);
res = timer_start(handle->config.tg_num, handle->config.timer_num);
@ -770,9 +764,8 @@ esp_err_t pwm_audio_stop(void)
/**< just disable timer ,keep pwm output to reduce switching nosie */
/**< timer disable interrupt */
portENTER_CRITICAL_SAFE(&timer_spinlock);
handle->timg_dev->hw_timer[handle->config.timer_num].config.enable = 0;
handle->timg_dev->int_ena.val &= (~BIT(handle->config.timer_num));
handle->timg_dev->hw_timer[handle->config.timer_num].config.level_int_en = 0;
timer_ll_enable_intr(handle->timg_dev, handle->config.timer_num, 0);
timer_ll_enable_counter(handle->timg_dev, handle->config.timer_num, 0);
portEXIT_CRITICAL_SAFE(&timer_spinlock);
// timer_pause(handle->config.tg_num, handle->config.timer_num);

View file

@ -0,0 +1,784 @@
/**
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/** Group: Configuration and Control Register */
/** Type of txconfig register
* Timer x configuration register
*/
typedef union {
struct {
uint32_t reserved_0: 10;
/** tx_alarm_en : R/W; bitpos: [10]; default: 0;
* When set, the alarm is enabled. This bit is automatically cleared once an
*
* alarm occurs.
*/
uint32_t tx_alarm_en: 1;
/** tx_level_int_en : R/W; bitpos: [11]; default: 0;
* When set, an alarm will generate a level type interrupt.
*/
uint32_t tx_level_int_en: 1;
/** tx_edge_int_en : R/W; bitpos: [12]; default: 0;
* When set, an alarm will generate an edge type interrupt.
*/
uint32_t tx_edge_int_en: 1;
/** tx_divider : R/W; bitpos: [28:13]; default: 1;
* Timer x clock (Tx_clk) prescaler value.
*/
uint32_t tx_divider: 16;
/** tx_autoreload : R/W; bitpos: [29]; default: 1;
* When set, timer x auto-reload at alarm is enabled.
*/
uint32_t tx_autoreload: 1;
/** tx_increase : R/W; bitpos: [30]; default: 1;
* When set, the timer x time-base counter will increment every clock tick. When
*
* cleared, the timer x time-base counter will decrement.
*/
uint32_t tx_increase: 1;
/** tx_en : R/W; bitpos: [31]; default: 0;
* When set, the timer x time-base counter is enabled.
*/
uint32_t tx_en: 1;
};
uint32_t val;
} _timg_txconfig_reg_t;
/** Type of txlo register
* Timer x current value, low 32 bits
*/
typedef union {
struct {
/** tx_lo : RO; bitpos: [31:0]; default: 0;
* After writing to TIMG_TxUPDATE_REG, the low 32 bits of the time-base counter
*
* of timer x can be read here.
*/
uint32_t tx_lo: 32;
};
uint32_t val;
} _timg_txlo_reg_t;
/** Type of txhi register
* Timer x current value, high 32 bits
*/
typedef union {
struct {
/** tx_hi : RO; bitpos: [31:0]; default: 0;
* After writing to TIMG_TxUPDATE_REG, the high 32 bits of the time-base counter
*
* of timer x can be read here.
*/
uint32_t tx_hi: 32;
};
uint32_t val;
} _timg_txhi_reg_t;
/** Type of txupdate register
* Write to copy current timer value to TIMGn_Tx_(LO/HI)_REG
*/
typedef union {
struct {
uint32_t reserved_0: 31;
/** tx_update : R/W; bitpos: [31]; default: 0;
* After writing 0 or 1 to TIMG_TxUPDATE_REG, the counter value is latched.
*/
uint32_t tx_update: 1;
};
uint32_t val;
} _timg_txupdate_reg_t;
/** Type of txalarmlo register
* Timer x alarm value, low 32 bits
*/
typedef union {
struct {
/** tx_alarm_lo : R/W; bitpos: [31:0]; default: 0;
* Timer x alarm trigger time-base counter value, low 32 bits.
*/
uint32_t tx_alarm_lo: 32;
};
uint32_t val;
} _timg_txalarmlo_reg_t;
/** Type of txalarmhi register
* Timer x alarm value, high bits
*/
typedef union {
struct {
/** tx_alarm_hi : R/W; bitpos: [31:0]; default: 0;
*
*
* Timer x alarm trigger time-base counter value, high 32 bits.
*/
uint32_t tx_alarm_hi: 32;
};
uint32_t val;
} _timg_txalarmhi_reg_t;
/** Type of txloadlo register
* Timer x reload value, low 32 bits
*/
typedef union {
struct {
/** tx_load_lo : R/W; bitpos: [31:0]; default: 0;
*
*
* Low 32 bits of the value that a reload will load onto timer x time-base
*
* Counter.
*/
uint32_t tx_load_lo: 32;
};
uint32_t val;
} _timg_txloadlo_reg_t;
/** Type of txloadhi register
* Timer x reload value, high 32 bits
*/
typedef union {
struct {
/** tx_load_hi : R/W; bitpos: [31:0]; default: 0;
*
*
* High 32 bits of the value that a reload will load onto timer x time-base
*
* counter.
*/
uint32_t tx_load_hi: 32;
};
uint32_t val;
} _timg_txloadhi_reg_t;
/** Type of txload register
* Write to reload timer from TIMG_T0_(LOADLOLOADHI)_REG
*/
typedef union {
struct {
/** tx_load : WO; bitpos: [31:0]; default: 0;
*
*
* Write any value to trigger a timer x time-base counter reload.
*/
uint32_t tx_load: 32;
};
uint32_t val;
} _timg_txload_reg_t;
/** Group: Configuration and Control Register for WDT */
/** Type of wdtconfig0 register
* Watchdog timer configuration register
*/
typedef union {
struct {
uint32_t reserved_0: 14;
/** wdt_flashboot_mod_en : R/W; bitpos: [14]; default: 1;
* When set, Flash boot protection is enabled.
*/
uint32_t wdt_flashboot_mod_en: 1;
/** wdt_sys_reset_length : R/W; bitpos: [17:15]; default: 1;
* System reset signal length selection. 0: 100 ns, 1: 200 ns,
*
* 2: 300 ns, 3: 400 ns, 4: 500 ns, 5: 800 ns, 6: 1.6 us, 7: 3.2 us.
*/
uint32_t wdt_sys_reset_length: 3;
/** wdt_cpu_reset_length : R/W; bitpos: [20:18]; default: 1;
* CPU reset signal length selection. 0: 100 ns, 1: 200 ns,
*
* 2: 300 ns, 3: 400 ns, 4: 500 ns, 5: 800 ns, 6: 1.6 us, 7: 3.2 us.
*/
uint32_t wdt_cpu_reset_length: 3;
/** wdt_level_int_en : R/W; bitpos: [21]; default: 0;
* When set, a level type interrupt will occur at the timeout of a stage
*
* configured to generate an interrupt.
*/
uint32_t wdt_level_int_en: 1;
/** wdt_edge_int_en : R/W; bitpos: [22]; default: 0;
* When set, an edge type interrupt will occur at the timeout of a stage
*
* configured to generate an interrupt.
*/
uint32_t wdt_edge_int_en: 1;
/** wdt_stg3 : R/W; bitpos: [24:23]; default: 0;
* Stage 3 configuration. 0: off, 1: interrupt, 2: reset CPU, 3: reset system.
*
*/
uint32_t wdt_stg3: 2;
/** wdt_stg2 : R/W; bitpos: [26:25]; default: 0;
* Stage 2 configuration. 0: off, 1: interrupt, 2: reset CPU, 3: reset system.
*
*/
uint32_t wdt_stg2: 2;
/** wdt_stg1 : R/W; bitpos: [28:27]; default: 0;
* Stage 1 configuration. 0: off, 1: interrupt, 2: reset CPU, 3: reset system.
*
*/
uint32_t wdt_stg1: 2;
/** wdt_stg0 : R/W; bitpos: [30:29]; default: 0;
* Stage 0 configuration. 0: off, 1: interrupt, 2: reset CPU, 3: reset system.
*
*/
uint32_t wdt_stg0: 2;
/** wdt_en : R/W; bitpos: [31]; default: 0;
* When set, MWDT is enabled.
*/
uint32_t wdt_en: 1;
};
uint32_t val;
} _timg_wdtconfig0_reg_t;
/** Type of wdtconfig1 register
* Watchdog timer prescaler register
*/
typedef union {
struct {
uint32_t reserved_0: 16;
/** wdt_clk_prescaler : R/W; bitpos: [31:16]; default: 1;
* MWDT clock prescaler value. MWDT clock period = 12.5 ns *
*
* TIMG_WDT_CLK_PRESCALE.
*/
uint32_t wdt_clk_prescaler: 16;
};
uint32_t val;
} _timg_wdtconfig1_reg_t;
/** Type of wdtconfig2 register
* Watchdog timer stage 0 timeout value
*/
typedef union {
struct {
/** wdt_stg0_hold : R/W; bitpos: [31:0]; default: 26000000;
* Stage 0 timeout value, in MWDT clock cycles.
*/
uint32_t wdt_stg0_hold: 32;
};
uint32_t val;
} _timg_wdtconfig2_reg_t;
/** Type of wdtconfig3 register
* Watchdog timer stage 1 timeout value
*/
typedef union {
struct {
/** wdt_stg1_hold : R/W; bitpos: [31:0]; default: 134217727;
* Stage 1 timeout value, in MWDT clock cycles.
*/
uint32_t wdt_stg1_hold: 32;
};
uint32_t val;
} _timg_wdtconfig3_reg_t;
/** Type of wdtconfig4 register
* Watchdog timer stage 2 timeout value
*/
typedef union {
struct {
/** wdt_stg2_hold : R/W; bitpos: [31:0]; default: 1048575;
* Stage 2 timeout value, in MWDT clock cycles.
*/
uint32_t wdt_stg2_hold: 32;
};
uint32_t val;
} _timg_wdtconfig4_reg_t;
/** Type of wdtconfig5 register
* Watchdog timer stage 3 timeout value
*/
typedef union {
struct {
/** wdt_stg3_hold : R/W; bitpos: [31:0]; default: 1048575;
* Stage 3 timeout value, in MWDT clock cycles.
*/
uint32_t wdt_stg3_hold: 32;
};
uint32_t val;
} _timg_wdtconfig5_reg_t;
/** Type of wdtfeed register
* Write to feed the watchdog timer
*/
typedef union {
struct {
/** wdt_feed : WO; bitpos: [31:0]; default: 0;
* Write any value to feed the MWDT. (WO)
*/
uint32_t wdt_feed: 32;
};
uint32_t val;
} _timg_wdtfeed_reg_t;
/** Type of wdtwprotect register
* Watchdog write protect register
*/
typedef union {
struct {
/** wdt_wkey : R/W; bitpos: [31:0]; default: 1356348065;
* If the register contains a different value than its reset value, write
*
* protection is enabled.
*/
uint32_t wdt_wkey: 32;
};
uint32_t val;
} _timg_wdtwprotect_reg_t;
/** Group: Configuration and Control Register for RTC CALI */
/** Type of rtccalicfg register
* RTC calibration configuration register
*/
typedef union {
struct {
uint32_t reserved_0: 12;
/** rtc_cali_start_cycling : R/W; bitpos: [12]; default: 1;
* Reserved
*/
uint32_t rtc_cali_start_cycling: 1;
/** rtc_cali_clk_sel : R/W; bitpos: [14:13]; default: 1;
* 0:rtcslowclock. 1:clk_80m. 2:xtal_32k.
*/
uint32_t rtc_cali_clk_sel: 2;
/** rtc_cali_rdy : RO; bitpos: [15]; default: 0;
* Reserved
*/
uint32_t rtc_cali_rdy: 1;
/** rtc_cali_max : R/W; bitpos: [30:16]; default: 1;
* Reserved
*/
uint32_t rtc_cali_max: 15;
/** rtc_cali_start : R/W; bitpos: [31]; default: 0;
* Reserved
*/
uint32_t rtc_cali_start: 1;
};
uint32_t val;
} _timg_rtccalicfg_reg_t;
/** Type of rtccalicfg1 register
* RTC calibration configuration1 register
*/
typedef union {
struct {
uint32_t reserved_0: 7;
/** rtc_cali_value : RO; bitpos: [31:7]; default: 0;
* Reserved
*/
uint32_t rtc_cali_value: 25;
};
uint32_t val;
} _timg_rtccalicfg1_reg_t;
/** Group: Configuration and Control Register for LACT */
/** Type of lactconfig register
* LACT configuration register
*/
typedef union {
struct {
uint32_t reserved_0: 7;
/** lact_rtc_only : R/W; bitpos: [7]; default: 0;
* Reserved
*/
uint32_t lact_rtc_only: 1;
/** lact_cpst_en : R/W; bitpos: [8]; default: 1;
* Reserved
*/
uint32_t lact_cpst_en: 1;
/** lact_lac_en : R/W; bitpos: [9]; default: 1;
* Reserved
*/
uint32_t lact_lac_en: 1;
/** lact_alarm_en : R/W; bitpos: [10]; default: 0;
* Reserved
*/
uint32_t lact_alarm_en: 1;
/** lact_level_int_en : R/W; bitpos: [11]; default: 0;
* Reserved
*/
uint32_t lact_level_int_en: 1;
/** lact_edge_int_en : R/W; bitpos: [12]; default: 0;
* Reserved
*/
uint32_t lact_edge_int_en: 1;
/** lact_divider : R/W; bitpos: [28:13]; default: 1;
* Reserved
*/
uint32_t lact_divider: 16;
/** lact_autoreload : R/W; bitpos: [29]; default: 1;
* Reserved
*/
uint32_t lact_autoreload: 1;
/** lact_increase : R/W; bitpos: [30]; default: 1;
* Reserved
*/
uint32_t lact_increase: 1;
/** lact_en : R/W; bitpos: [31]; default: 0;
* Reserved
*/
uint32_t lact_en: 1;
};
uint32_t val;
} _timg_lactconfig_reg_t;
/** Type of lactrtc register
* LACT RTC register
*/
typedef union {
struct {
uint32_t reserved_0: 6;
/** lact_rtc_step_len : R/W; bitpos: [31:6]; default: 0;
* Reserved
*/
uint32_t lact_rtc_step_len: 26;
};
uint32_t val;
} _timg_lactrtc_reg_t;
/** Type of lactlo register
* LACT low register
*/
typedef union {
struct {
/** lact_lo : RO; bitpos: [31:0]; default: 0;
* Reserved
*/
uint32_t lact_lo: 32;
};
uint32_t val;
} _timg_lactlo_reg_t;
/** Type of lacthi register
* LACT high register
*/
typedef union {
struct {
/** lact_hi : RO; bitpos: [31:0]; default: 0;
* Reserved
*/
uint32_t lact_hi: 32;
};
uint32_t val;
} _timg_lacthi_reg_t;
/** Type of lactupdate register
* LACT update register
*/
typedef union {
struct {
/** lact_update : WO; bitpos: [31:0]; default: 0;
* Reserved
*/
uint32_t lact_update: 32;
};
uint32_t val;
} _timg_lactupdate_reg_t;
/** Type of lactalarmlo register
* LACT alarm low register
*/
typedef union {
struct {
/** lact_alarm_lo : R/W; bitpos: [31:0]; default: 0;
* Reserved
*/
uint32_t lact_alarm_lo: 32;
};
uint32_t val;
} _timg_lactalarmlo_reg_t;
/** Type of lactalarmhi register
* LACT alarm high register
*/
typedef union {
struct {
/** lact_alarm_hi : R/W; bitpos: [31:0]; default: 0;
* Reserved
*/
uint32_t lact_alarm_hi: 32;
};
uint32_t val;
} _timg_lactalarmhi_reg_t;
/** Type of lactloadlo register
* LACT load low register
*/
typedef union {
struct {
/** lact_load_lo : R/W; bitpos: [31:0]; default: 0;
* Reserved
*/
uint32_t lact_load_lo: 32;
};
uint32_t val;
} _timg_lactloadlo_reg_t;
/** Type of lactloadhi register
* Timer LACT load high register
*/
typedef union {
struct {
/** lact_load_hi : R/W; bitpos: [31:0]; default: 0;
* Reserved
*/
uint32_t lact_load_hi: 32;
};
uint32_t val;
} _timg_lactloadhi_reg_t;
/** Type of lactload register
* Timer LACT load register
*/
typedef union {
struct {
/** lact_load : WO; bitpos: [31:0]; default: 0;
* Reserved
*/
uint32_t lact_load: 32;
};
uint32_t val;
} _timg_lactload_reg_t;
/** Group: Interrupt Register */
/** Type of int_ena_timers register
* Interrupt enable bits
*/
typedef union {
struct {
/** tx_int_ena : R/W; bitpos: [0]; default: 0;
* The interrupt enable bit for the TIMG_T0_INT interrupt.
*/
uint32_t t0_int_ena: 1;
/** t1_int_ena : R/W; bitpos: [1]; default: 0;
* The interrupt enable bit for the TIMG_T1_INT interrupt.
*/
uint32_t t1_int_ena: 1;
/** wdt_int_ena : R/W; bitpos: [2]; default: 0;
* The interrupt enable bit for the TIMG_WDT_INT interrupt.
*/
uint32_t wdt_int_ena: 1;
/** lact_int_ena : R/W; bitpos: [3]; default: 0;
* The interrupt enable bit for the TIMG_LACT_INT interrupt.
*/
uint32_t lact_int_ena: 1;
uint32_t reserved_4: 28;
};
uint32_t val;
} _timg_int_ena_timers_reg_t;
/** Type of int_raw_timers register
* Raw interrupt status
*/
typedef union {
struct {
/** t0_int_raw : RO; bitpos: [0]; default: 0;
* The raw interrupt status bit for the TIMG_T0_INT interrupt.
*/
uint32_t t0_int_raw: 1;
/** t1_int_raw : RO; bitpos: [1]; default: 0;
* The raw interrupt status bit for the TIMG_T1_INT interrupt.
*/
uint32_t t1_int_raw: 1;
/** wdt_int_raw : RO; bitpos: [2]; default: 0;
* The raw interrupt status bit for the TIMG_WDT_INT interrupt.
*/
uint32_t wdt_int_raw: 1;
/** lact_int_raw : RO; bitpos: [3]; default: 0;
* The raw interrupt status bit for the TIMG_LACT_INT interrupt.
*/
uint32_t lact_int_raw: 1;
uint32_t reserved_4: 28;
};
uint32_t val;
} _timg_int_raw_timers_reg_t;
/** Type of int_st_timers register
* Masked interrupt status
*/
typedef union {
struct {
/** t0_int_st : RO; bitpos: [0]; default: 0;
* The masked interrupt status bit for the TIMG_T0_INT interrupt.
*/
uint32_t t0_int_st: 1;
/** t1_int_st : RO; bitpos: [1]; default: 0;
* The masked interrupt status bit for the TIMG_T1_INT interrupt.
*/
uint32_t t1_int_st: 1;
/** wdt_int_st : RO; bitpos: [2]; default: 0;
* The masked interrupt status bit for the TIMG_WDT_INT interrupt.
*/
uint32_t wdt_int_st: 1;
/** lact_int_st : RO; bitpos: [3]; default: 0;
* The masked interrupt status bit for the TIMG_LACT_INT interrupt.
*/
uint32_t lact_int_st: 1;
uint32_t reserved_4: 28;
};
uint32_t val;
} _timg_int_st_timers_reg_t;
/** Type of int_clr_timers register
* Interrupt clear bits
*/
typedef union {
struct {
/** t0_int_clr : WO; bitpos: [0]; default: 0;
* Set this bit to clear the TIMG_T0_INT interrupt.
*/
uint32_t t0_int_clr: 1;
/** t1_int_clr : WO; bitpos: [1]; default: 0;
* Set this bit to clear the TIMG_T1_INT interrupt.
*/
uint32_t t1_int_clr: 1;
/** wdt_int_clr : WO; bitpos: [2]; default: 0;
* Set this bit to clear the TIMG_WDT_INT interrupt.
*/
uint32_t wdt_int_clr: 1;
/** lact_int_clr : WO; bitpos: [3]; default: 0;
* Set this bit to clear the TIMG_LACT_INT interrupt.
*/
uint32_t lact_int_clr: 1;
uint32_t reserved_4: 28;
};
uint32_t val;
} _timg_int_clr_timers_reg_t;
/** Group: Version Register */
/** Type of timers_date register
* Version control register
*/
typedef union {
struct {
/** timers_date : R/W; bitpos: [27:0]; default: 26243681;
* Version control register.
*/
uint32_t timers_date: 28;
uint32_t reserved_28: 4;
};
uint32_t val;
} _timg_timers_date_reg_t;
/** Group: Configuration Register */
/** Type of regclk register
* Timer group clock gate register
*/
typedef union {
struct {
uint32_t reserved_0: 31;
/** clk_en : R/W; bitpos: [31]; default: 0;
* Register clock gate signal. 1: Registers can be read and written to by software. 0:
* Registers can not be read or written to by software.
*/
uint32_t clk_en: 1;
};
uint32_t val;
} _timg_regclk_reg_t;
typedef struct {
volatile _timg_txconfig_reg_t config;
volatile _timg_txlo_reg_t lo;
volatile _timg_txhi_reg_t hi;
volatile _timg_txupdate_reg_t update;
volatile _timg_txalarmlo_reg_t alarmlo;
volatile _timg_txalarmhi_reg_t alarmhi;
volatile _timg_txloadlo_reg_t loadlo;
volatile _timg_txloadhi_reg_t loadhi;
volatile _timg_txload_reg_t load;
} _timg_hwtimer_reg_t;
typedef struct _timg_dev_t {
volatile _timg_hwtimer_reg_t hw_timer[2];
volatile _timg_wdtconfig0_reg_t wdtconfig0;
volatile _timg_wdtconfig1_reg_t wdtconfig1;
volatile _timg_wdtconfig2_reg_t wdtconfig2;
volatile _timg_wdtconfig3_reg_t wdtconfig3;
volatile _timg_wdtconfig4_reg_t wdtconfig4;
volatile _timg_wdtconfig5_reg_t wdtconfig5;
volatile _timg_wdtfeed_reg_t wdtfeed;
volatile _timg_wdtwprotect_reg_t wdtwprotect;
volatile _timg_rtccalicfg_reg_t rtccalicfg;
volatile _timg_rtccalicfg1_reg_t rtccalicfg1;
volatile _timg_lactconfig_reg_t lactconfig;
volatile _timg_lactrtc_reg_t lactrtc;
volatile _timg_lactlo_reg_t lactlo;
volatile _timg_lacthi_reg_t lacthi;
volatile _timg_lactupdate_reg_t lactupdate;
volatile _timg_lactalarmlo_reg_t lactalarmlo;
volatile _timg_lactalarmhi_reg_t lactalarmhi;
volatile _timg_lactloadlo_reg_t lactloadlo;
volatile _timg_lactloadhi_reg_t lactloadhi;
volatile _timg_lactload_reg_t lactload;
volatile _timg_int_ena_timers_reg_t int_ena_timers;
volatile _timg_int_raw_timers_reg_t int_raw_timers;
volatile _timg_int_st_timers_reg_t int_st_timers;
volatile _timg_int_clr_timers_reg_t int_clr_timers;
uint32_t _reserved_0ac[20];
volatile _timg_timers_date_reg_t timers_date;
volatile _timg_regclk_reg_t regclk;
} _timg_dev_t;
#define TIMERG0_BASE 0x3ff5F000
#define TIMERG1_BASE 0x3ff60000
#define TIMERG0 ((_timg_dev_t*) TIMERG0_BASE)
#define TIMERG1 ((_timg_dev_t*) TIMERG1_BASE)
__attribute__((always_inline))
static inline void timer_ll_enable_alarm(_timg_dev_t *hw, uint32_t timer_num, bool en)
{
hw->hw_timer[timer_num].config.tx_alarm_en = en;
// use level type interrupt
hw->hw_timer[timer_num].config.tx_level_int_en = en;
}
__attribute__((always_inline))
static inline void timer_ll_enable_counter(_timg_dev_t *hw, uint32_t timer_num, bool en)
{
hw->hw_timer[timer_num].config.tx_en = en;
}
__attribute__((always_inline))
static inline void timer_ll_enable_intr(_timg_dev_t *hw, uint32_t timer_num, bool en)
{
if (en) {
hw->int_ena_timers.val |= BIT(timer_num);
} else {
hw->int_ena_timers.val &= ~BIT(timer_num);
}
}
__attribute__((always_inline))
static inline void timer_ll_clear_intr_status(_timg_dev_t *hw, uint32_t timer_num)
{
hw->int_clr_timers.val = BIT(timer_num);
}
__attribute__((always_inline))
static inline uint32_t timer_ll_get_intr_status(_timg_dev_t *hw)
{
return hw->int_st_timers.val;
}
__attribute__((always_inline))
static inline uint32_t timer_ll_get_clock_prescale(_timg_dev_t *hw, uint32_t timer_num)
{
return hw->hw_timer[timer_num].config.tx_divider;
}
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,598 @@
/**
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/** Group: T0 Control and configuration registers */
/** Type of txconfig register
* Timer x configuration register
*/
typedef union {
struct {
uint32_t reserved_0: 9;
/** tx_use_xtal : R/W; bitpos: [9]; default: 0;
* 1: Use XTAL_CLK as the source clock of timer group. 0: Use APB_CLK as the source
* clock of timer group.
*/
uint32_t tx_use_xtal: 1;
/** tx_alarm_en : R/W/SC; bitpos: [10]; default: 0;
* When set, the alarm is enabled. This bit is automatically cleared once an
* alarm occurs.
*/
uint32_t tx_alarm_en: 1;
uint32_t reserved_11: 1;
/** tx_divcnt_rst : WT; bitpos: [12]; default: 0;
* When set, Timer x 's clock divider counter will be reset.
*/
uint32_t tx_divcnt_rst: 1;
/** tx_divider : R/W; bitpos: [28:13]; default: 1;
* Timer x clock (Tx_clk) prescaler value.
*/
uint32_t tx_divider: 16;
/** tx_autoreload : R/W; bitpos: [29]; default: 1;
* When set, timer x auto-reload at alarm is enabled.
*/
uint32_t tx_autoreload: 1;
/** tx_increase : R/W; bitpos: [30]; default: 1;
* When set, the timer x time-base counter will increment every clock tick. When
* cleared, the timer x time-base counter will decrement.
*/
uint32_t tx_increase: 1;
/** tx_en : R/W; bitpos: [31]; default: 0;
* When set, the timer x time-base counter is enabled.
*/
uint32_t tx_en: 1;
};
uint32_t val;
} _timg_txconfig_reg_t;
/** Type of txlo register
* Timer x current value, low 32 bits
*/
typedef union {
struct {
/** tx_lo : RO; bitpos: [31:0]; default: 0;
* After writing to TIMG_TxUPDATE_REG, the low 32 bits of the time-base counter
* of timer x can be read here.
*/
uint32_t tx_lo: 32;
};
uint32_t val;
} _timg_txlo_reg_t;
/** Type of txhi register
* Timer $x current value, high 22 bits
*/
typedef union {
struct {
/** tx_hi : RO; bitpos: [21:0]; default: 0;
* After writing to TIMG_T$xUPDATE_REG, the high 22 bits of the time-base counter
* of timer $x can be read here.
*/
uint32_t tx_hi: 22;
uint32_t reserved_22: 10;
};
uint32_t val;
} _timg_txhi_reg_t;
/** Type of txupdate register
* Write to copy current timer value to TIMGn_T$x_(LO/HI)_REG
*/
typedef union {
struct {
uint32_t reserved_0: 31;
/** tx_update : R/W/SC; bitpos: [31]; default: 0;
* After writing 0 or 1 to TIMG_T$xUPDATE_REG, the counter value is latched.
*/
uint32_t tx_update: 1;
};
uint32_t val;
} _timg_txupdate_reg_t;
/** Type of txalarmlo register
* Timer $x alarm value, low 32 bits
*/
typedef union {
struct {
/** tx_alarm_lo : R/W; bitpos: [31:0]; default: 0;
* Timer $x alarm trigger time-base counter value, low 32 bits.
*/
uint32_t tx_alarm_lo: 32;
};
uint32_t val;
} _timg_txalarmlo_reg_t;
/** Type of txalarmhi register
* Timer $x alarm value, high bits
*/
typedef union {
struct {
/** tx_alarm_hi : R/W; bitpos: [21:0]; default: 0;
* Timer $x alarm trigger time-base counter value, high 22 bits.
*/
uint32_t tx_alarm_hi: 22;
uint32_t reserved_22: 10;
};
uint32_t val;
} _timg_txalarmhi_reg_t;
/** Type of txloadlo register
* Timer $x reload value, low 32 bits
*/
typedef union {
struct {
/** tx_load_lo : R/W; bitpos: [31:0]; default: 0;
* Low 32 bits of the value that a reload will load onto timer $x time-base
* Counter.
*/
uint32_t tx_load_lo: 32;
};
uint32_t val;
} _timg_txloadlo_reg_t;
/** Type of txloadhi register
* Timer $x reload value, high 22 bits
*/
typedef union {
struct {
/** tx_load_hi : R/W; bitpos: [21:0]; default: 0;
* High 22 bits of the value that a reload will load onto timer $x time-base
* counter.
*/
uint32_t tx_load_hi: 22;
uint32_t reserved_22: 10;
};
uint32_t val;
} _timg_txloadhi_reg_t;
/** Type of txload register
* Write to reload timer from TIMG_T$x_(LOADLOLOADHI)_REG
*/
typedef union {
struct {
/** tx_load : WT; bitpos: [31:0]; default: 0;
*
* Write any value to trigger a timer $x time-base counter reload.
*/
uint32_t tx_load: 32;
};
uint32_t val;
} _timg_txload_reg_t;
/** Group: WDT Control and configuration registers */
/** Type of wdtconfig0 register
* Watchdog timer configuration register
*/
typedef union {
struct {
uint32_t reserved_0: 12;
/** wdt_appcpu_reset_en : R/W; bitpos: [12]; default: 0;
* WDT reset CPU enable.
*/
uint32_t wdt_appcpu_reset_en: 1;
/** wdt_procpu_reset_en : R/W; bitpos: [13]; default: 0;
* WDT reset CPU enable.
*/
uint32_t wdt_procpu_reset_en: 1;
/** wdt_flashboot_mod_en : R/W; bitpos: [14]; default: 1;
* When set, Flash boot protection is enabled.
*/
uint32_t wdt_flashboot_mod_en: 1;
/** wdt_sys_reset_length : R/W; bitpos: [17:15]; default: 1;
* System reset signal length selection. 0: 100 ns, 1: 200 ns,
* 2: 300 ns, 3: 400 ns, 4: 500 ns, 5: 800 ns, 6: 1.6 us, 7: 3.2 us.
*/
uint32_t wdt_sys_reset_length: 3;
/** wdt_cpu_reset_length : R/W; bitpos: [20:18]; default: 1;
* CPU reset signal length selection. 0: 100 ns, 1: 200 ns,
* 2: 300 ns, 3: 400 ns, 4: 500 ns, 5: 800 ns, 6: 1.6 us, 7: 3.2 us.
*/
uint32_t wdt_cpu_reset_length: 3;
/** wdt_use_xtal : R/W; bitpos: [21]; default: 0;
* choose WDT clock:0-apb_clk; 1-xtal_clk.
*/
uint32_t wdt_use_xtal: 1;
/** wdt_conf_update_en : WT; bitpos: [22]; default: 0;
* update the WDT configuration registers
*/
uint32_t wdt_conf_update_en: 1;
/** wdt_stg3 : R/W; bitpos: [24:23]; default: 0;
* Stage 3 configuration. 0: off, 1: interrupt, 2: reset CPU, 3: reset system.
*/
uint32_t wdt_stg3: 2;
/** wdt_stg2 : R/W; bitpos: [26:25]; default: 0;
* Stage 2 configuration. 0: off, 1: interrupt, 2: reset CPU, 3: reset system.
*/
uint32_t wdt_stg2: 2;
/** wdt_stg1 : R/W; bitpos: [28:27]; default: 0;
* Stage 1 configuration. 0: off, 1: interrupt, 2: reset CPU, 3: reset system.
*/
uint32_t wdt_stg1: 2;
/** wdt_stg0 : R/W; bitpos: [30:29]; default: 0;
* Stage 0 configuration. 0: off, 1: interrupt, 2: reset CPU, 3: reset system.
*/
uint32_t wdt_stg0: 2;
/** wdt_en : R/W; bitpos: [31]; default: 0;
* When set, MWDT is enabled.
*/
uint32_t wdt_en: 1;
};
uint32_t val;
} _timg_wdtconfig0_reg_t;
/** Type of wdtconfig1 register
* Watchdog timer prescaler register
*/
typedef union {
struct {
/** wdt_divcnt_rst : WT; bitpos: [0]; default: 0;
* When set, WDT 's clock divider counter will be reset.
*/
uint32_t wdt_divcnt_rst: 1;
uint32_t reserved_1: 15;
/** wdt_clk_prescale : R/W; bitpos: [31:16]; default: 1;
* MWDT clock prescaler value. MWDT clock period = 12.5 ns *
* TIMG_WDT_CLK_PRESCALE.
*/
uint32_t wdt_clk_prescale: 16;
};
uint32_t val;
} _timg_wdtconfig1_reg_t;
/** Type of wdtconfig2 register
* Watchdog timer stage 0 timeout value
*/
typedef union {
struct {
/** wdt_stg0_hold : R/W; bitpos: [31:0]; default: 26000000;
* Stage 0 timeout value, in MWDT clock cycles.
*/
uint32_t wdt_stg0_hold: 32;
};
uint32_t val;
} _timg_wdtconfig2_reg_t;
/** Type of wdtconfig3 register
* Watchdog timer stage 1 timeout value
*/
typedef union {
struct {
/** wdt_stg1_hold : R/W; bitpos: [31:0]; default: 134217727;
* Stage 1 timeout value, in MWDT clock cycles.
*/
uint32_t wdt_stg1_hold: 32;
};
uint32_t val;
} _timg_wdtconfig3_reg_t;
/** Type of wdtconfig4 register
* Watchdog timer stage 2 timeout value
*/
typedef union {
struct {
/** wdt_stg2_hold : R/W; bitpos: [31:0]; default: 1048575;
* Stage 2 timeout value, in MWDT clock cycles.
*/
uint32_t wdt_stg2_hold: 32;
};
uint32_t val;
} _timg_wdtconfig4_reg_t;
/** Type of wdtconfig5 register
* Watchdog timer stage 3 timeout value
*/
typedef union {
struct {
/** wdt_stg3_hold : R/W; bitpos: [31:0]; default: 1048575;
* Stage 3 timeout value, in MWDT clock cycles.
*/
uint32_t wdt_stg3_hold: 32;
};
uint32_t val;
} _timg_wdtconfig5_reg_t;
/** Type of wdtfeed register
* Write to feed the watchdog timer
*/
typedef union {
struct {
/** wdt_feed : WT; bitpos: [31:0]; default: 0;
* Write any value to feed the MWDT. (WO)
*/
uint32_t wdt_feed: 32;
};
uint32_t val;
} _timg_wdtfeed_reg_t;
/** Type of wdtwprotect register
* Watchdog write protect register
*/
typedef union {
struct {
/** wdt_wkey : R/W; bitpos: [31:0]; default: 1356348065;
* If the register contains a different value than its reset value, write
* protection is enabled.
*/
uint32_t wdt_wkey: 32;
};
uint32_t val;
} _timg_wdtwprotect_reg_t;
/** Group: RTC CALI Control and configuration registers */
/** Type of rtccalicfg register
* RTC calibration configure register
*/
typedef union {
struct {
uint32_t reserved_0: 12;
/** rtc_cali_start_cycling : R/W; bitpos: [12]; default: 1;
* Reserved
*/
uint32_t rtc_cali_start_cycling: 1;
/** rtc_cali_clk_sel : R/W; bitpos: [14:13]; default: 1;
* 0:rtc slow clock. 1:clk_8m, 2:xtal_32k.
*/
uint32_t rtc_cali_clk_sel: 2;
/** rtc_cali_rdy : RO; bitpos: [15]; default: 0;
* Reserved
*/
uint32_t rtc_cali_rdy: 1;
/** rtc_cali_max : R/W; bitpos: [30:16]; default: 1;
* Reserved
*/
uint32_t rtc_cali_max: 15;
/** rtc_cali_start : R/W; bitpos: [31]; default: 0;
* Reserved
*/
uint32_t rtc_cali_start: 1;
};
uint32_t val;
} _timg_rtccalicfg_reg_t;
/** Type of rtccalicfg1 register
* RTC calibration configure1 register
*/
typedef union {
struct {
/** rtc_cali_cycling_data_vld : RO; bitpos: [0]; default: 0;
* Reserved
*/
uint32_t rtc_cali_cycling_data_vld: 1;
uint32_t reserved_1: 6;
/** rtc_cali_value : RO; bitpos: [31:7]; default: 0;
* Reserved
*/
uint32_t rtc_cali_value: 25;
};
uint32_t val;
} _timg_rtccalicfg1_reg_t;
/** Type of rtccalicfg2 register
* Timer group calibration register
*/
typedef union {
struct {
/** rtc_cali_timeout : RO; bitpos: [0]; default: 0;
* RTC calibration timeout indicator
*/
uint32_t rtc_cali_timeout: 1;
uint32_t reserved_1: 2;
/** rtc_cali_timeout_rst_cnt : R/W; bitpos: [6:3]; default: 3;
* Cycles that release calibration timeout reset
*/
uint32_t rtc_cali_timeout_rst_cnt: 4;
/** rtc_cali_timeout_thres : R/W; bitpos: [31:7]; default: 33554431;
* Threshold value for the RTC calibration timer. If the calibration timer's value
* exceeds this threshold, a timeout is triggered.
*/
uint32_t rtc_cali_timeout_thres: 25;
};
uint32_t val;
} _timg_rtccalicfg2_reg_t;
/** Group: Interrupt registers */
/** Type of int_ena_timers register
* Interrupt enable bits
*/
typedef union {
struct {
/** t0_int_ena : R/W; bitpos: [0]; default: 0;
* The interrupt enable bit for the TIMG_T$x_INT interrupt.
*/
uint32_t t0_int_ena: 1;
/** wdt_int_ena : R/W; bitpos: [1]; default: 0;
* The interrupt enable bit for the TIMG_WDT_INT interrupt.
*/
uint32_t wdt_int_ena: 1;
uint32_t reserved_2: 30;
};
uint32_t val;
} _timg_int_ena_timers_reg_t;
/** Type of int_raw_timers register
* Raw interrupt status
*/
typedef union {
struct {
/** t0_int_raw : R/SS/WTC; bitpos: [0]; default: 0;
* The raw interrupt status bit for the TIMG_T$x_INT interrupt.
*/
uint32_t t0_int_raw: 1;
/** wdt_int_raw : R/SS/WTC; bitpos: [1]; default: 0;
* The raw interrupt status bit for the TIMG_WDT_INT interrupt.
*/
uint32_t wdt_int_raw: 1;
uint32_t reserved_2: 30;
};
uint32_t val;
} _timg_int_raw_timers_reg_t;
/** Type of int_st_timers register
* Masked interrupt status
*/
typedef union {
struct {
/** t0_int_st : RO; bitpos: [0]; default: 0;
* The masked interrupt status bit for the TIMG_T$x_INT interrupt.
*/
uint32_t t0_int_st: 1;
/** wdt_int_st : RO; bitpos: [1]; default: 0;
* The masked interrupt status bit for the TIMG_WDT_INT interrupt.
*/
uint32_t wdt_int_st: 1;
uint32_t reserved_2: 30;
};
uint32_t val;
} _timg_int_st_timers_reg_t;
/** Type of int_clr_timers register
* Interrupt clear bits
*/
typedef union {
struct {
/** t0_int_clr : WT; bitpos: [0]; default: 0;
* Set this bit to clear the TIMG_T$x_INT interrupt.
*/
uint32_t t0_int_clr: 1;
/** wdt_int_clr : WT; bitpos: [1]; default: 0;
* Set this bit to clear the TIMG_WDT_INT interrupt.
*/
uint32_t wdt_int_clr: 1;
uint32_t reserved_2: 30;
};
uint32_t val;
} _timg_int_clr_timers_reg_t;
/** Group: Version register */
/** Type of ntimers_date register
* Timer version control register
*/
typedef union {
struct {
/** ntimgs_date : R/W; bitpos: [27:0]; default: 33579409;
* Timer version control register
*/
uint32_t ntimgs_date: 28;
uint32_t reserved_28: 4;
};
uint32_t val;
} _timg_ntimers_date_reg_t;
/** Group: Clock configuration registers */
/** Type of regclk register
* Timer group clock gate register
*/
typedef union {
struct {
uint32_t reserved_0: 29;
/** wdt_clk_is_active : R/W; bitpos: [29]; default: 1;
* enable WDT's clock
*/
uint32_t wdt_clk_is_active: 1;
/** timer_clk_is_active : R/W; bitpos: [30]; default: 1;
* enable Timer $x's clock
*/
uint32_t timer_clk_is_active: 1;
/** clk_en : R/W; bitpos: [31]; default: 0;
* Register clock gate signal. 1: Registers can be read and written to by software. 0:
* Registers can not be read or written to by software.
*/
uint32_t clk_en: 1;
};
uint32_t val;
} _timg_regclk_reg_t;
typedef struct {
volatile _timg_txconfig_reg_t config;
volatile _timg_txlo_reg_t lo;
volatile _timg_txhi_reg_t hi;
volatile _timg_txupdate_reg_t update;
volatile _timg_txalarmlo_reg_t alarmlo;
volatile _timg_txalarmhi_reg_t alarmhi;
volatile _timg_txloadlo_reg_t loadlo;
volatile _timg_txloadhi_reg_t loadhi;
volatile _timg_txload_reg_t load;
} _timg_hwtimer_reg_t;
typedef struct _timg_dev_t {
volatile _timg_hwtimer_reg_t hw_timer[1];
uint32_t _reserved_024[9];
volatile _timg_wdtconfig0_reg_t wdtconfig0;
volatile _timg_wdtconfig1_reg_t wdtconfig1;
volatile _timg_wdtconfig2_reg_t wdtconfig2;
volatile _timg_wdtconfig3_reg_t wdtconfig3;
volatile _timg_wdtconfig4_reg_t wdtconfig4;
volatile _timg_wdtconfig5_reg_t wdtconfig5;
volatile _timg_wdtfeed_reg_t wdtfeed;
volatile _timg_wdtwprotect_reg_t wdtwprotect;
volatile _timg_rtccalicfg_reg_t rtccalicfg;
volatile _timg_rtccalicfg1_reg_t rtccalicfg1;
volatile _timg_int_ena_timers_reg_t int_ena_timers;
volatile _timg_int_raw_timers_reg_t int_raw_timers;
volatile _timg_int_st_timers_reg_t int_st_timers;
volatile _timg_int_clr_timers_reg_t int_clr_timers;
volatile _timg_rtccalicfg2_reg_t rtccalicfg2;
uint32_t _reserved_084[29];
volatile _timg_ntimers_date_reg_t ntimers_date;
volatile _timg_regclk_reg_t regclk;
} _timg_dev_t;
#define TIMERG0_BASE 0x6001F000
#define TIMERG1_BASE 0x60020000
#define TIMERG0 ((_timg_dev_t*) TIMERG0_BASE)
#define TIMERG1 ((_timg_dev_t*) TIMERG1_BASE)
__attribute__((always_inline))
static inline void timer_ll_enable_alarm(_timg_dev_t *hw, uint32_t timer_num, bool en)
{
hw->hw_timer[timer_num].config.tx_alarm_en = en;
}
__attribute__((always_inline))
static inline void timer_ll_enable_counter(_timg_dev_t *hw, uint32_t timer_num, bool en)
{
hw->hw_timer[timer_num].config.tx_en = en;
}
__attribute__((always_inline))
static inline void timer_ll_enable_intr(_timg_dev_t *hw, uint32_t timer_num, bool en)
{
if (en) {
hw->int_ena_timers.val |= BIT(timer_num);
} else {
hw->int_ena_timers.val &= ~BIT(timer_num);
}
}
__attribute__((always_inline))
static inline void timer_ll_clear_intr_status(_timg_dev_t *hw, uint32_t timer_num)
{
hw->int_clr_timers.val = BIT(timer_num);
}
static inline uint32_t timer_ll_get_intr_status(_timg_dev_t *hw)
{
return hw->int_st_timers.val;
}
static inline uint32_t timer_ll_get_clock_prescale(_timg_dev_t *hw, uint32_t timer_num)
{
return hw->hw_timer[timer_num].config.tx_divider;
}
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,828 @@
/**
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/** Group: Configuration and Control Register */
/** Type of txconfig register
* Timer x configuration register
*/
typedef union {
struct {
uint32_t reserved_0: 9;
/** tx_use_xtal : R/W; bitpos: [9]; default: 0;
* 1: Use XTAL_CLK as the source clock of timer group. 0: Use APB_CLK as the source
* clock of timer group.
*/
uint32_t tx_use_xtal: 1;
/** tx_alarm_en : R/W; bitpos: [10]; default: 0;
* When set, the alarm is enabled. This bit is automatically cleared once an
*
* alarm occurs.
*/
uint32_t tx_alarm_en: 1;
/** tx_level_int_en : R/W; bitpos: [11]; default: 0;
* When set, an alarm will generate a level type interrupt.
*/
uint32_t tx_level_int_en: 1;
/** tx_edge_int_en : R/W; bitpos: [12]; default: 0;
* When set, an alarm will generate an edge type interrupt.
*/
uint32_t tx_edge_int_en: 1;
/** tx_divider : R/W; bitpos: [28:13]; default: 1;
* Timer x clock (Tx_clk) prescaler value.
*/
uint32_t tx_divider: 16;
/** tx_autoreload : R/W; bitpos: [29]; default: 1;
* When set, timer x auto-reload at alarm is enabled.
*/
uint32_t tx_autoreload: 1;
/** tx_increase : R/W; bitpos: [30]; default: 1;
* When set, the timer x time-base counter will increment every clock tick. When
*
* cleared, the timer x time-base counter will decrement.
*/
uint32_t tx_increase: 1;
/** tx_en : R/W; bitpos: [31]; default: 0;
* When set, the timer x time-base counter is enabled.
*/
uint32_t tx_en: 1;
};
uint32_t val;
} _timg_txconfig_reg_t;
/** Type of txlo register
* Timer x current value, low 32 bits
*/
typedef union {
struct {
/** tx_lo : RO; bitpos: [31:0]; default: 0;
* After writing to TIMG_TxUPDATE_REG, the low 32 bits of the time-base counter
*
* of timer x can be read here.
*/
uint32_t tx_lo: 32;
};
uint32_t val;
} _timg_txlo_reg_t;
/** Type of txhi register
* Timer x current value, high 32 bits
*/
typedef union {
struct {
/** tx_hi : RO; bitpos: [31:0]; default: 0;
* After writing to TIMG_TxUPDATE_REG, the high 32 bits of the time-base counter
*
* of timer x can be read here.
*/
uint32_t tx_hi: 32;
};
uint32_t val;
} _timg_txhi_reg_t;
/** Type of txupdate register
* Write to copy current timer value to TIMGn_Tx_(LO/HI)_REG
*/
typedef union {
struct {
uint32_t reserved_0: 31;
/** tx_update : R/W; bitpos: [31]; default: 0;
* After writing 0 or 1 to TIMG_TxUPDATE_REG, the counter value is latched.
*/
uint32_t tx_update: 1;
};
uint32_t val;
} _timg_txupdate_reg_t;
/** Type of txalarmlo register
* Timer x alarm value, low 32 bits
*/
typedef union {
struct {
/** tx_alarm_lo : R/W; bitpos: [31:0]; default: 0;
* Timer x alarm trigger time-base counter value, low 32 bits.
*/
uint32_t tx_alarm_lo: 32;
};
uint32_t val;
} _timg_txalarmlo_reg_t;
/** Type of txalarmhi register
* Timer x alarm value, high bits
*/
typedef union {
struct {
/** tx_alarm_hi : R/W; bitpos: [31:0]; default: 0;
*
*
* Timer x alarm trigger time-base counter value, high 32 bits.
*/
uint32_t tx_alarm_hi: 32;
};
uint32_t val;
} _timg_txalarmhi_reg_t;
/** Type of txloadlo register
* Timer x reload value, low 32 bits
*/
typedef union {
struct {
/** tx_load_lo : R/W; bitpos: [31:0]; default: 0;
*
*
* Low 32 bits of the value that a reload will load onto timer x time-base
*
* Counter.
*/
uint32_t tx_load_lo: 32;
};
uint32_t val;
} _timg_txloadlo_reg_t;
/** Type of txloadhi register
* Timer x reload value, high 32 bits
*/
typedef union {
struct {
/** tx_load_hi : R/W; bitpos: [31:0]; default: 0;
*
*
* High 32 bits of the value that a reload will load onto timer x time-base
*
* counter.
*/
uint32_t tx_load_hi: 32;
};
uint32_t val;
} _timg_txloadhi_reg_t;
/** Type of txload register
* Write to reload timer from TIMG_T0_(LOADLOLOADHI)_REG
*/
typedef union {
struct {
/** tx_load : WO; bitpos: [31:0]; default: 0;
*
*
* Write any value to trigger a timer x time-base counter reload.
*/
uint32_t tx_load: 32;
};
uint32_t val;
} _timg_txload_reg_t;
/** Group: Configuration and Control Register for WDT */
/** Type of wdtconfig0 register
* Watchdog timer configuration register
*/
typedef union {
struct {
uint32_t reserved_0: 12;
/** wdt_appcpu_reset_en : R/W; bitpos: [12]; default: 0;
* Reserved
*/
uint32_t wdt_appcpu_reset_en: 1;
/** wdt_procpu_reset_en : R/W; bitpos: [13]; default: 0;
* WDT reset CPU enable.
*/
uint32_t wdt_procpu_reset_en: 1;
/** wdt_flashboot_mod_en : R/W; bitpos: [14]; default: 1;
* When set, Flash boot protection is enabled.
*/
uint32_t wdt_flashboot_mod_en: 1;
/** wdt_sys_reset_length : R/W; bitpos: [17:15]; default: 1;
* System reset signal length selection. 0: 100 ns, 1: 200 ns,
*
* 2: 300 ns, 3: 400 ns, 4: 500 ns, 5: 800 ns, 6: 1.6 us, 7: 3.2 us.
*/
uint32_t wdt_sys_reset_length: 3;
/** wdt_cpu_reset_length : R/W; bitpos: [20:18]; default: 1;
* CPU reset signal length selection. 0: 100 ns, 1: 200 ns,
*
* 2: 300 ns, 3: 400 ns, 4: 500 ns, 5: 800 ns, 6: 1.6 us, 7: 3.2 us.
*/
uint32_t wdt_cpu_reset_length: 3;
/** wdt_level_int_en : R/W; bitpos: [21]; default: 0;
* When set, a level type interrupt will occur at the timeout of a stage
*
* configured to generate an interrupt.
*/
uint32_t wdt_level_int_en: 1;
/** wdt_edge_int_en : R/W; bitpos: [22]; default: 0;
* When set, an edge type interrupt will occur at the timeout of a stage
*
* configured to generate an interrupt.
*/
uint32_t wdt_edge_int_en: 1;
/** wdt_stg3 : R/W; bitpos: [24:23]; default: 0;
* Stage 3 configuration. 0: off, 1: interrupt, 2: reset CPU, 3: reset system.
*
*/
uint32_t wdt_stg3: 2;
/** wdt_stg2 : R/W; bitpos: [26:25]; default: 0;
* Stage 2 configuration. 0: off, 1: interrupt, 2: reset CPU, 3: reset system.
*
*/
uint32_t wdt_stg2: 2;
/** wdt_stg1 : R/W; bitpos: [28:27]; default: 0;
* Stage 1 configuration. 0: off, 1: interrupt, 2: reset CPU, 3: reset system.
*
*/
uint32_t wdt_stg1: 2;
/** wdt_stg0 : R/W; bitpos: [30:29]; default: 0;
* Stage 0 configuration. 0: off, 1: interrupt, 2: reset CPU, 3: reset system.
*
*/
uint32_t wdt_stg0: 2;
/** wdt_en : R/W; bitpos: [31]; default: 0;
* When set, MWDT is enabled.
*/
uint32_t wdt_en: 1;
};
uint32_t val;
} _timg_wdtconfig0_reg_t;
/** Type of wdtconfig1 register
* Watchdog timer prescaler register
*/
typedef union {
struct {
uint32_t reserved_0: 16;
/** wdt_clk_prescaler : R/W; bitpos: [31:16]; default: 1;
* MWDT clock prescaler value. MWDT clock period = 12.5 ns *
*
* TIMG_WDT_CLK_PRESCALE.
*/
uint32_t wdt_clk_prescaler: 16;
};
uint32_t val;
} _timg_wdtconfig1_reg_t;
/** Type of wdtconfig2 register
* Watchdog timer stage 0 timeout value
*/
typedef union {
struct {
/** wdt_stg0_hold : R/W; bitpos: [31:0]; default: 26000000;
* Stage 0 timeout value, in MWDT clock cycles.
*/
uint32_t wdt_stg0_hold: 32;
};
uint32_t val;
} _timg_wdtconfig2_reg_t;
/** Type of wdtconfig3 register
* Watchdog timer stage 1 timeout value
*/
typedef union {
struct {
/** wdt_stg1_hold : R/W; bitpos: [31:0]; default: 134217727;
* Stage 1 timeout value, in MWDT clock cycles.
*/
uint32_t wdt_stg1_hold: 32;
};
uint32_t val;
} _timg_wdtconfig3_reg_t;
/** Type of wdtconfig4 register
* Watchdog timer stage 2 timeout value
*/
typedef union {
struct {
/** wdt_stg2_hold : R/W; bitpos: [31:0]; default: 1048575;
* Stage 2 timeout value, in MWDT clock cycles.
*/
uint32_t wdt_stg2_hold: 32;
};
uint32_t val;
} _timg_wdtconfig4_reg_t;
/** Type of wdtconfig5 register
* Watchdog timer stage 3 timeout value
*/
typedef union {
struct {
/** wdt_stg3_hold : R/W; bitpos: [31:0]; default: 1048575;
* Stage 3 timeout value, in MWDT clock cycles.
*/
uint32_t wdt_stg3_hold: 32;
};
uint32_t val;
} _timg_wdtconfig5_reg_t;
/** Type of wdtfeed register
* Write to feed the watchdog timer
*/
typedef union {
struct {
/** wdt_feed : WO; bitpos: [31:0]; default: 0;
* Write any value to feed the MWDT. (WO)
*/
uint32_t wdt_feed: 32;
};
uint32_t val;
} _timg_wdtfeed_reg_t;
/** Type of wdtwprotect register
* Watchdog write protect register
*/
typedef union {
struct {
/** wdt_wkey : R/W; bitpos: [31:0]; default: 1356348065;
* If the register contains a different value than its reset value, write
*
* protection is enabled.
*/
uint32_t wdt_wkey: 32;
};
uint32_t val;
} _timg_wdtwprotect_reg_t;
/** Group: Configuration and Control Register for RTC CALI */
/** Type of rtccalicfg register
* RTC calibration configuration register
*/
typedef union {
struct {
uint32_t reserved_0: 12;
/** rtc_cali_start_cycling : R/W; bitpos: [12]; default: 1;
* Reserved
*/
uint32_t rtc_cali_start_cycling: 1;
/** rtc_cali_clk_sel : R/W; bitpos: [14:13]; default: 1;
* 0:rtcslowclock. 1:clk_80m. 2:xtal_32k.
*/
uint32_t rtc_cali_clk_sel: 2;
/** rtc_cali_rdy : RO; bitpos: [15]; default: 0;
* Reserved
*/
uint32_t rtc_cali_rdy: 1;
/** rtc_cali_max : R/W; bitpos: [30:16]; default: 1;
* Reserved
*/
uint32_t rtc_cali_max: 15;
/** rtc_cali_start : R/W; bitpos: [31]; default: 0;
* Reserved
*/
uint32_t rtc_cali_start: 1;
};
uint32_t val;
} _timg_rtccalicfg_reg_t;
/** Type of rtccalicfg1 register
* RTC calibration configuration1 register
*/
typedef union {
struct {
/** rtc_cali_cycling_data_vld : RO; bitpos: [0]; default: 0;
* Reserved
*/
uint32_t rtc_cali_cycling_data_vld: 1;
uint32_t reserved_1: 6;
/** rtc_cali_value : RO; bitpos: [31:7]; default: 0;
* Reserved
*/
uint32_t rtc_cali_value: 25;
};
uint32_t val;
} _timg_rtccalicfg1_reg_t;
/** Type of rtccalicfg2 register
* Timer group calibration register
*/
typedef union {
struct {
/** rtc_cali_timeout : RO; bitpos: [0]; default: 0;
* RTC calibration timeout indicator
*/
uint32_t rtc_cali_timeout: 1;
uint32_t reserved_1: 2;
/** rtc_cali_timeout_rst_cnt : R/W; bitpos: [6:3]; default: 3;
* Cycles that release calibration timeout reset
*/
uint32_t rtc_cali_timeout_rst_cnt: 4;
/** rtc_cali_timeout_thres : R/W; bitpos: [31:7]; default: 33554431;
* Threshold value for the RTC calibration timer. If the calibration timer's value
* exceeds this threshold, a timeout is triggered.
*/
uint32_t rtc_cali_timeout_thres: 25;
};
uint32_t val;
} _timg_rtccalicfg2_reg_t;
/** Group: Configuration and Control Register for LACT */
/** Type of lactconfig register
* LACT configuration register
*/
typedef union {
struct {
uint32_t reserved_0: 6;
/** lact_use_reftick : R/W; bitpos: [6]; default: 0;
* Reserved
*/
uint32_t lact_use_reftick: 1;
/** lact_rtc_only : R/W; bitpos: [7]; default: 0;
* Reserved
*/
uint32_t lact_rtc_only: 1;
/** lact_cpst_en : R/W; bitpos: [8]; default: 1;
* Reserved
*/
uint32_t lact_cpst_en: 1;
/** lact_lac_en : R/W; bitpos: [9]; default: 1;
* Reserved
*/
uint32_t lact_lac_en: 1;
/** lact_alarm_en : R/W; bitpos: [10]; default: 0;
* Reserved
*/
uint32_t lact_alarm_en: 1;
/** lact_level_int_en : R/W; bitpos: [11]; default: 0;
* Reserved
*/
uint32_t lact_level_int_en: 1;
/** lact_edge_int_en : R/W; bitpos: [12]; default: 0;
* Reserved
*/
uint32_t lact_edge_int_en: 1;
/** lact_divider : R/W; bitpos: [28:13]; default: 1;
* Reserved
*/
uint32_t lact_divider: 16;
/** lact_autoreload : R/W; bitpos: [29]; default: 1;
* Reserved
*/
uint32_t lact_autoreload: 1;
/** lact_increase : R/W; bitpos: [30]; default: 1;
* Reserved
*/
uint32_t lact_increase: 1;
/** lact_en : R/W; bitpos: [31]; default: 0;
* Reserved
*/
uint32_t lact_en: 1;
};
uint32_t val;
} _timg_lactconfig_reg_t;
/** Type of lactrtc register
* LACT RTC register
*/
typedef union {
struct {
uint32_t reserved_0: 6;
/** lact_rtc_step_len : R/W; bitpos: [31:6]; default: 0;
* Reserved
*/
uint32_t lact_rtc_step_len: 26;
};
uint32_t val;
} _timg_lactrtc_reg_t;
/** Type of lactlo register
* LACT low register
*/
typedef union {
struct {
/** lact_lo : RO; bitpos: [31:0]; default: 0;
* Reserved
*/
uint32_t lact_lo: 32;
};
uint32_t val;
} _timg_lactlo_reg_t;
/** Type of lacthi register
* LACT high register
*/
typedef union {
struct {
/** lact_hi : RO; bitpos: [31:0]; default: 0;
* Reserved
*/
uint32_t lact_hi: 32;
};
uint32_t val;
} _timg_lacthi_reg_t;
/** Type of lactupdate register
* LACT update register
*/
typedef union {
struct {
/** lact_update : WO; bitpos: [31:0]; default: 0;
* Reserved
*/
uint32_t lact_update: 32;
};
uint32_t val;
} _timg_lactupdate_reg_t;
/** Type of lactalarmlo register
* LACT alarm low register
*/
typedef union {
struct {
/** lact_alarm_lo : R/W; bitpos: [31:0]; default: 0;
* Reserved
*/
uint32_t lact_alarm_lo: 32;
};
uint32_t val;
} _timg_lactalarmlo_reg_t;
/** Type of lactalarmhi register
* LACT alarm high register
*/
typedef union {
struct {
/** lact_alarm_hi : R/W; bitpos: [31:0]; default: 0;
* Reserved
*/
uint32_t lact_alarm_hi: 32;
};
uint32_t val;
} _timg_lactalarmhi_reg_t;
/** Type of lactloadlo register
* LACT load low register
*/
typedef union {
struct {
/** lact_load_lo : R/W; bitpos: [31:0]; default: 0;
* Reserved
*/
uint32_t lact_load_lo: 32;
};
uint32_t val;
} _timg_lactloadlo_reg_t;
/** Type of lactloadhi register
* Timer LACT load high register
*/
typedef union {
struct {
/** lact_load_hi : R/W; bitpos: [31:0]; default: 0;
* Reserved
*/
uint32_t lact_load_hi: 32;
};
uint32_t val;
} _timg_lactloadhi_reg_t;
/** Type of lactload register
* Timer LACT load register
*/
typedef union {
struct {
/** lact_load : WO; bitpos: [31:0]; default: 0;
* Reserved
*/
uint32_t lact_load: 32;
};
uint32_t val;
} _timg_lactload_reg_t;
/** Group: Interrupt Register */
/** Type of int_ena_timers register
* Interrupt enable bits
*/
typedef union {
struct {
/** t0_int_ena : R/W; bitpos: [0]; default: 0;
* The interrupt enable bit for the TIMG_T0_INT interrupt.
*/
uint32_t t0_int_ena: 1;
/** t1_int_ena : R/W; bitpos: [1]; default: 0;
* The interrupt enable bit for the TIMG_T1_INT interrupt.
*/
uint32_t t1_int_ena: 1;
/** wdt_int_ena : R/W; bitpos: [2]; default: 0;
* The interrupt enable bit for the TIMG_WDT_INT interrupt.
*/
uint32_t wdt_int_ena: 1;
/** lact_int_ena : R/W; bitpos: [3]; default: 0;
* The interrupt enable bit for the TIMG_LACT_INT interrupt.
*/
uint32_t lact_int_ena: 1;
uint32_t reserved_4: 28;
};
uint32_t val;
} _timg_int_ena_timers_reg_t;
/** Type of int_raw_timers register
* Raw interrupt status
*/
typedef union {
struct {
/** t0_int_raw : RO; bitpos: [0]; default: 0;
* The raw interrupt status bit for the TIMG_T0_INT interrupt.
*/
uint32_t t0_int_raw: 1;
/** t1_int_raw : RO; bitpos: [1]; default: 0;
* The raw interrupt status bit for the TIMG_T1_INT interrupt.
*/
uint32_t t1_int_raw: 1;
/** wdt_int_raw : RO; bitpos: [2]; default: 0;
* The raw interrupt status bit for the TIMG_WDT_INT interrupt.
*/
uint32_t wdt_int_raw: 1;
/** lact_int_raw : RO; bitpos: [3]; default: 0;
* The raw interrupt status bit for the TIMG_LACT_INT interrupt.
*/
uint32_t lact_int_raw: 1;
uint32_t reserved_4: 28;
};
uint32_t val;
} _timg_int_raw_timers_reg_t;
/** Type of int_st_timers register
* Masked interrupt status
*/
typedef union {
struct {
/** t0_int_st : RO; bitpos: [0]; default: 0;
* The masked interrupt status bit for the TIMG_T0_INT interrupt.
*/
uint32_t t0_int_st: 1;
/** t1_int_st : RO; bitpos: [1]; default: 0;
* The masked interrupt status bit for the TIMG_T1_INT interrupt.
*/
uint32_t t1_int_st: 1;
/** wdt_int_st : RO; bitpos: [2]; default: 0;
* The masked interrupt status bit for the TIMG_WDT_INT interrupt.
*/
uint32_t wdt_int_st: 1;
/** lact_int_st : RO; bitpos: [3]; default: 0;
* The masked interrupt status bit for the TIMG_LACT_INT interrupt.
*/
uint32_t lact_int_st: 1;
uint32_t reserved_4: 28;
};
uint32_t val;
} _timg_int_st_timers_reg_t;
/** Type of int_clr_timers register
* Interrupt clear bits
*/
typedef union {
struct {
/** t0_int_clr : WO; bitpos: [0]; default: 0;
* Set this bit to clear the TIMG_T0_INT interrupt.
*/
uint32_t t0_int_clr: 1;
/** t1_int_clr : WO; bitpos: [1]; default: 0;
* Set this bit to clear the TIMG_T1_INT interrupt.
*/
uint32_t t1_int_clr: 1;
/** wdt_int_clr : WO; bitpos: [2]; default: 0;
* Set this bit to clear the TIMG_WDT_INT interrupt.
*/
uint32_t wdt_int_clr: 1;
/** lact_int_clr : WO; bitpos: [3]; default: 0;
* Set this bit to clear the TIMG_LACT_INT interrupt.
*/
uint32_t lact_int_clr: 1;
uint32_t reserved_4: 28;
};
uint32_t val;
} _timg_int_clr_timers_reg_t;
/** Group: Version Register */
/** Type of timers_date register
* Version control register
*/
typedef union {
struct {
/** timers_date : R/W; bitpos: [27:0]; default: 26243681;
* Version control register.
*/
uint32_t timers_date: 28;
uint32_t reserved_28: 4;
};
uint32_t val;
} _timg_timers_date_reg_t;
/** Group: Configuration Register */
/** Type of regclk register
* Timer group clock gate register
*/
typedef union {
struct {
uint32_t reserved_0: 31;
/** clk_en : R/W; bitpos: [31]; default: 0;
* Register clock gate signal. 1: Registers can be read and written to by software. 0:
* Registers can not be read or written to by software.
*/
uint32_t clk_en: 1;
};
uint32_t val;
} _timg_regclk_reg_t;
typedef struct {
volatile _timg_txconfig_reg_t config;
volatile _timg_txlo_reg_t lo;
volatile _timg_txhi_reg_t hi;
volatile _timg_txupdate_reg_t update;
volatile _timg_txalarmlo_reg_t alarmlo;
volatile _timg_txalarmhi_reg_t alarmhi;
volatile _timg_txloadlo_reg_t loadlo;
volatile _timg_txloadhi_reg_t loadhi;
volatile _timg_txload_reg_t load;
} _timg_hwtimer_reg_t;
typedef struct _timg_dev_t {
volatile _timg_hwtimer_reg_t hw_timer[2];
volatile _timg_wdtconfig0_reg_t wdtconfig0;
volatile _timg_wdtconfig1_reg_t wdtconfig1;
volatile _timg_wdtconfig2_reg_t wdtconfig2;
volatile _timg_wdtconfig3_reg_t wdtconfig3;
volatile _timg_wdtconfig4_reg_t wdtconfig4;
volatile _timg_wdtconfig5_reg_t wdtconfig5;
volatile _timg_wdtfeed_reg_t wdtfeed;
volatile _timg_wdtwprotect_reg_t wdtwprotect;
volatile _timg_rtccalicfg_reg_t rtccalicfg;
volatile _timg_rtccalicfg1_reg_t rtccalicfg1;
volatile _timg_lactconfig_reg_t lactconfig;
volatile _timg_lactrtc_reg_t lactrtc;
volatile _timg_lactlo_reg_t lactlo;
volatile _timg_lacthi_reg_t lacthi;
volatile _timg_lactupdate_reg_t lactupdate;
volatile _timg_lactalarmlo_reg_t lactalarmlo;
volatile _timg_lactalarmhi_reg_t lactalarmhi;
volatile _timg_lactloadlo_reg_t lactloadlo;
volatile _timg_lactloadhi_reg_t lactloadhi;
volatile _timg_lactload_reg_t lactload;
volatile _timg_int_ena_timers_reg_t int_ena_timers;
volatile _timg_int_raw_timers_reg_t int_raw_timers;
volatile _timg_int_st_timers_reg_t int_st_timers;
volatile _timg_int_clr_timers_reg_t int_clr_timers;
volatile _timg_rtccalicfg2_reg_t rtccalicfg2;
uint32_t _reserved_0ac[19];
volatile _timg_timers_date_reg_t timers_date;
volatile _timg_regclk_reg_t regclk;
} _timg_dev_t;
#define TIMERG0_BASE 0x3f41F000
#define TIMERG1_BASE 0x3f420000
#define TIMERG0 ((_timg_dev_t*) TIMERG0_BASE)
#define TIMERG1 ((_timg_dev_t*) TIMERG1_BASE)
__attribute__((always_inline))
static inline void timer_ll_enable_alarm(_timg_dev_t *hw, uint32_t timer_num, bool en)
{
hw->hw_timer[timer_num].config.tx_alarm_en = en;
// use level type interrupt
hw->hw_timer[timer_num].config.tx_level_int_en = en;
}
__attribute__((always_inline))
static inline void timer_ll_enable_counter(_timg_dev_t *hw, uint32_t timer_num, bool en)
{
hw->hw_timer[timer_num].config.tx_en = en;
}
__attribute__((always_inline))
static inline void timer_ll_enable_intr(_timg_dev_t *hw, uint32_t timer_num, bool en)
{
if (en) {
hw->int_ena_timers.val |= BIT(timer_num);
} else {
hw->int_ena_timers.val &= ~BIT(timer_num);
}
}
__attribute__((always_inline))
static inline void timer_ll_clear_intr_status(_timg_dev_t *hw, uint32_t timer_num)
{
hw->int_clr_timers.val = BIT(timer_num);
}
static inline uint32_t timer_ll_get_intr_status(_timg_dev_t *hw)
{
return hw->int_st_timers.val;
}
static inline uint32_t timer_ll_get_clock_prescale(_timg_dev_t *hw, uint32_t timer_num)
{
return hw->hw_timer[timer_num].config.tx_divider;
}
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,593 @@
/**
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/** Group: Configuration and control registers */
/** Type of tnconfig register
* Timer n configuration register
*/
typedef union {
struct {
uint32_t reserved_0: 9;
/** tn_use_xtal : R/W; bitpos: [9]; default: 0;
* 1: Use XTAL_CLK as the source clock of timer group. 0: Use APB_CLK as the source
* clock of timer group.
*/
uint32_t tn_use_xtal: 1;
/** tn_alarm_en : R/W/SC; bitpos: [10]; default: 0;
* When set, the alarm is enabled. This bit is automatically cleared once an
* alarm occurs.
*/
uint32_t tn_alarm_en: 1;
uint32_t reserved_11: 1;
/** tn_divcnt_rst : WT; bitpos: [12]; default: 0;
* When set, Timer n 's clock divider counter will be reset.
*/
uint32_t tn_divcnt_rst: 1;
/** tn_divider : R/W; bitpos: [28:13]; default: 1;
* Timer n clock (Tn_clk) prescaler value.
*/
uint32_t tn_divider: 16;
/** tn_autoreload : R/W; bitpos: [29]; default: 1;
* When set, timer n auto-reload at alarm is enabled.
*/
uint32_t tn_autoreload: 1;
/** tn_increase : R/W; bitpos: [30]; default: 1;
* When set, the timer n time-base counter will increment every clock tick. When
* cleared, the timer n time-base counter will decrement.
*/
uint32_t tn_increase: 1;
/** tn_en : R/W; bitpos: [31]; default: 0;
* When set, the timer n time-base counter is enabled.
*/
uint32_t tn_en: 1;
};
uint32_t val;
} _timg_tnconfig_reg_t;
/** Type of tnlo register
* Timer n current value, low 32 bits
*/
typedef union {
struct {
/** tn_lo : RO; bitpos: [31:0]; default: 0;
* After writing to TIMG_TnUPDATE_REG, the low 32 bits of the time-base counter
* of timer n can be read here.
*/
uint32_t tn_lo: 32;
};
uint32_t val;
} _timg_tnlo_reg_t;
/** Type of tnhi register
* Timer n current value, high 22 bits
*/
typedef union {
struct {
/** tn_hi : RO; bitpos: [21:0]; default: 0;
* After writing to TIMG_TnUPDATE_REG, the high 22 bits of the time-base counter
* of timer n can be read here.
*/
uint32_t tn_hi: 22;
uint32_t reserved_22: 10;
};
uint32_t val;
} _timg_tnhi_reg_t;
/** Type of tnupdate register
* Write to copy current timer value to TIMGn_Tn_(LO/HI)_REG
*/
typedef union {
struct {
uint32_t reserved_0: 31;
/** tn_update : R/W/SC; bitpos: [31]; default: 0;
* After writing 0 or 1 to TIMG_TnUPDATE_REG, the counter value is latched.
*/
uint32_t tn_update: 1;
};
uint32_t val;
} _timg_tnupdate_reg_t;
/** Type of tnalarmlo register
* Timer n alarm value, low 32 bits
*/
typedef union {
struct {
/** tn_alarm_lo : R/W; bitpos: [31:0]; default: 0;
* Timer n alarm trigger time-base counter value, low 32 bits.
*/
uint32_t tn_alarm_lo: 32;
};
uint32_t val;
} _timg_tnalarmlo_reg_t;
/** Type of tnalarmhi register
* Timer n alarm value, high bits
*/
typedef union {
struct {
/** tn_alarm_hi : R/W; bitpos: [21:0]; default: 0;
* Timer n alarm trigger time-base counter value, high 22 bits.
*/
uint32_t tn_alarm_hi: 22;
uint32_t reserved_22: 10;
};
uint32_t val;
} _timg_tnalarmhi_reg_t;
/** Type of tnloadlo register
* Timer n reload value, low 32 bits
*/
typedef union {
struct {
/** tn_load_lo : R/W; bitpos: [31:0]; default: 0;
* Low 32 bits of the value that a reload will load onto timer n time-base
* Counter.
*/
uint32_t tn_load_lo: 32;
};
uint32_t val;
} _timg_tnloadlo_reg_t;
/** Type of tnloadhi register
* Timer n reload value, high 22 bits
*/
typedef union {
struct {
/** tn_load_hi : R/W; bitpos: [21:0]; default: 0;
* High 22 bits of the value that a reload will load onto timer n time-base
* counter.
*/
uint32_t tn_load_hi: 22;
uint32_t reserved_22: 10;
};
uint32_t val;
} _timg_tnloadhi_reg_t;
/** Type of tnload register
* Write to reload timer from TIMG_Tn_(LOADLOLOADHI)_REG
*/
typedef union {
struct {
/** tn_load : WT; bitpos: [31:0]; default: 0;
*
* Write any value to trigger a timer n time-base counter reload.
*/
uint32_t tn_load: 32;
};
uint32_t val;
} _timg_tnload_reg_t;
/** Group: Configuration and control registers for WDT */
/** Type of wdtconfig0 register
* Watchdog timer configuration register
*/
typedef union {
struct {
uint32_t reserved_0: 12;
/** wdt_appcpu_reset_en : R/W; bitpos: [12]; default: 0;
* Reserved
*/
uint32_t wdt_appcpu_reset_en: 1;
/** wdt_procpu_reset_en : R/W; bitpos: [13]; default: 0;
* WDT reset CPU enable.
*/
uint32_t wdt_procpu_reset_en: 1;
/** wdt_flashboot_mod_en : R/W; bitpos: [14]; default: 1;
* When set, Flash boot protection is enabled.
*/
uint32_t wdt_flashboot_mod_en: 1;
/** wdt_sys_reset_length : R/W; bitpos: [17:15]; default: 1;
* System reset signal length selection. 0: 100 ns, 1: 200 ns,
* 2: 300 ns, 3: 400 ns, 4: 500 ns, 5: 800 ns, 6: 1.6 us, 7: 3.2 us.
*/
uint32_t wdt_sys_reset_length: 3;
/** wdt_cpu_reset_length : R/W; bitpos: [20:18]; default: 1;
* CPU reset signal length selection. 0: 100 ns, 1: 200 ns,
* 2: 300 ns, 3: 400 ns, 4: 500 ns, 5: 800 ns, 6: 1.6 us, 7: 3.2 us.
*/
uint32_t wdt_cpu_reset_length: 3;
uint32_t reserved_21: 2;
/** wdt_stg3 : R/W; bitpos: [24:23]; default: 0;
* Stage 3 configuration. 0: off, 1: interrupt, 2: reset CPU, 3: reset system.
*/
uint32_t wdt_stg3: 2;
/** wdt_stg2 : R/W; bitpos: [26:25]; default: 0;
* Stage 2 configuration. 0: off, 1: interrupt, 2: reset CPU, 3: reset system.
*/
uint32_t wdt_stg2: 2;
/** wdt_stg1 : R/W; bitpos: [28:27]; default: 0;
* Stage 1 configuration. 0: off, 1: interrupt, 2: reset CPU, 3: reset system.
*/
uint32_t wdt_stg1: 2;
/** wdt_stg0 : R/W; bitpos: [30:29]; default: 0;
* Stage 0 configuration. 0: off, 1: interrupt, 2: reset CPU, 3: reset system.
*/
uint32_t wdt_stg0: 2;
/** wdt_en : R/W; bitpos: [31]; default: 0;
* When set, MWDT is enabled.
*/
uint32_t wdt_en: 1;
};
uint32_t val;
} _timg_wdtconfig0_reg_t;
/** Type of wdtconfig1 register
* Watchdog timer prescaler register
*/
typedef union {
struct {
uint32_t reserved_0: 16;
/** wdt_clk_prescale : R/W; bitpos: [31:16]; default: 1;
* MWDT clock prescaler value. MWDT clock period = 12.5 ns *
* TIMG_WDT_CLK_PRESCALE.
*/
uint32_t wdt_clk_prescale: 16;
};
uint32_t val;
} _timg_wdtconfig1_reg_t;
/** Type of wdtconfig2 register
* Watchdog timer stage 0 timeout value
*/
typedef union {
struct {
/** wdt_stg0_hold : R/W; bitpos: [31:0]; default: 26000000;
* Stage 0 timeout value, in MWDT clock cycles.
*/
uint32_t wdt_stg0_hold: 32;
};
uint32_t val;
} _timg_wdtconfig2_reg_t;
/** Type of wdtconfig3 register
* Watchdog timer stage 1 timeout value
*/
typedef union {
struct {
/** wdt_stg1_hold : R/W; bitpos: [31:0]; default: 134217727;
* Stage 1 timeout value, in MWDT clock cycles.
*/
uint32_t wdt_stg1_hold: 32;
};
uint32_t val;
} _timg_wdtconfig3_reg_t;
/** Type of wdtconfig4 register
* Watchdog timer stage 2 timeout value
*/
typedef union {
struct {
/** wdt_stg2_hold : R/W; bitpos: [31:0]; default: 1048575;
* Stage 2 timeout value, in MWDT clock cycles.
*/
uint32_t wdt_stg2_hold: 32;
};
uint32_t val;
} _timg_wdtconfig4_reg_t;
/** Type of wdtconfig5 register
* Watchdog timer stage 3 timeout value
*/
typedef union {
struct {
/** wdt_stg3_hold : R/W; bitpos: [31:0]; default: 1048575;
* Stage 3 timeout value, in MWDT clock cycles.
*/
uint32_t wdt_stg3_hold: 32;
};
uint32_t val;
} _timg_wdtconfig5_reg_t;
/** Type of wdtfeed register
* Write to feed the watchdog timer
*/
typedef union {
struct {
/** wdt_feed : WT; bitpos: [31:0]; default: 0;
* Write any value to feed the MWDT. (WO)
*/
uint32_t wdt_feed: 32;
};
uint32_t val;
} _timg_wdtfeed_reg_t;
/** Type of wdtwprotect register
* Watchdog write protect register
*/
typedef union {
struct {
/** wdt_wkey : R/W; bitpos: [31:0]; default: 1356348065;
* If the register contains a different value than its reset value, write
* protection is enabled.
*/
uint32_t wdt_wkey: 32;
};
uint32_t val;
} _timg_wdtwprotect_reg_t;
/** Group: Configuration and control registers for RTC CALI */
/** Type of rtccalicfg register
* RTC calibration configure register
*/
typedef union {
struct {
uint32_t reserved_0: 12;
/** rtc_cali_start_cycling : R/W; bitpos: [12]; default: 1;
* Reserved
*/
uint32_t rtc_cali_start_cycling: 1;
/** rtc_cali_clk_sel : R/W; bitpos: [14:13]; default: 1;
* 0:rtc slow clock. 1:clk_80m. 2:xtal_32k.
*/
uint32_t rtc_cali_clk_sel: 2;
/** rtc_cali_rdy : RO; bitpos: [15]; default: 0;
* Reserved
*/
uint32_t rtc_cali_rdy: 1;
/** rtc_cali_max : R/W; bitpos: [30:16]; default: 1;
* Reserved
*/
uint32_t rtc_cali_max: 15;
/** rtc_cali_start : R/W; bitpos: [31]; default: 0;
* Reserved
*/
uint32_t rtc_cali_start: 1;
};
uint32_t val;
} _timg_rtccalicfg_reg_t;
/** Type of rtccalicfg1 register
* RTC calibration configure1 register
*/
typedef union {
struct {
/** rtc_cali_cycling_data_vld : RO; bitpos: [0]; default: 0;
* Reserved
*/
uint32_t rtc_cali_cycling_data_vld: 1;
uint32_t reserved_1: 6;
/** rtc_cali_value : RO; bitpos: [31:7]; default: 0;
* Reserved
*/
uint32_t rtc_cali_value: 25;
};
uint32_t val;
} _timg_rtccalicfg1_reg_t;
/** Type of rtccalicfg2 register
* Timer group calibration register
*/
typedef union {
struct {
/** rtc_cali_timeout : RO; bitpos: [0]; default: 0;
* RTC calibration timeout indicator
*/
uint32_t rtc_cali_timeout: 1;
uint32_t reserved_1: 2;
/** rtc_cali_timeout_rst_cnt : R/W; bitpos: [6:3]; default: 3;
* Cycles that release calibration timeout reset
*/
uint32_t rtc_cali_timeout_rst_cnt: 4;
/** rtc_cali_timeout_thres : R/W; bitpos: [31:7]; default: 33554431;
* Threshold value for the RTC calibration timer. If the calibration timer's value
* exceeds this threshold, a timeout is triggered.
*/
uint32_t rtc_cali_timeout_thres: 25;
};
uint32_t val;
} _timg_rtccalicfg2_reg_t;
/** Group: Interrupt registers */
/** Type of int_ena_timers register
* Interrupt enable bits
*/
typedef union {
struct {
/** t0_int_ena : R/W; bitpos: [0]; default: 0;
* The interrupt enable bit for the TIMG_T0_INT interrupt.
*/
uint32_t t0_int_ena: 1;
/** t1_int_ena : R/W; bitpos: [1]; default: 0;
* The interrupt enable bit for the TIMG_T1_INT interrupt.
*/
uint32_t t1_int_ena: 1;
/** wdt_int_ena : R/W; bitpos: [2]; default: 0;
* The interrupt enable bit for the TIMG_WDT_INT interrupt.
*/
uint32_t wdt_int_ena: 1;
uint32_t reserved_3: 29;
};
uint32_t val;
} _timg_int_ena_timers_reg_t;
/** Type of int_raw_timers register
* Raw interrupt status
*/
typedef union {
struct {
/** t0_int_raw : R/WTC/SS; bitpos: [0]; default: 0;
* The raw interrupt status bit for the TIMG_T0_INT interrupt.
*/
uint32_t t0_int_raw: 1;
/** t1_int_raw : R/WTC/SS; bitpos: [1]; default: 0;
* The raw interrupt status bit for the TIMG_T1_INT interrupt.
*/
uint32_t t1_int_raw: 1;
/** wdt_int_raw : R/WTC/SS; bitpos: [2]; default: 0;
* The raw interrupt status bit for the TIMG_WDT_INT interrupt.
*/
uint32_t wdt_int_raw: 1;
uint32_t reserved_3: 29;
};
uint32_t val;
} _timg_int_raw_timers_reg_t;
/** Type of int_st_timers register
* Masked interrupt status
*/
typedef union {
struct {
/** t0_int_st : RO; bitpos: [0]; default: 0;
* The masked interrupt status bit for the TIMG_T0_INT interrupt.
*/
uint32_t t0_int_st: 1;
/** t1_int_st : RO; bitpos: [1]; default: 0;
* The masked interrupt status bit for the TIMG_T1_INT interrupt.
*/
uint32_t t1_int_st: 1;
/** wdt_int_st : RO; bitpos: [2]; default: 0;
* The masked interrupt status bit for the TIMG_WDT_INT interrupt.
*/
uint32_t wdt_int_st: 1;
uint32_t reserved_3: 29;
};
uint32_t val;
} _timg_int_st_timers_reg_t;
/** Type of int_clr_timers register
* Interrupt clear bits
*/
typedef union {
struct {
/** t0_int_clr : WT; bitpos: [0]; default: 0;
* Set this bit to clear the TIMG_T0_INT interrupt.
*/
uint32_t t0_int_clr: 1;
/** t1_int_clr : WT; bitpos: [1]; default: 0;
* Set this bit to clear the TIMG_T1_INT interrupt.
*/
uint32_t t1_int_clr: 1;
/** wdt_int_clr : WT; bitpos: [2]; default: 0;
* Set this bit to clear the TIMG_WDT_INT interrupt.
*/
uint32_t wdt_int_clr: 1;
uint32_t reserved_3: 29;
};
uint32_t val;
} _timg_int_clr_timers_reg_t;
/** Group: Configuration registers */
/** Type of ntimers_date register
* Timer version control register
*/
typedef union {
struct {
/** ntimers_date : R/W; bitpos: [27:0]; default: 33566833;
* Timer version control register
*/
uint32_t ntimers_date: 28;
uint32_t reserved_28: 4;
};
uint32_t val;
} _timg_ntimers_date_reg_t;
/** Type of regclk register
* Timer group clock gate register
*/
typedef union {
struct {
uint32_t reserved_0: 31;
/** clk_en : R/W; bitpos: [31]; default: 0;
* Register clock gate signal. 1: The clock for software to read and write registers
* is always on. 0: The clock for software to read and write registers only exits when
* the operation happens.
*/
uint32_t clk_en: 1;
};
uint32_t val;
} _timg_regclk_reg_t;
typedef struct {
volatile _timg_tnconfig_reg_t config;
volatile _timg_tnlo_reg_t lo;
volatile _timg_tnhi_reg_t hi;
volatile _timg_tnupdate_reg_t update;
volatile _timg_tnalarmlo_reg_t alarmlo;
volatile _timg_tnalarmhi_reg_t alarmhi;
volatile _timg_tnloadlo_reg_t loadlo;
volatile _timg_tnloadhi_reg_t loadhi;
volatile _timg_tnload_reg_t load;
} _timg_hwtimer_reg_t;
typedef struct _timg_dev_t {
volatile _timg_hwtimer_reg_t hw_timer[2];
volatile _timg_wdtconfig0_reg_t wdtconfig0;
volatile _timg_wdtconfig1_reg_t wdtconfig1;
volatile _timg_wdtconfig2_reg_t wdtconfig2;
volatile _timg_wdtconfig3_reg_t wdtconfig3;
volatile _timg_wdtconfig4_reg_t wdtconfig4;
volatile _timg_wdtconfig5_reg_t wdtconfig5;
volatile _timg_wdtfeed_reg_t wdtfeed;
volatile _timg_wdtwprotect_reg_t wdtwprotect;
volatile _timg_rtccalicfg_reg_t rtccalicfg;
volatile _timg_rtccalicfg1_reg_t rtccalicfg1;
volatile _timg_int_ena_timers_reg_t int_ena_timers;
volatile _timg_int_raw_timers_reg_t int_raw_timers;
volatile _timg_int_st_timers_reg_t int_st_timers;
volatile _timg_int_clr_timers_reg_t int_clr_timers;
volatile _timg_rtccalicfg2_reg_t rtccalicfg2;
uint32_t _reserved_084[29];
volatile _timg_ntimers_date_reg_t ntimers_date;
volatile _timg_regclk_reg_t regclk;
} _timg_dev_t;
#define TIMERG0_BASE 0x6001F000
#define TIMERG1_BASE 0x60020000
#define TIMERG0 ((_timg_dev_t*) TIMERG0_BASE)
#define TIMERG1 ((_timg_dev_t*) TIMERG1_BASE)
__attribute__((always_inline))
static inline void timer_ll_enable_alarm(_timg_dev_t *hw, uint32_t timer_num, bool en)
{
hw->hw_timer[timer_num].config.tn_alarm_en = en;
}
__attribute__((always_inline))
static inline void timer_ll_enable_counter(_timg_dev_t *hw, uint32_t timer_num, bool en)
{
hw->hw_timer[timer_num].config.tn_en = en;
}
__attribute__((always_inline))
static inline void timer_ll_enable_intr(_timg_dev_t *hw, uint32_t timer_num, bool en)
{
if (en) {
hw->int_ena_timers.val |= BIT(timer_num);
} else {
hw->int_ena_timers.val &= ~BIT(timer_num);
}
}
__attribute__((always_inline))
static inline void timer_ll_clear_intr_status(_timg_dev_t *hw, uint32_t timer_num)
{
hw->int_clr_timers.val = BIT(timer_num);
}
static inline uint32_t timer_ll_get_intr_status(_timg_dev_t *hw)
{
return hw->int_st_timers.val;
}
static inline uint32_t timer_ll_get_clock_prescale(_timg_dev_t *hw, uint32_t timer_num)
{
return hw->hw_timer[timer_num].config.tn_divider;
}
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,524 @@
// Copyright 2010-2021 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "sdkconfig.h"
#if CONFIG_IDF_TARGET_ESP32S3
#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "esp_heap_caps.h"
#include "esp_log.h"
#include "esp32s3/rom/lldesc.h"
#include "esp32s3/rom/gpio.h"
#include "driver/gpio.h"
#include "soc/gpio_periph.h"
#include "soc/system_reg.h"
#include "soc/lcd_cam_struct.h"
#include "soc/lcd_cam_reg.h"
#include "soc/gdma_struct.h"
#include "soc/gdma_periph.h"
#include "soc/gdma_reg.h"
#include "i2s_lcd_driver.h"
static const char *TAG = "ESP32S3_LCD";
#define LCD_CHECK(a, str, ret) if (!(a)) { \
ESP_LOGE(TAG,"%s:%d (%s):%s", __FILE__, __LINE__, __FUNCTION__, str); \
return (ret); \
}
#define LCD_CAM_DMA_NODE_BUFFER_MAX_SIZE (4000)
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0))
#define ets_delay_us esp_rom_delay_us
#define portTICK_RATE_MS portTICK_PERIOD_MS
#endif
typedef struct {
uint32_t dma_buffer_size;
uint32_t dma_half_buffer_size;
uint32_t dma_node_buffer_size;
uint32_t dma_node_cnt;
uint32_t dma_half_node_cnt;
lldesc_t *dma;
uint8_t *dma_buffer;
QueueHandle_t event_queue;
uint8_t width;
bool swap_data;
uint8_t dma_num;
intr_handle_t dma_out_intr_handle;
} lcd_cam_obj_t;
typedef struct {
int rs_io_num;
lcd_cam_obj_t *i2s_lcd_obj;
SemaphoreHandle_t mutex;
} i2s_lcd_driver_t;
static void IRAM_ATTR dma_isr(void *arg)
{
BaseType_t woken = pdFALSE;
lcd_cam_obj_t *lcd_cam_obj = (lcd_cam_obj_t *)arg;
uint32_t out_status = GDMA.channel[lcd_cam_obj->dma_num].out.int_st.val;
if (out_status & GDMA_OUT_EOF_CH0_INT_ST) {
GDMA.channel[lcd_cam_obj->dma_num].out.int_clr.val = GDMA_OUT_EOF_CH0_INT_ST;
xQueueSendFromISR(lcd_cam_obj->event_queue, &out_status, &woken);
}
if (woken == pdTRUE) {
portYIELD_FROM_ISR();
}
}
static void lcd_dma_set_int(lcd_cam_obj_t *lcd_cam_obj)
{
// Generate a data DMA linked list
for (int x = 0; x < lcd_cam_obj->dma_node_cnt; x++) {
lcd_cam_obj->dma[x].size = lcd_cam_obj->dma_node_buffer_size;
lcd_cam_obj->dma[x].length = lcd_cam_obj->dma_node_buffer_size;
lcd_cam_obj->dma[x].buf = (lcd_cam_obj->dma_buffer + lcd_cam_obj->dma_node_buffer_size * x);
lcd_cam_obj->dma[x].eof = !((x + 1) % lcd_cam_obj->dma_half_node_cnt);
lcd_cam_obj->dma[x].empty = (uint32_t)&lcd_cam_obj->dma[(x + 1) % lcd_cam_obj->dma_node_cnt];
}
lcd_cam_obj->dma[lcd_cam_obj->dma_half_node_cnt - 1].empty = (uint32_t)NULL;
lcd_cam_obj->dma[lcd_cam_obj->dma_node_cnt - 1].empty = (uint32_t)NULL;
}
static void lcd_dma_set_left(lcd_cam_obj_t *lcd_cam_obj, int pos, size_t len)
{
int end_pos = 0, size = 0;
// Processing data length is an integer multiple of lcd_cam_obj->lcd.dma_node_buffer_size
if (len % lcd_cam_obj->dma_node_buffer_size) {
end_pos = (pos % 2) * lcd_cam_obj->dma_half_node_cnt + len / lcd_cam_obj->dma_node_buffer_size;
size = len % lcd_cam_obj->dma_node_buffer_size;
} else {
end_pos = (pos % 2) * lcd_cam_obj->dma_half_node_cnt + len / lcd_cam_obj->dma_node_buffer_size - 1;
size = lcd_cam_obj->dma_node_buffer_size;
}
// Process the tail node to make it a DMA tail
lcd_cam_obj->dma[end_pos].size = size;
lcd_cam_obj->dma[end_pos].length = size;
lcd_cam_obj->dma[end_pos].eof = 1;
lcd_cam_obj->dma[end_pos].empty = (uint32_t)NULL;
}
static void lcd_start(uint32_t dma_num, uint32_t addr, size_t len)
{
while (LCD_CAM.lcd_user.lcd_start);
LCD_CAM.lcd_user.lcd_reset = 1;
LCD_CAM.lcd_user.lcd_reset = 0;
LCD_CAM.lcd_misc.lcd_afifo_reset = 1;
LCD_CAM.lcd_misc.lcd_afifo_reset = 0;
while (GDMA.channel[dma_num].out.link.start);
GDMA.channel[dma_num].out.conf0.val = 0;
GDMA.channel[dma_num].out.conf1.val = 0;
GDMA.channel[dma_num].out.int_clr.val = ~0;
GDMA.channel[dma_num].out.int_ena.val = 0;
GDMA.channel[dma_num].out.conf0.out_rst = 1;
GDMA.channel[dma_num].out.conf0.out_rst = 0;
GDMA.channel[dma_num].out.conf0.outdscr_burst_en = 1;
GDMA.channel[dma_num].out.conf0.out_data_burst_en = 1;
GDMA.channel[dma_num].out.peri_sel.sel = 5;
GDMA.channel[dma_num].out.pri.tx_pri = 1;
GDMA.channel[dma_num].out.int_ena.out_eof = 1;
GDMA.channel[dma_num].out.link.addr = addr;
GDMA.channel[dma_num].out.link.start = 1;
ets_delay_us(1);
LCD_CAM.lcd_user.lcd_update = 1;
LCD_CAM.lcd_user.lcd_start = 1;
}
static void lcd_write_data(lcd_cam_obj_t *lcd_cam_obj, const uint8_t *data, size_t len)
{
int event = 0;
int x = 0, left = 0, cnt = 0;
if (len <= 0) {
ESP_LOGE(TAG, "wrong len!");
return;
}
lcd_dma_set_int(lcd_cam_obj);
uint32_t half_buffer_size = lcd_cam_obj->dma_half_buffer_size;
cnt = len / half_buffer_size;
// Start signal
xQueueSend(lcd_cam_obj->event_queue, &event, 0);
// Process a complete piece of data, ping-pong operation
for (x = 0; x < cnt; x++) {
uint8_t *out = (uint8_t *)lcd_cam_obj->dma[(x % 2) * lcd_cam_obj->dma_half_node_cnt].buf;
const uint8_t *in = data;
if (lcd_cam_obj->swap_data) {
LCD_CAM.lcd_user.lcd_8bits_order = 1;
memcpy(out, in, half_buffer_size);
} else {
LCD_CAM.lcd_user.lcd_8bits_order = 0;
memcpy(out, in, half_buffer_size);
}
data += half_buffer_size;
xQueueReceive(lcd_cam_obj->event_queue, (void *)&event, portMAX_DELAY);
lcd_start(lcd_cam_obj->dma_num, ((uint32_t)&lcd_cam_obj->dma[(x % 2) * lcd_cam_obj->dma_half_node_cnt]) & 0xfffff, half_buffer_size);
}
left = len % half_buffer_size;
// Process remaining incomplete segment data
if (left) {
uint8_t *out = (uint8_t *)lcd_cam_obj->dma[(x % 2) * lcd_cam_obj->dma_half_node_cnt].buf;
const uint8_t *in = data;
cnt = left - left % 2;
if (cnt) {
if (lcd_cam_obj->swap_data) {
LCD_CAM.lcd_user.lcd_8bits_order = 1;
memcpy(out, in, cnt);
} else {
LCD_CAM.lcd_user.lcd_8bits_order = 0;
memcpy(out, in, cnt);
}
}
if (left % 2) {
LCD_CAM.lcd_user.lcd_8bits_order = 0;
out[cnt] = in[cnt];
}
lcd_dma_set_left(lcd_cam_obj, x, left);
xQueueReceive(lcd_cam_obj->event_queue, (void *)&event, portMAX_DELAY);
lcd_start(lcd_cam_obj->dma_num, ((uint32_t)&lcd_cam_obj->dma[(x % 2) * lcd_cam_obj->dma_half_node_cnt]) & 0xfffff, left);
}
xQueueReceive(lcd_cam_obj->event_queue, (void *)&event, portMAX_DELAY);
}
static esp_err_t lcd_cam_config(const i2s_lcd_config_t *config, uint32_t dma_num)
{
GDMA.channel[dma_num].out.conf0.val = 0;
GDMA.channel[dma_num].out.conf1.val = 0;
GDMA.channel[dma_num].in.conf0.val = 0;
GDMA.channel[dma_num].in.conf1.val = 0;
GDMA.channel[dma_num].out.int_clr.val = ~0;
GDMA.channel[dma_num].out.int_ena.val = 0;
GDMA.channel[dma_num].in.int_clr.val = ~0;
GDMA.channel[dma_num].in.int_ena.val = 0;
LCD_CAM.lcd_clock.val = 0;
LCD_CAM.lcd_clock.clk_en = 1;
LCD_CAM.lcd_clock.lcd_clk_sel = 3;
LCD_CAM.lcd_clock.lcd_clkm_div_b = 0;
LCD_CAM.lcd_clock.lcd_clkm_div_a = 10;
LCD_CAM.lcd_clock.lcd_clkm_div_num = 2;
LCD_CAM.lcd_clock.lcd_clkcnt_n = 80000000 / config->clk_freq - 1;
LCD_CAM.lcd_clock.lcd_clk_equ_sysclk = 0;
LCD_CAM.lcd_clock.lcd_ck_idle_edge = 1; // After lcd_clk_equ_sysclk is set to 1, this bit has no effect
LCD_CAM.lcd_clock.lcd_ck_out_edge = 0; // After lcd_clk_equ_sysclk is set to 1, this bit has no effect
LCD_CAM.lcd_user.val = 0;
LCD_CAM.lcd_user.lcd_2byte_en = (config->data_width == 16) ? 1 : 0;
LCD_CAM.lcd_user.lcd_byte_order = 0;
LCD_CAM.lcd_user.lcd_bit_order = 0;
LCD_CAM.lcd_user.lcd_cmd = 0; // FSM CMD phase
LCD_CAM.lcd_user.lcd_cmd_2_cycle_en = 0; // 2 cycle command
LCD_CAM.lcd_user.lcd_dout = 1; // FSM DOUT phase
LCD_CAM.lcd_user.lcd_dout_cyclelen = 2 - 1;
LCD_CAM.lcd_user.lcd_8bits_order = 0;
LCD_CAM.lcd_user.lcd_always_out_en = 1;
LCD_CAM.lcd_misc.val = 0;
LCD_CAM.lcd_misc.lcd_afifo_threshold_num = 11;
LCD_CAM.lcd_misc.lcd_vfk_cyclelen = 3;
LCD_CAM.lcd_misc.lcd_vbk_cyclelen = 0;
LCD_CAM.lcd_misc.lcd_cd_idle_edge = 1; // idle edge of CD is set to 0
LCD_CAM.lcd_misc.lcd_cd_cmd_set = 1;
LCD_CAM.lcd_misc.lcd_cd_dummy_set = 0;
LCD_CAM.lcd_misc.lcd_cd_data_set = 0; // change when DOUT start
LCD_CAM.lcd_misc.lcd_bk_en = 1;
LCD_CAM.lcd_misc.lcd_afifo_reset = 1;
LCD_CAM.lcd_misc.lcd_afifo_reset = 0;
LCD_CAM.lcd_ctrl.val = 0;
LCD_CAM.lcd_ctrl.lcd_rgb_mode_en = 0;
LCD_CAM.lcd_cmd_val.val = 0; // write command
LCD_CAM.lcd_user.lcd_update = 1;
GDMA.channel[dma_num].out.conf0.out_rst = 1;
GDMA.channel[dma_num].out.conf0.out_rst = 0;
GDMA.channel[dma_num].out.conf0.outdscr_burst_en = 1;
GDMA.channel[dma_num].out.conf0.out_data_burst_en = 1;
GDMA.channel[dma_num].out.peri_sel.sel = (config->data_width == 1) ? 1 : 5;
GDMA.channel[dma_num].out.pri.tx_pri = 1;
GDMA.channel[dma_num].out.int_ena.out_eof = 1;
return ESP_OK;
}
static void lcd_set_pin(const i2s_lcd_config_t *config)
{
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[config->pin_num_wr], PIN_FUNC_GPIO);
gpio_set_direction(config->pin_num_wr, GPIO_MODE_OUTPUT);
gpio_set_pull_mode(config->pin_num_wr, GPIO_FLOATING);
gpio_matrix_out(config->pin_num_wr, LCD_PCLK_IDX, false, false);
for (int i = 0; i < config->data_width; i++) {
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[config->pin_data_num[i]], PIN_FUNC_GPIO);
gpio_set_direction(config->pin_data_num[i], GPIO_MODE_OUTPUT);
gpio_set_pull_mode(config->pin_data_num[i], GPIO_FLOATING);
gpio_matrix_out(config->pin_data_num[i], LCD_DATA_OUT0_IDX + i, false, false);
}
}
static esp_err_t lcd_dma_config(lcd_cam_obj_t *lcd_cam_obj, const i2s_lcd_config_t *config)
{
int cnt = 0;
if (LCD_CAM_DMA_NODE_BUFFER_MAX_SIZE % 2 != 0) {
ESP_LOGE(TAG, "need 2-byte aligned data length");
return ESP_FAIL;
}
if (config->buffer_size >= LCD_CAM_DMA_NODE_BUFFER_MAX_SIZE * 2) {
lcd_cam_obj->dma_node_buffer_size = LCD_CAM_DMA_NODE_BUFFER_MAX_SIZE;
for (cnt = 0; cnt < config->buffer_size - 8; cnt++) { // Find a buffer size that can divide dma_size
if ((config->buffer_size - cnt) % (lcd_cam_obj->dma_node_buffer_size * 2) == 0) {
break;
}
}
lcd_cam_obj->dma_buffer_size = config->buffer_size - cnt;
} else {
lcd_cam_obj->dma_node_buffer_size = config->buffer_size / 2;
lcd_cam_obj->dma_buffer_size = lcd_cam_obj->dma_node_buffer_size * 2;
}
lcd_cam_obj->dma_half_buffer_size = lcd_cam_obj->dma_buffer_size / 2;
lcd_cam_obj->dma_node_cnt = (lcd_cam_obj->dma_buffer_size) / lcd_cam_obj->dma_node_buffer_size; // Number of DMA nodes
lcd_cam_obj->dma_half_node_cnt = lcd_cam_obj->dma_node_cnt / 2;
ESP_LOGI(TAG, "lcd_buffer_size: %d, lcd_dma_size: %d, lcd_dma_node_cnt: %d", lcd_cam_obj->dma_buffer_size, lcd_cam_obj->dma_node_buffer_size, lcd_cam_obj->dma_node_cnt);
lcd_cam_obj->dma = (lldesc_t *)heap_caps_malloc(lcd_cam_obj->dma_node_cnt * sizeof(lldesc_t), MALLOC_CAP_DMA);
lcd_cam_obj->dma_buffer = (uint8_t *)heap_caps_malloc(lcd_cam_obj->dma_buffer_size * sizeof(uint8_t), MALLOC_CAP_DMA);
return ESP_OK;
}
esp_err_t lcd_cam_deinit(i2s_lcd_driver_t *drv)
{
if (!drv->i2s_lcd_obj) {
return ESP_FAIL;
}
if (drv->i2s_lcd_obj->event_queue) {
vQueueDelete(drv->i2s_lcd_obj->event_queue);
}
if (drv->i2s_lcd_obj->dma) {
free(drv->i2s_lcd_obj->dma);
}
if (drv->i2s_lcd_obj->dma_buffer) {
free(drv->i2s_lcd_obj->dma_buffer);
}
if (drv->i2s_lcd_obj->dma_out_intr_handle) {
esp_intr_free(drv->i2s_lcd_obj->dma_out_intr_handle);
}
GDMA.channel[drv->i2s_lcd_obj->dma_num].out.link.start = 0x0;
free(drv->i2s_lcd_obj);
drv->i2s_lcd_obj = NULL;
return ESP_OK;
}
static esp_err_t lcd_cam_init(i2s_lcd_driver_t *drv, const i2s_lcd_config_t *config)
{
esp_err_t ret = ESP_OK;
lcd_cam_obj_t *lcd_cam_obj = (lcd_cam_obj_t *)heap_caps_calloc(1, sizeof(lcd_cam_obj_t), MALLOC_CAP_DMA);
if (lcd_cam_obj == NULL) {
ESP_LOGE(TAG, "lcd_cam object malloc error");
return ESP_ERR_NO_MEM;
}
drv->i2s_lcd_obj = lcd_cam_obj;
//Enable LCD_CAM periph
if (REG_GET_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_LCD_CAM_CLK_EN) == 0) {
REG_CLR_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_LCD_CAM_CLK_EN);
REG_SET_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_LCD_CAM_CLK_EN);
REG_SET_BIT(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_LCD_CAM_RST);
REG_CLR_BIT(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_LCD_CAM_RST);
}
if (REG_GET_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_DMA_CLK_EN) == 0) {
REG_CLR_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_DMA_CLK_EN);
REG_SET_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_DMA_CLK_EN);
REG_SET_BIT(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_DMA_RST);
REG_CLR_BIT(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_DMA_RST);
}
for (int x = SOC_GDMA_PAIRS_PER_GROUP - 1; x >= 0; x--) {
if (GDMA.channel[x].out.link.start == 0x0) {
lcd_cam_obj->dma_num = x;
break;
}
if (x == SOC_GDMA_PAIRS_PER_GROUP - 1) {
ESP_LOGE(TAG, "DMA error");
lcd_cam_deinit(drv);
return ESP_FAIL;
}
}
ret |= lcd_cam_config(config, lcd_cam_obj->dma_num);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "lcd_cam config fail!");
lcd_cam_deinit(drv);
return ESP_FAIL;
}
lcd_set_pin(config);
ret |= lcd_dma_config(lcd_cam_obj, config);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "lcd config fail!");
lcd_cam_deinit(drv);
return ESP_FAIL;
}
lcd_cam_obj->event_queue = xQueueCreate(1, sizeof(int));
lcd_cam_obj->width = config->data_width;
lcd_cam_obj->swap_data = config->swap_data;
if (lcd_cam_obj->event_queue == NULL) {
ESP_LOGE(TAG, "lcd config fail!");
lcd_cam_deinit(drv);
return ESP_FAIL;
}
ret |= esp_intr_alloc_intrstatus(gdma_periph_signals.groups[0].pairs[lcd_cam_obj->dma_num].tx_irq_id,
ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_IRAM,
(uint32_t)&GDMA.channel[lcd_cam_obj->dma_num].out.int_st, GDMA_OUT_EOF_CH0_INT_ST,
dma_isr, lcd_cam_obj, &lcd_cam_obj->dma_out_intr_handle);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "lcd_cam intr alloc fail!");
lcd_cam_deinit(drv);
return ESP_FAIL;
}
ESP_LOGI(TAG, "lcd init ok");
return ESP_OK;
}
/**< Public functions */
i2s_lcd_handle_t i2s_lcd_driver_init(const i2s_lcd_config_t *config)
{
LCD_CHECK(NULL != config, "config pointer invalid", NULL);
LCD_CHECK(GPIO_IS_VALID_GPIO(config->pin_num_wr), "GPIO WR invalid", NULL);
LCD_CHECK(GPIO_IS_VALID_GPIO(config->pin_num_rs), "GPIO RS invalid", NULL);
LCD_CHECK(config->data_width > 0 && config->data_width <= 16, "Bit width out of range", NULL);
LCD_CHECK(0 == (config->data_width % 8), "Bit width must be a multiple of 8", NULL);
uint64_t pin_mask = 0;
for (size_t i = 0; i < config->data_width; i++) {
uint64_t mask = 1ULL << config->pin_data_num[i];
LCD_CHECK(!(pin_mask & mask), "Data bus GPIO has a duplicate", NULL);
LCD_CHECK(GPIO_IS_VALID_GPIO(config->pin_data_num[i]), "Data bus gpio invalid", NULL);
pin_mask |= mask;
}
i2s_lcd_driver_t *i2s_lcd_drv = (i2s_lcd_driver_t *)heap_caps_malloc(sizeof(i2s_lcd_driver_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
LCD_CHECK(NULL != i2s_lcd_drv, "Error malloc handle of i2s lcd driver", NULL);
esp_err_t ret = lcd_cam_init(i2s_lcd_drv, config);
if (ESP_OK != ret) {
ESP_LOGE(TAG, "%s:%d (%s):%s", __FILE__, __LINE__, __FUNCTION__, "i2s lcd driver initialize failed");
heap_caps_free(i2s_lcd_drv);
return NULL;
}
i2s_lcd_drv->mutex = xSemaphoreCreateMutex();
if (i2s_lcd_drv->mutex == NULL) {
ESP_LOGE(TAG, "%s:%d (%s):%s", __FILE__, __LINE__, __FUNCTION__, "lcd create mutex failed");
lcd_cam_deinit(i2s_lcd_drv);
heap_caps_free(i2s_lcd_drv);
return NULL;
}
if (config->pin_num_cs >= 0) {
gpio_pad_select_gpio(config->pin_num_cs);
gpio_set_direction(config->pin_num_cs, GPIO_MODE_OUTPUT);
gpio_set_level(config->pin_num_cs, 0);
}
gpio_pad_select_gpio(config->pin_num_rs);
gpio_set_direction(config->pin_num_rs, GPIO_MODE_OUTPUT);
gpio_set_level(config->pin_num_rs, LCD_DATA_LEV);
i2s_lcd_drv->rs_io_num = config->pin_num_rs;
return (i2s_lcd_handle_t)i2s_lcd_drv;
}
esp_err_t i2s_lcd_driver_deinit(i2s_lcd_handle_t handle)
{
i2s_lcd_driver_t *i2s_lcd_drv = (i2s_lcd_driver_t *)handle;
LCD_CHECK(NULL != i2s_lcd_drv, "handle pointer invalid", ESP_ERR_INVALID_ARG);
lcd_cam_deinit(i2s_lcd_drv);
vSemaphoreDelete(i2s_lcd_drv->mutex);
heap_caps_free(handle);
return ESP_OK;
}
esp_err_t i2s_lcd_write_data(i2s_lcd_handle_t handle, uint16_t data)
{
i2s_lcd_driver_t *i2s_lcd_drv = (i2s_lcd_driver_t *)handle;
LCD_CHECK(NULL != i2s_lcd_drv, "handle pointer invalid", ESP_ERR_INVALID_ARG);
lcd_write_data(i2s_lcd_drv->i2s_lcd_obj, (uint8_t *)&data, i2s_lcd_drv->i2s_lcd_obj->width == 16 ? 2 : 1);
return ESP_OK;
}
esp_err_t i2s_lcd_write_cmd(i2s_lcd_handle_t handle, uint16_t cmd)
{
i2s_lcd_driver_t *i2s_lcd_drv = (i2s_lcd_driver_t *)handle;
LCD_CHECK(NULL != i2s_lcd_drv, "handle pointer invalid", ESP_ERR_INVALID_ARG);
gpio_set_level(i2s_lcd_drv->rs_io_num, LCD_CMD_LEV);
lcd_write_data(i2s_lcd_drv->i2s_lcd_obj, (uint8_t *)&cmd, i2s_lcd_drv->i2s_lcd_obj->width == 16 ? 2 : 1);
gpio_set_level(i2s_lcd_drv->rs_io_num, LCD_DATA_LEV);
return ESP_OK;
}
esp_err_t i2s_lcd_write_command(i2s_lcd_handle_t handle, const uint8_t *cmd, uint32_t length)
{
i2s_lcd_driver_t *i2s_lcd_drv = (i2s_lcd_driver_t *)handle;
LCD_CHECK(NULL != i2s_lcd_drv, "handle pointer invalid", ESP_ERR_INVALID_ARG);
gpio_set_level(i2s_lcd_drv->rs_io_num, LCD_CMD_LEV);
lcd_write_data(i2s_lcd_drv->i2s_lcd_obj, cmd, length);
gpio_set_level(i2s_lcd_drv->rs_io_num, LCD_DATA_LEV);
return ESP_OK;
}
esp_err_t i2s_lcd_write(i2s_lcd_handle_t handle, const uint8_t *data, uint32_t length)
{
i2s_lcd_driver_t *i2s_lcd_drv = (i2s_lcd_driver_t *)handle;
LCD_CHECK(NULL != i2s_lcd_drv, "handle pointer invalid", ESP_ERR_INVALID_ARG);
lcd_write_data(i2s_lcd_drv->i2s_lcd_obj, data, length);
return ESP_OK;
}
esp_err_t i2s_lcd_acquire(i2s_lcd_handle_t handle)
{
i2s_lcd_driver_t *i2s_lcd_drv = (i2s_lcd_driver_t *)handle;
LCD_CHECK(NULL != i2s_lcd_drv, "handle pointer invalid", ESP_ERR_INVALID_ARG);
BaseType_t ret = xSemaphoreTake(i2s_lcd_drv->mutex, portMAX_DELAY);
LCD_CHECK(pdTRUE == ret, "Take semaphore failed", ESP_FAIL);
return ESP_OK;
}
esp_err_t i2s_lcd_release(i2s_lcd_handle_t handle)
{
i2s_lcd_driver_t *i2s_lcd_drv = (i2s_lcd_driver_t *)handle;
LCD_CHECK(NULL != i2s_lcd_drv, "handle pointer invalid", ESP_ERR_INVALID_ARG);
BaseType_t ret = xSemaphoreGive(i2s_lcd_drv->mutex);
LCD_CHECK(pdTRUE == ret, "Give semaphore failed", ESP_FAIL);
return ESP_OK;
}
#endif

View file

@ -1,2 +1,3 @@
idf_component_register(SRC_DIRS "."
INCLUDE_DIRS "include" )
INCLUDE_DIRS "include"
REQUIRES driver)

View file

@ -20,8 +20,13 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "freertos/semphr.h"
#include "esp_heap_caps.h"
#include "esp32/rom/lldesc.h"
#include "esp32/rom/gpio.h"
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0))
#include "esp_private/periph_ctrl.h"
#endif
#include "soc/dport_access.h"
#include "soc/dport_reg.h"
#include "soc/i2s_struct.h"
@ -36,6 +41,11 @@ static const char *TAG = "ESP32_I2S_LCD";
return (ret); \
}
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0))
#define ets_delay_us esp_rom_delay_us
#define portTICK_RATE_MS portTICK_PERIOD_MS
#endif
#define LCD_CAM_DMA_NODE_BUFFER_MAX_SIZE (4000) // 4-byte aligned
#define LCD_DATA_MAX_WIDTH (24) /*!< Maximum width of LCD data bus */
@ -566,6 +576,16 @@ esp_err_t i2s_lcd_write_cmd(i2s_lcd_handle_t handle, uint16_t cmd)
return ESP_OK;
}
esp_err_t i2s_lcd_write_command(i2s_lcd_handle_t handle, const uint8_t *cmd, uint32_t length)
{
i2s_lcd_driver_t *i2s_lcd_drv = (i2s_lcd_driver_t *)handle;
I2S_CHECK(NULL != i2s_lcd_drv, "handle pointer invalid", ESP_ERR_INVALID_ARG);
gpio_set_level(i2s_lcd_drv->rs_io_num, LCD_CMD_LEV);
i2s_lcd_drv->i2s_write_data_func(i2s_lcd_drv->i2s_lcd_obj, (uint8_t *)cmd, length);
gpio_set_level(i2s_lcd_drv->rs_io_num, LCD_DATA_LEV);
return ESP_OK;
}
esp_err_t i2s_lcd_write(i2s_lcd_handle_t handle, const uint8_t *data, uint32_t length)
{
i2s_lcd_driver_t *i2s_lcd_drv = (i2s_lcd_driver_t *)handle;

View file

@ -22,7 +22,13 @@
#include "freertos/semphr.h"
#include "esp_log.h"
#include "driver/gpio.h"
#include "esp32s2/rom/gpio.h"
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0))
#include "esp_private/periph_ctrl.h"
#endif
#include "soc/gpio_periph.h"
#include "driver/i2s.h"
#include "soc/i2s_struct.h"
#include "esp_heap_caps.h"
#include "esp32s2/rom/lldesc.h"
#include "soc/system_reg.h"
@ -39,6 +45,11 @@ static const char *TAG = "ESP32S2_I2S_LCD";
#define LCD_CAM_DMA_NODE_BUFFER_MAX_SIZE (4000) // 4-byte aligned
#define LCD_DATA_MAX_WIDTH (24) /*!< Maximum width of LCD data bus */
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0))
#define ets_delay_us esp_rom_delay_us
#define portTICK_RATE_MS portTICK_PERIOD_MS
#endif
typedef struct {
uint32_t dma_buffer_size;
uint32_t dma_half_buffer_size;
@ -439,6 +450,16 @@ esp_err_t i2s_lcd_write_cmd(i2s_lcd_handle_t handle, uint16_t cmd)
return ESP_OK;
}
esp_err_t i2s_lcd_write_command(i2s_lcd_handle_t handle, const uint8_t *cmd, uint32_t length)
{
i2s_lcd_driver_t *i2s_lcd_drv = (i2s_lcd_driver_t *)handle;
I2S_CHECK(NULL != i2s_lcd_drv, "handle pointer invalid", ESP_ERR_INVALID_ARG);
gpio_set_level(i2s_lcd_drv->rs_io_num, LCD_CMD_LEV);
i2s_write_data(i2s_lcd_drv->i2s_lcd_obj, (uint8_t *)cmd, length);
gpio_set_level(i2s_lcd_drv->rs_io_num, LCD_DATA_LEV);
return ESP_OK;
}
esp_err_t i2s_lcd_write(i2s_lcd_handle_t handle, const uint8_t *data, uint32_t length)
{
i2s_lcd_driver_t *i2s_lcd_drv = (i2s_lcd_driver_t *)handle;

View file

@ -25,6 +25,11 @@ extern "C"
{
#endif
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0))
#define gpio_pad_select_gpio esp_rom_gpio_pad_select_gpio
#define portTICK_RATE_MS portTICK_PERIOD_MS
#endif
/**************************************** Public Functions (Application level)*********************************************/
/**

View file

@ -86,6 +86,19 @@ esp_err_t i2s_lcd_write_data(i2s_lcd_handle_t handle, uint16_t data);
*/
esp_err_t i2s_lcd_write_cmd(i2s_lcd_handle_t handle, uint16_t cmd);
/**
* @brief Write a command to LCD
*
* @param handle Handle of i2s lcd driver
* @param cmd command to write
* @param length length of command
*
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG handle is invalid
*/
esp_err_t i2s_lcd_write_command(i2s_lcd_handle_t handle, const uint8_t *cmd, uint32_t length);
/**
* @brief Write block data to LCD
*

View file

@ -69,8 +69,12 @@ spi_bus_handle_t spi_bus_create(spi_host_device_t host_id, const spi_config_t *b
.quadhd_io_num = -1,
.max_transfer_sz = bus_conf->max_transfer_sz,
};
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 3, 0))
esp_err_t ret = spi_bus_initialize(host_id, &buscfg, SPI_DMA_CH_AUTO);
#else
int dma_chan = host_id; //set dma channel equals to host_id by default
esp_err_t ret = spi_bus_initialize(host_id, &buscfg, dma_chan);
#endif
SPI_BUS_CHECK(ESP_OK == ret, "spi bus create failed", NULL);
s_spi_bus[index].host_id = host_id;
memcpy(&s_spi_bus[index].conf, &buscfg, sizeof(spi_bus_config_t));
@ -199,7 +203,7 @@ esp_err_t spi_bus_transfer_bytes(spi_bus_device_handle_t dev_handle, const uint8
return ESP_OK;
}
/**************************************** Public Functions (Low level)*********************************************/
/**************************************** Public Functions (Low level)*********************************************/
esp_err_t spi_bus_transmit_begin(spi_bus_device_handle_t dev_handle, spi_transaction_t *p_trans)
{

View file

@ -1,3 +1,12 @@
set(PRIVREQ esp_timer)
if("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_GREATER_EQUAL "5.0")
list(APPEND PRIVREQ esp_adc)
else()
list(APPEND PRIVREQ esp_adc_cal)
endif()
idf_component_register(SRCS "button_adc.c" "button_gpio.c" "iot_button.c"
INCLUDE_DIRS include
PRIV_REQUIRES esp_adc_cal)
REQUIRES driver
PRIV_REQUIRES ${PRIVREQ})

View file

@ -0,0 +1,17 @@
# Component: Button
[Chinese documentation](https://docs.espressif.com/projects/espressif-esp-iot-solution/en/latest/input_device/button.html)
After creating a new button object by calling function `button_create()`, the button object can create press events, every press event can have its own callback.
List of supported events:
* Button pressed
* Button released
* Button pressed - repeated
* Button single click
* Button double click
* Button long press start
* Button long press hold
There are two ways this driver can handle buttons:
1. Buttons connected to standard digital GPIO
2. Multiple buttons connected to single ADC channel

View file

@ -31,11 +31,7 @@ static const char *TAG = "adc button";
#define DEFAULT_VREF 1100
#define NO_OF_SAMPLES CONFIG_ADC_BUTTON_SAMPLE_TIMES //Multisampling
#if CONFIG_IDF_TARGET_ESP32
#define ADC_BUTTON_WIDTH ADC_WIDTH_BIT_12
#elif CONFIG_IDF_TARGET_ESP32S2
#define ADC_BUTTON_WIDTH ADC_WIDTH_BIT_13
#endif
#define ADC_BUTTON_WIDTH ADC_WIDTH_MAX-1
#define ADC_BUTTON_ATTEN ADC_ATTEN_DB_11
#define ADC_BUTTON_ADC_UNIT ADC_UNIT_1
#define ADC_BUTTON_MAX_CHANNEL CONFIG_ADC_BUTTON_MAX_CHANNEL

View file

@ -0,0 +1,5 @@
version: "2.2.0"
description: GPIO and ADC button driver
url: https://github.com/espressif/esp-iot-solution/tree/master/components/button
dependencies:
idf: ">=4.0"

View file

@ -21,7 +21,7 @@
extern "C" {
#endif
typedef void (* button_cb_t)(void *);
typedef void (* button_cb_t)(void *, void *);
typedef void *button_handle_t;
/**
@ -87,12 +87,13 @@ esp_err_t iot_button_delete(button_handle_t btn_handle);
* @param btn_handle A button handle to register
* @param event Button event
* @param cb Callback function.
* @param usr_data user data
*
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG Arguments is invalid.
*/
esp_err_t iot_button_register_cb(button_handle_t btn_handle, button_event_t event, button_cb_t cb);
esp_err_t iot_button_register_cb(button_handle_t btn_handle, button_event_t event, button_cb_t cb, void *usr_data);
/**
* @brief Unregister the button event callback function.

View file

@ -39,7 +39,8 @@ typedef struct Button {
uint8_t debounce_cnt: 3;
uint8_t active_level: 1;
uint8_t button_level: 1;
uint8_t (*hal_button_Level)(void *usr_data);
uint8_t (*hal_button_Level)(void *hardware_data);
void *hardware_data;
void *usr_data;
button_type_t type;
button_cb_t cb[BUTTON_EVENT_MAX];
@ -56,14 +57,14 @@ static bool g_is_timer_running = false;
#define SHORT_TICKS (CONFIG_BUTTON_SHORT_PRESS_TIME_MS /TICKS_INTERVAL)
#define LONG_TICKS (CONFIG_BUTTON_LONG_PRESS_TIME_MS /TICKS_INTERVAL)
#define CALL_EVENT_CB(ev) if(btn->cb[ev])btn->cb[ev](btn)
#define CALL_EVENT_CB(ev) if(btn->cb[ev])btn->cb[ev](btn, btn->usr_data)
/**
* @brief Button driver core function, driver state machine.
*/
static void button_handler(button_dev_t *btn)
{
uint8_t read_gpio_level = btn->hal_button_Level(btn->usr_data);
uint8_t read_gpio_level = btn->hal_button_Level(btn->hardware_data);
/** ticks counter working.. */
if ((btn->state) > 0) {
@ -163,13 +164,13 @@ static void button_cb(void *args)
}
}
static button_dev_t *button_create_com(uint8_t active_level, uint8_t (*hal_get_key_state)(void *usr_data), void *usr_data)
static button_dev_t *button_create_com(uint8_t active_level, uint8_t (*hal_get_key_state)(void *hardware_data), void *hardware_data)
{
BTN_CHECK(NULL != hal_get_key_state, "Function pointer is invalid", NULL);
button_dev_t *btn = (button_dev_t *) calloc(1, sizeof(button_dev_t));
BTN_CHECK(NULL != btn, "Button memory alloc failed", NULL);
btn->usr_data = usr_data;
btn->hardware_data = hardware_data;
btn->event = BUTTON_NONE_PRESS;
btn->active_level = active_level;
btn->hal_button_Level = hal_get_key_state;
@ -259,10 +260,10 @@ esp_err_t iot_button_delete(button_handle_t btn_handle)
button_dev_t *btn = (button_dev_t *)btn_handle;
switch (btn->type) {
case BUTTON_TYPE_GPIO:
ret = button_gpio_deinit((int)(btn->usr_data));
ret = button_gpio_deinit((int)(btn->hardware_data));
break;
case BUTTON_TYPE_ADC:
ret = button_adc_deinit(ADC_BUTTON_SPLIT_CHANNEL(btn->usr_data), ADC_BUTTON_SPLIT_INDEX(btn->usr_data));
ret = button_adc_deinit(ADC_BUTTON_SPLIT_CHANNEL(btn->hardware_data), ADC_BUTTON_SPLIT_INDEX(btn->hardware_data));
break;
default:
break;
@ -272,12 +273,13 @@ esp_err_t iot_button_delete(button_handle_t btn_handle)
return ESP_OK;
}
esp_err_t iot_button_register_cb(button_handle_t btn_handle, button_event_t event, button_cb_t cb)
esp_err_t iot_button_register_cb(button_handle_t btn_handle, button_event_t event, button_cb_t cb, void *usr_data)
{
BTN_CHECK(NULL != btn_handle, "Pointer of handle is invalid", ESP_ERR_INVALID_ARG);
BTN_CHECK(event < BUTTON_EVENT_MAX, "event is invalid", ESP_ERR_INVALID_ARG);
button_dev_t *btn = (button_dev_t *) btn_handle;
btn->cb[event] = cb;
btn->usr_data = usr_data;
return ESP_OK;
}

View file

@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View file

@ -1,15 +1,18 @@
set(SCREEN_DIR "controller_driver/ili9341"
"controller_driver/ili9342"
"controller_driver/st7789"
"controller_driver/st7796"
"controller_driver/nt35510"
"controller_driver/ili9806"
"controller_driver/ili9486"
"controller_driver/ili9488"
"controller_driver/ssd1351"
"controller_driver/rm68120"
"controller_driver/ssd1306"
"controller_driver/ssd1307"
"controller_driver/ssd1322"
"controller_driver/ssd1963"
)
idf_component_register(SRC_DIRS "${SCREEN_DIR}" "screen_utility" "interface_driver" "."

View file

@ -4,12 +4,18 @@ menu "LCD Drivers"
config LCD_DRIVER_SCREEN_CONTROLLER_ILI9341
bool "ILI9341"
default y
config LCD_DRIVER_SCREEN_CONTROLLER_ILI9342
bool "ILI9342"
default y
config LCD_DRIVER_SCREEN_CONTROLLER_ILI9486
bool "ILI9486"
default n
config LCD_DRIVER_SCREEN_CONTROLLER_ILI9806
bool "ILI9806"
default n
config LCD_DRIVER_SCREEN_CONTROLLER_ILI9488
bool "ILI9488"
default n
config LCD_DRIVER_SCREEN_CONTROLLER_NT35510
bool "NT35510"
default n
@ -19,6 +25,9 @@ menu "LCD Drivers"
config LCD_DRIVER_SCREEN_CONTROLLER_SSD1351
bool "SSD1351"
default n
config LCD_DRIVER_SCREEN_CONTROLLER_SSD1963
bool "SSD1963"
default n
config LCD_DRIVER_SCREEN_CONTROLLER_ST7789
bool "ST7789"
default n
@ -37,4 +46,4 @@ menu "LCD Drivers"
default n
endmenu
endmenu
endmenu

View file

@ -5,16 +5,19 @@
SCREEN_DIR = controller_driver/ili9341 \
controller_driver/st7789 \
controller_driver/st7796 \
controller_driver/nt35510 \
controller_driver/ili9806 \
controller_driver/ili9486 \
controller_driver/ssd1351 \
controller_driver/rm68120 \
controller_driver/ssd1306 \
controller_driver/ssd1307 \
controller_driver/ssd1322
controller_driver/ili9342 \
controller_driver/st7789 \
controller_driver/st7796 \
controller_driver/nt35510 \
controller_driver/ili9806 \
controller_driver/ili9486 \
controller_driver/ili9488 \
controller_driver/ssd1351 \
controller_driver/rm68120 \
controller_driver/ssd1306 \
controller_driver/ssd1307 \
controller_driver/ssd1322 \
controller_driver/ssd1963
COMPONENT_ADD_INCLUDEDIRS := . iface_driver $(SCREEN_DIR) screen_utility
COMPONENT_SRCDIRS := . iface_driver $(SCREEN_DIR) screen_utility
COMPONENT_ADD_INCLUDEDIRS := . interface_driver $(SCREEN_DIR) screen_utility
COMPONENT_SRCDIRS := . interface_driver $(SCREEN_DIR) screen_utility

View file

@ -79,7 +79,7 @@ esp_err_t lcd_ili9341_init(const scr_controller_config_t *lcd_conf)
LCD_CHECK(lcd_conf->width <= ILI9341_RESOLUTION_HOR, "Width greater than maximum", ESP_ERR_INVALID_ARG);
LCD_CHECK(lcd_conf->height <= ILI9341_RESOLUTION_VER, "Height greater than maximum", ESP_ERR_INVALID_ARG);
LCD_CHECK(NULL != lcd_conf, "config pointer invalid", ESP_ERR_INVALID_ARG);
LCD_CHECK((NULL != lcd_conf->interface_drv->write_cmd && \
LCD_CHECK((NULL != lcd_conf->interface_drv->write_command && \
NULL != lcd_conf->interface_drv->write_data && \
NULL != lcd_conf->interface_drv->write && \
NULL != lcd_conf->interface_drv->read && \

View file

@ -0,0 +1,394 @@
// Copyright 2020 Espressif Systems (Shanghai) Co. Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "driver/gpio.h"
#include "screen_driver.h"
#include "screen_utility.h"
#include "ili9342.h"
static const char *TAG = "lcd ili9342";
#define LCD_CHECK(a, str, ret) if(!(a)) { \
ESP_LOGE(TAG,"%s:%d (%s):%s", __FILE__, __LINE__, __FUNCTION__, str); \
return (ret); \
}
#define LCD_NAME "ILI9342"
#define LCD_BPP 16
/** commands of ILI9342 */
#define LCD_SWRESET 0x01 // Software Reset
#define LCD_RDDID 0x04 // Read Display ID
#define LCD_INVOFF 0x20 // Display Inversion Off
#define LCD_INVON 0x21 // Display Inversion On
#define LCD_CASET 0x2A // Column Address Set
#define LCD_PASET 0x2B // Row Address Set
#define LCD_RAMWR 0x2C // Memory Writ
#define LCD_RAMRD 0x2E // Memory Read
#define LCD_MADCTL 0x36 // Memory Data Access Contro
/* MADCTL Defines */
#define MADCTL_MY 0x80
#define MADCTL_MX 0x40
#define MADCTL_MV 0x20
#define MADCTL_ML 0x10
#define MADCTL_RGB 0x08
#define MADCTL_MH 0x04
#define ILI9342_RESOLUTION_HOR 320
#define ILI9342_RESOLUTION_VER 240
static scr_handle_t g_lcd_handle;
/**
* This header file is only used to redefine the function to facilitate the call.
* It can only be placed in this position, not in the head of the file.
*/
#include "interface_drv_def.h"
scr_driver_t lcd_ili9342_default_driver = {
.init = lcd_ili9342_init,
.deinit = lcd_ili9342_deinit,
.set_direction = lcd_ili9342_set_rotation,
.set_window = lcd_ili9342_set_window,
.write_ram_data = lcd_ili9342_write_ram_data,
.draw_pixel = lcd_ili9342_draw_pixel,
.draw_bitmap = lcd_ili9342_draw_bitmap,
.get_info = lcd_ili9342_get_info,
};
static esp_err_t lcd_ili9342_init_reg(void);
esp_err_t lcd_ili9342_init(const scr_controller_config_t *lcd_conf)
{
LCD_CHECK(lcd_conf->width <= ILI9342_RESOLUTION_HOR, "Width greater than maximum", ESP_ERR_INVALID_ARG);
LCD_CHECK(lcd_conf->height <= ILI9342_RESOLUTION_VER, "Height greater than maximum", ESP_ERR_INVALID_ARG);
LCD_CHECK(NULL != lcd_conf, "config pointer invalid", ESP_ERR_INVALID_ARG);
LCD_CHECK((NULL != lcd_conf->interface_drv->write_command && \
NULL != lcd_conf->interface_drv->write_data && \
NULL != lcd_conf->interface_drv->write && \
NULL != lcd_conf->interface_drv->read && \
NULL != lcd_conf->interface_drv->bus_acquire && \
NULL != lcd_conf->interface_drv->bus_release),
"Interface driver invalid", ESP_ERR_INVALID_ARG);
esp_err_t ret;
// Reset the display
if (lcd_conf->pin_num_rst >= 0) {
gpio_pad_select_gpio(lcd_conf->pin_num_rst);
gpio_set_direction(lcd_conf->pin_num_rst, GPIO_MODE_OUTPUT);
gpio_set_level(lcd_conf->pin_num_rst, (lcd_conf->rst_active_level) & 0x1);
vTaskDelay(100 / portTICK_RATE_MS);
gpio_set_level(lcd_conf->pin_num_rst, (~(lcd_conf->rst_active_level)) & 0x1);
vTaskDelay(100 / portTICK_RATE_MS);
}
g_lcd_handle.interface_drv = lcd_conf->interface_drv;
g_lcd_handle.original_width = lcd_conf->width;
g_lcd_handle.original_height = lcd_conf->height;
g_lcd_handle.offset_hor = lcd_conf->offset_hor;
g_lcd_handle.offset_ver = lcd_conf->offset_ver;
ret = lcd_ili9342_init_reg();
LCD_CHECK(ESP_OK == ret, "Write lcd register encounter error", ESP_FAIL);
// Enable invert
ret = lcd_ili9342_set_invert(true);
LCD_CHECK(ESP_OK == ret, "Write lcd register invert error", ESP_FAIL);
// Enable backlight
if (lcd_conf->pin_num_bckl >= 0) {
gpio_pad_select_gpio(lcd_conf->pin_num_bckl);
gpio_set_direction(lcd_conf->pin_num_bckl, GPIO_MODE_OUTPUT);
gpio_set_level(lcd_conf->pin_num_bckl, (lcd_conf->bckl_active_level) & 0x1);
}
return lcd_ili9342_set_rotation(lcd_conf->rotate);
}
esp_err_t lcd_ili9342_deinit(void)
{
memset(&g_lcd_handle, 0, sizeof(scr_handle_t));
return ESP_OK;
}
esp_err_t lcd_ili9342_set_rotation(scr_dir_t dir)
{
esp_err_t ret;
uint8_t reg_data = 0;
reg_data |= MADCTL_RGB;
if (SCR_DIR_MAX < dir) {
dir >>= 5;
}
LCD_CHECK(dir < 8, "Unsupport rotate direction", ESP_ERR_INVALID_ARG);
switch (dir) {
case SCR_DIR_LRTB:
g_lcd_handle.width = g_lcd_handle.original_width;
g_lcd_handle.height = g_lcd_handle.original_height;
break;
case SCR_DIR_LRBT:
reg_data |= MADCTL_MY;
g_lcd_handle.width = g_lcd_handle.original_width;
g_lcd_handle.height = g_lcd_handle.original_height;
break;
case SCR_DIR_RLTB:
reg_data |= MADCTL_MX;
g_lcd_handle.width = g_lcd_handle.original_width;
g_lcd_handle.height = g_lcd_handle.original_height;
break;
case SCR_DIR_RLBT:
reg_data |= MADCTL_MX | MADCTL_MY;
g_lcd_handle.width = g_lcd_handle.original_width;
g_lcd_handle.height = g_lcd_handle.original_height;
break;
case SCR_DIR_TBLR:
reg_data |= MADCTL_MV;
g_lcd_handle.width = g_lcd_handle.original_height;
g_lcd_handle.height = g_lcd_handle.original_width;
break;
case SCR_DIR_BTLR:
reg_data |= MADCTL_MY | MADCTL_MV;
g_lcd_handle.width = g_lcd_handle.original_height;
g_lcd_handle.height = g_lcd_handle.original_width;
break;
case SCR_DIR_TBRL:
reg_data |= MADCTL_MX | MADCTL_MV;
g_lcd_handle.width = g_lcd_handle.original_height;
g_lcd_handle.height = g_lcd_handle.original_width;
break;
case SCR_DIR_BTRL:
reg_data |= MADCTL_MX | MADCTL_MY | MADCTL_MV;
g_lcd_handle.width = g_lcd_handle.original_height;
g_lcd_handle.height = g_lcd_handle.original_width;
break;
default: break;
}
ESP_LOGI(TAG, "MADCTL=%x", reg_data);
ret = LCD_WRITE_REG(LCD_MADCTL, reg_data);
LCD_CHECK(ESP_OK == ret, "Set screen rotate failed", ESP_FAIL);
g_lcd_handle.dir = dir;
return ESP_OK;
}
esp_err_t lcd_ili9342_get_info(scr_info_t *info)
{
LCD_CHECK(NULL != info, "info pointer invalid", ESP_ERR_INVALID_ARG);
info->width = g_lcd_handle.width;
info->height = g_lcd_handle.height;
info->dir = g_lcd_handle.dir;
info->name = LCD_NAME;
info->color_type = SCR_COLOR_TYPE_RGB565;
info->bpp = LCD_BPP;
return ESP_OK;
}
esp_err_t lcd_ili9342_set_window(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1)
{
LCD_CHECK((x1 < g_lcd_handle.width) && (y1 < g_lcd_handle.height), "The set coordinates exceed the screen size", ESP_ERR_INVALID_ARG);
LCD_CHECK((x0 <= x1) && (y0 <= y1), "Window coordinates invalid", ESP_ERR_INVALID_ARG);
esp_err_t ret = ESP_OK;
scr_utility_apply_offset(&g_lcd_handle, ILI9342_RESOLUTION_HOR, ILI9342_RESOLUTION_VER, &x0, &y0, &x1, &y1);
ret |= LCD_WRITE_CMD(LCD_CASET);
ret |= LCD_WRITE_DATA(x0 >> 8);
ret |= LCD_WRITE_DATA(x0 & 0xff);
ret |= LCD_WRITE_DATA(x1 >> 8);
ret |= LCD_WRITE_DATA(x1 & 0xff);
ret |= LCD_WRITE_CMD(LCD_PASET);
ret |= LCD_WRITE_DATA(y0 >> 8);
ret |= LCD_WRITE_DATA(y0 & 0xff);
ret |= LCD_WRITE_DATA(y1 >> 8);
ret |= LCD_WRITE_DATA(y1 & 0xff);
ret |= LCD_WRITE_CMD(LCD_RAMWR);
LCD_CHECK(ESP_OK == ret, "Set window failed", ESP_FAIL);
return ESP_OK;
}
esp_err_t lcd_ili9342_set_invert(bool is_invert)
{
return LCD_WRITE_CMD(is_invert ? LCD_INVON : LCD_INVOFF);
}
esp_err_t lcd_ili9342_write_ram_data(uint16_t color)
{
static uint8_t data[2];
data[0] = (uint8_t)(color & 0xff);
data[1] = (uint8_t)(color >> 8);
return LCD_WRITE(data, 2);
}
esp_err_t lcd_ili9342_draw_pixel(uint16_t x, uint16_t y, uint16_t color)
{
esp_err_t ret;
ret = lcd_ili9342_set_window(x, y, x, y);
if (ESP_OK != ret) {
return ESP_FAIL;
}
return lcd_ili9342_write_ram_data(color);
}
esp_err_t lcd_ili9342_draw_bitmap(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t *bitmap)
{
esp_err_t ret;
LCD_CHECK(NULL != bitmap, "bitmap pointer invalid", ESP_ERR_INVALID_ARG);
LCD_IFACE_ACQUIRE();
ret = lcd_ili9342_set_window(x, y, x + w - 1, y + h - 1);
if (ESP_OK != ret) {
return ESP_FAIL;
}
uint32_t len = w * h;
ret = LCD_WRITE((uint8_t *)bitmap, 2 * len);
LCD_IFACE_RELEASE();
LCD_CHECK(ESP_OK == ret, "lcd write ram data failed", ESP_FAIL);
return ESP_OK;
}
static esp_err_t lcd_ili9342_init_reg(void)
{
//SOFTWARE RESET
LCD_WRITE_CMD(0x01);
vTaskDelay(pdMS_TO_TICKS(100));
//POWER CONTROL A
LCD_WRITE_CMD(0xCB);
LCD_WRITE_DATA(0x39);
LCD_WRITE_DATA(0x2C);
LCD_WRITE_DATA(0x00);
LCD_WRITE_DATA(0x34);
LCD_WRITE_DATA(0x02);
//POWER CONTROL B
LCD_WRITE_CMD(0xCF);
LCD_WRITE_DATA(0x00);
LCD_WRITE_DATA(0xC1);
LCD_WRITE_DATA(0x30);
//DRIVER TIMING CONTROL A
LCD_WRITE_CMD(0xE8);
LCD_WRITE_DATA(0x85);
LCD_WRITE_DATA(0x00);
LCD_WRITE_DATA(0x78);
//DRIVER TIMING CONTROL B
LCD_WRITE_CMD(0xEA);
LCD_WRITE_DATA(0x00);
LCD_WRITE_DATA(0x00);
//POWER ON SEQUENCE CONTROL
LCD_WRITE_CMD(0xED);
LCD_WRITE_DATA(0x64);
LCD_WRITE_DATA(0x03);
LCD_WRITE_DATA(0x12);
LCD_WRITE_DATA(0x81);
//PUMP RATIO CONTROL
LCD_WRITE_CMD(0xF7);
LCD_WRITE_DATA(0x20);
//POWER CONTROL,VRH[5:0]
LCD_WRITE_CMD(0xC0);
LCD_WRITE_DATA(0x23);
//POWER CONTROL,SAP[2:0];BT[3:0]
LCD_WRITE_CMD(0xC1);
LCD_WRITE_DATA(0x10);
//VCM CONTROL
LCD_WRITE_CMD(0xC5);
LCD_WRITE_DATA(0x3E);
LCD_WRITE_DATA(0x28);
//VCM CONTROL 2
LCD_WRITE_CMD(0xC7);
LCD_WRITE_DATA(0x86);
//MEMORY ACCESS CONTROL
LCD_WRITE_CMD(0x36);
LCD_WRITE_DATA(0x48);
//PIXEL FORMAT
LCD_WRITE_CMD(0x3A);
LCD_WRITE_DATA(0x55);
//FRAME RATIO CONTROL, STANDARD RGB COLOR
LCD_WRITE_CMD(0xB1);
LCD_WRITE_DATA(0x00);
LCD_WRITE_DATA(0x18);
//DISPLAY FUNCTION CONTROL
LCD_WRITE_CMD(0xB6);
LCD_WRITE_DATA(0x08);
LCD_WRITE_DATA(0x82);
LCD_WRITE_DATA(0x27);
//3GAMMA FUNCTION DISABLE
LCD_WRITE_CMD(0xF2);
LCD_WRITE_DATA(0x00);
//GAMMA CURVE SELECTED
LCD_WRITE_CMD(0x26);
LCD_WRITE_DATA(0x01);
//POSITIVE GAMMA CORRECTION
LCD_WRITE_CMD(0xE0);
LCD_WRITE_DATA(0x0F);
LCD_WRITE_DATA(0x31);
LCD_WRITE_DATA(0x2B);
LCD_WRITE_DATA(0x0C);
LCD_WRITE_DATA(0x0E);
LCD_WRITE_DATA(0x08);
LCD_WRITE_DATA(0x4E);
LCD_WRITE_DATA(0xF1);
LCD_WRITE_DATA(0x37);
LCD_WRITE_DATA(0x07);
LCD_WRITE_DATA(0x10);
LCD_WRITE_DATA(0x03);
LCD_WRITE_DATA(0x0E);
LCD_WRITE_DATA(0x09);
LCD_WRITE_DATA(0x00);
//NEGATIVE GAMMA CORRECTION
LCD_WRITE_CMD(0xE1);
LCD_WRITE_DATA(0x00);
LCD_WRITE_DATA(0x0E);
LCD_WRITE_DATA(0x14);
LCD_WRITE_DATA(0x03);
LCD_WRITE_DATA(0x11);
LCD_WRITE_DATA(0x07);
LCD_WRITE_DATA(0x31);
LCD_WRITE_DATA(0xC1);
LCD_WRITE_DATA(0x48);
LCD_WRITE_DATA(0x08);
LCD_WRITE_DATA(0x0F);
LCD_WRITE_DATA(0x0C);
LCD_WRITE_DATA(0x31);
LCD_WRITE_DATA(0x36);
LCD_WRITE_DATA(0x0F);
//EXIT SLEEP
LCD_WRITE_CMD(0x11);
vTaskDelay(pdMS_TO_TICKS(120));
//TURN ON DISPLAY
LCD_WRITE_CMD(0x29);
return ESP_OK;
}

View file

@ -0,0 +1,134 @@
// Copyright 2020 Espressif Systems (Shanghai) Co. Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef _IOT_LCD_ILI9342_H_
#define _IOT_LCD_ILI9342_H_
#include "screen_driver.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Initialize screen
*
* @param lcd_conf Pointer to a structure with lcd config arguments.
*
* @return
* - ESP_OK on success
* - ESP_FAIL Driver not installed
*/
esp_err_t lcd_ili9342_init(const scr_controller_config_t *lcd_conf);
/**
* @brief Deinitialize screen
*
* @return
* - ESP_OK on success
* - ESP_FAIL Deinitialize failed
* - ESP_ERR_NOT_SUPPORTED unsupported
*/
esp_err_t lcd_ili9342_deinit(void);
/**
* @brief Set screen direction of rotation
*
* @param dir Pointer to a scr_dir_t structure.
*
* @return
* - ESP_OK on success
* - ESP_FAIL Failed
*/
esp_err_t lcd_ili9342_set_rotation(scr_dir_t dir);
/**
* @brief Get screen information
*
* @param info Pointer to a scr_info_t structure.
*
* @return
* - ESP_OK on success
* - ESP_FAIL Failed
*/
esp_err_t lcd_ili9342_get_info(scr_info_t *info);
/**
* @brief Set screen window
*
* @param x0 Starting point in X direction
* @param y0 Starting point in Y direction
* @param x1 End point in X direction
* @param y1 End point in Y direction
*
* @return
* - ESP_OK on success
* - ESP_FAIL Failed
*/
esp_err_t lcd_ili9342_set_window(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1);
/**
* @brief Set screen color invert
*
* @param is_invert true: color invert on, false: color invert off
* @return
* - ESP_OK on success
* - ESP_FAIL Failed
*/
esp_err_t lcd_ili9342_set_invert(bool is_invert);
/**
* @brief Write a RAM data
*
* @param color New color of a pixel
*
* @return
* - ESP_OK on success
* - ESP_FAIL Failed
*/
esp_err_t lcd_ili9342_write_ram_data(uint16_t color);
/**
* @brief Draw one pixel in screen with color
*
* @param x X co-ordinate of set orientation
* @param y Y co-ordinate of set orientation
* @param color New color of the pixel
*
* @return
* - ESP_OK on success
* - ESP_FAIL Failed
*/
esp_err_t lcd_ili9342_draw_pixel(uint16_t x, uint16_t y, uint16_t color);
/**
* @brief Fill the pixels on LCD screen with bitmap
*
* @param x Starting point in X direction
* @param y Starting point in Y direction
* @param w width of image in bitmap array
* @param h height of image in bitmap array
* @param bitmap pointer to bitmap array
*
* @return
* - ESP_OK on success
* - ESP_FAIL Failed
*/
esp_err_t lcd_ili9342_draw_bitmap(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t *bitmap);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -74,7 +74,7 @@ esp_err_t lcd_ili9486_init(const scr_controller_config_t *lcd_conf)
LCD_CHECK(lcd_conf->width <= ILI9486_RESOLUTION_HOR, "Width greater than maximum", ESP_ERR_INVALID_ARG);
LCD_CHECK(lcd_conf->height <= ILI9486_RESOLUTION_VER, "Height greater than maximum", ESP_ERR_INVALID_ARG);
LCD_CHECK(NULL != lcd_conf, "config pointer invalid", ESP_ERR_INVALID_ARG);
LCD_CHECK((NULL != lcd_conf->interface_drv->write_cmd && \
LCD_CHECK((NULL != lcd_conf->interface_drv->write_command && \
NULL != lcd_conf->interface_drv->write_data && \
NULL != lcd_conf->interface_drv->write && \
NULL != lcd_conf->interface_drv->read && \

View file

@ -0,0 +1,401 @@
// Copyright 2020 Espressif Systems (Shanghai) Co. Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "driver/gpio.h"
#include "screen_driver.h"
#include "screen_utility.h"
#include "ili9488.h"
static const char *TAG = "ILI9488";
#define LCD_CHECK(a, str, ret) if(!(a)) { \
ESP_LOGE(TAG,"%s:%d (%s):%s", __FILE__, __LINE__, __FUNCTION__, str); \
return (ret); \
}
#define ILI9488_NOP 0x00
#define ILI9488_SWRESET 0x01
#define ILI9488_RDDID 0x04
#define ILI9488_RDDST 0x09
#define ILI9488_SLPIN 0x10
#define ILI9488_SLPOUT 0x11
#define ILI9488_PTLON 0x12
#define ILI9488_NORON 0x13
#define ILI9488_RDMODE 0x0A
#define ILI9488_RDMADCTL 0x0B
#define ILI9488_RDPIXFMT 0x0C
#define ILI9488_RDIMGFMT 0x0D
#define ILI9488_RDSELFDIAG 0x0F
#define ILI9488_INVOFF 0x20
#define ILI9488_INVON 0x21
#define ILI9488_GAMMASET 0x26
#define ILI9488_DISPOFF 0x28
#define ILI9488_DISPON 0x29
#define ILI9488_CASET 0x2A
#define ILI9488_PASET 0x2B
#define ILI9488_RAMWR 0x2C
#define ILI9488_RAMRD 0x2E
#define ILI9488_PTLAR 0x30
#define ILI9488_VSCRDEF 0x33
#define ILI9488_MADCTL 0x36
#define ILI9488_VSCRSADD 0x37
#define ILI9488_PIXFMT 0x3A
#define ILI9488_RAMWRCONT 0x3C
#define ILI9488_RAMRDCONT 0x3E
#define ILI9488_IMCTR 0xB0
#define ILI9488_FRMCTR1 0xB1
#define ILI9488_FRMCTR2 0xB2
#define ILI9488_FRMCTR3 0xB3
#define ILI9488_INVCTR 0xB4
#define ILI9488_DFUNCTR 0xB6
#define ILI9488_PWCTR1 0xC0
#define ILI9488_PWCTR2 0xC1
#define ILI9488_PWCTR3 0xC2
#define ILI9488_PWCTR4 0xC3
#define ILI9488_PWCTR5 0xC4
#define ILI9488_VMCTR1 0xC5
#define ILI9488_VMCTR2 0xC7
#define ILI9488_RDID1 0xDA
#define ILI9488_RDID2 0xDB
#define ILI9488_RDID3 0xDC
#define ILI9488_RDID4 0xDD
#define ILI9488_GMCTRP1 0xE0
#define ILI9488_GMCTRN1 0xE1
#define ILI9488_IMGFUNCT 0xE9
#define ILI9488_ADJCTR3 0xF7
#define ILI9488_MAD_RGB 0x08
#define ILI9488_MAD_BGR 0x00
#define ILI9488_MAD_VERTICAL 0x20
#define ILI9488_MAD_X_LEFT 0x00
#define ILI9488_MAD_X_RIGHT 0x40
#define ILI9488_MAD_Y_UP 0x80
#define ILI9488_MAD_Y_DOWN 0x00
/* MADCTL Defines */
#define MADCTL_MY 0x80
#define MADCTL_MX 0x40
#define MADCTL_MV 0x20
#define MADCTL_ML 0x10
#define MADCTL_RGB 0x08
#define MADCTL_MH 0x04
#define LCD_NAME "ILI9488"
#define LCD_BPP 16
#define ILI9488_RESOLUTION_HOR 320
#define ILI9488_RESOLUTION_VER 480
static scr_handle_t g_lcd_handle;
/**
* This header file is only used to redefine the function to facilitate the call.
* It can only be placed in this position, not in the head of the file.
*/
#include "interface_drv_def.h"
scr_driver_t lcd_ili9488_default_driver = {
.init = lcd_ili9488_init,
.deinit = lcd_ili9488_deinit,
.set_direction = lcd_ili9488_set_rotation,
.set_window = lcd_ili9488_set_window,
.write_ram_data = lcd_ili9488_write_ram_data,
.draw_pixel = lcd_ili9488_draw_pixel,
.draw_bitmap = lcd_ili9488_draw_bitmap,
.get_info = lcd_ili9488_get_info,
};
static void lcd_ili9488_init_reg(void);
esp_err_t lcd_ili9488_init(const scr_controller_config_t *lcd_conf)
{
LCD_CHECK(lcd_conf->width <= ILI9488_RESOLUTION_HOR, "Width greater than maximum", ESP_ERR_INVALID_ARG);
LCD_CHECK(lcd_conf->height <= ILI9488_RESOLUTION_VER, "Height greater than maximum", ESP_ERR_INVALID_ARG);
LCD_CHECK(NULL != lcd_conf, "config pointer invalid", ESP_ERR_INVALID_ARG);
LCD_CHECK((NULL != lcd_conf->interface_drv->write_command && \
NULL != lcd_conf->interface_drv->write_data && \
NULL != lcd_conf->interface_drv->write && \
NULL != lcd_conf->interface_drv->read && \
NULL != lcd_conf->interface_drv->bus_acquire && \
NULL != lcd_conf->interface_drv->bus_release),
"Interface driver invalid", ESP_ERR_INVALID_ARG);
esp_err_t ret;
// Reset the display
if (lcd_conf->pin_num_rst >= 0) {
gpio_pad_select_gpio(lcd_conf->pin_num_rst);
gpio_set_direction(lcd_conf->pin_num_rst, GPIO_MODE_OUTPUT);
gpio_set_level(lcd_conf->pin_num_rst, (lcd_conf->rst_active_level) & 0x1);
vTaskDelay(100 / portTICK_RATE_MS);
gpio_set_level(lcd_conf->pin_num_rst, (~(lcd_conf->rst_active_level)) & 0x1);
vTaskDelay(100 / portTICK_RATE_MS);
}
g_lcd_handle.interface_drv = lcd_conf->interface_drv;
g_lcd_handle.original_width = lcd_conf->width;
g_lcd_handle.original_height = lcd_conf->height;
g_lcd_handle.offset_hor = lcd_conf->offset_hor;
g_lcd_handle.offset_ver = lcd_conf->offset_ver;
lcd_ili9488_init_reg();
// Enable backlight
if (lcd_conf->pin_num_bckl >= 0) {
gpio_pad_select_gpio(lcd_conf->pin_num_bckl);
gpio_set_direction(lcd_conf->pin_num_bckl, GPIO_MODE_OUTPUT);
gpio_set_level(lcd_conf->pin_num_bckl, (lcd_conf->bckl_active_level) & 0x1);
}
ret = lcd_ili9488_set_rotation(lcd_conf->rotate);
LCD_CHECK(ESP_OK == ret, "set rotation failed", ESP_FAIL);
ret = lcd_ili9488_set_invert(1); /**< ILI9488 setting the reverse color is the normal color */
LCD_CHECK(ESP_OK == ret, "Set color invert failed", ESP_FAIL);
return ESP_OK;
}
esp_err_t lcd_ili9488_deinit(void)
{
memset(&g_lcd_handle, 0, sizeof(scr_handle_t));
return ESP_OK;
}
esp_err_t lcd_ili9488_set_rotation(scr_dir_t dir)
{
esp_err_t ret;
uint8_t reg_data = MADCTL_RGB;
if (SCR_DIR_MAX < dir) {
dir >>= 5;
}
LCD_CHECK(dir < 8, "Unsupport rotate direction", ESP_ERR_INVALID_ARG);
switch (dir) {
case SCR_DIR_LRTB:
g_lcd_handle.width = g_lcd_handle.original_width;
g_lcd_handle.height = g_lcd_handle.original_height;
break;
case SCR_DIR_LRBT:
reg_data |= MADCTL_MY;
g_lcd_handle.width = g_lcd_handle.original_width;
g_lcd_handle.height = g_lcd_handle.original_height;
break;
case SCR_DIR_RLTB:
reg_data |= MADCTL_MX;
g_lcd_handle.width = g_lcd_handle.original_width;
g_lcd_handle.height = g_lcd_handle.original_height;
break;
case SCR_DIR_RLBT:
reg_data |= MADCTL_MX | MADCTL_MY;
g_lcd_handle.width = g_lcd_handle.original_width;
g_lcd_handle.height = g_lcd_handle.original_height;
break;
case SCR_DIR_TBLR:
reg_data |= MADCTL_MV;
g_lcd_handle.width = g_lcd_handle.original_height;
g_lcd_handle.height = g_lcd_handle.original_width;
break;
case SCR_DIR_BTLR:
reg_data |= MADCTL_MY | MADCTL_MV;
g_lcd_handle.width = g_lcd_handle.original_height;
g_lcd_handle.height = g_lcd_handle.original_width;
break;
case SCR_DIR_TBRL:
reg_data |= MADCTL_MX | MADCTL_MV;
g_lcd_handle.width = g_lcd_handle.original_height;
g_lcd_handle.height = g_lcd_handle.original_width;
break;
case SCR_DIR_BTRL:
reg_data |= MADCTL_MX | MADCTL_MY | MADCTL_MV;
g_lcd_handle.width = g_lcd_handle.original_height;
g_lcd_handle.height = g_lcd_handle.original_width;
break;
default: break;
}
ESP_LOGI(TAG, "MADCTL=0x%x", reg_data);
ret = LCD_WRITE_REG(ILI9488_MADCTL, reg_data);
LCD_CHECK(ESP_OK == ret, "Set screen rotate failed", ESP_FAIL);
g_lcd_handle.dir = dir;
return ESP_OK;
}
esp_err_t lcd_ili9488_get_info(scr_info_t *info)
{
LCD_CHECK(NULL != info, "info pointer invalid", ESP_ERR_INVALID_ARG);
info->width = g_lcd_handle.width;
info->height = g_lcd_handle.height;
info->dir = g_lcd_handle.dir;
info->name = LCD_NAME;
info->color_type = SCR_COLOR_TYPE_RGB565;
info->bpp = LCD_BPP;
return ESP_OK;
}
esp_err_t lcd_ili9488_set_invert(bool is_invert)
{
return LCD_WRITE_CMD(is_invert ? ILI9488_INVON : ILI9488_INVOFF);
}
esp_err_t lcd_ili9488_set_window(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1)
{
LCD_CHECK((x1 < g_lcd_handle.width) && (y1 < g_lcd_handle.height), "The set coordinates exceed the screen size", ESP_ERR_INVALID_ARG);
LCD_CHECK((x0 <= x1) && (y0 <= y1), "Window coordinates invalid", ESP_ERR_INVALID_ARG);
esp_err_t ret = ESP_OK;
scr_utility_apply_offset(&g_lcd_handle, ILI9488_RESOLUTION_HOR, ILI9488_RESOLUTION_VER, &x0, &y0, &x1, &y1);
ret |= LCD_WRITE_CMD(ILI9488_CASET);
ret |= LCD_WRITE_DATA(x0 >> 8);
ret |= LCD_WRITE_DATA(x0 & 0xff);
ret |= LCD_WRITE_DATA(x1 >> 8);
ret |= LCD_WRITE_DATA(x1 & 0xff);
ret |= LCD_WRITE_CMD(ILI9488_PASET);
ret |= LCD_WRITE_DATA(y0 >> 8);
ret |= LCD_WRITE_DATA(y0 & 0xff);
ret |= LCD_WRITE_DATA(y1 >> 8);
ret |= LCD_WRITE_DATA(y1 & 0xff);
ret |= LCD_WRITE_CMD(ILI9488_RAMWR);
LCD_CHECK(ESP_OK == ret, "Set window failed", ESP_FAIL);
return ESP_OK;
}
esp_err_t lcd_ili9488_write_ram_data(uint16_t color)
{
static uint8_t data[2];
data[0] = (uint8_t)(color & 0xff);
data[1] = (uint8_t)(color >> 8);
return LCD_WRITE(data, 2);
}
esp_err_t lcd_ili9488_draw_pixel(uint16_t x, uint16_t y, uint16_t color)
{
esp_err_t ret;
ret = lcd_ili9488_set_window(x, y, x, y);
if (ESP_OK != ret) {
return ESP_FAIL;
}
return lcd_ili9488_write_ram_data(color);
}
esp_err_t lcd_ili9488_draw_bitmap(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t *bitmap)
{
esp_err_t ret;
LCD_CHECK(NULL != bitmap, "bitmap pointer invalid", ESP_ERR_INVALID_ARG);
LCD_IFACE_ACQUIRE();
ret = lcd_ili9488_set_window(x, y, x + w - 1, y + h - 1);
if (ESP_OK != ret) {
return ESP_FAIL;
}
uint32_t len = w * h;
ret = LCD_WRITE((uint8_t *)bitmap, 2 * len);
LCD_IFACE_RELEASE();
LCD_CHECK(ESP_OK == ret, "lcd write ram data failed", ESP_FAIL);
return ESP_OK;
}
static void lcd_ili9488_init_reg(void)
{
LCD_WRITE_CMD(ILI9488_SWRESET);
vTaskDelay(120 / portTICK_RATE_MS);
// positive gamma control
LCD_WRITE_CMD(ILI9488_GMCTRP1);
LCD_WRITE_DATA(0x00);
LCD_WRITE_DATA(0x03);
LCD_WRITE_DATA(0x09);
LCD_WRITE_DATA(0x08);
LCD_WRITE_DATA(0x16);
LCD_WRITE_DATA(0x0A);
LCD_WRITE_DATA(0x3F);
LCD_WRITE_DATA(0x78);
LCD_WRITE_DATA(0x4C);
LCD_WRITE_DATA(0x09);
LCD_WRITE_DATA(0x0A);
LCD_WRITE_DATA(0x08);
LCD_WRITE_DATA(0x16);
LCD_WRITE_DATA(0x1A);
LCD_WRITE_DATA(0x0F);
// negative gamma control
LCD_WRITE_CMD(ILI9488_GMCTRN1);
LCD_WRITE_DATA(0x00);
LCD_WRITE_DATA(0x16);
LCD_WRITE_DATA(0x19);
LCD_WRITE_DATA(0x03);
LCD_WRITE_DATA(0x0F);
LCD_WRITE_DATA(0x05);
LCD_WRITE_DATA(0x32);
LCD_WRITE_DATA(0x45);
LCD_WRITE_DATA(0x46);
LCD_WRITE_DATA(0x04);
LCD_WRITE_DATA(0x0E);
LCD_WRITE_DATA(0x0D);
LCD_WRITE_DATA(0x35);
LCD_WRITE_DATA(0x37);
LCD_WRITE_DATA(0x0F);
// Power Control 1 (Vreg1out, Verg2out)
LCD_WRITE_CMD(ILI9488_PWCTR1);
LCD_WRITE_DATA(0x17);
LCD_WRITE_DATA(0x15);
// Power Control 2 (VGH,VGL)
LCD_WRITE_CMD(ILI9488_PWCTR2);
LCD_WRITE_DATA(0x41);
// Power Control 3 (Vcom)
LCD_WRITE_CMD(ILI9488_VMCTR1);
LCD_WRITE_DATA(0x00);
LCD_WRITE_DATA(0x12);
LCD_WRITE_DATA(0x80);
LCD_WRITE_CMD(ILI9488_IMCTR); LCD_WRITE_DATA(0x80); // Interface Mode Control (SDO NOT USE)
LCD_WRITE_CMD(ILI9488_PIXFMT); LCD_WRITE_DATA(0x55); // Interface Pixel Format (16 bit)
LCD_WRITE_CMD(ILI9488_FRMCTR1); LCD_WRITE_DATA(0xA0); // Frame rate (60Hz)
LCD_WRITE_CMD(ILI9488_INVCTR); LCD_WRITE_DATA(0x02); // Display Inversion Control (2-dot)
LCD_WRITE_CMD(ILI9488_DFUNCTR); // Display Function Control RGB/MCU Interface Control
LCD_WRITE_DATA(0x02);
LCD_WRITE_DATA(0x02);
LCD_WRITE_CMD(ILI9488_IMGFUNCT); // Set Image Functio (Disable 24 bit data)
LCD_WRITE_DATA(0x00);
LCD_WRITE_CMD(ILI9488_ADJCTR3); // Adjust Control (D7 stream, loose)
LCD_WRITE_DATA(0xa9);
LCD_WRITE_DATA(0x51);
LCD_WRITE_DATA(0x2c);
LCD_WRITE_DATA(0x82);
LCD_WRITE_CMD(ILI9488_SLPOUT); // Exit Sleep
LCD_WRITE_CMD(ILI9488_DISPON); // Display on
vTaskDelay(120 / portTICK_RATE_MS);
}

View file

@ -0,0 +1,138 @@
// Copyright 2020 Espressif Systems (Shanghai) Co. Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef _IOT_ILI9488_H_
#define _IOT_ILI9488_H_
#include "screen_driver.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Initialize screen
*
* @param lcd_conf Pointer to a structure with lcd config arguments.
*
* @return
* - ESP_OK on success
* - ESP_FAIL Driver not installed
*/
esp_err_t lcd_ili9488_init(const scr_controller_config_t *lcd_conf);
/**
* @brief Deinitialize screen
*
* @return
* - ESP_OK on success
* - ESP_FAIL Deinitialize failed
* - ESP_ERR_NOT_SUPPORTED unsupported
*/
esp_err_t lcd_ili9488_deinit(void);
/**
* @brief Set screen direction of rotation
*
* @param dir Pointer to a scr_dir_t structure.
*
* @return
* - ESP_OK on success
* - ESP_FAIL Failed
*/
esp_err_t lcd_ili9488_set_rotation(scr_dir_t dir);
/**
* @brief Get screen information
*
* @param info Pointer to a scr_info_t structure.
*
* @return
* - ESP_OK on success
* - ESP_FAIL Failed
*/
esp_err_t lcd_ili9488_get_info(scr_info_t *info);
/**
* @brief Set screen color invert
*
* @param is_invert true: color invert on, false: color invert off
* @return
* - ESP_OK on success
* - ESP_FAIL Failed
*/
esp_err_t lcd_ili9488_set_invert(bool is_invert);
/**
* @brief Set screen window
*
* @param x0 Starting point in X direction
* @param y0 Starting point in Y direction
* @param x1 End point in X direction
* @param y1 End point in Y direction
*
* @return
* - ESP_OK on success
* - ESP_FAIL Failed
*/
esp_err_t lcd_ili9488_set_window(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1);
/**
* @brief Write a RAM data
*
* @param color New color of a pixel
*
* @return
* - ESP_OK on success
* - ESP_FAIL Failed
*/
esp_err_t lcd_ili9488_write_ram_data(uint16_t color);
/**
* @brief Draw one pixel in screen with color
*
* @param x X co-ordinate of set orientation
* @param y Y co-ordinate of set orientation
* @param color New color of the pixel
*
* @return
* - ESP_OK on success
* - ESP_FAIL Failed
*/
esp_err_t lcd_ili9488_draw_pixel(uint16_t x, uint16_t y, uint16_t color);
/**
* @brief Fill the pixels on LCD screen with bitmap
*
* @param x Starting point in X direction
* @param y Starting point in Y direction
* @param w width of image in bitmap array
* @param h height of image in bitmap array
* @param bitmap pointer to bitmap array
*
* @return
* - ESP_OK on success
* - ESP_FAIL Failed
*/
esp_err_t lcd_ili9488_draw_bitmap(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t *bitmap);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -76,7 +76,7 @@ esp_err_t lcd_ili9806_init(const scr_controller_config_t *lcd_conf)
LCD_CHECK(lcd_conf->width <= ILI9806_RESOLUTION_HOR, "Width greater than maximum", ESP_ERR_INVALID_ARG);
LCD_CHECK(lcd_conf->height <= ILI9806_RESOLUTION_VER, "Height greater than maximum", ESP_ERR_INVALID_ARG);
LCD_CHECK(NULL != lcd_conf, "config pointer invalid", ESP_ERR_INVALID_ARG);
LCD_CHECK((NULL != lcd_conf->interface_drv->write_cmd && \
LCD_CHECK((NULL != lcd_conf->interface_drv->write_command && \
NULL != lcd_conf->interface_drv->write_data && \
NULL != lcd_conf->interface_drv->write && \
NULL != lcd_conf->interface_drv->read && \

View file

@ -77,7 +77,7 @@ esp_err_t lcd_nt35510_init(const scr_controller_config_t *lcd_conf)
LCD_CHECK(lcd_conf->width <= NT35510_RESOLUTION_HOR, "Width greater than maximum", ESP_ERR_INVALID_ARG);
LCD_CHECK(lcd_conf->height <= NT35510_RESOLUTION_VER, "Height greater than maximum", ESP_ERR_INVALID_ARG);
LCD_CHECK(NULL != lcd_conf, "config pointer invalid", ESP_ERR_INVALID_ARG);
LCD_CHECK((NULL != lcd_conf->interface_drv->write_cmd && \
LCD_CHECK((NULL != lcd_conf->interface_drv->write_command && \
NULL != lcd_conf->interface_drv->write_data && \
NULL != lcd_conf->interface_drv->write && \
NULL != lcd_conf->interface_drv->read && \
@ -176,7 +176,7 @@ esp_err_t lcd_nt35510_set_rotation(scr_dir_t dir)
default: break;
}
ESP_LOGI(TAG, "MADCTL=0x%x", reg_data);
ret = LCD_WRITE_REG(NT35510_MADCTL, reg_data);
ret = LCD_WRITE_REG_16B(NT35510_MADCTL, reg_data);
LCD_CHECK(ESP_OK == ret, "Set screen rotate failed", ESP_FAIL);
g_lcd_handle.dir = dir;
return ESP_OK;
@ -201,16 +201,16 @@ esp_err_t lcd_nt35510_set_window(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t
esp_err_t ret = ESP_OK;
scr_utility_apply_offset(&g_lcd_handle, NT35510_RESOLUTION_HOR, NT35510_RESOLUTION_VER, &x0, &y0, &x1, &y1);
ret |= LCD_WRITE_REG(NT35510_CASET, x0 >> 8);
ret |= LCD_WRITE_REG(NT35510_CASET + 1, x0 & 0xff);
ret |= LCD_WRITE_REG(NT35510_CASET + 2, x1 >> 8);
ret |= LCD_WRITE_REG(NT35510_CASET + 3, x1 & 0xff);
ret |= LCD_WRITE_REG(NT35510_RASET, y0 >> 8);
ret |= LCD_WRITE_REG(NT35510_RASET + 1, y0 & 0xff);
ret |= LCD_WRITE_REG(NT35510_RASET + 2, y1 >> 8);
ret |= LCD_WRITE_REG(NT35510_RASET + 3, y1 & 0xff);
ret |= LCD_WRITE_REG_16B(NT35510_CASET, x0 >> 8);
ret |= LCD_WRITE_REG_16B(NT35510_CASET + 1, x0 & 0xff);
ret |= LCD_WRITE_REG_16B(NT35510_CASET + 2, x1 >> 8);
ret |= LCD_WRITE_REG_16B(NT35510_CASET + 3, x1 & 0xff);
ret |= LCD_WRITE_REG_16B(NT35510_RASET, y0 >> 8);
ret |= LCD_WRITE_REG_16B(NT35510_RASET + 1, y0 & 0xff);
ret |= LCD_WRITE_REG_16B(NT35510_RASET + 2, y1 >> 8);
ret |= LCD_WRITE_REG_16B(NT35510_RASET + 3, y1 & 0xff);
ret |= LCD_WRITE_CMD(NT35510_RAMWR);
ret |= LCD_WRITE_CMD_16B(NT35510_RAMWR);
LCD_CHECK(ESP_OK == ret, "Set window failed", ESP_FAIL);
return ESP_OK;
}
@ -253,387 +253,426 @@ esp_err_t lcd_nt35510_draw_bitmap(uint16_t x, uint16_t y, uint16_t w, uint16_t h
static void lcd_nt35510_init_reg(void)
{
LCD_WRITE_CMD(0x0100); // Software Reset
// Software Reset
LCD_WRITE_CMD_16B(0x0100);
vTaskDelay(10 / portTICK_RATE_MS);
LCD_WRITE_CMD(0x1200);
LCD_WRITE_REG(0xf000, 0x0055);
LCD_WRITE_REG(0xf001, 0x00aa);
LCD_WRITE_REG(0xf002, 0x0052);
LCD_WRITE_REG(0xf003, 0x0008);
LCD_WRITE_REG(0xf004, 0x0001);
LCD_WRITE_REG(0xbc01, 0x0086);
LCD_WRITE_REG(0xbc02, 0x006a);
LCD_WRITE_REG(0xbd01, 0x0086);
LCD_WRITE_REG(0xbd02, 0x006a);
LCD_WRITE_REG(0xbe01, 0x0067);
// Partial mode on
LCD_WRITE_CMD_16B(0x1200);
LCD_WRITE_REG(0xd100, 0x0000);
LCD_WRITE_REG(0xd101, 0x005d);
LCD_WRITE_REG(0xd102, 0x0000);
LCD_WRITE_REG(0xd103, 0x006b);
LCD_WRITE_REG(0xd104, 0x0000);
LCD_WRITE_REG(0xd105, 0x0084);
LCD_WRITE_REG(0xd106, 0x0000);
LCD_WRITE_REG(0xd107, 0x009c);
LCD_WRITE_REG(0xd108, 0x0000);
LCD_WRITE_REG(0xd109, 0x00b1);
LCD_WRITE_REG(0xd10a, 0x0000);
LCD_WRITE_REG(0xd10b, 0x00d9);
LCD_WRITE_REG(0xd10c, 0x0000);
LCD_WRITE_REG(0xd10d, 0x00fd);
LCD_WRITE_REG(0xd10e, 0x0001);
LCD_WRITE_REG(0xd10f, 0x0038);
LCD_WRITE_REG(0xd110, 0x0001);
LCD_WRITE_REG(0xd111, 0x0068);
LCD_WRITE_REG(0xd112, 0x0001);
LCD_WRITE_REG(0xd113, 0x00b9);
LCD_WRITE_REG(0xd114, 0x0001);
LCD_WRITE_REG(0xd115, 0x00fb);
LCD_WRITE_REG(0xd116, 0x0002);
LCD_WRITE_REG(0xd117, 0x0063);
LCD_WRITE_REG(0xd118, 0x0002);
LCD_WRITE_REG(0xd119, 0x00b9);
LCD_WRITE_REG(0xd11a, 0x0002);
LCD_WRITE_REG(0xd11b, 0x00bb);
LCD_WRITE_REG(0xd11c, 0x0003);
LCD_WRITE_REG(0xd11d, 0x0003);
LCD_WRITE_REG(0xd11e, 0x0003);
LCD_WRITE_REG(0xd11f, 0x0046);
LCD_WRITE_REG(0xd120, 0x0003);
LCD_WRITE_REG(0xd121, 0x0069);
LCD_WRITE_REG(0xd122, 0x0003);
LCD_WRITE_REG(0xd123, 0x008f);
LCD_WRITE_REG(0xd124, 0x0003);
LCD_WRITE_REG(0xd125, 0x00a4);
LCD_WRITE_REG(0xd126, 0x0003);
LCD_WRITE_REG(0xd127, 0x00b9);
LCD_WRITE_REG(0xd128, 0x0003);
LCD_WRITE_REG(0xd129, 0x00c7);
LCD_WRITE_REG(0xd12a, 0x0003);
LCD_WRITE_REG(0xd12b, 0x00c9);
LCD_WRITE_REG(0xd12c, 0x0003);
LCD_WRITE_REG(0xd12d, 0x00cb);
LCD_WRITE_REG(0xd12e, 0x0003);
LCD_WRITE_REG(0xd12f, 0x00cb);
LCD_WRITE_REG(0xd130, 0x0003);
LCD_WRITE_REG(0xd131, 0x00cb);
LCD_WRITE_REG(0xd132, 0x0003);
LCD_WRITE_REG(0xd133, 0x00cc);
// Enable manufacturer command set, select page 1
LCD_WRITE_REG_16B(0xf000, 0x0055);
LCD_WRITE_REG_16B(0xf001, 0x00aa);
LCD_WRITE_REG_16B(0xf002, 0x0052);
LCD_WRITE_REG_16B(0xf003, 0x0008);
LCD_WRITE_REG_16B(0xf004, 0x0001);
LCD_WRITE_REG(0xd200, 0x0000);
LCD_WRITE_REG(0xd201, 0x005d);
LCD_WRITE_REG(0xd202, 0x0000);
LCD_WRITE_REG(0xd203, 0x006b);
LCD_WRITE_REG(0xd204, 0x0000);
LCD_WRITE_REG(0xd205, 0x0084);
LCD_WRITE_REG(0xd206, 0x0000);
LCD_WRITE_REG(0xd207, 0x009c);
LCD_WRITE_REG(0xd208, 0x0000);
LCD_WRITE_REG(0xd209, 0x00b1);
LCD_WRITE_REG(0xd20a, 0x0000);
LCD_WRITE_REG(0xd20b, 0x00d9);
LCD_WRITE_REG(0xd20c, 0x0000);
LCD_WRITE_REG(0xd20d, 0x00fd);
LCD_WRITE_REG(0xd20e, 0x0001);
LCD_WRITE_REG(0xd20f, 0x0038);
LCD_WRITE_REG(0xd210, 0x0001);
LCD_WRITE_REG(0xd211, 0x0068);
LCD_WRITE_REG(0xd212, 0x0001);
LCD_WRITE_REG(0xd213, 0x00b9);
LCD_WRITE_REG(0xd214, 0x0001);
LCD_WRITE_REG(0xd215, 0x00fb);
LCD_WRITE_REG(0xd216, 0x0002);
LCD_WRITE_REG(0xd217, 0x0063);
LCD_WRITE_REG(0xd218, 0x0002);
LCD_WRITE_REG(0xd219, 0x00b9);
LCD_WRITE_REG(0xd21a, 0x0002);
LCD_WRITE_REG(0xd21b, 0x00bb);
LCD_WRITE_REG(0xd21c, 0x0003);
LCD_WRITE_REG(0xd21d, 0x0003);
LCD_WRITE_REG(0xd21e, 0x0003);
LCD_WRITE_REG(0xd21f, 0x0046);
LCD_WRITE_REG(0xd220, 0x0003);
LCD_WRITE_REG(0xd221, 0x0069);
LCD_WRITE_REG(0xd222, 0x0003);
LCD_WRITE_REG(0xd223, 0x008f);
LCD_WRITE_REG(0xd224, 0x0003);
LCD_WRITE_REG(0xd225, 0x00a4);
LCD_WRITE_REG(0xd226, 0x0003);
LCD_WRITE_REG(0xd227, 0x00b9);
LCD_WRITE_REG(0xd228, 0x0003);
LCD_WRITE_REG(0xd229, 0x00c7);
LCD_WRITE_REG(0xd22a, 0x0003);
LCD_WRITE_REG(0xd22b, 0x00c9);
LCD_WRITE_REG(0xd22c, 0x0003);
LCD_WRITE_REG(0xd22d, 0x00cb);
LCD_WRITE_REG(0xd22e, 0x0003);
LCD_WRITE_REG(0xd22f, 0x00cb);
LCD_WRITE_REG(0xd230, 0x0003);
LCD_WRITE_REG(0xd231, 0x00cb);
LCD_WRITE_REG(0xd232, 0x0003);
LCD_WRITE_REG(0xd233, 0x00cc);
// VGML and VGSP voltages (regulator output voltage VGMP/VGSP for positive gamma divider)
LCD_WRITE_REG_16B(0xbc01, 0x0086);
LCD_WRITE_REG_16B(0xbc02, 0x006a);
LCD_WRITE_REG(0xd300, 0x0000);
LCD_WRITE_REG(0xd301, 0x005d);
LCD_WRITE_REG(0xd302, 0x0000);
LCD_WRITE_REG(0xd303, 0x006b);
LCD_WRITE_REG(0xd304, 0x0000);
LCD_WRITE_REG(0xd305, 0x0084);
LCD_WRITE_REG(0xd306, 0x0000);
LCD_WRITE_REG(0xd307, 0x009c);
LCD_WRITE_REG(0xd308, 0x0000);
LCD_WRITE_REG(0xd309, 0x00b1);
LCD_WRITE_REG(0xd30a, 0x0000);
LCD_WRITE_REG(0xd30b, 0x00d9);
LCD_WRITE_REG(0xd30c, 0x0000);
LCD_WRITE_REG(0xd30d, 0x00fd);
LCD_WRITE_REG(0xd30e, 0x0001);
LCD_WRITE_REG(0xd30f, 0x0038);
LCD_WRITE_REG(0xd310, 0x0001);
LCD_WRITE_REG(0xd311, 0x0068);
LCD_WRITE_REG(0xd312, 0x0001);
LCD_WRITE_REG(0xd313, 0x00b9);
LCD_WRITE_REG(0xd314, 0x0001);
LCD_WRITE_REG(0xd315, 0x00fb);
LCD_WRITE_REG(0xd316, 0x0002);
LCD_WRITE_REG(0xd317, 0x0063);
LCD_WRITE_REG(0xd318, 0x0002);
LCD_WRITE_REG(0xd319, 0x00b9);
LCD_WRITE_REG(0xd31a, 0x0002);
LCD_WRITE_REG(0xd31b, 0x00bb);
LCD_WRITE_REG(0xd31c, 0x0003);
LCD_WRITE_REG(0xd31d, 0x0003);
LCD_WRITE_REG(0xd31e, 0x0003);
LCD_WRITE_REG(0xd31f, 0x0046);
LCD_WRITE_REG(0xd320, 0x0003);
LCD_WRITE_REG(0xd321, 0x0069);
LCD_WRITE_REG(0xd322, 0x0003);
LCD_WRITE_REG(0xd323, 0x008f);
LCD_WRITE_REG(0xd324, 0x0003);
LCD_WRITE_REG(0xd325, 0x00a4);
LCD_WRITE_REG(0xd326, 0x0003);
LCD_WRITE_REG(0xd327, 0x00b9);
LCD_WRITE_REG(0xd328, 0x0003);
LCD_WRITE_REG(0xd329, 0x00c7);
LCD_WRITE_REG(0xd32a, 0x0003);
LCD_WRITE_REG(0xd32b, 0x00c9);
LCD_WRITE_REG(0xd32c, 0x0003);
LCD_WRITE_REG(0xd32d, 0x00cb);
LCD_WRITE_REG(0xd32e, 0x0003);
LCD_WRITE_REG(0xd32f, 0x00cb);
LCD_WRITE_REG(0xd330, 0x0003);
LCD_WRITE_REG(0xd331, 0x00cb);
LCD_WRITE_REG(0xd332, 0x0003);
LCD_WRITE_REG(0xd333, 0x00cc);
// VGML and VGSP voltages (regulator output voltage VGMP/VGSP for negative gamma divider)
LCD_WRITE_REG_16B(0xbd01, 0x0086);
LCD_WRITE_REG_16B(0xbd02, 0x006a);
LCD_WRITE_REG(0xd400, 0x0000);
LCD_WRITE_REG(0xd401, 0x005d);
LCD_WRITE_REG(0xd402, 0x0000);
LCD_WRITE_REG(0xd403, 0x006b);
LCD_WRITE_REG(0xd404, 0x0000);
LCD_WRITE_REG(0xd405, 0x0084);
LCD_WRITE_REG(0xd406, 0x0000);
LCD_WRITE_REG(0xd407, 0x009c);
LCD_WRITE_REG(0xd408, 0x0000);
LCD_WRITE_REG(0xd409, 0x00b1);
LCD_WRITE_REG(0xd40a, 0x0000);
LCD_WRITE_REG(0xd40b, 0x00d9);
LCD_WRITE_REG(0xd40c, 0x0000);
LCD_WRITE_REG(0xd40d, 0x00fd);
LCD_WRITE_REG(0xd40e, 0x0001);
LCD_WRITE_REG(0xd40f, 0x0038);
LCD_WRITE_REG(0xd410, 0x0001);
LCD_WRITE_REG(0xd411, 0x0068);
LCD_WRITE_REG(0xd412, 0x0001);
LCD_WRITE_REG(0xd413, 0x00b9);
LCD_WRITE_REG(0xd414, 0x0001);
LCD_WRITE_REG(0xd415, 0x00fb);
LCD_WRITE_REG(0xd416, 0x0002);
LCD_WRITE_REG(0xd417, 0x0063);
LCD_WRITE_REG(0xd418, 0x0002);
LCD_WRITE_REG(0xd419, 0x00b9);
LCD_WRITE_REG(0xd41a, 0x0002);
LCD_WRITE_REG(0xd41b, 0x00bb);
LCD_WRITE_REG(0xd41c, 0x0003);
LCD_WRITE_REG(0xd41d, 0x0003);
LCD_WRITE_REG(0xd41e, 0x0003);
LCD_WRITE_REG(0xd41f, 0x0046);
LCD_WRITE_REG(0xd420, 0x0003);
LCD_WRITE_REG(0xd421, 0x0069);
LCD_WRITE_REG(0xd422, 0x0003);
LCD_WRITE_REG(0xd423, 0x008f);
LCD_WRITE_REG(0xd424, 0x0003);
LCD_WRITE_REG(0xd425, 0x00a4);
LCD_WRITE_REG(0xd426, 0x0003);
LCD_WRITE_REG(0xd427, 0x00b9);
LCD_WRITE_REG(0xd428, 0x0003);
LCD_WRITE_REG(0xd429, 0x00c7);
LCD_WRITE_REG(0xd42a, 0x0003);
LCD_WRITE_REG(0xd42b, 0x00c9);
LCD_WRITE_REG(0xd42c, 0x0003);
LCD_WRITE_REG(0xd42d, 0x00cb);
LCD_WRITE_REG(0xd42e, 0x0003);
LCD_WRITE_REG(0xd42f, 0x00cb);
LCD_WRITE_REG(0xd430, 0x0003);
LCD_WRITE_REG(0xd431, 0x00cb);
LCD_WRITE_REG(0xd432, 0x0003);
LCD_WRITE_REG(0xd433, 0x00cc);
// VCOM Offset Voltage
LCD_WRITE_REG_16B(0xbe01, 0x0067);
LCD_WRITE_REG(0xd500, 0x0000);
LCD_WRITE_REG(0xd501, 0x005d);
LCD_WRITE_REG(0xd502, 0x0000);
LCD_WRITE_REG(0xd503, 0x006b);
LCD_WRITE_REG(0xd504, 0x0000);
LCD_WRITE_REG(0xd505, 0x0084);
LCD_WRITE_REG(0xd506, 0x0000);
LCD_WRITE_REG(0xd507, 0x009c);
LCD_WRITE_REG(0xd508, 0x0000);
LCD_WRITE_REG(0xd509, 0x00b1);
LCD_WRITE_REG(0xd50a, 0x0000);
LCD_WRITE_REG(0xd50b, 0x00D9);
LCD_WRITE_REG(0xd50c, 0x0000);
LCD_WRITE_REG(0xd50d, 0x00fd);
LCD_WRITE_REG(0xd50e, 0x0001);
LCD_WRITE_REG(0xd50f, 0x0038);
LCD_WRITE_REG(0xd510, 0x0001);
LCD_WRITE_REG(0xd511, 0x0068);
LCD_WRITE_REG(0xd512, 0x0001);
LCD_WRITE_REG(0xd513, 0x00b9);
LCD_WRITE_REG(0xd514, 0x0001);
LCD_WRITE_REG(0xd515, 0x00fb);
LCD_WRITE_REG(0xd516, 0x0002);
LCD_WRITE_REG(0xd517, 0x0063);
LCD_WRITE_REG(0xd518, 0x0002);
LCD_WRITE_REG(0xd519, 0x00b9);
LCD_WRITE_REG(0xd51a, 0x0002);
LCD_WRITE_REG(0xd51b, 0x00bb);
LCD_WRITE_REG(0xd51c, 0x0003);
LCD_WRITE_REG(0xd51d, 0x0003);
LCD_WRITE_REG(0xd51e, 0x0003);
LCD_WRITE_REG(0xd51f, 0x0046);
LCD_WRITE_REG(0xd520, 0x0003);
LCD_WRITE_REG(0xd521, 0x0069);
LCD_WRITE_REG(0xd522, 0x0003);
LCD_WRITE_REG(0xd523, 0x008f);
LCD_WRITE_REG(0xd524, 0x0003);
LCD_WRITE_REG(0xd525, 0x00a4);
LCD_WRITE_REG(0xd526, 0x0003);
LCD_WRITE_REG(0xd527, 0x00b9);
LCD_WRITE_REG(0xd528, 0x0003);
LCD_WRITE_REG(0xd529, 0x00c7);
LCD_WRITE_REG(0xd52a, 0x0003);
LCD_WRITE_REG(0xd52b, 0x00c9);
LCD_WRITE_REG(0xd52c, 0x0003);
LCD_WRITE_REG(0xd52d, 0x00cb);
LCD_WRITE_REG(0xd52e, 0x0003);
LCD_WRITE_REG(0xd52f, 0x00cb);
LCD_WRITE_REG(0xd530, 0x0003);
LCD_WRITE_REG(0xd531, 0x00cb);
LCD_WRITE_REG(0xd532, 0x0003);
LCD_WRITE_REG(0xd533, 0x00cc);
// Gamma 2.2 Correction for Red (Positive)
LCD_WRITE_REG_16B(0xd100, 0x0000);
LCD_WRITE_REG_16B(0xd101, 0x005d);
LCD_WRITE_REG_16B(0xd102, 0x0000);
LCD_WRITE_REG_16B(0xd103, 0x006b);
LCD_WRITE_REG_16B(0xd104, 0x0000);
LCD_WRITE_REG_16B(0xd105, 0x0084);
LCD_WRITE_REG_16B(0xd106, 0x0000);
LCD_WRITE_REG_16B(0xd107, 0x009c);
LCD_WRITE_REG_16B(0xd108, 0x0000);
LCD_WRITE_REG_16B(0xd109, 0x00b1);
LCD_WRITE_REG_16B(0xd10a, 0x0000);
LCD_WRITE_REG_16B(0xd10b, 0x00d9);
LCD_WRITE_REG_16B(0xd10c, 0x0000);
LCD_WRITE_REG_16B(0xd10d, 0x00fd);
LCD_WRITE_REG_16B(0xd10e, 0x0001);
LCD_WRITE_REG_16B(0xd10f, 0x0038);
LCD_WRITE_REG_16B(0xd110, 0x0001);
LCD_WRITE_REG_16B(0xd111, 0x0068);
LCD_WRITE_REG_16B(0xd112, 0x0001);
LCD_WRITE_REG_16B(0xd113, 0x00b9);
LCD_WRITE_REG_16B(0xd114, 0x0001);
LCD_WRITE_REG_16B(0xd115, 0x00fb);
LCD_WRITE_REG_16B(0xd116, 0x0002);
LCD_WRITE_REG_16B(0xd117, 0x0063);
LCD_WRITE_REG_16B(0xd118, 0x0002);
LCD_WRITE_REG_16B(0xd119, 0x00b9);
LCD_WRITE_REG_16B(0xd11a, 0x0002);
LCD_WRITE_REG_16B(0xd11b, 0x00bb);
LCD_WRITE_REG_16B(0xd11c, 0x0003);
LCD_WRITE_REG_16B(0xd11d, 0x0003);
LCD_WRITE_REG_16B(0xd11e, 0x0003);
LCD_WRITE_REG_16B(0xd11f, 0x0046);
LCD_WRITE_REG_16B(0xd120, 0x0003);
LCD_WRITE_REG_16B(0xd121, 0x0069);
LCD_WRITE_REG_16B(0xd122, 0x0003);
LCD_WRITE_REG_16B(0xd123, 0x008f);
LCD_WRITE_REG_16B(0xd124, 0x0003);
LCD_WRITE_REG_16B(0xd125, 0x00a4);
LCD_WRITE_REG_16B(0xd126, 0x0003);
LCD_WRITE_REG_16B(0xd127, 0x00b9);
LCD_WRITE_REG_16B(0xd128, 0x0003);
LCD_WRITE_REG_16B(0xd129, 0x00c7);
LCD_WRITE_REG_16B(0xd12a, 0x0003);
LCD_WRITE_REG_16B(0xd12b, 0x00c9);
LCD_WRITE_REG_16B(0xd12c, 0x0003);
LCD_WRITE_REG_16B(0xd12d, 0x00cb);
LCD_WRITE_REG_16B(0xd12e, 0x0003);
LCD_WRITE_REG_16B(0xd12f, 0x00cb);
LCD_WRITE_REG_16B(0xd130, 0x0003);
LCD_WRITE_REG_16B(0xd131, 0x00cb);
LCD_WRITE_REG_16B(0xd132, 0x0003);
LCD_WRITE_REG_16B(0xd133, 0x00cc);
LCD_WRITE_REG(0xd600, 0x0000);
LCD_WRITE_REG(0xd601, 0x005d);
LCD_WRITE_REG(0xd602, 0x0000);
LCD_WRITE_REG(0xd603, 0x006b);
LCD_WRITE_REG(0xd604, 0x0000);
LCD_WRITE_REG(0xd605, 0x0084);
LCD_WRITE_REG(0xd606, 0x0000);
LCD_WRITE_REG(0xd607, 0x009c);
LCD_WRITE_REG(0xd608, 0x0000);
LCD_WRITE_REG(0xd609, 0x00b1);
LCD_WRITE_REG(0xd60a, 0x0000);
LCD_WRITE_REG(0xd60b, 0x00d9);
LCD_WRITE_REG(0xd60c, 0x0000);
LCD_WRITE_REG(0xd60d, 0x00fd);
LCD_WRITE_REG(0xd60e, 0x0001);
LCD_WRITE_REG(0xd60f, 0x0038);
LCD_WRITE_REG(0xd610, 0x0001);
LCD_WRITE_REG(0xd611, 0x0068);
LCD_WRITE_REG(0xd612, 0x0001);
LCD_WRITE_REG(0xd613, 0x00b9);
LCD_WRITE_REG(0xd614, 0x0001);
LCD_WRITE_REG(0xd615, 0x00fb);
LCD_WRITE_REG(0xd616, 0x0002);
LCD_WRITE_REG(0xd617, 0x0063);
LCD_WRITE_REG(0xd618, 0x0002);
LCD_WRITE_REG(0xd619, 0x00b9);
LCD_WRITE_REG(0xd61a, 0x0002);
LCD_WRITE_REG(0xd61b, 0x00bb);
LCD_WRITE_REG(0xd61c, 0x0003);
LCD_WRITE_REG(0xd61d, 0x0003);
LCD_WRITE_REG(0xd61e, 0x0003);
LCD_WRITE_REG(0xd61f, 0x0046);
LCD_WRITE_REG(0xd620, 0x0003);
LCD_WRITE_REG(0xd621, 0x0069);
LCD_WRITE_REG(0xd622, 0x0003);
LCD_WRITE_REG(0xd623, 0x008f);
LCD_WRITE_REG(0xd624, 0x0003);
LCD_WRITE_REG(0xd625, 0x00a4);
LCD_WRITE_REG(0xd626, 0x0003);
LCD_WRITE_REG(0xd627, 0x00b9);
LCD_WRITE_REG(0xd628, 0x0003);
LCD_WRITE_REG(0xd629, 0x00c7);
LCD_WRITE_REG(0xd62a, 0x0003);
LCD_WRITE_REG(0xd62b, 0x00c9);
LCD_WRITE_REG(0xd62c, 0x0003);
LCD_WRITE_REG(0xd62d, 0x00cb);
LCD_WRITE_REG(0xd62e, 0x0003);
LCD_WRITE_REG(0xd62f, 0x00cb);
LCD_WRITE_REG(0xd630, 0x0003);
LCD_WRITE_REG(0xd631, 0x00cb);
LCD_WRITE_REG(0xd632, 0x0003);
LCD_WRITE_REG(0xd633, 0x00cc);
// Gamma 2.2 Correction for Green (Positive)
LCD_WRITE_REG_16B(0xd200, 0x0000);
LCD_WRITE_REG_16B(0xd201, 0x005d);
LCD_WRITE_REG_16B(0xd202, 0x0000);
LCD_WRITE_REG_16B(0xd203, 0x006b);
LCD_WRITE_REG_16B(0xd204, 0x0000);
LCD_WRITE_REG_16B(0xd205, 0x0084);
LCD_WRITE_REG_16B(0xd206, 0x0000);
LCD_WRITE_REG_16B(0xd207, 0x009c);
LCD_WRITE_REG_16B(0xd208, 0x0000);
LCD_WRITE_REG_16B(0xd209, 0x00b1);
LCD_WRITE_REG_16B(0xd20a, 0x0000);
LCD_WRITE_REG_16B(0xd20b, 0x00d9);
LCD_WRITE_REG_16B(0xd20c, 0x0000);
LCD_WRITE_REG_16B(0xd20d, 0x00fd);
LCD_WRITE_REG_16B(0xd20e, 0x0001);
LCD_WRITE_REG_16B(0xd20f, 0x0038);
LCD_WRITE_REG_16B(0xd210, 0x0001);
LCD_WRITE_REG_16B(0xd211, 0x0068);
LCD_WRITE_REG_16B(0xd212, 0x0001);
LCD_WRITE_REG_16B(0xd213, 0x00b9);
LCD_WRITE_REG_16B(0xd214, 0x0001);
LCD_WRITE_REG_16B(0xd215, 0x00fb);
LCD_WRITE_REG_16B(0xd216, 0x0002);
LCD_WRITE_REG_16B(0xd217, 0x0063);
LCD_WRITE_REG_16B(0xd218, 0x0002);
LCD_WRITE_REG_16B(0xd219, 0x00b9);
LCD_WRITE_REG_16B(0xd21a, 0x0002);
LCD_WRITE_REG_16B(0xd21b, 0x00bb);
LCD_WRITE_REG_16B(0xd21c, 0x0003);
LCD_WRITE_REG_16B(0xd21d, 0x0003);
LCD_WRITE_REG_16B(0xd21e, 0x0003);
LCD_WRITE_REG_16B(0xd21f, 0x0046);
LCD_WRITE_REG_16B(0xd220, 0x0003);
LCD_WRITE_REG_16B(0xd221, 0x0069);
LCD_WRITE_REG_16B(0xd222, 0x0003);
LCD_WRITE_REG_16B(0xd223, 0x008f);
LCD_WRITE_REG_16B(0xd224, 0x0003);
LCD_WRITE_REG_16B(0xd225, 0x00a4);
LCD_WRITE_REG_16B(0xd226, 0x0003);
LCD_WRITE_REG_16B(0xd227, 0x00b9);
LCD_WRITE_REG_16B(0xd228, 0x0003);
LCD_WRITE_REG_16B(0xd229, 0x00c7);
LCD_WRITE_REG_16B(0xd22a, 0x0003);
LCD_WRITE_REG_16B(0xd22b, 0x00c9);
LCD_WRITE_REG_16B(0xd22c, 0x0003);
LCD_WRITE_REG_16B(0xd22d, 0x00cb);
LCD_WRITE_REG_16B(0xd22e, 0x0003);
LCD_WRITE_REG_16B(0xd22f, 0x00cb);
LCD_WRITE_REG_16B(0xd230, 0x0003);
LCD_WRITE_REG_16B(0xd231, 0x00cb);
LCD_WRITE_REG_16B(0xd232, 0x0003);
LCD_WRITE_REG_16B(0xd233, 0x00cc);
LCD_WRITE_REG(0xba00, 0x0024);
LCD_WRITE_REG(0xba01, 0x0024);
LCD_WRITE_REG(0xba02, 0x0024);
// Gamma 2.2 Correction for Blue (Positive)
LCD_WRITE_REG_16B(0xd300, 0x0000);
LCD_WRITE_REG_16B(0xd301, 0x005d);
LCD_WRITE_REG_16B(0xd302, 0x0000);
LCD_WRITE_REG_16B(0xd303, 0x006b);
LCD_WRITE_REG_16B(0xd304, 0x0000);
LCD_WRITE_REG_16B(0xd305, 0x0084);
LCD_WRITE_REG_16B(0xd306, 0x0000);
LCD_WRITE_REG_16B(0xd307, 0x009c);
LCD_WRITE_REG_16B(0xd308, 0x0000);
LCD_WRITE_REG_16B(0xd309, 0x00b1);
LCD_WRITE_REG_16B(0xd30a, 0x0000);
LCD_WRITE_REG_16B(0xd30b, 0x00d9);
LCD_WRITE_REG_16B(0xd30c, 0x0000);
LCD_WRITE_REG_16B(0xd30d, 0x00fd);
LCD_WRITE_REG_16B(0xd30e, 0x0001);
LCD_WRITE_REG_16B(0xd30f, 0x0038);
LCD_WRITE_REG_16B(0xd310, 0x0001);
LCD_WRITE_REG_16B(0xd311, 0x0068);
LCD_WRITE_REG_16B(0xd312, 0x0001);
LCD_WRITE_REG_16B(0xd313, 0x00b9);
LCD_WRITE_REG_16B(0xd314, 0x0001);
LCD_WRITE_REG_16B(0xd315, 0x00fb);
LCD_WRITE_REG_16B(0xd316, 0x0002);
LCD_WRITE_REG_16B(0xd317, 0x0063);
LCD_WRITE_REG_16B(0xd318, 0x0002);
LCD_WRITE_REG_16B(0xd319, 0x00b9);
LCD_WRITE_REG_16B(0xd31a, 0x0002);
LCD_WRITE_REG_16B(0xd31b, 0x00bb);
LCD_WRITE_REG_16B(0xd31c, 0x0003);
LCD_WRITE_REG_16B(0xd31d, 0x0003);
LCD_WRITE_REG_16B(0xd31e, 0x0003);
LCD_WRITE_REG_16B(0xd31f, 0x0046);
LCD_WRITE_REG_16B(0xd320, 0x0003);
LCD_WRITE_REG_16B(0xd321, 0x0069);
LCD_WRITE_REG_16B(0xd322, 0x0003);
LCD_WRITE_REG_16B(0xd323, 0x008f);
LCD_WRITE_REG_16B(0xd324, 0x0003);
LCD_WRITE_REG_16B(0xd325, 0x00a4);
LCD_WRITE_REG_16B(0xd326, 0x0003);
LCD_WRITE_REG_16B(0xd327, 0x00b9);
LCD_WRITE_REG_16B(0xd328, 0x0003);
LCD_WRITE_REG_16B(0xd329, 0x00c7);
LCD_WRITE_REG_16B(0xd32a, 0x0003);
LCD_WRITE_REG_16B(0xd32b, 0x00c9);
LCD_WRITE_REG_16B(0xd32c, 0x0003);
LCD_WRITE_REG_16B(0xd32d, 0x00cb);
LCD_WRITE_REG_16B(0xd32e, 0x0003);
LCD_WRITE_REG_16B(0xd32f, 0x00cb);
LCD_WRITE_REG_16B(0xd330, 0x0003);
LCD_WRITE_REG_16B(0xd331, 0x00cb);
LCD_WRITE_REG_16B(0xd332, 0x0003);
LCD_WRITE_REG_16B(0xd333, 0x00cc);
LCD_WRITE_REG(0xb900, 0x0024);
LCD_WRITE_REG(0xb901, 0x0024);
LCD_WRITE_REG(0xb902, 0x0024);
// Gamma 2.2 Correction for Red (Negative)
LCD_WRITE_REG_16B(0xd400, 0x0000);
LCD_WRITE_REG_16B(0xd401, 0x005d);
LCD_WRITE_REG_16B(0xd402, 0x0000);
LCD_WRITE_REG_16B(0xd403, 0x006b);
LCD_WRITE_REG_16B(0xd404, 0x0000);
LCD_WRITE_REG_16B(0xd405, 0x0084);
LCD_WRITE_REG_16B(0xd406, 0x0000);
LCD_WRITE_REG_16B(0xd407, 0x009c);
LCD_WRITE_REG_16B(0xd408, 0x0000);
LCD_WRITE_REG_16B(0xd409, 0x00b1);
LCD_WRITE_REG_16B(0xd40a, 0x0000);
LCD_WRITE_REG_16B(0xd40b, 0x00d9);
LCD_WRITE_REG_16B(0xd40c, 0x0000);
LCD_WRITE_REG_16B(0xd40d, 0x00fd);
LCD_WRITE_REG_16B(0xd40e, 0x0001);
LCD_WRITE_REG_16B(0xd40f, 0x0038);
LCD_WRITE_REG_16B(0xd410, 0x0001);
LCD_WRITE_REG_16B(0xd411, 0x0068);
LCD_WRITE_REG_16B(0xd412, 0x0001);
LCD_WRITE_REG_16B(0xd413, 0x00b9);
LCD_WRITE_REG_16B(0xd414, 0x0001);
LCD_WRITE_REG_16B(0xd415, 0x00fb);
LCD_WRITE_REG_16B(0xd416, 0x0002);
LCD_WRITE_REG_16B(0xd417, 0x0063);
LCD_WRITE_REG_16B(0xd418, 0x0002);
LCD_WRITE_REG_16B(0xd419, 0x00b9);
LCD_WRITE_REG_16B(0xd41a, 0x0002);
LCD_WRITE_REG_16B(0xd41b, 0x00bb);
LCD_WRITE_REG_16B(0xd41c, 0x0003);
LCD_WRITE_REG_16B(0xd41d, 0x0003);
LCD_WRITE_REG_16B(0xd41e, 0x0003);
LCD_WRITE_REG_16B(0xd41f, 0x0046);
LCD_WRITE_REG_16B(0xd420, 0x0003);
LCD_WRITE_REG_16B(0xd421, 0x0069);
LCD_WRITE_REG_16B(0xd422, 0x0003);
LCD_WRITE_REG_16B(0xd423, 0x008f);
LCD_WRITE_REG_16B(0xd424, 0x0003);
LCD_WRITE_REG_16B(0xd425, 0x00a4);
LCD_WRITE_REG_16B(0xd426, 0x0003);
LCD_WRITE_REG_16B(0xd427, 0x00b9);
LCD_WRITE_REG_16B(0xd428, 0x0003);
LCD_WRITE_REG_16B(0xd429, 0x00c7);
LCD_WRITE_REG_16B(0xd42a, 0x0003);
LCD_WRITE_REG_16B(0xd42b, 0x00c9);
LCD_WRITE_REG_16B(0xd42c, 0x0003);
LCD_WRITE_REG_16B(0xd42d, 0x00cb);
LCD_WRITE_REG_16B(0xd42e, 0x0003);
LCD_WRITE_REG_16B(0xd42f, 0x00cb);
LCD_WRITE_REG_16B(0xd430, 0x0003);
LCD_WRITE_REG_16B(0xd431, 0x00cb);
LCD_WRITE_REG_16B(0xd432, 0x0003);
LCD_WRITE_REG_16B(0xd433, 0x00cc);
LCD_WRITE_REG(0xf000, 0x0055);
LCD_WRITE_REG(0xf001, 0x00aa);
LCD_WRITE_REG(0xf002, 0x0052);
LCD_WRITE_REG(0xf003, 0x0008);
LCD_WRITE_REG(0xf004, 0x0000);
// Gamma 2.2 Correction for Green (Negative)
LCD_WRITE_REG_16B(0xd500, 0x0000);
LCD_WRITE_REG_16B(0xd501, 0x005d);
LCD_WRITE_REG_16B(0xd502, 0x0000);
LCD_WRITE_REG_16B(0xd503, 0x006b);
LCD_WRITE_REG_16B(0xd504, 0x0000);
LCD_WRITE_REG_16B(0xd505, 0x0084);
LCD_WRITE_REG_16B(0xd506, 0x0000);
LCD_WRITE_REG_16B(0xd507, 0x009c);
LCD_WRITE_REG_16B(0xd508, 0x0000);
LCD_WRITE_REG_16B(0xd509, 0x00b1);
LCD_WRITE_REG_16B(0xd50a, 0x0000);
LCD_WRITE_REG_16B(0xd50b, 0x00D9);
LCD_WRITE_REG_16B(0xd50c, 0x0000);
LCD_WRITE_REG_16B(0xd50d, 0x00fd);
LCD_WRITE_REG_16B(0xd50e, 0x0001);
LCD_WRITE_REG_16B(0xd50f, 0x0038);
LCD_WRITE_REG_16B(0xd510, 0x0001);
LCD_WRITE_REG_16B(0xd511, 0x0068);
LCD_WRITE_REG_16B(0xd512, 0x0001);
LCD_WRITE_REG_16B(0xd513, 0x00b9);
LCD_WRITE_REG_16B(0xd514, 0x0001);
LCD_WRITE_REG_16B(0xd515, 0x00fb);
LCD_WRITE_REG_16B(0xd516, 0x0002);
LCD_WRITE_REG_16B(0xd517, 0x0063);
LCD_WRITE_REG_16B(0xd518, 0x0002);
LCD_WRITE_REG_16B(0xd519, 0x00b9);
LCD_WRITE_REG_16B(0xd51a, 0x0002);
LCD_WRITE_REG_16B(0xd51b, 0x00bb);
LCD_WRITE_REG_16B(0xd51c, 0x0003);
LCD_WRITE_REG_16B(0xd51d, 0x0003);
LCD_WRITE_REG_16B(0xd51e, 0x0003);
LCD_WRITE_REG_16B(0xd51f, 0x0046);
LCD_WRITE_REG_16B(0xd520, 0x0003);
LCD_WRITE_REG_16B(0xd521, 0x0069);
LCD_WRITE_REG_16B(0xd522, 0x0003);
LCD_WRITE_REG_16B(0xd523, 0x008f);
LCD_WRITE_REG_16B(0xd524, 0x0003);
LCD_WRITE_REG_16B(0xd525, 0x00a4);
LCD_WRITE_REG_16B(0xd526, 0x0003);
LCD_WRITE_REG_16B(0xd527, 0x00b9);
LCD_WRITE_REG_16B(0xd528, 0x0003);
LCD_WRITE_REG_16B(0xd529, 0x00c7);
LCD_WRITE_REG_16B(0xd52a, 0x0003);
LCD_WRITE_REG_16B(0xd52b, 0x00c9);
LCD_WRITE_REG_16B(0xd52c, 0x0003);
LCD_WRITE_REG_16B(0xd52d, 0x00cb);
LCD_WRITE_REG_16B(0xd52e, 0x0003);
LCD_WRITE_REG_16B(0xd52f, 0x00cb);
LCD_WRITE_REG_16B(0xd530, 0x0003);
LCD_WRITE_REG_16B(0xd531, 0x00cb);
LCD_WRITE_REG_16B(0xd532, 0x0003);
LCD_WRITE_REG_16B(0xd533, 0x00cc);
LCD_WRITE_REG(0xb100, 0x00cc);
LCD_WRITE_REG(0xB500, 0x0050);
// Gamma 2.2 Correction for Blue (Negative)
LCD_WRITE_REG_16B(0xd600, 0x0000);
LCD_WRITE_REG_16B(0xd601, 0x005d);
LCD_WRITE_REG_16B(0xd602, 0x0000);
LCD_WRITE_REG_16B(0xd603, 0x006b);
LCD_WRITE_REG_16B(0xd604, 0x0000);
LCD_WRITE_REG_16B(0xd605, 0x0084);
LCD_WRITE_REG_16B(0xd606, 0x0000);
LCD_WRITE_REG_16B(0xd607, 0x009c);
LCD_WRITE_REG_16B(0xd608, 0x0000);
LCD_WRITE_REG_16B(0xd609, 0x00b1);
LCD_WRITE_REG_16B(0xd60a, 0x0000);
LCD_WRITE_REG_16B(0xd60b, 0x00d9);
LCD_WRITE_REG_16B(0xd60c, 0x0000);
LCD_WRITE_REG_16B(0xd60d, 0x00fd);
LCD_WRITE_REG_16B(0xd60e, 0x0001);
LCD_WRITE_REG_16B(0xd60f, 0x0038);
LCD_WRITE_REG_16B(0xd610, 0x0001);
LCD_WRITE_REG_16B(0xd611, 0x0068);
LCD_WRITE_REG_16B(0xd612, 0x0001);
LCD_WRITE_REG_16B(0xd613, 0x00b9);
LCD_WRITE_REG_16B(0xd614, 0x0001);
LCD_WRITE_REG_16B(0xd615, 0x00fb);
LCD_WRITE_REG_16B(0xd616, 0x0002);
LCD_WRITE_REG_16B(0xd617, 0x0063);
LCD_WRITE_REG_16B(0xd618, 0x0002);
LCD_WRITE_REG_16B(0xd619, 0x00b9);
LCD_WRITE_REG_16B(0xd61a, 0x0002);
LCD_WRITE_REG_16B(0xd61b, 0x00bb);
LCD_WRITE_REG_16B(0xd61c, 0x0003);
LCD_WRITE_REG_16B(0xd61d, 0x0003);
LCD_WRITE_REG_16B(0xd61e, 0x0003);
LCD_WRITE_REG_16B(0xd61f, 0x0046);
LCD_WRITE_REG_16B(0xd620, 0x0003);
LCD_WRITE_REG_16B(0xd621, 0x0069);
LCD_WRITE_REG_16B(0xd622, 0x0003);
LCD_WRITE_REG_16B(0xd623, 0x008f);
LCD_WRITE_REG_16B(0xd624, 0x0003);
LCD_WRITE_REG_16B(0xd625, 0x00a4);
LCD_WRITE_REG_16B(0xd626, 0x0003);
LCD_WRITE_REG_16B(0xd627, 0x00b9);
LCD_WRITE_REG_16B(0xd628, 0x0003);
LCD_WRITE_REG_16B(0xd629, 0x00c7);
LCD_WRITE_REG_16B(0xd62a, 0x0003);
LCD_WRITE_REG_16B(0xd62b, 0x00c9);
LCD_WRITE_REG_16B(0xd62c, 0x0003);
LCD_WRITE_REG_16B(0xd62d, 0x00cb);
LCD_WRITE_REG_16B(0xd62e, 0x0003);
LCD_WRITE_REG_16B(0xd62f, 0x00cb);
LCD_WRITE_REG_16B(0xd630, 0x0003);
LCD_WRITE_REG_16B(0xd631, 0x00cb);
LCD_WRITE_REG_16B(0xd632, 0x0003);
LCD_WRITE_REG_16B(0xd633, 0x00cc);
LCD_WRITE_REG(0xbc00, 0x0005);
LCD_WRITE_REG(0xbc01, 0x0005);
LCD_WRITE_REG(0xbc02, 0x0005);
// BT5 Power Control for VGLX
LCD_WRITE_REG_16B(0xba00, 0x0024);
LCD_WRITE_REG_16B(0xba01, 0x0024);
LCD_WRITE_REG_16B(0xba02, 0x0024);
LCD_WRITE_REG(0xb800, 0x0001);
LCD_WRITE_REG(0xb801, 0x0003);
LCD_WRITE_REG(0xb802, 0x0003);
LCD_WRITE_REG(0xb803, 0x0003);
// BT4 Power Control for VGH
LCD_WRITE_REG_16B(0xb900, 0x0024);
LCD_WRITE_REG_16B(0xb901, 0x0024);
LCD_WRITE_REG_16B(0xb902, 0x0024);
LCD_WRITE_REG(0xbd02, 0x0007);
LCD_WRITE_REG(0xbd03, 0x0031);
LCD_WRITE_REG(0xbe02, 0x0007);
LCD_WRITE_REG(0xbe03, 0x0031);
LCD_WRITE_REG(0xbf02, 0x0007);
LCD_WRITE_REG(0xbf03, 0x0031);
// Enable manufacturer command set, select page 0
LCD_WRITE_REG_16B(0xf000, 0x0055);
LCD_WRITE_REG_16B(0xf001, 0x00aa);
LCD_WRITE_REG_16B(0xf002, 0x0052);
LCD_WRITE_REG_16B(0xf003, 0x0008);
LCD_WRITE_REG_16B(0xf004, 0x0000);
LCD_WRITE_REG(0xff00, 0x00aa);
LCD_WRITE_REG(0xff01, 0x0055);
LCD_WRITE_REG(0xff02, 0x0025);
LCD_WRITE_REG(0xff03, 0x0001);
// Display Option Control
LCD_WRITE_REG_16B(0xb100, 0x00cc);
LCD_WRITE_REG(0xf304, 0x0011);
LCD_WRITE_REG(0xf306, 0x0010);
LCD_WRITE_REG(0xf308, 0x0000);
// Display Resolution Control
LCD_WRITE_REG_16B(0xB500, 0x0050); // 480RGB X 800
// Inversion Driving Control
// 000: Column inversion
// 001: 1-dot inversion
// 010: 2-dot inversion
// 011: 3-dot inversion
// 100: 4-dot inversion
// 101: Zigzag inversion
LCD_WRITE_REG_16B(0xbc00, 0x0005); // Normal mode
LCD_WRITE_REG_16B(0xbc01, 0x0005); // Idle mode
LCD_WRITE_REG_16B(0xbc02, 0x0005); // Partial mode
// EQ Control Function for Source Driver
LCD_WRITE_REG_16B(0xb800, 0x0001); // EQ mode 1
LCD_WRITE_REG_16B(0xb801, 0x0003); // Normal mode, 0.5us per step = 1.5 us
LCD_WRITE_REG_16B(0xb802, 0x0003); // Idle mode, 0.5us per step = 1.5 us
LCD_WRITE_REG_16B(0xb803, 0x0003); // Partial mode, 0.5us per step = 1.5 us
// Display Timing Control
LCD_WRITE_REG_16B(0xbd02, 0x0007); // Normal mode
LCD_WRITE_REG_16B(0xbd03, 0x0031); // Normal mode
LCD_WRITE_REG_16B(0xbe02, 0x0007); // Idle mode
LCD_WRITE_REG_16B(0xbe03, 0x0031); // Idle mode
LCD_WRITE_REG_16B(0xbf02, 0x0007); // Parial mode
LCD_WRITE_REG_16B(0xbf03, 0x0031); // Parial mode
// Undocumented registers
LCD_WRITE_REG_16B(0xff00, 0x00aa);
LCD_WRITE_REG_16B(0xff01, 0x0055);
LCD_WRITE_REG_16B(0xff02, 0x0025);
LCD_WRITE_REG_16B(0xff03, 0x0001);
// Undocumented registers
LCD_WRITE_REG_16B(0xf304, 0x0011);
LCD_WRITE_REG_16B(0xf306, 0x0010);
LCD_WRITE_REG_16B(0xf308, 0x0000);
// Tearing effect line on
LCD_WRITE_REG_16B(0x3500, 0x0000); // Only v-blanking information
// Interface Pixel Format
LCD_WRITE_REG_16B(0x3A00, 0x0005); // I80 16-bit per pixel
// Display On
LCD_WRITE_CMD_16B(0x2900);
LCD_WRITE_REG(0x3500, 0x0000);
LCD_WRITE_REG(0x3A00, 0x0005);
//Display On
LCD_WRITE_CMD(0x2900);
// Out sleep
LCD_WRITE_CMD(0x1100);
LCD_WRITE_CMD_16B(0x1100);
// Write continue
LCD_WRITE_CMD(0x2C00);
LCD_WRITE_CMD_16B(0x2C00);
}

View file

@ -77,7 +77,7 @@ esp_err_t lcd_rm68120_init(const scr_controller_config_t *lcd_conf)
LCD_CHECK(lcd_conf->width <= RM68120_RESOLUTION_HOR, "Width greater than maximum", ESP_ERR_INVALID_ARG);
LCD_CHECK(lcd_conf->height <= RM68120_RESOLUTION_VER, "Height greater than maximum", ESP_ERR_INVALID_ARG);
LCD_CHECK(NULL != lcd_conf, "config pointer invalid", ESP_ERR_INVALID_ARG);
LCD_CHECK((NULL != lcd_conf->interface_drv->write_cmd && \
LCD_CHECK((NULL != lcd_conf->interface_drv->write_command && \
NULL != lcd_conf->interface_drv->write_data && \
NULL != lcd_conf->interface_drv->write && \
NULL != lcd_conf->interface_drv->read && \
@ -176,7 +176,7 @@ esp_err_t lcd_rm68120_set_rotation(scr_dir_t dir)
default: break;
}
ESP_LOGI(TAG, "MADCTL=0x%x", reg_data);
ret = LCD_WRITE_REG(RM68120_MADCTL, reg_data);
ret = LCD_WRITE_REG_16B(RM68120_MADCTL, reg_data);
LCD_CHECK(ESP_OK == ret, "Set screen rotate failed", ESP_FAIL);
g_lcd_handle.dir = dir;
return ESP_OK;
@ -201,16 +201,16 @@ esp_err_t lcd_rm68120_set_window(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t
esp_err_t ret = ESP_OK;
scr_utility_apply_offset(&g_lcd_handle, RM68120_RESOLUTION_HOR, RM68120_RESOLUTION_VER, &x0, &y0, &x1, &y1);
ret |= LCD_WRITE_REG(RM68120_CASET, x0 >> 8);
ret |= LCD_WRITE_REG(RM68120_CASET + 1, x0 & 0xff);
ret |= LCD_WRITE_REG(RM68120_CASET + 2, x1 >> 8);
ret |= LCD_WRITE_REG(RM68120_CASET + 3, x1 & 0xff);
ret |= LCD_WRITE_REG(RM68120_RASET, y0 >> 8);
ret |= LCD_WRITE_REG(RM68120_RASET + 1, y0 & 0xff);
ret |= LCD_WRITE_REG(RM68120_RASET + 2, y1 >> 8);
ret |= LCD_WRITE_REG(RM68120_RASET + 3, y1 & 0xff);
ret |= LCD_WRITE_REG_16B(RM68120_CASET, x0 >> 8);
ret |= LCD_WRITE_REG_16B(RM68120_CASET + 1, x0 & 0xff);
ret |= LCD_WRITE_REG_16B(RM68120_CASET + 2, x1 >> 8);
ret |= LCD_WRITE_REG_16B(RM68120_CASET + 3, x1 & 0xff);
ret |= LCD_WRITE_REG_16B(RM68120_RASET, y0 >> 8);
ret |= LCD_WRITE_REG_16B(RM68120_RASET + 1, y0 & 0xff);
ret |= LCD_WRITE_REG_16B(RM68120_RASET + 2, y1 >> 8);
ret |= LCD_WRITE_REG_16B(RM68120_RASET + 3, y1 & 0xff);
ret |= LCD_WRITE_CMD(RM68120_RAMWR);
ret |= LCD_WRITE_CMD_16B(RM68120_RAMWR);
LCD_CHECK(ESP_OK == ret, "Set window failed", ESP_FAIL);
return ESP_OK;
}
@ -253,434 +253,434 @@ esp_err_t lcd_rm68120_draw_bitmap(uint16_t x, uint16_t y, uint16_t w, uint16_t h
static void lcd_rm68120_init_reg(void)
{
LCD_WRITE_CMD(0x0100); // Software Reset
LCD_WRITE_CMD_16B(0x0100); // Software Reset
vTaskDelay(10 / portTICK_RATE_MS);
LCD_WRITE_REG(0xF000, 0x55);
LCD_WRITE_REG(0xF001, 0xAA);
LCD_WRITE_REG(0xF002, 0x52);
LCD_WRITE_REG(0xF003, 0x08);
LCD_WRITE_REG(0xF004, 0x01);
LCD_WRITE_REG_16B(0xF000, 0x55);
LCD_WRITE_REG_16B(0xF001, 0xAA);
LCD_WRITE_REG_16B(0xF002, 0x52);
LCD_WRITE_REG_16B(0xF003, 0x08);
LCD_WRITE_REG_16B(0xF004, 0x01);
//GAMMA SETING RED
LCD_WRITE_REG(0xD100, 0x00);
LCD_WRITE_REG(0xD101, 0x00);
LCD_WRITE_REG(0xD102, 0x1b);
LCD_WRITE_REG(0xD103, 0x44);
LCD_WRITE_REG(0xD104, 0x62);
LCD_WRITE_REG(0xD105, 0x00);
LCD_WRITE_REG(0xD106, 0x7b);
LCD_WRITE_REG(0xD107, 0xa1);
LCD_WRITE_REG(0xD108, 0xc0);
LCD_WRITE_REG(0xD109, 0xee);
LCD_WRITE_REG(0xD10A, 0x55);
LCD_WRITE_REG(0xD10B, 0x10);
LCD_WRITE_REG(0xD10C, 0x2c);
LCD_WRITE_REG(0xD10D, 0x43);
LCD_WRITE_REG(0xD10E, 0x57);
LCD_WRITE_REG(0xD10F, 0x55);
LCD_WRITE_REG(0xD110, 0x68);
LCD_WRITE_REG(0xD111, 0x78);
LCD_WRITE_REG(0xD112, 0x87);
LCD_WRITE_REG(0xD113, 0x94);
LCD_WRITE_REG(0xD114, 0x55);
LCD_WRITE_REG(0xD115, 0xa0);
LCD_WRITE_REG(0xD116, 0xac);
LCD_WRITE_REG(0xD117, 0xb6);
LCD_WRITE_REG(0xD118, 0xc1);
LCD_WRITE_REG(0xD119, 0x55);
LCD_WRITE_REG(0xD11A, 0xcb);
LCD_WRITE_REG(0xD11B, 0xcd);
LCD_WRITE_REG(0xD11C, 0xd6);
LCD_WRITE_REG(0xD11D, 0xdf);
LCD_WRITE_REG(0xD11E, 0x95);
LCD_WRITE_REG(0xD11F, 0xe8);
LCD_WRITE_REG(0xD120, 0xf1);
LCD_WRITE_REG(0xD121, 0xfa);
LCD_WRITE_REG(0xD122, 0x02);
LCD_WRITE_REG(0xD123, 0xaa);
LCD_WRITE_REG(0xD124, 0x0b);
LCD_WRITE_REG(0xD125, 0x13);
LCD_WRITE_REG(0xD126, 0x1d);
LCD_WRITE_REG(0xD127, 0x26);
LCD_WRITE_REG(0xD128, 0xaa);
LCD_WRITE_REG(0xD129, 0x30);
LCD_WRITE_REG(0xD12A, 0x3c);
LCD_WRITE_REG(0xD12B, 0x4A);
LCD_WRITE_REG(0xD12C, 0x63);
LCD_WRITE_REG(0xD12D, 0xea);
LCD_WRITE_REG(0xD12E, 0x79);
LCD_WRITE_REG(0xD12F, 0xa6);
LCD_WRITE_REG(0xD130, 0xd0);
LCD_WRITE_REG(0xD131, 0x20);
LCD_WRITE_REG(0xD132, 0x0f);
LCD_WRITE_REG(0xD133, 0x8e);
LCD_WRITE_REG(0xD134, 0xff);
LCD_WRITE_REG_16B(0xD100, 0x00);
LCD_WRITE_REG_16B(0xD101, 0x00);
LCD_WRITE_REG_16B(0xD102, 0x1b);
LCD_WRITE_REG_16B(0xD103, 0x44);
LCD_WRITE_REG_16B(0xD104, 0x62);
LCD_WRITE_REG_16B(0xD105, 0x00);
LCD_WRITE_REG_16B(0xD106, 0x7b);
LCD_WRITE_REG_16B(0xD107, 0xa1);
LCD_WRITE_REG_16B(0xD108, 0xc0);
LCD_WRITE_REG_16B(0xD109, 0xee);
LCD_WRITE_REG_16B(0xD10A, 0x55);
LCD_WRITE_REG_16B(0xD10B, 0x10);
LCD_WRITE_REG_16B(0xD10C, 0x2c);
LCD_WRITE_REG_16B(0xD10D, 0x43);
LCD_WRITE_REG_16B(0xD10E, 0x57);
LCD_WRITE_REG_16B(0xD10F, 0x55);
LCD_WRITE_REG_16B(0xD110, 0x68);
LCD_WRITE_REG_16B(0xD111, 0x78);
LCD_WRITE_REG_16B(0xD112, 0x87);
LCD_WRITE_REG_16B(0xD113, 0x94);
LCD_WRITE_REG_16B(0xD114, 0x55);
LCD_WRITE_REG_16B(0xD115, 0xa0);
LCD_WRITE_REG_16B(0xD116, 0xac);
LCD_WRITE_REG_16B(0xD117, 0xb6);
LCD_WRITE_REG_16B(0xD118, 0xc1);
LCD_WRITE_REG_16B(0xD119, 0x55);
LCD_WRITE_REG_16B(0xD11A, 0xcb);
LCD_WRITE_REG_16B(0xD11B, 0xcd);
LCD_WRITE_REG_16B(0xD11C, 0xd6);
LCD_WRITE_REG_16B(0xD11D, 0xdf);
LCD_WRITE_REG_16B(0xD11E, 0x95);
LCD_WRITE_REG_16B(0xD11F, 0xe8);
LCD_WRITE_REG_16B(0xD120, 0xf1);
LCD_WRITE_REG_16B(0xD121, 0xfa);
LCD_WRITE_REG_16B(0xD122, 0x02);
LCD_WRITE_REG_16B(0xD123, 0xaa);
LCD_WRITE_REG_16B(0xD124, 0x0b);
LCD_WRITE_REG_16B(0xD125, 0x13);
LCD_WRITE_REG_16B(0xD126, 0x1d);
LCD_WRITE_REG_16B(0xD127, 0x26);
LCD_WRITE_REG_16B(0xD128, 0xaa);
LCD_WRITE_REG_16B(0xD129, 0x30);
LCD_WRITE_REG_16B(0xD12A, 0x3c);
LCD_WRITE_REG_16B(0xD12B, 0x4A);
LCD_WRITE_REG_16B(0xD12C, 0x63);
LCD_WRITE_REG_16B(0xD12D, 0xea);
LCD_WRITE_REG_16B(0xD12E, 0x79);
LCD_WRITE_REG_16B(0xD12F, 0xa6);
LCD_WRITE_REG_16B(0xD130, 0xd0);
LCD_WRITE_REG_16B(0xD131, 0x20);
LCD_WRITE_REG_16B(0xD132, 0x0f);
LCD_WRITE_REG_16B(0xD133, 0x8e);
LCD_WRITE_REG_16B(0xD134, 0xff);
//GAMMA SETING GREEN
LCD_WRITE_REG(0xD200, 0x00);
LCD_WRITE_REG(0xD201, 0x00);
LCD_WRITE_REG(0xD202, 0x1b);
LCD_WRITE_REG(0xD203, 0x44);
LCD_WRITE_REG(0xD204, 0x62);
LCD_WRITE_REG(0xD205, 0x00);
LCD_WRITE_REG(0xD206, 0x7b);
LCD_WRITE_REG(0xD207, 0xa1);
LCD_WRITE_REG(0xD208, 0xc0);
LCD_WRITE_REG(0xD209, 0xee);
LCD_WRITE_REG(0xD20A, 0x55);
LCD_WRITE_REG(0xD20B, 0x10);
LCD_WRITE_REG(0xD20C, 0x2c);
LCD_WRITE_REG(0xD20D, 0x43);
LCD_WRITE_REG(0xD20E, 0x57);
LCD_WRITE_REG(0xD20F, 0x55);
LCD_WRITE_REG(0xD210, 0x68);
LCD_WRITE_REG(0xD211, 0x78);
LCD_WRITE_REG(0xD212, 0x87);
LCD_WRITE_REG(0xD213, 0x94);
LCD_WRITE_REG(0xD214, 0x55);
LCD_WRITE_REG(0xD215, 0xa0);
LCD_WRITE_REG(0xD216, 0xac);
LCD_WRITE_REG(0xD217, 0xb6);
LCD_WRITE_REG(0xD218, 0xc1);
LCD_WRITE_REG(0xD219, 0x55);
LCD_WRITE_REG(0xD21A, 0xcb);
LCD_WRITE_REG(0xD21B, 0xcd);
LCD_WRITE_REG(0xD21C, 0xd6);
LCD_WRITE_REG(0xD21D, 0xdf);
LCD_WRITE_REG(0xD21E, 0x95);
LCD_WRITE_REG(0xD21F, 0xe8);
LCD_WRITE_REG(0xD220, 0xf1);
LCD_WRITE_REG(0xD221, 0xfa);
LCD_WRITE_REG(0xD222, 0x02);
LCD_WRITE_REG(0xD223, 0xaa);
LCD_WRITE_REG(0xD224, 0x0b);
LCD_WRITE_REG(0xD225, 0x13);
LCD_WRITE_REG(0xD226, 0x1d);
LCD_WRITE_REG(0xD227, 0x26);
LCD_WRITE_REG(0xD228, 0xaa);
LCD_WRITE_REG(0xD229, 0x30);
LCD_WRITE_REG(0xD22A, 0x3c);
LCD_WRITE_REG(0xD22B, 0x4a);
LCD_WRITE_REG(0xD22C, 0x63);
LCD_WRITE_REG(0xD22D, 0xea);
LCD_WRITE_REG(0xD22E, 0x79);
LCD_WRITE_REG(0xD22F, 0xa6);
LCD_WRITE_REG(0xD230, 0xd0);
LCD_WRITE_REG(0xD231, 0x20);
LCD_WRITE_REG(0xD232, 0x0f);
LCD_WRITE_REG(0xD233, 0x8e);
LCD_WRITE_REG(0xD234, 0xff);
LCD_WRITE_REG_16B(0xD200, 0x00);
LCD_WRITE_REG_16B(0xD201, 0x00);
LCD_WRITE_REG_16B(0xD202, 0x1b);
LCD_WRITE_REG_16B(0xD203, 0x44);
LCD_WRITE_REG_16B(0xD204, 0x62);
LCD_WRITE_REG_16B(0xD205, 0x00);
LCD_WRITE_REG_16B(0xD206, 0x7b);
LCD_WRITE_REG_16B(0xD207, 0xa1);
LCD_WRITE_REG_16B(0xD208, 0xc0);
LCD_WRITE_REG_16B(0xD209, 0xee);
LCD_WRITE_REG_16B(0xD20A, 0x55);
LCD_WRITE_REG_16B(0xD20B, 0x10);
LCD_WRITE_REG_16B(0xD20C, 0x2c);
LCD_WRITE_REG_16B(0xD20D, 0x43);
LCD_WRITE_REG_16B(0xD20E, 0x57);
LCD_WRITE_REG_16B(0xD20F, 0x55);
LCD_WRITE_REG_16B(0xD210, 0x68);
LCD_WRITE_REG_16B(0xD211, 0x78);
LCD_WRITE_REG_16B(0xD212, 0x87);
LCD_WRITE_REG_16B(0xD213, 0x94);
LCD_WRITE_REG_16B(0xD214, 0x55);
LCD_WRITE_REG_16B(0xD215, 0xa0);
LCD_WRITE_REG_16B(0xD216, 0xac);
LCD_WRITE_REG_16B(0xD217, 0xb6);
LCD_WRITE_REG_16B(0xD218, 0xc1);
LCD_WRITE_REG_16B(0xD219, 0x55);
LCD_WRITE_REG_16B(0xD21A, 0xcb);
LCD_WRITE_REG_16B(0xD21B, 0xcd);
LCD_WRITE_REG_16B(0xD21C, 0xd6);
LCD_WRITE_REG_16B(0xD21D, 0xdf);
LCD_WRITE_REG_16B(0xD21E, 0x95);
LCD_WRITE_REG_16B(0xD21F, 0xe8);
LCD_WRITE_REG_16B(0xD220, 0xf1);
LCD_WRITE_REG_16B(0xD221, 0xfa);
LCD_WRITE_REG_16B(0xD222, 0x02);
LCD_WRITE_REG_16B(0xD223, 0xaa);
LCD_WRITE_REG_16B(0xD224, 0x0b);
LCD_WRITE_REG_16B(0xD225, 0x13);
LCD_WRITE_REG_16B(0xD226, 0x1d);
LCD_WRITE_REG_16B(0xD227, 0x26);
LCD_WRITE_REG_16B(0xD228, 0xaa);
LCD_WRITE_REG_16B(0xD229, 0x30);
LCD_WRITE_REG_16B(0xD22A, 0x3c);
LCD_WRITE_REG_16B(0xD22B, 0x4a);
LCD_WRITE_REG_16B(0xD22C, 0x63);
LCD_WRITE_REG_16B(0xD22D, 0xea);
LCD_WRITE_REG_16B(0xD22E, 0x79);
LCD_WRITE_REG_16B(0xD22F, 0xa6);
LCD_WRITE_REG_16B(0xD230, 0xd0);
LCD_WRITE_REG_16B(0xD231, 0x20);
LCD_WRITE_REG_16B(0xD232, 0x0f);
LCD_WRITE_REG_16B(0xD233, 0x8e);
LCD_WRITE_REG_16B(0xD234, 0xff);
//GAMMA SETING BLUE
LCD_WRITE_REG(0xD300, 0x00);
LCD_WRITE_REG(0xD301, 0x00);
LCD_WRITE_REG(0xD302, 0x1b);
LCD_WRITE_REG(0xD303, 0x44);
LCD_WRITE_REG(0xD304, 0x62);
LCD_WRITE_REG(0xD305, 0x00);
LCD_WRITE_REG(0xD306, 0x7b);
LCD_WRITE_REG(0xD307, 0xa1);
LCD_WRITE_REG(0xD308, 0xc0);
LCD_WRITE_REG(0xD309, 0xee);
LCD_WRITE_REG(0xD30A, 0x55);
LCD_WRITE_REG(0xD30B, 0x10);
LCD_WRITE_REG(0xD30C, 0x2c);
LCD_WRITE_REG(0xD30D, 0x43);
LCD_WRITE_REG(0xD30E, 0x57);
LCD_WRITE_REG(0xD30F, 0x55);
LCD_WRITE_REG(0xD310, 0x68);
LCD_WRITE_REG(0xD311, 0x78);
LCD_WRITE_REG(0xD312, 0x87);
LCD_WRITE_REG(0xD313, 0x94);
LCD_WRITE_REG(0xD314, 0x55);
LCD_WRITE_REG(0xD315, 0xa0);
LCD_WRITE_REG(0xD316, 0xac);
LCD_WRITE_REG(0xD317, 0xb6);
LCD_WRITE_REG(0xD318, 0xc1);
LCD_WRITE_REG(0xD319, 0x55);
LCD_WRITE_REG(0xD31A, 0xcb);
LCD_WRITE_REG(0xD31B, 0xcd);
LCD_WRITE_REG(0xD31C, 0xd6);
LCD_WRITE_REG(0xD31D, 0xdf);
LCD_WRITE_REG(0xD31E, 0x95);
LCD_WRITE_REG(0xD31F, 0xe8);
LCD_WRITE_REG(0xD320, 0xf1);
LCD_WRITE_REG(0xD321, 0xfa);
LCD_WRITE_REG(0xD322, 0x02);
LCD_WRITE_REG(0xD323, 0xaa);
LCD_WRITE_REG(0xD324, 0x0b);
LCD_WRITE_REG(0xD325, 0x13);
LCD_WRITE_REG(0xD326, 0x1d);
LCD_WRITE_REG(0xD327, 0x26);
LCD_WRITE_REG(0xD328, 0xaa);
LCD_WRITE_REG(0xD329, 0x30);
LCD_WRITE_REG(0xD32A, 0x3c);
LCD_WRITE_REG(0xD32B, 0x4A);
LCD_WRITE_REG(0xD32C, 0x63);
LCD_WRITE_REG(0xD32D, 0xea);
LCD_WRITE_REG(0xD32E, 0x79);
LCD_WRITE_REG(0xD32F, 0xa6);
LCD_WRITE_REG(0xD330, 0xd0);
LCD_WRITE_REG(0xD331, 0x20);
LCD_WRITE_REG(0xD332, 0x0f);
LCD_WRITE_REG(0xD333, 0x8e);
LCD_WRITE_REG(0xD334, 0xff);
LCD_WRITE_REG_16B(0xD300, 0x00);
LCD_WRITE_REG_16B(0xD301, 0x00);
LCD_WRITE_REG_16B(0xD302, 0x1b);
LCD_WRITE_REG_16B(0xD303, 0x44);
LCD_WRITE_REG_16B(0xD304, 0x62);
LCD_WRITE_REG_16B(0xD305, 0x00);
LCD_WRITE_REG_16B(0xD306, 0x7b);
LCD_WRITE_REG_16B(0xD307, 0xa1);
LCD_WRITE_REG_16B(0xD308, 0xc0);
LCD_WRITE_REG_16B(0xD309, 0xee);
LCD_WRITE_REG_16B(0xD30A, 0x55);
LCD_WRITE_REG_16B(0xD30B, 0x10);
LCD_WRITE_REG_16B(0xD30C, 0x2c);
LCD_WRITE_REG_16B(0xD30D, 0x43);
LCD_WRITE_REG_16B(0xD30E, 0x57);
LCD_WRITE_REG_16B(0xD30F, 0x55);
LCD_WRITE_REG_16B(0xD310, 0x68);
LCD_WRITE_REG_16B(0xD311, 0x78);
LCD_WRITE_REG_16B(0xD312, 0x87);
LCD_WRITE_REG_16B(0xD313, 0x94);
LCD_WRITE_REG_16B(0xD314, 0x55);
LCD_WRITE_REG_16B(0xD315, 0xa0);
LCD_WRITE_REG_16B(0xD316, 0xac);
LCD_WRITE_REG_16B(0xD317, 0xb6);
LCD_WRITE_REG_16B(0xD318, 0xc1);
LCD_WRITE_REG_16B(0xD319, 0x55);
LCD_WRITE_REG_16B(0xD31A, 0xcb);
LCD_WRITE_REG_16B(0xD31B, 0xcd);
LCD_WRITE_REG_16B(0xD31C, 0xd6);
LCD_WRITE_REG_16B(0xD31D, 0xdf);
LCD_WRITE_REG_16B(0xD31E, 0x95);
LCD_WRITE_REG_16B(0xD31F, 0xe8);
LCD_WRITE_REG_16B(0xD320, 0xf1);
LCD_WRITE_REG_16B(0xD321, 0xfa);
LCD_WRITE_REG_16B(0xD322, 0x02);
LCD_WRITE_REG_16B(0xD323, 0xaa);
LCD_WRITE_REG_16B(0xD324, 0x0b);
LCD_WRITE_REG_16B(0xD325, 0x13);
LCD_WRITE_REG_16B(0xD326, 0x1d);
LCD_WRITE_REG_16B(0xD327, 0x26);
LCD_WRITE_REG_16B(0xD328, 0xaa);
LCD_WRITE_REG_16B(0xD329, 0x30);
LCD_WRITE_REG_16B(0xD32A, 0x3c);
LCD_WRITE_REG_16B(0xD32B, 0x4A);
LCD_WRITE_REG_16B(0xD32C, 0x63);
LCD_WRITE_REG_16B(0xD32D, 0xea);
LCD_WRITE_REG_16B(0xD32E, 0x79);
LCD_WRITE_REG_16B(0xD32F, 0xa6);
LCD_WRITE_REG_16B(0xD330, 0xd0);
LCD_WRITE_REG_16B(0xD331, 0x20);
LCD_WRITE_REG_16B(0xD332, 0x0f);
LCD_WRITE_REG_16B(0xD333, 0x8e);
LCD_WRITE_REG_16B(0xD334, 0xff);
//GAMMA SETING RED
LCD_WRITE_REG(0xD400, 0x00);
LCD_WRITE_REG(0xD401, 0x00);
LCD_WRITE_REG(0xD402, 0x1b);
LCD_WRITE_REG(0xD403, 0x44);
LCD_WRITE_REG(0xD404, 0x62);
LCD_WRITE_REG(0xD405, 0x00);
LCD_WRITE_REG(0xD406, 0x7b);
LCD_WRITE_REG(0xD407, 0xa1);
LCD_WRITE_REG(0xD408, 0xc0);
LCD_WRITE_REG(0xD409, 0xee);
LCD_WRITE_REG(0xD40A, 0x55);
LCD_WRITE_REG(0xD40B, 0x10);
LCD_WRITE_REG(0xD40C, 0x2c);
LCD_WRITE_REG(0xD40D, 0x43);
LCD_WRITE_REG(0xD40E, 0x57);
LCD_WRITE_REG(0xD40F, 0x55);
LCD_WRITE_REG(0xD410, 0x68);
LCD_WRITE_REG(0xD411, 0x78);
LCD_WRITE_REG(0xD412, 0x87);
LCD_WRITE_REG(0xD413, 0x94);
LCD_WRITE_REG(0xD414, 0x55);
LCD_WRITE_REG(0xD415, 0xa0);
LCD_WRITE_REG(0xD416, 0xac);
LCD_WRITE_REG(0xD417, 0xb6);
LCD_WRITE_REG(0xD418, 0xc1);
LCD_WRITE_REG(0xD419, 0x55);
LCD_WRITE_REG(0xD41A, 0xcb);
LCD_WRITE_REG(0xD41B, 0xcd);
LCD_WRITE_REG(0xD41C, 0xd6);
LCD_WRITE_REG(0xD41D, 0xdf);
LCD_WRITE_REG(0xD41E, 0x95);
LCD_WRITE_REG(0xD41F, 0xe8);
LCD_WRITE_REG(0xD420, 0xf1);
LCD_WRITE_REG(0xD421, 0xfa);
LCD_WRITE_REG(0xD422, 0x02);
LCD_WRITE_REG(0xD423, 0xaa);
LCD_WRITE_REG(0xD424, 0x0b);
LCD_WRITE_REG(0xD425, 0x13);
LCD_WRITE_REG(0xD426, 0x1d);
LCD_WRITE_REG(0xD427, 0x26);
LCD_WRITE_REG(0xD428, 0xaa);
LCD_WRITE_REG(0xD429, 0x30);
LCD_WRITE_REG(0xD42A, 0x3c);
LCD_WRITE_REG(0xD42B, 0x4A);
LCD_WRITE_REG(0xD42C, 0x63);
LCD_WRITE_REG(0xD42D, 0xea);
LCD_WRITE_REG(0xD42E, 0x79);
LCD_WRITE_REG(0xD42F, 0xa6);
LCD_WRITE_REG(0xD430, 0xd0);
LCD_WRITE_REG(0xD431, 0x20);
LCD_WRITE_REG(0xD432, 0x0f);
LCD_WRITE_REG(0xD433, 0x8e);
LCD_WRITE_REG(0xD434, 0xff);
LCD_WRITE_REG_16B(0xD400, 0x00);
LCD_WRITE_REG_16B(0xD401, 0x00);
LCD_WRITE_REG_16B(0xD402, 0x1b);
LCD_WRITE_REG_16B(0xD403, 0x44);
LCD_WRITE_REG_16B(0xD404, 0x62);
LCD_WRITE_REG_16B(0xD405, 0x00);
LCD_WRITE_REG_16B(0xD406, 0x7b);
LCD_WRITE_REG_16B(0xD407, 0xa1);
LCD_WRITE_REG_16B(0xD408, 0xc0);
LCD_WRITE_REG_16B(0xD409, 0xee);
LCD_WRITE_REG_16B(0xD40A, 0x55);
LCD_WRITE_REG_16B(0xD40B, 0x10);
LCD_WRITE_REG_16B(0xD40C, 0x2c);
LCD_WRITE_REG_16B(0xD40D, 0x43);
LCD_WRITE_REG_16B(0xD40E, 0x57);
LCD_WRITE_REG_16B(0xD40F, 0x55);
LCD_WRITE_REG_16B(0xD410, 0x68);
LCD_WRITE_REG_16B(0xD411, 0x78);
LCD_WRITE_REG_16B(0xD412, 0x87);
LCD_WRITE_REG_16B(0xD413, 0x94);
LCD_WRITE_REG_16B(0xD414, 0x55);
LCD_WRITE_REG_16B(0xD415, 0xa0);
LCD_WRITE_REG_16B(0xD416, 0xac);
LCD_WRITE_REG_16B(0xD417, 0xb6);
LCD_WRITE_REG_16B(0xD418, 0xc1);
LCD_WRITE_REG_16B(0xD419, 0x55);
LCD_WRITE_REG_16B(0xD41A, 0xcb);
LCD_WRITE_REG_16B(0xD41B, 0xcd);
LCD_WRITE_REG_16B(0xD41C, 0xd6);
LCD_WRITE_REG_16B(0xD41D, 0xdf);
LCD_WRITE_REG_16B(0xD41E, 0x95);
LCD_WRITE_REG_16B(0xD41F, 0xe8);
LCD_WRITE_REG_16B(0xD420, 0xf1);
LCD_WRITE_REG_16B(0xD421, 0xfa);
LCD_WRITE_REG_16B(0xD422, 0x02);
LCD_WRITE_REG_16B(0xD423, 0xaa);
LCD_WRITE_REG_16B(0xD424, 0x0b);
LCD_WRITE_REG_16B(0xD425, 0x13);
LCD_WRITE_REG_16B(0xD426, 0x1d);
LCD_WRITE_REG_16B(0xD427, 0x26);
LCD_WRITE_REG_16B(0xD428, 0xaa);
LCD_WRITE_REG_16B(0xD429, 0x30);
LCD_WRITE_REG_16B(0xD42A, 0x3c);
LCD_WRITE_REG_16B(0xD42B, 0x4A);
LCD_WRITE_REG_16B(0xD42C, 0x63);
LCD_WRITE_REG_16B(0xD42D, 0xea);
LCD_WRITE_REG_16B(0xD42E, 0x79);
LCD_WRITE_REG_16B(0xD42F, 0xa6);
LCD_WRITE_REG_16B(0xD430, 0xd0);
LCD_WRITE_REG_16B(0xD431, 0x20);
LCD_WRITE_REG_16B(0xD432, 0x0f);
LCD_WRITE_REG_16B(0xD433, 0x8e);
LCD_WRITE_REG_16B(0xD434, 0xff);
//GAMMA SETING GREEN
LCD_WRITE_REG(0xD500, 0x00);
LCD_WRITE_REG(0xD501, 0x00);
LCD_WRITE_REG(0xD502, 0x1b);
LCD_WRITE_REG(0xD503, 0x44);
LCD_WRITE_REG(0xD504, 0x62);
LCD_WRITE_REG(0xD505, 0x00);
LCD_WRITE_REG(0xD506, 0x7b);
LCD_WRITE_REG(0xD507, 0xa1);
LCD_WRITE_REG(0xD508, 0xc0);
LCD_WRITE_REG(0xD509, 0xee);
LCD_WRITE_REG(0xD50A, 0x55);
LCD_WRITE_REG(0xD50B, 0x10);
LCD_WRITE_REG(0xD50C, 0x2c);
LCD_WRITE_REG(0xD50D, 0x43);
LCD_WRITE_REG(0xD50E, 0x57);
LCD_WRITE_REG(0xD50F, 0x55);
LCD_WRITE_REG(0xD510, 0x68);
LCD_WRITE_REG(0xD511, 0x78);
LCD_WRITE_REG(0xD512, 0x87);
LCD_WRITE_REG(0xD513, 0x94);
LCD_WRITE_REG(0xD514, 0x55);
LCD_WRITE_REG(0xD515, 0xa0);
LCD_WRITE_REG(0xD516, 0xac);
LCD_WRITE_REG(0xD517, 0xb6);
LCD_WRITE_REG(0xD518, 0xc1);
LCD_WRITE_REG(0xD519, 0x55);
LCD_WRITE_REG(0xD51A, 0xcb);
LCD_WRITE_REG(0xD51B, 0xcd);
LCD_WRITE_REG(0xD51C, 0xd6);
LCD_WRITE_REG(0xD51D, 0xdf);
LCD_WRITE_REG(0xD51E, 0x95);
LCD_WRITE_REG(0xD51F, 0xe8);
LCD_WRITE_REG(0xD520, 0xf1);
LCD_WRITE_REG(0xD521, 0xfa);
LCD_WRITE_REG(0xD522, 0x02);
LCD_WRITE_REG(0xD523, 0xaa);
LCD_WRITE_REG(0xD524, 0x0b);
LCD_WRITE_REG(0xD525, 0x13);
LCD_WRITE_REG(0xD526, 0x1d);
LCD_WRITE_REG(0xD527, 0x26);
LCD_WRITE_REG(0xD528, 0xaa);
LCD_WRITE_REG(0xD529, 0x30);
LCD_WRITE_REG(0xD52A, 0x3c);
LCD_WRITE_REG(0xD52B, 0x4a);
LCD_WRITE_REG(0xD52C, 0x63);
LCD_WRITE_REG(0xD52D, 0xea);
LCD_WRITE_REG(0xD52E, 0x79);
LCD_WRITE_REG(0xD52F, 0xa6);
LCD_WRITE_REG(0xD530, 0xd0);
LCD_WRITE_REG(0xD531, 0x20);
LCD_WRITE_REG(0xD532, 0x0f);
LCD_WRITE_REG(0xD533, 0x8e);
LCD_WRITE_REG(0xD534, 0xff);
LCD_WRITE_REG_16B(0xD500, 0x00);
LCD_WRITE_REG_16B(0xD501, 0x00);
LCD_WRITE_REG_16B(0xD502, 0x1b);
LCD_WRITE_REG_16B(0xD503, 0x44);
LCD_WRITE_REG_16B(0xD504, 0x62);
LCD_WRITE_REG_16B(0xD505, 0x00);
LCD_WRITE_REG_16B(0xD506, 0x7b);
LCD_WRITE_REG_16B(0xD507, 0xa1);
LCD_WRITE_REG_16B(0xD508, 0xc0);
LCD_WRITE_REG_16B(0xD509, 0xee);
LCD_WRITE_REG_16B(0xD50A, 0x55);
LCD_WRITE_REG_16B(0xD50B, 0x10);
LCD_WRITE_REG_16B(0xD50C, 0x2c);
LCD_WRITE_REG_16B(0xD50D, 0x43);
LCD_WRITE_REG_16B(0xD50E, 0x57);
LCD_WRITE_REG_16B(0xD50F, 0x55);
LCD_WRITE_REG_16B(0xD510, 0x68);
LCD_WRITE_REG_16B(0xD511, 0x78);
LCD_WRITE_REG_16B(0xD512, 0x87);
LCD_WRITE_REG_16B(0xD513, 0x94);
LCD_WRITE_REG_16B(0xD514, 0x55);
LCD_WRITE_REG_16B(0xD515, 0xa0);
LCD_WRITE_REG_16B(0xD516, 0xac);
LCD_WRITE_REG_16B(0xD517, 0xb6);
LCD_WRITE_REG_16B(0xD518, 0xc1);
LCD_WRITE_REG_16B(0xD519, 0x55);
LCD_WRITE_REG_16B(0xD51A, 0xcb);
LCD_WRITE_REG_16B(0xD51B, 0xcd);
LCD_WRITE_REG_16B(0xD51C, 0xd6);
LCD_WRITE_REG_16B(0xD51D, 0xdf);
LCD_WRITE_REG_16B(0xD51E, 0x95);
LCD_WRITE_REG_16B(0xD51F, 0xe8);
LCD_WRITE_REG_16B(0xD520, 0xf1);
LCD_WRITE_REG_16B(0xD521, 0xfa);
LCD_WRITE_REG_16B(0xD522, 0x02);
LCD_WRITE_REG_16B(0xD523, 0xaa);
LCD_WRITE_REG_16B(0xD524, 0x0b);
LCD_WRITE_REG_16B(0xD525, 0x13);
LCD_WRITE_REG_16B(0xD526, 0x1d);
LCD_WRITE_REG_16B(0xD527, 0x26);
LCD_WRITE_REG_16B(0xD528, 0xaa);
LCD_WRITE_REG_16B(0xD529, 0x30);
LCD_WRITE_REG_16B(0xD52A, 0x3c);
LCD_WRITE_REG_16B(0xD52B, 0x4a);
LCD_WRITE_REG_16B(0xD52C, 0x63);
LCD_WRITE_REG_16B(0xD52D, 0xea);
LCD_WRITE_REG_16B(0xD52E, 0x79);
LCD_WRITE_REG_16B(0xD52F, 0xa6);
LCD_WRITE_REG_16B(0xD530, 0xd0);
LCD_WRITE_REG_16B(0xD531, 0x20);
LCD_WRITE_REG_16B(0xD532, 0x0f);
LCD_WRITE_REG_16B(0xD533, 0x8e);
LCD_WRITE_REG_16B(0xD534, 0xff);
//GAMMA SETING BLUE
LCD_WRITE_REG(0xD600, 0x00);
LCD_WRITE_REG(0xD601, 0x00);
LCD_WRITE_REG(0xD602, 0x1b);
LCD_WRITE_REG(0xD603, 0x44);
LCD_WRITE_REG(0xD604, 0x62);
LCD_WRITE_REG(0xD605, 0x00);
LCD_WRITE_REG(0xD606, 0x7b);
LCD_WRITE_REG(0xD607, 0xa1);
LCD_WRITE_REG(0xD608, 0xc0);
LCD_WRITE_REG(0xD609, 0xee);
LCD_WRITE_REG(0xD60A, 0x55);
LCD_WRITE_REG(0xD60B, 0x10);
LCD_WRITE_REG(0xD60C, 0x2c);
LCD_WRITE_REG(0xD60D, 0x43);
LCD_WRITE_REG(0xD60E, 0x57);
LCD_WRITE_REG(0xD60F, 0x55);
LCD_WRITE_REG(0xD610, 0x68);
LCD_WRITE_REG(0xD611, 0x78);
LCD_WRITE_REG(0xD612, 0x87);
LCD_WRITE_REG(0xD613, 0x94);
LCD_WRITE_REG(0xD614, 0x55);
LCD_WRITE_REG(0xD615, 0xa0);
LCD_WRITE_REG(0xD616, 0xac);
LCD_WRITE_REG(0xD617, 0xb6);
LCD_WRITE_REG(0xD618, 0xc1);
LCD_WRITE_REG(0xD619, 0x55);
LCD_WRITE_REG(0xD61A, 0xcb);
LCD_WRITE_REG(0xD61B, 0xcd);
LCD_WRITE_REG(0xD61C, 0xd6);
LCD_WRITE_REG(0xD61D, 0xdf);
LCD_WRITE_REG(0xD61E, 0x95);
LCD_WRITE_REG(0xD61F, 0xe8);
LCD_WRITE_REG(0xD620, 0xf1);
LCD_WRITE_REG(0xD621, 0xfa);
LCD_WRITE_REG(0xD622, 0x02);
LCD_WRITE_REG(0xD623, 0xaa);
LCD_WRITE_REG(0xD624, 0x0b);
LCD_WRITE_REG(0xD625, 0x13);
LCD_WRITE_REG(0xD626, 0x1d);
LCD_WRITE_REG(0xD627, 0x26);
LCD_WRITE_REG(0xD628, 0xaa);
LCD_WRITE_REG(0xD629, 0x30);
LCD_WRITE_REG(0xD62A, 0x3c);
LCD_WRITE_REG(0xD62B, 0x4A);
LCD_WRITE_REG(0xD62C, 0x63);
LCD_WRITE_REG(0xD62D, 0xea);
LCD_WRITE_REG(0xD62E, 0x79);
LCD_WRITE_REG(0xD62F, 0xa6);
LCD_WRITE_REG(0xD630, 0xd0);
LCD_WRITE_REG(0xD631, 0x20);
LCD_WRITE_REG(0xD632, 0x0f);
LCD_WRITE_REG(0xD633, 0x8e);
LCD_WRITE_REG(0xD634, 0xff);
LCD_WRITE_REG_16B(0xD600, 0x00);
LCD_WRITE_REG_16B(0xD601, 0x00);
LCD_WRITE_REG_16B(0xD602, 0x1b);
LCD_WRITE_REG_16B(0xD603, 0x44);
LCD_WRITE_REG_16B(0xD604, 0x62);
LCD_WRITE_REG_16B(0xD605, 0x00);
LCD_WRITE_REG_16B(0xD606, 0x7b);
LCD_WRITE_REG_16B(0xD607, 0xa1);
LCD_WRITE_REG_16B(0xD608, 0xc0);
LCD_WRITE_REG_16B(0xD609, 0xee);
LCD_WRITE_REG_16B(0xD60A, 0x55);
LCD_WRITE_REG_16B(0xD60B, 0x10);
LCD_WRITE_REG_16B(0xD60C, 0x2c);
LCD_WRITE_REG_16B(0xD60D, 0x43);
LCD_WRITE_REG_16B(0xD60E, 0x57);
LCD_WRITE_REG_16B(0xD60F, 0x55);
LCD_WRITE_REG_16B(0xD610, 0x68);
LCD_WRITE_REG_16B(0xD611, 0x78);
LCD_WRITE_REG_16B(0xD612, 0x87);
LCD_WRITE_REG_16B(0xD613, 0x94);
LCD_WRITE_REG_16B(0xD614, 0x55);
LCD_WRITE_REG_16B(0xD615, 0xa0);
LCD_WRITE_REG_16B(0xD616, 0xac);
LCD_WRITE_REG_16B(0xD617, 0xb6);
LCD_WRITE_REG_16B(0xD618, 0xc1);
LCD_WRITE_REG_16B(0xD619, 0x55);
LCD_WRITE_REG_16B(0xD61A, 0xcb);
LCD_WRITE_REG_16B(0xD61B, 0xcd);
LCD_WRITE_REG_16B(0xD61C, 0xd6);
LCD_WRITE_REG_16B(0xD61D, 0xdf);
LCD_WRITE_REG_16B(0xD61E, 0x95);
LCD_WRITE_REG_16B(0xD61F, 0xe8);
LCD_WRITE_REG_16B(0xD620, 0xf1);
LCD_WRITE_REG_16B(0xD621, 0xfa);
LCD_WRITE_REG_16B(0xD622, 0x02);
LCD_WRITE_REG_16B(0xD623, 0xaa);
LCD_WRITE_REG_16B(0xD624, 0x0b);
LCD_WRITE_REG_16B(0xD625, 0x13);
LCD_WRITE_REG_16B(0xD626, 0x1d);
LCD_WRITE_REG_16B(0xD627, 0x26);
LCD_WRITE_REG_16B(0xD628, 0xaa);
LCD_WRITE_REG_16B(0xD629, 0x30);
LCD_WRITE_REG_16B(0xD62A, 0x3c);
LCD_WRITE_REG_16B(0xD62B, 0x4A);
LCD_WRITE_REG_16B(0xD62C, 0x63);
LCD_WRITE_REG_16B(0xD62D, 0xea);
LCD_WRITE_REG_16B(0xD62E, 0x79);
LCD_WRITE_REG_16B(0xD62F, 0xa6);
LCD_WRITE_REG_16B(0xD630, 0xd0);
LCD_WRITE_REG_16B(0xD631, 0x20);
LCD_WRITE_REG_16B(0xD632, 0x0f);
LCD_WRITE_REG_16B(0xD633, 0x8e);
LCD_WRITE_REG_16B(0xD634, 0xff);
//AVDD VOLTAGE SETTING
LCD_WRITE_REG(0xB000, 0x05);
LCD_WRITE_REG(0xB001, 0x05);
LCD_WRITE_REG(0xB002, 0x05);
LCD_WRITE_REG_16B(0xB000, 0x05);
LCD_WRITE_REG_16B(0xB001, 0x05);
LCD_WRITE_REG_16B(0xB002, 0x05);
//AVEE VOLTAGE SETTING
LCD_WRITE_REG(0xB100, 0x05);
LCD_WRITE_REG(0xB101, 0x05);
LCD_WRITE_REG(0xB102, 0x05);
LCD_WRITE_REG_16B(0xB100, 0x05);
LCD_WRITE_REG_16B(0xB101, 0x05);
LCD_WRITE_REG_16B(0xB102, 0x05);
//AVDD Boosting
LCD_WRITE_REG(0xB600, 0x34);
LCD_WRITE_REG(0xB601, 0x34);
LCD_WRITE_REG(0xB603, 0x34);
LCD_WRITE_REG_16B(0xB600, 0x34);
LCD_WRITE_REG_16B(0xB601, 0x34);
LCD_WRITE_REG_16B(0xB603, 0x34);
//AVEE Boosting
LCD_WRITE_REG(0xB700, 0x24);
LCD_WRITE_REG(0xB701, 0x24);
LCD_WRITE_REG(0xB702, 0x24);
LCD_WRITE_REG_16B(0xB700, 0x24);
LCD_WRITE_REG_16B(0xB701, 0x24);
LCD_WRITE_REG_16B(0xB702, 0x24);
//VCL Boosting
LCD_WRITE_REG(0xB800, 0x24);
LCD_WRITE_REG(0xB801, 0x24);
LCD_WRITE_REG(0xB802, 0x24);
LCD_WRITE_REG_16B(0xB800, 0x24);
LCD_WRITE_REG_16B(0xB801, 0x24);
LCD_WRITE_REG_16B(0xB802, 0x24);
//VGLX VOLTAGE SETTING
LCD_WRITE_REG(0xBA00, 0x14);
LCD_WRITE_REG(0xBA01, 0x14);
LCD_WRITE_REG(0xBA02, 0x14);
LCD_WRITE_REG_16B(0xBA00, 0x14);
LCD_WRITE_REG_16B(0xBA01, 0x14);
LCD_WRITE_REG_16B(0xBA02, 0x14);
//VCL Boosting
LCD_WRITE_REG(0xB900, 0x24);
LCD_WRITE_REG(0xB901, 0x24);
LCD_WRITE_REG(0xB902, 0x24);
LCD_WRITE_REG_16B(0xB900, 0x24);
LCD_WRITE_REG_16B(0xB901, 0x24);
LCD_WRITE_REG_16B(0xB902, 0x24);
//Gamma Voltage
LCD_WRITE_REG(0xBc00, 0x00);
LCD_WRITE_REG(0xBc01, 0xa0);//vgmp=5.0
LCD_WRITE_REG(0xBc02, 0x00);
LCD_WRITE_REG(0xBd00, 0x00);
LCD_WRITE_REG(0xBd01, 0xa0);//vgmn=5.0
LCD_WRITE_REG(0xBd02, 0x00);
LCD_WRITE_REG_16B(0xBc00, 0x00);
LCD_WRITE_REG_16B(0xBc01, 0xa0);//vgmp=5.0
LCD_WRITE_REG_16B(0xBc02, 0x00);
LCD_WRITE_REG_16B(0xBd00, 0x00);
LCD_WRITE_REG_16B(0xBd01, 0xa0);//vgmn=5.0
LCD_WRITE_REG_16B(0xBd02, 0x00);
//VCOM Setting
LCD_WRITE_REG(0xBe01, 0x3d);//3
LCD_WRITE_REG_16B(0xBe01, 0x3d);//3
//ENABLE PAGE 0
LCD_WRITE_REG(0xF000, 0x55);
LCD_WRITE_REG(0xF001, 0xAA);
LCD_WRITE_REG(0xF002, 0x52);
LCD_WRITE_REG(0xF003, 0x08);
LCD_WRITE_REG(0xF004, 0x00);
LCD_WRITE_REG_16B(0xF000, 0x55);
LCD_WRITE_REG_16B(0xF001, 0xAA);
LCD_WRITE_REG_16B(0xF002, 0x52);
LCD_WRITE_REG_16B(0xF003, 0x08);
LCD_WRITE_REG_16B(0xF004, 0x00);
//Vivid Color Function Control
LCD_WRITE_REG(0xB400, 0x10);
LCD_WRITE_REG_16B(0xB400, 0x10);
//Z-INVERSION
LCD_WRITE_REG(0xBC00, 0x05);
LCD_WRITE_REG(0xBC01, 0x05);
LCD_WRITE_REG(0xBC02, 0x05);
LCD_WRITE_REG_16B(0xBC00, 0x05);
LCD_WRITE_REG_16B(0xBC01, 0x05);
LCD_WRITE_REG_16B(0xBC02, 0x05);
//*************** add on 20111021**********************//
LCD_WRITE_REG(0xB700, 0x22);//GATE EQ CONTROL
LCD_WRITE_REG(0xB701, 0x22);//GATE EQ CONTROL
LCD_WRITE_REG(0xC80B, 0x2A);//DISPLAY TIMING CONTROL
LCD_WRITE_REG(0xC80C, 0x2A);//DISPLAY TIMING CONTROL
LCD_WRITE_REG(0xC80F, 0x2A);//DISPLAY TIMING CONTROL
LCD_WRITE_REG(0xC810, 0x2A);//DISPLAY TIMING CONTROL
LCD_WRITE_REG_16B(0xB700, 0x22);//GATE EQ CONTROL
LCD_WRITE_REG_16B(0xB701, 0x22);//GATE EQ CONTROL
LCD_WRITE_REG_16B(0xC80B, 0x2A);//DISPLAY TIMING CONTROL
LCD_WRITE_REG_16B(0xC80C, 0x2A);//DISPLAY TIMING CONTROL
LCD_WRITE_REG_16B(0xC80F, 0x2A);//DISPLAY TIMING CONTROL
LCD_WRITE_REG_16B(0xC810, 0x2A);//DISPLAY TIMING CONTROL
//*************** add on 20111021**********************//
//PWM_ENH_OE =1
LCD_WRITE_REG(0xd000, 0x01);
LCD_WRITE_REG_16B(0xd000, 0x01);
//DM_SEL =1
LCD_WRITE_REG(0xb300, 0x10);
LCD_WRITE_REG_16B(0xb300, 0x10);
//VBPDA=07h
LCD_WRITE_REG(0xBd02, 0x07);
LCD_WRITE_REG_16B(0xBd02, 0x07);
//VBPDb=07h
LCD_WRITE_REG(0xBe02, 0x07);
LCD_WRITE_REG_16B(0xBe02, 0x07);
//VBPDc=07h
LCD_WRITE_REG(0xBf02, 0x07);
LCD_WRITE_REG_16B(0xBf02, 0x07);
//ENABLE PAGE 2
LCD_WRITE_REG(0xF000, 0x55);
LCD_WRITE_REG(0xF001, 0xAA);
LCD_WRITE_REG(0xF002, 0x52);
LCD_WRITE_REG(0xF003, 0x08);
LCD_WRITE_REG(0xF004, 0x02);
LCD_WRITE_REG_16B(0xF000, 0x55);
LCD_WRITE_REG_16B(0xF001, 0xAA);
LCD_WRITE_REG_16B(0xF002, 0x52);
LCD_WRITE_REG_16B(0xF003, 0x08);
LCD_WRITE_REG_16B(0xF004, 0x02);
//SDREG0 =0
LCD_WRITE_REG(0xc301, 0xa9);
LCD_WRITE_REG_16B(0xc301, 0xa9);
//DS=14
LCD_WRITE_REG(0xfe01, 0x94);
LCD_WRITE_REG_16B(0xfe01, 0x94);
//OSC =60h
LCD_WRITE_REG(0xf600, 0x60);
LCD_WRITE_REG_16B(0xf600, 0x60);
//TE ON
LCD_WRITE_REG(0x3500, 0x00);
LCD_WRITE_REG_16B(0x3500, 0x00);
//SLEEP OUT
LCD_WRITE_CMD(0x1100);
LCD_WRITE_CMD_16B(0x1100);
vTaskDelay(100 / portTICK_RATE_MS);
//DISPLY ON
LCD_WRITE_CMD(0x2900);
LCD_WRITE_CMD_16B(0x2900);
vTaskDelay(100 / portTICK_RATE_MS);
LCD_WRITE_REG(0x3A00, 0x55);
LCD_WRITE_REG(0x3600, 0xA3);
LCD_WRITE_REG_16B(0x3A00, 0x55);
LCD_WRITE_REG_16B(0x3600, 0xA3);
}

View file

@ -95,7 +95,7 @@ esp_err_t lcd_ssd1351_init(const scr_controller_config_t *lcd_conf)
LCD_CHECK(lcd_conf->width <= SSD1351_RESOLUTION_HOR, "Width greater than maximum", ESP_ERR_INVALID_ARG);
LCD_CHECK(lcd_conf->height <= SSD1351_RESOLUTION_VER, "Height greater than maximum", ESP_ERR_INVALID_ARG);
LCD_CHECK(NULL != lcd_conf, "config pointer invalid", ESP_ERR_INVALID_ARG);
LCD_CHECK((NULL != lcd_conf->interface_drv->write_cmd && \
LCD_CHECK((NULL != lcd_conf->interface_drv->write_command && \
NULL != lcd_conf->interface_drv->write_data && \
NULL != lcd_conf->interface_drv->write && \
NULL != lcd_conf->interface_drv->read && \

View file

@ -0,0 +1,345 @@
// Copyright 2020 Espressif Systems (Shanghai) Co. Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "driver/gpio.h"
#include "screen_driver.h"
#include "screen_utility.h"
#include "ssd1963.h"
static const char *TAG = "lcd ssd1963";
#define LCD_CHECK(a, str, ret) if(!(a)) { \
ESP_LOGE(TAG,"%s:%d (%s):%s", __FILE__, __LINE__, __FUNCTION__, str); \
return (ret); \
}
#define LCD_NAME "SSD1963"
#define LCD_BPP 16
#define SSD1963_CASET 0x2A
#define SSD1963_RASET 0x2B
#define SSD1963_RAMWR 0x2C
#define SSD1963_MADCTL 0x36
/* MADCTL Defines */
#define MADCTL_MY 0x01
#define MADCTL_MX 0x02
#define MADCTL_MV 0x20
#define MADCTL_ML 0x10
#define MADCTL_RGB 0x08
#define MADCTL_MH 0x04
#define SSD1963_RESOLUTION_HOR 800
#define SSD1963_RESOLUTION_VER 480
//LCD panel configuration
#define SSD_HOR_PULSE_WIDTH 1
#define SSD_HOR_BACK_PORCH 46
#define SSD_HOR_FRONT_PORCH 210
#define SSD_VER_PULSE_WIDTH 1
#define SSD_VER_BACK_PORCH 23
#define SSD_VER_FRONT_PORCH 22
#define SSD_HT (SSD1963_RESOLUTION_HOR+SSD_HOR_BACK_PORCH+SSD_HOR_FRONT_PORCH)
#define SSD_HPS (SSD_HOR_BACK_PORCH)
#define SSD_VT (SSD1963_RESOLUTION_VER+SSD_VER_BACK_PORCH+SSD_VER_FRONT_PORCH)
#define SSD_VPS (SSD_VER_BACK_PORCH)
static scr_handle_t g_lcd_handle;
/**
* This header file is only used to redefine the function to facilitate the call.
* It can only be placed in this position, not in the head of the file.
*/
#include "interface_drv_def.h"
scr_driver_t lcd_ssd1963_default_driver = {
.init = lcd_ssd1963_init,
.deinit = lcd_ssd1963_deinit,
.set_direction = lcd_ssd1963_set_rotation,
.set_window = lcd_ssd1963_set_window,
.write_ram_data = lcd_ssd1963_write_ram_data,
.draw_pixel = lcd_ssd1963_draw_pixel,
.draw_bitmap = lcd_ssd1963_draw_bitmap,
.get_info = lcd_ssd1963_get_info,
};
static void lcd_ssd1963_init_reg(void);
esp_err_t lcd_ssd1963_init(const scr_controller_config_t *lcd_conf)
{
LCD_CHECK(lcd_conf->width <= SSD1963_RESOLUTION_HOR, "Width greater than maximum", ESP_ERR_INVALID_ARG);
LCD_CHECK(lcd_conf->height <= SSD1963_RESOLUTION_VER, "Height greater than maximum", ESP_ERR_INVALID_ARG);
LCD_CHECK(NULL != lcd_conf, "config pointer invalid", ESP_ERR_INVALID_ARG);
LCD_CHECK((NULL != lcd_conf->interface_drv->write_command && \
NULL != lcd_conf->interface_drv->write_data && \
NULL != lcd_conf->interface_drv->write && \
NULL != lcd_conf->interface_drv->read && \
NULL != lcd_conf->interface_drv->bus_acquire && \
NULL != lcd_conf->interface_drv->bus_release),
"Interface driver invalid", ESP_ERR_INVALID_ARG);
esp_err_t ret;
// Reset the display
if (lcd_conf->pin_num_rst >= 0) {
gpio_pad_select_gpio(lcd_conf->pin_num_rst);
gpio_set_direction(lcd_conf->pin_num_rst, GPIO_MODE_OUTPUT);
gpio_set_level(lcd_conf->pin_num_rst, (lcd_conf->rst_active_level) & 0x1);
vTaskDelay(100 / portTICK_RATE_MS);
gpio_set_level(lcd_conf->pin_num_rst, (~(lcd_conf->rst_active_level)) & 0x1);
vTaskDelay(100 / portTICK_RATE_MS);
}
g_lcd_handle.interface_drv = lcd_conf->interface_drv;
g_lcd_handle.original_width = lcd_conf->width;
g_lcd_handle.original_height = lcd_conf->height;
g_lcd_handle.offset_hor = lcd_conf->offset_hor;
g_lcd_handle.offset_ver = lcd_conf->offset_ver;
lcd_ssd1963_init_reg();
// Enable backlight
if (lcd_conf->pin_num_bckl >= 0) {
gpio_pad_select_gpio(lcd_conf->pin_num_bckl);
gpio_set_direction(lcd_conf->pin_num_bckl, GPIO_MODE_OUTPUT);
gpio_set_level(lcd_conf->pin_num_bckl, (lcd_conf->bckl_active_level) & 0x1);
}
ret = lcd_ssd1963_set_rotation(lcd_conf->rotate);
LCD_CHECK(ESP_OK == ret, "set rotation failed", ESP_FAIL);
return ESP_OK;
}
esp_err_t lcd_ssd1963_deinit(void)
{
memset(&g_lcd_handle, 0, sizeof(scr_handle_t));
return ESP_OK;
}
esp_err_t lcd_ssd1963_set_rotation(scr_dir_t dir)
{
esp_err_t ret;
uint8_t reg_data = 0;
reg_data &= ~MADCTL_RGB;
if (SCR_DIR_MAX < dir) {
dir >>= 5;
}
LCD_CHECK(dir < 8, "Unsupport rotate direction", ESP_ERR_INVALID_ARG);
switch (dir) {
case SCR_DIR_LRTB:
g_lcd_handle.width = g_lcd_handle.original_width;
g_lcd_handle.height = g_lcd_handle.original_height;
break;
case SCR_DIR_LRBT:
reg_data |= MADCTL_MY;
g_lcd_handle.width = g_lcd_handle.original_width;
g_lcd_handle.height = g_lcd_handle.original_height;
break;
case SCR_DIR_RLTB:
reg_data |= MADCTL_MX;
g_lcd_handle.width = g_lcd_handle.original_width;
g_lcd_handle.height = g_lcd_handle.original_height;
break;
case SCR_DIR_RLBT:
reg_data |= MADCTL_MX | MADCTL_MY;
g_lcd_handle.width = g_lcd_handle.original_width;
g_lcd_handle.height = g_lcd_handle.original_height;
break;
case SCR_DIR_TBLR:
reg_data |= MADCTL_MV;
g_lcd_handle.width = g_lcd_handle.original_height;
g_lcd_handle.height = g_lcd_handle.original_width;
break;
case SCR_DIR_BTLR:
reg_data |= MADCTL_MY | MADCTL_MV;
g_lcd_handle.width = g_lcd_handle.original_height;
g_lcd_handle.height = g_lcd_handle.original_width;
break;
case SCR_DIR_TBRL:
reg_data |= MADCTL_MX | MADCTL_MV;
g_lcd_handle.width = g_lcd_handle.original_height;
g_lcd_handle.height = g_lcd_handle.original_width;
break;
case SCR_DIR_BTRL:
reg_data |= MADCTL_MX | MADCTL_MY | MADCTL_MV;
g_lcd_handle.width = g_lcd_handle.original_height;
g_lcd_handle.height = g_lcd_handle.original_width;
break;
default: break;
}
ESP_LOGI(TAG, "MADCTL=0x%x", reg_data);
ret = LCD_WRITE_REG(SSD1963_MADCTL, reg_data);
LCD_CHECK(ESP_OK == ret, "Set screen rotate failed", ESP_FAIL);
g_lcd_handle.dir = dir;
return ESP_OK;
}
esp_err_t lcd_ssd1963_get_info(scr_info_t *info)
{
LCD_CHECK(NULL != info, "info pointer invalid", ESP_ERR_INVALID_ARG);
info->width = g_lcd_handle.width;
info->height = g_lcd_handle.height;
info->dir = g_lcd_handle.dir;
info->name = LCD_NAME;
info->color_type = SCR_COLOR_TYPE_RGB565;
info->bpp = LCD_BPP;
return ESP_OK;
}
esp_err_t lcd_ssd1963_set_window(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1)
{
LCD_CHECK((x1 < g_lcd_handle.width) && (y1 < g_lcd_handle.height), "The set coordinates exceed the screen size", ESP_ERR_INVALID_ARG);
LCD_CHECK((x0 <= x1) && (y0 <= y1), "Window coordinates invalid", ESP_ERR_INVALID_ARG);
esp_err_t ret = ESP_OK;
scr_utility_apply_offset(&g_lcd_handle, SSD1963_RESOLUTION_HOR, SSD1963_RESOLUTION_VER, &x0, &y0, &x1, &y1);
LCD_WRITE_CMD(SSD1963_CASET);
LCD_WRITE_DATA(x0 >> 8);
LCD_WRITE_DATA(x0 & 0XFF);
LCD_WRITE_DATA(x1 >> 8);
LCD_WRITE_DATA(x1 & 0XFF);
LCD_WRITE_CMD(SSD1963_RASET);
LCD_WRITE_DATA(y0 >> 8);
LCD_WRITE_DATA(y0 & 0XFF);
LCD_WRITE_DATA(y1 >> 8);
LCD_WRITE_DATA(y1 & 0XFF);
ret |= LCD_WRITE_CMD(SSD1963_RAMWR);
LCD_CHECK(ESP_OK == ret, "Set window failed", ESP_FAIL);
return ESP_OK;
}
esp_err_t lcd_ssd1963_write_ram_data(uint16_t color)
{
static uint8_t data[2];
data[0] = (uint8_t)(color & 0xff);
data[1] = (uint8_t)(color >> 8);
return LCD_WRITE(data, 2);
}
esp_err_t lcd_ssd1963_draw_pixel(uint16_t x, uint16_t y, uint16_t color)
{
esp_err_t ret;
ret = lcd_ssd1963_set_window(x, y, x, y);
if (ESP_OK != ret) {
return ESP_FAIL;
}
return lcd_ssd1963_write_ram_data(color);
}
esp_err_t lcd_ssd1963_draw_bitmap(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t *bitmap)
{
LCD_CHECK((x + w <= g_lcd_handle.width) && (y + h <= g_lcd_handle.height), "The set coordinates exceed the screen size", ESP_ERR_INVALID_ARG);
esp_err_t ret = ESP_OK;
uint8_t *p = (uint8_t *)bitmap;
LCD_IFACE_ACQUIRE();
ret = lcd_ssd1963_set_window(x, y, x + w - 1, y + h - 1);
if (ESP_OK != ret) {
return ESP_FAIL;
}
ret = LCD_WRITE(p, w * LCD_BPP / 8 * h);
LCD_IFACE_RELEASE();
LCD_CHECK(ESP_OK == ret, "Draw bitmap failed", ESP_FAIL);
return ESP_OK;
}
static void lcd_ssd1963_init_reg(void)
{
LCD_WRITE_CMD(0xE2); //Set PLL with OSC = 10MHz (hardware), Multiplier N = 35, 250MHz < VCO < 800MHz = OSC*(N+1), VCO = 300MHz
LCD_WRITE_DATA(0x1D); //
LCD_WRITE_DATA(0x02); //Divider M = 2, PLL = 300/(M+1) = 100MHz
LCD_WRITE_DATA(0x04); //Validate M and N values
vTaskDelay(pdMS_TO_TICKS(1));
LCD_WRITE_CMD(0xE0); // Start PLL command
LCD_WRITE_DATA(0x01); // enable PLL
vTaskDelay(pdMS_TO_TICKS(10));
LCD_WRITE_CMD(0xE0); // Start PLL command again
LCD_WRITE_DATA(0x03); // now, use PLL output as system clock
vTaskDelay(pdMS_TO_TICKS(12));
LCD_WRITE_CMD(0x01); //soft-reset
vTaskDelay(pdMS_TO_TICKS(10));
LCD_WRITE_CMD(0xE6); //set pixel frequency,33Mhz
LCD_WRITE_DATA(0x2F);
LCD_WRITE_DATA(0xFF);
LCD_WRITE_DATA(0xFF);
LCD_WRITE_CMD(0xB0); //set LCD mode
LCD_WRITE_DATA(0x20); //24-bit mode
LCD_WRITE_DATA(0x00); //TFT
LCD_WRITE_DATA((SSD1963_RESOLUTION_HOR - 1) >> 8); //set LCD horizontal pixel number
LCD_WRITE_DATA((SSD1963_RESOLUTION_HOR - 1) & 0xff);
LCD_WRITE_DATA((SSD1963_RESOLUTION_VER - 1) >> 8); //set LCD vertical pixel number
LCD_WRITE_DATA((SSD1963_RESOLUTION_VER - 1) & 0xff);
LCD_WRITE_DATA(0x00); //RGB
LCD_WRITE_CMD(0xB4); //Set horizontal period
LCD_WRITE_DATA((SSD_HT - 1) >> 8);
LCD_WRITE_DATA((SSD_HT - 1) & 0xff);
LCD_WRITE_DATA(SSD_HPS >> 8);
LCD_WRITE_DATA((SSD_HPS) & 0xff);
LCD_WRITE_DATA(SSD_HOR_PULSE_WIDTH - 1);
LCD_WRITE_DATA(0x00);
LCD_WRITE_DATA(0x00);
LCD_WRITE_DATA(0x00);
LCD_WRITE_CMD(0xB6); //Set vertical period
LCD_WRITE_DATA((SSD_VT - 1) >> 8);
LCD_WRITE_DATA((SSD_VT - 1) & 0xff);
LCD_WRITE_DATA(SSD_VPS >> 8);
LCD_WRITE_DATA((SSD_VPS) & 0xff);
LCD_WRITE_DATA(SSD_VER_FRONT_PORCH - 1);
LCD_WRITE_DATA(0x00);
LCD_WRITE_DATA(0x00);
LCD_WRITE_CMD(0xF0); //set SSD1963 interface is 16bit
LCD_WRITE_DATA(0x03); //16-bit(565 format) data for 16bpp
LCD_WRITE_CMD(0x29); //display on
LCD_WRITE_CMD(0xD0);
LCD_WRITE_DATA(0x00); //disable
LCD_WRITE_CMD(0xBE); //configuration PWM output
LCD_WRITE_DATA(0x05); //1 PWM frequency
LCD_WRITE_DATA(0xFE); //2 PWM duty
LCD_WRITE_DATA(0x01); //3 C
LCD_WRITE_DATA(0x00); //4 D
LCD_WRITE_DATA(0x00); //5 E
LCD_WRITE_DATA(0x00); //6 F
LCD_WRITE_CMD(0xB8); //set GPIO
LCD_WRITE_DATA(0x03);
LCD_WRITE_DATA(0x01);
LCD_WRITE_CMD(0xBA);
LCD_WRITE_DATA(0X01); //GPIO[1:0]=01
}

View file

@ -0,0 +1,123 @@
// Copyright 2020 Espressif Systems (Shanghai) Co. Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef __LCD_SSD1963_H__
#define __LCD_SSD1963_H__
#include "screen_driver.h"
#ifdef __cplusplus
extern "C"
{
#endif
/**
* @brief device initialization
*
* @param lcd_conf configuration struct of ssd1963
*
* @return
* - ESP_OK Success
* - ESP_FAIL Fail
*/
esp_err_t lcd_ssd1963_init(const scr_controller_config_t *lcd_conf);
/**
* @brief Deinitial screen
*
* @return
* - ESP_OK Success
* - ESP_FAIL Fail
*/
esp_err_t lcd_ssd1963_deinit(void);
/**
* @brief Get screen information
*
* @param info Pointer to a scr_info_t structure.
*
* @return
* - ESP_OK Success
* - ESP_FAIL Fail
*/
esp_err_t lcd_ssd1963_get_info(scr_info_t *info);
/**
* @brief Set screen direction of rotation
*
* @param dir Pointer to a scr_dir_t structure.
*
* @return
* - ESP_OK Success
* - ESP_FAIL Fail
*/
esp_err_t lcd_ssd1963_set_rotation(scr_dir_t dir);
/**
* @brief Set screen window
*
* @param x0 Starting point in X direction
* @param y0 Starting point in Y direction
* @param x1 End point in X direction
* @param y1 End point in Y direction
*
* @return
* - ESP_OK on success
* - ESP_FAIL Failed
*/
esp_err_t lcd_ssd1963_set_window(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1);
/**
* @brief Write a RAM data
*
* @param color New color of a pixel
*
* @return
* - ESP_OK on success
* - ESP_FAIL Failed
*/
esp_err_t lcd_ssd1963_write_ram_data(uint16_t color);
/**
* @brief Draw one pixel in screen with color
*
* @param x X co-ordinate of set orientation
* @param y Y co-ordinate of set orientation
* @param color New color of the pixel
*
* @return
* - ESP_OK Success
* - ESP_FAIL Fail
*/
esp_err_t lcd_ssd1963_draw_pixel(uint16_t x, uint16_t y, uint16_t color);
/**
* @brief Fill the pixels on LCD screen with bitmap
*
* @param x Starting point in X direction
* @param y Starting point in Y direction
* @param w width of image in bitmap array
* @param h height of image in bitmap array
* @param bitmap pointer to bitmap array
*
* @return
* - ESP_OK Success
* - ESP_FAIL Fail
*/
esp_err_t lcd_ssd1963_draw_bitmap(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t *bitmap);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -151,7 +151,7 @@ esp_err_t lcd_st7789_init(const scr_controller_config_t *lcd_conf)
LCD_CHECK(lcd_conf->width <= ST7789_RESOLUTION_HOR, "Width greater than maximum", ESP_ERR_INVALID_ARG);
LCD_CHECK(lcd_conf->height <= ST7789_RESOLUTION_VER, "Height greater than maximum", ESP_ERR_INVALID_ARG);
LCD_CHECK(NULL != lcd_conf, "config pointer invalid", ESP_ERR_INVALID_ARG);
LCD_CHECK((NULL != lcd_conf->interface_drv->write_cmd && \
LCD_CHECK((NULL != lcd_conf->interface_drv->write_command && \
NULL != lcd_conf->interface_drv->write_data && \
NULL != lcd_conf->interface_drv->write && \
NULL != lcd_conf->interface_drv->read && \

View file

@ -81,7 +81,7 @@ esp_err_t lcd_st7796_init(const scr_controller_config_t *lcd_conf)
LCD_CHECK(lcd_conf->width <= ST7796_RESOLUTION_HOR, "Width greater than maximum", ESP_ERR_INVALID_ARG);
LCD_CHECK(lcd_conf->height <= ST7796_RESOLUTION_VER, "Height greater than maximum", ESP_ERR_INVALID_ARG);
LCD_CHECK(NULL != lcd_conf, "config pointer invalid", ESP_ERR_INVALID_ARG);
LCD_CHECK((NULL != lcd_conf->interface_drv->write_cmd && \
LCD_CHECK((NULL != lcd_conf->interface_drv->write_command && \
NULL != lcd_conf->interface_drv->write_data && \
NULL != lcd_conf->interface_drv->write && \
NULL != lcd_conf->interface_drv->read && \

View file

@ -28,6 +28,11 @@ static const char *TAG = "screen interface";
return (ret); \
}
#if (CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S3)
#define SOC_SUPPORT_8080_IFACE 1
#endif
#ifdef SOC_SUPPORT_8080_IFACE
/**--------------------- I2S interface driver ----------------------*/
typedef struct {
i2s_lcd_handle_t i2s_lcd_handle;
@ -40,10 +45,10 @@ static esp_err_t _i2s_lcd_write_data(void *handle, uint16_t data)
return i2s_lcd_write_data(interface_i2s->i2s_lcd_handle, data);
}
static esp_err_t _i2s_lcd_write_cmd(void *handle, uint16_t cmd)
static esp_err_t _i2s_lcd_write_command(void *handle, const uint8_t *cmd, uint32_t length)
{
interface_i2s_handle_t *interface_i2s = __containerof(handle, interface_i2s_handle_t, interface_drv);
return i2s_lcd_write_cmd(interface_i2s->i2s_lcd_handle, cmd);
return i2s_lcd_write_command(interface_i2s->i2s_lcd_handle, cmd, length);
}
static esp_err_t _i2s_lcd_write(void *handle, const uint8_t *data, uint32_t length)
@ -68,6 +73,7 @@ static esp_err_t _i2s_lcd_release(void *handle)
interface_i2s_handle_t *interface_i2s = __containerof(handle, interface_i2s_handle_t, interface_drv);
return i2s_lcd_release(interface_i2s->i2s_lcd_handle);
}
#endif
/**--------------------- I2C interface driver ----------------------*/
#define SSD1306_WRITE_CMD 0x00
@ -110,10 +116,11 @@ static esp_err_t i2c_lcd_write_byte(i2c_bus_device_handle_t i2c_dev, uint8_t ctr
return ESP_OK;
}
static esp_err_t i2c_lcd_write_cmd(void *handle, uint16_t cmd)
static esp_err_t i2c_lcd_write_command(void *handle, const uint8_t *cmd, uint32_t length)
{
(void)length;// TODO: In most cases, the length is 1
interface_i2c_handle_t *interface_i2c = __containerof(handle, interface_i2c_handle_t, interface_drv);
uint8_t v = cmd;
uint8_t v = *cmd;
return i2c_lcd_write_byte(interface_i2c->i2c_dev, SSD1306_WRITE_CMD, v);
}
@ -162,7 +169,7 @@ typedef struct {
static esp_err_t spi_lcd_driver_init(const scr_interface_spi_config_t *cfg, interface_spi_handle_t *out_interface_spi)
{
LCD_IFACE_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(cfg->pin_num_cs), "gpio cs invalid", ESP_ERR_INVALID_ARG);
LCD_IFACE_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(cfg->pin_num_cs) || cfg->pin_num_cs == -1, "gpio cs invalid", ESP_ERR_INVALID_ARG);
LCD_IFACE_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(cfg->pin_num_dc), "gpio dc invalid", ESP_ERR_INVALID_ARG);
//Initialize non-SPI GPIOs
@ -204,13 +211,12 @@ static esp_err_t _lcd_spi_rw(spi_bus_device_handle_t spi, const uint8_t *output,
return spi_bus_transfer_bytes(spi, output, input, length);
}
static esp_err_t spi_lcd_driver_write_cmd(void *handle, uint16_t value)
static esp_err_t spi_lcd_driver_write_command(void *handle, const uint8_t *cmd, uint32_t length)
{
interface_spi_handle_t *interface_spi = __containerof(handle, interface_spi_handle_t, interface_drv);
esp_err_t ret;
gpio_set_level(interface_spi->pin_num_dc, LCD_CMD_LEV);
uint8_t data = value;
ret = _lcd_spi_rw(interface_spi->spi_wr_dev, &data, NULL, 1);
ret = _lcd_spi_rw(interface_spi->spi_wr_dev, cmd, NULL, length);
gpio_set_level(interface_spi->pin_num_dc, LCD_DATA_LEV);
LCD_IFACE_CHECK(ESP_OK == ret, "Send cmd failed", ESP_FAIL);
return ESP_OK;
@ -278,6 +284,7 @@ esp_err_t scr_interface_create(scr_interface_type_t type, void *config, scr_inte
LCD_IFACE_CHECK(NULL != out_driver, "Pointer of driver is invalid", ESP_ERR_INVALID_ARG);
switch (type) {
#ifdef SOC_SUPPORT_8080_IFACE
case SCREEN_IFACE_8080: {
interface_i2s_handle_t *interface_i2s = heap_caps_malloc(sizeof(interface_i2s_handle_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
LCD_IFACE_CHECK(NULL != interface_i2s, "memory of iface i2s is not enough", ESP_ERR_NO_MEM);
@ -289,7 +296,7 @@ esp_err_t scr_interface_create(scr_interface_type_t type, void *config, scr_inte
}
interface_i2s->interface_drv.type = type;
interface_i2s->interface_drv.write_cmd = _i2s_lcd_write_cmd;
interface_i2s->interface_drv.write_command = _i2s_lcd_write_command;
interface_i2s->interface_drv.write_data = _i2s_lcd_write_data;
interface_i2s->interface_drv.write = _i2s_lcd_write;
interface_i2s->interface_drv.read = _i2s_lcd_read;
@ -298,6 +305,7 @@ esp_err_t scr_interface_create(scr_interface_type_t type, void *config, scr_inte
*out_driver = &interface_i2s->interface_drv;
} break;
#endif
case SCREEN_IFACE_SPI: {
interface_spi_handle_t *interface_spi = heap_caps_malloc(sizeof(interface_spi_handle_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
LCD_IFACE_CHECK(NULL != interface_spi, "memory of iface spi is not enough", ESP_ERR_NO_MEM);
@ -309,7 +317,7 @@ esp_err_t scr_interface_create(scr_interface_type_t type, void *config, scr_inte
}
interface_spi->interface_drv.type = type;
interface_spi->interface_drv.write_cmd = spi_lcd_driver_write_cmd;
interface_spi->interface_drv.write_command = spi_lcd_driver_write_command;
interface_spi->interface_drv.write_data = spi_lcd_driver_write_data;
interface_spi->interface_drv.write = spi_lcd_driver_write;
interface_spi->interface_drv.read = spi_lcd_driver_read;
@ -330,7 +338,7 @@ esp_err_t scr_interface_create(scr_interface_type_t type, void *config, scr_inte
}
interface_i2c->interface_drv.type = type;
interface_i2c->interface_drv.write_cmd = i2c_lcd_write_cmd;
interface_i2c->interface_drv.write_command = i2c_lcd_write_command;
interface_i2c->interface_drv.write_data = i2c_lcd_write_data;
interface_i2c->interface_drv.write = i2c_lcd_write;
interface_i2c->interface_drv.read = i2c_lcd_read;
@ -352,11 +360,13 @@ esp_err_t scr_interface_delete(const scr_interface_driver_t *driver)
LCD_IFACE_CHECK(NULL != driver, "Pointer of driver is invalid", ESP_ERR_INVALID_ARG);
switch (driver->type) {
#ifdef SOC_SUPPORT_8080_IFACE
case SCREEN_IFACE_8080: {
interface_i2s_handle_t *interface_i2s = __containerof(driver, interface_i2s_handle_t, interface_drv);
i2s_lcd_driver_deinit(interface_i2s->i2s_lcd_handle);
heap_caps_free(interface_i2s);
} break;
#endif
case SCREEN_IFACE_SPI: {
interface_spi_handle_t *interface_spi = __containerof(driver, interface_spi_handle_t, interface_drv);
spi_lcd_driver_deinit(interface_spi);

View file

@ -62,7 +62,7 @@ typedef enum {
*/
typedef struct {
scr_interface_type_t type; /*!< Interface bus type, see scr_interface_type_t struct */
esp_err_t (*write_cmd)(void *handle, uint16_t cmd); /*!< Function to write a command */
esp_err_t (*write_command)(void *handle, const uint8_t *cmd, uint32_t length); /*!< Function to write command */
esp_err_t (*write_data)(void *handle, uint16_t data); /*!< Function to write a data */
esp_err_t (*write)(void *handle, const uint8_t *data, uint32_t length); /*!< Function to write a block data */
esp_err_t (*read)(void *handle, uint8_t *data, uint32_t length); /*!< Function to read a block data */

View file

@ -31,12 +31,18 @@ static const char *TAG = "screen driver";
#ifdef CONFIG_LCD_DRIVER_SCREEN_CONTROLLER_ILI9341
extern scr_driver_t lcd_ili9341_default_driver;
#endif
#ifdef CONFIG_LCD_DRIVER_SCREEN_CONTROLLER_ILI9342
extern scr_driver_t lcd_ili9342_default_driver;
#endif
#ifdef CONFIG_LCD_DRIVER_SCREEN_CONTROLLER_ILI9486
extern scr_driver_t lcd_ili9486_default_driver;
#endif
#ifdef CONFIG_LCD_DRIVER_SCREEN_CONTROLLER_ILI9806
extern scr_driver_t lcd_ili9806_default_driver;
#endif
#ifdef CONFIG_LCD_DRIVER_SCREEN_CONTROLLER_ILI9488
extern scr_driver_t lcd_ili9488_default_driver;
#endif
#ifdef CONFIG_LCD_DRIVER_SCREEN_CONTROLLER_NT35510
extern scr_driver_t lcd_nt35510_default_driver;
#endif
@ -46,6 +52,9 @@ extern scr_driver_t lcd_rm68120_default_driver;
#ifdef CONFIG_LCD_DRIVER_SCREEN_CONTROLLER_SSD1351
extern scr_driver_t lcd_ssd1351_default_driver;
#endif
#ifdef CONFIG_LCD_DRIVER_SCREEN_CONTROLLER_SSD1963
extern scr_driver_t lcd_ssd1963_default_driver;
#endif
#ifdef CONFIG_LCD_DRIVER_SCREEN_CONTROLLER_ST7789
extern scr_driver_t lcd_st7789_default_driver;
#endif
@ -76,6 +85,11 @@ esp_err_t scr_find_driver(scr_controller_t controller, scr_driver_t *out_screen)
*out_screen = lcd_ili9341_default_driver;
break;
#endif
#ifdef CONFIG_LCD_DRIVER_SCREEN_CONTROLLER_ILI9342
case SCREEN_CONTROLLER_ILI9342:
*out_screen = lcd_ili9342_default_driver;
break;
#endif
#ifdef CONFIG_LCD_DRIVER_SCREEN_CONTROLLER_ILI9806
case SCREEN_CONTROLLER_ILI9806:
*out_screen = lcd_ili9806_default_driver;
@ -86,6 +100,11 @@ esp_err_t scr_find_driver(scr_controller_t controller, scr_driver_t *out_screen)
*out_screen = lcd_ili9486_default_driver;
break;
#endif
#ifdef CONFIG_LCD_DRIVER_SCREEN_CONTROLLER_ILI9488
case SCREEN_CONTROLLER_ILI9488:
*out_screen = lcd_ili9488_default_driver;
break;
#endif
#ifdef CONFIG_LCD_DRIVER_SCREEN_CONTROLLER_NT35510
case SCREEN_CONTROLLER_NT35510:
*out_screen = lcd_nt35510_default_driver;
@ -111,6 +130,11 @@ esp_err_t scr_find_driver(scr_controller_t controller, scr_driver_t *out_screen)
*out_screen = lcd_ssd1351_default_driver;
break;
#endif
#ifdef CONFIG_LCD_DRIVER_SCREEN_CONTROLLER_SSD1963
case SCREEN_CONTROLLER_SSD1963:
*out_screen = lcd_ssd1963_default_driver;
break;
#endif
/**< Monochrome screen */
#ifdef CONFIG_LCD_DRIVER_SCREEN_CONTROLLER_SSD1306

View file

@ -126,13 +126,16 @@ typedef enum {
typedef enum {
/* color screen */
SCREEN_CONTROLLER_ILI9341,
SCREEN_CONTROLLER_ILI9342,
SCREEN_CONTROLLER_ILI9806,
SCREEN_CONTROLLER_ILI9486,
SCREEN_CONTROLLER_ILI9488,
SCREEN_CONTROLLER_NT35510,
SCREEN_CONTROLLER_RM68120,
SCREEN_CONTROLLER_ST7789,
SCREEN_CONTROLLER_ST7796,
SCREEN_CONTROLLER_SSD1351,
SCREEN_CONTROLLER_SSD1963,
/* monochrome screen */
SCREEN_CONTROLLER_SSD1306,

View file

@ -19,15 +19,40 @@
extern "C" {
#endif
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0))
#define gpio_pad_select_gpio esp_rom_gpio_pad_select_gpio
#define portTICK_RATE_MS portTICK_PERIOD_MS
#endif
/**< Define the function of interface instance */
#define LCD_WRITE_CMD(cmd) g_lcd_handle.interface_drv->write_cmd(g_lcd_handle.interface_drv, (cmd))
#define LCD_WRITE_DATA(data) g_lcd_handle.interface_drv->write_data(g_lcd_handle.interface_drv, (data))
#define LCD_WRITE_COMMAND(data, length) g_lcd_handle.interface_drv->write_command(g_lcd_handle.interface_drv, (data), (length))
#define LCD_WRITE(data, length) g_lcd_handle.interface_drv->write(g_lcd_handle.interface_drv, (data), (length))
#define LCD_READ(data, length) g_lcd_handle.interface_drv->read(g_lcd_handle.interface_drv, (data), (length))
#define LCD_IFACE_ACQUIRE() g_lcd_handle.interface_drv->bus_acquire(g_lcd_handle.interface_drv)
#define LCD_IFACE_RELEASE() g_lcd_handle.interface_drv->bus_release(g_lcd_handle.interface_drv)
static inline esp_err_t LCD_WRITE_REG(uint16_t cmd, uint16_t data)
static inline esp_err_t LCD_WRITE_CMD(uint8_t cmd)
{
return LCD_WRITE_COMMAND((uint8_t*)&cmd, 1);
}
static inline esp_err_t LCD_WRITE_CMD_16B(uint16_t cmd)
{
return LCD_WRITE_COMMAND((uint8_t*)&cmd, 2);
}
static inline esp_err_t LCD_WRITE_DATA(uint8_t data)
{
return LCD_WRITE((uint8_t*)&data, 1);
}
static inline esp_err_t LCD_WRITE_DATA_16B(uint16_t data)
{
return LCD_WRITE((uint8_t*)&data, 2);
}
static inline esp_err_t LCD_WRITE_REG(uint8_t cmd, uint8_t data)
{
esp_err_t ret;
ret = LCD_WRITE_CMD(cmd);
@ -39,6 +64,18 @@ static inline esp_err_t LCD_WRITE_REG(uint16_t cmd, uint16_t data)
return ESP_OK;
}
static inline esp_err_t LCD_WRITE_REG_16B(uint16_t cmd, uint16_t data)
{
esp_err_t ret;
ret = LCD_WRITE_CMD_16B(cmd);
ret |= LCD_WRITE_DATA_16B(data);
if (ESP_OK != ret) {
return ESP_FAIL;
}
return ESP_OK;
}
#ifdef __cplusplus
}
#endif

View file

@ -406,6 +406,34 @@ TEST_CASE("Screen RM68210 8080 test", "[screen][iot]")
scr_interface_delete(iface_drv);
}
TEST_CASE("Screen SSD1963 8080 test", "[screen][iot]")
{
scr_driver_t lcd;
scr_interface_driver_t *iface_drv = get_8080_iface();
scr_controller_config_t lcd_cfg = {0};
lcd_cfg.interface_drv = iface_drv;
lcd_cfg.pin_num_rst = -1;
#ifdef CONFIG_IDF_TARGET_ESP32
lcd_cfg.pin_num_bckl = -1;
#else
lcd_cfg.pin_num_bckl = -1;
#endif
lcd_cfg.rst_active_level = 0;
lcd_cfg.bckl_active_level = 1;
lcd_cfg.offset_hor = 0;
lcd_cfg.offset_ver = 0;
lcd_cfg.width = 800;
lcd_cfg.height = 480;
lcd_cfg.rotate = SCR_DIR_LRTB;
TEST_ASSERT(ESP_OK == scr_find_driver(SCREEN_CONTROLLER_SSD1963, &lcd));
TEST_ASSERT(ESP_OK == lcd.init(&lcd_cfg));
lcd_colorful_test_all(&lcd);
lcd.deinit();
scr_interface_delete(iface_drv);
}
TEST_CASE("Screen ILI9341 SPI test", "[screen][iot]")
{
scr_driver_t lcd;

View file

@ -92,28 +92,33 @@ void painter_draw_char(int x, int y, char ascii_char, const font_t *font, uint16
PAINTER_CHECK(ascii_char >= ' ', "ACSII code invalid");
PAINTER_CHECK(NULL != font, "Font pointer invalid");
int i, j;
int x0 = x;
uint16_t char_size = font->Height * (font->Width / 8 + (font->Width % 8 ? 1 : 0));
unsigned int char_offset = (ascii_char - ' ') * char_size;
const unsigned char *ptr = &font->table[char_offset];
uint16_t buf[18 * 25];
PAINTER_CHECK(font->Height * font->Width * sizeof(uint16_t) <= sizeof(buf), "Font size is too large");
int ox = 0;
int oy = 0;
for (i = 0; i < font->Width * font->Height; i++) {
buf[i] = g_back_color;
}
for (j = 0; j < char_size; j++) {
uint8_t temp = ptr[j];
for (i = 0; i < 8; i++) {
if (temp & 0x80) {
g_lcd.draw_pixel(x, y, g_point_color);
} else {
g_lcd.draw_pixel(x, y, g_back_color);
buf[ox + (font->Width * oy)] = g_point_color;
}
temp <<= 1;
x++;
if ((x - x0) == font->Width) {
x = x0;
y++;
ox++;
if (ox == font->Width) {
ox = 0;
oy++;
break;
}
}
}
g_lcd.draw_bitmap(x, y, font->Width, font->Height, buf); // Draw NxN char
}
void painter_draw_string(int x, int y, const char *text, const font_t *font, uint16_t color)
@ -149,7 +154,7 @@ void painter_draw_num(int x, int y, uint32_t num, uint8_t len, const font_t *fon
{
PAINTER_CHECK(len < 10, "The length of the number is too long");
PAINTER_CHECK(NULL != font, "Font pointer invalid");
char buf[10]={0};
char buf[10] = {0};
int8_t num_len;
itoa(num, buf, 10);
@ -196,7 +201,7 @@ void painter_draw_line(int x1, int y1, int x2, int y2, uint16_t color)
uint16_t t;
int xerr = 0, yerr = 0, delta_x, delta_y, distance;
int incx, incy, uRow, uCol;
delta_x = x2 - x1;
delta_x = x2 - x1;
delta_y = y2 - y1;
uRow = x1;
uCol = y1;

View file

@ -286,7 +286,7 @@ esp_err_t touch_calibration_run(const scr_driver_t *screen,
calibrate_error = 0;
ESP_LOGI(TAG, "/ XL = (%f)X + (%f)Y + (%f)", g_caldata.ax, g_caldata.bx, g_caldata.cx);
ESP_LOGI(TAG, "\\ YL = (%f)X + (%f)Y + (%f)", g_caldata.ay, g_caldata.by, g_caldata.cy);
show_prompt_with_dir(30, h/2, "Successful", &Font16, COLOR_BLUE, old_dir);
show_prompt_with_dir((w/2)-(Font16.Width*5), (h/2)+Font16.Height, "Successful", &Font16, COLOR_BLUE, old_dir);
touch_save_calibration(&g_caldata, sizeof(Calibration_t));
vTaskDelay(2000 / portTICK_PERIOD_MS);
}

View file

@ -1,8 +1,7 @@
file(GLOB_RECURSE srcs lvgl/src/*.c)
list(APPEND srcs "lvgl_gui.c"
"lvgl_adapter.c")
list(APPEND srcs "lvgl_gui.c")
set(incdirs "."
"lvgl"
@ -10,6 +9,6 @@ set(incdirs "."
"lvgl/src")
idf_component_register(SRCS "${srcs}"
INCLUDE_DIRS "${incdirs}"
REQUIRES screen touch_panel)
REQUIRES screen touch_panel esp_timer)
target_compile_definitions(${COMPONENT_LIB} INTERFACE LV_CONF_INCLUDE_SIMPLE=1)

View file

@ -1 +0,0 @@
[[中文]](../../../documents/hmi_solution/littlevgl/littlevgl_guide_cn.md)/[[EN]]((../../../documents/hmi_solution/littlevgl/littlevgl_guide_en.md))

View file

@ -1,17 +1,16 @@
#ifndef _COM_GUI_LVGL_H
#define _COM_GUI_LVGL_H
#include "lv_conf.h"
#include "lvgl.h"
#include "touch_panel.h"
#include "screen_driver.h"
#ifdef __cplusplus
extern "C"
{
#endif
#include "sdkconfig.h"
#include "lv_conf.h"
#include "lvgl.h"
#include "lvgl_adapter.h"
/**
* @brief Initialize lvgl and register driver to lvgl
*
@ -26,9 +25,22 @@ extern "C"
*/
esp_err_t lvgl_init(scr_driver_t *lcd_drv, touch_panel_driver_t *touch_drv);
/**
* @brief Acquire lock for LVGL
*
* @note If you wish to call any lvgl function from other threads/tasks you should lock on the very same semaphore
*
*/
void lvgl_acquire(void);
/**
* @brief Release lock for LVGL
*
*/
void lvgl_release(void);
#ifdef __cplusplus
}
#endif
#endif /* _COM_GUI_LVGL_H */
#endif /* _COM_GUI_LVGL_H */

View file

@ -1,146 +0,0 @@
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "freertos/semphr.h"
#include "lvgl_adapter.h"
#include "sdkconfig.h"
static const char *TAG = "lvgl adapter";
static scr_driver_t lcd_obj;
static touch_panel_driver_t touch_obj;
static uint16_t g_screen_width = 240;
static uint16_t g_screen_height = 320;
/*Write the internal buffer (VDB) to the display. 'lv_flush_ready()' has to be called when finished*/
static void ex_disp_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map)
{
lcd_obj.draw_bitmap(area->x1, area->y1, (uint16_t)(area->x2 - area->x1 + 1), (uint16_t)(area->y2 - area->y1 + 1), (uint16_t *)color_map);
/* IMPORTANT!!!
* Inform the graphics library that you are ready with the flushing*/
lv_disp_flush_ready(drv);
}
#define DISP_BUF_SIZE (g_screen_width * 64)
#define SIZE_TO_PIXEL(v) ((v) / sizeof(lv_color_t))
#define PIXEL_TO_SIZE(v) ((v) * sizeof(lv_color_t))
#define BUFFER_NUMBER (2)
esp_err_t lvgl_display_init(scr_driver_t *driver)
{
if (NULL == driver) {
ESP_LOGE(TAG, "Pointer of lcd driver is invalid");
return ESP_ERR_INVALID_ARG;
}
lcd_obj = *driver;
scr_info_t info;
lcd_obj.get_info(&info);
g_screen_width = info.width;
g_screen_height = info.height;
lv_disp_drv_t disp_drv; /*Descriptor of a display driver*/
lv_disp_drv_init(&disp_drv); /*Basic initialization*/
disp_drv.hor_res = g_screen_width;
disp_drv.ver_res = g_screen_height;
disp_drv.flush_cb = ex_disp_flush; /*Used in buffered mode (LV_VDB_SIZE != 0 in lv_conf.h)*/
size_t free_size = heap_caps_get_free_size(MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
const size_t remain_size = 60 * 1024; /**< Remain for other functions */
size_t alloc_pixel = DISP_BUF_SIZE;
if (((BUFFER_NUMBER * PIXEL_TO_SIZE(alloc_pixel)) + remain_size) > free_size) {
size_t allow_size = (free_size - remain_size) & 0xfffffffc;
alloc_pixel = SIZE_TO_PIXEL(allow_size / BUFFER_NUMBER);
ESP_LOGW(TAG, "Exceeded max free size, force shrink to %u Byte", allow_size);
}
lv_color_t *buf1 = heap_caps_malloc(PIXEL_TO_SIZE(alloc_pixel), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
if (NULL == buf1) {
ESP_LOGE(TAG, "Display buffer memory not enough");
return ESP_ERR_NO_MEM;
}
#if (BUFFER_NUMBER == 2)
lv_color_t *buf2 = heap_caps_malloc(PIXEL_TO_SIZE(alloc_pixel), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
if (NULL == buf2) {
heap_caps_free(buf1);
ESP_LOGE(TAG, "Display buffer memory not enough");
return ESP_ERR_NO_MEM;
}
#endif
ESP_LOGI(TAG, "Alloc memory total size: %u Byte", BUFFER_NUMBER * PIXEL_TO_SIZE(alloc_pixel));
static lv_disp_buf_t disp_buf;
#if (BUFFER_NUMBER == 2)
lv_disp_buf_init(&disp_buf, buf1, buf2, alloc_pixel);
#else
lv_disp_buf_init(&disp_buf, buf1, NULL, alloc_pixel);
#endif
disp_drv.buffer = &disp_buf;
/* Finally register the driver */
lv_disp_drv_register(&disp_drv);
return ESP_OK;
}
/*Function pointer to read data. Return 'true' if there is still data to be read (buffered)*/
static bool ex_tp_read(struct _lv_indev_drv_t *indev_drv, lv_indev_data_t *data)
{
data->state = LV_INDEV_STATE_REL;
touch_panel_points_t points;
touch_obj.read_point_data(&points);
// please be sure that your touch driver every time return old (last clcked) value.
if (TOUCH_EVT_PRESS == points.event) {
int32_t x = points.curx[0];
int32_t y = points.cury[0];
data->point.x = x;
data->point.y = y;
data->state = LV_INDEV_STATE_PR;
}
return false;
}
/* Input device interfaceInitialize your touchpad */
esp_err_t lvgl_indev_init(touch_panel_driver_t *driver)
{
if (NULL == driver) {
ESP_LOGE(TAG, "Pointer of touch driver is invalid");
return ESP_ERR_INVALID_ARG;
}
touch_obj = *driver;
lv_indev_drv_t indev_drv; /*Descriptor of an input device driver*/
lv_indev_drv_init(&indev_drv); /*Basic initialization*/
indev_drv.type = LV_INDEV_TYPE_POINTER; /*The touchpad is pointer type device*/
indev_drv.read_cb = ex_tp_read; /*Library ready your touchpad via this function*/
lv_indev_drv_register(&indev_drv); /*Finally register the driver*/
return ESP_OK;
}

View file

@ -1,41 +0,0 @@
#ifndef _LVGL_LCD_ADAPTER_H
#define _LVGL_LCD_ADAPTER_H
#include "lvgl.h"
#include "esp_err.h"
#include "touch_panel.h"
#include "screen_driver.h"
#ifdef __cplusplus
extern "C"
{
#endif
/**
* @brief Initiliaze display device for lvgl
* @note This function only registers the dispaly driver into lvgl, and does not initiliaze the display driver.
*
* @param driver Pointer to display driver
* @return
* - ESP_OK: Success
* - ESP_ERR_NO_MEM: Cannot allocate memory
* - ESP_ERR_INVALID_ARG: Invalid pointer of driver
*/
esp_err_t lvgl_display_init(scr_driver_t *driver);
/**
* @brief Initiliaze touch device for lvgl
* @note This function only registers the touch driver into lvgl, and does not initiliaze the touch driver.
*
* @param driver Pointer to display driver
* @return
* - ESP_OK: Success
* - ESP_ERR_INVALID_ARG: Invalid pointer of driver
*/
esp_err_t lvgl_indev_init(touch_panel_driver_t *driver);
#ifdef __cplusplus
}
#endif
#endif /* _LVGL_LCD_ADAPTER_H */

View file

@ -14,75 +14,156 @@
/* FreeRTOS includes */
#include "freertos/FreeRTOS.h"
#include "freertos/timers.h"
#include "freertos/semphr.h"
#include "esp_log.h"
/* LVGL includes */
#include "esp_timer.h"
#include "lvgl_gui.h"
static const char *TAG = "lvgl_gui";
typedef struct {
scr_driver_t *lcd_drv;
touch_panel_driver_t *touch_drv;
} lvgl_drv_t;
// wait for execute lv_task_handler and lv_tick_inc to avoid some widget don't refresh.
#define LVGL_TICK_MS 1
static void lv_tick_timercb(void *timer)
{
/* Initialize a Timer for 1 ms period and
* in its interrupt call
* lv_tick_inc(1); */
lv_tick_inc(LVGL_TICK_MS);
}
#define ESP_GOTO_ON_FALSE(a, err_code, goto_tag, log_tag, format, ...) do { \
if (unlikely(!(a))) { \
ESP_LOGE(log_tag, "%s(%d): " format, __FUNCTION__, __LINE__ __VA_OPT__(,) __VA_ARGS__); \
ret = err_code; \
goto goto_tag; \
} \
} while (0)
/* Creates a semaphore to handle concurrent call to lvgl stuff
* If you wish to call *any* lvgl function from other threads/tasks
* you should lock on the very same semaphore! */
static SemaphoreHandle_t xGuiSemaphore = NULL;
static void gui_task(void *args)
static TaskHandle_t g_lvgl_task_handle;
#define LVGL_TICK_MS 5
static scr_driver_t lcd_obj;
static touch_panel_driver_t touch_obj;
static uint16_t g_screen_width = 240;
static uint16_t g_screen_height = 320;
/*Write the internal buffer (VDB) to the display. 'lv_flush_ready()' has to be called when finished*/
static void ex_disp_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map)
{
esp_err_t ret;
lvgl_drv_t *lvgl_driver = (lvgl_drv_t *)args;
lcd_obj.draw_bitmap(area->x1, area->y1, (uint16_t)(area->x2 - area->x1 + 1), (uint16_t)(area->y2 - area->y1 + 1), (uint16_t *)color_map);
/* Initialize LittlevGL */
lv_init();
/* IMPORTANT!!!
* Inform the graphics library that you are ready with the flushing*/
lv_disp_flush_ready(drv);
}
/* Display interface */
ret = lvgl_display_init(lvgl_driver->lcd_drv);
if (ESP_OK != ret) {
ESP_LOGE(TAG, "lvgl display initialize failed");
// lv_deinit(); /**< lvgl should be deinit here, but it seems lvgl doesn't support it */
vTaskDelete(NULL);
#define DISP_BUF_SIZE (g_screen_width * 64)
#define SIZE_TO_PIXEL(v) ((v) / sizeof(lv_color_t))
#define PIXEL_TO_SIZE(v) ((v) * sizeof(lv_color_t))
#define BUFFER_NUMBER (2)
static esp_err_t lvgl_display_init(scr_driver_t *driver)
{
if (NULL == driver) {
ESP_LOGE(TAG, "Pointer of lcd driver is invalid");
return ESP_ERR_INVALID_ARG;
}
#if defined(CONFIG_LVGL_DRIVER_TOUCH_SCREEN_ENABLE)
if (NULL != lvgl_driver->touch_drv) {
/* Input device interface */
ret = lvgl_indev_init(lvgl_driver->touch_drv);
if (ESP_OK != ret) {
ESP_LOGE(TAG, "lvgl indev initialize failed");
// lv_deinit(); /**< lvgl should be deinit here, but it seems lvgl doesn't support it */
vTaskDelete(NULL);
}
lcd_obj = *driver;
scr_info_t info;
lcd_obj.get_info(&info);
g_screen_width = info.width;
g_screen_height = info.height;
lv_disp_drv_t disp_drv; /*Descriptor of a display driver*/
lv_disp_drv_init(&disp_drv); /*Basic initialization*/
disp_drv.hor_res = g_screen_width;
disp_drv.ver_res = g_screen_height;
disp_drv.flush_cb = ex_disp_flush; /*Used in buffered mode (LV_VDB_SIZE != 0 in lv_conf.h)*/
size_t free_size = heap_caps_get_free_size(MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
const size_t remain_size = 60 * 1024; /**< Remain for other functions */
size_t alloc_pixel = DISP_BUF_SIZE;
if (((BUFFER_NUMBER * PIXEL_TO_SIZE(alloc_pixel)) + remain_size) > free_size) {
size_t allow_size = (free_size - remain_size) & 0xfffffffc;
alloc_pixel = SIZE_TO_PIXEL(allow_size / BUFFER_NUMBER);
ESP_LOGW(TAG, "Exceeded max free size, force shrink to %u Byte", allow_size);
}
lv_color_t *buf1 = heap_caps_malloc(PIXEL_TO_SIZE(alloc_pixel), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
if (NULL == buf1) {
ESP_LOGE(TAG, "Display buffer memory not enough");
return ESP_ERR_NO_MEM;
}
#if (BUFFER_NUMBER == 2)
lv_color_t *buf2 = heap_caps_malloc(PIXEL_TO_SIZE(alloc_pixel), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
if (NULL == buf2) {
heap_caps_free(buf1);
ESP_LOGE(TAG, "Display buffer memory not enough");
return ESP_ERR_NO_MEM;
}
#endif
esp_timer_create_args_t timer_conf = {
.callback = lv_tick_timercb,
.name = "lv_tick_timer"
};
esp_timer_handle_t g_wifi_connect_timer = NULL;
esp_timer_create(&timer_conf, &g_wifi_connect_timer);
esp_timer_start_periodic(g_wifi_connect_timer, LVGL_TICK_MS * 1000U);
ESP_LOGI(TAG, "Alloc memory total size: %u Byte", BUFFER_NUMBER * PIXEL_TO_SIZE(alloc_pixel));
xGuiSemaphore = xSemaphoreCreateMutex();
static lv_disp_buf_t disp_buf;
#if (BUFFER_NUMBER == 2)
lv_disp_buf_init(&disp_buf, buf1, buf2, alloc_pixel);
#else
lv_disp_buf_init(&disp_buf, buf1, NULL, alloc_pixel);
#endif
disp_drv.buffer = &disp_buf;
/* Finally register the driver */
lv_disp_drv_register(&disp_drv);
return ESP_OK;
}
/*Function pointer to read data. Return 'true' if there is still data to be read (buffered)*/
static bool ex_tp_read(struct _lv_indev_drv_t *indev_drv, lv_indev_data_t *data)
{
data->state = LV_INDEV_STATE_REL;
touch_panel_points_t points;
touch_obj.read_point_data(&points);
// please be sure that your touch driver every time return old (last clcked) value.
if (TOUCH_EVT_PRESS == points.event) {
int32_t x = points.curx[0];
int32_t y = points.cury[0];
data->point.x = x;
data->point.y = y;
data->state = LV_INDEV_STATE_PR;
}
return false;
}
/* Input device interfaceInitialize your touchpad */
static esp_err_t lvgl_indev_init(touch_panel_driver_t *driver)
{
if (NULL == driver) {
ESP_LOGE(TAG, "Pointer of touch driver is invalid");
return ESP_ERR_INVALID_ARG;
}
touch_obj = *driver;
lv_indev_drv_t indev_drv; /*Descriptor of an input device driver*/
lv_indev_drv_init(&indev_drv); /*Basic initialization*/
indev_drv.type = LV_INDEV_TYPE_POINTER; /*The touchpad is pointer type device*/
indev_drv.read_cb = ex_tp_read; /*Library ready your touchpad via this function*/
lv_indev_drv_register(&indev_drv); /*Finally register the driver*/
return ESP_OK;
}
static void lv_tick_timercb(void *timer)
{
lv_tick_inc(LVGL_TICK_MS);
}
static void gui_task(void *args)
{
ESP_LOGI(TAG, "Start to run LVGL");
while (1) {
/* Delay 1 tick (assumes FreeRTOS tick is 10ms */
vTaskDelay(pdMS_TO_TICKS(10));
/* Try to take the semaphore, call lvgl related function on success */
@ -95,27 +176,66 @@ static void gui_task(void *args)
esp_err_t lvgl_init(scr_driver_t *lcd_drv, touch_panel_driver_t *touch_drv)
{
/* If you want to use a task to create the graphic, you NEED to create a Pinned task
* Otherwise there can be problem such as memory corruption and so on.
* NOTE: When not using Wi-Fi nor Bluetooth you can pin the gui_task to core 0 */
esp_chip_info_t chip_info;
esp_chip_info(&chip_info);
ESP_LOGI(TAG, "GUI Run at %s Pinned to Core%d", CONFIG_IDF_TARGET, chip_info.cores - 1);
esp_err_t ret;
esp_timer_handle_t tick_timer = NULL;
static lvgl_drv_t lvgl_driver;
lvgl_driver.lcd_drv = lcd_drv;
lvgl_driver.touch_drv = touch_drv;
/* Initialize LittlevGL */
lv_init();
xTaskCreatePinnedToCore(gui_task, "lv gui", 1024 * 8, &lvgl_driver, 5, NULL, chip_info.cores - 1);
/* Display interface */
ret = lvgl_display_init(lcd_drv);
ESP_GOTO_ON_FALSE(ESP_OK == ret, ESP_FAIL, err, TAG, "lvgl display initialize failed");
uint16_t timeout = 20;
while (NULL == xGuiSemaphore) {
vTaskDelay(pdMS_TO_TICKS(100));
timeout--;
if (0 == timeout) {
ESP_LOGW(TAG, "GUI Task Start Timeout");
return ESP_ERR_TIMEOUT;
}
#if defined(CONFIG_LVGL_DRIVER_TOUCH_SCREEN_ENABLE)
if (NULL != touch_drv) {
/* Input device interface */
ret = lvgl_indev_init(touch_drv);
ESP_GOTO_ON_FALSE(ESP_OK == ret, ESP_FAIL, err, TAG, "lvgl indev initialize failed");
}
#endif
esp_timer_create_args_t timer_conf = {
.callback = lv_tick_timercb,
.name = "lv_tick_timer"
};
ret = esp_timer_create(&timer_conf, &tick_timer);
ESP_GOTO_ON_FALSE(ESP_OK == ret, ESP_FAIL, err, TAG, "lvgl tick timer initialize failed");
xGuiSemaphore = xSemaphoreCreateMutex();
ESP_GOTO_ON_FALSE(NULL != xGuiSemaphore, ESP_FAIL, err, TAG, "Create mutex for LVGL failed");
#if CONFIG_FREERTOS_UNICORE == 0
int err = xTaskCreatePinnedToCore(gui_task, "lv gui", 1024 * 8, NULL, 5, &g_lvgl_task_handle, 1);
#else
int err = xTaskCreatePinnedToCore(gui_task, "lv gui", 1024 * 8, NULL, 5, &g_lvgl_task_handle, 0);
#endif
ESP_GOTO_ON_FALSE(pdPASS == err, ESP_FAIL, err, TAG, "Create task for LVGL failed");
esp_timer_start_periodic(tick_timer, LVGL_TICK_MS * 1000U);
return ESP_OK;
}
err:
if (xGuiSemaphore) {
vSemaphoreDelete(xGuiSemaphore);
}
if (tick_timer) {
esp_timer_delete(tick_timer);
}
return ESP_FAIL;
}
void lvgl_acquire(void)
{
TaskHandle_t task = xTaskGetCurrentTaskHandle();
if (g_lvgl_task_handle != task) {
xSemaphoreTake(xGuiSemaphore, portMAX_DELAY);
}
}
void lvgl_release(void)
{
TaskHandle_t task = xTaskGetCurrentTaskHandle();
if (g_lvgl_task_handle != task) {
xSemaphoreGive(xGuiSemaphore);
}
}

View file

@ -1,2 +1,3 @@
idf_component_register(SRCS "led_indicator.c"
INCLUDE_DIRS include)
INCLUDE_DIRS include
REQUIRES driver)

View file

@ -255,7 +255,6 @@ static esp_err_t _led_set_state(int io_num, bool off_level, blink_step_state_t s
static void _blink_list_switch(_led_indicator_t *p_led_indicator)
{
p_led_indicator->active_blink = NULL_ACTIVE_BLINK; //stop active blink
_led_set_state(p_led_indicator->io_num, p_led_indicator->off_level, LED_STATE_OFF); //turn off the led
for(size_t index = 0; index < BLINK_LIST_NUM; index ++) //find the first incomplete blink
{
if (p_led_indicator->p_blink_steps[index] != LED_BLINK_STOP)
@ -271,7 +270,7 @@ static void _blink_list_switch(_led_indicator_t *p_led_indicator)
*
* @param xTimer handle of the timmer instance
*/
static void _blink_list_runner(xTimerHandle xTimer)
static void _blink_list_runner(TimerHandle_t xTimer)
{
_led_indicator_t * p_led_indicator = (_led_indicator_t *)pvTimerGetTimerID(xTimer);
bool leave = false;
@ -287,9 +286,9 @@ static void _blink_list_runner(xTimerHandle xTimer)
p_led_indicator->p_blink_steps[active_blink] += 1;
if (pdFALSE == xSemaphoreTake(p_led_indicator->mutex, (100 / portTICK_RATE_MS))) {
if (pdFALSE == xSemaphoreTake(p_led_indicator->mutex, pdMS_TO_TICKS(100))) {
ESP_LOGW(TAG, "blinks runner blockTime expired, try repairing...");
xTimerChangePeriod(p_led_indicator->h_timer, (100 / portTICK_RATE_MS), 0);
xTimerChangePeriod(p_led_indicator->h_timer, pdMS_TO_TICKS(100), 0);
xTimerStart(p_led_indicator->h_timer, 0);
break;
}
@ -308,7 +307,7 @@ static void _blink_list_runner(xTimerHandle xTimer)
_led_set_state(p_led_indicator->io_num, p_led_indicator->off_level, p_blink_step->on_off);
if (p_blink_step->hold_time_ms == 0)
break;
xTimerChangePeriod(p_led_indicator->h_timer, (p_blink_step->hold_time_ms / portTICK_RATE_MS), 0);
xTimerChangePeriod(p_led_indicator->h_timer, pdMS_TO_TICKS(p_blink_step->hold_time_ms), 0);
xTimerStart(p_led_indicator->h_timer, 0);
leave=true;
break;
@ -327,13 +326,13 @@ led_indicator_handle_t led_indicator_create(int io_num, const led_indicator_conf
char timmer_name[16] = {'\0'};
snprintf(timmer_name, sizeof(timmer_name) - 1, "%s%02x", "led_tmr_", io_num);
_led_indicator_t *p_led_indicator = (_led_indicator_t *)calloc(1, sizeof(_led_indicator_t));
LED_INDICATOR_CHECK(p_led_indicator != NULL, "calloc memory failed", NULL);
LED_INDICATOR_CHECK(p_led_indicator != NULL, "calloc indicator memory failed", NULL);
p_led_indicator->off_level = config->off_level;
p_led_indicator->io_num = io_num;
p_led_indicator->mode = config->mode;
p_led_indicator->active_blink = NULL_ACTIVE_BLINK;
p_led_indicator->p_blink_steps = (int *)calloc(BLINK_LIST_NUM, sizeof(int));
LED_INDICATOR_CHECK_GOTO(p_led_indicator->p_blink_steps != NULL, "calloc memory failed 2", cleanup_indicator);
LED_INDICATOR_CHECK_GOTO(p_led_indicator->p_blink_steps != NULL, "calloc blink_steps memory failed", cleanup_indicator);
p_led_indicator->mutex = xSemaphoreCreateMutex();
LED_INDICATOR_CHECK_GOTO(p_led_indicator->mutex != NULL, "create mutex failed", cleanup_indicator_blinkstep);
@ -347,7 +346,7 @@ led_indicator_handle_t led_indicator_create(int io_num, const led_indicator_conf
{
bool ininted = _led_gpio_init(p_led_indicator->io_num);
LED_INDICATOR_CHECK_GOTO(ininted != false, "init led gpio failed", cleanup_all);
p_led_indicator->h_timer = xTimerCreate(timmer_name, (100 / portTICK_RATE_MS), pdFALSE, (void *)p_led_indicator, _blink_list_runner);
p_led_indicator->h_timer = xTimerCreate(timmer_name, (pdMS_TO_TICKS(100)), pdFALSE, (void *)p_led_indicator, _blink_list_runner);
LED_INDICATOR_CHECK_GOTO(p_led_indicator->h_timer != NULL, "led timmer create failed", cleanup_all);
}
break;
@ -440,6 +439,10 @@ esp_err_t led_indicator_stop(led_indicator_handle_t handle, led_indicator_blink_
p_led_indicator->p_blink_steps[blink_type] = LED_BLINK_STOP;
_blink_list_switch(p_led_indicator); //stop and swith to next blink steps
xSemaphoreGive(p_led_indicator->mutex);
_blink_list_runner(p_led_indicator->h_timer);
if(p_led_indicator->active_blink == blink_type) { //re-run from first step
_blink_list_runner(p_led_indicator->h_timer);
}
return ESP_OK;
}

View file

@ -1,2 +1,3 @@
idf_component_register(SRCS "light.c"
INCLUDE_DIRS include)
INCLUDE_DIRS include
REQUIRES driver)

View file

@ -143,7 +143,7 @@ esp_err_t iot_light_channel_regist(light_handle_t light_handle, uint8_t channel_
{
light_t* light = (light_t*)light_handle;
POINT_ASSERT(TAG, light_handle);
IOT_CHECK(TAG, channel_idx < light->channel_num, FAIL);
IOT_CHECK(TAG, channel_idx < light->channel_num, ESP_FAIL);
if (light->channel_group[channel_idx] != NULL) {
ESP_LOGE(TAG, "this channel index has been registered");
return ESP_FAIL;
@ -184,7 +184,7 @@ esp_err_t iot_light_breath_write(light_handle_t light_handle, uint8_t channel_id
{
light_t* light = (light_t*)light_handle;
POINT_ASSERT(TAG, light_handle);
IOT_CHECK(TAG, channel_id < light->channel_num, FAIL);
IOT_CHECK(TAG, channel_id < light->channel_num, ESP_FAIL);
POINT_ASSERT(TAG, light->channel_group[channel_id]);
light_channel_t* l_chn = light->channel_group[channel_id];
if (l_chn->breath_period != breath_period_ms) {

View file

@ -1,2 +1,3 @@
idf_component_register(SRCS "iot_servo.c"
INCLUDE_DIRS include)
INCLUDE_DIRS include
REQUIRES driver)

View file

@ -1,3 +1,3 @@
idf_component_register(SRCS "sht3x.c"
INCLUDE_DIRS include
REQUIRES bus)
REQUIRES bus esp_timer)

View file

@ -17,6 +17,7 @@
#include "i2c_bus.h"
#include "esp_log.h"
#include "esp_system.h"
#include "esp_timer.h"
#include "sht3x.h"
typedef struct {

View file

@ -20,7 +20,6 @@
#include "esp_log.h"
#include "mpu6050.h"
static const char *TAG = "MPU6050";
#define WRITE_BIT I2C_MASTER_WRITE /*!< I2C master write */
#define READ_BIT I2C_MASTER_READ /*!< I2C master read */
@ -330,6 +329,7 @@ esp_err_t mpu6050_complimentory_filter(mpu6050_handle_t sensor, mpu6050_acce_val
/***sensors hal interface****/
#ifdef CONFIG_SENSOR_IMU_INCLUDED_MPU6050
static const char *TAG = "MPU6050";
static mpu6050_handle_t mpu6050 = NULL;
static bool is_init = false;

View file

@ -9,4 +9,4 @@ list(APPEND requires bh1750 veml6040 veml6075)
idf_component_register(SRC_DIRS "." "hal"
INCLUDE_DIRS "include"
REQUIRES "${requires}")
REQUIRES "${requires}" "esp_timer")

View file

@ -16,6 +16,7 @@
#include <sys/queue.h>
#include "esp_log.h"
#include "iot_sensor_hub.h"
#include "esp_timer.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

BIN
docs/_static/camera-workflow.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View file

@ -0,0 +1,4 @@
{% extends '!layout.html' %}
{% block comments %}
<p style="text-align:center"><a href="https://www.espressif.com/en/company/documents/documentation_feedback?docId=5602&sections={{ title|striptags|e }} ({{ pagename }})&version={{ release }} ({{ version }})">Provide feedback about this document</a></p>
{% endblock %}

View file

@ -2,6 +2,10 @@ PWM Audio
==============
:link_to_translation:`zh_CN:[中文]`
================== =========== =============== =============== =============
Supported Socs ESP32 ESP32-S2 ESP32-S3 ESP32-C3
================== =========== =============== =============== =============
The PWM audio function uses the internal LEDC peripheral in ESP32 to generate PWM audio, which does not need an external audio Codec chip. This is mainly used for cost-sensitive applications with low audio quality requirements.
Features

View file

@ -217,9 +217,9 @@ Initialize the Screen
/** Find screen driver for ILI9806 */
ret = scr_find_driver(SCREEN_CONTROLLER_ILI9806, &g_lcd);
if (ESP_OK != ret) {
return;
if (ESP_OK != ret) {
ESP_LOGE(TAG, "screen find failed");
return;
}
/** Configure screen controller */

View file

@ -1,15 +1,16 @@
# This is a list of python packages used to generate documentation. This file is used with pip:
# pip install --user -r requirements.txt
#
setuptools<58
sphinx==2.3.1
breathe==4.14.1
sphinx-rtd-theme
sphinx-notfound-page
sphinx-rtd-theme==1.0.0
sphinx-notfound-page==0.7.1
sphinxcontrib-blockdiag==2.0.0
sphinxcontrib-seqdiag==2.0.0
sphinxcontrib-actdiag==2.0.0
sphinxcontrib-nwdiag==2.0.0
sphinxcontrib-wavedrom==2.0.0
nwdiag==2.0.0
recommonmark
future>=0.16.0 # for ../tools/gen_esp_err_to_name.py
recommonmark==0.7.0
future==0.16.0 # for ../tools/gen_esp_err_to_name.py

View file

@ -0,0 +1 @@
setuptools<58

View file

@ -0,0 +1,4 @@
{% extends '!layout.html' %}
{% block comments %}
<p style="text-align:center"><a href="https://www.espressif.com/zh-hans/company/documents/documentation_feedback?docId=5603&sections={{ title|striptags|e }} ({{ pagename }})&version={{ release }} ({{ version }})">提供有关此文档的反馈</a></p>
{% endblock %}

View file

@ -2,8 +2,11 @@ PWM 音频
==============
:link_to_translation:`en:[English]`
PWM 音频功能使用 ESP32 内部的 LEDC 外设产生 PWM 播放音频,无需使用外部的音频 Codec 芯片,适用于对音质要求不高而对成本敏感的应用。
================== =========== =============== =============== =============
支持的芯片 ESP32 ESP32-S2 ESP32-S3 ESP32-C3
================== =========== =============== =============== =============
PWM 音频功能使用 ESP32 内部的 LEDC 外设产生 PWM 播放音频,无需使用外部的音频 Codec 芯片,适用于对音质要求不高而对成本敏感的应用。
特性
------

View file

@ -15,6 +15,8 @@
+------------+----------------+------------+
| ILI9486 | 320 x 480 | Color |
+------------+----------------+------------+
| ILI9488 | 320 x 480 | Color |
+------------+----------------+------------+
| ILI9341 | 240 x 320 | Color |
+------------+----------------+------------+
| ST7789 | 240 x 320 | Color |
@ -29,6 +31,8 @@
+------------+----------------+------------+
| SSD1322 | 480 x 128 | Gray |
+------------+----------------+------------+
| SSD1963 | 480 x 864 | Color |
+------------+----------------+------------+
.. note:: 8080 接口通过 ESP32 I2S 的 LCD 模式实现,故下文中有时也称之为 ``I2S 接口``
@ -216,9 +220,9 @@ BPP < 8 时,一个字节映射到了多个像素,因此无法直接地控制
/** Find screen driver for ILI9806 */
ret = scr_find_driver(SCREEN_CONTROLLER_ILI9806, &g_lcd);
if (ESP_OK != ret) {
return;
if (ESP_OK != ret) {
ESP_LOGE(TAG, "screen find failed");
return;
}
/** Configure screen controller */

View file

@ -6,23 +6,24 @@ This example will show how to configure and operate the LEDC peripheral to play
### Hardware Required
* A development board with ESP32 SoC (e.g., ESP32-DevKitC, ESP-WROVER-KIT, etc.)
* A development board with ESP32, ESP32-S2, ESP32-S3 or ESP32-C3 SoC (e.g., ESP32-DevKitC, ESP-S2-Saola, ESP32-S3-DevKitC-1, etc.)
* A USB cable for power supply and programming
The following is the hardware connection:
|hardware|GPIO|
|SoC|GPIO|
|:---:|:---:|
|speaker(R)|GPIO25|
|speaker(L)|GPIO26|
|ESP32|speaker(R) ----- GPIO25<br />speaker(L) ------- GPIO26|
|ESP32S2|speaker(R) ----- GPIO1<br />speaker(L) ------- GPIO2|
|ESP32S3|speaker(R) ----- GPIO1<br />speaker(L) ------- GPIO2|
|ESP32C3|speaker(R) ----- GPIO1<br />speaker(L) ------- GPIO2|
If you have ESP32-LCDKit board, just plug the speakers into the socket on the board.
If you only have ESP32-DevKitC board, connect two speakers to gpio of ESP32 directly, as shown in the figure below. The volume of this connection will sound small.
You can connect two speakers to gpio of the SoC directly, as shown in the figure below. The volume of this connection will sound small.
```
47R
GPIO25 +----/\/\/\----+
GPIOX +----/\/\/\----+
|
| /|
+-+ | Speaker
@ -33,7 +34,7 @@ GPIO25 +----/\/\/\----+
+--------------+ GND
47R
GPIO26 +----/\/\/\----+
GPIOX +----/\/\/\----+
|
| /|
+-+ | Speaker

View file

@ -40,6 +40,22 @@ static char **g_file_list = NULL;
static uint16_t g_file_num = 0;
#endif
#ifdef CONFIG_IDF_TARGET_ESP32
#define GPIO_AUDIO_OUTPUT_L 25
#define GPIO_AUDIO_OUTPUT_R 26
#elif defined CONFIG_IDF_TARGET_ESP32S2
#define GPIO_AUDIO_OUTPUT_L 1
#define GPIO_AUDIO_OUTPUT_R 2
#elif defined CONFIG_IDF_TARGET_ESP32S3
#define GPIO_AUDIO_OUTPUT_L 1
#define GPIO_AUDIO_OUTPUT_R 2
#elif defined CONFIG_IDF_TARGET_ESP32C3
#define GPIO_AUDIO_OUTPUT_L 1
#define GPIO_AUDIO_OUTPUT_R 2
#else
#endif
static esp_err_t play_wav(const char *filepath)
{
FILE *fd = NULL;
@ -121,9 +137,9 @@ void app_main()
pwm_audio_config_t pac;
pac.duty_resolution = LEDC_TIMER_10_BIT;
pac.gpio_num_left = 25;
pac.gpio_num_left = GPIO_AUDIO_OUTPUT_L;
pac.ledc_channel_left = LEDC_CHANNEL_0;
pac.gpio_num_right = 26;
pac.gpio_num_right = GPIO_AUDIO_OUTPUT_R;
pac.ledc_channel_right = LEDC_CHANNEL_1;
pac.ledc_timer_sel = LEDC_TIMER_0;
pac.tg_num = TIMER_GROUP_0;

View file

@ -26,16 +26,16 @@
#include "sdmmc_cmd.h"
#include "file_manager.h"
#ifdef CONFIG_IDF_TARGET_ESP32
#include "driver/sdmmc_host.h"
#endif
static const char *TAG = "file manager";
static const char *partition_label = "audio";
#define FLN_MAX CONFIG_FATFS_MAX_LFN
#ifdef CONFIG_STORAGE_SDCARD
#ifdef CONFIG_IDF_TARGET_ESP32
#include "driver/sdmmc_host.h"
#endif
// #define USE_SPI_MODE /* To enable SPI mode, uncomment this line*/
// ESP32-S2 doesn't have an SD Host peripheral, always use SPI:
@ -147,6 +147,7 @@ esp_err_t fm_sdcard_init(void)
sdmmc_card_print_info(stdout, card);
return ESP_OK;
}
#endif
esp_err_t fm_spiffs_init(void)
{

83
examples/camera/README.md Normal file
View file

@ -0,0 +1,83 @@
# Camera Examples
This directory contains a range of example [esp32-camera](https://github.com/espressif/esp32-camera) projects.
See the [README.md](../../README.md) file in the upper level directory for more information about examples.
## Camera driver workflow
![](../../docs/_static/camera-workflow.png)
The camera sensor transmits data to ESP32 device through DVP(parallel digital video port) interface. When initializing the camera, some `frame_buffer` will be allocated to store the data transmitted by the camera sensor. Once the camera is initialized, it starts working immediately, and the application can call `esp_camera_fb_get()` to get image data. After the application has applied the image data, the `frame_buffer` can be reused by calling `esp_camera_fb_return()`.
## Example Layout
* `basic` demonstrates basic usage of `ESP32-camera driver`.
* `pic_server` introduces how to control the action of taking pictures, and view the pictures immediately on the web page.
* `test_framerate` introduces how to evaluate the speed of the camera sensor and how to improve the speed of the camera sensor.
* `video_stream_server` demonstrates how to implement a video stream HTTP server on ESP32.
### More
* [ESP-WHO](https://github.com/espressif/esp-who) is an image processing development platform based on Espressif chips. It contains development examples that may be applied in practical applications.
* [USB_camera_examples](https://github.com/espressif/esp-iot-solution/tree/usb/add_usb_solutions/examples/usb/host) Contains some examples of using USB cameras.
## API Reference
The APIs included in the [esp32-camera](https://github.com/espressif/esp32-camera) are described below.
### Header File
- [esp32-camera/driver/include/esp_camera.h](https://github.com/espressif/esp32-camera/blob/master/driver/include/esp_camera.h)
#### Functions
- `esp_err_t esp_camera_init(const camera_config_t* config)`
Initialize the camera driver.
- `esp_err_t esp_camera_deinit()`
Deinitialize the camera driver.
- `camera_fb_t* esp_camera_fb_get()`
Obtain pointer to a frame buffer.
- `void esp_camera_fb_return(camera_fb_t * fb)`
Return the frame buffer to be reused again.
- `sensor_t * esp_camera_sensor_get()`
Get a pointer to the image sensor control structure.
- `esp_err_t esp_camera_save_to_nvs(const char *key)`
Save camera settings to non-volatile-storage (NVS).
- `esp_err_t esp_camera_load_from_nvs(const char *key)`
Load camera settings from non-volatile-storage (NVS).
### Header File
- [esp32-camera/driver/include/sensor.h](https://github.com/espressif/esp32-camera/blob/master/driver/include/sensor.h)
#### Functions
- `camera_sensor_info_t *esp_camera_sensor_get_info(sensor_id_t *id)`
Get the camera sensor information.
### Header File
- [esp32-camera/conversions/include/img_converters.h](https://github.com/espressif/esp32-camera/blob/master/conversions/include/img_converters.h)
#### Functions
- `bool fmt2jpg_cb(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, pixformat_t format, uint8_t quality, jpg_out_cb cb, void * arg)`
Convert image buffer to JPEG.
- `bool frame2jpg_cb(camera_fb_t * fb, uint8_t quality, jpg_out_cb cb, void * arg)`
Convert camera frame buffer to JPEG.
- `bool fmt2jpg(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, pixformat_t format, uint8_t quality, uint8_t ** out, size_t * out_len)`
Convert image buffer to JPEG buffer.
- `bool fmt2bmp(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, pixformat_t format, uint8_t ** out, size_t * out_len)`
Convert image buffer to BMP buffer.
- `bool frame2bmp(camera_fb_t * fb, uint8_t ** out, size_t * out_len)`
Convert camera frame buffer to BMP buffer.
- `bool frame2bmp(camera_fb_t * fb, uint8_t ** out, size_t * out_len)`
Convert camera frame buffer to BMP buffer.
- `bool fmt2rgb888(const uint8_t *src_buf, size_t src_len, pixformat_t format, uint8_t * rgb_buf)`
Convert image buffer to RGB888 buffer.
- `bool jpg2rgb565(const uint8_t *src, size_t src_len, uint8_t * out, jpg_scale_t scale)`
Convert image buffer to RGB565 buffer.
### Header File
- [esp32-camera/conversions/include/esp_jpg_decode.h](https://github.com/espressif/esp32-camera/blob/master/conversions/include/esp_jpg_decode.h)
#### Functions
- `esp_err_t esp_jpg_decode(size_t len, jpg_scale_t scale, jpg_reader_cb reader, jpg_writer_cb writer, void * arg)`
JPEG scaling function.

View file

@ -0,0 +1,18 @@
# The following lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)
#If IOT_SOLUTION_PATH is not defined, use relative path as default value
if(NOT DEFINED ENV{IOT_SOLUTION_PATH})
get_filename_component(IOT_SOLUTION_PATH "${CMAKE_SOURCE_DIR}/../../.." ABSOLUTE)
set(ENV{IOT_SOLUTION_PATH} ${IOT_SOLUTION_PATH})
message(WARNING "Can't detect IOT_SOLUTION_PATH in your environment, we infer it is $ENV{IOT_SOLUTION_PATH}")
endif()
list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IOT_SOLUTION_PATH}/examples/camera/camera_components/camera_example_common" "$ENV{IOT_SOLUTION_PATH}/examples/camera/camera_components/esp32-camera")
include($ENV{IOT_SOLUTION_PATH}/component.cmake)
add_compile_options(-fdiagnostics-color=always)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(camera_basic_example)

View file

@ -0,0 +1,55 @@
| Supported Targets | ESP32 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- |
# Camera Basic Example
This example demonstrates how to initialize the camera sensor and then get the data captured by the sensor.
See the [README.md](../README.md) file in the upper level [camera](../) directory for more information about examples.
## How to use example
### Hardware Required
* A development board with camera module (e.g., ESP-EYE, ESP32-S2-Kaluga-1, ESP32-S3-EYE, etc.)
* A USB cable for power supply and programming
### Configure the project
```
idf.py menuconfig
```
* Open the project configuration menu (`idf.py menuconfig -> Camera Pin Configuration`) to configure camera pins.
### Build and Flash
Build the project and flash it to the board, then run monitor tool to view serial output:
```
idf.py -p PORT flash monitor
```
(Replace PORT with the name of the serial port to use.)
(To exit the serial monitor, type ``Ctrl-]``.)
See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for full steps to configure and use ESP-IDF to build projects.
## Example Output
```
I (325) camera: Detected OV2640 camera
I (325) camera: Camera PID=0x26 VER=0x42 MIDL=0x7f MIDH=0xa2
I (504) s2 ll_cam: node_size: 3840, nodes_per_line: 1, lines_per_node: 6
I (504) s2 ll_cam: dma_half_buffer_min: 3840, dma_half_buffer: 15360, lines_per_half_buffer: 24, dma_buffer_size: 30720
I (512) cam_hal: buffer_size: 30720, half_buffer_size: 15360, node_buffer_size: 3840, node_cnt: 8, total_cnt: 10
I (522) cam_hal: Allocating 153600 Byte frame buffer in PSRAM
I (529) cam_hal: Allocating 153600 Byte frame buffer in PSRAM
I (535) cam_hal: cam config ok
I (539) ov2640: Set PLL: clk_2x: 1, clk_div: 3, pclk_auto: 1, pclk_div: 8
I (714) example:take_picture: Taking picture...
I (855) example:take_picture: Picture taken! Its size was: 153600 bytes
```
## Troubleshooting
* If the log shows "gpio: gpio_intr_disable(176): GPIO number error", then you probably need to check the configuration of camera pins, which you can find in the project configuration menu (`idf.py menuconfig`): Component config -> Camera Pin Config.
* If the initialization of the camera sensor fails. Please check the initialization parameters and pin configuration of your camera sensor.

View file

@ -0,0 +1,3 @@
idf_component_register(SRC_DIRS .
PRIV_INCLUDE_DIRS .
PRIV_REQUIRES nvs_flash esp32-camera camera_example_common)

View file

@ -0,0 +1,5 @@
#
# "main" pseudo-component makefile.
#
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)

View file

@ -0,0 +1,118 @@
/* Camera basic example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <esp_log.h>
#include <esp_system.h>
#include <nvs_flash.h>
#include <sys/param.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_camera.h"
#include "camera_pin.h"
static bool auto_jpeg_support = false; // whether the camera sensor support compression or JPEG encode
static const char *TAG = "example:take_picture";
static esp_err_t init_camera(uint32_t xclk_freq_hz, pixformat_t pixel_format, framesize_t frame_size, uint8_t fb_count)
{
camera_config_t camera_config = {
.pin_pwdn = CAMERA_PIN_PWDN,
.pin_reset = CAMERA_PIN_RESET,
.pin_xclk = CAMERA_PIN_XCLK,
.pin_sscb_sda = CAMERA_PIN_SIOD,
.pin_sscb_scl = CAMERA_PIN_SIOC,
.pin_d7 = CAMERA_PIN_D7,
.pin_d6 = CAMERA_PIN_D6,
.pin_d5 = CAMERA_PIN_D5,
.pin_d4 = CAMERA_PIN_D4,
.pin_d3 = CAMERA_PIN_D3,
.pin_d2 = CAMERA_PIN_D2,
.pin_d1 = CAMERA_PIN_D1,
.pin_d0 = CAMERA_PIN_D0,
.pin_vsync = CAMERA_PIN_VSYNC,
.pin_href = CAMERA_PIN_HREF,
.pin_pclk = CAMERA_PIN_PCLK,
// EXPERIMENTAL: Set to 16MHz on ESP32-S2 or ESP32-S3 to enable EDMA mode.
.xclk_freq_hz = xclk_freq_hz,
.ledc_timer = LEDC_TIMER_0, // This is only valid on ESP32/ESP32-S2. ESP32-S3 use LCD_CAM interface.
.ledc_channel = LEDC_CHANNEL_0,
.pixel_format = pixel_format, // YUV422,GRAYSCALE,RGB565,JPEG
.frame_size = frame_size, // QQVGA-UXGA, sizes above QVGA are not been recommended when not JPEG format.
.jpeg_quality = 30, // 0-63, used only with JPEG format.
.fb_count = fb_count, // For ESP32/ESP32-S2, if more than one, i2s runs in continuous mode.
.grab_mode = CAMERA_GRAB_WHEN_EMPTY,
.fb_location = CAMERA_FB_IN_PSRAM
};
// initialize the camera sensor
esp_err_t ret = esp_camera_init(&camera_config);
if (ret != ESP_OK) {
return ret;
}
// Get the sensor object, and then use some of its functions to adjust the parameters when taking a photo.
// Note: Do not call functions that set resolution, set picture format and PLL clock,
// If you need to reset the appeal parameters, please reinitialize the sensor.
sensor_t *s = esp_camera_sensor_get();
s->set_vflip(s, 1); // flip it back
// initial sensors are flipped vertically and colors are a bit saturated
if (s->id.PID == OV3660_PID) {
s->set_brightness(s, 1); // up the blightness just a bit
s->set_saturation(s, -2); // lower the saturation
}
if (s->id.PID == OV3660_PID || s->id.PID == OV2640_PID) {
s->set_vflip(s, 1); // flip it back
} else if (s->id.PID == GC0308_PID) {
s->set_hmirror(s, 0);
} else if (s->id.PID == GC032A_PID) {
s->set_vflip(s, 1);
}
// Get the basic information of the sensor.
camera_sensor_info_t *s_info = esp_camera_sensor_get_info(&(s->id));
if (ESP_OK == ret && PIXFORMAT_JPEG == pixel_format && s_info->support_jpeg == true) {
auto_jpeg_support = true;
}
return ret;
}
void app_main()
{
if (ESP_OK != init_camera(10 * 1000000, PIXFORMAT_RGB565, FRAMESIZE_QVGA, 2)) {
ESP_LOGE(TAG, "init camrea sensor fail");
return;
}
// take a picture every two seconds and print the size of the picture.
while (1) {
ESP_LOGI(TAG, "Taking picture...");
camera_fb_t *pic = esp_camera_fb_get();
if(pic){
// use pic->buf to access the image
ESP_LOGI(TAG, "Picture taken! Its size was: %zu bytes", pic->len);
// To enable the frame buffer can be reused again.
// Note: If you don't call fb_return(), the next time you call fb_get() you may get
// an error "Failed to get the frame on time!"because there is no frame buffer space available.
esp_camera_fb_return(pic);
}
vTaskDelay(pdMS_TO_TICKS(2000));
}
}

View file

@ -0,0 +1,2 @@
CONFIG_SPIRAM_SUPPORT=n
CONFIG_ESP32S2_SPIRAM_SUPPORT=n

View file

@ -0,0 +1,24 @@
CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y
CONFIG_ESP32S2_DEFAULT_CPU_FREQ_240=y
CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240=y
CONFIG_ESPTOOLPY_FLASHFREQ_80M=y
CONFIG_ESPTOOLPY_FLASHMODE_QIO=y
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
CONFIG_FREERTOS_HZ=1000
CONFIG_SPIRAM_SUPPORT=y
CONFIG_ESP32_SPIRAM_SUPPORT=y
CONFIG_ESP32S2_SPIRAM_SUPPORT=y
CONFIG_ESP32S3_SPIRAM_SUPPORT=y
CONFIG_SPIRAM_MODE_OCT=y
CONFIG_SPIRAM_SPEED_80M=y
CONFIG_SPIRAM_MEMTEST=n
CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=1580
CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1536
CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP=y
CONFIG_BOOTLOADER_SKIP_VALIDATE_ON_POWER_ON=y
CONFIG_BOOTLOADER_SKIP_VALIDATE_ALWAYS=y

View file

@ -0,0 +1,5 @@
# The following lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)
idf_component_register(INCLUDE_DIRS "include")

View file

@ -0,0 +1,156 @@
menu "Camera Pin Configuration"
choice CAMERA_MODULE
bool "Select Camera Pinout"
default CAMERA_MODULE_WROVER_KIT
help
Select Camera Pinout.
config CAMERA_MODULE_WROVER_KIT
bool "WROVER-KIT With OV2640 Module"
config CAMERA_MODULE_ESP_EYE
bool "ESP-EYE DevKit"
config CAMERA_MODULE_ESP_S2_KALUGA
bool "ESP32-S2-Kaluga-1 V1.3"
config CAMERA_MODULE_ESP_S3_EYE
bool "ESP-S3-EYE DevKit"
config CAMERA_MODEL_ESP32_CAM_BOARD
bool "ESP32 Camera Development Board"
config CAMERA_MODULE_M5STACK_PSRAM
bool "M5Stack Camera With PSRAM"
config CAMERA_MODULE_M5STACK_WIDE
bool "M5Stack Camera F (Wide)"
config CAMERA_MODULE_AI_THINKER
bool "ESP32-CAM by AI-Thinker"
config CAMERA_MODULE_CUSTOM
bool "Custom Camera Pinout"
endchoice
config CAMERA_PIN_PWDN
depends on CAMERA_MODULE_CUSTOM
int "Power Down pin"
range -1 33
default -1
help
Select Power Down pin or -1 for unmanaged.
config CAMERA_PIN_RESET
depends on CAMERA_MODULE_CUSTOM
int "Reset pin"
range -1 33
default -1
help
Select Camera Reset pin or -1 for software reset.
config CAMERA_PIN_XCLK
depends on CAMERA_MODULE_CUSTOM
int "XCLK pin"
range 0 33
default 21
help
Select Camera XCLK pin.
config CAMERA_PIN_SIOD
depends on CAMERA_MODULE_CUSTOM
int "SIOD pin"
range 0 33
default 26
help
Select Camera SIOD pin.
config CAMERA_PIN_SIOC
depends on CAMERA_MODULE_CUSTOM
int "SIOC pin"
range 0 33
default 27
help
Select Camera SIOC pin.
config CAMERA_PIN_VSYNC
depends on CAMERA_MODULE_CUSTOM
int "VSYNC pin"
range 0 39
default 25
help
Select Camera VSYNC pin.
config CAMERA_PIN_HREF
depends on CAMERA_MODULE_CUSTOM
int "HREF pin"
range 0 39
default 23
help
Select Camera HREF pin.
config CAMERA_PIN_PCLK
depends on CAMERA_MODULE_CUSTOM
int "PCLK pin"
range 0 39
default 25
help
Select Camera PCLK pin.
config CAMERA_PIN_Y2
depends on CAMERA_MODULE_CUSTOM
int "Y2 pin"
range 0 39
default 4
help
Select Camera Y2 pin.
config CAMERA_PIN_Y3
depends on CAMERA_MODULE_CUSTOM
int "Y3 pin"
range 0 39
default 5
help
Select Camera Y3 pin.
config CAMERA_PIN_Y4
depends on CAMERA_MODULE_CUSTOM
int "Y4 pin"
range 0 39
default 18
help
Select Camera Y4 pin.
config CAMERA_PIN_Y5
depends on CAMERA_MODULE_CUSTOM
int "Y5 pin"
range 0 39
default 19
help
Select Camera Y5 pin.
config CAMERA_PIN_Y6
depends on CAMERA_MODULE_CUSTOM
int "Y6 pin"
range 0 39
default 36
help
Select Camera Y6 pin.
config CAMERA_PIN_Y7
depends on CAMERA_MODULE_CUSTOM
int "Y7 pin"
range 0 39
default 39
help
Select Camera Y7 pin.
config CAMERA_PIN_Y8
depends on CAMERA_MODULE_CUSTOM
int "Y8 pin"
range 0 39
default 34
help
Select Camera Y8 pin.
config CAMERA_PIN_Y9
depends on CAMERA_MODULE_CUSTOM
int "Y9 pin"
range 0 39
default 35
help
Select Camera Y9 pin.
endmenu

View file

@ -0,0 +1,3 @@
# Camera Example Common
This directory contains component that is common for esp32-camera examples. The component defines camera pins used by different development boards.

View file

@ -0,0 +1,188 @@
#pragma once
#include "sdkconfig.h"
#if CONFIG_CAMERA_MODULE_WROVER_KIT
#define CAMERA_MODULE_NAME "Wrover Kit"
#define CAMERA_PIN_PWDN -1
#define CAMERA_PIN_RESET -1
#define CAMERA_PIN_XCLK 21
#define CAMERA_PIN_SIOD 26
#define CAMERA_PIN_SIOC 27
#define CAMERA_PIN_D7 35
#define CAMERA_PIN_D6 34
#define CAMERA_PIN_D5 39
#define CAMERA_PIN_D4 36
#define CAMERA_PIN_D3 19
#define CAMERA_PIN_D2 18
#define CAMERA_PIN_D1 5
#define CAMERA_PIN_D0 4
#define CAMERA_PIN_VSYNC 25
#define CAMERA_PIN_HREF 23
#define CAMERA_PIN_PCLK 22
#elif CONFIG_CAMERA_MODULE_ESP_EYE
#define CAMERA_MODULE_NAME "ESP-EYE"
#define CAMERA_PIN_PWDN -1
#define CAMERA_PIN_RESET -1
#define CAMERA_PIN_XCLK 4
#define CAMERA_PIN_SIOD 18
#define CAMERA_PIN_SIOC 23
#define CAMERA_PIN_D7 36
#define CAMERA_PIN_D6 37
#define CAMERA_PIN_D5 38
#define CAMERA_PIN_D4 39
#define CAMERA_PIN_D3 35
#define CAMERA_PIN_D2 14
#define CAMERA_PIN_D1 13
#define CAMERA_PIN_D0 34
#define CAMERA_PIN_VSYNC 5
#define CAMERA_PIN_HREF 27
#define CAMERA_PIN_PCLK 25
#elif CONFIG_CAMERA_MODULE_ESP_S2_KALUGA
#define CAMERA_MODULE_NAME "ESP-S2-KALUGA"
#define CAMERA_PIN_PWDN -1
#define CAMERA_PIN_RESET -1
#define CAMERA_PIN_XCLK 1
#define CAMERA_PIN_SIOD 8
#define CAMERA_PIN_SIOC 7
#define CAMERA_PIN_D7 38
#define CAMERA_PIN_D6 21
#define CAMERA_PIN_D5 40
#define CAMERA_PIN_D4 39
#define CAMERA_PIN_D3 42
#define CAMERA_PIN_D2 41
#define CAMERA_PIN_D1 37
#define CAMERA_PIN_D0 36
#define CAMERA_PIN_VSYNC 2
#define CAMERA_PIN_HREF 3
#define CAMERA_PIN_PCLK 33
#elif CONFIG_CAMERA_MODULE_ESP_S3_EYE
#define CAMERA_MODULE_NAME "ESP-S3-EYE"
#define CAMERA_PIN_PWDN -1
#define CAMERA_PIN_RESET -1
#define CAMERA_PIN_VSYNC 6
#define CAMERA_PIN_HREF 7
#define CAMERA_PIN_PCLK 13
#define CAMERA_PIN_XCLK 15
#define CAMERA_PIN_SIOD 4
#define CAMERA_PIN_SIOC 5
#define CAMERA_PIN_D0 11
#define CAMERA_PIN_D1 9
#define CAMERA_PIN_D2 8
#define CAMERA_PIN_D3 10
#define CAMERA_PIN_D4 12
#define CAMERA_PIN_D5 18
#define CAMERA_PIN_D6 17
#define CAMERA_PIN_D7 16
#elif CONFIG_CAMERA_MODEL_ESP32_CAM_BOARD
#define CAMERA_MODULE_NAME "ESP-DEVCAM"
#define CAMERA_PIN_PWDN 32
#define CAMERA_PIN_RESET 33
#define CAMERA_PIN_XCLK 4
#define CAMERA_PIN_SIOD 18
#define CAMERA_PIN_SIOC 23
#define CAMERA_PIN_D7 36
#define CAMERA_PIN_D6 19
#define CAMERA_PIN_D5 21
#define CAMERA_PIN_D4 39
#define CAMERA_PIN_D3 35
#define CAMERA_PIN_D2 14
#define CAMERA_PIN_D1 13
#define CAMERA_PIN_D0 34
#define CAMERA_PIN_VSYNC 5
#define CAMERA_PIN_HREF 27
#define CAMERA_PIN_PCLK 25
#elif CONFIG_CAMERA_MODULE_M5STACK_PSRAM
#define CAMERA_MODULE_NAME "M5STACK-PSRAM"
#define CAMERA_PIN_PWDN -1
#define CAMERA_PIN_RESET 15
#define CAMERA_PIN_XCLK 27
#define CAMERA_PIN_SIOD 25
#define CAMERA_PIN_SIOC 23
#define CAMERA_PIN_D7 19
#define CAMERA_PIN_D6 36
#define CAMERA_PIN_D5 18
#define CAMERA_PIN_D4 39
#define CAMERA_PIN_D3 5
#define CAMERA_PIN_D2 34
#define CAMERA_PIN_D1 35
#define CAMERA_PIN_D0 32
#define CAMERA_PIN_VSYNC 22
#define CAMERA_PIN_HREF 26
#define CAMERA_PIN_PCLK 21
#elif CONFIG_CAMERA_MODULE_M5STACK_WIDE
#define CAMERA_MODULE_NAME "M5STACK-WIDE"
#define CAMERA_PIN_PWDN -1
#define CAMERA_PIN_RESET 15
#define CAMERA_PIN_XCLK 27
#define CAMERA_PIN_SIOD 22
#define CAMERA_PIN_SIOC 23
#define CAMERA_PIN_D7 19
#define CAMERA_PIN_D6 36
#define CAMERA_PIN_D5 18
#define CAMERA_PIN_D4 39
#define CAMERA_PIN_D3 5
#define CAMERA_PIN_D2 34
#define CAMERA_PIN_D1 35
#define CAMERA_PIN_D0 32
#define CAMERA_PIN_VSYNC 25
#define CAMERA_PIN_HREF 26
#define CAMERA_PIN_PCLK 21
#elif CONFIG_CAMERA_MODULE_AI_THINKER
#define CAMERA_MODULE_NAME "AI-THINKER"
#define CAMERA_PIN_PWDN 32
#define CAMERA_PIN_RESET -1
#define CAMERA_PIN_XCLK 0
#define CAMERA_PIN_SIOD 26
#define CAMERA_PIN_SIOC 27
#define CAMERA_PIN_D7 35
#define CAMERA_PIN_D6 34
#define CAMERA_PIN_D5 39
#define CAMERA_PIN_D4 36
#define CAMERA_PIN_D3 21
#define CAMERA_PIN_D2 19
#define CAMERA_PIN_D1 18
#define CAMERA_PIN_D0 5
#define CAMERA_PIN_VSYNC 25
#define CAMERA_PIN_HREF 23
#define CAMERA_PIN_PCLK 22
#elif CONFIG_CAMERA_MODULE_CUSTOM
#define CAMERA_MODULE_NAME "CUSTOM"
#define CAMERA_PIN_PWDN CONFIG_CAMERA_PIN_PWDN
#define CAMERA_PIN_RESET CONFIG_CAMERA_PIN_RESET
#define CAMERA_PIN_XCLK CONFIG_CAMERA_PIN_XCLK
#define CAMERA_PIN_SIOD CONFIG_CAMERA_PIN_SIOD
#define CAMERA_PIN_SIOC CONFIG_CAMERA_PIN_SIOC
#define CAMERA_PIN_D7 CONFIG_CAMERA_PIN_Y9
#define CAMERA_PIN_D6 CONFIG_CAMERA_PIN_Y8
#define CAMERA_PIN_D5 CONFIG_CAMERA_PIN_Y7
#define CAMERA_PIN_D4 CONFIG_CAMERA_PIN_Y6
#define CAMERA_PIN_D3 CONFIG_CAMERA_PIN_Y5
#define CAMERA_PIN_D2 CONFIG_CAMERA_PIN_Y4
#define CAMERA_PIN_D1 CONFIG_CAMERA_PIN_Y3
#define CAMERA_PIN_D0 CONFIG_CAMERA_PIN_Y2
#define CAMERA_PIN_VSYNC CONFIG_CAMERA_PIN_VSYNC
#define CAMERA_PIN_HREF CONFIG_CAMERA_PIN_HREF
#define CAMERA_PIN_PCLK CONFIG_CAMERA_PIN_PCLK
#endif

@ -0,0 +1 @@
Subproject commit 1ac48e5397ee22a59a18a314c4acf44c23dfe946

View file

@ -0,0 +1,16 @@
# The following lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)
#If IOT_SOLUTION_PATH is not defined, use relative path as default value
if(NOT DEFINED ENV{IOT_SOLUTION_PATH})
get_filename_component(IOT_SOLUTION_PATH "${CMAKE_SOURCE_DIR}/../../.." ABSOLUTE)
set(ENV{IOT_SOLUTION_PATH} ${IOT_SOLUTION_PATH})
message(WARNING "Can't detect IOT_SOLUTION_PATH in your environment, we infer it is $ENV{IOT_SOLUTION_PATH}")
endif()
list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IOT_SOLUTION_PATH}/examples/camera/camera_components/camera_example_common" "$ENV{IOT_SOLUTION_PATH}/examples/camera/camera_components/esp32-camera")
include($ENV{IOT_SOLUTION_PATH}/component.cmake)
# add_compile_options(-fdiagnostics-color=always)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(camera_pic_server)

View file

@ -0,0 +1,53 @@
| Supported Targets | ESP32 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- |
# ESP Camera Picture Server
The example starts a web server on a local network. You can use a browser to access this server to view pictures.
See the [README.md](../README.md) file in the upper level [camera](../) directory for more information about examples.
## How to use the example
### Hardware Required
* A development board with camera module (e.g., ESP-EYE, ESP32-S2-Kaluga-1, ESP32-S3-EYE, etc.)
* A USB cable for power supply and programming
### Configure the project
step1: chose your taget chip.
````
idf.py menuconfig -> Camera Pin Configuration
````
step2: Configure your wifi.
```
idf.py menuconfig -> Example Connection Configuration
```
step3: Configure the camera.
```
idf.py menuconfig -> component config -> Camera Configuration
```
step 4: Launch and monitor
Flash the program and launch IDF Monitor:
```bash
idf.py flash monitor
```
step 5: Test the example interactively on a web browser (assuming IP is 192.168.43.130):
open path `http://192.168.43.130/pic` to see an HTML web page on the server.
step 6: Click the refresh button to get next picture on the HTML web page.
## Troubleshooting
* If the log shows "gpio: gpio_intr_disable(176): GPIO number error", then you probably need to check the configuration of camera pins, which you can find in the project configuration menu (`idf.py menuconfig`): Component config -> Camera Pin Config.
* If the initialization of the camera sensor fails. Please check the initialization parameters and pin configuration of your camera sensor.

View file

@ -0,0 +1,3 @@
idf_component_register(SRC_DIRS .
PRIV_INCLUDE_DIRS .
PRIV_REQUIRES esp32-camera nvs_flash esp_http_server camera_example_common)

View file

@ -0,0 +1,50 @@
menu "Example Connection Configuration"
config ESP_WIFI_SSID
string "WiFi STA SSID"
default ""
help
WiFi SSID (network name) to connect to or empty for Off.
config ESP_WIFI_PASSWORD
string "WiFi STA Password"
default ""
help
WiFi Password if WEP/WPA/WPA2 or empty if Open.
config ESP_WIFI_AP_SSID
string "WiFi AP SSID"
default "ESP32-Camera"
help
AP SSID (network name) to create or empty for Off.
config ESP_WIFI_AP_PASSWORD
string "WiFi AP Password"
default ""
help
AP password for WPA2 or empty for Open.
config MAX_STA_CONN
int "Maximal STA connections"
default 1
help
Max number of the STA connects to AP.
config ESP_WIFI_AP_CHANNEL
string "WiFi AP Channel"
default ""
help
AP channel for better connection performance.
config SERVER_IP
string "WiFi AP IP Address"
default "192.168.4.1"
help
IP address that the ESP will assign to it's AP interface. You can use this IP to connect to the camera after flashing.
config ESP_MAXIMUM_RETRY
int "Maximum retry"
default 5
help
Set the Maximum retry to avoid station reconnecting to the AP unlimited when the AP is really inexistent.
endmenu

Some files were not shown because too many files have changed in this diff Show more