initial commit

This commit is contained in:
Mikkeli Matlock
2026-02-15 02:48:59 +09:00
commit 19db125619
258 changed files with 345581 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
*.hpp linguist-language=C++

View File

@@ -0,0 +1,11 @@
.pio
.vscode
test
.travis.yml
test
assets
*.bk
*.test
build
*.old
sdkconfig

View File

@@ -0,0 +1,19 @@
set(src_dirs ./src
./src/touch
./src/platform
./src/bosch
./src/bosch/BMM150
./src/bosch/common
)
set(include_dirs ./src
./src/REG
./src/touch
./src/platform
./src/bosch
./src/bosch/firmware
./src/bosch/BMM150
./src/bosch/common)
idf_component_register(SRC_DIRS ${src_dirs}
INCLUDE_DIRS ${include_dirs}
REQUIRES esp_timer esp_driver_gpio driver)

View File

@@ -0,0 +1,16 @@
menu "SensorLib Configuration"
choice SensorLib_ESP_IDF_API
prompt "SensorLib library esp-idf api version"
default SENSORLIB_ESP_IDF_NEW_API
help
Define API version
config SENSORLIB_ESP_IDF_NEW_API
bool "Use esp-idf higher version (>= 5.0) API"
config SENSORLIB_ESP_IDF_OLD_API
bool "Use esp-idf lower version ( < 5.0) API , Compatible with lower versions of esp-idf"
endchoice
endmenu

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022 lewis he
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,44 @@
<center><img src="extras/images/SensroLib.jpg" width="80%" height="30%"></center>
[![Build with ESP-IDF](https://github.com/lewisxhe/SensorLib/actions/workflows/esp-idf.yml/badge.svg)](https://github.com/lewisxhe/SensorLib/actions/workflows/esp-idf.yml)
[![Build with Arduino](https://github.com/lewisxhe/SensorLib/actions/workflows/arduino_ci.yml/badge.svg)](https://github.com/lewisxhe/SensorLib/actions/workflows/arduino_ci.yml)
[![Build with PlatformIO](https://github.com/lewisxhe/SensorLib/actions/workflows/platformio.yml/badge.svg)](https://github.com/lewisxhe/SensorLib/actions/workflows/platformio.yml)
[![arduino-library-badge](https://www.ardu-badge.com/badge/SensorLib.svg?)](https://www.ardu-badge.com/SensorLib)
[![PlatformIO Registry](https://badges.registry.platformio.org/packages/lewisxhe/library/SensorLib.svg)](https://registry.platformio.org/libraries/lewisxhe/SensorLib)
[![LICENSE](https://img.shields.io/github/license/lewisxhe/SensorLib)](https://github.com/lewisxhe/SensorLib/blob/master/LICENSE)
[![ISSUES](https://img.shields.io/github/issues/lewisxhe/SensorsLib)](https://github.com/lewisxhe/SensorsLib/issues)
[![FORK](https://img.shields.io/github/forks/lewisxhe/SensorsLib)](https://github.com/lewisxhe/SensorsLib/graphs/contributors)
[![STAR](https://img.shields.io/github/stars/lewisxhe/SensorsLib)](https://github.com/lewisxhe/SensorsLib/stargazers)
[![releases](https://img.shields.io/github/release/lewisxhe/SensorsLib)](https://github.com/lewisxhe/SensorLib/releases)
Support list:
| Sensor | Description | I2C | SPI |
| --------------- | ------------------------ | --- | --- |
| PCF8563/HYM8563 | Real-time clock | ✔️ | ❌ |
| PCF85063 | Real-time clock | ✔️ | ❌ |
| QMI8658 | IMU | ✔️ | ✔️ |
| BHI260AP | IMU | ✔️ | ✔️ |
| QMC6310 | Magnetic Sensor | ✔️ | ❌ |
| BMM150 | Magnetic Sensor | ✔️ | ❌ |
| XL9555 | I/O expander | ✔️ | ❌ |
| BMA423 | Accelerometer | ✔️ | ❌ |
| DRV2605 | Haptic Driver | ✔️ | ❌ |
| CM32181 | Ambient Light Sensor | ✔️ | ❌ |
| LTR553 | Light & Proximity Sensor | ✔️ | ❌ |
| FT3267 | Capacitive touch | ✔️ | ❌ |
| FT5206 | Capacitive touch | ✔️ | ❌ |
| FT6206 | Capacitive touch | ✔️ | ❌ |
| FT6236 | Capacitive touch | ✔️ | ❌ |
| CST820 | Capacitive touch | ✔️ | ❌ |
| CST816S/T/D | Capacitive touch | ✔️ | ❌ |
| CST226SE | Capacitive touch | ✔️ | ❌ |
| CHSC5816 | Capacitive touch | ✔️ | ❌ |
| GT911 | Capacitive touch | ✔️ | ❌ |
| CST9217 | Capacitive touch | ✔️ | ❌ |
| CST9220 | Capacitive touch | ✔️ | ❌ |
| GT9895 | Capacitive touch | ✔️ | ❌ |
| AW9364 | Led Driver (GPIO) | ❌ | ❌ |

View File

@@ -0,0 +1,402 @@
#######################################
# Syntax Coloring Map For SensorLib By lewis He
# github:https://github.com/lewisxhe
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
ExtensionIOXL9555 KEYWORD1
SensorPCF8563 KEYWORD1
SensorQMC6310 KEYWORD1
SensorBMM150 KEYWORD1
SensorBHI260AP KEYWORD1
SensorBMA423 KEYWORD1
SensorCM32181 KEYWORD1
SensorDRV2605 KEYWORD1
SensorLTR553 KEYWORD1
SensorPCF85063 KEYWORD1
SensorWireHelper KEYWORD1
TouchDrvCHSC5816 KEYWORD1
TouchDrvCST92xx KEYWORD1
TouchDrvCSTXXX KEYWORD1
TouchDrvFT6X36 KEYWORD1
TouchDrvGT911 KEYWORD1
TouchDrvInterface KEYWORD1
TouchClassCST226 KEYWORD1
TouchClassCST816 KEYWORD1
TouchDrvGT9895 KEYWORD1
AW9364LedDriver KEYWORD1
RTC_DateTime KEYWORD1
RTC_Alarm KEYWORD1
MagRange KEYWORD1
OutputRate KEYWORD1
CtrlReg KEYWORD1
OverSampleRatio KEYWORD1
DownSampleRatio KEYWORD1
SensorQMI8658 KEYWORD1
AccelRange KEYWORD1
GyroRange KEYWORD1
AccelODR KEYWORD1
GyroODR KEYWORD1
LpfMode KEYWORD1
MotionEvent KEYWORD1
IntPin KEYWORD1
FIFO_Samples KEYWORD1
FIFO_Mode KEYWORD1
SampleMode KEYWORD1
CommandTable KEYWORD1
StatusReg KEYWORD1
TapDetectionPriority KEYWORD1
SensorStatus KEYWORD1
ioEvent_t KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
### XL9555 Coloring Map ###
init KEYWORD2
deinit KEYWORD2
pinMode KEYWORD2
digitalRead KEYWORD2
digitalWrite KEYWORD2
digitalToggle KEYWORD2
readPort KEYWORD2
writePort KEYWORD2
readConfig KEYWORD2
configPort KEYWORD2
update KEYWORD2
removePinEvent KEYWORD2
setPinEvent KEYWORD2
write KEYWORD2
read KEYWORD2
transferDataBits KEYWORD2
transfer9 KEYWORD2
transfer8 KEYWORD2
setBitOrder KEYWORD2
beginSPI KEYWORD2
setPinEvent KEYWORD2
removePinEvent KEYWORD2
update KEYWORD2
setClock KEYWORD2
getClock KEYWORD2
### PCF8563 Coloring Map ###
setDateTime KEYWORD2
getDateTime KEYWORD2
getAlarm KEYWORD2
enableAlarm KEYWORD2
disableAlarm KEYWORD2
resetAlarm KEYWORD2
isAlarmActive KEYWORD2
setAlarm KEYWORD2
setAlarmByMinutes KEYWORD2
setAlarmByDays KEYWORD2
setAlarmByHours KEYWORD2
setAlarmByWeekDay KEYWORD2
isCountdownTimerEnable KEYWORD2
isCountdownTimerActive KEYWORD2
enableCountdownTimer KEYWORD2
disableCountdownTimer KEYWORD2
setCountdownTimer KEYWORD2
clearCountdownTimer KEYWORD2
enableCLK KEYWORD2
strftime KEYWORD2
conversionUnixTime KEYWORD2
hwClockRead KEYWORD2
hwClockWrite KEYWORD2
getDayOfWeek KEYWORD2
getNextMonth KEYWORD2
getNextYear KEYWORD2
getLeapYear KEYWORD2
getDaysInMonth KEYWORD2
### SensorQMC6310 Coloring Map ###
reset KEYWORD2
getChipID KEYWORD2
getStatus KEYWORD2
isDataReady KEYWORD2
isDataOverflow KEYWORD2
setSelfTest KEYWORD2
setMode KEYWORD2
setCtrlRegister KEYWORD2
setDataOutputRate KEYWORD2
setOverSampleRate KEYWORD2
setDownSampleRate KEYWORD2
setSign KEYWORD2
configMagnetometer KEYWORD2
setMagRange KEYWORD2
setOffset KEYWORD2
readData KEYWORD2
setDeclination KEYWORD2
readPolar KEYWORD2
getRawX KEYWORD2
getRawY KEYWORD2
getRawZ KEYWORD2
getX KEYWORD2
getY KEYWORD2
getZ KEYWORD2
getMag KEYWORD2
dumpCtrlRegister KEYWORD2
### SensorQMI8658 Coloring Map ###
whoAmI KEYWORD2
getTimestamp KEYWORD2
getTemperature_C KEYWORD2
enableINT KEYWORD2
getIrqStatus KEYWORD2
enableDataReadyINT KEYWORD2
configAccelerometer KEYWORD2
configGyroscope KEYWORD2
configFIFO KEYWORD2
getFifoNeedBytes KEYWORD2
readFromFifo KEYWORD2
enableAccelerometer KEYWORD2
disableAccelerometer KEYWORD2
isEnableAccelerometer KEYWORD2
isEnableGyroscope KEYWORD2
enableGyroscope KEYWORD2
disableGyroscope KEYWORD2
getAccelRaw KEYWORD2
getAccelerometer KEYWORD2
getAccelerometerScales KEYWORD2
getGyroscopeScales KEYWORD2
getGyroRaw KEYWORD2
getGyroscope KEYWORD2
getDataReady KEYWORD2
enableSyncSampleMode KEYWORD2
disableSyncSampleMode KEYWORD2
enableLockingMechanism KEYWORD2
disableLockingMechanism KEYWORD2
powerDown KEYWORD2
powerOn KEYWORD2
getStatusRegister KEYWORD2
configActivityInterruptMap KEYWORD2
configPedometer KEYWORD2
getPedometerCounter KEYWORD2
clearPedometerCounter KEYWORD2
enablePedometer KEYWORD2
disablePedometer KEYWORD2
configTap KEYWORD2
enableTap KEYWORD2
disableTap KEYWORD2
getTapStatus KEYWORD2
configMotion KEYWORD2
enableMotionDetect KEYWORD2
disableMotionDetect KEYWORD2
configWakeOnMotion KEYWORD2
getChipUsid KEYWORD2
getChipFirmwareVersion KEYWORD2
setWakeupMotionEventCallBack KEYWORD2
setTapEventCallBack KEYWORD2
setPedometerEventCallBack KEYWORD2
setNoMotionEventCallBack KEYWORD2
setAnyMotionEventCallBack KEYWORD2
setSignificantMotionEventCallBack KEYWORD2
setGyroDataReadyCallBack KEYWORD2
setAccelDataReadyEventCallBack KEYWORD2
setDataLockingEventCallBack KEYWORD2
### SensorBMM150 Coloring Map ###
sleep KEYWORD2
setMode KEYWORD2
setThreshold KEYWORD2
setInterruptLevel KEYWORD2
enabledDataReady KEYWORD2
disabledDataReady KEYWORD2
# getIrqStatus KEYWORD2
# isDataReady KEYWORD2
isLowThreshold KEYWORD2
isHighThreshold KEYWORD2
# getMag KEYWORD2
### SensorBHI260AP Coloring Map ###
setPins KEYWORD2
setBootFromFlash KEYWORD2
getHandler KEYWORD2
printInfo KEYWORD2
setInterruptCtrl KEYWORD2
getInterruptCtrl KEYWORD2
printInterruptCtrl KEYWORD2
isReady KEYWORD2
getKernelVersion KEYWORD2
onEvent KEYWORD2
removeEvent KEYWORD2
onResultEvent KEYWORD2
removeResultEvent KEYWORD2
setProcessBufferSize KEYWORD2
uploadFirmware KEYWORD2
getError KEYWORD2
configure KEYWORD2
getConfigure KEYWORD2
getScaling KEYWORD2
setFirmware KEYWORD2
getSensorName KEYWORD2
getAccuracy KEYWORD2
getPhySensorInfo KEYWORD2
getSensorInfo KEYWORD2
disableGpio KEYWORD2
setDebug KEYWORD2
setDebugCallback KEYWORD2
### SensorBMA423 Coloring Map ###
enablePowerSave KEYWORD2
disablePowerSave KEYWORD2
disableInterruptCtrl KEYWORD2
enableInterruptCtrl KEYWORD2
enableAccelerometer KEYWORD2
disableAccelerometer KEYWORD2
configAccelerometer KEYWORD2
getAccelRaw KEYWORD2
getAccelerometer KEYWORD2
getTemperature KEYWORD2
direction KEYWORD2
setRemapAxes KEYWORD2
setStepCounterWatermark KEYWORD2
resetPedometer KEYWORD2
enableFeature KEYWORD2
readIrqStatus KEYWORD2
configInterrupt KEYWORD2
configFeatureInterrupt KEYWORD2
enablePedometerIRQ KEYWORD2
enableTiltIRQ KEYWORD2
enableWakeupIRQ KEYWORD2
enableAnyNoMotionIRQ KEYWORD2
enableActivityIRQ KEYWORD2
disablePedometerIRQ KEYWORD2
disableTiltIRQ KEYWORD2
disableWakeupIRQ KEYWORD2
disableAnyNoMotionIRQ KEYWORD2
disableActivityIRQ KEYWORD2
isActivity KEYWORD2
isTilt KEYWORD2
isDoubleTap KEYWORD2
isAnyNoMotion KEYWORD2
isPedometer KEYWORD2
### SensorCM32181 Coloring Map ###
setSampling KEYWORD2
setIntThreshold KEYWORD2
powerSave KEYWORD2
getRaw KEYWORD2
getLux KEYWORD2
### SensorDRV2605 Coloring Map ###
setWaveform KEYWORD2
selectLibrary KEYWORD2
run KEYWORD2
stop KEYWORD2
setMode KEYWORD2
setRealtimeValue KEYWORD2
useERM KEYWORD2
useLRA KEYWORD2
### SensorLTR553 Coloring Map ###
setIRQLevel KEYWORD2
enableIRQ KEYWORD2
disableIRQ KEYWORD2
psAvailable KEYWORD2
setLightSensorThreshold KEYWORD2
setLightSensorPersists KEYWORD2
setLightSensorRate KEYWORD2
enableLightSensor KEYWORD2
disableLightSensor KEYWORD2
setLightSensorGain KEYWORD2
getLightSensor KEYWORD2
setProximityPersists KEYWORD2
setProximityThreshold KEYWORD2
setProximityRate KEYWORD2
enableProximity KEYWORD2
disableProximity KEYWORD2
enablePsIndicator KEYWORD2
disablePsIndicator KEYWORD2
getProximity KEYWORD2
setPsLedPulsePeriod KEYWORD2
setPsLedDutyCycle KEYWORD2
setPsLedCurrent KEYWORD2
setPsLedPulses KEYWORD2
getPartID KEYWORD2
getRevisionID KEYWORD2
getManufacturerID KEYWORD2
### SensorWireHelper Coloring Map ###
regdump KEYWORD2
dumpDevices KEYWORD2
hexdump KEYWORD2
### TouchDrvCHSC5816 Coloring Map ###
getPoint KEYWORD2
isPressed KEYWORD2
getModelName KEYWORD2
sleep KEYWORD2
wakeup KEYWORD2
idle KEYWORD2
getSupportTouchPoint KEYWORD2
getResolution KEYWORD2
setGpioCallback KEYWORD2
### TouchDrvCST92xx Coloring Map ###
jumpCheck KEYWORD2
setCoverScreenCallback KEYWORD2
### TouchDrvCSTXXX Coloring Map ###
setCenterButtonCoordinate KEYWORD2
setHomeButtonCallback KEYWORD2
disableAutoSleep KEYWORD2
enableAutoSleep KEYWORD2
setSwapXY KEYWORD2
setMirrorXY KEYWORD2
setMaxCoordinates KEYWORD2
### TouchDrvFT6X36 Coloring Map ###
getDeviceMode KEYWORD2
getGesture KEYWORD2
getThreshold KEYWORD2
getMonitorTime KEYWORD2
setMonitorTime KEYWORD2
getLibraryVersion KEYWORD2
interruptPolling KEYWORD2
interruptTrigger KEYWORD2
getVendorID KEYWORD2
getErrorCode KEYWORD2
### TouchDrvGT911 Coloring Map ###
setInterruptMode KEYWORD2
getInterruptMode KEYWORD2
getFwVersion KEYWORD2
getConfigVersion KEYWORD2
updateRefreshRate KEYWORD2
getRefreshRate KEYWORD2
writeConfig KEYWORD2
loadConfig KEYWORD2
reloadConfig KEYWORD2
dumpRegister KEYWORD2
setMaxTouchPoint KEYWORD2
getMaxTouchPoint KEYWORD2
### AW9364LedDriver Coloring Map ###
setBrightness KEYWORD2
getBrightness KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################

View File

@@ -0,0 +1,35 @@
{
"name": "SensorLib",
"version": "0.3.1",
"description": "Commonly used I2C , SPI device multi-platform libraries",
"keywords": "QMC6310, QMI8658, PCF8563, PCF85063, XL9555, BMA423, BHI260AP, DRV2605, CM32181, LTR553, FT5206, FT3267, FT6236, FT6336, CST816S,CST816T,CST816D, CST820, CST226, CHSC5816, GT911, CST9217, CST9220, AW9364",
"authors": [
{
"name": "LewisHe",
"url": "https://github.com/lewisxhe",
"maintainer": true
}
],
"repository": {
"type": "git",
"url": "https://github.com/lewisxhe/SensorsLib.git"
},
"homepage": "https://github.com/lewisxhe/SensorsLib",
"export": {
"include": [
"LICENSE",
"library.json",
"library.properties",
"README.md",
"keywords.txt",
"src/*",
"examples/*"
]
},
"frameworks": [
"arduino",
"espidf"
],
"platforms": "ststm32,espressif32,nordicnrf52,raspberrypi",
"license": "MIT"
}

View File

@@ -0,0 +1,9 @@
name=SensorLib
version=0.3.1
author=Lewis He
maintainer=Lewis He <lewishe@outlook.com>
sentence=Commonly used I2C , SPI device multi-platform libraries
paragraph=Support QMC6310,QMI8658,PCF8563,PCF85063,XL9555,BMA423,BHI260AP,DRV2605,CM32181,LTR553,FT5206,FT3267,FT6236,FT6336,CST816S/T/D,CST820,CST226,CHSC5816,GT911,CST9217,CST9220,AW9364
category=Communication
url=https://github.com/lewisxhe/SensorsLib
architectures=*

View File

@@ -0,0 +1,226 @@
;PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[platformio]
; !LedDriver
; src_dir = examples/AW9364_LedDriver
; !Fuel gauge
; src_dir = examples/BQ27220_GaugeExample
; !Haptic Driver
; src_dir = examples/DRV2605_Basic
; !Light Sensor
; src_dir = examples/LTR553ALS_Sensor
; src_dir = examples/CM32181_LightSensor
; src_dir = examples/CM32181_LightSensorInterrupt
; !Real-time clock
; src_dir = examples/PCF85063_AlarmByUnits
; src_dir = examples/PCF85063_ClockOutput
; src_dir = examples/PCF85063_SimpleTime
; src_dir = examples/PCF8563_AlarmByUnits
; src_dir = examples/PCF8563_ClockOutput
; src_dir = examples/PCF8563_SimpleTime
; src_dir = examples/PCF8563_TimeLib
; src_dir = examples/PCF8563_TimeSynchronization
; !IMU examples
src_dir = examples/BHI260AP_6DoF
; src_dir = examples/BHI260AP_Orientation
; src_dir = examples/BHI260AP_StepCounter
; src_dir = examples/BHI260AP_aux_BMM150
; src_dir = examples/BHI260AP_aux_BMM150_BME280
; src_dir = examples/BHI260AP_aux_BMM150_euler
; src_dir = examples/BHI260AP_aux_BMM150_quaternion
; src_dir = examples/BHI260AP_aux_BMM150_BME280_Expand_GPIO
; src_dir = examples/BHI260AP_Activity
; src_dir = examples/BHI260AP_Euler
; src_dir = examples/BHI260AP_Expand_GPIO
; src_dir = examples/BHI260AP_UpdateFirmware
; src_dir = examples/BHI260AP_Debug
; src_dir = examples/BHI260AP_Commander
; src_dir = examples/BHI260AP_Klio_RecognizeMultiple
; src_dir = examples/BHI260AP_Klio_Recognition
; src_dir = examples/BHI260AP_Klio_Selflearning
; src_dir = examples/QMI8658_BlockExample
; src_dir = examples/QMI8658_CalibrationExample
; src_dir = examples/QMI8658_GetDataExample
; src_dir = examples/QMI8658_InterruptBlockExample
; src_dir = examples/QMI8658_InterruptExample
; src_dir = examples/QMI8658_LockingMechanismExample
; src_dir = examples/QMI8658_MadgwickAHRS
; src_dir = examples/QMI8658_MotionDetectionExample
; src_dir = examples/QMI8658_PedometerExample
; src_dir = examples/QMI8658_ReadFromFifoExample
; src_dir = examples/QMI8658_TapDetectionExample
; src_dir = examples/QMI8658_WakeOnMotion
; src_dir = examples/QMI8658_WakeOnMotionCallBackExample
; !Magnetometer
; src_dir = examples/QMC6310_CalibrateExample
; src_dir = examples/QMC6310_CompassExample
; src_dir = examples/QMC6310_GetDataExample
; src_dir = examples/QMC6310_GetPolarExample
; src_dir = examples/BMM150_GetDataExample
; !Accelerometer
; src_dir = examples/BMA423_Accelerometer
; src_dir = examples/BMA423_Feature
; src_dir = examples/BMA423_Orientation
; src_dir = examples/BMA423_Temperature
; !GPIO Expansion examples
; src_dir = examples/XL9555_AdjustBacklight
; src_dir = examples/XL9555_ExtensionIOInterrupt
; src_dir = examples/XL9555_ExtensionIORead
; src_dir = examples/XL9555_ExtensionIOWrite
; src_dir = examples/XL9555_ioEvent
; src_dir = examples/XL9555_ExtensionSPI
; src_dir = examples/CustomCallbackTouchDrvInterface
; src_dir = examples/CustomCallbackUsageExamples
; src_dir = examples/SensorWireHelper
; !Touch devices support list
; src_dir = examples/TouchDrvInterface_Example
; src_dir = examples/TouchDrv_CHSC5816_GetPoint
; src_dir = examples/TouchDrv_CST9217_GetPoint
; src_dir = examples/TouchDrv_CSTxxx_GetPoint
; src_dir = examples/TouchDrv_FT6232_GetPoint
; src_dir = examples/TouchDrv_GT911_GetPoint
; src_dir = examples/TouchDrv_GT9895_GetPoint
; default_envs = esp32dev_arduino
; default_envs = esp32s3_arduino
; default_envs = esp32c3_arduino
; default_envs = rp2040_arduino
; default_envs = nrf52840_arduino
; default_envs = stm32_arduino
default_envs = pico_mbed
; src_dir =examples/mbed
; boards_dir = test/board
[env]
lib_extra_dirs = .
monitor_speed = 115200
build_flags =
; -DSENSOR_SDA=8
; -DSENSOR_SCL=9
; -DSENSOR_IRQ=3
; -DARDUINO_T_DECK
; -DARDUINO_T_AMOLED_191
; -DARDUINO_T_AMOLED_191_QWIIC
; -DARDUINO_T_AMOLED_241
; -DARDUINO_T_AMOLED_147
; -DARDUINO_T_DISPLAY_S3_PRO
; -DARDUINO_T_DISPLAY_S3
; -DARDUINO_T_EPD47_S3
; -DARDUINO_T_WATCH_S3_U
; -DARDUINO_T_ULTIMA
; -DUSE_SPI_INTERFACE=1
; -DLOG_PORT=Serial
; -DBHI260AP_PARSE_DATA_DUMP
-Wignored-qualifiers
-Wnarrowing
-Wtype-limits
; -Werror
-Wall
-Wunused-variable
-Werror=format
-Wmissing-field-initializers
-std=c++11
lib_deps =
creativerobotics/Commander @ ^4.3.0
[env:esp32dev_arduino]
extends = env
platform = espressif32@6.8.1
framework = arduino
board = esp32dev
build_flags =
${env.build_flags}
-DCORE_DEBUG_LEVEL=0
[env:esp32c3_arduino]
extends = env
platform = espressif32@6.8.1
framework = arduino
board = esp32-c3-devkitm-1
build_flags =
${env.build_flags}
-DCORE_DEBUG_LEVEL=0
[env:esp32s3_arduino]
extends = env
platform = espressif32@6.8.1
framework = arduino
board = esp32-s3-devkitm-1
build_flags =
${env.build_flags}
-DARDUINO_USB_CDC_ON_BOOT=1
; -UARDUINO_USB_CDC_ON_BOOT
-DCORE_DEBUG_LEVEL=0
[env:rp2040_arduino]
extends = env
platform = raspberrypi
board = pico
framework = arduino
board_build.core = earlephilhower
[env:nrf52840_arduino]
extends = env
platform = nordicnrf52@10.6.0
board = nrf52840_dk_adafruit
framework = arduino
monitor_speed = 115200
upload_protocol = nrfutil
; upload_protocol = nrfjprog
; upload_protocol = jlink
build_flags =
${env.build_flags}
-DCFG_DEBUG=3
-DCFG_LOGGER=0
-DCFG_SYSVIEW=1
lib_deps =
adafruit/SdFat - Adafruit Fork @ ^2.2.3 ;BHI260AP_UpdateFirmware example use
creativerobotics/Commander @ ^4.3.0 ;BHI260AP_aux_BMM150_BME280_Expand_GPIO example use
[env:stm32_arduino]
extends = env
platform = ststm32
framework = arduino
board = nucleo_f411re
upload_protocol = stlink
[env:pico_mbed]
extends = env
platform = raspberrypi
framework = arduino
board = pico

View File

@@ -0,0 +1,131 @@
/**
*
* @license MIT License
*
* Copyright (c) 2024 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file AW9364LedDriver.hpp
* @author Lewis He (lewishe@outlook.com)
* @date 2024-11-22
*
*/
#pragma once
#include "SensorLib.h"
#include "VirtualGpio.hpp"
constexpr uint8_t MAX_BRIGHTNESS_STEPS = 16;
class AW9364LedDriver
{
public:
void begin(uint8_t pin)
{
_driver_pin = pin;
_virtualGpio = NULL;
this->_pinMode(_driver_pin, OUTPUT);
this->_digitalWrite(_driver_pin, LOW);
}
void begin(VirtualGpio *handler, uint8_t pin)
{
_virtualGpio = handler;
_driver_pin = pin;
this->_pinMode(_driver_pin, OUTPUT);
this->_digitalWrite(_driver_pin, LOW);
}
void setBrightness(uint8_t value)
{
if (_brightness == value) {
return;
}
if (value > 16) {
value = 16;
}
if (value == 0) {
this->_digitalWrite(_driver_pin, 0);
_brightness = 0;
return;
}
if (_brightness == 0) {
this->_digitalWrite(_driver_pin, 1);
_brightness = MAX_BRIGHTNESS_STEPS;
}
int from = MAX_BRIGHTNESS_STEPS - _brightness;
int to = MAX_BRIGHTNESS_STEPS - value;
int num = (MAX_BRIGHTNESS_STEPS + to - from) % MAX_BRIGHTNESS_STEPS;
uint32_t frequency = 0;
if (_virtualGpio) {
// If use I / O port Expander for driving, need to increase the I2C communication rate.
// The test uses XINLUDA XL9555. The manual advertises the maximum communication rate as 400K.
// In fact, it can be driven normally at 1000K.
// https://item.szlcsc.com/datasheet/XL9555/639796.html
frequency = _virtualGpio->getClock();
_virtualGpio->setClock(1000000UL);
}
for (int i = 0; i < num; i++) {
this->_digitalWrite(_driver_pin, 0);
this->_digitalWrite(_driver_pin, 1);
}
if (_virtualGpio) {
// Restore the original communication speed to avoid disrupting
// the communication of other devices that do not support high-speed rates
_virtualGpio->setClock(frequency);
}
_brightness = value;
}
uint8_t getBrightness() const
{
return _brightness;
}
protected:
void _pinMode(uint8_t pin, uint8_t mode)
{
if (_virtualGpio) {
_virtualGpio->pinMode(pin, mode);
} else {
pinMode(pin, mode);
}
}
void _digitalWrite(uint8_t pin, uint8_t value)
{
if (_virtualGpio) {
_virtualGpio->digitalWrite(pin, value);
} else {
digitalWrite(pin, value);
}
}
private:
VirtualGpio *_virtualGpio = NULL;
uint8_t _driver_pin;
uint8_t _brightness = 0;
};

View File

@@ -0,0 +1,82 @@
/**
*
* @license MIT License
*
* Copyright (c) 2025 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file BoschFirmware.h
* @author Lewis He (lewishe@outlook.com)
* @date 2025-01-27
*/
#pragma once
#if defined(BOSCH_APP30_SHUTTLE_BHI260_FW)
#include "bosch/firmware/bosch_app30_shuttle_bhi260.h"
#elif defined(BOSCH_APP30_SHUTTLE_BHI260_AUX_BMM150FW)
#include "bosch/firmware/bosch_app30_shuttle_bhi260_aux_bmm150.h"
#elif defined(BOSCH_APP30_SHUTTLE_BHI260_BME68X)
#include "bosch/firmware/bosch_app30_shuttle_bhi260_bme68x.h"
#elif defined(BOSCH_APP30_SHUTTLE_BHI260_BMP390)
#include "bosch/firmware/bosch_app30_shuttle_bhi260_bmp390.h"
#elif defined(BOSCH_APP30_SHUTTLE_BHI260_TURBO)
#include "bosch/firmware/bosch_app30_shuttle_bhi260_turbo.h"
#elif defined(BOSCH_BHI260_AUX_BEM280)
#include "bosch/firmware/bosch_bhi260_aux_bem280.h"
#elif defined(BOSCH_BHI260_AUX_BMM150_BEM280)
#include "bosch/firmware/bosch_bhi260_aux_bmm150_bem280.h"
#elif defined(BOSCH_BHI260_AUX_BMM150_BEM280_GPIO)
#include "bosch/firmware/bosch_bhi260_aux_bmm150_bem280_gpio.h"
#elif defined(BOSCH_BHI260_AUX_BMM150_GPIO)
#include "bosch/firmware/bosch_bhi260_aux_bmm150_gpio.h"
#elif defined(BOSCH_BHI260_GPIO)
#include "bosch/firmware/bosch_bhi260_gpio.h"
#elif defined(BOSCH_BHI260_KLIO)
#include "bosch/firmware/bosch_bhi260_klio.h"
#elif defined(BOSCH_APP30_SHUTTLE_BHI260_AUX_BMM150_FLASH)
#include "bosch/firmware/bosch_app30_shuttle_bhi260_aux_bmm150_flash.h"
#elif defined(BOSCH_APP30_SHUTTLE_BHI260_BME68X_FLASH)
#include "bosch/firmware/bosch_app30_shuttle_bhi260_bme68x_flash.h"
#elif defined(BOSCH_APP30_SHUTTLE_BHI260_BMP390_FLASH)
#include "bosch/firmware/bosch_app30_shuttle_bhi260_bmp390_flash.h"
#elif defined(BOSCH_APP30_SHUTTLE_BHI260_FLASH)
#include "bosch/firmware/bosch_app30_shuttle_bhi260_flash.h"
#elif defined(BOSCH_APP30_SHUTTLE_BHI260_TURBO_FLASH)
#include "bosch/firmware/bosch_app30_shuttle_bhi260_turbo_flash.h"
#elif defined(BOSCH_BHI260_AUX_BEM280_FLASH)
#include "bosch/firmware/bosch_bhi260_aux_bem280_flash.h"
#elif defined(BOSCH_BHI260_AUX_BMM150_BEM280_FLASH)
#include "bosch/firmware/bosch_bhi260_aux_bmm150_bem280_flash.h"
#elif defined(BOSCH_BHI260_AUX_BMM150_BEM280_GPIO_FLASH)
#include "bosch/firmware/bosch_bhi260_aux_bmm150_bem280_gpio_flash.h"
#elif defined(BOSCH_BHI260_AUX_BMM150_GPIO_FLASH)
#include "bosch/firmware/bosch_bhi260_aux_bmm150_gpio_flash.h"
#elif defined(BOSCH_BHI260_GPIO_FLASH)
#include "bosch/firmware/bosch_bhi260_gpio_flash.h"
#elif defined(BOSCH_BHI260_KLIO_FLASH)
#include "bosch/firmware/bosch_bhi260_klio_flash.h"
#elif defined(BOSCH_BHI260_KLIO_TURBO_FLASH)
#include "bosch/firmware/bosch_bhi260_klio_turbo_flash.h"
#else
#warning "None of the defined conditions were met, so no firmware will be included".
#endif

View File

@@ -0,0 +1,160 @@
/**
*
* @license MIT License
*
* Copyright (c) 2024 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file TouchDrv_GT9895_GetPoint.ino
* @author Lewis He (lewishe@outlook.com)
* @date 2024-09-14
*
*/
#pragma once
#if defined(ARDUINO_T_DECK)
// T-Deck GT911
#define TOUCH_SDA 18
#define TOUCH_SCL 8
#define TOUCH_IRQ 16
#define TOUCH_RST -1
#elif defined(ARDUINO_T_AMOLED_191)
// T-Display-AMOLED 1.91 Inch CST816T✅
#define TOUCH_SDA 3
#define TOUCH_SCL 2
#define TOUCH_IRQ 21
#define TOUCH_RST -1
#elif defined(ARDUINO_T_AMOLED_191_QWIIC)
// T-Display-AMOLED 1.91 Inch QWIIC
#define SENSOR_SDA 3
#define SENSOR_SCL 2
#define SENSOR_IRQ 43//TX
#define SENSOR_RST 44//RX
#elif defined(ARDUINO_T_AMOLED_241)
// T4-S3 CST226SE ✅
#define TOUCH_SDA 6
#define TOUCH_SCL 7
#define TOUCH_IRQ 8
#define TOUCH_RST 17
#elif defined(ARDUINO_T_AMOLED_147)
// T-Display-Lite 1.47 Inch CHSC5816 ✅
#define SENSOR_SDA 1
#define SENSOR_SCL 2
#define SENSOR_IRQ 8
#define TOUCH_SDA 1
#define TOUCH_SCL 2
#define TOUCH_RST 14
#define TOUCH_IRQ 13
#elif defined(ARDUINO_T_DISPLAY_S3_PRO)
// T-Display-S3-Pro CST226SE✅
#define SENSOR_SDA 5
#define SENSOR_SCL 6
#define SENSOR_IRQ 21
#define SENSOR_RST 13
#elif defined(ARDUINO_T_DISPLAY_S3)
// T-Display-S3 CST816T✅
#define SENSOR_SDA 18
#define SENSOR_SCL 17
#define SENSOR_IRQ 16
#define SENSOR_RST 21
#elif defined(ARDUINO_T_EPD47_S3)
// T-EPD47 S3 GT911 2 Point touch✅
#define SENSOR_SDA 6
#define SENSOR_SCL 5
#define SENSOR_IRQ 15
#define SENSOR_RST 41
#elif defined(ARDUINO_T_WATCH_S3_U)
// T-Watch-S3-U
#define SENSOR_SDA 2
#define SENSOR_SCL 3
#define SENSOR_IRQ 12
#define SENSOR_RST 16
#elif defined(ARDUINO_T_WATCH_S3)
// T-Watch-S3
#define SENSOR_SDA 10
#define SENSOR_SCL 11
#define PCF8563_IRQ 17
#define BMA423_IRQ 14
#define FT6336_SDA 39
#define FT6336_SCL 40
#define FT6336_IRQ 16
#elif defined(ARDUINO_T_BEAM_S3_SUPREME)
#define OLED_SDA (17)
#define OLED_SCL (18)
#define SPI_MOSI (35)
#define SPI_SCK (36)
#define SPI_MISO (37)
#define SPI_CS (47)
#define IMU_CS (34)
#define IMU_IRQ (33) //INTERRUPT PIN1 & PIN2 ,Use or logic to form a pin
#define RTC_IRQ (14)
#define RTC_PMU_SDA (42)
#define RTC_PMU_SCL (41)
#elif defined(ARDUINO_BHI260_SENSOR)
#define SPI_MOSI 33
#define SPI_MISO 34
#define SPI_SCK 35
#define BHI260_CS 36
#define BHI260_IRQ 37
#define BHI260_RST 47
#define BHI260_POWER 48
#define SENSOR_SDA 9
#define SENSOR_SCL 8
#define USE_SPI_INTERFACE 1
#define TOUCH_BUTTON 14
#elif defined(ARDUINO_T_ULTIMA)
#define SPI_MOSI 4
#define SPI_MISO 7
#define SPI_SCK 26
#define BHI260_CS 27
#define BHI260_IRQ 5
#define BHI260_RST -1
#define USE_SPI_INTERFACE 1
#endif

View File

@@ -0,0 +1,320 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file ExtensionIOXL9555.hpp
* @author Lewis He (lewishe@outlook.com)
* @date 2022-12-27
*
*/
#pragma once
#include "REG/XL9555Constants.h"
#include "SensorPlatform.hpp"
#include "ExtensionSPI.hpp"
#include "VirtualGpio.hpp"
typedef void (*gpio_event_t)(void *user_data);
typedef struct ioEvent {
uint8_t mode;
gpio_event_t cb;
void *user_data;
uint8_t last_state;
ioEvent() : mode(0), cb(NULL), user_data(NULL), last_state(LOW)
{
}
} ioEvent_t;
class ExtensionIOXL9555 :
public VirtualGpio,
public XL95xxConstants,
public ExtensionSPI<ExtensionIOXL9555>
{
friend class ExtensionSPI<ExtensionIOXL9555>;
public:
enum {
PORT0,
PORT1,
};
enum ExtensionGPIO {
IO0,
IO1,
IO2,
IO3,
IO4,
IO5,
IO6,
IO7,
IO8,
IO9,
IO10,
IO11,
IO12,
IO13,
IO14,
IO15,
};
ExtensionIOXL9555() : comm(nullptr) {}
~ExtensionIOXL9555()
{
if (comm) {
comm->deinit();
}
}
#if defined(ARDUINO)
bool begin(TwoWire &wire, uint8_t addr = XL9555_UNKOWN_ADDRESS, int sda = -1, int scl = -1)
{
comm = std::make_unique<SensorCommI2C>(wire, addr, sda, scl);
if (!comm) {
return false;
}
comm->init();
return initImpl(addr);
}
#elif defined(ESP_PLATFORM)
#if defined(USEING_I2C_LEGACY)
bool begin(i2c_port_t port_num, uint8_t addr = XL9555_UNKOWN_ADDRESS, int sda = -1, int scl = -1)
{
comm = std::make_unique<SensorCommI2C>(port_num, addr, sda, scl);
if (!comm) {
return false;
}
comm->init();
return initImpl(addr);
}
#else
bool begin(i2c_master_bus_handle_t handle, uint8_t addr = XL9555_UNKOWN_ADDRESS)
{
comm = std::make_unique<SensorCommI2C>(handle, addr);
if (!comm) {
return false;
}
comm->init();
return initImpl(addr);
}
#endif //ESP_PLATFORM
#endif //ARDUINO
bool begin(SensorCommCustom::CustomCallback callback, uint8_t addr)
{
comm = std::make_unique<SensorCommCustom>(callback, addr);
if (!comm) {
return false;
}
comm->init();
return initImpl(addr);
}
void deinit()
{
// end();
}
void pinMode(uint8_t pin, uint8_t mode)
{
uint8_t registers = 0;
if (pin >= IO8) {
pin -= IO8;
registers = XL9555_CTRL_CFG1;
} else {
registers = XL9555_CTRL_CFG0;
}
switch (mode) {
case INPUT:
comm->setRegisterBit(registers, pin);
break;
case OUTPUT:
comm->clrRegisterBit(registers, pin);
break;
default:
break;
}
}
int digitalRead(uint8_t pin)
{
uint8_t registers = 0;
if (pin >= IO8) {
pin -= IO8;
registers = XL9555_CTRL_INP1;
} else {
registers = XL9555_CTRL_INP0;
}
return comm->getRegisterBit(registers, pin);
}
void digitalWrite(uint8_t pin, uint8_t val)
{
uint8_t registers = 0;
if (pin >= IO8) {
pin -= IO8;
registers = XL9555_CTRL_OUTP1;
} else {
registers = XL9555_CTRL_OUTP0;
}
val ? comm->setRegisterBit(registers, pin) : comm->clrRegisterBit(registers, pin);
}
// Invert gpio
void digitalToggle(uint8_t pin)
{
int state = 1 - digitalRead(pin);
digitalWrite(pin, state);
}
// Read 8-bit gpio input status
int readPort(uint8_t port)
{
return comm->readRegister(port == PORT0 ? XL9555_CTRL_INP0 : XL9555_CTRL_INP1);
}
// Write 8 bits of data to the specified port
int writePort(uint8_t port, uint8_t mask)
{
return comm->writeRegister(port == PORT0 ? XL9555_CTRL_OUTP0 : XL9555_CTRL_OUTP1, mask);
}
// Read 16-bit gpio input status
uint16_t read()
{
uint16_t val = 0x0;
comm->readRegister(XL9555_CTRL_INP0, (uint8_t *)&val, 2);
return val;
}
// Write 16-bit data to gpio, low bit port 0
void write(uint16_t value)
{
uint8_t buffer[2] = {highByte(value), lowByte(value)};
comm->writeRegister(XL9555_CTRL_OUTP0, buffer, 2);
}
// Read the specified port configuration status
int readConfig(uint8_t port)
{
return comm->readRegister(port == PORT0 ? XL9555_CTRL_CFG0 : XL9555_CTRL_CFG1);
}
// Configure the specified port as input or output , 0xFF = all pin input , 0x00 = all pin output
int configPort(uint8_t port, uint8_t mask)
{
return comm->writeRegister(port == PORT0 ? XL9555_CTRL_CFG0 : XL9555_CTRL_CFG1, mask);
}
void setPinEvent(uint8_t pin, uint8_t mode, gpio_event_t event, void *user_data)
{
if (pin > XL9555_MAX_PIN) {
log_e("XL9555 Max use io pin is 0 ~ 15 .");
return;
}
this->event[pin].cb = event;
this->event[pin].mode = mode;
this->event[pin].user_data = user_data;
}
void removePinEvent(uint8_t pin)
{
if (pin > XL9555_MAX_PIN) {
log_e("XL9555 Max use io pin is 0 ~ 15 .");
return;
}
this->event[pin].cb = NULL;
}
void update()
{
uint16_t val = this->read();
int i = XL9555_MAX_PIN;
for (; i >= 0; i--) {
uint8_t _index = XL9555_MAX_PIN - i;
if (this->event[_index].cb != NULL) {
if (!(val & 1)) {
if (this->event[_index].mode == LOW) {
this->event[_index].cb(this->event[_index].user_data);
}
this->event[_index].last_state = LOW;
} else {
if (this->event[_index].mode == HIGH && this->event[_index].last_state == LOW) {
this->event[_index].cb(this->event[_index].user_data);
}
this->event[_index].last_state = HIGH;
}
}
val >>= 1;
}
}
void setClock(uint32_t frequency)
{
//TODO:
}
uint32_t getClock()
{
//TODO:
return 0;
}
private:
bool initImpl(uint8_t addr)
{
if (addr == XL9555_UNKOWN_ADDRESS) {
log_d("Try to automatically discover the device");
for (uint8_t a = XL9555_SLAVE_ADDRESS0; a <= XL9555_SLAVE_ADDRESS7; ++a) {
I2CParam params(I2CParam::I2C_SET_ADDR, a);
comm->setParams(params);
log_d("Try to use 0x%02x address.", a);
if (comm->readRegister(XL9555_CTRL_INP0) != -1) {
log_d("Found the xl9555 chip address is 0x%X", a);
return true;
}
}
log_e("No found xl9555 chip ...");
return false;
}
if (comm->readRegister(XL9555_CTRL_INP0) < 0 ) {
return false;
}
return true;
}
ioEvent_t event[16];
protected:
uint32_t _frequency;
std::unique_ptr<SensorCommBase> comm;
};

View File

@@ -0,0 +1,124 @@
/**
*
* @license MIT License
*
* Copyright (c) 2024 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file ExtensionSPI.hpp
* @author Lewis He (lewishe@outlook.com)
* @date 2024-01-19
*
*/
#pragma once
#include "SensorLib.h"
template <class chipType>
class ExtensionSPI
{
public:
void beginSPI(int mosi,
int miso,
int sck,
int cs
)
{
_mosi = mosi;
_miso = miso;
_sck = sck;
_cs = cs;
thisChip().pinMode(_mosi, OUTPUT);
thisChip().pinMode(_sck, OUTPUT);
if (_cs != -1) {
thisChip().pinMode(_cs, OUTPUT);
thisChip().digitalWrite(_cs, HIGH);
}
if (_miso != -1) {
thisChip().pinMode(_miso, INPUT);
}
thisChip().digitalWrite(_mosi, HIGH);
thisChip().digitalWrite(_sck, HIGH);
}
void setBitOrder(uint8_t order)
{
_order = order & 1;
}
uint8_t transfer8(uint8_t val)
{
return transferDataBits(val, 8);
}
uint16_t transfer9(uint16_t val)
{
return transferDataBits(val, 9);
}
uint32_t transferDataBits(uint32_t val, uint32_t bits)
{
uint32_t mask = _BV(bits - 1);
uint8_t out = 0;
if (_cs != -1) {
thisChip().digitalWrite(_cs, LOW);
}
for (int i = 0; i < bits ; i++) {
thisChip().digitalWrite(_sck, LOW);
out <<= 1;
if (_miso != -1) {
if (thisChip().digitalRead(_miso)) {
out |= 0x01;
}
}
thisChip().digitalWrite(_mosi, val & mask ? HIGH : LOW);
val <<= 1;
thisChip().digitalWrite(_sck, HIGH);
}
if (_cs != -1) {
thisChip().digitalWrite(_cs, HIGH);
}
return out;
}
protected:
inline const chipType &thisChip() const
{
return static_cast<const chipType &>(*this);
}
inline chipType &thisChip()
{
return static_cast<chipType &>(*this);
}
private:
int _mosi;
int _sck;
int _miso;
int _order;
int _cs;
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,545 @@
/**
*
* @license MIT License
*
* Copyright (c) 2025 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file BMA423Config.h
* @author Lewis He (lewishe@outlook.com)
* @date 2025-01-20
*
*/
#pragma once
/**\name Feature configuration file */
static const unsigned char bma423_config_file[6144] = {
0x80, 0x2e, 0xfc, 0x00, 0x80, 0x2e, 0xfe, 0x00, 0xc8, 0x2e, 0x00, 0x2e,
0x80, 0x2e, 0xfa, 0x00, 0x80, 0x2e, 0x23, 0xb1, 0x80, 0x2e, 0xfd, 0x00,
0x80, 0x2e, 0xfb, 0x00, 0x80, 0x2e, 0x5a, 0xb1, 0x50, 0x39, 0x21, 0x2e,
0xb0, 0xf0, 0x10, 0x30, 0x21, 0x2e, 0x16, 0xf0, 0x80, 0x2e, 0xfc, 0x01,
0x5d, 0x50, 0x45, 0x52, 0x01, 0x42, 0x3b, 0x80, 0x41, 0x30, 0x01, 0x42,
0x3c, 0x80, 0x00, 0x2e, 0x01, 0x40, 0x01, 0x42, 0x21, 0x2e, 0xff, 0xaf,
0xb8, 0x2e, 0xb6, 0xd6, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0xfd, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 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, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x24, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x2e,
0x99, 0x01, 0x20, 0x26, 0x98, 0x2e, 0xf6, 0x00, 0x98, 0x2e, 0xe9, 0x01,
0x10, 0x30, 0x21, 0x2e, 0x59, 0xf0, 0x98, 0x2e, 0xd8, 0x00, 0x00, 0x2e,
0x00, 0x2e, 0xd0, 0x2e, 0x98, 0x2e, 0xdd, 0x00, 0x01, 0x2e, 0x56, 0x00,
0x00, 0xb2, 0x11, 0x2f, 0x00, 0x30, 0x21, 0x2e, 0x56, 0x00, 0x41, 0x50,
0x98, 0x2e, 0xcc, 0xb0, 0x41, 0x50, 0x98, 0x2e, 0x8f, 0xb4, 0x01, 0x2e,
0x03, 0xf0, 0x0d, 0xbc, 0x0f, 0xb8, 0x00, 0x90, 0x02, 0x2f, 0x45, 0x50,
0x21, 0x2e, 0xbc, 0xf0, 0x01, 0x2e, 0x55, 0x00, 0x00, 0xb2, 0x1a, 0x2f,
0x00, 0x30, 0x21, 0x2e, 0x55, 0x00, 0x43, 0x50, 0x98, 0x2e, 0xcc, 0xb0,
0x43, 0x50, 0x98, 0x2e, 0xdc, 0xb1, 0x43, 0x50, 0x98, 0x2e, 0x92, 0xb5,
0x43, 0x50, 0x98, 0x2e, 0x00, 0xb0, 0x01, 0x2e, 0x1c, 0x01, 0x0f, 0xbc,
0x0f, 0xb8, 0x00, 0x90, 0x45, 0x50, 0x02, 0x2f, 0x21, 0x2e, 0xbc, 0xf0,
0x02, 0x2d, 0x21, 0x2e, 0xba, 0xf0, 0x98, 0x2e, 0xd8, 0x00, 0xc3, 0x2d,
0x01, 0x2e, 0x55, 0xf0, 0xc0, 0x2e, 0x21, 0x2e, 0x55, 0xf0, 0x03, 0x2e,
0x00, 0xf0, 0x45, 0x54, 0x01, 0x2e, 0x59, 0xf0, 0x4a, 0x0e, 0x02, 0x2f,
0xf1, 0x33, 0x0d, 0x2c, 0x01, 0x08, 0xf2, 0x30, 0x4a, 0x08, 0x79, 0x84,
0x82, 0xa2, 0x04, 0x2f, 0x02, 0x34, 0x82, 0x0a, 0x47, 0xa2, 0x03, 0x2c,
0x10, 0x22, 0x45, 0x52, 0x01, 0x0a, 0xc0, 0x2e, 0x21, 0x2e, 0x59, 0xf0,
0x00, 0x31, 0xc0, 0x2e, 0x21, 0x2e, 0xba, 0xf0, 0xc8, 0x2e, 0xc8, 0x2e,
0xc8, 0x2e, 0xc8, 0x2e, 0xc8, 0x2e, 0x44, 0x47, 0xaa, 0x00, 0x05, 0x00,
0x2d, 0x01, 0xd4, 0x7b, 0x3b, 0x01, 0xdb, 0x7a, 0x04, 0x00, 0x3f, 0x7b,
0xcd, 0x6c, 0xc3, 0x04, 0x85, 0x09, 0xc3, 0x04, 0xec, 0xe6, 0x0c, 0x46,
0x01, 0x00, 0x27, 0x00, 0x19, 0x00, 0x96, 0x00, 0xa0, 0x00, 0x01, 0x00,
0x0c, 0x00, 0xf0, 0x3c, 0x00, 0x01, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00,
0x0e, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x43, 0x28, 0x88, 0x00,
0x52, 0x00, 0x4f, 0x00, 0x80, 0x00, 0x5b, 0x00, 0x00, 0x40, 0xaf, 0x00,
0xff, 0x00, 0xff, 0xb7, 0x00, 0x02, 0x00, 0xb0, 0x05, 0x80, 0xb1, 0xf0,
0xc0, 0x00, 0x00, 0x01, 0x5e, 0xf0, 0x39, 0xf0, 0x89, 0xf0, 0x00, 0x20,
0xff, 0x7f, 0x7d, 0x00, 0x5e, 0x00, 0x62, 0x00, 0x7c, 0x00, 0xff, 0xfb,
0x52, 0xf0, 0x56, 0xf0, 0x33, 0x09, 0x33, 0x07, 0x00, 0x08, 0x90, 0x01,
0x00, 0xf8, 0x67, 0x00, 0x4c, 0x04, 0xa0, 0x00, 0xe8, 0x03, 0x81, 0x00,
0x82, 0x00, 0x6a, 0x00, 0x6d, 0x00, 0x6c, 0x00, 0xeb, 0x07, 0xae, 0x07,
0x72, 0x00, 0x6f, 0x00, 0xa1, 0x01, 0x1e, 0x05, 0x47, 0xfd, 0x73, 0x00,
0x77, 0x00, 0x79, 0x00, 0x76, 0x00, 0xcc, 0x00, 0x30, 0x50, 0x50, 0x40,
0x00, 0x18, 0x50, 0x40, 0x56, 0x25, 0x47, 0x25, 0x00, 0x18, 0x2e, 0x00,
0x41, 0x40, 0xa7, 0x02, 0x09, 0x18, 0xc6, 0x00, 0xfb, 0x7f, 0x00, 0x30,
0x49, 0x52, 0x05, 0x30, 0x05, 0x2c, 0x17, 0x03, 0x1e, 0xbd, 0xd2, 0xba,
0x92, 0xb8, 0x6a, 0x0b, 0x61, 0x0e, 0xf9, 0x2f, 0x61, 0x1a, 0x01, 0x2f,
0x5d, 0x0e, 0xf5, 0x2f, 0xd4, 0x7f, 0x02, 0x30, 0x1f, 0x2c, 0xe3, 0x7f,
0x85, 0x01, 0xd1, 0x03, 0x7c, 0x0e, 0x03, 0x2f, 0x7c, 0x1a, 0x0f, 0x2f,
0x73, 0x0f, 0x0d, 0x2f, 0xe3, 0x6f, 0xde, 0x04, 0x5f, 0xba, 0x11, 0xbf,
0xb4, 0x0b, 0xd4, 0x6f, 0x27, 0x07, 0xb3, 0x25, 0xd1, 0xbf, 0xeb, 0x7f,
0x07, 0x00, 0xb4, 0x25, 0x96, 0x02, 0xdb, 0x7f, 0x2f, 0xbf, 0x9e, 0xbf,
0x01, 0xb8, 0xd2, 0xba, 0x21, 0xb9, 0x92, 0xb8, 0x06, 0x0a, 0x6f, 0x0b,
0x40, 0x90, 0xdf, 0x2f, 0x40, 0x91, 0xdd, 0x2f, 0xfb, 0x6f, 0xd0, 0x5f,
0xb8, 0x2e, 0x57, 0x50, 0x41, 0x30, 0x02, 0x40, 0x51, 0x0a, 0x01, 0x42,
0x18, 0x82, 0x4b, 0x50, 0x60, 0x42, 0x70, 0x3c, 0x4d, 0x54, 0x42, 0x42,
0x69, 0x82, 0x82, 0x32, 0x43, 0x40, 0x18, 0x08, 0x02, 0x0a, 0x40, 0x42,
0x42, 0x80, 0x02, 0x3f, 0x01, 0x40, 0x10, 0x50, 0x4a, 0x08, 0xfb, 0x7f,
0x11, 0x42, 0x0b, 0x31, 0x0b, 0x42, 0x3e, 0x80, 0x01, 0x32, 0x01, 0x42,
0x00, 0x2e, 0x01, 0x2e, 0x40, 0xf0, 0x13, 0x90, 0x20, 0x2f, 0x03, 0x30,
0x51, 0x50, 0x4f, 0x54, 0xf4, 0x34, 0x06, 0x30, 0x55, 0x52, 0x55, 0x32,
0x1d, 0x1a, 0xe3, 0x22, 0x18, 0x1a, 0x53, 0x58, 0xe3, 0x22, 0x04, 0x30,
0xd5, 0x40, 0xb5, 0x0d, 0xe1, 0xbe, 0x6f, 0xbb, 0x80, 0x91, 0xa9, 0x0d,
0x01, 0x89, 0xb5, 0x23, 0x10, 0xa1, 0xf7, 0x2f, 0xda, 0x0e, 0xf4, 0x34,
0xeb, 0x2f, 0x01, 0x2e, 0x25, 0x00, 0x70, 0x1a, 0x00, 0x30, 0x21, 0x30,
0x02, 0x2c, 0x08, 0x22, 0x30, 0x30, 0x00, 0xb2, 0x06, 0x2f, 0x21, 0x2e,
0x59, 0xf0, 0x98, 0x2e, 0xd8, 0x00, 0x00, 0x2e, 0x00, 0x2e, 0xd0, 0x2e,
0xfb, 0x6f, 0xf0, 0x5f, 0xb8, 0x2e, 0x01, 0x2e, 0xb1, 0xf0, 0x59, 0x52,
0x01, 0x0a, 0x21, 0x2e, 0xb1, 0xf0, 0x01, 0x2e, 0x1c, 0x01, 0x0f, 0xbc,
0x0f, 0xb8, 0x00, 0x90, 0x45, 0x50, 0x02, 0x2f, 0xc0, 0x2e, 0x21, 0x2e,
0xbc, 0xf0, 0xc0, 0x2e, 0x21, 0x2e, 0xba, 0xf0, 0x1a, 0x24, 0x26, 0x00,
0x80, 0x2e, 0x8f, 0x00, 0x03, 0x2e, 0x01, 0x01, 0x05, 0x2e, 0x01, 0x01,
0x92, 0xbd, 0x20, 0x50, 0x03, 0x2e, 0x01, 0x01, 0xbf, 0xba, 0x21, 0xbd,
0x2f, 0xbb, 0x1f, 0xba, 0x40, 0x91, 0xf0, 0x7f, 0x04, 0x2f, 0x80, 0x91,
0x02, 0x2f, 0x00, 0xb3, 0x90, 0x2e, 0xc7, 0xb0, 0x03, 0x2e, 0x7b, 0x00,
0x01, 0x80, 0x40, 0x90, 0x14, 0x2f, 0x41, 0x84, 0xf1, 0x6f, 0x25, 0x2e,
0x7b, 0x00, 0x41, 0x40, 0x23, 0x2e, 0x5a, 0x00, 0x47, 0x52, 0x12, 0x40,
0x52, 0x42, 0x02, 0x30, 0x00, 0x40, 0x40, 0x42, 0xe0, 0x5f, 0x25, 0x2e,
0x57, 0x00, 0x25, 0x2e, 0x58, 0x00, 0x25, 0x2e, 0x5d, 0x00, 0xb8, 0x2e,
0x07, 0x2e, 0x00, 0x01, 0x03, 0x2e, 0x01, 0x01, 0x05, 0x2e, 0x00, 0x01,
0x24, 0xbd, 0x0f, 0x2e, 0x59, 0x00, 0xb5, 0xbd, 0x93, 0xbc, 0x2f, 0xb9,
0xb5, 0xb9, 0x93, 0xb8, 0x3a, 0x1a, 0x06, 0x2f, 0x07, 0x30, 0x25, 0x2e,
0x59, 0x00, 0x2f, 0x2e, 0x57, 0x00, 0x2f, 0x2e, 0x58, 0x00, 0x40, 0xb3,
0x05, 0x30, 0x07, 0x30, 0x0a, 0x2f, 0xf7, 0x6f, 0xe6, 0x7f, 0x00, 0x2e,
0xc6, 0x41, 0x0f, 0x2e, 0x5a, 0x00, 0xb7, 0x05, 0x80, 0xa9, 0xee, 0x05,
0xf7, 0x23, 0xe6, 0x6f, 0x80, 0xb3, 0x06, 0x30, 0x09, 0x2f, 0xe7, 0x7f,
0x00, 0x2e, 0x06, 0x40, 0x0f, 0x2e, 0x5b, 0x00, 0xb7, 0x05, 0x80, 0xa9,
0xee, 0x05, 0xb7, 0x23, 0xe7, 0x6f, 0x00, 0xb3, 0x04, 0x30, 0x0b, 0x2f,
0xf4, 0x6f, 0x02, 0x89, 0xe7, 0x7f, 0x00, 0x2e, 0x04, 0x41, 0x0f, 0x2e,
0x5c, 0x00, 0x27, 0x05, 0x00, 0xa9, 0xec, 0x05, 0x27, 0x23, 0xe7, 0x6f,
0x7b, 0x0f, 0x17, 0x30, 0x0b, 0x2f, 0x73, 0x0f, 0x05, 0x30, 0x17, 0x30,
0x07, 0x2f, 0x63, 0x0f, 0x15, 0x30, 0x17, 0x30, 0x00, 0x2f, 0x07, 0x30,
0xe3, 0x0e, 0x00, 0x2f, 0x05, 0x30, 0x80, 0x90, 0x05, 0x2e, 0x57, 0x00,
0x13, 0x30, 0x13, 0x29, 0xf2, 0x6f, 0x47, 0x5c, 0x17, 0x2f, 0xc0, 0x91,
0x05, 0x30, 0x0b, 0x2f, 0x07, 0x2e, 0x58, 0x00, 0xc1, 0x86, 0x2b, 0x2e,
0x57, 0x00, 0x59, 0x0e, 0x27, 0x2e, 0x58, 0x00, 0x24, 0x2f, 0x2b, 0x2e,
0x5d, 0x00, 0x22, 0x2d, 0x61, 0x0e, 0x29, 0x2e, 0x57, 0x00, 0x2b, 0x2e,
0x58, 0x00, 0x1b, 0x2f, 0x27, 0x2e, 0x5d, 0x00, 0x19, 0x2d, 0x40, 0x91,
0x05, 0x2f, 0x01, 0x30, 0x23, 0x2e, 0x57, 0x00, 0x23, 0x2e, 0x5d, 0x00,
0x06, 0x2d, 0x29, 0x2e, 0x57, 0x00, 0x61, 0x0e, 0x01, 0x2f, 0x27, 0x2e,
0x5d, 0x00, 0x81, 0x40, 0x23, 0x2e, 0x5a, 0x00, 0x30, 0x25, 0x47, 0x52,
0xd4, 0x40, 0x54, 0x42, 0x00, 0x2e, 0xc3, 0x40, 0x43, 0x42, 0x00, 0x2e,
0x03, 0x2e, 0x5d, 0x00, 0x40, 0xb2, 0x0d, 0x2f, 0x81, 0x40, 0x23, 0x2e,
0x5a, 0x00, 0x11, 0x40, 0x91, 0x43, 0x01, 0x34, 0x00, 0x40, 0x80, 0x43,
0x23, 0x2e, 0x5e, 0xf0, 0x03, 0x2d, 0x00, 0x30, 0x21, 0x2e, 0x7b, 0x00,
0xe0, 0x5f, 0xb8, 0x2e, 0x50, 0x50, 0xf0, 0x7f, 0x1a, 0x25, 0x13, 0x40,
0x7b, 0x84, 0xe0, 0x7f, 0x83, 0x42, 0x35, 0x30, 0x11, 0x40, 0x04, 0x40,
0xc1, 0x7f, 0xd4, 0x7f, 0x86, 0x31, 0x07, 0x2e, 0x59, 0xf0, 0x03, 0x2e,
0x1f, 0x01, 0x0d, 0x09, 0x02, 0xab, 0x05, 0x30, 0x8e, 0x09, 0x2c, 0x23,
0xe3, 0xba, 0x42, 0xab, 0x16, 0x30, 0x75, 0x23, 0x59, 0x5c, 0x8e, 0x09,
0x66, 0xbb, 0x82, 0xab, 0x27, 0x30, 0xbe, 0x23, 0x3e, 0x80, 0x25, 0x1a,
0x06, 0x2f, 0x2e, 0x1a, 0x04, 0x2f, 0x26, 0x1a, 0x02, 0x2f, 0xf7, 0x3d,
0x03, 0x2c, 0xdf, 0x08, 0x07, 0x32, 0xdf, 0x0a, 0x14, 0x01, 0x55, 0x01,
0x04, 0x41, 0x14, 0x42, 0x16, 0x01, 0x42, 0x41, 0x45, 0x30, 0x4d, 0x09,
0x04, 0x41, 0x12, 0x42, 0x04, 0x42, 0x40, 0xb3, 0x04, 0x2f, 0xf0, 0x6f,
0x02, 0x30, 0x04, 0x40, 0x94, 0x04, 0x02, 0x42, 0x00, 0x32, 0x08, 0x08,
0x00, 0xb2, 0x00, 0x30, 0x05, 0x2f, 0xe2, 0x6f, 0x00, 0x2e, 0x84, 0x40,
0x04, 0x05, 0x84, 0x42, 0x00, 0x2e, 0x5b, 0x54, 0x4a, 0x08, 0x40, 0xb2,
0xf1, 0x6f, 0x04, 0x2f, 0x42, 0x82, 0x00, 0x2e, 0x42, 0x40, 0x02, 0x04,
0x40, 0x42, 0xb0, 0x5f, 0x27, 0x2e, 0x59, 0xf0, 0xb8, 0x2e, 0x50, 0x50,
0xf7, 0x7f, 0x00, 0x2e, 0x0f, 0x2e, 0xb8, 0xf0, 0xf8, 0xbf, 0xff, 0xbb,
0xc0, 0xb3, 0x2a, 0x2f, 0x0f, 0x2e, 0x01, 0xf0, 0xfe, 0xbf, 0xe6, 0x7f,
0x7e, 0xbb, 0xd5, 0x7f, 0x37, 0x30, 0x5f, 0x5a, 0xbe, 0x05, 0x67, 0x41,
0xc4, 0x7f, 0x78, 0xbe, 0x47, 0x41, 0x27, 0x0b, 0xb3, 0x7f, 0xe6, 0x11,
0x41, 0x56, 0x43, 0x89, 0xd7, 0x42, 0x00, 0x2e, 0x27, 0x41, 0x05, 0x41,
0xf8, 0xbf, 0x7d, 0x0b, 0x6e, 0x11, 0x03, 0x8f, 0xd5, 0x42, 0x14, 0x30,
0xe5, 0x41, 0xc7, 0x41, 0xd8, 0xbe, 0x6f, 0x0b, 0x6e, 0x11, 0xc5, 0x42,
0x29, 0x2e, 0x56, 0x00, 0x45, 0x56, 0x27, 0x2e, 0xb8, 0xf0, 0xe6, 0x6f,
0xd5, 0x6f, 0xc4, 0x6f, 0xb3, 0x6f, 0xf7, 0x6f, 0xb0, 0x5f, 0xc8, 0x2e,
0x50, 0x50, 0xe5, 0x7f, 0xd7, 0x7f, 0xf6, 0x7f, 0x36, 0x30, 0x0b, 0x2e,
0x01, 0xf0, 0xde, 0xbe, 0xde, 0xbb, 0x61, 0x5a, 0xb7, 0x05, 0x67, 0x41,
0xc4, 0x7f, 0x78, 0xbe, 0x47, 0x41, 0x27, 0x0b, 0xb3, 0x7f, 0xe6, 0x11,
0x43, 0x56, 0x43, 0x89, 0xd7, 0x42, 0x00, 0x2e, 0x27, 0x41, 0x05, 0x41,
0xf8, 0xbf, 0x7d, 0x0b, 0x6e, 0x11, 0x03, 0x8f, 0xd5, 0x42, 0x14, 0x30,
0xe5, 0x41, 0xc7, 0x41, 0xd8, 0xbe, 0x6f, 0x0b, 0x6e, 0x11, 0xc5, 0x42,
0x29, 0x2e, 0x55, 0x00, 0x03, 0x31, 0x27, 0x2e, 0xb8, 0xf0, 0xf6, 0x6f,
0xe5, 0x6f, 0xd7, 0x6f, 0xc4, 0x6f, 0xb3, 0x6f, 0xb0, 0x5f, 0xc8, 0x2e,
0x40, 0x50, 0xf6, 0x7f, 0x1a, 0x18, 0x63, 0x56, 0x33, 0x00, 0x06, 0x30,
0xfe, 0x03, 0x0e, 0xb8, 0xf2, 0xbf, 0x07, 0x0a, 0x2a, 0x18, 0x63, 0x5a,
0xb5, 0x01, 0x03, 0x30, 0xfb, 0x03, 0x6e, 0xbb, 0xf2, 0xbf, 0xe1, 0x7f,
0xf7, 0x0b, 0x56, 0x40, 0x36, 0x25, 0x46, 0x40, 0x06, 0x28, 0xc7, 0x7f,
0x22, 0x18, 0xd1, 0x7f, 0xb5, 0x00, 0x01, 0x30, 0x39, 0x03, 0x2e, 0xb9,
0x42, 0xbe, 0x14, 0x0b, 0xf2, 0x6f, 0x10, 0x18, 0xb5, 0x00, 0xb9, 0x03,
0x2e, 0xb9, 0x62, 0xbf, 0x96, 0x0a, 0xb6, 0x6f, 0x30, 0x18, 0x75, 0x01,
0xb9, 0x03, 0x5c, 0x28, 0xe2, 0xbf, 0xde, 0xb9, 0xd6, 0x6f, 0xdf, 0x0a,
0x8a, 0x28, 0xc4, 0x6f, 0x82, 0x43, 0x23, 0x29, 0xe5, 0x6f, 0xc0, 0x2e,
0x44, 0x43, 0xc0, 0x5f, 0x40, 0x50, 0xd0, 0x7f, 0x4a, 0x17, 0x00, 0x40,
0x01, 0x18, 0x46, 0x25, 0x07, 0x25, 0x65, 0x56, 0xd9, 0x04, 0x53, 0x18,
0xeb, 0x18, 0x05, 0x30, 0x49, 0x16, 0x69, 0x06, 0xca, 0x18, 0xa6, 0x00,
0xc7, 0x02, 0x65, 0x58, 0xcb, 0x7f, 0x98, 0x2e, 0x7f, 0xb6, 0xcb, 0x6f,
0xd2, 0x6f, 0xc0, 0x2e, 0x80, 0x42, 0xc0, 0x5f, 0x09, 0x2e, 0x1b, 0x01,
0x05, 0x2e, 0x1b, 0x01, 0xa3, 0xbc, 0x44, 0xbe, 0x90, 0x50, 0x4f, 0xb9,
0x07, 0x2e, 0x1b, 0x01, 0x4a, 0x25, 0x9f, 0xb8, 0x39, 0x8f, 0xb2, 0xbd,
0xf2, 0x7f, 0xbf, 0xb9, 0xeb, 0x7f, 0x8a, 0x0a, 0x37, 0x89, 0x0b, 0x30,
0x93, 0x0a, 0x8b, 0x7f, 0xcb, 0x43, 0x0b, 0x43, 0x80, 0xb2, 0xd3, 0x7f,
0xc1, 0x7f, 0x90, 0x2e, 0x87, 0xb2, 0x20, 0x25, 0x01, 0x2e, 0x64, 0x00,
0x01, 0x90, 0x0e, 0x2f, 0x67, 0x52, 0x01, 0x2e, 0x61, 0x00, 0xb4, 0x7f,
0xa2, 0x7f, 0x98, 0x2e, 0x8d, 0xb2, 0x00, 0x30, 0x21, 0x2e, 0x64, 0x00,
0xc1, 0x6f, 0xd3, 0x6f, 0xa2, 0x6f, 0xb4, 0x6f, 0x0b, 0x30, 0x01, 0x2e,
0x1b, 0x01, 0x06, 0xbc, 0x06, 0xbb, 0x57, 0x25, 0x01, 0x2e, 0x1b, 0x01,
0x94, 0xb1, 0x05, 0xbc, 0xb6, 0x7f, 0x0f, 0xbb, 0x6b, 0x50, 0x80, 0xb3,
0x0f, 0x2f, 0x0d, 0x2e, 0x1b, 0x01, 0x6f, 0x5e, 0xb7, 0x09, 0x2d, 0x2e,
0x1b, 0x01, 0x71, 0x5c, 0x69, 0x5e, 0x9b, 0x43, 0x9b, 0x43, 0xdb, 0x43,
0x9b, 0x43, 0x1b, 0x42, 0xcb, 0x43, 0x0b, 0x42, 0x8b, 0x43, 0x40, 0xb2,
0x05, 0x2f, 0x69, 0x50, 0x00, 0x2e, 0x16, 0x40, 0x0b, 0x40, 0x76, 0x7f,
0x8b, 0x7f, 0xcb, 0x0a, 0x01, 0x2e, 0x61, 0x00, 0x67, 0x52, 0x6d, 0x5c,
0x98, 0x2e, 0xd3, 0xb2, 0x90, 0x6f, 0x00, 0xb2, 0x0b, 0x2f, 0xf0, 0x6f,
0x00, 0xb2, 0x08, 0x2f, 0x69, 0x58, 0x6b, 0x50, 0x12, 0x41, 0x12, 0x42,
0x21, 0x30, 0x04, 0x41, 0x04, 0x42, 0x23, 0x2e, 0x5e, 0xf0, 0xc0, 0x6f,
0x00, 0xb2, 0x26, 0x2f, 0x74, 0x6f, 0x80, 0x6f, 0x71, 0x54, 0x88, 0xbd,
0xc8, 0xb8, 0x4b, 0x0a, 0x94, 0x42, 0x91, 0x42, 0x90, 0x42, 0x88, 0xba,
0x69, 0x52, 0xf3, 0x6f, 0x54, 0x42, 0x85, 0x42, 0xc0, 0x90, 0x40, 0x42,
0x15, 0x2f, 0x6b, 0x52, 0x00, 0x2e, 0x52, 0x40, 0x41, 0x40, 0xa2, 0x04,
0x41, 0x06, 0x40, 0xaa, 0x04, 0x2f, 0x40, 0x90, 0x0b, 0x2f, 0xb1, 0x6f,
0x4a, 0x0f, 0x08, 0x2f, 0xb2, 0x6f, 0x80, 0xb2, 0x05, 0x2f, 0x6b, 0x54,
0x21, 0x30, 0x94, 0x42, 0x80, 0x42, 0x23, 0x2e, 0x5e, 0xf0, 0xd0, 0x6f,
0x00, 0xb2, 0x13, 0x2f, 0x01, 0x2e, 0x60, 0x00, 0x09, 0x2e, 0x7c, 0x00,
0x04, 0x1a, 0x0d, 0x2f, 0x73, 0x50, 0x29, 0x2e, 0x60, 0x00, 0x24, 0x42,
0x44, 0x30, 0x02, 0x40, 0x02, 0x42, 0x09, 0x80, 0x00, 0x2e, 0x04, 0x42,
0x03, 0x2d, 0x10, 0x30, 0x21, 0x2e, 0x64, 0x00, 0xeb, 0x6f, 0x70, 0x5f,
0xb8, 0x2e, 0x09, 0x86, 0x49, 0x54, 0xe4, 0x40, 0xc3, 0x80, 0x94, 0x04,
0xc3, 0x40, 0x13, 0x05, 0x05, 0x40, 0x25, 0x05, 0x8a, 0x17, 0x73, 0x30,
0x73, 0x09, 0x8c, 0x17, 0xf3, 0x08, 0xe3, 0x00, 0x4c, 0x82, 0x95, 0x00,
0xb3, 0xb5, 0x23, 0xb5, 0x53, 0x42, 0x52, 0x42, 0x53, 0x42, 0x42, 0x42,
0x71, 0x82, 0x75, 0x54, 0x52, 0x42, 0x10, 0x50, 0x77, 0x54, 0x52, 0x42,
0xfb, 0x7f, 0x22, 0x30, 0x79, 0x56, 0x43, 0x42, 0x44, 0x82, 0x0b, 0x30,
0x52, 0x42, 0x5b, 0x42, 0x7c, 0x84, 0x4b, 0x42, 0x35, 0x82, 0x8c, 0x80,
0x8b, 0x42, 0x0b, 0x42, 0x39, 0x80, 0x04, 0x30, 0x0b, 0x42, 0x37, 0x80,
0x15, 0x30, 0x60, 0x25, 0x98, 0x2e, 0xc6, 0xb2, 0x8b, 0x83, 0xfb, 0x6f,
0x65, 0x42, 0xc0, 0x2e, 0x44, 0x42, 0xf0, 0x5f, 0x05, 0x80, 0x02, 0x30,
0x51, 0x82, 0x02, 0x42, 0x13, 0x30, 0x41, 0x40, 0x4b, 0x08, 0x7b, 0x54,
0x3e, 0x80, 0x51, 0x14, 0xc0, 0x2e, 0x01, 0x42, 0x00, 0x2e, 0x40, 0x51,
0xd1, 0x7f, 0x12, 0x25, 0x02, 0x30, 0x42, 0x43, 0x32, 0x30, 0x82, 0x43,
0xc6, 0x7f, 0xe5, 0x7f, 0xb4, 0x7f, 0xa3, 0x7f, 0x90, 0x7f, 0x8b, 0x7f,
0x98, 0x2e, 0x54, 0x01, 0xc0, 0x7e, 0x00, 0xac, 0x01, 0x2f, 0x65, 0x50,
0xc0, 0x7e, 0x00, 0x2e, 0x90, 0x6f, 0x09, 0x8a, 0xd1, 0x6f, 0x75, 0x7f,
0x4c, 0x82, 0x63, 0x41, 0x65, 0x7f, 0x11, 0x7f, 0x00, 0x2e, 0x64, 0x41,
0x44, 0x85, 0x52, 0x7f, 0x45, 0x7f, 0x00, 0x2e, 0xa6, 0x40, 0x80, 0x40,
0x32, 0x7f, 0x82, 0x8e, 0xc2, 0x6e, 0x45, 0x41, 0xf0, 0x7f, 0x27, 0x7f,
0x02, 0x7f, 0x98, 0x2e, 0x8a, 0xb1, 0x23, 0x6f, 0xd1, 0x6f, 0xc2, 0x40,
0xf9, 0x86, 0x23, 0x7f, 0x80, 0xb2, 0xe0, 0x7e, 0x0f, 0x2f, 0x32, 0x6f,
0x64, 0x6f, 0x82, 0x40, 0xf2, 0x7f, 0x4e, 0x82, 0x42, 0x6f, 0x50, 0x6f,
0x73, 0x6f, 0x85, 0x40, 0xc3, 0x40, 0x04, 0x41, 0x06, 0x40, 0xe2, 0x6e,
0x98, 0x2e, 0x8a, 0xb1, 0xe0, 0x7e, 0xf3, 0x31, 0x10, 0x6f, 0x36, 0x80,
0xe1, 0x6e, 0x02, 0x40, 0x71, 0x7f, 0x51, 0x04, 0x02, 0x30, 0x40, 0xa8,
0x91, 0x04, 0x4a, 0x22, 0x89, 0x16, 0x93, 0x08, 0x4a, 0x00, 0x95, 0xb4,
0x09, 0x18, 0x8e, 0x16, 0x13, 0x30, 0x93, 0x08, 0x21, 0x6f, 0x60, 0x7f,
0x4d, 0x86, 0x02, 0x80, 0xb2, 0x00, 0x41, 0x40, 0x21, 0xb5, 0x50, 0x7f,
0x43, 0x7f, 0x98, 0x2e, 0xc2, 0xb1, 0x40, 0x6f, 0x62, 0x6f, 0x55, 0x6f,
0x13, 0x40, 0x84, 0x40, 0x01, 0x40, 0x45, 0x41, 0x42, 0xbe, 0x1d, 0x18,
0x4c, 0x04, 0x31, 0x0f, 0x04, 0x8a, 0xc0, 0x6f, 0x11, 0x30, 0x02, 0x2f,
0x00, 0x2e, 0x03, 0x2c, 0x01, 0x42, 0x23, 0x30, 0x03, 0x42, 0x00, 0x2e,
0xd6, 0x6f, 0x44, 0x41, 0x8a, 0x87, 0x76, 0x8b, 0x00, 0xb3, 0x53, 0x7f,
0x15, 0x2f, 0x04, 0x6f, 0x7d, 0x5e, 0x8b, 0x8d, 0xe7, 0x01, 0xc0, 0xa5,
0x84, 0x41, 0x01, 0x2f, 0x00, 0xa1, 0x03, 0x2f, 0xc0, 0xad, 0x08, 0x2f,
0x00, 0xa5, 0x06, 0x2f, 0xc6, 0x40, 0x81, 0x8d, 0x07, 0x30, 0x3c, 0x05,
0xd6, 0x42, 0x04, 0x2c, 0xc4, 0x42, 0x02, 0x2c, 0x07, 0x30, 0x07, 0x30,
0x86, 0x86, 0x94, 0x6f, 0xd7, 0x7e, 0x0e, 0x8d, 0x00, 0x40, 0x74, 0x89,
0xc7, 0x40, 0x02, 0xb2, 0xf9, 0x29, 0x45, 0x41, 0x86, 0x41, 0xbe, 0x80,
0x21, 0x41, 0x75, 0x23, 0x82, 0x40, 0xc7, 0x42, 0x45, 0x7f, 0x34, 0x7f,
0x20, 0x7f, 0x98, 0x2e, 0xc2, 0xb1, 0x31, 0x6f, 0x60, 0x6f, 0x24, 0x6f,
0x22, 0x40, 0x05, 0x41, 0x43, 0x40, 0x13, 0x01, 0x43, 0x86, 0xac, 0x0f,
0xd1, 0x6f, 0x30, 0x7f, 0x00, 0x2f, 0x44, 0x42, 0x48, 0x8a, 0x41, 0x88,
0xe1, 0x40, 0x13, 0x7f, 0x04, 0x7f, 0xf5, 0x7e, 0x98, 0x2e, 0xc2, 0xb1,
0x11, 0x6f, 0x60, 0x6f, 0x34, 0x6f, 0x42, 0x40, 0x03, 0x40, 0x9a, 0x04,
0x04, 0x41, 0x43, 0x82, 0xa2, 0x0e, 0x03, 0x6f, 0x00, 0x2f, 0xc2, 0x42,
0x00, 0x2e, 0x41, 0x40, 0x72, 0x6f, 0x98, 0x2e, 0xc2, 0xb1, 0x25, 0x6f,
0x72, 0x6f, 0x53, 0x41, 0x93, 0x0e, 0xd1, 0x6f, 0x46, 0x80, 0x1b, 0x30,
0x03, 0x30, 0x0c, 0x2f, 0x04, 0x40, 0x00, 0x91, 0x42, 0x42, 0x08, 0x2f,
0xf6, 0x6e, 0x44, 0x6f, 0x86, 0x41, 0xb4, 0x0e, 0x03, 0x2f, 0x02, 0x88,
0xdb, 0x7e, 0x03, 0x43, 0x0b, 0x42, 0x46, 0x8d, 0x44, 0x41, 0x47, 0x80,
0x05, 0x6f, 0x94, 0x0f, 0x76, 0x7f, 0x60, 0x7f, 0x02, 0x2f, 0x45, 0x89,
0x42, 0x43, 0x03, 0x43, 0x49, 0x88, 0xa5, 0x6f, 0x40, 0x91, 0xa4, 0x7f,
0x15, 0x30, 0xe2, 0x6f, 0xd3, 0x6e, 0x03, 0x2f, 0x04, 0x30, 0x83, 0x42,
0x80, 0x2e, 0x77, 0xb4, 0x04, 0x40, 0x25, 0x29, 0x04, 0x42, 0x83, 0x42,
0x45, 0x82, 0x94, 0x6f, 0x04, 0x85, 0xc0, 0xb2, 0x90, 0x2e, 0x63, 0xb4,
0x15, 0x87, 0x3c, 0x8c, 0xc4, 0x40, 0x46, 0x7f, 0xc2, 0x86, 0x07, 0x40,
0x86, 0x41, 0xf4, 0xbf, 0x00, 0xb3, 0x0c, 0x2f, 0x90, 0x6f, 0x16, 0x80,
0x46, 0x25, 0x00, 0x40, 0x57, 0x25, 0x04, 0x18, 0xae, 0x0e, 0x10, 0x30,
0x06, 0x30, 0x75, 0x25, 0x46, 0x23, 0x60, 0x6f, 0x64, 0x25, 0xc4, 0x40,
0xfa, 0x86, 0x00, 0xb3, 0x33, 0x7f, 0x09, 0x2f, 0x93, 0x6f, 0xd8, 0x88,
0x53, 0x6f, 0x04, 0x41, 0xc3, 0x40, 0xdc, 0x0e, 0x13, 0x30, 0x04, 0x30,
0xdc, 0x22, 0xb3, 0x25, 0x40, 0xb3, 0x02, 0x2f, 0x3b, 0x25, 0xc0, 0x90,
0x05, 0x2f, 0x91, 0x6f, 0xd0, 0x6f, 0x98, 0x2e, 0xc6, 0xb2, 0x4d, 0x2c,
0x04, 0x30, 0x8d, 0x88, 0x43, 0x40, 0x82, 0x40, 0x54, 0x7f, 0xda, 0x0f,
0x04, 0x30, 0x08, 0x2f, 0xc1, 0x80, 0x40, 0x42, 0xc2, 0x0f, 0x02, 0x2f,
0x00, 0x30, 0xc0, 0x7e, 0x1b, 0x2d, 0xc0, 0x7e, 0x19, 0x2d, 0xe1, 0xbc,
0x92, 0x6f, 0x4f, 0x04, 0x90, 0x84, 0x40, 0xa8, 0x21, 0x05, 0x83, 0x40,
0x4c, 0x22, 0x4b, 0x0e, 0xb6, 0x84, 0x21, 0x30, 0x02, 0x2f, 0x11, 0x30,
0x04, 0x2c, 0xc1, 0x7e, 0xe3, 0x6f, 0xc1, 0x7e, 0xc1, 0x42, 0x00, 0x2e,
0x00, 0x40, 0x81, 0x40, 0x04, 0xbd, 0x40, 0x6f, 0x98, 0x2e, 0xc2, 0xb1,
0x50, 0x6f, 0x11, 0x30, 0x02, 0x40, 0x51, 0x08, 0xc3, 0x6e, 0x03, 0x80,
0x99, 0x15, 0x0b, 0x40, 0xb1, 0x6f, 0xd0, 0x6f, 0xb6, 0x7f, 0x5b, 0x7f,
0x04, 0x30, 0x4d, 0x54, 0x03, 0x30, 0x11, 0x2c, 0x10, 0x80, 0x55, 0x6f,
0x06, 0x40, 0x75, 0x01, 0x58, 0xbb, 0x6a, 0x09, 0x05, 0x42, 0xc1, 0x86,
0x47, 0x40, 0x51, 0x25, 0xbe, 0x01, 0x56, 0x43, 0x00, 0x2e, 0x46, 0x41,
0xf4, 0x03, 0xb6, 0x6f, 0x47, 0x43, 0x5e, 0x0e, 0xed, 0x2f, 0x31, 0x6f,
0x60, 0x6f, 0x42, 0x40, 0x15, 0x30, 0x02, 0x82, 0x95, 0x08, 0x04, 0x42,
0x52, 0x42, 0x02, 0x2c, 0x44, 0x42, 0x04, 0x30, 0x3e, 0x8e, 0x91, 0x6f,
0x4f, 0x8c, 0x02, 0x40, 0x83, 0x41, 0xb5, 0x8d, 0x93, 0x0e, 0xd0, 0x6f,
0x01, 0x2f, 0x98, 0x2e, 0xc6, 0xb2, 0x00, 0x2e, 0xc0, 0x41, 0x81, 0x41,
0xc1, 0x0f, 0xc0, 0x6f, 0x01, 0x2f, 0x04, 0x42, 0x00, 0x2e, 0x70, 0x6f,
0x3c, 0x82, 0x00, 0x40, 0x41, 0x40, 0x89, 0x16, 0x95, 0x08, 0x4a, 0x00,
0x04, 0xbc, 0x91, 0xb4, 0x01, 0x0e, 0xe0, 0x6f, 0x07, 0x2f, 0xa1, 0x6f,
0x00, 0x2e, 0x41, 0x40, 0x40, 0xb2, 0x02, 0x2f, 0xa1, 0x6f, 0x05, 0x42,
0x44, 0x42, 0x00, 0x2e, 0x8b, 0x6f, 0xc0, 0x5e, 0xb8, 0x2e, 0x03, 0x2e,
0x1c, 0x01, 0x9c, 0xbc, 0x1d, 0xb9, 0x02, 0x82, 0x25, 0x2e, 0x8e, 0x00,
0x83, 0x56, 0x13, 0x18, 0x01, 0x2e, 0x66, 0x00, 0x43, 0x40, 0xd8, 0x04,
0x05, 0x2e, 0x65, 0x00, 0x40, 0x50, 0x27, 0x2e, 0x65, 0x00, 0xfb, 0x7f,
0xda, 0x05, 0x8b, 0x50, 0x4b, 0x40, 0x02, 0x40, 0x81, 0x82, 0x01, 0x42,
0x03, 0x80, 0x81, 0x52, 0xb1, 0x00, 0x03, 0x40, 0x3b, 0x82, 0x85, 0x58,
0x14, 0x01, 0xc0, 0xb2, 0x37, 0x2e, 0x66, 0x00, 0xd1, 0x7f, 0xe2, 0x7f,
0x04, 0x2f, 0x05, 0x2e, 0x6b, 0x00, 0x81, 0x84, 0x25, 0x2e, 0x6b, 0x00,
0x62, 0x40, 0x3a, 0x0f, 0x45, 0x40, 0xc1, 0x7f, 0x21, 0x30, 0x12, 0x30,
0x42, 0x2f, 0x0d, 0x2e, 0x69, 0x00, 0x3e, 0x0e, 0x33, 0x2f, 0x05, 0x2e,
0x6a, 0x00, 0x01, 0x35, 0x91, 0x0e, 0x01, 0x30, 0x03, 0x2f, 0x09, 0x2e,
0x6e, 0x00, 0x00, 0xb3, 0x24, 0x2f, 0xc0, 0x35, 0x90, 0x0e, 0x39, 0x2f,
0x8f, 0x50, 0x02, 0x30, 0x01, 0x40, 0x7f, 0x82, 0x43, 0xa2, 0x02, 0x2f,
0x00, 0x2e, 0x0c, 0x2c, 0x01, 0x30, 0xc0, 0xb2, 0x11, 0x30, 0x02, 0x2f,
0x25, 0x2e, 0x6d, 0x00, 0x03, 0x2d, 0x23, 0x2e, 0x6d, 0x00, 0x21, 0x30,
0x25, 0x2e, 0x6b, 0x00, 0x42, 0xb2, 0x04, 0x2f, 0x41, 0xb2, 0x02, 0x2f,
0x25, 0x2e, 0x6d, 0x00, 0x31, 0x30, 0x3e, 0x80, 0x04, 0x86, 0x25, 0x2e,
0x6c, 0x00, 0x02, 0x42, 0xc2, 0x42, 0x18, 0x2d, 0x02, 0x35, 0x01, 0x42,
0x25, 0x2e, 0x6a, 0x00, 0x13, 0x2d, 0x2c, 0x04, 0x38, 0x1e, 0x21, 0x2e,
0x69, 0x00, 0x7f, 0x50, 0x11, 0x30, 0x22, 0x30, 0x98, 0x2e, 0x66, 0xb5,
0x09, 0x2c, 0x01, 0x30, 0x2c, 0x00, 0x38, 0x1c, 0x21, 0x2e, 0x68, 0x00,
0x7f, 0x50, 0x98, 0x2e, 0x66, 0xb5, 0x01, 0x30, 0xc0, 0x6f, 0xd4, 0xb1,
0xf5, 0xbd, 0x6b, 0xba, 0x91, 0x5a, 0x02, 0x40, 0x15, 0x18, 0xf5, 0xbe,
0xeb, 0xbb, 0xe3, 0x0a, 0x3d, 0x0b, 0xd2, 0x6f, 0xe3, 0x00, 0x84, 0x40,
0x63, 0x05, 0x93, 0x58, 0x2c, 0x18, 0xf5, 0xbe, 0x03, 0x42, 0xeb, 0xbb,
0xfd, 0x0b, 0xe0, 0x6f, 0x58, 0x01, 0xdf, 0x01, 0x7d, 0x1f, 0x95, 0x42,
0x18, 0x04, 0x85, 0x40, 0x5d, 0x05, 0x2c, 0x18, 0x75, 0xbe, 0xeb, 0xba,
0x2c, 0x0b, 0xdc, 0x04, 0x18, 0x1c, 0x80, 0x42, 0x84, 0x80, 0x02, 0x30,
0x00, 0x40, 0x00, 0xb2, 0x0c, 0x2f, 0x01, 0x2e, 0x6b, 0x00, 0x03, 0x35,
0x83, 0x0e, 0x07, 0x2f, 0x8d, 0x50, 0x3e, 0x80, 0x25, 0x2e, 0x6d, 0x00,
0x02, 0x42, 0x03, 0x80, 0x00, 0x2e, 0x02, 0x42, 0x40, 0xb2, 0x04, 0x2f,
0x8b, 0x50, 0x04, 0x80, 0x25, 0x2e, 0x6a, 0x00, 0x02, 0x42, 0x42, 0xb2,
0x89, 0x56, 0x9a, 0x22, 0x41, 0xb2, 0x01, 0x2e, 0x1c, 0x01, 0x87, 0x52,
0x0b, 0xbc, 0x8a, 0x22, 0x0f, 0xb8, 0x00, 0x90, 0x01, 0x32, 0x06, 0x2f,
0x10, 0x30, 0x90, 0x08, 0x80, 0xb2, 0x08, 0x2f, 0x23, 0x2e, 0x5e, 0xf0,
0x06, 0x2d, 0x20, 0x30, 0x90, 0x08, 0x80, 0xb2, 0x01, 0x2f, 0x23, 0x2e,
0x5e, 0xf0, 0xfb, 0x6f, 0xc0, 0x5f, 0xb8, 0x2e, 0x07, 0x86, 0xfc, 0x88,
0xc6, 0x40, 0x05, 0x41, 0x31, 0x1a, 0x12, 0x2f, 0x80, 0x91, 0x22, 0x2f,
0x01, 0x35, 0x29, 0x0f, 0x0a, 0x2f, 0x06, 0x80, 0x00, 0x2e, 0x00, 0x40,
0x00, 0xb2, 0x01, 0x2f, 0x44, 0xa9, 0x03, 0x2f, 0x00, 0x30, 0xc0, 0x42,
0x00, 0x43, 0xb8, 0x2e, 0xc2, 0x42, 0x01, 0x43, 0xb8, 0x2e, 0x01, 0x35,
0xa9, 0x0e, 0x0e, 0x2f, 0x03, 0x3b, 0xeb, 0x00, 0xcc, 0xa8, 0x0a, 0x2f,
0x05, 0x86, 0xc2, 0x80, 0xc3, 0x40, 0x02, 0x42, 0x3c, 0x84, 0xc1, 0x80,
0x81, 0x42, 0x82, 0x84, 0xc0, 0x2e, 0x80, 0x42, 0x00, 0x2e, 0xb8, 0x2e,
0x03, 0x2e, 0x1d, 0x01, 0x9f, 0xbc, 0x9f, 0xb8, 0x90, 0x50, 0x40, 0xb2,
0x90, 0x2e, 0x71, 0xb6, 0x12, 0x40, 0x03, 0x30, 0x11, 0x40, 0x80, 0xa8,
0x5a, 0x05, 0x9f, 0x58, 0x55, 0x23, 0x00, 0x40, 0x75, 0x7f, 0x40, 0xa8,
0x16, 0x41, 0xd9, 0x05, 0xcf, 0x23, 0x56, 0x05, 0x40, 0xa9, 0x9d, 0x05,
0x87, 0x7f, 0x6e, 0x23, 0x17, 0x41, 0xa5, 0x7f, 0x3e, 0x8b, 0x04, 0x41,
0x52, 0x43, 0x00, 0xa8, 0x98, 0x05, 0xf2, 0x7f, 0x86, 0x22, 0xcf, 0x05,
0xc0, 0xa9, 0x9f, 0x05, 0xbe, 0x23, 0x04, 0x05, 0x92, 0x7f, 0x00, 0xa9,
0xdc, 0x05, 0x51, 0x43, 0xb6, 0x7f, 0x27, 0x23, 0xa7, 0x54, 0xe1, 0x7f,
0x02, 0x18, 0x7d, 0x83, 0x40, 0x43, 0xeb, 0xba, 0x75, 0xbd, 0xaa, 0x0a,
0x0b, 0x2e, 0x71, 0x00, 0x77, 0x5c, 0x2e, 0x18, 0xf5, 0xbe, 0x6b, 0xbb,
0x75, 0x0b, 0xaa, 0x00, 0xc4, 0x7f, 0x25, 0x2e, 0x71, 0x00, 0xb2, 0x6f,
0xa5, 0x6f, 0xaa, 0x00, 0x54, 0x01, 0x84, 0x6f, 0x72, 0x6f, 0x94, 0x05,
0x80, 0xa9, 0xde, 0x05, 0xb7, 0x23, 0x99, 0x5e, 0x77, 0x0e, 0x41, 0x40,
0x97, 0x5c, 0xb1, 0x01, 0xd5, 0x7f, 0x00, 0x2e, 0x85, 0x41, 0x0e, 0x2f,
0x00, 0xa0, 0x0c, 0x2f, 0x14, 0x0f, 0x04, 0x2f, 0xe0, 0x6f, 0x00, 0xac,
0x10, 0x30, 0x08, 0x2c, 0x18, 0x22, 0xf0, 0x6f, 0x00, 0xac, 0x30, 0x30,
0x24, 0x30, 0x02, 0x2c, 0x20, 0x22, 0x40, 0x30, 0x0d, 0x2e, 0x71, 0x00,
0x80, 0xa1, 0x1e, 0x23, 0x79, 0x5e, 0x37, 0x0f, 0xbc, 0x23, 0x00, 0x90,
0x14, 0x30, 0x10, 0x30, 0x18, 0x2f, 0x9d, 0x50, 0x30, 0x00, 0x9b, 0x56,
0x43, 0x0e, 0x02, 0x2f, 0x10, 0x30, 0x0a, 0x2c, 0x03, 0x30, 0x99, 0x50,
0x10, 0x0e, 0x13, 0x30, 0x00, 0x2f, 0x03, 0x30, 0x90, 0x0f, 0x10, 0x30,
0x00, 0x2f, 0x00, 0x30, 0x00, 0x90, 0x10, 0x30, 0x00, 0x2f, 0x00, 0x30,
0xc0, 0x90, 0x13, 0x30, 0x00, 0x2f, 0x03, 0x30, 0x40, 0xb2, 0x87, 0x5c,
0x22, 0x2f, 0x41, 0x90, 0x4a, 0x2f, 0xa5, 0x50, 0x00, 0x2e, 0x01, 0x40,
0x41, 0x82, 0x01, 0x42, 0x02, 0x80, 0x4a, 0xa8, 0x01, 0x40, 0x06, 0x2f,
0xd0, 0x6f, 0x85, 0x0e, 0x3e, 0x2f, 0x41, 0x80, 0x21, 0x2e, 0x78, 0x00,
0x3b, 0x2d, 0x95, 0x50, 0xfb, 0x7f, 0x4a, 0xa8, 0x06, 0x2f, 0x98, 0x2e,
0x73, 0xb6, 0xc0, 0x90, 0xfb, 0x6f, 0x32, 0x2f, 0x00, 0x2e, 0x30, 0x2d,
0x98, 0x2e, 0x73, 0xb6, 0x29, 0x2e, 0x7a, 0x00, 0x2b, 0x2c, 0xfb, 0x6f,
0xa1, 0x52, 0xd2, 0x6f, 0x95, 0x0e, 0x41, 0x40, 0x05, 0x2f, 0x00, 0x90,
0x17, 0x2f, 0x05, 0x2e, 0x7a, 0x00, 0x80, 0x90, 0x13, 0x2f, 0x7f, 0x82,
0x40, 0xac, 0x23, 0x2e, 0x77, 0x00, 0x01, 0x30, 0x18, 0x2f, 0xa1, 0x54,
0x82, 0x84, 0x23, 0x2e, 0x77, 0x00, 0x82, 0x40, 0x80, 0xb2, 0x11, 0x2f,
0x00, 0x90, 0x23, 0x2e, 0x79, 0x00, 0x0d, 0x2f, 0x29, 0x2e, 0x72, 0x00,
0x0b, 0x2d, 0x41, 0x80, 0x21, 0x2e, 0x77, 0x00, 0x0f, 0xa4, 0x05, 0x2f,
0xa3, 0x50, 0x3e, 0x80, 0xf1, 0x30, 0x29, 0x2e, 0x79, 0x00, 0x01, 0x42,
0x06, 0x30, 0x34, 0x08, 0x00, 0xb2, 0x02, 0x2f, 0x80, 0x30, 0x21, 0x2e,
0x5e, 0xf0, 0x70, 0x5f, 0xb8, 0x2e, 0x04, 0x84, 0x01, 0x30, 0x81, 0x42,
0x82, 0x84, 0x01, 0x42, 0xa1, 0x42, 0x81, 0x42, 0x82, 0x84, 0x00, 0x2e,
0x91, 0x42, 0x81, 0x42, 0xb8, 0x2e, 0x30, 0x50, 0xf3, 0x7f, 0xc0, 0xac,
0xe4, 0x7f, 0xd5, 0x7f, 0x03, 0x2f, 0x00, 0x30, 0x82, 0x04, 0xf3, 0x6f,
0xc3, 0x06, 0x40, 0xad, 0x05, 0x2f, 0xe0, 0x6f, 0x05, 0x30, 0x28, 0x04,
0xd1, 0x6f, 0x69, 0x07, 0xe0, 0x7f, 0x40, 0xa1, 0x01, 0x30, 0x20, 0x2f,
0x13, 0x25, 0x02, 0x25, 0x04, 0x32, 0x06, 0x30, 0x02, 0x30, 0x03, 0x30,
0xaf, 0xbb, 0xb1, 0xbd, 0xdf, 0x0a, 0x9f, 0xbb, 0x21, 0xbd, 0x97, 0x0a,
0x8f, 0xbb, 0x91, 0xbc, 0x01, 0xbc, 0x4f, 0x0a, 0x6b, 0x0e, 0x04, 0x2f,
0x6b, 0x1a, 0x07, 0x2f, 0xe7, 0x6f, 0x7a, 0x0f, 0x04, 0x2f, 0xe7, 0x6f,
0x97, 0x04, 0x17, 0x30, 0x07, 0x0a, 0xdd, 0x06, 0x81, 0x8d, 0x34, 0x0e,
0xe6, 0x2f, 0x00, 0x2e, 0x0d, 0x2d, 0x6b, 0x0e, 0x00, 0x30, 0x05, 0x2f,
0x6b, 0x1a, 0x07, 0x2f, 0xe0, 0x6f, 0x42, 0x0f, 0x00, 0x30, 0x03, 0x2f,
0xe0, 0x6f, 0x90, 0x04, 0xdd, 0x06, 0x10, 0x30, 0xf5, 0x6f, 0xc3, 0x7f,
0xb2, 0x7f, 0x40, 0xad, 0x06, 0x2f, 0x03, 0x30, 0xb2, 0x6f, 0x9a, 0x04,
0xc4, 0x6f, 0xdc, 0x06, 0xb2, 0x7f, 0xc3, 0x7f, 0x00, 0x2e, 0xd2, 0x6f,
0xaa, 0x0c, 0x80, 0xac, 0x02, 0x30, 0x01, 0x2f, 0x10, 0x04, 0x51, 0x06,
0xd0, 0x5f, 0xb8, 0x2e, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00
};

View File

@@ -0,0 +1,213 @@
/**
*
* @license MIT License
*
* Copyright (c) 2025 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file BMA423Constants.h
* @author Lewis He (lewishe@outlook.com)
* @date 2025-01-17
*
*/
#pragma once
#include <stdint.h>
#define BMA423_I2C_ADDR_PRIMARY (0x18)
#define BMA423_I2C_ADDR_SECONDARY (0x19)
class BMA423Constants
{
protected:
static constexpr uint8_t BAM423_SENSOR_RESOLUTION = (12) ; //*
static constexpr uint8_t RESET_REG = (0x7E); //*
static constexpr uint8_t CHIP_ID_ADDR = (0x00); /**\name CHIP ID ADDRESS*/
static constexpr uint8_t CHIP_ID = (0x13); /**\name Chip ID of BMA423 sensor */
static constexpr uint8_t POWER_CONF_ADDR = (0x7C); /**\name POWER_CTRL REGISTER*/
static constexpr uint8_t POWER_CTRL_ADDR = (0x7D); /**\name POWER_CTRL REGISTER*/
static constexpr uint8_t ADVANCE_POWER_SAVE_MSK = (0x01); /**\name ADVANCE POWER SAVE POSITION AND MASK*/
static constexpr uint8_t INT_MAP_1_ADDR = (0X56); /**\name MAP INTERRUPT 1 and 2 REGISTERS*/
static constexpr uint8_t INT_MAP_2_ADDR = (0X57); /**\name MAP INTERRUPT 1 and 2 REGISTERS*/
static constexpr uint8_t INT_MAP_DATA_ADDR = (0x58); /**\name MAP INTERRUPT 1 and 2 REGISTERS*/
static constexpr uint8_t INIT_CTRL_ADDR = (0x59); /**\name MAP INTERRUPT 1 and 2 REGISTERS*/
static constexpr uint8_t RESERVED_REG_5B_ADDR = (0x5B); /**\name FEATURE CONFIG RELATED */
static constexpr uint8_t RESERVED_REG_5C_ADDR = (0x5C); /**\name FEATURE CONFIG RELATED */
static constexpr uint8_t FEATURE_CONFIG_ADDR = (0x5E); /**\name FEATURE CONFIG RELATED */
static constexpr uint8_t INTERNAL_ERROR = (0x5F); /**\name FEATURE CONFIG RELATED */
static constexpr uint8_t STEP_CNT_OUT_0_ADDR = (0x1E); /**\name GPIO REGISTERS*/
static constexpr uint8_t HIGH_G_OUT_ADDR = (0x1F); /**\name GPIO REGISTERS*/
static constexpr uint8_t ACTIVITY_OUT_ADDR = (0x27); /**\name GPIO REGISTERS*/
static constexpr uint8_t ORIENTATION_OUT_ADDR = (0x28); /**\name GPIO REGISTERS*/
static constexpr uint8_t INTERNAL_STAT = (0x2A); /**\name GPIO REGISTERS*/
static constexpr uint8_t SENSORTIME_0_ADDR = (0X18); /**\name SENSOR TIME REGISTERS*/
static constexpr uint8_t INT_STAT_0_ADDR = (0X1C); /**\name INTERRUPT/FEATURE STATUS REGISTERS*/
static constexpr uint8_t INT_STAT_1_ADDR = (0X1D); /**\name INTERRUPT/FEATURE STATUS REGISTERS*/
static constexpr uint8_t DATA_0_ADDR = (0X0A); /**\name AUX/ACCEL DATA BASE ADDRESS REGISTERS*/
static constexpr uint8_t DATA_8_ADDR = (0X12); /**\name AUX/ACCEL DATA BASE ADDRESS REGISTERS*/
static constexpr uint8_t ACCEL_CONFIG_ADDR = (0X40); /**\name AUX/ACCEL DATA BASE ADDRESS REGISTERS*/
static constexpr uint8_t TEMPERATURE_ADDR = (0X22); /**\name AUX/ACCEL DATA BASE ADDRESS REGISTERS*/
static constexpr uint8_t INT1_IO_CTRL_ADDR = (0X53); /**\name INTERRUPT ENABLE REGISTERS*/
static constexpr uint8_t INT2_IO_CTRL_ADDR = (0X54); /**\name INTERRUPT ENABLE REGISTERS*/
static constexpr uint8_t INTR_LATCH_ADDR = (0X55); /**\name LATCH DURATION REGISTERS*/
/**\name BUS READ AND WRITE LENGTH FOR MAG & ACCEL*/
static constexpr uint8_t MAG_TRIM_DATA_SIZE = (16);
static constexpr uint8_t MAG_XYZ_DATA_LENGTH = (6);
static constexpr uint8_t MAG_XYZR_DATA_LENGTH = (8);
static constexpr uint8_t ACCEL_DATA_LENGTH = (6);
static constexpr uint8_t FIFO_DATA_LENGTH = (2);
static constexpr uint8_t TEMP_DATA_SIZE = (1);
/**\name Feature offset address */
static constexpr uint8_t ANY_NO_MOTION_OFFSET = (0x00);
static constexpr uint8_t STEP_CNTR_OFFSET = (0x36);
static constexpr uint8_t STEP_CNTR_PARAM_OFFSET = (0x04);
static constexpr uint8_t WAKEUP_OFFSET = (0x38);
static constexpr uint8_t TILT_OFFSET = (0x3A);
static constexpr uint8_t CONFIG_ID_OFFSET = (0x3C);
static constexpr uint8_t AXES_REMAP_OFFSET = (0x3E);
/**\name Sensor feature size */
static constexpr uint8_t FEATURE_SIZE = (64);
static constexpr uint8_t ANYMOTION_EN_LEN = (2);
static constexpr uint8_t RD_WR_MIN_LEN = (2);
/**************************************************************/
/**\name Remap Axes */
/**************************************************************/
static constexpr uint8_t X_AXIS_MASK = (0x03);
static constexpr uint8_t X_AXIS_SIGN_MASK = (0x04);
static constexpr uint8_t Y_AXIS_MASK = (0x18);
static constexpr uint8_t Y_AXIS_SIGN_MASK = (0x20);
static constexpr uint8_t Z_AXIS_MASK = (0xC0);
static constexpr uint8_t Z_AXIS_SIGN_MASK = (0x01);
/**\name ACCELEROMETER ENABLE POSITION AND MASK*/
static constexpr uint8_t ACCEL_ENABLE_MSK = (0x04);
static constexpr uint8_t ASIC_INITIALIZED = (0x01);
/**************************************************************/
/**\name Step Counter & Detector */
/**************************************************************/
/**\name Step counter enable macros */
static constexpr uint8_t STEP_CNTR_EN_POS = (4);
static constexpr uint8_t STEP_CNTR_EN_MSK = (0x10);
static constexpr uint8_t ACTIVITY_EN_MSK = (0x20);
/**\name Step counter watermark macros */
static constexpr uint16_t STEP_CNTR_WM_MSK = (0x03FF);
/**\name Step counter reset macros */
static constexpr uint8_t STEP_CNTR_RST_POS = (2);
static constexpr uint8_t STEP_CNTR_RST_MSK = (0x04);
/**\name Step detector enable macros */
static constexpr uint8_t STEP_DETECTOR_EN_POS = (3);
static constexpr uint8_t STEP_DETECTOR_EN_MSK = (0x08);
/**\name Tilt enable macros */
static constexpr uint8_t TILT_EN_MSK = (0x01);
/**\name Step count output length*/
static constexpr uint8_t STEP_CNTR_DATA_SIZE = (4);
/**\name Wakeup enable macros */
static constexpr uint8_t WAKEUP_EN_MSK = (0x01);
/**\name Wake up sensitivity macros */
static constexpr uint8_t WAKEUP_SENS_POS = (1);
static constexpr uint8_t WAKEUP_SENS_MSK = (0x0E);
/**\name Tap selection macro */
static constexpr uint8_t TAP_SEL_POS = (4);
static constexpr uint8_t TAP_SEL_MSK = (0x10);
/**************************************************************/
/**\name Any Motion */
/**************************************************************/
/**\name Any motion threshold macros */
static constexpr uint8_t ANY_NO_MOTION_THRES_POS = (0);
static constexpr uint16_t ANY_NO_MOTION_THRES_MSK = (0x07FF);
/**\name Any motion selection macros */
static constexpr uint8_t ANY_NO_MOTION_SEL_POS = (3);
static constexpr uint8_t ANY_NO_MOTION_SEL_MSK = (0x08);
/**\name Any motion enable macros */
static constexpr uint8_t ANY_NO_MOTION_AXIS_EN_POS = (5);
static constexpr uint8_t ANY_NO_MOTION_AXIS_EN_MSK = (0xE0);
/**\name Any motion duration macros */
static constexpr uint16_t ANY_NO_MOTION_DUR_MSK = (0x1FFF);
/**\name INTERRUPT MAPS */
static constexpr uint8_t INTR1_MAP = (0);
static constexpr uint8_t INTR2_MAP = (1);
/**\name CONSTANTS */
static constexpr uint8_t FIFO_CONFIG_LENGTH = (2);
static constexpr uint8_t ACCEL_CONFIG_LENGTH = (2);
static constexpr uint8_t FIFO_WM_LENGTH = (2);
static constexpr uint16_t CONFIG_STREAM_SIZE = (6144);
static constexpr uint8_t NON_LATCH_MODE = (0);
static constexpr uint8_t LATCH_MODE = (1);
static constexpr uint8_t PUSH_PULL = (0);
static constexpr uint8_t ACTIVE_HIGH = (1);
static constexpr uint8_t ACTIVE_LOW = (0);
static constexpr uint8_t EDGE_TRIGGER = (1);
static constexpr uint8_t LEVEL_TRIGGER = (0);
static constexpr uint8_t OUTPUT_ENABLE = (1);
static constexpr uint8_t OUTPUT_DISABLE = (0);
static constexpr uint8_t INPUT_ENABLE = (1);
static constexpr uint8_t INPUT_DISABLE = (0);
/**\name OUTPUT TYPE ENABLE POSITION AND MASK*/
static constexpr uint8_t INT_EDGE_CTRL_MASK = (0x01);
static constexpr uint8_t INT_EDGE_CTRL_POS = (0x00);
static constexpr uint8_t INT_LEVEL_MASK = (0x02);
static constexpr uint8_t INT_LEVEL_POS = (0x01);
static constexpr uint8_t INT_OPEN_DRAIN_MASK = (0x04);
static constexpr uint8_t INT_OPEN_DRAIN_POS = (0x02);
static constexpr uint8_t INT_OUTPUT_EN_MASK = (0x08);
static constexpr uint8_t INT_OUTPUT_EN_POS = (0x03);
static constexpr uint8_t INT_INPUT_EN_MASK = (0x10);
static constexpr uint8_t INT_INPUT_EN_POS = (0x04);
/**\name Interrupt status macros */
static constexpr uint8_t STEP_CNTR_INT = (0x02);
static constexpr uint8_t ACTIVITY_INT = (0x04);
static constexpr uint8_t TILT_INT = (0x08);
static constexpr uint8_t WAKEUP_INT = (0x20);
static constexpr uint8_t ANY_NO_MOTION_INT = (0x40);
static constexpr uint8_t ERROR_INT = (0x80);
};

View File

@@ -0,0 +1,113 @@
/**
*
* @license MIT License
*
* Copyright (c) 2025 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file BQ27220Constants.h
* @author Lewis He (lewishe@outlook.com)
* @date 2025-01-16
*
*/
#pragma once
#include <stdint.h>
class BQ27220Constants
{
protected:
//* Sub command
static constexpr uint16_t BQ27220_SUB_CMD_CTRL_STATUS = (0x0000);
static constexpr uint16_t BQ27220_SUB_CMD_DEVICE_NUMBER = (0x0001);
static constexpr uint16_t BQ27220_SUB_CMD_FW_VERSION = (0x0002);
static constexpr uint16_t BQ27220_SUB_CMD_HW_VERSION = (0x0003);
static constexpr uint16_t BQ27220_SUB_CMD_BOARD_OFFSET = (0x0009);
static constexpr uint16_t BQ27220_SUB_CMD_CC_OFFSET = (0x000A);
static constexpr uint16_t BQ27220_SUB_CMD_CC_OFFSET_SAVE = (0x000B);
static constexpr uint16_t BQ27220_SUB_CMD_OCV_CMD = (0x000C);
static constexpr uint16_t BQ27220_SUB_CMD_BAT_INSERT = (0x000D);
static constexpr uint16_t BQ27220_SUB_CMD_BAT_REMOVE = (0x000E);
static constexpr uint16_t BQ27220_SUB_CMD_SET_SNOOZE = (0x0013);
static constexpr uint16_t BQ27220_SUB_CMD_CLEAR_SNOOZE = (0x0014);
static constexpr uint16_t BQ27220_SUB_CMD_SET_PROFILE_1 = (0x0015);
static constexpr uint16_t BQ27220_SUB_CMD_SET_PROFILE_2 = (0x0016);
static constexpr uint16_t BQ27220_SUB_CMD_SET_PROFILE_3 = (0x0017);
static constexpr uint16_t BQ27220_SUB_CMD_SET_PROFILE_4 = (0x0018);
static constexpr uint16_t BQ27220_SUB_CMD_SET_PROFILE_5 = (0x0019);
static constexpr uint16_t BQ27220_SUB_CMD_SET_PROFILE_6 = (0x001A);
static constexpr uint16_t BQ27220_SUB_CMD_CAL_TOGGLE = (0x002D);
static constexpr uint16_t BQ27220_SUB_CMD_SEALED = (0x0030);
static constexpr uint16_t BQ27220_SUB_CMD_RESET = (0x0041);
static constexpr uint16_t BQ27220_SUB_CMD_EXIT_CAL = (0x0080);
static constexpr uint16_t BQ27220_SUB_CMD_ENTER_CAL = (0x0081);
static constexpr uint16_t BQ27220_SUB_CMD_ENTER_CFG_UPDATE = (0x0090);
static constexpr uint16_t BQ27220_SUB_CMD_EXIT_CFG_UPDATE_REINIT = (0x0091);
static constexpr uint16_t BQ27220_SUB_CMD_EXIT_CFG_UPDATE = (0x0092);
static constexpr uint16_t BQ27220_SUB_CMD_RETURN_TO_ROM = (0x0F00);
//* Standard commands
static constexpr uint8_t BQ27220_REG_STA_AT_RATE = (0x02);
static constexpr uint8_t BQ27220_REG_STA_AT_RATE_TIME_TO_EMPTY = (0x04);
static constexpr uint8_t BQ27220_REG_STA_NTC_TEMP = (0x06);
static constexpr uint8_t BQ27220_REG_STA_BAT_VOLTAGE = (0x08);
static constexpr uint8_t BQ27220_REG_STA_BAT_STATUS = (0x0A);
static constexpr uint8_t BQ27220_REG_STA_CURRENT = (0x0C);
static constexpr uint8_t BQ27220_REG_STA_REMAINING_CAPACITY = (0x10);
static constexpr uint8_t BQ27220_REG_STA_FULL_CHARGE_CAPACITY = (0x12);
static constexpr uint8_t BQ27220_REG_STA_TIME_TO_EMPTY = (0x16);
static constexpr uint8_t BQ27220_REG_STA_TIME_TO_FULL = (0x18);
static constexpr uint8_t BQ27220_REG_STA_STANDBY_CURRENT = (0x1A);
static constexpr uint8_t BQ27220_REG_STA_STANDBY_TIME_TO_EMPTY = (0x1C);
static constexpr uint8_t BQ27220_REG_STA_MAX_LOAD_CURRENT = (0x1E);
static constexpr uint8_t BQ27220_REG_STA_MAX_LOAD_TO_EMPTY = (0x20);
static constexpr uint8_t BQ27220_REG_STA_COULOMB_COUNT = (0x22);
static constexpr uint8_t BQ27220_REG_STA_AVG_POWER = (0x24);
static constexpr uint8_t BQ27220_REG_STA_INTER_TEMP = (0x28);
static constexpr uint8_t BQ27220_REG_STA_CYCLE_COUNT = (0x2A);
static constexpr uint8_t BQ27220_REG_STA_STATE_OF_CHARGE = (0x2C);
static constexpr uint8_t BQ27220_REG_STA_STATE_OF_HEALTH = (0x2E);
static constexpr uint8_t BQ27220_REG_STA_CHARGING_VOLTAGE = (0x30);
static constexpr uint8_t BQ27220_REG_STA_CHARGING_CURRENT = (0x32);
static constexpr uint8_t BQ27220_REG_STA_BTP_DISC_SET = (0x34);
static constexpr uint8_t BQ27220_REG_STA_BTP_CHARGE_SET = (0x36);
static constexpr uint8_t BQ27220_REG_STA_OPERATION_STATUS = (0x3A);
static constexpr uint8_t BQ27220_REG_STA_DESIGN_CAPACITY = (0x3C);
static constexpr uint8_t BQ27220_REG_STA_DESIGN_CAPACITY_MSB = (0x3E);
static constexpr uint8_t BQ27220_REG_STA_DESIGN_CAPACITY_LSB = (0x3F);
static constexpr uint8_t BQ27220_REG_MAC_BUFFER_START = (0x40);
static constexpr uint8_t BQ27220_REG_MAC_BUFFER_END = (0x5F);
static constexpr uint8_t BQ27220_REG_MAC_DATA_SUM = (0x60);
static constexpr uint8_t BQ27220_REG_MAC_DATA_LEN = (0x61);
static constexpr uint8_t BQ27220_REG_ANALOG_COUNT = (0x79);
static constexpr uint8_t BQ27220_REG_RAW_CURRENT = (0x7A);
static constexpr uint8_t BQ27220_REG_RAW_VOLTAGE = (0x7C);
static constexpr uint8_t BQ27220_REG_ROM_START = (0x3E);
static constexpr uint16_t BQ27220_CHIP_ID = (0x0220);
static constexpr uint16_t BQ27220_ROM_FULL_CHARGE_CAPACITY = (0x929D);
static constexpr uint16_t BQ27220_ROM_DESIGN_CAPACITY = (0x929F);
static constexpr uint16_t BQ27220_ROM_OPERATION_CONFIG_A = (0x9206);
static constexpr uint16_t BQ27220_ROM_OPERATION_CONFIG_B = (0x9208);
};

View File

@@ -0,0 +1,32 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file CHSC5816Constants.h
* @author Lewis He (lewishe@outlook.com)
* @date 2023-04-17
*
*/
#pragma once

View File

@@ -0,0 +1,64 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file CM32181Constants.h
* @author Lewis He (lewishe@outlook.com)
* @date 2023-04-14
*
*/
#pragma once
#include <stdint.h>
// CM32181 slave address can be 0x10 or 0x48, determined by pin ADDR configuration
#define CM32181_ADDR_PRIMARY (0x10)
#define CM32181_ADDR_SECONDARY (0x48)
#define CM32181_SLAVE_ADDRESS (0x10) //Compatible with previous version definitions
class CM32181Constants
{
protected:
// CM32181 registers
static constexpr uint8_t REG_ALS_CONF = 0x00;
static constexpr uint8_t REG_ALS_THDH = 0x01;
static constexpr uint8_t REG_ALS_THDL = 0x02;
static constexpr uint8_t REG_ALS_PSM = 0x03;
static constexpr uint8_t REG_ALS_DATA = 0x04;
static constexpr uint8_t REG_ALS_STATUS = 0x06;
static constexpr uint8_t REG_ID = 0x07;
static constexpr uint8_t CM32181_CHIP_ID = 0x81;
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,43 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file CSTxxxConstants.h
* @author Lewis He (lewishe@outlook.com)
* @date 2023-04-24
*
*/
#pragma once
// #define CST816S_CHIP_ID (0xB4)
// #define CST816T_CHIP_ID (0xB5)
// #define CST716_CHIP_ID (0x20)
// #define CST226SE_CHIP_ID (0xA8)

View File

@@ -0,0 +1,89 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file DRV2605Constants.h
* @author Lewis He (lewishe@outlook.com)
* @date 2023-04-03
*
*/
#pragma once
#include <stdint.h>
class DRV2605Constants
{
protected:
static constexpr uint8_t DRV2605_SLAVE_ADDRESS = 0x5A;
// Chip IDs
static constexpr uint8_t DRV2604_CHIP_ID = 0x04; //* DRV2604 (contains RAM, does not contain licensed ROM library)
static constexpr uint8_t DRV2605_CHIP_ID = 0x03; //* DRV2605 (contains licensed ROM library, does not contain RAM)
static constexpr uint8_t DRV2604L_CHIP_ID = 0x06; //* DRV2604L (low-voltage version of the DRV2604 device)
static constexpr uint8_t DRV2605L_CHIP_ID = 0x07; //* DRV2605L (low-voltage version of the DRV2605 device)
// Registers
static constexpr uint8_t DRV2605_REG_STATUS = 0x00; //* Status register
static constexpr uint8_t DRV2605_REG_MODE = 0x01; //* Mode register
static constexpr uint8_t DRV2605_REG_RTPIN = 0x02; //* Real-time playback input register
static constexpr uint8_t DRV2605_REG_LIBRARY = 0x03; //* Waveform library selection register
static constexpr uint8_t DRV2605_REG_WAVESEQ1 = 0x04; //* Waveform sequence register 1
static constexpr uint8_t DRV2605_REG_WAVESEQ2 = 0x05; //* Waveform sequence register 2
static constexpr uint8_t DRV2605_REG_WAVESEQ3 = 0x06; //* Waveform sequence register 3
static constexpr uint8_t DRV2605_REG_WAVESEQ4 = 0x07; //* Waveform sequence register 4
static constexpr uint8_t DRV2605_REG_WAVESEQ5 = 0x08; //* Waveform sequence register 5
static constexpr uint8_t DRV2605_REG_WAVESEQ6 = 0x09; //* Waveform sequence register 6
static constexpr uint8_t DRV2605_REG_WAVESEQ7 = 0x0A; //* Waveform sequence register 7
static constexpr uint8_t DRV2605_REG_WAVESEQ8 = 0x0B; //* Waveform sequence register 8
static constexpr uint8_t DRV2605_REG_GO = 0x0C; //* Go register
static constexpr uint8_t DRV2605_REG_OVERDRIVE = 0x0D; //* Overdrive time offset register
static constexpr uint8_t DRV2605_REG_SUSTAINPOS = 0x0E; //* Sustain time offset, positive register
static constexpr uint8_t DRV2605_REG_SUSTAINNEG = 0x0F; //* Sustain time offset, negative register
static constexpr uint8_t DRV2605_REG_BREAK = 0x10; //* Brake time offset register
static constexpr uint8_t DRV2605_REG_AUDIOCTRL = 0x11; //* Audio-to-vibe control register
static constexpr uint8_t DRV2605_REG_AUDIOLVL = 0x12; //* Audio-to-vibe minimum input level register
static constexpr uint8_t DRV2605_REG_AUDIOMAX = 0x13; //* Audio-to-vibe maximum input level register
static constexpr uint8_t DRV2605_REG_AUDIOOUTMIN = 0x14; //* Audio-to-vibe minimum output drive register
static constexpr uint8_t DRV2605_REG_AUDIOOUTMAX = 0x15; //* Audio-to-vibe maximum output drive register
static constexpr uint8_t DRV2605_REG_RATEDV = 0x16; //* Rated voltage register
static constexpr uint8_t DRV2605_REG_CLAMPV = 0x17; //* Overdrive clamp voltage register
static constexpr uint8_t DRV2605_REG_AUTOCALCOMP = 0x18; //* Auto-calibration compensation result register
static constexpr uint8_t DRV2605_REG_AUTOCALEMP = 0x19; //* Auto-calibration back-EMF result register
static constexpr uint8_t DRV2605_REG_FEEDBACK = 0x1A; //* Feedback control register
static constexpr uint8_t DRV2605_REG_CONTROL1 = 0x1B; //* Control1 Register
static constexpr uint8_t DRV2605_REG_CONTROL2 = 0x1C; //* Control2 Register
static constexpr uint8_t DRV2605_REG_CONTROL3 = 0x1D; //* Control3 Register
static constexpr uint8_t DRV2605_REG_CONTROL4 = 0x1E; //* Control4 Register
static constexpr uint8_t DRV2605_REG_VBAT = 0x21; //* Vbat voltage-monitor register
static constexpr uint8_t DRV2605_REG_LRARESON = 0x22; //* LRA resonance-period register
};

View File

@@ -0,0 +1,65 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file FT6X36Constants.h
* @author Lewis He (lewishe@outlook.com)
* @date 2023-04-01
*
*/
#pragma once
#define FT3267_SLAVE_ADDRESS (0x38)
#define FT5206_SLAVE_ADDRESS (0x38)
#define FT6X36_SLAVE_ADDRESS (0x38)
#define FT6X36_VEND_ID ((uint8_t)0x11)
#define FT3267_CHIP_ID ((uint8_t)0x33)
#define FT6206_CHIP_ID ((uint8_t)0x06)
#define FT6236_CHIP_ID ((uint8_t)0x36)
#define FT6236U_CHIP_ID ((uint8_t)0x64)
#define FT5206U_CHIP_ID ((uint8_t)0x64)
#define FT6X36_REG_MODE ((uint8_t)0x00)
#define FT6X36_REG_GEST ((uint8_t)0x01)
#define FT6X36_REG_STATUS ((uint8_t)0x02)
#define FT6X36_REG_TOUCH1_XH ((uint8_t)0x03)
#define FT6X36_REG_TOUCH1_XL ((uint8_t)0x04)
#define FT6X36_REG_TOUCH1_YH ((uint8_t)0x05)
#define FT6X36_REG_TOUCH1_YL ((uint8_t)0x06)
#define FT6X36_REG_THRESHOLD ((uint8_t)0x80)
#define FT6X36_REG_MONITOR_TIME ((uint8_t)0x87)
#define FT6X36_REG_PERIOD_ACTIVE ((uint8_t)0x88)
#define FT6X36_REG_PERIOD_MONITOR ((uint8_t)0x89)
#define FT6X36_REG_AUTO_CLB_MODE ((uint8_t)0xA0)
#define FT6X36_REG_LIB_VERSION_H ((uint8_t)0xA1)
#define FT6X36_REG_LIB_VERSION_L ((uint8_t)0xA2)
#define FT6X36_REG_INT_STATUS ((uint8_t)0xA4)
#define FT6X36_REG_POWER_MODE ((uint8_t)0xA5)
#define FT6X36_REG_FIRM_VERS ((uint8_t)0xA6)
#define FT6X36_REG_CHIP_ID ((uint8_t)0xA3)
#define FT6X36_REG_VENDOR1_ID ((uint8_t)0xA8)
#define FT6X36_REG_ERROR_STATUS ((uint8_t)0xA9)

View File

@@ -0,0 +1,172 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file GT911Constants.h
* @author Lewis He (lewishe@outlook.com)
* @date 2023-04-12
*
*/
#pragma once
#include <stdint.h>
#define GT911_SLAVE_ADDRESS_H (0x14)
#define GT911_SLAVE_ADDRESS_L (0x5D)
#define GT911_SLAVE_ADDRESS_UNKOWN (0xFF)
class GT911Constants
{
protected:
// Real-time command (Write only)
static constexpr uint16_t GT911_COMMAND = (0x8040);
static constexpr uint16_t GT911_ESD_CHECK = (0x8041);
static constexpr uint16_t GT911_COMMAND_CHECK = (0x8046);
// Configuration information (R/W)
static constexpr uint16_t GT911_CONFIG_START = (0x8047);
static constexpr uint16_t GT911_CONFIG_VERSION = (0x8047);
static constexpr uint16_t GT911_X_OUTPUT_MAX_LOW = (0x8048);
static constexpr uint16_t GT911_X_OUTPUT_MAX_HIGH = (0x8049);
static constexpr uint16_t GT911_Y_OUTPUT_MAX_LOW = (0x804A);
static constexpr uint16_t GT911_Y_OUTPUT_MAX_HIGH = (0x804B);
static constexpr uint16_t GT911_TOUCH_NUMBER = (0x804C);
static constexpr uint16_t GT911_MODULE_SWITCH_1 = (0x804D);
static constexpr uint16_t GT911_MODULE_SWITCH_2 = (0x804E);
static constexpr uint16_t GT911_SHAKE_COUNT = (0x804F);
static constexpr uint16_t GT911_FILTER = (0x8050);
static constexpr uint16_t GT911_LARGE_TOUCH = (0x8051);
static constexpr uint16_t GT911_NOISE_REDUCTION = (0x8052);
static constexpr uint16_t GT911_SCREEN_TOUCH_LEVEL = (0x8053);
static constexpr uint16_t GT911_SCREEN_RELEASE_LEVEL = (0x8054);
static constexpr uint16_t GT911_LOW_POWER_CONTROL = (0x8055);
static constexpr uint16_t GT911_REFRESH_RATE = (0x8056);
static constexpr uint16_t GT911_X_THRESHOLD = (0x8057);
static constexpr uint16_t GT911_Y_THRESHOLD = (0x8058);
static constexpr uint16_t GT911_X_SPEED_LIMIT = (0x8059); // Reserve
static constexpr uint16_t GT911_Y_SPEED_LIMIT = (0x805A); // Reserve
static constexpr uint16_t GT911_SPACE_TOP_BOTTOM = (0x805B);
static constexpr uint16_t GT911_SPACE_LEFT_RIGHT = (0x805C);
static constexpr uint16_t GT911_MINI_FILTER = (0x805D);
static constexpr uint16_t GT911_STRETCH_R0 = (0x805E);
static constexpr uint16_t GT911_STRETCH_R1 = (0x805F);
static constexpr uint16_t GT911_STRETCH_R2 = (0x8060);
static constexpr uint16_t GT911_STRETCH_RM = (0x8061);
static constexpr uint16_t GT911_DRV_GROUPA_NUM = (0x8062);
static constexpr uint16_t GT911_DRV_GROUPB_NUM = (0x8063);
static constexpr uint16_t GT911_SENSOR_NUM = (0x8064);
static constexpr uint16_t GT911_FREQ_A_FACTOR = (0x8065);
static constexpr uint16_t GT911_FREQ_B_FACTOR = (0x8066);
static constexpr uint16_t GT911_PANEL_BIT_FREQ_L = (0x8067);
static constexpr uint16_t GT911_PANEL_BIT_FREQ_H = (0x8068);
static constexpr uint16_t GT911_PANEL_SENSOR_TIME_L = (0x8069); // Reserve
static constexpr uint16_t GT911_PANEL_SENSOR_TIME_H = (0x806A);
static constexpr uint16_t GT911_PANEL_TX_GAIN = (0x806B);
static constexpr uint16_t GT911_PANEL_RX_GAIN = (0x806C);
static constexpr uint16_t GT911_PANEL_DUMP_SHIFT = (0x806D);
static constexpr uint16_t GT911_DRV_FRAME_CONTROL = (0x806E);
static constexpr uint16_t GT911_CHARGING_LEVEL_UP = (0x806F);
static constexpr uint16_t GT911_MODULE_SWITCH3 = (0x8070);
static constexpr uint16_t GT911_GESTURE_DIS = (0X8071);
static constexpr uint16_t GT911_GESTURE_LONG_PRESS_TIME = (0x8072);
static constexpr uint16_t GT911_X_Y_SLOPE_ADJUST = (0X8073);
static constexpr uint16_t GT911_GESTURE_CONTROL = (0X8074);
static constexpr uint16_t GT911_GESTURE_SWITCH1 = (0X8075);
static constexpr uint16_t GT911_GESTURE_SWITCH2 = (0X8076);
static constexpr uint16_t GT911_GESTURE_REFRESH_RATE = (0x8077);
static constexpr uint16_t GT911_GESTURE_TOUCH_LEVEL = (0x8078);
static constexpr uint16_t GT911_NEWGREENWAKEUPLEVEL = (0x8079);
static constexpr uint16_t GT911_FREQ_HOPPING_START = (0x807A);
static constexpr uint16_t GT911_FREQ_HOPPING_END = (0X807B);
static constexpr uint16_t GT911_NOISE_DETECT_TIMES = (0x807C);
static constexpr uint16_t GT911_HOPPING_FLAG = (0X807D);
static constexpr uint16_t GT911_HOPPING_THRESHOLD = (0X807E);
static constexpr uint16_t GT911_NOISE_THRESHOLD = (0X807F); // Reserve
static constexpr uint16_t GT911_NOISE_MIN_THRESHOLD = (0X8080);
static constexpr uint16_t GT911_HOPPING_SENSOR_GROUP = (0X8082);
static constexpr uint16_t GT911_HOPPING_SEG1_NORMALIZE = (0X8083);
static constexpr uint16_t GT911_HOPPING_SEG1_FACTOR = (0X8084);
static constexpr uint16_t GT911_MAIN_CLOCK_ADJUST = (0X8085);
static constexpr uint16_t GT911_HOPPING_SEG2_NORMALIZE = (0X8086);
static constexpr uint16_t GT911_HOPPING_SEG2_FACTOR = (0X8087);
static constexpr uint16_t GT911_HOPPING_SEG3_NORMALIZE = (0X8089);
static constexpr uint16_t GT911_HOPPING_SEG3_FACTOR = (0X808A);
static constexpr uint16_t GT911_HOPPING_SEG4_NORMALIZE = (0X808C);
static constexpr uint16_t GT911_HOPPING_SEG4_FACTOR = (0X808D);
static constexpr uint16_t GT911_HOPPING_SEG5_NORMALIZE = (0X808F);
static constexpr uint16_t GT911_HOPPING_SEG5_FACTOR = (0X8090);
static constexpr uint16_t GT911_HOPPING_SEG6_NORMALIZE = (0X8092);
static constexpr uint16_t GT911_KEY_1 = (0X8093);
static constexpr uint16_t GT911_KEY_2 = (0X8094);
static constexpr uint16_t GT911_KEY_3 = (0X8095);
static constexpr uint16_t GT911_KEY_4 = (0X8096);
static constexpr uint16_t GT911_KEY_AREA = (0X8097);
static constexpr uint16_t GT911_KEY_TOUCH_LEVEL = (0X8098);
static constexpr uint16_t GT911_KEY_LEAVE_LEVEL = (0X8099);
static constexpr uint16_t GT911_KEY_SENS_1_2 = (0X809A);
static constexpr uint16_t GT911_KEY_SENS_3_4 = (0X809B);
static constexpr uint16_t GT911_KEY_RESTRAIN = (0X809C);
static constexpr uint16_t GT911_KEY_RESTRAIN_TIME = (0X809D);
static constexpr uint16_t GT911_GESTURE_LARGE_TOUCH = (0X809E);
static constexpr uint16_t GT911_HOTKNOT_NOISE_MAP = (0X80A1);
static constexpr uint16_t GT911_LINK_THRESHOLD = (0X80A2);
static constexpr uint16_t GT911_PXY_THRESHOLD = (0X80A3);
static constexpr uint16_t GT911_GHOT_DUMP_SHIFT = (0X80A4);
static constexpr uint16_t GT911_GHOT_RX_GAIN = (0X80A5);
static constexpr uint16_t GT911_FREQ_GAIN0 = (0X80A6);
static constexpr uint16_t GT911_FREQ_GAIN1 = (0X80A7);
static constexpr uint16_t GT911_FREQ_GAIN2 = (0X80A8);
static constexpr uint16_t GT911_FREQ_GAIN3 = (0X80A9);
static constexpr uint16_t GT911_COMBINE_DIS = (0X80B3);
static constexpr uint16_t GT911_SPLIT_SET = (0X80B4);
static constexpr uint16_t GT911_SENSOR_CH0 = (0X80B7);
static constexpr uint16_t GT911_DRIVER_CH0 = (0X80D5);
static constexpr uint16_t GT911_CONFIG_CHKSUM = (0X80FF);
static constexpr uint16_t GT911_CONFIG_FRESH = (0X8100);
static constexpr uint16_t GT911_CONFIG_SIZE = (0xFF - 0x46);
// Coordinate information
static constexpr uint16_t GT911_PRODUCT_ID = (0x8140);
static constexpr uint16_t GT911_FIRMWARE_VERSION = (0x8144);
static constexpr uint16_t GT911_X_RESOLUTION = (0x8146);
static constexpr uint16_t GT911_Y_RESOLUTION = (0x8148);
static constexpr uint16_t GT911_VENDOR_ID = (0X8140);
static constexpr uint16_t GT911_INFORMATION = (0X8140);
static constexpr uint16_t GT911_POINT_INFO = (0X814E);
static constexpr uint16_t GT911_POINT_1 = (0X814F);
static constexpr uint16_t GT911_POINT_2 = (0X8157);
static constexpr uint16_t GT911_POINT_3 = (0X815F);
static constexpr uint16_t GT911_POINT_4 = (0X8167);
static constexpr uint16_t GT911_POINT_5 = (0X816F);
static constexpr uint16_t GT911_DEV_ID = (911);
static constexpr uint8_t GT911_BASE_REF_RATE = (5);
static constexpr uint8_t GT911_REG_LENGTH = (186);
};

View File

@@ -0,0 +1,251 @@
/**
*
* @license MIT License
*
* Copyright (c) 2024 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file GT9895Constants.h
* @author Lewis He (lewishe@outlook.com)
* @date 2024-09-21
*
*/
#pragma once
#include <stdint.h>
#define GT9895_SLAVE_ADDRESS_H (0x14)
#define GT9895_SLAVE_ADDRESS_L (0x5D)
class GT9895Constants
{
public:
#define GT9895_MAX_TOUCH (10)
#define GT9895_MAX_PEN_KEY (2)
#define GT9895_INFO_MAX_LENGTH (1024)
#define GT9895_MAX_SCAN_RATE_NUM (8)
#define GT9895_MAX_SCAN_FREQ_NUM (8)
#define GT9895_MAX_FREQ_NUM_STYLUS (8)
#define GT9895_GESTURE_DATA_LEN (16)
#define GT9895_IRQ_EVENT_HEAD_LEN (8)
#define GT9895_BYTES_PER_POINT (8)
#define GT9895_COORDS_DATA_CHECKSUM_SIZE (2)
enum CHECKSUM_MODE {
CHECKSUM_MODE_U8_LE,
CHECKSUM_MODE_U16_LE,
};
enum TouchPointStatus {
TS_NONE,
TS_RELEASE,
TS_TOUCH,
};
/* interrupt event type */
enum TsEventType {
EVENT_INVALID = 0,
EVENT_TOUCH = (1 << 0), /* finger touch event */
EVENT_PEN = (1 << 1), /* pen event */
EVENT_REQUEST = (1 << 2),
EVENT_GESTURE = (1 << 3),
};
enum brl_request_code {
BRL_REQUEST_CODE_CONFIG = 0x01,
BRL_REQUEST_CODE_REF_ERR = 0x02,
BRL_REQUEST_CODE_RESET = 0x03,
BRL_REQUEST_CODE_CLOCK = 0x04,
};
/* coordinate package */
typedef struct {
int status; /* NONE, RELEASE, TOUCH */
unsigned int x, y, w, p;
} TsCoords;
/* touch event data */
typedef struct {
int touch_num;
uint64_t timestamp;
TsCoords coords[GT9895_MAX_TOUCH];
} TouchData;
typedef struct {
int status;
int code;
} TsKey;
typedef struct {
int status; /* NONE, RELEASE, TOUCH */
int tool_type; /* BTN_TOOL_RUBBER BTN_TOOL_PEN */
unsigned int x, y, p;
signed char tilt_x;
signed char tilt_y;
} PenCoords;
typedef struct {
PenCoords coords;
TsKey keys[GT9895_MAX_PEN_KEY];
} PenData;
typedef struct {
int id;
int x;
int y;
int w;
int p;
int tool_type;
} PointData;
/*
* ChipTsEvent - touch event struct
* @event_type: touch event type, touch data or
* request event
* @event_data: event data
*/
typedef struct {
enum TsEventType event_type;
uint8_t fp_flag; /* finger print DOWN flag */
uint8_t request_code; /* represent the request type */
uint8_t gesture_type;
uint8_t gesture_data[GT9895_GESTURE_DATA_LEN];
TouchData touch_data;
PenData pen_data;
} ChipTsEvent;
typedef struct {
uint8_t rom_pid[6]; /* rom PID */
uint8_t rom_vid[3]; /* Mask VID */
uint8_t rom_vid_reserved;
uint8_t patch_pid[8]; /* Patch PID */
uint8_t patch_vid[4]; /* Patch VID */
uint8_t patch_vid_reserved;
uint8_t sensor_id;
uint8_t reserved[2];
uint16_t checksum;
} ChipFirmwareVersion;
typedef struct {
uint8_t info_customer_id;
uint8_t info_version_id;
uint8_t ic_die_id;
uint8_t ic_version_id;
uint32_t config_id;
uint8_t config_version;
uint8_t frame_data_customer_id;
uint8_t frame_data_version_id;
uint8_t touch_data_customer_id;
uint8_t touch_data_version_id;
uint8_t reserved[3];
} ChipInfoVersion;
typedef struct { /* feature info*/
uint16_t freqhop_feature;
uint16_t calibration_feature;
uint16_t gesture_feature;
uint16_t side_touch_feature;
uint16_t stylus_feature;
} ChipInfoFeature;
typedef struct { /* param */
uint8_t drv_num;
uint8_t sen_num;
uint8_t button_num;
uint8_t force_num;
uint8_t active_scan_rate_num;
uint16_t active_scan_rate[GT9895_MAX_SCAN_RATE_NUM];
uint8_t mutual_freq_num;
uint16_t mutual_freq[GT9895_MAX_SCAN_FREQ_NUM];
uint8_t self_tx_freq_num;
uint16_t self_tx_freq[GT9895_MAX_SCAN_FREQ_NUM];
uint8_t self_rx_freq_num;
uint16_t self_rx_freq[GT9895_MAX_SCAN_FREQ_NUM];
uint8_t stylus_freq_num;
uint16_t stylus_freq[GT9895_MAX_FREQ_NUM_STYLUS];
} ChipInfoParams;
typedef struct { /* other data */
uint32_t cmd_addr;
uint16_t cmd_max_len;
uint32_t cmd_reply_addr;
uint16_t cmd_reply_len;
uint32_t fw_state_addr;
uint16_t fw_state_len;
uint32_t fw_buffer_addr;
uint16_t fw_buffer_max_len;
uint32_t frame_data_addr;
uint16_t frame_data_head_len;
uint16_t fw_attr_len;
uint16_t fw_log_len;
uint8_t pack_max_num;
uint8_t pack_compress_version;
uint16_t stylus_struct_len;
uint16_t mutual_struct_len;
uint16_t self_struct_len;
uint16_t noise_struct_len;
uint32_t touch_data_addr;
uint16_t touch_data_head_len;
uint16_t point_struct_len;
uint16_t reserved1;
uint16_t reserved2;
uint32_t mutual_rawdata_addr;
uint32_t mutual_diffdata_addr;
uint32_t mutual_refdata_addr;
uint32_t self_rawdata_addr;
uint32_t self_diffdata_addr;
uint32_t self_refdata_addr;
uint32_t iq_rawdata_addr;
uint32_t iq_refdata_addr;
uint32_t im_rawdata_addr;
uint16_t im_readata_len;
uint32_t noise_rawdata_addr;
uint16_t noise_rawdata_len;
uint32_t stylus_rawdata_addr;
uint16_t stylus_rawdata_len;
uint32_t noise_data_addr;
uint32_t esd_addr;
} ChipInfoMisc;
typedef struct {
uint16_t length;
ChipInfoVersion version;
ChipInfoFeature feature;
ChipInfoParams parm;
ChipInfoMisc misc;
} ChipInfo;
protected:
static constexpr uint8_t GT9895_POINT_TYPE_STYLUS_HOVER = (0x01);
static constexpr uint8_t GT9895_POINT_TYPE_STYLUS = (0x03);
static constexpr uint8_t GT9895_TOUCH_EVENT = (0x80);
static constexpr uint8_t GT9895_REQUEST_EVENT = (0x40);
static constexpr uint8_t GT9895_GESTURE_EVENT = (0x20);
static constexpr uint8_t GT9895_FP_EVENT = (0x08);
#define GT9895_REG_FW_VERSION (0x00010014u)
#define GT9895_REG_INFO (0x00010070u)
#define GT9895_REG_CMD (0x00010174u)
#define GT9895_REG_POINT (0x00010308u)
};

View File

@@ -0,0 +1,71 @@
/**
*
* @license MIT License
*
* Copyright (c) 2023 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file LTR533Constants.hpp
* @author Lewis He (lewishe@outlook.com)
* @date 2023-09-09
*/
#pragma once
#include <stdint.h>
class LTR553Constants
{
protected:
// Unique I2C device address
static constexpr uint8_t LTR553_SLAVE_ADDRESS = 0x23;
// Registers
static constexpr uint8_t REG_ALS_CONTR = 0x80;
static constexpr uint8_t REG_PS_CONTR = 0x81;
static constexpr uint8_t REG_PS_LED = 0x82;
static constexpr uint8_t REG_PS_N_PULSES = 0x83;
static constexpr uint8_t REG_PS_MEAS_RATE = 0x84;
static constexpr uint8_t REG_ALS_MEAS_RATE = 0x85;
static constexpr uint8_t REG_PART_ID = 0x86;
static constexpr uint8_t REG_MANUFAC_ID = 0x87;
static constexpr uint8_t REG_ALS_DATA_CH1_0 = 0x88;
static constexpr uint8_t REG_ALS_DATA_CH1_1 = 0x89;
static constexpr uint8_t REG_ALS_DATA_CH0_0 = 0x8A;
static constexpr uint8_t REG_ALS_DATA_CH0_1 = 0x8B;
static constexpr uint8_t REG_ALS_PS_STATUS = 0x8C;
static constexpr uint8_t REG_PS_DATA_0 = 0x8D;
static constexpr uint8_t REG_PS_DATA_1 = 0x8E;
static constexpr uint8_t REG_INTERRUPT = 0x8F;
static constexpr uint8_t REG_PS_THRES_UP_0 = 0x90;
static constexpr uint8_t REG_PS_THRES_UP_1 = 0x91;
static constexpr uint8_t REG_PS_THRES_LOW_0 = 0x92;
static constexpr uint8_t REG_PS_THRES_LOW_1 = 0x93;
static constexpr uint8_t REG_PS_OFFSET_1 = 0x94;
static constexpr uint8_t REG_PS_OFFSET_0 = 0x95;
static constexpr uint8_t REG_ALS_THRES_UP_0 = 0x97;
static constexpr uint8_t REG_ALS_THRES_UP_1 = 0x98;
static constexpr uint8_t REG_ALS_THRES_LOW_0 = 0x99;
static constexpr uint8_t REG_ALS_THRES_LOW_1 = 0x9A;
static constexpr uint8_t REG_INTERRUPT_PERSIST = 0x9E;
// Default Manufacturer ID
static constexpr uint8_t LTR553_DEFAULT_MAN_ID = 0x05;
};

View File

@@ -0,0 +1,115 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file MPU6886Constants.h
* @author Lewis He (lewishe@outlook.com)
* @date 2022-10-16
*
*/
#pragma once
#define MPU6886_SLAVE_ADDRESS (0x68)
#define MPU6886_REG_XG_OFFS_TC_H ((uint8_t)0x04)
#define MPU6886_REG_XG_OFFS_TC_L ((uint8_t)0x05)
#define MPU6886_REG_YG_OFFS_TC_H ((uint8_t)0x07)
#define MPU6886_REG_YG_OFFS_TC_L ((uint8_t)0x08)
#define MPU6886_REG_ZG_OFFS_TC_H ((uint8_t)0x0A)
#define MPU6886_REG_ZG_OFFS_TC_L ((uint8_t)0x0B)
#define MPU6886_REG_SELF_TEST_X_ACCEL ((uint8_t)0x0D)
#define MPU6886_REG_SELF_TEST_Y_ACCEL ((uint8_t)0x0E)
#define MPU6886_REG_SELF_TEST_Z_ACCEL ((uint8_t)0x0F)
#define MPU6886_REG_XG_OFFS_USRH ((uint8_t)0x13)
#define MPU6886_REG_XG_OFFS_USRL ((uint8_t)0x14)
#define MPU6886_REG_YG_OFFS_USRH ((uint8_t)0x15)
#define MPU6886_REG_YG_OFFS_USRL ((uint8_t)0x16)
#define MPU6886_REG_ZG_OFFS_USRH ((uint8_t)0x17)
#define MPU6886_REG_ZG_OFFS_USRL ((uint8_t)0x18)
#define MPU6886_REG_SMPLRT_DIV ((uint8_t)0x19)
#define MPU6886_REG_CONFIG ((uint8_t)0x1A)
#define MPU6886_REG_GYRO_CONFIG ((uint8_t)0x1B)
#define MPU6886_REG_ACCEL_CONFIG ((uint8_t)0x1C)
#define MPU6886_REG_ACCEL_CONFIG_2 ((uint8_t)0x1D)
#define MPU6886_REG_LP_MODE_CFG ((uint8_t)0x1E)
#define MPU6886_REG_ACCEL_WOM_X_THR ((uint8_t)0x20)
#define MPU6886_REG_ACCEL_WOM_Y_THR ((uint8_t)0x21)
#define MPU6886_REG_ACCEL_WOM_Z_THR ((uint8_t)0x22)
#define MPU6886_REG_FIFO_EN ((uint8_t)0x23)
#define MPU6886_REG_FSYNC_INT ((uint8_t)0x36)
#define MPU6886_REG_INT_PIN_CFG ((uint8_t)0x37)
#define MPU6886_REG_INT_ENABLE ((uint8_t)0x38)
#define MPU6886_REG_FIFO_WM_INT_STATUS ((uint8_t)0x39)
#define MPU6886_REG_INT_STATUS ((uint8_t)0x3A)
#define MPU6886_REG_ACCEL_XOUT_H ((uint8_t)0x3B)
#define MPU6886_REG_ACCEL_XOUT_L ((uint8_t)0x3C)
#define MPU6886_REG_ACCEL_YOUT_H ((uint8_t)0x3D)
#define MPU6886_REG_ACCEL_YOUT_L ((uint8_t)0x3E)
#define MPU6886_REG_ACCEL_ZOUT_H ((uint8_t)0x3F)
#define MPU6886_REG_ACCEL_ZOUT_L ((uint8_t)0x40)
#define MPU6886_REG_TEMP_OUT_H ((uint8_t)0x41)
#define MPU6886_REG_TEMP_OUT_L ((uint8_t)0x42)
#define MPU6886_REG_GYRO_XOUT_H ((uint8_t)0x43)
#define MPU6886_REG_GYRO_XOUT_L ((uint8_t)0x44)
#define MPU6886_REG_GYRO_YOUT_H ((uint8_t)0x45)
#define MPU6886_REG_GYRO_YOUT_L ((uint8_t)0x46)
#define MPU6886_REG_GYRO_ZOUT_H ((uint8_t)0x47)
#define MPU6886_REG_GYRO_ZOUT_L ((uint8_t)0x48)
#define MPU6886_REG_SELF_TEST_X_GYRO ((uint8_t)0x50)
#define MPU6886_REG_SELF_TEST_Y_GYRO ((uint8_t)0x51)
#define MPU6886_REG_SELF_TEST_Z_GYRO ((uint8_t)0x52)
#define MPU6886_REG_E_ID0 ((uint8_t)0x53)
#define MPU6886_REG_E_ID1 ((uint8_t)0x54)
#define MPU6886_REG_E_ID2 ((uint8_t)0x55)
#define MPU6886_REG_E_ID3 ((uint8_t)0x56)
#define MPU6886_REG_E_ID4 ((uint8_t)0x57)
#define MPU6886_REG_E_ID5 ((uint8_t)0x58)
#define MPU6886_REG_E_ID6 ((uint8_t)0x59)
#define MPU6886_REG_FIFO_WM_TH1 ((uint8_t)0x60)
#define MPU6886_REG_FIFO_WM_TH2 ((uint8_t)0x61)
#define MPU6886_REG_SIGNAL_PATH_RESET ((uint8_t)0x68)
#define MPU6886_REG_ACCEL_INTEL_CTRL ((uint8_t)0x69)
#define MPU6886_REG_USER_CTRL ((uint8_t)0x6A)
#define MPU6886_REG_PWR_MGMT_1 ((uint8_t)0x6B)
#define MPU6886_REG_PWR_MGMT_2 ((uint8_t)0x6C)
#define MPU6886_REG_I2C_IF ((uint8_t)0x70)
#define MPU6886_REG_FIFO_COUNTH ((uint8_t)0x72)
#define MPU6886_REG_FIFO_COUNTL ((uint8_t)0x73)
#define MPU6886_REG_FIFO_R_W ((uint8_t)0x74)
#define MPU6886_REG_WHO_AM_I ((uint8_t)0x75)
#define MPU6886_REG_XA_OFFSET_H ((uint8_t)0x77)
#define MPU6886_REG_XA_OFFSET_L ((uint8_t)0x78)
#define MPU6886_REG_YA_OFFSET_H ((uint8_t)0x7A)
#define MPU6886_REG_YA_OFFSET_L ((uint8_t)0x7B)
#define MPU6886_REG_ZA_OFFSET_H ((uint8_t)0x7D)
#define MPU6886_REG_ZA_OFFSET_L ((uint8_t)0x7E)
#define MPU6886_WHO_AM_I_RES ((uint8_t)0x19)

View File

@@ -0,0 +1,71 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file PCF85063Constants.h
* @author Lewis He (lewishe@outlook.com)
* @date 2023-09-07
*
*/
#pragma once
#include <stdint.h>
class PCF85063Constants
{
protected:
// Unique I2C device address
static constexpr uint8_t PCF85063_SLAVE_ADDRESS = 0x51;
// Register addresses
static constexpr uint8_t PCF85063_CTRL1_REG = 0x00;
static constexpr uint8_t PCF85063_CTRL2_REG = 0x01;
static constexpr uint8_t PCF85063_OFFSET_REG = 0x02;
static constexpr uint8_t PCF85063_RAM_REG = 0x03;
static constexpr uint8_t PCF85063_SEC_REG = 0x04;
static constexpr uint8_t PCF85063_MIN_REG = 0x05;
static constexpr uint8_t PCF85063_HR_REG = 0x06;
static constexpr uint8_t PCF85063_DAY_REG = 0x07;
static constexpr uint8_t PCF85063_WEEKDAY_REG = 0x08;
static constexpr uint8_t PCF85063_MONTH_REG = 0x09;
static constexpr uint8_t PCF85063_YEAR_REG = 0x0A;
static constexpr uint8_t PCF85063_ALRM_SEC_REG = 0x0B;
static constexpr uint8_t PCF85063_ALRM_MIN_REG = 0x0C;
static constexpr uint8_t PCF8563_ALRM_HR_REG = 0x0D;
static constexpr uint8_t PCF85063_ALRM_DAY_REG = 0x0E;
static constexpr uint8_t PCF85063_ALRM_WEEK_REG = 0x0F;
static constexpr uint8_t PCF85063_TIMER_VAL_REG = 0x10;
static constexpr uint8_t PCF85063_TIMER_MD_REG = 0x11;
// Mask values
static constexpr uint8_t PCF85063_CTRL1_TEST_EN_MASK = (1 << 7u);
static constexpr uint8_t PCF85063_CTRL1_CLOCK_EN_MASK = (1 << 5u);
static constexpr uint8_t PCF85063_CTRL1_SOFTRST_EN_MASK = (1 << 4u);
static constexpr uint8_t PCF85063_CTRL1_CIE_EN_MASK = (1 << 2u);
static constexpr uint8_t PCF85063_CTRL1_HOUR_FORMAT_12H_MASK = (1 << 1u);
// Other constants
static constexpr uint8_t PCF85063_NO_ALARM = 0xFF;
static constexpr uint8_t PCF85063_ALARM_ENABLE = 0x80;
};

View File

@@ -0,0 +1,79 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file PCF8563Constants.h
* @author Lewis He (lewishe@outlook.com)
* @date 2022-12-09
*
*/
#pragma once
#include <stdint.h>
class PCF8563Constants
{
protected:
// Unique I2C device address
static constexpr uint8_t PCF8563_SLAVE_ADDRESS = 0x51;
// Register addresses
static constexpr uint8_t STAT1_REG = 0x00;
static constexpr uint8_t STAT2_REG = 0x01;
static constexpr uint8_t SEC_REG = 0x02;
static constexpr uint8_t MIN_REG = 0x03;
static constexpr uint8_t HR_REG = 0x04;
static constexpr uint8_t DAY_REG = 0x05;
static constexpr uint8_t WEEKDAY_REG = 0x06;
static constexpr uint8_t MONTH_REG = 0x07;
static constexpr uint8_t YEAR_REG = 0x08;
static constexpr uint8_t ALRM_MIN_REG = 0x09;
static constexpr uint8_t SQW_REG = 0x0D;
static constexpr uint8_t TIMER1_REG = 0x0E;
static constexpr uint8_t TIMER2_REG = 0x0F;
// Mask values
static constexpr uint8_t VOL_LOW_MASK = 0x80;
static constexpr uint8_t MINUTES_MASK = 0x7F;
static constexpr uint8_t HOUR_MASK = 0x3F;
static constexpr uint8_t WEEKDAY_MASK = 0x07;
static constexpr uint8_t CENTURY_MASK = 0x80;
static constexpr uint8_t DAY_MASK = 0x3F;
static constexpr uint8_t MONTH_MASK = 0x1F;
static constexpr uint8_t TIMER_CTL_MASK = 0x03;
// Alarm and Timer flags
static constexpr uint8_t ALARM_AF = 0x08;
static constexpr uint8_t TIMER_TF = 0x04;
static constexpr uint8_t ALARM_AIE = 0x02;
static constexpr uint8_t TIMER_TIE = 0x01;
static constexpr uint8_t TIMER_TE = 0x80;
static constexpr uint8_t TIMER_TD10 = 0x03;
// Other constants
static constexpr uint8_t NO_ALARM = 0xFF;
static constexpr uint8_t ALARM_ENABLE = 0x80;
static constexpr uint8_t CLK_ENABLE = 0x80;
};

View File

@@ -0,0 +1,58 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file QMC6310Constants.h
* @author Lewis He (lewishe@outlook.com)
* @date 2022-10-16
*
*/
#pragma once
#include <stdint.h>
class QMC6310Constants
{
protected:
// Register addresses
static constexpr uint8_t REG_CHIP_ID = 0x00;
static constexpr uint8_t REG_LSB_DX = 0x01;
static constexpr uint8_t REG_MSB_DX = 0x02;
static constexpr uint8_t REG_LSB_DY = 0x03;
static constexpr uint8_t REG_MSB_DY = 0x04;
static constexpr uint8_t REG_LSB_DZ = 0x05;
static constexpr uint8_t REG_MSB_DZ = 0x06;
static constexpr uint8_t REG_STAT = 0x09;
static constexpr uint8_t REG_CMD1 = 0x0A;
static constexpr uint8_t REG_CMD2 = 0x0B;
static constexpr uint8_t REG_SIGN = 0x29;
static constexpr uint8_t QMC6310_CHIP_ID = 0x80;
};

View File

@@ -0,0 +1,150 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file QMI8658Constants.h
* @author Lewis He (lewishe@outlook.com)
* @date 2022-10-16
*
*/
#pragma once
#include <stdint.h>
// @brief device address
#define QMI8658_L_SLAVE_ADDRESS (0x6B)
#define QMI8658_H_SLAVE_ADDRESS (0x6A)
class QMI8658Constants
{
protected:
// @brief registers default value
static constexpr uint8_t QMI8658_REG_WHOAMI_DEFAULT = 0x05;
static constexpr uint8_t QMI8658_REG_STATUS_DEFAULT = 0x03;
static constexpr uint8_t QMI8658_REG_RESET_DEFAULT = 0xB0;
//* General Purpose Registers
static constexpr uint8_t QMI8658_REG_WHOAMI = 0x00;
static constexpr uint8_t QMI8658_REG_REVISION = 0x01;
//* Setup and Control Registers
static constexpr uint8_t QMI8658_REG_CTRL1 = 0x02;
static constexpr uint8_t QMI8658_REG_CTRL2 = 0x03;
static constexpr uint8_t QMI8658_REG_CTRL3 = 0x04;
// Reserved
static constexpr uint8_t QMI8658_REG_CTRL5 = 0x06;
// Reserved
static constexpr uint8_t QMI8658_REG_CTRL7 = 0x08;
static constexpr uint8_t QMI8658_REG_CTRL8 = 0x09;
static constexpr uint8_t QMI8658_REG_CTRL9 = 0x0A;
//* Host Controlled Calibration Registers (See CTRL9, Usage is Optional)
static constexpr uint8_t QMI8658_REG_CAL1_L = 0x0B;
static constexpr uint8_t QMI8658_REG_CAL1_H = 0x0C;
static constexpr uint8_t QMI8658_REG_CAL2_L = 0x0D;
static constexpr uint8_t QMI8658_REG_CAL2_H = 0x0E;
static constexpr uint8_t QMI8658_REG_CAL3_L = 0x0F;
static constexpr uint8_t QMI8658_REG_CAL3_H = 0x10;
static constexpr uint8_t QMI8658_REG_CAL4_L = 0x11;
static constexpr uint8_t QMI8658_REG_CAL4_H = 0x12;
//* FIFO Registers
static constexpr uint8_t QMI8658_REG_FIFO_WTM_TH = 0x13;
static constexpr uint8_t QMI8658_REG_FIFO_CTRL = 0x14;
static constexpr uint8_t QMI8658_REG_FIFO_COUNT = 0x15;
static constexpr uint8_t QMI8658_REG_FIFO_STATUS = 0x16;
static constexpr uint8_t QMI8658_REG_FIFO_DATA = 0x17;
//* Status Registers
static constexpr uint8_t QMI8658_REG_STATUS_INT = 0x2D;
static constexpr uint8_t QMI8658_REG_STATUS0 = 0x2E;
static constexpr uint8_t QMI8658_REG_STATUS1 = 0x2F;
//* Timestamp Register
static constexpr uint8_t QMI8658_REG_TIMESTAMP_L = 0x30;
static constexpr uint8_t QMI8658_REG_TIMESTAMP_M = 0x31;
static constexpr uint8_t QMI8658_REG_TIMESTAMP_H = 0x32;
//* Data Output Registers (16 bits 2s Complement Except COD Sensor Data)
static constexpr uint8_t QMI8658_REG_TEMPERATURE_L = 0x33;
static constexpr uint8_t QMI8658_REG_TEMPERATURE_H = 0x34;
static constexpr uint8_t QMI8658_REG_AX_L = 0x35;
static constexpr uint8_t QMI8658_REG_AX_H = 0x36;
static constexpr uint8_t QMI8658_REG_AY_L = 0x37;
static constexpr uint8_t QMI8658_REG_AY_H = 0x38;
static constexpr uint8_t QMI8658_REG_AZ_L = 0x39;
static constexpr uint8_t QMI8658_REG_AZ_H = 0x3A;
static constexpr uint8_t QMI8658_REG_GX_L = 0x3B;
static constexpr uint8_t QMI8658_REG_GX_H = 0x3C;
static constexpr uint8_t QMI8658_REG_GY_L = 0x3D;
static constexpr uint8_t QMI8658_REG_GY_H = 0x3E;
static constexpr uint8_t QMI8658_REG_GZ_L = 0x3F;
static constexpr uint8_t QMI8658_REG_GZ_H = 0x40;
//* COD Indication and General Purpose Registers
// Calibration-On-Demand status register
static constexpr uint8_t QMI8658_REG_COD_STATUS = 0x46;
static constexpr uint8_t QMI8658_REG_DQW_L = 0x49;
static constexpr uint8_t QMI8658_REG_DQW_H = 0x4A;
static constexpr uint8_t QMI8658_REG_DQX_L = 0x4B;
static constexpr uint8_t QMI8658_REG_DQX_H = 0x4C;
static constexpr uint8_t QMI8658_REG_DQY_L = 0x4D;
static constexpr uint8_t QMI8658_REG_DQY_H = 0x4E;
static constexpr uint8_t QMI8658_REG_DQZ_L = 0x4F;
static constexpr uint8_t QMI8658_REG_DQZ_H = 0x50;
static constexpr uint8_t QMI8658_REG_DVX_L = 0x51;
static constexpr uint8_t QMI8658_REG_DVX_H = 0x52;
static constexpr uint8_t QMI8658_REG_DVY_L = 0x53;
static constexpr uint8_t QMI8658_REG_DVY_H = 0x54;
static constexpr uint8_t QMI8658_REG_DVZ_L = 0x55;
static constexpr uint8_t QMI8658_REG_DVZ_H = 0x56;
//* Activity Detection Output Registers
static constexpr uint8_t QMI8658_REG_TAP_STATUS = 0x59;
static constexpr uint8_t QMI8658_REG_STEP_CNT_LOW = 0x5A;
static constexpr uint8_t QMI8658_REG_STEP_CNT_MID = 0x5B;
static constexpr uint8_t QMI8658_REG_STEP_CNT_HIGH = 0x5C;
static constexpr uint8_t QMI8658_REG_RESET = 0x60;
//* Reset Register
static constexpr uint8_t QMI8658_REG_RST_RESULT = 0x4D;
static constexpr uint8_t QMI8658_REG_RST_RESULT_VAL = 0x80;
static constexpr uint8_t STATUS0_ACCEL_AVAIL = 0x01;
static constexpr uint8_t STATUS0_GYRO_AVAIL = 0x02;
static constexpr uint8_t QMI8658_ACCEL_LPF_MASK = 0xF9;
static constexpr uint8_t QMI8658_GYRO_LPF_MASK = 0x9F;
static constexpr uint8_t QMI8658_ACCEL_EN_MASK = 0x01;
static constexpr uint8_t QMI8658_GYRO_EN_MASK = 0x02;
static constexpr uint8_t QMI8658_ACCEL_GYRO_EN_MASK = 0x03;
static constexpr uint8_t QMI8658_FIFO_MAP_INT1 = 0x04; // ctrl1
};

View File

@@ -0,0 +1,58 @@
/**
*
* @license MIT License
*
* Copyright (c) 2025 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file XL9555Constants.h
* @author Lewis He (lewishe@outlook.com)
* @date 2025-01-17
*
*/
#pragma once
#include <stdint.h>
// A0, A1, A2 connect to GND
#define XL9555_UNKOWN_ADDRESS (0xFF)
#define XL9555_SLAVE_ADDRESS0 (0x20)
#define XL9555_SLAVE_ADDRESS1 (0x21)
#define XL9555_SLAVE_ADDRESS2 (0x22)
#define XL9555_SLAVE_ADDRESS3 (0x23)
#define XL9555_SLAVE_ADDRESS4 (0x24)
#define XL9555_SLAVE_ADDRESS5 (0x25)
#define XL9555_SLAVE_ADDRESS6 (0x26)
#define XL9555_SLAVE_ADDRESS7 (0x27)
class XL95xxConstants
{
protected:
static constexpr uint8_t XL9555_CTRL_INP0 = (0x00); // Input Port 0 /R
static constexpr uint8_t XL9555_CTRL_INP1 = (0x01); // Input Port 1 /R
static constexpr uint8_t XL9555_CTRL_OUTP0 = (0x02); // Output Port 0 /RW
static constexpr uint8_t XL9555_CTRL_OUTP1 = (0x03); // Output Port 1 /RW
static constexpr uint8_t XL9555_CTRL_PIP0 = (0x04); // Polarity Inversion Port 0 /RW
static constexpr uint8_t XL9555_CTRL_PIP1 = (0x05); // Polarity Inversion Port 1 /RW
static constexpr uint8_t XL9555_CTRL_CFG0 = (0x06); // Configuration Port 0 /RW
static constexpr uint8_t XL9555_CTRL_CFG1 = (0x07); // Configuration Port 1 /RW
static constexpr uint8_t XL9555_MAX_PIN = (15);
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,638 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file SensorBHI260AP.hpp
* @author Lewis He (lewishe@outlook.com)
* @date 2023-09-06
* @note Most source code references come from the https://github.com/boschsensortec/BHY2-Sensor-API
* Simplification for Arduino
*/
#pragma once
#include "bosch/BoschSensorControl.hpp"
#include "bosch/BoschPhySensorInfo.hpp"
#include "bosch/BoschSensorInfo.hpp"
#include "SensorPlatform.hpp"
#include "bosch/BoschSensorID.hpp"
#include "bosch/BoschParseBase.hpp"
#include "bosch/BoschParseCallbackManager.hpp"
#define BHI260AP_SLAVE_ADDRESS_L 0x28
#define BHI260AP_SLAVE_ADDRESS_H 0x29
using SensorConfig = struct bhy2_virt_sensor_conf;
using ProcessCallback = void (*)(void *user_data, uint32_t total, uint32_t transferred);
class SensorBHI260AP : public BoschVirtualSensor, BoschParseBase
{
public:
using SensorDebugMessageCallback = void (*)(const char *message);
using SensorEventCallback = void (*)(uint8_t event, uint8_t sensor_id, uint8_t data);
enum BoschOrientation {
DIRECTION_TOP_RIGHT,
DIRECTION_TOP_LEFT,
DIRECTION_BOTTOM_LEFT,
DIRECTION_BOTTOM_RIGHT,
};
enum SensorEvent {
EVENT_FLUSH_COMPLETE = 1,
EVENT_SAMPLE_RATE_CHANGED,
EVENT_POWER_MODE_CHANGED,
EVENT_ALGORITHM_EVENTS = 5,
EVENT_SENSOR_STATUS,
EVENT_BSX_DO_STEPS_MAIN,
EVENT_BSX_DO_STEPS_CALIB,
EVENT_BSX_GET_OUTPUT_SIGNAL,
EVENT_SENSOR_ERROR = 11,
EVENT_FIFO_OVERFLOW,
EVENT_DYNAMIC_RANGE_CHANGED,
EVENT_FIFO_WATERMARK,
EVENT_INITIALIZED = 16,
EVENT_TRANSFER_CAUSE,
EVENT_SENSOR_FRAMEWORK,
EVENT_RESET,
};
/**
* @enum SensorRemap
* @brief Enumeration representing different remapping options for the sensor's orientation.
*
* This enum defines various positions and orientations of the sensor chip. Each value corresponds
* to a specific corner or location of the chip, which can be used to remap the axes of the sensor
* according to its physical placement.
*
* Top view of the chip, where 'T' stands for top,
* 'B' stands for bottom,
* 'L' stands for left, and 'R' stands for right
* -------------
* | TL TR |
* | |
* | |
* | |
* | BL BR |
* -------------
*
* There is also a bottom view of the chip
*
* -------------
* | BT BB |
* | |
* | |
* | |
* | LT RT |
* -------------
*/
enum SensorRemap {
// Chip top view, upper left corner
// -------------
// | * |
// | |
// | |
// | |
// | |
// -------------
TOP_LAYER_LEFT_CORNER,
// Chip top view, upper right corner
// -------------
// | * |
// | |
// | |
// | |
// | |
// -------------
TOP_LAYER_RIGHT_CORNER,
// Chip top view, bottom right corner of the top
// -------------
// | |
// | |
// | |
// | |
// | * |
// -------------
TOP_LAYER_BOTTOM_RIGHT_CORNER,
// The top view of the chip, the lower left corner of the front bottom
// -------------
// | |
// | |
// | |
// | |
// | * |
// -------------
TOP_LAYER_BOTTOM_LEFT_CORNER,
// The bottom view of the chip, the upper left corner of the top
// -------------
// | * |
// | |
// | |
// | |
// | |
// -------------
BOTTOM_LAYER_TOP_LEFT_CORNER,
// The bottom view of the chip, the upper right corner of the top
// -------------
// | * |
// | |
// | |
// | |
// | |
// -------------
BOTTOM_LAYER_TOP_RIGHT_CORNER,
// The bottom view of the chip, the lower right corner of the bottom
// -------------
// | |
// | |
// | |
// | |
// | * |
// -------------
BOTTOM_LAYER_BOTTOM_RIGHT_CORNER,
// Chip bottom view, bottom left corner
// -------------
// | |
// | |
// | |
// | |
// | * |
// -------------
BOTTOM_LAYER_BOTTOM_LEFT_CORNER,
};
// The pin names are named according to the sensor manual.
enum BHI260AP_GPIO {
MCSB1 = 1,
RESV1 = 2,
RESV2 = 3,
MCSB2 = 4, //It may be connected to the BMM150 sensor, select according to the actual situation
MCSB3 = 5,
MCSB4 = 6,
QSPI_CLK = 8, // If BHI260 carries external flash, it is not available
QSPI_CSN = 9, // If BHI260 carries external flash, it is not available
QSPI_D0 = 10, // If BHI260 carries external flash, it is not available
QSPI_D1 = 11, // If BHI260 carries external flash, it is not available
QSPI_D2 = 12, // If BHI260 carries external flash, it is not available
QSPI_D3 = 13, // If BHI260 carries external flash, it is not available
M2SCX = 14,
M2SDX = 15,
M2SDI = 16,
M3SCL = 17, //It may be connected to the BMM150 sensor, select according to the actual situation
M3SDA = 18, //It may be connected to the BMM150 sensor, select according to the actual situation
JTAG_CLK = 19,
JTAG_DIO = 20,
M1SCX = 127, // Invalid Pin
M1SDX = 128, // Invalid Pin
M1SDI = 129, // Invalid Pin
RESV3 = 130, // Invalid Pin
};
~SensorBHI260AP();
SensorBHI260AP();
/**
* @brief setPins
* @note Set the reset pin. reset pin is not set by default.
* @param rst:
* @retval None
*/
void setPins(int rst);
#if defined(ARDUINO)
/**
* @brief begin
* @note Initialization using the Arduino Wire Interface
* @param &wire: TwoWire Class
* @param addr: Device address, default 0x28, can also be changed to 0x29
* @param sda: Set I2C SCL Pin, not set by default
* @param scl: Set I2C SDA Pin, not set by default
* @retval bool true-> Success false-> failure
*/
bool begin(TwoWire &wire, uint8_t addr = BHI260AP_SLAVE_ADDRESS_L, int sda = -1, int scl = -1);
/**
* @brief begin
* @note Initialization using the Arduino SPI Interface
* @param &spi: SPIClass
* @param csPin: Set CS SCL Pin, not set by default
* @param mosi: Set SPI MOSI SCL Pin, not set by default
* @param miso: Set SPI MISO SCL Pin, not set by default
* @param sck: Set SPI SCK SCL Pin, not set by default
* @retval bool true-> Success false-> failure
*/
bool begin(SPIClass &spi, uint8_t csPin, int mosi = -1, int miso = -1, int sck = -1);
#elif defined(ESP_PLATFORM)
#if defined(USEING_I2C_LEGACY)
/**
* @brief begin
* @note Initialization using the ESP-IDF I2C Legacy Interface
* @param port_num: I2C_NUM0 or I2C_NUM1
* @param addr: Device address, default 0x28, can also be changed to 0x29
* @param sda: Set I2C SCL Pin, not set by default
* @param scl: Set I2C SDA Pin, not set by default
* @retval bool true-> Success false-> failure
*/
bool begin(i2c_port_t port_num, uint8_t addr = BHI260AP_SLAVE_ADDRESS_L, int sda = -1, int scl = -1);
#else
/**
* @brief begin
* @note Initialization using the ESP-IDF I2C LL Interface idf version > 5.0.0
* @param handle: I2C Handle
* @param addr: Device address, default 0x28, can also be changed to 0x29
* @retval bool true-> Success false-> failure
*/
bool begin(i2c_master_bus_handle_t handle, uint8_t addr = BHI260AP_SLAVE_ADDRESS_L);
#endif //ESP_PLATFORM
/**
* @brief begin
* @note Initialization using the ESP-IDF SPI Interface
* @param host: spi_host_device_t enum
* @param handle: spi_device_handle_t handle
* @param csPin: cs pin
* @param mosi: spi mosi pin
* @param miso: spi miso pin
* @param sck: spi sck pin
* @retval bool true-> Success false-> failure
*/
bool begin(spi_host_device_t host, spi_device_handle_t handle, uint8_t csPin, int mosi, int miso, int sck);
#endif //ARDUINO
/**
* @brief begin
* @note Custom callback interface, suitable for other platforms
* @param interface: Communication mode, COMM_SPI or COMM_I2C
* @param callback: Register read and write callback function
* @param hal_callback: Platform digital IO and delay callback function
* @param addr: Device address, default 0x28, can also be changed to 0x29
* @retval bool true-> Success false-> failure
*/
bool begin(CommInterface interface, SensorCommCustom::CustomCallback callback,
SensorCommCustomHal::CustomHalCallback hal_callback,
uint8_t addr = BHI260AP_SLAVE_ADDRESS_L);
/**
* @brief reset
* @note Reset sensor
* @retval None
*/
void reset();
/**
* @brief update
* @note Update sensor fifo data
* @retval None
*/
void update();
/**
* @brief setBootFromFlash
* @note Set whether to start from external flash
* @param boot_from_flash: true boot form flash or boot form ram
* @retval None
*/
void setBootFromFlash(bool boot_from_flash);
/**
* @brief getHandler
* @note Get the native BHI API handle
* @retval handle
*/
bhy2_dev *getHandler();
/**
* @brief setInterruptCtrl
* @note Set the interrupt control mask
* @param data:
* BHY2_ICTL_DISABLE_FIFO_W
* BHY2_ICTL_DISABLE_FIFO_NW
* BHY2_ICTL_DISABLE_STATUS_FIFO
* BHY2_ICTL_DISABLE_DEBUG
* BHY2_ICTL_DISABLE_FAULT
* BHY2_ICTL_ACTIVE_LOW
* BHY2_ICTL_EDGE
* BHY2_ICTL_OPEN_DRAIN
*
* @retval true is success , false is failed
*/
bool setInterruptCtrl(uint8_t data);
/**
* @brief getInterruptCtrl
* @note Get interrupt control info
* @retval SensorBHI260APControl class
*/
SensorBHI260APControl getInterruptCtrl();
/**
* @brief isReady
* @note Query whether the sensor is ready
* @retval true OK , false Not ready
*/
bool isReady();
/**
* @brief getKernelVersion
* @note Get the sensor firmware kernel version
* @retval 2 bytes
*/
uint16_t getKernelVersion();
/**
* @brief onEvent
* @note Registered sensor event callback function
* @param callback: Callback Function
* @retval None
*/
void onEvent(SensorEventCallback callback);
/**
* @brief removeEvent
* @note Remove sensor event callback function
* @retval None
*/
void removeEvent();
/**
* @brief onResultEvent
* @note Registered sensor result callback function , The same sensor ID can register multiple event callbacks.
* Please note that you should not register the same event callback repeatedly.
* @param sensor_id: Sensor ID , see enum BoschSensorID
* @param callback: Callback Function
* @param *user_data: user data,can be null
* @retval bool true-> Success false-> failure
*/
bool onResultEvent(BoschSensorID sensor_id, SensorDataParseCallback callback, void *user_data = nullptr);
/**
* @brief removeResultEvent
* @note Remove the registered result callback function
* @param sensor_id: Sensor ID , see enum BoschSensorID
* @param callback: Callback Function
* @retval bool true-> Success false-> failure
*/
bool removeResultEvent(BoschSensorID sensor_id, SensorDataParseCallback callback);
/**
* @brief setProcessBufferSize
* @note The default value is 512Bytes , Must be called before initialization
* @param size: The set buffer size is requested by malloc, and if PSRAM is enabled, it is requested from PSRAM
* @retval None
*/
void setProcessBufferSize(uint32_t size);
/**
* @brief uploadFirmware
* @note Update BHI sensor firmware
* @param *firmware: Firmware data address
* @param length: Firmware data length
* @param write2Flash: 1 is written to external flash, 0 is written to RAM
* @retval bool true-> Success false-> failure
*/
bool uploadFirmware(const uint8_t *firmware, uint32_t length, bool write2Flash = false);
/**
* @brief getError
* @note Get the error status string
* @retval string
*/
const char *getError();
/**
* @brief configure
* @note Sensor Configuration
* @param sensor_id: Sensor ID , see enum BoschSensorID
* @param sample_rate: Data output rate, unit: HZ
* @param report_latency_ms: Report interval in milliseconds
* @return bool true-> Success false-> failure
*/
bool configure(uint8_t sensor_id, float sample_rate, uint32_t report_latency_ms);
/**
* @brief configureRange
* @note Set range of the sensor
* @param sensor_id: Sensor ID , see enum BoschSensorID
* @param range: Range for selected SensorID. See Table 79 in BHY260 datasheet 109 page
* @retval bool true-> Success false-> failure
*/
bool configureRange(uint8_t sensor_id, uint16_t range);
/**
* @brief getConfigure
* @note Get sensor configuration
* @param sensor_id: Sensor ID , see enum BoschSensorID
* @retval SensorConfig
*/
SensorConfig getConfigure(uint8_t sensor_id);
/**
* @brief getScaling
* @note Get sensor scale factor
* @param sensor_id: Sensor ID , see enum BoschSensorID
* @retval scale factor
*/
float getScaling(uint8_t sensor_id);
/**
* @brief setFirmware
* @note Set the firmware
* @param *image: firmware data address
* @param image_len: firmware length
* @param write_flash: true : write to flash otherwise ram
* @param force_update: true, rewrite to flash or ram regardless of whether there is firmware, false, do not write if firmware is detected
* @retval None
*/
void setFirmware(const uint8_t *image, size_t image_len, bool write_flash = false, bool force_update = false);
/**
* @brief getSensorName
* @note Get sensor name
* @param sensor_id: Sensor ID , see enum BoschSensorID
* @retval sensor name
*/
const char *getSensorName(uint8_t sensor_id);
/**
* @brief getAccuracy
* @note Get an accuracy report
* @retval Current report accuracy
*/
uint8_t getAccuracy();
/**
* @brief digitalRead
* @note Read GPIO level, only for custom firmware
* @param pin: see BHI260AP_aux_BMM150_BME280_Expand_GPIO example
* @param pullup: true is set pullup or input mode
* @retval 1 is high ,0 is low
*/
uint8_t digitalRead(uint8_t pin, bool pullup = false);
/**
* @brief digitalWrite
* @note Write GPIO level, only for custom firmware
* @param pin: see BHI260AP_aux_BMM150_BME280_Expand_GPIO example
* @param level: 1 is high ,0 is low
* @retval None
*/
void digitalWrite(uint8_t pin, uint8_t level);
/**
* @brief disableGpio
* @note Disable GPIO function
* @param pin: see BHI260AP_aux_BMM150_BME280_Expand_GPIO example
* @retval None
*/
void disableGpio(uint8_t pin);
/**
* @brief setDebug
* @note Whether to enable chip debug output
* @param enable: true Enable message debug , false disable debug , Requires firmware support, the default firmware will not output any messages
* @param &serial: Stream
* @retval None
*/
void setDebugKernel(bool enable);
/**
* @brief setDebugCallback
* @param cb: Sensor debug output callback function , Requires firmware support, the default firmware will not output any messages
* @retval None
*/
void setDebugCallback(SensorDebugMessageCallback cb);
/**
* @brief getPhySensorInfo
* @note Get all information about physical sensors
* @param sens_id: ID of the physical sensor
* @retval BoschPhySensorInfo Class
*/
BoschPhySensorInfo getPhySensorInfo(uint8_t sens_id);
/**
* @brief getSensorInfo
* @note Get all information about sensors
* @retval BoschSensorInfo Class
*/
BoschSensorInfo getSensorInfo();
/**
* @brief setMaxiTransferSize
* @note Set the maximum number of bytes transmitted by the interface , Called before begin
* @param size_of_bytes: The maximum transmission bytes of different platforms are different.
* Set it according to the platform. If not set, the default is I2C 32 bytes, SPI 256 bytes.
* @retval None
*/
void setMaxiTransferSize(uint16_t size_of_bytes);
/**
* @brief setUpdateProcessCallback
* @note Set the callback function of the firmware update process to obtain the update progress
* @param callback: callback function
* @param *user_data: user data, can be nullptr
* @retval None
*/
void setUpdateProcessCallback(ProcessCallback callback, void *user_data = nullptr);
/**
* @brief availableSensorNums
* @note Get the number of available sensors
* @retval available sensors
*/
uint8_t availableSensorNums();
/**
* @brief Set the axis remapping for the sensor based on the specified orientation.
*
* This function allows you to configure the sensor's axis remapping according to a specific
* physical orientation of the chip. By passing one of the values from the SensorRemap enum,
* you can ensure that the sensor data is correctly interpreted based on how the chip is placed.
* [bst-bhi260ab-ds000.pdf](https://www.mouser.com/datasheet/2/783/bst-bhi260ab-ds000-1816249.pdf)
* 20.3 Sensing axes and axes remapping
* @param remap An enumeration value from SensorRemap that specifies the desired axis remapping.
* @return Returns true if the axis remapping is successfully set; false otherwise.
*/
bool setRemapAxes(SensorRemap remap);
protected:
void parseData(const struct bhy2_fifo_parse_data_info *fifo, void *user_data) override;
void parseMetaEvent(const struct bhy2_fifo_parse_data_info *callback_info, void *user_data) override;
void parseDebugMessage(const struct bhy2_fifo_parse_data_info *callback_info, void *user_data) override;
private:
/**
* @brief bootFromFlash
* @note Boot from external flash
* @retval bool true-> Success false-> failure
*/
bool bootFromFlash();
void print_boot_status(uint8_t boot_status);
bool initImpl(bhy2_intf interface);
protected:
std::unique_ptr<SensorCommBase> comm;
std::unique_ptr<SensorHal> hal;
std::unique_ptr<SensorCommStatic> staticComm;
std::unique_ptr<struct bhy2_dev> _bhy2;
int _rst;
int8_t _error_code;
uint8_t *_processBuffer;
size_t _processBufferSize;
const uint8_t *_firmware_stream;
size_t _firmware_size;
bool _write_flash;
bool _boot_from_flash;
bool _force_update;
int _max_rw_length;
uint8_t _accuracy; /* Accuracy is reported as a meta event. */
bool _debug;
ProcessCallback _process_callback;
void *_process_callback_user_data;
SensorEventCallback _event_callback;
SensorDebugMessageCallback _debug_callback;
BoschParseCallbackManager _callback_manager;
uint8_t _sensor_available_nums;
char _err_buffer[128];
};

View File

@@ -0,0 +1,388 @@
/**
*
* @license MIT License
*
* Copyright (c) 2025 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file SensorBHI260AP_Klio.cpp
* @author Lewis He (lewishe@outlook.com)
* @date 2025-02-01
* @note Most source code references come from the https://github.com/boschsensortec/BHY2-Sensor-API
* Simplification for Arduino
*/
#include "SensorBHI260AP_Klio.hpp"
const char *SensorBHI260AP_Klio::errorMessages[9] = {
"",
"Invalid parameter",
"Parameter out of range",
"Invalid pattern operation",
"Not implemented",
"Buffer size",
"Internal",
"Undefined",
"Operation pending"
};
SensorBHI260AP_Klio::SensorBHI260AP_Klio(SensorBHI260AP &sensor) :
sensor(&sensor),
max_patterns(0),
max_pattern_size(0),
similarity_result_buf(nullptr),
similarity_idx_buf(nullptr),
learning_callback(nullptr),
learning_callback_user_data(nullptr),
recognition_callback(nullptr),
recognition_callback_user_data(nullptr),
errorCode(KLIO_DRIVER_ERROR_NONE),
k_state({0, 0, 0, 0}) {}
SensorBHI260AP_Klio::~SensorBHI260AP_Klio()
{
end();
}
void SensorBHI260AP_Klio::end()
{
if (sensor) {
sensor->configure(SensorBHI260AP::KLIO, 0, 0);
sensor->removeResultEvent(SensorBHI260AP::KLIO, static_klio_callback);
sensor->configure(SensorBHI260AP::KLIO_LOG, 0, 0);
sensor->removeResultEvent(SensorBHI260AP::KLIO_LOG, static_klio_log_callback);
}
if (similarity_result_buf ) {
free(similarity_result_buf);
similarity_result_buf = nullptr;
}
if (similarity_idx_buf ) {
free(similarity_idx_buf);
similarity_idx_buf = nullptr;
}
}
bool SensorBHI260AP_Klio::begin()
{
if (similarity_result_buf && similarity_idx_buf && sensor) {
return true;
}
if (!sensor) {
log_e("BHI260 data pointer is empty");
return false;
}
const uint8_t PARAM_BUF_LEN = 252;
uint8_t param_buf[PARAM_BUF_LEN];
uint16_t size = sizeof(param_buf);
int major = -1;
int minor = -1;
int version = -1;
int count = 0;
if (!getParameter(KLIO_PARAM_ALGORITHM_VERSION, param_buf, &size)) {
log_e("Unable to get Klio firmware version.");
return false;
}
if (size > 0) {
count = sscanf((char *)param_buf, "%d.%d.%d", &major, &minor, &version);
}
if (major < 0 || minor < 0 || version < 0 || count != 3) {
log_e("Unable to get Klio firmware version.");
return false;
}
log_d("Klio version %d.%d.%d - buf:%s", major, minor, version, param_buf);
/* Get number of supported patterns */
uint16_t length = sizeof(param_buf);
if (!getParameter(KLIO_PARAM_RECOGNITION_MAX_PATTERNS, param_buf, &length)) {
return false;
}
max_patterns = *((uint16_t *) param_buf);
similarity_result_buf = (float *)malloc(sizeof(float) * max_patterns);
if (!similarity_result_buf) {
log_e("Klio result buffer allocate failed!");
return false;
}
similarity_idx_buf = (uint8_t *)malloc(sizeof(uint8_t) * max_patterns);
if (!similarity_idx_buf) {
log_e("Klio index buffer allocate failed!");
free(similarity_result_buf);
return false;
}
log_d("Klio process allocate successfully!");
/* Get maximum supported pattern size */
length = sizeof(param_buf);
if (!getParameter(KLIO_PARAM_PATTERN_BLOB_SIZE, param_buf, &length)) {
free(similarity_idx_buf);
free(similarity_result_buf);
return false;
}
max_pattern_size = *((uint16_t *) param_buf);
log_d("Klio Max patterns :%u", max_patterns);
log_d("Klio Max pattern len:%u", max_pattern_size);
uint8_t ignore_insignificant_movement = 1;
/* Prevent learning with small movements, parameter writes should be done after reset and before sensor enable */
setParameter(KLIO_PARAM_LEARNING_IGNORE_INSIG_MOVEMENT, &ignore_insignificant_movement,
sizeof(ignore_insignificant_movement));
sensor->onResultEvent(SensorBHI260AP::KLIO_LOG, static_klio_log_callback, this);
return sensor->onResultEvent(SensorBHI260AP::KLIO, static_klio_callback, this);
}
bool SensorBHI260AP_Klio::setState(bool learning_enable, bool learning_reset, bool recognition_enable, bool recognition_reset)
{
bhy2_klio_sensor_state_t sensor_state = {
.learning_enabled = learning_enable,
.learning_reset = learning_reset,
.recognition_enabled = recognition_enable,
.recognition_reset = recognition_reset
};
return KlioTemplate(bhy2_klio_set_state, &sensor_state);
}
SensorBHI260AP_Klio::KlioState SensorBHI260AP_Klio::getState()
{
assert(sensor);
bhy2_klio_sensor_state_t sensor_state;
bhy2_klio_get_state(&sensor_state, sensor->getHandler());
return sensor_state;
}
bool SensorBHI260AP_Klio::setState(KlioState sensor_state)
{
if (!sensor) {
log_e("BHI260 data pointer is empty");
return false;
}
return bhy2_klio_set_state(&sensor_state, sensor->getHandler()) == BHY2_OK;
}
bool SensorBHI260AP_Klio::learning()
{
k_state = getState();
k_state.learning_enabled = true;
return setState(k_state);
}
bool SensorBHI260AP_Klio::recognition(const uint8_t *pattern_ids, size_t size)
{
if (!KlioTemplate(bhy2_klio_set_pattern_states, KLIO_PATTERN_STATE_ENABLE, pattern_ids, size)) {
log_e("Klio set pattern idx failed!");
return false;
}
k_state = getState();
k_state.learning_enabled = false;
k_state.recognition_enabled = true;
return setState(k_state);
}
bool SensorBHI260AP_Klio::getLearnPattern(uint8_t *pattern, uint16_t *size)
{
return KlioTemplate(bhy2_klio_read_pattern, 0, pattern, size);
}
uint8_t SensorBHI260AP_Klio::getMaxPatterns()
{
return max_patterns;
}
void SensorBHI260AP_Klio::static_klio_callback(uint8_t sensor_id, uint8_t *data, uint32_t size, uint64_t *timestamp, void *user_data)
{
SensorBHI260AP_Klio *self = static_cast<SensorBHI260AP_Klio *>(user_data);
self->klio_call_local(sensor_id, data, size, timestamp, self);
}
void SensorBHI260AP_Klio::klio_call_local(uint8_t sensor_id, uint8_t *data_ptr, uint32_t size, uint64_t *timestamp, void *user_data)
{
bhy2_klio_sensor_frame_t data;
if (size != 11) {
return;
}
memcpy(&data, data_ptr, sizeof(data));
if (learning_callback) {
if (k_state.learning_enabled) {
learning_callback(static_cast<LeaningChangeReason>(data.learn.change_reason),
data.learn.progress, data.learn.index, learning_callback_user_data);
}
}
if (recognition_callback && data.recognize.index != 0xFF) {
if (k_state.recognition_enabled) {
recognition_callback(data.recognize.index, data.recognize.count, recognition_callback_user_data);
}
}
}
void SensorBHI260AP_Klio::static_klio_log_callback(uint8_t sensor_id, uint8_t *data, uint32_t size, uint64_t *timestamp, void *user_data)
{
SensorBHI260AP_Klio *self = static_cast<SensorBHI260AP_Klio *>(user_data);
self->klio_log_call_local(sensor_id, data, size, timestamp, self);
}
void SensorBHI260AP_Klio::klio_log_call_local(uint8_t sensor_id, uint8_t *data_ptr, uint32_t size, uint64_t *timestamp, void *user_data)
{
bhy2_klio_log_frame_t data;
memcpy(&data, data_ptr, sizeof(data));
log_d("ax: %.9g, ay: %.9g, az: %.9g, gx: %.9g, gy: %.9g, gz: %.9g\n",
data.accel[0],
data.accel[1],
data.accel[2],
data.gyro[0],
data.gyro[1],
data.gyro[2]);
}
bool SensorBHI260AP_Klio::getParameter(KlioParameter id, uint8_t *parameter_data, uint16_t *size)
{
return KlioTemplate(bhy2_klio_get_parameter, id, parameter_data, size);
}
bool SensorBHI260AP_Klio::setParameter(KlioParameter id, const void *parameter_data, uint16_t size)
{
return KlioTemplate(bhy2_klio_set_parameter, id, parameter_data, size);
}
bool SensorBHI260AP_Klio::writePattern(uint8_t idx, const uint8_t *parameter_data, uint16_t size)
{
return KlioTemplate(bhy2_klio_write_pattern, idx, parameter_data, size);
}
bool SensorBHI260AP_Klio::writeMultiplePatterns(const uint8_t *ids, const uint8_t **parameter_data_array, const uint16_t *sizes, uint8_t count)
{
for (uint8_t i = 0; i < count; ++i) {
if (!KlioTemplate(bhy2_klio_write_pattern, ids[i], parameter_data_array[i], sizes[i])) {
log_d("Write pattern with ID :%u failed", ids[i]);
return false;
}
}
return true;
}
bool SensorBHI260AP_Klio::setPattern(KlioPatternState operation, const uint8_t *pattern_ids, uint16_t size)
{
return KlioTemplate(bhy2_klio_set_pattern_states, static_cast<bhy2_klio_pattern_state_t>(operation), pattern_ids, size);
}
bool SensorBHI260AP_Klio::enablePattern(const uint8_t *pattern_ids, uint16_t size)
{
return KlioTemplate(bhy2_klio_set_pattern_states, KLIO_PATTERN_STATE_ENABLE, pattern_ids, size);
}
bool SensorBHI260AP_Klio::readPattern(uint8_t idx, uint8_t *buffer, uint16_t *length)
{
return KlioTemplate(bhy2_klio_read_pattern, idx, buffer, length);
}
bool SensorBHI260AP_Klio::enable(float sample_rate, uint32_t report_latency_ms)
{
if (!sensor) {
log_e("BHI260 data pointer is empty");
return false;
}
return sensor->configure(SensorBHI260AP::KLIO, sample_rate, report_latency_ms);
}
void SensorBHI260AP_Klio::disable()
{
if (!sensor) {
log_e("BHI260 data pointer is empty");
return;
}
sensor->configure(SensorBHI260AP::KLIO, 0, 0);
}
bool SensorBHI260AP_Klio::logout(float sample_rate, uint32_t report_latency_ms)
{
if (!sensor) {
log_e("BHI260 data pointer is empty");
return false;
}
return sensor->configure(SensorBHI260AP::KLIO_LOG, sample_rate, report_latency_ms);
}
void SensorBHI260AP_Klio::setLearningCallback(LearningCallback cb, void *user_data)
{
learning_callback = cb;
learning_callback_user_data = user_data;
}
void SensorBHI260AP_Klio::setRecognitionCallback(RecognitionCallback cb, void *user_data)
{
recognition_callback = cb;
recognition_callback_user_data = user_data;
}
bool SensorBHI260AP_Klio::checkError()
{
if (!sensor) {
log_e("BHI260 data pointer is empty");
return false;
}
uint32_t klio_status;
int8_t rslt = bhy2_klio_read_reset_driver_status(&klio_status, sensor->getHandler());
if (rslt != BHY2_OK) {
errorCode = static_cast<KlioError>(klio_status);
return true;
}
errorCode = static_cast<KlioError>(klio_status);
return errorCode != KLIO_DRIVER_ERROR_NONE;
}
SensorBHI260AP_Klio::KlioError SensorBHI260AP_Klio::getError() const
{
return errorCode;
}
const char *SensorBHI260AP_Klio::errorToString() const
{
if (errorCode <= 8) {
return errorMessages[errorCode];
}
return "Unknown error code";
}
template<typename Func, typename... Args>
bool SensorBHI260AP_Klio::KlioTemplate(Func func, Args &&... args)
{
if (!sensor) {
log_e("BHI260 data pointer is empty");
return false;
}
int8_t rslt = func(std::forward<Args>(args)..., sensor->getHandler());
if (rslt != BHY2_OK) {
log_e("Interface access error, %s", get_api_error(rslt));
return false;
}
if (checkError()) {
log_e("%s", errorToString());
return false;
}
return true;
}

View File

@@ -0,0 +1,354 @@
/**
*
* @license MIT License
*
* Copyright (c) 2025 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file SensorBHI260AP_Klio.hpp
* @author Lewis He (lewishe@outlook.com)
* @date 2025-02-01
* @note Most source code references come from the https://github.com/boschsensortec/BHY2-Sensor-API
* Simplification for Arduino
*/
#pragma once
#include "SensorBHI260AP.hpp"
class SensorBHI260AP_Klio
{
public:
static constexpr int8_t INVALID_LEARNING_INDEX = -1;
enum LeaningChangeReason {
LEARNING_PROGRESSING, //Learning is progressing.
LEARNING_NO_REPETITIVE_ACTIVITY, //Learning was interrupted by a non-repetitive activity.
LEARNING_NO_SIGNIFICANT, //Learning was interrupted because no significant movement was detected.
};
enum KlioPatternState {
PATTERN_STATE_DISABLE = 0, //Disable pattern
PATTERN_STATE_ENABLE, //Enable pattern
PATTERN_STATE_SWITCH_HAND, //Switch hand
PATTERN_STATE_AP_DISABLE //Disable adaptive pattern
};
using KlioParameter = bhy2_klio_parameter_t;
using KlioError = bhy2_klio_driver_error_state_t;
using KlioState = bhy2_klio_sensor_state_t;
using RecognitionCallback = void (*)(uint8_t pattern_id, float count, void *user_data);
using LearningCallback = void (*)(LeaningChangeReason reason, uint32_t progress, int learn_index, void *user_data);
/**
* @brief Constructor to initialize the SensorBHI260AP_Klio object.
*
* @param sensor A reference to the SensorBHI260AP object, used for communication with the BHI260AP sensor.
*/
SensorBHI260AP_Klio(SensorBHI260AP &sensor);
/**
* @brief Destructor to release resources occupied by the SensorBHI260AP_Klio object.
*/
~SensorBHI260AP_Klio();
/**
* @brief End the interaction with the KLIO functionality of the BHI260AP sensor and release related resources.
*/
void end();
/**
* @brief Initialize the interaction with the KLIO functionality of the BHI260AP sensor.
*
* @return Returns true if the initialization is successful, otherwise false.
*/
bool begin();
/**
* @brief Set the learning and recognition states of the KLIO sensor.
*
* @param learning_enable Whether to enable the learning function. true for enable, false for disable.
* @param learning_reset Whether to reset the learning state. true for reset, false for not reset.
* @param recognition_enable Whether to enable the recognition function. true for enable, false for disable.
* @param recognition_reset Whether to reset the recognition state. true for reset, false for not reset.
* @return Returns true if the setting is successful, otherwise false.
*/
bool setState(bool learning_enable, bool learning_reset, bool recognition_enable, bool recognition_reset);
/**
* @brief Get the current state of the KLIO sensor.
*
* @return Returns a KlioState object containing the current learning and recognition state information.
*/
KlioState getState();
/**
* @brief Set the state of the KLIO sensor using a KlioState object.
*
* @param sensor_state A KlioState object containing learning and recognition state information.
* @return Returns true if the setting is successful, otherwise false.
*/
bool setState(KlioState sensor_state);
/**
* @brief Start the learning function of the KLIO sensor.
*
* @return Returns true if the learning function is started successfully, otherwise false.
*/
bool learning();
/**
* @brief Start the recognition function of the KLIO sensor for the specified pattern IDs.
*
* @param pattern_ids An array containing the pattern IDs to be recognized.
* @param size The number of elements in the pattern_ids array.
* @return Returns true if the recognition function is started successfully, otherwise false.
*/
bool recognition(const uint8_t *pattern_ids, size_t size);
/**
* @brief Retrieve the learned pattern from the sensor.
*
* This function attempts to obtain the learned pattern data from the sensor.
* It populates the provided buffer with the pattern data and sets the size
* parameter to indicate the actual size of the retrieved pattern.
*
* @param pattern A pointer to a buffer where the learned pattern data will be stored.
* The buffer should be large enough to hold the entire pattern.
* @param size A pointer to a variable of type uint16_t.
* On input, it can be used to specify the maximum capacity of the pattern buffer.
* On output, it will be updated to contain the actual size of the retrieved pattern.
*
* @return Returns true if the learned pattern is successfully retrieved and stored in the provided buffer.
* Returns false if there is an error during the retrieval process, such as an invalid buffer,
* insufficient buffer size, or a problem communicating with the sensor.
*/
bool getLearnPattern(uint8_t *pattern, uint16_t *size);
/**
* @brief Retrieve the maximum number of recognition patterns allowed.
*
* This function is used to obtain the maximum number of recognition patterns
* that the system or device can support. It provides an important parameter
* for operations related to pattern recognition, such as determining how many
* different patterns can be learned and stored for subsequent recognition tasks.
*
* @return The maximum number of recognition patterns allowed, represented as an 8 - bit unsigned integer.
*/
uint8_t getMaxPatterns();
/**
* @brief Get a parameter from the KLIO sensor.
*
* @param id The ID of the parameter to be retrieved.
* @param parameter_data A pointer to the buffer where the parameter data will be stored.
* @param size A pointer to the variable that stores the size of the parameter data.
* On input, it should be the size of the buffer. On output, it will be the actual size of the retrieved data.
* @return Returns true if the parameter is retrieved successfully, otherwise false.
*/
bool getParameter(KlioParameter id, uint8_t *parameter_data, uint16_t *size);
/**
* @brief Set a parameter of the KLIO sensor.
*
* @param id The ID of the parameter to be set.
* @param parameter_data A pointer to the data to be set as the parameter.
* @param size The size of the parameter data.
* @return Returns true if the parameter is set successfully, otherwise false.
*/
bool setParameter(KlioParameter id, const void *parameter_data, uint16_t size);
/**
* @brief Write a pattern to the KLIO sensor.
*
* @param idx The index of the pattern to be written.
* @param parameter_data A pointer to the pattern data.
* @param size The size of the pattern data.
* @return Returns true if the pattern is written successfully, otherwise false.
*/
bool writePattern(uint8_t idx, const uint8_t *parameter_data, uint16_t size);
/**
* @brief Write multiple patterns to the KLIO sensor.
*
* @param ids An array containing the indices of the patterns to be written.
* @param parameter_data_array An array of pointers to the pattern data arrays.
* @param sizes An array containing the sizes of the pattern data arrays.
* @param count The number of patterns to be written.
* @return Returns true if all patterns are written successfully, otherwise false.
*/
bool writeMultiplePatterns(const uint8_t *ids, const uint8_t **parameter_data_array, const uint16_t *sizes, uint8_t count);
/**
* @brief Set the state of patterns in the KLIO sensor.
*
* @param operation The operation to be performed on the patterns (e.g., enable, disable).
* @param pattern_ids An array containing the IDs of the patterns to be operated on.
* @param size The number of elements in the pattern_ids array.
* @return Returns true if the pattern state is set successfully, otherwise false.
*/
bool setPattern(KlioPatternState operation, const uint8_t *pattern_ids, uint16_t size);
/**
* @brief Enable specified patterns in the KLIO sensor.
*
* @param pattern_ids An array containing the IDs of the patterns to be enabled.
* @param size The number of elements in the pattern_ids array.
* @return Returns true if the patterns are enabled successfully, otherwise false.
*/
bool enablePattern(const uint8_t *pattern_ids, uint16_t size);
/**
* @brief Read a pattern from the KLIO sensor.
*
* @param idx The index of the pattern to be read.
* @param buffer A pointer to the buffer where the pattern data will be stored.
* @param length A pointer to the variable that stores the size of the buffer.
* On input, it should be the size of the buffer. On output, it will be the actual size of the read data.
* @return Returns true if the pattern is read successfully, otherwise false.
*/
bool readPattern(uint8_t idx, uint8_t *buffer, uint16_t *length);
/**
* @brief Enable the KLIO sensor with specified sample rate and report latency.
*
* @param sample_rate The sample rate of the sensor.
* @param report_latency_ms The report latency in milliseconds.
* @return Returns true if the sensor is enabled successfully, otherwise false.
*/
bool enable(float sample_rate, uint32_t report_latency_ms);
/**
* @brief Disable the KLIO sensor.
*/
void disable();
/**
* @brief Log out the KLIO sensor with specified sample rate and report latency.
*
* @param sample_rate The sample rate of the sensor.
* @param report_latency_ms The report latency in milliseconds.
* @return Returns true if the logout operation is successful, otherwise false.
*/
bool logout(float sample_rate, uint32_t report_latency_ms);
/**
* @brief Set the callback function for the learning event.
*
* @param cb A pointer to the callback function to be set.
* @param user_data A pointer to user - defined data to be passed to the callback function.
*/
void setLearningCallback(LearningCallback cb, void *user_data);
/**
* @brief Set the callback function for the recognition event.
*
* @param cb A pointer to the callback function to be set.
* @param user_data A pointer to user - defined data to be passed to the callback function.
*/
void setRecognitionCallback(RecognitionCallback cb, void *user_data);
/**
* @brief Check if there is an error in the KLIO sensor.
*
* @return Returns true if an error is detected, otherwise false.
*/
bool checkError();
/**
* @brief Get the error information of the KLIO sensor.
*
* @return Returns a KlioError object containing the error information.
*/
KlioError getError() const;
/**
* @brief Convert the error information to a string.
*
* @return Returns a const char* pointer to the error information string.
*/
const char *errorToString() const;
private:
/**
* @brief Static KLIO callback function to handle sensor data.
* This function calls the corresponding non - static member function klio_call_local for actual processing.
*
* @param sensor_id The sensor ID.
* @param data The sensor data array.
* @param size The size of the sensor data.
* @param timestamp The timestamp of the data.
* @param user_data A pointer to user - defined data.
*/
static void static_klio_callback(uint8_t sensor_id, uint8_t *data, uint32_t size, uint64_t *timestamp, void *user_data);
/**
* @brief Local KLIO callback function to actually handle sensor data.
*
* @param sensor_id The sensor ID.
* @param data_ptr A pointer to the sensor data array.
* @param size The size of the sensor data.
* @param timestamp The timestamp of the data.
* @param user_data A pointer to user - defined data.
*/
void klio_call_local(uint8_t sensor_id, uint8_t *data_ptr, uint32_t size, uint64_t *timestamp, void *user_data);
/**
* @brief Static KLIO log callback function to handle sensor log data.
* This function calls the corresponding non - static member function klio_log_call_local for actual processing.
*
* @param sensor_id The sensor ID.
* @param data The sensor log data array.
* @param size The size of the sensor log data.
* @param timestamp The timestamp of the log data.
* @param user_data A pointer to user - defined data.
*/
static void static_klio_log_callback(uint8_t sensor_id, uint8_t *data, uint32_t size, uint64_t *timestamp, void *user_data);
/**
* @brief Local KLIO log callback function to actually handle sensor log data.
*
* @param sensor_id The sensor ID.
* @param data_ptr A pointer to the sensor log data array.
* @param size The size of the sensor log data.
* @param timestamp The timestamp of the log data.
* @param user_data A pointer to user - defined data.
*/
void klio_log_call_local(uint8_t sensor_id, uint8_t *data_ptr, uint32_t size, uint64_t *timestamp, void *user_data);
template<typename Func, typename... Args>
bool KlioTemplate(Func func, Args &&... args);
private:
SensorBHI260AP *sensor;
uint16_t max_patterns;
uint16_t max_pattern_size;
float *similarity_result_buf;
uint8_t *similarity_idx_buf;
LearningCallback learning_callback;
void *learning_callback_user_data;
RecognitionCallback recognition_callback;
void *recognition_callback_user_data;
KlioError errorCode;
KlioState k_state;
static const char *errorMessages[9];
};

View File

@@ -0,0 +1,730 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file SensorBMA423.cpp
* @author Lewis He (lewishe@outlook.com)
* @date 2022-03-31
* @note Most source code references come from the https://github.com/boschsensortec/BMA423-Sensor-API
* Simplification for Arduino
*/
#include "SensorBMA423.hpp"
#include "REG/BMA423Config.h"
SensorBMA423::SensorBMA423() : comm(nullptr) {}
SensorBMA423::~SensorBMA423()
{
if (comm) {
comm->deinit();
}
}
#if defined(ARDUINO)
bool SensorBMA423::begin(TwoWire &wire, uint8_t addr, int sda, int scl)
{
if (!beginCommon<SensorCommI2C, HalArduino>(comm, hal, wire, addr, sda, scl)) {
return false;
}
return initImpl();
}
#elif defined(ESP_PLATFORM)
#if defined(USEING_I2C_LEGACY)
bool SensorBMA423::begin(i2c_port_t port_num, uint8_t addr, int sda, int scl)
{
if (!beginCommon<SensorCommI2C, HalEspIDF>(comm, hal, port_num, addr, sda, scl)) {
return false;
}
return initImpl();
}
#else /*USEING_I2C_LEGACY*/
bool SensorBMA423::begin(i2c_master_bus_handle_t handle, uint8_t addr)
{
if (!beginCommon<SensorCommI2C, HalEspIDF>(comm, hal, handle, addr)) {
return false;
}
return initImpl();
}
#endif //ESP_PLATFORM
#endif //ARDUINO
bool SensorBMA423::begin(SensorCommCustom::CustomCallback callback,
SensorCommCustomHal::CustomHalCallback hal_callback,
uint8_t addr)
{
if (!beginCommCustomCallback<SensorCommCustom, SensorCommCustomHal>(COMM_CUSTOM,
callback, hal_callback, addr, comm, hal)) {
return false;
}
return initImpl();
}
void SensorBMA423::reset()
{
comm->writeRegister(RESET_REG, 0xB6);
hal->delay(20);
}
bool SensorBMA423::enablePowerSave()
{
uint8_t val;
val = comm->readRegister(POWER_CONF_ADDR);
val |= ADVANCE_POWER_SAVE_MSK;
comm->writeRegister(POWER_CONF_ADDR, val);
return true;
}
bool SensorBMA423::disablePowerSave()
{
uint8_t val;
val = comm->readRegister(POWER_CONF_ADDR);
val &= ~(ADVANCE_POWER_SAVE_MSK);
comm->writeRegister(POWER_CONF_ADDR, val);
return true;
}
void SensorBMA423::disableInterruptCtrl()
{
comm->writeRegister(INIT_CTRL_ADDR, (uint8_t)0x00);
}
void SensorBMA423::enableInterruptCtrl()
{
comm->writeRegister(INIT_CTRL_ADDR, (uint8_t)0x01);
}
bool SensorBMA423::enableAccelerometer()
{
uint8_t val;
val = comm->readRegister(POWER_CTRL_ADDR);
val |= ACCEL_ENABLE_MSK;
comm->writeRegister(POWER_CTRL_ADDR, val);
return true;
}
bool SensorBMA423::disableAccelerometer()
{
uint8_t val;
val = comm->readRegister( POWER_CTRL_ADDR);
val &= (~ACCEL_ENABLE_MSK);
comm->writeRegister(POWER_CTRL_ADDR, val);
return true;
}
bool SensorBMA423::configAccelerometer(AccelRange range, AccelODR odr,
BandWidth bw,
PerformanceMode perfMode )
{
uint8_t buffer[2] = {0, 0};
if (perfMode == PERF_CONTINUOUS_MODE) {
if (bw > BW_NORMAL_AVG4) {
return false;
}
} else if (perfMode == PERF_CIC_AVG_MODE) {
if (bw > BW_RES_AVG128) {
return false;
}
} else {
return false;
}
if ((odr < ODR_0_78HZ) || (odr > ODR_1600HZ)) {
return false;
}
buffer[0] = odr & 0x0F;
buffer[0] |= (uint8_t)(bw << 4);
buffer[0] |= (uint8_t)(perfMode << 7);
buffer[1] = range & 0x03;
/* Burst write is not possible in
suspend mode hence individual write is
used with hal->delay of 1 ms */
comm->writeRegister(ACCEL_CONFIG_ADDR, buffer[0]);
hal->delay(2);
comm->writeRegister(ACCEL_CONFIG_ADDR + 1, buffer[1]);
return true;
}
bool SensorBMA423::getAccelRaw(int16_t *rawBuffer)
{
uint8_t buffer[6] = {0};
if (comm->readRegister(DATA_8_ADDR, buffer, 6) != -1) {
/* Accel data x axis */
rawBuffer[0] = (int16_t)(buffer[1] << 8) | (buffer[0]);
/* Accel data y axis */
rawBuffer[1] = (int16_t)(buffer[3] << 8) | (buffer[2]);
/* Accel data z axis */
rawBuffer[2] = (int16_t)(buffer[5] << 8) | (buffer[4]);
} else {
return false;
}
return true;
}
bool SensorBMA423::getAccelerometer(int16_t &x, int16_t &y, int16_t &z)
{
int16_t raw[3];
if (getAccelRaw(raw)) {
x = raw[0] / 16;
y = raw[1] / 16;
z = raw[2] / 16;
return true;
}
return false;
}
float SensorBMA423::getTemperature(TemperatureUnit unit)
{
int32_t raw = comm->readRegister(TEMPERATURE_ADDR);
/* '0' value read from the register corresponds to 23 degree C */
raw = (raw * 1000) + (23 * 1000);
switch (unit) {
case TEMP_FAHRENHEIT:
/* Temperature in degree Fahrenheit */
/* 1800 = 1.8 * 1000 */
raw = ((raw / 1000) * 1800) + (32 * 1000);
break;
case TEMP_KELVIN:
/* Temperature in degree Kelvin */
/* 273150 = 273.15 * 1000 */
raw = raw + 273150;
break;
default:
break;
}
float res = (float)raw / (float)1000.0;
/* 0x80 - raw read from the register and 23 is the ambient raw added.
* If the raw read from register is 0x80, it means no valid
* information is available */
if (((raw - 23) / 1000) == 0x80) {
return 0;
}
return res;
}
uint8_t SensorBMA423::direction()
{
int16_t x = 0, y = 0, z = 0;
getAccelerometer(x, y, z);
uint16_t absX = abs(x);
uint16_t absY = abs(y);
uint16_t absZ = abs(z);
if ((absZ > absX) && (absZ > absY)) {
if (z > 0) {
return DIRECTION_TOP;
} else {
return DIRECTION_BOTTOM;
}
} else if ((absY > absX) && (absY > absZ)) {
if (y > 0) {
return DIRECTION_TOP_RIGHT;
} else {
return DIRECTION_BOTTOM_LEFT;
}
} else {
if (x < 0) {
return DIRECTION_BOTTOM_RIGHT;
} else {
return DIRECTION_TOP_LEFT;
}
}
return 0;
}
bool SensorBMA423::setRemapAxes(SensorRemap remap)
{
//Top
// No.1 REG: 0x3e -> 0x88 REG: 0x3f -> 0x0
// No.2 REG: 0x3e -> 0xac REG: 0x3f -> 0x0
// No.3 REG: 0x3e -> 0x85 REG: 0x3f -> 0x0
// No.4 REG: 0x3e -> 0xa1 REG: 0x3f -> 0x0
// Bottom
// No.5 REG: 0x3e -> 0x81 REG: 0x3f -> 0x1
// No.6 REG: 0x3e -> 0xa5 REG: 0x3f -> 0x1
// No.7 REG: 0x3e -> 0x8c REG: 0x3f -> 0x1
// No.8 REG: 0x3e -> 0xa8 REG: 0x3f -> 0x1
uint8_t configReg0[] = {0x88, 0xAC, 0x85, 0xA1, 0x81, 0xA5, 0x8C, 0xA8};
if (remap > sizeof(configReg0) / sizeof(configReg0[0])) {
return false;
}
uint8_t buffer[FEATURE_SIZE] = {0};
uint8_t index = AXES_REMAP_OFFSET;
if (comm->readRegister(FEATURE_CONFIG_ADDR, buffer, FEATURE_SIZE) == -1) {
return false;
}
buffer[index] = configReg0[remap];
buffer[index + 1] = remap >= 4 ? 0x00 : 0x01;
return comm->writeRegister(FEATURE_CONFIG_ADDR, buffer, FEATURE_SIZE) != -1;
}
bool SensorBMA423::setStepCounterWatermark(uint16_t watermark)
{
uint8_t buffer[FEATURE_SIZE] = {0};
uint8_t index = STEP_CNTR_OFFSET;
uint16_t wm_lsb = 0;
uint16_t wm_msb = 0;
int rslt;
uint16_t data = 0;
rslt = comm->readRegister(FEATURE_CONFIG_ADDR, buffer, FEATURE_SIZE);
if (rslt != -1) {
wm_lsb = buffer[index];
wm_msb = buffer[index + 1] << 8;
data = wm_lsb | wm_msb;
/* Sets only watermark bits in the complete 16 bits of data */
data = ((data & ~(0x03FFU)) | (watermark & 0x03FFU));
/* Splits 16 bits of data to individual 8 bits data */
buffer[index] = (uint8_t)(data & 0x00FFU);
buffer[index + 1] = (uint8_t)((data & 0xFF00U) >> 8);
/* Writes stepcounter watermark settings in the sensor */
rslt = comm->writeRegister(FEATURE_CONFIG_ADDR, buffer, FEATURE_SIZE);
}
return rslt != -1;
}
bool SensorBMA423::disablePedometer()
{
return enablePedometer(false);
}
bool SensorBMA423::enablePedometer(bool enable)
{
int rslt;
uint8_t buffer[FEATURE_SIZE] = {0};
/* Step detector enable bit pos. is 1 byte ahead of the base address */
uint8_t index = STEP_CNTR_OFFSET + 1;
rslt = comm->readRegister(FEATURE_CONFIG_ADDR, buffer, FEATURE_SIZE);
if (rslt != -1) {
buffer[index] = ((buffer[index] & ~0x08) | ((enable << 3) & 0x08));
rslt = comm->writeRegister(FEATURE_CONFIG_ADDR, buffer, FEATURE_SIZE);
}
return rslt != -1;
}
uint32_t SensorBMA423::getPedometerCounter()
{
uint8_t buffer[4] = {0};
/* Reads the step counter output data from the gpio register */
int rslt = comm->readRegister(STEP_CNT_OUT_0_ADDR, buffer, 4);
if (rslt != -1) {
return ((uint32_t)buffer[0]) | ((uint32_t)buffer[1] << 8) | ((uint32_t)buffer[2] << 16) | ((uint32_t)buffer[3] << 24);
}
return 0;
}
void SensorBMA423::resetPedometer()
{
uint8_t buffer[FEATURE_SIZE] = {0};
/* Reset bit is 1 byte ahead of base address */
uint8_t index = STEP_CNTR_OFFSET + 1;
int rslt = comm->readRegister(FEATURE_CONFIG_ADDR, buffer, FEATURE_SIZE);
if (rslt != -1) {
buffer[index] = ((buffer[index] & ~0x04U) | ((1 << 2U) & 0x04U));
comm->writeRegister(FEATURE_CONFIG_ADDR, buffer, FEATURE_SIZE);
}
}
bool SensorBMA423::enableFeature(uint8_t feature, uint8_t enable)
{
uint8_t buffer[FEATURE_SIZE] = {0};
int rslt;
uint8_t len;
/* Update the length for read and write */
update_len(&len, feature, enable);
rslt = comm->readRegister(FEATURE_CONFIG_ADDR, buffer, len);
if (rslt != -1) {
if (enable) {
/* Enables the feature */
rslt = feature_enable(feature, len, buffer);
} else {
/* Disables the feature */
rslt = feature_disable(feature, len, buffer);
}
}
return rslt != -1;
}
uint16_t SensorBMA423::readIrqStatus()
{
uint8_t data[2] = {0};
if (comm->readRegister(INT_STAT_0_ADDR, data, 2) != -1) {
int_status = data[0] | (data[1] << 8);
return int_status;
}
return 0;
}
uint16_t SensorBMA423::getIrqStatus()
{
return int_status;
}
bool SensorBMA423::configInterrupt(
/*! Trigger condition of interrupt pin */
uint8_t edge_ctrl,
/*! Level of interrupt pin */
uint8_t level,
/*! Behaviour of interrupt pin to open drain */
uint8_t od,
/*! Output enable for interrupt pin */
uint8_t output_en,
/*! Input enable for interrupt pin */
uint8_t input_en,
/*! Variable used to select the interrupt pin1 or pin2 for interrupt configuration. */
uint8_t int_line
)
{
uint8_t interrupt_address_array[2] = {INT1_IO_CTRL_ADDR, INT2_IO_CTRL_ADDR};
uint8_t data = 0;
if (int_line > 1) {
return false;
}
data = ((uint8_t)((edge_ctrl & INT_EDGE_CTRL_MASK) |
((level << 1) & INT_LEVEL_MASK) |
((od << 2) & INT_OPEN_DRAIN_MASK) |
((output_en << 3) & INT_OUTPUT_EN_MASK) |
((input_en << 4) & INT_INPUT_EN_MASK)));
this->int_line = int_line;
return comm->writeRegister(interrupt_address_array[int_line], &data, 1) != -1;
}
bool SensorBMA423::configFeatureInterrupt(uint16_t feature_interrupt_mask, bool enable)
{
return interruptMap(int_line, feature_interrupt_mask, enable);
}
bool SensorBMA423::enablePedometerIRQ()
{
return (interruptMap(int_line, INT_STEP_CNTR, true));
}
bool SensorBMA423::enableTiltIRQ()
{
return (interruptMap(int_line, INT_TILT, true));
}
bool SensorBMA423::enableWakeupIRQ()
{
return (interruptMap(int_line, INT_WAKEUP, true));
}
bool SensorBMA423::enableAnyNoMotionIRQ()
{
return (interruptMap(int_line, INT_ANY_NO_MOTION, true));
}
bool SensorBMA423::enableActivityIRQ()
{
return (interruptMap(int_line, INT_ACTIVITY, true));
}
bool SensorBMA423::disablePedometerIRQ()
{
return (interruptMap(int_line, INT_STEP_CNTR, false));
}
bool SensorBMA423::disableTiltIRQ()
{
return (interruptMap(int_line, INT_TILT, false));
}
bool SensorBMA423::disableWakeupIRQ()
{
return (interruptMap(int_line, INT_WAKEUP, false));
}
bool SensorBMA423::disableAnyNoMotionIRQ()
{
return (interruptMap(int_line, INT_ANY_NO_MOTION, false));
}
bool SensorBMA423::disableActivityIRQ()
{
return (interruptMap(int_line, INT_ACTIVITY, false));
}
bool SensorBMA423::isActivity()
{
return (int_status & ACTIVITY_INT);
}
bool SensorBMA423::isTilt()
{
return (int_status & TILT_INT);
}
bool SensorBMA423::isDoubleTap()
{
return (int_status & WAKEUP_INT);
}
bool SensorBMA423::isAnyNoMotion()
{
return (int_status & ACTIVITY_INT);
}
bool SensorBMA423::isPedometer()
{
return (int_status & STEP_CNTR_INT);
}
bool SensorBMA423::interruptMap(uint8_t int_line, uint16_t int_map, uint8_t enable)
{
int rslt;
uint8_t data[3] = {0, 0, 0};
uint8_t index[2] = {INT_MAP_1_ADDR, INT_MAP_2_ADDR};
rslt = comm->readRegister(INT_MAP_1_ADDR, data, 3);
if (enable) {
/* Feature interrupt mapping */
data[int_line] |= (uint8_t)(int_map & (0x00FF));
/* Hardware interrupt mapping */
if (int_line == INTR2_MAP)
data[2] |= (uint8_t)((int_map & (0xFF00)) >> 4);
else
data[2] |= (uint8_t)((int_map & (0xFF00)) >> 8);
rslt = comm->writeRegister(index[int_line], &data[int_line], 1);
rslt = comm->writeRegister(INT_MAP_DATA_ADDR, &data[2], 1);
} else {
/* Feature interrupt un-mapping */
data[int_line] &= (~(uint8_t)(int_map & (0x00FF)));
/* Hardware interrupt un-mapping */
if (int_line == INTR2_MAP)
data[2] &= (~(uint8_t)((int_map & (0xFF00)) >> 4));
else
data[2] &= (~(uint8_t)((int_map & (0xFF00)) >> 8));
rslt = comm->writeRegister(index[int_line], &data[int_line], 1);
rslt = comm->writeRegister(INT_MAP_DATA_ADDR, &data[2], 1);
}
return rslt != -1;
}
/*!
* @brief This API sets the interrupt mode in the sensor.
*/
bool SensorBMA423::setInterruptMode(uint8_t mode)
{
if (mode == NON_LATCH_MODE || mode == LATCH_MODE)
return comm->writeRegister(INTR_LATCH_ADDR, &mode, 1) != -1;
return false;
}
bool SensorBMA423::feature_disable(uint8_t feature, uint8_t len, uint8_t *buffer)
{
uint8_t index = 0;
/* Disable step counter */
if ((feature & FEATURE_STEP_CNTR) > 0) {
/* Step counter enable bit pos. is 1 byte ahead of the
base address */
index = STEP_CNTR_OFFSET + 1;
buffer[index] = buffer[index] & (~STEP_CNTR_EN_MSK);
}
/* Disable activity */
if ((feature & FEATURE_ACTIVITY) > 0) {
/* Activity enable bit pos. is 1 byte ahead of the
base address */
index = STEP_CNTR_OFFSET + 1;
buffer[index] = buffer[index] & (~ACTIVITY_EN_MSK);
}
/* Disable tilt */
if ((feature & FEATURE_TILT) > 0) {
/* Tilt enable bit pos. is the base address(0x3A) of tilt */
index = TILT_OFFSET;
buffer[index] = buffer[index] & (~TILT_EN_MSK);
}
/* Disable wakeup */
if ((feature & FEATURE_WAKEUP) > 0) {
/* Tilt enable bit pos. is the base address(0x38) of wakeup */
index = WAKEUP_OFFSET;
buffer[index] = buffer[index] & (~WAKEUP_EN_MSK);
}
/* Disable anymotion/nomotion */
if ((feature & FEATURE_ANY_MOTION) > 0 || (feature & FEATURE_NO_MOTION) > 0) {
/* Any/Nomotion enable bit pos. is 1 bytes ahead of the
any/nomotion base address(0x00) */
index = 1;
if ((feature & FEATURE_ANY_MOTION) > 0) {
/* Disable anymotion */
buffer[index] = buffer[index] | ANY_NO_MOTION_SEL_MSK;
} else {
/* Disable nomotion */
buffer[index] = buffer[index] & (~ANY_NO_MOTION_SEL_MSK);
}
/* Any/Nomotion axis enable bit pos. is 3 byte ahead of the
any/nomotion base address(0x00) */
index = 3;
buffer[index] = buffer[index] & (~ANY_NO_MOTION_AXIS_EN_MSK);
}
/* Write the configured settings in the sensor */
return comm->writeRegister(FEATURE_CONFIG_ADDR, buffer, len) != -1;
}
int SensorBMA423::feature_enable(uint8_t feature, uint8_t len, uint8_t *buffer)
{
uint8_t index = 0;
/* Enable step counter */
if ((feature & FEATURE_STEP_CNTR) > 0) {
/* Step counter enable bit pos. is 1 byte ahead of the
base address */
index = STEP_CNTR_OFFSET + 1;
buffer[index] = buffer[index] | STEP_CNTR_EN_MSK;
}
/* Enable activity */
if ((feature & FEATURE_ACTIVITY) > 0) {
/* Activity enable bit pos. is 1 byte ahead of the
base address */
index = STEP_CNTR_OFFSET + 1;
buffer[index] = buffer[index] | ACTIVITY_EN_MSK;
}
/* Enable tilt */
if ((feature & FEATURE_TILT) > 0) {
/* Tilt enable bit pos. is the base address(0x3A) of tilt */
index = TILT_OFFSET;
buffer[index] = buffer[index] | TILT_EN_MSK;
}
/* Enable wakeup */
if ((feature & FEATURE_WAKEUP) > 0) {
/* Wakeup enable bit pos. is the base address(0x38) of wakeup */
index = WAKEUP_OFFSET;
buffer[index] = buffer[index] | WAKEUP_EN_MSK;
}
/* Enable anymotion/nomotion */
if ((feature & FEATURE_ANY_MOTION) > 0 || (feature & FEATURE_NO_MOTION) > 0) {
/* Any/Nomotion enable bit pos. is 1 bytes ahead of the
any/nomotion base address(0x00) */
index = 1;
if ((feature & FEATURE_ANY_MOTION) > 0) {
/* Enable anymotion */
buffer[index] = buffer[index] & (~ANY_NO_MOTION_SEL_MSK);
} else {
/* Enable nomotion */
buffer[index] = buffer[index] | ANY_NO_MOTION_SEL_MSK;
}
}
/* Write the feature enable settings in the sensor */
return comm->writeRegister(FEATURE_CONFIG_ADDR, buffer, len) != -1;
}
void SensorBMA423::update_len(uint8_t *len, uint8_t feature, uint8_t enable)
{
uint8_t length = FEATURE_SIZE;
if ((feature == FEATURE_ANY_MOTION) || (feature == FEATURE_NO_MOTION)) {
/* Change the feature length to 2 for reading and writing of 2 bytes for
any/no-motion enable */
length = ANYMOTION_EN_LEN;
/* Read and write 4 byte to disable the any/no motion completely along with
all axis */
if (!enable) {
/*Change the feature length to 4 for reading and writing
of 4 bytes for any/no-motion enable */
length = length + 2;
}
}
*len = length;
}
bool SensorBMA423::configure()
{
uint8_t val;
val = comm->readRegister(INTERNAL_STAT);
if (val == ASIC_INITIALIZED) {
log_d("No need configure!");
readIrqStatus(); //clear irq status
return true;
}
disablePowerSave();
hal->delay(1);
disableInterruptCtrl();
const uint8_t *stream_data = bma423_config_file;
const uint8_t maxReadWriteLength = 32;
for (size_t index = 0; index < CONFIG_STREAM_SIZE; index += maxReadWriteLength) {
uint8_t msb = (uint8_t)((index / 2) >> 4);
uint8_t lsb = ((index / 2) & 0x0F);
comm->writeRegister(RESERVED_REG_5B_ADDR, lsb);
comm->writeRegister(RESERVED_REG_5C_ADDR, msb);
comm->writeRegister(FEATURE_CONFIG_ADDR, (uint8_t *)(stream_data + index), maxReadWriteLength);
}
enableInterruptCtrl();
hal->delay(150);
val = comm->readRegister(INTERNAL_STAT);
if (val == ASIC_INITIALIZED) {
log_d("BMA configure SUCCESS!");
} else {
log_d("BMA configure FAILED!");
}
return val == ASIC_INITIALIZED;
}
bool SensorBMA423::initImpl()
{
uint8_t id = 0x00;
int retry = 5;
while (retry--) {
id = comm->readRegister(CHIP_ID_ADDR);
if (id != CHIP_ID) {
reset();
}
}
if (id == CHIP_ID) {
return configure();
}
log_d("ChipID:0x%x should be 0x%x", id, CHIP_ID);
return false;
}

View File

@@ -0,0 +1,269 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file SensorBMA423.hpp
* @author Lewis He (lewishe@outlook.com)
* @date 2022-03-31
* @note Most source code references come from the https://github.com/boschsensortec/BMA423-Sensor-API
* Simplification for Arduino
*/
#pragma once
#include "REG/BMA423Constants.h"
#include "SensorPlatform.hpp"
class SensorBMA423 : public BMA423Constants
{
public:
enum AccelRange {
RANGE_2G,
RANGE_4G,
RANGE_8G,
RANGE_16G
};
/*! Output data rate in Hz */
enum AccelODR {
ODR_0_78HZ = 1,
ODR_1_56HZ,
ODR_3_12HZ,
ODR_6_25HZ,
ODR_12_5HZ,
ODR_25HZ,
ODR_50HZ,
ODR_100HZ,
ODR_200HZ,
ODR_400HZ,
ODR_800HZ,
ODR_1600HZ,
};
/*! Bandwidth parameter, determines filter configuration */
enum BandWidth {
BW_OSR4_AVG1,
BW_OSR2_AVG2,
BW_NORMAL_AVG4,
BW_CIC_AVG8,
BW_RES_AVG16,
BW_RES_AVG32,
BW_RES_AVG64,
BW_RES_AVG128,
};
enum PerformanceMode {
PERF_CIC_AVG_MODE,
PERF_CONTINUOUS_MODE,
};
enum TemperatureUnit {
TEMP_DEG,
TEMP_FAHRENHEIT,
TEMP_KELVIN,
};
// Calculate direction facing the front of the chip
enum SensorDir {
DIRECTION_BOTTOM_LEFT,
DIRECTION_TOP_RIGHT,
DIRECTION_TOP_LEFT,
DIRECTION_BOTTOM_RIGHT,
DIRECTION_BOTTOM,
DIRECTION_TOP
};
// Chip orientation and orientation
enum SensorRemap {
// Top right corner
REMAP_TOP_LAYER_RIGHT_CORNER,
// Front bottom left corner
REMAP_TOP_LAYER_BOTTOM_LEFT_CORNER,
// Top left corner
REMAP_TOP_LAYER_LEFT_CORNER,
// Top bottom right corner
REMAP_TOP_LAYER_BOTTOM_RIGHT_CORNER,
// Bottom top right corner
REMAP_BOTTOM_LAYER_TOP_RIGHT_CORNER,
// Bottom bottom left corner
REMAP_BOTTOM_LAYER_BOTTOM_LEFT_CORNER,
// Bottom bottom right corner
REMAP_BOTTOM_LAYER_BOTTOM_RIGHT_CORNER,
// Bottom top left corner
REMAP_BOTTOM_LAYER_TOP_LEFT_CORNER,
};
enum Feature {
/**\name Feature enable macros for the sensor */
FEATURE_STEP_CNTR = 0x01,
/**\name Below macros are mutually exclusive */
FEATURE_ANY_MOTION = 0x02,
FEATURE_NO_MOTION = 0x04,
FEATURE_ACTIVITY = 0x08,
FEATURE_TILT = 0x10,
FEATURE_WAKEUP = 0x20,
};
/**\name Interrupt status macros */
enum FeatureInterrupt {
INT_STEP_CNTR = 0x02,
INT_ACTIVITY = 0x04,
INT_TILT = 0x05,
INT_WAKEUP = 0x20,
INT_ANY_NO_MOTION = 0x40,
};
SensorBMA423();
~SensorBMA423();
#if defined(ARDUINO)
bool begin(TwoWire &wire, uint8_t addr = BMA423_I2C_ADDR_SECONDARY, int sda = -1, int scl = -1);
#elif defined(ESP_PLATFORM)
#if defined(USEING_I2C_LEGACY)
bool begin(i2c_port_t port_num, uint8_t addr = BMA423_I2C_ADDR_SECONDARY, int sda = -1, int scl = -1);
#else
bool begin(i2c_master_bus_handle_t handle, uint8_t addr = BMA423_I2C_ADDR_SECONDARY);
#endif //ESP_PLATFORM
#endif //ARDUINO
bool begin(SensorCommCustom::CustomCallback callback,
SensorCommCustomHal::CustomHalCallback hal_callback,
uint8_t addr = BMA423_I2C_ADDR_SECONDARY);
void reset();
bool enablePowerSave();
bool disablePowerSave();
void disableInterruptCtrl();
void enableInterruptCtrl();
bool enableAccelerometer();
bool disableAccelerometer();
bool configAccelerometer(AccelRange range = RANGE_4G, AccelODR odr = ODR_200HZ,
BandWidth bw = BW_NORMAL_AVG4,
PerformanceMode perfMode = PERF_CONTINUOUS_MODE);
bool getAccelRaw(int16_t *rawBuffer);
bool getAccelerometer(int16_t &x, int16_t &y, int16_t &z);
float getTemperature(TemperatureUnit unit);
uint8_t direction();
bool setRemapAxes(SensorRemap remap);
bool setStepCounterWatermark(uint16_t watermark);
bool disablePedometer();
bool enablePedometer(bool enable = true);
uint32_t getPedometerCounter();
void resetPedometer();
bool enableFeature(uint8_t feature, uint8_t enable);
uint16_t readIrqStatus();
uint16_t getIrqStatus();
bool configInterrupt(
/*! Trigger condition of interrupt pin */
uint8_t edge_ctrl = LEVEL_TRIGGER,
/*! Level of interrupt pin */
uint8_t level = ACTIVE_HIGH,
/*! Behaviour of interrupt pin to open drain */
uint8_t od = PUSH_PULL,
/*! Output enable for interrupt pin */
uint8_t output_en = OUTPUT_ENABLE,
/*! Input enable for interrupt pin */
uint8_t input_en = INPUT_DISABLE,
/*! Variable used to select the interrupt pin1 or pin2 for interrupt configuration. */
uint8_t int_line = INTR1_MAP
);
bool configFeatureInterrupt(uint16_t feature_interrupt_mask, bool enable);
bool enablePedometerIRQ();
bool enableTiltIRQ();
bool enableWakeupIRQ();
bool enableAnyNoMotionIRQ();
bool enableActivityIRQ();
bool disablePedometerIRQ();
bool disableTiltIRQ();
bool disableWakeupIRQ();
bool disableAnyNoMotionIRQ();
bool disableActivityIRQ();
bool isActivity();
bool isTilt();
bool isDoubleTap();
bool isAnyNoMotion();
bool isPedometer();
private:
bool interruptMap(uint8_t int_line, uint16_t int_map, uint8_t enable);
/*!
* @brief This API sets the interrupt mode in the sensor.
*/
bool setInterruptMode(uint8_t mode);
bool feature_disable(uint8_t feature, uint8_t len, uint8_t *buffer);
int feature_enable(uint8_t feature, uint8_t len, uint8_t *buffer);
void update_len(uint8_t *len, uint8_t feature, uint8_t enable);
bool configure();
bool initImpl();
uint16_t int_status;
uint8_t int_line;
std::unique_ptr<SensorCommBase> comm;
std::unique_ptr<SensorHal> hal;
};

View File

@@ -0,0 +1,287 @@
/**
*
* @license MIT License
*
* Copyright (c) 2023 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file SensorBMM150.hpp
* @author Lewis He (lewishe@outlook.com)
* @date 2023-10-09
* @note Most source code references come from the https://github.com/boschsensortec/BMM150-Sensor-API
* Simplification for Arduino
*/
#pragma once
#include "bosch/BMM150/bmm150.h"
#include "SensorPlatform.hpp"
#if defined(ARDUINO)
/*! @name I2C ADDRESS */
#define BMM150_DEFAULT_I2C_ADDRESS UINT8_C(0x10)
#define BMM150_I2C_ADDRESS_CSB_LOW_SDO_HIGH UINT8_C(0x11)
#define BMM150_I2C_ADDRESS_CSB_HIGH_SDO_LOW UINT8_C(0x12)
#define BMM150_I2C_ADDRESS_CSB_HIGH_SDO_HIGH UINT8_C(0x13)
class SensorBMM150
{
public:
enum PowerMode {
POWERMODE_NORMAL,
POWERMODE_FORCED,
POWERMODE_SLEEP,
POWERMODE_SUSPEND,
};
enum InterruptLevel {
INTERRUPT_HIGH_ACTIVE,
INTERRUPT_LOW_ACTIVE,
};
SensorBMM150(): comm(nullptr),
hal(nullptr),
staticComm(nullptr),
dev(nullptr),
_rst(-1),
_error_code(0)
{
}
~SensorBMM150()
{
}
void setPins(int rst)
{
_rst = rst;
}
#if defined(ARDUINO)
bool begin(TwoWire &wire, uint8_t addr, int sda, int scl)
{
if (!beginCommonStatic<SensorCommI2C, HalArduino>(comm, staticComm, hal, wire, addr, sda, scl)) {
return false;
}
return initImpl(BMM150_I2C_INTF);
}
bool begin(SPIClass &spi, uint8_t csPin, int mosi, int miso, int sck)
{
if (!beginCommonStatic<SensorCommSPI, HalArduino>(comm,
staticComm, hal,
spi, csPin, mosi, miso, sck)) {
return false;
}
return initImpl(BMM150_I2C_INTF);
}
#elif defined(ESP_PLATFORM)
#if defined(USEING_I2C_LEGACY)
bool begin(i2c_port_t port_num, uint8_t addr, int sda, int scl)
{
if (!beginCommonStatic<SensorCommI2C, HalEspIDF>(comm, staticComm, hal, port_num, addr, sda, scl)) {
return false;
}
return initImpl(BHY2_I2C_INTERFACE);
}
#else
bool begin(i2c_master_bus_handle_t handle, uint8_t addr)
{
if (!beginCommonStatic<SensorCommI2C, HalEspIDF>(comm, staticComm, hal, handle, addr)) {
return false;
}
return initImpl(BHY2_I2C_INTERFACE);
}
#endif //ESP_PLATFORM
#endif //ARDUINO
bool begin(CommInterface interface,
SensorCommCustom::CustomCallback callback,
SensorCommCustomHal::CustomHalCallback hal_callback,
uint8_t addr)
{
if (!beginCommCustomCallback<SensorCommCustom, SensorCommCustomHal>(interface,
callback, hal_callback, addr, comm, hal)) {
return false;
}
return initImpl(static_cast<bmm150_intf>(interface));
}
void reset()
{
if (_rst != -1) {
hal->digitalWrite(_rst, HIGH);
hal->delay(5);
hal->digitalWrite(_rst, LOW);
hal->delay(10);
hal->digitalWrite(_rst, HIGH);
hal->delay(5);
}
}
void sleep()
{
setMode(POWERMODE_SLEEP);
}
bool setMode(PowerMode mode)
{
settings.pwr_mode = mode;
return bmm150_set_op_mode(&settings, dev.get()) == BMM150_OK;
}
bool setThreshold(uint8_t high_th, uint8_t low_th)
{
settings.int_settings.high_threshold = high_th;
settings.int_settings.low_threshold = low_th;
return bmm150_set_sensor_settings(BMM150_SEL_HIGH_THRESHOLD_SETTING, &settings, dev.get()) == BMM150_OK;
}
bool setInterruptLevel(InterruptLevel level)
{
settings.int_settings.high_int_en = level;
return bmm150_set_sensor_settings(BMM150_SEL_HIGH_THRESHOLD_INT, &settings, dev.get()) == BMM150_OK;
}
bool enableINT()
{
settings.int_settings.int_pin_en = BMM150_INT_ENABLE;
return bmm150_set_sensor_settings(BMM150_SEL_INT_PIN_EN, &settings, dev.get()) == BMM150_OK;
}
bool disableINT()
{
settings.int_settings.int_pin_en = BMM150_INT_DISABLE;
return bmm150_set_sensor_settings(BMM150_SEL_INT_PIN_EN, &settings, dev.get()) == BMM150_OK;
}
bool enabledDataReady()
{
settings.int_settings.drdy_pin_en = BMM150_INT_ENABLE;
return bmm150_set_sensor_settings(BMM150_SEL_DRDY_PIN_EN, &settings, dev.get()) == BMM150_OK;
}
bool disabledDataReady()
{
settings.int_settings.drdy_pin_en = BMM150_INT_DISABLE;
return bmm150_set_sensor_settings(BMM150_SEL_DRDY_PIN_EN, &settings, dev.get()) == BMM150_OK;
}
uint8_t getChipID()
{
return dev->chip_id;
}
uint8_t getIrqStatus()
{
bmm150_get_interrupt_status(dev.get());
return dev->int_status;
}
bool isDataReady()
{
return dev->int_status & BMM150_INT_ASSERTED_DRDY;
}
bool isLowThreshold()
{
return dev->int_status & BMM150_INT_ASSERTED_LOW_THRES;
}
bool isHighThreshold()
{
return dev->int_status & BMM150_INT_ASSERTED_HIGH_THRES;
}
struct bmm150_mag_data getMag()
{
struct bmm150_mag_data data = {0, 0, 0};
bmm150_read_mag_data(&data, dev.get());
return data;
}
bool getMag(int16_t &x, int16_t &y, int16_t &z)
{
struct bmm150_mag_data data;
if (bmm150_read_mag_data(&data, dev.get()) != BMM150_OK) {
return false;
}
x = data.x;
y = data.y;
z = data.z;
return true;
}
private:
bool initImpl(bmm150_intf interface)
{
memset(&settings, 0, sizeof(settings));
if (_rst != -1) {
hal->pinMode(_rst, OUTPUT);
}
reset();
dev = std::make_unique<struct bmm150_dev>();
if (!dev) {
log_e(" Device handler malloc failed!");
return false;
}
dev->intf = interface;
dev->read = SensorCommStatic::sensor_static_read_data;
dev->write = SensorCommStatic::sensor_static_write_data;
dev->intf_ptr = staticComm.get();
dev->delay_us = SensorCommStatic::sensor_static_delay_us;
_error_code = bmm150_init(dev.get());
if (_error_code != BMM150_OK) {
return false;
}
_error_code = bmm150_soft_reset(dev.get());
if (_error_code != BMM150_OK) {
return false;
}
bmm150_get_sensor_settings(&settings, dev.get());
return _error_code == BMM150_OK;
}
std::unique_ptr<SensorCommBase> comm;
std::unique_ptr<SensorHal> hal;
std::unique_ptr<SensorCommStatic> staticComm;
std::unique_ptr<struct bmm150_dev> dev;
int _rst;
int8_t _error_code;
struct bmm150_settings settings;
};
#endif /*defined(ARDUINO)*/

View File

@@ -0,0 +1,239 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file SensorCM32181.hpp
* @author Lewis He (lewishe@outlook.com)
* @date 2023-04-14
*
*/
#pragma once
#include "REG/CM32181Constants.h"
#include "SensorPlatform.hpp"
class SensorCM32181 : public CM32181Constants
{
public:
enum Sampling {
SAMPLING_X1, //ALS Sensitivity x 1
SAMPLING_X2, //ALS Sensitivity x 2
SAMPLING_X1_8, //ALS Sensitivity x (1/8)
SAMPLING_X1_4, //ALS Sensitivity x (1/4)
};
enum IntegrationTime {
INTEGRATION_TIME_25MS = 0x0C,
INTEGRATION_TIME_50MS = 0x08,
INTEGRATION_TIME_100MS = 0x00, //0000 = 100ms
INTEGRATION_TIME_200MS, //0001 = 200ms
INTEGRATION_TIME_400MS, //0010 = 400ms
INTEGRATION_TIME_800MS, //0011 = 800ms
};
enum PowerSaveMode {
PowerSaveMode1 = 0x00,
PowerSaveMode2,
PowerSaveMode3,
PowerSaveMode4
};
enum InterruptEvent {
ALS_EVENT_LOW_TRIGGER = 0x00,
ALS_EVENT_HIGH_TRIGGER,
ALS_EVENT_NULL,
};
SensorCM32181() : comm(nullptr) {}
~SensorCM32181()
{
if (comm) {
comm->deinit();
}
}
#if defined(ARDUINO)
bool begin(TwoWire &wire, uint8_t addr = CM32181_ADDR_PRIMARY, int sda = -1, int scl = -1)
{
comm = std::make_unique<SensorCommI2C>(wire, addr, sda, scl);
if (!comm) {
return false;
}
comm->init();
return initImpl();
}
#elif defined(ESP_PLATFORM)
#if defined(USEING_I2C_LEGACY)
bool begin(i2c_port_t port_num, uint8_t addr = CM32181_ADDR_PRIMARY, int sda = -1, int scl = -1)
{
comm = std::make_unique<SensorCommI2C>(port_num, addr, sda, scl);
if (!comm) {
return false;
}
comm->init();
return initImpl();
}
#else
bool begin(i2c_master_bus_handle_t handle, uint8_t addr = CM32181_ADDR_PRIMARY)
{
comm = std::make_unique<SensorCommI2C>(handle, addr);
if (!comm) {
return false;
}
comm->init();
return initImpl();
}
#endif //ESP_PLATFORM
#endif //ARDUINO
bool begin(SensorCommCustom::CustomCallback callback, uint8_t addr = CM32181_ADDR_PRIMARY)
{
comm = std::make_unique<SensorCommCustom>(callback, addr);
if (!comm) {
return false;
}
comm->init();
return initImpl();
}
void setSampling(Sampling tempSampling = SAMPLING_X1,
IntegrationTime int_time = INTEGRATION_TIME_200MS
)
{
uint16_t data;
comm->readRegister(REG_ALS_CONF, (uint8_t *)&data, 2);
data &= ~(0x03 << 11);
data |= tempSampling << 11;
data &= ~(0xF << 6);
data |= int_time << 6;
comm->readRegister(REG_ALS_CONF, (uint8_t *)&data, 2);
}
void setIntThreshold(uint16_t low_threshold, uint16_t high_threshold)
{
uint8_t buffer[2] = {0};
buffer[1] = highByte(high_threshold);
buffer[0] = lowByte(high_threshold);;
comm->writeRegister(REG_ALS_THDH, buffer, 2);
buffer[1] = highByte(low_threshold);
buffer[0] = lowByte(low_threshold);
comm->writeRegister(REG_ALS_THDL, buffer, 2);
}
void powerSave(PowerSaveMode mode, bool enable)
{
uint16_t data = 0x00;
comm->readRegister(REG_ALS_PSM, (uint8_t *)&data, 2);
data |= mode << 1;
enable ? data |= 0x01 : data |= 0x00;
comm->writeRegister(REG_ALS_PSM, (uint8_t *)&data, 2);
}
// Read REG_ALS_STATUS register to clear interrupt
InterruptEvent getIrqStatus()
{
uint16_t data;
comm->readRegister(REG_ALS_STATUS, (uint8_t *)&data, 2);
return bitRead(data, 15) ? ALS_EVENT_LOW_TRIGGER : bitRead(data, 14) ? ALS_EVENT_HIGH_TRIGGER : ALS_EVENT_NULL;
}
void enableINT()
{
uint16_t data;
comm->readRegister(REG_ALS_CONF, (uint8_t *)&data, 2);
bitWrite(data, 1, 1);
comm->writeRegister(REG_ALS_CONF, (uint8_t *)&data, 2);
}
void disableINT()
{
uint16_t data;
comm->readRegister(REG_ALS_CONF, (uint8_t *)&data, 2);
bitWrite(data, 1, 0);
comm->writeRegister(REG_ALS_CONF, (uint8_t *)&data, 2);
}
void powerOn()
{
uint16_t data;
comm->readRegister(REG_ALS_CONF, (uint8_t *)&data, 2);
bitClear(data, 0);
comm->writeRegister(REG_ALS_CONF, (uint8_t *)&data, 2);
}
void powerDown()
{
uint16_t data;
comm->readRegister(REG_ALS_CONF, (uint8_t *)&data, 2);
bitSet(data, 0);
comm->writeRegister(REG_ALS_CONF, (uint8_t *)&data, 2);
}
uint16_t getRaw()
{
uint8_t buffer[2] = {0};
comm->readRegister(REG_ALS_DATA, buffer, 2);
return (uint16_t) buffer[0] | (uint16_t)(buffer[1] << 8);
}
float getLux()
{
return getRaw() * calibration_factor;
}
int getChipID()
{
uint8_t buffer[2] = {0};
comm->readRegister(REG_ID, buffer, 2);
return lowByte(buffer[0]);
}
private:
bool initImpl()
{
I2CParam params(I2CParam::I2C_SET_FLAG, false);
comm->setParams(params);
int chipID = getChipID();
log_i("chipID:%d\n", chipID);
if (chipID < 0 ) {
return false;
}
if (chipID != CM32181_CHIP_ID) {
return false;
}
return true;
}
std::unique_ptr<SensorCommBase> comm;
// The default calibration value, learned from the manual,
// is now unable to obtain the calibration value from the specified register
const float calibration_factor = 0.286;
};

View File

@@ -0,0 +1,252 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file SensorDRV2605.hpp
* @author Lewis He (lewishe@outlook.com)
* @date 2023-04-03
* @note Source code from https://github.com/adafruit/Adafruit_DRV2605_Library
*/
#pragma once
#include "REG/DRV2605Constants.h"
#include "SensorPlatform.hpp"
class SensorDRV2605 : public DRV2605Constants
{
public:
static constexpr uint8_t MODE_INTTRIG = 0x00; //* Internal trigger mode
static constexpr uint8_t MODE_EXTTRIGEDGE = 0x01; //* External edge trigger mode
static constexpr uint8_t MODE_EXTTRIGLVL = 0x02; //* External level trigger mode
static constexpr uint8_t MODE_PWMANALOG = 0x03; //* PWM/Analog input mode
static constexpr uint8_t MODE_AUDIOVIBE = 0x04; //* Audio-to-vibe mode
static constexpr uint8_t MODE_REALTIME = 0x05; //* Real-time playback (RTP) mode
static constexpr uint8_t MODE_DIAGNOS = 0x06; //* Diagnostics mode
static constexpr uint8_t MODE_AUTOCAL = 0x07; //* Auto calibration mode
SensorDRV2605() : comm(nullptr) {}
~SensorDRV2605()
{
if (comm) {
comm->deinit();
}
}
#if defined(ARDUINO)
bool begin(TwoWire &wire, int sda = -1, int scl = -1)
{
comm = std::make_unique<SensorCommI2C>(wire, DRV2605_SLAVE_ADDRESS, sda, scl);
if (!comm) {
return false;
}
comm->init();
return initImpl();
}
#elif defined(ESP_PLATFORM)
#if defined(USEING_I2C_LEGACY)
bool begin(i2c_port_t port_num, int sda = -1, int scl = -1)
{
comm = std::make_unique<SensorCommI2C>(port_num, DRV2605_SLAVE_ADDRESS, sda, scl);
if (!comm) {
return false;
}
comm->init();
return initImpl();
}
#else
bool begin(i2c_master_bus_handle_t handle)
{
comm = std::make_unique<SensorCommI2C>(handle, DRV2605_SLAVE_ADDRESS);
if (!comm) {
return false;
}
comm->init();
return initImpl();
}
#endif //ESP_PLATFORM
#endif //ARDUINO
bool begin(SensorCommCustom::CustomCallback callback)
{
comm = std::make_unique<SensorCommCustom>(callback, DRV2605_SLAVE_ADDRESS);
if (!comm) {
return false;
}
comm->init();
return initImpl();
}
/**************************************************************************/
/*!
@brief Select the haptic waveform to use.
@param slot The waveform slot to set, from 0 to 7
@param w The waveform sequence value, refers to an index in the ROM library.
Playback starts at slot 0 and continues through to slot 7, stopping if it
encounters a value of 0. A list of available waveforms can be found in
section 11.2 of the datasheet: http://www.adafruit.com/datasheets/DRV2605.pdf
*/
/**************************************************************************/
void setWaveform(uint8_t slot, uint8_t w)
{
comm->writeRegister(DRV2605_REG_WAVESEQ1 + slot, w);
}
/**************************************************************************/
/*!
@brief Select the waveform library to use.
@param lib Library to use, 0 = Empty, 1-5 are ERM, 6 is LRA.
See section 7.6.4 in the datasheet for more details:
http://www.adafruit.com/datasheets/DRV2605.pdf
*/
/**************************************************************************/
void selectLibrary(uint8_t lib)
{
comm->writeRegister(DRV2605_REG_LIBRARY, lib);
}
/**************************************************************************/
/*!
@brief Start playback of the waveforms (start moving!).
*/
/**************************************************************************/
void run()
{
comm->writeRegister(DRV2605_REG_GO, 1);
}
/**************************************************************************/
/*!
@brief Stop playback.
*/
/**************************************************************************/
void stop()
{
comm->writeRegister(DRV2605_REG_GO, (uint8_t)0);
}
/**************************************************************************/
/*!
@brief Set the device mode.
@param mode Mode value, see datasheet section 7.6.2:
http://www.adafruit.com/datasheets/DRV2605.pdf
0: Internal trigger, call run() to start playback\n
1: External trigger, rising edge on IN pin starts playback\n
2: External trigger, playback follows the state of IN pin\n
3: PWM/analog input\n
4: Audio\n
5: Real-time playback\n
6: Diagnostics\n
7: Auto calibration
*/
/**************************************************************************/
void setMode(uint8_t mode)
{
comm->writeRegister(DRV2605_REG_MODE, mode);
}
/**************************************************************************/
/*!
@brief Set the realtime value when in RTP mode, used to directly drive the
haptic motor.
@param rtp 8-bit drive value.
*/
/**************************************************************************/
void setRealtimeValue(uint8_t rtp)
{
comm->writeRegister(DRV2605_REG_RTPIN, rtp);
}
/**************************************************************************/
/*!
@brief Use ERM (Eccentric Rotating Mass) mode.
*/
/**************************************************************************/
void useERM()
{
comm->writeRegister(DRV2605_REG_FEEDBACK, comm->readRegister(DRV2605_REG_FEEDBACK) & 0x7F);
}
/**************************************************************************/
/*!
@brief Use LRA (Linear Resonance Actuator) mode.
*/
/**************************************************************************/
void useLRA()
{
comm->writeRegister(DRV2605_REG_FEEDBACK, comm->readRegister(DRV2605_REG_FEEDBACK) | 0x80);
}
private:
bool initImpl()
{
int chipID = comm->readRegister(DRV2605_REG_STATUS);
if (chipID < 0) {
return false;
}
chipID >>= 5;
if (chipID != DRV2604_CHIP_ID &&
chipID != DRV2605_CHIP_ID &&
chipID != DRV2604L_CHIP_ID &&
chipID != DRV2605L_CHIP_ID ) {
log_e("ChipID:0x%x should be 0x03 or 0x04 or 0x06 or 0x07\n", chipID);
return false;
}
comm->writeRegister(DRV2605_REG_MODE, (uint8_t)0x00); // out of standby
comm->writeRegister(DRV2605_REG_RTPIN, (uint8_t)0x00); // no real-time-playback
comm->writeRegister(DRV2605_REG_WAVESEQ1, (uint8_t)1); // strong click
comm->writeRegister(DRV2605_REG_WAVESEQ2, (uint8_t)0); // end sequence
comm->writeRegister(DRV2605_REG_OVERDRIVE, (uint8_t)0); // no overdrive
comm->writeRegister(DRV2605_REG_SUSTAINPOS, (uint8_t)0);
comm->writeRegister(DRV2605_REG_SUSTAINNEG, (uint8_t)0);
comm->writeRegister(DRV2605_REG_BREAK, (uint8_t)0);
comm->writeRegister(DRV2605_REG_AUDIOMAX, (uint8_t)0x64);
// ERM open loop
// turn off N_ERM_LRA
comm->writeRegister(DRV2605_REG_FEEDBACK,
comm->readRegister(DRV2605_REG_FEEDBACK) & 0x7F);
// turn on ERM_OPEN_LOOP
comm->writeRegister(DRV2605_REG_CONTROL3,
comm->readRegister(DRV2605_REG_CONTROL3) | 0x20);
return true;
}
protected:
std::unique_ptr<SensorCommBase> comm;
};

View File

@@ -0,0 +1,355 @@
/**
*
* @license MIT License
*
* Copyright (c) 2023 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file SensorLTR553ALS.hpp
* @author Lewis He (lewishe@outlook.com)
* @date 2023-09-09
*
*/
#pragma once
#include "REG/LTR533Constants.h"
#include "SensorPlatform.hpp"
class SensorLTR553 : public LTR553Constants
{
public:
enum IrqLevel {
ALS_IRQ_ACTIVE_LOW, // INT pin is considered active when it is a logic 0 (default)
ALS_IRQ_ACTIVE_HIGH // INT pin is considered active when it is a logic 1
};
enum IrqMode {
ALS_IRQ_ONLY_PS = 1, // Only PS measurement can trigger interrupt
ALS_IRQ_ONLY_ALS, // Only ALS measurement can trigger interrupt
ALS_IRQ_BOTH, // Both ALS and PS measurement can trigger interrupt
};
enum LightSensorGain {
ALS_GAIN_1X = 0x00, // 1 lux to 64k lux (default)
ALS_GAIN_2X = 0x01, // 0.5 lux to 32k lux
ALS_GAIN_4X = 0x02, // 0.25 lux to 16k lux
ALS_GAIN_8X = 0x03, // 0.125 lux to 8k lux
ALS_GAIN_48X = 0x06, // 0.02 lux to 1.3k lux
ALS_GAIN_96X = 0x07, // 0.01 lux to 600 lux
};
enum PsLedPeriod {
PS_LED_PLUSE_30KHZ = 0x00,
PS_LED_PLUSE_40KHZ,
PS_LED_PLUSE_50KHZ,
PS_LED_PLUSE_60KHZ,
PS_LED_PLUSE_70KHZ,
PS_LED_PLUSE_80KHZ,
PS_LED_PLUSE_90KHZ,
PS_LED_PLUSE_100KHZ,
};
enum PsLedDuty {
PS_LED_DUTY_25 = 0x00,
PS_LED_DUTY_50,
PS_LED_DUTY_75,
PS_LED_DUTY_100,
};
enum PsLedCurrent {
PS_LED_CUR_5MA = 0x00,
PS_LED_CUR_10MA,
PS_LED_CUR_20MA,
PS_LED_CUR_50MA,
PS_LED_CUR_100MA,
};
enum PsRate {
PS_MEAS_RATE_50MS,
PS_MEAS_RATE_70MS,
PS_MEAS_RATE_100MS,
PS_MEAS_RATE_200MS,
PS_MEAS_RATE_500MS,
PS_MEAS_RATE_1000MS,
PS_MEAS_RATE_2000MS,
PS_MEAS_RATE_10MS = 8,
};
enum IntegrationTime {
ALS_INTEGRATION_TIME_100MS = 0x00,
ALS_INTEGRATION_TIME_50MS,
ALS_INTEGRATION_TIME_200MS,
ALS_INTEGRATION_TIME_400MS,
ALS_INTEGRATION_TIME_150MS,
ALS_INTEGRATION_TIME_250MS,
ALS_INTEGRATION_TIME_300MS,
ALS_INTEGRATION_TIME_350MS,
};
enum MeasurementRate {
ALS_MEASUREMENT_TIME_50MS,
ALS_MEASUREMENT_TIME_100MS,
ALS_MEASUREMENT_TIME_200MS,
ALS_MEASUREMENT_TIME_500MS,
ALS_MEASUREMENT_TIME_1000MS,
ALS_MEASUREMENT_TIME_2000MS,
};
SensorLTR553() : comm(nullptr) {}
~SensorLTR553()
{
if (comm) {
comm->deinit();
}
}
#if defined(ARDUINO)
bool begin(TwoWire &wire, int sda = -1, int scl = -1)
{
comm = std::make_unique<SensorCommI2C>(wire, LTR553_SLAVE_ADDRESS, sda, scl);
if (!comm) {
return false;
}
comm->init();
return initImpl();
}
#elif defined(ESP_PLATFORM)
#if defined(USEING_I2C_LEGACY)
bool begin(i2c_port_t port_num, int sda = -1, int scl = -1)
{
comm = std::make_unique<SensorCommI2C>(port_num, LTR553_SLAVE_ADDRESS, sda, scl);
if (!comm) {
return false;
}
comm->init();
return initImpl();
}
#else
bool begin(i2c_master_bus_handle_t handle)
{
comm = std::make_unique<SensorCommI2C>(handle, LTR553_SLAVE_ADDRESS);
if (!comm) {
return false;
}
comm->init();
return initImpl();
}
#endif //ESP_PLATFORM
#endif //ARDUINO
bool begin(SensorCommCustom::CustomCallback callback)
{
comm = std::make_unique<SensorCommCustom>(callback, LTR553_SLAVE_ADDRESS);
if (!comm) {
return false;
}
comm->init();
return initImpl();
}
void setIRQLevel(IrqLevel level)
{
level ? comm->setRegisterBit(REG_INTERRUPT, 2) : comm->clrRegisterBit(REG_INTERRUPT, 2);
}
void enableIRQ(IrqMode mode)
{
comm->writeRegister(REG_INTERRUPT, 0xFC, mode);
}
void disableIRQ()
{
comm->writeRegister(REG_INTERRUPT, 0xFC, 0x00);
}
//! Light Sensor !
bool psAvailable()
{
return comm->getRegisterBit(REG_ALS_PS_STATUS, 0);
}
void setLightSensorThreshold(uint16_t low, uint16_t high)
{
uint8_t buffer[4] = {lowByte(high), highByte(high),
lowByte(low), highByte(low)
};
comm->writeRegister(REG_ALS_THRES_UP_0, buffer, 4);
}
// Controls the N number of times the measurement data is outside the range
// defined by the upper and lower threshold limits before asserting the interrupt.
void setLightSensorPersists(uint8_t count)
{
comm->writeRegister(REG_INTERRUPT_PERSIST, 0xF0, count - 1);
}
void setLightSensorRate(IntegrationTime integrationTime, MeasurementRate measurementRate)
{
uint8_t value = (integrationTime & 0xF) << 8 | (measurementRate & 0xF);
comm->writeRegister(REG_ALS_MEAS_RATE, 0x00, value);
}
void enableLightSensor()
{
comm->setRegisterBit(REG_ALS_CONTR, 0);
}
void disableLightSensor()
{
comm->clrRegisterBit(REG_ALS_CONTR, 0);
}
void setLightSensorGain(LightSensorGain gain)
{
comm->writeRegister(REG_ALS_CONTR, 0xE3, gain << 2);
}
int getLightSensor(uint8_t ch)
{
uint8_t buffer[2] = {0};
// Check ALS Data is Valid
if (comm->getRegisterBit(REG_ALS_PS_STATUS, 7) != false) {
return 0;
}
int val = comm->readRegister(ch == 1 ? REG_ALS_DATA_CH1_0 : REG_ALS_DATA_CH0_0, buffer, 2);
if (val == -1) {
return -1;
}
return buffer[0] | (buffer[1] << 8);
}
//! Proximity sensor !
// Controls the N number of times the measurement data is outside the range
// defined by the upper and lower threshold limits before asserting the interrupt.
void setProximityPersists(uint8_t count)
{
comm->writeRegister(REG_INTERRUPT_PERSIST, 0x0F, count == 0 ? 0 : count - 1);
}
void setProximityThreshold(uint16_t low, uint16_t high)
{
comm->writeRegister(REG_PS_THRES_UP_0, lowByte(high));
comm->writeRegister(REG_PS_THRES_UP_1, lowByte(high >> 8) & 0x0F);
comm->writeRegister(REG_PS_THRES_LOW_0, lowByte(low));
comm->writeRegister(REG_PS_THRES_LOW_1, lowByte(low >> 8) & 0x0F);
}
void setProximityRate(PsRate rate)
{
comm->writeRegister(REG_PS_MEAS_RATE, 0xF0, rate & 0x0F);
}
void enableProximity()
{
comm->writeRegister(REG_PS_CONTR, 0xF3u, 0x03u);
}
void disableProximity()
{
comm->writeRegister(REG_PS_CONTR, 0xF3u, 0x00u);
}
void enablePsIndicator()
{
comm->setRegisterBit(REG_PS_CONTR, 5);
}
void disablePsIndicator()
{
comm->clrRegisterBit(REG_PS_CONTR, 5);
}
int getProximity(bool *saturated = NULL )
{
uint8_t buffer[2] = {0};
int val = comm->readRegister(REG_PS_DATA_0, buffer, 2);
if (val == -1) {
return -1;
}
if (saturated) {
*saturated = buffer[1] & 0x80;
}
return buffer[0] | (buffer[1] & 0x07);
}
void setPsLedPulsePeriod(PsLedPeriod period)
{
comm->writeRegister(REG_PS_LED, 0x1F, period);
}
void setPsLedDutyCycle(PsLedDuty duty)
{
comm->writeRegister(REG_PS_LED, 0xE7, duty);
}
void setPsLedCurrent(PsLedCurrent cur)
{
comm->writeRegister(REG_PS_LED, 0xF8, cur);
}
void setPsLedPulses(uint8_t pulesNum)
{
comm->writeRegister(REG_PS_N_PULSES, 0xF0, pulesNum & 0x0F);
}
int getPartID()
{
int val = comm->readRegister(REG_PART_ID);
if (val == -1) {
return -1;
}
return (val >> 4) & 0x0F;
}
int getRevisionID()
{
int val = comm->readRegister(REG_PART_ID);
if (val == -1) {
return -1;
}
return (val) & 0x0F;
}
int getManufacturerID()
{
// Manufacturer ID (0x05H)
return comm->readRegister(REG_MANUFAC_ID);
}
void reset()
{
comm->setRegisterBit(REG_ALS_CONTR, 1);
}
private:
bool initImpl()
{
I2CParam params(I2CParam::I2C_SET_FLAG, false);
comm->setParams(params);
reset();
return getManufacturerID() == LTR553_DEFAULT_MAN_ID;
}
protected:
std::unique_ptr<SensorCommBase> comm;
};

View File

@@ -0,0 +1,187 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file SensorLib.h
* @author Lewis He (lewishe@outlook.com)
* @date 2023-10-05
*/
#pragma once
#if defined(ARDUINO)
#include <Arduino.h>
#include <SPI.h>
#include <Wire.h>
#else
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#endif
#include "SensorLib_Version.h"
#include "DevicesPins.h"
#if !defined(ARDUINO_ARCH_MBED) && !defined(ARDUINO_ARCH_ZEPHYR)
#define PLATFORM_HAS_PRINTF
#endif
#if defined(ARDUINO_ARCH_RP2040) && !defined(ARDUINO_ARCH_MBED)
#define SPIClass SPIClassRP2040
#endif
#ifdef _BV
#undef _BV
#endif
#define _BV(b) (1UL << (uint32_t)(b))
#ifndef lowByte
#define lowByte(w) ((uint8_t) ((w) & 0xff))
#endif
#ifndef highByte
#define highByte(w) ((uint8_t) ((w) >> 8))
#endif
#ifndef bitRead
#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
#endif
#ifndef bitSet
#define bitSet(value, bit) ((value) |= (1UL << (bit)))
#endif
#ifndef bitClear
#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
#endif
#ifndef bitToggle
#define bitToggle(value, bit) ((value) ^= (1UL << (bit)))
#endif
#ifndef bitWrite
#define bitWrite(value, bit, bitvalue) ((bitvalue) ? bitSet(value, bit) : bitClear(value, bit))
#endif
#ifndef isBitSet
#define isBitSet(value, bit) (((value) & (1UL << (bit))) == (1UL << (bit)))
#endif
#define ATTR_NOT_IMPLEMENTED __attribute__((error("Not implemented")))
#if !defined(ARDUINO_ARCH_ESP32) && defined(LOG_PORT) && defined(ARDUINO) && !defined(ARDUINO_ARCH_MBED) && !defined(ARDUINO_ARCH_ZEPHYR)
#define LOG_FILE_LINE_INFO __FILE__, __LINE__
#ifndef log_e
#define log_e(fmt, ...) LOG_PORT.printf("[E][%s:%d] " fmt "\n", LOG_FILE_LINE_INFO, ##__VA_ARGS__)
#endif /*log_e*/
#ifndef log_i
#define log_i(fmt, ...) LOG_PORT.printf("[I][%s:%d] " fmt "\n", LOG_FILE_LINE_INFO, ##__VA_ARGS__)
#endif /*log_i*/
#ifndef log_d
#define log_d(fmt, ...) LOG_PORT.printf("[D][%s:%d] " fmt "\n", LOG_FILE_LINE_INFO, ##__VA_ARGS__)
#endif /*log_d*/
#elif defined(ARDUINO_ARCH_MBED) || defined(ARDUINO_ARCH_ZEPHYR)
#define LOG_FILE_LINE_INFO __FILE__, __LINE__
#ifndef log_e
#define log_e(fmt, ...) printf("[E][%s:%d] " fmt "\n", LOG_FILE_LINE_INFO, ##__VA_ARGS__)
#endif /*log_e*/
#ifndef log_i
#define log_i(fmt, ...) printf("[I][%s:%d] " fmt "\n", LOG_FILE_LINE_INFO, ##__VA_ARGS__)
#endif /*log_i*/
#ifndef log_d
#define log_d(fmt, ...) printf("[D][%s:%d] " fmt "\n", LOG_FILE_LINE_INFO, ##__VA_ARGS__)
#endif /*log_d*/
#elif defined(ESP_PLATFORM) && !defined(ARDUINO)
#include "esp_log.h"
#define ESP_TAG_LIB "SensorLib"
#if defined(__cplusplus) && (__cplusplus > 201703L)
#define log_e(format, ... ) ESP_LOG_LEVEL_LOCAL(ESP_LOG_ERROR, ESP_TAG_LIB, format __VA_OPT__(,) __VA_ARGS__)
#define log_w(format, ... ) ESP_LOG_LEVEL_LOCAL(ESP_LOG_WARN, ESP_TAG_LIB, format __VA_OPT__(,) __VA_ARGS__)
#define log_i(format, ... ) ESP_LOG_LEVEL_LOCAL(ESP_LOG_INFO, ESP_TAG_LIB, format __VA_OPT__(,) __VA_ARGS__)
#define log_d(format, ... ) ESP_LOG_LEVEL_LOCAL(ESP_LOG_DEBUG, ESP_TAG_LIB, format __VA_OPT__(,) __VA_ARGS__)
#define log_v(format, ... ) ESP_LOG_LEVEL_LOCAL(ESP_LOG_VERBOSE, ESP_TAG_LIB, format __VA_OPT__(,) __VA_ARGS__)
#else // !(defined(__cplusplus) && (__cplusplus > 201703L))
#define log_e(format, ... ) ESP_LOG_LEVEL_LOCAL(ESP_LOG_ERROR, ESP_TAG_LIB, format, ##__VA_ARGS__)
#define log_w(format, ... ) ESP_LOG_LEVEL_LOCAL(ESP_LOG_WARN, ESP_TAG_LIB, format, ##__VA_ARGS__)
#define log_i(format, ... ) ESP_LOG_LEVEL_LOCAL(ESP_LOG_INFO, ESP_TAG_LIB, format, ##__VA_ARGS__)
#define log_d(format, ... ) ESP_LOG_LEVEL_LOCAL(ESP_LOG_DEBUG, ESP_TAG_LIB, format, ##__VA_ARGS__)
#define log_v(format, ... ) ESP_LOG_LEVEL_LOCAL(ESP_LOG_VERBOSE, ESP_TAG_LIB, format, ##__VA_ARGS__)
#endif // !(defined(__cplusplus) && (__cplusplus > 201703L))
#else /*ESP_PLATFORM*/
#ifndef log_e
#define log_e(...)
#endif
#ifndef log_i
#define log_i(...)
#endif
#ifndef log_d
#define log_d(...)
#endif
#endif /*ARDUINO*/
#if !defined(ARDUINO) && defined(ESP_PLATFORM)
#ifndef INPUT
#define INPUT (0x0)
#endif
#ifndef OUTPUT
#define OUTPUT (0x1)
#endif
#ifndef RISING
#define RISING (0x01)
#endif
#ifndef FALLING
#define FALLING (0x02)
#endif
#ifndef LOW
#define LOW (0)
#endif
#ifndef HIGH
#define HIGH (1)
#endif
#endif

View File

@@ -0,0 +1,56 @@
/**
*
* @license MIT License
*
* Copyright (c) 2024 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file SensorLib_Version.h
* @author Lewis He (lewishe@outlook.com)
* @date 2024-12-12
*
*/
#pragma once
/** Major version number (X.x.x) */
#define SENSORLIB_VERSION_MAJOR 0
/** Minor version number (x.X.x) */
#define SENSORLIB_VERSION_MINOR 3
/** Patch version number (x.x.X) */
#define SENSORLIB_VERSION_PATCH 1
/**
* Macro to convert SENSORLIB version number into an integer
*
* To be used in comparisons, such as SENSORLIB_VERSION >= SENSORLIB_VERSION_VAL(2, 0, 0)
*/
#define SENSORLIB_VERSION_VAL(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
/**
* Current SENSORLIB version, as an integer
*
* To be used in comparisons, such as SENSORLIB_VERSION >= SENSORLIB_VERSION_VAL(2, 0, 0)
*/
#define SENSORLIB_VERSION SENSORLIB_VERSION_VAL(SENSORLIB_VERSION_MAJOR, \
SENSORLIB_VERSION_MINOR, \
SENSORLIB_VERSION_PATCH)
#define SENSORLIB_VERSION_STR "v0.3.0"

View File

@@ -0,0 +1,402 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file SensorPCF85063.hpp
* @author Lewis He (lewishe@outlook.com)
* @date 2023-09-07
*
*/
#pragma once
#include "REG/PCF85063Constants.h"
#include "SensorRTC.h"
#include "SensorPlatform.hpp"
class SensorPCF85063 : public SensorRTC, public PCF85063Constants
{
public:
using SensorRTC::setDateTime;
using SensorRTC::getDateTime;
enum ClockHz {
CLK_32768HZ = 0,
CLK_16384HZ,
CLK_8192HZ,
CLK_4096HZ,
CLK_2048HZ,
CLK_1024HZ,
CLK_1HZ,
CLK_LOW,
};
SensorPCF85063() : comm(nullptr) {}
~SensorPCF85063()
{
if (comm) {
comm->deinit();
}
}
#if defined(ARDUINO)
bool begin(TwoWire &wire, int sda = -1, int scl = -1)
{
comm = std::make_unique<SensorCommI2C>(wire, PCF85063_SLAVE_ADDRESS, sda, scl);
if (!comm) {
return false;
}
comm->init();
return initImpl();
}
#elif defined(ESP_PLATFORM)
#if defined(USEING_I2C_LEGACY)
bool begin(i2c_port_t port_num, int sda = -1, int scl = -1)
{
comm = std::make_unique<SensorCommI2C>(port_num, PCF85063_SLAVE_ADDRESS, sda, scl);
if (!comm) {
return false;
}
comm->init();
return initImpl();
}
#else
bool begin(i2c_master_bus_handle_t handle)
{
comm = std::make_unique<SensorCommI2C>(handle, PCF85063_SLAVE_ADDRESS);
if (!comm) {
return false;
}
comm->init();
return initImpl();
}
#endif //ESP_PLATFORM
#endif //ARDUINO
bool begin(SensorCommCustom::CustomCallback callback)
{
comm = std::make_unique<SensorCommCustom>(callback, PCF85063_SLAVE_ADDRESS);
if (!comm) {
return false;
}
comm->init();
return initImpl();
}
void setDateTime(RTC_DateTime datetime)
{
uint8_t buffer[7];
buffer[0] = DEC2BCD(datetime.getSecond()) & 0x7F;
buffer[1] = DEC2BCD(datetime.getMinute());
buffer[2] = DEC2BCD(datetime.getHour());
buffer[3] = DEC2BCD(datetime.getDay());
buffer[4] = getDayOfWeek(datetime.getDay(), datetime.getMonth(), datetime.getYear());
buffer[5] = DEC2BCD(datetime.getMonth());
buffer[6] = DEC2BCD(datetime.getYear() % 100);
comm->writeRegister(PCF85063_SEC_REG, buffer, 7);
}
RTC_DateTime getDateTime()
{
RTC_DateTime datetime;
uint8_t buffer[7];
uint8_t hour = 0;
comm->readRegister(PCF85063_SEC_REG, buffer, 7);
uint8_t second = BCD2DEC(buffer[0] & 0x7F);
uint8_t minute = BCD2DEC(buffer[1] & 0x7F);
if (is24Hour) {
hour = BCD2DEC(buffer[2] & 0x3F); // 24-hour mode
} else {
// datetime.AMPM = (buffer[2] & 0x20) == 0x20 ? 'A' : 'P';
hour = BCD2DEC(buffer[2] & 0x1F); // 12-hour mode
}
uint8_t day = BCD2DEC(buffer[3] & 0x3F);
uint8_t week = BCD2DEC(buffer[4] & 0x07);
uint8_t month = BCD2DEC(buffer[5] & 0x1F);
uint16_t year = BCD2DEC(buffer[6]) + 2000;
return RTC_DateTime(year, month, day, hour, minute, second, week);
}
bool isClockIntegrityGuaranteed()
{
return comm->getRegisterBit(PCF85063_SEC_REG, 7) == 0;
}
/*
Default use 24H mode
bool is24HourMode()
{
return is24Hour;
}
bool is12HourMode()
{
return !is24Hour;
}
void set24Hour()
{
is24Hour = true;
comm->clrRegisterBit(PCF85063_CTRL1_REG, 1);
}
void set12Hour()
{
is24Hour = false;
comm->setRegisterBit(PCF85063_CTRL1_REG, 1);
}
*/
void stop()
{
comm->setRegisterBit(PCF85063_CTRL1_REG, 5);
}
void start()
{
comm->clrRegisterBit(PCF85063_CTRL1_REG, 5);
}
bool isRunning()
{
return !comm->getRegisterBit(PCF85063_CTRL1_REG, 5);
}
void enableAlarm()
{
comm->setRegisterBit(PCF85063_CTRL2_REG, 7);
}
void disableAlarm()
{
comm->clrRegisterBit(PCF85063_CTRL2_REG, 7);
}
void resetAlarm()
{
comm->clrRegisterBit(PCF85063_CTRL2_REG, 6);
}
bool isAlarmActive()
{
return comm->getRegisterBit(PCF85063_CTRL2_REG, 6);
}
RTC_Alarm getAlarm()
{
uint8_t buffer[5];
comm->readRegister(PCF85063_ALRM_MIN_REG, buffer, 5);
buffer[0] = BCD2DEC(buffer[0] & 0x80); //second
buffer[1] = BCD2DEC(buffer[1] & 0x40); //minute
buffer[2] = BCD2DEC(buffer[2] & 0x40); //hour
buffer[3] = BCD2DEC(buffer[3] & 0x08); //day
buffer[4] = BCD2DEC(buffer[4] & 0x08); //weekday
return RTC_Alarm(buffer[2], buffer[1], buffer[0], buffer[3], buffer[4]);
}
void setAlarm(RTC_Alarm alarm)
{
setAlarm(alarm.getHour(), alarm.getMinute(), alarm.getSecond(),
alarm.getDay(), alarm.getWeek());
}
void setAlarm(uint8_t hour, uint8_t minute, uint8_t second, uint8_t day, uint8_t week)
{
uint8_t buffer[5] = {0};
RTC_DateTime datetime = getDateTime();
uint8_t daysInMonth = getDaysInMonth(datetime.getMonth(), datetime.getYear());
if (second != PCF85063_NO_ALARM) {
if (second > 59) {
second = 59;
}
buffer[0] = DEC2BCD(second);
buffer[0] &= ~PCF85063_ALARM_ENABLE;
} else {
buffer[0] = PCF85063_ALARM_ENABLE;
}
if (minute != PCF85063_NO_ALARM) {
if (minute > 59) {
minute = 59;
}
buffer[1] = DEC2BCD(minute);
buffer[1] &= ~PCF85063_ALARM_ENABLE;
} else {
buffer[1] = PCF85063_ALARM_ENABLE;
}
if (hour != PCF85063_NO_ALARM) {
if (is24Hour) {
if (hour > 23) {
hour = 23;
}
buffer[2] = DEC2BCD(hour);
buffer[2] &= ~PCF85063_ALARM_ENABLE;
} else {
/*
if (hour > 12) {
hour = 12;
}
buffer[2] = DEC2BCD(hour);
buffer[2] |= isAM ? 0 : _BV(5);
buffer[2] &= ~PCF85063_ALARM_ENABLE;
*/
}
} else {
buffer[2] = PCF85063_ALARM_ENABLE;
}
if (day != PCF85063_NO_ALARM) {
buffer[3] = DEC2BCD(((day) < (1) ? (1) : ((day) > (daysInMonth) ? (daysInMonth) : (day))));
buffer[3] &= ~PCF85063_ALARM_ENABLE;
} else {
buffer[3] = PCF85063_ALARM_ENABLE;
}
if (week != PCF85063_NO_ALARM) {
if (week > 6) {
week = 6;
}
buffer[4] = DEC2BCD(week);
buffer[4] &= ~PCF85063_ALARM_ENABLE;
} else {
buffer[4] = PCF85063_ALARM_ENABLE;
}
comm->writeRegister(PCF85063_ALRM_SEC_REG, buffer, 4);
}
void setAlarmByHours(uint8_t hour)
{
setAlarm(hour,
PCF85063_NO_ALARM,
PCF85063_NO_ALARM,
PCF85063_NO_ALARM,
PCF85063_NO_ALARM);
}
void setAlarmBySecond(uint8_t second)
{
setAlarm(PCF85063_NO_ALARM,
PCF85063_NO_ALARM,
second,
PCF85063_NO_ALARM,
PCF85063_NO_ALARM);
}
void setAlarmByMinutes(uint8_t minute)
{
setAlarm(PCF85063_NO_ALARM,
minute,
PCF85063_NO_ALARM,
PCF85063_NO_ALARM,
PCF85063_NO_ALARM);
}
void setAlarmByDays(uint8_t day)
{
setAlarm(PCF85063_NO_ALARM,
PCF85063_NO_ALARM,
PCF85063_NO_ALARM,
day,
PCF85063_NO_ALARM);
}
void setAlarmByWeekDay(uint8_t week)
{
setAlarm(PCF85063_NO_ALARM,
PCF85063_NO_ALARM,
PCF85063_NO_ALARM,
PCF85063_NO_ALARM,
week);
}
void setClockOutput(ClockHz hz)
{
int val = comm->readRegister(PCF85063_CTRL2_REG);
if (val == -1)return;
val &= 0xF8;
val |= hz;
comm->writeRegister(PCF85063_CTRL2_REG, val);
}
const char *getChipName()
{
return "PCF85063";
}
private:
bool initImpl()
{
//Check device is online
int val = comm->readRegister(PCF85063_RAM_REG);
if (val < 0) {
log_e("Device is offline!");
return false;
}
// Read the contents of a RAM register
uint8_t tmp = comm->readRegister(PCF85063_RAM_REG);
bool rlst = false;
// By judging whether the highest bit of the RAM register can be changed,
// it can be judged whether it belongs to PCF85063
comm->writeRegister(PCF85063_RAM_REG, val | _BV(7));
val = comm->readRegister(PCF85063_RAM_REG);
if (val & 0x80) {
comm->writeRegister(PCF85063_RAM_REG, val & ~_BV(7));
val = comm->readRegister(PCF85063_RAM_REG);
if ((val & 0x80) == 0) {
rlst = true;
}
}
if (!rlst) {
log_e("Failed to write to RAM memory register. Maybe this chip is pcf8563.");
return false;
}
// Restore the contents of the RAM registers
comm->writeRegister(PCF85063_RAM_REG, tmp);
//Default use 24-hour mode
is24Hour = !comm->getRegisterBit(PCF85063_CTRL1_REG, 1);
if (!is24Hour) {
// Set 24H Mode
comm->clrRegisterBit(PCF85063_CTRL1_REG, 1);
is24Hour = true;
}
//Turn on RTC
start();
return isRunning();
}
protected:
std::unique_ptr<SensorCommBase> comm;
bool is24Hour;
};

View File

@@ -0,0 +1,325 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file SensorPCF8563.hpp
* @author Lewis He (lewishe@outlook.com)
* @date 2022-12-09
*
*/
#pragma once
#include "REG/PCF8563Constants.h"
#include "SensorRTC.h"
#include "SensorPlatform.hpp"
class SensorPCF8563 : public SensorRTC, public PCF8563Constants
{
public:
using SensorRTC::setDateTime;
using SensorRTC::getDateTime;
enum ClockHz {
CLK_32768HZ,
CLK_1024HZ,
CLK_32HZ,
CLK_1HZ,
CLK_DISABLE,
};
SensorPCF8563() : comm(nullptr) {}
~SensorPCF8563()
{
if (comm) {
comm->deinit();
}
}
#if defined(ARDUINO)
bool begin(TwoWire &wire, int sda = -1, int scl = -1)
{
comm = std::make_unique<SensorCommI2C>(wire, PCF8563_SLAVE_ADDRESS, sda, scl);
if (!comm) {
return false;
}
comm->init();
return initImpl();
}
#elif defined(ESP_PLATFORM)
#if defined(USEING_I2C_LEGACY)
bool begin(i2c_port_t port_num, int sda = -1, int scl = -1)
{
comm = std::make_unique<SensorCommI2C>(port_num, PCF8563_SLAVE_ADDRESS, sda, scl);
if (!comm) {
return false;
}
comm->init();
return initImpl();
}
#else
bool begin(i2c_master_bus_handle_t handle)
{
comm = std::make_unique<SensorCommI2C>(handle, PCF8563_SLAVE_ADDRESS);
if (!comm) {
return false;
}
comm->init();
return initImpl();
}
#endif //ESP_PLATFORM
#endif //ARDUINO
bool begin(SensorCommCustom::CustomCallback callback)
{
comm = std::make_unique<SensorCommCustom>(callback, PCF8563_SLAVE_ADDRESS);
if (!comm) {
return false;
}
comm->init();
return initImpl();
}
void setDateTime(RTC_DateTime datetime)
{
uint8_t buffer[7];
buffer[0] = DEC2BCD(datetime.getSecond()) & 0x7F;
buffer[1] = DEC2BCD(datetime.getMinute());
buffer[2] = DEC2BCD(datetime.getHour());
buffer[3] = DEC2BCD(datetime.getDay());
buffer[4] = getDayOfWeek(datetime.getDay(), datetime.getMonth(), datetime.getYear());
buffer[5] = DEC2BCD(datetime.getMonth());
buffer[6] = DEC2BCD(datetime.getYear() % 100);
if ((2000 % datetime.getYear()) == 2000) {
buffer[5] &= 0x7F;
} else {
buffer[5] |= 0x80;
}
comm->writeRegister(SEC_REG, buffer, 7);
}
RTC_DateTime getDateTime()
{
uint8_t buffer[7];
comm->readRegister(SEC_REG, buffer, 7);
uint8_t second = BCD2DEC(buffer[0] & 0x7F);
uint8_t minute = BCD2DEC(buffer[1] & 0x7F);
uint8_t hour = BCD2DEC(buffer[2] & 0x3F);
uint8_t day = BCD2DEC(buffer[3] & 0x3F);
uint8_t week = BCD2DEC(buffer[4] & 0x07);
uint8_t month = BCD2DEC(buffer[5] & 0x1F);
uint16_t year = BCD2DEC(buffer[6]);
//century : 0 = 1900 , 1 = 2000
year += (buffer[5] & CENTURY_MASK) ? 1900 : 2000;
return RTC_DateTime(year, month, day, hour, minute, second, week);
}
bool isClockIntegrityGuaranteed()
{
return comm->getRegisterBit(SEC_REG, 7) == 0;
}
RTC_Alarm getAlarm()
{
uint8_t buffer[4];
comm->readRegister(ALRM_MIN_REG, buffer, 4);
buffer[0] = BCD2DEC(buffer[0] & 0x80); //minute
buffer[1] = BCD2DEC(buffer[1] & 0x40); //hour
buffer[2] = BCD2DEC(buffer[2] & 0x40); //day
buffer[3] = BCD2DEC(buffer[3] & 0x08); //weekday
// RTC_Alarm(uint8_t hour, uint8_t minute, uint8_t second, uint8_t day, uint8_t week)
return RTC_Alarm(buffer[1], buffer[0], 0, buffer[2], buffer[3]);
}
void enableAlarm()
{
comm->setRegisterBit(STAT2_REG, 1);
}
void disableAlarm()
{
comm->clrRegisterBit(STAT2_REG, 1);
}
void resetAlarm()
{
comm->clrRegisterBit(STAT2_REG, 3);
}
bool isAlarmActive()
{
return comm->getRegisterBit(STAT2_REG, 3);
}
void setAlarm(RTC_Alarm alarm)
{
setAlarm( alarm.getHour(), alarm.getMinute(), alarm.getDay(), alarm.getWeek());
}
void setAlarm(uint8_t hour, uint8_t minute, uint8_t day, uint8_t week)
{
uint8_t buffer[4] = {0};
RTC_DateTime datetime = getDateTime();
uint8_t daysInMonth = getDaysInMonth(datetime.getMonth(), datetime.getYear());
if (minute != NO_ALARM) {
if (minute > 59) {
minute = 59;
}
buffer[0] = DEC2BCD(minute);
buffer[0] &= ~ALARM_ENABLE;
} else {
buffer[0] = ALARM_ENABLE;
}
if (hour != NO_ALARM) {
if (hour > 23) {
hour = 23;
}
buffer[1] = DEC2BCD(hour);
buffer[1] &= ~ALARM_ENABLE;
} else {
buffer[1] = ALARM_ENABLE;
}
if (day != NO_ALARM) {
buffer[2] = DEC2BCD(((day) < (1) ? (1) : ((day) > (daysInMonth) ? (daysInMonth) : (day))));
buffer[2] &= ~ALARM_ENABLE;
} else {
buffer[2] = ALARM_ENABLE;
}
if (week != NO_ALARM) {
if (week > 6) {
week = 6;
}
buffer[3] = DEC2BCD(week);
buffer[3] &= ~ALARM_ENABLE;
} else {
buffer[3] = ALARM_ENABLE;
}
comm->writeRegister(ALRM_MIN_REG, buffer, 4);
}
void setAlarmByMinutes(uint8_t minute)
{
setAlarm(NO_ALARM, minute, NO_ALARM, NO_ALARM);
}
void setAlarmByDays(uint8_t day)
{
setAlarm(NO_ALARM, NO_ALARM, day, NO_ALARM);
}
void setAlarmByHours(uint8_t hour)
{
setAlarm(hour, NO_ALARM, NO_ALARM, NO_ALARM);
}
void setAlarmByWeekDay(uint8_t week)
{
setAlarm(NO_ALARM, NO_ALARM, NO_ALARM, week);
}
bool isCountdownTimerEnable()
{
uint8_t buffer[2];
buffer[0] = comm->readRegister(STAT2_REG);
buffer[1] = comm->readRegister(TIMER1_REG);
if (buffer[0] & TIMER_TIE) {
return buffer[1] & TIMER_TE ? true : false;
}
return false;
}
bool isCountdownTimerActive()
{
return comm->getRegisterBit(STAT2_REG, 2);
}
void enableCountdownTimer()
{
comm->setRegisterBit(STAT2_REG, 0);
}
void disableCountdownTimer()
{
comm->clrRegisterBit(STAT2_REG, 0);
}
void setCountdownTimer(uint8_t val, uint8_t freq)
{
uint8_t buffer[3];
buffer[1] = comm->readRegister(TIMER1_REG);
buffer[1] |= (freq & TIMER_TD10);
buffer[2] = val;
comm->writeRegister(TIMER1_REG, buffer[1]);
comm->writeRegister(TIMER2_REG, buffer[2]);
}
void clearCountdownTimer()
{
uint8_t val;
val = comm->readRegister(STAT2_REG);
val &= ~(TIMER_TF | TIMER_TIE);
val |= ALARM_AF;
comm->writeRegister(STAT2_REG, val);
comm->writeRegister(TIMER1_REG, (uint8_t)0x00);
}
void setClockOutput(ClockHz freq)
{
if (freq == CLK_DISABLE) {
comm->clrRegisterBit(SQW_REG, 7);
} else {
comm->writeRegister(SQW_REG, freq | CLK_ENABLE);
}
}
const char *getChipName()
{
return "PCF8563";
}
private:
bool initImpl()
{
//Check device is online
int ret = comm->readRegister(SEC_REG);
if (ret < 0) {
return false;
}
if (BCD2DEC(ret & 0x7F) > 59) {
return false;
}
return true;
}
protected:
std::unique_ptr<SensorCommBase> comm;
};

View File

@@ -0,0 +1,116 @@
/**
*
* @license MIT License
*
* Copyright (c) 2025 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file SensorPlatform.hpp
* @author Lewis He (lewishe@outlook.com)
* @date 2025-01-18
*
*/
#pragma once
#if defined(ARDUINO)
#include "platform/arduino/SensorCommArduino_HW.hpp"
#include "platform/arduino/SensorCommArduino_I2C.hpp"
#include "platform/arduino/SensorCommArduino_SPI.hpp"
#elif !defined(ARDUINO) && defined(ESP_PLATFORM)
#include "platform/espidf/SensorCommEspIDF_HW.hpp"
#include "platform/espidf/SensorCommEspIDF_I2C.hpp"
#include "platform/espidf/SensorCommEspIDF_SPI.hpp"
#endif
#include "platform/SensorCommCustom.hpp"
#include "platform/SensorCommCustomHal.hpp"
#include "platform/SensorCommDebug.hpp"
#include "platform/SensorCommStatic.hpp"
enum CommInterface {
COMM_CUSTOM = 0,
COMM_SPI = 1,
COMM_I2C = 2
};
template<typename CommType, typename HalType, typename... Args>
bool beginCommonStatic(
std::unique_ptr<SensorCommBase> &comm,
std::unique_ptr<SensorCommStatic> &staticComm,
std::unique_ptr<SensorHal> &hal,
Args &&... args)
{
hal = std::make_unique<HalType>();
if (!hal) {
return false;
}
comm = std::make_unique<CommType>(std::forward<Args>(args)..., hal.get());
if (!comm) {
hal.reset();
return false;
}
if (!comm->init()) {
log_e("Bus init failed!");
return false;
}
staticComm = std::make_unique<SensorCommStatic>(comm.get(), hal.get());
if (!staticComm) {
return false;
}
return true;
}
template<typename CommType, typename HalType, typename... Args>
bool beginCommon(
std::unique_ptr<SensorCommBase> &comm,
std::unique_ptr<SensorHal> &hal,
Args &&... args)
{
hal = std::make_unique<HalType>();
if (!hal) {
return false;
}
comm = std::make_unique<CommType>(std::forward<Args>(args)..., hal.get());
if (!comm) {
hal.reset();
return false;
}
comm->init();
return true;
}
template <typename CommType, typename HalType>
bool beginCommCustomCallback(CommInterface interface,
typename CommType::CustomCallback callback,
typename HalType::CustomHalCallback hal_callback,
uint8_t addr,
std::unique_ptr<SensorCommBase> &comm,
std::unique_ptr<SensorHal> &hal)
{
hal = std::make_unique<HalType>(hal_callback);
if (!hal) {
return false;
}
comm = std::make_unique<CommType>(callback, addr);
if (!comm) {
return false;
}
comm->init();
return true;
}

View File

@@ -0,0 +1,394 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file SensorQMC6310.hpp
* @author Lewis He (lewishe@outlook.com)
* @date 2022-10-16
*
*/
#pragma once
#include "REG/QMC6310Constants.h"
#include "SensorPlatform.hpp"
static constexpr uint8_t QMC6310U_SLAVE_ADDRESS = 0x1C;
static constexpr uint8_t QMC6310N_SLAVE_ADDRESS = 0x3C;
class Polar
{
public:
Polar(): polar(0), Gauss(0), uT(0) {}
Polar(float polar, float Gauss, float uT): polar(polar), Gauss(Gauss), uT(uT) {}
float polar;
float Gauss;
float uT;
};
class SensorQMC6310 : public QMC6310Constants
{
public:
enum SensorMode {
MODE_SUSPEND,
MODE_NORMAL,
MODE_SINGLE,
MODE_CONTINUOUS,
};
// Unit:Gauss
enum MagRange {
RANGE_30G,
RANGE_12G,
RANGE_8G,
RANGE_2G,
};
enum OutputRate {
DATARATE_10HZ,
DATARATE_50HZ,
DATARATE_100HZ,
DATARATE_200HZ,
};
enum CtrlReg {
SET_RESET_ON,
SET_ONLY_ON,
SET_RESET_OFF,
};
enum OverSampleRatio {
OSR_8,
OSR_4,
OSR_2,
OSR_1,
};
enum DownSampleRatio {
DSR_1,
DSR_2,
DSR_4,
DSR_8,
};
SensorQMC6310() : comm(nullptr), hal(nullptr) {}
~SensorQMC6310()
{
if (comm) {
comm->deinit();
}
}
#if defined(ARDUINO)
bool begin(TwoWire &wire, uint8_t addr = QMC6310U_SLAVE_ADDRESS, int sda = -1, int scl = -1)
{
if (!beginCommon<SensorCommI2C, HalArduino>(comm, hal, wire, addr, sda, scl)) {
return false;
}
return initImpl();
}
#elif defined(ESP_PLATFORM)
#if defined(USEING_I2C_LEGACY)
bool begin(i2c_port_t port_num, uint8_t addr = QMC6310U_SLAVE_ADDRESS, int sda = -1, int scl = -1)
{
if (!beginCommon<SensorCommI2C, HalEspIDF>(comm, hal, port_num, addr, sda, scl)) {
return false;
}
return initImpl();
}
#else
bool begin(i2c_master_bus_handle_t handle, uint8_t addr = QMC6310U_SLAVE_ADDRESS)
{
if (!beginCommon<SensorCommI2C, HalEspIDF>(comm, hal, handle, addr, sda, scl)) {
return false;
}
return initImpl();
}
#endif
#endif
bool begin(SensorCommCustom::CustomCallback callback,
SensorCommCustomHal::CustomHalCallback hal_callback,
uint8_t addr = QMC6310U_SLAVE_ADDRESS)
{
if (!beginCommCustomCallback<SensorCommCustom, SensorCommCustomHal>(COMM_CUSTOM,
callback, hal_callback, addr, comm, hal)) {
return false;
}
return initImpl();
}
void reset()
{
comm->writeRegister(REG_CMD2, (uint8_t)0x80);
hal->delay(10);
comm->writeRegister(REG_CMD2, (uint8_t)0x00);
}
uint8_t getChipID()
{
return comm->readRegister(REG_CHIP_ID);
}
int getStatus()
{
return comm->readRegister(REG_STAT);
}
bool isDataReady()
{
if (comm->readRegister(REG_STAT) & 0x01) {
return true;
}
return false;
}
bool isDataOverflow()
{
if (comm->readRegister(REG_STAT) & 0x02) {
return true;
}
return false;
}
void setSelfTest(bool en)
{
en ? comm->setRegisterBit(REG_CMD2, 1)
: comm->clrRegisterBit(REG_CMD2, 1);
}
int setMode(SensorMode m)
{
return comm->writeRegister(REG_CMD1, 0xFC, m);
}
int setCtrlRegister(CtrlReg c)
{
return comm->writeRegister(REG_CMD2, 0xFC, c);
}
int setDataOutputRate(OutputRate odr)
{
return comm->writeRegister(REG_CMD1, 0xF3, (odr << 2));
}
int setOverSampleRate(OverSampleRatio osr)
{
return comm->writeRegister(REG_CMD1, 0xCF, (osr << 4));
}
int setDownSampleRate(DownSampleRatio dsr)
{
return comm->writeRegister(REG_CMD1, 0x3F, (dsr << 6));
}
// Define the sign for X Y and Z axis
int setSign(uint8_t x, uint8_t y, uint8_t z)
{
int sign = x + y * 2 + z * 4;
return comm->writeRegister(REG_SIGN, sign);
}
int configMagnetometer(SensorMode mode, MagRange range, OutputRate odr,
OverSampleRatio osr, DownSampleRatio dsr)
{
if (setMagRange(range) < 0) {
return -1;;
}
if (comm->writeRegister(REG_CMD1, 0xFC, mode) < 0) {
return -1;;
}
if (comm->writeRegister(REG_CMD1, 0xF3, (odr << 2)) < 0) {
return -1;;
}
if (comm->writeRegister(REG_CMD1, 0xCF, (osr << 4)) < 0) {
return -1;;
}
if (comm->writeRegister(REG_CMD1, 0x3F, (dsr << 6)) < 0) {
return -1;;
}
return 0;
}
int setMagRange(MagRange range)
{
switch (range) {
case RANGE_30G:
_sensitivity = 0.1;
break;
case RANGE_12G:
_sensitivity = 0.04;
break;
case RANGE_8G:
_sensitivity = 0.026;
break;
case RANGE_2G:
_sensitivity = 0.0066;
break;
default:
break;
}
return comm->writeRegister(REG_CMD2, 0xF3, (range << 2));
}
void setOffset(int x, int y, int z)
{
_x_offset = x; _y_offset = y; _z_offset = z;
}
int readData()
{
uint8_t buffer[6];
int16_t x, y, z;
if (comm->readRegister(REG_LSB_DX, buffer,
6) != -1) {
x = (int16_t)(buffer[1] << 8) | (buffer[0]);
y = (int16_t)(buffer[3] << 8) | (buffer[2]);
z = (int16_t)(buffer[5] << 8) | (buffer[4]);
if (x == 32767) {
x = -((65535 - x) + 1);
}
x = (x - _x_offset);
if (y == 32767) {
y = -((65535 - y) + 1);
}
y = (y - _y_offset);
if (z == 32767) {
z = -((65535 - z) + 1);
}
z = (z - _z_offset);
_raw[0] = x;
_raw[1] = y;
_raw[2] = z;
_mag[0] = (float)x * _sensitivity;
_mag[1] = (float)y * _sensitivity;
_mag[2] = (float)z * _sensitivity;
return 0;
}
return -1;;
}
void setDeclination(float dec)
{
_declination = dec;
}
bool readPolar(Polar &p)
{
if (isDataReady()) {
readData();
float x = getX();
float y = getY();
float z = getZ();
float angle = (atan2(x, -y) / PI) * 180.0 + _declination;
angle = _convertAngleToPositive(angle);
float magnitude = sqrt(x * x + y * y + z * z);
p = Polar(angle, magnitude * 100, magnitude);
return true;
}
return false;
}
int16_t getRawX()
{
return _raw[0];
}
int16_t getRawY()
{
return _raw[1];
}
int16_t getRawZ()
{
return _raw[2];
}
float getX()
{
return _mag[0];
}
float getY()
{
return _mag[1];
}
float getZ()
{
return _mag[2];
}
void getMag(float &x, float &y, float &z)
{
x = _mag[0];
y = _mag[1];
z = _mag[2];
}
void dumpCtrlRegister()
{
uint8_t buffer[2];
comm->readRegister(REG_CMD1, buffer, 2);
for (int i = 0; i < 2; ++i) {
log_d("CMD%d: 0x%02x", i + 1, buffer[i]);
}
}
private:
float _convertAngleToPositive(float angle)
{
if (angle >= 360.0) {
angle = angle - 360.0;
}
if (angle < 0) {
angle = angle + 360.0;
}
return angle;
}
bool initImpl()
{
reset();
return getChipID() == QMC6310_CHIP_ID;
}
protected:
std::unique_ptr<SensorCommBase> comm;
std::unique_ptr<SensorHal> hal;
int16_t _raw[3];
float _mag[3];
float _declination;
float _sensitivity;
int16_t _x_offset = 0, _y_offset = 0, _z_offset = 0;
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,703 @@
/**
*
* @license MIT License
*
* Copyright (c) 2023 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file SensorRTC.h
* @author Lewis He (lewishe@outlook.com)
* @date 2023-09-07
*
*/
#pragma once
#ifdef ARDUINO
#include <Arduino.h>
#else
#include <stdint.h>
#endif /*defined(ARDUINO)*/
#include <sys/time.h>
#include "SensorPlatform.hpp"
typedef enum {
DT_FMT_HM, // Format Style : Hour:Minute
DT_FMT_HMS, // Format Style : Hour:Minute:Second
DT_FMT_YMD, // Format Style : Year-Month-Day
DT_FMT_MDY, // Format Style : Month-Day-Year
DT_FMT_DMY, // Format Style : Day-Month-Year
DT_FMT_YMD_HMS, // Format Style : Year-Month-Day/Hour:Minute:Second
DT_FMT_YMD_HMS_WEEK // Format Style : Year-Month-Day/Hour:Minute:Second - Weekday
} DateTimeFormat;
class RTC_DateTime
{
enum Month {
JANUARY = 1,
FEBRUARY,
MARCH,
APRIL,
MAY,
JUNE,
JULY,
AUGUST,
SEPTEMBER,
OCTOBER,
NOVEMBER,
DECEMBER
};
public:
RTC_DateTime() : year(0), month(0), day(0), hour(0), minute(0), second(0), week(0) {}
RTC_DateTime(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second, uint8_t week = 0) :
year(year), month(month), day(day), hour(hour), minute(minute), second(second), week(week) {}
RTC_DateTime(struct tm info) : year(info.tm_year + 1900), month(info.tm_mon + 1), day(info.tm_mday),
hour(info.tm_hour), minute(info.tm_min), second(info.tm_sec), week(info.tm_wday) {}
RTC_DateTime(const char *date, const char *time)
{
if (date == nullptr || time == nullptr) {
year = 0;
month = 0;
day = 0;
hour = 0;
minute = 0;
second = 0;
week = 0;
return;
}
// sample input: date = "Dec 26 2009", time = "12:34:56"
year = 2000 + parseStringToUint8(date + 9);
switch (date[0]) {
case 'J':
if ( date[1] == 'a' )
month = JANUARY;
else if ( date[2] == 'n' )
month = JUNE;
else
month = JULY;
break;
case 'F':
month = FEBRUARY;
break;
case 'A':
month = date[1] == 'p' ? APRIL : AUGUST;
break;
case 'M':
month = date[2] == 'r' ? MARCH : MAY;
break;
case 'S':
month = SEPTEMBER;
break;
case 'O':
month = OCTOBER;
break;
case 'N':
month = NOVEMBER;
break;
case 'D':
month = DECEMBER;
break;
}
day = parseStringToUint8(date + 4);
hour = parseStringToUint8(time);
minute = parseStringToUint8(time + 3);
second = parseStringToUint8(time + 6);
}
bool operator==(RTC_DateTime d)
{
return ((d.year == year) && (d.month == month) && (d.day == day)
&& (d.hour == hour) && (d.minute == minute));
}
struct tm toUnixTime()
{
struct tm t_tm;
t_tm.tm_hour = hour;
t_tm.tm_min = minute;
t_tm.tm_sec = second;
t_tm.tm_year = year - 1900; //Year, whose value starts from 1900
t_tm.tm_mon = month - 1; //Month (starting from January, 0 for January) - Value range is [0,11]
t_tm.tm_mday = day;
t_tm.tm_wday = week;
return t_tm;
}
// *INDENT-OFF*
uint16_t getYear() const { return year; }
uint8_t getMonth() const { return month; }
uint8_t getDay() const { return day; }
uint8_t getHour() const { return hour; }
uint8_t getMinute() const { return minute; }
uint8_t getSecond() const { return second; }
uint8_t getWeek() const { return week; }
// char getAMPM() const { return AMPM; }
// bool isAvailable() const { return available; }
// *INDENT-ON*
private:
// *INDENT-OFF*
// void setAMPM(char ampm) { AMPM = ampm; }
// void setAvailable(bool avail) { available = avail; }
// *INDENT-ON*
uint16_t year;
uint8_t month;
uint8_t day;
uint8_t hour;
uint8_t minute;
uint8_t second;
uint8_t week;
// char AMPM;
// bool available;
uint8_t parseStringToUint8(const char *pString)
{
uint8_t value = 0;
// skip leading 0 and spaces
while ('0' == *pString || *pString == ' ') {
pString++;
}
// calculate number until we hit non-numeral char
while ('0' <= *pString && *pString <= '9') {
value *= 10;
value += *pString - '0';
pString++;
}
return value;
}
};
class RTC_Alarm
{
public:
RTC_Alarm(void): second(0), minute(0), hour(0), day(0), week(0) {}
RTC_Alarm(uint8_t hour, uint8_t minute, uint8_t second, uint8_t day, uint8_t week ) :
second(second), minute(minute), hour(hour), day(day), week(week) {}
// *INDENT-OFF*
uint8_t getDay() const { return day; }
uint8_t getHour() const { return hour; }
uint8_t getMinute() const { return minute; }
uint8_t getSecond() const { return second; }
uint8_t getWeek() const { return week; }
// *INDENT-ON*
private:
uint8_t second;
uint8_t minute;
uint8_t hour;
uint8_t day;
uint8_t week;
};
class SensorRTC
{
public:
#if defined(ARDUINO)
/**
* @brief Initialize the RTC device on the Arduino platform using I2C.
*
* This function is used to initialize the RTC device when the code is running on an Arduino platform.
* It takes an I2C bus object (`TwoWire`), and the pin numbers for the SDA (Serial Data Line) and SCL (Serial Clock Line)
* as parameters. The function attempts to establish communication with the RTC device over the specified I2C bus.
*
* @param wire A reference to the `TwoWire` object representing the I2C bus.
* @param sda The GPIO pin number used for the SDA line.
* @param scl The GPIO pin number used for the SCL line.
* @return `true` if the initialization is successful, `false` otherwise.
*/
virtual bool begin(TwoWire &wire, int sda, int scl) = 0;
#elif defined(ESP_PLATFORM)
#if defined(USEING_I2C_LEGACY)
/**
* @brief Initialize the RTC device on the ESP platform using legacy I2C.
*
* This function is used to initialize the RTC device when the code is running on an ESP platform
* and the legacy I2C interface is being used. It takes the I2C port number, and the pin numbers for
* the SDA and SCL lines as parameters. The function tries to set up communication with the RTC device
* using the specified I2C port and pins.
*
* @param port_num The I2C port number to use for communication.
* @param sda The GPIO pin number used for the SDA line.
* @param scl The GPIO pin number used for the SCL line.
* @return `true` if the initialization is successful, `false` otherwise.
*/
virtual bool begin(i2c_port_t port_num, int sda, int scl) = 0;
#else
/**
* @brief Initialize the RTC device on the ESP platform using an I2C master bus handle.
*
* This function is used to initialize the RTC device when the code is running on an ESP platform
* and an I2C master bus handle is provided. It takes the I2C master bus handle as a parameter
* and attempts to establish communication with the RTC device using this handle.
*
* @param handle The I2C master bus handle to use for communication.
* @return `true` if the initialization is successful, `false` otherwise.
*/
virtual bool begin(i2c_master_bus_handle_t handle) = 0;
#endif
#endif // defined(ARDUINO)
/**
* @brief Initialize the RTC device using a custom callback.
*
* This function allows for a custom way of initializing the RTC device. It takes a custom callback function
* as a parameter. The callback can be used to perform custom communication or configuration operations
* during the initialization process.
*
* @param callback A pointer to the custom callback function. The callback should follow the signature
* defined in `SensorCommCustom::CustomCallback`.
* @return `true` if the initialization is successful, `false` otherwise.
*/
virtual bool begin(SensorCommCustom::CustomCallback callback) = 0;
/**
* @brief Set the date and time of the RTC using an RTC_DateTime object.
*
* This is a pure virtual function that derived classes must implement.
* It allows setting the RTC's date and time using a single RTC_DateTime object.
*
* @param datetime An RTC_DateTime object containing the date and time information to set on the RTC.
*/
virtual void setDateTime(RTC_DateTime datetime) = 0;
/**
* @brief Get the current date and time from the RTC.
*
* This is a pure virtual function that derived classes must implement.
* It retrieves the current date and time from the RTC and returns them as an RTC_DateTime object.
*
* @return An RTC_DateTime object representing the current date and time of the RTC.
*/
virtual RTC_DateTime getDateTime() = 0;
/**
* @brief Get the name of the RTC chip.
*
* This is a pure virtual function that derived classes must implement.
* It returns a pointer to a null - terminated string representing the name of the RTC chip.
*
* @return A pointer to a constant character array containing the name of the RTC chip.
*/
virtual const char *getChipName() = 0;
/**
* @brief Retrieve the current date and time from the RTC (Real-Time Clock) and populate a struct tm object.
*
* This function fetches the current date and time information from the RTC device.
* It then fills the provided `struct tm` object with the corresponding values.
* The `struct tm` object is a standard C structure used to represent date and time components,
* such as year, month, day, hour, minute, and second.
*
* @param info A pointer to a `struct tm` object where the retrieved date and time information will be stored.
* This pointer must not be a null pointer
*
* @note The year value in the `struct tm` object is the number of years since 1900.
* The month value ranges from 0 (January) to 11 (December).
* The day value represents the day of the month, starting from 1.
* The hour value ranges from 0 to 23, the minute and second values range from 0 to 59.
*/
void getDateTime(struct tm*info)
{
if (!info)return;
RTC_DateTime datetime = getDateTime();
*info = datetime.toUnixTime();
}
/**
* @brief Set the date and time of the RTC using individual values.
* @param year The year to set on the RTC. It's usually a 16 - bit unsigned integer.
* @param month The month to set on the RTC, ranging from 1 (January) to 12 (December).
* @param day The day of the month to set on the RTC, ranging from 1 to 31, depending on the month and leap year.
* @param hour The hour to set on the RTC, ranging from 0 to 23.
* @param minute The minute to set on the RTC, ranging from 0 to 59.
* @param second The second to set on the RTC, ranging from 0 to 59.
*/
void setDateTime(uint16_t year, uint8_t month, uint8_t day,
uint8_t hour, uint8_t minute, uint8_t second)
{
setDateTime(RTC_DateTime(year, month, day, hour, minute, second));
}
/**
* @brief Format the current date and time according to the specified style.
*
* This function retrieves the current date and time from the RTC (Real-Time Clock)
* using the `getDateTime()` function. Then, it formats the date and time
* into a string based on the provided style. The result is stored in a static buffer
* and a pointer to this buffer is returned.
*
* @param style The format style for the date and time string. It should be one of the
* values defined in the `DateTimeFormat` enumeration. The default value
* is `DT_FMT_YMD_HMS_WEEK`, which represents the format "Year-Month-Day/Hour:Minute:Second - Weekday".
* @return A pointer to a static character array containing the formatted date and time string.
* Note that the buffer is static, so subsequent calls to this function will overwrite
* the previous result.
*/
const char *strftime(DateTimeFormat style = DT_FMT_YMD_HMS_WEEK)
{
const char *formatStr = NULL;
static char format[FORMAT_BUFFER_SIZE];
RTC_DateTime t = getDateTime();
switch (style) {
case DT_FMT_HM:
formatStr = "%02d:%02d";
break;
case DT_FMT_HMS:
formatStr = "%02d:%02d:%02d";
break;
case DT_FMT_YMD:
formatStr = "%d-%02d-%02d";
break;
case DT_FMT_MDY:
formatStr = "%02d-%02d-%d";
break;
case DT_FMT_DMY:
formatStr = "%02d-%02d-%d";
break;
case DT_FMT_YMD_HMS:
formatStr = "%d-%02d-%02d/%02d:%02d:%02d";
break;
case DT_FMT_YMD_HMS_WEEK:
formatStr = "%d-%02d-%02d/%02d:%02d:%02d - %s";
break;
default:
formatStr = "%02d:%02d";
break;
}
int result = formatDateTime(formatStr, format, FORMAT_BUFFER_SIZE, &t);
if (result < 0 || (size_t)result >= FORMAT_BUFFER_SIZE) {
format[0] = '\0';
}
return format;
}
/**
* @brief Read the time from the RTC (Real-Time Clock) and write it to the system clock.
*
* This function retrieves the current date and time from the RTC chip,
* converts it to a Unix timestamp, and then sets this timestamp as the system time
* on systems that support it (e.g., BSD systems).
*
* @param tz A pointer to a timezone structure specifying timezone information.
* In modern systems, this parameter is usually ignored and can be set to NULL.
* The default value of this parameter is NULL.
* @return On success, returns the Unix timestamp (in seconds) read from the RTC and converted;
* if the mktime call fails during the conversion process, returns -1;
* if the settimeofday call fails on a supported system, an error log is recorded,
* but the timestamp is still returned.
*/
time_t hwClockRead(const timezone *tz = NULL)
{
struct timeval val;
// Retrieve the date and time from the RTC chip and convert it to a struct tm structure
struct tm t_tm = getDateTime().toUnixTime();
// Convert the struct tm structure to a Unix timestamp
time_t timestamp = mktime(&t_tm);
// Check if the mktime conversion was successful
if (timestamp == -1) {
log_e("mktime failed");
return -1;
}
val.tv_sec = timestamp;
val.tv_usec = 0;
#if __BSD_VISIBLE
// On supported BSD systems, attempt to set the new time to the system clock
if (settimeofday(&val, tz) == -1) {
log_e("settimeofday failed");
}
#endif /*__BSD_VISIBLE*/
// Return the converted Unix timestamp
return val.tv_sec;
}
/**
* @brief Write the current system time to the RTC clock chip.
* @return If the system time is not obtained (time call) or the time is not converted (localtime_r call), it returns -1;
* If the time is successfully obtained, converted and set to the RTC chip, it returns 0
*/
int hwClockWrite()
{
time_t now;
struct tm info;
// Get the current system time as a Unix timestamp
now = time(NULL);
if (now == -1) {
log_e("time failed");
return -1;
}
if (localtime_r(&now, &info) == NULL) {
log_e("localtime_r failed");
return -1;
}
setDateTime(info);
return 0;
}
/**
* Calculate the day of the week for a given date using Zeller's congruence.
*
* @param day The day of the month (1 - 31).
* @param month The month of the year (1 - 12).
* @param year The year.
* @return The day of the week, where 0 represents Sunday, 1 represents Monday, ..., 6 represents Saturday.
* Returns 0xFF if the input date is invalid.
*/
uint32_t getDayOfWeek(uint32_t day, uint32_t month, uint32_t year)
{
if (day < 1 || day > 31 || month < 1 || month > 12) {
return 0xFF;
}
if (month < 3) {
month += 12;
year--;
}
// Evaluate the parts of Zeller's congruence formula
uint32_t part1 = day;
uint32_t part2 = ((month + 1) * 26) / 10;
uint32_t part3 = year;
uint32_t part4 = year / 4;
uint32_t part5 = 6 * (year / 100);
uint32_t part6 = year / 400;
uint32_t val = (part1 + part2 + part3 + part4 + part5 + part6) % 7;
if (val == 0) {
val = 7;
}
return val - 1;
}
/**
* Get the next month based on the current month.
*
* @param curMonth The current month (1 - 12).
* @return The next month (1 - 12). If the current month is 12, it returns 1.
*/
uint8_t getNextMonth(uint8_t curMonth)
{
return ((curMonth < 12u) ? (curMonth + 1u) : 1u);
}
/**
* Get the next year based on the current year.
*
* @param curYear The current year.
* @return The next year.
*/
uint16_t getNextYear(uint16_t curYear)
{
return (curYear + 1u);
}
/**
* Determine whether a given year is a leap year.
*
* @param year The year to check.
* @return 1 if the year is a leap year, 0 otherwise.
*/
uint32_t getLeapYear(uint32_t year)
{
uint32_t isDivisibleBy4 = (year % 4 == 0);
uint32_t isDivisibleBy100 = (year % 100 == 0);
uint32_t isDivisibleBy400 = (year % 400 == 0);
return (isDivisibleBy4 && !isDivisibleBy100) || isDivisibleBy400;
}
/**
* Get the number of days in a given month of a specific year, considering leap years.
*
* @param month The month (1 - 12).
* @param year The year.
* @return The number of days in the specified month of the given year.
*/
uint8_t getDaysInMonth(uint8_t month, uint16_t year)
{
constexpr uint8_t DAYS_IN_JANUARY = (31u);
constexpr uint8_t DAYS_IN_FEBRUARY = (28u);
constexpr uint8_t DAYS_IN_MARCH = (31u);
constexpr uint8_t DAYS_IN_APRIL = (30u);
constexpr uint8_t DAYS_IN_MAY = (31u);
constexpr uint8_t DAYS_IN_JUNE = (30u);
constexpr uint8_t DAYS_IN_JULY = (31u);
constexpr uint8_t DAYS_IN_AUGUST = (31u);
constexpr uint8_t DAYS_IN_SEPTEMBER = (30u);
constexpr uint8_t DAYS_IN_OCTOBER = (31u);
constexpr uint8_t DAYS_IN_NOVEMBER = (30u);
constexpr uint8_t DAYS_IN_DECEMBER = (31u);
const uint8_t daysInMonthTable[12] = {DAYS_IN_JANUARY,
DAYS_IN_FEBRUARY,
DAYS_IN_MARCH,
DAYS_IN_APRIL,
DAYS_IN_MAY,
DAYS_IN_JUNE,
DAYS_IN_JULY,
DAYS_IN_AUGUST,
DAYS_IN_SEPTEMBER,
DAYS_IN_OCTOBER,
DAYS_IN_NOVEMBER,
DAYS_IN_DECEMBER
};
uint8_t val = daysInMonthTable[month - 1u];
if (2 == month) {
if (0u != getLeapYear(year)) {
val++;
}
}
return val;
}
/**
* Convert UTC time represented by individual values to the time in the specified timezone.
*
* @param year: The year of the UTC time.
* @param month: The month of the UTC time (1 - 12).
* @param day: The day of the UTC time.
* @param hour: The hour of the UTC time (0 - 23).
* @param minute: The minute of the UTC time (0 - 59).
* @param second: The second of the UTC time (0 - 59).
* @param timezoneOffsetSeconds: The offset of the target timezone from UTC (in seconds).
*/
void convertUtcToTimezone(int &year, int &month, int &day, int &hour, int &minute, int &second, int timezoneOffsetSeconds)
{
if (year < 0 || month < 1 || month > 12 || day < 1 || day > getDaysInMonth(month, year) ||
hour < 0 || hour > 23 || minute < 0 || minute > 59 || second < 0 || second > 59) {
log_e("Invalid date or time input");
return;
}
int totalSeconds = hour * 3600 + minute * 60 + second;
totalSeconds += timezoneOffsetSeconds;
int daysOffset = totalSeconds / (24 * 3600);
totalSeconds %= (24 * 3600);
adjustDate(year, month, day, daysOffset);
if (totalSeconds < 0) {
totalSeconds += 24 * 3600;
adjustDate(year, month, day, -1);
}
hour = totalSeconds / 3600;
minute = (totalSeconds % 3600) / 60;
second = totalSeconds % 60;
}
/**
* Overloaded function to convert UTC time represented by a struct tm object to the time in the specified timezone.
*
* @param utcTime: A reference to the struct tm object representing UTC time.
* @param timezoneOffsetSeconds: The offset of the target timezone from UTC (in seconds).
*/
void convertUtcToTimezone(struct tm& utcTime, int timezoneOffsetSeconds)
{
int year = utcTime.tm_year + 1900;
int month = utcTime.tm_mon + 1;
int day = utcTime.tm_mday;
int hour = utcTime.tm_hour;
int minute = utcTime.tm_min;
int second = utcTime.tm_sec;
convertUtcToTimezone(year, month, day, hour, minute, second, timezoneOffsetSeconds);
utcTime.tm_year = year - 1900;
utcTime.tm_mon = month - 1;
utcTime.tm_mday = day;
utcTime.tm_hour = hour;
utcTime.tm_min = minute;
utcTime.tm_sec = second;
}
/**
* Convert a Binary Coded Decimal (BCD) number to a decimal number.
* @param val A uint8_t value representing a BCD number.
* @return The decimal equivalent of the input BCD number.
*/
uint8_t BCD2DEC(uint8_t val)
{
return ((val >> 4) * 10) + (val & 0x0F);
}
/**
* Convert a decimal number to a Binary Coded Decimal (BCD) number.
* @param val A uint8_t value representing a decimal number.
* @return The BCD equivalent of the input decimal number.
*/
uint8_t DEC2BCD(uint8_t val)
{
return ((val / 10) << 4) | (val % 10);
}
private:
static const size_t FORMAT_BUFFER_SIZE = 64;
void adjustDate(int &year, int &month, int &day, int daysOffset)
{
day += daysOffset;
while (day > getDaysInMonth(month, year)) {
day -= getDaysInMonth(month, year);
month++;
if (month > 12) {
year++;
month = 1;
}
}
while (day < 1) {
month--;
if (month < 1) {
year--;
month = 12;
}
day += getDaysInMonth(month, year);
}
}
int formatDateTime(const char *fmt, char *buffer, size_t bufferSize, const RTC_DateTime *t)
{
const char *weekString[] = {"Sun", "Mon", "Tue", "Wed", "Thur", "Fri", "Sat"};
if (!fmt || !buffer || bufferSize == 0 || !t) {
return -1;
}
return snprintf(buffer, bufferSize, fmt, t->getYear(), t->getMonth(), t->getDay(),
t->getHour(), t->getMinute(), t->getSecond(),
t->getWeek() > 6 ? weekString[0] : weekString[t->getWeek()]);
}
};

View File

@@ -0,0 +1,153 @@
/**
*
* @license MIT License
*
* Copyright (c) 2025 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file SensorRtcHelper.cpp
* @author Lewis He (lewishe@outlook.com)
* @date 2025-02-24
*
*/
#include "SensorRtcHelper.hpp"
SensorRtcHelper::DriverCreator SensorRtcHelper::driverCreators[SensorRtcHelper::driverCreatorMaxNum] = {
[]() -> std::unique_ptr<SensorRTC> { return std::make_unique<SensorPCF85063>(); },
[]() -> std::unique_ptr<SensorRTC> { return std::make_unique<SensorPCF8563>(); },
};
SensorRtcHelper::SensorRtcHelper() : _drvType(RtcDrv_UNKOWN), _drv(nullptr)
{
}
SensorRtcHelper::~SensorRtcHelper()
{
}
void SensorRtcHelper::setRtcDrvModel(SensorRTCType model)
{
_drvType = model;
}
#if defined(ARDUINO)
bool SensorRtcHelper::begin(TwoWire &wire, int sda, int scl)
{
bool success = false;
for (int i = (_drvType == RtcDrv_UNKOWN) ? 0 : _drvType; i < driverCreatorMaxNum; ++i) {
_drv = createDriver(static_cast<SensorRTCType>(i));
if (_drv && _drv->begin(wire, sda, scl)) {
_drvType = static_cast<SensorRTCType>(i);
success = true;
break;
}
}
if (!success) {
_drvType = RtcDrv_UNKOWN;
}
return success;
}
#elif defined(ESP_PLATFORM)
#if defined(USEING_I2C_LEGACY)
bool SensorRtcHelper::begin(i2c_port_t port_num, int sda, int scl)
{
bool success = false;
for (int i = (_drvType == RtcDrv_UNKOWN) ? 0 : _drvType; i < driverCreatorMaxNum; ++i) {
_drv = createDriver(static_cast<SensorRTCType>(i));
if (_drv && _drv->begin(port_num, sda, scl)) {
_drvType = static_cast<SensorRTCType>(i);
success = true;
break;
}
}
if (!success) {
_drvType = RtcDrv_UNKOWN;
}
return success;
}
#else
bool SensorRtcHelper::begin(i2c_master_bus_handle_t handle)
{
bool success = false;
for (int i = (_drvType == RtcDrv_UNKOWN) ? 0 : _drvType; i < driverCreatorMaxNum; ++i) {
_drv = createDriver(static_cast<SensorRTCType>(i));
if (_drv && _drv->begin(handle)) {
_drvType = static_cast<SensorRTCType>(i);
success = true;
break;
}
}
if (!success) {
_drvType = RtcDrv_UNKOWN;
}
return success;
}
#endif // ESP_PLATFORM
#endif // ARDUINO
bool SensorRtcHelper::begin(SensorCommCustom::CustomCallback callback)
{
bool success = false;
for (int i = (_drvType == RtcDrv_UNKOWN) ? 0 : _drvType; i < driverCreatorMaxNum; ++i) {
_drv = createDriver(static_cast<SensorRTCType>(i));
if (_drv && _drv->begin(callback)) {
_drvType = static_cast<SensorRTCType>(i);
success = true;
break;
}
}
if (!success) {
_drvType = RtcDrv_UNKOWN;
}
return success;
}
void SensorRtcHelper::setDateTime(RTC_DateTime datetime)
{
_drv->setDateTime(datetime);
}
RTC_DateTime SensorRtcHelper::getDateTime()
{
return _drv->getDateTime();
}
const char *SensorRtcHelper::getChipName()
{
return _drv->getChipName();
}
std::unique_ptr<SensorRTC> SensorRtcHelper::createDriver(SensorRTCType type)
{
if (type < sizeof(driverCreators) / sizeof(driverCreators[0])) {
return driverCreators[type]();
}
return nullptr;
}

View File

@@ -0,0 +1,200 @@
/**
*
* @license MIT License
*
* Copyright (c) 2025 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file SensorRtcHelper.hpp
* @author Lewis He (lewishe@outlook.com)
* @date 2025-02-24
* @note The SensorRtcHelper class supports automatic determination of the commonly
* used PCF8563 and PCF8503 real-time clock chips. There are some differences in the registers
* between the two. This class is added to facilitate switching between different chips without
* having to worry about the specific model used.
*/
#include "SensorPCF8563.hpp"
#include "SensorPCF85063.hpp"
/**
* @brief Enumeration of different RTC (Real-Time Clock) driver types.
*
* This enumeration defines the possible types of RTC drivers that can be used.
* Currently only supports NXP PCF85063 and PCF8563.
*/
typedef enum {
RtcDrv_UNKOWN, // Represents an unknown or unsupported RTC driver type.
RtcDrv_PCF85063, // Represents the PCF85063 RTC driver type.
RtcDrv_PCF8563, // Represents the PCF8563 RTC driver type.
} SensorRTCType;
class SensorRtcHelper: public SensorRTC
{
public:
using SensorRTC::setDateTime;
using SensorRTC::getDateTime;
SensorRtcHelper();
~SensorRtcHelper();
/**
* @brief Set the model of the RTC (real-time clock) driver.
*
* This method is used to specify the type of RTC driver model that the system should use.
* If not set, the chip type is automatically determined by register information by default.
*
* @param model An enumeration value of the SensorRTCType type, indicating a specific
* RTC driver model. Possible values include RtcDrv_UNKOWN (unknown model),
* RtcDrv_PCF85063 (PCF85063 model), RtcDrv_PCF8563 (PCF8563 model), etc.
*/
void setRtcDrvModel(SensorRTCType model);
#if defined(ARDUINO)
/**
* @brief Initialize the RTC driver for Arduino platform using I2C.
*
* This method initializes the RTC driver on the Arduino platform using the specified I2C bus,
* SDA (Serial Data Line), and SCL (Serial Clock Line) pins.
*
* @param wire A reference to the TwoWire object representing the I2C bus.
* @param sda The GPIO pin number for the SDA line. The default setting is -1, which does not initialize any GPIO.
* @param scl The GPIO pin number for the SCL line. The default setting is -1, which does not initialize any GPIO.
* @return true if the initialization is successful, false otherwise.
*/
bool begin(TwoWire &wire, int sda = -1, int scl = -1);
#elif defined(ESP_PLATFORM)
#if defined(USEING_I2C_LEGACY)
/**
* @brief Initialize the RTC driver for ESP platform using legacy I2C.
*
* This method initializes the RTC driver on the ESP platform using the legacy I2C interface.
* It takes the I2C port number, SDA, and SCL pin numbers as parameters.
*
* @param port_num The I2C port number to use.
* @param sda The GPIO pin number for the SDA line. The default setting is -1, which does not initialize any GPIO.
* @param scl The GPIO pin number for the SCL line. The default setting is -1, which does not initialize any GPIO.
* @return true if the initialization is successful, false otherwise.
*/
bool begin(i2c_port_t port_num, int sda, int scl);
#else
/**
* @brief Initialize the RTC driver for ESP platform using I2C master bus handle.
*
* This method initializes the RTC driver on the ESP platform using the provided I2C master bus handle.
*
* @param handle The I2C master bus handle to use.
* @return true if the initialization is successful, false otherwise.
*/
bool begin(i2c_master_bus_handle_t handle);
#endif //USEING_I2C_LEGACY
#endif // ESP_PLATFORM
/**
* @brief Initialize the RTC driver using a custom callback.
*
* This method allows the user to initialize the RTC driver using a custom callback function.
* The callback can be used to perform custom communication or configuration operations.
*
* @param callback A pointer to the custom callback function.
* @return true if the initialization is successful, false otherwise.
*/
bool begin(SensorCommCustom::CustomCallback callback);
/**
* @brief Set the date and time on the RTC device.
*
* This method sets the specified date and time on the RTC device.
*
* @param datetime An RTC_DateTime object containing the date and time to set.
*/
void setDateTime(RTC_DateTime datetime);
/**
* @brief Get the current date and time from the RTC device.
*
* This method retrieves the current date and time from the RTC device and returns it as an RTC_DateTime object.
*
* @return An RTC_DateTime object representing the current date and time.
*/
RTC_DateTime getDateTime();
/**
* @brief Get the name of the RTC chip.
* @return A pointer to a constant character array containing the name of the RTC chip.
*/
const char *getChipName();
private:
/**
* @brief Create a new RTC driver instance based on the specified type.
*
* This private method creates a new RTC driver instance of the specified type using the driver creators array.
*
* @param type The type of the RTC driver to create, as defined in the SensorRTCType enumeration.
* @return A unique pointer to the newly created SensorRTC object.
*/
std::unique_ptr<SensorRTC> createDriver(SensorRTCType type);
/**
* @brief Function pointer type for creating a SensorRTC object.
*
* This typedef defines a function pointer type that can be used to create a SensorRTC object.
* The function should return a unique pointer to a SensorRTC object.
*/
using DriverCreator = std::unique_ptr<SensorRTC> (*)();
/**
* @brief The maximum number of driver creators in the array.
*
* This constant defines the maximum number of driver creator functions that can be stored in the driverCreators array.
*/
static constexpr uint8_t driverCreatorMaxNum = 2;
/**
* @brief An array of driver creator functions.
*
* This static array stores function pointers to the driver creator functions.
* Each function can create a specific type of SensorRTC object.
*/
static DriverCreator driverCreators[driverCreatorMaxNum];
/**
* @brief The type of the currently used RTC driver.
*
* This member variable stores the type of the RTC driver that is currently in use,
* as defined in the SensorRTCType enumeration.
*/
SensorRTCType _drvType;
/**
* @brief A unique pointer to the RTC driver object.
*
* This member variable holds a unique pointer to the SensorRTC object that represents the RTC driver.
* It is used to interact with the RTC device.
*/
std::unique_ptr<SensorRTC> _drv;
};

View File

@@ -0,0 +1,130 @@
/**
*
* @license MIT License
*
* Copyright (c) 2023 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file SensorWireHelper.cpp
* @author Lewis He (lewishe@outlook.com)
* @date 2023-10-05
*
*/
#include "SensorWireHelper.h"
#if defined(ARDUINO)
// regdump does not call Wire.begin, you need to call it before using regdump
int SensorWireHelper::regdump(TwoWire &w, Stream &serial, uint8_t devAddr, uint8_t start, uint8_t length)
{
uint8_t *buffer = (uint8_t *)malloc(length);
if (!buffer) return -1;
w.beginTransmission(devAddr);
w.write(start);
if (w.endTransmission() != 0) {
free(buffer);
return -1;
}
size_t len = w.requestFrom(devAddr, length);
if (length != len) {
free(buffer);
return -1;
}
w.readBytes(buffer, length);
hexdump(buffer, length, serial);
free(buffer);
return 0;
}
void SensorWireHelper::dumpDevices(TwoWire &w, Stream &serial, int first, int last)
{
int i, j;
int ret;
serial.println(" 0 1 2 3 4 5 6 7 8 9 a b c d e f");
for (i = 0; i < 128; i += 16) {
if (i < 16) {
serial.print("0");
}
serial.print(i, HEX);
serial.print(": ");
for (j = 0; j < 16; j++) {
/* Skip unwanted addresses */
if (i + j < first || i + j > last) {
serial.print(" ");
continue;
}
w.beginTransmission(i + j);
ret = w.endTransmission();
if (ret != 0) {
serial.print("-- ");
} else {
if (i < 16) {
serial.print("0");
}
serial.print(i + j, HEX);
serial.print(" ");
}
}
serial.println();
}
}
void SensorWireHelper::hexdump(uint8_t *data, size_t len, Stream &serial)
{
size_t rem_len = len;
for (size_t i = 0; i < len; i += 16) {
char str[80];
snprintf(str, 80, "%07x ", i);
size_t line_len = 16;
if (rem_len < line_len) {
line_len = rem_len;
}
for (size_t j = 0; j < line_len; j++) {
snprintf(&str[8 + j * 3], 80, "%02x ", data[i + j]);
}
for (size_t j = line_len; j < 16; j++) {
snprintf(&str[8 + j * 3], 80, " ");
}
str[56] = '|';
str[57] = ' ';
for (size_t j = 0; j < line_len; j++) {
char c = data[i + j];
if ((c < ' ') || (c > '~')) {
c = '.';
}
snprintf(&str[58 + j], 80, "%c", c);
}
for (size_t j = line_len; j < 16; j++) {
snprintf(&str[58 + j], 80, " ");
}
serial.println(str);
rem_len -= 16;
}
}
#endif //ARDUINO

View File

@@ -0,0 +1,47 @@
/**
*
* @license MIT License
*
* Copyright (c) 2023 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file SensorWireHelper.h
* @author Lewis He (lewishe@outlook.com)
* @date 2023-09-10
*
*/
#pragma once
#if defined(ARDUINO)
#include <Arduino.h>
#include <Wire.h>
class SensorWireHelper
{
public:
// regdump,dumpDevices method does not call Wire.begin, you need to call it before using regdump or dumpDevices
static int regdump(TwoWire &w, Stream &serial, uint8_t devAddr, uint8_t start, uint8_t len);
static void dumpDevices(TwoWire &w, Stream &serial = Serial, int first = 0, int last = 127);
static void hexdump(uint8_t *data, size_t len, Stream &serial = Serial);
};
#endif /*ARDUINO*/

View File

@@ -0,0 +1,331 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file TouchDrvCHSC5816.hpp
* @author Lewis He (lewishe@outlook.com)
* @date 2023-04-12
*
*/
#pragma once
#include "REG/CHSC5816Constants.h"
#include "TouchDrvInterface.hpp"
#define CHSC5816_SLAVE_ADDRESS (0x2E)
class TouchDrvCHSC5816 : public TouchDrvInterface
{
typedef struct {
uint16_t fw_ver;
uint16_t checksum;
uint32_t sig;
uint32_t vid_pid;
uint16_t raw_offset;
uint16_t dif_offset;
} Header_t;
union PointReg {
struct {
uint8_t status;
uint8_t fingerNumber;
uint8_t x_l8;
uint8_t y_l8;
uint8_t z;
uint8_t x_h4: 4;
uint8_t y_h4: 4;
uint8_t id: 4;
uint8_t event: 4;
uint8_t p2;
} report;
unsigned char data[8];
};
public:
TouchDrvCHSC5816() : comm(nullptr), hal(nullptr) {}
~TouchDrvCHSC5816()
{
if (comm) {
comm->deinit();
}
}
#if defined(ARDUINO)
bool begin(TwoWire &wire, uint8_t addr = CHSC5816_SLAVE_ADDRESS, int sda = -1, int scl = -1)
{
if (!beginCommon<SensorCommI2C, HalArduino>(comm, hal, wire, addr, sda, scl)) {
return false;
}
return initImpl();
}
#elif defined(ESP_PLATFORM)
#if defined(USEING_I2C_LEGACY)
bool begin(i2c_port_t port_num, uint8_t addr = CHSC5816_SLAVE_ADDRESS, int sda = -1, int scl = -1)
{
if (!beginCommon<SensorCommI2C, HalEspIDF>(comm, hal, port_num, addr, sda, scl)) {
return false;
}
return initImpl();
}
#else
bool begin(i2c_master_bus_handle_t handle, uint8_t addr = CHSC5816_SLAVE_ADDRESS)
{
if (!beginCommon<SensorCommI2C, HalEspIDF>(comm, hal, handle, addr)) {
return false;
}
return initImpl();
}
#endif //ESP_PLATFORM
#endif //ARDUINO
bool begin(SensorCommCustom::CustomCallback callback,
SensorCommCustomHal::CustomHalCallback hal_callback,
uint8_t addr = CHSC5816_SLAVE_ADDRESS)
{
if (!beginCommCustomCallback<SensorCommCustom, SensorCommCustomHal>(COMM_CUSTOM,
callback, hal_callback, addr, comm, hal)) {
return false;
}
return initImpl();
}
void reset()
{
if (_rst != -1) {
hal->digitalWrite(_rst, LOW);
hal->delay(3);
hal->digitalWrite(_rst, HIGH);
hal->delay(5);
}
}
uint8_t getPoint(int16_t *x_array, int16_t *y_array, uint8_t get_point = 1)
{
PointReg touch;
uint8_t CHSC5816_REG_POINT[] = {0x20, 0x00, 0x00, 0x2c};
comm->writeThenRead(CHSC5816_REG_POINT, arraySize(CHSC5816_REG_POINT), touch.data, 8);
if (touch.report.status == 0xFF && touch.report.fingerNumber == 0) {
return 0;
}
if (x_array) {
*x_array = (unsigned int)(touch.report.x_h4 << 8) | touch.report.x_l8;
}
if (y_array) {
*y_array = (unsigned int)(touch.report.y_h4 << 8) | touch.report.y_l8;
}
updateXY(1, x_array, y_array);
return 1;
}
bool isPressed()
{
if (_irq != -1) {
return hal->digitalRead(_irq) == LOW;
}
return getPoint(NULL, NULL);
}
const char *getModelName()
{
return "CHSC5816";
}
//2uA
void sleep()
{
uint8_t CHSC5816_REG_SLEEP[] = {
0x20, 0x00, 0x00, 0x00, // CHSC5816_REG_CMD_BUFF
0xF8, 0x16, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xE9
};
comm->writeBuffer(CHSC5816_REG_SLEEP, arraySize(CHSC5816_REG_SLEEP));
}
void wakeup()
{
reset();
}
void idle()
{
uint8_t CHSC5816_REG_IDEL[] = {
0x20, 0x00, 0x00, 0x00, // CHSC5816_REG_CMD_BUFF
0x20, 0x16, 0x02, 0x00, 0xDB, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xE9
};
comm->writeBuffer(CHSC5816_REG_IDEL, arraySize(CHSC5816_REG_IDEL));
}
uint8_t getSupportTouchPoint()
{
return 1;
}
bool getResolution(int16_t *width, int16_t *height)
{
#if 0
//TODO: NEED TEST
uint8_t CHSC5816_REG_FW[] = {
0x20, 0x00, 0x00, 0x00, // CHSC5816_REG_CMD_BUFF
0xFC, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xe9
};
if (comm->writeThenRead(CHSC5816_REG_FW,
arraySize(CHSC5816_REG_FW),
CHSC5816_REG_FW,
arraySize(CHSC5816_REG_FW)) < 0) {
return false;
}
SensorLibDumpBuffer(CHSC5816_REG_FW, arraySize(CHSC5816_REG_FW));
int16_t res_w = (CHSC5816_REG_FW[2] << 8) | CHSC5816_REG_FW[3];
int16_t res_h = (CHSC5816_REG_FW[4] << 8) | CHSC5816_REG_FW[5];
if (width) {
*width = res_w;
}
if (height) {
*height = res_h;
}
return true;
#endif
return false;
}
void setGpioCallback(CustomMode mode_cb,
CustomWrite write_cb,
CustomRead read_cb)
{
SensorHalCustom::setCustomMode(mode_cb);
SensorHalCustom::setCustomWrite(write_cb);
SensorHalCustom::setCustomRead(read_cb);
}
private:
bool checkOnline()
{
Header_t first;
Header_t second;
memset(&second, 0, sizeof(Header_t));
memset(&first, 0, sizeof(Header_t));
// CHSC5816_REG_BOOT_STATE 0x20000018
uint8_t CHSC5816_REG_BOOT_STATE[] = {0x20, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00};
if (comm->writeBuffer(CHSC5816_REG_BOOT_STATE, arraySize(CHSC5816_REG_BOOT_STATE)) < 0) {
log_e("comm->writeBuffer clean boot state failed!\n");
return false;
}
reset();
for (int i = 0; i < 10; ++i) {
hal->delay(10);
// CHSC5816_REG_IMG_HEAD 0x20000014
uint8_t CHSC5816_REG_IMG_HEAD[] = {0x20, 0x00, 0x00, 0x14};
if (comm->writeThenRead(CHSC5816_REG_IMG_HEAD,
arraySize(CHSC5816_REG_IMG_HEAD),
(uint8_t *)&first,
sizeof(Header_t)) < 0) {
return false;
}
if (comm->writeThenRead(CHSC5816_REG_IMG_HEAD,
arraySize(CHSC5816_REG_IMG_HEAD),
(uint8_t *)&second,
sizeof(Header_t)) < 0) {
return false;
}
if (memcmp(&second, &first, sizeof(Header_t)) != 0 ) {
continue;
}
if (first.sig == CHSC5816_SIG_VALUE) {
return true;
}
}
return false;
}
bool initImpl()
{
if (_irq != -1) {
hal->pinMode(_irq, INPUT);
}
if (_rst != -1) {
hal->pinMode(_rst, OUTPUT);
}
reset();
if (checkOnline()) {
reset();
return true;
}
return false;
}
protected:
std::unique_ptr<SensorCommBase> comm;
std::unique_ptr<SensorHal> hal;
static constexpr uint32_t CHSC5816_SIG_VALUE = (0x43534843U);
};
// #define CHSC5816_REG_CMD_BUFF (0x20000000U)
// #define CHSC5816_REG_RSP_BUFF (0x20000000U)
// #define CHSC5816_REG_IMG_HEAD (0x20000014U)
// #define CHSC5816_REG_POINT (0x2000002CU)
// #define CHSC5816_REG_WR_BUFF (0x20002000U)
// #define CHSC5816_REG_RD_BUFF (0x20002400U)
// #define CHSC5816_REG_HOLD_MCU (0x40007000U)
// #define CHSC5816_REG_AUTO_FEED (0x40007010U)
// #define CHSC5816_REG_REMAP_MCU (0x40007000U)
// #define CHSC5816_REG_RELEASE_MCU (0x40007000U)
// #define CHSC5816_REG_BOOT_STATE (0x20000018U)
// #define CHSC5816_HOLD_MCU_VAL (0x12044000U)
// #define CHSC5816_AUTO_FEED_VAL (0x0000925aU)
// #define CHSC5816_REMAP_MCU_VAL (0x12044002U)
// #define CHSC5816_RELEASE_MCU_VAL (0x12044003U)
// #define CHSC5816_REG_VID_PID_BACKUP (40 * 1024 + 0x10U)
// /*ctp work staus*/
// #define CHSC5816_POINTING_WORK (0x00000000U)
// #define CHSC5816_READY_UPGRADE (1 << 1)
// #define CHSC5816_UPGRAD_RUNING (1 << 2)
// #define CHSC5816_SLFTEST_RUNING (1 << 3)
// #define CHSC5816_SUSPEND_GATE (1 << 16)
// #define CHSC5816_GUESTURE_GATE (1 << 17)
// #define CHSC5816_PROXIMITY_GATE (1 << 18)
// #define CHSC5816_GLOVE_GATE (1 << 19)
// #define CHSC5816_ORIENTATION_GATE (1 << 20)

View File

@@ -0,0 +1,269 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file TouchDrvCSTXXX.cpp
* @author Lewis He (lewishe@outlook.com)
* @date 2023-04-24
* @date last 2025-01-20
*
*/
#include "TouchDrvCSTXXX.hpp"
#define CSTXXX_SLAVE_ADDRESS (0x15)
#define CST328_SLAVE_ADDRESS (0x1A)
TouchDrvCSTXXX::DriverCreator TouchDrvCSTXXX::driverCreators[TouchDrvCSTXXX::driverCreatorMaxNum] = {
[]() -> std::unique_ptr<TouchDrvInterface> { return std::make_unique<TouchDrvCST226>(); },
[]() -> std::unique_ptr<TouchDrvInterface> { return std::make_unique<TouchDrvCST816>(); },
[]() -> std::unique_ptr<TouchDrvInterface> { return std::make_unique<TouchDrvCST92xx>(); }
};
TouchDrvCSTXXX::TouchDrvCSTXXX():
_writePtr(nullptr),
_readPtr(nullptr),
_modePtr(nullptr),
_touchType(TouchDrv_UNKOWN),
_drv(nullptr) {}
TouchDrvCSTXXX::~TouchDrvCSTXXX() {}
void TouchDrvCSTXXX::setTouchDrvModel(TouchDrvType model)
{
_touchType = model;
}
void TouchDrvCSTXXX::setupDriver()
{
if (_drv) {
_drv->setPins(_rst, _irq);
_drv->setCustomMode(_modePtr);
_drv->setCustomWrite(_writePtr);
_drv->setCustomRead(_readPtr);
}
}
#if defined(ARDUINO)
bool TouchDrvCSTXXX::begin(TwoWire &wire, uint8_t addr, int sda, int scl)
{
bool success = false;
for (int i = (_touchType == TouchDrv_UNKOWN) ? 0 : _touchType; i < driverCreatorMaxNum; ++i) {
_drv = createDriver(static_cast<TouchDrvType>(i));
setupDriver();
if (_drv && _drv->begin(wire, addr, sda, scl)) {
_touchType = static_cast<TouchDrvType>(i);
success = true;
break;
}
}
if (!success) {
_touchType = TouchDrv_UNKOWN;
}
return success;
}
#elif defined(ESP_PLATFORM)
#if defined(USEING_I2C_LEGACY)
bool TouchDrvCSTXXX::begin(i2c_port_t port_num, uint8_t addr, int sda, int scl)
{
bool success = false;
for (int i = (_touchType == TouchDrv_UNKOWN) ? 0 : _touchType; i < driverCreatorMaxNum; ++i) {
_drv = createDriver(static_cast<TouchDrvType>(i));
setupDriver();
if (_drv && _drv->begin(port_num, addr, sda, scl)) {
_touchType = static_cast<TouchDrvType>(i);
success = true;
break;
}
}
if (!success) {
_touchType = TouchDrv_UNKOWN;
}
return success;
}
#else
bool TouchDrvCSTXXX::begin(i2c_master_bus_handle_t handle, uint8_t addr)
{
bool success = false;
for (int i = (_touchType == TouchDrv_UNKOWN) ? 0 : _touchType; i < driverCreatorMaxNum; ++i) {
_drv = createDriver(static_cast<TouchDrvType>(i));
setupDriver();
if (_drv && _drv->begin(handle, addr)) {
_touchType = static_cast<TouchDrvType>(i);
success = true;
break;
}
}
if (!success) {
_touchType = TouchDrv_UNKOWN;
}
return success;
}
#endif // ESP_PLATFORM
#endif // ARDUINO
void TouchDrvCSTXXX::setGpioCallback(SensorHalCustom::CustomMode mode_cb,
SensorHalCustom::CustomWrite write_cb,
SensorHalCustom::CustomRead read_cb)
{
_writePtr = write_cb;
_readPtr = read_cb;
_modePtr = mode_cb;
}
bool TouchDrvCSTXXX::begin(SensorCommCustom::CustomCallback callback,
SensorCommCustomHal::CustomHalCallback hal_callback,
uint8_t addr)
{
bool success = false;
for (int i = (_touchType == TouchDrv_UNKOWN) ? 0 : _touchType; i < driverCreatorMaxNum; ++i) {
_drv = createDriver(static_cast<TouchDrvType>(i));
setupDriver();
if (_drv && _drv->begin(callback, hal_callback, addr)) {
_touchType = static_cast<TouchDrvType>(i);
success = true;
break;
}
}
if (!success) {
_touchType = TouchDrv_UNKOWN;
}
return success;
}
void TouchDrvCSTXXX::reset()
{
if (!_drv)return;
_drv->reset();
}
uint8_t TouchDrvCSTXXX::getPoint(int16_t *x_array, int16_t *y_array, uint8_t get_point)
{
if (!_drv)return 0;
return _drv->getPoint(x_array, y_array, get_point);
}
bool TouchDrvCSTXXX::isPressed()
{
if (!_drv)return false;
return _drv->isPressed();
}
const char *TouchDrvCSTXXX::getModelName()
{
if (!_drv)return "NULL";
return _drv->getModelName();
}
void TouchDrvCSTXXX::sleep()
{
if (!_drv)return;
_drv->sleep();
}
void TouchDrvCSTXXX::wakeup()
{
if (!_drv)return;
_drv->reset();
}
void TouchDrvCSTXXX::idle()
{
if (!_drv)return;
_drv->idle();
}
uint8_t TouchDrvCSTXXX::getSupportTouchPoint()
{
if (!_drv)return 0;
return _drv->getSupportTouchPoint();
}
bool TouchDrvCSTXXX::getResolution(int16_t *x, int16_t *y)
{
if (!_drv)return false;
return _drv->getResolution(x, y);
}
void TouchDrvCSTXXX::setCenterButtonCoordinate(uint16_t x, uint16_t y)
{
if (!_drv)return ;
const char *model = _drv->getModelName();
if (strncmp(model, "CST8", 3) == 0) {
TouchDrvCST816 *pT = static_cast<TouchDrvCST816 *>(_drv.get());
pT->setCenterButtonCoordinate(x, y);
}
}
void TouchDrvCSTXXX::setHomeButtonCallback(TouchDrvInterface::HomeButtonCallback callback, void *user_data)
{
if (!_drv)return ;
const char *model = _drv->getModelName();
if (strncmp(model, "CST8", 3) == 0) {
TouchDrvCST816 *pT = static_cast<TouchDrvCST816 *>(_drv.get());
pT->setHomeButtonCallback(callback, user_data);
} else if (strncmp(model, "CST2", 3) == 0) {
TouchDrvCST226 *pT = static_cast<TouchDrvCST226 *>(_drv.get());
pT->setHomeButtonCallback(callback, user_data);
}
}
void TouchDrvCSTXXX::disableAutoSleep()
{
if (!_drv)return ;
const char *model = _drv->getModelName();
if (strncmp(model, "CST8", 3) == 0) {
TouchDrvCST816 *pT = static_cast<TouchDrvCST816 *>(_drv.get());
pT->disableAutoSleep();
}
}
void TouchDrvCSTXXX::enableAutoSleep()
{
if (!_drv)return ;
const char *model = _drv->getModelName();
if (strncmp(model, "CST8", 3) == 0) {
TouchDrvCST816 *pT = static_cast<TouchDrvCST816 *>(_drv.get());
pT->enableAutoSleep();
}
}
void TouchDrvCSTXXX::setSwapXY(bool swap)
{
if (!_drv)return ;
_drv->setSwapXY(swap);
}
void TouchDrvCSTXXX::setMirrorXY(bool mirrorX, bool mirrorY)
{
if (!_drv)return ;
_drv->setMirrorXY(mirrorX, mirrorY);
}
void TouchDrvCSTXXX::setMaxCoordinates(uint16_t x, uint16_t y)
{
if (!_drv)return ;
_drv->setMaxCoordinates(x, y);
}

View File

@@ -0,0 +1,151 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file TouchDrvCSTXXX.hpp
* @author Lewis He (lewishe@outlook.com)
* @date 2023-04-24
* @date last 2025-01-20
*
*/
#pragma once
#include "touch/TouchDrvCST226.h"
#include "touch/TouchDrvCST816.h"
#include "touch/TouchDrvCST92xx.h"
#define CSTXXX_SLAVE_ADDRESS (0x15)
#define CST328_SLAVE_ADDRESS (0x1A)
enum TouchDrvType {
TouchDrv_CST226,
TouchDrv_CST8XX,
TouchDrv_CST92XX,
TouchDrv_UNKOWN,
};
class TouchDrvCSTXXX : public TouchDrvInterface
{
public:
TouchDrvCSTXXX();
~TouchDrvCSTXXX();
// Set the touch screen model. If not set, the default is to read
// the touch screen version information to determine which screen it is.
void setTouchDrvModel(TouchDrvType model);
#if defined(ARDUINO)
bool begin(TwoWire &wire, uint8_t addr, int sda, int scl)override;
#elif defined(ESP_PLATFORM)
#if defined(USEING_I2C_LEGACY)
bool begin(i2c_port_t port_num, uint8_t addr, int sda = -1, int scl = -1)override;
#else
bool begin(i2c_master_bus_handle_t handle, uint8_t addr)override;
#endif // ESP_PLATFORM
#endif // ARDUINO
// Set the callback I2C read and write method and initialize the touch screen.
// If successful, return true, otherwise false
bool begin(SensorCommCustom::CustomCallback callback,
SensorCommCustomHal::CustomHalCallback hal_callback,
uint8_t addr) override;
// Set other ways to control touch RST or INT
void setGpioCallback(SensorHalCustom::CustomMode mode_cb,
SensorHalCustom::CustomWrite write_cb,
SensorHalCustom::CustomRead read_cb) override;
// Reset Touch
void reset()override;
// Get the XY coordinates of the touch screen touch
uint8_t getPoint(int16_t *x_array, int16_t *y_array, uint8_t get_point = 1)override;
// Get whether the touch screen is pressed
bool isPressed()override;
// Get the touch screen model
const char *getModelName()override;
// Set the touch screen to sleep mode
void sleep()override;
// Wake up the touch screen, depends on the RST Pin, if it is not connected, it will be invalid
void wakeup()override;
// Idle mode, this is not implemented, most of the CSTXXX series have automatic sleep function
void idle()override;
// Get the maximum number of touch points supported by the touch screen
uint8_t getSupportTouchPoint()override;
// Get touch screen resolution, not implemented
bool getResolution(int16_t *x, int16_t *y)override;
// Set the screen touch button coordinates
void setCenterButtonCoordinate(uint16_t x, uint16_t y);
// Set screen touch button callback function
void setHomeButtonCallback(TouchDrvInterface::HomeButtonCallback callback, void *user_data = NULL);
// Disable automatic sleep, only for CST328
void disableAutoSleep();
// Enable automatic sleep, only for CST328
void enableAutoSleep();
// Swap XY coordinates
void setSwapXY(bool swap);
// Mirror XY Coordinates
void setMirrorXY(bool mirrorX, bool mirrorY);
// Set the maximum X, Y coordinates of the screen
void setMaxCoordinates(uint16_t x, uint16_t y);
private:
using DriverCreator = std::unique_ptr<TouchDrvInterface> (*)();
static constexpr uint8_t driverCreatorMaxNum = 3;
static DriverCreator driverCreators[driverCreatorMaxNum];
std::unique_ptr<TouchDrvInterface> createDriver(TouchDrvType type)
{
if (/*type >= TouchDrv_UNKOWN &&*/
type < sizeof(driverCreators) / sizeof(driverCreators[0])) {
return driverCreators[type]();
}
return nullptr;
}
void setupDriver();
SensorHalCustom::CustomWrite _writePtr;
SensorHalCustom::CustomRead _readPtr;
SensorHalCustom::CustomMode _modePtr;
TouchDrvType _touchType;
std::unique_ptr<TouchDrvInterface> _drv;
};

View File

@@ -0,0 +1,388 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file TouchDrvFT6X36.hpp
* @author Lewis He (lewishe@outlook.com)
* @date 2023-04-01
*
*/
#pragma once
#include "REG/FT6X36Constants.h"
#include "TouchDrvInterface.hpp"
class TouchDrvFT6X36 : public TouchDrvInterface
{
public:
enum GesTrue {
NO_GESTURE,
MOVE_UP,
MOVE_LEFT,
MOVE_DOWN,
MOVE_RIGHT,
ZOOM_IN,
ZOOM_OUT,
} ;
enum EventFlag {
EVENT_PUT_DOWN,
EVENT_PUT_UP,
EVENT_CONTACT,
EVENT_NONE,
} ;
enum PowerMode {
PMODE_ACTIVE = 0, // ~4mA
PMODE_MONITOR = 1, // ~3mA
PMODE_DEEP_SLEEP = 3, // ~100uA The reset pin must be pulled down to wake up
} ;
EventFlag event;
TouchDrvFT6X36() : comm(nullptr), hal(nullptr) {}
~TouchDrvFT6X36()
{
if (comm) {
comm->deinit();
}
}
#if defined(ARDUINO)
bool begin(TwoWire &wire, uint8_t addr = FT6X36_SLAVE_ADDRESS, int sda = -1, int scl = -1)
{
if (!beginCommon<SensorCommI2C, HalArduino>(comm, hal, wire, addr, sda, scl)) {
return false;
}
return initImpl();
}
#elif defined(ESP_PLATFORM)
#if defined(USEING_I2C_LEGACY)
bool begin(i2c_port_t port_num, uint8_t addr = FT6X36_SLAVE_ADDRESS, int sda = -1, int scl = -1)
{
if (!beginCommon<SensorCommI2C, HalEspIDF>(comm, hal, port_num, addr, sda, scl)) {
return false;
}
return initImpl();
}
#else
bool begin(i2c_master_bus_handle_t handle, uint8_t addr = FT6X36_SLAVE_ADDRESS)
{
if (!beginCommon<SensorCommI2C, HalEspIDF>(comm, hal, handle, addr)) {
return false;
}
return initImpl();
}
#endif //ESP_PLATFORM
#endif //ARDUINO
bool begin(SensorCommCustom::CustomCallback callback,
SensorCommCustomHal::CustomHalCallback hal_callback,
uint8_t addr)
{
if (!beginCommCustomCallback<SensorCommCustom, SensorCommCustomHal>(COMM_CUSTOM,
callback, hal_callback, addr, comm, hal)) {
return false;
}
return initImpl();
}
uint8_t getDeviceMode(void)
{
return comm->readRegister(FT6X36_REG_MODE) & 0x03;
}
// Obtaining gestures depends on whether the built-in firmware of the chip has this function
uint8_t getGesture()
{
int val = comm->readRegister(FT6X36_REG_GEST);
switch (val) {
case 0x10:
return MOVE_UP;
case 0x14:
return MOVE_RIGHT;
case 0x18:
return MOVE_DOWN;
case 0x1C:
return MOVE_LEFT;
case 0x48:
return ZOOM_IN;
case 0x49:
return ZOOM_OUT;
default:
break;
}
return NO_GESTURE;
}
void setThreshold(uint8_t value)
{
comm->writeRegister(FT6X36_REG_THRESHOLD, value);
}
uint8_t getThreshold(void)
{
return comm->readRegister(FT6X36_REG_THRESHOLD);
}
uint8_t getMonitorTime(void)
{
return comm->readRegister(FT6X36_REG_MONITOR_TIME);
}
void setMonitorTime(uint8_t sec)
{
comm->writeRegister(FT6X36_REG_MONITOR_TIME, sec);
}
// Calibration useless actually,
// any value set will not be valid,
// depending on the internal firmware of the chip.
/*
void enableAutoCalibration(void)
{
comm->writeRegister(FT6X36_REG_AUTO_CLB_MODE, 0x00);
}
void disableAutoCalibration(void)
{
comm->writeRegister(FT6X36_REG_AUTO_CLB_MODE, 0xFF);
}
*/
uint16_t getLibraryVersion()
{
uint8_t buffer[2];
comm->readRegister(FT6X36_REG_LIB_VERSION_H, buffer, 2);
return (buffer[0] << 8) | buffer[1];
}
// The interrupt is triggered only if a touch is detected during the scan cycle
void interruptPolling(void)
{
//datasheet this bit is 0,Actually, it's wrong
comm->writeRegister(FT6X36_REG_INT_STATUS, 1);
}
// Triggers an interrupt whenever a touch is detected
void interruptTrigger(void)
{
//datasheet this bit is 1,Actually, it's wrong
comm->writeRegister(FT6X36_REG_INT_STATUS, (uint8_t)0);
}
uint8_t getPoint(int16_t *x_array, int16_t *y_array, uint8_t size = 1)
{
uint8_t buffer[16];
if (!x_array || !y_array || !size)
return 0;
if (comm->readRegister(FT6X36_REG_MODE, buffer, 16) == -1) {
return 0;
}
// uint8_t mode = buffer[0];
//REG 0x01
// uint8_t gesture = buffer[1];
//REG 0x02
uint8_t numPoints = buffer[2] & 0x0F;
if (numPoints == 0 || numPoints == 0x0F) {
return 0;
}
//REG 0x03 ~ 0x04
// uint8_t eventFlag = (buffer[3] & 0xC0) >> 6;
uint16_t posX = ((buffer[3] & 0x0F) << 8) | buffer[4];
//REG 0x05 ~ 0x06
uint16_t posY = ((buffer[5] & 0x0F) << 8) | buffer[6] ;
x_array[0] = posX;
y_array[0] = posY;
if (numPoints == 2) {
//REG 0x09 ~ 0x0A
posX = ((buffer[9] & 0x0F) << 8) | buffer[10];
//REG 0x0B ~ 0x0C
posY = ((buffer[11] & 0x0F) << 8) | buffer[12] ;
if (size == 2) {
x_array[1] = posX;
y_array[1] = posY;
}
}
updateXY(numPoints, x_array, y_array);
return numPoints;
}
bool isPressed()
{
if (_irq != -1) {
return hal->digitalRead(_irq) == LOW;
}
return comm->readRegister(FT6X36_REG_STATUS) & 0x0F;
}
void setPowerMode(PowerMode mode)
{
comm->writeRegister(FT6X36_REG_POWER_MODE, mode);
}
void sleep()
{
comm->writeRegister(FT6X36_REG_POWER_MODE, PMODE_DEEP_SLEEP);
}
void wakeup()
{
reset();
}
void idle()
{
}
uint8_t getSupportTouchPoint()
{
return 1;
}
uint32_t getChipID(void)
{
return comm->readRegister(FT6X36_REG_CHIP_ID);
}
uint8_t getVendorID(void)
{
return comm->readRegister(FT6X36_REG_VENDOR1_ID);
}
uint8_t getErrorCode(void)
{
return comm->readRegister(FT6X36_REG_ERROR_STATUS);
}
const char *getModelName()
{
switch (_chipID) {
case FT6206_CHIP_ID: return "FT6206";
case FT6236_CHIP_ID: return "FT6236";
case FT6236U_CHIP_ID: return "FT6236U";
case FT3267_CHIP_ID: return "FT3267";
default: return "UNKNOWN";
}
}
bool getResolution(int16_t *x, int16_t *y)
{
return false;
}
void reset()
{
if (_rst != -1) {
hal->pinMode(_rst, OUTPUT);
hal->digitalWrite(_rst, HIGH);
hal->delay(10);
hal->digitalWrite(_rst, LOW);
hal->delay(30);
hal->digitalWrite(_rst, HIGH);
// For the variant of GPIO extended RST,
// communication and hal->delay are carried out simultaneously, and 160ms is measured in T-RGB esp-idf new api
hal->delay(160);
}
}
void setGpioCallback(CustomMode mode_cb,
CustomWrite write_cb,
CustomRead read_cb)
{
SensorHalCustom::setCustomMode(mode_cb);
SensorHalCustom::setCustomWrite(write_cb);
SensorHalCustom::setCustomRead(read_cb);
}
private:
bool initImpl()
{
if (_irq != -1) {
hal->pinMode(_irq, INPUT);
}
reset();
uint8_t vendId = comm->readRegister(FT6X36_REG_VENDOR1_ID);
if (vendId != FT6X36_VEND_ID) {
log_e("Vendor id is 0x%X not match!", vendId);
return false;
}
_chipID = comm->readRegister(FT6X36_REG_CHIP_ID);
if ((_chipID != FT6206_CHIP_ID) &&
(_chipID != FT6236_CHIP_ID) &&
(_chipID != FT6236U_CHIP_ID) &&
(_chipID != FT3267_CHIP_ID)
) {
log_e("Vendor id is not match!");
log_e("ChipID:0x%lx should be 0x06 or 0x36 or 0x64", _chipID);
return false;
}
log_i("Vend ID: 0x%X", vendId);
log_i("Chip ID: 0x%lx", _chipID);
log_i("Firm Version: 0x%X", comm->readRegister(FT6X36_REG_FIRM_VERS));
log_i("Point Rate Hz: %u", comm->readRegister(FT6X36_REG_PERIOD_ACTIVE));
log_i("Thresh : %u", comm->readRegister(FT6X36_REG_THRESHOLD));
// change threshold to be higher/lower
comm->writeRegister(FT6X36_REG_THRESHOLD, 60);
log_i("Chip library version : 0x%x", getLibraryVersion());
// This register describes period of monitor status, it should not less than 30.
log_i("Chip period of monitor status : 0x%x", comm->readRegister(FT6X36_REG_PERIOD_MONITOR));
// This register describes the period of active status, it should not less than 12
return true;
}
protected:
std::unique_ptr<SensorCommBase> comm;
std::unique_ptr<SensorHal> hal;
};

View File

@@ -0,0 +1,704 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file TouchDrvGT911.hpp
* @author Lewis He (lewishe@outlook.com)
* @date 2023-04-12
*
*/
#pragma once
#include "REG/GT911Constants.h"
#include "TouchDrvInterface.hpp"
#if defined(ARDUINO_ARCH_NRF52)
// NRF52840 I2C BUFFER : 64 Bytes ,
#warning "NRF Platform I2C Buffer expansion is not implemented , GT911 requires at least 188 bytes to read all configurations"
#endif
#define GT911_GET_POINT(x) (x & 0x0F)
#define GT911_GET_BUFFER_STATUS(x) (x & 0x80)
#define GT911_GET_HAVE_KEY(x) (x & 0x10)
class TouchDrvGT911 : public TouchDrvInterface, public GT911Constants
{
typedef struct {
uint8_t trackID;
int16_t x;
int16_t y;
int16_t size;
} PointReg;
public:
TouchDrvGT911() : comm(nullptr), hal(nullptr) {}
~TouchDrvGT911()
{
if (comm) {
comm->deinit();
}
}
#if defined(ARDUINO)
bool begin(TwoWire &wire, uint8_t addr = GT911_SLAVE_ADDRESS_H, int sda = -1, int scl = -1)
{
if (!beginCommon<SensorCommI2C, HalArduino>(comm, hal, wire, addr, sda, scl)) {
return false;
}
return initImpl(addr);
}
#elif defined(ESP_PLATFORM)
#if defined(USEING_I2C_LEGACY)
bool begin(i2c_port_t port_num, uint8_t addr = GT911_SLAVE_ADDRESS_H, int sda = -1, int scl = -1)
{
if (!beginCommon<SensorCommI2C, HalEspIDF>(comm, hal, port_num, addr, sda, scl)) {
return false;
}
return initImpl(addr);
}
#else
bool begin(i2c_master_bus_handle_t handle, uint8_t addr = GT911_SLAVE_ADDRESS_H)
{
if (!beginCommon<SensorCommI2C, HalEspIDF>(comm, hal, handle, addr)) {
return false;
}
return initImpl(addr);
}
#endif //ESP_PLATFORM
#endif //ARDUINO
bool begin(SensorCommCustom::CustomCallback callback,
SensorCommCustomHal::CustomHalCallback hal_callback,
uint8_t addr)
{
if (!beginCommCustomCallback<SensorCommCustom, SensorCommCustomHal>(COMM_CUSTOM,
callback, hal_callback, addr, comm, hal)) {
return false;
}
return initImpl(addr);
}
void reset()
{
if (_rst != -1) {
hal->pinMode(_rst, OUTPUT);
hal->digitalWrite(_rst, HIGH);
hal->delay(10);
}
if (_irq != -1) {
hal->pinMode(_irq, INPUT);
}
/*
* If you perform a software reset on a board without a reset pin connected,
* subsequent interrupt settings or re-writing of configurations will be invalid.
* For example, when debugging a LilyGo T-Deck, resetting the interrupt mode will
* be invalid after a software reset.
* */
// comm->writeRegister(GT911_COMMAND, 0x02);
// writeCommand(0x02);
}
void sleep()
{
if (_irq != -1) {
hal->pinMode(_irq, OUTPUT);
hal->digitalWrite(_irq, LOW);
}
// comm->writeRegister(GT911_COMMAND, 0x05);
writeCommand(0x05);
/*
* Depending on the chip and platform, setting it to input after removing sleep will affect power consumption.
* The chip platform determines whether
*
* * */
// if (_irq != -1) {
// hal->digitalWrite(_irq, INPUT);
// }
}
void wakeup()
{
if (_irq != -1) {
hal->pinMode(_irq, OUTPUT);
hal->digitalWrite(_irq, HIGH);
hal->delay(8);
hal->pinMode(_irq, INPUT);
} else {
reset();
}
}
void idle()
{
}
uint8_t getSupportTouchPoint()
{
return 5;
}
uint8_t getPoint(int16_t *x_array, int16_t *y_array, uint8_t size = 1)
{
uint8_t buffer[39];
uint8_t touchPoint = 0;
PointReg p[5];
if (!x_array || !y_array || size == 0)
return 0;
uint8_t val = readGT911(GT911_POINT_INFO);
bool haveKey = GT911_GET_HAVE_KEY(val);
// bool bufferStatus = GT911_GET_BUFFER_STATUS(val);
// log_i("REG:0x%X S:0X%d K:%d\n", val,bufferStatus,haveKey);
if (_HButtonCallback && haveKey) {
_HButtonCallback(_userData);
}
clearBuffer();
touchPoint = GT911_GET_POINT(val);
if (touchPoint == 0) {
return 0;
}
// GT911_POINT_1 0X814F
uint8_t write_buffer[2] = {0x81, 0x4F};
if (comm->writeThenRead(write_buffer, arraySize(write_buffer),
buffer, 39) == -1) {
return 0;
}
for (uint8_t i = 0; i < size; i++) {
p[i].trackID = buffer[i * 8];
p[i].x = buffer[0x01 + i * 8] ;
p[i].x |= (buffer[0x02 + i * 8] << 8 );
p[i].y = buffer[0x03 + i * 8] ;
p[i].y |= (buffer[0x04 + i * 8] << 8);
p[i].size = buffer[0x05 + i * 8] ;
p[i].size |= (buffer[0x06 + i * 8] << 8) ;
x_array[i] = p[i].x;
y_array[i] = p[i].y;
}
updateXY(touchPoint, x_array, y_array);
return touchPoint;
}
bool isPressed()
{
if (_irq != -1) {
if (_irq_mode == FALLING) {
return hal->digitalRead(_irq) == LOW;
} else if (_irq_mode == RISING ) {
return hal->digitalRead(_irq) == HIGH;
} else if (_irq_mode == LOW_LEVEL_QUERY) {
return hal->digitalRead(_irq) == LOW;
} else if (_irq_mode == HIGH_LEVEL_QUERY) {
return hal->digitalRead(_irq) == HIGH;
}
}
return getPoint();
}
bool setInterruptMode(uint8_t mode)
{
// GT911_MODULE_SWITCH_1 0x804D
uint8_t val = readGT911(GT911_MODULE_SWITCH_1);
val &= 0XFC;
if (mode == FALLING) {
val |= 0x01;
} else if (mode == RISING ) {
val |= 0x00;
} else if (mode == LOW_LEVEL_QUERY ) {
val |= 0x02;
} else if (mode == HIGH_LEVEL_QUERY ) {
val |= 0x03;
}
_irq_mode = mode;
writeGT911(GT911_MODULE_SWITCH_1, val);
return reloadConfig();
}
/**
* @retval
* * 0x0: Rising edge trigger
* * 0x1: Falling edge trigger
* * 0x2: Low level query
* * 0x3: High level query
*/
uint8_t getInterruptMode()
{
uint8_t val = readGT911(GT911_MODULE_SWITCH_1);
// return val & 0x03;
val &= 0x03;
if (val == 0x00) {
_irq_mode = RISING;
} else if (val == 0x01) {
_irq_mode = FALLING;
} else if (val == 0x02) {
_irq_mode = LOW_LEVEL_QUERY;
} else if (val == 0x03) {
_irq_mode = HIGH_LEVEL_QUERY;
}
return val;
}
uint8_t getPoint()
{
// GT911_POINT_INFO 0X814E
uint8_t val = readGT911(GT911_POINT_INFO);
clearBuffer();
return GT911_GET_POINT(val);
}
uint32_t getChipID()
{
char product_id[4] = {0};
// GT911_PRODUCT_ID 0x8140
for (int i = 0; i < 4; ++i) {
product_id[i] = readGT911(GT911_PRODUCT_ID + i);
}
return atoi(product_id);
}
uint16_t getFwVersion()
{
uint8_t fw_ver[2] = {0};
// GT911_FIRMWARE_VERSION 0x8144
for (int i = 0; i < 2; ++i) {
fw_ver[i] = readGT911(GT911_FIRMWARE_VERSION + i);
}
return fw_ver[0] | (fw_ver[1] << 8);
}
uint8_t getConfigVersion()
{
return readGT911(GT911_CONFIG_VERSION);
}
bool getResolution(int16_t *x, int16_t *y)
{
uint8_t x_resolution[2] = {0}, y_resolution[2] = {0};
for (int i = 0; i < 2; ++i) {
x_resolution[i] = readGT911(GT911_X_RESOLUTION + i);
}
for (int i = 0; i < 2; ++i) {
y_resolution[i] = readGT911(GT911_Y_RESOLUTION + i);
}
*x = x_resolution[0] | (x_resolution[1] << 8);
*y = y_resolution[0] | (y_resolution[1] << 8);
return true;
}
//Range : 5 ~ 15 ms
void updateRefreshRate(uint8_t rate_ms)
{
if ((rate_ms - 5) < 5) {
rate_ms = 5;
}
if (rate_ms > 15) {
rate_ms = 15;
}
rate_ms -= 5;
writeGT911(GT911_REFRESH_RATE, rate_ms);
reloadConfig();
}
uint8_t getRefreshRate()
{
uint8_t rate_ms = readGT911(GT911_REFRESH_RATE);
return rate_ms + GT911_BASE_REF_RATE ;
}
int getVendorID()
{
return readGT911(GT911_VENDOR_ID);
}
const char *getModelName()
{
return "GT911";
}
void setGpioCallback(CustomMode mode_cb,
CustomWrite write_cb,
CustomRead read_cb)
{
SensorHalCustom::setCustomMode(mode_cb);
SensorHalCustom::setCustomWrite(write_cb);
SensorHalCustom::setCustomRead(read_cb);
}
void setHomeButtonCallback(HomeButtonCallback cb, void *user_data)
{
_HButtonCallback = cb;
_userData = user_data;
}
bool writeConfig(const uint8_t *config_buffer, size_t buffer_size)
{
#if 0 //TODO:
uint8_t check_sum = 0;
for (int i = 0; i < (GT911_REG_LENGTH - 2 ); i++) {
check_sum += config_buffer[i];
}
check_sum = (~check_sum) + 1;
if (check_sum != config_buffer[GT911_REG_LENGTH - 2]) {
log_e("Config checksum error !");
return false;
}
log_d("Update touch config , write %lu Bytes check sum:0x%X", buffer_size, check_sum);
uint8_t cmd[] = {lowByte(GT911_CONFIG_VERSION), highByte(GT911_CONFIG_VERSION)};
int err = comm->writeRegister(GT911_CONFIG_VERSION, (uint8_t *)config_buffer, buffer_size);
#if 0
while (digitalRead(_irq)) {
log_i("Wait irq.."); hal->delay(500);
}
int err = comm->writeBuffer((uint8_t *)config_buffer, buffer_size);
#endif
return err == 0;
#endif
return false;
}
uint8_t *loadConfig(size_t *output_size, bool print_out = false)
{
*output_size = 0;
uint8_t *buffer = (uint8_t * )malloc(GT911_REG_LENGTH * sizeof(uint8_t));
if (!buffer)return NULL;
uint8_t write_buffer[2] = {highByte(GT911_CONFIG_VERSION), lowByte(GT911_CONFIG_VERSION)};
if (comm->writeThenRead(write_buffer, arraySize(write_buffer), buffer, GT911_REG_LENGTH) == -1) {
free(buffer);
return NULL;
}
if (print_out) {
printf("const unsigned char config[186] = {");
for (int i = 0; i < GT911_REG_LENGTH; ++i) {
if ( (i % 8) == 0) {
printf("\n");
}
printf(" 0x%02X", buffer[i]);
if ((i + 1) < GT911_REG_LENGTH) {
printf(",");
}
}
printf("};\n");
}
*output_size = GT911_REG_LENGTH;
return buffer;
}
bool reloadConfig()
{
uint8_t buffer[GT911_REG_LENGTH] = {highByte(GT911_CONFIG_VERSION), lowByte(GT911_CONFIG_VERSION)};
if (comm->writeThenRead(buffer, 2, buffer, GT911_REG_LENGTH - 2) == -1) {
return false;
}
uint8_t check_sum = 0;
for (int i = 0; i < (GT911_REG_LENGTH - 2 ); i++) {
check_sum += buffer[i];
}
check_sum = (~check_sum) + 1;
log_d("reloadConfig check_sum : 0x%X\n", check_sum);
writeGT911(GT911_CONFIG_CHKSUM, check_sum);
writeGT911(GT911_CONFIG_FRESH, 0x01);
return true;
}
void dumpRegister()
{
size_t output_size = 0;
uint8_t *buffer = loadConfig(&output_size, true);
if (output_size == 0) {
return;
}
if (buffer == NULL)return;
printf("----------Dump register------------\n");
for (size_t i = 0; i < output_size; ++i) {
printf("[%d] REG: 0x%X : 0x%02X\n", i, GT911_CONFIG_VERSION + i, buffer[i]);
}
free(buffer);
}
// Range : 1~5
void setMaxTouchPoint(uint8_t num)
{
if (num < 1)num = 1;
if (num > 5) num = 5;
writeGT911(GT911_TOUCH_NUMBER, num);
reloadConfig();
}
uint8_t getMaxTouchPoint()
{
uint8_t num = readGT911(GT911_TOUCH_NUMBER);
return num & 0x0F;
}
void setConfigData(uint8_t *data, uint16_t length)
{
_config = data;
_config_size = length;
}
private:
uint8_t readGT911(uint16_t cmd)
{
uint8_t value = 0x00;
uint8_t write_buffer[2] = {highByte(cmd), lowByte(cmd)};
comm->writeThenRead(write_buffer, arraySize(write_buffer),
&value, 1);
return value;
}
int writeGT911(uint16_t cmd, uint8_t value)
{
uint8_t write_buffer[3] = {highByte(cmd), lowByte(cmd), value};
return comm->writeBuffer(write_buffer, arraySize(write_buffer));
}
void writeCommand(uint8_t command)
{
// GT911_COMMAND 0x8040
uint8_t write_buffer[3] = {0x80, 0x40, command};
comm->writeBuffer(write_buffer, arraySize(write_buffer));
}
void inline clearBuffer()
{
writeGT911(GT911_POINT_INFO, 0x00);
}
bool probeAddress()
{
const uint8_t device_address[2] = {GT911_SLAVE_ADDRESS_L, GT911_SLAVE_ADDRESS_H};
for (size_t i = 0; i < arraySize(device_address); ++i) {
I2CParam params(I2CParam::I2C_SET_ADDR, device_address[i]);
comm->setParams(params);
for (int retry = 0; retry < 3; ++retry) {
_chipID = getChipID();
if (_chipID == GT911_DEV_ID) {
log_i("Touch device address found is : 0x%X", device_address[i]);
return true;
}
}
}
log_e("GT911 not found, touch device 7-bit address should be 0x5D or 0x14");
return false;
}
bool initImpl(uint8_t addr)
{
int16_t x = 0, y = 0;
if (addr == GT911_SLAVE_ADDRESS_H && _rst != -1 && _irq != -1) {
log_i("Try using 0x14 as the device address");
hal->pinMode(_rst, OUTPUT);
hal->pinMode(_irq, OUTPUT);
hal->digitalWrite(_rst, LOW);
hal->digitalWrite(_irq, HIGH);
hal->delayMicroseconds(120);
hal->digitalWrite(_rst, HIGH);
#if defined(ARDUINO)
// In the Arduino ESP32 platform, the test delay is 8ms and the GT911
// can be accessed correctly. If the time is too long, it will not be accessible.
hal->delay(8);
#elif defined(ESP_PLATFORM)
// For the variant of GPIO extended RST,
// communication and delay are carried out simultaneously, and 18 ms is measured in T-RGB esp-idf new api
hal->delay(18);
#endif
hal->pinMode(_irq, INPUT);
} else if (addr == GT911_SLAVE_ADDRESS_L && _rst != -1 && _irq != -1) {
log_i("Try using 0x5D as the device address");
hal->pinMode(_rst, OUTPUT);
hal->pinMode(_irq, OUTPUT);
hal->digitalWrite(_rst, LOW);
hal->digitalWrite(_irq, LOW);
hal->delayMicroseconds(120);
hal->digitalWrite(_rst, HIGH);
#if defined(ARDUINO)
// In the Arduino ESP32 platform, the test hal->delay is 8ms and the GT911
// can be accessed correctly. If the time is too long, it will not be accessible.
hal->delay(8);
#elif defined(ESP_PLATFORM)
// For the variant of GPIO extended RST,
// communication and hal->delay are carried out simultaneously, and 18 ms is measured in T-RGB esp-idf new api
hal->delay(18);
#endif
hal->pinMode(_irq, INPUT);
} else {
if (!autoProbe()) {
return false;
}
}
// For variants where the GPIO is controlled by I2C, a hal->delay is required here
hal->delay(20);
/*
* For the ESP32 platform, the default buffer is 128.
* Need to re-apply for a larger buffer to fully read the configuration table.
*
* TODO: NEED FIX
if (!this->reallocBuffer(GT911_REG_LENGTH + 2)) {
log_e("realloc i2c buffer failed !");
return false;
}
*/
_chipID = getChipID();
if (_chipID != GT911_DEV_ID) {
log_i("Not found device GT911,Try to found the GT911");
if (!autoProbe()) {
return false;
}
}
log_i("Product id:%ld", _chipID);
#if 0
/*If the configuration is not written, the touch screen may be damaged. */
if (_config && _config_size != 0) {
log_d("Current version char :%x", getConfigVersion());
hal->delay(100);
writeConfig(_config, _config_size);
if (_irq != -1) {
hal->pinMode(_irq, INPUT);
}
log_d("WriteConfig version char :%x", getConfigVersion());
// hal->delay(1000);
// size_t output_size;
// loadConfig(&output_size, true);
// log_d("loadConfig version char :%x", version_char);
}
#endif
log_i("Firmware version: 0x%x", getFwVersion());
getResolution(&x, &y);
log_i("Resolution : X = %d Y = %d", x, y);
log_i("Vendor id:%d", getVendorID());
log_i("Refresh Rate:%d ms", getRefreshRate());
log_i("MaxTouchPoint:%d", getMaxTouchPoint());
// Get the default interrupt trigger mode of the current screen
getInterruptMode();
if ( _irq_mode == RISING) {
log_i("Interrupt Mode: RISING");
} else if (_irq_mode == FALLING) {
log_i("Interrupt Mode: FALLING");
} else if (_irq_mode == LOW_LEVEL_QUERY) {
log_i("Interrupt Mode: LOW_LEVEL_QUERY");
} else if (_irq_mode == HIGH_LEVEL_QUERY) {
log_i("Interrupt Mode: HIGH_LEVEL_QUERY");
} else {
log_e("UNKOWN");
}
if (x == -1 || y == -1) {
log_e("The screen configuration is lost, please update the configuration file again !");
return false;
}
return true;
}
bool autoProbe()
{
if (_rst != -1) {
hal->pinMode(_rst, OUTPUT);
hal->digitalWrite(_rst, HIGH);
hal->delay(10);
}
// Automatically determine the current device
// address when using the reset pin without connection
if (!probeAddress()) {
return false;
}
// Reset Config
reset();
if (_irq != -1) {
hal->pinMode(_irq, INPUT);
}
return true;
}
static constexpr uint8_t LOW_LEVEL_QUERY = 0x03;
static constexpr uint8_t HIGH_LEVEL_QUERY = 0x04;
protected:
std::unique_ptr<SensorCommBase> comm;
std::unique_ptr<SensorHal> hal;
int _irq_mode;
uint8_t *_config = NULL;
uint16_t _config_size = 0;
};

View File

@@ -0,0 +1,640 @@
/**
*
* @license MIT License
*
* Copyright (c) 2024 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file TouchDrvGT9895.cpp
* @author Lewis He (lewishe@outlook.com)
* @date 2024-09-21
*
*/
#include "TouchDrvGT9895.hpp"
TouchDrvGT9895::TouchDrvGT9895() : comm(nullptr), hal(nullptr) {}
TouchDrvGT9895::~TouchDrvGT9895()
{
if (comm) {
comm->deinit();
}
}
#if defined(ARDUINO)
bool TouchDrvGT9895::begin(TwoWire &wire, uint8_t addr, int sda, int scl)
{
if (!beginCommon<SensorCommI2C, HalArduino>(comm, hal, wire, addr, sda, scl)) {
return false;
}
return initImpl();
}
#elif defined(ESP_PLATFORM)
#if defined(USEING_I2C_LEGACY)
bool TouchDrvGT9895::begin(i2c_port_t port_num, uint8_t addr, int sda, int scl)
{
if (!beginCommon<SensorCommI2C, HalEspIDF>(comm, hal, port_num, addr, sda, scl)) {
return false;
}
return initImpl();
}
#else
bool TouchDrvGT9895::begin(i2c_master_bus_handle_t handle, uint8_t addr)
{
if (!beginCommon<SensorCommI2C, HalEspIDF>(comm, hal, handle, addr)) {
return false;
}
return initImpl();
}
#endif //ESP_PLATFORM
#endif //ARDUINO
bool TouchDrvGT9895::begin(SensorCommCustom::CustomCallback callback,
SensorCommCustomHal::CustomHalCallback hal_callback,
uint8_t addr)
{
if (!beginCommCustomCallback<SensorCommCustom, SensorCommCustomHal>(COMM_CUSTOM,
callback, hal_callback, addr, comm, hal)) {
return false;
}
return initImpl();
}
void TouchDrvGT9895::deinit()
{
}
void TouchDrvGT9895::reset()
{
if (_rst != -1) {
hal->pinMode(_rst, OUTPUT);
hal->digitalWrite(_rst, HIGH);
hal->delay(10);
hal->digitalWrite(_rst, LOW);
hal->delay(30);
hal->digitalWrite(_rst, HIGH);
hal->delay(100);
}
if (_irq != -1) {
hal->pinMode(_irq, INPUT);
}
}
void TouchDrvGT9895::sleep()
{
if (_irq != -1) {
hal->pinMode(_irq, OUTPUT);
hal->digitalWrite(_irq, LOW);
}
uint8_t sleep_cmd[] = {
((GT9895_REG_CMD >> 24) & 0xFF),
((GT9895_REG_CMD >> 16) & 0xFF),
((GT9895_REG_CMD >> 8) & 0xFF),
(GT9895_REG_CMD & 0xFF),
0x00, 0x00, 0x04, 0x84, 0x88, 0x00
};
comm->writeBuffer(sleep_cmd, sizeof(sleep_cmd));
}
void TouchDrvGT9895::wakeup()
{
if (_irq != -1) {
hal->pinMode(_irq, OUTPUT);
hal->digitalWrite(_irq, HIGH);
hal->delay(8);
}
reset();
}
void TouchDrvGT9895::idle()
{
}
uint8_t TouchDrvGT9895::getSupportTouchPoint()
{
return GT9895_MAX_TOUCH;
}
uint8_t TouchDrvGT9895::getPoint(int16_t *x_array, int16_t *y_array, uint8_t size)
{
uint8_t buffer[32] = {0};
uint8_t event_status;
int length = GT9895_IRQ_EVENT_HEAD_LEN + GT9895_BYTES_PER_POINT * 2 + GT9895_COORDS_DATA_CHECKSUM_SIZE;
ByteUnion u;
u.value = GT9895_REG_POINT;
if (comm->writeThenRead(u.byte_array, 4, buffer, length) == -1) {
return 0;
}
if (buffer[0] == 0x00) {
return 0;
}
if (checksum_cmp(buffer, GT9895_IRQ_EVENT_HEAD_LEN, CHECKSUM_MODE_U8_LE)) {
// log_e("touch head checksum err[%*ph]", GT9895_IRQ_EVENT_HEAD_LEN, buffer);
return 0;
}
event_status = buffer[0];
if (event_status & GT9895_TOUCH_EVENT) {
int touchNum = getTouchData(buffer, length);
if (!touchNum) {
return 0;
}
if ( x_array && y_array && size) {
uint8_t length = size < touchNum ? size : touchNum;
for (int i = 0; i < length; ++i) {
x_array[i] = _ts_event.touch_data.coords[i].x;
y_array[i] = _ts_event.touch_data.coords[i].y;
}
updateXY(touchNum, x_array, y_array);
}
return touchNum;
}
#if 0
if (event_status & GT9895_REQUEST_EVENT) {
_ts_event.event_type = EVENT_REQUEST;
if (buffer[2] == BRL_REQUEST_CODE_CONFIG)
_ts_event.request_code = REQUEST_TYPE_CONFIG;
else if (buffer[2] == BRL_REQUEST_CODE_RESET)
_ts_event.request_code = REQUEST_TYPE_RESET;
else
log_e("unsupported request code 0x%x", buffer[2]);
}
if (event_status & GT9895_GESTURE_EVENT) {
_ts_event.event_type = EVENT_GESTURE;
_ts_event.gesture_type = buffer[4];
memcpy(_ts_event.gesture_data, &buffer[8], GT9895_GESTURE_DATA_LEN);
}
#endif
clearStatus();
return 0;
}
bool TouchDrvGT9895::isPressed()
{
if (_irq != -1) {
return hal->digitalRead(_irq) == LOW;
} else {
return getPoint(NULL, NULL, 0);
}
return false;
}
uint32_t TouchDrvGT9895::getChipID()
{
return (uint32_t)strtol((const char *)_version.patch_pid, NULL, 16);
}
bool TouchDrvGT9895::getResolution(int16_t *x, int16_t *y)
{
return 0;
}
const char *TouchDrvGT9895::getModelName()
{
return "GT9895";
}
void TouchDrvGT9895::setGpioCallback(CustomMode mode_cb,
CustomWrite write_cb,
CustomRead read_cb)
{
SensorHalCustom::setCustomMode(mode_cb);
SensorHalCustom::setCustomWrite(write_cb);
SensorHalCustom::setCustomRead(read_cb);
}
int TouchDrvGT9895::is_risk_data(const uint8_t *data, int size)
{
int zero_count = 0;
int ff_count = 0;
for (int i = 0; i < size; i++) {
if (data[i] == 0)
zero_count++;
else if (data[i] == 0xFF)
ff_count++;
}
if (zero_count == size || ff_count == size) {
log_e("warning data is all %s\n", zero_count == size ? "0x00" : "0xFF");
return 1;
}
return 0;
}
int TouchDrvGT9895::checksum_cmp(const uint8_t *data, int size, int mode)
{
uint32_t cal_checksum = 0;
uint32_t r_checksum = 0;
if (mode == CHECKSUM_MODE_U8_LE) {
if (size < 2)
return 1;
for (int i = 0; i < size - 2; i++)
cal_checksum += data[i];
r_checksum = data[size - 2] + (data[size - 1] << 8);
return (cal_checksum & 0xFFFF) == r_checksum ? 0 : 1;
}
if (size < 4)
return 1;
for (int i = 0; i < size - 4; i += 2)
cal_checksum += data[i] + (data[i + 1] << 8);
r_checksum = data[size - 4] + (data[size - 3] << 8) +
(data[size - 2] << 16) + (data[size - 1] << 24);
return cal_checksum == r_checksum ? 0 : 1;
}
int TouchDrvGT9895::readVersion(ChipFirmwareVersion *version)
{
int ret = 0;
uint8_t buffer[sizeof(ChipFirmwareVersion)] = {0};
uint8_t temp_pid[8] = {0};
if (!version) {
return -1;
}
for (int i = 0; i < 2; i++) {
ByteUnion u;
u.value = GT9895_REG_FW_VERSION;
if (comm->writeThenRead(u.byte_array, 4, buffer, sizeof(buffer)) == -1) {
log_e("read fw version: %d, retry %d", ret, i);
ret = -1;
hal->delay(5);
continue;
}
if (!checksum_cmp(buffer, sizeof(buffer), CHECKSUM_MODE_U8_LE)) {
ret = 0;
break;
}
log_e("Invalid fw version: checksum error!");
log_e("Firmware version:%*ph", (int)sizeof(buffer), buffer);
ret = -1;
hal->delay(15);
}
if (ret == -1) {
log_e("Failed get valid firmware version");
return ret;
}
memcpy(version, buffer, sizeof(*version));
memcpy(temp_pid, version->rom_pid, sizeof(version->rom_pid));
log_d("Rom_pid:%s", (const char *)temp_pid);
log_d("Rom_vid:%*p", (int)sizeof(version->rom_vid), version->rom_vid);
log_d("PID:%s", (const char *)version->patch_pid);
log_d("VID:%*p", (int)sizeof(version->patch_vid), version->patch_vid);
log_d("Sensor ID:%d", version->sensor_id);
return 0;
}
int TouchDrvGT9895::convertChipInfo(ChipInfo *info, const uint8_t *data)
{
int i = 0;
ChipInfoVersion *version = &info->version;
ChipInfoFeature *feature = &info->feature;
ChipInfoParams *parm = &info->parm;
ChipInfoMisc *misc = &info->misc;
info->length = *((uint16_t *)data);
data += 2;
memcpy(version, data, sizeof(*version));
data += sizeof(ChipInfoVersion);
memcpy(feature, data, sizeof(*feature));
data += sizeof(ChipInfoFeature);
parm->drv_num = *(data++);
parm->sen_num = *(data++);
parm->button_num = *(data++);
parm->force_num = *(data++);
parm->active_scan_rate_num = *(data++);
if (parm->active_scan_rate_num > GT9895_MAX_SCAN_RATE_NUM) {
log_e("Invalid scan rate num %d > %d", parm->active_scan_rate_num, GT9895_MAX_SCAN_RATE_NUM);
return -1;
}
for (i = 0; i < parm->active_scan_rate_num; i++)
parm->active_scan_rate[i] = *((uint16_t *)(data + i * 2));
data += parm->active_scan_rate_num * 2;
parm->mutual_freq_num = *(data++);
if (parm->mutual_freq_num > GT9895_MAX_SCAN_FREQ_NUM) {
log_e("invalid mutual freq num %d > %d", parm->mutual_freq_num, GT9895_MAX_SCAN_FREQ_NUM);
return -1;
}
for (i = 0; i < parm->mutual_freq_num; i++)
parm->mutual_freq[i] = *((uint16_t *)(data + i * 2));
data += parm->mutual_freq_num * 2;
parm->self_tx_freq_num = *(data++);
if (parm->self_tx_freq_num > GT9895_MAX_SCAN_FREQ_NUM) {
log_e("Invalid tx freq num %d > %d", parm->self_tx_freq_num, GT9895_MAX_SCAN_FREQ_NUM);
return -1;
}
for (i = 0; i < parm->self_tx_freq_num; i++)
parm->self_tx_freq[i] = *((uint16_t *)(data + i * 2));
data += parm->self_tx_freq_num * 2;
parm->self_rx_freq_num = *(data++);
if (parm->self_rx_freq_num > GT9895_MAX_SCAN_FREQ_NUM) {
log_e("Invalid rx freq num %d > %d", parm->self_rx_freq_num, GT9895_MAX_SCAN_FREQ_NUM);
return -1;
}
for (i = 0; i < parm->self_rx_freq_num; i++)
parm->self_rx_freq[i] = *((uint16_t *)(data + i * 2));
data += parm->self_rx_freq_num * 2;
parm->stylus_freq_num = *(data++);
if (parm->stylus_freq_num > GT9895_MAX_FREQ_NUM_STYLUS) {
log_e("Invalid stylus freq num %d > %d", parm->stylus_freq_num, GT9895_MAX_FREQ_NUM_STYLUS);
return -1;
}
for (i = 0; i < parm->stylus_freq_num; i++)
parm->stylus_freq[i] = *((uint16_t *)(data + i * 2));
data += parm->stylus_freq_num * 2;
memcpy(misc, data, sizeof(*misc));
return 0;
}
void TouchDrvGT9895::printChipInfo(ChipInfo *ic_info)
{
ChipInfoVersion *version = &ic_info->version;
ChipInfoFeature *feature = &ic_info->feature;
ChipInfoParams *parm = &ic_info->parm;
ChipInfoMisc *misc = &ic_info->misc;
(void)version;
(void)feature;
(void)parm;
(void)misc;
log_d("ic_info_length: %d", ic_info->length);
log_d("info_customer_id: 0x%01X", version->info_customer_id);
log_d("info_version_id: 0x%01X", version->info_version_id);
log_d("ic_die_id: 0x%01X", version->ic_die_id);
log_d("ic_version_id: 0x%01X", version->ic_version_id);
log_d("config_id: 0x%4lX", version->config_id);
log_d("config_version: 0x%01X", version->config_version);
log_d("frame_data_customer_id: 0x%01X", version->frame_data_customer_id);
log_d("frame_data_version_id: 0x%01X", version->frame_data_version_id);
log_d("touch_data_customer_id: 0x%01X", version->touch_data_customer_id);
log_d("touch_data_version_id: 0x%01X", version->touch_data_version_id);
log_d("freq_hop_feature: 0x%04X", feature->freqhop_feature);
log_d("calibration_feature: 0x%04X", feature->calibration_feature);
log_d("gesture_feature: 0x%04X", feature->gesture_feature);
log_d("side_touch_feature: 0x%04X", feature->side_touch_feature);
log_d("stylus_feature: 0x%04X", feature->stylus_feature);
log_d("Drv*Sen,Button,Force num: %u x %u, %u, %u", parm->drv_num, parm->sen_num, parm->button_num, parm->force_num);
log_d("Cmd: 0x%04lX, %u", misc->cmd_addr, misc->cmd_max_len);
log_d("Cmd-Reply: 0x%04lX, %u", misc->cmd_reply_addr, misc->cmd_reply_len);
log_d("FW-State: 0x%04lX, %u", misc->fw_state_addr, misc->fw_state_len);
log_d("FW-Buffer: 0x%04lX, %u", misc->fw_buffer_addr, misc->fw_buffer_max_len);
log_d("Touch-Data: 0x%04lX, %u", misc->touch_data_addr, misc->touch_data_head_len);
log_d("point_struct_len: %u", misc->point_struct_len);
log_d("mutual_raw_data_addr: 0x%04lX", misc->mutual_rawdata_addr);
log_d("mutual_diff_data_addr: 0x%04lX", misc->mutual_diffdata_addr);
log_d("self_raw_data_addr: 0x%04lX", misc->self_rawdata_addr);
log_d("self_diff_data_addr: 0x%04lX", misc->self_diffdata_addr);
log_d("stylus_raw_data_addr: 0x%04lX, %u", misc->stylus_rawdata_addr, misc->stylus_rawdata_len);
log_d("esd_addr: 0x%04lX", misc->esd_addr);
}
int TouchDrvGT9895::readChipInfo(ChipInfo *ic_info)
{
int i = 0;
uint16_t length = 0;
uint8_t afe_data[GT9895_INFO_MAX_LENGTH] = {0};
for (i = 0; i < 3; i++) {
ByteUnion u;
u.value = GT9895_REG_INFO;
if (comm->writeThenRead(u.byte_array, 4, (uint8_t *)&length, sizeof(length)) == -1) {
log_e("Failed get ic info length");
hal->delay(5);
continue;
}
if (length >= GT9895_INFO_MAX_LENGTH || length == 0) {
log_e("Invalid ic info length %d, retry %d", length, i);
continue;
}
if (comm->writeThenRead(u.byte_array, 4, afe_data, length) == -1) {
log_e("Failed get ic info data");
hal->delay(5);
continue;
}
/* judge whether the data is valid */
if (is_risk_data((const uint8_t *)afe_data, length)) {
log_e("Firmware info data invalid");
hal->delay(5);
continue;
}
if (checksum_cmp((const uint8_t *)afe_data, length, CHECKSUM_MODE_U8_LE)) {
log_e("Firmware info checksum error!");
hal->delay(5);
continue;
}
break;
}
if (i == 3) {
log_e("Failed get ic info");
return -1;
}
if (convertChipInfo(ic_info, afe_data) == -1) {
log_e("Convert ic info encounter error");
return -1;
}
printChipInfo(ic_info);
/* check some key info */
if (!ic_info->misc.cmd_addr || !ic_info->misc.fw_buffer_addr ||
!ic_info->misc.touch_data_addr) {
log_e("cmd_addr fw_buf_addr and touch_data_addr is null");
return -1;
}
return 0;
}
void TouchDrvGT9895::clearStatus()
{
uint8_t buffer[5] = { 0x00, 0x01, 0x03, 0x08, 0x00};
comm->writeBuffer(buffer, 5);
}
int TouchDrvGT9895::getTouchData(uint8_t *pre_buf, uint32_t pre_buf_len)
{
uint8_t touch_num = 0;
uint8_t point_type = 0;
uint8_t buffer[GT9895_IRQ_EVENT_HEAD_LEN + GT9895_BYTES_PER_POINT * GT9895_MAX_TOUCH + 2];
/* clean event buffer */
memset(&_ts_event, 0, sizeof(_ts_event));
/* copy pre-data to buffer */
memcpy(buffer, pre_buf, pre_buf_len);
touch_num = buffer[2] & 0x0F;
if (touch_num > GT9895_MAX_TOUCH) {
log_e("invalid touch num %d", touch_num);
return 0;
}
if (touch_num > 2) {
ByteUnion u;
u.value = GT9895_REG_POINT + pre_buf_len;
if (comm->writeThenRead(u.byte_array, 4, &buffer[pre_buf_len], (touch_num - 2) * GT9895_BYTES_PER_POINT) == -1) {
log_e("Failed get touch data");
return 0;
}
}
if (touch_num > 0) {
point_type = buffer[GT9895_IRQ_EVENT_HEAD_LEN] & 0x0F;
if (point_type == GT9895_POINT_TYPE_STYLUS || point_type == GT9895_POINT_TYPE_STYLUS_HOVER) {
if (checksum_cmp(&buffer[GT9895_IRQ_EVENT_HEAD_LEN], GT9895_BYTES_PER_POINT * 2 + 2, CHECKSUM_MODE_U8_LE)) {
// log_e("Touch data checksum error");
return 0;
}
} else {
if (checksum_cmp(&buffer[GT9895_IRQ_EVENT_HEAD_LEN], touch_num * GT9895_BYTES_PER_POINT + 2, CHECKSUM_MODE_U8_LE)) {
// log_e("Touch data checksum error");
return 0;
}
}
}
_ts_event.fp_flag = pre_buf[0] & GT9895_FP_EVENT;
/* finger info */
_ts_event.event_type = EVENT_TOUCH;
uint32_t id = 0, x = 0, y = 0, w = 0;
uint8_t *pdat = &buffer[GT9895_IRQ_EVENT_HEAD_LEN];
for (int i = 0; i < touch_num; i++) {
id = (pdat[0] >> 4) & 0x0F;
if (id >= GT9895_MAX_TOUCH) {
log_e("Invalid finger id");
_ts_event.touch_data.touch_num = 0;
return 0;
}
x = *((uint16_t *)(pdat + 2));
y = *((uint16_t *)(pdat + 4));
w = *((uint16_t *)(pdat + 6));
_ts_event.touch_data.coords[id].status = TS_TOUCH;
_ts_event.touch_data.coords[id].x = x;
_ts_event.touch_data.coords[id].y = y;
_ts_event.touch_data.coords[id].w = w;
pdat += GT9895_BYTES_PER_POINT;
}
_ts_event.touch_data.touch_num = touch_num;
return touch_num;
}
bool TouchDrvGT9895::initImpl()
{
if (_irq != -1) {
hal->pinMode(_irq, INPUT);
}
reset();
if (readVersion(&_version) != 0) {
return false;
}
readChipInfo(&_ic_info);
return true;
}
/*
[ 7142][I][SensorCommon.hpp:65] begin(): Using Arduino Wire interface.
[ 7148][W][Wire.cpp:301] begin(): Bus already started in Master Mode.
[ 7197][D][TouchDrvGT9895.cpp:348] readVersion(): Rom_pid:BERLIN
[ 7203][D][TouchDrvGT9895.cpp:349] readVersion(): Rom_vid:0x3fc95c33
[ 7210][D][TouchDrvGT9895.cpp:350] readVersion(): PID:9895
[ 7215][D][TouchDrvGT9895.cpp:351] readVersion(): VID:0x3fc95c3f
[ 7221][D][TouchDrvGT9895.cpp:352] readVersion(): Sensor ID:255
[ 7244][I][TouchDrvGT9895.cpp:435] printChipInfo(): ic_info_length: 173
[ 7252][I][TouchDrvGT9895.cpp:436] printChipInfo(): info_customer_id: 0x1
[ 7260][I][TouchDrvGT9895.cpp:437] printChipInfo(): info_version_id: 0x0
[ 7267][I][TouchDrvGT9895.cpp:438] printChipInfo(): ic_die_id: 0x0
[ 7275][I][TouchDrvGT9895.cpp:439] printChipInfo(): ic_version_id: 0x0
[ 7283][I][TouchDrvGT9895.cpp:440] printChipInfo(): config_id: 0x650BFC22
[ 7291][I][TouchDrvGT9895.cpp:441] printChipInfo(): config_version: 0x2
[ 7299][I][TouchDrvGT9895.cpp:442] printChipInfo(): frame_data_customer_id: 0x1
[ 7307][I][TouchDrvGT9895.cpp:443] printChipInfo(): frame_data_version_id: 0x0
[ 7315][I][TouchDrvGT9895.cpp:444] printChipInfo(): touch_data_customer_id: 0x1
[ 7323][I][TouchDrvGT9895.cpp:445] printChipInfo(): touch_data_version_id: 0x0
[ 7330][I][TouchDrvGT9895.cpp:446] printChipInfo(): freq_hop_feature: 0x0000
[ 7338][I][TouchDrvGT9895.cpp:447] printChipInfo(): calibration_feature: 0x0000
[ 7346][I][TouchDrvGT9895.cpp:448] printChipInfo(): gesture_feature: 0x0000
[ 7354][I][TouchDrvGT9895.cpp:449] printChipInfo(): side_touch_feature: 0x0000
[ 7363][I][TouchDrvGT9895.cpp:450] printChipInfo(): stylus_feature: 0x0000
[ 7371][I][TouchDrvGT9895.cpp:452] printChipInfo(): Drv*Sen,Button,Force num: 10 x 23, 0, 0
[ 7379][I][TouchDrvGT9895.cpp:453] printChipInfo(): Cmd: 0x10174, 16
[ 7388][I][TouchDrvGT9895.cpp:454] printChipInfo(): Cmd-Reply: 0x10184, 16
[ 7396][I][TouchDrvGT9895.cpp:455] printChipInfo(): FW-State: 0x10218, 92
[ 7405][I][TouchDrvGT9895.cpp:456] printChipInfo(): FW-Buffer: 0x13D80, 4096
[ 7413][I][TouchDrvGT9895.cpp:457] printChipInfo(): Touch-Data: 0x10308, 8
[ 7422][I][TouchDrvGT9895.cpp:458] printChipInfo(): point_struct_len: 8
[ 7429][I][TouchDrvGT9895.cpp:459] printChipInfo(): mutual_raw_data_addr: 0x13830
[ 7438][I][TouchDrvGT9895.cpp:460] printChipInfo(): mutual_diff_data_addr: 0x11224
[ 7446][I][TouchDrvGT9895.cpp:461] printChipInfo(): self_raw_data_addr: 0x137C4
[ 7454][I][TouchDrvGT9895.cpp:462] printChipInfo(): self_diff_data_addr: 0x13758
[ 7462][I][TouchDrvGT9895.cpp:463] printChipInfo(): stylus_raw_data_addr: 0x0000, 0
[ 7471][I][TouchDrvGT9895.cpp:464] printChipInfo(): esd_addr: 0x10170
*/

View File

@@ -0,0 +1,98 @@
/**
*
* @license MIT License
*
* Copyright (c) 2024 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file TouchDrvGT9895.hpp
* @author Lewis He (lewishe@outlook.com)
* @date 2024-09-21
*
*/
#pragma once
#include "REG/GT9895Constants.h"
#include "TouchDrvInterface.hpp"
class TouchDrvGT9895 : public TouchDrvInterface, public GT9895Constants
{
public:
TouchDrvGT9895();
~TouchDrvGT9895();
#if defined(ARDUINO)
bool begin(TwoWire &wire, uint8_t address = GT9895_SLAVE_ADDRESS_L, int sda = -1, int scl = -1);
#elif defined(ESP_PLATFORM)
#if defined(USEING_I2C_LEGACY)
bool begin(i2c_port_t port_num, uint8_t addr = GT9895_SLAVE_ADDRESS_L, int sda = -1, int scl = -1);
#else
bool begin(i2c_master_bus_handle_t handle, uint8_t addr = GT9895_SLAVE_ADDRESS_L);
#endif //ESP_PLATFORM
#endif //ARDUINO
bool begin(SensorCommCustom::CustomCallback callback,
SensorCommCustomHal::CustomHalCallback hal_callback,
uint8_t addr = GT9895_SLAVE_ADDRESS_L);
void deinit();
void reset();
void sleep();
void wakeup();
void idle();
uint8_t getSupportTouchPoint();
uint8_t getPoint(int16_t *x_array, int16_t *y_array, uint8_t size = 1);
bool isPressed();
uint32_t getChipID();
bool getResolution(int16_t *x, int16_t *y);
const char *getModelName();
void setGpioCallback(CustomMode mode_cb,
CustomWrite write_cb,
CustomRead read_cb);
private:
int is_risk_data(const uint8_t *data, int size);
int checksum_cmp(const uint8_t *data, int size, int mode);
int readVersion(ChipFirmwareVersion *version);
int convertChipInfo(ChipInfo *info, const uint8_t *data);
void printChipInfo(ChipInfo *ic_info);
int readChipInfo(ChipInfo *ic_info);
void clearStatus();
int getTouchData( uint8_t *pre_buf, uint32_t pre_buf_len);
bool initImpl();
protected:
std::unique_ptr<SensorCommBase> comm;
std::unique_ptr<SensorHal> hal;
ChipTsEvent _ts_event;
ChipFirmwareVersion _version;
ChipInfo _ic_info;
};

View File

@@ -0,0 +1,100 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* Permission is hereby granted,free of charge,to any person obtaining a copy
* of this software and associated documentation files (the "Software"),to deal
* in the Software without restriction,including without limitation the rights
* to use,copy,modify,merge,publish,distribute,sublicense,and/or sell
* copies of the Software,and to permit persons to whom the Software is
* furnished to do so,subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS",WITHOUT WARRANTY OF ANY KIND,EXPRESS OR
* IMPLIED,INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,DAMAGES OR OTHER
* LIABILITY,WHETHER IN AN ACTION OF CONTRACT,TORT OR OTHERWISE,ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file TouchDrvInterface.cpp
* @author Lewis He (lewishe@outlook.com)
* @date 2023-09-21
*
*/
#include "TouchDrvInterface.hpp"
TouchDrvInterface::TouchDrvInterface() :
_resX(0),
_resY(0),
_xMax(0),
_yMax(0),
_swapXY(false),
_mirrorX(false),
_mirrorY(false),
_rst(-1),
_irq(-1),
_chipID(0x00),
_HButtonCallback(nullptr),
_userData(nullptr)
{
}
TouchDrvInterface::~TouchDrvInterface()
{
}
uint32_t TouchDrvInterface::getChipID()
{
return _chipID;
}
void TouchDrvInterface::setPins(int rst, int irq)
{
_irq = irq;
_rst = rst;
}
void TouchDrvInterface::setSwapXY(bool swap)
{
_swapXY = swap;
}
void TouchDrvInterface::setMirrorXY(bool mirrorX, bool mirrorY)
{
_mirrorX = mirrorX;
_mirrorY = mirrorY;
}
void TouchDrvInterface::setMaxCoordinates(uint16_t x, uint16_t y)
{
_xMax = x;
_yMax = y;
}
void TouchDrvInterface::updateXY(uint8_t pointNum, int16_t *xBuffer, int16_t *yBuffer)
{
if (!pointNum)
return;
for (int i = 0; i < pointNum; ++i) {
if (_swapXY) {
uint16_t tmp = xBuffer[i];
xBuffer[i] = yBuffer[i];
yBuffer[i] = tmp;
}
if (_mirrorX && _xMax ) {
xBuffer[i] = _xMax - xBuffer[i];
}
if (_mirrorY && _yMax) {
yBuffer[i] = _yMax - yBuffer[i];
}
}
}

View File

@@ -0,0 +1,133 @@
/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* Permission is hereby granted,free of charge,to any person obtaining a copy
* of this software and associated documentation files (the "Software"),to deal
* in the Software without restriction,including without limitation the rights
* to use,copy,modify,merge,publish,distribute,sublicense,and/or sell
* copies of the Software,and to permit persons to whom the Software is
* furnished to do so,subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS",WITHOUT WARRANTY OF ANY KIND,EXPRESS OR
* IMPLIED,INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,DAMAGES OR OTHER
* LIABILITY,WHETHER IN AN ACTION OF CONTRACT,TORT OR OTHERWISE,ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file TouchDrvInterface.hpp
* @author Lewis He (lewishe@outlook.com)
* @date 2023-04-17
*
*/
#pragma once
#include "SensorPlatform.hpp"
class TouchData
{
public:
TouchData() {}
~TouchData() {};
uint8_t available;
uint8_t id[5];
int16_t x[5];
int16_t y[5];
uint8_t status[5];
uint8_t pressure[5];
uint16_t getX(uint8_t index = 0)
{
return x[index];
}
uint16_t getY(uint8_t index = 0)
{
return y[index];
}
uint16_t getPressure(uint8_t index = 0)
{
return pressure[index];
}
uint16_t getStatus(uint8_t index = 0)
{
return status[index];
}
};
class TouchDrvInterface : public SensorHalCustom
{
public:
using HomeButtonCallback = void(*)(void *user_data);
TouchDrvInterface();
virtual ~TouchDrvInterface();
#if defined(ARDUINO)
virtual bool begin(TwoWire &wire, uint8_t address, int sda, int scl) = 0;
#elif defined(ESP_PLATFORM)
#if defined(USEING_I2C_LEGACY)
virtual bool begin(i2c_port_t port_num, uint8_t addr, int sda, int scl) = 0;
#else
virtual bool begin(i2c_master_bus_handle_t handle, uint8_t addr) = 0;
#endif
#endif // defined(ARDUINO)
virtual bool begin(SensorCommCustom::CustomCallback callback,
SensorCommCustomHal::CustomHalCallback hal_callback,
uint8_t addr) = 0;
virtual void reset() = 0;
virtual uint8_t getPoint(int16_t *x_array, int16_t *y_array, uint8_t get_point) = 0;
virtual bool isPressed() = 0;
virtual const char *getModelName() = 0;
virtual void sleep() = 0;
virtual void wakeup() = 0;
virtual void idle() = 0;
virtual uint8_t getSupportTouchPoint() = 0;
virtual bool getResolution(int16_t *x, int16_t *y) = 0;
virtual void setGpioCallback(CustomMode mode_cb,
CustomWrite write_cb,
CustomRead read_cb) = 0;
uint32_t getChipID();
void setPins(int rst, int irq);
void setSwapXY(bool swap);
void setMirrorXY(bool mirrorX, bool mirrorY);
void setMaxCoordinates(uint16_t x, uint16_t y);
void updateXY(uint8_t pointNum, int16_t *xBuffer, int16_t *yBuffer);
protected:
uint16_t _resX, _resY, _xMax, _yMax;
bool _swapXY, _mirrorX, _mirrorY;
int _rst;
int _irq;
uint32_t _chipID;
HomeButtonCallback _HButtonCallback;
void *_userData;
};

View File

@@ -0,0 +1,54 @@
/**
*
* @license MIT License
*
* Copyright (c) 2024 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file VirtualGpio.hpp
* @author Lewis He (lewishe@outlook.com)
* @date 2024-11-22
*
*/
#pragma once
#include <stdint.h>
class VirtualGpio
{
public:
virtual void pinMode(uint8_t pin, uint8_t mode) = 0;
virtual void digitalWrite(uint8_t pin, uint8_t val) = 0;
virtual int digitalRead(uint8_t pin) = 0;
virtual void setClock(uint32_t frequency)
{
(void)frequency;
};
virtual uint32_t getClock()
{
return 0;
};
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,479 @@
/**
* Copyright (c) 2020 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 bmm150.h
* @date 2020-06-03
* @version v2.0.0
*
*/
/*!
* @defgroup bmm150 BMM150
*/
#ifndef _BMM150_H
#define _BMM150_H
/*! CPP guard */
#ifdef __cplusplus
extern "C" {
#endif
/********************************************************************/
/* header files */
#include "bmm150_defs.h"
/********************************************************************/
/* (extern) variable declarations */
/********************************************************************/
/* function prototype declarations */
/**
* \ingroup bmm150
* \defgroup bmm150ApiInit Initialization
* @brief Initialize the sensor and device structure
*/
/*!
* \ingroup bmm150ApiInit
* \page bmm150_api_bmm150_init bmm150_init
* \code
* int8_t bmm150_init(struct bmm150_dev *dev);
* \endcode
* @details This API is the entry point, Call this API before using other APIs.
* This API reads the chip-id of the sensor which is the first step to
* verify the sensor and also it configures the read mechanism of SPI and
* I2C interface.
*
* @param[in,out] dev : Structure instance of bmm150_dev
* @note : Refer user guide for detailed info.
*
* @return Result of API execution status
* @retval 0 -> Success
* @retval >0 -> Warning
* @retval <0 -> Fail
*/
int8_t bmm150_init(struct bmm150_dev *dev);
/**
* \ingroup bmm150
* \defgroup bmm150ApiRegs Registers
* @brief Read / Write data to the given register address of the sensor
*/
/*!
* \ingroup bmm150ApiRegs
* \page bmm150_api_bmm150_set_regs bmm150_set_regs
* \code
* int8_t bmm150_set_regs(uint8_t reg_addr, const uint8_t *reg_data, uint32_t len, struct bmm150_dev *dev);
* \endcode
* @details This API writes the given data to the register address
* of the sensor.
*
* @param[in] reg_addr : Register address from where the data to be written.
* @param[in] reg_data : Pointer to data buffer which is to be written
* in the reg_addr of sensor.
* @param[in] len : No of bytes of data to write..
* @param[in] dev : Structure instance of bmm150_dev.
*
* @return Result of API execution status
* @retval 0 -> Success
* @retval >0 -> Warning
* @retval <0 -> Fail
*/
int8_t bmm150_set_regs(uint8_t reg_addr, const uint8_t *reg_data, uint32_t len, struct bmm150_dev *dev);
/*!
* \ingroup bmm150ApiRegs
* \page bmm150_api_bmm150_get_regs bmm150_get_regs
* \code
* int8_t bmm150_get_regs(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, struct bmm150_dev *dev)
* \endcode
* @details This API reads the data from the given register address of sensor.
*
* @param[in] reg_addr : Register address from where the data to be read
* @param[out] reg_data : Pointer to data buffer to store the read data.
* @param[in] len : No of bytes of data to be read.
* @param[in] dev : Structure instance of bmm150_dev.
*
* @return Result of API execution status
* @retval 0 -> Success
* @retval >0 -> Warning
* @retval <0 -> Fail
*/
int8_t bmm150_get_regs(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, struct bmm150_dev *dev);
/**
* \ingroup bmm150
* \defgroup bmm150ApiSoftreset Soft reset
* @brief Perform soft reset of the sensor
*/
/*!
* \ingroup bmm150ApiSoftreset
* \page bmm150_api_bmm150_soft_reset bmm150_soft_reset
* \code
* int8_t bmm150_soft_reset(struct bmm150_dev *dev);
* \endcode
* @details This API is used to perform soft-reset of the sensor
* where all the registers are reset to their default values except 0x4B.
*
* @param[in] dev : Structure instance of bmm150_dev.
*
* @return Result of API execution status
* @retval 0 -> Success
* @retval >0 -> Warning
* @retval <0 -> Fail
*/
int8_t bmm150_soft_reset(struct bmm150_dev *dev);
/**
* \ingroup bmm150
* \defgroup bmm150ApiPowermode Power mode
* @brief Set / Get power mode of the sensor
*/
/*!
* \ingroup bmm150ApiPowermode
* \page bmm150_api_bmm150_set_op_mode bmm150_set_op_mode
* \code
* int8_t bmm150_set_op_mode(const struct bmm150_settings *settings, struct bmm150_dev *dev);
* \endcode
* @details This API is used to set the power mode of the sensor.
*
* @param[in] settings : Structure instance of bmm150_settings.
* @param[in] dev : Structure instance of bmm150_dev.
*
*@verbatim
* settings->pwr_mode | Power mode
* ------------------------|-----------------------
* 0x00 | BMM150_POWERMODE_NORMAL
* 0x01 | BMM150_POWERMODE_FORCED
* 0x03 | BMM150_POWERMODE_SLEEP
* 0x04 | BMM150_POWERMODE_SUSPEND
*@endverbatim
*
* @return Result of API execution status
* @retval 0 -> Success
* @retval >0 -> Warning
* @retval <0 -> Fail
*/
int8_t bmm150_set_op_mode(const struct bmm150_settings *settings, struct bmm150_dev *dev);
/*!
* \ingroup bmm150ApiPowermode
* \page bmm150_api_bmm150_get_op_mode bmm150_get_op_mode
* \code
* int8_t bmm150_get_op_mode(uint8_t *op_mode, struct bmm150_dev *dev);
* \endcode
* @details This API is used to get the power mode of the sensor.
*
* @param[out] op_mode : power mode of the sensor.
* @param[in] dev : Structure instance of bmm150_dev.
*
*@verbatim
* op_mode | Power mode
* -------------|-----------------------
* 0x00 | BMM150_POWERMODE_NORMAL
* 0x01 | BMM150_POWERMODE_FORCED
* 0x03 | BMM150_POWERMODE_SLEEP
* 0x04 | BMM150_POWERMODE_SUSPEND
*@endverbatim
*
* @return Result of API execution status
* @retval 0 -> Success
* @retval >0 -> Warning
* @retval <0 -> Fail
*/
int8_t bmm150_get_op_mode(uint8_t *op_mode, struct bmm150_dev *dev);
/**
* \ingroup bmm150
* \defgroup bmm150ApiPresetmode Preset mode
* @brief Set preset mode of the sensor
*/
/*!
* \ingroup bmm150ApiPresetmode
* \page bmm150_api_bmm150_set_presetmode bmm150_set_presetmode
* \code
* int8_t bmm150_set_presetmode(struct bmm150_settings *settings, struct bmm150_dev *dev);
* \endcode
* @details This API is used to set the preset mode of the sensor.
*
* @param[in] settings : Structure instance of bmm150_settings.
* @param[in] dev : Structure instance of bmm150_dev.
*
*@verbatim
* settings->preset_mode | Preset mode
* ---------------------------|----------------------------------
* 0x01 | BMM150_PRESETMODE_LOWPOWER
* 0x02 | BMM150_PRESETMODE_REGULAR
* 0x03 | BMM150_PRESETMODE_HIGHACCURACY
* 0x04 | BMM150_PRESETMODE_ENHANCED
*@endverbatim
*
* @return Result of API execution status
* @retval 0 -> Success
* @retval >0 -> Warning
* @retval <0 -> Fail
*/
int8_t bmm150_set_presetmode(struct bmm150_settings *settings, struct bmm150_dev *dev);
/**
* \ingroup bmm150
* \defgroup bmm150ApiSensorSettings Sensor Settings
* @brief Set / Get sensor settings of the sensor
*/
/*!
* \ingroup bmm150ApiSensorSettings
* \page bmm150_api_bmm150_set_sensor_settings bmm150_set_sensor_settings
* \code
* int8_t bmm150_set_sensor_settings(uint16_t desired_settings, const struct bmm150_settings *settings, struct bmm150_dev *dev);
* \endcode
* @details This API sets the sensor settings based on the desired_settings
* and the dev structure configuration
*
* @param[in] desired_settings : Selection macro for selecting the setting.
* @param[in] settings : Structure instance of bmm150_settings.
* @param[in] dev : Structure instance of bmm150_dev.
*
* @note Assign the sensor setting macros (multiple macros can be
* set by doing a bitwise-OR operation) to the desired_settings parameter
* of this API to perform the corresponding setting.
*
* @note threshold interrupt for each axes are set by using bitwise AND
* operation of the following macros
* - BMM150_THRESHOLD_X
* - BMM150_THRESHOLD_Y
* - BMM150_THRESHOLD_Z
*
*@verbatim
* desired_settings | Selected sensor setting macros
* -------------------|--------------------------------
* 0x0001 | BMM150_SEL_DATA_RATE
* 0x0002 | BMM150_SEL_CONTROL_MEASURE
* 0x0004 | BMM150_SEL_XY_REP
* 0x0008 | BMM150_SEL_Z_REP
* 0x0010 | BMM150_SEL_DRDY_PIN_EN
* 0x0020 | BMM150_SEL_INT_PIN_EN
* 0x0040 | BMM150_SEL_DRDY_POLARITY
* 0x0080 | BMM150_SEL_INT_LATCH
* 0x0100 | BMM150_SEL_INT_POLARITY
* 0x0200 | BMM150_SEL_DATA_OVERRUN_INT
* 0x0400 | BMM150_SEL_OVERFLOW_INT
* 0x0800 | BMM150_SEL_HIGH_THRESHOLD_INT
* 0x1000 | BMM150_SEL_LOW_THRESHOLD_INT
* 0x2000 | BMM150_SEL_LOW_THRESHOLD_SETTING
* 0x4000 | BMM150_SEL_HIGH_THRESHOLD_SETTING
*@endverbatim
*
* @return Result of API execution status
* @retval 0 -> Success
* @retval >0 -> Warning
* @retval <0 -> Fail
*/
int8_t bmm150_set_sensor_settings(uint16_t desired_settings,
const struct bmm150_settings *settings,
struct bmm150_dev *dev);
/*!
* \ingroup bmm150ApiSensorSettings
* \page bmm150_api_bmm150_get_sensor_settings bmm150_get_sensor_settings
* \code
* int8_t bmm150_get_sensor_settings(struct bmm150_settings *settings, struct bmm150_dev *dev);
* \endcode
* @details This API gets all the sensor settings and updates the dev structure
*
* @param[in] settings : Structure instance of bmm150_settings.
* @param[in] dev : Structure instance of bmm150_dev.
*
* @return Result of API execution status
* @retval 0 -> Success
* @retval >0 -> Warning
* @retval <0 -> Fail
*/
int8_t bmm150_get_sensor_settings(struct bmm150_settings *settings, struct bmm150_dev *dev);
/**
* \ingroup bmm150
* \defgroup bmm150ApiMagData Read magnetometer data
* @brief Read magnetometer data
*/
/*!
* \ingroup bmm150ApiMagData
* \page bmm150_api_bmm150_read_mag_data bmm150_read_mag_data
* \code
* int8_t bbmm150_read_mag_data(struct bmm150_mag_data *mag_data, struct bmm150_dev *dev);
* \endcode
* @details This API reads the magnetometer data from registers 0x42 to 0x49
* and updates the dev structure with compensated mag data in micro-tesla
*
* @param[in] mag_data : Structure instance of bmm150_mag_data.
* @param[in,out] dev : Structure instance of bmm150_dev.
*
* @note The output mag data can be obtained either in int16_t or float format
* using this API.
* @note Enable the macro "BMM150_USE_FLOATING_POINT" in the bmm150_defs.h
* file and call this API to get the mag data in float,
* disable this macro to get the mag data in int16_t format
*
*@verbatim
* Mag data output(micro-tesla) | Mag data in dev structure(int16_t/float)
* --------------------------------|------------------------------------------
* X-axis data | mag_data->x
* Y-axis data | mag_data->y
* Z-axis data | mag_data->z
*@endverbatim
*
* @return Result of API execution status
* @retval 0 -> Success
* @retval >0 -> Warning
* @retval <0 -> Fail
*/
int8_t bmm150_read_mag_data(struct bmm150_mag_data *mag_data, struct bmm150_dev *dev);
/**
* \ingroup bmm150
* \defgroup bmm150ApiSelftest Self test
* @brief Perform self test
*/
/*!
* \ingroup bmm150ApiSelftest
* \page bmm150_api_bmm150_perform_self_test bmm150_perform_self_test
* \code
* int8_t bmm150_perform_self_test(uint8_t self_test_mode, struct bmm150_dev *dev);
* \endcode
* @details This API is used to perform the complete self test
* (both normal and advanced) for the BMM150 sensor
*
* @param[in] self_test_mode : The type of self test to be performed
* @param[in] dev : Structure instance of bmm150_dev.
*
*@verbatim
* self_test_mode | Self test enabled
* --------------------|--------------------------
* 0 | BMM150_SELF_TEST_NORMAL
* 1 | BMM150_SELF_TEST_ADVANCED
*@endverbatim
*
* @note The return value of this API gives us the result of self test.
*
* @note Performing advanced self test does soft reset of the sensor, User can
* set the desired settings after performing the advanced self test.
*
* @return Result of API execution status and self test result.
* @retval 0 BMM150_OK
* @retval 1 BMM150_W_NORMAL_SELF_TEST_YZ_FAIL
* @retval 2 BMM150_W_NORMAL_SELF_TEST_XZ_FAIL
* @retval 3 BMM150_W_NORMAL_SELF_TEST_Z_FAIL
* @retval 4 BMM150_W_NORMAL_SELF_TEST_XY_FAIL
* @retval 5 BMM150_W_NORMAL_SELF_TEST_Y_FAIL
* @retval 6 BMM150_W_NORMAL_SELF_TEST_X_FAIL
* @retval 7 BMM150_W_NORMAL_SELF_TEST_XYZ_FAIL
* @retval 8 BMM150_W_ADV_SELF_TEST_FAIL
*/
int8_t bmm150_perform_self_test(uint8_t self_test_mode, struct bmm150_dev *dev);
/**
* \ingroup bmm150
* \defgroup bmm150ApiInt Interrupt status
* @brief Obtain interrupt staus flags
*/
/*!
* \ingroup bmm150ApiInt
* \page bmm150_api_bmm150_get_interrupt_status bmm150_get_interrupt_status
* \code
* int8_t bmm150_get_interrupt_status(struct bmm150_dev *dev);
* \endcode
* @details This API obtains the status flags of all interrupt
* which is used to check for the assertion of interrupts
*
* @param[in,out] dev : Structure instance of bmm150_dev.
*
* @note The status flags of all the interrupts are stored in the
* dev->int_status.
*
* @note The value of dev->int_status is performed a bitwise AND operation
* with predefined interrupt status macros to find the interrupt status
* which is either set or reset.
*
* Ex.
* if (dev->int_status & BMM150_INT_ASSERTED_DRDY)
* {
* Occurrence of data ready interrupt
* } else {
* No interrupt occurred
* }
*
* @return Result of API execution status and self test result.
* @retval 0 -> Success
* @retval >0 -> Warning
* @retval <0 -> Fail
*/
int8_t bmm150_get_interrupt_status(struct bmm150_dev *dev);
/**
* \ingroup bmm150
* \defgroup bmm150ApiAux Compensate magnetometer data
* @brief Compensation of magnetometer data
*/
/*!
* \ingroup bmm150ApiAux
* \page bmm150_api_bmm150_aux_mag_data bmm150_aux_mag_data
* \code
* int8_t bmm150_aux_mag_data(uint8_t *aux_data, struct bmm150_mag_data *mag_data, const struct bmm150_dev *dev);
* \endcode
* @details This API is used to compensate the raw mag data
*
* @param[in] aux_data : Raw mag data obtained from BMI160 registers
* @param[in] mag_data : Structure instance of bmm150_mag_data.
* @param[in,out] dev : Structure instance of bmm150_dev.
*
* @return Result of API execution status and self test result.
* @retval 0 -> Success
* @retval >0 -> Warning
* @retval <0 -> Fail
*/
int8_t bmm150_aux_mag_data(uint8_t *aux_data, struct bmm150_mag_data *mag_data, const struct bmm150_dev *dev);
#ifdef __cplusplus
}
#endif /* End of CPP guard */
#endif /* _BMM150_H */

View File

@@ -0,0 +1,643 @@
/**
* Copyright (c) 2020 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 bmm150_defs.h
* @date 2020-06-03
* @version v2.0.0
*
*/
/*! \file bmm150_defs.h */
#ifndef _BMM150_DEFS_H
#define _BMM150_DEFS_H
/******************************************************************************/
/*! @name Header includes */
/******************************************************************************/
#ifdef __KERNEL__
#include <linux/types.h>
#else
#include <stdint.h>
#include <stddef.h>
#endif
/******************************************************************************/
/*! @name Common macros */
/******************************************************************************/
#ifdef __KERNEL__
#if (LONG_MAX) > 0x7fffffff
#define __have_long64 1
#elif (LONG_MAX) == 0x7fffffff
#define __have_long32 1
#endif
#endif
#if !defined(UINT8_C)
#define INT8_C(x) x
#if (INT_MAX) > 0x7f
#define UINT8_C(x) x
#else
#define UINT8_C(x) x##U
#endif
#endif
#if !defined(UINT16_C)
#define INT16_C(x) x
#if (INT_MAX) > 0x7fff
#define UINT16_C(x) x
#else
#define UINT16_C(x) x##U
#endif
#endif
#if !defined(INT32_C) && !defined(UINT32_C)
#if __have_long32
#define INT32_C(x) x##L
#define UINT32_C(x) x##UL
#else
#define INT32_C(x) x
#define UINT32_C(x) x##U
#endif
#endif
#if !defined(INT64_C) && !defined(UINT64_C)
#if __have_long64
#define INT64_C(x) x##L
#define UINT64_C(x) x##UL
#else
#define INT64_C(x) x##LL
#define UINT64_C(x) x##ULL
#endif
#endif
/*! @name C standard macros */
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *) 0)
#endif
#endif
/******************************************************************************/
/*! @name Compiler switch macros Definitions */
/******************************************************************************/
#ifndef BMM150_USE_FLOATING_POINT /*< Check if floating point (using BMM150_USE_FLOATING_POINT) is enabled */
#ifndef BMM150_USE_FIXED_POINT /*< If floating point is not enabled then enable BMM150_USE_FIXED_POINT */
#define BMM150_USE_FIXED_POINT
#endif
#endif
/******************************************************************************/
/*! @name General Macro Definitions */
/******************************************************************************/
/*! @name API success code */
#define BMM150_OK INT8_C(0)
/*! @name To define TRUE or FALSE */
#define BMM150_TRUE UINT8_C(1)
#define BMM150_FALSE UINT8_C(0)
/*! @name API error codes */
#define BMM150_E_NULL_PTR INT8_C(-1)
#define BMM150_E_DEV_NOT_FOUND INT8_C(-2)
#define BMM150_E_INVALID_CONFIG INT8_C(-3)
#define BMM150_E_COM_FAIL INT8_C(-4)
/*! @name API warning codes */
#define BMM150_W_NORMAL_SELF_TEST_YZ_FAIL INT8_C(1)
#define BMM150_W_NORMAL_SELF_TEST_XZ_FAIL INT8_C(2)
#define BMM150_W_NORMAL_SELF_TEST_Z_FAIL INT8_C(3)
#define BMM150_W_NORMAL_SELF_TEST_XY_FAIL INT8_C(4)
#define BMM150_W_NORMAL_SELF_TEST_Y_FAIL INT8_C(5)
#define BMM150_W_NORMAL_SELF_TEST_X_FAIL INT8_C(6)
#define BMM150_W_NORMAL_SELF_TEST_XYZ_FAIL INT8_C(7)
#define BMM150_W_ADV_SELF_TEST_FAIL INT8_C(8)
/*! @name CHIP ID & SOFT RESET VALUES */
#define BMM150_CHIP_ID UINT8_C(0x32)
#define BMM150_SET_SOFT_RESET UINT8_C(0x82)
/*! @name POWER MODE DEFINTIONS */
#define BMM150_POWERMODE_NORMAL UINT8_C(0x00)
#define BMM150_POWERMODE_FORCED UINT8_C(0x01)
#define BMM150_POWERMODE_SLEEP UINT8_C(0x03)
#define BMM150_POWERMODE_SUSPEND UINT8_C(0x04)
/*! @name Power mode settings */
#define BMM150_POWER_CNTRL_DISABLE UINT8_C(0x00)
#define BMM150_POWER_CNTRL_ENABLE UINT8_C(0x01)
/*! @name Sensor delay time settings */
#define BMM150_DELAY_SOFT_RESET UINT8_C(1000)
#define BMM150_DELAY_NORMAL_SELF_TEST UINT8_C(2000)
#define BMM150_START_UP_TIME UINT8_C(3000)
#define BMM150_DELAY_ADV_SELF_TEST UINT8_C(4000)
/*! @name ENABLE/DISABLE DEFINITIONS */
#define BMM150_XYZ_CHANNEL_ENABLE UINT8_C(0x00)
#define BMM150_XYZ_CHANNEL_DISABLE UINT8_C(0x07)
/*! @name Register Address */
#define BMM150_REG_CHIP_ID UINT8_C(0x40)
#define BMM150_REG_DATA_X_LSB UINT8_C(0x42)
#define BMM150_REG_DATA_READY_STATUS UINT8_C(0x48)
#define BMM150_REG_INTERRUPT_STATUS UINT8_C(0x4A)
#define BMM150_REG_POWER_CONTROL UINT8_C(0x4B)
#define BMM150_REG_OP_MODE UINT8_C(0x4C)
#define BMM150_REG_INT_CONFIG UINT8_C(0x4D)
#define BMM150_REG_AXES_ENABLE UINT8_C(0x4E)
#define BMM150_REG_LOW_THRESHOLD UINT8_C(0x4F)
#define BMM150_REG_HIGH_THRESHOLD UINT8_C(0x50)
#define BMM150_REG_REP_XY UINT8_C(0x51)
#define BMM150_REG_REP_Z UINT8_C(0x52)
/*! @name Macros to select the sensor settings to be set by the user
* These values are internal for API implementation. Don't relate this to
* data sheet.
*/
#define BMM150_SEL_DATA_RATE UINT16_C(1)
#define BMM150_SEL_CONTROL_MEASURE UINT16_C(1 << 1)
#define BMM150_SEL_XY_REP UINT16_C(1 << 2)
#define BMM150_SEL_Z_REP UINT16_C(1 << 3)
#define BMM150_SEL_DRDY_PIN_EN UINT16_C(1 << 4)
#define BMM150_SEL_INT_PIN_EN UINT16_C(1 << 5)
#define BMM150_SEL_DRDY_POLARITY UINT16_C(1 << 6)
#define BMM150_SEL_INT_LATCH UINT16_C(1 << 7)
#define BMM150_SEL_INT_POLARITY UINT16_C(1 << 8)
#define BMM150_SEL_DATA_OVERRUN_INT UINT16_C(1 << 9)
#define BMM150_SEL_OVERFLOW_INT UINT16_C(1 << 10)
#define BMM150_SEL_HIGH_THRESHOLD_INT UINT16_C(1 << 11)
#define BMM150_SEL_LOW_THRESHOLD_INT UINT16_C(1 << 12)
#define BMM150_SEL_LOW_THRESHOLD_SETTING UINT16_C(1 << 13)
#define BMM150_SEL_HIGH_THRESHOLD_SETTING UINT16_C(1 << 14)
/*! @name DATA RATE DEFINITIONS */
#define BMM150_DATA_RATE_10HZ UINT8_C(0x00)
#define BMM150_DATA_RATE_02HZ UINT8_C(0x01)
#define BMM150_DATA_RATE_06HZ UINT8_C(0x02)
#define BMM150_DATA_RATE_08HZ UINT8_C(0x03)
#define BMM150_DATA_RATE_15HZ UINT8_C(0x04)
#define BMM150_DATA_RATE_20HZ UINT8_C(0x05)
#define BMM150_DATA_RATE_25HZ UINT8_C(0x06)
#define BMM150_DATA_RATE_30HZ UINT8_C(0x07)
#define BMM150_ODR_MAX UINT8_C(0x07)
#define BMM150_ODR_MSK UINT8_C(0x38)
#define BMM150_ODR_POS UINT8_C(0x03)
/*! @name TRIM REGISTERS */
/* Trim Extended Registers */
#define BMM150_DIG_X1 UINT8_C(0x5D)
#define BMM150_DIG_Y1 UINT8_C(0x5E)
#define BMM150_DIG_Z4_LSB UINT8_C(0x62)
#define BMM150_DIG_Z4_MSB UINT8_C(0x63)
#define BMM150_DIG_X2 UINT8_C(0x64)
#define BMM150_DIG_Y2 UINT8_C(0x65)
#define BMM150_DIG_Z2_LSB UINT8_C(0x68)
#define BMM150_DIG_Z2_MSB UINT8_C(0x69)
#define BMM150_DIG_Z1_LSB UINT8_C(0x6A)
#define BMM150_DIG_Z1_MSB UINT8_C(0x6B)
#define BMM150_DIG_XYZ1_LSB UINT8_C(0x6C)
#define BMM150_DIG_XYZ1_MSB UINT8_C(0x6D)
#define BMM150_DIG_Z3_LSB UINT8_C(0x6E)
#define BMM150_DIG_Z3_MSB UINT8_C(0x6F)
#define BMM150_DIG_XY2 UINT8_C(0x70)
#define BMM150_DIG_XY1 UINT8_C(0x71)
/*! @name Threshold interrupt setting macros for x,y,z axes selection */
#define BMM150_THRESHOLD_X UINT8_C(0x06)
#define BMM150_THRESHOLD_Y UINT8_C(0x05)
#define BMM150_THRESHOLD_Z UINT8_C(0x03)
#define BMM150_HIGH_THRESHOLD_INT_MSK UINT8_C(0x38)
#define BMM150_HIGH_THRESHOLD_INT_POS UINT8_C(0x03)
#define BMM150_LOW_THRESHOLD_INT_MSK UINT8_C(0x07)
/*! @name User configurable interrupt setting macros */
#define BMM150_INT_ENABLE UINT8_C(0x01)
#define BMM150_INT_DISABLE UINT8_C(0x00)
#define BMM150_ACTIVE_HIGH_POLARITY UINT8_C(0x01)
#define BMM150_ACTIVE_LOW_POLARITY UINT8_C(0x00)
#define BMM150_LATCHED UINT8_C(0x01)
#define BMM150_NON_LATCHED UINT8_C(0x00)
/*! @name Interrupt status */
#define BMM150_INT_THRESHOLD_X_LOW UINT16_C(0x0001)
#define BMM150_INT_THRESHOLD_Y_LOW UINT16_C(0x0002)
#define BMM150_INT_THRESHOLD_Z_LOW UINT16_C(0x0004)
#define BMM150_INT_THRESHOLD_X_HIGH UINT16_C(0x0008)
#define BMM150_INT_THRESHOLD_Y_HIGH UINT16_C(0x0010)
#define BMM150_INT_THRESHOLD_Z_HIGH UINT16_C(0x0020)
#define BMM150_INT_DATA_OVERFLOW UINT16_C(0x0040)
#define BMM150_INT_DATA_OVERRUN UINT16_C(0x0080)
#define BMM150_INT_DATA_READY UINT16_C(0x0100)
#define BMM150_DRDY_EN_MSK UINT8_C(0x80)
#define BMM150_DRDY_EN_POS UINT8_C(0x07)
#define BMM150_DRDY_POLARITY_MSK UINT8_C(0x04)
#define BMM150_DRDY_POLARITY_POS UINT8_C(0x02)
#define BMM150_INT_PIN_EN_MSK UINT8_C(0x40)
#define BMM150_INT_PIN_EN_POS UINT8_C(0x06)
#define BMM150_INT_LATCH_MSK UINT8_C(0x02)
#define BMM150_INT_LATCH_POS UINT8_C(0x01)
#define BMM150_INT_POLARITY_MSK UINT8_C(0x01)
#define BMM150_DRDY_STATUS_MSK UINT8_C(0x01)
/*! @name Interrupt status macros */
#define BMM150_INT_ASSERTED_DRDY UINT16_C(0x0100)
#define BMM150_INT_ASSERTED_LOW_THRES UINT16_C(0x0007)
#define BMM150_INT_ASSERTED_HIGH_THRES UINT16_C(0x0380)
/*! @name Power control bit macros */
#define BMM150_PWR_CNTRL_MSK UINT8_C(0x01)
#define BMM150_CONTROL_MEASURE_MSK UINT8_C(0x38)
#define BMM150_CONTROL_MEASURE_POS UINT8_C(0x03)
#define BMM150_POWER_CONTROL_BIT_MSK UINT8_C(0x01)
#define BMM150_POWER_CONTROL_BIT_POS UINT8_C(0x00)
/*! @name Data macros */
#define BMM150_DATA_X_MSK UINT8_C(0xF8)
#define BMM150_DATA_X_POS UINT8_C(0x03)
#define BMM150_DATA_Y_MSK UINT8_C(0xF8)
#define BMM150_DATA_Y_POS UINT8_C(0x03)
#define BMM150_DATA_Z_MSK UINT8_C(0xFE)
#define BMM150_DATA_Z_POS UINT8_C(0x01)
#define BMM150_DATA_RHALL_MSK UINT8_C(0xFC)
#define BMM150_DATA_RHALL_POS UINT8_C(0x02)
#define BMM150_DATA_OVERRUN_INT_MSK UINT8_C(0x80)
#define BMM150_DATA_OVERRUN_INT_POS UINT8_C(0x07)
#define BMM150_OVERFLOW_INT_MSK UINT8_C(0x40)
#define BMM150_OVERFLOW_INT_POS UINT8_C(0x06)
/*! @name OVERFLOW DEFINITIONS */
#define BMM150_OVERFLOW_ADCVAL_XYAXES_FLIP INT16_C(-4096)
#define BMM150_OVERFLOW_ADCVAL_ZAXIS_HALL INT16_C(-16384)
#define BMM150_OVERFLOW_OUTPUT INT16_C(-32768)
#define BMM150_NEGATIVE_SATURATION_Z INT16_C(-32767)
#define BMM150_POSITIVE_SATURATION_Z INT16_C(32767)
#ifdef BMM150_USE_FLOATING_POINT
#define BMM150_OVERFLOW_OUTPUT_FLOAT 0.0f
#endif
/*! @name PRESET MODE DEFINITIONS */
#define BMM150_PRESETMODE_LOWPOWER UINT8_C(0x01)
#define BMM150_PRESETMODE_REGULAR UINT8_C(0x02)
#define BMM150_PRESETMODE_HIGHACCURACY UINT8_C(0x03)
#define BMM150_PRESETMODE_ENHANCED UINT8_C(0x04)
#define BMM150_OP_MODE_MSK UINT8_C(0x06)
#define BMM150_OP_MODE_POS UINT8_C(0x01)
/*! @name PRESET MODES - REPETITIONS-XY RATES */
#define BMM150_REPXY_LOWPOWER UINT8_C(0x01)
#define BMM150_REPXY_REGULAR UINT8_C(0x04)
#define BMM150_REPXY_ENHANCED UINT8_C(0x07)
#define BMM150_REPXY_HIGHACCURACY UINT8_C(0x17)
/*! @name PRESET MODES - REPETITIONS-Z RATES */
#define BMM150_REPZ_LOWPOWER UINT8_C(0x01)
#define BMM150_REPZ_REGULAR UINT8_C(0x07)
#define BMM150_REPZ_ENHANCED UINT8_C(0x0D)
#define BMM150_REPZ_HIGHACCURACY UINT8_C(0x29)
/*! @name Self test settings */
#define BMM150_DISABLE_XY_AXIS UINT8_C(0x03)
#define BMM150_SELF_TEST_REP_Z UINT8_C(0x04)
/*! @name Self test selection macros */
#define BMM150_SELF_TEST_NORMAL UINT8_C(0)
#define BMM150_SELF_TEST_ADVANCED UINT8_C(1)
/*! @name Advanced self-test current settings */
#define BMM150_DISABLE_SELF_TEST_CURRENT UINT8_C(0x00)
#define BMM150_ENABLE_NEGATIVE_CURRENT UINT8_C(0x02)
#define BMM150_ENABLE_POSITIVE_CURRENT UINT8_C(0x03)
/*! @name Normal self-test status */
#define BMM150_SELF_TEST_STATUS_XYZ_FAIL UINT8_C(0x00)
#define BMM150_SELF_TEST_STATUS_SUCCESS UINT8_C(0x07)
#define BMM150_SELF_TEST_MSK UINT8_C(0x01)
#define BMM150_ADV_SELF_TEST_MSK UINT8_C(0xC0)
#define BMM150_ADV_SELF_TEST_POS UINT8_C(0x06)
/*! @name Register read lengths */
#define BMM150_LEN_SELF_TEST UINT8_C(5)
#define BMM150_LEN_SETTING_DATA UINT8_C(8)
#define BMM150_LEN_XYZR_DATA UINT8_C(8)
/*! @name Boundary check macros */
#define BMM150_BOUNDARY_MAXIMUM UINT8_C(0)
#define BMM150_BOUNDARY_MINIMUM UINT8_C(1)
/*! @name Macro to SET and GET BITS of a register*/
#define BMM150_SET_BITS(reg_data, bitname, data) \
((reg_data & ~(bitname##_MSK)) | \
((data << bitname##_POS) & bitname##_MSK))
#define BMM150_GET_BITS(reg_data, bitname) ((reg_data & (bitname##_MSK)) >> \
(bitname##_POS))
#define BMM150_SET_BITS_POS_0(reg_data, bitname, data) \
((reg_data & ~(bitname##_MSK)) | \
(data & bitname##_MSK))
#define BMM150_GET_BITS_POS_0(reg_data, bitname) (reg_data & (bitname##_MSK))
/********************************************************/
/*!
* @brief Interface selection Enums
*/
enum bmm150_intf {
/*! SPI interface */
BMM150_SPI_INTF,
/*! I2C interface */
BMM150_I2C_INTF
};
/******************************************************************************/
/*! @name Function Pointers */
/******************************************************************************/
#ifndef BMM150_INTF_RET_TYPE
#define BMM150_INTF_RET_TYPE int8_t
#endif
#ifndef BMM150_INTF_RET_SUCCESS
#define BMM150_INTF_RET_SUCCESS INT8_C(0)
#endif
/*!
* @brief Bus communication function pointer which should be mapped to
* the platform specific read functions of the user
*
* @param[in] reg_addr : 8bit register address of the sensor
* @param[out] reg_data : Data from the specified address
* @param[in] length : Length of the reg_data array
* @param[in,out] intf_ptr : Void pointer that can enable the linking of descriptors
* for interface related callbacks
* @retval 0 for Success
* @retval Non-zero for Failure
*/
typedef BMM150_INTF_RET_TYPE (*bmm150_read_fptr_t)(uint8_t reg_addr, uint8_t *reg_data, uint32_t length,
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 : 8bit register address of the sensor
* @param[out] reg_data : Data to the specified address
* @param[in] length : Length of the reg_data array
* @param[in,out] intf_ptr : Void pointer that can enable the linking of descriptors
* for interface related callbacks
* @retval 0 for Success
* @retval Non-zero for Failure
*
*/
typedef BMM150_INTF_RET_TYPE (*bmm150_write_fptr_t)(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length,
void *intf_ptr);
/*!
* @brief Delay function pointer which should be mapped to
* delay function of the user
*
* @param period : The time period in microseconds
* @param[in,out] intf_ptr : Void pointer that can enable the linking of descriptors
* for interface related callbacks
*/
typedef void (*bmm150_delay_us_fptr_t)(uint32_t period, void *intf_ptr);
/******************************************************************************/
/*! @name Structure Declarations */
/******************************************************************************/
/*!
* @brief bmm150 trim data structure
*/
struct bmm150_trim_registers {
/*! trim x1 data */
int8_t dig_x1;
/*! trim y1 data */
int8_t dig_y1;
/*! trim x2 data */
int8_t dig_x2;
/*! trim y2 data */
int8_t dig_y2;
/*! trim z1 data */
uint16_t dig_z1;
/*! trim z2 data */
int16_t dig_z2;
/*! trim z3 data */
int16_t dig_z3;
/*! trim z4 data */
int16_t dig_z4;
/*! trim xy1 data */
uint8_t dig_xy1;
/*! trim xy2 data */
int8_t dig_xy2;
/*! trim xyz1 data */
uint16_t dig_xyz1;
};
/*!
* @brief bmm150 interrupt pin settings
*/
struct bmm150_int_ctrl_settings {
/*! Data ready interrupt enable */
uint8_t drdy_pin_en;
/*! Threshold and overflow interrupts enable */
uint8_t int_pin_en;
/*! Data ready interrupt polarity Active high/low */
uint8_t drdy_polarity;
/*! Interrupt pin - Latched or Non-latched */
uint8_t int_latch;
/*! Interrupt polarity Active high/low */
uint8_t int_polarity;
/*! Data overrun interrupt enable */
uint8_t data_overrun_en;
/*! Overflow interrupt enable */
uint8_t overflow_int_en;
/*! high interrupt enable/disable axis selection */
uint8_t high_int_en;
/*! low interrupt enable/disable axis selection */
uint8_t low_int_en;
/*! low threshold limit */
uint8_t low_threshold;
/*! high threshold limit */
uint8_t high_threshold;
};
/*!
* @brief bmm150 sensor settings
*/
struct bmm150_settings {
/*! Control measurement of XYZ axes */
uint8_t xyz_axes_control;
/*! Power mode of sensor */
uint8_t pwr_mode;
/*! Data rate value (ODR) */
uint8_t data_rate;
/*! XY Repetitions */
uint8_t xy_rep;
/*! Z Repetitions */
uint8_t z_rep;
/*! Preset mode of sensor */
uint8_t preset_mode;
/*! Interrupt configuration settings */
struct bmm150_int_ctrl_settings int_settings;
};
/*!
* @brief bmm150 un-compensated (raw) magnetometer data
*/
struct bmm150_raw_mag_data {
/*! Raw mag X data */
int16_t raw_datax;
/*! Raw mag Y data */
int16_t raw_datay;
/*! Raw mag Z data */
int16_t raw_dataz;
/*! Raw mag resistance value */
uint16_t raw_data_r;
};
#ifdef BMM150_USE_FLOATING_POINT
/*!
* @brief bmm150 compensated magnetometer data in float
*/
struct bmm150_mag_data {
/*! compensated mag X data */
float x;
/*! compensated mag Y data */
float y;
/*! compensated mag Z data */
float z;
};
#else
/*!
* @brief bmm150 compensated magnetometer data in int16_t format
*/
struct bmm150_mag_data {
/*! compensated mag X data */
int16_t x;
/*! compensated mag Y data */
int16_t y;
/*! compensated mag Z data */
int16_t z;
};
#endif
/*!
* @brief bmm150 device structure
*/
struct bmm150_dev {
/*! Chip Id */
uint8_t chip_id;
/*! SPI/I2C Interface */
enum bmm150_intf intf;
/*!
* The interface pointer is used to enable the user
* to link their interface descriptors for reference during the
* implementation of the read and write interfaces to the
* hardware.
*/
void *intf_ptr;
/*! Variable that holds result of read/write function */
BMM150_INTF_RET_TYPE intf_rslt;
/*! Bus read function pointer */
bmm150_read_fptr_t read;
/*! Bus write function pointer */
bmm150_write_fptr_t write;
/*! delay(in us) function pointer */
bmm150_delay_us_fptr_t delay_us;
/*! Trim registers */
struct bmm150_trim_registers trim_data;
/*! Interrupt status */
uint16_t int_status;
/*! Power control bit value */
uint8_t pwr_cntrl_bit;
};
#endif /* BMM150_DEFS_H_ */

View File

@@ -0,0 +1,41 @@
/**
*
* @license MIT License
*
* Copyright (c) 2025 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file BoschParseBase.hpp
* @author Lewis He (lewishe@outlook.com)
* @date 2025-01-30
*
*/
#pragma once
#include "bhy2_defs.h"
class BoschParseBase
{
public:
virtual void parseData(const struct bhy2_fifo_parse_data_info *fifo, void *user_data) = 0;
virtual void parseMetaEvent(const struct bhy2_fifo_parse_data_info *callback_info, void *user_data) = 0;
virtual void parseDebugMessage(const struct bhy2_fifo_parse_data_info *callback_info, void *user_data) = 0;
virtual ~BoschParseBase() {}
};

View File

@@ -0,0 +1,169 @@
/**
*
* @license MIT License
*
* Copyright (c) 2025 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file BoschParseCallbackManager.hpp
* @author Lewis He (lewishe@outlook.com)
* @date 2025-01-31
*/
#pragma once
#include <stdint.h>
#include <cstdlib>
#include <assert.h>
#if __GNUC__ < 10
#define USE_CUSTOM_VECTOR
#else
#include <vector>
#endif
using SensorDataParseCallback = void (*)(uint8_t sensor_id, uint8_t *data, uint32_t size, uint64_t *timestamp, void *user_data);
class BoschParseCallbackManager
{
private:
struct Entry {
uint8_t id;
SensorDataParseCallback cb;
uint32_t length;
uint8_t *data;
void *user_data;
Entry() : id(0), cb(nullptr), length(0), data(nullptr), user_data(nullptr) {}
};
#ifdef USE_CUSTOM_VECTOR
Entry *entries;
uint32_t size;
uint32_t capacity;
bool expand()
{
capacity *= 2;
Entry *newEntries = static_cast<Entry *>(std::realloc(entries, capacity * sizeof(Entry)));
if (!newEntries) {
return false;
}
entries = newEntries;
return true;
}
#else
std::vector<Entry> entries;
#endif
public:
BoschParseCallbackManager()
{
#ifdef USE_CUSTOM_VECTOR
size = 0;
capacity = 10;
entries = static_cast<Entry *>(std::malloc(capacity * sizeof(Entry)));
if (!entries) {
assert(0);
}
#else
#endif
}
~BoschParseCallbackManager()
{
#ifdef USE_CUSTOM_VECTOR
std::free(entries);
#endif
}
bool add(uint8_t sensor_id, SensorDataParseCallback callback, void *user_data)
{
if (!callback) {
return false;
}
#ifdef USE_CUSTOM_VECTOR
if (size == capacity) {
if (!expand()) {
return false;
}
}
Entry newEntry;
newEntry.id = sensor_id;
newEntry.cb = callback;
newEntry.user_data = user_data;
entries[size++] = newEntry;
#else
Entry newEntry;
newEntry.id = sensor_id;
newEntry.cb = callback;
newEntry.user_data = user_data;
entries.push_back(newEntry);
#endif
return true;
}
bool remove(uint8_t sensor_id, SensorDataParseCallback callback)
{
if (!callback) {
return false;
}
#ifdef USE_CUSTOM_VECTOR
for (uint32_t i = 0; i < size; i++) {
if (entries[i].cb == callback && entries[i].id == sensor_id) {
for (uint32_t j = i; j < size - 1; j++) {
entries[j] = entries[j + 1];
}
size--;
break;
}
}
#else
for (auto it = entries.begin(); it != entries.end(); ++it) {
if (it->cb == callback && it->id == sensor_id) {
entries.erase(it);
break;
}
}
#endif
return true;
}
void call(uint8_t sensor_id, uint8_t *data, uint32_t size, uint64_t *timestamp)
{
#ifdef USE_CUSTOM_VECTOR
for (uint32_t i = 0; i < size; i++) {
if (entries[i].cb) {
if (entries[i].id == sensor_id) {
entries[i].cb(sensor_id, data, size, timestamp, entries[i].user_data);
}
}
}
#else
for (uint32_t i = 0; i < entries.size(); i++) {
if (entries[i].cb) {
if (entries[i].id == sensor_id) {
entries[i].cb(sensor_id, data, size, timestamp, entries[i].user_data);
}
}
}
#endif
}
};

View File

@@ -0,0 +1,54 @@
/**
*
* @license MIT License
*
* Copyright (c) 2025 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file BoschParseStatic.cpp
* @author Lewis He (lewishe@outlook.com)
* @date 2025-01-30
*
*/
#include "BoschParseStatic.hpp"
void BoschParseStatic::parseData(const struct bhy2_fifo_parse_data_info *fifo, void *user_data)
{
BoschParseBase *sensor = static_cast<BoschParseBase *>(user_data);
if (sensor) {
sensor->parseData(fifo, user_data);
}
}
void BoschParseStatic::parseMetaEvent(const struct bhy2_fifo_parse_data_info *callback_info, void *user_data)
{
BoschParseBase *sensor = static_cast<BoschParseBase *>(user_data);
if (sensor) {
sensor->parseMetaEvent(callback_info, user_data);
}
}
void BoschParseStatic::parseDebugMessage(const struct bhy2_fifo_parse_data_info *callback_info, void *user_data)
{
BoschParseBase *sensor = static_cast<BoschParseBase *>(user_data);
if (sensor) {
sensor->parseDebugMessage(callback_info, user_data);
}
}

View File

@@ -0,0 +1,42 @@
/**
*
* @license MIT License
*
* Copyright (c) 2025 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file BoschParseStatic.hpp
* @author Lewis He (lewishe@outlook.com)
* @date 2025-01-30
*
*/
#pragma once
#include "BoschParseBase.hpp"
class BoschParseStatic
{
public:
static void parseData(const struct bhy2_fifo_parse_data_info *fifo, void *user_data);
static void parseMetaEvent(const struct bhy2_fifo_parse_data_info *callback_info, void *user_data);
static void parseDebugMessage(const struct bhy2_fifo_parse_data_info *callback_info, void *user_data);
};

View File

@@ -0,0 +1,155 @@
/**
*
* @license MIT License
*
* Copyright (c) 2025 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file BHI260APSensorInfo.hpp
* @author Lewis He (lewishe@outlook.com)
* @date 2025-01-22
*
*/
#pragma once
#include <stdint.h>
#include <stdio.h>
#include "bhy2_parse.h"
#ifdef ARDUINO
#include <Stream.h>
#endif
class BoschPhySensorInfo
{
public:
uint8_t sensor_type;
uint8_t driver_id;
uint8_t driver_version;
float power_current;
uint16_t curr_range;
bool irq_status;
int master_intf;
int power_mode;
uint8_t slave_address;
uint8_t gpio_assignment;
float curr_rate;
uint8_t num_axis;
int8_t orientation_matrix[9];
uint8_t reserved;
uint8_t flags;
BoschPhySensorInfo() : sensor_type(0), driver_id(0), driver_version(0), power_current(0), curr_range(0), irq_status(false),
master_intf(0), power_mode(0), slave_address(0), gpio_assignment(0), curr_rate(0), num_axis(0), reserved(0), flags(0)
{
memset(orientation_matrix, 0, sizeof(orientation_matrix));
}
#if defined(ARDUINO) && !defined(ARDUINO_ARCH_MBED) && !defined(ARDUINO_ARCH_ZEPHYR)
void print(Stream &stream)
{
const char *irq_status_str[2] = { "Disabled", "Enabled" };
const char *master_intf_str[5] = { "None", "SPI0", "I2C0", "SPI1", "I2C1" };
const char *power_mode_str[8] = {
"Sensor Not Present", "Power Down", "Suspend", "Self-Test", "Interrupt Motion", "One Shot",
"Low Power Active", "Active"
};
stream.printf("Field Name hex | Value (dec)\n");
stream.printf("----------------------------------------------------------\n");
stream.printf("Physical Sensor ID %02X | %d\n", sensor_type, sensor_type);
stream.printf("Driver ID %02X | %d\n", driver_id, driver_id);
stream.printf("Driver Version %02X | %d\n", driver_version, driver_version);
stream.printf("Current Consumption %02X | %0.3f mA\n", (int)power_current, power_current);
stream.printf("Dynamic Range %04X | %d\n", curr_range, curr_range);
stream.printf("Flags %02X | IRQ status : %s\n", flags, irq_status_str[irq_status ? 1 : 0]);
stream.printf(" | Master interface : %s\n", master_intf_str[master_intf]);
stream.printf(" | Power mode : %s\n", power_mode_str[power_mode]);
stream.printf("Slave Address %02X | %d\n", slave_address, slave_address);
stream.printf("GPIO Assignment %02X | %d\n", gpio_assignment, gpio_assignment);
stream.printf("Current Rate %08X | %.3f Hz\n", (unsigned int)curr_rate, curr_rate);
stream.printf("Number of axes %02X | %d\n", num_axis, num_axis);
stream.printf("Orientation Matrix %02X%02X%02X%02X%02X | %+02d %+02d %+02d |\n",
orientation_matrix[0],
orientation_matrix[1],
orientation_matrix[2],
orientation_matrix[3],
orientation_matrix[4],
orientation_matrix[0],
orientation_matrix[1],
orientation_matrix[2]);
stream.printf(" | %+02d %+02d %+02d |\n",
orientation_matrix[3],
orientation_matrix[4],
orientation_matrix[5]);
stream.printf(" | %+02d %+02d %+02d |\n",
orientation_matrix[6],
orientation_matrix[7],
orientation_matrix[8]);
stream.printf("Reserved %02X | %d\n", reserved, reserved);
stream.printf("\n");
}
#else
void print()
{
const char *irq_status_str[2] = { "Disabled", "Enabled" };
const char *master_intf_str[5] = { "None", "SPI0", "I2C0", "SPI1", "I2C1" };
const char *power_mode_str[8] = {
"Sensor Not Present", "Power Down", "Suspend", "Self-Test", "Interrupt Motion", "One Shot",
"Low Power Active", "Active"
};
printf("Field Name hex | Value (dec)\n");
printf("----------------------------------------------------------\n");
printf("Physical Sensor ID %02X | %d\n", sensor_type, sensor_type);
printf("Driver ID %02X | %d\n", driver_id, driver_id);
printf("Driver Version %02X | %d\n", driver_version, driver_version);
printf("Current Consumption %02X | %0.3f mA\n", (int)power_current, power_current);
printf("Dynamic Range %04X | %d\n", curr_range, curr_range);
printf("Flags %02X | IRQ status : %s\n", flags, irq_status_str[irq_status ? 1 : 0]);
printf(" | Master interface : %s\n", master_intf_str[master_intf]);
printf(" | Power mode : %s\n", power_mode_str[power_mode]);
printf("Slave Address %02X | %d\n", slave_address, slave_address);
printf("GPIO Assignment %02X | %d\n", gpio_assignment, gpio_assignment);
printf("Current Rate %08X | %.3f Hz\n", (unsigned int)curr_rate, curr_rate);
printf("Number of axes %02X | %d\n", num_axis, num_axis);
printf("Orientation Matrix %02X%02X%02X%02X%02X | %+02d %+02d %+02d |\n",
orientation_matrix[0],
orientation_matrix[1],
orientation_matrix[2],
orientation_matrix[3],
orientation_matrix[4],
orientation_matrix[0],
orientation_matrix[1],
orientation_matrix[2]);
printf(" | %+02d %+02d %+02d |\n",
orientation_matrix[3],
orientation_matrix[4],
orientation_matrix[5]);
printf(" | %+02d %+02d %+02d |\n",
orientation_matrix[6],
orientation_matrix[7],
orientation_matrix[8]);
printf("Reserved %02X | %d\n", reserved, reserved);
printf("\n");
}
#endif
};

View File

@@ -0,0 +1,82 @@
/**
*
* @license MIT License
*
* Copyright (c) 2025 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file BoschSensorControl.hpp
* @author Lewis He (lewishe@outlook.com)
* @date 2025-01-22
*
*/
#pragma once
#include <stdint.h>
#include <stdio.h>
#ifdef ARDUINO
#include <Stream.h>
#endif
class SensorBHI260APControl
{
public:
bool wakeUpFIFOEnabled;
bool nonWakeUpFIFOEnabled;
bool statusFIFOEnabled;
bool debuggingEnabled;
bool faultEnabled;
bool interruptIsActiveLow;
bool interruptIsPulseTriggered;
bool interruptPinDriveIsOpenDrain;
SensorBHI260APControl() : wakeUpFIFOEnabled(true), nonWakeUpFIFOEnabled(true), statusFIFOEnabled(true),
debuggingEnabled(true), faultEnabled(true), interruptIsActiveLow(false),
interruptIsPulseTriggered(false), interruptPinDriveIsOpenDrain(false) {}
#if defined(ARDUINO) && !defined(ARDUINO_ARCH_MBED) && !defined(ARDUINO_ARCH_ZEPHYR)
void print(Stream &stream)
{
stream.printf("Host interrupt control\n");
stream.printf("-- Wake up FIFO :%s\n", (wakeUpFIFOEnabled ? "enabled" : "disabled"));
stream.printf("-- Non wake up FIFO :%s\n", (nonWakeUpFIFOEnabled ? "enabled" : "disabled"));
stream.printf("-- Status FIFO :%s\n", (statusFIFOEnabled ? "enabled" : "disabled"));
stream.printf("-- Debugging :%s\n", (debuggingEnabled ? "enabled" : "disabled"));
stream.printf("-- Fault :%s\n", (faultEnabled ? "enabled" : "disabled"));
stream.printf("-- Interrupt is :%s\n", (interruptIsActiveLow ? "active low" : "active high"));
stream.printf("-- Interrupt is :%s triggered.\n", (interruptIsPulseTriggered ? "pulse" : "level"));
stream.printf("-- Interrupt pin drive is :%s\n", (interruptPinDriveIsOpenDrain ? "open drain" : "push-pull"));
}
#else
void print()
{
printf("Host interrupt control\n");
printf("-- Wake up FIFO :%s\n", (wakeUpFIFOEnabled ? "enabled" : "disabled"));
printf("-- Non wake up FIFO :%s\n", (nonWakeUpFIFOEnabled ? "enabled" : "disabled"));
printf("-- Status FIFO :%s\n", (statusFIFOEnabled ? "enabled" : "disabled"));
printf("-- Debugging :%s\n", (debuggingEnabled ? "enabled" : "disabled"));
printf("-- Fault :%s\n", (faultEnabled ? "enabled" : "disabled"));
printf("-- Interrupt is :%s\n", (interruptIsActiveLow ? "active low" : "active high"));
printf("-- Interrupt is :%s triggered.\n", (interruptIsPulseTriggered ? "pulse" : "level"));
printf("-- Interrupt pin drive is :%s\n", (interruptPinDriveIsOpenDrain ? "open drain" : "push-pull"));
}
#endif
};

View File

@@ -0,0 +1,575 @@
/**
*
* @license MIT License
*
* Copyright (c) 2025 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file BoschSensorDataHelper.hpp
* @author Lewis He (lewishe@outlook.com)
* @date 2025-02-04
*
*/
#pragma once
#include "../SensorBHI260AP.hpp"
#include "bhy2_defs.h"
#include <math.h>
class BoschSensorDataHelperBase
{
public:
typedef union {
float temperature;
float humidity;
float pressure;
float altitude;
bhy2_data_quaternion quaternion;
bhy2_data_orientation orientation;
bhy2_data_xyz vector;
uint32_t step_counter;
uint32_t gas;
uint16_t activity_bitmap;
uint8_t dev_ori;
bool detected;
} SensorData;
BoschSensorDataHelperBase(SensorBHI260AP::BoschSensorID sensor_id, SensorBHI260AP &handle)
: _sensor_id(sensor_id), _handle(handle)
{
_scaling_factor = _handle.getScaling(_sensor_id);
}
virtual ~BoschSensorDataHelperBase() = default;
uint8_t id() const
{
return _sensor_id;
}
bool configure(float sample_rate, uint32_t report_latency_ms)
{
return _handle.configure(_sensor_id, sample_rate, report_latency_ms);
}
bool setRange(uint16_t range)
{
return _handle.configureRange(_sensor_id, range);
}
const SensorConfig getConfiguration()
{
return _handle.getConfigure(_sensor_id);
}
float getScaling()
{
return _scaling_factor;
}
protected:
SensorData parse_data(uint8_t sensor_id, const uint8_t *data)
{
SensorData result;
switch (sensor_id) {
case BHY2_SENSOR_ID_TEMP:
case BHY2_SENSOR_ID_TEMP_WU:
bhy2_parse_temperature_celsius(data, &result.temperature);
break;
case BHY2_SENSOR_ID_HUM:
case BHY2_SENSOR_ID_HUM_WU:
bhy2_parse_humidity(data, &result.humidity);
break;
case BHY2_SENSOR_ID_BARO:
case BHY2_SENSOR_ID_BARO_WU:
bhy2_parse_pressure(data, &result.pressure);
break;
case BHY2_SENSOR_ID_GAS:
case BHY2_SENSOR_ID_GAS_WU:
result.gas = BHY2_LE2U32(data);
break;
case BHY2_SENSOR_ID_RV:
case BHY2_SENSOR_ID_RV_WU:
case BHY2_SENSOR_ID_GAMERV:
case BHY2_SENSOR_ID_GAMERV_WU:
case BHY2_SENSOR_ID_GEORV:
case BHY2_SENSOR_ID_GEORV_WU:
bhy2_parse_quaternion(data, &result.quaternion);
break;
case BHY2_SENSOR_ID_ORI:
case BHY2_SENSOR_ID_ORI_WU:
bhy2_parse_orientation(data, &result.orientation);
break;
case BHY2_SENSOR_ID_DEVICE_ORI:
case BHY2_SENSOR_ID_DEVICE_ORI_WU:
result.dev_ori = data[0];
break;
case BHY2_SENSOR_ID_ACC_PASS:
case BHY2_SENSOR_ID_ACC_RAW:
case BHY2_SENSOR_ID_ACC:
case BHY2_SENSOR_ID_ACC_BIAS:
case BHY2_SENSOR_ID_ACC_WU:
case BHY2_SENSOR_ID_ACC_RAW_WU:
case BHY2_SENSOR_ID_GRA:
case BHY2_SENSOR_ID_GRA_WU:
case BHY2_SENSOR_ID_LACC:
case BHY2_SENSOR_ID_LACC_WU:
case BHY2_SENSOR_ID_ACC_BIAS_WU:
case BHY2_SENSOR_ID_GYRO_PASS:
case BHY2_SENSOR_ID_GYRO_RAW:
case BHY2_SENSOR_ID_GYRO:
case BHY2_SENSOR_ID_GYRO_BIAS:
case BHY2_SENSOR_ID_GYRO_WU:
case BHY2_SENSOR_ID_GYRO_RAW_WU:
case BHY2_SENSOR_ID_GYRO_BIAS_WU:
case BHY2_SENSOR_ID_MAG_PASS:
case BHY2_SENSOR_ID_MAG_RAW:
case BHY2_SENSOR_ID_MAG:
case BHY2_SENSOR_ID_MAG_BIAS:
case BHY2_SENSOR_ID_MAG_WU:
case BHY2_SENSOR_ID_MAG_RAW_WU:
case BHY2_SENSOR_ID_MAG_BIAS_WU:
bhy2_parse_xyz(data, &result.vector);
break;
case BHY2_SENSOR_ID_STC:
case BHY2_SENSOR_ID_STC_WU:
result.step_counter = bhy2_parse_step_counter(data);
break;
case BHY2_SENSOR_ID_STD:
result.detected = true;
break;
case BHY2_SENSOR_ID_AR:
result.activity_bitmap = (data[1] << 8) | data[0];
break;
default:
log_e("Sensor ID Undefined");
break;
}
return result;
}
SensorBHI260AP::BoschSensorID _sensor_id;
float _scaling_factor;
SensorBHI260AP &_handle;
};
template <typename DataType>
class SensorTemplateBase : public BoschSensorDataHelperBase
{
public:
SensorTemplateBase(SensorBHI260AP::BoschSensorID sensor_id, SensorBHI260AP &handle)
: BoschSensorDataHelperBase(sensor_id, handle)
{
}
~SensorTemplateBase() override
{
}
const DataType &getValue() const
{
return _value;
}
bool enable(float sample_rate, uint32_t report_latency_ms)
{
_handle.onResultEvent(_sensor_id, staticCallback, this);
return configure(sample_rate, report_latency_ms);
}
void disable()
{
_handle.removeResultEvent(_sensor_id, staticCallback);
_handle.configure(_sensor_id, 0, 0);
}
bool hasUpdated()
{
bool result = _lastUpdateTime != _currentTime;
_lastUpdateTime = _currentTime;
return result;
}
uint64_t getTimestamp()
{
return _currentTime;
}
uint32_t getLastUpdateSecond()
{
uint64_t tns = getNanosecondsFromCurrentTime();
return static_cast<uint32_t>(tns / UINT64_C(1000000000));
}
uint64_t getLastUpdateNanoseconds()
{
uint64_t tns = getNanosecondsFromCurrentTime();
uint32_t s = static_cast<uint32_t>(tns / UINT64_C(1000000000));
return tns - (static_cast<uint64_t>(s) * UINT64_C(1000000000));
}
void getLastTime(uint32_t &s, uint32_t &ns)
{
uint64_t tns = getNanosecondsFromCurrentTime(); /* timestamp is now in nanoseconds */
s = (uint32_t)(tns / UINT64_C(1000000000));
ns = (uint32_t)(tns - ((s) * UINT64_C(1000000000)));
}
protected:
virtual void updateValue(const SensorData &data) = 0;
DataType _value;
uint64_t _lastUpdateTime;
uint64_t _currentTime;
private:
uint64_t getNanosecondsFromCurrentTime() const
{
return _currentTime * 15625;
}
static void staticCallback(uint8_t sensor_id, uint8_t *data, uint32_t size, uint64_t *timestamp, void *user_data)
{
auto self = static_cast<SensorTemplateBase<DataType>*>(user_data);
SensorData parsedData = self->parse_data(sensor_id, data);
self->updateValue(parsedData);
self->_lastUpdateTime = self->_currentTime;
self->_currentTime = *timestamp;
}
};
class SensorTemperature : public SensorTemplateBase<float>
{
public:
SensorTemperature(SensorBHI260AP &handle)
: SensorTemplateBase<float>(SensorBHI260AP::TEMPERATURE, handle) {}
float getCelsius() const
{
return getValue();
}
float getFahrenheit()
{
return getCelsius() * (9.0 / 5.0) + 32;
}
float getKelvin()
{
return getCelsius() + 273.15;
}
bool enable()
{
return SensorTemplateBase::enable(1, 0);
}
protected:
void updateValue(const SensorData &data) override
{
_value = data.temperature;
}
};
class SensorHumidity : public SensorTemplateBase<float>
{
public:
SensorHumidity(SensorBHI260AP &handle)
: SensorTemplateBase<float>(SensorBHI260AP::HUMIDITY, handle) {}
float getHumidity() const
{
return getValue();
}
bool enable()
{
return SensorTemplateBase::enable(1, 0);
}
protected:
void updateValue(const SensorData &data) override
{
_value = data.humidity;
}
};
class SensorPressure : public SensorTemplateBase<float>
{
public:
SensorPressure(SensorBHI260AP &handle)
: SensorTemplateBase<float>(SensorBHI260AP::BAROMETER, handle) {}
float getPressure() const
{
return getValue();
}
protected:
void updateValue(const SensorData &data) override
{
_value = data.pressure;
}
};
class SensorGas : public SensorTemplateBase<uint32_t>
{
public:
SensorGas(SensorBHI260AP &handle)
: SensorTemplateBase<uint32_t>(SensorBHI260AP::GAS, handle) {}
uint32_t getGas() const
{
return getValue() * _scaling_factor;
}
protected:
void updateValue(const SensorData &data) override
{
_value = data.gas;
}
};
class SensorOrientation : public SensorTemplateBase<uint8_t>
{
public:
SensorOrientation(SensorBHI260AP &handle)
: SensorTemplateBase<uint8_t>(SensorBHI260AP::DEVICE_ORIENTATION, handle) {}
uint32_t getOrientation() const
{
return getValue();
}
protected:
void updateValue(const SensorData &data) override
{
_value = data.dev_ori;
}
};
class SensorEuler : public SensorTemplateBase<bhy2_data_orientation>
{
public:
SensorEuler(SensorBHI260AP &handle)
: SensorTemplateBase<bhy2_data_orientation>(SensorBHI260AP::ORIENTATION, handle) {}
float getHeading() const
{
return getValue().heading * _scaling_factor;
}
float getPitch() const
{
return getValue().pitch * _scaling_factor;
}
float getRoll() const
{
return getValue().roll * _scaling_factor;
}
protected:
void updateValue(const SensorData &data) override
{
_value = data.orientation;
}
};
class SensorQuaternion : public SensorTemplateBase<bhy2_data_quaternion>
{
public:
SensorQuaternion(SensorBHI260AP &handle)
: SensorTemplateBase<bhy2_data_quaternion>(SensorBHI260AP::GAME_ROTATION_VECTOR, handle) {}
float getX() const
{
return getValue().x * _scaling_factor;
}
float getY() const
{
return getValue().y * _scaling_factor;
}
float getZ() const
{
return getValue().z * _scaling_factor;
}
float getW() const
{
return getValue().w * _scaling_factor;
}
uint16_t getAccuracy() const
{
return getValue().accuracy;
}
float getHeading() const
{
return heading;
}
float getPitch() const
{
return pitch;
}
float getRoll() const
{
return roll;
}
void toEuler()
{
float w, x, y, z;
w = _value.w / 16384.0f;
x = _value.x / 16384.0f;
y = _value.y / 16384.0f;
z = _value.z / 16384.0f;
roll = atan2(2 * (w * x + y * z), 1 - 2 * (x * x + y * y));
pitch = asin(2 * (w * y - z * x));
heading = atan2(2 * (w * z + x * y), 1 - 2 * (y * y + z * z));
// Convert radians to degrees
roll = roll * (180.0 / M_PI);
pitch = pitch * (180.0 / M_PI);
heading = heading * (180.0 / M_PI);
}
protected:
float heading;
float pitch;
float roll;
void updateValue(const SensorData &data) override
{
_value = data.quaternion;
}
};
class SensorStepCounter : public SensorTemplateBase<uint32_t>
{
public:
SensorStepCounter(SensorBHI260AP &handle)
: SensorTemplateBase<uint32_t>(SensorBHI260AP::STEP_COUNTER, handle) {}
uint32_t getStepCount() const
{
return getValue();
}
protected:
void updateValue(const SensorData &data) override
{
_value = data.step_counter;
}
};
class SensorStepDetector : public SensorTemplateBase<bool>
{
public:
SensorStepDetector(SensorBHI260AP &handle)
: SensorTemplateBase<bool>(SensorBHI260AP::STEP_DETECTOR, handle) {}
bool isDetected()
{
bool tmp = getValue();
_value = false;
return tmp;
}
protected:
void updateValue(const SensorData &data) override
{
_value = data.detected;
}
};
class SensorXYZ : public SensorTemplateBase<bhy2_data_xyz>
{
public:
SensorXYZ(SensorBHI260AP::BoschSensorID sensor_id, SensorBHI260AP &handle)
: SensorTemplateBase<bhy2_data_xyz>(sensor_id, handle) {}
float getX() const
{
return getValue().x * _scaling_factor;
}
float getY() const
{
return getValue().y * _scaling_factor;
}
float getZ() const
{
return getValue().z * _scaling_factor;
}
protected:
void updateValue(const SensorData &data) override
{
_value = data.vector;
}
};
class SensorActivity : public SensorTemplateBase<uint16_t>
{
public:
// See [bst-bhi260ab-ds000.pdf](https://www.mouser.com/datasheet/2/783/bst-bhi260ab-ds000-1816249.pdf)
// 15.1.4 Format "Activity"
enum ActivityStatus {
STILL_ACTIVITY_ENDED,
WALKING_ACTIVITY_ENDED,
RUNNING_ACTIVITY_ENDED,
ON_BICYCLE_ACTIVITY_ENDED,
IN_VEHICLE_ACTIVITY_ENDED,
TILTING_ACTIVITY_ENDED,
IN_VEHICLE_STILL_ENDED,
RESERVED_LOW,
STILL_ACTIVITY_STARTED,
WALKING_ACTIVITY_STARTED,
RUNNING_ACTIVITY_STARTED,
ON_BICYCLE_ACTIVITY_STARTED,
IN_VEHICLE_ACTIVITY_STARTED,
TILTING_ACTIVITY_STARTED,
IN_VEHICLE_STILL_STARTED,
RESERVED_HIGH
};
SensorActivity(SensorBHI260AP &handle)
: SensorTemplateBase<uint16_t>(SensorBHI260AP::ACTIVITY_RECOGNITION, handle) {}
/**
* @brief Check if a specific activity status is set in the activity bitmap.
*
* This function checks if the bit corresponding to the given activity status is set.
*
* @param status The activity status to check. It is an enumeration value of ActivityStatus.
* @return bool Returns true if the bit corresponding to the given activity status is set in the bitmap,
* false otherwise.
*/
bool isActivitySet(ActivityStatus status)
{
bool bitStatus = (_value & (1 << static_cast<uint16_t>(status))) != 0;
_value &= ~(1 << static_cast<uint16_t>(status));
return bitStatus;
}
/**
* @brief Manually clear all motion status
* @retval None
*/
void clear()
{
_value = 0;
}
protected:
void updateValue(const SensorData &data) override
{
_value = data.activity_bitmap;
}
};

View File

@@ -0,0 +1,114 @@
/**
*
* @license MIT License
*
* Copyright (c) 2025 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file BoschSensorID.hpp
* @author Lewis He (lewishe@outlook.com)
* @date 2025-01-30
* @note Raw API sensor IDs in bhy2_defs.h
*/
#pragma once
class BoschVirtualSensor
{
public:
enum BoschSensorID {
ACCEL_PASSTHROUGH = (1), /*BHY2_SENSOR_ID_ACC_PASS: Accelerometer passthrough */
ACCEL_UNCALIBRATED = (3), /*BHY2_SENSOR_ID_ACC_RAW: Accelerometer uncalibrated */
ACCEL_CORRECTED = (4), /*BHY2_SENSOR_ID_ACC: Accelerometer corrected */
ACCEL_OFFSET = (5), /*BHY2_SENSOR_ID_ACC_BIAS: Accelerometer offset */
ACCEL_CORRECTED_WAKE_UP = (6), /*BHY2_SENSOR_ID_ACC_WU: Accelerometer corrected wake up */
ACCEL_UNCALIBRATED_WAKE_UP = (7), /*BHY2_SENSOR_ID_ACC_RAW_WU: Accelerometer uncalibrated wake up */
// VIRTUAL_SENSOR_ID_FOR_ACCEL = (8), /*BHY2_SENSOR_ID_SI_ACCEL: Virtual Sensor ID for Accelerometer */
GYRO_PASSTHROUGH = (10), /*BHY2_SENSOR_ID_GYRO_PASS: Gyroscope passthrough */
GYRO_UNCALIBRATED = (12), /*BHY2_SENSOR_ID_GYRO_RAW: Gyroscope uncalibrated */
GYRO_CORRECTED = (13), /*BHY2_SENSOR_ID_GYRO: Gyroscope corrected */
GYRO_OFFSET = (14), /*BHY2_SENSOR_ID_GYRO_BIAS: Gyroscope offset */
GYRO_WAKE_UP = (15), /*BHY2_SENSOR_ID_GYRO_WU: Gyroscope wake up */
GYRO_UNCALIBRATED_WAKE_UP = (16), /*BHY2_SENSOR_ID_GYRO_RAW_WU: Gyroscope uncalibrated wake up */
// VIRTUAL_SENSOR_ID_FOR_GYRO = (17), /*BHY2_SENSOR_ID_SI_GYROS: Virtual Sensor ID for Gyroscope */
MAGNETOMETER_PASSTHROUGH = (19), /*BHY2_SENSOR_ID_MAG_PASS: Magnetometer passthrough */
MAGNETOMETER_UNCALIBRATED = (21), /*BHY2_SENSOR_ID_MAG_RAW: Magnetometer uncalibrated */
MAGNETOMETER_CORRECTED = (22), /*BHY2_SENSOR_ID_MAG: Magnetometer corrected */
MAGNETOMETER_OFFSET = (23), /*BHY2_SENSOR_ID_MAG_BIAS: Magnetometer offset */
MAGNETOMETER_WAKE_UP = (24), /*BHY2_SENSOR_ID_MAG_WU: Magnetometer wake up */
MAGNETOMETER_UNCALIBRATED_WAKE_UP = (25), /*BHY2_SENSOR_ID_MAG_RAW_WU: Magnetometer uncalibrated wake up */
GRAVITY_VECTOR = (28), /*BHY2_SENSOR_ID_GRA: Gravity vector */
GRAVITY_VECTOR_WAKE_UP = (29), /*BHY2_SENSOR_ID_GRA_WU: Gravity vector wake up */
LINEAR_ACCELERATION = (31), /*BHY2_SENSOR_ID_LACC: Linear acceleration */
LINEAR_ACCELERATION_WAKE_UP = (32), /*BHY2_SENSOR_ID_LACC_WU: Linear acceleration wake up */
ROTATION_VECTOR = (34), /*BHY2_SENSOR_ID_RV: Rotation vector , quaternion*/
ROTATION_VECTOR_WAKE_UP = (35), /*BHY2_SENSOR_ID_RV_WU: Rotation vector wake up */
GAME_ROTATION_VECTOR = (37), /*BHY2_SENSOR_ID_GAMERV: Game rotation vector */
GAME_ROTATION_VECTOR_WAKE_UP = (38), /*BHY2_SENSOR_ID_GAMERV_WU: Game rotation vector wake up */
GEO_MAGNETIC_ROTATION_VECTOR = (40), /*BHY2_SENSOR_ID_GEORV: Geo-magnetic rotation vector */
GEO_MAGNETIC_ROTATION_VECTOR_WAKE_UP = (41), /*BHY2_SENSOR_ID_GEORV_WU: Geo-magnetic rotation vector wake up */
ORIENTATION = (43), /*BHY2_SENSOR_ID_ORI: Orientation */
ORIENTATION_WAKE_UP = (44), /*BHY2_SENSOR_ID_ORI_WU: Orientation wake up , Euler*/
TILT_DETECTOR = (48), /*BHY2_SENSOR_ID_TILT_DETECTOR: Tilt detector */
STEP_DETECTOR = (50), /*BHY2_SENSOR_ID_STD: Step detector */
STEP_COUNTER = (52), /*BHY2_SENSOR_ID_STC: Step counter */
STEP_COUNTER_WAKE_UP = (53), /*BHY2_SENSOR_ID_STC_WU: Step counter wake up */
SIGNIFICANT_MOTION = (55), /*BHY2_SENSOR_ID_SIG: Significant motion */
WAKE_GESTURE = (57), /*BHY2_SENSOR_ID_WAKE_GESTURE: Wake gesture */
GLANCE_GESTURE = (59), /*BHY2_SENSOR_ID_GLANCE_GESTURE: Glance gesture */
PICKUP_GESTURE = (61), /*BHY2_SENSOR_ID_PICKUP_GESTURE: Pickup gesture */
ACTIVITY_RECOGNITION = (63), /*BHY2_SENSOR_ID_AR: Activity recognition */
WRIST_TILT_GESTURE = (67), /*BHY2_SENSOR_ID_WRIST_TILT_GESTURE: Wrist tilt gesture */
DEVICE_ORIENTATION = (69), /*BHY2_SENSOR_ID_DEVICE_ORI: Device orientation */
DEVICE_ORIENTATION_WAKE_UP = (70), /*BHY2_SENSOR_ID_DEVICE_ORI_WU: Device orientation wake up */
STATIONARY_DETECT = (75), /*BHY2_SENSOR_ID_STATIONARY_DET: Stationary detect */
MOTION_DETECT = (77), /*BHY2_SENSOR_ID_MOTION_DET: Motion detect */
ACCEL_OFFSET_WAKE_UP = (91), /*BHY2_SENSOR_ID_ACC_BIAS_WU: Accelerometer offset wake up */
GYRO_OFFSET_WAKE_UP = (92), /*BHY2_SENSOR_ID_GYRO_BIAS_WU: Gyroscope offset wake up */
MAGNETOMETER_OFFSET_WAKE_UP = (93), /*BHY2_SENSOR_ID_MAG_BIAS_WU: Magnetometer offset wake up */
STEP_DETECTOR_WAKE_UP = (94), /*BHY2_SENSOR_ID_STD_WU: Step detector wake up */
KLIO = (112), /*BHY2_SENSOR_ID_KLIO Supported by klio firmware ,defined in bhy2_klio_defs.h */
SWIM = (114), /*BHY2_SENSOR_ID_SWIM:Supported by swim firmware ,defined in bhy2_swim_defs.h */
KLIO_LOG = (127), /*BHY2_SENSOR_ID_KLIO_LOG Supported by klio firmware ,defined in bhy2_klio_defs.h */
TEMPERATURE = (128), /*BHY2_SENSOR_ID_TEMP: Temperature */
BAROMETER = (129), /*BHY2_SENSOR_ID_BARO: Barometer */
HUMIDITY = (130), /*BHY2_SENSOR_ID_HUM: Humidity */
GAS = (131), /*BHY2_SENSOR_ID_GAS: Gas */
TEMPERATURE_WAKE_UP = (132), /*BHY2_SENSOR_ID_TEMP_WU: Temperature wake up */
BAROMETER_WAKE_UP = (133), /*BHY2_SENSOR_ID_BARO_WU: Barometer wake up */
HUMIDITY_WAKE_UP = (134), /*BHY2_SENSOR_ID_HUM_WU: Humidity wake up */
GAS_WAKE_UP = (135), /*BHY2_SENSOR_ID_GAS_WU: Gas wake up */
STEP_COUNTER_LOW_POWER = (136), /*BHY2_SENSOR_ID_STC_LP: Step counter Low Power */
STEP_DETECTOR_LOW_POWER = (137), /*BHY2_SENSOR_ID_STD_LP: Step detector Low Power */
SIGNIFICANT_MOTION_LOW_POWER = (138), /*BHY2_SENSOR_ID_SIG_LP: Significant motion Low Power */
STEP_COUNTER_LOW_POWER_WAKE_UP = (139), /*BHY2_SENSOR_ID_STC_LP_WU: Step counter Low Power wake up */
STEP_DETECTOR_LOW_POWER_WAKE_UP = (140), /*BHY2_SENSOR_ID_STD_LP_WU: Step detector Low Power wake up */
SIGNIFICANT_MOTION_LOW_POWER_WAKE_UP = (141), /*BHY2_SENSOR_ID_SIG_LP_WU: Significant motion Low Power wake up */
ANY_MOTION_LOW_POWER = (142), /*BHY2_SENSOR_ID_ANY_MOTION_LP: Any motion Low Power */
ANY_MOTION_LOW_POWER_WAKE_UP = (143), /*BHY2_SENSOR_ID_ANY_MOTION_LP_WU: Any motion Low Power wake up */
EXTERNAL_CAMERA_TRIGGER = (144), /*BHY2_SENSOR_ID_EXCAMERA: External camera trigger */
GPS = (145), /*BHY2_SENSOR_ID_GPS: GPS */
LIGHT = (146), /*BHY2_SENSOR_ID_LIGHT: Light */
PROXIMITY = (147), /*BHY2_SENSOR_ID_PROX: Proximity */
LIGHT_WAKE_UP = (148), /*BHY2_SENSOR_ID_LIGHT_WU: Light wake up */
PROXIMITY_WAKE_UP = (149), /*BHY2_SENSOR_ID_PROX_WU: Proximity wake up */
GPIO_EXP = (151), /*BHY2_SENSOR_ID_GPIO_EXP: GPIO_EXP*/
};
};

View File

@@ -0,0 +1,297 @@
/**
*
* @license MIT License
*
* Copyright (c) 2025 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file BoschSensorInfo.hpp
* @author Lewis He (lewishe@outlook.com)
* @date 2025-01-22
*
*/
#pragma once
#include <stdint.h>
#include <stdio.h>
#include "bhy2_parse.h"
#include "bhy2_defs.h"
#include "common/common.h"
#ifdef ARDUINO
#include <Stream.h>
#endif
class BoschSensorInfo
{
public:
uint16_t kernel_version;
uint16_t user_version;
uint16_t rom_version;
uint8_t product_id;
uint8_t host_status;
uint8_t feat_status;
uint8_t boot_status;
uint8_t sensor_error;
bhy2_dev *dev;
struct bhy2_sensor_info *info;
BoschSensorInfo() : kernel_version(0), user_version(0), rom_version(0),
product_id(0), host_status(0), feat_status(0), boot_status(0), sensor_error(0), dev(nullptr), info(nullptr)
{
info = (struct bhy2_sensor_info *)calloc(BHY2_SENSOR_ID_MAX, sizeof(struct bhy2_sensor_info));
}
~BoschSensorInfo()
{
if (info) {
free(info);
}
}
BoschSensorInfo(const BoschSensorInfo &other)
: kernel_version(other.kernel_version),
user_version(other.user_version),
rom_version(other.rom_version),
product_id(other.product_id),
host_status(other.host_status),
feat_status(other.feat_status),
boot_status(other.boot_status),
sensor_error(other.sensor_error),
dev(other.dev),
info(nullptr)
{
if (other.info) {
info = (struct bhy2_sensor_info *)calloc(BHY2_SENSOR_ID_MAX, sizeof(struct bhy2_sensor_info));
for (int i = 0; i < BHY2_SENSOR_ID_MAX; ++i) {
info[i] = other.info[i];
}
}
}
BoschSensorInfo &operator=(const BoschSensorInfo &other)
{
if (this != &other) {
if (info) {
free(info);
}
kernel_version = other.kernel_version;
user_version = other.user_version;
rom_version = other.rom_version;
product_id = other.product_id;
host_status = other.host_status;
feat_status = other.feat_status;
boot_status = other.boot_status;
sensor_error = other.sensor_error;
dev = other.dev;
info = nullptr;
if (other.info) {
info = (struct bhy2_sensor_info *)calloc(BHY2_SENSOR_ID_MAX, sizeof(struct bhy2_sensor_info));
for (int i = 0; i < BHY2_SENSOR_ID_MAX; ++i) {
info[i] = other.info[i];
}
}
}
return *this;
}
BoschSensorInfo(BoschSensorInfo &&other) noexcept
: kernel_version(other.kernel_version),
user_version(other.user_version),
rom_version(other.rom_version),
product_id(other.product_id),
host_status(other.host_status),
feat_status(other.feat_status),
boot_status(other.boot_status),
sensor_error(other.sensor_error),
dev(other.dev),
info(other.info)
{
other.info = nullptr;
other.dev = nullptr;
}
BoschSensorInfo &operator=(BoschSensorInfo &&other) noexcept
{
if (this != &other) {
if (info) {
free(info);
}
kernel_version = other.kernel_version;
user_version = other.user_version;
rom_version = other.rom_version;
product_id = other.product_id;
host_status = other.host_status;
feat_status = other.feat_status;
boot_status = other.boot_status;
sensor_error = other.sensor_error;
dev = other.dev;
info = other.info;
other.info = nullptr;
other.dev = nullptr;
}
return *this;
}
#if defined(ARDUINO) && !defined(ARDUINO_ARCH_MBED) && !defined(ARDUINO_ARCH_ZEPHYR)
void printVirtualSensorList(Stream &stream)
{
if (!dev) {
return;
}
if (!info) {
return;
}
if (feat_status & BHY2_FEAT_STATUS_OPEN_RTOS_MSK) {
stream.printf("Virtual sensor list.\n");
stream.printf("Sensor ID | Sensor Name | ID | Ver | Min rate | Max rate |\n");
stream.printf("----------+--------------------------------------+-----+-----+-----------+-----------|\n");
for (uint8_t i = 0; i < BHY2_SENSOR_ID_MAX; i++) {
if (bhy2_is_sensor_available(i, dev)) {
if (i < BHY2_SENSOR_ID_CUSTOM_START) {
stream.printf(" %8u | %36s ", i, get_sensor_name(i));
}
stream.printf("| %3u | %3u | %9.4f | %9.4f |\n",
(unsigned int)info[i].driver_id,
(unsigned int)info[i].driver_version,
info[i].min_rate.f_val,
info[i].max_rate.f_val);
}
}
}
}
void printBootStatus(Stream &stream)
{
stream.printf("Boot Status : 0x%02x: ", boot_status);
if (boot_status & BHY2_BST_FLASH_DETECTED) {
stream.printf("\tFlash detected. \n");
}
if (boot_status & BHY2_BST_FLASH_VERIFY_DONE) {
stream.printf("\tFlash verify done. \n");
}
if (boot_status & BHY2_BST_FLASH_VERIFY_ERROR) {
stream.printf("Flash verification failed. \n");
}
if (boot_status & BHY2_BST_NO_FLASH) {
stream.printf("\tNo flash installed. \n");
}
if (boot_status & BHY2_BST_HOST_INTERFACE_READY) {
stream.printf("\tHost interface ready. \n");
}
if (boot_status & BHY2_BST_HOST_FW_VERIFY_DONE) {
stream.printf("\tFirmware verification done. \n");
}
if (boot_status & BHY2_BST_HOST_FW_VERIFY_ERROR) {
stream.printf("\tFirmware verification error. \n");
}
if (boot_status & BHY2_BST_HOST_FW_IDLE) {
stream.printf("\tFirmware halted. \n");
}
}
void printInfo(Stream &stream)
{
stream.printf("Product ID : %02x\n", product_id);
stream.printf("Kernel version : %04u\n", kernel_version);
stream.printf("User version : %04u\n", user_version);
stream.printf("ROM version : %04u\n", rom_version);
stream.printf("Power state : %s\n", (host_status & BHY2_HST_POWER_STATE) ? "sleeping" : "active");
stream.printf("Host interface : %s\n", (host_status & BHY2_HST_HOST_PROTOCOL) ? "SPI" : "I2C");
stream.printf("Feature status : 0x%02x\n", feat_status);
printBootStatus(stream);
if (sensor_error) {
stream.printf( "%s\n", get_sensor_error_text(sensor_error));
}
printVirtualSensorList(stream);
}
#else
void printVirtualSensorList()
{
if (!dev) {
return;
}
if (!info) {
return;
}
if (feat_status & BHY2_FEAT_STATUS_OPEN_RTOS_MSK) {
printf("Virtual sensor list.\n");
printf("Sensor ID | Sensor Name | ID | Ver | Min rate | Max rate |\n");
printf("----------+--------------------------------------+-----+-----+-----------+-----------|\n");
for (uint8_t i = 0; i < BHY2_SENSOR_ID_MAX; i++) {
if (bhy2_is_sensor_available(i, dev)) {
if (i < BHY2_SENSOR_ID_CUSTOM_START) {
printf(" %8u | %36s ", i, get_sensor_name(i));
}
printf("| %3u | %3u | %9.4f | %9.4f |\n",
(unsigned int)info[i].driver_id,
(unsigned int)info[i].driver_version,
info[i].min_rate.f_val,
info[i].max_rate.f_val);
}
}
}
}
void printBootStatus()
{
printf("Boot Status : 0x%02x: ", boot_status);
if (boot_status & BHY2_BST_FLASH_DETECTED) {
printf("\tFlash detected. \n");
}
if (boot_status & BHY2_BST_FLASH_VERIFY_DONE) {
printf("\tFlash verify done. \n");
}
if (boot_status & BHY2_BST_FLASH_VERIFY_ERROR) {
printf("Flash verification failed. \n");
}
if (boot_status & BHY2_BST_NO_FLASH) {
printf("\tNo flash installed. \n");
}
if (boot_status & BHY2_BST_HOST_INTERFACE_READY) {
printf("\tHost interface ready. \n");
}
if (boot_status & BHY2_BST_HOST_FW_VERIFY_DONE) {
printf("\tFirmware verification done. \n");
}
if (boot_status & BHY2_BST_HOST_FW_VERIFY_ERROR) {
printf("\tFirmware verification error. \n");
}
if (boot_status & BHY2_BST_HOST_FW_IDLE) {
printf("\tFirmware halted. \n");
}
}
void printInfo()
{
printf("Product ID : %02x\n", product_id);
printf("Kernel version : %04u\n", kernel_version);
printf("User version : %04u\n", user_version);
printf("ROM version : %04u\n", rom_version);
printf("Power state : %s\n", (host_status & BHY2_HST_POWER_STATE) ? "sleeping" : "active");
printf("Host interface : %s\n", (host_status & BHY2_HST_HOST_PROTOCOL) ? "SPI" : "I2C");
printf("Feature status : 0x%02x\n", feat_status);
if (sensor_error) {
printf( "%s\n", get_sensor_error_text(sensor_error));
}
printBootStatus();
printVirtualSensorList();
}
#endif
};

View File

@@ -0,0 +1,730 @@
/**
* 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 bhi3.c
* @date 2023-03-24
* @version v1.6.0
*
*/
/*********************************************************************/
/* system header files */
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
/*********************************************************************/
/* BHI3 SensorAPI header files */
#include "bhi3.h"
/*************************Private Functions***************************/
/*!
* @brief To set the Physical Sensor Control Parameters
*/
int8_t bhi3_physical_sensor_control_set_config(uint8_t sensor_id,
const uint8_t *payload,
uint16_t len,
uint8_t control_code,
struct bhy2_dev *dev)
{
int8_t rslt = BHY2_OK;
uint16_t cmnd_len = BHY2_LE24MUL(len + 1); /*1 byte added for control code */
uint8_t cmnd[cmnd_len];
memset(cmnd, 0, cmnd_len);
cmnd[0] = BHI3_PHY_SENSOR_CTRL_CODE(BHI3_PHY_SENSOR_CTRL_WRITE, control_code);
if (dev == NULL)
{
rslt = BHY2_E_NULL_PTR;
}
else
{
if (payload == NULL)
{
rslt = BHY2_E_NULL_PTR;
}
else
{
for (int i = 0; i < len; i++)
{
cmnd[i + 1] = *(payload + i);
}
rslt = bhy2_set_parameter(BHI3_PHY_SENSOR_CTRL_PARAM(sensor_id), cmnd, cmnd_len, dev);
}
}
return rslt;
}
/*!
* @brief To get the Physical Sensor Control Parameters
*/
int8_t bhi3_physical_sensor_control_get_config(uint8_t sensor_id,
uint8_t *payload,
uint32_t len,
uint8_t control_code,
struct bhy2_dev *dev)
{
int8_t rslt = BHY2_OK;
uint32_t ret_len = 0;
uint8_t cmnd[BHY2_COMMAND_HEADER_LEN] = {0};
uint8_t rdbck[BHY2_LE24MUL(len)];
cmnd[0] = BHI3_PHY_SENSOR_CTRL_CODE(BHI3_PHY_SENSOR_CTRL_READ, control_code);
if (dev == NULL)
{
rslt = BHY2_E_NULL_PTR;
}
else
{
rslt = bhy2_set_parameter(BHI3_PHY_SENSOR_CTRL_PARAM(sensor_id), cmnd, BHY2_COMMAND_HEADER_LEN, dev);
if (rslt != BHY2_OK)
{
return rslt;
}
rslt = bhy2_get_parameter(BHI3_PHY_SENSOR_CTRL_PARAM(sensor_id), rdbck, BHY2_LE24MUL(len), &ret_len, dev);
if (rslt != BHY2_OK)
{
return rslt;
}
memcpy(payload, &rdbck[1], len); /*0th element holds control code */
}
return rslt;
}
/**************************Public Functions***************************/
/*!
* @brief To parse Wrist Gesture Detection Data
*/
int8_t bhi3_wrist_gesture_detect_parse_data(const uint8_t *data, bhi3_wrist_gesture_detect_t *output)
{
int8_t rslt = BHY2_OK;
if ((data == NULL) || (output == NULL))
{
rslt = BHY2_E_NULL_PTR;
}
else
{
output->wrist_gesture = (enum bhi3_wrist_gesture_activity) * (data);
}
return rslt;
}
/*!
* @brief To set the Accelerometer Fast Offset Calibration
*/
int8_t bhi3_set_acc_foc(const struct bhy2_data_xyz *acc_foc, struct bhy2_dev *dev)
{
int8_t rslt = BHY2_OK;
if (dev == NULL)
{
rslt = BHY2_E_NULL_PTR;
}
else
{
/*! Set the configuration parameter */
rslt = bhi3_physical_sensor_control_set_config(BHY2_PHYS_SENSOR_ID_ACCELEROMETER,
(uint8_t *)acc_foc,
BHI3_PHY_ACC_FOC_CTRL_LEN,
BHI3_PHY_ACC_FOC_CTRL_CODE,
dev);
}
return rslt;
}
/*!
* @brief To get the Accelerometer Fast Offset Calibration
*/
int8_t bhi3_get_acc_foc(struct bhy2_data_xyz *acc_foc, struct bhy2_dev *dev)
{
int8_t rslt = BHY2_OK;
if (dev == NULL)
{
rslt = BHY2_E_NULL_PTR;
}
else
{
/*! Get the configuration parameter */
rslt = bhi3_physical_sensor_control_get_config(BHY2_PHYS_SENSOR_ID_ACCELEROMETER,
(uint8_t *)acc_foc,
BHI3_PHY_ACC_FOC_CTRL_LEN,
BHI3_PHY_ACC_FOC_CTRL_CODE,
dev);
}
return rslt;
}
/*!
* @brief To set the Accelerometer Power Mode
*/
int8_t bhi3_set_acc_power_mode(const uint8_t *acc_pwm, struct bhy2_dev *dev)
{
int8_t rslt = BHY2_OK;
if (dev == NULL)
{
rslt = BHY2_E_NULL_PTR;
}
else
{
/*! Set the configuration parameter */
rslt = bhi3_physical_sensor_control_set_config(BHY2_PHYS_SENSOR_ID_ACCELEROMETER,
acc_pwm,
BHI3_PHY_ACC_LOW_POWER_MODE_CTRL_LEN,
BHI3_PHY_ACC_LOW_POWER_MODE_CTRL_CODE,
dev);
}
return rslt;
}
/*!
* @brief To get the Accelerometer Power Mode
*/
int8_t bhi3_get_acc_power_mode(uint8_t *acc_pwm, struct bhy2_dev *dev)
{
int8_t rslt = BHY2_OK;
if (dev == NULL)
{
rslt = BHY2_E_NULL_PTR;
}
else
{
/*! Get the configuration parameter */
rslt = bhi3_physical_sensor_control_get_config(BHY2_PHYS_SENSOR_ID_ACCELEROMETER,
acc_pwm,
BHI3_PHY_ACC_LOW_POWER_MODE_CTRL_LEN,
BHI3_PHY_ACC_LOW_POWER_MODE_CTRL_CODE,
dev);
}
return rslt;
}
/*!
* @brief To set the Gyroscope Fast Offset Calibration
*/
int8_t bhi3_set_gyro_foc(const struct bhy2_data_xyz *gyro_foc, struct bhy2_dev *dev)
{
int8_t rslt = BHY2_OK;
if (dev == NULL)
{
rslt = BHY2_E_NULL_PTR;
}
else
{
/*! Set the configuration parameter */
rslt = bhi3_physical_sensor_control_set_config(BHY2_PHYS_SENSOR_ID_GYROSCOPE,
(uint8_t *)gyro_foc,
BHI3_PHY_GYRO_FOC_CTRL_LEN,
BHI3_PHY_GYRO_FOC_CTRL_CODE,
dev);
}
return rslt;
}
/*!
* @brief To get the Gyroscope Fast Offset Calibration
*/
int8_t bhi3_get_gyro_foc(struct bhy2_data_xyz *gyro_foc, struct bhy2_dev *dev)
{
int8_t rslt = BHY2_OK;
if (dev == NULL)
{
rslt = BHY2_E_NULL_PTR;
}
else
{
/*! Get the configuration parameter */
rslt = bhi3_physical_sensor_control_get_config(BHY2_PHYS_SENSOR_ID_GYROSCOPE,
(uint8_t *)gyro_foc,
BHI3_PHY_GYRO_FOC_CTRL_LEN,
BHI3_PHY_GYRO_FOC_CTRL_CODE,
dev);
}
return rslt;
}
/*!
* @brief To set the Gyroscope OIS
*/
int8_t bhi3_set_gyro_ois(const uint8_t *gyro_ois, struct bhy2_dev *dev)
{
int8_t rslt = BHY2_OK;
if (dev == NULL)
{
rslt = BHY2_E_NULL_PTR;
}
else
{
/*! Set the configuration parameter */
rslt = bhi3_physical_sensor_control_set_config(BHY2_PHYS_SENSOR_ID_GYROSCOPE,
gyro_ois,
BHI3_PHY_GYRO_OIS_CTRL_LEN,
BHI3_PHY_GYRO_OIS_CTRL_CODE,
dev);
}
return rslt;
}
/*!
* @brief To get the Gyroscope OIS
*/
int8_t bhi3_get_gyro_ois(uint8_t *gyro_ois, struct bhy2_dev *dev)
{
int8_t rslt = BHY2_OK;
if (dev == NULL)
{
rslt = BHY2_E_NULL_PTR;
}
else
{
/*! Get the configuration parameter */
rslt = bhi3_physical_sensor_control_get_config(BHY2_PHYS_SENSOR_ID_GYROSCOPE,
gyro_ois,
BHI3_PHY_GYRO_OIS_CTRL_LEN,
BHI3_PHY_GYRO_OIS_CTRL_CODE,
dev);
}
return rslt;
}
/*!
* @brief To set the Gyroscope Fast Startup
*/
int8_t bhi3_set_gyro_fast_startup(const uint8_t *gyro_fs, struct bhy2_dev *dev)
{
int8_t rslt = BHY2_OK;
if (dev == NULL)
{
rslt = BHY2_E_NULL_PTR;
}
else
{
/*! Set the configuration parameter */
rslt = bhi3_physical_sensor_control_set_config(BHY2_PHYS_SENSOR_ID_GYROSCOPE,
gyro_fs,
BHI3_PHY_GYRO_FAST_STARTUP_CTRL_LEN,
BHI3_PHY_GYRO_FAST_STARTUP_CTRL_CODE,
dev);
}
return rslt;
}
/*!
* @brief To get the Gyroscope Fast Startup
*/
int8_t bhi3_get_gyro_fast_startup(uint8_t *gyro_fs, struct bhy2_dev *dev)
{
int8_t rslt = BHY2_OK;
if (dev == NULL)
{
rslt = BHY2_E_NULL_PTR;
}
else
{
/*! Get the configuration parameter */
rslt = bhi3_physical_sensor_control_get_config(BHY2_PHYS_SENSOR_ID_GYROSCOPE,
gyro_fs,
BHI3_PHY_GYRO_FAST_STARTUP_CTRL_LEN,
BHI3_PHY_GYRO_FAST_STARTUP_CTRL_CODE,
dev);
}
return rslt;
}
/*!
* @brief To set the Gyroscope CRT
*/
int8_t bhi3_set_gyro_crt(const uint8_t *gyro_crt, struct bhy2_dev *dev)
{
int8_t rslt = BHY2_OK;
if (dev == NULL)
{
rslt = BHY2_E_NULL_PTR;
}
else
{
/*! Set the configuration parameter */
rslt = bhi3_physical_sensor_control_set_config(BHY2_PHYS_SENSOR_ID_GYROSCOPE,
gyro_crt,
BHI3_PHY_GYRO_CRT_CTRL_LEN,
BHI3_PHY_GYRO_CRT_CTRL_CODE,
dev);
}
return rslt;
}
/*!
* @brief To get the Gyroscope CRT
*/
/*lint -e506, -e778 */
int8_t bhi3_get_gyro_crt(uint8_t *gyro_crt, struct bhy2_dev *dev)
{
int8_t rslt = BHY2_OK;
if (dev == NULL)
{
rslt = BHY2_E_NULL_PTR;
}
else
{
/*! Get the configuration parameter */
rslt =
bhi3_physical_sensor_control_get_config(BHY2_PHYS_SENSOR_ID_GYROSCOPE,
gyro_crt,
BHY2_LE24MUL(BHI3_PHY_GYRO_CRT_CTRL_LEN),
BHI3_PHY_GYRO_CRT_CTRL_CODE,
dev);
}
return rslt;
}
/*!
* @brief To set the Gyroscope Power Mode
*/
int8_t bhi3_set_gyro_power_mode(const uint8_t *gyro_pwm, struct bhy2_dev *dev)
{
int8_t rslt = BHY2_OK;
if (dev == NULL)
{
rslt = BHY2_E_NULL_PTR;
}
else
{
/*! Set the configuration parameter */
rslt = bhi3_physical_sensor_control_set_config(BHY2_PHYS_SENSOR_ID_GYROSCOPE,
gyro_pwm,
BHI3_PHY_GYRO_LOW_POWER_MODE_CTRL_LEN,
BHI3_PHY_GYRO_LOW_POWER_MODE_CTRL_CODE,
dev);
}
return rslt;
}
/*!
* @brief To get the Gyroscope Power Mode
*/
int8_t bhi3_get_gyro_power_mode(uint8_t *gyro_pwm, struct bhy2_dev *dev)
{
int8_t rslt = BHY2_OK;
if (dev == NULL)
{
rslt = BHY2_E_NULL_PTR;
}
else
{
/*! Get the configuration parameter */
rslt = bhi3_physical_sensor_control_get_config(BHY2_PHYS_SENSOR_ID_GYROSCOPE,
gyro_pwm,
BHI3_PHY_GYRO_LOW_POWER_MODE_CTRL_LEN,
BHI3_PHY_GYRO_LOW_POWER_MODE_CTRL_CODE,
dev);
}
return rslt;
}
/*!
* @brief To set the Gyroscope Timer Auto Trim state
*/
int8_t bhi3_set_gyro_timer_auto_trim(const uint8_t *gyro_tat, struct bhy2_dev *dev)
{
int8_t rslt = BHY2_OK;
if (dev == NULL)
{
rslt = BHY2_E_NULL_PTR;
}
else
{
/*! Set the configuration parameter */
rslt = bhi3_physical_sensor_control_set_config(BHY2_PHYS_SENSOR_ID_GYROSCOPE,
gyro_tat,
BHI3_PHY_GYRO_TIMER_AUTO_TRIM_CTRL_LEN,
BHI3_PHY_GYRO_TIMER_AUTO_TRIM_CTRL_CODE,
dev);
}
return rslt;
}
/*!
* @brief To get the Gyroscope Timer Auto Trim Status
*/
int8_t bhi3_get_gyro_timer_auto_trim(uint8_t *gyro_tat, struct bhy2_dev *dev)
{
int8_t rslt = BHY2_OK;
if (dev == NULL)
{
rslt = BHY2_E_NULL_PTR;
}
else
{
/*! Get the configuration parameter */
rslt = bhi3_physical_sensor_control_get_config(BHY2_PHYS_SENSOR_ID_GYROSCOPE,
gyro_tat,
BHI3_PHY_GYRO_TIMER_AUTO_TRIM_CTRL_LEN,
BHI3_PHY_GYRO_TIMER_AUTO_TRIM_CTRL_CODE,
dev);
}
return rslt;
}
/*!
* @brief To set the Wrist Wear Wakeup Configuration
*/
int8_t bhi3_set_wrist_wear_wakeup_config(const uint8_t *www_cnfg, struct bhy2_dev *dev)
{
int8_t rslt = BHY2_OK;
if (dev == NULL)
{
rslt = BHY2_E_NULL_PTR;
}
else
{
/*! Set the configuration parameter */
rslt = bhi3_physical_sensor_control_set_config(BHY2_PHYS_SENSOR_ID_WRIST_WEAR_WAKEUP,
www_cnfg,
BHI3_PHY_WRIST_WEAR_WAKEUP_CTRL_LEN,
BHI3_PHY_WRIST_WEAR_WAKEUP_CTRL_CODE,
dev);
}
return rslt;
}
/*!
* @brief To get the Wrist Wear Wakeup Configuration
*/
int8_t bhi3_get_wrist_wear_wakeup_config(uint8_t *www_cnfg, struct bhy2_dev *dev)
{
int8_t rslt = BHY2_OK;
if (dev == NULL)
{
rslt = BHY2_E_NULL_PTR;
}
else
{
/*! Get the configuration parameter */
rslt = bhi3_physical_sensor_control_get_config(BHY2_PHYS_SENSOR_ID_WRIST_WEAR_WAKEUP,
www_cnfg,
BHI3_PHY_WRIST_WEAR_WAKEUP_CTRL_LEN,
BHI3_PHY_WRIST_WEAR_WAKEUP_CTRL_CODE,
dev);
}
return rslt;
}
/*!
* @brief To set the Any Motion Configuration
*/
int8_t bhi3_set_anymotion_config(const uint8_t *any_motion_cnfg, struct bhy2_dev *dev)
{
int8_t rslt = BHY2_OK;
if (dev == NULL)
{
rslt = BHY2_E_NULL_PTR;
}
else
{
/*! Set the configuration parameter */
rslt = bhi3_physical_sensor_control_set_config(BHY2_PHYS_SENSOR_ID_PHYS_ANY_MOTION,
any_motion_cnfg,
BHI3_PHY_ANY_MOTION_CTRL_LEN,
BHI3_PHY_ANY_MOTION_CTRL_CODE,
dev);
}
return rslt;
}
/*!
* @brief To get the Any Motion Configuration
*/
int8_t bhi3_get_anymotion_config(uint8_t *any_motion_cnfg, struct bhy2_dev *dev)
{
int8_t rslt = BHY2_OK;
if (dev == NULL)
{
rslt = BHY2_E_NULL_PTR;
}
else
{
/*! Get the configuration parameter */
rslt = bhi3_physical_sensor_control_get_config(BHY2_PHYS_SENSOR_ID_PHYS_ANY_MOTION,
any_motion_cnfg,
BHI3_PHY_ANY_MOTION_CTRL_LEN,
BHI3_PHY_ANY_MOTION_CTRL_CODE,
dev);
}
return rslt;
}
/*!
* @brief To set the No Motion Configuration
*/
int8_t bhi3_set_nomotion_config(const uint8_t *no_motion_cnfg, struct bhy2_dev *dev)
{
int8_t rslt = BHY2_OK;
if (dev == NULL)
{
rslt = BHY2_E_NULL_PTR;
}
else
{
/*! Set the configuration parameter */
rslt = bhi3_physical_sensor_control_set_config(BHY2_PHYS_SENSOR_ID_PHYS_NO_MOTION,
no_motion_cnfg,
BHI3_PHY_NO_MOTION_CTRL_LEN,
BHI3_PHY_NO_MOTION_CTRL_CODE,
dev);
}
return rslt;
}
/*!
* @brief To get the No Motion Configuration
*/
int8_t bhi3_get_nomotion_config(uint8_t *no_motion_cnfg, struct bhy2_dev *dev)
{
int8_t rslt = BHY2_OK;
if (dev == NULL)
{
rslt = BHY2_E_NULL_PTR;
}
else
{
/*! Get the configuration parameter */
rslt = bhi3_physical_sensor_control_get_config(BHY2_PHYS_SENSOR_ID_PHYS_NO_MOTION,
no_motion_cnfg,
BHI3_PHY_NO_MOTION_CTRL_LEN,
BHI3_PHY_NO_MOTION_CTRL_CODE,
dev);
}
return rslt;
}
/*!
* @brief To set the Wrist Gesture Detect Configuration
*/
int8_t bhi3_set_wrist_gesture_detect_config(const uint8_t *wgd_cnfg, struct bhy2_dev *dev)
{
int8_t rslt = BHY2_OK;
if (dev == NULL)
{
rslt = BHY2_E_NULL_PTR;
}
else
{
/*! Set the configuration parameter */
rslt = bhi3_physical_sensor_control_set_config(BHY2_PHYS_SENSOR_ID_WRIST_GESTURE_DETECT,
wgd_cnfg,
BHI3_PHY_WRIST_GESTURE_DETECT_CTRL_LEN,
BHI3_PHY_WRIST_GESTURE_DETECT_CTRL_CODE,
dev);
}
return rslt;
}
/*!
* @brief To get the Wrist Gesture Detect Configuration
*/
int8_t bhi3_get_wrist_gesture_detect_config(uint8_t *wgd_cnfg, struct bhy2_dev *dev)
{
int8_t rslt = BHY2_OK;
if (dev == NULL)
{
rslt = BHY2_E_NULL_PTR;
}
else
{
rslt = bhi3_physical_sensor_control_get_config(BHY2_PHYS_SENSOR_ID_WRIST_GESTURE_DETECT,
wgd_cnfg,
BHI3_PHY_WRIST_GESTURE_DETECT_CTRL_LEN,
BHI3_PHY_WRIST_GESTURE_DETECT_CTRL_CODE,
dev);
}
return rslt;
}

View File

@@ -0,0 +1,330 @@
/**
* 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 bhi3.h
* @date 2023-03-24
* @version v1.6.0
*
*/
#ifndef __BHI3_H__
#define __BHI3_H__
/* Start of CPP Guard */
#ifdef __cplusplus
extern "C" {
#endif /*__cplusplus */
#include "bhy2.h"
#include "bhi3_defs.h"
/*!
* @brief To parse Wrist Gesture Detection Data
*
* @param[in] Wrist Gesture Detection Data
* @param[in] Wrist Gesture Detection Output Structure
*
* @return API error codes
*
*/
int8_t bhi3_wrist_gesture_detect_parse_data(const uint8_t *data, bhi3_wrist_gesture_detect_t *output);
/*!
* @brief To set the Accelerometer Fast Offset Calibration
*
* @param[in] Physical Accelerometer FOC data
* @param[in] dev hub handle
*
* @return API error codes
*
*/
int8_t bhi3_set_acc_foc(const struct bhy2_data_xyz *acc_foc, struct bhy2_dev *dev);
/*!
* @brief To get the Accelerometer Fast Offset Calibration
*
* @param[out] Physical Accelerometer FOC data
* @param[in] dev hub handle
*
* @return API error codes
*
*/
int8_t bhi3_get_acc_foc(struct bhy2_data_xyz *acc_foc, struct bhy2_dev *dev);
/*!
* @brief To set the Accelerometer Power Mode
*
* @param[in] Physical Accelerometer Power Mode data
* @param[in] dev hub handle
*
* @return API error codes
*
*/
int8_t bhi3_set_acc_power_mode(const uint8_t *acc_pwm, struct bhy2_dev *dev);
/*!
* @brief To get the Accelerometer Power Mode
*
* @param[out] Physical Accelerometer Power Mode data
* @param[in] dev hub handle
*
* @return API error codes
*
*/
int8_t bhi3_get_acc_power_mode(uint8_t *acc_pwm, struct bhy2_dev *dev);
/*!
* @brief To set the Gyroscope Fast Offset Calibration
*
* @param[in] Physical Gyroscope FOC data
* @param[in] dev hub handle
*
* @return API error codes
*
*/
int8_t bhi3_set_gyro_foc(const struct bhy2_data_xyz *gyro_foc, struct bhy2_dev *dev);
/*!
* @brief To get the Gyroscope Fast Offset Calibration
*
* @param[out] Physical Gyroscope FOC data
* @param[in] dev hub handle
*
* @return API error codes
*
*/
int8_t bhi3_get_gyro_foc(struct bhy2_data_xyz *gyro_foc, struct bhy2_dev *dev);
/*!
* @brief To set the Gyroscope OIS
*
* @param[in] Physical Gyroscope OIS data
* @param[in] dev hub handle
*
* @return API error codes
*
*/
int8_t bhi3_set_gyro_ois(const uint8_t *gyro_ois, struct bhy2_dev *dev);
/*!
* @brief To get the Gyroscope OIS
*
* @param[out] Physical Gyroscope OIS data
* @param[in] dev hub handle
*
* @return API error codes
*
*/
int8_t bhi3_get_gyro_ois(uint8_t *gyro_ois, struct bhy2_dev *dev);
/*!
* @brief To set the Gyroscope Fast Startup
*
* @param[in] Physical Gyroscope Fast Startup data
* @param[in] dev hub handle
*
* @return API error codes
*
*/
int8_t bhi3_set_gyro_fast_startup(const uint8_t *gyro_fs, struct bhy2_dev *dev);
/*!
* @brief To get the Gyroscope Fast Startup
*
* @param[out] Physical Gyroscope Fast Startup data
* @param[in] dev hub handle
*
* @return API error codes
*
*/
int8_t bhi3_get_gyro_fast_startup(uint8_t *gyro_fs, struct bhy2_dev *dev);
/*!
* @brief To set the Gyroscope CRT
*
* @param[in] Physical Gyroscope CRT data
* @param[in] dev hub handle
*
* @return API error codes
*
*/
int8_t bhi3_set_gyro_crt(const uint8_t *gyro_crt, struct bhy2_dev *dev);
/*!
* @brief To get the Gyroscope CRT
*
* @param[out] Physical Gyroscope CRT data
* @param[in] dev hub handle
*
* @return API error codes
*
*/
int8_t bhi3_get_gyro_crt(uint8_t *gyro_crt, struct bhy2_dev *dev);
/*!
* @brief To set the Gyroscope Power Mode
*
* @param[in] Physical Gyroscope Power Mode data
* @param[in] dev hub handle
*
* @return API error codes
*
*/
int8_t bhi3_set_gyro_power_mode(const uint8_t *gyro_pwm, struct bhy2_dev *dev);
/*!
* @brief To get the Gyroscope Power Mode
*
* @param[out] Physical Gyroscope Power Mode data
* @param[in] dev hub handle
*
* @return API error codes
*
*/
int8_t bhi3_get_gyro_power_mode(uint8_t *gyro_pwm, struct bhy2_dev *dev);
/*!
* @brief To set the Gyroscope Timer Auto Trim state
*
* @param[in] Physical Gyroscope Timer Auto Trim state
* @param[in] dev hub handle
*
* @return API error codes
*
*/
int8_t bhi3_set_gyro_timer_auto_trim(const uint8_t *gyro_tat, struct bhy2_dev *dev);
/*!
* @brief To get the Gyroscope Timer Auto Trim status
*
* @param[out] Physical Gyroscope Timer Auto Trim state
* @param[in] dev hub handle
*
* @return API error codes
*
*/
int8_t bhi3_get_gyro_timer_auto_trim(uint8_t *gyro_tat, struct bhy2_dev *dev);
/*!
* @brief To set the Wrist Wear Wakeup Configuration
*
* @param[in] Wrist Wear Wakeup Configuration
* @param[in] dev hub handle
*
* @return API error codes
*
*/
int8_t bhi3_set_wrist_wear_wakeup_config(const uint8_t *www_cnfg, struct bhy2_dev *dev);
/*!
* @brief To get the Wrist Wear Wakeup Configuration
*
* @param[out] Wrist Wear Wakeup Configuration
* @param[in] dev hub handle
*
* @return API error codes
*
*/
int8_t bhi3_get_wrist_wear_wakeup_config(uint8_t *www_cnfg, struct bhy2_dev *dev);
/*!
* @brief To set the Any Motion Configuration
*
* @param[in] Any Motion Configuration
* @param[in] dev hub handle
*
* @return API error codes
*
*/
int8_t bhi3_set_anymotion_config(const uint8_t *any_motion_cnfg, struct bhy2_dev *dev);
/*!
* @brief To get the Any Motion Configuration
*
* @param[out] Any Motion Configuration
* @param[in] dev hub handle
*
* @return API error codes
*
*/
int8_t bhi3_get_anymotion_config(uint8_t *any_motion_cnfg, struct bhy2_dev *dev);
/*!
* @brief To set the No Motion Configuration
*
* @param[in] No Motion Configuration
* @param[in] dev hub handle
*
* @return API error codes
*
*/
int8_t bhi3_set_nomotion_config(const uint8_t *no_motion_cnfg, struct bhy2_dev *dev);
/*!
* @brief To get the No Motion Configuration
*
* @param[out] No Motion Configuration
* @param[in] dev hub handle
*
* @return API error codes
*
*/
int8_t bhi3_get_nomotion_config(uint8_t *no_motion_cnfg, struct bhy2_dev *dev);
/*!
* @brief To set the Wrist Gesture Detection Configuration
*
* @param[in] Wrist Gesture Detection Configuration
* @param[in] dev hub handle
*
* @return API error codes
*
*/
int8_t bhi3_set_wrist_gesture_detect_config(const uint8_t *wgd_cnfg, struct bhy2_dev *dev);
/*!
* @brief To get the Wrist Gesture Detection Configuration
*
* @param[out] Wrist Gesture Detection Configuration
* @param[in] dev hub handle
*
* @return API error codes
*
*/
int8_t bhi3_get_wrist_gesture_detect_config(uint8_t *wgd_cnfg, struct bhy2_dev *dev);
/* End of CPP Guard */
#ifdef __cplusplus
}
#endif /*__cplusplus */
#endif /* __BHI3_H__ */

View File

@@ -0,0 +1,204 @@
/**
* 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 bhi3_defs.h
* @date 2023-03-24
* @version v1.6.0
*
*/
#ifndef __BHI3_DEFS_H__
#define __BHI3_DEFS_H__
/* Start of CPP Guard */
#ifdef __cplusplus
extern "C" {
#endif /*__cplusplus */
#include "bhy2_defs.h"
/*! The Product ID needs to be replaced with Chip ID for explicit HW specific Identification*/
#define BHI3_PRODUCT_ID BHY2_PRODUCT_ID
/*! Firmware header identifier */
/*#define BHY2_FW_MAGIC UINT16_C(0x662B) */
/*! BHI3 Variant IDs */
#define BHI3_VARIANT_ID_BHI360 UINT32_C(0x18BC5434)
#define BHI3_VARIANT_ID_BHI380 UINT32_C(0x6E6D6CA6)
/*! BHI3 Specifc Sensor IDs */
#define BHI3_SENSOR_ID_AR_WEAR_WU UINT8_C(154) /* Activity Recognition (wear/hear) */
#define BHI3_SENSOR_ID_WRIST_GEST_DETECT_LP_WU UINT8_C(156) /* Wrist Gesture Detector Low Power Wakeup*/
#define BHI3_SENSOR_ID_WRIST_WEAR_LP_WU UINT8_C(158) /* Wrist Wear Low Power Wakeup */
#define BHI3_SENSOR_ID_NO_MOTION_LP_WU UINT8_C(159) /* No motion Low Power */
/*! Physical Sensor Control Parameter Page Base Address*/
#define BHI3_PHY_SENSOR_CTRL_PAGE UINT16_C(0x0E)
/*! Physical Sensor Control pages
* Here the 'id' refers to the Sensor ID of requisite Physical Sensors (Acc/Gyro)
* */
#define BHI3_PHY_SENSOR_CTRL_PARAM(id) (((BHI3_PHY_SENSOR_CTRL_PAGE) << 8) | (id))
#define BHI3_PHY_SENSOR_CTRL_CODE(dir, code) ((dir << 7) | (code))
#define BHI3_PHY_SENSOR_CTRL_WRITE UINT8_C(0x00)
#define BHI3_PHY_SENSOR_CTRL_READ UINT8_C(0x01)
#define BHI3_PHY_ACC_FOC_CTRL_CODE UINT8_C(0x01)
#define BHI3_PHY_ACC_FOC_CTRL_LEN 6
#define BHI3_PHY_ACC_LOW_POWER_MODE_CTRL_CODE UINT8_C(0x05)
#define BHI3_PHY_ACC_NORMAL_POWER_MODE UINT8_C(0x00)
#define BHI3_PHY_ACC_LOW_POWER_MODE UINT8_C(0x02)
#define BHI3_PHY_ACC_LOW_POWER_MODE_CTRL_LEN 1
#define BHI3_PHY_GYRO_FOC_CTRL_CODE UINT8_C(0x01)
#define BHI3_PHY_GYRO_FOC_CTRL_LEN 6
#define BHI3_PHY_GYRO_OIS_CTRL_CODE UINT8_C(0x02)
#define BHI3_PHY_GYRO_DISABLE_OIS UINT8_C(0x00)
#define BHI3_PHY_GYRO_ENABLE_OIS UINT8_C(0x01)
#define BHI3_PHY_GYRO_OIS_CTRL_LEN 1
#define BHI3_PHY_GYRO_FAST_STARTUP_CTRL_CODE UINT8_C(0x03)
#define BHI3_PHY_GYRO_DISABLE_FAST_STARTUP UINT8_C(0x00)
#define BHI3_PHY_GYRO_ENABLE_FAST_STARTUP UINT8_C(0x01)
#define BHI3_PHY_GYRO_FAST_STARTUP_CTRL_LEN 1
#define BHI3_PHY_GYRO_CRT_CTRL_CODE UINT8_C(0x04)
#define BHI3_PHY_GYRO_CRT_STATUS_SUCCESS UINT8_C(0x00)
#define BHI3_PHY_GYRO_ENABLE_CRT UINT8_C(0x01)
#define BHI3_PHY_GYRO_CRT_CTRL_LEN 1
#define BHI3_PHY_GYRO_LOW_POWER_MODE_CTRL_CODE UINT8_C(0x05)
#define BHI3_PHY_GYRO_NORMAL_POWER_MODE UINT8_C(0x00)
#define BHI3_PHY_GYRO_PERFORMANCE_POWER_MODE UINT8_C(0x01)
#define BHI3_PHY_GYRO_LOW_POWER_MODE UINT8_C(0x02)
#define BHI3_PHY_GYRO_LOW_POWER_MODE_CTRL_LEN 1
#define BHI3_PHY_GYRO_TIMER_AUTO_TRIM_CTRL_CODE UINT8_C(0x06)
#define BHI3_PHY_GYRO_DISABLE_TIMER_AUTO_TRIM UINT8_C(0x00)
#define BHI3_PHY_GYRO_ENABLE_TIMER_AUTO_TRIM UINT8_C(0x01)
#define BHI3_PHY_GYRO_TIMER_AUTO_TRIM_CTRL_LEN 1
#define BHI3_PHY_WRIST_WEAR_WAKEUP_CTRL_CODE UINT8_C(0x01)
#define BHI3_PHY_WRIST_WEAR_WAKEUP_CTRL_LEN 10
#define BHI3_PHY_ANY_MOTION_CTRL_CODE UINT8_C(0x01)
#define BHI3_PHY_ANY_MOTION_CTRL_LEN 4
#define BHI3_PHY_NO_MOTION_CTRL_CODE UINT8_C(0x01)
#define BHI3_PHY_NO_MOTION_CTRL_LEN 4
#define BHI3_PHY_WRIST_GESTURE_DETECT_CTRL_CODE UINT8_C(0x07)
#define BHI3_PHY_WRIST_GESTURE_DETECT_CTRL_LEN 19
typedef struct bhi3_wrist_wear_wakeup_config_param {
uint16_t min_angle_focus;
uint16_t min_angle_nonfocus;
uint8_t angle_landscape_right;
uint8_t angle_landscape_left;
uint8_t angle_portrait_down;
uint8_t angle_portrait_up;
uint8_t min_dur_moved;
uint8_t min_dur_quite;
} __attribute__ ((packed)) bhi3_wrist_wear_wakeup_config_param_t;
typedef struct bhi3_any_no_motion_config_param {
uint16_t duration;
uint8_t axis;
uint16_t threshold;
} __attribute__ ((packed)) bhi3_any_no_motion_config_param_t;
typedef struct bhi3_wrist_gesture_detect_config_param {
uint16_t min_flick_peak_y_threshold;
uint16_t min_flick_peak_z_threshold;
uint16_t gravity_bounds_x_pos;
uint16_t gravity_bounds_x_neg;
uint16_t gravity_bounds_y_neg;
uint16_t gravity_bounds_z_neg;
uint16_t flick_peak_decay_coeff;
uint16_t lp_mean_filter_coeff;
uint16_t max_duration_jiggle_peaks;
uint8_t device_position;
} __attribute__ ((packed)) bhi3_wrist_gesture_detect_config_param_t;
enum bhi3_wrist_gesture_activity {
NO_GESTURE,
WRIST_SHAKE_JIGGLE = 0x03,
FLICK_IN,
FLICK_OUT
};
typedef struct bhi3_wrist_gesture_detect {
enum bhi3_wrist_gesture_activity wrist_gesture;
} __attribute__ ((packed)) bhi3_wrist_gesture_detect_t;
static const char *const bhi3_wrist_gesture_detect_output[] = {
[NO_GESTURE] = "NO_GESTURE",
[1] = "",
[2] = "",
[WRIST_SHAKE_JIGGLE] = "WRIST_SHAKE_JIGGLE",
[FLICK_IN] = "FLICK_IN",
[FLICK_OUT] = "FLICK_OUT"
}; /*lint -e528 */
enum bhi3_phy_sensor_acc_power_mode {
ACC_NORMAL,
ACC_LOW_POWER = 0x02
};
enum bhi3_phy_sensor_gyro_power_mode {
GYRO_NORMAL,
GYRO_PERFORMANCE,
GYRO_LOW_POWER
};
static const char *const bhi3_phy_sensor_acc_pwm_output[] = {
[ACC_NORMAL] = "NORMAL",
[1] = "",
[ACC_LOW_POWER] = "LOW POWER"
}; /*lint -e528 */
static const char *const bhi3_phy_sensor_gyro_pwm_output[] = {
[GYRO_NORMAL] = "NORMAL",
[GYRO_PERFORMANCE] = "PERFORMANCE",
[GYRO_LOW_POWER] = "LOW POWER"
}; /*lint -e528 */
/* End of CPP Guard */
#ifdef __cplusplus
}
#endif /*__cplusplus */
#endif /* __BHI3_DEFS_H__ */

View File

@@ -0,0 +1,211 @@
/**
* 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 bhi3_multi_tap.c
* @date 2023-03-24
* @version v1.6.0
*
*/
/*********************************************************************/
/* system header files */
/*********************************************************************/
#include <string.h>
#include <stdio.h>
/*********************************************************************/
/* BHI3 SensorAPI header files */
/*********************************************************************/
#include "bhi3.h"
/*********************************************************************/
/* own header files */
/*********************************************************************/
#include "bhi3_multi_tap.h"
/*lint -e506, -e778*/
/*!
* @brief This API writes to the configuration parameter
*
* @param[in] buffer to store Multi Tap configuration
* @param[out] dev hub handle.
*
* @return rslt execution result.
*/
int8_t bhi3_multi_tap_set_config(const void *buffer, struct bhy2_dev *dev)
{
int8_t rslt = BHY2_OK;
if (dev == NULL)
{
rslt = BHY2_E_NULL_PTR;
}
else
{
/*! Set the Multi Tap configuration parameter */
rslt = bhy2_set_parameter(BHI3_MULTI_TAP_PARAM(BHI3_MULTI_TAP_ENABLE_PARAM),
(uint8_t*)buffer,
BHI3_MULTI_TAP_ENABLE_LENGTH,
dev);
}
return rslt;
}
/*!
* @brief To get the MULTI-TAP configuration parameters
*
* @param[out] buffer to store Multi Tap configuration
* @param[in] dev hub handle
*
* @return status code, BHY_HIF_E_SUCCESS in case of success
*
*/
int8_t bhi3_multi_tap_get_config(const void *buffer, struct bhy2_dev *dev)
{
int8_t rslt = BHY2_OK;
uint32_t ret_length;
if (dev == NULL)
{
rslt = BHY2_E_NULL_PTR;
}
else
{
/*! Get the Multi Tap configuration from the parameter page*/
rslt =
bhy2_get_parameter(BHI3_MULTI_TAP_PARAM(BHI3_MULTI_TAP_ENABLE_PARAM),
(uint8_t *)buffer,
BHY2_LE24MUL(BHI3_MULTI_TAP_ENABLE_LENGTH),
&ret_length,
dev);
if (rslt != BHY2_OK)
{
/*! Invalid number of parameters readout */
rslt = BHY2_E_INVALID_EVENT_SIZE;
}
}
return rslt;
}
/*!
* @brief This API writes to the tap detector configuration parameter
*
* @param[in] buffer to store Multi Tap Detector configuration
* @param[out] dev hub handle.
*
* @return rslt execution result.
*/
int8_t bhi3_multi_tap_detector_set_config(const void *buffer, struct bhy2_dev *dev)
{
int8_t rslt = BHY2_OK;
if (dev == NULL)
{
rslt = BHY2_E_NULL_PTR;
}
else
{
/*! Set the Multi Tap configuration parameter */
rslt = bhy2_set_parameter(BHI3_MULTI_TAP_PARAM(BHI3_MULTI_TAP_DETECTOR_CONFIG_PARAM),
(uint8_t*)buffer,
BHI3_MULTI_TAP_DETECTOR_CONFIG_LENGTH,
dev);
}
return rslt;
}
/*!
* @brief To get the MULTI-TAP Detector configuration parameters
*
* @param[out] buffer to store Multi Tap Detector configuration
* @param[in] dev hub handle
*
* @return status code, BHY_HIF_E_SUCCESS in case of success
*
*/
int8_t bhi3_multi_tap_detector_get_config(const void *buffer, struct bhy2_dev *dev)
{
int8_t rslt = BHY2_OK;
uint32_t ret_length;
if (dev == NULL)
{
rslt = BHY2_E_NULL_PTR;
}
else
{
/*! Get the Multi Tap configuration from the parameter page*/
rslt = bhy2_get_parameter(BHI3_MULTI_TAP_PARAM(BHI3_MULTI_TAP_DETECTOR_CONFIG_PARAM),
(uint8_t *)buffer,
BHY2_LE24MUL(BHI3_MULTI_TAP_DETECTOR_CONFIG_LENGTH),
&ret_length,
dev);
if (rslt != BHY2_OK)
{
/*! Invalid number of parameters readout */
rslt = BHY2_E_INVALID_EVENT_SIZE;
}
}
return rslt;
}
/*!
* @brief Parsing the fifo data to Multi Tap output format
*
* @param[in] Multi Tap data
* @param[out] buffer to store parameter data
*
* @return API error codes
*
*/
int8_t bhi3_multi_tap_parse_data(const uint8_t *data, uint8_t* output)
{
int8_t rslt = BHY2_OK;
if ((data == NULL) || (output == NULL))
{
rslt = BHY2_E_NULL_PTR;
}
else
{
*output = *data;
}
return rslt;
}

View File

@@ -0,0 +1,111 @@
/**
* 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 bhi3_multi_tap.h
* @date 2023-03-24
* @version v1.6.0
*
*/
#ifndef _BHY2_MULTI_TAP_H_
#define _BHY2_MULTI_TAP_H_
/* Start of CPP Guard */
#ifdef __cplusplus
extern "C" {
#endif /*__cplusplus */
#include <stdint.h>
#include <stdlib.h>
#include "bhi3.h"
#include "bhi3_multi_tap_defs.h"
/*!
* @brief Parsing the fifo data to MULTI_TAP output structure format
*
* @param[in] Multi Tap data
* @param[out] buffer to store parameter data
*
* @return API error codes
*
*/
int8_t bhi3_multi_tap_parse_data(const uint8_t *data, uint8_t *output);
/*!
* @brief To set the MULTI_TAP configuration parameters
* @param[out] buffer to store parameter data
* @param[in] dev hub handle
*
* @return status code, BHY_HIF_E_SUCCESS in case of success
*
*/
int8_t bhi3_multi_tap_set_config(const void *buffer, struct bhy2_dev *dev);
/*!
* @brief To get the MULTI_TAP configuration parameters
*
* @param[out] buffer to store parameter data
* @param[in] dev hub handle
*
* @return status code, BHY_HIF_E_SUCCESS in case of success
*
*/
int8_t bhi3_multi_tap_get_config(const void *buffer, struct bhy2_dev *dev);
/*!
* @brief To set the MULTI_TAP Detector configuration parameters
* @param[out] buffer to store parameter data
* @param[in] dev hub handle
*
* @return status code, BHY_HIF_E_SUCCESS in case of success
*
*/
int8_t bhi3_multi_tap_detector_set_config(const void *buffer, struct bhy2_dev *dev);
/*!
* @brief To get the MULTI_TAP Detector configuration parameters
*
* @param[out] buffer to store parameter data
* @param[in] dev hub handle
*
* @return status code, BHY_HIF_E_SUCCESS in case of success
*
*/
int8_t bhi3_multi_tap_detector_get_config(const void *buffer, struct bhy2_dev *dev);
/* End of CPP Guard */
#ifdef __cplusplus
}
#endif /*__cplusplus */
#endif /* _BHY2_MULTI_TAP_H_ */

View File

@@ -0,0 +1,189 @@
/**
* 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 bhi3_multi_tap_defs.h
* @date 2023-03-24
* @version v1.6.0
*
*/
#ifndef _BHI3_MULTI_TAP_DEFS_H_
#define _BHI3_MULTI_TAP_DEFS_H_
/* Start of CPP Guard */
#ifdef __cplusplus
extern "C" {
#endif /*__cplusplus */
#include <stdint.h>
#include <string.h>
/*! Sensor ID for Multi-Tap */
#define BHI3_SENSOR_ID_MULTI_TAP UINT8_C(153)
/*! Multi-Tap Parameter Page Base Address*/
#define BHI3_MULTI_TAP_PAGE UINT16_C(0x0D)
/*! Multi-Tap Configuration pages */
#define BHI3_MULTI_TAP_ENABLE_PARAM 0x01
#define BHI3_MULTI_TAP_DETECTOR_CONFIG_PARAM 0x02
#define BHI3_MULTI_TAP_PARAM(id) (((BHI3_MULTI_TAP_PAGE) << 8) | (id))
#define BHI3_MULTI_TAP_ENABLE_LENGTH UINT8_C(4)
#define BHI3_MULTI_TAP_DETECTOR_CONFIG_LENGTH UINT8_C(6)
#define BHI3_MULTI_TAP_AXIS_SEL_X UINT8_C(0)
#define BHI3_MULTI_TAP_AXIS_SEL_Y UINT8_C(1)
#define BHI3_MULTI_TAP_AXIS_SEL_Z UINT8_C(2)
#define BHI3_MULTI_TAP_WAIT_TIMEOUT_DISABLE UINT8_C(0)
#define BHI3_MULTI_TAP_WAIT_TIMEOUT_ENABLE UINT8_C(1)
#define BHI3_MULTI_TAP_FILTER_MODE_SENSITIVE UINT8_C(0)
#define BHI3_MULTI_TAP_FILTER_MODE_NORMAL UINT8_C(1)
#define BHI3_MULTI_TAP_FILTER_MODE_ROBUST UINT8_C(2)
#define BHI3_SINGLE_TAP_AXIS_SEL_MASK 0x03
#define BHI3_SINGLE_TAP_WAIT_TIMEOUT_MASK 0x04
#define BHI3_SINGLE_TAP_MAX_PEAKS_FOR_TAP_MASK 0x38
#define BHI3_SINGLE_TAP_FILTER_MODE_MASK 0xC0
#define BHI3_DOUBLE_TAP_TAP_PEAK_DUR_MASK 0x03FF
#define BHI3_DOUBLE_TAP_MAX_GES_DUR_MASK 0xFC00
#define BHI3_TRIPLE_TAP_MAX_DUR_BW_PEAKS_MASK 0x0F
#define BHI3_TRIPLE_TAP_TAP_SHOCK_SETL_DUR_MASK 0xF0
#define BHI3_TRIPLE_TAP_MIN_QT_DUR_BW_PEAKS_MASK 0x0F
#define BHI3_TRIPLE_TAP_QT_TM_AFTER_GESTURE_MASK 0xF0
#define BHI3_SINGLE_TAP_AXIS_SEL_SHIFT UINT8_C(0)
#define BHI3_SINGLE_TAP_WAIT_TIMEOUT_SHIFT UINT8_C(2)
#define BHI3_SINGLE_TAP_MAX_PEAKS_FOR_TAP_SHIFT UINT8_C(3)
#define BHI3_SINGLE_TAP_FILTER_MODE_SHIFT UINT8_C(6)
#define BHI3_DOUBLE_TAP_TAP_PEAK_DUR_SHIFT UINT8_C(0)
#define BHI3_DOUBLE_TAP_MAX_GES_DUR_SHIFT UINT8_C(10)
#define BHI3_TRIPLE_TAP_MAX_DUR_BW_PEAKS_SHIFT UINT8_C(0)
#define BHI3_TRIPLE_TAP_TAP_SHOCK_SETL_DUR_SHIFT UINT8_C(4)
#define BHI3_TRIPLE_TAP_MIN_QT_DUR_BW_PEAKS_SHIFT UINT8_C(0)
#define BHI3_TRIPLE_TAP_QT_TM_AFTER_GESTURE_SHIFT UINT8_C(4)
/*!
* Single Tap Configuration.
*/
typedef union bhi3_singletap_detector_settings
{
uint16_t as_uint16;
struct
{
uint16_t axis_sel : 2; /* Tap axis selection */
uint16_t wait_for_timeout : 1; /* Wait for gesture confirmation */
uint16_t max_peaks_for_tap : 3; /* Maximum number of peaks that can occur when a tap is done
* */
uint16_t mode : 2; /* Filter configuration for various detection mode: SENSITIVE, NORMAL and
* ROBUST */
uint16_t reserved8 : 8;
} as_s;
} __attribute__ ((packed)) bhi3_singletap_detector_settings_t;
/*!
* Double Tap Configuration.
*/
typedef union bhi3_doubletap_detector_settings
{
uint16_t as_uint16;
struct
{
uint16_t tap_peak_thres : 10; /* Minimum threshold for peak detection */
uint16_t max_gesture_dur : 6; /* Maximum time duration from first tap within which matching
* tap/s should happen to be detected as double/triple tap */
} as_s;
} __attribute__ ((packed)) bhi3_doubletap_detector_settings_t;
/*!
* Triple Tap Configuration.
*/
typedef union bhi3_tripletap_detector_settings
{
uint16_t as_uint16;
struct
{
uint16_t max_dur_between_peaks : 4; /* Maximum time duration within which matching peaks of tap
* should occur */
uint16_t tap_shock_settling_dur : 4; /* Maximum duration to wait for tap shock settling */
uint16_t min_quite_dur_between_taps : 4; /* Minimum quite time between detection of consecutive taps
* of double/triple taps*/
uint16_t quite_time_after_gesture : 4; /* Minimum quite time between detection of 2 consecutive
* selected gesture */
} as_s;
} __attribute__ ((packed)) bhi3_tripletap_detector_settings_t;
/*!
* Multi Tap Configuration.
*/
typedef struct bhi3_multi_tap_detector
{
bhi3_singletap_detector_settings_t stap_setting;
bhi3_doubletap_detector_settings_t dtap_setting;
bhi3_tripletap_detector_settings_t ttap_setting;
} __attribute__ ((packed)) bhi3_multi_tap_detector_t;
/*!
* Multi Tap Setting.
*/
enum bhi3_multi_tap_val {
NO_TAP,
SINGLE_TAP,
DOUBLE_TAP,
DOUBLE_SINGLE_TAP,
TRIPLE_TAP,
TRIPLE_SINGLE_TAP,
TRIPLE_DOUBLE_TAP,
TRIPLE_DOUBLE_SINGLE_TAP
};
/*!
* Multi Tap Output.
*/
static const char * const bhi3_multi_tap_string_out[] = {
[NO_TAP] = "NO_TAP", [SINGLE_TAP] = "SINGLE_TAP", [DOUBLE_TAP] = "DOUBLE_TAP",
[DOUBLE_SINGLE_TAP] = "DOUBLE_SINGLE_TAP", [TRIPLE_TAP] = "TRIPLE_TAP", [TRIPLE_SINGLE_TAP] = "TRIPLE_SINGLE_TAP",
[TRIPLE_DOUBLE_TAP] = "TRIPLE_DOUBLE_TAP", [TRIPLE_DOUBLE_SINGLE_TAP] = "TRIPLE_DOUBLE_SINGLE_TAP"
}; /*lint -e528 */
/* End of CPP Guard */
#ifdef __cplusplus
}
#endif /*__cplusplus */
#endif /* _BHI3_MULTI_TAP_DEFS_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,665 @@
/**
* 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 bhy2.h
* @date 2023-03-24
* @version v1.6.0
*
*/
#ifndef __BHY2_H__
#define __BHY2_H__
/* Start of CPP Guard */
#ifdef __cplusplus
extern "C" {
#endif /*__cplusplus */
#include "bhy2_defs.h"
/**
* @brief Function to link the callback interfaces
* @param[in] intf : Physical communication interface
* @param[in] read : Read function pointer
* @param[in] write : Write function pointer
* @param[in] delay_us : Microsecond delay function pointer
* @param[in] read_write_len : Maximum read/write lengths supported
* @param[in] intf_ptr : Reference to the interface. Can be NULL
* @param[out] dev : Device reference
* @return API error codes
*/
int8_t bhy2_init(enum bhy2_intf intf,
bhy2_read_fptr_t read,
bhy2_write_fptr_t write,
bhy2_delay_us_fptr_t delay_us,
uint32_t read_write_len,
void *intf_ptr,
struct bhy2_dev *dev);
/**
* @brief Function to get data from registers
* @param[in] reg_addr : Register address to be read from
* @param[out] reg_data : Reference to the data buffer
* @param[in] length : Length of the data buffer
* @param[in] dev : Device reference
* @return API Error codes
*/
int8_t bhy2_get_regs(uint8_t reg_addr, uint8_t *reg_data, uint16_t length, struct bhy2_dev *dev);
/**
* @brief Function to set data to registers
* @param[in] reg_addr : Register address to write to
* @param[in] reg_data : Reference to the data buffer
* @param[in] length : Length of the data buffer
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_set_regs(uint8_t reg_addr, const uint8_t *reg_data, uint16_t length, struct bhy2_dev *dev);
/**
* @brief Function to get the product ID
* @param[out] product_id : Reference to data buffer to store the product ID
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_get_product_id(uint8_t *product_id, struct bhy2_dev *dev);
/**
* @brief Function to get the chip ID
* @param[out] chip_id : Reference to data buffer to store the chip ID
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_get_chip_id(uint8_t *chip_id, struct bhy2_dev *dev);
/**
* @brief Function to get the revision ID
* @param[out] revision_id : Reference to data buffer to store the revision ID
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_get_revision_id(uint8_t *revision_id, struct bhy2_dev *dev);
/**
* @brief Function to get the ROM version
* @param[out] rom_version : Reference to the data buffer to store the ROM version
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_get_rom_version(uint16_t *rom_version, struct bhy2_dev *dev);
/**
* @brief Function to get the kernel version
* @param[out] kernel_version : Reference to the data buffer to store the kernel version
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_get_kernel_version(uint16_t *kernel_version, struct bhy2_dev *dev);
/**
* @brief Function to get the user version
* @param[out] user_version : Reference to the data buffer to store the user version
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_get_user_version(uint16_t *user_version, struct bhy2_dev *dev);
/**
* @brief Function to get the boot status
* @param[out] boot_status : Reference to the data buffer to store the boot status
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_get_boot_status(uint8_t *boot_status, struct bhy2_dev *dev);
/**
* @brief Function to get the host status
* @param[out] host_status : Reference to the data buffer to store the host status
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_get_host_status(uint8_t *host_status, struct bhy2_dev *dev);
/**
* @brief Function to get the feature status
* @param[out] feat_status : Reference to the data buffer to store the feature status
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_get_feature_status(uint8_t *feat_status, struct bhy2_dev *dev);
/**
* @brief Function to get the virtual sensor list and store in the device structure
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_get_virt_sensor_list(struct bhy2_dev *dev);
/**
* @brief Function to get the virtual sensor configuration
* @param[in] sensor_id : Sensor ID of the virtual sensor
* @param[out] virt_sensor_conf : Reference to the data buffer to store the virtual sensor configuration
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_get_virt_sensor_cfg(uint8_t sensor_id, struct bhy2_virt_sensor_conf *virt_sensor_conf,
struct bhy2_dev *dev);
/**
* @brief Function to set the sample rate and latency of the virtual sensor
* @param[in] sensor_id : Sensor ID of the virtual sensor
* @param[in] sample_rate : Sample rate in Hz
* @param[in] latency : Report latency in milliseconds
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_set_virt_sensor_cfg(uint8_t sensor_id, bhy2_float sample_rate, uint32_t latency, struct bhy2_dev *dev);
/**
* @brief Function set the range of the virtual sensor
* @param[in] sensor_id : Sensor ID of the virtual sensor
* @param[in] range : Range of the virtual sensor
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_set_virt_sensor_range(uint8_t sensor_id, uint16_t range, struct bhy2_dev *dev);
/**
* @brief Function to get and process the FIFOs
* @param[in] work_buffer : Reference to the data buffer where the FIFO data is copied to before parsing
* @param[in] buffer_size : Size of the data buffer
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_get_and_process_fifo(uint8_t *work_buffer, uint32_t buffer_size, struct bhy2_dev *dev);
/**
* @brief Function get the FIFO control register
* @param[out] fifo_ctrl : Reference to the data buffer to store the FIFO control
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_get_fifo_ctrl(uint32_t *fifo_ctrl, struct bhy2_dev *dev);
/**
* @brief Function to set the Wake up FIFO watermark
* @param[in] watermark : Size of the watermark
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_set_fifo_wmark_wkup(uint32_t watermark, struct bhy2_dev *dev);
/**
* @brief Function to get the Wake up FIFO watermark
* @param[out] watermark : Reference to the data buffer to store the FIFO watermark size
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_get_fifo_wmark_wkup(uint32_t *watermark, struct bhy2_dev *dev);
/**
* @brief Function to set the Non wake up FIFO watermark
* @param[in] watermark : Size of the watermark
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_set_fifo_wmark_nonwkup(uint32_t watermark, struct bhy2_dev *dev);
/**
* @brief Function to get the Non wake up FIFO watermark
* @param[out] watermark : Reference to the data buffer to store the FIFO watermark size
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_get_fifo_wmark_nonwkup(uint32_t *watermark, struct bhy2_dev *dev);
/**
* @brief Function to flush data of a virtual sensor from the FIFOs
* @param[in] sensor_id : Sensor ID of the virtual sensor
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_flush_fifo(uint8_t sensor_id, struct bhy2_dev *dev);
/**
* @brief Function to set the FIFO format
* @param[in] param : FIFO format settings
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_set_fifo_format_ctrl(uint8_t param, struct bhy2_dev *dev);
/**
* @brief Function to upload firmware to RAM
* @param[in] firmware : Reference to the data buffer containing the firmware
* @param[in] length : Size of the firmware
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_upload_firmware_to_ram(const uint8_t *firmware, uint32_t length, struct bhy2_dev *dev);
/**
* @brief Function to upload part of the firmware to RAM
* @param[in] firmware : Reference to the data buffer containing the current firmware section
* @param[in] total_size : Total size of the firmware
* @param[in] cur_pos : Current position of the part being loaded
* @param[in] packet_len : Size of the part being loaded
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_upload_firmware_to_ram_partly(const uint8_t *firmware,
uint32_t total_size,
uint32_t cur_pos,
uint32_t packet_len,
struct bhy2_dev *dev);
/**
* @brief Function to boot firmware from RAM
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_boot_from_ram(struct bhy2_dev *dev);
/**
* @brief Function to erase the flash
* @param[in] start_addr : Start address
* @param[in] end_addr : End address
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_erase_flash(uint32_t start_address, uint32_t end_addr, struct bhy2_dev *dev);
/**
* @brief Function to upload firmware to Flash
* @param[in] firmware : Reference to the data buffer containing the firmware
* @param[in] length : Size of the firwmare
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_upload_firmware_to_flash(const uint8_t *firmware, uint32_t length, struct bhy2_dev *dev,
bhy2_progress_callback progress_cb, void *user_data);
/**
* @brief Function to upload part of the firmware to Flash
* @param[in] firmware : Reference to the data buffer containing the current firmware section
* @param[in] cur_pos : Current position of the part being loaded
* @param[in] packet_len : Size of the part being loaded
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_upload_firmware_to_flash_partly(const uint8_t *firmware,
uint32_t cur_pos,
uint32_t packet_len,
struct bhy2_dev *dev);
/**
* @brief Function to boot from Flash
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_boot_from_flash(struct bhy2_dev *dev);
/**
* @brief Function to set the host interrupt control register
* @param[in] hintr_ctrl : Host interrupt control configuration
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_set_host_interrupt_ctrl(uint8_t hintr_ctrl, struct bhy2_dev *dev);
/**
* @brief Function to get the host interrupt control register
* @param[out] hintr_ctrl : Reference to the data buffer to store the configuration
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_get_host_interrupt_ctrl(uint8_t *hintr_ctrl, struct bhy2_dev *dev);
/**
* @brief Function to get the interrupt status register
* @param[out] int_status : Reference to the data buffer to store the interrupt status
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_get_interrupt_status(uint8_t *int_status, struct bhy2_dev *dev);
/**
* @brief Function to set the host interface control register
* @param[in] hintf_ctrl : Host interface control configuration
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_set_host_intf_ctrl(uint8_t hintf_ctrl, struct bhy2_dev *dev);
/**
* @brief Function to get the host interface control register
* @param[out] hintf_ctrl : Reference to the data buffer to store the configuration
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_get_host_intf_ctrl(uint8_t *hintf_ctrl, struct bhy2_dev *dev);
/**
* @brief Function to trigger a timestamp event
* @param[in] ts_ev_req : Pass a non-zero value to trigger a timestamp event
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_set_timestamp_event_req(uint8_t ts_ev_req, struct bhy2_dev *dev);
/**
* @brief Function to get the timestamp of the sensor in nanoseconds
* @param[out] timestamp_ns : Reference to the data buffer to store the timestamp in nanoseconds
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_get_hw_timestamp_ns(uint64_t *timestamp_ns, struct bhy2_dev *dev);
/**
* @brief Function to get the host control register
* @param[in] host_ctrl : Host control configuration
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_set_host_ctrl(uint8_t host_ctrl, struct bhy2_dev *dev);
/**
* @brief Function to get the host control register
* @param[out] host_ctrl : Reference to the data buffer to store the host control configuration
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_get_host_ctrl(uint8_t *host_ctrl, struct bhy2_dev *dev);
/**
* @brief Function to trigger a soft reset
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_soft_reset(struct bhy2_dev *dev);
/**
* @brief Function to perform a self test of a virtual sensor
* @param[in] phys_sensor_id : Physical sensor ID of the virtual sensor
* @param[out] self_test_resp : Reference to the data buffer to store the self test response from the virtual sensor
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_perform_self_test(uint8_t phys_sensor_id, struct bhy2_self_test_resp *self_test_resp, struct bhy2_dev *dev);
/**
* @brief Function to perform a fast offset compensation of a virtual sensor
* @param[in] phys_sensor_id : Physical Sensor ID of the virtual sensor
* @param[out] self_test_resp : Reference to the data buffer to store the FOC response from the virtual sensor
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_perform_foc(uint8_t phys_sensor_id, struct bhy2_foc_resp *foc_resp, struct bhy2_dev *dev);
/**
* @brief Function to set the orientation matrix of a physical sensor
* @param[in] phys_sensor_id : Sensor ID of the virtual sensor
* @param[in] orient_matrix : Orientation matrix
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_set_orientation_matrix(uint8_t phys_sensor_id, struct bhy2_orient_matrix orient_matrix,
struct bhy2_dev *dev);
/**
* @brief Function to get the physical sensor information
* @param[in] phys_sensor_id : Sensor ID of the physical sensor
* @param[out] phy_sen_info : Reference to the data buffer to the store the physical sensor information
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_get_phys_sensor_info(uint8_t phys_sensor_id,
struct bhy2_phys_sensor_info *phy_sen_info,
struct bhy2_dev *dev);
/**
* @brief Function to get the orientation matrix of a physical sensor
* @param[in] phys_sensor_id : Sensor ID of the virtual sensor
* @param[out] orient_matrix : Reference to the data buffer to the store the orientation matrix
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_get_orientation_matrix(uint8_t phys_sensor_id,
struct bhy2_orient_matrix *orient_matrix,
struct bhy2_dev *dev);
/**
* @brief Function to set the Soft Iron Correction matrix
* @param[in] sic_matrix : Reference to the data buffer storing the Soft Iron Correction matrix
* @param[in] matrix_len : Length of the matrix
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_set_sic_matrix(const uint8_t *sic_matrix, uint16_t matrix_len, struct bhy2_dev *dev);
/**
* @brief Function to get the Soft Iron Correction matrix
* @param[out] sic_matrix : Reference to the data buffer to store the Soft Iron Correction matrix
* @param[in] matrix_len : Length of data buffer
* @param[out] actual_len : Actual length of the Soft Iron Correction matrix
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_get_sic_matrix(uint8_t *sic_matrix, uint16_t matrix_len, uint32_t *actual_len, struct bhy2_dev *dev);
/**
* @brief Function to get the calibration profile of a BSX virtual sensor
* @param[in] phys_sensor_id: Physical Sensor ID of the virtual sensor
* @param[out] calib_prof : Reference to the data buffer to store the calibration profile
* @param[in] prof_len : Length of the data buffer
* @param[out] actual_len : Actual length of the calibration profile
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_get_calibration_profile(uint8_t phys_sensor_id,
uint8_t *calib_prof,
uint16_t prof_len,
uint32_t *actual_len,
struct bhy2_dev *dev);
/**
* @brief Function to set the calibration profile of a BSX virtual sensor
* @param[in] phys_sensor_id: Physical Sensor ID of the virtual sensor
* @param[in] calib_prof : Reference to the data buffer storing the calibration profile
* @param[in] prof_len : Length of the profil
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_set_calibration_profile(uint8_t phys_sensor_idv,
const uint8_t *calib_prof,
uint16_t prof_len,
struct bhy2_dev *dev);
/**
* @brief Function to get the post mortem data
* @param[out] post_mortem : Reference to the data buffer to store the post mortem data
* @param[in] buffer_len : Length of the data buffer
* @param[out] actual_len : Actual length of the post mortem data
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_get_post_mortem_data(uint8_t *post_mortem, uint32_t buffer_len, uint32_t *actual_len, struct bhy2_dev *dev);
/**
* @brief Function to link a callback and relevant reference when the sensor event is available in the FIFO
* @param[in] sensor_id : Sensor ID of the virtual sensor
* @param[in] callback : Reference of the callback function
* @param[in] callback_ref : Reference needed inside the callback function. Can be NULL
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_register_fifo_parse_callback(uint8_t sensor_id,
bhy2_fifo_parse_callback_t callback,
void *callback_ref,
struct bhy2_dev *dev);
/**
* @brief Function to unlink a callback and relevant reference
* @param[in] sensor_id : Sensor ID of the virtual sensor
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_deregister_fifo_parse_callback(uint8_t sensor_id, struct bhy2_dev *dev);
/**
* @brief Function to update the callback table's information
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_update_virtual_sensor_list(struct bhy2_dev *dev);
/**
* @brief Function to get information of a virtual sensor
* @param[in] sensor_id : Sensor ID of the virtual sensor
* @param[out] info : Reference to the data buffer to store the virtual sensor information
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_get_sensor_info(uint8_t sensor_id, struct bhy2_sensor_info *info, struct bhy2_dev *dev);
/**
* @brief Function to set a parameter
* @param[in] param : Parameter ID
* @param[in] payload : Reference to the data buffer storing the parameter's payload
* @param[in] length : Length of the payload
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_set_parameter(uint16_t param, const uint8_t *payload, uint32_t length, struct bhy2_dev *dev);
/**
* @brief Function to get a parameter
* @param[in] param : Parameter ID
* @param[out] payload : Reference to the data buffer to store the parameter's payload
* @param[in] payload_len : Length of the data buffer
* @param[out] actual_len : Actual length of the payload
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_get_parameter(uint16_t param,
uint8_t *payload,
uint32_t payload_len,
uint32_t *actual_len,
struct bhy2_dev *dev);
/**
* @brief Function to get the error value register
* @param[out] error_value : Reference to the data buffer to store the error value
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_get_error_value(uint8_t *error_value, struct bhy2_dev *dev);
/**
* @brief Function to directly communicate with the sensor
* @param[in] conf : The configuration of the transfer
* @param[in] reg_addr : Register address to write to
* @param[in] length : Length of the data buffer to be transferred
* @param[in/out] reg_data : Reference to the data buffer
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_soft_passthrough_transfer(union bhy2_soft_passthrough_conf *conf,
uint8_t reg_addr,
uint8_t length,
uint8_t *reg_data,
struct bhy2_dev *dev);
/**
* @brief Function to check if a virtual sensor is available
* @param[in] sensor_id : Sensor ID of the virtual sensor
* @param[in] dev : Device reference
* @return 1 if the sensor is available. 0 otherwise
*/
uint8_t bhy2_is_sensor_available(uint8_t sensor_id, const struct bhy2_dev *dev);
/**
* @brief Function to get the BHy260 variant ID
*
* @param[in] variant_id : Reference to store the variant ID
* @param[in] dev : Device reference
* @return int8_t API error codes
*/
int8_t bhy2_get_variant_id(uint32_t *variant_id, struct bhy2_dev *dev);
/**
* @brief Function to inject data
* @param[in] payload : Reference to the data buffer
* @param[in] payload_len : Length of the data buffer
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_inject_data(const uint8_t *payload, uint32_t payload_len, struct bhy2_dev *dev);
/**
* @brief Function to set inject mode
* @param[in] mode : Type of data inject mode
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_set_data_injection_mode(enum bhy2_data_inj_mode mode, struct bhy2_dev *dev);
/**
* @brief Function to clear the FIFO
* @param[in] flush_cfg : Type of FIFO Flush
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_clear_fifo(uint8_t flush_cfg, struct bhy2_dev *dev);
/**
* @brief Function to read the status FIFO
* @param[out] status_code : Status Code
* @param[in] status_buff : Buffer for reading Status Response
* @param[in] status_len : Length of the Response
* @param[out] actual_len : Length of Data read
* @param[in] dev : Device reference
* @return API error codes
*/
int8_t bhy2_read_status(uint16_t *status_code,
uint8_t *status_buff,
uint32_t status_len,
uint32_t *actual_len,
struct bhy2_dev *dev);
/* End of CPP Guard */
#ifdef __cplusplus
}
#endif /*__cplusplus */
#endif /* __BHY2_H__ */

View File

@@ -0,0 +1,77 @@
/**
* 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 bhy2_bsec.c
* @date 2023-03-24
* @version v1.6.0
*
*/
/*********************************************************************/
/* system header files */
/*********************************************************************/
#include <string.h>
#include <stdlib.h>
/*********************************************************************/
/* BHY2 SensorAPI header files */
/*********************************************************************/
#include "bhy2.h"
/*********************************************************************/
/* own header files */
/*********************************************************************/
#include "bhy2_bsec.h"
void bhy2_bsec_parse_air_quality(const uint8_t *payload, struct bhy2_bsec_air_quality *data)
{
uint8_t i = 0;
if ((payload != NULL) && (data != NULL))
{
data->comp_temp = BHY2_LE2U32(payload + i);
i += 4;
data->comp_hum = BHY2_LE2U32(payload + i);
i += 4;
data->comp_gas = BHY2_LE2U32(payload + i);
i += 4;
data->iaq = BHY2_LE2U32(payload + i);
i += 4;
data->static_iaq = BHY2_LE2U32(payload + i);
i += 4;
data->e_co2 = BHY2_LE2U32(payload + i);
i += 4;
data->voc = BHY2_LE2U32(payload + i);
i += 4;
data->iaq_accuracy = payload[i];
}
}

View File

@@ -0,0 +1,74 @@
/**
* 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 bhy2_bsec.h
* @date 2023-03-24
* @version v1.6.0
*
*/
#ifndef _BHY2_BSEC_H_
#define _BHY2_BSEC_H_
/* Start of CPP Guard */
#ifdef __cplusplus
extern "C" {
#endif /*__cplusplus */
#include <stdint.h>
#include <stdlib.h>
#include <stdlib.h>
#include "bhy2.h"
#define BHY2_SENSOR_ID_AIR_QUALITY UINT8_C(115)
struct bhy2_bsec_air_quality
{
float comp_temp; /* Sensor heat compensated temperature (deg C) */
float comp_hum; /* Sensor heat compensated humidity (%rH) */
float comp_gas; /* Compensated gas resistance (ohms) */
float iaq; /* Indoor Air Quality index */
float static_iaq; /* Static IAQ index */
float e_co2; /* Equivalent CO2 (ppm) */
float voc; /* Volatile organic compounds (ppb) */
uint8_t iaq_accuracy; /* IAQ index accuracy (0-3) */
};
void bhy2_bsec_parse_air_quality(const uint8_t *payload, struct bhy2_bsec_air_quality *data);
/* End of CPP Guard */
#ifdef __cplusplus
}
#endif /*__cplusplus */
#endif /* _BHY2_BSEC_H_ */

View File

@@ -0,0 +1,798 @@
/**
* 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 bhy2_defs.h
* @date 2023-03-24
* @version v1.6.0
*
*/
#ifndef __BHY2_DEFS_H__
#define __BHY2_DEFS_H__
/* Start of CPP Guard */
#ifdef __cplusplus
extern "C" {
#endif /*__cplusplus */
#ifdef __KERNEL__
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/types.h>
#else
#include <string.h>
#include <stdint.h>
#endif /*~ __KERNEL__ */
#ifndef UNUSED
#define UNUSED(__x__) ((void)(__x__))
#endif /*~ UNUSED */
#ifdef __KERNEL__
#define bhy2_float u32
#else
#define bhy2_float float
#endif /*~ __KERNEL__ */
#ifdef __KERNEL__
#if !defined(UINT8_C) && !defined(INT8_C)
#define INT8_C(x) S8_C(x)
#define UINT8_C(x) U8_C(x)
#endif
#if !defined(UINT16_C) && !defined(INT16_C)
#define INT16_C(x) S16_C(x)
#define UINT16_C(x) U16_C(x)
#endif
#if !defined(INT32_C) && !defined(UINT32_C)
#define INT32_C(x) S32_C(x)
#define UINT32_C(x) U32_C(x)
#endif
#if !defined(INT64_C) && !defined(UINT64_C)
#define INT64_C(x) S64_C(x)
#define UINT64_C(x) U64_C(x)
#endif
#else /* __KERNEL__ */
#if !defined(UINT8_C) && !defined(INT8_C)
#define INT8_C(x) (x)
#define UINT8_C(x) (x##U)
#endif
#if !defined(UINT16_C) && !defined(INT16_C)
#define INT16_C(x) (x)
#define UINT16_C(x) (x##U)
#endif
#if !defined(INT32_C) && !defined(UINT32_C)
#define INT32_C(x) (x)
#define UINT32_C(x) (x##U)
#endif
#if !defined(INT64_C) && !defined(UINT64_C)
#define INT64_C(x) (x##LL)
#define UINT64_C(x) (x##ULL)
#endif
#endif /* __KERNEL__ */
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *) 0)
#endif
#endif
#ifndef BHY2_PACKED
#define BHY2_PACKED __attribute__ ((__packed__))
#endif
/** API error codes */
#define BHY2_OK INT8_C(0)
#define BHY2_E_NULL_PTR INT8_C(-1)
#define BHY2_E_INVALID_PARAM INT8_C(-2)
#define BHY2_E_IO INT8_C(-3)
#define BHY2_E_MAGIC INT8_C(-4)
#define BHY2_E_TIMEOUT INT8_C(-5)
#define BHY2_E_BUFFER INT8_C(-6)
#define BHY2_E_INVALID_FIFO_TYPE INT8_C(-7)
#define BHY2_E_INVALID_EVENT_SIZE INT8_C(-8)
#define BHY2_E_PARAM_NOT_SET INT8_C(-9)
#define BHy2_E_INSUFFICIENT_MAX_SIMUL_SENSORS INT8_C(-10)
#ifndef BHY2_COMMAND_PACKET_LEN
#define BHY2_COMMAND_PACKET_LEN UINT16_C(256)
#endif
#ifndef BHY2_COMMAND_HEADER_LEN
#define BHY2_COMMAND_HEADER_LEN UINT16_C(4)
#endif
#if (BHY2_COMMAND_PACKET_LEN < BHY2_COMMAND_HEADER_LEN)
#error "BHY2_COMMAND_PACKET_LEN should be at least 4 bytes"
#endif
#define BHY2_PRODUCT_ID UINT8_C(0x89)
/*! Register map */
#define BHY2_REG_CHAN_CMD UINT8_C(0x00)
#define BHY2_REG_CHAN_FIFO_W UINT8_C(0x01)
#define BHY2_REG_CHAN_FIFO_NW UINT8_C(0x02)
#define BHY2_REG_CHAN_STATUS UINT8_C(0x03)
#define BHY2_REG_CHIP_CTRL UINT8_C(0x05)
#define BHY2_REG_HOST_INTERFACE_CTRL UINT8_C(0x06)
#define BHY2_REG_HOST_INTERRUPT_CTRL UINT8_C(0x07)
#define BHY2_REG_RESET_REQ UINT8_C(0x14)
#define BHY2_REG_TIME_EV_REQ UINT8_C(0x15)
#define BHY2_REG_HOST_CTRL UINT8_C(0x16)
#define BHY2_REG_HOST_STATUS UINT8_C(0x17)
#define BHY2_REG_CRC_0 UINT8_C(0x18) /* Totally 4 */
#define BHY2_REG_PRODUCT_ID UINT8_C(0x1C)
#define BHY2_REG_REVISION_ID UINT8_C(0x1D)
#define BHY2_REG_ROM_VERSION_0 UINT8_C(0x1E) /* Totally 2 */
#define BHY2_REG_KERNEL_VERSION_0 UINT8_C(0x20) /* Totally 2 */
#define BHY2_REG_USER_VERSION_0 UINT8_C(0x22) /* Totally 2 */
#define BHY2_REG_FEATURE_STATUS UINT8_C(0x24)
#define BHY2_REG_BOOT_STATUS UINT8_C(0x25)
#define BHY2_REG_HOST_INTR_TIME_0 UINT8_C(0x26) /* Totally 5 */
#define BHY2_REG_CHIP_ID UINT8_C(0x2B)
#define BHY2_REG_INT_STATUS UINT8_C(0x2D)
#define BHY2_REG_ERROR_VALUE UINT8_C(0x2E)
#define BHY2_REG_ERROR_AUX UINT8_C(0x2F)
#define BHY2_REG_DEBUG_VALUE UINT8_C(0x30)
#define BHY2_REG_DEBUG_STATE UINT8_C(0x31)
#define BHY2_REG_GP_5 UINT8_C(0x32)
#define BHY2_REG_GP_6 UINT8_C(0x36)
#define BHY2_REG_GP_7 UINT8_C(0x3A)
/*! Command packets */
#define BHY2_CMD_REQ_POST_MORTEM_DATA UINT16_C(0x0001)
#define BHY2_CMD_UPLOAD_TO_PROGRAM_RAM UINT16_C(0x0002)
#define BHY2_CMD_BOOT_PROGRAM_RAM UINT16_C(0x0003)
#define BHY2_CMD_ERASE_FLASH UINT16_C(0x0004)
#define BHY2_CMD_WRITE_FLASH UINT16_C(0x0005)
#define BHY2_CMD_BOOT_FLASH UINT16_C(0x0006)
#define BHY2_CMD_SET_INJECT_MODE UINT16_C(0x0007)
#define BHY2_CMD_INJECT_DATA UINT16_C(0x0008)
#define BHY2_CMD_FIFO_FLUSH UINT16_C(0x0009)
#define BHY2_CMD_SW_PASSTHROUGH UINT16_C(0x000A)
#define BHY2_CMD_REQ_SELF_TEST UINT16_C(0x000B)
#define BHY2_CMD_REQ_FOC UINT16_C(0x000C)
#define BHY2_CMD_CONFIG_SENSOR UINT16_C(0x000D)
#define BHY2_CMD_CHANGE_RANGE UINT16_C(0x000E)
#define BHY2_CMD_FIFO_FORMAT_CTRL UINT16_C(0x0015)
/*! Soft passthrough feature */
#define BHY2_SPASS_READ UINT8_C(0)
#define BHY2_SPASS_WRITE UINT8_C(1)
#define BHY2_SPASS_SINGLE_TRANS UINT8_C(0)
#define BHY2_SPASS_MULTI_TRANS UINT8_C(1)
#define BHY2_SPASS_DELAY_DIS UINT8_C(0)
#define BHY2_SPASS_DELAY_EN UINT8_C(1)
#define BHY2_SPASS_SIF1 UINT8_C(1)
#define BHY2_SPASS_SIF2 UINT8_C(2)
#define BHY2_SPASS_SIF3 UINT8_C(3)
#define BHY2_SPASS_SPI_4_WIRE UINT8_C(0)
#define BHY2_SPASS_SPI_3_WIRE UINT8_C(1)
#define BHY2_SPASS_SPI_CPOL_0 UINT8_C(0)
#define BHY2_SPASS_SPI_CPOL_1 UINT8_C(1)
#define BHY2_SPASS_SPI_CPHA_0 UINT8_C(0)
#define BHY2_SPASS_SPI_CPHA_1 UINT8_C(1)
#define BHY2_SPASS_SPI_CS_LOW UINT8_C(0)
#define BHY2_SPASS_SPI_CS_HIGH UINT8_C(1)
#define BHY2_SPASS_SPI_LSB_FIRST_DIS UINT8_C(0)
#define BHY2_SPASS_SPI_LSB_FIRST_EN UINT8_C(1)
#define BHY2_SPASS_SPI_READ_BIT_POL_LOW UINT8_C(0)
#define BHY2_SPASS_SPI_READ_BIT_POL_HIGH UINT8_C(1)
#define BHY2_SPASS_SPI_READ_BIT_POS_0 UINT8_C(0)
#define BHY2_SPASS_SPI_READ_BIT_POS_1 UINT8_C(1)
#define BHY2_SPASS_SPI_READ_BIT_POS_2 UINT8_C(2)
#define BHY2_SPASS_SPI_READ_BIT_POS_3 UINT8_C(3)
#define BHY2_SPASS_SPI_READ_BIT_POS_4 UINT8_C(4)
#define BHY2_SPASS_SPI_READ_BIT_POS_5 UINT8_C(5)
#define BHY2_SPASS_SPI_READ_BIT_POS_6 UINT8_C(6)
#define BHY2_SPASS_SPI_READ_BIT_POS_7 UINT8_C(7)
#define BHY2_SPASS_READ_PACKET_LEN UINT8_C(0x13)
#define BHY2_SPASS_WRITE_RESP_PACKET_LEN UINT8_C(16)
/*! Helper macros */
#define BHY2_CHK_BIT(data, bit) (((uint32_t)data >> bit) & 0x01)
#define BHY2_ROUND_WORD_LOWER(x) ((x >> 2) << 2)
#define BHY2_ROUND_WORD_HIGHER(x) (((x >> 2) + 1) << 2)
#define BHY2_COUNTOF(__BUFFER__) (sizeof(__BUFFER__) / sizeof(*(__BUFFER__)))
#define BHY2_DATA_INJECT_MODE_PAYLOAD_LEN UINT8_C(0x04)
/*! Firmware header identifier */
#define BHY2_FW_MAGIC UINT16_C(0x662B)
/*! BHy260 Variant IDs */
#define BHY2_VARIANT_ID_BHA260AB UINT32_C(0x2838C2C2)
#define BHY2_VARIANT_ID_BHI260AB UINT32_C(0x266EB6E7)
#define BHY2_VARIANT_ID_BHI260AP UINT32_C(0x98D7A5D1)
/*! Boot status */
#define BHY2_BST_FLASH_DETECTED UINT8_C(0x01)
#define BHY2_BST_FLASH_VERIFY_DONE UINT8_C(0x02)
#define BHY2_BST_FLASH_VERIFY_ERROR UINT8_C(0x04)
#define BHY2_BST_NO_FLASH UINT8_C(0x08)
#define BHY2_BST_HOST_INTERFACE_READY UINT8_C(0x10)
#define BHY2_BST_HOST_FW_VERIFY_DONE UINT8_C(0x20)
#define BHY2_BST_HOST_FW_VERIFY_ERROR UINT8_C(0x40)
#define BHY2_BST_HOST_FW_IDLE UINT8_C(0x80)
#define BHY2_BST_CHECK_RETRY UINT8_C(100)
/*! Host status */
#define BHY2_HST_POWER_STATE UINT8_C(0x01)
#define BHY2_HST_HOST_PROTOCOL UINT8_C(0x02)
#define BHY2_HST_HOST_CHANNEL_0 UINT8_C(0x10)
#define BHY2_HST_HOST_CHANNEL_1 UINT8_C(0x20)
#define BHY2_HST_HOST_CHANNEL_2 UINT8_C(0x40)
#define BHY2_HST_HOST_CHANNEL_3 UINT8_C(0x80)
/*! Interrupt status masks */
#define BHY2_IST_MASK_ASSERTED (0x1)
#define BHY2_IST_MASK_FIFO_W (0x6)
#define BHY2_IST_MASK_FIFO_NW (0x18)
#define BHY2_IST_MASK_STATUS (0x20)
#define BHY2_IST_MASK_DEBUG (0x40)
#define BHY2_IST_MASK_RESET_FAULT (0x80)
#define BHY2_IST_FIFO_W_DRDY UINT8_C(0x2)
#define BHY2_IST_FIFO_W_LTCY UINT8_C(0x4)
#define BHY2_IST_FIFO_W_WM UINT8_C(0x6)
#define BHY2_IST_FIFO_NW_DRDY UINT8_C(0x8)
#define BHY2_IST_FIFO_NW_LTCY UINT8_C(0x10)
#define BHY2_IST_FIFO_NW_WM UINT8_C(0x18)
#define BHY2_IS_INT_FIFO_W(status) (status & BHY2_IST_MASK_FIFO_W)
#define BHY2_IS_INT_FIFO_NW(status) (status & BHY2_IST_MASK_FIFO_NW)
#define BHY2_IS_INT_STATUS(status) (status & BHY2_IST_MASK_STATUS)
#define BHY2_IS_INT_ASYNC_STATUS(status) (status & BHY2_IST_MASK_DEBUG)
#define BHY2_IS_INT_RESET(status) (status & BHY2_IST_MASK_RESET_FAULT)
#define BHY2_IST_MASK_FIFO (BHY2_IST_MASK_FIFO_W | BHY2_IST_MASK_FIFO_NW)
#define BHY2_IS_INT_FIFO(status) (status & BHY2_IST_MASK_FIFO)
/*! Chip control bits */
#define BHY2_CHIP_CTRL_DISABLE UINT8_C(0x00)
#define BHY2_CHIP_CTRL_TURBO_ENABLE UINT8_C(0x01)
#define BHY2_CHIP_CTRL_CLR_ERR_REG UINT8_C(0x02)
/*! Host interface control bits */
#define BHY2_HIF_CTRL_ABORT_TRANSFER_CHANNEL_0 UINT8_C(0x01)
#define BHY2_HIF_CTRL_ABORT_TRANSFER_CHANNEL_1 UINT8_C(0x02)
#define BHY2_HIF_CTRL_ABORT_TRANSFER_CHANNEL_2 UINT8_C(0x04)
#define BHY2_HIF_CTRL_ABORT_TRANSFER_CHANNEL_3 UINT8_C(0x08)
#define BHY2_HIF_CTRL_AP_SUSPENDED UINT8_C(0x10)
#define BHY2_HIF_CTRL_TIMESTAMP_EV_CTRL UINT8_C(0x40)
#define BHY2_HIF_CTRL_ASYNC_STATUS_CHANNEL UINT8_C(0x80)
/*! Interrupt control bits */
#define BHY2_ICTL_DISABLE_FIFO_W UINT8_C(0x01)
#define BHY2_ICTL_DISABLE_FIFO_NW UINT8_C(0x02)
#define BHY2_ICTL_DISABLE_STATUS_FIFO UINT8_C(0x04)
#define BHY2_ICTL_DISABLE_DEBUG UINT8_C(0x08)
#define BHY2_ICTL_DISABLE_FAULT UINT8_C(0x10)
#define BHY2_ICTL_ACTIVE_LOW UINT8_C(0x20)
#define BHY2_ICTL_EDGE UINT8_C(0x40)
#define BHY2_ICTL_OPEN_DRAIN UINT8_C(0x80)
/*! Reset command */
#define BHY2_REQUEST_RESET UINT8_C(0x01)
/*! FIFO Format bit */
#define BHY2_FIFO_FORMAT_CTRL_MASK UINT8_C(0x03)
#define BHY2_FIFO_FORMAT_CTRL_DIS_DELTA_TS UINT8_C(0x01)
#define BHY2_FIFO_FORMAT_CTRL_DIS_FULL_TS UINT8_C(0x02)
#define BHY2_FIFO_FORMAT_CTRL_DIS_ALL_TS UINT8_C(0x03)
/*! System parameters */
#define BHY2_PARAM_READ_MASK UINT16_C(0x1000)
#define BHY2_PARAM_FIFO_CTRL UINT16_C(0x103)
#define BHY2_PARAM_SYS_VIRT_SENSOR_PRESENT UINT16_C(0x11F)
#define BHY2_PARAM_SYS_PHYS_SENSOR_PRESENT UINT16_C(0x120)
#define BHY2_PARAM_PHYSICAL_SENSOR_BASE UINT16_C(0x120)
#define BHY2_PARAM_BSX_CALIB_STATE_BASE UINT16_C(0x200)
#define BHY2_PARAM_BSX_CALIB_STATE_ACCEL UINT16_C(0x201)
#define BHY2_PARAM_BSX_CALIB_STATE_GYRO UINT16_C(0x203)
#define BHY2_PARAM_BSX_CALIB_STATE_MAG UINT16_C(0x205)
#define BHY2_PARAM_BSX_SIC UINT16_C(0x27D)
#define BHY2_PARAM_BSX_VERSION UINT16_C(0x27E)
#define BHY2_PARAM_SET_SENSOR_CTRL UINT16_C(0x0E00)
#define BHY2_PARAM_GET_SENSOR_CTRL UINT16_C(0x1E00)
#define BHY2_PARAM_SENSOR_CTRL_FOC UINT8_C(0x1)
#define BHY2_PARAM_SENSOR_CTRL_OIS UINT8_C(0x2)
#define BHY2_PARAM_SENSOR_CTRL_FST UINT8_C(0x3)
#define BHY2_PARAM_SENSOR_CTRL_READ UINT8_C(0x80)
#define BHY2_PARAM_SENSOR_INFO_0 UINT16_C(0x300)
#define BHY2_PARAM_SENSOR_CONF_0 UINT16_C(0x500)
#define BHY2_BSX_STATE_TRANSFER_COMPLETE UINT8_C(0x80)
#define BHY2_BSX_STATE_BLOCK_NUM_MSK UINT8_C(0x7F)
#define BHY2_BSX_STATE_BLOCK_LEN UINT8_C(64)
#define BHY2_BSX_STATE_STRUCT_LEN UINT8_C(68)
#define BHY2_QUERY_PARAM_STATUS_READY_MAX_RETRY UINT16_C(1000)
#define BHY2_QUERY_FLASH_MAX_RETRY UINT16_C(1200)
/*! Meta event definitions */
#define BHY2_META_EVENT_FLUSH_COMPLETE (1)
#define BHY2_META_EVENT_SAMPLE_RATE_CHANGED (2)
#define BHY2_META_EVENT_POWER_MODE_CHANGED (3)
#define BHY2_META_EVENT_ALGORITHM_EVENTS (5)
#define BHY2_META_EVENT_SENSOR_STATUS (6)
#define BHY2_META_EVENT_BSX_DO_STEPS_MAIN (7)
#define BHY2_META_EVENT_BSX_DO_STEPS_CALIB (8)
#define BHY2_META_EVENT_BSX_GET_OUTPUT_SIGNAL (9)
#define BHY2_META_EVENT_RESERVED1 (10)
#define BHY2_META_EVENT_SENSOR_ERROR (11)
#define BHY2_META_EVENT_FIFO_OVERFLOW (12)
#define BHY2_META_EVENT_DYNAMIC_RANGE_CHANGED (13)
#define BHY2_META_EVENT_FIFO_WATERMARK (14)
#define BHY2_META_EVENT_RESERVED2 (15)
#define BHY2_META_EVENT_INITIALIZED (16)
#define BHY2_META_TRANSFER_CAUSE (17)
#define BHY2_META_EVENT_SENSOR_FRAMEWORK (18)
#define BHY2_META_EVENT_RESET (19)
#define BHY2_META_EVENT_SPACER (20)
/* Flash start address in memory */
#define BHY2_FLASH_SECTOR_START_ADDR UINT32_C(0x1F84)
#define BHY2_FLASH_BULK_ERASE UINT32_C(0xFFFFFFFF)
/* End address for common flash sizes */
#define BHY2_FLASH_SIZE_0_5MB UINT32_C(0x7FFFF)
#define BHY2_FLASH_SIZE_1MB UINT32_C(0xFFFFF)
#define BHY2_FLASH_SIZE_2MB UINT32_C(0x1FFFFF)
#define BHY2_FLASH_SIZE_4MB UINT32_C(0x3FFFFF)
#define BHY2_FLASH_SIZE_8MB UINT32_C(0x7FFFFF)
/* Sensor IDs */
#define BHY2_SENSOR_ID_CUSTOM_START UINT8_C(160)
#define BHY2_SENSOR_ID_CUSTOM_END UINT8_C(191)
#define BHY2_SENSOR_ID_MAX UINT8_C(200)
#define BHY2_SENSOR_ID_TBD UINT8_C(BHY2_SENSOR_ID_MAX - 1)
/* Virtual Sensor IDs */
#define BHY2_SENSOR_ID_ACC_PASS UINT8_C(1) /* Accelerometer passthrough */
#define BHY2_SENSOR_ID_ACC_RAW UINT8_C(3) /* Accelerometer uncalibrated */
#define BHY2_SENSOR_ID_ACC UINT8_C(4) /* Accelerometer corrected */
#define BHY2_SENSOR_ID_ACC_BIAS UINT8_C(5) /* Accelerometer offset */
#define BHY2_SENSOR_ID_ACC_WU UINT8_C(6) /* Accelerometer corrected wake up */
#define BHY2_SENSOR_ID_ACC_RAW_WU UINT8_C(7) /* Accelerometer uncalibrated wake up */
#define BHY2_SENSOR_ID_SI_ACCEL UINT8_C(8) /* Virtual Sensor ID for Accelerometer */
#define BHY2_SENSOR_ID_GYRO_PASS UINT8_C(10) /* Gyroscope passthrough */
#define BHY2_SENSOR_ID_GYRO_RAW UINT8_C(12) /* Gyroscope uncalibrated */
#define BHY2_SENSOR_ID_GYRO UINT8_C(13) /* Gyroscope corrected */
#define BHY2_SENSOR_ID_GYRO_BIAS UINT8_C(14) /* Gyroscope offset */
#define BHY2_SENSOR_ID_GYRO_WU UINT8_C(15) /* Gyroscope wake up */
#define BHY2_SENSOR_ID_GYRO_RAW_WU UINT8_C(16) /* Gyroscope uncalibrated wake up */
#define BHY2_SENSOR_ID_SI_GYROS UINT8_C(17) /* Virtual Sensor ID for Gyroscope */
#define BHY2_SENSOR_ID_MAG_PASS UINT8_C(19) /* Magnetometer passthrough */
#define BHY2_SENSOR_ID_MAG_RAW UINT8_C(21) /* Magnetometer uncalibrated */
#define BHY2_SENSOR_ID_MAG UINT8_C(22) /* Magnetometer corrected */
#define BHY2_SENSOR_ID_MAG_BIAS UINT8_C(23) /* Magnetometer offset */
#define BHY2_SENSOR_ID_MAG_WU UINT8_C(24) /* Magnetometer wake up */
#define BHY2_SENSOR_ID_MAG_RAW_WU UINT8_C(25) /* Magnetometer uncalibrated wake up */
#define BHY2_SENSOR_ID_GRA UINT8_C(28) /* Gravity vector */
#define BHY2_SENSOR_ID_GRA_WU UINT8_C(29) /* Gravity vector wake up */
#define BHY2_SENSOR_ID_LACC UINT8_C(31) /* Linear acceleration */
#define BHY2_SENSOR_ID_LACC_WU UINT8_C(32) /* Linear acceleration wake up */
#define BHY2_SENSOR_ID_RV UINT8_C(34) /* Rotation vector */
#define BHY2_SENSOR_ID_RV_WU UINT8_C(35) /* Rotation vector wake up */
#define BHY2_SENSOR_ID_GAMERV UINT8_C(37) /* Game rotation vector */
#define BHY2_SENSOR_ID_GAMERV_WU UINT8_C(38) /* Game rotation vector wake up */
#define BHY2_SENSOR_ID_GEORV UINT8_C(40) /* Geo-magnetic rotation vector */
#define BHY2_SENSOR_ID_GEORV_WU UINT8_C(41) /* Geo-magnetic rotation vector wake up */
#define BHY2_SENSOR_ID_ORI UINT8_C(43) /* Orientation */
#define BHY2_SENSOR_ID_ORI_WU UINT8_C(44) /* Orientation wake up */
#define BHY2_SENSOR_ID_TILT_DETECTOR UINT8_C(48) /* Tilt detector */
#define BHY2_SENSOR_ID_STD UINT8_C(50) /* Step detector */
#define BHY2_SENSOR_ID_STC UINT8_C(52) /* Step counter */
#define BHY2_SENSOR_ID_STC_WU UINT8_C(53) /* Step counter wake up */
#define BHY2_SENSOR_ID_SIG UINT8_C(55) /* Significant motion */
#define BHY2_SENSOR_ID_WAKE_GESTURE UINT8_C(57) /* Wake gesture */
#define BHY2_SENSOR_ID_GLANCE_GESTURE UINT8_C(59) /* Glance gesture */
#define BHY2_SENSOR_ID_PICKUP_GESTURE UINT8_C(61) /* Pickup gesture */
#define BHY2_SENSOR_ID_AR UINT8_C(63) /* Activity recognition */
#define BHY2_SENSOR_ID_WRIST_TILT_GESTURE UINT8_C(67) /* Wrist tilt gesture */
#define BHY2_SENSOR_ID_DEVICE_ORI UINT8_C(69) /* Device orientation */
#define BHY2_SENSOR_ID_DEVICE_ORI_WU UINT8_C(70) /* Device orientation wake up */
#define BHY2_SENSOR_ID_STATIONARY_DET UINT8_C(75) /* Stationary detect */
#define BHY2_SENSOR_ID_MOTION_DET UINT8_C(77) /* Motion detect */
#define BHY2_SENSOR_ID_ACC_BIAS_WU UINT8_C(91) /* Accelerometer offset wake up */
#define BHY2_SENSOR_ID_GYRO_BIAS_WU UINT8_C(92) /* Gyroscope offset wake up */
#define BHY2_SENSOR_ID_MAG_BIAS_WU UINT8_C(93) /* Magnetometer offset wake up */
#define BHY2_SENSOR_ID_STD_WU UINT8_C(94) /* Step detector wake up */
#define BHY2_SENSOR_ID_TEMP UINT8_C(128) /* Temperature */
#define BHY2_SENSOR_ID_BARO UINT8_C(129) /* Barometer */
#define BHY2_SENSOR_ID_HUM UINT8_C(130) /* Humidity */
#define BHY2_SENSOR_ID_GAS UINT8_C(131) /* Gas */
#define BHY2_SENSOR_ID_TEMP_WU UINT8_C(132) /* Temperature wake up */
#define BHY2_SENSOR_ID_BARO_WU UINT8_C(133) /* Barometer wake up */
#define BHY2_SENSOR_ID_HUM_WU UINT8_C(134) /* Humidity wake up */
#define BHY2_SENSOR_ID_GAS_WU UINT8_C(135) /* Gas wake up */
#define BHY2_SENSOR_ID_STC_LP UINT8_C(136) /* Step counter Low Power */
#define BHY2_SENSOR_ID_STD_LP UINT8_C(137) /* Step detector Low Power */
#define BHY2_SENSOR_ID_SIG_LP UINT8_C(138) /* Significant motion Low Power */
#define BHY2_SENSOR_ID_STC_LP_WU UINT8_C(139) /* Step counter Low Power wake up */
#define BHY2_SENSOR_ID_STD_LP_WU UINT8_C(140) /* Step detector Low Power wake up */
#define BHY2_SENSOR_ID_SIG_LP_WU UINT8_C(141) /* Significant motion Low Power wake up */
#define BHY2_SENSOR_ID_ANY_MOTION_LP UINT8_C(142) /* Any motion Low Power */
#define BHY2_SENSOR_ID_ANY_MOTION_LP_WU UINT8_C(143) /* Any motion Low Power wake up */
#define BHY2_SENSOR_ID_EXCAMERA UINT8_C(144) /* External camera trigger */
#define BHY2_SENSOR_ID_GPS UINT8_C(145) /* GPS */
#define BHY2_SENSOR_ID_LIGHT UINT8_C(146) /* Light */
#define BHY2_SENSOR_ID_PROX UINT8_C(147) /* Proximity */
#define BHY2_SENSOR_ID_LIGHT_WU UINT8_C(148) /* Light wake up */
#define BHY2_SENSOR_ID_PROX_WU UINT8_C(149) /* Proximity wake up */
#define BHY2_SENSOR_ID_GPIO_EXP UINT8_C(151) /* Custom GPIO ID, only valid for custom firmware*/
/*! Physical sensor IDs*/
#define BHY2_PHYS_SENSOR_ID_ACCELEROMETER UINT8_C(1)
#define BHY2_PHYS_SENSOR_ID_GYROSCOPE UINT8_C(3)
#define BHY2_PHYS_SENSOR_ID_MAGNETOMETER UINT8_C(5)
#define BHY2_PHYS_SENSOR_ID_TEMP_GYRO UINT8_C(7)
#define BHY2_PHYS_SENSOR_ID_ANY_MOTION UINT8_C(9)
#define BHY2_PHYS_SENSOR_ID_PRESSURE UINT8_C(11)
#define BHY2_PHYS_SENSOR_ID_POSITION UINT8_C(13)
#define BHY2_PHYS_SENSOR_ID_HUMIDITY UINT8_C(15)
#define BHY2_PHYS_SENSOR_ID_TEMPERATURE UINT8_C(17)
#define BHY2_PHYS_SENSOR_ID_GAS_RESISTOR UINT8_C(19)
#define BHY2_PHYS_SENSOR_ID_PHYS_STEP_COUNTER UINT8_C(32)
#define BHY2_PHYS_SENSOR_ID_PHYS_STEP_DETECTOR UINT8_C(33)
#define BHY2_PHYS_SENSOR_ID_PHYS_SIGN_MOTION UINT8_C(34)
#define BHY2_PHYS_SENSOR_ID_PHYS_ANY_MOTION UINT8_C(35)
#define BHY2_PHYS_SENSOR_ID_EX_CAMERA_INPUT UINT8_C(36)
#define BHY2_PHYS_SENSOR_ID_GPS UINT8_C(48)
#define BHY2_PHYS_SENSOR_ID_LIGHT UINT8_C(49)
#define BHY2_PHYS_SENSOR_ID_PROXIMITY UINT8_C(50)
#define BHY2_PHYS_SENSOR_ID_PHYS_NO_MOTION UINT8_C(55)
#define BHY2_PHYS_SENSOR_ID_WRIST_GESTURE_DETECT UINT8_C(56)
#define BHY2_PHYS_SENSOR_ID_WRIST_WEAR_WAKEUP UINT8_C(57)
/*! System data IDs */
#define BHY2_IS_SYS_ID(sid) ((sid) >= 224)
#define BHY2_SYS_ID_PADDING UINT8_C(0)
#define BHY2_SYS_ID_TS_SMALL_DELTA UINT8_C(251)
#define BHY2_SYS_ID_TS_LARGE_DELTA UINT8_C(252)
#define BHY2_SYS_ID_TS_FULL UINT8_C(253)
#define BHY2_SYS_ID_META_EVENT UINT8_C(254)
#define BHY2_SYS_ID_TS_SMALL_DELTA_WU UINT8_C(245)
#define BHY2_SYS_ID_TS_LARGE_DELTA_WU UINT8_C(246)
#define BHY2_SYS_ID_TS_FULL_WU UINT8_C(247)
#define BHY2_SYS_ID_META_EVENT_WU UINT8_C(248)
#define BHY2_SYS_ID_FILLER UINT8_C(255)
#define BHY2_SYS_ID_DEBUG_MSG UINT8_C(250)
#define BHY2_SYS_ID_BHY2_LOG_UPDATE_SUB UINT8_C(243)
#define BHY2_SYS_ID_BHY2_LOG_DOSTEP UINT8_C(244)
/*! Status code definitions */
#define BHY2_STATUS_INITIALIZED UINT8_C(0x1)
#define BHY2_STATUS_DEBUG_OUTPUT UINT8_C(0x2)
#define BHY2_STATUS_CRASH_DUMP UINT8_C(0x3)
#define BHY2_STATUS_INJECT_SENSOR_CONF_REQ UINT8_C(0x4)
#define BHY2_STATUS_SW_PASS_THRU_RES UINT8_C(0x5)
#define BHY2_STATUS_SELF_TEST_RES UINT8_C(0x6)
#define BHY2_STATUS_FOC_RES UINT8_C(0x7)
#define BHY2_STATUS_SYSTEM_ERROR UINT8_C(0x8)
#define BHY2_STATUS_SENSOR_ERROR UINT8_C(0x9)
#define BHY2_STATUS_FLASH_ERASE_COMPLETE UINT8_C(0xA)
#define BHY2_STATUS_FLASH_WRITE_COMPLETE UINT8_C(0xB)
#define BHY2_STATUS_FLASH_CONTINUE_UPLOAD UINT8_C(0xC)
#define BHY2_STATUS_HOST_EV_TIMESTAMP UINT8_C(0xD)
#define BHY2_STATUS_DUT_TEST_RES UINT8_C(0xE)
#define BHY2_STATUS_CMD_ERR UINT8_C(0xF)
#define BHY2_IS_STATUS_GET_PARAM_OUTPUT(status) ((status) >= 0x100 && (status) <= 0xFFF)
/*! Activity bits */
#define BHY2_STILL_ACTIVITY_ENDED (0x0001)
#define BHY2_WALKING_ACTIVITY_ENDED (0x0002)
#define BHY2_RUNNING_ACTIVITY_ENDED (0x0004)
#define BHY2_ON_BICYCLE_ACTIVITY_ENDED (0x0008)
#define BHY2_IN_VEHICLE_ACTIVITY_ENDED (0x0010)
#define BHY2_TILTING_ACTIVITY_ENDED (0x0020)
#define BHY2_STILL_ACTIVITY_STARTED (0x0100)
#define BHY2_WALKING_ACTIVITY_STARTED (0x0200)
#define BHY2_RUNNING_ACTIVITY_STARTED (0x0400)
#define BHY2_ON_BICYCLE_ACTIVITY_STARTED (0x0800)
#define BHY2_IN_VEHICLE_ACTIVITY_STARTED (0x1000)
#define BHY2_TILTING_ACTIVITY_STARTED (0x2000)
/*! Custom firmware gpio control command*/
#define BHY2_INPUT (0x0)
#define BHY2_OUTPUT (0x1)
#define BHY2_INPUT_PULLUP (0x2)
#define BHY2_OPEN_DRAIN (0x3)
#define BHY2_GPIO_SET (0x80)
/*! Feature status */
#define BHY2_FEAT_STATUS_FLASH_DESC_MSK UINT8_C(0x01)
#define BHY2_FEAT_STATUS_OPEN_RTOS_MSK UINT8_C(0x02)
#define BHY2_FEAT_STATUS_OPEN_RTOS_POS (1)
#define BHY2_FEAT_STATUS_HOST_ID_MSK UINT8_C(0x1C)
#define BHY2_FEAT_STATUS_HOST_ID_POS (2)
#define BHY2_FEAT_STATUS_ALGO_ID_MSK UINT8_C(0xE0)
#define BHY2_FEAT_STATUS_ALGO_ID_POS (5)
/*! Fast offset compensation status codes */
#define BHY2_FOC_PASS UINT8_C(0x00)
#define BHY2_FOC_FAILED UINT8_C(0x65)
#define BHY2_FOC_UNKNOWN_FAILURE UINT8_C(0x23)
/*! Self test status codes */
#define BHY2_ST_PASSED UINT8_C(0x00)
#define BHY2_ST_X_AXIS_FAILED UINT8_C(0x01)
#define BHY2_ST_Y_AXIS_FAILED UINT8_C(0x02)
#define BHY2_ST_Z_AXIS_FAILED UINT8_C(0x04)
#define BHY2_ST_MULTI_AXIS_FAILURE UINT8_C(0x07)
#define BHY2_ST_NOT_SUPPORTED UINT8_C(0x08)
#define BHY2_ST_INVALID_PHYS_ID UINT8_C(0x09)
#define BHY2_LE2U16(x) ((uint16_t)((x)[0] | (x)[1] << 8))
#define BHY2_LE2S16(x) ((int16_t)BHY2_LE2U16(x))
#define BHY2_LE2U24(x) ((uint32_t)((x)[0] | (uint32_t)(x)[1] << 8 | (uint32_t)(x)[2] << 16))
#define BHY2_LE2S24(x) ((int32_t)(BHY2_LE2U24(x) << 8) >> 8)
#define BHY2_LE2U32(x) ((uint32_t)((x)[0] | (uint32_t)(x)[1] << 8 | (uint32_t)(x)[2] << 16 | \
(uint32_t)(x)[3] << 24))
#define BHY2_LE2S32(x) ((int32_t)BHY2_LE2U32(x))
#define BHY2_LE2U40(x) (BHY2_LE2U32(x) | (uint64_t)(x)[4] << 32)
#define BHY2_LE2U64(x) (BHY2_LE2U32(x) | (uint64_t)BHY2_LE2U32(&(x)[4]) << 32)
#define BHY2_LE24MUL(x) (((x) % 4) ? (uint16_t)((((x) / 4) + 1) * 4) : (uint16_t)((x) + 4))
/*! Maximum no of available virtual sensor */
#define BHY2_N_VIRTUAL_SENSOR_MAX UINT8_C(256)
#ifndef BHY2_MAX_SIMUL_SENSORS
#define BHY2_MAX_SIMUL_SENSORS 48
#endif
/* Special & debug virtual sensor id starts at 245 */
#define BHY2_SPECIAL_SENSOR_ID_OFFSET UINT8_C(245)
#ifndef BHY2_INTF_RET_TYPE
#define BHY2_INTF_RET_TYPE int8_t
#endif
#ifndef BHY2_INTF_RET_SUCCESS
#define BHY2_INTF_RET_SUCCESS 0
#endif
/* Type definitions for the function pointers */
typedef BHY2_INTF_RET_TYPE (*bhy2_read_fptr_t)(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr);
typedef BHY2_INTF_RET_TYPE (*bhy2_write_fptr_t)(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length,
void *intf_ptr);
typedef void (*bhy2_delay_us_fptr_t)(uint32_t period_us, void *intf_ptr);
typedef void (*bhy2_progress_callback)(void *user_data, uint32_t total, uint32_t transferred);
enum bhy2_intf {
BHY2_SPI_INTERFACE = 1,
BHY2_I2C_INTERFACE
};
/* HIF device structure */
struct bhy2_hif_dev {
bhy2_read_fptr_t read;
bhy2_write_fptr_t write;
bhy2_delay_us_fptr_t delay_us;
enum bhy2_intf intf;
void *intf_ptr;
BHY2_INTF_RET_TYPE intf_rslt;
uint32_t read_write_len;
};
enum bhy2_fifo_type {
BHY2_FIFO_TYPE_WAKEUP,
BHY2_FIFO_TYPE_NON_WAKEUP,
BHY2_FIFO_TYPE_STATUS,
BHY2_FIFO_TYPE_MAX
};
struct BHY2_PACKED bhy2_fifo_parse_data_info {
uint8_t sensor_id;
enum bhy2_fifo_type fifo_type;
uint8_t data_size;
uint8_t *data_ptr;
uint64_t *time_stamp;
};
typedef void (*bhy2_fifo_parse_callback_t)(const struct bhy2_fifo_parse_data_info *callback_info, void *private_data);
struct BHY2_PACKED bhy2_fifo_parse_callback_table {
uint8_t sensor_id;
bhy2_fifo_parse_callback_t callback;
void *callback_ref;
};
/* Device structure */
struct bhy2_dev {
struct bhy2_hif_dev hif;
struct bhy2_fifo_parse_callback_table table[BHY2_MAX_SIMUL_SENSORS];
uint8_t event_size[BHY2_N_VIRTUAL_SENSOR_MAX];
uint64_t last_time_stamp[BHY2_FIFO_TYPE_MAX];
uint8_t present_buff[32];
};
struct bhy2_fifo_buffer {
uint32_t read_pos;
uint32_t read_length;
uint32_t remain_length;
uint32_t buffer_size;
uint8_t *buffer;
};
typedef int16_t (*bhy2_frame_parse_func_t)(struct bhy2_fifo_buffer *p_fifo_buffer, struct bhy2_dev *bhy2_p);
struct bhy2_virt_sensor_conf {
uint16_t sensitivity;
uint16_t range;
uint32_t latency;
bhy2_float sample_rate;
};
struct bhy2_data_xyz {
int16_t x;
int16_t y;
int16_t z;
};
struct bhy2_data_quaternion {
int16_t x;
int16_t y;
int16_t z;
int16_t w;
uint16_t accuracy;
};
struct bhy2_data_orientation {
int16_t heading;
int16_t pitch;
int16_t roll;
};
union BHY2_PACKED bhy2_spt_dev_id {
uint8_t slave_address;
uint8_t cs_pin;
};
struct BHY2_PACKED bhy2_spt_bits {
/*! byte 1 */
uint8_t direction : 1; /**< 0: read; 1: write. */
uint8_t trans_type : 1; /**< 0: single burst; 1:multi single transfers. */
uint8_t delay_ctrl : 1; /**< 0: none; 1: delay between bytes. */
uint8_t master_bus : 2; /**< 1: SIF1; 2: SIF2; 3:SIF3. */
uint8_t spi_mode : 1; /**< 0: 4 wire; 1: 3 wire. */
uint8_t cpol : 1; /**< spi clock polarity. */
uint8_t cpha : 1; /**< spi clock phase. */
/*! byte 2 */
uint8_t delay_val : 6; /**< multiples of 50us. min is 200us (4LSB) */
uint8_t cs_level : 1; /**< chip select level. */
uint8_t lsb_first : 1; /**< least significant byte first. */
/*! byte 3~4 */
uint16_t trans_rate; /**< spi clock rate. */
/*! byte 5 */
uint8_t address_shift : 4; /**< number of bits to shift register address. */
uint8_t read_bit_pol : 1; /**< 0: active low; 1: active high. */
uint8_t read_bit_pos : 3; /**< bit number of read bit in command byte. */
/*! byte 6 */
union bhy2_spt_dev_id func_set;
/*! byte 7 */
uint8_t trans_count;
/*! byte 8 */
uint8_t reg;
};
union bhy2_soft_passthrough_conf {
struct bhy2_spt_bits conf;
uint8_t data[8];
};
union bhy2_u16_conv {
uint16_t u16_val;
uint8_t bytes[2];
};
union bhy2_u32_conv {
uint32_t u32_val;
uint8_t bytes[4];
};
union bhy2_float_conv {
bhy2_float f_val;
uint32_t u32_val;
uint8_t bytes[4];
};
struct bhy2_sensor_info {
uint8_t sensor_type;
uint8_t driver_id;
uint8_t driver_version;
uint8_t power;
union bhy2_u16_conv max_range;
union bhy2_u16_conv resolution;
union bhy2_float_conv max_rate;
union bhy2_u32_conv fifo_reserved;
union bhy2_u32_conv fifo_max;
uint8_t event_size;
union bhy2_float_conv min_rate;
};
struct bhy2_phys_sensor_info {
uint8_t sensor_type;
uint8_t driver_id;
uint8_t driver_version;
uint8_t power_current;
union bhy2_u16_conv curr_range;
uint8_t flags;
uint8_t slave_address;
uint8_t gpio_assignment;
union bhy2_float_conv curr_rate;
uint8_t num_axis;
uint8_t orientation_matrix[5];
uint8_t reserved;
};
struct bhy2_self_test_resp {
uint8_t test_status;
int16_t x_offset, y_offset, z_offset;
};
struct bhy2_foc_resp {
uint8_t foc_status;
int16_t x_offset, y_offset, z_offset;
};
struct bhy2_orient_matrix {
int8_t c[9];
};
enum bhy2_data_inj_mode {
BHY2_NORMAL_MODE = 0,
BHY2_REAL_TIME_INJECTION = 1,
BHY2_STEP_BY_STEP_INJECTION = 2
};
#define BHY2_BYTE_TO_NIBBLE(X) (((uint8_t)(X)[0] & 0x0F) | (((uint8_t)(X)[1] << 4) & 0xF0))
/* End of CPP Guard */
#ifdef __cplusplus
}
#endif /*__cplusplus */
#endif /* __BHY2_DEFS_H__ */

View File

@@ -0,0 +1,353 @@
/**
* 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 bhy2_head_tracker.c
* @date 2023-03-24
* @version v1.6.0
*
*/
/*********************************************************************/
/* system header files */
/*********************************************************************/
#include <string.h>
#include <stdlib.h>
/*********************************************************************/
/* BHY2 SensorAPI header files */
/*********************************************************************/
#include "bhy2.h"
/*********************************************************************/
/* own header files */
/*********************************************************************/
#include "bhy2_head_tracker.h"
/*Parsing callback for Head Orientation Quaternion*/
void bhy2_head_tracker_quat_parsing(const uint8_t *payload, struct bhy2_head_tracker_quat_data *data)
{
uint8_t i = 0;
if ((payload != NULL) && (data != NULL))
{
data->x = BHY2_LE2S16(&payload[i]);
i += 2;
data->y = BHY2_LE2S16(&payload[i]);
i += 2;
data->z = BHY2_LE2S16(&payload[i]);
i += 2;
data->w = BHY2_LE2S16(&payload[i]);
i += 2;
data->accuracy = payload[i];
}
}
/*Parsing callback for Head Orientation Euler*/
void bhy2_head_tracker_eul_parsing(const uint8_t *payload, struct bhy2_head_tracker_eul_data *data)
{
uint8_t i = 0;
if ((payload != NULL) && (data != NULL))
{
data->heading = BHY2_LE2S16(&payload[i]);
i += 2;
data->pitch = BHY2_LE2S16(&payload[i]);
i += 2;
data->roll = BHY2_LE2S16(&payload[i]);
i += 2;
data->accuracy = payload[i];
}
}
/*Callback for triggering Head Misalignment Calibration*/
int8_t bhy2_head_tracker_trigger_hmc_calibration(const void *buffer, struct bhy2_dev *dev)
{
int8_t rslt = BHY2_OK;
if (dev == NULL)
{
rslt = BHY2_E_NULL_PTR;
}
else
{
/*! Trigger Head Misalignment Calibration */
rslt = bhy2_set_parameter(BHY2_HEAD_ORI_PARAM(BHY2_HEAD_ORI_HMC_TRIGGER_CALIB),
(uint8_t*)buffer,
BHY2_HEAD_ORI_HMC_TRIGGER_CALIB_LENGTH,
dev);
}
return rslt;
}
/*Callback for setting Head Misalignment Calibration Configuration*/
int8_t bhy2_head_tracker_set_hmc_configuration(const void *buffer, struct bhy2_dev *dev)
{
int8_t rslt = BHY2_OK;
if (dev == NULL)
{
rslt = BHY2_E_NULL_PTR;
}
else
{
/*! Set Head Misalignment Configuration */
rslt = bhy2_set_parameter(BHY2_HEAD_ORI_PARAM(BHY2_HEAD_ORI_HMC_CONFIG),
(uint8_t*)buffer,
BHY2_HEAD_ORI_HMC_CONFIG_LENGTH,
dev);
}
return rslt;
}
/*Callback for getting Head Misalignment Calibration Configuration*/
int8_t bhy2_head_tracker_get_hmc_configuration(const void *buffer, struct bhy2_dev *dev)
{
int8_t rslt = BHY2_OK;
uint32_t act_len;
if (dev == NULL)
{
rslt = BHY2_E_NULL_PTR;
}
else
{
/*! Get Head Misalignment Configuration */
rslt = bhy2_get_parameter(BHY2_HEAD_ORI_PARAM(BHY2_HEAD_ORI_HMC_CONFIG),
(uint8_t*)buffer,
BHY2_HEAD_ORI_HMC_CONFIG_LENGTH,
&act_len,
dev);
}
return rslt;
}
/*Callback for setting default Head Misalignment Calibration Configuration*/
int8_t bhy2_head_tracker_set_default_hmc_configuration(const void *buffer, struct bhy2_dev *dev)
{
int8_t rslt = BHY2_OK;
if (dev == NULL)
{
rslt = BHY2_E_NULL_PTR;
}
else
{
/*! Set default Head Misalignment Configuration */
rslt = bhy2_set_parameter(BHY2_HEAD_ORI_PARAM(BHY2_HEAD_ORI_HMC_SET_DEF_CONFIG),
(uint8_t*)buffer,
BHY2_HEAD_ORI_HMC_SET_DEF_CONFIG_LENGTH,
dev);
}
return rslt;
}
/*Callback for getting Head Misalignment Calibrator Version*/
int8_t bhy2_head_tracker_get_hmc_version(const void *buffer, struct bhy2_dev *dev)
{
int8_t rslt = BHY2_OK;
uint32_t act_len;
if (dev == NULL)
{
rslt = BHY2_E_NULL_PTR;
}
else
{
/*! Get Head Misalignment Calibrator Version */
rslt = bhy2_get_parameter(BHY2_HEAD_ORI_PARAM(BHY2_HEAD_ORI_HMC_VERSION),
(uint8_t*)buffer,
BHY2_HEAD_ORI_HMC_VERSION_LENGTH,
&act_len,
dev);
}
return rslt;
}
/*Callback for setting Head Misalignment Calibration Correction Quaternion Configuration*/
int8_t bhy2_head_tracker_set_hmc_quat_calib_corr_config(const void *buffer, struct bhy2_dev *dev)
{
int8_t rslt = BHY2_OK;
if (dev == NULL)
{
rslt = BHY2_E_NULL_PTR;
}
else
{
/*! Set Head Misalignment Calibration Correction Quaternion Configuration */
rslt = bhy2_set_parameter(BHY2_HEAD_ORI_PARAM(BHY2_HEAD_ORI_HMC_QUAT_CALIB_CORR),
(uint8_t*)buffer,
BHY2_HEAD_ORI_HMC_QUAT_CALIB_CORR_WLENGTH,
dev);
}
return rslt;
}
/*Callback for getting Head Misalignment Calibration Correction Quaternion Configuration*/
int8_t bhy2_head_tracker_get_hmc_quat_calib_corr_config(const void *buffer, struct bhy2_dev *dev)
{
int8_t rslt = BHY2_OK;
uint32_t act_len;
if (dev == NULL)
{
rslt = BHY2_E_NULL_PTR;
}
else
{
/*! Get Head Misalignment Calibration Correction Quaternion Configuration */
rslt = bhy2_get_parameter(BHY2_HEAD_ORI_PARAM(BHY2_HEAD_ORI_HMC_QUAT_CALIB_CORR),
(uint8_t*)buffer,
BHY2_HEAD_ORI_HMC_QUAT_CALIB_CORR_RLENGTH,
&act_len,
dev);
}
return rslt;
}
/*Callback for setting Head Orientation Initial Head Correction for Quaternion*/
int8_t bhy2_head_tracker_set_quat_initial_head_correction(const void *buffer, struct bhy2_dev *dev)
{
int8_t rslt = BHY2_OK;
if (dev == NULL)
{
rslt = BHY2_E_NULL_PTR;
}
else
{
/*! Set Head Orientation Initial Head Correction for Quaternion */
rslt = bhy2_set_parameter(BHY2_HEAD_ORI_PARAM(BHY2_HEAD_ORI_QUAT_INITIAL_HEAD_CORR),
(uint8_t*)buffer,
BHY2_HEAD_ORI_QUAT_INITIAL_HEAD_CORR_LENGTH,
dev);
}
return rslt;
}
/*Callback for getting Head Orientation Initial Head Correction for Quaternion*/
int8_t bhy2_head_tracker_get_quat_initial_head_correction(const void *buffer, struct bhy2_dev *dev)
{
int8_t rslt = BHY2_OK;
uint32_t act_len;
if (dev == NULL)
{
rslt = BHY2_E_NULL_PTR;
}
else
{
/*! Get Head Orientation Initial Head Correction for Quaternion */
rslt = bhy2_get_parameter(BHY2_HEAD_ORI_PARAM(BHY2_HEAD_ORI_QUAT_INITIAL_HEAD_CORR),
(uint8_t*)buffer,
BHY2_HEAD_ORI_QUAT_INITIAL_HEAD_CORR_LENGTH,
&act_len,
dev);
}
return rslt;
}
/*Callback for getting Head Orientation Version*/
int8_t bhy2_head_tracker_get_ho_version(const void *buffer, struct bhy2_dev *dev)
{
int8_t rslt = BHY2_OK;
uint32_t act_len;
if (dev == NULL)
{
rslt = BHY2_E_NULL_PTR;
}
else
{
/*! Get IMU/NDOF Head Orientation Version */
rslt = bhy2_get_parameter(BHY2_HEAD_ORI_PARAM(BHY2_HEAD_ORI_VERSION),
(uint8_t*)buffer,
BHY2_HEAD_ORI_VERSION_LENGTH,
&act_len,
dev);
}
return rslt;
}
/*Callback for setting Head Orientation Initial Head Correction for Euler*/
int8_t bhy2_head_tracker_set_eul_initial_head_correction(const void *buffer, struct bhy2_dev *dev)
{
int8_t rslt = BHY2_OK;
if (dev == NULL)
{
rslt = BHY2_E_NULL_PTR;
}
else
{
/*! Set Head Orientation Initial Head Correction for Euler */
rslt = bhy2_set_parameter(BHY2_HEAD_ORI_PARAM(BHY2_HEAD_ORI_EUL_INITIAL_HEAD_CORR),
(uint8_t*)buffer,
BHY2_HEAD_ORI_EUL_INITIAL_HEAD_CORR_LENGTH,
dev);
}
return rslt;
}
/*Callback for getting Head Orientation Initial Head Correction for Euler*/
int8_t bhy2_head_tracker_get_eul_initial_head_correction(const void *buffer, struct bhy2_dev *dev)
{
int8_t rslt = BHY2_OK;
uint32_t act_len;
if (dev == NULL)
{
rslt = BHY2_E_NULL_PTR;
}
else
{
/*! Get Head Orientation Initial Head Correction for Euler */
rslt = bhy2_get_parameter(BHY2_HEAD_ORI_PARAM(BHY2_HEAD_ORI_EUL_INITIAL_HEAD_CORR),
(uint8_t*)buffer,
BHY2_HEAD_ORI_EUL_INITIAL_HEAD_CORR_LENGTH,
&act_len,
dev);
}
return rslt;
}

View File

@@ -0,0 +1,213 @@
/**
* 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 bhy2_head_tracker.h
* @date 2023-03-24
* @version v1.6.0
*
*/
#ifndef _BHY2_HEAD_TRACKER_H_
#define _BHY2_HEAD_TRACKER_H_
/* Start of CPP Guard */
#ifdef __cplusplus
extern "C" {
#endif /*__cplusplus */
#include <stdint.h>
#include <stdlib.h>
#include <stdlib.h>
#include "bhy2.h"
#include "bhy2_head_tracker_defs.h"
/*!
* @brief Parsing callback for Head Orientation Quaternion
*
* @param[in] payload
* @param[out] bhy2_head_tracker_quat_data to store Head Orientation [Quaternion] data
*
* @return API error codes
*
*/
void bhy2_head_tracker_quat_parsing(const uint8_t *payload, struct bhy2_head_tracker_quat_data *data);
/*!
* @brief Parsing callback for Head Orientation Euler
*
* @param[in] payload
* @param[out] bhy2_head_tracker_eul_data to store Head Orientation [Euler] data
*
* @return API error codes
*
*/
void bhy2_head_tracker_eul_parsing(const uint8_t *payload, struct bhy2_head_tracker_eul_data *data);
/*!
* @brief To trigger the Head Misalignment Calibration
*
* @param[in] buffer
* @param[in] dev hub handle
*
* @return API error codes
*
*/
int8_t bhy2_head_tracker_trigger_hmc_calibration(const void *buffer, struct bhy2_dev *dev);
/*!
* @brief To set the Head Misalignment Calibration Configuration
*
* @param[in] buffer to hold the Head Misalignment Calibration Configuration
* @param[in] dev hub handle
*
* @return API error codes
*
*/
int8_t bhy2_head_tracker_set_hmc_configuration(const void *buffer, struct bhy2_dev *dev);
/*!
* @brief To get the Head Misalignment Calibration Configuration
*
* @param[out] buffer to hold the Head Misalignment Calibration Configuration
* @param[in] dev hub handle
*
* @return API error codes
*
*/
int8_t bhy2_head_tracker_get_hmc_configuration(const void *buffer, struct bhy2_dev *dev);
/*!
* @brief To set the default Head Misalignment Calibration Configuration
*
* @param[in] command buffer
* @param[in] dev hub handle
*
* @return API error codes
*
*/
int8_t bhy2_head_tracker_set_default_hmc_configuration(const void *buffer, struct bhy2_dev *dev);
/*!
* @brief To get the Head Misalignment Calibrator Version
*
* @param[out] buffer to hold the Head Misalignment Calibrator Version
* @param[in] dev hub handle
*
* @return API error codes
*
*/
int8_t bhy2_head_tracker_get_hmc_version(const void *buffer, struct bhy2_dev *dev);
/*!
* @brief To set the Head Misalignment Quaternion Calibration Correction Configuration
*
* @param[in] buffer to hold the Head Misalignment Quaternion Calibration Correction Configuration
* @param[in] dev hub handle
*
* @return API error codes
*
*/
int8_t bhy2_head_tracker_set_hmc_quat_calib_corr_config(const void *buffer, struct bhy2_dev *dev);
/*!
* @brief To get the Head Misalignment Quaternion Calibration Correction Configuration
*
* @param[out] buffer to hold the Head Misalignment Quaternion Calibration Correction Configuration
* @param[in] dev hub handle
*
* @return API error codes
*
*/
int8_t bhy2_head_tracker_get_hmc_quat_calib_corr_config(const void *buffer, struct bhy2_dev *dev);
/*!
* @brief To set the Head Misalignment Quaternion Initial Head Correction
*
* @param[in] buffer to hold the Head Misalignment Quaternion Initial Head Correction
* @param[in] dev hub handle
*
* @return API error codes
*
*/
int8_t bhy2_head_tracker_set_quat_initial_head_correction(const void *buffer, struct bhy2_dev *dev);
/*!
* @brief To get the Head Misalignment Quaternion Initial Head Correction
*
* @param[out] buffer to hold the Head Misalignment Quaternion Initial Head Correction
* @param[in] dev hub handle
*
* @return API error codes
*
*/
int8_t bhy2_head_tracker_get_quat_initial_head_correction(const void *buffer, struct bhy2_dev *dev);
/*!
* @brief To get the IMU/NDOF Head Orientation Version
*
* @param[out] buffer to hold the IMU/NDOF Head Orientation Version
* @param[in] dev hub handle
*
* @return API error codes
*
*/
int8_t bhy2_head_tracker_get_ho_version(const void *buffer, struct bhy2_dev *dev);
/*!
* @brief To set the Head Misalignment Euler Initial Head Correction
*
* @param[in] buffer to hold the Head Misalignment Euler Initial Head Correction
* @param[in] dev hub handle
*
* @return API error codes
*
*/
int8_t bhy2_head_tracker_set_eul_initial_head_correction(const void *buffer, struct bhy2_dev *dev);
/*!
* @brief To get the Head Misalignment Euler Initial Head Correction
*
* @param[out] buffer to hold the Head Misalignment Euler Initial Head Correction
* @param[in] dev hub handle
*
* @return API error codes
*
*/
int8_t bhy2_head_tracker_get_eul_initial_head_correction(const void *buffer, struct bhy2_dev *dev);
/* End of CPP Guard */
#ifdef __cplusplus
}
#endif /*__cplusplus */
#endif /* _BHY2_HEAD_TRACKER_H_ */

View File

@@ -0,0 +1,138 @@
/**
* 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 bhy2_head_tracker_defs.h
* @date 2023-03-24
* @version v1.6.0
*
*/
#ifndef _BHY2_HEAD_TRACKER_DEFS_H_
#define _BHY2_HEAD_TRACKER_DEFS_H_
/* Start of CPP Guard */
#ifdef __cplusplus
extern "C" {
#endif /*__cplusplus */
#include <stdint.h>
#include <stdlib.h>
#include <stdlib.h>
#include "bhy2.h"
/*! Virtual Sensor Macros */
#define BHY2_SENSOR_ID_HEAD_ORI_MIS_ALG UINT8_C(120) /*Head Orientation Misalignment*/
#define BHY2_SENSOR_ID_IMU_HEAD_ORI_Q UINT8_C(121) /*IMU Head Orientation Quaternion*/
#define BHY2_SENSOR_ID_NDOF_HEAD_ORI_Q UINT8_C(122) /*NDOF Head Orientation Quaternion*/
#define BHY2_SENSOR_ID_IMU_HEAD_ORI_E UINT8_C(123) /*IMU Head Orientation Euler*/
#define BHY2_SENSOR_ID_NDOF_HEAD_ORI_E UINT8_C(124) /*NDOF Head Orientation Euler*/
#define BHY2_HEAD_ORI_PAGE UINT16_C(12)
#define BHY2_HEAD_ORI_PARAM(id) (((BHY2_HEAD_ORI_PAGE) << 8) | (id))
#define BHY2_HEAD_ORI_HMC_TRIGGER_CALIB UINT8_C(1)
#define BHY2_HEAD_ORI_HMC_TRIGGER_CALIB_LENGTH UINT8_C(4)
#define BHY2_HEAD_ORI_HMC_TRIGGER_CALIB_SET UINT8_C(1)
#define BHY2_HEAD_ORI_HMC_CONFIG UINT8_C(2)
#define BHY2_HEAD_ORI_HMC_CONFIG_LENGTH UINT8_C(8)
#define BHY2_HEAD_ORI_HMC_SET_DEF_CONFIG UINT8_C(3)
#define BHY2_HEAD_ORI_HMC_SET_DEF_CONFIG_LENGTH UINT8_C(4)
#define BHY2_HEAD_ORI_HMC_SET_DEF_CONFIG_SET UINT8_C(1)
#define BHY2_HEAD_ORI_HMC_VERSION UINT8_C(4)
#define BHY2_HEAD_ORI_HMC_VERSION_LENGTH UINT8_C(4)
#define BHY2_HEAD_ORI_HMC_QUAT_CALIB_CORR UINT8_C(5)
#define BHY2_HEAD_ORI_HMC_QUAT_CALIB_CORR_WLENGTH UINT8_C(16)
#define BHY2_HEAD_ORI_HMC_QUAT_CALIB_CORR_RLENGTH UINT8_C(20)
#define BHY2_HEAD_ORI_QUAT_INITIAL_HEAD_CORR UINT8_C(10)
#define BHY2_HEAD_ORI_QUAT_INITIAL_HEAD_CORR_LENGTH UINT8_C(4)
#define BHY2_HEAD_ORI_QUAT_INITIAL_HEAD_CORR_DISABLE UINT8_C(0)
#define BHY2_HEAD_ORI_QUAT_INITIAL_HEAD_CORR_ENABLE UINT8_C(1)
#define BHY2_HEAD_ORI_VERSION UINT8_C(11)
#define BHY2_HEAD_ORI_VERSION_LENGTH UINT8_C(4)
#define BHY2_HEAD_ORI_EUL_INITIAL_HEAD_CORR UINT8_C(12)
#define BHY2_HEAD_ORI_EUL_INITIAL_HEAD_CORR_LENGTH UINT8_C(4)
#define BHY2_HEAD_ORI_EUL_INITIAL_HEAD_CORR_DISABLE UINT8_C(0)
#define BHY2_HEAD_ORI_EUL_INITIAL_HEAD_CORR_ENABLE UINT8_C(1)
/*! Sensor Structure for Head Orientation Quaternion */
struct bhy2_head_tracker_quat_data
{
int16_t x, y, z, w;
uint8_t accuracy;
};
/*! Sensor Structure for Head Orientation Euler */
struct bhy2_head_tracker_eul_data
{
int16_t heading, pitch, roll;
uint8_t accuracy;
};
/*! Structure for Head Misalignment Configuration */
struct bhy2_head_tracker_misalignment_config
{
uint8_t still_phase_max_dur;
uint8_t still_phase_min_dur;
uint8_t still_phase_max_samples;
int32_t acc_diff_threshold;
};
/*! Structure for Head Orientation /Head Misalignment version */
struct bhy2_head_tracker_ver
{
uint8_t major, minor, patch, reserved;
};
/*! Structure for Head Misalignment Quaternion Correction */
struct bhy2_head_tracker_misalignment_quat_corr
{
int32_t quaternion_x;
int32_t quaternion_y;
int32_t quaternion_z;
int32_t quaternion_w;
int32_t accuracy;
};
/* End of CPP Guard */
#ifdef __cplusplus
}
#endif /*__cplusplus */
#endif /* _BHY2_HEAD_TRACKER_DEFS_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,578 @@
/**
* 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 bhy2_hif.h
* @date 2023-03-24
* @version v1.6.0
*
*/
#ifndef __BHY2_HIF_H__
#define __BHY2_HIF_H__
/* Start of CPP Guard */
#ifdef __cplusplus
extern "C" {
#endif /*__cplusplus */
#include "bhy2_defs.h"
/**
* @brief Function to link the callback interfaces
* @param[in] intf : Physical communication interface
* @param[in] read : Read function pointer
* @param[in] write : Write function pointer
* @param[in] delay_us : Microsecond delay function pointer
* @param[in] read_write_len : Maximum read/write lengths supported
* @param[in] intf_ptr : Reference to the interface. Can be NULL
* @param[in] hif : HIF device reference
* @return API error codes
*/
int8_t bhy2_hif_init(enum bhy2_intf intf,
bhy2_read_fptr_t read,
bhy2_write_fptr_t write,
bhy2_delay_us_fptr_t delay_us,
uint32_t read_write_len,
void *intf_ptr,
struct bhy2_hif_dev *hif);
/**
* @brief Function to get data from registers
* @param[in] reg_addr : Register address to be read from
* @param[out] reg_data : Reference to the data buffer
* @param[in] length : Length of the data buffer
* @param[in] hif : HIF device reference
* @return API error codes
*/
int8_t bhy2_hif_get_regs(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, struct bhy2_hif_dev *hif);
/**
* @brief Function to set data to registers
* @param[in] reg_addr : Register address to write to
* @param[in] reg_data : Reference to the data buffer
* @param[in] length : Length of the data buffer
* @param[in] hif : HIF device reference
* @return API error codes
*/
int8_t bhy2_hif_set_regs(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, struct bhy2_hif_dev *hif);
/**
* @brief Function to delay in microseconds
* @param[in] period_us : Period to delay in microseconds
* @param[in] hif : HIF device reference
* @return API error codes
*/
int8_t bhy2_hif_delay_us(uint32_t period_us, const struct bhy2_hif_dev *hif);
/**
* Function to execute a command
* @param[in] cmd : Command code
* @param[in] payload : Reference to the data buffer containing the command's payload
* @param[in] length : Length of the data buffer
* @param[in] hif : HIF device reference
* @return API error codes
*/
int8_t bhy2_hif_exec_cmd(uint16_t cmd, const uint8_t *payload, uint32_t length, struct bhy2_hif_dev *hif);
/**
* @brief Function to get a parameter
* @param[in] param : Parameter ID
* @param[out] payload : Reference to the data buffer to store the parameter's payload
* @param[in] payload_len : Length of the data buffer
* @param[out] actual_len : Actual length of the payload
* @param[in] hif : HIF device reference
* @return API error codes
*/
int8_t bhy2_hif_get_parameter(uint16_t param,
uint8_t *payload,
uint32_t payload_len,
uint32_t *actual_len,
struct bhy2_hif_dev *hif);
/**
* @brief Function to set a parameter
* @param[in] param : Parameter ID
* @param[in] payload : Reference to the data buffer storing the parameter's payload
* @param[in] length : Length of the data buffer
* @param[in] hif : HIF device reference
* @return API error codes
*/
int8_t bhy2_hif_set_parameter(uint16_t param, const uint8_t *payload, uint32_t length, struct bhy2_hif_dev *hif);
/**
* @brief Function to erase the flash
* @param[in] start_addr : Start address
* @param[in] end_addr : End address
* @param[in] hif : HIF device address
* @return API error codes
*/
int8_t bhy2_hif_erase_flash(uint32_t start_addr, uint32_t end_addr, struct bhy2_hif_dev *hif);
/**
* @brief Function to upload data to flash
* @param[in] firmware : Reference to the data buffer storing the firmware
* @param[in] length : Length of the data buffer
* @param[in/out] work_buffer : Reference to the work buffer
* @param[in] work_buf_len : Length of the work buffer
* @param[out] exp_size : Expected size of the work buffer if insufficient size
* @param[in] hif : HIF device reference
* @return API error codes
*/
int8_t bhy2_hif_upload_to_flash(const uint8_t *firmware,
uint32_t length,
uint8_t *work_buffer,
uint32_t work_buf_len,
uint32_t *exp_size,
struct bhy2_hif_dev *hif,
bhy2_progress_callback progress_cb,
void *user_data);
/**
* @brief Function to upload data to flash partly
* @param[in] firmware : Reference cur_pos of the data buffer storing the firmware
* @param[in] cur_pos : Current position of the firmware
* @param[in] packet_len : Length of the firmware packet to be transferred
* @param[in] hif : HIF device reference
* @return API error codes
*/
int8_t bhy2_hif_upload_to_flash_partly(const uint8_t *firmware,
uint32_t cur_pos,
uint32_t packet_len,
struct bhy2_hif_dev *hif);
/**
* @brief Function to boot from flash
* @param[in] hif : HIF device reference
* @return API error codes
*/
int8_t bhy2_hif_boot_from_flash(struct bhy2_hif_dev *hif);
/**
* @brief Function to get the product ID
* @param[out] product_id : Reference to the data buffer to store the product ID
* @param[in] hif : HIF device reference
* @return API error codes
*/
int8_t bhy2_hif_get_product_id(uint8_t *product_id, struct bhy2_hif_dev *hif);
/**
* @brief Function to get the chip ID
* @param[out] chip_id : Reference to the data buffer to store the chip ID
* @param[in] hif : HIF device reference
* @return API error codes
*/
int8_t bhy2_hif_get_chip_id(uint8_t *chip_id, struct bhy2_hif_dev *hif);
/**
* @brief Function to get the ROM version
* @param[out] rom_version : Reference to the data buffer to store the ROM version
* @param[in] hif : HIF device reference
* @return API error codes
*/
int8_t bhy2_hif_get_rom_version(uint16_t *rom_version, struct bhy2_hif_dev *hif);
/**
* @brief Function to get the kernel version
* @param[out] kernel_version : Reference to the data buffer to store the kernel version
* @param[in] hif : HIF device reference
* @return API error codes
*/
int8_t bhy2_hif_get_kernel_version(uint16_t *kernel_version, struct bhy2_hif_dev *hif);
/**
* @brief Function to get the user version
* @param[out] user_version : Reference to the data buffer to store the user version
* @param[in] hif : HIF device reference
* @return API error codes
*/
int8_t bhy2_hif_get_user_version(uint16_t *user_version, struct bhy2_hif_dev *hif);
/**
* @brief Function to get the boot status
* @param[out] boot_status : Reference to the data buffer to store the boot status
* @param[in] hif : HIF device reference
* @return API error codes
*/
int8_t bhy2_hif_get_boot_status(uint8_t *boot_status, struct bhy2_hif_dev *hif);
/**
* @brief Function to get the host status
* @param[out] host_status : Reference to the data buffer to store the host status
* @param[in] hif : HIF device reference
* @return API error codes
*/
int8_t bhy2_hif_get_host_status(uint8_t *host_status, struct bhy2_hif_dev *hif);
/**
* @brief Function to get the feature status
* @param[out] feat_status : Reference to the data buffer to store the feature status
* @param[in] hif : HIF device reference
* @return API error codes
*/
int8_t bhy2_hif_get_feature_status(uint8_t *feat_status, struct bhy2_hif_dev *hif);
/**
* @brief Function get the interrupt status
* @param[out] int_status : Reference to the data buffer to store the interrupt status
* @param[in] hif : HIF device reference
* @return API error codes
*/
int8_t bhy2_hif_get_interrupt_status(uint8_t *int_status, struct bhy2_hif_dev *hif);
/**
* @brief Function get the firmware error code
* @param[out] fw_error : Reference to the data buffer to store the firmware error code
* @param[in] hif : HIF device reference
* @return API error code
*/
int8_t bhy2_hif_get_fw_error(uint8_t *fw_error, struct bhy2_hif_dev *hif);
/**
* @brief Function to trigger a soft reset
* @param[in] hif : HIF device reference
* @return API error codes
*/
int8_t bhy2_hif_reset(struct bhy2_hif_dev *hif);
/**
* @brief Function to upload a firmware to RAM
* @param[in] firmware : Reference to the data buffer storing the firmware
* @param[in] length : Length of the firmware
* @param[in] hif : HIF device reference
* @return API error codes
*/
int8_t bhy2_hif_upload_firmware_to_ram(const uint8_t *firmware, uint32_t length, struct bhy2_hif_dev *hif);
/**
* @brief Function to upload a part of the firmware to RAM
* @param[in] firmware : Reference to the data buffer storing the current part of firmware
* @param[in] total_size : Total size of the firmware
* @param[in] cur_pos : Current position of the firmware
* @param[in] packet_len : Size of firmware part to be uploaded
* @param[in] hif : HIF device reference
* @return API error codes
*/
int8_t bhy2_hif_upload_firmware_to_ram_partly(const uint8_t *firmware,
uint32_t total_size,
uint32_t cur_pos,
uint32_t packet_len,
struct bhy2_hif_dev *hif);
/**
* @brief Function to boot from RAM
* @param[in] hif : HIF device reference
* @return API error codes
*/
int8_t bhy2_hif_boot_program_ram(struct bhy2_hif_dev *hif);
/**
* @brief Function to get data from the Wake-up FIFO
* @param[out] fifo : Reference to the data buffer to store data from the FIFO
* @param[in] fifo_len : Length of the data buffer
* @param[out] bytes_read : Number of bytes read into the data buffer
* @param[out] bytes_remain : Bytes remaining in the sensor FIFO
* @param[in] hif : HIF device reference
* @return API error codes
*/
int8_t bhy2_hif_get_wakeup_fifo(uint8_t *fifo,
uint32_t fifo_len,
uint32_t *bytes_read,
uint32_t *bytes_remain,
struct bhy2_hif_dev *hif);
/**
* @brief Function to get data from the Non-wake-up FIFO
* @param[out] fifo : Reference to the data buffer to store data from the FIFO
* @param[in] fifo_len : Length of the data buffer
* @param[out] bytes_read : Number of bytes read into the data buffer
* @param[out] bytes_remain : Bytes remaining in the sensor FIFO
* @param[in] hif : HIF device reference
* @return API error codes
*/
int8_t bhy2_hif_get_nonwakeup_fifo(uint8_t *fifo,
uint32_t fifo_len,
uint32_t *bytes_read,
uint32_t *bytes_remain,
struct bhy2_hif_dev *hif);
/**
* @brief Function to get synchronous data from the Status FIFO
* @param[out] status_code : Status code received
* @param[out] fifo : Reference to the data buffer to store the payload of the status code
* @param[in] fifo_len : Length of the data buffer
* @param[out] bytes_remain : Number of bytes in the payload
* @param[in] hif : HIF device reference
* @return API error codes
*/
int8_t bhy2_hif_get_status_fifo(uint16_t *status_code,
uint8_t *fifo,
uint32_t fifo_len,
uint32_t *bytes_remain,
struct bhy2_hif_dev *hif);
/**
* @brief Function to get asynchronous data from the Status FIFO
* @param[out] fifo : Reference to the data buffer to store data from the FIFO
* @param[in] fifo_len : Length of the data buffer
* @param[out] bytes_read : Number of bytes read into the data buffer
* @param[out] bytes_remain : Bytes remaining in the sensor FIFO
* @param[in] hif : HIF device reference
* @return API error codes
*/
int8_t bhy2_hif_get_status_fifo_async(uint8_t *fifo,
uint32_t fifo_len,
uint32_t *bytes_read,
uint32_t *bytes_remain,
struct bhy2_hif_dev *hif);
/**
* @brief Function to configure a virtual sensor
* @param[in] sensor_id : Sensor ID of the virtual sensor
* @param[in] sample_rate : Sample rate in Hz
* @param[in] latency : Report latency in milliseconds
* @param[in] hif : HIF device reference
* @return API error codes
*/
int8_t bhy2_hif_exec_sensor_conf_cmd(uint8_t sensor_id,
bhy2_float sample_rate,
uint32_t latency,
struct bhy2_hif_dev *hif);
/**
* @brief Function to flush data of a virtual sensor from the FIFOs
* @param[in] sensor_id : Sensor ID of the virtual sensor
* @param[in] hif : HIF device reference
* @return API error codes
*/
int8_t bhy2_hif_set_fifo_flush(uint8_t sensor_id, struct bhy2_hif_dev *hif);
/**
* @brief Function to perform a self-test for a particular virtual sensor
* @param[in] phys_sensor_id : Physical sensor ID of the virtual sensor
* @param[out] self_test_resp : Reference to the data buffer to store the self-test response
* @param[in] hif : HIF device reference
* @return API error codes
*/
int8_t bhy2_hif_do_self_test(uint8_t phys_sensor_id,
struct bhy2_self_test_resp *self_test_resp,
struct bhy2_hif_dev *hif);
/**
* @brief Function to perform a fast offset compensation for a particular virtual sensor
* @param[in] phys_sensor_id : Physical Sensor ID of the virtual sensor
* @param[out] foc_resp : Reference to the data buffer to store the FOC response
* @param[in] hif : HIF device reference
* @return API error codes
*/
int8_t bhy2_hif_do_foc(uint8_t phys_sensor_id, struct bhy2_foc_resp *foc_resp, struct bhy2_hif_dev *hif);
/**
* @brief Function to get the sensor control configuration of a virtual sensor
* @param[in] sensor_id : Sensor ID of the virtual sensor
* @param[in] ctrl_code : Sensor control code
* @param[out] payload : Reference to the data buffer to store the sensor control
* @param[in] payload_len : Length of the data buffer
* @param[out] actual_len : Actual length of the sensor control configuration
* @param[in] hif : HIF device reference
* @return API error codes
*/
int8_t bhy2_hif_get_sensor_ctrl(uint8_t sensor_id,
uint8_t ctrl_code,
uint8_t *payload,
uint32_t payload_len,
uint32_t *actual_len,
struct bhy2_hif_dev *hif);
/**
* @brief Function to set the sensor control configuration of a virtual sensor
* @param[in] sensor_id : Sensor ID of the virtual sensor
* @param[in] ctrl_code : Sensor control code
* @param[in] payload : Reference to the data buffer storing the sensor control
* @param[in] payload_len : Length of the sensor control configuration
* @param[in] hif : HIF device reference
* @return API error codes
*/
int8_t bhy2_hif_set_sensor_ctrl(uint8_t sensor_id,
uint8_t ctrl_code,
const uint8_t *payload,
uint32_t payload_len,
struct bhy2_hif_dev *hif);
/**
* @brief Function to get the BSX state of a BSX parameter
* @param[in] param_id : Parameter ID of the BSX parameter
* @param[out] bsx_state : Reference to teh data buffer to store the BSX state
* @param[in] state_len : Length of the buffer
* @param[out] actual_len : Actual length of the BSX state
* @param[in] hif : HIF device reference
* @return API error codes
*/
int8_t bhy2_hif_get_bsx_state(uint16_t param_id,
uint8_t *bsx_state,
uint32_t state_len,
uint32_t *actual_len,
struct bhy2_hif_dev *hif);
/**
* @brief Function to the BSX state of a BSX parameter
* @param[in] param_id : Parameter ID of the BSX parameter
* @param[in] bsx_state : Reference to the data buffer storing the BSX state
* @param[in] state_len : Length of the BSX state
* @param[in] hif : HIF device reference
* @return API error codes
*/
int8_t bhy2_hif_set_bsx_state(uint16_t param_id, const uint8_t *bsx_state, uint32_t state_len,
struct bhy2_hif_dev *hif);
/**
* @brief Function to request a timestamp event
* @param[in] hif : HIF device reference
* @return API error codes
*/
int8_t bhy2_hif_request_hw_timestamp(struct bhy2_hif_dev *hif);
/**
* @brief Function to get the hardware timestamp
* @param[out] ts_ticks : Reference to the data buffer to store the timestamp in ticks
* @param[in] hif : HIF device reference
* @return API error codes
*/
int8_t bhy2_hif_get_hw_timestamp(uint64_t *ts_ticks, struct bhy2_hif_dev *hif);
/**
* @brief Function to request and get the hardware timestamp
* @param[out] ts_ticks : Reference to the data buffer to store the timestamp in ticks
* @param[in] hif : HIF device reference
* @return API error codes
*/
int8_t bhy2_hif_req_and_get_hw_timestamp(uint64_t *ts_ticks, struct bhy2_hif_dev *hif);
/**
* @brief Function to communicate with connected sensors
* @param[in] payload : Command payload
* @param[in] payload_len : Payload length
* @param[in/out] reg_data : Reference to the data buffer storing the register data
* @param[in] length : Length of the data buffer
* @param[out] actual_len : Registers actually read
* @param[in] hif : HIF device reference
* @return API error codes
*/
int8_t bhy2_hif_exec_soft_passthrough(const uint8_t *payload,
uint32_t payload_len,
uint8_t *reg_data,
uint32_t length,
uint32_t *actual_len,
struct bhy2_hif_dev *hif);
/**
* @brief Function to get the post-mortem data dump
* @param[out] code : Post-mortem status code
* @param[out] actual_len : Actual length of the post-mortem data dump
* @param[out] post_mortem : Reference to the data buffer to store the data dump
* @param[in] buffer_len : Length of the data buffer
* @param[in] hif : HIF device reference
* @return API error codes
*/
int8_t bhy2_hif_get_post_mortem(uint16_t *code,
uint32_t *actual_len,
uint8_t *post_mortem,
uint32_t buffer_len,
struct bhy2_hif_dev *hif);
/**
* @brief Function get information of a virtual sensor
* @param[in] sensor_id : Sensor ID of the virtual sensor
* @param[out] info : Reference to the data buffer to store the sensor info
* @param[in] hif : HIF device reference
* @return API error codes
*/
int8_t bhy2_hif_get_sensor_info(uint8_t sensor_id, struct bhy2_sensor_info *info, struct bhy2_hif_dev *hif);
/**
* @brief Function to get the physical sensor information of a virtual sensor
* @param[in] sensor_id : Sensor ID of the virtual sensor
* @param[out] info : Reference to the data buffer to store the physical sensor info
* @param[in] hif : HIF device reference
* @return API error codes
*/
int8_t bhy2_hif_get_phys_sensor_info(uint8_t sensor_id, struct bhy2_phys_sensor_info *info, struct bhy2_hif_dev *hif);
/**
* @brief Function to get the orientation matrix of a virtual sensor
* @param[in] sensor_id : Sensor ID of the virtual sensor
* @param[out] orient_matrix : Reference to the data buffer to store the orientation matrix
* @param[in] hif : HIF device reference
* @return API error codes
*/
int8_t bhy2_hif_set_orientation_matrix(uint8_t sensor_id,
struct bhy2_orient_matrix orient_matrix,
struct bhy2_hif_dev *hif);
/**
* @brief Function to set the data injection mode
* @param[in] payload : Reference to the data buffer containing the host injection mode
* @param[in] payload_len : Length of the data buffer
* @param[in/out] work_buf : Reference to the work buffer
* @param[in] work_buf_len : Length of the work buffer
* @param[out] actual_len : Expected length of the work buffer
* @param[in] hif : HIF device reference
* @return API error codes
*/
int8_t bhy2_hif_set_inject_data_mode(const uint8_t *payload,
uint8_t payload_len,
const uint8_t *work_buf,
uint32_t work_buf_len,
const uint32_t *actual_len,
struct bhy2_hif_dev *hif);
/**
* @brief Function to inject data
* @param[in] payload : Reference to the data buffer
* @param[in] payload_len : Length of the data buffer
* @param[in] hif : HIF device reference
* @return API error codes
*/
int8_t bhy2_hif_inject_data(const uint8_t *payload, uint32_t payload_len, struct bhy2_hif_dev *hif);
/**
* @brief Function to wait till status is ready
* @param[in] hif : HIF device reference
* @return API error codes
*/
int8_t bhy2_hif_wait_status_ready(struct bhy2_hif_dev *hif);
/* End of CPP Guard */
#ifdef __cplusplus
}
#endif /*__cplusplus */
#endif /* __BHY2_HIF_H__ */

View File

@@ -0,0 +1,373 @@
/**
* 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 bhy2_klio.c
* @date 2023-03-24
* @version v1.6.0
*
*/
/*********************************************************************/
/* system header files */
#include <string.h>
#include <stdio.h>
/*********************************************************************/
/* BHY2 SensorAPI header files */
#include "bhy2.h"
/*********************************************************************/
/* own header files */
#include "bhy2_klio.h"
int8_t bhy2_klio_read_pattern(const uint8_t id, uint8_t *buffer, uint16_t *length, struct bhy2_dev *dev)
{
int8_t rslt;
uint32_t ret_len;
bhy2_klio_pattern_transfer_t pattern = { 0 };
if (!buffer || !length || !dev)
{
return BHY2_E_NULL_PTR;
}
if (id != 0 || *length < sizeof(pattern.pattern_data))
{
return BHY2_E_INVALID_PARAM;
}
rslt = bhy2_get_parameter(KLIO_PARAM(KLIO_HIF_PARAM_PATTERN), (uint8_t*)&pattern, sizeof(pattern), &ret_len, dev);
if (rslt != BHY2_OK)
{
return rslt;
}
if (ret_len != sizeof(pattern))
{
return BHY2_E_INVALID_PARAM;
}
memcpy(buffer, pattern.pattern_data, pattern.full_size);
*length = pattern.full_size;
return rslt;
}
int8_t bhy2_klio_read_reset_driver_status(uint32_t *klio_driver_status, struct bhy2_dev *dev)
{
uint32_t ret_len = 0;
int8_t rslt;
if (!klio_driver_status || !dev)
{
return BHY2_E_NULL_PTR;
}
do
{
rslt =
bhy2_get_parameter(KLIO_PARAM(KLIO_HIF_PARAM_DRIVER_STATUS),
(uint8_t*)klio_driver_status,
sizeof(*klio_driver_status),
&ret_len,
dev);
if (rslt != BHY2_OK)
{
return rslt;
}
} while (*klio_driver_status == KLIO_DRIVER_ERROR_OPERATION_PENDING);
return rslt;
}
int8_t bhy2_klio_write_pattern(const uint8_t idx, const uint8_t *pattern_data, const uint16_t size,
struct bhy2_dev *dev)
{
bhy2_klio_pattern_transfer_t pattern = {
.block_id = 0, .block_size = (uint8_t)size, .full_size = size, .pattern_id = idx, .pattern_data = { 0 }
};
if (!dev || size > sizeof(pattern.pattern_data))
{
return BHY2_E_INVALID_PARAM;
}
memcpy(pattern.pattern_data, pattern_data, size);
return bhy2_set_parameter(KLIO_PARAM(KLIO_HIF_PARAM_PATTERN), (const uint8_t*)&pattern, sizeof(pattern), dev);
}
int8_t bhy2_klio_set_pattern_states(const bhy2_klio_pattern_state_t operation,
const uint8_t *pattern_ids,
const uint16_t count,
struct bhy2_dev *dev)
{
uint32_t buffer_size = sizeof(bhy2_klio_pattern_state_op_t) + count;
uint8_t buffer[buffer_size];
if (!dev || count == 0)
{
return BHY2_E_INVALID_PARAM;
}
buffer[1] = (uint8_t)count;
buffer[0] = operation;
for (uint8_t i = 0; i < count; i++)
{
buffer[i + 2] = pattern_ids[i];
}
return bhy2_set_parameter(KLIO_PARAM(KLIO_HIF_PARAM_PATTERN_STATE), buffer, buffer_size, dev);
}
int8_t bhy2_klio_set_state(const bhy2_klio_sensor_state_t *state, struct bhy2_dev *dev)
{
int8_t rslt = BHY2_OK;
uint8_t buffer[4];
if (!dev || !state)
{
rslt = BHY2_E_NULL_PTR;
}
else
{
buffer[0] = state->learning_enabled;
buffer[1] = state->learning_reset;
buffer[2] = state->recognition_enabled;
buffer[3] = state->recognition_reset;
rslt = bhy2_set_parameter(KLIO_PARAM(KLIO_HIF_PARAM_ALGORITHM_STATE), buffer, sizeof(buffer), dev);
}
return rslt;
}
int8_t bhy2_klio_get_state(bhy2_klio_sensor_state_t *state, struct bhy2_dev *dev)
{
int8_t rslt = BHY2_OK;
if (!dev || !state)
{
rslt = BHY2_E_NULL_PTR;
}
else
{
uint8_t buffer[4];
uint32_t ret_len;
rslt = bhy2_get_parameter(KLIO_PARAM(KLIO_HIF_PARAM_ALGORITHM_STATE), buffer, sizeof(buffer), &ret_len, dev);
if (rslt == BHY2_OK && ret_len == sizeof(buffer))
{
state->learning_enabled = buffer[0];
state->learning_reset = buffer[1];
state->recognition_enabled = buffer[2];
state->recognition_reset = buffer[3];
}
}
return rslt;
}
int8_t bhy2_klio_similarity_score(const uint8_t *first_pattern,
const uint8_t *second_pattern,
const uint16_t size,
float *similarity,
struct bhy2_dev *dev)
{
uint32_t klio_driver_status = 0;
int8_t rslt;
uint32_t ret_len;
bhy2_klio_pattern_transfer_t pattern1 = { 0 }, pattern2 = { 0 };
uint8_t buffer[4];
if (!dev || size > sizeof(pattern1.pattern_data))
{
return BHY2_E_INVALID_PARAM;
}
pattern1.block_size = pattern2.block_size = (uint8_t)size;
pattern1.full_size = pattern2.full_size = size;
memcpy(pattern1.pattern_data, first_pattern, size);
memcpy(pattern2.pattern_data, second_pattern, size);
rslt =
bhy2_set_parameter(KLIO_PARAM(KLIO_HIF_PARAM_PATTERN_SIMILARITY), (uint8_t*)&pattern1, sizeof(pattern1), dev);
if (rslt != BHY2_OK)
{
return rslt;
}
rslt =
bhy2_set_parameter(KLIO_PARAM(KLIO_HIF_PARAM_PATTERN_SIMILARITY), (uint8_t*)&pattern2, sizeof(pattern2), dev);
if (rslt != BHY2_OK)
{
return rslt;
}
/* Wait for similarity calculation to complete. */
rslt = bhy2_klio_read_reset_driver_status(&klio_driver_status, dev);
if (rslt != BHY2_OK || klio_driver_status != KLIO_DRIVER_ERROR_NONE)
{
return BHY2_E_INVALID_PARAM;
}
rslt = bhy2_get_parameter(KLIO_PARAM(KLIO_HIF_PARAM_PATTERN_SIMILARITY), buffer, sizeof(buffer), &ret_len, dev);
if (rslt != BHY2_OK)
{
return rslt;
}
if (ret_len != sizeof(buffer))
{
return BHY2_E_INVALID_PARAM;
}
memcpy(similarity, buffer, sizeof(*similarity));
return BHY2_OK;
}
int8_t bhy2_klio_similarity_score_multiple(const uint8_t idx,
const uint8_t *indexes,
const uint8_t count,
float *similarity,
struct bhy2_dev *dev)
{
uint32_t klio_driver_status;
int8_t rslt;
uint32_t ret_len;
uint32_t buffer_size = sizeof(bhy2_klio_similarity_calculation_t) + count;
buffer_size = BHY2_ROUND_WORD_HIGHER(buffer_size);
uint8_t buffer[256] = { 0 };
if (!indexes || !similarity || !dev)
{
return BHY2_E_NULL_PTR;
}
/* buffer[0-3] values are initialized to zero's to distinguish from regular pattern comparison*/
buffer[4] = idx;
buffer[5] = count;
for (uint8_t i = 0; i < count; i++)
{
buffer[i + 6] = indexes[i];
}
/* Start similarity calculations. */
rslt = bhy2_set_parameter(KLIO_PARAM(KLIO_HIF_PARAM_PATTERN_SIMILARITY), (uint8_t*)buffer, buffer_size, dev);
if (rslt != BHY2_OK)
{
return rslt;
}
/* Wait for similarity calculation to complete. */
rslt = bhy2_klio_read_reset_driver_status(&klio_driver_status, dev);
if (rslt != BHY2_OK || klio_driver_status != KLIO_DRIVER_ERROR_NONE)
{
return BHY2_E_INVALID_PARAM;
}
/* Read similarity results. */
rslt = bhy2_get_parameter(KLIO_PARAM(KLIO_HIF_PARAM_PATTERN_SIMILARITY),
(uint8_t *)similarity,
sizeof(float) * count,
&ret_len,
dev);
if (rslt != BHY2_OK)
{
return rslt;
}
return BHY2_OK;
}
int8_t bhy2_klio_set_parameter(const bhy2_klio_parameter_t id,
const void *parameter_data,
const uint16_t size,
struct bhy2_dev *dev)
{
bhy2_klio_parameter_wrapper_t buffer;
buffer.id = id;
buffer.flags = 0;
buffer.size = (uint8_t)size;
memcpy(buffer.payload.data, parameter_data, size);
/* Size is 3 bytes header and buffer.size then rounded up to a four byte multiple. */
return bhy2_set_parameter(KLIO_PARAM(KLIO_HIF_PARAM_ALGO_DRIVER_PARAMETER),
(uint8_t*)&buffer,
(3 + buffer.size + 3) & ~3,
dev);
}
int8_t bhy2_klio_get_parameter(const bhy2_klio_parameter_t id,
uint8_t *parameter_data,
uint16_t *size,
struct bhy2_dev *dev)
{
uint32_t ret_len;
uint8_t buffer[260] = { 0 };
buffer[0] = id;
int8_t rslt;
/* Size is 3 bytes header and buffer.size then rounded up to a four byte multiple. */
rslt = bhy2_set_parameter(KLIO_PARAM(KLIO_HIF_PARAM_ALGO_DRIVER_PARAMETER), buffer, (3 + buffer[2] + 3) & ~3, dev);
if (rslt != BHY2_OK)
{
return rslt;
}
rslt = bhy2_get_parameter(KLIO_PARAM(KLIO_HIF_PARAM_ALGO_DRIVER_PARAMETER), buffer, sizeof(buffer), &ret_len, dev);
if (rslt != BHY2_OK)
{
return rslt;
}
if (ret_len < 3 || buffer[2] > *size)
{
return BHY2_E_INVALID_PARAM;
}
for (uint16_t i = 3, j = 0; i < buffer[2] + 3; i++, j++)
{
parameter_data[j] = buffer[i];
}
*size = buffer[2];
return BHY2_OK;
}

View File

@@ -0,0 +1,227 @@
/**
* 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 bhy2_klio.h
* @date 2023-03-24
* @version v1.6.0
*
*/
#ifndef __BHY2_KLIO_H__
#define __BHY2_KLIO_H__
/* Start of CPP Guard */
#ifdef __cplusplus
extern "C" {
#endif /*__cplusplus */
#include <stdint.h>
#include <stdlib.h>
#include "bhy2.h"
#include "bhy2_klio_defs.h"
/*!
* @brief Reads and resets current driver status.
*
* The driver_status will be set to one of the values in
* @ref bhy2_klio_driver_error_state_t. This function will not return a driver
* status of
* @ref bhy2_klio_driver_error_state_t::KLIO_DRIVER_ERROR_OPERATION_PENDING.
* but will retry until the pending operation is finished.
*
* @param[out] driver_status Pointer to uint32_t
* @param[in] dev Device reference.
*
* @return BHY2 API error codes.
*/
int8_t bhy2_klio_read_reset_driver_status(uint32_t *driver_status, struct bhy2_dev *dev);
/*!
* @brief Read learnt pattern.
*
* @param[in] id pattern id (only 0 supported now)
* @param[out] buffer buffer big enough to fit complete pattern fingerprint data
* @param[in,out] length size of buffer, return size of actual pattern data
* @param[in] dev Device reference
*
* @return BHY2 API error codes.
*
* After learning of a new pattern has been signaled by a sensor data event,
* call this function to retrieve the learnt pattern.
*/
int8_t bhy2_klio_read_pattern(const uint8_t id, uint8_t *buffer, uint16_t *length, struct bhy2_dev *dev);
/*!
* @brief Set KLIO algorithm learning and recognition state.
*
* @param[in] state new state for algorithm
* @param[in] dev Device reference
*
* @return BHY2 API error codes.
*
* Writing 1 to the reset fields resets all internal algorithm state and
* removes any patterns loaded for recognition.
*/
int8_t bhy2_klio_set_state(const bhy2_klio_sensor_state_t *state, struct bhy2_dev *dev);
/*!
* @brief Get KLIO algorithm learning and recognition state.
*
* @param[out] state current state for algorithm
* @param[in] dev Device reference
*
* @return BHY2 API error codes.
*
* The resets are always read as 0.
*/
int8_t bhy2_klio_get_state(bhy2_klio_sensor_state_t *state, struct bhy2_dev *dev);
/*!
* @brief Write pattern to recognition algorithm.
*
* @param[in] idx pattern index
* @param[in] pattern_data containing pattern
* @param[in] size pattern size
* @param[in] dev Device reference
*
* @return BHY2 API error codes.
*
* Write a pattern to the specified recognition index. The allowed number of
* recognition patterns may be retrieved using the
* @ref bhy2_klio_parameter::KLIO_PARAM_RECOGNITION_MAX_PATTERNS parameter.
*
* After a pattern is written, it is in disabled state and not used. It must
* be enabled using @ref bhy2_klio_set_pattern_states() before it will be used
* by the recognition algorithm.
*/
int8_t bhy2_klio_write_pattern(const uint8_t idx, const uint8_t *pattern_data, const uint16_t size,
struct bhy2_dev *dev);
/*!
* @brief Sets the specified state for the specified pattern ids.
*
* @param[in] operation operation to perform
* @param[in] pattern_ids ids of pattern(s) to perform operation on
* @param[in] size size of pattern_ids array
* @param[in] dev Device reference
*
* @return BHY2 API error codes.
*/
int8_t bhy2_klio_set_pattern_states(const bhy2_klio_pattern_state_t operation,
const uint8_t *pattern_ids,
const uint16_t size,
struct bhy2_dev *dev);
/*!
* @brief Calculates similarity score between two patterns.
*
* The similariy between patterns is a meassure of the similarity between the
* performed activities or exercises. If the two patterns represent the same
* excercise the similarity will be close to 1.0, and if they are for very
* different excercises, the similarity will be negative.
*
* @param[in] first_pattern Buffer containing first pattern.
* @param[in] second_pattern Buffer containing second pattern.
* @param[in] size Pattern size.
* @param[out] similarity Similarity score.
* @param[in] dev Device reference.
*
* @return BHY2 API error codes.
*/
int8_t bhy2_klio_similarity_score(const uint8_t *first_pattern,
const uint8_t *second_pattern,
const uint16_t size,
float *similarity,
struct bhy2_dev *dev);
/*!
* @brief Calculates similarity score between multiple patterns.
*
* This is more efficient than bhy2_klio_similarity_score() since if the patterns
* are already available on the bhy2, they need not be uploaded again to
* perform the comparison. And several comparisons may be performed with one
* API call.
*
* @param[in] idx Reference pattern.
* @param[in] indexes Buffer containing indexes of patterns to compare reference pattern with.
* @param[in] count Number of patterns in indexes buffer.
* @param[out] similarity Similarity scores (one score for each pattern in indexes buffer).
* @param[in] dev Device reference.
*
* @return BHY2 API error codes.
*/
int8_t bhy2_klio_similarity_score_multiple(const uint8_t idx,
const uint8_t *indexes,
const uint8_t count,
float *similarity,
struct bhy2_dev *dev);
/*!
* @brief Set KLIO algorithm parameter
*
* @param[in] id Parameter to set.
* @param[in] parameter_data Buffer containing new parameter value.
* @param[in] size Parameter size.
* @param[in] dev Device reference.
*
* @return BHY2 API error codes.
*/
int8_t bhy2_klio_set_parameter(const bhy2_klio_parameter_t id,
const void *parameter_data,
const uint16_t size,
struct bhy2_dev *dev);
/*!
* @brief Get KLIO algorithm parameter
*
* @param[in] id Parameter id.
* @param[out] parameter_data Buffer to store parameter data.
* @param[in,out] size Parameter data size.
* @param[in] dev Device reference.
*
* @return BHY2 API error codes.
*
* The expected type or buffer size of parameter_data for respective parameter
* id is specified in the @ref bhy2_klio_parameter_t enum.
*/
int8_t bhy2_klio_get_parameter(const bhy2_klio_parameter_t id,
uint8_t *parameter_data,
uint16_t *size,
struct bhy2_dev *dev);
/* End of CPP Guard */
#ifdef __cplusplus
}
#endif /*__cplusplus */
#endif

View File

@@ -0,0 +1,349 @@
/**
* 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 bhy2_klio_defs.h
* @date 2023-03-24
* @version v1.6.0
*
*/
#ifndef __BHY2_KLIO_DEFS_H__
#define __BHY2_KLIO_DEFS_H__
/* Start of CPP Guard */
#ifdef __cplusplus
extern "C" {
#endif /*__cplusplus */
#include <stdint.h>
#define BHY2_SENSOR_ID_KLIO UINT8_C(112)
#define BHY2_SENSOR_ID_KLIO_LOG UINT8_C(127)
#ifndef BHY2_KLIO_PAGE
#define BHY2_KLIO_PAGE UINT16_C(9)
#endif
#define KLIO_PARAM(id) (((BHY2_KLIO_PAGE) << 8) | (id))
/*!
* @enum bhy2_klio_parameter
*
* KLIO algorithm parameters
*
* @var bhy2_klio_parameter::KLIO_PARAM_ALGORITHM_VERSION
* Algorithm version. (read)
* @code{.c} char version[244]; @endcode
*
* @var bhy2_klio_parameter::KLIO_PARAM_RECOGNITION_RESPONSIVNESS
* The approximate number of cycles / repetitions for recognition to recognize
* an activity. (read / write)
* @code{.c} float cycle_fraction; @endcode
*
* @var bhy2_klio_parameter::KLIO_PARAM_PATTERN_BLOB_SIZE
* Pattern blob size in bytes. (read)
* @code{.c} uint16_t pattern_blob_size; @endcode
*
* @var bhy2_klio_parameter::KLIO_PARAM_RECOGNITION_MAX_PATTERNS
* Read Maximum number of patterns. (read)
* @code{.c} uint16_t recognition_max_patterns; @endcode
*
* @var bhy2_klio_parameter::KLIO_PARAM_LEARNING_IGNORE_INSIG_MOVEMENT
* Flag if insignificant movements should be ignored in learning. Value 0 or 1. (read / write)
* @code{.c} uint8_t ignore_insig_movement; @endcode
*/
typedef enum
{
KLIO_PARAM_ALGORITHM_VERSION = 0,
KLIO_PARAM_RECOGNITION_SENSITIVITY = 1,
KLIO_PARAM_RECOGNITION_RESPONSIVNESS = 2,
KLIO_PARAM_LEARNING_SPEED = 3,
KLIO_PARAM_LEARNING_SIMILARITY_THRESHOLD = 4,
KLIO_PARAM_LEARNING_FREQUENCIES = 5,
KLIO_PARAM_LEARNING_PROGRESS = 6,
KLIO_PARAM_PATTERN_BLOB_SIZE = 7,
KLIO_PARAM_RECOGNITION_MAX_PATTERNS = 8,
KLIO_PARAM_INPUT_SENSORS = 9,
KLIO_PARAM_LEARNING_IGNORE_INSIG_MOVEMENT = 10
} bhy2_klio_parameter_t;
/*!
*
* @brief Convenience wrapper used in bhy2_klio.c algo parameter wrapper.
*
*/
typedef struct
{
uint8_t id;
uint8_t flags;
uint8_t size;
union
{
uint8_t data[244];
char version[244];
float cycle_fraction;
uint16_t pattern_blob_size;
uint16_t recognition_max_patterns;
uint8_t ignore_insig_movement;
} BHY2_PACKED payload;
} BHY2_PACKED bhy2_klio_parameter_wrapper_t;
/*!
*
* @brief bhy2 klio state structure
*
*/
typedef struct
{
uint8_t learning_enabled; /*!< 0 - disable learning, 1 - enable learning. */
uint8_t learning_reset; /*!< 0 - nop, 1 - reset learning. Always read as 0. */
uint8_t recognition_enabled; /*!< 0 - disable recognition, 1 - enable recognition. */
uint8_t recognition_reset; /*!< 0 - nop, 1 - reset learning. Always read as 0. */
} BHY2_PACKED bhy2_klio_sensor_state_t;
typedef struct
{
uint8_t instance;
/*!
* A value of -1 means no new learning has occurred. If the value is >= 0,
* then a new pattern has been learnt, and reading of this pattern may be
* performed.
*/
int8_t index;
/*!
* While learning a new pattern, this field counts from 0 to 100. When 100 is
* reached a new pattern will be learnt. If learning is interrupted, this
* progress will return to 0, and change reason will be set to indicate
* why learning was interrupted.
*/
uint8_t progress;
/*!
* | Value | Description |
* |:-----:|:-----------------------------------------------------------------------|
* | 0 | Learning is progressing. |
* | 1 | Learning was interrupted by a non-repetitive activity. |
* | 2 | Learning was interrupted because no significant movement was detected. |
*/
uint8_t change_reason;
} BHY2_PACKED bhy2_klio_sensor_frame_learning_t;
typedef struct
{
uint8_t instance;
/*! The index of the recognized activity. 255 means no activity was
* recognized. */
uint8_t index;
/*! The current repetition count of the recognized activity. */
float count;
} BHY2_PACKED bhy2_klio_sensor_frame_recognition_t;
/*!
*
* @brief bhy2 klio combined data structure
*
* When the algorithm generates a new data frame, it is sent in this structure.
*
*/
typedef struct
{
bhy2_klio_sensor_frame_learning_t learn;
bhy2_klio_sensor_frame_recognition_t recognize;
} BHY2_PACKED bhy2_klio_sensor_frame_t;
/*!
*
* @brief bhy2 klio sensor log frame
*
* When the algorithm consumes a new set of samples, it is sent in this structure.
*
*/
typedef struct
{
float timestamp;
float accel[3];
float gyro[3];
} BHY2_PACKED bhy2_klio_log_frame_t;
/*!
*
* @brief bhy2 klio pattern transfer format
*
*/
typedef struct
{
uint8_t block_id; /*!< Write as 0. */
uint8_t block_size; /*!< Write as 0. */
/*! Size of pattern_data in bytes. The size of patterns may be obtained
using the @ref bhy2_klio_parameter::KLIO_PARAM_PATTERN_BLOB_SIZE
parameter. */
uint16_t full_size;
/*! Id of pattern to write. */
uint8_t pattern_id;
/*! Actual pattern data describing the exercise. */
uint8_t pattern_data[244];
} BHY2_PACKED bhy2_klio_pattern_transfer_t;
/*!
*
* @brief Convenience wrapper used by @ref bhy2_klio_similarity_score_multiple().
*
*/
typedef struct
{
uint32_t zero;
uint8_t index;
uint8_t count;
uint8_t *indexes;
} BHY2_PACKED bhy2_klio_similarity_calculation_t;
/*!
*
* @brief Convenience wrapper used by @ref bhy2_klio_set_pattern_states().
*
*/
typedef struct
{
uint8_t operation;
uint8_t count;
uint8_t *indexes;
} BHY2_PACKED bhy2_klio_pattern_state_op_t;
/*!
* KLIO pattern state
*/
typedef enum
{
/*!< disable pattern */
KLIO_PATTERN_STATE_DISABLE = 0,
/*!< enable pattern */
KLIO_PATTERN_STATE_ENABLE = 1,
/*!< switch hand */
KLIO_PATTERN_STATE_SWITCH_HAND = 2,
/*!< disable adaptive pattern */
KLIO_PATTERN_STATE_AP_DISABLE = 3
} bhy2_klio_pattern_state_t;
/*!
* @brief KLIO host interface parameter identifiers.
*
* The parameter id used when calling the BHY2 functions directly. E.g. to read the driver status this may be used.
*
* ~~~{.c}
* uint32_t klio_driver_status = 0;
* uint32_t ret_len = 0;
* int8_t rslt = bhy2_get_parameter(KLIO_PARAM(KLIO_HIF_PARAM_DRIVER_STATUS),
* (uint8_t*)&klio_driver_status,
* sizeof(klio_driver_status),
* &ret_len,
* dev);
* if (rslt != BHY2_OK)
* {
* return rslt;
* }
* ~~~
*/
typedef enum
{
/*!< Read and write algorighm state. */
KLIO_HIF_PARAM_ALGORITHM_STATE = 0,
/*!< Read and write patterns. */
KLIO_HIF_PARAM_PATTERN = 1,
/*!< Read and write algorithm parameters. */
KLIO_HIF_PARAM_ALGO_DRIVER_PARAMETER = 2,
KLIO_HIF_PARAM_STATISTIC = 3,
KLIO_HIF_PARAM_PATTERN_STATE = 4,
/*!< Perform pattern similarity. */
KLIO_HIF_PARAM_PATTERN_SIMILARITY = 5,
KLIO_HIF_PARAM_PATTERN_COMBINING = 6,
/*!< Read driver status. */
KLIO_HIF_PARAM_DRIVER_STATUS = 7
} bhy2_klio_hif_parameter_t;
/*!
* KLIO driver error codes
*/
typedef enum
{
/*!< No error. */
KLIO_DRIVER_ERROR_NONE = 0,
/*!< Invalid parameter. */
KLIO_DRIVER_ERROR_INVALID_PARAMETER = 1,
/*!< Parameter out of range. */
KLIO_DRIVER_ERROR_PARAMETER_OUT_OF_RANGE = 2,
/*!
* Invalid pattern operation. E.g. trying to read a learnt pattern when no
* pattern has been learnt, or trying to write an invalid pattern.
*/
KLIO_DRIVER_ERROR_INVALID_PATTERN_OPERATION = 3,
/*!< Not implemented. */
KLIO_DRIVER_ERROR_NOT_IMPLEMENTED = 4,
/*!< Insufficient buffer size */
KLIO_DRIVER_ERROR_BUFSIZE = 5,
/*!< Internal error. */
KLIO_DRIVER_ERROR_INTERNAL = 6,
/*!< Undefined error */
KLIO_DRIVER_ERROR_UNDEFINED = 7,
/*!
* Previous operation is still progressing. Read driver status again until
* operation is finished.
*/
KLIO_DRIVER_ERROR_OPERATION_PENDING = 8
} bhy2_klio_driver_error_state_t;
/* End of CPP Guard */
#ifdef __cplusplus
}
#endif /*__cplusplus */
#endif /* __BHY2_KLIO_DEFS_H__ */

View File

@@ -0,0 +1,115 @@
/**
* 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 bhy2_parse.c
* @date 2023-03-24
* @version v1.6.0
*
*/
#include "bhy2.h"
#include "bhy2_parse.h"
#include <math.h>
void bhy2_parse_temperature_celsius(const uint8_t *data, bhy2_float *temperature)
{
/* 1 LSB = 1/100 degC */
float scale_factor = (float)1 / 100;
*temperature = BHY2_LE2S16(data) * scale_factor;
}
void bhy2_parse_humidity(const uint8_t *data, bhy2_float *humidity)
{
float scale_factor = (float)1;
*humidity = data[0] * scale_factor;
}
void bhy2_parse_pressure(const uint8_t *data, bhy2_float *pressure)
{
/* 1 LSB = 1/128 Pa */
float scale_factor = (float)1 / 128;
*pressure = (float)BHY2_LE2U24(data) * scale_factor;
}
void bhy2_parse_altitude(const uint8_t *data, bhy2_float *altitude)
{
*altitude = (float)(data[0] | ((uint32_t)data[1] << 8) | ((uint32_t)data[2] << 16) | ((uint32_t)data[3] << 24));
}
void bhy2_parse_quaternion(const uint8_t *data, struct bhy2_data_quaternion *quaternion)
{
quaternion->x = BHY2_LE2S16(data);
quaternion->y = BHY2_LE2S16(data + 2);
quaternion->z = BHY2_LE2S16(data + 4);
quaternion->w = BHY2_LE2S16(data + 6);
quaternion->accuracy = BHY2_LE2U16(data + 8);
}
void bhy2_parse_xyz(const uint8_t *data, struct bhy2_data_xyz *vector)
{
vector->x = BHY2_LE2S16(data);
vector->y = BHY2_LE2S16(data + 2);
vector->z = BHY2_LE2S16(data + 4);
}
void bhy2_parse_orientation(const uint8_t *data, struct bhy2_data_orientation *orientation)
{
orientation->heading = BHY2_LE2S16(data);
orientation->pitch = BHY2_LE2S16(data + 2);
orientation->roll = BHY2_LE2S16(data + 4);
}
uint32_t bhy2_parse_step_counter(const uint8_t *data)
{
return (uint32_t)(data[0] | ((uint32_t)data[1] << 8) | ((uint32_t)data[2] << 16) | ((uint32_t)data[3] << 24));
}
void bhy2_quaternion_to_euler(const uint8_t *data, float *roll, float *pitch, float *yaw)
{
float w, x, y, z;
struct bhy2_data_quaternion quaternion;
bhy2_parse_quaternion(data, &quaternion);
w = quaternion.w / 16384.0f;
x = quaternion.x / 16384.0f;
y = quaternion.y / 16384.0f;
z = quaternion.z / 16384.0f;
*roll = atan2(2 * (w * x + y * z), 1 - 2 * (x * x + y * y));
*pitch = asin(2 * (w * y - z * x));
*yaw = atan2(2 * (w * z + x * y), 1 - 2 * (y * y + z * z));
// Convert radians to degrees
*roll = *roll * (180.0 / M_PI);
*pitch = *pitch * (180.0 / M_PI);
*yaw = *yaw * (180.0 / M_PI);
}

View File

@@ -0,0 +1,124 @@
/**
* 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 bhy2_parse.h
* @date 2023-03-24
* @version v1.6.0
*
*/
#ifndef __BHY2_PARSE_H__
#define __BHY2_PARSE_H__
/* Start of CPP Guard */
#ifdef __cplusplus
extern "C" {
#endif /*__cplusplus */
#include "bhy2.h"
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
/**
* @brief Function to parse FIFO frame data into temperature
* @param[in] data : Reference to the data buffer storing data from the FIFO
* @param[out] temperature : Reference to the data buffer to store temperature in degree C
*/
void bhy2_parse_temperature_celsius(const uint8_t *data, bhy2_float *temperature);
/**
* @brief Function to parse FIFO frame data into humidity
* @param[in] data : Reference to the data buffer storing data from the FIFO
* @param[out] humidity : Reference to the data buffer to store humidity in %
*/
void bhy2_parse_humidity(const uint8_t *data, bhy2_float *humidity);
/**
* @brief Function to parse FIFO frame data into barometric pressure
* @param[in] data : Reference to the data buffer storing data from the FIFO
* @param[out] pressure : Reference to the data buffer to store pressure in Pascals
*/
void bhy2_parse_pressure(const uint8_t *data, bhy2_float *pressure);
/**
* @brief Function to parse FIFO frame data into altitude
* @param[in] data : Reference to the data buffer storing data from the FIFO
* @param[out] altitude : Reference to the data buffer to store altitude
*/
void bhy2_parse_altitude(const uint8_t *data, bhy2_float *altitude);
/**
* @brief Function to parse FIFO frame data into quaternion
* @param[in] data : Reference to the data buffer storing data from the FIFO
* @param[out] quaternion : Reference to the data buffer to store quaternion
*/
void bhy2_parse_quaternion(const uint8_t *data, struct bhy2_data_quaternion *quaternion);
/**
* @brief Function to parse FIFO frame data into orientation
* @param[in] data : Reference to the data buffer storing data from the FIFO
* @param[out] orientation : Reference to the data buffer to store orientation
*/
void bhy2_parse_orientation(const uint8_t *data, struct bhy2_data_orientation *orientation);
/**
* @brief Function to parse FIFO frame data into 3 axes vector
* @param[in] data : Reference to the data buffer storing data from the FIFO
* @param[out] vector : Reference to the data buffer to store vector
*/
void bhy2_parse_xyz(const uint8_t *data, struct bhy2_data_xyz *vector);
/**
* @brief Function to parse FIFO frame data into step counter
* @param[in] data : Reference to the data buffer storing data from the FIFO
* @return[out] : Reference to the data buffer to step counter
*/
uint32_t bhy2_parse_step_counter(const uint8_t *data);
/**
* @brief Function converts quaternion to Euler angle
* @param *data: Quaternions data
* @param *roll: Data pointer
* @param *pitch: Data pointer
* @param *yaw: Data pointer
* @retval None
*/
void bhy2_quaternion_to_euler(const uint8_t *data, float *roll, float *pitch, float *yaw);
/* End of CPP Guard */
#ifdef __cplusplus
}
#endif /*__cplusplus */
#endif /* __BHY2_PARSE_H__ */

View File

@@ -0,0 +1,203 @@
/**
* 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 bhy2_swim.c
* @date 2023-03-24
* @version v1.6.0
*
*/
/*********************************************************************/
/* system header files */
/*********************************************************************/
#include <string.h>
#include <stdio.h>
/*********************************************************************/
/* BHY2 SensorAPI header files */
/*********************************************************************/
#include "bhy2.h"
/*********************************************************************/
/* own header files */
/*********************************************************************/
#include "bhy2_swim.h"
/*!
* @brief This API writes to the configuration parameter
* Config parameters are pool length and handedness
*
* @param[in] buffer to store swim configuration
* @param[out] dev hub handle.
*
* @return rslt execution result.
*/
int8_t bhy2_swim_set_config(const void *buffer, struct bhy2_dev *dev)
{
int8_t rslt = BHY2_OK;
/*! Length of the configuration is 4 bytes */
uint32_t length = BHY2_SWIM_DATA_LENGTH;
/*! Swim Parameter page with offset 0 used for swim configuration*/
uint16_t param = BHY2_SWIM_CONFIG_PARAM;
if (dev == NULL)
{
rslt = BHY2_E_NULL_PTR;
}
else
{
/*! Set the swim configuration parameter */
rslt = bhy2_set_parameter(param, (uint8_t *)buffer, length, dev);
}
return rslt;
}
/*!
* @brief To get the SWIM configuration parameters like swim length and handedness
*
* @param[out] buffer to store swim configuration
* @param[in] dev hub handle
*
* @return status code, BHY_HIF_E_SUCCESS in case of success
*
*/
int8_t bhy2_swim_get_config(void *buffer, struct bhy2_dev *dev)
{
int8_t rslt = BHY2_OK;
/*! Length of the configuration is 4 bytes */
uint32_t length = BHY2_SWIM_DATA_LENGTH;
uint32_t ret_length;
/*! Swim Parameter page with offset 0 used to store swim configuration*/
uint16_t param = BHY2_SWIM_CONFIG_PARAM;
if (dev == NULL)
{
rslt = BHY2_E_NULL_PTR;
}
else
{
/*! Get the swim configuration from the parameter page*/
rslt = bhy2_get_parameter(param, buffer, length, &ret_length, dev);
if ((rslt == BHY2_OK) && (ret_length != BHY2_SWIM_DATA_LENGTH))
{
/*! Invalid number of parameters readout */
rslt = BHY2_E_INVALID_EVENT_SIZE;
}
}
return rslt;
}
/*!
* @brief To get the SWIM Algorithm version
*
* @param[out] buffer to store version data
* @param[in] dev hub handle
*
* @return status code, BHY_HIF_E_SUCCESS in case of success
*
*/
int8_t bhy2_swim_get_version(bhy2_swim_version_t *version, struct bhy2_dev *dev)
{
int8_t rslt = BHY2_OK;
/*! Buffer to store the swim version */
uint8_t buffer[4];
/*! Length of the configuration is 4 */
uint32_t length = BHY2_SWIM_DATA_LENGTH;
uint32_t ret_length;
/*! Swim Parameter page with offset 1 used to store swim algorithm version*/
uint16_t param = BHY2_SWIM_VERSION;
if (dev == NULL)
{
rslt = BHY2_E_NULL_PTR;
}
else
{
/*! Get the swim version from the parameter page */
rslt = bhy2_get_parameter(param, buffer, length, &ret_length, dev);
if ((rslt == BHY2_OK) && (ret_length != BHY2_SWIM_DATA_LENGTH))
{
/*! Invalid number of parameters readout */
rslt = BHY2_E_INVALID_EVENT_SIZE;
}
else
{
version->improvement = buffer[0];
version->platform = buffer[1];
version->bugfix = buffer[2];
}
}
return rslt;
}
/*!
* @brief Parsing the fifo data to SWIM output structure format
*
* @param[in] Swim data
* @param[out] bhy2_swim_aglo_output to store parameter data
*
* @return API error codes
*
*/
int8_t bhy2_swim_parse_data(const uint8_t *data, struct bhy2_swim_algo_output* output)
{
int8_t rslt = BHY2_OK;
if ((data == NULL) || (output == NULL))
{
rslt = BHY2_E_NULL_PTR;
}
else
{
output->total_distance = BHY2_LE2U16(data);
output->length_count = BHY2_LE2U16(data + 2);
output->lengths_freestyle = BHY2_LE2U16(data + 4);
output->lengths_breaststroke = BHY2_LE2U16(data + 6);
output->lengths_butterfly = BHY2_LE2U16(data + 8);
output->lengths_backstroke = BHY2_LE2U16(data + 10);
output->stroke_count = BHY2_LE2U16(data + 12);
}
return rslt;
}

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