You've already forked M5Unit-HEART
mirror of
https://github.com/m5stack/M5Unit-HEART.git
synced 2026-05-20 11:28:19 -07:00
Merge branch 'develop'
This commit is contained in:
@@ -12,28 +12,28 @@ on:
|
||||
branches:
|
||||
- '*'
|
||||
paths:
|
||||
- 'src/unit/**.cpp'
|
||||
- 'src/unit/**.hpp'
|
||||
- 'src/unit/**.h'
|
||||
- 'src/unit/**.c'
|
||||
- 'src/**.cpp'
|
||||
- 'src/**.hpp'
|
||||
- 'src/**.h'
|
||||
- 'src/**.c'
|
||||
- 'examples/UnitUnified/**.ino'
|
||||
- 'examples/UnitUnified/**.cpp'
|
||||
- 'examples/UnitUnified/**.hpp'
|
||||
- 'examples/UnitUnified/**.h'
|
||||
- 'examples/UnitUnified/**.c'
|
||||
- '**arduino-esp-v2-build-check.yml'
|
||||
- '.github/workflows/arduino-esp-v2-build-check.yml'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'src/unit/**.cpp'
|
||||
- 'src/unit/**.hpp'
|
||||
- 'src/unit/**.h'
|
||||
- 'src/unit/**.c'
|
||||
- 'src/**.cpp'
|
||||
- 'src/**.hpp'
|
||||
- 'src/**.h'
|
||||
- 'src/**.c'
|
||||
- 'examples/UnitUnified/**.ino'
|
||||
- 'examples/UnitUnified/**.cpp'
|
||||
- 'examples/UnitUnified/**.hpp'
|
||||
- 'examples/UnitUnified/**.h'
|
||||
- 'examples/UnitUnified/**.c'
|
||||
- '**arduino-esp-v2-build-check.yml'
|
||||
- '.github/workflows/arduino-esp-v2-build-check.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
defaults:
|
||||
@@ -46,13 +46,13 @@ concurrency:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: ${{ matrix.unit }}:${{ matrix.sketch }}:${{matrix.board}}@${{matrix.platform-version}}
|
||||
name: ${{ matrix.build-properties }}:${{ matrix.sketch }}:${{matrix.board}}@${{matrix.platform-version}}
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
timeout-minutes: 12
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
#max-parallel: 1
|
||||
max-parallel: 20
|
||||
matrix:
|
||||
platform-url:
|
||||
- https://espressif.github.io/arduino-esp32/package_esp32_index.json
|
||||
@@ -60,8 +60,8 @@ jobs:
|
||||
sketch:
|
||||
- PlotToSerial
|
||||
|
||||
unit:
|
||||
- UnitHeart
|
||||
build-properties:
|
||||
- "-DUSING_UNIT_HEART"
|
||||
|
||||
board:
|
||||
- m5stack-atom
|
||||
@@ -84,29 +84,54 @@ jobs:
|
||||
include:
|
||||
# Specific sketches
|
||||
- sketch: GraphicalMeter
|
||||
unit: UnitHeart
|
||||
platform-url: https://espressif.github.io/arduino-esp32/package_esp32_index.json
|
||||
platform: esp32
|
||||
archi: esp32
|
||||
platform-version: 2.0.17
|
||||
board: m5stack-core-esp32
|
||||
build-properties: "-DUSING_UNIT_HEART"
|
||||
- sketch: PlotToSerial
|
||||
platform-url: https://espressif.github.io/arduino-esp32/package_esp32_index.json
|
||||
platform: esp32
|
||||
archi: esp32
|
||||
platform-version: 2.0.17
|
||||
board: m5stack-coreink
|
||||
build-properties: "-DUSING_HAT_HEART"
|
||||
- sketch: DualSensor
|
||||
platform-url: https://espressif.github.io/arduino-esp32/package_esp32_index.json
|
||||
platform: esp32
|
||||
archi: esp32
|
||||
platform-version: 2.0.17
|
||||
board: m5stack-coreink
|
||||
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
|
||||
# Build
|
||||
- name: Prepare libraries list
|
||||
id: libs
|
||||
run: |
|
||||
{
|
||||
echo "yaml<<EOF"
|
||||
echo "$REQUIRED_LIBRARIES" | tr ',' '\n' | while read -r lib; do
|
||||
echo "- name: $lib"
|
||||
done
|
||||
echo "- source-path: ./"
|
||||
echo "EOF"
|
||||
} >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Compile examples
|
||||
uses: ArminJo/arduino-test-compile@master
|
||||
uses: arduino/compile-sketches@v1
|
||||
with:
|
||||
arduino-board-fqbn: ${{ matrix.platform }}:${{ matrix.archi }}:${{ matrix.board }}
|
||||
arduino-platform: ${{ matrix.platform }}:${{ matrix.archi }}@${{ matrix.platform-version }}
|
||||
platform-url: ${{ matrix.platform-url }}
|
||||
required-libraries: ${{ env.REQUIRED_LIBRARIES }}
|
||||
extra-arduino-cli-args: ${{ matrix.cli-args }}
|
||||
#build-properties: ${{ toJson(matrix.build-properties) }}
|
||||
sketch-names: ${{ matrix.sketch }}.ino
|
||||
sketch-names-find-start: ${{ env.SKETCH_NAMES_FIND_START }}/${{ matrix.unit }}
|
||||
#sketches-exclude: ${{ matrix.sketches-exclude }}
|
||||
fqbn: ${{ matrix.platform }}:${{ matrix.archi }}:${{ matrix.board }}
|
||||
platforms: |
|
||||
- name: ${{ matrix.platform }}:${{ matrix.archi }}
|
||||
source-url: ${{ matrix.platform-url }}
|
||||
version: ${{ matrix.platform-version }}
|
||||
libraries: ${{ steps.libs.outputs.yaml }}
|
||||
sketch-paths: |
|
||||
- ${{ env.SKETCH_NAMES_FIND_START }}/${{ matrix.sketch }}
|
||||
cli-compile-flags: |
|
||||
- --build-property
|
||||
- build.extra_flags=${{ matrix.build-properties }}
|
||||
|
||||
@@ -12,28 +12,28 @@ on:
|
||||
branches:
|
||||
- '*'
|
||||
paths:
|
||||
- 'src/unit/**.cpp'
|
||||
- 'src/unit/**.hpp'
|
||||
- 'src/unit/**.h'
|
||||
- 'src/unit/**.c'
|
||||
- 'src/**.cpp'
|
||||
- 'src/**.hpp'
|
||||
- 'src/**.h'
|
||||
- 'src/**.c'
|
||||
- 'examples/UnitUnified/**.ino'
|
||||
- 'examples/UnitUnified/**.cpp'
|
||||
- 'examples/UnitUnified/**.hpp'
|
||||
- 'examples/UnitUnified/**.h'
|
||||
- 'examples/UnitUnified/**.c'
|
||||
- '**arduino-esp-v3-build-check.yml'
|
||||
- '.github/workflows/arduino-esp-v3-build-check.yml'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'src/unit/**.cpp'
|
||||
- 'src/unit/**.hpp'
|
||||
- 'src/unit/**.h'
|
||||
- 'src/unit/**.c'
|
||||
- 'src/**.cpp'
|
||||
- 'src/**.hpp'
|
||||
- 'src/**.h'
|
||||
- 'src/**.c'
|
||||
- 'examples/UnitUnified/**.ino'
|
||||
- 'examples/UnitUnified/**.cpp'
|
||||
- 'examples/UnitUnified/**.hpp'
|
||||
- 'examples/UnitUnified/**.h'
|
||||
- 'examples/UnitUnified/**.c'
|
||||
- '**arduino-esp-v3-build-check.yml'
|
||||
- '.github/workflows/arduino-esp-v3-build-check.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
defaults:
|
||||
@@ -46,13 +46,13 @@ concurrency:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: ${{ matrix.unit }}:${{ matrix.sketch }}:${{matrix.board}}@${{matrix.platform-version}}
|
||||
name: ${{ matrix.build-properties }}:${{ matrix.sketch }}:${{matrix.board}}@${{matrix.platform-version}}
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
timeout-minutes: 12
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
#max-parallel: 1
|
||||
max-parallel: 20
|
||||
matrix:
|
||||
platform-url:
|
||||
- https://espressif.github.io/arduino-esp32/package_esp32_index.json
|
||||
@@ -60,19 +60,21 @@ jobs:
|
||||
sketch:
|
||||
- PlotToSerial
|
||||
|
||||
unit:
|
||||
- UnitHeart
|
||||
build-properties:
|
||||
- "-DUSING_UNIT_HEART"
|
||||
|
||||
board:
|
||||
- arduino_nesso_n1
|
||||
- m5stack_atom
|
||||
- m5stack_atoms3
|
||||
- m5stack_capsule
|
||||
# - m5stack_cardputer
|
||||
- m5stack_cardputer
|
||||
- m5stack_core
|
||||
- m5stack_core2
|
||||
- m5stack_coreink
|
||||
- m5stack_cores3
|
||||
- m5stack_dial
|
||||
- m5stack_dinmeter
|
||||
- m5stack_fire
|
||||
- m5stack_nanoc6
|
||||
- m5stack_paper
|
||||
@@ -84,13 +86,14 @@ jobs:
|
||||
# - m5stack_stickc
|
||||
- m5stack_stickc_plus
|
||||
- m5stack_stickc_plus2
|
||||
- m5stack_tab5
|
||||
# - m5stack_timer_cam
|
||||
# - m5stack_tough
|
||||
# - m5stack_unit_cam
|
||||
# - m5stack_unit_cams3
|
||||
|
||||
platform-version:
|
||||
- 3.0.4
|
||||
- 3.3.6
|
||||
|
||||
platform:
|
||||
- esp32
|
||||
@@ -100,70 +103,84 @@ jobs:
|
||||
|
||||
include:
|
||||
# Specific sketches
|
||||
# HAT
|
||||
- sketch: PlotToSerial
|
||||
unit: HatHeart
|
||||
platform-url: https://espressif.github.io/arduino-esp32/package_esp32_index.json
|
||||
platform: esp32
|
||||
archi: esp32
|
||||
platform-version: 3.0.4
|
||||
platform-version: 3.3.6
|
||||
board: m5stack_stickc_plus
|
||||
build-properties: "-DUSING_HAT_HEART"
|
||||
- sketch: PlotToSerial
|
||||
unit: HatHeart
|
||||
platform-url: https://espressif.github.io/arduino-esp32/package_esp32_index.json
|
||||
platform: esp32
|
||||
archi: esp32
|
||||
platform-version: 3.0.4
|
||||
platform-version: 3.3.6
|
||||
board: m5stack_stickc_plus2
|
||||
- sketch: GraphicalMeter
|
||||
unit: UnitHeart
|
||||
build-properties: "-DUSING_HAT_HEART"
|
||||
- sketch: PlotToSerial
|
||||
platform-url: https://espressif.github.io/arduino-esp32/package_esp32_index.json
|
||||
platform: esp32
|
||||
archi: esp32
|
||||
platform-version: 3.0.4
|
||||
platform-version: 3.3.6
|
||||
board: m5stack_coreink
|
||||
build-properties: "-DUSING_HAT_HEART"
|
||||
- sketch: PlotToSerial
|
||||
platform-url: https://espressif.github.io/arduino-esp32/package_esp32_index.json
|
||||
platform: esp32
|
||||
archi: esp32
|
||||
platform-version: 3.3.6
|
||||
board: arduino_nesso_n1
|
||||
build-properties: "-DUSING_HAT_HEART"
|
||||
#GraphicalMeter
|
||||
- sketch: GraphicalMeter
|
||||
platform-url: https://espressif.github.io/arduino-esp32/package_esp32_index.json
|
||||
platform: esp32
|
||||
archi: esp32
|
||||
platform-version: 3.3.6
|
||||
board: m5stack_core
|
||||
build-properties: "-DUSING_UNIT_HEART"
|
||||
- sketch: GraphicalMeter
|
||||
unit: HatHeart
|
||||
platform-url: https://espressif.github.io/arduino-esp32/package_esp32_index.json
|
||||
platform: esp32
|
||||
archi: esp32
|
||||
platform-version: 3.0.4
|
||||
board: m5stack_stickc_plus
|
||||
- sketch: GraphicalMeter
|
||||
unit: HatHeart
|
||||
platform-url: https://espressif.github.io/arduino-esp32/package_esp32_index.json
|
||||
platform: esp32
|
||||
archi: esp32
|
||||
platform-version: 3.0.4
|
||||
platform-version: 3.3.6
|
||||
board: m5stack_stickc_plus2
|
||||
build-properties: "-DUSING_HAT_HEART"
|
||||
- sketch: DualSensor
|
||||
platform-url: https://espressif.github.io/arduino-esp32/package_esp32_index.json
|
||||
platform: esp32
|
||||
archi: esp32
|
||||
platform-version: 3.0.4
|
||||
board: m5stack_stickc_plus
|
||||
- sketch: DualSensor
|
||||
platform-url: https://espressif.github.io/arduino-esp32/package_esp32_index.json
|
||||
platform: esp32
|
||||
archi: esp32
|
||||
platform-version: 3.0.4
|
||||
platform-version: 3.3.6
|
||||
board: m5stack_stickc_plus2
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
|
||||
# Build
|
||||
- name: Prepare libraries list
|
||||
id: libs
|
||||
run: |
|
||||
{
|
||||
echo "yaml<<EOF"
|
||||
echo "$REQUIRED_LIBRARIES" | tr ',' '\n' | while read -r lib; do
|
||||
echo "- name: $lib"
|
||||
done
|
||||
echo "- source-path: ./"
|
||||
echo "EOF"
|
||||
} >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Compile examples
|
||||
uses: ArminJo/arduino-test-compile@master
|
||||
uses: arduino/compile-sketches@v1
|
||||
with:
|
||||
arduino-board-fqbn: ${{ matrix.platform }}:${{ matrix.archi }}:${{ matrix.board }}
|
||||
arduino-platform: ${{ matrix.platform }}:${{ matrix.archi }}@${{ matrix.platform-version }}
|
||||
platform-url: ${{ matrix.platform-url }}
|
||||
required-libraries: ${{ env.REQUIRED_LIBRARIES }}
|
||||
extra-arduino-cli-args: ${{ matrix.cli-args }}
|
||||
#build-properties: ${{ toJson(matrix.build-properties) }}
|
||||
sketch-names: ${{ matrix.sketch }}.ino
|
||||
sketch-names-find-start: ${{ env.SKETCH_NAMES_FIND_START }}/${{ matrix.unit }}
|
||||
#sketches-exclude: ${{ matrix.sketches-exclude }}
|
||||
fqbn: ${{ matrix.platform }}:${{ matrix.archi }}:${{ matrix.board }}
|
||||
platforms: |
|
||||
- name: ${{ matrix.platform }}:${{ matrix.archi }}
|
||||
source-url: ${{ matrix.platform-url }}
|
||||
version: ${{ matrix.platform-version }}
|
||||
libraries: ${{ steps.libs.outputs.yaml }}
|
||||
sketch-paths: |
|
||||
- ${{ env.SKETCH_NAMES_FIND_START }}/${{ matrix.sketch }}
|
||||
cli-compile-flags: |
|
||||
- --build-property
|
||||
- build.extra_flags=${{ matrix.build-properties }}
|
||||
|
||||
@@ -12,28 +12,28 @@ on:
|
||||
branches:
|
||||
- '*'
|
||||
paths:
|
||||
- 'src/unit/**.cpp'
|
||||
- 'src/unit/**.hpp'
|
||||
- 'src/unit/**.h'
|
||||
- 'src/unit/**.c'
|
||||
- 'src/**.cpp'
|
||||
- 'src/**.hpp'
|
||||
- 'src/**.h'
|
||||
- 'src/**.c'
|
||||
- 'examples/UnitUnified/**.ino'
|
||||
- 'examples/UnitUnified/**.cpp'
|
||||
- 'examples/UnitUnified/**.hpp'
|
||||
- 'examples/UnitUnified/**.h'
|
||||
- 'examples/UnitUnified/**.c'
|
||||
- '**arduino-m5-build-check.yml'
|
||||
- '.github/workflows/arduino-m5-build-check.yml'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'src/unit/**.cpp'
|
||||
- 'src/unit/**.hpp'
|
||||
- 'src/unit/**.h'
|
||||
- 'src/unit/**.c'
|
||||
- 'src/**.cpp'
|
||||
- 'src/**.hpp'
|
||||
- 'src/**.h'
|
||||
- 'src/**.c'
|
||||
- 'examples/UnitUnified/**.ino'
|
||||
- 'examples/UnitUnified/**.cpp'
|
||||
- 'examples/UnitUnified/**.hpp'
|
||||
- 'examples/UnitUnified/**.h'
|
||||
- 'examples/UnitUnified/**.c'
|
||||
- '**arduino-m5-build-check.yml'
|
||||
- '.github/workflows/arduino-m5-build-check.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
defaults:
|
||||
@@ -46,13 +46,13 @@ concurrency:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: ${{ matrix.unit }}:${{ matrix.sketch }}:${{matrix.board}}@${{matrix.platform-version}}
|
||||
name: ${{ matrix.build-properties }}:${{ matrix.sketch }}:${{matrix.board}}@${{matrix.platform-version}}
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
timeout-minutes: 12
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
# max-parallel: 1
|
||||
max-parallel: 20
|
||||
matrix:
|
||||
platform-url:
|
||||
- https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/arduino/package_m5stack_index.json
|
||||
@@ -60,15 +60,17 @@ jobs:
|
||||
sketch:
|
||||
- PlotToSerial
|
||||
|
||||
unit:
|
||||
- UnitHeart
|
||||
build-properties:
|
||||
- "-DUSING_UNIT_HEART"
|
||||
|
||||
board:
|
||||
- arduino_nesso_n1
|
||||
- m5stack_atom
|
||||
- m5stack_atoms3
|
||||
- m5stack_atoms3r
|
||||
- m5stack_capsule
|
||||
# - m5stack_cardputer
|
||||
- m5stack_cardputer
|
||||
# - m5stack_chain_dualkey
|
||||
- m5stack_core
|
||||
- m5stack_core2
|
||||
- m5stack_coreink
|
||||
@@ -76,22 +78,30 @@ jobs:
|
||||
- m5stack_dial
|
||||
- m5stack_dinmeter
|
||||
- m5stack_fire
|
||||
- m5stack_nano_c6
|
||||
# - m5stack_nano_h2
|
||||
- m5stack_paper
|
||||
- m5stack_papers3
|
||||
# - m5stack_poe_cam
|
||||
# - m5stack_powerhub
|
||||
# - m5stack_stamp_c3
|
||||
# - m5stack_stamp_pico
|
||||
- m5stack_stamp_s3
|
||||
# - m5stack_stamplc
|
||||
# - m5stack_station
|
||||
# - m5stack_stickc
|
||||
- m5stack_stickc
|
||||
- m5stack_stickc_plus
|
||||
- m5stack_stickc_plus2
|
||||
- m5stack_sticks3
|
||||
- m5stack_tab5
|
||||
# - m5stack_timer_cam
|
||||
# - m5stack_tough
|
||||
# - m5stack_unit_c6l
|
||||
# - m5stack_unit_cam
|
||||
# - m5stack_unit_cams3
|
||||
|
||||
platform-version:
|
||||
- 2.1.2
|
||||
- 3.2.5
|
||||
|
||||
platform:
|
||||
- m5stack
|
||||
@@ -101,71 +111,93 @@ jobs:
|
||||
|
||||
include:
|
||||
# Specific sketches
|
||||
# HAT
|
||||
- sketch: PlotToSerial
|
||||
unit: HatHeart
|
||||
platform-url: https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/arduino/package_m5stack_index.json
|
||||
platform: m5stack
|
||||
archi: esp32
|
||||
platform-version: 2.1.2
|
||||
platform-version: 3.2.5
|
||||
board: m5stack_stickc_plus
|
||||
build-properties: "-DUSING_HAT_HEART"
|
||||
- sketch: PlotToSerial
|
||||
unit: HatHeart
|
||||
platform-url: https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/arduino/package_m5stack_index.json
|
||||
platform: m5stack
|
||||
archi: esp32
|
||||
platform-version: 2.1.2
|
||||
platform-version: 3.2.5
|
||||
board: m5stack_stickc_plus2
|
||||
- sketch: GraphicalMeter
|
||||
unit: UnitHeart
|
||||
build-properties: "-DUSING_HAT_HEART"
|
||||
- sketch: PlotToSerial
|
||||
platform-url: https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/arduino/package_m5stack_index.json
|
||||
platform: m5stack
|
||||
archi: esp32
|
||||
platform-version: 2.1.2
|
||||
platform-version: 3.2.5
|
||||
board: m5stack_sticks3
|
||||
build-properties: "-DUSING_HAT_HEART"
|
||||
- sketch: PlotToSerial
|
||||
platform-url: https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/arduino/package_m5stack_index.json
|
||||
platform: m5stack
|
||||
archi: esp32
|
||||
platform-version: 3.2.5
|
||||
board: m5stack_coreink
|
||||
build-properties: "-DUSING_HAT_HEART"
|
||||
- sketch: PlotToSerial
|
||||
platform-url: https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/arduino/package_m5stack_index.json
|
||||
platform: m5stack
|
||||
archi: esp32
|
||||
platform-version: 3.2.5
|
||||
board: arduino_nesso_n1
|
||||
build-properties: "-DUSING_HAT_HEART"
|
||||
# GraphicalMeter
|
||||
- sketch: GraphicalMeter
|
||||
platform-url: https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/arduino/package_m5stack_index.json
|
||||
platform: m5stack
|
||||
archi: esp32
|
||||
platform-version: 3.2.5
|
||||
board: m5stack_core
|
||||
build-properties: "-DUSING_UNIT_HEART"
|
||||
- sketch: GraphicalMeter
|
||||
unit: HatHeart
|
||||
platform-url: https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/arduino/package_m5stack_index.json
|
||||
platform: m5stack
|
||||
archi: esp32
|
||||
platform-version: 2.1.2
|
||||
board: m5stack_stickc_plus
|
||||
- sketch: GraphicalMeter
|
||||
unit: HatHeart
|
||||
platform-url: https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/arduino/package_m5stack_index.json
|
||||
platform: m5stack
|
||||
archi: esp32
|
||||
platform-version: 2.1.2
|
||||
platform-version: 3.2.5
|
||||
board: m5stack_stickc_plus2
|
||||
build-properties: "-DUSING_HAT_HEART"
|
||||
# DualSensor
|
||||
- sketch: DualSensor
|
||||
platform-url: https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/arduino/package_m5stack_index.json
|
||||
platform: m5stack
|
||||
archi: esp32
|
||||
platform-version: 2.1.2
|
||||
board: m5stack_stickc_plus
|
||||
- sketch: DualSensor
|
||||
platform-url: https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/arduino/package_m5stack_index.json
|
||||
platform: m5stack
|
||||
archi: esp32
|
||||
platform-version: 2.1.2
|
||||
platform-version: 3.2.5
|
||||
board: m5stack_stickc_plus2
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
|
||||
# Build
|
||||
- name: Prepare libraries list
|
||||
id: libs
|
||||
run: |
|
||||
{
|
||||
echo "yaml<<EOF"
|
||||
echo "$REQUIRED_LIBRARIES" | tr ',' '\n' | while read -r lib; do
|
||||
echo "- name: $lib"
|
||||
done
|
||||
echo "- source-path: ./"
|
||||
echo "EOF"
|
||||
} >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Compile examples
|
||||
uses: ArminJo/arduino-test-compile@master
|
||||
uses: arduino/compile-sketches@v1
|
||||
with:
|
||||
arduino-board-fqbn: ${{ matrix.platform }}:${{ matrix.archi }}:${{ matrix.board }}
|
||||
arduino-platform: ${{ matrix.platform }}:${{ matrix.archi }}@${{ matrix.platform-version }}
|
||||
platform-url: ${{ matrix.platform-url }}
|
||||
required-libraries: ${{ env.REQUIRED_LIBRARIES }}
|
||||
extra-arduino-cli-args: ${{ matrix.cli-args }}
|
||||
#build-properties: ${{ toJson(matrix.build-properties) }}
|
||||
sketch-names: ${{ matrix.sketch }}.ino
|
||||
sketch-names-find-start: ${{ env.SKETCH_NAMES_FIND_START }}/${{ matrix.unit }}
|
||||
#sketches-exclude: ${{ matrix.sketches-exclude }}
|
||||
fqbn: ${{ matrix.platform }}:${{ matrix.archi }}:${{ matrix.board }}
|
||||
platforms: |
|
||||
- name: ${{ matrix.platform }}:${{ matrix.archi }}
|
||||
source-url: ${{ matrix.platform-url }}
|
||||
version: ${{ matrix.platform-version }}
|
||||
libraries: ${{ steps.libs.outputs.yaml }}
|
||||
sketch-paths: |
|
||||
- ${{ env.SKETCH_NAMES_FIND_START }}/${{ matrix.sketch }}
|
||||
cli-compile-flags: |
|
||||
- --build-property
|
||||
- build.extra_flags=${{ matrix.build-properties }}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ on:
|
||||
- '**.h'
|
||||
- '**.c'
|
||||
- '**.inl'
|
||||
- '**clang-format-check.yml'
|
||||
- '.github/workflows/clang-format-check.yml'
|
||||
- '**.clang-format'
|
||||
pull_request:
|
||||
paths:
|
||||
@@ -27,7 +27,7 @@ on:
|
||||
- '**.h'
|
||||
- '**.c'
|
||||
- '**.inl'
|
||||
- '**clang-format-check.yml'
|
||||
- '.github/workflows/clang-format-check.yml'
|
||||
- '**.clang-format'
|
||||
workflow_dispatch:
|
||||
|
||||
@@ -55,11 +55,9 @@ jobs:
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
|
||||
- name: Run clang-format style check for C/C++/Protobuf programs.
|
||||
uses: jidicula/clang-format-action@v4.10.2 # Using include-regex 10.x or later
|
||||
uses: jidicula/clang-format-action@v4.16.0
|
||||
with:
|
||||
clang-format-version: '13'
|
||||
check-path: ${{ matrix.path['check'] }}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
name: Deploy Doxygen docuemnt on GitHub Pages
|
||||
name: Deploy Doxygen document on GitHub Pages
|
||||
on: [release, workflow_dispatch]
|
||||
# branches:
|
||||
# - main
|
||||
# - master
|
||||
permissions:
|
||||
contents: write
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
@@ -8,30 +8,30 @@ on:
|
||||
branches:
|
||||
- '*'
|
||||
paths:
|
||||
- 'src/unit/**.cpp'
|
||||
- 'src/unit/**.hpp'
|
||||
- 'src/unit/**.h'
|
||||
- 'src/unit/**.c'
|
||||
- 'src/**.cpp'
|
||||
- 'src/**.hpp'
|
||||
- 'src/**.h'
|
||||
- 'src/**.c'
|
||||
- 'examples/UnitUnified/**.ino'
|
||||
- 'examples/UnitUnified/**.cpp'
|
||||
- 'examples/UnitUnified/**.hpp'
|
||||
- 'examples/UnitUnified/**.h'
|
||||
- 'examples/UnitUnified/**.c'
|
||||
- '/platformio-build-check.yml'
|
||||
- '**platformio.ini'
|
||||
- '.github/workflows/platformio-build-check.yml'
|
||||
- 'platformio.ini'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'src/unit/**.cpp'
|
||||
- 'src/unit/**.hpp'
|
||||
- 'src/unit/**.h'
|
||||
- 'src/unit/**.c'
|
||||
- 'src/**.cpp'
|
||||
- 'src/**.hpp'
|
||||
- 'src/**.h'
|
||||
- 'src/**.c'
|
||||
- 'examples/UnitUnified/**.ino'
|
||||
- 'examples/UnitUnified/**.cpp'
|
||||
- 'examples/UnitUnified/**.hpp'
|
||||
- 'examples/UnitUnified/**.h'
|
||||
- 'examples/UnitUnified/**.c'
|
||||
- '**/platformio-build-check.yml'
|
||||
- '**platformio.ini'
|
||||
- '.github/workflows/platformio-build-check.yml'
|
||||
- 'platformio.ini'
|
||||
workflow_dispatch:
|
||||
|
||||
defaults:
|
||||
@@ -46,11 +46,11 @@ jobs:
|
||||
build:
|
||||
name: ${{ matrix.unit }}:${{ matrix.example }}@${{ matrix.board }}:${{ matrix.framework }}:${{ matrix.espressif32 }}
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
timeout-minutes: 12
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
#max-parallel: 1
|
||||
max-parallel: 20
|
||||
|
||||
matrix:
|
||||
example:
|
||||
@@ -66,55 +66,28 @@ jobs:
|
||||
- Fire
|
||||
- StampS3
|
||||
- Dial
|
||||
- AtomMatrix
|
||||
- Atom
|
||||
- AtomS3
|
||||
- AtomS3R
|
||||
- NanoC6
|
||||
- StickCPlus
|
||||
- StickCPlus2
|
||||
- StickS3
|
||||
- Paper
|
||||
- CoreInk
|
||||
- Cardputer
|
||||
- Tab5
|
||||
- NessoN1
|
||||
|
||||
framework:
|
||||
- Arduino
|
||||
|
||||
espressif32:
|
||||
- latest
|
||||
# - '5_4_0'
|
||||
# - '4_4_0'
|
||||
|
||||
# exclude:
|
||||
# - board: CoreS3
|
||||
# espressif32: '5_4_0'
|
||||
# - board: CoreS3
|
||||
# espressif32: '4_4_0'
|
||||
# - board: StampS3
|
||||
# espressif32: '5_4_0'
|
||||
# - board: StampS3
|
||||
# espressif32: '4_4_0'
|
||||
# - board: AtomS3
|
||||
# espressif32: '5_4_0'
|
||||
# - board: AtomS3
|
||||
# espressif32: '4_4_0'
|
||||
# - board: Dial
|
||||
# espressif32: '5_4_0'
|
||||
# - board: Dial
|
||||
# espressif32: '4_4_0'
|
||||
# - board: NanoC6
|
||||
# espressif32: '5_4_0'
|
||||
# - board: NanoC6
|
||||
# espressif32: '4_4_0'
|
||||
# - board: StickCPlus
|
||||
# espressif32: '5_4_0'
|
||||
# - board: StickCPlus
|
||||
# espressif32: '4_4_0'
|
||||
# - board: Paper
|
||||
# espressif32: '5_4_0'
|
||||
# - board: Paper
|
||||
# espressif32: '4_4_0'
|
||||
|
||||
include:
|
||||
# Specific sketches
|
||||
# Hat
|
||||
- example: PlotToSerial
|
||||
unit: HatHeart
|
||||
board: StickCPlus
|
||||
@@ -125,36 +98,49 @@ jobs:
|
||||
board: StickCPlus2
|
||||
framework: Arduino
|
||||
espressif32: latest
|
||||
- example: PlotToSerial
|
||||
unit: HatHeart
|
||||
board: StickS3
|
||||
framework: Arduino
|
||||
espressif32: latest
|
||||
- example: PlotToSerial
|
||||
unit: HatHeart
|
||||
board: CoreInk
|
||||
framework: Arduino
|
||||
espressif32: latest
|
||||
- example: PlotToSerial
|
||||
unit: HatHeart
|
||||
board: NessoN1
|
||||
framework: Arduino
|
||||
espressif32: latest
|
||||
# GraphicalMeter
|
||||
- example: GraphicalMeter
|
||||
unit: UnitHeart
|
||||
board: Core
|
||||
framework: Arduino
|
||||
espressif32: latest
|
||||
- example: GraphicalMeter
|
||||
unit: HatHeart
|
||||
board: StickCPlus
|
||||
framework: Arduino
|
||||
espressif32: latest
|
||||
- example: GraphicalMeter
|
||||
unit: HatHeart
|
||||
board: StickCPlus2
|
||||
framework: Arduino
|
||||
espressif32: latest
|
||||
- example: DualSensor
|
||||
board: StickCPlus
|
||||
framework: Arduino
|
||||
espressif32: latest
|
||||
# DualSensor
|
||||
- example: DualSensor
|
||||
board: StickCPlus2
|
||||
framework: Arduino
|
||||
espressif32: latest
|
||||
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
python-version: '3.10'
|
||||
|
||||
- name: Install intelhex
|
||||
run: pip install intelhex
|
||||
|
||||
- name: Build examples
|
||||
uses: karniv00l/platformio-run-action@v1
|
||||
|
||||
+21
@@ -30,3 +30,24 @@
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
|
||||
# Doxygen
|
||||
docs/html/
|
||||
|
||||
# PlatformIO
|
||||
.pio/
|
||||
|
||||
# IDE
|
||||
.vscode/
|
||||
|
||||
# macOS
|
||||
.DS_Store
|
||||
|
||||
# Temporary
|
||||
tmp/
|
||||
|
||||
# Secrets
|
||||
.env*
|
||||
*.pem
|
||||
*.key
|
||||
*.cert
|
||||
|
||||
@@ -2,26 +2,20 @@
|
||||
|
||||
## Overview
|
||||
|
||||
Library for UnitHEART [M5UnitUnified](https://github.com/m5stack/M5UnitUnified).
|
||||
Library for UnitHEART using [M5UnitUnified](https://github.com/m5stack/M5UnitUnified).
|
||||
M5UnitUnified is a library for unified handling of various M5 units products.
|
||||
|
||||
### SKU:U029
|
||||
|
||||
HEART is built using the MAX30100 chipset.
|
||||
|
||||
MAX30100 is a complete pulse oximetry and heart-rate sensor system solution designed for the demanding requirements of wearable devices.
|
||||
|
||||
The MAX30100 provides very small total solution size without sacrificing optical or electrical performance. Minimal external hardware components are needed for integration into a wearable device.
|
||||
Unit Heart is a blood oxygen and heart rate sensor. Integrated MAX30100, it offers a complete pulse oximeter and heart rate sensor system solution. This is a non-invasive blood oxygen and heart rate sensor, integrating two infrared light-emitting diodes and a photodetector. The detection principle is to use infrared LEDs to illuminate and detect the proportion of red blood cells carrying oxygen versus those not carrying oxygen, thereby obtaining the oxygen content.
|
||||
|
||||
### SKU:U118
|
||||
|
||||
HEART RATE HAT is a blood oxygen heart rate sensor. Integrate MAX30102 to provide a complete pulse oximeter and heart rate sensor system solution. This is a non-pluggable blood oxygen heart rate sensor. The sensor uses I2C communication interface, internally integrates infrared light-emitting diodes, photo-detectors, optical components and low-noise electronic equipment. A certain amount of ambient light suppression function can make the measurement results more accurate. .
|
||||
Hat Heart is a blood oxygen and heart rate sensor. It integrates MAX30102, providing a complete pulse oximeter and heart rate sensor system solution. This is a non-invasive blood oxygen and heart rate sensor. Its detection principle is based on infrared LED light illumination, which detects the ratio of oxygenated to deoxygenated red blood cells to determine blood oxygen levels. The sensor uses an I2C communication interface and integrates infrared LEDs, photodetectors, optical components, and low-noise electronics, with some ambient light suppression for more accurate measurements.
|
||||
|
||||
|
||||
## Related Link
|
||||
See also examples using conventional methods here.
|
||||
|
||||
- [Unit Heart & Datasheet](https://docs.m5stack.com/ja/unit/heart)
|
||||
- [Unit Heart & Datasheet](https://docs.m5stack.com/en/unit/heart)
|
||||
- [Hat Heart & Datasheet](https://docs.m5stack.com/en/hat/hat_heart_rate)
|
||||
|
||||
## Required Libraries:
|
||||
@@ -32,12 +26,29 @@ See also examples using conventional methods here.
|
||||
|
||||
## License
|
||||
|
||||
- [M5Unit-HEART- MIT](LICENSE)
|
||||
- [M5Unit-HEART - MIT](LICENSE)
|
||||
|
||||
|
||||
## Examples
|
||||
See also [examples/UnitUnified](examples/UnitUnified)
|
||||
|
||||
### For ArduinoIDE settings
|
||||
You must choose a define symbol for the unit you will use.
|
||||
(Rewrite source or specify with compile options)
|
||||
|
||||
- PlotToSerial / GraphicalMeter
|
||||
```cpp
|
||||
// *************************************************************
|
||||
// Choose one define symbol to match the unit you are using
|
||||
// *************************************************************
|
||||
#if !defined(USING_UNIT_HEART) && !defined(USING_HAT_HEART)
|
||||
// For UnitHeart (U029)
|
||||
// #define USING_UNIT_HEART
|
||||
// For HatHeart (U118)
|
||||
// #define USING_HAT_HEART
|
||||
#endif
|
||||
```
|
||||
|
||||
## Doxygen document
|
||||
[GitHub Pages](https://m5stack.github.io/M5Unit-HEART/)
|
||||
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@ DOXYFILE_ENCODING = UTF-8
|
||||
# title of most generated pages and in a few other places.
|
||||
# The default value is: My Project.
|
||||
|
||||
PROJECT_NAME = M5Unit-HEART
|
||||
PROJECT_NAME = "M5Unit-HEART"
|
||||
|
||||
# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
|
||||
# could be handy for archiving the generated documentation or if some version
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Please execute on repositry root
|
||||
# Please execute on repository root
|
||||
|
||||
## Get version from library.properties
|
||||
## Get git rev of HEAD
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <M5UnitUnified.h>
|
||||
#include <M5UnitUnifiedHEART.h>
|
||||
#include <Wire.h>
|
||||
#include <M5HAL.hpp>
|
||||
#include "../src/view.hpp"
|
||||
|
||||
namespace {
|
||||
@@ -19,6 +20,30 @@ m5::unit::UnitHeart unit;
|
||||
m5::unit::HatHeart hat;
|
||||
|
||||
View* view[2]{};
|
||||
bool is_epd_panel{};
|
||||
|
||||
struct I2cPins {
|
||||
int sda;
|
||||
int scl;
|
||||
};
|
||||
|
||||
I2cPins get_hat_i2c_pins(const m5::board_t board)
|
||||
{
|
||||
switch (board) {
|
||||
case m5::board_t::board_M5StickC:
|
||||
case m5::board_t::board_M5StickCPlus:
|
||||
case m5::board_t::board_M5StickCPlus2:
|
||||
return {0, 26};
|
||||
case m5::board_t::board_M5StickS3:
|
||||
return {8, 0};
|
||||
case m5::board_t::board_M5StackCoreInk:
|
||||
return {25, 26};
|
||||
case m5::board_t::board_ArduinoNessoN1:
|
||||
return {6, 7};
|
||||
default:
|
||||
return {-1, -1};
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -32,39 +57,73 @@ void setup()
|
||||
m5cfg.internal_imu = false; // Disable internal IMU
|
||||
m5cfg.internal_rtc = false; // Disable internal RTC
|
||||
M5.begin(m5cfg);
|
||||
M5.setTouchButtonHeightByRatio(100);
|
||||
is_epd_panel = lcd.isEPD();
|
||||
|
||||
auto board = M5.getBoard();
|
||||
if (board != m5::board_t::board_M5StickCPlus && board != m5::board_t::board_M5StickCPlus2) {
|
||||
M5_LOGE("Example for StickCPlus/CPlus2");
|
||||
lcd.clear(TFT_RED);
|
||||
while (true) {
|
||||
m5::utility::delay(10000);
|
||||
}
|
||||
}
|
||||
const auto board_type = M5.getBoard();
|
||||
|
||||
// The screen shall be in landscape mode
|
||||
if (lcd.height() > lcd.width()) {
|
||||
lcd.setRotation(1);
|
||||
}
|
||||
|
||||
// Setup required to use HatHEART
|
||||
pinMode(25, INPUT_PULLUP);
|
||||
pinMode(26, OUTPUT);
|
||||
const auto pins = get_hat_i2c_pins(board_type);
|
||||
M5_LOGI("getHatPin: SDA:%u SCL:%u", pins.sda, pins.scl);
|
||||
if (pins.sda < 0 || pins.scl < 0) {
|
||||
M5_LOGE("Hat port not exists");
|
||||
lcd.fillScreen(TFT_RED);
|
||||
while (true) {
|
||||
m5::utility::delay(10000);
|
||||
}
|
||||
}
|
||||
|
||||
// Wire settings
|
||||
// Setup required to use HatHEART
|
||||
pinMode(pins.scl, OUTPUT);
|
||||
|
||||
// HatHeart settings
|
||||
bool hat_ready{};
|
||||
if (board_type == m5::board_t::board_ArduinoNessoN1) {
|
||||
// Using wire1
|
||||
Wire1.end();
|
||||
Wire1.begin(pins.sda, pins.scl, 400 * 1000U);
|
||||
hat_ready = Units.add(hat, Wire1);
|
||||
} else {
|
||||
// SoftwareI2C for Hat
|
||||
m5::hal::bus::I2CBusConfig hat_i2c_cfg;
|
||||
hat_i2c_cfg.pin_sda = m5::hal::gpio::getPin(pins.sda);
|
||||
hat_i2c_cfg.pin_scl = m5::hal::gpio::getPin(pins.scl);
|
||||
auto hat_i2c_bus = m5::hal::bus::i2c::getBus(hat_i2c_cfg);
|
||||
hat_ready = Units.add(hat, hat_i2c_bus ? hat_i2c_bus.value() : nullptr);
|
||||
}
|
||||
|
||||
// UnitHeart settings
|
||||
auto pin_num_sda = M5.getPin(m5::pin_name_t::port_a_sda);
|
||||
auto pin_num_scl = M5.getPin(m5::pin_name_t::port_a_scl);
|
||||
Wire.end();
|
||||
Wire.begin(pin_num_sda, pin_num_scl, 400 * 1000U);
|
||||
bool unit_ready{};
|
||||
if (board_type == m5::board_t::board_ArduinoNessoN1) {
|
||||
// For NessoN1 GROVE
|
||||
// Wire is used internally, so SoftwareI2C handles the unit
|
||||
pin_num_sda = M5.getPin(m5::pin_name_t::port_b_out);
|
||||
pin_num_scl = M5.getPin(m5::pin_name_t::port_b_in);
|
||||
M5_LOGI("getPin(NessoN1): SDA:%u SCL:%u", pin_num_sda, pin_num_scl);
|
||||
m5::hal::bus::I2CBusConfig i2c_cfg;
|
||||
i2c_cfg.pin_sda = m5::hal::gpio::getPin(pin_num_sda);
|
||||
i2c_cfg.pin_scl = m5::hal::gpio::getPin(pin_num_scl);
|
||||
auto i2c_bus = m5::hal::bus::i2c::getBus(i2c_cfg);
|
||||
M5_LOGI("Bus:%d", i2c_bus.has_value());
|
||||
unit_ready = Units.add(unit, i2c_bus ? i2c_bus.value() : nullptr);
|
||||
} else {
|
||||
// UnitHeart on Wire
|
||||
M5_LOGI("getPin: SDA:%u SCL:%u", pin_num_sda, pin_num_scl);
|
||||
Wire.end();
|
||||
Wire.begin(pin_num_sda, pin_num_scl, 400 * 1000U);
|
||||
unit_ready = Units.add(unit, Wire);
|
||||
}
|
||||
|
||||
Wire1.end();
|
||||
Wire1.begin(0, 26, 400 * 1000U);
|
||||
|
||||
// UnitHeart connected to GROOVE with Wire
|
||||
// HatHeart connected to PIN sockect with Wire1
|
||||
if (!Units.add(unit, Wire) || !Units.add(hat, Wire1) || !Units.begin()) {
|
||||
M5_LOGE("Failed to begin");
|
||||
lcd.clear(TFT_RED);
|
||||
if (!hat_ready || !unit_ready || !Units.begin()) {
|
||||
M5_LOGE("Failed to begin %u/%u", hat_ready, unit_ready);
|
||||
M5_LOGE("%s", Units.debugInfo().c_str());
|
||||
lcd.fillScreen(TFT_RED);
|
||||
while (true) {
|
||||
m5::utility::delay(10000);
|
||||
}
|
||||
@@ -73,14 +132,14 @@ void setup()
|
||||
M5_LOGI("M5UnitUnified has been begun");
|
||||
M5_LOGI("%s", Units.debugInfo().c_str());
|
||||
|
||||
lcd.startWrite();
|
||||
|
||||
view[0] = new View(lcd.width() >> 1, lcd.height(), true);
|
||||
view[1] = new View(lcd.width() >> 1, lcd.height(), false);
|
||||
view[0]->_monitor.setSamplingRate(unit.caluculateSamplingRate());
|
||||
view[1]->_monitor.setSamplingRate(hat.caluculateSamplingRate());
|
||||
view[0]->push(&lcd, lcd.width() >> 1, 0);
|
||||
view[1]->push(&lcd, 0, 0);
|
||||
view[0]->_monitor.setSamplingRate(unit.calculateSamplingRate());
|
||||
view[1]->_monitor.setSamplingRate(hat.calculateSamplingRate());
|
||||
if (!is_epd_panel) {
|
||||
view[0]->push(&lcd, lcd.width() >> 1, 0);
|
||||
view[1]->push(&lcd, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void loop()
|
||||
@@ -88,34 +147,66 @@ void loop()
|
||||
M5.update();
|
||||
Units.update();
|
||||
|
||||
if (!is_epd_panel) {
|
||||
lcd.startWrite();
|
||||
}
|
||||
if (unit.updated()) {
|
||||
if (unit.overflow()) {
|
||||
M5_LOGW("OVERFLOW U:%u", unit.overflow());
|
||||
}
|
||||
bool beat{};
|
||||
while (unit.available()) {
|
||||
view[0]->push_back(unit.ir(), unit.red());
|
||||
const auto ir = unit.ir();
|
||||
const auto red = unit.red();
|
||||
view[0]->push_back(ir, red);
|
||||
view[0]->update();
|
||||
if (is_epd_panel) {
|
||||
M5.Log.printf(">UIR:%u\n>URED:%u\n", static_cast<uint32_t>(ir), static_cast<uint32_t>(red));
|
||||
M5.Log.printf(">UMIR:%f\n", view[0]->_monitor.latestIR());
|
||||
}
|
||||
beat |= view[0]->_monitor.isBeat();
|
||||
unit.discard();
|
||||
}
|
||||
view[0]->render();
|
||||
view[0]->push(&lcd, lcd.width() >> 1, 0);
|
||||
if (is_epd_panel) {
|
||||
M5.Log.printf(">UBPM:%f\n>USpO2:%f\n>UBEAT:%u\n", view[0]->_monitor.bpm(), view[0]->_monitor.SpO2(), beat);
|
||||
}
|
||||
if (!is_epd_panel) {
|
||||
view[0]->render();
|
||||
view[0]->push(&lcd, lcd.width() >> 1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (hat.updated()) {
|
||||
if (hat.overflow()) {
|
||||
M5_LOGW("OVERFLOW H:%u", hat.overflow());
|
||||
}
|
||||
bool beat{};
|
||||
while (hat.available()) {
|
||||
view[1]->push_back(hat.ir(), hat.red());
|
||||
const auto ir = hat.ir();
|
||||
const auto red = hat.red();
|
||||
view[1]->push_back(ir, red);
|
||||
view[1]->update();
|
||||
if (is_epd_panel) {
|
||||
M5.Log.printf(">HIR:%u\n>HRED:%u\n", static_cast<uint32_t>(ir), static_cast<uint32_t>(red));
|
||||
M5.Log.printf(">HMIR:%f\n", view[1]->_monitor.latestIR());
|
||||
}
|
||||
beat |= view[1]->_monitor.isBeat();
|
||||
hat.discard();
|
||||
}
|
||||
view[1]->render();
|
||||
view[1]->push(&lcd, 0, 0);
|
||||
if (is_epd_panel) {
|
||||
M5.Log.printf(">HBPM:%f\n>HSpO2:%f\n>HBEAT:%u\n", view[1]->_monitor.bpm(), view[1]->_monitor.SpO2(), beat);
|
||||
}
|
||||
if (!is_epd_panel) {
|
||||
view[1]->render();
|
||||
view[1]->push(&lcd, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (M5.BtnA.wasClicked()) {
|
||||
view[0]->clear();
|
||||
view[1]->clear();
|
||||
}
|
||||
if (!is_epd_panel) {
|
||||
lcd.endWrite();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,12 +12,15 @@
|
||||
|
||||
class Meter {
|
||||
public:
|
||||
Meter(const uint32_t left, const uint32_t top, const uint32_t wid, const uint32_t hgt, m5gfx::rgb565_t tcolor)
|
||||
: _left(left), _top(top), _theme_color(tcolor)
|
||||
Meter(const uint32_t left, const uint32_t top, const uint32_t wid, const uint32_t hgt, m5gfx::rgb565_t tcolor,
|
||||
m5gfx::rgb565_t gcolor = TFT_DARKGRAY, m5gfx::rgb565_t bcolor = TFT_BLACK)
|
||||
: _left(left), _top(top), _theme_color(tcolor), _gauge_color(gcolor), _background_color(bcolor)
|
||||
{
|
||||
_plotter = new m5::ui::Plotter(nullptr, wid, wid, hgt);
|
||||
_plotter->setGaugeTextDatum(textdatum_t::top_right);
|
||||
_plotter->setLineColor(_theme_color);
|
||||
_plotter->setGaugeColor(_gauge_color);
|
||||
_plotter->setBackgroundColor(_background_color);
|
||||
}
|
||||
|
||||
inline void push_back(const float value)
|
||||
@@ -25,7 +28,7 @@ public:
|
||||
_plotter->push_back(value);
|
||||
}
|
||||
|
||||
inline void push(LovyanGFX* target, const uint32_t x, const uint32_t y)
|
||||
inline void push(LovyanGFX* target)
|
||||
{
|
||||
_plotter->push(target, _left, _top);
|
||||
}
|
||||
@@ -39,5 +42,7 @@ private:
|
||||
uint32_t _left{}, _top{};
|
||||
m5::ui::Plotter* _plotter{};
|
||||
m5gfx::rgb565_t _theme_color{};
|
||||
m5gfx::rgb565_t _gauge_color{TFT_DARKGRAY};
|
||||
m5gfx::rgb565_t _background_color{TFT_BLACK};
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -83,7 +83,8 @@ void Plotter::push(LovyanGFX* dst, const int32_t x, const int32_t y)
|
||||
left += _wid - sz;
|
||||
}
|
||||
|
||||
while (it != itend && left < _wid) {
|
||||
const int32_t right = x + _wid;
|
||||
while (it != itend && left < right) {
|
||||
int32_t s{*it}, e{*(++it)};
|
||||
dst->drawLine(left, y + hh - hh * (s - _min) / range, left + 1, y + hh - hh * (e - _min) / range, _lineClr);
|
||||
++left;
|
||||
|
||||
@@ -11,9 +11,17 @@
|
||||
struct View {
|
||||
View(const uint32_t wid, const uint32_t hgt, bool unit) : _type{unit}
|
||||
{
|
||||
_theme_color = unit ? TFT_BLUE : TFT_YELLOW;
|
||||
_sprite.setPsram(false);
|
||||
_sprite.setColorDepth(2);
|
||||
_sprite.createSprite(wid, hgt);
|
||||
_sprite.setPaletteColor(palette_black, TFT_BLACK);
|
||||
_sprite.setPaletteColor(palette_white, TFT_WHITE);
|
||||
_sprite.setPaletteColor(palette_theme, _theme_color);
|
||||
_sprite.setPaletteColor(palette_gauge, TFT_DARKGRAY);
|
||||
_sprite.setTextColor(palette_white, palette_black);
|
||||
_sprite.setFont(&fonts::FreeSansBold9pt7b);
|
||||
_meter = new Meter(0, hgt * 2 / 3, wid, hgt / 3, unit ? TFT_BLUE : TFT_YELLOW);
|
||||
_meter = new Meter(0, hgt * 2 / 3, wid, hgt / 3, palette_theme, palette_gauge, palette_black);
|
||||
}
|
||||
|
||||
inline void push_back(const float ir, const float red)
|
||||
@@ -33,13 +41,13 @@ struct View {
|
||||
|
||||
void render()
|
||||
{
|
||||
_sprite.clear();
|
||||
_sprite.clear(palette_black);
|
||||
_sprite.drawString(_type ? "Unit" : "Hat", 0, 0);
|
||||
_sprite.setCursor(0, 24);
|
||||
_sprite.printf("BPM: %3.2f\nSpO2:%3.2f", _monitor.bpm(), _monitor.SpO2());
|
||||
_sprite.fillCircle(_sprite.width() - 12, 24 * 3, 7, _beat ? TFT_RED : TFT_WHITE);
|
||||
_sprite.fillCircle(_sprite.width() - 12, 24 * 3, 7, _beat ? palette_theme : palette_white);
|
||||
|
||||
_meter->push(&_sprite, 0, _sprite.height() >> 1);
|
||||
_meter->push(&_sprite);
|
||||
}
|
||||
|
||||
void clear()
|
||||
@@ -53,10 +61,17 @@ struct View {
|
||||
_sprite.pushSprite(target, x, y);
|
||||
}
|
||||
|
||||
enum : uint8_t {
|
||||
palette_black = 0,
|
||||
palette_white = 1,
|
||||
palette_theme = 2,
|
||||
palette_gauge = 3,
|
||||
};
|
||||
LGFX_Sprite _sprite{};
|
||||
m5::heart::PulseMonitor _monitor{100, 2};
|
||||
Meter* _meter{};
|
||||
uint32_t _left{}, _top{}, _beat{};
|
||||
bool _type{};
|
||||
m5gfx::rgb565_t _theme_color{};
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
/*
|
||||
Graphical meter example for UnitHeart / HatHeart
|
||||
*/
|
||||
// *************************************************************
|
||||
// Choose one define symbol to match the unit you are using
|
||||
// *************************************************************
|
||||
#if !defined(USING_UNIT_HEART) && !defined(USING_HAT_HEART)
|
||||
// For UnitHeart (U029)
|
||||
// #define USING_UNIT_HEART
|
||||
// For HatHeart (U118)
|
||||
// #define USING_HAT_HEART
|
||||
#endif
|
||||
#include "main/GraphicalMeter.cpp"
|
||||
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
/*
|
||||
Graphical meter example for UnitHeart / HatHeart
|
||||
The core must be equipped with LCD
|
||||
*/
|
||||
#include <M5Unified.h>
|
||||
#include <M5UnitUnified.h>
|
||||
#include <M5UnitUnifiedHEART.h>
|
||||
#include <Wire.h>
|
||||
#include <M5HAL.hpp>
|
||||
#include "../src/view.hpp"
|
||||
|
||||
// *************************************************************
|
||||
// Choose one define symbol to match the unit you are using
|
||||
// *************************************************************
|
||||
#if !defined(USING_UNIT_HEART) && !defined(USING_HAT_HEART)
|
||||
// #define USING_UNIT_HEART
|
||||
// #define USING_HAT_HEART
|
||||
#endif
|
||||
|
||||
#if defined(USING_UNIT_HEART)
|
||||
#pragma message "Using UnitHeart"
|
||||
using namespace m5::unit::max30100;
|
||||
#elif defined(USING_HAT_HEART)
|
||||
#pragma message "Using HatHeart"
|
||||
using namespace m5::unit::max30102;
|
||||
#else
|
||||
#error Please choose unit!
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
auto& lcd = M5.Display;
|
||||
m5::unit::UnitUnified Units;
|
||||
#if defined(USING_UNIT_HEART)
|
||||
m5::unit::UnitHeart heart;
|
||||
#elif defined(USING_HAT_HEART)
|
||||
m5::unit::HatHeart heart;
|
||||
#endif
|
||||
|
||||
View* view{};
|
||||
|
||||
#if defined(USING_HAT_HEART)
|
||||
struct I2cPins {
|
||||
int sda;
|
||||
int scl;
|
||||
};
|
||||
|
||||
I2cPins get_hat_i2c_pins(const m5::board_t board)
|
||||
{
|
||||
switch (board) {
|
||||
case m5::board_t::board_M5StickC:
|
||||
case m5::board_t::board_M5StickCPlus:
|
||||
case m5::board_t::board_M5StickCPlus2:
|
||||
return {0, 26};
|
||||
case m5::board_t::board_M5StickS3:
|
||||
return {8, 0};
|
||||
case m5::board_t::board_M5StackCoreInk:
|
||||
return {25, 26};
|
||||
case m5::board_t::board_ArduinoNessoN1:
|
||||
return {6, 7};
|
||||
default:
|
||||
return {-1, -1};
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
|
||||
void setup()
|
||||
{
|
||||
auto m5cfg = M5.config();
|
||||
#if defined(USING_HAT_HEART)
|
||||
m5cfg.pmic_button = false; // Disable BtnPWR
|
||||
m5cfg.internal_imu = false; // Disable internal IMU
|
||||
m5cfg.internal_rtc = false; // Disable internal RTC
|
||||
#endif
|
||||
M5.begin(m5cfg);
|
||||
M5.setTouchButtonHeightByRatio(100);
|
||||
|
||||
auto board = M5.getBoard();
|
||||
// The screen shall be in landscape mode (skip for M5Tab5)
|
||||
if (board != m5::board_t::board_M5Tab5 && lcd.height() > lcd.width()) {
|
||||
lcd.setRotation(1);
|
||||
}
|
||||
|
||||
#if defined(USING_HAT_HEART)
|
||||
const auto pins = get_hat_i2c_pins(board);
|
||||
M5_LOGI("getHatPin: SDA:%u SCL:%u", pins.sda, pins.scl);
|
||||
if (pins.sda < 0 || pins.scl < 0) {
|
||||
M5_LOGE("Illegal pin number");
|
||||
lcd.fillScreen(TFT_RED);
|
||||
while (true) {
|
||||
m5::utility::delay(10000);
|
||||
}
|
||||
}
|
||||
|
||||
// Setup required to use HatHEART
|
||||
pinMode(pins.scl, OUTPUT);
|
||||
|
||||
auto& wire = (board == m5::board_t::board_ArduinoNessoN1) ? Wire1 : Wire;
|
||||
wire.end();
|
||||
wire.begin(pins.sda, pins.scl, 400 * 1000U);
|
||||
if (!Units.add(heart, wire) || !Units.begin()) {
|
||||
M5_LOGE("Failed to begin");
|
||||
lcd.fillScreen(TFT_RED);
|
||||
while (true) {
|
||||
m5::utility::delay(10000);
|
||||
}
|
||||
}
|
||||
#else
|
||||
// NessoN1: Arduino Wire (I2C_NUM_0) cannot be used for GROVE port.
|
||||
// Wire is used by M5Unified In_I2C for internal devices (IOExpander etc.).
|
||||
// Wire1 exists but is reserved for HatPort — cannot be used for GROVE.
|
||||
// Reconfiguring Wire to GROVE pins breaks In_I2C, causing ESP_ERR_INVALID_STATE in M5.update().
|
||||
// Solution: Use SoftwareI2C via M5HAL (bit-banging) for the GROVE port.
|
||||
// NanoC6: Wire.begin() on GROVE pins conflicts with m5::I2C_Class registered by Ex_I2C.setPort()
|
||||
// on the same I2C_NUM_0, causing sporadic NACK errors.
|
||||
// Solution: Use M5.Ex_I2C (m5::I2C_Class) directly instead of Arduino Wire.
|
||||
bool unit_ready{};
|
||||
if (board == m5::board_t::board_ArduinoNessoN1) {
|
||||
// NessoN1: GROVE is on port_b (GPIO 5/4), not port_a (which maps to Wire pins 8/10)
|
||||
auto pin_num_sda = M5.getPin(m5::pin_name_t::port_b_out);
|
||||
auto pin_num_scl = M5.getPin(m5::pin_name_t::port_b_in);
|
||||
M5_LOGI("getPin(M5HAL): SDA:%u SCL:%u", pin_num_sda, pin_num_scl);
|
||||
m5::hal::bus::I2CBusConfig i2c_cfg;
|
||||
i2c_cfg.pin_sda = m5::hal::gpio::getPin(pin_num_sda);
|
||||
i2c_cfg.pin_scl = m5::hal::gpio::getPin(pin_num_scl);
|
||||
auto i2c_bus = m5::hal::bus::i2c::getBus(i2c_cfg);
|
||||
M5_LOGI("Bus:%d", i2c_bus.has_value());
|
||||
unit_ready = Units.add(heart, i2c_bus ? i2c_bus.value() : nullptr) && Units.begin();
|
||||
} else if (board == m5::board_t::board_M5NanoC6) {
|
||||
// NanoC6: Use M5.Ex_I2C (m5::I2C_Class, not Arduino Wire)
|
||||
M5_LOGI("Using M5.Ex_I2C");
|
||||
unit_ready = Units.add(heart, M5.Ex_I2C) && Units.begin();
|
||||
} else {
|
||||
auto pin_num_sda = M5.getPin(m5::pin_name_t::port_a_sda);
|
||||
auto pin_num_scl = M5.getPin(m5::pin_name_t::port_a_scl);
|
||||
M5_LOGI("getPin: SDA:%u SCL:%u", pin_num_sda, pin_num_scl);
|
||||
Wire.end();
|
||||
Wire.begin(pin_num_sda, pin_num_scl, 400000U);
|
||||
unit_ready = Units.add(heart, Wire) && Units.begin();
|
||||
}
|
||||
if (!unit_ready) {
|
||||
M5_LOGE("Failed to begin");
|
||||
lcd.fillScreen(TFT_RED);
|
||||
while (true) {
|
||||
m5::utility::delay(10000);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
M5_LOGI("M5UnitUnified has been begun");
|
||||
M5_LOGI("%s", Units.debugInfo().c_str());
|
||||
|
||||
lcd.fillScreen(0);
|
||||
|
||||
#if defined(USING_UNIT_HEART)
|
||||
view = new View(lcd.width(), lcd.height(), true);
|
||||
#else
|
||||
view = new View(lcd.width(), lcd.height(), false);
|
||||
#endif
|
||||
view->_monitor.setSamplingRate(heart.calculateSamplingRate());
|
||||
view->push(&lcd, 0, 0);
|
||||
|
||||
M5_LOGI("periodic:%d", heart.inPeriodic());
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
M5.update();
|
||||
Units.update();
|
||||
|
||||
if (heart.updated()) {
|
||||
if (heart.overflow()) {
|
||||
M5_LOGW("OVERFLOW:%u", heart.overflow());
|
||||
}
|
||||
while (heart.available()) {
|
||||
view->push_back(heart.ir(), heart.red());
|
||||
view->update();
|
||||
heart.discard();
|
||||
}
|
||||
view->render();
|
||||
view->push(&lcd, 0, 0);
|
||||
}
|
||||
|
||||
if (M5.BtnA.wasClicked()) {
|
||||
view->clear();
|
||||
}
|
||||
}
|
||||
+8
-3
@@ -12,12 +12,15 @@
|
||||
|
||||
class Meter {
|
||||
public:
|
||||
Meter(const uint32_t left, const uint32_t top, const uint32_t wid, const uint32_t hgt, m5gfx::rgb565_t tcolor)
|
||||
: _left(left), _top(top), _theme_color(tcolor)
|
||||
Meter(const uint32_t left, const uint32_t top, const uint32_t wid, const uint32_t hgt, m5gfx::rgb565_t tcolor,
|
||||
m5gfx::rgb565_t gcolor = TFT_DARKGRAY, m5gfx::rgb565_t bcolor = TFT_BLACK)
|
||||
: _left(left), _top(top), _theme_color(tcolor), _gauge_color(gcolor), _background_color(bcolor)
|
||||
{
|
||||
_plotter = new m5::ui::Plotter(nullptr, wid, wid, hgt);
|
||||
_plotter->setGaugeTextDatum(textdatum_t::top_right);
|
||||
_plotter->setLineColor(_theme_color);
|
||||
_plotter->setGaugeColor(_gauge_color);
|
||||
_plotter->setBackgroundColor(_background_color);
|
||||
}
|
||||
|
||||
inline void push_back(const float value)
|
||||
@@ -25,7 +28,7 @@ public:
|
||||
_plotter->push_back(value);
|
||||
}
|
||||
|
||||
inline void push(LovyanGFX* target, const uint32_t x, const uint32_t y)
|
||||
inline void push(LovyanGFX* target)
|
||||
{
|
||||
_plotter->push(target, _left, _top);
|
||||
}
|
||||
@@ -39,5 +42,7 @@ private:
|
||||
uint32_t _left{}, _top{};
|
||||
m5::ui::Plotter* _plotter{};
|
||||
m5gfx::rgb565_t _theme_color{};
|
||||
m5gfx::rgb565_t _gauge_color{TFT_DARKGRAY};
|
||||
m5gfx::rgb565_t _background_color{TFT_BLACK};
|
||||
};
|
||||
#endif
|
||||
+2
-1
@@ -83,7 +83,8 @@ void Plotter::push(LovyanGFX* dst, const int32_t x, const int32_t y)
|
||||
left += _wid - sz;
|
||||
}
|
||||
|
||||
while (it != itend && left < _wid) {
|
||||
const int32_t right = x + _wid;
|
||||
while (it != itend && left < right) {
|
||||
int32_t s{*it}, e{*(++it)};
|
||||
dst->drawLine(left, y + hh - hh * (s - _min) / range, left + 1, y + hh - hh * (e - _min) / range, _lineClr);
|
||||
++left;
|
||||
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#ifndef M5_UNIT_HEART_EXAMPLE_VIEW_HPP
|
||||
#define M5_UNIT_HEART_EXAMPLE_VIEW_HPP
|
||||
|
||||
#include "meter.hpp"
|
||||
|
||||
struct View {
|
||||
View(const uint32_t wid, const uint32_t hgt, bool unit) : _type{unit}
|
||||
{
|
||||
_theme_color = unit ? TFT_BLUE : TFT_YELLOW;
|
||||
_screen_w = wid;
|
||||
_screen_h = hgt;
|
||||
_plot_top = hgt * 2 / 3;
|
||||
_plot_hgt = hgt / 3;
|
||||
const uint32_t spr_w = wid;
|
||||
const uint32_t spr_h = _plot_hgt;
|
||||
_plot_sprite.setPsram(false);
|
||||
_plot_sprite.setColorDepth(2);
|
||||
_plot_sprite.createSprite(spr_w, spr_h);
|
||||
_plot_sprite.setPaletteColor(palette_black, TFT_BLACK);
|
||||
_plot_sprite.setPaletteColor(palette_white, TFT_WHITE);
|
||||
_plot_sprite.setPaletteColor(palette_theme, _theme_color);
|
||||
_plot_sprite.setPaletteColor(palette_gauge, TFT_DARKGRAY);
|
||||
_plot_sprite.setTextColor(palette_white, palette_black);
|
||||
_plot_sprite.setFont(&fonts::FreeSansBold9pt7b);
|
||||
_text_sprite.setPsram(false);
|
||||
_text_sprite.setColorDepth(2);
|
||||
_text_sprite.setPaletteColor(palette_black, TFT_BLACK);
|
||||
_text_sprite.setPaletteColor(palette_white, TFT_WHITE);
|
||||
_text_sprite.setPaletteColor(palette_theme, _theme_color);
|
||||
_text_sprite.setPaletteColor(palette_gauge, TFT_DARKGRAY);
|
||||
_text_sprite.setTextColor(palette_white, palette_black);
|
||||
_text_sprite.setFont(&fonts::FreeSansBold9pt7b);
|
||||
const int32_t line_h = _text_sprite.fontHeight();
|
||||
const int32_t title_w = _text_sprite.textWidth("Unit");
|
||||
const int32_t bpm_w = _text_sprite.textWidth("BPM: 000.00");
|
||||
const int32_t spo2_w = _text_sprite.textWidth("SpO2:100.00");
|
||||
_text_w = std::max(title_w, std::max(bpm_w, spo2_w));
|
||||
_text_h = line_h * 3;
|
||||
_text_sprite.createSprite(_text_w, _text_h);
|
||||
_text_sprite.setPaletteColor(palette_black, TFT_BLACK);
|
||||
_text_sprite.setPaletteColor(palette_white, TFT_WHITE);
|
||||
_text_sprite.setPaletteColor(palette_theme, _theme_color);
|
||||
_text_sprite.setPaletteColor(palette_gauge, TFT_DARKGRAY);
|
||||
_text_sprite.setTextColor(palette_white, palette_black);
|
||||
_text_sprite.setFont(&fonts::FreeSansBold9pt7b);
|
||||
_beat_size = 16;
|
||||
_beat_x = _screen_w - _beat_size - 2;
|
||||
_beat_y = (line_h * 2) + (line_h / 2) - (_beat_size / 2);
|
||||
_beat_sprite.setPsram(false);
|
||||
_beat_sprite.setColorDepth(2);
|
||||
_beat_sprite.createSprite(_beat_size, _beat_size);
|
||||
_beat_sprite.setPaletteColor(palette_black, TFT_BLACK);
|
||||
_beat_sprite.setPaletteColor(palette_white, TFT_WHITE);
|
||||
_beat_sprite.setPaletteColor(palette_theme, _theme_color);
|
||||
_beat_sprite.setPaletteColor(palette_gauge, TFT_DARKGRAY);
|
||||
_meter = new Meter(0, 0, spr_w, spr_h, palette_theme, palette_gauge, palette_black);
|
||||
}
|
||||
|
||||
inline void push_back(const float ir, const float red)
|
||||
{
|
||||
_monitor.push_back(ir, red);
|
||||
}
|
||||
|
||||
void update()
|
||||
{
|
||||
if (_beat) {
|
||||
--_beat;
|
||||
}
|
||||
_meter->push_back(_monitor.latestIR());
|
||||
_monitor.update();
|
||||
_beat += _monitor.isBeat() * 8;
|
||||
}
|
||||
|
||||
void render()
|
||||
{
|
||||
_plot_sprite.clear(palette_black);
|
||||
_meter->push(&_plot_sprite);
|
||||
_text_sprite.clear(palette_black);
|
||||
_text_sprite.drawString(_type ? "Unit" : "Hat", 0, 0);
|
||||
_text_sprite.setCursor(0, _text_sprite.fontHeight());
|
||||
_text_sprite.printf("BPM: %3.2f\nSpO2:%3.2f", _monitor.bpm(), _monitor.SpO2());
|
||||
_beat_sprite.clear(palette_black);
|
||||
_beat_sprite.fillCircle(_beat_size / 2, _beat_size / 2, 7, _beat ? palette_theme : palette_white);
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
_monitor.clear();
|
||||
_meter->clear();
|
||||
_plot_sprite.clear(palette_black);
|
||||
_text_sprite.clear(palette_black);
|
||||
_beat_sprite.clear(palette_black);
|
||||
}
|
||||
|
||||
void push(LovyanGFX* target, const uint32_t x, const uint32_t y)
|
||||
{
|
||||
_text_sprite.pushSprite(target, x, y);
|
||||
_beat_sprite.pushSprite(target, x + _beat_x, y + _beat_y);
|
||||
_plot_sprite.pushSprite(target, x, y + _plot_top);
|
||||
}
|
||||
|
||||
enum : uint8_t {
|
||||
palette_black = 0,
|
||||
palette_white = 1,
|
||||
palette_theme = 2,
|
||||
palette_gauge = 3,
|
||||
};
|
||||
LGFX_Sprite _plot_sprite{};
|
||||
LGFX_Sprite _text_sprite{};
|
||||
LGFX_Sprite _beat_sprite{};
|
||||
m5::heart::PulseMonitor _monitor{100, 2};
|
||||
Meter* _meter{};
|
||||
uint32_t _left{}, _top{}, _beat{};
|
||||
uint32_t _screen_w{}, _screen_h{}, _plot_top{}, _plot_hgt{};
|
||||
int32_t _text_w{}, _text_h{}, _beat_x{}, _beat_y{}, _beat_size{};
|
||||
bool _type{};
|
||||
m5gfx::rgb565_t _theme_color{};
|
||||
};
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user