Compare commits
316 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b0a22e756f | |||
| a60c9840ca | |||
| 29e80cfd65 | |||
| 429125734a | |||
| 08eac48e64 | |||
| 8b92aa8e5a | |||
| a3fda9ad8f | |||
| 2fbc44466a | |||
| 2d768ef3a1 | |||
| bd30aa046a | |||
| f9453d8956 | |||
| 5f54f7ca3d | |||
| d896657bf9 | |||
| 3b5a401594 | |||
| 6fb2bb736c | |||
| bd8fdfd858 | |||
| 8af6204ba1 | |||
| 955416dac8 | |||
| fa4a6e255c | |||
| 50c0a14a93 | |||
| c4406b24ba | |||
| 0922c4d55b | |||
| 7a7f09be35 | |||
| 16a61a087c | |||
| 1c2806bddf | |||
| dbb96a891c | |||
| d6ac070e30 | |||
| f4f91f81d6 | |||
| cca7224252 | |||
| 66a4eb66d6 | |||
| dfaeb9a2d9 | |||
| 9d5993930d | |||
| ecad2248d9 | |||
| a323f8e148 | |||
| 05720821f8 | |||
| 90afba647e | |||
| 35fd7dd536 | |||
| cd07c64926 | |||
| 2f5e183f18 | |||
| d3439f6f45 | |||
| 599fa46766 | |||
| e50659a3fb | |||
| aeccc15ab6 | |||
| 594b8bd27e | |||
| e8b9a1f2a9 | |||
| a35c88c8fd | |||
| 8dabda2b5b | |||
| 8dd9bee8d0 | |||
| 543390a977 | |||
| 62266dff58 | |||
| 3dcc95f6f3 | |||
| a59fbf4ed5 | |||
| 5c78d55b04 | |||
| 895e6bc50d | |||
| 4170b86137 | |||
| be2cdc0b90 | |||
| 10ba4f58e2 | |||
| 4dd2762b79 | |||
| e64f4ff16b | |||
| e560cc7df2 | |||
| aa7530e515 | |||
| 2de35b2d2d | |||
| 9fc0aa51d7 | |||
| 2426c387eb | |||
| 33caf09856 | |||
| d2048e01b6 | |||
| f0f764baff | |||
| d860ba1f34 | |||
| 3a24d058c9 | |||
| 72b55b221e | |||
| 9a11e6f47b | |||
| 72c9b2b113 | |||
| 4ab29ae466 | |||
| 8ff990d635 | |||
| 49632d15c9 | |||
| 26c17986c6 | |||
| dff93cb655 | |||
| 25c3f19e5d | |||
| 93efadd5e3 | |||
| d27404964a | |||
| 74127a5f6c | |||
| 7e24105d0c | |||
| 2aa41cb562 | |||
| 0042ce6d32 | |||
| 79e43b093a | |||
| 1757af859c | |||
| 626d0d9776 | |||
| ecc0a9c076 | |||
| 4fe4faf422 | |||
| a1c835e073 | |||
| 9a672a30ff | |||
| 9cc96fd32b | |||
| a935410f82 | |||
| 1a61eac8e0 | |||
| 1f9e7f82fd | |||
| 9f721e6655 | |||
| 3fe1dc0312 | |||
| 5993ceb232 | |||
| 399dca5e14 | |||
| c9185740d7 | |||
| d62314f41f | |||
| 87ca888bb4 | |||
| 71f8369377 | |||
| f6ddb14ec1 | |||
| d551e467b8 | |||
| c05d46a28c | |||
| e6abd496f9 | |||
| 619b5aa53b | |||
| 10381b10cd | |||
| dfe2c865d1 | |||
| 96eccbdc8d | |||
| 2839ea4c35 | |||
| 51b9547e99 | |||
| d3797abf4e | |||
| 4b6ed871a9 | |||
| 0d16eb606f | |||
| b8214fd378 | |||
| 01ffe420eb | |||
| c98cb2bf10 | |||
| f620255c41 | |||
| 719f7bcece | |||
| 2ca8ae62fb | |||
| fa544f9b3c | |||
| 812c2901db | |||
| 524b197105 | |||
| 7283920def | |||
| a4dc633063 | |||
| feaeb11e49 | |||
| 3fc2ff8bc6 | |||
| f48654d3dc | |||
| 261796068e | |||
| 134e0b34b6 | |||
| 6c4a9975a4 | |||
| 776e3cd4c0 | |||
| 76686e5c90 | |||
| cbaa32c27e | |||
| 65d3d55cc4 | |||
| 62124541e9 | |||
| 8de88dd3fd | |||
| c6cc4034df | |||
| b565d56029 | |||
| fec8033fd7 | |||
| 6ab6ae5686 | |||
| eba1f8955a | |||
| a4f4784ed9 | |||
| dddca1ea76 | |||
| c1ff024657 | |||
| c7c9618f48 | |||
| 0df6b78bd6 | |||
| 7918451699 | |||
| 8335611796 | |||
| 0d8c0a37cc | |||
| ab2aa2c4d4 | |||
| e2ec39304c | |||
| 569cce38fa | |||
| 9ae3e48600 | |||
| 388c2cfe4b | |||
| adea6678a5 | |||
| 4a343e58cc | |||
| 61277e74b8 | |||
| efd3c6041c | |||
| 647678ff82 | |||
| 8115ca4fd9 | |||
| db6d3b4acb | |||
| 37420db000 | |||
| b067978c16 | |||
| 09f8031bff | |||
| 1450ca319d | |||
| c139300a58 | |||
| d0d05c67ca | |||
| f660550f86 | |||
| e9384e0c11 | |||
| 9c5a427a34 | |||
| d8346998ce | |||
| 3a59540365 | |||
| d25603166a | |||
| 17b4fc6a47 | |||
| 45a8379426 | |||
| 1e4234d895 | |||
| 2cb413c3d1 | |||
| 5777a1381b | |||
| 15de4e20b8 | |||
| 3802679de4 | |||
| a05a6afaaf | |||
| efd9662cfc | |||
| 00347cbd29 | |||
| b214a3358e | |||
| c7621b5e4c | |||
| 6dc4f698c9 | |||
| f97ca26b01 | |||
| 98bbea3e9c | |||
| f6cdabf3c0 | |||
| dcf28d0868 | |||
| 9cc58099b4 | |||
| 1216862aec | |||
| 7ad0a3cb04 | |||
| bab3eb19bc | |||
| a4d15b2a1e | |||
| 41ad569154 | |||
| faab6d825f | |||
| a2af95b92d | |||
| 53b711584f | |||
| ce8ac61d42 | |||
| d5c94c7a8a | |||
| 7027da00b8 | |||
| 095c8146c3 | |||
| 62c613477a | |||
| d83b98e99b | |||
| ade86c99b4 | |||
| 980b115f1d | |||
| 84049658db | |||
| 068600f98c | |||
| fe7fdd8583 | |||
| f26266ba76 | |||
| 35a918c82b | |||
| 63866fb371 | |||
| 457c21ffd8 | |||
| 65335578a4 | |||
| c0ed8f0a44 | |||
| a9b69010d8 | |||
| 1627b9fa85 | |||
| 1deaf4c426 | |||
| 0f8380e8fe | |||
| 5cc5b50694 | |||
| 5dfc6d70da | |||
| 50007ea9ed | |||
| e9f72490fc | |||
| 8c8ccd8783 | |||
| ee5a5a7181 | |||
| fbaff8cbac | |||
| d875ade8cb | |||
| 15f4fbfdc6 | |||
| 982fce9207 | |||
| 00b62a2831 | |||
| ab4cf79a47 | |||
| d06197a6aa | |||
| efd3dc43ed | |||
| 6de0f442fb | |||
| 29e4350517 | |||
| f9acf04dcb | |||
| a091923353 | |||
| 1593eb80ce | |||
| 869a56125f | |||
| 6116521556 | |||
| 3dfc27e93e | |||
| e4ecec64c9 | |||
| ce96474d84 | |||
| 2691dbb014 | |||
| 74eb830870 | |||
| 870924229a | |||
| b2647f46bb | |||
| d1c1a3a369 | |||
| a5090ec194 | |||
| f67cb241b7 | |||
| b2d4dc5ecb | |||
| a7c5d6a2ee | |||
| 08029a84dd | |||
| eb4e9f9649 | |||
| 3f1bfee3f5 | |||
| d72852a6e2 | |||
| d0ca3b16f8 | |||
| 81ece6f2e7 | |||
| 49a46f6236 | |||
| 358954f8be | |||
| 59ab11d498 | |||
| ebd2c7c6f9 | |||
| 7f33364bf4 | |||
| 0ebc022946 | |||
| f85d0239ff | |||
| 21936f7e9e | |||
| 19521791c5 | |||
| ef410086d9 | |||
| 2d535fec2a | |||
| 778e003d4d | |||
| 85a6ad3bbe | |||
| 13d7e84ef3 | |||
| 83a82be901 | |||
| b85ef7a2e7 | |||
| de46401d85 | |||
| bd2786b122 | |||
| 6d1d08944b | |||
| 70d36131f6 | |||
| b14887d5fb | |||
| 44b366b557 | |||
| ee88a563dc | |||
| 09cdf07b7c | |||
| d29e47f0eb | |||
| 933bc5fb97 | |||
| 6e8fbae62b | |||
| 0563e42dc9 | |||
| 5055fa7822 | |||
| ad2cad3bf1 | |||
| 6e77d5027f | |||
| 55bfb9fe3b | |||
| 2e86d4774b | |||
| b7f39f883d | |||
| 14e459e50f | |||
| 2345ba6d13 | |||
| a7a3b17ff6 | |||
| fd1e31dec4 | |||
| c5fc8790bb | |||
| e1bfdd7c91 | |||
| 5b375c21bb | |||
| c74006f8b6 | |||
| 8ccba15c25 | |||
| c1f55429b6 | |||
| 88b3bfbe3e | |||
| 6337458992 | |||
| 68e34ca740 | |||
| 5ec96f60f1 | |||
| c0f4738abe | |||
| 2e61aea93c | |||
| cff0605b0a | |||
| c87200a80d | |||
| 7856827ecf | |||
| 6c67845645 |
+1
-1
@@ -45,7 +45,7 @@ IndentPPDirectives: None
|
|||||||
IndentWidth: 4
|
IndentWidth: 4
|
||||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||||
MaxEmptyLinesToKeep: 2
|
MaxEmptyLinesToKeep: 2
|
||||||
NamespaceIndentation: All
|
NamespaceIndentation: None
|
||||||
ObjCSpaceAfterProperty: false
|
ObjCSpaceAfterProperty: false
|
||||||
ObjCSpaceBeforeProtocolList: true
|
ObjCSpaceBeforeProtocolList: true
|
||||||
PointerAlignment: Left
|
PointerAlignment: Left
|
||||||
|
|||||||
+1
-1
@@ -10,6 +10,6 @@ liberapay: # Replace with a single Liberapay username
|
|||||||
issuehunt: # Replace with a single IssueHunt username
|
issuehunt: # Replace with a single IssueHunt username
|
||||||
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
|
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
|
||||||
polar: # Replace with a single Polar username
|
polar: # Replace with a single Polar username
|
||||||
buy_me_a_coffee: # Replace with a single Buy Me a Coffee username
|
buy_me_a_coffee: bytewelder
|
||||||
thanks_dev: # Replace with a single thanks.dev username
|
thanks_dev: # Replace with a single thanks.dev username
|
||||||
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
||||||
|
|||||||
@@ -30,4 +30,4 @@ If applicable, add screenshots to help explain your problem.
|
|||||||
|
|
||||||
**Additional context**
|
**Additional context**
|
||||||
Add any other context about the problem here.
|
Add any other context about the problem here.
|
||||||
Add your oops.tactility.one URL if you had a crash (scanned from QR).
|
Add your oops.tactilityproject.org URL if you had a crash (scanned from QR).
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
### Checklist
|
### Checklist
|
||||||
|
|
||||||
- [ ] I read [contribution guidelines](https://github.com/ByteWelder/Tactility/blob/main/CONTRIBUTING.md)
|
- [ ] I read [contribution guidelines](https://github.com/TactilityProject/Tactility/blob/main/CONTRIBUTING.md)
|
||||||
- [ ] Code adheres to the [coding style](https://github.com/ByteWelder/Tactility/blob/main/CODING_STYLE.md)
|
- [ ] Code adheres to the [coding style](https://github.com/TactilityProject/Tactility/blob/main/CODING_STYLE.md)
|
||||||
|
|
||||||
### Description
|
### Description
|
||||||
|
|
||||||
|
|||||||
@@ -11,21 +11,28 @@ inputs:
|
|||||||
runs:
|
runs:
|
||||||
using: "composite"
|
using: "composite"
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
- name: 'Board select'
|
- name: 'Board select'
|
||||||
shell: bash
|
shell: bash
|
||||||
run: cp sdkconfig.board.${{ inputs.board_id }} sdkconfig
|
run: python device.py ${{ inputs.board_id }}
|
||||||
- name: 'Build'
|
- name: 'Build'
|
||||||
uses: espressif/esp-idf-ci-action@main
|
uses: espressif/esp-idf-ci-action@v1
|
||||||
with:
|
with:
|
||||||
esp_idf_version: v5.4
|
esp_idf_version: v5.5.2
|
||||||
target: ${{ inputs.arch }}
|
target: ${{ inputs.arch }}
|
||||||
path: './'
|
path: './'
|
||||||
- name: 'Release'
|
- name: 'Release'
|
||||||
shell: bash
|
shell: bash
|
||||||
run: Buildscripts/release.sh ${{ inputs.board_id }}
|
run: Buildscripts/release.sh ${{ inputs.board_id }}
|
||||||
|
- name: 'Merge binary'
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
python -m pip install esptool
|
||||||
|
cd release/Tactility-${{ inputs.board_id }}
|
||||||
|
bash ./merge.sh ${{ inputs.arch }}
|
||||||
|
mv Binaries/merged_binary.bin ../Tactility-${{ inputs.board_id }}.bin
|
||||||
- name: 'Upload Artifact: Release'
|
- name: 'Upload Artifact: Release'
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
@@ -38,3 +45,9 @@ runs:
|
|||||||
name: Tactility-${{ inputs.board_id }}-symbols
|
name: Tactility-${{ inputs.board_id }}-symbols
|
||||||
path: release/Tactility-${{ inputs.board_id }}-symbols
|
path: release/Tactility-${{ inputs.board_id }}-symbols
|
||||||
retention-days: 30
|
retention-days: 30
|
||||||
|
- name: 'Upload Artifact: Merged binary'
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: Tactility-${{ inputs.board_id }}.bin
|
||||||
|
path: release/Tactility-${{ inputs.board_id }}.bin
|
||||||
|
retention-days: 30
|
||||||
|
|||||||
@@ -11,21 +11,39 @@ inputs:
|
|||||||
runs:
|
runs:
|
||||||
using: "composite"
|
using: "composite"
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
- name: 'Board select'
|
- name: 'Board select'
|
||||||
shell: bash
|
shell: bash
|
||||||
run: cp sdkconfig.board.${{ inputs.board_id }} sdkconfig
|
run: python device.py ${{ inputs.board_id }}
|
||||||
- name: 'Build'
|
- name: 'Build'
|
||||||
uses: espressif/esp-idf-ci-action@main
|
uses: espressif/esp-idf-ci-action@v1
|
||||||
with:
|
with:
|
||||||
esp_idf_version: v5.4
|
# NOTE: Update with ESP-IDF!
|
||||||
|
esp_idf_version: v5.5.2
|
||||||
target: ${{ inputs.arch }}
|
target: ${{ inputs.arch }}
|
||||||
path: './'
|
path: './'
|
||||||
- name: 'Release'
|
- name: 'Release'
|
||||||
shell: bash
|
shell: bash
|
||||||
run: Buildscripts/release-sdk.sh release/TactilitySDK
|
env:
|
||||||
|
# NOTE: Update with ESP-IDF!
|
||||||
|
ESP_IDF_VERSION: '5.5.2'
|
||||||
|
run: python Buildscripts/release-sdk.py release/TactilitySDK
|
||||||
|
- name: 'Test Integration Prep'
|
||||||
|
shell: bash
|
||||||
|
# The manifest.properties of our integration test uses version 0.0.0 to indicate that it is not using a normal SDK
|
||||||
|
# This way, it only works with our custom build. That means we have to create a copy of the SDK with the correct folder structure:
|
||||||
|
run: |
|
||||||
|
TACTILITY_SDK_NAME="0.0.0-${{ inputs.arch }}"
|
||||||
|
mkdir -p test_sdk/$TACTILITY_SDK_NAME
|
||||||
|
cp -r release/TactilitySDK test_sdk/$TACTILITY_SDK_NAME
|
||||||
|
- name: 'Test Integration'
|
||||||
|
uses: espressif/esp-idf-ci-action@v1
|
||||||
|
with:
|
||||||
|
esp_idf_version: v5.5.2
|
||||||
|
target: ${{ inputs.arch }}
|
||||||
|
command: export TACTILITY_SDK_PATH=../../test_sdk && cd Tests/SdkIntegration && python tactility.py build ${{ inputs.arch }} --local-sdk
|
||||||
- name: 'Upload Artifact'
|
- name: 'Upload Artifact'
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ runs:
|
|||||||
using: "composite"
|
using: "composite"
|
||||||
steps:
|
steps:
|
||||||
- name: "Checkout repo"
|
- name: "Checkout repo"
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
- name: Install Linux Dependencies for SDL
|
- name: Install Linux Dependencies for SDL
|
||||||
@@ -23,6 +23,7 @@ runs:
|
|||||||
shell: bash
|
shell: bash
|
||||||
# See Libraries/SDL/docs/README-linux.md
|
# See Libraries/SDL/docs/README-linux.md
|
||||||
run: >
|
run: >
|
||||||
|
sudo apt-get update &&
|
||||||
sudo apt-get install build-essential git make
|
sudo apt-get install build-essential git make
|
||||||
pkg-config cmake ninja-build gnome-desktop-testing libasound2-dev libpulse-dev
|
pkg-config cmake ninja-build gnome-desktop-testing libasound2-dev libpulse-dev
|
||||||
libaudio-dev libjack-dev libsndio-dev libx11-dev libxext-dev
|
libaudio-dev libjack-dev libsndio-dev libx11-dev libxext-dev
|
||||||
@@ -35,14 +36,16 @@ runs:
|
|||||||
WLR_LIBINPUT_NO_DEVICES: 1
|
WLR_LIBINPUT_NO_DEVICES: 1
|
||||||
WAYLAND_DISPLAY: wayland-1
|
WAYLAND_DISPLAY: wayland-1
|
||||||
GTK_USE_PORTAL: 0
|
GTK_USE_PORTAL: 0
|
||||||
- name: "Configure Project"
|
- name: Setup cmake
|
||||||
uses: threeal/cmake-action@v1.3.0
|
uses: jwlawson/actions-setup-cmake@v2
|
||||||
|
with:
|
||||||
|
cmake-version: '3.31.x'
|
||||||
- name: "Prepare Project"
|
- name: "Prepare Project"
|
||||||
shell: bash
|
shell: bash
|
||||||
run: cmake -S ./ -B buildsim
|
run: cmake -S ./ -B buildsim
|
||||||
- name: "Build Tests"
|
- name: "Build Tests"
|
||||||
shell: bash
|
shell: bash
|
||||||
run: cmake --build buildsim --target AppSim
|
run: cmake --build buildsim --target FirmwareSim
|
||||||
- name: 'Release'
|
- name: 'Release'
|
||||||
shell: bash
|
shell: bash
|
||||||
run: Buildscripts/release-simulator.sh buildsim release/Simulator-${{ inputs.os_name }}-${{ inputs.platform_name }}
|
run: Buildscripts/release-simulator.sh buildsim release/Simulator-${{ inputs.os_name }}-${{ inputs.platform_name }}
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
name: Bundle All
|
||||||
|
|
||||||
|
runs:
|
||||||
|
using: 'composite'
|
||||||
|
steps:
|
||||||
|
- name: 'Download artifacts'
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
path: artifacts
|
||||||
|
- name: 'Upload Artifact'
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: 'all-artifacts'
|
||||||
|
path: artifacts/
|
||||||
|
retention-days: 3
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
name: Publish Firmware
|
||||||
|
|
||||||
|
inputs:
|
||||||
|
cdn_version:
|
||||||
|
description: The version that determines the path on the CDN
|
||||||
|
required: true
|
||||||
|
|
||||||
|
runs:
|
||||||
|
using: 'composite'
|
||||||
|
steps:
|
||||||
|
- name: 'Download all-artifacts'
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: 'all-artifacts'
|
||||||
|
path: artifacts
|
||||||
|
- name: 'Install boto3'
|
||||||
|
shell: bash
|
||||||
|
run: pip install boto3
|
||||||
|
- name: 'Generate files'
|
||||||
|
shell: bash
|
||||||
|
run: version=`cat version.txt` && python Buildscripts/CDN/generate-firmware-files.py artifacts artifacts-cdn $version
|
||||||
|
- name: 'Upload files'
|
||||||
|
shell: bash
|
||||||
|
run: python Buildscripts/CDN/upload-firmware-files.py artifacts-cdn ${{ inputs.cdn_version }} ${{ env.CDN_ID }} ${{ env.CDN_TOKEN_NAME }} ${{ env.CDN_TOKEN_VALUE }}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
name: Publish SDK
|
||||||
|
|
||||||
|
runs:
|
||||||
|
using: 'composite'
|
||||||
|
steps:
|
||||||
|
- name: 'Download all-artifacts'
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: 'all-artifacts'
|
||||||
|
path: artifacts
|
||||||
|
- name: 'Install boto3'
|
||||||
|
shell: bash
|
||||||
|
run: pip install boto3
|
||||||
|
- name: 'Generate files'
|
||||||
|
shell: bash
|
||||||
|
run: version=`cat version.txt` && python Buildscripts/CDN/generate-sdk-files.py artifacts artifacts-cdn $version
|
||||||
|
- name: 'Upload files'
|
||||||
|
shell: bash
|
||||||
|
run: version=`cat version.txt` && python Buildscripts/CDN/upload-sdk-files.py artifacts-cdn $version ${{ env.CDN_ID }} ${{ env.CDN_TOKEN_NAME }} ${{ env.CDN_TOKEN_VALUE }}
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
name: Build Firmware
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
pull_request:
|
|
||||||
types: [opened, synchronize, reopened]
|
|
||||||
|
|
||||||
permissions: read-all
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
cyd-2432S024c:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: "Build"
|
|
||||||
uses: ./.github/actions/build-firmware
|
|
||||||
with:
|
|
||||||
board_id: cyd-2432S024c
|
|
||||||
arch: esp32
|
|
||||||
lilygo-tdeck:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: "Build"
|
|
||||||
uses: ./.github/actions/build-firmware
|
|
||||||
with:
|
|
||||||
board_id: lilygo-tdeck
|
|
||||||
arch: esp32s3
|
|
||||||
m5stack-core2:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: "Build"
|
|
||||||
uses: ./.github/actions/build-firmware
|
|
||||||
with:
|
|
||||||
board_id: m5stack-core2
|
|
||||||
arch: esp32
|
|
||||||
m5stack-cores3:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: "Build"
|
|
||||||
uses: ./.github/actions/build-firmware
|
|
||||||
with:
|
|
||||||
board_id: m5stack-cores3
|
|
||||||
arch: esp32s3
|
|
||||||
unphone:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: "Build"
|
|
||||||
uses: ./.github/actions/build-firmware
|
|
||||||
with:
|
|
||||||
board_id: unphone
|
|
||||||
arch: esp32s3
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
name: Build SDK
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
pull_request:
|
|
||||||
types: [opened, synchronize, reopened]
|
|
||||||
|
|
||||||
permissions: read-all
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
esp32:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: "Build"
|
|
||||||
uses: ./.github/actions/build-sdk
|
|
||||||
with:
|
|
||||||
board_id: cyd-2432S024c
|
|
||||||
arch: esp32
|
|
||||||
esp32s3:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: "Build"
|
|
||||||
uses: ./.github/actions/build-sdk
|
|
||||||
with:
|
|
||||||
board_id: lilygo-tdeck
|
|
||||||
arch: esp32s3
|
|
||||||
@@ -7,20 +7,24 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
types: [ opened, synchronize, reopened ]
|
types: [ opened, synchronize, reopened ]
|
||||||
jobs:
|
jobs:
|
||||||
Build-Simulator-Linux:
|
Linux:
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-24.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
- name: "Build"
|
- name: "Build"
|
||||||
uses: ./.github/actions/build-simulator
|
uses: ./.github/actions/build-simulator
|
||||||
with:
|
with:
|
||||||
os_name: linux
|
os_name: linux
|
||||||
platform_name: amd64
|
platform_name: amd64
|
||||||
publish: true
|
publish: true
|
||||||
Build-Simulator-macOS:
|
macOS:
|
||||||
runs-on: macos-latest
|
runs-on: macos-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
- name: "Build"
|
- name: "Build"
|
||||||
uses: ./.github/actions/build-simulator
|
uses: ./.github/actions/build-simulator
|
||||||
with:
|
with:
|
||||||
|
|||||||
@@ -0,0 +1,109 @@
|
|||||||
|
name: Build Firmware
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
tags:
|
||||||
|
- v*
|
||||||
|
pull_request:
|
||||||
|
types: [ opened, synchronize, reopened ]
|
||||||
|
|
||||||
|
permissions: read-all
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
BuildSdk:
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
board: [
|
||||||
|
{ id: generic-esp32, arch: esp32 },
|
||||||
|
{ id: generic-esp32c6, arch: esp32c6 },
|
||||||
|
{ id: generic-esp32p4, arch: esp32p4 },
|
||||||
|
{ id: generic-esp32s3, arch: esp32s3 },
|
||||||
|
]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v6
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
|
- name: "Build SDK"
|
||||||
|
uses: ./.github/actions/build-sdk
|
||||||
|
with:
|
||||||
|
board_id: ${{ matrix.board.id }}
|
||||||
|
arch: ${{ matrix.board.arch }}
|
||||||
|
GenerateDeviceMatrix:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [ BuildSdk ]
|
||||||
|
outputs:
|
||||||
|
matrix: ${{ steps.set-matrix.outputs.matrix }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v6
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
|
- id: set-matrix
|
||||||
|
run: python3 Buildscripts/gh-generate-device-matrix.py
|
||||||
|
BuildFirmware:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: GenerateDeviceMatrix
|
||||||
|
strategy:
|
||||||
|
matrix: ${{ fromJSON(needs.GenerateDeviceMatrix.outputs.matrix) }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v6
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
|
- name: "Build Firmware"
|
||||||
|
uses: ./.github/actions/build-firmware
|
||||||
|
with:
|
||||||
|
board_id: ${{ matrix.board.id }}
|
||||||
|
arch: ${{ matrix.board.arch }}
|
||||||
|
BundleArtifacts:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [ BuildFirmware ]
|
||||||
|
if: |
|
||||||
|
(github.event_name == 'push' && github.ref == 'refs/heads/main') ||
|
||||||
|
(github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v'))
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v6
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
|
- name: "Bundle Artifacts"
|
||||||
|
uses: ./.github/actions/bundle-artifacts
|
||||||
|
PublishFirmwareSnapshot:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [ BundleArtifacts ]
|
||||||
|
if: (github.event_name == 'push' && github.ref == 'refs/heads/main')
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v6
|
||||||
|
- name: "Publish Firmware Snapshot"
|
||||||
|
env:
|
||||||
|
CDN_ID: ${{ secrets.CDN_ID }}
|
||||||
|
CDN_TOKEN_NAME: ${{ secrets.CDN_TOKEN_NAME }}
|
||||||
|
CDN_TOKEN_VALUE: ${{ secrets.CDN_TOKEN_VALUE }}
|
||||||
|
uses: ./.github/actions/publish-firmware
|
||||||
|
with:
|
||||||
|
cdn_version: snapshot
|
||||||
|
PublishFirmwareStable:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [ BundleArtifacts ]
|
||||||
|
if: (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v'))
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v6
|
||||||
|
- name: "Publish Firmware Stable"
|
||||||
|
env:
|
||||||
|
CDN_ID: ${{ secrets.CDN_ID }}
|
||||||
|
CDN_TOKEN_NAME: ${{ secrets.CDN_TOKEN_NAME }}
|
||||||
|
CDN_TOKEN_VALUE: ${{ secrets.CDN_TOKEN_VALUE }}
|
||||||
|
uses: ./.github/actions/publish-firmware
|
||||||
|
with:
|
||||||
|
cdn_version: stable
|
||||||
|
PublishSdk:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [ BundleArtifacts ]
|
||||||
|
if: (github.event_name == 'push' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')))
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v6
|
||||||
|
- name: "Publish SDKs"
|
||||||
|
env:
|
||||||
|
CDN_ID: ${{ secrets.CDN_ID }}
|
||||||
|
CDN_TOKEN_NAME: ${{ secrets.CDN_TOKEN_NAME }}
|
||||||
|
CDN_TOKEN_VALUE: ${{ secrets.CDN_TOKEN_VALUE }}
|
||||||
|
uses: ./.github/actions/publish-sdk
|
||||||
@@ -6,11 +6,11 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
types: [ opened, synchronize, reopened ]
|
types: [ opened, synchronize, reopened ]
|
||||||
jobs:
|
jobs:
|
||||||
Run:
|
TactilityTests:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: "Checkout repo"
|
- name: "Checkout repo"
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
- name: "Configure Project"
|
- name: "Configure Project"
|
||||||
@@ -19,5 +19,25 @@ jobs:
|
|||||||
run: cmake -S ./ -B build
|
run: cmake -S ./ -B build
|
||||||
- name: "Build Tests"
|
- name: "Build Tests"
|
||||||
run: cmake --build build --target build-tests
|
run: cmake --build build --target build-tests
|
||||||
- name: "Run Tests"
|
- name: "Run TactilityFreeRtos Tests"
|
||||||
run: build/Tests/TactilityCore/TactilityCoreTests --exit
|
run: build/Tests/TactilityFreeRtos/TactilityFreeRtosTests
|
||||||
|
- name: "Run Tactility Tests"
|
||||||
|
run: build/Tests/Tactility/TactilityTests
|
||||||
|
- name: "Run TactilityKernel Tests"
|
||||||
|
run: build/Tests/TactilityKernel/TactilityKernelTests
|
||||||
|
- name: "Run CryptModuleTests Tests"
|
||||||
|
run: build/Tests/crypt-module/CryptModuleTests
|
||||||
|
DevicetreeTests:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v6
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
|
submodules: recursive
|
||||||
|
- name: "Install Python Dependencies"
|
||||||
|
shell: bash
|
||||||
|
run: pip install lark==1.3.1 pyyaml==6.0.3
|
||||||
|
- name: "Run Devicetree Tests"
|
||||||
|
shell: bash
|
||||||
|
working-directory: Buildscripts/DevicetreeCompiler/tests
|
||||||
|
run: python test_integration.py
|
||||||
|
|||||||
+13
-2
@@ -3,10 +3,11 @@
|
|||||||
|
|
||||||
build/
|
build/
|
||||||
buildsim/
|
buildsim/
|
||||||
build-sim/
|
build-*/
|
||||||
cmake-build-*/
|
cmake-*/
|
||||||
CMakeCache.txt
|
CMakeCache.txt
|
||||||
*.cbp
|
*.cbp
|
||||||
|
CMakeFiles
|
||||||
|
|
||||||
release/
|
release/
|
||||||
|
|
||||||
@@ -16,3 +17,13 @@ sdkconfig.old
|
|||||||
managed_components/
|
managed_components/
|
||||||
dependencies.lock
|
dependencies.lock
|
||||||
|
|
||||||
|
.vscode/
|
||||||
|
*.code-workspace
|
||||||
|
.gitpod.yml
|
||||||
|
|
||||||
|
sdkconfig.board.*.dev
|
||||||
|
|
||||||
|
.tactility/
|
||||||
|
|
||||||
|
.caveman.json
|
||||||
|
.ai/mcp
|
||||||
@@ -10,3 +10,9 @@
|
|||||||
[submodule "Libraries/SDL"]
|
[submodule "Libraries/SDL"]
|
||||||
path = Libraries/SDL
|
path = Libraries/SDL
|
||||||
url = https://github.com/libsdl-org/SDL.git
|
url = https://github.com/libsdl-org/SDL.git
|
||||||
|
[submodule "Libraries/minitar/minitar"]
|
||||||
|
path = Libraries/minitar/minitar
|
||||||
|
url = https://github.com/ByteWelder/minitar.git
|
||||||
|
[submodule "Libraries/cJSON/cJSON"]
|
||||||
|
path = Libraries/cJSON/cJSON
|
||||||
|
url = https://github.com/DaveGamble/cJSON.git
|
||||||
|
|||||||
@@ -1,40 +0,0 @@
|
|||||||
cmake_minimum_required(VERSION 3.20)
|
|
||||||
|
|
||||||
if (DEFINED ENV{ESP_IDF_VERSION})
|
|
||||||
set(BOARD_COMPONENTS Tactility TactilityC)
|
|
||||||
|
|
||||||
if("${IDF_TARGET}" STREQUAL "esp32")
|
|
||||||
list(APPEND BOARD_COMPONENTS
|
|
||||||
CYD-2432S024C
|
|
||||||
M5stackCore2
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if("${IDF_TARGET}" STREQUAL "esp32s3")
|
|
||||||
list(APPEND BOARD_COMPONENTS
|
|
||||||
LilygoTdeck
|
|
||||||
M5stackCoreS3
|
|
||||||
UnPhone
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
idf_component_register(
|
|
||||||
SRC_DIRS "Source"
|
|
||||||
"Source/HelloWorld"
|
|
||||||
REQUIRES ${BOARD_COMPONENTS}
|
|
||||||
)
|
|
||||||
else()
|
|
||||||
|
|
||||||
file(GLOB_RECURSE SOURCES "Source/*.c*")
|
|
||||||
add_executable(AppSim ${SOURCES})
|
|
||||||
target_link_libraries(AppSim
|
|
||||||
PRIVATE Tactility
|
|
||||||
PRIVATE TactilityCore
|
|
||||||
PRIVATE TactilityHeadless
|
|
||||||
PRIVATE Simulator
|
|
||||||
PRIVATE SDL2::SDL2-static SDL2-static
|
|
||||||
)
|
|
||||||
|
|
||||||
add_definitions(-D_Nullable=)
|
|
||||||
add_definitions(-D_Nonnull=)
|
|
||||||
endif()
|
|
||||||
-36
@@ -1,36 +0,0 @@
|
|||||||
# Kconfig file for Tactility example app
|
|
||||||
menu "Tactility App"
|
|
||||||
config TT_BOARD_NAME
|
|
||||||
string "Board Name"
|
|
||||||
default ""
|
|
||||||
config TT_BOARD_ID
|
|
||||||
string "Board ID"
|
|
||||||
default ""
|
|
||||||
choice
|
|
||||||
prompt "Board"
|
|
||||||
default TT_BOARD_CUSTOM
|
|
||||||
config TT_BOARD_CUSTOM
|
|
||||||
bool "Custom"
|
|
||||||
config TT_BOARD_CYD_2432S024C
|
|
||||||
bool "CYD 2432S024C"
|
|
||||||
config TT_BOARD_LILYGO_TDECK
|
|
||||||
bool "LilyGo T-Deck"
|
|
||||||
config TT_BOARD_M5STACK_CORE2
|
|
||||||
bool "M5Stack Core2"
|
|
||||||
config TT_BOARD_M5STACK_CORES3
|
|
||||||
bool "M5Stack CoreS3"
|
|
||||||
config TT_BOARD_UNPHONE
|
|
||||||
bool "unPhone"
|
|
||||||
help
|
|
||||||
Select a board/hardware configuration.
|
|
||||||
Use TT_BOARD_CUSTOM if you will manually configure the board in your project.
|
|
||||||
endchoice
|
|
||||||
|
|
||||||
config TT_SPLASH_DURATION
|
|
||||||
int "Splash Duration (ms)"
|
|
||||||
default 1500
|
|
||||||
range 0 3000
|
|
||||||
help
|
|
||||||
The minimum time to show the splash screen in milliseconds.
|
|
||||||
When set to 0, startup will continue to desktop as soon as boot operations are finished.
|
|
||||||
endmenu
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#ifdef ESP_PLATFORM
|
|
||||||
#include "sdkconfig.h"
|
|
||||||
|
|
||||||
// Supported hardware:
|
|
||||||
#if defined(CONFIG_TT_BOARD_LILYGO_TDECK)
|
|
||||||
#include "LilygoTdeck.h"
|
|
||||||
#define TT_BOARD_HARDWARE &lilygo_tdeck
|
|
||||||
#elif defined(CONFIG_TT_BOARD_CYD_2432S024C)
|
|
||||||
#include "CYD2432S024C.h"
|
|
||||||
#define TT_BOARD_HARDWARE &cyd_2432S024c_config
|
|
||||||
#elif defined(CONFIG_TT_BOARD_M5STACK_CORE2)
|
|
||||||
#include "M5stackCore2.h"
|
|
||||||
#define TT_BOARD_HARDWARE &m5stack_core2
|
|
||||||
#elif defined(CONFIG_TT_BOARD_M5STACK_CORES3)
|
|
||||||
#include "M5stackCoreS3.h"
|
|
||||||
#define TT_BOARD_HARDWARE &m5stack_cores3
|
|
||||||
#elif defined(CONFIG_TT_BOARD_UNPHONE)
|
|
||||||
#include "UnPhone.h"
|
|
||||||
#define TT_BOARD_HARDWARE &unPhone
|
|
||||||
#else
|
|
||||||
#define TT_BOARD_HARDWARE NULL
|
|
||||||
#error Replace TT_BOARD_HARDWARE in main.c with your own. Or copy one of the ./sdkconfig.board.* files into ./sdkconfig.
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#else // else simulator
|
|
||||||
|
|
||||||
#include "Simulator.h"
|
|
||||||
|
|
||||||
extern tt::hal::Configuration hardware;
|
|
||||||
#define TT_BOARD_HARDWARE &hardware
|
|
||||||
|
|
||||||
#endif // ESP_PLATFORM
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
#include "app/AppManifest.h"
|
|
||||||
#include "lvgl.h"
|
|
||||||
#include "lvgl/Toolbar.h"
|
|
||||||
|
|
||||||
using namespace tt::app;
|
|
||||||
|
|
||||||
class HelloWorldApp : public App {
|
|
||||||
|
|
||||||
void onShow(AppContext& context, lv_obj_t* parent) override {
|
|
||||||
lv_obj_t* toolbar = tt::lvgl::toolbar_create(parent, context);
|
|
||||||
lv_obj_align(toolbar, LV_ALIGN_TOP_MID, 0, 0);
|
|
||||||
|
|
||||||
lv_obj_t* label = lv_label_create(parent);
|
|
||||||
lv_label_set_text(label, "Hello, world!");
|
|
||||||
lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
extern const AppManifest hello_world_app = {
|
|
||||||
.id = "HelloWorld",
|
|
||||||
.name = "Hello World",
|
|
||||||
.createApp = create<HelloWorldApp>
|
|
||||||
};
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
#include "Boards.h"
|
|
||||||
#include "Tactility.h"
|
|
||||||
|
|
||||||
#ifdef ESP_PLATFORM
|
|
||||||
#include "tt_init.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern const tt::app::AppManifest hello_world_app;
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
|
|
||||||
void app_main() {
|
|
||||||
static const tt::Configuration config = {
|
|
||||||
/**
|
|
||||||
* Auto-select a board based on the ./sdkconfig.board.* file
|
|
||||||
* that you copied to ./sdkconfig before you opened this project.
|
|
||||||
*/
|
|
||||||
.hardware = TT_BOARD_HARDWARE,
|
|
||||||
.apps = {
|
|
||||||
&hello_world_app,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef ESP_PLATFORM
|
|
||||||
tt_init_tactility_c(); // ELF bindings for side-loading on ESP32
|
|
||||||
#endif
|
|
||||||
|
|
||||||
tt::run(config);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // extern
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
dependencies:
|
|
||||||
espressif/esp_lcd_ili9341: "2.0.0"
|
|
||||||
espressif/esp_lcd_touch: "1.1.2"
|
|
||||||
atanisoft/esp_lcd_touch_xpt2046: "1.0.5"
|
|
||||||
espressif/esp_lcd_touch_cst816s: "1.0.3"
|
|
||||||
espressif/esp_lcd_touch_gt911: "1.1.1~2"
|
|
||||||
espressif/esp_lcd_touch_ft5x06: "1.0.6~1"
|
|
||||||
espressif/esp_io_expander: "1.0.1"
|
|
||||||
espressif/esp_io_expander_tca95xx_16bit: "1.0.1"
|
|
||||||
espressif/esp_tinyusb:
|
|
||||||
version: "1.5.0"
|
|
||||||
rules:
|
|
||||||
- if: "target == esp32s3"
|
|
||||||
idf: '5.4'
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
idf_component_register(
|
|
||||||
SRC_DIRS "Source" "Source/hal"
|
|
||||||
INCLUDE_DIRS "Source"
|
|
||||||
REQUIRES Tactility esp_lvgl_port esp_lcd_touch_cst816s esp_lcd_ili9341 driver vfs fatfs
|
|
||||||
)
|
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
#include "YellowConfig.h"
|
|
||||||
#include "TactilityCore.h"
|
|
||||||
#include "hal/YellowTouchConstants.h"
|
|
||||||
#include <driver/spi_common.h>
|
|
||||||
|
|
||||||
#define TAG "twodotfour_bootstrap"
|
|
||||||
|
|
||||||
static bool init_i2c() {
|
|
||||||
TT_LOG_I(TAG, LOG_MESSAGE_I2C_INIT_START);
|
|
||||||
|
|
||||||
const i2c_config_t i2c_conf = {
|
|
||||||
.mode = I2C_MODE_MASTER,
|
|
||||||
.sda_io_num = GPIO_NUM_33,
|
|
||||||
.scl_io_num = GPIO_NUM_32,
|
|
||||||
.sda_pullup_en = false,
|
|
||||||
.scl_pullup_en = false,
|
|
||||||
.master = {
|
|
||||||
.clk_speed = 400000
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (i2c_param_config(TWODOTFOUR_TOUCH_I2C_PORT, &i2c_conf) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, LOG_MESSAGE_I2C_INIT_CONFIG_FAILED );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i2c_driver_install(TWODOTFOUR_TOUCH_I2C_PORT, i2c_conf.mode, 0, 0, 0) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, LOG_MESSAGE_I2C_INIT_DRIVER_INSTALL_FAILED);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool init_spi2() {
|
|
||||||
TT_LOG_I(TAG, LOG_MESSAGE_SPI_INIT_START_FMT, SPI2_HOST);
|
|
||||||
|
|
||||||
const spi_bus_config_t bus_config = {
|
|
||||||
.mosi_io_num = TWODOTFOUR_SPI2_PIN_MOSI,
|
|
||||||
.miso_io_num = GPIO_NUM_NC,
|
|
||||||
.sclk_io_num = TWODOTFOUR_SPI2_PIN_SCLK,
|
|
||||||
.quadwp_io_num = GPIO_NUM_NC,
|
|
||||||
.quadhd_io_num = GPIO_NUM_NC,
|
|
||||||
.max_transfer_sz = TWODOTFOUR_SPI2_TRANSACTION_LIMIT
|
|
||||||
};
|
|
||||||
|
|
||||||
if (spi_bus_initialize(SPI2_HOST, &bus_config, SPI_DMA_CH_AUTO) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, LOG_MESSAGE_SPI_INIT_FAILED_FMT, SPI2_HOST);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool init_spi3() {
|
|
||||||
TT_LOG_I(TAG, LOG_MESSAGE_SPI_INIT_START_FMT, SPI3_HOST);
|
|
||||||
|
|
||||||
const spi_bus_config_t bus_config = {
|
|
||||||
.mosi_io_num = TWODOTFOUR_SPI3_PIN_MOSI,
|
|
||||||
.miso_io_num = TWODOTFOUR_SPI3_PIN_MISO,
|
|
||||||
.sclk_io_num = TWODOTFOUR_SPI3_PIN_SCLK,
|
|
||||||
.quadwp_io_num = GPIO_NUM_NC,
|
|
||||||
.quadhd_io_num = GPIO_NUM_NC,
|
|
||||||
.data4_io_num = 0,
|
|
||||||
.data5_io_num = 0,
|
|
||||||
.data6_io_num = 0,
|
|
||||||
.data7_io_num = 0,
|
|
||||||
.max_transfer_sz = TWODOTFOUR_SPI3_TRANSACTION_LIMIT,
|
|
||||||
.flags = 0,
|
|
||||||
.isr_cpu_id = ESP_INTR_CPU_AFFINITY_AUTO,
|
|
||||||
.intr_flags = 0
|
|
||||||
};
|
|
||||||
|
|
||||||
if (spi_bus_initialize(SPI3_HOST, &bus_config, SPI_DMA_CH_AUTO) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, LOG_MESSAGE_SPI_INIT_FAILED_FMT, SPI3_HOST);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool twodotfour_boot() {
|
|
||||||
return init_i2c() && init_spi2() && init_spi3();
|
|
||||||
}
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
#include "CYD2432S024C.h"
|
|
||||||
#include "hal/YellowDisplay.h"
|
|
||||||
#include "hal/YellowSdCard.h"
|
|
||||||
|
|
||||||
bool twodotfour_lvgl_init();
|
|
||||||
bool twodotfour_boot();
|
|
||||||
|
|
||||||
const tt::hal::Configuration cyd_2432S024c_config = {
|
|
||||||
.initBoot = &twodotfour_boot,
|
|
||||||
.initLvgl = &twodotfour_lvgl_init,
|
|
||||||
.createDisplay = createDisplay,
|
|
||||||
.sdcard = createYellowSdCard(),
|
|
||||||
.power = nullptr,
|
|
||||||
.i2c = {
|
|
||||||
tt::hal::i2c::Configuration {
|
|
||||||
.name = "First",
|
|
||||||
.port = I2C_NUM_0,
|
|
||||||
.initMode = tt::hal::i2c::InitMode::Disabled,
|
|
||||||
.canReinit = true,
|
|
||||||
.hasMutableConfiguration = true,
|
|
||||||
.config = (i2c_config_t) {
|
|
||||||
.mode = I2C_MODE_MASTER,
|
|
||||||
.sda_io_num = GPIO_NUM_NC,
|
|
||||||
.scl_io_num = GPIO_NUM_NC,
|
|
||||||
.sda_pullup_en = false,
|
|
||||||
.scl_pullup_en = false,
|
|
||||||
.master = {
|
|
||||||
.clk_speed = 400000
|
|
||||||
},
|
|
||||||
.clk_flags = 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
tt::hal::i2c::Configuration {
|
|
||||||
.name = "Second",
|
|
||||||
.port = I2C_NUM_1,
|
|
||||||
.initMode = tt::hal::i2c::InitMode::Disabled,
|
|
||||||
.canReinit = true,
|
|
||||||
.hasMutableConfiguration = true,
|
|
||||||
.config = (i2c_config_t) {
|
|
||||||
.mode = I2C_MODE_MASTER,
|
|
||||||
.sda_io_num = GPIO_NUM_NC,
|
|
||||||
.scl_io_num = GPIO_NUM_NC,
|
|
||||||
.sda_pullup_en = false,
|
|
||||||
.scl_pullup_en = false,
|
|
||||||
.master = {
|
|
||||||
.clk_speed = 400000
|
|
||||||
},
|
|
||||||
.clk_flags = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "hal/Configuration.h"
|
|
||||||
|
|
||||||
// Capacitive touch version of the 2.4" yellow board
|
|
||||||
extern const tt::hal::Configuration cyd_2432S024c_config;
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
#include "esp_lvgl_port.h"
|
|
||||||
#include "Log.h"
|
|
||||||
#include "lvgl/LvglSync.h"
|
|
||||||
#include "Thread.h"
|
|
||||||
|
|
||||||
#define TAG "twodotfour_lvgl"
|
|
||||||
|
|
||||||
bool twodotfour_lvgl_init() {
|
|
||||||
const lvgl_port_cfg_t lvgl_cfg = {
|
|
||||||
.task_priority = static_cast<UBaseType_t>(tt::THREAD_PRIORITY_RENDER),
|
|
||||||
.task_stack = 8096,
|
|
||||||
.task_affinity = -1, // core pinning
|
|
||||||
.task_max_sleep_ms = 500,
|
|
||||||
.timer_period_ms = 5
|
|
||||||
};
|
|
||||||
|
|
||||||
if (lvgl_port_init(&lvgl_cfg) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, "lvgl port init failed");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set syncing functions
|
|
||||||
tt::lvgl::syncSet(&lvgl_port_lock, &lvgl_port_unlock);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "driver/spi_common.h"
|
|
||||||
#include "driver/i2c.h"
|
|
||||||
#include "driver/gpio.h"
|
|
||||||
#include "hal/YellowDisplayConstants.h"
|
|
||||||
|
|
||||||
// SPI 2 - display
|
|
||||||
#define TWODOTFOUR_SPI2_PIN_SCLK GPIO_NUM_14
|
|
||||||
#define TWODOTFOUR_SPI2_PIN_MOSI GPIO_NUM_13
|
|
||||||
#define TWODOTFOUR_SPI2_TRANSACTION_LIMIT TWODOTFOUR_LCD_DRAW_BUFFER_SIZE
|
|
||||||
|
|
||||||
// SPI 3 - sdcard
|
|
||||||
#define TWODOTFOUR_SPI3_PIN_SCLK GPIO_NUM_18
|
|
||||||
#define TWODOTFOUR_SPI3_PIN_MOSI GPIO_NUM_23
|
|
||||||
#define TWODOTFOUR_SPI3_PIN_MISO GPIO_NUM_19
|
|
||||||
#define TWODOTFOUR_SPI3_TRANSACTION_LIMIT 8192 // TODO: Determine proper limit
|
|
||||||
@@ -1,214 +0,0 @@
|
|||||||
#include "YellowDisplay.h"
|
|
||||||
#include "YellowDisplayConstants.h"
|
|
||||||
#include "YellowTouch.h"
|
|
||||||
#include "Log.h"
|
|
||||||
|
|
||||||
#include <TactilityCore.h>
|
|
||||||
#include <esp_lcd_panel_commands.h>
|
|
||||||
|
|
||||||
#include "driver/gpio.h"
|
|
||||||
#include "driver/ledc.h"
|
|
||||||
#include "esp_err.h"
|
|
||||||
#include "esp_lcd_ili9341.h"
|
|
||||||
#include "esp_lcd_panel_ops.h"
|
|
||||||
#include "esp_lvgl_port.h"
|
|
||||||
|
|
||||||
#define TAG "yellow_display"
|
|
||||||
|
|
||||||
static bool isBacklightInitialized = false;
|
|
||||||
|
|
||||||
static bool initBacklight() {
|
|
||||||
ledc_timer_config_t ledc_timer = {
|
|
||||||
.speed_mode = TWODOTFOUR_LCD_BACKLIGHT_LEDC_MODE,
|
|
||||||
.duty_resolution = TWODOTFOUR_LCD_BACKLIGHT_LEDC_DUTY_RES,
|
|
||||||
.timer_num = TWODOTFOUR_LCD_BACKLIGHT_LEDC_TIMER,
|
|
||||||
.freq_hz = TWODOTFOUR_LCD_BACKLIGHT_LEDC_FREQUENCY,
|
|
||||||
.clk_cfg = LEDC_AUTO_CLK,
|
|
||||||
.deconfigure = false
|
|
||||||
};
|
|
||||||
|
|
||||||
if (ledc_timer_config(&ledc_timer) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, "Backlight led timer config failed");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool setBacklight(uint8_t duty) {
|
|
||||||
ledc_channel_config_t ledc_channel = {
|
|
||||||
.gpio_num = TWODOTFOUR_LCD_PIN_BACKLIGHT,
|
|
||||||
.speed_mode = TWODOTFOUR_LCD_BACKLIGHT_LEDC_MODE,
|
|
||||||
.channel = TWODOTFOUR_LCD_BACKLIGHT_LEDC_CHANNEL,
|
|
||||||
.intr_type = LEDC_INTR_DISABLE,
|
|
||||||
.timer_sel = TWODOTFOUR_LCD_BACKLIGHT_LEDC_TIMER,
|
|
||||||
.duty = duty,
|
|
||||||
.hpoint = 0,
|
|
||||||
.sleep_mode = LEDC_SLEEP_MODE_NO_ALIVE_NO_PD,
|
|
||||||
.flags = {
|
|
||||||
.output_invert = false
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (ledc_channel_config(&ledc_channel) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, "Backlight init failed");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool YellowDisplay::start() {
|
|
||||||
TT_LOG_I(TAG, "Starting");
|
|
||||||
|
|
||||||
const esp_lcd_panel_io_spi_config_t panel_io_config = ILI9341_PANEL_IO_SPI_CONFIG(
|
|
||||||
TWODOTFOUR_LCD_PIN_CS,
|
|
||||||
TWODOTFOUR_LCD_PIN_DC,
|
|
||||||
nullptr,
|
|
||||||
nullptr
|
|
||||||
);
|
|
||||||
|
|
||||||
if (esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)TWODOTFOUR_LCD_SPI_HOST, &panel_io_config, &ioHandle) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, "Failed to create panel");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const esp_lcd_panel_dev_config_t panel_config = {
|
|
||||||
.reset_gpio_num = GPIO_NUM_NC,
|
|
||||||
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_BGR,
|
|
||||||
.data_endian = LCD_RGB_DATA_ENDIAN_LITTLE,
|
|
||||||
.bits_per_pixel = TWODOTFOUR_LCD_BITS_PER_PIXEL,
|
|
||||||
.flags = {
|
|
||||||
.reset_active_high = false
|
|
||||||
},
|
|
||||||
.vendor_config = nullptr
|
|
||||||
};
|
|
||||||
|
|
||||||
if (esp_lcd_new_panel_ili9341(ioHandle, &panel_config, &panelHandle) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, "Failed to create ili9341");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (esp_lcd_panel_reset(panelHandle) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, "Failed to reset panel");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (esp_lcd_panel_init(panelHandle) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, "Failed to init panel");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (esp_lcd_panel_mirror(panelHandle, true, false) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, "Failed to set panel to mirror");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (esp_lcd_panel_disp_on_off(panelHandle, true) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, "Failed to turn display on");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const lvgl_port_display_cfg_t disp_cfg = {
|
|
||||||
.io_handle = ioHandle,
|
|
||||||
.panel_handle = panelHandle,
|
|
||||||
.control_handle = nullptr,
|
|
||||||
.buffer_size = TWODOTFOUR_LCD_DRAW_BUFFER_SIZE,
|
|
||||||
.double_buffer = false,
|
|
||||||
.trans_size = 0,
|
|
||||||
.hres = TWODOTFOUR_LCD_HORIZONTAL_RESOLUTION,
|
|
||||||
.vres = TWODOTFOUR_LCD_VERTICAL_RESOLUTION,
|
|
||||||
.monochrome = false,
|
|
||||||
.rotation = {
|
|
||||||
.swap_xy = false,
|
|
||||||
.mirror_x = true,
|
|
||||||
.mirror_y = false,
|
|
||||||
},
|
|
||||||
.color_format = LV_COLOR_FORMAT_RGB565,
|
|
||||||
.flags = {
|
|
||||||
.buff_dma = true,
|
|
||||||
.buff_spiram = false,
|
|
||||||
.sw_rotate = false,
|
|
||||||
.swap_bytes = true,
|
|
||||||
.full_refresh = false,
|
|
||||||
.direct_mode = false
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
displayHandle = lvgl_port_add_disp(&disp_cfg);
|
|
||||||
TT_LOG_I(TAG, "Finished");
|
|
||||||
return displayHandle != nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool YellowDisplay::stop() {
|
|
||||||
assert(displayHandle != nullptr);
|
|
||||||
|
|
||||||
lvgl_port_remove_disp(displayHandle);
|
|
||||||
|
|
||||||
if (esp_lcd_panel_del(panelHandle) != ESP_OK) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (esp_lcd_panel_io_del(ioHandle) != ESP_OK) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
displayHandle = nullptr;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void YellowDisplay::setBacklightDuty(uint8_t backlightDuty) {
|
|
||||||
if (!isBacklightInitialized) {
|
|
||||||
tt_check(initBacklight());
|
|
||||||
isBacklightInitialized = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!setBacklight(backlightDuty)) {
|
|
||||||
TT_LOG_E(TAG, "Failed to configure display backlight");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Note:
|
|
||||||
* The datasheet implies this should work, but it doesn't:
|
|
||||||
* https://www.digikey.com/htmldatasheets/production/1640716/0/0/1/ILI9341-Datasheet.pdf
|
|
||||||
*
|
|
||||||
* This repo claims it only has 1 curve:
|
|
||||||
* https://github.com/brucemack/hello-ili9341
|
|
||||||
*
|
|
||||||
* I'm leaving it in as I'm not sure if it's just my hardware that's problematic.
|
|
||||||
*/
|
|
||||||
void YellowDisplay::setGammaCurve(uint8_t index) {
|
|
||||||
uint8_t gamma_curve;
|
|
||||||
switch (index) {
|
|
||||||
case 0:
|
|
||||||
gamma_curve = 0x01;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
gamma_curve = 0x04;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
gamma_curve = 0x02;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
gamma_curve = 0x08;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const uint8_t param[] = {
|
|
||||||
gamma_curve
|
|
||||||
};
|
|
||||||
|
|
||||||
if (esp_lcd_panel_io_tx_param(ioHandle , LCD_CMD_GAMSET, param, 1) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, "Failed to set gamma");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tt::hal::Touch* _Nullable YellowDisplay::createTouch() {
|
|
||||||
return static_cast<tt::hal::Touch*>(new YellowTouch());
|
|
||||||
}
|
|
||||||
|
|
||||||
tt::hal::Display* createDisplay() {
|
|
||||||
return static_cast<tt::hal::Display*>(new YellowDisplay());
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "lvgl.h"
|
|
||||||
#include "hal/Display.h"
|
|
||||||
#include "esp_lcd_panel_io.h"
|
|
||||||
|
|
||||||
extern lv_disp_t* displayHandle;
|
|
||||||
|
|
||||||
class YellowDisplay : public tt::hal::Display {
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
esp_lcd_panel_io_handle_t ioHandle = nullptr;
|
|
||||||
esp_lcd_panel_handle_t panelHandle = nullptr;
|
|
||||||
lv_display_t* displayHandle = nullptr;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
bool start() override;
|
|
||||||
|
|
||||||
bool stop() override;
|
|
||||||
|
|
||||||
tt::hal::Touch* _Nullable createTouch() override;
|
|
||||||
|
|
||||||
void setBacklightDuty(uint8_t backlightDuty) override;
|
|
||||||
bool supportsBacklightDuty() const override { return true; }
|
|
||||||
|
|
||||||
void setGammaCurve(uint8_t index) override;
|
|
||||||
uint8_t getGammaCurveCount() const override { return 4; };
|
|
||||||
|
|
||||||
lv_display_t* _Nullable getLvglDisplay() const override { return displayHandle; }
|
|
||||||
};
|
|
||||||
|
|
||||||
tt::hal::Display* createDisplay();
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
// Display backlight (PWM)
|
|
||||||
#define TWODOTFOUR_LCD_BACKLIGHT_LEDC_TIMER LEDC_TIMER_0
|
|
||||||
#define TWODOTFOUR_LCD_BACKLIGHT_LEDC_MODE LEDC_LOW_SPEED_MODE
|
|
||||||
#define TWODOTFOUR_LCD_BACKLIGHT_LEDC_CHANNEL LEDC_CHANNEL_0
|
|
||||||
#define TWODOTFOUR_LCD_BACKLIGHT_LEDC_DUTY_RES LEDC_TIMER_8_BIT
|
|
||||||
#define TWODOTFOUR_LCD_BACKLIGHT_LEDC_FREQUENCY (1000)
|
|
||||||
|
|
||||||
#define TWODOTFOUR_LCD_PIN_BACKLIGHT GPIO_NUM_27
|
|
||||||
|
|
||||||
// Display
|
|
||||||
#define TWODOTFOUR_LCD_SPI_HOST SPI2_HOST
|
|
||||||
#define TWODOTFOUR_LCD_HORIZONTAL_RESOLUTION 240
|
|
||||||
#define TWODOTFOUR_LCD_VERTICAL_RESOLUTION 320
|
|
||||||
#define TWODOTFOUR_LCD_BITS_PER_PIXEL 16
|
|
||||||
#define TWODOTFOUR_LCD_DRAW_BUFFER_HEIGHT (TWODOTFOUR_LCD_VERTICAL_RESOLUTION / 10)
|
|
||||||
#define TWODOTFOUR_LCD_DRAW_BUFFER_SIZE (TWODOTFOUR_LCD_HORIZONTAL_RESOLUTION * TWODOTFOUR_LCD_DRAW_BUFFER_HEIGHT * (TWODOTFOUR_LCD_BITS_PER_PIXEL / 8))
|
|
||||||
#define TWODOTFOUR_LCD_PIN_CS GPIO_NUM_15
|
|
||||||
#define TWODOTFOUR_LCD_PIN_DC GPIO_NUM_2
|
|
||||||
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
#include "YellowSdCard.h"
|
|
||||||
|
|
||||||
#define TAG "twodotfour_sdcard"
|
|
||||||
|
|
||||||
#include "lvgl/LvglSync.h"
|
|
||||||
#include "hal/SpiSdCard.h"
|
|
||||||
|
|
||||||
#define SDCARD_SPI_HOST SPI3_HOST
|
|
||||||
#define SDCARD_PIN_CS GPIO_NUM_5
|
|
||||||
|
|
||||||
std::shared_ptr<SdCard> createYellowSdCard() {
|
|
||||||
auto* configuration = new tt::hal::SpiSdCard::Config(
|
|
||||||
SDCARD_PIN_CS,
|
|
||||||
GPIO_NUM_NC,
|
|
||||||
GPIO_NUM_NC,
|
|
||||||
GPIO_NUM_NC,
|
|
||||||
SdCard::MountBehaviour::AtBoot,
|
|
||||||
nullptr,
|
|
||||||
std::vector<gpio_num_t>(),
|
|
||||||
SDCARD_SPI_HOST
|
|
||||||
);
|
|
||||||
|
|
||||||
auto* sdcard = (SdCard*) new SpiSdCard(
|
|
||||||
std::unique_ptr<SpiSdCard::Config>(configuration)
|
|
||||||
);
|
|
||||||
|
|
||||||
return std::shared_ptr<SdCard>(sdcard);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "hal/SdCard.h"
|
|
||||||
|
|
||||||
using namespace tt::hal;
|
|
||||||
|
|
||||||
std::shared_ptr<SdCard> createYellowSdCard();
|
|
||||||
|
|
||||||
@@ -1,83 +0,0 @@
|
|||||||
#include "YellowTouch.h"
|
|
||||||
#include "YellowTouchConstants.h"
|
|
||||||
#include "Log.h"
|
|
||||||
#include "driver/i2c.h"
|
|
||||||
#include "esp_err.h"
|
|
||||||
#include "esp_lcd_touch_cst816s.h"
|
|
||||||
#include "esp_lcd_touch.h"
|
|
||||||
#include "esp_lvgl_port.h"
|
|
||||||
|
|
||||||
#define TAG "twodotfour_touch"
|
|
||||||
|
|
||||||
bool YellowTouch::start(lv_display_t* display) {
|
|
||||||
TT_LOG_I(TAG, "Starting");
|
|
||||||
const esp_lcd_panel_io_i2c_config_t touch_io_config = ESP_LCD_TOUCH_IO_I2C_CST816S_CONFIG();
|
|
||||||
|
|
||||||
if (esp_lcd_new_panel_io_i2c((esp_lcd_i2c_bus_handle_t)TWODOTFOUR_TOUCH_I2C_PORT, &touch_io_config, &ioHandle) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, "Touch I2C IO init failed");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_lcd_touch_config_t config = {
|
|
||||||
.x_max = 240,
|
|
||||||
.y_max = 320,
|
|
||||||
.rst_gpio_num = GPIO_NUM_NC, //GPIO_NUM_25,
|
|
||||||
.int_gpio_num = GPIO_NUM_NC, //GPIO_NUM_21,
|
|
||||||
.levels = {
|
|
||||||
.reset = 0,
|
|
||||||
.interrupt = 0,
|
|
||||||
},
|
|
||||||
.flags = {
|
|
||||||
.swap_xy = 0,
|
|
||||||
.mirror_x = 0,
|
|
||||||
.mirror_y = 0,
|
|
||||||
},
|
|
||||||
.process_coordinates = nullptr,
|
|
||||||
.interrupt_callback = nullptr,
|
|
||||||
.user_data = nullptr,
|
|
||||||
.driver_data = nullptr
|
|
||||||
};
|
|
||||||
|
|
||||||
if (esp_lcd_touch_new_i2c_cst816s(ioHandle, &config, &touchHandle) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, "Driver init failed");
|
|
||||||
cleanup();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const lvgl_port_touch_cfg_t touch_cfg = {
|
|
||||||
.disp = display,
|
|
||||||
.handle = touchHandle,
|
|
||||||
};
|
|
||||||
|
|
||||||
deviceHandle = lvgl_port_add_touch(&touch_cfg);
|
|
||||||
if (deviceHandle == nullptr) {
|
|
||||||
TT_LOG_E(TAG, "Adding touch failed");
|
|
||||||
cleanup();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
TT_LOG_I(TAG, "Finished");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool YellowTouch::stop() {
|
|
||||||
cleanup();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void YellowTouch::cleanup() {
|
|
||||||
if (deviceHandle != nullptr) {
|
|
||||||
lv_indev_delete(deviceHandle);
|
|
||||||
deviceHandle = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (touchHandle != nullptr) {
|
|
||||||
esp_lcd_touch_del(touchHandle);
|
|
||||||
touchHandle = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ioHandle != nullptr) {
|
|
||||||
esp_lcd_panel_io_del(ioHandle);
|
|
||||||
ioHandle = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "hal/Touch.h"
|
|
||||||
#include "TactilityCore.h"
|
|
||||||
#include <esp_lcd_touch.h>
|
|
||||||
|
|
||||||
class YellowTouch : public tt::hal::Touch {
|
|
||||||
private:
|
|
||||||
esp_lcd_panel_io_handle_t ioHandle = nullptr;
|
|
||||||
esp_lcd_touch_handle_t touchHandle = nullptr;
|
|
||||||
lv_indev_t* _Nullable deviceHandle = nullptr;
|
|
||||||
void cleanup();
|
|
||||||
public:
|
|
||||||
bool start(lv_display_t* display) override;
|
|
||||||
bool stop() override;
|
|
||||||
lv_indev_t* _Nullable getLvglIndev() override { return deviceHandle; }
|
|
||||||
};
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
// Touch
|
|
||||||
#define TWODOTFOUR_TOUCH_I2C_PORT I2C_NUM_0
|
|
||||||
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
idf_component_register(
|
|
||||||
SRC_DIRS "Source" "Source/hal"
|
|
||||||
INCLUDE_DIRS "Source"
|
|
||||||
REQUIRES Tactility esp_lvgl_port esp_lcd esp_lcd_touch_gt911 driver esp_adc
|
|
||||||
)
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
#include "TactilityCore.h"
|
|
||||||
#include "hal/TdeckDisplayConstants.h"
|
|
||||||
#include <driver/spi_common.h>
|
|
||||||
#include <soc/gpio_num.h>
|
|
||||||
|
|
||||||
#define TAG "tdeck"
|
|
||||||
|
|
||||||
// SPI
|
|
||||||
#define TDECK_SPI_HOST SPI2_HOST
|
|
||||||
#define TDECK_SPI_PIN_SCLK GPIO_NUM_40
|
|
||||||
#define TDECK_SPI_PIN_MOSI GPIO_NUM_41
|
|
||||||
#define TDECK_SPI_PIN_MISO GPIO_NUM_38
|
|
||||||
#define TDECK_SPI_TRANSFER_SIZE_LIMIT (TDECK_LCD_HORIZONTAL_RESOLUTION * TDECK_LCD_SPI_TRANSFER_HEIGHT * (TDECK_LCD_BITS_PER_PIXEL / 8))
|
|
||||||
|
|
||||||
#define TDECK_LCD_BACKLIGHT_LEDC_TIMER LEDC_TIMER_0
|
|
||||||
#define TDECK_LCD_BACKLIGHT_LEDC_MODE LEDC_LOW_SPEED_MODE
|
|
||||||
#define TDECK_LCD_BACKLIGHT_LEDC_CHANNEL LEDC_CHANNEL_0
|
|
||||||
#define TDECK_LCD_BACKLIGHT_LEDC_DUTY_RES LEDC_TIMER_8_BIT
|
|
||||||
#define TDECK_LCD_BACKLIGHT_LEDC_FREQUENCY (4000)
|
|
||||||
|
|
||||||
static bool init_spi() {
|
|
||||||
TT_LOG_I(TAG, LOG_MESSAGE_SPI_INIT_START_FMT, TDECK_SPI_HOST);
|
|
||||||
|
|
||||||
spi_bus_config_t bus_config = {
|
|
||||||
.mosi_io_num = TDECK_SPI_PIN_MOSI,
|
|
||||||
.miso_io_num = TDECK_SPI_PIN_MISO,
|
|
||||||
.sclk_io_num = TDECK_SPI_PIN_SCLK,
|
|
||||||
.quadwp_io_num = -1, // Quad SPI LCD driver is not yet supported
|
|
||||||
.quadhd_io_num = -1, // Quad SPI LCD driver is not yet supported
|
|
||||||
.data4_io_num = 0,
|
|
||||||
.data5_io_num = 0,
|
|
||||||
.data6_io_num = 0,
|
|
||||||
.data7_io_num = 0,
|
|
||||||
.data_io_default_level = false,
|
|
||||||
.max_transfer_sz = TDECK_SPI_TRANSFER_SIZE_LIMIT,
|
|
||||||
.flags = 0,
|
|
||||||
.isr_cpu_id = ESP_INTR_CPU_AFFINITY_AUTO,
|
|
||||||
.intr_flags = 0
|
|
||||||
};
|
|
||||||
|
|
||||||
if (spi_bus_initialize(TDECK_SPI_HOST, &bus_config, SPI_DMA_CH_AUTO) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, LOG_MESSAGE_SPI_INIT_FAILED_FMT, TDECK_SPI_HOST);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool tdeck_init_hardware() {
|
|
||||||
return init_spi();
|
|
||||||
}
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
#include "hal/Configuration.h"
|
|
||||||
#include "hal/TdeckDisplay.h"
|
|
||||||
#include "hal/TdeckKeyboard.h"
|
|
||||||
#include "hal/TdeckPower.h"
|
|
||||||
#include "hal/TdeckSdCard.h"
|
|
||||||
|
|
||||||
bool tdeck_init_power();
|
|
||||||
bool tdeck_init_hardware();
|
|
||||||
bool tdeck_init_lvgl();
|
|
||||||
|
|
||||||
extern const tt::hal::Configuration lilygo_tdeck = {
|
|
||||||
.initBoot = tdeck_init_power,
|
|
||||||
.initHardware = tdeck_init_hardware,
|
|
||||||
.initLvgl = tdeck_init_lvgl,
|
|
||||||
.createDisplay = createDisplay,
|
|
||||||
.createKeyboard = createKeyboard,
|
|
||||||
.sdcard = createTdeckSdCard(),
|
|
||||||
.power = tdeck_get_power,
|
|
||||||
.i2c = {
|
|
||||||
tt::hal::i2c::Configuration {
|
|
||||||
.name = "Internal",
|
|
||||||
.port = I2C_NUM_0,
|
|
||||||
.initMode = tt::hal::i2c::InitMode::ByTactility,
|
|
||||||
.canReinit = false,
|
|
||||||
.hasMutableConfiguration = false,
|
|
||||||
.config = (i2c_config_t) {
|
|
||||||
.mode = I2C_MODE_MASTER,
|
|
||||||
.sda_io_num = GPIO_NUM_18,
|
|
||||||
.scl_io_num = GPIO_NUM_8,
|
|
||||||
.sda_pullup_en = true,
|
|
||||||
.scl_pullup_en = true,
|
|
||||||
.master = {
|
|
||||||
.clk_speed = 400000
|
|
||||||
},
|
|
||||||
.clk_flags = 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
tt::hal::i2c::Configuration {
|
|
||||||
.name = "External",
|
|
||||||
.port = I2C_NUM_1,
|
|
||||||
.initMode = tt::hal::i2c::InitMode::ByTactility,
|
|
||||||
.canReinit = true,
|
|
||||||
.hasMutableConfiguration = true,
|
|
||||||
.config = (i2c_config_t) {
|
|
||||||
.mode = I2C_MODE_MASTER,
|
|
||||||
.sda_io_num = GPIO_NUM_43,
|
|
||||||
.scl_io_num = GPIO_NUM_44,
|
|
||||||
.sda_pullup_en = false,
|
|
||||||
.scl_pullup_en = false,
|
|
||||||
.master = {
|
|
||||||
.clk_speed = 400000
|
|
||||||
},
|
|
||||||
.clk_flags = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <hal/Configuration.h>
|
|
||||||
|
|
||||||
extern const tt::hal::Configuration lilygo_tdeck;
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
#include "Log.h"
|
|
||||||
#include "Thread.h"
|
|
||||||
#include "lvgl/LvglSync.h"
|
|
||||||
#include "esp_lvgl_port.h"
|
|
||||||
#include "hal/TdeckDisplay.h"
|
|
||||||
|
|
||||||
#define TAG "tdeck_lvgl"
|
|
||||||
|
|
||||||
// LVGL
|
|
||||||
// The minimum task stack seems to be about 3500, but that crashes the wifi app in some scenarios
|
|
||||||
// At 8192, it sometimes crashes when wifi-auto enables and is busy connecting and then you open WifiManage
|
|
||||||
#define TDECK_LVGL_TASK_STACK_DEPTH 9216
|
|
||||||
|
|
||||||
bool tdeck_init_lvgl() {
|
|
||||||
static lv_disp_t* display = nullptr;
|
|
||||||
const lvgl_port_cfg_t lvgl_cfg = {
|
|
||||||
.task_priority = static_cast<UBaseType_t>(tt::THREAD_PRIORITY_RENDER),
|
|
||||||
.task_stack = TDECK_LVGL_TASK_STACK_DEPTH,
|
|
||||||
.task_affinity = -1, // core pinning
|
|
||||||
.task_max_sleep_ms = 500,
|
|
||||||
.timer_period_ms = 5
|
|
||||||
};
|
|
||||||
|
|
||||||
TT_LOG_D(TAG, "LVGL port init");
|
|
||||||
if (lvgl_port_init(&lvgl_cfg) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, "LVGL port init failed");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
tt::lvgl::syncSet(&lvgl_port_lock, &lvgl_port_unlock);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
@@ -1,238 +0,0 @@
|
|||||||
#include "TdeckDisplay.h"
|
|
||||||
#include "TdeckDisplayConstants.h"
|
|
||||||
#include "TdeckTouch.h"
|
|
||||||
#include "Log.h"
|
|
||||||
|
|
||||||
#include <TactilityCore.h>
|
|
||||||
#include <esp_lcd_panel_commands.h>
|
|
||||||
|
|
||||||
#include "driver/ledc.h"
|
|
||||||
#include "driver/spi_master.h"
|
|
||||||
#include "esp_err.h"
|
|
||||||
#include "esp_lcd_panel_ops.h"
|
|
||||||
#include "esp_lcd_panel_vendor.h"
|
|
||||||
#include "esp_lvgl_port.h"
|
|
||||||
|
|
||||||
#define TAG "tdeck_display"
|
|
||||||
|
|
||||||
static bool isBacklightInitialized = false;
|
|
||||||
|
|
||||||
static bool initBacklight() {
|
|
||||||
TT_LOG_I(TAG, "Init backlight");
|
|
||||||
ledc_timer_config_t ledc_timer = {
|
|
||||||
.speed_mode = TDECK_LCD_BACKLIGHT_LEDC_MODE,
|
|
||||||
.duty_resolution = TDECK_LCD_BACKLIGHT_LEDC_DUTY_RES,
|
|
||||||
.timer_num = TDECK_LCD_BACKLIGHT_LEDC_TIMER,
|
|
||||||
.freq_hz = TDECK_LCD_BACKLIGHT_LEDC_FREQUENCY,
|
|
||||||
.clk_cfg = LEDC_AUTO_CLK,
|
|
||||||
.deconfigure = false
|
|
||||||
};
|
|
||||||
|
|
||||||
if (ledc_timer_config(&ledc_timer) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, "Backlight led timer config failed");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool setBacklight(uint8_t duty) {
|
|
||||||
ledc_channel_config_t ledc_channel = {
|
|
||||||
.gpio_num = TDECK_LCD_PIN_BACKLIGHT,
|
|
||||||
.speed_mode = TDECK_LCD_BACKLIGHT_LEDC_MODE,
|
|
||||||
.channel = TDECK_LCD_BACKLIGHT_LEDC_CHANNEL,
|
|
||||||
.intr_type = LEDC_INTR_DISABLE,
|
|
||||||
.timer_sel = TDECK_LCD_BACKLIGHT_LEDC_TIMER,
|
|
||||||
.duty = duty,
|
|
||||||
.hpoint = 0,
|
|
||||||
.sleep_mode = LEDC_SLEEP_MODE_NO_ALIVE_NO_PD,
|
|
||||||
.flags = {
|
|
||||||
.output_invert = 0
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Setting the config in the timer init and then calling ledc_set_duty() doesn't work when
|
|
||||||
// the app is running. For an unknown reason we have to call this config method every time:
|
|
||||||
return ledc_channel_config(&ledc_channel) == ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TdeckDisplay::start() {
|
|
||||||
TT_LOG_I(TAG, "Starting");
|
|
||||||
|
|
||||||
const esp_lcd_panel_io_spi_config_t panel_io_config = {
|
|
||||||
.cs_gpio_num = TDECK_LCD_PIN_CS,
|
|
||||||
.dc_gpio_num = TDECK_LCD_PIN_DC,
|
|
||||||
.spi_mode = 0,
|
|
||||||
.pclk_hz = TDECK_LCD_SPI_FREQUENCY,
|
|
||||||
.trans_queue_depth = 10,
|
|
||||||
.on_color_trans_done = nullptr,
|
|
||||||
.user_ctx = nullptr,
|
|
||||||
.lcd_cmd_bits = 8,
|
|
||||||
.lcd_param_bits = 8,
|
|
||||||
.cs_ena_pretrans = 0,
|
|
||||||
.cs_ena_posttrans = 0,
|
|
||||||
.flags = {
|
|
||||||
.dc_high_on_cmd = 0,
|
|
||||||
.dc_low_on_data = 0,
|
|
||||||
.dc_low_on_param = 0,
|
|
||||||
.octal_mode = 0,
|
|
||||||
.quad_mode = 0,
|
|
||||||
.sio_mode = 1,
|
|
||||||
.lsb_first = 0,
|
|
||||||
.cs_high_active = 0,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)TDECK_LCD_SPI_HOST, &panel_io_config, &ioHandle) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, "Failed to create panel IO");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const esp_lcd_panel_dev_config_t panel_config = {
|
|
||||||
.reset_gpio_num = GPIO_NUM_NC,
|
|
||||||
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
|
|
||||||
.data_endian = LCD_RGB_DATA_ENDIAN_LITTLE,
|
|
||||||
.bits_per_pixel = TDECK_LCD_BITS_PER_PIXEL,
|
|
||||||
.flags = {
|
|
||||||
.reset_active_high = 0
|
|
||||||
},
|
|
||||||
.vendor_config = nullptr
|
|
||||||
};
|
|
||||||
|
|
||||||
if (esp_lcd_new_panel_st7789(ioHandle, &panel_config, &panelHandle) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, "Failed to create panel");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (esp_lcd_panel_reset(panelHandle) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, "Failed to reset panel");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (esp_lcd_panel_init(panelHandle) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, "Failed to init panel");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (esp_lcd_panel_invert_color(panelHandle, true) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, "Failed to init panel");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (esp_lcd_panel_swap_xy(panelHandle, true) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, "Failed to swap XY ");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (esp_lcd_panel_mirror(panelHandle, true, false) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, "Failed to mirror panel");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (esp_lcd_panel_disp_on_off(panelHandle, true) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, "Failed to turn display on");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const lvgl_port_display_cfg_t disp_cfg = {
|
|
||||||
.io_handle = ioHandle,
|
|
||||||
.panel_handle = panelHandle,
|
|
||||||
.control_handle = nullptr,
|
|
||||||
.buffer_size = TDECK_LCD_HORIZONTAL_RESOLUTION * TDECK_LCD_DRAW_BUFFER_HEIGHT * (TDECK_LCD_BITS_PER_PIXEL / 8),
|
|
||||||
.double_buffer = true, // Disable to free up SPIRAM
|
|
||||||
.trans_size = 0,
|
|
||||||
.hres = TDECK_LCD_HORIZONTAL_RESOLUTION,
|
|
||||||
.vres = TDECK_LCD_VERTICAL_RESOLUTION,
|
|
||||||
.monochrome = false,
|
|
||||||
.rotation = {
|
|
||||||
.swap_xy = true,
|
|
||||||
.mirror_x = true,
|
|
||||||
.mirror_y = false,
|
|
||||||
},
|
|
||||||
.color_format = LV_COLOR_FORMAT_RGB565,
|
|
||||||
.flags = {
|
|
||||||
.buff_dma = false,
|
|
||||||
.buff_spiram = true,
|
|
||||||
.sw_rotate = false,
|
|
||||||
.swap_bytes = false,
|
|
||||||
.full_refresh = false,
|
|
||||||
.direct_mode = false
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
displayHandle = lvgl_port_add_disp(&disp_cfg);
|
|
||||||
TT_LOG_I(TAG, "Finished");
|
|
||||||
return displayHandle != nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TdeckDisplay::stop() {
|
|
||||||
assert(displayHandle != nullptr);
|
|
||||||
|
|
||||||
lvgl_port_remove_disp(displayHandle);
|
|
||||||
|
|
||||||
if (esp_lcd_panel_del(panelHandle) != ESP_OK) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (esp_lcd_panel_io_del(ioHandle) != ESP_OK) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
displayHandle = nullptr;
|
|
||||||
return true;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void TdeckDisplay::setPowerOn(bool turnOn) {
|
|
||||||
if (esp_lcd_panel_disp_on_off(panelHandle, turnOn) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, "Failed to turn display on/off");
|
|
||||||
} else {
|
|
||||||
poweredOn = turnOn;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tt::hal::Touch* _Nullable TdeckDisplay::createTouch() {
|
|
||||||
return static_cast<tt::hal::Touch*>(new TdeckTouch());
|
|
||||||
}
|
|
||||||
|
|
||||||
void TdeckDisplay::setBacklightDuty(uint8_t backlightDuty) {
|
|
||||||
if (!isBacklightInitialized) {
|
|
||||||
tt_check(initBacklight());
|
|
||||||
isBacklightInitialized = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!setBacklight(backlightDuty)) {
|
|
||||||
TT_LOG_E(TAG, "Failed to configure display backlight");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TdeckDisplay::setGammaCurve(uint8_t index) {
|
|
||||||
uint8_t gamma_curve;
|
|
||||||
switch (index) {
|
|
||||||
case 0:
|
|
||||||
gamma_curve = 0x01;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
gamma_curve = 0x04;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
gamma_curve = 0x02;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
gamma_curve = 0x08;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const uint8_t param[] = {
|
|
||||||
gamma_curve
|
|
||||||
};
|
|
||||||
|
|
||||||
if (esp_lcd_panel_io_tx_param(ioHandle , LCD_CMD_GAMSET, param, 1) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, "Failed to set gamma");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tt::hal::Display* createDisplay() {
|
|
||||||
return static_cast<tt::hal::Display*>(new TdeckDisplay());
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <esp_lcd_types.h>
|
|
||||||
#include "lvgl.h"
|
|
||||||
#include "hal/Display.h"
|
|
||||||
|
|
||||||
extern lv_disp_t* displayHandle;
|
|
||||||
|
|
||||||
class TdeckDisplay : public tt::hal::Display {
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
esp_lcd_panel_io_handle_t ioHandle = nullptr;
|
|
||||||
esp_lcd_panel_handle_t panelHandle = nullptr;
|
|
||||||
lv_display_t* displayHandle = nullptr;
|
|
||||||
bool poweredOn = false;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
bool start() override;
|
|
||||||
|
|
||||||
bool stop() override;
|
|
||||||
|
|
||||||
void setPowerOn(bool turnOn) override;
|
|
||||||
bool isPoweredOn() const override { return poweredOn; };
|
|
||||||
bool supportsPowerControl() const override { return true; }
|
|
||||||
|
|
||||||
tt::hal::Touch* _Nullable createTouch() override;
|
|
||||||
|
|
||||||
void setBacklightDuty(uint8_t backlightDuty) override;
|
|
||||||
bool supportsBacklightDuty() const override { return true; }
|
|
||||||
|
|
||||||
void setGammaCurve(uint8_t index) override;
|
|
||||||
uint8_t getGammaCurveCount() const override { return 4; };
|
|
||||||
|
|
||||||
lv_display_t* _Nullable getLvglDisplay() const override { return displayHandle; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
static bool startBacklight();
|
|
||||||
};
|
|
||||||
|
|
||||||
tt::hal::Display* createDisplay();
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#define TDECK_LCD_SPI_HOST SPI2_HOST
|
|
||||||
#define TDECK_LCD_PIN_CS GPIO_NUM_12
|
|
||||||
#define TDECK_LCD_PIN_DC GPIO_NUM_11 // RS
|
|
||||||
#define TDECK_LCD_PIN_BACKLIGHT GPIO_NUM_42
|
|
||||||
#define TDECK_LCD_SPI_FREQUENCY 80000000
|
|
||||||
#define TDECK_LCD_HORIZONTAL_RESOLUTION 320
|
|
||||||
#define TDECK_LCD_VERTICAL_RESOLUTION 240
|
|
||||||
#define TDECK_LCD_BITS_PER_PIXEL 16
|
|
||||||
#define TDECK_LCD_DRAW_BUFFER_HEIGHT (TDECK_LCD_VERTICAL_RESOLUTION / 10)
|
|
||||||
#define TDECK_LCD_SPI_TRANSFER_HEIGHT (TDECK_LCD_VERTICAL_RESOLUTION / 10)
|
|
||||||
|
|
||||||
// Backlight (PWM)
|
|
||||||
#define TDECK_LCD_BACKLIGHT_LEDC_TIMER LEDC_TIMER_0
|
|
||||||
#define TDECK_LCD_BACKLIGHT_LEDC_MODE LEDC_LOW_SPEED_MODE
|
|
||||||
#define TDECK_LCD_BACKLIGHT_LEDC_CHANNEL LEDC_CHANNEL_0
|
|
||||||
#define TDECK_LCD_BACKLIGHT_LEDC_DUTY_RES LEDC_TIMER_8_BIT
|
|
||||||
#define TDECK_LCD_BACKLIGHT_LEDC_FREQUENCY (4000)
|
|
||||||
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
#include "TdeckKeyboard.h"
|
|
||||||
#include "hal/i2c/I2c.h"
|
|
||||||
#include <driver/i2c.h>
|
|
||||||
|
|
||||||
#define TAG "tdeck_keyboard"
|
|
||||||
|
|
||||||
#define TDECK_KEYBOARD_I2C_BUS_HANDLE I2C_NUM_0
|
|
||||||
#define TDECK_KEYBOARD_SLAVE_ADDRESS 0x55
|
|
||||||
|
|
||||||
static inline bool keyboard_i2c_read(uint8_t* output) {
|
|
||||||
return tt::hal::i2c::masterRead(TDECK_KEYBOARD_I2C_BUS_HANDLE, TDECK_KEYBOARD_SLAVE_ADDRESS, output, 1, 100 / portTICK_PERIOD_MS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The callback simulates press and release events, because the T-Deck
|
|
||||||
* keyboard only publishes press events on I2C.
|
|
||||||
* LVGL currently works without those extra release events, but they
|
|
||||||
* are implemented for correctness and future compatibility.
|
|
||||||
*
|
|
||||||
* @param indev_drv
|
|
||||||
* @param data
|
|
||||||
*/
|
|
||||||
static void keyboard_read_callback(TT_UNUSED lv_indev_t* indev, lv_indev_data_t* data) {
|
|
||||||
static uint8_t last_buffer = 0x00;
|
|
||||||
uint8_t read_buffer = 0x00;
|
|
||||||
|
|
||||||
// Defaults
|
|
||||||
data->key = 0;
|
|
||||||
data->state = LV_INDEV_STATE_RELEASED;
|
|
||||||
|
|
||||||
if (keyboard_i2c_read(&read_buffer)) {
|
|
||||||
if (read_buffer == 0 && read_buffer != last_buffer) {
|
|
||||||
TT_LOG_D(TAG, "Released %d", last_buffer);
|
|
||||||
data->key = last_buffer;
|
|
||||||
data->state = LV_INDEV_STATE_RELEASED;
|
|
||||||
} else if (read_buffer != 0) {
|
|
||||||
TT_LOG_D(TAG, "Pressed %d", read_buffer);
|
|
||||||
data->key = read_buffer;
|
|
||||||
data->state = LV_INDEV_STATE_PRESSED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
last_buffer = read_buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TdeckKeyboard::start(lv_display_t* display) {
|
|
||||||
deviceHandle = lv_indev_create();
|
|
||||||
lv_indev_set_type(deviceHandle, LV_INDEV_TYPE_KEYPAD);
|
|
||||||
lv_indev_set_read_cb(deviceHandle, &keyboard_read_callback);
|
|
||||||
lv_indev_set_display(deviceHandle, display);
|
|
||||||
lv_indev_set_user_data(deviceHandle, this);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TdeckKeyboard::stop() {
|
|
||||||
lv_indev_delete(deviceHandle);
|
|
||||||
deviceHandle = nullptr;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TdeckKeyboard::isAttached() const {
|
|
||||||
return tt::hal::i2c::masterHasDeviceAtAddress(TDECK_KEYBOARD_I2C_BUS_HANDLE, TDECK_KEYBOARD_SLAVE_ADDRESS, 100);
|
|
||||||
}
|
|
||||||
|
|
||||||
tt::hal::Keyboard* createKeyboard() {
|
|
||||||
return dynamic_cast<tt::hal::Keyboard*>(new TdeckKeyboard());
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "hal/Keyboard.h"
|
|
||||||
#include <TactilityCore.h>
|
|
||||||
#include "esp_lcd_panel_io_interface.h"
|
|
||||||
#include "esp_lcd_touch.h"
|
|
||||||
|
|
||||||
class TdeckKeyboard : public tt::hal::Keyboard {
|
|
||||||
private:
|
|
||||||
lv_indev_t* _Nullable deviceHandle = nullptr;
|
|
||||||
public:
|
|
||||||
bool start(lv_display_t* display) override;
|
|
||||||
bool stop() override;
|
|
||||||
bool isAttached() const override;
|
|
||||||
lv_indev_t* _Nullable getLvglIndev() override { return deviceHandle; }
|
|
||||||
};
|
|
||||||
|
|
||||||
tt::hal::Keyboard* createKeyboard();
|
|
||||||
@@ -1,131 +0,0 @@
|
|||||||
#include "TdeckPower.h"
|
|
||||||
|
|
||||||
#include "Log.h"
|
|
||||||
#include "CoreDefines.h"
|
|
||||||
|
|
||||||
#define TAG "power"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 2.0 ratio, but +.11 added as display voltage sag compensation.
|
|
||||||
*/
|
|
||||||
#define ADC_MULTIPLIER 2.11
|
|
||||||
|
|
||||||
#define ADC_REF_VOLTAGE 3.3f
|
|
||||||
#define BATTERY_VOLTAGE_MIN 3.2f
|
|
||||||
#define BATTERY_VOLTAGE_MAX 4.2f
|
|
||||||
|
|
||||||
static adc_oneshot_unit_init_cfg_t adcConfig = {
|
|
||||||
.unit_id = ADC_UNIT_1,
|
|
||||||
.clk_src = ADC_RTC_CLK_SRC_DEFAULT,
|
|
||||||
.ulp_mode = ADC_ULP_MODE_DISABLE,
|
|
||||||
};
|
|
||||||
|
|
||||||
static adc_oneshot_chan_cfg_t adcChannelConfig = {
|
|
||||||
.atten = ADC_ATTEN_DB_12,
|
|
||||||
.bitwidth = ADC_BITWIDTH_DEFAULT,
|
|
||||||
};
|
|
||||||
|
|
||||||
static uint8_t estimateChargeLevelFromVoltage(uint32_t milliVolt) {
|
|
||||||
float volts = TT_MIN((float)milliVolt / 1000.f, BATTERY_VOLTAGE_MAX);
|
|
||||||
float voltage_percentage = (volts - BATTERY_VOLTAGE_MIN) / (BATTERY_VOLTAGE_MAX - BATTERY_VOLTAGE_MIN);
|
|
||||||
float voltage_factor = TT_MIN(1.0f, voltage_percentage);
|
|
||||||
auto charge_level = (uint8_t) (voltage_factor * 100.f);
|
|
||||||
TT_LOG_V(TAG, "mV = %lu, scaled = %.2f, factor = %.2f, result = %d", milliVolt, volts, voltage_factor, charge_level);
|
|
||||||
return charge_level;
|
|
||||||
}
|
|
||||||
|
|
||||||
TdeckPower::TdeckPower() {
|
|
||||||
if (adc_oneshot_new_unit(&adcConfig, &adcHandle) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, "ADC config failed");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (adc_oneshot_config_channel(adcHandle, ADC_CHANNEL_3, &adcChannelConfig) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, "ADC channel config failed");
|
|
||||||
|
|
||||||
adc_oneshot_del_unit(adcHandle);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TdeckPower::~TdeckPower() {
|
|
||||||
if (adcHandle) {
|
|
||||||
adc_oneshot_del_unit(adcHandle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TdeckPower::supportsMetric(MetricType type) const {
|
|
||||||
switch (type) {
|
|
||||||
case MetricType::BatteryVoltage:
|
|
||||||
case MetricType::ChargeLevel:
|
|
||||||
return true;
|
|
||||||
case MetricType::IsCharging:
|
|
||||||
case MetricType::Current:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false; // Safety guard for when new enum values are introduced
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TdeckPower::getMetric(Power::MetricType type, Power::MetricData& data) {
|
|
||||||
switch (type) {
|
|
||||||
case MetricType::BatteryVoltage:
|
|
||||||
return readBatteryVoltageSampled(data.valueAsUint32);
|
|
||||||
case MetricType::ChargeLevel:
|
|
||||||
if (readBatteryVoltageSampled(data.valueAsUint32)) {
|
|
||||||
data.valueAsUint32 = estimateChargeLevelFromVoltage(data.valueAsUint32);
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
case MetricType::IsCharging:
|
|
||||||
case MetricType::Current:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false; // Safety guard for when new enum values are introduced
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TdeckPower::readBatteryVoltageOnce(uint32_t& output) {
|
|
||||||
int raw;
|
|
||||||
if (adc_oneshot_read(adcHandle, ADC_CHANNEL_3, &raw) == ESP_OK) {
|
|
||||||
output = ADC_MULTIPLIER * ((1000.f * ADC_REF_VOLTAGE) / 4096.f) * (float)raw;
|
|
||||||
TT_LOG_V(TAG, "Raw = %d, voltage = %lu", raw, output);
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
TT_LOG_E(TAG, "Read failed");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MAX_VOLTAGE_SAMPLES 15
|
|
||||||
|
|
||||||
bool TdeckPower::readBatteryVoltageSampled(uint32_t& output) {
|
|
||||||
size_t samples_read = 0;
|
|
||||||
uint32_t sample_accumulator = 0;
|
|
||||||
uint32_t sample_read_buffer;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < MAX_VOLTAGE_SAMPLES; ++i) {
|
|
||||||
if (readBatteryVoltageOnce(sample_read_buffer)) {
|
|
||||||
sample_accumulator += sample_read_buffer;
|
|
||||||
samples_read++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (samples_read > 0) {
|
|
||||||
output = sample_accumulator / samples_read;
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::shared_ptr<Power> power;
|
|
||||||
|
|
||||||
std::shared_ptr<Power> tdeck_get_power() {
|
|
||||||
if (power == nullptr) {
|
|
||||||
power = std::make_shared<TdeckPower>();
|
|
||||||
}
|
|
||||||
return power;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "hal/Power.h"
|
|
||||||
#include <esp_adc/adc_oneshot.h>
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
using namespace tt::hal;
|
|
||||||
|
|
||||||
class TdeckPower : public Power {
|
|
||||||
|
|
||||||
adc_oneshot_unit_handle_t adcHandle = nullptr;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
TdeckPower();
|
|
||||||
~TdeckPower();
|
|
||||||
|
|
||||||
bool supportsMetric(MetricType type) const override;
|
|
||||||
bool getMetric(Power::MetricType type, Power::MetricData& data) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
bool readBatteryVoltageSampled(uint32_t& output);
|
|
||||||
bool readBatteryVoltageOnce(uint32_t& output);
|
|
||||||
};
|
|
||||||
|
|
||||||
std::shared_ptr<Power> tdeck_get_power();
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
#include "TdeckSdCard.h"
|
|
||||||
|
|
||||||
#include "lvgl/LvglSync.h"
|
|
||||||
#include "hal/SpiSdCard.h"
|
|
||||||
|
|
||||||
#include <esp_vfs_fat.h>
|
|
||||||
#include <sdmmc_cmd.h>
|
|
||||||
|
|
||||||
#define TDECK_SDCARD_PIN_CS GPIO_NUM_39
|
|
||||||
#define TDECK_LCD_PIN_CS GPIO_NUM_12
|
|
||||||
#define TDECK_RADIO_PIN_CS GPIO_NUM_9
|
|
||||||
|
|
||||||
std::shared_ptr<SdCard> createTdeckSdCard() {
|
|
||||||
auto* configuration = new tt::hal::SpiSdCard::Config(
|
|
||||||
TDECK_SDCARD_PIN_CS,
|
|
||||||
GPIO_NUM_NC,
|
|
||||||
GPIO_NUM_NC,
|
|
||||||
GPIO_NUM_NC,
|
|
||||||
SdCard::MountBehaviour::AtBoot,
|
|
||||||
tt::lvgl::getLvglSyncLockable(),
|
|
||||||
{
|
|
||||||
TDECK_RADIO_PIN_CS,
|
|
||||||
TDECK_LCD_PIN_CS
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
auto* sdcard = (SdCard*) new SpiSdCard(
|
|
||||||
std::unique_ptr<SpiSdCard::Config>(configuration)
|
|
||||||
);
|
|
||||||
|
|
||||||
return std::shared_ptr<SdCard>(sdcard);
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "hal/SdCard.h"
|
|
||||||
|
|
||||||
using namespace tt::hal;
|
|
||||||
|
|
||||||
std::shared_ptr<SdCard> createTdeckSdCard();
|
|
||||||
@@ -1,85 +0,0 @@
|
|||||||
#include "TdeckTouch.h"
|
|
||||||
|
|
||||||
#include "esp_err.h"
|
|
||||||
#include "esp_lcd_touch_gt911.h"
|
|
||||||
#include "Log.h"
|
|
||||||
#include "esp_lvgl_port.h"
|
|
||||||
|
|
||||||
#define TAG "tdeck_touch"
|
|
||||||
|
|
||||||
// Touch (GT911)
|
|
||||||
#define TDECK_TOUCH_I2C_BUS_HANDLE I2C_NUM_0
|
|
||||||
#define TDECK_TOUCH_X_MAX 240
|
|
||||||
#define TDECK_TOUCH_Y_MAX 320
|
|
||||||
|
|
||||||
bool TdeckTouch::start(lv_display_t* display) {
|
|
||||||
const esp_lcd_panel_io_i2c_config_t io_config = ESP_LCD_TOUCH_IO_I2C_GT911_CONFIG();
|
|
||||||
|
|
||||||
if (esp_lcd_new_panel_io_i2c(TDECK_TOUCH_I2C_BUS_HANDLE, &io_config, &ioHandle) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, "touch io i2c creation failed");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_lcd_touch_config_t config = {
|
|
||||||
.x_max = TDECK_TOUCH_X_MAX,
|
|
||||||
.y_max = TDECK_TOUCH_Y_MAX,
|
|
||||||
.rst_gpio_num = GPIO_NUM_NC,
|
|
||||||
.int_gpio_num = GPIO_NUM_NC, // There is no reset pin for touch on the T-Deck, leading to a bug in esp_lvgl_port firing multiple click events when tapping the screen
|
|
||||||
.levels = {
|
|
||||||
.reset = 0,
|
|
||||||
.interrupt = 0,
|
|
||||||
},
|
|
||||||
.flags = {
|
|
||||||
.swap_xy = 1,
|
|
||||||
.mirror_x = 1,
|
|
||||||
.mirror_y = 0,
|
|
||||||
},
|
|
||||||
.process_coordinates = nullptr,
|
|
||||||
.interrupt_callback = nullptr,
|
|
||||||
.user_data = nullptr,
|
|
||||||
.driver_data = nullptr
|
|
||||||
};
|
|
||||||
|
|
||||||
if (esp_lcd_touch_new_i2c_gt911(ioHandle, &config, &touchHandle) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, "GT199 driver init failed");
|
|
||||||
cleanup();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const lvgl_port_touch_cfg_t touch_cfg = {
|
|
||||||
.disp = display,
|
|
||||||
.handle = touchHandle,
|
|
||||||
};
|
|
||||||
|
|
||||||
TT_LOG_I(TAG, "Adding touch to LVGL");
|
|
||||||
deviceHandle = lvgl_port_add_touch(&touch_cfg);
|
|
||||||
if (deviceHandle == nullptr) {
|
|
||||||
TT_LOG_E(TAG, "Adding touch failed");
|
|
||||||
cleanup();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TdeckTouch::stop() {
|
|
||||||
cleanup();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TdeckTouch::cleanup() {
|
|
||||||
if (deviceHandle != nullptr) {
|
|
||||||
lv_indev_delete(deviceHandle);
|
|
||||||
deviceHandle = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (touchHandle != nullptr) {
|
|
||||||
esp_lcd_touch_del(touchHandle);
|
|
||||||
touchHandle = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ioHandle != nullptr) {
|
|
||||||
esp_lcd_panel_io_del(ioHandle);
|
|
||||||
ioHandle = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "hal/Touch.h"
|
|
||||||
#include "TactilityCore.h"
|
|
||||||
#include "esp_lcd_panel_io_interface.h"
|
|
||||||
#include "esp_lcd_touch.h"
|
|
||||||
|
|
||||||
class TdeckTouch : public tt::hal::Touch {
|
|
||||||
private:
|
|
||||||
esp_lcd_panel_io_handle_t _Nullable ioHandle = nullptr;
|
|
||||||
esp_lcd_touch_handle_t _Nullable touchHandle = nullptr;
|
|
||||||
lv_indev_t* _Nullable deviceHandle = nullptr;
|
|
||||||
void cleanup();
|
|
||||||
public:
|
|
||||||
bool start(lv_display_t* display) override;
|
|
||||||
bool stop() override;
|
|
||||||
lv_indev_t* _Nullable getLvglIndev() override { return deviceHandle; }
|
|
||||||
};
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
idf_component_register(
|
|
||||||
SRC_DIRS "Source" "Source/hal" "Source/ft6x36" "Source/axp192"
|
|
||||||
INCLUDE_DIRS "Source"
|
|
||||||
REQUIRES Tactility esp_lvgl_port esp_lcd esp_lcd_ili9341 driver vfs fatfs
|
|
||||||
)
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
# M5Stack Core2
|
|
||||||
|
|
||||||
This board implementation concerns the original Core2 hardware and **not** the v1.1 variant.
|
|
||||||
|
|
||||||
Reference implementations:
|
|
||||||
- [ESP-BSP](https://github.com/espressif/esp-bsp/tree/master/bsp/m5stack_core_2)
|
|
||||||
- [M5Unified](https://github.com/m5stack/M5Unified)
|
|
||||||
- [M5GFX](https://github.com/m5stack/M5GFX)
|
|
||||||
|
|
||||||
Docs:
|
|
||||||
- [M5Stack.com](https://docs.m5stack.com/en/core/Core2)
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
#include <driver/i2c.h>
|
|
||||||
#include <driver/spi_master.h>
|
|
||||||
#include <esp_intr_types.h>
|
|
||||||
#include "Log.h"
|
|
||||||
#include "hal/Core2DisplayConstants.h"
|
|
||||||
#include "axp192/axp192.h"
|
|
||||||
#include "hal/i2c/I2c.h"
|
|
||||||
#include "CoreDefines.h"
|
|
||||||
|
|
||||||
#define TAG "core2"
|
|
||||||
|
|
||||||
#define CORE2_SPI2_PIN_SCLK GPIO_NUM_18
|
|
||||||
#define CORE2_SPI2_PIN_MOSI GPIO_NUM_23
|
|
||||||
#define CORE2_SPI2_PIN_MISO GPIO_NUM_38
|
|
||||||
|
|
||||||
axp192_t axpDevice;
|
|
||||||
|
|
||||||
static int32_t axpI2cRead(TT_UNUSED void* handle, uint8_t address, uint8_t reg, uint8_t* buffer, uint16_t size) {
|
|
||||||
return tt::hal::i2c::masterReadRegister(I2C_NUM_0, address, reg, buffer, size, 50 / portTICK_PERIOD_MS);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int32_t axpI2cWrite(TT_UNUSED void* handle, uint8_t address, uint8_t reg, const uint8_t* buffer, uint16_t size) {
|
|
||||||
return tt::hal::i2c::masterWriteRegister(I2C_NUM_0, address, reg, buffer, size, 50 / portTICK_PERIOD_MS);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool initSpi2() {
|
|
||||||
TT_LOG_I(TAG, LOG_MESSAGE_SPI_INIT_START_FMT, SPI2_HOST);
|
|
||||||
const spi_bus_config_t bus_config = {
|
|
||||||
.mosi_io_num = CORE2_SPI2_PIN_MOSI,
|
|
||||||
.miso_io_num = CORE2_SPI2_PIN_MISO,
|
|
||||||
.sclk_io_num = CORE2_SPI2_PIN_SCLK,
|
|
||||||
.data2_io_num = GPIO_NUM_NC,
|
|
||||||
.data3_io_num = GPIO_NUM_NC,
|
|
||||||
.data4_io_num = GPIO_NUM_NC,
|
|
||||||
.data5_io_num = GPIO_NUM_NC,
|
|
||||||
.data6_io_num = GPIO_NUM_NC,
|
|
||||||
.data7_io_num = GPIO_NUM_NC,
|
|
||||||
.max_transfer_sz = CORE2_LCD_DRAW_BUFFER_SIZE,
|
|
||||||
.flags = 0,
|
|
||||||
.isr_cpu_id = ESP_INTR_CPU_AFFINITY_AUTO,
|
|
||||||
.intr_flags = 0
|
|
||||||
};
|
|
||||||
|
|
||||||
if (spi_bus_initialize(SPI2_HOST, &bus_config, SPI_DMA_CH_AUTO) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, LOG_MESSAGE_SPI_INIT_FAILED_FMT, SPI2_HOST);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool initAxp() {
|
|
||||||
axpDevice.read = axpI2cRead;
|
|
||||||
axpDevice.write = axpI2cWrite;
|
|
||||||
|
|
||||||
axp192_ioctl(&axpDevice, AXP192_LDO2_SET_VOLTAGE, 3300); // LCD + SD
|
|
||||||
axp192_ioctl(&axpDevice, AXP192_LDO3_SET_VOLTAGE, 0); // VIB_MOTOR STOP
|
|
||||||
axp192_ioctl(&axpDevice, AXP192_DCDC3_SET_VOLTAGE, 3300);
|
|
||||||
|
|
||||||
axp192_ioctl(&axpDevice, AXP192_LDO2_ENABLE);
|
|
||||||
axp192_ioctl(&axpDevice, AXP192_LDO3_DISABLE);
|
|
||||||
axp192_ioctl(&axpDevice, AXP192_DCDC3_ENABLE);
|
|
||||||
|
|
||||||
axp192_write(&axpDevice, AXP192_PWM1_DUTY_CYCLE_2, 255); // PWM 255 (LED OFF)
|
|
||||||
axp192_write(&axpDevice, AXP192_GPIO1_CONTROL, 0x02); // GPIO1 PWM
|
|
||||||
// TODO: We could charge at 390mA according to the M5Unified code, but the AXP driver in M5Unified limits to 132mA, so it's unclear what the AXP supports.
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool initBoot() {
|
|
||||||
TT_LOG_I(TAG, "initBoot");
|
|
||||||
return initAxp() && initSpi2();
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
bool initBoot();
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
#include "Log.h"
|
|
||||||
#include "Thread.h"
|
|
||||||
#include "lvgl/LvglSync.h"
|
|
||||||
#include "esp_lvgl_port.h"
|
|
||||||
|
|
||||||
#define TAG "core2"
|
|
||||||
|
|
||||||
// LVGL
|
|
||||||
// The minimum task stack seems to be about 3500, but that crashes the wifi app in some scenarios
|
|
||||||
// At 4000, it crashes when the fps renderer is available
|
|
||||||
#define CORE2_LVGL_TASK_STACK_DEPTH 9216
|
|
||||||
|
|
||||||
bool initLvgl() {
|
|
||||||
const lvgl_port_cfg_t lvgl_cfg = {
|
|
||||||
.task_priority = static_cast<UBaseType_t>(tt::THREAD_PRIORITY_RENDER),
|
|
||||||
.task_stack = CORE2_LVGL_TASK_STACK_DEPTH,
|
|
||||||
.task_affinity = -1, // core pinning
|
|
||||||
.task_max_sleep_ms = 500,
|
|
||||||
.timer_period_ms = 5
|
|
||||||
};
|
|
||||||
|
|
||||||
TT_LOG_D(TAG, "LVGL port init");
|
|
||||||
if (lvgl_port_init(&lvgl_cfg) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, "LVGL port init failed");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
tt::lvgl::syncSet(&lvgl_port_lock, &lvgl_port_unlock);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
bool initLvgl();
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
#include "M5stackCore2.h"
|
|
||||||
#include "InitBoot.h"
|
|
||||||
#include "InitLvgl.h"
|
|
||||||
#include "hal/Core2Display.h"
|
|
||||||
#include "hal/Core2SdCard.h"
|
|
||||||
#include "hal/Core2Power.h"
|
|
||||||
|
|
||||||
extern const tt::hal::Configuration m5stack_core2 = {
|
|
||||||
.initBoot = initBoot,
|
|
||||||
.initLvgl = initLvgl,
|
|
||||||
.createDisplay = createDisplay,
|
|
||||||
.sdcard = createSdCard(),
|
|
||||||
.power = createPower,
|
|
||||||
.i2c = {
|
|
||||||
tt::hal::i2c::Configuration {
|
|
||||||
.name = "Internal",
|
|
||||||
.port = I2C_NUM_0,
|
|
||||||
.initMode = tt::hal::i2c::InitMode::ByTactility,
|
|
||||||
.canReinit = false, // Might be set to try after trying out what it does AXP and screen
|
|
||||||
.hasMutableConfiguration = false,
|
|
||||||
.config = (i2c_config_t) {
|
|
||||||
.mode = I2C_MODE_MASTER,
|
|
||||||
.sda_io_num = GPIO_NUM_21,
|
|
||||||
.scl_io_num = GPIO_NUM_22,
|
|
||||||
.sda_pullup_en = true,
|
|
||||||
.scl_pullup_en = true,
|
|
||||||
.master = {
|
|
||||||
.clk_speed = 400000
|
|
||||||
},
|
|
||||||
.clk_flags = 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
tt::hal::i2c::Configuration {
|
|
||||||
.name = "External", // (Grove)
|
|
||||||
.port = I2C_NUM_1,
|
|
||||||
.initMode = tt::hal::i2c::InitMode::ByTactility,
|
|
||||||
.canReinit = true,
|
|
||||||
.hasMutableConfiguration = true,
|
|
||||||
.config = (i2c_config_t) {
|
|
||||||
.mode = I2C_MODE_MASTER,
|
|
||||||
.sda_io_num = GPIO_NUM_32,
|
|
||||||
.scl_io_num = GPIO_NUM_33,
|
|
||||||
.sda_pullup_en = true,
|
|
||||||
.scl_pullup_en = true,
|
|
||||||
.master = {
|
|
||||||
.clk_speed = 400000
|
|
||||||
},
|
|
||||||
.clk_flags = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "hal/Configuration.h"
|
|
||||||
|
|
||||||
extern const tt::hal::Configuration m5stack_core2;
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2019-2021 Mika Tuupola
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
From https://github.com/tuupola/axp192
|
|
||||||
|
|
||||||
Changed some code for Tactility:
|
|
||||||
- `axp192_write()` now accepts a byte value instead of a byte pointer
|
|
||||||
@@ -1,440 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2019-2021 Mika Tuupola
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
|
|
||||||
-cut-
|
|
||||||
|
|
||||||
This file is part of hardware agnostic I2C driver for AXP192:
|
|
||||||
https://github.com/tuupola/axp192
|
|
||||||
|
|
||||||
SPDX-License-Identifier: MIT
|
|
||||||
Version: 0.6.0
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include "axp192_config.h"
|
|
||||||
#include "axp192.h"
|
|
||||||
|
|
||||||
static axp192_err_t read_coloumb_counter(const axp192_t *axp, float *buffer);
|
|
||||||
static axp192_err_t read_battery_power(const axp192_t *axp, float *buffer);
|
|
||||||
|
|
||||||
static const axp192_init_command_t init_commands[] = {
|
|
||||||
#ifdef AXP192_INCLUDE_SDKCONFIG_H
|
|
||||||
/* Currently you have to use menuconfig to be able to use axp192_init() */
|
|
||||||
{AXP192_DCDC1_VOLTAGE, {CONFIG_AXP192_DCDC1_VOLTAGE}, 1},
|
|
||||||
{AXP192_DCDC3_VOLTAGE, {CONFIG_AXP192_DCDC3_VOLTAGE}, 1},
|
|
||||||
{AXP192_LDO23_VOLTAGE, {CONFIG_AXP192_LDO23_VOLTAGE}, 1},
|
|
||||||
{AXP192_GPIO0_LDOIO0_VOLTAGE, {CONFIG_AXP192_GPIO0_LDOIO0_VOLTAGE}, 1},
|
|
||||||
{AXP192_DCDC13_LDO23_CONTROL, {CONFIG_AXP192_DCDC13_LDO23_CONTROL}, 1},
|
|
||||||
{AXP192_EXTEN_DCDC2_CONTROL, {CONFIG_AXP192_EXTEN_DCDC2_CONTROL}, 1},
|
|
||||||
{AXP192_GPIO0_CONTROL, {CONFIG_AXP192_GPIO0_CONTROL}, 1},
|
|
||||||
{AXP192_GPIO1_CONTROL, {CONFIG_AXP192_GPIO1_CONTROL}, 1},
|
|
||||||
{AXP192_GPIO2_CONTROL, {CONFIG_AXP192_GPIO2_CONTROL}, 1},
|
|
||||||
{AXP192_GPIO43_FUNCTION_CONTROL, {CONFIG_AXP192_GPIO43_FUNCTION_CONTROL}, 1},
|
|
||||||
{AXP192_ADC_ENABLE_1, {CONFIG_AXP192_ADC_ENABLE_1}, 1},
|
|
||||||
{AXP192_CHARGE_CONTROL_1, {CONFIG_AXP192_CHARGE_CONTROL_1}, 1},
|
|
||||||
{AXP192_BATTERY_CHARGE_CONTROL, {CONFIG_AXP192_BATTERY_CHARGE_CONTROL}, 1},
|
|
||||||
#endif /* AXP192_INCLUDE_SDKCONFIG_H */
|
|
||||||
/* End of commands. */
|
|
||||||
{0, {0}, 0xff},
|
|
||||||
};
|
|
||||||
|
|
||||||
axp192_err_t axp192_init(const axp192_t *axp)
|
|
||||||
{
|
|
||||||
uint8_t cmd = 0;
|
|
||||||
axp192_err_t status;
|
|
||||||
|
|
||||||
/* Send all the commands. */
|
|
||||||
while (init_commands[cmd].count != 0xff) {
|
|
||||||
status = axp->write(
|
|
||||||
axp->handle,
|
|
||||||
AXP192_ADDRESS,
|
|
||||||
init_commands[cmd].command,
|
|
||||||
init_commands[cmd].data,
|
|
||||||
init_commands[cmd].count & 0x1f
|
|
||||||
);
|
|
||||||
if (AXP192_OK != status) {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
cmd++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return AXP192_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static axp192_err_t axp192_read_adc(const axp192_t *axp, uint8_t reg, float *buffer)
|
|
||||||
{
|
|
||||||
uint8_t tmp[4];
|
|
||||||
float sensitivity = 1.0;
|
|
||||||
float offset = 0.0;
|
|
||||||
axp192_err_t status;
|
|
||||||
|
|
||||||
switch (reg) {
|
|
||||||
case AXP192_ACIN_VOLTAGE:
|
|
||||||
case AXP192_VBUS_VOLTAGE:
|
|
||||||
/* 1.7mV per LSB */
|
|
||||||
sensitivity = 1.7 / 1000;
|
|
||||||
break;
|
|
||||||
case AXP192_ACIN_CURRENT:
|
|
||||||
/* 0.375mA per LSB */
|
|
||||||
sensitivity = 0.625 / 1000;
|
|
||||||
break;
|
|
||||||
case AXP192_VBUS_CURRENT:
|
|
||||||
/* 0.375mA per LSB */
|
|
||||||
sensitivity = 0.375 / 1000;
|
|
||||||
break;
|
|
||||||
case AXP192_TEMP:
|
|
||||||
/* 0.1C per LSB, 0x00 = -144.7C */
|
|
||||||
sensitivity = 0.1;
|
|
||||||
offset = -144.7;
|
|
||||||
break;
|
|
||||||
case AXP192_TS_INPUT:
|
|
||||||
/* 0.8mV per LSB */
|
|
||||||
sensitivity = 0.8 / 1000;
|
|
||||||
break;
|
|
||||||
case AXP192_BATTERY_POWER:
|
|
||||||
/* 1.1mV * 0.5mA per LSB */
|
|
||||||
return read_battery_power(axp, buffer);
|
|
||||||
break;
|
|
||||||
case AXP192_BATTERY_VOLTAGE:
|
|
||||||
/* 1.1mV per LSB */
|
|
||||||
sensitivity = 1.1 / 1000;
|
|
||||||
break;
|
|
||||||
case AXP192_CHARGE_CURRENT:
|
|
||||||
case AXP192_DISCHARGE_CURRENT:
|
|
||||||
/* 0.5mV per LSB */
|
|
||||||
sensitivity = 0.5 / 1000;
|
|
||||||
break;
|
|
||||||
case AXP192_APS_VOLTAGE:
|
|
||||||
/* 1.4mV per LSB */
|
|
||||||
sensitivity = 1.4 / 1000;
|
|
||||||
break;
|
|
||||||
case AXP192_COULOMB_COUNTER:
|
|
||||||
/* This is currently untested. */
|
|
||||||
return read_coloumb_counter(axp, buffer);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
status = axp->read(axp->handle, AXP192_ADDRESS, reg, tmp, 2);
|
|
||||||
if (AXP192_OK != status) {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
*buffer = (((tmp[0] << 4) + tmp[1]) * sensitivity) + offset;
|
|
||||||
|
|
||||||
return AXP192_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
axp192_err_t axp192_read(const axp192_t *axp, uint8_t reg, void *buffer) {
|
|
||||||
switch (reg) {
|
|
||||||
case AXP192_ACIN_VOLTAGE:
|
|
||||||
case AXP192_VBUS_VOLTAGE:
|
|
||||||
case AXP192_ACIN_CURRENT:
|
|
||||||
case AXP192_VBUS_CURRENT:
|
|
||||||
case AXP192_TEMP:
|
|
||||||
case AXP192_TS_INPUT:
|
|
||||||
case AXP192_BATTERY_POWER:
|
|
||||||
case AXP192_BATTERY_VOLTAGE:
|
|
||||||
case AXP192_CHARGE_CURRENT:
|
|
||||||
case AXP192_DISCHARGE_CURRENT:
|
|
||||||
case AXP192_APS_VOLTAGE:
|
|
||||||
case AXP192_COULOMB_COUNTER:
|
|
||||||
/* Return ADC value. */
|
|
||||||
return axp192_read_adc(axp, reg, buffer);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
/* Return raw register value. */
|
|
||||||
return axp->read(axp->handle, AXP192_ADDRESS, reg, buffer, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
axp192_err_t axp192_write(const axp192_t *axp, uint8_t reg, uint8_t value) {
|
|
||||||
switch (reg) {
|
|
||||||
case AXP192_ACIN_VOLTAGE:
|
|
||||||
case AXP192_VBUS_VOLTAGE:
|
|
||||||
case AXP192_ACIN_CURRENT:
|
|
||||||
case AXP192_VBUS_CURRENT:
|
|
||||||
case AXP192_TEMP:
|
|
||||||
case AXP192_TS_INPUT:
|
|
||||||
case AXP192_BATTERY_POWER:
|
|
||||||
case AXP192_BATTERY_VOLTAGE:
|
|
||||||
case AXP192_CHARGE_CURRENT:
|
|
||||||
case AXP192_DISCHARGE_CURRENT:
|
|
||||||
case AXP192_APS_VOLTAGE:
|
|
||||||
case AXP192_COULOMB_COUNTER:
|
|
||||||
/* Read only register. */
|
|
||||||
return AXP192_ERROR_ENOTSUP;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
/* Write raw register value. */
|
|
||||||
return axp->write(axp->handle, AXP192_ADDRESS, reg, &value, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
axp192_err_t axp192_ioctl(const axp192_t *axp, int command, ...)
|
|
||||||
{
|
|
||||||
uint8_t reg = command >> 8;
|
|
||||||
uint8_t tmp;
|
|
||||||
uint16_t argument;
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
switch (command) {
|
|
||||||
case AXP192_COULOMB_COUNTER_ENABLE:
|
|
||||||
tmp = 0b10000000;
|
|
||||||
return axp->write(axp->handle, AXP192_ADDRESS, reg, &tmp, 1);
|
|
||||||
break;
|
|
||||||
case AXP192_COULOMB_COUNTER_DISABLE:
|
|
||||||
tmp = 0b00000000;
|
|
||||||
return axp->write(axp->handle, AXP192_ADDRESS, reg, &tmp, 1);
|
|
||||||
break;
|
|
||||||
case AXP192_COULOMB_COUNTER_SUSPEND:
|
|
||||||
tmp = 0b11000000;
|
|
||||||
return axp->write(axp->handle, AXP192_ADDRESS, reg, &tmp, 1);
|
|
||||||
break;
|
|
||||||
case AXP192_COULOMB_COUNTER_CLEAR:
|
|
||||||
tmp = 0b10100000;
|
|
||||||
return axp->write(axp->handle, AXP192_ADDRESS, reg, &tmp, 1);
|
|
||||||
break;
|
|
||||||
/* This is currently untested. */
|
|
||||||
case AXP192_LDOIO0_ENABLE:
|
|
||||||
/* 0x02 = LDO */
|
|
||||||
tmp = 0b00000010;
|
|
||||||
return axp->write(axp->handle, AXP192_ADDRESS, reg, &tmp, 1);
|
|
||||||
break;
|
|
||||||
/* This is currently untested. */
|
|
||||||
case AXP192_LDOIO0_DISABLE:
|
|
||||||
/* 0x07 = float */
|
|
||||||
tmp = 0b00000111;
|
|
||||||
return axp->write(axp->handle, AXP192_ADDRESS, reg, &tmp, 1);
|
|
||||||
break;
|
|
||||||
case AXP192_LDO2_ENABLE:
|
|
||||||
/* This is currently untested. */
|
|
||||||
case AXP192_EXTEN_ENABLE:
|
|
||||||
axp->read(axp->handle, AXP192_ADDRESS, reg, &tmp, 1);
|
|
||||||
tmp |= 0b00000100;
|
|
||||||
return axp->write(axp->handle, AXP192_ADDRESS, reg, &tmp, 1);
|
|
||||||
break;
|
|
||||||
case AXP192_LDO2_DISABLE:
|
|
||||||
/* This is currently untested. */
|
|
||||||
case AXP192_EXTEN_DISABLE:
|
|
||||||
axp->read(axp->handle, AXP192_ADDRESS, reg, &tmp, 1);
|
|
||||||
tmp &= ~0b00000100;
|
|
||||||
return axp->write(axp->handle, AXP192_ADDRESS, reg, &tmp, 1);
|
|
||||||
break;
|
|
||||||
/* This is currently untested. */
|
|
||||||
case AXP192_GPIO2_SET_LEVEL:
|
|
||||||
axp->read(axp->handle, AXP192_ADDRESS, reg, &tmp, 1);
|
|
||||||
va_start(ap, command);
|
|
||||||
argument = (uint8_t) va_arg(ap, int);
|
|
||||||
va_end(ap);
|
|
||||||
if (argument) {
|
|
||||||
tmp |= 0b00000100;
|
|
||||||
} else {
|
|
||||||
tmp &= ~0b00000100;
|
|
||||||
}
|
|
||||||
return axp->write(axp->handle, AXP192_ADDRESS, reg, &tmp, 1);
|
|
||||||
break;
|
|
||||||
case AXP192_LDO3_ENABLE:
|
|
||||||
axp->read(axp->handle, AXP192_ADDRESS, reg, &tmp, 1);
|
|
||||||
tmp |= 0b00001000;
|
|
||||||
return axp->write(axp->handle, AXP192_ADDRESS, reg, &tmp, 1);
|
|
||||||
break;
|
|
||||||
case AXP192_LDO3_DISABLE:
|
|
||||||
axp->read(axp->handle, AXP192_ADDRESS, reg, &tmp, 1);
|
|
||||||
tmp &= ~0b00001000;
|
|
||||||
return axp->write(axp->handle, AXP192_ADDRESS, reg, &tmp, 1);
|
|
||||||
break;
|
|
||||||
/* This is currently untested. */
|
|
||||||
case AXP192_DCDC1_ENABLE:
|
|
||||||
/* This is currently untested. */
|
|
||||||
case AXP192_DCDC2_ENABLE:
|
|
||||||
axp->read(axp->handle, AXP192_ADDRESS, reg, &tmp, 1);
|
|
||||||
tmp |= 0b00000001;
|
|
||||||
return axp->write(axp->handle, AXP192_ADDRESS, reg, &tmp, 1);
|
|
||||||
break;
|
|
||||||
/* This is currently untested. */
|
|
||||||
case AXP192_DCDC1_DISABLE:
|
|
||||||
/* This is currently untested. */
|
|
||||||
case AXP192_DCDC2_DISABLE:
|
|
||||||
axp->read(axp->handle, AXP192_ADDRESS, reg, &tmp, 1);
|
|
||||||
tmp &= ~0b00000001;
|
|
||||||
return axp->write(axp->handle, AXP192_ADDRESS, reg, &tmp, 1);
|
|
||||||
break;
|
|
||||||
case AXP192_DCDC3_ENABLE:
|
|
||||||
axp->read(axp->handle, AXP192_ADDRESS, reg, &tmp, 1);
|
|
||||||
tmp |= 0b00000010;
|
|
||||||
return axp->write(axp->handle, AXP192_ADDRESS, reg, &tmp, 1);
|
|
||||||
break;
|
|
||||||
case AXP192_DCDC3_DISABLE:
|
|
||||||
axp->read(axp->handle, AXP192_ADDRESS, reg, &tmp, 1);
|
|
||||||
tmp &= ~0b00000010;
|
|
||||||
return axp->write(axp->handle, AXP192_ADDRESS, reg, &tmp, 1);
|
|
||||||
break;
|
|
||||||
case AXP192_GPIO1_SET_LEVEL:
|
|
||||||
case AXP192_GPIO4_SET_LEVEL:
|
|
||||||
axp->read(axp->handle, AXP192_ADDRESS, reg, &tmp, 1);
|
|
||||||
va_start(ap, command);
|
|
||||||
argument = (uint8_t) va_arg(ap, int);
|
|
||||||
va_end(ap);
|
|
||||||
if (argument) {
|
|
||||||
tmp |= 0b00000010;
|
|
||||||
} else {
|
|
||||||
tmp &= ~0b00000010;
|
|
||||||
}
|
|
||||||
return axp->write(axp->handle, AXP192_ADDRESS, reg, &tmp, 1);
|
|
||||||
break;
|
|
||||||
/* This is currently untested. */
|
|
||||||
case AXP192_GPIO0_SET_LEVEL:
|
|
||||||
axp->read(axp->handle, AXP192_ADDRESS, reg, &tmp, 1);
|
|
||||||
va_start(ap, command);
|
|
||||||
argument = (uint8_t) va_arg(ap, int);
|
|
||||||
va_end(ap);
|
|
||||||
if (argument) {
|
|
||||||
tmp |= 0b00000001;
|
|
||||||
} else {
|
|
||||||
tmp &= ~0b00000001;
|
|
||||||
}
|
|
||||||
return axp->write(axp->handle, AXP192_ADDRESS, reg, &tmp, 1);
|
|
||||||
break;
|
|
||||||
case AXP192_DCDC1_SET_VOLTAGE:
|
|
||||||
case AXP192_DCDC3_SET_VOLTAGE:
|
|
||||||
va_start(ap, command);
|
|
||||||
argument = (uint16_t) va_arg(ap, int);
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
/* 700-3500mv 25mV per step */
|
|
||||||
if ((argument < 700) || (argument > 3500)) {
|
|
||||||
return AXP192_ERROR_EINVAL;
|
|
||||||
}
|
|
||||||
tmp = (argument - 700) / 25;
|
|
||||||
|
|
||||||
return axp->write(axp->handle, AXP192_ADDRESS, reg, &tmp, 1);
|
|
||||||
break;
|
|
||||||
/* This is currently untested. */
|
|
||||||
case AXP192_DCDC2_SET_VOLTAGE:
|
|
||||||
va_start(ap, command);
|
|
||||||
argument = (uint16_t) va_arg(ap, int);
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
/* 700-2275mV 25mV per step */
|
|
||||||
if ((argument < 700) || (argument > 2275)) {
|
|
||||||
return AXP192_ERROR_EINVAL;
|
|
||||||
}
|
|
||||||
tmp = (argument - 700) / 25;
|
|
||||||
|
|
||||||
return axp->write(axp->handle, AXP192_ADDRESS, reg, &tmp, 1);
|
|
||||||
break;
|
|
||||||
/* This is currently untested. */
|
|
||||||
case AXP192_LDO2_SET_VOLTAGE:
|
|
||||||
va_start(ap, command);
|
|
||||||
argument = (uint16_t) va_arg(ap, int);
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
/* 1800-3300mV 100mV per step */
|
|
||||||
if ((argument < 1800) || (argument > 3300)) {
|
|
||||||
return AXP192_ERROR_EINVAL;
|
|
||||||
}
|
|
||||||
axp->read(axp->handle, AXP192_ADDRESS, reg, &tmp, 1);
|
|
||||||
|
|
||||||
tmp &= ~0xf0;
|
|
||||||
tmp |= (((argument - 1800) / 100) << 4);
|
|
||||||
|
|
||||||
return axp->write(axp->handle, AXP192_ADDRESS, reg, &tmp, 1);
|
|
||||||
break;
|
|
||||||
/* This is currently untested. */
|
|
||||||
case AXP192_LDO3_SET_VOLTAGE:
|
|
||||||
va_start(ap, command);
|
|
||||||
argument = (uint16_t) va_arg(ap, int);
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
/* 1800-3300mV 100mV per step */
|
|
||||||
if ((argument < 1800) || (argument > 3300)) {
|
|
||||||
return AXP192_ERROR_EINVAL;
|
|
||||||
}
|
|
||||||
axp->read(axp->handle, AXP192_ADDRESS, reg, &tmp, 1);
|
|
||||||
|
|
||||||
tmp &= ~0x0f;
|
|
||||||
tmp |= ((argument - 1800) / 100);
|
|
||||||
|
|
||||||
return axp->write(axp->handle, AXP192_ADDRESS, reg, &tmp, 1);
|
|
||||||
break;
|
|
||||||
/* This is currently untested. */
|
|
||||||
case AXP192_LDOIO0_SET_VOLTAGE:
|
|
||||||
va_start(ap, command);
|
|
||||||
argument = (uint16_t) va_arg(ap, int);
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
/* 1800-3300mV 100mV per step, 2800mV default. */
|
|
||||||
if ((argument < 1800) || (argument > 3300)) {
|
|
||||||
return AXP192_ERROR_EINVAL;
|
|
||||||
}
|
|
||||||
tmp = (((argument - 1800) / 100) << 4);
|
|
||||||
|
|
||||||
return axp->write(axp->handle, AXP192_ADDRESS, reg, &tmp, 1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return AXP192_ERROR_NOTTY;
|
|
||||||
}
|
|
||||||
|
|
||||||
static axp192_err_t read_coloumb_counter(const axp192_t *axp, float *buffer)
|
|
||||||
{
|
|
||||||
uint8_t tmp[4];
|
|
||||||
int32_t coin, coout;
|
|
||||||
axp192_err_t status;
|
|
||||||
|
|
||||||
status = axp->read(axp->handle, AXP192_ADDRESS, AXP192_CHARGE_COULOMB, tmp, sizeof(coin));
|
|
||||||
if (AXP192_OK != status) {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
coin = (tmp[0] << 24) + (tmp[1] << 16) + (tmp[2] << 8) + tmp[3];
|
|
||||||
|
|
||||||
status = axp->read(axp->handle, AXP192_ADDRESS, AXP192_DISCHARGE_COULOMB, tmp, sizeof(coout));
|
|
||||||
if (AXP192_OK != status) {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
coout = (tmp[0] << 24) + (tmp[1] << 16) + (tmp[2] << 8) + tmp[3];
|
|
||||||
|
|
||||||
/* CmAh = 65536 * 0.5mA *(coin - cout) / 3600 / ADC sample rate */
|
|
||||||
*buffer = 32768 * (coin - coout) / 3600 / 25;
|
|
||||||
|
|
||||||
return AXP192_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static axp192_err_t read_battery_power(const axp192_t *axp, float *buffer)
|
|
||||||
{
|
|
||||||
uint8_t tmp[4];
|
|
||||||
float sensitivity;
|
|
||||||
axp192_err_t status;
|
|
||||||
|
|
||||||
/* 1.1mV * 0.5mA per LSB */
|
|
||||||
sensitivity = 1.1 * 0.5 / 1000;
|
|
||||||
status = axp->read(axp->handle, AXP192_ADDRESS, AXP192_BATTERY_POWER, tmp, 3);
|
|
||||||
if (AXP192_OK != status) {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
*buffer = (((tmp[0] << 16) + (tmp[1] << 8) + tmp[2]) * sensitivity);
|
|
||||||
return AXP192_OK;
|
|
||||||
}
|
|
||||||
@@ -1,213 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2019-2021 Mika Tuupola
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
|
|
||||||
-cut-
|
|
||||||
|
|
||||||
This file is part of hardware agnostic I2C driver for AXP192:
|
|
||||||
https://github.com/tuupola/axp192
|
|
||||||
|
|
||||||
SPDX-License-Identifier: MIT
|
|
||||||
Version: 0.6.0
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _AXP192_H
|
|
||||||
#define _AXP192_H
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#define AXP192_ADDRESS (0x34)
|
|
||||||
|
|
||||||
/* Power control registers */
|
|
||||||
#define AXP192_POWER_STATUS (0x00)
|
|
||||||
#define AXP192_CHARGE_STATUS (0x01)
|
|
||||||
#define AXP192_OTG_VBUS_STATUS (0x04)
|
|
||||||
#define AXP192_DATA_BUFFER0 (0x06)
|
|
||||||
#define AXP192_DATA_BUFFER1 (0x07)
|
|
||||||
#define AXP192_DATA_BUFFER2 (0x08)
|
|
||||||
#define AXP192_DATA_BUFFER3 (0x09)
|
|
||||||
#define AXP192_DATA_BUFFER4 (0x0a)
|
|
||||||
#define AXP192_DATA_BUFFER5 (0x0b)
|
|
||||||
/* Output control: 2 EXTEN, 0 DCDC2 */
|
|
||||||
#define AXP192_EXTEN_DCDC2_CONTROL (0x10)
|
|
||||||
/* Power output control: 6 EXTEN, 4 DCDC2, 3 LDO3, 2 LDO2, 1 DCDC3, 0 DCDC1 */
|
|
||||||
#define AXP192_DCDC13_LDO23_CONTROL (0x12)
|
|
||||||
#define AXP192_DCDC2_VOLTAGE (0x23)
|
|
||||||
#define AXP192_DCDC2_SLOPE (0x25)
|
|
||||||
#define AXP192_DCDC1_VOLTAGE (0x26)
|
|
||||||
#define AXP192_DCDC3_VOLTAGE (0x27)
|
|
||||||
/* Output voltage control: 7-4 LDO2, 3-0 LDO3 */
|
|
||||||
#define AXP192_LDO23_VOLTAGE (0x28)
|
|
||||||
#define AXP192_VBUS_IPSOUT_CHANNEL (0x30)
|
|
||||||
#define AXP192_SHUTDOWN_VOLTAGE (0x31)
|
|
||||||
#define AXP192_SHUTDOWN_BATTERY_CHGLED_CONTROL (0x32)
|
|
||||||
#define AXP192_CHARGE_CONTROL_1 (0x33)
|
|
||||||
#define AXP192_CHARGE_CONTROL_2 (0x34)
|
|
||||||
#define AXP192_BATTERY_CHARGE_CONTROL (0x35)
|
|
||||||
#define AXP192_PEK (0x36)
|
|
||||||
#define AXP192_DCDC_FREQUENCY (0x37)
|
|
||||||
#define AXP192_BATTERY_CHARGE_LOW_TEMP (0x38)
|
|
||||||
#define AXP192_BATTERY_CHARGE_HIGH_TEMP (0x39)
|
|
||||||
#define AXP192_APS_LOW_POWER1 (0x3A)
|
|
||||||
#define AXP192_APS_LOW_POWER2 (0x3B)
|
|
||||||
#define AXP192_BATTERY_DISCHARGE_LOW_TEMP (0x3c)
|
|
||||||
#define AXP192_BATTERY_DISCHARGE_HIGH_TEMP (0x3d)
|
|
||||||
#define AXP192_DCDC_MODE (0x80)
|
|
||||||
#define AXP192_ADC_ENABLE_1 (0x82)
|
|
||||||
#define AXP192_ADC_ENABLE_2 (0x83)
|
|
||||||
#define AXP192_ADC_RATE_TS_PIN (0x84)
|
|
||||||
#define AXP192_GPIO30_INPUT_RANGE (0x85)
|
|
||||||
#define AXP192_GPIO0_ADC_IRQ_RISING (0x86)
|
|
||||||
#define AXP192_GPIO0_ADC_IRQ_FALLING (0x87)
|
|
||||||
#define AXP192_TIMER_CONTROL (0x8a)
|
|
||||||
#define AXP192_VBUS_MONITOR (0x8b)
|
|
||||||
#define AXP192_TEMP_SHUTDOWN_CONTROL (0x8f)
|
|
||||||
|
|
||||||
/* GPIO control registers */
|
|
||||||
#define AXP192_GPIO0_CONTROL (0x90)
|
|
||||||
#define AXP192_GPIO0_LDOIO0_VOLTAGE (0x91)
|
|
||||||
#define AXP192_GPIO1_CONTROL (0x92)
|
|
||||||
#define AXP192_GPIO2_CONTROL (0x93)
|
|
||||||
#define AXP192_GPIO20_SIGNAL_STATUS (0x94)
|
|
||||||
#define AXP192_GPIO43_FUNCTION_CONTROL (0x95)
|
|
||||||
#define AXP192_GPIO43_SIGNAL_STATUS (0x96)
|
|
||||||
#define AXP192_GPIO20_PULLDOWN_CONTROL (0x97)
|
|
||||||
#define AXP192_PWM1_FREQUENCY (0x98)
|
|
||||||
#define AXP192_PWM1_DUTY_CYCLE_1 (0x99)
|
|
||||||
#define AXP192_PWM1_DUTY_CYCLE_2 (0x9a)
|
|
||||||
#define AXP192_PWM2_FREQUENCY (0x9b)
|
|
||||||
#define AXP192_PWM2_DUTY_CYCLE_1 (0x9c)
|
|
||||||
#define AXP192_PWM2_DUTY_CYCLE_2 (0x9d)
|
|
||||||
#define AXP192_N_RSTO_GPIO5_CONTROL (0x9e)
|
|
||||||
|
|
||||||
/* Interrupt control registers */
|
|
||||||
#define AXP192_ENABLE_CONTROL_1 (0x40)
|
|
||||||
#define AXP192_ENABLE_CONTROL_2 (0x41)
|
|
||||||
#define AXP192_ENABLE_CONTROL_3 (0x42)
|
|
||||||
#define AXP192_ENABLE_CONTROL_4 (0x43)
|
|
||||||
#define AXP192_ENABLE_CONTROL_5 (0x4a)
|
|
||||||
#define AXP192_IRQ_STATUS_1 (0x44)
|
|
||||||
#define AXP192_IRQ_STATUS_2 (0x45)
|
|
||||||
#define AXP192_IRQ_STATUS_3 (0x46)
|
|
||||||
#define AXP192_IRQ_STATUS_4 (0x47)
|
|
||||||
#define AXP192_IRQ_STATUS_5 (0x4d)
|
|
||||||
|
|
||||||
/* ADC data registers */
|
|
||||||
#define AXP192_ACIN_VOLTAGE (0x56)
|
|
||||||
#define AXP192_ACIN_CURRENT (0x58)
|
|
||||||
#define AXP192_VBUS_VOLTAGE (0x5a)
|
|
||||||
#define AXP192_VBUS_CURRENT (0x5c)
|
|
||||||
#define AXP192_TEMP (0x5e)
|
|
||||||
#define AXP192_TS_INPUT (0x62)
|
|
||||||
#define AXP192_GPIO0_VOLTAGE (0x64)
|
|
||||||
#define AXP192_GPIO1_VOLTAGE (0x66)
|
|
||||||
#define AXP192_GPIO2_VOLTAGE (0x68)
|
|
||||||
#define AXP192_GPIO3_VOLTAGE (0x6a)
|
|
||||||
#define AXP192_BATTERY_POWER (0x70)
|
|
||||||
#define AXP192_BATTERY_VOLTAGE (0x78)
|
|
||||||
#define AXP192_CHARGE_CURRENT (0x7a)
|
|
||||||
#define AXP192_DISCHARGE_CURRENT (0x7c)
|
|
||||||
#define AXP192_APS_VOLTAGE (0x7e)
|
|
||||||
#define AXP192_CHARGE_COULOMB (0xb0)
|
|
||||||
#define AXP192_DISCHARGE_COULOMB (0xb4)
|
|
||||||
#define AXP192_COULOMB_COUNTER_CONTROL (0xb8)
|
|
||||||
|
|
||||||
/* Computed ADC */
|
|
||||||
#define AXP192_COULOMB_COUNTER (0xff)
|
|
||||||
|
|
||||||
/* IOCTL commands */
|
|
||||||
#define AXP192_READ_POWER_STATUS (0x0001)
|
|
||||||
#define AXP192_READ_CHARGE_STATUS (0x0101)
|
|
||||||
|
|
||||||
#define AXP192_COULOMB_COUNTER_ENABLE (0xb801)
|
|
||||||
#define AXP192_COULOMB_COUNTER_DISABLE (0xb802)
|
|
||||||
#define AXP192_COULOMB_COUNTER_SUSPEND (0xb803)
|
|
||||||
#define AXP192_COULOMB_COUNTER_CLEAR (0xb804)
|
|
||||||
|
|
||||||
#define AXP192_LDOIO0_ENABLE (0x9000)
|
|
||||||
#define AXP192_LDOIO0_DISABLE (0x9001)
|
|
||||||
|
|
||||||
#define AXP192_DCDC2_ENABLE (0x1000)
|
|
||||||
#define AXP192_DCDC2_DISABLE (0x1001)
|
|
||||||
#define AXP192_EXTEN_ENABLE (0x1002)
|
|
||||||
#define AXP192_EXTEN_DISABLE (0x1003)
|
|
||||||
|
|
||||||
#define AXP192_LDO2_ENABLE (0x1200)
|
|
||||||
#define AXP192_LDO2_DISABLE (0x1201)
|
|
||||||
#define AXP192_LDO3_ENABLE (0x1202)
|
|
||||||
#define AXP192_LDO3_DISABLE (0x1203)
|
|
||||||
#define AXP192_DCDC1_ENABLE (0x1204)
|
|
||||||
#define AXP192_DCDC1_DISABLE (0x1205)
|
|
||||||
#define AXP192_DCDC3_ENABLE (0x1206)
|
|
||||||
#define AXP192_DCDC3_DISABLE (0x1207)
|
|
||||||
|
|
||||||
#define AXP192_DCDC1_SET_VOLTAGE (0x2600)
|
|
||||||
#define AXP192_DCDC2_SET_VOLTAGE (0x2300)
|
|
||||||
#define AXP192_DCDC3_SET_VOLTAGE (0x2700)
|
|
||||||
#define AXP192_LDO2_SET_VOLTAGE (0x2800)
|
|
||||||
#define AXP192_LDO3_SET_VOLTAGE (0x2801)
|
|
||||||
#define AXP192_LDOIO0_SET_VOLTAGE (0x9100)
|
|
||||||
|
|
||||||
#define AXP192_LOW (0)
|
|
||||||
#define AXP192_HIGH (1)
|
|
||||||
|
|
||||||
#define AXP192_GPIO0_SET_LEVEL (0x9400)
|
|
||||||
#define AXP192_GPIO1_SET_LEVEL (0x9401)
|
|
||||||
#define AXP192_GPIO2_SET_LEVEL (0x9402)
|
|
||||||
#define AXP192_GPIO4_SET_LEVEL (0x9601)
|
|
||||||
|
|
||||||
/* Error codes */
|
|
||||||
#define AXP192_OK (0)
|
|
||||||
#define AXP192_ERROR_NOTTY (-1)
|
|
||||||
#define AXP192_ERROR_EINVAL (-22)
|
|
||||||
#define AXP192_ERROR_ENOTSUP (-95)
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint8_t command;
|
|
||||||
uint8_t data[2];
|
|
||||||
uint8_t count;
|
|
||||||
} axp192_init_command_t;
|
|
||||||
|
|
||||||
/* These should be provided by the HAL. */
|
|
||||||
typedef struct {
|
|
||||||
int32_t (* read)(void *handle, uint8_t address, uint8_t reg, uint8_t *buffer, uint16_t size);
|
|
||||||
int32_t (* write)(void *handle, uint8_t address, uint8_t reg, const uint8_t *buffer, uint16_t size);
|
|
||||||
void *handle;
|
|
||||||
} axp192_t;
|
|
||||||
|
|
||||||
typedef int32_t axp192_err_t;
|
|
||||||
|
|
||||||
axp192_err_t axp192_init(const axp192_t *axp);
|
|
||||||
axp192_err_t axp192_read(const axp192_t *axp, uint8_t reg, void *buffer);
|
|
||||||
axp192_err_t axp192_write(const axp192_t *axp, uint8_t reg, uint8_t value);
|
|
||||||
axp192_err_t axp192_ioctl(const axp192_t *axp, int command, ...);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
@@ -1,125 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2019-2021 Mika Tuupola
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
|
|
||||||
-cut-
|
|
||||||
|
|
||||||
This file is part of hardware agnostic I2C driver for AXP192:
|
|
||||||
https://github.com/tuupola/axp192
|
|
||||||
|
|
||||||
SPDX-License-Identifier: MIT
|
|
||||||
Version: 0.6.0
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _AXP192_CONFIG_H
|
|
||||||
#define _AXP192_CONFIG_H
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef AXP192_INCLUDE_SDKCONFIG_H
|
|
||||||
#include "sdkconfig.h"
|
|
||||||
|
|
||||||
/* This requires you to run menuconfig first. */
|
|
||||||
|
|
||||||
#define CONFIG_AXP192_EXTEN_DCDC2_CONTROL ( \
|
|
||||||
CONFIG_AXP192_EXTEN_DCDC2_CONTROL_BIT2 | \
|
|
||||||
CONFIG_AXP192_EXTEN_DCDC2_CONTROL_BIT0 \
|
|
||||||
)
|
|
||||||
|
|
||||||
#define CONFIG_AXP192_DCDC13_LDO23_CONTROL ( \
|
|
||||||
CONFIG_AXP192_DCDC13_LDO23_CONTROL_BIT6 | \
|
|
||||||
CONFIG_AXP192_DCDC13_LDO23_CONTROL_BIT4 | \
|
|
||||||
CONFIG_AXP192_DCDC13_LDO23_CONTROL_BIT3 | \
|
|
||||||
CONFIG_AXP192_DCDC13_LDO23_CONTROL_BIT2 | \
|
|
||||||
CONFIG_AXP192_DCDC13_LDO23_CONTROL_BIT1 | \
|
|
||||||
CONFIG_AXP192_DCDC13_LDO23_CONTROL_BIT0 \
|
|
||||||
)
|
|
||||||
|
|
||||||
#define CONFIG_AXP192_LDO23_VOLTAGE ( \
|
|
||||||
CONFIG_AXP192_LDO23_VOLTAGE_BIT74 | \
|
|
||||||
CONFIG_AXP192_LDO23_VOLTAGE_BIT30 \
|
|
||||||
)
|
|
||||||
|
|
||||||
#define CONFIG_AXP192_DCDC1_VOLTAGE ( \
|
|
||||||
CONFIG_AXP192_DCDC1_VOLTAGE_BIT60 \
|
|
||||||
)
|
|
||||||
|
|
||||||
#define CONFIG_AXP192_DCDC3_VOLTAGE ( \
|
|
||||||
CONFIG_AXP192_DCDC3_VOLTAGE_BIT60 \
|
|
||||||
)
|
|
||||||
|
|
||||||
#define CONFIG_AXP192_ADC_ENABLE_1 ( \
|
|
||||||
CONFIG_AXP192_ADC_ENABLE_1_BIT7 | \
|
|
||||||
CONFIG_AXP192_ADC_ENABLE_1_BIT6 | \
|
|
||||||
CONFIG_AXP192_ADC_ENABLE_1_BIT5 | \
|
|
||||||
CONFIG_AXP192_ADC_ENABLE_1_BIT4 | \
|
|
||||||
CONFIG_AXP192_ADC_ENABLE_1_BIT3 | \
|
|
||||||
CONFIG_AXP192_ADC_ENABLE_1_BIT2 | \
|
|
||||||
CONFIG_AXP192_ADC_ENABLE_1_BIT1 | \
|
|
||||||
CONFIG_AXP192_ADC_ENABLE_1_BIT0 \
|
|
||||||
)
|
|
||||||
|
|
||||||
#define CONFIG_AXP192_CHARGE_CONTROL_1 ( \
|
|
||||||
CONFIG_AXP192_CHARGE_CONTROL_1_BIT7 | \
|
|
||||||
CONFIG_AXP192_CHARGE_CONTROL_1_BIT65 | \
|
|
||||||
CONFIG_AXP192_CHARGE_CONTROL_1_BIT4 | \
|
|
||||||
CONFIG_AXP192_CHARGE_CONTROL_1_BIT30 \
|
|
||||||
)
|
|
||||||
|
|
||||||
#define CONFIG_AXP192_BATTERY_CHARGE_CONTROL ( \
|
|
||||||
CONFIG_AXP192_BATTERY_CHARGE_CONTROL_BIT7 | \
|
|
||||||
CONFIG_AXP192_BATTERY_CHARGE_CONTROL_BIT65 | \
|
|
||||||
CONFIG_AXP192_BATTERY_CHARGE_CONTROL_BIT10 \
|
|
||||||
)
|
|
||||||
|
|
||||||
#define CONFIG_AXP192_GPIO0_CONTROL ( \
|
|
||||||
CONFIG_AXP192_GPIO0_CONTROL_BIT20 \
|
|
||||||
)
|
|
||||||
|
|
||||||
#define CONFIG_AXP192_GPIO1_CONTROL ( \
|
|
||||||
CONFIG_AXP192_GPIO1_CONTROL_BIT20 \
|
|
||||||
)
|
|
||||||
|
|
||||||
#define CONFIG_AXP192_GPIO2_CONTROL ( \
|
|
||||||
CONFIG_AXP192_GPIO2_CONTROL_BIT20 \
|
|
||||||
)
|
|
||||||
|
|
||||||
#define CONFIG_AXP192_GPIO43_FUNCTION_CONTROL ( \
|
|
||||||
CONFIG_AXP192_GPIO43_FUNCTION_CONTROL_BIT7 | \
|
|
||||||
CONFIG_AXP192_GPIO43_FUNCTION_CONTROL_BIT32 | \
|
|
||||||
CONFIG_AXP192_GPIO43_FUNCTION_CONTROL_BIT10 \
|
|
||||||
)
|
|
||||||
|
|
||||||
#define CONFIG_AXP192_GPIO0_LDOIO0_VOLTAGE ( \
|
|
||||||
CONFIG_AXP192_GPIO0_LDOIO0_VOLTAGE_BIT74 \
|
|
||||||
)
|
|
||||||
|
|
||||||
#endif /* AXP192_INCLUDE_SDKCONFIG_H */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
@@ -1,378 +0,0 @@
|
|||||||
#include "FT6X36.h"
|
|
||||||
|
|
||||||
#include "freertos/FreeRTOS.h"
|
|
||||||
|
|
||||||
#define CONFIG_FT6X36_DEBUG false
|
|
||||||
|
|
||||||
FT6X36 *FT6X36::_instance = nullptr;
|
|
||||||
static const char *TAG = "i2c-touch";
|
|
||||||
|
|
||||||
//Handle indicating I2C is ready to read the touch
|
|
||||||
SemaphoreHandle_t TouchSemaphore = xSemaphoreCreateBinary();
|
|
||||||
|
|
||||||
FT6X36::FT6X36(i2c_port_t port, gpio_num_t interruptPin)
|
|
||||||
{
|
|
||||||
_instance = this;
|
|
||||||
_port = port;
|
|
||||||
_intPin = interruptPin;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Destructor should detach interrupt to the pin
|
|
||||||
FT6X36::~FT6X36()
|
|
||||||
{
|
|
||||||
if (_intPin >= 0)
|
|
||||||
gpio_isr_handler_remove((gpio_num_t)_intPin);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FT6X36::begin(uint8_t threshold, uint16_t width, uint16_t height)
|
|
||||||
{
|
|
||||||
_touch_width = width;
|
|
||||||
_touch_height = height;
|
|
||||||
if (width == 0 || height ==0) {
|
|
||||||
ESP_LOGE(TAG,"begin(uint8_t threshold, uint16_t width, uint16_t height) did not receive the width / height so touch cannot be rotation aware");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t data_panel_id;
|
|
||||||
readRegister8(FT6X36_REG_PANEL_ID, &data_panel_id);
|
|
||||||
|
|
||||||
if (data_panel_id != FT6X36_VENDID) {
|
|
||||||
ESP_LOGE(TAG,"FT6X36_VENDID does not match. Received:0x%x Expected:0x%x\n",data_panel_id,FT6X36_VENDID);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
ESP_LOGI(TAG, "\tDevice ID: 0x%02x", data_panel_id);
|
|
||||||
|
|
||||||
uint8_t chip_id;
|
|
||||||
readRegister8(FT6X36_REG_CHIPID, &chip_id);
|
|
||||||
if (chip_id != FT6206_CHIPID && chip_id != FT6236_CHIPID && chip_id != FT6336_CHIPID) {
|
|
||||||
ESP_LOGE(TAG,"FT6206_CHIPID does not match. Received:0x%x\n",chip_id);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
ESP_LOGI(TAG, "\tFound touch controller with Chip ID: 0x%02x", chip_id);
|
|
||||||
|
|
||||||
if (_intPin >= 0)
|
|
||||||
{
|
|
||||||
// INT pin triggers the callback function on the Falling edge of the GPIO
|
|
||||||
gpio_config_t io_conf;
|
|
||||||
io_conf.intr_type = GPIO_INTR_NEGEDGE; // GPIO_INTR_NEGEDGE repeats always interrupt
|
|
||||||
io_conf.pin_bit_mask = 1ULL<<_intPin;
|
|
||||||
io_conf.mode = GPIO_MODE_INPUT;
|
|
||||||
io_conf.pull_down_en = (gpio_pulldown_t) 0; // disable pull-down mode
|
|
||||||
io_conf.pull_up_en = (gpio_pullup_t) 1; // pull-up mode
|
|
||||||
gpio_config(&io_conf);
|
|
||||||
|
|
||||||
esp_err_t isr_service = gpio_install_isr_service(0);
|
|
||||||
printf("ISR trigger install response: 0x%x %s\n", isr_service, (isr_service==0)?"ESP_OK":"");
|
|
||||||
gpio_isr_handler_add((gpio_num_t)_intPin, isr, (void*) 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
writeRegister8(FT6X36_REG_DEVICE_MODE, 0x00);
|
|
||||||
writeRegister8(FT6X36_REG_THRESHHOLD, threshold);
|
|
||||||
writeRegister8(FT6X36_REG_TOUCHRATE_ACTIVE, 0x0E);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FT6X36::registerTouchHandler(void (*fn)(TPoint point, TEvent e))
|
|
||||||
{
|
|
||||||
_touchHandler = fn;
|
|
||||||
if (CONFIG_FT6X36_DEBUG) printf("Touch handler function registered\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t FT6X36::touched()
|
|
||||||
{
|
|
||||||
uint8_t data_buf;
|
|
||||||
esp_err_t ret = readRegister8(FT6X36_REG_NUM_TOUCHES, &data_buf);
|
|
||||||
if (ret != ESP_OK) {
|
|
||||||
ESP_LOGE(TAG, "Error reading from device: %s", esp_err_to_name(ret));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data_buf > 2)
|
|
||||||
{
|
|
||||||
data_buf = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return data_buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FT6X36::loop()
|
|
||||||
{
|
|
||||||
processTouch();
|
|
||||||
}
|
|
||||||
|
|
||||||
void IRAM_ATTR FT6X36::isr(void* arg)
|
|
||||||
{
|
|
||||||
/* Un-block the interrupt processing task now */
|
|
||||||
xSemaphoreGive(TouchSemaphore);
|
|
||||||
//xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FT6X36::processTouch()
|
|
||||||
{
|
|
||||||
/* Task move to Block state to wait for interrupt event */
|
|
||||||
if (_intPin >= 0)
|
|
||||||
{
|
|
||||||
if (xSemaphoreTake(TouchSemaphore, portMAX_DELAY) == false) return;
|
|
||||||
}
|
|
||||||
|
|
||||||
readData();
|
|
||||||
uint8_t n = 0;
|
|
||||||
TRawEvent event = (TRawEvent)_touchEvent[n];
|
|
||||||
TPoint point{_touchX[n], _touchY[n]};
|
|
||||||
|
|
||||||
switch (event) {
|
|
||||||
|
|
||||||
case TRawEvent::PressDown:
|
|
||||||
_points[0] = point;
|
|
||||||
_dragMode = false;
|
|
||||||
// Note: Is in microseconds. Ref https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/esp_timer.html
|
|
||||||
_touchStartTime = esp_timer_get_time()/1000;
|
|
||||||
fireEvent(point, TEvent::TouchStart);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TRawEvent::Contact:
|
|
||||||
// Dragging makes no sense IMHO. Since the X & Y are not getting updated while dragging
|
|
||||||
// Dragging && _points[0].aboutEqual(point) - Not used IDEA 2: && (lastEvent == 2)
|
|
||||||
if (!_dragMode &&
|
|
||||||
(abs(lastX-_touchX[n]) <= maxDeviation || abs(lastY-_touchY[n])<=maxDeviation) &&
|
|
||||||
esp_timer_get_time()/1000 - _touchStartTime > 300) {
|
|
||||||
_dragMode = true;
|
|
||||||
fireEvent(point, TEvent::DragStart);
|
|
||||||
#if defined(CONFIG_FT6X36_DEBUG_EVENTS) && CONFIG_FT6X36_DEBUG_EVENTS==1
|
|
||||||
printf("EV: DragStart\n");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} else if (_dragMode) {
|
|
||||||
fireEvent(point, TEvent::DragMove);
|
|
||||||
#if defined(CONFIG_FT6X36_DEBUG_EVENTS) && CONFIG_FT6X36_DEBUG_EVENTS==1
|
|
||||||
printf("EV: DragMove\n");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
fireEvent(point, TEvent::TouchMove);
|
|
||||||
|
|
||||||
// For me the _touchStartTime shouold be set in both PressDown & Contact events, but after Drag detection
|
|
||||||
_touchStartTime = esp_timer_get_time()/1000;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TRawEvent::LiftUp:
|
|
||||||
|
|
||||||
_points[9] = point;
|
|
||||||
_touchEndTime = esp_timer_get_time()/1000;
|
|
||||||
|
|
||||||
//printf("TIMEDIFF: %lu End: %lu\n", _touchEndTime - _touchStartTime, _touchEndTime);
|
|
||||||
|
|
||||||
fireEvent(point, TEvent::TouchEnd);
|
|
||||||
if (_dragMode) {
|
|
||||||
fireEvent(point, TEvent::DragEnd);
|
|
||||||
#if defined(CONFIG_FT6X36_DEBUG_EVENTS) && CONFIG_FT6X36_DEBUG_EVENTS==1
|
|
||||||
printf("EV: DragEnd\n");
|
|
||||||
#endif
|
|
||||||
_dragMode = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( _touchEndTime - _touchStartTime <= 900) {
|
|
||||||
// Do not get why this: _points[0].aboutEqual(point) (Original library)
|
|
||||||
fireEvent(point, TEvent::Tap);
|
|
||||||
_points[0] = {0, 0};
|
|
||||||
_touchStartTime = 0;
|
|
||||||
|
|
||||||
#if defined(CONFIG_FT6X36_DEBUG_EVENTS) && CONFIG_FT6X36_DEBUG_EVENTS==1
|
|
||||||
printf("EV: Tap\n");
|
|
||||||
#endif
|
|
||||||
_dragMode = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TRawEvent::NoEvent:
|
|
||||||
#if defined(CONFIG_FT6X36_DEBUG_EVENTS) && CONFIG_FT6X36_DEBUG_EVENTS==1
|
|
||||||
printf("EV: NoEvent\n");
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// Store lastEvent
|
|
||||||
lastEvent = (int) event;
|
|
||||||
lastX = _touchX[0];
|
|
||||||
lastY = _touchY[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
void FT6X36::poll(TPoint * point, TEvent * e)
|
|
||||||
{
|
|
||||||
readData();
|
|
||||||
// TPoint point{_touchX[0], _touchY[0]};
|
|
||||||
TRawEvent event = (TRawEvent)_touchEvent[0];
|
|
||||||
|
|
||||||
if (point != NULL)
|
|
||||||
{
|
|
||||||
point->x = _touchX[0];
|
|
||||||
point->y = _touchY[0];
|
|
||||||
}
|
|
||||||
if (e != NULL)
|
|
||||||
{
|
|
||||||
switch (event)
|
|
||||||
{
|
|
||||||
case TRawEvent::PressDown:
|
|
||||||
*e = TEvent::TouchStart;
|
|
||||||
break;
|
|
||||||
case TRawEvent::Contact:
|
|
||||||
*e = TEvent::TouchMove;
|
|
||||||
break;
|
|
||||||
case TRawEvent::LiftUp:
|
|
||||||
default:
|
|
||||||
*e = TEvent::TouchEnd;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t FT6X36::read8(uint8_t regName) {
|
|
||||||
uint8_t buf;
|
|
||||||
readRegister8(regName, &buf);
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define data_size 16 // Discarding last 2: 0x0E & 0x0F as not relevant
|
|
||||||
bool FT6X36::readData(void)
|
|
||||||
{
|
|
||||||
esp_err_t ret;
|
|
||||||
uint8_t data[data_size];
|
|
||||||
uint8_t touch_pnt_cnt; // Number of detected touch points
|
|
||||||
readRegister8(FT6X36_REG_NUM_TOUCHES, &touch_pnt_cnt);
|
|
||||||
|
|
||||||
// Read data
|
|
||||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
|
||||||
i2c_master_start(cmd);
|
|
||||||
i2c_master_write_byte(cmd, (FT6X36_ADDR<<1), ACK_CHECK_EN);
|
|
||||||
i2c_master_write_byte(cmd, 0, ACK_CHECK_EN);
|
|
||||||
i2c_master_stop(cmd);
|
|
||||||
ret = i2c_master_cmd_begin(_port, cmd, 1000 / portTICK_PERIOD_MS);
|
|
||||||
i2c_cmd_link_delete(cmd);
|
|
||||||
if (ret != ESP_OK) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd = i2c_cmd_link_create();
|
|
||||||
i2c_master_start(cmd);
|
|
||||||
i2c_master_write_byte(cmd, (FT6X36_ADDR<<1)|1, ACK_CHECK_EN);
|
|
||||||
i2c_master_read(cmd, data, data_size, I2C_MASTER_LAST_NACK);
|
|
||||||
i2c_master_stop(cmd);
|
|
||||||
ret = i2c_master_cmd_begin(_port, cmd, 1000 / portTICK_PERIOD_MS);
|
|
||||||
i2c_cmd_link_delete(cmd);
|
|
||||||
|
|
||||||
if (CONFIG_FT6X36_DEBUG) {
|
|
||||||
//printf("REGISTERS:\n");
|
|
||||||
for (int16_t i = 0; i < data_size; i++)
|
|
||||||
{
|
|
||||||
printf("%x:%x ", i, data[i]);
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
const uint8_t addrShift = 6;
|
|
||||||
|
|
||||||
// READ X, Y and Touch events (X 2)
|
|
||||||
for (uint8_t i = 0; i < 2; i++)
|
|
||||||
{
|
|
||||||
_touchX[i] = data[FT6X36_REG_P1_XH + i * addrShift] & 0x0F;
|
|
||||||
_touchX[i] <<= 8;
|
|
||||||
_touchX[i] |= data[FT6X36_REG_P1_XL + i * addrShift];
|
|
||||||
_touchY[i] = data[FT6X36_REG_P1_YH + i * addrShift] & 0x0F;
|
|
||||||
_touchY[i] <<= 8;
|
|
||||||
_touchY[i] |= data[FT6X36_REG_P1_YL + i * addrShift];
|
|
||||||
_touchEvent[i] = data[FT6X36_REG_P1_XH + i * addrShift] >> 6;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make _touchX[idx] and _touchY[idx] rotation aware
|
|
||||||
switch (_rotation)
|
|
||||||
{
|
|
||||||
case 1:
|
|
||||||
swap(_touchX[0], _touchY[0]);
|
|
||||||
swap(_touchX[1], _touchY[1]);
|
|
||||||
_touchY[0] = _touch_width - _touchY[0] -1;
|
|
||||||
_touchY[1] = _touch_width - _touchY[1] -1;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
_touchX[0] = _touch_width - _touchX[0] - 1;
|
|
||||||
_touchX[1] = _touch_width - _touchX[1] - 1;
|
|
||||||
_touchY[0] = _touch_height - _touchY[0] - 1;
|
|
||||||
_touchY[1] = _touch_height - _touchY[1] - 1;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
swap(_touchX[0], _touchY[0]);
|
|
||||||
swap(_touchX[1], _touchY[1]);
|
|
||||||
_touchX[0] = _touch_height - _touchX[0] - 1;
|
|
||||||
_touchX[1] = _touch_height - _touchX[1] - 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (CONFIG_FT6X36_DEBUG) {
|
|
||||||
printf("X0:%d Y0:%d EVENT:%d\n", _touchX[0], _touchY[0], _touchEvent[0]);
|
|
||||||
//printf("X1:%d Y1:%d EVENT:%d\n", _touchX[1], _touchY[1], _touchEvent[1]);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FT6X36::writeRegister8(uint8_t reg, uint8_t value)
|
|
||||||
{
|
|
||||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
|
||||||
i2c_master_start(cmd);
|
|
||||||
i2c_master_write_byte(cmd, FT6X36_ADDR << 1 | I2C_MASTER_WRITE, ACK_CHECK_EN);
|
|
||||||
i2c_master_write_byte(cmd, reg , ACK_CHECK_EN);
|
|
||||||
i2c_master_write_byte(cmd, value , ACK_CHECK_EN);
|
|
||||||
i2c_master_stop(cmd);
|
|
||||||
i2c_master_cmd_begin(_port, cmd, 1000 / portTICK_PERIOD_MS);
|
|
||||||
i2c_cmd_link_delete(cmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t FT6X36::readRegister8(uint8_t reg, uint8_t *data_buf)
|
|
||||||
{
|
|
||||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
|
||||||
i2c_master_start(cmd);
|
|
||||||
i2c_master_write_byte(cmd, FT6X36_ADDR << 1 | I2C_MASTER_WRITE, ACK_CHECK_EN);
|
|
||||||
i2c_master_write_byte(cmd, reg, I2C_MASTER_ACK);
|
|
||||||
// Research: Why it's started a 2nd time here
|
|
||||||
i2c_master_start(cmd);
|
|
||||||
i2c_master_write_byte(cmd, (FT6X36_ADDR << 1) | I2C_MASTER_READ, true);
|
|
||||||
|
|
||||||
i2c_master_read_byte(cmd, data_buf, I2C_MASTER_NACK);
|
|
||||||
i2c_master_stop(cmd);
|
|
||||||
esp_err_t ret = i2c_master_cmd_begin(_port, cmd, 1000 / portTICK_PERIOD_MS);
|
|
||||||
i2c_cmd_link_delete(cmd);
|
|
||||||
|
|
||||||
|
|
||||||
//FT6X36_REG_GESTURE_ID. Check if it can be read!
|
|
||||||
#if defined(FT6X36_DEBUG) && FT6X36_DEBUG==1
|
|
||||||
printf("REG 0x%x: 0x%x\n",reg,ret);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FT6X36::fireEvent(TPoint point, TEvent e)
|
|
||||||
{
|
|
||||||
if (_touchHandler)
|
|
||||||
_touchHandler(point, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FT6X36::debugInfo()
|
|
||||||
{
|
|
||||||
printf(" TH_DIFF: %d CTRL: %d\n", read8(FT6X36_REG_FILTER_COEF), read8(FT6X36_REG_CTRL));
|
|
||||||
printf(" TIMEENTERMONITOR: %d PERIODACTIVE: %d\n", read8(FT6X36_REG_TIME_ENTER_MONITOR), read8(FT6X36_REG_TOUCHRATE_ACTIVE));
|
|
||||||
printf(" PERIODMONITOR: %d RADIAN_VALUE: %d\n", read8(FT6X36_REG_TOUCHRATE_MONITOR), read8(FT6X36_REG_RADIAN_VALUE));
|
|
||||||
printf(" OFFSET_LEFT_RIGHT: %d OFFSET_UP_DOWN: %d\n", read8(FT6X36_REG_OFFSET_LEFT_RIGHT), read8(FT6X36_REG_OFFSET_UP_DOWN));
|
|
||||||
printf("DISTANCE_LEFT_RIGHT: %d DISTANCE_UP_DOWN: %d\n", read8(FT6X36_REG_DISTANCE_LEFT_RIGHT), read8(FT6X36_REG_DISTANCE_UP_DOWN));
|
|
||||||
printf(" DISTANCE_ZOOM: %d CIPHER: %d\n", read8(FT6X36_REG_DISTANCE_ZOOM), read8(FT6X36_REG_CHIPID));
|
|
||||||
printf(" G_MODE: %d PWR_MODE: %d\n", read8(FT6X36_REG_INTERRUPT_MODE), read8(FT6X36_REG_POWER_MODE));
|
|
||||||
printf(" FIRMID: %d FOCALTECH_ID: %d STATE: %d\n", read8(FT6X36_REG_FIRMWARE_VERSION), read8(FT6X36_REG_PANEL_ID), read8(FT6X36_REG_STATE));
|
|
||||||
}
|
|
||||||
|
|
||||||
void FT6X36::setRotation(uint8_t rotation) {
|
|
||||||
_rotation = rotation;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FT6X36::setTouchWidth(uint16_t width) {
|
|
||||||
printf("touch w:%d\n",width);
|
|
||||||
_touch_width = width;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FT6X36::setTouchHeight(uint16_t height) {
|
|
||||||
printf("touch h:%d\n",height);
|
|
||||||
_touch_height = height;
|
|
||||||
}
|
|
||||||
@@ -1,184 +0,0 @@
|
|||||||
#include <stdint.h>
|
|
||||||
#include <cstdlib>
|
|
||||||
#include "driver/gpio.h"
|
|
||||||
#include "freertos/FreeRTOS.h"
|
|
||||||
#include "freertos/task.h"
|
|
||||||
#include "freertos/semphr.h"
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "esp_log.h"
|
|
||||||
#include "driver/i2c.h"
|
|
||||||
#include "sdkconfig.h"
|
|
||||||
#include <esp_timer.h>
|
|
||||||
|
|
||||||
#ifndef ft6x36_h
|
|
||||||
#define ft6x36_h
|
|
||||||
// I2C Constants
|
|
||||||
#define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
|
|
||||||
#define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
|
|
||||||
|
|
||||||
#define ACK_CHECK_EN 0x1 /*!< I2C master will check ack from slave*/
|
|
||||||
#define ACK_CHECK_DIS 0x0 /*!< I2C master will not check ack from slave */
|
|
||||||
#define ACK_VAL 0x0 /*!< I2C ack value */
|
|
||||||
#define NACK_VAL 0x1 /*!< I2C nack value */
|
|
||||||
|
|
||||||
//SemaphoreHandle_t print_mux = NULL;
|
|
||||||
|
|
||||||
#define FT6X36_ADDR 0x38
|
|
||||||
|
|
||||||
#define FT6X36_REG_DEVICE_MODE 0x00
|
|
||||||
#define FT6X36_REG_GESTURE_ID 0x01
|
|
||||||
#define FT6X36_REG_NUM_TOUCHES 0x02
|
|
||||||
#define FT6X36_REG_P1_XH 0x03
|
|
||||||
#define FT6X36_REG_P1_XL 0x04
|
|
||||||
#define FT6X36_REG_P1_YH 0x05
|
|
||||||
#define FT6X36_REG_P1_YL 0x06
|
|
||||||
#define FT6X36_REG_P1_WEIGHT 0x07
|
|
||||||
#define FT6X36_REG_P1_MISC 0x08
|
|
||||||
#define FT6X36_REG_P2_XH 0x09
|
|
||||||
#define FT6X36_REG_P2_XL 0x0A
|
|
||||||
#define FT6X36_REG_P2_YH 0x0B
|
|
||||||
#define FT6X36_REG_P2_YL 0x0C
|
|
||||||
#define FT6X36_REG_P2_WEIGHT 0x0D
|
|
||||||
#define FT6X36_REG_P2_MISC 0x0E
|
|
||||||
#define FT6X36_REG_THRESHHOLD 0x80
|
|
||||||
#define FT6X36_REG_FILTER_COEF 0x85
|
|
||||||
#define FT6X36_REG_CTRL 0x86
|
|
||||||
#define FT6X36_REG_TIME_ENTER_MONITOR 0x87
|
|
||||||
#define FT6X36_REG_TOUCHRATE_ACTIVE 0x88
|
|
||||||
#define FT6X36_REG_TOUCHRATE_MONITOR 0x89 // value in ms
|
|
||||||
#define FT6X36_REG_RADIAN_VALUE 0x91
|
|
||||||
#define FT6X36_REG_OFFSET_LEFT_RIGHT 0x92
|
|
||||||
#define FT6X36_REG_OFFSET_UP_DOWN 0x93
|
|
||||||
#define FT6X36_REG_DISTANCE_LEFT_RIGHT 0x94
|
|
||||||
#define FT6X36_REG_DISTANCE_UP_DOWN 0x95
|
|
||||||
#define FT6X36_REG_DISTANCE_ZOOM 0x96
|
|
||||||
#define FT6X36_REG_LIB_VERSION_H 0xA1
|
|
||||||
#define FT6X36_REG_LIB_VERSION_L 0xA2
|
|
||||||
#define FT6X36_REG_CHIPID 0xA3
|
|
||||||
#define FT6X36_REG_INTERRUPT_MODE 0xA4
|
|
||||||
#define FT6X36_REG_POWER_MODE 0xA5
|
|
||||||
#define FT6X36_REG_FIRMWARE_VERSION 0xA6
|
|
||||||
#define FT6X36_REG_PANEL_ID 0xA8
|
|
||||||
#define FT6X36_REG_STATE 0xBC
|
|
||||||
|
|
||||||
#define FT6X36_PMODE_ACTIVE 0x00
|
|
||||||
#define FT6X36_PMODE_MONITOR 0x01
|
|
||||||
#define FT6X36_PMODE_STANDBY 0x02
|
|
||||||
#define FT6X36_PMODE_HIBERNATE 0x03
|
|
||||||
|
|
||||||
/* Possible values returned by FT6X36_GEST_ID_REG */
|
|
||||||
#define FT6X36_GEST_ID_NO_GESTURE 0x00
|
|
||||||
#define FT6X36_GEST_ID_MOVE_UP 0x10
|
|
||||||
#define FT6X36_GEST_ID_MOVE_RIGHT 0x14
|
|
||||||
#define FT6X36_GEST_ID_MOVE_DOWN 0x18
|
|
||||||
#define FT6X36_GEST_ID_MOVE_LEFT 0x1C
|
|
||||||
#define FT6X36_GEST_ID_ZOOM_IN 0x48
|
|
||||||
#define FT6X36_GEST_ID_ZOOM_OUT 0x49
|
|
||||||
|
|
||||||
#define FT6X36_VENDID 0x11
|
|
||||||
#define FT6206_CHIPID 0x06
|
|
||||||
#define FT6236_CHIPID 0x36
|
|
||||||
#define FT6336_CHIPID 0x64
|
|
||||||
|
|
||||||
#define FT6X36_DEFAULT_THRESHOLD 22
|
|
||||||
|
|
||||||
// From: https://github.com/lvgl/lv_port_esp32/blob/master/components/lvgl_esp32_drivers/lvgl_touch/ft6x36.h
|
|
||||||
#define FT6X36_MSB_MASK 0x0F
|
|
||||||
#define FT6X36_LSB_MASK 0xFF
|
|
||||||
|
|
||||||
enum class TRawEvent
|
|
||||||
{
|
|
||||||
PressDown,
|
|
||||||
LiftUp,
|
|
||||||
Contact,
|
|
||||||
NoEvent
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class TEvent
|
|
||||||
{
|
|
||||||
None,
|
|
||||||
TouchStart,
|
|
||||||
TouchMove,
|
|
||||||
TouchEnd,
|
|
||||||
Tap,
|
|
||||||
DragStart,
|
|
||||||
DragMove,
|
|
||||||
DragEnd
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TPoint
|
|
||||||
{
|
|
||||||
uint16_t x;
|
|
||||||
uint16_t y;
|
|
||||||
/**
|
|
||||||
* This is being used in the original library but I'm not using it in this implementation
|
|
||||||
*/
|
|
||||||
bool aboutEqual(const TPoint point)
|
|
||||||
{
|
|
||||||
return abs(x - point.x) <= 5 && abs(y - point.y) <= 5;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class FT6X36
|
|
||||||
{
|
|
||||||
static void IRAM_ATTR isr(void* arg);
|
|
||||||
public:
|
|
||||||
// TwoWire * wire will be replaced by ESP-IDF https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/i2c.html
|
|
||||||
FT6X36(i2c_port_t = I2C_NUM_0, gpio_num_t interruptPin = GPIO_NUM_NC);
|
|
||||||
~FT6X36();
|
|
||||||
bool begin(uint8_t threshold = FT6X36_DEFAULT_THRESHOLD, uint16_t width = 0, uint16_t height = 0);
|
|
||||||
void registerTouchHandler(void(*fn)(TPoint point, TEvent e));
|
|
||||||
uint8_t touched();
|
|
||||||
void loop();
|
|
||||||
void processTouch();
|
|
||||||
void debugInfo();
|
|
||||||
void poll(TPoint * point, TEvent * event);
|
|
||||||
// Helper functions to make the touch display aware
|
|
||||||
void setRotation(uint8_t rotation);
|
|
||||||
void setTouchWidth(uint16_t width);
|
|
||||||
void setTouchHeight(uint16_t height);
|
|
||||||
// Pending implementation. How much x->touch y↓touch is placed (In case is smaller than display)
|
|
||||||
void setXoffset(uint16_t x_offset);
|
|
||||||
void setYoffset(uint16_t y_offset);
|
|
||||||
// Smart template from EPD to swap x,y:
|
|
||||||
template <typename T> static inline void
|
|
||||||
swap(T& a, T& b)
|
|
||||||
{
|
|
||||||
T t = a;
|
|
||||||
a = b;
|
|
||||||
b = t;
|
|
||||||
}
|
|
||||||
void(*_touchHandler)(TPoint point, TEvent e) = nullptr;
|
|
||||||
|
|
||||||
bool readData(void);
|
|
||||||
private:
|
|
||||||
void writeRegister8(uint8_t reg, uint8_t val);
|
|
||||||
uint8_t readRegister8(uint8_t reg, uint8_t *data_buf);
|
|
||||||
void fireEvent(TPoint point, TEvent e);
|
|
||||||
uint8_t read8(uint8_t regName);
|
|
||||||
static FT6X36 * _instance;
|
|
||||||
|
|
||||||
i2c_port_t _port;
|
|
||||||
int8_t _intPin;
|
|
||||||
|
|
||||||
// Make touch rotation aware:
|
|
||||||
uint8_t _rotation = 0;
|
|
||||||
uint16_t _touch_width = 0;
|
|
||||||
uint16_t _touch_height = 0;
|
|
||||||
|
|
||||||
uint8_t _touches;
|
|
||||||
uint16_t _touchX[2], _touchY[2], _touchEvent[2];
|
|
||||||
TPoint _points[10];
|
|
||||||
uint8_t _pointIdx = 0;
|
|
||||||
unsigned long _touchStartTime = 0;
|
|
||||||
unsigned long _touchEndTime = 0;
|
|
||||||
uint8_t lastEvent = 3; // No event
|
|
||||||
uint16_t lastX = 0;
|
|
||||||
uint16_t lastY = 0;
|
|
||||||
bool _dragMode = false;
|
|
||||||
const uint8_t maxDeviation = 5;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2019 strange_v
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
This project is an adaption of the code at https://github.com/martinberlin/FT6X36-IDF which is an adaptation of https://github.com/strange-v/FT6X36
|
|
||||||
The original license is an MIT license and is included in this directory.
|
|
||||||
|
|
||||||
Changes:
|
|
||||||
- Remove Kconfig-based configuratio
|
|
||||||
- Removed I2C init code
|
|
||||||
- Allow for passing a different I2C port
|
|
||||||
|
|
||||||
@@ -1,164 +0,0 @@
|
|||||||
#include "Core2Display.h"
|
|
||||||
#include "Core2DisplayConstants.h"
|
|
||||||
#include "Log.h"
|
|
||||||
|
|
||||||
#include <TactilityCore.h>
|
|
||||||
#include <esp_lcd_panel_commands.h>
|
|
||||||
|
|
||||||
#include "driver/gpio.h"
|
|
||||||
#include "esp_err.h"
|
|
||||||
#include "esp_lcd_ili9341.h"
|
|
||||||
#include "esp_lcd_panel_ops.h"
|
|
||||||
#include "esp_lvgl_port.h"
|
|
||||||
#include "Core2Touch.h"
|
|
||||||
|
|
||||||
#define TAG "core2_display"
|
|
||||||
|
|
||||||
bool Core2Display::start() {
|
|
||||||
TT_LOG_I(TAG, "Starting");
|
|
||||||
|
|
||||||
const esp_lcd_panel_io_spi_config_t panel_io_config = ILI9341_PANEL_IO_SPI_CONFIG(
|
|
||||||
CORE2_LCD_PIN_CS,
|
|
||||||
CORE2_LCD_PIN_DC,
|
|
||||||
nullptr,
|
|
||||||
nullptr
|
|
||||||
);
|
|
||||||
|
|
||||||
if (esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)CORE2_LCD_SPI_HOST, &panel_io_config, &ioHandle) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, "Failed to create panel");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const esp_lcd_panel_dev_config_t panel_config = {
|
|
||||||
.reset_gpio_num = GPIO_NUM_NC,
|
|
||||||
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_BGR,
|
|
||||||
.data_endian = LCD_RGB_DATA_ENDIAN_LITTLE,
|
|
||||||
.bits_per_pixel = CORE2_LCD_BITS_PER_PIXEL,
|
|
||||||
.flags = {
|
|
||||||
.reset_active_high = false
|
|
||||||
},
|
|
||||||
.vendor_config = nullptr
|
|
||||||
};
|
|
||||||
|
|
||||||
if (esp_lcd_new_panel_ili9341(ioHandle, &panel_config, &panelHandle) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, "Failed to create ili9341");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (esp_lcd_panel_reset(panelHandle) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, "Failed to reset panel");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (esp_lcd_panel_init(panelHandle) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, "Failed to init panel");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (esp_lcd_panel_mirror(panelHandle, false, false) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, "Failed to set panel to mirror");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (esp_lcd_panel_invert_color(panelHandle, true) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, "Failed to set panel to invert");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (esp_lcd_panel_disp_on_off(panelHandle, true) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, "Failed to turn display on");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const lvgl_port_display_cfg_t disp_cfg = {
|
|
||||||
.io_handle = ioHandle,
|
|
||||||
.panel_handle = panelHandle,
|
|
||||||
.control_handle = nullptr,
|
|
||||||
.buffer_size = CORE2_LCD_DRAW_BUFFER_SIZE,
|
|
||||||
.double_buffer = true,
|
|
||||||
.trans_size = 0,
|
|
||||||
.hres = CORE2_LCD_HORIZONTAL_RESOLUTION,
|
|
||||||
.vres = CORE2_LCD_VERTICAL_RESOLUTION,
|
|
||||||
.monochrome = false,
|
|
||||||
.rotation = {
|
|
||||||
.swap_xy = false,
|
|
||||||
.mirror_x = false,
|
|
||||||
.mirror_y = false,
|
|
||||||
},
|
|
||||||
.color_format = LV_COLOR_FORMAT_RGB565,
|
|
||||||
.flags = {
|
|
||||||
.buff_dma = false,
|
|
||||||
.buff_spiram = true,
|
|
||||||
.sw_rotate = false,
|
|
||||||
.swap_bytes = true,
|
|
||||||
.full_refresh = false,
|
|
||||||
.direct_mode = false
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
displayHandle = lvgl_port_add_disp(&disp_cfg);
|
|
||||||
TT_LOG_I(TAG, "Finished");
|
|
||||||
return displayHandle != nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Core2Display::stop() {
|
|
||||||
assert(displayHandle != nullptr);
|
|
||||||
|
|
||||||
lvgl_port_remove_disp(displayHandle);
|
|
||||||
|
|
||||||
if (esp_lcd_panel_del(panelHandle) != ESP_OK) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (esp_lcd_panel_io_del(ioHandle) != ESP_OK) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
displayHandle = nullptr;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Note:
|
|
||||||
* The datasheet implies this should work, but it doesn't:
|
|
||||||
* https://www.digikey.com/htmldatasheets/production/1640716/0/0/1/ILI9341-Datasheet.pdf
|
|
||||||
*
|
|
||||||
* This repo claims it only has 1 curve:
|
|
||||||
* https://github.com/brucemack/hello-ili9341
|
|
||||||
*
|
|
||||||
* I'm leaving it in as I'm not sure if it's just my hardware that's problematic.
|
|
||||||
*/
|
|
||||||
void Core2Display::setGammaCurve(uint8_t index) {
|
|
||||||
uint8_t gamma_curve;
|
|
||||||
switch (index) {
|
|
||||||
case 0:
|
|
||||||
gamma_curve = 0x01;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
gamma_curve = 0x04;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
gamma_curve = 0x02;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
gamma_curve = 0x08;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const uint8_t param[] = {
|
|
||||||
gamma_curve
|
|
||||||
};
|
|
||||||
|
|
||||||
if (esp_lcd_panel_io_tx_param(ioHandle , LCD_CMD_GAMSET, param, 1) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, "Failed to set gamma");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tt::hal::Touch* _Nullable Core2Display::createTouch() {
|
|
||||||
return static_cast<tt::hal::Touch*>(new Core2Touch());
|
|
||||||
}
|
|
||||||
|
|
||||||
tt::hal::Display* createDisplay() {
|
|
||||||
return static_cast<tt::hal::Display*>(new Core2Display());
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "lvgl.h"
|
|
||||||
#include "hal/Display.h"
|
|
||||||
|
|
||||||
#include <esp_lcd_types.h>
|
|
||||||
|
|
||||||
extern lv_disp_t* displayHandle;
|
|
||||||
|
|
||||||
class Core2Display : public tt::hal::Display {
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
esp_lcd_panel_io_handle_t ioHandle = nullptr;
|
|
||||||
esp_lcd_panel_handle_t panelHandle = nullptr;
|
|
||||||
lv_display_t* displayHandle = nullptr;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
bool start() override;
|
|
||||||
|
|
||||||
bool stop() override;
|
|
||||||
|
|
||||||
tt::hal::Touch* _Nullable createTouch() override;
|
|
||||||
|
|
||||||
bool supportsBacklightDuty() const override { return false; }
|
|
||||||
|
|
||||||
void setGammaCurve(uint8_t index) override;
|
|
||||||
uint8_t getGammaCurveCount() const override { return 4; };
|
|
||||||
|
|
||||||
lv_display_t* _Nullable getLvglDisplay() const override { return displayHandle; }
|
|
||||||
};
|
|
||||||
|
|
||||||
tt::hal::Display* createDisplay();
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
// Display
|
|
||||||
#define CORE2_LCD_SPI_HOST SPI2_HOST
|
|
||||||
#define CORE2_LCD_PIN_CS GPIO_NUM_5
|
|
||||||
#define CORE2_LCD_PIN_DC GPIO_NUM_15
|
|
||||||
#define CORE2_LCD_HORIZONTAL_RESOLUTION 320
|
|
||||||
#define CORE2_LCD_VERTICAL_RESOLUTION 240
|
|
||||||
#define CORE2_LCD_BITS_PER_PIXEL 16
|
|
||||||
#define CORE2_LCD_DRAW_BUFFER_HEIGHT (CORE2_LCD_VERTICAL_RESOLUTION / 10)
|
|
||||||
#define CORE2_LCD_DRAW_BUFFER_SIZE (CORE2_LCD_HORIZONTAL_RESOLUTION * CORE2_LCD_DRAW_BUFFER_HEIGHT * (CORE2_LCD_BITS_PER_PIXEL / 8))
|
|
||||||
@@ -1,108 +0,0 @@
|
|||||||
#include "Core2Power.h"
|
|
||||||
#include "TactilityCore.h"
|
|
||||||
#include "axp192/axp192.h"
|
|
||||||
|
|
||||||
#define TAG "core2_power"
|
|
||||||
|
|
||||||
extern axp192_t axpDevice;
|
|
||||||
|
|
||||||
bool Core2Power::supportsMetric(MetricType type) const {
|
|
||||||
switch (type) {
|
|
||||||
case MetricType::BatteryVoltage:
|
|
||||||
case MetricType::ChargeLevel:
|
|
||||||
case MetricType::IsCharging:
|
|
||||||
return true;
|
|
||||||
case MetricType::Current:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false; // Safety guard for when new enum values are introduced
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Core2Power::getMetric(Power::MetricType type, Power::MetricData& data) {
|
|
||||||
switch (type) {
|
|
||||||
case MetricType::BatteryVoltage: {
|
|
||||||
float voltage;
|
|
||||||
if (axp192_read(&axpDevice, AXP192_BATTERY_VOLTAGE, &voltage) == ESP_OK) {
|
|
||||||
data.valueAsUint32 = (uint32_t)TT_MAX((voltage * 1000.f), 0.0f);
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case MetricType::ChargeLevel: {
|
|
||||||
float vbat, charge_current;
|
|
||||||
if (
|
|
||||||
axp192_read(&axpDevice, AXP192_BATTERY_VOLTAGE, &vbat) == ESP_OK &&
|
|
||||||
axp192_read(&axpDevice, AXP192_CHARGE_CURRENT, &charge_current) == ESP_OK
|
|
||||||
) {
|
|
||||||
float max_voltage = 4.20f;
|
|
||||||
float min_voltage = 2.69f; // From M5Unified
|
|
||||||
float voltage_correction = (charge_current > 0.01f) ? -0.1f : 0.f; // Roughly 0.1V drop when ccharging
|
|
||||||
float corrected_voltage = vbat + voltage_correction;
|
|
||||||
if (corrected_voltage > 2.69f) {
|
|
||||||
float charge_factor = (corrected_voltage - min_voltage) / (max_voltage - min_voltage);
|
|
||||||
data.valueAsUint8 = (uint8_t)(charge_factor * 100.f);
|
|
||||||
} else {
|
|
||||||
data.valueAsUint8 = 0;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case MetricType::IsCharging: {
|
|
||||||
float charge_current;
|
|
||||||
if (axp192_read(&axpDevice, AXP192_CHARGE_CURRENT, &charge_current) == ESP_OK) {
|
|
||||||
data.valueAsBool = charge_current > 0.001f;
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case MetricType::Current: {
|
|
||||||
float charge_current, discharge_current;
|
|
||||||
if (
|
|
||||||
axp192_read(&axpDevice, AXP192_CHARGE_CURRENT, &charge_current) == ESP_OK &&
|
|
||||||
axp192_read(&axpDevice, AXP192_DISCHARGE_CURRENT, &discharge_current) == ESP_OK
|
|
||||||
) {
|
|
||||||
if (charge_current > 0.0f) {
|
|
||||||
data.valueAsInt32 = (int32_t) (charge_current * 1000.0f);
|
|
||||||
} else {
|
|
||||||
data.valueAsInt32 = -(int32_t) (discharge_current * 1000.0f);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false; // Safety guard for when new enum values are introduced
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Core2Power::isAllowedToCharge() const {
|
|
||||||
uint8_t buffer;
|
|
||||||
if (axp192_read(&axpDevice, AXP192_CHARGE_CONTROL_1, &buffer) == ESP_OK) {
|
|
||||||
return buffer & 0x80;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Core2Power::setAllowedToCharge(bool canCharge) {
|
|
||||||
uint8_t buffer;
|
|
||||||
if (axp192_read(&axpDevice, AXP192_CHARGE_CONTROL_1, &buffer) == ESP_OK) {
|
|
||||||
buffer = (buffer & 0x7F) + (canCharge ? 0x80 : 0x00);
|
|
||||||
axp192_write(&axpDevice, AXP192_CHARGE_CONTROL_1, buffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::shared_ptr<Power> power;
|
|
||||||
|
|
||||||
std::shared_ptr<Power> createPower() {
|
|
||||||
if (power == nullptr) {
|
|
||||||
power = std::make_shared<Core2Power>();
|
|
||||||
}
|
|
||||||
return power;
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "hal/Power.h"
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
using namespace tt::hal;
|
|
||||||
|
|
||||||
class Core2Power : public Power {
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
Core2Power() = default;
|
|
||||||
~Core2Power() override = default;
|
|
||||||
|
|
||||||
bool supportsMetric(MetricType type) const override;
|
|
||||||
bool getMetric(Power::MetricType type, Power::MetricData& data) override;
|
|
||||||
|
|
||||||
bool supportsChargeControl() const override { return true; }
|
|
||||||
bool isAllowedToCharge() const override;
|
|
||||||
void setAllowedToCharge(bool canCharge) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::shared_ptr<Power> createPower();
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
#include "Core2SdCard.h"
|
|
||||||
|
|
||||||
#include "lvgl/LvglSync.h"
|
|
||||||
#include "hal/SpiSdCard.h"
|
|
||||||
|
|
||||||
#include <esp_vfs_fat.h>
|
|
||||||
|
|
||||||
#define CORE2_SDCARD_PIN_CS GPIO_NUM_4
|
|
||||||
#define CORE2_LCD_PIN_CS GPIO_NUM_5
|
|
||||||
|
|
||||||
std::shared_ptr<SdCard> createSdCard() {
|
|
||||||
auto* configuration = new tt::hal::SpiSdCard::Config(
|
|
||||||
CORE2_SDCARD_PIN_CS,
|
|
||||||
GPIO_NUM_NC,
|
|
||||||
GPIO_NUM_NC,
|
|
||||||
GPIO_NUM_NC,
|
|
||||||
SdCard::MountBehaviour::AtBoot,
|
|
||||||
tt::lvgl::getLvglSyncLockable(),
|
|
||||||
{
|
|
||||||
CORE2_LCD_PIN_CS
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
auto* sdcard = (SdCard*) new SpiSdCard(
|
|
||||||
std::unique_ptr<SpiSdCard::Config>(configuration)
|
|
||||||
);
|
|
||||||
|
|
||||||
return std::shared_ptr<SdCard>(sdcard);
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "hal/SdCard.h"
|
|
||||||
|
|
||||||
using namespace tt::hal;
|
|
||||||
|
|
||||||
std::shared_ptr<SdCard> createSdCard();
|
|
||||||
@@ -1,94 +0,0 @@
|
|||||||
#include "Core2Touch.h"
|
|
||||||
#include <esp_lvgl_port.h>
|
|
||||||
|
|
||||||
#define TAG "core2_touch"
|
|
||||||
|
|
||||||
static void touchReadCallback(lv_indev_t* indev, lv_indev_data_t* data) {
|
|
||||||
auto* touch = (Core2Touch*)lv_indev_get_driver_data(indev);
|
|
||||||
touch->readLast(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int32_t threadCallback(void* context) {
|
|
||||||
auto* touch = (Core2Touch*)context;
|
|
||||||
touch->driverThreadMain();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Core2Touch::Core2Touch() :
|
|
||||||
driverThread(tt::Thread("core2_touch", 4096, threadCallback, this))
|
|
||||||
{ }
|
|
||||||
|
|
||||||
void Core2Touch::driverThreadMain() {
|
|
||||||
TPoint point = { .x = 0, .y = 0 };
|
|
||||||
TEvent event = TEvent::None;
|
|
||||||
|
|
||||||
while (!shouldInterruptDriverThread()) {
|
|
||||||
driver.processTouch();
|
|
||||||
driver.poll(&point, &event);
|
|
||||||
|
|
||||||
if (mutex.lock(100)) {
|
|
||||||
switch (event) {
|
|
||||||
case TEvent::TouchStart:
|
|
||||||
case TEvent::TouchMove:
|
|
||||||
case TEvent::DragStart:
|
|
||||||
case TEvent::DragMove:
|
|
||||||
case TEvent::DragEnd:
|
|
||||||
lastState = LV_INDEV_STATE_PR;
|
|
||||||
lastPoint.x = point.x;
|
|
||||||
lastPoint.y = point.y;
|
|
||||||
break;
|
|
||||||
case TEvent::TouchEnd:
|
|
||||||
lastState = LV_INDEV_STATE_REL;
|
|
||||||
lastPoint.x = point.x;
|
|
||||||
lastPoint.y = point.y;
|
|
||||||
break;
|
|
||||||
case TEvent::Tap:
|
|
||||||
case TEvent::None:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
mutex.unlock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Core2Touch::shouldInterruptDriverThread() {
|
|
||||||
bool interrupt = false;
|
|
||||||
if (mutex.lock(50 / portTICK_PERIOD_MS)) {
|
|
||||||
interrupt = interruptDriverThread;
|
|
||||||
mutex.unlock();
|
|
||||||
}
|
|
||||||
return interrupt;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Core2Touch::start(lv_display_t* display) {
|
|
||||||
TT_LOG_I(TAG, "start");
|
|
||||||
|
|
||||||
driverThread.start();
|
|
||||||
|
|
||||||
uint16_t width = lv_display_get_horizontal_resolution(display);
|
|
||||||
uint16_t height = lv_display_get_vertical_resolution(display);
|
|
||||||
if (!driver.begin(FT6X36_DEFAULT_THRESHOLD, width, height)) {
|
|
||||||
TT_LOG_E(TAG, "driver.begin() failed");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
deviceHandle = lv_indev_create();
|
|
||||||
lv_indev_set_type(deviceHandle, LV_INDEV_TYPE_POINTER);
|
|
||||||
lv_indev_set_driver_data(deviceHandle, this);
|
|
||||||
lv_indev_set_read_cb(deviceHandle, touchReadCallback);
|
|
||||||
|
|
||||||
TT_LOG_I(TAG, "start success");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Core2Touch::stop() {
|
|
||||||
lv_indev_delete(deviceHandle);
|
|
||||||
interruptDriverThread = true;
|
|
||||||
driverThread.join();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Core2Touch::readLast(lv_indev_data_t* data) {
|
|
||||||
data->point = lastPoint;
|
|
||||||
data->state = lastState;
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "hal/Touch.h"
|
|
||||||
#include "TactilityCore.h"
|
|
||||||
#include "ft6x36/FT6X36.h"
|
|
||||||
|
|
||||||
class Core2Touch : public tt::hal::Touch {
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
lv_indev_t* _Nullable deviceHandle = nullptr;
|
|
||||||
FT6X36 driver = FT6X36(I2C_NUM_0, GPIO_NUM_39);
|
|
||||||
tt::Thread driverThread;
|
|
||||||
bool interruptDriverThread = false;
|
|
||||||
tt::Mutex mutex;
|
|
||||||
|
|
||||||
lv_point_t lastPoint = { .x = 0, .y = 0 };
|
|
||||||
lv_indev_state_t lastState = LV_INDEV_STATE_RELEASED;
|
|
||||||
|
|
||||||
bool shouldInterruptDriverThread();
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
Core2Touch();
|
|
||||||
|
|
||||||
bool start(lv_display_t* display) override;
|
|
||||||
bool stop() override;
|
|
||||||
|
|
||||||
void readLast(lv_indev_data_t* data);
|
|
||||||
lv_indev_t* _Nullable getLvglIndev() override { return deviceHandle; }
|
|
||||||
void driverThreadMain();
|
|
||||||
};
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
idf_component_register(
|
|
||||||
SRC_DIRS "Source" "Source/hal" "Source/Axp2101" "Source/Aw9523"
|
|
||||||
INCLUDE_DIRS "Source"
|
|
||||||
REQUIRES Tactility esp_lvgl_port esp_lcd esp_lcd_ili9341 esp_lcd_touch_ft5x06 driver vfs fatfs
|
|
||||||
)
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
# M5Stack CoreS3
|
|
||||||
|
|
||||||
Reference implementations:
|
|
||||||
- [ESP-BSP](https://github.com/espressif/esp-bsp/tree/master/bsp/m5stack_core_s3)
|
|
||||||
- [M5Unified](https://github.com/m5stack/M5Unified)
|
|
||||||
- [M5GFX](https://github.com/m5stack/M5GFX)
|
|
||||||
|
|
||||||
Docs:
|
|
||||||
- [M5Stack.com](https://docs.m5stack.com/en/core/CoreS3)
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
#include "Aw9523.h"
|
|
||||||
|
|
||||||
#define AW9523_REGISTER_P0 0x02
|
|
||||||
#define AW9523_REGISTER_P1 0x03
|
|
||||||
|
|
||||||
bool Aw9523::readP0(uint8_t& output) const {
|
|
||||||
return readRegister8(AW9523_REGISTER_P0, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Aw9523::readP1(uint8_t& output) const {
|
|
||||||
return readRegister8(AW9523_REGISTER_P1, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Aw9523::writeP0(uint8_t value) const {
|
|
||||||
return writeRegister8(AW9523_REGISTER_P0, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Aw9523::writeP1(uint8_t value) const {
|
|
||||||
return writeRegister8(AW9523_REGISTER_P1, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Aw9523::bitOnP1(uint8_t bitmask) const {
|
|
||||||
return bitOn(AW9523_REGISTER_P1, bitmask);
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "hal/i2c/I2cDevice.h"
|
|
||||||
|
|
||||||
#define AW9523_ADDRESS 0x58
|
|
||||||
|
|
||||||
class Aw9523 : I2cDevice {
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
explicit Aw9523(i2c_port_t port) : I2cDevice(port, AW9523_ADDRESS) {}
|
|
||||||
|
|
||||||
bool readP0(uint8_t& output) const;
|
|
||||||
bool readP1(uint8_t& output) const;
|
|
||||||
|
|
||||||
bool writeP0(uint8_t value) const;
|
|
||||||
bool writeP1(uint8_t value) const;
|
|
||||||
|
|
||||||
bool bitOnP1(uint8_t bitmask) const;
|
|
||||||
};
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
#include "Axp2101.h"
|
|
||||||
#include "Log.h"
|
|
||||||
|
|
||||||
bool Axp2101::getBatteryVoltage(float& vbatMillis) const {
|
|
||||||
return readRegister14(0x34, vbatMillis);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Axp2101::getChargeStatus(ChargeStatus& status) const {
|
|
||||||
uint8_t value;
|
|
||||||
if (readRegister8(0x01, value)) {
|
|
||||||
value = (value >> 5) & 0b11;
|
|
||||||
status = (value == 1) ? CHARGE_STATUS_CHARGING : ((value == 2) ? CHARGE_STATUS_DISCHARGING : CHARGE_STATUS_STANDBY);
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Axp2101::isChargingEnabled(bool& enabled) const {
|
|
||||||
uint8_t value;
|
|
||||||
if (readRegister8(0x18, value)) {
|
|
||||||
enabled = value & 0b10;
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Axp2101::setChargingEnabled(bool enabled) const {
|
|
||||||
uint8_t value;
|
|
||||||
if (readRegister8(0x18, value)) {
|
|
||||||
return writeRegister8(0x18, (value & 0xFD) | (enabled << 1));
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Axp2101::isVBus() const {
|
|
||||||
uint8_t value;
|
|
||||||
return readRegister8(0x00, value) && (value & 0x20);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Axp2101::getVBusVoltage(float& out) const {
|
|
||||||
if (!isVBus()) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
float vbus;
|
|
||||||
if (readRegister14(0x38, vbus) && vbus < 16375) {
|
|
||||||
out = vbus / 1000.0f;
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Axp2101::setRegisters(uint8_t* bytePairs, size_t bytePairsSize) const {
|
|
||||||
return tt::hal::i2c::masterWriteRegisterArray(port, address, bytePairs, bytePairsSize, DEFAULT_TIMEOUT);
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "hal/i2c/I2cDevice.h"
|
|
||||||
|
|
||||||
#define AXP2101_ADDRESS 0x34
|
|
||||||
|
|
||||||
/**
|
|
||||||
* References:
|
|
||||||
* - https://github.com/m5stack/M5Unified/blob/master/src/utility/AXP2101_Class.cpp
|
|
||||||
* - http://file.whycan.com/files/members/6736/AXP2101_Datasheet_V1.0_en_3832.pdf
|
|
||||||
*/
|
|
||||||
class Axp2101 : I2cDevice {
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
enum ChargeStatus {
|
|
||||||
CHARGE_STATUS_CHARGING = 0b01,
|
|
||||||
CHARGE_STATUS_DISCHARGING = 0b10,
|
|
||||||
CHARGE_STATUS_STANDBY = 0b00
|
|
||||||
};
|
|
||||||
|
|
||||||
explicit Axp2101(i2c_port_t port) : I2cDevice(port, AXP2101_ADDRESS) {}
|
|
||||||
|
|
||||||
bool setRegisters(uint8_t* bytePairs, size_t bytePairsSize) const;
|
|
||||||
|
|
||||||
bool getBatteryVoltage(float& vbatMillis) const;
|
|
||||||
bool getChargeStatus(ChargeStatus& status) const;
|
|
||||||
bool isChargingEnabled(bool& enabled) const;
|
|
||||||
bool setChargingEnabled(bool enabled) const;
|
|
||||||
|
|
||||||
bool isVBus() const;
|
|
||||||
bool getVBusVoltage(float& out) const;
|
|
||||||
};
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#define AXP2101_ADDRESS 0x34
|
|
||||||
#define AW9523_ADDRESS 0x58
|
|
||||||
@@ -1,185 +0,0 @@
|
|||||||
#include <driver/i2c.h>
|
|
||||||
#include <driver/spi_master.h>
|
|
||||||
#include <esp_intr_types.h>
|
|
||||||
#include "Log.h"
|
|
||||||
#include "hal/CoreS3DisplayConstants.h"
|
|
||||||
#include "kernel/Kernel.h"
|
|
||||||
#include "Axp2101/Axp2101.h"
|
|
||||||
#include "Aw9523/Aw9523.h"
|
|
||||||
|
|
||||||
#define TAG "core2"
|
|
||||||
|
|
||||||
#define CORES3_SPI2_PIN_SCLK GPIO_NUM_36
|
|
||||||
#define CORES3_SPI2_PIN_MOSI GPIO_NUM_37
|
|
||||||
#define CORES3_SPI2_PIN_MISO GPIO_NUM_35
|
|
||||||
|
|
||||||
/**
|
|
||||||
* For details see https://github.com/espressif/esp-bsp/blob/master/bsp/m5stack_core_s3/m5stack_core_s3.c
|
|
||||||
*/
|
|
||||||
static bool initSpi3() {
|
|
||||||
TT_LOG_I(TAG, LOG_MESSAGE_SPI_INIT_START_FMT, SPI3_HOST);
|
|
||||||
const spi_bus_config_t bus_config = {
|
|
||||||
.mosi_io_num = CORES3_SPI2_PIN_MOSI,
|
|
||||||
.miso_io_num = CORES3_SPI2_PIN_MISO,
|
|
||||||
.sclk_io_num = CORES3_SPI2_PIN_SCLK,
|
|
||||||
.data2_io_num = GPIO_NUM_NC,
|
|
||||||
.data3_io_num = GPIO_NUM_NC,
|
|
||||||
.data4_io_num = GPIO_NUM_NC,
|
|
||||||
.data5_io_num = GPIO_NUM_NC,
|
|
||||||
.data6_io_num = GPIO_NUM_NC,
|
|
||||||
.data7_io_num = GPIO_NUM_NC,
|
|
||||||
.data_io_default_level = false,
|
|
||||||
.max_transfer_sz = CORES3_LCD_DRAW_BUFFER_SIZE,
|
|
||||||
.flags = 0,
|
|
||||||
.isr_cpu_id = ESP_INTR_CPU_AFFINITY_AUTO,
|
|
||||||
.intr_flags = 0
|
|
||||||
};
|
|
||||||
|
|
||||||
if (spi_bus_initialize(SPI3_HOST, &bus_config, SPI_DMA_CH_AUTO) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, LOG_MESSAGE_SPI_INIT_FAILED_FMT, SPI3_HOST);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* For details see https://github.com/espressif/esp-bsp/blob/master/bsp/m5stack_core_s3/m5stack_core_s3.c
|
|
||||||
* and schematic: https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/docs/datasheet/core/K128%20CoreS3/Sch_M5_CoreS3_v1.0.pdf
|
|
||||||
*/
|
|
||||||
bool initGpioExpander() {
|
|
||||||
TT_LOG_I(TAG, "AW9523 init");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* P0 pins:
|
|
||||||
* 0: Touch reset
|
|
||||||
* 1: Bus out enable
|
|
||||||
* 2: AW88298 reset (I2S)
|
|
||||||
* 3: ES7210 interrupt (Audio ADC)
|
|
||||||
* 4: SD Card SW(itch on?)
|
|
||||||
* 5: USB OTG enable
|
|
||||||
* 6: /
|
|
||||||
* 7: /
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* P1 pins:
|
|
||||||
* 0: Cam reset
|
|
||||||
* 1: LCD reset
|
|
||||||
* 2: Touch interrupt
|
|
||||||
* 3: AW88298 interrupt (I2S)
|
|
||||||
* 4: /
|
|
||||||
* 5: /
|
|
||||||
* 6: /
|
|
||||||
* 7: Boost enable
|
|
||||||
*/
|
|
||||||
|
|
||||||
uint8_t p0_state = 0U;
|
|
||||||
uint8_t p1_state = 0U;
|
|
||||||
|
|
||||||
// Enable touch
|
|
||||||
p0_state |= (1U);
|
|
||||||
// Bus out enable
|
|
||||||
p0_state |= (1U << 1U);
|
|
||||||
// I2S
|
|
||||||
p0_state |= (1U << 2U);
|
|
||||||
// SD card
|
|
||||||
p0_state |= (1U << 4U);
|
|
||||||
|
|
||||||
// Enable LCD
|
|
||||||
p1_state |= (1U << 1U);
|
|
||||||
// Boost enable
|
|
||||||
p1_state |= (1U << 7U);
|
|
||||||
|
|
||||||
Aw9523 aw(I2C_NUM_0);
|
|
||||||
|
|
||||||
if (!aw.writeP0(p0_state)) {
|
|
||||||
TT_LOG_E(TAG, "AW9523: Failed to set P0");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!aw.writeP1(p1_state)) {
|
|
||||||
TT_LOG_E(TAG, "AW9523: Failed to set P1");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Axp2101 axp(I2C_NUM_0);
|
|
||||||
if (axp.isVBus()) {
|
|
||||||
float voltage = 0.0f;
|
|
||||||
axp.getVBusVoltage(voltage);
|
|
||||||
TT_LOG_I(TAG, "AXP2101: VBus at %.2f", voltage);
|
|
||||||
} else {
|
|
||||||
TT_LOG_W(TAG, "AXP2101: VBus disabled");
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool initPowerControl() {
|
|
||||||
TT_LOG_I(TAG, "Init power control (AXP2101)");
|
|
||||||
|
|
||||||
Aw9523 aw(I2C_NUM_0);
|
|
||||||
// Source: https://github.com/m5stack/M5Unified/blob/b8cfec7fed046242da7f7b8024a4e92004a51ff7/src/utility/Power_Class.cpp#L61
|
|
||||||
aw.bitOnP1(0b10000000); // SY7088 boost enable
|
|
||||||
|
|
||||||
/** AXP2101 usage
|
|
||||||
Source: https://github.com/m5stack/M5Unified/blob/b8cfec7fed046242da7f7b8024a4e92004a51ff7/README.md?plain=1#L223
|
|
||||||
| |M5Stack<BR>CoreS3<BR>CoreS3SE| |
|
|
||||||
|:---------:|:-----------------:|:---------:|
|
|
||||||
| ALDO1 |VDD 1v8 | ALDO1 |
|
|
||||||
| ALDO2 |VDDA 3v3 | ALDO2 |
|
|
||||||
| ALDO3 |CAM 3v3 | ALDO3 |
|
|
||||||
| ALDO4 |TF 3v3 | ALDO4 |
|
|
||||||
| BLDO1 |AVDD | BLDO1 |
|
|
||||||
| BLDO2 |DVDD | BLDO2 |
|
|
||||||
| DLDO1/DC1 |LCD BL | DLDO1/DC1 |
|
|
||||||
| DLDO2/DC2 | --- | DLDO2/DC2 |
|
|
||||||
| BACKUP |RTC BAT | BACKUP |
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 0x92 = ALD01
|
|
||||||
* 0x93 = ALD02
|
|
||||||
* 0x94 = ALD03
|
|
||||||
* 0x95 = ALD04
|
|
||||||
* 0x96 = BLD01
|
|
||||||
* 0x97 = BLD02
|
|
||||||
*
|
|
||||||
* DCDC1 : 0.7-3.5V, 25mV/step 1200mA
|
|
||||||
* DCDC2 : 0.7-2.275V,25mV/step 1600mA
|
|
||||||
* DCDC3 : 0.7-3.5V, 25mV/step 700mA
|
|
||||||
|
|
||||||
* LDOio0: 1.8-3.3V, 100mV/step 50mA
|
|
||||||
* LDO1 : 30mA always on
|
|
||||||
* LDO2 : 1.8-3.3V, 100mV/step 200mA
|
|
||||||
* LDO3 : 1.8-3.3V, 100mV/step 200mA
|
|
||||||
*/
|
|
||||||
// Source: https://github.com/m5stack/M5Unified/blob/b8cfec7fed046242da7f7b8024a4e92004a51ff7/src/utility/Power_Class.cpp#L64
|
|
||||||
static constexpr uint8_t reg_data_array[] = {
|
|
||||||
0x90U, 0xBFU, // LDOS ON/OFF control 0 (backlight)
|
|
||||||
0x92U, 18U -5U, // ALDO1 set to 1.8v // for AW88298
|
|
||||||
0x93U, 33U -5U, // ALDO2 set to 3.3v // for ES7210
|
|
||||||
0x94U, 33U -5U, // ALDO3 set to 3.3v // for camera
|
|
||||||
0x95U, 33U -5U, // ALDO3 set to 3.3v // for TF card slot
|
|
||||||
0x27, 0x00, // PowerKey Hold=1sec / PowerOff=4sec
|
|
||||||
0x69, 0x11, // CHGLED setting
|
|
||||||
0x10, 0x30, // PMU common config
|
|
||||||
0x30, 0x0F // ADC enabled (for voltage measurement)
|
|
||||||
};
|
|
||||||
|
|
||||||
Axp2101 axp(I2C_NUM_0);
|
|
||||||
if (axp.setRegisters((uint8_t*)reg_data_array, sizeof(reg_data_array))) {
|
|
||||||
TT_LOG_I(TAG, "AXP2101 initialized with %d registers", sizeof(reg_data_array) / 2);
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
TT_LOG_E(TAG, "AXP2101: Failed to set registers");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool initBoot() {
|
|
||||||
TT_LOG_I(TAG, "initBoot()");
|
|
||||||
return initPowerControl() &&
|
|
||||||
initGpioExpander() &&
|
|
||||||
initSpi3();
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
bool initBoot();
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
#include "Log.h"
|
|
||||||
#include "Thread.h"
|
|
||||||
#include "lvgl/LvglSync.h"
|
|
||||||
#include "esp_lvgl_port.h"
|
|
||||||
|
|
||||||
#define TAG "core2"
|
|
||||||
|
|
||||||
// LVGL
|
|
||||||
// The minimum task stack seems to be about 3500, but that crashes the wifi app in some scenarios
|
|
||||||
// At 4000, it crashes when the fps renderer is available
|
|
||||||
#define CORE2_LVGL_TASK_STACK_DEPTH 9216
|
|
||||||
|
|
||||||
bool initLvgl() {
|
|
||||||
const lvgl_port_cfg_t lvgl_cfg = {
|
|
||||||
.task_priority = static_cast<UBaseType_t>(tt::THREAD_PRIORITY_RENDER),
|
|
||||||
.task_stack = CORE2_LVGL_TASK_STACK_DEPTH,
|
|
||||||
.task_affinity = -1, // core pinning
|
|
||||||
.task_max_sleep_ms = 500,
|
|
||||||
.timer_period_ms = 5
|
|
||||||
};
|
|
||||||
|
|
||||||
TT_LOG_D(TAG, "LVGL port init");
|
|
||||||
if (lvgl_port_init(&lvgl_cfg) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, "LVGL port init failed");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
tt::lvgl::syncSet(&lvgl_port_lock, &lvgl_port_unlock);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
bool initLvgl();
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
#include "M5stackCoreS3.h"
|
|
||||||
#include "InitBoot.h"
|
|
||||||
#include "InitLvgl.h"
|
|
||||||
#include "hal/CoreS3Display.h"
|
|
||||||
#include "hal/CoreS3SdCard.h"
|
|
||||||
#include "hal/CoreS3Power.h"
|
|
||||||
|
|
||||||
const tt::hal::Configuration m5stack_cores3 = {
|
|
||||||
.initBoot = initBoot,
|
|
||||||
.initLvgl = initLvgl,
|
|
||||||
.createDisplay = createDisplay,
|
|
||||||
.sdcard = createSdCard(),
|
|
||||||
.power = createPower,
|
|
||||||
.i2c = {
|
|
||||||
tt::hal::i2c::Configuration {
|
|
||||||
.name = "Internal",
|
|
||||||
.port = I2C_NUM_0,
|
|
||||||
.initMode = tt::hal::i2c::InitMode::ByTactility,
|
|
||||||
.canReinit = false,
|
|
||||||
.hasMutableConfiguration = false,
|
|
||||||
.config = (i2c_config_t) {
|
|
||||||
.mode = I2C_MODE_MASTER,
|
|
||||||
.sda_io_num = GPIO_NUM_12,
|
|
||||||
.scl_io_num = GPIO_NUM_11,
|
|
||||||
.sda_pullup_en = true,
|
|
||||||
.scl_pullup_en = true,
|
|
||||||
.master = {
|
|
||||||
.clk_speed = 400000
|
|
||||||
},
|
|
||||||
.clk_flags = 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
tt::hal::i2c::Configuration {
|
|
||||||
.name = "External", // Grove
|
|
||||||
.port = I2C_NUM_1,
|
|
||||||
.initMode = tt::hal::i2c::InitMode::ByTactility,
|
|
||||||
.canReinit = true,
|
|
||||||
.hasMutableConfiguration = true,
|
|
||||||
.config = (i2c_config_t) {
|
|
||||||
.mode = I2C_MODE_MASTER,
|
|
||||||
.sda_io_num = GPIO_NUM_2,
|
|
||||||
.scl_io_num = GPIO_NUM_1,
|
|
||||||
.sda_pullup_en = true,
|
|
||||||
.scl_pullup_en = true,
|
|
||||||
.master = {
|
|
||||||
.clk_speed = 400000
|
|
||||||
},
|
|
||||||
.clk_flags = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "hal/Configuration.h"
|
|
||||||
|
|
||||||
extern const tt::hal::Configuration m5stack_cores3;
|
|
||||||
@@ -1,191 +0,0 @@
|
|||||||
#include "CoreS3Display.h"
|
|
||||||
#include "CoreS3DisplayConstants.h"
|
|
||||||
#include "Log.h"
|
|
||||||
|
|
||||||
#include <TactilityCore.h>
|
|
||||||
#include <esp_lcd_panel_commands.h>
|
|
||||||
|
|
||||||
#include "driver/gpio.h"
|
|
||||||
#include "esp_err.h"
|
|
||||||
#include "esp_lcd_ili9341.h"
|
|
||||||
#include "esp_lcd_panel_ops.h"
|
|
||||||
#include "esp_lvgl_port.h"
|
|
||||||
#include "hal/i2c/I2c.h"
|
|
||||||
#include "CoreS3Constants.h"
|
|
||||||
#include "CoreS3Touch.h"
|
|
||||||
|
|
||||||
#define TAG "cores3_display"
|
|
||||||
|
|
||||||
bool CoreS3Display::start() {
|
|
||||||
TT_LOG_I(TAG, "Starting");
|
|
||||||
|
|
||||||
const esp_lcd_panel_io_spi_config_t panel_io_config = {
|
|
||||||
.cs_gpio_num = CORES3_LCD_PIN_CS,
|
|
||||||
.dc_gpio_num = CORES3_LCD_PIN_DC,
|
|
||||||
.spi_mode = 0,
|
|
||||||
.pclk_hz = 40000000,
|
|
||||||
.trans_queue_depth = 10,
|
|
||||||
.on_color_trans_done = nullptr,
|
|
||||||
.user_ctx = nullptr,
|
|
||||||
.lcd_cmd_bits = 8,
|
|
||||||
.lcd_param_bits = 8,
|
|
||||||
.cs_ena_pretrans = 0,
|
|
||||||
.cs_ena_posttrans = 0,
|
|
||||||
.flags = {
|
|
||||||
.dc_high_on_cmd = 0,
|
|
||||||
.dc_low_on_data = 0,
|
|
||||||
.dc_low_on_param = 0,
|
|
||||||
.octal_mode = 0,
|
|
||||||
.quad_mode = 0,
|
|
||||||
.sio_mode = 0,
|
|
||||||
.lsb_first = 0,
|
|
||||||
.cs_high_active = 0
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)CORES3_LCD_SPI_HOST, &panel_io_config, &ioHandle) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, "Failed to create panel");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const esp_lcd_panel_dev_config_t panel_config = {
|
|
||||||
.reset_gpio_num = GPIO_NUM_NC,
|
|
||||||
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_BGR,
|
|
||||||
.data_endian = LCD_RGB_DATA_ENDIAN_LITTLE,
|
|
||||||
.bits_per_pixel = CORES3_LCD_BITS_PER_PIXEL,
|
|
||||||
.flags = {
|
|
||||||
.reset_active_high = false
|
|
||||||
},
|
|
||||||
.vendor_config = nullptr
|
|
||||||
};
|
|
||||||
|
|
||||||
if (esp_lcd_new_panel_ili9341(ioHandle, &panel_config, &panelHandle) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, "Failed to create ili9341");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (esp_lcd_panel_reset(panelHandle) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, "Failed to reset panel");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (esp_lcd_panel_init(panelHandle) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, "Failed to init panel");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (esp_lcd_panel_mirror(panelHandle, false, false) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, "Failed to set panel to mirror");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (esp_lcd_panel_invert_color(panelHandle, true) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, "Failed to set panel to invert");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (esp_lcd_panel_disp_on_off(panelHandle, true) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, "Failed to turn display on");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const lvgl_port_display_cfg_t disp_cfg = {
|
|
||||||
.io_handle = ioHandle,
|
|
||||||
.panel_handle = panelHandle,
|
|
||||||
.control_handle = nullptr,
|
|
||||||
.buffer_size = CORES3_LCD_DRAW_BUFFER_SIZE,
|
|
||||||
.double_buffer = true,
|
|
||||||
.trans_size = 0,
|
|
||||||
.hres = CORES3_LCD_HORIZONTAL_RESOLUTION,
|
|
||||||
.vres = CORES3_LCD_VERTICAL_RESOLUTION,
|
|
||||||
.monochrome = false,
|
|
||||||
.rotation = {
|
|
||||||
.swap_xy = false,
|
|
||||||
.mirror_x = false,
|
|
||||||
.mirror_y = false,
|
|
||||||
},
|
|
||||||
.color_format = LV_COLOR_FORMAT_RGB565,
|
|
||||||
.flags = {
|
|
||||||
.buff_dma = false,
|
|
||||||
.buff_spiram = true,
|
|
||||||
.sw_rotate = false,
|
|
||||||
.swap_bytes = true,
|
|
||||||
.full_refresh = false,
|
|
||||||
.direct_mode = false
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
displayHandle = lvgl_port_add_disp(&disp_cfg);
|
|
||||||
TT_LOG_I(TAG, "Finished");
|
|
||||||
return displayHandle != nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CoreS3Display::stop() {
|
|
||||||
assert(displayHandle != nullptr);
|
|
||||||
|
|
||||||
lvgl_port_remove_disp(displayHandle);
|
|
||||||
|
|
||||||
if (esp_lcd_panel_del(panelHandle) != ESP_OK) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (esp_lcd_panel_io_del(ioHandle) != ESP_OK) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
displayHandle = nullptr;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Note:
|
|
||||||
* The datasheet implies this should work, but it doesn't:
|
|
||||||
* https://www.digikey.com/htmldatasheets/production/1640716/0/0/1/ILI9341-Datasheet.pdf
|
|
||||||
*
|
|
||||||
* This repo claims it only has 1 curve:
|
|
||||||
* https://github.com/brucemack/hello-ili9341
|
|
||||||
*
|
|
||||||
* I'm leaving it in as I'm not sure if it's just my hardware that's problematic.
|
|
||||||
*/
|
|
||||||
void CoreS3Display::setGammaCurve(uint8_t index) {
|
|
||||||
uint8_t gamma_curve;
|
|
||||||
switch (index) {
|
|
||||||
case 0:
|
|
||||||
gamma_curve = 0x01;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
gamma_curve = 0x04;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
gamma_curve = 0x02;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
gamma_curve = 0x08;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const uint8_t param[] = {
|
|
||||||
gamma_curve
|
|
||||||
};
|
|
||||||
|
|
||||||
if (esp_lcd_panel_io_tx_param(ioHandle , LCD_CMD_GAMSET, param, 1) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, "Failed to set gamma");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreS3Display::setBacklightDuty(uint8_t backlightDuty) {
|
|
||||||
const uint8_t voltage = 20 + ((8 * backlightDuty) / 255); // [0b00000, 0b11100] - under 20 is too dark
|
|
||||||
// TODO: Refactor to use Axp2102 class with https://github.com/m5stack/M5Unified/blob/b8cfec7fed046242da7f7b8024a4e92004a51ff7/src/utility/AXP2101_Class.cpp#L42
|
|
||||||
if (!tt::hal::i2c::masterWriteRegister(I2C_NUM_0, AXP2101_ADDRESS, 0x99, &voltage, 1, 1000)) { // Sets DLD01
|
|
||||||
TT_LOG_E(TAG, "Failed to set display backlight voltage");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tt::hal::Touch* _Nullable CoreS3Display::createTouch() {
|
|
||||||
return static_cast<tt::hal::Touch*>(new CoreS3Touch());
|
|
||||||
}
|
|
||||||
|
|
||||||
tt::hal::Display* createDisplay() {
|
|
||||||
return static_cast<tt::hal::Display*>(new CoreS3Display());
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "lvgl.h"
|
|
||||||
#include "hal/Display.h"
|
|
||||||
|
|
||||||
#include <esp_lcd_types.h>
|
|
||||||
|
|
||||||
extern lv_disp_t* displayHandle;
|
|
||||||
|
|
||||||
class CoreS3Display : public tt::hal::Display {
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
esp_lcd_panel_io_handle_t ioHandle = nullptr;
|
|
||||||
esp_lcd_panel_handle_t panelHandle = nullptr;
|
|
||||||
lv_display_t* displayHandle = nullptr;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
bool start() override;
|
|
||||||
|
|
||||||
bool stop() override;
|
|
||||||
|
|
||||||
tt::hal::Touch* _Nullable createTouch() override;
|
|
||||||
|
|
||||||
void setBacklightDuty(uint8_t backlightDuty) override;
|
|
||||||
bool supportsBacklightDuty() const override { return true; }
|
|
||||||
|
|
||||||
void setGammaCurve(uint8_t index) override;
|
|
||||||
uint8_t getGammaCurveCount() const override { return 4; };
|
|
||||||
|
|
||||||
lv_display_t* _Nullable getLvglDisplay() const override { return displayHandle; }
|
|
||||||
};
|
|
||||||
|
|
||||||
tt::hal::Display* createDisplay();
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
// Display
|
|
||||||
#define CORES3_LCD_SPI_HOST SPI3_HOST
|
|
||||||
#define CORES3_LCD_PIN_CS GPIO_NUM_3
|
|
||||||
#define CORES3_LCD_PIN_DC GPIO_NUM_35
|
|
||||||
#define CORES3_LCD_HORIZONTAL_RESOLUTION 320
|
|
||||||
#define CORES3_LCD_VERTICAL_RESOLUTION 240
|
|
||||||
#define CORES3_LCD_BITS_PER_PIXEL 16
|
|
||||||
#define CORES3_LCD_DRAW_BUFFER_HEIGHT (CORES3_LCD_VERTICAL_RESOLUTION / 10)
|
|
||||||
#define CORES3_LCD_DRAW_BUFFER_SIZE (CORES3_LCD_HORIZONTAL_RESOLUTION * CORES3_LCD_DRAW_BUFFER_HEIGHT * (CORES3_LCD_BITS_PER_PIXEL / 8))
|
|
||||||
@@ -1,83 +0,0 @@
|
|||||||
#include "CoreS3Power.h"
|
|
||||||
#include "TactilityCore.h"
|
|
||||||
|
|
||||||
#define TAG "core2_power"
|
|
||||||
|
|
||||||
bool CoreS3Power::supportsMetric(MetricType type) const {
|
|
||||||
switch (type) {
|
|
||||||
case MetricType::BatteryVoltage:
|
|
||||||
case MetricType::IsCharging:
|
|
||||||
case MetricType::ChargeLevel:
|
|
||||||
return true;
|
|
||||||
case MetricType::Current:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false; // Safety guard for when new enum values are introduced
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CoreS3Power::getMetric(Power::MetricType type, Power::MetricData& data) {
|
|
||||||
switch (type) {
|
|
||||||
case MetricType::BatteryVoltage: {
|
|
||||||
float milliVolt;
|
|
||||||
if (axpDevice.getBatteryVoltage(milliVolt)) {
|
|
||||||
data.valueAsUint32 = (uint32_t)milliVolt;
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case MetricType::ChargeLevel: {
|
|
||||||
float vbatMillis;
|
|
||||||
if (axpDevice.getBatteryVoltage(vbatMillis)) {
|
|
||||||
float vbat = vbatMillis / 1000.f;
|
|
||||||
float max_voltage = 4.20f;
|
|
||||||
float min_voltage = 2.69f; // From M5Unified
|
|
||||||
if (vbat > 2.69f) {
|
|
||||||
float charge_factor = (vbat - min_voltage) / (max_voltage - min_voltage);
|
|
||||||
data.valueAsUint8 = (uint8_t)(charge_factor * 100.f);
|
|
||||||
} else {
|
|
||||||
data.valueAsUint8 = 0;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case MetricType::IsCharging: {
|
|
||||||
Axp2101::ChargeStatus status;
|
|
||||||
if (axpDevice.getChargeStatus(status)) {
|
|
||||||
data.valueAsBool = (status == Axp2101::CHARGE_STATUS_CHARGING);
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case MetricType::Current:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false; // Safety guard for when new enum values are introduced
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CoreS3Power::isAllowedToCharge() const {
|
|
||||||
bool enabled;
|
|
||||||
if (axpDevice.isChargingEnabled(enabled)) {
|
|
||||||
return enabled;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreS3Power::setAllowedToCharge(bool canCharge) {
|
|
||||||
axpDevice.setChargingEnabled(canCharge);
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::shared_ptr<Power> power;
|
|
||||||
|
|
||||||
std::shared_ptr<Power> createPower() {
|
|
||||||
if (power == nullptr) {
|
|
||||||
power = std::make_shared<CoreS3Power>();
|
|
||||||
}
|
|
||||||
return power;
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "hal/Power.h"
|
|
||||||
#include "Axp2101/Axp2101.h"
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
using namespace tt::hal;
|
|
||||||
|
|
||||||
class CoreS3Power : public Power {
|
|
||||||
|
|
||||||
Axp2101 axpDevice = Axp2101(I2C_NUM_0);
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
CoreS3Power() = default;
|
|
||||||
~CoreS3Power() override = default;
|
|
||||||
|
|
||||||
bool supportsMetric(MetricType type) const override;
|
|
||||||
bool getMetric(Power::MetricType type, Power::MetricData& data) override;
|
|
||||||
|
|
||||||
bool supportsChargeControl() const override { return true; }
|
|
||||||
bool isAllowedToCharge() const override;
|
|
||||||
void setAllowedToCharge(bool canCharge) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::shared_ptr<Power> createPower();
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
#include "CoreS3SdCard.h"
|
|
||||||
|
|
||||||
#include "lvgl/LvglSync.h"
|
|
||||||
#include "hal/SpiSdCard.h"
|
|
||||||
|
|
||||||
#include <esp_vfs_fat.h>
|
|
||||||
|
|
||||||
#define CORES3_SDCARD_PIN_CS GPIO_NUM_4
|
|
||||||
#define CORES3_LCD_PIN_CS GPIO_NUM_3
|
|
||||||
|
|
||||||
std::shared_ptr<SdCard> createSdCard() {
|
|
||||||
auto* configuration = new tt::hal::SpiSdCard::Config(
|
|
||||||
CORES3_SDCARD_PIN_CS,
|
|
||||||
GPIO_NUM_NC,
|
|
||||||
GPIO_NUM_NC,
|
|
||||||
GPIO_NUM_NC,
|
|
||||||
SdCard::MountBehaviour::AtBoot,
|
|
||||||
tt::lvgl::getLvglSyncLockable(),
|
|
||||||
{
|
|
||||||
CORES3_LCD_PIN_CS
|
|
||||||
},
|
|
||||||
SPI3_HOST
|
|
||||||
);
|
|
||||||
|
|
||||||
auto* sdcard = (SdCard*) new SpiSdCard(
|
|
||||||
std::unique_ptr<SpiSdCard::Config>(configuration)
|
|
||||||
);
|
|
||||||
|
|
||||||
return std::shared_ptr<SdCard>(sdcard);
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "hal/SdCard.h"
|
|
||||||
|
|
||||||
using namespace tt::hal;
|
|
||||||
|
|
||||||
std::shared_ptr<SdCard> createSdCard();
|
|
||||||
@@ -1,83 +0,0 @@
|
|||||||
#include "CoreS3Touch.h"
|
|
||||||
#include "Log.h"
|
|
||||||
#include "driver/i2c.h"
|
|
||||||
#include "esp_err.h"
|
|
||||||
#include "esp_lcd_touch_ft5x06.h"
|
|
||||||
#include "esp_lcd_touch.h"
|
|
||||||
#include "esp_lvgl_port.h"
|
|
||||||
|
|
||||||
#define TAG "cores3_touch"
|
|
||||||
|
|
||||||
bool CoreS3Touch::start(lv_display_t* display) {
|
|
||||||
TT_LOG_I(TAG, "Starting");
|
|
||||||
|
|
||||||
esp_lcd_panel_io_i2c_config_t touch_io_config = ESP_LCD_TOUCH_IO_I2C_FT5x06_CONFIG();
|
|
||||||
|
|
||||||
if (esp_lcd_new_panel_io_i2c(I2C_NUM_0, &touch_io_config, &ioHandle) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, "Touch I2C IO init failed");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_lcd_touch_config_t config = {
|
|
||||||
.x_max = 320,
|
|
||||||
.y_max = 240,
|
|
||||||
.rst_gpio_num = GPIO_NUM_NC,
|
|
||||||
.int_gpio_num = GPIO_NUM_NC,
|
|
||||||
.levels = {
|
|
||||||
.reset = 0,
|
|
||||||
.interrupt = 0,
|
|
||||||
},
|
|
||||||
.flags = {
|
|
||||||
.swap_xy = 0,
|
|
||||||
.mirror_x = 0,
|
|
||||||
.mirror_y = 0,
|
|
||||||
},
|
|
||||||
.process_coordinates = nullptr,
|
|
||||||
.interrupt_callback = nullptr,
|
|
||||||
.user_data = nullptr,
|
|
||||||
.driver_data = nullptr
|
|
||||||
};
|
|
||||||
|
|
||||||
if (esp_lcd_touch_new_i2c_ft5x06(ioHandle, &config, &touchHandle) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, "Driver init failed");
|
|
||||||
cleanup();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const lvgl_port_touch_cfg_t touch_cfg = {
|
|
||||||
.disp = display,
|
|
||||||
.handle = touchHandle,
|
|
||||||
};
|
|
||||||
|
|
||||||
deviceHandle = lvgl_port_add_touch(&touch_cfg);
|
|
||||||
if (deviceHandle == nullptr) {
|
|
||||||
TT_LOG_E(TAG, "Adding touch failed");
|
|
||||||
cleanup();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
TT_LOG_I(TAG, "Finished");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CoreS3Touch::stop() {
|
|
||||||
cleanup();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreS3Touch::cleanup() {
|
|
||||||
if (deviceHandle != nullptr) {
|
|
||||||
lv_indev_delete(deviceHandle);
|
|
||||||
deviceHandle = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (touchHandle != nullptr) {
|
|
||||||
esp_lcd_touch_del(touchHandle);
|
|
||||||
touchHandle = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ioHandle != nullptr) {
|
|
||||||
esp_lcd_panel_io_del(ioHandle);
|
|
||||||
ioHandle = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user