mirror of
https://github.com/m5stack/StackChan.git
synced 2026-04-27 11:02:40 +00:00
@@ -0,0 +1,164 @@
|
||||
BasedOnStyle: Google
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveMacros: true
|
||||
AlignConsecutiveAssignments: true
|
||||
AlignConsecutiveDeclarations: false
|
||||
AlignEscapedNewlines: Left
|
||||
AlignOperands: true
|
||||
AlignTrailingComments: true
|
||||
AllowAllArgumentsOnNextLine: true
|
||||
AllowAllConstructorInitializersOnNextLine: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowShortBlocksOnASingleLine: Never
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: false
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: WithoutElse
|
||||
AllowShortLoopsOnASingleLine: true
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: true
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
AfterClass: false
|
||||
AfterControlStatement: false
|
||||
AfterEnum: false
|
||||
AfterFunction: true
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
AfterExternBlock: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: true
|
||||
SplitEmptyRecord: true
|
||||
SplitEmptyNamespace: true
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeBraces: Custom
|
||||
BreakBeforeInheritanceComma: false
|
||||
BreakInheritanceList: BeforeColon
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 120
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DeriveLineEnding: true
|
||||
DerivePointerAlignment: true
|
||||
DisableFormat: false
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
FixNamespaceComments: true
|
||||
ForEachMacros:
|
||||
- foreach
|
||||
- Q_FOREACH
|
||||
- BOOST_FOREACH
|
||||
IncludeBlocks: Regroup
|
||||
IncludeCategories:
|
||||
- Regex: '^<ext/.*\.h>'
|
||||
Priority: 2
|
||||
SortPriority: 0
|
||||
- Regex: '^<.*\.h>'
|
||||
Priority: 1
|
||||
SortPriority: 0
|
||||
- Regex: '^<.*'
|
||||
Priority: 2
|
||||
SortPriority: 0
|
||||
- Regex: '.*'
|
||||
Priority: 3
|
||||
SortPriority: 0
|
||||
IncludeIsMainRegex: '([-_](test|unittest))?$'
|
||||
IncludeIsMainSourceRegex: ''
|
||||
IndentCaseLabels: true
|
||||
IndentGotoLabels: true
|
||||
IndentPPDirectives: None
|
||||
IndentWidth: 4
|
||||
IndentWrappedFunctionNames: false
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
ObjCBinPackProtocolList: Never
|
||||
ObjCBlockIndentWidth: 2
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PenaltyBreakAssignment: 2
|
||||
PenaltyBreakBeforeFirstCallParameter: 1
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyBreakTemplateDeclaration: 10
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 200
|
||||
PointerAlignment: Left
|
||||
RawStringFormats:
|
||||
- Language: Cpp
|
||||
Delimiters:
|
||||
- cc
|
||||
- CC
|
||||
- cpp
|
||||
- Cpp
|
||||
- CPP
|
||||
- 'c++'
|
||||
- 'C++'
|
||||
CanonicalDelimiter: ''
|
||||
BasedOnStyle: google
|
||||
- Language: TextProto
|
||||
Delimiters:
|
||||
- pb
|
||||
- PB
|
||||
- proto
|
||||
- PROTO
|
||||
EnclosingFunctions:
|
||||
- EqualsProto
|
||||
- EquivToProto
|
||||
- PARSE_PARTIAL_TEXT_PROTO
|
||||
- PARSE_TEST_PROTO
|
||||
- PARSE_TEXT_PROTO
|
||||
- ParseTextOrDie
|
||||
- ParseTextProtoOrDie
|
||||
CanonicalDelimiter: ''
|
||||
BasedOnStyle: google
|
||||
ReflowComments: true
|
||||
SortIncludes: false
|
||||
SortUsingDeclarations: true
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceInEmptyBlock: false
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 2
|
||||
SpacesInAngles: false
|
||||
SpacesInConditionalStatement: false
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
SpaceBeforeSquareBrackets: false
|
||||
Standard: Auto
|
||||
StatementMacros:
|
||||
- Q_UNUSED
|
||||
- QT_REQUIRE_VERSION
|
||||
TabWidth: 4
|
||||
UseCRLF: false
|
||||
UseTab: Never
|
||||
@@ -0,0 +1,67 @@
|
||||
# Prerequisites
|
||||
*.d
|
||||
|
||||
# Compiled Object files
|
||||
*.slo
|
||||
*.lo
|
||||
*.o
|
||||
*.obj
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Compiled Dynamic libraries
|
||||
*.so
|
||||
*.dylib
|
||||
*.dll
|
||||
|
||||
# Fortran module files
|
||||
*.mod
|
||||
*.smod
|
||||
|
||||
# Compiled Static libraries
|
||||
*.lai
|
||||
*.la
|
||||
*.a
|
||||
*.lib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
|
||||
# MacOS desktop metadata files
|
||||
.DS_Store
|
||||
|
||||
# Build files
|
||||
build/
|
||||
cmake-build-*/
|
||||
/components/
|
||||
managed_components/
|
||||
|
||||
# PlatformIO
|
||||
.pio/
|
||||
|
||||
# VSCode
|
||||
.vscode/
|
||||
.cache/
|
||||
|
||||
# Python virtual environment
|
||||
.venv/
|
||||
|
||||
# Debug / Release files
|
||||
Debug/
|
||||
debug/
|
||||
Release/
|
||||
release/
|
||||
out/
|
||||
bin/
|
||||
obj/
|
||||
|
||||
*.code-workspace
|
||||
|
||||
sdkconfig
|
||||
sdkconfig.old
|
||||
|
||||
xiaozhi-esp32/
|
||||
@@ -0,0 +1,11 @@
|
||||
# The following five lines of boilerplate have to be in your project's
|
||||
# CMakeLists in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
set(PROJECT_VER "2.0.4")
|
||||
|
||||
# Add this line to disable the specific warning
|
||||
add_compile_options(-Wno-missing-field-initializers)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(StackChan)
|
||||
+25
-1
@@ -1 +1,25 @@
|
||||
# StackChan Firmware
|
||||
# StackChan Firmware
|
||||
|
||||
## Build
|
||||
|
||||
### Fetch Dependencies
|
||||
|
||||
```bash
|
||||
python3 ./fetch_repos.py
|
||||
```
|
||||
|
||||
### Tool Chains
|
||||
|
||||
[ESP-IDF v5.5.1](https://docs.espressif.com/projects/esp-idf/en/v5.5.1/esp32s3/index.html)
|
||||
|
||||
### Build
|
||||
|
||||
```bash
|
||||
idf.py build
|
||||
```
|
||||
|
||||
### Flash
|
||||
|
||||
```bash
|
||||
idf.py flash
|
||||
```
|
||||
|
||||
@@ -0,0 +1,770 @@
|
||||
dependencies:
|
||||
78/esp-ml307:
|
||||
component_hash: 57c8cc3309fb3da9195ec861cba3726b5cf24c362def803e7174c0b1d72e60e3
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=5.3'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 3.3.7
|
||||
78/esp-opus:
|
||||
component_hash: 8182b733f071d7bfe1e837f4c9f8649a63e4c937177f089e65772880c02f2e17
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=5.0'
|
||||
source:
|
||||
registry_url: https://components.espressif.com
|
||||
type: service
|
||||
version: 1.0.5
|
||||
78/esp-opus-encoder:
|
||||
component_hash: b80e5b6d6dc4bf6b0bf1a3729f52b80500e9e6b1003b3e827b78ba738283a296
|
||||
dependencies:
|
||||
- name: 78/esp-opus
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: ^1.0.5
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=5.3'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 2.4.1
|
||||
78/esp-wifi-connect:
|
||||
component_hash: 2613d9970df9f2203c2c549991e3bad74847b0a7facffe6698f4341e0bf73589
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=5.3'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 2.6.1
|
||||
78/esp_lcd_nv3023:
|
||||
component_hash: fa88abfc19a312eb5e6f2ffa187e0a9faf67e01e758bfb979d3f9d92561a494f
|
||||
dependencies:
|
||||
- name: espressif/cmake_utilities
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: 0.*
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=4.4'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.0.0
|
||||
78/xiaozhi-fonts:
|
||||
component_hash: 51f67bcf9dec623de90d9deb72de50dfbc3634fb948b7abf27df65b386258b94
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=5.3'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.5.4
|
||||
espressif/adc_battery_estimation:
|
||||
component_hash: b915167c87ed5a84b13d680bd011c2ed9a15121f1e247c6903141b9f138f3606
|
||||
dependencies:
|
||||
- name: espressif/cmake_utilities
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: '*'
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=5.0'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 0.2.1
|
||||
espressif/adc_mic:
|
||||
component_hash: ca6ef69bba4dc0d3e0ce53937635ed2734d38ac947881da81b8526e6851a71a4
|
||||
dependencies:
|
||||
- name: espressif/cmake_utilities
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: '*'
|
||||
- name: espressif/esp_codec_dev
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: ^1.3.*
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=5.0'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 0.2.1
|
||||
espressif/button:
|
||||
component_hash: 4ed25fcf354b48aa5e5680b9e7549e38d7738f9b613c94a2e39119c100db9c95
|
||||
dependencies:
|
||||
- name: espressif/cmake_utilities
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: '*'
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=4.0'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 4.1.4
|
||||
espressif/cmake_utilities:
|
||||
component_hash: 351350613ceafba240b761b4ea991e0f231ac7a9f59a9ee901f751bddc0bb18f
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=4.1'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 0.5.3
|
||||
espressif/dl_fft:
|
||||
component_hash: 7dadbd644c0d7ba4733cc3726ec4cff6edf27b043725e1115861dec1609a3d28
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=5.0'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 0.3.1
|
||||
espressif/esp-dsp:
|
||||
component_hash: 42dce32d46ac93dc11f60d368e29a830e9661c7345d794b8a45c343479cae636
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=4.2'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.7.0
|
||||
espressif/esp_cam_sensor:
|
||||
component_hash: 35c1648ea87aac81da7a085d35f61b6d5ad88574bd0c5fdc4ab75efdef4ee6c1
|
||||
dependencies:
|
||||
- name: espressif/cmake_utilities
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: 0.*
|
||||
- name: espressif/esp_sccb_intf
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: '>=0.0.5'
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=5.3'
|
||||
source:
|
||||
registry_url: https://components.espressif.com
|
||||
type: service
|
||||
targets:
|
||||
- esp32p4
|
||||
- esp32s3
|
||||
- esp32c3
|
||||
- esp32c5
|
||||
- esp32c6
|
||||
- esp32c61
|
||||
version: 1.5.2
|
||||
espressif/esp_codec_dev:
|
||||
component_hash: 0d9e9bc288156eb55f79338d312e1ebf8c9dfbd5e7d13ef0f20ccb031b4e15cf
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=4.0'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.5.4
|
||||
espressif/esp_image_effects:
|
||||
component_hash: a35037db02862d3cef6f72c25f422ae62da6e6c88219ce03c9ea24e0315ceaaa
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=5.0'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.0.1
|
||||
espressif/esp_io_expander:
|
||||
component_hash: abf3ea0d71407d79d15500550aa3ba433848459b0fa94717cf9478822593ee5d
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=4.4.2'
|
||||
source:
|
||||
registry_url: https://components.espressif.com
|
||||
type: service
|
||||
version: 1.1.0
|
||||
espressif/esp_io_expander_tca9554:
|
||||
component_hash: 8a9e3a7dbef589a54f814ff22e9121da86bce19d0e1ccffa53f5df6bb346a140
|
||||
dependencies:
|
||||
- name: espressif/esp_io_expander
|
||||
registry_url: https://components.espressif.com
|
||||
require: public
|
||||
version: ^1.0.1
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=5.2'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 2.0.0
|
||||
espressif/esp_io_expander_tca95xx_16bit:
|
||||
component_hash: c384d55e429775d6a1eef26512fbc33bc41823745a8c2ad6d5927729f33a2c21
|
||||
dependencies:
|
||||
- name: espressif/esp_io_expander
|
||||
registry_url: https://components.espressif.com
|
||||
require: public
|
||||
version: ^1.0.1
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=5.2'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 2.0.1
|
||||
espressif/esp_lcd_axs15231b:
|
||||
component_hash: e614bd75827e95800e39df1ba9474166060ab26c3807d06df9cc312a27021cda
|
||||
dependencies:
|
||||
- name: espressif/cmake_utilities
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: 0.*
|
||||
- name: espressif/esp_lcd_touch
|
||||
registry_url: https://components.espressif.com
|
||||
require: public
|
||||
version: ^1
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>5.0.4,!=5.1.1'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.0.1~1
|
||||
espressif/esp_lcd_gc9a01:
|
||||
component_hash: 09ddc8f5c9d718a659ffa30a4040e1ae75077e68492c38aec8c2beaaa7b3a9bc
|
||||
dependencies:
|
||||
- name: espressif/cmake_utilities
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: 0.*
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=4.4'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 2.0.1
|
||||
espressif/esp_lcd_ili9341:
|
||||
component_hash: 31f1b793aa2110dd2ae071c21ccbff0a4eb20d9a4ee40b6294c0dc0ad9552c4e
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=4.4'
|
||||
- name: espressif/cmake_utilities
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: 0.*
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.2.0
|
||||
espressif/esp_lcd_panel_io_additions:
|
||||
component_hash: 213d5c4a3c322a48c9f993d6bc2372206d34af95db34e87a3e02601bdcad7ce8
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=4.4.2'
|
||||
- name: espressif/cmake_utilities
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: 0.*
|
||||
- name: espressif/esp_io_expander
|
||||
registry_url: https://components.espressif.com
|
||||
require: public
|
||||
version: ^1
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.0.1
|
||||
espressif/esp_lcd_spd2010:
|
||||
component_hash: 8637c97feeb8d83ba637599f6bf4ef30e83595486930e7df17ffa24f3fef1242
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>5.0.4,!=5.1.1'
|
||||
- name: espressif/cmake_utilities
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: 0.*
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.0.2
|
||||
espressif/esp_lcd_st7701:
|
||||
component_hash: 0b11e8733e51e12da83003b9d475777eaf47bfbdce01379879bd2504d14f4f83
|
||||
dependencies:
|
||||
- name: espressif/cmake_utilities
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: 0.*
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>5.0.4,!=5.1.1'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
targets:
|
||||
- esp32s3
|
||||
- esp32p4
|
||||
version: 1.1.5
|
||||
espressif/esp_lcd_st77916:
|
||||
component_hash: 5fa0f8b1274576d4484e2b8d9358e2a5d09c721511bef0dce6a55b4206b5f0e9
|
||||
dependencies:
|
||||
- name: espressif/cmake_utilities
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: 0.*
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>5.0.4,!=5.1.1'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.0.1
|
||||
espressif/esp_lcd_st7796:
|
||||
component_hash: c37b10363125eb3b4757d509392ffca963c27262b61939fdb49a7b18eeef975c
|
||||
dependencies:
|
||||
- name: espressif/cmake_utilities
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: 0.*
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=4.4'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
targets:
|
||||
- esp32
|
||||
- esp32s2
|
||||
- esp32s3
|
||||
- esp32p4
|
||||
version: 1.3.5
|
||||
espressif/esp_lcd_touch:
|
||||
component_hash: 3f85a7d95af876f1a6ecca8eb90a81614890d0f03a038390804e5a77e2caf862
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=4.4.2'
|
||||
source:
|
||||
registry_url: https://components.espressif.com
|
||||
type: service
|
||||
version: 1.2.1
|
||||
espressif/esp_lcd_touch_cst816s:
|
||||
component_hash: 51dfa9cee38d8a20f4b625d7f89120dff08c8557e613e09dfb31f53d48648235
|
||||
dependencies:
|
||||
- name: espressif/esp_lcd_touch
|
||||
registry_url: https://components.espressif.com
|
||||
require: public
|
||||
version: ^1.0.4
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=4.4.2'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.1.0
|
||||
espressif/esp_lcd_touch_ft5x06:
|
||||
component_hash: abaec05f46a793549b60afdda9eff86e3c8e87782c8c169007911232388d2858
|
||||
dependencies:
|
||||
- name: espressif/esp_lcd_touch
|
||||
registry_url: https://components.espressif.com
|
||||
require: public
|
||||
version: ^1.0.4
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=4.4.2'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.0.7
|
||||
espressif/esp_lcd_touch_gt1151:
|
||||
component_hash: 69dd86cd5fad2442e3bf15c8c4ddddbe9e8739bdb26cd5f2c5249601b4c3cc38
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=4.4.2'
|
||||
- name: espressif/esp_lcd_touch
|
||||
registry_url: https://components.espressif.com
|
||||
require: public
|
||||
version: ^1.0.4
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.0.5~2
|
||||
espressif/esp_lcd_touch_gt911:
|
||||
component_hash: acc1c184358aa29ef72506f618c9c76a8cc2bf12af38a2bff3d44d84f3a08857
|
||||
dependencies:
|
||||
- name: espressif/esp_lcd_touch
|
||||
registry_url: https://components.espressif.com
|
||||
require: public
|
||||
version: ^1.1.0
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=4.4.2'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.1.3
|
||||
espressif/esp_lcd_touch_st7123:
|
||||
component_hash: 3592f0dac4b3baf34c40679922026c1e22e9b925b9446e981cd1c23306ecfe65
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=4.4.2'
|
||||
- name: espressif/cmake_utilities
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: 0.*
|
||||
- name: espressif/esp_lcd_touch
|
||||
registry_url: https://components.espressif.com
|
||||
require: public
|
||||
version: ^1
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.0.0
|
||||
espressif/esp_lvgl_port:
|
||||
component_hash: bfb2778c063b05a6c47c1a8de6d166ee4d911bc86fe0b3ff9e6bab06d2812033
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=5.1'
|
||||
- name: lvgl/lvgl
|
||||
registry_url: https://components.espressif.com
|
||||
require: public
|
||||
version: '>=8,<10'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 2.6.2
|
||||
espressif/esp_mmap_assets:
|
||||
component_hash: 91d785326b03db15e2f7f1314d8c976d38f21aa5759b570dcbbc89bcf247fd27
|
||||
dependencies:
|
||||
- name: espressif/cmake_utilities
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: 0.*
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=5.0'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.4.0
|
||||
espressif/esp_new_jpeg:
|
||||
component_hash: e6af208a875abd0ecfc0213d3751a11b504b463ebde6930f24096047925fa5c1
|
||||
dependencies: []
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
targets:
|
||||
- esp32
|
||||
- esp32s2
|
||||
- esp32s3
|
||||
- esp32p4
|
||||
- esp32c2
|
||||
- esp32c3
|
||||
- esp32c5
|
||||
- esp32c6
|
||||
version: 0.6.1
|
||||
espressif/esp_sccb_intf:
|
||||
component_hash: 44dfa738680ccbc3705ae6940f59be603165f4f7e4d05c3eb5f433705fdc92be
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=5.3'
|
||||
source:
|
||||
registry_url: https://components.espressif.com
|
||||
type: service
|
||||
version: 0.0.7
|
||||
espressif/esp_video:
|
||||
component_hash: fbad1178f39cb5a81ed808c460c851b911a9858db833e2e667ada988022c0660
|
||||
dependencies:
|
||||
- name: espressif/cmake_utilities
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: 0.*
|
||||
- name: espressif/esp_cam_sensor
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: 1.5.*
|
||||
- name: espressif/esp_h264
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
rules:
|
||||
- if: target in [esp32p4]
|
||||
version: 1.0.4
|
||||
- name: espressif/esp_ipa
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
rules:
|
||||
- if: target in [esp32p4]
|
||||
version: ~1.2.0
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=5.4'
|
||||
- name: espressif/usb
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
rules:
|
||||
- if: target in [esp32p4, esp32s3]
|
||||
- if: idf_version >=6.0
|
||||
version: '*'
|
||||
- name: espressif/usb_host_uvc
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
rules:
|
||||
- if: target in [esp32p4, esp32s3]
|
||||
version: 2.3.*
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
targets:
|
||||
- esp32p4
|
||||
- esp32s3
|
||||
- esp32c3
|
||||
- esp32c5
|
||||
- esp32c6
|
||||
- esp32c61
|
||||
version: 1.3.1
|
||||
espressif/freetype:
|
||||
component_hash: cd5e2d8458e6e8d73f1120ac474467cabb669d8ea4b25050bf6a348c1e89225e
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=4.4'
|
||||
source:
|
||||
registry_url: https://components.espressif.com
|
||||
type: service
|
||||
version: 2.13.3~1
|
||||
espressif/i2c_bus:
|
||||
component_hash: 4e990dc11734316186b489b362c61d41f23f79d58bc169795cec215e528cba14
|
||||
dependencies:
|
||||
- name: espressif/cmake_utilities
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: '*'
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=4.0'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.5.0
|
||||
espressif/knob:
|
||||
component_hash: 23bb6b0f62d4a2bbfe8b65e182397541339b8e48d54cef15909f5d4f5bd43d29
|
||||
dependencies:
|
||||
- name: espressif/cmake_utilities
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: 0.*
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=4.4.1'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.0.1
|
||||
espressif/led_strip:
|
||||
component_hash: 223998f10cae6d81f2ad2dd3c1103c2221be298c708e37917482b0153f3ec64e
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=5.0'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 3.0.1~1
|
||||
espressif/usb_host_uvc:
|
||||
component_hash: b0cb9a3a2eaa09dc6e5cc3e47e04d0a73e47c2d3dcfb3afce959224a1fe5fb5e
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=5.0'
|
||||
- name: espressif/usb
|
||||
registry_url: https://components.espressif.com
|
||||
require: public
|
||||
rules:
|
||||
- if: idf_version >=6.0
|
||||
- if: target not in ["linux"]
|
||||
version: ^1.0.0
|
||||
source:
|
||||
registry_url: https://components.espressif.com
|
||||
type: service
|
||||
targets:
|
||||
- esp32s2
|
||||
- esp32s3
|
||||
- esp32p4
|
||||
- esp32h4
|
||||
- linux
|
||||
version: 2.3.1
|
||||
espressif2022/esp_emote_gfx:
|
||||
component_hash: 7478561e4e8bd0efd4307647ec7221da2519de4ff1cd0cb08dccfbd0161cadaa
|
||||
dependencies:
|
||||
- name: espressif/cmake_utilities
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: 0.*
|
||||
- name: espressif/esp_new_jpeg
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: 0.6.*
|
||||
- name: espressif/freetype
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: 2.*
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=5.0'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.2.0~1
|
||||
espressif2022/image_player:
|
||||
component_hash: 0e42ed1c9665debd15f2f3e7e56519100e75e446410962226cb5e5402da3fa43
|
||||
dependencies:
|
||||
- name: espressif/cmake_utilities
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: 0.*
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=5.0'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.1.1
|
||||
idf:
|
||||
source:
|
||||
type: idf
|
||||
version: 5.5.1
|
||||
lvgl/lvgl:
|
||||
component_hash: b702d642e03e95928046d5c6726558e6444e112420c77efa5fdb6650b0a13c5d
|
||||
dependencies: []
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 9.3.0
|
||||
tny-robotics/sh1106-esp-idf:
|
||||
component_hash: 7be190d7c58cd635adf8b74b3a841f8245f2f82f36d135a64d8e53cfab39124d
|
||||
dependencies: []
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.0.0
|
||||
txp666/otto-emoji-gif-component:
|
||||
component_hash: 5a722dd0a40014b31d5998ea5b21f0b53a99d1025626d765d08710b47636ee97
|
||||
dependencies:
|
||||
- name: lvgl/lvgl
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: '>=9.0'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.0.4
|
||||
waveshare/esp_lcd_sh8601:
|
||||
component_hash: 1a2829e9db4e0515bad6ce83368f199dec60519fbba40251d6c8249f5d070ae1
|
||||
dependencies:
|
||||
- name: espressif/cmake_utilities
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: 0.*
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=5.3'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.0.2
|
||||
waveshare/esp_lcd_touch_cst9217:
|
||||
component_hash: c5da844e73ab7b7e02938901e71f38deed94b26976045fb4517e7fc1e8dc4db5
|
||||
dependencies:
|
||||
- name: espressif/esp_lcd_touch
|
||||
registry_url: https://components.espressif.com
|
||||
require: public
|
||||
version: ^1.1.0
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=4.4.2'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.0.3
|
||||
wvirgil123/sscma_client:
|
||||
component_hash: bf7d4a1f157303f4850d0b9b465c733ce38e8689ff40ac4743a44520524c41d5
|
||||
dependencies:
|
||||
- name: espressif/esp_io_expander
|
||||
registry_url: https://components.espressif.com
|
||||
require: private
|
||||
version: ^1.0.1
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=4.4.2'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.0.2
|
||||
direct_dependencies:
|
||||
- 78/esp-ml307
|
||||
- 78/esp-opus-encoder
|
||||
- 78/esp-wifi-connect
|
||||
- 78/esp_lcd_nv3023
|
||||
- 78/xiaozhi-fonts
|
||||
- espressif/adc_battery_estimation
|
||||
- espressif/adc_mic
|
||||
- espressif/button
|
||||
- espressif/cmake_utilities
|
||||
- espressif/dl_fft
|
||||
- espressif/esp-dsp
|
||||
- espressif/esp_codec_dev
|
||||
- espressif/esp_image_effects
|
||||
- espressif/esp_io_expander_tca9554
|
||||
- espressif/esp_io_expander_tca95xx_16bit
|
||||
- espressif/esp_lcd_axs15231b
|
||||
- espressif/esp_lcd_gc9a01
|
||||
- espressif/esp_lcd_ili9341
|
||||
- espressif/esp_lcd_panel_io_additions
|
||||
- espressif/esp_lcd_spd2010
|
||||
- espressif/esp_lcd_st7701
|
||||
- espressif/esp_lcd_st77916
|
||||
- espressif/esp_lcd_st7796
|
||||
- espressif/esp_lcd_touch_cst816s
|
||||
- espressif/esp_lcd_touch_ft5x06
|
||||
- espressif/esp_lcd_touch_gt1151
|
||||
- espressif/esp_lcd_touch_gt911
|
||||
- espressif/esp_lcd_touch_st7123
|
||||
- espressif/esp_lvgl_port
|
||||
- espressif/esp_mmap_assets
|
||||
- espressif/esp_new_jpeg
|
||||
- espressif/esp_video
|
||||
- espressif/i2c_bus
|
||||
- espressif/knob
|
||||
- espressif/led_strip
|
||||
- espressif2022/esp_emote_gfx
|
||||
- espressif2022/image_player
|
||||
- idf
|
||||
- lvgl/lvgl
|
||||
- tny-robotics/sh1106-esp-idf
|
||||
- txp666/otto-emoji-gif-component
|
||||
- waveshare/esp_lcd_sh8601
|
||||
- waveshare/esp_lcd_touch_cst9217
|
||||
- wvirgil123/sscma_client
|
||||
manifest_hash: 8b8d8d3a405eda302202a654ce1dfdbc17f486994ac285a18867b38f07a065c0
|
||||
target: esp32s3
|
||||
version: 2.0.0
|
||||
@@ -0,0 +1,61 @@
|
||||
import os
|
||||
import subprocess
|
||||
import json
|
||||
|
||||
|
||||
def clone_or_update_repo(
|
||||
repo_url, path, ref=None, with_submodules=False, patch_path=None
|
||||
):
|
||||
import os
|
||||
|
||||
if not os.path.exists(path):
|
||||
subprocess.run(["git", "clone", repo_url, path], check=True)
|
||||
else:
|
||||
subprocess.run(["git", "-C", path, "fetch"], check=True)
|
||||
|
||||
if ref:
|
||||
subprocess.run(["git", "-C", path, "checkout", ref], check=True)
|
||||
|
||||
if with_submodules:
|
||||
subprocess.run(
|
||||
["git", "-C", path, "submodule", "update", "--init", "--recursive"],
|
||||
check=True,
|
||||
)
|
||||
|
||||
# 应用 patch
|
||||
if patch_path:
|
||||
patch_full_path = (
|
||||
patch_path
|
||||
if os.path.isabs(patch_path)
|
||||
else os.path.join(os.getcwd(), patch_path)
|
||||
)
|
||||
# 使用 git apply --check 先检测补丁是否能应用,避免报错
|
||||
check_result = subprocess.run(
|
||||
["git", "-C", path, "apply", "--check", patch_full_path]
|
||||
)
|
||||
if check_result.returncode == 0:
|
||||
subprocess.run(["git", "-C", path, "apply", patch_full_path], check=True)
|
||||
print(f"Applied patch {patch_path} to {path}")
|
||||
else:
|
||||
print(f"Patch {patch_path} cannot be applied cleanly to {path}, skipped.")
|
||||
|
||||
|
||||
def fetch_dependencies():
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
config_path = os.path.join(script_dir, "repos.json")
|
||||
|
||||
with open(config_path) as f:
|
||||
repos = json.load(f)
|
||||
|
||||
for repo in repos:
|
||||
repo_path = os.path.join(script_dir, repo["path"])
|
||||
branch = repo.get("branch")
|
||||
with_submodules = repo.get("with_submodules", False)
|
||||
patch = repo.get("patch")
|
||||
if patch and not os.path.isabs(patch):
|
||||
patch = os.path.join(script_dir, patch)
|
||||
clone_or_update_repo(repo["url"], repo_path, branch, with_submodules, patch)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
fetch_dependencies()
|
||||
@@ -0,0 +1,458 @@
|
||||
# Define xiaozhi source directory
|
||||
set(XIAOZHI_MAIN_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../xiaozhi-esp32/main")
|
||||
|
||||
|
||||
file(GLOB_RECURSE STACK_CHAN_SOURCES
|
||||
"apps/*.c"
|
||||
"apps/*.cc"
|
||||
"apps/*.cpp"
|
||||
"assets/*.c"
|
||||
"assets/*.cc"
|
||||
"assets/*.cpp"
|
||||
"hal/*.c"
|
||||
"hal/*.cc"
|
||||
"hal/*.cpp"
|
||||
"stackchan/*.c"
|
||||
"stackchan/*.cc"
|
||||
"stackchan/*.cpp"
|
||||
)
|
||||
set(STACK_CHAN_INCLUDE_DIRS
|
||||
"."
|
||||
)
|
||||
list(APPEND STACK_CHAN_SOURCES main.cpp)
|
||||
|
||||
# Define source files
|
||||
set(SOURCES "audio/audio_codec.cc"
|
||||
"audio/audio_service.cc"
|
||||
"audio/codecs/no_audio_codec.cc"
|
||||
"audio/codecs/box_audio_codec.cc"
|
||||
"audio/codecs/es8311_audio_codec.cc"
|
||||
"audio/codecs/es8374_audio_codec.cc"
|
||||
"audio/codecs/es8388_audio_codec.cc"
|
||||
"audio/codecs/es8389_audio_codec.cc"
|
||||
"audio/codecs/dummy_audio_codec.cc"
|
||||
"audio/processors/audio_debugger.cc"
|
||||
"led/single_led.cc"
|
||||
"led/circular_strip.cc"
|
||||
"led/gpio_led.cc"
|
||||
"display/display.cc"
|
||||
"display/lcd_display.cc"
|
||||
"display/oled_display.cc"
|
||||
"display/lvgl_display/lvgl_display.cc"
|
||||
"display/emote_display.cc"
|
||||
"display/lvgl_display/emoji_collection.cc"
|
||||
"display/lvgl_display/lvgl_theme.cc"
|
||||
"display/lvgl_display/lvgl_font.cc"
|
||||
"display/lvgl_display/lvgl_image.cc"
|
||||
"display/lvgl_display/gif/lvgl_gif.cc"
|
||||
"display/lvgl_display/gif/gifdec.c"
|
||||
"display/lvgl_display/jpg/image_to_jpeg.cpp"
|
||||
"protocols/protocol.cc"
|
||||
"protocols/mqtt_protocol.cc"
|
||||
"protocols/websocket_protocol.cc"
|
||||
"mcp_server.cc"
|
||||
"system_info.cc"
|
||||
"application.cc"
|
||||
"ota.cc"
|
||||
"settings.cc"
|
||||
"device_state_event.cc"
|
||||
"assets.cc"
|
||||
)
|
||||
|
||||
# Transform relative paths to absolute paths from xiaozhi-esp32/main
|
||||
list(TRANSFORM SOURCES PREPEND "${XIAOZHI_MAIN_DIR}/")
|
||||
|
||||
set(INCLUDE_DIRS "." "display" "display/lvgl_display" "display/lvgl_display/jpg" "audio" "protocols")
|
||||
# Transform include dirs to absolute paths from xiaozhi-esp32/main
|
||||
list(TRANSFORM INCLUDE_DIRS PREPEND "${XIAOZHI_MAIN_DIR}/")
|
||||
list(APPEND INCLUDE_DIRS)
|
||||
|
||||
# Add board common files
|
||||
file(GLOB BOARD_COMMON_SOURCES ${XIAOZHI_MAIN_DIR}/boards/common/*.cc)
|
||||
list(APPEND SOURCES ${BOARD_COMMON_SOURCES} ${STACK_CHAN_SOURCES})
|
||||
list(APPEND INCLUDE_DIRS ${XIAOZHI_MAIN_DIR}/boards/common ${STACK_CHAN_INCLUDE_DIRS})
|
||||
|
||||
idf_build_get_property(build_components BUILD_COMPONENTS)
|
||||
# Function to find component dynamically by pattern
|
||||
function(find_component_by_pattern PATTERN COMPONENT_VAR PATH_VAR)
|
||||
foreach(COMPONENT ${build_components})
|
||||
if(COMPONENT MATCHES "${PATTERN}")
|
||||
set(${COMPONENT_VAR} ${COMPONENT} PARENT_SCOPE)
|
||||
idf_component_get_property(COMPONENT_PATH ${COMPONENT} COMPONENT_DIR)
|
||||
set(${PATH_VAR} "${COMPONENT_PATH}" PARENT_SCOPE)
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
# Set default BUILTIN_TEXT_FONT and BUILTIN_ICON_FONT
|
||||
set(BUILTIN_TEXT_FONT font_puhui_14_1)
|
||||
set(BUILTIN_ICON_FONT font_awesome_14_1)
|
||||
|
||||
# Add board files according to BOARD_TYPE
|
||||
# Set default assets if the board uses partition table V2
|
||||
if(CONFIG_BOARD_TYPE_M5STACK_STACK_CHAN)
|
||||
set(BOARD_TYPE "m5stack-stack-chan")
|
||||
set(BUILTIN_TEXT_FONT font_puhui_basic_20_4)
|
||||
set(BUILTIN_ICON_FONT font_awesome_20_4)
|
||||
set(DEFAULT_EMOJI_COLLECTION twemoji_64)
|
||||
endif()
|
||||
|
||||
file(GLOB BOARD_SOURCES
|
||||
)
|
||||
list(APPEND SOURCES ${BOARD_SOURCES})
|
||||
|
||||
# Select audio processor according to Kconfig
|
||||
if(CONFIG_USE_AUDIO_PROCESSOR)
|
||||
set(AUDIO_PROCESSOR_SRC "audio/processors/afe_audio_processor.cc")
|
||||
else()
|
||||
set(AUDIO_PROCESSOR_SRC "audio/processors/no_audio_processor.cc")
|
||||
endif()
|
||||
list(APPEND SOURCES "${XIAOZHI_MAIN_DIR}/${AUDIO_PROCESSOR_SRC}")
|
||||
|
||||
if(CONFIG_IDF_TARGET_ESP32S3 OR CONFIG_IDF_TARGET_ESP32P4)
|
||||
set(WAKE_WORD_SRCS "audio/wake_words/afe_wake_word.cc" "audio/wake_words/custom_wake_word.cc")
|
||||
else()
|
||||
set(WAKE_WORD_SRCS "audio/wake_words/esp_wake_word.cc")
|
||||
endif()
|
||||
list(TRANSFORM WAKE_WORD_SRCS PREPEND "${XIAOZHI_MAIN_DIR}/")
|
||||
list(APPEND SOURCES ${WAKE_WORD_SRCS})
|
||||
|
||||
# Select language directory according to Kconfig
|
||||
if(CONFIG_LANGUAGE_ZH_CN)
|
||||
set(LANG_DIR "zh-CN")
|
||||
elseif(CONFIG_LANGUAGE_ZH_TW)
|
||||
set(LANG_DIR "zh-TW")
|
||||
elseif(CONFIG_LANGUAGE_EN_US)
|
||||
set(LANG_DIR "en-US")
|
||||
elseif(CONFIG_LANGUAGE_JA_JP)
|
||||
set(LANG_DIR "ja-JP")
|
||||
elseif(CONFIG_LANGUAGE_KO_KR)
|
||||
set(LANG_DIR "ko-KR")
|
||||
elseif(CONFIG_LANGUAGE_VI_VN)
|
||||
set(LANG_DIR "vi-VN")
|
||||
elseif(CONFIG_LANGUAGE_TH_TH)
|
||||
set(LANG_DIR "th-TH")
|
||||
elseif(CONFIG_LANGUAGE_DE_DE)
|
||||
set(LANG_DIR "de-DE")
|
||||
elseif(CONFIG_LANGUAGE_FR_FR)
|
||||
set(LANG_DIR "fr-FR")
|
||||
elseif(CONFIG_LANGUAGE_ES_ES)
|
||||
set(LANG_DIR "es-ES")
|
||||
elseif(CONFIG_LANGUAGE_IT_IT)
|
||||
set(LANG_DIR "it-IT")
|
||||
elseif(CONFIG_LANGUAGE_RU_RU)
|
||||
set(LANG_DIR "ru-RU")
|
||||
elseif(CONFIG_LANGUAGE_AR_SA)
|
||||
set(LANG_DIR "ar-SA")
|
||||
elseif(CONFIG_LANGUAGE_HI_IN)
|
||||
set(LANG_DIR "hi-IN")
|
||||
elseif(CONFIG_LANGUAGE_PT_PT)
|
||||
set(LANG_DIR "pt-PT")
|
||||
elseif(CONFIG_LANGUAGE_PL_PL)
|
||||
set(LANG_DIR "pl-PL")
|
||||
elseif(CONFIG_LANGUAGE_CS_CZ)
|
||||
set(LANG_DIR "cs-CZ")
|
||||
elseif(CONFIG_LANGUAGE_FI_FI)
|
||||
set(LANG_DIR "fi-FI")
|
||||
elseif(CONFIG_LANGUAGE_TR_TR)
|
||||
set(LANG_DIR "tr-TR")
|
||||
elseif(CONFIG_LANGUAGE_ID_ID)
|
||||
set(LANG_DIR "id-ID")
|
||||
elseif(CONFIG_LANGUAGE_UK_UA)
|
||||
set(LANG_DIR "uk-UA")
|
||||
elseif(CONFIG_LANGUAGE_RO_RO)
|
||||
set(LANG_DIR "ro-RO")
|
||||
elseif(CONFIG_LANGUAGE_BG_BG)
|
||||
set(LANG_DIR "bg-BG")
|
||||
elseif(CONFIG_LANGUAGE_CA_ES)
|
||||
set(LANG_DIR "ca-ES")
|
||||
elseif(CONFIG_LANGUAGE_DA_DK)
|
||||
set(LANG_DIR "da-DK")
|
||||
elseif(CONFIG_LANGUAGE_EL_GR)
|
||||
set(LANG_DIR "el-GR")
|
||||
elseif(CONFIG_LANGUAGE_FA_IR)
|
||||
set(LANG_DIR "fa-IR")
|
||||
elseif(CONFIG_LANGUAGE_FIL_PH)
|
||||
set(LANG_DIR "fil-PH")
|
||||
elseif(CONFIG_LANGUAGE_HE_IL)
|
||||
set(LANG_DIR "he-IL")
|
||||
elseif(CONFIG_LANGUAGE_HR_HR)
|
||||
set(LANG_DIR "hr-HR")
|
||||
elseif(CONFIG_LANGUAGE_HU_HU)
|
||||
set(LANG_DIR "hu-HU")
|
||||
elseif(CONFIG_LANGUAGE_MS_MY)
|
||||
set(LANG_DIR "ms-MY")
|
||||
elseif(CONFIG_LANGUAGE_NB_NO)
|
||||
set(LANG_DIR "nb-NO")
|
||||
elseif(CONFIG_LANGUAGE_NL_NL)
|
||||
set(LANG_DIR "nl-NL")
|
||||
elseif(CONFIG_LANGUAGE_SK_SK)
|
||||
set(LANG_DIR "sk-SK")
|
||||
elseif(CONFIG_LANGUAGE_SL_SI)
|
||||
set(LANG_DIR "sl-SI")
|
||||
elseif(CONFIG_LANGUAGE_SV_SE)
|
||||
set(LANG_DIR "sv-SE")
|
||||
elseif(CONFIG_LANGUAGE_SR_RS)
|
||||
set(LANG_DIR "sr-RS")
|
||||
endif()
|
||||
|
||||
# Define generation path
|
||||
set(LANG_JSON "${XIAOZHI_MAIN_DIR}/assets/locales/${LANG_DIR}/language.json")
|
||||
set(LANG_HEADER "${XIAOZHI_MAIN_DIR}/assets/lang_config.h")
|
||||
|
||||
# Collect current language audio files
|
||||
file(GLOB LANG_SOUNDS ${XIAOZHI_MAIN_DIR}/assets/locales/${LANG_DIR}/*.ogg)
|
||||
|
||||
# If not en-US, collect en-US audio files as fallback for missing files
|
||||
if(NOT LANG_DIR STREQUAL "en-US")
|
||||
file(GLOB EN_US_SOUNDS ${XIAOZHI_MAIN_DIR}/assets/locales/en-US/*.ogg)
|
||||
|
||||
# Extract filenames (without path) from current language
|
||||
set(EXISTING_NAMES "")
|
||||
foreach(SOUND_FILE ${LANG_SOUNDS})
|
||||
get_filename_component(FILENAME ${SOUND_FILE} NAME)
|
||||
list(APPEND EXISTING_NAMES ${FILENAME})
|
||||
endforeach()
|
||||
|
||||
# Only add en-US audio files that are missing in current language
|
||||
foreach(EN_SOUND ${EN_US_SOUNDS})
|
||||
get_filename_component(FILENAME ${EN_SOUND} NAME)
|
||||
if(NOT ${FILENAME} IN_LIST EXISTING_NAMES)
|
||||
list(APPEND LANG_SOUNDS ${EN_SOUND})
|
||||
message(STATUS "Using en-US fallback for missing audio: ${FILENAME}")
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
# file(GLOB COMMON_SOUNDS ${XIAOZHI_MAIN_DIR}/assets/common/*.ogg)
|
||||
file(GLOB COMMON_SOUNDS
|
||||
${XIAOZHI_MAIN_DIR}/assets/common/*.ogg
|
||||
assets/sfx/*.ogg
|
||||
)
|
||||
|
||||
# If target chip is ESP32, exclude specific files to avoid build errors
|
||||
if(CONFIG_IDF_TARGET_ESP32)
|
||||
set(ESP32_EXCLUDE_FILES
|
||||
"audio/codecs/box_audio_codec.cc"
|
||||
"audio/codecs/es8388_audio_codec.cc"
|
||||
"audio/codecs/es8389_audio_codec.cc"
|
||||
"led/gpio_led.cc"
|
||||
"boards/common/esp32_camera.cc"
|
||||
"display/lvgl_display/jpg/image_to_jpeg.cpp"
|
||||
)
|
||||
list(TRANSFORM ESP32_EXCLUDE_FILES PREPEND "${XIAOZHI_MAIN_DIR}/")
|
||||
list(REMOVE_ITEM SOURCES ${ESP32_EXCLUDE_FILES})
|
||||
endif()
|
||||
|
||||
idf_component_register(SRCS ${SOURCES}
|
||||
EMBED_FILES ${LANG_SOUNDS} ${COMMON_SOUNDS}
|
||||
INCLUDE_DIRS ${INCLUDE_DIRS}
|
||||
WHOLE_ARCHIVE
|
||||
)
|
||||
|
||||
# Use target_compile_definitions to define BOARD_TYPE, BOARD_NAME
|
||||
# If BOARD_NAME is empty, use BOARD_TYPE
|
||||
if(NOT BOARD_NAME)
|
||||
set(BOARD_NAME ${BOARD_TYPE})
|
||||
endif()
|
||||
target_compile_definitions(${COMPONENT_LIB}
|
||||
PRIVATE BOARD_TYPE=\"${BOARD_TYPE}\" BOARD_NAME=\"${BOARD_NAME}\"
|
||||
PRIVATE BUILTIN_TEXT_FONT=${BUILTIN_TEXT_FONT} BUILTIN_ICON_FONT=${BUILTIN_ICON_FONT}
|
||||
)
|
||||
|
||||
# Add generation rules
|
||||
add_custom_command(
|
||||
OUTPUT ${LANG_HEADER}
|
||||
COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/../xiaozhi-esp32/scripts/gen_lang.py
|
||||
--language "${LANG_DIR}"
|
||||
--output "${LANG_HEADER}"
|
||||
DEPENDS
|
||||
${LANG_JSON}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../xiaozhi-esp32/scripts/gen_lang.py
|
||||
COMMENT "Generating ${LANG_DIR} language config"
|
||||
)
|
||||
|
||||
# Force build generation dependencies
|
||||
add_custom_target(lang_header ALL
|
||||
DEPENDS ${LANG_HEADER}
|
||||
)
|
||||
|
||||
# Find ESP-SR component dynamically
|
||||
find_component_by_pattern("espressif__esp-sr" ESP_SR_COMPONENT ESP_SR_COMPONENT_PATH)
|
||||
if(ESP_SR_COMPONENT_PATH)
|
||||
set(ESP_SR_MODEL_PATH "${ESP_SR_COMPONENT_PATH}/model")
|
||||
endif()
|
||||
|
||||
# Find xiaozhi-fonts component dynamically
|
||||
find_component_by_pattern("xiaozhi-fonts" XIAOZHI_FONTS_COMPONENT XIAOZHI_FONTS_COMPONENT_PATH)
|
||||
if(XIAOZHI_FONTS_COMPONENT_PATH)
|
||||
set(XIAOZHI_FONTS_PATH "${XIAOZHI_FONTS_COMPONENT_PATH}")
|
||||
endif()
|
||||
|
||||
if(CONFIG_BOARD_TYPE_ESP_HI)
|
||||
set(URL "https://github.com/espressif2022/image_player/raw/main/test_apps/test_8bit")
|
||||
set(EMOJI_DIR "${CMAKE_BINARY_DIR}/emoji")
|
||||
file(MAKE_DIRECTORY ${EMOJI_DIR})
|
||||
|
||||
# List all files to download
|
||||
set(FILES_TO_DOWNLOAD "")
|
||||
list(APPEND FILES_TO_DOWNLOAD "Anger_enter.aaf" "Anger_loop.aaf" "Anger_return.aaf")
|
||||
list(APPEND FILES_TO_DOWNLOAD "happy_enter.aaf" "happy_loop.aaf" "happ_return.aaf")
|
||||
list(APPEND FILES_TO_DOWNLOAD "sad_enter.aaf" "sad_loop.aaf" "sad_return.aaf")
|
||||
list(APPEND FILES_TO_DOWNLOAD "scorn_enter.aaf" "scorn_loop.aaf" "scorn_return.aaf")
|
||||
list(APPEND FILES_TO_DOWNLOAD "left_enter.aaf" "left_loop.aaf" "left_return.aaf")
|
||||
list(APPEND FILES_TO_DOWNLOAD "right_enter.aaf" "right_loop.aaf" "right_return.aaf")
|
||||
list(APPEND FILES_TO_DOWNLOAD "asking.aaf" "blink_once.aaf" "blink_quick.aaf")
|
||||
list(APPEND FILES_TO_DOWNLOAD "connecting.aaf" "panic_enter.aaf" "panic_loop.aaf")
|
||||
list(APPEND FILES_TO_DOWNLOAD "panic_return.aaf" "wake.aaf")
|
||||
|
||||
foreach(FILENAME IN LISTS FILES_TO_DOWNLOAD)
|
||||
set(REMOTE_FILE "${URL}/${FILENAME}")
|
||||
set(LOCAL_FILE "${EMOJI_DIR}/${FILENAME}")
|
||||
|
||||
# Check if local file exists
|
||||
if(EXISTS ${LOCAL_FILE})
|
||||
message(STATUS "File ${FILENAME} already exists, skipping download")
|
||||
else()
|
||||
message(STATUS "Downloading ${FILENAME}")
|
||||
file(DOWNLOAD ${REMOTE_FILE} ${LOCAL_FILE}
|
||||
STATUS DOWNLOAD_STATUS)
|
||||
list(GET DOWNLOAD_STATUS 0 STATUS_CODE)
|
||||
if(NOT STATUS_CODE EQUAL 0)
|
||||
message(FATAL_ERROR "Failed to download ${FILENAME} from ${URL}")
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
endif()
|
||||
|
||||
|
||||
# Function to build default assets based on configuration
|
||||
function(build_default_assets_bin)
|
||||
# Set output path for generated assets.bin
|
||||
set(GENERATED_ASSETS_BIN "${CMAKE_BINARY_DIR}/generated_assets.bin")
|
||||
|
||||
# Prepare arguments for build script
|
||||
set(BUILD_ARGS
|
||||
"--sdkconfig" "${SDKCONFIG}"
|
||||
"--output" "${GENERATED_ASSETS_BIN}"
|
||||
)
|
||||
|
||||
# Add builtin text font if defined
|
||||
if(BUILTIN_TEXT_FONT)
|
||||
list(APPEND BUILD_ARGS "--builtin_text_font" "${BUILTIN_TEXT_FONT}")
|
||||
endif()
|
||||
|
||||
# Add default emoji collection if defined
|
||||
if(DEFAULT_EMOJI_COLLECTION)
|
||||
list(APPEND BUILD_ARGS "--emoji_collection" "${DEFAULT_EMOJI_COLLECTION}")
|
||||
endif()
|
||||
|
||||
# Add default assets extra files if defined
|
||||
if(DEFAULT_ASSETS_EXTRA_FILES)
|
||||
list(APPEND BUILD_ARGS "--extra_files" "${DEFAULT_ASSETS_EXTRA_FILES}")
|
||||
endif()
|
||||
|
||||
list(APPEND BUILD_ARGS "--esp_sr_model_path" "${ESP_SR_MODEL_PATH}")
|
||||
list(APPEND BUILD_ARGS "--xiaozhi_fonts_path" "${XIAOZHI_FONTS_PATH}")
|
||||
|
||||
# Create custom command to build assets
|
||||
add_custom_command(
|
||||
OUTPUT ${GENERATED_ASSETS_BIN}
|
||||
COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/../xiaozhi-esp32/scripts/build_default_assets.py ${BUILD_ARGS}
|
||||
DEPENDS
|
||||
${SDKCONFIG}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../xiaozhi-esp32/scripts/build_default_assets.py
|
||||
COMMENT "Building default assets.bin based on configuration"
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
# Create target for generated assets
|
||||
add_custom_target(generated_default_assets ALL
|
||||
DEPENDS ${GENERATED_ASSETS_BIN}
|
||||
)
|
||||
|
||||
# Set the generated file path in parent scope
|
||||
set(GENERATED_ASSETS_LOCAL_FILE ${GENERATED_ASSETS_BIN} PARENT_SCOPE)
|
||||
|
||||
message(STATUS "Default assets build configured: ${GENERATED_ASSETS_BIN}")
|
||||
endfunction()
|
||||
|
||||
|
||||
# Function to get local assets file path (handles both URL and local file)
|
||||
function(get_assets_local_file assets_source assets_local_file_var)
|
||||
# Check if it's a URL (starts with http:// or https://)
|
||||
if(assets_source MATCHES "^https?://")
|
||||
# It's a URL, download it
|
||||
get_filename_component(ASSETS_FILENAME "${assets_source}" NAME)
|
||||
set(ASSETS_LOCAL_FILE "${CMAKE_BINARY_DIR}/${ASSETS_FILENAME}")
|
||||
set(ASSETS_TEMP_FILE "${CMAKE_BINARY_DIR}/${ASSETS_FILENAME}.tmp")
|
||||
|
||||
# Check if local file exists
|
||||
if(EXISTS ${ASSETS_LOCAL_FILE})
|
||||
message(STATUS "Assets file ${ASSETS_FILENAME} already exists, skipping download")
|
||||
else()
|
||||
message(STATUS "Downloading ${ASSETS_FILENAME}")
|
||||
|
||||
# Clean up any existing temp file
|
||||
if(EXISTS ${ASSETS_TEMP_FILE})
|
||||
file(REMOVE ${ASSETS_TEMP_FILE})
|
||||
endif()
|
||||
|
||||
# Download to temporary file first
|
||||
file(DOWNLOAD ${assets_source} ${ASSETS_TEMP_FILE}
|
||||
STATUS DOWNLOAD_STATUS)
|
||||
list(GET DOWNLOAD_STATUS 0 STATUS_CODE)
|
||||
if(NOT STATUS_CODE EQUAL 0)
|
||||
# Clean up temp file on failure
|
||||
if(EXISTS ${ASSETS_TEMP_FILE})
|
||||
file(REMOVE ${ASSETS_TEMP_FILE})
|
||||
endif()
|
||||
message(FATAL_ERROR "Failed to download ${ASSETS_FILENAME} from ${assets_source}")
|
||||
endif()
|
||||
|
||||
# Move temp file to final location (atomic operation)
|
||||
file(RENAME ${ASSETS_TEMP_FILE} ${ASSETS_LOCAL_FILE})
|
||||
message(STATUS "Successfully downloaded ${ASSETS_FILENAME}")
|
||||
endif()
|
||||
else()
|
||||
# It's a local file path
|
||||
if(IS_ABSOLUTE "${assets_source}")
|
||||
set(ASSETS_LOCAL_FILE "${assets_source}")
|
||||
else()
|
||||
set(ASSETS_LOCAL_FILE "${CMAKE_CURRENT_SOURCE_DIR}/${assets_source}")
|
||||
endif()
|
||||
|
||||
# Check if local file exists
|
||||
if(NOT EXISTS ${ASSETS_LOCAL_FILE})
|
||||
message(FATAL_ERROR "Assets file not found: ${ASSETS_LOCAL_FILE}")
|
||||
endif()
|
||||
|
||||
message(STATUS "Using assets file: ${ASSETS_LOCAL_FILE}")
|
||||
endif()
|
||||
|
||||
set(${assets_local_file_var} ${ASSETS_LOCAL_FILE} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
|
||||
partition_table_get_partition_info(size "--partition-name assets" "size")
|
||||
partition_table_get_partition_info(offset "--partition-name assets" "offset")
|
||||
if ("${size}" AND "${offset}")
|
||||
# Flash assets based on configuration
|
||||
if(CONFIG_FLASH_DEFAULT_ASSETS)
|
||||
# Build default assets based on configuration
|
||||
build_default_assets_bin()
|
||||
esptool_py_flash_to_partition(flash "assets" "${GENERATED_ASSETS_LOCAL_FILE}")
|
||||
message(STATUS "Generated default assets flash configured: ${GENERATED_ASSETS_LOCAL_FILE} -> assets partition")
|
||||
elseif(CONFIG_FLASH_CUSTOM_ASSETS)
|
||||
# Flash custom assets
|
||||
get_assets_local_file("${CONFIG_CUSTOM_ASSETS_FILE}" ASSETS_LOCAL_FILE)
|
||||
esptool_py_flash_to_partition(flash "assets" "${ASSETS_LOCAL_FILE}")
|
||||
message(STATUS "Custom assets flash configured: ${ASSETS_LOCAL_FILE} -> assets partition")
|
||||
elseif(CONFIG_FLASH_NONE_ASSETS)
|
||||
message(STATUS "Assets flashing disabled (FLASH_NONE_ASSETS)")
|
||||
endif()
|
||||
else()
|
||||
message(STATUS "Assets partition not found, using v1 partition table")
|
||||
endif()
|
||||
@@ -0,0 +1,839 @@
|
||||
menu "Xiaozhi Assistant"
|
||||
|
||||
config OTA_URL
|
||||
string "Default OTA URL"
|
||||
default "https://api.tenclass.net/xiaozhi/ota/"
|
||||
help
|
||||
The application will access this URL to check for new firmwares and server address.
|
||||
|
||||
choice
|
||||
prompt "Flash Assets"
|
||||
default FLASH_DEFAULT_ASSETS
|
||||
help
|
||||
Select the assets to flash.
|
||||
|
||||
config FLASH_NONE_ASSETS
|
||||
bool "Do not flash assets"
|
||||
config FLASH_DEFAULT_ASSETS
|
||||
bool "Flash Default Assets"
|
||||
config FLASH_CUSTOM_ASSETS
|
||||
bool "Flash Custom Assets"
|
||||
endchoice
|
||||
|
||||
config CUSTOM_ASSETS_FILE
|
||||
depends on FLASH_CUSTOM_ASSETS
|
||||
string "Custom Assets File"
|
||||
default "assets.bin"
|
||||
help
|
||||
The custom assets file to flash.
|
||||
It can be a local file relative to the project directory or a remote url.
|
||||
|
||||
choice
|
||||
prompt "Default Language"
|
||||
default LANGUAGE_ZH_CN
|
||||
help
|
||||
Select device display language
|
||||
|
||||
config LANGUAGE_ZH_CN
|
||||
bool "Chinese"
|
||||
config LANGUAGE_ZH_TW
|
||||
bool "Chinese Traditional"
|
||||
config LANGUAGE_EN_US
|
||||
bool "English"
|
||||
config LANGUAGE_JA_JP
|
||||
bool "Japanese"
|
||||
config LANGUAGE_KO_KR
|
||||
bool "Korean"
|
||||
config LANGUAGE_VI_VN
|
||||
bool "Vietnamese"
|
||||
config LANGUAGE_TH_TH
|
||||
bool "Thai"
|
||||
config LANGUAGE_DE_DE
|
||||
bool "German"
|
||||
config LANGUAGE_FR_FR
|
||||
bool "French"
|
||||
config LANGUAGE_ES_ES
|
||||
bool "Spanish"
|
||||
config LANGUAGE_IT_IT
|
||||
bool "Italian"
|
||||
config LANGUAGE_RU_RU
|
||||
bool "Russian"
|
||||
config LANGUAGE_AR_SA
|
||||
bool "Arabic"
|
||||
config LANGUAGE_HI_IN
|
||||
bool "Hindi"
|
||||
config LANGUAGE_PT_PT
|
||||
bool "Portuguese"
|
||||
config LANGUAGE_PL_PL
|
||||
bool "Polish"
|
||||
config LANGUAGE_CS_CZ
|
||||
bool "Czech"
|
||||
config LANGUAGE_FI_FI
|
||||
bool "Finnish"
|
||||
config LANGUAGE_TR_TR
|
||||
bool "Turkish"
|
||||
config LANGUAGE_ID_ID
|
||||
bool "Indonesian"
|
||||
config LANGUAGE_UK_UA
|
||||
bool "Ukrainian"
|
||||
config LANGUAGE_RO_RO
|
||||
bool "Romanian"
|
||||
config LANGUAGE_BG_BG
|
||||
bool "Bulgarian"
|
||||
config LANGUAGE_CA_ES
|
||||
bool "Catalan"
|
||||
config LANGUAGE_DA_DK
|
||||
bool "Danish"
|
||||
config LANGUAGE_EL_GR
|
||||
bool "Greek"
|
||||
config LANGUAGE_FA_IR
|
||||
bool "Persian"
|
||||
config LANGUAGE_FIL_PH
|
||||
bool "Filipino"
|
||||
config LANGUAGE_HE_IL
|
||||
bool "Hebrew"
|
||||
config LANGUAGE_HR_HR
|
||||
bool "Croatian"
|
||||
config LANGUAGE_HU_HU
|
||||
bool "Hungarian"
|
||||
config LANGUAGE_MS_MY
|
||||
bool "Malay"
|
||||
config LANGUAGE_NB_NO
|
||||
bool "Norwegian"
|
||||
config LANGUAGE_NL_NL
|
||||
bool "Dutch"
|
||||
config LANGUAGE_SK_SK
|
||||
bool "Slovak"
|
||||
config LANGUAGE_SL_SI
|
||||
bool "Slovenian"
|
||||
config LANGUAGE_SV_SE
|
||||
bool "Swedish"
|
||||
config LANGUAGE_SR_RS
|
||||
bool "Serbian"
|
||||
endchoice
|
||||
|
||||
choice BOARD_TYPE
|
||||
prompt "Board Type"
|
||||
default BOARD_TYPE_BREAD_COMPACT_WIFI
|
||||
help
|
||||
Board type. 开发板类型
|
||||
config BOARD_TYPE_BREAD_COMPACT_WIFI
|
||||
bool "Bread Compact WiFi (面包板)"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_BREAD_COMPACT_WIFI_LCD
|
||||
bool "Bread Compact WiFi + LCD (面包板)"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_BREAD_COMPACT_WIFI_CAM
|
||||
bool "Bread Compact WiFi + LCD + Camera (面包板)"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_BREAD_COMPACT_ML307
|
||||
bool "Bread Compact ML307/EC801E (面包板 4G)"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_BREAD_COMPACT_ESP32
|
||||
bool "Bread Compact ESP32 DevKit (面包板)"
|
||||
depends on IDF_TARGET_ESP32
|
||||
config BOARD_TYPE_BREAD_COMPACT_ESP32_LCD
|
||||
bool "Bread Compact ESP32 DevKit + LCD (面包板)"
|
||||
depends on IDF_TARGET_ESP32
|
||||
config BOARD_TYPE_XMINI_C3_V3
|
||||
bool "Xmini C3 V3"
|
||||
depends on IDF_TARGET_ESP32C3
|
||||
config BOARD_TYPE_XMINI_C3_4G
|
||||
bool "Xmini C3 4G"
|
||||
depends on IDF_TARGET_ESP32C3
|
||||
config BOARD_TYPE_XMINI_C3
|
||||
bool "Xmini C3"
|
||||
depends on IDF_TARGET_ESP32C3
|
||||
config BOARD_TYPE_ESP_KORVO2_V3
|
||||
bool "Espressif Korvo2 V3"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ESP_SPARKBOT
|
||||
bool "Espressif SparkBot"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ESP_SPOT_S3
|
||||
bool "Espressif Spot-S3"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ESP_HI
|
||||
bool "Espressif ESP-HI"
|
||||
depends on IDF_TARGET_ESP32C3
|
||||
config BOARD_TYPE_ESP_BOX_3
|
||||
bool "Espressif ESP-BOX-3"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ESP_BOX
|
||||
bool "Espressif ESP-BOX"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ESP_BOX_LITE
|
||||
bool "Espressif ESP-BOX-Lite"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ESP_P4_FUNCTION_EV_BOARD
|
||||
bool "Espressif ESP-P4-Function-EV-Board"
|
||||
depends on IDF_TARGET_ESP32P4
|
||||
config BOARD_TYPE_ECHOEAR
|
||||
bool "EchoEar"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_KEVIN_BOX_2
|
||||
bool "Kevin Box 2"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_KEVIN_C3
|
||||
bool "Kevin C3"
|
||||
depends on IDF_TARGET_ESP32C3
|
||||
config BOARD_TYPE_KEVIN_SP_V3_DEV
|
||||
bool "Kevin SP V3"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_KEVIN_SP_V4_DEV
|
||||
bool "Kevin SP V4"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_KEVIN_YUYING_313LCD
|
||||
bool "鱼鹰科技 3.13LCD"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_CGC
|
||||
bool "CGC"
|
||||
depends on IDF_TARGET_ESP32
|
||||
config BOARD_TYPE_CGC_144
|
||||
bool "CGC 144"
|
||||
depends on IDF_TARGET_ESP32
|
||||
config BOARD_TYPE_LICHUANG_DEV_S3
|
||||
bool "立创·实战派 ESP32-S3"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_LICHUANG_DEV_C3
|
||||
bool "立创·实战派 ESP32-C3"
|
||||
depends on IDF_TARGET_ESP32C3
|
||||
config BOARD_TYPE_DF_K10
|
||||
bool "DFRobot 行空板 k10"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_DF_S3_AI_CAM
|
||||
bool "DFRobot ESP32-S3 AI智能摄像头模块"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_MAGICLICK_S3_2P4
|
||||
bool "神奇按钮 Magiclick_2.4"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_MAGICLICK_S3_2P5
|
||||
bool "神奇按钮 Magiclick_2.5"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_MAGICLICK_C3
|
||||
bool "神奇按钮 Magiclick_C3"
|
||||
depends on IDF_TARGET_ESP32C3
|
||||
config BOARD_TYPE_MAGICLICK_C3_V2
|
||||
bool "神奇按钮 Magiclick_C3_v2"
|
||||
depends on IDF_TARGET_ESP32C3
|
||||
config BOARD_TYPE_M5STACK_CORE_S3
|
||||
bool "M5Stack CoreS3"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_M5STACK_STACK_CHAN
|
||||
bool "M5Stack StackChan"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_M5STACK_CORE_TAB5
|
||||
bool "M5Stack Tab5"
|
||||
depends on IDF_TARGET_ESP32P4
|
||||
config BOARD_TYPE_M5STACK_ATOM_S3_ECHO_BASE
|
||||
bool "M5Stack AtomS3 + Echo Base"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_M5STACK_ATOM_S3R_ECHO_BASE
|
||||
bool "M5Stack AtomS3R + Echo Base"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_M5STACK_ATOM_S3R_CAM_M12_ECHO_BASE
|
||||
bool "M5Stack AtomS3R CAM/M12 + Echo Base"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_M5STACK_ATOM_ECHOS3R
|
||||
bool "M5Stack AtomEchoS3R"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_M5STACK_ATOM_MATRIX_ECHO_BASE
|
||||
bool "M5Stack AtomMatrix + Echo Base"
|
||||
depends on IDF_TARGET_ESP32
|
||||
config BOARD_TYPE_WAVESHARE_S3_AUDIO_BOARD
|
||||
bool "Waveshare ESP32-S3-Audio-Board"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_WAVESHARE_S3_TOUCH_AMOLED_1_8
|
||||
bool "Waveshare ESP32-S3-Touch-AMOLED-1.8"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_WAVESHARE_S3_TOUCH_AMOLED_2_06
|
||||
bool "Waveshare ESP32-S3-Touch-AMOLED-2.06"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_WAVESHARE_S3_TOUCH_AMOLED_1_75
|
||||
bool "Waveshare ESP32-S3-Touch-AMOLED-1.75"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_WAVESHARE_S3_TOUCH_LCD_1_83
|
||||
bool "Waveshare ESP32-S3-Touch-LCD-1.83"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_WAVESHARE_S3_TOUCH_LCD_4B
|
||||
bool "Waveshare ESP32-S3-Touch-LCD-4B"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_WAVESHARE_S3_TOUCH_LCD_1_85C
|
||||
bool "Waveshare ESP32-S3-Touch-LCD-1.85C"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_WAVESHARE_S3_TOUCH_LCD_1_85
|
||||
bool "Waveshare ESP32-S3-Touch-LCD-1.85"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_WAVESHARE_S3_TOUCH_LCD_1_46
|
||||
bool "Waveshare ESP32-S3-Touch-LCD-1.46"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_WAVESHARE_C6_LCD_1_69
|
||||
bool "Waveshare ESP32-C6-LCD-1.69"
|
||||
depends on IDF_TARGET_ESP32C6
|
||||
config BOARD_TYPE_WAVESHARE_C6_TOUCH_AMOLED_1_43
|
||||
bool "Waveshare ESP32-C6-Touch-AMOLOED-1.43"
|
||||
depends on IDF_TARGET_ESP32C6
|
||||
config BOARD_TYPE_WAVESHARE_C6_TOUCH_AMOLED_1_32
|
||||
bool "Waveshare ESP32-C6-Touch-AMOLOED-1.32"
|
||||
depends on IDF_TARGET_ESP32C6
|
||||
config BOARD_TYPE_WAVESHARE_S3_TOUCH_AMOLED_1_32
|
||||
bool "Waveshare ESP32-S3-Touch-AMOLOED-1.32"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_WAVESHARE_S3_TOUCH_LCD_3_49
|
||||
bool "Waveshare ESP32-S3-Touch-LCD-3.49"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_WAVESHARE_S3_TOUCH_LCD_3_5
|
||||
bool "Waveshare ESP32-S3-Touch-LCD-3.5"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_WAVESHARE_S3_TOUCH_LCD_3_5B
|
||||
bool "Waveshare ESP32-S3-Touch-LCD-3.5B"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_WAVESHARE_P4_NANO
|
||||
bool "Waveshare ESP32-P4-NANO"
|
||||
depends on IDF_TARGET_ESP32P4
|
||||
config BOARD_TYPE_WAVESHARE_P4_WIFI6_TOUCH_LCD_4B
|
||||
bool "Waveshare ESP32-P4-WIFI6-Touch-LCD-4B"
|
||||
depends on IDF_TARGET_ESP32P4
|
||||
config BOARD_TYPE_WAVESHARE_P4_WIFI6_TOUCH_LCD_7B
|
||||
bool "Waveshare ESP32-P4-WIFI6-Touch-LCD-7B"
|
||||
depends on IDF_TARGET_ESP32P4
|
||||
config BOARD_TYPE_WAVESHARE_P4_WIFI6_TOUCH_LCD_XC
|
||||
bool "Waveshare ESP32-P4-WIFI6-Touch-LCD-3.4C or ESP32-P4-WIFI6-Touch-LCD-4C"
|
||||
depends on IDF_TARGET_ESP32P4
|
||||
config BOARD_TYPE_TUDOUZI
|
||||
bool "土豆子"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_LILYGO_T_CIRCLE_S3
|
||||
bool "LILYGO T-Circle-S3"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_LILYGO_T_CAMERAPLUS_S3_V1_0_V1_1
|
||||
bool "LILYGO T-CameraPlus-S3_V1_0_V1_1"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_LILYGO_T_CAMERAPLUS_S3_V1_2
|
||||
bool "LILYGO T-CameraPlus-S3_V1_2"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_LILYGO_T_DISPLAY_S3_PRO_MVSRLORA
|
||||
bool "LILYGO T-Display-S3-Pro-MVSRLora"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_LILYGO_T_DISPLAY_S3_PRO_MVSRLORA_NO_BATTERY
|
||||
bool "LILYGO T-Display-S3-Pro-MVSRLora_No_Battery"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_LILYGO_T_DISPLAY_P4
|
||||
bool "LILYGO T-Display-P4"
|
||||
depends on IDF_TARGET_ESP32P4
|
||||
config BOARD_TYPE_MOVECALL_MOJI_ESP32S3
|
||||
bool "Movecall Moji 小智AI衍生版"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_MOVECALL_CUICAN_ESP32S3
|
||||
bool "Movecall CuiCan 璀璨·AI吊坠"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ATK_DNESP32S3
|
||||
bool "正点原子DNESP32S3开发板"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ATK_DNESP32S3_BOX
|
||||
bool "正点原子DNESP32S3-BOX"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ATK_DNESP32S3_BOX0
|
||||
bool "正点原子DNESP32S3-BOX0"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ATK_DNESP32S3_BOX2_WIFI
|
||||
bool "正点原子DNESP32S3-BOX2-WIFI"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ATK_DNESP32S3_BOX2_4G
|
||||
bool "正点原子DNESP32S3-BOX2-4G"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ATK_DNESP32S3M_WIFI
|
||||
bool "正点原子DNESP32S3M-WIFI"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ATK_DNESP32S3M_4G
|
||||
bool "正点原子DNESP32S3M-4G"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_DU_CHATX
|
||||
bool "嘟嘟开发板CHATX(wifi)"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_TAIJI_PI_S3
|
||||
bool "太极小派esp32s3"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_XINGZHI_CUBE_0_85TFT_WIFI
|
||||
bool "无名科技星智0.85(WIFI)"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_XINGZHI_CUBE_0_85TFT_ML307
|
||||
bool "无名科技星智0.85(ML307)"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_XINGZHI_CUBE_0_96OLED_WIFI
|
||||
bool "无名科技星智0.96(WIFI)"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_XINGZHI_CUBE_0_96OLED_ML307
|
||||
bool "无名科技星智0.96(ML307)"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_XINGZHI_CUBE_1_54TFT_WIFI
|
||||
bool "无名科技星智1.54(WIFI)"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_XINGZHI_CUBE_1_54TFT_ML307
|
||||
bool "无名科技星智1.54(ML307)"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_SEEED_STUDIO_SENSECAP_WATCHER
|
||||
bool "Seeed Studio SenseCAP Watcher"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_DOIT_S3_AIBOX
|
||||
bool "四博智联AI陪伴盒子"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_MIXGO_NOVA
|
||||
bool "元控·青春"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_GENJUTECH_S3_1_54TFT
|
||||
bool "亘具科技1.54(s3)"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ESP_S3_LCD_EV_Board
|
||||
bool "乐鑫ESP S3 LCD EV Board开发板"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ESP_S3_LCD_EV_Board_2
|
||||
bool "乐鑫ESP S3 LCD EV Board 2开发板"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ZHENGCHEN_1_54TFT_WIFI
|
||||
bool "征辰科技1.54(WIFI)"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ZHENGCHEN_1_54TFT_ML307
|
||||
bool "征辰科技1.54(ML307)"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_MINSI_K08_DUAL
|
||||
bool "敏思科技K08(DUAL)"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_SPOTPEAR_ESP32_S3_1_54_MUMA
|
||||
bool "Spotpear ESP32-S3-1.54-MUMA"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_SPOTPEAR_ESP32_S3_1_28_BOX
|
||||
bool "Spotpear ESP32-S3-1.28-BOX"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_OTTO_ROBOT
|
||||
bool "ottoRobot"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ELECTRON_BOT
|
||||
bool "electronBot"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_JIUCHUAN
|
||||
bool "九川智能"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_LABPLUS_MPYTHON_V3
|
||||
bool "labplus mpython_v3 board"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_LABPLUS_LEDONG_V2
|
||||
bool "labplus ledong_v2 board"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_SURFER_C3_1_14TFT
|
||||
bool "Surfer-C3-1.14TFT"
|
||||
depends on IDF_TARGET_ESP32C3
|
||||
config BOARD_TYPE_YUNLIAO_S3
|
||||
bool "小智云聊-S3"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_WIRELESS_TAG_WTP4C5MP07S
|
||||
bool "Wireless-Tag WTP4C5MP07S"
|
||||
depends on IDF_TARGET_ESP32P4
|
||||
config BOARD_TYPE_AIPI_LITE
|
||||
bool "AIPI-Lite"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
endchoice
|
||||
|
||||
choice
|
||||
depends on BOARD_TYPE_LILYGO_T_DISPLAY_P4
|
||||
prompt "Select the screen type"
|
||||
default SCREEN_TYPE_HI8561
|
||||
config SCREEN_TYPE_HI8561
|
||||
bool "HI8561"
|
||||
config SCREEN_TYPE_RM69A10
|
||||
bool "RM69A10"
|
||||
endchoice
|
||||
|
||||
choice
|
||||
depends on BOARD_TYPE_LILYGO_T_DISPLAY_P4
|
||||
prompt "Select the color format of the screen"
|
||||
default SCREEN_PIXEL_FORMAT_RGB565
|
||||
config SCREEN_PIXEL_FORMAT_RGB565
|
||||
bool "RGB565"
|
||||
config SCREEN_PIXEL_FORMAT_RGB888
|
||||
bool "RGB888"
|
||||
endchoice
|
||||
|
||||
choice ESP_S3_LCD_EV_Board_Version_TYPE
|
||||
depends on BOARD_TYPE_ESP_S3_LCD_EV_Board
|
||||
prompt "EV_BOARD Type"
|
||||
default ESP_S3_LCD_EV_Board_1p4
|
||||
config ESP_S3_LCD_EV_Board_1p4
|
||||
bool "乐鑫ESP32_S3_LCD_EV_Board-MB_V1.4"
|
||||
config ESP_S3_LCD_EV_Board_1p5
|
||||
bool "乐鑫ESP32_S3_LCD_EV_Board-MB_V1.5"
|
||||
endchoice
|
||||
|
||||
choice DISPLAY_OLED_TYPE
|
||||
depends on BOARD_TYPE_BREAD_COMPACT_WIFI || BOARD_TYPE_BREAD_COMPACT_ML307 || BOARD_TYPE_BREAD_COMPACT_ESP32
|
||||
prompt "OLED Type"
|
||||
default OLED_SSD1306_128X32
|
||||
help
|
||||
OLED Monochrome Display Type
|
||||
config OLED_SSD1306_128X32
|
||||
bool "SSD1306 128*32"
|
||||
config OLED_SSD1306_128X64
|
||||
bool "SSD1306 128*64"
|
||||
config OLED_SH1106_128X64
|
||||
bool "SH1106 128*64"
|
||||
endchoice
|
||||
|
||||
choice DISPLAY_LCD_TYPE
|
||||
depends on BOARD_TYPE_BREAD_COMPACT_WIFI_LCD || BOARD_TYPE_BREAD_COMPACT_ESP32_LCD || BOARD_TYPE_CGC || BOARD_TYPE_WAVESHARE_P4_NANO || BOARD_TYPE_WAVESHARE_P4_WIFI6_TOUCH_LCD_XC || BOARD_TYPE_BREAD_COMPACT_WIFI_CAM
|
||||
prompt "LCD Type"
|
||||
default LCD_ST7789_240X320
|
||||
help
|
||||
LCD Display Type
|
||||
config LCD_ST7789_240X320
|
||||
bool "ST7789 240*320, IPS"
|
||||
config LCD_ST7789_240X320_NO_IPS
|
||||
bool "ST7789 240*320, Non-IPS"
|
||||
config LCD_ST7789_170X320
|
||||
bool "ST7789 170*320"
|
||||
config LCD_ST7789_172X320
|
||||
bool "ST7789 172*320"
|
||||
config LCD_ST7789_240X280
|
||||
bool "ST7789 240*280"
|
||||
config LCD_ST7789_240X240
|
||||
bool "ST7789 240*240"
|
||||
config LCD_ST7789_240X240_7PIN
|
||||
bool "ST7789 240*240, 7PIN"
|
||||
config LCD_ST7789_240X135
|
||||
bool "ST7789 240*135"
|
||||
config LCD_ST7735_128X160
|
||||
bool "ST7735 128*160"
|
||||
config LCD_ST7735_128X128
|
||||
bool "ST7735 128*128"
|
||||
config LCD_ST7796_320X480
|
||||
bool "ST7796 320*480 IPS"
|
||||
config LCD_ST7796_320X480_NO_IPS
|
||||
bool "ST7796 320*480, Non-IPS"
|
||||
config LCD_ILI9341_240X320
|
||||
bool "ILI9341 240*320"
|
||||
config LCD_ILI9341_240X320_NO_IPS
|
||||
bool "ILI9341 240*320, Non-IPS"
|
||||
config LCD_GC9A01_240X240
|
||||
bool "GC9A01 240*240 Circle"
|
||||
config LCD_TYPE_800_1280_10_1_INCH
|
||||
bool "Waveshare 101M-8001280-IPS-CT-K Display"
|
||||
config LCD_TYPE_800_1280_10_1_INCH_A
|
||||
bool "Waveshare 10.1-DSI-TOUCH-A Display"
|
||||
config LCD_TYPE_800_800_3_4_INCH
|
||||
bool "Waveshare ESP32-P4-WIFI6-Touch-LCD-3.4C with 800*800 3.4inch round display"
|
||||
config LCD_TYPE_720_720_4_INCH
|
||||
bool "Waveshare ESP32-P4-WIFI6-Touch-LCD-4C with 720*720 4inch round display"
|
||||
config LCD_CUSTOM
|
||||
bool "Custom LCD (自定义屏幕参数)"
|
||||
endchoice
|
||||
|
||||
choice DISPLAY_ESP32S3_KORVO2_V3
|
||||
depends on BOARD_TYPE_ESP_KORVO2_V3
|
||||
prompt "ESP32S3_KORVO2_V3 LCD Type"
|
||||
default ESP32S3_KORVO2_V3_LCD_ST7789
|
||||
help
|
||||
LCD Display Type
|
||||
config ESP32S3_KORVO2_V3_LCD_ST7789
|
||||
bool "ST7789 240*280"
|
||||
config ESP32S3_KORVO2_V3_LCD_ILI9341
|
||||
bool "ILI9341 240*320"
|
||||
endchoice
|
||||
|
||||
choice DISPLAY_ESP32S3_AUDIO_BOARD
|
||||
depends on BOARD_TYPE_WAVESHARE_S3_AUDIO_BOARD
|
||||
prompt "ESP32S3_AUDIO_BOARD LCD Type"
|
||||
default AUDIO_BOARD_LCD_JD9853
|
||||
help
|
||||
LCD Display Type
|
||||
config AUDIO_BOARD_LCD_JD9853
|
||||
bool "JD9853 320*172"
|
||||
config AUDIO_BOARD_LCD_ST7789
|
||||
bool "ST7789 240*320"
|
||||
endchoice
|
||||
|
||||
choice DISPLAY_STYLE
|
||||
prompt "Select display style"
|
||||
default USE_DEFAULT_MESSAGE_STYLE
|
||||
help
|
||||
Select display style for Xiaozhi device
|
||||
|
||||
config USE_DEFAULT_MESSAGE_STYLE
|
||||
bool "Enable default message style"
|
||||
|
||||
config USE_WECHAT_MESSAGE_STYLE
|
||||
bool "Enable WeChat Message Style"
|
||||
|
||||
config USE_EMOTE_MESSAGE_STYLE
|
||||
bool "Emote animation style"
|
||||
depends on BOARD_TYPE_ESP_BOX_3 || BOARD_TYPE_ECHOEAR || BOARD_TYPE_LICHUANG_DEV_S3
|
||||
endchoice
|
||||
|
||||
choice WAKE_WORD_TYPE
|
||||
prompt "Wake Word Implementation Type"
|
||||
default USE_AFE_WAKE_WORD if (IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32P4) && SPIRAM
|
||||
default WAKE_WORD_DISABLED
|
||||
help
|
||||
Choose the type of wake word implementation to use
|
||||
|
||||
config WAKE_WORD_DISABLED
|
||||
bool "Disabled"
|
||||
help
|
||||
Disable wake word detection
|
||||
|
||||
config USE_ESP_WAKE_WORD
|
||||
bool "Wakenet model without AFE"
|
||||
depends on IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32C5 || IDF_TARGET_ESP32C6 || (IDF_TARGET_ESP32 && SPIRAM)
|
||||
help
|
||||
Support ESP32 C3、ESP32 C5 与 ESP32 C6, and (ESP32 with PSRAM)
|
||||
|
||||
config USE_AFE_WAKE_WORD
|
||||
bool "Wakenet model with AFE"
|
||||
depends on (IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32P4) && SPIRAM
|
||||
help
|
||||
Support AEC if available, requires ESP32 S3 and PSRAM
|
||||
|
||||
config USE_CUSTOM_WAKE_WORD
|
||||
bool "Multinet model (Custom Wake Word)"
|
||||
depends on (IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32P4) && SPIRAM
|
||||
help
|
||||
Requires ESP32 S3 and PSRAM
|
||||
|
||||
endchoice
|
||||
|
||||
config CUSTOM_WAKE_WORD
|
||||
string "Custom Wake Word"
|
||||
default "xiao tu dou"
|
||||
depends on USE_CUSTOM_WAKE_WORD
|
||||
help
|
||||
Custom Wake Word, use pinyin for Chinese, separated by spaces
|
||||
|
||||
config CUSTOM_WAKE_WORD_DISPLAY
|
||||
string "Custom Wake Word Display"
|
||||
default "小土豆"
|
||||
depends on USE_CUSTOM_WAKE_WORD
|
||||
help
|
||||
Greeting sent to the server after wake word detection
|
||||
|
||||
config CUSTOM_WAKE_WORD_THRESHOLD
|
||||
int "Custom Wake Word Threshold (%)"
|
||||
default 20
|
||||
range 1 99
|
||||
depends on USE_CUSTOM_WAKE_WORD
|
||||
help
|
||||
Custom Wake Word Threshold, range 1-99, the smaller the more sensitive, default 20
|
||||
|
||||
config SEND_WAKE_WORD_DATA
|
||||
bool "Send Wake Word Data"
|
||||
default y
|
||||
depends on USE_AFE_WAKE_WORD || USE_CUSTOM_WAKE_WORD
|
||||
help
|
||||
Send wake word data to the server as the first message of the conversation and wait for response
|
||||
|
||||
config USE_AUDIO_PROCESSOR
|
||||
bool "Enable Audio Noise Reduction"
|
||||
default y
|
||||
depends on (IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32P4) && SPIRAM
|
||||
help
|
||||
Requires ESP32 S3 and PSRAM
|
||||
|
||||
config USE_DEVICE_AEC
|
||||
bool "Enable Device-Side AEC"
|
||||
default n
|
||||
depends on USE_AUDIO_PROCESSOR && (BOARD_TYPE_ESP_BOX_3 || BOARD_TYPE_ESP_BOX || BOARD_TYPE_ESP_BOX_LITE \
|
||||
|| BOARD_TYPE_LICHUANG_DEV_S3 || BOARD_TYPE_ESP_KORVO2_V3 || BOARD_TYPE_WAVESHARE_S3_TOUCH_AMOLED_1_75 || BOARD_TYPE_WAVESHARE_S3_TOUCH_LCD_1_83\
|
||||
|| BOARD_TYPE_WAVESHARE_S3_TOUCH_AMOLED_2_06 || BOARD_TYPE_WAVESHARE_S3_TOUCH_LCD_4B || BOARD_TYPE_WAVESHARE_P4_WIFI6_TOUCH_LCD_4B || BOARD_TYPE_WAVESHARE_P4_WIFI6_TOUCH_LCD_7B \
|
||||
|| BOARD_TYPE_WAVESHARE_P4_WIFI6_TOUCH_LCD_XC || BOARD_TYPE_ESP_S3_LCD_EV_Board_2 || BOARD_TYPE_YUNLIAO_S3 \
|
||||
|| BOARD_TYPE_ECHOEAR || BOARD_TYPE_WAVESHARE_S3_TOUCH_LCD_3_49)
|
||||
help
|
||||
To work properly, device-side AEC requires a clean output reference path from the speaker signal and physical acoustic isolation between the microphone and speaker.
|
||||
|
||||
config USE_SERVER_AEC
|
||||
bool "Enable Server-Side AEC (Unstable)"
|
||||
default n
|
||||
depends on USE_AUDIO_PROCESSOR
|
||||
help
|
||||
To work perperly, server-side AEC requires server support
|
||||
|
||||
config USE_AUDIO_DEBUGGER
|
||||
bool "Enable Audio Debugger"
|
||||
default n
|
||||
help
|
||||
Enable audio debugger, send audio data through UDP to the host machine
|
||||
|
||||
config AUDIO_DEBUG_UDP_SERVER
|
||||
string "Audio Debug UDP Server Address"
|
||||
default "192.168.2.100:8000"
|
||||
depends on USE_AUDIO_DEBUGGER
|
||||
help
|
||||
UDP server address, format: IP:PORT, used to receive audio debugging data
|
||||
|
||||
config USE_ACOUSTIC_WIFI_PROVISIONING
|
||||
bool "Enable Acoustic WiFi Provisioning"
|
||||
default n
|
||||
help
|
||||
Enable acoustic WiFi provisioning, use audio signal to transmit WiFi configuration data
|
||||
|
||||
config RECEIVE_CUSTOM_MESSAGE
|
||||
bool "Enable Custom Message Reception"
|
||||
default n
|
||||
help
|
||||
Enable custom message reception, allow the device to receive custom messages from the server (preferably through the MQTT protocol)
|
||||
|
||||
menu "Camera Configuration"
|
||||
depends on !IDF_TARGET_ESP32
|
||||
|
||||
comment "Warning: Please read the help text before modifying these settings."
|
||||
|
||||
config XIAOZHI_ENABLE_HARDWARE_JPEG_ENCODER
|
||||
bool "Enable Hardware JPEG Encoder"
|
||||
default y
|
||||
depends on SOC_JPEG_ENCODE_SUPPORTED
|
||||
help
|
||||
Use hardware JPEG encoder on ESP32-P4 to encode image to JPEG.
|
||||
See https://docs.espressif.com/projects/esp-idf/en/stable/esp32p4/api-reference/peripherals/jpeg.html for more details.
|
||||
|
||||
config XIAOZHI_ENABLE_CAMERA_DEBUG_MODE
|
||||
bool "Enable Camera Debug Mode"
|
||||
default n
|
||||
help
|
||||
Enable camera debug mode, print camera debug information to the console.
|
||||
Only works on boards that support camera.
|
||||
|
||||
config XIAOZHI_ENABLE_CAMERA_ENDIANNESS_SWAP
|
||||
bool "Enable software camera buffer endianness swapping (USE WITH CAUTION)"
|
||||
default n
|
||||
depends on !CAMERA_SENSOR_SWAP_PIXEL_BYTE_ORDER
|
||||
help
|
||||
This option treats the camera buffer as a uint16_t[] array and performs byte-swapping (endianness conversion) on each element.
|
||||
|
||||
Should only be modified by development board integration engineers.
|
||||
|
||||
**Incorrect usage may result in incorrect image colors!**
|
||||
|
||||
ATTENTION: If the option CAMERA_SENSOR_SWAP_PIXEL_BYTE_ORDER is available for your sensor, please use that instead.
|
||||
|
||||
menuconfig XIAOZHI_ENABLE_ROTATE_CAMERA_IMAGE
|
||||
bool "Enable Camera Image Rotation"
|
||||
default n
|
||||
help
|
||||
Enable camera image rotation, rotate the camera image to the correct orientation.
|
||||
- On ESP32-P4, rotation is handled by PPA hardware.
|
||||
- On other chips, rotation is done in software with performance cost.
|
||||
- For 180° rotation, use HFlip + VFlip instead of this option.
|
||||
|
||||
if XIAOZHI_ENABLE_ROTATE_CAMERA_IMAGE
|
||||
choice XIAOZHI_CAMERA_IMAGE_ROTATION_ANGLE
|
||||
prompt "Camera Image Rotation Angle (clockwise)"
|
||||
default XIAOZHI_CAMERA_IMAGE_ROTATION_ANGLE_90
|
||||
help
|
||||
Camera image rotation angle.
|
||||
config XIAOZHI_CAMERA_IMAGE_ROTATION_ANGLE_90
|
||||
bool "90°"
|
||||
config XIAOZHI_CAMERA_IMAGE_ROTATION_ANGLE_270
|
||||
bool "270°"
|
||||
comment "For 180° rotation, use HFlip + VFlip instead of this option"
|
||||
endchoice
|
||||
endif
|
||||
endmenu
|
||||
|
||||
menu "TAIJIPAI_S3_CONFIG"
|
||||
depends on BOARD_TYPE_TAIJI_PI_S3
|
||||
choice I2S_TYPE_TAIJIPI_S3
|
||||
prompt "taiji-pi-S3 I2S Type"
|
||||
default TAIJIPAI_I2S_TYPE_STD
|
||||
help
|
||||
I2S 类型选择
|
||||
config TAIJIPAI_I2S_TYPE_STD
|
||||
bool "I2S Type STD"
|
||||
config TAIJIPAI_I2S_TYPE_PDM
|
||||
bool "I2S Type PDM"
|
||||
endchoice
|
||||
|
||||
config I2S_USE_2SLOT
|
||||
bool "Enable I2S 2 Slot"
|
||||
default y
|
||||
help
|
||||
启动双声道
|
||||
endmenu
|
||||
|
||||
endmenu
|
||||
|
||||
menu "BLE prph Configuration"
|
||||
|
||||
choice EXAMPLE_USE_IO_TYPE
|
||||
prompt "I/O Capability"
|
||||
default BLE_SM_IO_CAP_NO_IO
|
||||
help
|
||||
I/O capability of device.
|
||||
|
||||
config BLE_SM_IO_CAP_DISP_ONLY
|
||||
bool "DISPLAY ONLY"
|
||||
config BLE_SM_IO_CAP_DISP_YES_NO
|
||||
bool "DISPLAY YESNO"
|
||||
config BLE_SM_IO_CAP_KEYBOARD_ONLY
|
||||
bool "KEYBOARD ONLY"
|
||||
config BLE_SM_IO_CAP_NO_IO
|
||||
bool "Just works"
|
||||
config BLE_SM_IO_CAP_KEYBOARD_DISP
|
||||
bool "Both KEYBOARD & DISPLAY"
|
||||
endchoice
|
||||
|
||||
config EXAMPLE_IO_TYPE
|
||||
int
|
||||
default 0 if BLE_SM_IO_CAP_DISP_ONLY
|
||||
default 1 if BLE_SM_IO_CAP_DISP_YES_NO
|
||||
default 2 if BLE_SM_IO_CAP_KEYBOARD_ONLY
|
||||
default 3 if BLE_SM_IO_CAP_NO_IO
|
||||
default 4 if BLE_SM_IO_CAP_KEYBOARD_DISP
|
||||
|
||||
config EXAMPLE_BONDING
|
||||
bool
|
||||
default n
|
||||
prompt "Use Bonding"
|
||||
help
|
||||
Use this option to enable/disable bonding.
|
||||
|
||||
config EXAMPLE_MITM
|
||||
bool
|
||||
default n
|
||||
prompt "MITM security"
|
||||
help
|
||||
Use this option to enable/disable MITM security.
|
||||
|
||||
config EXAMPLE_USE_SC
|
||||
bool
|
||||
depends on BT_NIMBLE_SM_SC
|
||||
default n
|
||||
prompt "Use Secure Connection feature"
|
||||
help
|
||||
Use this option to enable/disable Security Manager Secure Connection 4.2 feature.
|
||||
|
||||
config EXAMPLE_EXTENDED_ADV
|
||||
bool
|
||||
depends on SOC_BLE_50_SUPPORTED && BT_NIMBLE_50_FEATURE_SUPPORT
|
||||
default y if SOC_ESP_NIMBLE_CONTROLLER
|
||||
select BT_NIMBLE_EXT_ADV
|
||||
prompt "Enable Extended Adv"
|
||||
help
|
||||
Use this option to enable extended advertising in the example.
|
||||
If this option is disabled, ensure config BT_NIMBLE_EXT_ADV is
|
||||
also disabled from Nimble stack menuconfig
|
||||
|
||||
config EXAMPLE_RANDOM_ADDR
|
||||
bool
|
||||
prompt "Advertise RANDOM Address"
|
||||
help
|
||||
Use this option to advertise a random address instead of public address
|
||||
|
||||
config EXAMPLE_ENCRYPTION
|
||||
bool
|
||||
prompt "Enable Link Encryption"
|
||||
help
|
||||
This adds Encrypted Read and Write permissions in the custom GATT server.
|
||||
|
||||
config EXAMPLE_RESOLVE_PEER_ADDR
|
||||
bool
|
||||
prompt "Enable resolving peer address"
|
||||
help
|
||||
Use this option to enable resolving peer's address.
|
||||
|
||||
endmenu
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#include "app_ai_agent.h"
|
||||
#include <hal/hal.h>
|
||||
#include <mooncake.h>
|
||||
#include <mooncake_log.h>
|
||||
#include <assets/assets.h>
|
||||
#include <smooth_lvgl.hpp>
|
||||
|
||||
using namespace mooncake;
|
||||
using namespace smooth_ui_toolkit::lvgl_cpp;
|
||||
|
||||
AppAiAgent::AppAiAgent()
|
||||
{
|
||||
// Configure App name
|
||||
setAppInfo().name = "AI.AGENT";
|
||||
// Configure App icon
|
||||
setAppInfo().icon = (void*)&icon_ai_agent;
|
||||
// Configure App theme color
|
||||
static uint32_t theme_color = 0x33CC99;
|
||||
setAppInfo().userData = (void*)&theme_color;
|
||||
}
|
||||
|
||||
// Called when the App is installed
|
||||
void AppAiAgent::onCreate()
|
||||
{
|
||||
mclog::tagInfo(getAppInfo().name, "on create");
|
||||
}
|
||||
|
||||
// Called when the App is opened
|
||||
// You can construct UI, initialize operations, etc. here
|
||||
void AppAiAgent::onOpen()
|
||||
{
|
||||
mclog::tagInfo(getAppInfo().name, "on open");
|
||||
|
||||
GetHAL().startXiaozhi();
|
||||
}
|
||||
|
||||
// Called repeatedly while the App is running
|
||||
void AppAiAgent::onRunning()
|
||||
{
|
||||
}
|
||||
|
||||
// Called when the App is closed
|
||||
// You can destroy UI, release resources, etc. here
|
||||
void AppAiAgent::onClose()
|
||||
{
|
||||
mclog::tagInfo(getAppInfo().name, "on close");
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#pragma once
|
||||
#include <mooncake.h>
|
||||
|
||||
/**
|
||||
* @brief Derived App
|
||||
*
|
||||
*/
|
||||
class AppAiAgent : public mooncake::AppAbility {
|
||||
public:
|
||||
AppAiAgent();
|
||||
|
||||
// Override lifecycle callbacks
|
||||
void onCreate() override;
|
||||
void onOpen() override;
|
||||
void onRunning() override;
|
||||
void onClose() override;
|
||||
};
|
||||
@@ -0,0 +1,255 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#include "app_avatar.h"
|
||||
#include "view/ws_call.h"
|
||||
#include <hal/hal.h>
|
||||
#include <mooncake.h>
|
||||
#include <mooncake_log.h>
|
||||
#include <assets/assets.h>
|
||||
#include <smooth_lvgl.hpp>
|
||||
#include <stackchan/stackchan.h>
|
||||
#include <string_view>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
|
||||
using namespace mooncake;
|
||||
using namespace smooth_ui_toolkit::lvgl_cpp;
|
||||
using namespace stackchan;
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <unordered_set>
|
||||
|
||||
static bool contains_word(const std::string& text, const std::unordered_set<std::string>& words)
|
||||
{
|
||||
auto to_lower = [](std::string s) {
|
||||
std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c) { return std::tolower(c); });
|
||||
return s;
|
||||
};
|
||||
|
||||
std::istringstream iss(text);
|
||||
std::string token;
|
||||
while (iss >> token) {
|
||||
token = to_lower(token);
|
||||
if (words.find(token) != words.end()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
AppAvatar::AppAvatar()
|
||||
{
|
||||
// 配置 App 名
|
||||
setAppInfo().name = "AVATAR";
|
||||
// 配置 App 图标
|
||||
setAppInfo().icon = (void*)&icon_sentinel;
|
||||
// 配置 App 主题颜色
|
||||
static uint32_t theme_color = 0xFF6699;
|
||||
setAppInfo().userData = (void*)&theme_color;
|
||||
}
|
||||
|
||||
// App 被安装时会被调用
|
||||
void AppAvatar::onCreate()
|
||||
{
|
||||
mclog::tagInfo(getAppInfo().name, "on create");
|
||||
}
|
||||
|
||||
void AppAvatar::onOpen()
|
||||
{
|
||||
mclog::tagInfo(getAppInfo().name, "on open");
|
||||
|
||||
// GetHAL().startBleServer();
|
||||
GetHAL().startWebSocketAvatar();
|
||||
|
||||
LvglLockGuard lock;
|
||||
|
||||
// Create default avatar
|
||||
auto avatar = std::make_unique<avatar::DefaultAvatar>();
|
||||
avatar->init(lv_screen_active());
|
||||
GetStackChan().attachAvatar(std::move(avatar));
|
||||
|
||||
/* ------------------------------- BLE events ------------------------------- */
|
||||
_ble_avatar_data.callback_id = GetHAL().onBleAvatarData.connect([&](const char* data) {
|
||||
std::lock_guard<std::mutex> lock(_mutex);
|
||||
if (_ble_avatar_data.update_flag) {
|
||||
return;
|
||||
}
|
||||
_ble_avatar_data.update_flag = true;
|
||||
_ble_avatar_data.data_ptr = (char*)data;
|
||||
});
|
||||
|
||||
_ble_motion_data.callback_id = GetHAL().onBleMotionData.connect([&](const char* data) {
|
||||
std::lock_guard<std::mutex> lock(_mutex);
|
||||
if (_ble_motion_data.update_flag) {
|
||||
return;
|
||||
}
|
||||
_ble_motion_data.update_flag = true;
|
||||
_ble_motion_data.data_ptr = (char*)data;
|
||||
});
|
||||
|
||||
/* ---------------------------- Websocket events ---------------------------- */
|
||||
// Avatar control
|
||||
_ws_callback_ids.avatar_id = GetHAL().onWsAvatarData.connect([&](std::string_view data) {
|
||||
LvglLockGuard lvgl_lock;
|
||||
GetStackChan().updateAvatarFromJson(data.data());
|
||||
});
|
||||
|
||||
// Motion control
|
||||
_ws_callback_ids.motion_id = GetHAL().onWsMotionData.connect([&](std::string_view data) {
|
||||
LvglLockGuard lvgl_lock;
|
||||
check_auto_angle_sync_mode();
|
||||
GetStackChan().updateMotionFromJson(data.data());
|
||||
});
|
||||
|
||||
// Phone call handling
|
||||
_ws_callback_ids.call_req_id = GetHAL().onWsCallRequest.connect([&](std::string caller) {
|
||||
if (_ws_call_view_id >= 0) {
|
||||
mclog::tagWarn(getAppInfo().name, "ws call view already exists");
|
||||
return;
|
||||
}
|
||||
|
||||
LvglLockGuard lvgl_lock;
|
||||
|
||||
auto& avatar = GetStackChan().avatar();
|
||||
avatar.setSpeech("");
|
||||
avatar.leftEye().setVisible(false);
|
||||
avatar.rightEye().setVisible(false);
|
||||
avatar.mouth().setVisible(false);
|
||||
|
||||
auto view = std::make_unique<view::WsCallView>(lv_screen_active(), caller);
|
||||
view->onAccept = []() {
|
||||
auto& avatar = GetStackChan().avatar();
|
||||
avatar.setSpeech("");
|
||||
avatar.leftEye().setVisible(true);
|
||||
avatar.rightEye().setVisible(true);
|
||||
avatar.mouth().setVisible(true);
|
||||
|
||||
GetHAL().onWsCallResponse.emit(true);
|
||||
};
|
||||
view->onDecline = []() {
|
||||
auto& avatar = GetStackChan().avatar();
|
||||
avatar.setSpeech("");
|
||||
avatar.leftEye().setVisible(true);
|
||||
avatar.rightEye().setVisible(true);
|
||||
avatar.mouth().setVisible(true);
|
||||
|
||||
GetHAL().onWsCallResponse.emit(false);
|
||||
};
|
||||
view->onEnd = []() { GetHAL().onWsCallEnd.emit(WsSignalSource::Local); };
|
||||
view->onDestory = [&]() { _ws_call_view_id = -1; };
|
||||
|
||||
_ws_call_view_id = avatar.addDecorator(std::move(view));
|
||||
});
|
||||
|
||||
_ws_callback_ids.call_end_id = GetHAL().onWsCallEnd.connect([&](WsSignalSource source) {
|
||||
if (source != WsSignalSource::Remote) {
|
||||
return;
|
||||
}
|
||||
|
||||
LvglLockGuard lvgl_lock;
|
||||
|
||||
if (_ws_call_view_id < 0) {
|
||||
mclog::tagWarn(getAppInfo().name, "ws call view does not exist");
|
||||
return;
|
||||
}
|
||||
|
||||
auto& avatar = GetStackChan().avatar();
|
||||
avatar.setSpeech("");
|
||||
avatar.leftEye().setVisible(true);
|
||||
avatar.rightEye().setVisible(true);
|
||||
avatar.mouth().setVisible(true);
|
||||
|
||||
avatar.removeDecorator(_ws_call_view_id);
|
||||
_ws_call_view_id = -1;
|
||||
});
|
||||
|
||||
// Text message handling
|
||||
_ws_callback_ids.text_msg_id = GetHAL().onWsTextMessage.connect([&](const WsTextMessage_t& message) {
|
||||
LvglLockGuard lvgl_lock;
|
||||
|
||||
auto& stackchan = GetStackChan();
|
||||
auto& avatar = stackchan.avatar();
|
||||
|
||||
stackchan.addModifier(
|
||||
std::make_unique<TimedSpeechModifier>(fmt::format("{} says: {}", message.name, message.content), 6000));
|
||||
stackchan.addModifier(std::make_unique<SpeakingModifier>(2000));
|
||||
|
||||
// Special handling
|
||||
if (contains_word(message.content, {"hello", "hi"})) {
|
||||
stackchan.addModifier(std::make_unique<TimedEmotionModifier>(avatar::Emotion::Happy, 2000));
|
||||
} else if (contains_word(message.content, {"love"})) {
|
||||
stackchan.addModifier(std::make_unique<TimedEmotionModifier>(avatar::Emotion::Happy, 2000));
|
||||
}
|
||||
});
|
||||
|
||||
_ws_callback_ids.dance_data_id = GetHAL().onWsDanceData.connect([&](std::string_view data) {
|
||||
LvglLockGuard lvgl_lock;
|
||||
auto sequence = stackchan::animation::parse_sequence_from_json(data.data());
|
||||
if (!sequence.empty()) {
|
||||
GetStackChan().addModifier(std::make_unique<DanceModifier>(sequence));
|
||||
}
|
||||
});
|
||||
|
||||
/* ------------------------------ Video window ------------------------------ */
|
||||
_video_window = std::make_unique<view::VideoWindow>(lv_screen_active());
|
||||
}
|
||||
|
||||
void AppAvatar::onRunning()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_mutex);
|
||||
|
||||
LvglLockGuard lvgl_lock;
|
||||
|
||||
if (_ble_avatar_data.update_flag) {
|
||||
GetStackChan().updateAvatarFromJson(_ble_avatar_data.data_ptr);
|
||||
_ble_avatar_data.update_flag = false;
|
||||
_ble_avatar_data.data_ptr = nullptr;
|
||||
}
|
||||
|
||||
if (_ble_motion_data.update_flag) {
|
||||
check_auto_angle_sync_mode();
|
||||
GetStackChan().updateMotionFromJson(_ble_motion_data.data_ptr);
|
||||
_ble_motion_data.update_flag = false;
|
||||
_ble_motion_data.data_ptr = nullptr;
|
||||
}
|
||||
|
||||
GetStackChan().update();
|
||||
}
|
||||
|
||||
void AppAvatar::onClose()
|
||||
{
|
||||
mclog::tagInfo(getAppInfo().name, "on close");
|
||||
|
||||
LvglLockGuard lock;
|
||||
|
||||
GetStackChan().resetAvatar();
|
||||
_video_window.reset();
|
||||
|
||||
GetHAL().onBleAvatarData.disconnect(_ble_avatar_data.callback_id);
|
||||
GetHAL().onBleMotionData.disconnect(_ble_motion_data.callback_id);
|
||||
|
||||
GetHAL().onWsAvatarData.disconnect(_ws_callback_ids.avatar_id);
|
||||
GetHAL().onWsMotionData.disconnect(_ws_callback_ids.motion_id);
|
||||
GetHAL().onWsCallRequest.disconnect(_ws_callback_ids.call_req_id);
|
||||
GetHAL().onWsCallEnd.disconnect(_ws_callback_ids.call_end_id);
|
||||
GetHAL().onWsTextMessage.disconnect(_ws_callback_ids.text_msg_id);
|
||||
GetHAL().onWsDanceData.disconnect(_ws_callback_ids.dance_data_id);
|
||||
}
|
||||
|
||||
void AppAvatar::check_auto_angle_sync_mode()
|
||||
{
|
||||
auto& motion = GetStackChan().motion();
|
||||
|
||||
// If far from last command, enable auto angle sync
|
||||
if (GetHAL().millis() - _last_motion_cmd_tick > 2000) {
|
||||
motion.setAutoAngleSyncEnabled(true);
|
||||
} else {
|
||||
motion.setAutoAngleSyncEnabled(false);
|
||||
}
|
||||
|
||||
_last_motion_cmd_tick = GetHAL().millis();
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#pragma once
|
||||
#include "view/video_window.hpp"
|
||||
#include <mooncake.h>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* @brief 派生 App
|
||||
*
|
||||
*/
|
||||
class AppAvatar : public mooncake::AppAbility {
|
||||
public:
|
||||
AppAvatar();
|
||||
|
||||
// 重写生命周期回调
|
||||
void onCreate() override;
|
||||
void onOpen() override;
|
||||
void onRunning() override;
|
||||
void onClose() override;
|
||||
|
||||
private:
|
||||
std::mutex _mutex;
|
||||
|
||||
struct BleHandlerData_t {
|
||||
bool update_flag = false;
|
||||
char* data_ptr = nullptr;
|
||||
int callback_id = -1;
|
||||
};
|
||||
BleHandlerData_t _ble_avatar_data;
|
||||
BleHandlerData_t _ble_motion_data;
|
||||
|
||||
struct WsCallbackIds_t {
|
||||
int avatar_id = -1;
|
||||
int motion_id = -1;
|
||||
int call_req_id = -1;
|
||||
int call_end_id = -1;
|
||||
int text_msg_id = -1;
|
||||
int dance_data_id = -1;
|
||||
};
|
||||
WsCallbackIds_t _ws_callback_ids;
|
||||
|
||||
int _ws_call_view_id = -1;
|
||||
|
||||
uint32_t _last_motion_cmd_tick = 0;
|
||||
|
||||
std::unique_ptr<view::VideoWindow> _video_window;
|
||||
|
||||
void check_auto_angle_sync_mode();
|
||||
};
|
||||
@@ -0,0 +1,240 @@
|
||||
#ifdef __has_include
|
||||
#if __has_include("lvgl.h")
|
||||
#ifndef LV_LVGL_H_INCLUDE_SIMPLE
|
||||
#define LV_LVGL_H_INCLUDE_SIMPLE
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(LV_LVGL_H_INCLUDE_SIMPLE)
|
||||
#include "lvgl.h"
|
||||
#else
|
||||
#include "lvgl/lvgl.h"
|
||||
#endif
|
||||
|
||||
#ifndef LV_ATTRIBUTE_MEM_ALIGN
|
||||
#define LV_ATTRIBUTE_MEM_ALIGN
|
||||
#endif
|
||||
|
||||
#ifndef LV_ATTRIBUTE_IMAGE_ICON_PHONE
|
||||
#define LV_ATTRIBUTE_IMAGE_ICON_PHONE
|
||||
#endif
|
||||
|
||||
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMAGE_ICON_PHONE uint8_t icon_phone_map[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x80, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff,
|
||||
0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x40, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x40, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff,
|
||||
0xff, 0xff, 0xbf, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x40, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xbf, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
const lv_image_dsc_t icon_phone = {
|
||||
.header.cf = LV_COLOR_FORMAT_RGB565A8,
|
||||
.header.magic = LV_IMAGE_HEADER_MAGIC,
|
||||
.header.w = 36,
|
||||
.header.h = 36,
|
||||
.data_size = 1296 * 3,
|
||||
.data = icon_phone_map,
|
||||
};
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#pragma once
|
||||
#include <lvgl.h>
|
||||
#include <hal/hal.h>
|
||||
#include <smooth_lvgl.hpp>
|
||||
#include <uitk/short_namespace.hpp>
|
||||
#include <memory>
|
||||
|
||||
namespace view {
|
||||
|
||||
class VideoWindow {
|
||||
public:
|
||||
VideoWindow(lv_obj_t* parent)
|
||||
{
|
||||
_image = std::make_unique<uitk::lvgl_cpp::Image>(parent);
|
||||
_image->align(LV_ALIGN_CENTER, 0, 0);
|
||||
_image->setSize(320, 240);
|
||||
_image->setHidden(true);
|
||||
|
||||
_on_ws_video_mode_change_id = GetHAL().onWsVideoModeChange.connect([this](bool enabled) {
|
||||
LvglLockGuard lock;
|
||||
if (enabled) {
|
||||
_image->setHidden(false);
|
||||
} else {
|
||||
_image->setHidden(true);
|
||||
}
|
||||
});
|
||||
|
||||
_on_ws_video_frame_id = GetHAL().onWsVideoFrame.connect([this](std::shared_ptr<LvglImage> img) {
|
||||
LvglLockGuard lock;
|
||||
_image_cached = img;
|
||||
auto img_dsc = _image_cached->image_dsc();
|
||||
_image->setSrc(img_dsc);
|
||||
});
|
||||
}
|
||||
|
||||
~VideoWindow()
|
||||
{
|
||||
GetHAL().onWsVideoModeChange.disconnect(_on_ws_video_mode_change_id);
|
||||
GetHAL().onWsVideoFrame.disconnect(_on_ws_video_frame_id);
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<uitk::lvgl_cpp::Image> _image;
|
||||
std::shared_ptr<LvglImage> _image_cached;
|
||||
|
||||
int _on_ws_video_mode_change_id = -1;
|
||||
int _on_ws_video_frame_id = -1;
|
||||
};
|
||||
|
||||
} // namespace view
|
||||
@@ -0,0 +1,259 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#include "ws_call.h"
|
||||
#include <smooth_ui_toolkit.hpp>
|
||||
#include <mooncake_log.h>
|
||||
#include <functional>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
|
||||
using namespace smooth_ui_toolkit::lvgl_cpp;
|
||||
using namespace smooth_ui_toolkit;
|
||||
using namespace view;
|
||||
|
||||
LV_IMAGE_DECLARE(icon_phone);
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
*/
|
||||
class IncomingPanel : public Container {
|
||||
public:
|
||||
std::function<void(void)> onAccept;
|
||||
std::function<void(void)> onDecline;
|
||||
|
||||
IncomingPanel(lv_obj_t* parent, std::string caller) : Container(parent)
|
||||
{
|
||||
setSize(320, 240);
|
||||
align(LV_ALIGN_CENTER, 0, 0);
|
||||
setBorderWidth(0);
|
||||
setBgOpa(0);
|
||||
|
||||
_label_caller = std::make_unique<Label>(get());
|
||||
_label_caller->setTextFont(&lv_font_montserrat_24);
|
||||
_label_caller->setTextColor(lv_color_hex(0xFFFFFF));
|
||||
_label_caller->align(LV_ALIGN_CENTER, 0, -63);
|
||||
_label_caller->setText(caller);
|
||||
|
||||
_button_decline = std::make_unique<Button>(get());
|
||||
_button_decline->align(LV_ALIGN_CENTER, -73, 30);
|
||||
_button_decline->setBgColor(lv_color_hex(0xEB5545));
|
||||
_button_decline->setRadius(LV_RADIUS_CIRCLE);
|
||||
_button_decline->setShadowWidth(0);
|
||||
_button_decline->setBorderWidth(0);
|
||||
_button_decline->setSize(64, 64);
|
||||
_button_decline->onClick().connect([&]() {
|
||||
if (onDecline) {
|
||||
onDecline();
|
||||
}
|
||||
});
|
||||
|
||||
_img_decline = std::make_unique<Image>(_button_decline->get());
|
||||
_img_decline->align(LV_ALIGN_CENTER, 0, 0);
|
||||
_img_decline->setRotation(1325);
|
||||
_img_decline->setSrc(&icon_phone);
|
||||
|
||||
_label_decline = std::make_unique<Label>(get());
|
||||
_label_decline->setTextFont(&lv_font_montserrat_14);
|
||||
_label_decline->setTextColor(lv_color_hex(0xFFFFFF));
|
||||
_label_decline->align(LV_ALIGN_CENTER, -73, 77);
|
||||
_label_decline->setText("Decline");
|
||||
|
||||
_button_accept = std::make_unique<Button>(get());
|
||||
_button_accept->align(LV_ALIGN_CENTER, 73, 30);
|
||||
_button_accept->setBgColor(lv_color_hex(0x67CE67));
|
||||
_button_accept->setRadius(LV_RADIUS_CIRCLE);
|
||||
_button_accept->setShadowWidth(0);
|
||||
_button_accept->setBorderWidth(0);
|
||||
_button_accept->setSize(64, 64);
|
||||
_button_accept->onClick().connect([&]() {
|
||||
if (onAccept) {
|
||||
onAccept();
|
||||
}
|
||||
});
|
||||
|
||||
_img_accept = std::make_unique<Image>(_button_accept->get());
|
||||
_img_accept->align(LV_ALIGN_CENTER, 0, 0);
|
||||
_img_accept->setSrc(&icon_phone);
|
||||
|
||||
_label_accept = std::make_unique<Label>(get());
|
||||
_label_accept->setTextFont(&lv_font_montserrat_14);
|
||||
_label_accept->setTextColor(lv_color_hex(0xFFFFFF));
|
||||
_label_accept->align(LV_ALIGN_CENTER, 73, 77);
|
||||
_label_accept->setText("Accept");
|
||||
}
|
||||
|
||||
void update()
|
||||
{
|
||||
if (GetHAL().millis() - _time_count > 600) {
|
||||
_anim_flag = !_anim_flag;
|
||||
if (_anim_flag) {
|
||||
_img_accept->setRotation(-200);
|
||||
} else {
|
||||
_img_accept->setRotation(0);
|
||||
}
|
||||
|
||||
_time_count = GetHAL().millis();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<Label> _label_caller;
|
||||
std::unique_ptr<Label> _label_decline;
|
||||
std::unique_ptr<Label> _label_accept;
|
||||
std::unique_ptr<Button> _button_decline;
|
||||
std::unique_ptr<Button> _button_accept;
|
||||
std::unique_ptr<Image> _img_decline;
|
||||
std::unique_ptr<Image> _img_accept;
|
||||
|
||||
uint32_t _time_count = 0;
|
||||
bool _anim_flag = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
*/
|
||||
class ConnectingPanel : public Container {
|
||||
public:
|
||||
std::function<void(void)> onEnd;
|
||||
|
||||
ConnectingPanel(lv_obj_t* parent, std::string caller) : Container(parent)
|
||||
{
|
||||
setSize(320, 240);
|
||||
align(LV_ALIGN_CENTER, 0, 0);
|
||||
setPadding(0, 0, 0, 0);
|
||||
setBorderWidth(0);
|
||||
setBgOpa(0);
|
||||
|
||||
_label_caller = std::make_unique<Label>(get());
|
||||
_label_caller->setTextFont(&lv_font_montserrat_16);
|
||||
_label_caller->setTextColor(lv_color_hex(0xFFFFFF));
|
||||
_label_caller->align(LV_ALIGN_LEFT_MID, 13, 85);
|
||||
_label_caller->setText(caller);
|
||||
|
||||
_label_timer = std::make_unique<Label>(get());
|
||||
_label_timer->setTextFont(&lv_font_montserrat_14);
|
||||
_label_timer->setTextColor(lv_color_hex(0x67CE67));
|
||||
_label_timer->align(LV_ALIGN_LEFT_MID, 13, 104);
|
||||
|
||||
_button_end = std::make_unique<Button>(get());
|
||||
_button_end->align(LV_ALIGN_CENTER, 116, 94);
|
||||
_button_end->setBgColor(lv_color_hex(0xEB5545));
|
||||
_button_end->setRadius(10);
|
||||
_button_end->setShadowWidth(0);
|
||||
_button_end->setBorderWidth(0);
|
||||
_button_end->setSize(72, 36);
|
||||
_button_end->onClick().connect([&]() {
|
||||
if (onEnd) {
|
||||
onEnd();
|
||||
}
|
||||
});
|
||||
_button_end->label().setTextFont(&lv_font_montserrat_14);
|
||||
_button_end->label().setTextColor(lv_color_hex(0xFFFFFF));
|
||||
_button_end->label().setText("End");
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
_connect_time_count = GetHAL().millis();
|
||||
update_timer_label();
|
||||
}
|
||||
|
||||
void update_timer_label()
|
||||
{
|
||||
uint32_t elapsed = (GetHAL().millis() - _connect_time_count) / 1000;
|
||||
uint32_t min = elapsed / 60;
|
||||
uint32_t sec = elapsed % 60;
|
||||
|
||||
_label_timer->setText(fmt::format("{:02}:{:02}", min, sec));
|
||||
}
|
||||
|
||||
void update()
|
||||
{
|
||||
if (GetHAL().millis() - _time_count > 1000) {
|
||||
update_timer_label();
|
||||
_time_count = GetHAL().millis();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<Label> _label_caller;
|
||||
std::unique_ptr<Label> _label_timer;
|
||||
std::unique_ptr<Button> _button_end;
|
||||
|
||||
uint32_t _time_count = 0;
|
||||
uint32_t _connect_time_count = 0;
|
||||
};
|
||||
|
||||
WsCallView::WsCallView(lv_obj_t* parent, std::string caller)
|
||||
{
|
||||
auto panel_incoming = std::make_unique<IncomingPanel>(parent, caller);
|
||||
panel_incoming->onAccept = [&]() { handle_accept(); };
|
||||
panel_incoming->onDecline = [&]() { handle_decline(); };
|
||||
|
||||
auto panel_connecting = std::make_unique<ConnectingPanel>(parent, caller);
|
||||
panel_connecting->onEnd = [&]() { handle_end(); };
|
||||
panel_connecting->setHidden(true);
|
||||
|
||||
_panel_incoming = std::move(panel_incoming);
|
||||
_panel_connecting = std::move(panel_connecting);
|
||||
|
||||
_state = State::Incoming;
|
||||
}
|
||||
|
||||
void WsCallView::_update()
|
||||
{
|
||||
switch (_state) {
|
||||
case State::Incoming: {
|
||||
auto icoming_panel = static_cast<IncomingPanel*>(_panel_incoming.get());
|
||||
icoming_panel->update();
|
||||
break;
|
||||
}
|
||||
case State::Connecting: {
|
||||
auto connecting_panel = static_cast<ConnectingPanel*>(_panel_connecting.get());
|
||||
if (_panel_incoming) {
|
||||
_panel_incoming.reset();
|
||||
connecting_panel->setHidden(false);
|
||||
connecting_panel->reset();
|
||||
}
|
||||
connecting_panel->update();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void WsCallView::handle_accept()
|
||||
{
|
||||
_state = State::Connecting;
|
||||
if (onAccept) {
|
||||
onAccept();
|
||||
}
|
||||
}
|
||||
|
||||
void WsCallView::handle_decline()
|
||||
{
|
||||
if (onDecline) {
|
||||
onDecline();
|
||||
}
|
||||
if (onDestory) {
|
||||
onDestory();
|
||||
}
|
||||
requestDestroy();
|
||||
}
|
||||
|
||||
void WsCallView::handle_end()
|
||||
{
|
||||
if (onEnd) {
|
||||
onEnd();
|
||||
}
|
||||
if (onDestory) {
|
||||
onDestory();
|
||||
}
|
||||
requestDestroy();
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#pragma once
|
||||
#include <lvgl.h>
|
||||
#include <smooth_lvgl.hpp>
|
||||
#include <uitk/short_namespace.hpp>
|
||||
#include <stackchan/stackchan.h>
|
||||
#include <memory>
|
||||
|
||||
namespace view {
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
*/
|
||||
class WsCallView : public stackchan::avatar::Decorator {
|
||||
public:
|
||||
std::function<void(void)> onAccept;
|
||||
std::function<void(void)> onDecline;
|
||||
std::function<void(void)> onEnd;
|
||||
std::function<void(void)> onDestory;
|
||||
|
||||
enum class State {
|
||||
Incoming = 0,
|
||||
Connecting,
|
||||
};
|
||||
|
||||
WsCallView(lv_obj_t* parent, std::string caller);
|
||||
|
||||
private:
|
||||
State _state = State::Incoming;
|
||||
std::unique_ptr<uitk::lvgl_cpp::Container> _panel_incoming;
|
||||
std::unique_ptr<uitk::lvgl_cpp::Container> _panel_connecting;
|
||||
|
||||
void _update() override;
|
||||
|
||||
void handle_accept();
|
||||
void handle_decline();
|
||||
void handle_end();
|
||||
};
|
||||
|
||||
} // namespace view
|
||||
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#include "app_espnow_ctrl.h"
|
||||
#include "view/page_selector.h"
|
||||
#include <hal/hal.h>
|
||||
#include <mooncake.h>
|
||||
#include <mooncake_log.h>
|
||||
#include <assets/assets.h>
|
||||
#include <smooth_lvgl.hpp>
|
||||
#include <stackchan/stackchan.h>
|
||||
#include <cstdint>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
|
||||
using namespace mooncake;
|
||||
using namespace smooth_ui_toolkit::lvgl_cpp;
|
||||
using namespace stackchan;
|
||||
|
||||
AppEspnowControl::AppEspnowControl()
|
||||
{
|
||||
// 配置 App 名
|
||||
setAppInfo().name = "ESPNOW.REMOTE";
|
||||
// 配置 App 图标
|
||||
setAppInfo().icon = (void*)&icon_controller;
|
||||
// 配置 App 主题颜色
|
||||
static uint32_t theme_color = 0xCCCC33;
|
||||
setAppInfo().userData = (void*)&theme_color;
|
||||
}
|
||||
|
||||
void AppEspnowControl::onCreate()
|
||||
{
|
||||
mclog::tagInfo(getAppInfo().name, "on create");
|
||||
}
|
||||
|
||||
static std::mutex _mutex;
|
||||
static std::vector<uint8_t> _received_data;
|
||||
static int _receiver_id = 0;
|
||||
static bool _is_receiver = false;
|
||||
|
||||
void AppEspnowControl::onOpen()
|
||||
{
|
||||
mclog::tagInfo(getAppInfo().name, "on open");
|
||||
|
||||
// Get role
|
||||
std::vector<std::string> role_options = {"Receiver", "Sender"};
|
||||
int role_selection = view::create_page_selector_and_wait("Select Role", role_options);
|
||||
_is_receiver = (role_selection == 0);
|
||||
mclog::tagInfo(getAppInfo().name, "selected role: {}", _is_receiver ? "Receiver" : "Sender");
|
||||
|
||||
// Get channel
|
||||
std::vector<std::string> channel_options;
|
||||
for (int i = 0; i < 13; i++) {
|
||||
channel_options.push_back(std::to_string(i + 1));
|
||||
}
|
||||
auto wifi_channel = view::create_page_selector_and_wait("Select WiFi Channel", channel_options) + 1;
|
||||
mclog::tagInfo(getAppInfo().name, "selected wifi channel: {}", wifi_channel);
|
||||
|
||||
// Get id
|
||||
std::vector<std::string> id_options;
|
||||
for (int i = 0; i < 255; i++) {
|
||||
id_options.push_back(std::to_string(i));
|
||||
}
|
||||
_receiver_id = view::create_page_selector_and_wait("Select ID", id_options);
|
||||
mclog::tagInfo(getAppInfo().name, "selected id: {}", _receiver_id);
|
||||
|
||||
// Start espnow
|
||||
GetHAL().startEspNow(wifi_channel);
|
||||
GetHAL().onEspNowData.connect([](const std::vector<uint8_t>& data) {
|
||||
std::lock_guard<std::mutex> lock(_mutex);
|
||||
_received_data = data;
|
||||
});
|
||||
|
||||
// Normal avatar
|
||||
LvglLockGuard lock;
|
||||
|
||||
auto& stackchan = GetStackChan();
|
||||
|
||||
auto avatar = std::make_unique<avatar::DefaultAvatar>();
|
||||
avatar->init(lv_screen_active());
|
||||
stackchan.attachAvatar(std::move(avatar));
|
||||
|
||||
stackchan.addModifier(std::make_unique<BreathModifier>());
|
||||
stackchan.addModifier(std::make_unique<BlinkModifier>());
|
||||
|
||||
// Diable auto angle sync to prevent jitter
|
||||
stackchan.motion().setAutoAngleSyncEnabled(false);
|
||||
|
||||
GetHAL().setLaserEnabled(false);
|
||||
}
|
||||
|
||||
void handle_received_data()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_mutex);
|
||||
|
||||
// [target-id (uint8)] [yaw-angle (int16)] [pitch-angle (int16)] [speed (int16)] [laser-enabled (uint8)]
|
||||
// id: 0 for broadcast
|
||||
// yaw: -1280 ~ 1280
|
||||
// pitch: 0 ~ 900
|
||||
// speed: 0 ~ 1000, suggest 600
|
||||
// laser-enabled: 0 = off, 1 = on
|
||||
if (_received_data.size() >= 8) {
|
||||
uint8_t target_id = _received_data[0];
|
||||
if (target_id != 0 && target_id != _receiver_id) {
|
||||
mclog::info("not me, target id: {}", target_id);
|
||||
_received_data.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
int16_t yaw_angle = static_cast<int16_t>(_received_data[1] | (_received_data[2] << 8));
|
||||
int16_t pitch_angle = static_cast<int16_t>(_received_data[3] | (_received_data[4] << 8));
|
||||
int16_t speed = static_cast<int16_t>(_received_data[5] | (_received_data[6] << 8));
|
||||
bool laser_enabled = (_received_data[7] != 0);
|
||||
|
||||
mclog::info("yaw: {}, pitch: {}, speed: {}, laser: {}", yaw_angle, pitch_angle, speed, laser_enabled);
|
||||
|
||||
auto& motion = GetStackChan().motion();
|
||||
motion.moveWithSpeed(yaw_angle, pitch_angle, speed);
|
||||
|
||||
GetHAL().setLaserEnabled(laser_enabled);
|
||||
}
|
||||
|
||||
_received_data.clear();
|
||||
}
|
||||
|
||||
void handle_send_pose()
|
||||
{
|
||||
static uint32_t last_send_tick = 0;
|
||||
|
||||
if (GetHAL().millis() - last_send_tick < 50) {
|
||||
return;
|
||||
}
|
||||
last_send_tick = GetHAL().millis();
|
||||
|
||||
// [target-id (uint8)] [yaw-angle (int16)] [pitch-angle (int16)] [speed (int16)] [laser-enabled (uint8)]
|
||||
// id: 0 for broadcast
|
||||
// yaw: -1280 ~ 1280
|
||||
// pitch: 0 ~ 900
|
||||
// speed: 0 ~ 1000, suggest 600
|
||||
// laser-enabled: 0 = off, 1 = on
|
||||
auto& motion = GetStackChan().motion();
|
||||
int16_t yaw_angle = motion.getCurrentYawAngle();
|
||||
int16_t pitch_angle = motion.getCurrentPitchAngle();
|
||||
const int16_t speed = 800;
|
||||
|
||||
std::vector<uint8_t> data;
|
||||
data.reserve(8); // 预留空间提高效率
|
||||
|
||||
// [0] target-id
|
||||
data.push_back(_receiver_id);
|
||||
|
||||
// [1-2] yaw-angle (小端序:先发低位,再发高位)
|
||||
data.push_back(static_cast<uint8_t>(yaw_angle & 0xFF));
|
||||
data.push_back(static_cast<uint8_t>((yaw_angle >> 8) & 0xFF));
|
||||
// [3-4] pitch-angle
|
||||
data.push_back(static_cast<uint8_t>(pitch_angle & 0xFF));
|
||||
data.push_back(static_cast<uint8_t>((pitch_angle >> 8) & 0xFF));
|
||||
// [5-6] speed
|
||||
data.push_back(static_cast<uint8_t>(speed & 0xFF));
|
||||
data.push_back(static_cast<uint8_t>((speed >> 8) & 0xFF));
|
||||
|
||||
// [7] laser-enabled
|
||||
data.push_back(0); // always off for sender
|
||||
|
||||
GetHAL().espNowSend(data);
|
||||
}
|
||||
|
||||
void AppEspnowControl::onRunning()
|
||||
{
|
||||
LvglLockGuard lock;
|
||||
|
||||
if (_is_receiver) {
|
||||
handle_received_data();
|
||||
} else {
|
||||
handle_send_pose();
|
||||
}
|
||||
|
||||
GetStackChan().update();
|
||||
}
|
||||
|
||||
void AppEspnowControl::onClose()
|
||||
{
|
||||
mclog::tagInfo(getAppInfo().name, "on close");
|
||||
|
||||
LvglLockGuard lock;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#pragma once
|
||||
#include <mooncake.h>
|
||||
|
||||
/**
|
||||
* @brief 派生 App
|
||||
*
|
||||
*/
|
||||
class AppEspnowControl : public mooncake::AppAbility {
|
||||
public:
|
||||
AppEspnowControl();
|
||||
|
||||
// 重写生命周期回调
|
||||
void onCreate() override;
|
||||
void onOpen() override;
|
||||
void onRunning() override;
|
||||
void onClose() override;
|
||||
};
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#pragma once
|
||||
#include <memory>
|
||||
#include <smooth_lvgl.hpp>
|
||||
#include <uitk/short_namespace.hpp>
|
||||
#include <hal/hal.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
namespace view {
|
||||
|
||||
class PageSelector {
|
||||
public:
|
||||
PageSelector(std::string_view label, const std::vector<std::string> options)
|
||||
{
|
||||
_panel = std::make_unique<uitk::lvgl_cpp::Container>(lv_screen_active());
|
||||
_panel->setPadding(0, 0, 0, 0);
|
||||
_panel->setSize(320, 240);
|
||||
|
||||
_label = std::make_unique<uitk::lvgl_cpp::Label>(_panel->get());
|
||||
_label->setText(label);
|
||||
_label->setTextFont(&lv_font_montserrat_24);
|
||||
_label->align(LV_ALIGN_CENTER, 0, -80);
|
||||
|
||||
_roller = std::make_unique<uitk::lvgl_cpp::Roller>(_panel->get());
|
||||
_roller->setSize(200, 150);
|
||||
_roller->setOptions(options);
|
||||
_roller->align(LV_ALIGN_CENTER, -45, 35);
|
||||
_roller->onValueChanged().connect([&](uint32_t index) { _selected_index = index; });
|
||||
_roller->setTextFont(&lv_font_montserrat_24);
|
||||
|
||||
_btn_confirm = std::make_unique<uitk::lvgl_cpp::Button>(_panel->get());
|
||||
_btn_confirm->label().setText("ok");
|
||||
_btn_confirm->setSize(70, 110);
|
||||
_btn_confirm->align(LV_ALIGN_CENTER, 110, 40);
|
||||
_btn_confirm->onClick().connect([&]() { _is_selected = true; });
|
||||
}
|
||||
|
||||
bool update()
|
||||
{
|
||||
return _is_selected;
|
||||
}
|
||||
|
||||
int getSelectedIndex() const
|
||||
{
|
||||
return _selected_index;
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<uitk::lvgl_cpp::Container> _panel;
|
||||
std::unique_ptr<uitk::lvgl_cpp::Roller> _roller;
|
||||
std::unique_ptr<uitk::lvgl_cpp::Button> _btn_confirm;
|
||||
std::unique_ptr<uitk::lvgl_cpp::Label> _label;
|
||||
bool _is_selected = false;
|
||||
int _selected_index = 0;
|
||||
};
|
||||
|
||||
static inline int create_page_selector_and_wait(std::string_view label, const std::vector<std::string> options)
|
||||
{
|
||||
GetHAL().lvglLock();
|
||||
auto page_selector = std::make_unique<view::PageSelector>(label, options);
|
||||
GetHAL().lvglUnlock();
|
||||
|
||||
int index = 0;
|
||||
while (1) {
|
||||
GetHAL().delay(50);
|
||||
|
||||
LvglLockGuard lock;
|
||||
if (page_selector->update()) {
|
||||
index = page_selector->getSelectedIndex();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
LvglLockGuard lock;
|
||||
page_selector.reset();
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
} // namespace view
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#include "app_launcher.h"
|
||||
#include <hal/hal.h>
|
||||
#include <mooncake.h>
|
||||
#include <mooncake_log.h>
|
||||
#include <stackchan/stackchan.h>
|
||||
#include <cstdint>
|
||||
|
||||
using namespace mooncake;
|
||||
|
||||
void AppLauncher::onLauncherCreate()
|
||||
{
|
||||
mclog::tagInfo(getAppInfo().name, "on create");
|
||||
|
||||
// 打开自己
|
||||
open();
|
||||
}
|
||||
|
||||
void AppLauncher::onLauncherOpen()
|
||||
{
|
||||
mclog::tagInfo(getAppInfo().name, "on open");
|
||||
|
||||
LvglLockGuard lock;
|
||||
|
||||
_view = std::make_unique<view::LauncherView>();
|
||||
_view->init(getAppProps());
|
||||
_view->onAppClicked = [&](int appID) {
|
||||
mclog::tagInfo(getAppInfo().name, "handle open app, app id: {}", appID);
|
||||
openApp(appID);
|
||||
};
|
||||
}
|
||||
|
||||
void AppLauncher::onLauncherRunning()
|
||||
{
|
||||
LvglLockGuard lock;
|
||||
|
||||
_view->update();
|
||||
|
||||
screensaver_update();
|
||||
|
||||
GetStackChan().update();
|
||||
}
|
||||
|
||||
void AppLauncher::onLauncherClose()
|
||||
{
|
||||
mclog::tagInfo(getAppInfo().name, "on close");
|
||||
|
||||
LvglLockGuard lock;
|
||||
|
||||
_view.reset();
|
||||
}
|
||||
|
||||
void AppLauncher::onLauncherDestroy()
|
||||
{
|
||||
mclog::tagInfo(getAppInfo().name, "on close");
|
||||
}
|
||||
|
||||
void AppLauncher::screensaver_update()
|
||||
{
|
||||
const uint32_t SCREENSAVER_TIMEOUT_MS = 30000;
|
||||
|
||||
uint32_t idle_time = lv_display_get_inactive_time(NULL);
|
||||
if (idle_time >= SCREENSAVER_TIMEOUT_MS) {
|
||||
if (!_screensaver) {
|
||||
_screensaver = std::make_unique<view::Screensaver>();
|
||||
_screensaver->init();
|
||||
}
|
||||
} else if (_screensaver) {
|
||||
_screensaver.reset();
|
||||
}
|
||||
|
||||
// Update in 30ms interval
|
||||
if (_screensaver && GetHAL().millis() - _screensaver_timecount > 30) {
|
||||
_screensaver_timecount = GetHAL().millis();
|
||||
_screensaver->update();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#pragma once
|
||||
#include "view/view.h"
|
||||
#include <mooncake.h>
|
||||
#include <mooncake_templates.h>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
|
||||
class AppLauncher : public mooncake::templates::AppLauncherBase {
|
||||
public:
|
||||
void onLauncherCreate() override;
|
||||
void onLauncherOpen() override;
|
||||
void onLauncherRunning() override;
|
||||
void onLauncherClose() override;
|
||||
void onLauncherDestroy() override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<view::LauncherView> _view;
|
||||
std::unique_ptr<view::Screensaver> _screensaver;
|
||||
|
||||
uint32_t _screensaver_timecount = 0;
|
||||
void screensaver_update();
|
||||
};
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#include "view.h"
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
|
||||
using namespace view;
|
||||
using namespace uitk;
|
||||
using namespace uitk::lvgl_cpp;
|
||||
using namespace uitk::games;
|
||||
using namespace uitk::games::dvd_screensaver;
|
||||
|
||||
static const Vector2 _screen_size = {320, 240};
|
||||
static const Vector2 _logo_size = {64, 48};
|
||||
static const int _logo_id = 666;
|
||||
static const std::vector<uint32_t> _logo_colors = {
|
||||
0xffffff, 0xfffa01, 0xff8300, 0x00feff, 0xff2600, 0xbe00ff, 0x0026ff, 0xff008b,
|
||||
};
|
||||
static const uint32_t _bg_color = 0x000000;
|
||||
|
||||
Screensaver::~Screensaver()
|
||||
{
|
||||
_prev_screen->load();
|
||||
}
|
||||
|
||||
void Screensaver::onInit()
|
||||
{
|
||||
_prev_screen = std::make_unique<ScreenActive>();
|
||||
|
||||
_screen = std::make_unique<Screen>();
|
||||
_screen->setBgColor(lv_color_hex(_bg_color));
|
||||
_screen->removeFlag(LV_OBJ_FLAG_SCROLLABLE);
|
||||
_screen->setPadding(0, 0, 0, 0);
|
||||
_screen->load();
|
||||
|
||||
_logo = std::make_unique<Container>(_screen->get());
|
||||
_logo->setSize(_logo_size.width, _logo_size.height);
|
||||
_logo->setBgColor(lv_color_hex(_logo_colors[0]));
|
||||
_logo->align(LV_ALIGN_TOP_LEFT, 2333, 2333);
|
||||
_logo->removeFlag(LV_OBJ_FLAG_SCROLLABLE);
|
||||
_logo->setPadding(0, 0, 0, 0);
|
||||
_logo->setBorderWidth(0);
|
||||
_logo->setRadius(0);
|
||||
|
||||
_left_eye = std::make_unique<Container>(_logo->get());
|
||||
_left_eye->align(LV_ALIGN_CENTER, -15, -3);
|
||||
_left_eye->setBgColor(lv_color_hex(_bg_color));
|
||||
_left_eye->removeFlag(LV_OBJ_FLAG_SCROLLABLE);
|
||||
_left_eye->setRadius(LV_RADIUS_CIRCLE);
|
||||
_left_eye->setBorderWidth(0);
|
||||
_left_eye->setSize(6, 6);
|
||||
|
||||
_right_eye = std::make_unique<Container>(_logo->get());
|
||||
_right_eye->align(LV_ALIGN_CENTER, 15, -3);
|
||||
_right_eye->setBgColor(lv_color_hex(_bg_color));
|
||||
_right_eye->removeFlag(LV_OBJ_FLAG_SCROLLABLE);
|
||||
_right_eye->setRadius(LV_RADIUS_CIRCLE);
|
||||
_right_eye->setBorderWidth(0);
|
||||
_right_eye->setSize(6, 6);
|
||||
|
||||
_mouth = std::make_unique<Container>(_logo->get());
|
||||
_mouth->align(LV_ALIGN_CENTER, 0, 5);
|
||||
_mouth->setBgColor(lv_color_hex(_bg_color));
|
||||
_mouth->removeFlag(LV_OBJ_FLAG_SCROLLABLE);
|
||||
_mouth->setBorderWidth(0);
|
||||
_mouth->setSize(18, 2);
|
||||
_mouth->setRadius(0);
|
||||
}
|
||||
|
||||
void Screensaver::onBuildLevel()
|
||||
{
|
||||
addScreenFrameAsWall(_screen_size);
|
||||
|
||||
auto& random = Random::getInstance();
|
||||
Vector2 direction = {random.getFloat(0.3, 0.7), random.getFloat(0.3, 0.7)};
|
||||
direction = direction.normalized();
|
||||
|
||||
addLogo(_logo_id, {_screen_size.width / 2, _screen_size.height / 2}, _logo_size, direction, 110);
|
||||
}
|
||||
|
||||
void Screensaver::onRender(float dt)
|
||||
{
|
||||
getWorld().forEachObject([&](GameObject* obj) {
|
||||
if (obj->groupId == _logo_id) {
|
||||
auto p = obj->get<Transform>()->position;
|
||||
_logo->setPos((int)p.x - _logo_size.width / 2, (int)p.y - _logo_size.height / 2);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void Screensaver::onLogoCollide(int logoGroupId)
|
||||
{
|
||||
_color_index++;
|
||||
if (_color_index >= _logo_colors.size()) {
|
||||
_color_index = 0;
|
||||
}
|
||||
|
||||
_logo->setBgColor(lv_color_hex(_logo_colors[_color_index]));
|
||||
}
|
||||
@@ -0,0 +1,513 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#include "view.h"
|
||||
#include <mooncake_log.h>
|
||||
#include <assets/assets.h>
|
||||
#include <functional>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
using namespace view;
|
||||
using namespace uitk;
|
||||
using namespace uitk::lvgl_cpp;
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Dynamic backgroud color handle class */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
class DynamicBgColor {
|
||||
public:
|
||||
std::function<void(const uint32_t& bgColor)> onBgColorChanged;
|
||||
|
||||
void init(const std::vector<uint32_t>& stepColors, int stepGap)
|
||||
{
|
||||
_step_colors = stepColors;
|
||||
_step_gap = stepGap;
|
||||
|
||||
_bg_color.duration = 0.3;
|
||||
_bg_color.begin();
|
||||
|
||||
jumpTo(0);
|
||||
}
|
||||
|
||||
void jumpTo(int index)
|
||||
{
|
||||
if (index < 0 || index >= _step_colors.size()) {
|
||||
return;
|
||||
}
|
||||
_bg_color.teleport(_step_colors[index]);
|
||||
_current_index = index;
|
||||
|
||||
if (onBgColorChanged) {
|
||||
onBgColorChanged(_step_colors[index]);
|
||||
}
|
||||
}
|
||||
|
||||
void update(int scrollValue)
|
||||
{
|
||||
_last_index = _current_index;
|
||||
|
||||
// Update current index
|
||||
_current_index = (scrollValue + _step_gap / 2) / _step_gap;
|
||||
if (_current_index < 0) {
|
||||
_current_index = 0;
|
||||
}
|
||||
if (_current_index >= _step_colors.size()) {
|
||||
_current_index = _step_colors.size() - 1;
|
||||
}
|
||||
|
||||
// If index changed
|
||||
if (_last_index != _current_index) {
|
||||
// mclog::tagInfo(_tag, "index changed from {} to {}", _last_index, _current_index);
|
||||
_bg_color = _step_colors[_current_index];
|
||||
}
|
||||
|
||||
// Update background color
|
||||
_bg_color.update();
|
||||
if (!_bg_color.done()) {
|
||||
if (onBgColorChanged) {
|
||||
onBgColorChanged(_bg_color.toHex());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<uint32_t> _step_colors;
|
||||
int _current_index = 0;
|
||||
int _last_index = 0;
|
||||
int _step_gap = 0;
|
||||
color::AnimateRgb_t _bg_color;
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Page indicator */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
class PageIndicator {
|
||||
public:
|
||||
const int dot_size = 8;
|
||||
const int dot_size_big = 14;
|
||||
const int dot_gap = 16;
|
||||
|
||||
void init(int pageNum, int pageGap, lv_obj_t* parent, int posX, int posY)
|
||||
{
|
||||
_page_num = pageNum;
|
||||
_page_gap = pageGap;
|
||||
|
||||
_panel = std::make_unique<Container>(parent);
|
||||
_panel->removeFlag(LV_OBJ_FLAG_SCROLLABLE);
|
||||
_panel->addFlag(LV_OBJ_FLAG_FLOATING);
|
||||
_panel->setAlign(LV_ALIGN_CENTER);
|
||||
_panel->setPadding(0, 0, 24, 24);
|
||||
_panel->setPos(posX, posY);
|
||||
_panel->setBorderWidth(0);
|
||||
_panel->setHeight(24);
|
||||
_panel->setWidth((pageNum * dot_size) + (pageNum - 1) * (dot_gap - dot_size) + 24 * 2);
|
||||
_panel->setBgOpa(0);
|
||||
|
||||
for (int i = 0; i < pageNum; i++) {
|
||||
_dots.push_back(std::make_unique<Container>(_panel->get()));
|
||||
_dots.back()->setAlign(LV_ALIGN_CENTER);
|
||||
_dots.back()->setPos(i * dot_gap - (pageNum - 1) * dot_gap / 2, 0);
|
||||
_dots.back()->setBgColor(lv_color_hex(0xFFFFFF));
|
||||
_dots.back()->removeFlag(LV_OBJ_FLAG_SCROLLABLE);
|
||||
_dots.back()->setRadius(LV_RADIUS_CIRCLE);
|
||||
_dots.back()->setSize(dot_size, dot_size);
|
||||
_dots.back()->setBorderWidth(0);
|
||||
}
|
||||
|
||||
jumpTo(0);
|
||||
}
|
||||
|
||||
void jumpTo(int index)
|
||||
{
|
||||
if (index < 0 || index >= _page_num) {
|
||||
return;
|
||||
}
|
||||
_current_index = index;
|
||||
_last_index = index;
|
||||
update_dots();
|
||||
}
|
||||
|
||||
void update(int scrollValue)
|
||||
{
|
||||
_last_index = _current_index;
|
||||
|
||||
_current_index = (scrollValue + _page_gap / 2) / _page_gap;
|
||||
if (_current_index < 0) {
|
||||
_current_index = 0;
|
||||
}
|
||||
if (_current_index >= _page_num) {
|
||||
_current_index = _page_num - 1;
|
||||
}
|
||||
|
||||
if (_last_index != _current_index) {
|
||||
update_dots();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
int _page_num = 0;
|
||||
int _page_gap = 0;
|
||||
|
||||
int _current_index = 0;
|
||||
int _last_index = 0;
|
||||
|
||||
std::unique_ptr<Container> _panel;
|
||||
std::vector<std::unique_ptr<Container>> _dots;
|
||||
|
||||
void update_dots()
|
||||
{
|
||||
for (int i = 0; i < _page_num; i++) {
|
||||
if (i == _current_index) {
|
||||
_dots[i]->setSize(dot_size_big, dot_size_big);
|
||||
_dots[i]->setOpa(255);
|
||||
} else {
|
||||
_dots[i]->setSize(dot_size, dot_size);
|
||||
_dots[i]->setOpa(128);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Dynamic icon label */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
class DynamicIconLabel {
|
||||
public:
|
||||
const int show_range = 50;
|
||||
const int hidden_pos_y = -150;
|
||||
const int visible_pos_y = -99;
|
||||
const int transition_zone = 30;
|
||||
|
||||
void init(const std::vector<std::string>& iconLabelTexts, int iconGap, lv_obj_t* parent)
|
||||
{
|
||||
_icon_label_texts = iconLabelTexts;
|
||||
_icon_gap = iconGap;
|
||||
|
||||
// Create floating label
|
||||
_label = std::make_unique<Label>(parent);
|
||||
_label->setTextColor(lv_color_hex(0x000000));
|
||||
_label->setTextFont(&MontserratSemiBold26);
|
||||
_label->setAlign(LV_ALIGN_CENTER);
|
||||
_label->addFlag(LV_OBJ_FLAG_FLOATING);
|
||||
_label->setOpa(233);
|
||||
|
||||
// Setup animation
|
||||
_pos_y_anim = std::make_unique<AnimateValue>();
|
||||
_pos_y_anim->springOptions().visualDuration = 0.3;
|
||||
_pos_y_anim->springOptions().bounce = 0.1;
|
||||
_pos_y_anim->begin();
|
||||
|
||||
jumpTo(0);
|
||||
}
|
||||
|
||||
void jumpTo(int index)
|
||||
{
|
||||
if (index < 0 || index >= _icon_label_texts.size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
_current_index = index;
|
||||
_last_index = index;
|
||||
_is_visible = true;
|
||||
|
||||
// Update label
|
||||
_label->setText(_icon_label_texts[index]);
|
||||
_label->setPos(0, visible_pos_y);
|
||||
_pos_y_anim->teleport(visible_pos_y);
|
||||
}
|
||||
|
||||
void update(int scrollValue)
|
||||
{
|
||||
_last_index = _current_index;
|
||||
|
||||
// Calculate current icon index and distance to icon center
|
||||
_current_index = (scrollValue + _icon_gap / 2) / _icon_gap;
|
||||
int icon_center_pos_x = _current_index * _icon_gap;
|
||||
int distance_to_icon = std::abs(scrollValue - icon_center_pos_x);
|
||||
|
||||
// Clamp index
|
||||
if (_current_index < 0) {
|
||||
_current_index = 0;
|
||||
}
|
||||
if (_current_index >= _icon_label_texts.size()) {
|
||||
_current_index = _icon_label_texts.size() - 1;
|
||||
}
|
||||
|
||||
// Check if label should be visible
|
||||
bool should_be_visible = (distance_to_icon <= show_range);
|
||||
|
||||
// If index changed, update label text
|
||||
if (_last_index != _current_index) {
|
||||
_label->setText(_icon_label_texts[_current_index]);
|
||||
}
|
||||
|
||||
// Handle visibility state change
|
||||
if (should_be_visible && !_is_visible) {
|
||||
// Show label
|
||||
_pos_y_anim->move(visible_pos_y);
|
||||
_is_visible = true;
|
||||
} else if (!should_be_visible && _is_visible) {
|
||||
// Hide label
|
||||
_pos_y_anim->move(hidden_pos_y);
|
||||
_is_visible = false;
|
||||
}
|
||||
|
||||
// Update animation and apply position
|
||||
_pos_y_anim->update();
|
||||
_label->setY(_pos_y_anim->directValue());
|
||||
|
||||
// Update opacity based on distance when in transition zone
|
||||
if (should_be_visible && distance_to_icon > (show_range - transition_zone)) {
|
||||
// Fade out as approaching edge
|
||||
float fade_ratio = 1.0f - (float)(distance_to_icon - (show_range - transition_zone)) / transition_zone;
|
||||
_label->setOpa(233 * fade_ratio);
|
||||
} else if (should_be_visible) {
|
||||
_label->setOpa(233);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<std::string> _icon_label_texts;
|
||||
int _icon_gap = 0;
|
||||
int _current_index = 0;
|
||||
int _last_index = 0;
|
||||
bool _is_visible = false;
|
||||
|
||||
std::unique_ptr<Label> _label;
|
||||
std::unique_ptr<AnimateValue> _pos_y_anim;
|
||||
};
|
||||
|
||||
static std::string _tag = "LauncherView";
|
||||
static constexpr int _icon_gap = 320;
|
||||
|
||||
static int _last_clicked_icon_pos_x = -1;
|
||||
static std::unique_ptr<DynamicBgColor> _dynamic_bg_color;
|
||||
static std::unique_ptr<PageIndicator> _page_indicator;
|
||||
static std::unique_ptr<DynamicIconLabel> _dynamic_icon_label;
|
||||
|
||||
LauncherView::~LauncherView()
|
||||
{
|
||||
_icon_images.clear();
|
||||
_icon_panels.clear();
|
||||
_lr_indicators_images.clear();
|
||||
_lr_indicator_panels.clear();
|
||||
_panel.reset();
|
||||
_dynamic_bg_color.reset();
|
||||
_page_indicator.reset();
|
||||
_dynamic_icon_label.reset();
|
||||
}
|
||||
|
||||
void LauncherView::init(std::vector<mooncake::AppProps_t> appPorps)
|
||||
{
|
||||
mclog::tagInfo(_tag, "init");
|
||||
|
||||
/* ------------------------------ Screen setup ------------------------------ */
|
||||
ScreenActive screen;
|
||||
screen.removeFlag(LV_OBJ_FLAG_SCROLLABLE);
|
||||
|
||||
/* ---------------------------------- Panel --------------------------------- */
|
||||
_panel = std::make_unique<Container>(lv_screen_active());
|
||||
_panel->setAlign(LV_ALIGN_CENTER);
|
||||
_panel->setSize(320, 240);
|
||||
_panel->setRadius(0);
|
||||
_panel->setBorderWidth(0);
|
||||
_panel->setScrollbarMode(LV_SCROLLBAR_MODE_OFF);
|
||||
_panel->setBgColor(lv_color_hex(0x33CC99));
|
||||
_panel->addFlag(LV_OBJ_FLAG_SCROLL_ONE);
|
||||
lv_obj_set_scroll_snap_x(_panel->get(), LV_SCROLL_SNAP_CENTER);
|
||||
|
||||
/* ---------------------------------- Icons --------------------------------- */
|
||||
int icon_x = 0;
|
||||
int icon_y = 0;
|
||||
std::vector<std::string> icon_label_texts;
|
||||
for (const auto& props : appPorps) {
|
||||
// mclog::tagInfo(_tag, "name: {}, id: {}", props.info.name, props.appID);
|
||||
|
||||
// Icon panel
|
||||
_icon_panels.push_back(std::make_unique<Container>(_panel->get()));
|
||||
_icon_panels.back()->setAlign(LV_ALIGN_CENTER);
|
||||
_icon_panels.back()->setSize(190, 160);
|
||||
_icon_panels.back()->setPos(icon_x, icon_y);
|
||||
_icon_panels.back()->setBorderWidth(0);
|
||||
_icon_panels.back()->removeFlag(LV_OBJ_FLAG_SCROLLABLE);
|
||||
_icon_panels.back()->setBgOpa(0);
|
||||
|
||||
// Icon click callback
|
||||
auto app_id = props.appID;
|
||||
auto pos_x = icon_x;
|
||||
_icon_panels.back()->onClick().connect([&, app_id, pos_x]() {
|
||||
_clicked_app_id = app_id;
|
||||
_last_clicked_icon_pos_x = pos_x;
|
||||
});
|
||||
|
||||
// Collect icon label texts
|
||||
icon_label_texts.push_back(props.info.name);
|
||||
|
||||
// Icon image
|
||||
if (props.info.icon != nullptr) {
|
||||
_icon_images.push_back(std::make_unique<Image>(_icon_panels.back()->get()));
|
||||
_icon_images.back()->setSrc(props.info.icon);
|
||||
_icon_images.back()->setAlign(LV_ALIGN_CENTER);
|
||||
}
|
||||
|
||||
icon_x += _icon_gap;
|
||||
}
|
||||
|
||||
/* ------------------------------ LR indicators ----------------------------- */
|
||||
// Scroll to nearby icon handler with wrap-around
|
||||
int total_icons = appPorps.size();
|
||||
auto scroll_to_nearby_icon = [&, total_icons](int direction) {
|
||||
auto current_scroll_x = _panel->getScrollX();
|
||||
int current_index = (current_scroll_x + _icon_gap / 2) / _icon_gap;
|
||||
int target_index = current_index + direction;
|
||||
|
||||
// Wrap around at boundaries
|
||||
if (target_index < 0) {
|
||||
target_index = total_icons - 1;
|
||||
} else if (target_index >= total_icons) {
|
||||
target_index = 0;
|
||||
}
|
||||
|
||||
int target_x = target_index * _icon_gap;
|
||||
int scroll_distance = target_x - current_scroll_x;
|
||||
_panel->scrollBy(-scroll_distance, 0, LV_ANIM_ON);
|
||||
};
|
||||
|
||||
// Go left indicator
|
||||
_lr_indicator_panels.push_back(std::make_unique<Container>(_panel->get()));
|
||||
_lr_indicator_panels.back()->setAlign(LV_ALIGN_CENTER);
|
||||
_lr_indicator_panels.back()->setSize(52, 160);
|
||||
_lr_indicator_panels.back()->setPos(-134, 0);
|
||||
_lr_indicator_panels.back()->setBorderWidth(0);
|
||||
_lr_indicator_panels.back()->addFlag(LV_OBJ_FLAG_FLOATING);
|
||||
_lr_indicator_panels.back()->removeFlag(LV_OBJ_FLAG_SCROLLABLE);
|
||||
_lr_indicator_panels.back()->setBgOpa(0);
|
||||
_lr_indicator_panels.back()->onClick().connect([scroll_to_nearby_icon]() { scroll_to_nearby_icon(-1); });
|
||||
|
||||
_lr_indicators_images.push_back(std::make_unique<Image>(_lr_indicator_panels.back()->get()));
|
||||
_lr_indicators_images.back()->setSrc(&icon_indicator_left);
|
||||
_lr_indicators_images.back()->align(LV_ALIGN_CENTER, 0, 0);
|
||||
|
||||
// Go right indicator
|
||||
_lr_indicator_panels.push_back(std::make_unique<Container>(_panel->get()));
|
||||
_lr_indicator_panels.back()->setAlign(LV_ALIGN_CENTER);
|
||||
_lr_indicator_panels.back()->setSize(52, 160);
|
||||
_lr_indicator_panels.back()->setPos(134, 0);
|
||||
_lr_indicator_panels.back()->setBorderWidth(0);
|
||||
_lr_indicator_panels.back()->addFlag(LV_OBJ_FLAG_FLOATING);
|
||||
_lr_indicator_panels.back()->removeFlag(LV_OBJ_FLAG_SCROLLABLE);
|
||||
_lr_indicator_panels.back()->setBgOpa(0);
|
||||
_lr_indicator_panels.back()->onClick().connect([scroll_to_nearby_icon]() { scroll_to_nearby_icon(1); });
|
||||
|
||||
_lr_indicators_images.push_back(std::make_unique<Image>(_lr_indicator_panels.back()->get()));
|
||||
_lr_indicators_images.back()->setSrc(&icon_indicator_right);
|
||||
_lr_indicators_images.back()->align(LV_ALIGN_CENTER, 0, 0);
|
||||
|
||||
/* ---------------------------- Dynamic bg color ---------------------------- */
|
||||
_dynamic_bg_color = std::make_unique<DynamicBgColor>();
|
||||
|
||||
std::vector<uint32_t> step_colors;
|
||||
step_colors.resize(appPorps.size());
|
||||
for (size_t i = 0; i < appPorps.size(); i++) {
|
||||
uint32_t color = 0xDADADA;
|
||||
if (appPorps[i].info.userData != nullptr) {
|
||||
color = *(uint32_t*)appPorps[i].info.userData;
|
||||
}
|
||||
step_colors[i] = color;
|
||||
}
|
||||
|
||||
_dynamic_bg_color->onBgColorChanged = [&](const uint32_t& bgColor) {
|
||||
// mclog::tagInfo(_tag, "bg color changed to {:06X}", bgColor);
|
||||
_panel->setBgColor(lv_color_hex(bgColor));
|
||||
};
|
||||
|
||||
_dynamic_bg_color->init(step_colors, _icon_gap);
|
||||
|
||||
/* ------------------------------ Page indicator ---------------------------- */
|
||||
_page_indicator = std::make_unique<PageIndicator>();
|
||||
_page_indicator->init(appPorps.size(), _icon_gap, _panel->get(), 0, 103);
|
||||
|
||||
/* --------------------------- Dynamic icon label --------------------------- */
|
||||
_dynamic_icon_label = std::make_unique<DynamicIconLabel>();
|
||||
_dynamic_icon_label->init(icon_label_texts, _icon_gap, _panel->get());
|
||||
|
||||
/* ----------------------------- History restore ---------------------------- */
|
||||
if (_last_clicked_icon_pos_x != -1) {
|
||||
// mclog::tagInfo(_tag, "navigate to last clicked icon, pos x: {}", _last_clicked_icon_pos_x);
|
||||
_panel->scrollBy(-_last_clicked_icon_pos_x, 0, LV_ANIM_OFF);
|
||||
|
||||
_dynamic_bg_color->jumpTo(_last_clicked_icon_pos_x / _icon_gap);
|
||||
_page_indicator->jumpTo(_last_clicked_icon_pos_x / _icon_gap);
|
||||
_dynamic_icon_label->jumpTo(_last_clicked_icon_pos_x / _icon_gap);
|
||||
|
||||
_last_clicked_icon_pos_x = -1;
|
||||
_state = STATE_NORMAL;
|
||||
}
|
||||
|
||||
// If first create
|
||||
else {
|
||||
// Setup startup animation
|
||||
// x for pos_y, y for radius
|
||||
_startup_anim = std::make_unique<AnimateVector2>();
|
||||
|
||||
_startup_anim->x.springOptions().damping = 12.0;
|
||||
_startup_anim->y.delay = 0.15;
|
||||
_startup_anim->y.springOptions().visualDuration = 0.4;
|
||||
_startup_anim->y.springOptions().bounce = 0.05;
|
||||
|
||||
_startup_anim->teleport(240, 120);
|
||||
_panel->setY(_startup_anim->directValue().x);
|
||||
_panel->setRadius(_startup_anim->directValue().y);
|
||||
|
||||
_startup_anim->move(0, 0);
|
||||
|
||||
_state = STATE_STARTUP;
|
||||
}
|
||||
}
|
||||
|
||||
void LauncherView::update()
|
||||
{
|
||||
switch (_state) {
|
||||
case STATE_STARTUP:
|
||||
handle_state_startup();
|
||||
break;
|
||||
case STATE_NORMAL:
|
||||
handle_state_normal();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void LauncherView::handle_state_startup()
|
||||
{
|
||||
_startup_anim->update();
|
||||
|
||||
_panel->setY(_startup_anim->directValue().x);
|
||||
_panel->setRadius(_startup_anim->directValue().y);
|
||||
|
||||
if (_startup_anim->done()) {
|
||||
_startup_anim.reset();
|
||||
_state = STATE_NORMAL;
|
||||
}
|
||||
}
|
||||
|
||||
void LauncherView::handle_state_normal()
|
||||
{
|
||||
if (_clicked_app_id != -1) {
|
||||
if (onAppClicked) {
|
||||
onAppClicked(_clicked_app_id);
|
||||
}
|
||||
_clicked_app_id = -1;
|
||||
}
|
||||
|
||||
int scroll_x = _panel->getScrollX();
|
||||
// mclog::tagInfo(_tag, "scroll x: {}", scroll_x);
|
||||
|
||||
_dynamic_bg_color->update(scroll_x);
|
||||
_page_indicator->update(scroll_x);
|
||||
_dynamic_icon_label->update(scroll_x);
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#pragma once
|
||||
#include <mooncake.h>
|
||||
#include <smooth_ui_toolkit.hpp>
|
||||
#include <uitk/short_namespace.hpp>
|
||||
#include <games/dvd_screensaver/dvd_screensaver.hpp>
|
||||
#include <smooth_lvgl.hpp>
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
namespace view {
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
*/
|
||||
class LauncherView {
|
||||
public:
|
||||
~LauncherView();
|
||||
|
||||
enum State_t {
|
||||
STATE_STARTUP,
|
||||
STATE_NORMAL,
|
||||
};
|
||||
|
||||
std::function<void(int appID)> onAppClicked;
|
||||
|
||||
void init(std::vector<mooncake::AppProps_t> appPorps);
|
||||
void update();
|
||||
|
||||
private:
|
||||
std::unique_ptr<uitk::lvgl_cpp::Container> _panel;
|
||||
std::vector<std::unique_ptr<uitk::lvgl_cpp::Container>> _icon_panels;
|
||||
std::vector<std::unique_ptr<uitk::lvgl_cpp::Image>> _icon_images;
|
||||
std::vector<std::unique_ptr<uitk::lvgl_cpp::Container>> _lr_indicator_panels;
|
||||
std::vector<std::unique_ptr<uitk::lvgl_cpp::Image>> _lr_indicators_images;
|
||||
|
||||
std::unique_ptr<uitk::AnimateVector2> _startup_anim;
|
||||
|
||||
int _clicked_app_id = -1;
|
||||
State_t _state = STATE_STARTUP;
|
||||
|
||||
void handle_state_startup();
|
||||
void handle_state_normal();
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
*/
|
||||
class Screensaver : public uitk::games::dvd_screensaver::DvdScreensaver {
|
||||
public:
|
||||
~Screensaver();
|
||||
|
||||
void onInit() override;
|
||||
void onBuildLevel() override;
|
||||
void onRender(float dt) override;
|
||||
void onLogoCollide(int logoGroupId) override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<uitk::lvgl_cpp::ScreenActive> _prev_screen;
|
||||
std::unique_ptr<uitk::lvgl_cpp::Screen> _screen;
|
||||
std::unique_ptr<uitk::lvgl_cpp::Container> _logo;
|
||||
std::unique_ptr<uitk::lvgl_cpp::Container> _left_eye;
|
||||
std::unique_ptr<uitk::lvgl_cpp::Container> _right_eye;
|
||||
std::unique_ptr<uitk::lvgl_cpp::Container> _mouth;
|
||||
int _color_index = 0;
|
||||
};
|
||||
|
||||
} // namespace view
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#include "app_setup.h"
|
||||
#include <hal/hal.h>
|
||||
#include <mooncake.h>
|
||||
#include <mooncake_log.h>
|
||||
#include <assets/assets.h>
|
||||
#include <stackchan/stackchan.h>
|
||||
#include <apps/common/common.h>
|
||||
|
||||
using namespace mooncake;
|
||||
using namespace view;
|
||||
using namespace setup_workers;
|
||||
|
||||
AppSetup::AppSetup()
|
||||
{
|
||||
// 配置 App 名
|
||||
setAppInfo().name = "SETUP";
|
||||
// 配置 App 图标
|
||||
setAppInfo().icon = (void*)&icon_setup;
|
||||
// 配置 App 主题颜色
|
||||
static uint32_t theme_color = 0xB3B3B3;
|
||||
setAppInfo().userData = (void*)&theme_color;
|
||||
}
|
||||
|
||||
void AppSetup::onCreate()
|
||||
{
|
||||
mclog::tagInfo(getAppInfo().name, "on create");
|
||||
// open();
|
||||
}
|
||||
|
||||
void AppSetup::onOpen()
|
||||
{
|
||||
mclog::tagInfo(getAppInfo().name, "on open");
|
||||
|
||||
LvglLockGuard lock;
|
||||
|
||||
_menu_sections = {{
|
||||
"Connectivity",
|
||||
{
|
||||
// {"Set Up Wi-Fi",
|
||||
// [&]() {
|
||||
// _destroy_menu = true;
|
||||
// _worker = std::make_unique<WifiSetupWorker>();
|
||||
// }},
|
||||
{"App Bind Code",
|
||||
[&]() {
|
||||
_destroy_menu = true;
|
||||
_worker = std::make_unique<AppBindCodeWorker>();
|
||||
}}},
|
||||
},
|
||||
{
|
||||
"Servo",
|
||||
{{"Zero Calibration",
|
||||
[&]() {
|
||||
_destroy_menu = true;
|
||||
_worker = std::make_unique<ZeroCalibrationWorker>();
|
||||
}},
|
||||
{"LED Strips Test",
|
||||
[&]() {
|
||||
_destroy_menu = true;
|
||||
_worker = std::make_unique<RgbTestWorker>();
|
||||
}}},
|
||||
},
|
||||
{
|
||||
"About",
|
||||
{{fmt::format("FW Version: {}", common::FirmwareVersion), nullptr}},
|
||||
},
|
||||
{
|
||||
"End",
|
||||
{{"Quit", [&]() { close(); }}},
|
||||
}};
|
||||
|
||||
_menu_page = std::make_unique<view::SelectMenuPage>(_menu_sections);
|
||||
}
|
||||
|
||||
void AppSetup::onRunning()
|
||||
{
|
||||
LvglLockGuard lock;
|
||||
|
||||
if (_menu_page) {
|
||||
_menu_page->update();
|
||||
}
|
||||
|
||||
if (_destroy_menu) {
|
||||
_menu_page.reset();
|
||||
_destroy_menu = false;
|
||||
}
|
||||
|
||||
if (_worker) {
|
||||
_worker->update();
|
||||
if (_worker->isDone()) {
|
||||
_worker.reset();
|
||||
_menu_page = std::make_unique<view::SelectMenuPage>(_menu_sections);
|
||||
}
|
||||
}
|
||||
|
||||
GetStackChan().update();
|
||||
}
|
||||
|
||||
void AppSetup::onClose()
|
||||
{
|
||||
mclog::tagInfo(getAppInfo().name, "on close");
|
||||
|
||||
LvglLockGuard lock;
|
||||
|
||||
_menu_page.reset();
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#pragma once
|
||||
#include "view/view.h"
|
||||
#include "workers/workers.h"
|
||||
#include <mooncake.h>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
|
||||
/**
|
||||
* @brief 派生 App
|
||||
*
|
||||
*/
|
||||
class AppSetup : public mooncake::AppAbility {
|
||||
public:
|
||||
AppSetup();
|
||||
|
||||
// 重写生命周期回调
|
||||
void onCreate() override;
|
||||
void onOpen() override;
|
||||
void onRunning() override;
|
||||
void onClose() override;
|
||||
|
||||
private:
|
||||
std::vector<view::SelectMenuPage::MenuSection> _menu_sections;
|
||||
std::unique_ptr<view::SelectMenuPage> _menu_page;
|
||||
std::unique_ptr<setup_workers::WorkerBase> _worker;
|
||||
bool _destroy_menu = false;
|
||||
};
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#include "view.h"
|
||||
|
||||
using namespace view;
|
||||
using namespace uitk::lvgl_cpp;
|
||||
|
||||
SelectMenuPage::SelectMenuPage(std::vector<MenuSection> sections) : _sections(std::move(sections))
|
||||
{
|
||||
_pannel = std::make_unique<uitk::lvgl_cpp::Container>(lv_screen_active());
|
||||
_pannel->setSize(320, 240);
|
||||
_pannel->setBgColor(lv_color_hex(0xffffff));
|
||||
_pannel->setPadding(10, 24, 0, 0);
|
||||
_pannel->setBorderWidth(0);
|
||||
_pannel->setRadius(0);
|
||||
_pannel->setScrollDir(LV_DIR_VER);
|
||||
|
||||
int cursor_y = 10;
|
||||
|
||||
for (int i = 0; i < _sections.size(); ++i) {
|
||||
const auto& section = _sections[i];
|
||||
create_selection_label(20, cursor_y, section.title);
|
||||
cursor_y += 24 + 12;
|
||||
|
||||
for (int j = 0; j < section.items.size(); ++j) {
|
||||
const auto& item = section.items[j];
|
||||
create_item_button(cursor_y, item, i, j);
|
||||
cursor_y += 48 + 12;
|
||||
}
|
||||
cursor_y += 8;
|
||||
}
|
||||
cursor_y += 20;
|
||||
}
|
||||
|
||||
void SelectMenuPage::update()
|
||||
{
|
||||
if (_pending_section_index >= 0 && _pending_item_index >= 0) {
|
||||
if (_pending_section_index < _sections.size()) {
|
||||
auto& section = _sections[_pending_section_index];
|
||||
if (_pending_item_index < section.items.size()) {
|
||||
auto& item = section.items[_pending_item_index];
|
||||
if (item.onClick) {
|
||||
item.onClick();
|
||||
}
|
||||
}
|
||||
}
|
||||
_pending_section_index = -1;
|
||||
_pending_item_index = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void SelectMenuPage::create_selection_label(int x, int y, std::string_view text)
|
||||
{
|
||||
auto label = std::make_unique<uitk::lvgl_cpp::Label>(*_pannel);
|
||||
label->setText(text);
|
||||
label->setTextFont(&lv_font_montserrat_16);
|
||||
label->setTextColor(lv_color_hex(0x6A6882));
|
||||
label->setPos(x, y);
|
||||
_labels.push_back(std::move(label));
|
||||
}
|
||||
|
||||
void SelectMenuPage::create_item_button(int y, const MenuItem& item, int section_idx, int item_idx)
|
||||
{
|
||||
auto btn = std::make_unique<uitk::lvgl_cpp::Button>(*_pannel);
|
||||
btn->setSize(282, 48);
|
||||
btn->align(LV_ALIGN_TOP_MID, 0, y);
|
||||
btn->setBgColor(lv_color_hex(0xB8D3FD));
|
||||
btn->setBorderWidth(0);
|
||||
btn->setShadowWidth(0);
|
||||
btn->setRadius(12);
|
||||
|
||||
btn->label().setText(item.label);
|
||||
btn->label().setTextFont(&lv_font_montserrat_24);
|
||||
btn->label().setTextColor(lv_color_hex(0x26206A));
|
||||
btn->label().align(LV_ALIGN_CENTER, 0, 0);
|
||||
btn->label().setWidth(256);
|
||||
btn->label().setTextAlign(LV_TEXT_ALIGN_CENTER);
|
||||
btn->label().setLongMode(LV_LABEL_LONG_MODE_SCROLL_CIRCULAR);
|
||||
|
||||
if (item.onClick) {
|
||||
btn->onClick().connect([this, section_idx, item_idx]() {
|
||||
_pending_section_index = section_idx;
|
||||
_pending_item_index = item_idx;
|
||||
});
|
||||
}
|
||||
_buttons.push_back(std::move(btn));
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#pragma once
|
||||
#include <smooth_lvgl.hpp>
|
||||
#include <uitk/short_namespace.hpp>
|
||||
#include <string_view>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace view {
|
||||
|
||||
class SelectMenuPage {
|
||||
public:
|
||||
struct MenuItem {
|
||||
std::string label;
|
||||
std::function<void()> onClick;
|
||||
};
|
||||
|
||||
struct MenuSection {
|
||||
std::string title;
|
||||
std::vector<MenuItem> items;
|
||||
};
|
||||
|
||||
SelectMenuPage(std::vector<MenuSection> sections);
|
||||
|
||||
void update();
|
||||
|
||||
private:
|
||||
std::vector<MenuSection> _sections;
|
||||
std::unique_ptr<uitk::lvgl_cpp::Container> _pannel;
|
||||
std::vector<std::unique_ptr<uitk::lvgl_cpp::Label>> _labels;
|
||||
std::vector<std::unique_ptr<uitk::lvgl_cpp::Button>> _buttons;
|
||||
int _pending_section_index = -1;
|
||||
int _pending_item_index = -1;
|
||||
|
||||
void create_selection_label(int x, int y, std::string_view text);
|
||||
void create_item_button(int y, const MenuItem& item, int section_idx, int item_idx);
|
||||
};
|
||||
|
||||
} // namespace view
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#pragma once
|
||||
#include <smooth_lvgl.hpp>
|
||||
#include <uitk/short_namespace.hpp>
|
||||
|
||||
namespace setup_workers {
|
||||
|
||||
inline void apply_button_common_style(uitk::lvgl_cpp::Button& btn)
|
||||
{
|
||||
btn.setBgColor(lv_color_hex(0xB8D3FD));
|
||||
btn.setBorderWidth(0);
|
||||
btn.setShadowWidth(0);
|
||||
btn.setRadius(18);
|
||||
btn.label().setTextFont(&lv_font_montserrat_24);
|
||||
btn.label().setTextColor(lv_color_hex(0x26206A));
|
||||
}
|
||||
|
||||
} // namespace setup_workers
|
||||
@@ -0,0 +1,273 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#include "workers.h"
|
||||
#include <stackchan/stackchan.h>
|
||||
#include <ArduinoJson.hpp>
|
||||
#include <mooncake_log.h>
|
||||
#include <hal/hal.h>
|
||||
#include <memory>
|
||||
|
||||
using namespace smooth_ui_toolkit::lvgl_cpp;
|
||||
using namespace setup_workers;
|
||||
using namespace stackchan;
|
||||
|
||||
static std::string _tag = "Setup-Connectivity";
|
||||
|
||||
WifiSetupWorker::WifiSetupWorker()
|
||||
{
|
||||
_state = State::AppDownload;
|
||||
_last_state = State::None;
|
||||
_is_first_in = true;
|
||||
|
||||
// Create default avatar
|
||||
auto avatar = std::make_unique<avatar::DefaultAvatar>();
|
||||
avatar->init(lv_screen_active(), &lv_font_montserrat_24);
|
||||
GetStackChan().attachAvatar(std::move(avatar));
|
||||
|
||||
_app_config_signal_id =
|
||||
GetHAL().onAppConfigEvent.connect([this](AppConfigEvent event) { _last_app_config_event = event; });
|
||||
|
||||
GetHAL().startAppConfigServer();
|
||||
}
|
||||
|
||||
WifiSetupWorker::~WifiSetupWorker()
|
||||
{
|
||||
GetHAL().onAppConfigEvent.disconnect(_app_config_signal_id);
|
||||
GetStackChan().resetAvatar();
|
||||
}
|
||||
|
||||
void WifiSetupWorker::update()
|
||||
{
|
||||
cleanup_ui();
|
||||
update_state();
|
||||
}
|
||||
|
||||
void WifiSetupWorker::update_state()
|
||||
{
|
||||
switch (_state) {
|
||||
case State::AppDownload: {
|
||||
if (_is_first_in) {
|
||||
_is_first_in = false;
|
||||
|
||||
auto& avatar = GetStackChan().avatar();
|
||||
avatar.leftEye().setVisible(false);
|
||||
avatar.rightEye().setVisible(false);
|
||||
avatar.mouth().setVisible(false);
|
||||
avatar.setSpeech("Scan the QR code to download the \"StackChan\" app.");
|
||||
|
||||
auto& data = _state_app_download_data;
|
||||
|
||||
std::string qrcode_text = "todotodotodotodotodotodotodlotodotodotodoto";
|
||||
data.qrcode = std::make_unique<Qrcode>(lv_screen_active());
|
||||
data.qrcode->setSize(150);
|
||||
data.qrcode->setDarkColor(lv_color_white());
|
||||
data.qrcode->setLightColor(lv_color_black());
|
||||
data.qrcode->update(qrcode_text);
|
||||
data.qrcode->align(LV_ALIGN_CENTER, -60, -25);
|
||||
|
||||
data.btn = std::make_unique<Button>(lv_screen_active());
|
||||
apply_button_common_style(*data.btn);
|
||||
data.btn->align(LV_ALIGN_CENTER, 90, 0);
|
||||
data.btn->setSize(100, 60);
|
||||
data.btn->label().setText("Next");
|
||||
data.btn->onClick().connect([this]() { _state_app_download_data.is_clicked = true; });
|
||||
}
|
||||
|
||||
if (_state_app_download_data.is_clicked) {
|
||||
switch_state(State::WaitAppConnection);
|
||||
}
|
||||
|
||||
// Check events
|
||||
if (_last_app_config_event != AppConfigEvent::None) {
|
||||
if (_last_app_config_event == AppConfigEvent::AppConnected) {
|
||||
switch_state(State::AppConnected);
|
||||
}
|
||||
_last_app_config_event = AppConfigEvent::None;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case State::WaitAppConnection: {
|
||||
if (_is_first_in) {
|
||||
_is_first_in = false;
|
||||
|
||||
auto& avatar = GetStackChan().avatar();
|
||||
avatar.leftEye().setVisible(false);
|
||||
avatar.rightEye().setVisible(false);
|
||||
avatar.mouth().setVisible(false);
|
||||
avatar.setSpeech("Look for me in \"StackChan\" app to start the setup.");
|
||||
avatar.addDecorator(std::make_unique<avatar::HeartDecorator>(lv_screen_active(), 3000));
|
||||
|
||||
auto& data = _state_wait_app_connection_data;
|
||||
data.id_btn = std::make_unique<Button>(lv_screen_active());
|
||||
apply_button_common_style(*data.id_btn);
|
||||
data.id_btn->align(LV_ALIGN_CENTER, 0, 0);
|
||||
data.id_btn->setSize(262, 52);
|
||||
data.id_btn->onClick().connect([]() {
|
||||
auto& avatar = GetStackChan().avatar();
|
||||
avatar.clearDecorators();
|
||||
avatar.addDecorator(std::make_unique<avatar::HeartDecorator>(lv_screen_active(), 3000));
|
||||
});
|
||||
data.id_btn->label().setText(fmt::format("ID: {}", GetHAL().getFactoryMacString()));
|
||||
}
|
||||
|
||||
// Check events
|
||||
if (_last_app_config_event != AppConfigEvent::None) {
|
||||
if (_last_app_config_event == AppConfigEvent::AppConnected) {
|
||||
switch_state(State::AppConnected);
|
||||
}
|
||||
_last_app_config_event = AppConfigEvent::None;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case State::AppConnected: {
|
||||
if (_is_first_in) {
|
||||
_is_first_in = false;
|
||||
|
||||
auto& avatar = GetStackChan().avatar();
|
||||
avatar.leftEye().setVisible(true);
|
||||
avatar.rightEye().setVisible(true);
|
||||
avatar.mouth().setVisible(true);
|
||||
avatar.setSpeech("Ready to Configure ~");
|
||||
|
||||
GetStackChan().addModifier(std::make_unique<TimedEmotionModifier>(avatar::Emotion::Happy, 4000));
|
||||
GetStackChan().addModifier(std::make_unique<BreathModifier>());
|
||||
GetStackChan().addModifier(std::make_unique<BlinkModifier>());
|
||||
GetStackChan().addModifier(std::make_unique<SpeakingModifier>(2000, 180, false));
|
||||
}
|
||||
|
||||
// Check events
|
||||
if (_last_app_config_event != AppConfigEvent::None) {
|
||||
if (_last_app_config_event == AppConfigEvent::AppDisconnected) {
|
||||
switch_state(State::WaitAppConnection);
|
||||
} else if (_last_app_config_event == AppConfigEvent::TryWifiConnect) {
|
||||
auto& avatar = GetStackChan().avatar();
|
||||
avatar.setSpeech("Verifying...");
|
||||
GetStackChan().addModifier(std::make_unique<SpeakingModifier>(2000, 180, false));
|
||||
} else if (_last_app_config_event == AppConfigEvent::WifiConnectFailed) {
|
||||
GetStackChan().addModifier(std::make_unique<TimedEmotionModifier>(avatar::Emotion::Sad, 4000));
|
||||
GetStackChan().addModifier(
|
||||
std::make_unique<TimedSpeechModifier>("Connect Failed. Try again?", 6000));
|
||||
GetStackChan().addModifier(std::make_unique<SpeakingModifier>(3000, 180, false));
|
||||
} else if (_last_app_config_event == AppConfigEvent::WifiConnected) {
|
||||
switch_state(State::Done);
|
||||
}
|
||||
_last_app_config_event = AppConfigEvent::None;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case State::Done: {
|
||||
if (_is_first_in) {
|
||||
_is_first_in = false;
|
||||
|
||||
auto& avatar = GetStackChan().avatar();
|
||||
avatar.leftEye().setVisible(true);
|
||||
avatar.rightEye().setVisible(true);
|
||||
avatar.mouth().setVisible(true);
|
||||
avatar.setEmotion(avatar::Emotion::Happy);
|
||||
|
||||
GetStackChan().addModifier(std::make_unique<SpeakingModifier>(1500, 180, false));
|
||||
|
||||
_state_done_data.reboot_count = 4;
|
||||
}
|
||||
|
||||
if (GetHAL().millis() - _last_tick > 1000) {
|
||||
_last_tick = GetHAL().millis();
|
||||
if (_state_done_data.reboot_count > 0) {
|
||||
_state_done_data.reboot_count--;
|
||||
auto& avatar = GetStackChan().avatar();
|
||||
avatar.setSpeech(fmt::format("Done! Reboot in {}s.", _state_done_data.reboot_count));
|
||||
} else {
|
||||
mclog::tagInfo(_tag, "rebooting...");
|
||||
GetHAL().delay(100);
|
||||
GetHAL().reboot();
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void WifiSetupWorker::cleanup_ui()
|
||||
{
|
||||
if (_last_state == State::None) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (_last_state) {
|
||||
case State::AppDownload: {
|
||||
_state_app_download_data.reset();
|
||||
GetStackChan().avatar().setSpeech("");
|
||||
break;
|
||||
}
|
||||
case State::WaitAppConnection: {
|
||||
_state_wait_app_connection_data.reset();
|
||||
GetStackChan().avatar().setSpeech("");
|
||||
break;
|
||||
}
|
||||
case State::AppConnected: {
|
||||
GetStackChan().avatar().setSpeech("");
|
||||
GetStackChan().clearModifiers();
|
||||
break;
|
||||
}
|
||||
case State::Done: {
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
_last_state = State::None;
|
||||
}
|
||||
|
||||
void WifiSetupWorker::switch_state(State newState)
|
||||
{
|
||||
_last_state = _state;
|
||||
_state = newState;
|
||||
_is_first_in = true;
|
||||
}
|
||||
|
||||
AppBindCodeWorker::AppBindCodeWorker()
|
||||
{
|
||||
// Create default avatar
|
||||
auto avatar = std::make_unique<avatar::DefaultAvatar>();
|
||||
avatar->init(lv_screen_active(), &lv_font_montserrat_24);
|
||||
avatar->leftEye().setVisible(false);
|
||||
avatar->rightEye().setVisible(false);
|
||||
avatar->mouth().setVisible(false);
|
||||
avatar->setSpeech("Scan the QR code with the StackChan APP to bind.");
|
||||
GetStackChan().attachAvatar(std::move(avatar));
|
||||
|
||||
std::string qrcode_text;
|
||||
ArduinoJson::JsonDocument doc;
|
||||
doc["mac"] = GetHAL().getFactoryMacString();
|
||||
ArduinoJson::serializeJson(doc, qrcode_text);
|
||||
mclog::tagInfo(_tag, "qr code text: {}", qrcode_text);
|
||||
|
||||
_qrcode = std::make_unique<Qrcode>(lv_screen_active());
|
||||
_qrcode->setSize(150);
|
||||
_qrcode->setDarkColor(lv_color_white());
|
||||
_qrcode->setLightColor(lv_color_black());
|
||||
_qrcode->update(qrcode_text);
|
||||
_qrcode->align(LV_ALIGN_CENTER, -60, -25);
|
||||
|
||||
_btn_quit = std::make_unique<Button>(lv_screen_active());
|
||||
apply_button_common_style(*_btn_quit);
|
||||
_btn_quit->align(LV_ALIGN_CENTER, 90, 0);
|
||||
_btn_quit->setSize(100, 60);
|
||||
_btn_quit->label().setText("Back");
|
||||
_btn_quit->onClick().connect([this]() { _is_done = true; });
|
||||
}
|
||||
|
||||
AppBindCodeWorker::~AppBindCodeWorker()
|
||||
{
|
||||
GetStackChan().resetAvatar();
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#include "workers.h"
|
||||
#include <stackchan/stackchan.h>
|
||||
#include <mooncake_log.h>
|
||||
#include <hal/hal.h>
|
||||
|
||||
using namespace smooth_ui_toolkit::lvgl_cpp;
|
||||
using namespace setup_workers;
|
||||
|
||||
static std::string _tag = "Setup-Servo";
|
||||
|
||||
ZeroCalibrationWorker::ZeroCalibrationWorker()
|
||||
{
|
||||
_pannel = std::make_unique<Container>(lv_screen_active());
|
||||
_pannel->setBgColor(lv_color_hex(0xFFFFFF));
|
||||
_pannel->removeFlag(LV_OBJ_FLAG_SCROLLABLE);
|
||||
_pannel->align(LV_ALIGN_CENTER, 0, 0);
|
||||
_pannel->setBorderWidth(0);
|
||||
_pannel->setSize(320, 240);
|
||||
_pannel->setRadius(0);
|
||||
|
||||
_btn_go_home = std::make_unique<Button>(lv_screen_active());
|
||||
apply_button_common_style(*_btn_go_home);
|
||||
_btn_go_home->setAlign(LV_ALIGN_CENTER);
|
||||
_btn_go_home->setPos(0, -85);
|
||||
_btn_go_home->setSize(230, 55);
|
||||
_btn_go_home->label().setText("Move To Home");
|
||||
_btn_go_home->onClick().connect([this]() { _go_home_flag = true; });
|
||||
|
||||
_btn_confirm = std::make_unique<Button>(lv_screen_active());
|
||||
apply_button_common_style(*_btn_confirm);
|
||||
_btn_confirm->setAlign(LV_ALIGN_CENTER);
|
||||
_btn_confirm->setPos(0, 0);
|
||||
_btn_confirm->setSize(290, 70);
|
||||
_btn_confirm->label().setText("Set Current Position\nAs Home");
|
||||
_btn_confirm->label().setTextAlign(LV_TEXT_ALIGN_CENTER);
|
||||
_btn_confirm->onClick().connect([this]() { _confirm_flag = true; });
|
||||
|
||||
_btn_quit = std::make_unique<Button>(lv_screen_active());
|
||||
apply_button_common_style(*_btn_quit);
|
||||
_btn_quit->setAlign(LV_ALIGN_CENTER);
|
||||
_btn_quit->setPos(0, 85);
|
||||
_btn_quit->setSize(230, 55);
|
||||
_btn_quit->label().setText("Done");
|
||||
_btn_quit->onClick().connect([this]() { _is_done = true; });
|
||||
|
||||
auto& motion = GetStackChan().motion();
|
||||
motion.setAutoAngleSyncEnabled(true);
|
||||
}
|
||||
|
||||
void ZeroCalibrationWorker::update()
|
||||
{
|
||||
if (_confirm_flag) {
|
||||
_confirm_flag = false;
|
||||
|
||||
mclog::tagInfo(_tag, "set current angle as zero");
|
||||
|
||||
auto& motion = GetStackChan().motion();
|
||||
motion.yawServo().setCurrentAngleAsZero();
|
||||
motion.pitchServo().setCurrentAngleAsZero();
|
||||
}
|
||||
|
||||
if (_go_home_flag) {
|
||||
_go_home_flag = false;
|
||||
|
||||
mclog::tagInfo(_tag, "go home");
|
||||
|
||||
auto& motion = GetStackChan().motion();
|
||||
motion.goHome(300);
|
||||
}
|
||||
}
|
||||
|
||||
struct RgbColorEntry {
|
||||
std::string name;
|
||||
uint8_t r;
|
||||
uint8_t g;
|
||||
uint8_t b;
|
||||
};
|
||||
|
||||
static const std::vector<RgbColorEntry> _rgb_colors = {
|
||||
{"Red", 255, 0, 0}, {"Green", 0, 255, 0}, {"Blue", 0, 0, 255}, {"Yellow", 255, 255, 0},
|
||||
{"Cyan", 0, 255, 255}, {"Magenta", 255, 0, 255}, {"White", 255, 255, 255}, {"Off", 0, 0, 0},
|
||||
};
|
||||
|
||||
RgbTestWorker::RgbTestWorker()
|
||||
{
|
||||
_pannel = std::make_unique<Container>(lv_screen_active());
|
||||
_pannel->setBgColor(lv_color_hex(0xFFFFFF));
|
||||
_pannel->align(LV_ALIGN_CENTER, 0, 0);
|
||||
_pannel->setBorderWidth(0);
|
||||
_pannel->setSize(320, 240);
|
||||
_pannel->setRadius(0);
|
||||
_pannel->setFlexFlow(LV_FLEX_FLOW_COLUMN);
|
||||
_pannel->setFlexAlign(LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
|
||||
_pannel->setPadding(20, 20, 20, 20);
|
||||
_pannel->setPadRow(15);
|
||||
|
||||
for (const auto& color : _rgb_colors) {
|
||||
auto btn = std::make_unique<Button>(*_pannel);
|
||||
apply_button_common_style(*btn);
|
||||
btn->setSize(200, 50);
|
||||
btn->label().setText(color.name);
|
||||
|
||||
uint8_t r = color.r;
|
||||
uint8_t g = color.g;
|
||||
uint8_t b = color.b;
|
||||
btn->onClick().connect([r, g, b]() { GetHAL().showRgbColor(r, g, b); });
|
||||
|
||||
_buttons.push_back(std::move(btn));
|
||||
}
|
||||
|
||||
auto btn_quit = std::make_unique<Button>(*_pannel);
|
||||
apply_button_common_style(*btn_quit);
|
||||
btn_quit->setSize(200, 50);
|
||||
btn_quit->label().setText("Quit");
|
||||
btn_quit->onClick().connect([this]() { _is_done = true; });
|
||||
_buttons.push_back(std::move(btn_quit));
|
||||
}
|
||||
|
||||
RgbTestWorker::~RgbTestWorker()
|
||||
{
|
||||
GetHAL().showRgbColor(0, 0, 0);
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#pragma once
|
||||
#include "common.h"
|
||||
#include <smooth_lvgl.hpp>
|
||||
#include <uitk/short_namespace.hpp>
|
||||
#include <hal/hal.h>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
|
||||
namespace setup_workers {
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
*/
|
||||
class WorkerBase {
|
||||
public:
|
||||
virtual ~WorkerBase() = default;
|
||||
|
||||
virtual void update()
|
||||
{
|
||||
}
|
||||
|
||||
bool isDone() const
|
||||
{
|
||||
return _is_done;
|
||||
}
|
||||
|
||||
protected:
|
||||
bool _is_done = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
*/
|
||||
class ZeroCalibrationWorker : public WorkerBase {
|
||||
public:
|
||||
ZeroCalibrationWorker();
|
||||
void update() override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<uitk::lvgl_cpp::Container> _pannel;
|
||||
std::unique_ptr<uitk::lvgl_cpp::Button> _btn_quit;
|
||||
std::unique_ptr<uitk::lvgl_cpp::Button> _btn_confirm;
|
||||
std::unique_ptr<uitk::lvgl_cpp::Button> _btn_go_home;
|
||||
bool _confirm_flag = false;
|
||||
bool _go_home_flag = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
*/
|
||||
class WifiSetupWorker : public WorkerBase {
|
||||
public:
|
||||
WifiSetupWorker();
|
||||
~WifiSetupWorker();
|
||||
void update() override;
|
||||
|
||||
private:
|
||||
enum class State {
|
||||
None,
|
||||
AppDownload,
|
||||
WaitAppConnection,
|
||||
AppConnected,
|
||||
Done,
|
||||
};
|
||||
|
||||
State _state = State::AppDownload;
|
||||
State _last_state = State::None;
|
||||
|
||||
uint32_t _last_tick = 0;
|
||||
bool _is_first_in = false;
|
||||
|
||||
AppConfigEvent _last_app_config_event = AppConfigEvent::None;
|
||||
int _app_config_signal_id = -1;
|
||||
|
||||
struct StateAppDownloadData {
|
||||
std::unique_ptr<uitk::lvgl_cpp::Qrcode> qrcode;
|
||||
std::unique_ptr<uitk::lvgl_cpp::Button> btn;
|
||||
bool is_clicked = false;
|
||||
|
||||
void reset()
|
||||
{
|
||||
qrcode.reset();
|
||||
btn.reset();
|
||||
is_clicked = false;
|
||||
}
|
||||
};
|
||||
StateAppDownloadData _state_app_download_data;
|
||||
|
||||
struct StateWaitAppConnectionData {
|
||||
std::unique_ptr<uitk::lvgl_cpp::Button> id_btn;
|
||||
|
||||
void reset()
|
||||
{
|
||||
id_btn.reset();
|
||||
}
|
||||
};
|
||||
StateWaitAppConnectionData _state_wait_app_connection_data;
|
||||
|
||||
struct StateDoneData {
|
||||
int reboot_count = 0;
|
||||
};
|
||||
StateDoneData _state_done_data;
|
||||
|
||||
void update_state();
|
||||
void cleanup_ui();
|
||||
void switch_state(State newState);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
*/
|
||||
class AppBindCodeWorker : public WorkerBase {
|
||||
public:
|
||||
AppBindCodeWorker();
|
||||
~AppBindCodeWorker();
|
||||
|
||||
private:
|
||||
std::unique_ptr<uitk::lvgl_cpp::Qrcode> _qrcode;
|
||||
std::unique_ptr<uitk::lvgl_cpp::Button> _btn_quit;
|
||||
};
|
||||
|
||||
class RgbTestWorker : public WorkerBase {
|
||||
public:
|
||||
RgbTestWorker();
|
||||
~RgbTestWorker();
|
||||
|
||||
private:
|
||||
std::unique_ptr<uitk::lvgl_cpp::Container> _pannel;
|
||||
std::vector<std::unique_ptr<uitk::lvgl_cpp::Button>> _buttons;
|
||||
};
|
||||
|
||||
} // namespace setup_workers
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#include "app_template.h"
|
||||
#include <hal/hal.h>
|
||||
#include <mooncake.h>
|
||||
#include <mooncake_log.h>
|
||||
#include <assets/assets.h>
|
||||
#include <smooth_lvgl.hpp>
|
||||
|
||||
using namespace mooncake;
|
||||
using namespace smooth_ui_toolkit::lvgl_cpp;
|
||||
|
||||
AppTemplate::AppTemplate()
|
||||
{
|
||||
// Configure App name
|
||||
setAppInfo().name = "AppTemplate";
|
||||
// Configure App icon
|
||||
// setAppInfo().icon = (void*)&icon_app_dummy;
|
||||
}
|
||||
|
||||
// Called when the App is installed
|
||||
void AppTemplate::onCreate()
|
||||
{
|
||||
mclog::tagInfo(getAppInfo().name, "on create");
|
||||
}
|
||||
|
||||
static std::unique_ptr<Button> _button_quit;
|
||||
static uint32_t _time_count = 0;
|
||||
|
||||
// Called when the App is opened
|
||||
// You can construct UI, initialize operations, etc. here
|
||||
void AppTemplate::onOpen()
|
||||
{
|
||||
mclog::tagInfo(getAppInfo().name, "on open");
|
||||
|
||||
// Lock before Lvgl operations to avoid conflict with lvgl thread
|
||||
// GetHAL().lvglLock(); to lock, GetHAL().lvglUnlock(); to unlock
|
||||
// You can also use LvglLockGuard for automatic locking and unlocking
|
||||
LvglLockGuard lock;
|
||||
|
||||
// Create a quit button
|
||||
// Using lvgl cpp wrapper here
|
||||
// Same as using c method directly, lv_button_create...
|
||||
_button_quit = std::make_unique<Button>(lv_screen_active());
|
||||
_button_quit->setAlign(LV_ALIGN_CENTER);
|
||||
_button_quit->label().setText("QUIT");
|
||||
_button_quit->onClick().connect([this]() {
|
||||
// Call close() to close the App
|
||||
close();
|
||||
});
|
||||
}
|
||||
|
||||
// Called repeatedly while the App is running
|
||||
void AppTemplate::onRunning()
|
||||
{
|
||||
// mclog::tagInfo(getAppInfo().name, "on running");
|
||||
|
||||
// Print "hi" every 1 second
|
||||
if (GetHAL().millis() - _time_count > 1000) {
|
||||
mclog::tagInfo(getAppInfo().name, "hi");
|
||||
_time_count = GetHAL().millis();
|
||||
}
|
||||
}
|
||||
|
||||
// Called when the App is closed
|
||||
// You can destroy UI, release resources, etc. here
|
||||
void AppTemplate::onClose()
|
||||
{
|
||||
mclog::tagInfo(getAppInfo().name, "on close");
|
||||
|
||||
LvglLockGuard lock;
|
||||
|
||||
// Destroy button
|
||||
_button_quit.reset();
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#pragma once
|
||||
#include <mooncake.h>
|
||||
|
||||
/**
|
||||
* @brief Derived App
|
||||
*
|
||||
*/
|
||||
class AppTemplate : public mooncake::AppAbility {
|
||||
public:
|
||||
AppTemplate();
|
||||
|
||||
// Override lifecycle callbacks
|
||||
void onCreate() override;
|
||||
void onOpen() override;
|
||||
void onRunning() override;
|
||||
void onClose() override;
|
||||
};
|
||||
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#pragma once
|
||||
#include "app_launcher/app_launcher.h"
|
||||
#include "app_ai_agent/app_ai_agent.h"
|
||||
#include "app_avatar/app_avatar.h"
|
||||
#include "app_setup/app_setup.h"
|
||||
#include "app_espnow_ctrl/app_espnow_ctrl.h"
|
||||
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#pragma once
|
||||
#include <string_view>
|
||||
|
||||
namespace common {
|
||||
|
||||
inline constexpr std::string_view FirmwareVersion = "V0.11";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#pragma once
|
||||
#include <lvgl.h>
|
||||
#include <string_view>
|
||||
|
||||
LV_FONT_DECLARE(MontserratSemiBold26);
|
||||
|
||||
LV_IMG_DECLARE(icon_ai_agent);
|
||||
LV_IMG_DECLARE(icon_controller);
|
||||
LV_IMG_DECLARE(icon_indicator_left);
|
||||
LV_IMG_DECLARE(icon_indicator_right);
|
||||
LV_IMG_DECLARE(icon_sentinel);
|
||||
LV_IMG_DECLARE(icon_setup);
|
||||
LV_IMG_DECLARE(icon_uiflow);
|
||||
LV_IMG_DECLARE(icon_calibrate);
|
||||
LV_IMG_DECLARE(icon_remote);
|
||||
|
||||
extern const char ogg_camera_shutter_start[] asm("_binary_camera_shutter_ogg_start");
|
||||
extern const char ogg_camera_shutter_end[] asm("_binary_camera_shutter_ogg_end");
|
||||
static const std::string_view OGG_CAMERA_SHUTTER{
|
||||
static_cast<const char*>(ogg_camera_shutter_start),
|
||||
static_cast<size_t>(ogg_camera_shutter_end - ogg_camera_shutter_start)};
|
||||
@@ -0,0 +1,717 @@
|
||||
/*******************************************************************************
|
||||
* Size: 26 px
|
||||
* Bpp: 2
|
||||
* Opts: --bpp 2 --size 26 --no-compress --stride 1 --align 1 --font Montserrat-SemiBold.ttf --symbols
|
||||
*!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ --format lvgl -o
|
||||
*MontserratSemiBold26.c
|
||||
******************************************************************************/
|
||||
|
||||
#ifdef __has_include
|
||||
#if __has_include("lvgl.h")
|
||||
#ifndef LV_LVGL_H_INCLUDE_SIMPLE
|
||||
#define LV_LVGL_H_INCLUDE_SIMPLE
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
|
||||
#include "lvgl.h"
|
||||
#else
|
||||
#include "lvgl/lvgl.h"
|
||||
#endif
|
||||
|
||||
#ifndef MONTSERRATSEMIBOLD26
|
||||
#define MONTSERRATSEMIBOLD26 1
|
||||
#endif
|
||||
|
||||
#if MONTSERRATSEMIBOLD26
|
||||
|
||||
/*-----------------
|
||||
* BITMAPS
|
||||
*----------------*/
|
||||
|
||||
/*Store the image of the glyphs*/
|
||||
static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
|
||||
/* U+0020 " " */
|
||||
|
||||
/* U+0021 "!" */
|
||||
0x7f, 0x8f, 0xd3, 0xf4, 0xfd, 0x3f, 0x4f, 0xd3, 0xf0, 0xfc, 0x3f, 0xf, 0xc2, 0xf0, 0xbc, 0x0, 0x0, 0x2, 0xf1, 0xfe,
|
||||
0x7f, 0x8b, 0xc0,
|
||||
|
||||
/* U+0022 "\"" */
|
||||
0xbd, 0x2f, 0x6f, 0x7, 0xc7, 0xc1, 0xf1, 0xf0, 0x7c, 0x7c, 0x1f, 0x1f, 0x7, 0xc7, 0xc1, 0xf0, 0x0, 0x0,
|
||||
|
||||
/* U+0023 "#" */
|
||||
0x0, 0xf, 0x0, 0xbc, 0x0, 0x1, 0xf0, 0xb, 0x80, 0x0, 0x1f, 0x0, 0xf8, 0x0, 0x2, 0xf0, 0xf, 0x40, 0x2f, 0xff, 0xff,
|
||||
0xff, 0xf2, 0xff, 0xff, 0xff, 0xff, 0x5, 0x7e, 0x56, 0xf5, 0x50, 0x3, 0xd0, 0x1f, 0x0, 0x0, 0x7c, 0x2, 0xf0, 0x0,
|
||||
0x7, 0xc0, 0x2e, 0x0, 0x0, 0xbc, 0x2, 0xe0, 0x7, 0xff, 0xff, 0xff, 0xfc, 0x7f, 0xff, 0xff, 0xff, 0xc1, 0x5f, 0x95,
|
||||
0x7e, 0x54, 0x0, 0xf4, 0x3, 0xc0, 0x0, 0xf, 0x0, 0x7c, 0x0, 0x1, 0xf0, 0x7, 0xc0, 0x0, 0x1f, 0x0, 0xbc, 0x0,
|
||||
|
||||
/* U+0024 "$" */
|
||||
0x0, 0x1, 0x80, 0x0, 0x0, 0x2, 0xd0, 0x0, 0x0, 0x2, 0xd0, 0x0, 0x0, 0x2, 0xd0, 0x0, 0x0, 0x6f, 0xfe, 0x40, 0x2,
|
||||
0xff, 0xff, 0xf4, 0xf, 0xff, 0xff, 0xf4, 0x1f, 0xe2, 0xd0, 0xb0, 0x2f, 0xc2, 0xd0, 0x0, 0x2f, 0x82, 0xd0, 0x0, 0x2f,
|
||||
0xd2, 0xd0, 0x0, 0xf, 0xff, 0xd0, 0x0, 0x3, 0xff, 0xfe, 0x0, 0x0, 0x6f, 0xff, 0xe0, 0x0, 0x3, 0xff, 0xfc, 0x0, 0x2,
|
||||
0xd2, 0xfd, 0x0, 0x2, 0xd0, 0xfd, 0x4, 0x2, 0xd0, 0xfd, 0x1f, 0x42, 0xd2, 0xfc, 0x3f, 0xff, 0xff, 0xf8, 0xf, 0xff,
|
||||
0xff, 0xe0, 0x0, 0xbf, 0xfe, 0x0, 0x0, 0x2, 0xd0, 0x0, 0x0, 0x2, 0xd0, 0x0, 0x0, 0x2, 0xd0, 0x0,
|
||||
|
||||
/* U+0025 "%" */
|
||||
0x2, 0xfd, 0x0, 0x0, 0xf4, 0x0, 0xfe, 0xf4, 0x0, 0x3e, 0x0, 0x2e, 0x3, 0xc0, 0xb, 0xc0, 0x3, 0xc0, 0x2d, 0x1, 0xf4,
|
||||
0x0, 0x3c, 0x2, 0xe0, 0x3e, 0x0, 0x3, 0xc0, 0x2e, 0xb, 0xc0, 0x0, 0x3d, 0x3, 0xd1, 0xf0, 0x0, 0x2, 0xf0, 0xbc, 0x3d,
|
||||
0x0, 0x0, 0xf, 0xff, 0x4b, 0xc1, 0xf8, 0x0, 0x1f, 0x81, 0xf0, 0xff, 0xf4, 0x0, 0x0, 0x3d, 0x2f, 0xb, 0xc0, 0x0, 0xf,
|
||||
0x83, 0xc0, 0x3d, 0x0, 0x2, 0xf0, 0x3c, 0x2, 0xd0, 0x0, 0x3d, 0x3, 0xc0, 0x2d, 0x0, 0xf, 0x80, 0x3c, 0x3, 0xd0, 0x2,
|
||||
0xf0, 0x2, 0xe0, 0x7c, 0x0, 0x7d, 0x0, 0xf, 0xef, 0x40, 0xf, 0x80, 0x0, 0x2f, 0xd0,
|
||||
|
||||
/* U+0026 "&" */
|
||||
0x0, 0x6f, 0xe4, 0x0, 0x0, 0xbf, 0xff, 0x80, 0x0, 0x7f, 0x57, 0xf0, 0x0, 0x2f, 0x40, 0x7d, 0x0, 0xb, 0xd0, 0x1f,
|
||||
0x40, 0x1, 0xf8, 0x1f, 0xc0, 0x0, 0x3f, 0xaf, 0xd0, 0x0, 0x3, 0xff, 0xc0, 0x0, 0x2, 0xff, 0xc0, 0x0, 0x3, 0xff,
|
||||
0xfc, 0x6, 0x43, 0xf8, 0x3f, 0xc3, 0xf2, 0xf8, 0x3, 0xfd, 0xfc, 0xfd, 0x0, 0x3f, 0xfd, 0x3f, 0x40, 0x2, 0xff, 0xb,
|
||||
0xf0, 0x0, 0xbf, 0xd1, 0xff, 0xeb, 0xff, 0xfd, 0x1f, 0xff, 0xff, 0x2f, 0x40, 0x7f, 0xf9, 0x1, 0x80, 0x0, 0x0, 0x0,
|
||||
0x0,
|
||||
|
||||
/* U+0027 "'" */
|
||||
0xbd, 0xbc, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x0,
|
||||
|
||||
/* U+0028 "(" */
|
||||
0x0, 0x50, 0xf, 0xc0, 0xbe, 0x3, 0xf0, 0x1f, 0xc0, 0xfd, 0x3, 0xf0, 0x1f, 0xc0, 0x7e, 0x2, 0xf8, 0xb, 0xd0, 0x3f,
|
||||
0x40, 0xfd, 0x3, 0xf4, 0xf, 0xd0, 0x2f, 0x80, 0xbe, 0x1, 0xfc, 0x3, 0xf0, 0xf, 0xc0, 0x2f, 0x80, 0x7f, 0x0, 0xfc,
|
||||
0x1, 0xf8, 0x3, 0xf0,
|
||||
|
||||
/* U+0029 ")" */
|
||||
0x14, 0x0, 0xfc, 0x2, 0xf8, 0x3, 0xf0, 0xb, 0xe0, 0x1f, 0xc0, 0x3f, 0x0, 0xfd, 0x2, 0xf8, 0xb, 0xe0, 0x1f, 0x80,
|
||||
0x7f, 0x1, 0xfc, 0x7, 0xf0, 0x1f, 0xc0, 0x7e, 0x2, 0xf8, 0xb, 0xd0, 0x3f, 0x40, 0xfc, 0x7, 0xe0, 0x3f, 0x40, 0xfc,
|
||||
0xb, 0xe0, 0x3f, 0x0,
|
||||
|
||||
/* U+002A "*" */
|
||||
0x0, 0xb4, 0x0, 0x2, 0xd0, 0x3, 0xcb, 0x5f, 0x1f, 0xff, 0xfc, 0xb, 0xff, 0x40, 0x1f, 0xfd, 0x7, 0xff, 0xff, 0xf,
|
||||
0x2d, 0x7c, 0x0, 0xb4, 0x0, 0x2, 0xd0, 0x0,
|
||||
|
||||
/* U+002B "+" */
|
||||
0x0, 0x2f, 0x0, 0x0, 0xb, 0xc0, 0x0, 0x2, 0xf0, 0x0, 0x0, 0xbc, 0x0, 0x2a, 0xbf, 0xaa, 0x5f, 0xff, 0xff, 0xe7, 0xff,
|
||||
0xff, 0xf8, 0x0, 0xbc, 0x0, 0x0, 0x2f, 0x0, 0x0, 0xb, 0xc0, 0x0, 0x2, 0xf0, 0x0, 0x0, 0x68, 0x0,
|
||||
|
||||
/* U+002C "," */
|
||||
0x0, 0x1f, 0x8f, 0xf3, 0xfc, 0x3f, 0xf, 0x83, 0xd1, 0xf0, 0xb8, 0x0,
|
||||
|
||||
/* U+002D "-" */
|
||||
0x6a, 0xa9, 0xbf, 0xfe, 0xbf, 0xfe,
|
||||
|
||||
/* U+002E "." */
|
||||
0x4, 0x1f, 0xcf, 0xf7, 0xfc, 0x3d, 0x0,
|
||||
|
||||
/* U+002F "/" */
|
||||
0x0, 0x0, 0x29, 0x0, 0x0, 0xbd, 0x0, 0x0, 0xfc, 0x0, 0x1, 0xf8, 0x0, 0x2, 0xf4, 0x0, 0x3, 0xf0, 0x0, 0x7, 0xe0, 0x0,
|
||||
0xb, 0xd0, 0x0, 0xf, 0xc0, 0x0, 0x1f, 0x80, 0x0, 0x2f, 0x0, 0x0, 0x3f, 0x0, 0x0, 0x7e, 0x0, 0x0, 0xfc, 0x0, 0x0,
|
||||
0xfc, 0x0, 0x1, 0xf4, 0x0, 0x3, 0xf0, 0x0, 0x3, 0xf0, 0x0, 0xb, 0xd0, 0x0, 0xf, 0xc0, 0x0, 0xf, 0x80, 0x0, 0x2f,
|
||||
0x40, 0x0, 0x3f, 0x0, 0x0, 0x7e, 0x0, 0x0, 0xbd, 0x0, 0x0,
|
||||
|
||||
/* U+0030 "0" */
|
||||
0x0, 0x6f, 0xf8, 0x0, 0x2, 0xff, 0xff, 0x40, 0xf, 0xff, 0xff, 0xd0, 0x2f, 0xe0, 0x1f, 0xf0, 0x3f, 0x80, 0x3, 0xf8,
|
||||
0x7f, 0x0, 0x2, 0xfc, 0xbf, 0x0, 0x1, 0xfc, 0xfe, 0x0, 0x0, 0xfd, 0xfe, 0x0, 0x0, 0xfd, 0xfe, 0x0, 0x0, 0xfd, 0xfe,
|
||||
0x0, 0x0, 0xfd, 0xbf, 0x0, 0x1, 0xfc, 0x7f, 0x0, 0x2, 0xfc, 0x3f, 0x80, 0x3, 0xf8, 0x2f, 0xe0, 0x1f, 0xf0, 0xf,
|
||||
0xff, 0xff, 0xd0, 0x2, 0xff, 0xff, 0x40, 0x0, 0x6f, 0xf4, 0x0,
|
||||
|
||||
/* U+0031 "1" */
|
||||
0xff, 0xfd, 0xff, 0xfd, 0xbf, 0xfd, 0x0, 0xfd, 0x0, 0xfd, 0x0, 0xfd, 0x0, 0xfd, 0x0, 0xfd, 0x0, 0xfd, 0x0, 0xfd,
|
||||
0x0, 0xfd, 0x0, 0xfd, 0x0, 0xfd, 0x0, 0xfd, 0x0, 0xfd, 0x0, 0xfd, 0x0, 0xfd, 0x0, 0xfd,
|
||||
|
||||
/* U+0032 "2" */
|
||||
0x1, 0xbf, 0xe4, 0x0, 0x7f, 0xff, 0xfc, 0x7, 0xff, 0xff, 0xfc, 0xf, 0xd0, 0xb, 0xf4, 0x8, 0x0, 0xf, 0xe0, 0x0, 0x0,
|
||||
0x3f, 0x80, 0x0, 0x0, 0xfd, 0x0, 0x0, 0x7, 0xf0, 0x0, 0x0, 0x7f, 0x80, 0x0, 0x7, 0xf8, 0x0, 0x0, 0x7f, 0x80, 0x0,
|
||||
0x7, 0xf8, 0x0, 0x0, 0xbf, 0x80, 0x0, 0xb, 0xf8, 0x0, 0x0, 0xbf, 0x40, 0x0, 0xf, 0xff, 0xff, 0xfd, 0x3f, 0xff, 0xff,
|
||||
0xf4, 0xff, 0xff, 0xff, 0xd0,
|
||||
|
||||
/* U+0033 "3" */
|
||||
0x3f, 0xff, 0xff, 0xd0, 0xff, 0xff, 0xff, 0x43, 0xff, 0xff, 0xfc, 0x0, 0x0, 0x1f, 0xc0, 0x0, 0x1, 0xfd, 0x0, 0x0,
|
||||
0x1f, 0xd0, 0x0, 0x0, 0xfd, 0x0, 0x0, 0xf, 0xfe, 0x0, 0x0, 0x3f, 0xff, 0x40, 0x0, 0xab, 0xff, 0x40, 0x0, 0x1, 0xff,
|
||||
0x0, 0x0, 0x2, 0xfc, 0x0, 0x0, 0x7, 0xf0, 0x40, 0x0, 0x2f, 0xc3, 0xe4, 0x2, 0xfe, 0x2f, 0xff, 0xff, 0xf0, 0x3f,
|
||||
0xff, 0xff, 0x0, 0xb, 0xff, 0x90, 0x0,
|
||||
|
||||
/* U+0034 "4" */
|
||||
0x0, 0x0, 0x2f, 0xc0, 0x0, 0x0, 0x7, 0xf4, 0x0, 0x0, 0x0, 0xfe, 0x0, 0x0, 0x0, 0x3f, 0xc0, 0x0, 0x0, 0xb, 0xf0, 0x0,
|
||||
0x0, 0x1, 0xfd, 0x0, 0x0, 0x0, 0x3f, 0x40, 0x0, 0x0, 0xf, 0xe0, 0x2a, 0x0, 0x2, 0xfc, 0x3, 0xf0, 0x0, 0xbf, 0x0,
|
||||
0x3f, 0x0, 0x1f, 0xd0, 0x3, 0xf0, 0x3, 0xff, 0xff, 0xff, 0xfd, 0x3f, 0xff, 0xff, 0xff, 0xd3, 0xff, 0xff, 0xff, 0xfd,
|
||||
0x0, 0x0, 0x3, 0xf0, 0x0, 0x0, 0x0, 0x3f, 0x0, 0x0, 0x0, 0x3, 0xf0, 0x0, 0x0, 0x0, 0x3f, 0x0,
|
||||
|
||||
/* U+0035 "5" */
|
||||
0x7, 0xff, 0xff, 0xd0, 0x2f, 0xff, 0xff, 0x40, 0xbf, 0xff, 0xfd, 0x2, 0xf4, 0x0, 0x0, 0xf, 0xd0, 0x0, 0x0, 0x3f,
|
||||
0x0, 0x0, 0x0, 0xfc, 0x0, 0x0, 0x3, 0xff, 0xfe, 0x0, 0xf, 0xff, 0xff, 0x80, 0x3f, 0xff, 0xff, 0x80, 0x0, 0x1, 0xff,
|
||||
0x0, 0x0, 0x1, 0xfd, 0x0, 0x0, 0x3, 0xf4, 0x0, 0x0, 0x1f, 0xc3, 0xe4, 0x1, 0xff, 0x1f, 0xff, 0xff, 0xf4, 0x2f, 0xff,
|
||||
0xff, 0x40, 0x6, 0xff, 0xd0, 0x0,
|
||||
|
||||
/* U+0036 "6" */
|
||||
0x0, 0x1b, 0xff, 0x40, 0x7, 0xff, 0xff, 0x80, 0x7f, 0xff, 0xfc, 0x7, 0xfd, 0x0, 0x10, 0x3f, 0xc0, 0x0, 0x1, 0xfc,
|
||||
0x0, 0x0, 0xb, 0xf0, 0x6a, 0x40, 0x2f, 0xaf, 0xff, 0xd0, 0xff, 0xff, 0xff, 0xd3, 0xff, 0x80, 0x7f, 0xcf, 0xf8, 0x0,
|
||||
0x3f, 0x6f, 0xc0, 0x0, 0xbe, 0x7f, 0x0, 0x2, 0xf8, 0xfd, 0x0, 0xf, 0xd2, 0xfd, 0x0, 0xbf, 0x3, 0xff, 0xaf, 0xf8,
|
||||
0x3, 0xff, 0xff, 0x80, 0x1, 0xbf, 0xe0, 0x0,
|
||||
|
||||
/* U+0037 "7" */
|
||||
0x7f, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xdf, 0xc0, 0x1, 0xfd, 0x7f, 0x0, 0xb, 0xf0, 0xfc,
|
||||
0x0, 0x3f, 0x40, 0x0, 0x2, 0xfc, 0x0, 0x0, 0xf, 0xe0, 0x0, 0x0, 0xbf, 0x0, 0x0, 0x3, 0xf8, 0x0, 0x0, 0x1f, 0xc0,
|
||||
0x0, 0x0, 0xfe, 0x0, 0x0, 0x7, 0xf4, 0x0, 0x0, 0x3f, 0xc0, 0x0, 0x0, 0xfd, 0x0, 0x0, 0xb, 0xf0, 0x0, 0x0, 0x3f,
|
||||
0x40, 0x0, 0x2, 0xfc, 0x0, 0x0,
|
||||
|
||||
/* U+0038 "8" */
|
||||
0x1, 0xbf, 0xf8, 0x0, 0x2f, 0xff, 0xfe, 0x2, 0xff, 0xab, 0xfe, 0xf, 0xe0, 0x2, 0xfc, 0x7f, 0x0, 0x3, 0xf0, 0xfc,
|
||||
0x0, 0xf, 0xc3, 0xfd, 0x1, 0xff, 0x3, 0xff, 0xff, 0xf0, 0xb, 0xff, 0xff, 0x80, 0xff, 0x95, 0xbf, 0xcb, 0xf0, 0x0,
|
||||
0x7f, 0xbf, 0x80, 0x0, 0xbf, 0xfd, 0x0, 0x2, 0xff, 0xf8, 0x0, 0xf, 0xfb, 0xf8, 0x0, 0xbf, 0x4f, 0xfe, 0xaf, 0xfc,
|
||||
0xf, 0xff, 0xff, 0x80, 0x6, 0xff, 0xe4, 0x0,
|
||||
|
||||
/* U+0039 "9" */
|
||||
0x0, 0xbf, 0xf4, 0x0, 0x7, 0xff, 0xff, 0x40, 0x1f, 0xfa, 0xbf, 0xd0, 0x3f, 0x80, 0xb, 0xf0, 0x7f, 0x0, 0x3, 0xf4,
|
||||
0x7f, 0x0, 0x3, 0xfc, 0x7f, 0x0, 0x3, 0xfc, 0x3f, 0xd0, 0x1f, 0xfc, 0x1f, 0xff, 0xff, 0xfc, 0x7, 0xff, 0xfd, 0xfc,
|
||||
0x0, 0x6a, 0x81, 0xfc, 0x0, 0x0, 0x2, 0xfc, 0x0, 0x0, 0x3, 0xf8, 0x0, 0x0, 0xb, 0xf0, 0x5, 0x0, 0x7f, 0xe0, 0xf,
|
||||
0xff, 0xff, 0x80, 0x1f, 0xff, 0xfe, 0x0, 0x6, 0xff, 0xe0, 0x0,
|
||||
|
||||
/* U+003A ":" */
|
||||
0x7e, 0x3f, 0xcf, 0xf5, 0xfc, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x7, 0xf3, 0xfd, 0xff, 0xf, 0x40,
|
||||
|
||||
/* U+003B ";" */
|
||||
0x7e, 0x3f, 0xcf, 0xf5, 0xfc, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xe3, 0xfc, 0xff, 0xf, 0xc3, 0xe0, 0xf4, 0x7c,
|
||||
0x2e, 0x0,
|
||||
|
||||
/* U+003C "<" */
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xa0, 0x0, 0x7, 0xf8, 0x0, 0x6f, 0xfd, 0x2, 0xff, 0xf4, 0xf, 0xff, 0x80, 0x7, 0xf9,
|
||||
0x0, 0x1, 0xff, 0x40, 0x0, 0x2f, 0xfe, 0x40, 0x0, 0x7f, 0xfe, 0x0, 0x0, 0xbf, 0xf8, 0x0, 0x1, 0xbe, 0x0, 0x0, 0x2,
|
||||
0x80,
|
||||
|
||||
/* U+003D "=" */
|
||||
0x7f, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xe2, 0xaa, 0xaa, 0xa4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xaa,
|
||||
0xaa, 0xa5, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0x80,
|
||||
|
||||
/* U+003E ">" */
|
||||
0x0, 0x0, 0x0, 0x1d, 0x0, 0x0, 0x7, 0xf8, 0x0, 0x0, 0xff, 0xf4, 0x0, 0x6, 0xff, 0xe4, 0x0, 0x7, 0xff, 0xd0, 0x0,
|
||||
0xb, 0xf8, 0x0, 0x6, 0xfe, 0x0, 0x2f, 0xff, 0x41, 0xff, 0xf8, 0x3, 0xff, 0x90, 0x1, 0xfd, 0x0, 0x0, 0x64, 0x0, 0x0,
|
||||
0x0,
|
||||
|
||||
/* U+003F "?" */
|
||||
0x1, 0xbf, 0xe4, 0x1, 0xff, 0xff, 0xf0, 0x7f, 0xff, 0xff, 0xc7, 0xf4, 0x2, 0xfd, 0x4, 0x0, 0xf, 0xe0, 0x0, 0x0,
|
||||
0xfd, 0x0, 0x0, 0x1f, 0xc0, 0x0, 0x7, 0xf4, 0x0, 0x2, 0xfd, 0x0, 0x0, 0x7f, 0x40, 0x0, 0xf, 0xd0, 0x0, 0x0, 0xfc,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0x80, 0x0, 0x2, 0xfd, 0x0, 0x0, 0x2f, 0xd0, 0x0, 0x0, 0xf8, 0x0,
|
||||
|
||||
/* U+0040 "@" */
|
||||
0x0, 0x0, 0x6f, 0xfe, 0x40, 0x0, 0x0, 0x2, 0xff, 0xff, 0xfe, 0x0, 0x0, 0xb, 0xfe, 0x40, 0x5b, 0xf8, 0x0, 0xb, 0xf0,
|
||||
0x0, 0x0, 0x2f, 0x80, 0xb, 0xe0, 0x0, 0x0, 0x1, 0xf8, 0x7, 0xe0, 0xb, 0xfd, 0x3f, 0x1f, 0x43, 0xf0, 0x1f, 0xff,
|
||||
0xef, 0xc2, 0xf0, 0xf4, 0x1f, 0xf5, 0xbf, 0xf0, 0x3c, 0xbc, 0xf, 0xe0, 0x3, 0xfc, 0xf, 0x6e, 0x3, 0xf0, 0x0, 0x3f,
|
||||
0x2, 0xef, 0x81, 0xf8, 0x0, 0xf, 0xc0, 0x7b, 0xe0, 0x7d, 0x0, 0x3, 0xf0, 0x1f, 0xf8, 0x1f, 0x80, 0x0, 0xfc, 0xb,
|
||||
0xae, 0x3, 0xf0, 0x0, 0x7f, 0x2, 0xe7, 0xc0, 0xfe, 0x0, 0x3f, 0xc0, 0xf0, 0xf4, 0xf, 0xf9, 0xbf, 0xfd, 0xfc, 0x3f,
|
||||
0x1, 0xff, 0xff, 0x3f, 0xfc, 0x3, 0xe0, 0xb, 0xfd, 0x7, 0xf8, 0x0, 0xbe, 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0xf0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0xbf, 0xd4, 0x6, 0xf0, 0x0, 0x0, 0x2, 0xff, 0xff, 0xfc, 0x0, 0x0, 0x0, 0x6, 0xff, 0xe4, 0x0,
|
||||
0x0,
|
||||
|
||||
/* U+0041 "A" */
|
||||
0x0, 0x0, 0x3f, 0x80, 0x0, 0x0, 0x0, 0x2f, 0xf0, 0x0, 0x0, 0x0, 0xf, 0xfe, 0x0, 0x0, 0x0, 0xb, 0xff, 0xc0, 0x0, 0x0,
|
||||
0x3, 0xf3, 0xf4, 0x0, 0x0, 0x1, 0xfc, 0x7f, 0x0, 0x0, 0x0, 0xfd, 0xf, 0xd0, 0x0, 0x0, 0x7f, 0x1, 0xfc, 0x0, 0x0,
|
||||
0x3f, 0x40, 0x3f, 0x40, 0x0, 0x1f, 0xc0, 0xb, 0xe0, 0x0, 0xb, 0xe0, 0x0, 0xfc, 0x0, 0x3, 0xff, 0xff, 0xff, 0x80,
|
||||
0x2, 0xff, 0xff, 0xff, 0xf0, 0x0, 0xfe, 0xaa, 0xaa, 0xfe, 0x0, 0xbf, 0x0, 0x0, 0x1f, 0xc0, 0x3f, 0x40, 0x0, 0x3,
|
||||
0xf4, 0x1f, 0xc0, 0x0, 0x0, 0xbf, 0xf, 0xe0, 0x0, 0x0, 0xf, 0xd0,
|
||||
|
||||
/* U+0042 "B" */
|
||||
0xbf, 0xff, 0xff, 0x40, 0x2f, 0xff, 0xff, 0xfd, 0xb, 0xfa, 0xaa, 0xff, 0xc2, 0xfc, 0x0, 0x7, 0xf8, 0xbf, 0x0, 0x0,
|
||||
0xfe, 0x2f, 0xc0, 0x0, 0x3f, 0x8b, 0xf0, 0x0, 0x1f, 0xc2, 0xfe, 0xaa, 0xbf, 0xd0, 0xbf, 0xff, 0xff, 0xf0, 0x2f,
|
||||
0xff, 0xff, 0xff, 0x4b, 0xf0, 0x0, 0x1f, 0xf2, 0xfc, 0x0, 0x0, 0xfd, 0xbf, 0x0, 0x0, 0x3f, 0xaf, 0xc0, 0x0, 0xf,
|
||||
0xeb, 0xf0, 0x0, 0xb, 0xf6, 0xfe, 0xaa, 0xaf, 0xfc, 0xbf, 0xff, 0xff, 0xfc, 0x2f, 0xff, 0xff, 0xe4, 0x0,
|
||||
|
||||
/* U+0043 "C" */
|
||||
0x0, 0x7, 0xff, 0x90, 0x0, 0xb, 0xff, 0xff, 0xd0, 0x3, 0xff, 0xff, 0xff, 0x80, 0xff, 0xd0, 0x7, 0xf8, 0x2f, 0xe0,
|
||||
0x0, 0x9, 0x3, 0xf8, 0x0, 0x0, 0x0, 0xbf, 0x0, 0x0, 0x0, 0xb, 0xe0, 0x0, 0x0, 0x0, 0xfe, 0x0, 0x0, 0x0, 0xf, 0xe0,
|
||||
0x0, 0x0, 0x0, 0xbe, 0x0, 0x0, 0x0, 0xb, 0xf0, 0x0, 0x0, 0x0, 0x3f, 0x80, 0x0, 0x0, 0x2, 0xfe, 0x0, 0x0, 0x90, 0xf,
|
||||
0xfd, 0x0, 0x7f, 0x80, 0x3f, 0xff, 0xff, 0xf8, 0x0, 0xbf, 0xff, 0xfd, 0x0, 0x0, 0x7f, 0xf9, 0x0,
|
||||
|
||||
/* U+0044 "D" */
|
||||
0xbf, 0xff, 0xfe, 0x40, 0x2, 0xff, 0xff, 0xff, 0xd0, 0xb, 0xff, 0xff, 0xff, 0xe0, 0x2f, 0xc0, 0x0, 0xbf, 0xe0, 0xbf,
|
||||
0x0, 0x0, 0x3f, 0xc2, 0xfc, 0x0, 0x0, 0x3f, 0x8b, 0xf0, 0x0, 0x0, 0xbf, 0x2f, 0xc0, 0x0, 0x0, 0xfc, 0xbf, 0x0, 0x0,
|
||||
0x3, 0xf6, 0xfc, 0x0, 0x0, 0xf, 0xdb, 0xf0, 0x0, 0x0, 0x3f, 0x2f, 0xc0, 0x0, 0x2, 0xfc, 0xbf, 0x0, 0x0, 0xf, 0xe2,
|
||||
0xfc, 0x0, 0x0, 0xff, 0xb, 0xf0, 0x0, 0x2f, 0xf8, 0x2f, 0xff, 0xff, 0xff, 0x80, 0xbf, 0xff, 0xff, 0xf4, 0x2, 0xff,
|
||||
0xff, 0xf9, 0x0, 0x0,
|
||||
|
||||
/* U+0045 "E" */
|
||||
0xbf, 0xff, 0xff, 0xe2, 0xff, 0xff, 0xff, 0x8b, 0xff, 0xff, 0xfe, 0x2f, 0xc0, 0x0, 0x0, 0xbf, 0x0, 0x0, 0x2, 0xfc,
|
||||
0x0, 0x0, 0xb, 0xf0, 0x0, 0x0, 0x2f, 0xff, 0xff, 0xd0, 0xbf, 0xff, 0xff, 0x82, 0xff, 0xff, 0xfe, 0xb, 0xf0, 0x0,
|
||||
0x0, 0x2f, 0xc0, 0x0, 0x0, 0xbf, 0x0, 0x0, 0x2, 0xfc, 0x0, 0x0, 0xb, 0xf0, 0x0, 0x0, 0x2f, 0xff, 0xff, 0xfc, 0xbf,
|
||||
0xff, 0xff, 0xf2, 0xff, 0xff, 0xff, 0xc0,
|
||||
|
||||
/* U+0046 "F" */
|
||||
0xbf, 0xff, 0xff, 0xeb, 0xff, 0xff, 0xfe, 0xbf, 0xff, 0xff, 0xeb, 0xf0, 0x0, 0x0, 0xbf, 0x0, 0x0, 0xb, 0xf0, 0x0,
|
||||
0x0, 0xbf, 0x0, 0x0, 0xb, 0xf0, 0x0, 0x0, 0xbf, 0xff, 0xff, 0x8b, 0xff, 0xff, 0xf8, 0xbf, 0xff, 0xff, 0x8b, 0xf0,
|
||||
0x0, 0x0, 0xbf, 0x0, 0x0, 0xb, 0xf0, 0x0, 0x0, 0xbf, 0x0, 0x0, 0xb, 0xf0, 0x0, 0x0, 0xbf, 0x0, 0x0, 0xb, 0xf0, 0x0,
|
||||
0x0,
|
||||
|
||||
/* U+0047 "G" */
|
||||
0x0, 0x6, 0xff, 0x90, 0x0, 0xb, 0xff, 0xff, 0xe0, 0x3, 0xff, 0xff, 0xff, 0xc0, 0xff, 0xd0, 0x6, 0xf8, 0x2f, 0xe0,
|
||||
0x0, 0x6, 0x3, 0xf8, 0x0, 0x0, 0x0, 0xbf, 0x0, 0x0, 0x0, 0xb, 0xe0, 0x0, 0x0, 0x0, 0xfe, 0x0, 0x0, 0x0, 0xf, 0xe0,
|
||||
0x0, 0x0, 0xfc, 0xbe, 0x0, 0x0, 0xf, 0xcb, 0xf0, 0x0, 0x0, 0xfc, 0x3f, 0x80, 0x0, 0xf, 0xc2, 0xfe, 0x0, 0x0, 0xfc,
|
||||
0xf, 0xfd, 0x0, 0x6f, 0xc0, 0x3f, 0xff, 0xff, 0xfc, 0x0, 0xbf, 0xff, 0xfe, 0x0, 0x0, 0x7f, 0xf9, 0x0,
|
||||
|
||||
/* U+0048 "H" */
|
||||
0xbf, 0x0, 0x0, 0x3f, 0xaf, 0xc0, 0x0, 0xf, 0xeb, 0xf0, 0x0, 0x3, 0xfa, 0xfc, 0x0, 0x0, 0xfe, 0xbf, 0x0, 0x0, 0x3f,
|
||||
0xaf, 0xc0, 0x0, 0xf, 0xeb, 0xf0, 0x0, 0x3, 0xfa, 0xff, 0xff, 0xff, 0xfe, 0xbf, 0xff, 0xff, 0xff, 0xaf, 0xff, 0xff,
|
||||
0xff, 0xeb, 0xf0, 0x0, 0x3, 0xfa, 0xfc, 0x0, 0x0, 0xfe, 0xbf, 0x0, 0x0, 0x3f, 0xaf, 0xc0, 0x0, 0xf, 0xeb, 0xf0, 0x0,
|
||||
0x3, 0xfa, 0xfc, 0x0, 0x0, 0xfe, 0xbf, 0x0, 0x0, 0x3f, 0xaf, 0xc0, 0x0, 0xf, 0xe0,
|
||||
|
||||
/* U+0049 "I" */
|
||||
0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf,
|
||||
|
||||
/* U+004A "J" */
|
||||
0x7, 0xff, 0xff, 0x41, 0xff, 0xff, 0xd0, 0x7f, 0xff, 0xf4, 0x0, 0x0, 0xfd, 0x0, 0x0, 0x3f, 0x40, 0x0, 0xf, 0xd0,
|
||||
0x0, 0x3, 0xf4, 0x0, 0x0, 0xfd, 0x0, 0x0, 0x3f, 0x40, 0x0, 0xf, 0xd0, 0x0, 0x3, 0xf4, 0x0, 0x0, 0xfd, 0x0, 0x0,
|
||||
0x3f, 0x42, 0x0, 0xf, 0xd2, 0xf0, 0xf, 0xf0, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xf8, 0x0, 0x7f, 0xe4, 0x0,
|
||||
|
||||
/* U+004B "K" */
|
||||
0xbf, 0x0, 0x0, 0xbf, 0xb, 0xf0, 0x0, 0x2f, 0xc0, 0xbf, 0x0, 0xb, 0xf4, 0xb, 0xf0, 0x2, 0xfd, 0x0, 0xbf, 0x0, 0xbf,
|
||||
0x40, 0xb, 0xf0, 0x2f, 0xd0, 0x0, 0xbf, 0xb, 0xf4, 0x0, 0xb, 0xf1, 0xfd, 0x0, 0x0, 0xbf, 0x7f, 0xd0, 0x0, 0xb, 0xff,
|
||||
0xff, 0x0, 0x0, 0xbf, 0xfb, 0xfc, 0x0, 0xb, 0xfe, 0x1f, 0xf0, 0x0, 0xbf, 0x80, 0xbf, 0x80, 0xb, 0xf0, 0x2, 0xfd,
|
||||
0x0, 0xbf, 0x0, 0xf, 0xf0, 0xb, 0xf0, 0x0, 0x3f, 0xc0, 0xbf, 0x0, 0x0, 0xff, 0xb, 0xf0, 0x0, 0x7, 0xf8,
|
||||
|
||||
/* U+004C "L" */
|
||||
0xbf, 0x0, 0x0, 0xb, 0xf0, 0x0, 0x0, 0xbf, 0x0, 0x0, 0xb, 0xf0, 0x0, 0x0, 0xbf, 0x0, 0x0, 0xb, 0xf0, 0x0, 0x0, 0xbf,
|
||||
0x0, 0x0, 0xb, 0xf0, 0x0, 0x0, 0xbf, 0x0, 0x0, 0xb, 0xf0, 0x0, 0x0, 0xbf, 0x0, 0x0, 0xb, 0xf0, 0x0, 0x0, 0xbf, 0x0,
|
||||
0x0, 0xb, 0xf0, 0x0, 0x0, 0xbf, 0x0, 0x0, 0xb, 0xff, 0xff, 0xfd, 0xbf, 0xff, 0xff, 0xdb, 0xff, 0xff, 0xfd,
|
||||
|
||||
/* U+004D "M" */
|
||||
0xbe, 0x0, 0x0, 0x0, 0x3f, 0x6f, 0xc0, 0x0, 0x0, 0x1f, 0xdb, 0xf8, 0x0, 0x0, 0xf, 0xf6, 0xff, 0x40, 0x0, 0xb, 0xfd,
|
||||
0xbf, 0xf0, 0x0, 0x3, 0xff, 0x6f, 0xfe, 0x0, 0x2, 0xff, 0xdb, 0xff, 0xc0, 0x1, 0xff, 0xf6, 0xfa, 0xfc, 0x0, 0xfc,
|
||||
0xfd, 0xbe, 0x3f, 0x40, 0xbe, 0x3f, 0x6f, 0x87, 0xf0, 0x3f, 0xf, 0xdb, 0xe0, 0xbe, 0x2f, 0x43, 0xf6, 0xf8, 0xf,
|
||||
0xef, 0xc0, 0xfd, 0xbe, 0x1, 0xff, 0xc0, 0x3f, 0x6f, 0x80, 0x3f, 0xe0, 0xf, 0xdb, 0xe0, 0x3, 0xf0, 0x3, 0xf6, 0xf8,
|
||||
0x0, 0xb4, 0x0, 0xfd, 0xbe, 0x0, 0x0, 0x0, 0x3f, 0x6f, 0x80, 0x0, 0x0, 0xf, 0xd0,
|
||||
|
||||
/* U+004E "N" */
|
||||
0xbe, 0x0, 0x0, 0x2f, 0xaf, 0xd0, 0x0, 0xb, 0xeb, 0xfd, 0x0, 0x2, 0xfa, 0xff, 0xc0, 0x0, 0xbe, 0xbf, 0xfc, 0x0,
|
||||
0x2f, 0xaf, 0xff, 0x80, 0xb, 0xeb, 0xfb, 0xf8, 0x2, 0xfa, 0xfc, 0xbf, 0x40, 0xbe, 0xbf, 0xf, 0xf0, 0x2f, 0xaf, 0xc0,
|
||||
0xff, 0xb, 0xeb, 0xf0, 0x1f, 0xf2, 0xfa, 0xfc, 0x1, 0xfe, 0xbe, 0xbf, 0x0, 0x2f, 0xff, 0xaf, 0xc0, 0x3, 0xff, 0xeb,
|
||||
0xf0, 0x0, 0x3f, 0xfa, 0xfc, 0x0, 0x3, 0xfe, 0xbf, 0x0, 0x0, 0x7f, 0xaf, 0xc0, 0x0, 0xb, 0xe0,
|
||||
|
||||
/* U+004F "O" */
|
||||
0x0, 0x6, 0xff, 0x90, 0x0, 0x0, 0xbf, 0xff, 0xfe, 0x0, 0x3, 0xff, 0xff, 0xff, 0xc0, 0xf, 0xfd, 0x0, 0x7f, 0xf0,
|
||||
0x2f, 0xe0, 0x0, 0xb, 0xf8, 0x3f, 0x80, 0x0, 0x3, 0xfc, 0xbf, 0x0, 0x0, 0x0, 0xfd, 0xbe, 0x0, 0x0, 0x0, 0xfe, 0xfe,
|
||||
0x0, 0x0, 0x0, 0xbe, 0xfe, 0x0, 0x0, 0x0, 0xbe, 0xbe, 0x0, 0x0, 0x0, 0xfe, 0xbf, 0x0, 0x0, 0x0, 0xfd, 0x3f, 0x80,
|
||||
0x0, 0x3, 0xfc, 0x2f, 0xe0, 0x0, 0xb, 0xf8, 0xf, 0xfd, 0x0, 0x7f, 0xf0, 0x3, 0xff, 0xff, 0xff, 0xc0, 0x0, 0xbf,
|
||||
0xff, 0xfe, 0x0, 0x0, 0x6, 0xff, 0x90, 0x0,
|
||||
|
||||
/* U+0050 "P" */
|
||||
0xbf, 0xff, 0xf9, 0x0, 0xbf, 0xff, 0xff, 0xd0, 0xbf, 0xff, 0xff, 0xf4, 0xbf, 0x0, 0x7, 0xfc, 0xbf, 0x0, 0x0, 0xfd,
|
||||
0xbf, 0x0, 0x0, 0xfe, 0xbf, 0x0, 0x0, 0xbe, 0xbf, 0x0, 0x0, 0xfe, 0xbf, 0x0, 0x1, 0xfd, 0xbf, 0x0, 0xb, 0xfc, 0xbf,
|
||||
0xff, 0xff, 0xf4, 0xbf, 0xff, 0xff, 0xc0, 0xbf, 0xff, 0xe9, 0x0, 0xbf, 0x0, 0x0, 0x0, 0xbf, 0x0, 0x0, 0x0, 0xbf,
|
||||
0x0, 0x0, 0x0, 0xbf, 0x0, 0x0, 0x0, 0xbf, 0x0, 0x0, 0x0,
|
||||
|
||||
/* U+0051 "Q" */
|
||||
0x0, 0x6, 0xff, 0x90, 0x0, 0x0, 0x2f, 0xff, 0xff, 0x80, 0x0, 0x3f, 0xff, 0xff, 0xfc, 0x0, 0x3f, 0xf4, 0x1, 0xff,
|
||||
0xc0, 0x2f, 0xe0, 0x0, 0xb, 0xf8, 0xf, 0xe0, 0x0, 0x0, 0xff, 0xb, 0xf0, 0x0, 0x0, 0xf, 0xd2, 0xf8, 0x0, 0x0, 0x3,
|
||||
0xf8, 0xfe, 0x0, 0x0, 0x0, 0xbe, 0x3f, 0x80, 0x0, 0x0, 0x2f, 0x8b, 0xe0, 0x0, 0x0, 0xf, 0xe2, 0xfc, 0x0, 0x0, 0x3,
|
||||
0xf4, 0x3f, 0x80, 0x0, 0x3, 0xfc, 0xb, 0xf8, 0x0, 0x2, 0xfe, 0x0, 0xff, 0xd0, 0x7, 0xff, 0x0, 0xf, 0xff, 0xff, 0xff,
|
||||
0x0, 0x0, 0xbf, 0xff, 0xfe, 0x0, 0x0, 0x1, 0xbf, 0xf8, 0x0, 0x0, 0x0, 0x2, 0xff, 0x41, 0xf0, 0x0, 0x0, 0x1f, 0xff,
|
||||
0xfd, 0x0, 0x0, 0x0, 0xff, 0xfd, 0x0, 0x0, 0x0, 0x1, 0xa4, 0x0,
|
||||
|
||||
/* U+0052 "R" */
|
||||
0xbf, 0xff, 0xf9, 0x0, 0xbf, 0xff, 0xff, 0xd0, 0xbf, 0xff, 0xff, 0xf4, 0xbf, 0x0, 0x7, 0xfc, 0xbf, 0x0, 0x0, 0xfd,
|
||||
0xbf, 0x0, 0x0, 0xfe, 0xbf, 0x0, 0x0, 0xbe, 0xbf, 0x0, 0x0, 0xfe, 0xbf, 0x0, 0x1, 0xfd, 0xbf, 0x0, 0xb, 0xfc, 0xbf,
|
||||
0xff, 0xff, 0xf0, 0xbf, 0xff, 0xff, 0xc0, 0xbf, 0xff, 0xff, 0x0, 0xbf, 0x0, 0x3f, 0xc0, 0xbf, 0x0, 0xf, 0xe0, 0xbf,
|
||||
0x0, 0x7, 0xf0, 0xbf, 0x0, 0x2, 0xfc, 0xbf, 0x0, 0x0, 0xfe,
|
||||
|
||||
/* U+0053 "S" */
|
||||
0x0, 0x6f, 0xfe, 0x40, 0x2, 0xff, 0xff, 0xf4, 0xf, 0xff, 0xff, 0xf4, 0x1f, 0xe0, 0x0, 0xb0, 0x2f, 0xc0, 0x0, 0x0,
|
||||
0x2f, 0x80, 0x0, 0x0, 0x2f, 0xd0, 0x0, 0x0, 0xf, 0xfe, 0x40, 0x0, 0x3, 0xff, 0xfe, 0x0, 0x0, 0x6f, 0xff, 0xe0, 0x0,
|
||||
0x1, 0xbf, 0xfc, 0x0, 0x0, 0x2, 0xfd, 0x0, 0x0, 0x0, 0xfd, 0x4, 0x0, 0x0, 0xfd, 0x1f, 0x40, 0x2, 0xfc, 0x3f, 0xff,
|
||||
0xff, 0xf8, 0xf, 0xff, 0xff, 0xe0, 0x0, 0xbf, 0xfe, 0x0,
|
||||
|
||||
/* U+0054 "T" */
|
||||
0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xfd, 0x0, 0xf, 0xe0, 0x0, 0x0, 0xf, 0xe0, 0x0,
|
||||
0x0, 0xf, 0xe0, 0x0, 0x0, 0xf, 0xe0, 0x0, 0x0, 0xf, 0xe0, 0x0, 0x0, 0xf, 0xe0, 0x0, 0x0, 0xf, 0xe0, 0x0, 0x0, 0xf,
|
||||
0xe0, 0x0, 0x0, 0xf, 0xe0, 0x0, 0x0, 0xf, 0xe0, 0x0, 0x0, 0xf, 0xe0, 0x0, 0x0, 0xf, 0xe0, 0x0, 0x0, 0xf, 0xe0, 0x0,
|
||||
0x0, 0xf, 0xe0, 0x0, 0x0, 0xf, 0xe0, 0x0,
|
||||
|
||||
/* U+0055 "U" */
|
||||
0xbe, 0x0, 0x0, 0x3f, 0x2f, 0x80, 0x0, 0xf, 0xcb, 0xe0, 0x0, 0x3, 0xf2, 0xf8, 0x0, 0x0, 0xfc, 0xbe, 0x0, 0x0, 0x3f,
|
||||
0x2f, 0x80, 0x0, 0xf, 0xcb, 0xe0, 0x0, 0x3, 0xf2, 0xf8, 0x0, 0x0, 0xfc, 0xbe, 0x0, 0x0, 0x3f, 0x2f, 0x80, 0x0, 0xf,
|
||||
0xcb, 0xe0, 0x0, 0x3, 0xf2, 0xfc, 0x0, 0x1, 0xfc, 0x7f, 0x0, 0x0, 0xbf, 0xf, 0xe0, 0x0, 0x3f, 0x82, 0xfe, 0x0, 0x7f,
|
||||
0xc0, 0x3f, 0xff, 0xff, 0xd0, 0x3, 0xff, 0xff, 0xd0, 0x0, 0x1b, 0xff, 0x80, 0x0,
|
||||
|
||||
/* U+0056 "V" */
|
||||
0x3f, 0x80, 0x0, 0x0, 0xbf, 0x7, 0xf0, 0x0, 0x0, 0x3f, 0x40, 0xfe, 0x0, 0x0, 0x1f, 0xc0, 0x2f, 0xc0, 0x0, 0xf, 0xe0,
|
||||
0x3, 0xf4, 0x0, 0x7, 0xf0, 0x0, 0xbf, 0x0, 0x2, 0xf8, 0x0, 0x1f, 0xd0, 0x0, 0xfc, 0x0, 0x3, 0xfc, 0x0, 0xbf, 0x0,
|
||||
0x0, 0x7f, 0x0, 0x3f, 0x40, 0x0, 0xf, 0xe0, 0x1f, 0xc0, 0x0, 0x1, 0xfc, 0xf, 0xd0, 0x0, 0x0, 0x3f, 0x87, 0xf0, 0x0,
|
||||
0x0, 0xb, 0xf3, 0xf8, 0x0, 0x0, 0x0, 0xfe, 0xfc, 0x0, 0x0, 0x0, 0x2f, 0xfe, 0x0, 0x0, 0x0, 0x7, 0xff, 0x40, 0x0,
|
||||
0x0, 0x0, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x1f, 0xd0, 0x0, 0x0,
|
||||
|
||||
/* U+0057 "W" */
|
||||
0x3f, 0x40, 0x0, 0x2f, 0x80, 0x0, 0x1f, 0xc3, 0xf8, 0x0, 0x3, 0xfc, 0x0, 0x2, 0xf8, 0x1f, 0xc0, 0x0, 0x7f, 0xd0,
|
||||
0x0, 0x3f, 0x0, 0xfd, 0x0, 0xf, 0xfe, 0x0, 0x7, 0xf0, 0xf, 0xe0, 0x0, 0xff, 0xf0, 0x0, 0xbe, 0x0, 0x7f, 0x0, 0x1f,
|
||||
0xbf, 0x40, 0xf, 0xc0, 0x3, 0xf4, 0x3, 0xf5, 0xf8, 0x1, 0xfc, 0x0, 0x3f, 0x80, 0x3f, 0xf, 0xc0, 0x2f, 0x80, 0x1,
|
||||
0xfc, 0x7, 0xe0, 0xfd, 0x3, 0xf0, 0x0, 0xf, 0xd0, 0xfd, 0x7, 0xe0, 0x7f, 0x0, 0x0, 0xfe, 0xf, 0xc0, 0x3f, 0xb, 0xe0,
|
||||
0x0, 0x7, 0xf2, 0xf8, 0x3, 0xf4, 0xfc, 0x0, 0x0, 0x3f, 0x7f, 0x0, 0x1f, 0x9f, 0xc0, 0x0, 0x3, 0xff, 0xf0, 0x0, 0xff,
|
||||
0xf8, 0x0, 0x0, 0x1f, 0xfe, 0x0, 0xf, 0xff, 0x0, 0x0, 0x0, 0xff, 0xc0, 0x0, 0x7f, 0xf0, 0x0, 0x0, 0xf, 0xfc, 0x0,
|
||||
0x3, 0xfe, 0x0, 0x0, 0x0, 0x7f, 0x80, 0x0, 0x3f, 0xc0, 0x0,
|
||||
|
||||
/* U+0058 "X" */
|
||||
0x3f, 0xc0, 0x0, 0x2f, 0xc1, 0xfe, 0x0, 0x7, 0xf4, 0xb, 0xf4, 0x0, 0xfe, 0x0, 0x3f, 0xc0, 0x3f, 0xc0, 0x0, 0xfe,
|
||||
0xb, 0xf0, 0x0, 0x7, 0xf5, 0xfd, 0x0, 0x0, 0x2f, 0xff, 0x80, 0x0, 0x0, 0xff, 0xf0, 0x0, 0x0, 0x7, 0xfc, 0x0, 0x0,
|
||||
0x0, 0xbf, 0xe0, 0x0, 0x0, 0x1f, 0xff, 0x40, 0x0, 0x3, 0xfb, 0xfc, 0x0, 0x0, 0xbf, 0xf, 0xf0, 0x0, 0x1f, 0xd0, 0x7f,
|
||||
0x80, 0x3, 0xf8, 0x2, 0xfd, 0x0, 0xff, 0x0, 0xf, 0xf0, 0x2f, 0xc0, 0x0, 0x3f, 0x87, 0xf4, 0x0, 0x1, 0xfd,
|
||||
|
||||
/* U+0059 "Y" */
|
||||
0x3f, 0x80, 0x0, 0x3, 0xf0, 0x7f, 0x40, 0x0, 0x3f, 0x80, 0xbf, 0x0, 0x1, 0xfc, 0x0, 0xfe, 0x0, 0xf, 0xd0, 0x1, 0xfc,
|
||||
0x0, 0xbe, 0x0, 0x3, 0xf8, 0x7, 0xf0, 0x0, 0x7, 0xf4, 0x3f, 0x40, 0x0, 0xb, 0xf2, 0xfc, 0x0, 0x0, 0xf, 0xef, 0xc0,
|
||||
0x0, 0x0, 0x1f, 0xfe, 0x0, 0x0, 0x0, 0x3f, 0xf0, 0x0, 0x0, 0x0, 0x7f, 0x40, 0x0, 0x0, 0x0, 0xfd, 0x0, 0x0, 0x0, 0x3,
|
||||
0xf4, 0x0, 0x0, 0x0, 0xf, 0xd0, 0x0, 0x0, 0x0, 0x3f, 0x40, 0x0, 0x0, 0x0, 0xfd, 0x0, 0x0, 0x0, 0x3, 0xf4, 0x0, 0x0,
|
||||
|
||||
/* U+005A "Z" */
|
||||
0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfd, 0xbf, 0xff, 0xff, 0xfc, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0x2f, 0xd0,
|
||||
0x0, 0x0, 0x7f, 0x80, 0x0, 0x1, 0xfe, 0x0, 0x0, 0x3, 0xfc, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0x2f, 0xd0, 0x0, 0x0,
|
||||
0xbf, 0x40, 0x0, 0x1, 0xfe, 0x0, 0x0, 0x7, 0xf8, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0x3f, 0xc0, 0x0, 0x0, 0xbf, 0xff,
|
||||
0xff, 0xfe, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xfe,
|
||||
|
||||
/* U+005B "[" */
|
||||
0xbf, 0xfa, 0xff, 0xeb, 0xfa, 0x6f, 0x80, 0xbe, 0x2, 0xf8, 0xb, 0xe0, 0x2f, 0x80, 0xbe, 0x2, 0xf8, 0xb, 0xe0, 0x2f,
|
||||
0x80, 0xbe, 0x2, 0xf8, 0xb, 0xe0, 0x2f, 0x80, 0xbe, 0x2, 0xf8, 0xb, 0xe0, 0x2f, 0x80, 0xbe, 0x2, 0xfe, 0x9b, 0xff,
|
||||
0xaf, 0xfe,
|
||||
|
||||
/* U+005C "\\" */
|
||||
0x19, 0x0, 0x0, 0xb, 0xc0, 0x0, 0x1, 0xf8, 0x0, 0x0, 0x3f, 0x0, 0x0, 0xb, 0xd0, 0x0, 0x1, 0xf8, 0x0, 0x0, 0x3f, 0x0,
|
||||
0x0, 0xb, 0xd0, 0x0, 0x0, 0xf8, 0x0, 0x0, 0x3f, 0x0, 0x0, 0xb, 0xd0, 0x0, 0x0, 0xf8, 0x0, 0x0, 0x3f, 0x0, 0x0, 0x7,
|
||||
0xd0, 0x0, 0x0, 0xfc, 0x0, 0x0, 0x3f, 0x0, 0x0, 0x7, 0xd0, 0x0, 0x0, 0xfc, 0x0, 0x0, 0x2f, 0x0, 0x0, 0x7, 0xe0, 0x0,
|
||||
0x0, 0xfc, 0x0, 0x0, 0x2f, 0x0, 0x0, 0x7, 0xe0, 0x0, 0x0, 0xfc, 0x0, 0x0, 0x2f, 0x40,
|
||||
|
||||
/* U+005D "]" */
|
||||
0xbf, 0xfa, 0xff, 0xe6, 0xbf, 0x80, 0xbe, 0x2, 0xf8, 0xb, 0xe0, 0x2f, 0x80, 0xbe, 0x2, 0xf8, 0xb, 0xe0, 0x2f, 0x80,
|
||||
0xbe, 0x2, 0xf8, 0xb, 0xe0, 0x2f, 0x80, 0xbe, 0x2, 0xf8, 0xb, 0xe0, 0x2f, 0x80, 0xbe, 0x2, 0xf9, 0xaf, 0xeb, 0xff,
|
||||
0xaf, 0xfe,
|
||||
|
||||
/* U+005E "^" */
|
||||
0x0, 0x3f, 0x0, 0x0, 0x1f, 0xe0, 0x0, 0xb, 0xfc, 0x0, 0x3, 0xdf, 0x40, 0x2, 0xf2, 0xf0, 0x0, 0xf8, 0x3d, 0x0, 0x7c,
|
||||
0xb, 0xc0, 0x3e, 0x1, 0xf0, 0xf, 0x40, 0x3e, 0xb, 0xc0, 0xb, 0xc3, 0xd0, 0x0, 0xf4,
|
||||
|
||||
/* U+005F "_" */
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0,
|
||||
|
||||
/* U+0060 "`" */
|
||||
0x1a, 0x40, 0xf, 0xd0, 0x2, 0xf4, 0x0, 0x7d,
|
||||
|
||||
/* U+0061 "a" */
|
||||
0x6, 0xff, 0xd0, 0xf, 0xff, 0xff, 0x3, 0xfe, 0xbf, 0xf0, 0x60, 0x1, 0xfd, 0x0, 0x0, 0x2f, 0x80, 0x0, 0xb, 0xe0,
|
||||
0xbf, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xbf, 0x0, 0x2f, 0xff, 0x40, 0xb, 0xff, 0xd0, 0x3, 0xfd, 0xfd, 0x7, 0xff, 0x3f,
|
||||
0xff, 0xef, 0xc1, 0xff, 0x97, 0xf0,
|
||||
|
||||
/* U+0062 "b" */
|
||||
0x54, 0x0, 0x0, 0x3, 0xf4, 0x0, 0x0, 0xf, 0xd0, 0x0, 0x0, 0x3f, 0x40, 0x0, 0x0, 0xfd, 0x0, 0x0, 0x3, 0xf4, 0x0, 0x0,
|
||||
0xf, 0xd2, 0xff, 0x80, 0x3f, 0xbf, 0xff, 0xd0, 0xff, 0xff, 0xff, 0xd3, 0xff, 0x0, 0x7f, 0xcf, 0xf0, 0x0, 0x3f, 0x7f,
|
||||
0x80, 0x0, 0xbe, 0xfd, 0x0, 0x1, 0xff, 0xf4, 0x0, 0x7, 0xff, 0xe0, 0x0, 0x2f, 0xbf, 0xc0, 0x0, 0xfd, 0xff, 0xc0,
|
||||
0x1f, 0xf3, 0xff, 0xff, 0xff, 0x4f, 0xef, 0xff, 0xf4, 0x3f, 0xb, 0xfe, 0x0,
|
||||
|
||||
/* U+0063 "c" */
|
||||
0x0, 0x1f, 0xfd, 0x0, 0x7, 0xff, 0xff, 0x0, 0x7f, 0xff, 0xff, 0x3, 0xfc, 0x1, 0xf8, 0x2f, 0xc0, 0x0, 0x40, 0xfd,
|
||||
0x0, 0x0, 0x3, 0xf4, 0x0, 0x0, 0xf, 0xd0, 0x0, 0x0, 0x3f, 0x80, 0x0, 0x0, 0xbf, 0x0, 0x1, 0x0, 0xff, 0x0, 0x7f, 0x1,
|
||||
0xff, 0xff, 0xfc, 0x1, 0xff, 0xff, 0xc0, 0x0, 0x7f, 0xf4, 0x0,
|
||||
|
||||
/* U+0064 "d" */
|
||||
0x0, 0x0, 0x0, 0x15, 0x0, 0x0, 0x0, 0xbe, 0x0, 0x0, 0x0, 0xbe, 0x0, 0x0, 0x0, 0xbe, 0x0, 0x0, 0x0, 0xbe, 0x0, 0x0,
|
||||
0x0, 0xbe, 0x0, 0x2f, 0xf8, 0xbe, 0x2, 0xff, 0xff, 0xbe, 0xb, 0xff, 0xff, 0xfe, 0xf, 0xf0, 0x7, 0xfe, 0x2f, 0xc0,
|
||||
0x0, 0xfe, 0x3f, 0x80, 0x0, 0xbe, 0x3f, 0x40, 0x0, 0xbe, 0x3f, 0x40, 0x0, 0xbe, 0x3f, 0x80, 0x0, 0xbe, 0x2f, 0xc0,
|
||||
0x0, 0xfe, 0xf, 0xf0, 0x7, 0xfe, 0xb, 0xff, 0xff, 0xfe, 0x1, 0xff, 0xff, 0xbe, 0x0, 0x2f, 0xf8, 0x7e,
|
||||
|
||||
/* U+0065 "e" */
|
||||
0x0, 0x2f, 0xf9, 0x0, 0x1, 0xff, 0xff, 0x80, 0x7, 0xfe, 0xbf, 0xe0, 0xf, 0xe0, 0x7, 0xf4, 0x2f, 0x80, 0x1, 0xfc,
|
||||
0x3f, 0x40, 0x0, 0xfc, 0x3f, 0xff, 0xff, 0xfc, 0x3f, 0xff, 0xff, 0xfc, 0x3f, 0x40, 0x0, 0x0, 0x2f, 0xc0, 0x0, 0x0,
|
||||
0xf, 0xf0, 0x1, 0xc0, 0x7, 0xff, 0xff, 0xf0, 0x1, 0xff, 0xff, 0xd0, 0x0, 0x1f, 0xfe, 0x0,
|
||||
|
||||
/* U+0066 "f" */
|
||||
0x0, 0x1a, 0x90, 0x3, 0xff, 0xd0, 0x2f, 0xff, 0x0, 0xfd, 0x4, 0x7, 0xf0, 0x0, 0x1f, 0x80, 0xb, 0xff, 0xfe, 0x2f,
|
||||
0xff, 0xf8, 0x6f, 0xfa, 0x90, 0x1f, 0xc0, 0x0, 0x7f, 0x0, 0x1, 0xfc, 0x0, 0x7, 0xf0, 0x0, 0x1f, 0xc0, 0x0, 0x7f,
|
||||
0x0, 0x1, 0xfc, 0x0, 0x7, 0xf0, 0x0, 0x1f, 0xc0, 0x0, 0x7f, 0x0, 0x1, 0xfc, 0x0,
|
||||
|
||||
/* U+0067 "g" */
|
||||
0x0, 0x2f, 0xf8, 0x3f, 0x2, 0xff, 0xff, 0xbf, 0xb, 0xfe, 0xaf, 0xff, 0x1f, 0xe0, 0x2, 0xff, 0x2f, 0xc0, 0x0, 0xff,
|
||||
0x3f, 0x40, 0x0, 0x7f, 0x3f, 0x40, 0x0, 0x7f, 0x3f, 0x40, 0x0, 0x7f, 0x2f, 0xc0, 0x0, 0xff, 0x1f, 0xf0, 0x3, 0xff,
|
||||
0xb, 0xff, 0xff, 0xff, 0x2, 0xff, 0xff, 0xbf, 0x0, 0x2f, 0xf8, 0x7f, 0x0, 0x0, 0x0, 0xbf, 0x0, 0x0, 0x0, 0xfe, 0x7,
|
||||
0x80, 0x2, 0xfc, 0xf, 0xff, 0xbf, 0xf8, 0xb, 0xff, 0xff, 0xe0, 0x0, 0x6f, 0xfe, 0x0,
|
||||
|
||||
/* U+0068 "h" */
|
||||
0x0, 0x0, 0x0, 0xf, 0xd0, 0x0, 0x0, 0xfd, 0x0, 0x0, 0xf, 0xd0, 0x0, 0x0, 0xfd, 0x0, 0x0, 0xf, 0xd0, 0x0, 0x0, 0xfd,
|
||||
0x2f, 0xf8, 0xf, 0xef, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xcf, 0xfc, 0x2, 0xfd, 0xff, 0x0, 0xf, 0xef, 0xe0, 0x0, 0xbf,
|
||||
0xfd, 0x0, 0x7, 0xff, 0xd0, 0x0, 0x7f, 0xfd, 0x0, 0x7, 0xff, 0xd0, 0x0, 0x7f, 0xfd, 0x0, 0x7, 0xff, 0xd0, 0x0, 0x7f,
|
||||
0xfd, 0x0, 0x7, 0xff, 0xd0, 0x0, 0x7f,
|
||||
|
||||
/* U+0069 "i" */
|
||||
0x2f, 0xf, 0xf3, 0xf8, 0x78, 0x0, 0x0, 0x3, 0xf4, 0xfd, 0x3f, 0x4f, 0xd3, 0xf4, 0xfd, 0x3f, 0x4f, 0xd3, 0xf4, 0xfd,
|
||||
0x3f, 0x4f, 0xd3, 0xf4, 0xfd,
|
||||
|
||||
/* U+006A "j" */
|
||||
0x0, 0x1f, 0x40, 0xf, 0xf0, 0x3, 0xfc, 0x0, 0x7c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xf8, 0x0, 0xbe, 0x0, 0x2f, 0x80,
|
||||
0xb, 0xe0, 0x2, 0xf8, 0x0, 0xbe, 0x0, 0x2f, 0x80, 0xb, 0xe0, 0x2, 0xf8, 0x0, 0xbe, 0x0, 0x2f, 0x80, 0xb, 0xe0, 0x2,
|
||||
0xf8, 0x0, 0xbe, 0x0, 0x3f, 0x80, 0xf, 0xd3, 0xef, 0xf0, 0xff, 0xf4, 0x2f, 0xe4, 0x0,
|
||||
|
||||
/* U+006B "k" */
|
||||
0x0, 0x0, 0x0, 0x3, 0xf4, 0x0, 0x0, 0xf, 0xd0, 0x0, 0x0, 0x3f, 0x40, 0x0, 0x0, 0xfd, 0x0, 0x0, 0x3, 0xf4, 0x0, 0x0,
|
||||
0xf, 0xd0, 0x1, 0xfe, 0x3f, 0x40, 0x1f, 0xe0, 0xfd, 0x2, 0xfe, 0x3, 0xf4, 0x2f, 0xe0, 0xf, 0xd2, 0xfe, 0x0, 0x3f,
|
||||
0x6f, 0xe0, 0x0, 0xff, 0xff, 0x80, 0x3, 0xff, 0xff, 0x40, 0xf, 0xfd, 0xff, 0x40, 0x3f, 0xd0, 0xff, 0x0, 0xfd, 0x0,
|
||||
0xff, 0x3, 0xf4, 0x1, 0xfe, 0xf, 0xd0, 0x2, 0xfd, 0x3f, 0x40, 0x3, 0xfc,
|
||||
|
||||
/* U+006C "l" */
|
||||
0x0, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd,
|
||||
0xfd,
|
||||
|
||||
/* U+006D "m" */
|
||||
0xfc, 0x2f, 0xf4, 0x6, 0xff, 0x40, 0xfe, 0xff, 0xff, 0x2f, 0xff, 0xe0, 0xff, 0xfa, 0xff, 0xff, 0xaf, 0xf8, 0xff,
|
||||
0x80, 0x3f, 0xf8, 0x3, 0xfc, 0xff, 0x0, 0xf, 0xf0, 0x0, 0xfc, 0xfe, 0x0, 0xf, 0xe0, 0x0, 0xfd, 0xfd, 0x0, 0xf, 0xd0,
|
||||
0x0, 0xfd, 0xfd, 0x0, 0xf, 0xd0, 0x0, 0xfd, 0xfd, 0x0, 0xf, 0xd0, 0x0, 0xfd, 0xfd, 0x0, 0xf, 0xd0, 0x0, 0xfd, 0xfd,
|
||||
0x0, 0xf, 0xd0, 0x0, 0xfd, 0xfd, 0x0, 0xf, 0xd0, 0x0, 0xfd, 0xfd, 0x0, 0xf, 0xd0, 0x0, 0xfd, 0xfd, 0x0, 0xf, 0xd0,
|
||||
0x0, 0xfd,
|
||||
|
||||
/* U+006E "n" */
|
||||
0xfc, 0x2f, 0xf8, 0xf, 0xef, 0xff, 0xf0, 0xff, 0xfa, 0xff, 0xcf, 0xf8, 0x1, 0xfd, 0xff, 0x0, 0xf, 0xef, 0xe0, 0x0,
|
||||
0xbf, 0xfd, 0x0, 0x7, 0xff, 0xd0, 0x0, 0x7f, 0xfd, 0x0, 0x7, 0xff, 0xd0, 0x0, 0x7f, 0xfd, 0x0, 0x7, 0xff, 0xd0, 0x0,
|
||||
0x7f, 0xfd, 0x0, 0x7, 0xff, 0xd0, 0x0, 0x7f,
|
||||
|
||||
/* U+006F "o" */
|
||||
0x0, 0x2f, 0xf9, 0x0, 0x1, 0xff, 0xff, 0xc0, 0x7, 0xff, 0xff, 0xf0, 0xf, 0xf0, 0x7, 0xfc, 0x2f, 0xc0, 0x0, 0xfd,
|
||||
0x3f, 0x40, 0x0, 0xbe, 0x3f, 0x40, 0x0, 0xbf, 0x3f, 0x40, 0x0, 0xbe, 0x3f, 0x80, 0x0, 0xbe, 0x2f, 0xc0, 0x0, 0xfd,
|
||||
0xf, 0xf0, 0x7, 0xfc, 0x7, 0xff, 0xff, 0xf0, 0x1, 0xff, 0xff, 0xc0, 0x0, 0x1f, 0xf9, 0x0,
|
||||
|
||||
/* U+0070 "p" */
|
||||
0xfc, 0x2f, 0xf8, 0x3, 0xfb, 0xff, 0xfd, 0xf, 0xff, 0xff, 0xfd, 0x3f, 0xf0, 0x7, 0xfc, 0xff, 0x0, 0x3, 0xf7, 0xf8,
|
||||
0x0, 0xb, 0xef, 0xd0, 0x0, 0x1f, 0xff, 0x40, 0x0, 0x7f, 0xfe, 0x0, 0x2, 0xfb, 0xfc, 0x0, 0xf, 0xdf, 0xfc, 0x1, 0xff,
|
||||
0x3f, 0xff, 0xff, 0xf4, 0xfe, 0xff, 0xff, 0x43, 0xf4, 0xbf, 0xe0, 0xf, 0xd0, 0x0, 0x0, 0x3f, 0x40, 0x0, 0x0, 0xfd,
|
||||
0x0, 0x0, 0x3, 0xf4, 0x0, 0x0, 0xf, 0xd0, 0x0, 0x0, 0x0,
|
||||
|
||||
/* U+0071 "q" */
|
||||
0x0, 0x2f, 0xf8, 0x7e, 0x2, 0xff, 0xff, 0xbe, 0xb, 0xff, 0xff, 0xfe, 0xf, 0xf0, 0x7, 0xfe, 0x2f, 0xc0, 0x0, 0xfe,
|
||||
0x3f, 0x40, 0x0, 0xbe, 0x3f, 0x40, 0x0, 0xbe, 0x3f, 0x40, 0x0, 0xbe, 0x3f, 0x80, 0x0, 0xbe, 0x2f, 0xc0, 0x0, 0xfe,
|
||||
0xf, 0xf0, 0x7, 0xfe, 0xb, 0xff, 0xff, 0xfe, 0x2, 0xff, 0xff, 0xbe, 0x0, 0x2f, 0xf8, 0xbe, 0x0, 0x0, 0x0, 0xbe, 0x0,
|
||||
0x0, 0x0, 0xbe, 0x0, 0x0, 0x0, 0xbe, 0x0, 0x0, 0x0, 0xbe, 0x0, 0x0, 0x0, 0xbe,
|
||||
|
||||
/* U+0072 "r" */
|
||||
0xfc, 0x2f, 0x3f, 0xbf, 0xcf, 0xff, 0xf3, 0xff, 0x40, 0xff, 0x0, 0x3f, 0x80, 0xf, 0xd0, 0x3, 0xf4, 0x0, 0xfd, 0x0,
|
||||
0x3f, 0x40, 0xf, 0xd0, 0x3, 0xf4, 0x0, 0xfd, 0x0, 0x3f, 0x40, 0x0,
|
||||
|
||||
/* U+0073 "s" */
|
||||
0x1, 0xbf, 0xf8, 0x2, 0xff, 0xff, 0xc2, 0xff, 0xaf, 0xe0, 0xfd, 0x0, 0x10, 0x3f, 0x0, 0x0, 0xf, 0xf9, 0x0, 0x1,
|
||||
0xff, 0xff, 0x40, 0xb, 0xff, 0xfc, 0x0, 0x5, 0xbf, 0x80, 0x0, 0xb, 0xe1, 0x80, 0x2, 0xf8, 0xff, 0xab, 0xfd, 0x3f,
|
||||
0xff, 0xfd, 0x1, 0xbf, 0xf8, 0x0,
|
||||
|
||||
/* U+0074 "t" */
|
||||
0x7, 0xf0, 0x0, 0x1f, 0xc0, 0x0, 0x7f, 0x0, 0x2f, 0xff, 0xf8, 0xbf, 0xff, 0xe1, 0xbf, 0xea, 0x40, 0x7f, 0x0, 0x1,
|
||||
0xfc, 0x0, 0x7, 0xf0, 0x0, 0x1f, 0xc0, 0x0, 0x7f, 0x0, 0x1, 0xfc, 0x0, 0x7, 0xf0, 0x0, 0x1f, 0xc0, 0x0, 0x3f, 0xef,
|
||||
0x0, 0x7f, 0xfd, 0x0, 0x7f, 0xe0,
|
||||
|
||||
/* U+0075 "u" */
|
||||
0xfd, 0x0, 0xb, 0xef, 0xd0, 0x0, 0xbe, 0xfd, 0x0, 0xb, 0xef, 0xd0, 0x0, 0xbe, 0xfd, 0x0, 0xb, 0xef, 0xd0, 0x0, 0xbe,
|
||||
0xfd, 0x0, 0xb, 0xef, 0xd0, 0x0, 0xbe, 0xfd, 0x0, 0xf, 0xef, 0xe0, 0x1, 0xfe, 0xbf, 0x40, 0x7f, 0xe3, 0xff, 0xff,
|
||||
0xfe, 0x1f, 0xff, 0xfb, 0xe0, 0x2f, 0xf4, 0xbe,
|
||||
|
||||
/* U+0076 "v" */
|
||||
0x3f, 0x40, 0x0, 0x3f, 0x7, 0xf0, 0x0, 0x2f, 0x40, 0xfd, 0x0, 0xf, 0xc0, 0x2f, 0x80, 0x7, 0xe0, 0x3, 0xf0, 0x3,
|
||||
0xf0, 0x0, 0xfe, 0x1, 0xfc, 0x0, 0x1f, 0xc0, 0xfd, 0x0, 0x3, 0xf4, 0x3f, 0x0, 0x0, 0xbf, 0x2f, 0x80, 0x0, 0xf, 0xdf,
|
||||
0xc0, 0x0, 0x2, 0xff, 0xe0, 0x0, 0x0, 0x3f, 0xf0, 0x0, 0x0, 0xf, 0xfc, 0x0, 0x0, 0x1, 0xfd, 0x0, 0x0,
|
||||
|
||||
/* U+0077 "w" */
|
||||
0xbd, 0x0, 0xb, 0xe0, 0x0, 0x7e, 0x7e, 0x0, 0xf, 0xf0, 0x0, 0xbd, 0x3f, 0x0, 0x1f, 0xf4, 0x0, 0xfc, 0x2f, 0x40,
|
||||
0x2f, 0xf8, 0x1, 0xf8, 0x1f, 0xc0, 0x3f, 0xfc, 0x2, 0xf0, 0xf, 0xc0, 0x7e, 0xbd, 0x3, 0xf0, 0xb, 0xd0, 0xfc, 0x3e,
|
||||
0x7, 0xd0, 0x3, 0xf0, 0xfc, 0x3f, 0xf, 0xc0, 0x3, 0xf1, 0xf4, 0x2f, 0x4f, 0x80, 0x1, 0xfb, 0xf0, 0xf, 0xef, 0x40,
|
||||
0x0, 0xff, 0xe0, 0xf, 0xff, 0x0, 0x0, 0xbf, 0xd0, 0x7, 0xfe, 0x0, 0x0, 0x7f, 0xc0, 0x3, 0xfc, 0x0, 0x0, 0x3f, 0x80,
|
||||
0x2, 0xfc, 0x0,
|
||||
|
||||
/* U+0078 "x" */
|
||||
0x3f, 0x40, 0x7, 0xf0, 0x7f, 0x0, 0x3f, 0x40, 0xbf, 0x3, 0xf8, 0x0, 0xfe, 0x2f, 0x80, 0x0, 0xff, 0xfc, 0x0, 0x1,
|
||||
0xff, 0xc0, 0x0, 0x2, 0xfd, 0x0, 0x0, 0xf, 0xf8, 0x0, 0x0, 0xbf, 0xf4, 0x0, 0x7, 0xfb, 0xf0, 0x0, 0x3f, 0x4b, 0xf0,
|
||||
0x3, 0xf8, 0xf, 0xe0, 0x2f, 0xc0, 0xf, 0xe1, 0xfc, 0x0, 0x1f, 0xd0,
|
||||
|
||||
/* U+0079 "y" */
|
||||
0x3f, 0x40, 0x0, 0x3f, 0x7, 0xf0, 0x0, 0x2f, 0x40, 0xfd, 0x0, 0xf, 0xc0, 0x2f, 0x80, 0x7, 0xe0, 0x3, 0xf0, 0x3,
|
||||
0xf0, 0x0, 0xbe, 0x1, 0xf8, 0x0, 0x1f, 0xc0, 0xfd, 0x0, 0x3, 0xf4, 0x3f, 0x0, 0x0, 0x7f, 0x2f, 0x40, 0x0, 0xf, 0xdf,
|
||||
0xc0, 0x0, 0x2, 0xff, 0xe0, 0x0, 0x0, 0x3f, 0xf0, 0x0, 0x0, 0xb, 0xf8, 0x0, 0x0, 0x0, 0xfc, 0x0, 0x0, 0x0, 0x7f,
|
||||
0x0, 0x0, 0x0, 0x3f, 0x40, 0x0, 0x3f, 0xbf, 0xc0, 0x0, 0x1f, 0xff, 0xc0, 0x0, 0x1, 0xbf, 0x80, 0x0, 0x0,
|
||||
|
||||
/* U+007A "z" */
|
||||
0x3f, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xe2, 0xaa, 0xaf, 0xf4, 0x0, 0x3, 0xf8, 0x0, 0x3, 0xf8, 0x0, 0x2, 0xfc, 0x0,
|
||||
0x2, 0xfc, 0x0, 0x1, 0xfd, 0x0, 0x0, 0xfd, 0x0, 0x0, 0xfe, 0x0, 0x0, 0xff, 0x0, 0x0, 0xbf, 0xaa, 0xaa, 0x3f, 0xff,
|
||||
0xff, 0xcf, 0xff, 0xff, 0xf0,
|
||||
|
||||
/* U+007B "{" */
|
||||
0x0, 0xbf, 0x0, 0xff, 0xc0, 0x7f, 0xe0, 0x2f, 0xc0, 0xb, 0xe0, 0x2, 0xf8, 0x0, 0xbe, 0x0, 0x2f, 0x80, 0xb, 0xe0,
|
||||
0x2, 0xf8, 0x6, 0xfe, 0x2, 0xfe, 0x0, 0xbf, 0xd0, 0x3, 0xf8, 0x0, 0xbe, 0x0, 0x2f, 0x80, 0xb, 0xe0, 0x2, 0xf8, 0x0,
|
||||
0xbe, 0x0, 0x2f, 0x80, 0x7, 0xf0, 0x1, 0xff, 0x80, 0x2f, 0xf0, 0x2, 0xfc,
|
||||
|
||||
/* U+007C "|" */
|
||||
0x14, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd,
|
||||
0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd,
|
||||
|
||||
/* U+007D "}" */
|
||||
0xbf, 0x40, 0x2f, 0xf4, 0x6, 0xff, 0x0, 0x1f, 0xc0, 0x3, 0xf0, 0x0, 0xfc, 0x0, 0x3f, 0x0, 0xf, 0xc0, 0x3, 0xf0, 0x0,
|
||||
0xfd, 0x0, 0x3f, 0xe0, 0x3, 0xfc, 0x2, 0xff, 0x0, 0xfd, 0x0, 0x3f, 0x0, 0xf, 0xc0, 0x3, 0xf0, 0x0, 0xfc, 0x0, 0x3f,
|
||||
0x0, 0xf, 0xc0, 0x7, 0xf0, 0x1b, 0xfc, 0xb, 0xfd, 0x2, 0xfd, 0x0,
|
||||
|
||||
/* U+007E "~" */
|
||||
0xb, 0xe0, 0x3, 0xcb, 0xff, 0x41, 0xf3, 0xeb, 0xfa, 0xf9, 0xf0, 0x3f, 0xfc, 0xb8, 0x2, 0xfc, 0x0};
|
||||
|
||||
/*---------------------
|
||||
* GLYPH DESCRIPTION
|
||||
*--------------------*/
|
||||
|
||||
static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = {
|
||||
{.bitmap_index = 0, .adv_w = 0, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0} /* id = 0 reserved */,
|
||||
{.bitmap_index = 0, .adv_w = 115, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0},
|
||||
{.bitmap_index = 0, .adv_w = 116, .box_w = 5, .box_h = 18, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 23, .adv_w = 172, .box_w = 9, .box_h = 8, .ofs_x = 1, .ofs_y = 10},
|
||||
{.bitmap_index = 41, .adv_w = 296, .box_w = 18, .box_h = 18, .ofs_x = 0, .ofs_y = 0},
|
||||
{.bitmap_index = 122, .adv_w = 262, .box_w = 16, .box_h = 25, .ofs_x = 0, .ofs_y = -3},
|
||||
{.bitmap_index = 222, .adv_w = 358, .box_w = 22, .box_h = 18, .ofs_x = 0, .ofs_y = 0},
|
||||
{.bitmap_index = 321, .adv_w = 294, .box_w = 17, .box_h = 19, .ofs_x = 1, .ofs_y = -1},
|
||||
{.bitmap_index = 402, .adv_w = 92, .box_w = 4, .box_h = 8, .ofs_x = 1, .ofs_y = 10},
|
||||
{.bitmap_index = 410, .adv_w = 144, .box_w = 7, .box_h = 25, .ofs_x = 2, .ofs_y = -5},
|
||||
{.bitmap_index = 454, .adv_w = 145, .box_w = 7, .box_h = 25, .ofs_x = 0, .ofs_y = -5},
|
||||
{.bitmap_index = 498, .adv_w = 173, .box_w = 11, .box_h = 10, .ofs_x = 0, .ofs_y = 9},
|
||||
{.bitmap_index = 526, .adv_w = 245, .box_w = 13, .box_h = 12, .ofs_x = 1, .ofs_y = 3},
|
||||
{.bitmap_index = 565, .adv_w = 102, .box_w = 5, .box_h = 9, .ofs_x = 1, .ofs_y = -4},
|
||||
{.bitmap_index = 577, .adv_w = 160, .box_w = 8, .box_h = 3, .ofs_x = 1, .ofs_y = 6},
|
||||
{.bitmap_index = 583, .adv_w = 102, .box_w = 5, .box_h = 5, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 590, .adv_w = 154, .box_w = 12, .box_h = 25, .ofs_x = -1, .ofs_y = -3},
|
||||
{.bitmap_index = 665, .adv_w = 280, .box_w = 16, .box_h = 18, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 737, .adv_w = 158, .box_w = 8, .box_h = 18, .ofs_x = 0, .ofs_y = 0},
|
||||
{.bitmap_index = 773, .adv_w = 242, .box_w = 15, .box_h = 18, .ofs_x = 0, .ofs_y = 0},
|
||||
{.bitmap_index = 841, .adv_w = 242, .box_w = 15, .box_h = 18, .ofs_x = 0, .ofs_y = 0},
|
||||
{.bitmap_index = 909, .adv_w = 282, .box_w = 18, .box_h = 18, .ofs_x = 0, .ofs_y = 0},
|
||||
{.bitmap_index = 990, .adv_w = 243, .box_w = 15, .box_h = 18, .ofs_x = 0, .ofs_y = 0},
|
||||
{.bitmap_index = 1058, .adv_w = 261, .box_w = 15, .box_h = 18, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 1126, .adv_w = 253, .box_w = 15, .box_h = 18, .ofs_x = 0, .ofs_y = 0},
|
||||
{.bitmap_index = 1194, .adv_w = 271, .box_w = 15, .box_h = 18, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 1262, .adv_w = 261, .box_w = 16, .box_h = 18, .ofs_x = 0, .ofs_y = 0},
|
||||
{.bitmap_index = 1334, .adv_w = 102, .box_w = 5, .box_h = 14, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 1352, .adv_w = 102, .box_w = 5, .box_h = 18, .ofs_x = 1, .ofs_y = -4},
|
||||
{.bitmap_index = 1375, .adv_w = 245, .box_w = 13, .box_h = 13, .ofs_x = 1, .ofs_y = 3},
|
||||
{.bitmap_index = 1418, .adv_w = 245, .box_w = 13, .box_h = 9, .ofs_x = 1, .ofs_y = 5},
|
||||
{.bitmap_index = 1448, .adv_w = 245, .box_w = 13, .box_h = 13, .ofs_x = 1, .ofs_y = 3},
|
||||
{.bitmap_index = 1491, .adv_w = 242, .box_w = 14, .box_h = 18, .ofs_x = 0, .ofs_y = 0},
|
||||
{.bitmap_index = 1554, .adv_w = 430, .box_w = 25, .box_h = 23, .ofs_x = 1, .ofs_y = -5},
|
||||
{.bitmap_index = 1698, .adv_w = 312, .box_w = 21, .box_h = 18, .ofs_x = -1, .ofs_y = 0},
|
||||
{.bitmap_index = 1793, .adv_w = 317, .box_w = 17, .box_h = 18, .ofs_x = 2, .ofs_y = 0},
|
||||
{.bitmap_index = 1870, .adv_w = 299, .box_w = 18, .box_h = 18, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 1951, .adv_w = 344, .box_w = 19, .box_h = 18, .ofs_x = 2, .ofs_y = 0},
|
||||
{.bitmap_index = 2037, .adv_w = 279, .box_w = 15, .box_h = 18, .ofs_x = 2, .ofs_y = 0},
|
||||
{.bitmap_index = 2105, .adv_w = 265, .box_w = 14, .box_h = 18, .ofs_x = 2, .ofs_y = 0},
|
||||
{.bitmap_index = 2168, .adv_w = 321, .box_w = 18, .box_h = 18, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 2249, .adv_w = 337, .box_w = 17, .box_h = 18, .ofs_x = 2, .ofs_y = 0},
|
||||
{.bitmap_index = 2326, .adv_w = 133, .box_w = 4, .box_h = 18, .ofs_x = 2, .ofs_y = 0},
|
||||
{.bitmap_index = 2344, .adv_w = 219, .box_w = 13, .box_h = 18, .ofs_x = -1, .ofs_y = 0},
|
||||
{.bitmap_index = 2403, .adv_w = 303, .box_w = 18, .box_h = 18, .ofs_x = 2, .ofs_y = 0},
|
||||
{.bitmap_index = 2484, .adv_w = 249, .box_w = 14, .box_h = 18, .ofs_x = 2, .ofs_y = 0},
|
||||
{.bitmap_index = 2547, .adv_w = 397, .box_w = 21, .box_h = 18, .ofs_x = 2, .ofs_y = 0},
|
||||
{.bitmap_index = 2642, .adv_w = 337, .box_w = 17, .box_h = 18, .ofs_x = 2, .ofs_y = 0},
|
||||
{.bitmap_index = 2719, .adv_w = 350, .box_w = 20, .box_h = 18, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 2809, .adv_w = 302, .box_w = 16, .box_h = 18, .ofs_x = 2, .ofs_y = 0},
|
||||
{.bitmap_index = 2881, .adv_w = 350, .box_w = 21, .box_h = 22, .ofs_x = 1, .ofs_y = -4},
|
||||
{.bitmap_index = 2997, .adv_w = 304, .box_w = 16, .box_h = 18, .ofs_x = 2, .ofs_y = 0},
|
||||
{.bitmap_index = 3069, .adv_w = 262, .box_w = 16, .box_h = 18, .ofs_x = 0, .ofs_y = 0},
|
||||
{.bitmap_index = 3141, .adv_w = 250, .box_w = 16, .box_h = 18, .ofs_x = 0, .ofs_y = 0},
|
||||
{.bitmap_index = 3213, .adv_w = 328, .box_w = 17, .box_h = 18, .ofs_x = 2, .ofs_y = 0},
|
||||
{.bitmap_index = 3290, .adv_w = 303, .box_w = 21, .box_h = 18, .ofs_x = -1, .ofs_y = 0},
|
||||
{.bitmap_index = 3385, .adv_w = 476, .box_w = 30, .box_h = 18, .ofs_x = 0, .ofs_y = 0},
|
||||
{.bitmap_index = 3520, .adv_w = 288, .box_w = 18, .box_h = 18, .ofs_x = 0, .ofs_y = 0},
|
||||
{.bitmap_index = 3601, .adv_w = 275, .box_w = 19, .box_h = 18, .ofs_x = -1, .ofs_y = 0},
|
||||
{.bitmap_index = 3687, .adv_w = 276, .box_w = 16, .box_h = 18, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 3759, .adv_w = 146, .box_w = 7, .box_h = 24, .ofs_x = 2, .ofs_y = -5},
|
||||
{.bitmap_index = 3801, .adv_w = 154, .box_w = 13, .box_h = 25, .ofs_x = -2, .ofs_y = -3},
|
||||
{.bitmap_index = 3883, .adv_w = 146, .box_w = 7, .box_h = 24, .ofs_x = 0, .ofs_y = -5},
|
||||
{.bitmap_index = 3925, .adv_w = 246, .box_w = 13, .box_h = 11, .ofs_x = 1, .ofs_y = 4},
|
||||
{.bitmap_index = 3961, .adv_w = 208, .box_w = 13, .box_h = 2, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 3968, .adv_w = 250, .box_w = 8, .box_h = 4, .ofs_x = 2, .ofs_y = 16},
|
||||
{.bitmap_index = 3976, .adv_w = 253, .box_w = 13, .box_h = 14, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 4022, .adv_w = 285, .box_w = 15, .box_h = 20, .ofs_x = 2, .ofs_y = 0},
|
||||
{.bitmap_index = 4097, .adv_w = 242, .box_w = 15, .box_h = 14, .ofs_x = 0, .ofs_y = 0},
|
||||
{.bitmap_index = 4150, .adv_w = 286, .box_w = 16, .box_h = 20, .ofs_x = 0, .ofs_y = 0},
|
||||
{.bitmap_index = 4230, .adv_w = 259, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = 0},
|
||||
{.bitmap_index = 4286, .adv_w = 154, .box_w = 11, .box_h = 20, .ofs_x = 0, .ofs_y = 0},
|
||||
{.bitmap_index = 4341, .adv_w = 289, .box_w = 16, .box_h = 19, .ofs_x = 0, .ofs_y = -5},
|
||||
{.bitmap_index = 4417, .adv_w = 285, .box_w = 14, .box_h = 20, .ofs_x = 2, .ofs_y = 0},
|
||||
{.bitmap_index = 4487, .adv_w = 120, .box_w = 5, .box_h = 20, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 4512, .adv_w = 123, .box_w = 9, .box_h = 25, .ofs_x = -3, .ofs_y = -5},
|
||||
{.bitmap_index = 4569, .adv_w = 264, .box_w = 15, .box_h = 20, .ofs_x = 2, .ofs_y = 0},
|
||||
{.bitmap_index = 4644, .adv_w = 120, .box_w = 4, .box_h = 20, .ofs_x = 2, .ofs_y = 0},
|
||||
{.bitmap_index = 4664, .adv_w = 438, .box_w = 24, .box_h = 14, .ofs_x = 2, .ofs_y = 0},
|
||||
{.bitmap_index = 4748, .adv_w = 285, .box_w = 14, .box_h = 14, .ofs_x = 2, .ofs_y = 0},
|
||||
{.bitmap_index = 4797, .adv_w = 268, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = 0},
|
||||
{.bitmap_index = 4853, .adv_w = 285, .box_w = 15, .box_h = 19, .ofs_x = 2, .ofs_y = -5},
|
||||
{.bitmap_index = 4925, .adv_w = 285, .box_w = 16, .box_h = 19, .ofs_x = 0, .ofs_y = -5},
|
||||
{.bitmap_index = 5001, .adv_w = 175, .box_w = 9, .box_h = 14, .ofs_x = 2, .ofs_y = 0},
|
||||
{.bitmap_index = 5033, .adv_w = 214, .box_w = 13, .box_h = 14, .ofs_x = 0, .ofs_y = 0},
|
||||
{.bitmap_index = 5079, .adv_w = 176, .box_w = 11, .box_h = 17, .ofs_x = 0, .ofs_y = 0},
|
||||
{.bitmap_index = 5126, .adv_w = 283, .box_w = 14, .box_h = 14, .ofs_x = 2, .ofs_y = 0},
|
||||
{.bitmap_index = 5175, .adv_w = 240, .box_w = 17, .box_h = 14, .ofs_x = -1, .ofs_y = 0},
|
||||
{.bitmap_index = 5235, .adv_w = 382, .box_w = 24, .box_h = 14, .ofs_x = 0, .ofs_y = 0},
|
||||
{.bitmap_index = 5319, .adv_w = 238, .box_w = 15, .box_h = 14, .ofs_x = 0, .ofs_y = 0},
|
||||
{.bitmap_index = 5372, .adv_w = 240, .box_w = 17, .box_h = 19, .ofs_x = -1, .ofs_y = -5},
|
||||
{.bitmap_index = 5453, .adv_w = 221, .box_w = 13, .box_h = 14, .ofs_x = 0, .ofs_y = 0},
|
||||
{.bitmap_index = 5499, .adv_w = 154, .box_w = 9, .box_h = 24, .ofs_x = 1, .ofs_y = -5},
|
||||
{.bitmap_index = 5553, .adv_w = 126, .box_w = 4, .box_h = 25, .ofs_x = 2, .ofs_y = -5},
|
||||
{.bitmap_index = 5578, .adv_w = 154, .box_w = 9, .box_h = 24, .ofs_x = 0, .ofs_y = -5},
|
||||
{.bitmap_index = 5632, .adv_w = 245, .box_w = 13, .box_h = 5, .ofs_x = 1, .ofs_y = 7}};
|
||||
|
||||
/*---------------------
|
||||
* CHARACTER MAPPING
|
||||
*--------------------*/
|
||||
|
||||
/*Collect the unicode lists and glyph_id offsets*/
|
||||
static const lv_font_fmt_txt_cmap_t cmaps[] = {{.range_start = 32,
|
||||
.range_length = 95,
|
||||
.glyph_id_start = 1,
|
||||
.unicode_list = NULL,
|
||||
.glyph_id_ofs_list = NULL,
|
||||
.list_length = 0,
|
||||
.type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY}};
|
||||
|
||||
/*--------------------
|
||||
* ALL CUSTOM DATA
|
||||
*--------------------*/
|
||||
|
||||
#if LVGL_VERSION_MAJOR == 8
|
||||
/*Store all the custom data of the font*/
|
||||
static lv_font_fmt_txt_glyph_cache_t cache;
|
||||
#endif
|
||||
|
||||
#if LVGL_VERSION_MAJOR >= 8
|
||||
static const lv_font_fmt_txt_dsc_t font_dsc = {
|
||||
#else
|
||||
static lv_font_fmt_txt_dsc_t font_dsc = {
|
||||
#endif
|
||||
.glyph_bitmap = glyph_bitmap,
|
||||
.glyph_dsc = glyph_dsc,
|
||||
.cmaps = cmaps,
|
||||
.kern_dsc = NULL,
|
||||
.kern_scale = 0,
|
||||
.cmap_num = 1,
|
||||
.bpp = 2,
|
||||
.kern_classes = 0,
|
||||
.bitmap_format = 0,
|
||||
#if LVGL_VERSION_MAJOR == 8
|
||||
.cache = &cache
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
/*-----------------
|
||||
* PUBLIC FONT
|
||||
*----------------*/
|
||||
|
||||
/*Initialize a public general font descriptor*/
|
||||
#if LVGL_VERSION_MAJOR >= 8
|
||||
const lv_font_t MontserratSemiBold26 = {
|
||||
#else
|
||||
lv_font_t MontserratSemiBold26 = {
|
||||
#endif
|
||||
.get_glyph_dsc = lv_font_get_glyph_dsc_fmt_txt, /*Function pointer to get glyph's data*/
|
||||
.get_glyph_bitmap = lv_font_get_bitmap_fmt_txt, /*Function pointer to get glyph's bitmap*/
|
||||
.line_height = 27, /*The maximum line height required by the font*/
|
||||
.base_line = 5, /*Baseline measured from the bottom of the line*/
|
||||
#if !(LVGL_VERSION_MAJOR == 6 && LVGL_VERSION_MINOR == 0)
|
||||
.subpx = LV_FONT_SUBPX_NONE,
|
||||
#endif
|
||||
#if LV_VERSION_CHECK(7, 4, 0) || LVGL_VERSION_MAJOR >= 8
|
||||
.underline_position = -3,
|
||||
.underline_thickness = 1,
|
||||
#endif
|
||||
.static_bitmap = 0,
|
||||
.dsc = &font_dsc, /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */
|
||||
#if LV_VERSION_CHECK(8, 2, 0) || LVGL_VERSION_MAJOR >= 9
|
||||
.fallback = NULL,
|
||||
#endif
|
||||
.user_data = NULL,
|
||||
};
|
||||
|
||||
#endif /*#if MONTSERRATSEMIBOLD26*/
|
||||
@@ -0,0 +1 @@
|
||||
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,407 @@
|
||||
#ifdef __has_include
|
||||
#if __has_include("lvgl.h")
|
||||
#ifndef LV_LVGL_H_INCLUDE_SIMPLE
|
||||
#define LV_LVGL_H_INCLUDE_SIMPLE
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(LV_LVGL_H_INCLUDE_SIMPLE)
|
||||
#include "lvgl.h"
|
||||
#else
|
||||
#include "lvgl/lvgl.h"
|
||||
#endif
|
||||
|
||||
#ifndef LV_ATTRIBUTE_MEM_ALIGN
|
||||
#define LV_ATTRIBUTE_MEM_ALIGN
|
||||
#endif
|
||||
|
||||
#ifndef LV_ATTRIBUTE_IMAGE_ICON_INDICATOR_LEFT
|
||||
#define LV_ATTRIBUTE_IMAGE_ICON_INDICATOR_LEFT
|
||||
#endif
|
||||
|
||||
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMAGE_ICON_INDICATOR_LEFT uint8_t
|
||||
icon_indicator_left_map[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7d, 0xef, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbe, 0xf7, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
|
||||
0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb, 0xde, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xf7,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x7a, 0xd6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbe, 0xf7, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x1c, 0xe7, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
|
||||
0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xfe, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xdf, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbb, 0xde, 0xdf, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0x75, 0xad, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbb, 0xde, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x75, 0xad, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x1c, 0xe7, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||
0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0xd6, 0xdf, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0x75, 0xad,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0xd6, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xfb, 0xde, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0x75, 0xad, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xfe, 0xf7, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x7d, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x10, 0x84, 0xbe, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xde, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xbe, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x7e, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xbe, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xfb, 0xde, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xfb, 0xde, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x7e, 0xf7,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
|
||||
0xbe, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xfb, 0xde, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xde, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x9e, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x9e, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xfb, 0xde,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xfb, 0xde, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xfe, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xde, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xff, 0xff, 0x9e, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x9e, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xbe, 0xf7, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbe, 0xf7,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x9e, 0xf7, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xbf, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x84,
|
||||
0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xff, 0xff, 0xbe, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xff, 0xff, 0x7d, 0xef, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xde, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x1e, 0x5a, 0x53, 0x0c, 0x01, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x27, 0x85, 0xbf, 0xb0, 0x60, 0x13, 0x01, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x2d, 0x7a, 0xd7, 0xf8, 0xec, 0xb8, 0x58, 0x1a, 0x01,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x05, 0x28, 0x77, 0xde, 0xf9, 0xff, 0xfe, 0xf2, 0xbb, 0x4f, 0x09,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x20, 0x83, 0xd9, 0xf9, 0xfe, 0xff, 0xff, 0xfc, 0xec, 0x8c, 0x26,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x26, 0x87, 0xd1, 0xf8, 0xfe, 0xff, 0xff, 0xff, 0xf5, 0xc3, 0x5c, 0x10,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x07, 0x2c, 0x7b, 0xd7, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xc4, 0x6b, 0x22, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x01, 0x05, 0x27, 0x74, 0xde, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xf4, 0xc5, 0x71, 0x16, 0x01, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x06, 0x20, 0x81, 0xd9, 0xf8, 0xfe, 0xff, 0xff, 0xfe, 0xf8, 0xc2, 0x6d, 0x17, 0x03, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x06, 0x24, 0x87, 0xd1, 0xf8, 0xfe, 0xff, 0xff, 0xff, 0xf5, 0xc3, 0x67, 0x1f, 0x02, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x08, 0x2b, 0x7c, 0xd5, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xc3, 0x6a, 0x23, 0x01, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
|
||||
0x29, 0x74, 0xdd, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xc5, 0x70, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x22,
|
||||
0x7f, 0xda, 0xf8, 0xfe, 0xff, 0xff, 0xfe, 0xf8, 0xc2, 0x6e, 0x17, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x23, 0x87,
|
||||
0xd2, 0xf9, 0xfe, 0xff, 0xff, 0xff, 0xf6, 0xc4, 0x67, 0x1d, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x2a, 0x7d, 0xd3,
|
||||
0xf7, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xc3, 0x69, 0x23, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x2a, 0x74, 0xdb, 0xf9,
|
||||
0xff, 0xff, 0xff, 0xff, 0xf2, 0xc5, 0x70, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x23, 0x7d, 0xdb, 0xf8, 0xfe,
|
||||
0xff, 0xff, 0xfe, 0xf8, 0xc3, 0x6f, 0x17, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x22, 0x87, 0xd3, 0xf9, 0xfe, 0xff,
|
||||
0xff, 0xff, 0xf7, 0xc5, 0x68, 0x1c, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x29, 0x7f, 0xd2, 0xf7, 0xff, 0xff, 0xff,
|
||||
0xff, 0xf1, 0xc3, 0x68, 0x23, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x2b, 0x74, 0xda, 0xf9, 0xff, 0xff, 0xff, 0xff,
|
||||
0xf1, 0xc6, 0x6f, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x06, 0x24, 0x7c, 0xdd, 0xf8, 0xfe, 0xff, 0xff, 0xfe, 0xf7,
|
||||
0xc3, 0x6f, 0x17, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x87, 0xd4, 0xfa, 0xfe, 0xff, 0xff, 0xff, 0xf8, 0xc5,
|
||||
0x68, 0x19, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x27, 0x80, 0xd1, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xf2, 0xc3, 0x68,
|
||||
0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x2b, 0x74, 0xd8, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xc5, 0x6f, 0x1c,
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x01, 0x06, 0x25, 0x7a, 0xdd, 0xf8, 0xfe, 0xff, 0xff, 0xfe, 0xf6, 0xc3, 0x70, 0x17, 0x03,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x05, 0x1f, 0x86, 0xd6, 0xfa, 0xfe, 0xff, 0xff, 0xff, 0xf8, 0xc4, 0x69, 0x17, 0x03, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x07, 0x27, 0x82, 0xd0, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xc2, 0x67, 0x23, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x07, 0x2c, 0x75, 0xd7, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xc5, 0x6e, 0x1d, 0x01, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x05, 0x26, 0x79, 0xdd, 0xf9, 0xfe, 0xff, 0xff, 0xfe, 0xf5, 0xc3, 0x70, 0x17, 0x03, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x1e, 0x84, 0xd6, 0xf9, 0xfe, 0xff, 0xff, 0xff, 0xf9, 0xc4, 0x6a, 0x16, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x5d, 0xc0, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xed, 0x80, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x57, 0xb4, 0xee, 0xfe, 0xff, 0xff, 0xff, 0xfd, 0xed, 0x8a, 0x35, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x0d, 0x65, 0xbd, 0xf3, 0xfd, 0xff, 0xff, 0xff, 0xfc, 0xe0, 0x89, 0x28, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x02, 0x15, 0x5c, 0xc1, 0xf3, 0xfe, 0xff, 0xff, 0xfe, 0xfa, 0xda, 0x94, 0x27, 0x07, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x01, 0x1c, 0x5b, 0xbd, 0xef, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xda, 0x8d, 0x30, 0x07, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x01, 0x16, 0x65, 0xba, 0xee, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xdc, 0x83, 0x35, 0x06, 0x01, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x01, 0x0e, 0x67, 0xbd, 0xf4, 0xfd, 0xff, 0xff, 0xff, 0xfb, 0xe1, 0x87, 0x29, 0x08, 0x01,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x02, 0x14, 0x5d, 0xc1, 0xf2, 0xfe, 0xff, 0xff, 0xfe, 0xfa, 0xda, 0x93, 0x28, 0x07,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1c, 0x59, 0xbe, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xd9, 0x8f, 0x2e,
|
||||
0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x16, 0x64, 0xbb, 0xed, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xdb, 0x84,
|
||||
0x36, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0e, 0x68, 0xbd, 0xf4, 0xfd, 0xff, 0xff, 0xff, 0xfb, 0xe3,
|
||||
0x87, 0x2a, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x13, 0x5f, 0xc0, 0xf2, 0xfd, 0xff, 0xff, 0xfe, 0xfb,
|
||||
0xda, 0x92, 0x28, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1b, 0x58, 0xbe, 0xf0, 0xff, 0xff, 0xff, 0xff,
|
||||
0xf8, 0xd9, 0x91, 0x2c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x18, 0x63, 0xbb, 0xed, 0xff, 0xff, 0xff,
|
||||
0xff, 0xf8, 0xdb, 0x85, 0x36, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0f, 0x68, 0xbd, 0xf2, 0xfd, 0xff,
|
||||
0xff, 0xff, 0xfb, 0xe3, 0x85, 0x2c, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x12, 0x60, 0xbf, 0xf2, 0xfd,
|
||||
0xff, 0xff, 0xfe, 0xfb, 0xdb, 0x91, 0x28, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1a, 0x58, 0xbe, 0xf1,
|
||||
0xff, 0xff, 0xff, 0xff, 0xf8, 0xd9, 0x92, 0x2a, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x19, 0x61, 0xbb,
|
||||
0xed, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xda, 0x87, 0x36, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x68,
|
||||
0xbb, 0xf1, 0xfd, 0xff, 0xff, 0xff, 0xfb, 0xe3, 0x84, 0x2e, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10,
|
||||
0x61, 0xbe, 0xf2, 0xfd, 0xff, 0xff, 0xfe, 0xfb, 0xdb, 0x8f, 0x27, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
|
||||
0x19, 0x58, 0xbf, 0xf2, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xd9, 0x94, 0x29, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x01, 0x1a, 0x60, 0xbd, 0xed, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xda, 0x88, 0x35, 0x07, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x01, 0x12, 0x68, 0xbb, 0xf0, 0xfd, 0xff, 0xff, 0xff, 0xfa, 0xe1, 0x83, 0x30, 0x07, 0x01, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x02, 0x0f, 0x63, 0xbe, 0xf2, 0xfd, 0xff, 0xff, 0xfe, 0xfb, 0xdd, 0x8f, 0x28, 0x08, 0x01, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x01, 0x18, 0x58, 0xc0, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xdb, 0x96, 0x29, 0x06, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x01, 0x1c, 0x60, 0xbe, 0xee, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xdb, 0x8b, 0x35, 0x05,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x14, 0x69, 0xbc, 0xf0, 0xfe, 0xff, 0xff, 0xff, 0xfa, 0xdf, 0x6c, 0x13,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0f, 0x65, 0xbf, 0xf3, 0xfd, 0xff, 0xff, 0xfb, 0xe5, 0x82, 0x20,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x17, 0x5b, 0xc2, 0xf4, 0xff, 0xfe, 0xea, 0x91, 0x39, 0x07,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x1d, 0x5f, 0xbe, 0xee, 0xde, 0x95, 0x3c, 0x0f, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x15, 0x67, 0xa5, 0x94, 0x3d, 0x0a, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0d, 0x31, 0x30, 0x07, 0x01, 0x00, 0x00,
|
||||
};
|
||||
|
||||
const lv_image_dsc_t icon_indicator_left = {
|
||||
.header.cf = LV_COLOR_FORMAT_RGB565A8,
|
||||
.header.magic = LV_IMAGE_HEADER_MAGIC,
|
||||
.header.w = 36,
|
||||
.header.h = 62,
|
||||
.data_size = 2232 * 3,
|
||||
.data = icon_indicator_left_map,
|
||||
};
|
||||
@@ -0,0 +1,407 @@
|
||||
#ifdef __has_include
|
||||
#if __has_include("lvgl.h")
|
||||
#ifndef LV_LVGL_H_INCLUDE_SIMPLE
|
||||
#define LV_LVGL_H_INCLUDE_SIMPLE
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(LV_LVGL_H_INCLUDE_SIMPLE)
|
||||
#include "lvgl.h"
|
||||
#else
|
||||
#include "lvgl/lvgl.h"
|
||||
#endif
|
||||
|
||||
#ifndef LV_ATTRIBUTE_MEM_ALIGN
|
||||
#define LV_ATTRIBUTE_MEM_ALIGN
|
||||
#endif
|
||||
|
||||
#ifndef LV_ATTRIBUTE_IMAGE_ICON_INDICATOR_RIGHT
|
||||
#define LV_ATTRIBUTE_IMAGE_ICON_INDICATOR_RIGHT
|
||||
#endif
|
||||
|
||||
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMAGE_ICON_INDICATOR_RIGHT uint8_t
|
||||
icon_indicator_right_map[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x5d, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7d, 0xef, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xff, 0xff, 0x9e, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5d, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x9e, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0x7d, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0x7d, 0xef, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
|
||||
0x1c, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xff, 0xff, 0x9e, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x10, 0x84, 0x9e, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5d, 0xef, 0xff, 0xff, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x1c, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7d, 0xef,
|
||||
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x9e, 0xf7, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x84, 0x9e, 0xf7, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x1c, 0xe7,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x1c, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7e, 0xf7, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7a, 0xd6,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x87, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
|
||||
0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xdf, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0xd6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xbb, 0xde, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x18, 0xc6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x75, 0xad, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x18, 0xc6, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
|
||||
0x00, 0x00, 0x0a, 0x29, 0x6d, 0x35, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x08, 0x3f, 0x97, 0xc9, 0x9b, 0x4a, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x0a, 0x3f, 0x93, 0xe6, 0xf9, 0xe4, 0x9e, 0x43, 0x0d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x2b, 0x98, 0xe6, 0xfd, 0xff, 0xfe, 0xe5, 0xa8, 0x39, 0x0d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x74, 0xcd, 0xfa, 0xff, 0xff, 0xff, 0xfb, 0xe7, 0xa7, 0x3f, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x3b, 0xa2, 0xe9, 0xfe, 0xff, 0xff, 0xff, 0xfb, 0xe5, 0xa0, 0x49, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x0b, 0x50, 0xa5, 0xea, 0xfc, 0xff, 0xff, 0xff, 0xfc, 0xe4, 0x9d, 0x44, 0x0d, 0x01, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x08, 0x49, 0xb1, 0xea, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xe6, 0xa7, 0x39, 0x0d, 0x01, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x01, 0x10, 0x3f, 0xb0, 0xe9, 0xfd, 0xff, 0xff, 0xff, 0xfb, 0xe7, 0xa7, 0x3d, 0x0b, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x01, 0x10, 0x45, 0xa8, 0xe9, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xe5, 0xa2, 0x48, 0x05, 0x01, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x01, 0x0c, 0x50, 0xa4, 0xea, 0xfc, 0xff, 0xff, 0xff, 0xfc, 0xe5, 0x9d, 0x46, 0x0c, 0x01,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x4b, 0xb0, 0xea, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xe5, 0xa5, 0x3b, 0x0d,
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0f, 0x3f, 0xb0, 0xe9, 0xfd, 0xff, 0xff, 0xff, 0xfb, 0xe6, 0xa7, 0x3c,
|
||||
0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0f, 0x43, 0xaa, 0xea, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xe5, 0xa4,
|
||||
0x48, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0d, 0x4f, 0xa4, 0xea, 0xfc, 0xff, 0xff, 0xff, 0xfc, 0xe5,
|
||||
0x9d, 0x48, 0x0c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x4d, 0xae, 0xe9, 0xfb, 0xff, 0xff, 0xff, 0xff,
|
||||
0xe5, 0xa4, 0x3c, 0x0d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0f, 0x41, 0xb0, 0xe9, 0xfc, 0xff, 0xff, 0xff,
|
||||
0xfc, 0xe5, 0xa7, 0x3a, 0x0c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x42, 0xac, 0xea, 0xff, 0xff, 0xff,
|
||||
0xff, 0xfb, 0xe6, 0xa5, 0x46, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0e, 0x4f, 0xa4, 0xea, 0xfc, 0xff,
|
||||
0xff, 0xff, 0xfb, 0xe5, 0x9d, 0x48, 0x0b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x4f, 0xac, 0xe9, 0xfb,
|
||||
0xff, 0xff, 0xff, 0xff, 0xe5, 0xa2, 0x3d, 0x0d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0e, 0x42, 0xb0, 0xe9,
|
||||
0xfc, 0xff, 0xff, 0xff, 0xfc, 0xe5, 0xa7, 0x39, 0x0d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x41, 0xae,
|
||||
0xea, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xe7, 0xa7, 0x44, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0f, 0x4d,
|
||||
0xa4, 0xea, 0xfd, 0xff, 0xff, 0xff, 0xfb, 0xe6, 0x9d, 0x49, 0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08,
|
||||
0x4f, 0xaa, 0xe9, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xe4, 0xa0, 0x3f, 0x0d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
|
||||
0x0d, 0x43, 0xb0, 0xea, 0xfc, 0xff, 0xff, 0xff, 0xfc, 0xe5, 0xa7, 0x39, 0x0d, 0x01, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x01, 0x0f, 0x3f, 0xb0, 0xea, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xe7, 0xa8, 0x43, 0x05, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x02, 0x0f, 0x4b, 0xa4, 0xe9, 0xfd, 0xff, 0xff, 0xff, 0xfb, 0xe5, 0x9e, 0x4a, 0x08, 0x01, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x01, 0x08, 0x50, 0xa9, 0xe9, 0xfc, 0xff, 0xff, 0xff, 0xfe, 0xe4, 0xa0, 0x40, 0x0d, 0x01, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x0c, 0x46, 0xb1, 0xeb, 0xfc, 0xff, 0xff, 0xff, 0xfd, 0xe5, 0xa8, 0x3a, 0x0e, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x40, 0xb2, 0xeb, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xe7, 0xa8, 0x41, 0x05,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x14, 0x64, 0xc6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xe4, 0x7a, 0x1c,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x1f, 0x6e, 0xca, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xd3, 0x72, 0x1b,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x04, 0x1d, 0x5e, 0xce, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xd9, 0x7f, 0x2a, 0x01,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x01, 0x1c, 0x62, 0xcc, 0xf4, 0xfe, 0xff, 0xff, 0xff, 0xfc, 0xd4, 0x80, 0x26, 0x07, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x03, 0x1a, 0x6c, 0xc2, 0xf4, 0xfe, 0xff, 0xff, 0xff, 0xfd, 0xcd, 0x80, 0x2b, 0x07, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x05, 0x1e, 0x67, 0xbe, 0xf8, 0xfe, 0xff, 0xff, 0xff, 0xf8, 0xd3, 0x7f, 0x31, 0x03, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x04, 0x1d, 0x5e, 0xcc, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xd9, 0x7f, 0x2c, 0x01, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
|
||||
0x1d, 0x61, 0xcc, 0xf4, 0xfe, 0xff, 0xff, 0xff, 0xfb, 0xd4, 0x7f, 0x26, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x1a,
|
||||
0x6b, 0xc4, 0xf4, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xce, 0x7f, 0x2b, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x1e, 0x68,
|
||||
0xbe, 0xf8, 0xfe, 0xff, 0xff, 0xff, 0xf8, 0xd2, 0x7f, 0x30, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x1c, 0x5d, 0xcb,
|
||||
0xf8, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xd9, 0x7f, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x1e, 0x60, 0xcc, 0xf4,
|
||||
0xfe, 0xff, 0xff, 0xff, 0xfa, 0xd5, 0x7f, 0x26, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x1a, 0x6b, 0xc6, 0xf3, 0xfe,
|
||||
0xff, 0xff, 0xff, 0xff, 0xce, 0x7f, 0x2a, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x1e, 0x6a, 0xbe, 0xf8, 0xfe, 0xff,
|
||||
0xff, 0xff, 0xf9, 0xd1, 0x7f, 0x30, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x1c, 0x5f, 0xc8, 0xf8, 0xff, 0xff, 0xff,
|
||||
0xff, 0xf8, 0xd8, 0x7f, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x1e, 0x5f, 0xcc, 0xf4, 0xfe, 0xff, 0xff, 0xff,
|
||||
0xfa, 0xd6, 0x7f, 0x27, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x1a, 0x6a, 0xc9, 0xf4, 0xfd, 0xff, 0xff, 0xff, 0xff,
|
||||
0xcf, 0x7f, 0x29, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x1e, 0x6b, 0xbe, 0xf8, 0xfe, 0xff, 0xff, 0xff, 0xf9, 0xd0,
|
||||
0x7f, 0x2f, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x1c, 0x60, 0xc7, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xd7, 0x7f,
|
||||
0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x1e, 0x5e, 0xcd, 0xf4, 0xfe, 0xff, 0xff, 0xff, 0xf9, 0xd7, 0x80, 0x28,
|
||||
0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x02, 0x1a, 0x68, 0xcb, 0xf4, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xd0, 0x80, 0x28, 0x07,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x05, 0x1d, 0x6c, 0xbe, 0xf8, 0xfe, 0xff, 0xff, 0xff, 0xfa, 0xcf, 0x7f, 0x2f, 0x06, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x06, 0x1d, 0x62, 0xc4, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xd6, 0x7f, 0x2f, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x04, 0x1e, 0x5e, 0xcd, 0xf4, 0xfe, 0xff, 0xff, 0xff, 0xf9, 0xd8, 0x7f, 0x29, 0x05, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x01, 0x1a, 0x68, 0xcd, 0xf4, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xd1, 0x7f, 0x27, 0x07, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x1c, 0x6c, 0xbf, 0xf7, 0xfe, 0xff, 0xff, 0xff, 0xfa, 0xce, 0x7f, 0x2d, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x49, 0xb8, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xd5, 0x7f, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x69, 0xc5, 0xf7, 0xff, 0xff, 0xff, 0xf8, 0xd9, 0x7f, 0x2a, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x1c, 0x79, 0xce, 0xfd, 0xff, 0xff, 0xd2, 0x7f, 0x26, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x03, 0x2b, 0x77, 0xcd, 0xf3, 0xce, 0x7f, 0x2c, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x01, 0x2a, 0x76, 0xb2, 0x7a, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x04, 0x14, 0x3f, 0x1d, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
const lv_image_dsc_t icon_indicator_right = {
|
||||
.header.cf = LV_COLOR_FORMAT_RGB565A8,
|
||||
.header.magic = LV_IMAGE_HEADER_MAGIC,
|
||||
.header.w = 36,
|
||||
.header.h = 62,
|
||||
.data_size = 2232 * 3,
|
||||
.data = icon_indicator_right_map,
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@@ -0,0 +1,66 @@
|
||||
#ifndef _BOARD_CONFIG_H_
|
||||
#define _BOARD_CONFIG_H_
|
||||
|
||||
// M5Stack StackChan Board configuration
|
||||
|
||||
#include <driver/gpio.h>
|
||||
|
||||
#define AUDIO_INPUT_REFERENCE true
|
||||
#define AUDIO_INPUT_SAMPLE_RATE 24000
|
||||
#define AUDIO_OUTPUT_SAMPLE_RATE 24000
|
||||
|
||||
#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_0
|
||||
#define AUDIO_I2S_GPIO_WS GPIO_NUM_33
|
||||
#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_34
|
||||
#define AUDIO_I2S_GPIO_DIN GPIO_NUM_14
|
||||
#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_13
|
||||
|
||||
#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_12
|
||||
#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_11
|
||||
#define AUDIO_CODEC_AW88298_ADDR AW88298_CODEC_DEFAULT_ADDR
|
||||
#define AUDIO_CODEC_ES7210_ADDR ES7210_CODEC_DEFAULT_ADDR
|
||||
|
||||
#define BUILTIN_LED_GPIO GPIO_NUM_NC
|
||||
#define BOOT_BUTTON_GPIO GPIO_NUM_0
|
||||
#define VOLUME_UP_BUTTON_GPIO GPIO_NUM_NC
|
||||
#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_NC
|
||||
|
||||
#define DISPLAY_SDA_PIN GPIO_NUM_NC
|
||||
#define DISPLAY_SCL_PIN GPIO_NUM_NC
|
||||
#define DISPLAY_WIDTH 320
|
||||
#define DISPLAY_HEIGHT 240
|
||||
#define DISPLAY_MIRROR_X false
|
||||
#define DISPLAY_MIRROR_Y false
|
||||
#define DISPLAY_SWAP_XY false
|
||||
|
||||
#define DISPLAY_OFFSET_X 0
|
||||
#define DISPLAY_OFFSET_Y 0
|
||||
|
||||
#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_NC
|
||||
#define DISPLAY_BACKLIGHT_OUTPUT_INVERT true
|
||||
|
||||
|
||||
|
||||
/* Camera pins */
|
||||
#define CAMERA_PIN_PWDN GPIO_NUM_NC
|
||||
#define CAMERA_PIN_RESET GPIO_NUM_NC
|
||||
#define CAMERA_PIN_XCLK GPIO_NUM_NC // 像素时钟 (固定由 20MHz 外部晶振输入)
|
||||
#define CAMERA_PIN_SIOD GPIO_NUM_NC // 串行时钟 Using existing I2C port
|
||||
#define CAMERA_PIN_SIOC GPIO_NUM_NC // 串行时钟 Using existing I2C port
|
||||
#define CAMERA_PIN_D0 GPIO_NUM_39
|
||||
#define CAMERA_PIN_D1 GPIO_NUM_40
|
||||
#define CAMERA_PIN_D2 GPIO_NUM_41
|
||||
#define CAMERA_PIN_D3 GPIO_NUM_42
|
||||
#define CAMERA_PIN_D4 GPIO_NUM_15
|
||||
#define CAMERA_PIN_D5 GPIO_NUM_16
|
||||
#define CAMERA_PIN_D6 GPIO_NUM_48
|
||||
#define CAMERA_PIN_D7 GPIO_NUM_47
|
||||
#define CAMERA_PIN_VSYNC GPIO_NUM_46
|
||||
#define CAMERA_PIN_HREF GPIO_NUM_38
|
||||
#define CAMERA_PIN_PCLK GPIO_NUM_45
|
||||
|
||||
#define XCLK_FREQ_HZ 20000000
|
||||
|
||||
|
||||
|
||||
#endif // _BOARD_CONFIG_H_
|
||||
@@ -0,0 +1,244 @@
|
||||
#include "cores3_audio_codec.h"
|
||||
|
||||
#include <esp_log.h>
|
||||
#include <driver/i2c_master.h>
|
||||
#include <driver/i2s_tdm.h>
|
||||
|
||||
#define TAG "CoreS3AudioCodec"
|
||||
|
||||
CoreS3AudioCodec::CoreS3AudioCodec(void* i2c_master_handle, int input_sample_rate, int output_sample_rate,
|
||||
gpio_num_t mclk, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din,
|
||||
uint8_t aw88298_addr, uint8_t es7210_addr, bool input_reference) {
|
||||
duplex_ = true; // 是否双工
|
||||
input_reference_ = input_reference; // 是否使用参考输入,实现回声消除
|
||||
input_channels_ = input_reference_ ? 2 : 1; // 输入通道数
|
||||
input_sample_rate_ = input_sample_rate;
|
||||
output_sample_rate_ = output_sample_rate;
|
||||
input_gain_ = 30;
|
||||
|
||||
CreateDuplexChannels(mclk, bclk, ws, dout, din);
|
||||
|
||||
// Do initialize of related interface: data_if, ctrl_if and gpio_if
|
||||
audio_codec_i2s_cfg_t i2s_cfg = {
|
||||
.port = I2S_NUM_0,
|
||||
.rx_handle = rx_handle_,
|
||||
.tx_handle = tx_handle_,
|
||||
};
|
||||
data_if_ = audio_codec_new_i2s_data(&i2s_cfg);
|
||||
assert(data_if_ != NULL);
|
||||
|
||||
// Audio Output(Speaker)
|
||||
audio_codec_i2c_cfg_t i2c_cfg = {
|
||||
.port = (i2c_port_t)1,
|
||||
.addr = aw88298_addr,
|
||||
.bus_handle = i2c_master_handle,
|
||||
};
|
||||
out_ctrl_if_ = audio_codec_new_i2c_ctrl(&i2c_cfg);
|
||||
assert(out_ctrl_if_ != NULL);
|
||||
|
||||
gpio_if_ = audio_codec_new_gpio();
|
||||
assert(gpio_if_ != NULL);
|
||||
|
||||
aw88298_codec_cfg_t aw88298_cfg = {};
|
||||
aw88298_cfg.ctrl_if = out_ctrl_if_;
|
||||
aw88298_cfg.gpio_if = gpio_if_;
|
||||
aw88298_cfg.reset_pin = GPIO_NUM_NC;
|
||||
aw88298_cfg.hw_gain.pa_voltage = 5.0;
|
||||
aw88298_cfg.hw_gain.codec_dac_voltage = 3.3;
|
||||
aw88298_cfg.hw_gain.pa_gain = 1;
|
||||
out_codec_if_ = aw88298_codec_new(&aw88298_cfg);
|
||||
assert(out_codec_if_ != NULL);
|
||||
|
||||
esp_codec_dev_cfg_t dev_cfg = {
|
||||
.dev_type = ESP_CODEC_DEV_TYPE_OUT,
|
||||
.codec_if = out_codec_if_,
|
||||
.data_if = data_if_,
|
||||
};
|
||||
output_dev_ = esp_codec_dev_new(&dev_cfg);
|
||||
assert(output_dev_ != NULL);
|
||||
|
||||
// Audio Input(Microphone)
|
||||
i2c_cfg.addr = es7210_addr;
|
||||
in_ctrl_if_ = audio_codec_new_i2c_ctrl(&i2c_cfg);
|
||||
assert(in_ctrl_if_ != NULL);
|
||||
|
||||
es7210_codec_cfg_t es7210_cfg = {};
|
||||
es7210_cfg.ctrl_if = in_ctrl_if_;
|
||||
es7210_cfg.mic_selected = ES7210_SEL_MIC1 | ES7210_SEL_MIC2 | ES7210_SEL_MIC3;
|
||||
in_codec_if_ = es7210_codec_new(&es7210_cfg);
|
||||
assert(in_codec_if_ != NULL);
|
||||
|
||||
dev_cfg.dev_type = ESP_CODEC_DEV_TYPE_IN;
|
||||
dev_cfg.codec_if = in_codec_if_;
|
||||
input_dev_ = esp_codec_dev_new(&dev_cfg);
|
||||
assert(input_dev_ != NULL);
|
||||
|
||||
ESP_LOGI(TAG, "CoreS3AudioCodec initialized");
|
||||
}
|
||||
|
||||
CoreS3AudioCodec::~CoreS3AudioCodec() {
|
||||
ESP_ERROR_CHECK(esp_codec_dev_close(output_dev_));
|
||||
esp_codec_dev_delete(output_dev_);
|
||||
ESP_ERROR_CHECK(esp_codec_dev_close(input_dev_));
|
||||
esp_codec_dev_delete(input_dev_);
|
||||
|
||||
audio_codec_delete_codec_if(in_codec_if_);
|
||||
audio_codec_delete_ctrl_if(in_ctrl_if_);
|
||||
audio_codec_delete_codec_if(out_codec_if_);
|
||||
audio_codec_delete_ctrl_if(out_ctrl_if_);
|
||||
audio_codec_delete_gpio_if(gpio_if_);
|
||||
audio_codec_delete_data_if(data_if_);
|
||||
}
|
||||
|
||||
void CoreS3AudioCodec::CreateDuplexChannels(gpio_num_t mclk, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din) {
|
||||
assert(input_sample_rate_ == output_sample_rate_);
|
||||
|
||||
ESP_LOGI(TAG, "Audio IOs: mclk: %d, bclk: %d, ws: %d, dout: %d, din: %d", mclk, bclk, ws, dout, din);
|
||||
|
||||
i2s_chan_config_t chan_cfg = {
|
||||
.id = I2S_NUM_0,
|
||||
.role = I2S_ROLE_MASTER,
|
||||
.dma_desc_num = AUDIO_CODEC_DMA_DESC_NUM,
|
||||
.dma_frame_num = AUDIO_CODEC_DMA_FRAME_NUM,
|
||||
.auto_clear_after_cb = true,
|
||||
.auto_clear_before_cb = false,
|
||||
.intr_priority = 0,
|
||||
};
|
||||
ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, &tx_handle_, &rx_handle_));
|
||||
|
||||
i2s_std_config_t std_cfg = {
|
||||
.clk_cfg = {
|
||||
.sample_rate_hz = (uint32_t)output_sample_rate_,
|
||||
.clk_src = I2S_CLK_SRC_DEFAULT,
|
||||
.ext_clk_freq_hz = 0,
|
||||
.mclk_multiple = I2S_MCLK_MULTIPLE_256
|
||||
},
|
||||
.slot_cfg = {
|
||||
.data_bit_width = I2S_DATA_BIT_WIDTH_16BIT,
|
||||
.slot_bit_width = I2S_SLOT_BIT_WIDTH_AUTO,
|
||||
.slot_mode = I2S_SLOT_MODE_STEREO,
|
||||
.slot_mask = I2S_STD_SLOT_BOTH,
|
||||
.ws_width = I2S_DATA_BIT_WIDTH_16BIT,
|
||||
.ws_pol = false,
|
||||
.bit_shift = true,
|
||||
.left_align = true,
|
||||
.big_endian = false,
|
||||
.bit_order_lsb = false
|
||||
},
|
||||
.gpio_cfg = {
|
||||
.mclk = mclk,
|
||||
.bclk = bclk,
|
||||
.ws = ws,
|
||||
.dout = dout,
|
||||
.din = I2S_GPIO_UNUSED,
|
||||
.invert_flags = {
|
||||
.mclk_inv = false,
|
||||
.bclk_inv = false,
|
||||
.ws_inv = false
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
i2s_tdm_config_t tdm_cfg = {
|
||||
.clk_cfg = {
|
||||
.sample_rate_hz = (uint32_t)input_sample_rate_,
|
||||
.clk_src = I2S_CLK_SRC_DEFAULT,
|
||||
.ext_clk_freq_hz = 0,
|
||||
.mclk_multiple = I2S_MCLK_MULTIPLE_256,
|
||||
.bclk_div = 8,
|
||||
},
|
||||
.slot_cfg = {
|
||||
.data_bit_width = I2S_DATA_BIT_WIDTH_16BIT,
|
||||
.slot_bit_width = I2S_SLOT_BIT_WIDTH_AUTO,
|
||||
.slot_mode = I2S_SLOT_MODE_STEREO,
|
||||
.slot_mask = i2s_tdm_slot_mask_t(I2S_TDM_SLOT0 | I2S_TDM_SLOT1 | I2S_TDM_SLOT2 | I2S_TDM_SLOT3),
|
||||
.ws_width = I2S_TDM_AUTO_WS_WIDTH,
|
||||
.ws_pol = false,
|
||||
.bit_shift = true,
|
||||
.left_align = false,
|
||||
.big_endian = false,
|
||||
.bit_order_lsb = false,
|
||||
.skip_mask = false,
|
||||
.total_slot = I2S_TDM_AUTO_SLOT_NUM
|
||||
},
|
||||
.gpio_cfg = {
|
||||
.mclk = mclk,
|
||||
.bclk = bclk,
|
||||
.ws = ws,
|
||||
.dout = I2S_GPIO_UNUSED,
|
||||
.din = din,
|
||||
.invert_flags = {
|
||||
.mclk_inv = false,
|
||||
.bclk_inv = false,
|
||||
.ws_inv = false
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_handle_, &std_cfg));
|
||||
ESP_ERROR_CHECK(i2s_channel_init_tdm_mode(rx_handle_, &tdm_cfg));
|
||||
ESP_LOGI(TAG, "Duplex channels created");
|
||||
}
|
||||
|
||||
void CoreS3AudioCodec::SetOutputVolume(int volume) {
|
||||
ESP_ERROR_CHECK(esp_codec_dev_set_out_vol(output_dev_, volume));
|
||||
AudioCodec::SetOutputVolume(volume);
|
||||
}
|
||||
|
||||
void CoreS3AudioCodec::EnableInput(bool enable) {
|
||||
if (enable == input_enabled_) {
|
||||
return;
|
||||
}
|
||||
if (enable) {
|
||||
esp_codec_dev_sample_info_t fs = {
|
||||
.bits_per_sample = 16,
|
||||
.channel = 2,
|
||||
.channel_mask = ESP_CODEC_DEV_MAKE_CHANNEL_MASK(0),
|
||||
.sample_rate = (uint32_t)output_sample_rate_,
|
||||
.mclk_multiple = 0,
|
||||
};
|
||||
if (input_reference_) {
|
||||
fs.channel_mask |= ESP_CODEC_DEV_MAKE_CHANNEL_MASK(1);
|
||||
}
|
||||
ESP_ERROR_CHECK(esp_codec_dev_open(input_dev_, &fs));
|
||||
ESP_ERROR_CHECK(esp_codec_dev_set_in_channel_gain(input_dev_, ESP_CODEC_DEV_MAKE_CHANNEL_MASK(0), input_gain_));
|
||||
} else {
|
||||
ESP_ERROR_CHECK(esp_codec_dev_close(input_dev_));
|
||||
}
|
||||
AudioCodec::EnableInput(enable);
|
||||
}
|
||||
|
||||
void CoreS3AudioCodec::EnableOutput(bool enable) {
|
||||
if (enable == output_enabled_) {
|
||||
return;
|
||||
}
|
||||
if (enable) {
|
||||
// Play 16bit 1 channel
|
||||
esp_codec_dev_sample_info_t fs = {
|
||||
.bits_per_sample = 16,
|
||||
.channel = 1,
|
||||
.channel_mask = 0,
|
||||
.sample_rate = (uint32_t)output_sample_rate_,
|
||||
.mclk_multiple = 0,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_codec_dev_open(output_dev_, &fs));
|
||||
ESP_ERROR_CHECK(esp_codec_dev_set_out_vol(output_dev_, output_volume_));
|
||||
} else {
|
||||
ESP_ERROR_CHECK(esp_codec_dev_close(output_dev_));
|
||||
}
|
||||
AudioCodec::EnableOutput(enable);
|
||||
}
|
||||
|
||||
int CoreS3AudioCodec::Read(int16_t* dest, int samples) {
|
||||
if (input_enabled_) {
|
||||
ESP_ERROR_CHECK_WITHOUT_ABORT(esp_codec_dev_read(input_dev_, (void*)dest, samples * sizeof(int16_t)));
|
||||
}
|
||||
return samples;
|
||||
}
|
||||
|
||||
int CoreS3AudioCodec::Write(const int16_t* data, int samples) {
|
||||
if (output_enabled_) {
|
||||
ESP_ERROR_CHECK_WITHOUT_ABORT(esp_codec_dev_write(output_dev_, (void*)data, samples * sizeof(int16_t)));
|
||||
}
|
||||
return samples;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
#ifndef _BOX_AUDIO_CODEC_H
|
||||
#define _BOX_AUDIO_CODEC_H
|
||||
|
||||
#include "audio_codec.h"
|
||||
|
||||
#include <esp_codec_dev.h>
|
||||
#include <esp_codec_dev_defaults.h>
|
||||
|
||||
class CoreS3AudioCodec : public AudioCodec {
|
||||
private:
|
||||
const audio_codec_data_if_t* data_if_ = nullptr;
|
||||
const audio_codec_ctrl_if_t* out_ctrl_if_ = nullptr;
|
||||
const audio_codec_if_t* out_codec_if_ = nullptr;
|
||||
const audio_codec_ctrl_if_t* in_ctrl_if_ = nullptr;
|
||||
const audio_codec_if_t* in_codec_if_ = nullptr;
|
||||
const audio_codec_gpio_if_t* gpio_if_ = nullptr;
|
||||
|
||||
esp_codec_dev_handle_t output_dev_ = nullptr;
|
||||
esp_codec_dev_handle_t input_dev_ = nullptr;
|
||||
|
||||
void CreateDuplexChannels(gpio_num_t mclk, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din);
|
||||
|
||||
virtual int Read(int16_t* dest, int samples) override;
|
||||
virtual int Write(const int16_t* data, int samples) override;
|
||||
|
||||
public:
|
||||
CoreS3AudioCodec(void* i2c_master_handle, int input_sample_rate, int output_sample_rate,
|
||||
gpio_num_t mclk, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din,
|
||||
uint8_t aw88298_addr, uint8_t es7210_addr, bool input_reference);
|
||||
virtual ~CoreS3AudioCodec();
|
||||
|
||||
virtual void SetOutputVolume(int volume) override;
|
||||
virtual void EnableInput(bool enable) override;
|
||||
virtual void EnableOutput(bool enable) override;
|
||||
};
|
||||
|
||||
#endif // _BOX_AUDIO_CODEC_H
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#include "hal_bridge.h"
|
||||
#include "stackchan_display.h"
|
||||
#include <esp_log.h>
|
||||
#include <esp_err.h>
|
||||
#include <nvs.h>
|
||||
#include <nvs_flash.h>
|
||||
#include <driver/gpio.h>
|
||||
#include <esp_event.h>
|
||||
#include <application.h>
|
||||
#include <board.h>
|
||||
#include <display.h>
|
||||
#include <mutex>
|
||||
#include <assets.h>
|
||||
|
||||
static const char* _tag = "HAL_BRIDGE";
|
||||
|
||||
namespace hal_bridge {
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* State and touch point */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
static std::mutex _mutex;
|
||||
static Data_t _data;
|
||||
|
||||
void lock()
|
||||
{
|
||||
_mutex.lock();
|
||||
}
|
||||
|
||||
void unlock()
|
||||
{
|
||||
_mutex.unlock();
|
||||
}
|
||||
|
||||
Data_t& get_data()
|
||||
{
|
||||
return _data;
|
||||
}
|
||||
|
||||
void set_touch_point(int num, int x, int y)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_mutex);
|
||||
_data.touchPoint.num = num;
|
||||
_data.touchPoint.x = x;
|
||||
_data.touchPoint.y = y;
|
||||
}
|
||||
|
||||
TouchPoint_t get_touch_point()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_mutex);
|
||||
return _data.touchPoint;
|
||||
}
|
||||
|
||||
bool is_xiaozhi_mode()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_mutex);
|
||||
return _data.isXiaozhiMode;
|
||||
}
|
||||
|
||||
void set_xiaozhi_mode(bool mode)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_mutex);
|
||||
_data.isXiaozhiMode = mode;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Display */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
#define DISPLAY_TYPE StackChanAvatarDisplay
|
||||
|
||||
lv_disp_t* display_get_lvgl_display()
|
||||
{
|
||||
auto display = static_cast<DISPLAY_TYPE*>(Board::GetInstance().GetDisplay());
|
||||
return display->GetLvglDisplay();
|
||||
}
|
||||
|
||||
void disply_lvgl_lock()
|
||||
{
|
||||
auto display = static_cast<DISPLAY_TYPE*>(Board::GetInstance().GetDisplay());
|
||||
display->LvglLock();
|
||||
}
|
||||
|
||||
void disply_lvgl_unlock()
|
||||
{
|
||||
auto display = static_cast<DISPLAY_TYPE*>(Board::GetInstance().GetDisplay());
|
||||
display->LvglUnlock();
|
||||
}
|
||||
|
||||
void display_setup_xiaozhi_ui()
|
||||
{
|
||||
auto display = static_cast<DISPLAY_TYPE*>(Board::GetInstance().GetDisplay());
|
||||
display->SetupXiaoZhiUI();
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Application */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void xiaozhi_board_init()
|
||||
{
|
||||
// Initialize the default event loop
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
|
||||
// Init board
|
||||
auto& board = Board::GetInstance();
|
||||
|
||||
// test
|
||||
board.GetBacklight()->SetBrightness(100);
|
||||
}
|
||||
|
||||
void start_xiaozhi_app()
|
||||
{
|
||||
display_setup_xiaozhi_ui();
|
||||
|
||||
set_xiaozhi_mode(true);
|
||||
|
||||
// Launch the application
|
||||
auto& app = Application::GetInstance();
|
||||
app.Start();
|
||||
}
|
||||
|
||||
void app_play_sound(const std::string_view& sound)
|
||||
{
|
||||
auto& app = Application::GetInstance();
|
||||
app.PlaySound(sound);
|
||||
}
|
||||
|
||||
} // namespace hal_bridge
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#pragma once
|
||||
#include "stackchan_camera.h"
|
||||
#include <lvgl.h>
|
||||
#include <driver/i2c_master.h>
|
||||
#include <string_view>
|
||||
|
||||
namespace hal_bridge {
|
||||
|
||||
struct TouchPoint_t {
|
||||
int num = 0;
|
||||
int x = -1;
|
||||
int y = -1;
|
||||
};
|
||||
|
||||
struct Data_t {
|
||||
TouchPoint_t touchPoint;
|
||||
bool isXiaozhiMode = false;
|
||||
};
|
||||
|
||||
void lock();
|
||||
void unlock();
|
||||
Data_t& get_data();
|
||||
|
||||
void set_touch_point(int num, int x, int y);
|
||||
TouchPoint_t get_touch_point();
|
||||
|
||||
bool is_xiaozhi_mode();
|
||||
void set_xiaozhi_mode(bool mode);
|
||||
|
||||
void disply_lvgl_lock();
|
||||
void disply_lvgl_unlock();
|
||||
lv_disp_t* display_get_lvgl_display();
|
||||
void display_setup_xiaozhi_ui();
|
||||
|
||||
void xiaozhi_board_init();
|
||||
void start_xiaozhi_app();
|
||||
|
||||
i2c_master_bus_handle_t board_get_i2c_bus();
|
||||
|
||||
StackChanCamera* board_get_camera();
|
||||
|
||||
void app_play_sound(const std::string_view& sound);
|
||||
|
||||
} // namespace hal_bridge
|
||||
@@ -0,0 +1,497 @@
|
||||
#include "wifi_board.h"
|
||||
#include "cores3_audio_codec.h"
|
||||
#include "display/lcd_display.h"
|
||||
#include "stackchan_display.h"
|
||||
#include "application.h"
|
||||
#include "config.h"
|
||||
#include "power_save_timer.h"
|
||||
#include "i2c_device.h"
|
||||
#include "axp2101.h"
|
||||
|
||||
#include <esp_log.h>
|
||||
#include <driver/i2c_master.h>
|
||||
#include <wifi_station.h>
|
||||
#include <esp_lcd_panel_io.h>
|
||||
#include <esp_lcd_panel_ops.h>
|
||||
#include <esp_lcd_ili9341.h>
|
||||
#include <esp_timer.h>
|
||||
// #include "esp32_camera.h"
|
||||
#include "stackchan_camera.h"
|
||||
#include "hal_bridge.h"
|
||||
|
||||
#define TAG "M5Stack-StackChan-Board"
|
||||
|
||||
#define XPOWERS_AXP2101_ICC_CHG_SET (0x62)
|
||||
|
||||
class Pmic : public Axp2101 {
|
||||
public:
|
||||
/**
|
||||
* @brief axp2101 charge currnet voltage parameters.
|
||||
*/
|
||||
typedef enum __xpowers_axp2101_chg_curr {
|
||||
XPOWERS_AXP2101_CHG_CUR_0MA,
|
||||
XPOWERS_AXP2101_CHG_CUR_100MA = 4,
|
||||
XPOWERS_AXP2101_CHG_CUR_125MA,
|
||||
XPOWERS_AXP2101_CHG_CUR_150MA,
|
||||
XPOWERS_AXP2101_CHG_CUR_175MA,
|
||||
XPOWERS_AXP2101_CHG_CUR_200MA,
|
||||
XPOWERS_AXP2101_CHG_CUR_300MA,
|
||||
XPOWERS_AXP2101_CHG_CUR_400MA,
|
||||
XPOWERS_AXP2101_CHG_CUR_500MA,
|
||||
XPOWERS_AXP2101_CHG_CUR_600MA,
|
||||
XPOWERS_AXP2101_CHG_CUR_700MA,
|
||||
XPOWERS_AXP2101_CHG_CUR_800MA,
|
||||
XPOWERS_AXP2101_CHG_CUR_900MA,
|
||||
XPOWERS_AXP2101_CHG_CUR_1000MA,
|
||||
} xpowers_axp2101_chg_curr_t;
|
||||
|
||||
// Power Init
|
||||
Pmic(i2c_master_bus_handle_t i2c_bus, uint8_t addr) : Axp2101(i2c_bus, addr)
|
||||
{
|
||||
uint8_t data = ReadReg(0x90);
|
||||
data |= 0b10110100;
|
||||
WriteReg(0x90, data);
|
||||
WriteReg(0x99, (0b11110 - 5));
|
||||
WriteReg(0x97, (0b11110 - 2));
|
||||
WriteReg(0x69, 0b00110101);
|
||||
WriteReg(0x30, 0b111111);
|
||||
WriteReg(0x90, 0xBF);
|
||||
WriteReg(0x94, 33 - 5);
|
||||
WriteReg(0x95, 33 - 5);
|
||||
|
||||
auto ret = setChargerConstantCurr(XPOWERS_AXP2101_CHG_CUR_700MA);
|
||||
if (!ret) {
|
||||
ESP_LOGE(TAG, "Set charge current failed");
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Set charge current success");
|
||||
}
|
||||
}
|
||||
|
||||
void SetBrightness(uint8_t brightness)
|
||||
{
|
||||
brightness = ((brightness + 641) >> 5);
|
||||
WriteReg(0x99, brightness);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set charge current.
|
||||
* @param opt: See xpowers_axp2101_chg_curr_t enum for details.
|
||||
* @retval
|
||||
*/
|
||||
bool setChargerConstantCurr(uint8_t opt)
|
||||
{
|
||||
if (opt > XPOWERS_AXP2101_CHG_CUR_1000MA) {
|
||||
return false;
|
||||
}
|
||||
int val = ReadReg(XPOWERS_AXP2101_ICC_CHG_SET);
|
||||
if (val == -1) {
|
||||
return false;
|
||||
}
|
||||
val &= 0xE0;
|
||||
WriteReg(XPOWERS_AXP2101_ICC_CHG_SET, val | opt);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class CustomBacklight : public Backlight {
|
||||
public:
|
||||
CustomBacklight(Pmic* pmic) : pmic_(pmic)
|
||||
{
|
||||
}
|
||||
|
||||
void SetBrightnessImpl(uint8_t brightness) override
|
||||
{
|
||||
pmic_->SetBrightness(target_brightness_);
|
||||
brightness_ = target_brightness_;
|
||||
}
|
||||
|
||||
private:
|
||||
Pmic* pmic_;
|
||||
};
|
||||
|
||||
class Aw9523 : public I2cDevice {
|
||||
public:
|
||||
// Exanpd IO Init
|
||||
Aw9523(i2c_master_bus_handle_t i2c_bus, uint8_t addr) : I2cDevice(i2c_bus, addr)
|
||||
{
|
||||
WriteReg(0x02, 0b00000111); // P0
|
||||
WriteReg(0x03, 0b10001111); // P1
|
||||
WriteReg(0x04, 0b00011000); // CONFIG_P0
|
||||
WriteReg(0x05, 0b00001100); // CONFIG_P1
|
||||
WriteReg(0x11, 0b00010000); // GCR P0 port is Push-Pull mode.
|
||||
WriteReg(0x12, 0b11111111); // LEDMODE_P0
|
||||
WriteReg(0x13, 0b11111111); // LEDMODE_P1
|
||||
}
|
||||
|
||||
void ResetAw88298()
|
||||
{
|
||||
ESP_LOGI(TAG, "Reset AW88298");
|
||||
WriteReg(0x02, 0b00000011);
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
WriteReg(0x02, 0b00000111);
|
||||
vTaskDelay(pdMS_TO_TICKS(50));
|
||||
}
|
||||
|
||||
void ResetIli9342()
|
||||
{
|
||||
ESP_LOGI(TAG, "Reset IlI9342");
|
||||
WriteReg(0x03, 0b10000001);
|
||||
vTaskDelay(pdMS_TO_TICKS(20));
|
||||
WriteReg(0x03, 0b10000011);
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
}
|
||||
};
|
||||
|
||||
class Ft6336 : public I2cDevice {
|
||||
public:
|
||||
struct TouchPoint_t {
|
||||
int num = 0;
|
||||
int x = -1;
|
||||
int y = -1;
|
||||
};
|
||||
|
||||
Ft6336(i2c_master_bus_handle_t i2c_bus, uint8_t addr) : I2cDevice(i2c_bus, addr)
|
||||
{
|
||||
uint8_t chip_id = ReadReg(0xA3);
|
||||
ESP_LOGI(TAG, "Get chip ID: 0x%02X", chip_id);
|
||||
read_buffer_ = new uint8_t[6];
|
||||
}
|
||||
|
||||
~Ft6336()
|
||||
{
|
||||
delete[] read_buffer_;
|
||||
}
|
||||
|
||||
void UpdateTouchPoint()
|
||||
{
|
||||
ReadRegs(0x02, read_buffer_, 6);
|
||||
tp_.num = read_buffer_[0] & 0x0F;
|
||||
tp_.x = ((read_buffer_[1] & 0x0F) << 8) | read_buffer_[2];
|
||||
tp_.y = ((read_buffer_[3] & 0x0F) << 8) | read_buffer_[4];
|
||||
}
|
||||
|
||||
inline const TouchPoint_t& GetTouchPoint()
|
||||
{
|
||||
return tp_;
|
||||
}
|
||||
|
||||
private:
|
||||
uint8_t* read_buffer_ = nullptr;
|
||||
TouchPoint_t tp_;
|
||||
};
|
||||
|
||||
class M5StackCoreS3Board : public WifiBoard {
|
||||
private:
|
||||
i2c_master_bus_handle_t i2c_bus_;
|
||||
Pmic* pmic_;
|
||||
Aw9523* aw9523_;
|
||||
Ft6336* ft6336_;
|
||||
LvglDisplay* display_;
|
||||
StackChanCamera* camera_;
|
||||
esp_timer_handle_t touchpad_timer_;
|
||||
PowerSaveTimer* power_save_timer_;
|
||||
|
||||
void InitializePowerSaveTimer()
|
||||
{
|
||||
power_save_timer_ = new PowerSaveTimer(-1, 300, 600);
|
||||
power_save_timer_->OnEnterSleepMode([this]() {
|
||||
GetDisplay()->SetPowerSaveMode(true);
|
||||
// GetBacklight()->SetBrightness(10);
|
||||
});
|
||||
power_save_timer_->OnExitSleepMode([this]() {
|
||||
GetDisplay()->SetPowerSaveMode(false);
|
||||
GetBacklight()->RestoreBrightness();
|
||||
});
|
||||
power_save_timer_->OnShutdownRequest([this]() { pmic_->PowerOff(); });
|
||||
power_save_timer_->SetEnabled(true);
|
||||
}
|
||||
|
||||
void InitializeI2c()
|
||||
{
|
||||
// Initialize I2C peripheral
|
||||
i2c_master_bus_config_t i2c_bus_cfg = {
|
||||
.i2c_port = (i2c_port_t)1,
|
||||
.sda_io_num = AUDIO_CODEC_I2C_SDA_PIN,
|
||||
.scl_io_num = AUDIO_CODEC_I2C_SCL_PIN,
|
||||
.clk_source = I2C_CLK_SRC_DEFAULT,
|
||||
.glitch_ignore_cnt = 7,
|
||||
.intr_priority = 0,
|
||||
.trans_queue_depth = 0,
|
||||
.flags =
|
||||
{
|
||||
.enable_internal_pullup = 1,
|
||||
},
|
||||
};
|
||||
ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_));
|
||||
}
|
||||
|
||||
void I2cDetect()
|
||||
{
|
||||
uint8_t address;
|
||||
printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\r\n");
|
||||
for (int i = 0; i < 128; i += 16) {
|
||||
printf("%02x: ", i);
|
||||
for (int j = 0; j < 16; j++) {
|
||||
fflush(stdout);
|
||||
address = i + j;
|
||||
esp_err_t ret = i2c_master_probe(i2c_bus_, address, pdMS_TO_TICKS(200));
|
||||
if (ret == ESP_OK) {
|
||||
printf("%02x ", address);
|
||||
} else if (ret == ESP_ERR_TIMEOUT) {
|
||||
printf("UU ");
|
||||
} else {
|
||||
printf("-- ");
|
||||
}
|
||||
}
|
||||
printf("\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
void InitializeAxp2101()
|
||||
{
|
||||
ESP_LOGI(TAG, "Init AXP2101");
|
||||
pmic_ = new Pmic(i2c_bus_, 0x34);
|
||||
}
|
||||
|
||||
void InitializeAw9523()
|
||||
{
|
||||
ESP_LOGI(TAG, "Init AW9523");
|
||||
aw9523_ = new Aw9523(i2c_bus_, 0x58);
|
||||
vTaskDelay(pdMS_TO_TICKS(50));
|
||||
}
|
||||
|
||||
void PollTouchpad()
|
||||
{
|
||||
static bool was_touched = false;
|
||||
static int64_t touch_start_time = 0;
|
||||
const int64_t TOUCH_THRESHOLD_MS = 500; // 触摸时长阈值,超过500ms视为长按
|
||||
|
||||
ft6336_->UpdateTouchPoint();
|
||||
auto& touch_point = ft6336_->GetTouchPoint();
|
||||
|
||||
if (!hal_bridge::is_xiaozhi_mode()) {
|
||||
hal_bridge::set_touch_point(touch_point.num, touch_point.x, touch_point.y);
|
||||
return;
|
||||
}
|
||||
|
||||
// 检测触摸开始
|
||||
if (touch_point.num > 0 && !was_touched) {
|
||||
was_touched = true;
|
||||
touch_start_time = esp_timer_get_time() / 1000; // 转换为毫秒
|
||||
}
|
||||
// 检测触摸释放
|
||||
else if (touch_point.num == 0 && was_touched) {
|
||||
was_touched = false;
|
||||
int64_t touch_duration = (esp_timer_get_time() / 1000) - touch_start_time;
|
||||
|
||||
// 只有短触才触发
|
||||
if (touch_duration < TOUCH_THRESHOLD_MS) {
|
||||
auto& app = Application::GetInstance();
|
||||
if (app.GetDeviceState() == kDeviceStateStarting && !WifiStation::GetInstance().IsConnected()) {
|
||||
ResetWifiConfiguration();
|
||||
}
|
||||
app.ToggleChatState();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InitializeFt6336TouchPad()
|
||||
{
|
||||
ESP_LOGI(TAG, "Init FT6336");
|
||||
ft6336_ = new Ft6336(i2c_bus_, 0x38);
|
||||
|
||||
// 创建定时器,20ms 间隔
|
||||
esp_timer_create_args_t timer_args = {
|
||||
.callback =
|
||||
[](void* arg) {
|
||||
M5StackCoreS3Board* board = (M5StackCoreS3Board*)arg;
|
||||
board->PollTouchpad();
|
||||
},
|
||||
.arg = this,
|
||||
.dispatch_method = ESP_TIMER_TASK,
|
||||
.name = "touchpad_timer",
|
||||
.skip_unhandled_events = true,
|
||||
};
|
||||
|
||||
ESP_ERROR_CHECK(esp_timer_create(&timer_args, &touchpad_timer_));
|
||||
ESP_ERROR_CHECK(esp_timer_start_periodic(touchpad_timer_, 20 * 1000));
|
||||
}
|
||||
|
||||
void InitializeSpi()
|
||||
{
|
||||
spi_bus_config_t buscfg = {};
|
||||
buscfg.mosi_io_num = GPIO_NUM_37;
|
||||
buscfg.miso_io_num = GPIO_NUM_NC;
|
||||
buscfg.sclk_io_num = GPIO_NUM_36;
|
||||
buscfg.quadwp_io_num = GPIO_NUM_NC;
|
||||
buscfg.quadhd_io_num = GPIO_NUM_NC;
|
||||
buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t);
|
||||
ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &buscfg, SPI_DMA_CH_AUTO));
|
||||
}
|
||||
|
||||
void InitializeIli9342Display()
|
||||
{
|
||||
ESP_LOGI(TAG, "Init IlI9342");
|
||||
|
||||
esp_lcd_panel_io_handle_t panel_io = nullptr;
|
||||
esp_lcd_panel_handle_t panel = nullptr;
|
||||
|
||||
ESP_LOGD(TAG, "Install panel IO");
|
||||
esp_lcd_panel_io_spi_config_t io_config = {};
|
||||
io_config.cs_gpio_num = GPIO_NUM_3;
|
||||
io_config.dc_gpio_num = GPIO_NUM_35;
|
||||
io_config.spi_mode = 2;
|
||||
io_config.pclk_hz = 40 * 1000 * 1000;
|
||||
io_config.trans_queue_depth = 10;
|
||||
io_config.lcd_cmd_bits = 8;
|
||||
io_config.lcd_param_bits = 8;
|
||||
ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI3_HOST, &io_config, &panel_io));
|
||||
|
||||
ESP_LOGD(TAG, "Install LCD driver");
|
||||
esp_lcd_panel_dev_config_t panel_config = {};
|
||||
panel_config.reset_gpio_num = GPIO_NUM_NC;
|
||||
panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_BGR;
|
||||
panel_config.bits_per_pixel = 16;
|
||||
ESP_ERROR_CHECK(esp_lcd_new_panel_ili9341(panel_io, &panel_config, &panel));
|
||||
|
||||
esp_lcd_panel_reset(panel);
|
||||
aw9523_->ResetIli9342();
|
||||
|
||||
esp_lcd_panel_init(panel);
|
||||
esp_lcd_panel_invert_color(panel, true);
|
||||
esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY);
|
||||
esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y);
|
||||
|
||||
// display_ = new StackChanLcdDisplay(panel_io, panel, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X,
|
||||
// DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY);
|
||||
display_ = new StackChanAvatarDisplay(panel_io, panel, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X,
|
||||
DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY);
|
||||
}
|
||||
|
||||
void InitializeCamera()
|
||||
{
|
||||
ESP_LOGI(TAG, "Init Camera");
|
||||
|
||||
static esp_cam_ctlr_dvp_pin_config_t dvp_pin_config = {
|
||||
.data_width = CAM_CTLR_DATA_WIDTH_8,
|
||||
.data_io =
|
||||
{
|
||||
[0] = CAMERA_PIN_D0,
|
||||
[1] = CAMERA_PIN_D1,
|
||||
[2] = CAMERA_PIN_D2,
|
||||
[3] = CAMERA_PIN_D3,
|
||||
[4] = CAMERA_PIN_D4,
|
||||
[5] = CAMERA_PIN_D5,
|
||||
[6] = CAMERA_PIN_D6,
|
||||
[7] = CAMERA_PIN_D7,
|
||||
},
|
||||
.vsync_io = CAMERA_PIN_VSYNC,
|
||||
.de_io = CAMERA_PIN_HREF,
|
||||
.pclk_io = CAMERA_PIN_PCLK,
|
||||
.xclk_io = CAMERA_PIN_XCLK,
|
||||
};
|
||||
|
||||
esp_video_init_sccb_config_t sccb_config = {
|
||||
.init_sccb = false,
|
||||
.i2c_handle = i2c_bus_,
|
||||
.freq = 100000,
|
||||
};
|
||||
|
||||
esp_video_init_dvp_config_t dvp_config = {
|
||||
.sccb_config = sccb_config,
|
||||
.reset_pin = CAMERA_PIN_RESET,
|
||||
.pwdn_pin = CAMERA_PIN_PWDN,
|
||||
.dvp_pin = dvp_pin_config,
|
||||
.xclk_freq = XCLK_FREQ_HZ,
|
||||
};
|
||||
|
||||
esp_video_init_config_t video_config = {
|
||||
.dvp = &dvp_config,
|
||||
};
|
||||
|
||||
camera_ = new StackChanCamera(video_config);
|
||||
camera_->SetHMirror(false);
|
||||
}
|
||||
|
||||
public:
|
||||
M5StackCoreS3Board()
|
||||
{
|
||||
InitializePowerSaveTimer();
|
||||
InitializeI2c();
|
||||
InitializeAxp2101();
|
||||
InitializeAw9523();
|
||||
I2cDetect();
|
||||
InitializeSpi();
|
||||
InitializeIli9342Display();
|
||||
InitializeCamera();
|
||||
InitializeFt6336TouchPad();
|
||||
GetBacklight()->RestoreBrightness();
|
||||
}
|
||||
|
||||
virtual AudioCodec* GetAudioCodec() override
|
||||
{
|
||||
static CoreS3AudioCodec audio_codec(i2c_bus_, AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE,
|
||||
AUDIO_I2S_GPIO_MCLK, AUDIO_I2S_GPIO_BCLK, AUDIO_I2S_GPIO_WS,
|
||||
AUDIO_I2S_GPIO_DOUT, AUDIO_I2S_GPIO_DIN, AUDIO_CODEC_AW88298_ADDR,
|
||||
AUDIO_CODEC_ES7210_ADDR, AUDIO_INPUT_REFERENCE);
|
||||
return &audio_codec;
|
||||
}
|
||||
|
||||
virtual Display* GetDisplay() override
|
||||
{
|
||||
return display_;
|
||||
}
|
||||
|
||||
virtual Camera* GetCamera() override
|
||||
{
|
||||
return camera_;
|
||||
}
|
||||
|
||||
virtual bool GetBatteryLevel(int& level, bool& charging, bool& discharging) override
|
||||
{
|
||||
static bool last_discharging = false;
|
||||
charging = pmic_->IsCharging();
|
||||
discharging = pmic_->IsDischarging();
|
||||
if (discharging != last_discharging) {
|
||||
power_save_timer_->SetEnabled(discharging);
|
||||
last_discharging = discharging;
|
||||
}
|
||||
|
||||
level = pmic_->GetBatteryLevel();
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void SetPowerSaveMode(bool enabled) override
|
||||
{
|
||||
if (!enabled) {
|
||||
power_save_timer_->WakeUp();
|
||||
}
|
||||
WifiBoard::SetPowerSaveMode(enabled);
|
||||
}
|
||||
|
||||
virtual Backlight* GetBacklight() override
|
||||
{
|
||||
static CustomBacklight backlight(pmic_);
|
||||
return &backlight;
|
||||
}
|
||||
|
||||
i2c_master_bus_handle_t GetI2cBus()
|
||||
{
|
||||
return i2c_bus_;
|
||||
}
|
||||
};
|
||||
|
||||
DECLARE_BOARD(M5StackCoreS3Board);
|
||||
|
||||
i2c_master_bus_handle_t hal_bridge::board_get_i2c_bus()
|
||||
{
|
||||
auto& board = (M5StackCoreS3Board&)Board::GetInstance();
|
||||
return board.GetI2cBus();
|
||||
}
|
||||
|
||||
StackChanCamera* hal_bridge::board_get_camera()
|
||||
{
|
||||
auto& board = Board::GetInstance();
|
||||
auto camera = (StackChanCamera*)board.GetCamera();
|
||||
return camera;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,82 @@
|
||||
#pragma once
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32
|
||||
#include <lvgl.h>
|
||||
#include <thread>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/queue.h>
|
||||
|
||||
#include "camera.h"
|
||||
#include "jpg/image_to_jpeg.h"
|
||||
#include "esp_video_init.h"
|
||||
|
||||
struct JpegChunk {
|
||||
uint8_t* data;
|
||||
size_t len;
|
||||
};
|
||||
|
||||
class StackChanCamera : public Camera {
|
||||
private:
|
||||
struct FrameBuffer {
|
||||
uint8_t* data = nullptr;
|
||||
size_t len = 0;
|
||||
uint16_t width = 0;
|
||||
uint16_t height = 0;
|
||||
v4l2_pix_fmt_t format = 0;
|
||||
} frame_;
|
||||
v4l2_pix_fmt_t sensor_format_ = 0;
|
||||
#ifdef CONFIG_XIAOZHI_ENABLE_ROTATE_CAMERA_IMAGE
|
||||
uint16_t sensor_width_ = 0;
|
||||
uint16_t sensor_height_ = 0;
|
||||
#endif // CONFIG_XIAOZHI_ENABLE_ROTATE_CAMERA_IMAGE
|
||||
int video_fd_ = -1;
|
||||
bool streaming_on_ = false;
|
||||
struct MmapBuffer {
|
||||
void* start = nullptr;
|
||||
size_t length = 0;
|
||||
};
|
||||
std::vector<MmapBuffer> mmap_buffers_;
|
||||
std::string explain_url_;
|
||||
std::string explain_token_;
|
||||
std::thread encoder_thread_;
|
||||
|
||||
public:
|
||||
StackChanCamera(const esp_video_init_config_t& config);
|
||||
~StackChanCamera();
|
||||
|
||||
virtual void SetExplainUrl(const std::string& url, const std::string& token);
|
||||
virtual bool Capture() override;
|
||||
bool StreamCaptures();
|
||||
|
||||
// 翻转控制函数
|
||||
virtual bool SetHMirror(bool enabled) override;
|
||||
virtual bool SetVFlip(bool enabled) override;
|
||||
virtual std::string Explain(const std::string& question);
|
||||
|
||||
const uint8_t* GetFrameData()
|
||||
{
|
||||
return frame_.data;
|
||||
}
|
||||
size_t GetFrameSize()
|
||||
{
|
||||
return frame_.len;
|
||||
}
|
||||
int GetFrameWidth()
|
||||
{
|
||||
return frame_.width;
|
||||
}
|
||||
int GetFrameHeight()
|
||||
{
|
||||
return frame_.height;
|
||||
}
|
||||
int GetFrameFormat()
|
||||
{
|
||||
return frame_.format;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // ndef CONFIG_IDF_TARGET_ESP32
|
||||
@@ -0,0 +1,462 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#include "stackchan_display.h"
|
||||
#include <esp_log.h>
|
||||
#include <esp_err.h>
|
||||
#include <esp_lvgl_port.h>
|
||||
#include <esp_psram.h>
|
||||
#include <vector>
|
||||
#include <cstring>
|
||||
#include <settings.h>
|
||||
#include <lvgl.h>
|
||||
#include <lvgl_theme.h>
|
||||
#include <stackchan/stackchan.h>
|
||||
#include <assets/lang_config.h>
|
||||
#include <hal/hal.h>
|
||||
|
||||
using namespace stackchan;
|
||||
using namespace stackchan::avatar;
|
||||
|
||||
#define TAG "StackChanAvatarDisplay"
|
||||
|
||||
LV_FONT_DECLARE(BUILTIN_TEXT_FONT);
|
||||
LV_FONT_DECLARE(BUILTIN_ICON_FONT);
|
||||
LV_FONT_DECLARE(font_awesome_30_4);
|
||||
|
||||
// Have to register themes, so the asset apply can update the text font
|
||||
void StackChanAvatarDisplay::InitializeLcdThemes()
|
||||
{
|
||||
auto text_font = std::make_shared<LvglBuiltInFont>(&BUILTIN_TEXT_FONT);
|
||||
auto icon_font = std::make_shared<LvglBuiltInFont>(&BUILTIN_ICON_FONT);
|
||||
auto large_icon_font = std::make_shared<LvglBuiltInFont>(&font_awesome_30_4);
|
||||
|
||||
// light theme
|
||||
auto light_theme = new LvglTheme("light");
|
||||
light_theme->set_background_color(lv_color_hex(0xFFFFFF)); // rgb(255, 255, 255)
|
||||
light_theme->set_text_color(lv_color_hex(0x000000)); // rgb(0, 0, 0)
|
||||
light_theme->set_chat_background_color(lv_color_hex(0xE0E0E0)); // rgb(224, 224, 224)
|
||||
light_theme->set_user_bubble_color(lv_color_hex(0x00FF00)); // rgb(0, 128, 0)
|
||||
light_theme->set_assistant_bubble_color(lv_color_hex(0xDDDDDD)); // rgb(221, 221, 221)
|
||||
light_theme->set_system_bubble_color(lv_color_hex(0xFFFFFF)); // rgb(255, 255, 255)
|
||||
light_theme->set_system_text_color(lv_color_hex(0x000000)); // rgb(0, 0, 0)
|
||||
light_theme->set_border_color(lv_color_hex(0x000000)); // rgb(0, 0, 0)
|
||||
light_theme->set_low_battery_color(lv_color_hex(0x000000)); // rgb(0, 0, 0)
|
||||
light_theme->set_text_font(text_font);
|
||||
light_theme->set_icon_font(icon_font);
|
||||
light_theme->set_large_icon_font(large_icon_font);
|
||||
|
||||
// dark theme
|
||||
auto dark_theme = new LvglTheme("dark");
|
||||
dark_theme->set_background_color(lv_color_hex(0x000000)); // rgb(0, 0, 0)
|
||||
dark_theme->set_text_color(lv_color_hex(0xFFFFFF)); // rgb(255, 255, 255)
|
||||
dark_theme->set_chat_background_color(lv_color_hex(0x1F1F1F)); // rgb(31, 31, 31)
|
||||
dark_theme->set_user_bubble_color(lv_color_hex(0x00FF00)); // rgb(0, 128, 0)
|
||||
dark_theme->set_assistant_bubble_color(lv_color_hex(0x222222)); // rgb(34, 34, 34)
|
||||
dark_theme->set_system_bubble_color(lv_color_hex(0x000000)); // rgb(0, 0, 0)
|
||||
dark_theme->set_system_text_color(lv_color_hex(0xFFFFFF)); // rgb(255, 255, 255)
|
||||
dark_theme->set_border_color(lv_color_hex(0xFFFFFF)); // rgb(255, 255, 255)
|
||||
dark_theme->set_low_battery_color(lv_color_hex(0xFF0000)); // rgb(255, 0, 0)
|
||||
dark_theme->set_text_font(text_font);
|
||||
dark_theme->set_icon_font(icon_font);
|
||||
dark_theme->set_large_icon_font(large_icon_font);
|
||||
|
||||
auto& theme_manager = LvglThemeManager::GetInstance();
|
||||
theme_manager.RegisterTheme("light", light_theme);
|
||||
theme_manager.RegisterTheme("dark", dark_theme);
|
||||
}
|
||||
|
||||
StackChanAvatarDisplay::StackChanAvatarDisplay(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_handle_t panel,
|
||||
int width, int height, int offset_x, int offset_y, bool mirror_x,
|
||||
bool mirror_y, bool swap_xy)
|
||||
: LvglDisplay(), panel_io_(panel_io), panel_(panel)
|
||||
{
|
||||
width_ = width;
|
||||
height_ = height;
|
||||
|
||||
// Initialize LCD themes
|
||||
InitializeLcdThemes();
|
||||
|
||||
// Load theme from settings
|
||||
Settings settings("display", false);
|
||||
std::string theme_name = settings.GetString("theme", "light");
|
||||
current_theme_ = LvglThemeManager::GetInstance().GetTheme(theme_name);
|
||||
|
||||
// Draw white screen
|
||||
std::vector<uint16_t> buffer(width_, 0xFFFF);
|
||||
for (int y = 0; y < height_; y++) {
|
||||
esp_lcd_panel_draw_bitmap(panel_, 0, y, width_, y + 1, buffer.data());
|
||||
}
|
||||
|
||||
// Set the display to on
|
||||
ESP_LOGI(TAG, "Turning display on");
|
||||
{
|
||||
esp_err_t __err = esp_lcd_panel_disp_on_off(panel_, true);
|
||||
if (__err == ESP_ERR_NOT_SUPPORTED) {
|
||||
ESP_LOGW(TAG, "Panel does not support disp_on_off; assuming ON");
|
||||
} else {
|
||||
ESP_ERROR_CHECK(__err);
|
||||
}
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Initialize LVGL library");
|
||||
lv_init();
|
||||
|
||||
#if CONFIG_SPIRAM
|
||||
// lv image cache, currently only PNG is supported
|
||||
size_t psram_size_mb = esp_psram_get_size() / 1024 / 1024;
|
||||
if (psram_size_mb >= 8) {
|
||||
lv_image_cache_resize(2 * 1024 * 1024, true);
|
||||
ESP_LOGI(TAG, "Use 2MB of PSRAM for image cache");
|
||||
} else if (psram_size_mb >= 2) {
|
||||
lv_image_cache_resize(512 * 1024, true);
|
||||
ESP_LOGI(TAG, "Use 512KB of PSRAM for image cache");
|
||||
}
|
||||
#endif
|
||||
|
||||
ESP_LOGI(TAG, "Initialize LVGL port");
|
||||
lvgl_port_cfg_t port_cfg = ESP_LVGL_PORT_INIT_CONFIG();
|
||||
port_cfg.task_priority = 20;
|
||||
#if CONFIG_SOC_CPU_CORES_NUM > 1
|
||||
port_cfg.task_affinity = 1;
|
||||
#endif
|
||||
lvgl_port_init(&port_cfg);
|
||||
|
||||
ESP_LOGI(TAG, "Adding LCD display");
|
||||
const lvgl_port_display_cfg_t display_cfg = {
|
||||
.io_handle = panel_io_,
|
||||
.panel_handle = panel_,
|
||||
.control_handle = nullptr,
|
||||
.buffer_size = static_cast<uint32_t>(width_ * 20),
|
||||
.double_buffer = true,
|
||||
.trans_size = 0,
|
||||
.hres = static_cast<uint32_t>(width_),
|
||||
.vres = static_cast<uint32_t>(height_),
|
||||
.monochrome = false,
|
||||
.rotation =
|
||||
{
|
||||
.swap_xy = swap_xy,
|
||||
.mirror_x = mirror_x,
|
||||
.mirror_y = mirror_y,
|
||||
},
|
||||
.color_format = LV_COLOR_FORMAT_RGB565,
|
||||
.flags =
|
||||
{
|
||||
.buff_dma = 1,
|
||||
.buff_spiram = 0,
|
||||
.sw_rotate = 0,
|
||||
.swap_bytes = 1,
|
||||
.full_refresh = 0,
|
||||
.direct_mode = 0,
|
||||
},
|
||||
};
|
||||
|
||||
display_ = lvgl_port_add_disp(&display_cfg);
|
||||
if (display_ == nullptr) {
|
||||
ESP_LOGE(TAG, "Failed to add display");
|
||||
return;
|
||||
}
|
||||
|
||||
if (offset_x != 0 || offset_y != 0) {
|
||||
lv_display_set_offset(display_, offset_x, offset_y);
|
||||
}
|
||||
|
||||
// Create a timer to hide the preview image
|
||||
esp_timer_create_args_t preview_timer_args = {
|
||||
.callback =
|
||||
[](void* arg) {
|
||||
StackChanAvatarDisplay* display = static_cast<StackChanAvatarDisplay*>(arg);
|
||||
display->SetPreviewImage(nullptr);
|
||||
},
|
||||
.arg = this,
|
||||
.dispatch_method = ESP_TIMER_TASK,
|
||||
.name = "preview_timer",
|
||||
.skip_unhandled_events = false,
|
||||
};
|
||||
esp_timer_create(&preview_timer_args, &preview_timer_);
|
||||
|
||||
// Robot will be created later in SetupXiaoZhiUI()
|
||||
}
|
||||
|
||||
StackChanAvatarDisplay::~StackChanAvatarDisplay()
|
||||
{
|
||||
ESP_LOGI(TAG, "Destroying StackChanAvatarDisplay");
|
||||
|
||||
if (preview_timer_ != nullptr) {
|
||||
esp_timer_stop(preview_timer_);
|
||||
esp_timer_delete(preview_timer_);
|
||||
}
|
||||
|
||||
if (preview_image_ != nullptr) {
|
||||
lv_obj_del(preview_image_);
|
||||
}
|
||||
|
||||
auto& stackchan = GetStackChan();
|
||||
if (stackchan.hasAvatar()) {
|
||||
stackchan.resetAvatar();
|
||||
}
|
||||
}
|
||||
|
||||
bool StackChanAvatarDisplay::Lock(int timeout_ms)
|
||||
{
|
||||
return lvgl_port_lock(timeout_ms);
|
||||
}
|
||||
|
||||
void StackChanAvatarDisplay::Unlock()
|
||||
{
|
||||
lvgl_port_unlock();
|
||||
}
|
||||
|
||||
lv_disp_t* StackChanAvatarDisplay::GetLvglDisplay()
|
||||
{
|
||||
return display_;
|
||||
}
|
||||
|
||||
void StackChanAvatarDisplay::SetupXiaoZhiUI()
|
||||
{
|
||||
auto& stackchan = GetStackChan();
|
||||
|
||||
if (stackchan.hasAvatar()) {
|
||||
ESP_LOGW(TAG, "Avatar already created");
|
||||
return;
|
||||
}
|
||||
|
||||
DisplayLockGuard lock(this);
|
||||
|
||||
ESP_LOGI(TAG, "Creating Stack-chan Avatar...");
|
||||
|
||||
auto avatar = std::make_unique<DefaultAvatar>();
|
||||
avatar->init(lv_screen_active());
|
||||
|
||||
stackchan.attachAvatar(std::move(avatar));
|
||||
stackchan.addModifier(std::make_unique<BreathModifier>());
|
||||
blink_modifier_id_ = stackchan.addModifier(std::make_unique<BlinkModifier>());
|
||||
stackchan.addModifier(std::make_unique<HeadPetModifier>());
|
||||
// stackchan.addModifier(std::make_unique<IMUMotionModifier>());
|
||||
|
||||
preview_image_ = lv_image_create(lv_screen_active());
|
||||
lv_obj_set_size(preview_image_, 192, 144);
|
||||
lv_obj_align(preview_image_, LV_ALIGN_CENTER, 0, -25);
|
||||
lv_obj_add_flag(preview_image_, LV_OBJ_FLAG_HIDDEN);
|
||||
|
||||
GetHAL().startStackChanAutoUpdate(24);
|
||||
|
||||
ESP_LOGI(TAG, "Avatar created and started");
|
||||
}
|
||||
|
||||
void StackChanAvatarDisplay::LvglLock()
|
||||
{
|
||||
if (!Lock(30000)) {
|
||||
ESP_LOGE("Display", "Failed to lock display");
|
||||
}
|
||||
}
|
||||
|
||||
void StackChanAvatarDisplay::LvglUnlock()
|
||||
{
|
||||
Unlock();
|
||||
}
|
||||
|
||||
void StackChanAvatarDisplay::SetEmotion(const char* emotion)
|
||||
{
|
||||
auto& stackchan = GetStackChan();
|
||||
|
||||
if (!stackchan.hasAvatar() || !emotion) {
|
||||
return;
|
||||
}
|
||||
|
||||
DisplayLockGuard lock(this);
|
||||
|
||||
ESP_LOGE(TAG, "SetEmotion: %s", emotion);
|
||||
|
||||
auto& avatar = stackchan.avatar();
|
||||
|
||||
// Map emotion string to stackchan::Emotion
|
||||
if (strcmp(emotion, "neutral") == 0) {
|
||||
avatar.setEmotion(Emotion::Neutral);
|
||||
} else if (strcmp(emotion, "happy") == 0) {
|
||||
avatar.setEmotion(Emotion::Happy);
|
||||
} else if (strcmp(emotion, "laughing") == 0) {
|
||||
avatar.setEmotion(Emotion::Happy);
|
||||
} else if (strcmp(emotion, "angry") == 0) {
|
||||
avatar.setEmotion(Emotion::Angry);
|
||||
} else if (strcmp(emotion, "sad") == 0) {
|
||||
avatar.setEmotion(Emotion::Sad);
|
||||
} else if (strcmp(emotion, "crying") == 0) {
|
||||
avatar.setEmotion(Emotion::Sad);
|
||||
} else if (strcmp(emotion, "sleepy") == 0) {
|
||||
avatar.setEmotion(Emotion::Sleepy);
|
||||
avatar.setSpeech("Zzz…");
|
||||
is_sleeping_ = true;
|
||||
// avatar.mouth().setWeight(10);
|
||||
|
||||
// Stop idle motion
|
||||
ESP_LOGW(TAG, "Stop idle motion");
|
||||
if (idle_motion_modifier_id_ >= 0) {
|
||||
stackchan.removeModifier(idle_motion_modifier_id_);
|
||||
idle_motion_modifier_id_ = -1;
|
||||
}
|
||||
|
||||
// Return to default pose
|
||||
auto& motion = GetStackChan().motion();
|
||||
motion.pitchServo().moveWithSpeed(0, 80);
|
||||
|
||||
} else if (strcmp(emotion, "doubtful") == 0) {
|
||||
avatar.setEmotion(Emotion::Doubt);
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Unknown emotion: %s, using NEUTRAL", emotion);
|
||||
avatar.setEmotion(Emotion::Neutral);
|
||||
}
|
||||
|
||||
// Resync blink modifier base eye weights
|
||||
auto blink_modifier = static_cast<BlinkModifier*>(stackchan.getModifier(blink_modifier_id_));
|
||||
if (blink_modifier) {
|
||||
blink_modifier->resyncEyeWeights();
|
||||
}
|
||||
}
|
||||
|
||||
void StackChanAvatarDisplay::SetChatMessage(const char* role, const char* content)
|
||||
{
|
||||
auto& stackchan = GetStackChan();
|
||||
if (!stackchan.hasAvatar()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGE(TAG, "SetChatMessage: role=%s, content=%s", role ? role : "null", content ? content : "null");
|
||||
|
||||
DisplayLockGuard lock(this);
|
||||
|
||||
if (strcmp(role, "system") == 0) {
|
||||
stackchan.avatar().setSpeech(content);
|
||||
} else if (strcmp(role, "assistant") == 0) {
|
||||
stackchan.avatar().setSpeech(content);
|
||||
}
|
||||
}
|
||||
|
||||
void StackChanAvatarDisplay::SetPreviewImage(std::unique_ptr<LvglImage> image)
|
||||
{
|
||||
DisplayLockGuard lock(this);
|
||||
if (preview_image_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (image == nullptr) {
|
||||
esp_timer_stop(preview_timer_);
|
||||
lv_obj_add_flag(preview_image_, LV_OBJ_FLAG_HIDDEN);
|
||||
preview_image_cached_.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
preview_image_cached_ = std::move(image);
|
||||
auto img_dsc = preview_image_cached_->image_dsc();
|
||||
// Set image source and show preview image
|
||||
lv_image_set_src(preview_image_, img_dsc);
|
||||
if (img_dsc->header.w > 0 && img_dsc->header.h > 0) {
|
||||
// Scale to fit width
|
||||
lv_image_set_scale(preview_image_, 256 * width_ / img_dsc->header.w);
|
||||
}
|
||||
|
||||
lv_obj_remove_flag(preview_image_, LV_OBJ_FLAG_HIDDEN);
|
||||
lv_obj_move_foreground(preview_image_);
|
||||
esp_timer_stop(preview_timer_);
|
||||
ESP_ERROR_CHECK(esp_timer_start_once(preview_timer_, 6000 * 1000));
|
||||
}
|
||||
|
||||
void StackChanAvatarDisplay::SetTheme(Theme* theme)
|
||||
{
|
||||
ESP_LOGI(TAG, "SetTheme: %s", theme->name().c_str());
|
||||
|
||||
auto& stackchan = GetStackChan();
|
||||
if (!stackchan.hasAvatar()) {
|
||||
ESP_LOGE(TAG, "Avatar is invalid");
|
||||
return;
|
||||
}
|
||||
|
||||
DisplayLockGuard lock(this);
|
||||
|
||||
auto lvgl_theme = static_cast<LvglTheme*>(theme);
|
||||
auto text_font = lvgl_theme->text_font()->font();
|
||||
|
||||
stackchan.avatar().setSpeechTextFont((void*)text_font);
|
||||
}
|
||||
|
||||
void StackChanAvatarDisplay::SetStatus(const char* status)
|
||||
{
|
||||
ESP_LOGE(TAG, "SetStatus: %s", status);
|
||||
|
||||
LvglDisplay::SetStatus(status);
|
||||
|
||||
auto& stackchan = GetStackChan();
|
||||
if (!stackchan.hasAvatar()) {
|
||||
ESP_LOGE(TAG, "Avatar is invalid");
|
||||
return;
|
||||
}
|
||||
|
||||
auto& avatar = stackchan.avatar();
|
||||
auto& motion = stackchan.motion();
|
||||
|
||||
DisplayLockGuard lock(this);
|
||||
|
||||
bool is_idle = false;
|
||||
bool is_listening = false;
|
||||
|
||||
if (strcmp(status, Lang::Strings::LISTENING) == 0) {
|
||||
if (speaking_modifier_id_ >= 0) {
|
||||
// Start speaking
|
||||
stackchan.removeModifier(speaking_modifier_id_);
|
||||
avatar.mouth().setWeight(0);
|
||||
speaking_modifier_id_ = -1;
|
||||
}
|
||||
|
||||
GetHAL().setRgbColor(0, 0, 50, 0);
|
||||
GetHAL().refreshRgb();
|
||||
|
||||
} else if (strcmp(status, Lang::Strings::STANDBY) == 0) {
|
||||
if (speaking_modifier_id_ >= 0) {
|
||||
// Stop speaking
|
||||
stackchan.removeModifier(speaking_modifier_id_);
|
||||
avatar.mouth().setWeight(0);
|
||||
speaking_modifier_id_ = -1;
|
||||
}
|
||||
|
||||
is_idle = true;
|
||||
|
||||
GetHAL().setRgbColor(0, 0, 0, 0);
|
||||
GetHAL().refreshRgb();
|
||||
|
||||
} else if (strcmp(status, Lang::Strings::SPEAKING) == 0) {
|
||||
if (speaking_modifier_id_ < 0) {
|
||||
speaking_modifier_id_ = stackchan.addModifier(std::make_unique<SpeakingModifier>());
|
||||
}
|
||||
|
||||
GetHAL().setRgbColor(0, 0, 0, 50);
|
||||
GetHAL().refreshRgb();
|
||||
}
|
||||
|
||||
if (is_idle) {
|
||||
// Start idle motion
|
||||
ESP_LOGW(TAG, "Start idle motion");
|
||||
if (idle_motion_modifier_id_ < 0) {
|
||||
idle_motion_modifier_id_ = stackchan.addModifier(std::make_unique<IdleMotionModifier>());
|
||||
}
|
||||
} else {
|
||||
// Stop idle motion
|
||||
ESP_LOGW(TAG, "Stop idle motion");
|
||||
if (idle_motion_modifier_id_ >= 0) {
|
||||
stackchan.removeModifier(idle_motion_modifier_id_);
|
||||
idle_motion_modifier_id_ = -1;
|
||||
}
|
||||
|
||||
// if (!is_listening) {
|
||||
// // Return to default pose
|
||||
// motion.pitchServo().moveWithSpeed(200, 350);
|
||||
// motion.yawServo().moveWithSpeed(0, 350);
|
||||
// }
|
||||
}
|
||||
|
||||
// Clear sleep state
|
||||
if (is_sleeping_) {
|
||||
avatar.setSpeech("");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#pragma once
|
||||
#include <display/lvgl_display/lvgl_display.h>
|
||||
#include <esp_lcd_panel_io.h>
|
||||
#include <esp_lcd_panel_ops.h>
|
||||
#include <esp_timer.h>
|
||||
#include <memory>
|
||||
|
||||
class StackChanAvatarDisplay : public LvglDisplay {
|
||||
private:
|
||||
esp_lcd_panel_io_handle_t panel_io_ = nullptr;
|
||||
esp_lcd_panel_handle_t panel_ = nullptr;
|
||||
int speaking_modifier_id_ = -1;
|
||||
int idle_motion_modifier_id_ = -1;
|
||||
int blink_modifier_id_ = -1;
|
||||
bool is_sleeping_ = false;
|
||||
|
||||
lv_obj_t* preview_image_ = nullptr;
|
||||
esp_timer_handle_t preview_timer_ = nullptr;
|
||||
std::unique_ptr<LvglImage> preview_image_cached_ = nullptr;
|
||||
|
||||
protected:
|
||||
virtual bool Lock(int timeout_ms = 0) override;
|
||||
virtual void Unlock() override;
|
||||
|
||||
public:
|
||||
StackChanAvatarDisplay(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_handle_t panel, int width, int height,
|
||||
int offset_x, int offset_y, bool mirror_x, bool mirror_y, bool swap_xy);
|
||||
virtual ~StackChanAvatarDisplay();
|
||||
|
||||
void InitializeLcdThemes();
|
||||
|
||||
// Override Display methods to control Robot
|
||||
virtual void SetEmotion(const char* emotion) override;
|
||||
virtual void SetChatMessage(const char* role, const char* content) override;
|
||||
virtual void SetPreviewImage(std::unique_ptr<LvglImage> image) override;
|
||||
virtual void SetTheme(Theme* theme) override;
|
||||
virtual void SetStatus(const char* status) override;
|
||||
|
||||
void SetupXiaoZhiUI();
|
||||
void LvglLock();
|
||||
void LvglUnlock();
|
||||
lv_disp_t* GetLvglDisplay();
|
||||
};
|
||||
@@ -0,0 +1,358 @@
|
||||
#include "PY32IOExpander_Class.hpp"
|
||||
#include "esp_log.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include <cstring>
|
||||
|
||||
static const char* TAG = "PY32IOExpander";
|
||||
|
||||
namespace m5 {
|
||||
|
||||
// Register definitions
|
||||
static constexpr uint8_t REG_UID_L = 0x00;
|
||||
static constexpr uint8_t REG_UID_H = 0x01;
|
||||
static constexpr uint8_t REG_VERSION = 0x02;
|
||||
static constexpr uint8_t REG_GPIO_M_L = 0x03;
|
||||
static constexpr uint8_t REG_GPIO_M_H = 0x04;
|
||||
static constexpr uint8_t REG_GPIO_O_L = 0x05;
|
||||
static constexpr uint8_t REG_GPIO_O_H = 0x06;
|
||||
static constexpr uint8_t REG_GPIO_I_L = 0x07;
|
||||
static constexpr uint8_t REG_GPIO_I_H = 0x08;
|
||||
static constexpr uint8_t REG_GPIO_PU_L = 0x09;
|
||||
static constexpr uint8_t REG_GPIO_PU_H = 0x0A;
|
||||
static constexpr uint8_t REG_GPIO_PD_L = 0x0B;
|
||||
static constexpr uint8_t REG_GPIO_PD_H = 0x0C;
|
||||
static constexpr uint8_t REG_GPIO_IE_L = 0x0D;
|
||||
static constexpr uint8_t REG_GPIO_IE_H = 0x0E;
|
||||
static constexpr uint8_t REG_GPIO_IT_L = 0x0F;
|
||||
static constexpr uint8_t REG_GPIO_IT_H = 0x10;
|
||||
static constexpr uint8_t REG_GPIO_IS_L = 0x11;
|
||||
static constexpr uint8_t REG_GPIO_IS_H = 0x12;
|
||||
static constexpr uint8_t REG_GPIO_DRV_L = 0x13;
|
||||
static constexpr uint8_t REG_GPIO_DRV_H = 0x14;
|
||||
|
||||
static constexpr uint8_t REG_ADC_CTRL = 0x15;
|
||||
static constexpr uint8_t REG_ADC_D_L = 0x16;
|
||||
static constexpr uint8_t REG_ADC_D_H = 0x17;
|
||||
|
||||
static constexpr uint8_t REG_PWM_FREQ_L = 0x25;
|
||||
static constexpr uint8_t REG_PWM_FREQ_H = 0x26;
|
||||
|
||||
static constexpr uint8_t REG_LED_CFG = 0x24;
|
||||
static constexpr uint8_t REG_LED_RAM_START = 0x30;
|
||||
|
||||
// PWM Duty Registers
|
||||
static constexpr uint8_t REG_PWM1_DUTY_L = 0x1B;
|
||||
static constexpr uint8_t REG_PWM1_DUTY_H = 0x1C;
|
||||
static constexpr uint8_t REG_PWM2_DUTY_L = 0x1D;
|
||||
static constexpr uint8_t REG_PWM2_DUTY_H = 0x1E;
|
||||
static constexpr uint8_t REG_PWM3_DUTY_L = 0x1F;
|
||||
static constexpr uint8_t REG_PWM3_DUTY_H = 0x20;
|
||||
static constexpr uint8_t REG_PWM4_DUTY_L = 0x21;
|
||||
static constexpr uint8_t REG_PWM4_DUTY_H = 0x22;
|
||||
|
||||
PY32IOExpander_Class::PY32IOExpander_Class(i2c_master_bus_handle_t i2c_bus_handle, uint8_t addr)
|
||||
: _addr(addr), _initialized(false)
|
||||
{
|
||||
i2c_device_config_t dev_cfg = {
|
||||
.dev_addr_length = I2C_ADDR_BIT_LEN_7,
|
||||
.device_address = _addr,
|
||||
.scl_speed_hz = 100000,
|
||||
};
|
||||
ESP_ERROR_CHECK(i2c_master_bus_add_device(i2c_bus_handle, &dev_cfg, &_i2c_dev));
|
||||
}
|
||||
|
||||
PY32IOExpander_Class::~PY32IOExpander_Class()
|
||||
{
|
||||
if (_i2c_dev) {
|
||||
i2c_master_bus_rm_device(_i2c_dev);
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t PY32IOExpander_Class::writeRegister8(uint8_t reg, uint8_t value)
|
||||
{
|
||||
uint8_t buf[2] = {reg, value};
|
||||
return i2c_master_transmit(_i2c_dev, buf, sizeof(buf), 1000);
|
||||
}
|
||||
|
||||
uint8_t PY32IOExpander_Class::readRegister8(uint8_t reg)
|
||||
{
|
||||
uint8_t val = 0;
|
||||
esp_err_t err = i2c_master_transmit_receive(_i2c_dev, ®, 1, &val, 1, 1000);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "readRegister8 failed: %s", esp_err_to_name(err));
|
||||
return 0;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
esp_err_t PY32IOExpander_Class::writeRegister(uint8_t reg, const uint8_t* data, size_t len)
|
||||
{
|
||||
if (len == 0) return ESP_OK;
|
||||
|
||||
// Allocate buffer for reg + data
|
||||
uint8_t* buf = (uint8_t*)malloc(len + 1);
|
||||
if (!buf) return ESP_ERR_NO_MEM;
|
||||
|
||||
buf[0] = reg;
|
||||
memcpy(buf + 1, data, len);
|
||||
|
||||
esp_err_t err = i2c_master_transmit(_i2c_dev, buf, len + 1, 1000);
|
||||
free(buf);
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_err_t PY32IOExpander_Class::readRegister(uint8_t reg, uint8_t* data, size_t len)
|
||||
{
|
||||
return i2c_master_transmit_receive(_i2c_dev, ®, 1, data, len, 1000);
|
||||
}
|
||||
|
||||
esp_err_t PY32IOExpander_Class::bitOn(uint8_t reg, uint8_t mask)
|
||||
{
|
||||
uint8_t val = readRegister8(reg);
|
||||
val |= mask;
|
||||
return writeRegister8(reg, val);
|
||||
}
|
||||
|
||||
esp_err_t PY32IOExpander_Class::bitOff(uint8_t reg, uint8_t mask)
|
||||
{
|
||||
uint8_t val = readRegister8(reg);
|
||||
val &= ~mask;
|
||||
return writeRegister8(reg, val);
|
||||
}
|
||||
|
||||
void PY32IOExpander_Class::_writeBit(uint8_t reg_l, uint8_t reg_h, uint8_t pin, bool value)
|
||||
{
|
||||
if (pin < 8) {
|
||||
if (value)
|
||||
bitOn(reg_l, 1 << pin);
|
||||
else
|
||||
bitOff(reg_l, 1 << pin);
|
||||
} else {
|
||||
if (value)
|
||||
bitOn(reg_h, 1 << (pin - 8));
|
||||
else
|
||||
bitOff(reg_h, 1 << (pin - 8));
|
||||
}
|
||||
}
|
||||
|
||||
bool PY32IOExpander_Class::_readBit(uint8_t reg_l, uint8_t reg_h, uint8_t pin)
|
||||
{
|
||||
if (pin < 8) {
|
||||
return (readRegister8(reg_l) & (1 << pin)) != 0;
|
||||
} else {
|
||||
return (readRegister8(reg_h) & (1 << (pin - 8))) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool PY32IOExpander_Class::begin()
|
||||
{
|
||||
uint8_t version = readRegister8(REG_VERSION);
|
||||
if (version == 0 || version == 0xFF) {
|
||||
ESP_LOGE(TAG, "Invalid version: 0x%02X", version);
|
||||
return false;
|
||||
}
|
||||
ESP_LOGI(TAG, "Version: 0x%02X", version);
|
||||
_initialized = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void PY32IOExpander_Class::setDirection(uint8_t pin, bool direction)
|
||||
{
|
||||
// direction: false=input (0), true=output (1)
|
||||
_writeBit(REG_GPIO_M_L, REG_GPIO_M_H, pin, direction);
|
||||
}
|
||||
|
||||
void PY32IOExpander_Class::enablePull(uint8_t pin, bool enablePull)
|
||||
{
|
||||
if (enablePull) {
|
||||
// Enable Pull Up by default if neither is set
|
||||
bool pu = _readBit(REG_GPIO_PU_L, REG_GPIO_PU_H, pin);
|
||||
bool pd = _readBit(REG_GPIO_PD_L, REG_GPIO_PD_H, pin);
|
||||
if (!pu && !pd) {
|
||||
_writeBit(REG_GPIO_PU_L, REG_GPIO_PU_H, pin, true);
|
||||
}
|
||||
// If one is already set, leave it.
|
||||
} else {
|
||||
// Disable both
|
||||
_writeBit(REG_GPIO_PU_L, REG_GPIO_PU_H, pin, false);
|
||||
_writeBit(REG_GPIO_PD_L, REG_GPIO_PD_H, pin, false);
|
||||
}
|
||||
}
|
||||
|
||||
void PY32IOExpander_Class::setPullMode(uint8_t pin, bool mode)
|
||||
{
|
||||
// mode: false=down, true=up
|
||||
if (mode) {
|
||||
// Pull Up
|
||||
_writeBit(REG_GPIO_PD_L, REG_GPIO_PD_H, pin, false);
|
||||
_writeBit(REG_GPIO_PU_L, REG_GPIO_PU_H, pin, true);
|
||||
} else {
|
||||
// Pull Down
|
||||
_writeBit(REG_GPIO_PU_L, REG_GPIO_PU_H, pin, false);
|
||||
_writeBit(REG_GPIO_PD_L, REG_GPIO_PD_H, pin, true);
|
||||
}
|
||||
}
|
||||
|
||||
void PY32IOExpander_Class::setDriveMode(uint8_t pin, bool openDrain)
|
||||
{
|
||||
// openDrain: false=push-pull (0), true=open-drain (1)
|
||||
_writeBit(REG_GPIO_DRV_L, REG_GPIO_DRV_H, pin, openDrain);
|
||||
}
|
||||
|
||||
void PY32IOExpander_Class::setHighImpedance(uint8_t pin, bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
// Input mode
|
||||
setDirection(pin, false);
|
||||
// Disable pulls
|
||||
enablePull(pin, false);
|
||||
}
|
||||
}
|
||||
|
||||
bool PY32IOExpander_Class::getWriteValue(uint8_t pin)
|
||||
{
|
||||
return _readBit(REG_GPIO_O_L, REG_GPIO_O_H, pin);
|
||||
}
|
||||
|
||||
void PY32IOExpander_Class::digitalWrite(uint8_t pin, bool level)
|
||||
{
|
||||
_writeBit(REG_GPIO_O_L, REG_GPIO_O_H, pin, level);
|
||||
}
|
||||
|
||||
bool PY32IOExpander_Class::digitalRead(uint8_t pin)
|
||||
{
|
||||
return _readBit(REG_GPIO_I_L, REG_GPIO_I_H, pin);
|
||||
}
|
||||
|
||||
void PY32IOExpander_Class::resetIrq()
|
||||
{
|
||||
// Clear all interrupts by writing 1s to IS registers
|
||||
writeRegister8(REG_GPIO_IS_L, 0xFF);
|
||||
writeRegister8(REG_GPIO_IS_H, 0xFF); // Only bits 0-5 used for high byte (pins 8-13)
|
||||
}
|
||||
|
||||
void PY32IOExpander_Class::disableIrq()
|
||||
{
|
||||
// Disable all interrupts
|
||||
writeRegister8(REG_GPIO_IE_L, 0x00);
|
||||
writeRegister8(REG_GPIO_IE_H, 0x00);
|
||||
}
|
||||
|
||||
void PY32IOExpander_Class::enableIrq()
|
||||
{
|
||||
// Enable all interrupts
|
||||
writeRegister8(REG_GPIO_IE_L, 0xFF);
|
||||
writeRegister8(REG_GPIO_IE_H, 0x3F); // Pins 8-13
|
||||
}
|
||||
|
||||
uint16_t PY32IOExpander_Class::readDeviceUID()
|
||||
{
|
||||
uint8_t l = readRegister8(REG_UID_L);
|
||||
uint8_t h = readRegister8(REG_UID_H);
|
||||
return (h << 8) | l;
|
||||
}
|
||||
|
||||
uint8_t PY32IOExpander_Class::readVersion()
|
||||
{
|
||||
return readRegister8(REG_VERSION);
|
||||
}
|
||||
|
||||
uint16_t PY32IOExpander_Class::analogRead(uint8_t channel)
|
||||
{
|
||||
if (channel < 1 || channel > 4) return 0;
|
||||
|
||||
// Start conversion
|
||||
// REG_ADC_CTRL: [7:Busy] [6:Start] [2:0:Channel]
|
||||
// Channel mapping: 1->1, 2->2, 3->3, 4->4
|
||||
writeRegister8(REG_ADC_CTRL, (1 << 6) | (channel & 0x07));
|
||||
|
||||
// Wait for busy bit to clear
|
||||
// Simple polling with timeout
|
||||
for (int i = 0; i < 100; i++) {
|
||||
uint8_t ctrl = readRegister8(REG_ADC_CTRL);
|
||||
if (!(ctrl & (1 << 7))) {
|
||||
break;
|
||||
}
|
||||
vTaskDelay(pdMS_TO_TICKS(1));
|
||||
}
|
||||
|
||||
uint8_t l = readRegister8(REG_ADC_D_L);
|
||||
uint8_t h = readRegister8(REG_ADC_D_H);
|
||||
return (h << 8) | l;
|
||||
}
|
||||
|
||||
void PY32IOExpander_Class::setPwmDuty(uint8_t channel, uint8_t duty)
|
||||
{
|
||||
if (channel > 3) return;
|
||||
|
||||
// Calculate register address
|
||||
// Channel 0 -> PWM1 (0x1B)
|
||||
// Channel 1 -> PWM2 (0x1D)
|
||||
// Channel 2 -> PWM3 (0x1F)
|
||||
// Channel 3 -> PWM4 (0x21)
|
||||
uint8_t reg_l = REG_PWM1_DUTY_L + (channel * 2);
|
||||
uint8_t reg_h = reg_l + 1;
|
||||
|
||||
// Duty is 8-bit percentage (0-100)? Or 0-255?
|
||||
// m5_io_py32ioexpander uses percentage (0-100) or 12-bit raw.
|
||||
// Let's assume 0-255 for standard Arduino style, but map to 12-bit (0-4095).
|
||||
// 255 -> 4095. val * 4095 / 255 = val * 16 approx.
|
||||
uint16_t duty12 = (uint16_t)duty * 16;
|
||||
if (duty12 > 4095) duty12 = 4095;
|
||||
|
||||
// High byte contains Enable(7) and Polarity(6) bits.
|
||||
// We need to preserve them or set defaults.
|
||||
// Let's enable by default, polarity normal (0).
|
||||
uint8_t h_val = (duty12 >> 8) & 0x0F;
|
||||
h_val |= (1 << 7); // Enable
|
||||
|
||||
writeRegister8(reg_l, duty12 & 0xFF);
|
||||
writeRegister8(reg_h, h_val);
|
||||
}
|
||||
|
||||
void PY32IOExpander_Class::setPwmFrequency(uint16_t freq)
|
||||
{
|
||||
writeRegister8(REG_PWM_FREQ_L, freq & 0xFF);
|
||||
writeRegister8(REG_PWM_FREQ_H, (freq >> 8) & 0xFF);
|
||||
}
|
||||
|
||||
void PY32IOExpander_Class::setLedCount(uint8_t count)
|
||||
{
|
||||
if (count > 32) count = 32;
|
||||
writeRegister8(REG_LED_CFG, count & 0x3F);
|
||||
}
|
||||
|
||||
void PY32IOExpander_Class::setLedColor(uint8_t index, uint16_t color565)
|
||||
{
|
||||
if (index >= 32) return;
|
||||
uint8_t data[2] = {(uint8_t)(color565 & 0xFF), (uint8_t)((color565 >> 8) & 0xFF)};
|
||||
writeRegister(REG_LED_RAM_START + index * 2, data, 2);
|
||||
}
|
||||
|
||||
void PY32IOExpander_Class::setLedColor(uint8_t index, uint8_t r, uint8_t g, uint8_t b)
|
||||
{
|
||||
// RGB888 to RGB565: RRRRRGGG GGGBBBBB
|
||||
uint16_t val = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
|
||||
setLedColor(index, val);
|
||||
}
|
||||
|
||||
void PY32IOExpander_Class::setLedColor(uint8_t index, uint32_t color)
|
||||
{
|
||||
setLedColor(index, (uint8_t)((color >> 16) & 0xFF), (uint8_t)((color >> 8) & 0xFF), (uint8_t)(color & 0xFF));
|
||||
}
|
||||
|
||||
void PY32IOExpander_Class::setLedData(const uint8_t* data, size_t len)
|
||||
{
|
||||
if (!data || len == 0) return;
|
||||
if (len > 64) len = 64; // Max 32 LEDs * 2 bytes
|
||||
writeRegister(REG_LED_RAM_START, data, len);
|
||||
}
|
||||
|
||||
void PY32IOExpander_Class::refreshLeds()
|
||||
{
|
||||
uint8_t val = readRegister8(REG_LED_CFG);
|
||||
writeRegister8(REG_LED_CFG, val | (1 << 6));
|
||||
}
|
||||
|
||||
} // namespace m5
|
||||
@@ -0,0 +1,88 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include "driver/i2c_master.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
namespace m5 {
|
||||
|
||||
class PY32IOExpander_Class {
|
||||
public:
|
||||
static constexpr uint8_t DEFAULT_ADDRESS = 0x6F;
|
||||
|
||||
PY32IOExpander_Class(i2c_master_bus_handle_t i2c_bus_handle, uint8_t addr = DEFAULT_ADDRESS);
|
||||
~PY32IOExpander_Class();
|
||||
|
||||
/**
|
||||
* @brief Initialize the device
|
||||
*
|
||||
* @return true if successful
|
||||
* @return false if failed
|
||||
*/
|
||||
bool begin();
|
||||
|
||||
// IOExpander methods
|
||||
// false input, true output
|
||||
void setDirection(uint8_t pin, bool direction);
|
||||
|
||||
void enablePull(uint8_t pin, bool enablePull);
|
||||
|
||||
// false down, true up
|
||||
void setPullMode(uint8_t pin, bool mode);
|
||||
|
||||
// false push-pull, true open-drain
|
||||
void setDriveMode(uint8_t pin, bool openDrain);
|
||||
|
||||
void setHighImpedance(uint8_t pin, bool enable);
|
||||
|
||||
bool getWriteValue(uint8_t pin);
|
||||
|
||||
void digitalWrite(uint8_t pin, bool level);
|
||||
|
||||
bool digitalRead(uint8_t pin);
|
||||
|
||||
void resetIrq();
|
||||
|
||||
void disableIrq();
|
||||
|
||||
void enableIrq();
|
||||
|
||||
// Extended functionality
|
||||
uint16_t readDeviceUID();
|
||||
uint8_t readVersion();
|
||||
|
||||
// ADC
|
||||
// channel: 1-4
|
||||
uint16_t analogRead(uint8_t channel);
|
||||
|
||||
// PWM
|
||||
// channel: 0-3
|
||||
void setPwmDuty(uint8_t channel, uint8_t duty);
|
||||
void setPwmFrequency(uint16_t freq);
|
||||
|
||||
// LED
|
||||
void setLedCount(uint8_t count);
|
||||
void setLedColor(uint8_t index, uint16_t color565);
|
||||
void setLedColor(uint8_t index, uint8_t r, uint8_t g, uint8_t b);
|
||||
void setLedColor(uint8_t index, uint32_t color);
|
||||
void setLedData(const uint8_t* data, size_t len);
|
||||
void refreshLeds();
|
||||
|
||||
private:
|
||||
i2c_master_dev_handle_t _i2c_dev;
|
||||
uint8_t _addr;
|
||||
bool _initialized;
|
||||
|
||||
esp_err_t writeRegister8(uint8_t reg, uint8_t value);
|
||||
uint8_t readRegister8(uint8_t reg);
|
||||
esp_err_t writeRegister(uint8_t reg, const uint8_t* data, size_t len);
|
||||
esp_err_t readRegister(uint8_t reg, uint8_t* data, size_t len);
|
||||
|
||||
esp_err_t bitOn(uint8_t reg, uint8_t mask);
|
||||
esp_err_t bitOff(uint8_t reg, uint8_t mask);
|
||||
|
||||
void _writeBit(uint8_t reg_l, uint8_t reg_h, uint8_t pin, bool value);
|
||||
bool _readBit(uint8_t reg_l, uint8_t reg_h, uint8_t pin);
|
||||
};
|
||||
|
||||
} // namespace m5
|
||||
@@ -0,0 +1,12 @@
|
||||
idf_component_register(
|
||||
SRCS
|
||||
"src/SCS.cpp"
|
||||
"src/SCSCL.cpp"
|
||||
"src/SCSerial.cpp"
|
||||
INCLUDE_DIRS
|
||||
"src"
|
||||
REQUIRES
|
||||
driver
|
||||
esp_timer
|
||||
)
|
||||
|
||||
@@ -0,0 +1,674 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* INST.h
|
||||
* FIT serial servo protocol command definition
|
||||
*/
|
||||
|
||||
#ifndef _INST_H
|
||||
#define _INST_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef int8_t s8;
|
||||
typedef uint8_t u8;
|
||||
typedef uint16_t u16;
|
||||
typedef int16_t s16;
|
||||
typedef uint32_t u32;
|
||||
typedef int32_t s32;
|
||||
|
||||
#define INST_PING 0x01
|
||||
#define INST_READ 0x02
|
||||
#define INST_WRITE 0x03
|
||||
#define INST_REG_WRITE 0x04
|
||||
#define INST_REG_ACTION 0x05
|
||||
#define INST_SYNC_READ 0x82
|
||||
#define INST_SYNC_WRITE 0x83
|
||||
|
||||
// Baud rate definition
|
||||
#define _1M 0
|
||||
#define _0_5M 1
|
||||
#define _250K 2
|
||||
#define _128K 3
|
||||
#define _115200 4
|
||||
#define _76800 5
|
||||
#define _57600 6
|
||||
#define _38400 7
|
||||
#define _19200 8
|
||||
#define _14400 9
|
||||
#define _9600 10
|
||||
#define _4800 11
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,369 @@
|
||||
/*
|
||||
* SCS.cpp
|
||||
* FIT serial servo communication layer protocol program
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include "SCS.h"
|
||||
|
||||
SCS::SCS()
|
||||
{
|
||||
Level = 1; // All commands except broadcast commands return responses
|
||||
Error = 0;
|
||||
}
|
||||
|
||||
SCS::SCS(u8 End)
|
||||
{
|
||||
Level = 1;
|
||||
this->End = End;
|
||||
Error = 0;
|
||||
}
|
||||
|
||||
SCS::SCS(u8 End, u8 Level)
|
||||
{
|
||||
this->Level = Level;
|
||||
this->End = End;
|
||||
Error = 0;
|
||||
}
|
||||
|
||||
// Split a 16-bit number into two 8-bit numbers
|
||||
// DataL is the low bit, DataH is the high bit
|
||||
void SCS::Host2SCS(u8 *DataL, u8 *DataH, u16 Data)
|
||||
{
|
||||
if (End) {
|
||||
*DataL = (Data >> 8);
|
||||
*DataH = (Data & 0xff);
|
||||
} else {
|
||||
*DataH = (Data >> 8);
|
||||
*DataL = (Data & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
// 8-bit numbers are combined into a 16-bit number
|
||||
// DataL is the low bit, DataH is the high bit
|
||||
u16 SCS::SCS2Host(u8 DataL, u8 DataH)
|
||||
{
|
||||
u16 Data;
|
||||
if (End) {
|
||||
Data = DataL;
|
||||
Data <<= 8;
|
||||
Data |= DataH;
|
||||
} else {
|
||||
Data = DataH;
|
||||
Data <<= 8;
|
||||
Data |= DataL;
|
||||
}
|
||||
return Data;
|
||||
}
|
||||
|
||||
void SCS::writeBuf(u8 ID, u8 MemAddr, u8 *nDat, u8 nLen, u8 Fun)
|
||||
{
|
||||
u8 msgLen = 2;
|
||||
u8 bBuf[6];
|
||||
u8 CheckSum = 0;
|
||||
bBuf[0] = 0xff;
|
||||
bBuf[1] = 0xff;
|
||||
bBuf[2] = ID;
|
||||
bBuf[4] = Fun;
|
||||
if (nDat) {
|
||||
msgLen += nLen + 1;
|
||||
bBuf[3] = msgLen;
|
||||
bBuf[5] = MemAddr;
|
||||
writeSCS(bBuf, 6);
|
||||
|
||||
} else {
|
||||
bBuf[3] = msgLen;
|
||||
writeSCS(bBuf, 5);
|
||||
}
|
||||
CheckSum = ID + msgLen + Fun + MemAddr;
|
||||
u8 i = 0;
|
||||
if (nDat) {
|
||||
for (i = 0; i < nLen; i++) {
|
||||
CheckSum += nDat[i];
|
||||
}
|
||||
writeSCS(nDat, nLen);
|
||||
}
|
||||
writeSCS(~CheckSum);
|
||||
}
|
||||
|
||||
// Normal write command
|
||||
// Servo ID, MemAddr memory table address, write data, write length
|
||||
int SCS::genWrite(u8 ID, u8 MemAddr, u8 *nDat, u8 nLen)
|
||||
{
|
||||
rFlushSCS();
|
||||
writeBuf(ID, MemAddr, nDat, nLen, INST_WRITE);
|
||||
wFlushSCS();
|
||||
return Ack(ID);
|
||||
}
|
||||
|
||||
// Asynchronous write command
|
||||
// Servo ID, MemAddr memory table address, write data, write length
|
||||
int SCS::regWrite(u8 ID, u8 MemAddr, u8 *nDat, u8 nLen)
|
||||
{
|
||||
rFlushSCS();
|
||||
writeBuf(ID, MemAddr, nDat, nLen, INST_REG_WRITE);
|
||||
wFlushSCS();
|
||||
return Ack(ID);
|
||||
}
|
||||
|
||||
// Asynchronous write execution command
|
||||
// Servo ID
|
||||
int SCS::RegWriteAction(u8 ID)
|
||||
{
|
||||
rFlushSCS();
|
||||
writeBuf(ID, 0, NULL, 0, INST_REG_ACTION);
|
||||
wFlushSCS();
|
||||
return Ack(ID);
|
||||
}
|
||||
|
||||
// Synchronous write command
|
||||
// Servo ID[] array, IDN array length, MemAddr memory table address, write data, write length
|
||||
void SCS::syncWrite(u8 ID[], u8 IDN, u8 MemAddr, u8 *nDat, u8 nLen)
|
||||
{
|
||||
rFlushSCS();
|
||||
u8 mesLen = ((nLen + 1) * IDN + 4);
|
||||
u8 Sum = 0;
|
||||
u8 bBuf[7];
|
||||
bBuf[0] = 0xff;
|
||||
bBuf[1] = 0xff;
|
||||
bBuf[2] = 0xfe;
|
||||
bBuf[3] = mesLen;
|
||||
bBuf[4] = INST_SYNC_WRITE;
|
||||
bBuf[5] = MemAddr;
|
||||
bBuf[6] = nLen;
|
||||
writeSCS(bBuf, 7);
|
||||
|
||||
Sum = 0xfe + mesLen + INST_SYNC_WRITE + MemAddr + nLen;
|
||||
u8 i, j;
|
||||
for (i = 0; i < IDN; i++) {
|
||||
writeSCS(ID[i]);
|
||||
writeSCS(nDat + i * nLen, nLen);
|
||||
Sum += ID[i];
|
||||
for (j = 0; j < nLen; j++) {
|
||||
Sum += nDat[i * nLen + j];
|
||||
}
|
||||
}
|
||||
writeSCS(~Sum);
|
||||
wFlushSCS();
|
||||
}
|
||||
|
||||
int SCS::writeByte(u8 ID, u8 MemAddr, u8 bDat)
|
||||
{
|
||||
rFlushSCS();
|
||||
writeBuf(ID, MemAddr, &bDat, 1, INST_WRITE);
|
||||
wFlushSCS();
|
||||
return Ack(ID);
|
||||
}
|
||||
|
||||
int SCS::writeWord(u8 ID, u8 MemAddr, u16 wDat)
|
||||
{
|
||||
u8 bBuf[2];
|
||||
Host2SCS(bBuf + 0, bBuf + 1, wDat);
|
||||
rFlushSCS();
|
||||
writeBuf(ID, MemAddr, bBuf, 2, INST_WRITE);
|
||||
wFlushSCS();
|
||||
return Ack(ID);
|
||||
}
|
||||
|
||||
// Read command
|
||||
// Servo ID, MemAddr memory table address, return data nData, data length nLen
|
||||
int SCS::Read(u8 ID, u8 MemAddr, u8 *nData, u8 nLen)
|
||||
{
|
||||
rFlushSCS();
|
||||
writeBuf(ID, MemAddr, &nLen, 1, INST_READ);
|
||||
wFlushSCS();
|
||||
if (!checkHead()) {
|
||||
return 0;
|
||||
}
|
||||
u8 bBuf[4];
|
||||
Error = 0;
|
||||
if (readSCS(bBuf, 3) != 3) {
|
||||
return 0;
|
||||
}
|
||||
int Size = readSCS(nData, nLen);
|
||||
if (Size != nLen) {
|
||||
return 0;
|
||||
}
|
||||
if (readSCS(bBuf + 3, 1) != 1) {
|
||||
return 0;
|
||||
}
|
||||
u8 calSum = bBuf[0] + bBuf[1] + bBuf[2];
|
||||
u8 i;
|
||||
for (i = 0; i < Size; i++) {
|
||||
calSum += nData[i];
|
||||
}
|
||||
calSum = ~calSum;
|
||||
if (calSum != bBuf[3]) {
|
||||
return 0;
|
||||
}
|
||||
Error = bBuf[2];
|
||||
return Size;
|
||||
}
|
||||
|
||||
// Read 1 byte, return -1 if timeout
|
||||
int SCS::readByte(u8 ID, u8 MemAddr)
|
||||
{
|
||||
u8 bDat;
|
||||
int Size = Read(ID, MemAddr, &bDat, 1);
|
||||
if (Size != 1) {
|
||||
return -1;
|
||||
} else {
|
||||
return bDat;
|
||||
}
|
||||
}
|
||||
|
||||
// Read 2 bytes, return -1 if timeout
|
||||
int SCS::readWord(u8 ID, u8 MemAddr)
|
||||
{
|
||||
u8 nDat[2];
|
||||
int Size;
|
||||
u16 wDat;
|
||||
Size = Read(ID, MemAddr, nDat, 2);
|
||||
if (Size != 2) return -1;
|
||||
wDat = SCS2Host(nDat[0], nDat[1]);
|
||||
return wDat;
|
||||
}
|
||||
|
||||
// Ping command, return the servo ID, timeout returns -1
|
||||
int SCS::Ping(u8 ID)
|
||||
{
|
||||
rFlushSCS();
|
||||
writeBuf(ID, 0, NULL, 0, INST_PING);
|
||||
wFlushSCS();
|
||||
Error = 0;
|
||||
if (!checkHead()) {
|
||||
return -1;
|
||||
}
|
||||
u8 bBuf[4];
|
||||
if (readSCS(bBuf, 4) != 4) {
|
||||
return -1;
|
||||
}
|
||||
if (bBuf[0] != ID && ID != 0xfe) {
|
||||
return -1;
|
||||
}
|
||||
if (bBuf[1] != 2) {
|
||||
return -1;
|
||||
}
|
||||
u8 calSum = ~(bBuf[0] + bBuf[1] + bBuf[2]);
|
||||
if (calSum != bBuf[3]) {
|
||||
return -1;
|
||||
}
|
||||
Error = bBuf[2];
|
||||
return bBuf[0];
|
||||
}
|
||||
|
||||
int SCS::checkHead()
|
||||
{
|
||||
u8 bDat;
|
||||
u8 bBuf[2] = {0, 0};
|
||||
u8 Cnt = 0;
|
||||
while (1) {
|
||||
if (!readSCS(&bDat, 1)) {
|
||||
return 0;
|
||||
}
|
||||
bBuf[1] = bBuf[0];
|
||||
bBuf[0] = bDat;
|
||||
if (bBuf[0] == 0xff && bBuf[1] == 0xff) {
|
||||
break;
|
||||
}
|
||||
Cnt++;
|
||||
if (Cnt > 10) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int SCS::Ack(u8 ID)
|
||||
{
|
||||
Error = 0;
|
||||
if (ID != 0xfe && Level) {
|
||||
if (!checkHead()) {
|
||||
return 0;
|
||||
}
|
||||
u8 bBuf[4];
|
||||
if (readSCS(bBuf, 4) != 4) {
|
||||
return 0;
|
||||
}
|
||||
if (bBuf[0] != ID) {
|
||||
return 0;
|
||||
}
|
||||
if (bBuf[1] != 2) {
|
||||
return 0;
|
||||
}
|
||||
u8 calSum = ~(bBuf[0] + bBuf[1] + bBuf[2]);
|
||||
if (calSum != bBuf[3]) {
|
||||
return 0;
|
||||
}
|
||||
Error = bBuf[2];
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int SCS::syncReadPacketTx(u8 ID[], u8 IDN, u8 MemAddr, u8 nLen)
|
||||
{
|
||||
syncReadRxPacketLen = nLen;
|
||||
u8 checkSum = (4 + 0xfe) + IDN + MemAddr + nLen + INST_SYNC_READ;
|
||||
u8 i;
|
||||
writeSCS(0xff);
|
||||
writeSCS(0xff);
|
||||
writeSCS(0xfe);
|
||||
writeSCS(IDN + 4);
|
||||
writeSCS(INST_SYNC_READ);
|
||||
writeSCS(MemAddr);
|
||||
writeSCS(nLen);
|
||||
for (i = 0; i < IDN; i++) {
|
||||
writeSCS(ID[i]);
|
||||
checkSum += ID[i];
|
||||
}
|
||||
checkSum = ~checkSum;
|
||||
writeSCS(checkSum);
|
||||
return nLen;
|
||||
}
|
||||
|
||||
int SCS::syncReadPacketRx(u8 ID, u8 *nDat)
|
||||
{
|
||||
syncReadRxPacket = nDat;
|
||||
syncReadRxPacketIndex = 0;
|
||||
u8 bBuf[4];
|
||||
if (!checkHead()) {
|
||||
return 0;
|
||||
}
|
||||
if (readSCS(bBuf, 3) != 3) {
|
||||
return 0;
|
||||
}
|
||||
if (bBuf[0] != ID) {
|
||||
return 0;
|
||||
}
|
||||
if (bBuf[1] != (syncReadRxPacketLen + 2)) {
|
||||
return 0;
|
||||
}
|
||||
Error = bBuf[2];
|
||||
if (readSCS(nDat, syncReadRxPacketLen) != syncReadRxPacketLen) {
|
||||
return 0;
|
||||
}
|
||||
return syncReadRxPacketLen;
|
||||
}
|
||||
|
||||
int SCS::syncReadRxPacketToByte()
|
||||
{
|
||||
if (syncReadRxPacketIndex >= syncReadRxPacketLen) {
|
||||
return -1;
|
||||
}
|
||||
return syncReadRxPacket[syncReadRxPacketIndex++];
|
||||
}
|
||||
|
||||
int SCS::syncReadRxPacketToWrod(u8 negBit)
|
||||
{
|
||||
if ((syncReadRxPacketIndex + 1) >= syncReadRxPacketLen) {
|
||||
return -1;
|
||||
}
|
||||
int Word = SCS2Host(syncReadRxPacket[syncReadRxPacketIndex], syncReadRxPacket[syncReadRxPacketIndex + 1]);
|
||||
syncReadRxPacketIndex += 2;
|
||||
if (negBit) {
|
||||
if (Word & (1 << negBit)) {
|
||||
Word = -(Word & ~(1 << negBit));
|
||||
}
|
||||
}
|
||||
return Word;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* SCS.h
|
||||
* FIT serial servo communication layer protocol program
|
||||
*/
|
||||
|
||||
#ifndef _SCS_H
|
||||
#define _SCS_H
|
||||
|
||||
#include "INST.h"
|
||||
|
||||
class SCS {
|
||||
public:
|
||||
SCS();
|
||||
SCS(u8 End);
|
||||
SCS(u8 End, u8 Level);
|
||||
int genWrite(u8 ID, u8 MemAddr, u8 *nDat, u8 nLen); // Normal write instruction
|
||||
int regWrite(u8 ID, u8 MemAddr, u8 *nDat, u8 nLen); // Asynchronous write command
|
||||
int RegWriteAction(u8 ID = 0xfe); // Asynchronous write execution instruction
|
||||
void syncWrite(u8 ID[], u8 IDN, u8 MemAddr, u8 *nDat, u8 nLen); // Synchronous write instruction
|
||||
int writeByte(u8 ID, u8 MemAddr, u8 bDat); // Write 1 byte
|
||||
int writeWord(u8 ID, u8 MemAddr, u16 wDat); // Write 2 bytes
|
||||
int Read(u8 ID, u8 MemAddr, u8 *nData, u8 nLen); // Read instruction
|
||||
int readByte(u8 ID, u8 MemAddr); // Read 1 byte
|
||||
int readWord(u8 ID, u8 MemAddr); // Read 2 bytes
|
||||
int Ping(u8 ID); // Ping Command
|
||||
int syncReadPacketTx(u8 ID[], u8 IDN, u8 MemAddr, u8 nLen); // Synchronous read instruction packet sending
|
||||
int syncReadPacketRx(
|
||||
u8 ID,
|
||||
u8 *nDat); // Synchronous read return packet reception, successful return memory byte count, failed return 0
|
||||
int syncReadRxPacketToByte(); // Decode a byte
|
||||
int syncReadRxPacketToWrod(
|
||||
u8 negBit = 0); // Decode two bytes, negBit is the direction, negBit=0 means no direction
|
||||
public:
|
||||
u8 Level; // Servo return level
|
||||
u8 End; // Processor endian structure
|
||||
u8 Error; // Servo status
|
||||
u8 syncReadRxPacketIndex;
|
||||
u8 syncReadRxPacketLen;
|
||||
u8 *syncReadRxPacket;
|
||||
|
||||
protected:
|
||||
virtual int writeSCS(unsigned char *nDat, int nLen) = 0;
|
||||
virtual int readSCS(unsigned char *nDat, int nLen) = 0;
|
||||
virtual int writeSCS(unsigned char bDat) = 0;
|
||||
virtual void rFlushSCS() = 0;
|
||||
virtual void wFlushSCS() = 0;
|
||||
|
||||
protected:
|
||||
void writeBuf(u8 ID, u8 MemAddr, u8 *nDat, u8 nLen, u8 Fun);
|
||||
void Host2SCS(u8 *DataL, u8 *DataH, u16 Data); // Split a 16-digit number into two 8-digit numbers
|
||||
u16 SCS2Host(u8 DataL, u8 DataH); // Two 8-digit numbers combined into a 16-digit number
|
||||
int Ack(u8 ID); // Return Response
|
||||
int checkHead(); // Frame header detection
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,319 @@
|
||||
/*
|
||||
* SCSCL.cpp
|
||||
* FIT SCSCL series serial servo application layer program
|
||||
*/
|
||||
|
||||
#include "SCSCL.h"
|
||||
|
||||
SCSCL::SCSCL()
|
||||
{
|
||||
End = 1;
|
||||
}
|
||||
|
||||
SCSCL::SCSCL(u8 End) : SCSerial(End)
|
||||
{
|
||||
}
|
||||
|
||||
SCSCL::SCSCL(u8 End, u8 Level) : SCSerial(End, Level)
|
||||
{
|
||||
}
|
||||
|
||||
int SCSCL::WritePos(u8 ID, u16 Position, u16 Time, u16 Speed)
|
||||
{
|
||||
u8 bBuf[6];
|
||||
Host2SCS(bBuf + 0, bBuf + 1, Position);
|
||||
Host2SCS(bBuf + 2, bBuf + 3, Time);
|
||||
Host2SCS(bBuf + 4, bBuf + 5, Speed);
|
||||
|
||||
return genWrite(ID, SCSCL_GOAL_POSITION_L, bBuf, 6);
|
||||
}
|
||||
|
||||
int SCSCL::WritePosEx(u8 ID, s16 Position, u16 Speed, u8 ACC)
|
||||
{
|
||||
(void)ACC; // ACC parameter is not used in this implementation
|
||||
u16 Time = 0;
|
||||
u8 bBuf[6];
|
||||
Host2SCS(bBuf + 0, bBuf + 1, Position);
|
||||
Host2SCS(bBuf + 2, bBuf + 3, Time);
|
||||
Host2SCS(bBuf + 4, bBuf + 5, Speed);
|
||||
|
||||
return genWrite(ID, SCSCL_GOAL_POSITION_L, bBuf, 6);
|
||||
}
|
||||
|
||||
int SCSCL::RegWritePos(u8 ID, u16 Position, u16 Time, u16 Speed)
|
||||
{
|
||||
u8 bBuf[6];
|
||||
Host2SCS(bBuf + 0, bBuf + 1, Position);
|
||||
Host2SCS(bBuf + 2, bBuf + 3, Time);
|
||||
Host2SCS(bBuf + 4, bBuf + 5, Speed);
|
||||
|
||||
return regWrite(ID, SCSCL_GOAL_POSITION_L, bBuf, 6);
|
||||
}
|
||||
|
||||
int SCSCL::CalibrationOfs(u8 ID)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
void SCSCL::SyncWritePos(u8 ID[], u8 IDN, u16 Position[], u16 Time[], u16 Speed[])
|
||||
{
|
||||
u8 offbuf[6 * IDN];
|
||||
for (u8 i = 0; i < IDN; i++) {
|
||||
u16 T, V;
|
||||
if (Time) {
|
||||
T = Time[i];
|
||||
} else {
|
||||
T = 0;
|
||||
}
|
||||
if (Speed) {
|
||||
V = Speed[i];
|
||||
} else {
|
||||
V = 0;
|
||||
}
|
||||
Host2SCS(offbuf + i * 6 + 0, offbuf + i * 6 + 1, Position[i]);
|
||||
Host2SCS(offbuf + i * 6 + 2, offbuf + i * 6 + 3, T);
|
||||
Host2SCS(offbuf + i * 6 + 4, offbuf + i * 6 + 5, V);
|
||||
}
|
||||
syncWrite(ID, IDN, SCSCL_GOAL_POSITION_L, offbuf, 6);
|
||||
}
|
||||
|
||||
int SCSCL::PWMMode(u8 ID)
|
||||
{
|
||||
u8 bBuf[4];
|
||||
bBuf[0] = 0;
|
||||
bBuf[1] = 0;
|
||||
bBuf[2] = 0;
|
||||
bBuf[3] = 0;
|
||||
return genWrite(ID, SCSCL_MIN_ANGLE_LIMIT_L, bBuf, 4);
|
||||
}
|
||||
|
||||
int SCSCL::WritePWM(u8 ID, s16 pwmOut)
|
||||
{
|
||||
if (pwmOut < 0) {
|
||||
pwmOut = -pwmOut;
|
||||
pwmOut |= (1 << 10);
|
||||
}
|
||||
u8 bBuf[2];
|
||||
Host2SCS(bBuf + 0, bBuf + 1, pwmOut);
|
||||
|
||||
return genWrite(ID, SCSCL_GOAL_TIME_L, bBuf, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch between position mode and PWM mode 切换位置模式和PWM模式
|
||||
* ID: Servo ID
|
||||
* mode: 0 for position mode, 1 for PWM mode 0表示位置模式,1表示PWM模式
|
||||
* Return: Result of the operation
|
||||
*/
|
||||
int SCSCL::SwitchMode(int ID, uint8_t mode)
|
||||
{
|
||||
if (ID < 0 || ID > 1) {
|
||||
return -1; // Invalid ID
|
||||
}
|
||||
if (mode > 1) {
|
||||
return -2; // Invalid mode
|
||||
}
|
||||
|
||||
if (mode == 1) { // PWM mode
|
||||
// Store current angle limits
|
||||
min_angle[ID] = readWord(ID, SCSCL_MIN_ANGLE_LIMIT_L);
|
||||
max_angle[ID] = readWord(ID, SCSCL_MAX_ANGLE_LIMIT_L);
|
||||
|
||||
if (min_angle[ID] == -1 || max_angle[ID] == -1) {
|
||||
return -3; // Failed to read angle limits
|
||||
}
|
||||
PWMMode(ID); // Switch to PWM mode
|
||||
return 0;
|
||||
} else { // Position mode (mode == 0)
|
||||
if (writeWord(ID, SCSCL_MIN_ANGLE_LIMIT_L, (uint16_t)min_angle[ID]) != 1) {
|
||||
return -4; // Failed to write min angle limit
|
||||
}
|
||||
if (writeWord(ID, SCSCL_MAX_ANGLE_LIMIT_L, (uint16_t)max_angle[ID]) != 1) {
|
||||
return -5; // Failed to write max angle limit
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disable torque 扭矩开关
|
||||
* ID: Servo ID
|
||||
* Enable: 1 to enable, 0 to disable 2 to damping 1表示使能,0表示关闭,2表示阻尼
|
||||
* Return: Result of the operation
|
||||
*/
|
||||
int SCSCL::EnableTorque(u8 ID, u8 Enable)
|
||||
{
|
||||
return writeByte(ID, SCSCL_TORQUE_ENABLE, Enable);
|
||||
}
|
||||
|
||||
int SCSCL::unLockEprom(u8 ID)
|
||||
{
|
||||
return writeByte(ID, SCSCL_LOCK, 0);
|
||||
}
|
||||
|
||||
int SCSCL::LockEprom(u8 ID)
|
||||
{
|
||||
return writeByte(ID, SCSCL_LOCK, 1);
|
||||
}
|
||||
|
||||
int SCSCL::FeedBack(int ID)
|
||||
{
|
||||
int nLen = Read(ID, SCSCL_PRESENT_POSITION_L, Mem, sizeof(Mem));
|
||||
if (nLen != sizeof(Mem)) {
|
||||
Err = 1;
|
||||
return -1;
|
||||
}
|
||||
Err = 0;
|
||||
return nLen;
|
||||
}
|
||||
|
||||
int SCSCL::ReadPos(int ID)
|
||||
{
|
||||
int Pos = -1;
|
||||
if (ID == -1) {
|
||||
Pos = Mem[SCSCL_PRESENT_POSITION_L - SCSCL_PRESENT_POSITION_L];
|
||||
Pos <<= 8;
|
||||
Pos |= Mem[SCSCL_PRESENT_POSITION_H - SCSCL_PRESENT_POSITION_L];
|
||||
} else {
|
||||
Err = 0;
|
||||
Pos = readWord(ID, SCSCL_PRESENT_POSITION_L);
|
||||
if (Pos == -1) {
|
||||
Err = 1;
|
||||
}
|
||||
}
|
||||
return Pos;
|
||||
}
|
||||
|
||||
int SCSCL::ReadSpeed(int ID)
|
||||
{
|
||||
int Speed = -1;
|
||||
if (ID == -1) {
|
||||
Speed = Mem[SCSCL_PRESENT_SPEED_L - SCSCL_PRESENT_POSITION_L];
|
||||
Speed <<= 8;
|
||||
Speed |= Mem[SCSCL_PRESENT_SPEED_H - SCSCL_PRESENT_POSITION_L];
|
||||
} else {
|
||||
Err = 0;
|
||||
Speed = readWord(ID, SCSCL_PRESENT_SPEED_L);
|
||||
if (Speed == -1) {
|
||||
Err = 1;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (!Err && (Speed & (1 << 15))) {
|
||||
Speed = -(Speed & ~(1 << 15));
|
||||
}
|
||||
return Speed;
|
||||
}
|
||||
|
||||
int SCSCL::ReadLoad(int ID)
|
||||
{
|
||||
int Load = -1;
|
||||
if (ID == -1) {
|
||||
Load = Mem[SCSCL_PRESENT_LOAD_L - SCSCL_PRESENT_POSITION_L];
|
||||
Load <<= 8;
|
||||
Load |= Mem[SCSCL_PRESENT_LOAD_H - SCSCL_PRESENT_POSITION_L];
|
||||
} else {
|
||||
Err = 0;
|
||||
Load = readWord(ID, SCSCL_PRESENT_LOAD_L);
|
||||
if (Load == -1) {
|
||||
Err = 1;
|
||||
}
|
||||
}
|
||||
if (!Err && (Load & (1 << 10))) {
|
||||
Load = -(Load & ~(1 << 10));
|
||||
}
|
||||
return Load;
|
||||
}
|
||||
|
||||
int SCSCL::ReadVoltage(int ID)
|
||||
{
|
||||
int Voltage = -1;
|
||||
if (ID == -1) {
|
||||
Voltage = Mem[SCSCL_PRESENT_VOLTAGE - SCSCL_PRESENT_POSITION_L];
|
||||
} else {
|
||||
Err = 0;
|
||||
Voltage = readByte(ID, SCSCL_PRESENT_VOLTAGE);
|
||||
if (Voltage == -1) {
|
||||
Err = 1;
|
||||
}
|
||||
}
|
||||
return Voltage;
|
||||
}
|
||||
|
||||
int SCSCL::ReadTemper(int ID)
|
||||
{
|
||||
int Temper = -1;
|
||||
if (ID == -1) {
|
||||
Temper = Mem[SCSCL_PRESENT_TEMPERATURE - SCSCL_PRESENT_POSITION_L];
|
||||
} else {
|
||||
Err = 0;
|
||||
Temper = readByte(ID, SCSCL_PRESENT_TEMPERATURE);
|
||||
if (Temper == -1) {
|
||||
Err = 1;
|
||||
}
|
||||
}
|
||||
return Temper;
|
||||
}
|
||||
|
||||
int SCSCL::ReadMove(int ID)
|
||||
{
|
||||
int Move = -1;
|
||||
if (ID == -1) {
|
||||
Move = Mem[SCSCL_MOVING - SCSCL_PRESENT_POSITION_L];
|
||||
} else {
|
||||
Err = 0;
|
||||
Move = readByte(ID, SCSCL_MOVING);
|
||||
if (Move == -1) {
|
||||
Err = 1;
|
||||
}
|
||||
}
|
||||
return Move;
|
||||
}
|
||||
|
||||
int SCSCL::ReadMode(int ID)
|
||||
{
|
||||
int ValueRead = -1;
|
||||
ValueRead = readWord(ID, SCSCL_MIN_ANGLE_LIMIT_L);
|
||||
if (ValueRead == 0) {
|
||||
return 1;
|
||||
} else if (ValueRead > 0) {
|
||||
return 0;
|
||||
}
|
||||
return ValueRead;
|
||||
}
|
||||
|
||||
int SCSCL::ReadToqueEnable(int ID)
|
||||
{
|
||||
// return writeByte(ID, SCSCL_TORQUE_ENABLE, Enable);
|
||||
int ValueRead = -1;
|
||||
ValueRead = readWord(ID, SCSCL_TORQUE_ENABLE);
|
||||
return ValueRead;
|
||||
}
|
||||
|
||||
int SCSCL::ReadInfoValue(int ID, int AddInput)
|
||||
{
|
||||
int ValueRead = -1;
|
||||
ValueRead = readWord(ID, AddInput);
|
||||
return ValueRead;
|
||||
}
|
||||
|
||||
int SCSCL::ReadCurrent(int ID)
|
||||
{
|
||||
int Current = -1;
|
||||
if (ID == -1) {
|
||||
Current = Mem[SCSCL_PRESENT_CURRENT_L - SCSCL_PRESENT_POSITION_L];
|
||||
Current <<= 8;
|
||||
Current |= Mem[SCSCL_PRESENT_CURRENT_H - SCSCL_PRESENT_POSITION_L];
|
||||
} else {
|
||||
Err = 0;
|
||||
Current = readWord(ID, SCSCL_PRESENT_CURRENT_L);
|
||||
if (Current == -1) {
|
||||
Err = 1;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (!Err && (Current & (1 << 15))) {
|
||||
Current = -(Current & ~(1 << 15));
|
||||
}
|
||||
return Current;
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* SCSCL.h
|
||||
* FIT SCSCL series serial servo application layer program
|
||||
*/
|
||||
|
||||
#ifndef _SCSCL_H
|
||||
#define _SCSCL_H
|
||||
|
||||
// Memory table definition
|
||||
//-------EPROM (read-only)--------
|
||||
#define SCSCL_VERSION_L 3
|
||||
#define SCSCL_VERSION_H 4
|
||||
|
||||
//-------EPROM (read and write)--------
|
||||
#define SCSCL_ID 5
|
||||
#define SCSCL_BAUD_RATE 6
|
||||
#define SCSCL_MIN_ANGLE_LIMIT_L 9
|
||||
#define SCSCL_MIN_ANGLE_LIMIT_H 10
|
||||
#define SCSCL_MAX_ANGLE_LIMIT_L 11
|
||||
#define SCSCL_MAX_ANGLE_LIMIT_H 12
|
||||
#define SCSCL_CW_DEAD 26
|
||||
#define SCSCL_CCW_DEAD 27
|
||||
|
||||
//-------SRAM (read and write)--------
|
||||
#define SCSCL_TORQUE_ENABLE 40
|
||||
#define SCSCL_GOAL_POSITION_L 42
|
||||
#define SCSCL_GOAL_POSITION_H 43
|
||||
#define SCSCL_GOAL_TIME_L 44
|
||||
#define SCSCL_GOAL_TIME_H 45
|
||||
#define SCSCL_GOAL_SPEED_L 46
|
||||
#define SCSCL_GOAL_SPEED_H 47
|
||||
#define SCSCL_LOCK 48
|
||||
|
||||
//-------SRAM (read only)--------
|
||||
#define SCSCL_PRESENT_POSITION_L 56
|
||||
#define SCSCL_PRESENT_POSITION_H 57
|
||||
#define SCSCL_PRESENT_SPEED_L 58
|
||||
#define SCSCL_PRESENT_SPEED_H 59
|
||||
#define SCSCL_PRESENT_LOAD_L 60
|
||||
#define SCSCL_PRESENT_LOAD_H 61
|
||||
#define SCSCL_PRESENT_VOLTAGE 62
|
||||
#define SCSCL_PRESENT_TEMPERATURE 63
|
||||
#define SCSCL_MOVING 66
|
||||
#define SCSCL_PRESENT_CURRENT_L 69
|
||||
#define SCSCL_PRESENT_CURRENT_H 70
|
||||
|
||||
#include "SCSerial.h"
|
||||
|
||||
class SCSCL : public SCSerial {
|
||||
public:
|
||||
SCSCL();
|
||||
SCSCL(u8 End);
|
||||
SCSCL(u8 End, u8 Level);
|
||||
virtual int WritePos(u8 ID, u16 Position, u16 Time, u16 Speed); // Normal write of single servo position command
|
||||
virtual int WritePosEx(u8 ID, s16 Position, u16 Speed, u8 ACC); // Single servo position command
|
||||
virtual int RegWritePos(
|
||||
u8 ID, u16 Position, u16 Time,
|
||||
u16 Speed = 0); // Asynchronously write a single servo position command (RegWriteAction takes effect)
|
||||
virtual void SyncWritePos(u8 ID[], u8 IDN, u16 Position[], u16 Time[],
|
||||
u16 Speed[]); // Synchronously write multiple servo position commands
|
||||
virtual int PWMMode(u8 ID); // PWM output mode
|
||||
virtual int WritePWM(u8 ID, s16 pwmOut); // PWM output mode command
|
||||
virtual int SwitchMode(int ID, uint8_t mode); // Switch between position mode and PWM mode
|
||||
virtual int EnableTorque(u8 ID, u8 Enable); // Torque control command
|
||||
virtual int unLockEprom(u8 ID); // eprom unlock
|
||||
virtual int LockEprom(u8 ID); // eprom lock
|
||||
virtual int FeedBack(int ID); // Feedback servo information
|
||||
virtual int ReadPos(int ID); // Read position
|
||||
virtual int ReadSpeed(int ID); // Read speed
|
||||
virtual int ReadLoad(int ID); // Read the output voltage percentage to the motor (0~1000)
|
||||
virtual int ReadVoltage(int ID); // Read voltage
|
||||
virtual int ReadTemper(int ID); // Read temperature
|
||||
virtual int ReadMove(int ID); // Read movement status
|
||||
virtual int ReadCurrent(int ID); // read current
|
||||
virtual int ReadMode(int ID);
|
||||
virtual int ReadToqueEnable(int ID);
|
||||
virtual int CalibrationOfs(u8 ID);
|
||||
virtual int ReadInfoValue(int ID, int AddInput);
|
||||
|
||||
private:
|
||||
u8 Mem[SCSCL_PRESENT_CURRENT_H - SCSCL_PRESENT_POSITION_L + 1];
|
||||
int min_angle[2];
|
||||
int max_angle[2];
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* SCSerial.cpp
|
||||
* FIT serial servo hardware interface layer program
|
||||
*/
|
||||
|
||||
#include "SCSerial.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_timer.h"
|
||||
|
||||
static const char *TAG = "SCSerial";
|
||||
|
||||
SCSerial::SCSerial()
|
||||
{
|
||||
IOTimeOut = 100;
|
||||
uart_num = UART_NUM_MAX;
|
||||
}
|
||||
|
||||
SCSerial::SCSerial(u8 End) : SCS(End)
|
||||
{
|
||||
IOTimeOut = 100;
|
||||
uart_num = UART_NUM_MAX;
|
||||
}
|
||||
|
||||
SCSerial::SCSerial(u8 End, u8 Level) : SCS(End, Level)
|
||||
{
|
||||
IOTimeOut = 100;
|
||||
uart_num = UART_NUM_MAX;
|
||||
}
|
||||
|
||||
bool SCSerial::begin(uart_port_t uart_num, int baud_rate, int tx_pin, int rx_pin, int buf_size)
|
||||
{
|
||||
this->uart_num = uart_num;
|
||||
|
||||
uart_config_t uart_config = {
|
||||
.baud_rate = baud_rate,
|
||||
.data_bits = UART_DATA_8_BITS,
|
||||
.parity = UART_PARITY_DISABLE,
|
||||
.stop_bits = UART_STOP_BITS_1,
|
||||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
||||
.rx_flow_ctrl_thresh = 0,
|
||||
.source_clk = UART_SCLK_DEFAULT,
|
||||
};
|
||||
|
||||
esp_err_t ret = uart_driver_install(uart_num, buf_size, buf_size, 0, NULL, 0);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to install UART driver: %s", esp_err_to_name(ret));
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = uart_param_config(uart_num, &uart_config);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to configure UART: %s", esp_err_to_name(ret));
|
||||
uart_driver_delete(uart_num);
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = uart_set_pin(uart_num, tx_pin, rx_pin, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to set UART pins: %s", esp_err_to_name(ret));
|
||||
uart_driver_delete(uart_num);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SCSerial::end()
|
||||
{
|
||||
if (uart_num < UART_NUM_MAX) {
|
||||
uart_driver_delete(uart_num);
|
||||
uart_num = UART_NUM_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
int SCSerial::readSCS(unsigned char *nDat, int nLen)
|
||||
{
|
||||
if (uart_num >= UART_NUM_MAX) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Size = 0;
|
||||
int64_t t_begin = esp_timer_get_time() / 1000; // Convert to milliseconds
|
||||
int64_t t_user;
|
||||
|
||||
while (1) {
|
||||
size_t available = 0;
|
||||
uart_get_buffered_data_len(uart_num, &available);
|
||||
|
||||
if (available > 0) {
|
||||
unsigned char byte;
|
||||
int len = uart_read_bytes(uart_num, &byte, 1, 0);
|
||||
if (len > 0) {
|
||||
if (nDat) {
|
||||
nDat[Size] = byte;
|
||||
}
|
||||
Size++;
|
||||
t_begin = esp_timer_get_time() / 1000;
|
||||
}
|
||||
}
|
||||
|
||||
if (Size >= nLen) {
|
||||
break;
|
||||
}
|
||||
|
||||
t_user = (esp_timer_get_time() / 1000) - t_begin;
|
||||
if (t_user > IOTimeOut) {
|
||||
break;
|
||||
}
|
||||
|
||||
vTaskDelay(1 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
return Size;
|
||||
}
|
||||
|
||||
int SCSerial::writeSCS(unsigned char *nDat, int nLen)
|
||||
{
|
||||
if (uart_num >= UART_NUM_MAX || nDat == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int len = uart_write_bytes(uart_num, (const char *)nDat, nLen);
|
||||
return len;
|
||||
}
|
||||
|
||||
int SCSerial::writeSCS(unsigned char bDat)
|
||||
{
|
||||
if (uart_num >= UART_NUM_MAX) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int len = uart_write_bytes(uart_num, (const char *)&bDat, 1);
|
||||
return len;
|
||||
}
|
||||
|
||||
void SCSerial::rFlushSCS()
|
||||
{
|
||||
if (uart_num >= UART_NUM_MAX) {
|
||||
return;
|
||||
}
|
||||
|
||||
uart_flush_input(uart_num);
|
||||
}
|
||||
|
||||
void SCSerial::wFlushSCS()
|
||||
{
|
||||
if (uart_num >= UART_NUM_MAX) {
|
||||
return;
|
||||
}
|
||||
|
||||
uart_wait_tx_done(uart_num, pdMS_TO_TICKS(100));
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* SCSerial.h
|
||||
* FIT serial servo hardware interface layer program
|
||||
*/
|
||||
|
||||
#ifndef _SCSERIAL_H
|
||||
#define _SCSERIAL_H
|
||||
|
||||
#include "driver/uart.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include <string.h>
|
||||
|
||||
#include "SCS.h"
|
||||
|
||||
class SCSerial : public SCS {
|
||||
public:
|
||||
SCSerial();
|
||||
SCSerial(u8 End);
|
||||
SCSerial(u8 End, u8 Level);
|
||||
|
||||
// Initialize UART
|
||||
bool begin(uart_port_t uart_num, int baud_rate, int tx_pin, int rx_pin, int buf_size = 1024);
|
||||
void end();
|
||||
|
||||
protected:
|
||||
virtual int writeSCS(unsigned char *nDat, int nLen); // Output nLen bytes
|
||||
virtual int readSCS(unsigned char *nDat, int nLen); // Input nLen bytes
|
||||
virtual int writeSCS(unsigned char bDat); // Output 1 byte
|
||||
virtual void rFlushSCS();
|
||||
virtual void wFlushSCS();
|
||||
|
||||
public:
|
||||
unsigned long int IOTimeOut; // Input and output timeout (in milliseconds)
|
||||
uart_port_t uart_num; // UART port number
|
||||
int Err;
|
||||
|
||||
public:
|
||||
virtual int getErr()
|
||||
{
|
||||
return Err;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* SCServo.h
|
||||
* FIT serial servo interface
|
||||
*/
|
||||
|
||||
#ifndef _SCSERVO_H
|
||||
#define _SCSERVO_H
|
||||
|
||||
#include "SCSCL.h"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,310 @@
|
||||
#include "Si12T.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "esp_log.h"
|
||||
|
||||
static const char *TAG = "Si12T";
|
||||
|
||||
#define I2C_TIMEOUT_MS 100
|
||||
|
||||
/**
|
||||
* @brief Si12T设备结构体
|
||||
*/
|
||||
struct si12t_dev_t {
|
||||
i2c_master_dev_handle_t i2c_dev; /*!< I2C设备句柄 */
|
||||
uint8_t dev_addr; /*!< 设备地址 */
|
||||
};
|
||||
|
||||
uint8_t si12t_point_type[3] = {SI12T_OUTPUT_NONE, SI12T_OUTPUT_NONE, SI12T_OUTPUT_NONE};
|
||||
|
||||
/**
|
||||
* @brief 写寄存器
|
||||
*/
|
||||
static esp_err_t si12t_i2c_write_reg(si12t_handle_t handle, uint8_t reg_addr, uint8_t value)
|
||||
{
|
||||
uint8_t write_buf[2] = {reg_addr, value};
|
||||
return i2c_master_transmit(handle->i2c_dev, write_buf, sizeof(write_buf), I2C_TIMEOUT_MS);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 读寄存器
|
||||
*/
|
||||
static esp_err_t si12t_i2c_read_reg(si12t_handle_t handle, uint8_t reg_addr, uint8_t *value)
|
||||
{
|
||||
esp_err_t ret = i2c_master_transmit_receive(handle->i2c_dev, ®_addr, 1, value, 1, I2C_TIMEOUT_MS);
|
||||
ESP_LOGD(TAG, "Read reg 0x%02x, value: 0x%02x", reg_addr, *value);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 设置所有灵敏度寄存器
|
||||
*/
|
||||
static esp_err_t si12t_set_sens(si12t_handle_t handle, uint8_t value)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
ret |= si12t_i2c_write_reg(handle, SI12T_SENSITIVITY1_ADDR, value);
|
||||
ret |= si12t_i2c_write_reg(handle, SI12T_SENSITIVITY2_ADDR, value);
|
||||
ret |= si12t_i2c_write_reg(handle, SI12T_SENSITIVITY3_ADDR, value);
|
||||
ret |= si12t_i2c_write_reg(handle, SI12T_SENSITIVITY4_ADDR, value);
|
||||
ret |= si12t_i2c_write_reg(handle, SI12T_SENSITIVITY5_ADDR, value);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t si12t_init(const si12t_config_t *config, si12t_handle_t *handle)
|
||||
{
|
||||
if (config == NULL || handle == NULL || config->i2c_bus == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
si12t_handle_t dev = (si12t_handle_t)calloc(1, sizeof(struct si12t_dev_t));
|
||||
if (dev == NULL) {
|
||||
ESP_LOGE(TAG, "Failed to allocate memory for Si12T device");
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
dev->dev_addr = config->dev_addr ? config->dev_addr : SI12T_GND_ADDRESS;
|
||||
|
||||
i2c_device_config_t dev_cfg = {
|
||||
.dev_addr_length = I2C_ADDR_BIT_LEN_7,
|
||||
.device_address = dev->dev_addr,
|
||||
.scl_speed_hz = 100000, // 100kHz
|
||||
};
|
||||
|
||||
esp_err_t ret = i2c_master_bus_add_device(config->i2c_bus, &dev_cfg, &dev->i2c_dev);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to add I2C device: %s", esp_err_to_name(ret));
|
||||
free(dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
*handle = dev;
|
||||
ESP_LOGI(TAG, "Si12T initialized, version: %s", SI12T_VERSION);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t si12t_setup(si12t_handle_t handle, si12t_type_t sens_type, si12t_sensitivity_level_t sens_level)
|
||||
{
|
||||
if (handle == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
ret |= si12t_enable_channel(handle);
|
||||
ret |= si12t_set_ctrl2(handle);
|
||||
ret |= si12t_set_ctrl1(handle);
|
||||
ret |= si12t_set_sensitivity(handle, sens_type, sens_level);
|
||||
ret |= si12t_get_sensitivity(handle);
|
||||
|
||||
if (ret == ESP_OK) {
|
||||
ESP_LOGI(TAG, "Si12T setup done");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t si12t_delete(si12t_handle_t handle)
|
||||
{
|
||||
if (handle == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
esp_err_t ret = i2c_master_bus_rm_device(handle->i2c_dev);
|
||||
free(handle);
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t si12t_get_sensitivity(si12t_handle_t handle)
|
||||
{
|
||||
if (handle == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
uint8_t data = 0;
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
ret |= si12t_i2c_read_reg(handle, SI12T_SENSITIVITY1_ADDR, &data);
|
||||
ret |= si12t_i2c_read_reg(handle, SI12T_SENSITIVITY2_ADDR, &data);
|
||||
ret |= si12t_i2c_read_reg(handle, SI12T_SENSITIVITY3_ADDR, &data);
|
||||
ret |= si12t_i2c_read_reg(handle, SI12T_SENSITIVITY4_ADDR, &data);
|
||||
ret |= si12t_i2c_read_reg(handle, SI12T_SENSITIVITY5_ADDR, &data);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t si12t_set_sensitivity(si12t_handle_t handle, si12t_type_t sens_type, si12t_sensitivity_level_t sens_level)
|
||||
{
|
||||
if (handle == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (sens_type != SI12T_TYPE_LOW && sens_type != SI12T_TYPE_HIGH) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
uint8_t value = 0x00;
|
||||
|
||||
if (sens_type == SI12T_TYPE_HIGH) {
|
||||
switch (sens_level) {
|
||||
case SI12T_SENSITIVITY_LEVEL_0:
|
||||
value = 0x88;
|
||||
break;
|
||||
case SI12T_SENSITIVITY_LEVEL_1:
|
||||
value = 0x99;
|
||||
break;
|
||||
case SI12T_SENSITIVITY_LEVEL_2:
|
||||
value = 0xAA;
|
||||
break;
|
||||
case SI12T_SENSITIVITY_LEVEL_3:
|
||||
value = 0xBB;
|
||||
break;
|
||||
case SI12T_SENSITIVITY_LEVEL_4:
|
||||
value = 0xCC;
|
||||
break;
|
||||
case SI12T_SENSITIVITY_LEVEL_5:
|
||||
value = 0xDD;
|
||||
break;
|
||||
case SI12T_SENSITIVITY_LEVEL_6:
|
||||
value = 0xEE;
|
||||
break;
|
||||
case SI12T_SENSITIVITY_LEVEL_7:
|
||||
value = 0xFF;
|
||||
break;
|
||||
default:
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
} else {
|
||||
switch (sens_level) {
|
||||
case SI12T_SENSITIVITY_LEVEL_0:
|
||||
value = 0x00;
|
||||
break;
|
||||
case SI12T_SENSITIVITY_LEVEL_1:
|
||||
value = 0x11;
|
||||
break;
|
||||
case SI12T_SENSITIVITY_LEVEL_2:
|
||||
value = 0x22;
|
||||
break;
|
||||
case SI12T_SENSITIVITY_LEVEL_3:
|
||||
value = 0x33;
|
||||
break;
|
||||
case SI12T_SENSITIVITY_LEVEL_4:
|
||||
value = 0x44;
|
||||
break;
|
||||
case SI12T_SENSITIVITY_LEVEL_5:
|
||||
value = 0x55;
|
||||
break;
|
||||
case SI12T_SENSITIVITY_LEVEL_6:
|
||||
value = 0x66;
|
||||
break;
|
||||
case SI12T_SENSITIVITY_LEVEL_7:
|
||||
value = 0x77;
|
||||
break;
|
||||
default:
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "Set sensitivity value: 0x%02x", value);
|
||||
return si12t_set_sens(handle, value);
|
||||
}
|
||||
|
||||
esp_err_t si12t_set_ctrl1(si12t_handle_t handle)
|
||||
{
|
||||
if (handle == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
uint8_t test;
|
||||
// sends register data, Auto Mode, FTC=01, Interrupt(Middle,High), Response 4 (2+2)
|
||||
esp_err_t ret = si12t_i2c_write_reg(handle, SI12T_CTRL1_ADDR, 0x22);
|
||||
si12t_i2c_read_reg(handle, SI12T_CTRL1_ADDR, &test);
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t si12t_set_ctrl2(si12t_handle_t handle)
|
||||
{
|
||||
if (handle == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
uint8_t test;
|
||||
esp_err_t ret = ESP_OK;
|
||||
// S/W Reset Enable, Sleep Mode Enable
|
||||
ret |= si12t_i2c_write_reg(handle, SI12T_CTRL2_ADDR, 0x0F);
|
||||
ret |= si12t_i2c_write_reg(handle, SI12T_CTRL2_ADDR, 0x07);
|
||||
si12t_i2c_read_reg(handle, SI12T_CTRL2_ADDR, &test);
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t si12t_sleep_enable(si12t_handle_t handle)
|
||||
{
|
||||
if (handle == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
return si12t_i2c_write_reg(handle, SI12T_CTRL2_ADDR, 0x07); // S/W Reset Enable, Sleep Mode Enable
|
||||
}
|
||||
|
||||
esp_err_t si12t_sleep_disable(si12t_handle_t handle)
|
||||
{
|
||||
if (handle == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
return si12t_i2c_write_reg(handle, SI12T_CTRL2_ADDR, 0x03); // S/W Reset Disable, Sleep Mode Disable
|
||||
}
|
||||
|
||||
esp_err_t si12t_enable_channel(si12t_handle_t handle)
|
||||
{
|
||||
if (handle == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
esp_err_t ret = ESP_OK;
|
||||
uint8_t data = 1;
|
||||
|
||||
ret |= si12t_i2c_write_reg(handle, SI12T_REF_RST1_ADDR, 0x00); // channel 1-8 enable reference calibration
|
||||
ret |= si12t_i2c_write_reg(handle, SI12T_REF_RST2_ADDR, 0x00); // channel 9 enable reference calibration
|
||||
|
||||
ret |= si12t_i2c_write_reg(handle, SI12T_CH_HOLD1_ADDR, 0x00); // channel 1-8 enable
|
||||
ret |= si12t_i2c_write_reg(handle, SI12T_CH_HOLD2_ADDR, 0x00); // channel 9 enable
|
||||
|
||||
ret |= si12t_i2c_write_reg(handle, SI12T_CAL_HOLD1_ADDR, 0x00); // channel 1-8 enable reference calibration
|
||||
ret |= si12t_i2c_write_reg(handle, SI12T_CAL_HOLD2_ADDR, 0x00); // channel 9 enable reference calibration
|
||||
|
||||
// Read back to verify
|
||||
si12t_i2c_read_reg(handle, SI12T_REF_RST1_ADDR, &data);
|
||||
si12t_i2c_read_reg(handle, SI12T_REF_RST2_ADDR, &data);
|
||||
si12t_i2c_read_reg(handle, SI12T_CH_HOLD1_ADDR, &data);
|
||||
si12t_i2c_read_reg(handle, SI12T_CH_HOLD2_ADDR, &data);
|
||||
si12t_i2c_read_reg(handle, SI12T_CAL_HOLD1_ADDR, &data);
|
||||
si12t_i2c_read_reg(handle, SI12T_CAL_HOLD2_ADDR, &data);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t si12t_read_touch_result(si12t_handle_t handle, uint8_t *touch_result)
|
||||
{
|
||||
if (handle == NULL || touch_result == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
return si12t_i2c_read_reg(handle, SI12T_OUTPUT1_ADDR, touch_result);
|
||||
}
|
||||
|
||||
void si12t_parse_touch_result(uint8_t touch_result)
|
||||
{
|
||||
int index = 0;
|
||||
for (int j = 0; j < 6; j += 2) {
|
||||
si12t_point_type[index] = (touch_result >> j) & 0x03;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
void si12t_parse_touch_result_to(uint8_t touch_result, uint8_t *parsed_result)
|
||||
{
|
||||
int index = 0;
|
||||
for (int j = 0; j < 6; j += 2) {
|
||||
parsed_result[index] = (touch_result >> j) & 0x03;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
#ifndef __SI12T_H__
|
||||
#define __SI12T_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "driver/i2c_master.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define SI12T_VERSION "0.0.2"
|
||||
|
||||
/*LTR-507 SEL pin is "GND"*/
|
||||
#define SI12T_GND_ADDRESS 0x68 // 7bit i2c address
|
||||
|
||||
#define SI12T_SENSITIVITY1_ADDR 0x02
|
||||
#define SI12T_SENSITIVITY2_ADDR 0x03
|
||||
#define SI12T_SENSITIVITY3_ADDR 0x04
|
||||
#define SI12T_SENSITIVITY4_ADDR 0x05
|
||||
#define SI12T_SENSITIVITY5_ADDR 0x06
|
||||
#define SI12T_SENSITIVITY6_ADDR 0x07
|
||||
#define SI12T_CTRL1_ADDR 0x08
|
||||
#define SI12T_CTRL2_ADDR 0x09
|
||||
#define SI12T_REF_RST1_ADDR 0x0A
|
||||
#define SI12T_REF_RST2_ADDR 0x0B
|
||||
#define SI12T_CH_HOLD1_ADDR 0x0C
|
||||
#define SI12T_CH_HOLD2_ADDR 0x0D
|
||||
#define SI12T_CAL_HOLD1_ADDR 0x0E
|
||||
#define SI12T_CAL_HOLD2_ADDR 0x0F
|
||||
#define SI12T_OUTPUT1_ADDR 0x10
|
||||
#define SI12T_OUTPUT2_ADDR 0x11
|
||||
#define SI12T_OUTPUT3_ADDR 0x12
|
||||
|
||||
typedef enum { SI12T_TYPE_LOW = 0, SI12T_TYPE_HIGH } si12t_type_t;
|
||||
|
||||
typedef enum {
|
||||
SI12T_SENSITIVITY_LEVEL_0 = 0,
|
||||
SI12T_SENSITIVITY_LEVEL_1,
|
||||
SI12T_SENSITIVITY_LEVEL_2,
|
||||
SI12T_SENSITIVITY_LEVEL_3,
|
||||
SI12T_SENSITIVITY_LEVEL_4,
|
||||
SI12T_SENSITIVITY_LEVEL_5,
|
||||
SI12T_SENSITIVITY_LEVEL_6,
|
||||
SI12T_SENSITIVITY_LEVEL_7,
|
||||
SI12T_SENSITIVITY_LEVEL_INVALID,
|
||||
} si12t_sensitivity_level_t;
|
||||
|
||||
typedef enum { SI12T_OUTPUT_NONE = 0, SI12T_OUTPUT_LOW, SI12T_OUTPUT_MID, SI12T_OUTPUT_HIGH } si12t_output_t;
|
||||
|
||||
/**
|
||||
* @brief Si12T配置结构体
|
||||
*/
|
||||
typedef struct {
|
||||
i2c_master_bus_handle_t i2c_bus; /*!< I2C总线句柄 */
|
||||
uint8_t dev_addr; /*!< 设备地址,默认SI12T_GND_ADDRESS */
|
||||
} si12t_config_t;
|
||||
|
||||
/**
|
||||
* @brief Si12T设备句柄
|
||||
*/
|
||||
typedef struct si12t_dev_t *si12t_handle_t;
|
||||
|
||||
extern uint8_t si12t_point_type[3];
|
||||
|
||||
/**
|
||||
* @brief 初始化Si12T设备
|
||||
*
|
||||
* @param config 配置参数
|
||||
* @param handle 返回的设备句柄
|
||||
* @return esp_err_t ESP_OK成功,其他失败
|
||||
*/
|
||||
esp_err_t si12t_init(const si12t_config_t *config, si12t_handle_t *handle);
|
||||
|
||||
/**
|
||||
* @brief 初始化Si12T设备(使用灵敏度参数)
|
||||
*
|
||||
* @param handle 设备句柄
|
||||
* @param sens_type 灵敏度类型
|
||||
* @param sens_level 灵敏度等级
|
||||
* @return esp_err_t ESP_OK成功,其他失败
|
||||
*/
|
||||
esp_err_t si12t_setup(si12t_handle_t handle, si12t_type_t sens_type, si12t_sensitivity_level_t sens_level);
|
||||
|
||||
/**
|
||||
* @brief 删除Si12T设备
|
||||
*
|
||||
* @param handle 设备句柄
|
||||
* @return esp_err_t ESP_OK成功,其他失败
|
||||
*/
|
||||
esp_err_t si12t_delete(si12t_handle_t handle);
|
||||
|
||||
/**
|
||||
* @brief 使能所有通道
|
||||
*
|
||||
* @param handle 设备句柄
|
||||
* @return esp_err_t ESP_OK成功,其他失败
|
||||
*/
|
||||
esp_err_t si12t_enable_channel(si12t_handle_t handle);
|
||||
|
||||
/**
|
||||
* @brief 设置灵敏度
|
||||
*
|
||||
* @param handle 设备句柄
|
||||
* @param sens_type 灵敏度类型
|
||||
* @param sens_level 灵敏度等级
|
||||
* @return esp_err_t ESP_OK成功,其他失败
|
||||
*/
|
||||
esp_err_t si12t_set_sensitivity(si12t_handle_t handle, si12t_type_t sens_type, si12t_sensitivity_level_t sens_level);
|
||||
|
||||
/**
|
||||
* @brief 获取灵敏度
|
||||
*
|
||||
* @param handle 设备句柄
|
||||
* @return esp_err_t ESP_OK成功,其他失败
|
||||
*/
|
||||
esp_err_t si12t_get_sensitivity(si12t_handle_t handle);
|
||||
|
||||
/**
|
||||
* @brief 设置Ctrl1寄存器
|
||||
*
|
||||
* @param handle 设备句柄
|
||||
* @return esp_err_t ESP_OK成功,其他失败
|
||||
*/
|
||||
esp_err_t si12t_set_ctrl1(si12t_handle_t handle);
|
||||
|
||||
/**
|
||||
* @brief 设置Ctrl2寄存器
|
||||
*
|
||||
* @param handle 设备句柄
|
||||
* @return esp_err_t ESP_OK成功,其他失败
|
||||
*/
|
||||
esp_err_t si12t_set_ctrl2(si12t_handle_t handle);
|
||||
|
||||
/**
|
||||
* @brief 使能睡眠模式
|
||||
*
|
||||
* @param handle 设备句柄
|
||||
* @return esp_err_t ESP_OK成功,其他失败
|
||||
*/
|
||||
esp_err_t si12t_sleep_enable(si12t_handle_t handle);
|
||||
|
||||
/**
|
||||
* @brief 禁用睡眠模式
|
||||
*
|
||||
* @param handle 设备句柄
|
||||
* @return esp_err_t ESP_OK成功,其他失败
|
||||
*/
|
||||
esp_err_t si12t_sleep_disable(si12t_handle_t handle);
|
||||
|
||||
/**
|
||||
* @brief 读取触摸结果
|
||||
*
|
||||
* @param handle 设备句柄
|
||||
* @param touch_result 触摸结果输出
|
||||
* @return esp_err_t ESP_OK成功,其他失败
|
||||
*/
|
||||
esp_err_t si12t_read_touch_result(si12t_handle_t handle, uint8_t *touch_result);
|
||||
|
||||
/**
|
||||
* @brief 解析触摸结果
|
||||
*
|
||||
* @param touch_result 触摸结果
|
||||
*/
|
||||
void si12t_parse_touch_result(uint8_t touch_result);
|
||||
|
||||
void si12t_parse_touch_result_to(uint8_t touch_result, uint8_t *parsed_result);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __SI12T_H__ */
|
||||
@@ -0,0 +1,30 @@
|
||||
Copyright (c) 2023 Bosch Sensortec GmbH. All rights reserved.
|
||||
|
||||
BSD-3-Clause
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
@@ -0,0 +1,172 @@
|
||||
# Sensor API for the BMI2's OIS interface
|
||||
|
||||
## Table of Contents
|
||||
- [Introduction](#Intro)
|
||||
- [Integration details](#Integration)
|
||||
- [Driver files information](#file)
|
||||
- [Sensor interfaces](#interface)
|
||||
- [Integration Examples](#examples)
|
||||
|
||||
### Introduction<a name=Intro></a>
|
||||
This package contains Bosch Sensortec's BMI2 Sensor API.
|
||||
|
||||
### Integration details<a name=Integration></a>
|
||||
- Integrate _bmi2.c_, _bmi2.h_, _bmi2_ois.c_, _bmi2_ois.h_, _bmi2_defs.h_ and the required variant files in your project.
|
||||
- User has to include _bmi2_ois.h_ in the code to call OIS related APIs and a _variant header_ for initialization as
|
||||
well as BMI2 related API calls, as shown below:
|
||||
``` c
|
||||
#include "bmi261.h"
|
||||
#include "bmi2_ois.h"
|
||||
````
|
||||
### Driver files information<a name=file></a>
|
||||
- *_bmi2_ois.c_*
|
||||
* This file has function definitions of OIS related API interfaces.
|
||||
- *_bmi2_ois.h_*
|
||||
* This header file has necessary include files, function declarations, required to make OIS related API calls.
|
||||
|
||||
### Sensor interfaces<a name=interface></a>
|
||||
#### _Host Interface_
|
||||
- I2C interface
|
||||
- SPI interface
|
||||
_Note: By default, the interface is I2C._
|
||||
|
||||
#### _OIS Interface_
|
||||
- SPI interface
|
||||
|
||||
### Integration examples<a name=examples></a>
|
||||
#### Configuring SPI/I2C for host interface.
|
||||
To configure host interface, an instance of the bmi2_dev structure should be
|
||||
created for initializing BMI2 sensor. "_Refer **README** for initializing BMI2
|
||||
sensor._"
|
||||
|
||||
#### Configuring SPI for OIS interface.
|
||||
To configure OIS interface, an instance of the bmi2_ois_dev structure should be
|
||||
created. The following parameters are required to be updated in the structure,
|
||||
by the user.
|
||||
|
||||
Parameters | Details
|
||||
--------------|-----------------------------------
|
||||
_intf_ptr_ | device address reference of SPI interface
|
||||
_ois_read_ | read through SPI interface
|
||||
_ois_write_ | read through SPI interface
|
||||
_ois_delay_us_| delay in micro seconds
|
||||
_acc_en_ | for enabling accelerometer
|
||||
_gyr_en_ | for enabling gyroscope
|
||||
|
||||
``` c
|
||||
int8_t rslt = 0;
|
||||
|
||||
struct bmi2_ois_dev ois_dev = {
|
||||
.intf_ptr = intf_ptr will contain the chip selection info of SPI CS pin,
|
||||
.ois_read = user_spi_reg_read,
|
||||
.ois_write = user_spi_reg_write,
|
||||
.ois_delay_us = user_delay_us
|
||||
};
|
||||
```
|
||||
>**_Important Note_**: For initializing and configuring BMI2 sensors, which is
|
||||
done through host interface, the API's are to be used from bmi2.c file. Rest
|
||||
of the API's, for OIS configurations and the reading of OIS data, which is done
|
||||
through OIS interface, are to be used from bmi2_ois.c file.
|
||||
|
||||
##### Get accelerometer and gyroscope data through OIS interface
|
||||
``` c
|
||||
int8_t rslt;
|
||||
/* Array to enable sensor through host interface */
|
||||
uint8_t sens_list[2] = {BMI2_ACCEL, BMI2_GYRO};
|
||||
/* Array to enable sensor through OIS interface */
|
||||
uint8_t sens_sel[2] = {BMI2_OIS_ACCEL, BMI2_OIS_GYRO};
|
||||
/* Initialize the configuration structure */
|
||||
struct bmi2_sens_config sens_cfg = {0};
|
||||
|
||||
/* Initialize BMI2 */
|
||||
rslt = bmi2_init(&dev);
|
||||
if (rslt != BMI2_OK) {
|
||||
printf("Error: %d\n", rslt);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Enable accelerometer and gyroscope through host interface */
|
||||
rslt = bmi2_sensor_enable(sens_list, 2, &dev);
|
||||
if (rslt != BMI2_OK) {
|
||||
printf("Error: %d\n", rslt);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Setting of OIS Range is done through host interface */
|
||||
/* Select the gyroscope sensor for OIS Range configuration */
|
||||
sens_cfg.type = BMI2_GYRO;
|
||||
|
||||
/* Get gyroscope configuration */
|
||||
rslt = bmi2_get_sensor_config(&sens_cfg, 1, &dev);
|
||||
if (rslt != BMI2_OK) {
|
||||
printf("Error: %d\n", rslt);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set the desired OIS Range */
|
||||
sens_cfg.cfg.gyr.ois_range = BMI2_GYR_OIS_2000;
|
||||
|
||||
/* Set gyroscope configuration for default values */
|
||||
rslt = bmi2_set_sensor_config(&sens_cfg, 1, &dev);
|
||||
if (rslt != BMI2_OK) {
|
||||
printf("Error: %d\n", rslt);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Enable OIS through host interface */
|
||||
rslt = bmi2_set_ois_interface(BMI2_ENABLE, &dev);
|
||||
if (rslt != BMI2_OK) {
|
||||
printf("Error: %d\n", rslt);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Disable Advance Power Save Mode through host interface */
|
||||
rslt = bmi2_set_adv_power_save(BMI2_DISABLE, &dev);
|
||||
if (rslt != BMI2_OK) {
|
||||
printf("Error: %d\n", rslt);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get configurations for OIS through OIS interface for default values */
|
||||
rslt = bmi2_ois_get_config(&ois_dev);
|
||||
if (rslt != BMI2_OK) {
|
||||
printf("Error: %d\n", rslt);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Enable accelerometer and gyroscope for reading OIS data */
|
||||
ois_dev.acc_en = BMI2_ENABLE;
|
||||
ois_dev.gyr_en = BMI2_ENABLE;
|
||||
|
||||
/* Set configurations for OIS through OIS interface */
|
||||
rslt = bmi2_ois_set_config(&ois_dev);
|
||||
if (rslt == BMI2_OK) {
|
||||
/* Get OIS accelerometer and gyroscope data through OIS interface */
|
||||
rslt = bmi2_ois_read_data(sens_sel, 2, &ois_dev);
|
||||
if (rslt == BMI2_OK) {
|
||||
/* Print accelerometer data */
|
||||
printf("OIS Accel x-axis = %d\t", ois_dev.acc_data.x);
|
||||
printf("OIS Accel y-axis= %d\t", ois_dev.acc_data.y);
|
||||
printf("OIS Accel z-axis = %d\r\n", ois_dev.acc_data.z);
|
||||
|
||||
/* Print gyroscope data */
|
||||
printf("OIS Gyro x-axis = %d\t", ois_dev.gyr_data.x);
|
||||
printf("OIS Gyro y-axis= %d\t", ois_dev.gyr_data.y);
|
||||
printf("OIS Gyro z-axis = %d\r\n", ois_dev.gyr_data.z);
|
||||
}
|
||||
}
|
||||
|
||||
if (rslt != BMI2_OK) {
|
||||
printf("Error code: %d\n", rslt);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Enable Advance Power Save Mode through host interface */
|
||||
rslt = bmi2_set_adv_power_save(BMI2_ENABLE, &dev);
|
||||
if (rslt != BMI2_OK) {
|
||||
printf("Error: %d\n", rslt);
|
||||
return;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
BMI270 Sensor API
|
||||
|
||||
> This package contains the sensor APIs for the BMI270 sensor
|
||||
|
||||
## Sensor Overview
|
||||
The BMI270 is a small, low power, low noise inertial measurement unit designed for use in mobile applications like augmented reality or indoor navigation which require highly accurate, real-time sensor data.
|
||||
|
||||
## Applications
|
||||
|
||||
### BMI270 (base)
|
||||
|
||||
- Any motion, No motion, Significant motion detectors
|
||||
- Wrist worn Step counter and Step detector (Pedometer)
|
||||
- Activity change recognition
|
||||
- Still
|
||||
- Walking
|
||||
- Running
|
||||
- Wrist gestures
|
||||
- Push arm down
|
||||
- Pivot up
|
||||
- Wrist shake jiggle
|
||||
- Flick in
|
||||
- Flick out
|
||||
- Wrist wear wake up
|
||||
|
||||
### BMI270 Context
|
||||
|
||||
- Step counter and Step detector (Pedometer)
|
||||
- Activity change recognition
|
||||
- Still
|
||||
- Walking
|
||||
- Running
|
||||
|
||||
### BMI270 Legacy
|
||||
|
||||
- Any motion, No motion, Significant motion detector
|
||||
- Orientation detector (Advanced Potrait-Landscape)
|
||||
- High-G, Low-G (Freefall) detector
|
||||
- Flat detector
|
||||
- Tap detection (Single, Double, Triple taps)
|
||||
- Smartphone Step counter and Step detector (Pedometer)
|
||||
- Activity change recognition
|
||||
- Still
|
||||
- Walking
|
||||
- Running
|
||||
|
||||
### BMI270 Maximum FIFO
|
||||
|
||||
- Supports a 6kB FIFO
|
||||
|
||||
For more information refer product page [Link](https://www.bosch-sensortec.com/products/motion-sensors/imus/bmi270.html)
|
||||
|
||||
---
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,420 @@
|
||||
/**
|
||||
* Copyright (c) 2023 Bosch Sensortec GmbH. All rights reserved.
|
||||
*
|
||||
* BSD-3-Clause
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* @file bmi270.h
|
||||
* @date 2023-05-03
|
||||
* @version v2.86.1
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* \ingroup bmi2xy
|
||||
* \defgroup bmi270 BMI270
|
||||
* @brief Sensor driver for BMI270 sensor
|
||||
*/
|
||||
|
||||
#ifndef BMI270_H_
|
||||
#define BMI270_H_
|
||||
|
||||
/*! CPP guard */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
/*! Header files
|
||||
****************************************************************************/
|
||||
#include "bmi2.h"
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
/*! Macro definitions
|
||||
****************************************************************************/
|
||||
|
||||
/*! @name BMI270 Chip identifier */
|
||||
#define BMI270_CHIP_ID UINT8_C(0x24)
|
||||
|
||||
/*! @name BMI270 feature input start addresses */
|
||||
#define BMI270_CONFIG_ID_STRT_ADDR UINT8_C(0x00)
|
||||
#define BMI270_MAX_BURST_LEN_STRT_ADDR UINT8_C(0x02)
|
||||
#define BMI270_CRT_GYRO_SELF_TEST_STRT_ADDR UINT8_C(0x03)
|
||||
#define BMI270_ABORT_STRT_ADDR UINT8_C(0x03)
|
||||
#define BMI270_AXIS_MAP_STRT_ADDR UINT8_C(0x04)
|
||||
#define BMI270_GYRO_SELF_OFF_STRT_ADDR UINT8_C(0x05)
|
||||
#define BMI270_NVM_PROG_PREP_STRT_ADDR UINT8_C(0x05)
|
||||
#define BMI270_GYRO_GAIN_UPDATE_STRT_ADDR UINT8_C(0x06)
|
||||
#define BMI270_ANY_MOT_STRT_ADDR UINT8_C(0x0C)
|
||||
#define BMI270_NO_MOT_STRT_ADDR UINT8_C(0x00)
|
||||
#define BMI270_SIG_MOT_STRT_ADDR UINT8_C(0x04)
|
||||
#define BMI270_STEP_CNT_1_STRT_ADDR UINT8_C(0x00)
|
||||
#define BMI270_STEP_CNT_4_STRT_ADDR UINT8_C(0x02)
|
||||
#define BMI270_WRIST_GEST_STRT_ADDR UINT8_C(0x06)
|
||||
#define BMI270_WRIST_WEAR_WAKE_UP_STRT_ADDR UINT8_C(0x00)
|
||||
|
||||
/*! @name BMI270 feature output start addresses */
|
||||
#define BMI270_STEP_CNT_OUT_STRT_ADDR UINT8_C(0x00)
|
||||
#define BMI270_STEP_ACT_OUT_STRT_ADDR UINT8_C(0x04)
|
||||
#define BMI270_WRIST_GEST_OUT_STRT_ADDR UINT8_C(0x06)
|
||||
#define BMI270_GYR_USER_GAIN_OUT_STRT_ADDR UINT8_C(0x08)
|
||||
#define BMI270_GYRO_CROSS_SENSE_STRT_ADDR UINT8_C(0x0C)
|
||||
#define BMI270_NVM_VFRM_OUT_STRT_ADDR UINT8_C(0x0E)
|
||||
|
||||
/*! @name Defines maximum number of pages */
|
||||
#define BMI270_MAX_PAGE_NUM UINT8_C(8)
|
||||
|
||||
/*! @name Defines maximum number of feature input configurations */
|
||||
#define BMI270_MAX_FEAT_IN UINT8_C(17)
|
||||
|
||||
/*! @name Defines maximum number of feature outputs */
|
||||
#define BMI270_MAX_FEAT_OUT UINT8_C(7)
|
||||
|
||||
/*! @name Mask definitions for feature interrupt status bits */
|
||||
#define BMI270_SIG_MOT_STATUS_MASK UINT8_C(0x01)
|
||||
#define BMI270_STEP_CNT_STATUS_MASK UINT8_C(0x02)
|
||||
#define BMI270_STEP_ACT_STATUS_MASK UINT8_C(0x04)
|
||||
#define BMI270_WRIST_WAKE_UP_STATUS_MASK UINT8_C(0x08)
|
||||
#define BMI270_WRIST_GEST_STATUS_MASK UINT8_C(0x10)
|
||||
#define BMI270_NO_MOT_STATUS_MASK UINT8_C(0x20)
|
||||
#define BMI270_ANY_MOT_STATUS_MASK UINT8_C(0x40)
|
||||
|
||||
/*! @name Mask definitions for feature interrupt mapping bits */
|
||||
#define BMI270_INT_SIG_MOT_MASK UINT8_C(0x01)
|
||||
#define BMI270_INT_STEP_COUNTER_MASK UINT8_C(0x02)
|
||||
#define BMI270_INT_STEP_DETECTOR_MASK UINT8_C(0x02)
|
||||
#define BMI270_INT_STEP_ACT_MASK UINT8_C(0x04)
|
||||
#define BMI270_INT_WRIST_WEAR_WAKEUP_MASK UINT8_C(0x08)
|
||||
#define BMI270_INT_WRIST_GEST_MASK UINT8_C(0x10)
|
||||
#define BMI270_INT_NO_MOT_MASK UINT8_C(0x20)
|
||||
#define BMI270_INT_ANY_MOT_MASK UINT8_C(0x40)
|
||||
|
||||
/*! @name Defines maximum number of feature interrupts */
|
||||
#define BMI270_MAX_INT_MAP UINT8_C(8)
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
/*! BMI270 User Interface function prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* \ingroup bmi270
|
||||
* \defgroup bmi270ApiInit Initialization
|
||||
* @brief Initialize the sensor and device structure
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \ingroup bmi270ApiInit
|
||||
* \page bmi270_api_bmi270_init bmi270_init
|
||||
* \code
|
||||
* int8_t bmi270_init(struct bmi2_dev *dev);
|
||||
* \endcode
|
||||
* @details This API:
|
||||
* 1) updates the device structure with address of the configuration file.
|
||||
* 2) Initializes BMI270 sensor.
|
||||
* 3) Writes the configuration file.
|
||||
* 4) Updates the feature offset parameters in the device structure.
|
||||
* 5) Updates the maximum number of pages, in the device structure.
|
||||
*
|
||||
* @param[in, out] dev : Structure instance of bmi2_dev.
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval 0 -> Success
|
||||
* @retval < 0 -> Fail
|
||||
*/
|
||||
int8_t bmi270_init(struct bmi2_dev *dev);
|
||||
|
||||
/**
|
||||
* \ingroup bmi270
|
||||
* \defgroup bmi270ApiSensor Feature Set
|
||||
* @brief Enable / Disable features of the sensor
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \ingroup bmi270ApiSensor
|
||||
* \page bmi270_api_bmi270_sensor_enable bmi270_sensor_enable
|
||||
* \code
|
||||
* int8_t bmi270_sensor_enable(const uint8_t *sens_list, uint8_t n_sens, struct bmi2_dev *dev);
|
||||
* \endcode
|
||||
* @details This API selects the sensors/features to be enabled.
|
||||
*
|
||||
* @param[in] sens_list : Pointer to select the sensor/feature.
|
||||
* @param[in] n_sens : Number of sensors selected.
|
||||
* @param[in, out] dev : Structure instance of bmi2_dev.
|
||||
*
|
||||
* @note Sensors/features that can be enabled.
|
||||
*
|
||||
*@verbatim
|
||||
* sens_list | Values
|
||||
* ----------------------------|-----------
|
||||
* BMI2_ACCEL | 0
|
||||
* BMI2_GYRO | 1
|
||||
* BMI2_AUX | 2
|
||||
* BMI2_SIG_MOTION | 3
|
||||
* BMI2_ANY_MOTION | 4
|
||||
* BMI2_NO_MOTION | 5
|
||||
* BMI2_STEP_DETECTOR | 6
|
||||
* BMI2_STEP_COUNTER | 7
|
||||
* BMI2_STEP_ACTIVITY | 8
|
||||
* BMI2_GYRO_GAIN_UPDATE | 9
|
||||
* BMI2_WRIST_GESTURE | 19
|
||||
* BMI2_WRIST_WEAR_WAKE_UP | 20
|
||||
* BMI2_GYRO_SELF_OFF | 33
|
||||
*@endverbatim
|
||||
*
|
||||
* @note :
|
||||
* example uint8_t sens_list[2] = {BMI2_ACCEL, BMI2_GYRO};
|
||||
* uint8_t n_sens = 2;
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval 0 -> Success
|
||||
* @retval < 0 -> Fail
|
||||
*/
|
||||
int8_t bmi270_sensor_enable(const uint8_t *sens_list, uint8_t n_sens, struct bmi2_dev *dev);
|
||||
|
||||
/*!
|
||||
* \ingroup bmi270ApiSensor
|
||||
* \page bmi270_api_bmi270_sensor_disable bmi270_sensor_disable
|
||||
* \code
|
||||
* int8_t bmi270_sensor_disable(const uint8_t *sens_list, uint8_t n_sens, struct bmi2_dev *dev);
|
||||
* \endcode
|
||||
* @details This API selects the sensors/features to be disabled.
|
||||
*
|
||||
* @param[in] sens_list : Pointer to select the sensor/feature.
|
||||
* @param[in] n_sens : Number of sensors selected.
|
||||
* @param[in, out] dev : Structure instance of bmi2_dev.
|
||||
*
|
||||
* @note Sensors/features that can be disabled.
|
||||
*
|
||||
*@verbatim
|
||||
* sens_list | Values
|
||||
* ----------------------------|-----------
|
||||
* BMI2_ACCEL | 0
|
||||
* BMI2_GYRO | 1
|
||||
* BMI2_AUX | 2
|
||||
* BMI2_SIG_MOTION | 3
|
||||
* BMI2_ANY_MOTION | 4
|
||||
* BMI2_NO_MOTION | 5
|
||||
* BMI2_STEP_DETECTOR | 6
|
||||
* BMI2_STEP_COUNTER | 7
|
||||
* BMI2_STEP_ACTIVITY | 8
|
||||
* BMI2_GYRO_GAIN_UPDATE | 9
|
||||
* BMI2_WRIST_GESTURE | 19
|
||||
* BMI2_WRIST_WEAR_WAKE_UP | 20
|
||||
* BMI2_GYRO_SELF_OFF | 33
|
||||
*@endverbatim
|
||||
*
|
||||
* @note :
|
||||
* example uint8_t sens_list[2] = {BMI2_ACCEL, BMI2_GYRO};
|
||||
* uint8_t n_sens = 2;
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval 0 -> Success
|
||||
* @retval < 0 -> Fail
|
||||
*/
|
||||
int8_t bmi270_sensor_disable(const uint8_t *sens_list, uint8_t n_sens, struct bmi2_dev *dev);
|
||||
|
||||
/**
|
||||
* \ingroup bmi270
|
||||
* \defgroup bmi270ApiSensorC Sensor Configuration
|
||||
* @brief Enable / Disable feature configuration of the sensor
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \ingroup bmi270ApiSensorC
|
||||
* \page bmi270_api_bmi270_set_sensor_config bmi270_set_sensor_config
|
||||
* \code
|
||||
* int8_t bmi270_set_sensor_config(struct bmi2_sens_config *sens_cfg, uint8_t n_sens, struct bmi2_dev *dev);
|
||||
* \endcode
|
||||
* @details This API sets the sensor/feature configuration.
|
||||
*
|
||||
* @param[in] sens_cfg : Structure instance of bmi2_sens_config.
|
||||
* @param[in] n_sens : Number of sensors selected.
|
||||
* @param[in, out] dev : Structure instance of bmi2_dev.
|
||||
*
|
||||
* @note Sensors/features that can be configured
|
||||
*
|
||||
*@verbatim
|
||||
* sens_list | Values
|
||||
* ----------------------------|-----------
|
||||
* BMI2_SIG_MOTION | 3
|
||||
* BMI2_ANY_MOTION | 4
|
||||
* BMI2_NO_MOTION | 5
|
||||
* BMI2_STEP_DETECTOR | 6
|
||||
* BMI2_STEP_COUNTER | 7
|
||||
* BMI2_STEP_ACTIVITY | 8
|
||||
* BMI2_WRIST_GESTURE | 19
|
||||
* BMI2_WRIST_WEAR_WAKE_UP | 20
|
||||
* BMI2_STEP_COUNTER_PARAMS | 28
|
||||
*@endverbatim
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval 0 -> Success
|
||||
* @retval < 0 -> Fail
|
||||
*/
|
||||
int8_t bmi270_set_sensor_config(struct bmi2_sens_config *sens_cfg, uint8_t n_sens, struct bmi2_dev *dev);
|
||||
|
||||
/*!
|
||||
* \ingroup bmi270ApiSensorC
|
||||
* \page bmi270_api_bmi270_get_sensor_config bmi270_get_sensor_config
|
||||
* \code
|
||||
* int8_t bmi270_get_sensor_config(struct bmi2_sens_config *sens_cfg, uint8_t n_sens, struct bmi2_dev *dev);
|
||||
* \endcode
|
||||
* @details This API gets the sensor/feature configuration.
|
||||
*
|
||||
* @param[in] sens_cfg : Structure instance of bmi2_sens_config.
|
||||
* @param[in] n_sens : Number of sensors selected.
|
||||
* @param[in, out] dev : Structure instance of bmi2_dev.
|
||||
*
|
||||
* @note Sensors/features whose configurations can be read.
|
||||
*
|
||||
*@verbatim
|
||||
* sens_list | Values
|
||||
* ----------------------------|-----------
|
||||
* BMI2_SIG_MOTION | 3
|
||||
* BMI2_ANY_MOTION | 4
|
||||
* BMI2_NO_MOTION | 5
|
||||
* BMI2_STEP_DETECTOR | 6
|
||||
* BMI2_STEP_COUNTER | 7
|
||||
* BMI2_STEP_ACTIVITY | 8
|
||||
* BMI2_WRIST_GESTURE | 19
|
||||
* BMI2_WRIST_WEAR_WAKE_UP | 20
|
||||
* BMI2_STEP_COUNTER_PARAMS | 28
|
||||
*@endverbatim
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval 0 -> Success
|
||||
* @retval < 0 -> Fail
|
||||
*/
|
||||
int8_t bmi270_get_sensor_config(struct bmi2_sens_config *sens_cfg, uint8_t n_sens, struct bmi2_dev *dev);
|
||||
|
||||
/**
|
||||
* \ingroup bmi270
|
||||
* \defgroup bmi270ApiSensorD Feature Sensor Data
|
||||
* @brief Get feature sensor data
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \ingroup bmi270ApiSensorD
|
||||
* \page bmi270_api_bmi270_get_feature_data bmi270_get_feature_data
|
||||
* \code
|
||||
* int8_t bmi270_get_feature_data(struct bmi2_feat_sensor_data *feature_data, uint8_t n_sens, struct bmi2_dev *dev);
|
||||
* \endcode
|
||||
* @details This API gets the feature data.
|
||||
*
|
||||
* @param[out] feature_data : Structure instance of bmi2_feat_sensor_data.
|
||||
* @param[in] n_sens : Number of sensors selected.
|
||||
* @param[in] dev : Structure instance of bmi2_dev.
|
||||
*
|
||||
* @note Sensors/features whose data can be read
|
||||
*
|
||||
*@verbatim
|
||||
* sens_list | Values
|
||||
* ----------------------------|-----------
|
||||
* BMI2_STEP_COUNTER | 7
|
||||
* BMI2_STEP_ACTIVITY | 8
|
||||
* BMI2_WRIST_GESTURE | 19
|
||||
* BMI2_NVM_STATUS | 38
|
||||
* BMI2_VFRM_STATUS | 39
|
||||
*@endverbatim
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval 0 -> Success
|
||||
* @retval < 0 -> Fail
|
||||
*/
|
||||
int8_t bmi270_get_feature_data(struct bmi2_feat_sensor_data *feature_data, uint8_t n_sens, struct bmi2_dev *dev);
|
||||
|
||||
/**
|
||||
* \ingroup bmi270
|
||||
* \defgroup bmi270ApiGyroUG Gyro User Gain
|
||||
* @brief Set / Get Gyro User Gain of the sensor
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \ingroup bmi270ApiGyroUG
|
||||
* \page bmi270_api_bmi270_update_gyro_user_gain bmi270_update_gyro_user_gain
|
||||
* \code
|
||||
* int8_t bmi270_update_gyro_user_gain(const struct bmi2_gyro_user_gain_config *user_gain, struct bmi2_dev *dev);
|
||||
* \endcode
|
||||
* @details This API updates the gyroscope user-gain.
|
||||
*
|
||||
* @param[in] user_gain : Structure that stores user-gain configurations.
|
||||
* @param[in] dev : Structure instance of bmi2_dev.
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval 0 -> Success
|
||||
* @retval < 0 -> Fail
|
||||
*/
|
||||
int8_t bmi270_update_gyro_user_gain(const struct bmi2_gyro_user_gain_config *user_gain, struct bmi2_dev *dev);
|
||||
|
||||
/*!
|
||||
* \ingroup bmi270ApiGyroUG
|
||||
* \page bmi270_api_bmi270_read_gyro_user_gain bmi270_read_gyro_user_gain
|
||||
* \code
|
||||
* int8_t bmi270_read_gyro_user_gain(struct bmi2_gyro_user_gain_data *gyr_usr_gain, const struct bmi2_dev *dev);
|
||||
* \endcode
|
||||
* @details This API reads the compensated gyroscope user-gain values.
|
||||
*
|
||||
* @param[out] gyr_usr_gain : Structure that stores gain values.
|
||||
* @param[in] dev : Structure instance of bmi2_dev.
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval 0 -> Success
|
||||
* @retval < 0 -> Fail
|
||||
*/
|
||||
int8_t bmi270_read_gyro_user_gain(struct bmi2_gyro_user_gain_data *gyr_usr_gain, struct bmi2_dev *dev);
|
||||
|
||||
/*!
|
||||
* \ingroup bmi270ApiInt
|
||||
* \page bmi270_api_bmi270_map_feat_int bmi270_map_feat_int
|
||||
* \code
|
||||
* int8_t bmi270_map_feat_int(const struct bmi2_sens_int_config *sens_int, uint8_t n_sens, struct bmi2_dev *dev)
|
||||
* \endcode
|
||||
* @details This API maps/unmaps feature interrupts to that of interrupt pins.
|
||||
*
|
||||
* @param[in] sens_int : Structure instance of bmi2_sens_int_config.
|
||||
* @param[in] n_sens : Number of interrupts to be mapped.
|
||||
* @param[in] dev : Structure instance of bmi2_dev.
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval 0 -> Success
|
||||
* @retval < 0 -> Fail
|
||||
*/
|
||||
int8_t bmi270_map_feat_int(const struct bmi2_sens_int_config *sens_int, uint8_t n_sens, struct bmi2_dev *dev);
|
||||
|
||||
/******************************************************************************/
|
||||
/*! @name C++ Guard Macros */
|
||||
/******************************************************************************/
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* End of CPP guard */
|
||||
|
||||
#endif /* BMI270_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,452 @@
|
||||
/**
|
||||
* Copyright (c) 2023 Bosch Sensortec GmbH. All rights reserved.
|
||||
*
|
||||
* BSD-3-Clause
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* @file bmi270_context.h
|
||||
* @date 2023-05-03
|
||||
* @version v2.86.1
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* \ingroup bmi2xy
|
||||
* \defgroup bmi270_context BMI270_CONTEXT
|
||||
* @brief Sensor driver for BMI270_CONTEXT sensor
|
||||
*/
|
||||
|
||||
#ifndef BMI270_CONTEXT_H_
|
||||
#define BMI270_CONTEXT_H_
|
||||
|
||||
/*! CPP guard */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
/*! Header files
|
||||
****************************************************************************/
|
||||
#include "bmi2.h"
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
/*! Macro definitions
|
||||
****************************************************************************/
|
||||
|
||||
/*! @name BMI270_CONTEXT Chip identifier */
|
||||
#define BMI270_CONTEXT_CHIP_ID UINT8_C(0x24)
|
||||
|
||||
/*! @name BMI270_CONTEXT feature input start addresses */
|
||||
#define BMI270_CONTEXT_CONFIG_ID_STRT_ADDR UINT8_C(0x06)
|
||||
#define BMI270_CONTEXT_STEP_CNT_1_STRT_ADDR UINT8_C(0x00)
|
||||
#define BMI270_CONTEXT_STEP_CNT_4_STRT_ADDR UINT8_C(0x02)
|
||||
#define BMI270_CONTEXT_MAX_BURST_LEN_STRT_ADDR UINT8_C(0x08)
|
||||
#define BMI270_CONTEXT_CRT_GYRO_SELF_TEST_STRT_ADDR UINT8_C(0x09)
|
||||
#define BMI270_CONTEXT_ABORT_STRT_ADDR UINT8_C(0x09)
|
||||
#define BMI270_CONTEXT_NVM_PROG_PREP_STRT_ADDR UINT8_C(0x0A)
|
||||
#define BMI270_CONTEXT_ACT_RGN_SETT_STRT_ADDR UINT8_C(0x00)
|
||||
#define BMI270_CONTEXT_ACT_RGN_STRT_ADDR UINT8_C(0x0A)
|
||||
|
||||
/*! @name BMI270_CONTEXT feature output start addresses */
|
||||
#define BMI270_CONTEXT_STEP_CNT_OUT_STRT_ADDR UINT8_C(0x00)
|
||||
#define BMI270_CONTEXT_GYR_USER_GAIN_OUT_STRT_ADDR UINT8_C(0x04)
|
||||
#define BMI270_CONTEXT_GYRO_CROSS_SENSE_STRT_ADDR UINT8_C(0x0C)
|
||||
#define BMI270_CONTEXT_NVM_VFRM_OUT_STRT_ADDR UINT8_C(0x0E)
|
||||
|
||||
/*! @name Defines maximum number of pages */
|
||||
#define BMI270_CONTEXT_MAX_PAGE_NUM UINT8_C(8)
|
||||
|
||||
/*! @name Defines maximum number of feature input configurations */
|
||||
#define BMI270_CONTEXT_MAX_FEAT_IN UINT8_C(10)
|
||||
|
||||
/*! @name Defines maximum number of feature outputs */
|
||||
#define BMI270_CONTEXT_MAX_FEAT_OUT UINT8_C(5)
|
||||
|
||||
/*! @name Mask definitions for feature interrupt status bits */
|
||||
#define BMI270_CONTEXT_STEP_CNT_STATUS_MASK UINT8_C(0x01)
|
||||
|
||||
/*! @name Mask definitions for feature interrupt mapping bits */
|
||||
#define BMI270_C_INT_STEP_COUNTER_MASK UINT8_C(0x01)
|
||||
#define BMI270_C_INT_STEP_DETECTOR_MASK UINT8_C(0x01)
|
||||
|
||||
/*! @name Defines maximum number of feature interrupts */
|
||||
#define BMI270_C_MAX_INT_MAP UINT8_C(2)
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
/*! BMI270_CONTEXT User Interface function prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* \ingroup bmi270_context
|
||||
* \defgroup bmi270_contextApiInit Initialization
|
||||
* @brief Initialize the sensor and device structure
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \ingroup bmi270_contextApiInit
|
||||
* \page bmi270_context_api_bmi270_context_init bmi270_context_init
|
||||
* \code
|
||||
* int8_t bmi270_context_init(struct bmi2_dev *dev);
|
||||
* \endcode
|
||||
* @details This API:
|
||||
* 1) updates the device structure with address of the configuration file.
|
||||
* 2) Initializes BMI270_CONTEXT sensor.
|
||||
* 3) Writes the configuration file.
|
||||
* 4) Updates the feature offset parameters in the device structure.
|
||||
* 5) Updates the maximum number of pages, in the device structure.
|
||||
*
|
||||
* @param[in, out] dev : Structure instance of bmi2_dev.
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval 0 -> Success
|
||||
* @retval < 0 -> Fail
|
||||
*/
|
||||
int8_t bmi270_context_init(struct bmi2_dev *dev);
|
||||
|
||||
/**
|
||||
* \ingroup bmi270_context
|
||||
* \defgroup bmi270_contextApiSensor Feature Set
|
||||
* @brief Enable / Disable features of the sensor
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \ingroup bmi270_contextApiSensor
|
||||
* \page bmi270_context_api_bmi270_context_sensor_enable bmi270_context_sensor_enable
|
||||
* \code
|
||||
* int8_t bmi270_context_sensor_enable(const uint8_t *sens_list, uint8_t n_sens, struct bmi2_dev *dev);
|
||||
* \endcode
|
||||
* @details This API selects the sensors/features to be enabled.
|
||||
*
|
||||
* @param[in] sens_list : Pointer to select the sensor/feature.
|
||||
* @param[in] n_sens : Number of sensors selected.
|
||||
* @param[in, out] dev : Structure instance of bmi2_dev.
|
||||
*
|
||||
* @note Sensors/features that can be enabled.
|
||||
*
|
||||
*@verbatim
|
||||
* sens_list | Values
|
||||
* ----------------------------|-----------
|
||||
* BMI2_ACCEL | 0
|
||||
* BMI2_GYRO | 1
|
||||
* BMI2_AUX | 2
|
||||
* BMI2_STEP_DETECTOR | 6
|
||||
* BMI2_STEP_COUNTER | 7
|
||||
* BMI2_GYRO_GAIN_UPDATE | 9
|
||||
* BMI2_ACTIVITY_RECOGNITION | 34
|
||||
*@endverbatim
|
||||
*
|
||||
* @note :
|
||||
* example uint8_t sens_list[2] = {BMI2_ACCEL, BMI2_GYRO};
|
||||
* uint8_t n_sens = 2;
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval 0 -> Success
|
||||
* @retval < 0 -> Fail
|
||||
*/
|
||||
int8_t bmi270_context_sensor_enable(const uint8_t *sens_list, uint8_t n_sens, struct bmi2_dev *dev);
|
||||
|
||||
/*!
|
||||
* \ingroup bmi270_contextApiSensor
|
||||
* \page bmi270_context_api_bmi270_context_sensor_disable bmi270_context_sensor_disable
|
||||
* \code
|
||||
* int8_t bmi270_context_sensor_disable(const uint8_t *sens_list, uint8_t n_sens, struct bmi2_dev *dev);
|
||||
* \endcode
|
||||
* @details This API selects the sensors/features to be disabled.
|
||||
*
|
||||
* @param[in] sens_list : Pointer to select the sensor/feature.
|
||||
* @param[in] n_sens : Number of sensors selected.
|
||||
* @param[in, out] dev : Structure instance of bmi2_dev.
|
||||
*
|
||||
* @note Sensors/features that can be disabled.
|
||||
*
|
||||
*@verbatim
|
||||
* sens_list | Values
|
||||
* ----------------------------|-----------
|
||||
* BMI2_ACCEL | 0
|
||||
* BMI2_GYRO | 1
|
||||
* BMI2_AUX | 2
|
||||
* BMI2_STEP_DETECTOR | 6
|
||||
* BMI2_STEP_COUNTER | 7
|
||||
* BMI2_GYRO_GAIN_UPDATE | 9
|
||||
* BMI2_ACTIVITY_RECOGNITION | 34
|
||||
*@endverbatim
|
||||
*
|
||||
* @note :
|
||||
* example uint8_t sens_list[2] = {BMI2_ACCEL, BMI2_GYRO};
|
||||
* uint8_t n_sens = 2;
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval 0 -> Success
|
||||
* @retval < 0 -> Fail
|
||||
*/
|
||||
int8_t bmi270_context_sensor_disable(const uint8_t *sens_list, uint8_t n_sens, struct bmi2_dev *dev);
|
||||
|
||||
/**
|
||||
* \ingroup bmi270_context
|
||||
* \defgroup bmi270_contextApiSensorC Sensor Configuration
|
||||
* @brief Enable / Disable feature configuration of the sensor
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \ingroup bmi270_contextApiSensorC
|
||||
* \page bmi270_context_api_bmi270_context_set_sensor_config bmi270_context_set_sensor_config
|
||||
* \code
|
||||
* int8_t bmi270_context_set_sensor_config(struct bmi2_sens_config *sens_cfg, uint8_t n_sens, struct bmi2_dev *dev);
|
||||
* \endcode
|
||||
* @details This API sets the sensor/feature configuration.
|
||||
*
|
||||
* @param[in] sens_cfg : Structure instance of bmi2_sens_config.
|
||||
* @param[in] n_sens : Number of sensors selected.
|
||||
* @param[in, out] dev : Structure instance of bmi2_dev.
|
||||
*
|
||||
* @note Sensors/features that can be configured
|
||||
*
|
||||
*@verbatim
|
||||
* sens_list | Values
|
||||
* ----------------------------|-----------
|
||||
* BMI2_STEP_DETECTOR | 6
|
||||
* BMI2_STEP_COUNTER | 7
|
||||
* BMI2_STEP_COUNTER_PARAMS | 28
|
||||
*@endverbatim
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval 0 -> Success
|
||||
* @retval < 0 -> Fail
|
||||
*/
|
||||
int8_t bmi270_context_set_sensor_config(struct bmi2_sens_config *sens_cfg, uint8_t n_sens, struct bmi2_dev *dev);
|
||||
|
||||
/*!
|
||||
* \ingroup bmi270_contextApiSensorC
|
||||
* \page bmi270_context_api_bmi270_context_get_sensor_config bmi270_context_get_sensor_config
|
||||
* \code
|
||||
* int8_t bmi270_context_get_sensor_config(struct bmi2_sens_config *sens_cfg, uint8_t n_sens, struct bmi2_dev *dev);
|
||||
* \endcode
|
||||
* @details This API gets the sensor/feature configuration.
|
||||
*
|
||||
* @param[in] sens_cfg : Structure instance of bmi2_sens_config.
|
||||
* @param[in] n_sens : Number of sensors selected.
|
||||
* @param[in, out] dev : Structure instance of bmi2_dev.
|
||||
*
|
||||
* @note Sensors/features whose configurations can be read.
|
||||
*
|
||||
*@verbatim
|
||||
* sens_list | Values
|
||||
* ----------------------------|-----------
|
||||
* BMI2_STEP_DETECTOR | 6
|
||||
* BMI2_STEP_COUNTER | 7
|
||||
* BMI2_STEP_COUNTER_PARAMS | 28
|
||||
*@endverbatim
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval 0 -> Success
|
||||
* @retval < 0 -> Fail
|
||||
*/
|
||||
int8_t bmi270_context_get_sensor_config(struct bmi2_sens_config *sens_cfg, uint8_t n_sens, struct bmi2_dev *dev);
|
||||
|
||||
/**
|
||||
* \ingroup bmi270_context
|
||||
* \defgroup bmi270_contextApiSensorD Feature Sensor Data
|
||||
* @brief Get feature sensor data
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \ingroup bmi270_contextApiSensorD
|
||||
* \page bmi270_context_api_bmi270_context_get_feature_data bmi270_context_get_feature_data
|
||||
* \code
|
||||
* int8_t bmi270_context_get_feature_data(struct bmi2_feat_sensor_data *feature_data, uint8_t n_sens, struct bmi2_dev *dev);
|
||||
* \endcode
|
||||
* @details This API gets the feature data.
|
||||
*
|
||||
* @param[out] feature_data : Structure instance of bmi2_feat_sensor_data.
|
||||
* @param[in] n_sens : Number of sensors selected.
|
||||
* @param[in] dev : Structure instance of bmi2_dev.
|
||||
*
|
||||
* @note Sensors/features whose data can be read
|
||||
*
|
||||
*@verbatim
|
||||
* sens_list | Values
|
||||
* ---------------------|-----------
|
||||
* BMI2_STEP_COUNTER | 7
|
||||
* BMI2_NVM_STATUS | 38
|
||||
* BMI2_VFRM_STATUS | 39
|
||||
*@endverbatim
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval 0 -> Success
|
||||
* @retval < 0 -> Fail
|
||||
*/
|
||||
int8_t bmi270_context_get_feature_data(struct bmi2_feat_sensor_data *feature_data, uint8_t n_sens,
|
||||
struct bmi2_dev *dev);
|
||||
|
||||
/**
|
||||
* \ingroup bmi270_context
|
||||
* \defgroup bmi270_contextApiARecog Activity recognition settings
|
||||
* @brief Set / Get activity recognition settings of the sensor
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \ingroup bmi270_contextApiARecog
|
||||
* \page bmi270_context_api_bmi270_context_get_act_recg_sett bmi270_context_get_act_recg_sett
|
||||
* \code
|
||||
* int8_t bmi270_context_get_act_recg_sett(struct bmi2_act_recg_sett *sett, struct bmi2_dev *dev);
|
||||
* \endcode
|
||||
* @details This api is used for retrieving the following activity recognition settings currently set.
|
||||
* enable/disable post processing(0/1) by default -> 1(enable),
|
||||
* Setting the min & max Gini's diversity index (GDI) threshold. min_GDI_tres(0-0XFFFF) by default ->(0x06e1)
|
||||
* max_GDI_tres(0-0xFFFF) by default ->(0x0A66)
|
||||
* buffer size for post processing. range (1-0x0A) default -> (0x0A)
|
||||
* min segment confidence. range (1-0x0A) default -> (0x0A)
|
||||
*
|
||||
* @param[in] sett : Structure instance of bmi2_act_recg_sett.
|
||||
* @param[in] dev : Structure instance of bmi2_dev.
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval 0 -> Success
|
||||
* @retval < 0 -> Fail
|
||||
*/
|
||||
int8_t bmi270_context_get_act_recg_sett(struct bmi2_act_recg_sett *sett, struct bmi2_dev *dev);
|
||||
|
||||
/*!
|
||||
* \ingroup bmi270_contextApiARecog
|
||||
* \page bmi270_context_api_bmi270_context_set_act_recg_sett bmi270_context_set_act_recg_sett
|
||||
* \code
|
||||
* int8_t bmi270_context_set_act_recg_sett(const struct bmi2_act_recg_sett *sett, struct bmi2_dev *dev);
|
||||
* \endcode
|
||||
* @details This api is used for setting the following activity recognition settings
|
||||
* enable/disable post processing(0/1) by default -> 1(enable),
|
||||
* Setting the min & max Gini's diversity index (GDI) threshold. min_GDI_tres(0-0XFFFF) by default ->(0x06e1)
|
||||
* max_GDI_tres(0-0xFFFF) by default ->(0x0A66)
|
||||
* buffer size for post processing. range (1-0x0A) default -> (0x0A)
|
||||
* min segment confidence. range (1-0x0A) default -> (0x0A)
|
||||
*
|
||||
* @param[in] sett : Structure instance of bmi2_act_recg_sett.
|
||||
* @param[in] dev : Structure instance of bmi2_dev.
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval 0 -> Success
|
||||
* @retval < 0 -> Fail
|
||||
*/
|
||||
int8_t bmi270_context_set_act_recg_sett(const struct bmi2_act_recg_sett *sett, struct bmi2_dev *dev);
|
||||
|
||||
/**
|
||||
* \ingroup bmi270_contex
|
||||
* \defgroup bmi270_contextApiactOut Activity Output
|
||||
* @brief Activity output operations of the sensor
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \ingroup bmi270_contextApiactOut
|
||||
* \page bmi270_context_api_bmi270_context_get_act_recog_output bmi270_context_get_act_recog_output
|
||||
* \code
|
||||
* int8_t bmi270_context_get_act_recog_output(struct bmi2_act_recog_output *act_recog,
|
||||
* uint16_t *act_frm_len,
|
||||
* struct bmi2_fifo_frame *fifo,
|
||||
* const struct bmi2_dev *dev);
|
||||
*
|
||||
* \endcode
|
||||
* @details This internal API is used to parse the activity output from the
|
||||
* FIFO in header mode.
|
||||
*
|
||||
* @param[out] act_recog : Pointer to buffer where the parsed activity data
|
||||
* bytes are stored.
|
||||
* @param[in] act_frm_len : Number of activity frames parsed.
|
||||
* @param[in] fifo : Structure instance of bmi2_fifo_frame.
|
||||
* @param[in] dev : Structure instance of bmi2_dev.
|
||||
*
|
||||
* @verbatim
|
||||
* ----------------------------------------------------------------------------
|
||||
* bmi2_act_rec_output |
|
||||
* Structure parameters | Description
|
||||
*--------------------------|--------------------------------------------------
|
||||
* time_stamp | time-stamp (expressed in 50Hz ticks)
|
||||
* -------------------------|---------------------------------------------------
|
||||
* type | Type of activity
|
||||
* -------------------------|---------------------------------------------------
|
||||
* stat | Activity status
|
||||
* -------------------------|---------------------------------------------------
|
||||
* @endverbatim
|
||||
*
|
||||
*@verbatim
|
||||
* type | Activities
|
||||
*----------|---------------------
|
||||
* 0 | UNKNOWN
|
||||
* 1 | STILL
|
||||
* 2 | WALK
|
||||
* 3 | RUN
|
||||
* 4 | BIKE
|
||||
* 5 | VEHICLE
|
||||
* 6 | TILTED
|
||||
*@endverbatim
|
||||
*
|
||||
*
|
||||
*@verbatim
|
||||
* stat | Activity status
|
||||
*----------|---------------------
|
||||
* 1 | START
|
||||
* 2 | END
|
||||
*@endverbatim
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval 0 -> Success
|
||||
* @retval < 0 -> Fail
|
||||
*/
|
||||
int8_t bmi270_context_get_act_recog_output(struct bmi2_act_recog_output *act_recog,
|
||||
uint16_t *act_frm_len,
|
||||
struct bmi2_fifo_frame *fifo,
|
||||
const struct bmi2_dev *dev);
|
||||
|
||||
/*!
|
||||
* \ingroup bmi270_contextApiInt
|
||||
* \page bmi270_context_api_bmi270_context_map_feat_int bmi270_context_map_feat_int
|
||||
* \code
|
||||
* int8_t bmi270_context_map_feat_int(const struct bmi2_sens_int_config *sens_int, uint8_t n_sens, struct bmi2_dev *dev)
|
||||
* \endcode
|
||||
* @details This API maps/unmaps feature interrupts to that of interrupt pins.
|
||||
*
|
||||
* @param[in] sens_int : Structure instance of bmi2_sens_int_config.
|
||||
* @param[in] n_sens : Number of interrupts to be mapped.
|
||||
* @param[in] dev : Structure instance of bmi2_dev.
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval 0 -> Success
|
||||
* @retval < 0 -> Fail
|
||||
*/
|
||||
int8_t bmi270_context_map_feat_int(const struct bmi2_sens_int_config *sens_int, uint8_t n_sens, struct bmi2_dev *dev);
|
||||
|
||||
/******************************************************************************/
|
||||
/*! @name C++ Guard Macros */
|
||||
/******************************************************************************/
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* End of CPP guard */
|
||||
|
||||
#endif /* BMI270_CONTEXT_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,411 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Bosch Sensortec GmbH. All rights reserved.
|
||||
*
|
||||
* BSD-3-Clause
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* @file bmi270_dsd.h
|
||||
* @date 2025-04-22
|
||||
* @version v2.113.0
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* \ingroup bmi2xy
|
||||
* \defgroup bmi270_dsd BMI270_DSD
|
||||
* @brief Sensor driver for BMI270_DSD sensor
|
||||
*/
|
||||
|
||||
#ifndef BMI270_DSD_H_
|
||||
#define BMI270_DSD_H_
|
||||
|
||||
/*! CPP guard */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
/*! Header files
|
||||
****************************************************************************/
|
||||
#include "bmi2.h"
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
/*! Macro definitions
|
||||
****************************************************************************/
|
||||
|
||||
/*! @name BMI270_DSD chip identifier */
|
||||
#define BMI270_DSD_CHIP_ID UINT8_C(0x24)
|
||||
|
||||
/*! @name BMI270_DSD feature input start addresses */
|
||||
#define BMI270_DSD_CONFIG_ID_STRT_ADDR UINT8_C(0x00)
|
||||
#define BMI270_DSD_MAX_BURST_LEN_STRT_ADDR UINT8_C(0x02)
|
||||
#define BMI270_DSD_CRT_GYRO_SELF_TEST_STRT_ADDR UINT8_C(0x03)
|
||||
#define BMI270_DSD_ABORT_STRT_ADDR UINT8_C(0x03)
|
||||
#define BMI270_DSD_GYRO_SELF_OFF_STRT_ADDR UINT8_C(0x05)
|
||||
#define BMI270_DSD_NVM_PROG_PREP_STRT_ADDR UINT8_C(0x05)
|
||||
#define BMI270_DSD_GYRO_GAIN_UPDATE_STRT_ADDR UINT8_C(0x06)
|
||||
#define BMI270_DSD_DOOR_STATUS_DET_STRT_ADDR UINT8_C(0x00)
|
||||
#define BMI270_DSD_DOOR_STATUS_DET_2_STRT_ADDR UINT8_C(0x00)
|
||||
#define BMI270_DSD_ANY_MOT_STRT_ADDR UINT8_C(0x08)
|
||||
#define BMI270_DSD_NO_MOT_STRT_ADDR UINT8_C(0x04)
|
||||
|
||||
/*! @name BMI270_DSD feature output start addresses */
|
||||
#define BMI270_DSD_DOOR_EVENT_OUT_STRT_ADDR UINT8_C(0x06)
|
||||
#define BMI270_DSD_HEADING_OUT_STRT_ADDR UINT8_C(0x08)
|
||||
#define BMI270_DSD_GYR_USER_GAIN_OUT_STRT_ADDR UINT8_C(0x0A)
|
||||
#define BMI270_DSD_GYRO_CROSS_SENSE_STRT_ADDR UINT8_C(0x0C)
|
||||
#define BMI270_DSD_NVM_VFRM_OUT_STRT_ADDR UINT8_C(0x0E)
|
||||
|
||||
/*! @name Defines maximum number of pages */
|
||||
#define BMI270_DSD_MAX_PAGE_NUM UINT8_C(8)
|
||||
|
||||
/*! @name Defines maximum number of feature input configurations */
|
||||
#define BMI270_DSD_MAX_FEAT_IN UINT8_C(11)
|
||||
|
||||
/*! @name Defines maximum number of feature outputs */
|
||||
#define BMI270_DSD_MAX_FEAT_OUT UINT8_C(6)
|
||||
|
||||
/*! @name Mask definitions for feature interrupt mapping bits */
|
||||
#define BMI270_DSD_INT_DOOR_STATE_DETECTOR_MASK UINT8_C(0x08)
|
||||
#define BMI270_DSD_INT_NO_MOT_MASK UINT8_C(0x20)
|
||||
#define BMI270_DSD_INT_ANY_MOT_MASK UINT8_C(0x40)
|
||||
|
||||
/*! @name Defines maximum number of feature interrupts */
|
||||
#define BMI270_DSD_MAX_INT_MAP UINT8_C(3)
|
||||
|
||||
/*! @name BMI270 door state detector output type */
|
||||
#define BMI270_DSD_DOOR_EVENT_OUTPUT UINT8_C(1)
|
||||
#define BMI270_DSD_HEADING_OUTPUT UINT8_C(2)
|
||||
|
||||
/*! @name Mask definitions for BMI2 door state detector feature configuration */
|
||||
#define BMI270_DSD_ENABLE_MASK UINT8_C(0x01)
|
||||
#define BMI270_DSD_REMAP_FLAG_MASK UINT8_C(0x60) /* 0x 1100000 */
|
||||
#define BMI270_DSD_Z_SIGN_MASK UINT8_C(0x80) /* 0x10000000 */
|
||||
#define BMI270_DSD_Z_AXIS_MASK UINT16_C(0x300)
|
||||
#define BMI270_DSD_GYRO_CALIB_APPLY_MASK UINT16_C(0x400)
|
||||
#define BMI270_DSD_INIT_CALIB_THR_MASK UINT8_C(0xFF)
|
||||
#define BMI270_DSD_RESET_ENABLE_FLAG_MASK UINT16_C(0x100)
|
||||
#define BMI270_DSD_BIAS_X_LOW_WORD_MASK UINT16_C(0xFFFF)
|
||||
#define BMI270_DSD_BIAS_X_HIGH_WORD_MASK UINT16_C(0xFFFF)
|
||||
#define BMI270_DSD_BIAS_Y_LOW_WORD_MASK UINT16_C(0xFFFF)
|
||||
#define BMI270_DSD_BIAS_Y_HIGH_WORD_MASK UINT16_C(0xFFFF)
|
||||
#define BMI270_DSD_BIAS_Z_LOW_WORD_MASK UINT16_C(0xFFFF)
|
||||
#define BMI270_DSD_BIAS_Z_HIGH_WORD_MASK UINT16_C(0xFFFF)
|
||||
#define BMI270_DSD_DOOR_CLOSED_THR_MASK UINT16_C(0x3FF)
|
||||
#define BMI270_DSD_INT_MASK UINT8_C(0x08)
|
||||
|
||||
/*! @name Bit position definitions for BMI2 door state detector feature configuration */
|
||||
#define BMI270_DSD_REMAP_FLAG_POS UINT8_C(0x5) /* 0x 100000 */
|
||||
#define BMI270_DSD_Z_SIGN_POS UINT8_C(0x7) /* 0x10000000 */
|
||||
#define BMI270_DSD_Z_AXIS_POS UINT16_C(0x8)
|
||||
#define BMI270_DSD_GYRO_CALIB_APPLY_POS UINT16_C(0xA)
|
||||
#define BMI270_DSD_RESET_ENABLE_FLAG_POS UINT16_C(0x8)
|
||||
|
||||
/*! @name Defines GPIO0 output MASK */
|
||||
#define BMI270_DSD_DSD_OUT_MASK UINT8_C(0x03)
|
||||
#define BMI270_DSD_CALIB_FLAG_MASK UINT8_C(0x04)
|
||||
|
||||
/*! @name Defines GPIO0 output POS */
|
||||
#define BMI270_DSD_CALIB_FLAG_POS UINT8_C(0x02)
|
||||
|
||||
/*! @name Mask definitions for feature interrupt status bits */
|
||||
#define BMI270_DSD_STATUS_MASK UINT8_C(0x08)
|
||||
#define BMI270_DSD_NO_MOT_STATUS_MASK UINT8_C(0x20)
|
||||
#define BMI270_DSD_ANY_MOT_STATUS_MASK UINT8_C(0x40)
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
/*! BMI270_DSD User Interface function prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* \ingroup bmi270_dsd
|
||||
* \defgroup bmi270_dsdApiInit Initialization
|
||||
* @brief Initialize the sensor and device structure
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \ingroup bmi270_dsdApiInit
|
||||
* \page bmi270_dsd_api_bmi270_dsd_init bmi270_dsd_init
|
||||
* \code
|
||||
* int8_t bmi270_dsd_init(struct bmi2_dev *dev);
|
||||
* \endcode
|
||||
* @details This API:
|
||||
* 1) updates the device structure with address of the configuration file.
|
||||
* 2) Initializes BMI270_DSD sensor.
|
||||
* 3) Writes the configuration file.
|
||||
* 4) Updates the feature offset parameters in the device structure.
|
||||
* 5) Updates the maximum number of pages, in the device structure.
|
||||
*
|
||||
* @param[in, out] dev : Structure instance of bmi2_dev.
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval 0 -> Success
|
||||
* @retval < 0 -> Fail
|
||||
*/
|
||||
int8_t bmi270_dsd_init(struct bmi2_dev *dev);
|
||||
|
||||
/**
|
||||
* \ingroup bmi270_dsd
|
||||
* \defgroup bmi270_dsdApiSensor Feature Set
|
||||
* @brief Enable / Disable features of the sensor
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \ingroup bmi270_dsdApiSensor
|
||||
* \page bmi270_dsd_api_bmi270_dsd_sensor_enable bmi270_dsd_sensor_enable
|
||||
* \code
|
||||
* int8_t bmi270_dsd_sensor_enable(const uint8_t *sens_list, uint8_t n_sens, struct bmi2_dev *dev);
|
||||
* \endcode
|
||||
* @details This API selects the sensors/features to be enabled.
|
||||
*
|
||||
* @param[in] sens_list : Pointer to select the sensor/feature.
|
||||
* @param[in] n_sens : Number of sensors selected.
|
||||
* @param[in, out] dev : Structure instance of bmi2_dev.
|
||||
*
|
||||
* @note Sensors/features that can be enabled.
|
||||
*
|
||||
*@verbatim
|
||||
* sens_list | Values
|
||||
* ----------------------------|-----------
|
||||
* BMI2_ACCEL | 0
|
||||
* BMI2_GYRO | 1
|
||||
* BMI2_AUX | 2
|
||||
* BMI2_GYRO_GAIN_UPDATE | 9
|
||||
* BMI2_DOOR_STATE_DETECTOR | 57
|
||||
* BMI2_TEMP | 31
|
||||
*@endverbatim
|
||||
*
|
||||
* @note :
|
||||
* example uint8_t sens_list[2] = {BMI2_ACCEL, BMI2_GYRO};
|
||||
* uint8_t n_sens = 2;
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval 0 -> Success
|
||||
* @retval < 0 -> Fail
|
||||
*/
|
||||
int8_t bmi270_dsd_sensor_enable(const uint8_t *sens_list, uint8_t n_sens, struct bmi2_dev *dev);
|
||||
|
||||
/*!
|
||||
* \ingroup bmi270_dsdApiSensor
|
||||
* \page bmi270_dsd_api_bmi270_dsd_sensor_disable bmi270_dsd_sensor_disable
|
||||
* \code
|
||||
* int8_t bmi270_dsd_sensor_disable(const uint8_t *sens_list, uint8_t n_sens, struct bmi2_dev *dev);
|
||||
* \endcode
|
||||
* @details This API selects the sensors/features to be disabled.
|
||||
*
|
||||
* @param[in] sens_list : Pointer to select the sensor/feature.
|
||||
* @param[in] n_sens : Number of sensors selected.
|
||||
* @param[in, out] dev : Structure instance of bmi2_dev.
|
||||
*
|
||||
* @note Sensors/features that can be disabled.
|
||||
*
|
||||
*@verbatim
|
||||
* sens_list | Values
|
||||
* ----------------------------|-----------
|
||||
* BMI2_ACCEL | 0
|
||||
* BMI2_GYRO | 1
|
||||
* BMI2_AUX | 2
|
||||
* BMI2_GYRO_GAIN_UPDATE | 9
|
||||
* BMI2_DOOR_STATE_DETECTOR | 57
|
||||
* BMI2_TEMP | 31
|
||||
*@endverbatim
|
||||
*
|
||||
* @note :
|
||||
* example uint8_t sens_list[2] = {BMI2_ACCEL, BMI2_GYRO};
|
||||
* uint8_t n_sens = 2;
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval 0 -> Success
|
||||
* @retval < 0 -> Fail
|
||||
*/
|
||||
int8_t bmi270_dsd_sensor_disable(const uint8_t *sens_list, uint8_t n_sens, struct bmi2_dev *dev);
|
||||
|
||||
/**
|
||||
* \ingroup bmi270_dsd
|
||||
* \defgroup bmi270_dsdApiSensorC Sensor Configuration
|
||||
* @brief Enable / Disable feature configuration of the sensor
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \ingroup bmi270_dsdApiSensorC
|
||||
* \page bmi270_dsd_api_bmi270_dsd_set_sensor_config bmi270_dsd_set_sensor_config
|
||||
* \code
|
||||
* int8_t bmi270_dsd_set_sensor_config(struct bmi2_sens_config *sens_cfg, uint8_t n_sens, struct bmi2_dev *dev);
|
||||
* \endcode
|
||||
* @details This API sets the sensor/feature configuration.
|
||||
*
|
||||
* @param[in] sens_cfg : Structure instance of bmi2_sens_config.
|
||||
* @param[in] n_sens : Number of sensors selected.
|
||||
* @param[in, out] dev : Structure instance of bmi2_dev.
|
||||
*
|
||||
* @note Sensors/features that can be configured
|
||||
*
|
||||
*@verbatim
|
||||
* sens_list | Values
|
||||
* ----------------------------|-----------
|
||||
* BMI2_DOOR_STATE_DETECTOR | 57
|
||||
*@endverbatim
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval 0 -> Success
|
||||
* @retval < 0 -> Fail
|
||||
*/
|
||||
int8_t bmi270_dsd_set_sensor_config(struct bmi2_sens_config *sens_cfg, uint8_t n_sens, struct bmi2_dev *dev);
|
||||
|
||||
/*!
|
||||
* \ingroup bmi270_dsdApiSensorC
|
||||
* \page bmi270_dsd_api_bmi270_dsd_get_sensor_config bmi270_dsd_get_sensor_config
|
||||
* \code
|
||||
* int8_t bmi270_dsd_get_sensor_config(struct bmi2_sens_config *sens_cfg, uint8_t n_sens, struct bmi2_dev *dev);
|
||||
* \endcode
|
||||
* @details This API gets the sensor/feature configuration.
|
||||
*
|
||||
* @param[in] sens_cfg : Structure instance of bmi2_sens_config.
|
||||
* @param[in] n_sens : Number of sensors selected.
|
||||
* @param[in, out] dev : Structure instance of bmi2_dev.
|
||||
*
|
||||
* @note Sensors/features whose configurations can be read.
|
||||
*
|
||||
*@verbatim
|
||||
* sens_list | Values
|
||||
* ----------------------------|-----------
|
||||
* BMI2_DOOR_STATE_DETECTOR | 57
|
||||
*@endverbatim
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval 0 -> Success
|
||||
* @retval < 0 -> Fail
|
||||
*/
|
||||
int8_t bmi270_dsd_get_sensor_config(struct bmi2_sens_config *sens_cfg, uint8_t n_sens, struct bmi2_dev *dev);
|
||||
|
||||
/**
|
||||
* \ingroup bmi270_dsd
|
||||
* \defgroup bmi270_dsdApiSensorD Feature Sensor Data
|
||||
* @brief Get feature sensor data
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \ingroup bmi270_dsdApiSensorD
|
||||
* \page bmi270_dsd_api_bmi270_dsd_get_feature_data bmi270_dsd_get_feature_data
|
||||
* \code
|
||||
* int8_t bmi270_dsd_get_feature_data(struct bmi2_feat_sensor_data *feature_data, uint8_t n_sens, struct bmi2_dev *dev);
|
||||
* \endcode
|
||||
* @details This API gets the feature data for accelerometer, gyroscope,
|
||||
* auxiliary sensor, step counter, high-g, gyroscope user-gain update,
|
||||
* orientation, gyroscope cross sensitivity and error status for NVM and VFRM.
|
||||
*
|
||||
* @param[out] feature_data : Structure instance of bmi2_feat_sensor_data.
|
||||
* @param[in] n_sens : Number of sensors selected.
|
||||
* @param[in] dev : Structure instance of bmi2_dev.
|
||||
*
|
||||
* @note Sensors/features whose data can be read
|
||||
*
|
||||
*@verbatim
|
||||
* sens_list | Values
|
||||
* -----------------------------|-----------
|
||||
* BMI2_DOOR_STATE_DETECTOR | 57
|
||||
* BMI2_NVM_STATUS | 38
|
||||
* BMI2_VFRM_STATUS | 39
|
||||
*@endverbatim
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval 0 -> Success
|
||||
* @retval < 0 -> Fail
|
||||
*/
|
||||
int8_t bmi270_dsd_get_feature_data(struct bmi2_feat_sensor_data *feature_data, uint8_t n_sens, struct bmi2_dev *dev);
|
||||
|
||||
/**
|
||||
* \ingroup bmi270_dsd
|
||||
* \defgroup bmi270_dsdApiGyroUG Gyro User Gain
|
||||
* @brief Set / Get Gyro User Gain of the sensor
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \ingroup bmi270_dsdApiGyroUG
|
||||
* \page bmi270_dsd_api_bmi270_dsd_update_gyro_user_gain bmi270_dsd_update_gyro_user_gain
|
||||
* \code
|
||||
* int8_t bmi270_dsd_update_gyro_user_gain(const struct bmi2_gyro_user_gain_config *user_gain, struct bmi2_dev *dev);
|
||||
* \endcode
|
||||
* @details This API updates the gyroscope user-gain.
|
||||
*
|
||||
* @param[in] user_gain : Structure that stores user-gain configurations.
|
||||
* @param[in] dev : Structure instance of bmi2_dev.
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval 0 -> Success
|
||||
* @retval < 0 -> Fail
|
||||
*/
|
||||
int8_t bmi270_dsd_update_gyro_user_gain(const struct bmi2_gyro_user_gain_config *user_gain, struct bmi2_dev *dev);
|
||||
|
||||
/*!
|
||||
* \ingroup bmi270_dsdApiGyroUG
|
||||
* \page bmi270_dsd_api_bmi270_dsd_read_gyro_user_gain bmi270_dsd_read_gyro_user_gain
|
||||
* \code
|
||||
* int8_t bmi270_dsd_read_gyro_user_gain(struct bmi2_gyro_user_gain_data *gyr_usr_gain, const struct bmi2_dev *dev);
|
||||
* \endcode
|
||||
* @details This API reads the compensated gyroscope user-gain values.
|
||||
*
|
||||
* @param[out] gyr_usr_gain : Structure that stores gain values.
|
||||
* @param[in] dev : Structure instance of bmi2_dev.
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval 0 -> Success
|
||||
* @retval < 0 -> Fail
|
||||
*/
|
||||
int8_t bmi270_dsd_read_gyro_user_gain(struct bmi2_gyro_user_gain_data *gyr_usr_gain, struct bmi2_dev *dev);
|
||||
|
||||
/*!
|
||||
* \ingroup bmi270_dsdApiInt
|
||||
* \page bmi270_dsd_api_bmi270_dsd_map_feat_int bmi270_dsd_map_feat_int
|
||||
* \code
|
||||
* int8_t bmi270_dsd_map_feat_int(const struct bmi2_sens_int_config *sens_int, uint8_t n_sens, struct bmi2_dev *dev)
|
||||
* \endcode
|
||||
* @details This API maps/unmaps feature interrupts to that of interrupt pins.
|
||||
*
|
||||
* @param[in] sens_int : Structure instance of bmi2_sens_int_config.
|
||||
* @param[in] n_sens : Number of interrupts to be mapped.
|
||||
* @param[in] dev : Structure instance of bmi2_dev.
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval 0 -> Success
|
||||
* @retval < 0 -> Fail
|
||||
*/
|
||||
int8_t bmi270_dsd_map_feat_int(const struct bmi2_sens_int_config *sens_int, uint8_t n_sens, struct bmi2_dev *dev);
|
||||
|
||||
/******************************************************************************/
|
||||
/*! @name C++ Guard Macros */
|
||||
/******************************************************************************/
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* End of CPP guard */
|
||||
|
||||
#endif /* BMI270_DSD_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,460 @@
|
||||
/**
|
||||
* Copyright (c) 2023 Bosch Sensortec GmbH. All rights reserved.
|
||||
*
|
||||
* BSD-3-Clause
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* @file bmi270_legacy.h
|
||||
* @date 2023-05-03
|
||||
* @version v2.86.1
|
||||
*
|
||||
*/
|
||||
|
||||
/* BMI270_legacy offers same low-power features as in BMI160 */
|
||||
|
||||
/**
|
||||
* \ingroup bmi2xy
|
||||
* \defgroup bmi270_legacy BMI270_LEGACY
|
||||
* @brief Sensor driver for BMI270_LEGACY sensor
|
||||
*/
|
||||
|
||||
#ifndef BMI270_LEGACY_H_
|
||||
#define BMI270_LEGACY_H_
|
||||
|
||||
/*! CPP guard */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
/*! Header files
|
||||
****************************************************************************/
|
||||
#include "bmi2.h"
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
/*! Macro definitions
|
||||
****************************************************************************/
|
||||
|
||||
/*! @name BMI270_LEGACY chip identifier */
|
||||
#define BMI270_LEGACY_CHIP_ID UINT8_C(0x24)
|
||||
|
||||
/*! @name BMI270_LEGACY feature input start addresses */
|
||||
#define BMI270_LEGACY_CONFIG_ID_STRT_ADDR UINT8_C(0x00)
|
||||
#define BMI270_LEGACY_MAX_BURST_LEN_STRT_ADDR UINT8_C(0x02)
|
||||
#define BMI270_LEGACY_CRT_GYRO_SELF_TEST_STRT_ADDR UINT8_C(0x03)
|
||||
#define BMI270_LEGACY_ABORT_STRT_ADDR UINT8_C(0x03)
|
||||
#define BMI270_LEGACY_AXIS_MAP_STRT_ADDR UINT8_C(0x04)
|
||||
#define BMI270_LEGACY_GYRO_SELF_OFF_STRT_ADDR UINT8_C(0x05)
|
||||
#define BMI270_LEGACY_NVM_PROG_PREP_STRT_ADDR UINT8_C(0x05)
|
||||
#define BMI270_LEGACY_ANY_MOT_STRT_ADDR UINT8_C(0x06)
|
||||
#define BMI270_LEGACY_NO_MOT_STRT_ADDR UINT8_C(0x0A)
|
||||
#define BMI270_LEGACY_ORIENT_STRT_ADDR UINT8_C(0x00)
|
||||
#define BMI270_LEGACY_HIGH_G_STRT_ADDR UINT8_C(0x04)
|
||||
#define BMI270_LEGACY_LOW_G_STRT_ADDR UINT8_C(0x0A)
|
||||
#define BMI270_LEGACY_FLAT_STRT_ADDR UINT8_C(0x00)
|
||||
#define BMI270_LEGACY_SIG_MOT_STRT_ADDR UINT8_C(0x04)
|
||||
#define BMI270_LEGACY_STEP_COUNT_STRT_ADDR UINT8_C(0x00)
|
||||
#define BMI270_LEGACY_GYRO_USERGAIN_UPDATE_STRT_ADDR UINT8_C(0x04)
|
||||
#define BMI270_LEGACY_TAP_DETECT_1_STRT_ADDR UINT8_C(0x00)
|
||||
#define BMI270_LEGACY_TAP_DETECT_2_STRT_ADDR UINT8_C(0x00)
|
||||
|
||||
/*! @name BMI270_LEGACY feature output start addresses */
|
||||
#define BMI270_LEGACY_STEP_CNT_OUT_STRT_ADDR UINT8_C(0x00)
|
||||
#define BMI270_LEGACY_STEP_ACT_OUT_STRT_ADDR UINT8_C(0x04)
|
||||
#define BMI270_LEGACY_ORIENT_HIGH_G_OUT_STRT_ADDR UINT8_C(0x06)
|
||||
#define BMI270_LEGACY_GYR_USER_GAIN_OUT_STRT_ADDR UINT8_C(0x08)
|
||||
#define BMI270_LEGACY_GYRO_CROSS_SENSE_STRT_ADDR UINT8_C(0x0C)
|
||||
#define BMI270_LEGACY_NVM_VFRM_OUT_STRT_ADDR UINT8_C(0x0E)
|
||||
|
||||
/*! @name Defines maximum number of pages */
|
||||
#define BMI270_LEGACY_MAX_PAGE_NUM UINT8_C(8)
|
||||
|
||||
/*! @name Defines maximum number of feature input configurations */
|
||||
#define BMI270_LEGACY_MAX_FEAT_IN UINT8_C(23)
|
||||
|
||||
/*! @name Defines maximum number of feature outputs */
|
||||
#define BMI270_LEGACY_MAX_FEAT_OUT UINT8_C(8)
|
||||
|
||||
/*! @name Mask definitions for feature interrupt status bits */
|
||||
#define BMI270_LEGACY_SIG_MOT_STATUS_MASK UINT8_C(0x01)
|
||||
#define BMI270_LEGACY_STEP_CNT_STATUS_MASK UINT8_C(0x02)
|
||||
#define BMI270_LEGACY_HIGH_G_STATUS_MASK UINT8_C(0x04)
|
||||
#define BMI270_LEGACY_LOW_G_STATUS_MASK UINT8_C(0x04)
|
||||
#define BMI270_LEGACY_TAP_STATUS_MASK UINT8_C(0x08)
|
||||
#define BMI270_LEGACY_FLAT_STATUS_MASK UINT8_C(0x10)
|
||||
#define BMI270_LEGACY_NO_MOT_STATUS_MASK UINT8_C(0x20)
|
||||
#define BMI270_LEGACY_ANY_MOT_STATUS_MASK UINT8_C(0x40)
|
||||
#define BMI270_LEGACY_ORIENT_STATUS_MASK UINT8_C(0x80)
|
||||
#define BMI270_LEGACY_SINGLE_TAP_MASK UINT8_C(0x20)
|
||||
#define BMI270_LEGACY_DOUBLE_TAP_MASK UINT8_C(0x40)
|
||||
#define BMI270_LEGACY_TRIPLE_TAP_MASK UINT8_C(0x80)
|
||||
|
||||
/*! @name Status register for tap */
|
||||
#define BMI270_LEGACY_TAP_STATUS_REG UINT8_C(0x20)
|
||||
|
||||
/*! @name Macros for high-g interrupt axis/sign */
|
||||
#define BMI270_LEGACY_HIGH_G_DETECT_X UINT8_C(0x08)
|
||||
#define BMI270_LEGACY_HIGH_G_DETECT_Y UINT8_C(0x10)
|
||||
#define BMI270_LEGACY_HIGH_G_DETECT_Z UINT8_C(0x20)
|
||||
#define BMI270_LEGACY_HIGH_G_DETECT_SIGN UINT8_C(0x40)
|
||||
|
||||
/*! @name Mask definitions for feature interrupt mapping bits */
|
||||
#define BMI270_LEGACY_INT_SIG_MOT_MASK UINT8_C(0x01)
|
||||
#define BMI270_LEGACY_INT_STEP_COUNTER_MASK UINT8_C(0x02)
|
||||
#define BMI270_LEGACY_INT_STEP_DETECTOR_MASK UINT8_C(0x02)
|
||||
#define BMI270_LEGACY_INT_STEP_ACTIVITY_MASK UINT8_C(0x02)
|
||||
#define BMI270_LEGACY_INT_HIGH_G_MASK UINT8_C(0x04)
|
||||
#define BMI270_LEGACY_INT_LOW_G_MASK UINT8_C(0x04)
|
||||
#define BMI270_LEGACY_INT_TAP_MASK UINT8_C(0x08)
|
||||
#define BMI270_LEGACY_INT_FLAT_MASK UINT8_C(0x10)
|
||||
#define BMI270_LEGACY_INT_NO_MOT_MASK UINT8_C(0x20)
|
||||
#define BMI270_LEGACY_INT_ANY_MOT_MASK UINT8_C(0x40)
|
||||
#define BMI270_LEGACY_INT_ORIENT_MASK UINT8_C(0x80)
|
||||
#define BMI270_LEGACY_INT_SINGLE_TAP_MASK UINT8_C(0x20)
|
||||
#define BMI270_LEGACY_INT_DOUBLE_TAP_MASK UINT8_C(0x40)
|
||||
#define BMI270_LEGACY_INT_TRIPLE_TAP_MASK UINT8_C(0x80)
|
||||
|
||||
/*! @name Defines maximum number of feature interrupts */
|
||||
#define BMI270_LEGACY_MAX_INT_MAP UINT8_C(14)
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
/*! BMI270_LEGACY User Interface function prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* \ingroup bmi270_legacy
|
||||
* \defgroup bmi270_legacyApiInit Initialization
|
||||
* @brief Initialize the sensor and device structure
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \ingroup bmi270_legacyApiInit
|
||||
* \page bmi270_legacy_api_bmi270_legacy_init bmi270_legacy_init
|
||||
* \code
|
||||
* int8_t bmi270_legacy_init(struct bmi2_dev *dev);
|
||||
* \endcode
|
||||
* @details This API:
|
||||
* 1) updates the device structure with address of the configuration file.
|
||||
* 2) Initializes BMI270_LEGACY sensor.
|
||||
* 3) Writes the configuration file.
|
||||
* 4) Updates the feature offset parameters in the device structure.
|
||||
* 5) Updates the maximum number of pages, in the device structure.
|
||||
*
|
||||
* @param[in, out] dev : Structure instance of bmi2_dev.
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval 0 -> Success
|
||||
* @retval < 0 -> Fail
|
||||
*/
|
||||
int8_t bmi270_legacy_init(struct bmi2_dev *dev);
|
||||
|
||||
/**
|
||||
* \ingroup bmi270_legacy
|
||||
* \defgroup bmi270_legacyApiSensor Feature Set
|
||||
* @brief Enable / Disable features of the sensor
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \ingroup bmi270_legacyApiSensor
|
||||
* \page bmi270_legacy_api_bmi270_legacy_sensor_enable bmi270_legacy_sensor_enable
|
||||
* \code
|
||||
* int8_t bmi270_legacy_sensor_enable(const uint8_t *sens_list, uint8_t n_sens, struct bmi2_dev *dev);
|
||||
* \endcode
|
||||
* @details This API selects the sensors/features to be enabled.
|
||||
*
|
||||
* @param[in] sens_list : Pointer to select the sensor/feature.
|
||||
* @param[in] n_sens : Number of sensors selected.
|
||||
* @param[in, out] dev : Structure instance of bmi2_dev.
|
||||
*
|
||||
* @note Sensors/features that can be enabled.
|
||||
*
|
||||
*@verbatim
|
||||
* sens_list | Values
|
||||
* ----------------------------|-----------
|
||||
* BMI2_ACCEL | 0
|
||||
* BMI2_GYRO | 1
|
||||
* BMI2_AUX | 2
|
||||
* BMI2_SIG_MOTION | 3
|
||||
* BMI2_ANY_MOTION | 4
|
||||
* BMI2_NO_MOTION | 5
|
||||
* BMI2_STEP_DETECTOR | 6
|
||||
* BMI2_STEP_COUNTER | 7
|
||||
* BMI2_STEP_ACTIVITY | 8
|
||||
* BMI2_GYRO_GAIN_UPDATE | 9
|
||||
* BMI2_ORIENTATION | 14
|
||||
* BMI2_HIGH_G | 15
|
||||
* BMI2_LOW_G | 16
|
||||
* BMI2_FLAT | 17
|
||||
* BMI2_SINGLE_TAP | 25
|
||||
* BMI2_DOUBLE_TAP | 26
|
||||
* BMI2_TRIPLE_TAP | 27
|
||||
* BMI2_TEMP | 31
|
||||
*@endverbatim
|
||||
*
|
||||
* @note :
|
||||
* example uint8_t sens_list[2] = {BMI2_ACCEL, BMI2_GYRO};
|
||||
* uint8_t n_sens = 2;
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval 0 -> Success
|
||||
* @retval < 0 -> Fail
|
||||
*/
|
||||
int8_t bmi270_legacy_sensor_enable(const uint8_t *sens_list, uint8_t n_sens, struct bmi2_dev *dev);
|
||||
|
||||
/*!
|
||||
* \ingroup bmi270_legacyApiSensor
|
||||
* \page bmi270_legacy_api_bmi270_legacy_sensor_disable bmi270_legacy_sensor_disable
|
||||
* \code
|
||||
* int8_t bmi270_legacy_sensor_disable(const uint8_t *sens_list, uint8_t n_sens, struct bmi2_dev *dev);
|
||||
* \endcode
|
||||
* @details This API selects the sensors/features to be disabled.
|
||||
*
|
||||
* @param[in] sens_list : Pointer to select the sensor/feature.
|
||||
* @param[in] n_sens : Number of sensors selected.
|
||||
* @param[in, out] dev : Structure instance of bmi2_dev.
|
||||
*
|
||||
* @note Sensors/features that can be disabled.
|
||||
*
|
||||
*@verbatim
|
||||
* sens_list | Values
|
||||
* ----------------------------|-----------
|
||||
* BMI2_ACCEL | 0
|
||||
* BMI2_GYRO | 1
|
||||
* BMI2_AUX | 2
|
||||
* BMI2_SIG_MOTION | 3
|
||||
* BMI2_ANY_MOTION | 4
|
||||
* BMI2_NO_MOTION | 5
|
||||
* BMI2_STEP_DETECTOR | 6
|
||||
* BMI2_STEP_COUNTER | 7
|
||||
* BMI2_STEP_ACTIVITY | 8
|
||||
* BMI2_GYRO_GAIN_UPDATE | 9
|
||||
* BMI2_ORIENTATION | 14
|
||||
* BMI2_HIGH_G | 15
|
||||
* BMI2_LOW_G | 16
|
||||
* BMI2_FLAT | 17
|
||||
* BMI2_SINGLE_TAP | 25
|
||||
* BMI2_DOUBLE_TAP | 26
|
||||
* BMI2_TRIPLE_TAP | 27
|
||||
* BMI2_TEMP | 31
|
||||
*@endverbatim
|
||||
*
|
||||
* @note :
|
||||
* example uint8_t sens_list[2] = {BMI2_ACCEL, BMI2_GYRO};
|
||||
* uint8_t n_sens = 2;
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval 0 -> Success
|
||||
* @retval < 0 -> Fail
|
||||
*/
|
||||
int8_t bmi270_legacy_sensor_disable(const uint8_t *sens_list, uint8_t n_sens, struct bmi2_dev *dev);
|
||||
|
||||
/**
|
||||
* \ingroup bmi270_legacy
|
||||
* \defgroup bmi270_legacyApiSensorC Sensor Configuration
|
||||
* @brief Enable / Disable feature configuration of the sensor
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \ingroup bmi270_legacyApiSensorC
|
||||
* \page bmi270_legacy_api_bmi270_legacy_set_sensor_config bmi270_legacy_set_sensor_config
|
||||
* \code
|
||||
* int8_t bmi270_legacy_set_sensor_config(struct bmi2_sens_config *sens_cfg, uint8_t n_sens, struct bmi2_dev *dev);
|
||||
* \endcode
|
||||
* @details This API sets the sensor/feature configuration.
|
||||
*
|
||||
* @param[in] sens_cfg : Structure instance of bmi2_sens_config.
|
||||
* @param[in] n_sens : Number of sensors selected.
|
||||
* @param[in, out] dev : Structure instance of bmi2_dev.
|
||||
*
|
||||
* @note Sensors/features that can be configured
|
||||
*
|
||||
*@verbatim
|
||||
* sens_list | Values
|
||||
* ----------------------------|-----------
|
||||
* BMI2_SIG_MOTION | 3
|
||||
* BMI2_ANY_MOTION | 4
|
||||
* BMI2_NO_MOTION | 5
|
||||
* BMI2_STEP_DETECTOR | 6
|
||||
* BMI2_STEP_COUNTER | 7
|
||||
* BMI2_STEP_ACTIVITY | 8
|
||||
* BMI2_ORIENTATION | 14
|
||||
* BMI2_HIGH_G | 15
|
||||
* BMI2_LOW_G | 16
|
||||
* BMI2_FLAT | 17
|
||||
* BMI2_TAP | 28
|
||||
*@endverbatim
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval 0 -> Success
|
||||
* @retval < 0 -> Fail
|
||||
*/
|
||||
int8_t bmi270_legacy_set_sensor_config(struct bmi2_sens_config *sens_cfg, uint8_t n_sens, struct bmi2_dev *dev);
|
||||
|
||||
/*!
|
||||
* \ingroup bmi270_legacyApiSensorC
|
||||
* \page bmi270_legacy_api_bmi270_legacy_get_sensor_config bmi270_legacy_get_sensor_config
|
||||
* \code
|
||||
* int8_t bmi270_legacy_get_sensor_config(struct bmi2_sens_config *sens_cfg, uint8_t n_sens, struct bmi2_dev *dev);
|
||||
* \endcode
|
||||
* @details This API gets the sensor/feature configuration.
|
||||
*
|
||||
* @param[in] sens_cfg : Structure instance of bmi2_sens_config.
|
||||
* @param[in] n_sens : Number of sensors selected.
|
||||
* @param[in, out] dev : Structure instance of bmi2_dev.
|
||||
*
|
||||
* @note Sensors/features whose configurations can be read.
|
||||
*
|
||||
*@verbatim
|
||||
* sens_list | Values
|
||||
* ----------------------------|-----------
|
||||
* BMI2_SIG_MOTION | 3
|
||||
* BMI2_ANY_MOTION | 4
|
||||
* BMI2_NO_MOTION | 5
|
||||
* BMI2_STEP_DETECTOR | 6
|
||||
* BMI2_STEP_COUNTER | 7
|
||||
* BMI2_STEP_ACTIVITY | 8
|
||||
* BMI2_ORIENTATION | 14
|
||||
* BMI2_HIGH_G | 15
|
||||
* BMI2_LOW_G | 16
|
||||
* BMI2_FLAT | 17
|
||||
* BMI2_TAP | 28
|
||||
*@endverbatim
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval 0 -> Success
|
||||
* @retval < 0 -> Fail
|
||||
*/
|
||||
int8_t bmi270_legacy_get_sensor_config(struct bmi2_sens_config *sens_cfg, uint8_t n_sens, struct bmi2_dev *dev);
|
||||
|
||||
/**
|
||||
* \ingroup bmi270_legacy
|
||||
* \defgroup bmi270_legacyApiSensorD Feature Sensor Data
|
||||
* @brief Get feature sensor data
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \ingroup bmi270_legacyApiSensorD
|
||||
* \page bmi270_legacy_api_bmi270_legacy_get_feature_data bmi270_legacy_get_feature_data
|
||||
* \code
|
||||
* int8_t bmi270_legacy_get_feature_data(struct bmi2_feat_sensor_data *feature_data, uint8_t n_sens, struct bmi2_dev *dev);
|
||||
* \endcode
|
||||
* @details This API gets the feature data.
|
||||
*
|
||||
* @param[out] feature_data : Structure instance of bmi2_feat_sensor_data.
|
||||
* @param[in] n_sens : Number of sensors selected.
|
||||
* @param[in] dev : Structure instance of bmi2_dev.
|
||||
*
|
||||
* @note Sensors/features whose data can be read
|
||||
*
|
||||
*@verbatim
|
||||
* sens_list | Values
|
||||
* ---------------------|-----------
|
||||
* BMI2_STEP_COUNTER | 7
|
||||
* BMI2_STEP_ACTIVITY | 8
|
||||
* BMI2_ORIENTATION | 14
|
||||
* BMI2_HIGH_G | 15
|
||||
* BMI2_NVM_STATUS | 38
|
||||
* BMI2_VFRM_STATUS | 39
|
||||
*@endverbatim
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval 0 -> Success
|
||||
* @retval < 0 -> Fail
|
||||
*/
|
||||
int8_t bmi270_legacy_get_feature_data(struct bmi2_feat_sensor_data *feature_data, uint8_t n_sens, struct bmi2_dev *dev);
|
||||
|
||||
/**
|
||||
* \ingroup bmi270_legacy
|
||||
* \defgroup bmi270_legacyApiGyroUG Gyro User Gain
|
||||
* @brief Set / Get Gyro User Gain of the sensor
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \ingroup bmi270_legacyApiGyroUG
|
||||
* \page bmi270_legacy_api_bmi270_legacy_update_gyro_user_gain bmi270_legacy_update_gyro_user_gain
|
||||
* \code
|
||||
* int8_t bmi270_legacy_update_gyro_user_gain(const struct bmi2_gyro_user_gain_config *user_gain, struct bmi2_dev *dev);
|
||||
* \endcode
|
||||
* @details This API updates the gyroscope user-gain.
|
||||
*
|
||||
* @param[in] user_gain : Structure that stores user-gain configurations.
|
||||
* @param[in] dev : Structure instance of bmi2_dev.
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval 0 -> Success
|
||||
* @retval < 0 -> Fail
|
||||
*/
|
||||
int8_t bmi270_legacy_update_gyro_user_gain(const struct bmi2_gyro_user_gain_config *user_gain, struct bmi2_dev *dev);
|
||||
|
||||
/*!
|
||||
* \ingroup bmi270_legacyApiGyroUG
|
||||
* \page bmi270_legacy_api_bmi270_legacy_read_gyro_user_gain bmi270_legacy_read_gyro_user_gain
|
||||
* \code
|
||||
* int8_t bmi270_legacy_read_gyro_user_gain(struct bmi2_gyro_user_gain_data *gyr_usr_gain, const struct bmi2_dev *dev);
|
||||
* \endcode
|
||||
* @details This API reads the compensated gyroscope user-gain values.
|
||||
*
|
||||
* @param[out] gyr_usr_gain : Structure that stores gain values.
|
||||
* @param[in] dev : Structure instance of bmi2_dev.
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval 0 -> Success
|
||||
* @retval < 0 -> Fail
|
||||
*/
|
||||
int8_t bmi270_legacy_read_gyro_user_gain(struct bmi2_gyro_user_gain_data *gyr_usr_gain, struct bmi2_dev *dev);
|
||||
|
||||
/*!
|
||||
* \ingroup bmi270_legacyApiInt
|
||||
* \page bmi270_legacy_api_bmi270_legacy_map_feat_int bmi270_legacy_map_feat_int
|
||||
* \code
|
||||
* int8_t bmi270_legacy_map_feat_int(const struct bmi2_sens_int_config *sens_int, uint8_t n_sens, struct bmi2_dev *dev)
|
||||
* \endcode
|
||||
* @details This API maps/unmaps feature interrupts to that of interrupt pins.
|
||||
*
|
||||
* @param[in] sens_int : Structure instance of bmi2_sens_int_config.
|
||||
* @param[in] n_sens : Number of interrupts to be mapped.
|
||||
* @param[in] dev : Structure instance of bmi2_dev.
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval 0 -> Success
|
||||
* @retval < 0 -> Fail
|
||||
*/
|
||||
int8_t bmi270_legacy_map_feat_int(const struct bmi2_sens_int_config *sens_int, uint8_t n_sens, struct bmi2_dev *dev);
|
||||
|
||||
/******************************************************************************/
|
||||
/*! @name C++ Guard Macros */
|
||||
/******************************************************************************/
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* End of CPP guard */
|
||||
|
||||
#endif /* _BMI270_LEGACY_H_ */
|
||||
@@ -0,0 +1,208 @@
|
||||
/**
|
||||
* Copyright (c) 2023 Bosch Sensortec GmbH. All rights reserved.
|
||||
*
|
||||
* BSD-3-Clause
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* @file bmi270_maximum_fifo.c
|
||||
* @date 2023-05-03
|
||||
* @version v2.86.1
|
||||
*
|
||||
*/
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
/*! Header files
|
||||
****************************************************************************/
|
||||
#include "bmi270_maximum_fifo.h"
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
/*! Global Variable
|
||||
****************************************************************************/
|
||||
|
||||
/*! @name Global array that stores the configuration file of BMI270 */
|
||||
const uint8_t bmi270_maximum_fifo_config_file[] = {
|
||||
0xc8, 0x2e, 0x00, 0x2e, 0x80, 0x2e, 0x1a, 0x00, 0xc8, 0x2e, 0x00, 0x2e, 0xc8, 0x2e, 0x00, 0x2e, 0xc8, 0x2e, 0x00,
|
||||
0x2e, 0xc8, 0x2e, 0x00, 0x2e, 0xc8, 0x2e, 0x00, 0x2e, 0xc8, 0x2e, 0x00, 0x2e, 0x90, 0x32, 0x21, 0x2e, 0x59, 0xf5,
|
||||
0x10, 0x30, 0x21, 0x2e, 0x6a, 0xf5, 0x1a, 0x24, 0x22, 0x00, 0x80, 0x2e, 0x3b, 0x00, 0xc8, 0x2e, 0x44, 0x47, 0x22,
|
||||
0x00, 0x37, 0x00, 0xa4, 0x00, 0xff, 0x0f, 0xd1, 0x00, 0x07, 0xad, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1,
|
||||
0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00,
|
||||
0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x11, 0x24, 0xfc, 0xf5, 0x80, 0x30, 0x40, 0x42, 0x50, 0x50, 0x00, 0x30, 0x12, 0x24, 0xeb,
|
||||
0x00, 0x03, 0x30, 0x00, 0x2e, 0xc1, 0x86, 0x5a, 0x0e, 0xfb, 0x2f, 0x21, 0x2e, 0xfc, 0xf5, 0x13, 0x24, 0x63, 0xf5,
|
||||
0xe0, 0x3c, 0x48, 0x00, 0x22, 0x30, 0xf7, 0x80, 0xc2, 0x42, 0xe1, 0x7f, 0x3a, 0x25, 0xfc, 0x86, 0xf0, 0x7f, 0x41,
|
||||
0x33, 0x98, 0x2e, 0xc2, 0xc4, 0xd6, 0x6f, 0xf1, 0x30, 0xf1, 0x08, 0xc4, 0x6f, 0x11, 0x24, 0xff, 0x03, 0x12, 0x24,
|
||||
0x00, 0xfc, 0x61, 0x09, 0xa2, 0x08, 0x36, 0xbe, 0x2a, 0xb9, 0x13, 0x24, 0x38, 0x00, 0x64, 0xbb, 0xd1, 0xbe, 0x94,
|
||||
0x0a, 0x71, 0x08, 0xd5, 0x42, 0x21, 0xbd, 0x91, 0xbc, 0xd2, 0x42, 0xc1, 0x42, 0x00, 0xb2, 0xfe, 0x82, 0x05, 0x2f,
|
||||
0x50, 0x30, 0x21, 0x2e, 0x21, 0xf2, 0x00, 0x2e, 0x00, 0x2e, 0xd0, 0x2e, 0xf0, 0x6f, 0x02, 0x30, 0x02, 0x42, 0x20,
|
||||
0x26, 0xe0, 0x6f, 0x02, 0x31, 0x03, 0x40, 0x9a, 0x0a, 0x02, 0x42, 0xf0, 0x37, 0x05, 0x2e, 0x5e, 0xf7, 0x10, 0x08,
|
||||
0x12, 0x24, 0x1e, 0xf2, 0x80, 0x42, 0x83, 0x84, 0xf1, 0x7f, 0x0a, 0x25, 0x13, 0x30, 0x83, 0x42, 0x3b, 0x82, 0xf0,
|
||||
0x6f, 0x00, 0x2e, 0x00, 0x2e, 0xd0, 0x2e, 0x12, 0x40, 0x52, 0x42, 0x00, 0x2e, 0x12, 0x40, 0x52, 0x42, 0x3e, 0x84,
|
||||
0x00, 0x40, 0x40, 0x42, 0x7e, 0x82, 0xe1, 0x7f, 0xf2, 0x7f, 0x98, 0x2e, 0x6a, 0xd6, 0x21, 0x30, 0x23, 0x2e, 0x61,
|
||||
0xf5, 0xeb, 0x2c, 0xe1, 0x6f
|
||||
};
|
||||
|
||||
/*! @name Global array that stores the feature input configuration of BMI270 */
|
||||
const struct bmi2_feature_config bmi270_maximum_fifo_feat_in[BMI270_MAXIMUM_FIFO_MAX_FEAT_IN] = {
|
||||
|
||||
};
|
||||
|
||||
/*! @name Global array that stores the feature output configuration */
|
||||
const struct bmi2_feature_config bmi270_maximum_fifo_feat_out[BMI270_MAXIMUM_FIFO_MAX_FEAT_OUT] = {
|
||||
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/*! Local Function Prototypes
|
||||
******************************************************************************/
|
||||
|
||||
/*!
|
||||
* @brief This internal API is used to validate the device pointer for
|
||||
* null conditions.
|
||||
*
|
||||
* @param[in] dev : Structure instance of bmi2_dev.
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval 0 -> Success
|
||||
* @retval < 0 -> Fail
|
||||
*/
|
||||
static int8_t null_ptr_check(const struct bmi2_dev *dev);
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
/*! User Interface Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/*!
|
||||
* @brief This API:
|
||||
* 1) updates the device structure with address of the configuration file.
|
||||
* 2) Initializes BMI270 sensor.
|
||||
* 3) Writes the configuration file.
|
||||
* 4) Updates the feature offset parameters in the device structure.
|
||||
* 5) Updates the maximum number of pages, in the device structure.
|
||||
*/
|
||||
int8_t bmi270_maximum_fifo_init(struct bmi2_dev *dev)
|
||||
{
|
||||
/* Variable to define result */
|
||||
int8_t rslt;
|
||||
|
||||
/* Null-pointer check */
|
||||
rslt = null_ptr_check(dev);
|
||||
|
||||
if (rslt == BMI2_OK)
|
||||
{
|
||||
/* Assign chip id of BMI270 */
|
||||
dev->chip_id = BMI270_MAXIMUM_FIFO_CHIP_ID;
|
||||
|
||||
dev->config_size = sizeof(bmi270_maximum_fifo_config_file);
|
||||
|
||||
/* Enable the variant specific features if any */
|
||||
dev->variant_feature = BMI2_GYRO_CROSS_SENS_ENABLE | BMI2_MAXIMUM_FIFO_VARIANT;
|
||||
|
||||
/* An extra dummy byte is read during SPI read */
|
||||
if (dev->intf == BMI2_SPI_INTF)
|
||||
{
|
||||
dev->dummy_byte = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
dev->dummy_byte = 0;
|
||||
}
|
||||
|
||||
/* If configuration file pointer is not assigned any address */
|
||||
if (!dev->config_file_ptr)
|
||||
{
|
||||
/* Give the address of the configuration file array to
|
||||
* the device pointer
|
||||
*/
|
||||
dev->config_file_ptr = bmi270_maximum_fifo_config_file;
|
||||
}
|
||||
|
||||
/* Initialize BMI2 sensor */
|
||||
rslt = bmi2_sec_init(dev);
|
||||
|
||||
if (rslt == BMI2_OK)
|
||||
{
|
||||
/* Assign the offsets of the feature input
|
||||
* configuration to the device structure
|
||||
*/
|
||||
dev->feat_config = bmi270_maximum_fifo_feat_in;
|
||||
|
||||
/* Assign the offsets of the feature output to
|
||||
* the device structure
|
||||
*/
|
||||
dev->feat_output = bmi270_maximum_fifo_feat_out;
|
||||
|
||||
/* Assign the maximum number of pages to the
|
||||
* device structure
|
||||
*/
|
||||
dev->page_max = BMI270_MAXIMUM_FIFO_MAX_PAGE_NUM;
|
||||
|
||||
/* Assign maximum number of input sensors/
|
||||
* features to device structure
|
||||
*/
|
||||
dev->input_sens = BMI270_MAXIMUM_FIFO_MAX_FEAT_IN;
|
||||
|
||||
/* Assign maximum number of output sensors/
|
||||
* features to device structure
|
||||
*/
|
||||
dev->out_sens = BMI270_MAXIMUM_FIFO_MAX_FEAT_OUT;
|
||||
|
||||
/* Get the gyroscope cross axis sensitivity */
|
||||
rslt = bmi2_get_gyro_cross_sense(dev);
|
||||
}
|
||||
}
|
||||
|
||||
return rslt;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
/*! Local Function Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/*!
|
||||
* @brief This internal API is used to validate the device structure pointer for
|
||||
* null conditions.
|
||||
*/
|
||||
static int8_t null_ptr_check(const struct bmi2_dev *dev)
|
||||
{
|
||||
/* Variable to define result */
|
||||
int8_t rslt = BMI2_OK;
|
||||
|
||||
if ((dev == NULL) || (dev->read == NULL) || (dev->write == NULL) || (dev->delay_us == NULL))
|
||||
{
|
||||
/* Device structure pointer is not valid */
|
||||
rslt = BMI2_E_NULL_PTR;
|
||||
}
|
||||
|
||||
return rslt;
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
/**
|
||||
* Copyright (c) 2023 Bosch Sensortec GmbH. All rights reserved.
|
||||
*
|
||||
* BSD-3-Clause
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* @file bmi270_maximum_fifo.h
|
||||
* @date 2023-05-03
|
||||
* @version v2.86.1
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* \ingroup bmi2xy
|
||||
* \defgroup bmi270_maximum_fifo BMI270_MAXIMUM_FIFO
|
||||
* @brief Sensor driver for BMI270_MAXIMUM_FIFO sensor
|
||||
*/
|
||||
|
||||
#ifndef BMI270_MAXIMUM_FIFO_H_
|
||||
#define BMI270_MAXIMUM_FIFO_H_
|
||||
|
||||
/*! CPP guard */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
/*! Header files
|
||||
****************************************************************************/
|
||||
#include "bmi2.h"
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
/*! Macro definitions
|
||||
****************************************************************************/
|
||||
|
||||
/*! @name BMI270 Chip identifier */
|
||||
#define BMI270_MAXIMUM_FIFO_CHIP_ID UINT8_C(0x24)
|
||||
|
||||
/*! @name Defines maximum number of pages */
|
||||
#define BMI270_MAXIMUM_FIFO_MAX_PAGE_NUM UINT8_C(0)
|
||||
|
||||
/*! @name Defines maximum number of feature input configurations */
|
||||
#define BMI270_MAXIMUM_FIFO_MAX_FEAT_IN UINT8_C(0)
|
||||
|
||||
/*! @name Defines maximum number of feature outputs */
|
||||
#define BMI270_MAXIMUM_FIFO_MAX_FEAT_OUT UINT8_C(0)
|
||||
|
||||
/*! @name Mask definitions for feature interrupt status bits */
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
/*! BMI270 User Interface function prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* \ingroup bmi270_maximum_fifo
|
||||
* \defgroup bmi270_maximum_fifoApiInit Initialization
|
||||
* @brief Initialize the sensor and device structure
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \ingroup bmi270_maximum_fifoApiInit
|
||||
* \page bmi270_maximum_fifo_api_bmi270_maximum_fifo_init bmi270_maximum_fifo_init
|
||||
* \code
|
||||
* int8_t bmi270_maximum_fifo_init(struct bmi2_dev *dev);
|
||||
* \endcode
|
||||
* @details This API:
|
||||
* 1) updates the device structure with address of the configuration file.
|
||||
* 2) Initializes BMI270 sensor.
|
||||
* 3) Writes the configuration file.
|
||||
* 4) Updates the feature offset parameters in the device structure.
|
||||
* 5) Updates the maximum number of pages, in the device structure.
|
||||
*
|
||||
* @param[in, out] dev : Structure instance of bmi2_dev.
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval 0 -> Success
|
||||
* @retval < 0 -> Fail
|
||||
*/
|
||||
int8_t bmi270_maximum_fifo_init(struct bmi2_dev *dev);
|
||||
|
||||
/******************************************************************************/
|
||||
/*! @name C++ Guard Macros */
|
||||
/******************************************************************************/
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* End of CPP guard */
|
||||
|
||||
#endif /* BMI270_MAXIMUM_FIFO_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,417 @@
|
||||
/**
|
||||
* Copyright (c) 2023 Bosch Sensortec GmbH. All rights reserved.
|
||||
*
|
||||
* BSD-3-Clause
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* @file bmi2_ois.c
|
||||
* @date 2023-05-03
|
||||
* @version v2.86.1
|
||||
*
|
||||
*/
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/*! @name Header Files */
|
||||
/******************************************************************************/
|
||||
#include "bmi2_ois.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/*! Local Function Prototypes
|
||||
******************************************************************************/
|
||||
|
||||
/*!
|
||||
* @brief This internal API gets the OIS accelerometer and the gyroscope data.
|
||||
*
|
||||
* @param[out] ois_data : Structure instance of bmi2_sens_axes_data.
|
||||
* @param[in] reg_addr : Register address where data is stored.
|
||||
* @param[in] ois_dev : Structure instance of bmi2_ois_dev.
|
||||
* @param[in] ois_gyr_cross_sens_zx :"gyroscope cross sensitivity value which was calculated during
|
||||
* bmi2xy_init(), refer the example ois_accel_gyro.c for more info"
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval 0 -> Success
|
||||
* @retval < 0 -> Fail
|
||||
*/
|
||||
static int8_t get_ois_acc_gyr_data(struct bmi2_ois_sens_axes_data *ois_data,
|
||||
uint8_t reg_addr,
|
||||
struct bmi2_ois_dev *ois_dev,
|
||||
int16_t ois_gyr_cross_sens_zx);
|
||||
|
||||
/*!
|
||||
* @brief This internal API is used to validate the OIS device pointer for null
|
||||
* conditions.
|
||||
*
|
||||
* @param[in] ois_dev : Structure instance of bmi2_ois_dev.
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval 0 -> Success
|
||||
* @retval < 0 -> Fail
|
||||
*/
|
||||
static int8_t null_ptr_check(const struct bmi2_ois_dev *ois_dev);
|
||||
|
||||
/*!
|
||||
* @brief This internal API corrects the gyroscope cross-axis sensitivity
|
||||
* between the z and the x axis.
|
||||
*
|
||||
* @param[in] ois_dev : Structure instance of bmi2_ois_dev.
|
||||
* @param[in] ois_gyr_cross_sens_zx : "gyroscope cross sensitivity value which was calculated during bmi2xy_init(),
|
||||
* refer the example ois_accel_gyro.c for more info"
|
||||
*
|
||||
*/
|
||||
static void comp_gyro_cross_axis_sensitivity(struct bmi2_ois_sens_axes_data *ois_data, int16_t ois_gyr_cross_sens_zx);
|
||||
|
||||
/******************************************************************************/
|
||||
/*! @name User Interface Definitions */
|
||||
/******************************************************************************/
|
||||
|
||||
/*!
|
||||
* @brief This API reads the data from the given OIS register address of bmi2
|
||||
* sensor.
|
||||
*/
|
||||
int8_t bmi2_ois_get_regs(uint8_t ois_reg_addr, uint8_t *ois_reg_data, uint16_t data_len, struct bmi2_ois_dev *ois_dev)
|
||||
{
|
||||
/* Variable to define error */
|
||||
int8_t rslt;
|
||||
|
||||
/* Variable to define dummy byte for SPI read */
|
||||
uint8_t dummy_byte = 1;
|
||||
|
||||
/* Variable to define temporary length */
|
||||
uint16_t temp_len = data_len + dummy_byte;
|
||||
|
||||
/* Variable to define temporary buffer */
|
||||
uint8_t temp_buf[temp_len];
|
||||
|
||||
/* Variable to index bytes read */
|
||||
uint16_t index = 0;
|
||||
|
||||
/* Null-pointer check */
|
||||
rslt = null_ptr_check(ois_dev);
|
||||
if ((rslt == BMI2_OIS_OK) && (ois_reg_data != NULL))
|
||||
{
|
||||
/* Configuring reg_addr for SPI Interface */
|
||||
ois_reg_addr = (ois_reg_addr | BMI2_OIS_SPI_RD_MASK);
|
||||
|
||||
/* Read from OIS register through OIS interface */
|
||||
ois_dev->intf_rslt = ois_dev->ois_read(ois_reg_addr, temp_buf, temp_len, ois_dev->intf_ptr);
|
||||
if (ois_dev->intf_rslt == BMI2_INTF_RET_SUCCESS)
|
||||
{
|
||||
/* Read the data from the position next to dummy byte */
|
||||
while (index < data_len)
|
||||
{
|
||||
ois_reg_data[index] = temp_buf[index + dummy_byte];
|
||||
index++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rslt = BMI2_OIS_E_COM_FAIL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rslt = BMI2_OIS_E_NULL_PTR;
|
||||
}
|
||||
|
||||
return rslt;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief This API writes data to the given OIS register address of bmi2 sensor.
|
||||
*/
|
||||
int8_t bmi2_ois_set_regs(uint8_t ois_reg_addr,
|
||||
const uint8_t *ois_reg_data,
|
||||
uint16_t data_len,
|
||||
struct bmi2_ois_dev *ois_dev)
|
||||
{
|
||||
/* Variable to define error */
|
||||
int8_t rslt;
|
||||
|
||||
/* Null-pointer check */
|
||||
rslt = null_ptr_check(ois_dev);
|
||||
if ((rslt == BMI2_OIS_OK) && (ois_reg_data != NULL))
|
||||
{
|
||||
/* Configuring reg_addr for SPI Interface */
|
||||
ois_reg_addr = (ois_reg_addr & BMI2_OIS_SPI_WR_MASK);
|
||||
|
||||
/* Burst write to OIS register through OIS interface */
|
||||
ois_dev->intf_rslt = ois_dev->ois_write(ois_reg_addr, ois_reg_data, data_len, ois_dev->intf_ptr);
|
||||
if (ois_dev->intf_rslt != BMI2_INTF_RET_SUCCESS)
|
||||
{
|
||||
rslt = BMI2_OIS_E_COM_FAIL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rslt = BMI2_OIS_E_NULL_PTR;
|
||||
}
|
||||
|
||||
return rslt;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief This API enables/disables accelerometer/gyroscope data read through
|
||||
* OIS interface.
|
||||
*/
|
||||
int8_t bmi2_ois_set_config(struct bmi2_ois_dev *ois_dev)
|
||||
{
|
||||
/* Variable to define error */
|
||||
int8_t rslt;
|
||||
|
||||
/* Variable to store data */
|
||||
uint8_t reg_data = 0;
|
||||
|
||||
/* Null-pointer check */
|
||||
rslt = null_ptr_check(ois_dev);
|
||||
if (rslt == BMI2_OIS_OK)
|
||||
{
|
||||
rslt = bmi2_ois_get_regs(BMI2_OIS_CONFIG_ADDR, ®_data, 1, ois_dev);
|
||||
if (rslt == BMI2_OIS_OK)
|
||||
{
|
||||
/* Enable/Disable Low pass filter */
|
||||
reg_data = BMI2_SET_BIT_POS0(reg_data, BMI2_OIS_LP_FILTER_EN, ois_dev->lp_filter_en);
|
||||
|
||||
/* Configures Low pass filter cut-off frequency */
|
||||
reg_data = BMI2_OIS_SET_BITS(reg_data, BMI2_OIS_LP_FILTER_CONFIG, ois_dev->lp_filter_config);
|
||||
|
||||
/* Low pass filter - mute on secondary interface */
|
||||
reg_data = BMI2_OIS_SET_BITS(reg_data, BMI2_OIS_LP_FILTER_MUTE, ois_dev->lp_filter_mute);
|
||||
|
||||
/* Enable/Disable ois on accelerometer */
|
||||
reg_data = BMI2_OIS_SET_BITS(reg_data, BMI2_OIS_ACC_EN, ois_dev->acc_en);
|
||||
|
||||
/* Enable/Disable ois on gyroscope */
|
||||
reg_data = BMI2_OIS_SET_BITS(reg_data, BMI2_OIS_GYR_EN, ois_dev->gyr_en);
|
||||
|
||||
/* Set the OIS configurations */
|
||||
rslt = bmi2_ois_set_regs(BMI2_OIS_CONFIG_ADDR, ®_data, 1, ois_dev);
|
||||
}
|
||||
}
|
||||
|
||||
return rslt;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief This API gets the status of accelerometer/gyroscope enable for data
|
||||
* read through OIS interface.
|
||||
*/
|
||||
int8_t bmi2_ois_get_config(struct bmi2_ois_dev *ois_dev)
|
||||
{
|
||||
/* Variable to define error */
|
||||
int8_t rslt;
|
||||
|
||||
/* Variable to store data */
|
||||
uint8_t reg_data = 0;
|
||||
|
||||
/* Null-pointer check */
|
||||
rslt = null_ptr_check(ois_dev);
|
||||
if (rslt == BMI2_OIS_OK)
|
||||
{
|
||||
rslt = bmi2_ois_get_regs(BMI2_OIS_CONFIG_ADDR, ®_data, 1, ois_dev);
|
||||
if (rslt == BMI2_OIS_OK)
|
||||
{
|
||||
/* Get the status of Low pass filter enable */
|
||||
ois_dev->lp_filter_en = BMI2_GET_BIT_POS0(reg_data, BMI2_OIS_LP_FILTER_EN);
|
||||
|
||||
/* Get the status of Low pass filter cut-off frequency */
|
||||
ois_dev->lp_filter_config = BMI2_OIS_GET_BITS(reg_data, BMI2_OIS_LP_FILTER_CONFIG);
|
||||
|
||||
/* Get the status of Low pass filter mute */
|
||||
ois_dev->lp_filter_mute = BMI2_OIS_GET_BITS(reg_data, BMI2_OIS_LP_FILTER_MUTE);
|
||||
|
||||
/* Get the status of accelerometer enable */
|
||||
ois_dev->acc_en = BMI2_OIS_GET_BITS(reg_data, BMI2_OIS_ACC_EN);
|
||||
|
||||
/* Get the status of gyroscope enable */
|
||||
ois_dev->gyr_en = BMI2_OIS_GET_BITS(reg_data, BMI2_OIS_GYR_EN);
|
||||
}
|
||||
}
|
||||
|
||||
return rslt;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief This API reads accelerometer/gyroscope data through OIS interface.
|
||||
*/
|
||||
int8_t bmi2_ois_read_data(const uint8_t *sens_sel,
|
||||
uint8_t n_sens,
|
||||
struct bmi2_ois_dev *ois_dev,
|
||||
int16_t gyr_cross_sens_zx)
|
||||
{
|
||||
/* Variable to define error */
|
||||
int8_t rslt;
|
||||
|
||||
/* Variable to define loop */
|
||||
uint8_t loop = 0;
|
||||
|
||||
/* Variable to update register address */
|
||||
uint8_t reg_addr = 0;
|
||||
|
||||
/* Null-pointer check */
|
||||
rslt = null_ptr_check(ois_dev);
|
||||
if ((rslt == BMI2_OIS_OK) && (sens_sel != NULL))
|
||||
{
|
||||
|
||||
for (loop = 0; loop < n_sens; loop++)
|
||||
{
|
||||
switch (sens_sel[loop])
|
||||
{
|
||||
case BMI2_OIS_ACCEL:
|
||||
|
||||
/* Update OIS accelerometer address */
|
||||
reg_addr = BMI2_OIS_ACC_X_LSB_ADDR;
|
||||
|
||||
/* Get OIS accelerometer data */
|
||||
rslt = get_ois_acc_gyr_data(&ois_dev->acc_data, reg_addr, ois_dev, 0);
|
||||
break;
|
||||
case BMI2_OIS_GYRO:
|
||||
|
||||
/* Update OIS gyroscope address */
|
||||
reg_addr = BMI2_OIS_GYR_X_LSB_ADDR;
|
||||
|
||||
/* Get OIS gyroscope data */
|
||||
rslt = get_ois_acc_gyr_data(&ois_dev->gyr_data, reg_addr, ois_dev, gyr_cross_sens_zx);
|
||||
break;
|
||||
default:
|
||||
rslt = BMI2_OIS_E_INVALID_SENSOR;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Return error if any of the get sensor data fails */
|
||||
if (rslt != BMI2_OIS_OK)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rslt = BMI2_OIS_E_NULL_PTR;
|
||||
}
|
||||
|
||||
return rslt;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
/*! Local Function Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/*! @cond DOXYGEN_SUPRESS */
|
||||
|
||||
/* Suppressing doxygen warnings triggered for same static function names present across various sensor variant
|
||||
* directories */
|
||||
|
||||
/*!
|
||||
* @brief This internal API gets the accelerometer and the gyroscope data.
|
||||
*/
|
||||
static int8_t get_ois_acc_gyr_data(struct bmi2_ois_sens_axes_data *ois_data,
|
||||
uint8_t reg_addr,
|
||||
struct bmi2_ois_dev *ois_dev,
|
||||
int16_t ois_gyr_cross_sens_zx)
|
||||
{
|
||||
/* Variable to define error */
|
||||
int8_t rslt;
|
||||
|
||||
/* Variables to store MSB value */
|
||||
uint8_t msb;
|
||||
|
||||
/* Variables to store LSB value */
|
||||
uint8_t lsb;
|
||||
|
||||
/* Variables to store both MSB and LSB value */
|
||||
uint16_t msb_lsb;
|
||||
|
||||
/* Variables to define index */
|
||||
uint8_t index = 0;
|
||||
|
||||
/* Array to define data stored in register */
|
||||
uint8_t reg_data[BMI2_OIS_ACC_GYR_NUM_BYTES] = { 0 };
|
||||
|
||||
/* Read the sensor data */
|
||||
rslt = bmi2_ois_get_regs(reg_addr, reg_data, BMI2_OIS_ACC_GYR_NUM_BYTES, ois_dev);
|
||||
if (rslt == BMI2_OIS_OK)
|
||||
{
|
||||
/* Read x-axis data */
|
||||
lsb = reg_data[index++];
|
||||
msb = reg_data[index++];
|
||||
msb_lsb = ((uint16_t)msb << 8) | (uint16_t)lsb;
|
||||
ois_data->x = (int16_t)msb_lsb;
|
||||
|
||||
/* Read y-axis data */
|
||||
lsb = reg_data[index++];
|
||||
msb = reg_data[index++];
|
||||
msb_lsb = ((uint16_t)msb << 8) | (uint16_t)lsb;
|
||||
ois_data->y = (int16_t)msb_lsb;
|
||||
|
||||
/* Read z-axis data */
|
||||
lsb = reg_data[index++];
|
||||
msb = reg_data[index++];
|
||||
msb_lsb = ((uint16_t)msb << 8) | (uint16_t)lsb;
|
||||
ois_data->z = (int16_t)msb_lsb;
|
||||
|
||||
comp_gyro_cross_axis_sensitivity(ois_data, ois_gyr_cross_sens_zx);
|
||||
}
|
||||
|
||||
return rslt;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief This internal API is used to validate the device structure pointer for
|
||||
* null conditions.
|
||||
*/
|
||||
static int8_t null_ptr_check(const struct bmi2_ois_dev *ois_dev)
|
||||
{
|
||||
/* Variable to define error */
|
||||
int8_t rslt = BMI2_OIS_OK;
|
||||
|
||||
if ((ois_dev == NULL) || (ois_dev->ois_read == NULL) || (ois_dev->ois_write == NULL) ||
|
||||
(ois_dev->ois_delay_us == NULL))
|
||||
{
|
||||
/* Device structure pointer is NULL */
|
||||
rslt = BMI2_OIS_E_NULL_PTR;
|
||||
}
|
||||
|
||||
return rslt;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief This internal API corrects the gyroscope cross-axis sensitivity
|
||||
* between the z and the x axis.
|
||||
*/
|
||||
static void comp_gyro_cross_axis_sensitivity(struct bmi2_ois_sens_axes_data *ois_data, int16_t ois_gyr_cross_sens_zx)
|
||||
{
|
||||
|
||||
/* Get the compensated gyroscope x-axis */
|
||||
ois_data->x = ois_data->x - (int16_t)(((int32_t)ois_gyr_cross_sens_zx * (int32_t)ois_data->z) / 512);
|
||||
}
|
||||
|
||||
/*! @endcond */
|
||||
@@ -0,0 +1,380 @@
|
||||
/**
|
||||
* Copyright (c) 2023 Bosch Sensortec GmbH. All rights reserved.
|
||||
*
|
||||
* BSD-3-Clause
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* @file bmi2_ois.h
|
||||
* @date 2023-05-03
|
||||
* @version v2.86.1
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* \ingroup bmi2xy
|
||||
* \defgroup bmi2_ois BMI2_OIS
|
||||
* @brief Sensor driver for BMI2_OIS sensor
|
||||
*/
|
||||
#ifndef _BMI2_OIS_H
|
||||
#define _BMI2_OIS_H
|
||||
|
||||
/*! CPP guard */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
/*! Header files
|
||||
****************************************************************************/
|
||||
#ifdef __KERNEL__
|
||||
#include <linux/types.h>
|
||||
#include <linux/kernel.h>
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#endif
|
||||
|
||||
#include "bmi2_defs.h"
|
||||
|
||||
/******************************************************************************/
|
||||
/*! @name Macros */
|
||||
/******************************************************************************/
|
||||
|
||||
#ifndef BMI2_INTF_RETURN_TYPE
|
||||
#define BMI2_INTF_RETURN_TYPE int8_t
|
||||
#endif
|
||||
|
||||
/*! @name Utility macros */
|
||||
#define BMI2_OIS_SET_BITS(reg_data, bitname, data) \
|
||||
((reg_data & ~(bitname##_MASK)) | \
|
||||
((data << bitname##_POS) & bitname##_MASK))
|
||||
|
||||
#define BMI2_OIS_GET_BITS(reg_data, bitname) \
|
||||
((reg_data & (bitname##_MASK)) >> \
|
||||
(bitname##_POS))
|
||||
|
||||
/*! @name For enable and disable */
|
||||
#define BMI2_OIS_ENABLE UINT8_C(1)
|
||||
#define BMI2_OIS_DISABLE UINT8_C(0)
|
||||
|
||||
/*! @name To define success code */
|
||||
#define BMI2_OIS_OK UINT8_C(0)
|
||||
|
||||
/*! @name To define error codes */
|
||||
#define BMI2_OIS_E_NULL_PTR INT8_C(-1)
|
||||
#define BMI2_OIS_E_COM_FAIL INT8_C(-2)
|
||||
#define BMI2_OIS_E_INVALID_SENSOR INT8_C(-8)
|
||||
|
||||
/*! @name Mask definitions for SPI read/write address for OIS */
|
||||
#define BMI2_OIS_SPI_RD_MASK UINT8_C(0x80)
|
||||
#define BMI2_OIS_SPI_WR_MASK UINT8_C(0x7F)
|
||||
|
||||
/*! @name BMI2 OIS data bytes */
|
||||
#define BMI2_OIS_ACC_GYR_NUM_BYTES UINT8_C(6)
|
||||
|
||||
/*! @name Macros to select sensor for OIS data read */
|
||||
#define BMI2_OIS_ACCEL UINT8_C(0x01)
|
||||
#define BMI2_OIS_GYRO UINT8_C(0x02)
|
||||
|
||||
/*! @name Macros to define OIS register addresses */
|
||||
#define BMI2_OIS_CONFIG_ADDR UINT8_C(0x40)
|
||||
#define BMI2_OIS_ACC_X_LSB_ADDR UINT8_C(0x0C)
|
||||
#define BMI2_OIS_GYR_X_LSB_ADDR UINT8_C(0x12)
|
||||
|
||||
/*! @name Mask definitions for OIS configurations */
|
||||
#define BMI2_OIS_GYR_EN_MASK UINT8_C(0x40)
|
||||
#define BMI2_OIS_ACC_EN_MASK UINT8_C(0x80)
|
||||
|
||||
/*! @name Bit Positions for OIS configurations */
|
||||
#define BMI2_OIS_GYR_EN_POS UINT8_C(0x06)
|
||||
#define BMI2_OIS_ACC_EN_POS UINT8_C(0x07)
|
||||
|
||||
/*! Low pass filter configuration position and mask */
|
||||
#define BMI2_OIS_LP_FILTER_EN_POS UINT8_C(0x00)
|
||||
#define BMI2_OIS_LP_FILTER_EN_MASK UINT8_C(0x01)
|
||||
|
||||
#define BMI2_OIS_LP_FILTER_CONFIG_POS UINT8_C(0x01)
|
||||
#define BMI2_OIS_LP_FILTER_CONFIG_MASK UINT8_C(0x06)
|
||||
|
||||
#define BMI2_OIS_LP_FILTER_MUTE_POS UINT8_C(0x05)
|
||||
#define BMI2_OIS_LP_FILTER_MUTE_MASK UINT8_C(0x20)
|
||||
|
||||
/******************************************************************************/
|
||||
/*! @name Function Pointers */
|
||||
/******************************************************************************/
|
||||
|
||||
/*!
|
||||
* @brief Bus communication function pointer which should be mapped to
|
||||
* the platform specific read functions of the user
|
||||
*
|
||||
* @param[in] reg_addr : Register address from which data is read.
|
||||
* @param[out] reg_data : Pointer to data buffer where read data is stored.
|
||||
* @param[in] len : Number of bytes of data to be read.
|
||||
* @param[in, out] intf_ptr : Void pointer that can enable the linking of descriptors
|
||||
* for interface related call backs.
|
||||
*
|
||||
* retval = BMI2_INTF_RET_SUCCESS -> Success
|
||||
* retval != BMI2_INTF_RET_SUCCESS -> Failure
|
||||
*
|
||||
*/
|
||||
typedef BMI2_INTF_RETURN_TYPE (*bmi2_ois_read_fptr_t)(uint8_t reg_addr, uint8_t *data, uint32_t len, void *intf_ptr);
|
||||
|
||||
/*!
|
||||
* @brief Bus communication function pointer which should be mapped to
|
||||
* the platform specific write functions of the user
|
||||
*
|
||||
* @param[in] reg_addr : Register address to which the data is written.
|
||||
* @param[in] reg_data : Pointer to data buffer in which data to be written
|
||||
* is stored.
|
||||
* @param[in] len : Number of bytes of data to be written.
|
||||
* @param[in, out] intf_ptr : Void pointer that can enable the linking of descriptors
|
||||
* for interface related call backs
|
||||
*
|
||||
* retval = BMI2_INTF_RET_SUCCESS -> Success
|
||||
* retval != BMI2_INTF_RET_SUCCESS -> Failure
|
||||
*
|
||||
*/
|
||||
typedef BMI2_INTF_RETURN_TYPE (*bmi2_ois_write_fptr_t)(uint8_t reg_addr, const uint8_t *data, uint32_t len,
|
||||
void *intf_ptr);
|
||||
|
||||
/*!
|
||||
* @brief Delay function pointer which should be mapped to
|
||||
* delay function of the user
|
||||
*
|
||||
* @param[in] period : Delay in microseconds.
|
||||
* @param[in, out] intf_ptr : Void pointer that can enable the linking of descriptors
|
||||
* for interface related call backs
|
||||
*
|
||||
*/
|
||||
typedef void (*bmi2_ois_delay_fptr_t)(uint32_t period, void *intf_ptr);
|
||||
|
||||
/******************************************************************************/
|
||||
/*! @name Structure Declarations */
|
||||
/******************************************************************************/
|
||||
/*! @name Structure to define accelerometer and gyroscope sensor axes for OIS */
|
||||
struct bmi2_ois_sens_axes_data
|
||||
{
|
||||
/*! Data in x-axis */
|
||||
int16_t x;
|
||||
|
||||
/*! Data in y-axis */
|
||||
int16_t y;
|
||||
|
||||
/*! Data in z-axis */
|
||||
int16_t z;
|
||||
|
||||
};
|
||||
|
||||
/*! @name Structure to define bmi2 OIS sensor configurations */
|
||||
struct bmi2_ois_dev
|
||||
{
|
||||
/*! Read function pointer */
|
||||
bmi2_ois_read_fptr_t ois_read;
|
||||
|
||||
/*! Write function pointer */
|
||||
bmi2_ois_write_fptr_t ois_write;
|
||||
|
||||
/*! Delay function pointer */
|
||||
bmi2_ois_delay_fptr_t ois_delay_us;
|
||||
|
||||
/*! Low pass filter en/dis */
|
||||
uint8_t lp_filter_en;
|
||||
|
||||
/*! Void interface pointer */
|
||||
void *intf_ptr;
|
||||
|
||||
/*! To store interface pointer error */
|
||||
int8_t intf_rslt;
|
||||
|
||||
/*! Low pass filter cut-off frequency */
|
||||
uint8_t lp_filter_config;
|
||||
|
||||
/*! Low pass filter mute */
|
||||
uint8_t lp_filter_mute;
|
||||
|
||||
/*! Accelerometer enable for OIS */
|
||||
uint8_t acc_en;
|
||||
|
||||
/*! Gyroscope enable for OIS */
|
||||
uint8_t gyr_en;
|
||||
|
||||
/*! Accelerometer data axes */
|
||||
struct bmi2_ois_sens_axes_data acc_data;
|
||||
|
||||
/*! Gyroscope data axes */
|
||||
struct bmi2_ois_sens_axes_data gyr_data;
|
||||
};
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
/*! BMI2 OIS User Interface function prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* \ingroup bmi2_ois
|
||||
* \defgroup bmi2_oisApiRegs Registers
|
||||
* @brief Read data from the given OIS register address of bmi2
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \ingroup bmi2_oisApiRegs
|
||||
* \page bmi2_ois_api_bmi2_ois_get_regs bmi2_ois_get_regs
|
||||
* \code
|
||||
* int8_t bmi2_ois_get_regs(uint8_t ois_reg_addr,
|
||||
* uint8_t *ois_reg_data,
|
||||
* uint16_t data_len,
|
||||
* const struct bmi2_ois_dev *ois_dev);
|
||||
* \endcode
|
||||
* @details This API reads the data from the given OIS register address of bmi2
|
||||
* sensor.
|
||||
*
|
||||
* @param[in] ois_reg_addr : OIS register address from which data is read.
|
||||
* @param[out] ois_reg_data : Pointer to data buffer where read data is stored.
|
||||
* @param[in] data_len : No. of bytes of data to be read.
|
||||
* @param[in] ois_dev : Structure instance of bmi2_ois_dev.
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval 0 -> Success
|
||||
* @retval < 0 -> Fail
|
||||
*/
|
||||
int8_t bmi2_ois_get_regs(uint8_t ois_reg_addr, uint8_t *ois_reg_data, uint16_t data_len, struct bmi2_ois_dev *ois_dev);
|
||||
|
||||
/*!
|
||||
* \ingroup bmi2_oisApiRegs
|
||||
* \page bmi2_ois_api_bmi2_ois_set_regs bmi2_ois_set_regs
|
||||
* \code
|
||||
* int8_t bmi2_ois_set_regs(uint8_t ois_reg_addr,
|
||||
* uint8_t *ois_reg_data,
|
||||
* uint16_t data_len,
|
||||
* const struct bmi2_ois_dev *ois_dev);
|
||||
* \endcode
|
||||
* @details This API writes data to the given OIS register address of bmi2 sensor.
|
||||
*
|
||||
* @param[in] ois_reg_addr : OIS register address to which the data is written.
|
||||
* @param[in] ois_reg_data : Pointer to data buffer in which data to be written
|
||||
* is stored.
|
||||
* @param[in] data_len : No. of bytes of data to be written.
|
||||
* @param[in] ois_dev : Structure instance of bmi2_ois_dev.
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval 0 -> Success
|
||||
* @retval < 0 -> Fail
|
||||
*/
|
||||
int8_t bmi2_ois_set_regs(uint8_t ois_reg_addr,
|
||||
const uint8_t *ois_reg_data,
|
||||
uint16_t data_len,
|
||||
struct bmi2_ois_dev *ois_dev);
|
||||
|
||||
/**
|
||||
* \ingroup bmi2_ois
|
||||
* \defgroup bmi2_oisApiConfig Status update
|
||||
* @brief Get / Set the status of Enable / Disable accelerometer / gyroscope data read through OIS interface
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \ingroup bmi2_oisApiConfig
|
||||
* \page bmi2_ois_api_bmi2_ois_set_config bmi2_ois_set_config
|
||||
* \code
|
||||
* int8_t bmi2_ois_set_config(const struct bmi2_ois_dev *ois_dev);
|
||||
* \endcode
|
||||
* @details This API sets the status of enable/disable accelerometer/gyroscope data read through
|
||||
* OIS interface.
|
||||
*
|
||||
* @param[in] ois_dev : Structure instance of bmi2_ois_dev.
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval 0 -> Success
|
||||
* @retval < 0 -> Fail
|
||||
*/
|
||||
int8_t bmi2_ois_set_config(struct bmi2_ois_dev *ois_dev);
|
||||
|
||||
/*!
|
||||
* \ingroup bmi2_oisApiConfig
|
||||
* \page bmi2_ois_api_bmi2_ois_get_config bmi2_ois_get_config
|
||||
* \code
|
||||
* int8_t bmi2_ois_get_config(struct bmi2_ois_dev *ois_dev);
|
||||
* \endcode
|
||||
* @details This API gets the status of accelerometer/gyroscope enable for data
|
||||
* read through OIS interface.
|
||||
*
|
||||
* @param[in, out] ois_dev : Structure instance of bmi2_ois_dev.
|
||||
*
|
||||
* @note Enabling and disabling is done during OIS structure initialization.
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval 0 -> Success
|
||||
* @retval < 0 -> Fail
|
||||
*/
|
||||
int8_t bmi2_ois_get_config(struct bmi2_ois_dev *ois_dev);
|
||||
|
||||
/**
|
||||
* \ingroup bmi2_ois
|
||||
* \defgroup bmi2_oisApiRead Data read
|
||||
* @brief Read accelerometer / gyroscope data through OIS interface
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \ingroup bmi2_oisApiRead
|
||||
* \page bmi2_ois_api_bmi2_ois_read_data bmi2_ois_read_data
|
||||
* \code
|
||||
* int8_t bmi2_ois_read_data(const uint8_t *sens_sel,
|
||||
* uint8_t n_sens,
|
||||
* struct bmi2_ois_dev *ois_dev,
|
||||
* int16_t gyr_cross_sens_zx);
|
||||
* \endcode
|
||||
* @details This API reads accelerometer/gyroscope data through OIS interface.
|
||||
*
|
||||
* @param[in] sens_sel : Select sensor whose data is to be read.
|
||||
* @param[in] n_sens : Number of sensors selected.
|
||||
* @param[in, out] ois_dev : Structure instance of bmi2_ois_dev.
|
||||
* @param[in] gyr_cross_sens_zx : Store the gyroscope cross sensitivity values taken from the bmi2xy
|
||||
* (refer bmi2_ois example).
|
||||
*
|
||||
*@verbatim
|
||||
* sens_sel | Value
|
||||
* ---------------|---------------
|
||||
* BMI2_OIS_ACCEL | 0x01
|
||||
* BMI2_OIS_GYRO | 0x02
|
||||
*@endverbatim
|
||||
*
|
||||
* @return Result of API execution status
|
||||
* @retval 0 -> Success
|
||||
* @retval < 0 -> Fail
|
||||
*/
|
||||
int8_t bmi2_ois_read_data(const uint8_t *sens_sel,
|
||||
uint8_t n_sens,
|
||||
struct bmi2_ois_dev *ois_dev,
|
||||
int16_t gyr_cross_sens_zx);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* End of CPP guard */
|
||||
|
||||
#endif /* End of _BMI2_OIS_H */
|
||||
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#include "bmi270.h"
|
||||
#include "esp_log.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
|
||||
static const char* TAG = "BMI270";
|
||||
|
||||
BMI270::BMI270(i2c_master_bus_handle_t i2c_bus_handle, uint8_t addr) : _addr(addr), _initialized(false)
|
||||
{
|
||||
i2c_device_config_t dev_cfg = {
|
||||
.dev_addr_length = I2C_ADDR_BIT_LEN_7,
|
||||
.device_address = _addr,
|
||||
.scl_speed_hz = 400000,
|
||||
};
|
||||
ESP_ERROR_CHECK(i2c_master_bus_add_device(i2c_bus_handle, &dev_cfg, &_i2c_dev));
|
||||
|
||||
_bmi.intf = BMI2_I2C_INTF;
|
||||
_bmi.read = bmi2_i2c_read;
|
||||
_bmi.write = bmi2_i2c_write;
|
||||
_bmi.delay_us = bmi2_delay_us;
|
||||
_bmi.read_write_len = 32; // Max read/write length
|
||||
_bmi.config_file_ptr = NULL; // Use default config
|
||||
_bmi.intf_ptr = &_i2c_dev; // Pass the device handle as interface pointer
|
||||
}
|
||||
|
||||
BMI270::~BMI270()
|
||||
{
|
||||
if (_i2c_dev) {
|
||||
i2c_master_bus_rm_device(_i2c_dev);
|
||||
}
|
||||
}
|
||||
|
||||
BMI2_INTF_RETURN_TYPE BMI270::bmi2_i2c_read(uint8_t reg_addr, uint8_t* reg_data, uint32_t len, void* intf_ptr)
|
||||
{
|
||||
i2c_master_dev_handle_t dev = *(i2c_master_dev_handle_t*)intf_ptr;
|
||||
esp_err_t err = i2c_master_transmit_receive(dev, ®_addr, 1, reg_data, len, 1000);
|
||||
return (err == ESP_OK) ? BMI2_OK : BMI2_E_COM_FAIL;
|
||||
}
|
||||
|
||||
BMI2_INTF_RETURN_TYPE BMI270::bmi2_i2c_write(uint8_t reg_addr, const uint8_t* reg_data, uint32_t len, void* intf_ptr)
|
||||
{
|
||||
i2c_master_dev_handle_t dev = *(i2c_master_dev_handle_t*)intf_ptr;
|
||||
|
||||
uint8_t* buf = (uint8_t*)malloc(len + 1);
|
||||
if (!buf) return BMI2_E_COM_FAIL;
|
||||
|
||||
buf[0] = reg_addr;
|
||||
memcpy(buf + 1, reg_data, len);
|
||||
|
||||
esp_err_t err = i2c_master_transmit(dev, buf, len + 1, 1000);
|
||||
free(buf);
|
||||
|
||||
return (err == ESP_OK) ? BMI2_OK : BMI2_E_COM_FAIL;
|
||||
}
|
||||
|
||||
#define NOP() asm volatile("nop")
|
||||
|
||||
void BMI270::bmi2_delay_us(uint32_t period, void* intf_ptr)
|
||||
{
|
||||
uint64_t m = (uint64_t)esp_timer_get_time();
|
||||
if (period) {
|
||||
uint64_t e = (m + period);
|
||||
if (m > e) { // overflow
|
||||
while ((uint64_t)esp_timer_get_time() > e) {
|
||||
NOP();
|
||||
}
|
||||
}
|
||||
while ((uint64_t)esp_timer_get_time() < e) {
|
||||
NOP();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool BMI270::begin()
|
||||
{
|
||||
int8_t rslt;
|
||||
|
||||
// Initialize bmi270
|
||||
rslt = bmi270_init(&_bmi);
|
||||
if (rslt != BMI2_OK) {
|
||||
ESP_LOGE(TAG, "bmi270_init failed: %d", rslt);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Configure Accel
|
||||
struct bmi2_sens_config config;
|
||||
config.type = BMI2_ACCEL;
|
||||
rslt = bmi2_get_sensor_config(&config, 1, &_bmi);
|
||||
if (rslt == BMI2_OK) {
|
||||
config.cfg.acc.odr = BMI2_ACC_ODR_100HZ;
|
||||
config.cfg.acc.range = BMI2_ACC_RANGE_2G;
|
||||
config.cfg.acc.bwp = BMI2_ACC_NORMAL_AVG4;
|
||||
config.cfg.acc.filter_perf = BMI2_PERF_OPT_MODE;
|
||||
rslt = bmi2_set_sensor_config(&config, 1, &_bmi);
|
||||
}
|
||||
if (rslt != BMI2_OK) {
|
||||
ESP_LOGE(TAG, "Accel config failed: %d", rslt);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Configure Gyro
|
||||
config.type = BMI2_GYRO;
|
||||
rslt = bmi2_get_sensor_config(&config, 1, &_bmi);
|
||||
if (rslt == BMI2_OK) {
|
||||
config.cfg.gyr.odr = BMI2_GYR_ODR_100HZ;
|
||||
config.cfg.gyr.range = BMI2_GYR_RANGE_2000;
|
||||
config.cfg.gyr.bwp = BMI2_GYR_NORMAL_MODE;
|
||||
config.cfg.gyr.filter_perf = BMI2_PERF_OPT_MODE;
|
||||
config.cfg.gyr.noise_perf = BMI2_PERF_OPT_MODE;
|
||||
rslt = bmi2_set_sensor_config(&config, 1, &_bmi);
|
||||
}
|
||||
if (rslt != BMI2_OK) {
|
||||
ESP_LOGE(TAG, "Gyro config failed: %d", rslt);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Enable sensors
|
||||
uint8_t sensor_list[2] = {BMI2_ACCEL, BMI2_GYRO};
|
||||
rslt = bmi2_sensor_enable(sensor_list, 2, &_bmi);
|
||||
if (rslt != BMI2_OK) {
|
||||
ESP_LOGE(TAG, "Sensor enable failed: %d", rslt);
|
||||
return false;
|
||||
}
|
||||
|
||||
_initialized = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BMI270::update()
|
||||
{
|
||||
if (!_initialized) return false;
|
||||
|
||||
struct bmi2_sens_data sens_data = {{0}};
|
||||
int8_t rslt = bmi2_get_sensor_data(&sens_data, &_bmi);
|
||||
|
||||
if (rslt == BMI2_OK) {
|
||||
// Convert Accel
|
||||
// Assuming 2G range and 16-bit resolution as configured
|
||||
_data.accel_x = lsb_to_mps2(sens_data.acc.x, 2.0f, 16);
|
||||
_data.accel_y = lsb_to_mps2(sens_data.acc.y, 2.0f, 16);
|
||||
_data.accel_z = lsb_to_mps2(sens_data.acc.z, 2.0f, 16);
|
||||
|
||||
// Convert Gyro
|
||||
// Assuming 2000dps range and 16-bit resolution
|
||||
_data.gyro_x = lsb_to_dps(sens_data.gyr.x, 2000.0f, 16);
|
||||
_data.gyro_y = lsb_to_dps(sens_data.gyr.y, 2000.0f, 16);
|
||||
_data.gyro_z = lsb_to_dps(sens_data.gyr.z, 2000.0f, 16);
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void BMI270::getAccelerometer(float& x, float& y, float& z)
|
||||
{
|
||||
x = _data.accel_x;
|
||||
y = _data.accel_y;
|
||||
z = _data.accel_z;
|
||||
}
|
||||
|
||||
void BMI270::getGyroscope(float& x, float& y, float& z)
|
||||
{
|
||||
x = _data.gyro_x;
|
||||
y = _data.gyro_y;
|
||||
z = _data.gyro_z;
|
||||
}
|
||||
|
||||
const BMI270_Data& BMI270::getData()
|
||||
{
|
||||
return _data;
|
||||
}
|
||||
|
||||
float BMI270::lsb_to_mps2(int16_t val, float g_range, uint8_t bit_width)
|
||||
{
|
||||
float half_scale = (float)(1 << (bit_width - 1));
|
||||
return (9.80665f * val * g_range) / half_scale;
|
||||
}
|
||||
|
||||
float BMI270::lsb_to_dps(int16_t val, float dps, uint8_t bit_width)
|
||||
{
|
||||
float half_scale = (float)(1 << (bit_width - 1));
|
||||
return (dps * val) / half_scale;
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include "driver/i2c_master.h"
|
||||
#include "esp_err.h"
|
||||
#include "BMI270_SensorAPI/bmi270.h"
|
||||
|
||||
struct BMI270_Data {
|
||||
float accel_x;
|
||||
float accel_y;
|
||||
float accel_z;
|
||||
float gyro_x;
|
||||
float gyro_y;
|
||||
float gyro_z;
|
||||
};
|
||||
|
||||
class BMI270 {
|
||||
public:
|
||||
static constexpr uint8_t DEFAULT_ADDRESS = BMI2_I2C_PRIM_ADDR; // 0x68
|
||||
|
||||
BMI270(i2c_master_bus_handle_t i2c_bus_handle, uint8_t addr = DEFAULT_ADDRESS);
|
||||
~BMI270();
|
||||
|
||||
/**
|
||||
* @brief Initialize the device
|
||||
*
|
||||
* @return true if successful
|
||||
* @return false if failed
|
||||
*/
|
||||
bool begin();
|
||||
|
||||
/**
|
||||
* @brief Read sensor data
|
||||
*
|
||||
* @return true if successful
|
||||
* @return false if failed
|
||||
*/
|
||||
bool update();
|
||||
|
||||
void getAccelerometer(float& x, float& y, float& z);
|
||||
void getGyroscope(float& x, float& y, float& z);
|
||||
const BMI270_Data& getData();
|
||||
|
||||
private:
|
||||
i2c_master_dev_handle_t _i2c_dev;
|
||||
struct bmi2_dev _bmi;
|
||||
uint8_t _addr;
|
||||
bool _initialized;
|
||||
BMI270_Data _data;
|
||||
|
||||
static BMI2_INTF_RETURN_TYPE bmi2_i2c_read(uint8_t reg_addr, uint8_t* reg_data, uint32_t len, void* intf_ptr);
|
||||
static BMI2_INTF_RETURN_TYPE bmi2_i2c_write(uint8_t reg_addr, const uint8_t* reg_data, uint32_t len,
|
||||
void* intf_ptr);
|
||||
static void bmi2_delay_us(uint32_t period, void* intf_ptr);
|
||||
|
||||
float lsb_to_mps2(int16_t val, float g_range, uint8_t bit_width);
|
||||
float lsb_to_dps(int16_t val, float dps, uint8_t bit_width);
|
||||
};
|
||||
@@ -0,0 +1,219 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#include "hal.h"
|
||||
#include <memory>
|
||||
#include <mooncake_log.h>
|
||||
#include <nvs_flash.h>
|
||||
|
||||
static std::unique_ptr<Hal> _hal_instance;
|
||||
static const std::string _tag = "HAL";
|
||||
|
||||
Hal& GetHAL()
|
||||
{
|
||||
if (!_hal_instance) {
|
||||
mclog::tagInfo(_tag, "creating hal instance");
|
||||
_hal_instance = std::make_unique<Hal>();
|
||||
}
|
||||
return *_hal_instance.get();
|
||||
}
|
||||
|
||||
void Hal::init()
|
||||
{
|
||||
mclog::tagInfo(_tag, "init");
|
||||
|
||||
// Initialize NVS
|
||||
esp_err_t ret = nvs_flash_init();
|
||||
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
|
||||
ESP_ERROR_CHECK(nvs_flash_erase());
|
||||
ret = nvs_flash_init();
|
||||
}
|
||||
ESP_ERROR_CHECK(ret);
|
||||
|
||||
// ble_init();
|
||||
xiaozhi_board_init();
|
||||
xiaozhi_mcp_init();
|
||||
head_touch_init();
|
||||
io_expander_init();
|
||||
imu_init();
|
||||
servo_init();
|
||||
lvgl_init();
|
||||
reminder_init();
|
||||
|
||||
// startWebSocketAvatar();
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* System */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
#include <esp_system.h>
|
||||
#include <esp_timer.h>
|
||||
#include <esp_mac.h>
|
||||
|
||||
void Hal::delay(std::uint32_t ms)
|
||||
{
|
||||
vTaskDelay(pdMS_TO_TICKS(ms));
|
||||
}
|
||||
|
||||
std::uint32_t Hal::millis()
|
||||
{
|
||||
return esp_timer_get_time() / 1000;
|
||||
}
|
||||
|
||||
void Hal::feedTheDog()
|
||||
{
|
||||
vTaskDelay(1);
|
||||
}
|
||||
|
||||
std::array<uint8_t, 6> Hal::getFactoryMac()
|
||||
{
|
||||
std::array<uint8_t, 6> mac;
|
||||
esp_efuse_mac_get_default(mac.data());
|
||||
return mac;
|
||||
}
|
||||
|
||||
std::string Hal::getFactoryMacString(std::string divider)
|
||||
{
|
||||
auto mac = getFactoryMac();
|
||||
return fmt::format("{:02X}{}{:02X}{}{:02X}{}{:02X}{}{:02X}{}{:02X}", mac[0], divider, mac[1], divider, mac[2],
|
||||
divider, mac[3], divider, mac[4], divider, mac[5]);
|
||||
}
|
||||
|
||||
void Hal::reboot()
|
||||
{
|
||||
esp_restart();
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Xiaozhi */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
#include "board/hal_bridge.h"
|
||||
|
||||
void Hal::xiaozhi_board_init()
|
||||
{
|
||||
mclog::tagInfo(_tag, "xiaozhi board init");
|
||||
|
||||
hal_bridge::xiaozhi_board_init();
|
||||
}
|
||||
|
||||
void Hal::startXiaozhi()
|
||||
{
|
||||
mclog::tagInfo(_tag, "start xiaozhi");
|
||||
|
||||
hal_bridge::start_xiaozhi_app();
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Display */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
#include "board/hal_bridge.h"
|
||||
|
||||
void Hal::lvglLock()
|
||||
{
|
||||
hal_bridge::disply_lvgl_lock();
|
||||
}
|
||||
|
||||
void Hal::lvglUnlock()
|
||||
{
|
||||
hal_bridge::disply_lvgl_unlock();
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Lvgl */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
#include "board/hal_bridge.h"
|
||||
#include <stackchan/stackchan.h>
|
||||
|
||||
static void lvgl_read_cb(lv_indev_t* indev, lv_indev_data_t* data)
|
||||
{
|
||||
hal_bridge::lock();
|
||||
auto bridge_data = hal_bridge::get_data();
|
||||
|
||||
if (bridge_data.isXiaozhiMode) {
|
||||
hal_bridge::unlock();
|
||||
data->state = LV_INDEV_STATE_RELEASED;
|
||||
return;
|
||||
}
|
||||
|
||||
// mclog::tagInfo(_tag, "touchpoint: {}, x: {}, y: {}", bridge_data.touchPoint.num, bridge_data.touchPoint.x,
|
||||
// bridge_data.touchPoint.y);
|
||||
|
||||
if (bridge_data.touchPoint.num == 0) {
|
||||
data->state = LV_INDEV_STATE_RELEASED;
|
||||
} else {
|
||||
data->state = LV_INDEV_STATE_PRESSED;
|
||||
data->point.x = bridge_data.touchPoint.x;
|
||||
data->point.y = bridge_data.touchPoint.y;
|
||||
}
|
||||
|
||||
hal_bridge::unlock();
|
||||
}
|
||||
|
||||
void Hal::lvgl_init()
|
||||
{
|
||||
mclog::tagInfo(_tag, "lvgl init");
|
||||
|
||||
hal_bridge::disply_lvgl_lock();
|
||||
|
||||
mclog::tagInfo(_tag, "create lvgl touchpad indev");
|
||||
lvTouchpad = lv_indev_create();
|
||||
lv_indev_set_type(lvTouchpad, LV_INDEV_TYPE_POINTER);
|
||||
lv_indev_set_read_cb(lvTouchpad, lvgl_read_cb);
|
||||
lv_indev_set_group(lvTouchpad, lv_group_get_default());
|
||||
lv_indev_set_display(lvTouchpad, hal_bridge::display_get_lvgl_display());
|
||||
|
||||
hal_bridge::disply_lvgl_unlock();
|
||||
}
|
||||
|
||||
lv_timer_t* _timer_stackchan_update = NULL;
|
||||
|
||||
void Hal::startStackChanAutoUpdate(int fps)
|
||||
{
|
||||
mclog::tagInfo(_tag, "start stack chan auto update with fps: {}", fps);
|
||||
|
||||
if (_timer_stackchan_update) {
|
||||
mclog::tagWarn(_tag, "stack chan auto update already started");
|
||||
return;
|
||||
}
|
||||
|
||||
_timer_stackchan_update = lv_timer_create([](lv_timer_t* timer) { GetStackChan().update(); }, 1000 / fps, NULL);
|
||||
}
|
||||
|
||||
void Hal::stopStackChanAutoUpdate()
|
||||
{
|
||||
mclog::tagInfo(_tag, "stop stack chan auto update");
|
||||
|
||||
if (!_timer_stackchan_update) {
|
||||
mclog::tagWarn(_tag, "stack chan auto update already stopped");
|
||||
return;
|
||||
}
|
||||
|
||||
lv_timer_delete(_timer_stackchan_update);
|
||||
_timer_stackchan_update = NULL;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Reminder */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
#include "hal/utils/reminder/reminder.h"
|
||||
|
||||
int Hal::createReminder(int duration_s, const std::string& message)
|
||||
{
|
||||
return ReminderManager::GetInstance().CreateReminder(duration_s, message);
|
||||
}
|
||||
|
||||
void Hal::stopReminder(int id)
|
||||
{
|
||||
ReminderManager::GetInstance().StopReminder(id);
|
||||
}
|
||||
|
||||
void Hal::reminder_init()
|
||||
{
|
||||
mclog::tagInfo(_tag, "reminder init");
|
||||
|
||||
ReminderManager::GetInstance().Start();
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#pragma once
|
||||
#include <memory>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <lvgl.h>
|
||||
#include <smooth_ui_toolkit.hpp>
|
||||
#include <uitk/short_namespace.hpp>
|
||||
#include <array>
|
||||
#include <lvgl_image.h>
|
||||
#include <string_view>
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
*/
|
||||
enum class HeadPetGesture { None, Press, Release, SwipeForward, SwipeBackward };
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
*/
|
||||
enum class WsSignalSource {
|
||||
Local = 0,
|
||||
Remote,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
*/
|
||||
struct WsTextMessage_t {
|
||||
std::string name;
|
||||
std::string content;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
*/
|
||||
enum class ImuMotionEvent {
|
||||
None = 0,
|
||||
Shake,
|
||||
PickUp,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
*/
|
||||
enum class AppConfigEvent {
|
||||
None = 0,
|
||||
AppConnected,
|
||||
AppDisconnected,
|
||||
TryWifiConnect,
|
||||
WifiConnectFailed,
|
||||
WifiConnected,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
*/
|
||||
class Hal {
|
||||
public:
|
||||
void init();
|
||||
|
||||
/* --------------------------------- System --------------------------------- */
|
||||
void delay(std::uint32_t ms);
|
||||
std::uint32_t millis();
|
||||
void feedTheDog();
|
||||
std::array<uint8_t, 6> getFactoryMac();
|
||||
std::string getFactoryMacString(std::string divider = "");
|
||||
void reboot();
|
||||
|
||||
/* --------------------------------- Display -------------------------------- */
|
||||
lv_indev_t* lvTouchpad = nullptr;
|
||||
void lvglLock();
|
||||
void lvglUnlock();
|
||||
|
||||
/* --------------------------------- Xiaozhi -------------------------------- */
|
||||
void startXiaozhi();
|
||||
|
||||
/* ----------------------------------- BLE ---------------------------------- */
|
||||
uitk::Signal<const char*> onBleMotionData;
|
||||
uitk::Signal<const char*> onBleAvatarData;
|
||||
uitk::Signal<const char*> onBleConfigData;
|
||||
uitk::Signal<const char*> onBleAnimationData;
|
||||
uitk::Signal<AppConfigEvent> onAppConfigEvent;
|
||||
|
||||
void startBleServer();
|
||||
bool isBleConnected();
|
||||
void startAppConfigServer();
|
||||
bool isAppConfiged();
|
||||
|
||||
/* --------------------------------- HeadPet -------------------------------- */
|
||||
uitk::Signal<HeadPetGesture> onHeadPetGesture;
|
||||
|
||||
/* -------------------------------- StackChan ------------------------------- */
|
||||
void startStackChanAutoUpdate(int fps); // Start the auto update with lvgl timer
|
||||
void stopStackChanAutoUpdate();
|
||||
|
||||
/* ----------------------------------- RGB ---------------------------------- */
|
||||
void setRgbColor(uint8_t index, uint8_t r, uint8_t g, uint8_t b);
|
||||
void showRgbColor(uint8_t r, uint8_t g, uint8_t b);
|
||||
void refreshRgb();
|
||||
|
||||
/* ---------------------------------- Power --------------------------------- */
|
||||
void setServoPowerEnabled(bool enabled);
|
||||
|
||||
/* -------------------------------- Websocket ------------------------------- */
|
||||
uitk::Signal<std::string_view> onWsMotionData;
|
||||
uitk::Signal<std::string_view> onWsAvatarData;
|
||||
uitk::Signal<std::string> onWsCallRequest;
|
||||
uitk::Signal<bool> onWsCallResponse;
|
||||
uitk::Signal<WsSignalSource> onWsCallEnd;
|
||||
uitk::Signal<const WsTextMessage_t&> onWsTextMessage;
|
||||
uitk::Signal<bool> onWsVideoModeChange;
|
||||
uitk::Signal<std::shared_ptr<LvglImage>> onWsVideoFrame;
|
||||
uitk::Signal<std::string_view> onWsDanceData;
|
||||
|
||||
void startWebSocketAvatar();
|
||||
|
||||
/* -------------------------------- Reminder -------------------------------- */
|
||||
uitk::Signal<int, std::string> onReminderTriggered;
|
||||
int createReminder(int duration_s, const std::string& message);
|
||||
void stopReminder(int id);
|
||||
|
||||
/* ----------------------------------- IMU ---------------------------------- */
|
||||
uitk::Signal<ImuMotionEvent> onImuMotionEvent;
|
||||
|
||||
/* --------------------------------- EspNow --------------------------------- */
|
||||
uitk::Signal<const std::vector<uint8_t>&> onEspNowData;
|
||||
void startEspNow(int channel);
|
||||
bool espNowSend(const std::vector<uint8_t>& data, const uint8_t* destAddr = nullptr);
|
||||
void setLaserEnabled(bool enabled);
|
||||
|
||||
private:
|
||||
void xiaozhi_board_init();
|
||||
void lvgl_init();
|
||||
void xiaozhi_mcp_init();
|
||||
void ble_init();
|
||||
void servo_init();
|
||||
void head_touch_init();
|
||||
void io_expander_init();
|
||||
void reminder_init();
|
||||
void imu_init();
|
||||
};
|
||||
|
||||
Hal& GetHAL();
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
*/
|
||||
class LvglLockGuard {
|
||||
public:
|
||||
LvglLockGuard()
|
||||
{
|
||||
GetHAL().lvglLock();
|
||||
}
|
||||
~LvglLockGuard()
|
||||
{
|
||||
GetHAL().lvglUnlock();
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#include "hal.h"
|
||||
#include "utils/bleprph/bleprph.h"
|
||||
#include <ArduinoJson.hpp>
|
||||
#include <mooncake_log.h>
|
||||
#include <esp_mac.h>
|
||||
#include <settings.h>
|
||||
|
||||
static const std::string _tag = "HAL-BLE";
|
||||
|
||||
static int _handle_ble_motion_write(const char* json_data, uint16_t len, uint16_t conn_handle)
|
||||
{
|
||||
// mclog::tagInfo(_tag, "on motion:\n{}", json_data);
|
||||
GetHAL().onBleMotionData.emit(json_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _handle_ble_avatar_write(const char* json_data, uint16_t len, uint16_t conn_handle)
|
||||
{
|
||||
// mclog::tagInfo(_tag, "on avatar:\n{}", json_data);
|
||||
GetHAL().onBleAvatarData.emit(json_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _handle_ble_config_write(const char* json_data, uint16_t len, uint16_t conn_handle)
|
||||
{
|
||||
mclog::tagInfo(_tag, "on config:\n{}", json_data);
|
||||
GetHAL().onBleConfigData.emit(json_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _handle_ble_animation_write(const char* json_data, uint16_t len, uint16_t conn_handle)
|
||||
{
|
||||
mclog::tagInfo(_tag, "on animation:\n{}", json_data);
|
||||
GetHAL().onBleAnimationData.emit(json_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t _handle_ble_battery_read(void)
|
||||
{
|
||||
mclog::tagInfo(_tag, "on bat read");
|
||||
return 96;
|
||||
}
|
||||
|
||||
void Hal::ble_init()
|
||||
{
|
||||
mclog::tagInfo(_tag, "init");
|
||||
|
||||
static stackchan_ble_callbacks_t ble_callbacks = {
|
||||
.motion_cb = _handle_ble_motion_write,
|
||||
.avatar_cb = _handle_ble_avatar_write,
|
||||
.config_cb = _handle_ble_config_write,
|
||||
.animation_cb = _handle_ble_animation_write,
|
||||
.battery_read_cb = _handle_ble_battery_read,
|
||||
};
|
||||
stackchan_ble_register_callbacks(&ble_callbacks);
|
||||
|
||||
ble_prph_init();
|
||||
|
||||
uint8_t mac[6];
|
||||
esp_read_mac(mac, ESP_MAC_EFUSE_FACTORY);
|
||||
mclog::tagInfo(_tag, "init done, factory mac: {:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}", mac[0], mac[1], mac[2],
|
||||
mac[3], mac[4], mac[5]);
|
||||
}
|
||||
|
||||
void Hal::startBleServer()
|
||||
{
|
||||
mclog::tagInfo(_tag, "start ble server");
|
||||
ble_init();
|
||||
}
|
||||
|
||||
bool Hal::isBleConnected()
|
||||
{
|
||||
return stackchan_ble_is_connected();
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* App config server */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
#include "utils/wifi_connect/wifi_station.h"
|
||||
#include <string_view>
|
||||
#include <queue>
|
||||
#include <mutex>
|
||||
|
||||
class WifiConfigServer {
|
||||
public:
|
||||
void init()
|
||||
{
|
||||
GetHAL().onBleConfigData.connect([this](const char* data) { on_config_data(data); });
|
||||
_was_connected = stackchan_ble_is_connected();
|
||||
|
||||
// Setup WifiStation callbacks
|
||||
auto& wifi = StackChanWifiStation::GetInstance();
|
||||
wifi.OnConnect([this](const std::string& ssid) {
|
||||
mclog::tagInfo(_tag, "Wifi Connecting to {}", ssid);
|
||||
notify_state(0, "wifiConnecting");
|
||||
});
|
||||
wifi.OnConnected([this](const std::string& ssid) {
|
||||
mclog::tagInfo(_tag, "Wifi Connected to {}", ssid);
|
||||
notify_state(1, "wifiConnected");
|
||||
GetHAL().onAppConfigEvent.emit(AppConfigEvent::WifiConnected);
|
||||
|
||||
Settings settings("app_config", true);
|
||||
settings.SetBool("is_configed", true);
|
||||
});
|
||||
wifi.OnConnectFailed([this](const std::string& ssid) {
|
||||
mclog::tagInfo(_tag, "Wifi Connect Failed to {}", ssid);
|
||||
notify_state(2, "wifiConnectFailed");
|
||||
GetHAL().onAppConfigEvent.emit(AppConfigEvent::WifiConnectFailed);
|
||||
});
|
||||
|
||||
wifi.Start();
|
||||
}
|
||||
|
||||
void update()
|
||||
{
|
||||
bool is_connected = stackchan_ble_is_connected();
|
||||
if (is_connected != _was_connected) {
|
||||
_was_connected = is_connected;
|
||||
if (is_connected) {
|
||||
mclog::tagInfo("WifiConfigServer", "app Connected");
|
||||
GetHAL().onAppConfigEvent.emit(AppConfigEvent::AppConnected);
|
||||
} else {
|
||||
mclog::tagInfo("WifiConfigServer", "app Disconnected");
|
||||
GetHAL().onAppConfigEvent.emit(AppConfigEvent::AppDisconnected);
|
||||
}
|
||||
}
|
||||
|
||||
std::string data;
|
||||
bool has_data = false;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_mutex);
|
||||
if (!_msg_queue.empty()) {
|
||||
data = _msg_queue.front();
|
||||
_msg_queue.pop();
|
||||
has_data = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (has_data) {
|
||||
process_config_data(data.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static constexpr std::string_view _tag = "WifiConfigServer";
|
||||
std::queue<std::string> _msg_queue;
|
||||
std::mutex _mutex;
|
||||
bool _was_connected = false;
|
||||
|
||||
void on_config_data(const char* json_data)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_mutex);
|
||||
_msg_queue.push(json_data);
|
||||
}
|
||||
|
||||
void process_config_data(const char* json_data)
|
||||
{
|
||||
ArduinoJson::JsonDocument doc;
|
||||
auto error = ArduinoJson::deserializeJson(doc, json_data);
|
||||
|
||||
if (error) {
|
||||
mclog::tagError(_tag, "deserializeJson() failed: {}", error.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
if (doc["cmd"] == "setWifi") {
|
||||
handle_set_wifi(doc["data"]);
|
||||
}
|
||||
}
|
||||
|
||||
void handle_set_wifi(ArduinoJson::JsonObject data)
|
||||
{
|
||||
const char* ssid = data["ssid"];
|
||||
const char* password = data["password"];
|
||||
|
||||
mclog::tagInfo("WifiConfigServer", "get wifi config: {} / {}", ssid, password);
|
||||
|
||||
// Notify state: connecting
|
||||
notify_state(0, "wifiConnecting");
|
||||
GetHAL().onAppConfigEvent.emit(AppConfigEvent::TryWifiConnect);
|
||||
|
||||
connect_wifi(ssid, password);
|
||||
}
|
||||
|
||||
void connect_wifi(const char* ssid, const char* password)
|
||||
{
|
||||
auto& wifi = StackChanWifiStation::GetInstance();
|
||||
|
||||
// Save to NVS (compatible with Xiaozhi) and connect
|
||||
wifi.AddAuth(ssid, password);
|
||||
}
|
||||
|
||||
void notify_state(int type, const char* state)
|
||||
{
|
||||
ArduinoJson::JsonDocument doc;
|
||||
doc["cmd"] = "notifyState";
|
||||
doc["data"]["type"] = type;
|
||||
doc["data"]["state"] = state;
|
||||
|
||||
std::string json_str;
|
||||
ArduinoJson::serializeJson(doc, json_str);
|
||||
stackchan_ble_notify_config(json_str.c_str(), json_str.length());
|
||||
}
|
||||
};
|
||||
|
||||
static void _app_config_server_task(void* param)
|
||||
{
|
||||
auto server = std::make_unique<WifiConfigServer>();
|
||||
server->init();
|
||||
|
||||
while (1) {
|
||||
server->update();
|
||||
vTaskDelay(pdMS_TO_TICKS(50));
|
||||
}
|
||||
}
|
||||
|
||||
void Hal::startAppConfigServer()
|
||||
{
|
||||
mclog::tagInfo(_tag, "start app config server");
|
||||
|
||||
ble_init();
|
||||
|
||||
xTaskCreate(_app_config_server_task, "appconfig", 6000, NULL, 10, NULL);
|
||||
}
|
||||
|
||||
bool Hal::isAppConfiged()
|
||||
{
|
||||
Settings settings("app_config", false);
|
||||
return settings.GetBool("is_configed", false);
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#include "hal.h"
|
||||
#include <algorithm>
|
||||
#include <mooncake_log.h>
|
||||
#include <esp_wifi.h>
|
||||
#include <esp_netif.h>
|
||||
#include <esp_err.h>
|
||||
#include <esp_system.h>
|
||||
#include <esp_event.h>
|
||||
#include <lwip/err.h>
|
||||
#include <lwip/sys.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <esp_sntp.h>
|
||||
#include <esp_log.h>
|
||||
#include <esp_mac.h>
|
||||
#include <espnow.h>
|
||||
#include <espnow_storage.h>
|
||||
#include <espnow_utils.h>
|
||||
#include <esp_check.h>
|
||||
|
||||
static const std::string _tag = "HAL-EspNow";
|
||||
|
||||
static EventGroupHandle_t s_wifi_event_group = NULL;
|
||||
static const int WIFI_CONNECTED_BIT = BIT0;
|
||||
static const int WIFI_DISCONNECTED_BIT = BIT1;
|
||||
static const int WIFI_FAIL_BIT = BIT2;
|
||||
static const int WIFI_STARTED_BIT = BIT3;
|
||||
|
||||
static void wifi_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data)
|
||||
{
|
||||
const char* TAG = "WiFi";
|
||||
|
||||
// Wifi started
|
||||
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
|
||||
xEventGroupSetBits(s_wifi_event_group, WIFI_STARTED_BIT);
|
||||
}
|
||||
|
||||
// Disconnected
|
||||
else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
|
||||
xEventGroupSetBits(s_wifi_event_group, WIFI_DISCONNECTED_BIT);
|
||||
xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT);
|
||||
}
|
||||
|
||||
// Connected
|
||||
else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
|
||||
ip_event_got_ip_t* event = (ip_event_got_ip_t*)event_data;
|
||||
ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip));
|
||||
xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
|
||||
}
|
||||
}
|
||||
|
||||
static void _wifi_init(int channel = 1)
|
||||
{
|
||||
mclog::tagInfo(_tag, "wifi init");
|
||||
|
||||
// ESP_ERROR_CHECK(nvs_flash_init());
|
||||
// ESP_ERROR_CHECK(esp_netif_init());
|
||||
// ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
esp_netif_t* sta_netif = esp_netif_create_default_wifi_sta();
|
||||
assert(sta_netif);
|
||||
|
||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
|
||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
|
||||
|
||||
if (!s_wifi_event_group) {
|
||||
s_wifi_event_group = xEventGroupCreate();
|
||||
}
|
||||
|
||||
ESP_ERROR_CHECK(
|
||||
esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, nullptr, nullptr));
|
||||
ESP_ERROR_CHECK(
|
||||
esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &wifi_event_handler, nullptr, nullptr));
|
||||
|
||||
ESP_ERROR_CHECK(esp_wifi_start());
|
||||
|
||||
channel = std::clamp(channel, 1, 13);
|
||||
|
||||
mclog::tagInfo(_tag, "wifi channel set to {}", channel);
|
||||
|
||||
// 建议先开启混杂模式再设信道,确保射频频率被强制锁定
|
||||
ESP_ERROR_CHECK(esp_wifi_set_promiscuous(true));
|
||||
ESP_ERROR_CHECK(esp_wifi_set_channel(channel, WIFI_SECOND_CHAN_NONE));
|
||||
ESP_ERROR_CHECK(esp_wifi_set_promiscuous(false));
|
||||
}
|
||||
|
||||
static esp_err_t _handle_espnow_received(uint8_t* src_addr, void* data, size_t size, wifi_pkt_rx_ctrl_t* rx_ctrl)
|
||||
{
|
||||
const char* TAG = "EspNow";
|
||||
|
||||
ESP_PARAM_CHECK(src_addr);
|
||||
ESP_PARAM_CHECK(data);
|
||||
ESP_PARAM_CHECK(size);
|
||||
ESP_PARAM_CHECK(rx_ctrl);
|
||||
|
||||
static uint32_t count = 0;
|
||||
|
||||
ESP_LOGI(TAG, "espnow_recv, <%" PRIu32 "> [" MACSTR "][%d][%d][%u]: %.*s", count++, MAC2STR(src_addr),
|
||||
rx_ctrl->channel, rx_ctrl->rssi, size, size, "~");
|
||||
|
||||
std::vector<uint8_t> received_data((uint8_t*)data, (uint8_t*)data + size);
|
||||
GetHAL().onEspNowData.emit(received_data);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void Hal::startEspNow(int channel)
|
||||
{
|
||||
mclog::tagInfo(_tag, "start EspNow on channel {}", channel);
|
||||
|
||||
_wifi_init(channel);
|
||||
|
||||
espnow_config_t espnow_config = ESPNOW_INIT_CONFIG_DEFAULT();
|
||||
|
||||
// 2. 修改关键参数以兼容 Arduino
|
||||
espnow_config.forward_enable = false; // 关闭转发(多跳),Arduino 无法解析带转发头的包
|
||||
espnow_config.forward_switch_channel = false; // 关闭自动切信道
|
||||
espnow_config.send_retry_num = 5; // 失败重试次数(可按需调,建议5-10)
|
||||
|
||||
// 3. 修改接收使能开关
|
||||
espnow_config.receive_enable.forward = false; // 关闭转发包接收
|
||||
espnow_config.receive_enable.data = true; // 必须开启这个,才能接收 Arduino 发来的普通数据包
|
||||
|
||||
espnow_init(&espnow_config);
|
||||
espnow_set_config_for_data_type(ESPNOW_DATA_TYPE_DATA, true, _handle_espnow_received);
|
||||
|
||||
mclog::tagInfo(_tag, "factory mac: {}", getFactoryMacString());
|
||||
}
|
||||
|
||||
bool Hal::espNowSend(const std::vector<uint8_t>& data, const uint8_t* destAddr)
|
||||
{
|
||||
mclog::tagInfo(_tag, "send data with size: {}", data.size());
|
||||
|
||||
espnow_frame_head_t frame_head = ESPNOW_FRAME_CONFIG_DEFAULT();
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
|
||||
if (destAddr == nullptr) {
|
||||
ret = espnow_send(ESPNOW_DATA_TYPE_DATA, ESPNOW_ADDR_BROADCAST, data.data(), data.size(), &frame_head,
|
||||
portMAX_DELAY);
|
||||
} else {
|
||||
ret = espnow_send(ESPNOW_DATA_TYPE_DATA, destAddr, data.data(), data.size(), &frame_head, portMAX_DELAY);
|
||||
}
|
||||
|
||||
if (ret != ESP_OK) {
|
||||
mclog::tagError(_tag, "send failed: {}", esp_err_to_name(ret));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#include <driver/gpio.h>
|
||||
|
||||
void Hal::setLaserEnabled(bool enabled)
|
||||
{
|
||||
static bool laser_enabled = false;
|
||||
static bool is_inited = false;
|
||||
|
||||
if (laser_enabled == enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
const gpio_num_t laser_pin = GPIO_NUM_9;
|
||||
|
||||
if (!is_inited) {
|
||||
gpio_reset_pin(laser_pin);
|
||||
gpio_set_direction(laser_pin, GPIO_MODE_OUTPUT);
|
||||
gpio_set_pull_mode(laser_pin, GPIO_PULLUP_ONLY);
|
||||
is_inited = true;
|
||||
}
|
||||
|
||||
mclog::tagInfo(_tag, "set laser {}", enabled ? "enabled" : "disabled");
|
||||
|
||||
if (enabled) {
|
||||
gpio_set_level(laser_pin, 1);
|
||||
} else {
|
||||
gpio_set_level(laser_pin, 0);
|
||||
}
|
||||
laser_enabled = enabled;
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#include "hal.h"
|
||||
#include "drivers/Si12T/Si12T.h"
|
||||
#include "board/hal_bridge.h"
|
||||
#include <mooncake_log.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
|
||||
static const std::string _tag = "HAL-HeadTouch";
|
||||
|
||||
// 触摸状态
|
||||
enum class TouchState { IDLE, TOUCHED, SWIPING };
|
||||
|
||||
// 配置参数
|
||||
struct TouchConfig {
|
||||
uint8_t touch_threshold = 1;
|
||||
int16_t swipe_threshold = 40; // 使用百分比,范围-100到100
|
||||
};
|
||||
|
||||
// 触摸数据
|
||||
struct TouchData {
|
||||
uint8_t intensity[3];
|
||||
uint32_t timestamp;
|
||||
|
||||
// 计算位置(返回-100到100的整数)
|
||||
int16_t get_position() const
|
||||
{
|
||||
uint16_t total = intensity[0] + intensity[1] + intensity[2];
|
||||
if (total == 0) return 0;
|
||||
|
||||
int32_t weighted = intensity[0] * (-100) + intensity[1] * 0 + intensity[2] * 100;
|
||||
return static_cast<int16_t>(weighted / total);
|
||||
}
|
||||
|
||||
uint8_t get_max_intensity() const
|
||||
{
|
||||
uint8_t max_val = intensity[0];
|
||||
if (intensity[1] > max_val) max_val = intensity[1];
|
||||
if (intensity[2] > max_val) max_val = intensity[2];
|
||||
return max_val;
|
||||
}
|
||||
|
||||
bool is_touched() const
|
||||
{
|
||||
return get_max_intensity() >= 1;
|
||||
}
|
||||
};
|
||||
|
||||
// 手势识别器类
|
||||
class GestureRecognizer {
|
||||
public:
|
||||
GestureRecognizer() : current_state(TouchState::IDLE), initial_position(0)
|
||||
{
|
||||
}
|
||||
|
||||
// 更新状态机,返回识别到的手势
|
||||
HeadPetGesture update(const TouchData& data)
|
||||
{
|
||||
HeadPetGesture gesture = HeadPetGesture::None;
|
||||
|
||||
switch (current_state) {
|
||||
case TouchState::IDLE:
|
||||
if (data.is_touched()) {
|
||||
current_state = TouchState::TOUCHED;
|
||||
initial_position = data.get_position();
|
||||
gesture = HeadPetGesture::Press;
|
||||
// mclog::tagDebug(_tag, "Touch detected at position: {}", initial_position);
|
||||
}
|
||||
break;
|
||||
|
||||
case TouchState::TOUCHED:
|
||||
if (!data.is_touched()) {
|
||||
current_state = TouchState::IDLE;
|
||||
gesture = HeadPetGesture::Release;
|
||||
} else {
|
||||
// Check for swipe
|
||||
int16_t current_pos = data.get_position();
|
||||
int16_t delta = current_pos - initial_position;
|
||||
|
||||
if (delta > config.swipe_threshold) {
|
||||
current_state = TouchState::SWIPING;
|
||||
gesture = HeadPetGesture::SwipeForward;
|
||||
// mclog::tagDebug(_tag, "Swipe forward detected, delta: {}", delta);
|
||||
} else if (delta < -config.swipe_threshold) {
|
||||
current_state = TouchState::SWIPING;
|
||||
gesture = HeadPetGesture::SwipeBackward;
|
||||
// mclog::tagDebug(_tag, "Swipe backward detected, delta: {}", delta);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TouchState::SWIPING:
|
||||
if (!data.is_touched()) {
|
||||
current_state = TouchState::IDLE;
|
||||
gesture = HeadPetGesture::Release;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return gesture;
|
||||
}
|
||||
|
||||
void set_config(const TouchConfig& cfg)
|
||||
{
|
||||
config = cfg;
|
||||
}
|
||||
|
||||
private:
|
||||
TouchConfig config;
|
||||
TouchState current_state;
|
||||
int16_t initial_position;
|
||||
};
|
||||
|
||||
static void _head_touch_update_task(void* param)
|
||||
{
|
||||
mclog::tagInfo(_tag, "start update task");
|
||||
|
||||
si12t_handle_t si12t = (si12t_handle_t)param;
|
||||
uint8_t touch_result = 0;
|
||||
TouchData data;
|
||||
|
||||
GestureRecognizer recognizer;
|
||||
HeadPetGesture gesture;
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(200));
|
||||
|
||||
while (1) {
|
||||
// Read data
|
||||
si12t_read_touch_result(si12t, &touch_result);
|
||||
si12t_parse_touch_result_to(touch_result, data.intensity);
|
||||
data.timestamp = xTaskGetTickCount();
|
||||
|
||||
// Update and fire event
|
||||
gesture = recognizer.update(data);
|
||||
if (gesture != HeadPetGesture::None) {
|
||||
GetHAL().onHeadPetGesture.emit(gesture);
|
||||
}
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(50));
|
||||
}
|
||||
}
|
||||
|
||||
void Hal::head_touch_init()
|
||||
{
|
||||
mclog::tagInfo(_tag, "init");
|
||||
|
||||
auto i2c_bus = hal_bridge::board_get_i2c_bus();
|
||||
|
||||
si12t_config_t si12t_cfg = {
|
||||
.i2c_bus = i2c_bus,
|
||||
.dev_addr = SI12T_GND_ADDRESS,
|
||||
};
|
||||
static si12t_handle_t si12t;
|
||||
si12t_init(&si12t_cfg, &si12t);
|
||||
si12t_setup(si12t, SI12T_TYPE_LOW, SI12T_SENSITIVITY_LEVEL_3);
|
||||
|
||||
xTaskCreate(_head_touch_update_task, "headtouch", 4096, si12t, 5, NULL);
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#include "hal.h"
|
||||
#include "board/hal_bridge.h"
|
||||
#include "drivers/bmi270/bmi270.h"
|
||||
#include "utils/motion_detector/motion_detector.h"
|
||||
#include <mooncake_log.h>
|
||||
#include <memory>
|
||||
|
||||
static const std::string _tag = "HAL-IMU";
|
||||
|
||||
static std::unique_ptr<BMI270> _bmi270;
|
||||
|
||||
static void _imu_task(void* param)
|
||||
{
|
||||
auto motion_detector = std::make_unique<MotionDetector>();
|
||||
|
||||
while (1) {
|
||||
if (_bmi270 && _bmi270->update()) {
|
||||
auto& data = _bmi270->getData();
|
||||
// mclog::debug("IMU Accel: {:.2f}\t{:.2f}\t{:.2f}", data.accel_x, data.accel_y, data.accel_z);
|
||||
|
||||
motion_detector->update(data.accel_x, data.accel_y, data.accel_z);
|
||||
|
||||
if (motion_detector->isShakeDetected()) {
|
||||
mclog::tagInfo(_tag, "Shake Detected!");
|
||||
GetHAL().onImuMotionEvent.emit(ImuMotionEvent::Shake);
|
||||
}
|
||||
if (motion_detector->isPickUpDetected()) {
|
||||
mclog::tagInfo(_tag, "Pick Up Detected!");
|
||||
GetHAL().onImuMotionEvent.emit(ImuMotionEvent::PickUp);
|
||||
}
|
||||
}
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
}
|
||||
}
|
||||
|
||||
void Hal::imu_init()
|
||||
{
|
||||
mclog::tagInfo(_tag, "init");
|
||||
|
||||
auto i2c_bus = hal_bridge::board_get_i2c_bus();
|
||||
|
||||
_bmi270 = std::make_unique<BMI270>(i2c_bus, 0x69);
|
||||
if (!_bmi270->begin()) {
|
||||
_bmi270.reset();
|
||||
mclog::tagError(_tag, "BMI270 init failed");
|
||||
return;
|
||||
}
|
||||
mclog::tagInfo(_tag, "BMI270 init ok");
|
||||
|
||||
// xTaskCreate(_imu_task, "imu", 4096, NULL, 5, NULL);
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#include "hal.h"
|
||||
#include "board/hal_bridge.h"
|
||||
#include "drivers/PY32IOExpander_Class/PY32IOExpander_Class.hpp"
|
||||
#include <mooncake_log.h>
|
||||
#include <memory>
|
||||
|
||||
static const std::string _tag = "HAL-IOE";
|
||||
|
||||
static std::unique_ptr<m5::PY32IOExpander_Class> _io_expander;
|
||||
|
||||
void Hal::io_expander_init()
|
||||
{
|
||||
mclog::tagInfo(_tag, "init");
|
||||
|
||||
auto i2c_bus = hal_bridge::board_get_i2c_bus();
|
||||
_io_expander = std::make_unique<m5::PY32IOExpander_Class>(i2c_bus);
|
||||
uint32_t start_tick = GetHAL().millis();
|
||||
|
||||
// PY32 IO Expander may boot slowly, wait for it
|
||||
while (1) {
|
||||
vTaskDelay(pdMS_TO_TICKS(200));
|
||||
|
||||
if (GetHAL().millis() - start_tick > 1200) {
|
||||
mclog::tagError(_tag, "init timeout");
|
||||
_io_expander.reset();
|
||||
break;
|
||||
}
|
||||
|
||||
if (_io_expander->begin()) {
|
||||
break;
|
||||
}
|
||||
mclog::tagInfo(_tag, "init failed, retrying...");
|
||||
}
|
||||
|
||||
if (_io_expander) {
|
||||
// VM EN
|
||||
_io_expander->setDirection(0, true); // Output
|
||||
_io_expander->setPullMode(0, true); // Pull-up
|
||||
GetHAL().setServoPowerEnabled(true);
|
||||
vTaskDelay(pdMS_TO_TICKS(200));
|
||||
|
||||
// RGB
|
||||
_io_expander->setDirection(13, true); // Output
|
||||
_io_expander->setPullMode(13, true); // Pull-up
|
||||
_io_expander->setDriveMode(13, false); // Push-pull
|
||||
_io_expander->setLedCount(12);
|
||||
vTaskDelay(pdMS_TO_TICKS(200));
|
||||
GetHAL().showRgbColor(0, 0, 0);
|
||||
vTaskDelay(pdMS_TO_TICKS(50));
|
||||
GetHAL().showRgbColor(0, 0, 0);
|
||||
|
||||
mclog::tagInfo(_tag, "init done");
|
||||
}
|
||||
}
|
||||
|
||||
void Hal::setServoPowerEnabled(bool enabled)
|
||||
{
|
||||
if (!_io_expander) {
|
||||
return;
|
||||
}
|
||||
_io_expander->digitalWrite(0, enabled ? true : false);
|
||||
}
|
||||
|
||||
void Hal::setRgbColor(uint8_t index, uint8_t r, uint8_t g, uint8_t b)
|
||||
{
|
||||
if (!_io_expander) {
|
||||
return;
|
||||
}
|
||||
_io_expander->setLedColor(index, r, g, b);
|
||||
}
|
||||
|
||||
void Hal::refreshRgb()
|
||||
{
|
||||
if (!_io_expander) {
|
||||
return;
|
||||
}
|
||||
_io_expander->refreshLeds();
|
||||
}
|
||||
|
||||
void Hal::showRgbColor(uint8_t r, uint8_t g, uint8_t b)
|
||||
{
|
||||
for (int i = 0; i < 12; i++) {
|
||||
setRgbColor(i, r, g, b);
|
||||
}
|
||||
refreshRgb();
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#include "hal.h"
|
||||
#include <mooncake_log.h>
|
||||
#include <mcp_server.h>
|
||||
#include <stackchan/stackchan.h>
|
||||
|
||||
using namespace stackchan;
|
||||
|
||||
static const std::string _tag = "HAL-MCP";
|
||||
|
||||
void Hal::xiaozhi_mcp_init()
|
||||
{
|
||||
mclog::tagInfo(_tag, "init");
|
||||
|
||||
// https://github.com/78/xiaozhi-esp32/blob/main/docs/mcp-usage.md
|
||||
auto& mcp_server = McpServer::GetInstance();
|
||||
|
||||
mclog::tagInfo(_tag, "add motion.set_angles tool");
|
||||
mcp_server.AddTool(
|
||||
"self.motion.set_angles",
|
||||
"Set the angles of the robot's servos (head movement). Yaw controls left/right (-1280 to "
|
||||
"1280), Pitch controls up/down (0 to 900). Note: 10 units equals 1 degree. For natural movement, prefer angles "
|
||||
"within +/- 300 (30 degrees) unless instructed otherwise. Speed controls the movement speed (100-1000).",
|
||||
PropertyList({Property("yaw", kPropertyTypeInteger, 0, -1280, 1280),
|
||||
Property("pitch", kPropertyTypeInteger, 0, 0, 900),
|
||||
Property("speed", kPropertyTypeInteger, 150, 100, 1000)}),
|
||||
[this](const PropertyList& properties) -> ReturnValue {
|
||||
int pitch = properties["pitch"].value<int>();
|
||||
int yaw = properties["yaw"].value<int>();
|
||||
int speed = properties["speed"].value<int>();
|
||||
|
||||
mclog::tagInfo(_tag, "motion set angles: pitch: {}, yaw: {}, speed: {}", pitch, yaw, speed);
|
||||
|
||||
auto& motion = GetStackChan().motion();
|
||||
motion.pitchServo().moveWithSpeed(pitch, speed);
|
||||
motion.yawServo().moveWithSpeed(yaw, speed);
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
mclog::tagInfo(_tag, "add led.set_color tool");
|
||||
mcp_server.AddTool("self.led.set_color",
|
||||
"Set the color of the RGB LED strip. Each channel (red, green, blue) ranges from 0 to 255. "
|
||||
"Note: For power saving and eye protection, it is recommended to keep each channel value below "
|
||||
"126.",
|
||||
PropertyList({Property("red", kPropertyTypeInteger, 0, 0, 168),
|
||||
Property("green", kPropertyTypeInteger, 0, 0, 168),
|
||||
Property("blue", kPropertyTypeInteger, 0, 0, 168)}),
|
||||
[this](const PropertyList& properties) -> ReturnValue {
|
||||
int r = properties["red"].value<int>();
|
||||
int g = properties["green"].value<int>();
|
||||
int b = properties["blue"].value<int>();
|
||||
|
||||
mclog::tagInfo(_tag, "led set color: r: {}, g: {}, b: {}", r, g, b);
|
||||
GetHAL().showRgbColor(r, g, b);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#include "hal.h"
|
||||
#include "drivers/SCServo_lib/src/SCSCL.h"
|
||||
#include <stackchan/stackchan.h>
|
||||
#include <smooth_ui_toolkit.hpp>
|
||||
#include <mooncake_log.h>
|
||||
#include <settings.h>
|
||||
|
||||
using namespace smooth_ui_toolkit;
|
||||
using namespace stackchan::motion;
|
||||
|
||||
static SCSCL _scs_bus;
|
||||
|
||||
class ScsServo : public Servo {
|
||||
public:
|
||||
static inline const std::string _tag = "ScsServo";
|
||||
|
||||
ScsServo(int id, Vector2i angleLimit, const std::string& settingNs, const std::string& zeroPosKey,
|
||||
bool enablePwmMode = false)
|
||||
: _id(id), _setting_ns(settingNs), _zero_pos_key(zeroPosKey), _enable_pwm_mode(enablePwmMode)
|
||||
{
|
||||
set_angle_limit(angleLimit);
|
||||
|
||||
Settings settings(_setting_ns, false);
|
||||
_zero_pos = settings.GetInt(_zero_pos_key, 0);
|
||||
|
||||
mclog::tagInfo(_tag, "id: {} get zero pos: {} from settings", _id, _zero_pos);
|
||||
}
|
||||
|
||||
void set_angle_impl(int angle) override
|
||||
{
|
||||
int mapped_angle = _zero_pos + angle * 16 / 5 / 10; // 一步对应 0.3125度, 0.3125 = 5/16
|
||||
if (mapped_angle < 0) {
|
||||
mapped_angle = 0;
|
||||
}
|
||||
|
||||
// mclog::tagInfo(_tag, "id: {} mapped angle: {}", _id, mapped_angle);
|
||||
|
||||
check_mode(Mode::Position);
|
||||
_scs_bus.WritePos(_id, mapped_angle, 20, 0);
|
||||
}
|
||||
|
||||
int getCurrentAngle() override
|
||||
{
|
||||
int current_pos = _scs_bus.ReadPos(_id);
|
||||
int angle = (current_pos - _zero_pos) * 5 * 10 / 16;
|
||||
angle = uitk::clamp(angle, getAngleLimit().x, getAngleLimit().y);
|
||||
// mclog::tagInfo(_tag, "id: {} current pos: {} angle: {}", _id, current_pos, angle);
|
||||
return angle;
|
||||
}
|
||||
|
||||
bool isMoving() override
|
||||
{
|
||||
int moving = _scs_bus.ReadMove(_id);
|
||||
// mclog::tagInfo(_tag, "id: {} moving: {}", _id, moving);
|
||||
return moving != 0;
|
||||
}
|
||||
|
||||
void setTorqueEnabled(bool enabled) override
|
||||
{
|
||||
Servo::setTorqueEnabled(enabled);
|
||||
_scs_bus.EnableTorque(_id, enabled ? 1 : 0);
|
||||
// mclog::tagInfo(_tag, "id: {} set torque: {}", _id, enabled);
|
||||
}
|
||||
|
||||
bool getTorqueEnabled() override
|
||||
{
|
||||
int torque_enable = _scs_bus.ReadToqueEnable(_id);
|
||||
// mclog::tagInfo(_tag, "id: {} torque enable: {}", _id, torque_enable);
|
||||
return torque_enable > 0;
|
||||
}
|
||||
|
||||
void setCurrentAngleAsZero() override
|
||||
{
|
||||
_zero_pos = _scs_bus.ReadPos(_id);
|
||||
|
||||
Settings settings(_setting_ns, true);
|
||||
settings.SetInt(_zero_pos_key, _zero_pos);
|
||||
|
||||
mclog::tagInfo(_tag, "id: {} set zero pos: {} to settings", _id, _zero_pos);
|
||||
}
|
||||
|
||||
void rotate(int velocity) override
|
||||
{
|
||||
velocity = uitk::clamp(velocity, -1000, 1000);
|
||||
|
||||
if (!_enable_pwm_mode) {
|
||||
return;
|
||||
}
|
||||
|
||||
int mapped_velocity = map_range(velocity, 0, 1000, 0, 1023);
|
||||
|
||||
check_mode(Mode::PWM);
|
||||
_scs_bus.WritePWM(_id, mapped_velocity);
|
||||
}
|
||||
|
||||
private:
|
||||
enum class Mode { Position = 0, PWM = 1 };
|
||||
|
||||
int _id = -1;
|
||||
int _zero_pos = 0;
|
||||
std::string _setting_ns;
|
||||
std::string _zero_pos_key;
|
||||
Mode _current_mode = Mode::Position;
|
||||
bool _enable_pwm_mode;
|
||||
|
||||
uint32_t _last_true_move_ms = 0;
|
||||
const uint32_t STOP_DEBOUNCE_MS = 250;
|
||||
|
||||
void check_mode(Mode targetMode)
|
||||
{
|
||||
if (targetMode == _current_mode) {
|
||||
return;
|
||||
}
|
||||
|
||||
_scs_bus.SwitchMode(_id, static_cast<uint8_t>(targetMode));
|
||||
_current_mode = targetMode;
|
||||
}
|
||||
};
|
||||
|
||||
void Hal::servo_init()
|
||||
{
|
||||
mclog::tagInfo("HAL-Servo", "init");
|
||||
|
||||
_scs_bus.begin(UART_NUM_1, 1000000, 6, 7);
|
||||
|
||||
auto motion =
|
||||
std::make_unique<Motion>(std::make_unique<ScsServo>(1, Vector2i(-1280, 1280), "servo", "zero_pos_1", true),
|
||||
std::make_unique<ScsServo>(2, Vector2i(0, 900), "servo", "zero_pos_2"));
|
||||
motion->init();
|
||||
|
||||
GetStackChan().attachMotion(std::move(motion));
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user